diff --git a/.dockerignore b/.dockerignore index 834924b9f79d8..39dbc05c97e16 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,3 +3,4 @@ doc .idea/ Dockerfile .dockerignore +.local diff --git a/.editorconfig b/.editorconfig index f511aad460790..47fde53b690b5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ tab_width=4 end_of_line=lf charset=utf-8 trim_trailing_whitespace=true -max_line_length=120 +max_line_length=100 insert_final_newline=true [*.yml] diff --git a/.gitignore b/.gitignore index 28885a4830d9b..aadaa13912c19 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,11 @@ **/*.rs.bk *.swp .wasm-binaries -polkadot/runtime/wasm/target/ -core/executor/wasm/target/ -core/test-runtime/wasm/target/ pwasm-alloc/target/ pwasm-libc/target/ pwasm-alloc/Cargo.lock pwasm-libc/Cargo.lock -node/runtime/wasm/target/ +bin/node/runtime/wasm/target/ **/._* **/.criterion/ .vscode @@ -21,3 +18,4 @@ rls*.log *.orig *.rej **/wip/*.stderr +.local diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 769ee60d1e78e..05834f11d1944 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,6 +15,7 @@ stages: variables: GIT_STRATEGY: fetch + GIT_DEPTH: 100 CARGO_HOME: "/ci-cache/${CI_PROJECT_NAME}/cargo/${CI_JOB_NAME}" SCCACHE_DIR: "/ci-cache/${CI_PROJECT_NAME}/sccache" CARGO_INCREMENTAL: 0 @@ -49,6 +50,14 @@ variables: - schedules - web - /^[0-9]+$/ # PRs + retry: + max: 2 + when: + - runner_system_failure + - unknown_failure + - api_failure + dependencies: [] + interruptible: true tags: - linux-docker @@ -72,7 +81,8 @@ check-runtime: GITLAB_API: "https://gitlab.parity.io/api/v4" GITHUB_API_PROJECT: "parity%2Finfrastructure%2Fgithub-api" script: - - ./scripts/gitlab/check_runtime.sh + - ./.maintain/gitlab/check_runtime.sh + interruptible: true allow_failure: true @@ -83,7 +93,8 @@ check-line-width: only: - /^[0-9]+$/ script: - - ./scripts/gitlab/check_line_width.sh + - ./.maintain/gitlab/check_line_width.sh + interruptible: true allow_failure: true @@ -111,7 +122,7 @@ cargo-check-subkey: except: - /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 script: - - cd ./subkey + - cd ./bin/utils/subkey - BUILD_DUMMY_WASM_BINARY=1 time cargo check --release - sccache -s @@ -127,7 +138,7 @@ test-linux-stable: &test-linux variables: - $DEPLOY_TAG script: - - time cargo test --all --release --verbose --locked | + - WASM_BUILD_NO_COLOR=1 time cargo test --all --release --verbose --locked | tee output.log - sccache -s after_script: @@ -139,8 +150,16 @@ test-linux-stable: &test-linux paths: - ${CI_COMMIT_SHORT_SHA}_warnings.log +test-dependency-rules: + stage: test + <<: *docker-env + except: + variables: + - $DEPLOY_TAG + script: + - .maintain/ensure-deps.sh -test-srml-staking: &test-srml-staking +test-frame-staking: stage: test <<: *docker-env variables: @@ -152,14 +171,25 @@ test-srml-staking: &test-srml-staking variables: - $DEPLOY_TAG script: - - cd srml/staking/ - - time cargo test --release --verbose --no-default-features --features std + - cd frame/staking/ + - WASM_BUILD_NO_COLOR=1 time cargo test --release --verbose --no-default-features --features std - sccache -s - - - - +test-wasmtime: + stage: test + <<: *docker-env + variables: + # Enable debug assertions since we are running optimized builds for testing + # but still want to have debug assertions. + RUSTFLAGS: -Cdebug-assertions=y + RUST_BACKTRACE: 1 + except: + variables: + - $DEPLOY_TAG + script: + - cd client/executor + - WASM_BUILD_NO_COLOR=1 time cargo test --release --verbose --features wasmtime + - sccache -s test-linux-stable-int: <<: *test-linux @@ -171,8 +201,8 @@ test-linux-stable-int: script: - echo "___Logs will be partly shown at the end in case of failure.___" - echo "___Full log will be saved to the job artifacts only in case of failure.___" - - RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace - time cargo test -p node-cli --release --verbose --locked -- --ignored --test-threads=1 + - WASM_BUILD_NO_COLOR=1 RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace + time cargo test -p node-cli --release --verbose --locked -- --ignored &> ${CI_COMMIT_SHORT_SHA}_int_failure.log - sccache -s after_script: @@ -193,27 +223,16 @@ check-web-wasm: script: # WASM support is in progress. As more and more crates support WASM, we # should add entries here. See https://github.com/paritytech/substrate/issues/2416 - - time cargo web build -p sr-io - - time cargo web build -p sr-primitives - - time cargo web build -p sr-std - - time cargo web build -p substrate-client - - time cargo web build -p substrate-consensus-aura - - time cargo web build -p substrate-consensus-babe - - time cargo web build -p substrate-consensus-common - - time cargo web build -p substrate-keyring - - time cargo web build -p substrate-keystore - - time cargo web build -p substrate-executor - - time cargo web build -p substrate-network - - time cargo web build -p substrate-panic-handler - - time cargo web build -p substrate-peerset - - time cargo web build -p substrate-primitives - # TODO: we can't use cargo web until https://github.com/paritytech/jsonrpc/pull/436 is deployed - - time cargo build -p substrate-rpc-servers --target wasm32-unknown-unknown - - time cargo web build -p substrate-serializer - - time cargo web build -p substrate-state-db - - time cargo web build -p substrate-state-machine - - time cargo web build -p substrate-telemetry - - time cargo web build -p substrate-trie + - time cargo build --target=wasm32-unknown-unknown -p sp-io + - time cargo build --target=wasm32-unknown-unknown -p sp-runtime + - time cargo build --target=wasm32-unknown-unknown -p sp-std + - time cargo build --target=wasm32-unknown-unknown -p sc-client + - time cargo build --target=wasm32-unknown-unknown -p sc-consensus-aura + - time cargo build --target=wasm32-unknown-unknown -p sc-consensus-babe + - time cargo build --target=wasm32-unknown-unknown -p sp-consensus + - time cargo build --target=wasm32-unknown-unknown -p sc-telemetry + # Note: the command below is a bit weird because several Cargo issues prevent us from compiling the node in a more straight-forward way. + - time cargo build --manifest-path=bin/node/cli/Cargo.toml --no-default-features --features "browser" --target=wasm32-unknown-unknown - sccache -s node-exits: @@ -222,21 +241,42 @@ node-exits: except: - /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 script: - - ./ci/check_for_exit.sh + - ./.maintain/check_for_exit.sh + + +test-full-crypto-feature: + stage: test + <<: *docker-env + variables: + # Enable debug assertions since we are running optimized builds for testing + # but still want to have debug assertions. + RUSTFLAGS: -Cdebug-assertions=y + RUST_BACKTRACE: 1 + except: + variables: + - $DEPLOY_TAG + script: + - cd primitives/core/ + - time cargo +nightly build --verbose --no-default-features --features full_crypto + - cd ../application-crypto + - time cargo +nightly build --verbose --no-default-features --features full_crypto + - sccache -s + #### stage: build -build-linux-substrate: +build-linux-substrate: &build-binary stage: build <<: *collect-artifacts <<: *docker-env <<: *build-only + before_script: + - mkdir -p ./artifacts/substrate/ except: variables: - $DEPLOY_TAG script: - - time cargo build --release --verbose - - mkdir -p ./artifacts/substrate/ + - WASM_BUILD_NO_COLOR=1 time cargo build --release --verbose - mv ./target/release/substrate ./artifacts/substrate/. - echo -n "Substrate version = " - if [ "${CI_COMMIT_TAG}" ]; then @@ -248,31 +288,25 @@ build-linux-substrate: fi - sha256sum ./artifacts/substrate/substrate | tee ./artifacts/substrate/substrate.sha256 - printf '\n# building node-template\n\n' - - ./scripts/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz - - cp -r scripts/docker/substrate.Dockerfile ./artifacts/substrate/ + - ./.maintain/node-template-release.sh ./artifacts/substrate/substrate-node-template.tar.gz + - cp -r .maintain/docker/substrate.Dockerfile ./artifacts/substrate/ - sccache -s build-linux-subkey: - stage: build - <<: *collect-artifacts - <<: *docker-env - <<: *build-only - except: - variables: - - $DEPLOY_TAG + <<: *build-binary + before_script: + - mkdir -p ./artifacts/subkey script: - - cd ./subkey + - cd ./bin/utils/subkey - BUILD_DUMMY_WASM_BINARY=1 time cargo build --release --verbose - - cd .. - - sccache -s - - mkdir -p ./artifacts/subkey + - cd - - mv ./target/release/subkey ./artifacts/subkey/. - echo -n "Subkey version = " - ./artifacts/subkey/subkey --version | sed -n -r 's/^subkey ([0-9.]+.*)/\1/p' | tee ./artifacts/subkey/VERSION; - sha256sum ./artifacts/subkey/subkey | tee ./artifacts/subkey/subkey.sha256 - - cp -r scripts/docker/subkey.Dockerfile ./artifacts/subkey/ + - cp -r .maintain/docker/subkey.Dockerfile ./artifacts/subkey/ - sccache -s build-rust-doc-release: @@ -288,9 +322,9 @@ build-rust-doc-release: <<: *build-only script: - rm -f ./crate-docs/index.html # use it as an indicator if the job succeeds - - BUILD_DUMMY_WASM_BINARY=1 RUSTDOCFLAGS="--html-in-header $(pwd)/rustdoc-header.html" time cargo +nightly doc --release --all --verbose + - BUILD_DUMMY_WASM_BINARY=1 RUSTDOCFLAGS="--html-in-header $(pwd)/.maintain/rustdoc-header.html" time cargo +nightly doc --release --all --verbose - cp -R ./target/doc ./crate-docs - - echo "" > ./crate-docs/index.html + - echo "" > ./crate-docs/index.html - sccache -s check_warnings: @@ -312,6 +346,42 @@ check_warnings: fi allow_failure: true +# Nightly check whether Polkadot 'master' branch builds. +check_polkadot: + stage: build + <<: *docker-env + allow_failure: true + only: + - master + - schedules + script: + - SUBSTRATE_PATH=$(pwd) + # Clone the current Polkadot master branch into ./polkadot. + - git clone --depth 1 https://gitlab.parity.io/parity/polkadot.git + - cd polkadot + # Make sure we override the crates in native and wasm build + - mkdir .cargo + - echo "paths = [ \"$SUBSTRATE_PATH\" ]" > .cargo/config + - mkdir -p target/debug/wbuild/.cargo + - echo "paths = [ \"$SUBSTRATE_PATH\" ]" > target/debug/wbuild/.cargo/config + # package, others are updated along the way. + - cargo update + # Check whether Polkadot 'master' branch builds with this Substrate commit. + - time cargo check + - cd - + - sccache -s + +trigger-contracts-ci: + stage: publish + needs: + - build-linux-substrate + trigger: + project: parity/srml-contracts-waterfall + branch: "master" + only: + - master + - schedules + #### stage: publish .publish-docker-release: &publish-docker-release @@ -478,10 +548,10 @@ publish-gh-doc: - echo "Substrate version = ${DEPLOY_TAG}" # or use helm to render the template - helm template - --values ./scripts/kubernetes/values.yaml + --values ./.maintain/kubernetes/values.yaml --set image.tag=${DEPLOY_TAG} --set validator.keys=${VALIDATOR_KEYS} - ./scripts/kubernetes | kubectl apply -f - --dry-run=false + ./.maintain/kubernetes | kubectl apply -f - --dry-run=false - echo "# substrate namespace ${KUBE_NAMESPACE}" - kubectl -n ${KUBE_NAMESPACE} get all - echo "# substrate's nodes' external ip addresses:" @@ -543,16 +613,16 @@ deploy-ue1-tag: validator 1 4: <<: *validator-deploy script: - - ./scripts/flamingfir-deploy.sh flamingfir-validator1 + - ./.maintain/flamingfir-deploy.sh flamingfir-validator1 validator 2 4: <<: *validator-deploy script: - - ./scripts/flamingfir-deploy.sh flamingfir-validator2 + - ./.maintain/flamingfir-deploy.sh flamingfir-validator2 validator 3 4: <<: *validator-deploy script: - - ./scripts/flamingfir-deploy.sh flamingfir-validator3 + - ./.maintain/flamingfir-deploy.sh flamingfir-validator3 validator 4 4: <<: *validator-deploy script: - - ./scripts/flamingfir-deploy.sh flamingfir-validator4 + - ./.maintain/flamingfir-deploy.sh flamingfir-validator4 diff --git a/Dockerfile b/.maintain/Dockerfile similarity index 100% rename from Dockerfile rename to .maintain/Dockerfile diff --git a/scripts/build-only-wasm.sh b/.maintain/build-only-wasm.sh similarity index 100% rename from scripts/build-only-wasm.sh rename to .maintain/build-only-wasm.sh diff --git a/ci/check_for_exit.sh b/.maintain/check_for_exit.sh similarity index 100% rename from ci/check_for_exit.sh rename to .maintain/check_for_exit.sh diff --git a/scripts/docker/subkey.Dockerfile b/.maintain/docker/subkey.Dockerfile similarity index 93% rename from scripts/docker/subkey.Dockerfile rename to .maintain/docker/subkey.Dockerfile index 6d5c559ea03dd..9184cad5b4058 100644 --- a/scripts/docker/subkey.Dockerfile +++ b/.maintain/docker/subkey.Dockerfile @@ -8,7 +8,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="parity/subkey" \ io.parity.image.description="Subkey: key generating utility for Substrate." \ - io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/scripts/docker/subkey.Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/.maintain/docker/subkey.Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://github.com/paritytech/substrate/tree/${VCS_REF}/subkey" diff --git a/scripts/docker/substrate.Dockerfile b/.maintain/docker/substrate.Dockerfile similarity index 96% rename from scripts/docker/substrate.Dockerfile rename to .maintain/docker/substrate.Dockerfile index 2bdf49e2fcec2..7cd4576a9e89f 100644 --- a/scripts/docker/substrate.Dockerfile +++ b/.maintain/docker/substrate.Dockerfile @@ -8,7 +8,7 @@ LABEL io.parity.image.authors="devops-team@parity.io" \ io.parity.image.vendor="Parity Technologies" \ io.parity.image.title="parity/substrate" \ io.parity.image.description="Substrate: The platform for blockchain innovators." \ - io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/scripts/docker/Dockerfile" \ + io.parity.image.source="https://github.com/paritytech/substrate/blob/${VCS_REF}/.maintain/docker/Dockerfile" \ io.parity.image.revision="${VCS_REF}" \ io.parity.image.created="${BUILD_DATE}" \ io.parity.image.documentation="https://wiki.parity.io/Parity-Substrate" diff --git a/.maintain/ensure-deps.sh b/.maintain/ensure-deps.sh new file mode 100755 index 0000000000000..7087200cef518 --- /dev/null +++ b/.maintain/ensure-deps.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +# The script is meant to check if the rules regarding packages +# dependencies are satisfied. +# The general format is: +# [top-lvl-dir] MESSAGE/[other-top-dir] + +# For instance no crate within `./client` directory +# is allowed to import any crate with a directory path containing `frame`. +# Such rule is just: `client crates must not depend on anything in /frame`. + +# The script should be run from the main repo directory! + +set -u + +# HARD FAILING +MUST_NOT=( + "client crates must not depend on anything in /frame" + "client crates must not depend on anything in /node" + "frame crates must not depend on anything in /node" + "frame crates must not depend on anything in /client" + "primitives crates must not depend on anything in /frame" +) + +# ONLY DISPLAYED, script still succeeds +PLEASE_DONT=( + "primitives crates should not depend on anything in /client" +) + +VIOLATIONS=() +PACKAGES=() + +function check_rule() { + rule=$1 + from=$(echo $rule | cut -f1 -d\ ) + to=$(echo $rule | cut -f2 -d\/) + + cd $from + echo "Checking rule '$rule'" + packages=$(find -name Cargo.toml | xargs grep -wn "path.*\.\.\/$to") + has_references=$(echo -n $packages | wc -c) + if [ "$has_references" != "0" ]; then + VIOLATIONS+=("$rule") + # Find packages that violate: + PACKAGES+=("$packages") + fi + cd - > /dev/null +} + +for rule in "${MUST_NOT[@]}" +do + check_rule "$rule"; +done + +# Only the MUST NOT will be counted towards failure +HARD_VIOLATIONS=${#VIOLATIONS[@]} + + +for rule in "${PLEASE_DONT[@]}" +do + check_rule "$rule"; +done + +# Display violations and fail +I=0 +for v in "${VIOLATIONS[@]}" +do + cat << EOF + +=========================================== +======= Violation of rule: $v +=========================================== +${PACKAGES[$I]} + + +EOF + I=$I+1 +done + +exit $HARD_VIOLATIONS diff --git a/scripts/flamingfir-deploy.sh b/.maintain/flamingfir-deploy.sh similarity index 100% rename from scripts/flamingfir-deploy.sh rename to .maintain/flamingfir-deploy.sh diff --git a/scripts/getgoing.sh b/.maintain/getgoing.sh similarity index 100% rename from scripts/getgoing.sh rename to .maintain/getgoing.sh diff --git a/scripts/gitlab/check_line_width.sh b/.maintain/gitlab/check_line_width.sh similarity index 100% rename from scripts/gitlab/check_line_width.sh rename to .maintain/gitlab/check_line_width.sh diff --git a/scripts/gitlab/check_runtime.sh b/.maintain/gitlab/check_runtime.sh similarity index 83% rename from scripts/gitlab/check_runtime.sh rename to .maintain/gitlab/check_runtime.sh index cd988718d05db..f989904cb5cde 100755 --- a/scripts/gitlab/check_runtime.sh +++ b/.maintain/gitlab/check_runtime.sh @@ -1,7 +1,7 @@ #!/bin/sh # # -# check for any changes in the node/src/runtime, srml/ and core/sr_* trees. if +# check for any changes in the node/src/runtime, frame/ and primitives/sr_* trees. if # there are any changes found, it should mark the PR breaksconsensus and # "auto-fail" the PR if there isn't a change in the runtime/src/lib.rs file # that alters the version. @@ -12,9 +12,7 @@ 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" +VERSIONS_FILE="bin/node/runtime/src/lib.rs" github_label () { echo @@ -29,10 +27,18 @@ github_label () { +git fetch --depth=${GIT_DEPTH:-100} origin master + +# check if master is part of this checkout +if ! git log -n 1 origin/master +then + echo "unable to check for runtime changes: checkout does not contain origin/master branch" + exit 3 +fi # check if the wasm sources changed if ! git diff --name-only origin/master...${CI_COMMIT_SHA} \ - | grep -q -e '^node/src/runtime' -e '^srml/' -e '^core/sr-' | grep -v -e '^core/sr-arithmetic/fuzzer' + | grep -q -e '^bin/node/src/runtime' -e '^frame/' -e '^primitives/sr-' | grep -v -e '^primitives/sr-arithmetic/fuzzer' then cat <<-EOT @@ -66,7 +72,7 @@ then changes to the runtime sources and changes in the spec version. spec_version: ${sub_spec_version} -> ${add_spec_version} - + EOT exit 0 @@ -101,9 +107,9 @@ else If they do change logic, bump 'spec_version' and rebuild wasm. source file directories: - - node/src/runtime - - srml - - core/sr-* + - bin/node/src/runtime + - frame + - primitives/sr-* versions file: ${VERSIONS_FILE} diff --git a/node-template/scripts/init.sh b/.maintain/init.sh similarity index 100% rename from node-template/scripts/init.sh rename to .maintain/init.sh diff --git a/scripts/kubernetes/Chart.yaml b/.maintain/kubernetes/Chart.yaml similarity index 100% rename from scripts/kubernetes/Chart.yaml rename to .maintain/kubernetes/Chart.yaml diff --git a/scripts/kubernetes/README.md b/.maintain/kubernetes/README.md similarity index 100% rename from scripts/kubernetes/README.md rename to .maintain/kubernetes/README.md diff --git a/scripts/kubernetes/templates/poddisruptionbudget.yaml b/.maintain/kubernetes/templates/poddisruptionbudget.yaml similarity index 100% rename from scripts/kubernetes/templates/poddisruptionbudget.yaml rename to .maintain/kubernetes/templates/poddisruptionbudget.yaml diff --git a/scripts/kubernetes/templates/secrets.yaml b/.maintain/kubernetes/templates/secrets.yaml similarity index 100% rename from scripts/kubernetes/templates/secrets.yaml rename to .maintain/kubernetes/templates/secrets.yaml diff --git a/scripts/kubernetes/templates/service.yaml b/.maintain/kubernetes/templates/service.yaml similarity index 100% rename from scripts/kubernetes/templates/service.yaml rename to .maintain/kubernetes/templates/service.yaml diff --git a/scripts/kubernetes/templates/serviceaccount.yaml b/.maintain/kubernetes/templates/serviceaccount.yaml similarity index 100% rename from scripts/kubernetes/templates/serviceaccount.yaml rename to .maintain/kubernetes/templates/serviceaccount.yaml diff --git a/scripts/kubernetes/templates/statefulset.yaml b/.maintain/kubernetes/templates/statefulset.yaml similarity index 100% rename from scripts/kubernetes/templates/statefulset.yaml rename to .maintain/kubernetes/templates/statefulset.yaml diff --git a/scripts/kubernetes/values.yaml b/.maintain/kubernetes/values.yaml similarity index 100% rename from scripts/kubernetes/values.yaml rename to .maintain/kubernetes/values.yaml diff --git a/.maintain/node-template-release.sh b/.maintain/node-template-release.sh new file mode 100755 index 0000000000000..1a6c245320593 --- /dev/null +++ b/.maintain/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/.maintain/node-template-release + +cargo run $PROJECT_ROOT/bin/node-template $PATH_TO_ARCHIVE diff --git a/scripts/node-template-release/Cargo.toml b/.maintain/node-template-release/Cargo.toml similarity index 100% rename from scripts/node-template-release/Cargo.toml rename to .maintain/node-template-release/Cargo.toml diff --git a/.maintain/node-template-release/src/main.rs b/.maintain/node-template-release/src/main.rs new file mode 100644 index 0000000000000..db42b155e65e7 --- /dev/null +++ b/.maintain/node-template-release/src/main.rs @@ -0,0 +1,244 @@ +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(); + + for &table in &["dependencies", "build-dependencies"] { + let mut dependencies: toml::value::Table = match cargo_toml + .remove(table) + .and_then(|v| v.try_into().ok()) { + Some(deps) => deps, + None => continue, + }; + + let deps_rewritten = dependencies + .iter() + .filter_map(|(k, v)| v.clone().try_into::().ok().map(move |v| (k, v))) + .filter(|t| t.1.contains_key("path")) + .filter(|t| { + // if the path does not exists, we need to add this as git dependency + t.1.get("path").unwrap().as_str().map(|path| !cargo_toml_path.join(path).exists()).unwrap_or(false) + }) + .map(|(k, mut v)| { + // remove `path` and add `git` and `rev` + v.remove("path"); + v.insert("git".into(), SUBSTRATE_GIT_URL.into()); + v.insert("rev".into(), commit_id.into()); + + (k.clone(), v.into()) + }).collect::>(); + + dependencies.extend(deps_rewritten.into_iter()); + + cargo_toml.insert(table.into(), dependencies.into()); + } +} + +/// Update the top level (workspace) `Cargo.toml` file. +/// +/// - Adds `profile.release` = `panic = unwind` +/// - Adds `workspace` definition +fn update_top_level_cargo_toml( + cargo_toml: &mut CargoToml, + workspace_members: Vec<&PathBuf>, + node_template_path: &Path, +) { + let mut panic_unwind = toml::value::Table::new(); + panic_unwind.insert("panic".into(), "unwind".into()); + + let mut profile = toml::value::Table::new(); + profile.insert("release".into(), panic_unwind.into()); + + cargo_toml.insert("profile".into(), profile.into()); + + let members = workspace_members.iter() + .map(|p| + p.strip_prefix(node_template_path) + .expect("Workspace member is a child of the node template path!") + .parent() + // We get the `Cargo.toml` paths as workspace members, but for the `members` field + // we just need the path. + .expect("The given path ends with `Cargo.toml` as file name!") + .display() + .to_string() + ) + .collect::>(); + + let mut members_section = toml::value::Table::new(); + members_section.insert("members".into(), members.into()); + + cargo_toml.insert("workspace".into(), members_section.into()); +} + +fn write_cargo_toml(path: &Path, cargo_toml: CargoToml) { + 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 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); + let top_level_cargo_toml_path = node_template_path.join("Cargo.toml"); + + cargo_tomls.iter().for_each(|t| { + let mut cargo_toml = parse_cargo_toml(&t); + replace_path_dependencies_with_git(&t, &commit_id, &mut cargo_toml); + + // Check if this is the top level `Cargo.toml`, as this requires some special treatments. + if top_level_cargo_toml_path == *t { + // All workspace member `Cargo.toml` file paths. + let workspace_members = cargo_tomls.iter() + .filter(|p| **p != top_level_cargo_toml_path) + .collect(); + + update_top_level_cargo_toml(&mut cargo_toml, workspace_members, &node_template_path); + } + + write_cargo_toml(&t, cargo_toml); + }); + + 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/.maintain/rename-crates-for-2.0.sh b/.maintain/rename-crates-for-2.0.sh new file mode 100644 index 0000000000000..d2bd871f09780 --- /dev/null +++ b/.maintain/rename-crates-for-2.0.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +function rust_rename() { + sed -i "s/$1/$2/g" `grep -Rl --include="*.rs" --include="*.stderr" "$1" *` > /dev/null +} + +function cargo_rename() { + find . -name "Cargo.toml" -exec sed -i "s/\(^\|[^\/]\)$1/\1$2/g" {} \; +} + +function rename_gitlabci() { + sed -i "s/$1/$2/g" .gitlab-ci.yml +} + +function rename() { + old=$(echo $1 | cut -f1 -d\ ); + new=$(echo $1 | cut -f2 -d\ ); + + echo "Renaming $old to $new" + # rename in Cargo.tomls + cargo_rename $old $new + rename_gitlabci $old $new + # and it appears, we have the same syntax in rust files + rust_rename $old $new + + # but generally we have the snail case syntax in rust files + old=$(echo $old | sed s/-/_/g ); + new=$(echo $new | sed s/-/_/g ); + + echo " > $old to $new" + rust_rename $old $new +} + +TO_RENAME=( + # OLD-CRATE-NAME NEW-CRATE-NAME + + # post initial rename fixes + "sc-application-crypto sp-application-crypto" + "sp-transaction-pool-api sp-transaction-pool" + "sp-transaction-pool-runtime-api sp-transaction-pool" + "sp-core-storage sp-storage" + "transaction-factory node-transaction-factory" + "sp-finality-granpda sp-finality-grandpa" + "sp-sesssion sp-session" + "sp-tracing-pool sp-transaction-pool" + + # PRIMITIVES + "substrate-application-crypto sp-application-crypto" + "substrate-authority-discovery-primitives sp-authority-discovery" + "substrate-block-builder-runtime-api sp-block-builder" + "substrate-consensus-aura-primitives sp-consensus-aura" + "substrate-consensus-babe-primitives sp-consensus-babe" + "substrate-consensus-common sp-consensus" + "substrate-consensus-pow-primitives sp-consensus-pow" + "substrate-primitives sp-core" + "substrate-debug-derive sp-debug-derive" + "substrate-primitives-storage sp-storage" + "substrate-externalities sp-externalities" + "substrate-finality-grandpa-primitives sp-finality-grandpa" + "substrate-inherents sp-inherents" + "substrate-keyring sp-keyring" + "substrate-offchain-primitives sp-offchain" + "substrate-panic-handler sp-panic-handler" + "substrate-phragmen sp-phragmen" + "substrate-rpc-primitives sp-rpc" + "substrate-runtime-interface sp-runtime-interface" + "substrate-runtime-interface-proc-macro sp-runtime-interface-proc-macro" + "substrate-runtime-interface-test-wasm sp-runtime-interface-test-wasm" + "substrate-serializer sp-serializer" + "substrate-session sp-session" + "sr-api sp-api" + "sr-api-proc-macro sp-api-proc-macro" + "sr-api-test sp-api-test" + "sr-arithmetic sp-arithmetic" + "sr-arithmetic-fuzzer sp-arithmetic-fuzzer" + "sr-io sp-io" + "sr-primitives sp-runtime" + "sr-sandbox sp-sandbox" + "sr-staking-primitives sp-staking" + "sr-std sp-std" + "sr-version sp-version" + "substrate-state-machine sp-state-machine" + "substrate-transaction-pool-runtime-api sp-transaction-pool" + "substrate-trie sp-trie" + "substrate-wasm-interface sp-wasm-interface" + + # # CLIENT + "substrate-client sc-client" + "substrate-client-api sc-api" + "substrate-authority-discovery sc-authority-discovery" + "substrate-basic-authorship sc-basic-authority" + "substrate-block-builder sc-block-builder" + "substrate-chain-spec sc-chain-spec" + "substrate-chain-spec-derive sc-chain-spec-derive" + "substrate-cli sc-cli" + "substrate-consensus-aura sc-consensus-aura" + "substrate-consensus-babe sc-consensus-babe" + "substrate-consensus-pow sc-consensus-pow" + "substrate-consensus-slots sc-consensus-slots" + "substrate-consensus-uncles sc-consensus-uncles" + "substrate-client-db sc-database" + "substrate-executor sc-executor" + "substrate-runtime-test sc-runtime-test" + "substrate-finality-grandpa sc-finality-grandpa" + "substrate-keystore sc-keystore" + "substrate-network sc-network" + "substrate-offchain sc-offchain" + "substrate-peerset sc-peerset" + "substrate-rpc-servers sc-rpc-server" + "substrate-rpc sc-rpc" + "substrate-service sc-service" + "substrate-service-test sc-service-test" + "substrate-state-db sc-state-db" + "substrate-telemetry sc-telemetry" + "substrate-test-primitives sp-test-primitives" + "substrate-tracing sc-tracing" + +); + +for rule in "${TO_RENAME[@]}" +do + rename "$rule"; +done diff --git a/scripts/runtime-dep.py b/.maintain/runtime-dep.py similarity index 91% rename from scripts/runtime-dep.py rename to .maintain/runtime-dep.py index 1d0c42b2f57e8..3198bb3e2669e 100755 --- a/scripts/runtime-dep.py +++ b/.maintain/runtime-dep.py @@ -4,7 +4,7 @@ # pip install toml # sudo apt-get install graphviz # the first parameter is the runtime folder -# python ./scripts/runtime-dep.py ./substrate/runtime | dot -Tpng -o output.png +# python ./.maintain/runtime-dep.py ./substrate/runtime | dot -Tpng -o output.png import sys import os import toml diff --git a/rustdoc-header.html b/.maintain/rustdoc-header.html similarity index 100% rename from rustdoc-header.html rename to .maintain/rustdoc-header.html diff --git a/scripts/sentry-node/docker-compose.yml b/.maintain/sentry-node/docker-compose.yml similarity index 79% rename from scripts/sentry-node/docker-compose.yml rename to .maintain/sentry-node/docker-compose.yml index 78f8ba36b82ee..0ca42613b4576 100644 --- a/scripts/sentry-node/docker-compose.yml +++ b/.maintain/sentry-node/docker-compose.yml @@ -12,7 +12,7 @@ # # 1. Build `target/release/substrate` binary: `cargo build --release` # -# 2. Start networks and containers: `sudo docker-compose -f scripts/sentry-node/docker-compose.yml up` +# 2. Start networks and containers: `sudo docker-compose -f .maintain/sentry-node/docker-compose.yml up` # # 3. Reach: # - polkadot/apps on localhost:3000 @@ -38,22 +38,23 @@ services: - "--base-path" - "/tmp/alice" - "--chain=local" - - "--key" - - "//Alice" - "--port" - "30333" - "--validator" - - "--name" - - "AlicesNode" + - "--alice" + - "--sentry-nodes" + - "/dns4/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi" - "--reserved-nodes" - "/dns4/sentry-a/tcp/30333/p2p/QmV7EhW6J6KgmNdr558RH1mPx2xGGznW7At4BhXzntRFsi" # Not only bind to localhost. - - "--ws-external" - - "--rpc-external" + - "--unsafe-ws-external" + - "--unsafe-rpc-external" # - "--log" # - "sub-libp2p=trace" # - "--log" # - "afg=trace" + - "--log" + - "sub-authority-discovery=trace" - "--no-telemetry" - "--rpc-cors" - "all" @@ -74,28 +75,24 @@ services: - "--base-path" - "/tmp/sentry" - "--chain=local" - # Don't configure a key, as sentry-a is not a validator. - # - "--key" - # - "//Charlie" - "--port" - "30333" - # sentry-a is not a validator. - # - "--validator" - - "--name" - - "CharliesNode" + - "--charlie" - "--bootnodes" - "/dns4/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" - "--bootnodes" - "/dns4/validator-b/tcp/30333/p2p/QmSVnNf9HwVMT1Y4cK1P6aoJcEZjmoTXpjKBmAABLMnZEk" + - "--reserved-nodes" + - "/dns4/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" - "--no-telemetry" - "--rpc-cors" - "all" # Not only bind to localhost. - - "--ws-external" - - "--rpc-external" - # Make sure sentry-a still participates as a grandpa voter to forward - # grandpa finality gossip messages. - - "--grandpa-voter" + - "--unsafe-ws-external" + - "--unsafe-rpc-external" + - "--log" + - "sub-authority-discovery=trace" + - "--sentry" validator-b: image: parity/substrate @@ -112,13 +109,10 @@ services: - "--base-path" - "/tmp/bob" - "--chain=local" - - "--key" - - "//Bob" - "--port" - "30333" - "--validator" - - "--name" - - "BobsNode" + - "--bob" - "--bootnodes" - "/dns4/validator-a/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR" - "--bootnodes" @@ -127,8 +121,10 @@ services: - "--rpc-cors" - "all" # Not only bind to localhost. - - "--ws-external" - - "--rpc-external" + - "--unsafe-ws-external" + - "--unsafe-rpc-external" + - "--log" + - "sub-authority-discovery=trace" ui: image: polkadot-js/apps diff --git a/scripts/update-copyright.sh b/.maintain/update-copyright.sh similarity index 100% rename from scripts/update-copyright.sh rename to .maintain/update-copyright.sh diff --git a/scripts/update-deps.sh b/.maintain/update-deps.sh similarity index 100% rename from scripts/update-deps.sh rename to .maintain/update-deps.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 4180defedfd6a..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Request an environment that provides sudo (that goes with larger containers) -# and a minimal language environment. -sudo: true -language: minimal - -cache: cargo - -branches: - only: - - master - -env: - global: - - RUST_BACKTRACE=1 - matrix: - - RUST_TOOLCHAIN=nightly TARGET=wasm - - RUST_TOOLCHAIN=stable TARGET=native - -before_install: - # Check how much space we've got on this machine. - - df -h - -script: - - ./ci/script.sh - -after_script: - # Check how much free disk space left after the build - - df -h diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index 866f16522316b..0000000000000 --- a/CODEOWNERS +++ /dev/null @@ -1,68 +0,0 @@ -# Lists some code owners. -# -# A codeowner just oversees some part of the codebase. If an owned file is changed then the -# corresponding codeowner receives a review request. An approval of the codeowner is -# not required for merging a PR though. -# -# **This is pretty much an experiment at the moment**. Feel free to remove yourself at any time if -# you do not want to receive review requests any longer. -# -# For details about syntax, see: -# https://help.github.com/en/articles/about-code-owners -# But here are some important notes: -# -# - Glob syntax is git-like, e.g. `/core` means the core directory in the root, unlike `core` which -# can be everywhere. -# - Multiple owners are supported. -# - Either handle (e.g, @pepyakin) or email can be used. Keep in mind, that handles might work better because they -# are more recognizable on GitHub, you can use them for mentioning unlike an email. -# - The latest matching rule, if multiple, takes precedence. - -# Wasm execution and the wasm side of Substrate Runtime Interface -/core/executor/ @pepyakin -/core/sr-io/without_std.rs @pepyakin -/core/sr-std/without_std.rs @pepyakin - -# Sandboxing capability of Substrate Runtime -/core/sr-sandbox/ @pepyakin -/core/primitives/src/sandbox.rs @pepyakin - -# Transaction pool -/core/transaction-pool/ @tomusdrw - -# Offchain -/core/offchain/ @tomusdrw -/sr-io/src/offchain/ @tomusdrw - -# Everything that has RPC in it -/core/rpc/ @tomusdrw -/node/rpc/ @tomusdrw -/node/rpc-client/ @tomusdrw -/core/rpc-servers/ @tomusdrw - -# GRANDPA, BABE, consensus stuff -/srml/babe/ @andresilva @DemiMarie-parity -/srml/grandpa/ @andresilva @DemiMarie-parity -/core/finality-grandpa/ @andresilva @DemiMarie-parity -/core/consensus/babe/ @andresilva @DemiMarie-parity -/core/consensus/slots/ @andresilva @DemiMarie-parity - -# Contracts -/srml/contracts/ @pepyakin @thiolliere @jimpo -/srml/contracts/src/wasm/runtime.rs @Robbepop - -# Inflation points -/srml/staking/src/inflation.rs @thiolliere - -# NPoS and Governance -/srml/staking/ @kianenigma -/srml/election/ @kianenigma - -# End to end testing of substrate node -/node/executor/ @kianenigma - -# Transaction weight stuff -/core/sr-primitives/weights.rs @kianenigma - -# Support crates -/srml/support/ @thiolliere @kianenigma diff --git a/Cargo.lock b/Cargo.lock index e29118c45ce54..49766b9fae217 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "adler32" version = "1.0.4" @@ -38,7 +47,7 @@ dependencies = [ [[package]] name = "ahash" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -52,19 +61,6 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "aio-limited" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ansi_term" version = "0.11.0" @@ -81,6 +77,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "anyhow" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "app_dirs" version = "1.2.1" @@ -94,7 +95,7 @@ dependencies = [ [[package]] name = "arc-swap" -version = "0.3.11" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -110,6 +111,11 @@ dependencies = [ "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "asn1_der" version = "0.6.3" @@ -124,7 +130,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -132,38 +138,92 @@ name = "assert_matches" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "async-macros" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-std" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "broadcaster 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-task" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.38" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -177,7 +237,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -188,30 +248,45 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bincode" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bindgen" -version = "0.47.3" +version = "0.49.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -221,7 +296,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitvec" -version = "0.14.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -245,12 +320,13 @@ dependencies = [ ] [[package]] -name = "block-buffer" -version = "0.2.0" +name = "blake2b_simd" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -258,7 +334,7 @@ name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.5 (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.2 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -274,17 +350,57 @@ dependencies = [ [[package]] name = "block-padding" -version = "0.1.4" +version = "0.1.5" 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 = "broadcaster" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "browser-utils" +version = "2.0.0" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "console_log 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-web 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-chain-spec 2.0.0", + "sc-network 0.8.0", + "sc-service 2.0.0", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bs58" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bs58" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bstr" version = "0.2.8" @@ -293,7 +409,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -306,17 +422,12 @@ dependencies = [ [[package]] name = "bumpalo" -version = "2.6.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byte-slice-cast" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byte-tools" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -344,13 +455,17 @@ dependencies = [ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bytes" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "c2-chacha" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -360,32 +475,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo_metadata" -version = "0.8.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cast" -version = "0.2.2" +version = "0.2.3" 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 = "cc" -version = "1.0.45" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cexpr" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -403,29 +521,29 @@ dependencies = [ "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "node-cli 2.0.0", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-keystore 2.0.0", - "substrate-primitives 2.0.0", + "sc-keystore 2.0.0", + "sp-core 2.0.0", + "structopt 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "chrono" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clang-sys" -version = "0.26.4" +version = "0.28.1" 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.62 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -436,12 +554,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -449,7 +566,7 @@ name = "clear_on_drop" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -457,7 +574,7 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -465,7 +582,25 @@ name = "cmake" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "console_log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -474,7 +609,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -482,7 +617,7 @@ name = "const-random-macro" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -497,7 +632,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -505,6 +640,88 @@ name = "core-foundation-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cranelift-bforest" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-bforest 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-meta 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-entity" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-frontend" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-native" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-wasm" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crc32fast" version = "1.2.0" @@ -519,22 +736,22 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -545,20 +762,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -569,8 +786,8 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -578,37 +795,37 @@ name = "criterion-plot" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "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)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-channel" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -620,6 +837,14 @@ dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.6.6" @@ -630,18 +855,19 @@ dependencies = [ ] [[package]] -name = "crunchy" -version = "0.2.2" +name = "crossbeam-utils" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "crypto-mac" -version = "0.4.0" +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "constant_time_eq 0.1.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]] name = "crypto-mac" @@ -660,8 +886,8 @@ dependencies = [ "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -672,13 +898,21 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ct-logs" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ctor" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -717,7 +951,19 @@ dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curve25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -727,15 +973,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "derive_more" -version = "0.15.0" +version = "0.99.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -745,18 +988,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "digest" -version = "0.6.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "digest" -version = "0.8.1" +name = "directories" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dirs-sys" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -775,25 +1030,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ed25519-dalek" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.0-pre.2" +version = "1.0.0-pre.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -803,11 +1045,21 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "elastic-array" -version = "0.10.2" +name = "enumflags2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "enumflags2_derive 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "enumflags2_derive" +version = "0.6.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)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -824,7 +1076,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -844,25 +1096,91 @@ name = "erased-serde" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "error-chain" -version = "0.12.1" +name = "errno" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "evm" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "evm-core 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-gasometer 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "evm-core" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "evm-gasometer" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "evm-core 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "evm-runtime" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "evm-core 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "exit-future" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "faerie" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -870,7 +1188,7 @@ name = "failure" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -881,8 +1199,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -890,49 +1208,52 @@ name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fdlimit" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "finality-grandpa" -version = "0.9.1" -source = "git+https://github.com/paritytech/finality-grandpa#286133ec5de04b077f093bcb4487637125ad2397" +name = "file-per-thread-logger" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "fixed-hash" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "finality-grandpa" +version = "0.11.0" +source = "git+https://github.com/expenses/finality-grandpa?branch=future#2abf691f4ceadaa7f65b6713ad2d16cf87445bd9" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fixed-hash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -942,16 +1263,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "flate2" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -976,7 +1295,131 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "fork-tree" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-executive" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-balances 2.0.0", + "pallet-indices 2.0.0", + "pallet-transaction-payment 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "frame-metadata" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "frame-support" +version = "2.0.0" +dependencies = [ + "bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-metadata 2.0.0", + "frame-support-procedural 2.0.0", + "frame-system 2.0.0", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-arithmetic 2.0.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "sp-std 2.0.0", + "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-support-procedural" +version = "2.0.0" +dependencies = [ + "frame-support-procedural-tools 2.0.0", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "2.0.0" +dependencies = [ + "frame-support-procedural-tools-derive 2.0.0", + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "2.0.0" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-support-test" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "trybuild 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-system" +version = "2.0.0" +dependencies = [ + "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.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.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", + "sp-version 2.0.0", +] + +[[package]] +name = "frame-system-rpc-runtime-api" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", ] [[package]] @@ -985,7 +1428,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -995,7 +1438,7 @@ name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1009,7 +1452,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1023,6 +1466,29 @@ name = "futures" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "futures-channel-preview" version = "0.3.0-alpha.19" @@ -1032,6 +1498,11 @@ dependencies = [ "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "futures-core-preview" version = "0.3.0-alpha.19" @@ -1043,59 +1514,84 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "futures-executor-preview" -version = "0.3.0-alpha.19" +name = "futures-executor" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "futures-io-preview" -version = "0.3.0-alpha.19" +name = "futures-io" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "futures-preview" -version = "0.3.0-alpha.19" +name = "futures-macro" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-sink" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "futures-sink-preview" version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures-task" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "futures-timer" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-timer" -version = "0.4.0" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1103,30 +1599,37 @@ name = "futures-util-preview" version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "gcc" -version = "0.3.55" +name = "futures_codec" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "generic-array" -version = "0.8.3" +name = "fxhash" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "generic-array" version = "0.12.3" @@ -1142,7 +1645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1152,17 +1655,30 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gimli" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1188,22 +1704,78 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.1.26" +name = "goblin" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "grafana-data-source" +version = "2.0.0" +dependencies = [ + "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "grafana-data-source-test" +version = "2.0.0" +dependencies = [ + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "grafana-data-source 2.0.0", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "h2" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "h2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hash-db" version = "0.15.2" @@ -1228,19 +1800,16 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.6.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "heapsize" -version = "0.4.2" +name = "hashbrown" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1248,12 +1817,20 @@ name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hermit-abi" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hex" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1262,7 +1839,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1270,17 +1847,7 @@ name = "hex-literal-impl" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.10 (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)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1292,16 +1859,6 @@ dependencies = [ "digest 0.8.1 (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 = "hmac-drbg" version = "0.2.0" @@ -1314,7 +1871,7 @@ dependencies = [ [[package]] name = "http" -version = "0.1.18" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1322,6 +1879,16 @@ dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "http-body" version = "0.1.0" @@ -1329,10 +1896,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http-body" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.4" @@ -1356,7 +1932,7 @@ 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.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (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)", @@ -1373,7 +1949,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1384,15 +1960,53 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 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-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 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)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-rustls" +version = "0.17.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)", + "ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hyper-tls" version = "0.3.2" @@ -1412,7 +2026,7 @@ 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)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1422,39 +2036,50 @@ 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)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "impl-codec" -version = "0.4.1" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-rlp" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "impl-serde" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "impl-trait-for-tuples" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "indexmap" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "integer-sqrt" @@ -1471,17 +2096,17 @@ name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ipnet" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itertools" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1497,120 +2122,120 @@ name = "jobserver" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "js-sys" -version = "0.3.28" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-client-transports" -version = "13.2.0" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-core" -version = "13.2.0" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-core-client" -version = "13.2.0" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-client-transports 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-client-transports 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-derive" -version = "13.2.0" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-http-server" -version = "13.2.0" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-server-utils 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-pubsub" -version = "13.2.0" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-server-utils" -version = "13.2.0" +version = "14.0.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)", "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-ws-server" -version = "13.2.0" +version = "14.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-server-utils 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1637,38 +2262,66 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "kv-log-macro" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (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" +version = "0.3.1" +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)", - "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-util-mem 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "kvdb-memorydb" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "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)", + "kvdb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-util-mem 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "kvdb-rocksdb" -version = "0.1.4" -source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" +version = "0.4.1" +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)", "fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "kvdb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-util-mem 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rocksdb 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kvdb-web" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-util-mem 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "send_wrapper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1680,6 +2333,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "lazycell" @@ -1688,7 +2344,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1696,425 +2352,391 @@ name = "libloading" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p" -version = "0.12.0" +version = "0.14.0-alpha.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.29 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core-derive 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-deflate 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-dns 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-floodsub 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-identify 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-kad 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mdns 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mplex 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-noise 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ping 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-plaintext 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ratelimit 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-secio 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-tcp 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-uds 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-wasm-ext 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-websocket 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-yamux 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core-derive 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-deflate 0.6.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-dns 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-floodsub 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-kad 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mdns 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mplex 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-noise 0.12.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-plaintext 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-secio 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.4.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-tcp 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-uds 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-wasm-ext 0.7.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-websocket 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-yamux 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-core" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "multistream-select 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-core-derive" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-deflate" -version = "0.4.0" +version = "0.6.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-dns" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-floodsub" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bs58 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (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.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.4.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-identify" -version = "0.12.0" +version = "0.14.0-alpha.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.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures_codec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.4.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-kad" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures_codec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.4.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-mdns" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "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.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.4.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-mplex" -version = "0.12.0" +version = "0.14.0-alpha.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)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures_codec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-noise" -version = "0.10.0" +version = "0.12.0-alpha.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)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "snow 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-ping" -version = "0.12.0" +version = "0.14.0-alpha.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.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.4.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-plaintext" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-ratelimit" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aio-limited 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures_codec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.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-secio" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quicksink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-swarm" -version = "0.2.0" +version = "0.4.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-tcp" -version = "0.12.0" +version = "0.14.0-alpha.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.29 (registry+https://github.com/rust-lang/crates.io-index)", + "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnet 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnet 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-uds" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-wasm-ext" -version = "0.5.0" +version = "0.7.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-websocket" -version = "0.12.0" +version = "0.14.0-alpha.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.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-tls 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "soketto 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.10.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quicksink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "soketto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-yamux" -version = "0.12.0" +version = "0.14.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "yamux 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "yamux 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "librocksdb-sys" -version = "5.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libsecp256k1" -version = "0.2.2" +version = "6.2.4" 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.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bindgen 0.49.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libsecp256k1" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2123,10 +2745,10 @@ name = "libz-sys" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2147,21 +2769,12 @@ 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 = "lock_api" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lock_api" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2184,21 +2797,37 @@ dependencies = [ ] [[package]] -name = "lru-cache" -version = "0.1.2" +name = "lru" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lru" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mach" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "malloc_size_of_derive" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2206,17 +2835,22 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memoffset" -version = "0.5.1" +version = "0.5.3" 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)", @@ -2224,12 +2858,13 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.15.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-util-mem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2239,13 +2874,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "merlin" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2258,7 +2893,7 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2266,14 +2901,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "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.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2283,12 +2919,12 @@ dependencies = [ [[package]] name = "mio-extras" -version = "2.0.5" +version = "2.0.6" 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.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2298,8 +2934,8 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2313,6 +2949,11 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "more-asserts" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "multimap" version = "0.4.0" @@ -2320,15 +2961,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "multistream-select" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2345,14 +2986,14 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.26 (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.51 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2362,7 +3003,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2371,10 +3012,10 @@ name = "nix" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2382,84 +3023,96 @@ dependencies = [ name = "node-cli" version = "2.0.0" dependencies = [ - "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "browser-utils 2.0.0", + "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "node-executor 2.0.0", "node-primitives 2.0.0", "node-rpc 2.0.0", "node-runtime 2.0.0", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "node-transaction-factory 2.0.0", + "pallet-authority-discovery 2.0.0", + "pallet-balances 2.0.0", + "pallet-contracts 2.0.0", + "pallet-im-online 2.0.0", + "pallet-indices 2.0.0", + "pallet-timestamp 2.0.0", + "pallet-transaction-payment 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "srml-authority-discovery 0.1.0", - "srml-balances 2.0.0", - "srml-contracts 2.0.0", - "srml-finality-tracker 2.0.0", - "srml-im-online 0.1.0", - "srml-indices 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "srml-transaction-payment 2.0.0", - "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-authority-discovery 2.0.0", - "substrate-basic-authorship 2.0.0", - "substrate-chain-spec 2.0.0", - "substrate-cli 2.0.0", - "substrate-client 2.0.0", - "substrate-client-db 2.0.0", - "substrate-consensus-babe 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-finality-grandpa 2.0.0", - "substrate-finality-grandpa-primitives 2.0.0", - "substrate-inherents 2.0.0", - "substrate-keyring 2.0.0", - "substrate-keystore 2.0.0", - "substrate-network 2.0.0", - "substrate-offchain 2.0.0", - "substrate-primitives 2.0.0", - "substrate-rpc 2.0.0", - "substrate-service 2.0.0", - "substrate-service-test 2.0.0", - "substrate-telemetry 2.0.0", - "substrate-transaction-pool 2.0.0", + "sc-authority-discovery 2.0.0", + "sc-basic-authority 2.0.0", + "sc-chain-spec 2.0.0", + "sc-cli 2.0.0", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-client-db 2.0.0", + "sc-consensus-babe 0.8.0", + "sc-finality-grandpa 2.0.0", + "sc-keystore 2.0.0", + "sc-network 0.8.0", + "sc-offchain 2.0.0", + "sc-rpc 2.0.0", + "sc-service 2.0.0", + "sc-service-test 2.0.0", + "sc-telemetry 2.0.0", + "sc-transaction-pool 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-authority-discovery 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-finality-grandpa 2.0.0", + "sp-finality-tracker 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-timestamp 2.0.0", + "sp-transaction-pool 2.0.0", + "structopt 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-build-script-utils 2.0.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-factory 0.0.1", + "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "node-executor" version = "2.0.0" dependencies = [ + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", "node-primitives 2.0.0", "node-runtime 2.0.0", "node-testing 2.0.0", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "srml-balances 2.0.0", - "srml-contracts 2.0.0", - "srml-grandpa 2.0.0", - "srml-indices 2.0.0", - "srml-session 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "srml-transaction-payment 2.0.0", - "srml-treasury 2.0.0", - "substrate-executor 2.0.0", - "substrate-primitives 2.0.0", - "substrate-state-machine 2.0.0", + "pallet-balances 2.0.0", + "pallet-contracts 2.0.0", + "pallet-grandpa 2.0.0", + "pallet-im-online 2.0.0", + "pallet-indices 2.0.0", + "pallet-session 2.0.0", + "pallet-timestamp 2.0.0", + "pallet-transaction-payment 2.0.0", + "pallet-treasury 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-executor 2.0.0", + "sp-application-crypto 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "sp-trie 2.0.0", "substrate-test-client 2.0.0", - "substrate-trie 2.0.0", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2469,88 +3122,95 @@ name = "node-primitives" version = "2.0.0" dependencies = [ "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-primitives 2.0.0", - "substrate-serializer 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "sp-serializer 2.0.0", ] [[package]] name = "node-rpc" version = "2.0.0" dependencies = [ - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 2.0.0", - "sr-primitives 2.0.0", - "srml-contracts-rpc 2.0.0", - "srml-system-rpc 2.0.0", - "substrate-client 2.0.0", - "substrate-transaction-pool 2.0.0", + "node-runtime 2.0.0", + "pallet-contracts-rpc 2.0.0", + "pallet-transaction-payment-rpc 2.0.0", + "sc-client 2.0.0", + "sp-api 2.0.0", + "sp-runtime 2.0.0", + "sp-transaction-pool 2.0.0", + "substrate-frame-rpc-system 2.0.0", ] [[package]] name = "node-rpc-client" version = "2.0.0" dependencies = [ - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core-client 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 2.0.0", - "substrate-rpc 2.0.0", + "sc-rpc 2.0.0", ] [[package]] name = "node-runtime" version = "2.0.0" dependencies = [ + "frame-executive 2.0.0", + "frame-support 2.0.0", + "frame-system 2.0.0", + "frame-system-rpc-runtime-api 2.0.0", "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 2.0.0", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-authority-discovery 2.0.0", + "pallet-authorship 2.0.0", + "pallet-babe 2.0.0", + "pallet-balances 2.0.0", + "pallet-collective 2.0.0", + "pallet-contracts 2.0.0", + "pallet-contracts-rpc-runtime-api 2.0.0", + "pallet-democracy 2.0.0", + "pallet-elections-phragmen 2.0.0", + "pallet-finality-tracker 2.0.0", + "pallet-grandpa 2.0.0", + "pallet-im-online 2.0.0", + "pallet-indices 2.0.0", + "pallet-membership 2.0.0", + "pallet-nicks 2.0.0", + "pallet-offences 2.0.0", + "pallet-randomness-collective-flip 2.0.0", + "pallet-session 2.0.0", + "pallet-staking 2.0.0", + "pallet-staking-reward-curve 2.0.0", + "pallet-sudo 2.0.0", + "pallet-timestamp 2.0.0", + "pallet-transaction-payment 2.0.0", + "pallet-transaction-payment-rpc-runtime-api 2.0.0", + "pallet-treasury 2.0.0", + "pallet-utility 2.0.0", + "parity-scale-codec 1.1.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.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-staking-primitives 2.0.0", - "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-authority-discovery 0.1.0", - "srml-authorship 0.1.0", - "srml-babe 2.0.0", - "srml-balances 2.0.0", - "srml-collective 2.0.0", - "srml-contracts 2.0.0", - "srml-contracts-rpc-runtime-api 2.0.0", - "srml-democracy 2.0.0", - "srml-elections-phragmen 2.0.0", - "srml-executive 2.0.0", - "srml-finality-tracker 2.0.0", - "srml-grandpa 2.0.0", - "srml-im-online 0.1.0", - "srml-indices 2.0.0", - "srml-membership 2.0.0", - "srml-nicks 2.0.0", - "srml-offences 1.0.0", - "srml-randomness-collective-flip 2.0.0", - "srml-session 2.0.0", - "srml-staking 2.0.0", - "srml-staking-reward-curve 2.0.0", - "srml-sudo 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-system-rpc-runtime-api 2.0.0", - "srml-timestamp 2.0.0", - "srml-transaction-payment 2.0.0", - "srml-treasury 2.0.0", - "srml-utility 2.0.0", - "substrate-authority-discovery-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-keyring 2.0.0", - "substrate-offchain-primitives 2.0.0", - "substrate-primitives 2.0.0", - "substrate-session 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-authority-discovery 2.0.0", + "sp-block-builder 2.0.0", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-keyring 2.0.0", + "sp-offchain 2.0.0", + "sp-runtime 2.0.0", + "sp-session 2.0.0", + "sp-staking 2.0.0", + "sp-std 2.0.0", + "sp-transaction-pool 2.0.0", + "sp-version 2.0.0", "substrate-wasm-builder-runner 1.0.4", ] @@ -2559,29 +3219,30 @@ name = "node-template" version = "2.0.0" dependencies = [ "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "node-template-runtime 2.0.0", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "substrate-basic-authorship 2.0.0", - "substrate-cli 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-aura 2.0.0", - "substrate-consensus-aura-primitives 2.0.0", - "substrate-executor 2.0.0", - "substrate-finality-grandpa 2.0.0", - "substrate-finality-grandpa-primitives 2.0.0", - "substrate-inherents 2.0.0", - "substrate-network 2.0.0", - "substrate-primitives 2.0.0", - "substrate-service 2.0.0", - "substrate-transaction-pool 2.0.0", + "sc-basic-authority 2.0.0", + "sc-cli 2.0.0", + "sc-client 2.0.0", + "sc-consensus-aura 0.8.0", + "sc-executor 2.0.0", + "sc-finality-grandpa 2.0.0", + "sc-network 0.8.0", + "sc-service 2.0.0", + "sc-transaction-pool 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-aura 0.8.0", + "sp-core 2.0.0", + "sp-finality-grandpa 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-transaction-pool 2.0.0", + "substrate-build-script-utils 2.0.0", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2591,61 +3252,82 @@ dependencies = [ name = "node-template-runtime" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-executive 2.0.0", + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-aura 2.0.0", + "pallet-balances 2.0.0", + "pallet-grandpa 2.0.0", + "pallet-indices 2.0.0", + "pallet-randomness-collective-flip 2.0.0", + "pallet-sudo 2.0.0", + "pallet-timestamp 2.0.0", + "pallet-transaction-payment 2.0.0", + "parity-scale-codec 1.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.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-aura 2.0.0", - "srml-balances 2.0.0", - "srml-executive 2.0.0", - "srml-grandpa 2.0.0", - "srml-indices 2.0.0", - "srml-randomness-collective-flip 2.0.0", - "srml-sudo 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "srml-transaction-payment 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-aura-primitives 2.0.0", - "substrate-offchain-primitives 2.0.0", - "substrate-primitives 2.0.0", - "substrate-session 2.0.0", - "substrate-wasm-builder-runner 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-block-builder 2.0.0", + "sp-consensus-aura 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-offchain 2.0.0", + "sp-runtime 2.0.0", + "sp-session 2.0.0", + "sp-std 2.0.0", + "sp-transaction-pool 2.0.0", + "sp-version 2.0.0", + "substrate-wasm-builder-runner 1.0.4", ] [[package]] name = "node-testing" version = "2.0.0" dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", "node-executor 2.0.0", "node-primitives 2.0.0", "node-runtime 2.0.0", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "srml-balances 2.0.0", - "srml-contracts 2.0.0", - "srml-grandpa 2.0.0", - "srml-indices 2.0.0", - "srml-session 2.0.0", - "srml-staking 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "srml-transaction-payment 2.0.0", - "srml-treasury 2.0.0", - "substrate-client 2.0.0", - "substrate-executor 2.0.0", - "substrate-keyring 2.0.0", - "substrate-primitives 2.0.0", + "pallet-balances 2.0.0", + "pallet-contracts 2.0.0", + "pallet-grandpa 2.0.0", + "pallet-indices 2.0.0", + "pallet-session 2.0.0", + "pallet-staking 2.0.0", + "pallet-timestamp 2.0.0", + "pallet-transaction-payment 2.0.0", + "pallet-treasury 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-executor 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", "substrate-test-client 2.0.0", "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "node-transaction-factory" +version = "2.0.0" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-cli 2.0.0", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-service 2.0.0", + "sp-api 2.0.0", + "sp-block-builder 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2670,9 +3352,9 @@ name = "num-bigint" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2680,8 +3362,8 @@ name = "num-integer" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2689,26 +3371,27 @@ name = "num-rational" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num_cpus" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2733,6 +3416,11 @@ name = "once_cell" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "once_cell" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "opaque-debug" version = "0.2.3" @@ -2740,15 +3428,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.25" +version = "0.10.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2758,14 +3446,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.51" +version = "0.9.53" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2785,201 +3473,848 @@ dependencies = [ ] [[package]] -name = "parity-bytes" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" +name = "pallet-assets" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] [[package]] -name = "parity-multiaddr" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-aura" +version = "2.0.0" dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-session 2.0.0", + "pallet-timestamp 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-application-crypto 2.0.0", + "sp-consensus-aura 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", + "sp-timestamp 2.0.0", ] [[package]] -name = "parity-multihash" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-authority-discovery" +version = "2.0.0" dependencies = [ - "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-session 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-application-crypto 2.0.0", + "sp-authority-discovery 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-staking 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parity-scale-codec" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-authorship" +version = "2.0.0" dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-authorship 2.0.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parity-scale-codec-derive" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-babe" +version = "2.0.0" dependencies = [ - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-session 2.0.0", + "pallet-timestamp 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-staking 2.0.0", + "sp-std 2.0.0", + "sp-timestamp 2.0.0", + "sp-version 2.0.0", + "substrate-test-runtime 2.0.0", ] [[package]] -name = "parity-send-wrapper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-balances" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-transaction-payment 2.0.0", + "parity-scale-codec 1.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.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] [[package]] -name = "parity-util-mem" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-collective" +version = "2.0.0" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-balances 2.0.0", + "parity-scale-codec 1.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.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parity-wasm" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-contracts" +version = "2.0.0" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-balances 2.0.0", + "pallet-randomness-collective-flip 2.0.0", + "pallet-timestamp 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-sandbox 2.0.0", + "sp-std 2.0.0", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parity-wasm" -version = "0.40.3" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-contracts-rpc" +version = "2.0.0" +dependencies = [ + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-contracts-rpc-runtime-api 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-core 2.0.0", + "sp-rpc 2.0.0", + "sp-runtime 2.0.0", +] [[package]] -name = "parking_lot" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-contracts-rpc-runtime-api" +version = "2.0.0" 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)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parking_lot" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-democracy" +version = "2.0.0" 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)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.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.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parking_lot" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-elections" +version = "2.0.0" dependencies = [ - "lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-balances 2.0.0", + "parity-scale-codec 1.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.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-elections-phragmen" +version = "2.0.0" dependencies = [ - "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-phragmen 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", + "substrate-test-utils 2.0.0", ] [[package]] -name = "parking_lot_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-evm" +version = "2.0.0" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "evm 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "pallet-timestamp 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parking_lot_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-example" +version = "2.0.0" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parking_lot_core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-finality-tracker" +version = "2.0.0" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-finality-tracker 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-generic-asset" +version = "2.0.0" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "paste" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-grandpa" +version = "2.0.0" dependencies = [ - "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-finality-tracker 2.0.0", + "pallet-session 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-finality-grandpa 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-staking 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "paste-impl" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "pallet-identity" +version = "2.0.0" +dependencies = [ + "enumflags2 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-im-online" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-authorship 2.0.0", + "pallet-session 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-application-crypto 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-staking 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-indices" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "parity-scale-codec 1.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.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-membership" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-nicks" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-offences" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-staking 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-randomness-collective-flip" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "parity-scale-codec 1.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)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-scored-pool" +version = "2.0.0" dependencies = [ - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-session" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-timestamp 2.0.0", + "parity-scale-codec 1.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.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-application-crypto 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-staking 2.0.0", + "sp-std 2.0.0", + "sp-trie 2.0.0", +] + +[[package]] +name = "pallet-society" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-staking" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-authorship 2.0.0", + "pallet-balances 2.0.0", + "pallet-session 2.0.0", + "pallet-staking-reward-curve 2.0.0", + "pallet-timestamp 2.0.0", + "parity-scale-codec 1.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.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-keyring 2.0.0", + "sp-phragmen 2.0.0", + "sp-runtime 2.0.0", + "sp-staking 2.0.0", + "sp-std 2.0.0", + "substrate-test-utils 2.0.0", +] + +[[package]] +name = "pallet-staking-reward-curve" +version = "2.0.0" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pallet-sudo" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-timestamp" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", + "sp-timestamp 2.0.0", +] + +[[package]] +name = "pallet-transaction-payment" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "pallet-transaction-payment-rpc-runtime-api 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-transaction-payment-rpc" +version = "2.0.0" +dependencies = [ + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-transaction-payment-rpc-runtime-api 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-core 2.0.0", + "sp-rpc 2.0.0", + "sp-runtime 2.0.0", +] + +[[package]] +name = "pallet-transaction-payment-rpc-runtime-api" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-treasury" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "pallet-utility" +version = "2.0.0" +dependencies = [ + "frame-support 2.0.0", + "frame-system 2.0.0", + "pallet-balances 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "parity-bytes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "parity-multiaddr" +version = "0.5.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.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multiaddr" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multihash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multihash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-scale-codec" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-slice-cast 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec-derive 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-send-wrapper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "parity-util-mem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-util-mem" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-util-mem-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-util-mem-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-wasm" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-wasm" +version = "0.41.0" +source = "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" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (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 = "parking_lot" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.7.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.66 (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.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3012,12 +4347,35 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "petgraph" -version = "0.4.13" +name = "petgraph" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "pin-utils" @@ -3026,12 +4384,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pkg-config" -version = "0.3.16" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ppv-lite86" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3047,53 +4410,63 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "primitive-types" -version = "0.6.0" +name = "proc-macro-crate" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "proc-macro-crate" -version = "0.1.4" +name = "proc-macro-error" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "proc-macro-error" -version = "0.2.6" +name = "proc-macro-error-attr" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn-mid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-hack" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-nested" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.30" @@ -3127,7 +4500,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3143,7 +4516,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3165,19 +4538,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pwasm-utils" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "quick-error" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "quick-error" version = "1.2.2" @@ -3194,6 +4562,16 @@ dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quicksink" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.6.13" @@ -3215,7 +4593,7 @@ name = "rand" version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3225,31 +4603,19 @@ 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.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (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.8 (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.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (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.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3266,8 +4632,8 @@ name = "rand" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3278,7 +4644,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3287,7 +4653,7 @@ name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3309,7 +4675,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3341,7 +4707,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3353,9 +4719,10 @@ 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.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3364,7 +4731,7 @@ name = "rand_os" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3373,7 +4740,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3402,26 +4769,36 @@ dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "raw-cpuid" +version = "7.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rayon" -version = "1.2.0" +version = "1.2.1" 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-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3434,2287 +4811,2097 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ref_thread_local" -version = "0.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "regex" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.12 (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 = "regex-automata" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "remove_dir_all" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rhododendron" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ring" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rocksdb" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "librocksdb-sys 5.18.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rpassword" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.16" -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 = "rustls" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustversion" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rw-stream-sink" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ryu" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "safe-mix" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "safemem" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "same-file" -version = "1.0.5" -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" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "schnorrkel" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sct" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "security-framework-sys" +name = "redox_users" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "semver" -version = "0.6.0" +name = "regex" +version = "1.3.1" 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)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (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 = "semver" -version = "0.9.0" +name = "regex-automata" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "send_wrapper" -version = "0.2.0" +name = "regex-syntax" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "serde" -version = "1.0.101" +name = "region" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "serde_derive" -version = "1.0.101" +name = "remove_dir_all" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "serde_json" -version = "1.0.41" +name = "ring" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sha-1" -version = "0.8.1" +name = "rlp" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sha2" -version = "0.6.0" +name = "rocksdb" +version = "0.13.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)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "librocksdb-sys 6.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sha2" -version = "0.8.0" +name = "rpassword" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sha3" -version = "0.8.2" +name = "rust-argon2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "shell32-sys" -version = "0.1.2" +name = "rustc-demangle" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "slab" -version = "0.4.2" +name = "rustc-hex" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "slog" -version = "2.5.2" +name = "rustc_version" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "slog-async" -version = "2.3.0" -source = "git+https://github.com/paritytech/slog-async#107848e7ded5e80dc43f6296c2b96039eb92c0a5" +name = "rustls" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (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)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "slog-json" -version = "2.3.0" +name = "rustversion" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", - "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "slog-scope" -version = "4.1.2" +name = "rw-stream-sink" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "slog_derive" -version = "0.1.1" +name = "ryu" +version = "1.0.2" +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 = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "smallvec" -version = "0.6.10" +name = "safemem" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "snow" -version = "0.5.2" +name = "same-file" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (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 = "soketto" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "sc-authority-discovery" +version = "2.0.0" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost-build 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client-api 2.0.0", + "sc-keystore 2.0.0", + "sc-network 0.8.0", + "sc-peerset 2.0.0", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-authority-discovery 2.0.0", + "sp-blockchain 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "substrate-test-runtime-client 2.0.0", ] [[package]] -name = "sourcefile" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "sc-basic-authority" +version = "2.0.0" +dependencies = [ + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-block-builder 2.0.0", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-telemetry 2.0.0", + "sc-transaction-pool 2.0.0", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-transaction-pool 2.0.0", + "substrate-test-runtime-client 2.0.0", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "sr-api-macros" +name = "sc-block-builder" version = "2.0.0" dependencies = [ - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-version 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-primitives 2.0.0", - "substrate-state-machine 2.0.0", - "substrate-test-runtime-client 2.0.0", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client-api 2.0.0", + "sp-api 2.0.0", + "sp-block-builder 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", ] [[package]] -name = "sr-arithmetic" +name = "sc-chain-spec" version = "2.0.0" dependencies = [ - "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-debug-derive 2.0.0", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-chain-spec-derive 2.0.0", + "sc-network 0.8.0", + "sc-telemetry 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-runtime 2.0.0", ] [[package]] -name = "sr-io" +name = "sc-chain-spec-derive" version = "2.0.0" dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-externalities 2.0.0", - "substrate-primitives 2.0.0", - "substrate-state-machine 2.0.0", - "substrate-trie 2.0.0", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sr-primitives" +name = "sc-cli" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-arithmetic 2.0.0", - "sr-io 2.0.0", - "sr-std 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-offchain 2.0.0", - "substrate-primitives 2.0.0", + "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client-api 2.0.0", + "sc-network 0.8.0", + "sc-service 2.0.0", + "sc-telemetry 2.0.0", + "sc-tracing 2.0.0", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-blockchain 2.0.0", + "sp-core 2.0.0", + "sp-keyring 2.0.0", + "sp-panic-handler 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "structopt 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.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.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sr-sandbox" +name = "sc-client" version = "2.0.0" dependencies = [ - "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-primitives 2.0.0", - "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-block-builder 2.0.0", + "sc-client-api 2.0.0", + "sc-executor 2.0.0", + "sc-telemetry 2.0.0", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-externalities 2.0.0", + "sp-inherents 2.0.0", + "sp-keyring 2.0.0", + "sp-panic-handler 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "sp-std 2.0.0", + "sp-trie 2.0.0", + "sp-version 2.0.0", + "substrate-test-runtime-client 2.0.0", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sr-staking-primitives" +name = "sc-client-api" +version = "2.0.0" +dependencies = [ + "derive_more 0.99.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.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-executor 2.0.0", + "sc-telemetry 2.0.0", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-externalities 2.0.0", + "sp-inherents 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "sp-std 2.0.0", + "sp-test-primitives 2.0.0", + "sp-transaction-pool 2.0.0", + "sp-trie 2.0.0", + "sp-version 2.0.0", +] + +[[package]] +name = "sc-client-db" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-rocksdb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-util-mem 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-executor 2.0.0", + "sc-state-db 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "sp-trie 2.0.0", + "substrate-test-runtime-client 2.0.0", ] [[package]] -name = "sr-std" -version = "2.0.0" +name = "sc-consensus-aura" +version = "0.8.0" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-consensus-slots 0.8.0", + "sc-executor 2.0.0", + "sc-keystore 2.0.0", + "sc-network 0.8.0", + "sc-network-test 2.0.0", + "sc-service 2.0.0", + "sc-telemetry 2.0.0", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-block-builder 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-aura 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-timestamp 2.0.0", + "sp-version 2.0.0", + "substrate-test-runtime-client 2.0.0", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sr-version" -version = "2.0.0" +name = "sc-consensus-babe" +version = "0.8.0" dependencies = [ - "impl-serde 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fork-tree 2.0.0", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-block-builder 2.0.0", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-consensus-slots 0.8.0", + "sc-consensus-uncles 0.8.0", + "sc-executor 2.0.0", + "sc-keystore 2.0.0", + "sc-network 0.8.0", + "sc-network-test 2.0.0", + "sc-service 2.0.0", + "sc-telemetry 2.0.0", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-block-builder 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-timestamp 2.0.0", + "sp-version 2.0.0", + "substrate-test-runtime-client 2.0.0", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-assets" -version = "2.0.0" +name = "sc-consensus-pow" +version = "0.8.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client-api 2.0.0", + "sp-api 2.0.0", + "sp-block-builder 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-pow 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-timestamp 2.0.0", ] [[package]] -name = "srml-aura" -version = "2.0.0" +name = "sc-consensus-slots" +version = "0.8.0" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-session 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-consensus-aura-primitives 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", -] - -[[package]] -name = "srml-authority-discovery" -version = "0.1.0" -dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-staking-primitives 2.0.0", - "sr-std 2.0.0", - "srml-session 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-primitives 2.0.0", + "sc-client-api 2.0.0", + "sc-telemetry 2.0.0", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "substrate-test-runtime-client 2.0.0", ] [[package]] -name = "srml-authorship" -version = "0.1.0" +name = "sc-consensus-uncles" +version = "0.8.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client-api 2.0.0", + "sp-authorship 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", ] [[package]] -name = "srml-babe" +name = "sc-executor" version = "2.0.0" dependencies = [ + "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-staking-primitives 2.0.0", - "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-session 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", + "sc-executor-common 2.0.0", + "sc-executor-wasmi 2.0.0", + "sc-executor-wasmtime 2.0.0", + "sc-runtime-test 2.0.0", + "sp-core 2.0.0", + "sp-externalities 2.0.0", + "sp-io 2.0.0", + "sp-panic-handler 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-serializer 2.0.0", + "sp-state-machine 2.0.0", + "sp-trie 2.0.0", + "sp-version 2.0.0", + "sp-wasm-interface 2.0.0", "substrate-test-runtime 2.0.0", + "test-case 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-balances" +name = "sc-executor-common" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-transaction-payment 2.0.0", - "substrate-keyring 2.0.0", - "substrate-primitives 2.0.0", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-serializer 2.0.0", + "sp-wasm-interface 2.0.0", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-collective" +name = "sc-executor-wasmi" version = "2.0.0" dependencies = [ - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-executor-common 2.0.0", + "sp-core 2.0.0", + "sp-externalities 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-wasm-interface 2.0.0", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-contracts" +name = "sc-executor-wasmtime" version = "2.0.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-sandbox 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-randomness-collective-flip 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "substrate-primitives 2.0.0", - "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-executor-common 2.0.0", + "sp-core 2.0.0", + "sp-externalities 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-wasm-interface 2.0.0", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-environ 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-jit 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-runtime 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-contracts-rpc" +name = "sc-finality-grandpa" version = "2.0.0" dependencies = [ - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core-client 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-derive 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "srml-contracts-rpc-runtime-api 2.0.0", - "substrate-client 2.0.0", - "substrate-primitives 2.0.0", - "substrate-rpc-primitives 2.0.0", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "finality-grandpa 0.11.0 (git+https://github.com/expenses/finality-grandpa?branch=future)", + "fork-tree 2.0.0", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-keystore 2.0.0", + "sc-network 0.8.0", + "sc-network-gossip 2.0.0", + "sc-network-test 2.0.0", + "sc-telemetry 2.0.0", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-finality-grandpa 2.0.0", + "sp-finality-tracker 2.0.0", + "sp-inherents 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "substrate-test-runtime-client 2.0.0", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-contracts-rpc-runtime-api" +name = "sc-keystore" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "substrate-client 2.0.0", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-application-crypto 2.0.0", + "sp-core 2.0.0", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-democracy" -version = "2.0.0" +name = "sc-network" +version = "0.8.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fork-tree 2.0.0", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures_codec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lru 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-block-builder 2.0.0", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-peerset 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "slog_derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-arithmetic 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-test-primitives 2.0.0", + "substrate-test-client 2.0.0", + "substrate-test-runtime-client 2.0.0", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-elections" +name = "sc-network-gossip" version = "2.0.0" dependencies = [ - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lru 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-network 0.8.0", + "sp-runtime 2.0.0", ] [[package]] -name = "srml-elections-phragmen" +name = "sc-network-test" version = "2.0.0" dependencies = [ - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-phragmen 2.0.0", - "substrate-primitives 2.0.0", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-block-builder 2.0.0", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-network 0.8.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "substrate-test-runtime 2.0.0", + "substrate-test-runtime-client 2.0.0", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-example" +name = "sc-offchain" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client-api 2.0.0", + "sc-client-db 2.0.0", + "sc-keystore 2.0.0", + "sc-network 0.8.0", + "sc-transaction-pool 2.0.0", + "sp-api 2.0.0", + "sp-core 2.0.0", + "sp-offchain 2.0.0", + "sp-runtime 2.0.0", + "sp-transaction-pool 2.0.0", + "substrate-test-runtime-client 2.0.0", + "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-executive" +name = "sc-peerset" version = "2.0.0" dependencies = [ - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-indices 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-transaction-payment 2.0.0", - "substrate-primitives 2.0.0", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-finality-tracker" +name = "sc-rpc" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", + "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-executor 2.0.0", + "sc-keystore 2.0.0", + "sc-network 0.8.0", + "sc-rpc-api 2.0.0", + "sc-transaction-pool 2.0.0", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-rpc 2.0.0", + "sp-runtime 2.0.0", + "sp-session 2.0.0", + "sp-state-machine 2.0.0", + "sp-transaction-pool 2.0.0", + "sp-version 2.0.0", + "substrate-test-runtime-client 2.0.0", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-generic-asset" +name = "sc-rpc-api" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-rpc 2.0.0", + "sp-transaction-pool 2.0.0", + "sp-version 2.0.0", ] [[package]] -name = "srml-grandpa" +name = "sc-rpc-server" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-staking-primitives 2.0.0", - "sr-std 2.0.0", - "srml-finality-tracker 2.0.0", - "srml-session 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-finality-grandpa-primitives 2.0.0", - "substrate-primitives 2.0.0", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-http-server 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-ws-server 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0", ] [[package]] -name = "srml-im-online" -version = "0.1.0" +name = "sc-runtime-test" +version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-staking-primitives 2.0.0", - "sr-std 2.0.0", - "srml-session 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-offchain 2.0.0", - "substrate-primitives 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-sandbox 2.0.0", + "sp-std 2.0.0", + "substrate-wasm-builder-runner 1.0.4", ] [[package]] -name = "srml-indices" +name = "sc-service" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-keyring 2.0.0", - "substrate-primitives 2.0.0", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "grafana-data-source 2.0.0", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-chain-spec 2.0.0", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-client-db 2.0.0", + "sc-executor 2.0.0", + "sc-finality-grandpa 2.0.0", + "sc-keystore 2.0.0", + "sc-network 0.8.0", + "sc-offchain 2.0.0", + "sc-rpc 2.0.0", + "sc-rpc-server 2.0.0", + "sc-telemetry 2.0.0", + "sc-tracing 2.0.0", + "sc-transaction-pool 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-finality-grandpa 2.0.0", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-session 2.0.0", + "sp-transaction-pool 2.0.0", + "substrate-test-runtime-client 2.0.0", + "sysinfo 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", + "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-membership" +name = "sc-service-test" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "env_logger 0.7.1 (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.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-network 0.8.0", + "sc-service 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "sp-transaction-pool 2.0.0", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-metadata" +name = "sc-state-db" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-primitives 2.0.0", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", ] [[package]] -name = "srml-nicks" +name = "sc-telemetry" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (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.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "take_mut 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 = "srml-offences" -version = "1.0.0" +name = "sc-tracing" +version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-staking-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "grafana-data-source 2.0.0", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-telemetry 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-randomness-collective-flip" +name = "sc-transaction-graph" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "sp-transaction-pool 2.0.0", + "substrate-test-runtime 2.0.0", ] [[package]] -name = "srml-scored-pool" -version = "1.0.0" +name = "sc-transaction-pool" +version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client-api 2.0.0", + "sc-transaction-graph 2.0.0", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-core 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-transaction-pool 2.0.0", + "substrate-test-runtime-client 2.0.0", ] [[package]] -name = "srml-session" -version = "2.0.0" +name = "schannel" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-staking-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-primitives 2.0.0", - "substrate-trie 2.0.0", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-staking" -version = "2.0.0" +name = "schnorrkel" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-staking-primitives 2.0.0", - "sr-std 2.0.0", - "srml-authorship 0.1.0", - "srml-balances 2.0.0", - "srml-session 2.0.0", - "srml-staking-reward-curve 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-timestamp 2.0.0", - "substrate-keyring 2.0.0", - "substrate-phragmen 2.0.0", - "substrate-primitives 2.0.0", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.3.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.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-staking-reward-curve" -version = "2.0.0" +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scroll" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll_derive" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-sudo" -version = "2.0.0" +name = "sct" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-support" -version = "2.0.0" +name = "security-framework" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-metadata 2.0.0", - "srml-support-procedural 2.0.0", - "srml-system 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-support-procedural" -version = "2.0.0" +name = "security-framework-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-api-macros 2.0.0", - "srml-support-procedural-tools 2.0.0", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-support-procedural-tools" -version = "2.0.0" +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "srml-support-procedural-tools-derive 2.0.0", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-support-procedural-tools-derive" -version = "2.0.0" +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-support-test" -version = "2.0.0" +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "send_wrapper" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "send_wrapper" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "srml-support 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", - "trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-system" -version = "2.0.0" +name = "serde_derive" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-support 2.0.0", - "substrate-primitives 2.0.0", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-system-rpc" -version = "2.0.0" +name = "serde_json" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core-client 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-derive 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "srml-system-rpc-runtime-api 2.0.0", - "substrate-client 2.0.0", - "substrate-primitives 2.0.0", - "substrate-test-runtime-client 2.0.0", - "substrate-transaction-pool 2.0.0", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-system-rpc-runtime-api" -version = "2.0.0" +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-client 2.0.0", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-timestamp" -version = "2.0.0" -dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", -] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "srml-transaction-payment" -version = "2.0.0" +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-treasury" -version = "2.0.0" +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "srml-utility" -version = "2.0.0" +name = "shell32-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-balances 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-primitives 2.0.0", + "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 = "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" +name = "shlex" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "static_slice" -version = "0.0.3" +name = "slab" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "stream-cipher" -version = "0.3.2" +name = "slog" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "string" -version = "0.2.1" +name = "slog-json" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "strsim" -version = "0.8.0" +name = "slog-scope" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "structopt" -version = "0.3.3" +name = "slog_derive" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "structopt-derive" -version = "0.3.3" +name = "smallvec" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "strum" -version = "0.15.0" +name = "smallvec" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "strum_macros" -version = "0.15.0" +name = "snow" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "subkey" -version = "2.0.0" +name = "soketto" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "node-primitives 2.0.0", - "node-runtime 2.0.0", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "srml-balances 2.0.0", - "srml-system 2.0.0", - "srml-transaction-payment 2.0.0", - "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-primitives 2.0.0", - "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate" +name = "sourcefile" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sp-api" version = "2.0.0" dependencies = [ - "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "node-cli 2.0.0", - "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api-proc-macro 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "sp-std 2.0.0", + "sp-test-primitives 2.0.0", + "sp-version 2.0.0", ] [[package]] -name = "substrate-application-crypto" +name = "sp-api-proc-macro" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "substrate-primitives 2.0.0", - "substrate-test-runtime-client 2.0.0", + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-authority-discovery" +name = "sp-api-test" version = "2.0.0" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-build 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-authority-discovery-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-network 2.0.0", - "substrate-peerset 2.0.0", - "substrate-primitives 2.0.0", + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "sp-version 2.0.0", "substrate-test-runtime-client 2.0.0", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "trybuild 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-authority-discovery-primitives" +name = "sp-application-crypto" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "substrate-client 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-basic-authorship" +name = "sp-application-crypto-test" version = "2.0.0" dependencies = [ - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", - "substrate-telemetry 2.0.0", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", "substrate-test-runtime-client 2.0.0", - "substrate-transaction-pool 2.0.0", ] [[package]] -name = "substrate-bip39" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "sp-arithmetic" +version = "2.0.0" dependencies = [ - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-chain-spec" +name = "sp-authority-discovery" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-chain-spec-derive 2.0.0", - "substrate-network 2.0.0", - "substrate-primitives 2.0.0", - "substrate-telemetry 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-chain-spec-derive" +name = "sp-authorship" version = "2.0.0" dependencies = [ - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-cli" +name = "sp-block-builder" version = "2.0.0" dependencies = [ - "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-client 2.0.0", - "substrate-header-metadata 2.0.0", - "substrate-keyring 2.0.0", - "substrate-network 2.0.0", - "substrate-panic-handler 2.0.0", - "substrate-primitives 2.0.0", - "substrate-service 2.0.0", - "substrate-state-machine 2.0.0", - "substrate-telemetry 2.0.0", - "tempdir 0.3.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.22 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-client" +name = "sp-blockchain" version = "2.0.0" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lru 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-api-macros 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "sr-version 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-executor 2.0.0", - "substrate-header-metadata 2.0.0", - "substrate-inherents 2.0.0", - "substrate-keyring 2.0.0", - "substrate-panic-handler 2.0.0", - "substrate-primitives 2.0.0", - "substrate-state-machine 2.0.0", - "substrate-telemetry 2.0.0", - "substrate-test-runtime-client 2.0.0", - "substrate-trie 2.0.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-block-builder 2.0.0", + "sp-consensus 0.8.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", ] [[package]] -name = "substrate-client-db" -version = "2.0.0" +name = "sp-consensus" +version = "0.8.0" dependencies = [ - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-executor 2.0.0", - "substrate-header-metadata 2.0.0", - "substrate-keyring 2.0.0", - "substrate-primitives 2.0.0", - "substrate-state-db 2.0.0", - "substrate-state-machine 2.0.0", - "substrate-test-runtime-client 2.0.0", - "substrate-trie 2.0.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", + "sp-std 2.0.0", + "sp-test-primitives 2.0.0", + "sp-version 2.0.0", ] [[package]] -name = "substrate-consensus-aura" -version = "2.0.0" +name = "sp-consensus-aura" +version = "0.8.0" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-version 2.0.0", - "srml-aura 2.0.0", - "srml-support 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-consensus-slots 2.0.0", - "substrate-executor 2.0.0", - "substrate-inherents 2.0.0", - "substrate-keyring 2.0.0", - "substrate-keystore 2.0.0", - "substrate-network 2.0.0", - "substrate-primitives 2.0.0", - "substrate-service 2.0.0", - "substrate-telemetry 2.0.0", - "substrate-test-runtime-client 2.0.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", + "sp-timestamp 2.0.0", ] [[package]] -name = "substrate-consensus-aura-primitives" -version = "2.0.0" +name = "sp-consensus-babe" +version = "0.8.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-client 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-consensus 0.8.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", + "sp-timestamp 2.0.0", +] + +[[package]] +name = "sp-consensus-pow" +version = "0.8.0" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-consensus-babe" +name = "sp-core" version = "2.0.0" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fork-tree 2.0.0", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "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.2 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-version 2.0.0", - "srml-babe 2.0.0", - "srml-support 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-consensus-slots 2.0.0", - "substrate-consensus-uncles 2.0.0", - "substrate-executor 2.0.0", - "substrate-header-metadata 2.0.0", - "substrate-inherents 2.0.0", - "substrate-keyring 2.0.0", - "substrate-keystore 2.0.0", - "substrate-network 2.0.0", - "substrate-primitives 2.0.0", - "substrate-service 2.0.0", - "substrate-telemetry 2.0.0", - "substrate-test-runtime-client 2.0.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 2.0.0", + "sp-externalities 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-serializer 2.0.0", + "sp-std 2.0.0", + "sp-storage 2.0.0", + "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-consensus-babe-primitives" +name = "sp-debug-derive" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-slots 2.0.0", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-consensus-common" +name = "sp-externalities" version = "2.0.0" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "sr-version 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", - "substrate-test-runtime-client 2.0.0", + "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-std 2.0.0", + "sp-storage 2.0.0", ] [[package]] -name = "substrate-consensus-pow" +name = "sp-finality-grandpa" version = "2.0.0" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "srml-timestamp 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-consensus-pow-primitives 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-consensus-pow-primitives" +name = "sp-finality-tracker" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "substrate-client 2.0.0", - "substrate-primitives 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-inherents 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-consensus-rhd" +name = "sp-inherents" version = "2.0.0" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rhododendron 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-version 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-keyring 2.0.0", - "substrate-primitives 2.0.0", - "substrate-transaction-pool 2.0.0", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-consensus-slots" +name = "sp-io" version = "2.0.0" dependencies = [ - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", - "substrate-telemetry 2.0.0", - "substrate-test-runtime-client 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-externalities 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-state-machine 2.0.0", + "sp-std 2.0.0", + "sp-trie 2.0.0", ] [[package]] -name = "substrate-consensus-uncles" +name = "sp-keyring" version = "2.0.0" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "srml-authorship 0.1.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "strum 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-debug-derive" +name = "sp-offchain" version = "2.0.0" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-runtime 2.0.0", ] [[package]] -name = "substrate-executor" +name = "sp-panic-handler" version = "2.0.0" dependencies = [ - "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-version 2.0.0", - "substrate-client 2.0.0", - "substrate-externalities 2.0.0", - "substrate-offchain 2.0.0", - "substrate-panic-handler 2.0.0", - "substrate-primitives 2.0.0", - "substrate-runtime-test 2.0.0", - "substrate-serializer 2.0.0", - "substrate-state-machine 2.0.0", - "substrate-trie 2.0.0", - "substrate-wasm-interface 2.0.0", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-externalities" +name = "sp-phragmen" version = "2.0.0" dependencies = [ - "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-primitives-storage 2.0.0", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-io 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", + "substrate-test-utils 2.0.0", ] [[package]] -name = "substrate-finality-grandpa" +name = "sp-rpc" version = "2.0.0" dependencies = [ - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "finality-grandpa 0.9.1 (git+https://github.com/paritytech/finality-grandpa)", - "fork-tree 2.0.0", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", +] + +[[package]] +name = "sp-runtime" +version = "2.0.0" +dependencies = [ + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "srml-finality-tracker 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-finality-grandpa-primitives 2.0.0", - "substrate-header-metadata 2.0.0", - "substrate-inherents 2.0.0", - "substrate-keyring 2.0.0", - "substrate-keystore 2.0.0", - "substrate-network 2.0.0", - "substrate-primitives 2.0.0", - "substrate-telemetry 2.0.0", - "substrate-test-runtime-client 2.0.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-application-crypto 2.0.0", + "sp-arithmetic 2.0.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-std 2.0.0", +] + +[[package]] +name = "sp-runtime-interface" +version = "2.0.0" +dependencies = [ + "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-externalities 2.0.0", + "sp-io 2.0.0", + "sp-runtime-interface-proc-macro 2.0.0", + "sp-runtime-interface-test-wasm 2.0.0", + "sp-state-machine 2.0.0", + "sp-std 2.0.0", + "sp-wasm-interface 2.0.0", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trybuild 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "2.0.0" +dependencies = [ + "Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-finality-grandpa-primitives" +name = "sp-runtime-interface-test" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-client 2.0.0", + "sc-executor 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-runtime-interface-test-wasm 2.0.0", + "sp-state-machine 2.0.0", ] [[package]] -name = "substrate-header-metadata" +name = "sp-runtime-interface-test-wasm" version = "2.0.0" dependencies = [ - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-std 2.0.0", + "substrate-wasm-builder-runner 1.0.4", ] [[package]] -name = "substrate-inherents" +name = "sp-sandbox" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", + "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-io 2.0.0", + "sp-std 2.0.0", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-keyring" +name = "sp-serializer" version = "2.0.0" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-primitives 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-keystore" +name = "sp-session" version = "2.0.0" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-application-crypto 2.0.0", - "substrate-primitives 2.0.0", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-network" +name = "sp-staking" version = "2.0.0" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fork-tree 2.0.0", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-header-metadata 2.0.0", - "substrate-keyring 2.0.0", - "substrate-peerset 2.0.0", - "substrate-primitives 2.0.0", - "substrate-test-client 2.0.0", - "substrate-test-runtime 2.0.0", - "substrate-test-runtime-client 2.0.0", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-offchain" +name = "sp-state-machine" version = "2.0.0" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-client-db 2.0.0", - "substrate-keystore 2.0.0", - "substrate-network 2.0.0", - "substrate-offchain-primitives 2.0.0", - "substrate-primitives 2.0.0", - "substrate-test-runtime-client 2.0.0", - "substrate-transaction-pool 2.0.0", - "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-externalities 2.0.0", + "sp-panic-handler 2.0.0", + "sp-trie 2.0.0", + "trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-offchain-primitives" +name = "sp-std" +version = "2.0.0" + +[[package]] +name = "sp-storage" version = "2.0.0" dependencies = [ - "sr-primitives 2.0.0", - "substrate-client 2.0.0", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-panic-handler" +name = "sp-test-primitives" version = "2.0.0" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-application-crypto 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", ] [[package]] -name = "substrate-peerset" +name = "sp-timestamp" version = "2.0.0" dependencies = [ - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-inherents 2.0.0", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-phragmen" +name = "sp-transaction-pool" version = "2.0.0" dependencies = [ - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-runtime 2.0.0", ] [[package]] -name = "substrate-primitives" +name = "sp-trie" version = "2.0.0" dependencies = [ - "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-debug-derive 2.0.0", - "substrate-externalities 2.0.0", - "substrate-primitives-storage 2.0.0", - "substrate-serializer 2.0.0", - "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0", + "sp-std 2.0.0", + "trie-bench 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-primitives-storage" +name = "sp-version" version = "2.0.0" dependencies = [ - "impl-serde 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-debug-derive 2.0.0", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "substrate-rpc" +name = "sp-wasm-interface" version = "2.0.0" dependencies = [ - "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-version 2.0.0", - "substrate-client 2.0.0", - "substrate-executor 2.0.0", - "substrate-keystore 2.0.0", - "substrate-network 2.0.0", - "substrate-primitives 2.0.0", - "substrate-rpc-api 2.0.0", - "substrate-rpc-primitives 2.0.0", - "substrate-session 2.0.0", - "substrate-state-machine 2.0.0", - "substrate-test-runtime-client 2.0.0", - "substrate-transaction-pool 2.0.0", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-rpc-api" -version = "2.0.0" +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stream-cipher" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core-client 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-derive 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-version 2.0.0", - "substrate-primitives 2.0.0", - "substrate-rpc-primitives 2.0.0", - "substrate-transaction-graph 2.0.0", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-rpc-primitives" -version = "2.0.0" +name = "string" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-primitives 2.0.0", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-rpc-servers" -version = "2.0.0" +name = "string-interner" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-ws-server 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-runtime-test" -version = "2.0.0" +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-sandbox 2.0.0", - "sr-std 2.0.0", - "substrate-primitives 2.0.0", - "substrate-wasm-builder-runner 1.0.4", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-serializer" -version = "2.0.0" +name = "structopt-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-service" -version = "2.0.0" +name = "strum" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "node-executor 2.0.0", - "node-primitives 2.0.0", - "node-runtime 2.0.0", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-authority-discovery 2.0.0", - "substrate-authority-discovery-primitives 2.0.0", - "substrate-chain-spec 2.0.0", - "substrate-client 2.0.0", - "substrate-client-db 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-executor 2.0.0", - "substrate-finality-grandpa 2.0.0", - "substrate-finality-grandpa-primitives 2.0.0", - "substrate-keystore 2.0.0", - "substrate-network 2.0.0", - "substrate-offchain 2.0.0", - "substrate-primitives 2.0.0", - "substrate-rpc 2.0.0", - "substrate-rpc-servers 2.0.0", - "substrate-session 2.0.0", - "substrate-telemetry 2.0.0", - "substrate-test-runtime-client 2.0.0", - "substrate-transaction-pool 2.0.0", - "sysinfo 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", - "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "strum_macros 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-service-test" -version = "2.0.0" +name = "strum_macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-network 2.0.0", - "substrate-primitives 2.0.0", - "substrate-service 2.0.0", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-session" +name = "subkey" version = "2.0.0" dependencies = [ - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "substrate-client 2.0.0", - "substrate-primitives 2.0.0", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-system 2.0.0", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "node-primitives 2.0.0", + "node-runtime 2.0.0", + "pallet-balances 2.0.0", + "pallet-transaction-payment 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-rpc 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-state-db" -version = "2.0.0" +name = "substrate-bip39" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-primitives 2.0.0", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-state-machine" +name = "substrate-build-script-utils" +version = "2.0.0" + +[[package]] +name = "substrate-frame-rpc-support" version = "2.0.0" dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-externalities 2.0.0", - "substrate-panic-handler 2.0.0", - "substrate-primitives 2.0.0", - "substrate-trie 2.0.0", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support 2.0.0", + "frame-system 2.0.0", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-client-transports 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-rpc-api 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-storage 2.0.0", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate-telemetry" +name = "substrate-frame-rpc-system" version = "2.0.0" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-system-rpc-runtime-api 2.0.0", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.3.0 (git+https://github.com/paritytech/slog-async)", - "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-transaction-pool 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", + "sp-transaction-pool 2.0.0", + "substrate-test-runtime-client 2.0.0", ] [[package]] name = "substrate-test-client" version = "2.0.0" dependencies = [ - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-client-db 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-executor 2.0.0", - "substrate-keyring 2.0.0", - "substrate-primitives 2.0.0", - "substrate-state-machine 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sc-client-db 2.0.0", + "sc-executor 2.0.0", + "sp-blockchain 2.0.0", + "sp-consensus 0.8.0", + "sp-core 2.0.0", + "sp-keyring 2.0.0", + "sp-runtime 2.0.0", + "sp-state-machine 2.0.0", ] [[package]] @@ -5722,109 +6909,72 @@ name = "substrate-test-runtime" version = "2.0.0" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-executive 2.0.0", + "frame-support 2.0.0", + "frame-system 2.0.0", + "frame-system-rpc-runtime-api 2.0.0", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-babe 2.0.0", - "srml-executive 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "srml-system-rpc-runtime-api 2.0.0", - "srml-timestamp 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-babe-primitives 2.0.0", - "substrate-executor 2.0.0", - "substrate-inherents 2.0.0", - "substrate-keyring 2.0.0", - "substrate-offchain-primitives 2.0.0", - "substrate-primitives 2.0.0", - "substrate-session 2.0.0", - "substrate-state-machine 2.0.0", + "memory-db 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-babe 2.0.0", + "pallet-timestamp 2.0.0", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client 2.0.0", + "sc-executor 2.0.0", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", + "sp-application-crypto 2.0.0", + "sp-block-builder 2.0.0", + "sp-consensus-aura 0.8.0", + "sp-consensus-babe 0.8.0", + "sp-core 2.0.0", + "sp-inherents 2.0.0", + "sp-io 2.0.0", + "sp-keyring 2.0.0", + "sp-offchain 2.0.0", + "sp-runtime 2.0.0", + "sp-runtime-interface 2.0.0", + "sp-session 2.0.0", + "sp-state-machine 2.0.0", + "sp-std 2.0.0", + "sp-transaction-pool 2.0.0", + "sp-trie 2.0.0", + "sp-version 2.0.0", "substrate-test-runtime-client 2.0.0", - "substrate-trie 2.0.0", "substrate-wasm-builder-runner 1.0.4", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-test-runtime-client" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-primitives 2.0.0", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-block-builder 2.0.0", + "sc-client 2.0.0", + "sc-client-api 2.0.0", + "sp-api 2.0.0", + "sp-blockchain 2.0.0", + "sp-core 2.0.0", + "sp-runtime 2.0.0", "substrate-test-client 2.0.0", "substrate-test-runtime 2.0.0", ] [[package]] -name = "substrate-transaction-graph" -version = "2.0.0" -dependencies = [ - "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-primitives 2.0.0", - "substrate-test-runtime 2.0.0", -] - -[[package]] -name = "substrate-transaction-pool" +name = "substrate-test-utils" version = "2.0.0" -dependencies = [ - "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-client 2.0.0", - "substrate-keyring 2.0.0", - "substrate-primitives 2.0.0", - "substrate-test-runtime-client 2.0.0", - "substrate-transaction-graph 2.0.0", -] - -[[package]] -name = "substrate-trie" -version = "2.0.0" -dependencies = [ - "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-primitives 2.0.0", - "trie-bench 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "substrate-wasm-builder" version = "1.0.8" dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "build-helper 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-gc-api 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5833,18 +6983,6 @@ dependencies = [ name = "substrate-wasm-builder-runner" version = "1.0.4" -[[package]] -name = "substrate-wasm-builder-runner" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "substrate-wasm-interface" -version = "2.0.0" -dependencies = [ - "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "subtle" version = "1.0.0" @@ -5852,7 +6990,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "subtle" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -5867,7 +7005,7 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.7" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5876,36 +7014,35 @@ dependencies = [ ] [[package]] -name = "synstructure" -version = "0.10.2" +name = "syn-mid" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sysinfo" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5915,18 +7052,14 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "target_info" -version = "0.1.0" +name = "target-lexicon" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] +name = "target_info" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "tempfile" @@ -5934,7 +7067,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5949,12 +7082,42 @@ dependencies = [ "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "test-case" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5970,7 +7133,7 @@ name = "threadpool" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5978,7 +7141,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6005,13 +7168,21 @@ dependencies = [ "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-keccak" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tinytemplate" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6021,22 +7192,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.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-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (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.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-buf" version = "0.1.1" @@ -6063,27 +7245,26 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tokio-dns-unofficial" -version = "0.4.0" +name = "tokio-executor" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.8" +version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6093,7 +7274,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6108,33 +7289,33 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 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-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-rustls" -version = "0.10.0-alpha.4" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6146,6 +7327,16 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-sync" +version = "0.2.0-alpha.6" +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-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-tcp" version = "0.1.3" @@ -6154,36 +7345,36 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (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.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.16" +version = "0.1.17" 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-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.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.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6204,10 +7395,10 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (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.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6218,67 +7409,100 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (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.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-util" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "traitobject" -version = "0.1.0" +name = "tower-service" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "tracing" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-attributes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "transaction-factory" -version = "0.0.1" +name = "tracing-attributes" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "substrate-cli 2.0.0", - "substrate-client 2.0.0", - "substrate-consensus-common 2.0.0", - "substrate-primitives 2.0.0", - "substrate-service 2.0.0", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tracing-core" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "trie-bench" -version = "0.16.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.15.2" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6305,15 +7529,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "trybuild" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6346,12 +7570,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6364,10 +7589,10 @@ dependencies = [ [[package]] name = "unicase" -version = "2.5.1" +version = "2.6.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)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6380,20 +7605,20 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-segmentation" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-width" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -6410,14 +7635,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "unsigned-varint" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unsigned-varint" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures_codec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "untrusted" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -6442,7 +7673,7 @@ dependencies = [ [[package]] name = "vcpkg" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -6455,8 +7686,8 @@ name = "vergen" version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6465,6 +7696,11 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -6475,9 +7711,9 @@ name = "wabt" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6486,7 +7722,7 @@ name = "wabt-sys" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6511,6 +7747,15 @@ dependencies = [ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasi" version = "0.7.0" @@ -6518,77 +7763,76 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasm-bindgen" -version = "0.2.51" +version = "0.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.51" +version = "0.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bumpalo 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-futures" -version = "0.3.27" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.51" +version = "0.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.51" +version = "0.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.51" +version = "0.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasm-bindgen-webidl" -version = "0.2.51" +version = "0.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6604,89 +7848,208 @@ dependencies = [ [[package]] name = "wasm-timer" -version = "0.1.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmi" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmi-validation" -version = "0.2.0" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmparser" +version = "0.39.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmtime-debug" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-environ 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-environ" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "zstd 0.5.1+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-jit" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-debug 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-environ 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-runtime 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-runtime" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-environ 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "web-sys" -version = "0.3.28" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-webidl 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-webidl 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webpki" -version = "0.19.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webpki-roots" -version = "0.16.0" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki-roots" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "websocket" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 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)", "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)", + "websocket-base 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "websocket-base" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6703,7 +8066,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6754,16 +8117,16 @@ dependencies = [ [[package]] name = "ws" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6793,159 +8156,210 @@ name = "xdg" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "yaml-rust" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "yamux" -version = "0.2.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nohash-hasher 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "zeroize" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "zeroize_derive 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "zeroize" -version = "0.10.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "zeroize_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "zeroize_derive" -version = "0.9.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zstd" +version = "0.5.1+zstd.1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "zstd-safe 2.0.3+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zstd-safe" +version = "2.0.3+zstd.1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "zstd-sys 1.4.15+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zstd-sys" +version = "1.4.15+zstd.1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] +"checksum Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" "checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" "checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" -"checksum ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "b35dfc96a657c1842b4eb73180b65e37152d4b94d0eb5cb51708aee7826950b4" +"checksum ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" -"checksum aio-limited 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4dddf55b0b2da9acb7512f21c0a4f1c0871522ec4ab7fb919d0da807d1e32b3" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +"checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" -"checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" +"checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6fce6b6a0ffdafebd82c87e79e3f40e8d2c523e5fea5566ff6b90509bf98d638" "checksum asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" "checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" +"checksum async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "644a5a8de80f2085a1e7e57cd1544a2a7438f6e003c0790999bd43b92a77cdb2" +"checksum async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "513ee3c49800679a319912340f5601afda9e72848d7dea3a48bab489e8c1a46f" +"checksum async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de6bd58f7b9cc49032559422595c81cbfcf04db2f2133592f70af19e258a1ced" +"checksum async-tls 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce6977f57fa68da77ffe5542950d47e9c23d65f5bc7cb0a9f8700996913eec7" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" -"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df683a55b54b41d5ea8ebfaebb5aa7e6b84e3f3006a78f010dadc9ca88469260" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" +"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +"checksum bindgen 0.49.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4c07087f3d5731bf3fb375a81841b99597e25dc11bd3bc72d16d43adf6624a6e" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5da9b3d9f6f585199287a473f4f8dfab6566cf827d15c00c219f53c645687ead" -"checksum bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9633b74910e1870f50f5af189b08487195cdb83c0e27a71d6f64d5e09dd0538b" +"checksum bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" "checksum blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" +"checksum blake2b_simd 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b83b7baab1e671718d78204225800d6b170e648188ac7dc992e9d6bddf87d0c0" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" -"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" +"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +"checksum broadcaster 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "07a1446420a56f1030271649ba0da46d23239b3a68c73591cea5247f15a788a0" "checksum bs58 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c95ee6bba9d950218b6cc910cf62bc9e0a171d0f4537e3627b0f54d08549b188" +"checksum bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" "checksum build-helper 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdce191bf3fa4995ce948c8c83b4640a1745457a149e73c6db75b4ffe36aad5f" -"checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" -"checksum byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7cbcbf18128ec71d8d4a0d054461ec59fff5b75b7d10a4c9b7c7cb1a379c3e77" -"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" +"checksum bumpalo 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fe2567a8d8a3aedb4e39aa39e186d5673acfd56393c6ac83b2bc5bd82f4369c" +"checksum byte-slice-cast 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f6209f3b2c1edea170002e016d5ead6903d3bb0a846477f53bbeb614967a52a9" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38" +"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" -"checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" -"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" -"checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af" +"checksum cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" +"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" +"checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" -"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" +"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" +"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" +"checksum console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" +"checksum console_log 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e7871d2947441b0fdd8e2bd1ce2a2f75304f896582c0d572162d48290683c48" "checksum const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b641a8c9867e341f3295564203b1c250eb8ce6cb6126e007941f78c4d2ed7fe" "checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" "checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum cranelift-bforest 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd05aac8cefcde54ce26178df8f36cb1f518ac691db650e7d2440c2b6b41c4dc" +"checksum cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63d9b6ff8a94f98deabab21880d7fd54996e0e16be687b6f80a3b6bdd9c188d" +"checksum cranelift-codegen-meta 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb3df51c2c07d719d02869bfac6cabd8d82ee308d5b29ca62e6528723cc33a4" +"checksum cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "758f9426b2e22bf83fc1a6b231a9d53cd4830751883c7f0e196ebb3c210467b3" +"checksum cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff064733df8b98f453060264a8790393d1e807aca6942706b42f79a4f7aae9ed" +"checksum cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eaafb5fa623dcbe19a28084a8226d7a1b17184a949c1a1f29a46b479867998d" +"checksum cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90033dbd7293f6fad4cf9dcd769cd621d60df22b1c5a11799e86359b7447a51d" +"checksum cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "54cb82a1071f88822763a583ec1a8688ffe5e2cda02c111d4483dd4376ed14d8" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394" "checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" "checksum criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76f9212ddf2f4a9eb2d401635190600656a1f88a932ef53d06e7fa4c7e02fb8e" "checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" -"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" +"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" +"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" +"checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" "checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" "checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" "checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f" "checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" "checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" +"checksum curve25519-dalek 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839" "checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" -"checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" +"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" +"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" "checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" -"checksum ed25519-dalek 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d07e8b8a8386c3b89a7a4b329fdfa4cb545de2545e9e2ebbc3dd3929253e426" -"checksum ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "845aaacc16f01178f33349e7c992ecd0cee095aa5e577f0f4dee35971bd36455" +"checksum ed25519-dalek 1.0.0-pre.3 (registry+https://github.com/rust-lang/crates.io-index)" = "978710b352437433c97b2bff193f2fb1dfd58a093f863dd95e225a19baa599a2" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" +"checksum enumflags2 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "33121c8782ba948ba332dab29311b026a8716dc65a1599e5b88f392d38496af8" +"checksum enumflags2_derive 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ecf634c5213044b8d54a46dd282cf5dd1f86bb5cb53e92c409cb4680a7fb9894" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" -"checksum env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39ecdb7dd54465526f0a56d666e3b2dd5f3a218665a030b6e4ad9e70fa95d8fa" +"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "34f8467a0284de039e6bd0e25c14519538462ba5beb548bb1f03e645097837a8" "checksum erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3beee4bc16478a1b26f2e80ad819a52d24745e292f521a63c16eea5f74b7eb60" -"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" -"checksum exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d8013f441e38e31c670e7f34ec8f1d5d3a2bd9d303c1ff83976ca886005e8f48" +"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" +"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" +"checksum evm 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32a2c6961fdc9952371fc5f0416f03a9d90378a9dfb6862f6a7a9a3b8986b8dd" +"checksum evm-core 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bcde5af3d542874ddeb53de0919302d57586ea04b3f76f54d865f8a6cdc70ae" +"checksum evm-gasometer 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b82bc9f275cb59d2bcc05d85c98736ddfaba003a7ef7b73893fa7c1c1fab29dc" +"checksum evm-runtime 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbc89d29618c3722c17ba78ddf432d40ace8ee27e3f8b28b52a85921112e4b" +"checksum exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" +"checksum faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f902f2af041f6c7177a2a04f805687cdc71e69c7cbef059a2755d8923f4cd7a8" "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" -"checksum finality-grandpa 0.9.1 (git+https://github.com/paritytech/finality-grandpa)" = "" -"checksum fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "516877b7b9a1cc2d0293cbce23cd6203f0edbfd4090e6ca4489fecb5aa73050e" -"checksum fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6357b15872f8126e4ea7cf79d579473f132ccd2de239494ad1bf4aa892faea68" +"checksum file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8505b75b31ef7285168dd237c4a7db3c1f3e0927e7d314e670bc98e854272fe9" +"checksum finality-grandpa 0.11.0 (git+https://github.com/expenses/finality-grandpa?branch=future)" = "" +"checksum fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72fe7539e2c5692c6989f2f9c0457e42f1e5768f96b85c87d273574670ae459f" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" +"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" "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" @@ -6955,127 +8369,144 @@ dependencies = [ "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.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" +"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" "checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" +"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" "checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" -"checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" -"checksum futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" +"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" "checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" -"checksum futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f9eb554aa23143abc64ec4d0016f038caf53bb7cbc3d91490835c54edc96550" +"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" "checksum futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "878f1d2fc31355fa02ed2372e741b0c17e58373341e6a122569b4623a14a7d33" +"checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" +"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" "checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" +"checksum futures_codec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a0a73299e4718f5452e45980fc1d6957a070abe308d3700b63b8673f47e1c2b3" +"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" "checksum get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7" "checksum get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "162d18ae5f2e3b90a993d202f1ba17a5633c2484426f8bcae201f86194bacd00" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +"checksum goblin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88a79ef1f0dad46fd78075b6f80f92d97710eddf87b3e18a15a66761e8942672" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +"checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" "checksum hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" "checksum hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" -"checksum hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" -"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" +"checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" "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 hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +"checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" "checksum hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "961de220ec9a91af2e1e5bd80d02109155695e516771762381ef8581317066e0" "checksum hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d4c5c844e2fee0bf673d54c2c177f1713b3d2af2ff6e666b49cb7572e6cf42d" -"checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" -"checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" "checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" -"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" +"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +"checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" "checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +"checksum hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf49cfb32edee45d890537d9057d1b02ed55f53b7b6a30bae83a38c9231749e" +"checksum hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa0086251524c50fd53b32e7b05eb6d79e2f97221eaf0c53c0ca9c3096f21d3" -"checksum impl-serde 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a263dc95daa6c3788c8f7133d86dc2ad89ec5a0c56167f9e3441c5f7f33358c4" -"checksum impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6947b372790f8948f439bb6aaa6baabdf80be1a207a477ff072f83fb793e428f" -"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" +"checksum impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" +"checksum impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" +"checksum impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" +"checksum impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" +"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" "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.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -"checksum ipnet 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc15ac2e0886d62ba078989ef6920ab23997ab0b04ca5687f1a9a7484296a48" -"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" +"checksum ipnet 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f4b06b21db0228860c8dfd17d2106c49c7c6bd07477a4036985347d84def04" +"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" -"checksum js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc9a97d7cec30128fd8b28a7c1f9df1c001ceb9b441e2b755e24130a6b43c79" -"checksum jsonrpc-client-transports 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dbf2466adbf6d5b4e618857f22be40b1e1cc6ed79d72751324358f6b539b06d" -"checksum jsonrpc-core 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91d767c183a7e58618a609499d359ce3820700b3ebb4823a18c343b4a2a41a0d" -"checksum jsonrpc-core-client 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "161dc223549fa6fe4a4eda675de2d1d3cff5a7164e5c031cdf1e22c734700f8b" -"checksum jsonrpc-derive 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4a76285ebba4515680fbfe4b62498ccb2a932384c8732eed68351b02fb7ae475" -"checksum jsonrpc-http-server 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "601fcc7bec888c7cbc7fd124d3d6744d72c0ebb540eca6fe2261b71f9cff6320" -"checksum jsonrpc-pubsub 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64e0fb0664d8ce287e826940dafbb45379443c595bdd71d93655f3c8f25fd992" -"checksum jsonrpc-server-utils 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d415f51d016a4682878e19dd03e8c0b61cd4394912d7cd3dc48d4f19f061a4e" -"checksum jsonrpc-ws-server 13.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4699433c1ac006d7df178b4c29c191e5bb6d81e2dca18c5c804a094592900101" +"checksum js-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "c40e7a4fafb6cf0be06d25662fc99aacb25f526eb6e1bc0c24100bde5d6a834e" +"checksum jsonrpc-client-transports 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9ae166c4d1f702d297cd76d4b55758ace80272ffc6dbb139fdc1bf810de40b" +"checksum jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" +"checksum jsonrpc-core-client 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "080dc110be17701097df238fad3c816d4a478a1899dfbcf8ec8957dd40ec7304" +"checksum jsonrpc-derive 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8609af8f63b626e8e211f52441fcdb6ec54f1a446606b10d5c89ae9bf8a20058" +"checksum jsonrpc-http-server 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2d83d348120edee487c560b7cdd2565055d61cda053aa0d0ef0f8b6a18429048" +"checksum jsonrpc-pubsub 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3453625f0f0f5cd6d6776d389d73b7d70fcc98620b7cbb1cbbb1f6a36e95f39a" +"checksum jsonrpc-server-utils 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "95b7635e618a0edbbe0d2a2bbbc69874277c49383fcf6c3c0414491cfb517d22" +"checksum jsonrpc-ws-server 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b34faa167c3ac9705aeecb986c0da6056529f348425dbe0441db60a2c4cc41d1" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3468207deea1359a0e921591ae9b4c928733d94eb9d6a2eeda994cfd59f42cf8" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" +"checksum kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" +"checksum kvdb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8396be0e5561ccd1bf7ff0b2007487cdd7a87a056873fe6ea906b35d4dbf7ed8" +"checksum kvdb-memorydb 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d25ef14155e418515c4839e9144c839de3506e68946f255a32b7f166095493d" +"checksum kvdb-rocksdb 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "af488cc16c3801705c8d681c3a32c8faa8fafc7fb5309dee0f573f3c6a19d395" +"checksum kvdb-web 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37a0e36637fb86454de401e7cb88f40eb0ad1b9bcee837d46785e7c451f1ebf4" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" -"checksum libp2p 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4183fb4be621d97baebbbe0c499d6ae337e9e6ec955f9fa3cb29e55547dfacdb" -"checksum libp2p-core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a7ebd9d597299512e096cc1bd58e955c03ef28f33214a33b9c7e4ace109ff41" -"checksum libp2p-core-derive 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baffb3527eac95b717e5ebcd6539007152019a06b00548352cbd74474c07db27" -"checksum libp2p-deflate 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84bb91afe976893b9822103522cc178bd66eb7aa8e54c69ddd9e1825a3d894ab" -"checksum libp2p-dns 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b43d79936984b46a5ef4d7b070eaf786f6fab2d1a57e07646306b492e38b2d7f" -"checksum libp2p-floodsub 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "798615b01761454818788dafe61b4fe2bda4306bfa5378cbe8715f57b752235f" -"checksum libp2p-identify 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0a630d5ab928403e426672187514884a9ed0ea2065970ef0ec64971770be6d5" -"checksum libp2p-kad 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66d2214dd47fa67878eaf0d76d19fd129eff65c45f83617829eb177b7285f97" -"checksum libp2p-mdns 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbd443101542670935b6e6863b7bb88c10ac04393062e662201a3c104d80ae00" -"checksum libp2p-mplex 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "59f283e603b078aa88e65c66c5d4f842f67bfbe4d016b0ae345b7e3bb78fe0af" -"checksum libp2p-noise 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab3c7b36cde3bfe18a1d7a0a5693361115066365d32c60f210acc8224b88017" -"checksum libp2p-ping 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006bbfcb7d6ca7e617cb2924d99fff0e391d4c6e42e7047e226692c8c3e1f6a0" -"checksum libp2p-plaintext 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4e673668e5ef47689ca832c33f2dc1e321ede245ee50b6084e4c45cce10fff6" -"checksum libp2p-ratelimit 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "838538f6df5941626047903d14edc3112afb2807fc139535a8ca78469ccaf1ac" -"checksum libp2p-secio 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a99533cb55b9554d2927ad8a220c87b4e0bbfdec22b738eb6030b03e6a722fa1" -"checksum libp2p-swarm 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541f66cc794e522fb8072d35dba6be3fe4c3ffeadbed39bf4a6939d0695b4134" -"checksum libp2p-tcp 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4e56f7c7e31d303898d51b293f8d95dcb99e6293fefebe184df03e82dd37571" -"checksum libp2p-uds 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "180fa5ceb2f986786b4fca9582f6ffb98772db2e44df07c800693c97205e3310" -"checksum libp2p-wasm-ext 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a806f0e4985ae2dbac2cbebadb72d586ffe2e1f62a265f5e019e57a3f02aa481" -"checksum libp2p-websocket 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0dd3cb203aaa1736a38cdd157709153f90bfaed06b87f4dc3ebb62b5d79a643" -"checksum libp2p-yamux 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a37bed07c8ee0ceeecdfb90d703aa6b1cec99a69b4157e5f7f2c03acacbfca15" -"checksum librocksdb-sys 5.18.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19778314deaa7048f2ea7d07b8aa12e1c227acebe975a37eeab6d2f8c74e41b" -"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" -"checksum libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63cc09b49bf0cc55885982347b174ad89855e97a12284d2c9dcc6da2e20c28f5" +"checksum libp2p 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c85f850649e7533db125207d86bc2180faf7a962ea07686011031b71cbb3540" +"checksum libp2p-core 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "187ac3f588a74d48f163a8899fddafef4dc9796cad7b73ae754d9e928cebbbe7" +"checksum libp2p-core-derive 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b674da01855701636371b3d5f0e6b38bf5a74d283de705c1f66fab9980da8943" +"checksum libp2p-deflate 0.6.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f83cefe9f01a4a7012c1285e20fca4f193c46526a350679465150035afc5a97" +"checksum libp2p-dns 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67d5a6d0905479ee4c6bcfaeab597d506f3447e5eb09b84aff1ed5e6d834b221" +"checksum libp2p-floodsub 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "462f310a152433a94d4e9766aa8366e4770084f67b9a17289a9667a7b0780714" +"checksum libp2p-identify 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8269e7b673cf0fbce1cbfedf61708e860aeb4b2ad3ca2df54586f1e810b9fbc9" +"checksum libp2p-kad 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90fdc0027f76b50b0822f489f5b8a83664b71c6087e67e8e9e53e6c255b069b3" +"checksum libp2p-mdns 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0b7cdeb0ad2c009099eaed258ef18b308c1e3f56d8f57668a868305f1c4caa" +"checksum libp2p-mplex 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54c2ca42c7511fddc566af2259b81749d36011fefab1e99d9bf77bdc6210a5bd" +"checksum libp2p-noise 0.12.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8ff485bebd3181fc7f0c8ca7d11dde6231c132bbfb5d26c0e3a568e1a58b450" +"checksum libp2p-ping 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9061919a24a74760610c860e67cdb44ae4fd3cffe34c3b3a916f21ec68d9d50a" +"checksum libp2p-plaintext 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e9bf4b832590e0bf7efc09ff91c2d4cda0737f29b44356ef0cc3aecc08ed54a" +"checksum libp2p-secio 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2aa7599c5413cbc3de7138d64b932a26e86f8897ef3722f18840ed12ad54ea43" +"checksum libp2p-swarm 0.4.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea29f98b08c7a5113a787bce1a44d33fca6cf9f680f99812b50555e50baf408" +"checksum libp2p-tcp 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a4e0d1f322101d81c26782e76c523043f96fe53fa41962fd2c2193a709985186" +"checksum libp2p-uds 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d5620aca9d9f85158b934be33a25a6310f1ca6a038392498eb7f35d35063aee9" +"checksum libp2p-wasm-ext 0.7.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dfe80dd0d2cb6412b57fffeb3db2dc36f7ea23566ed94011e0e07ff948f9624" +"checksum libp2p-websocket 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ac2a4974254a91f5291ef8493e6377380473334ba166ea0487e898364931dd61" +"checksum libp2p-yamux 0.14.0-alpha.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ef3277eaffc7c3a0ad0c115dcbe3cbeb0e3a953a18b959d05081835fc2cf2ff9" +"checksum librocksdb-sys 6.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0785e816e1e11e7599388a492c61ef80ddc2afc91e313e61662cce537809be" +"checksum libsecp256k1 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "df6edf84fd62aad1c93932b39324eaeda3912c1d26bc18dfaee6293848e49a50" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7c91c4c7bbeb4f2f7c4e5be11e6a05bd6830bc37249c47ce1ad86ad453ff9c" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" -"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -"checksum malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3" +"checksum lru 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "5d8f669d42c72d18514dfca8115689c5f6370a17d980cb5bd777a67f404594c8" +"checksum lru 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0609345ddee5badacf857d4f547e0e5a2e987db77085c24cd887f73573a04237" +"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" +"checksum malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e37c5d4cd9473c5f4c9c111f033f15d4df9bd378fdf615944e360a4f55a05f0b" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef49315991403ba5fa225a70399df5e115f57b274cb0b1b4bcd6e734fa5bd783" +"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" +"checksum memory-db 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "828bdf600636e90c56652689f7c3823ae2072104e4b0b5e83ea984f592f12ab9" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "de2d16d3b15fec5943d1144f861f61f279d165fdd60998ca262913b9bf1c8adb" +"checksum merlin 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0942b357c1b4d0dc43ba724674ec89c3218e6ca2b3e8269e7cb53bcecd2f6e" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum miniz_oxide 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "304f66c19be2afa56530fa7c39796192eef38618da8d19df725ad7c6d6b2aaae" -"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" -"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" +"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +"checksum mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" "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 more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" "checksum multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb04b9f127583ed176e163fb9ec6f3e793b87e21deedd5734a69386a18a0151" -"checksum multistream-select 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f3cb4c93f2d79811fc11fa01faab99d8b7b8cbe024b602c27434ff2b08a59d" +"checksum multistream-select 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f938ffe420493e77c8b6cbcc3f282283f68fc889c5dcbc8e51668d5f3a01ad94" "checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" @@ -7086,34 +8517,37 @@ dependencies = [ "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" +"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" "checksum once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d584f08c2d717d5c23a6414fc2822b71c651560713e54fa7eace675f758a355e" +"checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" +"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)" = "ba24190c8f0805d3bd2ce028f439fe5af1d55882bbe6261bed1dbc93b50dd6b1" +"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "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-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c276d76c5333b8c2579e02d49a06733a55b8282d2d9b13e8d53b6406bd7e30a" "checksum parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "045b3c7af871285146300da35b1932bb6e4639b66c7c98e85d06a32cbc4e8fa7" +"checksum parity-multiaddr 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6de20a133b50f5120c6b8284ee88c5017fb167149208b3ee2e95f8719a434dc4" "checksum parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df3a17dc27848fd99e4f87eb0f8c9baba6ede0a6d555400c850ca45254ef4ce3" -"checksum parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "001fbbb956d8593f321c7a784f64d16b2c99b2657823976eea729006ad2c3668" -"checksum parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42af752f59119656fa3cb31e8852ed24e895b968c0bdb41847da7f0cea6d155f" +"checksum parity-multihash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70a4d7b05e51bff5ae2c29c7b8c3d889985bbd8f4e15b3542fcc1f6f9666d292" +"checksum parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9f9d99dae413590a5f37e43cd99b94d4e62a244160562899126913ea7108673" +"checksum parity-scale-codec-derive 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34e513ff3e406f3ede6796dcdc83d0b32ffb86668cea1ccf7363118abeb00476" "checksum parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" -"checksum parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2005637ccf93dbb60c85081ccaaf3f945f573da48dcc79f27f9646caa3ec1dc" +"checksum parity-util-mem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8174d85e62c4d615fddd1ef67966bdc5757528891d0742f15b131ad04667b3f9" +"checksum parity-util-mem 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "900dd84654b048e5bad420bb341658fc2c4d7fea628c22bcf4621733e54859b4" +"checksum parity-util-mem-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" "checksum parity-wasm 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16ad52817c4d343339b3bc2e26861bd21478eda0b7509acf83505727000512ac" -"checksum parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e39faaa292a687ea15120b1ac31899b13586446521df6c149e46f1584671e0f" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" +"checksum parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" +"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" "checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" "checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" @@ -7122,15 +8556,20 @@ dependencies = [ "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" +"checksum pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" +"checksum pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" +"checksum pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" "checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" -"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" +"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "83ef7b3b965c0eadcb6838f34f827e1dfb2939bdd5ebd43f9647e009b12b0371" -"checksum primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97b5a08dda18910f056e5c2060c034e77cab18e0bd7d895e44f03207af4c71d5" +"checksum primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0253db64c26d8b4e7896dd2063b516d2a1b9e0a5da26b5b78335f236d1e9522" "checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" -"checksum proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "114cdf1f426eb7f550f01af5f53a33c0946156f6814aec939b3bd77e844f9a9d" +"checksum proc-macro-error 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "53c98547ceaea14eeb26fcadf51dc70d01a2479a7839170eae133721105e4428" +"checksum proc-macro-error-attr 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c2bf5d493cf5d3e296beccfd61794e445e830dfc8070a9c248ad3ee071392c6c" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" +"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96d14b1c185652833d24aaad41c5832b0be5616a590227c1fbff57c616754b23" @@ -7138,15 +8577,14 @@ dependencies = [ "checksum prost-derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e7dc378b94ac374644181a2247cebf59a6ec1c88b49ac77f3a94b86b79d0e11" "checksum prost-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1de482a366941c8d56d19b650fac09ca08508f2a696119ee7513ad590c8bac6f" "checksum protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40361836defdd5871ff7e84096c6f6444af7fc157f8ef1789f54f147687caa20" -"checksum pwasm-utils 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d473123ba135028544926f7aa6f34058d8bc6f120c4fcd3777f84af724280b3" -"checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" +"checksum pwasm-utils 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7a12f176deee919f4ba55326ee17491c8b707d0987aed822682c821b660192" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5ca504a2fdaa08d3517f442fbbba91ac24d1ec4c51ea68688a038765e3b2662" +"checksum quicksink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8461ef7445f61fd72d8dcd0629ce724b9131b3c2eb36e83a5d3d4161c127530" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -7164,158 +8602,184 @@ dependencies = [ "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 rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" -"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" -"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" +"checksum raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf" +"checksum rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" +"checksum rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6" +"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "448e868c6e4cfddfa49b6a72c95906c04e8547465e9536575b95c70a4044f856" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum rhododendron 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36542aafc2429a4c010fafa079a20dee953b663cb2427f51d86cf1d436846b4d" -"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" -"checksum rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1651697fefd273bfb4fd69466cc2a9d20de557a0213b97233b22b5e95924b5e" -"checksum rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f072d931f11a96546efd97642e1e75e807345aced86b947f9239102f262d0fcd" +"checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac" +"checksum rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3a44d5ae8afcb238af8b75640907edc6c931efcfab2c854e81ed35fa080f84cd" +"checksum rocksdb 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12069b106981c6103d3eab7dd1c86751482d0779a520b7c14954c8b586c1e643" +"checksum rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d59f0e97173c514b9036cd450c195a6483ba81055c6fa0f1bff3ab563f47d44a" +"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f271e3552cd835fa28c541c34a7e8fdd8cdff09d77fe4eb8f6c42e87a11b096e" +"checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" "checksum rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48f91977f4ef3be5358c15d131d3f663f6b4d7a112555bf3bf52ad23b6659e5" -"checksum rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9cbe61c20455d3015b2bb7be39e1872310283b8e5a52f5b242b0ac7581fe78" -"checksum ryu 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19d2271fa48eaf61e53cc88b4ad9adcbafa2d512c531e7fadb6dc11a4d3656c5" +"checksum rw-stream-sink 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "761d4727649dc004ee5555a0779afd53963efafd2218c969a2c5e323cdf73a09" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b08423011dae9a5ca23f07cf57dac3857f5c885d352b76f6d95f4aea9434d0" +"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" "checksum schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eacd8381b3c37840c9c9f40472af529e49975bdcbc24f83c31059fd6539023d3" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f5adf8fbd58e1b1b52699dc8bed2630faecb6d8c7bee77d009d6bbe4af569b9" -"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" -"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" +"checksum scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" +"checksum scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28" +"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" +"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +"checksum send_wrapper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "686ef91cf020ad8d4aca9a7047641fd6add626b7b89e14546c2b6a76781cf822" +"checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" +"checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" "checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" +"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cc9c640a4adbfbcc11ffb95efe5aa7af7309e002adab54b185507dbf2377b99" -"checksum slog-async 2.3.0 (git+https://github.com/paritytech/slog-async)" = "" "checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -"checksum slog-scope 4.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1d3ec6214d46e57a7ec87c1972bbca66c59172a0cfffa5233c54726afb946bf" -"checksum slog_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eff3b513cf2e0d1a60e1aba152dc72bedc5b05585722bb3cebd7bcb1e31b98f" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5a64f02fd208ef15bd2d1a65861df4707e416151e1272d02c8faafad1c138100" -"checksum soketto 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bceb1a3a15232d013d9a3b7cac9e5ce8e2313f348f01d4bc1097e5e53aa07095" +"checksum slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6" +"checksum slog_derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a945ec7f7ce853e89ffa36be1e27dce9a43e82ff9093bf3461c30d5da74ed11b" +"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" +"checksum snow 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "afb767eee7d257ba202f0b9b08673bc13b22281632ef45267b19f13100accd2f" +"checksum soketto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3caa0ad6b765419f21e4cfa490ec7514a9fae4af986adef168a69477ba528671" "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362" +"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" "checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +"checksum string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd710eadff449a1531351b0e43eb81ea404336fa2f56c777427ab0e32a4cf183" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4f66a4c0ddf7aee4677995697366de0749b0139057342eccbb609b12d0affc" -"checksum structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fe0c13e476b4e21ff7f5c4ace3818b6d7bdc16897c31c73862471bc1663acae" -"checksum strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1c33039533f051704951680f1adfd468fd37ac46816ded0d9ee068e60f05f" -"checksum strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47cd23f5c7dee395a00fa20135e2ec0fffcdfa151c56182966d7a3261343432e" +"checksum structopt 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "884ae79d6aad1e738f4a70dff314203fd498490a63ebc4d03ea83323c40b7b72" +"checksum structopt-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a97f829a34a0a9d5b353a881025a23b8c9fd09d46be6045df6b22920dbd7a93" +"checksum strum 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6138f8f88a16d90134763314e3fc76fa3ed6a7db4725d6acf9a3ef95a3188d22" +"checksum strum_macros 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0054a7df764039a6cd8592b9de84be4bec368ff081d203a7d5371cbfa8e65c81" "checksum substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3be511be555a3633e71739a79e4ddff6a6aaa6579fa6114182a51d72c3eb93c5" -"checksum substrate-wasm-builder-runner 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bd48273fe9d7f92c1f7d6c1c537bb01c8068f925b47ad2cd8367e11dc32f8550" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab3af2eb31c42e8f0ccf43548232556c42737e01a96db6e1777b0be108e79799" +"checksum subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" -"checksum sysinfo 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bd3b813d94552a8033c650691645f8dd5a63d614dddd62428a95d3931ef7b6" +"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +"checksum syn-mid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0" +"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +"checksum sysinfo 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6f4b2468c629cffba39c0a4425849ab3cdb03d9dfacba69684609aea04d08ff9" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" +"checksum target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f4c118a7a38378f305a9e111fcb2f7f838c0be324bfb31a77ea04f7f6e684b4" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" -"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum test-case 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a605baa797821796a751f4a959e1206079b24a4b7e1ed302b7d785d81a9276c9" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f357d1814b33bc2dc221243f8424104bfe72dbe911d5b71b3816a2dff1c977e" +"checksum thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" "checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" +"checksum tiny-keccak 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2953ca5148619bc99695c1274cb54c5275bbb913c6adad87e72eaf8db9787f69" "checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +"checksum tokio 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bcced6bb623d4bff3739c176c415f13c418f426395c169c9c3cd9a492c715b16" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" -"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" +"checksum tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab" +"checksum tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee9ceecf69145923834ea73f32ba40c790fd877b74a7817dd0b089f1eb9c7c8" "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.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" -"checksum tokio-rustls 0.10.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e5cebc3ca33110e460c4d2e7c5e863b159fadcbf125449d896720695b2af709" +"checksum tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6732fe6b53c8d11178dcb77ac6d9682af27fc6d4cb87789449152e5377377146" +"checksum tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1df2fa53ac211c136832f530ccb081af9af891af22d685a9493e232c7a359bc2" "checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" +"checksum tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f1aaeb685540f7407ea0e27f1c9757d258c7c6bf4e3eb19da6fc59b747239d2" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" -"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c32ffea4827978e9aa392d2f743d973c1dfa3730a2ed3f22ce1e6984da848c" +"checksum tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1739638e364e558128461fc1ad84d997702c8e31c2e6b18fb99842268199e827" "checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" "checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" -"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" +"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" +"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +"checksum tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ff4e4f59e752cb3beb5b61c6d5e11191c7946231ba84faec2902c9efdd8691c5" +"checksum tracing-attributes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a4263b12c3d3c403274493eb805966093b53214124796552d674ca1dd5d27c2b" +"checksum tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bc913647c520c959b6d21e35ed8fa6984971deca9f0a2fcb8c51207e0c56af1d" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum trie-bench 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3073600c543ed001319d7e092c46dfd8c245af1a218ec5c75eb01582660a2b3e" -"checksum trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b62d27e8aa1c07414549ac872480ac82380bab39e730242ab08d82d7cc098a" +"checksum trie-bench 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d276e600d06806a4ac61e5d6b145a620001e6147151e60a4f1f46a784ec4baa" +"checksum trie-db 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "191fda5d0106f3ed35a8c6875428b213e15c516e48129cc263dd7ad16e9a665f" "checksum trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b779f7c1c8fe9276365d9d5be5c4b5adeacf545117bb3f64c974305789c5c0b" "checksum trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3161ba520ab28cd8e6b68e1126f1009f6e335339d1a73b978139011703264c8" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e6851bf8351876984fbab8a2391de6378947b898410d8714edd12164d2137127" +"checksum trybuild 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "b75e31d624df08744532e935f1d4bfedd319a277d5a162c5b15f6ced59307575" "checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" "checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -"checksum uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8f0f47ed099f0db671ce82c66548c5de012e3c0cba3963514d1db15c7588701" +"checksum uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" +"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" -"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f0023a96687fe169081e8adce3f65e3874426b7886e9234d490af2dc077959" -"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" +"checksum unsigned-varint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c689459fbaeb50e56c6749275f084decfd02194ac5852e6617d95d0d3cf02eaf" +"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" +"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5c5c1286c6e578416982609f47594265f9d489f9b836157d403ad605a46693" "checksum wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af5d153dc96aad7dc13ab90835b892c69867948112d95299e522d370c4e13a08" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "cd34c5ba0d228317ce388e87724633c57edca3e7531feb4e25e35aaa07a656af" -"checksum wasm-bindgen-backend 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "927196b315c23eed2748442ba675a4c54a1a079d90d9bdc5ad16ce31cf90b15b" -"checksum wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)" = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c" -"checksum wasm-bindgen-macro 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "92c2442bf04d89792816650820c3fb407af8da987a9f10028d5317f5b04c2b4a" -"checksum wasm-bindgen-macro-support 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "9c075d27b7991c68ca0f77fe628c3513e64f8c477d422b859e03f28751b46fc5" -"checksum wasm-bindgen-shared 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "83d61fe986a7af038dd8b5ec660e5849cbd9f38e7492b9404cc48b2b4df731d1" -"checksum wasm-bindgen-webidl 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "9b979afb0535fe4749906a674082db1211de8aef466331d43232f63accb7c07c" +"checksum wasm-bindgen 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)" = "701bc20794a7f9e8dcd85984a848f951ef6c5083322b6dd17fe880c99390f7cd" +"checksum wasm-bindgen-backend 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)" = "426315280d373e1a828e1c322507d51aa82e03c2fb1d654720b9e2f2368d291d" +"checksum wasm-bindgen-futures 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1de54efe80cb87a8fa1f715d60ab47a5eac6b1447dd68665300773f498c229b1" +"checksum wasm-bindgen-macro 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)" = "d9a8a46373db32c892de910ccca302ecdaf8262abab746324a8a4dac352fc11f" +"checksum wasm-bindgen-macro-support 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)" = "45d1c6c2259c0f4ef3d61ea0976ea075b6f8185497c4a5457793740c2cda6430" +"checksum wasm-bindgen-shared 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)" = "dd8e108ae395aae8017b091c4766101f08c635a5074e6631e0085e8a839e5810" +"checksum wasm-bindgen-webidl 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)" = "7a38859ace1c29c8ed75cd74940d4c96b980837179355de542a2eab3b435bb5c" "checksum wasm-gc-api 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c32691b6c7e6c14e7f8fd55361a9088b507aa49620fcd06c09b3a1082186b9" -"checksum wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aa3e01d234bb71760e685cfafa5e2c96f8ad877c161a721646356651069e26ac" -"checksum wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f31d26deb2d9a37e6cfed420edce3ed604eab49735ba89035e13c98f9a528313" -"checksum wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc0356e3df56e639fc7f7d8a99741915531e27ed735d911ed83d7e1339c8188" -"checksum web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)" = "c84440699cd02ca23bed6f045ffb1497bc18a3c2628bd13e2093186faaaacf6b" -"checksum webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7e1cd7900a3a6b65a3e8780c51a3e6b59c0e2c55c6dc69578c288d69f7d082" -"checksum webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c10fa4212003ba19a564f25cd8ab572c6791f99a03cc219c13ed35ccab00de0e" -"checksum websocket 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b255b190f412e45000c35be7fe9b48b39a2ac5eb90d093d421694e5dae8b335c" +"checksum wasm-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "324c5e65a08699c9c4334ba136597ab22b85dccd4b65dd1e36ccf8f723a95b54" +"checksum wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bf617d864d25af3587aa745529f7aaa541066c876d57e050c0d0c85c61c92aff" +"checksum wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea78c597064ba73596099281e2f4cfc019075122a65cdda3205af94f0b264d93" +"checksum wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c702914acda5feeeffbc29e4d953e5b9ce79d8b98da4dbf18a77086e116c5470" +"checksum wasmtime-debug 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5008729ad53f75020f28fa0d682269335d6f0eac0b3ffafe31f185b2f33aca74" +"checksum wasmtime-environ 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3947662a0b8e05b1418465e64f16de9114f9fec18cc3f56e0ed5aa7737b89d0" +"checksum wasmtime-jit 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ed7922689461a7b5bd0d9c7350cac526c8a520a23b3ffd7f5b446ac51dfc51f" +"checksum wasmtime-runtime 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "781d6bb8b346efaa3dc39746386957cd79b8d841e8652ed9b02d77bcf64fb514" +"checksum web-sys 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ba09295448c0b93bc87d2769614d371a924749e5e6c87e4c1df8b2416b49b775" +"checksum webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e664e770ac0110e2384769bcc59ed19e329d81f555916a6e072714957b81b4" +"checksum webpki-roots 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" +"checksum webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" +"checksum websocket 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)" = "413b37840b9e27b340ce91b319ede10731de8c72f5bc4cb0206ec1ca4ce581d0" +"checksum websocket-base 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e3810f0d00c4dccb54c30a4eee815e703232819dec7b007db115791c42aa374" "checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" @@ -7325,12 +8789,14 @@ dependencies = [ "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.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" -"checksum ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6f5bb86663ff4d1639408410f50bf6050367a8525d644d49a6894cd618a631" +"checksum ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee1585dc1484373cbc1cee7aafda26634665cf449436fd6e24bfd1fad230538" "checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" -"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" -"checksum yamux 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01bd67889938c48f0049fc60a77341039e6c3eaf16cb7693e6ead7c0ba701295" -"checksum zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4090487fa66630f7b166fba2bbb525e247a5449f41c468cc1d98f8ae6ac03120" +"checksum yamux 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "809f4388471d280173404e3d4f889e2d36004960a37d822ce5637fbef33a0ce4" "checksum zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" -"checksum zeroize_derive 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "080616bd0e31f36095288bb0acdf1f78ef02c2fa15527d7e993f2a6c7591643e" +"checksum zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" +"checksum zeroize_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" +"checksum zstd 0.5.1+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c5d978b793ae64375b80baf652919b148f6a496ac8802922d9999f5a553194f" +"checksum zstd-safe 2.0.3+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bee25eac9753cfedd48133fa1736cbd23b774e253d89badbeac7d12b23848d3f" +"checksum zstd-sys 1.4.15+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "89719b034dc22d240d5b407fb0a3fe6d29952c181cff9a9f95c0bd40b4f8f7d8" diff --git a/Cargo.toml b/Cargo.toml index 2c1e361fc993c..ade5cd24e5c54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,133 +1,157 @@ -[[bin]] -name = "substrate" -path = "node/src/main.rs" - -[package] -name = "substrate" -version = "2.0.0" -authors = ["Parity Technologies "] -build = "build.rs" -edition = "2018" - -[dependencies] -cli = { package = "node-cli", path = "node/cli" } -futures = "0.1.29" -ctrlc = { version = "3.1.3", features = ["termination"] } - -[build-dependencies] -vergen = "3.0.4" - [workspace] members = [ - "core/authority-discovery", - "core/application-crypto", - "core/chain-spec", - "core/chain-spec/derive", - "core/cli", - "core/client", - "core/client/db", - "core/client/header-metadata", - "core/consensus/aura", - "core/consensus/babe", - "core/consensus/common", - "core/consensus/rhd", - "core/consensus/slots", - "core/consensus/uncles", - "core/consensus/pow", - "core/executor", - "core/executor/runtime-test", - "core/externalities", - "core/finality-grandpa", - "core/finality-grandpa/primitives", - "core/inherents", - "core/keyring", - "core/keystore", - "core/network", - "core/panic-handler", - "core/primitives", - "core/rpc", - "core/rpc/primitives", - "core/rpc-servers", - "core/serializer", - "core/service", - "core/service/test", - "core/session", - "core/sr-api-macros", - "core/sr-arithmetic", - "core/sr-io", - "core/sr-primitives", - "core/sr-staking-primitives", - "core/sr-sandbox", - "core/sr-std", - "core/sr-version", - "core/state-machine", - "core/telemetry", - "core/test-client", - "core/test-runtime", - "core/test-runtime/client", - "core/transaction-pool", - "core/transaction-pool/graph", - "core/trie", - "core/utils/fork-tree", - "core/utils/wasm-builder", - "core/utils/wasm-builder-runner", - "core/wasm-interface", - "srml/support", - "srml/support/procedural", - "srml/support/procedural/tools", - "srml/support/procedural/tools/derive", - "srml/support/test", - "srml/authorship", - "srml/assets", - "srml/aura", - "srml/balances", - "srml/contracts", - "srml/collective", - "srml/democracy", - "srml/elections", - "srml/elections-phragmen", - "srml/example", - "srml/executive", - "srml/finality-tracker", - "srml/generic-asset", - "srml/grandpa", - "srml/im-online", - "srml/authority-discovery", - "srml/indices", - "srml/membership", - "srml/metadata", - "srml/nicks", - "srml/offences", - "srml/randomness-collective-flip", - "srml/scored-pool", - "srml/session", - "srml/staking", - "srml/staking/reward-curve", - "srml/sudo", - "srml/system", - "srml/system/rpc", - "srml/timestamp", - "srml/treasury", - "srml/transaction-payment", - "srml/utility", - "node/cli", - "node/executor", - "node/primitives", - "node/rpc", - "node/rpc-client", - "node/runtime", - "node/testing", - "node-template", - "subkey", - "test-utils/chain-spec-builder", + "bin/node-template", + "bin/node-template/runtime", + "bin/node/cli", + "bin/node/executor", + "bin/node/primitives", + "bin/node/rpc-client", + "bin/node/rpc", + "bin/node/runtime", + "bin/node/testing", + "bin/node/transaction-factory", + "bin/utils/subkey", + "bin/utils/chain-spec-builder", + "client", + "client/api", + "client/authority-discovery", + "client/basic-authorship", + "client/block-builder", + "client/chain-spec", + "client/chain-spec/derive", + "client/cli", + "client/consensus/aura", + "client/consensus/babe", + "client/consensus/pow", + "client/consensus/slots", + "client/consensus/uncles", + "client/db", + "client/executor", + "client/executor/common", + "client/executor/wasmi", + "client/executor/wasmtime", + "client/executor/runtime-test", + "client/finality-grandpa", + "client/tracing", + "client/keystore", + "client/network", + "client/network/test", + "client/network-gossip", + "client/offchain", + "client/peerset", + "client/rpc-servers", + "client/rpc", + "client/rpc-api", + "client/service", + "client/service/test", + "client/state-db", + "client/telemetry", + "client/transaction-pool", + "client/transaction-pool/graph", + "utils/wasm-builder-runner", + "utils/grafana-data-source", + "utils/grafana-data-source/test", + "frame/assets", + "frame/aura", + "frame/authority-discovery", + "frame/authorship", + "frame/babe", + "frame/balances", + "frame/collective", + "frame/contracts", + "frame/contracts/rpc", + "frame/contracts/rpc/runtime-api", + "frame/democracy", + "frame/elections-phragmen", + "frame/elections", + "frame/evm", + "frame/example", + "frame/executive", + "frame/finality-tracker", + "frame/generic-asset", + "frame/grandpa", + "frame/identity", + "frame/im-online", + "frame/indices", + "frame/membership", + "frame/metadata", + "frame/nicks", + "frame/offences", + "frame/randomness-collective-flip", + "frame/scored-pool", + "frame/session", + "frame/society", + "frame/staking", + "frame/staking/reward-curve", + "frame/sudo", + "frame/support", + "frame/support/procedural", + "frame/support/procedural/tools", + "frame/support/procedural/tools/derive", + "frame/support/test", + "frame/system", + "frame/system/rpc/runtime-api", + "frame/timestamp", + "frame/transaction-payment", + "frame/transaction-payment/rpc", + "frame/transaction-payment/rpc/runtime-api", + "frame/treasury", + "frame/utility", + "primitives/application-crypto", + "primitives/application-crypto/test", + "primitives/authority-discovery", + "primitives/authorship", + "primitives/block-builder", + "primitives/blockchain", + "primitives/consensus/aura", + "primitives/consensus/babe", + "primitives/consensus/common", + "primitives/consensus/pow", + "primitives/core", + "primitives/debug-derive", + "primitives/storage", + "primitives/externalities", + "primitives/finality-tracker", + "primitives/finality-grandpa", + "primitives/inherents", + "primitives/keyring", + "primitives/offchain", + "primitives/panic-handler", + "primitives/phragmen", + "primitives/rpc", + "primitives/runtime-interface", + "primitives/runtime-interface/proc-macro", + "primitives/runtime-interface/test-wasm", + "primitives/runtime-interface/test", + "primitives/serializer", + "primitives/session", + "primitives/api", + "primitives/api/proc-macro", + "primitives/api/test", + "primitives/arithmetic", + "primitives/io", + "primitives/runtime", + "primitives/sandbox", + "primitives/staking", + "primitives/std", + "primitives/version", + "primitives/state-machine", + "primitives/timestamp", + "primitives/test-primitives", + "primitives/transaction-pool", + "primitives/trie", + "primitives/wasm-interface", + "test-utils/client", + "test-utils/runtime", + "test-utils/runtime/client", + "utils/browser", + "utils/build-script-utils", + "utils/fork-tree", + "utils/frame/rpc/support", + "utils/frame/rpc/system", + "utils/wasm-builder", ] -[badges] -travis-ci = { repository = "paritytech/substrate", branch = "master" } -maintenance = { status = "actively-developed" } -is-it-maintained-issue-resolution = { repository = "paritytech/substrate" } -is-it-maintained-open-issues = { repository = "paritytech/substrate" } - [profile.release] # Substrate runtime requires unwinding. panic = "unwind" diff --git a/README.adoc b/README.adoc deleted file mode 100644 index bb23958bced1e..0000000000000 --- a/README.adoc +++ /dev/null @@ -1,526 +0,0 @@ -= Substrate -:Author: Substrate developers -:Revision: 0.2.0 -:toc: -:sectnums: - -== Intro in one sentence - -Substrate is a next-generation framework for blockchain innovation. - -== Description - -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 synchronize 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). - -Substrate is designed for use in one of three ways: - -**1. Trivial**: By running the Substrate binary `substrate` and configuring it with a genesis block that includes the current demonstration runtime. In this case, you just build Substrate, configure a JSON file, and launch your own blockchain. This affords you the least amount of customizability, primarily allowing you to change the genesis parameters of the various included runtime modules such as balances, staking, block-period, fees, and governance. - -**2. Modular**: By hacking together modules from the Substrate Runtime Module Library (SRML) into a new runtime and possibly altering or reconfiguring the Substrate client's block authoring logic. This affords you a very large amount of freedom over your blockchain's logic, letting you change datatypes, add or remove modules, and crucially, add your own modules. Much can be changed without touching the block authoring logic (since it is generic). If this is the case, then the existing Substrate binary can be used for block authoring and syncing. If the block authoring logic needs to be tweaked, then a new, altered block authoring binary must be built as a separate project and used by validators. This is how the Polkadot relay chain is built and should suffice for almost all circumstances in the near to mid-term. - -**3. Generic**: The entire SRML can be ignored and the entire runtime designed and implemented from scratch. If desired, this can be done in a language other than Rust, provided it can target WebAssembly. If the runtime can be made compatible with the existing client's block authoring logic, then you can simply construct a new genesis block from your Wasm blob and launch your chain with the existing Rust-based Substrate client. If not, then you'll need to alter the client's block authoring logic accordingly. This is probably a useless option for most projects right now, but provides complete flexibility allowing for a long-term, far-reaching upgrade path for the Substrate paradigm. - -=== The Basics of Substrate - -Substrate is a blockchain platform with a completely generic state transition function. That said, it does come with both standards and conventions (particularly regarding the Runtime Module Library) regarding underlying data structures. Roughly speaking, these core datatypes correspond to +trait+s in terms of the actual non-negotiable standard and generic +struct+s in terms of the convention. - -``` -Header := Parent + ExtrinsicsRoot + StorageRoot + Digest -Block := Header + Extrinsics + Justifications -``` - -=== Extrinsics - -Extrinsics in Substrate are pieces of information from "the outside world" that are contained in the blocks of the chain. You might think "ahh, that means *transactions*": in fact, no. Extrinsics fall into two broad categories of which only one is *transactions*. The other is known as *inherents*. The difference between these two is that transactions are signed and gossiped on the network and can be deemed useful *per se*. This fits the mold of what you would call transactions in Bitcoin or Ethereum. - -Inherents, meanwhile, are not passed on the network and are not signed. They represent data which describes the environment but which cannot call upon anything to prove it such as a signature. Rather they are assumed to be "true" simply because a sufficiently large number of validators have agreed on them being reasonable. - -To give an example, there is the timestamp inherent, which sets the current timestamp of the block. This is not a fixed part of Substrate, but does come as part of the Substrate Runtime Module Library to be used as desired. No signature could fundamentally prove that a block were authored at a given time in quite the same way that a signature can "prove" the desire to spend some particular funds. Rather, it is the business of each validator to ensure that they believe the timestamp is set to something reasonable before they agree that the block candidate is valid. - -Other examples include the parachain-heads extrinsic in Polkadot and the "note-missed-proposal" extrinsic used in the Substrate Runtime Module Library to determine and punish or deactivate offline validators. - - -=== 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. - -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 a snippet of the Polkadot API implementation as of PoC-3: - -```rust -impl_runtime_apis! { - impl client_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block) - } - - fn initialize_block(header: ::Header) { - Executive::initialize_block(&header) - } - } - // ---snip--- -} -``` - - -=== Inherent Extrinsics - -The Substrate Runtime Module Library includes functionality for timestamps and slashing. If used, these rely on "trusted" external information being passed in via inherent extrinsics. The Substrate reference block authoring client software will expect to be able to call into the runtime API with collated data (in the case of the reference Substrate authoring client, this is merely the current timestamp and which nodes were offline) in order to return the appropriate extrinsics ready for inclusion. If new inherent extrinsic types and data are to be used in a modified runtime, then it is this function (and its argument type) that would change. - -=== Block-authoring Logic - -In Substrate, there is a major distinction between blockchain *syncing* and block *authoring* ("authoring" is a more general term for what is called "mining" in Bitcoin). The first case might be referred to as a "full node" (or "light node" - Substrate supports both): authoring necessarily requires a synced node and, therefore, all authoring clients must necessarily be able to synchronize. However, the reverse is not true. The primary functionality that authoring nodes have which is not in "sync nodes" is threefold: transaction queue logic, inherent transaction knowledge and BFT consensus logic. BFT consensus logic is provided as a core element of Substrate and can be ignored since it is only exposed in the SDK under the `authorities()` API entry. - -Transaction queue logic in Substrate is designed to be as generic as possible, allowing a runtime to express which transactions are fit for inclusion in a block through the `initialize_block` and `apply_extrinsic` calls. However, more subtle aspects like prioritization and replacement policy must currently be expressed "hard coded" as part of the blockchain's authoring code. That said, Substrate's reference implementation for a transaction queue should be sufficient for an initial chain implementation. - -Inherent extrinsic knowledge is again somewhat generic, and the actual construction of the extrinsics is, by convention, delegated to the "soft code" in the runtime. If ever there needs to be additional extrinsic information in the chain, then both the block authoring logic will need to be altered to provide it into the runtime and the runtime's `inherent_extrinsics` call will need to use this extra information in order to construct any additional extrinsic transactions for inclusion in the block. - -== Roadmap - -=== So far - -- 0.1 "PoC-1": PBFT consensus, Wasm runtime engine, basic runtime modules. -- 0.2 "PoC-2": Libp2p - -=== In progress - -- AfG consensus -- Improved PoS -- Smart contract runtime module - -=== The future - -- Splitting out runtime modules into separate repo -- Introduce substrate executable (the skeleton-key runtime) -- Introduce basic but extensible transaction queue and block-builder and place them in the executable. -- DAO runtime module -- Audit - -== Trying out Substrate Node - -Substrate Node is Substrate's pre-baked blockchain client. You can run a development node locally or configure a new chain and launch your own global testnet. - -=== On Mac and Ubuntu - -To get going as fast as possible, there is a simple script that installs all required dependencies and installs Substrate into your path. Just open a terminal and run: - -[source, shell] ----- -curl https://getsubstrate.io -sSf | bash ----- - -You can start a local Substrate development chain with running `substrate --dev`. - -To create your own global network/cryptocurrency, you'll need to make a new Substrate Node chain specification file ("chainspec"). - -First let's get a template chainspec that you can edit. We'll use the "staging" chain, a sort of default chain that the node comes pre-configured with: - -[source, shell] ----- -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): - -[source, json] ----- - "timestamp": { - "minimumPeriod": 10 - }, ----- - -Now with this new chainspec file, you can build a "raw" chain definition for your new chain: - -[source, shell] ----- -substrate build-spec --chain ~/chainspec.json --raw > ~/mychain.json ----- - -This can be fed into Substrate: - -[source, shell] ----- -substrate --chain ~/mychain.json ----- - -It won't do much until you start producing blocks though, so to do that you'll need to use the `--validator` option together with passing the seed for the account(s) that is configured to be the initial authorities: - -[source, shell] ----- -substrate --chain ~/mychain.json --validator ----- - -You can distribute `mychain.json` so that everyone can synchronize and (depending on your authorities list) validate on your chain. - - -== Building - -=== Hacking on Substrate - -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: - -==== Linux and Mac - -For Unix-based operating systems, you should run the following commands: - -[source, shell] ----- -curl https://sh.rustup.rs -sSf | sh - -rustup update nightly -rustup target add wasm32-unknown-unknown --toolchain nightly -rustup update stable ----- - -You will also need to install the following packages: - - - Linux: -[source, shell] -sudo apt install cmake pkg-config libssl-dev git clang libclang-dev - -- Linux on ARM: -`rust-lld` is required for linking wasm, but is missing on non Tier 1 platforms. -So, use this https://github.com/Plume-org/Plume/blob/master/script/wasm-deps.sh[script] -to build `lld` and create the symlink `/usr/bin/rust-lld` to the build binary. - - - Mac: -[source, shell] -brew install cmake pkg-config openssl git llvm - -To finish installation of Substrate, jump down to <>. - -==== Windows - -If you are trying to set up Substrate on Windows, you should do the following: - -1. First, you will need to download and install "Build Tools for Visual Studio:" - - * You can get it at this link: https://aka.ms/buildtools - * Run the installation file: `vs_buildtools.exe` - * Please ensure the Windows 10 SDK component is included when installing the Visual C++ Build Tools. - * image:https://i.imgur.com/zayVLmu.png[image] - * Restart your computer. - -2. Next, you need to install Rust: - - * Detailed instructions are provided by the https://doc.rust-lang.org/book/ch01-01-installation.html#installing-rustup-on-windows[Rust Book]. - * Download from: https://www.rust-lang.org/tools/install - * Run the installation file: `rustup-init.exe` - > Note that it should not prompt you to install vs_buildtools since you did it in step 1. - * Choose "Default Installation." - * To get started, you need Cargo's bin directory (%USERPROFILE%\.cargo\bin) in your PATH environment variable. Future applications will automatically have the correct environment, but you may need to restart your current shell. - -3. Then, you will need to run some commands in CMD to set up your Wasm Build Environment: - - rustup update nightly - rustup update stable - rustup target add wasm32-unknown-unknown --toolchain nightly - -4. Then, you need to install LLVM: https://releases.llvm.org/download.html - -5. Next, you need to install OpenSSL, which we will do with `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 - -6. After, you need to add OpenSSL to your System Variables. Note that in order for the following commands to work, you need to use Windows Powershell: - - $env:OPENSSL_DIR = 'C:\Tools\vcpkg\installed\x64-windows-static' - $env:OPENSSL_STATIC = 'Yes' - [System.Environment]::SetEnvironmentVariable('OPENSSL_DIR', $env:OPENSSL_DIR, [System.EnvironmentVariableTarget]::User) - [System.Environment]::SetEnvironmentVariable('OPENSSL_STATIC', $env:OPENSSL_STATIC, [System.EnvironmentVariableTarget]::User) - -7. Finally, you need to install `cmake`: https://cmake.org/download/ - -==== Shared Steps - -Then, grab the Substrate source code: - -[source, shell] ----- -git clone https://github.com/paritytech/substrate.git -cd substrate ----- - -Then build the code: - -[source, shell] ----- -cargo build # Builds all native code ----- - -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 --release -- --dev - -Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run --release \-- --dev`. - -If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain specification that have been endowed with a testnet DOTs. We'll give each node a name and expose them so they are listed on link:https://telemetry.polkadot.io/#/Local%20Testnet[Telemetry]. You'll need two terminal windows open. - -We'll start Alice's Substrate node first on default TCP port 30333 with her chain database stored locally at `/tmp/alice`. The Bootnode ID of her node is `QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR`, which is generated from the `--node-key` value that we specify below: - -[source, shell] -cargo run --release \-- \ - --base-path /tmp/alice \ - --chain=local \ - --alice \ - --node-key 0000000000000000000000000000000000000000000000000000000000000001 \ - --telemetry-url ws://telemetry.polkadot.io:1024 \ - --validator - -In the second terminal, we'll run the following to start Bob's Substrate node on a different TCP port of 30334, and with his chain database stored locally at `/tmp/bob`. We'll specify a value for the `--bootnodes` option that will connect his node to Alice's Bootnode ID on TCP port 30333: - -[source, shell] -cargo run --release \-- \ - --base-path /tmp/bob \ - --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR \ - --chain=local \ - --bob \ - --port 30334 \ - --telemetry-url ws://telemetry.polkadot.io:1024 \ - --validator - -Additional Substrate CLI usage options are available and may be shown by running `cargo run \-- --help`. - -=== WASM binaries - -The WASM binaries are built during the normal `cargo build` process. To control the WASM binary building, -we support multiple environment variables: - -* `SKIP_WASM_BUILD` - Skips building any WASM binary. This is useful when only native should be recompiled. -* `BUILD_DUMMY_WASM_BINARY` - Builds dummy WASM binaries. These dummy binaries are empty and useful - for `cargo check` runs. -* `WASM_BUILD_TYPE` - Sets the build type for building WASM binaries. Supported values are `release` or `debug`. - By default the build type is equal to the build type used by the main build. -* `TRIGGER_WASM_BUILD` - Can be set to trigger a WASM build. On subsequent calls the value of the variable - needs to change. As WASM builder instructs `cargo` to watch for file changes - this environment variable should only be required in certain circumstances. -* `WASM_TARGET_DIRECTORY` - Will copy any build WASM binary to the given directory. The path needs - to be absolute. - -Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. -Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will -be `NODE_RUNTIME`. - -[[flaming-fir]] -=== Joining the Flaming Fir Testnet - -Flaming Fir is the new testnet for Substrate master (2.0) to test the latest development features. Please note that master is not compatible with the BBQ Birch, Charred Cherry, Dried Danta or Emberic Elm testnets. Ensure you have the dependencies listed above before compiling. - -Since Flaming Fir is targeting the master branch we make absolutely no guarantees of stability and/or persistence of the network. We might reset the chain at any time if it is necessary to deploy new changes. Currently, the validators are running with a client built from `d013bd900`, if you build from this commit you should be able to successfully sync, later commits may not work as new breaking changes may be introduced in master. - -Latest known working version: `a2a0eb5398d6223e531455b4c155ef053a4a3a2b` - -[source, shell] ----- -git clone https://github.com/paritytech/substrate.git -cd substrate -git checkout -b flaming-fir a2a0eb5398d6223e531455b4c155ef053a4a3a2b ----- - -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/#/Flaming%20Fir - -=== Joining the Emberic Elm Testnet - -Emberic Elm is the testnet for Substrate 1.0. Please note that 1.0 is not compatible with the BBQ Birch, Charred Cherry, Dried Danta or Flaming Fir testnets. -In order to join the Emberic Elm testnet you should build from the `v1.0` branch. Ensure you have the dependencies listed above before compiling. - -[source, shell] ----- -git clone https://github.com/paritytech/substrate.git -cd substrate -git checkout -b v1.0 origin/v1.0 ----- - -You can then follow the same steps for building and running as described above in <>. - -== Key management - -Keys in Substrate are stored in the keystore in the file system. To store keys into this keystore, -you need to use one of the two provided RPC calls. If your keys are encrypted or should be encrypted -by the keystore, you need to provide the key using one of the cli arguments `--password`, -`--password-interactive` or `--password-filename`. - -=== Recommended RPC call - -For most users who want to run a validator node, the `author_rotateKeys` RPC call is sufficient. -The RPC call will generate `N` Session keys for you and return their public keys. `N` is the number -of session keys configured in the runtime. The output of the RPC call can be used as input for the -`session::set_keys` transaction. - -``` -curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_rotateKeys", "id":1 }' localhost:9933 -``` - -=== Advanced RPC call - -If the Session keys need to match a fixed seed, they can be set individually key by key. The RPC call -expects the key seed and the key type. The key types supported by default in Substrate are listed -https://github.com/paritytech/substrate/blob/master/core/primitives/src/crypto.rs#L767[here], but the -user can declare any key type. - -``` -curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_insertKey", "params":["KEY_TYPE", "SEED", "PUBLIC"],"id":1 }' localhost:9933 -``` - -`KEY_TYPE` - needs to be replaced with the 4-character key type identifier. -`SEED` - is the seed of the key. -`PUBLIC` - public key for the given key. - -== Documentation - -=== Viewing documentation for Substrate packages - -You can generate documentation for a Substrate Rust package and have it automatically open in your web browser using https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo[rustdoc with Cargo], -(of the The Rustdoc Book), by running the following command: - -``` -cargo doc --package --open -``` - -Replacing `` with one of the following (i.e. `cargo doc --package substrate --open`): - -* All Substrate Packages -[source, shell] -substrate -* Substrate Core -[source, shell] -substrate, substrate-cli, substrate-client, substrate-client-db, -substrate-consensus-common, substrate-consensus-rhd, -substrate-executor, substrate-finality-grandpa, substrate-keyring, substrate-keystore, substrate-network, -substrate-network-libp2p, substrate-primitives, substrate-rpc, substrate-rpc-servers, -substrate-serializer, substrate-service, substrate-service-test, substrate-state-db, -substrate-state-machine, substrate-telemetry, substrate-test-client, -substrate-test-runtime, substrate-transaction-graph, substrate-transaction-pool, -substrate-trie -* Substrate Runtime -[source, shell] -sr-api, sr-io, sr-primitives, sr-sandbox, sr-std, sr-version -* Substrate Runtime Module Library (SRML) -[source, shell] -srml-assets, srml-balances, srml-consensus, srml-contracts, srml-council, srml-democracy, srml-example, -srml-executive, srml-metadata, srml-session, srml-staking, srml-support, srml-system, srml-timestamp, -srml-treasury -* Node -[source, shell] -node-cli, node-consensus, node-executor, node-network, node-primitives, node-runtime -* Subkey -[source, shell] -subkey - -=== Contributing to documentation for Substrate packages - -https://doc.rust-lang.org/1.9.0/book/documentation.html[Document source code] for Substrate packages by annotating the source code with documentation comments. - -Example (generic): -```markdown -/// Summary -/// -/// Description -/// -/// # Panics -/// -/// # Errors -/// -/// # Safety -/// -/// # Examples -/// -/// Summary of Example 1 -/// -/// ```rust -/// // insert example 1 code here -/// ``` -/// -``` - -* Important notes: -** Documentation comments must use annotations with a triple slash `///` -** Modules are documented using `//!` -``` -//! Summary (of module) -//! -//! Description (of module) -``` -* 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` -** `Examples` section includes examples of using the function or method -* 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 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)]` -* Hide documentation for items with `#[doc(hidden)]` - -=== Contributing to documentation (tests, extended examples, macros) for Substrate packages - -The code block annotations in the `# Example` section may be used as https://doc.rust-lang.org/1.9.0/book/documentation.html#documentation-as-tests[documentation as tests and for extended examples]. - -* 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[Documenting macros]. -** Documentation as tests examples are included when running `cargo test` - -== Contributing - -=== Contributing Guidelines - -include::CONTRIBUTING.adoc[] - -=== Contributor Code of Conduct - -include::CODE_OF_CONDUCT.adoc[] - -== License - -https://github.com/paritytech/substrate/blob/master/LICENSE[LICENSE] diff --git a/README.md b/README.md new file mode 100644 index 0000000000000..cd00013d1ae8a --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# Substrate · [![GitHub license](https://img.shields.io/github/license/paritytech/substrate)](LICENSE) [![GitLab Status](https://gitlab.parity.io/parity/substrate/badges/master/pipeline.svg)](https://gitlab.parity.io/parity/substrate/pipelines) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/CONTRIBUTING.adoc) + +Substrate is a next-generation framework for blockchain innovation. + +## Trying it out + +Simply go to [substrate.dev](https://substrate.dev) and follow the [getting started](https://substrate.dev/docs/en/overview/getting-started/) instructions. + +## Contributions & Code of Conduct + +Please follow the contributions guidelines as outlined in [`docs/CONTRIBUTING.adoc`](docs/CONTRIBUTING.adoc). In all communications and contributions, this project follows the [Contributor Covenant Code of Conduct](docs/CODE_OF_CONDUCT.adoc). + +## Security + +The security policy and procedures can be found in [`docs/SECURITY.md`](docs/SECURITY.md). + +## License + +Substrate is [GPL 3.0 licensed](LICENSE). diff --git a/bin/node-template/Cargo.toml b/bin/node-template/Cargo.toml new file mode 100644 index 0000000000000..aaaae647cf564 --- /dev/null +++ b/bin/node-template/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "node-template" +version = "2.0.0" +authors = ["Anonymous"] +build = "build.rs" +edition = "2018" + +[[bin]] +name = "node-template" +path = "src/main.rs" + +[dependencies] +futures = "0.3.1" +futures01 = { package = "futures", version = "0.1.29" } +ctrlc = { version = "3.1.3", features = ["termination"] } +log = "0.4.8" +tokio = "0.1.22" +parking_lot = "0.9.0" +codec = { package = "parity-scale-codec", version = "1.0.0" } +trie-root = "0.15.2" +sp-io = { version = "2.0.0", path = "../../primitives/io" } +sc-cli = { version = "2.0.0", path = "../../client/cli" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sc-executor = { version = "2.0.0", path = "../../client/executor" } +sc-service = { version = "2.0.0", path = "../../client/service" } +sp-inherents = { version = "2.0.0", path = "../../primitives/inherents" } +sc-transaction-pool = { version = "2.0.0", path = "../../client/transaction-pool" } +sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } +sc-network = { version = "0.8", path = "../../client/network" } +sc-consensus-aura = { version = "0.8", path = "../../client/consensus/aura" } +sp-consensus-aura = { version = "0.8", path = "../../primitives/consensus/aura" } +sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" } +grandpa = { version = "2.0.0", package = "sc-finality-grandpa", path = "../../client/finality-grandpa" } +grandpa-primitives = { version = "2.0.0", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" } +sc-client = { version = "2.0.0", path = "../../client/" } +node-template-runtime = { version = "2.0.0", path = "runtime" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sc-basic-authority = { path = "../../client/basic-authorship" } + +[build-dependencies] +vergen = "3.0.4" +build-script-utils = { version = "2.0.0", package = "substrate-build-script-utils", path = "../../utils/build-script-utils" } diff --git a/node-template/LICENSE b/bin/node-template/LICENSE similarity index 100% rename from node-template/LICENSE rename to bin/node-template/LICENSE diff --git a/node-template/README.md b/bin/node-template/README.md similarity index 100% rename from node-template/README.md rename to bin/node-template/README.md diff --git a/bin/node-template/build.rs b/bin/node-template/build.rs new file mode 100644 index 0000000000000..222cbb409285b --- /dev/null +++ b/bin/node-template/build.rs @@ -0,0 +1,9 @@ +use vergen::{ConstantsFlags, generate_cargo_keys}; + +const ERROR_MSG: &str = "Failed to generate metadata files"; + +fn main() { + generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG); + + build_script_utils::rerun_if_git_head_changed(); +} diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml new file mode 100644 index 0000000000000..b61ad25f466a4 --- /dev/null +++ b/bin/node-template/runtime/Cargo.toml @@ -0,0 +1,68 @@ +[package] +name = "node-template-runtime" +version = "2.0.0" +authors = ["Anonymous"] +edition = "2018" + +[dependencies] +aura = { version = "2.0.0", default-features = false, package = "pallet-aura", path = "../../../frame/aura" } +balances = { version = "2.0.0", default-features = false, package = "pallet-balances", path = "../../../frame/balances" } +frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" } +grandpa = { version = "2.0.0", default-features = false, package = "pallet-grandpa", path = "../../../frame/grandpa" } +indices = { version = "2.0.0", default-features = false, package = "pallet-indices", path = "../../../frame/indices" } +randomness-collective-flip = { version = "2.0.0", default-features = false, package = "pallet-randomness-collective-flip", path = "../../../frame/randomness-collective-flip" } +sudo = { version = "2.0.0", default-features = false, package = "pallet-sudo", path = "../../../frame/sudo" } +system = { version = "2.0.0", default-features = false, package = "frame-system", path = "../../../frame/system" } +timestamp = { version = "2.0.0", default-features = false, package = "pallet-timestamp", path = "../../../frame/timestamp" } +transaction-payment = { version = "2.0.0", default-features = false, package = "pallet-transaction-payment", path = "../../../frame/transaction-payment" } + +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +frame-executive = { version = "2.0.0", default-features = false, path = "../../../frame/executive" } +safe-mix = { version = "1.0.0", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-api = { version = "2.0.0", default-features = false, path = "../../../primitives/api" } +sp-block-builder = { path = "../../../primitives/block-builder", default-features = false} +sp-consensus-aura = { version = "0.8", default-features = false, path = "../../../primitives/consensus/aura" } +sp-core = { version = "2.0.0", default-features = false, path = "../../../primitives/core" } +sp-inherents = { path = "../../../primitives/inherents", default-features = false} +sp-io = { version = "2.0.0", default-features = false, path = "../../../primitives/io" } +sp-offchain = { version = "2.0.0", default-features = false, path = "../../../primitives/offchain" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-session = { version = "2.0.0", default-features = false, path = "../../../primitives/session" } +sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" } +sp-transaction-pool = { version = "2.0.0", default-features = false, path = "../../../primitives/transaction-pool" } +sp-version = { version = "2.0.0", default-features = false, path = "../../../primitives/version" } + +[build-dependencies] +wasm-builder-runner = { version = "1.0.4", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } + +[features] +default = ["std"] +std = [ + "aura/std", + "balances/std", + "codec/std", + "frame-executive/std", + "frame-support/std", + "grandpa/std", + "indices/std", + "randomness-collective-flip/std", + "safe-mix/std", + "serde", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "sudo/std", + "system/std", + "timestamp/std", + "transaction-payment/std", +] diff --git a/bin/node-template/runtime/build.rs b/bin/node-template/runtime/build.rs new file mode 100644 index 0000000000000..ed0e28ec0d140 --- /dev/null +++ b/bin/node-template/runtime/build.rs @@ -0,0 +1,27 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; + +fn main() { + build_current_project_with_rustflags( + "wasm_binary.rs", + WasmBuilderSource::Crates("1.0.8"), + // This instructs LLD to export __heap_base as a global variable, which is used by the + // external memory allocator. + "-Clink-arg=--export=__heap_base", + ); +} diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs new file mode 100644 index 0000000000000..4416cbf13ee00 --- /dev/null +++ b/bin/node-template/runtime/src/lib.rs @@ -0,0 +1,370 @@ +//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm. + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit="256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use sp_std::prelude::*; +use sp_core::OpaqueMetadata; +use sp_runtime::{ + ApplyExtrinsicResult, transaction_validity::TransactionValidity, generic, create_runtime_str, + impl_opaque_keys, MultiSignature +}; +use sp_runtime::traits::{ + BlakeTwo256, Block as BlockT, StaticLookup, Verify, ConvertInto, IdentifyAccount +}; +use sp_api::impl_runtime_apis; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use grandpa::AuthorityList as GrandpaAuthorityList; +use grandpa::fg_primitives; +use sp_version::RuntimeVersion; +#[cfg(feature = "std")] +use sp_version::NativeVersion; + +// A few exports that help ease life for downstream crates. +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use timestamp::Call as TimestampCall; +pub use balances::Call as BalancesCall; +pub use sp_runtime::{Permill, Perbill}; +pub use frame_support::{ + StorageValue, construct_runtime, parameter_types, + traits::Randomness, + weights::Weight, +}; + +/// An index to a block. +pub type BlockNumber = u32; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// The type for looking up accounts. We don't expect more than 4 billion of them, but you +/// never know... +pub type AccountIndex = u32; + +/// Balance of an account. +pub type Balance = u128; + +/// Index of a transaction in the chain. +pub type Index = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// Digest item type. +pub type DigestItem = generic::DigestItem; + +/// 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::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + + /// 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; + + impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + pub grandpa: Grandpa, + } + } +} + +/// This runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("node-template"), + impl_name: create_runtime_str!("node-template"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: RUNTIME_API_VERSIONS, +}; + +pub const MILLISECS_PER_BLOCK: u64 = 6000; + +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// These time units are defined in number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +/// The version infromation used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub const MaximumBlockWeight: Weight = 1_000_000; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const Version: RuntimeVersion = VERSION; +} + +impl system::Trait for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type Call = Call; + /// 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 = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous origin type. + type Origin = Origin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// Maximum weight of each block. + type MaximumBlockWeight = MaximumBlockWeight; + /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. + type MaximumBlockLength = MaximumBlockLength; + /// Portion of the block weight that is available to all normal transactions. + type AvailableBlockRatio = AvailableBlockRatio; + /// Version of the runtime. + type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type ModuleToIndex = ModuleToIndex; +} + +impl aura::Trait for Runtime { + type AuthorityId = AuraId; +} + +impl grandpa::Trait for Runtime { + type Event = Event; +} + +impl indices::Trait for Runtime { + /// The type for recording indexing into the account enumeration. If this ever overflows, there + /// will be problems! + type AccountIndex = AccountIndex; + /// 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 ubiquitous event type. + type Event = Event; +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + +impl timestamp::Trait for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 500; + pub const TransferFee: u128 = 0; + pub const CreationFee: u128 = 0; +} + +impl balances::Trait for Runtime { + /// The type for recording an account's balance. + type Balance = Balance; + /// What to do if an account's free balance gets zeroed. + type OnFreeBalanceZero = (); + /// What to do if an account is fully reaped from the system. + type OnReapAccount = System; + /// What to do if a new account is created. + type OnNewAccount = Indices; + /// The ubiquitous event type. + type Event = Event; + type DustRemoval = (); + type TransferPayment = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} + +parameter_types! { + pub const TransactionBaseFee: Balance = 0; + pub const TransactionByteFee: Balance = 1; +} + +impl transaction_payment::Trait for Runtime { + type Currency = balances::Module; + type OnTransactionPayment = (); + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = ConvertInto; + type FeeMultiplierUpdate = (); +} + +impl sudo::Trait for Runtime { + 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 where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Storage, Config, Event}, + Timestamp: timestamp::{Module, Call, Storage, Inherent}, + Aura: aura::{Module, Config, Inherent(Timestamp)}, + Grandpa: grandpa::{Module, Call, Storage, Config, Event}, + Indices: indices, + Balances: balances, + TransactionPayment: transaction_payment::{Module, Storage}, + Sudo: sudo, + // Used for the module template in `./template.rs` + TemplateModule: template::{Module, Call, Storage, Event}, + RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage}, + } +); + +/// The address format for describing accounts. +pub type Address = ::Source; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + system::CheckVersion, + system::CheckGenesis, + system::CheckEra, + system::CheckNonce, + system::CheckWeight, + transaction_payment::ChargeTransactionPayment +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive, Runtime, AllModules>; + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + Runtime::metadata().into() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + + fn random_seed() -> ::Hash { + RandomnessCollectiveFlip::random_seed() + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { + Executive::validate_transaction(tx) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { + Aura::slot_duration() + } + + fn authorities() -> Vec { + Aura::authorities() + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + opaque::SessionKeys::generate(seed) + } + } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + } +} diff --git a/node-template/runtime/src/template.rs b/bin/node-template/runtime/src/template.rs similarity index 88% rename from node-template/runtime/src/template.rs rename to bin/node-template/runtime/src/template.rs index db7bd24b0e419..a64a4c3216fe6 100644 --- a/node-template/runtime/src/template.rs +++ b/bin/node-template/runtime/src/template.rs @@ -6,9 +6,9 @@ /// For more guidance on Substrate modules, see the example module -/// https://github.com/paritytech/substrate/blob/master/srml/example/src/lib.rs +/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs -use support::{decl_module, decl_storage, decl_event, dispatch::Result}; +use frame_support::{decl_module, decl_storage, decl_event, dispatch}; use system::ensure_signed; /// The module's configuration trait. @@ -40,7 +40,7 @@ decl_module! { // Just a dummy entry point. // function that can be called by the external world as an extrinsics call // takes a parameter of the type `AccountId`, stores it and emits an event - pub fn do_something(origin, something: u32) -> Result { + pub fn do_something(origin, something: u32) -> dispatch::DispatchResult { // TODO: You only need this if you want to check it was signed. let who = ensure_signed(origin)?; @@ -69,10 +69,10 @@ decl_event!( mod tests { use super::*; - use primitives::H256; - use support::{impl_outer_origin, assert_ok, parameter_types}; - use sr_primitives::{ - traits::{BlakeTwo256, IdentityLookup}, testing::Header, weights::Weight, Perbill, + use sp_core::H256; + use frame_support::{impl_outer_origin, assert_ok, parameter_types, weights::Weight}; + use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, testing::Header, Perbill, }; impl_outer_origin! { @@ -106,6 +106,7 @@ mod tests { type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = (); + type ModuleToIndex = (); } impl Trait for Test { type Event = (); @@ -114,7 +115,7 @@ mod tests { // This function basically just builds a genesis storage key/value store according to // our desired mockup. - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> sp_io::TestExternalities { system::GenesisConfig::default().build_storage::().unwrap().into() } diff --git a/scripts/init.sh b/bin/node-template/scripts/init.sh similarity index 100% rename from scripts/init.sh rename to bin/node-template/scripts/init.sh diff --git a/bin/node-template/src/chain_spec.rs b/bin/node-template/src/chain_spec.rs new file mode 100644 index 0000000000000..fae9feaf5113b --- /dev/null +++ b/bin/node-template/src/chain_spec.rs @@ -0,0 +1,143 @@ +use sp_core::{Pair, Public, sr25519}; +use node_template_runtime::{ + AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, + SudoConfig, IndicesConfig, SystemConfig, WASM_BINARY, Signature +}; +use sp_consensus_aura::sr25519::{AuthorityId as AuraId}; +use grandpa_primitives::{AuthorityId as GrandpaId}; +use sc_service; +use sp_runtime::traits::{Verify, IdentifyAccount}; + +// Note this is the URL for the telemetry server +//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; + +/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. +pub type ChainSpec = sc_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, +} + +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +type AccountPublic = ::Signer; + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId where + AccountPublic: From<::Public> +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Helper function to generate an authority key for Aura +pub fn get_authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { + ( + get_from_seed::(s), + get_from_seed::(s), + ) +} + +impl Alternative { + /// Get an actual chain config from one of the alternatives. + pub(crate) fn load(self) -> Result { + Ok(match self { + Alternative::Development => ChainSpec::from_genesis( + "Development", + "dev", + || testnet_genesis(vec![ + get_authority_keys_from_seed("Alice"), + ], + get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + true), + vec![], + None, + None, + None, + None + ), + Alternative::LocalTestnet => ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + || testnet_genesis(vec![ + get_authority_keys_from_seed("Alice"), + get_authority_keys_from_seed("Bob"), + ], + get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + true), + vec![], + None, + None, + None, + None + ), + }) + } + + pub(crate) fn from(s: &str) -> Option { + match s { + "dev" => Some(Alternative::Development), + "" | "local" => Some(Alternative::LocalTestnet), + _ => None, + } + } +} + +fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, + root_key: AccountId, + endowed_accounts: Vec, + _enable_println: bool) -> GenesisConfig { + GenesisConfig { + system: Some(SystemConfig { + code: WASM_BINARY.to_vec(), + changes_trie_config: Default::default(), + }), + indices: Some(IndicesConfig { + ids: endowed_accounts.clone(), + }), + balances: Some(BalancesConfig { + balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), + vesting: vec![], + }), + sudo: Some(SudoConfig { + key: root_key, + }), + aura: Some(AuraConfig { + authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), + }), + grandpa: Some(GrandpaConfig { + authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), + }), + } +} diff --git a/bin/node-template/src/cli.rs b/bin/node-template/src/cli.rs new file mode 100644 index 0000000000000..16638c4af955d --- /dev/null +++ b/bin/node-template/src/cli.rs @@ -0,0 +1,128 @@ +use crate::service; +use futures::{future::{select, Map}, FutureExt, TryFutureExt, channel::oneshot, compat::Future01CompatExt}; +use std::cell::RefCell; +use tokio::runtime::Runtime; +pub use sc_cli::{VersionInfo, IntoExit, error}; +use sc_cli::{display_role, informant, parse_and_prepare, ParseAndPrepare, NoCustom}; +use sc_service::{AbstractService, Roles as ServiceRoles, Configuration}; +use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; +use crate::chain_spec; +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, +{ + type Config = Configuration<(), T>; + match parse_and_prepare::(&version, "substrate-node", args) { + ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, + |exit, _cli_args, _custom_args, config: 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: {}", display_role(&config)); + let runtime = Runtime::new().map_err(|e| format!("{:?}", e))?; + match config.roles { + ServiceRoles::LIGHT => run_until_exit( + runtime, + service::new_light(config)?, + exit + ), + _ => run_until_exit( + runtime, + service::new_full(config)?, + exit + ), + } + }), + ParseAndPrepare::BuildSpec(cmd) => cmd.run::(load_spec), + ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), + ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>| + Ok(new_full_start!(config).0), load_spec), + ParseAndPrepare::CustomCommand(_) => Ok(()) + }?; + + Ok(()) +} + +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: AbstractService, + E: IntoExit, +{ + let (exit_send, exit) = oneshot::channel(); + + let informant = informant::build(&service); + + let future = select(exit, informant) + .map(|_| Ok(())) + .compat(); + + runtime.executor().spawn(future); + + // we eagerly drop the service so that the internal exit future is fired, + // but we need to keep holding a reference to the global telemetry guard + let _telemetry = service.telemetry(); + + let service_res = { + let exit = e.into_exit(); + let service = service + .map_err(|err| error::Error::Service(err)) + .compat(); + let select = select(service, exit) + .map(|_| Ok(())) + .compat(); + runtime.block_on(select) + }; + + let _ = exit_send.send(()); + + // TODO [andre]: timeout this future #1318 + + use futures01::Future; + + let _ = runtime.shutdown_on_idle().wait(); + + service_res +} + +// handles ctrl-c +pub struct Exit; +impl IntoExit for Exit { + type Exit = Map, fn(Result<(), 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 || { + let exit_send = exit_send_cell.try_borrow_mut().expect("signal handler not reentrant; qed").take(); + if let Some(exit_send) = exit_send { + exit_send.send(()).expect("Error sending exit notification"); + } + }).expect("Error setting Ctrl-C handler"); + + exit.map(drop) + } +} diff --git a/bin/node-template/src/main.rs b/bin/node-template/src/main.rs new file mode 100644 index 0000000000000..2942bb68a37aa --- /dev/null +++ b/bin/node-template/src/main.rs @@ -0,0 +1,25 @@ +//! Substrate Node Template CLI library. + +#![warn(missing_docs)] +#![warn(unused_extern_crates)] + +mod chain_spec; +#[macro_use] +mod service; +mod cli; + +pub use sc_cli::{VersionInfo, IntoExit, error}; + +fn main() -> Result<(), cli::error::Error> { + let version = VersionInfo { + name: "Substrate Node", + commit: env!("VERGEN_SHA_SHORT"), + version: env!("CARGO_PKG_VERSION"), + executable_name: "node-template", + author: "Anonymous", + description: "Template Node", + support_url: "support.anonymous.an", + }; + + cli::run(std::env::args(), cli::Exit, version) +} diff --git a/bin/node-template/src/service.rs b/bin/node-template/src/service.rs new file mode 100644 index 0000000000000..ef7b44c6b6aff --- /dev/null +++ b/bin/node-template/src/service.rs @@ -0,0 +1,247 @@ +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. + +use std::sync::Arc; +use std::time::Duration; +use sc_client::LongestChain; +use node_template_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi}; +use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder}; +use sp_inherents::InherentDataProviders; +use sc_network::{construct_simple_protocol}; +use sc_executor::native_executor_instance; +pub use sc_executor::NativeExecutor; +use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; +use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; +use sc_basic_authority; + +// Our native executor instance. +native_executor_instance!( + pub Executor, + node_template_runtime::api::dispatch, + node_template_runtime::native_version, +); + +construct_simple_protocol! { + /// Demo protocol attachment for substrate. + pub struct NodeProtocol where Block = Block { } +} + +/// Starts a `ServiceBuilder` for a full service. +/// +/// Use this macro if you don't actually need the full service, but just the builder in order to +/// be able to perform chain operations. +macro_rules! new_full_start { + ($config:expr) => {{ + let mut import_setup = None; + let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + + let builder = sc_service::ServiceBuilder::new_full::< + node_template_runtime::opaque::Block, node_template_runtime::RuntimeApi, crate::service::Executor + >($config)? + .with_select_chain(|_config, backend| { + Ok(sc_client::LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client, _fetcher| { + let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); + let pool = sc_transaction_pool::BasicPool::new(config, pool_api); + let maintainer = sc_transaction_pool::FullBasicPoolMaintainer::new(pool.pool().clone(), client); + let maintainable_pool = sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer); + Ok(maintainable_pool) + })? + .with_import_queue(|_config, client, mut select_chain, transaction_pool| { + let select_chain = select_chain.take() + .ok_or_else(|| sc_service::Error::SelectChainRequired)?; + + let (grandpa_block_import, grandpa_link) = + grandpa::block_import::<_, _, _, node_template_runtime::RuntimeApi, _>( + client.clone(), &*client, select_chain + )?; + + let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( + grandpa_block_import.clone(), client.clone(), + ); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( + sc_consensus_aura::SlotDuration::get_or_compute(&*client)?, + aura_block_import, + Some(Box::new(grandpa_block_import.clone())), + None, + client, + inherent_data_providers.clone(), + Some(transaction_pool), + )?; + + import_setup = Some((grandpa_block_import, grandpa_link)); + + Ok(import_queue) + })?; + + (builder, import_setup, inherent_data_providers) + }} +} + +/// Builds a new service for a full client. +pub fn new_full(config: Configuration) + -> Result +{ + let is_authority = config.roles.is_authority(); + let force_authoring = config.force_authoring; + let name = config.name.clone(); + let disable_grandpa = config.disable_grandpa; + + // sentry nodes announce themselves as authorities to the network + // and should run the same protocols authorities do, but it should + // never actively participate in any consensus process. + let participates_in_consensus = is_authority && !config.sentry_mode; + + let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); + + let (block_import, grandpa_link) = + import_setup.take() + .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); + + let service = builder.with_network_protocol(|_| Ok(NodeProtocol::new()))? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) + )? + .build()?; + + if participates_in_consensus { + let proposer = sc_basic_authority::ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }; + + let client = service.client(); + let select_chain = service.select_chain() + .ok_or(ServiceError::SelectChainRequired)?; + + let can_author_with = + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + + let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( + sc_consensus_aura::SlotDuration::get_or_compute(&*client)?, + client, + select_chain, + block_import, + proposer, + service.network(), + inherent_data_providers.clone(), + force_authoring, + service.keystore(), + can_author_with, + )?; + + // the AURA authoring task is considered essential, i.e. if it + // fails we take down the service with it. + service.spawn_essential_task(aura); + } + + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if participates_in_consensus { + Some(service.keystore()) + } else { + None + }; + + let grandpa_config = grandpa::Config { + // FIXME #1578 make this available through chainspec + gossip_duration: Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: true, + keystore, + is_authority, + }; + + use futures::prelude::*; + + match (is_authority, disable_grandpa) { + (false, false) => { + // start the lightweight GRANDPA observer + service.spawn_task(grandpa::run_grandpa_observer( + grandpa_config, + grandpa_link, + service.network(), + service.on_exit(), + service.spawn_task_handle(), + )?.unit_error().compat()); + }, + (true, false) => { + // start the full GRANDPA voter + let voter_config = grandpa::GrandpaParams { + config: grandpa_config, + link: grandpa_link, + network: service.network(), + inherent_data_providers: inherent_data_providers.clone(), + on_exit: service.on_exit(), + telemetry_on_connect: Some(service.telemetry_on_connect_stream()), + voting_rule: grandpa::VotingRulesBuilder::default().build(), + executor: service.spawn_task_handle(), + }; + + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + service.spawn_essential_task(grandpa::run_grandpa_voter(voter_config)? + .unit_error().compat()); + }, + (_, true) => { + grandpa::setup_disabled_grandpa( + service.client(), + &inherent_data_providers, + service.network(), + )?; + }, + } + + Ok(service) +} + +/// Builds a new service for a light client. +pub fn new_light(config: Configuration) + -> Result +{ + let inherent_data_providers = InherentDataProviders::new(); + + ServiceBuilder::new_light::(config)? + .with_select_chain(|_config, backend| { + Ok(LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client, fetcher| { + let fetcher = fetcher + .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; + let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); + let pool = sc_transaction_pool::BasicPool::new(config, pool_api); + let maintainer = sc_transaction_pool::LightBasicPoolMaintainer::with_defaults(pool.pool().clone(), client, fetcher); + let maintainable_pool = sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer); + Ok(maintainable_pool) + })? + .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { + let fetch_checker = fetcher + .map(|fetcher| fetcher.checker().clone()) + .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; + let grandpa_block_import = grandpa::light_block_import::<_, _, _, RuntimeApi>( + client.clone(), backend, &*client.clone(), Arc::new(fetch_checker), + )?; + let finality_proof_import = grandpa_block_import.clone(); + let finality_proof_request_builder = + finality_proof_import.create_finality_proof_request_builder(); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, ()>( + sc_consensus_aura::SlotDuration::get_or_compute(&*client)?, + grandpa_block_import, + None, + Some(Box::new(finality_proof_import)), + client, + inherent_data_providers.clone(), + None, + )?; + + Ok((import_queue, finality_proof_request_builder)) + })? + .with_network_protocol(|_| Ok(NodeProtocol::new()))? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) + )? + .build() +} diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml new file mode 100644 index 0000000000000..1f7c90bc3a6c5 --- /dev/null +++ b/bin/node/cli/Cargo.toml @@ -0,0 +1,127 @@ +[package] +name = "node-cli" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Substrate node implementation in Rust." +build = "build.rs" +edition = "2018" +default-run = "substrate" + +[badges] +travis-ci = { repository = "paritytech/substrate", branch = "master" } +maintenance = { status = "actively-developed" } +is-it-maintained-issue-resolution = { repository = "paritytech/substrate" } +is-it-maintained-open-issues = { repository = "paritytech/substrate" } + +[[bin]] +name = "substrate" +path = "bin/main.rs" +required-features = ["cli"] + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +# third-party dependencies +codec = { package = "parity-scale-codec", version = "1.0.6" } +serde = { version = "1.0.102", features = ["derive"] } +futures01 = { package = "futures", version = "0.1.29" } +futures = { version = "0.3.1", features = ["compat"] } +hex-literal = "0.2.1" +jsonrpc-core = "14.0.3" +log = "0.4.8" +rand = "0.7.2" +structopt = "=0.3.7" + +# primitives +sp-authority-discovery = { version = "2.0.0", path = "../../../primitives/authority-discovery" } +sp-consensus-babe = { version = "0.8", path = "../../../primitives/consensus/babe" } +grandpa-primitives = { version = "2.0.0", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-timestamp = { version = "2.0.0", default-features = false, path = "../../../primitives/timestamp" } +sp-finality-tracker = { version = "2.0.0", default-features = false, path = "../../../primitives/finality-tracker" } +sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } +sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" } +sp-io = { version = "2.0.0", path = "../../../primitives/io" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } + +# client dependencies +sc-client-api = { version = "2.0.0", path = "../../../client/api" } +sc-client = { version = "2.0.0", path = "../../../client/" } +sc-chain-spec = { version = "2.0.0", path = "../../../client/chain-spec" } +sc-transaction-pool = { version = "2.0.0", path = "../../../client/transaction-pool" } +sp-transaction-pool = { version = "2.0.0", path = "../../../primitives/transaction-pool" } +sc-network = { version = "0.8", path = "../../../client/network" } +sc-consensus-babe = { version = "0.8", path = "../../../client/consensus/babe" } +grandpa = { version = "2.0.0", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } +sc-client-db = { version = "2.0.0", default-features = false, path = "../../../client/db" } +sc-offchain = { version = "2.0.0", path = "../../../client/offchain" } +sc-rpc = { version = "2.0.0", path = "../../../client/rpc" } +sc-basic-authority = { version = "2.0.0", path = "../../../client/basic-authorship" } +sc-service = { version = "2.0.0", default-features = false, path = "../../../client/service" } +sc-telemetry = { version = "2.0.0", path = "../../../client/telemetry" } +sc-authority-discovery = { version = "2.0.0", path = "../../../client/authority-discovery" } + +# frame dependencies +pallet-indices = { version = "2.0.0", path = "../../../frame/indices" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../../frame/timestamp" } +pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" } +frame-system = { version = "2.0.0", path = "../../../frame/system" } +pallet-balances = { version = "2.0.0", path = "../../../frame/balances" } +pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" } +frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" } +pallet-im-online = { version = "2.0.0", default-features = false, path = "../../../frame/im-online" } +pallet-authority-discovery = { version = "2.0.0", path = "../../../frame/authority-discovery" } + +# node-specific dependencies +node-runtime = { version = "2.0.0", path = "../runtime" } +node-rpc = { version = "2.0.0", path = "../rpc" } +node-primitives = { version = "2.0.0", path = "../primitives" } +node-executor = { version = "2.0.0", path = "../executor" } + +# CLI-specific dependencies +tokio = { version = "0.1.22", optional = true } +sc-cli = { version = "2.0.0", optional = true, path = "../../../client/cli" } +ctrlc = { version = "3.1.3", features = ["termination"], optional = true } +node-transaction-factory = { version = "2.0.0", optional = true, path = "../transaction-factory" } + +# WASM-specific dependencies +wasm-bindgen = { version = "0.2.57", optional = true } +wasm-bindgen-futures = { version = "0.4.7", optional = true } +browser-utils = { path = "../../../utils/browser", optional = true } + +[dev-dependencies] +sc-keystore = { version = "2.0.0", path = "../../../client/keystore" } +sc-consensus-babe = { version = "0.8", features = ["test-helpers"], path = "../../../client/consensus/babe" } +sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } +futures = "0.3.1" +tempfile = "3.1.0" + +[build-dependencies] +sc-cli = { version = "2.0.0", package = "sc-cli", path = "../../../client/cli" } +build-script-utils = { version = "2.0.0", package = "substrate-build-script-utils", path = "../../../utils/build-script-utils" } +structopt = "=0.3.7" +vergen = "3.0.4" + +[features] +default = ["cli", "wasmtime"] +browser = [ + "browser-utils", + "wasm-bindgen", + "wasm-bindgen-futures", +] +cli = [ + "sc-cli", + "node-transaction-factory", + "tokio", + "ctrlc", + "sc-service/rocksdb", + "node-executor/wasmi-errno", +] +wasmtime = [ + "cli", + "node-executor/wasmtime", + "sc-cli/wasmtime", + "sc-service/wasmtime", +] diff --git a/bin/node/cli/bin/main.rs b/bin/node/cli/bin/main.rs new file mode 100644 index 0000000000000..c766f3945c99f --- /dev/null +++ b/bin/node/cli/bin/main.rs @@ -0,0 +1,58 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate Node CLI + +#![warn(missing_docs)] + +use futures::channel::oneshot; +use futures::{future, FutureExt}; +use sc_cli::VersionInfo; + +use std::cell::RefCell; + +// handles ctrl-c +struct Exit; +impl sc_cli::IntoExit for Exit { + type Exit = future::Map, fn(Result<(), 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(|_| ()) + } +} + +fn main() -> Result<(), sc_cli::error::Error> { + let version = VersionInfo { + name: "Substrate Node", + commit: env!("VERGEN_SHA_SHORT"), + version: env!("CARGO_PKG_VERSION"), + executable_name: "substrate", + author: "Parity Technologies ", + description: "Generic substrate node", + support_url: "https://github.com/paritytech/substrate/issues/new", + }; + + node_cli::run(std::env::args(), Exit, version) +} diff --git a/bin/node/cli/browser-demo/.gitignore b/bin/node/cli/browser-demo/.gitignore new file mode 100644 index 0000000000000..0c6117d9fb83b --- /dev/null +++ b/bin/node/cli/browser-demo/.gitignore @@ -0,0 +1 @@ +pkg \ No newline at end of file diff --git a/bin/node/cli/browser-demo/README.md b/bin/node/cli/browser-demo/README.md new file mode 100644 index 0000000000000..2ff1cc54f5dbe --- /dev/null +++ b/bin/node/cli/browser-demo/README.md @@ -0,0 +1,9 @@ +# How to run this demo + +```sh +cargo install wasm-pack # If necessary + +wasm-pack build --target web --out-dir ./browser-demo/pkg --no-typescript --release ./.. -- --no-default-features --features "browser" + +xdg-open index.html +``` diff --git a/bin/node/cli/browser-demo/build.sh b/bin/node/cli/browser-demo/build.sh new file mode 100755 index 0000000000000..059ed9fe423b0 --- /dev/null +++ b/bin/node/cli/browser-demo/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +wasm-pack build --target web --out-dir ./browser-demo/pkg --no-typescript --release ./.. -- --no-default-features --features "browser" +python -m http.server 8000 diff --git a/bin/node/cli/browser-demo/favicon.png b/bin/node/cli/browser-demo/favicon.png new file mode 100644 index 0000000000000..8a4548ce34dfa Binary files /dev/null and b/bin/node/cli/browser-demo/favicon.png differ diff --git a/bin/node/cli/browser-demo/index.html b/bin/node/cli/browser-demo/index.html new file mode 100644 index 0000000000000..0b66b612f10f7 --- /dev/null +++ b/bin/node/cli/browser-demo/index.html @@ -0,0 +1,39 @@ + + + + + Substrate node + + + + + diff --git a/bin/node/cli/browser-demo/ws.js b/bin/node/cli/browser-demo/ws.js new file mode 100644 index 0000000000000..6da0c564278d3 --- /dev/null +++ b/bin/node/cli/browser-demo/ws.js @@ -0,0 +1,148 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +export default () => { + return { + dial: dial, + listen_on: (addr) => { + let err = new Error("Listening on WebSockets is not possible from within a browser"); + err.name = "NotSupportedError"; + throw err; + }, + }; +} + +/// Turns a string multiaddress into a WebSockets string URL. +// TODO: support dns addresses as well +const multiaddr_to_ws = (addr) => { + let parsed = addr.match(/^\/(ip4|ip6|dns4|dns6)\/(.*?)\/tcp\/(.*?)\/(ws|wss|x-parity-ws\/(.*)|x-parity-wss\/(.*))$/); + let proto = 'wss'; + if (parsed[4] == 'ws' || parsed[4] == 'x-parity-ws') { + proto = 'ws'; + } + let url = decodeURIComponent(parsed[5] || parsed[6] || ''); + if (parsed != null) { + if (parsed[1] == 'ip6') { + return proto + "://[" + parsed[2] + "]:" + parsed[3] + url; + } else { + return proto + "://" + parsed[2] + ":" + parsed[3] + url; + } + } + + let err = new Error("Address not supported: " + addr); + err.name = "NotSupportedError"; + throw err; +} + +// Attempt to dial a multiaddress. +const dial = (addr) => { + let ws = new WebSocket(multiaddr_to_ws(addr)); + let reader = read_queue(); + + return new Promise((resolve, reject) => { + // TODO: handle ws.onerror properly after dialing has happened + ws.onerror = (ev) => reject(ev); + ws.onmessage = (ev) => reader.inject_blob(ev.data); + ws.onclose = () => reader.inject_eof(); + ws.onopen = () => resolve({ + read: (function*() { while(ws.readyState == 1) { yield reader.next(); } })(), + write: (data) => { + if (ws.readyState == 1) { + ws.send(data); + return promise_when_ws_finished(ws); + } else { + return Promise.reject("WebSocket is closed"); + } + }, + shutdown: () => {}, + close: () => ws.close() + }); + }); +} + +// Takes a WebSocket object and returns a Promise that resolves when bufferedAmount is 0. +const promise_when_ws_finished = (ws) => { + if (ws.bufferedAmount == 0) { + return Promise.resolve(); + } + + return new Promise((resolve, reject) => { + setTimeout(function check() { + if (ws.bufferedAmount == 0) { + resolve(); + } else { + setTimeout(check, 100); + } + }, 2); + }) +} + +// Creates a queue reading system. +const read_queue = () => { + // State of the queue. + let state = { + // Array of promises resolving to `ArrayBuffer`s, that haven't been transmitted back with + // `next` yet. + queue: new Array(), + // If `resolve` isn't null, it is a "resolve" function of a promise that has already been + // returned by `next`. It should be called with some data. + resolve: null, + }; + + return { + // Inserts a new Blob in the queue. + inject_blob: (blob) => { + if (state.resolve != null) { + var resolve = state.resolve; + state.resolve = null; + + var reader = new FileReader(); + reader.addEventListener("loadend", () => resolve(reader.result)); + reader.readAsArrayBuffer(blob); + } else { + state.queue.push(new Promise((resolve, reject) => { + var reader = new FileReader(); + reader.addEventListener("loadend", () => resolve(reader.result)); + reader.readAsArrayBuffer(blob); + })); + } + }, + + // Inserts an EOF message in the queue. + inject_eof: () => { + if (state.resolve != null) { + var resolve = state.resolve; + state.resolve = null; + resolve(null); + } else { + state.queue.push(Promise.resolve(null)); + } + }, + + // Returns a Promise that yields the next entry as an ArrayBuffer. + next: () => { + if (state.queue.length != 0) { + return state.queue.shift(0); + } else { + if (state.resolve !== null) + throw "Internal error: already have a pending promise"; + return new Promise((resolve, reject) => { + state.resolve = resolve; + }); + } + } + }; +}; diff --git a/bin/node/cli/build.rs b/bin/node/cli/build.rs new file mode 100644 index 0000000000000..9e18fc669934d --- /dev/null +++ b/bin/node/cli/build.rs @@ -0,0 +1,52 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{fs, env, path::Path}; +use structopt::{StructOpt, clap::Shell}; +use sc_cli::{NoCustom, CoreParams}; +use vergen::{ConstantsFlags, generate_cargo_keys}; + +fn main() { + build_shell_completion(); + generate_cargo_keys(ConstantsFlags::all()).expect("Failed to generate metadata files"); + + build_script_utils::rerun_if_git_head_changed(); +} + +/// Build shell completion scripts for all known shells +/// Full list in https://github.com/kbknapp/clap-rs/blob/e9d0562a1dc5dfe731ed7c767e6cee0af08f0cf9/src/app/parser.rs#L123 +fn build_shell_completion() { + 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(); + + CoreParams::::clap().gen_completions("substrate-node", *shell, &path); +} diff --git a/node/cli/doc/shell-completion.adoc b/bin/node/cli/doc/shell-completion.adoc similarity index 100% rename from node/cli/doc/shell-completion.adoc rename to bin/node/cli/doc/shell-completion.adoc diff --git a/bin/node/cli/res/flaming-fir.json b/bin/node/cli/res/flaming-fir.json new file mode 100644 index 0000000000000..413fa3b6d7f90 --- /dev/null +++ b/bin/node/cli/res/flaming-fir.json @@ -0,0 +1,123 @@ +{ + "name": "Flaming Fir", + "id": "flamingfir5", + "bootNodes": [ + "/ip4/35.246.224.91/tcp/30333/p2p/QmaGKGpdm2iLiVCAnEcwrAhHxrcjMdGao4UubJxq7AF77n", + "/ip4/35.246.224.91/tcp/30334/ws/p2p/QmaGKGpdm2iLiVCAnEcwrAhHxrcjMdGao4UubJxq7AF77n", + "/ip4/35.246.210.11/tcp/30333/p2p/QmbS1xrmWyP5h4xsPwAS7CJEJNStsuAUDUzhggqDJtLpou", + "/ip4/35.246.210.11/tcp/30334/ws/p2p/QmbS1xrmWyP5h4xsPwAS7CJEJNStsuAUDUzhggqDJtLpou", + "/ip4/35.198.110.45/tcp/30333/p2p/QmdSHZLmwEL5Axz5JvWNE2mmxU7qyd7xHBFpyUfktgAdg7", + "/ip4/35.198.110.45/tcp/30334/ws/p2p/QmdSHZLmwEL5Axz5JvWNE2mmxU7qyd7xHBFpyUfktgAdg7", + "/ip4/35.198.114.154/tcp/30333/p2p/Qmeo7it7YGbhGZqkDGpgnR3xMRFSp6AutA9oTDZPQyny8h", + "/ip4/35.198.114.154/tcp/30334/ws/p2p/Qmeo7it7YGbhGZqkDGpgnR3xMRFSp6AutA9oTDZPQyny8h" + ], + "telemetryEndpoints": [ + [ + "wss://telemetry.polkadot.io/submit/", + 0 + ] + ], + "protocolId": "fir5", + "properties": { + "tokenDecimals": 15, + "tokenSymbol": "FIR" + }, + "forkBlocks": null, + "badBlocks": null, + "consensusEngine": null, + "genesis": { + "raw": { + "top": { + "0x2371e21684d2fae99bcb4d579242f74a8a2d09463effcc78a22d75b9cb87dffc": "0x0000000000000000", + "0xcec5070d609dd3497f72bde07fc96ba0e0cdd062e6eaf24295ad4ccfc41d4609": "0x10cafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367e23578cbc267982cfc0bf7be54cd952fa3c07631850880ca88e395e25f4812c7c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479f417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e297e8a1b8e637a062656eff12dc94bbbc3e254d9bb93bd44972f0a96c7fdde5b4de225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41ee225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41ee225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41e2a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b227615202d3e9c3bf075b44615f9ac4c28b8627079a219ff66e01655487c3bde52eb8e410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86ce410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86ce410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86cdc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3af6e62e9231c0424c1b747ffb5ccaedcb9fd6fddc2bfcb2db963c02db74c0c84dfe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310afe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310afe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310a", + "0x5f3e4907f716ac89b6347d15ececedca0b6a45321efae92aea15e0740ec7afe7": "0x00000000", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe7085268962a32b3f1cffce32ce1e5f6d6d3d633f7e21fd4e659402a2c62cab64ca": "0xfe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310a", + "0x3a636f6465": "0x0061736d010000000193033860037f7f7f017f60027f7f017f60027f7f0060017f0060037f7f7f0060057f7f7f7f7f0060047f7f7f7f0060017f017e60037f7e7e0060027e7e0060017e017f60017e017e60017e0060037e7e7f0060047e7e7f7e017e60047e7e7f7e0060057e7e7f7e7e0060037f7e7f017f60047f7e7e7f017f60067f7e7e7f7f7f017f6000017f60027f7e017e60047f7e7e7e017f60027f7e017f6000017e60047f7f7f7f017f60037f7f7e017e60027f7f017e60017f017f60037e7e7f017e60000060037e7f7f017f60067f7f7f7f7f7f017f60057f7f7f7f7f017f60027f7e0060067f7f7f7f7f7f0060047f7f7e7e0060057f7f7e7e7f0060057f7f7f7e7e0060027e7f0060067f7f7e7e7f7f0060067f7f7f7e7e7f0060077f7e7e7e7e7e7e0060087e7e7e7e7e7e7e7e017f60047f7e7e7e0060067f7f7f7f7e7e0060077f7f7e7e7f7f7f0060087f7f7f7f7f7e7e7f0060077f7f7f7e7e7f7f0060047f7f7f7f017e60077f7f7f7e7e7e7f0060057f7e7e7f7f0060037f7e7f0060047f7e7e7f0060057f7e7e7e7e0060067f7e7e7e7e7f0002ad0d2a03656e76196578745f6c6f6767696e675f6c6f675f76657273696f6e5f31000803656e76196578745f73746f726167655f7365745f76657273696f6e5f31000903656e761e6578745f68617368696e675f74776f785f3132385f76657273696f6e5f31000a03656e76196578745f73746f726167655f6765745f76657273696f6e5f31000b03656e761d6578745f6d6973635f7072696e745f757466385f76657273696f6e5f31000c03656e761b6578745f73746f726167655f636c6561725f76657273696f6e5f31000c03656e76206578745f68617368696e675f626c616b65325f3235365f76657273696f6e5f31000a03656e76286578745f73746f726167655f6368696c645f73746f726167655f6b696c6c5f76657273696f6e5f31000d03656e761f6578745f73746f726167655f6368696c645f6765745f76657273696f6e5f31000e03656e76216578745f73746f726167655f6368696c645f636c6561725f76657273696f6e5f31000f03656e761f6578745f73746f726167655f6368696c645f7365745f76657273696f6e5f31001003656e76236578745f63727970746f5f656432353531395f7665726966795f76657273696f6e5f31001103656e76236578745f63727970746f5f737232353531395f7665726966795f76657273696f6e5f31001103656e76226578745f73746f726167655f636c6561725f7072656669785f76657273696f6e5f31000c03656e761c6578745f6d6973635f7072696e745f6e756d5f76657273696f6e5f31000c03656e76206578745f73746f726167655f6368696c645f726f6f745f76657273696f6e5f31000b03656e76206578745f73616e64626f785f6d656d6f72795f6e65775f76657273696f6e5f31000103656e76256578745f73616e64626f785f6d656d6f72795f74656172646f776e5f76657273696f6e5f31000303656e76216578745f73616e64626f785f696e7374616e74696174655f76657273696f6e5f31001203656e761c6578745f73616e64626f785f696e766f6b655f76657273696f6e5f31001303656e76276578745f73616e64626f785f696e7374616e63655f74656172646f776e5f76657273696f6e5f31000303656e761c6578745f6d6973635f7072696e745f6865785f76657273696f6e5f31000c03656e76236578745f6f6666636861696e5f69735f76616c696461746f725f76657273696f6e5f31001403656e76286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f6765745f76657273696f6e5f31001503656e76346578745f6f6666636861696e5f6c6f63616c5f73746f726167655f636f6d706172655f616e645f7365745f76657273696f6e5f31001603656e76286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f7365745f76657273696f6e5f31000803656e76256578745f63727970746f5f656432353531395f67656e65726174655f76657273696f6e5f31001703656e761a6578745f73746f726167655f726f6f745f76657273696f6e5f31001803656e76226578745f73746f726167655f6368616e6765735f726f6f745f76657273696f6e5f31000b03656e761d6578745f68617368696e675f74776f785f36345f76657273696f6e5f31000a03656e76206578745f73616e64626f785f6d656d6f72795f6765745f76657273696f6e5f31001903656e76206578745f73616e64626f785f6d656d6f72795f7365745f76657273696f6e5f31001903656e76256578745f63727970746f5f737232353531395f67656e65726174655f76657273696f6e5f31001703656e76296578745f6f6666636861696e5f7375626d69745f7472616e73616374696f6e5f76657273696f6e5f31000b03656e76246578745f6f6666636861696e5f6e6574776f726b5f73746174655f76657273696f6e5f31001803656e76286578745f63727970746f5f737232353531395f7075626c69635f6b6579735f76657273696f6e5f31000703656e76216578745f63727970746f5f737232353531395f7369676e5f76657273696f6e5f31001a03656e76376578745f63727970746f5f736563703235366b315f65636473615f7265636f7665725f636f6d707265737365645f76657273696f6e5f31001b03656e761e6578745f616c6c6f6361746f725f6d616c6c6f635f76657273696f6e5f31001c03656e761c6578745f616c6c6f6361746f725f667265655f76657273696f6e5f31000303656e761a6578745f73746f726167655f726561645f76657273696f6e5f31001d03656e762a6578745f747269655f626c616b65325f3235365f6f7264657265645f726f6f745f76657273696f6e5f31000a03bc05ba051c1c030300001c1c1b1e1e1e040204001e060001010201021f030720190200060101011c0101010101010201060304030001010001012100000100010202040201020001010102030303020202021c020201020302020202020204020202020202020322010203020402041c022302020404082404022403081e030402040209080325260202020227060202040224030302020428242624080303020303020202020229081e040203040204022a2b010406050603031e1e02020202020403030304050402010402022a03020302020304050401040201062c040203030203021c02020202020202030202192403030302020202041c0402020202021c1c020202032d0303020409030303020202042a02030303040302040202010103030401030303030303030303030303030303030303032e2f04230330060202030202020202020202040204040602060404040204030302020202030302020904020306020201060202011e06230606060606060606060606060606060606060606060606060631021b1b0203020602031b1b1b021b0204021b04021b1b1b0402021b020201030501001b1b1b1b1b321b1b1b040406020303030202020302040402040402021c040404020404040403030302020302020203060303030303020303030203020204040202020224020202330202031e0302040202020203020205042602020302030302030202020203030302020203020202020202020202022904011c061c020202050302031c0202030203020202030202020219040203000101030302020606060303020102020302020201020106020404030303010104040504340202020402010502020404030303030205020201040206010401020101010101010402020104040302040102010301010401040304041c01010208010105040606040401050504040404060301010101000000003535363636370407017001f001f00105030100120619037f01418080c0000b7f0041e8a1c6000b7f0041e8a1c6000b078f0518066d656d6f72790200195f5f696e6469726563745f66756e6374696f6e5f7461626c6501000a5f5f646174615f656e6403010b5f5f686561705f62617365030209686173685f7465737400320c436f72655f76657273696f6e00af0312436f72655f657865637574655f626c6f636b00b00315436f72655f696e697469616c697a655f626c6f636b00b703114d657461646174615f6d6574616461746100b8031c426c6f636b4275696c6465725f6170706c795f65787472696e73696300b9031b426c6f636b4275696c6465725f66696e616c697a655f626c6f636b00bb0320426c6f636b4275696c6465725f696e686572656e745f65787472696e7369637300bf031c426c6f636b4275696c6465725f636865636b5f696e686572656e747300c20318426c6f636b4275696c6465725f72616e646f6d5f7365656400c3032b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e00c403214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b657200c8031e4772616e6470614170695f6772616e6470615f617574686f72697469657300d00315426162654170695f636f6e66696775726174696f6e00d10321417574686f72697479446973636f766572794170695f617574686f72697469657300d2031d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e636500d30311436f6e7472616374734170695f63616c6c00d40318436f6e7472616374734170695f6765745f73746f7261676500d603205472616e73616374696f6e5061796d656e744170695f71756572795f696e666f00d7032153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b65797300d80309c503010041010bef01404f554ac6054b4c5263c5028e01c9027bc40292039403950396039703980399039a039b039c039d039e039f03a003a103a203a303a403a503a603a703a803a903aa03ab03ac03ad03ce03f204a105a30583058f0553ae05cd05a605d805b905bb05b7053c3d3e83046544595a5b5c5d5e5f6a6b716c6d6e6f708803b501b401b601bc01e203bb01c501da04b304c004c8015150890287029d029c029b029a02b702b602b502c104ec01ed01f001ef01eb01f101df03de03ca02ab02fa03b504cb0281038203f603f503f703cc02cd02fe03ce02c401c301cf02c601bb02bc029c049a04d002a304ab0486028502d1028802d804d604d202dc0482048004d302810498029702d4029902c702c602d502e804e904ba01b901d602b302b202d702b402bf02b704b604d802bb04f004ef04d902820581058005da02c701db02bd02ae04ad04dc02b004e102fb01fc01fe01fd01fa01ff01f10484038303c205c505e103e003f803a204a104a0049f049d04a504a404af04b204b104ba04b904b804c504c404c304c204bf04be04bd04bc04db04d904e004df04de04dd04e504e604e704c804eb04ea04aa05a505a905a805a705d605b405b805d505d905d7050a98b646ba0506002000102b0b0600200010260b06002000102d0b0600200010270b0a00200020012002102f0b2801017f0240200210262203450d002003200020022001200120024b1b10db051a200010270b20030b0600200010310b1c01017f0240200010262201450d0020014100200010da051a0b20010bff0202017f037e230041206b220224002001ad42adfed5e4d485fda8d8007e42b9e0007c210302400240024002400240200141084b0d00200141014b0d0120010d02420021040c030b0240200141104b0d00200241106a2000290000200385420042adfed5e4d485fda8d800420010e005200241186a29030020022903107c200120006a41786a2900008521040c040b200120006a41786a2900002105200321040340200029000020048542adfed5e4d485fda8d8007e42178942adfed5e4d485fda8d8007e2003852103200041086a2100200442cf829ebbefefde82147c2104200141786a220141084b0d000b200320058521040c030b0240200141034b0d00200120006a417e6a33000042108620003300008420038521040c030b200120006a417c6a35000042208620003500008420038521040c020b200031000021040b200420038521040b20022004420042adfed5e4d485fda8d800420010e005200241086a290300210420022903002103200241206a2400200420037c42c300850b05001034000b2400410041988cc600ad4280808080f00084419f8cc600ad4280808080a00484100000000b1100418080c0004111419480c0001036000b3a01017f230041206b2203240020034204370310200342013702042003200136021c200320003602182003200341186a360200200320021041000b830301067f230041306b2202240020012802002103024002402001280204220441037422050d00410021060c010b200341046a2107410021060340200728020020066a2106200741086a2107200541786a22050d000b0b024002400240024002400240200141146a2802000d00200621070c010b024020040d0041bc80c000410041001038000b024002402006410f4b0d002003280204450d010b200620066a220720064f0d010b4101210541002107200241086a21060c010b2007417f4c0d01200241086a2106024020070d0041012105410021070c010b2007102a2205450d020b200241003602102002200736020c200220053602082002200241086a360214200241186a41106a200141106a290200370300200241186a41086a200141086a29020037030020022001290200370318200241146a41cc80c000200241186a10390d0220002006290200370200200041086a200641086a280200360200200241306a24000f0b103a000b1033000b41e480c0004133200241186a419881c000103b000b6c01017f230041306b2203240020032002360204200320013602002003411c6a41023602002003412c6a41013602002003420237020c200341f083c000360208200341013602242003200341206a360218200320033602282003200341046a360220200341086a20001041000bc40801087f230041c0006b22032400200341246a2001360200200341346a200241146a2802002204360200200341033a00382003412c6a2002280210220520044103746a36020020034280808080800437030820032000360220410021062003410036021820034100360210200320053602302003200536022802400240024002400240200228020822070d0020022802002108200228020422092004200420094b1b220a450d0141012104200020082802002008280204200128020c1100000d04200841086a210241012106034002402005280200200341086a200541046a280200110100450d00410121040c060b2006200a4f0d02200241046a210020022802002101200541086a2105200241086a210241012104200641016a2106200328022020012000280200200328022428020c110000450d000c050b0b20022802002108200228020422092002410c6a2802002205200520094b1b220a450d0041012104200020082802002008280204200128020c1100000d03200741106a2105200841086a21024101210603402003200541786a28020036020c2003200541106a2d00003a003820032005417c6a28020036020841002101410021000240024002400240200541086a2802000e0400010203000b2005410c6a2802002104410121000c020b02402005410c6a2802002207200328023422044f0d0041002100200328023020074103746a22072802044102470d0220072802002802002104410121000c020b41e489c000200720041038000b4100210020032802282207200328022c460d002003200741086a3602284100210020072802044102470d0020072802002802002104410121000b2003200436021420032000360210024002400240024002400240024020052802000e0404010006040b20032802282200200328022c470d010c050b200541046a2802002200200328023422044f0d01200328023020004103746a22002802044102470d04200028020028020021040c030b2003200041086a36022820002802044102470d03200028020028020021040c020b41e489c000200020041038000b200541046a28020021040b410121010b2003200436021c2003200136021802400240200541706a2802004101460d0020032802282204200328022c460d042003200441086a3602280c010b200541746a2802002204200328023422004f0d04200328023020044103746a21040b02402004280200200341086a200441046a280200110100450d00410121040c050b2006200a4f0d01200241046a210020022802002101200541246a2105200241086a210241012104200641016a2106200328022020012000280200200328022428020c110000450d000c040b0b0240200920064d0d00410121042003280220200820064103746a22052802002005280204200328022428020c1100000d030b410021040c020b419088c000412b41bc88c0001036000b41f489c000200420001038000b200341c0006a240020040b05001035000b810101017f230041c0006b220424002004200136020c2004200036020820042003360214200420023602102004412c6a41023602002004413c6a41033602002004420237021c2004419cafc000360218200441043602342004200441306a3602282004200441106a3602382004200441086a360230200441186a41acafc0001041000bad0101037f0240024002400240200028020022002802042203200028020822046b2002490d00200028020021030c010b200420026a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102a21030c010b200028020020032004102e21030b2003450d012000200436020420002003360200200028020821040b2000200420026a360208200320046a2001200210db051a41000f0b1033000b1035000b970401047f230041106b22022400200028020021000240024002400240024002402001418001490d002002410036020c2001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b0240200028020822032000280204470d00200341016a22042003490d05200341017422052004200520044b1b22044100480d050240024020030d002004102a21030c010b200028020020032004102e21030b2003450d042000200436020420002003360200200028020821030b200028020020036a20013a00002000200028020841016a3602080c020b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b0240024020002802042204200028020822036b2001490d00200028020021040c010b200320016a22052003490d03200441017422032005200320054b1b22034100480d030240024020040d002003102a21040c010b200028020020042003102e21040b2004450d022000200336020420002004360200200028020821030b2000200320016a360208200420036a2002410c6a200110db051a0b200241106a240041000f0b1033000b1035000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41cc80c000200241086a10392101200241206a240020010b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c2002418c86c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a419c86c0001041000b0d0020003502004101200110420b3101017f230041106b220224002002200136020c200220003602082002418084c0003602042002410136020020021043000bd40203027f017e037f230041306b22032400412721040240024020004290ce005a0d00200021050c010b412721040340200341096a20046a2206417c6a200020004290ce0080220542f0b17f7e7ca7220741ffff037141e4006e220841017441c284c0006a2f00003b00002006417e6a2008419c7f6c20076a41ffff037141017441c284c0006a2f00003b00002004417c6a2104200042ffc1d72f5621062005210020060d000b0b02402005a7220641e3004c0d00200341096a2004417e6a22046a2005a7220741ffff037141e4006e2206419c7f6c20076a41ffff037141017441c284c0006a2f00003b00000b024002402006410a480d00200341096a2004417e6a22046a200641017441c284c0006a2f00003b00000c010b200341096a2004417f6a22046a200641306a3a00000b2002200141dc9ec6004100200341096a20046a412720046b10452104200341306a240020040b6f01017f230041c0006b220124002001200036020c200141346a410136020020014201370224200141d49ec6003602202001410536023c2001200141386a36023020012001410c6a360238200141106a200141206a1037410141988cc60041072001280210200128021810c70500000b0c004283e1a2baf1cbc4f0370be40501057f024002402001450d00412b418080c4002000280200220641017122011b2107200120056a21080c010b200541016a210820002802002106412d21070b0240024020064104710d00410021020c010b4100210902402003450d002003210a200221010340200920012d000041c00171418001466a2109200141016a2101200a417f6a220a0d000b0b200820036a20096b21080b410121010240024020002802084101460d00200020072002200310460d012000280218200420052000411c6a28020028020c1100000f0b02402000410c6a280200220920084b0d00200020072002200310460d012000280218200420052000411c6a28020028020c1100000f0b0240024020064108710d0041002101200920086b22092108024002400240410120002d0030220a200a4103461b0e0402010001020b20094101762101200941016a41017621080c010b41002108200921010b200141016a210103402001417f6a2201450d0220002802182000280204200028021c280210110100450d000b41010f0b41012101200041013a003020004130360204200020072002200310460d0141002101200920086b220a2103024002400240410120002d0030220920094103461b0e0402010001020b200a4101762101200a41016a41017621030c010b41002103200a21010b200141016a2101024003402001417f6a2201450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210a41012101200028021820042005200028021c28020c1100000d01200341016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110100450d000c020b0b2000280204210a41012101200020072002200310460d00200028021820042005200028021c28020c1100000d00200841016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110100450d000b0b20010b5401017f024002402001418080c400460d0041012104200028021820012000411c6a2802002802101101000d010b024020020d0041000f0b2000280218200220032000411c6a28020028020c11000021040b20040b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c200241ec86c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41fc86c0001041000b8507010c7f200028021021030240024002400240200028020822044101460d0020030d012000280218200120022000411c6a28020028020c11000021030c030b2003450d010b0240024020020d00410021020c010b200120026a2105200041146a28020041016a21064100210720012103200121080340200341016a210902400240024020032c0000220a417f4a0d000240024020092005470d004100210b200521030c010b20032d0001413f71210b200341026a220921030b200a411f71210c0240200a41ff0171220a41df014b0d00200b200c41067472210a0c020b0240024020032005470d004100210d2005210e0c010b20032d0000413f71210d200341016a2209210e0b200d200b41067472210b0240200a41f0014f0d00200b200c410c7472210a0c020b02400240200e2005470d004100210a200921030c010b200e41016a2103200e2d0000413f71210a0b200b410674200c411274418080f0007172200a72220a418080c400470d020c040b200a41ff0171210a0b200921030b02402006417f6a2206450d00200720086b20036a21072003210820052003470d010c020b0b200a418080c400460d00024002402007450d0020072002460d0041002103200720024f0d01200120076a2c00004140480d010b200121030b2007200220031b21022003200120031b21010b20040d002000280218200120022000411c6a28020028020c1100000f0b4100210902402002450d002002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b0240200220096b200028020c2206490d002000280218200120022000411c6a28020028020c1100000f0b410021074100210902402002450d00410021092002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b200920026b20066a2209210a024002400240410020002d0030220320034103461b0e0402010001020b20094101762107200941016a410176210a0c010b4100210a200921070b200741016a2103024003402003417f6a2203450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210941012103200028021820012002200028021c28020c1100000d00200a41016a2103200028021c210a20002802182100034002402003417f6a22030d0041000f0b20002009200a280210110100450d000b41010f0b20030bd40801067f230041f0006b220424002004200336020c20042002360208410121052001210602402001418102490d00410020016b2107418002210803400240200820014f0d00200020086a2c000041bf7f4c0d0041002105200821060c020b2008417f6a21064100210520084101460d01200720086a21092006210820094101470d000b0b200420063602142004200036021020044100410520051b36021c200441dc9ec60041b287c00020051b3602180240024002400240200220014b22080d00200320014b0d00200220034b0d01024002402002450d0020012002460d00200120024d0d01200020026a2c00004140480d010b200321020b200420023602202002450d0220022001460d02200141016a210903400240200220014f0d00200020026a2c000041404e0d040b2002417f6a210820024101460d0420092002462106200821022006450d000c040b0b20042002200320081b360228200441306a41146a4103360200200441c8006a41146a4104360200200441d4006a410436020020044203370234200441b887c0003602302004410136024c2004200441c8006a3602402004200441186a3602582004200441106a3602502004200441286a360248200441306a41d087c0001041000b200441e4006a4104360200200441c8006a41146a4104360200200441d4006a4101360200200441306a41146a410436020020044204370234200441e087c0003602302004410136024c2004200441c8006a3602402004200441186a3602602004200441106a36025820042004410c6a3602502004200441086a360248200441306a418088c0001041000b200221080b024020082001460d00410121060240024002400240200020086a22092c00002202417f4a0d0041002105200020016a220621010240200941016a2006460d00200941026a210120092d0001413f7121050b2002411f712109200241ff017141df014b0d01200520094106747221010c020b2004200241ff0171360224200441286a21020c020b4100210020062107024020012006460d00200141016a210720012d0000413f7121000b200020054106747221010240200241ff017141f0014f0d0020012009410c747221010c010b41002102024020072006460d0020072d0000413f7121020b20014106742009411274418080f00071722002722201418080c400460d020b2004200136022441012106200441286a21022001418001490d00410221062001418010490d0041034104200141808004491b21060b200420083602282004200620086a36022c200441306a41146a4105360200200441ec006a4104360200200441e4006a4104360200200441c8006a41146a4106360200200441d4006a410736020020044205370234200441cc88c000360230200420023602582004410136024c2004200441c8006a3602402004200441186a3602682004200441106a3602602004200441246a3602502004200441206a360248200441306a41f488c0001041000b419088c000412b41bc88c0001036000b100020012000280200200028020410480b6f01037f230041206b22022400024020002802002001104e0d002001411c6a280200210320012802182104200242043703182002420137020c200241dc89c00036020820042003200241086a10390d0020002802042001104e2101200241206a240020010f0b200241206a240041010be70a02077f017e410121020240200128021841272001411c6a2802002802101101000d0041022103024002400240024002402000280200220241776a2200411e4d0d00200241dc00470d010c020b41f40021040240024020000e1f05010202000202020202020202020202020202020202020202030202020203050b41f20021040c040b41ee0021040c030b02400240024002400240024002402002104d0d00024002400240024002400240200241808004490d00200241808008490d0120024190fc476a4190fc0b490d0a200241e28b746a41e28d2c490d0a2002419fa8746a419f18490d0a200241dee2746a410e490d0a200241feffff0071419ef00a460d0a200241a9b2756a4129490d0a200241cb91756a410a4d0d0a410121030c0e0b20024180fe03714108762105419896c000210041002106200241ff017121040340200041026a2107200620002d000122036a2108024020002d000022002005460d00200020054b0d092008210620072100200741ea96c000470d010c090b20082006490d02200841a5024b0d03200641ea96c0006a2100024003402003450d012003417f6a210320002d00002106200041016a210020062004470d000c0c0b0b2008210620072100200741ea96c000470d000c080b0b20024180fe0371410876210541c99bc000210041002106200241ff017121040340200041026a2107200620002d000122036a2108024020002d000022002005460d00200020054b0d0720082106200721002007418f9cc000470d010c070b20082006490d03200841a6014b0d042006418f9cc0006a2100024003402003450d012003417f6a210320002d00002106200041016a210020062004470d000c0b0b0b20082106200721002007418f9cc000470d000c060b0b200620081047000b200841a502103f000b200620081047000b200841a601103f000b200241017267410276410773ad4280808080d0008421090c040b200241ffff0371210441b59dc00021034101210002400340200341016a21080240024020032d0000220641187441187522074100480d00200821030c010b200841cda0c000460d02200741ff007141087420032d0001722106200341026a21030b200420066b22044100480d0320004101732100200341cda0c000470d000c030b0b419088c000412b41bc88c0001036000b200241ffff03712104418f99c0002103410121000340200341016a21080240024020032d0000220641187441187522074100480d00200821030c010b200841c99bc000460d05200741ff007141087420032d0001722106200341026a21030b200420066b22044100480d0120004101732100200341c99bc000470d000b0b4101210320004101710d030b200241017267410276410773ad4280808080d0008421090b410321030c020b419088c000412b41bc88c0001036000b0b200221040b03402003210641dc0021004101210241012103024002400240024020060e0401020300010b024002400240024002402009422088a741ff01710e06050403020100050b200942ffffffff8f60834280808080c000842109410321030c060b200942ffffffff8f608342808080803084210941f5002100410321030c050b200942ffffffff8f608342808080802084210941fb002100410321030c040b20042009a72206410274411c7176410f712203413072200341d7006a2003410a491b210002402006450d002009427f7c42ffffffff0f83200942808080807083842109410321030c040b200942ffffffff8f6083428080808010842109410321030c030b200942ffffffff8f6083210941fd002100410321030c020b20012802184127200128021c2802101101000f0b41002103200421000b20012802182000200128021c280210110100450d000b0b20020b950201017f024002402000418010490d00024002400240024002400240200041808004490d002000410c7641706a2201418002490d0141f0a0c00020014180021038000b200041067641606a220141df074b0d01200141b88cc0006a2d0000220141c9004b0d02200141037441c0a1c0006a21010c060b2001419894c0006a2d00004106742000410676413f7172220141ff034b0d0220014190a6c0006a2d0000220141394b0d0320014103744190aac0006a21010c050b41d0a0c000200141e0071038000b41e0a0c000200141ca001038000b4180a1c00020014180041038000b4190a1c0002001413a1038000b200041037641f8ffffff017141a08ac0006a21010b200129030042012000413f71ad86834200520ba10201037f23004180016b2202240002400240024002400240200128020022034110710d0020034120710d012000ad41012001104221000c020b410021030340200220036a41ff006a2000410f712204413072200441d7006a2004410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141b087c0004102200220036a4180016a410020036b104521000c010b410021030340200220036a41ff006a2000410f712204413072200441376a2004410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141b087c0004102200220036a4180016a410020036b104521000b20024180016a240020000f0b20004180011047000b20004180011047000b0d0020003502004101200110420b1c00200128021841b6aec000410b2001411c6a28020028020c1100000b1c00200128021841c1aec000410e2001411c6a28020028020c1100000b6901037f230041206b220224002001411c6a280200210320012802182104200241086a41106a2000280200220141106a290200370300200241086a41086a200141086a2902003703002002200129020037030820042003200241086a10392101200241206a240020010b1500200120002802002200280200200028020410480b5e01017f230041306b220224002002200136020c20022000360208200241246a410136020020024201370214200241d49ec6003602102002410436022c2002200241286a3602202002200241086a360228200241106a418cafc0001041000b140020002802002001200028020428020c1101000bf30201067f410021040240024020024103712205450d00410420056b2205450d0020032005200520034b1b210441002105200141ff01712106034020042005460d01200220056a2107200541016a210520072d000022072006470d000b410121032007200141ff01714641016a41017120056a417f6a21050c010b200141ff017121060240024020034108490d002004200341786a22084b0d00200641818284086c210502400340200220046a220741046a2802002005732209417f73200941fffdfb776a7120072802002005732207417f73200741fffdfb776a7172418081828478710d01200441086a220420084d0d000b0b200420034b0d010b200220046a2109200320046b210241002103410021050240034020022005460d01200920056a2107200541016a210520072d000022072006470d000b410121032007200141ff01714641016a41017120056a417f6a21050b200520046a21050c010b200420031047000b20002005360204200020033602000b2601017f200028020022012802002001280204200028020428020020002802082802001049000b850804057f017e017f017e02400240024002402002450d00410020016b410020014103711b2103200241796a4100200241074b1b210441002105034002400240200120056a2d000022064118744118752207417f4a0d0042808080801021080240200641ee81c0006a2d0000417e6a220941024d0d0042808080808020210a0c070b0240024002400240024020090e03000102000b200541016a22062002490d024200210a0c090b4200210a200541016a220920024f0d08200120096a2d0000210902400240200641a07e6a2206410d4b0d000240024020060e0e0002020202020202020202020201000b200941e0017141a001460d0242808080808020210a0c0c0b02402009411874411875417f4c0d0042808080808020210a0c0c0b200941ff017141a001490d0142808080808020210a0c0b0b02402007411f6a41ff0171410b4b0d0002402009411874411875417f4c0d0042808080808020210a0c0c0b200941ff017141c001490d0142808080808020210a0c0b0b0240200941ff017141bf014d0d0042808080808020210a0c0b0b0240200741fe017141ee01460d0042808080808020210a0c0b0b2009411874411875417f4c0d0042808080808020210a0c0a0b42002108200541026a220620024f0d09200120066a2d000041c00171418001460d020c070b4200210a200541016a220920024f0d07200120096a2d0000210902400240200641907e6a220641044b0d000240024020060e050002020201000b200941f0006a41ff01714130490d0242808080808020210a0c0b0b02402009411874411875417f4c0d0042808080808020210a0c0b0b200941ff0171419001490d0142808080808020210a0c0a0b0240200941ff017141bf014d0d0042808080808020210a0c0a0b02402007410f6a41ff017141024d0d0042808080808020210a0c0a0b2009411874411875417f4c0d0042808080808020210a0c090b200541026a220620024f0d07200120066a2d000041c00171418001470d0642002108200541036a220620024f0d08200120066a2d000041c00171418001460d01428080808080e000210a42808080801021080c080b42808080808020210a4280808080102108200120066a2d000041c00171418001470d070b200641016a21050c010b0240200320056b4103710d000240200520044f0d000340200120056a220641046a280200200628020072418081828478710d01200541086a22052004490d000b0b200520024f0d010340200120056a2c00004100480d022002200541016a2205470d000c040b0b200541016a21050b20052002490d000b0b20002001360204200041086a2002360200200041003602000f0b428080808080c000210a42808080801021080c010b420021080b2000200a2008842005ad84370204200041013602000b02000ba20401077f230041306b220324000240024020020d00410021040c010b200341286a210502400240024002400340024020002802082d0000450d0020002802004188b0c0004104200028020428020c1100000d050b2003410a3602282003428a808080103703202003200236021c200341003602182003200236021420032001360210200341086a410a200120021056024002400240024020032802084101470d00200328020c210403402003200420032802186a41016a2204360218024002402004200328022422064f0d00200328021421070c010b200328021422072004490d00200641054f0d072003280210200420066b22086a22092005460d0420092005200610dd05450d040b200328021c22092004490d0220072009490d0220032006200341106a6a41176a2d0000200328021020046a200920046b10562003280204210420032802004101460d000b0b2003200328021c3602180b200028020841003a0000200221040c010b200028020841013a0000200841016a21040b2000280204210920002802002106024020044520022004467222070d00200220044d0d03200120046a2c000041bf7f4c0d030b200620012004200928020c1100000d04024020070d00200220044d0d04200120046a2c000041bf7f4c0d040b200120046a2101200220046b22020d000b410021040c040b20064104103f000b20012002410020041049000b20012002200420021049000b410121040b200341306a240020040bf90101017f230041106b220224002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b20002002410c6a2001105a2101200241106a240020010b6001017f230041206b2202240020022000360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41f0afc000200241086a10392101200241206a240020010b0d00200028020020012002105a0b800201017f230041106b22022400200028020021002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b20002002410c6a2001105a2101200241106a240020010b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41f0afc000200241086a10392101200241206a240020010bdb0302047f057e230041d0006b2205240041012106024020002d00040d0020002d000521070240200028020022082d00004104710d0041012106200828021841eeafc000418cb0c000200741ff017122071b4102410320071b2008411c6a28020028020c1100000d014101210620002802002208280218200120022008411c6a28020028020c1100000d01410121062000280200220828021841f5adc20041022008411c6a28020028020c1100000d0120032000280200200428020c11010021060c010b0240200741ff01710d00410121062008280218418fb0c00041032008411c6a28020028020c1100000d01200028020021080b41012106200541013a00172005200541176a360210200829020821092008290210210a200541346a41d4afc000360200200520082902183703082008290220210b2008290228210c200520082d00303a00482008290200210d2005200c3703402005200b3703382005200a370328200520093703202005200d3703182005200541086a360230200541086a20012002105a0d00200541086a41f5adc2004102105a0d002003200541186a200428020c1101000d00200528023041ecafc0004102200528023428020c11000021060b200041013a0005200020063a0004200541d0006a240020000bf30202047f057e230041d0006b2203240041012104024020002d00080d00200028020421050240200028020022062d00004104710d0041012104200628021841eeafc0004195b0c00020051b4102410120051b2006411c6a28020028020c1100000d0120012000280200200228020c11010021040c010b024020050d004101210420062802184196b0c00041022006411c6a28020028020c1100000d01200028020021060b41012104200341013a00172003200341176a3602102006290208210720062902102108200341346a41d4afc00036020020032006290218370308200629022021092006290228210a200320062d00303a00482006290200210b2003200a3703402003200937033820032008370328200320073703202003200b3703182003200341086a3602302001200341186a200228020c1101000d00200328023041ecafc0004102200328023428020c11000021040b200020043a00082000200028020441016a360204200341d0006a240020000bf40202037f057e230041d0006b2203240041012104024020002d00040d0020002d000521040240200028020022052d00004104710d000240200441ff0171450d0041012104200528021841eeafc00041022005411c6a28020028020c1100000d02200028020021050b20012005200228020c11010021040c010b0240200441ff01710d0041012104200528021841d3afc00041012005411c6a28020028020c1100000d01200028020021050b41012104200341013a00172003200341176a3602102005290208210620052902102107200341346a41d4afc000360200200320052902183703082005290220210820052902282109200320052d00303a00482005290200210a200320093703402003200837033820032007370328200320063703202003200a3703182003200341086a3602302001200341186a200228020c1101000d00200328023041ecafc0004102200328023428020c11000021040b200041013a0005200020043a0004200341d0006a240020000b6401027f230041206b220224002001411c6a280200210320012802182101200241086a41106a200041106a290200370300200241086a41086a200041086a2902003703002002200029020037030820012003200241086a10392100200241206a240020000bc30f020d7f017e230041206b220324004101210402400240200228021841222002411c6a2802002802101101000d000240024020010d00410021050c010b200020016a21062000210741002105410021080240034020072109200741016a210a02400240024020072c0000220b417f4a0d0002400240200a2006470d004100210c200621070c010b20072d0001413f71210c200741026a220a21070b200b411f7121040240200b41ff0171220b41df014b0d00200c200441067472210b0c020b0240024020072006470d004100210d2006210e0c010b20072d0000413f71210d200741016a220a210e0b200d200c41067472210c0240200b41f0014f0d00200c2004410c7472210b0c020b02400240200e2006470d004100210b200a21070c010b200e41016a2107200e2d0000413f71210b0b200c4106742004411274418080f0007172200b72220b418080c400470d020c040b200b41ff0171210b0b200a21070b4102210a024002400240024002400240200b41776a220c411e4d0d00200b41dc00470d010c020b41f400210e02400240200c0e1f05010202000202020202020202020202020202020202020202030202020203050b41f200210e0c040b41ee00210e0c030b02400240200b104d0d00024002400240024002400240024002400240200b41808004490d00200b41808008490d01200b4190fc476a4190fc0b490d09200b41e28b746a41e28d2c490d09200b419fa8746a419f18490d09200b41dee2746a410e490d09200b41feffff0071419ef00a460d09200b41a9b2756a4129490d09200b41cb91756a410a4d0d090c0e0b200b4180fe0371410876210f419896c000210c410021040340200c41026a210d2004200c2d0001220a6a210e0240200c2d0000220c200f460d00200c200f4b0d08200e2104200d210c200d41ea96c000470d010c080b200e2004490d02200e41a5024b0d03200441ea96c0006a210c02400340200a450d01200a417f6a210a200c2d00002104200c41016a210c2004200b41ff0171470d000c0b0b0b200e2104200d210c200d41ea96c000470d000c070b0b200b4180fe0371410876210f41c99bc000210c410021040340200c41026a210d2004200c2d0001220a6a210e0240200c2d0000220c200f460d00200c200f4b0d06200e2104200d210c200d418f9cc000470d010c060b200e2004490d03200e41a6014b0d042004418f9cc0006a210c02400340200a450d01200a417f6a210a200c2d00002104200c41016a210c2004200b41ff0171470d000c0a0b0b200e2104200d210c200d418f9cc000470d000c050b0b2004200e1047000b200e41a502103f000b2004200e1047000b200e41a601103f000b200b41ffff0371210e41b59dc000210a4101210c02400340200a41016a210d02400240200a2d00002204411874411875220f4100480d00200d210a0c010b200d41cda0c000460d02200f41ff0071410874200a2d0001722104200a41026a210a0b200e20046b220e4100480d03200c410173210c200a41cda0c000470d000c030b0b419088c000412b41bc88c0001036000b200b41ffff0371210e418f99c000210a4101210c0340200a41016a210d02400240200a2d00002204411874411875220f4100480d00200d210a0c010b200d41c99bc000460d04200f41ff0071410874200a2d0001722104200a41026a210a0b200e20046b220e4100480d01200c410173210c200a41c99bc000470d000b0b200c4101710d050b200b41017267410276410773ad4280808080d0008421104103210a0c020b419088c000412b41bc88c0001036000b0b200b210e0b2003200136020420032000360200200320053602082003200836020c0240024020082005490d0002402005450d0020052001460d00200520014f0d01200020056a2c000041bf7f4c0d010b02402008450d0020082001460d00200820014f0d01200020086a2c000041bf7f4c0d010b2002280218200020056a200820056b200228021c28020c110000450d01410121040c060b20032003410c6a3602182003200341086a36021420032003360210200341106a1057000b0340200a210c4101210441dc0021054101210a024002400240024002400240200c0e0402010500020b02400240024002402010422088a741ff01710e06050302010006050b201042ffffffff8f60834280808080308421104103210a41f50021050c070b201042ffffffff8f60834280808080208421104103210a41fb0021050c060b200e2010a7220c410274411c7176410f71220a413072200a41d7006a200a410a491b21050240200c450d002010427f7c42ffffffff0f832010428080808070838421100c050b201042ffffffff8f60834280808080108421100c040b201042ffffffff8f608321104103210a41fd0021050c040b4100210a200e21050c030b4101210a0240200b418001490d004102210a200b418010490d0041034104200b41808004491b210a0b200a20086a21050c040b201042ffffffff8f60834280808080c0008421100b4103210a0b20022802182005200228021c2802101101000d050c000b0b200820096b20076a210820062007470d000b0b2005450d0020052001460d00200520014f0d02200020056a2c000041bf7f4c0d020b410121042002280218200020056a200120056b200228021c28020c1100000d0020022802184122200228021c28021011010021040b200341206a240020040f0b20002001200520011049000b1c00200128021841dc9ec60041052001411c6a28020028020c1100000bf20301087f20002802042102024002400240024020002802004101460d00200041086a28020022002001106720004103742200450d01200220006a2103200141086a2104034020022802002105200241046a28020022002001106702400240200141046a22062802002207200428020022086b2000490d00200128020021070c010b200820006a22092008490d05200741017422082009200820094b1b22084100480d050240024020070d002008102a21070c010b200128020020072008102e21070b2007450d042001200736020020062008360200200428020021080b2004200820006a360200200720086a2005200010db051a200241086a22022003470d000c020b0b2000410c6a28020022002001106720004103742200450d00200220006a2103200141086a2104034020022802002105200241046a28020022002001106702400240200141046a22062802002207200428020022086b2000490d00200128020021070c010b200820006a22092008490d04200741017422082009200820094b1b22084100480d040240024020070d002008102a21070c010b200128020020072008102e21070b2007450d032001200736020020062008360200200428020021080b2004200820006a360200200720086a2005200010db051a200241086a22022003470d000b0b0f0b1033000b1035000be10601037f0240024002402000413f4b0d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d03200241017422042003200420034b1b22044100480d030240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20004102743a00000f0b0240200041808001490d0002402000418080808004490d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a000002400240200141046a2802002203200428020022026b4104490d00200128020021030c010b200241046a22042002490d04200341017422022004200220044b1b22024100480d040240024020030d002002102a21030c010b200128020020032002102e21030b2003450d0320012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20003600000f0b02400240200141046a2802002203200141086a28020022026b4104490d00200128020021030c010b200241046a22042002490d03200341017422022004200220044b1b22024100480d030240024020030d002002102a21030c010b200128020020032002102e21030b2003450d0220012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20004102744102723600000f0b02400240200141046a2802002203200141086a28020022026b4102490d00200128020021030c010b200241026a22042002490d02200341017422022004200220044b1b22024100480d020240024020030d002002102a21030c010b200128020020032002102e21030b2003450d0120012003360200200141046a2002360200200141086a28020021020b200141086a200241026a360200200320026a20004102744101723b00000f0b1033000b1035000bc91b010a7f230041106b220324002001200210670240024002402001450d00200141d8006c2104410021050340200020056a220641046a2802002107200641086a28020022082002106702400240200241046a2209280200220a200241086a2201280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d04200a410174220b200c200b200c4b1b220b4100480d0402400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d032002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a200641d4006a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0420084101742207200b2007200b4b1b22074100480d040240024020080d002007102a210b0c010b200228020020082007102e210b0b200b450d032002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a000002402006410c6a2d0000220841024b0d0002400240024020080e03000102000b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d072008410174220a200b200a200b4b1b220a4100480d070240024020080d00200a102a210b0c010b20022802002008200a102e210b0b200b450d062002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41003a0000200641146a2802002107200641186a280200220820021067024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d07200a410174220b200c200b200c4b1b220b4100480d0702400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d062002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a0c020b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d062008410174220a200b200a200b4b1b220a4100480d060240024020080d00200a102a210b0c010b20022802002008200a102e210b0b200b450d052002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41013a00002006410d6a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0620084101742207200b2007200b4b1b22074100480d060240024020080d002007102a210b0c010b200228020020082007102e210b0b200b450d052002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a0000200641146a2802002107200641186a280200220820021067024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d06200a410174220b200c200b200c4b1b220b4100480d0602400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d052002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a200641206a2802002107200641246a280200220820021067024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d06200a410174220b200c200b200c4b1b220b4100480d0602400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d052002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a2006410e6a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0620084101742207200b2007200b4b1b22074100480d060240024020080d002007102a210b0c010b200228020020082007102e210b0b200b450d052002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a00000c010b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d052008410174220a200b200a200b4b1b220a4100480d050240024020080d00200a102a210b0c010b20022802002008200a102e210b0b200b450d042002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41023a00002006410d6a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d0520084101742207200b2007200b4b1b22074100480d050240024020080d002007102a210b0c010b200228020020082007102e210b0b200b450d042002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a0000200641146a2802002107200641186a280200220820021067024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d05200a410174220b200c200b200c4b1b220b4100480d0502400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d042002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a200641206a2802002107200641246a280200220820021067024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d05200a410174220b200c200b200c4b1b220b4100480d0502400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d042002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a2006412c6a2802002107200641306a280200220820021067024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d05200a410174220b200c200b200c4b1b220b4100480d0502400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d042002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a2006410e6a2d0000220841044b0d000240024002400240024020080e050001020304000b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d092008410174220a200b200a200b4b1b220a4100480d090240024020080d00200a102a210b0c010b20022802002008200a102e210b0b200b450d082002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41003a00000c040b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d082008410174220a200b200a200b4b1b220a4100480d080240024020080d00200a102a210b0c010b20022802002008200a102e210b0b200b450d072002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41013a00000c030b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d072008410174220a200b200a200b4b1b220a4100480d070240024020080d00200a102a210b0c010b20022802002008200a102e210b0b200b450d062002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41023a00000c020b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d062008410174220a200b200a200b4b1b220a4100480d060240024020080d00200a102a210b0c010b20022802002008200a102e210b0b200b450d052002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41033a00000c010b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d052008410174220a200b200a200b4b1b220a4100480d050240024020080d00200a102a210b0c010b20022802002008200a102e210b0b200b450d042002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41043a00000b02400240200641346a2802004101460d002003200641386a2802002006413c6a28020028020c110200200328020021072003280208220820021067024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d06200a410174220b200c200b200c4b1b220b4100480d0602400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d052002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a2003280204450d012007102c0c010b200641386a2802002107200641c0006a280200220820021067024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d05200a410174220b200c200b200c4b1b220b4100480d0502400240200a0d00200b102a210a0c010b2002280200200a200b102e210a0b200a450d042002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a2007200810db051a0b200641c4006a200210662004200541d8006a2205470d000b0b200341106a24000f0b1033000b1035000bdc0601087f20002802042102024002400240024020002802004101460d00200041086a2802002200200110672000450d01200041186c2103200241146a2100200141086a2102200141046a21040340200041706a2802002105200041746a2802002206200110670240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d05200741017422082009200820094b1b22084100480d050240024020070d002008102a21070c010b200128020020072008102e21070b2007450d042001200736020020042008360200200228020021080b2002200820066a360200200720086a2005200610db051a2000417c6a280200210520002802002206200110670240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d05200741017422082009200820094b1b22084100480d050240024020070d002008102a21070c010b200128020020072008102e21070b2007450d042001200736020020042008360200200228020021080b2002200820066a360200200720086a2005200610db051a200041186a2100200341686a22030d000c020b0b2000410c6a2802002200200110672000450d00200041186c2103200241146a2100200141086a2102200141046a21040340200041706a2802002105200041746a2802002206200110670240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d04200741017422082009200820094b1b22084100480d040240024020070d002008102a21070c010b200128020020072008102e21070b2007450d032001200736020020042008360200200228020021080b2002200820066a360200200720086a2005200610db051a2000417c6a280200210520002802002206200110670240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d04200741017422082009200820094b1b22084100480d040240024020070d002008102a21070c010b200128020020072008102e21070b2007450d032001200736020020042008360200200228020021080b2002200820066a360200200720086a2005200610db051a200041186a2100200341686a22030d000b0b0f0b1033000b1035000b040041010bb60101017f230041c0006b2202240020024100360210200242013703082002410836021c20022001410c6a3602202002200241206a3602182002200241086a3602242002413c6a41013602002002420137022c200241d49ec6003602282002200241186a360238200241246a41b4b0c000200241286a10391a20012d0000417f6a41ff0171200141046a290200200235021042208620023502088410000240200228020c450d002002280208102c0b200241c0006a24000bbc0101037f02400240024002402000280200220041046a2802002203200041086a28020022046b2002490d00200028020021030c010b200420026a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102a21030c010b200028020020032004102e21030b2003450d0120002003360200200041046a2004360200200041086a28020021040b200041086a200420026a360200200320046a2001200210db051a41000f0b1033000b1035000ba70301047f230041106b22022400200028020021002002410036020c02400240200141ff004b0d00200220013a000c410121010c010b0240200141ff0f4b0d0020022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b0240200141ffff034b0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c010b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010b0240024002400240200041046a2802002203200041086a28020022046b2001490d00200028020021030c010b200420016a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102a21030c010b200028020020032004102e21030b2003450d0120002003360200200041046a2004360200200041086a28020021040b200041086a200420016a360200200320046a2002410c6a200110db051a200241106a240041000f0b1033000b1035000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41b4b0c000200241086a10392101200241206a240020010b040041000b02000b02000b950201057f230041f0026b22012400024020002802082202200028020c460d00200141b8016a4101722103200141e0016a210403402000200241b8016a36020820022d00002105200141b8016a200241016a41b70110db051a20054103460d01200141016a200141b8016a41b70110db051a200120053a00b8012003200141016a41b70110db051a02400240200541014b0d000240024020050e020001000b024020012802c001450d0020012802bc01102c0b20012d00c8014105490d0220012802f001450d0220012802ec01102c0c020b200410730c010b20012802a002450d00200128029c02102c0b20002802082202200028020c470d000b0b02402000280204450d002000280200102c0b200141f0026a24000bad0c01057f024002402000280200220141164b0d000240024002400240024002400240024002400240024002400240024020010e1700010f0f020f0f030405060708090f0a0f0b0c0d0f0f0f000b0240200041086a280200220141064b0d00024002400240024020010e0713130013010203130b200041106a280200450d122000410c6a280200102c0f0b200041106a280200450d112000410c6a280200102c0f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141186a2101200241686a22020d000b0b200041106a280200450d10200028020c102c0f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b200041106a280200450d0f200028020c102c0f0b200041106a280200450d0e2000410c6a280200102c0f0b02402000410c6a2802002202450d002000280204210120024190016c210203402001107320014190016a2101200241f07e6a22020d000b0b200041086a280200450d0d2000280204102c0f0b02402000410c6a2802002201450d0020002802042203200141f0006c6a2104034002402003410c6a2802002202450d0020032802042101200241246c210203400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012002415c6a22020d000b0b200341f0006a21010240200341086a280200450d002003280204102c0b2001210320012004470d000b0b200041086a280200450d0c2000280204102c0f0b0240200041086a2d00002201410f4b0d00410120017441bfbf03710d0c024020014106470d00200041106a280200450d0d2000410c6a280200102c0f0b200041106a280200450d0c2000410c6a280200102c0f0b200041146a280200450d0b200041106a280200102c0f0b200041086a280200450d0a2000280204102c0f0b200041086a2d0000416d6a220141014b0d090240024020010e020001000b200041106a280200450d0a2000410c6a280200102c0f0b200041106a280200450d092000410c6a280200102c0f0b20002d0004417f6a220141024b0d0802400240024020010e03000102000b2000410c6a280200450d0a200041086a280200102c0f0b200041086a220128020010732001280200102c0f0b2000410c6a220128020010732001280200102c0f0b20002d0004417f6a220141024b0d0702400240024020010e03000102000b2000410c6a280200450d09200041086a280200102c0f0b200041086a220128020010732001280200102c0f0b2000410c6a220128020010732001280200102c0f0b200041086a2802004101470d06200041106a280200450d062000410c6a280200102c0f0b20002d00044104470d052000410c6a280200450d05200041086a280200102c0f0b200041086a280200450d042000280204102c0f0b200041086a2d0000417e6a220141024b0d0302400240024020010e03000102000b200041106a280200450d052000410c6a280200102c0f0b200041346a280200450d04200041306a280200102c0f0b200041306a280200450d032000412c6a280200102c0f0b02402000280204220141024b0d00024020010e03040004040b200041086a220128020010732001280200102c0f0b2000412c6a220128020010732001280200102c0f0b02402000410c6a280200450d00200041086a280200102c0b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b200041186a280200450d012000280214102c0c010b02402000280204220141034b0d00024020010e0402000202020b2000410c6a280200450d01200041086a280200102c0f0b200041306a280200450d002000412c6a280200102c0f0b0ba205020c7f047e230041f0006b22022400200220011075024002400240024020022802000d00200128020441286e220341286c2204417f4c0d02200228020421050240024020040d00410821060c010b2004102a2206450d040b02402005450d00410021070340200241003a00682007220841016a210720012802042109417f210a410021040240024002400240034020092004460d01200241c8006a20046a2001280200220b2d00003a000020012009200a6a3602042001200b41016a3602002002200441016a220c3a0068200a417f6a210a200c2104200c4120470d000b200241286a41186a2204200241c8006a41186a290300370300200241286a41106a220a200241c8006a41106a290300370300200241286a41086a220d200241c8006a41086a290300370300200220022903483703282009200c6b220c4108490d01200b290001210e2001200b41096a3602002001200c41786a360204200241086a41086a220c200d290300370300200241086a41106a2209200a290300370300200241086a41186a220a20042903003703002002200229032837030820032008470d030240200841017422042007200420074b1b2203ad42287e220f422088a70d00200fa7220441004e0d030b1035000b200441ff0171450d00200241003a00680b200041003602002003450d052006102c0c050b0240024020080d002004102a21060c010b2006200841286c2004102e21060b2006450d060b2006200841286c6a22042002290308370300200c290300210f20092903002110200a29030021112004200e370320200441186a2011370300200441106a2010370300200441086a200f37030020072005470d000b0b2000200336020420002006360200200041086a20053602000c010b200041003602000b200241f0006a24000f0b103a000b1033000bcf0201067f0240024020012802042202450d00200128020022032d0000210420012002417f6a2205360204410121062001200341016a3602000240200441037122074103460d0002400240024020070e03000102000b20044102762107410021060c040b41012106024020050d000c040b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d03200141fcff03714102762107410021060c030b20054103490d01200341036a2d0000210620032f0001210720012002417c6a3602042001200341046a3602002007200641107472410874200472220141808004492106200141027621070c020b0240200441034d0d000c020b20054104490d012003280001210720012002417b6a3602042001200341056a36020020074180808080044921060c010b410121060b20002007360204200020063602000b800201077f230041106b2202240002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002006450d0020042d0001210720012003417e6a22063602042001200441026a3602002006450d0020042d0002210820012003417d6a22063602042001200441036a3602002006450d0020042d0003210620012003417c6a3602042001200441046a3602002002200110772002280200450d01200020022903003702042000410c6a200241086a280200360200200020074108742005722008411074722006411874723602000c020b200041003602040c010b200041003602040b200241106a24000be70101047f230041106b22022400200241086a20011075024002400240024020022802080d0002402001280204200228020c22034f0d00200041003602000c020b2003417f4c0d02024002400240024020030d00410121040c010b200310302204450d0120012802042003490d0220042001280200200310db051a200128020422052003490d062001200520036b3602042001200128020020036a3602000b2000200336020420002004360200200041086a20033602000c030b1033000b200041003602002004102c0c010b200041003602000b200241106a24000f0b103a000b200320051047000bcf0101067f024002402000280208220141ffffff3f712001470d0020014105742202417f4c0d00200028020021030240024020020d00410121040c010b2002102a2204450d020b024020010d0041000f0b20014105742105410021000340200420006a2202200320006a2206290000370000200241186a200641186a290000370000200241106a200641106a290000370000200241086a200641086a2900003700002005200041206a2200470d000b2001410574410575210002402001450d002004102c0b20000f0b103a000b1033000bbf0302077f027e230041106b220224000240024002402000280208220341146a2204417f4c0d000240024020040d00410121050c010b2004102a2205450d02200028020821030b200241003602082002200436020420022005360200200028020021062003200210670240024020022802042205200228020822076b2003490d00200228020021040c010b200720036a22042007490d03200541017422082004200820044b1b22084100480d030240024020050d002008102a21040c010b200228020020052008102e21040b2004450d022002200836020420022004360200200821050b2002200720036a2208360208200420076a2006200310db051a200041186a29030021092000290310210a02400240200520086b4110490d00200841106a21030c010b200841106a22032008490d03200541017422002003200020034b1b22004100480d030240024020050d002000102a21040c010b200420052000102e21040b2004450d022002200036020420022004360200200021050b200420086a220020093700082000200a37000020012902002003ad4220862004ad84100102402005450d002004102c0b200241106a24000f0b103a000b1033000b1035000b9203010a7f200041086a220228020021034100210420024100360200024002402003450d004100210541002106410021044100210702400340024002402004450d00200741057421080340200720034f0d062001200028020022096b2008460d02200920086a220a2001412010dd05450d020240200620076a220b20034f0d00200920056a20086a2209200a290000370000200941186a200a41186a290000370000200941106a200a41106a290000370000200941086a200a41086a290000370000200841206a2108200741016a22072003490d010c050b0b41fcb4c000200b20031038000b200028020020074105746a21080340200720034f0d0520012008460d0120082001412010dd05450d01200841206a2108200741016a22072003490d000b410021040c030b200541606a21052006417f6a2106200441016a2104200741016a22072003490d000b0b2004450d00200320074d0d00200028020020074105746a220820044105746b2008200320076b41057410dc051a0b2002200320046b3602000f0b41a8b4c000200720031038000bbd0101047f230041106b22022400200028020821032000280200210041012104200128021841d1afc00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d0003402002200036020c20022002410c6a41dc9ac50010621a200041016a21002003417f6a22030d000b20022d000421050b0240200541ff01710d002002280200220028021841d2afc00041012000411c6a28020028020c11000021040b200241106a240020040bf70405027f017e0a7f037e037f230041206b220224000240024020012802082203ad42d0007e2204422088a70d002004a72205417f4c0d00200128020021060240024020050d00410821070c010b2005102a2207450d020b0240024020030d00410021080c010b2006200341d0006c6a2109410021082007210a0340200241186a220b200641186a290300370300200241106a220c200641106a290300370300200241086a220d200641086a29030037030020022006290300370300200641c8006a280200220ead42307e2204422088a70d022004a72205417f4c0d02200641386a2903002104200641306a290300210f200641286a2903002110200641c0006a2802002101200629032021110240024020050d00410821120c010b2005102a2212450d040b200641d0006a210602400240200e0d00410021130c010b2001200e41306c6a211441002113201221050340200520012903003703002005200141086a290300370308200541106a200141106a290300370300200541186a200141186a290300370300200541206a200141206a290300370300200541286a200141286a290300370300200541306a2105201341016a2113200141306a22012014470d000b0b200a2011370320200a2002290300370300200a41386a2004370300200a41306a200f370300200a41286a2010370300200a41c8006a2013360200200a41c4006a200e360200200a41c0006a2012360200200a41186a200b290300370300200a41106a200c290300370300200a41086a200d290300370300200841016a2108200a41d0006a210a20062009470d000b0b200020083602082000200336020420002007360200200241206a24000f0b103a000b1033000bb10301037f024020002802082201450d002000280200220020014198016c6a21020340024020002d0000417f6a2201410f4b0d00024002400240024002400240024020010e1000070707070107070207030704070506000b200041086a280200450d06200041046a280200102c0c060b200041086a2d00004101470d05200041146a280200450d05200041106a280200102c0c050b200041046a2d00000d042000410c6a280200450d04200041086a280200102c0c040b200041046a2802000d032000410c6a280200450d03200041086a280200102c0c030b200041086a2d00004105490d02200041306a280200450d022000412c6a280200102c0c020b200041046a2d00004102490d010240200041106a2802002201450d00200141d0006c2103200041086a28020041c0006a210103400240200141046a280200450d002001280200102c0b200141d0006a2101200341b07f6a22030d000b0b2000410c6a280200450d012000280208102c0c010b200041086a280200450d00200041046a280200102c0b20004198016a210102402000418c016a280200450d00200028028801102c0b2001210020012002470d000b0b0be802010b7f230041106b22022400200241086a20011075024002400240024020022802080d0020012802042203417c712204417f4c0d02200228020c210502400240200341027622060d00410421070c010b2004102a2207450d040b02402005450d0041002108410021094100210403400240024002402001280204220a4104490d00200441016a21032001280200220b280000210c2001200a417c6a3602042001200b41046a36020020042006470d02024020082003200820034b1b220641ffffffff03712006470d002006410274220a41004e0d020b1035000b200041003602002006450d052007102c0c050b0240024020040d00200a102a21070c010b20072009200a102e21070b2007450d060b200720096a200c360200200841026a2108200941046a21092003210420052003470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241106a24000f0b103a000b1033000bba05020c7f067e230041f0006b22022400200220011075024002400240024020022802000d00200128020441306e220341306c2204417f4c0d02200228020421050240024020040d00410821060c010b2004102a2206450d040b02402005450d00410021070340200241003a00682007220841016a210720012802042109417f210a410021040240024002400240034020092004460d01200241c8006a20046a2001280200220b2d00003a000020012009200a6a3602042001200b41016a3602002002200441016a220c3a0068200a417f6a210a200c2104200c4120470d000b200241286a41186a2204200241c8006a41186a290300370300200241286a41106a220a200241c8006a41106a290300370300200241286a41086a220d200241c8006a41086a290300370300200220022903483703282009200c6b220c4110490d01200b41096a290000210e200b290001210f2001200c41706a3602042001200b41116a360200200241086a41086a220c200d290300370300200241086a41106a2209200a290300370300200241086a41186a220a20042903003703002002200229032837030820032008470d030240200841017422042007200420074b1b2203ad42307e2210422088a70d002010a7220441004e0d030b1035000b200441ff0171450d00200241003a00680b200041003602002003450d052006102c0c050b0240024020080d002004102a21060c010b2006200841306c2004102e21060b2006450d060b200c290300211020092903002111200a2903002112200229030821132006200841306c6a2204200f37032020042013370300200441286a200e370300200441186a2012370300200441106a2011370300200441086a201037030020072005470d000b0b2000200336020420002006360200200041086a20053602000c010b200041003602000b200241f0006a24000f0b103a000b1033000bd90403087f017e017f230041f0016b22022400200241086a200110750240024002400240024020022802080d00200128020441f0006e220341f0006c2204417f4c0d02200228020c21050240024020040d00410421060c010b2004102a2206450d040b024002402005450d00410021074100210841002109034020024180016a2001108101200228028401450d02200941016a2104200241106a20024180016a41f00010db051a024020092003470d0020072004200720044b1b2203ad42f0007e220a422088a70d08200aa7220b4100480d080240024020090d00200b102a21060c010b20062008200b102e21060b2006450d070b200620086a200241106a41f00010db051a200741026a2107200841f0006a21082004210920052004470d000b0b2000200336020420002006360200200041086a20053602000c020b2000410036020002402009450d00200620086a210120062107034002402007410c6a2802002209450d0020072802042104200941246c210903400240024020042d0000220841034b0d0002400240024020080e0404000102040b2004410c6a280200450d03200441086a280200102c0c030b2004410c6a280200450d02200441086a280200102c0c020b2004410c6a280200450d01200441086a280200102c0c010b200441086a280200450d00200441046a280200102c0b200441246a21042009415c6a22090d000b0b200741f0006a21040240200741086a280200450d002007280204102c0b2004210720012004470d000b0b2003450d012006102c0c010b200041003602000b200241f0016a24000f0b103a000b1033000b1035000ba00a03077f037e057f230041d0026b2202240041002103200241003a00c8022001280204417f6a210402400240024003402004417f460d01200241a8026a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00c8022004417f6a21042005210320054120470d000b200241e8006a41086a200241a8026a41086a290300370300200241e8006a41106a200241a8026a41106a290300370300200241e8006a41186a200241a8026a41186a290300370300200220022903a8023703682002200110752002280200450d01200041003602040c020b0240200341ff0171450d00200241003a00c8020b200041003602040c010b2002280204210641002104200241003a00c80220012802042107417f21030240034020072004460d01200241a8026a20046a200128020022082d00003a00002001200720036a3602042001200841016a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241a8016a41086a200241a8026a41086a2903002209370300200241a8016a41106a200241a8026a41106a290300220a370300200241a8016a41186a200241a8026a41186a290300220b37030020024188016a41086a200937030020024188016a41106a200a37030020024188016a41186a200b370300200220022903a80222093703a801200220093703880141002104200241003a00c802200720056b210c200720036a210303400240200c2004470d000240200441ff0171450d00200241003a00c8020b200041003602040c030b200241a8026a20046a200820046a220541016a2d00003a0000200120033602042001200541026a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241e8016a41086a200241a8026a41086a2903002209370300200241e8016a41106a200241a8026a41106a290300220a370300200241e8016a41186a200241a8026a41186a290300220b370300200241c8016a41086a22042009370300200241c8016a41106a2203200a370300200241c8016a41186a2205200b370300200220022903a80222093703e801200220093703c801200241a8026a2001108301024020022802a8022201450d00200241c8006a41086a2208200241e8006a41086a290300370300200241c8006a41106a2207200241e8006a41106a290300370300200241c8006a41186a220c200241e8006a41186a290300370300200241286a41086a220d20024188016a41086a290300370300200241286a41106a220e20024188016a41106a290300370300200241286a41186a220f20024188016a41186a29030037030020022002290368370348200220022903880137032820022902ac022109200241086a41186a22102005290300370300200241086a41106a22052003290300370300200241086a41086a22032004290300370300200220022903c801370308200020093702082000200136020420002006360200200041106a2002290348370200200041186a2008290300370200200041206a2007290300370200200041286a200c290300370200200041306a2002290328370200200041386a200d290300370200200041c0006a200e290300370200200041c8006a200f290300370200200041e8006a2010290300370200200041e0006a2005290300370200200041d8006a2003290300370200200041d0006a20022903083702000c020b200041003602040c010b0240200441ff0171450d00200241003a00c8020b200041003602040b200241d0026a24000ba104010a7f230041d0006b22022400200220011075024002400240024020022802000d00200128020422034160712204417f4c0d022002280204210502400240200341057622060d00410121070c010b2004102a2207450d040b02402005450d00410021080340200241003a00482008220941016a21082001280204417f6a21034100210402400240024003402003417f460d01200241286a20046a2001280200220a2d00003a0000200120033602042001200a41016a3602002002200441016a220a3a00482003417f6a2103200a2104200a4120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a220a200241286a41106a290300370300200241086a41086a220b200241286a41086a2903003703002002200229032837030820062009470d020240200941017422032008200320084b1b220641ffffff3f712006470d002006410574220341004e0d020b1035000b0240200441ff0171450d00200241003a00480b200041003602002006450d052007102c0c050b0240024020090d002003102a21070c010b200720094105742003102e21070b2007450d060b200720094105746a22032002290308370000200341186a2004290300370000200341106a200a290300370000200341086a200b29030037000020082005470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241d0006a24000f0b103a000b1033000b990b03117f017e037f23004180016b2202240020022001107502400240024002400240024020022802000d00200128020441246e220341246c2204417f4c0d01200228020421050240024020040d00410421060c010b2004102a2206450d030b0240024020050d00410021040c010b200241286a411c6a2107200241d8006a4104722108200241db006a2109200241336a210a200241c8006a410172220b41076a210c4100210d4100210e03402001280204220f450d06200128020022102d000021042001200f417f6a22113602042001201041016a360200200441064b0d0602400240024002400240024020040e07040c000c020301040b41002104200241003a0078200f417e6a210f0340024020112004470d00200441ff0171450d0d200241003a00780c0d0b200241d8006a20046a201020046a221241016a2d00003a00002001200f3602042001201241026a3602002002200441016a22123a0078200f417f6a210f2012210420124120470d000b200241286a41086a200841086a290000370300200241286a41106a200841106a290000370300200241286a41186a200841186a280000360200200220082900003703282002280258210f200741026a200241c8006a41026a2d00003a0000200720022f00483b0000410021120c040b200241d8006a20011076200228025c450d0a200241c8006a41086a200841086a28020022043602002002200829020022133703482002280258210f200941086a200436000020092013370000200220022900583703282002200241d8006a41076a29000037002f410121120c030b200241d8006a20011076200228025c450d09200241c8006a41086a200841086a28020022043602002002200829020022133703482002280258210f200941086a200436000020092013370000200220022900583703282002200241d8006a41076a29000037002f410221120c020b200241d8006a20011076200228025c450d08200241c8006a41086a200841086a28020022043602002002200829020022133703482002280258210f200941086a200436000020092013370000200220022900583703282002200241d8006a41076a29000037002f410321120c010b200241c8006a2001107720022802482204450d07200a2002290258370000200a41086a200241d8006a41086a290200370000200a41106a200241d8006a41106a2802003600002002200b2900003703282002200c28000036002f41042112201441ffffff07712004411874722214210f0b200241086a41176a2210200241286a41176a290000370000200241086a41106a2211200241286a41106a290300370300200241086a41086a2215200241286a41086a290300370300200220022903283703080240200e2003470d00200341016a22042003490d06200341017422162004201620044b1b2216ad42247e2213422088a70d062013a722044100480d060240024020030d002004102a21060c010b2006200341246c2004102e21060b2006450d05201621030b2006200e41246c6a2204200f360001200420123a0000200420022903083700052004410d6a2015290300370000200441156a20112903003700002004411c6a2010290000370000200d41246a210d200e41016a2204210e20042005470d000b0b2000200336020420002006360200200041086a20043602000c050b200041003602000c040b103a000b1033000b1035000b200041003602000240200e450d002006210403400240024020042d0000220141034b0d0002400240024020010e0404000102040b2004410c6a280200450d03200441086a280200102c0c030b2004410c6a280200450d02200441086a280200102c0c020b2004410c6a280200450d01200441086a280200102c0c010b200441086a280200450d00200441046a280200102c0b200441246a2104200d415c6a220d0d000b0b2003450d002006102c0b20024180016a24000bdf0704067f017e0a7f027e230041f0006b22032400200341206a2001200228020c22041102000240024020032802200d002000410036020820004208370200200120022802001103002002280204450d012001102c0c010b200341c8006a41106a200341206a41106a290300370300200341c8006a41086a200341206a41086a290300370300200341c8006a41186a200341206a41186a290300370300200341c8006a41206a200341206a41206a280200360200200341086a200341d4006a290200370300200341106a200341dc006a290200370300200341186a200341e4006a290200370300200320032903203703482003200329024c370300200341c8006a200120022802102205110200024002400240417f2003280248220641016a220720072006491b2208ad42287e2209422088a70d002009a72206417f4c0d000240024020060d004108210a4108210b0c010b2006102a220a450d02200a210b0b200a2003290300370300200a41186a200341186a220c290300370300200a41106a200341106a220d290300370300200a41086a200341086a290300370300200b4201370320200341206a200120041102000240024020032802200d004101210e0c010b200341c8006a410472210641c800210f4101210e0340200341c8006a41206a200341206a41206a280200360200200341c8006a41186a2210200341206a41186a290300370300200341c8006a41106a2211200341206a41106a290300370300200341c8006a41086a2212200341206a41086a29030037030020032003290320370348200341086a2207200641086a290200370300200d200641106a290200370300200c200641186a290200370300200320062902003703002010200c2903003703002011200d29030037030020122007290300370300200320032903003703480240200e2008470d00200341206a200120051102002008417f2003280220220741016a221320132007491b6a22072008490d05200841017422132007201320074b1b2207ad42287e2209422088a70d052009a722134100480d050240024020080d002013102a210a0c010b200a200841286c2013102e210a0b200a450d04200a210b200721080b200b200f6a221341606a2207200329034837030020122903002109201129030021142010290300211520134201370300200741186a2015370300200741106a2014370300200741086a2009370300200341206a20012004110200200f41286a210f200e41016a210e20032802200d000b0b2001200228020011030002402002280204450d002001102c0b2000200e360208200020083602042000200b3602000c030b103a000b1033000b1035000b200341f0006a24000ba308040c7f017e057f037e23004180016b22022400024002400240200141086a220328020022042001410c6a2802002205460d002001280210220628020021072006280208220841014b210903402003200441206a220a360200200241e0006a41186a200441186a290000370300200241e0006a41106a200441106a290000370300200241e0006a41086a200441086a29000037030020022004290000370360410021040240024020090d0020080e020401040b2008210b0340200b410176220c20046a220d20042007200d4105746a200241e0006a412010dd054101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a412010dd050d02200a2104200a2005470d000b0b20004100360208200042013702002001280204450d012001280200102c0c010b200241c0006a41086a2204200241e0006a41086a290300370300200241c0006a41106a220b200241e0006a41106a290300370300200241c0006a41186a220c200241e0006a41186a29030037030020022002290360220e3703002002200e370340024002404120102a220f450d00200f2002290340370000200f41186a200c290300370000200f41106a200b290300370000200f41086a2004290300370000200128020421102001280200211102400240200a2005470d0041012112410121130c010b41012112410121130340200628020821032006280200210702400340200241e0006a41186a2208200a41186a290000370300200241e0006a41106a2209200a41106a290000370300200241e0006a41086a2201200a41086a2900003703002002200a290000370360200a41206a210a4100210402400240200341014b0d0020030e020301030b2003210b0340200b410176220c20046a220d20042007200d4105746a200241e0006a412010dd054101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a412010dd050d01200a2005470d000c030b0b200241c0006a41086a2001290300220e370300200241c0006a41106a20092903002214370300200241c0006a41186a20082903002215370300200220022903602216370340200241186a220b2015370300200241106a220c2014370300200241086a220d200e37030020022016370300024020132012470d00201241016a22042012490d04201241017422072004200720044b1b221341ffffff3f712013470d04201341057422044100480d040240024020120d002004102a210f0c010b200f20124105742004102e210f0b200f450d030b200f20124105746a22042002290300370000200441186a200b290300370000200441106a200c290300370000200441086a200d290300370000201241016a2112200a2005470d000b0b02402010450d002011102c0b20002012360208200020133602042000200f3602000c020b1033000b1035000b20024180016a24000ba20705077f037e097f017e017f23004180016b22022400024002400240200141086a220328020022042001410c6a2802002205460d0020012802102106200241f4006a2107034020032004220841206a2204360200200841086a2903002109200841106a290300210a2008290300210b200241e0006a41186a200841186a290300370300200241e0006a41106a200a370300200241e0006a41086a20093703002002200b3703600240200aa720062802004d0d002001280214220c2007460d002007290000200c290000520d030b20052004470d000b0b20004100360208200042083702002001280204450d012001280200102c0c010b200241086a2204200241e0006a41086a290300370300200241106a2203200241e0006a41106a290300370300200241186a2207200241e0006a41186a29030037030020022002290360220a3703202002200a37030002400240024002404120102a220d450d00200d2002290300370300200d41186a2007290300370300200d41106a2003290300370300200d41086a20042903003703002001280204210e2001280200210f200541606a2008460d02200841206a2110200541606a2111200241f4006a21014101211241012113200d21140340200c2001460d032010210802400340200241e0006a41186a2204200841186a290300370300200241e0006a41106a2203200841106a290300220a370300200241e0006a41086a2207200841086a290300370300200220082903003703600240200aa720062802004d0d002001290000200c290000520d020b2005200841206a2208470d000c060b0b200241206a41086a2007290300220a370300200241206a41106a20032903002209370300200241206a41186a2004290300220b3703002002200229036022153703202004200b370300200320093703002007200a37030020022015370360024020132012470d00201241016a22132012490d03201241017422102013201020134b1b221341ffffff3f712013470d03201341057422104100480d030240024020120d002010102a21140c010b201420124105742010102e21140b2014450d020b200841206a2110201420124105746a22162002290360370300201641186a2004290300370300201641106a2003290300370300201641086a2007290300370300201241016a211220112008470d000c040b0b1033000b1035000b4101211241012113200d21140b0240200e450d00200f102c0b2000201236020820002013360204200020143602000b20024180016a24000bfe1503077f027e057f230041206b2202240002400240024041aa02102a2203450d00200241aa0236020420022003360200200341003b00002002410236020802400240200128020022042903684202520d00024020022802044102470d00200228020041024104102e2203450d0320024104360204200220033602000b200228020041043a00022002200228020841016a3602080c010b024020022802044102470d00200228020041024104102e2203450d0220024104360204200220033602000b20022802004184013a00022002200228020841016a36020820042002108801024020042d0024220341024b0d0002400240024020030e03000102000b02400240200228020420022802082203460d00200228020021010c010b200341016a22012003490d07200341017422052001200520014b1b22054100480d070240024020030d002005102a21010c010b200228020020032005102e21010b2001450d052002200536020420022001360200200228020821030b2002200341016a360208200120036a41003a0000200441256a2106410021010340200620016a2d0000210702400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d08200341017422082005200820054b1b22084100480d080240024020030d002008102a21050c010b200228020020032008102e21050b2005450d062002200836020420022005360200200228020821030b2002200341016a360208200520036a20073a0000200141016a220141c000470d000c030b0b02400240200228020420022802082203460d00200228020021010c010b200341016a22012003490d06200341017422052001200520014b1b22054100480d060240024020030d002005102a21010c010b200228020020032005102e21010b2001450d042002200536020420022001360200200228020821030b2002200341016a360208200120036a41013a0000200441256a2106410021010340200620016a2d0000210702400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d07200341017422082005200820054b1b22084100480d070240024020030d002008102a21050c010b200228020020032008102e21050b2005450d052002200836020420022005360200200228020821030b2002200341016a360208200520036a20073a0000200141016a220141c000470d000c020b0b02400240200228020420022802082203460d00200228020021010c010b200341016a22012003490d05200341017422052001200520014b1b22054100480d050240024020030d002005102a21010c010b200228020020032005102e21010b2001450d032002200536020420022001360200200228020821030b2002200341016a360208200120036a41023a0000412521010340200420016a2d0000210702400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d06200341017422082005200820054b1b22084100480d060240024020030d002008102a21050c010b200228020020032008102e21050b2005450d042002200836020420022005360200200228020821030b2002200341016a360208200520036a20073a0000200141016a220141e600470d000b0b0240024020042903684201510d0002400240200228020420022802082203460d00200228020021010c010b200341016a22012003490d06200341017422052001200520014b1b22054100480d060240024020030d002005102a21010c010b200228020020032005102e21010b2001450d042002200536020420022001360200200228020821030b2002200341016a360208200120036a41003a00000c010b200441f8006a29030020042903702209420c88220a4201200a4201561b80210a0240024020022802042201200228020822036b4102490d00200228020021010c010b200341026a22052003490d05200141017422032005200320054b1b22034100480d050240024020010d002003102a21010c010b200228020020012003102e21010b2001450d032002200336020420022001360200200228020821030b2002200341026a360208200120036a200aa741047420097aa7417f6a22034101200341014b1b2203410f2003410f491b723b00000b20044190016a2002108901200220044180016a360210200241106a2002108a010b20044198016a2002108b012002280208210320024100360218200242013703102003417e6a200241106a10672002280208220141014d0d01200228021821042002280214210b2002280210210720024100360208200228020021030240024002400240024002402001417e6a2208450d00410221062004450d04200320072d00003a00004101210c2002200228020841016a36020820044101460d04200720046a210d200320072d00013a00012002200228020841016a36020841022106200741026a21052004417e6a220e0d014100210e0c020b0240024002402002280204220120044f0d00200141017422052004200520044b1b22054100480d0a0240024020010d002005102a21030c010b200320012005102e21030b2003450d082002200536020420022003360200200228020821060c010b410021062004450d010b200320066a220120072d00003a0000024020044101470d00200641016a21060c010b2004417f6a2105200741016a2103200141016a21010340200120032d00003a0000200141016a2101200341016a21032005417f6a22050d000b200620046a21060b20022006360208410221060c020b024002402002280204220320016b200e490d00200228020021030c010b2001200e6a22062001490d07200341017422012006200120064b1b22014100480d070240024020030d002001102a21030c010b200228020020032001102e21030b2003450d0520022001360204200220033602000b200320046a200341026a200810dc051a0240200420022802082203460d00200420036b21062004417e6a2101200228020020036a210c410021030340024020012003470d00200421060c040b200c20036a20052d00003a00002002200228020841016a360208200541016a21052006200341016a2203470d000b200d20056b220e0d004100210e4101210c200421060c010b200e4100480d0620042106200e102a220c450d040b0240200d2005460d00200c20052d00003a00004101210f02400240200541016a2203200d470d00200c41016a21040c010b200c41016a21012007200420056b6a21050340200120032d00003a0000200141016a2101200d200341016a2203470d000b2005450d01200c20056a21042005210f0b0240024020022802042203200820066a22016b200f490d00200228020021030c010b2001200f6a22052001490d07200341017422012005200120054b1b22014100480d070240024020030d002001102a21030c010b200228020020032001102e21030b2003450d0520022001360204200220033602000b20032006200f6a220d6a200320066a200810dc051a0240200d20022802082203460d00200228020020036a21012006200f6a20036b2105200c2103034020042003460d01200120032d00003a00002002200228020841016a360208200341016a2103200141016a21012005417f6a22050d000b0b200d21060b200e450d00200c102c0b2008450d010b0240200620022802082203460d002002280200220120036a200120066a200810dc051a0b2002200820036a3602080b0240200b450d002007102c0b20002002290300370200200041086a200241086a280200360200200241206a24000f0b1033000b41dafec500411c41acfec5001036000b1035000bfd0701037f02400240024020002d00004101460d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d03200241017422042003200420034b1b22044100480d030240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41ff013a0000200041016a20011091010f0b0240024002400240200041046a280200220241ffff034b0d00200241ef014b0d03200141046a280200200141086a2802002200460d01200128020021030c020b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d05200041017422042003200420034b1b22044100480d050240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0420012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fd013a000002400240200141046a2802002203200428020022006b4104490d00200128020021030c010b200041046a22042000490d05200341017422002004200020044b1b22004100480d050240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20023600000f0b200041016a22032000490d03200041017422042003200420034b1b22044100480d030240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0220012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20023a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d02200041017422042003200420034b1b22044100480d020240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fc013a000002400240200141046a2802002203200428020022006b4102490d00200128020021030c010b200041026a22042000490d02200341017422002004200020044b1b22004100480d020240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20023b00000f0b1033000b1035000bed0601037f02400240024020002802002202413f4b0d0002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d03200041017422042003200420034b1b22044100480d030240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0220012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20024102743a00000f0b0240200241808001490d0002402002418080808004490d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280200210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d04200241017422002004200020044b1b22004100480d040240024020020d002000102a21020c010b200128020020022000102e21020b2002450d0320012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a2802002203200141086a28020022006b4104490d00200128020021030c010b200041046a22042000490d03200341017422002004200020044b1b22004100480d030240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0220012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20024102744102723600000f0b02400240200141046a2802002203200141086a28020022006b4102490d00200128020021030c010b200041026a22042000490d02200341017422002004200020044b1b22004100480d020240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20024102744101723b00000f0b1033000b1035000bd50903017f027e057f230041e0006b220224000240024002400240200028020022002903002203423f56200041086a290300220442005220045022051b0d0002400240200141046a280200200141086a2802002200460d00200128020021050c010b200041016a22052000490d04200041017422062005200620054b1b22064100480d040240024020000d002006102a21050c010b200128020020002006102e21050b2005450d0320012005360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200520006a2003a74102743a00000c010b024020034280800154410020051b0d000240200342808080800454410020051b0d000240411020047920037942c0007c20044200521ba741037622066b4104490d0002400240200141046a280200200141086a2802002205460d00200128020021070c010b200541016a22082005490d06200541017422072008200720084b1b22084100480d060240024020050d002008102a21070c010b200128020020052008102e21070b2007450d0520012007360200200141046a2008360200200141086a28020021050b200141086a2208200541016a360200200720056a413320064102746b3a0000200029030021032002200041086a290300220437030820022003370300200641706a2105200141046a2107034002400240200728020020082802002200460d00200128020021060c010b200041016a22062000490d07200041017422092006200920064b1b22094100480d070240024020000d002009102a21060c010b200128020020002009102e21060b2006450d062001200636020020072009360200200828020021000b2008200041016a360200200620006a2003a73a00002003420888200442388684210320044208882104200541016a22002005492106200021052006450d000b20022003370300200220043703082003200484500d03200241286a41146a4109360200200241346a410a360200200241106a41146a410336020020022002360240200241a0e2c10036024420024203370214200241ec9fc6003602102002410a36022c200242043703582002420137024c200241d8e1c1003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a4184c5c5001041000b4196e1c100413641acfec5001036000b02400240200141046a2802002205200141086a28020022006b4104490d00200128020021050c010b200041046a22062000490d04200541017422002006200020064b1b22004100480d040240024020050d002000102a21050c010b200128020020052000102e21050b2005450d0320012005360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200520006a2003a74102744102723600000c010b02400240200141046a2802002205200141086a28020022006b4102490d00200128020021050c010b200041026a22062000490d03200541017422002006200020064b1b22004100480d030240024020050d002000102a21050c010b200128020020052000102e21050b2005450d0220012005360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200520006a2003a74102744101723b00000b200241e0006a24000f0b1033000b1035000bdeca0103057f017e067f230041206b22022400024002400240024002402000280200220341174b0d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e18000102030405060708090a0b0c0d0e0f1011121314151617000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000280208417f6a220341064b0d17024002400240024002400240024020030e0700010203040506000b200241003a001402400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d20200041017422042003200420034b1b22044100480d200240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1f20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000c1d0b200241013a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1f200341017422052004200520044b1b22054100480d1f0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200028020c2106200041146a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d1f200441017422032005200320054b1b22034100480d1f0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1e20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c1c0b200241023a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000290310210702400240200141046a2802002203200528020022006b4108490d00200128020021030c010b200041086a22042000490d1e200341017422002004200020044b1b22004100480d1e0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1d20012003360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200320006a20073700000c1b0b200241033a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c2106200041146a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d1d200441017422032005200320054b1b22034100480d1d0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1c20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c1a0b200141086a2802002103200241043a0014024002402003200141046a280200460d00200128020021050c010b200341016a22042003490d1c200341017422052004200520044b1b22044100480d1c0240024020030d002004102a21050c010b200128020020032004102e21050b2005450d1b20012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41043a0000200028020c2103200041146a2802002200200110672000450d192003200041186c6a2108200141046a2106034020032802002109200341086a280200220020011067024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d1d200a4101742205200b2005200b4b1b22054100480d1d02400240200a0d002005102a210a0c010b2001280200200a2005102e210a0b200a450d1c2001200a36020020062005360200200428020021050b2004200520006a360200200a20056a2009200010db051a2003410c6a2802002109200341146a280200220020011067024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d1d200a4101742205200b2005200b4b1b22054100480d1d02400240200a0d002005102a210a0c010b2001280200200a2005102e210a0b200a450d1c2001200a36020020062005360200200428020021050b2004200520006a360200200a20056a2009200010db051a200341186a22032008470d000c1a0b0b200241053a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41053a0000200028020c2104200041146a2802002200200110672000450d1820042000410c6c6a2108200141046a210903402004280200210a200441086a2802002200200110670240024020092802002205200628020022036b2000490d00200128020021050c010b200320006a220b2003490d1c20054101742203200b2003200b4b1b22034100480d1c0240024020050d002003102a21050c010b200128020020052003102e21050b2005450d1b2001200536020020092003360200200628020021030b2006200320006a360200200520036a200a200010db051a2004410c6a22042008470d000c190b0b200241063a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41063a0000200028020c2106200041146a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d1a200441017422032005200320054b1b22034100480d1a0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1920012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c170b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020421032000410c6a2802002200200110672000450d1620004190016c2100034020032001108b0120034190016a2103200041f07e6a22000d000c170b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d18200041017422042003200420034b1b22044100480d180240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1720012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a0000200110e6020c150b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d17200341017422052004200520044b1b22054100480d170240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a200110c3020c140b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a220a200341016a360200200420036a41003a00002000280204210c2000410c6a2802002200200110672000450d13200c200041f0006c6a210d200141046a210b034020022001360200200c41106a2002109402200c200110890120022001360200200c41306a200210940220022001360200200c41d0006a2002109402200c2802042104200c28020c22002001106702402000450d00200041246c210903402002200410e7022002280200210602400240200b2802002205200a28020022006b20022802082203490d00200128020021050c010b200020036a22082000490d19200541017422002008200020084b1b22004100480d190240024020050d002000102a21050c010b200128020020052000102e21050b2005450d1820012005360200200b2000360200200a28020021000b200a200020036a360200200520006a2006200310db051a02402002280204450d002006102c0b200441246a21042009415c6a22090d000b0b200c41f0006a220c200d470d000c140b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d15200041017422042003200420034b1b22044100480d150240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1420012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41053a0000200110e6020c120b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a00002000280208417f6a220341034b0d110240024002400240024020030e0400010203000b200241003a001402400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d18200441017422052003200520034b1b22034100480d180240024020040d002003102a21050c010b200128020020042003102e21050b2005450d1720012005360200200141046a2003360200200141086a28020021040b200041306a2103200141086a200441016a360200200520046a41003a00002000410c6a2001108801200241106a21000c030b200241013a001402400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d17200441017422052003200520034b1b22034100480d170240024020040d002003102a21050c010b200128020020042003102e21050b2005450d1620012005360200200141046a2003360200200141086a28020021040b200041c0006a2103200141086a200441016a360200200520046a41013a00002000410c6a20011088012002200041306a360214200241146a2001108a01200241186a21000c020b200241023a001402400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d16200441017422052003200520034b1b22034100480d160240024020040d002003102a21050c010b200128020020042003102e21050b2005450d1520012005360200200141046a2003360200200141086a28020021040b200041d8006a2103200141086a200441016a360200200520046a41023a00002000410c6a2001108801200041306a20011088012002411c6a21000c010b200241033a001402400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22032004490d15200441017422052003200520034b1b22034100480d150240024020040d002003102a21050c010b200128020020042003102e21050b2005450d1420012005360200200141046a2003360200200141086a28020021040b200041306a2103200141086a200441016a360200200520046a41033a00002000410c6a2001108801200221000b2000200336020020002001108a010c110b02400240200141046a2206280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d132004410174220a2005200a20054b1b220a4100480d130240024020040d00200a102a21050c010b20012802002004200a102e21050b2005450d1220012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a41073a0000200041086a22052d0000417f6a2204410f4b0d10024002400240024002400240024002400240024002400240024002400240024020040e10000102030405060708090a0b0c0d0e0f000b200241003a001402400240200628020020032802002204460d002001280200210a0c010b200441016a220a2004490d2220044101742209200a2009200a4b1b22094100480d220240024020040d002009102a210a0c010b200128020020042009102e210a0b200a450d212001200a360200200141046a2009360200200141086a28020021040b200141086a200441016a360200200a20046a41003a00002000410c6a20011088012002200041306a36020020022001108a0120052d0001220041024b0d1f02400240024020000e03000102000b200241003a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d24200041017422052004200520044b1b22054100480d240240024020000d002005102a21040c010b200128020020002005102e21040b2004450d2320012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41003a00000c210b200241013a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d23200041017422052004200520044b1b22054100480d230240024020000d002005102a21040c010b200128020020002005102e21040b2004450d2220012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41013a00000c200b200241023a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d22200041017422052004200520044b1b22054100480d220240024020000d002005102a21040c010b200128020020002005102e21040b2004450d2120012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41023a00000c1f0b200241013a001402400240200628020020032802002203460d00200128020021040c010b200341016a22042003490d21200341017422052004200520044b1b22054100480d210240024020030d002005102a21040c010b200128020020032005102e21040b2004450d2020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002002200041106a36020020022001108a010c1e0b200241023a001402400240200628020020032802002203460d00200128020021040c010b200341016a22042003490d20200341017422052004200520044b1b22054100480d200240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200041106a36020020022001108a010c1d0b200241033a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d1f200041017422052004200520044b1b22054100480d1f0240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1e20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41033a00000c1c0b200241043a001402400240200628020020032802002203460d00200128020021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a20011089010c1b0b200241053a001402400240200628020020032802002203460d00200128020021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200028020c2103200041146a2802002200200110672000450d1a200041246c2100034020032001108801200341246a21032000415c6a22000d000c1b0b0b200241063a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d1c200041017422052004200520044b1b22054100480d1c0240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1b20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41063a00000c190b200241073a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d1b2000410174220a2004200a20044b1b220a4100480d1b0240024020000d00200a102a21040c010b20012802002000200a102e21040b2004450d1a20012004360200200141046a200a360200200141086a28020021000b2003200041016a360200200420006a41073a000020052d0001220041024b0d1802400240024020000e03000102000b200241003a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d1d200041017422052004200520044b1b22054100480d1d0240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1c20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41003a00000c1a0b200241013a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d1c200041017422052004200520044b1b22054100480d1c0240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1b20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41013a00000c190b200241023a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d1b200041017422052004200520044b1b22054100480d1b0240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1a20012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a41023a00000c180b200241083a001402400240200628020020032802002203460d00200128020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a00002000410c6a20011088010c170b200241093a001402400240200628020020032802002203460d00200128020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a20011089010c160b2002410a3a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d18200041017422052004200520044b1b22054100480d180240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1720012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a410a3a00000c150b2002410b3a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d17200041017422052004200520044b1b22054100480d170240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1620012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a410b3a00000c140b2002410c3a001402400240200628020020032802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a0000200028020c2103200041146a2802002200200110672000450d1320004105742100034020032001109101200341206a2103200041606a22000d000c140b0b2002410d3a001402400240200628020020032802002200460d00200128020021030c010b200041016a22032000490d15200041017422042003200420034b1b22044100480d150240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1420012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a410d3a0000200541016a20011091010c120b2002410e3a001402400240200628020020032802002200460d00200128020021040c010b200041016a22042000490d14200041017422052004200520044b1b22054100480d140240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1320012004360200200141046a2005360200200141086a28020021000b2003200041016a360200200420006a410e3a00000c110b2002410f3a001402400240200628020020032802002204460d00200128020021050c010b200441016a22052004490d132004410174220a2005200a20054b1b220a4100480d130240024020040d00200a102a21050c010b20012802002004200a102e21050b2005450d1220012005360200200141046a200a360200200141086a28020021040b2003200441016a360200200520046a410f3a0000200028020c210a0240024020062802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d13200541017422042009200420094b1b22044100480d130240024020050d002004102a21050c010b200128020020052004102e21050b2005450d1220012005360200200141046a2004360200200141086a28020021040b200141086a2208200441046a360200200520046a200a36000020002802102104200041186a2802002200200110672000450d102000410274210a0340200428020021090240024020062802002205200328020022006b4104490d00200128020021050c010b200041046a220b2000490d1420054101742200200b2000200b4b1b22004100480d140240024020050d002000102a21050c010b200128020020052000102e21050b2005450d1320012005360200200141046a2000360200200828020021000b200441046a21042003200041046a360200200520006a2009360000200a417c6a220a0d000c110b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041106a2001109101200041306a2001109101200041d0006a2001109101200041f0006a2001109101200028020421062000410c6a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d12200441017422032005200320054b1b22034100480d120240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1120012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c0f0b02400240200141046a2206280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d112003410174220a2005200a20054b1b220a4100480d110240024020030d00200a102a21050c010b20012802002003200a102e21050b2005450d1020012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41093a0000200041086a22052d0000417f6a220341144b0d0e02400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e15000102030405060708090a0b0c0d0e0f1011121314000b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d25200341017422062004200620044b1b22064100480d250240024020030d002006102a21040c010b200128020020032006102e21040b2004450d2420012004360200200141046a2006360200200141086a28020021030b200141086a200341016a360200200420036a41003a000020022001360200200541016a20021094022002200041306a36020020022001108a010c220b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d24200341017422052004200520044b1b22054100480d240240024020030d002005102a21040c010b200128020020032005102e21040b2004450d2320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a20011089010c210b02400240200628020020042802002203460d00200128020021060c010b200341016a22062003490d232003410174220a2006200a20064b1b220a4100480d230240024020030d00200a102a21060c010b20012802002003200a102e21060b2006450d2220012006360200200141046a200a360200200141086a28020021030b200141086a220a200341016a360200200620036a41023a00002000410c6a200110890120052d00012106200541026a2d0000210502400240200141046a280200200a2802002200460d00200128020021030c010b200041016a22032000490d232000410174220a2003200a20034b1b220a4100480d230240024020000d00200a102a21030c010b20012802002000200a102e21030b2003450d2220012003360200200141046a200a360200200141086a28020021000b2004200041016a360200200320006a20064100474107742005723a00000c200b02400240200628020020042802002203460d00200128020021060c010b200341016a22062003490d222003410174220a2006200a20064b1b220a4100480d220240024020030d00200a102a21060c010b20012802002003200a102e21060b2006450d2120012006360200200141046a200a360200200141086a28020021030b200141086a220a200341016a360200200620036a41033a00002000410c6a200110890120052d00012106200541026a2d0000210502400240200141046a280200200a2802002200460d00200128020021030c010b200041016a22032000490d222000410174220a2003200a20034b1b220a4100480d220240024020000d00200a102a21030c010b20012802002000200a102e21030b2003450d2120012003360200200141046a200a360200200141086a28020021000b2004200041016a360200200320006a20064100474107742005723a00000c1f0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d212003410174220a2005200a20054b1b220a4100480d210240024020030d00200a102a21050c010b20012802002003200a102e21050b2005450d2020012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41043a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d21200341017422002006200020064b1b22004100480d210240024020030d002000102a21030c010b200128020020032000102e21030b2003450d2020012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c1e0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d20200041017422042003200420034b1b22044100480d200240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1f20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41053a000020022001360200200541016a20021094020c1d0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1f200041017422042003200420034b1b22044100480d1f0240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1e20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41063a000020022001360200200541016a20021094020c1c0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1e200041017422042003200420034b1b22044100480d1e0240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1d20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41073a000020022001360200200541016a20021094020c1b0b02400240200628020020042802002203460d002001280200210a0c010b200341016a220a2003490d1d20034101742209200a2009200a4b1b22094100480d1d0240024020030d002009102a210a0c010b200128020020032009102e210a0b200a450d1c2001200a360200200141046a2009360200200141086a28020021030b200141086a2209200341016a360200200a20036a41083a000020022001360200200541016a2002109402200028022c210a02400240200141046a2802002205200928020022036b4104490d00200128020021050c010b200341046a22092003490d1d200541017422032009200320094b1b22034100480d1d0240024020050d002003102a21050c010b200128020020052003102e21050b2005450d1c20012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200a360000200028023021050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d1d200341017422002006200020064b1b22004100480d1d0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1c20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c1a0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1c200041017422042003200420034b1b22044100480d1c0240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1b20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41093a000020022001360200200541016a20021094020c190b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a00002000410c6a20011089010c180b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d1a2003410174220a2005200a20054b1b220a4100480d1a0240024020030d00200a102a21050c010b20012802002003200a102e21050b2005450d1920012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a410b3a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d1c200341017422002006200020064b1b22004100480d1c0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1b20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c170b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1b200041017422042003200420034b1b22044100480d1b0240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a410c3a0000200541016a20011091010c160b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1a200041017422052003200520034b1b22054100480d1a0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d1920012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a410d3a00000c150b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d19200041017422042003200420034b1b22044100480d190240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1820012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a410e3a0000200541016a20011091010c140b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d182000410174220a2003200a20034b1b220a4100480d180240024020000d00200a102a21030c010b20012802002000200a102e21030b2003450d1720012003360200200141046a200a360200200141086a28020021000b200141086a200041016a360200200320006a410f3a0000200541016a200110910120052d0021220041064b0d130240024002400240024002400240024020000e0700010203040506000b410021030c060b410121030c050b410221030c040b410321030c030b410421030c020b410521030c010b410621030b200220033a001402400240200628020020042802002200460d00200128020021050c010b200041016a22052000490d18200041017422062005200620054b1b22064100480d180240024020000d002006102a21050c010b200128020020002006102e21050b2005450d1720012005360200200141046a2006360200200141086a28020021000b2004200041016a360200200520006a20033a00000c130b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d17200041017422052003200520034b1b22054100480d170240024020000d002005102a21030c010b200128020020002005102e21030b2003450d1620012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41103a00000c120b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d16200041017422052003200520034b1b22054100480d160240024020000d002005102a21030c010b200128020020002005102e21030b2003450d1520012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41113a00000c110b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d15200341017422062005200620054b1b22064100480d150240024020030d002006102a21050c010b200128020020032006102e21050b2005450d1420012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a41123a0000200028020c210a200041146a28020022002001106702400240200141046a2802002205200628020022036b2000490d00200128020021050c010b200320006a22062003490d15200541017422032006200320064b1b22034100480d150240024020050d002003102a21050c010b200128020020052003102e21050b2005450d1420012005360200200141046a2003360200200141086a28020021030b2004200320006a360200200520036a200a200010db051a0c100b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d14200341017422062005200620054b1b22064100480d140240024020030d002006102a21050c010b200128020020032006102e21050b2005450d1320012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a41133a0000200028020c210a200041146a28020022002001106702400240200141046a2802002205200628020022036b2000490d00200128020021050c010b200320006a22062003490d14200541017422032006200320064b1b22034100480d140240024020050d002003102a21050c010b200128020020052003102e21050b2005450d1320012005360200200141046a2003360200200141086a28020021030b2004200320006a360200200520036a200a200010db051a0c0f0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d13200041017422042003200420034b1b22044100480d130240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1220012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41143a000020022001360200200541016a20021094020c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a0000200041046a200110e8020c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a0000200041046a200110e8020c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a00002000280208417f6a220341054b0d0b02400240024002400240024020030e06000102030405000b200241003a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200041186a2105200141086a200341016a360200200420036a41003a0000200028020c2103200041146a28020022002001106702402000450d0020004105742100034020032001109101200341206a2103200041606a22000d000b0b2002200536020020022001108a010c100b200241013a001402400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d14200041017422042003200420034b1b22044100480d140240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1320012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c0f0b200241023a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a20011088010c0e0b200241033a001402400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d12200041017422042003200420034b1b22044100480d120240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1120012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41033a00000c0d0b200141086a2802002100200241043a0014024002402000200141046a280200460d00200128020021030c010b200041016a22032000490d11200041017422042003200420034b1b22044100480d110240024020000d002004102a21030c010b200128020020002004102e21030b2003450d1020012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41043a00000c0c0b200241053a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000410c6a20011088010c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410d3a0000200041046a22032d0000417f6a220441044b0d0a0240024002400240024020040e050001020304000b200241003a001402400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d13200041017422052004200520044b1b22054100480d130240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1220012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a41003a0000200341016a20011091010c0e0b200141086a2802002100200141046a2802002104200241013a00140240024020042000460d00200128020021040c010b200041016a22042000490d12200041017422052004200520044b1b22054100480d120240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1120012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a41013a0000200341016a20011091010c0d0b200241023a001402400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d11200041017422052004200520044b1b22054100480d110240024020000d002005102a21040c010b200128020020002005102e21040b2004450d1020012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a41023a0000200341016a2001109101200341216a20011091010c0c0b200241033a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002802082103200041106a2802002200200110672000450d0b20004105742100034020032001109101200341206a2103200041606a22000d000c0c0b0b200141086a2802002100200241043a0014024002402000200141046a280200460d00200128020021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102a21040c010b200128020020002005102e21040b2004450d0e20012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a41043a0000200341016a20011091010c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410e3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041046a20011089010c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410f3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020421062000410c6a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d0d200441017422032005200320054b1b22034100480d0d0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0c20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41103a00002000280208417f6a220341024b0d0702400240024020030e03000102000b200241003a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002002200041306a36020020022001108a012000410c6a20011088010c090b200241013a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a20011089010c080b200241023a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a20011089010c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41113a0000200041086a22042d0000417f6a220341044b0d060240024002400240024020030e050001020304000b200241003a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041106a200110e9020c0a0b200241013a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a200110c302200028020c2106200041146a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d0e200441017422032005200320054b1b22034100480d0e0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c090b200241023a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000410c6a20011088012002200041c0006a36020020022001108a01200041d0006a200110c30220002802302106200041386a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d0d200441017422032005200320054b1b22034100480d0d0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0c20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c080b200241033a001402400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22052003490d0c200341017422062005200620054b1b22064100480d0c0240024020030d002006102a21050c010b200128020020032006102e21050b2005450d0b20012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a41033a00002002200041386a36020020022001108a01200041c8006a200110c30220022001360200200441016a2002109402200028022c2105200041346a28020022002001106702400240200141046a2802002204200628020022036b2000490d00200128020021040c010b200320006a22062003490d0c200441017422032006200320064b1b22034100480d0c0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0b20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2005200010db051a0c070b200141086a2802002100200241043a0014024002402000200141046a280200460d00200128020021030c010b200041016a22032000490d0b200041017422052003200520034b1b22054100480d0b0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d0a20012003360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200320006a41043a0000200441016a2001109101024020042d00214101460d00200241003a001402400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d0c200041017422042003200420034b1b22044100480d0c0240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0b20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000c070b200241013a001402400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d0b200041017422052003200520034b1b22054100480d0b0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d0a20012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a41013a0000200441226a20011091010c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41123a00002000280204417f6a220341024b0d0502400240024020030e03000102000b200241003a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a000020002802082001108b010c070b200241013a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041086a20011088010c060b200241023a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041086a2001108801200028022c2001108b010c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41133a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d09200441017422032005200320054b1b22034100480d090240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a220a200341046a360200200420036a2006360000200041086a2802002106200041106a28020022032001106702400240200141046a2802002205200a28020022046b2003490d00200128020021050c010b200420036a220a2004490d0920054101742204200a2004200a4b1b22044100480d090240024020050d002004102a21050c010b200128020020052004102e21050b2005450d0820012005360200200141046a2004360200200141086a28020021040b200141086a220a200420036a360200200520046a2006200310db051a200041146a28020021052000411c6a28020022032001106702402003450d0020052003410c6c6a210c200141046a210b034020052802002109200541086a28020022032001106702400240200b2802002206200a28020022046b2003490d00200128020021060c010b200420036a22082004490d0b200641017422042008200420084b1b22044100480d0b0240024020060d002004102a21060c010b200128020020062004102e21060b2006450d0a20012006360200200b2004360200200a28020021040b200a200420036a360200200620046a2009200310db051a2005410c6a2205200c470d000b0b200041206a280200210502400240200141046a2802002204200a28020022036b4104490d00200128020021040c010b200341046a22062003490d09200441017422032006200320064b1b22034100480d090240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041246a280200210a02400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22052003490d09200441017422032005200320054b1b22034100480d090240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a200a360000200041286a210b4100210303402002200b20036a2d000022063a001402400240200141046a220a28020020052802002200460d00200128020021040c010b200041016a22042000490d0a200041017422092004200920044b1b22094100480d0a0240024020000d002009102a21040c010b200128020020002009102e21040b2004450d0920012004360200200a2009360200200528020021000b2005200041016a360200200420006a20063a0000200341016a220341c000470d000c050b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d08200041017422042003200420034b1b22044100480d080240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0720012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41143a0000200110e6020c030b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d07200041017422042003200420034b1b22044100480d070240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0620012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41153a0000200110e6020c020b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d06200041017422042003200420034b1b22044100480d060240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0520012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41163a0000200110e6020c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41173a00002000280204417f6a220341034b0d00024002400240024020030e0400010203000b200241003a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000020002802082106200041106a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0720012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c030b200241013a001402400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d07200041017422042003200420034b1b22044100480d070240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0620012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c020b200241023a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041086a20011088010c010b200241033a001402400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041086a2001108801200028022c2106200041346a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d05200441017422032005200320054b1b22034100480d050240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0420012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0b200241206a24000f0b1033000b1035000b1033000b1035000ba67b05057f037e077f037e037f230041a0036b22012400200141e0006a41186a4200370300200141e0006a41106a22024200370300200141e0006a41086a220342003703002001420037036020014180026a41086a220441e0d9c500ad4280808080f001841002220541086a29000037030020012005290000370380022005102c20032004290300370300200120012903800222063703a00220012006370360200441beb9c000ad4280808080d001841002220541086a29000037030020012005290000370380022005102c20022001290380022206370300200141f0026a41086a2003290300370300200141f0026a41106a2006370300200141f0026a41186a2004290300370300200120063703a002200120012903603703f002200141203602e4012001200141f0026a3602e00120014180026a200141f0026aad2207428080808080048422081003108d010240024020012802800222030d0041022104200141023602e4020c010b20012802840221052001200428020022043602f401200120033602f0010240024020044104490d002001200341046a3602f00120012004417c6a22093602f40120094104490d00200328000021092001200441786a3602f4012001200341086a3602f0012003280004210a200141e0006a200141f0016a10742001280260220b450d002001290264210641002104200141003a00a00202400240024020012802f401220c450d002001200c417f6a220d3602f401200120012802f001220e41016a3602f001200e2d00004101460d010b0c010b200d4104490d002001200c417b6a3602f4012001200e41056a3602f001200e280001210f410121040b2001200f3602e802200120063702dc022001200b3602d8022001200a3602d402200120093602d0020c010b200141003602b802200142013703b0022001410b3602a4022001200141e0016a3602a0022001200141b0026a36029003200141f4006a410136020020014201370264200141d0b0c2003602602001200141a0026a36027020014190036a41c49ac500200141e0006a10391a20013502b80242208620013502b002841004024020012802b402450d0020012802b002102c0b410221040b200120043602e4022005450d002003102c0b200141e0006a41106a2203200141d0026a41106a2205280200360200200141e0006a41086a2209200141d0026a41086a220a290300370300200120012903d002370360024002400240024002400240024002400240024020044102460d00200141b0026a41106a20032802002203360200200141b0026a41086a200929030022103703002001200129036022063703b00220052003360200200a2010370300200141e8026a200f360200200120063703d002200120043602e40202402006a722032000470d000240024020044101460d00200141e0026a280200220fad42287e2206422088a70d042006a72203417f4c0d0420012802d802210420012802d402210b0240024020030d004108210a0c010b2003102a220a450d090b410021050240200f450d00200f41286c210941002105200a21030340200441086a2903002106200441106a2903002110200441186a290300211120042903002112200341206a200441206a290300370300200341186a2011370300200341106a2010370300200341086a200637030020032012370300200341286a2103200541016a2105200441286a2104200941586a22090d000b0b20014180036a200b360200200141f0026a410c6a2005360200200141f0026a41086a200f3602002001200a3602f402200141003602f002200141e0006a200141f0026a108f012001418b026a200141e0006a41086a2802003600002001200129036037008302200141e0006a410c6a20014187026a290000370000200141c6a4b9da04360061200141023a00602001200129008002370065200141e0006a109001200f450d01200a102c0c010b200141e0026a280200220aad42287e2206422088a70d032006a72203417f4c0d0320012802d802210420012802d402210c0240024020030d004108210b0c010b2003102a220b450d080b02400240200a0d00410021050c010b200a41286c210941002105200b21030340200441086a2903002106200441106a2903002110200441186a290300211120042903002112200341206a200441206a290300370300200341186a2011370300200341106a2010370300200341086a200637030020032012370300200341286a2103200541016a2105200441286a2104200941586a22090d000b0b20014184036a200c36020020014180036a2005360200200141f0026a410c6a200a360200200141f0026a41086a200b3602002001200f3602f402200141013602f002200141e0006a200141f0026a108f012001418b026a200141e0006a41086a2802003600002001200129036037008302200141e0006a410c6a20014187026a290000370000200141c6a4b9da04360061200141023a00602001200129008002370065200141e0006a109001200a450d00200b102c0b20012802d00221030b024020012802d40220036a2000470d004101102a2204450d06200142013702642001200436026020014101360268200141013a00a002200441013a000020012802d8022103200141e0026a2802002204200141e0006a106702402004450d002003200441286c6a210f03402003200141e0006a109101200341206a29030021060240024020012802642205200128026822046b4108490d00200128026021050c010b200441086a22092004490d0d200541017422042009200420094b1b22044100480d0d0240024020050d002004102a21050c010b200128026020052004102e21050b2005450d092001200436026420012005360260200128026821040b2001200441086a360268200520046a2006370000200f200341286a2203470d000b0b200141d8026a21032001280264210441b5b5c000ad4280808080c00284200135026842208620012802602205ad84100102402004450d002005102c0b200141e0006a41086a22042003290000370300200141e0006a41106a2205200341086a280000360200200141003602642001410b3a006041014100200141e0006a109201200141e0006a41186a220f420037030020054200370300200442003703002001420037036020014180026a41086a220341e0d9c500ad4280808080f001841002220941086a29000037030020012009290000370380022009102c20042003290300370300200120012903800222063703a00220012006370360200341beb9c000ad4280808080d001841002220941086a29000037030020012009290000370380022009102c200141a0026a41086a20032903002206370300200120012903800222103703a00220022010370000200241086a2006370000200141f0026a41086a2004290300370300200141f0026a41106a2005290300370300200141f0026a41186a200f290300370300200120012903603703f002200810050c010b200141dc026a280200450d0020012802d802102c0b200141e0006a41186a22094200370300200141e0006a41106a220f4200370300200141e0006a41086a220342003703002001420037036020014180026a41086a220441e0d9c500ad4280808080f001841002220541086a29000037030020012005290000370380022005102c20032004290300370300200120012903800222063703a00220012006370360200441cbb9c000ad4280808080d000841002220541086a29000037030020012005290000370380022005102c200141a0026a41086a20042903002206370300200120012903800222103703a00220022010370000200241086a2006370000200141f0026a41086a2003290300370300200141f0026a41106a200f290300370300200141f0026a41186a2009290300370300200120012903603703f00220014120360284022001200141f0026a36028002200141b0026a20081003108d0120012802b0022204450d03200141b0026a41086a280200210520012802b402210941002103200141003a00a0020240024002402005450d0020042d0000220f41034b0d00024002400240200f0e0405000102050b2005417f6a4108490d0220042900012106410121030c040b410221030c020b2005417f6a4108490d0020042900012106410321030c020b200141003602d802200142013703d0022001410b3602a402200120014180026a3602a0022001200141d0026a3602f001200141f4006a410136020020014201370264200141d0b0c2003602602001200141a0026a360270200141f0016a41c49ac500200141e0006a10391a20013502d80242208620013502d002841004024020012802d402450d0020012802d002102c0b410421030b0b02402009450d002004102c0b2003417f6a220441024b0d0320040e03020301020b103a000b2006422088a7210402402006a722032000470d00200141043602f002200120043602f402200141e0006a200141f0026a108f012001418b026a200141e8006a2802003600002001200129036037008302200141ec006a20014187026a290000370000200141c6a4b9da04360061200141023a00602001200129008002370065200141e0006a1090010b200420036a2000470d01200141003602d002200141e0006a41186a22094200370300200141e0006a41106a220f4200370300200141e0006a41086a220342003703002001420037036020014180026a41086a220441e0d9c500ad4280808080f001841002220541086a29000037030020012005290000370380022005102c20032004290300370300200120012903800222063703a00220012006370360200441cbb9c000ad4280808080d000841002220541086a29000037030020012005290000370380022005102c200141a0026a41086a20042903002206370300200120012903800222103703a00220022010370000200241086a2006370000200141f0026a41086a2003290300370300200141f0026a41106a200f290300370300200141f0026a41186a2009290300370300200120012903603703f002200141e0006a200141d0026a1093012008200135026842208620012802602204ad84100102402001280264450d002004102c0b200141023602642001410b3a006041014100200141e0006a1092010c010b2006422088a7210402402006a722032000470d00200141033602f002200120043602f402200141e0006a200141f0026a108f012001418b026a200141e8006a2802003600002001200129036037008302200141ec006a20014187026a290000370000200141c6a4b9da04360061200141023a00602001200129008002370065200141e0006a1090010b200420036a2000470d00200141023602d002200141e0006a41186a22094200370300200141e0006a41106a220f4200370300200141e0006a41086a220342003703002001420037036020014180026a41086a220441e0d9c500ad4280808080f001841002220541086a29000037030020012005290000370380022005102c20032004290300370300200120012903800222063703a00220012006370360200441cbb9c000ad4280808080d000841002220541086a29000037030020012005290000370380022005102c200141a0026a41086a20042903002206370300200120012903800222103703a00220022010370000200241086a2006370000200141f0026a41086a2003290300370300200141f0026a41106a200f290300370300200141f0026a41186a2009290300370300200120012903603703f002200141e0006a200141d0026a1093012008200135026842208620012802602204ad84100102402001280264450d002004102c0b200141013602642001410b3a006041014100200141e0006a1092010b200141e0006a41186a22054200370300200141e0006a41106a220e4200370300200141e0006a41086a2203420037030020014200370360200141e0016a41086a220441f9e8c500ad428080808090018422101002220941086a290000370300200120092900003703e0012009102c20032004290300370300200120012903e001370360200441de99c500ad4280808080e000841002220941086a290000370300200120092900003703e0012009102c200e20012903e0012206370300200141f0026a41086a220f2003290300370300200141f0026a41106a22022006370300200141f0026a41186a22002004290300370300200120063703d002200120012903603703f002200141d8006a200141f0026a4120109401200128025c210d02402001280258220a4101470d002007428080808080048410050b20054200370300200e42003703002003420037030020014200370360200420101002220941086a290000370300200120092900003703e0012009102c20032004290300370300200120012903e00137036020044183d7c500ad4280808080b001841002220941086a290000370300200120092900003703e0012009102c200141d0026a41086a20042903002206370300200120012903e00122103703d002200e2010370000200e41086a2006370000200f20032903003703002002200e29030037030020002005290300370300200120012903603703f00202400240200141f0026a109501220441ff01714102460d0020044101710d010b4104102a2203450d0120034100360200200141e0006a41186a220f4200370300200141e0006a41106a22024200370300200141e0006a41086a2205420037030020014200370360200141e0016a41086a220441f9e8c500ad42808080809001841002220941086a290000370300200120092900003703e0012009102c20052004290300370300200120012903e001370360200441e499c500ad4280808080b001841002220941086a290000370300200120092900003703e0012009102c200141d0026a41086a20042903002206370300200120012903e00122103703d002200e2010370000200e41086a2006370000200141f0026a41086a2005290300370300200141f0026a41106a2002290300370300200141f0026a41186a200f290300370300200120012903603703f00220014100360268200142013703604101200141e0006a10672003280200210f0240024020012802642209200128026822056b4104490d00200128026021040c010b200541046a22042005490d06200941017422022004200220044b1b22024100480d060240024020090d002002102a21040c010b200128026020092002102e21040b2004450d022001200236026420012004360260200221090b2001200541046a2202360268200420056a200f3600002007428080808080048422062002ad4220862004ad84100102402009450d002004102c0b2003102c4104102a2203450d0120034100360200200141e0006a41186a220f4200370300200141e0006a41106a22024200370300200141e0006a41086a2205420037030020014200370360200141e0016a41086a220441f9e8c500ad42808080809001841002220941086a290000370300200120092900003703e0012009102c20052004290300370300200120012903e001370360200441ec9ac500ad4280808080c001841002220941086a290000370300200120092900003703e0012009102c200141d0026a41086a20042903002210370300200120012903e00122113703d002200e2011370000200e41086a2010370000200141f0026a41086a2005290300370300200141f0026a41106a2002290300370300200141f0026a41186a200f290300370300200120012903603703f00220014100360268200142013703604101200141e0006a10672003280200210f0240024020012802642209200128026822056b4104490d00200128026021040c010b200541046a22042005490d06200941017422022004200220044b1b22024100480d060240024020090d002002102a21040c010b200128026020092002102e21040b2004450d022001200236026420012004360260200221090b2001200541046a2202360268200420056a200f36000020062002ad4220862004ad84100102402009450d002004102c0b2003102c200141e0006a41186a22054200370300200141e0006a41106a22094200370300200141e0006a41086a2203420037030020014200370360200141e0016a41086a220441f9e8c500ad428080808090018422101002220f41086a2900003703002001200f2900003703e001200f102c20032004290300370300200120012903e001370360200441f89ac500ad4280808080e000841002220f41086a2900003703002001200f2900003703e001200f102c200141d0026a41086a220220042903002211370300200120012903e00122123703d002200e2012370000200e41086a22002011370000200141f0026a41086a220b2003290300370300200141f0026a41106a220c2009290300370300200141f0026a41186a22132005290300370300200120012903603703f002200141003602602006200141e0006aad4280808080c00084100120054200370300200942003703002003420037030020014200370360200420101002220f41086a2900003703002001200f2900003703e001200f102c20032004290300370300200120012903e00137036020044183d7c500ad4280808080b001841002220f41086a2900003703002001200f2900003703e001200f102c200220042903002210370300200120012903e00122113703d002200e201137000020002010370000200b2003290300370300200c200929030037030020132005290300370300200120012903603703f002200141013a00a0022006200141a0026aad4280808080108410010b200141e0006a41186a22054200370300200141e0006a41106a22094200370300200141e0006a41086a2203420037030020014200370360200141e0016a41086a220441f9e8c500ad428080808090018422061002220f41086a2900003703002001200f2900003703e001200f102c20032004290300370300200120012903e001370360200441e499c500ad4280808080b001841002220f41086a2900003703002001200f2900003703e001200f102c200141d0026a41086a220220042903002210370300200120012903e00122113703d002200e2011370000200e41086a22002010370000200141f0026a41086a220b2003290300370300200141f0026a41106a220c2009290300370300200141f0026a41186a22142005290300370300200120012903603703f002200141e0006a200141f0026a10960102400240200128026022130d004104211341002115420021110c010b20012902642211422088a721150b20054200370300200942003703002003420037030020014200370360200420061002220f41086a2900003703002001200f2900003703e001200f102c20032004290300370300200120012903e001370360200441ec9ac500ad4280808080c001841002220f41086a2900003703002001200f2900003703e001200f102c200220042903002206370300200120012903e00122103703d002200e201037000020002006370000200b2003290300370300200c200929030037030020142005290300370300200120012903603703f002200141e0006a200141f0026a109601024002402001280260220f450d002001200f3602b00220012902642210422088a7210b0c010b4104210f200141043602b0024100210b420021100b02400240024002400240200a0d002015417f6a220420154f0d01200420154b0d01201320044102746a280200210d0b201541002015419c7f6a22042004201541016a4b1b2214490d012014450d03201320144102746a210c200bad21062013210a0340200a2802002102024002400240024002402006a7220041014b0d004100210420000e020201020b4100210420002103034020042003410176220520046a22092002200f20094102746a280200491b2104200320056b220341014b0d000b0b2002200f200441027422036a2802002205460d022004200220054b6a21040c010b410021040b2001200436026041a49bc500412e200141e0006a41d49bc500103b000b20062004ad580d03200f20036a2203200341046a2004417f7320006a41027410dc051a201042ffffffff0f832000417f6a220bad422086842110200a41046a220a200c460d042006427f7c210620012802b002210f0c000b0b41fe9ac50041261054000b41dafec500411c41acfec5001036000b418ab4c000411d41acfec5001036000b201142ffffffff0f8321060240201520146b2204450d0002402014450d002013201320144102746a200441027410dc051a2010422088a7210b0b20062004ad4220868421060b20012802b002210f41002104024002400240024002400240200b41014b0d00200b0e020201020b200b2103034020042003410176220520046a2209200d200f20094102746a280200491b2104200320056b220341014b0d000b0b0240200d200f20044102746a2802002203460d002004200d20034b6a21040b200b2004490d010b200b2010a7470d02200b41016a2203200b490d07200b41017422052003200520034b1b220341ffffffff03712003470d072003410274220541004e0d010c070b41ecb3c000411e41acfec5001036000b02400240200b0d002005102a210f0c010b200f200b4102742005102e210f0b200f450d012001200f3602b0022003ad21100b200f20044102746a220341046a2003200b20046b41027410dc051a2003200d360200024020064220882211a722032006a7470d00200341016a22042003490d052011a722094101742205200420042005491b220441ffffffff03712004470d05200441027422054100480d050240024020030d002005102a21130c010b201320094102742005102e21130b2013450d012006422088a721032004ad21060b201320034102746a200d3602000240200b41016a220c0d0041e49bc50041c30041acfec5001036000b200c200c41017622044d0d0120012802b002220520044102746a280200210d0240200c4101710d00200c2004417f6a22044d0d03200520044102746a280200200d6a410176210d0b200141e0006a41186a220f4200370300200141e0006a41106a22024200370300200141e0006a41086a2205420037030020014200370360200141e0016a41086a220441f9e8c500ad42808080809001841002220941086a290000370300200120092900003703e0012009102c20052004290300370300200120012903e001370360200441e499c500ad4280808080b001841002220941086a290000370300200120092900003703e0012009102c200141d0026a41086a20042903002211370300200120012903e00122123703d002200e2012370000200e41086a2011370000200141f0026a41086a2005290300370300200141f0026a41106a2002290300370300200141f0026a41186a200f290300370300200120012903603703f0022001410036026820014201370360200341016a2215200141e0006a10670240024020150d00200128026821022001280264210f200128026021030c010b4100200128026822046b2105200341027441046a21002001280264210f2013210903402009280200210a02400240200f20056a4104490d00200128026021030c010b200441046a22032004490d07200f41017422022003200220034b1b22024100480d0702400240200f0d002002102a21030c010b2001280260200f2002102e21030b2003450d0320012002360264200120033602602002210f0b200941046a21092001200441046a2202360268200320046a200a3600002005417c6a2105200221042000417c6a22000d000b0b2006a721042007428080808080048422062002ad4220862003ad8410010240200f450d002003102c0b02402004450d002013102c0b20012802b0022113200141e0006a41186a22094200370300200141e0006a41106a220f4200370300200141e0006a41086a2203420037030020014200370360200141e0016a41086a220441f9e8c500ad42808080809001841002220541086a290000370300200120052900003703e0012005102c20032004290300370300200120012903e001370360200441ec9ac500ad4280808080c001841002220541086a290000370300200120052900003703e0012005102c200141d0026a41086a20042903002211370300200120012903e00122123703d002200e2012370000200e41086a2011370000200141f0026a41086a2003290300370300200141f0026a41106a200f290300370300200141f0026a41186a2009290300370300200120012903603703f0022001420137036020014100360268200c200141e0006a1067200b41027441046a21024100200128026822046b21052010a7210b2001280264210f2013210903402009280200210a02400240200f20056a4104490d00200128026021030c010b200441046a22032004490d06200f41017422002003200020034b1b22004100480d0602400240200f0d002000102a21030c010b2001280260200f2000102e21030b2003450d0220012000360264200120033602602000210f0b200941046a21092001200441046a2200360268200320046a200a3600002005417c6a2105200021042002417c6a22020d000b20062000ad4220862003ad8410010240200f450d002003102c0b0240200b450d002013102c0b200141e0006a41186a22094200370300200141e0006a41106a22034200370300200141e0006a41086a2204420037030020014200370360200141e0016a41086a220541f9e8c500ad42808080809001841002220f41086a2900003703002001200f2900003703e001200f102c20042005290300370300200120012903e001370360200541f89ac500ad4280808080e000841002220f41086a2900003703002001200f2900003703e001200f102c200141d0026a41086a20052903002210370300200120012903e00122113703d002200e2011370000200e41086a2010370000200141f0026a41086a220f2004290300370300200141f0026a41106a22022003290300370300200141f0026a41186a22002009290300370300200120012903603703f0022001200d3602602006200141e0006aad22114280808080c0008410010240201541e500470d002009420037030020034200370300200442003703002001420037036020054191b0c200ad4280808080e000841002220a41086a2900003703002001200a2900003703e001200a102c20042005290300370300200120012903e001370360200541acb0c200ad4280808080e000841002220a41086a2900003703002001200a2900003703e001200a102c200320012903e0012206370300200f20042903003703002002200637030020002005290300370300200120063703d002200120012903603703f002200141d0006a200141f0026a4120109401200d419a086a2001280254410020012802501b4b0d00200141e0006a41186a220c4200370300200141e0006a41106a220e4200370300200141e0006a41086a220a420037030020014200370360200141e0016a41086a220541e0d9c500ad4280808080f001841002220b41086a2900003703002001200b2900003703e001200b102c200a2005290300370300200120012903e001370360200541aeb5c000ad4280808080f000841002220b41086a2900003703002001200b2900003703e001200b102c200141d0026a41086a20052903002206370300200120012903e00122103703d00220032010370000200341086a2006370000200141f0026a41086a200a290300370300200141f0026a41106a200e290300370300200141f0026a41186a200c290300370300200120012903603703f0024108102a2205450d012005200d360004200541e400360000200742808080808004842005ad428080808080018410012005102c0b2009420037030020034200370300200442003703002001420037036020014180026a41086a22054196e0c500ad4280808080f0008422101002220941086a29000037030020012009290000370380022009102c20042005290300370300200120012903800222063703d00220012006370360200541e6f8c200ad4280808080f0018422121002220941086a29000037030020012009290000370380022009102c20032001290380022206370300200f20042903003703002002200637030020002005290300370300200120063703d002200120012903603703f002200141c8006a200141f0026a4120410141004100109701024020012802484101460d00200141e0006a41186a220f4200370300200141e0006a41106a22094200370300200141e0006a41086a220542003703002001420037036020014180026a41086a220441f9e8c500ad42808080809001841002220241086a29000037030020012002290000370380022002102c2005200429030037030020012001290380023703602004419db1c200ad428080808030841002220241086a29000037030020012002290000370380022002102c20092001290380022206370300200141f0026a41086a22002005290300370300200141f0026a41106a220a2006370300200141f0026a41186a220b2004290300370300200120063703d002200120012903603703f002200141386a200141f0026a109801200129034021062001280238210c200f4200370300200942003703002005420037030020014200370360200420101002220241086a29000037030020012002290000370380022002102c20052004290300370300200120012903800222103703d00220012010370360200420121002220241086a29000037030020012002290000370380022002102c200141d0026a41086a20042903002210370300200120012903800222123703d00220032012370000200341086a201037000020002005290300370300200a2009290300370300200b200f290300370300200120012903603703f002200120064200200c1b370360200742808080808004842011428080808080018410010b200141e0006a41186a22024200370300200141e0006a41106a22034200370300200141e0006a41086a2205420037030020014200370360200141f0016a41086a2204418be9c500ad42808080808001841002220941086a290000370300200120092900003703f0012009102c20052004290300370300200120012903f00122063703d0022001200637036020044193e9c500ad42808080809002841002220941086a290000370300200120092900003703f0012009102c200320012903f0012206370300200141f0026a41086a2005290300370300200141f0026a41106a2006370300200141f0026a41186a2004290300370300200120063703d002200120012903603703f002200141286a200141f0026a109801200129033021102001280228210020014180026a41186a420037030020014180026a41106a220a420037030020014180026a41086a22094200370300200142003703800220044191b0c200ad4280808080e000841002220f41086a2900003703002001200f2900003703f001200f102c20092004290300370300200120012903f00137038002200441e0c2c200ad4280808080b002841002220f41086a2900003703002001200f2900003703f001200f102c200a20012903f0012206370300200520092903003703002003200637030020022004290300370300200120063703a0022001200129038002370360200141206a200141e0006a4120109401200141106a2001280224410020012802201b22044180e59af70020044180e59af7004b22051b4180e59af700200420051b6bad220642002006420010e005200642a8c3018021122010420020001b210642092001290310221042808090bbbad6adf00d7f20012903182010423f87521b211002400240200441ffe49af7004b0d0042ffffffffffffffffff00428080808080808080807f2006201220107d22127d22104200531b20102006427f5522042012427f554720042010427f5547711b22064280ec94a37c20064280ec94a37c551b21060c010b42ffffffffffffffffff00428080808080808080807f2006201220107c22127c22104200531b20102006427f5522042012427f554620042010427f5547711b21060b200141e0006a41186a22094200370300200141e0006a41106a22054200370300200141e0006a41086a2204420037030020014200370360200141f0016a41086a220f418be9c500ad42808080808001841002220241086a290000370300200120022900003703f0012002102c2004200f290300370300200120012903f00122103703d00220012010370360200f4193e9c500ad42808080809002841002220241086a290000370300200120022900003703f0012002102c200141d0026a41086a200f2903002210370300200120012903f00122123703d00220032012370000200341086a2010370000200141f0026a41086a220f2004290300370300200141f0026a41106a22022005290300370300200141f0026a41186a22002009290300370300200120012903603703f0022001200637036020074280808080800484220620114280808080800184100120094200370300200542003703002004420037030020014200370360200141a0026a41086a220341a4c6c500ad4280808080a0018422121002220a41086a2900003703002001200a2900003703a002200a102c20042003290300370300200120012903a00222103703d00220012010370360200341baecc100ad4280808080e000841002220a41086a2900003703002001200a2900003703a002200a102c200520012903a0022210370300200f20042903003703002002201037030020002003290300370300200120103703d002200120012903603703f0022006100520094200370300200542003703002004420037030020014200370360200320121002220a41086a2900003703002001200a2900003703a002200a102c20042003290300370300200120012903a00222103703d00220012010370360200341aec6c500ad4280808080c001841002220a41086a2900003703002001200a2900003703a002200a102c200920032903002210370300200f2004290300370300200220012903a002221237030020002010370300200120123703d002200120012903603703f0022006100520094200370300200542003703002004420037030020014200370360200141e0016a41086a220341f9e8c500ad42808080809001841002220941086a290000370300200120092900003703e0012009102c20042003290300370300200120012903e00137036020034182e9c500ad42808080809001841002220941086a290000370300200120092900003703e0012009102c200520012903e0012210370300200f200429030037030020022010370300200020032903003703002001201037038002200120012903603703f002200141f0026a109501220441ff01714102460d03200610052004410171450d03200141e0006a41186a4200370300200141e0006a41106a22094200370300200141e0006a41086a2203420037030020014200370360200141e0016a41086a220441bac6c500ad4280808080c000841002220541086a290000370300200120052900003703e0012005102c20032004290300370300200120012903e0012206370380022001200637036020044183d7c500ad4280808080b001841002220541086a290000370300200120052900003703e0012005102c200920012903e0012206370300200141f0026a41086a2003290300370300200141f0026a41106a2006370300200141f0026a41186a2004290300370300200120063703a002200120012903603703f002200141e0006a200141f0026a109901024020012d006022044102460d00200742808080808004841005200141b0026a41086a200141e9006a290000370300200141b0026a41106a200141f1006a290000370300200141b0026a41186a200141f9006a290000370300200120012900613703b0020240200441037122044103460d0020040e03010001010b200141d0026a41186a200141b0026a41186a290300370300200141d0026a41106a200141b0026a41106a290300370300200141d0026a41086a200141b0026a41086a290300370300200120012903b0023703d002200141e0006a41186a22054200370300200141e0006a41106a220f4200370300200141e0006a41086a2203420037030020014200370360200141e0016a41086a220441bac6c500ad4280808080c0008422061002220241086a290000370300200120022900003703e0012002102c20032004290300370300200120012903e0012210370380022001201037036020044181c7c500ad4280808080c001841002220241086a290000370300200120022900003703e0012002102c200141a0026a41086a220220042903002210370300200120012903e00122123703a00220092012370000200941086a2010370000200141f0026a41086a2003290300370300200141f0026a41106a200f290300370300200141f0026a41186a2005290300370300200120012903603703f002200141086a200141f0026a4120109401200128020c210a2001280208210b200420061002220041086a290000370300200120002900003703e0012000102c200141f0016a41086a220c2004290300370300200120012903e0013703f0012004418dc7c500ad42808080809002841002220041086a290000370300200120002900003703e0012000102c20022004290300370300200120012903e0013703a0022001200a4100200b1b22003602f00220014180026a41186a220a20074280808080c000841006220441186a29000037030020014180026a41106a220b200441106a29000037030020014180026a41086a220e200441086a29000037030020012004290000370380022004102c2005200a290300370300200f200b2903003703002003200e290300370300200120012903800237036041c000102a2204450d01200420012903f001370000200441086a200c290300370000200420012903a002370010200441186a200229030037000020042001290360370020200441286a2003290300370000200441306a200f290300370000200441386a2005290300370000200141e0006a200441c000109a010240024020012802602203450d002001200129026422063702940320012003360290032006422088a721052006a7210f0c010b4100210520014100360298032001420137039003410121034100210f0b2004102c024002402005418002490d004120102a2203450d03200320012903d002370000200341186a200141d0026a41186a290300370000200341106a200141d0026a41106a290300370000200341086a200141d0026a41086a290300370000200141e0016a41086a220441bac6c500ad4280808080c000841002220541086a290000370300200120052900003703e0012005102c200141f0016a41086a220f2004290300370300200120012903e0013703f0012004418dc7c500ad42808080809002841002220541086a290000370300200120052900003703e0012005102c200141a0026a41086a22052004290300370300200120012903e0013703a0022001200041016a22023602f00220014180026a41186a220020074280808080c000841006220441186a29000037030020014180026a41106a220a200441106a29000037030020014180026a41086a220b200441086a29000037030020012004290000370380022004102c200141e0006a41186a220c2000290300370300200141e0006a41106a2200200a290300370300200141e0006a41086a220a200b290300370300200120012903800237036041c000102a2204450d03200420012903f001370000200441086a200f290300370000200420012903a002370010200441186a200529030037000020042001290360370020200441286a200a290300370000200441306a2000290300370000200441386a200c290300370000200141e0006a20034101109b012004ad4280808080800884200135026842208620012802602205ad84100102402001280264450d002005102c0b2004102c2003102c200141e0006a41186a220f4200370300200141e0006a41106a22004200370300200141e0006a41086a2203420037030020014200370360200141e0016a41086a220441bac6c500ad4280808080c000841002220541086a290000370300200120052900003703e0012005102c20032004290300370300200120012903e0012206370380022001200637036020044181c7c500ad4280808080c001841002220541086a290000370300200120052900003703e0012005102c200141a0026a41086a20042903002206370300200120012903e00122103703a00220092010370000200941086a2006370000200141f0026a41086a2003290300370300200141f0026a41106a2000290300370300200141f0026a41186a200f290300370300200120012903603703f002200120023602602007428080808080048420114280808080c0008410010c010b200141e0006a41186a2209200141d0026a41186a290300370300200141e0006a41106a2202200141d0026a41106a290300370300200141e0006a41086a220a200141d0026a41086a290300370300200120012903d00237036002402005200f470d00200f41016a2204200f490d07200f410174220b2004200b20044b1b220441ffffff3f712004470d072004410574220b4100480d0702400240200f0d00200b102a21030c010b2003200f410574200b102e21030b2003450d03200120043602940320012003360290030b200320054105746a22042001290360370000200441186a2009290300370000200441106a2002290300370000200441086a200a2903003700002001200541016a220f36029803200141e0016a41086a220441bac6c500ad4280808080c000841002220541086a290000370300200120052900003703e0012005102c200141f0016a41086a2004290300370300200120012903e0013703f0012004418dc7c500ad42808080809002841002220541086a290000370300200120052900003703e0012005102c200141a0026a41086a2004290300370300200120012903e0013703a002200120003602f00220014180026a41186a220520074280808080c000841006220441186a29000037030020014180026a41106a2200200441106a29000037030020014180026a41086a220b200441086a29000037030020012004290000370380022004102c2009200529030037030020022000290300370300200a200b290300370300200120012903800237036041c000102a2204450d02200420012903f001370000200441086a200141f0016a41086a290300370000200420012903a002370010200441186a200141a0026a41086a29030037000020042001290360370020200441286a200141e0006a41086a290300370000200441306a200141f0006a290300370000200441386a200141e0006a41186a290300370000200141e0006a2003200f109b012004ad4280808080800884200135026842208620012802602203ad84100102402001280264450d002003102c0b2004102c0b200128029403450d00200128029003102c0b200141a0036a24000f0b1033000b41d087c6002004200c1038000b41d087c6002004200c1038000b41f2b0c200412b41acfec5001036000b1035000ba60101047f230041206b2202240020022001a7220336020820022001422088a7220436020c02402004450d0020032d0000210520022004417f6a36020c2002200341016a360208200541014b0d00410021030240024020050e020100010b200241106a200241086a107720022802102203450d01200229021421010b2000200137020420002003360200200241206a24000f0b41d88bc600412e200241106a41888cc600103b000bbd0101047f230041106b22022400200028020421032000280200210041012104200128021841d1afc00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d0003402002200036020c20022002410c6a41dc9ac50010621a200041016a21002003417f6a22030d000b20022d000421050b0240200541ff01710d002002280200220028021841d2afc00041012000411c6a28020028020c11000021040b200241106a240020040be40c03047f017e027f230041106b2202240020024100360208200242013703000240024002402001280200220341044b0d000240024002400240024020030e050001020304000b4101102a2203450d05200242818080801037020420022003360200200341013a0000200128020421042001410c6a28020022032002106702402003450d002004200341286c6a2105034020042002109101200441206a29030021060240024020022802042207200228020822036b4108490d00200228020021070c010b200341086a22082003490d09200741017422032008200320084b1b22034100480d090240024020070d002003102a21070c010b200228020020072003102e21070b2007450d082002200336020420022007360200200228020821030b2002200341086a360208200720036a20063700002005200441286a2204470d000b0b200141106a28020021070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d07200441017422032008200320084b1b22034100480d070240024020040d002003102a21040c010b200228020020042003102e21040b2004450d062002200336020420022004360200200228020821030b2002200341046a360208200420036a20073600000c040b4101102a2203450d04200242818080801037020420022003360200200341023a0000200128020421070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d06200441017422052008200520084b1b22084100480d060240024020040d002008102a21040c010b200228020020042008102e21040b2004450d0520022008360204200220043602000b2002200341046a360208200420036a200736000020012802082104200141106a28020022032002106702402003450d002004200341286c6a2105034020042002109101200441206a29030021060240024020022802042207200228020822036b4108490d00200228020021070c010b200341086a22082003490d08200741017422032008200320084b1b22034100480d080240024020070d002003102a21070c010b200228020020072003102e21070b2007450d072002200336020420022007360200200228020821030b2002200341086a360208200720036a20063700002005200441286a2204470d000b0b200141146a28020021070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d06200441017422032008200320084b1b22034100480d060240024020040d002003102a21040c010b200228020020042003102e21040b2004450d052002200336020420022004360200200228020821030b2002200341046a360208200420036a20073600000c030b4101102a2203450d03200242818080801037020420022003360200200341033a0000200141086a29030021060240024020022802042207200228020822036b4108490d00200341086a2104200228020021070c010b200341086a22042003490d05200741017422082004200820044b1b22084100480d050240024020070d002008102a21070c010b200228020020072008102e21070b2007450d0420022008360204200220073602000b20022004360208200720036a20063700000c020b4101102a2203450d02200242818080801037020420022003360200200341043a0000200128020421070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d04200441017422012008200120084b1b22084100480d040240024020040d002008102a21040c010b200228020020042008102e21040b2004450d0320022008360204200220043602000b2002200341046a360208200420036a20073600000c010b4101102a2203450d01200242818080801037020420022003360200200341053a0000200128020421080240024020022802042207200228020822036b4104490d00200341046a2104200228020021070c010b200341046a22042003490d03200741017422012004200120044b1b22014100480d030240024020070d002001102a21070c010b200228020020072001102e21070b2007450d0220022001360204200220073602000b20022004360208200720036a20083600000b20002002290300370200200041086a200241086a280200360200200241106a24000f0b1033000b1035000beb0807017f017e057f017e017f017e027f230041f0006b2201240042002102200141386a41186a22034200370300200141386a41106a22044200370300200141386a41086a2205420037030020014200370338200141e0006a41086a22064191b0c200ad4280808080e000841002220741086a290000370300200120072900003703602007102c2005200629030037030020012001290360220837032820012008370338200641cab0c200ad4280808080e000841002220741086a290000370300200120072900003703602007102c200420012903602208370300200141086a41086a2005290300370300200141086a41106a2008370300200141086a41186a20062903003703002001200837032820012001290338370308200141386a200141086a10e40202400240200128023822070d004104210741002106410021090c010b200129023c2202422088a721062002a721090b200141386a41206a200041206a2802003602002003200041186a2902003703002004200041106a2902003703002005200041086a2902003703002001200029020037033802400240024020062009470d00024020062002a7470d00200641016a22002006490d03200641017422052000200520004b1bad220842247e220a422088a70d03200aa722004100480d030240024020060d002000102a21070c010b2007200641246c2000102e21070b2007450d0220024280808080708320088421020b2002422088a721060b2007200641246c220b6a22002001290338370200200041206a200141386a41206a280200360200200041186a200141386a41186a2203290300370200200041106a200141386a41106a2209290300370200200041086a200141386a41086a220029030037020020034200370300200942003703002000420037030020014200370338200141e0006a41086a22054191b0c200ad4280808080e000841002220c41086a2900003703002001200c290000370360200c102c2000200529030037030020012001290360220837032820012008370338200541cab0c200ad4280808080e000841002220c41086a2900003703002001200c290000370360200c102c200141286a41086a2005290300220837030020012001290360220a3703282004200a370000200441086a2008370000200141086a41086a2000290300370300200141086a41106a2009290300370300200141086a41186a2003290300370300200120012903383703082001412036023c2001200141086a3602382007200641016a2200200141386a10da03024020002006490d00200b41246a21002007210603400240024020062d0000220441034b0d0002400240024020040e0404000102040b2006410c6a280200450d03200641086a280200102c0c030b2006410c6a280200450d02200641086a280200102c0c020b2006410c6a280200450d01200641086a280200102c0c010b200641086a280200450d00200641046a280200102c0b200641246a21062000415c6a22000d000b0b02402002a7450d002007102c0b200141f0006a24000f0b1033000b1035000bdb2601067f20002d000021020240024002400240200141046a2203280200200141086a22042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0001210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0002210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0003210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0004210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0005210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0006210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0007210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0008210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0009210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000a210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000b210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000c210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000d210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000e210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000f210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0010210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0011210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0012210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0013210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0014210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0015210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0016210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0017210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0018210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0019210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001a210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001b210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001c210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001d210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001e210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001f210502400240200328020020042802002200460d00200128020021030c010b200041016a22032000490d02200041017422062003200620034b1b22064100480d020240024020000d002006102a21030c010b200128020020002006102e21030b2003450d0120012003360200200141046a2006360200200141086a28020021000b2004200041016a360200200320006a20053a00000f0b1033000b1035000be32303087f037e097f23004180046b22032400200341186a4181b0c2004110109401200328021c21042003280218210541012106410021074100210802400240024002402001450d00200141057422074100480d022007102a2206450d012001410574220941606a410576210a20062107200021080340200841086a290000210b200841106a290000210c200841186a290000210d20072008290000370000200741186a200d370000200741106a200c370000200741086a200b370000200741206a2107200841206a2108200941606a22090d000b200a41016a2108200121070b200341a4016a200436020020032005453602a001200341206a200241800110db051a200341b0016a2008360200200341ac016a2007360200200320063602a80120034180036a41186a2206420037030020034180036a41106a2209420037030020034180036a41086a220842003703002003420037038003200341e0036a41086a22074191b0c200ad4280808080e00084220c1002220241086a290000370300200320022900003703e0032002102c20082007290300370300200320032903e003220b3703f0022003200b37038003200741e4c4c200ad4280808080a00184220d1002220241086a290000370300200320022900003703e0032002102c200920032903e003220b370300200341d0026a41086a22022008290300370300200341d0026a41106a200b370300200341d0026a41186a220420072903003703002003200b3703c80320032003290380033703d002200341106a200341d0026a412010940102400240024002400240024002400240024002402003280214410020032802101b220541016a220e2005490d002006420037030020034180036a41106a220a42003703002008420037030020034200370380032007200c1002220f41086a2900003703002003200f2900003703e003200f102c20082007290300370300200320032903e003220b3703f0022003200b370380032007200d1002220f41086a2900003703002003200f2900003703e003200f102c200341c8036a41086a220f2007290300220b370300200320032903e003220d3703c8032009200d370000200941086a2210200b37000020022008290300370300200341d0026a41106a2211200a2903003703002004200629030037030020032003290380033703d0022003200e3602b801200341d0026aad4280808080800484220b200341b8016aad4280808080c000841001200341b8016a200341206a41980110db051a20064200370300200a42003703002008420037030020034200370380032007200c1002220e41086a2900003703002003200e2900003703e003200e102c20082007290300370300200320032903e003220c3703f0022003200c37038003200741fdb1c200ad4280808080e000841002220e41086a2900003703002003200e2900003703e003200e102c200f2007290300220c370300200320032903e003220d3703c8032009200d3700002010200c370000200220082903003703002011200a2903003703002004200629030037030020032003290380033703d002200341c8036a200b1003108d010240024020032802c803450d00200341a0036a41086a200341c8036a41086a280200360200200320032903c8033703a0030c010b200341003602e803200342083703e00320034100360288032003420137038003410020034180036a1067200341a8036a20032802880336020020032003290380033703a003200341e0036a107d0b200341b0036a41086a200341a0036a41086a2802002207360200200320032903a0033703b003024002402007450d0020034180036a20032802b0032007410110db032003280280034101470d0120032802b403450d0920032802b003102c0c090b4101200341b0036a1067200341b8016a200341b0036a10dc030c060b200328028403210202402003418c036a280200220720034180036a41086a2802002208460d0020032802b803200720086b6a220641046a2204417f4c0d0d0240024020040d004101210a0c010b2004102a220a450d0c0b200320043602f4022003200a3602f002200320063602f8022003200341f0026a36028003200220034180036a200710c80220062007490d0220032802f80222022006490d0320032802b80322022008490d0420032802f002210420032802b003210a2003200620076b22063602c0032003200220086b22023602c40320062002470d05200420076a200a20086a200610db051a200341b8016a200341f0026a10dc0320032802f802210820032802f402210620032802f002210720032802b403450d0720032802b003102c0c070b2003200341b0036a36028003200220034180036a200810c802200341b8016a200341b0036a10dc030c050b200341206a10dd030c080b200720061047000b20062002103f000b200820021047000b200341e0036a41146a4109360200200341ec036a410c360200200341c8036a41146a4103360200200342033702cc03200341ec9fc6003602c8032003410c3602e4032003200341c0036a3602f8032003200341c4036a3602fc0320034204370390032003420137028403200341c0a0c600360280032003200341e0036a3602d803200320034180036a3602f0032003200341fc036a3602e8032003200341f8036a3602e003200341c8036a41fca0c6001041000b20032802b803210820032802b403210620032802b00321070b20070d010b200341b8016a10dd030c010b200b2008ad4220862007ad84100102402006450d002007102c0b200341b8016a10dd0320034180036a41186a2202420037030020034180036a41106a2204420037030020034180036a41086a220642003703002003420037038003200341e0036a41086a22084191b0c200ad4280808080e00084220c1002220741086a290000370300200320072900003703e0032007102c20062008290300370300200320032903e003220b3703f0022003200b37038003200841acb0c200ad4280808080e000841002220741086a290000370300200320072900003703e0032007102c200341c8036a41086a220a2008290300220b370300200320032903e003220d3703c8032009200d370000200941086a200b370000200341d0026a41086a22112006290300370300200341d0026a41106a22122004290300370300200341d0026a41186a2213200229030037030020032003290380033703d002200341086a200341d0026a41201094012001450d00200328020c410020032802081b21142001410574211003402008200c1002220741086a290000370300200320072900003703e0032007102c200341f0026a41086a22092008290300370300200320032903e0033703f00220084183b2c200ad4280808080b001841002220741086a290000370300200320072900003703e0032007102c200a2008290300370300200320032903e0033703c803200341b8016a41186a220142011006220741186a290000370300200341b8016a41106a220e200741106a290000370300200341b8016a41086a220f200741086a290000370300200320072900003703b8012007102c200220012903003703002004200e2903003703002006200f290300370300200320032903b8013703800341c000102a2207450d02200720032903f002370000200720032903c8033700102007200329038003370020200741086a2009290300370000200741186a200a290300370000200741286a2006290300370000200741306a2004290300370000200741386a2002290300370000200341d0026a2000109f01200741c000418001102e2207450d02200720032903d002370040200741d8006a2013290300370000200741d0006a2012290300370000200741c8006a201129030037000020034180036a2007ad4280808080800c84220b1003108d01024002402003280280032201450d002003280288032109200328028403210e0c010b200341003602c001200342013703b8014100200341b8016a106720032802c001210920032802bc01210e20032802b80121010b200320093602d0032003200e3602cc03200320013602c8030240024002400240024002400240024002400240024002402009450d00200341b8016a20012009410110db0320032802b8014101460d0420032802bc01210f20032802c401220920032802c0012201460d0320032802d003200920016b6a220e41046a2215417f4c0d1020150d01410121160c020b4101200341c8036a10670240024020032802cc03220120032802d00322096b4104490d0020032802c80321010c010b200941046a220e2009490d0f20014101742209200e2009200e4b1b22094100480d0f0240024020010d002009102a21010c010b20032802c80320012009102e21010b2001450d0e200320093602cc03200320013602c80320032802d00321090b2003200941046a3602d003200120096a20143600000240024020032802cc03220120032802d00322096b4104490d0020032802c80321010c010b200941046a220e2009490d0f20014101742209200e2009200e4b1b22094100480d0f0240024020010d002009102a21010c010b20032802c80320012009102e21010b2001450d0e200320093602cc03200320013602c80320032802d00321090b2003200941046a3602d003200120096a20053600000c080b2015102a2216450d0c0b200320153602d402200320163602d0022003200e3602d8022003200341d0026a3602b801200f200341b8016a200910c802200e2009490d0220032802d802220f200e490d0320032802d003220f2001490d0420032802d002211520032802c80321162003200e20096b220e3602fc032003200f20016b220f3602a003200e200f470d05201520096a201620016a200e10db051a0240024020032802d402220120032802d80222096b4104490d0020032802d00221010c010b200941046a220e2009490d0d20014101742209200e2009200e4b1b22094100480d0d0240024020010d002009102a21010c010b20032802d00220012009102e21010b2001450d0c200320093602d402200320013602d00220032802d80221090b2003200941046a3602d802200120096a20143600000240024020032802d402220120032802d80222096b4104490d0020032802d00221010c010b200941046a220e2009490d0d20014101742209200e2009200e4b1b22094100480d0d0240024020010d002009102a21010c010b20032802d00220012009102e21010b2001450d0c200320093602d402200320013602d00220032802d80221090b2003200941046a3602d802200120096a200536000020032802d802210120032802d402210e20032802d002210920032802cc03450d0720032802c803102c0c070b2003200341c8036a3602b801200f200341b8016a200110c8020240024020032802cc03220120032802d00322096b4104490d0020032802c80321010c010b200941046a220e2009490d0c20014101742209200e2009200e4b1b22094100480d0c0240024020010d002009102a21010c010b20032802c80320012009102e21010b2001450d0b200320093602cc03200320013602c80320032802d00321090b2003200941046a3602d003200120096a20143600000240024020032802cc03220120032802d00322096b4104490d0020032802c80321010c010b200941046a220e2009490d0c20014101742209200e2009200e4b1b22094100480d0c0240024020010d002009102a21010c010b20032802c80320012009102e21010b2001450d0b200320093602cc03200320013602c80320032802d00321090b2003200941046a3602d003200120096a20053600000c050b20032802cc03450d0620032802c803102c0c060b2009200e1047000b200e200f103f000b2001200f1047000b200341e0036a41146a4109360200200341ec036a410c36020020034180036a41146a41033602002003420337028403200341ec9fc600360280032003410c3602e4032003200341fc036a3602b0032003200341a0036a3602f002200342043703c801200342013702bc01200341c0a0c6003602b8012003200341e0036a360290032003200341b8016a3602f0032003200341f0026a3602e8032003200341b0036a3602e00320034180036a41fca0c6001041000b20032802d003210120032802cc03210e20032802c80321090b2009450d00200b2001ad4220862009ad8410010240200e450d002009102c0b200041206a21002007102c201041606a22100d010c020b0b2007102c0b20034180046a24000f0b1033000b1035000b103a000b8c0201037f024002400240024002400240024020012802000e0400010203000b410121024101102a2201450d05200141003a0000410121030c040b4101102a2202450d04200241013a000020012802042103200241014105102e2202450d042002200336000120012802082104410a210320024105410a102e2201450d04200120043600050c020b410121024101102a2201450d03200141023a0000410121030c020b4101102a2202450d02200241033a000020012802042103200241014105102e2202450d022002200336000120012802082104410a210320024105410a102e2201450d02200120043600050b410921020b2000200236020820002003360204200020013602000f0b1033000b8f0201037f230041d0006b220324002003200236020420032001360200200341086a2002ad4220862001ad841003108d0102400240200328020822040d00410021010c010b200328020c210502400240200341106a2802004104490d0020042800002102410121010c010b4100210120034100360220200342013703182003410b36022c200320033602282003200341186a360234200341cc006a41013602002003420137023c200341d0b0c2003602382003200341286a360248200341346a41c49ac500200341386a10391a200335022042208620033502188410040240200328021c450d002003280218102c0b0b2005450d002004102c0b2000200236020420002001360200200341d0006a24000b950201047f230041d0006b220124002001412036020420012000360200200141086a2000ad42808080808004841003108d0102400240200128020822020d00410221000c010b200128020c210302400240200141106a280200450d0020022d0000220441014b0d0041002100024020040e020200020b410121000c010b20014100360220200142013703182001410b36022c200120013602282001200141186a360234200141cc006a41013602002001420137023c200141d0b0c2003602382001200141286a360248200141346a41c49ac500200141386a10391a200135022042208620013502188410040240200128021c450d002001280218102c0b410221000b2003450d002002102c0b200141d0006a240020000bbc0201027f230041e0006b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022010d00200041003602000c010b200228021421032002200241106a41086a28020036022420022001360220200241c8006a200241206a107e024002402002280248450d0020002002290348370200200041086a200241c8006a41086a2802003602000c010b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241d0b0c2003602482002200241386a360258200241c4006a41c49ac500200241c8006a10391a2002350230422086200235022884100420004100360200200228022c450d002002280228102c0b2003450d002001102c0b200241e0006a24000b940102017f017e230041106b2206240002402002ad4220862001ad842004ad4220862003ad84200510282207422088a72203450d002007a722042d0000220241014b0d00410021050240024020020e020100010b2003417f6a4104490d0120042800012101410121050b2000200136020420002005360200200641106a24000f0b41d88bc600412e200641086a41888cc600103b000b990204017f017e017f017e230041d0006b220224002002412036020420022001360200200241086a2001ad42808080808004841003108d0102400240200228020822010d00420021030c010b200228020c210402400240200241086a41086a2802004108490d0020012900002105420121030c010b20024100360220200242013703182002410b36022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241d0b0c2003602382002200241286a360248200241346a41c49ac500200241386a10391a200235022042208620023502188410040240200228021c450d002002280218102c0b420021030b2004450d002001102c0b2000200537030820002003370300200241d0006a24000bd80402067f047e230041f0006b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022030d00200041023a00000c010b2002280214210402400240200241186a2802002205450d0020032d0000220641014b0d00410021010240024020060e020100010b41002101200241003a0068200341016a21072005417f6a21060340024020062001470d00200141ff0171450d03200241003a00680c030b200241c8006a20016a200720016a2d00003a00002002200141016a22053a00682005210120054120470d000b200241206a41186a200241c8006a41186a290300370300200241206a41106a200241c8006a41106a290300370300200241206a41086a200241c8006a41086a29030037030020022002290348370320410121010b200241c8006a41186a200241206a41186a2903002208370300200241c8006a41106a200241206a41106a2903002209370300200241c8006a41086a200241206a41086a290300220a37030020022002290320220b370348200041196a2008370000200041116a2009370000200041096a200a3700002000200b3700010c010b20024100360228200242013703202002410b3602442002200241086a3602402002200241206a36026c200241dc006a41013602002002420137024c200241d0b0c2003602482002200241c0006a360258200241ec006a41c49ac500200241c8006a10391a2002350228422086200235022084100402402002280224450d002002280220102c0b410221010b200020013a00002004450d002003102c0b200241f0006a24000bdf06010c7f23004190016b220324002003200236021420032001360210200341186a2002ad4220862001ad841003108d0102400240200328021822040d00200041003602000c010b200328021c21052003200341206a28020036023c20032004360238200341086a200341386a1075024002400240024020032802080d0002400240200328023c22014160712202417f4c0d00200328020c210602400240200141057622070d00410121080c010b2002102a2208450d020b02402006450d004100210903402001210a200341003a0088012009220b41016a2109410021010240024002400340200a2001460d01200341e8006a20016a200328023822022d00003a00002003200241016a3602382003200141016a22023a0088012002210120024120470d000b200341c8006a41186a220c200341e8006a41186a290300370300200341c8006a41106a220d200341e8006a41106a290300370300200341c8006a41086a220e200341e8006a41086a290300370300200320032903683703482007200b470d020240200b41017422012009200120094b1b220741ffffff3f712007470d002007410574220141004e0d020b1035000b2003410036023c0240200141ff0171450d00200341003a0088010b200341003602282007450d072008102c0c070b02400240200b0d002001102a21080c010b2008200b4105742001102e21080b2008450d040b200a20026b21012008200b4105746a220b2003290348370000200b41186a200c290300370000200b41106a200d290300370000200b41086a200e29030037000020092006470d000b200341306a20063602002003200736022c200320083602282003200a20026b36023c0c050b200341306a20063602002003200736022c2003200836022820080d040c030b103a000b1033000b200341003602280b20034100360250200342013703482003410b36022c2003200341106a3602282003200341c8006a360244200341fc006a41013602002003420137026c200341d0b0c2003602682003200341286a360278200341c4006a41c49ac500200341e8006a10391a2003350250422086200335024884100420004100360200200328024c450d012003280248102c0c010b20002003290328370200200041086a200341286a41086a2802003602000b2005450d002004102c0b20034190016a24000bed2401057f230041106b2203240020034100360208200342013703002002200310670240024002402002450d00200120024105746a2104034020012d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141016a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141026a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141036a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141046a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141056a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141066a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141076a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141086a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141096a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001410a6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001410b6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001410c6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001410d6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001410e6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001410f6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141106a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141116a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141126a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141136a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141146a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141156a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141166a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141176a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141186a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141196a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001411a6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001411b6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001411c6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001411d6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001411e6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a00002001411f6a2d0000210502400240200328020420032802082202460d00200328020021060c010b200241016a22062002490d04200241017422072006200720064b1b22074100480d040240024020020d002007102a21060c010b200328020020022007102e21060b2006450d0320032007360204200320063602000b2003200241016a360208200620026a20053a0000200141206a22012004470d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b1033000b1035000b9a0808017f027e037f017e017f027e047f037e23004190016b22032400200341206a200020012002109d01200341206a41086a290300210420032903202105200341d0006a41186a22064200370300200341d0006a41106a22074200370300200341d0006a41086a220842003703002003420037035020034180016a41086a2200418be9c500ad428080808080018422091002220a41086a2900003703002003200a29000037038001200a102c200820002903003703002003200329038001220b3703702003200b370350200041c9b5c000ad4280808080d00184220c1002220a41086a2900003703002003200a29000037038001200a102c2007200329038001220b370300200341306a41086a220a2008290300370300200341306a41106a220d200b370300200341306a41186a220e20002903003703002003200b37037020032003290350370330200341086a200341306a4120109e01200120057d200520017d200520015820042002582004200251220f1b22101b2111200220047d2001200554ad7d200420027d2005200154ad7d20101b2112200341086a41106a2903004200200328020822101b210b2003290310420020101b21130240024020052001562004200256200f1b0d0020064200370300200742003703002008420037030020034200370350200020091002220f41086a2900003703002003200f29000037038001200f102c2008200029030037030020032003290380012201370370200320013703502000200c1002220f41086a2900003703002003200f29000037038001200f102c200341f0006a41086a200029030022013703002003200329038001220237037020072002370000200741086a2001370000200a2008290300370300200d2007290300370300200e20062903003703002003200329035037033020034200200b20127d2013201154ad7d2201201320117d22022013562001200b562001200b511b22001b37035820034200200220001b370350200341d0006a21000c010b20064200370300200742003703002008420037030020034200370350200020091002220f41086a2900003703002003200f29000037038001200f102c2008200029030037030020032003290380012201370370200320013703502000200c1002220f41086a2900003703002003200f29000037038001200f102c200341f0006a41086a200029030022013703002003200329038001220237037020072002370000200741086a2001370000200a2008290300370300200d2007290300370300200e2006290300370300200320032903503703302003427f200b20127c201320117c22022013542200ad7c220120002001200b542001200b511b22001b3703582003427f200220001b370350200341d0006a21000b200341306aad42808080808004842000ad4280808080800284100120034190016a24000b950804057f047e037f017e23004190016b2204240020044180016a41086a2205418be9c500ad42808080808001841002220641086a29000037030020042006290000370380012006102c200441f0006a41086a220720052903003703002004200429038001370370200541d6b5c000ad4280808080b001841002220641086a29000037030020042006290000370380012006102c200441306a41086a220620052903003703002004200429038001370330200441d0006a2001109f010240024041c000102a2205450d00200520042903703700002005200429033037001020052004290050370020200541086a2007290300370000200541186a2006290300370000200541286a200441d0006a41086a290000370000200541306a200441d0006a41106a2206290000370000200541386a200441d0006a41186a2208290000370000200441186a200541c000109e01200441186a41106a29030021092004290320210a200428021821072005102c4200210b200441d0006a2001200a420020071b220a20027c22022009420020071b20037c2002200a54ad7c10a0012006290300210220042903582103024020042903504200520d002003210b0c020b2008420037030020064200370300200441d0006a41086a220142003703002004420037035020044180016a41086a2205418be9c500ad4280808080800184220a1002220741086a29000037030020042007290000370380012007102c200120052903003703002004200429038001220937037020042009370350200541c9b5c000ad4280808080d00184220c1002220741086a29000037030020042007290000370380012007102c20062004290380012209370300200441306a41086a220d2001290300370300200441306a41106a220e2009370300200441306a41186a220f200529030037030020042009370370200420042903503703302004200441306a4120109e01200441106a29030021092004290308211020042802002107200842003703002006420037030020014200370300200442003703502005200a1002220641086a29000037030020042006290000370380012006102c200120052903003703002004200429038001220a3703702004200a3703502005200c1002220641086a29000037030020042006290000370380012006102c20082005290300220a370300200d2001290300370300200e200429038001220c370300200f200a3703002004200c37037020042004290350370330200442002009420020071b220920027d2010420020071b2202200354ad7d220a200220037d2203200256200a200956200a2009511b22051b37035820044200200320051b370350200441306aad4280808080800484200441d0006aad42808080808002841001420021020c010b1033000b2000200b3703002000200237030820044190016a24000ba80202017f037e230041d0006b220324002003200236020420032001360200200341086a2002ad4220862001ad841003108d0102400240200328020822010d00420021040c010b200328020c210202400240200341086a41086a2802004110490d00200141086a290000210520012900002106420121040c010b20034100360220200342013703182003410b36022c200320033602282003200341186a360234200341cc006a41013602002003420137023c200341d0b0c2003602382003200341286a360248200341346a41c49ac500200341386a10391a200335022042208620033502188410040240200328021c450d002003280218102c0b420021040b2002450d002001102c0b2000200637030820002004370300200041106a2005370300200341d0006a24000bc30401057f230041206b2202240020012d0000210302404101102a2204450d00200420033a000020012d00012103200441014102102e2204450d00200420033a000120012d00022103200441024104102e2204450d00200420033a0002200420012d00033a000320012d00042103200441044108102e2204450d00200420033a0004200420012d00053a0005200420012d00063a0006200420012d00073a000720012d00082103200441084110102e2204450d00200420033a0008200420012d00093a0009200420012d000a3a000a200420012d000b3a000b200420012d000c3a000c200420012d000d3a000d200420012d000e3a000e200420012d000f3a000f20012d00102103200441104120102e2204450d00200420033a0010200420012d00113a0011200420012d00123a0012200420012d00133a0013200420012d00143a0014200420012d00153a0015200420012d00163a0016200420012d00173a0017200420012d00183a0018200420012d00193a0019200420012d001a3a001a200420012d001b3a001b200420012d001c3a001c200420012d001d3a001d200420012d001e3a001e200420012d001f3a001f200241186a22032004ad42808080808004841006220141186a290000370300200241106a2205200141106a290000370300200241086a2206200141086a290000370300200220012900003703002001102c200041186a2003290300370000200041106a2005290300370000200041086a2006290300370000200020022903003700002004102c200241206a24000f0b1033000b800802057f037e230041c0016b22042400200441c0006a41086a2205418be9c500ad42808080808001841002220641086a290000370300200420062900003703402006102c200441206a41086a2207200529030037030020042004290340370320200541d6b5c000ad4280808080b001841002220641086a290000370300200420062900003703402006102c200441306a41086a2208200529030037030020042004290340370330200441c0006a2001109f010240024041c000102a2206450d00200620042903203700002006200429033037001020062004290040370020200641086a2007290300370000200641186a2008290300370000200641286a2005290000370000200641306a200441c0006a41106a290000370000200641386a200441c0006a41186a290000370000200441086a200641c000109e01200441086a41106a29030021092004290310210a200428020821052006102c2009420020051b210b200a420020051b21090240200242ffffe883b1de1656200342005220035022061b0d002009200b844200520d0020004200370300200041013a0018200041106a4200370300200041086a42003703000c020b4101210502402002428080e983b1de1654410020061b0d00200441c0006a41086a2205418be9c500ad42808080808001841002220641086a290000370300200420062900003703402006102c200441206a41086a2207200529030037030020042004290340370320200541d6b5c000ad4280808080b001841002220641086a290000370300200420062900003703402006102c200441306a41086a2208200529030037030020042004290340370330200441c0006a2001109f0141c000102a2206450d01200620042903203700002006200429033037001020062004290040370020200641086a2007290300370000200641186a2008290300370000200641286a2005290000370000200641306a200441c0006a41106a290000370000200641386a200441c0006a41186a290000370000410021052004200641c000410141004100109701200428020021072006102c20074101460d00200110a101200441c0006a41386a2003370300200441c0006a41306a200237030041002105200441c0006a41086a41003a0000200441c9006a2001290000370000200441d1006a200141086a290000370000200441d9006a200141106a290000370000200441e1006a200141186a290000370000200441033a004041014100200441c0006a1092010b20012002200310a201200041106a200b20037d2009200254ad7d2003200b7d2002200954ad7d2009200256200b200356200b2003511b22061b3703002000200920027d200220097d20061b370308200020053a001820002006ad3703000c010b1033000b200441c0016a24000bbb0e05057f017e027f027e027f230041f0016b22012400200141e0006a41186a4200370300200141e0006a41106a22024200370300200141e0006a41086a2203420037030020014200370360200141e0016a41086a220441b5e5c200ad4280808080f000841002220541086a290000370300200120052900003703e0012005102c20032004290300370300200120012903e001220637035020012006370360200441bce5c200ad4280808080b001841002220541086a290000370300200120052900003703e0012005102c200220012903e0012206370300200141306a41086a2003290300370300200141306a41106a2006370300200141306a41186a20042903003703002001200637035020012001290360370330200141186a200141306a412010940120012802182107200128021c210820002d000021030240024002404101102a2204450d00200420033a000020002d00012103200441014102102e2204450d00200420033a000120002d00022103200441024104102e2204450d00200420033a0002200420002d00033a000320002d00042103200441044108102e2204450d00200420033a0004200420002d00053a0005200420002d00063a0006200420002d00073a000720002d00082103200441084110102e2204450d00200420033a0008200420002d00093a0009200420002d000a3a000a200420002d000b3a000b200420002d000c3a000c200420002d000d3a000d200420002d000e3a000e200420002d000f3a000f20002d00102103200441104120102e2204450d00200420033a0010200420002d00113a0011200420002d00123a0012200420002d00133a0013200420002d00143a0014200420002d00153a0015200420002d00163a0016200420002d00173a0017200420002d00183a0018200420002d00193a0019200420002d001a3a001a200420002d001b3a001b200420002d001c3a001c200420002d001d3a001d200420002d001e3a001e200420002d001f3a001f20042d0000210320042d000121052004102c200141306a2003200541087472410676220510910202402003413f71220420012802384f0d00200141086a200128023020044105746a220410b1012001290308200141086a41086a290300844200520d00200041086a2900002106200041106a2900002109200041186a290000210a20042000290000370000200441186a200a370000200441106a2009370000200441086a2006370000200141e0006a41086a200141306a41086a280200360200200120012903303703602005200141e0006a10fc030c030b2008410020071b210402402001280234450d002001280230102c0b200141e0006a20041091020240200128026841c000490d000340200441016a210402402001280264450d002001280260102c0b200141e0006a20041091022001280268413f4b0d000b0b200141206a41086a200141e0006a41086a2207280200220336020020012001290360370320200141e0006a41186a2208200041186a290000370300200141e0006a41106a220b200041106a2900003703002007200041086a29000037030020012000290000370360024020032001280224470d00200341016a22052003490d022003410174220c2005200c20054b1b220541ffffff3f712005470d022005410574220c4100480d020240024020030d00200c102a210c0c010b20012802202003410574200c102e210c0b200c450d01200120053602242001200c3602200b200320044106746a210c200128022020034105746a22052001290360370000200541086a2007290300370000200541106a200b290300370000200541186a20082903003700002001200341016a22033602280240200341c000470d00200141e0006a41186a22084200370300200141e0006a41106a220b4200370300200141e0006a41086a2205420037030020014200370360200141e0016a41086a220341b5e5c200ad4280808080f000841002220741086a290000370300200120072900003703e0012007102c20052003290300370300200120012903e001220637035020012006370360200341bce5c200ad4280808080b001841002220741086a290000370300200120072900003703e0012007102c200141d0006a41086a20032903002206370300200120012903e001220937035020022009370000200241086a2006370000200141306a41086a2005290300370300200141306a41106a200b290300370300200141306a41186a2008290300370300200120012903603703302001200441016a360260200141306aad4280808080800484200141e0006aad4280808080c0008410010b200141e0006a41086a2203200141206a41086a280200360200200120012903203703602004200141e0006a10fc0320032000290000370300200141e0006a41106a200041086a290000370300200141e0006a41186a200041106a29000037030020014180016a200041186a2900003703002001200c360264200141023a006041014100200141e0006a1092010c020b1033000b1035000b200141f0016a24000bb11403057f037e027f230041d0036b22032400200341c8026a41086a2204418be9c500ad42808080808001841002220541086a290000370300200320052900003703c8022005102c200341386a41086a22062004290300370300200320032903c802370338200441d6b5c000ad4280808080b001841002220541086a290000370300200320052900003703c8022005102c200341b8016a41086a22072004290300370300200320032903c8023703b801200341c8026a2000109f010240024041c000102a2205450d0020052003290338370000200520032903b801370010200520032900c802370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341d8026a290000370000200541386a200341c8026a41186a290000370000200320013703c802200320023703d0022005ad4280808080800884200341c8026aad428080808080028410012005102c0240200142ffffe883b1de165620024200522002501b0d00200341c8026a41086a2204418be9c500ad42808080808001841002220541086a290000370300200320052900003703c8022005102c200341386a41086a22062004290300370300200320032903c802370338200441d6b5c000ad4280808080b001841002220541086a290000370300200320052900003703c8022005102c200341b8016a41086a22072004290300370300200320032903c8023703b801200341c8026a2000109f0141c000102a2205450d0120052003290338370000200520032903b801370010200520032900c802370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341c8026a41106a290000370000200541386a200341c8026a41186a290000370000200341206a200541c000109e01200341206a41106a29030021082003290328210902402003290320220a4201520d002005ad428080808080088410050b2005102c200341c8026a41086a2204418be9c500ad42808080808001841002220541086a290000370300200320052900003703c8022005102c200341386a41086a22062004290300370300200320032903c802370338200441f0b5c000ad4280808080d000841002220541086a290000370300200320052900003703c8022005102c200341b8016a41086a22072004290300370300200320032903c8023703b801200341c8026a2000109f0141c000102a2205450d0120052003290338370000200520032903b801370010200520032900c802370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341d8026a220b290000370000200541386a200341c8026a41186a220c2900003700002005ad428080808080088410052005102c10a301200010a401200441e4d2c500ad42808080808001841002220541086a290000370300200320052900003703c8022005102c20062004290300370300200320032903c802370338200441a9e4c300ad4280808080e001841002220541086a290000370300200320052900003703c8022005102c20072004290300370300200320032903c8023703b801200341c8026a2000109f0141c000102a2205450d0120052003290338370000200520032903b801370010200520032900c802370020200541086a200341386a41086a290300370000200541186a200341b8016a41086a290300370000200541286a200341c8026a41086a290000370000200541306a200b290000370000200541386a200c290000370000200341c8026a200541c00010a501024020032d00c80222044102460d002005ad428080808080088410050b200341e8026a2802002107200341e4026a280200210b200341e0026a28020021062005102c0240024002400240200441037122054103460d0020050e03010003010b20040d02200b0d010c020b200741164d0d042007ad4220862006ad84200741696aad422086200641176aad8441011007200b450d010b2006102c0b200341b8026a200010a601200341c8026a20032802b802220520032802c002220610a701024020032d00c80241014722040d002006ad4220862005ad8410050b200341b8016a200341c8026a41017241800110db051a200341c8026a200341b8016a41800110db051a0240024020040d00200341386a200341c8026a41800110db051a024020032802bc02450d002005102c0b200341c8026a200341386a41800110db051a200341c0016a4120360200200341e7e485f3063602b8012003200341c8026a3602bc01200341b8026a200341b8016a10a80120033502c00242208620032802b8022205ad841005024020032802bc02450d002005102c0b200341e2c289ab063602b801200341203602c0012003200341c8026a41206a3602bc01200341b8026a200341b8016a10a80120033502c00242208620032802b8022205ad841005024020032802bc02450d002005102c0b200341203602c001200320034188036a3602bc01200341e9dabdf3063602b801200341b8026a200341b8016a10a80120033502c00242208620032802b8022205ad841005024020032802bc02450d002005102c0b200341203602c0012003200341a8036a3602bc01200341e1ea91cb063602b801200341b8026a200341b8016a10a80120033502c00242208620032802b8022205ad84100520032802bc02450d012005102c0c010b20032802bc02450d002005102c0b200341c8026a41086a2204418be9c500ad42808080808001841002220541086a290000370300200320052900003703c8022005102c200341386a41086a22062004290300370300200320032903c802370338200441e1b5c000ad4280808080f001841002220541086a290000370300200320052900003703c8022005102c200341b8016a41086a22072004290300370300200320032903c8023703b801200341c8026a2000109f0141c000102a2205450d0120052003290338370000200520032903b801370010200520032900c802370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341c8026a41106a290000370000200541386a200341c8026a41186a290000370000200341086a200541c000109e01200341086a41106a290300210220032903102101200328020821042005102c2002420020041b21022001420020041b2101024020094200200aa722051b22092008420020051b220884500d000240200142ffffe883b1de165620024200522002501b0d002009200810a9010c010b2000200120097c220a200220087c200a200154ad7c220210aa01200a21010b20012002844200520d00200010ab0120034180036a2008370300200341f8026a2009370300200341c8026a41086a41013a0000200341d1026a2000290000370000200341d9026a200041086a290000370000200341e1026a200041106a290000370000200341e9026a200041186a290000370000200341033a00c80241014100200341c8026a1092010b200341d0036a24000f0b1033000b411720071047000b8f2105057f017e047f017e127f230041c0046b2200240020004188026a41186a420037030020004188026a41106a2201420037030020004188026a41086a220242003703002000420037038802200041186a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200020042900003703182004102c200220032903003703002000200029031822053703a004200020053703880220034193e1c500ad4280808080e001841002220441086a290000370300200020042900003703182004102c200120002903182205370300200041e0026a41086a2002290300370300200041e0026a41106a2005370300200041e0026a41186a2003290300370300200020053703a00420002000290388023703e002200041106a200041e0026a412010940141012106024002402000280214410020002802101b220341014d0d00200321060c010b024020030e020001000b20004188026a41186a420037030020004188026a41106a2206420037030020004188026a41086a22024200370300200042003703880220004180046a41086a22034196e0c500ad4280808080f000841002220441086a29000037030020002004290000370380042004102c200220032903003703002000200029038004370388022003419de0c500ad4280808080a001841002220441086a29000037030020002004290000370380042004102c20062000290380042205370300200041e0026a41086a2002290300370300200041e0026a41106a2005370300200041e0026a41186a2003290300370300200020053703a00420002000290388023703e002200041086a200041e0026a4120109401200028020c210420002802082107200041e0026a10840420004188026a20002802e002220320002802e80210d301024020002802e402450d002003102c0b410121030240024020002d0088024101460d00200041a0046a41186a200041e0026a41186a290000370300200041a0046a41106a200041e0026a41106a290000370300200041a0046a41086a200041e0026a41086a290000370300200020002900e0023703a004410021020c010b200041a8046a20004192026a290100370300200041b0046a2000419a026a290100370300200041b7046a200041a1026a2900003700002000200029018a023703a0044100210320002d00890221020b20004180046a41086a2206200041a0046a41086a29030037030020004180046a41106a2208200041a0046a41106a29030037030020004180046a41186a200041a0046a41186a290300370300200020002903a004370380040240024020030d00200041286a41176a220320004180046a41176a290000370000200041286a41106a22092008290300370300200041286a41086a2208200629030022053703002000200029038004220a370328200041e8006a41096a2005370000200041e8006a41116a2009290300370000200041e8006a41186a2003290000370000200020023a00682000200a370069200020023a00880220004188026a41096a200829030037000020004188026a41116a200929030037000020004188026a41186a20032900003700002000200029032837008902200041e0026a10840420002802e0022103200020002802e8023602a404200020033602a00420004188026a200041a0046a10a102024020002802e402450d002003102c0b20004180046a41086a22024196e0c500ad4280808080f0008422051002220341086a29000037030020002003290000370380042003102c200041e0036a41086a2206200229030037030020002000290380043703e003200241aff8c200ad4280808080a00184220a1002220341086a29000037030020002003290000370380042003102c200041186a41086a220b2002290300370300200020002903800437031820004180046a200041e8006a109f01024041c000102a2203450d002004410020071b210c200041aa026a210d20004188026a410172210e200041b6026a210f20004195026a21104100211120004180046a41106a21120340200320002903e003370000200320002903183700102003200029008004370020200341086a2006290300370000200341186a200b290300370000200341286a2002290000370000200341306a2012290000370000200341386a20004180046a41186a221329000037000020004188026a200341c00010a002024020002d00940222044102460d002003ad428080808080088410050b200041a8016a41086a2207201041086a290000370300200041a8016a41106a2208201041106a290000370300200041a8016a41186a2209201041186a29000037030020004188016a41086a2214200f41086a29010037030020004188016a41106a2215200f41106a29010037030020004188016a41186a2216200f41186a290100370300200020102900003703a8012000200f29010037038801024020044102470d0002402011410171450d00200041a0046a41186a200041c8006a41186a290300370300200041a0046a41106a200041c8006a41106a290300370300200041a0046a41086a200041c8006a41086a290300370300200020002903483703a00420004180046a41086a22044196e0c500ad4280808080f000841002220241086a29000037030020002002290000370380042002102c200041e0036a41086a2206200429030037030020002000290380043703e003200441aff8c200ad4280808080a001841002220241086a29000037030020002002290000370380042002102c200041186a41086a22072004290300370300200020002903800437031820004180046a200041a0046a109f0141c000102a2202450d03200220002903e003370000200220002903183700102002200029038004370020200241086a2006290300370000200241186a2007290300370000200241286a2004290300370000200241306a20004180046a41106a290300370000200241386a20004180046a41186a29030037000020004188026a200241c00010ee03024020002d0098024102460d0020004180046a41106a20004188026a41106a28020036020020004180046a41086a20004188026a41086a290300370300200020002903880237038004200041e0026a2000419c026a41c20010db051a200041003a0081032000200041e0026a3602ac03200020004180046a3602a803200041c0003602e403200020023602e003200041a8036a200041e0036a108504200028028404450d00200028028004102c0b2002102c0b2003102c418ae3c300ad4280808080a0078410040c040b2000280290022111200028028c022117200028028802211820002d00b5022119200041e8016a41086a221a2007290300370300200041e8016a41106a221b2008290300370300200041e8016a41186a221c2009290300370300200041c8016a41086a22072014290300370300200041c8016a41106a22082015290300370300200041c8016a41186a22092016290300370300200020002903a8013703e80120002000290388013703c80141002114410021150240201941ff017141014722160d00200041a8036a41186a2009290300370300200041a8036a41106a2008290300370300200041a8036a41086a2007290300370300200020002903c8013703a803410121150b200041003a00d8032000200c3602d403200020113602d003200020173602cc03200020183602c803200041e0036a41186a22112009290300370300200041e0036a41106a2217200829030037030020062007290300370300200020002903c8013703e003200041e0026a41186a2207201c290300370300200041e0026a41106a2208201b290300370300200041e0026a41086a2209201a290300370300200020002903e8013703e002024020044101470d00200041a0046a41186a2007290300370300200041a0046a41106a2008290300370300200041a0046a41086a2009290300370300200020002903e0023703a004410121140b201320112903003703002012201729030037030020022006290300370300200020002903e0033703800441002104024020160d0020072013290300370300200820122903003703002009200229030037030020002000290380043703e002410121040b200e20002903a004370000200d20002903e002370000200e41086a200041a0046a41086a290300370000200e41106a200041a0046a41106a290300370000200e41186a200041a0046a41186a290300370000200d41086a2009290300370000200d41106a2008290300370000200d41186a2007290300370000200020143a008802200020043a00a9022007200041e8006a41186a22142903003703002008200041e8006a41106a22162903003703002009200041e8006a41086a2211290300370300200020002903683703e002200220051002220441086a29000037030020002004290000370380042004102c2006200229030037030020002000290380043703e0032002200a1002220441086a29000037030020002004290000370380042004102c200b2002290300370300200020002903800437031820004180046a200041e0026a109f0141c000102a2204450d01200420002903e003370000200420002903183700102004200029038004370020200441086a2006290300370000200441186a200b290300370000200441286a2002290300370000200441306a2012290300370000200441386a2013290300370000200020004188026a360284042000200041c8036a36028004200041c0003602a404200020043602a00420004180046a200041a0046a108504024020150d002004102c024020002802cc03450d0020002802c803102c0b2003102c0c040b200041c8006a41186a2007290300370300200041c8006a41106a2008290300370300200041c8006a41086a20092903003703002011200041a8036a41086a2903003703002016200041a8036a41106a2903003703002014200041a8036a41186a290300370300200020002903e002370348200020002903a8033703682004102c024020002802cc03450d0020002802c803102c0b2003102c200220051002220341086a29000037030020002003290000370380042003102c2006200229030037030020002000290380043703e0032002200a1002220341086a29000037030020002003290000370380042003102c200b2002290300370300200020002903800437031820004180046a200041e8006a109f014101211141c000102a22030d000b0b1033000b200241ff017122034102460d00418ae3c300ad4280808080a00784100420034101460d0041c4e3c300ad4280808080d0048410040b41e9e3c300ad42808080809005841004410121060b20004188026a41186a2207420037030020004188026a41106a2208420037030020004188026a41086a220242003703002000420037038802200041186a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200020042900003703182004102c200220032903003703002000200029031822053703a004200020053703880220034193e1c500ad4280808080e001841002220441086a290000370300200020042900003703182004102c200041a0046a41086a2003290300220537030020002000290318220a3703a0042001200a370000200141086a2005370000200041e0026a41086a2002290300370300200041e0026a41106a2008290300370300200041e0026a41186a200729030037030020002000290388023703e0022000200636028802200041e0026aad428080808080048420004188026aad4280808080c000841001200041c0046a24000bf50d03057f017e077f23004190016b22012400200141e8006a41086a22024196e0c500ad4280808080f000841002220341086a290000370300200120032900003703682003102c200141c8006a41086a2204200229030037030020012001290368370348200241d3f8c200ad4280808080e000841002220341086a290000370300200120032900003703682003102c200141d8006a41086a2205200229030037030020012001290368370358200141e8006a2000109f0102400240024002400240024041c000102a2203450d00200320012903483700002003200129035837001020032001290068370020200341086a2004290300370000200341186a2005290300370000200341286a2002290000370000200341306a200141e8006a41106a290000370000200341386a200141e8006a41186a290000370000200141e8006a200341c00010d3010240024020012d00684101470d002003ad42808080808008841005200141086a41186a220220014181016a290000370300200141086a41106a2204200141f9006a290000370300200141086a41086a2205200141f1006a290000370300200120012900693703082003102c200141286a41186a2002290300370300200141286a41106a2004290300370300200141286a41086a200529030037030020012001290308370328200141e8006a41086a22024196e0c500ad4280808080f000841002220341086a290000370300200120032900003703682003102c200141c8006a41086a2204200229030037030020012001290368370348200241d9f8c200ad4280808080e000841002220341086a290000370300200120032900003703682003102c200141d8006a41086a2205200229030037030020012001290368370358200141e8006a200141286a109f0141c000102a2203450d02200320012903483700002003200129035837001020032001290068370020200341086a2004290300370000200341186a2005290300370000200341286a2002290000370000200341306a200141f8006a290000370000200341386a200141e8006a41186a2900003700002003ad428080808080088410052003102c0c010b2003102c0b200141e8006a41086a22024196e0c500ad4280808080f0008422061002220341086a290000370300200120032900003703682003102c200141c8006a41086a2204200229030037030020012001290368370348200241b5fdc200ad4280808080d000841002220341086a290000370300200120032900003703682003102c200141d8006a41086a2205200229030037030020012001290368370358200141e8006a2000109f0141c000102a2203450d00200320012903483700002003200129035837001020032001290068370020200341086a2004290300370000200341186a2005290300370000200341286a2002290000370000200341306a200141f8006a2204290000370000200341386a200141e8006a41186a22052900003700002003ad428080808080088410052003102c20001086042000108704200220061002220341086a290000370300200120032900003703682003102c200141086a41086a2002290300370300200120012903683703082002419bf9c200ad4280808080d001841002220341086a290000370300200120032900003703682003102c200141286a41086a200229030037030020012001290368370328200141e8006a2000109f0141c000102a2203450d00200320012903083700002003200129032837001020032001290068370020200341086a200141086a41086a290300370000200341186a200141286a41086a290300370000200341286a200141e8006a41086a2207290000370000200341306a2004290000370000200341386a2005290000370000200141e8006a200341c00010f1030240200128027022080d002003102c0c060b2003ad4280808080800884100520012802682109200129027421062003102c20082006422088a74102746a210a2006a7210b2009210c2008210441002105410041ff01710e03010203010b1033000b410121030c020b410221030c010b410021030b0340024002400240024002400240024020030e03000102020b2004200a460d03200441046a210441022103200c417f6a2202210c0c020b41002103024020054102460d0041022105200921020c020b2004200a460d02200441046a210441022105200c417f6a2202210c410221030c010b2005410247210d410121034102210520092102200d450d010b200141e8006a41186a200041186a290000370300200141e8006a41106a200041106a2900003703002007200041086a290000370300200120023602880120012000290000370368200141e8006a1088040240200341ff01710e03000203000b410121030c030b200b450d032008102c0c030b410221030c010b410021030c000b0b20014190016a24000ba40b030b7f047e047f23004180016b220324002003200236020420032001360200200341086a2002ad4220862001ad841003108d0102400240200328020822040d00200041023a00000c010b200328020c21052003200341106a280200220236022c20032004360228024002402002450d0020042d0000210120032002417f6a36022c2003200441016a360228200141014b0d0002400240024002400240024020010e020001000b200341d8006a200341286a107720032802582206450d05200328025c2107200328022c22084104490d03200341e0006a28020021092003280228220a280000210b20032008417c6a220c36022c2003200a41046a36022841002101200341003a0078417b21020c010b41002101200341003a00782002417f6a21082002417e6a21020340024020082001470d00200141ff0171450d06200341003a00780c060b200341d8006a20016a200420016a220d41016a2d00003a00002003200d41026a3602282003200141016a220d3a00782003200236022c2002417f6a2102200d2101200d4120470d000b2003200328005b3600332003200328025836023020032003280033360043200320032802303602402003200328024036025020032003280043360053200341e7006a290000210e200329005f210f200328006f21062003280073210720032d0077210920032003280053360023200320032802503602202003200341cc006a28000036001b20032003280049360218410121010c010b03400240200c2001470d000240200141ff0171450d00200341003a00780b20070d040c050b200341d8006a20016a200a20016a220d41046a2d00003a00002003200820026a36022c2003200d41056a3602282003200141016a220d3a00782002417f6a2102200d2101200d4120470d000b2003200328005b36003320032003280258360230200320032802303602402003200328003336004302400240024002402008200d6b2201417c6a4110490d00200341e7006a2900002110200329005f2111200328006f21022003280073210c20032d007721122003200a200d6a221341146a221436022820032001416c6a220a36022c200a4104490d002013410c6a290000210e201341046a290000210f2014280000210a2003200141686a36022c2003201341186a2214360228200841686a200d460d0320142d000021142003200141676a221536022c2003201341196a360228201441014b0d034100210d20140e020201020b20070d050c060b20154104490d01201341196a28000021082003200141636a36022c20032013411d6a3602284101210d0b2003200328004336005320032003280240360250200320032802503602182003200328005336001b200320032800493602202003200341cc006a280000360023410021010c010b2007450d030c020b2003200328002336005b20032003280220360258200320032802183602302003200328001b360033200041106a200e370000200041086a200f370000200041046a200328005b36000020002003280258360001200041306a20083600002000412c6a200d360000200041286a200a360000200041246a200b360000200041206a20093600002000411c6a2007360000200041186a2006360000200041c3006a20103700002000413b6a2011370000200041d3006a20123a0000200041cf006a200c360000200041cb006a2002360000200041346a2003280230360000200041376a20032800333600000c030b2007450d010b2006102c0b20034100360238200342013703302003410b360244200320033602402003200341306a360250200341ec006a41013602002003420137025c200341d0b0c2003602582003200341c0006a360268200341d0006a41c49ac500200341d8006a10391a2003350238422086200335023084100402402003280234450d002003280230102c0b410221010b200020013a00002005450d002004102c0b20034180016a24000bbc0501087f230041c0006b22022400200241086a220341ecddc500ad4280808080f000841002220441086a290000370300200220042900003703002004102c200241206a41086a200329030037030020022002290300370320200341c3fbc000ad42808080808001841002220441086a290000370300200220042900003703002004102c200241306a41086a200329030037030020022002290300370330200241b6fbc000410d1083020240024002400240024002402002280208220541206a2204417f4c0d0020022802002106024002402004450d002004102a2203450d062004410f4d0d01200421070c050b200441017422034110200341104b1b2207102a21030c030b200441017422084110200841104b1b220741004e0d010c050b103a000b200320042007102e21030b2003450d010b20032002290320370000200341086a200241206a41086a2903003700000240024020074170714110460d00200721080c010b200741017422084120200841204b1b22084100480d02200320072008102e2203450d010b20032002290330370010200341186a200241306a41086a29030037000002400240200841606a2005490d00200821070c010b200541206a22072005490d02200841017422092007200920074b1b22074100480d02200320082007102e2203450d010b200341206a2006200510db051a02402002280204450d002006102c0b20022001109f0102400240200720046b411f4d0d00200721080c010b200441206a22082004490d02200741017422062008200620084b1b22084100480d02200320072008102e2203450d010b200320046a22042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a2900003700002000200541c0006a3602082000200836020420002003360200200241c0006a24000f0b1033000b1035000bd60201027f230041c0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041003a00000c010b200328021421042003200341186a2802003602ac02200320013602a802200341a0016a200341a8026a10e201410121020240024020032d00a0014101460d00200341206a200341a0016a41017241800110db051a200041016a200341206a41800110db051a0c010b4100210220034100360228200342013703202003410b3602b4022003200341086a3602b0022003200341206a3602bc02200341b4016a4101360200200342013702a401200341d0b0c2003602a0012003200341b0026a3602b001200341bc026a41c49ac500200341a0016a10391a200335022842208620033502208410042003280224450d002003280220102c0b200020023a00002004450d002001102c0b200341c0026a24000bcf0b010d7f230041d0006b22022400200241306a41086a220341ecddc500ad4280808080f000841002220441086a290000370300200220042900003703302004102c200241206a41086a200329030037030020022002290330370320200341cbfbc000ad42808080808001841002220441086a290000370300200220042900003703302004102c200241086a200329030037030020022002290330370300200241306a41b6fbc000410d1083020240024002402002280238220541206a2206417f4c0d002002280230210702400240024002402006450d002006102a2203450d052006410f4d0d01200621080c030b200641017422034110200341104b1b2208102a21030c010b200641017422044110200441104b1b22084100480d04200320062008102e21030b2003450d020b20032002290320370000200341086a200241206a41086a2903003700000240024020084170714110460d00200821040c010b200841017422044120200441204b1b22044100480d03200320082004102e2203450d020b20032002290300370010200341186a200241086a29030037000002400240200441606a2005490d00200421090c010b200541206a22082005490d032004410174220a2008200a20084b1b22094100480d03200320042009102e2203450d020b200341206a2007200510db051a02402002280234450d002007102c0b200141086a280200220a41046a2208417f4c0d000240024020080d00410121040c010b2008102a2204450d020b20024100360238200220083602342002200436023020012d00002107024020080d004101102a2204450d0220024101360234200220043602300b20024101360238200420073a000020012d0001210b02402002280234220720022802382208470d00200841016a22072008490d032008410174220c2007200c20074b1b22074100480d030240024020080d002007102a21040c010b200420082007102e21040b2004450d0220022007360234200220043602300b2002200841016a220c360238200420086a200b3a000020012d0002210d024002402007200c460d002007210b0c010b200741016a220b2007490d032007410174220e200b200e200b4b1b220b4100480d030240024020070d00200b102a21040c010b20042007200b102e21040b2004450d022002200b360234200220043602300b2002200841026a22073602382004200c6a200d3a000020012d0003210c0240200b2007470d00200b41016a220d200b490d03200b410174220e200d200e200d4b1b220d4100480d0302400240200b0d00200d102a21040c010b2004200b200d102e21040b2004450d022002200d360234200220043602300b2002200841036a360238200420076a200c3a000020012802042107200a200241306a10670240024020022802342201200228023822046b200a490d00200228023021080c010b2004200a6a22082004490d032001410174220b2008200b20084b1b220b4100480d030240024020010d00200b102a21080c010b20022802302001200b102e21080b2008450d022002200b36023420022008360230200b21010b200820046a2007200a10db051a200241306a41186a22072004200a6aad4220862008ad841006220441186a290000370300200241306a41106a220a200441106a290000370300200241306a41086a220b200441086a290000370300200220042900003703302004102c200241186a2007290300370300200241106a200a290300370300200241086a200b2903003703002002200229033037030002402001450d002008102c0b02400240200920066b411f4d0d00200921080c010b200641206a22042006490d03200941017422082004200820044b1b22084100480d03200320092008102e2203450d020b200320066a22042002290300370000200441186a200241186a290300370000200441106a200241106a290300370000200441086a200241086a2903003700002000200541c0006a3602082000200836020420002003360200200241d0006a24000f0b103a000b1033000b1035000b890a08017f017e047f017e017f017e037f017e230041b0016b22022400200241386a2000200110ce01200241386a41106a29030021012002290340210002400240024020022903382203a7450d00200241f0006a41186a22044200370300200241f0006a41106a22054200370300200241f0006a41086a2206420037030020024200370370200241a0016a41086a2207418be9c500ad428080808080018422081002220941086a290000370300200220092900003703a0012009102c20062007290300370300200220022903a00122033703900120022003370370200741c9b5c000ad4280808080d00184220a1002220941086a290000370300200220092900003703a0012009102c200520022903a0012203370300200241d0006a41086a220b2006290300370300200241d0006a41106a220c2003370300200241d0006a41186a220d2007290300370300200220033703900120022002290370370350200241206a200241d0006a4120109e01200241206a41106a29030021032002290328210e2002280220210920044200370300200542003703002006420037030020024200370370200720081002220541086a290000370300200220052900003703a0012005102c20062007290300370300200220022903a001220837039001200220083703702007200a1002220541086a290000370300200220052900003703a0012005102c200420072903002208370300200b2006290300370300200c20022903a001220a370300200d20083703002002200a3703900120022002290370370350200242002003420020091b220320017d200e420020091b2201200054ad7d2208200120007d2200200156200820035620082003511b22071b37037820024200200020071b370370200241f0006a2107200241d0006a21060c010b2003500d01200241f0006a41186a22044200370300200241f0006a41106a22054200370300200241f0006a41086a2206420037030020024200370370200241a0016a41086a2207418be9c500ad428080808080018422081002220941086a290000370300200220092900003703a0012009102c20062007290300370300200220022903a00122033703900120022003370370200741c9b5c000ad4280808080d00184220a1002220941086a290000370300200220092900003703a0012009102c200520022903a0012203370300200241d0006a41086a220b2006290300370300200241d0006a41106a220c2003370300200241d0006a41186a220d2007290300370300200220033703900120022002290370370350200241086a200241d0006a4120109e01200241086a41106a29030021032002290310210e2002280208210920044200370300200542003703002006420037030020024200370370200720081002220541086a290000370300200220052900003703a0012005102c20062007290300370300200220022903a001220837039001200220083703702007200a1002220541086a290000370300200220052900003703a0012005102c200420072903002208370300200b2006290300370300200c20022903a001220a370300200d20083703002002200a3703900120022002290370370350200242002003420020091b220320017d200e420020091b2201200054ad7d2208200120007d2200200156200820035620082003511b22071b37037820024200200020071b370370200241f0006a2107200241d0006a21060b2006ad42808080808004842007ad428080808080028410010b200241b0016a24000b8e0a02057f037e230041d0016b22032400200341d0006a41086a2204418be9c500ad42808080808001841002220541086a290000370300200320052900003703502005102c200341306a41086a2206200429030037030020032003290350370330200441e1b5c000ad4280808080f001841002220541086a290000370300200320052900003703502005102c200341c0006a41086a2207200429030037030020032003290350370340200341d0006a2000109f01024041c000102a2205450d00200520032903303700002005200329034037001020052003290050370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341e0006a290000370000200541386a200341d0006a41186a29000037000020032001370350200320023703582005ad4280808080800884200341d0006aad428080808080028410012005102c0240200142ffffe883b1de165620024200522002501b0d00200341d0006a41086a2204418be9c500ad42808080808001841002220541086a290000370300200320052900003703502005102c200341306a41086a2206200429030037030020032003290350370330200441e1b5c000ad4280808080f001841002220541086a290000370300200320052900003703502005102c200341c0006a41086a2207200429030037030020032003290350370340200341d0006a2000109f0141c000102a2205450d01200520032903303700002005200329034037001020052003290050370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341d0006a41106a290000370000200541386a200341d0006a41186a290000370000200341186a200541c000109e01200341186a41106a29030021082003290320210902402003290318220a4201520d002005ad428080808080088410050b2005102c200341d0006a41086a2204418be9c500ad42808080808001841002220541086a290000370300200320052900003703502005102c200341306a41086a2206200429030037030020032003290350370330200441d6b5c000ad4280808080b001841002220541086a290000370300200320052900003703502005102c200341c0006a41086a2207200429030037030020032003290350370340200341d0006a2000109f0141c000102a2205450d01200520032903303700002005200329034037001020052003290050370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341d0006a41106a290000370000200541386a200341d0006a41186a2900003700002003200541c000109e01200341106a290300210220032903082101200328020021042005102c2002420020041b21022001420020041b2101024020094200200aa722051b22092008420020051b220884500d000240200142ffffe883b1de165620024200522002501b0d002009200810a9010c010b2000200120097c220a200220087c200a200154ad7c220210a201200a21010b20012002844200520d00200010ab0120034188016a200837030020034180016a2009370300200341d0006a41086a41013a0000200341d9006a2000290000370000200341e1006a200041086a290000370000200341e9006a200041106a290000370000200341f1006a200041186a290000370000200341033a005041014100200341d0006a1092010b200341d0016a24000f0b1033000bbb0201057f230041c0006b22012400200141206a41086a22024191b0c200ad4280808080e000841002220341086a290000370300200120032900003703202003102c200141086a220420022903003703002001200129032037030020024197b0c200ad4280808080c001841002220341086a290000370300200120032900003703202003102c200141106a41086a2205200229030037030020012001290320370310200141206a2000109f01024041c000102a22030d001033000b200320012903003700002003200129031037001020032001290020370020200341086a2004290300370000200341186a2005290300370000200341286a2002290000370000200341306a200141306a290000370000200341386a200141206a41186a2900003700002003ad428080808080088410052003102c200141c0006a24000bdb0402057f047e230041e0006b22052400200541c0006a41086a2206418be9c500ad42808080808001841002220741086a290000370300200520072900003703402007102c200541206a41086a2208200629030037030020052005290340370320200641d6b5c000ad4280808080b001841002220741086a290000370300200520072900003703402007102c200541306a41086a2209200629030037030020052005290340370330200541c0006a2001109f01024002400240024041c000102a2207450d00200720052903203700002007200529033037001020072005290040370020200741086a2008290300370000200741186a2009290300370000200741286a2006290000370000200741306a200541c0006a41106a290000370000200741386a200541c0006a41186a290000370000200541086a200741c000109e01200541086a41106a290300210a2005290310210b200528020821062007102c410121070240200b420020061b220b20027d220c200b56200a420020061b220a20037d200b200254ad7d220d200a56200d200a511b4101470d00200041d0b9c000360204200041086a411d3602000c040b0240200b428080e983b1de16544100200a501b0d00200c42ffffe883b1de1656200d420052200d501b0d00200041edb9c000360204200041086a411a3602000c030b200520012004200c200d10ad01200528020022070d012001200c200d10a201200041106a2003370300200041086a2002370300410021070c030b1033000b2005280204210620002007360204200041086a20063602000b410121070b20002007360200200541e0006a24000bd40f08047f017e017f047e037f027e017f017e230041d0016b22052400024002400240024002402002410671450d00200541b8016a41086a2206418be9c500ad42808080808001841002220741086a290000370300200520072900003703b8012007102c200541a8016a41086a22082006290300370300200520052903b8013703a80120064187bac000ad4280808080f000841002220741086a290000370300200520072900003703b8012007102c200541e8006a41086a22072006290300370300200520052903b80137036820054188016a2001109f0141c000102a2206450d01200620052903a801370000200620052903683700102006200529008801370020200641086a2008290300370000200641186a2007290300370000200641286a20054188016a41086a290000370000200641306a20054188016a41106a290000370000200641386a20054188016a41186a290000370000200541c00036025c20052006360258200541b8016a2006ad42808080808008841003108d010240024020052802b80122070d00420021090c010b20052802bc01210802400240200541b8016a41086a280200220a4110490d00200a4170714110460d00200a417c714120460d00200741086a290000210b2007290000210c200741186a290000210d2007290010210e2007280020210f420121090c010b20054100360270200542013703682005410b3602ac012005200541d8006a3602a8012005200541e8006a3602cc012005419c016a41013602002005420137028c01200541d0b0c200360288012005200541a8016a36029801200541cc016a41c49ac50020054188016a10391a200535027042208620053502688410040240200528026c450d002005280268102c0b420021090b2008450d002007102c0b2006102c2009500d00200541b8016a41086a2207418be9c500ad42808080808001841002220641086a290000370300200520062900003703b8012006102c200541a8016a41086a22082007290300370300200520052903b8013703a801200741d6b5c000ad4280808080b001841002220641086a290000370300200520062900003703b8012006102c200541e8006a41086a220a2007290300370300200520052903b80137036820054188016a2001109f0141c000102a2206450d01200620052903a801370000200620052903683700102006200529008801370020200641086a2008290300370000200641186a200a290300370000200641286a20054188016a41086a2208290000370000200641306a20054188016a41106a2210290000370000200641386a20054188016a41186a2211290000370000200541c0006a200641c000109e01200541c0006a41106a290300211220052903482113200528024021142006102c42002115201142003703002010420037030020084200370300200542003703880120074191b0c200ad4280808080e000841002220641086a290000370300200520062900003703b8012006102c20082007290300370300200520052903b80137038801200741acb0c200ad4280808080e000841002220641086a290000370300200520062900003703b8012006102c201020052903b8012209370300200a2008290300370300200541e8006a41106a2009370300200541e8006a41186a2007290300370300200520093703a8012005200529038801370368200541386a200541e8006a4120109401200541186a200d42004100200528023c410020052802381b2206200f6b2207200720064b1bad2209420010e005200541286a20094200200e420010e005200541086a42004200200e420010e0052012420020141b210e2013420020141b210d4200210902402005290310200529032084420052200541286a41086a2903002213200529030820052903187c7c2212201354720d00200b2012200c2005290328221556200b201256200b2012511b22061b20127d200c201520061b220b201554ad7d2109200b20157d21150b2015200d200d201556200e200956200e2009511b22061b2003562009200e20061b220920045620092004511b450d0041bfbac0002106412621010c040b200541d8006a200110ae01200528026022080d0141002106200528025c450d022005280258102c0c020b1033000b20054188016a41186a420037030020054188016a41106a220a420037030020054188016a41086a220142003703002005420037038801200541b8016a41086a22064191b0c200ad4280808080e000841002220741086a290000370300200520072900003703b8012007102c20012006290300370300200520052903b80137038801200641acb0c200ad4280808080e000841002220741086a290000370300200520072900003703b8012007102c200a20052903b8012209370300200541e8006a41086a2001290300370300200541e8006a41106a2009370300200541e8006a41186a2006290300370300200520093703a80120052005290388013703682005200541e8006a41201094012005280204410020052802001b210720084105742101200528025c21082005280258220a21060240034002402007200641106a2802004f0d002006290300200358200641086a290300220920045820092004511b0d002006411c6a2d000020027141ff01710d020b200641206a2106200141606a22010d000b410021062008450d01200a102c0c010b418ebac00021062008450d00200a102c0b413121010b2000200136020420002006360200200541d0016a24000bac09030c7f037e037f230041f0006b22022400200241286a41086a2203418be9c500ad42808080808001841002220441086a290000370300200220042900003703282004102c200241086a41086a2205200329030037030020022002290328370308200341f0b5c000ad4280808080d000841002220441086a290000370300200220042900003703282004102c200241186a41086a2206200329030037030020022002290328370318200241286a2001109f0102400240024041c000102a2204450d00200420022903083700002004200229031837001020042002290028370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241386a290000370000200441386a200241286a41186a290000370000200241c00036024c20022004360248200241086a2004ad42808080808008841003108d010240024020022802082207450d00200228020c21082002200241106a280200360254200220073602502002200241d0006a107502400240024020022802000d00200228025422034160712201417f4c0d0620022802042109024002402003410576220a0d00410821010c010b2001102a2201450d060b02402009450d00411d210b4100210c4100210d0340200241186a200241d0006a10af010240024020022d00184101460d00200228025422054110490d002002290019210e20022002280250220341106a3602502002200541706a220636025420064104490d00200341086a290000210f2003290000211020022005416c6a22063602542002200341146a36025020060d010b20024100360228200a450d042001102c0c040b200d41016a210620032800102111200241ec006a41026a200241d8006a41026a2d000022123a0000200241e8006a41026a221320123a000020022005416b6a3602542002200341156a360250200220022f005822053b016c200220053b016820032d001421050240200d200a470d00200c2006200c20064b1b220a41ffffff3f71200a470d0a200a41057422034100480d0a02400240200d0d002003102a21010c010b2001200b41636a2003102e21010b2001450d080b2001200b6a2203417f6a20053a0000200341636a2205200f37030820052010370300200341776a200e370200200341736a2011360200200320022f01683b0000200341026a20132d00003a0000200c41026a210c200b41206a210b2006210d20092006470d000b200241306a20093602002002200a36022c20022001360228200229022c210e0c030b200241306a20093602002002200a36022c200220013602282001450d01200229022c210e0c020b200241003602280b4100210120024100360220200242013703182002410b36025c2002200241c8006a3602582002200241186a3602642002413c6a41013602002002420137022c200241d0b0c2003602282002200241d8006a360238200241e4006a41c49ac500200241286a10391a200235022042208620023502188410040240200228021c450d002002280218102c0b0b02402008450d002007102c0b2001450d002000200e370204200020013602000c010b20004100360208200042083702000b2004102c200241f0006a24000f0b1033000b103a000b1035000bf00204027f017e017f077e0240024020012802042202450d0020012802002203310000210420012002417f6a22053602042001200341016a3602002005450d012003310001210620012002417e6a22053602042001200341026a3602002005450d012003310002210720012002417d6a22053602042001200341036a3602002005450d012003310003210820012002417c6a22053602042001200341046a3602002005450d012003310004210920012002417b6a22053602042001200341056a3602002005450d012003310005210a20012002417a6a22053602042001200341066a3602002005450d012003310006210b2001200241796a22053602042001200341076a3602002005450d01200041003a00002003310007210c2001200241786a3602042001200341086a3602002000200c423886200b42308684200a422886842009422086842008421886842007421086842006420886842004843700010f0b200041013a00000f0b200041013a00000b831003097f027e037f230041c0006b22022400200241206a41086a2203418be9c500ad42808080808001841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341f0b5c000ad4280808080d000841002220441086a290000370300200220042900003703202004102c200241106a41086a2204200329030037030020022002290320370310200241206a2000109f010240024041c000102a2206450d00200620022903003700002006200229031037001020062002290020370020200641086a2005290300370000200641186a2004290300370000200641286a2003290000370000200641306a200241206a41106a290000370000200641386a200241206a41186a290000370000200128020021072001280208210320024100360228200242013703202003200241206a106702402003450d0020034105742108410021090340200720096a220341146a2d0000210502400240200228022420022802282204460d00200228022021000c010b200441016a22002004490d042004410174220a2000200a20004b1b220a4100480d040240024020040d00200a102a21000c010b20022802202004200a102e21000b2000450d032002200a360224200220003602200b2002200441016a360228200020046a20053a0000200341156a2d0000210502400240200228022420022802282204460d00200228022021000c010b200441016a22002004490d042004410174220a2000200a20004b1b220a4100480d040240024020040d00200a102a21000c010b20022802202004200a102e21000b2000450d032002200a360224200220003602200b2002200441016a360228200020046a20053a0000200341166a2d0000210502400240200228022420022802282204460d00200228022021000c010b200441016a22002004490d042004410174220a2000200a20004b1b220a4100480d040240024020040d00200a102a21000c010b20022802202004200a102e21000b2000450d032002200a360224200220003602200b2002200441016a360228200020046a20053a0000200341176a2d0000210502400240200228022420022802282204460d00200228022021000c010b200441016a22002004490d042004410174220a2000200a20004b1b220a4100480d040240024020040d00200a102a21000c010b20022802202004200a102e21000b2000450d032002200a360224200220003602200b2002200441016a360228200020046a20053a0000200341186a2d0000210502400240200228022420022802282204460d00200228022021000c010b200441016a22002004490d042004410174220a2000200a20004b1b220a4100480d040240024020040d00200a102a21000c010b20022802202004200a102e21000b2000450d032002200a360224200220003602200b2002200441016a360228200020046a20053a0000200341196a2d0000210502400240200228022420022802282204460d00200228022021000c010b200441016a22002004490d042004410174220a2000200a20004b1b220a4100480d040240024020040d00200a102a21000c010b20022802202004200a102e21000b2000450d032002200a360224200220003602200b2002200441016a360228200020046a20053a00002003411a6a2d0000210502400240200228022420022802282204460d00200228022021000c010b200441016a22002004490d042004410174220a2000200a20004b1b220a4100480d040240024020040d00200a102a21000c010b20022802202004200a102e21000b2000450d032002200a360224200220003602200b2002200441016a360228200020046a20053a00002003411b6a2d0000210502400240200228022420022802282204460d00200228022021000c010b200441016a22002004490d042004410174220a2000200a20004b1b220a4100480d040240024020040d00200a102a21000c010b20022802202004200a102e21000b2000450d032002200a360224200220003602200b2002200441016a360228200020046a20053a0000200341086a290300210b2003290300210c0240024020022802242200200228022822056b4110490d00200228022021040c010b200541106a22042005490d042000410174220a2004200a20044b1b220a4100480d040240024020000d00200a102a21040c010b20022802202000200a102e21040b2004450d032002200a36022420022004360220200a21000b200420056a220a200b370008200a200c3700002002200541106a220a360228200341106a280200210d02402000200a6b41034b0d00200a41046a220e200a490d042000410174220f200e200f200e4b1b220e4100480d040240024020000d00200e102a21040c010b20042000200e102e21040b2004450d032002200e360224200220043602200b2002200541146a3602282004200a6a200d3600002003411c6a2d0000210002400240200228022420022802282203460d00200228022021040c010b200341016a22042003490d04200341017422052004200520044b1b22054100480d040240024020030d002005102a21040c010b200228022020032005102e21040b2004450d0320022005360224200220043602200b2002200341016a360228200420036a20003a00002008200941206a2209470d000b0b200228022421032006ad4280808080800884200235022842208620022802202204ad84100102402003450d002004102c0b2006102c0240200141046a280200450d002007102c0b200241c0006a24000f0b1033000b1035000bc50504027f017e057f047e230041f0006b22022400200241d0006a41086a2203418be9c500ad428080808080018422041002220541086a290000370300200220052900003703502005102c200241306a41086a2206200329030037030020022002290350370330200341d6b5c000ad4280808080b001841002220541086a290000370300200220052900003703502005102c200241c0006a41086a2207200329030037030020022002290350370340200241d0006a2001109f01024041c000102a2205450d00200520022903303700002005200229034037001020052002290050370020200541086a2006290300370000200541186a2007290300370000200541286a2003290000370000200541306a200241d0006a41106a2208290000370000200541386a200241d0006a41186a2209290000370000200241186a200541c000109e01200241186a41106a290300210a2002290320210b2002290318210c2005102c200320041002220541086a290000370300200220052900003703502005102c2006200329030037030020022002290350370330200341e1b5c000ad4280808080f001841002220541086a290000370300200220052900003703502005102c2007200329030037030020022002290350370340200241d0006a2001109f0141c000102a2205450d00200520022903303700002005200229034037001020052002290050370020200541086a200241306a41086a290300370000200541186a200241c0006a41086a290300370000200541286a200241d0006a41086a290000370000200541306a2008290000370000200541386a20092900003700002002200541c000109e01200241106a29030021042002290308210d200228020021032005102c2000200d420020031b220d200b4200200ca722051b7c220b37030020002004420020031b200a420020051b7c200b200d54ad7c370308200241f0006a24000f0b1033000be10301077f230041f0006b22022400200241d0006a41086a220341e0d9c500ad4280808080f001841002220441086a290000370300200220042900003703502004102c200241086a41086a2205200329030037030020022002290350370308200341efd9c500ad4280808080c001841002220441086a290000370300200220042900003703502004102c200241186a41086a220620032903003703002002200229035037031820022000370348200241d0006a41186a2207200241c8006aad42808080808001841006220441186a290000370300200241d0006a41106a2208200441106a2900003703002003200441086a290000370300200220042900003703502004102c200241286a41186a22042007290300370300200241286a41106a22072008290300370300200241286a41086a2208200329030037030020022002290350370328024041c000102a22030d001033000b200320022903083700002003200229031837001020032002290328370020200341086a2005290300370000200341186a2006290300370000200341286a2008290300370000200341306a2007290300370000200341386a2004290300370000200220013602502003ad4280808080800884200241d0006aad4280808080c0008410012003102c200241f0006a24000b861305067f017e027f037e057f23004180016b22042400200441c0006a41186a22054200370300200441c0006a41106a22064200370300200441c0006a41086a2207420037030020044200370340200441f0006a41086a220841e0d9c500ad4280808080f001841002220941086a290000370300200420092900003703702009102c2007200829030037030020042004290370220a3703602004200a370340200841beb9c000ad4280808080d001841002220941086a290000370300200420092900003703702009102c20062004290370220a370300200441206a41086a22092007290300370300200441206a41106a220b200a370300200441206a41186a220c20082903003703002004200a37036020042004290340370320200441186a200441206a4120410141004100109701024002400240024020042802184101460d002005420037030020064200370300200742003703002004420037034020084191b0c200ad4280808080e000841002220541086a290000370300200420052900003703702005102c2007200829030037030020042004290370370340200841acb0c200ad4280808080e000841002220541086a290000370300200420052900003703702005102c20062004290370220a37030020092007290300370300200b200a370300200c20082903003703002004200a37036020042004290340370320200441106a200441206a41201094012004280214410020042802101b2109024020024101460d00200441206a210c0c020b200441c0006a41186a22054200370300200441c0006a41106a220b4200370300200441c0006a41086a2207420037030020044200370340200441f0006a41086a220841e0d9c500ad4280808080f00184220d1002220c41086a2900003703002004200c290000370370200c102c2007200829030037030020042004290370220a3703602004200a37034020084180bfc000ad4280808080a00184220e1002220c41086a2900003703002004200c290000370370200c102c200441e0006a41086a220c2008290300220a37030020042004290370220f3703602006200f370000200641086a2210200a370000200441206a41086a22112007290300370300200441206a41106a2212200b290300370300200441206a41186a2213200529030037030020042004290340370320200441086a200441206a4120109401024002402004280208450d00200428020c20094b0d010b20054200370300200b420037030020074200370300200442003703402008200d1002221441086a290000370300200420142900003703702014102c2007200829030037030020042004290370220a3703602004200a3703402008200e1002221441086a290000370300200420142900003703702014102c200c2008290300220a37030020042004290370220f3703602006200f3700002010200a370000201120072903003703002012200b29030037030020132005290300370300200420042903403703202004200920014101746a360240200441206aad4280808080800484200441c0006aad4280808080c000841001200441206a210c0c020b200041046a280200450d022000280200102c0c020b200041046a280200450d012000280200102c0c010b20002802082107200028020421102000280200210b200441c0006a41186a22114200370300200441c0006a41106a22124200370300200441c0006a41086a2200420037030020044200370340200441f0006a41086a220841e0d9c500ad4280808080f001841002220541086a290000370300200420052900003703702005102c2000200829030037030020042004290370220a3703602004200a370340200841beb9c000ad4280808080d001841002220541086a290000370300200420052900003703702005102c200441e0006a41086a2008290300220a37030020042004290370220f3703602006200f370000200641086a200a370000200441206a41086a2000290300370300200441206a41106a2012290300370300200441206a41186a20112903003703002004200429034037032020044100360248200442013703404104102a2208450d012004410436024420042004280248220641046a36024820042008360240200820066a200936000002400240024020042802442206200428024822086b4104490d00200428024021060c010b200841046a22002008490d01200641017422082000200820004b1b22084100480d010240024020060d002008102a21060c010b200428024020062008102e21060b2006450d032004200836024420042006360240200428024821080b2004200841046a360248200620086a20013600002007200441c0006a106702402007450d00200b200741286c6a2109200b210703402007200441c0006a109101200741206a290300210a0240024020042802442206200428024822086b4108490d00200428024021060c010b200841086a22002008490d03200641017422082000200820004b1b22084100480d030240024020060d002008102a21060c010b200428024020062008102e21060b2006450d052004200836024420042006360240200428024821080b2004200841086a360248200620086a200a3700002009200741286a2207470d000b0b20042802442107200428024821080240024020024101460d000240024020072008460d00200428024021070c010b200841016a22072008490d03200841017422062007200620074b1b22064100480d030240024020080d002006102a21070c010b200428024020082006102e21070b2007450d052004200636024420042007360240200428024821080b2004200841016a360248200720086a41003a00000c010b0240024020072008460d00200428024021070c010b200841016a22072008490d02200841017422062007200620074b1b22064100480d020240024020080d002006102a21070c010b200428024020082006102e21070b2007450d042004200636024420042007360240200428024821080b2004200841016a360248200720086a41013a00000240024020042802442207200428024822086b4104490d00200428024021070c010b200841046a22062008490d02200741017422082006200820064b1b22084100480d020240024020070d002008102a21070c010b200428024020072008102e21070b2007450d042004200836024420042007360240200428024821080b2004200841046a360248200720086a20033600000b20042802442108200cad4280808080800484200435024842208620042802402207ad84100102402008450d002007102c0b2010450d01200b102c0c010b1035000b20044180016a24000f0b1033000b290020004101360204200041086a200128020420012802006b41a0016e2201360200200020013602000bf40101047f230041d0006b21020240200128020022032001280204470d00200041003602000f0b2001200341a0016a3602002002200341c2006a29000037012a2002200341ca006a290000370132200241106a220120022903303703002002200341d2006a29000037013a200241186a220420022903383703002002200341da006a2800003601422002200341de006a2f00003b0146200241206a220520022903403703002002200341c0006a2f00003b01282002200229032837030820002003360200200020022903083700042000410c6a2001290300370000200041146a20042903003700002000411c6a20052903003700000bb905020b7f047e23004190016b22032400024002402001280200220420012802042205460d002001200441a0016a22063602002003200441c2006a29000037016a2003200441ca006a290000370172200341c8006a41086a220720032903703703002003200441d2006a29000037017a200341c8006a41106a220820032903783703002003200441da006a280000360182012003200441de006a2f00003b018601200341c8006a41186a22092003290380013703002003200441c0006a2f00003b016820032003290368370348200341286a41186a220a2009290300370300200341286a41106a220b2008290300370300200341286a41086a220c200729030037030020032003290348370328200541e07e6a210d02400340200341086a41186a200a290300220e370300200341086a41106a200b290300220f370300200341086a41086a200c2903002210370300200320032903282211370308200341e8006a41186a200e370300200341e8006a41106a200f370300200341e8006a41086a2010370300200320113703682002450d01200d2004460d022001200641a0016a22053602002003200641c2006a29000037016a2003200641ca006a290000370172200720032903703703002003200641d2006a29000037017a200820032903783703002003200641da006a280000360182012003200641de006a2f00003b01860120092003290380013703002003200641c0006a2f00003b016820032003290368370348200a2009290300370300200b2008290300370300200c200729030037030020032003290348370328200441a0016a21042002417f6a2102200521060c000b0b20002004360200200020032903683702042000410c6a200341f0006a290300370200200041146a200341f8006a2903003702002000411c6a20034180016a2903003702000c010b200041003602000b20034190016a24000bfa0202057f027e230041e0006b22022400200241c0006a41086a2203418be9c500ad42808080808001841002220441086a290000370300200220042900003703402004102c200241206a41086a2205200329030037030020022002290340370320200341d6b5c000ad4280808080b001841002220441086a290000370300200220042900003703402004102c200241306a41086a2206200329030037030020022002290340370330200241c0006a2001109f01024041c000102a22040d001033000b200420022903203700002004200229033037001020042002290040370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241c0006a41106a290000370000200441386a200241c0006a41186a290000370000200241086a200441c000109e01200241086a41106a290300210720022903102108200228020821032004102c20002007420020031b37030820002008420020031b370300200241e0006a24000bf60302037f037e230041f0006b22042400200441206a200110b1010240024002402004290320200441206a41086a29030084500d00200441d0006a41086a2205418be9c500ad42808080808001841002220641086a290000370300200420062900003703502006102c200441306a41086a200529030037030020042004290350370330200541d6b5c000ad4280808080b001841002220641086a290000370300200420062900003703502006102c200441c0006a41086a200529030037030020042004290350370340200441d0006a2001109f0141c000102a2205450d02200520042903303700002005200429034037001020052004290050370020200541086a200441306a41086a290300370000200541186a200441c0006a41086a290300370000200541286a200441d0006a41086a290000370000200541306a200441d0006a41106a290000370000200541386a200441d0006a41186a290000370000200441086a200541c000109e01200441086a41106a290300210720042903102108200428020821062005102c20012008420020061b220820027c22092007420020061b20037c2009200854ad7c10a201200041106a2003370300200041086a2002370300410021050c010b2000418cb5c000360204200041086a4122360200410121050b20002005360200200441f0006a24000f0b1033000b1300200041013602042000418cbfc0003602000b3400200041e0d9c50036020420004100360200200041146a4107360200200041106a418cc0c000360200200041086a420f3702000b2c01017f02404108102a22020d001033000b20004288808080800137020420002002360200200242003700000b2201017f230041106b220224002002410036020020002002109301200241106a24000beb0c0b077f017e017f017e067f027e017f027e027f017e017f230041f0006b22032400200341d0006a41186a22044200370300200341d0006a41106a2205420037030041082106200341d0006a41086a2207420037030020034200370350200341386a41086a22084191b0c200ad4280808080e000841002220941086a290000370300200320092900003703382009102c2007200829030037030020032003290338370350200841acb0c200ad4280808080e000841002220941086a290000370300200320092900003703382009102c20052003290338220a370300200341086a41086a2007290300370300200341086a41106a200a370300200341086a41186a20082903003703002003200a370328200320032903503703082003200341086a412010940120032802042108200328020021092000280000210b2000350004210c200341d0006a200110ae014100210d2003280250210e2003280254210f02400240024002400240024002400240024020032802582210450d002008410020091b2111200e201041057422106a2112200341e4006a2109200e21080340200841086a290300210a200841106a2903002113200829030021142004200841186a290300370300200520133703002007200a3703002003201437035020092000460d0220092900002000290000510d0202402003280260221520114d0d002003410a6a200341ef006a2d00003a0000200320032f006d3b0108200341d8006a2903002114427f2113200329035021164201210a20032d006c2109200329026421170c040b200841206a2108201041606a22100d000b0b200f450d02200e102c0c020b200328026022092002200920024b1b211520032d006c4102722109427f21164200211341002102200329026421174200210a4100210b427f21140b200341cc006a41026a220d200341086a41026a2d00003a0000200320032f01083b014c4120102a2206450d0420062016370300200620093a001c2006201737021420062015360210200620032f014c3b001d200620143703082006411f6a200d2d00003a00000240024020104120470d004101210d20132114410121070c010b200841206a2104201241606a2118200341ed006a2119200341e4006a2109201321144101210d41012107034020042108024002400340200341d0006a41186a200841186a290300370300200341d0006a41106a200841106a290300370300200341d0006a41086a2210200841086a290300370300200320082903003703500240024020092000460d0020092900002000290000510d002003280260220520114d0d01200341086a41026a201941026a2d00003a0000200320192f00003b0108201029030021162003290350211720032d006c21152003290264211a0c040b200a4201510d024200211341002102420021144200210a4100210b0b2012200841206a2208470d000c040b0b2010290300220a201420032903502217201356200a201456200a2014511b22101b21162017201320101b2117200328026022102002201020024b1b210520032d006c410272211542002113410021022003290264211a420021144200210a4100210b0b200341286a41026a200341086a41026a2d000022103a0000200320032f010822043b0128200341d0006a41026a221b20103a0000200320043b015002402007200d470d00200d41016a2210200d490d08200d41017422072010200720104b1b220741ffffff3f712007470d08200741057422104100480d0802400240200d0d002010102a21060c010b2006200d4105742010102e21060b2006450d070b200841206a21042006200d4105746a221020153a001c20102016370308201020173703002010201a37021420102005360210201020032f01503b001d2010411f6a201b2d00003a0000200d41016a210d20182008470d000b0b0240200f450d00200e102c0b200a4201520d03200d2007470d020c010b427f2113427f21140b200d41016a2208200d490d03200d41017422002008200020084b1b220741ffffff3f712007470d03200741057422084100480d0302400240200d0d002008102a21060c010b2006200d4105742008102e21060b2006450d020b2006200d4105746a22082014370308200820133703002008200b36021420082002360210200841186a200c42808080802084370300200d41016a210d0b2003200d36025820032007360254200320063602502001200341d0006a10b001200341f0006a24000f0b1033000b1035000be20c06077f027e017f017e037f0b7e23002206210720064180016b41607122062400200641e0006a41186a22084200370300200641e0006a41106a22094200370300200641e0006a41086a220a420037030020064200370360200641d0006a41086a220b4191b0c200ad4280808080e000841002220c41086a2900003703002006200c290000370350200c102c200a200b29030037030020062006290350370360200b41acb0c200ad4280808080e000841002220c41086a2900003703002006200c290000370350200c102c20092006290350220d370300200641206a41086a200a290300370300200641206a41106a200d370300200641206a41186a200b2903003703002006200d37034020062006290360370320200641186a200641206a4120109401200628021c210b2006280218210c2006200337033020062002370328200620043602384201210e200642013703202006200028000036023c2000350004210d200641e0006a200110ae014100210f200d2005ad42ff0183422086842110200628026021112006280264211202400240024002400240024020062802682205450d00200b4100200c1b210420112005410574220c6a2113200641f4006a21052006290320220e21022006290328221421152006290330221621172006290338221821192011210b0340200b41086a290300210d200b41106a2903002103200b290300211a2008200b41186a29030037030020092003370300200a200d3703002006201a3703600240024020052000460d0020052900002000290000510d000240200628027020044b0d002002210d420021020c020b2009290300211b2006290368211c2006290360211d2006290378211e2002210d420121020c010b4200210e4200211442002116420021184200210d2010211e2015211d2017211c2019211b0b20024201510d02200b41206a210b200d2102200c41606a220c0d000b2006200e3703202006201437032820062016370330200620183703380b2012450d012011102c0c010b2006200d3703202006201537032820062017370330200620193703384120102a2205450d022005201e3703182005201d3703002005201c370308200541106a201b37030002400240200c4120470d004101210f200d210e4101210a0c010b200b41206a210b200641f4006a2109200d210e4101210f4101210a03400240024020092000460d00200d21020340200641e0006a41186a200b41186a290300370300200641e0006a41106a220c200b41106a290300370300200641e0006a41086a200b41086a2903003703002006200b2903003703600240024020092900002000290000510d000240200628027020044b0d002002210d420021020c020b200c290300211e2006290368211a200629036021032006290378211d2002210d420121020c010b4200210e200642003703204200210d201521032017211a2019211e2010211d0b024020024201510d00200d21022013200b41206a220b470d010c050b0b200b41206a210b0c010b0240034020064200370320200d4201510d014200210d2013200b41206a220b470d000b4200210e0c030b200b41206a210b4200210e4200210d201521032017211a2019211e2010211d0b0240200a200f470d00200f41016a220c200f490d06200f410174220a200c200a200c4b1b220a41ffffff3f71200a470d06200a410574220c4100480d0602400240200f0d00200c102a21050c010b2005200f410574200c102e21050b2005450d050b2005200f4105746a220c201a370308200c2003370300200c41106a201e370300200c41186a201d370300200f41016a210f200b2013470d000b0b2012450d012011102c0c010b4100210a410821050b0240200e4201520d00200641e0006a41106a2200200641206a410872220b41106a290300370300200641e0006a41086a220c200b41086a2903003703002006200b2903003703600240200f200a470d00200f41016a220b200f490d03200f4101742209200b2009200b4b1b220a41ffffff3f71200a470d03200a410574220b4100480d0302400240200f0d00200b102a21050c010b2005200f410574200b102e21050b2005450d020b2005200f4105746a220b2006290360370300200b41106a2000290300370300200b41086a200c290300370300200b41186a2010370300200f41016a210f0b2006200f3602682006200a360264200620053602602001200641e0006a10b001200724000f0b1033000b1035000bb20302057f027e230041e0006b22042400200441c0006a41086a2205418be9c500ad42808080808001841002220641086a290000370300200420062900003703402006102c200441206a41086a2207200529030037030020042004290340370320200541e1b5c000ad4280808080f001841002220641086a290000370300200420062900003703402006102c200441306a41086a2208200529030037030020042004290340370330200441c0006a2001109f01024041c000102a22060d001033000b200620042903203700002006200429033037001020062004290040370020200641086a2007290300370000200641186a2008290300370000200641286a2005290000370000200641306a200441c0006a41106a290000370000200641386a200441c0006a41186a290000370000200441086a200641c000109e01200441086a41106a29030021092004290310210a200428020821052006102c2001200a420020051b220a2002200a200a2002562009420020051b220920035620092003511b22061b22027d20092003200920061b22037d200a200254ad7d10aa012000200337030820002002370300200441e0006a24000be70606027f017e057f027e017f037e23004180016b22052400200541306a200210b1010240024002402005290330200541306a41086a29030084500d00200541e0006a41086a2206418be9c500ad428080808080018422071002220841086a290000370300200520082900003703602008102c200541c0006a41086a200629030037030020052005290360370340200641e1b5c000ad4280808080f001841002220841086a290000370300200520082900003703602008102c200541d0006a41086a200629030037030020052005290360370350200541e0006a2001109f0141c000102a2206450d02200620052903403700002006200529035037001020062005290060370020200641086a200541c0006a41086a2209290300370000200641186a200541d0006a41086a220a290300370000200641286a200541e0006a41086a2208290000370000200641306a200541e0006a41106a220b290000370000200641386a200541e0006a41186a220c290000370000200541186a200641c000109e01200541186a41106a290300210d2005290320210e2005280218210f2006102c200820071002220641086a290000370300200520062900003703602006102c2009200829030037030020052005290360370340200841d6b5c000ad4280808080b001841002220641086a290000370300200520062900003703602006102c200a200829030037030020052005290360370350200541e0006a2002109f0141c000102a2206450d02200620052903403700002006200529035037001020062005290060370020200641086a2009290300370000200641186a200a290300370000200641286a2008290000370000200641306a200b290000370000200641386a200c2900003700002005200641c000109e01200541106a290300211020052903082107200528020021082006102c20022007420020081b22112003200e4200200f1b220e200e200356200d4200200f1b220d200456200d2004511b22061b22077c22122010420020081b2004200d20061b22107c2012201154ad7c10a2012001200e20077d200d20107d200e200754ad7d10aa01200041106a200420107d2003200754ad7d370300200041086a200320077d370300410021060c010b2000418cb5c000360204200041086a4122360200410121060b2000200636020020054180016a24000f0b1033000bd40602057f047e23004180016b22042400200441e0006a41086a2205418be9c500ad42808080808001841002220641086a290000370300200420062900003703602006102c200441c0006a41086a2207200529030037030020042004290360370340200541d6b5c000ad4280808080b001841002220641086a290000370300200420062900003703602006102c200441d0006a41086a2208200529030037030020042004290360370350200441e0006a2001109f0102400240024041c000102a2206450d00200620042903403700002006200429035037001020062004290060370020200641086a2007290300370000200641186a2008290300370000200641286a2005290000370000200641306a200441e0006a41106a290000370000200641386a200441e0006a41186a290000370000200441286a200641c000109e01200441286a41106a29030021092004290330210a200428022821052006102c0240200a420020051b220a20025422062009420020051b220920035420092003511b450d00419ccbc0002106411521050c030b200441206a20014104200a20027d220a200920037d2006ad7d220910ad01200428022022060d01200441e0006a41086a2205418be9c500ad42808080808001841002220641086a290000370300200420062900003703602006102c200441c0006a41086a2207200529030037030020042004290360370340200541e1b5c000ad4280808080f001841002220641086a290000370300200420062900003703602006102c200441d0006a41086a2208200529030037030020042004290360370350200441e0006a2001109f0141c000102a2206450d00200620042903403700002006200429035037001020062004290060370020200641086a2007290300370000200641186a2008290300370000200641286a2005290000370000200641306a200441e0006a41106a290000370000200641386a200441e0006a41186a290000370000200441086a200641c000109e01200441086a41106a290300210b2004290310210c200428020821052006102c2001200c420020051b220c20027c2202200b420020051b20037c2002200c54ad7c10aa012001200a200910a201410021060c020b1033000b200428022421050b200020053602042000200636020020044180016a24000bf90506027f017e057f027e017f027e230041f0006b22032400200341d0006a41086a2204418be9c500ad428080808080018422051002220641086a290000370300200320062900003703502006102c200341306a41086a2207200429030037030020032003290350370330200441e1b5c000ad4280808080f001841002220641086a290000370300200320062900003703502006102c200341c0006a41086a2208200429030037030020032003290350370340200341d0006a2000109f01024041c000102a2206450d00200620032903303700002006200329034037001020062003290050370020200641086a2007290300370000200641186a2008290300370000200641286a2004290000370000200641306a200341d0006a41106a2209290000370000200641386a200341d0006a41186a220a290000370000200341186a200641c000109e01200341186a41106a290300210b2003290320210c2003280218210d2006102c200420051002220641086a290000370300200320062900003703502006102c2007200429030037030020032003290350370330200441d6b5c000ad4280808080b001841002220641086a290000370300200320062900003703502006102c2008200429030037030020032003290350370340200341d0006a2000109f0141c000102a2206450d00200620032903303700002006200329034037001020062003290050370020200641086a200341306a41086a290300370000200641186a200341c0006a41086a290300370000200641286a200341d0006a41086a290000370000200641306a2009290000370000200641386a200a2900003700002003200641c000109e01200341106a290300210e20032903082105200328020021042006102c20002005420020041b220f2001200c4200200d1b22052005200156200b4200200d1b220b200256200b2002511b22061b22017c220c200e420020041b2002200b20061b22027c200c200f54ad7c10a2012000200520017d200b20027d2005200154ad7d10aa01200341f0006a24000f0b1033000b130020004104360204200041b4cbc0003602000b34002000418be9c50036020420004100360200200041146a4105360200200041106a41a4e0c000360200200041086a42083702000b3301017f02404110102a22020d001033000b2002420037000820024200370000200042908080808002370204200020023602000b13002000410336020420004194f1c0003602000b3400200041bddbc50036020420004100360200200041146a4103360200200041106a41b0f3c000360200200041086a42083702000b4d01027f230041106b2202240002404104102a22030d001033000b2002420437020420022003360200410020021067200041086a200228020836020020002002290300370200200241106a24000b8c0601077f230041d0006b22022400200241306a41086a220341bddbc500ad42808080808001841002220441086a290000370300200220042900003703302004102c200241206a41086a220520032903003703002002200229033037032020034194f6c000ad4280808080e002841002220441086a290000370300200220042900003703302004102c200241086a2206200329030037030020022002290330370300200241306a41cffac00010ca01024002400240024041c000102a2204450d00200420022903203700002004200229030037001020042002290030370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241c0006a290000370000200441386a200241306a41186a2900003700002001280208220341046a2205417f4c0d01200128020021070240024020050d00410121010c010b2005102a2201450d010b2002410036023820022005360234200220013602302003200241306a10670240024020022802342206200228023822016b2003490d00200228023021050c010b200120036a22052001490d03200641017422082005200820054b1b22084100480d030240024020060d002008102a21050c010b200228023020062008102e21050b2005450d012002200836023420022005360230200821060b200520016a2007200310db051a200241306a41186a2207200120036aad4220862005ad841006220341186a290000370300200241306a41106a2201200341106a290000370300200241306a41086a2208200341086a290000370300200220032900003703302003102c200241186a2007290300370300200241106a2001290300370300200241086a20082903003703002002200229033037030002402006450d002005102c0b200441c000418001102e22040d030b1033000b103a000b1035000b20042002290300370040200441d8006a200241186a290300370000200441d0006a200241106a290300370000200441c8006a200241086a29030037000020004280818080800c37020420002004360200200241d0006a24000b920301057f230041206b2202240020012d0000210302404101102a2204450d00200420033a000020012d00012103200441014102102e2204450d00200420033a000120012d00022103200441024104102e2204450d00200420033a0002200420012d00033a000320012d00042103200441044108102e2204450d00200420033a0004200420012d00053a0005200420012d00063a0006200420012d00073a000720012d00082103200441084110102e2204450d00200420033a0008200420012d00093a0009200420012d000a3a000a200420012d000b3a000b200420012d000c3a000c200420012d000d3a000d200420012d000e3a000e200420012d000f3a000f200241186a22032004ad42808080808002841006220141186a290000370300200241106a2205200141106a290000370300200241086a2206200141086a290000370300200220012900003703002001102c200041186a2003290300370000200041106a2005290300370000200041086a2006290300370000200020022903003700002004102c200241206a24000f0b1033000bb00e030e7f017e037f230041d0026b22022400200241f0016a41086a220341bddbc500ad42808080808001841002220441086a290000370300200220042900003703f0012004102c200241e8006a41086a22052003290300370300200220022903f001370368200341b7b9c000ad4280808080f000841002220441086a290000370300200220042900003703f0012004102c200241b0016a41086a22042003290300370300200220022903f0013703b001200241f0016a2001109f01024041c000102a2201450d0020012002290368370000200120022903b001370010200120022900f001370020200141086a2005290300370000200141186a2004290300370000200141286a2003290000370000200141306a200241f0016a41106a2206290000370000200141386a200241f0016a41186a2207290000370000200241c00036024420022001360240200241c8006a2001ad42808080808008841003108d0102400240200228024822050d00410021030c010b200228024c21082002200241d0006a28020022093602ac01200220053602a80141002103200241003a00200240024002400340024020092003470d00200241003602ac01200341ff0171450d02200241003a00200c020b200220036a200520036a22042d00003a00002002200441016a3602a8012002200341016a22043a00202004210320044120470d000b200241b0026a41086a220a200241086a220b290300370300200241b0026a41106a220c200241106a220d290300370300200241b0026a41186a220e200241186a220f290300370300200220022903003703b0022002200920046b3602ac012002200241a8016a10cc0120022802202203450d00200241f0016a41186a2209200e290300370300200241f0016a41106a220e200c290300370300200241f0016a41086a220c200a290300370300200241f0016a41286a220a200b290300370300200241f0016a41306a220b200d290300370300200241f0016a41386a220d200f290300370300200220022903b0023703f0012002200229030037039002200241246a2802002104200241286a220f2903002110200241b0016a41086a200c290300370300200241b0016a41106a200e290300370300200241b0016a41186a2009290300370300200241b0016a41206a2209200229039002370300200241b0016a41286a220c200a290300370300200241b0016a41306a220a200b290300370300200241b0016a41386a220b200d290300370300200220022903f0013703b001200241f0016a200241a8016a10820120022802f0010d012004450d002003102c0b41002103200241003602b801200242013703b0012002410b36026c2002200241c0006a3602682002200241b0016a36020020024184026a4101360200200242013702f401200241d0b0c2003602f0012002200241e8006a36028002200241c49ac500200241f0016a10391a20023502b80142208620023502b001841004024020022802b401450d0020022802b001102c0b0c010b200241d8006a41086a220d200241f0016a41086a280200360200200241e8006a41086a220e200241b0016a41086a290300370300200241e8006a41106a2211200241b0016a41106a290300370300200241e8006a41186a2212200241b0016a41186a290300370300200241e8006a41206a22132009290300370300200241e8006a41286a2209200c290300370300200241e8006a41306a220c200a290300370300200241e8006a41386a220a200b290300370300200220022903f001370358200220022903b001370368200241386a200a290300370300200241306a200c290300370300200f2009290300370300200241206a2013290300370300200241186a2012290300370300200241106a2011290300370300200241086a200e290300370300200241b0026a41086a200d28020036020020022002290368370300200220022903583703b0020b2008450d002005102c0b200241f0016a41086a2205200241086a2903003703002006200241106a2903003703002007200241186a290300370300200241f0016a41206a2209200241206a290300370300200241f0016a41286a200241286a290300370300200241f0016a41306a200241306a290300370300200241f0016a41386a200241386a290300370300200220022903003703f001200241b0016a41086a2206200241b0026a41086a280200360200200220022903b0023703b00102402003450d00200020022903f00137030020002004360244200041c8006a2010370200200041386a200241f0016a41386a290300370300200041306a200241f0016a41306a290300370300200041286a200241f0016a41286a290300370300200041206a2009290300370300200041186a200241f0016a41186a290300370300200041106a200241f0016a41106a290300370300200041086a2005290300370300200041d8006a2006280200360200200041d0006a20022903b0013702000b200020033602402001102c200241d0026a24000f0b1033000b860705017f047e087f057e017f23004180026b22022400200241c0006a2001108e02024002402002290340a7450d00200041003602200c010b200241c0006a41106a290300210320022903482104200241286a2001108e0202402002290328a7450d00200041003602200c010b200241286a41106a290300210520022903302106200241206a20011075024002400240024020022802200d00200128020441306e220741306c2208417f4c0d02200228022421090240024020080d004108210a0c010b2008102a220a450d040b02402009450d004100210b0340200241003a00f801200b220c41016a210b2001280204417f6a21084100210d024002400240024003402008417f460d01200241d8016a200d6a2001280200220e2d00003a0000200120083602042001200e41016a3602002002200d41016a220e3a00f8012008417f6a2108200e210d200e4120470d000b200241b8016a41186a2208200241d8016a41186a290300370300200241b8016a41106a220d200241d8016a41106a290300370300200241b8016a41086a220e200241d8016a41086a290300370300200220022903d8013703b801200241086a2001108e022002290308a70d01200241086a41106a290300210f20022903102110200241f8006a41086a200e2903002211370300200241f8006a41106a200d2903002212370300200241f8006a41186a20082903002213370300200241d8006a41086a220d2011370300200241d8006a41106a220e2012370300200241d8006a41186a22142013370300200220022903b8012211370378200220113703582007200c470d030240200c4101742208200b2008200b4b1b2207ad42307e2211422088a70d002011a7220841004e0d030b1035000b200d41ff0171450d00200241003a00f8010b200241f8006a41086a20024198016a41086a2903003703002007450d04200a102c0c040b02400240200c0d002008102a210a0c010b200a200c41306c2008102e210a0b200a450d060b200a200c41306c6a2208200f3703082008201037030020082002290358370310200841186a200d290300370300200841206a200e290300370300200841286a2014290300370300200b2009470d000b0b200a0d010b200041003602200c030b20002004370300200020073602242000200a3602202000200637031020002003370308200041286a2009360200200041186a20053703000c020b103a000b1033000b20024180026a24000bb90d08027f017e027f017e047f027e017f037e230041e0016b22062400200641e0006a41086a2207418be9c500ad428080808080018422081002220941086a290000370300200620092900003703602009102c200641c0006a41086a220a200729030037030020062006290360370340200741d6b5c000ad4280808080b00184220b1002220941086a290000370300200620092900003703602009102c200641d0006a41086a220c200729030037030020062006290360370350200641e0006a2001109f010240024041c000102a2209450d00200920062903403700002009200629035037001020092006290060370020200941086a200a290300370000200941186a200c2903003700004128210d200941286a2007290000370000200941306a200641e0006a41106a220e290000370000200941386a200641e0006a41186a220f290000370000200641286a200941c000109e01200641286a41106a290300211020062903302111200628022821122009102c200720081002220941086a290000370300200620092900003703602009102c200a2007290300370300200620062903603703402007200b1002220941086a290000370300200620092900003703602009102c200c200729030037030020062006290360370350200641e0006a2002109f0141c000102a2209450d00200920062903403700002009200629035037001020092006290060370020200941086a200641c0006a41086a290300370000200941186a200641d0006a41086a290300370000200941286a200641e0006a41086a290000370000200941306a200e290000370000200941386a200f290000370000200641106a200941c000109e01200641106a41106a2903002113200629031821142006280210210a2009102c41dffac000210920034280a094a58d1d7c2208200354220720042007ad7c220b200454200820035a1b0d0102402011420020121b221120087d22152011562010420020121b2210200b7d2011200854ad7d220820105620082010511b4101470d0041868dc2002109411d210d0c020b20134200200a1b210b20144200200a1b21100240200342ffffe883b1de165620044200522004501b0d002010200b8450450d0041a38dc2002109411f210d0c020b200641086a200141022015200810ad01024020062802082209450d00200628020c210d0c020b0240201020037c22112010542209200b20047c2009ad7c2210200b542010200b511b450d0041c28dc2002109412d210d0c020b41002109024020012002470d000c020b024020012002412010dd050d000c020b0240201542ffffe883b1de165620084200522008501b0d0020050d004187fbc0002109411b210d0c020b20012015200810a201200641e0006a41086a2209418be9c500ad42808080808001841002220741086a290000370300200620072900003703602007102c200641c0006a41086a220a200929030037030020062006290360370340200941d6b5c000ad4280808080b001841002220741086a290000370300200620072900003703602007102c200641d0006a41086a220c200929030037030020062006290360370350200641e0006a2002109f0141c000102a2207450d00200720062903403700002007200629035037001020072006290060370020200741086a200a290300370000200741186a200c290300370000200741286a2009290000370000200741306a200641e0006a41106a290000370000200741386a200641e0006a41186a290000370000410021092006200741c0004101410041001097012006280200210a2007102c0240200a4101460d00200210a101200641e0006a41386a2010370300200641e0006a41306a2011370300200641e0006a41086a41003a0000200641e9006a2002290000370000200641f1006a200241086a290000370000200641f9006a200241106a29000037000020064181016a200241186a290000370000200641033a006041014100200641e0006a1092010b200641c8016a4200370300200641c0016a4280a094a58d1d370300200641b8016a2004370300200641b0016a2003370300200641e0006a41086a41023a0000200641e9006a200129000037000020064189016a2002290000370000200641f1006a200141086a290000370000200641f9006a200141106a29000037000020064181016a200141186a29000037000020064191016a200241086a29000037000020064199016a200241106a290000370000200641a1016a200241186a290000370000200641033a006041014100200641e0006a10920120022011201010a2014280a094a58d1d420010a9010c010b1033000b2000200d36020420002009360200200641e0016a24000be90408027f017e037f017e017f027e037f017e23004180016b2203240020012002844200522204ad2105024020040d00200341c0006a41186a22064200370300200341c0006a41106a22074200370300200341c0006a41086a2208420037030020034200370340200341f0006a41086a2204418be9c500ad428080808080018422091002220a41086a2900003703002003200a290000370370200a102c2008200429030037030020032003290370220b3703602003200b370340200441c9b5c000ad4280808080d00184220c1002220a41086a2900003703002003200a290000370370200a102c20072003290370220b370300200341206a41086a220d2008290300370300200341206a41106a220e200b370300200341206a41186a220f20042903003703002003200b37036020032003290340370320200341086a200341206a4120109e01200341086a41106a290300210b200329031021102003280208210a20064200370300200742003703002008420037030020034200370340200420091002220741086a290000370300200320072900003703702007102c20082004290300370300200320032903702209370360200320093703402004200c1002220741086a290000370300200320072900003703702007102c200620042903002209370300200d2008290300370300200e2003290370220c370300200f20093703002003200c370360200320032903403703202003200b4200200a1b370348200320104200200a1b370340200341206aad4280808080800484200341c0006aad428080808080028410010b2000200137030820002005370300200041106a200237030020034180016a24000bb3ac010f017f017e047f017e077f017e027f017e027f017e027f017e157f027e0e7f230041f0056b2200240042002101200041b0036a41186a4200370300200041b0036a41106a22024200370300200041b0036a41086a22034200370300200042003703b003200041b0046a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b0043703b0032004419883c100ad4280808080a001841002220541086a290000370300200020052900003703b0042005102c200220002903b0042206370300200041c0056a41086a2003290300370300200041c0056a41106a2006370300200041c0056a41186a20042903003703002000200637038803200020002903b0033703c005200041b0036a200041c0056a412010d0010240024020002802b00322070d0041012107410021080c010b20002902b4032201422088a721080b0240024002400240200841ffffff3f712008470d0020084105742204417f4c0d000240024020040d00410121090c010b2004102a2209450d020b4100210a4100210b4100210c02402008450d00200841057421052009210420072103034020042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200441206a2104200341206a2103200541606a22050d000b200841057441606a41057641016a210c2008210b0b200041b0036a41186a22084200370300200041b0036a41106a220d4200370300200041b0036a41086a22034200370300200042003703b003200041b0046a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b0043703b003200441eae5c200ad4280808080f000841002220541086a290000370300200020052900003703b0042005102c20004188036a41086a20042903002206370300200020002903b004220e370388032002200e370000200241086a2006370000200041c0056a41086a2003290300370300200041c0056a41106a200d290300370300200041c0056a41186a2008290300370300200020002903b0033703c005200041b0036a200041c0056a10d10120002902b403420020002802b00322031b2206422088a7220541306c220841306d21040240024020080d004101210f0c010b200441ffffff3f712004470d04200441057422084100480d042008102a220f450d022004210a0b2006a721102003410820031b210d0240024020050d00410021080c010b200541306c210541002108200f2104200d21030340200341086a2900002106200341106a290000210e20032900002111200441186a200341186a290000370000200441106a200e370000200441086a200637000020042011370000200841016a2108200441206a2104200341306a2103200541506a22050d000b0b02402010450d00200d102c0b02402001a722042001422088a7220d6b20084f0d00200d20086a2203200d490d04200441017422052003200520034b1b220341ffffff3f712003470d04200341057422054100480d040240024020040d002005102a21070c010b200720044105742005102e21070b2007450d022001422088a7210d2003ad21010b2007200d4105746a200f200841057410db051a0240200a450d00200f102c0b200041b0036a41186a220f4200370300200041b0036a41106a220a4200370300200041b0036a41086a22034200370300200042003703b003200041b0046a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b0043703b003200441a283c100ad42808080809001841002220541086a290000370300200020052900003703b0042005102c20004188036a41086a20042903002206370300200020002903b004220e370388032002200e370000200241086a2006370000200041c0056a41086a2003290300370300200041c0056a41106a200a290300370300200041c0056a41186a200f290300370300200020002903b0033703c005200041b0036a200041c0056a10d10120002902b403420020002802b00322041b2206422088a7220341306c220241306d210f410021050240024020020d004101210a4100210f0c010b200f41ffffff3f71200f470d04200f41057422024100480d042002102a220a450d020b2006a721122004410820041b211002402003450d00200341306c210241002105200a2104201021030340200341086a2900002106200341106a290000210e20032900002111200441186a200341186a290000370000200441106a200e370000200441086a200637000020042011370000200541016a2105200441206a2104200341306a2103200241506a22020d000b0b200d20086a211302402012450d002010102c0b024002402001a7220420136b2005490d00200142ffffffff0f8321140c010b201320056a22032013490d04200441017422082003200820034b1b220341ffffff3f712003470d04200341057422084100480d040240024020040d002008102a21070c010b200720044105742008102e21070b2007450d022003ad21140b200720134105746a200a200541057410db051a0240200f450d00200a102c0b200041c0056a10d201200041b0036a20002802c005220420002802c80510d301024020002802c405450d002004102c0b200041e0026a41086a200041b0036a41086a22032903002206370300200041e0026a41106a200041b0036a41106a2208290300220e370300200041e0026a41186a200041b0036a41186a22022903002211370300200041e0026a41206a200041b0036a41206a2d000022043a0000200020002903b00322013703e00220004188036a41206a20043a000020004188036a41186a201137030020004188036a41106a200e37030020004188036a41086a20063703002000200137038803200041b0036a20004188036a10d4010240024020002802d00322040d004104211541002108410021160c010b200041c0056a41186a2002290300370300200041c0056a41106a2008290300370300200041c0056a41086a2003290300370300200020002903b0033703c00520002902d4032106412c102a2215450d02201520002903c0053702002015200637022420152004360220201541186a200041c0056a41186a2204290300370200201541106a200041c0056a41106a2203290300370200201541086a200041c0056a41086a2208290300370200200041c0056a41206a20004188036a41206a2d00003a0000200420004188036a41186a290300370300200320004188036a41106a290300370300200820004188036a41086a29030037030020002000290388033703c005200041b0036a200041c0056a10d401024020002802d003220d0d0041012108410121160c010b41022102412c210341012108410121160340200041c0046a41186a200041b0036a41186a2903002206370300200041c0046a41106a200041b0036a41106a290300220e370300200041c0046a41086a200041b0036a41086a2903002211370300200020002903b00322013703c00420002902d4032117200041e0046a41186a220f2006370300200041e0046a41106a220a200e370300200041e0046a41086a22102011370300200020013703e004024020082016470d00200841016a22042008490d0620022004200220044b1b2216ad422c7e2206422088a70d062006a722044100480d060240024020080d002004102a21150c010b201520032004102e21150b2015450d040b201520036a220420002903e004370200200441186a200f290300370200200441106a200a290300370200200441086a2010290300370200200441246a2017370200200441206a200d360200200241026a21022003412c6a2103200841016a2108200041b0036a200041c0056a10d40120002802d003220d0d000b0b2000420037028405200041d0e1c100360280052008201320056a22046a2218ad42e0007e2206422088a70d002006a72219417f4c0d00410821120240024020190d004108211a4108211b0c010b2019102a221a450d02201a211b0b410021134100211c024020044105742202450d002002410575221cad42d8007e2206422088a70d042006a722034100480d042003102a2212450d020b02402004450d00200241606a211d200041e0036a2103200041d8036a211e2012210d41002105200721040340200041e0026a41186a220f200441186a220a290000370300200041e0026a41106a2210200441106a2213290000370300200041e0026a41086a221f200441086a2220290000370300200020042900003703e002200041c0056a41186a200a290000370300200041c0056a41106a2013290000370300200041c0056a41086a2020290000370300200020042900003703c00520004180056a200041c0056a200510d501200041b0036a41086a4200370300200041b0036a41106a4200370300200041b0036a41186a4200370300200041b0036a41206a4200370300201e4200370300200341186a200f290300370000200341106a2010290300370000200341086a201f290300370000200320002903e002370000200042003703b003200d200041b0036a41d00010db05220d41d0006a41003a0000200d41d8006a210d200441206a2104200541016a2105200241606a22020d000b201d41057641016a21130b02402014500d002007102c0b0240024020182008412c6c2204412c6d2203490d00201821210c010b201841017422052003200520034b1b2221ad42e0007e2206422088a70d042006a722034100480d040240024020180d002003102a211a0c010b201a20192003102e211a0b201a450d02201a211b0b201520046a212202400240024020080d0041002123201521240c010b200041e0046a41106a211f20152104201a21254100212302400340200041c0046a41186a2203200441186a290200370300200041c0046a41106a2205200441106a290200370300200041c0046a41086a2208200441086a290200370300200020042902003703c0042004412c6a212420042802202226450d02200441286a2802002110200441246a2802002127200041e0026a41186a22282003290300370300200041e0026a41106a22292005290300370300200041e0026a41086a222a2008290300370300200020002903c0043703e002200041d0026a200041e0026a10d6012010ad42c8007e2206422088a70d042006a72204417f4c0d04200041d0026a41086a290300211720002903d00221140240024020040d004108211e0c010b2004102a221e450d060b02400240024020100d0041002110410021200c010b202620104105746a211d410021202026210d0340200d41086a2900002106200d41106a290000210e200d2900002111200041b0036a41186a2207200d41186a290000370300200041b0036a41106a2218200e370300200041b0036a41086a22192006370300200020113703b003200d41206a210d20004180056a2104200028028405210f024003402004280200220241086a210320022f0106220a4105742104410021050240024003402004450d01200041b0036a2003412010dd052208450d02200441606a2104200541016a2105200341206a21032008417f4a0d000b2005417f6a210a0b200f450d02200f417f6a210f2002200a4102746a4194036a21040c010b0b2013200220054102746a41e8026a220328020022044d0d032012200441d8006c6a22042903202106200441286a290300210e200041e0046a41186a22024200370300201f4200370300200041e0046a41086a22054200370300200042003703e004200041b0046a41086a2204418be9c500ad42808080808001841002220841086a290000370300200020082900003703b0042008102c20052004290300370300200020002903b0043703e004200441c9b5c000ad4280808080d001841002220841086a290000370300200020082900003703b0042008102c200041b0056a41086a20042903002211370300200020002903b00422013703b005201f2001370000201f41086a2011370000200041c0056a41086a2005290300370300200041c0056a41106a201f290300370300200041c0056a41186a2002290300370300200020002903e0043703c005200041b8026a200041c0056a4120109e01200041a8026a20002903c002200041b8026a41106a290300427f420010e1052013200328020022044d0d0520004198026a2014201720002903a802420020002802b80222051b221142012011420156200041a8026a41086a290300420020051b22114200522011501b22051b2011420020051b10e1052012200441d8006c6a220441286a427f200e20062000290398027c22112006542205ad7c220120052001200e54201120065a1b22051b3703002004427f201120051b37032020004188036a41186a2205200729030037030020004188036a41106a2208201829030037030020004188036a41086a22022019290300370300200020002903b00337038803200328020021030240024020202010460d00202021040c010b201041016a22042010490d0c2010410174220f2004200f20044b1b220fad42c8007e2206422088a70d0c2006a722044100480d0c0240024020100d002004102a211e0c010b201e201041c8006c2004102e211e0b201e450d0a20102104200f21100b201e200441c8006c6a2204420037030020042003360220200441186a4200370300200441106a4200370300200441086a420037030020042000290388033702242004412c6a2002290300370200200441346a20082903003702002004413c6a2005290300370200202041016a21200b200d201d470d000b0b02402027450d002026102c0b20004190056a41186a2208202829030037030020004190056a41106a2202202929030037030020004190056a41086a220d202a290300370300200020002903e00237039005200041e0046a41186a220f4200370300201f4200370300200041e0046a41086a22034200370300200042003703e004200041b0046a41086a2204418be9c500ad42808080808001841002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b0043703e004200441c9b5c000ad4280808080d001841002220541086a290000370300200020052900003703b0042005102c200041b0056a41086a20042903002206370300200020002903b004220e3703b005201f200e370000201f41086a2006370000200041c0056a41086a2003290300370300200041c0056a41106a201f290300370300200041c0056a41186a200f290300370300200020002903e0043703c00520004180026a200041c0056a4120109e01200041f0016a20002903880220004180026a41106a290300427f420010e105200041e0016a2014201720002903f001420020002802800222041b220642012006420156200041f0016a41086a290300420020041b22064200522006501b22041b2006420020041b10e10520254200370308202520002903e00137030020254200370310202541186a4200370300202541286a42003703002025420137032020252020360238202520103602342025201e360230202520002903900537023c202541c4006a200d290300370200202541cc006a2002290300370200202541d4006a2008290300370200202341016a2123202541e0006a21252024210420242022470d010c040b0b41d087c600200420131038000b41a888c600200420131038000b20242022460d000340202441206a2802002203450d012024412c6a21040240202441246a280200450d002003102c0b2004212420222004470d000b0b02402016450d002015102c0b41c007102a2207450d0141f006102a222b450d014100212841142129024002402013411420134114491b222a0d004114212c410021150c010b201241a87f6a2126201341d8006c2124201b202341e0006c6a21184114211d200041b0036a41186a2116200041b0036a41106a211e200041b0036a41086a21274100211541002125034002402013450d00202421032012210403400240200441d0006a2d00000d0002400240200441206a290300220e200441286a29030022118450450d0042002106427f210e427f21110c010b427f2106200041d0016a427f427f200e201110e105200041d0016a41086a290300211120002903d001210e0b2004200e37030020042011370308200441106a2006370300200441186a20063703000b200441d8006a2104200341a87f6a22030d000b0b201b210802402023450d0002400340024020082802382204450d00200441c8006c2105200828023041206a210403402013200428020022034d0d0302402012200341d8006c6a22032d00500d0020032903202206200341286a290300220e84500d00200041b0036a2008290310200841186a2903002008290300200841086a2903002006200e10d701200320032903002206427f2006427f20002903b80320002802b00341014622021b22117c220e200e200654220d200341086a220f2903002206427f201e29030020021b22017c200dad7c220e200654200e2006511b22021b201120018450220d1b370300200f2006427f200e20021b200d1b3703000b200441c8006a2104200541b87f6a22050d000b0b200841e0006a22082018460d020c000b0b41a888c600200320131038000b202541016a21252024210420262103201221050340024020040d00201d212c0c030b200441a87f6a2104200341d8006a2103200541d0006a2108200541d8006a2202210520082d00000d000b02402004450d00200341086a2903002106200341186a290300210e200341106a2903002111200329030021014100210503400240200220056a220841d0006a2d00000d00200841086a29030022172006200120062011200e200829030022142017200841106a290300222d200841186a290300222e10d80141ff0171410146220d1b210620142001200d1b2101202e200e200d1b210e202d2011200d1b211120082003200d1b21030b2004200541d8006a2205470d000b20030d00201d212c0c020b200341013a005002402023450d002003410c6a211f200341306a2120201b21050340200541e0006a2119024020052802382208450d0020052802302104200841c8006c2108034002400240201f2004460d00200441246a2020412010dd050d010b200541186a22022903002101200341086a220d2903002106200529031021112003290300210e20032903102117200441186a200341186a220f290300370300200441106a2017370300200420064200200620017d200e201154ad7d2217200e20117d2214200e56201720065620172006511b220a1b20112001845022101b3703082004200e42002014200a1b20101b370300200d2903002106200f290300210e2003290300211120052003290310370320200541286a200e37030020052011370310200220063703000b200441c8006a2104200841b87f6a22080d000b0b2019210520192018470d000b0b2016200341c8006a290000370300201e200341c0006a2900003703002027200341386a290000370300200020032900303703b003200341286a29030021062003290320210e024002402015201d460d00201d212c0c010b201d41016a2204201d490d06201d41017422032004200320044b1b222cad42307e2211422088a70d062011a722044100480d0602400240201d0d002004102a21070c010b2007201d41306c2004102e21070b2007450d04201d2115202c211d0b20272903002111201e29030021012016290300211720002903b00321142007201541306c6a2204200e37032020042014370300200441286a2006370300200441186a2017370300200441106a2001370300200441086a2011370300201541016a21152025202a490d000b0b02402023450d00201b202341e0006c6a2124201541306c211841142129200041c0056a41186a2119200041c0056a41106a211d200041c0056a41086a212541002128201b211f03402019201f41d4006a290000370300201d201f41cc006a2900003703002025201f41c4006a2900003703002000201f29003c3703c0050240201f2802382204450d00201f280230220a200441c8006c6a2120201f41106a211e41002110410421134100210f0340200a220d41246a2105200d41c8006a210a410021082018210320072104024003402003450d01024020052004460d0020042005412010dd052102200841016a2108200341506a2103200441306a210420020d010b0b418094ebdc0321040240201e200d10d9010d00410021030240200d290310201f29032085200d41186a290300201f41286a29030085844200520d00200041b0036a428094ebdc034200200d290300200d41086a290300201e290300201e41086a29030010d70120002802b0034101460d0120002903b803220e42ff93ebdc0356200041b0036a41106a29030022064200522006501b0d01200ea721030b200321040b200020043602b0032000418094ebdc033602b403200041b0036a2004418094ebdc034b4102746a2802002103200041b0036a41186a2205200d413c6a290000370300200041b0036a41106a2208200d41346a290000370300200041b0036a41086a2202200d412c6a2900003703002000200d2900243703b00302400240200f2010460d00200f21040c010b201041016a22042010490d092010410174220d2004200d20044b1b220dad42247e2206422088a70d092006a722044100480d090240024020100d002004102a21130c010b2013201041246c2004102e21130b2013450d0720102104200d21100b2013200441246c6a220420002903b003370200200229030021062008290300210e2005290300211120042003360220200441186a2011370200200441106a200e370200200441086a2006370200200f41016a210f0b200a2020470d000b024002400240200f450d0002400240200f41246c22050d00410021030c010b201341206a2104410021030340200428020020036a2103200441246a21042005415c6a22050d000b0b02404100418094ebdc0320036b22042004418094ebdc034b1b220d200f6e2204418094ebdc032004418094ebdc03491b2202450d00201341206a2104410021030340200f2003460d032000417f2004280200220520026a220820082005491b22053602b0032000418094ebdc033602b4032004200041b0036a2005418094ebdc034b4102746a280200360200200441246a2104200f200341016a2203470d000b0b0240200d2002200f6c6b2202450d00410021040340200f2004200f7022034d0d042000417f2013200341246c6a2203280220220541016a220820082005491b22053602b0032000418094ebdc033602b4032003200041b0036a2005418094ebdc034b4102746a280200360220200441016a22042002490d000b0b200041b0036a41186a22032019290300370300200041b0036a41106a2205201d290300370300200041b0036a41086a22082025290300370300200020002903c0053703b003024020282029470d00202941016a22042029490d0a202941017422022004200220044b1b2204ad422c7e2206422088a70d0a2006a722024100480d0a0240024020290d002002102a212b0c010b202b2029412c6c2002102e212b0b202b450d0820292128200421290b202b2028412c6c6a220420002903b003370200200829030021062005290300210e200329030021112004200f3602282004201036022420042013360220200441186a2011370200200441106a200e370200200441086a2006370200202841016a21280c030b2010450d022013102c0c020b41d087c6002003200f1038000b41d087c6002003200f1038000b201f41e0006a221f2024470d000b0b0240201c450d002012102c0b02402023450d00202341e0006c2103201b41306a210403400240200441046a280200450d002004280200102c0b200441e0006a2104200341a07f6a22030d000b0b02402021450d00201a102c0b20002802800520002802840520002802880510da010240024020070d0041012113200041013a00b403200041093a00b00341014100200041b0036a109201200041c0056a21020c010b42002106200041b0036a41186a4200370300200041b0036a41106a222f420037030041082108200041b0036a41086a22034200370300200042003703b003200041b0046a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b004220e370388032000200e3703b003200441eae5c200ad4280808080f000841002220541086a290000370300200020052900003703b0042005102c202f20002903b004220e370300200041c0056a41086a2003290300370300200041c0056a41106a200e370300200041c0056a41186a20042903003703002000200e37038803200020002903b0033703c005200041b0036a200041c0056a10d101024020002802b0032204450d00200041c0056aad4280808080800484100520002902b4032106200421080b2006422088a7220441306c220341306d2130410021220240024020030d0041012131410021300c010b203041ffffff3f712030470d05203041057422034100480d052003102a2231450d030b2006a7210202402004450d00200441306c21054100212220312104200821030340200341086a2900002106200341106a290000210e20032900002111200441186a200341186a290000370000200441106a200e370000200441086a200637000020042011370000202241016a2122200441206a2104200341306a2103200541506a22050d000b0b02402002450d002008102c0b42002106200041b0036a41186a22024200370300200041b0036a41106a220d420037030041082108200041b0036a41086a22034200370300200042003703b003200041b0046a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b004220e370388032000200e3703b003200441a283c100ad42808080809001841002220541086a290000370300200020052900003703b0042005102c20004188036a41086a2004290300220e370300200020002903b004221137038803202f2011370000202f41086a200e370000200041c0056a41086a2003290300370300200041c0056a41106a200d290300370300200041c0056a41186a2002290300370300200020002903b0033703c005200041b0036a200041c0056a10d101024020002802b0032204450d00200041c0056aad4280808080800484100520002902b4032106200421080b2006422088a7220441306c220341306d21324100211b0240024020030d0041012133410021320c010b203241ffffff3f712032470d05203241057422034100480d052003102a2233450d030b2006a7210202402004450d00200441306c21054100211b20332104200821030340200341086a2900002106200341106a290000210e20032900002111200441186a200341186a290000370000200441106a200e370000200441086a200637000020042011370000201b41016a211b200441206a2104200341306a2103200541506a22050d000b0b02402002450d002008102c0b024002400240201541306c2203450d00200721040340200441286a2903002106200441206a290300210e200041e0046a41186a200441186a290200370300200041e0046a41106a200441106a290200370300200041e0046a41086a200441086a290200370300200020042902003703e004200e2006844200520d02200441306a2104200341506a22030d000b0b410121184100211e0240202c0d00410021190c020b2007102c410021190c010b200041e0026a41086a2205200041e0046a41086a290300370300200041e0026a41106a2208200041e0046a41106a290300370300200041e0026a41186a2202200041e0046a41186a290300370300200020002903e004220637039005200020063703e0024120102a2218450d03201820002903e002370000201841186a2002290300370000201841106a2008290300370000201841086a20052903003700000240024020034130470d004101211e410121190c010b200441306a21052007201541306c6a220241506a210d4101211e4101211903402005210402400340200441286a2903002106200441206a290300210e200041e0046a41186a2203200441186a290200370300200041e0046a41106a2205200441106a290200370300200041e0046a41086a2208200441086a290200370300200020042902003703e004200e2006844200520d012002200441306a2204470d000c030b0b200041c0056a41086a20082903002206370300200041c0056a41106a2005290300220e370300200041c0056a41186a20032903002211370300200020002903e00422013703c00520004190056a41186a2208201137030020004190056a41106a220f200e37030020004190056a41086a220a2006370300200020013703900502402019201e470d00201e41016a2203201e490d08201e41017422052003200520034b1b221941ffffff3f712019470d08201941057422034100480d0802400240201e0d002003102a21180c010b2018201e4105742003102e21180b2018450d060b200441306a21052018201e4105746a2203200029039005370000200341186a2008290300370000200341106a200f290300370000200341086a200a290300370000201e41016a211e200d2004470d000b0b202c450d002007102c0b200042003702e402200041d0e1c1003602e0020240201e450d00201e410574210320182104034020004188036a41186a200441186a29000037030020004188036a41106a200441106a29000037030020004188036a41086a200441086a2900003703002000200429000037038803200041b0036a41186a4200370300200041b0036a41106a4200370300200041b0036a41086a4200370300200042003703b003200041003602d803200042083703d003200041c0056a200041e0026a20004188036a200041b0036a10db01024020002802e0052205450d0020002802e405450d002005102c0b200441206a2104200341606a22030d000b0b02402028412c6c2204450d00202b20046a2120200041e0046a41106a2113418be9c500ad42808080808001842117202b211003400240201028022841246c2204450d002010280220221220046a211f0340200041c0016a201010d601200041c0016a41086a290300210e20002903c0012111200041e0046a41186a2208420037030020134200370300200041e0046a41086a22034200370300200042003703e004200041b0046a41086a220420171002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b0043703e004200441c9b5c000ad4280808080d001841002220541086a290000370300200020052900003703b0042005102c200041b0056a41086a20042903002206370300200020002903b00422013703b00520132001370000201341086a2006370000200041c0056a41086a2003290300370300200041c0056a41106a2013290300370300200041c0056a41186a2008290300370300200020002903e0043703c005200041a8016a200041c0056a4120109e0120004198016a20002903b001200041a8016a41106a290300427f420010e10520004188016a2011200e200029039801420020002802a80122041b22064201200642015620004198016a41086a290300420020041b22064200522006501b22041b2006420020041b10e105200041f8006a2000290388012206428094ebdc0380220e4200201222023502202211420010e005200041f8006a41086a2903002000290378220120112006200e4280ec94a37c7e7c7e22062006428094ebdc038022064280ec94a37c7e7c4280cab5ee01562006a76aad7c2206200154ad7c210e200241246a2112200041e0026a210420002802e402210f024003402004280200220d41086a2103200d2f0106220a4105742104410021050240024003402004450d0120022003412010dd052208450d02200441606a2104200541016a2105200341206a21032008417f4a0d000b2005417f6a210a0b200f450d02200f417f6a210f200d200a4102746a41f8066a21040c010b0b200d41e8026a200541306c6a2104024020022010460d0020022010412010dd05450d002004427f2004290310221120067c220120012011542203200441186a22052903002211200e7c2003ad7c220120115420012011511b22031b3703102005427f200120031b37030020004188036a41186a2202201041186a29000037030020004188036a41106a220d201041106a29000037030020004188036a41086a220f201041086a2900003703002000201029000037038803200441286a2105200441206a2108024020042802282203200441246a280200470d00200341016a22042003490d0b2003410174220a2004200a20044b1b220aad42307e2211422088a70d0b2011a722044100480d0b0240024020030d002004102a21040c010b2008280200200341306c2004102e21040b2004450d0920082004360200200841046a200a360200200528020021030b2008280200200341306c6a220420002903880337030020042006370320200441186a2002290300370300200441106a200d290300370300200441086a200f290300370300200441286a200e3703002005200528020041016a3602000c010b2004427f2004290300221120067c220120012011542203200441086a22052903002211200e7c2003ad7c220120115420012011511b22031b3703002005427f200120031b3703002004427f2004290310221120067c220620062011542203200441186a22052903002206200e7c2003ad7c220e200654200e2006511b22031b3703102005427f200e20031b3703000b2012201f470d000b0b2010412c6a22102020470d000b0b4108213420004190056a41086a200041e0026a41086a280200360200200020002903e0023703900502400240201e0d00410021354100212a0c010b201e41057422044105752235ad42307e2206422088a70d052006a722034100480d052003102a2234450d03201820046a211e200041e0046a41106a21134100212a418be9c500ad428080808080018421172034210d2018210f0340200f41086a2900002106200f41106a290000210e200f2900002111200041b0036a41186a2212200f41186a290000370300200041b0036a41106a221f200e370300200041b0036a41086a22202006370300200020113703b003200f41206a210f20004190056a2104200028029405210a024003402004280200220241086a210320022f01062210410574210441002105024003402004450d01200041b0036a2003412010dd052208450d03200441606a2104200541016a2105200341206a21032008417f4a0d000b2005417f6a21100b0240200a450d00200a417f6a210a200220104102746a41f8066a21040c010b0b41cec4c10041da001054000b20004188036a41186a2208201229030037030020004188036a41106a220a201f29030037030020004188036a41086a22102020290300370300200020002903b003370388032002200541306c6a22044180036a290300210e200441f8026a2903002111200041e0046a41186a2202420037030020134200370300200041e0046a41086a22034200370300200042003703e004200041b0046a41086a220420171002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b0043703e004200441c9b5c000ad4280808080d001841002220541086a290000370300200020052900003703b0042005102c200041b0056a41086a20042903002206370300200020002903b00422013703b00520132001370000201341086a2006370000200041c0056a41086a2003290300370300200041c0056a41106a2013290300370300200041c0056a41186a2002290300370300200020002903e0043703c005200041e0006a200041c0056a4120109e01200041d0006a2000290368200041e0006a41106a290300427f420010e105200041c0006a20002903504200200028026022041b220642012006420156200041d0006a41086a290300420020041b22064200522006501b22041b2006420020041b2011200e10e005200d41186a2008290300370300200d41106a200a290300370300200d41086a2010290300370300200d200029038803370300200d41286a200041c0006a41086a290300370300200d2000290340370320202a41016a212a200d41306a210d200f201e470d000b0b02402019450d002018102c0b4100213602400240202a410d202a410d491b22370d004108211341002126410021230c010b203741306c2204102a2213450d03024020040d0041002126203721230c010b203741306c210841002105410021260340203420056a22042903002106200441086a290300210e200441106a2903002111200441186a2903002101201320056a220341286a200441286a290300370300200341206a200441206a290300370300200341186a2001370300200341106a2011370300200341086a200e37030020032006370300202641016a21262008200541306a2205470d000b0240024020264115490d0020264101762238ad42307e2206422088a70d042006a72204417f4c0d040240024020040d00410821394108210a0c010b2004102a2239450d062039210a0b201341506a213a201341f07e6a213b410421204100213c41002124410021122026212503402025210d41002125410121020240200d417f6a2205450d000240024002400240024002402013200541306c6a200d41306c220f20136a41a07f6a412010dd054100480d00200d417e6a2108203b200f6a210441002125410021030340024020082003470d00200d21020c080b200341016a2103200441306a2004412010dd052105200441506a21042005417f4a0d000b200341016a21022003417f73200d6a21050c010b203b200f6a210402400340024020054101470d00410021050c020b2005417f6a2105200441306a2004412010dd052103200441506a210420034100480d000b0b200d2005490d01200d20264b0d03200d20056b22024101762208450d00203a200f6a21042013200541306c6a21030340200041b0036a41286a220f200341286a2210290300370300200041b0036a41206a221f200341206a221e290300370300200041b0036a41186a2218200341186a2219290300370300200041b0036a41106a221d200341106a2225290300370300200041b0036a41086a2215200341086a2223290300370300200020032903003703b003200441086a22162903002106200441106a2227290300210e200441186a221a2903002111200441206a221c2903002101200441286a222129030021172003200429030037030020102017370300201e2001370300201920113703002025200e370300202320063703002021200f290300370300201c201f290300370300201a20182903003703002027201d29030037030020162015290300370300200420002903b003370300200441506a2104200341306a21032008417f6a22080d000b0b024020050d00200521250c050b0240200241094d0d00200521250c050b200d20264b0d01200d20056b21082013200541306c6a210f0340200d2005417f6a2225490d040240200d20256b22024102490d002013200541306c6a22042013202541306c6a2205412010dd05417f4a0d002005290300210620052004290300370300200041b0036a41286a2218200541286a2203290300370300200041b0036a41206a2219200541206a2210290300370300200041b0036a41186a221d200541186a221f290300370300200041b0036a41106a2215200541106a221e290300370300200041b0036a41086a2223200541086a22162903003703002016200441086a290300370300201e200441106a290300370300201f200441186a2903003703002010200441206a2903003703002003200441286a290300370300200020063703b0034101211e024020024103490d00200541e0006a200041b0036a412010dd05417f4a0d0041022103200f210402400340200441286a200441d8006a290300370300200441206a200441d0006a290300370300200441186a200441c8006a290300370300200441106a200441c0006a290300370300200441086a200441386a2903003703002004200441306a221029030037030020082003460d01200441e0006a211f2003211e20102104200341016a2103201f200041b0036a412010dd05417f4a0d020c000b0b2003211e0b2005201e41306c6a220420002903b003370300200441286a2018290300370300200441206a2019290300370300200441186a201d290300370300200441106a2015290300370300200441086a20232903003703000b2025450d05200f41506a210f200841016a2108202521052002410a4f0d050c000b0b2005200d1047000b200d2005417f6a2225490d010b200d2026103f000b2025200d1047000b02402012203c470d00203c41016a2204203c490d09203c41017422032004200320044b1b220441ffffffff01712004470d09200441037422034100480d0902400240203c0d002003102a21200c010b2020203c4103742003102e21200b2020450d072004213c202421120b202020124103746a2204200236020420042025360200202441016a221221240240024020124102490d0002400340024002400240024020202012417f6a22244103746a2204280200450d00201241037420206a220841746a2802002205200428020422034d0d000240201241024b0d0020122124410221122025450d080c090b20202012417d6a221e4103746a2802042204200320056a4d0d010240201241034b0d0020122124410321122025450d080c090b200841646a280200200420056a4d0d01201221240c060b20124103490d012004280204210320202012417d6a221e4103746a28020421040b20042003490d010b2012417e6a211e0b0240024002400240024002402012201e41016a22154b2223450d002012201e4b2216450d012020201e4103746a2218280204222720182802006a2204202020154103746a2219280200221d490d02200420264b0d032013201d41306c6a22102019280204221f41306c22036a2108200441306c21052004201d6b220d201f6b2204201f4f0d0420392008200441306c220310db051a200a20036a210202400240201f4101480d00200441014e0d010b20082104200a21050c060b203a20056a21032008210403402003200441506a2208200241506a220d200d2008412010dd05410048220f1b2205290300370300200341286a200541286a290300370300200341206a200541206a290300370300200341186a200541186a290300370300200341106a200541106a290300370300200341086a200541086a2903003703002002200d200f1b21020240201020082004200f1b2204490d00200a21050c070b200341506a2103200a2105200a2002490d000c060b0b41d087c600201520121038000b41d087c600201e20121038000b201d20041047000b20042026103f000b20392010200310db051a200a20036a210202400240201f4101480d00200d201f4a0d010b20102104200a21050c010b201320056a210f200a210520102104034020042008200520082005412010dd05410048220d1b2203290300370300200441286a200341286a290300370300200441206a200341206a290300370300200441186a200341186a290300370300200441106a200341106a290300370300200441086a200341086a2903003703002005200541306a200d1b2105200441306a2104200841306a2008200d1b2208200f4f0d01200220054b0d000b0b20042005200220056b220320034130706b10db051a02402016450d002018201d360200201841046a2027201f6a3602002023450d022019201941086a20122015417f736a41037410dc051a20242112202441014d0d030c010b0b41a888c600201e20121038000b418ab4c000411d41acfec5001036000b20250d010b0b0240203c450d002020102c0b2038450d012039102c0c010b20264102490d002026417f6a2103202641306c20136a41506a21024101210503400240024002400240202620032204417f6a2203490d00202620036b220d4102490d032013200441306c6a22042013200341306c6a2208412010dd05417f4a0d032008290300210620082004290300370300200041b0036a41286a2212200841286a220f290300370300200041b0036a41206a221f200841206a220a290300370300200041b0036a41186a2220200841186a2210290300370300200041b0036a41106a221e200841106a2218290300370300200041b0036a41086a2219200841086a221d290300370300201d200441086a2903003703002018200441106a2903003703002010200441186a290300370300200a200441206a290300370300200f200441286a290300370300200020063703b00341012104200d4103490d02200841e0006a200041b0036a412010dd05417f4a0d024100210d200221040340200441286a200441d8006a290300370300200441206a200441d0006a290300370300200441186a200441c8006a290300370300200441106a200441c0006a290300370300200441086a200441386a2903003703002004200441306a220a2903003703002005200d220f460d02200f417f6a210d200441e0006a2110200a21042010200041b0036a412010dd05417f4a0d020c000b0b200320261047000b4102200f6b21040b2008200441306c6a220420002903b003370300200441286a2012290300370300200441206a201f290300370300200441186a2020290300370300200441106a201e290300370300200441086a20192903003703000b200241506a21022005417f6a210520030d000b0b203721230b2013202641306c6a221220136b220341306e21040240024020030d004101211d0c010b200441057422034100480d052003102a221d450d03200421360b0240024020132012470d00410021050c010b2013202641306c6a210841002105201d210420132103034020042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200541016a2105200441206a21042008200341306a2203470d000b0b024002402034202a41306c6a2034203741306c6a6b22040d0041082118410021160c010b200441306e211620044100480d052004102a2218450d030b02400240202a410d4b0d00410121274100210a2018210f410121100c010b203741306c202a41306c22046b2108200420346a41506a21044100210a201821030340200441086a2903002106200441106a290300210e200441186a290300211120042903002101200341286a200441286a290300370300200341206a200441206a290300370300200341186a2011370300200341106a200e370300200341086a200637030020032001370300200341306a2103200441506a2104200a41016a210a200841306a22080d000b200a41ffffff3f71200a470d05200a41057422044100480d052004102a2210450d032018200a41306c6a210f410021270b024002402018200f470d00410021080c010b410021082010210420182103034020042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200841016a2108200441206a2104200f200341306a2203470d000b0b200041b0036a201d20052031202210dc01200041c4036a280200220d41ffffff3f71200d470d01200d410574221f417f4c0d01200041c0036a280200212a20002802bc03211520002802b403212220002802b003211a02400240201f0d00410121200c010b201f102a2220450d030b02400240200d0d0041002104410021030c010b200d41057421022020210420152103034020042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200441206a2104200341206a2103200241606a22020d000b200d41057441606a41057641016a2103200d21040b20202003201d200510dd0102402004450d002020102c0b02400240201f0d00410121190c010b201f102a2219450d030b02400240200d0d004100210d410021040c010b200d41057421052019210420152103034020042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200441206a2104200341206a2103200541606a22050d000b200d41057441606a41057641016a21040b200041b0036a201020082033201b10dc01200041c4036a2802002105200041c0036a280200210220002802bc032103024020002802b403450d0020002802b003102c0b02400240200d20046b20054105742205410575221f490d002004201f6a2125200d21240c010b2004201f6a22252004490d05200d410174221f2025201f20254b1b222441ffffff3f712024470d052024410574221f4100480d0502400240200d0d00201f102a21190c010b2019200d410574201f102e21190b2019450d030b201920044105746a2003200510db051a02402002450d002003102c0b0240200c450d002009200c4105746a211f024020260d0020084105742102200921080340200841086a2900002106200841106a290000210e20082900002111200041c0056a41186a200841186a290000370300200041c0056a41106a200e370300200041c0056a41086a2006370300200020113703c005200841206a210820022103201021040240024003402003450d01200041c0056a2004460d02200341606a21032004200041c0056a412010dd052105200441206a210420050d000c020b0b200041206a200041c0056a4280809aa6eaafe301420010bf012000290320200041206a41086a29030010a9010b2008201f470d000c020b0b200841057421202026410146211e2009210d0340200d41086a2900002106200d41106a290000210e200d2900002111200041c0056a41186a200d41186a290000370300200041c0056a41106a200e370300200041c0056a41086a2006370300200020113703c005410021030240201e0d0041002103202621050340200041b0036a41186a20132005410176220820036a220241306c6a220441186a290000370300200041b0036a41106a200441106a290000370300200041b0036a41086a200441086a290000370300200020042900003703b00320022003200041b0036a200041c0056a412010dd054101481b2103200520086b220541014b0d000b0b200d41206a210d200041b0036a41186a2013200341306c6a220441186a290000370300200041b0036a41106a200441106a290000370300200041b0036a41086a200441086a290000370300200020042900003703b00320202103201021040240200041b0036a200041c0056a412010dd05450d00024003402003450d01200041c0056a2004460d02200341606a21032004200041c0056a412010dd052105200441206a210420050d000c020b0b200041306a200041c0056a4280809aa6eaafe301420010bf012000290330200041306a41086a29030010a9010b200d201f470d000b0b0240200b450d002009102c0b02402025450d0020254105742103201921040340200441086a2900002106200441106a290000210e20042900002111200041b0036a41186a200441186a290000370300200041b0036a41106a200e370300200041b0036a41086a2006370300200020113703b003200041106a200041b0036a4280809aa6eaafe301420010bf012000290310200041106a41086a29030010a901200441206a2104200341606a22030d000b0b02402024450d002019102c0b200041b0036a41186a22084200370300200041b0036a41106a22024200370300200041b0036a41086a22034200370300200042003703b003200041b0046a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b004220637038803200020063703b003200441eae5c200ad4280808080f000841002220541086a290000370300200020052900003703b0042005102c20004188036a41086a20042903002206370300200020002903b004220e37038803202f200e370000202f41086a2006370000200041c0056a41086a2003290300370300200041c0056a41106a2002290300370300200041c0056a41186a2008290300370300200020002903b0033703c005200041003602b803200042013703b0032026200041b0036a1067024002402026450d002013210403402004200041b0036a109101200441286a2903002106200441206a290300210e0240024020002802b403220820002802b80322036b4110490d0020002802b00321050c010b200341106a22052003490d08200841017422032005200320054b1b22024100480d080240024020080d002002102a21050c010b20002802b00320082002102e21050b2005450d06200020023602b403200020053602b00320002802b8032103200221080b200520036a220220063700082002200e3700002000200341106a22033602b8032012200441306a2204470d000c020b0b20002802b803210320002802b403210820002802b00321050b200041c0056aad428080808080048422112003ad4220862005ad84100102402008450d002005102c0b200041b0036a41186a22084200370300200041b0036a41106a22024200370300200041b0036a41086a22034200370300200042003703b003200041b0046a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200020052900003703b0042005102c20032004290300370300200020002903b004220637038803200020063703b003200441a283c100ad42808080809001841002220541086a290000370300200020052900003703b0042005102c20004188036a41086a20042903002206370300200020002903b004220e37038803202f200e370000202f41086a2006370000200041c0056a41086a2003290300370300200041c0056a41106a2002290300370300200041c0056a41186a2008290300370300200020002903b0033703c005200041003602b803200042013703b003200a200041b0036a1067024002402027450d0020002802b803210320002802b403210820002802b00321050c010b2018210403402004200041b0036a109101200441286a2903002106200441206a290300210e0240024020002802b403220820002802b80322036b4110490d0020002802b00321050c010b200341106a22052003490d07200841017422032005200320054b1b22024100480d070240024020080d002002102a21050c010b20002802b00320082002102e21050b2005450d05200020023602b403200020053602b00320002802b8032103200221080b200520036a220220063700082002200e3700002000200341106a22033602b803200f200441306a2204470d000b0b20112003ad4220862005ad84100102402008450d002005102c0b2026ad42307e2206422088a70d012006a72204417f4c0d010240024020040d004108210d0c010b2004102a220d450d030b0240024020122013470d00410021050c010b2013202641306c6a210841002105200d2104201321030340200341086a2903002106200341106a290300210e200341186a290300211120032903002101200441286a200341286a290300370300200441206a200341206a290300370300200441186a2011370300200441106a200e370300200441086a200637030020042001370300200441306a2104200541016a21052008200341306a2203470d000b0b2005ad42307e2206422088a70d012006a72204417f4c0d010240024020040d004108210f0c010b2004102a220f450d030b410021080240200541306c2202450d0041002108200f2104200d21030340200341086a2903002106200341106a290300210e200341186a290300211120032903002101200441286a200341286a290300370300200441206a200341206a290300370300200441186a2011370300200441106a200e370300200441086a200637030020042001370300200441306a2104200841016a2108200341306a2103200241506a22020d000b0b200041c0036a2008360200200041bc036a2005360200200041b8036a200f360200200041003a00b403200041093a00b003200020002f00c0053b00b5032000200041c2056a2d00003a00b70341014100200041b0036a10920102402026450d00200d102c0b0240202a450d002015102c0b02402022450d00201a102c0b0240200a450d002010102c0b02402016450d002018102c0b02402036450d00201d102c0b02402023450d002013102c0b02402035450d002034102c0b200028029805210220002802900521040240024020002802940522050d00200421030c010b2005210820042103034020032802f80621032008417f6a22080d000b0340200420042f01064102746a41f8066a28020021042005417f6a22050d000b0b200041cc036a20042f0106360200200041c8036a4100360200200041c4036a2004360200200020023602d003200041003602c003200042003703b803200020033602b403200041003602b003200041b0036a10de0102402032450d002033102c0b02402030450d002031102c0b02402028450d002028412c6c2103202b41206a210403400240200441046a280200450d002004280200102c0b2004412c6a2104200341546a22030d000b0b41002113200041c0056a21022029450d00202b102c0b200041b0036a41186a22054200370300200041b0036a41106a22084200370300200041b0036a41086a22034200370300200042003703b003200041b0046a41086a220441e5d6c500ad428080808080028422061002220d41086a2900003703002000200d2900003703b004200d102c20032004290300370300200020002903b004220e370388032000200e3703b0032004419883c100ad4280808080a001841002220d41086a2900003703002000200d2900003703b004200d102c200820002903b004220e370300200041c0056a41086a220d2003290300370300200041c0056a41106a220f200e370300200041c0056a41186a220a20042903003703002000200e37038803200020002903b0033703c0052002ad4280808080800484220e1005200542003703002008420037030020034200370300200042003703b003200420061002221041086a290000370300200020102900003703b0042010102c20032004290300370300200020002903b004221137038803200020113703b003200441f5d6c500ad4280808080e0018422111002221041086a290000370300200020102900003703b0042010102c200520042903002201370300200d2003290300370300200f20002903b0042217370300200a20013703002000201737038803200020002903b0033703c005200041086a2002412010940120002802082102200028020c2110200542003703002008420037030020034200370300200042003703b003200420061002220841086a290000370300200020082900003703b0042008102c20032004290300370300200020002903b004220637038803200020063703b003200420111002220841086a290000370300200020082900003703b0042008102c200520042903002206370300200d2003290300370300200f20002903b0042211370300200a20063703002000201137038803200020002903b0033703c0052000201041016a410120021b3602b003200e200041b0036aad4280808080c0008410010240024020070d00200b450d042013410173450d010c040b2013450d030240202c450d002007102c0b02402028450d002028412c6c2103202b41206a210403400240200441046a280200450d002004280200102c0b2004412c6a2104200341546a22030d000b0b02402029450d00202b102c0b200b450d030b2009102c0c020b103a000b1033000b200041f0056a24000f0b1035000bbc0201017f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041003602000c010b200328021421022003200341106a41086a28020036022420032001360220200341c8006a200341206a108201024002402003280248450d0020002003290348370200200041086a200341c8006a41086a2802003602000c010b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341d0b0c2003602482003200341386a360258200341c4006a41c49ac500200341c8006a10391a2003350230422086200335022884100420004100360200200328022c450d002003280228102c0b2002450d002001102c0b200341e0006a24000bbc0201027f230041e0006b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022010d00200041003602000c010b200228021421032002200241106a41086a28020036022420022001360220200241c8006a200241206a107f024002402002280248450d0020002002290348370200200041086a200241c8006a41086a2802003602000c010b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241d0b0c2003602482002200241386a360258200241c4006a41c49ac500200241c8006a10391a2002350230422086200235022884100420004100360200200228022c450d002002280228102c0b2003450d002001102c0b200241e0006a24000bb30303047f017e017f230041d0006b22012400200141c0006a41086a220241e5d6c500ad42808080808002841002220341086a290000370300200120032900003703402003102c200141206a41086a2204200229030037030020012001290340370320200241a2fbc000ad4280808080d001841002220341086a290000370300200120032900003703402003102c200141306a41086a20022903002205370300200141086a2004290300370300200141186a20053703002001200129034022053703302001200129032037030020012005370310024002404101450d004120210402400240024002404120450d004120102a22020d010c050b411021044110102a2202450d04200141106a210320022001290300370000200241086a200141086a2903003700000c010b20022001290300370000200241086a200141086a290300370000200141106a21034120210641204110470d010b20022004200441017422064120200641204b1b2206102e2202450d020b20022003290000370010200241186a200341086a290000370000200041203602082000200636020420002002360200200141d0006a24000f0b103a000b1033000bd50302047f047e230041f0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022040d00200041003a00000c010b200341186a28020021052003280214210641002101200341003a006802400340024020052001470d000240200141ff0171450d00200341003a00680b4100210120034100360228200342013703202003410b3602442003200341086a3602402003200341206a36026c200341dc006a41013602002003420137024c200341d0b0c2003602482003200341c0006a360258200341ec006a41c49ac500200341c8006a10391a200335022842208620033502208410042003280224450d022003280220102c0c020b200341c8006a20016a200420016a2d00003a00002003200141016a22023a00682002210120024120470d000b200341206a41186a200341c8006a41186a2903002207370300200341206a41106a200341c8006a41106a2903002208370300200341206a41086a200341c8006a41086a290300220937030020032003290348220a370320200041196a2007370000200041116a2008370000200041096a20093700002000200a370001410121010b200020013a00002006450d002004102c0b200341f0006a24000bbe0703037f047e037f23002202210320024180036b41607122022400200141186a22042900002105200420022903f80137000020012900102106200120022903f00137001020012900082107200120022903e801370008200241003a00e00120012900002108200120022903e0013700002002200537039801200220063703900120022007370388012002200837038001200141206a2d00002104200241e0016a41176a22092005370000200241e0016a41106a220a200229009101370300200241e0016a41086a220b20022900890137030020022002290081013703e001024002402008a741ff01714101460d00200041003602200c010b200241186a41176a2009290000370000200241186a41106a200a290300370300200241186a41086a200b290300370300200220022903e001370318200220043a0037200241d0016a200241186a108402200241e0016a20022802d001220420022802d80110a002024020022d00ec014102470d00200241003602c802200242013703c002200241d0026a41146a410d360200200241dc026a410b360200200241103602ec02200241e5d6c5003602e8022002410b3602d402200241073602f402200241affbc0003602f0022002200241d0016a3602e0022002200241f0026a3602d8022002200241e8026a3602d0022002200241c0026a3602fc02200241386a41146a41033602002002420337023c200241a89cc5003602382002200241d0026a360248200241fc026a41c49ac500200241386a10391a20023502c80242208620023502c00284100420004100360220024020022802c402450d0020022802c002102c0b20022802d401450d0120022802d001102c200324000f0b20024180016a200241e0016a41d00010db051a024020022802d401450d002004102c0b200241d0026a41086a220420024180016a41086a28020036020020022002290380013703d002200241386a2002418c016a41c20010db051a200141206a200241f9006a2d00003a0000200141186a200241f1006a290000370000200141106a200241e9006a290000370000200141086a200241e1006a29000037000020012002290059370000200241e0016a41186a200241186a41186a2903002205370300200241e0016a41106a200241186a41106a2903002208370300200241e0016a41086a200241186a41086a2903002206370300200020022903182207370200200041086a2006370200200041106a2008370200200041186a2005370200200220073703e001200041206a20022903d002370200200041286a2004280200360200200324000f0b200324000bac1b03087f047e107f23004180056b22032400200341d0006a41186a200141186a290000370300200341d0006a41106a200141106a290000370300200341d0006a41086a200141086a290000370300200320012900003703500240024002402000280200220441d0e1c100460d00200028020421050c010b41002105200341c0016a410041e00210da051a200341b8016a22014100360200200341b0016a2206420037030020034190016a41186a420037030020034190016a41106a420037030020034190016a41086a42003703002003420037039001419403102a2204450d01200441003b010620044100360200200441086a200341c0016a41e00210db051a20044190036a200128020036020020044188036a200629030037020020044180036a200341a8016a290300370200200441f8026a200341a0016a290300370200200441f0026a20034190016a41086a29030037020020042003290390013702e80220004100360204200020043602000b024002400340200441086a2106200441066a210720042f010622084105742101410021090240024003402001450d01200341d0006a2006412010dd05220a450d02200141606a2101200941016a2109200641206a2106200a417f4a0d000b2009417f6a21080b2005450d022005417f6a2105200420084102746a4194036a28020021040c010b0b200420094102746a41e8026a20023602000c010b200341086a41186a200341d0006a41186a2201290300220b370300200341086a41106a200341d0006a41106a2206290300220c370300200341086a41086a200341d0006a41086a2209290300220d37030020032003290350220e3703082000200028020841016a3602082001200b3703002006200c3703002009200d3703002003200e37035002400240024020072f01002205410b490d00200341c0016a410041e00210da051a200341b8016a22014100360200200341b0016a2206420037030020034190016a41186a420037030020034190016a41106a420037030020034190016a41086a42003703002003420037039001419403102a220f450d04200f41003b0106200f4100360200200f41086a200341c0016a41e00210db052109200f4190036a2001280200360200200f4188036a2006290300370200200f4180036a20034190016a41186a290300370200200f41f8026a20034190016a41106a290300370200200f41f0026a20034190016a41086a290300370200200f2003290390013702e802200320042f00c8013b018c012003200441ca016a2d00003a008e01200441cb016a2800002110200441cf016a2800002111200441d3016a2800002112200441d7016a28000021132003200441e0016a29000037007d200320042900db0137037820042802800321142009200441e8016a20042f010641796a220141057410db052109200f41e8026a20044184036a200141027410db05210a200441063b0106200f20013b0106200320032f018c013b0174200320032d008e013a007620032003290378370390012003200329007d3700950120084107490d01200f41066a210720092008417a6a22054105746a2009200841796a22064105746a2209200141ffff037120066b41057410dc051a200941186a200341d0006a41186a290300370000200941106a200341d0006a41106a290300370000200941086a200341d0006a41086a29030037000020092003290350370000200a20054102746a2109200a20064102746a21010c020b200441086a220a200841016a22004105746a200a20084105746a220a200520086b41057410dc051a200a41186a2001290300370000200a41106a2006290300370000200a41086a2009290300370000200a2003290350370000200441e8026a220120004102746a200120084102746a220120042f010620086b41027410dc051a20012002360200200420042f010641016a3b01060c020b200441086a2201200841016a22064105746a200120084105746a220120072f010020086b41057410dc051a200141186a200341d0006a41186a290300370000200141106a200341d0006a41106a290300370000200141086a200341d0006a41086a29030037000020012003290350370000200441e8026a220920084102746a2101200920064102746a2109200821060b2009200120072f010020066b41027410dc051a20012002360200200720072f010041016a3b0100200341f0006a41026a221520032d007622013a00002003413c6a41026a221620013a000020032003290095013700452003200329039001370340200320032f017422013b01702003200329004537002d20032003290340370328200320013b013c024020042802002205450d0020042f01042107200341c0016a41027221170340201520162d00003a0000200320032f013c3b0170200320032903283703502003200329002d370055200741ffff0371210402400240024020052f01062201410b490d002017410041be0310da051a41c403102a220a450d06200a4100360200200a41046a200341c0016a41c00310db051a200320052f00c8013b018c012003200541ca016a2d00003a008e012003200541db016a2900003703782003200541e0016a29000037007d200541cb016a2800002118200541cf016a2800002119200541d3016a280000211a200541d7016a280000211b20054180036a280200211c200a41086a200541e8016a20052f0106220641796a220141057410db05211d200a41e8026a20054184036a200141027410db05211e200a4194036a200541b0036a2006417a6a220841027410db052102200541063b0106200a20013b010602402008450d00410021012002210603402006280200220920013b01042009200a360200200641046a21062008200141016a2201470d000b0b200320032d008e0122013a0076200320032f018c0122063b017420032003290378370390012003200329007d37009501200341c0006a41026a220820013a0000200320063b014020032003290390013703c00120032003290095013700c501200741ffff037122064107490d01201d2004417a6a22094105746a201d200441796a22014105746a2206200a2f010620016b41057410dc051a200641186a20032900553700002006201336000f2006201236000b2006201136000720062010360003200641026a20152d00003a0000200620032f01703b000020062003290350370013201e200941027422066a201e20014102746a2207200a2f0106221020016b41027410dc051a20072014360200200a201041016a22073b01062004410274221020026a416c6a200220066a2206200741ffff0371220420096b41027410dc051a2006200f36020020042009490d02200a20106a41fc026a2106034020062802002209200141016a22013b01042009200a360200200641046a210620012004490d000c030b0b200541086a2206200441016a22094105746a200620044105746a2206200120046b41057410dc051a200641186a20032900553700002006201336000f2006201236000b2006201136000720062010360003200641026a200341f0006a41026a2d00003a0000200620032f01703b000020062003290350370013200541e8026a2201200941027422066a20012004410274220a6a220120052f0106220820046b41027410dc051a200120143602002005200841016a22013b0106200a20054194036a22046a41086a200420066a2206200141ffff0371220a20096b41027410dc051a2006200f360200200741ffff0371200a4f0d0420052009417f6a22014102746a4198036a2106034020062802002209200141016a22013b010420092005360200200641046a21062001200a490d000c050b0b200541086a2201200441016a22074105746a200120044105746a220120052f010620046b41057410dc051a200141186a20032900553700002001201336000f2001201236000b2001201136000720012010360003200141026a20152d00003a0000200120032f01703b000020012003290350370013200541e8026a2209200741027422026a2009200441027422016a220920052f0106221020046b41027410dc051a200920143602002005201041016a22093b0106200120054194036a22106a41086a201020026a2202200941ffff0371220920076b41027410dc051a2002200f360200200620094f0d00200520016a4198036a2101034020012802002206200441016a22043b010420062005360200200141046a210120092004470d000b0b201620082d00003a0000200320032f01403b013c200320032903c001370328200320032900c50137002d0240200528020022010d0020182110201b2113201a211220192111200a210f201c21140c020b20052f0104210720182110201b2113201a21122019211120012105201c2114200a210f0c000b0b200341c0016a410272410041be0310da051a41c403102a2201450d0120014100360200200141046a200341c0016a41c00310db051a20012000280200220636029403200020013602002000200028020441016a360204200641003b010420062001360200200120012f010622094105746a220641086a20032f013c3b00002006410a6a2003413c6a41026a2d00003a0000200641176a2013360000200641136a20123600002006410f6a20113600002006410b6a20103600002006411b6a2003290328370000200641206a200329002d37000020014194036a200941016a22064102746a200f360200200120094102746a41e8026a2014360200200120063b0106200f20063b0104200f20013602000b20034180056a24000f0b1033000bfa0202057f027e230041e0006b22022400200241c0006a41086a220341e5d6c500ad42808080808002841002220441086a290000370300200220042900003703402004102c200241206a41086a2205200329030037030020022002290340370320200341fdfbc000ad4280808080f000841002220441086a290000370300200220042900003703402004102c200241306a41086a2206200329030037030020022002290340370330200241c0006a2001109f01024041c000102a22040d001033000b200420022903203700002004200229033037001020042002290040370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241c0006a41106a290000370000200441386a200241c0006a41186a290000370000200241086a200441c000109e01200241086a41106a290300210720022903102108200228020821032004102c20002007420020031b37030820002008420020031b370300200241e0006a24000b852d07017f017e017f027e017f027e187f23004180036b2207240002400240024002402001200284500d002003200484500d004201210820074198016a200320012003200156200420025620042002511b22091b220a2004200220091b220b20054201200542015620064200522006501b220c1b220520064200200c1b220610e10520074188016a200729039801220d20074198016a41086a290300220e2005200610e0052002200420091b21022001200320091b2104200a20072903880185200b20074188016a41086a290300858450450d01200d210a200e210b420021060c020b20004100360200200041106a4200370300200041086a42003703000c020b200741f8006a200420022005200610e105200741e8006a20072903782201200741f8006a41086a29030022032005200610e0054200200620042007290368852002200741e8006a41086a29030085845022091b21064201200520091b21082003200220091b21022001200420091b21040b200741386a200b42002004420010e005200741c8006a20024200200a420010e005200741d8006a200a42002004420010e005024002400240024002400240024002400240024002400240024002400240200b420052200242005271200729034042005272200729035042005272200741d8006a41086a2903002201200729033820072903487c7c2203200154724101470d004110102a2209450d0d2009200a3e020c2009200a4220883e02082009200b3e02042009200b4220883e020020074284808080c00037029c02200720093602980220074198026a10bd05200741a8016a41086a20072802a00236020020072007290398023703a8014110102a2209450d0d200920043e020c200920044220883e0208200920023e0204200920024220883e020020074284808080c00037029c02200720093602980220074198026a10bd05200741b8016a41086a20072802a00236020020072007290398023703b8014110102a2209450d0d20092008a7220f36020c200920084220883e0208200920063e0204200920064220883e020020074284808080c00037029c02200720093602980220074198026a10bd0520072802a0022110200728029c0221112007280298022112200741f0026a41086a200741b8016a41086a280200360200200720072903b8013703f00220074198026a41086a200741a8016a41086a280200360200200720072903a80137039802200741c8016a20074198026a200741f0026a10bf05024020072802f402450d0020072802f002102c0b200741c8016a10bd0520104101460d0120072802cc01211320072802c80121142010450d0a2012280200450d0a024020072802d0012215450d002014280200450d0b201520104d0d0b200720103602d401201520106b221641016a22174101201741014b1b221841ffffffff03712018470d0320184102742209417f4c0d030240024020090d00410421190c010b200910302219450d0f0b201041ffffffff03712010470d032010410274221a417f4c0d0302400240201a0d004104211b0c010b201a1030221b450d0f0b410221094101210f2012280200220c67221c211d0240200c41ffffffff034b0d0041022109201c210c4101210f034020094101200c4101711b200f6c210f200c41034b211e200920096c2109200c410176221d210c201e0d000b0b200720153602f802200720133602f402200720143602f0024104102a220c450d0e200c20094101201d4101461b200f6c220f360200200742818080801037029c022007200c36029802200741d8016a200741f0026a20074198026a10bf05200c102c02400240201a0d00410421090c010b201a102a2209450d0f0b20092012201041027410db052109200720103602f802200720103602f402200720093602f0024104102a2209450d0e2009200f360200200742818080801037029c022007200936029802200741e8016a200741f0026a20074198026a10bf052009102c0240024020072802d40120176a220920072802e001220c4d0d00024002402009200c6b22090d004104210f410021090c010b200941ffffffff03712009470d022009410274220f4100480d02200f102a220f450d11200f4100200941027410da051a0b20072802d801211d2009211e0240200c450d002009200c6a221e2009490d0220094101742214201e2014201e4b1b221e41ffffffff0371201e470d02201e41027422144100480d020240024020090d002014102a210f0c010b200f20094102742014102e210f0b200f450d110b200f20094102746a201d200c41027410db051a2009200c6a2109024020072802dc01450d00201d102c0b200720093602e0012007201e3602dc012007200f3602d8010b200741e8016a10bd050240024002400240024002400240024002400240034020072016221f3602f401024020072802e001220920072802d401220c201f6a220f417f736a221e2009490d0041d087c600201e20091038000b0240024002400240024002400240024002400240024002400240024020092009200f6b220f4d0d0020072802f00122092009200c6b220c4d0d0120072802e801200c4102746a35020022024200510d02201f201f4100476b211620072802d8012209201e4102746a35020021012009200f4102746a3502002104200741003602f80120072004200142208684200280220137038002200741003602880220072004200120027e7d42ffffffff0f83370390022007200741f4016a3602ac022007200741d8016a3602a8022007200741d4016a3602a4022007200741e8016a3602a002200720074188026a36029c022007200741f8016a3602980220074198026a10c0051a034020072802880241016a41004c0d04024020072903900242ffffffff0f560d0020074198026a10c0050d010b0b2007290380022102200720072802d40120072802f40122096a3602f402200720093602f0022007200741d8016a3602fc02200741023a00f802200741b0026a200741f0026a10c30520072802f001220941ffffffff03712009470d1d2009410274220c417f4c0d1d20072802e801210f02400240200c0d004104211e0c010b200c102a221e450d290b201e200f200c10db05210c200720093602e802200720093602e4022007200c3602e0024108102a2209450d2820092002a72220360204200920024220883e020020074282808080203702f402200720093602f002200741c0026a200741e0026a200741f0026a10bf052009102c20072802b802222120072802c8022222202120224b1b22144101201441014b1b220c41ffffffff0371200c470d1d200c410274220f417f4c0d1d20072802b402212320072802b002212402400240200f0d00410421250c010b200f10302225450d290b2014450d062022417f6a221a20224b211520072802c00221262021417f6a221720214b0d04200c417f6a21092025200f6a417c6a211d4100210f4200210203404100211e024020212017200f6b22134d0d004100211e201320174b0d00202420134102746a280200211e0b201ead21044100211e024020150d002022201a200f6b22134d0d002013201a4b0d00202620134102746a280200211e0b024002402004201ead22037d22012004560d00200120027d220a2001560d00200a42ffffffff0f832104420021020c010b20044280808080108420027d20037d2104420121020b200c20094d0d09201d20043e0200201d417c6a211d2009417f6a2109200f41016a220f2014490d000c060b0b41d087c600200f20091038000b41d087c600200c20091038000b419089c600411941b888c6001036000b41c689c6004118200741f0026a41e089c600103b000b200c417f6a21092025200f6a417c6a211e4100211d4200210203404100210f024020150d004100210f2022201a201d6b22134d0d004100210f2013201a4b0d00202620134102746a280200210f0b024002404200200fad22017d22044200520d00200420027d22032004560d00200342ffffffff0f832104420021020c010b428080808010200220017c7d2104420121020b200c20094d0d04201e20043e0200201e417c6a211e2009417f6a2109201d41016a221d2014490d000b0b41012113200250450d010b410021130b02402023450d002024102c0b20072802d401221e20072802f401220f6a2215201e490d05200f20154f0d01200f417f7321090340200c200c200f6a20096a221d4d0d03200920072802e00122146a220f20094f0d0420072802d801200f4102746a2025201d4102746a2802003602002009417f6a210920072802f401210f201e417f6a221e0d000c050b0b41a888c6002009200c1038000b201e450d020c030b41d087c60020222021202220214b1b22074101200741014b1b200f6a20096a200c1038000b41a888c600200f20141038000b200c200c2015417f7322096a200f6a220f4d0d0220072802e001220c20096a2209200c4f0d0320072802d80120094102746a2025200f4102746a28020036020020072802f401210f0b2018200f417f736a220920184f0d03201920094102746a202036020002402013450d00201820072802f401417f736a220920184f0d05201920094102746a22092009280200417f6a36020020072802f401210920072802d401210c200741023a00f8022007200c20096a3602f402200720093602f0022007200741d8016a3602fc02200741d0026a200741f0026a10c30520072802f001220941ffffffff03712009470d102009410274220c417f4c0d1020072802e801210f02400240200c0d004104211e0c010b200c102a221e450d1c0b201e200f200c10db05210c200720093602f802200720093602f4022007200c3602f002200741e0026a200741f0026a200741d0026a10be05024020072802d401220920072802f40122146a220c2009490d00024002402014200c4f0d00200c417f73210920072802e002211320072802e802210f2014211e0340200f200f201e6a20096a221e4d0d0a200920072802e00122156a221d20094f0d0b20072802d801201d4102746a2013201e4102746a280200360200200941016a210920072802f401211e2014200c417f6a220c490d000c020b0b20090d0120072802e802210f2014211e0b201e2014417f7322096a220c200f6a221e200c4f0d0920072802e001220c20096a2209200c4f0d0a20072802d80120094102746a20072802e002201e4102746a2802003602000b024020072802e402450d0020072802e002102c0b20072802d402450d0020072802d002102c0b2025102c024020072802c402450d0020072802c002102c0b201f0d000b0240201c450d004101210920072802d401220c4101460d134100200c6b2114201c411f7121134100201c6b411f7121152010410274201b6a417c6a210c417f210903400240200920072802e001221e6a220f2009490d0041d087c600200f201e1038000b201e200f417f6a221d4d0d0a201020096a221e20104f0d0b200c20072802d801221e201d4102746a280200201574201e200f4102746a28020020137672360200200c417c6a210c20142009417f6a2209460d130c000b0b20072802e001211020072802dc01210f20072802d801211e201b102c410021090c130b41d087c600200f200c1038000b41a888c6002009200c1038000b41a888c600200920181038000b41d087c600200920181038000b41d087c600201e200f1038000b41a888c600201d20151038000b41d087c600201e200f1038000b41a888c6002009200c1038000b41d087c600200f417f6a201e1038000b41a888c600201e20101038000b1035000b41d087c600410041001038000b200741286a200729035820032008200610e10520004100360200200041106a200741286a41086a290300370300200041086a20072903283703000c0e0b20074198026a41086a200741c8016a41086a280200221d360200200720072903c80137039802201d4101201d41014b1b221e41ffffffff0371201e470d00201e4102742209417f4c0d000240024020090d004104211a0c010b20091030221a450d0c0b201d450d02201d417f6a2114201a201e201d6b22134102746a210c200f4101200f41014b1bad21024200210441002109200728029802210f0340201e201320096a22154d0d02200c2004422086200f35020084220420028022013e020020142009460d03200c41046a210c200f41046a210f2004200120027e7d2104201d200941016a22094b0d000b41d087c6002009201d1038000b103a000b41a888c6002015201e1038000b2007201e3602f8022007201e3602f4022007201a3602f002200728029c02450d07200728029802102c0c070b20072802d40121090b20072802e001220c200c20096b220f4d0d012010201020096b22094d0d02201b20094102746a20072802d801200f4102746a280200201c411f7176360200410121092010210f201b211e0b024020072802ec01450d0020072802e801102c0b2009450d0320072802dc01450d0320072802d801102c0c030b41d087c600200f200c1038000b41a888c600200920101038000b4100211902402013450d002014102c0b0b4104102a2209450d01200941003602004104102a220c450d01200c41003602004101211d0240024020190d002009211941012118200c211e4101210f410121100c010b2009102c200c102c0b2007201836028002200720183602fc01200720193602f801200720103602a0022007200f36029c022007201e3602980220074198026a10bd05420021020240024020072802a00222094105744180014d0d00421d21040c010b4100211d024020090d00420021040c010b200728029802220c200941027422096a417c6a220f280200211e0240200c200f470d00201ead21040c010b200c41786a210f201ead2104200741206a211e4120210c420021020340200741186a200f20096a3502004200200c41e0007110de05201e29030020027c2007290318220220047c2204200254ad7c2102200c41206a210c2009417c6a22094104470d000b0b0240200728029c02450d00200728029802102c0b201d0d020240200420084201882006423f8684562002200642018822045620022004511b450d0020074188026a41086a200741f8016a41086a280200360200200720072903f801370388024110102a2209450d0220094280808080103702082009420037020020074284808080c00037029c02200720093602980220074198026a10bd05200741f0026a41086a20072802a00236020020072007290398023703f002200741f8016a20074188026a200741f0026a10be0520072802f402450d0020072802f002102c0b200741f0026a41086a200741f8016a41086a280200360200200720072903f8013703f0020b200741f0026a10bd0520074198026a41086a2209200741f0026a41086a280200360200200720072903f0023703980220074198026a10bd054200210202400240200928020022094105744180014d0d00421d21044101211d0c010b4100211d024020090d00420021040c010b200728029802220c200941027422096a417c6a220f280200211e0240200c200f470d00201ead21040c010b200c41786a210f201ead2104200741106a211e4120210c420021020340200741086a200f20096a3502004200200c41e0007110de05201e29030020027c2007290308220220047c2204200254ad7c2102200c41206a210c2009417c6a22094104470d000b0b0240200728029c02450d00200728029802102c0b02400240201d0d00200041106a2002370300200041086a2004370300410021090c010b200041d08ac600360204200041086a4119360200410121090b200020093602002011450d022012102c0c020b1033000b200720043e029c02200741a989c6003602980241908ac600412f20074198026a41c08ac600103b000b20074180036a24000bd30201037f230041d0006b220824000240024002402002200685200320078584500d00200220038450450d01410121090c020b417f20002004852001200585844200522000200454200120055420012005511b1b21090c010b0240200620078450450d0041ff0121090c010b200841206a2000200110c405200841306a2006200710c405200841c0006a41086a2209200841206a41086a220a280200360200200820082903203703402008200841c0006a200841306a10bf0502402008280234450d002008280230102c0b200841206a2004200510c405200841306a2002200310c4052009200a28020036020020082008290320370340200841106a200841c0006a200841306a10bf0502402008280234450d002008280230102c0b2008200841106a10c105210902402008280214450d002008280210102c0b2008280204450d002008280200102c0b200841d0006a240020090beb0203017f047e017f230041d0006b2202240002400240200029031022032001290310220485200041186a2903002205200141186a29030022068584500d00200241206a2000290300200041086a29030010c405200241306a2004200610c405200241c0006a41086a2200200241206a41086a2207280200360200200220022903203703402002200241c0006a200241306a10bf0502402002280234450d002002280230102c0b200241206a2001290300200141086a29030010c405200241306a2003200510c4052000200728020036020020022002290320370340200241106a200241c0006a200241306a10bf0502402002280234450d002002280230102c0b2002200241106a10c105210002402002280214450d002002280210102c0b200041ff0171210002402002280204450d002002280200102c0b20004521000c010b2000290300200129030085200041086a290300200141086a29030085845021000b200241d0006a240020000b8b0303017f017e027f02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d00410021034100210103402002417f6a210202400240200120002f01064f0d00200141016a21010c010b02400240200028020022010d002003ad210441002105410021010c010b20003301044220862003ad842104410121050b2000102c2004a72103024002402004422088a7220620012f01064f0d00200121000c010b034002400240200128020022000d002003ad2104410021000c010b200541016a210520013301044220862003ad8421040b2001102c2004a72103200021012004422088a7220620002f01064f0d000b0b200641027420006a4198036a280200210002402005417f6a2201450d00034020002802940321002001417f6a22010d000b0b410021010b20020d000b0b0240200041d0e1c100460d00200028020021012000102c2001450d00200128020021002001102c2000450d00024020002802002201450d0003402000102c2001210020012802002203210120030d000b0b2000102c0b0bf62803087f057e277f230041d00c6b22042400200441e0016a41186a200241186a290000370300200441e0016a41106a200241106a290000370300200441e0016a41086a200241086a290000370300200420022900003703e0010240024002402001280200220541d0e1c100460d00200128020421060c010b41002106200441c0026a410041e00210da051a200441a8056a410041900410da051a41f806102a2205450d01200541003b010620054100360200200541086a200441c0026a41e00210db051a200541e8026a200441a8056a41900410db051a20014100360204200120053602000b024002400340200541086a2107200541066a210820052f0106220941057421024100210a0240024003402002450d01200441e0016a2007412010dd05220b450d02200241606a2102200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200520094102746a41f8066a28020021050c010b0b2005200a41306c6a22024180036a2207290300210c2003290300210d2003290308210e2003290310210f2007200341186a290300370300200241f8026a220729030021102007200f370300200241f0026a2207290300210f2007200e370300200241e8026a2207290300210e2007200d370300200441a8056a41086a220720024190036a220a290300370300200420024188036a22022903003703a80520022003290320370300200a200341286a290300370300200441c0026a41086a22022007290300370300200420042903a805220d3703c002200041186a200c370300200020103703102000200f3703082000200e3703002000200d370320200041286a20022903003703000c010b200441186a2202200441e0016a41186a2207290300370300200441106a200441e0016a41106a220a290300220c370300200441086a200441e0016a41086a220b290300220d370300200420042903e001220e3703002001200128020841016a360208200441f8006a41106a2206200c370300200441f8006a41086a2211200d370300200441f8006a41186a221220022903003703002004200e370378200441e0016a41286a2213200341286a290300370300200441e0016a41206a2214200341206a2903003703002007200341186a290300370300200a200341106a290300370300200b200341086a290300370300200420032903003703e00102400240024020082f01002203410b490d00200441c0026a410041e00210da051a200441a8056a410041900410da051a41f806102a2215450d04201541003b010620154100360200201541086a200441c0026a41e00210db052107201541e8026a200441a8056a41900410db05210a200441a8056a41086a220b20054190056a290300370300200441a8056a41106a220320054198056a290300370300200441a8056a41186a2206200541a0056a290300370300200441a8056a41206a2211200541a8056a290300370300200441a8056a41286a2212200541b0056a290300370300200420052900db013703a8022004200541e0016a2900003700ad0220042005290388053703a805200420052f00c8013b01bc022004200541ca016a2d00003a00be02200541cb016a2800002116200541cf016a2800002117200541d3016a2800002118200541d7016a28000021192007200541e8016a20052f010641796a220241057410db052107200a200541b8056a200241306c10db05210a200541063b0106201520023b0106200420042f01bc023b01a402200420042d00be023a00a602200420042903a80237039002200420042900ad0237009502200441c0026a41286a2012290300370300200441c0026a41206a2011290300370300200441c0026a41186a2006290300370300200441c0026a41106a2003290300370300200441c0026a41086a200b290300370300200420042903a8053703c0020240024020094107490d00200941057420076a41c07e6a2007200941796a220b4105746a2207200241ffff0371200b6b41057410dc051a200741186a200441f8006a41186a290300370000200741106a200441f8006a41106a290300370000200741086a200441f8006a41086a29030037000020072004290378370000200941306c200a6a220241e07d6a200241b07d6a2202201541066a22082f0100200b6b41306c10dc051a200241286a200441e0016a41286a290300370300200241206a200441e0016a41206a290300370300200241186a200441e0016a41186a290300370300200241106a200441e0016a41106a290300370300200241086a200441e0016a41086a290300370300200220042903e0013703000c010b200541086a20094105746a220241206a200220082f010020096b41057410dc051a200241186a200441f8006a41186a290300370000200241106a200441f8006a41106a290300370000200241086a200441f8006a41086a29030037000020022004290378370000200541e8026a200941306c6a220241306a200220082f010020096b41306c10dc051a200241286a200441e0016a41286a290300370300200241206a200441e0016a41206a290300370300200241186a200441e0016a41186a290300370300200241106a200441e0016a41106a290300370300200241086a200441e0016a41086a290300370300200220042903e0013703000b200820082f010041016a3b0100200441c8016a41026a220220042d00a6023a000020044198016a41086a221a200441c0026a41086a221b29030037030020044198016a41106a221c200441c0026a41106a221d29030037030020044198016a41186a221e200441c0026a41186a221f29030037030020044198016a41206a2220200441c0026a41206a222129030037030020044198016a41286a2222200441c0026a41286a2223290300370300200420042f01a4023b01c8012004200429039002370368200420042900950237006d200420042903c00237039801200441386a41286a22242022290300370300200441386a41206a22252020290300370300200441386a41186a2226201e290300370300200441386a41106a2227201c290300370300200441386a41086a2228201a290300370300200441346a41026a222920022d00003a00002004200429039801370338200420042903683703202004200429006d370025200420042f01c8013b013420052802002203450d0120052f01042114200441a8056a410272212a0340200441dc016a41026a222b20292d00003a0000200420042f01343b01dc01200420042903203703682004200429002537006d200441e0016a41286a222c2024290300370300200441e0016a41206a222d2025290300370300200441e0016a41186a222e2026290300370300200441e0016a41106a222f2027290300370300200441e0016a41086a22302028290300370300200420042903383703e001201441ffff0371210502400240024020032f01062202410b490d00202a410041a20710da051a41a807102a220b450d08200b4100360200200b41046a200441a8056a41a40710db051a200420032f00c8013b01bc022004200341ca016a2d00003a00be02200420032900db013703a8022004200341e0016a2900003700ad02200341cb016a2800002131200341cf016a2800002132200341d3016a2800002133200341d7016a2800002134200441a8056a41286a2209200341b0056a290300370300200441a8056a41206a2208200341a8056a290300370300200441a8056a41186a2211200341a0056a290300370300200441a8056a41106a221220034198056a290300370300200441a8056a41086a221320034190056a29030037030020042003290388053703a805200b41086a200341e8016a20032f0106220741796a220241057410db052135200b41e8026a200341b8056a200241306c10db052136200b41f8066a20034194076a2007417a6a220641027410db052137200341063b0106200b20023b010602402006450d00410021022037210703402007280200220a20023b0104200a200b360200200741046a21072006200241016a2202470d000b0b2023200929030037030020212008290300370300201f2011290300370300201d2012290300370300201b2013290300370300200420042903a8053703c002200420042f01bc023b01a402200420042d00be023a00a602200420042903a80237039002200420042900ad0237009502200441a4056a41026a220620042d00a6023a0000200420042f01a4023b01a4052004200429039002370378200420042900950237007d20092023290300370300200820212903003703002011201f2903003703002012201d2903003703002013201b290300370300200420042903c0023703a805201441ffff037122074107490d0120352005417a6a220a4105746a2035200541796a22024105746a2207200b2f010620026b41057410dc051a200741186a200429006d3700002007201936000f2007201836000b2007201736000720072016360003200741026a202b2d00003a0000200720042f01dc013b000020072004290368370013200541306c20366a220741e07d6a200741b07d6a2207200b2f0106221420026b41306c10dc051a200741286a202c290300370300200741206a202d290300370300200741186a202e290300370300200741106a202f290300370300200741086a2030290300370300200720042903e001370300200b201441016a22073b01062005410274221620376a416c6a2037200a4102746a2214200741ffff03712205200a6b41027410dc051a201420153602002005200a490d02200b20166a41e0066a210703402007280200220a200241016a22023b0104200a200b360200200741046a210720022005490d000c030b0b200341086a2207200541016a220a4105746a200720054105746a2207200220056b220b41057410dc051a2007201936000f2007201836000b2007201736000720072016360003200741026a200441dc016a41026a2d00003a0000200720042f01dc013b000020072004290368370013200741186a200429006d3700002003200541306c6a22074198036a200741e8026a2206200b41306c10dc051a20074190036a20044188026a29030037030020074188036a20044180026a29030037030020074180036a200441e0016a41186a290300370300200741f8026a200441f0016a290300370300200741f0026a200441e0016a41086a290300370300200620042903e0013703002003200241016a22023b01062005410274200341f8066a22076a41086a2007200a4102746a2207200241ffff0371200a6b41027410dc051a20072015360200201441ffff037120032f010622024f0d052015200a3b010420152003360200200a20024f0d052002417f6a210b2003200a417f6a22024102746a4180076a210703402007280200220a200241026a3b0104200a2003360200200741046a2107200b200241016a2202470d000c060b0b200341086a2202200541016a220a4105746a200220054105746a220220032f0106221420056b223741057410dc051a2002201936000f2002201836000b2002201736000720022016360003200241026a202b2d00003a0000200220042f01dc013b000020022004290368370013200241186a200429006d370000200341e8026a200541306c6a220241306a2002203741306c10dc051a200241286a202c290300370300200241206a202d290300370300200241186a202e290300370300200241106a202f290300370300200241086a2030290300370300200220042903e0013703002003201441016a22023b010620054102742237200341f8066a22146a41086a2014200a4102746a2214200241ffff0371200a6b41027410dc051a20142015360200200720032f0106220a4f0d00200320376a41fc066a2102034020022802002207200541016a22053b010420072003360200200241046a2102200a2005470d000b0b200441d8016a41026a220220062d00003a0000201a2013290300370300201c2012290300370300201e20112903003703002020200829030037030020222009290300370300200420042f01a4053b01d801200420042903783703c8012004200429007d3700cd01200420042903a8053703980120242022290300370300202520202903003703002026201e2903003703002027201c2903003703002028201a290300370300202920022d00003a00002004200429039801370338200420042903c801370320200420042900cd01370025200420042f01d8013b01340240200328020022020d0020312116203421192033211820322117200b21150c030b20032f010421142031211620342119203321182032211720022103200b21150c000b0b200520094105746a220241286a200241086a2201200320096b41057410dc051a200241206a2012290300370000200241186a2006290300370000200241106a2011290300370000200120042903783700002005200941306c6a22024198036a200241e8026a220320052f010620096b41306c10dc051a20024190036a201329030037030020024188036a201429030037030020024180036a2007290300370300200241f8026a200a290300370300200241f0026a200b290300370300200320042903e001370300200520052f010641016a3b01060c010b200441a8056a410272410041a20710da051a41a807102a2202450d0220024100360200200241046a200441a8056a41a40710db051a2002200128020022073602f806200120023602002001200128020441016a360204200741003b010420072002360200200220022f0106220a4105746a220741086a20042f01343b00002007410a6a200441346a41026a2d00003a0000200741176a2019360000200741136a20183600002007410f6a20173600002007410b6a20163600002007411b6a2004290320370000200741206a20042900253700002002200a41306c6a220741e8026a2004290338370300200741f0026a200441386a41086a290300370300200741f8026a200441c8006a29030037030020074180036a200441d0006a29030037030020074188036a200441386a41206a29030037030020074190036a200441e0006a290300370300200241f8066a200a41016a22074102746a2015360200200220073b010620152002360200201520073b01040b200041003602200b200441d00c6a24000f0b1033000bac0901157f230041206b220524002003410020041b21062001410020021b2107200341206a200320041b2108200141206a200120021b2109200120024105746a210a200320044105746a210b4100210c4100210d4101210e4100210f410021104101211102400340200c4101742112200c41057421130240024002400340024020060d0020082114200e2115200d2116200c21020c020b2006210120082103200e2115200d2116200c2102201321042012211702400340024002402007450d0020012007460d0320012007412010dd052214450d032014417f4c0d01200321082015210e2016210d2002210c200121060c060b200541186a2203200641186a290000370300200541106a2202200641106a290000370300200541086a2207200641086a290000370300200520062900003703000240200c200d470d00200c41016a2201200c490d09200c41017422042001200420014b1b220d41ffffff3f71200d470d09200d41057422014100480d0902400240200c0d002001102a210e0c010b200e200c4105742001102e210e0b200e450d070b200e200c4105746a22012005290300370000200141186a2003290300370000200141106a2002290300370000200141086a200729030037000041002107410020082008200b4622011b2106201241026a2112201341206a2113200c41016a210c2008200841206a20011b21080c030b200541186a2214200141186a290000370300200541106a2218200141106a290000370300200541086a2219200141086a29000037030020052001290000370300024020022016470d00200241016a22012002490d0820172001201720014b1b221641ffffff3f712016470d08201641057422014100480d080240024020020d002001102a21150c010b201520042001102e21150b2015450d060b201520046a22012005290300370000200141186a2014290300370000200141106a2018290300370000200141086a2019290300370000410020032003200b4622141b2101201741026a2117200441206a2104200241016a21022003200341206a20141b221421032001450d030c000b0b0b2015210e2016210d2002210c2003200341206a2003200b4622011b2108410020092009200a4622021b21074100200320011b21062009200941206a20021b21090c030b41002106024020070d002000201536020c2000200f3602082000201036020420002011360200200041146a2002360200200041106a2016360200200541206a24000f0b201421082015210e2016210d2002210c0b200541186a2203200741186a290000370300200541106a2202200741106a290000370300200541086a2204200741086a290000370300200520072900003703000240200f2010470d00200f41016a2201200f490d03200f41017422072001200720014b1b221041ffffff3f712010470d03201041057422014100480d0302400240200f0d002001102a21110c010b2011200f4105742001102e21110b2011450d010b2011200f4105746a22012005290300370000200141186a2003290300370000200141106a2002290300370000200141086a2004290300370000410020092009200a4622011b2107200f41016a210f2009200941206a20011b21090c010b0b1033000b1035000b901008087f027e047f017e057f027e017f057e230022042105200441a0016b41607122042400024002400240200141ffffff3f712001470d0020014105742206417f4c0d000240024020060d00410121070c010b2006102a2207450d020b410021084100210602402001450d002001410574210820072106034020062000290000370000200641186a200041186a290000370000200641106a200041106a290000370000200641086a200041086a290000370000200641206a2106200041206a2100200841606a22080d000b200141057441606a41057641016a2106200121080b200420063602102004200836020c2004200736020820072006410041202006676b108903200441e0006a41186a22094200370300200441e0006a41106a220a4200370300200441e0006a41086a220b420037030020044200370360200441286a41086a220841fde7c200ad4280808080b00284220c1002220041086a290000370300200420002900003703282000102c200b200829030037030020042004290328370360200841e1e5c200ad42808080809001841002220041086a290000370300200420002900003703282000102c200a2004290328220d370300200441c0006a41086a220e200b290300370300200441c0006a41106a220f200d370300200441c0006a41186a221020082903003703002004200d3703900120042004290360370340200441e0006a200441c0006a412010d00120042802602200410120001b21112004290264420020001b2212422088a72200450d0220004105742113200441e0006a4114722114200441e0006a4108722115200441c0006a410c722116200441e0006a410c6a2117201121060340200641086a290000210d200641106a2900002118200629000021192009200641186a290000370300200a2018370300200b200d370300200420193703602008200c1002220041086a290000370300200420002900003703282000102c200441186a41086a2201200829030037030020042004290328370318200841f1e5c200ad4280808080e000841002220041086a290000370300200420002900003703282000102c20044190016a41086a220720082903003703002004200429032837039001200441c0006a200441e0006a109f0141c000102a2200450d0220002004290318370000200020042903900137001020002004290040370020200041086a2001290300370000200041186a2007290300370000200041286a200e290000370000200041306a200f290000370000200041386a2010290000370000200441e0006a200041c00010e5032008201741086a290200370300200441286a41106a221a201741106a28020036020020042017290200370328024020042802682201450d002004290360210d20162004290328370200201641086a2008290300370200201641106a201a2802003602002004200d3703400b20042001360248200441003602682004290358211920042004290378221b3703582004290350211c20042004290370221d3703502004290340211e2004200429036022183703402004290348210d20042004290368221f370348201fa7210102400240200da7221a0d00201f210d201d211c201b21190c010b2004201e3703602004200d3703682004201c370370200420193703782004201a201ca74105746a3602342004201a3602302004200d422088a736022c2004201a3602282004200441086a36023820044190016a200441286a108501201541086a200728020036020020152004290390013702002004201c422088a7221a2019422088a74105746a3602342004201a36023020042019a736022c2004201a3602282004200441086a36023820044190016a200441286a108501201441086a200728020036020020142004290390013702002004290368210d20042903602118200429037821192004290370211c02402001450d00201ba721070240201f422088a7450d002001102c0b2007450d00201d422088a7102c0b200420183703402004200d3703482004201c37035020042019370358200da721010b200420183703602004200d3703682004201c370370200da72107200420193703780240024020010d002000ad428080808080088410050c010b200441c00036022c20042000360228200441e0006a200441286a10fd030b02402007450d002019a721010240200d422088a7450d002007102c0b2001450d00201c422088a7102c0b200641206a21062000102c201341606a22130d000c030b0b103a000b1033000b02402012a7450d002011102c0b200441c0006a41186a4200370300200441c0006a41106a22014200370300200441c0006a41086a2206420037030020044200370340200441286a41086a220041fde7c200ad4280808080b002841002220841086a290000370300200420082900003703282008102c2006200029030037030020042004290328220d3703182004200d370340200041eae5c200ad4280808080f000841002220841086a290000370300200420082900003703282008102c20012004290328220d370300200441e0006a41086a2006290300370300200441e0006a41106a200d370300200441e0006a41186a20002903003703002004200d370390012004200429034037036020044100360248200442013703402003200441c0006a106702402003450d002003410574210003402002200441c0006a109101200241206a2102200041606a22000d000b0b20042802442100200441e0006aad4280808080800484200435024842208620042802402206ad84100102402000450d002006102c0b0240200428020c450d002004280208102c0b200524000bab0101037f230041d0006b220124002001200010fb030240200141c0006a2802002202450d00034002402001280244450d002002102c0b2001200010fb03200128024022020d000b0b02402000280204220241d0e1c100460d00200228020021032002102c2003450d00200328020021002003102c2000450d00024020002802002202450d0003402000102c2002210020022802002203210220030d000b0b2000102c0b200141d0006a24000bd0700c057f017e017f017e047f027e0b7f017e087f017e047f017e23004180076b2201240010e001024002400240024002400240024020004101470d0010a3010c010b200141d0046a41186a22024200370300200141d0046a41106a22034200370300200141d0046a41086a22044200370300200142003703d004200141b0036a41086a220541bac6c500ad4280808080c0008422061002220741086a290000370300200120072900003703b0032007102c20042005290300370300200120012903b00322083703d003200120083703d004200541dec6c500ad4280808080b001841002220741086a290000370300200120072900003703b0032007102c200320012903b0032208370300200141e0056a41086a22072004290300370300200141e0056a41106a22092008370300200141e0056a41186a220a20052903003703002001200837038801200120012903d0043703e005200141e8006a200141e0056a109801200129037021082001280268210b200242003703002003420037030020044200370300200142003703d004200520061002220c41086a2900003703002001200c2900003703b003200c102c20042005290300370300200120012903b003220d3703d0032001200d3703d004200541bec6c500ad4280808080a001841002220c41086a2900003703002001200c2900003703b003200c102c20022005290300220d37030020072004290300370300200920012903b003220e370300200a200d3703002001200e37038801200120012903d0043703e005200141d8006a200141e0056a1098012001280258210f2001290360210d200242003703002003420037030020044200370300200142003703d004200520061002220c41086a2900003703002001200c2900003703b003200c102c20042005290300370300200120012903b00322063703d003200120063703d004200541d3c6c500ad4280808080b001841002220c41086a2900003703002001200c2900003703b003200c102c20022005290300220637030020072004290300370300200920012903b003220e370300200a20063703002001200e37038801200120012903d0043703e005200141c8006a200141e0056a1098010240420020084200200b1b22062001290350420020012802481b200d42c8017e4200200f1b7c7d220820082006561b42c801540d00200a42003703002009420037030020074200370300200142003703e005200541ecddc500ad4280808080f0008422061002220441086a290000370300200120042900003703b0032004102c20072005290300370300200120012903b003220837038801200120083703e005200541f3ddc500ad4280808080c001841002220441086a290000370300200120042900003703b0032004102c200920012903b0032208370300200141d0036a41086a22042007290300370300200141d0036a41106a22022008370300200141d0036a41186a220c20052903003703002001200837038801200120012903e0053703d003200141c0006a200141d0036a41201094012001280244211020012802402111200a42003703002009420037030020074200370300200142003703e005200520061002220b41086a2900003703002001200b2900003703b003200b102c20072005290300370300200120012903b003220837038801200120083703e005200541ffddc500ad4280808080d001841002220b41086a2900003703002001200b2900003703b003200b102c200a2005290300220837030020042007290300370300200220012903b003220d370300200c20083703002001200d37038801200120012903e0053703d003200141d0036a109501210b10e101200a42003703002009420037030020074200370300200142003703e005200520061002220f41086a2900003703002001200f2900003703b003200f102c20072005290300370300200120012903b003220637038801200120063703e005200541ab83c100ad4280808080a001841002220f41086a2900003703002001200f2900003703b003200f102c200a2005290300220637030020042007290300370300200220012903b0032208370300200c20063703002001200837038801200120012903e0053703d0032001412036027c2001200141d0036a360278200141d0056a200141d0036aad4280808080800484220e1003108d014100211202400240024002400240024020012802d00522020d004100210a0c010b20012802d405210c2001200141d8056a280200360284012001200236028001200141386a20014180016a107502400240024020012802380d00200128028401220741a0016e221341a0016c2205417f4c0d04200128023c21140240024020050d004101210a0c010b2005102a220a450d0d0b02402014450d00200141e0056a41206a2115200141a8026a41017221164100210f0340200141003a00c802200f41016a21174100210502400240024002400340200141003a00af0320072005460d01200141a8026a20056a20012802800122042d00003a00002001200441016a360280012001200541016a22043a00c8022004210520044120470d000b200141d0046a41086a2205200141a8026a41086a290300370300200141d0046a41106a2218200141a8026a41106a290300370300200141d0046a41186a2219200141a8026a41186a290300370300200120012903a8023703d0042001200720046b36028401200141a8026a20014180016a10e20120012d00a8024101460d01200141e0056a41186a2019290300370300200141e0056a41106a2018290300370300200141e0056a41086a2005290300370300200120012903d0043703e0052015201641800110db051a20014188016a200141e0056a41a00110db051a2013200f470d03200f41017422052017200520174b1b2213ad42a0017e2206422088a70d142006a7220541004e0d020c140b2001410036028401200541ff0171450d00200141003a00c8020b200141003602b0032013450d05200a102c0c050b02400240200f0d002005102a210a0c010b200a200f41a0016c2005102e210a0b200a450d0f0b200a200f41a0016c6a20014188016a41a00110db051a20172014460d0120012802840121072017210f0c000b0b200141b8036a2014360200200120133602b4032001200a3602b003200a450d0120012902b40321060c020b200141003602b0030b4100210a200141003602900120014201370388012001410b3602ac022001200141f8006a3602a802200120014188016a3602d004200141f4056a4101360200200142013702e405200141d0b0c2003602e0052001200141a8026a3602f005200141d0046a41c49ac500200141e0056a10391a2001350290014220862001350288018410040240200128028c01450d00200128028801102c0b0b200c450d002002102c0b20064200200a1b221a422088a7221b41a0016c220241a0016e21054101211c02402002450d002005410574102a221c450d09200521120b200b41ff0171210c200a4101200a1b2115410021070240201b450d00201b41a0016c210a41002107201c210520152104034020052004290000370000200541186a200441186a290000370000200541106a200441106a290000370000200541086a200441086a290000370000200741016a2107200541206a2105200441a0016a2104200a41e07e6a220a0d000b0b200c410247210c200141e0056a41186a220f4200370300200141e0056a41106a22144200370300200141e0056a41086a22044200370300200142003703e005200141b0036a41086a220541ecddc500ad4280808080f000841002220a41086a2900003703002001200a2900003703b003200a102c20042005290300370300200120012903b003220637038801200120063703e005200541c9f8c200ad4280808080a001841002220a41086a2900003703002001200a2900003703b003200a102c20014188016a41086a20052903002206370300200120012903b00322083703880120092008370000200941086a2006370000200141d0036a41086a2004290300370300200141d0036a41106a2014290300370300200141d0036a41186a200f290300370300200120012903e0053703d003200141003602e805200142013703e0052007200141e0056a106702402007450d0020074105742104201c210503402005200141e0056a109101200541206a2105200441606a22040d000b0b200b200c71211820012802e4052105200e20013502e80542208620012802e0052204ad84100102402005450d002004102c0b02402018450d00200141e0056a41186a220a4200370300200141e0056a41106a220c4200370300200141e0056a41086a22044200370300200142003703e005200141b0036a41086a220541ecddc500ad4280808080f000841002220741086a290000370300200120072900003703b0032007102c20042005290300370300200120012903b003220637038801200120063703e0052005418cdec500ad4280808080a002841002220741086a290000370300200120072900003703b0032007102c20014188016a41086a20052903002206370300200120012903b00322083703880120092008370000200941086a2006370000200141d0036a41086a2004290300370300200141d0036a41106a200c290300370300200141d0036a41186a200a290300370300200120012903e0053703d003200141e0056a200141d0036a10960120012802e0052205450d00200e100520012802e405450d002005102c0b201520026a21174101211d10a301200141e0056a201041016a410120111b221e10e3010240024020012802e005221f0d00200141e0056a41186a4200370300200141e0056a41106a220a4200370300200141e0056a41086a22044200370300200142003703e005200141b0036a41086a220541ecddc500ad4280808080f000841002220741086a290000370300200120072900003703b0032007102c20042005290300370300200120012903b0033703e005200541c9f8c200ad4280808080a001841002220741086a290000370300200120072900003703b0032007102c200a20012903b003220637030020014188016a41086a200429030037030020014188016a41106a200637030020014188016a41186a2005290300370300200120063703a802200120012903e00537038801200141e0056a20014188016a412010d00120012902e405420020012802e00522051b21062005410120051b21204100211f410021210c010b200141e8056a3502002106200141f0056a280200210a200141ec056a280200210720012802e40521220240200141f4056a2802002205450d00200541d0006c2104200741c0006a210503400240200541046a280200450d002005280200102c0b200541d0006a2105200441b07f6a22040d000b0b0240200a450d002007102c0b20064220862022ad842106410121214100211d201f21200b200141e0056a41186a220a4200370300200141e0056a41106a22024200370300200141e0056a41086a22044200370300200142003703e005200141b0036a41086a220541ecddc500ad4280808080f000841002220741086a290000370300200120072900003703b0032007102c20042005290300370300200120012903b003220837038801200120083703e005200541f3ddc500ad4280808080c001841002220741086a290000370300200120072900003703b0032007102c20014188016a41086a20052903002208370300200120012903b003220d370388012009200d370000200941086a2008370000200141d0036a41086a2004290300370300200141d0036a41106a2002290300370300200141d0036a41186a200a290300370300200120012903e0053703d0032001201e3602e005200e200141e0056aad22234280808080c000841001200120213a00af032001201736027c200120153602782001200141f8006a360284012001200141af036a3602800141002113024002402006422088a7220541057422040d0041012116410021240c010b20044105752224ad42a0017e2208422088a70d0b2008a722044100480d0b2004102a2216450d090b2006a7212502402005450d002005410574220741606a410576212620014188016a4101722111200141e0056a41206a2114200141d0036a41e0006a2127200141d0036a41c0006a2119200141d0036a41206a21132016210a202021050340200541086a2900002106200541106a29000021082005290000210d200141b0036a41186a2202200541186a290000370300200141b0036a41106a220c2008370300200141b0036a41086a220b20063703002001200d3703b003200141d0056a200141b0036a10a60120014188016a20012802d005221020012802d80510a70120012d008801210f200141a8026a201141800110db051a410021040240200f4101470d00200141d0046a200141a8026a41800110db051a410121040b024020012802d405450d002010102c0b024002402004450d00200141d0036a200141d0046a41800110db051a0c010b200141d0036a410041800110da051a0b02402001280280012d00000d00200128028401220f2802002204200f280204460d00200f200441a0016a36020002400240200141d0036a200441206a220f460d00200f200141d0036a412010dd050d010b02402013200441c0006a220f460d00200f2013412010dd050d010b02402019200441e0006a220f460d00200f2019412010dd050d010b202720044180016a2204460d0120042027412010dd05450d010b20012802800141013a00000b200541206a2105200141e0056a41186a2002290300370300200141e0056a41106a200c290300370300200141e0056a41086a200b290300370300200120012903b0033703e0052014200141d0036a41800110db051a200a200141e0056a41a00110db0541a0016a210a200741606a22070d000b202641016a21130b02402025450d002020102c0b2013ad42a0017e2206422088a70d002006a72205417f4c0d0020012d00af0321110240024020050d00410121100c010b2005102a2210450d090b4100210c02402013450d002016201341a0016c6a210f200141e0056a4180016a2104200141e0056a41e0006a2107200141e0056a41c0006a210a200141e0056a41206a21024100210c2010210b201621050340200141e0056a41186a200541186a290000370300200141e0056a41106a200541106a290000370300200141e0056a41086a200541086a290000370300200120052900003703e005200241186a200541386a290000370000200241106a200541306a290000370000200241086a200541286a2900003700002002200541206a290000370000200a200541c0006a290000370000200a41086a200541c8006a290000370000200a41106a200541d0006a290000370000200a41186a200541d8006a2900003700002007200541e0006a290000370000200741086a200541e8006a290000370000200741106a200541f0006a290000370000200741186a200541f8006a290000370000200420054180016a290000370000200441086a20054188016a290000370000200441106a20054190016a290000370000200441186a20054198016a290000370000200c41016a210c200b200141e0056a41a00110db0541a0016a210b200541a0016a2205200f470d000b0b200141e0056a41186a220a4200370300200141e0056a41106a22024200370300200141e0056a41086a22044200370300200142003703e005200141b0036a41086a220541ecddc500ad4280808080f000841002220741086a290000370300200120072900003703b0032007102c20042005290300370300200120012903b003220637038801200120063703e005200541ab83c100ad4280808080a001841002220741086a290000370300200120072900003703b0032007102c20014188016a41086a20052903002206370300200120012903b00322083703880120092008370000200941086a2006370000200141d0036a41086a2004290300370300200141d0036a41106a2002290300370300200141d0036a41186a200a290300370300200120012903e0053703d003200141003602e805200142013703e005200c200141e0056a10670240200c450d002010200c41a0016c6a21042010210503402005200141e0056a109101200541206a200141e0056a109101200541c0006a200141e0056a109101200541e0006a200141e0056a10910120054180016a200141e0056a109101200541a0016a22052004470d000b0b20012802e4052105200e20013502e80542208620012802e0052204ad84100102402005450d002004102c0b02402013450d002010102c0b200141e0056a41186a220a4200370300200141e0056a41106a22024200370300200141e0056a41086a22044200370300200142003703e005200141b0036a41086a220541ecddc500ad4280808080f000841002220741086a290000370300200120072900003703b0032007102c20042005290300370300200120012903b003220637038801200120063703e005200541ffddc500ad4280808080d001841002220741086a290000370300200120072900003703b0032007102c20014188016a41086a20052903002206370300200120012903b00322083703880120092008370000200941086a2006370000200141d0036a41086a2004290300370300200141d0036a41106a2002290300370300200141d0036a41186a200a290300370300200120012903e0053703d003200120113a00e005200e20234280808080108410012001201e3602e405200141053a00e00541014100200141e0056a1092014108102a2207450d082007201736020420072015360200024020180d00200141e0056a41186a220c4200370300200141e0056a41106a220a4200370300200141e0056a41086a22044200370300200142003703e005200141d0036a41086a220541e0d9c500ad4280808080f001841002220241086a290000370300200120022900003703d0032002102c20042005290300370300200120012903d00322063703a802200120063703e005200541d4d9c500ad4280808080c001841002220241086a290000370300200120022900003703d0032002102c200a20012903d003220637030020014188016a41086a220b200429030037030020014188016a41106a220f200637030020014188016a41186a22102005290300370300200120063703a802200120012903e00537038801200141286a20014188016a1098012001290330210820012802282111200c4200370300200a420037030020044200370300200142003703e005200541ecddc500ad4280808080f000841002220241086a290000370300200120022900003703d0032002102c20042005290300370300200120012903d0033703e005200541f3ddc500ad4280808080c001841002220241086a290000370300200120022900003703d0032002102c200a20012903d0032206370300200b2004290300370300200f200637030020102005290300370300200120063703a802200120012903e00537038801200141206a20014188016a41201094012008420020111b2001280224410020012802201b10b2012007102c0c040b02400240201b450d002007201541a0016a220a360200200141003a008006201541206a2104410021050340200141003a00af03200141e0056a20056a200420056a2d00003a00002001200541016a22053a00800620054120470d000b20014188016a41086a2205200141e0056a41086a29030037030020014188016a41106a2204200141e0056a41106a29030037030020014188016a41186a2202200141e0056a41186a290300370300200120012903e0053703880120150d010b2007102c4108210f4100210a410021050c030b200141a8026a41186a2002290300370300200141a8026a41106a2004290300370300200141a8026a41086a200529030037030020012001290388013703a8022017200a6b41a0016e41016a220541286c2204417f4c0d002004102a220f450d08200f20012903a802370300200f4201370320200f41186a200141a8026a41186a290300370300200f41106a200141a8026a41106a290300370300200f41086a200141a8026a41086a2903003703000240200728020022042007280204470d004101210a0c020b2007200441a0016a360200200141003a008006200441206a210a410021040340200141003a00af03200141e0056a20046a200a20046a2d00003a00002001200441016a22043a00800620044120470d000b200141d0046a41186a2219200141e0056a41186a2202290300220637030020014188016a41086a2210200141e0056a41086a220c29030037030020014188016a41106a2211200141e0056a41106a220b29030037030020014188016a41186a22142006370300200120012903e005370388014101210a0340200141a8026a41186a20142903002206370300200141a8026a41106a20112903002208370300200141a8026a41086a2010290300220d3703002001200129038801220e3703a80220022006370300200b2008370300200c200d3703002001200e3703e005024002402005200a460d00200521090c010b200728020420072802006b41a0016e20056a41016a22042005490d0c200541017422092004200920044b1b2209ad42287e2206422088a70d0c2006a722044100480d0c0240024020050d002004102a210f0c010b200f200541286c2004102e210f0b200f450d0a0b200f200a41286c6a220520012903e005370300200c2903002106200b29030021082002290300210d20054201370320200541186a200d370300200541106a2008370300200541086a2006370300200a41016a210a0240200728020022042007280204470d00200921050c030b2007200441a0016a36020041002105200141003a008006200441206a21040340200141003a00af03200141e0056a20056a200420056a2d00003a00002001200541016a22053a00800620054120470d000b2019200229030022063703002010200c2903003703002011200b29030037030020142006370300200120012903e00537038801200921050c000b0b103a000b2007102c0b200141e0056a41186a4200370300200141e0056a41106a22024200370300200141e0056a41086a22074200370300200142003703e005200141d0036a41086a220441e0d9c500ad4280808080f001841002220c41086a2900003703002001200c2900003703d003200c102c20072004290300370300200120012903d00322063703a802200120063703e005200441aeb5c000ad4280808080f000841002220c41086a2900003703002001200c2900003703d003200c102c200220012903d003220637030020014188016a41086a200729030037030020014188016a41106a200637030020014188016a41186a2004290300370300200120063703a802200120012903e00537038801200141e0056a20014188016a10e4010240024020012802e0054101460d002001200a3602e805200120053602e4052001200f3602e005200141e0056a41004100200110b30120014188016aad428080808080048421060c010b20014188016aad42808080808004842206100520012902e40521082001200a3602e805200120053602e4052001200f3602e005200141e0056a2008a741012008422088a710b3010b200141e0056a41186a220a4200370300200141e0056a41106a22074200370300200141e0056a41086a22044200370300200142003703e005200141d0036a41086a220541e0d9c500ad4280808080f0018422081002220c41086a2900003703002001200c2900003703d003200c102c20042005290300370300200120012903d003220d3703a8022001200d3703e005200541d4d9c500ad4280808080c00184220d1002220c41086a2900003703002001200c2900003703d003200c102c200141a8026a41086a22112005290300220e370300200120012903d00322283703a80220022028370000200241086a2214200e37000020014188016a41086a220c200429030037030020014188016a41106a220b200729030037030020014188016a41186a220f200a290300370300200120012903e00537038801200141106a20014188016a109801200128021021092001290318210e200a42003703002007420037030020044200370300200142003703e005200520081002221041086a290000370300200120102900003703d0032010102c20042005290300370300200120012903d00322083703a802200120083703e0052005200d1002221041086a290000370300200120102900003703d0032010102c201120052903002208370300200120012903d003220d3703a8022002200d37000020142008370000200c2004290300370300200b2007290300370300200f200a290300370300200120012903e005370388012001200e42017c420120091b22083703e0052006202342808080808001841001200a42003703002007420037030020044200370300200142003703e005200541ecddc500ad4280808080f000841002220a41086a2900003703002001200a2900003703d003200a102c20042005290300370300200120012903d0033703e005200541f3ddc500ad4280808080c001841002220a41086a2900003703002001200a2900003703d003200a102c200720012903d0032206370300200c2004290300370300200b2006370300200f2005290300370300200120063703a802200120012903e00537038801200141086a20014188016a41201094012008200128020c410020012802081b10b2010b4108102a2205450d0420052017360204200520153602004108102a2204450d0420042016201341a0016c6a221e360204200420163602002005200410e5014108102a2207450d0420072017360204200720153602004108102a2219450d042019201e36020420192016360200200141e0056a41186a220c4200370300200141e0056a41106a221b4200370300200141e0056a41086a22044200370300200142003703e005200141d0036a41086a22054191b0c200ad4280808080e000841002220a41086a2900003703002001200a2900003703d003200a102c20042005290300370300200120012903d0033703e005200541acb0c200ad4280808080e000841002220a41086a2900003703002001200a2900003703d003200a102c201b20012903d003220637030020014188016a41086a200429030037030020014188016a41106a200637030020014188016a41186a2005290300370300200120063703a802200120012903e00537038801200120014188016a41201094012001280200210b2001280204210f200141d0046a41186a22104200370300200141d0046a41106a22114200370300200141d0046a41086a220a4200370300200142003703d004200541a3dbc500ad42808080808001841002220241086a290000370300200120022900003703d0032002102c200a2005290300370300200120012903d003220637038801200120063703d00420054187a6c500ad42808080808001841002220241086a290000370300200120022900003703d0032002102c200141b0036a41086a20052903002206370300200120012903d00322083703b00320032008370000200341086a20063700002004200a290300370300201b2011290300370300200c2010290300370300200120012903d0043703e0052001200f41e4006a41e400200b1b3602880120234280808080800484222320014188016aad22284280808080c0008410010240024002402007280200220520072802042202460d002007200541a0016a220c360200200141003a008006200541e0006a2104410021050340200141003a00af03200141e0056a20056a200420056a2d00003a00002001200541016a22053a00800620054120470d000b200141a8026a41086a2205200141e0056a41086a290300370300200141a8026a41106a220b200141e0056a41106a290300370300200141a8026a41186a220f200141e0056a41186a290300370300200120012903e005220637038801200120063703a8024101210a2002200c6b41a0016e41016a2204410574102a2210450d07201020012903a802370000201041186a200f290300370000201041106a200b290300370000201041086a2005290300370000200728020022052007280204460d012007200541a0016a360200200141003a008006200541e0006a210a410021050340200141003a00af03200141e0056a20056a200a20056a2d00003a00002001200541016a22053a00800620054120470d000b200141d0046a41186a2213200141e0056a41186a2202290300220637030020014188016a41086a2211200141e0056a41086a220c29030037030020014188016a41106a2214200141e0056a41106a220b29030037030020014188016a41186a22092006370300200120012903e005370388014101210a0340200141a8026a41186a20092903002206370300200141a8026a41106a20142903002208370300200141a8026a41086a2011290300220d3703002001200129038801220e3703a80220022006370300200b2008370300200c200d3703002001200e3703e005024002402004200a460d002004210f0c010b200728020420072802006b41a0016e20046a41016a22052004490d0b2004410174220f2005200f20054b1b220f41ffffff3f71200f470d0b200f41057422054100480d0b0240024020040d002005102a21100c010b201020044105742005102e21100b2010450d090b2010200a4105746a220520012903e005370000200541186a2002290300370000200541106a200b290300370000200541086a200c290300370000200a41016a210a0240200728020022042007280204470d00200f21040c030b2007200441a0016a36020041002105200141003a008006200441e0006a21040340200141003a00af03200141e0056a20056a200420056a2d00003a00002001200541016a22053a00800620054120470d000b2013200229030022063703002011200c2903003703002014200b29030037030020092006370300200120012903e00537038801200f21040c000b0b2007102c41002104410121104100210a0c010b2007102c0b200141d0046a41186a220c4200370300200141d0046a41106a220b4200370300200141d0046a41086a22074200370300200142003703d004200141d0036a41086a220541a3dbc500ad42808080808001841002220241086a290000370300200120022900003703d0032002102c20072005290300370300200120012903d003220637038801200120063703d004200541a0c6c500ad4280808080c000841002220241086a290000370300200120022900003703d0032002102c200141b0036a41086a20052903002206370300200120012903d00322083703b00320032008370000200341086a2006370000200141e0056a41086a2007290300370300200141e0056a41106a200b290300370300200141e0056a41186a200c290300370300200120012903d0043703e00520014100360290012001420137038801200a20014188016a10670240200a450d00200a4105742107201021050340200520014188016a109101200541206a2105200741606a22070d000b0b200128028c01210520232001350290014220862001280288012207ad84100102402005450d002007102c0b02402004450d002010102c0b2019102c4108102a220a450d04200a2017360204200a20153602004108102a2219450d042019201e36020420192016360200024002400240024002402018450d00200a2802002205200a2802042202460d01200a200541a0016a220c360200200141003a00800620054180016a2104410021050340200141003a00af03200141e0056a20056a200420056a2d00003a00002001200541016a22053a00800620054120470d000b200141a8026a41086a2205200141e0056a41086a290300370300200141a8026a41106a220b200141e0056a41106a290300370300200141a8026a41186a220f200141e0056a41186a290300370300200120012903e005220637038801200120063703a802410121072002200c6b41a0016e41016a2204410574102a2210450d09201020012903a802370000201041186a200f290300370000201041106a200b290300370000201041086a2005290300370000200a2802002205200a2802042213460d02200a200541a0016a2217360200200141003a00800620054180016a2107410021050340200141003a00af03200141e0056a20056a200720056a2d00003a00002001200541016a22053a00800620054120470d000b200141d0046a41186a2218200141e0056a41186a2202290300220637030020014188016a41086a2211200141e0056a41086a220c29030037030020014188016a41106a2214200141e0056a41106a220b29030037030020014188016a41186a22092006370300200120012903e00537038801410121070340200141a8026a41186a20092903002206370300200141a8026a41106a20142903002208370300200141a8026a41086a2011290300220d3703002001200129038801220e3703a80220022006370300200b2008370300200c200d3703002001200e3703e0050240024020042007460d002004210f0c010b201320176b41a0016e20046a41016a22052004490d0d2004410174220f2005200f20054b1b220f41ffffff3f71200f470d0d200f41057422054100480d0d0240024020040d002005102a21100c010b201020044105742005102e21100b2010450d0b0b201020074105746a220520012903e005370000200541186a2002290300370000200541106a200b290300370000200541086a200c290300370000200741016a21070240200a2802002204200a2802042213470d00200f21040c040b200a200441a0016a221736020041002105200141003a00800620044180016a21040340200141003a00af03200141e0056a20056a200420056a2d00003a00002001200541016a22053a00800620054120470d000b2018200229030022063703002011200c2903003703002014200b29030037030020092006370300200120012903e00537038801200f21040c000b0b2019102c200a102c0c030b200a102c4101211041002107410021040c010b200a102c0b200141e0056a41186a220c4200370300200141e0056a41106a220b4200370300200141e0056a41086a220a4200370300200142003703e005200141d0036a41086a2205418ec6c500ad4280808080a002841002220241086a290000370300200120022900003703d0032002102c200a2005290300370300200120012903d0033703e005200541a0c6c500ad4280808080c000841002220241086a290000370300200120022900003703d0032002102c200141a8026a41086a20052903002206370300200120012903d00322083703a802201b2008370000201b41086a200637000020014188016a41086a200a29030037030020014188016a41106a200b29030037030020014188016a41186a200c290300370300200120012903e00537038801200141003602e805200142013703e0052007200141e0056a106702402007450d00200741057421072010210503402005200141e0056a109101200541206a2105200741606a22070d000b0b20012802e40521052028428080808080048420013502e80542208620012802e0052207ad84100102402005450d002007102c0b02402004450d002010102c0b2019102c0b02402024450d002016102c0b02402022450d00201d2021720d00201f102c0b02402012450d00201c102c0b201aa7450d002015102c0b10a301200041044b0d010b200141e0056a210c0c010b200141d0046a41186a220a4200370300200141d0046a41106a22024200370300200141d0046a41086a22044200370300200142003703d004200141b0036a41086a220541a4c6c500ad4280808080a001841002220741086a290000370300200120072900003703b0032007102c20042005290300370300200120012903b0033703d004200541f889c200ad4280808080e000841002220741086a290000370300200120072900003703b0032007102c20014188016a41086a20052903002206370300200120012903b00322083703880120032008370000200341086a2006370000200141e0056a41086a2004290300370300200141e0056a41106a2002290300370300200141e0056a41186a200a290300370300200120012903d0043703e00520014188016a200141e0056a10e6012001280288012205410420051b210202400240200129028c01420020051b2206422088a7220c41c4006c22050d00410021040c010b2000417b6a210a200220056a2107410021042002210502400340024020052d00004101460d00200541046a280200200a4f0d020b200441016a21042007200541c4006a2205470d000b0b2004200c4b0d030b200642ffffffff0f8321060240200c20046b2205450d0002402004450d0020022002200441c4006c6a200541c4006c10dc051a0b2005ad42208620068421060b200141d0046a41186a4200370300200141d0046a41106a220a4200370300200141d0046a41086a22044200370300200142003703d004200141b0036a41086a220541a4c6c500ad4280808080a001841002220741086a290000370300200120072900003703b0032007102c20042005290300370300200120012903b00322083703a802200120083703d004200541f889c200ad4280808080e000841002220741086a290000370300200120072900003703b0032007102c200a20012903b0032208370300200141e0056a41086a2004290300370300200141e0056a41106a2008370300200141e0056a41186a2005290300370300200120083703d003200120012903d0043703e00520014188016a20022006422088a710e701200141e0056aad42808080808004842001350290014220862001280288012204ad8410012006a721050240200128028c01450d002004102c0b200141e0056a210c2005450d002002102c0b200141d0046a41186a220a4200370300200141d0046a41106a22074200370300200141d0046a41086a22044200370300200142003703d004200141b0036a41086a220541a4c6c500ad4280808080a001841002220241086a290000370300200120022900003703b0032002102c20042005290300370300200120012903b00322063703a802200120063703d004200541aec6c500ad4280808080c001841002220241086a290000370300200120022900003703b0032002102c200720012903b0032206370300200141e0056a41086a22022004290300370300200141e0056a41106a220b2006370300200141e0056a41186a220f2005290300370300200120063703d003200120012903d0043703e005200141003a00af03200cad4280808080800484200141af036aad42808080801084100120014188016a10e801200a20014188016a41186a220c290300370300200720014188016a41106a2210290300370300200420014188016a41086a221129030037030020012001290388013703d0044124102a2205450d00200520012903d00437000020054114360220200541186a200a290300370000200541106a2007290300370000200541086a200429030037000020014281808080103702e405200120053602e005200141e0056a10e901200f200c290300370300200b20102903003703002002201129030037030020012001290388013703e005200141e0056a10ea0110e00120014180076a24000f0b1033000b41dafec500411c41acfec5001036000b1035000b8a1e0a057f017e037f017e017f027e017f017e047f027e23004190046b22002400200041b8036a41186a4200370300200041b8036a41106a22014200370300200041b8036a41086a22024200370300200042003703b803200041f8026a41086a220341bac6c500ad4280808080c000841002220441086a290000370300200020042900003703f8022004102c20022003290300370300200020002903f80222053703e001200020053703b80320034183d7c500ad4280808080b001841002220441086a290000370300200020042900003703f8022004102c200120002903f8022205370300200041e8036a41086a2002290300370300200041e8036a41106a2005370300200041e8036a41186a2003290300370300200020053703e001200020002903b8033703e803200041f0016a200041e8036a1099010240024020002d00f0014102470d00200041f0016a41186a4200370300200041f0016a41106a22064200370300200041f0016a41086a22024200370300200042003703f00120034191b0c200ad4280808080e000841002220441086a290000370300200020042900003703f8022004102c20022003290300370300200020002903f8023703f001200341cab0c200ad4280808080e000841002220441086a290000370300200020042900003703f8022004102c200620002903f802220537030020004180016a41086a200229030037030020004180016a41106a200537030020004180016a41186a200329030037030020002005370318200020002903f00137038001200041b8036a20004180016a10e4020240024020002802b80322030d0041002107200041003602880120004204370380014102210620004180016a21080c010b200020002902bc0322053702840120002003360280012005a7210720004180016a210802402005422088a72202450d00200241246c210202400340024020032d00004101470d00200341016a2800002104200341086a28020021062000200341106a2802003602bc03200020063602b803200441c28289aa04470d00200041f0016a200041b8036a10e50220002d00f00122064102470d020b200341246a21032002415c6a2202450d020c000b0b200020002800f401360073200020002800f101360270200041f8016a2903002105200041186a20004180026a41d80010db051a200041d8026a29030021090c010b410221060b2008280200210a024020082802082203450d00200341246c2102200a210303400240024020032d0000220441034b0d0002400240024020040e0404000102040b2003410c6a280200450d03200341086a280200102c0c030b2003410c6a280200450d02200341086a280200102c0c020b2003410c6a280200450d01200341086a280200102c0c010b200341086a280200450d00200341046a280200102c0b200341246a21032002415c6a22020d000b0b02402007450d00200a102c0b200020002802703602d801200020002800733600db0120004180016a200041186a41d80010db051a0240024020064102470d0041002102200041e8036a21080c010b200020002802d8013602f002200020002800db013600f302200020053703e802200041f0016a20004180016a41d80010db051a200020093703e002200041b8036a41186a22044200370300200041b8036a41106a22084200370300200041b8036a41086a22024200370300200042003703b803200041f8026a41086a220341bac6c500ad4280808080c0008422091002220a41086a2900003703002000200a2900003703f802200a102c20022003290300370300200020002903f802220b3703e0012000200b3703b803200341d3c6c500ad4280808080b00184220c1002220a41086a2900003703002000200a2900003703f802200a102c200041e0016a41086a220d2003290300220b370300200020002903f802220e3703e0012001200e370000200141086a220f200b370000200041e8036a41086a220a2002290300370300200041e8036a41106a22072008290300370300200041e8036a41186a22102004290300370300200020002903b8033703e803200041086a200041e8036a109801024002402000280208450d002000290310500d00200041e8036aad4280808080800484210b200041e8036a21080c010b200041e8026a200041e0026a20064101461b290300210b200442003703002008420037030020024200370300200042003703b803200320091002221141086a290000370300200020112900003703f8022011102c20022003290300370300200020002903f802220e3703e0012000200e3703b8032003200c1002221141086a290000370300200020112900003703f8022011102c200d2003290300220e370300200020002903f802220c3703e0012001200c370000200f200e370000200a20022903003703002007200829030037030020102004290300370300200020002903b8033703e8032000200b3703b803200041e8036aad4280808080800484220b200041b8036aad42808080808001841001200442003703002008420037030020024200370300200042003703b803200320091002221141086a290000370300200020112900003703f8022011102c20022003290300370300200020002903f802220e3703e0012000200e3703b803200341c8c6c500ad4280808080b001841002221141086a290000370300200020112900003703f8022011102c200d2003290300220e370300200020002903f802220c3703e0012001200c370000200f200e370000200a20022903003703002007200829030037030020102004290300370300200020002903b8033703e803200041b8036a200041e8036a10ff0220002902bc03210e20002802b8032111200442003703002008420037030020024200370300200042003703b803200320091002221241086a290000370300200020122900003703f8022012102c20022003290300370300200020002903f80222093703e001200020093703b803200341e9c6c500ad4280808080a001841002221241086a290000370300200020122900003703f8022012102c200d20032903002209370300200020002903f802220c3703e0012001200c370000200f2009370000200a20022903003703002007200829030037030020102004290300370300200020002903b8033703e803200041b8036a200041e8036a10800320002d00b80321032010200041d1036a2900003703002007200041c9036a290000370300200a200041c1036a290000370300200020002900b9033703e8032011410820111b21020240024020034101460d00200041b0036a4200370300200041a8036a4200370300200041a0036a420037030020004200370398030c010b20004198036a41186a200041e8036a41186a29030037030020004198036a41106a200041e8036a41106a29030037030020004198036a41086a200041e8036a41086a290300370300200020002903e803370398030b200041f8026a41086a20004198036a41086a2903002209370300200041f8026a41106a20004198036a41106a290300220c370300200041f8026a41186a20004198036a41186a2903002213370300200020002903980322143703f802200041b8036a41086a2203200e420020111b370300200041b8036a41106a2014370300200041b8036a41186a2009370300200041d8036a200c370300200041e0036a2013370300200020023602bc03200041003602b803200041e8036a200041b8036a108b02200041a3036a200041e8036a41086a280200360000200020002903e80337009b03200041f4036a2000419f036a290000370000200041c28289aa043600e903200041023a00e80320002000290098033700ed03200041e8036a109001024020002802b8030d002003280200450d0020002802bc03102c0b200041e8036a21080b200041e8026a200041e0026a20064101461b2903002109200041b8036a41186a220a4200370300200041b8036a41106a22074200370300200041b8036a41086a22024200370300200042003703b803200041f8026a41086a220341bac6c500ad4280808080c000841002220441086a290000370300200020042900003703f8022004102c20022003290300370300200020002903f802220e3703e0012000200e3703b803200341dec6c500ad4280808080b001841002220441086a290000370300200020042900003703f8022004102c200041e0016a41086a2003290300220e370300200020002903f802220c3703e0012001200c370000200141086a200e370000200041e8036a41086a2002290300370300200041e8036a41106a2007290300370300200041e8036a41186a200a290300370300200020002903b8033703e803200020093703b803200b200041b8036aad428080808080018410014100210220060d0020004198036a41086a200041f0016a41086a29030037030020004198036a41106a200041f0016a41106a2d00003a0000200020002800f30236007b200020002802f002360278200020002903f00137039803410121020b200041f0016a41086a2005370300200041f0016a41106a200029039803370300200041f0016a41186a20004198036a41086a29030037030020004190026a20004198036a41106a2d00003a0000200020023a00f001200020002802783600f1012000200028007b3600f401200041b8036a41186a220a4200370300200041b8036a41106a22074200370300200041b8036a41086a22044200370300200042003703b803200041f8026a41086a220341bac6c500ad4280808080c000841002220641086a290000370300200020062900003703f8022006102c20042003290300370300200020002903f80222053703e001200020053703b80320034183d7c500ad4280808080b001841002220641086a290000370300200020062900003703f8022006102c200041e0016a41086a20032903002205370300200020002903f80222093703e00120012009370000200141086a2005370000200041e8036a41086a2004290300370300200041e8036a41106a2007290300370300200041e8036a41186a200a290300370300200020002903b8033703e8034101102a2203450d01200042013702840120002003360280010240024020020d002000410136028801200341003a00000c010b2000410136028801200341013a0000200041f0016a41017220004180016a10ba020b20002802840121032008ad42808080808004842000350288014220862000280280012202ad8410012003450d002002102c0b20004190046a24000f0b1033000b83790d067f017e017f017e057f017e017f017e0a7f017e167f037e057f23004180066b2200240020004180056a41186a2201420037030020004180056a41106a220242003703004108210320004180056a41086a220442003703002000420037038005200041b0026a41086a220541ecddc500ad4280808080f0008422061002220741086a290000370300200020072900003703b0022007102c20042005290300370300200020002903b00237038005200541f3ddc500ad4280808080c001841002220741086a290000370300200020072900003703b0022007102c200220002903b0022208370300200041b0046a41086a22092004290300370300200041b0046a41106a220a2008370300200041b0046a41186a220b2005290300370300200020083703e00320002000290380053703b004200041286a200041b0046a4120109401200028022c210c2000280228210d2001420037030020024200370300200442003703002000420037038005200541a3dbc500ad42808080808001841002220741086a290000370300200020072900003703b0022007102c20042005290300370300200020002903b00237038005200541a0c6c500ad4280808080c000841002220741086a290000370300200020072900003703b0022007102c20012005290300220837030020092004290300370300200a20002903b002220e370300200b20083703002000200e3703e00320002000290380053703b00420004180056a200041b0046a10f002200028028005210f20002902840521102001420037030020024200370300200442003703002000420037038005200520061002220741086a290000370300200020072900003703b0022007102c20042005290300370300200020002903b00237038005200541c9f8c200ad4280808080a001841002220741086a290000370300200020072900003703b0022007102c20012005290300220837030020092004290300370300200a20002903b0022206370300200b2008370300200020063703e00320002000290380053703b00420004180056a200041b0046a412010d0012000280280052207410120071b2111200029028405420020071b2208a72112024002400240024002400240024002402008422088a72207450d002011200741057422136a2114200041c4036a211520004180056a41206a2116200041f8026a4104722117200041d0026a410472211841022107410021190340200041e0016a41186a201120196a221a41186a2900002208370300200041e0016a41106a201a41106a2900002206370300200041e0016a41086a201a41086a290000220e3703002000201a290000221b3703e0012018201b370200201841086a200e370200201841106a2006370200201841186a200837020020002007417e6a221c3602d0024100211d0240201c201810cb030d00200041f8026a41206a200041d0026a41206a280200360200200041f8026a41186a200041d0026a41186a290300370300200041f8026a41106a200041d0026a41106a290300370300200041f8026a41086a200041d0026a41086a290300370300200020002903d0023703f80220004190026a41186a221d201741186a221c29000037030020004190026a41106a221e201741106a221f29000037030020004190026a41086a2220201741086a222129000037030020002017290000370390022001201c2900003703002002201f290000370300200420212900003703002000201729000037038005200041a0036a20004180056a109204200041b0026a41186a221c201d290300370300200041b0026a41106a221f201e2903003703002005202029030037030020002000290390023703b00220002802c003221d450d00201620002903a003370300201641186a200041a0036a41186a290300370300201641106a200041a0036a41106a290300370300201641086a200041a0036a41086a2903003703002001201c2903003703002002201f2903003703002004200529030037030020004180026a41086a221c201541086a280200360200200020002903b002370380052000201529020037038002200041b0046a41386a221e20004180056a41386a290300370300200041b0046a41306a221f20004180056a41306a290300370300200041b0046a41286a222020004180056a41286a290300370300200041b0046a41206a22212016290300370300200b2001290300370300200a20022903003703002009200429030037030020002000290380053703b004200041e0036a41386a201e290300370300200041e0036a41306a201f290300370300200041e0036a41286a2020290300370300200041e0036a41206a2021290300370300200041e0036a41186a200b290300370300200041e0036a41106a200a290300370300200041e0036a41086a2009290300370300200020002903b0043703e003200041d0036a41086a201c28020036020020002000290380023703d0030b200041a0016a41086a200041e0036a41086a290300370300200041a0016a41106a200041e0036a41106a290300370300200041a0016a41186a200041e0036a41186a290300370300200041a0016a41206a200041e0036a41206a290300370300200041a0016a41286a200041e0036a41286a290300370300200041a0016a41306a200041e0036a41306a290300370300200041a0016a41386a200041e0036a41386a29030037030020004190016a41086a200041d0036a41086a280200360200200020002903e0033703a001200020002903d00337039001201d0d02200741016a21072013201941206a2219470d000b0b410021222000410036029801200042083703900102402012450d002011102c0b4100211d0c010b200041c0006a41386a2218200041a0016a41386a290300370300200041c0006a41306a2217200041a0016a41306a290300370300200041c0006a41286a2204200041a0016a41286a290300370300200041c0006a41206a221c200041a0016a41206a290300370300200041c0006a41186a2205200041a0016a41186a290300370300200041c0006a41106a2201200041a0016a41106a290300370300200041c0006a41086a221e200041a0016a41086a29030037030020004180016a41086a221f20004190016a41086a280200360200200020002903a001370340200020002903900137038001200041306a41086a2220201f280200360200200020002903800137033020004180056a41086a221f201e29030037030020004180056a41106a221e200129030037030020004180056a41186a2201200529030037030020004180056a41206a2205201c29030037030020004180056a41286a221c200429030037030020004180056a41306a2204201729030037030020004180056a41386a221720182903003703002000200029034037038005200041b0046a41086a22182020280200360200200020002903303703b00441d000102a2203450d0120032000290380053703002003201d360240200320002903b004370244200341386a2017290300370300200341306a2004290300370300200341286a201c290300370300200341206a2005290300370300200341186a2001290300370300200341106a201e290300370300200341086a201f290300370300200341cc006a20182802003602000240024002400240201341606a2019470d004101211d0c010b201a41206a2118201320196b41606a2105200041c4036a2120200041f8026a4104722117200041d0026a410472211a0340200041e0016a41186a201841186a2219290000370300200041e0016a41106a201841106a221d290000370300200041e0016a41086a201841086a2204290000370300200020182900003703e00120002007417f6a221c3602d00220042900002108201d29000021062018290000210e201a41186a2019290000370000201a41106a2006370000201a41086a2008370000201a200e370000410021190240201c201a10cb030d00200041f8026a41206a200041d0026a41206a280200360200200041f8026a41186a200041d0026a41186a290300370300200041f8026a41106a200041d0026a41106a290300370300200041f8026a41086a200041d0026a41086a290300370300200020002903d0023703f80220004190026a41186a2219201741186a220429000037030020004190026a41106a2201201741106a221c29000037030020004190026a41086a2213201741086a221e290000370300200020172900003703900220004180056a41186a221d200429000037030020004180056a41106a2204201c29000037030020004180056a41086a221c201e2900003703002000201729000037038005200041a0036a20004180056a109204200041b0026a41186a221e2019290300370300200041b0026a41106a221f2001290300370300200041b0026a41086a2201201329030037030020002000290390023703b00220002802c0032219450d00201620002903a003370300201641186a200041a0036a41186a290300370300201641106a200041a0036a41106a290300370300201641086a200041a0036a41086a290300370300201d201e2903003703002004201f290300370300201c200129030037030020004180026a41086a2201202041086a280200360200200020002903b002370380052000202029020037038002200041b0046a41386a221320004180056a41386a290300370300200041b0046a41306a221e20004180056a41306a290300370300200041b0046a41286a221f20004180056a41286a290300370300200041b0046a41206a222120004180056a41206a290300370300200041b0046a41186a2209201d290300370300200041b0046a41106a221d2004290300370300200041b0046a41086a2204201c29030037030020002000290380053703b004200041e0036a41386a2013290300370300200041e0036a41306a201e290300370300200041e0036a41286a201f290300370300200041e0036a41206a2021290300370300200041e0036a41186a2009290300370300200041e0036a41106a201d290300370300200041e0036a41086a2004290300370300200020002903b0043703e003200041d0036a41086a200128020036020020002000290380023703d0030b200041a0016a41086a200041e0036a41086a290300370300200041a0016a41106a200041e0036a41106a290300370300200041a0016a41186a200041e0036a41186a290300370300200041a0016a41206a200041e0036a41206a290300370300200041a0016a41286a200041e0036a41286a290300370300200041a0016a41306a200041e0036a41306a290300370300200041a0016a41386a200041e0036a41386a29030037030020004190016a41086a200041d0036a41086a280200360200200020002903e0033703a001200020002903d0033703900120190d02201841206a21184101211d200741016a2107200541606a22050d000b0b410121220c010b200041c0006a41386a2223200041a0016a41386a221e290300370300200041c0006a41306a2224200041a0016a41306a221f290300370300200041c0006a41286a2225200041a0016a41286a2220290300370300200041c0006a41206a2226200041a0016a41206a2221290300370300200041c0006a41186a2227200041a0016a41186a2209290300370300200041c0006a41106a2228200041a0016a41106a220a290300370300200041c0006a41086a2229200041a0016a41086a220b29030037030020004180016a41086a222a20004190016a41086a2215280200360200200020002903a001370340200020002903900137038001200041306a41086a222b202a2802003602002000200029038001370330201841206a2118200041c4036a212c200041f8026a4104722117200041d0026a410472211a4101211d41012122034020004180056a41086a2205202929030037030020004180056a41106a2201202829030037030020004180056a41186a2213202729030037030020004180056a41206a222d202629030037030020004180056a41286a222e202529030037030020004180056a41306a222f202429030037030020004180056a41386a223020232903003703002000200029034037038005200041b0046a41086a2231202b280200360200200020002903303703b00402402022201d470d00201d41016a2204201d490d08201d410174221c2004201c20044b1b2222ad42d0007e2208422088a70d082008a722044100480d0802400240201d0d002004102a21030c010b2003201d41d0006c2004102e21030b2003450d040b2003201d41d0006c6a22042000290380053703002001290300210820132903002106202d290300210e202e290300211b202f2903002132203029030021332005290300213420042019360240200441086a2034370300200441386a2033370300200441306a2032370300200441286a201b370300200441206a200e370300200441186a2006370300200441106a2008370300200420002903b004370244200441cc006a2031280200360200201d41016a211d20182014460d010340200041e0016a41186a201841186a2219290000370300200041e0016a41106a201841106a2204290000370300200041e0016a41086a201841086a221c290000370300200020182900003703e001200020073602d002201c2900002108200429000021062018290000210e201a41186a2019290000370000201a41106a2006370000201a41086a2008370000201a200e3700004100211902402007201a10cb030d00200041f8026a41206a200041d0026a41206a280200360200200041f8026a41186a200041d0026a41186a290300370300200041f8026a41106a200041d0026a41106a290300370300200041f8026a41086a200041d0026a41086a290300370300200020002903d0023703f80220004190026a41186a2219201741186a220429000037030020004190026a41106a221c201741106a223529000037030020004190026a41086a2236201741086a223729000037030020002017290000370390022013200429000037030020012035290000370300200520372900003703002000201729000037038005200041a0036a20004180056a109204200041b0026a41186a22042019290300370300200041b0026a41106a2235201c290300370300200041b0026a41086a221c203629030037030020002000290390023703b00220002802c0032219450d00201620002903a003370300201641186a200041a0036a41186a290300370300201641106a200041a0036a41106a290300370300201641086a200041a0036a41086a29030037030020132004290300370300200120352903003703002005201c29030037030020004180026a41086a2204202c41086a280200360200200020002903b002370380052000202c29020037038002200041b0046a41386a221c2030290300370300200041b0046a41306a2235202f290300370300200041b0046a41286a2236202e290300370300200041b0046a41206a2237202d290300370300200041b0046a41186a22382013290300370300200041b0046a41106a223920012903003703002031200529030037030020002000290380053703b004200041e0036a41386a201c290300370300200041e0036a41306a2035290300370300200041e0036a41286a2036290300370300200041e0036a41206a2037290300370300200041e0036a41186a2038290300370300200041e0036a41106a2039290300370300200041e0036a41086a2031290300370300200020002903b0043703e003200041d0036a41086a200428020036020020002000290380023703d0030b200b200041e0036a41086a290300370300200a200041e0036a41106a2903003703002009200041e0036a41186a2903003703002021200041e0036a41206a2903003703002020200041e0036a41286a290300370300201f200041e0036a41306a290300370300201e200041e0036a41386a2903003703002015200041d0036a41086a280200360200200020002903e0033703a001200020002903d00337039001024020190d00200741016a21072014201841206a2218460d030c010b0b2023201e2903003703002024201f2903003703002025202029030037030020262021290300370300202720092903003703002028200a2903003703002029200b290300370300202a2015280200360200200020002903a001370340200020002903900137038001202b202a2802003602002000200029038001370330201841206a2118200741016a21070c000b0b02402012450d002011102c0b2000201d36029801200020223602940120002003360290010b20004180056a41186a2219420037030020004180056a41106a2217420037030020004180056a41086a221a42003703002000420037038005200041b0026a41086a220741ecddc500ad4280808080f0008422081002221841086a290000370300200020182900003703b0022018102c201a2007290300370300200020002903b00237038005200741f3ddc500ad4280808080c0018422061002221841086a290000370300200020182900003703b0022018102c200041e0036a41086a22162007290300220e370300200020002903b002221b3703e0032002201b370000200241086a2201200e370000200041b0046a41086a2204201a290300370300200041b0046a41106a22112017290300370300200041b0046a41186a2213201929030037030020002000290380053703b004200041206a200041b0046a41201094012000280224211c20002802202105200741a3dbc500ad4280808080800184220e1002221841086a290000370300200020182900003703b0022018102c20162007290300370300200020002903b0023703e003200741abdbc500ad4280808080a002841002221841086a290000370300200020182900003703b0022018102c20042007290300370300200020002903b0023703b0042000201c410020051b3602a001200041b0026a41186a221c200041a0016aad4280808080c00084221b1006221841186a290000370300200041b0026a41106a2205201841106a2900003703002007201841086a290000370300200020182900003703b0022018102c2019201c29030037030020172005290300370300201a2007290300370300200020002903b0023703800541c000102a2218450d00201820002903e003370000201820002903b0043700102018200029038005370020201841086a2016290300370000201841186a2004290300370000201841286a201a290300370000201841306a2017290300370000201841386a20192903003700002018ad4280808080800884100d2018102c2019420037030020174200370300201a42003703002000420037038005200720081002221841086a290000370300200020182900003703b0022018102c201a2007290300370300200020002903b00237038005200720061002221841086a290000370300200020182900003703b0022018102c201620072903002208370300200020002903b00222063703e00320022006370000200120083700002004201a290300370300201120172903003703002013201929030037030020002000290380053703b004200041186a200041b0046a4120109401200028021c2102200028021821012007200e1002221841086a290000370300200020182900003703b0022018102c20162007290300370300200020002903b0023703e00320074182aac500ad4280808080e001841002221841086a290000370300200020182900003703b0022018102c20042007290300370300200020002903b0023703b00420002002410020011b3602a001201c201b1006221841186a2900003703002005201841106a2900003703002007201841086a290000370300200020182900003703b0022018102c2019201c29030037030020172005290300370300201a2007290300370300200020002903b0023703800541c000102a2207450d0020104200200f1b210e200720002903e003370000200720002903b0043700102007200029038005370020200741086a200041e0036a41086a290300370000200741186a200041b0046a41086a290300370000200741286a20004180056a41086a2218290300370000200741306a20004180056a41106a290300370000200741386a20004180056a41186a2903003700002007ad4280808080800884100d2007102c0240024002400240201d450d0020004180056a20004190016a107c200041bb046a201828020036000020002000290380053700b3042000418c056a200041b7046a290000370000200041023a0084052000410f3a008005200020002900b004370085054101410020004180056a109201200041f8026a41106a20004190016a41086a2802003602002000200e422088a722393602fc022000200c4100200d1b22173602f802200020002903900137038003200041d0036a200041f8026a41086a107c20002802d803211c20002802d403213820002802d00321224104102a2212450d042012201736000020004284808080c0003702a401200020123602a001200041b0026a41086a220741bddbc500ad42808080808001841002221841086a290000370300200020182900003703b0022018102c200041e0036a41086a221a2007290300370300200020002903b0023703e003200741c5dbc500ad4280808080a002841002221841086a290000370300200020182900003703b0022018102c200041b0046a41086a22182007290300370300200020002903b0023703b00420004190026a41cffac00010ca0141c000102a2207450d04200720002903e003370000200720002903b0043700102007200029039002370020200741086a201a290300370000200741186a2018290300370000200741286a20004190026a41086a290300370000200741306a200041a0026a290300370000200741386a20004190026a41186a29030037000020004180056a200741c00010bd03200029028405210820002802800521182007102c20002008420020181b22064220883e02b40420002018410120181b22053602b004200041106a200041b0046a1075200028021421044100211620002802100d0320002802b404220741246e221d41246c2218417f4c0d010240024020180d00410421160c010b2018102a2216450d050b2004450d0341002102034020074104490d03200241016a210120002007417c6a221a3602b404200020002802b004221941046a3602b0042019280000211141002107200041003a00a00503400240201a2007470d00200041003602b404200741ff0171450d05200041003a00a0050c050b20004180056a20076a201920076a221841046a2d00003a00002000201841056a3602b0042000200741016a22183a00a0052018210720184120470d000b200041b0026a41086a221920004180056a41086a290300370300200041b0026a41106a221320004180056a41106a290300370300200041b0026a41186a221e20004180056a41186a29030037030020002000290380053703b0022000201a20186b22073602b4040240201d2002470d00200241017422182001201820014b1b221dad42247e2208422088a70d0a2008a722184100480d0a0240024020020d002018102a21160c010b2016200241246c2018102e21160b2016450d060b2016200241246c6a22182011360200201820002903b0023702042018410c6a2019290300370200201841146a20132903003702002018411c6a201e2903003702002001210220012004470d000c040b0b200041013a0084052000410f3a0080054101410020004180056a1092012022450d062003102c0c060b103a000b0240201d0d00410021160c010b2016102c410021160b20004180056a200041a0016a10c901200041b0046a200028028005221820002802880510d00120002802b004210720002902b40421080240200028028405450d002018102c0b2008420020071b210802402006a7450d002005102c0b201d410020161b21312016410420161b211d2007410120071b21362008a721350240024002400240024002400240201c450d002004410020161b21042008422088a721012022201c41d0006c6a210320004180056a410c6a211120004180056a41306a211e20004180056a41206a211f200041e0036a41c4006a210a200041a8046a21374100212c20222116034020004180056a41386a22182016220741386a290300370300201e200741306a29030037030020004180056a41286a221a200741286a290300370300201f200741206a29030037030020004180056a41186a221c200741186a29030037030020004180056a41106a2205200741106a29030037030020004180056a41086a2202200741086a29030037030020004180026a41086a2219200741cc006a28020036020020002007290300370380052000200741c4006a29020037038002200741d0006a2116200741c0006a2802002207450d02200041c0006a41386a22132018290300370300200041c0006a41306a2218201e290300370300200041c0006a41286a2220201a290300370300200041c0006a41206a221a201f290300370300200041c0006a41186a2221201c290300370300200041c0006a41106a22092005290300370300200041c0006a41086a220b200229030037030020004180016a41086a221520192802003602002000200029038005370340200020002903800237038001200041e0036a41386a2013290300370300200041e0036a41306a22192018290300370300200041e0036a41286a2020290300370300200041e0036a41206a2213201a290300370300200041e0036a41186a2021290300370300200041e0036a41106a2009290300370300200041e0036a41086a200b290300370300200020002903403703e003200020073602a004200a200029038001370200200a41086a20152802003602004104102a221a450d08201a2017360000201141002900cffa40370000201141086a41002900d7fa4037000020004284808080c000370284052000201a360280052000200041e0036a36029c054108102a2207450d08200042083702b404200020073602b0042011200041b0046a10ec024104200041b0046a10670240024020002802b404221820002802b80422076b4104490d0020002802b00421180c010b200741046a22202007490d0d201841017422072020200720204b1b22074100480d0d0240024020180d002007102a21180c010b20002802b00420182007102e21180b2018450d09200020073602b404200020183602b00420002802b80421070b2000200741046a3602b804201820076a201a280000360000200041e0036a200041b0046a109101200020133602a003200041a0036a200041b0046a108a01200020193602a003200041a0036a200041b0046a108a0120002802a004210720372802002218200041b0046a106702402018450d00201841306c21180340200741106a200041b0046a109101200020073602a003200741306a2107200041a0036a200041b0046a108a01201841506a22180d000b0b20002802b4042119200041b0026a41186a221320003502b80442208620002802b0042221ad841006220741186a290000370300200041b0026a41106a2220200741106a290000370300200041b0026a41086a2218200741086a290000370300200020072900003703b0022007102c200041a0016a41186a220b2013290300370300200041a0016a41106a22152020290300370300200041a0016a41086a22142018290300370300200020002903b0023703a00102402019450d002021102c0b201a102c201841bddbc500ad428080808080018422081002220741086a290000370300200020072900003703b0022007102c200041d0026a41086a22192018290300370300200020002903b0023703d002201841b7b9c000ad4280808080f0008422061002220741086a290000370300200020072900003703b0022007102c200041a0036a41086a22132018290300370300200020002903b0023703a003200041b0046a200041a0016a109f0141c000102a2207450d08200720002903d002370000200720002903a003370010200720002900b004370020200741086a2019290300370000200741186a2013290300370000200741286a200041b0046a41086a2220290000370000200741306a200041b0046a41106a2221290000370000200741386a200041b0046a41186a2209290000370000200041086a200741c0004101410041001097012000280208211a2007102c02400240201a4101470d0020002802a404450d0120002802a004102c0c010b200041b0046a200041e0036a41d00010db051a20004180056a200041b0046a41d00010db051a200041003602d805200042013703d005201820081002220741086a290000370300200020072900003703b0022007102c20192018290300370300200020002903b0023703d002201820061002220741086a290000370300200020072900003703b0022007102c20132018290300370300200020002903b0023703a003200041b0046a200041a0016a109f0141c000102a221a450d09201a20002903d002370000201a20002903a003370010201a20002900b004370020201a41086a2019290300370000201a41186a2013290300370000201a41286a2020290000370000201a41306a2021290000370000201a41386a2009290000370000200041003602b804200042013703b00420004180056a200041b0046a1091012000201f3602a003200041a0036a200041b0046a108a012000201e3602a003200041a0036a200041b0046a108a0120002802c005210720002802c8052218200041b0046a106702402018450d00201841306c21180340200741106a200041b0046a109101200020073602a003200741306a2107200041a0036a200041b0046a108a01201841506a22180d000b0b20002802d005210720002802d8052218200041b0046a106702402018450d002018410574211803402007200041b0046a109101200741206a2107201841606a22180d000b0b20002802b4042107201aad428080808080088420003502b80442208620002802b0042218ad84100102402007450d002018102c0b201a102c024020002802c405450d0020002802c005102c0b024020002802d405450d0020002802d005102c0b201c200b2903003703002005201529030037030020022014290300370300200020002903a0013703800541002107024002400240200441014b0d00024020040e020002000b200041e0016a41186a201c290300370300200041e0016a41106a2005290300370300200041e0016a41086a200229030037030020002000290380053703e001410021070c020b20042118034020072018410176221a20076a2219201d201941246c6a28020020174b1b21072018201a6b221841014b0d000b0b0240201d200741246c6a28020022182017460d00200720182017496a21070b200041e0016a41186a201c290300370300200041e0016a41106a2005290300370300200041e0016a41086a200229030037030020002000290380053703e001200420074f0d0041ecb3c000411e41acfec5001036000b024020042031470d00200441016a22182004490d0e2004410174221a2018201a20184b1b2231ad42247e2208422088a70d0e2008a722184100480d0e0240024020040d002018102a211d0c010b201d200441246c2018102e211d0b201d450d0a0b201d200741246c6a221841246a2018200420076b41246c10dc051a201820173602002018411c6a200041e0016a41186a290300370200201841146a200041e0016a41106a2903003702002018410c6a200041e0016a41086a290300370200201820002903e0013702042009201c290300370300202120052903003703002020200229030037030020002000290380053703b004024020012035470d00200141016a22072001490d0e200141017422182007201820074b1b223541ffffff3f712035470d0e203541057422074100480d0e0240024020010d002007102a21360c010b203620014105742007102e21360b2036450d0a0b200441016a2104203620014105746a220720002903b004370000200741186a2009290300370000200741106a2021290300370000200741086a20202903003700004101212c200141016a21010b20162003470d000b200321160c010b2038450d012022102c0c010b024020162003460d000340201641c0006a2802002218450d01201641d0006a21070240201641c4006a280200450d002018102c0b2007211620032007470d000b0b02402038450d002022102c0b202c410171450d0002402001450d002001410574211820362107034020004180056a200710cb0120002802c005221a0d03200741206a2107201841606a22180d000b0b4108211c41002105410021020c020b2012102c02402035450d002036102c0b2031450d02201d102c0c020b200041e0036a41386a221c20004180056a41386a2219290300370300200041e0036a41306a222020004180056a41306a2205290300370300200041e0036a41286a222120004180056a41286a2202290300370300200041e0036a41206a220920004180056a41206a2211290300370300200041e0036a41186a220a20004180056a41186a2213290300370300200041e0036a41106a220b20004180056a41106a221e290300370300200041e0036a41086a221520004180056a41086a221f290300370300200041a0036a41086a220320004180056a41cc006a290200370300200041a0036a41106a221420004180056a41d4006a290200370300200041a0036a41186a223720004180056a41dc006a28020036020020002000290380053703e0032000200041c4056a22162902003703a003200041c0006a41086a222c2015290300370300200041c0006a41106a2215200b290300370300200041c0006a41186a220b200a290300370300200041c0006a41206a220a2009290300370300200041c0006a41286a22092021290300370300200041c0006a41306a22212020290300370300200041c0006a41386a2220201c290300370300200041a0016a41086a221c2003290300370300200041a0016a41106a22032014290300370300200041a0016a41186a22142037280200360200200020002903e003370340200020002903a0033703a001201f202c290300370300201e20152903003703002013200b2903003703002011200a2903003703002002200929030037030020052021290300370300201920202903003703002000200029034037038005200041b0046a41086a2220201c290300370300200041b0046a41106a22212003290300370300200041b0046a41186a22092014280200360200200020002903a0013703b00441e000102a221c450d03201c200029038005370300201c201a360240201c20002903b004370244201c41386a2019290300370300201c41306a2005290300370300201c41286a2002290300370300201c41206a2011290300370300201c41186a2013290300370300201c41106a201e290300370300201c41086a201f290300370300201c41cc006a2020290300370200201c41d4006a2021290300370200201c41dc006a2009280200360200024020184120470d0041012105410121020c010b200741206a211f203620014105746a221a41606a211441012105410121020340201f21070240034020004180056a200710cb0120002802c00522180d01201a200741206a2207470d000c030b0b200041e0036a41386a221920004180056a41386a2220290300370300200041e0036a41306a221f20004180056a41306a2221290300370300200041e0036a41286a223720004180056a41286a2209290300370300200041e0036a41206a222c20004180056a41206a220a290300370300200041e0036a41186a221120004180056a41186a220b290300370300200041e0036a41106a221320004180056a41106a2215290300370300200041e0036a41086a221e20004180056a41086a2203290300370300200041a0036a41086a2222201641086a290200370300200041a0036a41106a2238201641106a290200370300200041a0036a41186a220c201641186a28020036020020002000290380053703e003200020162902003703a003200041b0046a41086a220d201e290300370300200041b0046a41106a222d2013290300370300200041b0046a41186a222e2011290300370300200041b0046a41206a222f202c290300370300200041b0046a41286a222c2037290300370300200041b0046a41306a2237201f290300370300200041b0046a41386a221f2019290300370300200041a0016a41086a22192022290300370300200041a0016a41106a22222038290300370300200041a0016a41186a2238200c280200360200200020002903e0033703b004200020002903a0033703a0012003200d2903003703002015202d290300370300200b202e290300370300200a202f2903003703002009202c290300370300202120372903003703002020201f290300370300200020002903b00437038005201e20192903003703002013202229030037030020112038280200360200200020002903a0013703e003024020022005470d00200541016a22192005490d09200541017422022019200220194b1b2202ad42e0007e2208422088a70d092008a722194100480d090240024020050d002019102a211c0c010b201c200541e0006c2019102e211c0b201c450d050b200741206a211f201c200541e0006c6a2219200029038005370300201941106a2015290300370300201941086a200329030037030020212903002108202029030021062009290300211b200a2903002110200b2903002132201941c0006a2018360200201941186a2032370300201941206a2010370300201941286a201b370300201941386a2006370300201941306a2008370300201941c4006a20002903e003370200201941cc006a201e290300370200201941d4006a2013290300370200201941dc006a2011280200360200200541016a210520142007470d000b0b200041a0056a20043602002000419c056a203136020020004190056a2001ad4220862035ad843703002000203636028c0520004284808080c0003702840520002012360280052000201d36029805200041003602b804200042013703b0042004200041b0046a106702402004450d00201d200441246c6a2104201d21180340201828020021190240024020002802b404221a20002802b80422076b4104490d0020002802b004211a0c010b200741046a22162007490d09201a41017422072016200720164b1b22074100480d0902400240201a0d002007102a211a0c010b20002802b004201a2007102e211a0b201a450d05200020073602b4042000201a3602b00420002802b80421070b2000200741046a3602b804201a20076a20193600002000200041b0046a3602e003201841046a200041e0036a109402201841246a22182004470d000b0b20002802b804211920002802b404211620002802b004211a200041b0026a41086a220741bddbc500ad42808080808001841002221841086a290000370300200020182900003703b0022018102c200041e0036a41086a22042007290300370300200020002903b0023703e003200741c5dbc500ad4280808080a002841002221841086a290000370300200020182900003703b0022018102c200041b0046a41086a22182007290300370300200020002903b0023703b00420004190026a41cffac00010ca0141c000102a2207450d02200720002903e003370000200720002903b0043700102007200029039002370020200741086a2004290300370000200741186a2018290300370000200741286a20004190026a41086a290300370000200741306a200041a0026a290300370000200741386a20004190026a41186a290300370000200041c0003602b404200020073602b004201a2019200041b0046a10f1022007102c02402016450d00201a102c0b200041e0036a20004180056a10c90120003502e803210820002802e003211a200041003602b804200042013703b0042001200041b0046a106702402001450d00200141057421182036210703402000200041b0046a3602a0012007200041a0016a109402200741206a2107201841606a22180d000b0b20002802b40421072008422086201aad8420003502b80442208620002802b0042218ad84100102402007450d002018102c0b024020002802e403450d00201a102c0b2012102c02402035450d002036102c0b02402031450d00201d102c0b201c0d010b200028028003211a024020004188036a2802002207450d00200741d0006c2118201a41c0006a210703400240200741046a280200450d002007280200102c0b200741d0006a2107201841b07f6a22180d000b0b20004184036a280200450d04201a102c0c040b4104102a2207450d002007201736000020004188056a4284808080c0003703004100211a20004198056a41002900d7fa40370300200041103a00800520004180056a41106a41002900cffa4037030020002007360284054101410020004180056a10920102402039410a6e417f7320056a221820054b0d002000418094ebdc0336028405200020394101203941014b1b2207201841036c221820072018491b2007418094ebdc036e22184101201841014b1b22186ead428094ebdc037e200720186ead8042ffffffff0f834280bbb0217e428094ebdc0380a722073602800520004180056a2007418094ebdc034b4102746a280200211a0b2005450d01200541ffffffff03712005470d04200541027422074100480d042007102a2219450d00200521182019210703402007201a360200200741046a21072018417f6a22180d000b201c200520192005201710a60402402005450d002019102c0b2005450d02200541e0006c2118201c41d4006a210703400240200741706a280200450d002007416c6a280200102c0b02402007280200450d002007417c6a280200102c0b200741e0006a2107201841a07f6a22180d000c030b0b1033000b201c410041044100201710a6040b02402002450d00201c102c0b200028028003211a024020004188036a2802002207450d00200741d0006c2118201a41c0006a210703400240200741046a280200450d002007280200102c0b200741d0006a2107201841b07f6a22180d000b0b20004184036a280200450d00201a102c0b0240200ea7450d00200f4101200f1b102c0b20004180066a24000f0b1035000ba60901077f230041d0026b2202240041002103200241003a002820012802042104417f210502400240034020042003460d01200241086a20036a200128020022062d00003a00002001200420056a3602042001200641016a3602002002200341016a22073a00282005417f6a21052007210320074120470d000b20024188016a41086a200241086a41086a29030037030020024188016a41106a200241086a41106a29030037030020024188016a41186a200241086a41186a290300370300200220022903083703880141002108200241003a0028200420076b2107200420056a21030340024020072008470d000240200841ff0171450d00200241003a00280b200041013a00000c030b200241086a20086a200620086a220541016a2d00003a0000200120033602042001200541026a3602002002200841016a22053a00282003417f6a21032005210820054120470d000b200241a8016a41086a200241086a41086a290300370300200241a8016a41106a200241086a41106a290300370300200241a8016a41186a200241086a41186a290300370300200220022903083703a80141002107200241003a0028200620056a2108034002402003417f470d000240200741ff0171450d00200241003a00280b200041013a00000c030b200241086a20076a200820076a220541016a2d00003a0000200120033602042001200541026a3602002002200741016a22053a00282003417f6a21032005210720054120470d000b200241c8016a41086a200241086a41086a290300370300200241c8016a41106a200241086a41106a290300370300200241c8016a41186a200241086a41186a290300370300200220022903083703c80141002107200241003a00c802200820056a41016a2105034002402003417f470d000240200741ff0171450d00200241003a00c8020b200041013a00000c030b200241a8026a20076a20052d00003a0000200120033602042001200541016a22053602002002200741016a22083a00c8022003417f6a21032008210720084120470d000b200241e8016a41086a2201200241a8026a41086a290300370300200241e8016a41106a2203200241a8026a41106a290300370300200241e8016a41186a2205200241a8026a41186a290300370300200241086a41086a20024188016a41086a290300370300200241086a41106a20024188016a41106a290300370300200241086a41186a20024188016a41186a290300370300200220022903a8023703e8012002200229038801370308200241c0006a200241a8016a41186a290300370300200241386a200241a8016a41106a290300370300200241306a200241a8016a41086a290300370300200220022903a801370328200241e0006a200241c8016a41186a290300370300200241d8006a200241c8016a41106a290300370300200241d0006a200241c8016a41086a290300370300200220022903c80137034820024180016a2005290300370300200241f8006a2003290300370300200241f0006a2001290300370300200220022903e801370368200041016a200241086a41800110db051a200041003a00000c010b0240200341ff0171450d00200241003a00280b200041013a00000b200241d0026a24000bca8c020f057f017e017f017e097f017e037f017e017f027e017f037e017f157e167f230041e00e6b22022400200241900e6a41186a22034200370300200241900e6a41106a22044200370300200241900e6a41086a22054200370300200242003703900e200241c80d6a41086a22064196e0c500ad4280808080f0008422071002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22093703e80c200220093703900e200641a7e0c500ad4280808080b003841002220841086a290000370300200220082900003703c80d2008102c200420022903c80d2209370300200241880b6a41086a220a2005290300370300200241880b6a41106a220b2009370300200241880b6a41186a220c2006290300370300200220093703a80d200220022903900e3703880b200241c80a6a200241880b6a412010940120022802cc0a210d20022802c80a210e200342003703002004420037030020054200370300200242003703900e200620071002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22093703e80c200220093703900e200641d8e0c500ad42808080808001841002220841086a290000370300200220082900003703c80d2008102c200320062903002209370300200a2005290300370300200b20022903c80d2207370300200c2009370300200220073703a80d200220022903900e3703880b02400240024002404100200241880b6a10ec032206200641ff01714104461b41ff0171220641034b0d00024020060e0400020103000b2001200d4100200e1b6b220620014b0d00200641064f0d020b200041003602000c020b200241900e6a41186a22084200370300200241900e6a41106a220a4200370300200241900e6a41086a22054200370300200242003703900e200241c80d6a41086a22064196e0c500ad4280808080f000841002220341086a290000370300200220032900003703c80d2003102c20052006290300370300200220022903c80d22093703e80c200220093703900e200641d8e0c500ad42808080808001841002220341086a290000370300200220032900003703c80d2003102c200241a80d6a41086a20062903002209370300200220022903c80d22073703a80d20042007370000200441086a2009370000200241880b6a41086a2005290300370300200241880b6a41106a200a290300370300200241880b6a41186a2008290300370300200220022903900e3703880b200241880b6aad428080808080048410050b200241e80b6a41186a4200370300200241e80b6a41106a220f420037030041082110200241e80b6a41086a22054200370300200242003703e80b200241c80d6a41086a220641ecddc500ad4280808080f000841002220441086a290000370300200220042900003703c80d2004102c20052006290300370300200220022903c80d3703e80b200641c9f8c200ad4280808080a001841002220441086a290000370300200220042900003703c80d2004102c200f20022903c80d2209370300200241880b6a41086a2005290300370300200241880b6a41106a2009370300200241880b6a41186a2006290300370300200220093703a80d200220022903e80b3703880b200241e80b6a200241880b6a412010d0014100211141002112024002400240024020022902ec0b420020022802e80b22061b2209422088a722054105742204450d0020044105752212ad42d0007e2207422088a70d032007a722044100480d032004102a2210450d010b2009a7210d2006410120061b210c02402005450d002005410574220441606a210e200241e80b6a41206a210620102103200c21050340200541086a2900002109200541106a290000210720052900002113200241880b6a41186a2208200541186a290000370300200241880b6a41106a220a2007370300200241880b6a41086a220b2009370300200220133703880b200241b00b6a200241880b6a109204200241e80b6a41186a2008290300370300200241e80b6a41106a200a290300370300200241e80b6a41086a200b290300370300200620022903b00b370300200641086a200241b00b6a41086a290300370300200641106a200241b00b6a41106a290300370300200641186a200241b00b6a41186a290300370300200641206a200241b00b6a41206a290300370300200641286a200241b00b6a41286a290300370300200220022903880b3703e80b2003200241e80b6a41d00010db0541d0006a2103200541206a2105200441606a22040d000b200e41057641016a21110b0240200d450d00200c102c0b200241880b6a41186a22044200370300200241880b6a41106a22144200370300200241880b6a41086a22054200370300200242003703880b200241c80d6a41086a22064196e0c500ad4280808080f0008422091002220341086a290000370300200220032900003703c80d2003102c20052006290300370300200220022903c80d22073703e80c200220073703880b200641c2e0c500ad4280808080e002841002220341086a290000370300200220032900003703c80d2003102c201420022903c80d2207370300200241e80b6a41086a22032005290300370300200241e80b6a41106a22082007370300200241e80b6a41186a220a2006290300370300200220073703a80d200220022903880b3703e80b200241b00b6a200241e80b6a10e403410021150240024020022802b40b22160d004104211642002117410021180c010b200241e80b6aad4280808080800484100520022802b00b211820022903b80b21170b200a42003703002008420037030020034200370300200242003703e80b200641f9e8c500ad42808080809001841002220b41086a2900003703002002200b2900003703c80d200b102c20032006290300370300200220022903c80d3703e80b2006419db1c200ad428080808030841002220b41086a2900003703002002200b2900003703c80d200b102c200241a80d6a41086a220b20062903002207370300200220022903c80d22133703a80d200f2013370000200f41086a200737000020052003290300370300201420082903003703002004200a290300370300200220022903e80b3703880b200241b80a6a200241880b6a10980120022903c00a210720022802b80a210d200442003703002014420037030020054200370300200242003703880b200620091002220c41086a2900003703002002200c2900003703c80d200c102c20052006290300370300200220022903c80d22133703e80c200220133703880b200641e6f8c200ad4280808080f0018422131002220c41086a2900003703002002200c2900003703c80d200c102c200b20062903002219370300200220022903c80d221a3703a80d2014201a370000201441086a220e20193700002003200529030037030020082014290300370300200a2004290300370300200220022903880b3703e80b200241a80a6a200241e80b6a10980120022903b00a211920022802a80a211b200442003703002014420037030020054200370300200242003703880b200620091002220c41086a2900003703002002200c2900003703c80d200c102c20052006290300370300200220022903c80d22093703e80c200220093703880b200620131002220c41086a2900003703002002200c2900003703c80d200c102c200b20062903002209370300200220022903c80d22133703a80d20142013370000200e20093700002003200529030037030020082014290300370300200a2004290300370300200220022903880b3703e80b200220074200200d1b22093703b00b200241e80b6aad221c4280808080800484221d200241b00b6aad221e428080808080018410010240200920194200201b1b7d2213500d00200241e80b6a41186a22044200370300200241e80b6a41106a22034200370300200241e80b6a41086a22054200370300200242003703e80b200241c80d6a41086a22064196e0c500ad4280808080f0008422091002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d3703e80b200641bafdc200ad4280808080e001841002220841086a290000370300200220082900003703c80d2008102c200241a80d6a41086a220d20062903002207370300200220022903c80d22193703a80d200f2019370000200f41086a221f2007370000200241880b6a41086a22082005290300370300200241880b6a41106a220a2003290300370300200241880b6a41186a220b2004290300370300200220022903e80b3703880b200241e80b6a200241880b6a412010d00120022802e80b210c20022902ec0b2119200b4200370300200a420037030020084200370300200242003703880b200620091002220e41086a2900003703002002200e2900003703c80d200e102c20082006290300370300200220022903c80d22093703e80c200220093703880b200641c8fdc200ad42808080809001841002220e41086a2900003703002002200e2900003703c80d200e102c200d20062903002209370300200220022903c80d22073703a80d20142007370000201441086a2009370000200520082903003703002003200a2903003703002004200b290300370300200220022903880b3703e80b200241900a6a200241e80b6a4120109e01200241900a6a41106a290300211a20022903980a212020022802900a210e200442003703002003420037030020054200370300200242003703e80b2006418be9c500ad42808080808001841002221b41086a2900003703002002201b2900003703c80d201b102c20052006290300370300200220022903c80d3703e80b200641c9b5c000ad4280808080d001841002221b41086a2900003703002002201b2900003703c80d201b102c200d20062903002209370300200220022903c80d22073703a80d200f2007370000201f200937000020082005290300370300200a2003290300370300200b2004290300370300200220022903e80b3703880b200241f8096a200241880b6a4120109e01200241e8096a20022903800a420020022802f80922061b2207200241f8096a41106a290300420020061b2209428094ebdc03420010e105200241c8096a20204200200e1b201a4200200e1b20194200200c1b22214220882222420010e005200241d8096a20022903e809221a200241e8096a41086a29030022204280ec94a37c427f10e0052009200241c8096a41086a290300221920022903c8092223200756201920095620192009511b22061b21092007202320061b212320022903d80920077c21192022a721032013428086ebc7f5002013428086ebc7f500541b421f8042ffffffff0f83428094ebdc037e429880b5e50380212241012105200c4101200c1b211f41d87d21060240024003402006450d01200241b8096a201a2020200641ccf0c1006a3502002207420010e0052005417f6a2105200641086a2106202320022903b8092213200720197e22072007428094ebdc038022074280ec94a37c7e7c4280cab5ee01562007a76aad7c2207542009200241b8096a41086a2903002007201354ad7c22075420092007511b2204450d000b0240200441016a41017120056b2206417f6a220520064d0d00200241b8086a201a202042c0f0f50b420010e005200241c0086a29030020022903b8082207201942c0f0f50b7e201942288022094280ec94a37c7e7c4280cab5ee01562009a76aad7c2209200754ad7c21130c020b0240200541244b0d00200241a8096a201a20202005410374220441a4eec1006a2802002208ad2207420010e00520024188096a202320022903a8092213200720197e22072007428094ebdc038022074280ec94a37c7e7c4280cab5ee01562007a76aad7c220720232007562009200241a8096a41086a2903002007201354ad7c22135620092013511b22051b22242007202320051b22077d22232009201320051b2013200920051b7d2024200754ad7d41002006410374220a41a4eec1006a280200220620086b2208200820064b1b22064101200641014b1bad2209420010e105200241f8086a200229038809220720024188096a41086a29030022242009420010e00520024198096a201a2020200441a8eec1006a2802002206ad2225420010e005200241c8086a20244200200a41a8eec1006a28020022042006200420064b22081b2006200420081b6bad2213420010e005200241e8086a200742002013420010e005200241d8086a420042002007420010e005427f427f200241e8086a41086a290300220720022903c80820022903d8087c7c222420022903d00820022903e0088442005220242007547222081b2224427f20022903e80820081b2207202320022903f8087d20137e2009807c22092007542208ad7c221320082013202454200920075a1b22081b2123427f200920081b211320024198096a41086a2903002002290398092209202520197e22072007428094ebdc038022074280ec94a37c7e7c4280cab5ee01562007a76aad7c2207200954ad7c210902402005200420064d730d004200200920237d2007201354ad7d2223200720137d2224200756202320095620232009511b22061b21134200202420061b21090c030b427f200920237c200720137c22232007542206ad7c22072006200720095420072009511b22061b2113427f202320061b21090c020b41b8a9c500200541251038000b200241a8086a201a202042e8aafa0b420010e005200241b0086a29030020022903a8082207201942e8aafa0b7e22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76aad7c2209200754ad7c21130b42002126200241e8076a201a20204280c2d72f420010e005200241d8076a20022903e807221a20194280c2d72f7e2019420a8022074280ec94a37c7e7c4280cab5ee01562007a76aad7c2207200241e8076a41086a2903002007201a54ad7c428094ebdc03420010e10520024198086a20092013428094ebdc03420010e105200241c8076a20022903d8072213200241d8076a41086a29030022194280ec94a37c427f10e005200241b8076a201320192022420010e00520024188086a200229039808221320024198086a41086a29030022194280ec94a37c427f10e005200241f8076a201320192022420010e0052022200720022903c8077c7e2227428094ebdc0380212820022903b8072129200241b8076a41086a290300212a202220092002290388087c7e2207428094ebdc038021090240024020030d004200212b0c010b201f20034105746a210e20162017422088a74102746a210d200241a8076a20022903f8072213200720094280ec94a37c7e7c4280cab5ee01562009a76aad7c2209200241f8076a41086a2903002009201354ad7c428094ebdc03420010e10520024198076a20022903a807222c200241a8076a41086a290300222d4280ec94a37c427f10e00520184101201841014b1b220a418094ebdc036e22064101200641014b1b210b20092002290398077c212e200241880b6a41106a2118420021264200212b20162103201f21080240024002400240024003402003200d460d060240024020032802002206450d0020024188076a202c202d200a2006200a2006491b200b6ead428094ebdc037e200a200b6ead8042ffffffff0f832209420010e005200241c80d6a41086a22064196e0c500ad4280808080f000841002220541086a290000370300200220052900003703c80d2005102c200241e80c6a41086a22042006290300370300200220022903c80d3703e80c200641c9f8c200ad4280808080a001841002220541086a290000370300200220052900003703c80d2005102c200241a80d6a41086a22052006290300370300200220022903c80d3703a80d200241880b6a2008109f012009202e7e2213428094ebdc03802109200229038807210720024188076a41086a290300211941c000102a2206450d0a20192007201320094280ec94a37c7e7c4280cab5ee01562009a76aad7c2209200754ad7c2107200620022903e80c370000200641086a2004290300370000200620022903a80d370010200641186a2005290300370000200620022903880b370020200641286a200241880b6a41086a290300370000200641306a2018290300370000200641386a200241880b6a41186a290300370000200241c0003602b40e200220063602b00e200241880b6a2006ad42808080808008841003108d010240024020022802880b22050d00410021040c010b200228028c0b211b200220022802900b3602e40a200220053602e00a20024180076a200241e00a6a1075024002402002280280070d00200228028407210c410121040c010b200241003602b80b200242013703b00b2002410b3602ec0d2002200241b00e6a3602e80d2002200241b00b6a3602900e200241013602fc0b200242013702ec0b200241d0b0c2003602e80b2002200241e80d6a3602f80b200241900e6a41c49ac500200241e80b6a10391a20023502b80b42208620023502b00b841004024020022802b40b450d0020022802b00b102c0b410021040b201b450d002005102c0b42002113200241f0066a20092007428094ebdc03420010e105200241e0066a20022903f0062219200241f0066a41086a290300221a4280ec94a37c427f10e005200241d0066a2019201a200c410020041bad2220420010e0052006102c200242003703b80b200242003703b00b024002404200200920022903d00622192020200920022903e0067c7e221a201a428094ebdc0380221a4280ec94a37c7e7c4280cab5ee0156201aa76aad7c222f7d221a201a2009562007200241d0066a41086a290300202f201954ad7c22307d2009202f54ad7d220920075620092007511b22061b22314200200920061b22328450450d00420021090c010b200241e80b6a2008109204200241c0066a20022903e80b220942012009420156200241e80b6a41086a29030022094200522009501b22061b22132009420020061b2209428094ebdc03420010e10520022802880c210c200241c0066a41086a290300213320022903c0062134024020022802900c2206450d00200241b0066a2013200920344201203442015620334200522033501b22051b221a2033420020051b222010e10520024190066a20312032428094ebdc03420010e105200241a0066a20312032428094ebdc03420010e20520022903b006220742ffffffff0f56200241b0066a41086a29030022194200522019501b0d032007a7450d05200c200641306c6a2104200742ffffffff0f83212320024190066a41086a2903002122200229039006212420022903a0062125200c2106034020024180066a20132006290300220720132007542009200641086a29030022075420092007511b22051b2009200720051b201a202010e105200229038006220742808080801054410020024180066a41086a290300501b450d0a200241d8056a20242022200742ffffffff0f83428094ebdc037e20238042ffffffff0f832207420010e005200241e8056a200641106a20022903d8052219200720257e22072007428094ebdc038022074280ec94a37c7e7c4280cab5ee01562007a76aad7c2207200241d8056a41086a2903002007201954ad7c109304200241b00b6a20022903e80520022903f005200241e8056a41106a290300108202200641306a22062004470d000b0b200241b8056a2013200920344201203442015620334200522033501b22061b221a2033420020061b222010e10520022903b8052207428080808010544100200241b8056a41086a290300501b450d05200241a8056a201320022903f80b221920132019542009200241e80b6a41186a29030022195420092019511b22061b2009201920061b201a202010e10520022903a8052209428080808010544100200241a8056a41086a290300501b450d062007a7450d0720024198056a20312032428094ebdc03420010e10520024188056a200229039805221320024198056a41086a29030022194280ec94a37c427f10e005200241f8046a20132019200942ffffffff0f83428094ebdc037e200742ffffffff0f838042ffffffff0f832209420010e00520022903f8042207200920312002290388057c7e22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76aad7c2213200754ad2109200241f8046a41086a29030021070240200228028c0c450d00200c102c0b200720097c21090b200241e0046a20082013202f7c2207200920307c2007201354ad7c109304200241b00b6a20022903e00420022903e804200241e0046a41106a290300108202427f202b200241b00b6a41086a2903007c202620022903b00b7c22072026542206ad7c220920062009202b542009202b511b22061b212b427f200720061b21260b200341046a2103200841206a2208200e470d010c070b0b2002411136028c0b200241f9e2c3003602880b41a7e1c30041e000200241880b6a4184ebc300103b000b200241c8056a2013200c290300220720132007542009200c41086a29030022075420092007511b22061b2009200720061b201a202010e10520022903c805428080808010544100200241c8056a41086a290300501b450d0341e0e2c30041194188e2c3001036000b2002411136028c0b200241f9e2c3003602880b41a7e1c30041e000200241880b6a4184ebc300103b000b2002411136028c0b200241f9e2c3003602880b41a7e1c30041e000200241880b6a4184ebc300103b000b41e0e2c30041194188e2c3001036000b2002411136028c0b200241f9e2c3003602880b41a7e1c30041e000200241880b6a4184ebc300103b000b202a2029202720284280ec94a37c7e7c4280cab5ee01562028a76aad7c2209202954ad7c210702402017a7450d002016102c0b200241e80b6a41186a202b370300200241e80b6a41106a2026370300200241e80b6a41086a41003a0000200241900c6a42002007202b7d2009202654ad7d2213200920267d2219200956201320075620132007511b22061b2207370300200241e80b6a41206a4200201920061b2213370300200241043a00e80b41014100200241e80b6a109201200241c8046a2026202b10ce01200241c8046a41106a290300211920022903d004211a02400240024020022903c8042209a7450d00200241880d6a41186a22044200370300200241880d6a41106a22034200370300200241880d6a41086a22054200370300200242003703880d200241c80d6a41086a2206418be9c500ad428080808080018422201002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22093703e80b200220093703880d200641c9b5c000ad4280808080d0018422231002220841086a290000370300200220082900003703c80d2008102c200320022903c80d2209370300200241e80c6a41086a220a2005290300370300200241e80c6a41106a220b2009370300200241e80c6a41186a220c2006290300370300200220093703880b200220022903880d3703e80c200241b0046a200241e80c6a4120109e01200241b0046a41106a290300210920022903b804212220022802b0042108200442003703002003420037030020054200370300200242003703880d200620201002220341086a290000370300200220032900003703c80d2003102c20052006290300370300200220022903c80d22203703e80b200220203703880d200620231002220341086a290000370300200220032900003703c80d2003102c200420062903002220370300200a2005290300370300200b20022903c80d2223370300200c2020370300200220233703880b200220022903880d3703e80c2002427f2009420020081b220920197c2022420020081b2219201a7c221a2019542206ad7c22192006201920095420192009511b22061b3703f00b2002427f201a20061b3703e80b200241e80b6a2106200241e80c6a21050c010b2009500d01200241880d6a41186a22044200370300200241880d6a41106a22034200370300200241880d6a41086a22054200370300200242003703880d200241c80d6a41086a2206418be9c500ad428080808080018422201002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22093703e80b200220093703880d200641c9b5c000ad4280808080d0018422231002220841086a290000370300200220082900003703c80d2008102c200320022903c80d2209370300200241e80c6a41086a220a2005290300370300200241e80c6a41106a220b2009370300200241e80c6a41186a220c2006290300370300200220093703880b200220022903880d3703e80c20024198046a200241e80c6a4120109e0120024198046a41106a290300210920022903a00421222002280298042108200442003703002003420037030020054200370300200242003703880d200620201002220341086a290000370300200220032900003703c80d2003102c20052006290300370300200220022903c80d22203703e80b200220203703880d200620231002220341086a290000370300200220032900003703c80d2003102c200420062903002220370300200a2005290300370300200b20022903c80d2223370300200c2020370300200220233703880b200220022903880d3703e80c2002427f2009420020081b220920197c2022420020081b2219201a7c221a2019542206ad7c22192006201920095420192009511b22061b3703f00b2002427f201a20061b3703e80b200241e80b6a2106200241e80c6a21050b2005ad42808080808004842006ad428080808080028410010b200241e80b6a41186a22044200370300200241e80b6a41106a22034200370300200241e80b6a41086a22054200370300200242003703e80b200241c80d6a41086a2206418be9c500ad428080808080018422201002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22093703b00b200220093703e80b200641c9b5c000ad4280808080d0018422231002220841086a290000370300200220082900003703c80d2008102c200241a80d6a41086a220b20062903002209370300200220022903c80d22193703a80d200f2019370000200f41086a220c2009370000200241880b6a41086a220d2005290300370300200241880b6a41106a220e2003290300370300200241880b6a41186a221b2004290300370300200220022903e80b3703880b20024180046a200241880b6a4120109e0120024180046a41106a290300210920022903880421192002280280042108200442003703002003420037030020054200370300200242003703e80b200620201002220a41086a2900003703002002200a2900003703c80d200a102c20052006290300370300200220022903c80d221a3703b00b2002201a3703e80b200620231002220a41086a2900003703002002200a2900003703c80d200a102c200b2006290300221a370300200220022903c80d22223703a80d200f2022370000200c201a370000200d2005290300370300200e2003290300370300201b2004290300370300200220022903e80b3703880b2002427f2009420020081b220920077c2019420020081b221920137c22222019542208ad7c221a2008201a200954201a2009511b22081b3703f00b2002427f202220081b3703e80b200241880b6aad4280808080800484201c4280808080800284221a1001024002402019427f85201320081b22132009427f85200720081b2209844200520d00200241880d6a41186a22044200370300200241880d6a41106a22034200370300200241880d6a41086a22054200370300200242003703880d200620201002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22093703e80b200220093703880d200620231002220841086a290000370300200220082900003703c80d2008102c200320022903c80d2209370300200241e80c6a41086a220a2005290300370300200241e80c6a41106a220b2009370300200241e80c6a41186a220c2006290300370300200220093703880b200220022903880d3703e80c200241e8036a200241e80c6a4120109e01200241e8036a41106a290300210920022903f003210720022802e8032108200442003703002003420037030020054200370300200242003703880d200620201002220341086a290000370300200220032900003703c80d2003102c20052006290300370300200220022903c80d22133703e80b200220133703880d200620231002220341086a290000370300200220032900003703c80d2003102c200420062903002213370300200a2005290300370300200b20022903c80d2219370300200c2013370300200220193703880b200220022903880d3703e80c20022009420020081b3703f00b20022007420020081b3703e80b200241e80c6aad4280808080800484201a10010c010b200241e80b6a10ae02200241e80b6a20132009109c012004200937030020032013370300200541053a00002002410c3a00e80b41014100200241e80b6a1092010b410121152021a7450d00201f102c0b200241880b6a41186a22044200370300200241880b6a41106a22034200370300200241880b6a41086a22054200370300200242003703880b200241c80d6a41086a22064196e0c500ad4280808080f0008422091002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22073703e80c200220073703880b2006419de0c500ad4280808080a0018422071002220841086a290000370300200220082900003703c80d2008102c200241a80d6a41086a220820062903002213370300200220022903c80d22193703a80d20142019370000201441086a220a2013370000200241e80b6a41086a220b2005290300370300200241e80b6a41106a220c2003290300370300200241e80b6a41186a220d2004290300370300200220022903880b3703e80b200241e0036a200241e80b6a412010940120022802e403211b20022802e0032118200442003703002003420037030020054200370300200242003703880b200620091002220e41086a2900003703002002200e2900003703c80d200e102c20052006290300370300200220022903c80d22133703e80c200220133703880b200620071002220e41086a2900003703002002200e2900003703c80d200e102c200820062903002207370300200220022903c80d22133703a80d20142013370000200a2007370000200b2005290300370300200c2003290300370300200d2004290300370300200220022903880b3703e80b2002201b410020181b221b41016a22353602b00b201d201e4280808080c0008422071001200442003703002003420037030020054200370300200242003703880b200620091002220e41086a2900003703002002200e2900003703c80d200e102c20052006290300370300200220022903c80d22133703e80c200220133703880b200641a7e0c500ad4280808080b0038422131002220e41086a2900003703002002200e2900003703c80d200e102c200820062903002219370300200220022903c80d221a3703a80d2014201a370000200a2019370000200b2005290300370300200c2003290300370300200d2004290300370300200220022903880b3703e80b200241d8036a200241e80b6a4120109401200442003703002003420037030020054200370300200242003703880b200620091002220e41086a2900003703002002200e2900003703c80d200e102c20052006290300370300200220022903c80d22193703e80c200220193703880b200620131002220e41086a2900003703002002200e2900003703c80d200e102c200820062903002213370300200220022903c80d22193703a80d20142019370000200a2013370000200b2005290300370300200c2003290300370300200d2004290300370300200220022903880b3703e80b200220013602b00b201d20071001200442003703002003420037030020054200370300200242003703880b200620091002220e41086a2900003703002002200e2900003703c80d200e102c20052006290300370300200220022903c80d22093703e80c200220093703880b200641f3e0c500ad4280808080a001841002220e41086a2900003703002002200e2900003703c80d200e102c200820062903002209370300200220022903c80d22073703a80d20142007370000200a2009370000200b2005290300370300200c2003290300370300200d2004290300370300200220022903880b3703e80b200241b00b6a200241e80b6a10eb0320022802b00b2206410420061b2118024020022902b40b420020061b22094220882207a722062009a7470d00200641016a22052006490d032007a722034101742204200520052004491b220541ffffffff01712005470d03200541037422044100480d030240024020060d002004102a21180c010b201820034103742004102e21180b2018450d012009422088a721062005ad21090b201820064103746a2205200136020420052035360200200942ffffffff0f832113200641016a213602400240203541a1054f0d0020132036ad4220868421130c010b2036450d00201b41e17a6a2104200641037441086a2105410021372018210602400340200628020020044f0d01200641086a2106203741016a2137200541786a22050d000b0b0240024020362037490d00024020370d00410021060c020b2037410374211f201e4280808080c0008421092018211b0340201b2802002101200241c80d6a41086a22054196e0c500ad4280808080f0008422071002220641086a290000370300200220062900003703c80d2006102c200241e80b6a41086a22042005290300370300200220022903c80d3703e80b200541f5f8c200ad4280808080b002841002220641086a290000370300200220062900003703c80d2006102c200241880b6a41086a22032005290300370300200220022903c80d3703880b200220013602b00b200241880d6a41186a220820091006220641186a290000370300200241880d6a41106a220a200641106a290000370300200241880d6a41086a220b200641086a290000370300200220062900003703880d2006102c200241e80c6a41186a220c2008290300370300200241e80c6a41106a220d200a290300370300200241e80c6a41086a220e200b290300370300200220022903880d3703e80c41c000102a2206450d04200620022903e80b370000200641086a2004290300370000200620022903880b370010200641186a2003290300370000200620022903e80c370020200641286a200e290300370000200641306a200d290300370000200641386a200c2903003700002006ad4280808080800884100d2006102c200520071002220641086a290000370300200220062900003703c80d2006102c20042005290300370300200220022903c80d3703e80b20054188f9c200ad4280808080b002841002220641086a290000370300200220062900003703c80d2006102c20032005290300370300200220022903c80d3703880b200220013602b00b200820091006220641186a290000370300200a200641106a290000370300200b200641086a290000370300200220062900003703880d2006102c200c2008290300370300200d200a290300370300200e200b290300370300200220022903880d3703e80c41c000102a2206450d04201b41086a211b200620022903e80b370000200641086a2004290300370000200620022903880b370010200641186a2003290300370000200620022903e80c370020200641286a200e290300370000200641306a200d290300370000200641386a200c2903003700002006ad4280808080800884100d2006102c201f41786a221f0d000b203721060c010b41dafec500411c41acfec5001036000b203620376b221f450d0002402006450d002018201820064103746a201f41037410dc051a0b20182802042136200241e80c6a41186a22374200370300200241e80c6a41106a220e4200370300200241e80c6a41086a221b4200370300200242003703e80c200241c80d6a41086a220341ecddc500ad4280808080f00084221a1002220641086a290000370300200220062900003703c80d2006102c201b2003290300370300200220022903c80d22093703e80b200220093703e80c200341e1ddc500ad4280808080b0018422201002220641086a290000370300200220062900003703c80d2006102c200e20022903c80d2209370300200241a80d6a41086a2238201b290300370300200241a80d6a41106a22392009370300200241a80d6a41186a223a2003290300370300200220093703880b200220022903e80c3703a80d200241e80b6a200241a80d6a10e4014101210420022902ec0b21190240024020022802e80b22064101460d00200641014621040c010b2019422088a7223b20362036203b4b1b22012019a72205490d000240200120054d0d00201e4280808080c00084210941ecddc500ad4280808080f0008421070340200241c80d6a41086a220620071002220441086a290000370300200220042900003703c80d2004102c200241e80b6a41086a22082006290300370300200220022903c80d3703e80b200641a1c6c100ad4280808080a002841002220441086a290000370300200220042900003703c80d2004102c200241880b6a41086a22042006290300370300200220022903c80d3703880b200220053602b00b200241880d6a41186a220a20091006220641186a290000370300200241880d6a41106a220b200641106a290000370300200241880d6a41086a220c200641086a290000370300200220062900003703880d2006102c200241e80c6a41186a220d200a290300370300200241e80c6a41106a220a200b290300370300200241e80c6a41086a220b200c290300370300200220022903880d3703e80c41c000102a2206450d04200620022903e80b370000200641086a2008290300370000200620022903880b370010200641186a2004290300370000200620022903e80c370020200641286a200b290300370000200641306a200a290300370000200641386a200d2903003700002006ad428080808080088410052006102c2001200541016a2205470d000b0b2036203b4921042019428080808070832001ad8421190b2013201fad42208684211320374200370300200e4200370300201b4200370300200242003703e80c2003201a1002220641086a290000370300200220062900003703c80d2006102c201b2003290300370300200220022903c80d22093703e80b200220093703e80c200320201002220641086a290000370300200220062900003703c80d2006102c200241880b6a41086a20032903002209370300200220022903c80d22073703880b200e2007370000200e41086a20093700002038201b2903003703002039200e290300370300203a2037290300370300200220022903e80c3703a80d024020040d00200241a80d6aad428080808080048410050c010b4108102a2206450d01200620193e0000200620194220883e0004200241a80d6aad42808080808004842006ad428080808080018410012006102c0b200241880b6a41186a22034200370300200241880b6a41106a22084200370300200241880b6a41086a22054200370300200242003703880b200241c80d6a41086a22064196e0c500ad4280808080f000841002220441086a290000370300200220042900003703c80d2004102c20052006290300370300200220022903c80d22093703e80c200220093703880b200641f3e0c500ad4280808080a001841002220441086a290000370300200220042900003703c80d2004102c200241a80d6a41086a20062903002209370300200220022903c80d22073703a80d20142007370000201441086a2009370000200241e80b6a41086a2005290300370300200241e80b6a41106a2008290300370300200241e80b6a41186a2003290300370300200220022903880b3703e80b0240024020180d00201d10050c010b200241003602b80b200242013703b00b2013422088a72206200241b00b6a10670240024020060d0020022802b80b210320022802b40b210420022802b00b21050c010b201820064103746a211b410020022802b80b220a6b210320022802b40b2104410021060340200a20066a2108201820066a220b280200210d02400240200420036a4104490d0020022802b00b21050c010b200841046a22052008490d062004410174220c2005200c20054b1b220c4100480d060240024020040d00200c102a21050c010b20022802b00b2004200c102e21050b2005450d042002200c3602b40b200220053602b00b200c21040b2002200841046a220c3602b80b2005200a6a20066a200d360000200b41046a280200210d0240200420036a417c6a41034b0d00200c41046a220e200c490d062004410174220c200e200c200e4b1b220c4100480d060240024020040d00200c102a21050c010b20052004200c102e21050b2005450d042002200c3602b40b200220053602b00b200c21040b2002200841086a3602b80b2005200a6a20066a41046a200d360000200341786a2103200641086a2106200b41086a201b470d000b200a20066a21030b2013a72106201d2003ad4220862005ad84100102402004450d002005102c0b2006450d002018102c0b200241003602d80a200242043703d00a200241e80b6a108a04200241e00a6a20022802e80b220620022802f00b10d301024020022802ec0b450d002006102c0b200241880b6a410c6a200241e00a6a41086a290300370200200241880b6a41146a200241e00a6a41106a290300370200200241880b6a411c6a200241e00a6a41186a290300370200200241880b6a41246a200241e00a6a41206a2d00003a0000200220022903e00a37028c0b2002200241d00a6a3602880b200241e80b6a200241880b6a410472109404410121180240024020022802e80b4101460d004100211b4100211f0c010b200241b00b6a41206a200241e80b6a41246a280200360200200241b00b6a41186a200241e80b6a411c6a22062902002209370300200241b00b6a41106a200241e80b6a41146a22052902002207370300200241b00b6a41086a200241e80b6a410c6a22042902002213370300200220022902ec0b22193703b00b200241900e6a41186a2009370300200241900e6a41106a2007370300200241900e6a41086a2013370300200220193703900e200241e80c6a41186a2006290200370300200241e80c6a41106a2005290200370300200241e80c6a41086a2004290200370300200220022902ec0b3703e80c4120102a2205450d01200520022903900e370000200541186a200241900e6a41186a2203290300370000200541106a200241900e6a41106a2208290300370000200541086a200241900e6a41086a220a290300370000200241a80d6a41086a200241e80c6a41086a2903002209370300200241a80d6a41106a200241e80c6a41106a2903002207370300200241a80d6a41186a200241e80c6a41186a2903002213370300200220022903e80c22193703a80d20022802880b2106200241880d6a41186a220b2013370300200241880d6a41106a220c2007370300200241880d6a41086a220d2009370300200220193703880d024020062802082204200641046a280200470d00200441016a220e2004490d042004410174221b200e201b200e4b1b220ead422c7e2209422088a70d042009a7221b4100480d040240024020040d00201b102a21040c010b20062802002004412c6c201b102e21040b2004450d0220062004360200200641046a200e360200200628020821040b200d2903002109200c2903002107200b290300211320022903880d211920062802002004412c6c6a22044281808080103702242004200536022020042019370200200441186a2013370200200441106a2007370200200441086a20093702004101211b2006200628020841016a360208200241b00e6a41086a200a290300370300200241b00e6a41106a2008290300370300200241b00e6a41186a2003290300370300200220022903900e3703b00e4120102a2218450d01201820022903b00e370000201841186a200241b00e6a41186a220e290300370000201841106a200241b00e6a41106a2201290300370000201841086a200241b00e6a41086a2237290300370000200241b00b6a41206a200241880b6a41206a290300370300200241b00b6a41186a200241880b6a41186a290300370300200241b00b6a41106a200241880b6a41106a290300370300200241b00b6a41086a200241880b6a41086a290300370300200220022903880b3703b00b200241e80b6a200241b00b6a410472223c109404024020022802e80b4101460d004101211f0c010b200241e80b6a41047221054102210a412021084101211b4101211f0340200241e80d6a41206a200541206a280200360200200241e80d6a41186a200541186a22062902002209370300200241e80d6a41106a200541106a22042902002207370300200241e80d6a41086a200541086a220329020022133703002002200529020022193703e80d200241900e6a41186a220b2009370300200241900e6a41106a220c2007370300200241900e6a41086a220d2013370300200220193703900e200241e80c6a41186a22362006290000370300200241e80c6a41106a22062004290000370300200241e80c6a41086a22382003290000370300200220052900003703e80c4120102a2204450d02200420022903900e370000200441186a200b290300370000200441106a200c290300370000200441086a200d290300370000200241a80d6a41086a20382903002209370300200241a80d6a41106a20062903002207370300200241a80d6a41186a20362903002213370300200220022903e80c22193703a80d20022802b00b2106200241880d6a41186a22362013370300200241880d6a41106a22382007370300200241880d6a41086a22392009370300200220193703880d024020062802082203200641046a223a280200470d00200341016a223b2003490d052003410174223d203b203d203b4b1b223bad422c7e2209422088a70d052009a7223d4100480d050240024020030d00203d102a21030c010b20062802002003412c6c203d102e21030b2003450d0320062003360200203a203b360200200628020821030b20392903002109203829030021072036290300211320022903880d211920062802002003412c6c6a22034281808080103702242003200436022020032019370200200341186a2013370200200341106a2007370200200341086a20093702002006200628020841016a360208200241c80d6a41086a2206200d290300370300200241c80d6a41106a2204200c290300370300200241c80d6a41186a2203200b290300370300200220022903900e3703c80d200e20032903003703002001200429030037030020372006290300370300200220022903c80d3703b00e0240201b201f470d00201b41016a2206201b490d05200a2006200a20064b1b221f41ffffff3f71201f470d05201f41057422064100480d0502400240201b0d002006102a21180c010b201820082006102e21180b2018450d030b201820086a220620022903b00e370000200641186a200e290300370000200641106a2001290300370000200641086a2037290300370000200241e80b6a203c109404200a41026a210a200841206a2108201b41016a211b20022802e80b4101460d000b0b200241b00b6a108404200241e80b6a20022802b00b220620022802b80b10d301024020022802b40b450d002006102c0b200241e80d6a41086a200241e80b6a41086a22362903002209370300200241e80d6a41106a200241e80b6a41106a22382903002207370300200241e80d6a41186a200241e80b6a41186a22392903002213370300200241e80d6a41206a200241e80b6a41206a220d2d000022063a0000200220022903e80b22193703e80d200241880b6a41206a20063a0000200241880b6a41186a2013370300200241880b6a41106a2007370300200241880b6a41086a2009370300200220193703880b200241e80b6a200241880b6a109504024020022d00980c4102460d000340200241b00b6a41286a200241e80b6a41286a280200360200200241b00b6a41206a200d290300370300200241b00b6a41186a220e2039290300370300200241b00b6a41106a22012038290300370300200241b00b6a41086a22372036290300370300200220022903e80b3703b00b200d28020021084100210a0240200229028c0c2209422088a72203450d0020022802940c210c4100210a41002106024003402006210502400240200a0d000340024020062003490d00200621050c0a0b2002200820064105746a3602c80d200241900e6a200241c80d6a1090040240024020022802980e2205450d0020022802940e21040240200228029c0e450d002005102c0b200641016a21062004200c4d0d010c040b200641016a21060b20062003490d000b4100210a0c040b0340200520034f0d082002200820054105746a22043602c80d200241900e6a200241c80d6a1090040240024020022802980e22060d00200541016a21060c010b20022802940e210b0240200228029c0e450d002006102c0b200541016a2106200b200c4b0d020b02402005200a6b220520034f0d00200820054105746a22052004290000370000200541186a200441186a290000370000200541106a200441106a290000370000200541086a200441086a29000037000020062105200620034f0d040c010b0b41fcb4c000200520031038000b200a41016a210a20062003490d000b0b200a450d00200620034f0d00200820064105746a2205200a4105746b2005200320066b41057410dc051a0b200241b00e6a41186a2206200e290300370300200241b00e6a41106a22052001290300370300200241b00e6a41086a22042037290300370300200220022903b00b3703b00e2008450d01200241880d6a41186a220b2006290300370300200241880d6a41106a220c2005290300370300200241880d6a41086a220e2004290300370300200220022903b00e3703880d0240024020022802d80a220520022802d40a460d0020022802d00a21060c010b200541016a22062005490d05200541017422042006200420064b1b2204ad422c7e2207422088a70d052007a722064100480d050240024020050d002006102a21060c010b20022802d00a2005412c6c2006102e21060b2006450d03200220043602d40a200220063602d00a0b200e2903002107200c2903002113200b290300211920022903880d211a20062005412c6c6a2206200942ffffffff0f832003200a6bad42208684370224200620083602202006201a370200200641186a2019370200200641106a2013370200200641086a20073702002002200541016a3602d80a200241e80b6a200241880b6a10950420022d00980c4102470d000b0b200241880b6a41186a22044200370300200241880b6a41106a22034200370300200241880b6a41086a22054200370300200242003703880b200241c80d6a41086a22064196e0c500ad4280808080f0008422091002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22073703e80c200220073703880b200641f3dfc500ad4280808080e001841002220841086a290000370300200220082900003703c80d2008102c200241a80d6a41086a220a20062903002207370300200220022903c80d22133703a80d20142013370000201441086a220b2007370000200241e80b6a41086a220c2005290300370300200241e80b6a41106a220d2003290300370300200241e80b6a41186a220e2004290300370300200220022903880b3703e80b200241d0036a200241e80b6a412010940120022802d403213e20022802d003213f200442003703002003420037030020054200370300200242003703880b200620091002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22093703e80c200220093703880b20064181e0c500ad4280808080d002841002220841086a290000370300200220082900003703c80d2008102c200a20062903002209370300200220022903c80d22073703a80d20142007370000200b2009370000200c2005290300370300200d2003290300370300200e2004290300370300200220022903880b3703e80b200241c8036a200241e80b6a412010940120022802cc03210620022802c803210520022802d00a214020022802d40a214120022802d80a2136200242003702d40e200241d0e1c1003602d00e02400240024002402036201b6a2239ad42e0007e2209422088a70d002009a72238417f4c0d004108210e0240024020380d0041082142410821430c010b2038102a2242450d05204221430b4100210d410021440240201b4105742203450d0020034105752244ad42d8007e2209422088a70d072009a722044100480d072004102a220e450d050b2006410420051b223a41014b213b0240201b450d00200341606a213c200241980c6a2105200241900c6a2137200e210841002104201821060340200241b00e6a41186a220a200641186a220b290000370300200241b00e6a41106a220c200641106a220d290000370300200241b00e6a41086a221b200641086a2201290000370300200220062900003703b00e200241b00b6a41186a200b290000370300200241b00b6a41106a200d290000370300200241b00b6a41086a2001290000370300200220062900003703b00b200241d00e6a200241b00b6a200410d501200241e80b6a41086a4200370300200241e80b6a41106a4200370300200241e80b6a41186a4200370300200241e80b6a41206a420037030020374200370300200541186a200a290300370000200541106a200c290300370000200541086a201b290300370000200520022903b00e370000200242003703e80b2008200241e80b6a41d00010db05220841d0006a41003a0000200841d8006a2108200641206a2106200441016a2104200341606a22030d000b203c41057641016a210d0b203a4101203b1b21060240201f450d002018102c0b02400240024002400240200d2006490d000240024020392036412c6c2206412c6d2205490d00203921450c010b203941017422042005200420054b1b2245ad42e0007e2209422088a70d0c2009a722054100480d0c0240024020390d002005102a21420c010b204220382005102e21420b2042450d0a204221430b204020066a2146024020360d004100213d2040213b0c040b200241880d6a41106a2101204021062042213a4100213d0340200241b00e6a41186a2205200641186a290200370300200241b00e6a41106a2204200641106a290200370300200241b00e6a41086a2203200641086a290200370300200220062902003703b00e2006412c6a213b2006280220223c450d04200641286a280200211b200641246a2802002147200241b00b6a41186a22482005290300370300200241b00b6a41106a22492004290300370300200241b00b6a41086a224a2003290300370300200220022903b00e3703b00b200241b8036a200241b00b6a109604201bad42c8007e2209422088a70d062009a72206417f4c0d06200241b8036a41086a290300211a20022903b80321200240024020060d004108211f0c010b2006102a221f450d0b0b02400240201b0d004100211b410021180c010b203c201b4105746a213941002118203c210a0340200a41086a2900002109200a41106a2900002107200a2900002113200241e80b6a41186a2237200a41186a290000370300200241e80b6a41106a22362007370300200241e80b6a41086a22382009370300200220133703e80b200a41206a210a200241d00e6a210620022802d40e210b024003402006280200220841086a210520082f0106220c4105742106410021040240024003402006450d01200241e80b6a2005412010dd052203450d02200641606a2106200441016a2104200541206a21052003417f4a0d000b2004417f6a210c0b200b450d02200b417f6a210b2008200c4102746a4194036a21060c010b0b200d200820044102746a41e8026a220528020022064d0d05200e200641d8006c6a22062903202109200641286a2903002107200241880d6a41186a2208420037030020014200370300200241880d6a41086a22044200370300200242003703880d200241c80d6a41086a2206418be9c500ad42808080808001841002220341086a290000370300200220032900003703c80d2003102c20042006290300370300200220022903c80d3703880d200641c9b5c000ad4280808080d001841002220341086a290000370300200220032900003703c80d2003102c200241880b6a41086a20062903002213370300200220022903c80d22193703880b20012019370000200141086a2013370000200241e80c6a41086a2004290300370300200241e80c6a41106a2001290300370300200241e80c6a41186a2008290300370300200220022903880d3703e80c200241a0036a200241e80c6a4120109e0120024190036a20022903a803200241a0036a41106a290300427f420010e105200d200528020022064d0d0620024180036a2020201a200229039003420020022802a00322041b22134201201342015620024190036a41086a290300420020041b22134200522013501b22041b2013420020041b10e105200e200641d8006c6a220641286a427f200720092002290380037c22132009542204ad7c221920042019200754201320095a1b22041b3703002006427f201320041b370320200241a80d6a41186a22042037290300370300200241a80d6a41106a22032036290300370300200241a80d6a41086a22082038290300370300200220022903e80b3703a80d20052802002105024002402018201b460d00201821060c010b201b41016a2206201b490d10201b410174220b2006200b20064b1b220bad42c8007e2209422088a70d102009a722064100480d1002400240201b0d002006102a211f0c010b201f201b41c8006c2006102e211f0b201f450d0e201b2106200b211b0b201f200641c8006c6a2206420037030020062005360220200641186a4200370300200641106a4200370300200641086a4200370300200620022903a80d3702242006412c6a2008290300370200200641346a20032903003702002006413c6a2004290300370200201841016a21180b200a2039470d000b0b02402047450d00203c102c0b200241900e6a41186a22032048290300370300200241900e6a41106a22082049290300370300200241900e6a41086a220a204a290300370300200220022903b00b3703900e200241880d6a41186a220b420037030020014200370300200241880d6a41086a22054200370300200242003703880d200241c80d6a41086a2206418be9c500ad42808080808001841002220441086a290000370300200220042900003703c80d2004102c20052006290300370300200220022903c80d3703880d200641c9b5c000ad4280808080d001841002220441086a290000370300200220042900003703c80d2004102c200241880b6a41086a20062903002209370300200220022903c80d22073703880b20012007370000200141086a2009370000200241e80c6a41086a2005290300370300200241e80c6a41106a2001290300370300200241e80c6a41186a200b290300370300200220022903880d3703e80c200241e8026a200241e80c6a4120109e01200241d8026a20022903f002200241e8026a41106a290300427f420010e105200241c8026a2020201a20022903d802420020022802e80222061b220942012009420156200241d8026a41086a290300420020061b22094200522009501b22061b2009420020061b10e105203a4200370308203a20022903c802370300203a4200370310203a41186a4200370300203a41286a4200370300203a4201370320203a2018360238203a201b360234203a201f360230203a20022903900e37023c203a41c4006a200a290300370200203a41cc006a2008290300370200203a41d4006a2003290300370200203d41016a213d203a41e0006a213a203b2106203b2046470d000c050b0b02402044450d00200e102c0b02402039450d002042102c0b20022802d00e20022802d40e20022802d80e10da0102402036450d002036412c6c2105204041206a210603400240200641046a280200450d002006280200102c0b2006412c6a2106200541546a22050d000b0b2041450d062040102c0c060b41d087c6002006200d1038000b41a888c6002006200d1038000b203b2046460d000340203b41206a2802002205450d01203b412c6a21060240203b41246a280200450d002005102c0b2006213b20462006470d000b0b203e4100203f1b213a02402041450d002040102c0b203aad42307e2209422088a70d002009a72206417f4c0d000240024020060d00410821370c010b2006102a2237450d050b203a412c6c2206417f4c0d000240024020060d004104214a0c010b2006102a224a450d050b4100213b02400240200d203a200d203a491b223e0d00203a2140410021480c010b200e41a87f6a2147200d41d8006c213c2043203d41e0006c6a211f200241b00e6a41186a2149200241b00e6a41106a2146200241b00e6a41086a2141203a2138410021484100213903400240200d450d00203c2105200e210603400240200641d0006a2d00000d0002400240200641206a2903002207200641286a29030022138450450d0042002109427f2107427f21130c010b427f2109200241b8026a427f427f2007201310e105200241b8026a41086a290300211320022903b80221070b2006200737030020062013370308200641106a2009370300200641186a20093703000b200641d8006a2106200541a87f6a22050d000b0b204321030240203d450d0002400340024020032802382206450d00200641c8006c2104200328023041206a21060340200d200628020022054d0d030240200e200541d8006c6a22052d00500d0020052903202209200541286a290300220784500d00200241e80b6a2003290310200341186a2903002003290300200341086a2903002009200710d701200520052903002209427f2009427f20022903f00b20022802e80b41014622081b22137c22072007200954220a200541086a220b2903002209427f200241e80b6a41106a29030020081b22197c200aad7c220720095420072009511b22081b201320198450220a1b370300200b2009427f200720081b200a1b3703000b200641c8006a2106200441b87f6a22040d000b0b200341e0006a2203201f460d020c000b0b41a888c6002005200d1038000b203941016a2139203c210620472105200e21040340024020060d00203821400c030b200641a87f6a2106200541d8006a2105200441d0006a2103200441d8006a2208210420032d00000d000b02402006450d00200541086a2903002109200541186a2903002107200541106a2903002113200529030021194100210403400240200820046a220341d0006a2d00000d00200341086a290300221a2009201920092013200720032903002220201a200341106a2903002223200341186a290300222210d80141ff0171410146220a1b210920202019200a1b211920222007200a1b210720232013200a1b211320032005200a1b21050b2006200441d8006a2204470d000b20050d00203821400c020b200541013a00500240203d450d002005410c6a2101200541306a2118204321040340200441e0006a2136024020042802382203450d0020042802302106200341c8006c210303400240024020012006460d00200641246a2018412010dd050d010b200441186a22082903002119200541086a220a290300210920042903102113200529030021072005290310211a200641186a200541186a220b290300370300200641106a201a370300200620094200200920197d2007201354ad7d221a200720137d2220200756201a200956201a2009511b220c1b201320198450221b1b3703082006200742002020200c1b201b1b370300200a2903002109200b29030021072005290300211320042005290310370320200441286a200737030020042013370310200820093703000b200641c8006a2106200341b87f6a22030d000b0b203621042036201f470d000b0b2049200541c8006a2900003703002046200541c0006a2900003703002041200541386a290000370300200220052900303703b00e200541286a2903002109200529032021070240024020482038460d00203821400c010b203841016a22062038490d09203841017422052006200520064b1b2240ad42307e2213422088a70d092013a722064100480d090240024020380d002006102a21370c010b2037203841306c2006102e21370b2037450d0720382148204021380b20412903002113204629030021192049290300211a20022903b00e21202037204841306c6a2206200737032020062020370300200641286a2009370300200641186a201a370300200641106a2019370300200641086a2013370300204841016a21482039203e490d000b0b0240203d450d002043203d41e0006c6a2147204841306c2136200241b00b6a41186a2138200241b00b6a41106a2139200241b00b6a41086a213c4100213b2043210103402038200141d4006a2900003703002039200141cc006a290000370300203c200141c4006a2900003703002002200129003c3703b00b024020012802382206450d002001280230220c200641c8006c6a2118200141106a211f4100210d4104211b4100210b0340200c220a41246a2104200a41c8006a210c410021032036210520372106024003402005450d01024020042006460d0020062004412010dd052108200341016a2103200541506a2105200641306a210620080d010b0b418094ebdc0321060240201f200a10d9010d00410021050240200a290310200129032085200a41186a290300200141286a29030085844200520d00200241e80b6a428094ebdc034200200a290300200a41086a290300201f290300201f41086a29030010d70120022802e80b4101460d0120022903f00b220742ff93ebdc0356200241e80b6a41106a29030022094200522009501b0d012007a721050b200521060b200220063602e80b2002418094ebdc033602ec0b200241e80b6a2006418094ebdc034b4102746a2802002105200241c80d6a41186a2204200a413c6a290000370300200241c80d6a41106a2203200a41346a290000370300200241c80d6a41086a2208200a412c6a2900003703002002200a2900243703c80d02400240200b200d460d00200b21060c010b200d41016a2206200d490d0c200d410174220a2006200a20064b1b220aad42247e2209422088a70d0c2009a722064100480d0c02400240200d0d002006102a211b0c010b201b200d41246c2006102e211b0b201b450d0a200d2106200a210d0b201b200641246c6a220620022903c80d37020020082903002109200329030021072004290300211320062005360220200641186a2013370200200641106a2007370200200641086a2009370200200b41016a210b0b200c2018470d000b024002400240200b450d0002400240200b41246c22040d00410021050c010b201b41206a2106410021050340200628020020056a2105200641246a21062004415c6a22040d000b0b02404100418094ebdc0320056b22062006418094ebdc034b1b220a200b6e2206418094ebdc032006418094ebdc03491b2208450d00201b41206a2106410021050340200b2005460d032002417f2006280200220420086a220320032004491b22043602e80b2002418094ebdc033602ec0b2006200241e80b6a2004418094ebdc034b4102746a280200360200200641246a2106200b200541016a2205470d000b0b0240200a2008200b6c6b2208450d00410021060340200b2006200b7022054d0d042002417f201b200541246c6a2205280220220441016a220320032004491b22043602e80b2002418094ebdc033602ec0b2005200241e80b6a2004418094ebdc034b4102746a280200360220200641016a22062008490d000b0b200241e80b6a41186a22052038290300370300200241e80b6a41106a22042039290300370300200241e80b6a41086a2203203c290300370300200220022903b00b3703e80b0240203b203a470d00203a41016a2206203a490d0d203a41017422082006200820064b1b2206ad422c7e2209422088a70d0d2009a722084100480d0d02400240203a0d002008102a214a0c010b204a203a412c6c2008102e214a0b204a450d0b203a213b2006213a0b204a203b412c6c6a220620022903e80b3702002003290300210920042903002107200529030021132006200b3602282006200d3602242006201b360220200641186a2013370200200641106a2007370200200641086a2009370200203b41016a213b0c030b200d450d02201b102c0c020b41d087c6002005200b1038000b41d087c6002005200b1038000b200141e0006a22012047470d000b0b02402044450d00200e102c0b0240203d450d00203d41e0006c2105204341306a210603400240200641046a280200450d002006280200102c0b200641e0006a2106200541a07f6a22050d000b0b02402045450d002042102c0b20022802d00e20022802d40e20022802d80e10da012037450d02204841306c220641306e21050240024020060d0042002126410121430c010b200541057422044100480d072004102a2243450d052005ad21260b024002402037203720066a470d00410021480c010b204841306c2104410021482043210620372105034020062005290000370000200641186a200541186a290000370000200641106a200541106a290000370000200641086a200541086a290000370000204841016a2148200641206a2106200541306a2105200441506a22040d000b0b200242003702b40e200241d0e1c1003602b00e02402048450d0020484105742105204321060340200241880b6a41186a200641186a290000370300200241880b6a41106a200641106a290000370300200241880b6a41086a200641086a290000370300200220062900003703880b200241e80b6a41186a4200370300200241e80b6a41106a4200370300200241e80b6a41086a4200370300200242003703e80b200241003602900c200242083703880c200241b00b6a200241b00e6a200241880b6a200241e80b6a10db01024020022802d00b2204450d0020022802d40b450d002004102c0b200641206a2106200541606a22050d000b0b0240203b412c6c2206450d00204a20066a2118200241880d6a41106a210e418be9c500ad4280808080800184211a204a210d03400240200d28022841246c2206450d00200d280220221b20066a21010340200241a8026a200d109604200241a8026a41086a290300210720022903a8022113200241880d6a41186a22034200370300200e4200370300200241880d6a41086a22054200370300200242003703880d200241c80d6a41086a2206201a1002220441086a290000370300200220042900003703c80d2004102c20052006290300370300200220022903c80d3703880d200641c9b5c000ad4280808080d001841002220441086a290000370300200220042900003703c80d2004102c200241880b6a41086a20062903002209370300200220022903c80d22193703880b200e2019370000200e41086a2009370000200241e80c6a41086a2005290300370300200241e80c6a41106a200e290300370300200241e80c6a41186a2003290300370300200220022903880d3703e80c20024190026a200241e80c6a4120109e0120024180026a20022903980220024190026a41106a290300427f420010e105200241f0016a20132007200229038002420020022802900222061b22094201200942015620024180026a41086a290300420020061b22094200522009501b22061b2009420020061b10e105200241e0016a20022903f0012209428094ebdc038022074200201b22083502202213420010e005200241e0016a41086a29030020022903e00122192013200920074280ec94a37c7e7c7e22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76aad7c2209201954ad7c2107200841246a211b200241b00e6a210620022802b40e210b024003402006280200220a41086a2105200a2f0106220c4105742106410021040240024003402006450d0120082005412010dd052203450d02200641606a2106200441016a2104200541206a21052003417f4a0d000b2004417f6a210c0b200b450d02200b417f6a210b200a200c4102746a41f8066a21060c010b0b200a41e8026a200441306c6a210602402008200d460d002008200d412010dd05450d002006427f2006290310221320097c221920192013542205200641186a2204290300221320077c2005ad7c221920135420192013511b22051b3703102004427f201920051b370300200241a80d6a41186a2208200d41186a290000370300200241a80d6a41106a220a200d41106a290000370300200241a80d6a41086a220b200d41086a2900003703002002200d2900003703a80d200641286a2104200641206a2103024020062802282205200641246a280200470d00200541016a22062005490d0d2005410174220c2006200c20064b1b220cad42307e2213422088a70d0d2013a722064100480d0d0240024020050d002006102a21060c010b2003280200200541306c2006102e21060b2006450d0b20032006360200200341046a200c360200200428020021050b200b2903002113200a29030021192008290300212020022903a80d21232003280200200541306c6a2206200937032020062023370300200641286a2007370300200641186a2020370300200641106a2019370300200641086a20133703002004200428020041016a3602000c010b2006427f2006290300221320097c221920192013542205200641086a2204290300221320077c2005ad7c221920135420192013511b22051b3703002004427f201920051b3703002006427f2006290310221320097c220920092013542205200641186a2204290300220920077c2005ad7c220720095420072009511b22051b3703102004427f200720051b3703000b201b2001470d000b0b200d412c6a220d2018470d000b0b20022802b80e210e20022802b40e210820022802b00e2105200241e80b6a41186a220a4200370300200241e80b6a41106a220b4200370300200241e80b6a41086a22044200370300200242003703e80b200241c80d6a41086a22064196e0c500ad4280808080f000841002220341086a290000370300200220032900003703c80d2003102c20042006290300370300200220022903c80d3703e80b200641bafdc200ad4280808080e001841002220341086a290000370300200220032900003703c80d2003102c200241a80d6a41086a20062903002209370300200220022903c80d22073703a80d200f2007370000200f41086a2009370000200241880b6a41086a2004290300370300200241880b6a41106a200b290300370300200241880b6a41186a200a290300370300200220022903e80b3703880b200241e80b6a200241880b6a412010d00120022902ec0b420020022802e80b22061b210702402006410120061b220d450d002007422088a72206450d002006410574210a4196e0c500ad4280808080f000842109200241980b6a210c200d21040340200241c80d6a41086a220620091002220341086a290000370300200220032900003703c80d2003102c200241e80c6a41086a220b2006290300370300200220022903c80d3703e80c200641dff8c200ad4280808080f000841002220341086a290000370300200220032900003703c80d2003102c200241a80d6a41086a22032006290300370300200220022903c80d3703a80d200241880b6a2004109f0141c000102a2206450d06200441206a2104200620022903e80c370000200641086a200b290300370000200620022903a80d370010200641186a2003290300370000200620022903880b370020200641286a200241880b6a41086a290300370000200641306a200c290300370000200641386a200241880b6a41186a2903003700002006ad428080808080088410052006102c200a41606a220a0d000b0b02402007a7450d00200d102c0b0240024020080d00200521060c010b2008210420052106034020062802f80621062004417f6a22040d000b0340200520052f01064102746a41f8066a28020021052008417f6a22080d000b0b200241cc0b6a20052f0106360200200241b00b6a41186a4100360200200241c40b6a20053602002002200e3602d00b200241003602c00b200242003703b80b200220063602b40b200241003602b00b200241e80b6a200241b00b6a10fb030240200241e80b6a41c0006a28020022380d00427f2125427f21220c020b200241880d6a41106a2103200241e80b6a41106a211f200241e80b6a41386a2146200241e80b6a41286a2142427f2125427f21220340200241900e6a41086a200241e80b6a41086a22062903002209370300200241900e6a41106a201f2903002207370300200241900e6a41186a200241e80b6a41186a22362903002213370300200220022903e80b22193703900e204629030021232042290300212420022802ac0c214920022802b00c210a20022903980c212b20022903880c212f200241b00e6a41186a2013370300200241b00e6a41106a2007370300200241b00e6a41086a2009370300200220193703b00e20364200370300201f420037030020064200370300200242003703e80b200241c80d6a41086a2204418be9c500ad4280808080800184221a1002220541086a290000370300200220052900003703c80d2005102c20062004290300370300200220022903c80d3703e80b200441c9b5c000ad4280808080d0018422201002220541086a290000370300200220052900003703c80d2005102c200241a80d6a41086a220c20042903002209370300200220022903c80d22073703a80d200f2007370000200f41086a220b2009370000200241880b6a41086a22182006290300370300200241880b6a41106a223c201f290300370300200241880b6a41186a223d2036290300370300200220022903e80b3703880b200241c8016a200241880b6a4120109e01200241a0016a20022903d001200241c8016a41106a290300427f420010e10520022802c801210520364200370300201f420037030020064200370300200242003703e80b2004201a1002220841086a290000370300200220082900003703c80d2008102c20062004290300370300200220022903c80d3703e80b200420201002220841086a290000370300200220082900003703c80d2008102c200c20042903002209370300200220022903c80d22073703a80d200f2007370000200b200937000020182006290300370300203c201f290300370300203d2036290300370300200220022903e80b3703880b200241b0016a200241880b6a4120109e0120024190016a20022903b801200241b0016a41106a290300427f420010e105200241f0006a20022903a001420020051b220942012009420156200241a0016a41086a290300420020051b22094200522009501b22061b2009420020061b202f202410e00520024180016a200229039001420020022802b00122061b22094201200942015620024190016a41086a290300420020061b22094200522009501b22061b2009420020061b202b202310e005200a41306c220d41306d2106200241f0006a41086a290300212b20024180016a41086a29030021234100210b2002290370212f200229038001212441082139410021470240200d450d002006ad42307e2209422088a70d082009a722054100480d082005102a2239450d06200621470b02402038200d6a2038460d004100210b20392106203821050340200541286a2903002107200541206a2903002113200241a80d6a41186a220e200541186a290300370300200241a80d6a41106a221b200541106a290300370300200c200541086a290300370300200220052903003703a80d200241880d6a41186a2201420037030020034200370300200241880d6a41086a22084200370300200242003703880d2004201a1002220a41086a2900003703002002200a2900003703c80d200a102c20082004290300370300200220022903c80d3703880d200420201002220a41086a2900003703002002200a2900003703c80d200a102c201820042903002209370300200220022903c80d22193703880b20032019370000200341086a2009370000200241e80c6a41086a2008290300370300200241e80c6a41106a2003290300370300200241e80c6a41186a2001290300370300200220022903880d3703e80c200241d8006a200241e80c6a4120109e01200241c8006a2002290360200241d8006a41106a290300427f420010e105200241386a20022903484200200228025822081b220942012009420156200241c8006a41086a290300420020081b22094200522009501b22081b2009420020081b2013200710e0052006200241386a41086a29030037030820062002290338370300200641106a20022903a80d370300200641186a200c290300370300200641206a201b290300370300200641286a200e290300370300200641306a2106200b41016a210b200541306a2105200d41506a220d0d000b0b02402049450d002038102c0b200bad42307e2209422088a70d012009a72206417f4c0d010240024020060d004108210d0c010b2006102a220d450d060b02400240200b0d00410021080c010b2039200b41306c6a210a41002108200d2106203921050340200620052903003703002006200541086a290300370308200641106a200541106a290300370300200641186a200541186a290300370300200641206a200541206a290300370300200641286a200541286a290300370300200641306a2106200841016a2108200541306a2205200a470d000b0b2036202b3703002002202f3703f80b200220243703e80b200220083602900c2002200b36028c0c2002200d3602880c200220233703f00b20044196e0c500ad4280808080f000841002220641086a290000370300200220062900003703c80d2006102c200241e80c6a41086a22052004290300370300200220022903c80d3703e80c200441dff8c200ad4280808080f000841002220641086a290000370300200220062900003703c80d2006102c200c2004290300370300200220022903c80d3703a80d200241880b6a200241b00e6a109f0141c000102a2204450d05200420022903e80c370000200441086a2005290300370000200420022903a80d370010200441186a200c290300370000200420022903880b370020200441286a2018290300370000200441306a203c290300370000200441386a203d290300370000200241003602900b200242013703880b2002200241e80b6a3602c80d200241c80d6a200241880b6a108a012002201f3602c80d200241c80d6a200241880b6a108a0120022802880c210620022802900c2205200241880b6a106702402005450d00200541306c21050340200641106a200241880b6a109101200220063602c80d200641306a2106200241c80d6a200241880b6a108a01200541506a22050d000b0b200228028c0b21062004ad428080808080088420023502900b42208620022802880b2205ad84100102402006450d002005102c0b2024202554210620232022512105202320225421082004102c0240200228028c0c450d0020022802880c102c0b2006200820051b210602402047450d002039102c0b2023202220061b21222024202520061b2125200241e80b6a200241b00b6a10fb0320022802a80c2238450d020c000b0b103a000b200241b00b6a10de01200241880b6a41186a22044200370300200241880b6a41106a22034200370300200241880b6a41086a22054200370300200242003703880b200241c80d6a41086a22064196e0c500ad4280808080f0008422091002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22073703e80c200220073703880b200641c8fdc200ad42808080809001841002220841086a290000370300200220082900003703c80d2008102c200241a80d6a41086a220a20062903002207370300200220022903c80d22133703a80d20142013370000201441086a220b2007370000200241e80b6a41086a220c2005290300370300200241e80b6a41106a220d2003290300370300200241e80b6a41186a220e2004290300370300200220022903880b3703e80b200220223703b80b200220253703b00b201d201e42808080808002841001200442003703002003420037030020054200370300200242003703880b200620091002220841086a290000370300200220082900003703c80d2008102c20052006290300370300200220022903c80d22093703e80c200220093703880b200641bafdc200ad4280808080e001841002220841086a290000370300200220082900003703c80d2008102c200a20062903002209370300200220022903c80d22073703a80d20142007370000200b2009370000200c2005290300370300200d2003290300370300200e2004290300370300200220022903880b3703e80b200241003602b80b200242013703b00b2048200241b00b6a106702402048450d00204841057421052043210603402006200241b00b6a109101200641206a2106200541606a22050d000b0b20022802b40b2106201d20023502b80b42208620022802b00b2205ad84100102402006450d002005102c0b2048ad21090240203b450d00203b412c6c2105204a41206a210603400240200641046a280200450d002006280200102c0b2006412c6a2106200541546a22050d000b0b200942208621090240203a450d00204a102c0b202620098421342040450d012037102c0c010b200241880b6a41186a22034200370300200241880b6a41106a22084200370300200241880b6a41086a22054200370300200242003703880b200241c80d6a41086a22064196e0c500ad4280808080f000841002220441086a290000370300200220042900003703c80d2004102c20052006290300370300200220022903c80d22093703e80c200220093703880b200641c8fdc200ad42808080809001841002220441086a290000370300200220042900003703c80d2004102c200241a80d6a41086a20062903002209370300200220022903c80d22073703a80d20142007370000201441086a2009370000200241e80b6a41086a2005290300370300200241e80b6a41106a2008290300370300200241e80b6a41186a2003290300370300200220022903880b3703e80b200241206a200241e80b6a4120109e01410021430b200241880b6a41186a224a4200370300200241880b6a41106a22464200370300200241880b6a41086a22494200370300200242003703880b200241c80d6a41086a22484196e0c500ad4280808080f0008422331002220641086a290000370300200220062900003703c80d2006102c20492048290300370300200220022903c80d22093703e80c200220093703880b204841fde0c500ad4280808080e0028422311002220641086a290000370300200220062900003703c80d2006102c200241a80d6a41086a224020482903002209370300200220022903c80d22073703a80d20142007370000201441086a22442009370000200241e80b6a41086a22412049290300370300200241e80b6a41106a223e2046290300370300200241e80b6a41186a223f204a290300370300200220022903880b3703e80b200241186a200241e80b6a4120109401200228021c21420240200228021822454101470d00024020424100203541d87e6a2206200620354b1b22474f0d00201c4280808080c00084212f200241e80b6a41386a210f200241e80b6a41246a21084196e0c500ad4280808080f0008421262042213c0340200241c80d6a41086a220620261002220541086a290000370300200220052900003703c80d2005102c200241e80c6a41086a22042006290300370300200220022903c80d3703e80c200641d1fdc200ad42808080808002841002220541086a290000370300200220052900003703c80d2005102c200241a80d6a41086a22052006290300370300200220022903c80d3703a80d2002203c3602e80b200241880d6a41186a2203202f1006220641186a290000370300200241880d6a41106a220a200641106a290000370300200241880d6a41086a220b200641086a290000370300200220062900003703880d2006102c200241880b6a41186a220c2003290300370300200241880b6a41106a220d200a290300370300200241880b6a41086a220a200b290300370300200220022903880d3703880b41c000102a2206450d03200620022903e80c370000200641086a2004290300370000200620022903a80d370010200641186a2005290300370000200620022903880b370020200641286a200a290300370000200641306a200d290300370000200641386a200c290300370000200241e80b6a200641c00010e9030240024020022802e80b223d450d002006ad4280808080800884100520022902ec0b212b0c010b4200212b4108213d0b2006102c203d202b422088a7220641d8006c6a210e203d210302402006450d000340200c200341186a290300370300200d200341106a290300370300200a200341086a2903003703002003280220210b20032903002109200241e80b6a41206a221b200341c4006a290200370300200241e80b6a41286a2201200341cc006a290200370300200241e80b6a41306a2218200341d4006a280200360200200241e80b6a41086a22062003412c6a290200370300200241e80b6a41106a2205200341346a290200370300200241e80b6a41186a22042003413c6a290200370300200220093703880b2002200341246a2902003703e80b200341d8006a2103200b450d01200241e80d6a41186a221f200c290300370300200241e80d6a41106a2237200d290300370300200241e80d6a41086a2236200a290300370300200241b00b6a41086a22382006290300370300200241b00b6a41106a22392005290300370300200241b00b6a41186a223a2004290300370300200241b00b6a41206a223b201b290300370300200241b00b6a41286a221b2001290300370300200241b00b6a41306a22012018280200360200200220022903880b3703e80d200220022903e80b3703b00b2004201f2903003703002005203729030037030020062036290300370300200820022903b00b370200200841086a2038290300370200200841106a2039290300370200200841186a203a290300370200200841206a203b290300370200200841286a201b290300370200200841306a2001280200360200200220022903e80d3703e80b2002200b3602880c200242003703e80a200242003703e00a200220042903003703900b200220052903003703880b200f20022903e80b2006290300200241880b6a200241e00a6a109704024020022802900c2205450d0020022802880c2106200541306c210503402006200641206a290300200641286a290300200241880b6a200241e00a6a109704200641306a2106200541506a22050d000b0b200241e00a6a41086a290300212320022903e00a2122024020022903880b2207200a290300220984500d00200228029c0c2205450d0020022802940c2106200241086a202220072022200754202320095420232009511b22041b22242023200920041b22252005ad420010e10520054105742105200241086a41086a29030021132002290308211a202421092025210703402006201a20092009201a56200720135620072013511b22041b22192013200720041b2220109c01200720207d2009201954ad7d2107200920197d2109200641206a2106200541606a22050d000b427f202320257d2022202454ad7d221320077c202220247d220720097c22192007542206ad7c22092006200920135420092013511b22061b2123427f201920061b21220b2022202310b1020240200228028c0c450d0020022802880c102c0b024020022802980c450d0020022802940c102c0b2003200e470d000b200e21030b202ba7210a02402003200e460d000340200341206a2802002205450d01200341306a28020021062003412c6a28020021040240200341246a280200450d002005102c0b200341d8006a210302402006450d002004102c0b200e2003470d000b0b203c41016a213c0240200a450d00203d102c0b203c2047470d000b0b20422047204220474b1b21420b204a42003703002046420037030020494200370300200242003703880b204820331002220641086a290000370300200220062900003703c80d2006102c20492048290300370300200220022903c80d22093703e80c200220093703880b204820311002220641086a290000370300200220062900003703c80d2006102c204020482903002209370300200220022903c80d22073703a80d201420073700002044200937000020412049290300370300203e2046290300370300203f204a290300370300200220022903880b3703e80b0240024020450d00201d10050c010b200220423602b00b201d201e4280808080c0008410010b024020152017a745720d002016102c0b024020430d002000410036020002402011450d00201141d0006c2105201041c0006a210603400240200641046a280200450d002006280200102c0b200641d0006a2106200541b07f6a22050d000b0b2012450d042010102c0c040b2000203437020420002043360200200041146a2011360200200041106a20123602002000410c6a20103602000c030b1033000b41a8b4c000200520031038000b1035000b200241e00e6a24000bbc0201047f230041d0006b220224002002412036020420022001360200200241086a2001ad42808080808004841003108d0102400240200228020822010d00200041003602000c010b200241106a2802002103200228020c2104200241003602380240024020034104490d0020012800002105200241003602382003417c714104460d00200041086a200128000436020020002005360204410121030c010b20024100360220200242013703182002410b36022c200220023602282002200241186a360234200241cc006a41013602002002420137023c200241d0b0c2003602382002200241286a360248200241346a41c49ac500200241386a10391a200235022042208620023502188410040240200228021c450d002002280218102c0b410021030b200020033602002004450d002001102c0b200241d0006a24000bd5340b067f017e017f027e027f017e037f017e217f027e207f230041e0016b22022400200241186a200041e8bac000108401200241286a200141f4bcc00010840120022802202103200228021c210420022802182105200241386a41086a200241286a41086a28020036020020022002290328370338200241c8006a41186a22064200370300200241c8006a41106a22074200370300200241c8006a41086a2200420037030020024200370348200241d0016a41086a220141bac6c500ad4280808080c0008422081002220941086a290000370300200220092900003703d0012009102c20002001290300370300200220022903d001220a3703c0012002200a370348200141bec6c500ad4280808080a00184220b1002220941086a290000370300200220092900003703d0012009102c200720022903d001220a370300200241f8006a41086a22092000290300370300200241f8006a41106a220c200a370300200241f8006a41186a220d20012903003703002002200a3703c00120022002290348370378200241086a200241f8006a109801024002400240024002402002290310420020022802081b220e42017c220a200e540d0020064200370300200742003703002000420037030020024200370348200120081002220f41086a2900003703002002200f2900003703d001200f102c20002001290300370300200220022903d001220e3703c0012002200e3703482001200b1002220f41086a2900003703002002200f2900003703d001200f102c200241c0016a41086a22102001290300220b370300200220022903d001220e3703c0012007200e370000200741086a2211200b37000020092000290300370300200c2007290300370300200d2006290300370300200220022903483703782002200a370348200241f8006aad42808080808004842212200241c8006aad220b4280808080800184100120064200370300200742003703002000420037030020024200370348200120081002220f41086a2900003703002002200f2900003703d001200f102c20002001290300370300200220022903d00122083703c00120022008370348200141c8c6c500ad4280808080b001841002220f41086a2900003703002002200f2900003703d001200f102c201020012903002208370300200220022903d001220e3703c0012007200e3700002011200837000020092000290300370300200c2007290300370300200d20062903003703002002200229034837037820024100360250200242013703482003200241c8006a106702402003450d002005200341286c6a21092005210003402000200241c8006a109101200041206a290300210802400240200228024c2206200228025022016b4108490d00200228024821060c010b200141086a22032001490d07200641017422012003200120034b1b22014100480d070240024020060d002001102a21060c010b200228024820062001102e21060b2006450d042002200136024c20022006360248200228025021010b2002200141086a360250200620016a20083700002009200041286a2200470d000b0b200228024c21012012200235025042208620022802482200ad84100102402001450d002000102c0b02402004450d002005102c0b200a42017c220e200a540d02200241f8006a41186a22064200370300200241f8006a41106a22134200370300200241f8006a41086a2200420037030020024200370378200241d0016a41086a220141bac6c500ad4280808080c0008422081002220341086a290000370300200220032900003703d0012003102c20002001290300370300200220022903d001220a3703c0012002200a370378200141f3c6c500ad4280808080e001841002220341086a290000370300200220032900003703d0012003102c201320022903d001220a37030020024198016a41086a2203200029030037030020024198016a41106a2209200a37030020024198016a41186a220c20012903003703002002200a3703c0012002200229037837039801200241c8006a20024198016a1080034100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f410021204100212141002122410021234100212441002125410021264100212741002128410021294100212a4100212b4100212c4100212d4100212e4100212f41002130410021314100213241002133024020022d00484101470d00200241c8006a41086a2d0000211b200241d1006a2d0000211c200241d2006a2d0000211d200241d3006a2d0000211e200241d4006a2d0000211f200241d5006a2d00002120200241d6006a2d00002121200241d7006a2d00002122200241c8006a41106a2d00002123200241d9006a2d00002124200241da006a2d00002125200241db006a2d00002126200241dc006a2d00002127200241dd006a2d00002128200241de006a2d00002129200241df006a2d0000212a200241c8006a41186a2d0000212b200241e1006a2d0000212c200241e2006a2d0000212d200241e3006a2d0000212e200241e4006a2d0000212f200241e5006a2d00002130200241e6006a2d00002131200241e7006a2d00002132200241e8006a2d0000213320022d0049211420022d004a211520022d004b211620022d004c211720022d004d211820022d004e211920022d004f211a0b20064200370300201342003703002000420037030020024200370378200120081002220d41086a2900003703002002200d2900003703d001200d102c20002001290300370300200220022903d001220a3703c0012002200a37037820014181c7c500ad4280808080c00184220a1002220d41086a2900003703002002200d2900003703d001200d102c200241c0016a41086a220f20012903002234370300200220022903d00122353703c00120132035370000201341086a220520343700002003200029030037030020092013290300370300200c20062903003703002002200229037837039801200220024198016a4120109401200228020421042002280200211020064200370300201342003703002000420037030020024200370378200120081002220d41086a2900003703002002200d2900003703d001200d102c20002001290300370300200220022903d00122083703c001200220083703782001200a1002220d41086a2900003703002002200d2900003703d001200d102c200f20012903002208370300200220022903d001220a3703c0012013200a370000200520083700002003200029030037030020092013290300370300200c200629030037030020022002290378370398012002410036024820024198016aad42808080808004842234200b4280808080c000841001417f2004410020101b223641016a220120012036491b410d744128722237417f4c0d032037102a2203450d012003200e370020200320333a001f200320323a001e200320313a001d200320303a001c2003202f3a001b2003202e3a001a2003202d3a00192003202c3a00182003202b3a00172003202a3a0016200320293a0015200320283a0014200320273a0013200320263a0012200320253a0011200320243a0010200320233a000f200320223a000e200320213a000d200320203a000c2003201f3a000b2003201e3a000a2003201d3a00092003201c3a00082003201b3a00072003201a3a0006200320193a0005200320183a0004200320173a0003200320163a0002200320153a0001200320143a0000200241d0016aad4280808080c00084210a4128213841002100410021394100213a410021010340024002400240024002402001450d0020042006470d010b034020012109200020364f0d02200241d0016a41086a220141bac6c500ad4280808080c000841002220641086a290000370300200220062900003703d0012006102c200241c0016a41086a220c2001290300370300200220022903d0013703c0012001418dc7c500ad42808080809002841002220641086a290000370300200220062900003703d0012006102c200241f8006a41086a22062001290300370300200220022903d001370378200220003602d001200a100622012d001f210d20012d001e210f20012d001d210520012d001c210420012d001b211020012d001a211120012d0019213b20012d0018213c20012d0017213d20012d0016213e20012d0015213f20012d0014214020012d0013214120012d0012214220012d0011214320012d0010214420012d000f214520012d000e214620012d000d214720012d000c214820012d000b214920012d000a214a20012d0009214b20012d0008214c20012d0007214d20012d0006214e20012d0005214f20012d0004215020012d0003215120012d0002215220012d0001215320012d000021542001102c41c000102a2201450d07200120022903c001370000200120022903783700102001200d3a003f2001200f3a003e200120053a003d200120043a003c200120103a003b200120113a003a2001203b3a00392001203c3a00382001203d3a00372001203e3a00362001203f3a0035200120403a0034200120413a0033200120423a0032200120433a0031200120443a0030200120453a002f200120463a002e200120473a002d200120483a002c200120493a002b2001204a3a002a2001204b3a00292001204c3a00282001204d3a00272001204e3a00262001204f3a0025200120503a0024200120513a0023200120523a0022200120533a0021200120543a0020200141086a200c290300370000200141186a2006290300370000200241f8006a200141c000109a01024020022802782206450d002001ad428080808080088410050b200229027c21082001102c2006410120061b2201450d022008420020061b2208422088a7210602402009450d002055450d00203a102c0b200041016a21002008a721552001213a200121392006450d000b200120064105746a2104200121392001213a200121060b20024198016a41186a200641186a220929000037030020024198016a41106a200641106a220c29000037030020024198016a41086a200641086a220d2900003703002002200629000037039801200d2900002108200c290000210b2006290000210e200241c8006a41186a220c2009290000370300200241c8006a41106a2209200b370300200241c8006a41086a220d20083703002002200e370348200241f8006a41186a220f200c290300370300200241f8006a41106a220c2009290300370300200241f8006a41086a2205200d29030037030020022002290348370378203720386b411f4b0d02203841206a22092038490d082037410174220d2009200d20094b1b220941004e0d010c080b02402009450d002055450d002039102c0b2038ad4220862003ad84100622012d001f210920012d001e210c20012d001d210d20012d001c210f20012d001b210520012d001a210420012d0019211020012d0018211120012d0017213b20012d0016213c20012d0015213d20012d0014213e20012d0013213f20012d0012214020012d0011214120012d0010214220012d000f214320012d000e214420012d000d214520012d000c214620012d000b214720012d000a214820012d0009214920012d0008214a20012d0007214b20012d0006214c20012d0005214d20012d0004214e20012d0003214f20012d0002215020012d0001215120012d000021522001102c02402037450d002003102c0b200241f8006a41186a22034200370300200241f8006a41106a22534200370300200241f8006a41086a2200420037030020024200370378200241d0016a41086a220141bac6c500ad4280808080c000841002220641086a290000370300200220062900003703d0012006102c20002001290300370300200220022903d00122083703c00120022008370378200141f3c6c500ad4280808080e001841002220641086a290000370300200220062900003703d0012006102c200241c0016a41086a20012903002208370300200220022903d001220a3703c0012013200a370000201341086a200837000020024198016a41086a200029030037030020024198016a41106a205329030037030020024198016a41186a200329030037030020022002290378370398014101102a2201450d04200120523a0000200141014102102e2201450d04200120513a0001200141024104102e2201450d042001204f3a0003200120503a0002200141044108102e2201450d042001204b3a00072001204c3a00062001204d3a00052001204e3a0004200141084110102e2201450d04200120433a000f200120443a000e200120453a000d200120463a000c200120473a000b200120483a000a200120493a00092001204a3a0008200141104120102e2201450d04200120093a001f2001200c3a001e2001200d3a001d2001200f3a001c200120053a001b200120043a001a200120103a0019200120113a00182001203b3a00172001203c3a00162001203d3a00152001203e3a00142001203f3a0013200120403a0012200120413a0011200120423a001020342001ad428080808080048410012001102c200241c8006a41186a22034200370300200241c8006a41106a22094200370300200241c8006a41086a2200420037030020024200370348200241d0016a41086a220141bac6c500ad4280808080c000841002220641086a290000370300200220062900003703d0012006102c20002001290300370300200220022903d00122083703c00120022008370348200141e9c6c500ad4280808080a001841002220641086a290000370300200220062900003703d0012006102c200241c0016a41086a20012903002208370300200220022903d001220a3703c0012007200a370000200741086a2008370000200241f8006a41086a2000290300370300200241f8006a41106a2009290300370300200241f8006a41186a2003290300370300200220022903483703784101102a2201450d04200120143a0000200141014102102e2201450d04200120153a0001200141024104102e2201450d04200120173a0003200120163a0002200141044108102e2201450d042001201b3a00072001201a3a0006200120193a0005200120183a0004200141084110102e2201450d04200120233a000f200120223a000e200120213a000d200120203a000c2001201f3a000b2001201e3a000a2001201d3a00092001201c3a0008200141104120102e2201450d04200120333a001f200120323a001e200120313a001d200120303a001c2001202f3a001b2001202e3a001a2001202d3a00192001202c3a00182001202b3a00172001202a3a0016200120293a0015200120283a0014200120273a0013200120263a0012200120253a0011200120243a001020122001ad428080808080048410012001102c200241c8006a41186a22004200370300200241c8006a41106a22064200370300200241c8006a41086a2203420037030020024200370348200241d0016a41086a220141bac6c500ad4280808080c000841002220941086a290000370300200220092900003703d0012009102c20032001290300370300200220022903d00122083703c00120022008370348200141f3c6c500ad4280808080e001841002220941086a290000370300200220092900003703d0012009102c200241c0016a41086a20012903002208370300200220022903d001220a3703c0012007200a370000200741086a2008370000200241f8006a41086a2003290300370300200241f8006a41106a2006290300370300200241f8006a41186a200029030037030020022002290348370378200241c8006a200241f8006a10800341002101410021094100210c4100210d4100210f410021054100210441002110410021114100213b4100213c4100213d4100213e4100213f410021404100214141002142410021434100214441002145410021464100214741002148410021494100214a4100214b4100214c4100214d4100214e4100214f4100215041002151024020022d00484101470d0020032d0000214a200241d1006a2d00002149200241d2006a2d00002148200241d3006a2d00002147200241d4006a2d00002146200241d5006a2d00002145200241d6006a2d00002144200241d7006a2d0000214320062d00002142200241d9006a2d00002141200241da006a2d00002140200241db006a2d0000213f200241dc006a2d0000213e200241dd006a2d0000213d200241de006a2d0000213c200241df006a2d0000213b20002d00002111200241e1006a2d00002110200241e2006a2d00002104200241e3006a2d00002105200241e4006a2d0000210f200241e5006a2d0000210d200241e6006a2d0000210c200241e7006a2d00002109200241e8006a2d0000210120022d0049215120022d004a215020022d004b214f20022d004c214e20022d004d214d20022d004e214c20022d004f214b0b200241f4006a200d3a0000200241f0006a20103a0000200241ec006a203d3a0000200241e8006a20413a0000200241e4006a20453a0000200020493a0000200241dc006a204d3a0000200620513a0000200241c8006a410c6a200241386a41086a2802003602002002200229033837024c200220013a0077200220093a00762002200c3a00752002200f3a0073200220053a0072200220043a0071200220113a006f2002203b3a006e2002203c3a006d2002203e3a006b2002203f3a006a200220403a0069200220423a0067200220433a0066200220443a0065200220463a0063200220473a0062200220483a00612002204a3a005f2002204b3a005e2002204c3a005d2002204e3a005b2002204f3a005a200220503a00592002410036024820024198016a200241c8006a108b0220024183016a20024198016a41086a280200360000200220022903980137007b20024198016a410c6a200241ff006a290000370000200241c28289aa0436009901200241023a0098012002200229007837009d0120024198016a109001024020022802480d00200241d0006a280200450d00200228024c102c0b200241e0016a24000f0b0240024020370d002009102a21030c010b200320372009102e21030b2003450d03200921370b200641206a2106200320386a22092002290378370000200941186a200f290300370000200941106a200c290300370000200941086a2005290300370000203841206a21380c000b0b41e2a8c20041c9001054000b1033000b41e2a8c20041c9001054000b103a000b1035000bd71302157f037e230041f0026b220224002002412036021420022001360210200241186a2001ad42808080808004841003108d0102400240200228021822030d00200041003602000c010b200228021c21042002200241206a28020036023c20022003360238200241086a200241386a107502400240024002400240024020022802080d00200228023c220541c4006e220641c4006c2201417f4c0d01200228020c210702400240024020010d00410421080c010b2001102a2208450d010b2007450d03200241c8026a41077221094100210a03400240024002400240024002402005450d0020022005417f6a220b36023c20022002280238220c41016a360238200c2d0000220141014b0d000240024020010e020001000b200b41034d0d0120024184026a41026a20024188026a41026a2d00003a0000200241e8016a41086a200241a8026a41086a290200370300200241e8016a41106a200241a8026a41106a290200370300200241e8016a41186a200241a8026a41186a2d00003a0000200241c8016a41086a200241c8026a41086a290100370300200241c8016a41106a200241c8026a41106a290100370300200241c8016a41186a200241c8026a41186a290100370300200220022f0088023b018402200220022902a8023703e801200220022901c8023703c80120022005417b6a220d36023c2002200c41056a360238200c280001210e200220022f01a4023b01c6014100210f0c030b4100210f200241003a00e8022005417e6a211003400240200b200f2201470d000240200141ff0171450d00200241003a00e8020b4100210d4102210f0c040b200241c8026a20016a200c20016a220f41016a2d00003a00002002200f41026a3602382002200141016a220f3a00e8022002201036023c2010417f6a2110200f4120470d000b200241a4026a41026a221120022d00ca023a000020024188026a41086a2212200941086a29000037030020024188026a41106a2213200941106a29000037030020024188026a41186a2214200941186a2d00003a0000200220022f01c8023b01a40220022009290000370388024100210d200b200f460d0120022800cb0221152002201036023c2002200c200f6a220b41026a3602380240200b41016a2d0000220f41014d0d002010210d4102210f0c030b024002400240200f0e020100010b4100210f200241003a00e802200520016b417c6a2101034002402010200f470d000240200f41ff0171450d00200241003a00e8020b4100210d0c050b200241c8026a200f6a200b200f6a220c41026a2d00003a00002002200c41036a3602382002200f41016a220c3a00e8022002200136023c2001417f6a2101200c210f200c4120470d000b200241a8026a41186a200241c8026a41186a290300370300200241a8026a41106a200241c8026a41106a290300370300200241a8026a41086a200241c8026a41086a290300370300200220022903c8023703a8022010200c6b210d410121160c010b410021162010210d0b200241c8016a41186a200241a8026a41186a290300370300200241c8016a41106a200241a8026a41106a290300370300200241c8016a41086a200241a8026a41086a29030037030020024184026a41026a20112d00003a0000200241e8016a41086a2012290300370300200241e8016a41106a2013290300370300200241e8016a41186a20142d00003a0000200220022903a8023703c801200220022f01a4023b01840220022002290388023703e8014101210f2015210e0c020b200241c2016a41026a20024184026a41026a2d00003a0000200241a8016a41086a200241e8016a41086a290300370300200241a8016a41106a200241e8016a41106a290300370300200241a8016a41186a200241e8016a41186a2d00003a000020024188016a41086a200241c8016a41086a29030037030020024188016a41106a200241c8016a41106a29030037030020024188016a41186a200241c8016a41186a290300370300200220022f0184023b01c201200220022903e8013703a801200220022903c80137038801200220022f01c6013b0186010c020b4102210f0b200241c2016a41026a220120024184026a41026a2d00003a0000200241a8016a41086a220c200241e8016a41086a290300370300200241a8016a41106a220b200241e8016a41106a290300370300200241a8016a41186a2205200241e8016a41186a2d00003a000020024188016a41086a2211200241c8016a41086a29030037030020024188016a41106a2212200241c8016a41106a29030037030020024188016a41186a2213200241c8016a41186a290300370300200220022f0184023b01c201200220022903e8013703a801200220022903c80137038801200220022f01c6013b018601200f4102460d00200a41016a211020024182016a41026a221420012d00003a0000200241e8006a41086a2215200c290300370300200241e8006a41106a220c200b290300370300200241e8006a41186a220b20052d00003a0000200241c8006a41086a22052011290300370300200241c8006a41106a22112012290300370300200241c8006a41186a22122013290300370300200220022f01c2013b018201200220022903a8013703682002200229038801370348200220022f0186013b01462006200a470d020240200a41017422012010200120104b1b2206ad42c4007e2217422088a70d002017a7220141004e0d020b1035000b200241003602282006450d072008102c0c070b02400240200a0d002001102a21080c010b2008200a41c4006c2001102e21080b2008450d020b2008200a41c4006c6a2201200f3a00002001200e360004200141036a20142d00003a0000200120022f0182013b0001200b2d0000210f200c29030021172015290300211820022903682119200120163a002120012019370008200141106a2018370000200141186a2017370000200141206a200f3a00002001413a6a2012290300370000200141326a20112903003700002001412a6a200529030037000020012002290348370022200120022f01463b0042200d21052010210a20102007470d000b200241306a20073602002002200636022c200220083602280c050b1033000b200241003602280c020b103a000b200241306a20073602002002200636022c2002200836022820080d010b200241003602b002200242013703a8022002410b3602cc012002200241106a3602c8012002200241a8026a36028801200241dc026a4101360200200242013702cc02200241d0b0c2003602c8022002200241c8016a3602d80220024188016a41c49ac500200241c8026a10391a20023502b00242208620023502a8028410042000410036020020022802ac02450d0120022802a802102c0c010b20002002290328370200200041086a200241286a41086a2802003602000b2004450d002003102c0b200241f0026a24000b860701057f230041106b2203240020034100360208200342013703002002200310670240024002402002450d00200241c4006c210403400240024020012d00004101460d0002400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d06200241017422062005200620054b1b22064100480d060240024020020d002006102a21050c010b200328020020022006102e21050b2005450d052003200636020420032005360200200328020821020b2003200241016a360208200520026a41003a0000200141046a28020021060240024020032802042205200328020822026b4104490d00200328020021050c010b200241046a22072002490d06200541017422022007200220074b1b22024100480d060240024020050d002002102a21050c010b200328020020052002102e21050b2005450d052003200236020420032005360200200328020821020b2003200241046a360208200520026a20063600000c010b02400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d05200241017422062005200620054b1b22064100480d050240024020020d002006102a21050c010b200328020020022006102e21050b2005450d042003200636020420032005360200200328020821020b2003200241016a360208200520026a41013a00002003200336020c200141016a2003410c6a1094020240200141216a2d00004101460d0002400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d06200241017422062005200620054b1b22064100480d060240024020020d002006102a21050c010b200328020020022006102e21050b2005450d052003200636020420032005360200200328020821020b2003200241016a360208200520026a41003a00000c010b02400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d05200241017422062005200620054b1b22064100480d050240024020020d002006102a21050c010b200328020020022006102e21050b2005450d042003200636020420032005360200200328020821020b2003200241016a360208200520026a41013a0000200141226a20031091010b200141c4006a2101200441bc7f6a22040d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b1033000b1035000ba20f06017f017e057f017e057f017e230041f0016b2201240042002102200141e0006a41186a22034200370300200141e0006a41106a22044200370300200141e0006a41086a2205420037030020014200370360200141d0006a41086a220641a4c6c500ad4280808080a001841002220741086a290000370300200120072900003703502007102c2005200629030037030020012001290350220837034020012008370360200641baecc100ad4280808080e000841002220741086a290000370300200120072900003703502007102c200420012903502208370300200141206a41086a2005290300370300200141206a41106a2008370300200141206a41186a2006290300370300200120083703402001200129036037032020014180016a200141206a412010d30120012d0080012107200320014199016a290000370300200420014191016a290000370300200520014189016a29000037030020012001290081013703600240024020074101470d0020002001290360370000200041186a2003290300370000200041106a2004290300370000200041086a20052903003700000c010b20014180016a41186a420037030020014180016a41106a2209420037030020014180016a41086a22074200370300200142003703800120064191b0c200ad4280808080e000841002220a41086a2900003703002001200a290000370350200a102c200720062903003703002001200129035037038001200641cab0c200ad4280808080e000841002220a41086a2900003703002001200a290000370350200a102c20092001290350220837030020052007290300370300200420083703002003200629030037030020012008370320200120012903800137036020014180016a200141e0006a10e40202400240200128028001220a0d004104210a410021060c010b2001290284012202422088a721060b02400240200641246c2206450d002006415c6a2105200a210603400240024020062d00004101460d002005450d030c010b200641016a2800002103200641086a28020021072001200641106a280200360264200120073602600240200341c28289aa04460d0020050d010c030b20014180016a200141e0006a10e50220012d00800122054102460d02200141e4016a2802002109200128028401210b20014180016a41186a420037030020014180016a41106a220c420037030020014180016a41086a220342003703002001420037038001200141d0006a41086a220641ecddc500ad4280808080f000841002220741086a290000370300200120072900003703502007102c200320062903003703002001200129035037038001200641c9f8c200ad4280808080a001841002220741086a290000370300200120072900003703502007102c200c20012903502208370300200141e0006a41086a2003290300370300200141e0006a41106a2008370300200141e0006a41186a200629030037030020012008370320200120012903800137036020014180016a200141e0006a412010d0012001280280012206410120061b2107410021030240200b200920054101711b2205200129028401420020061b2208422088a74f0d00200720054105746a2206450d00200141186a200641186a290000370300200141106a200641106a290000370300200141086a200641086a29000037030020012006290000370300410121030b02402008a7450d002007102c0b2003450d0220014180016a41186a2207200141186a29030037030020014180016a41106a2209200141106a29030037030020014180016a41086a220b200141086a2903003703002001200129030037038001200141e0006a41186a220c4200370300200141e0006a41106a220d4200370300200141e0006a41086a2205420037030020014200370360200141d0006a41086a220641a4c6c500ad4280808080a001841002220341086a290000370300200120032900003703502003102c2005200629030037030020012001290350220837034020012008370360200641baecc100ad4280808080e000841002220341086a290000370300200120032900003703502003102c200141c0006a41086a2006290300220837030020012001290350220e3703402004200e370000200441086a2008370000200141206a41086a2005290300370300200141206a41106a200d290300370300200141206a41186a200c29030037030020012001290360370320200141203602642001200141206a36026020014180016a200141e0006a10a102200041186a2007290300370000200041106a2009290300370000200041086a200b29030037000020002001290380013700000c030b200641246a21062005415c6a21050c000b0b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000b02402002422088a72206450d00200641246c2105200a210603400240024020062d0000220341034b0d0002400240024020030e0404000102040b2006410c6a280200450d03200641086a280200102c0c030b2006410c6a280200450d02200641086a280200102c0c020b2006410c6a280200450d01200641086a280200102c0c010b200641086a280200450d00200641046a280200102c0b200641246a21062005415c6a22050d000b0b2002a7450d00200a102c0b200141f0016a24000bfd0d09057f017e017f017e037f017e027f027e087f230041e0006b22012400200141206a41186a22024200370300200141206a41106a22034200370300200141206a41086a2204420037030020014200370320200141d0006a41086a22054196e0c500ad4280808080f0008422061002220741086a290000370300200120072900003703502007102c2004200529030037030020012001290350220837034020012008370320200541c2e0c500ad4280808080e002841002220741086a290000370300200120072900003703502007102c200320012903502208370300200141086a22092004290300370300200141106a220a2008370300200141186a220b20052903003703002001200837034020012001290320370300200141206a200110e4032001290328210c200128022421072001280220210d20024200370300200342003703002004420037030020014200370320200520061002220e41086a2900003703002001200e290000370350200e102c2004200529030037030020012001290350370320200541bafdc200ad4280808080e001841002220e41086a2900003703002001200e290000370350200e102c20032001290350220837030020092004290300370300200a2008370300200b20052903003703002001200837034020012001290320370300200141206a2001412010d001200d410020071b210b200c420020071b210f20012902244200200128022022051b21102007410420071b21112005410120051b210d2000280200211220002802042113024002400240024020002802082205450d002012200541246c6a21142010422088a741057421152012210903402009280220210a200941086a2900002108200941106a29000021062009290000210c2002200941186a29000037030020032006370300200420083703002001200c370320200941246a21094100210020152107200d21050240024003402007450d02200141206a2005460d01200041016a2100200741606a21072005200141206a412010dd05210e200541206a2105200e0d000b200e4541016a41017120006a417f6a21000b200b200a6a2207200b490d000240200041016a220e200f422088a722054d0d000240200fa7220b20056b200e2005200e20054b1b221620056b220e4f0d002005200e6a22172005490d07200b41017422182017201820174b1b221741ffffffff03712017470d07201741027422184100480d0702400240200b0d002018102a21110c010b2011200b4102742018102e21110b2011450d052017ad210f0b201120054102746a210b02400240200e4102490d00200b410020162005417f736a220e41027410da051a2011200520166a20056b4102746a417c6a210b200e20056a21050c010b200e450d010b200b4100360200200541016a21050b200520004d0d04201120004102746a22002000280200200a6a360200200f42ffffffff0f832005ad42208684210f2007210b0b20092014470d000b0b02402013450d002012102c0b02402010a7450d00200d102c0b200141206a41186a220e4200370300200141206a41106a22094200370300200141206a41086a2207420037030020014200370320200141d0006a41086a22054196e0c500ad4280808080f000841002220041086a290000370300200120002900003703502000102c2007200529030037030020012001290350220837034020012008370320200541c2e0c500ad4280808080e002841002220041086a290000370300200120002900003703502000102c200141c0006a41086a2005290300220837030020012001290350220637034020032006370000200341086a2008370000200141086a2007290300370300200141106a2009290300370300200141186a200e290300370300200120012903203703000240024020110d002001ad428080808080048410050c010b20014100360228200142013703204104102a2205450d012005200b36000020014284808080c00037022420012005360220200f422088a72205200141206a10670240024020050d002001280228210a20012802242109200128022021070c010b2005410274210b4100200128022822056b2100200128022421092011210e0340200e280200210302400240200920006a4104490d00200128022021070c010b200541046a22072005490d062009410174220a2007200a20074b1b220a4100480d060240024020090d00200a102a21070c010b20012802202009200a102e21070b2007450d042001200a36022420012007360220200a21090b200e41046a210e2001200541046a220a360228200720056a20033600002000417c6a2100200a2105200b417c6a220b0d000b0b2001ad4280808080800484200aad4220862007ad84100102402009450d002007102c0b2011450d00200fa7450d002011102c0b200141e0006a24000f0b1033000b41a888c600200020051038000b1035000b940703067f017e057f230041a0016b2201240020014180016a41186a2202420037030020014180016a41106a2203420037030020014180016a41086a220442003703002001420037038001200141f0006a41086a220541ecddc500ad4280808080f000841002220641086a290000370300200120062900003703702006102c200420052903003703002001200129037037038001200541f3ddc500ad4280808080c001841002220641086a290000370300200120062900003703702006102c200320012903702207370300200141d0006a41086a22062004290300370300200141d0006a41106a22082007370300200141d0006a41186a22092005290300370300200120073703102001200129038001370350200141086a200141d0006a4120109401200128020c210a2001280208210b200141106a41186a200041186a290000370300200141106a41106a200041106a290000370300200141106a41086a200041086a29000037030020012000290000370310200541a3dbc500ad42808080808001841002220041086a290000370300200120002900003703702000102c200141306a41086a220c20052903003703002001200129037037033020054182aac500ad4280808080e001841002220041086a290000370300200120002900003703702000102c200141c0006a41086a22002005290300370300200120012903703703402001200a4100200b1b3602702002200141f0006aad4280808080c000841006220541186a2900003703002003200541106a2900003703002004200541086a29000037030020012005290000370380012005102c2009200229030037030020082003290300370300200620042903003703002001200129038001370350024041c000102a2205450d00200520012903303700002005200129034037001020052001290350370020200541086a200c290300370000200541186a2000290300370000200541286a2006290300370000200541306a2008290300370000200541386a200929030037000020014180016a200141106a109f01200541c000418001102e2205450d002005200129008001370040200541d8006a20014198016a290000370000200541d0006a20014190016a290000370000200541c8006a20014188016a2900003700002001200541e0001094012001200128020441016a410120012802001b360280012005ad4280808080800c8420014180016aad4280808080c0008410012005102c200141a0016a24000f0b1033000b3802017f017e230041106b220324002003200210b701200329030021042000200341086a29030037030820002004370300200341106a24000b800201057f230041c0006b2205240002400240024020030d00200041003602000c010b2003280208220641164d0d0120032802002107200541206a41186a22082004ad42808080808004841006220341186a290000370300200541206a41106a2204200341106a290000370300200541206a41086a2209200341086a290000370300200520032900003703202003102c200541186a2008290300370300200541106a2004290300370300200541086a20092903003703002005200529032037030020002006ad4220862007ad84200641696aad422086200741176aad8441012005ad42808080808004841008108d010b200541c0006a24000f0b411720061047000baf0201027f23004190016b220324002003200210ee010240024020032d000022024102470d00200041003a00000c010b200341e0006a200341286a290300370300200341e8006a200341306a290300370300200341d8006a41186a200341386a290300370300200341d8006a41206a200341c0006a290300370300200341d8006a41286a200341c8006a290300370300200341d8006a41306a200341d0006a2802003602002003200341206a29030037035802402002450d00200041003a00000c010b2003411c6a2802002102200341186a28020021042000200329026c370001200041013a0000200041196a20034184016a290200370000200041116a200341fc006a290200370000200041096a200341d8006a411c6a2902003700002002450d002004102c0b20034190016a24000bfe0201057f230041c0016b22022400200241086a220341e4d2c500ad42808080808001841002220441086a290000370300200220042900003703002004102c200241d8006a41086a2205200329030037030020022002290300370358200341a9e4c300ad4280808080e001841002220441086a290000370300200220042900003703002004102c200241e8006a41086a220620032903003703002002200229030037036820022001109f01024041c000102a2204450d00200420022903583700002004200229036837001020042002290000370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241106a290000370000200441386a200241186a2900003700002002200441c00010a50120022d00002103200241e8006a200241017241d70010db051a0240024020034102470d00200041023a00000c010b200020033a0000200041016a200241e8006a41d70010db051a0b2004102c200241c0016a24000f0b1033000bd10201057f230041d0006b22022400200241306a41086a220341e4d2c500ad42808080808001841002220441086a290000370300200220042900003703302004102c200241106a41086a2205200329030037030020022002290330370310200341a9e4c300ad4280808080e001841002220441086a290000370300200220042900003703302004102c200241206a41086a2206200329030037030020022002290330370320200241306a2001109f01024041c000102a22040d001033000b200420022903103700002004200229032037001020042002290030370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241c0006a290000370000200441386a200241306a41186a290000370000200241086a200441c000410141004100109701200228020821032004102c200241d0006a240020034101460b870102017f037e230041e0006b22032400200341086a200210ee010240024020032d000822024102470d00420021040c010b2002410173ad2104200341186a2903002105200341106a290300210620020d00200341246a280200450d00200341206a280200102c0b2000200637030820002004370300200041106a2005370300200341e0006a24000be72e0a057f067e0d7f067e057f027e0d7f027e067f027e230041a0056b22022400200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b200241fc006a20042f0106360200200241e0006a41186a4100360200200241f4006a200436020020022003360280012002410036027042002107200242003703682002200136026420024100360260200241c8016a200241e0006a10f2010240024020022903e80122084202520d00420021094200210a0c010b200241f0046aad4280808080800484210b200241d0046aad4280808080800484210c200241fc016a210d200241c8016a412c6a210e200241c8016a410472210f200241c8016a41106a2103200241a5026a2110200241c8016a41086a2111200241a8036a412c6a2112200241a8036a41106a2113200241f8016a211420024190026a211542002107420021094200210a0340200241a8016a41186a2205200241c8016a41186a2201290300370300200241a8016a41106a22062003290300370300200241a8016a41086a2216201129030037030020024188016a41086a2217201041086a29000037030020024188016a41106a2218201041106a29000037030020024188016a41186a2219201041186a290000370300200220022903c8013703a80120022010290000370388012014290300211a2015290300211b20022903f001211c200229038802211d200229038002211e200229039802211f20022802a002212020022d00a402212120022d00c5022104200241c8026a41186a2005290300370300200241c8026a41106a2006290300370300200241c8026a41086a2016290300370300200220022903a8013703c802200241e8026a41186a22162019290300370300200241e8026a41106a22222018290300370300200241e8026a41086a2223201729030037030020022002290388013703e802024002400240024002402004ad42ff0183200820085022051b4201520d00200241c8016a200241c8026a4200201c20051b4200201a20051b10a00120022d00e0012105200241c8006a200a2007200920022903c80120022903d001200329030010f301200241c8006a41106a2903002109200229035021072002290348210a20050d010b024002400240202141ff0171222441014622050d00200441ff01710d002020201ea772450d010b200241c8016a200241c8026a10ee010240024020022d00c8012217417f6a220641014b0d00024020060e020002000b20170d0420022802e401450d0420022802e001102c0c040b20024188036a41086a200d41086a29020037030020024188036a41106a200d41106a29020037030020024188036a41186a200d41186a2902003703002002200d290200370388032003290300212520022903d0012126200228029c02212720022802f801212820022802f401212920022802f001212a20022802ec01212b20022802e801212c20022802e401212d20022802e001212e0c020b4102212920170d0120022802e401450d0120022802e001102c0c010b201fa7210402400240201f422088a722050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b200220203602e801200241003602e001200241003602d801200242003703d001200220013602cc01200241003602c801200220043602dc01200220042f01063602e401200241c8016a10f4010c040b4102212f0240024002400240024020294102460d00202c417f4c0d0202400240202c0d0041002130410121310c010b202c2130202c102a2231450d020b2031202e202c10db051a200120024188036a41186a290300370300200320024188036a41106a290300370300201120024188036a41086a29030037030020022002290388033703c8012029410146212f202c2132202b21332026213420252135202a2136202821370b200241f0046a41186a22182001290300370300200241f0046a41106a22192003290300370300200241f0046a41086a22212011290300370300200241d0046a41086a22382023290300370300200241d0046a41106a22392022290300370300200241d0046a41186a223a2016290300370300200220022903c8013703f004200220022903e8023703d00402400240024002400240024002400240200441ff01710d00202f4102460d01201220022903f004370200201241086a2021290300370200201241106a2019290300370200201241186a2018290300370200200220343703a803200220373602d0032002202f3602cc03200220363602c803200220333602c403200220323602c003200220303602bc03200220313602b803200220353703b0032036213b2034213c2035213d203321060c030b202f4102470d010b2005450d03200241f8036a200241c8026a10f501200142003703002003420037030041082106200241c8016a41086a22054200370300200242003703c801200241b0046a41086a22044191b0c200ad4280808080e000841002221741086a290000370300200220172900003703b0042017102c20052004290300370300200220022903b0043703c801200441acb0c200ad4280808080e000841002221741086a290000370300200220172900003703b0042017102c20024190056a41086a20042903002208370300200220022903b004221c370390052003201c370000200341086a200837000020024188046a41086a200529030037030020024188046a41106a200329030037030020024188046a41186a2001290300370300200220022903c80137038804200241386a20024188046a4120109401200228023c210420022802382105201341086a200241f8036a41086a280200360200201320022903f803370200201220022903d004370100201241086a200241d0046a41086a290300370100201241106a2039290300370100201241186a203a290300370100427f213c2002427f3703b0032002427f3703a803200241083602c4034100212f200241003602cc0320022004410020051b223b3602c803427f213d0c010b203241164d0d072032ad4220862031ad84203241696aad422086203141176aad84410110072005450d01200241f8036a200241c8026a10f501200142003703002003420037030041082106200241c8016a41086a22054200370300200242003703c801200241b0046a41086a22044191b0c200ad4280808080e000841002221741086a290000370300200220172900003703b0042017102c20052004290300370300200220022903b0043703c801200441acb0c200ad4280808080e000841002221741086a290000370300200220172900003703b0042017102c20024190056a41086a20042903002208370300200220022903b004221c370390052003201c370000200341086a200837000020024188046a41086a200529030037030020024188046a41106a200329030037030020024188046a41186a2001290300370300200220022903c80137038804200241c0006a20024188046a41201094012002280244210420022802402105201341086a200241f8036a41086a280200360200201320022903f803370200201220022903d004370100201241086a200241d0046a41086a290300370100201241106a2039290300370100201241186a203a290300370100427f213c2002427f3703b0032002427f3703a803200241083602c4034100212f200241003602cc0320022004410020051b223b3602c80302402030450d002031102c427f213c0b427f213d0b0240201e4201520d002002201d3703a8032002201b3703b003201d213c201b213d0b02402024450d00201220022903e802370000201241186a2016290300370000201241106a2022290300370000201241086a20232903003700000b02402020450d00200142003703002003420037030020114200370300200242003703c801200241b0046a41086a22044191b0c200ad4280808080e000841002220541086a290000370300200220052900003703b0042005102c20112004290300370300200220022903b0043703c801200441acb0c200ad4280808080e000841002220541086a290000370300200220052900003703b0042005102c20024190056a41086a20042903002208370300200220022903b004221e370390052003201e370000200341086a200837000020024188046a41086a201129030037030020024188046a41106a200329030037030020024188046a41186a2001290300370300200220022903c80137038804200241306a20024188046a41201094014101212f200241013602cc0320022002280234410020022802301b3602d0030b201fa72104201f422088a722160d02200421050c030b200241c8026a10f6012030450d002031102c0b20294102460d06202d0d054100212d0c060b2016211720042105034020052802ec0321052017417f6a22170d000b0340200420042f01064102746a41ec036a28020021042016417f6a22160d000b0b20042f01062116200220203602a804200220163602a404200241003602a0042002200436029c04200241003602980420024200370390042002200536028c042002410036028804200241c8016a20024188046a10f70120022802c8014101470d0620022802c003222041696aad42208620022802b803220441176aad8421082020ad4220862004ad84211f0340200241b0046a41186a200f41186a290200221e370300200241b0046a41106a200f41106a290200221c370300200241b0046a41086a200f41086a290200221a3703002002200f290200221d3703b00420022802ec01210520022802f001211720022802f4012116203a201e3703002039201c3703002038201a3703002002201d3703d00402400240202041164d0d002001200c1006220441186a2900003703002003200441106a2900003703002011200441086a290000370300200220042900003703c8012004102c201820012903003703002019200329030037030020212011290300370300200220022903c8013703f004200241c8016a201f20084101200b1008108d0120022802c8012204450d01200620022802d0016b210620022802cc01450d012004102c0c010b411720201047000b0240024020050d002001200c1006220441186a2900003703002003200441106a2900003703002011200441086a290000370300200220042900003703c8012004102c201820012903003703002019200329030037030020212011290300370300200220022903c8013703f004201f20084101200b10090c010b2001200c1006220441186a2900003703002003200441106a2900003703002011200441086a290000370300200220042900003703c8012004102c201820012903003703002019200329030037030020212011290300370300200220022903c8013703f004201f20084101200b2016ad4220862005ad84100a200620166a21062017450d002005102c0b200241c8016a20024188046a10f70120022802c8014101470d060c000b0b1033000b103a000b411720321047000b202e102c0b201fa7210402400240201f422088a722050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b200220203602e801200241003602e001200241003602d801200242003703d001200220013602cc01200241003602c801200220043602dc01200220042f01063602e401200241c8016a10f4010c020b200220063602c4030b20024188046a10f40120024188046a41186a220420024188036a41186a29030037030020024188046a41106a220120024188036a41106a29030037030020024188046a41086a220520024188036a41086a2903003703002002200229038803370388040240024020294102460d00200e200229038804370200200e41086a2005290300370200200e41106a2001290300370200200e41186a2004290300370200200220263703c801200220283602f001200220293602ec012002202a3602e8012002202b3602e4012002202d3602dc012002202e3602d8012002202736029402200220253703d0012002202c3602e001410121040240202c20022802c003470d0002400240202e20022802b8032201460d00202e2001202c10dd050d02202b2006470d020c010b202b2006470d010b200e2012412010dd050d002026203c852025203d85844200520d00202a203b470d0002402029202f470d004100210420294101470d01202820022802d003460d010b410121040b0240202d450d00202e102c0b20044102460d002004450d010b2011200241a8036a41d00010db051a200241003a00c801200241c8026a200241c8016a10f8010c010b20022802bc03450d0020022802b803102c0b200241c8016a200241e0006a10f20120022903e80122084202520d000b0b200241e0006a10f90102400240200a500d00200241c8016a41186a22054200370300200241c8016a41106a22064200370300200241c8016a41086a22014200370300200242003703c801200241b0046a41086a2204418be9c500ad4280808080800184221f1002220341086a290000370300200220032900003703b0042003102c20012004290300370300200220022903b00422083703a803200220083703c801200441c9b5c000ad4280808080d00184220c1002220341086a290000370300200220032900003703b0042003102c200620022903b004220837030020024188046a41086a2211200129030037030020024188046a41106a220f200837030020024188046a41186a221620042903003703002002200837039005200220022903c80137038804200241186a20024188046a4120109e01200241186a41106a29030021082002290320210b20022802182103200542003703002006420037030020014200370300200242003703c8012004201f1002220641086a290000370300200220062900003703b0042006102c20012004290300370300200220022903b004221f3703a8032002201f3703c8012004200c1002220641086a290000370300200220062900003703b0042006102c20052004290300221f37030020112001290300370300200f20022903b004220c3703002016201f3703002002200c37039005200220022903c80137038804200242002008420020031b220820097d200b420020031b221f200754ad7d220c201f20077d220b201f56200c200856200c2008511b22041b3703d00120024200200b20041b3703c801200241c8016a210420024188046a21010c010b02402007200984500d0041b583c100413341acfec5001036000b200241c8016a41186a22054200370300200241c8016a41106a22064200370300200241c8016a41086a22014200370300200242003703c801200241b0046a41086a2204418be9c500ad4280808080800184221f1002220341086a290000370300200220032900003703b0042003102c20012004290300370300200220022903b00422083703a803200220083703c801200441c9b5c000ad4280808080d00184220c1002220341086a290000370300200220032900003703b0042003102c200620022903b004220837030020024188046a41086a2211200129030037030020024188046a41106a220f200837030020024188046a41186a221620042903003703002002200837039005200220022903c80137038804200220024188046a4120109e01200241106a29030021082002290308210b20022802002103200542003703002006420037030020014200370300200242003703c8012004201f1002220641086a290000370300200220062900003703b0042006102c20012004290300370300200220022903b004221f3703a8032002201f3703c8012004200c1002220641086a290000370300200220062900003703b0042006102c20052004290300221f37030020112001290300370300200f20022903b004220c3703002016201f3703002002200c37039005200220022903c8013703880420022008420020031b3703d0012002200b420020031b3703c801200241c8016a210420024188046a21010b2001ad42808080808004842004ad42808080808002841001200241a0056a24000bf90503087f017e017f23004180026b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2203200128020422052f01064f0d01200241186a2206200520034105746a220741206a290000370300200241106a2208200741186a290000370300200241086a2209200741106a2900003703002002200741086a290000370300200241206a2005200341e0006c6a41e8026a41e00010db051a2001200341016a36020c200120043602082001200536020420024180016a41186a200629030037030020024180016a41106a200829030037030020024180016a41086a2009290300370300200220022903003703800120024180016a41206a200241206a41e00010db051a200020024180016a41800110db051a0c020b200042023703200c010b2001280200210702400240200528020022030d002004ad210a410021030c010b200741016a210720053301044220862004ad84210a0b2005102c200aa7210402400240200a422088a7220620032f01064f0d00200321050c010b034002400240200328020022050d002004ad210a410021050c010b200741016a210720033301044220862004ad84210a0b2003102c200aa7210420052103200a422088a7220620052f01064f0d000b0b200241186a2208200520064105746a220341206a290000370300200241106a2209200341186a290000370300200241086a220b200341106a2900003703002002200341086a290000370300200241206a2005200641e0006c6a41e8026a41e00010db051a200641027420056a418c0b6a280200210302402007417f6a2205450d00034020032802880b21032005417f6a22050d000b0b2001410036020c20012004360208200120033602042001410036020020024180016a41186a200829030037030020024180016a41106a200929030037030020024180016a41086a200b290300370300200220022903003703800120024180016a41206a200241206a41e00010db051a200020024180016a41800110db051a0b20024180026a24000ba31108037f037e047f017e017f017e037f017e230041c0016b220724002004a7210802400240024002400240024020014201510d0041012109024020084101460d00427f200320067c200220057c220a2002542208ad7c220b2008200b200354200b2003511b22081b210b427f200a20081b210a4200210c4100210d0c040b2002200556200320065620032006511b450d01200320067d2002200554ad7d210b200220057d210a4200210c0c020b4101210d024020084101470d00427f200320067c200220057c22012002542208ad7c22022008200220035420022003511b22081b210b427f200120081b210a410021094201210c0c040b200741306a20042005200642012002200310f301200741c0006a290300210b2007290338210a2007290330210c0c040b200620037d2005200254ad7d210b200520027d210a4201210c0b410021094101210d0b2001500d0020074180016a41186a220e420037030020074180016a41106a220f420037030020074180016a41086a221042003703002007420037038001200741b0016a41086a2208418be9c500ad428080808080018422111002221241086a290000370300200720122900003703b0012012102c20102008290300370300200720072903b00122013703a0012007200137038001200841c9b5c000ad4280808080d0018422131002221241086a290000370300200720122900003703b0012012102c200f20072903b0012201370300200741e0006a41086a22142010290300370300200741e0006a41106a22152001370300200741e0006a41186a22162008290300370300200720013703a0012007200729038001370360200741c8006a200741e0006a4120109e01200741c8006a41106a29030021012007290350211720072802482112200e4200370300200f4200370300201042003703002007420037038001200820111002220f41086a2900003703002007200f2900003703b001200f102c20102008290300370300200720072903b00122113703a0012007201137038001200820131002220f41086a2900003703002007200f2900003703b001200f102c200e2008290300221137030020142010290300370300201520072903b001221337030020162011370300200720133703a0012007200729038001370360200742002001420020121b220120037d2017420020121b2203200254ad7d2211200320027d2202200356201120015620112001511b22081b3703880120074200200220081b37038001200741e0006aad428080808080048420074180016aad428080808080028410010b02402004500d002009450d0120074180016a41186a2209420037030020074180016a41106a220d420037030020074180016a41086a221042003703002007420037038001200741b0016a41086a2208418be9c500ad428080808080018422021002220e41086a2900003703002007200e2900003703b001200e102c20102008290300370300200720072903b00122033703a0012007200337038001200841c9b5c000ad4280808080d0018422041002220e41086a2900003703002007200e2900003703b001200e102c200d20072903b0012203370300200741e0006a41086a220f2010290300370300200741e0006a41106a22122003370300200741e0006a41186a22142008290300370300200720033703a0012007200729038001370360200741186a200741e0006a4120109e01200741186a41106a2903002103200729032021012007280218210e20094200370300200d4200370300201042003703002007420037038001200820021002220d41086a2900003703002007200d2900003703b001200d102c20102008290300370300200720072903b00122023703a0012007200237038001200820041002220d41086a2900003703002007200d2900003703b001200d102c200920082903002202370300200f2010290300370300201220072903b001220437030020142002370300200720043703a00120072007290380013703602007420020034200200e1b220320067d20014200200e1b2202200554ad7d2204200220057d2205200256200420035620042003511b22081b3703880120074200200520081b37038001200741e0006aad428080808080048420074180016aad428080808080028410010c010b200d450d0020074180016a41186a2209420037030020074180016a41106a220d420037030020074180016a41086a221042003703002007420037038001200741b0016a41086a2208418be9c500ad428080808080018422021002220e41086a2900003703002007200e2900003703b001200e102c20102008290300370300200720072903b00122033703a0012007200337038001200841c9b5c000ad4280808080d0018422041002220e41086a2900003703002007200e2900003703b001200e102c200d20072903b0012203370300200741e0006a41086a220f2010290300370300200741e0006a41106a22122003370300200741e0006a41186a22142008290300370300200720033703a00120072007290380013703602007200741e0006a4120109e01200741106a2903002103200729030821012007280200210e20094200370300200d4200370300201042003703002007420037038001200820021002220d41086a2900003703002007200d2900003703b001200d102c20102008290300370300200720072903b00122023703a0012007200237038001200820041002220d41086a2900003703002007200d2900003703b001200d102c200920082903002202370300200f2010290300370300201220072903b001220437030020142002370300200720043703a00120072007290380013703602007427f20034200200e1b220320067c20014200200e1b220220057c22052002542208ad7c22022008200220035420022003511b22081b370388012007427f200520081b37038001200741e0006aad428080808080048420074180016aad428080808080028410010b2000200a3703082000200c370300200041106a200b370300200741c0016a24000bb00101037f230041306b220124002001200010f701024020012802004101470d000340024020012802242202450d002001280228450d002002102c0b2001200010f70120012802004101460d000b0b02402000280204220241d0e1c100460d00200228020021032002102c2003450d00200328020021002003102c2000450d00024020002802002202450d0003402000102c2002210020022802002203210220030d000b0b2000102c0b200141306a24000bc50805057f017e017f027e037f230041f0006b22022400200241d0006a41186a22034200370300200241d0006a41106a22044200370300200241d0006a41086a2205420037030020024200370350200241c0006a41086a220641e4d2c500ad428080808080018422071002220841086a290000370300200220082900003703402008102c200520062903003703002002200229034022093703302002200937035020064183d3c500ad4280808080e00184220a1002220841086a290000370300200220082900003703402008102c200420022903402209370300200241106a41086a22082005290300370300200241106a41106a220b2009370300200241106a41186a220c200629030037030020022009370330200220022903503703102002200241106a1098012002280200210d2002290308210920034200370300200442003703002005420037030020024200370350200620071002220441086a290000370300200220042900003703402004102c20052006290300370300200220022903402207370330200220073703502006200a1002220441086a290000370300200220042900003703402004102c20032006290300220737030020082005290300370300200b2002290340220a370300200c20073703002002200a370330200220022903503703102002200942017c4201200d1b2209370350200241106aad4280808080800484200241d0006aad4280808080800184100102404120102a2206450d0020062001290000370000200641186a200141186a290000370000200641106a200141106a290000370000200641086a200141086a2900003700002006412041c000102e2205450d0020052009370020200241d0006a41186a22012005ad42808080808005841006220641186a290000370300200241d0006a41106a2203200641106a290000370300200241d0006a41086a2204200641086a290000370300200220062900003703502006102c200241106a41186a2001290300370300200241106a41106a2003290300370300200241106a41086a2004290300370300200220022903503703104137102a2206450d00200642bac6a1cbc68dd9aff300370000200642f4dec98bf6ac999de400370008200641e5cc85ab073600102006413a3a0016200641ece8013b001420062002290310370017200620022f01183b001f2006200228011a360021200620022f011e3b0025200620022d00203a0027200620022d00213a0028200620022d00223a0029200620022d00233a002a200620022d00243a002b200620022d00253a002c200620022d00263a002d200620022d00273a002e200620022d00283a002f200620022d00293a0030200620022d002a3a0031200620022d002b3a0032200620022d002c3a0033200620022d002d3a0034200620022d002e3a0035200620022d002f3a0036200041bcfec3004194fec3006b410f6a36020820004137360204200020063602002005102c200241f0006a24000f0b1033000bbb0201057f230041c0006b22012400200141206a41086a220241e4d2c500ad42808080808001841002220341086a290000370300200120032900003703202003102c200141086a2204200229030037030020012001290320370300200241a9e4c300ad4280808080e001841002220341086a290000370300200120032900003703202003102c200141106a41086a2205200229030037030020012001290320370310200141206a2000109f01024041c000102a22030d001033000b200320012903003700002003200129031037001020032001290020370020200341086a2004290300370000200341186a2005290300370000200341286a2002290000370000200341306a200141306a290000370000200341386a200141206a41186a2900003700002003ad428080808080088410052003102c200141c0006a24000bdd0605057f047e017f017e047f23004190016b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2203200128020422052f01064f0d01200241e0006a41186a200520034105746a220641206a2900002207370300200241e0006a41106a200641186a2900002208370300200241e0006a41086a200641106a29000022093703002002200641086a290000220a370360200241306a41086a20052003410c6c6a220641f0026a280200220b360200200641e8026a290200210c2001200341016a36020c20012004360208200120053602042002200c3703302000200a3702042000410c6a2009370200200041146a20083702002000411c6a2007370200200041246a200c3702002000412c6a200b360200200041013602000c020b200041003602000c010b2001280200210602400240200528020022030d002004ad210c410021030c010b200641016a210620053301044220862004ad84210c0b2005102c200ca7210402400240200c422088a7220b20032f01064f0d00200321050c010b034002400240200328020022050d002004ad210c410021050c010b200641016a210620033301044220862004ad84210c0b2003102c200ca7210420052103200c422088a7220b20052f01064f0d000b0b200241306a41186a220d2005200b4105746a220341206a290000370300200241306a41106a220e200341186a290000370300200241306a41086a220f200341106a2900003703002002200341086a290000370330200241d0006a41086a22102005200b410c6c6a220341f0026a2802003602002002200341e8026a290200370350200b41027420056a41f0036a280200210302402006417f6a2205450d00034020032802ec0321032005417f6a22050d000b0b2001410036020c200120043602082001200336020420014100360200200241e0006a41186a200d290300220c370300200241e0006a41106a200e2903002207370300200241e0006a41086a200f290300220837030020024188016a201028020022033602002000200229033022093702042000410c6a2008370200200041146a20073702002000411c6a200c370200200041246a2002290350220c3702002000412c6a2003360200200220093703602002200c37038001200041013602000b20024190016a24000b8a0401057f230041c0006b22022400200241206a41086a220341e4d2c500ad42808080808001841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341a9e4c300ad4280808080e001841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2000109f01024041c000102a2204450d00200420022903003700002004200229031037001020042002290020370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241003602282002420137032020012d000021004101102a21030240024020004101460d002003450d02200242818080801037022420022003360220200341003a0000200141086a200241206a10b4040c010b2003450d01200242818080801037022420022003360220200341013a00002002200241206a360210200141016a200241106a1094020b200228022421032004ad4280808080800884200235022842208620022802202200ad84100102402003450d002000102c0b2004102c024020012d00000d002001411c6a280200450d00200141186a280200102c0b200241c0006a24000f0b1033000bca0201067f230041b0016b22012400200141086a200010f201024020012903284202510d000340200128026021022001280258210302400240200128025c22040d00200321050c010b2004210620032105034020052802ec0321052006417f6a22060d000b0340200320032f01064102746a41ec036a28020021032004417f6a22040d000b0b200120023602a801200141003602a001200141003602980120014200370390012001200536028c0120014100360288012001200336029c01200120032f01063602a40120014188016a10f401200141086a200010f20120012903284202520d000b0b02402000280204220341d0e1c100460d00200328020021042003102c2004450d00200428020021052004102c2005450d00024020052802002203450d0003402005102c2003210520032802002204210320040d000b0b2005102c0b200141b0016a24000be80202097f027e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d0120022008412010dd05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a220541c5036a310000200541e8026a290300220c200c5022081ba7450d004200200541f8026a29030020081b210c4200200541f0026a29030020081b210d0c010b200341086a20012802102002200141146a28020028021c110400200341106a290300210c200128020021042003290308210d0b20012004417f6a3602002000200c3703082000200d370300200341206a24000f0b41c689c6004118200341186a418883c100103b000bd40402097f017e230041106b22052400024002400240200128020041016a220641004c0d0020012006360200200141046a2106200141086a28020021070240024003402006280200220841086a210920082f0106220a41057421064100210b0240024003402006450d0120022009412010dd05220c450d02200641606a2106200b41016a210b200941206a2109200c417f4a0d000b200b417f6a210a0b2007450d022007417f6a21072008200a4102746a41880b6a21060c010b0b2008200b41e0006c6a22094198036a2106200941e8026a210d2009419c036a2802002107024003402006280200220841086a210920082f0106220a41057421064100210b0240024003402006450d0120042009412010dd05220c450d02200641606a2106200b41016a210b200941206a2109200c417f4a0d000b200b417f6a210a0b024020070d004100210c0c030b2007417f6a21072008200a4102746a41ec036a21060c010b0b4101210c0240200841e8026a200b410c6c6a2206280200220b0d00410021060c010b20062802082209417f4c0d040240024020090d0020054200370300410121060c010b2009102a2206450d0620054100360204200520093602000b200520093602042006200b200910db051a2005290300210e0b02400240200d2d005d450d0020064100200c1b21060c010b200c450d010b2000200e370204200020063602000c010b20002001280210200220032004200141146a28020028020c1105000b20012001280200417f6a360200200541106a24000f0b41c689c6004118200541086a418883c100103b000b103a000b1033000bcb0401097f230041c0006b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a280200210602400240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d0120022008412010dd05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a220841e8026a210502400240200841c5036a2d00000d00200341206a41086a220a200541c5006a290000370300200341206a41106a220b200541cd006a290000370300200341206a41186a2207200541d5006a29000037030020032005413d6a2900003703204102210820052d003c4101470d01200341186a2007290300370300200341106a200b290300370300200341086a200a29030037030020032003290320370300410121080c010b200341086a200541c5006a290000370300200341106a200541cd006a290000370300200341186a200541d5006a29000037030020032005413d6a29000037030020052d003c21080b200841ff01714102470d010b200020012802102002200141146a280200280210110400200128020021040c010b200020083a000020002003290300370001200041096a200341086a290300370000200041116a200341106a290300370000200041196a200341186a2903003700000b20012004417f6a360200200341c0006a24000f0b41c689c6004118200341206a418883c100103b000bb80201097f230041106b220224000240200028020041016a220341004c0d0020002003360200200041046a2104200041086a280200210502400240024003402004280200220641086a210720062f010622084105742104410021090240024003402004450d0120012007412010dd05220a450d02200441606a2104200941016a2109200741206a2107200a417f4a0d000b2009417f6a21080b2005450d022005417f6a2105200620084102746a41880b6a21040c010b0b2006200941e0006c6a220441a4036a2d000022074101410220074101461b200441c5036a2d00001b22044102470d010b20002802102001200041146a2802002802181101002104200028020021030c010b200441014621040b20002003417f6a360200200241106a240020040f0b41c689c6004118200241086a418883c100103b000bfc0202097f037e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d0120022008412010dd05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a22054190036a290300210c20054188036a290300210d20054180036a290300210e0240200541c5036a2d00000d00200ea721054201210e2005450d010c020b200e4202520d010b200320012802102002200141146a280200280214110400200341106a290300210c200128020021042003290308210d2003290300210e0b20012004417f6a360200200041106a200c3703002000200d3703082000200e370300200341206a24000f0b41c689c6004118200341186a418883c100103b000b851409057f017e0c7f047e037f017e037f047e097f230041f00c6b22022400024020002802000d002000417f360200200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b2002411c6a20042f0106360200200241186a4100360200200241146a20043602002002200336022020024100360210200242003703082002200136020420024100360200200241f0016a200210f201024020022903900222074202510d002000410c6a2108200041046a2109200241900a6a41146a210a200241900a6a41206a210b200241f0016a4104722103200241f0016a413d6a210c200241cd026a210d200241b8026a210e200241f0016a41306a210f200241f0016a41286a21100340200241c8006a41086a2204200241f0016a41086a2211290300370300200241c8006a41106a2201200241f0016a41106a2212290300370300200241c8006a41186a2205200241f0016a41186a2213290300370300200220022903f001370348200e2903002114200f290300211520022903b0022116200229039802211720022f01ee02211820022d00ed02211920022d00cc02211a20022903a802211b20022802c002211c20022802c402211d20022802c802211e200241286a41186a200d41186a290000221f370300200241286a41106a200d41106a2900002220370300200241286a41086a200d41086a29000022213703002002200d2900002222370328200241e8006a41186a2223201f370300200241e8006a41106a22242020370300200241e8006a41086a222520213703002002202237036820024188016a41186a2226200529030037030020024188016a41106a2227200129030037030020024188016a41086a222820042903003703002002200229034837038801024002400240024002402009280200222941d0e1c100460d002000280208212a0c010b200241900a6a410041e00210da051a200241f0016a410041a00810da051a41880b102a2229450d014100212a202941003b010620294100360200202941086a200241900a6a41e00210db051a202941e8026a200241f0016a41a00810db051a20004100360208200020293602040b0340202941086a210120292f0106222b410574210441002105024003402004450d0120024188016a2001412010dd052206450d04200441606a2104200541016a2105200141206a21012006417f4a0d000b2005417f6a212b0b0240202a450d00202a417f6a212a2029202b4102746a41880b6a28020021290c010b0b200241c0016a41186a2026290300221f370300200241c0016a41106a20272903002220370300200241c0016a41086a20282903002221370300200220022903880122223703c001200a2022370200200a41086a2021370200200a41106a2020370200200a41186a201f370200200220083602a00a2002202b36029c0a200220093602980a200220293602940a200241003602900a20102014370300201220153703002002201637039002200220173703f8012002201a3a00ac022002201e3602a8022002201d3602a4022002201c3602a0022002201b37038802200220073703f001200c2002290368370000200c41086a2025290300370000200c41106a2024290300370000200c41186a2023290300370000200220183b01ce02200220193a00cd02200241900a6a200241f0016a1080021a0c020b1033000b202941e8026a200541e0006c6a2129024020194101710d0020292029290300200720075022041b37030020292029290308201720041b370308202941106a22012001290300201520041b370300200241900a6a41186a22062023290300370300200241900a6a41106a222a2024290300370300200241900a6a41086a222b2025290300370300200220022903683703900a20292d003c21012013202941d5006a22052900003703002012202941cd006a22192900003703002011202941c5006a222329000037030020022029413d6a22242900003703f0012028200241900a6a200241f0016a201a41ff0171410146221a1b220441086a2900003703002027200441106a2900003703002026200441186a2900003703002002200429000037038801202941012001201a1b3a003c2024200229038801370000202320282903003700002019202729030037000020052026290300370000202920162029290320201ba722041b370320202941286a22012014200129030020041b3703002029201b202929031820041b37031802400240201d0d00201c21040c010b201d2101201c2104034020042802ec0321042001417f6a22010d000b0340201c201c2f01064102746a41ec036a280200211c201d417f6a221d0d000b0b201c2f010621012002201e3602a801200220013602a401200241003602a0012002201c36029c01200241003602980120024200370390012002200436028c012002410036028801200241f0016a20024188016a10f701024020022802f0014101470d00202941306a211c0340200241900a6a41286a200341286a280200360200200b200341206a2902003703002006200341186a2204290200370300202a200341106a2201290200370300202b200341086a2205290200370300200220032902003703900a200241c0016a41186a2004290000370300200241c0016a41106a2001290000370300200241c0016a41086a2005290000370300200220032900003703c001200241e0016a41086a200b41086a2802003602002002200b2902003703e001200241b0016a201c200241c0016a200241e0016a108102024020022802b001450d0020022802b4012204450d0020022802b801450d002004102c0b200241f0016a20024188016a10f70120022802f0014101460d000b0b20024188016a10f4010c010b202941386a212b202941306a212a202928023821262029280230210402400240202941346a28020022050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b200220263602900220024100360288022002410036028002200242003703f801200220013602f401200241003602f0012002200436028402200220042f010636028c02200241f0016a10f401202941286a201437030020292016370320202941106a2015370300202920173703082029201b37031820292007370300202a201d360204202a201c360200202b201e3602002029201a3a003c2029413d6a2002290368370000202941c5006a2025290300370000202941cd006a2024290300370000202941d5006a2023290300370000202920183b015e202920193a005d0b200241f0016a200210f20120022903900222074202520d000b0b200210f9012000200028020041016a360200200241f00c6a24000f0b41f089c6004110200241f0016a41f882c100103b000bf41801187f230041d0116b2202240020002802102203200328020041016a360200200028020c21042000280208210520002802042103200241206a41186a22062000412c6a290000370300200241206a41106a2207200041246a290000370300200241206a41086a22082000411c6a29000037030020022000290014370320200241a0026a200141e00010db051a024002400240024020032f01062201410b490d00200241b0036a410041e00210da051a20024198066a410041a00810da051a41880b102a2209450d03200941003b010620094100360200200941086a200241b0036a41e00210db052101200941e8026a20024198066a41a00810db052106200220032f00c8013b01ac032002200341ca016a2d00003a00ae03200220032900db01370398032002200341e0016a29000037009d03200341cb016a280000210a200341cf016a280000210b200341d3016a280000210c200341d7016a280000210d20024198066a200341a8076a41e00010db051a2001200341e8016a20032f010641796a220041057410db052101200620034188086a200041e0006c10db052106200341063b0106200920003b0106200220022f01ac033b019403200220022d00ae033a0096032002200229039803370380032002200229009d0337008503200241b0036a20024198066a41e00010db051a0240024020044107490d00200441057420016a41c07e6a2001200441796a22074105746a2201200041ffff037120076b41057410dc051a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200441e0006c20066a220041c07b6a200041e07a6a220e200941066a22002f010020076b41e0006c10dc051a200e200241a0026a41e00010db051a0c010b200341086a20044105746a220141206a2001200341066a22002f010020046b41057410dc051a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200341e8026a200441e0006c6a220e41e0006a200e20002f010020046b41e0006c10dc051a200e200241a0026a41e00010db051a0b20024188026a41026a220420022d0096033a0000200020002f010041016a3b0100200220022f0194033b01880220022002290380033703800120022002290085033700850120024190016a200241b0036a41e00010db051a2002411c6a41026a220f20042d00003a0000200220022f0188023b011c2002200229038001370308200220022900850137000d200241206a20024190016a41e00010db051a20032802002206450d0120032f0104211020024198066a410272211103402002419c026a41026a2212200f2d00003a0000200220022f011c3b019c0220022002290308370388022002200229000d37008d02200241a0026a200241206a41e00010db051a201041ffff0371210702400240024020062f01062203410b490d002011410041b20b10da051a41b80b102a2201450d0720014100360200200141046a20024198066a41b40b10db051a200220062f00c8013b01ac032002200641ca016a2d00003a00ae03200220062900db01370398032002200641e0016a29000037009d03200641cb016a2800002113200641cf016a2800002114200641d3016a2800002115200641d7016a280000211620024198066a200641a8076a41e00010db051a200141086a200641e8016a20062f0106220041796a220341057410db052117200141e8026a20064188086a200341e0006c10db052118200141880b6a200641a40b6a2000417a6a220841027410db052119200641063b0106200120033b010602402008450d00410021032019210003402000280200220420033b010420042001360200200041046a21002008200341016a2203470d000b0b200241b0036a20024198066a41e00010db051a200220022d00ae0322033a009603200220022f01ac0322003b0194032002200229009d033700850320022002290398033703800320024194066a41026a220820033a0000200220003b01940620022002290380033703800120022002290085033700850120024198066a200241b0036a41e00010db051a201041ffff037122004107490d0120172007417a6a22044105746a2017200741796a22034105746a220020012f010620036b41057410dc051a200041186a200229008d023700002000200d36000f2000200c36000b2000200b3600072000200a360003200041026a20122d00003a0000200020022f019c023b00002000200229038802370013200741e0006c20186a220041c07b6a200041e07a6a220020012f010620036b41e0006c10dc051a2000200241a0026a41e00010db051a200120012f010641016a22003b01062007410274220a20196a416c6a201920044102746a2210200041ffff0371220720046b41027410dc051a2010200936020020072004490d022001200a6a41f00a6a2100034020002802002204200341016a22033b010420042001360200200041046a210020032007490d000c030b0b200641086a2200200741016a22044105746a200020074105746a2200200320076b220141057410dc051a2000200d36000f2000200c36000b2000200b3600072000200a360003200041026a2002419c026a41026a2d00003a0000200020022f019c023b00002000200229038802370013200041186a200229008d023700002006200741e0006c6a220041c8036a200041e8026a2200200141e0006c10dc051a2000200241a0026a41e00010db051a2006200341016a22033b01062007410274200641880b6a22006a41086a200020044102746a2200200341ffff037120046b41027410dc051a20002009360200201041ffff037120062f010622034f0d05200920043b010420092006360200200420034f0d052003417f6a210120062004417f6a22034102746a41900b6a2100034020002802002204200341026a3b010420042006360200200041046a21002001200341016a2203470d000c060b0b200641086a2203200741016a22044105746a200320074105746a220320062f0106221020076b221941057410dc051a2003200d36000f2003200c36000b2003200b3600072003200a360003200341026a20122d00003a0000200320022f019c023b00002003200229038802370013200341186a200229008d02370000200641e8026a200741e0006c6a220341e0006a2003201941e0006c10dc051a2003200241a0026a41e00010db051a2006201041016a22033b010620074102742219200641880b6a22106a41086a201020044102746a2210200341ffff037120046b41027410dc051a20102009360200200020062f010622044f0d00200620196a418c0b6a2103034020032802002200200741016a22073b010420002006360200200341046a210320042007470d000b0b20024184026a41026a220320082d00003a0000200220022f0194063b01840220022002290380013703f00120022002290085013700f50120024190016a20024198066a41e00010db051a200f20032d00003a0000200220022f0184023b011c200220022903f001370308200220022900f50137000d200241206a20024190016a41e00010db051a0240200628020022030d002013210a2016210d2015210c2014210b200121090c030b20062f010421102013210a2016210d2015210c2014210b20032106200121090c000b0b200320044105746a220041286a200041086a2210200120046b41057410dc051a200041206a2006290300370000200041186a2007290300370000200041106a2008290300370000201020022903203700002003200441e0006c6a220041c8036a200041e8026a220e20032f010620046b41e0006c10dc051a200e200241a0026a41e00010db051a200320032f010641016a3b01060c010b20024198066a410272410041b20b10da051a41b80b102a2203450d0120034100360200200341046a20024198066a41b40b10db051a2003200528020022003602880b200520033602002005200528020441016a360204200041003b010420002003360200200320032f010622044105746a220041086a20022f011c3b00002000410a6a2002411c6a41026a2d00003a0000200041176a200d360000200041136a200c3600002000410f6a200b3600002000410b6a200a3600002000411b6a2002290308370000200041206a200229000d3700002003200441e0006c6a41e8026a200241206a41e00010db051a200341880b6a200441016a22004102746a2009360200200320003b0106200920003b0104200920033602000b200241d0116a2400200e0f0b1033000b9d1e03087f037e127f23004180076b22042400200441e0006a41186a200241186a290000370300200441e0006a41106a200241106a290000370300200441e0006a41086a200241086a290000370300200420022900003703600240024002402001280200220541d0e1c100460d00200128020421060c010b41002106200441e8026a410041e00210da051a200441c0016a410041840110da051a41ec03102a2205450d01200541003b010620054100360200200541086a200441e8026a41e00210db051a200541e8026a200441c0016a41840110db051a20014100360204200120053602000b024002400340200541086a2107200541066a210820052f0106220941057421024100210a0240024003402002450d01200441e0006a2007412010dd05220b450d02200241606a2102200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200520094102746a41ec036a28020021050c010b0b200441e8026a41086a22022005200a410c6c6a220741f0026a220a2802003602002004200741e8026a22072902003703e80220072003290200370200200a200341086a280200360200200441c0016a41086a20022802002202360200200420042903e802220c3703c0012000410c6a20023602002000200c370204200041013602000c010b200441086a41186a220b200441e0006a41186a2202290300370300200441086a41106a200441e0006a41106a2207290300220c370300200441086a41086a200441e0006a41086a220a290300220d37030020042004290360220e3703082001200128020841016a3602082007200c370300200a200d3703002002200b2903003703002004200e370360200441d8026a41086a2206200341086a280200360200200420032902003703d80202400240024020082f01002203410b490d00200441e8026a410041e00210da051a200441c0016a410041840110da051a41ec03102a220f450d04200f41003b0106200f4100360200200f41086a200441e8026a41e00210db052107200f41e8026a200441c0016a41840110db05210a200441e8026a41086a220b200541b8036a280200360200200420052900db013703a8012004200541e0016a2900003700ad01200420052902b0033703e802200420052f00c8013b01bc012004200541ca016a2d00003a00be01200541cb016a2800002110200541cf016a2800002111200541d3016a2800002112200541d7016a28000021132007200541e8016a20052f010641796a220241057410db052107200a200541bc036a2002410c6c10db05210a200541063b0106200f20023b0106200420042f01bc013b01a401200420042d00be013a00a601200420042903a8013703c001200420042900ad013700c501200441286a41086a200b280200360200200420042903e8023703280240024020094107490d00200941057420076a41c07e6a2007200941796a220b4105746a2207200241ffff0371200b6b41057410dc051a200741186a200441e0006a41186a290300370000200741106a200441e0006a41106a290300370000200741086a200441e0006a41086a290300370000200720042903603700002009410c6c200a6a220241b87f6a200241ac7f6a2202200f41066a22082f0100200b6b410c6c10dc051a200241086a200441d8026a41086a280200360200200220042903d8023702000c010b200541086a20094105746a220241206a200220082f010020096b41057410dc051a200241186a200441e0006a41186a290300370000200241106a200441e0006a41106a290300370000200241086a200441e0006a41086a29030037000020022004290360370000200541e8026a2009410c6c6a2202410c6a200220082f010020096b410c6c10dc051a200241086a200441d8026a41086a280200360200200220042903d8023702000b200820082f010041016a3b010020044198016a41026a220220042d00a6013a0000200441c8026a41086a2214200441286a41086a280200360200200420042f01a4013b019801200420042903c001370350200420042900c501370055200420042903283703c8022004413c6a41026a221520022d00003a0000200420042f0198013b013c2004200429005537002d20042004290350370328200441c0006a41086a22162014280200360200200420042903c80237034020052802002206450d0120052f01042103200441e8026a4102722117034020044194016a41026a221820152d00003a0000200420042f013c3b019401200420042903283703602004200429002d37006520044198016a41086a221920162802003602002004200429034037039801200341ffff0371210502400240024020062f01062202410b490d002017410041960410da051a419c04102a220b450d08200b4100360200200b41046a200441e8026a41980410db051a200420062f00c8013b01bc012004200641ca016a2d00003a00be012004200641db016a2900003703a8012004200641e0016a2900003700ad01200641cb016a280000211a200641cf016a280000211b200641d3016a280000211c200641d7016a280000211d200441e8026a41086a221e200641b8036a2802003602002004200641b0036a2902003703e802200b41086a200641e8016a20062f0106220741796a220241057410db05211f200b41e8026a200641bc036a2002410c6c10db052120200b41ec036a20064188046a2007417a6a220941027410db052108200641063b0106200b20023b010602402009450d00410021022008210703402007280200220a20023b0104200a200b360200200741046a21072009200241016a2202470d000b0b200441d8026a41086a2202201e280200360200200420042d00be0122073a00a601200420042f01bc01220a3b01a401200420042903a8013703c001200420042900ad013700c501200420042903e8023703d802200441c4026a41026a220920073a00002004200a3b01c402200420042903c0013703e802200420042900c5013700ed0220142002280200360200200420042903d8023703c802200341ffff037122074107490d01201f2005417a6a220a4105746a201f200541796a22024105746a2207200b2f010620026b41057410dc051a200741186a20042900653700002007201336000f2007201236000b2007201136000720072010360003200741026a20182d00003a0000200720042f0194013b0000200720042903603700132005410c6c20206a220741b87f6a200741ac7f6a2207200b2f0106220320026b410c6c10dc051a200741086a20192802003602002007200429039801370200200b200341016a22073b01062005410274221020086a416c6a2008200a4102746a2203200741ffff03712205200a6b41027410dc051a2003200f3602002005200a490d02200b20106a41d4036a210703402007280200220a200241016a22023b0104200a200b360200200741046a210720022005490d000c030b0b200641086a2207200541016a220a4105746a200720054105746a2207200220056b41057410dc051a200741186a20042900653700002007201336000f2007201236000b2007201136000720072010360003200741026a20044194016a41026a2d00003a0000200720042f0194013b00002007200429036037001320062005410c6c6a220241f4026a200241e8026a220720062f0106220b20056b410c6c10dc051a200241f0026a20044198016a41086a28020036020020072004290398013702002006200b41016a22023b01062005410274200641ec036a22076a41086a2007200a4102746a2207200241ffff0371220b200a6b41027410dc051a2007200f360200200341ffff0371200b4f0d052006200a417f6a22024102746a41f0036a210703402007280200220a200241016a22023b0104200a2006360200200741046a21072002200b490d000c060b0b200641086a2202200541016a22034105746a200220054105746a220220062f010620056b41057410dc051a200241186a20042900653700002002201336000f2002201236000b2002201136000720022010360003200241026a20182d00003a0000200220042f0194013b000020022004290360370013200641e8026a2005410c6c6a2202410c6a200220062f0106220a20056b410c6c10dc051a200241086a201928020036020020022004290398013702002006200a41016a22023b010620054102742210200641ec036a220a6a41086a200a20034102746a2208200241ffff0371220a20036b41027410dc051a2008200f3602002007200a4f0d00200620106a41f0036a2102034020022802002207200541016a22053b010420072006360200200241046a2102200a2005470d000b0b20044190016a41026a220220092d00003a000020044180016a41086a22072014280200360200200420042f01c402220a3b019001200420042903e802370350200420042900ed02370055200420042903c80237038001201520022d00003a00002004200a3b013c2004200429005537002d200420042903503703282016200728020036020020042004290380013703400240200628020022020d00201a2110201d2113201c2112201b2111200b210f0c030b20062f01042103201a2110201d2113201c2112201b211120022106200b210f0c000b0b200520094105746a220b41286a200b41086a2201200320096b41057410dc051a200b41206a2002290300370000200b41186a2007290300370000200b41106a200a2903003700002001200429036037000020052009410c6c6a220241f4026a200241e8026a220720052f010620096b410c6c10dc051a200241f0026a2006280200360200200720042903d802370200200520052f010641016a3b01060c010b200441e8026a410272410041960410da051a419c04102a2202450d0220024100360200200241046a200441e8026a41980410db051a2002200128020022073602ec03200120023602002001200128020441016a360204200741003b010420072002360200200220022f0106220a4105746a220741086a20042f013c3b00002007410a6a2004413c6a41026a2d00003a0000200741176a2013360000200741136a20123600002007410f6a20113600002007410b6a20103600002007411b6a2004290328370000200741206a200429002d3700002002200a410c6c6a220741f0026a200441c0006a41086a280200360200200741e8026a2004290340370200200241ec036a200a41016a22074102746a200f360200200220073b0106200f20073b0104200f20023602000b200041003602000b20044180076a24000f0b1033000bc50506047f017e017f017e037f017e23004180016b22042400024002402001a74101470d002000427f2000290300220120027c220220022001542205200041086a2206290300220120037c2005ad7c220220015420022001511b22051b3703002006427f200220051b3703000c010b20014201520d00200441c0006a41186a22064200370300200441c0006a41106a22074200370300200441c0006a41086a2205420037030020044200370340200441f0006a41086a2200418be9c500ad428080808080018422081002220941086a290000370300200420092900003703702009102c2005200029030037030020042004290370220137036020042001370340200041c9b5c000ad4280808080d00184220a1002220941086a290000370300200420092900003703702009102c200720042903702201370300200441206a41086a220b2005290300370300200441206a41106a220c2001370300200441206a41186a220d20002903003703002004200137036020042004290340370320200441086a200441206a4120109e01200441086a41106a29030021012004290310210e2004280208210920064200370300200742003703002005420037030020044200370340200020081002220741086a290000370300200420072900003703702007102c20052000290300370300200420042903702208370360200420083703402000200a1002220741086a290000370300200420072900003703702007102c200620002903002208370300200b2005290300370300200c2004290370220a370300200d20083703002004200a370360200420042903403703202004427f2001420020091b220120037c200e420020091b220320027c22082003542200ad7c22022000200220015420022001511b22001b3703482004427f200820001b370340200441206aad4280808080800484200441c0006aad428080808080028410010b20044180016a24000ba90603067f017e077f230041106b2203240002400240024002400240200241046a2204417f4c0d000240024020040d00410121050c010b2004102a2205450d040b2003410036020820032004360204200320053602002002200310670240024020032802042206200328020822046b2002490d00200328020021070c010b200420026a22052004490d05200641017422082005200820054b1b22054100480d050240024020060d002005102a21070c010b200328020020062005102e21070b2007450d042003200536020420032007360200200521060b200720046a2001200210db051a200420026a2201ad4220862007ad84101d220229000021092002102c20032009370300200720016a210a200141086a220b20014f0d01200341086a210c20032108410021024100210b410121042007210d41002105034020024101742101200c200841016a220e6b210f034020082d0000210802402002200b470d00200f210b024002400240200541ff01710e03010200010b200a200d6b210b0c010b417f200f200a200d6b6a220b200b200f491b210b0b2002417f200b41016a22102010200b491b6a220b2002490d072001200b2001200b4b1b220b4100480d070240024020020d00200b102a21040c010b20042002200b102e21040b2004450d060b200420026a20083a0000024002400240024002400240200541ff01710e03010300010b200a200d460d010c040b0240200e200c460d00410021050c030b200a200d470d030b200241016a21020c070b41012105200e200c470d00200241016a21020c060b200241016a2102200e21080c020b200241016a210241022105200141026a2101200d220841016a210d0c000b0b0b103a000b410121040240200b450d00200b4100480d03200b102a2204450d020b410021020340200420026a200320026a2d00003a0000200241016a22024108470d000b024020010d00410821020c010b200420026a2105410021020340200520026a200720026a2d00003a00002001200241016a2202470d000b200a20076b41086a21020b200020023602082000200b3602042000200436020002402006450d002007102c0b200341106a24000f0b1033000b1035000bbd0201057f230041c0006b22022400200241206a41086a220341e5d6c500ad42808080808002841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341affbc000ad4280808080f000841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2001109f01024041c000102a22040d001033000b200420022903003700002004200229031037001020042002290020370020200042c0808080800837020420002004360200200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241c0006a24000b130020004101360204200041e883c1003602000b3400200041ecddc50036020420004100360200200041146a4107360200200041106a41b487c100360200200041086a42073702000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241003600000b130020004101360204200041f493c1003602000bfa0101057f230041106b22022400024002404111102a2203450d002002421137020420022003360200410d200210670240024020022802042204200228020822036b410d490d002003410d6a2105200228020021040c010b2003410d6a22052003490d02200441017422062005200620054b1b22064100480d020240024020040d002006102a21040c010b200228020020042006102e21040b2004450d0120022006360204200220043602000b20022005360208200420036a220341002900b6fb40370000200341056a41002900bbfb4037000020002002290300370200200041086a2002280208360200200241106a24000f0b1033000b1035000bfb1206057f027e047f017e047f027e23004180016b22012400200141286a41186a4200370300200141286a41106a22024200370300200141286a41086a2203420037030020014200370328200141186a41086a220441ecddc500ad4280808080f000841002220541086a290000370300200120052900003703182005102c2003200429030037030020012001290318370328200441c9f8c200ad4280808080a001841002220541086a290000370300200120052900003703182005102c200220012903182206370300200141d8006a41086a2003290300370300200141d8006a41106a2006370300200141d8006a41186a20042903003703002001200637030820012001290328370358200141286a200141d8006a412010d001200129022c4200200128022822041b2207422088a74105742103410021052004410120041b22082104024002400240024002400340024020030d00410221090c030b20002004460d0120042000412010dd052102200541016a2105200341606a2103200441206a210420020d000b20024541016a41017120056a417f6a21050b200141286a41186a4200370300200141286a41106a220a4200370300200141286a41086a2203420037030020014200370328200141186a41086a220441ecddc500ad4280808080f000841002220041086a290000370300200120002900003703182000102c20032004290300370300200120012903182206370308200120063703282004418cdec500ad4280808080a002841002220041086a290000370300200120002900003703182000102c200a20012903182206370300200141d8006a41086a2003290300370300200141d8006a41106a2006370300200141d8006a41186a20042903003703002001200637030820012001290328370358200141286a200141d8006a10960120012802282203410420031b210b410021040240024002400240200129022c420020031b2206422088220ca7220d41014b0d00200d0e020201020b200d2103034020042003410176220020046a22022005200b20024102746a280200491b2104200320006b220341014b0d000b0b4100210902402005200b20044102746a2802002203470d004100210e0c020b2004200520034b6a21040b200141286a41186a220f4200370300200141286a41106a22104200370300200141286a41086a2200420037030020014200370328200141186a41086a220341ecddc500ad4280808080f000841002220241086a290000370300200120022900003703182002102c2000200329030037030020012001290318220c3703082001200c370328200341c9f8c200ad4280808080a001841002220241086a290000370300200120022900003703182002102c200141086a41086a2003290300220c370300200120012903182211370308200a2011370000200a41086a200c370000200141d8006a41086a2000290300370300200141d8006a41106a2010290300370300200141d8006a41186a200f29030037030020012001290328370358200141186a200141d8006aad42808080808004841003108d01024002400240024020012802182200450d00200128021c21022001200328020036022c200120003602282001200141286a107520012802000d01200128020421030c020b2001420037022c20014101360228200141286a107821030c020b410021030b2002450d002000102c0b20032003418094ebdc036e22004180ec94a37c6c6aad4280fd87d1007e2212428094ebdc038021112004200d4b0d020240200d2006a7470d00200d41016a2203200d490d05200d4101742202200320032002491b220341ffffffff03712003470d05200341027422024100480d0502400240200d0d002002102a210b0c010b200b200d4102742002102e210b0b200b450d042003ad21060b200b20044102746a220341046a2003200d20046b41027410dc051a200320053602004101210e200642ffffffff0f83200d41016a2204ad220c422086842106200420004180fd87d1006c2011a76a201220114280ec94a37c7e7c4280cab5ee01566a4b21090b200141286a41186a22024200370300200141286a41106a220d4200370300200141286a41086a2203420037030020014200370328200141186a41086a220441ecddc500ad4280808080f000841002220041086a290000370300200120002900003703182000102c20032004290300370300200120012903182211370308200120113703282004418cdec500ad4280808080a002841002220041086a290000370300200120002900003703182000102c200141086a41086a20042903002211370300200120012903182212370308200a2012370000200a41086a2011370000200141d8006a41086a2003290300370300200141d8006a41106a200d290300370300200141d8006a41186a20022903003703002001200129032837035802400240200b0d00200141d8006aad428080808080048410050c010b2001410036023020014201370328200ca72203200141286a10670240024020030d002001280230210a200128022c210d200128022821030c010b4100200128023022046b2100200b20034102746a2110200128022c210d200b210203402002280200210f02400240200d20006a4104490d00200128022821030c010b200441046a22032004490d07200d410174220a2003200a20034b1b220a4100480d0702400240200d0d00200a102a21030c010b2001280228200d200a102e21030b2003450d062001200a36022c20012003360228200a210d0b2001200441046a220a360230200320046a200f3600002000417c6a2100200a21042010200241046a2202470d000b0b2006a72104200141d8006aad4280808080800484200aad4220862003ad8410010240200d450d002003102c0b2004450d00200b102c0b200e450d00200141d8006a41086a22042005ad37030020014102360258200141286a200141d8006a108f01200141236a2203200141286a41086a22022802003600002001200129032837001b200141286a410c6a2001411f6a2200290000370000200141c6a4b9da04360029200141023a00282001200129001837002d200141286a109001200141013602282001200536022c200141d8006a200141286a108b02200320042802003600002001200129035837001b200141d8006a410c6a2000290000370000200141c28289aa04360059200141023a00582001200129001837005d200141d8006a10900120012802280d002002280200450d00200128022c102c0b02402007a7450d002008102c0b20014180016a240020090f0b41ecb3c000411e41acfec5001036000b1033000b1035000b9a0403047f017e027f230041106b220224002002410036020820024201370300200128020021034101102a2104024002400240024020034101460d002004450d02200242818080801037020420022004360200200441013a0000200128020421032001410c6a28020022042002106702402004450d002003200441286c6a2105034020032002109101200341206a29030021060240024020022802042207200228020822046b4108490d00200228020021070c010b200441086a22082004490d06200741017422042008200420084b1b22044100480d060240024020070d002004102a21070c010b200228020020072004102e21070b2007450d052002200436020420022007360200200228020821040b2002200441086a360208200720046a20063700002005200341286a2203470d000b0b200141106a200210ba020c010b2004450d01200242818080801037020420022004360200200441023a0000200128020421070240024020022802042203200228020822046b4104490d00200228020021030c010b200441046a22082004490d03200341017422052008200520084b1b22084100480d030240024020030d002008102a21030c010b200228020020032008102e21030b2003450d0220022008360204200220033602000b2002200441046a360208200320046a20073600000b20002002290300370200200041086a200241086a280200360200200241106a24000f0b1033000b1035000be31104047f017e037f047e230041b0056b22022400200241206a2001107502400240024002400240024020022802200d00024020022802242203450d0003402003417f6a22030d000b0b20012802042203450d01200128020022042d0000210520012003417f6a3602042001200441016a36020002400240200541ff00714104470d0020054118744118754100480d01420221060c060b200042033703680c060b200241c0036a2001108d0220022d00c0034102460d0220024198036a41206a200241c0036a41206a28020036020020024198036a41186a200241c0036a41186a29030037030020024198036a41106a200241c0036a41106a29030037030020024198036a41086a200241c0036a41086a290300370300200220022903c0033703980320012802042205450d02200128020022042d0000210320012005417f6a3602042001200441016a360200200341024b0d02024002400240024020030e03000102000b41002103200241003a00c0022005417f6a2107417e21080340024020072003470d00200341ff0171450d07200241003a00c0020c070b20024180026a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00c0022008417f6a210820092103200941c000470d000b200241f0046a41386a20024180026a41386a2903002206370300200241f0046a41306a20024180026a41306a290300220a370300200241f0046a41286a20024180026a41286a290300220b370300200241f0046a41206a20024180026a41206a290300220c370300200241f0046a41186a20024180026a41186a290300220d370300200241a8046a41086a20024180026a41086a290300370300200241a8046a41106a20024180026a41106a290300370300200241a8046a41186a200d370300200241a8046a41206a200c370300200241a8046a41286a200b370300200241a8046a41306a200a370300200241a8046a41386a200637030020022002290380023703a8042009417f7320056a2105200420096a41016a2104410021030c020b41002103200241003a00c0022005417f6a2107417e21080340024020072003470d00200341ff0171450d06200241003a00c002420221060c070b20024180026a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00c0022008417f6a210820092103200941c000470d000b200241f0046a41386a20024180026a41386a2903002206370300200241f0046a41306a20024180026a41306a290300220a370300200241f0046a41286a20024180026a41286a290300220b370300200241f0046a41206a20024180026a41206a290300220c370300200241f0046a41186a20024180026a41186a290300220d370300200241a8046a41086a20024180026a41086a290300370300200241a8046a41106a20024180026a41106a290300370300200241a8046a41186a200d370300200241a8046a41206a200c370300200241a8046a41286a200b370300200241a8046a41306a200a370300200241a8046a41386a200637030020022002290380023703a8042009417f7320056a210541012103200420096a41016a21040c010b41002103200241003a00c1022005417f6a2107417e21080340024020072003470d00200341ff0171450d05200241003a00c102420221060c060b20024180026a20036a200420036a220941016a2d00003a00002001200520086a3602042001200941026a3602002002200341016a22093a00c1022008417f6a210820092103200941c100470d000b200241a8046a20024180026a41c10010db051a2009417f7320056a2105200420096a41016a2104410221030b200241e7036a200241a8046a41c10010db051a2005450d022004310000210b20012005417f6a22083602042001200441016a36020002400240200b50450d00420021060c010b2008450d032004310001210c20012005417e6a3602042001200441026a3602004202200b420f8386220a4204540d0342012106200c420886200b84420488200a420c88220b4201200b4201561b7e220b200a5a0d030b200241186a2001107520022802180d02200228021c210520022001108e022002290300a70d02200241106a290300210d2002290308210c200241f0046a41206a20024198036a41206a280200360200200241f0046a41186a20024198036a41186a290300370300200241f0046a41106a20024198036a41106a290300370300200241f0046a41086a20024198036a41086a29030037030020022002290398033703f00420024180026a200241e7036a41c10010db051a200220022f0196033b01fe010c030b200042033703680c040b200042033703680c030b420221060b200241d8016a41086a2204200241f0046a41086a290300370300200241d8016a41106a2208200241f0046a41106a290300370300200241d8016a41186a2209200241f0046a41186a290300370300200241d8016a41206a2207200241f0046a41206a280200360200200220022903f0043703d80120024197016a20024180026a41c10010db051a200220022f01fe013b019401024020064202520d00200042033703680c020b200241f0006a41206a2007280200360200200241f0006a41186a2009290300370300200241f0006a41106a2008290300370300200241f0006a41086a2004290300370300200220022903d8013703702002412f6a20024197016a41c10010db051a200220022f0194013b012c0b20024180026a2001108f0202402002280280024118460d0020002002290370370300200020033a0024200041206a200241f0006a41206a280200360200200041186a200241f0006a41186a290300370300200041106a200241f0006a41106a290300370300200041086a200241f0006a41086a290300370300200041256a2002412f6a41c10010db051a200020022f012c3b016620004188016a200d37030020004180016a200c37030020004190016a2005360200200041f8006a200b3703002000200a3703702000200637036820004198016a20024180026a41900110db051a0c010b200042033703680b200241b0056a24000bf40601067f230041f0006b21020240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a2206360204410121072001200441016a360200200541f001490d0a200541847e6a220541034b0d0420050e0401020803010b200041023a00000f0b20064102490d0320042f0001210520012003417d6a3602042001200441036a360200200541ef014b0d04200041023a00000f0b20064104490d042004280001210520012003417b6a3602042001200441056a36020041012107200541ffff034b0d07200041023a00000f0b41002105200241003a00682003417f6a21062003417e6a210302400340024020062005470d000240200541ff0171450d00200241003a00680b410121010c020b200241c8006a20056a200420056a220741016a2d00003a0000200120033602042001200741026a3602002002200541016a22073a00682003417f6a21032007210520074120470d000b200241c6006a20022d004a3a0000200241306a200241d7006a290000370300200241386a200241df006a290000370300200241c0006a200241e7006a2d00003a0000200220022f01483b01442002200229004f370328200228004b2105410021010b200241246a41026a2203200241c4006a41026a2d00003a0000200241086a41086a2207200241286a41086a290300370300200241086a41106a2204200241286a41106a290300370300200241086a41186a2206200241286a41186a2d00003a0000200220022f01443b0124200220022903283703082001450d05200041023a00000f0b200041023a00000f0b200041023a00000f0b410121070c030b200041023a00000f0b0240200641044f0d00200041023a00000f0b200041023a000020012003417b6a3602042001200441056a3602000f0b200241286a41026a20032d00003a0000200241c8006a41086a2007290300370300200241c8006a41106a2004290300370300200241c8006a41186a20062d00003a0000200220022f01243b012820022002290308370348410021070b200020073a0000200020022f01283b0001200041046a2005360200200041086a2002290348370200200041036a2002412a6a2d00003a0000200041106a200241c8006a41086a290300370200200041186a200241c8006a41106a290300370200200041206a200241c8006a41186a2802003602000bde0506067f017e017f017e017f017e230041206b220224000240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200024002400240200541037122074103460d0002400240024020070e03000102000b2005410276ad21080c040b410121072006450d0220042d0001210620012003417e6a3602042001200441026a3602002006410874200572220141ffff0371418002490d02200141fcff0371410276ad21080c030b4101210720064103490d01200441036a2d0000210620042f0001210920012003417c6a3602042001200441046a3602002009200641107472410874200572220141808004490d012001410276ad21080c020b024020054102762209410c4b0d0002400240024020090e0d00030303010303030303030302000b20064104490d052004350001210820012003417b6a3602042001200441056a36020020084280808080045421074200210a0c060b20064108490d04200429000121082001200341776a3602042001200441096a3602002008428080808080808080015421074200210a0c050b20064110490d03200441096a290000210a2004290001210820012003416f6a3602042001200441116a360200200a428080808080808080015421070c040b200941046a220641104b0d022003417e6a2103200441026a21044100210541012107200241186a210b420021084200210a03402003417f460d01200241106a2004417f6a3100004200200541037441f8007110de0520012003360204200120043602002003417f6a2103200441016a2104200b290300200a84210a20022903102008842108200541016a220541ff01712006490d000b2002427f427f41e80020094103746b41f8007110df052008200229030058200a200241086a290300220c58200a200c511b21070c030b0c020b4200210a410021070c010b410121070b20002008370308200041106a200a37030020002007ad370300200241206a24000bd28f010b077f017e037f027e017f057e057f017e057f027e027f230041f0096b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200200541174b0d1920050e180102030405060708090a0b0c0d0e0f101112131415161718010b200041183602000c360b2006450d3420042d0001210620012003417e6a22073602042001200441026a360200200641064b0d34410121080240024002400240024002400240024020060e0707000102030406070b200241d0076a2001107720022802d0072205450d3b20022902d4072109410221080c060b20074108490d3a200429000221092001200341766a36020420012004410a6a360200410321080c050b200241d0076a2001107720022802d0072205450d3920022902d4072109410421080c040b200241086a2001107520022802080d38200128020441186e220a41186c2204417f4c0d25200228020c210b0240024020040d00410421050c010b2004102a2205450d270b0240200b450d004100210841002104410021060340200241b0046a200110770240024020022802b0042207450d0020022902b4042109200241d0076a2001107720022802d0070d012009a7450d002007102c0b02402006450d002005210103400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141186a2101200441686a22040d000b0b200a0d040c3b0b200641016a210320022802d807210c20022903d007210d02402006200a470d0020082003200820034b1b220aad42187e220e422088a70d2a200ea7220f4100480d2a0240024020060d00200f102a21050c010b20052004200f102e21050b2005450d290b200520046a22062007360200200641146a200c3602002006410c6a200d370200200641046a2009370200200841026a2108200441186a210420032106200b2003470d000b0b2005450d38200bad422086200aad842109410521080c030b200241106a2001107520022802100d372001280204410c6e220c410c6c2204417f4c0d242002280214210a0240024020040d00410421050c010b2004102a2205450d260b02400240200a450d004100210841002104410021060340200241d0076a2001107720022802d007450d02200641016a2103200241b0046a41086a2207200241d0076a41086a280200360200200220022903d0073703b00402402006200c470d0020082003200820034b1b220cad420c7e2209422088a70d2a2009a7220b4100480d2a0240024020060d00200b102a21050c010b20052004200b102e21050b2005450d290b200520046a220620022903b004370200200641086a2007280200360200200841026a21082004410c6a210420032106200a2003470d000b0b2005450d38200aad422086200cad842109410621080c030b02402006450d002005210103400240200141046a280200450d002001280200102c0b2001410c6a2101200441746a22040d000b0b200c450d370b2005102c0c360b200241d0076a2001107720022802d0072205450d3520022902d4072109410721080b20004100360200200041106a20093702002000410c6a2005360200200041086a2008360200200041186a200241e0086a41f80010db051a0c350b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241186a2001107520022802180d0020012802044190016e22074190016c2204417f4c0d21200228021c210c0240024020040d00410821080c010b2004102a2208450d230b02400240200c450d004100210641002104410021050340200241e0086a2001108f0220022802e0084118460d02200541016a2103200241d0076a200241e0086a41900110db051a024020052007470d0020062003200620034b1b2207ad4290017e2209422088a70d272009a7220a4100480d270240024020050d00200a102a21080c010b20082004200a102e21080b2008450d260b200820046a200241d0076a41900110db051a200641026a210620044190016a210420032105200c2003470d000b0b2008450d012000200836020420004101360200200041086a200cad4220862007ad84370200200041106a200241b0046a41800110db051a0c360b02402005450d002008210103402001107320014190016a2101200441f07e6a22040d000b0b2007450d002008102c0b200041183602000c340b02402006450d0020012003417e6a3602042001200441026a3602000b200041183602000c330b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241206a200110c2022002290320a70d002002290328210920004103360200200041086a2009370300200041106a200241e0086a41800110db051a0c330b200041183602000c320b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241d0076a200110800120022802d00722010d160b200041183602000c310b02402006450d0020012003417e6a3602042001200441026a3602000b200041183602000c300b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541034b0d00024002400240024020050e0400010203000b200241d0076a2001108d0220022d00d0074102460d03200241b0046a41086a2203200241dc076a290200370300200241b0046a41106a2205200241e4076a290200370300200241b0046a41186a2206200241ec076a290200370300200220022902d4073703b00420022802d0072104200241306a2001108e022002290330a70d03200241306a41106a29030021092002290338210d20024190046a41186a200629030037030020024190046a41106a200529030037030020024190046a41086a2003290300370300200220022903b00437039004410121010c310b200241d0076a2001108d0220022d00d0074102460d02200241b8046a200241dc076a290200370300200241b0046a41106a200241e4076a290200370300200241c8046a200241ec076a290200370300200220022902d4073703b00420022802d0072104200241e0006a2001108e022002290360a70d02200241e0006a41106a29030021092002290368210d200241c8006a2001108e022002290348a70d02200241c8006a41106a29030021102002290350211120024190046a41186a200241b0046a41186a29030037030020024190046a41106a200241b0046a41106a29030037030020024190046a41086a200241b0046a41086a290300370300200220022903b00437039004410221010c300b200241d0076a2001108d0220022d00d0074102460d01200241c8066a41086a200241dc076a290200370300200241c8066a41106a200241e4076a290200370300200241c8066a41186a200241ec076a290200370300200220022902d4073703c80620022802d0072104200241d0076a2001108d0220022d00d0074102460d01200241b0046a41206a2203200241d0076a41206a280200360200200241b0046a41186a200241d0076a41186a290300370300200241b0046a41106a200241d0076a41106a290300370300200241b0046a41086a200241d0076a41086a290300370300200220022903d0073703b004200241f8006a2001108e022002290378a70d01200241f8006a41106a29030021122002290380012113200241c8056a41186a200241c8066a41186a2903002209370300200241c8056a41106a200241c8066a41106a290300220d37030020024190046a41086a200241c8066a41086a29030037030020024190046a41106a200d37030020024190046a41186a2009370300200220022903c80637039004200241b0046a41086a2903002109200241b0046a41186a2903002110200241b0046a41106a29030021112003350200211420022903b004210d410321010c2f0b200241d0076a2001108d0220022d00d0074102460d00200241b0046a41086a2203200241dc076a290200370300200241b0046a41106a2205200241e4076a290200370300200241b0046a41186a2206200241ec076a290200370300200220022902d4073703b00420022802d007210420024190016a2001108e02200229039001a70d0020024190016a41106a2903002109200229039801210d20024190046a41086a200329030037030020024190046a41106a200529030037030020024190046a41186a2006290300370300200220022903b00437039004410421010c2e0b200041183602000c2f0b2006450d2b20042d0001210520012003417e6a22153602042001200441026a3602002005410f4b0d2b4104211602400240024002400240024002400240024002400240024002400240024020050e1000010239030405060708090a0b0c0d0e000b200241d0076a2001108d0220022d00d0074102460d392002200241eb076a2f00003b01b004200241dc076a290200210d200241e7076a2800002117200241e6076a2d00002118200241e5076a2d00002119200241e4076a2d0000210f200241ed076a2d0000210b200241ee076a2d0000210c200241ef076a2d00002107200241f0076a280200210a20022902d407210920022802d0072106200241a8016a2001108e0220022903a801a70d3920012802042204450d39200241b8016a290300211a20022903b001210e200128020022032d0000210820012004417f6a360204410121162001200341016a360200200841024b0d39200220022f01b0043b01c6050c380b200241c0016a2001108e0220022903c001a70d38200241d0016a290300210d20022903c8012109200220022f01c8063b01c605200241d9066a290000211a20022900d106210e20022d00ca06210b20022d00cb06210c20022d00cc06210720022800cd06210a410221160c370b200241d8016a2001108e0220022903d801a70d37200241e8016a290300210d20022903e0012109200220022f00b5043b01c605200241c6046a290100211a20022901be04210e20022800b104211720022d00b704210b20022d00b804210c20022d00b904210720022801ba04210a410321160c360b200241f0016a2001107520022802f0010d3620022802f4012106200220022f01d0073b01c60542002109410521164200210d0c350b200241f8016a2001107520022802f8010d35200128020441246e221b41246c2204417f4c0d2420022802fc01211c0240024020040d00410421060c010b2004102a2206450d260b0240201c450d004123210541002108410021040340200241d0076a2001108d02200220022f00ef073b01c805024020022d00d00722074102470d00201b450d382006102c0c380b200441016a210320022800eb07210c20022d00ea07210a20022d00e907210b20022d00e807210f20022903e007210920022903d807210d20022802d407211920022d00d307211820022d00d207211720022d00d107211620022d00f107211d20022d00f207211e20022d00f3072115200220022f01c8053b01c80602402004201b470d0020082003200820034b1b221bad42247e220e422088a70d29200ea7221f4100480d290240024020040d00201f102a21060c010b20062005415d6a201f102e21060b2006450d280b200620056a220441776a200a3a0000200441766a200b3a0000200441756a200f3a0000200441606a20183a00002004415f6a20173a00002004415e6a20163a00002004415d6a20073a00002004416d6a2009370000200441656a200d370000200441616a2019360000200441786a200c3600002004417c6a20022f01c8063b00002004417e6a201d3a00002004417f6a201e3a0000200420153a0000200841026a2108200541246a210520032104201c2003470d000b0b2006450d35201cad422086201bad842109200220022f01b0043b01c6054200210d410621160c340b410721160c330b2015450d3320042d0002210820012003417d6a3602042001200441036a360200200841034f0d33200220022f01d0073b01c605410821160c320b200241d0076a2001108d0220022d00d0074102460d322002200241eb076a2f00003b01c605200241dc076a290200210d200241e7076a2800002117200241e6076a2d00002118200241e5076a2d00002119200241e4076a2d0000210f200241ed076a2d0000210b200241ee076a2d0000210c200241ef076a2d00002107200241f0076a280200210a20022902d407210920022802d0072106410921160c310b20024180026a200110752002280280020d312002280284022106200220022f0190043b01c60542002109410a21164200210d0c300b410b21160c2f0b410c21160c2e0b200241d0076a200110820120022802d0072206450d2e200220022f01b0043b01c60520022902d40721094200210d410d21160c2d0b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d2f200241003a00f0070c2f0b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200220022f01ee073b01c605200241df076a290000210d20022900d707210920022801ea07211720022d00e907211820022d00e807211920022d00e707210f20022800d307210620022d00d207211d20022d00d107211e20022d00d0072108410e21160c2c0b410f21160c2b0b20154104490d2b2004280002210620012003417a6a3602042001200441066a360200200241d0076a2001107e20022802d007450d2b200220022f01b0043b01c605200241d8076a350200210d20022903d0072109411021160c2a0b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241c8066a200110e20120022d00c8064101460d00200241c8056a200241c8066a41017241800110db051a200241c8066a2001107720022802c80622010d130b200041183602000c2d0b2006450d2720042d0001210520012003417e6a221d3602042001200441026a360200200541144b0d27410e21160240024002400240024002400240024002400240024002400240024002400240024002400240024020050e15000102030405060708090a0b0c3a0d0e0f10111213000b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d3c200241003a00f0070c3c0b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200220022f01ee073b01b004200241df076a290000210920022900d707210d20022801ea07210f20022d00e907210b20022d00e807210a20022d00e707210c20022800d307210720022d00d207211820022d00d107211920022d00d007211720024188026a2001108e02200229038802a70d3a20024198026a290300211a200229039002210e200220022f01b0043b01c405410121160c390b200241a0026a2001107520022802a0020d3920022802a4022107200220022f01d0073b01c405410221160c380b200241a8026a2001107520022802a8020d3820012802042204450d3820022802ac022107200128020022052d0000210320012004417f6a3602042001200541016a360200200341ff0071221941064b0d38200220022f01d0073b01c40520034107762117410321160c370b200241b0026a2001107520022802b0020d3720012802042204450d3720022802b4022107200128020022052d0000210320012004417f6a3602042001200541016a360200200341ff0071221941064b0d37200220022f01d0073b01c40520034107762117410421160c360b201d41034d0d362004280002210720012003417a6a3602042001200441066a360200200220022f01d0073b01c405410521160c350b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d37200241003a00f0070c370b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200220022f01ee073b01c405200241df076a290000210920022900d707210d20022801ea07210f20022d00e907210b20022d00e807210a20022d00e707210c20022800d307210720022d00d207211820022d00d107211920022d00d0072117410621160c340b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d36200241003a00f0070c360b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200220022f01ee073b01c405200241df076a290000210920022900d707210d20022801ea07210f20022d00e907210b20022d00e807210a20022d00e707210c20022800d307210720022d00d207211820022d00d107211920022d00d0072117410721160c330b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d35200241003a00f0070c350b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200220022f01ee073b01c405200241df076a290000210920022900d707210d20022801ea07210f20022d00e907210b20022d00e807210a20022d00e707210c20022800d307210720022d00d207211820022d00d107211920022d00d0072117410821160c320b41002105200241003a00f0072003417e6a2107417d21060340024020072005470d00200541ff0171450d34200241003a00f0070c340b200241d0076a20056a200420056a220841026a2d00003a00002001200320066a3602042001200841036a3602002002200541016a22083a00f0072006417f6a21062008210520084120470d000b200220022f01ee073b01c805200320086b2203417e6a4104490d32200241df076a290000210920022900d707210d20022801ea07210f20022d00e907210b20022d00e807210a20022d00e707210c20022800d307210720022d00d207211820022d00d107211920022d00d0072117200420086a220441026a280000210620012003417a6a22053602042001200441066a220836020020054104490d322008350000210e2001200341766a36020420012004410a6a360200200220022f01c8053b01c4054200211a410921160c310b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d33200241003a00f0070c330b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200220022f01ee073b01c405200241df076a290000210920022900d707210d20022801ea07210f20022d00e907210b20022d00e807210a20022d00e707210c20022800d307210720022d00d207211820022d00d107211920022d00d0072117410a21160c300b200241b8026a2001107520022802b8020d3020022802bc022107200220022f01d0073b01c405410b21160c2f0b201d41034d0d2f2004280002210720012003417a6a3602042001200441066a360200200220022f0190043b01c405410c21160c2e0b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d30200241003a00f0070c300b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200220022f01ee073b01c405200241df076a290000210920022900d707210d20022801ea07210f20022d00e907210b20022d00e807210a20022d00e707210c20022800d307210720022d00d207211820022d00d107211920022d00d0072117410d21160c2d0b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d2f200241003a00f0070c2f0b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200220022f01ee073b01c405410f2116200241d0076a410f6a290000210920022900d707210d20022801ea07210f20022d00e907210b20022d00e807210a20022d00e707210c20022800d307210720022d00d207211820022d00d107211920022d00d00721170c2c0b41002105200241003a00f0072003417e6a21072003417d6a21060340024020072005470d00200541ff0171450d2e200241003a00f0070c2e0b200241d0076a20056a200420056a220841026a2d00003a0000200120063602042001200841036a3602002002200541016a22083a00f0072006417f6a21062008210520084120470d000b200220022900d707220d3703c806200220022f01ee073b00df06200220022801ea07220f3600db06200220022d00e907220b3a00da06200220022d00e807220a3a00d906200220022d00e707220c3a00d8062002200241df076a29000022093703d0062003417e6a2008460d2c20022800d307210720022d00d207211820022d00d107211920022d00d0072117200420086a220441026a2d00002108200120063602042001200441036a360200200841064b0d2c200220022f00df063b01c405411021160c2b0b411121160c2a0b411221160c290b200241d0076a2001107720022802d0072207450d29200220022f01b0043b01c40520022902d407210d411321160c280b200241d0076a2001107720022802d0072207450d28200220022f01b0043b01c40520022902d407210d411421160c270b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d29200241003a00f0070c290b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200241bd046a200241df076a2900002209370000200220022900d707220d3700b504200220022f01ee0722013b01cc04200220022801ea07220f3602c804200220022d00e907220b3a00c704200220022d00e807220a3a00c604200220022d00e707220c3a00c504200220022800d30722073600b104200220022d00d20722183a00b00420022d00d107211920022d00d0072117200220013b01c405411521160c260b200241d0076a200110fd0220022d00d0074105470d11200041183602000c2b0b200241d0076a200110fd0220022d00d0074105470d11200041183602000c2a0b2006450d2220042d0001210520012003417e6a360204410221032001200441026a360200200541054b0d220240024002400240024020050e06001701020304000b200241d0076a200110820120022802d0072204450d26200241d8076a280200210820022802d4072106200241c0026a2001108e0220022903c002a7450d152006450d262004102c0c260b200241d0076a2001108d0220022d00d0074102460d25200220022902d407221a3703c805200241dc076a290200210d200241e4076a290200210e200241ec076a290200210920022802d007210420022802cc052108201aa72106410321030c150b410421030c140b410521030c130b200241d0076a2001108d0220022d00d0074102460d22200220022902d407221a3703c805200241dc076a290200210d200241e4076a290200210e200241ec076a290200210920022802d007210420022802cc052108201aa72106410621030c120b2006450d2020042d0001210520012003417e6a3602042001200441026a360200200541044b0d200240024002400240024020050e050001020304000b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d26200241003a00f0070c260b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200241bd046a200241df076a2900002209370000200220022900d707220d3700b504200220022801ea07220a3602c804200220022d00e907220b3a00c704200220022d00e807220f3a00c604200220022d00e70722193a00c504200220022800d307220c3600b104200220022d00d20722183a00b00420022d00d007211720022d00d1072116200220022f01ee073b01c405200220022f01c8063b01c205410121010c230b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d25200241003a00f0070c250b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200241bd046a200241df076a2900002209370000200220022900d707220d3700b504200220022801ea07220a3602c804200220022d00e907220b3a00c704200220022d00e807220f3a00c604200220022d00e70722193a00c504200220022800d307220c3600b104200220022d00d20722183a00b00420022d00d007211720022d00d1072116200220022f01ee073b01c405200220022f01c8063b01c205410221010c220b41002105200241003a00f007410220036b21072003417d6a210603400240200720056a0d00200541ff0171450d24200241003a00f0070c240b200241d0076a20056a200420056a220841026a2d00003a0000200120063602042001200841036a3602002002200541016a22083a00f0072006417f6a21062008210520084120470d000b200241bd046a200241df076a2900002209370000200220022900d707220d3700b504200220022801ea07220a3602c804200220022d00e907220b3a00c704200220022d00e807220f3a00c604200220022d00e70722193a00c504200220022800d307220c3600b104200220022d00d20722183a00b00420022d00d007211720022d00d1072116200220022f01ee073b01c60541002105200241003a00f007200420086a2107200820036b41026a210303400240200320056a0d00200541ff0171450d24200241003a00f0070c240b200241d0076a20056a200720056a220441026a2d00003a0000200120063602042001200441036a3602002002200541016a22043a00f0072006417f6a21062004210520044120470d000b200241bd046a200241df076a290000221a370000200220022900d707220e3700b504200220022801ea07221e3602c804200220022d00e907221d3a00c704200220022d00e80722073a00c604200220022d00e70722083a00c504200220022800d30722063600b104200220022d00d20722053a00b00420022d00d007210420022d00d1072103200220022f01ee073b01c205200220022f01c6053b01c405410321010c210b200241d0076a200110820120022802d007220c450d21200220022f01b0043b01c405200220022f01c8063b01c20520022902d407210d410421010c200b41002105200241003a00f0072003417e6a21082003417d6a21030340024020082005470d00200541ff0171450d22200241003a00f0070c220b200241d0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a00f0072003417f6a21032006210520064120470d000b200241bd046a200241df076a2900002209370000200220022801ea073602c804200220022d00e9073a00c704200220022f00e7073b00c504200220022f01ee073b01cc04200220022900d707220d3700b504200220022800d307220c3600b104200220022d00d20722183a00b00420022d00d007211720022d00d1072116200241d8066a220120022900c504370300200241e0066a200241cd046a2d00003a0000200241d0066a20093703002002200d3703c80620012d0000211920022d00d906210f20022d00da06210b20022800db06210a200220022f00df063b01c405200220022f01c8053b01c205410521010c1f0b024002402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241d8026a2001107520022802d802450d010b200041183602000c280b20022802dc0221012000410e36020020002001360204200041086a200241e0086a41880110db051a0c270b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241d0076a2001107720022802d00722010d110b200041183602000c260b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541024b0d0002400240024020050e03000102000b200241e0026a2001108e0220022903e002a70d02200241f0026a290300210920022903e802210d200241d0076a2001108d0220022d00d0074102460d02200241b8046a200241dc076a290200370300200241c0046a200241e4076a290200370300200241c8046a200241ec076a290200370300200220022902d4073703b00420022802d0072101410121040c1e0b200241f8026a2001107520022802f8020d0120022802fc022101200241b0046a41186a200241d0076a41186a290300370300200241b0046a41106a200241d0076a41106a290300370300200241b0046a41086a200241d0076a41086a290300370300200220022903d0073703b004410221040c1d0b20024180036a200110752002280280030d002002280284032101200241b0046a41186a200241d0076a41186a290300370300200241b0046a41106a200241d0076a41106a290300370300200241b0046a41086a200241d0076a41086a290300370300200220022903d0073703b004410321040c1c0b200041183602000c250b2006450d1820042d0001210520012003417e6a3602042001200441026a360200200541044b0d180240024002400240024020050e050001020304000b200241e0086a200110fe0220022d00d0094102460d1c200241d8076a20024190096a290300370300200241e0076a20024198096a290300370300200220022f00f7083b01c20520022002290388093703d007200241f3086a280000210c200241fc086a280200210420022d00f208210a20022d00f108210b20022d00f008210320022903e808210920022903e008210d20022d00f908210520022d00fa08210620022d00fb08210f200229038009210e200220022f00bf093b01c005200241b0096a2903002120200241bb096a2800002101200241d0096a290300212120022903a809211420022d00ba09210820022d00b909211620022d00b809211d20022903a009211a20022802c409211e20022903c809211320022d00c309211520022d00c209211b20022d00c109211c4101211f0c1d0b20024188036a200110c202200229038803a70d1b2002290390032109200241b0046a2001107720022802b0042207450d1b200241d0076a41086a200241e0086a41086a290300370300200241d0076a41106a200241e0086a41106a290300370300200220022f01c8063b01c205200220022903e0083703d007200220022f0190043b01c00520022902b404210d420021144102211f420021200c1c0b200241e0086a2001108d0220022d00e0084102460d1a2002200241fb086a2f00003b01b004200241ec086a2902002109200241f7086a280000210c200241f6086a2d0000210a200241f5086a2d0000210b200241f4086a2d00002103200241fd086a2d00002105200241fe086a2d00002106200241ff086a2d0000210f20024180096a280200210420022902e408210d20022802e0082107200241a8036a2001108e0220022903a803a70d1a200241b8036a290300210e20022903b003212020024198036a200110c202200229039803a70d1a20022903a003211a200241e0086a2001107720022802e008450d1a200241e0076a200e370300200220203703d807200220022f01b0043b01c205200220022f0190043b01c0052002200241e8086a2802003602d00720022903e008210e420021144103211f420021200c1b0b200241d0036a2001108e0220022903d003a70d19200241e0036a290300210e20022903d803211a200241c0036a200110c20220022903c003a70d1920022903c803212041002103200241003a0080092001280204417f6a2104024003402004417f460d01200241e0086a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a0080092004417f6a21042005210320054120470d000b200241d8066a200241f7086a2900002221370300200241e0066a200241ff086a2d00003a0000200241d0066a200241ef086a2900002209370300200220022900e708220d3703c80620022800e308210720022d00e208211920022d00e108211820022d00e008211720022800db06210c20022d00da06210a20022d00d906210b200220022f00df063b019004200241e0086a2001107720022802e0082204450d1a2021a721032002201a3703d007200220022f0190043b01c205200220203703e007200220022f01b0043b01c0052002200e3703d80720022902e408210e420021144104211f420021200c1b0b200341ff0171450d19200241003a0080090c190b41002105200241003a0080092003417e6a21072003417d6a21060340024020072005470d00200541ff0171450d1a200241003a0080090c1a0b200241e0086a20056a200420056a220841026a2d00003a0000200120063602042001200841036a3602002002200541016a22083a0080092006417f6a21062008210520084120470d000b200241d8066a200241f7086a290000221a370300200241e0066a200241ff086a2d00003a0000200241d0066a200241ef086a2900002209370300200220022900e708220d3703c80620022800e308210720022d00e208211920022d00e108211820022d00e008211720022800db06210c20022d00da06210a20022d00d906210b200220022f00df063b01c6052003417e6a2008460d18200420086a221641026a2d0000211d200120063602042001201641036a360200201d41014b0d184100210502400240201d0e020100010b41002104200241003a008009200820036b41036a2106200320086b417c6a210303400240200620046a0d00200441ff0171450d1b200241003a0080090c1b0b200241e0086a20046a201620046a220541036a2d00003a0000200120033602042001200541046a3602002002200441016a22053a0080092003417f6a21032005210420054120470d000b200241bd046a200241ef086a290000370000200220022f01fe0822013b01f003200220022900e7083700b504200220022800e3083600b104200220022d00e2083a00b004200220022801fa083602c804200220022d00f9083a00c704200220022f00f7083b00c50420022d00e108210f20022d00e0082106200220013b01cc0420022902b404210e20022802b0042104200241d8066a20013b0100200241d0066a200241c4046a290200370300200220022902bc043703c806410121050b201aa72103200241d0076a41106a200241c8066a41106a2f01003b0100200241d0076a41086a200241c8066a41086a290300370300200241e6076a20024194046a2f01003b0100200220022903c8063703d007200220022f01c6053b01c20520022002280190043601e207200220022f01c4053b01c005420021144105211f420021200c190b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541024b0d00024002400240024020050e03000102000b200241d0076a2001108f0220022802d0074118460d03200241e0086a200241d0076a41900110db051a419001102a2204450d142004200241e0086a41900110db051a410121010c020b200241e0086a2001108d024102210120022d00e0084102460d02200241e0056a200241fc086a290200220d370300200241d8056a200241f4086a2902002209370300200241ec086a290200211a20022802e008210420022902e408210e0c010b200241e0086a2001108d0220022d00e0084102460d01200241d0066a200241ec086a290200370300200241d8066a200241f4086a290200370300200241c8066a41186a200241fc086a290200370300200220022902e4083703c80620022802e0082104200241d0076a2001108f0220022802d0074118460d01200241e0086a200241d0076a41900110db051a419001102a2203450d122003200241e0086a41900110db051a200241c8056a41186a200241c8066a41186a290300220d370300200241c8056a41106a200241c8066a41106a2903002209370300200241d0066a290300211a20022903c806210e410321010b2000200136020420004112360200200041246a200d3702002000411c6a2009370200200041146a201a3702002000410c6a200e3702002000412c6a2003360200200041086a2004360200200041306a200241b0046a41e00010db051a0c240b200041183602000c230b2006450d1520042d0001210520012003417e6a22063602042001200441026a36020020050d1520064104490d152004280002211820012003417a6a3602042001200441066a360200200241e0086a2001107720022802e008220f450d15200241e8086a280200211720022802e4082119200241e8036a2001107520022802e8030d142001280204410c6e220c410c6c2204417f4c0d0e20022802ec03210a0240024020040d00410421080c010b2004102a2208450d100b0240200a450d004100210641002104410021050340200241e0086a2001107720022802e0082207450d15200541016a210320022902e408210902402005200c470d0020062003200620034b1b220cad420c7e220d422088a70d13200da7220b4100480d130240024020050d00200b102a21080c010b20082004200b102e21080b2008450d120b200820046a22052007360200200541046a2009370200200641026a21062004410c6a210420032105200a2003470d000b0b2008450d14200f450d15200128020422034104490d1220012802002206280000210b20012003417c6a22043602042001200641046a36020020044104490d11200628000421162001200341786a22073602042001200641086a36020041002104200241003a00a009200341776a21030340024020072004470d000240200441ff0171450d00200241003a00a0090b02402019450d00200f102c0b0240200a450d00200a410c6c21042008210103400240200141046a280200450d002001280200102c0b2001410c6a2101200441746a22040d000b0b200c450d172008102c0c170b200241e0086a20046a200620046a220541086a2d00003a0000200120033602042001200541096a3602002002200441016a22053a00a0092003417f6a210320052104200541c000470d000b200241d0076a41386a2201200241e0086a41386a290300370300200241d0076a41306a2204200241e0086a41306a290300370300200241d0076a41286a2203200241e0086a41286a290300370300200241d0076a41206a2205200241e0086a41206a290300370300200241d0076a41186a2206200241e0086a41186a290300370300200241d0076a41106a2207200241e0086a41106a290300370300200241d0076a41086a221d200241e0086a41086a290300370300200220022903e0083703d007200f0d0d0c150b02402006450d0020012003417e6a3602042001200441026a3602000b200041183602000c210b02402006450d0020012003417e6a3602042001200441026a3602000b200041183602000c200b02402006450d0020012003417e6a3602042001200441026a3602000b200041183602000c1f0b2006450d0120042d0001210520012003417e6a360204410221032001200441026a360200200541034b0d01024002400240024020050e0400030102000b200241d0076a2001107720022802d0072204450d0420022902d4072109410121030c020b200241d0076a2001108d0220022d00d0074102460d03200241dc076a290200211a200241e4076a2902002120200241ec076a290200210d20022802d007210420022902d40721094200210e410321030c010b200241d0076a2001108d0220022d00d0074102460d02200241b0046a41086a2203200241dc076a290200370300200241c0046a2205200241e4076a290200370300200241c8046a2208200241ec076a290200370300200220022902d4073703b00420022802d0072104200241d0076a2001107720022802d007450d02200241d0076a41086a280200210620022903d007210e2003290300211a200529030021202008290300210d20022903b0042109410421030b20002003360204200041173602002000412c6a200e370200200041246a200d3702002000411c6a2020370200200041146a201a370200200041346a20063602002000410c6a2009370200200041086a2004360200200041386a200241e0086a41d80010db051a0c1e0b200041183602000c1d0b200041183602000c1c0b200041086a20022902d4073702002000200136020420004104360200200041106a200241e0086a41800110db051a0c1b0b200220022902cc063703e008200241e0086a41086a200241c8056a41800110db051a200241d0076a200241e0086a41880110db051a200241b0046a200241d0076a41880110db051a2000200136020420004108360200200041086a200241b0046a41880110db051a0c1a0b200241b0046a41206a200241d0076a41206a2903002209370300200241b0046a41186a200241d0076a41186a290300220d370300200241b0046a41106a200241d0076a41106a290300220e370300200241b0046a41086a200241d0076a41086a290300221a370300200220022903d00722203703b0042000410a360200200020203702042000410c6a201a370200200041146a200e3702002000411c6a200d370200200041246a20093702002000412c6a200241e0086a41e40010db051a0c190b200241b0046a41206a200241d0076a41206a2903002209370300200241b0046a41186a200241d0076a41186a290300220d370300200241b0046a41106a200241d0076a41106a290300220e370300200241b0046a41086a200241d0076a41086a290300221a370300200220022903d00722203703b0042000410b360200200020203702042000410c6a201a370200200041146a200e3702002000411c6a200d370200200041246a20093702002000412c6a200241e0086a41e40010db051a0c180b200241d0026a290300210e20022903c802210d410121030b2000410c360200200041206a200e370200200041186a200d370200200041286a2009370200200041146a2008360200200041106a20063602002000410c6a2004360200200041086a2003360200200041306a200241e0086a41e00010db051a0c160b200041086a20022902d407370200200020013602042000410f360200200041106a200241e0086a41800110db051a0c150b200241b0046a41386a221e2001290300370300200241b0046a41306a22012004290300370300200241b0046a41286a22042003290300370300200241b0046a41206a22032005290300370300200241b0046a41186a22052006290300370300200241b0046a41106a22062007290300370300200241b0046a41086a2207201d290300370300200220022903d0073703b004200041246a2016360200200041206a200b3602002000411c6a200a360200200041186a200c360200200041146a2008360200200041106a20173602002000410c6a2019360200200041086a200f3602002000201836020420004113360200200041286a20022903b004370200200041306a2007290300370200200041386a2006290300370200200041c0006a2005290300370200200041c8006a2003290300370200200041d0006a2004290300370200200041d8006a2001290300370200200041e0006a201e29030037020020004188016a200241c8066a41206a29030037030020004180016a200241c8066a41186a290300370300200041f8006a200241c8066a41106a290300370300200041f0006a200241c8066a41086a290300370300200041e8006a20022903c8063703000c140b103a000b1033000b1035000b02402019450d00200f102c0b0240200a450d00200a410c6c21042008210103400240200141046a280200450d002001280200102c0b2001410c6a2101200441746a22040d000b0b200c450d032008102c0c030b02402019450d00200f102c0b0240200a450d00200a410c6c21042008210103400240200141046a280200450d002001280200102c0b2001410c6a2101200441746a22040d000b0b200c450d022008102c0c020b02402005450d002008210103400240200141046a280200450d002001280200102c0b2001410c6a2101200441746a22040d000b0b200c450d002008102c0b2019450d00200f102c0b200041183602000c0c0b200041183602000c0b0b200241c8056a41086a2222200241d0076a41086a290300370300200241c8056a41106a2223200241d0076a41106a290300370300200220022f01c2053b01be05200220022903d0073703c805200220022f01c0053b01bc05200041236a200c3600002000200a3a00222000200b3a0021200041206a20033a0000200041186a2009370200200041106a200d3700002000410c6a2007360000200020193a000b200020183a000a200020173a0009200041086a201f3a000020004111360200200041306a200e3702002000412c6a20043602002000200f3a002b200020063a002a200020053a0029200020022f01be053b0027200041c8006a2023290300370200200041c0006a2022290300370200200041386a20022903c805370200200041e0006a2020370200200041d8006a2014370200200041eb006a2001360000200020083a006a200020163a0069200041e8006a201d3a0000200041d0006a201a37020020022f01bc05210120004180016a2021370200200041f8006a2013370200200041f4006a201e360200200020153a00732000201b3a00722000201c3a0071200020013b006f0c0a0b200241c8066a41186a200241b0046a41186a290300220e370300200241c8066a41106a200241b0046a41106a290300221a370300200241c8066a41086a200241b0046a41086a2903002220370300200220022903b00422213703c806200041386a2009370200200041306a200d3702002000410c6a2001360200200041086a200436020020004110360200200041106a2021370200200041186a2020370200200041206a201a370200200041286a200e370200200041c0006a200241e0086a41d00010db051a0c090b200220022f01c40522153b01c005200220022f01c2053b01be052000411f6a200a3600002000200b3a001e2000200f3a001d2000411c6a20193a0000200041146a20093700002000410c6a200d370000200041086a200c360000200020183a0007200020163a0006200020173a0005200020013a00042000410d3602002000413f6a201e3600002000201d3a003e200020073a003d2000413c6a20083a0000200041346a201a3700002000412c6a200e370000200041286a2006360000200020053a0027200020033a0026200020043a0025200020153b0023200020022f01be053b0043200041c8006a200241e0086a41c80010db051a0c080b200041183602000c070b200041183602000c060b200220022f01c40522013b01c205200041386a201a370200200041306a200e370200200041236a200f3600002000200b3a00222000200a3a0021200041206a200c3a0000200041186a2009370200200041106a200d3702002000410c6a2007360200200020183a000b200020193a000a200020173a0009200041086a20163a0000200041093602002000412c6a2006360200200020083a0029200020013b0027200041c0006a200241e0086a41d00010db051a0c050b200041183602000c040b200220022f01c60522013b01c405200041186a200d370200200041106a2009370200200041386a201a370200200041306a200e370200200041236a2017360000200020183a0022200020193a0021200041206a200f3a00002000410c6a20063602002000201d3a000b2000201e3a000a200020083a0009200041086a20163a0000200041073602002000412c6a200a360200200020073a002b2000200c3a002a2000200b3a0029200020013b0027200041c0006a200241e0086a41d00010db051a0c030b200041183602000c020b200241f0036a41186a20024190046a41186a290300220e370300200241f0036a41106a20024190046a41106a290300221a370300200241f0036a41086a20024190046a41086a2903002220370300200220022903900422213703f003200041e0006a2012370200200041d8006a2013370200200041c8006a2010370200200041c0006a2011370200200041386a2009370200200041306a200d3702002000410c6a2004360200200041086a200136020020004106360200200041106a2021370200200041186a2020370200200041206a201a370200200041286a200e370200200041d0006a2014370200200041e8006a20022903e008370300200041f0006a200241e0086a41086a290300370300200041f8006a200241e0086a41106a29030037030020004180016a200241e0086a41186a29030037030020004188016a200241e0086a41206a2903003703000c010b200041183602000b200241f0096a24000b802205017f037e087f017e037f230041800b6b22022400420221030240024002400240024002400240200129036822044202520d00200241106a20014198016a41900110db051a0c010b200241ee016a200141246a41c20010db051a200241b0026a41086a20014188016a290300370300200241b0026a41106a20014190016a290300370300200220014180016a2903003703b002200141f8006a2903002103200129037021052001280204210620012d00002107200241e00a6a41026a2208200141036a2d00003a0000200241e8026a41086a2209200141106a290200370300200241e8026a41106a220a200141186a290200370300200241e8026a41186a220b200141206a280200360200200220012f00013b01e00a200220012902083703e80202400240024020074101460d00200241a00a6a41026a20082d00003a0000200241e0066a41086a2009290300370300200241e0066a41106a200a290300370300200241e0066a41186a200b2d00003a0000200220022f01e00a3b01a00a200220022903e8023703e0060c010b200241f8076a200641067610910220022802f8072107024002402002280280082006413f7122064b0d00410021080c010b200241a00a6a41026a200720064105746a220641026a2d00003a0000200241e8066a2006410f6a290000370300200241f0066a200641176a290000370300200241f8066a2006411f6a2d00003a0000200220062f00003b01a00a200220062900073703e00620062800032106410121080b024020022802fc07450d002007102c0b20080d00410121070c010b200241f8076a41026a200241a00a6a41026a2d00003a0000200241e8026a41086a200241e0066a41086a290300370300200241e8026a41106a200241e0066a41106a290300370300200241e8026a41186a200241e0066a41186a2d00003a0000200220022f01a00a3b01f807200220022903e0063703e802410021070b200241800a6a41026a2208200241f8076a41026a2d00003a0000200241c8056a41086a2209200241e8026a41086a290300370300200241c8056a41106a220a200241e8026a41106a290300370300200241c8056a41186a220b200241e8026a41186a2d00003a0000200220022f01f8073b01800a200220022903e8023703c80502402007450d00200041013b0001200041013a0000200041036a41003a000020014198016a1092020c060b200241d7026a2009290300370000200241df026a200a290300370000200241e7026a200b2d00003a0000200220022f01800a3b01c802200220063600cb02200220022903c8053700cf02200220082d00003a00ca02200241f8076a20014198016a41900110db051a20024188096a41106a200241b0026a41106a29030037030020024188096a41086a200241b0026a41086a290300370300200220022903b0023703880941002106200241e00a6a4100109302200241800a6a41086a200241eb0a6a290000370300200241800a6a41106a200241f30a6a290000370300200241950a6a200241e00a6a41186a2209290000370000200220022900e30a3703800a20022f01e00a210c20022d00e20a210d200241a00a6a41186a4200370300200241a00a6a41106a220a4200370300200241a00a6a41086a22074200370300200242003703a00a200241e0096a41086a22014191b0c200ad4280808080e000841002220841086a290000370300200220082900003703e0092008102c20072001290300370300200220022903e009220e3703c00a2002200e3703a00a200141acb0c200ad4280808080e000841002220841086a290000370300200220082900003703e0092008102c200a20022903e009220e370300200241e00a6a41086a2007290300370300200241e00a6a41106a200e370300200920012903003703002002200e3703d00a200220022903a00a3703e00a200241086a200241e00a6a4120109401024020044201520d0020054200510d02200228020c410020022802081b2101417f21062001ad220e20032003200e541b220e200e20037d2005827d220e42ffffffff0f560d00200ea721060b200241e0096a41086a22014191b0c200ad4280808080e000841002220741086a290000370300200220072900003703e0092007102c200241c00a6a41086a22082001290300370300200220022903e0093703c00a200141a3b0c200ad42808080809001841002220741086a290000370300200220072900003703e0092007102c200241d00a6a41086a22072001290300370300200220022903e0093703d00a200220063602e009200241e00a6a41186a2209200241e0096aad4280808080c000841006220141186a290000370300200241e00a6a41106a220a200141106a290000370300200241e00a6a41086a220b200141086a290000370300200220012900003703e00a2001102c200241a00a6a41186a220f2009290300370300200241a00a6a41106a2209200a290300370300200241a00a6a41086a220a200b290300370300200220022903e00a3703a00a41c000102a2201450d02200120022903c00a370000200141086a2008290300370000200120022903d00a370010200141186a2007290300370000200120022903a00a370020200141286a200a290300370000200141306a2009290300370000200141386a200f290300370000410121072002200141c000410141004100109701200228020021082001102c0240024020084101460d000c010b200241e00a6a2006109302200241e0096a41086a200241eb0a6a290000370300200241e0096a41106a200241f30a6a290000370300200241e0096a41156a200241f80a6a290000370000200241a00a6a41086a200241800a6a41086a290300370300200241a00a6a41106a200241800a6a41106a290300370300200241a00a6a41156a200241800a6a41156a290000370000200220022900e30a3703e009200220022903800a3703a00a20022f01e00a20022d00e20a411074722101410021070b200241c0096a41156a2206200241a00a6a41156a290000370000200241c0096a41106a2208200241a00a6a41106a290300370300200241c0096a41086a2209200241a00a6a41086a290300370300200241a0096a41086a220a200241e0096a41086a290300370300200241a0096a41106a220b200241e0096a41106a290300370300200241a0096a41156a220f200241e0096a41156a290000370000200220022903a00a3703c009200220022903e0093703a00902402007450d00200241f8076a109202200041036a41003a0000200041800a3b0001200041013a00000c060b20024190056a41156a2207200629000037000020024190056a41106a2206200829030037030020024190056a41086a22082009290300370300200241f0046a41086a2209200a290300370300200241f0046a41106a220a200b290300370300200241f0046a41156a220b200f290000370000200220022903c00937039005200220022903a0093703f004200241b0056a41106a220f20024188096a41106a290300370300200241b0056a41086a221020024188096a41086a29030037030020022002290388093703b005200241e0066a41046a200241f8076a41900110db051a200241c8056a200241e0066a41940110db051a200241e8026a200241c8056a41046a41900110db051a200241ac046a2211200c200d41107472220c3b010020024188046a200337030020024180046a200537030020024190046a220d20022903b00537030020024198046a2010290300370300200241a0046a2210200f290300370300200241af046a200229039005370000200241b7046a2008290300370000200241bf046a2006290300370000200241c4046a2007290000370000200241c6013602a804200241e8026a41c6016a200c4110763a0000200220043703f803200241ce046a20014110763a0000200241cc046a220720013b0100200241cf046a20022903f004370000200241d7046a2009290300370000200241df046a200a290300370000200241e4046a200b2900003700004104102a2201450d02200242043702e406200220013602e006200241e8026a200241e0066a108b010240024020022903f8034201510d000240024020022802e40620022802e8062201460d0020022802e00621060c010b200141016a22062001490d06200141017422082006200820064b1b22084100480d060240024020010d002008102a21060c010b20022802e00620012008102e21060b2006450d05200220083602e406200220063602e00620022802e80621010b2002200141016a3602e806200620016a41003a00000c010b2002290388042002290380042203420c882204420120044201561b8021040240024020022802e406220620022802e80622016b4102490d0020022802e00621060c010b200141026a22082001490d05200641017422012008200120084b1b22014100480d050240024020060d002001102a21060c010b20022802e00620062001102e21060b2006450d04200220013602e406200220063602e00620022802e80621010b2002200141026a3602e806200620016a2004a741047420037aa7417f6a22014101200141014b1b2201410f2001410f491b723b00000b2010200241e0066a1089012002200d3602c805200241c8056a200241e0066a108a0120022802a80421080240024020022802e406220620022802e80622016b4104490d0020022802e00621060c010b200141046a22092001490d04200641017422012009200120094b1b22014100480d040240024020060d002001102a21060c010b20022802e00620062001102e21060b2006450d03200220013602e406200220063602e00620022802e80621010b2002200141046a3602e806200620016a20083600002002200241e0066a3602c8052011200241c8056a1094022002200241e0066a3602c8052007200241c8056a10940220022802e006210120022802e40621070240024020022802e80622064180024b0d00200241ee016a20012006200241c8026a10950221060c010b200241e00a6a41186a22082006ad4220862001ad841006220641186a290000370300200241e00a6a41106a2209200641106a290000370300200241e00a6a41086a220a200641086a290000370300200220062900003703e00a2006102c200241a00a6a41186a2008290300370300200241a00a6a41106a2009290300370300200241a00a6a41086a200a290300370300200220022903e00a3703a00a200241ee016a200241a00a6a4120200241c8026a10950221060b02402007450d002001102c0b2006450d04200241c8016a41086a200241c8026a41086a290300370300200241c8016a41106a200241c8026a41106a290300370300200241c8016a41186a200241c8026a41186a290300370300200241a0016a41086a20024188046a290300370300200241a0016a41106a20024190046a290300370300200241a0016a41186a20024198046a290300370300200241c0016a200241a0046a290300370300200220022903c8023703c801200220024180046a2903003703a00120022903f8032103200241106a200241e8026a41900110db051a0b200041086a20022903c801370300200041286a2003370300200041306a20022903a001370300200041206a200241c8016a41186a290300370300200041186a200241c8016a41106a290300370300200041106a200241c8016a41086a290300370300200041386a200241a0016a41086a290300370300200041c0006a200241a0016a41106a290300370300200041c8006a200241a0016a41186a290300370300200041d0006a200241a0016a41206a290300370300200041d8006a200241106a41900110db051a200041003a0000200241800b6a24000f0b41c090c600411941dc90c6001036000b1033000b1035000b20004180083b0001200041013a0000200041036a41003a0000200241e8026a1092020b200241800b6a24000bff0301067f230041f0006b22022400200241d0006a41086a220341b5e5c200ad4280808080f000841002220441086a290000370300200220042900003703502004102c200241086a41086a2205200329030037030020022002290350370308200341c7e5c200ad4280808080f000841002220441086a290000370300200220042900003703502004102c200241186a41086a22062003290300370300200220022903503703182002200136024c200241d0006a41186a2201200241cc006aad4280808080c000841006220441186a290000370300200241d0006a41106a2207200441106a2900003703002003200441086a290000370300200220042900003703502004102c200241286a41186a22042001290300370300200241286a41106a22012007290300370300200241286a41086a2207200329030037030020022002290350370328024041c000102a2203450d00200320022903083700002003200229031837001020032002290328370020200341086a2005290300370000200341186a2006290300370000200341286a2007290300370000200341306a2001290300370000200341386a2004290300370000200241d0006a200341c00010d0010240024020022802502204450d0020002002290254370204200020043602000c010b20004100360208200042013702000b2003102c200241f0006a24000f0b1033000bb30c01057f024002402000280200220141164b0d000240024002400240024002400240024002400240024002400240024020010e1700010f0f020f0f030405060708090f0a0f0b0c0d0f0f0f000b0240200041086a280200220141064b0d00024002400240024020010e0713130013010203130b200041106a280200450d122000410c6a280200102c0f0b200041106a280200450d112000410c6a280200102c0f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141186a2101200241686a22020d000b0b200041106a280200450d10200028020c102c0f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b200041106a280200450d0f200028020c102c0f0b200041106a280200450d0e2000410c6a280200102c0f0b02402000410c6a2802002202450d002000280204210120024190016c210203402001107320014190016a2101200241f07e6a22020d000b0b200041086a280200450d0d2000280204102c0f0b02402000410c6a2802002201450d0020002802042203200141f0006c6a2104034002402003410c6a2802002202450d0020032802042101200241246c210203400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012002415c6a22020d000b0b200341f0006a21010240200341086a280200450d002003280204102c0b2001210320012004470d000b0b200041086a280200450d0c2000280204102c0f0b0240200041086a2d00002201410f4b0d00410120017441bfbf03710d0c024020014106470d00200041106a280200450d0d2000410c6a280200102c0f0b200041106a280200450d0c2000410c6a280200102c0f0b200041146a280200450d0b200041106a280200102c0f0b200041086a280200450d0a2000280204102c0f0b200041086a2d0000416d6a220141014b0d090240024020010e020001000b200041106a280200450d0a2000410c6a280200102c0f0b200041106a280200450d092000410c6a280200102c0f0b20002d0004417f6a220141024b0d0802400240024020010e03000102000b2000410c6a280200450d0a200041086a280200102c0f0b200041086a22012802001092022001280200102c0f0b2000410c6a22012802001092022001280200102c0f0b20002d0004417f6a220141024b0d0702400240024020010e03000102000b2000410c6a280200450d09200041086a280200102c0f0b200041086a22012802001092022001280200102c0f0b2000410c6a22012802001092022001280200102c0f0b200041086a2802004101470d06200041106a280200450d062000410c6a280200102c0f0b20002d00044104470d052000410c6a280200450d05200041086a280200102c0f0b200041086a280200450d042000280204102c0f0b200041086a2d0000417e6a220141024b0d0302400240024020010e03000102000b200041106a280200450d052000410c6a280200102c0f0b200041346a280200450d04200041306a280200102c0f0b200041306a280200450d032000412c6a280200102c0f0b02402000280204220141024b0d00024020010e03040004040b200041086a22012802001092022001280200102c0f0b2000412c6a22012802001092022001280200102c0f0b02402000410c6a280200450d00200041086a280200102c0b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b200041186a280200450d012000280214102c0c010b02402000280204220141034b0d00024020010e0402000202020b2000410c6a280200450d01200041086a280200102c0f0b200041306a280200450d002000412c6a280200102c0f0b0bef0401067f230041f0006b22022400200241086a22034191b0c200ad4280808080e000841002220441086a290000370300200220042900003703002004102c200241286a41086a2205200329030037030020022002290300370328200341a3b0c200ad42808080809001841002220441086a290000370300200220042900003703002004102c200241386a41086a22062003290300370300200220022903003703382002200136026c200241186a2201200241ec006aad4280808080c000841006220441186a290000370300200241106a2207200441106a2900003703002003200441086a290000370300200220042900003703002004102c200241c8006a41186a22042001290300370300200241c8006a41106a22012007290300370300200241c8006a41086a2207200329030037030020022002290300370348024041c000102a2203450d00200320022903283700002003200229033837001020032002290348370020200341086a2005290300370000200341186a2006290300370000200341286a2007290300370000200341306a2001290300370000200341386a20042903003700002002200341c00010d3012007200241096a2900003703002001200241116a2900003703002004200241196a290000370300200220022900013703480240024020022d00004101460d0020004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b20002002290348370000200041186a200241c8006a41186a290300370000200041106a200241c8006a41106a290300370000200041086a200241c8006a41086a2903003700000b2003102c200241f0006a24000f0b1033000b920501037f20002d00002102024002404101102a2203450d00200320023a000020002d00012102200341014102102e2203450d00200320023a000120002d00022102200341024104102e2203450d00200320023a0002200320002d00033a000320002d00042102200341044108102e2203450d00200320023a0004200320002d00053a0005200320002d00063a0006200320002d00073a000720002d00082102200341084110102e2203450d00200320023a0008200320002d00093a0009200320002d000a3a000a200320002d000b3a000b200320002d000c3a000c200320002d000d3a000d200320002d000e3a000e200320002d000f3a000f20002d00102102200341104120102e2203450d00200320023a0010200320002d00113a0011200320002d00123a0012200320002d00133a0013200320002d00143a0014200320002d00153a0015200320002d00163a0016200320002d00173a0017200320002d00183a0018200320002d00193a0019200320002d001a3a001a200320002d001b3a001b200320002d001c3a001c200320002d001d3a001d200320002d001e3a001e200320002d001f3a001f024002402001280200220041046a2802002202200041086a28020022016b4120490d00200028020021020c010b200141206a22042001490d02200241017422012004200120044b1b22014100480d020240024020020d002001102a21020c010b200028020020022001102e21020b2002450d0120002002360200200041046a2001360200200041086a28020021010b200041086a200141206a360200200220016a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700002003102c0f0b1033000b1035000b9e0501037f230041b0016b22042400024002400240024020002d00000e03000102000b200441206a41186a200341186a290000370300200441206a41106a200341106a290000370300200441206a41086a200341086a29000037030020042003290000370320200041016a2002ad4220862001ad84200441206a100b41014621000c020b200441206a41186a200341186a290000370300200441206a41106a200341106a290000370300200441206a41086a200341086a29000037030020042003290000370320200041016a2002ad4220862001ad84200441206a100c41014621000c010b20044190016a41186a22052002ad4220862001ad841006220141186a29000037030020044190016a41106a2202200141106a29000037030020044190016a41086a2206200141086a29000037030020042001290000370390012001102c200441186a2005290300370300200441106a2002290300370300200441086a2006290300370300200420042903900137030041012101200441206a200041016a200410be024100210020042d00200d00200441c8006a41206a200441c1006a2d00003a0000200441c8006a41186a200441396a290000370300200441c8006a41106a200441316a290000370300200441c8006a41086a200441296a290000370300200420042900213703482005200441c8006aad42808080809004841006220041186a2900003703002002200041106a2900003703002006200041086a29000037030020042000290000370390012000102c200441f0006a41186a2005290300370300200441f0006a41106a2002290300370300200441f0006a41086a200629030037030020042004290390013703700240200441f0006a2003460d00200441f0006a2003412010dd054521010b200121000b200441b0016a240020000ba00701087f230041d00b6b220424000240024020002802000d002000417f360200200441206a41186a200141186a290000370300200441206a41106a200141106a290000370300200441206a41086a200141086a29000037030020042001290000370320024002402000280204220541d0e1c100460d00200041086a28020021060c010b41002106200441f0086a410041e00210da051a200441d0006a410041a00810da051a41880b102a2205450d02200541003b010620054100360200200541086a200441f0086a41e00210db051a200541e8026a200441d0006a41a00810db051a200041086a4100360200200020053602040b200041046a210702400240034020052f010622084105742109410021014100210a02400240034020092001460d01200441206a200520016a41086a412010dd05220b450d02200141206a2101200a41016a210a200b417f4a0d000b200a417f6a21080b2006450d022006417f6a2106200520084102746a41880b6a28020021050c010b0b2000410c6a210b410121010c010b200441186a200441206a41186a290300370300200441106a200441206a41106a290300370300200441086a200441206a41086a290300370300200420042903203703002000410c6a210b410021062008210a410021010b0240024020010d002004418c096a200441086a29030037020020044194096a200441106a2903003702002004419c096a200441186a2903003702002004200b360280092004200a3602fc08200420073602f808200420053602f408200420063602f0082004200429030037028409200441f0006a2004290340370300200441f8006a200441c0006a41086a29030037030020044184016a42003702002004420037036820044200370350200441d0e1c10036028001200441003a008c012004418d016a200429002037000020044195016a200441206a41086a2900003700002004419d016a200441206a41106a290000370000200441a5016a200441206a41186a290000370000200441003a00ad01200441f0086a200441d0006a10800221010c010b200441e8006a4200370300200441e4006a41d0e1c100360200200441003602702004410036026020044200370358200441d0e1c100360254200441003602502005200a41e0006c6a41e8026a2101200441d0006a10f4010b200141106a200337030020012002370308200142013703002000200028020041016a360200200441d00b6a24000f0b41f089c6004110200441d0006a41f882c100103b000b1033000b130020004106360204200041cc95c1003602000b3400200041e5d6c50036020420004100360200200041146a4106360200200041106a41fcaec100360200200041086a42103702000b130020004105360204200041e8b7c1003602000b2e01017f02404104102a22020d001033000b20004284808080c0003702042000200236020020024180a70c3600000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241073600000b2c01017f02404104102a22020d001033000b20004284808080c000370204200020023602002002410d3600000b3a01017f02404110102a22020d001033000b2002420037000820024280809aa6eaafe301370000200042908080808002370204200020023602000bed6807017f027e027f017e127f027e017f230041d0046b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e0700010203040508000b200341a4026a41013602002003420137029402200341fcc4c50036029002200341043602a401200341f4c4c5003602a0012003200341a0016a3602a00220034190026a4184c5c5001041000b200141186a2903002104200141106a29030021052001410c6a2802002106200141086a2802002107200128020421012002411a6a2901002108200241196a2d00002109200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241046a2d0000211641022117200241026a2f010021180240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f01002119200241086a2d000021024100211a0c010b4101211a41002102410021190b201941ffff0371410874200241187472201741ff01717221190240201a450d0041d6b2c0002102410f2117024002400240024020190e05000102031e000b20144108742015722013411874722102201141087420127220104118747221170c1d0b41dd8cc6002102410e21170c1c0b41c3b2c0002102411321170c1b0b41b2b2c0002102411121170c1a0b20032008370370200320093a006f2003200a3a006e2003200b3b016c2003200c3a006b2003200d3a006a2003200e3b01682003200f3a0067200320103a0066200320113b0164200320123a0063200320133a0062200320143b0160200320153a005f2003201936005b200320163a005a200320183b015820034190026a41186a420037030020034190026a41106a2202420037030020034190026a41086a22194200370300200342003703900220034180016a41086a221741e5d6c500ad42808080808002841002221a41086a2900003703002003201a29000037038001201a102c20192017290300370300200320032903800122083703f00120032008370390022017419883c100ad4280808080a001841002221a41086a2900003703002003201a29000037038001201a102c20022003290380012208370300200341c0036a41086a2019290300370300200341c0036a41106a2008370300200341c0036a41186a2017290300370300200320083703a00120032003290390023703c003200341a0016a200341c0036aad428080808080048422081003108d01024002400240024020032802a0012217450d0020032802a40121192003200341a8016a280200360294022003201736029002200341286a20034190026a107520032802280d01200328022c21100c020b2003420037029402200341013602900220034190026a107821100c020b410021100b2019450d002017102c0b20034190026a41186a2211420037030020034190026a41106a2212420037030020034190026a41086a22194200370300200342003703900220034180016a41086a221741e5d6c500ad42808080808002841002221a41086a2900003703002003201a29000037038001201a102c201920172903003703002003200329038001221b3703f0012003201b37039002201741eae5c200ad4280808080f000841002221a41086a2900003703002003201a29000037038001201a102c200341a0016a41086a2017290300221b3703002003200329038001221c3703a0012002201c370000200241086a201b370000200341c0036a41086a2019290300370300200341c0036a41106a2012290300370300200341c0036a41186a201129030037030020032003290390023703c00320034190026a20081003108d010240024020032802900222020d00410021170c010b200328029402211a200320192802003602a401200320023602a001200341206a200341a0016a10750240024020032802200d00200328022421170c010b410021170b201a450d002002102c0b0240201720106a22020d0041d7bbc1002102412f21170c1a0b0240200620024d0d004186bcc1002102412021170c1a0b41a6bcc100210241252117200641104b0d19024020060d0041cbbcc10021020c1a0b02402005428180e983b1de165441002004501b450d0041f0bcc1002102413021170c1a0b0240200341d8006a109f020d00200341186a200341d8006a428080e983b1de16420010c1012003280218450d0041a0bdc1002102411d21170c1a0b200341086a200341d8006a10b101200342f0d0c9abc6add9b1f400370378200341f8006a200341d8006a2003290308220820052008200554200341086a41086a290300220820045420082004511b22021b22052008200420021b2208417f411e10be0120034180016a41086a221741e5d6c500ad428080808080028422041002220241086a29000037030020032002290000370380012002102c200341f0016a41086a2219201729030037030020032003290380013703f001201741fdfbc000ad4280808080f000841002220241086a29000037030020032002290000370380012002102c200341a0016a41086a221a201729030037030020032003290380013703a00120034190026a200341d8006a109f0141c000102a2202450d16200220032903f001370000200241086a2019290300370000200220032903a001370010200241186a201a2903003700002002200329039002370020200241286a20034190026a41086a290300370000200241306a200341a0026a2210290300370000200241386a20034190026a41186a2211290300370000200320083703980220032005370390022002ad428080808080088420034190026aad428080808080028410012002102c201720041002220241086a29000037030020032002290000370380012002102c2019201729030037030020032003290380013703f001201741affbc000ad4280808080f000841002220241086a29000037030020032002290000370380012002102c201a201729030037030020032003290380013703a00120034190026a200341d8006a109f0141c000102a2217450d16201720032903f001370000201741086a200341f0016a41086a290300370000201720032903a001370010201741186a200341a0016a41086a2903003700002017200329039002370020201741286a20034190026a41086a290300370000201741306a2010290300370000201741386a2011290300370000200341a0016a201741c00010a0020240024020032d00ac0122024102460d00200341f0036a41086a200341b5016a290000370300200341f0036a41106a200341bd016a290000370300200341f0036a41186a200341c5016a29000037030020034180016a41086a200341d6016a29010037030020034180016a41106a200341de016a29010037030020034180016a41186a200341e6016a2901003703002003200341ad016a2900003703f0032003200341ce016a29010037038001200341cd016a2d0000211920032802a401450d0120032802a001102c0c010b2003200341d8006a3602940320034190026a10d20120034198036a200328029002220220032802980210d3010240200328029402450d002002102c0b0240024020032d0098030d0020034190026a10d201200328029002210220032003280298023602f403200320023602f003200341d8006a200341f0036a10a1020240200328029402450d002002102c0b410021190c010b200341d8036a200341b1036a290000370300200341c0036a41106a200341a9036a290000370300200341c0036a41086a200341a1036a29000037030020032003290099033703c003200341e0036a200341c0036a10840220034190026a20032802e003221a20032802e803221010a002024020032d009c024102470d00200341003602f801200342013703f00120034180016a41146a410d36020020034180016a410c6a410b360200200341103602bc04200341e5d6c5003602b8042003410b36028401200341073602c404200341affbc0003602c0042003200341e0036a360290012003200341c0046a360288012003200341b8046a360280012003200341f0016a3602cc04200341f0036a41146a4103360200200342033702f403200341c09dc5003602f003200320034180016a36028004200341cc046a41c49ac500200341f0036a10391a20033502f80142208620033502f0018410042003280294032119200341f0036a10d20120032802f0032102200320032802f803360284012003200236028001201920034180016a10a102024020032802f403450d002002102c0b024020032802f401450d0020032802f001102c0b024020032802e403450d0020032802e003102c0b410021190c010b200341f0036a20034190026a410c6a41c20010db051a20032d009104211920034180016a41086a20034190026a41086a280200220236020020034180016a41106a20034192046a410020194101461b3602002003200329039002220837038001200320034194036a36028c01200341003602f801200342013703f0012002200341f0016a106720034180016a410c6a21122008a7211102402002450d00200241057421192011210203402002200341f0016a109101200241206a2102201941606a22190d000b0b2012200341f0016a10a20220032802f40121022010ad422086201aad8420033502f80142208620032802f0012219ad84100102402002450d002019102c0b0240200328028401450d002011102c0b024020032802e403450d0020032802e003102c0b200328029403211920034190026a10d201200328029002210220032003280298023602f403200320023602f0032019200341f0036a10a1020240200328029402450d002002102c0b20034180016a41086a200341c0036a41086a29030037030020034180016a41106a200341c0036a41106a29030037030020034180016a41186a200341c0036a41186a290300370300200320032903c00337038001410121190b410021020b2003419d026a20032903f003370000200341bd026a20193a0000200341be026a200329038001370100200341a5026a200341f0036a41086a290300370000200341ad026a200341f0036a41106a290300370000200341b5026a200341f0036a41186a290300370000200341c6026a20034180016a41086a290300370100200341ce026a20034180016a41106a290300370100200341d6026a20034180016a41186a290300370100200320023a009c02200320063602980220032007360294022003200136029002200341003602a801200342013703a0012006200341a0016a1067200641057421022003419c026a210703402001200341a0016a109101200141206a2101200241606a22020d000b2007200341a0016a10a30220032802a40121022017ad428080808080088420033502a80142208620032802a0012201ad84100102402002450d002001102c0b2017102c200328029402450d18200328029002102c0c180b2002411a6a2901002108200241196a2d00002117200241186a2d00002107200241166a2f01002119200241156a2d0000211a200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d000021152002410c6a2d000021062002410a6a2f01002109200241096a2d0000210a200241046a2d0000210b41022101200241026a2f0100210c0240024020022d00000d0020022d00014101470d00200241056a2d00002101200241066a2f0100210d200241086a2d000021024100210e0c010b4101210e410021024100210d0b200320083703d803200320173a00d703200320073a00d603200320193b01d4032003201a3a00d303200320103a00d203200320113b01d003200320123a00cf03200320133a00ce03200320143b01cc03200320153a00cb03200320063a00ca03200320093b01c8032003200a3a00c7032003200b3a00c2032003200c3b01c0032003200d41ffff0371410874200241187472200141ff01717222013600c3030240200e450d0041d6b2c0002102410f2117024020010e05001605081b000b20032800c703210220032800cb0321170c1a0b20034190026a41186a200341c0036a41186a29030037030020034190026a41106a200341c0036a41106a29030037030020034190026a41086a200341c0036a41086a290300370300200320032903c00337039002024020034190026a109f02450d0020034190026a410110a402410021020c1a0b410f21174199bfc10021020c190b41022107200341b8046a41026a200141076a2d00003a0000200341d8006a41086a200141146a290200370300200341d8006a41106a2001411c6a290200370300200341d8006a41186a200141246a280200360200200320012f00053b01b80420032001410c6a290200370358200141086a280200211720012d000421152002411a6a2901002108200241196a2d00002106200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000211a2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241046a2d0000210f200241026a2f010021160240024020022d00000d0020022d00014101470d00200241056a2d00002107200241066a2f01002101200241086a2d00002102410021190c010b4101211941002101410021020b200141ffff0371410874200741ff017172200241187472210102402019450d0041d6b2c0002102410f2117024020010e05001504071a000b201341087420147220124118747221022010410874201172201a4118747221170c190b200320083703b003200320063a00af03200320093a00ae032003200a3b01ac032003200b3a00ab032003200c3a00aa032003200d3b01a8032003200e3a00a7032003201a3a00a603200320103b01a403200320113a00a303200320123a00a203200320133b01a003200320143a009f032003200136009b032003200f3a009a03200320163b019803200341e0036a41026a2202200341b8046a41026a2d00003a000020034180016a41086a200341d8006a41086a29030037030020034180016a41106a2201200341d8006a41106a29030037030020034180016a41186a200341d8006a41186a280200360200200320032f01b8043b01e00320032003290358370380010240201541ff01714101460d00200341c0046a41026a20022d00003a0000200341f0016a41086a20034180016a41086a290300370300200341f0016a41106a2001290300370300200341f0016a41186a20034180016a41186a2d00003a0000200320032f01e0033b01c00420032003290380013703f0010c120b200341a0016a201741067610910220032802a00121010240024020032802a8012017413f7122024b0d00410021020c010b200341c0046a41026a200120024105746a220241026a2d00003a0000200341f8016a2002410f6a29000037030020034180026a200241176a29000037030020034188026a2002411f6a2d00003a0000200320022f00003b01c004200320022900073703f00120022800032117410121020b024020032802a401450d002001102c0b20020d11410121020c120b2002411a6a2901002108200241196a2d00002114200241186a2d00002115200241166a2f01002106200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d000021192002410e6a2f0100211a2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d0000210d41022101200241026a2f0100210e0240024020022d00000d0020022d00014101470d00200241056a2d00002101200241066a2f01002117200241086a2d00002102410021070c010b4101210741002117410021020b201741ffff0371410874200141ff017172200241187472210102402007450d0041d6b2c0002102410f2117024020010e050014030619000b20124108742013722011411874722102201a41087420107220194118747221170c180b2003200837038804200320143a008704200320153a008604200320063b018404200320093a0083042003200a3a0082042003200b3b0180042003200c3a00ff03200320193a00fe032003201a3b01fc03200320103a00fb03200320113a00fa03200320123b01f803200320133a00f703200320013600f3032003200d3a00f2032003200e3b01f00320034190026a41186a420037030020034190026a41106a2210420037030020034190026a41086a22014200370300200342003703900220034180016a41086a220241e5d6c500ad42808080808002841002221741086a29000037030020032017290000370380012017102c200120022903003703002003200329038001370390022002419883c100ad4280808080a001841002221741086a29000037030020032017290000370380012017102c20102003290380012208370300200341a0016a41086a2001290300370300200341a0016a41106a2008370300200341a0016a41186a2002290300370300200320083703c00320032003290390023703a00120034190026a200341a0016a412010d0012003280290022201410120011b21194100211a410021020240200329029402420020011b2208422088a7220141014b0d004100210720010e020f0e0f0b03402001410176221720026a22072002201920074105746a200341f0036a412010dd054101481b2102200120176b220141014b0d000c0e0b0b2002411a6a2901002108200241196a2d00002115200241186a2d00002106200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000211a2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241046a2d0000210e41022117200241026a2f0100210f0240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f01002107200241086a2d00002102410021190c010b4101211941002107410021020b200741ffff0371410874201741ff01717220024118747221072019450d0141d6b2c0002102410f2117024020070e050012010417000b201341087420147220124118747221022010410874201172201a4118747221170c160b41c3b2c0002102411321170c150b2003200837038804200320153a008704200320063a008604200320093b0184042003200a3a0083042003200b3a0082042003200c3b0180042003200d3a00ff032003201a3a00fe03200320103b01fc03200320113a00fb03200320123a00fa03200320133b01f803200320143a00f703200320073600f3032003200e3a00f2032003200f3b01f003200341a0016a200341f0036a10a50220032d00a001450d0320034190026a41186a420037030020034190026a41106a2210420037030020034190026a41086a22174200370300200342003703900220034180016a41086a220241e5d6c500ad42808080808002841002220741086a29000037030020032007290000370380012007102c20172002290300370300200320032903800137039002200241a283c100ad42808080809001841002220741086a29000037030020032007290000370380012007102c20102003290380012208370300200341a0016a41086a2017290300370300200341a0016a41106a2008370300200341a0016a41186a2002290300370300200320083703c00320032003290390023703a00120034190026a200341a0016a10d1012003280290022217410820171b211a41002102024002400240024002400240200329029402420020171b2205422088a7221141014b0d0020110e020201020b2011211703402017410176220720026a22192002201a201941306c6a200341f0036a412010dd054101481b2102201720076b221741014b0d000b0b201a200241306c6a200341f0036a412010dd05450d010b20034190026a41186a2219420037030020034190026a41106a2211420037030020034190026a41086a22174200370300200342003703900220034180016a41086a220241e5d6c500ad42808080808002841002220741086a29000037030020032007290000370380012007102c201720022903003703002003200329038001370390022002419883c100ad4280808080a001841002220741086a29000037030020032007290000370380012007102c200341c0036a41086a20022903002208370300200320032903800122043703c00320102004370000201041086a2008370000200341a0016a41086a2017290300370300200341a0016a41106a2011290300370300200341a0016a41186a201929030037030020032003290390023703a00120034190026a200341a0016a412010d0012003280290022217410120171b211041002102024002400240200329029402420020171b2208422088a7221141014b0d0020110e020201020b2011211703402017410176220720026a22192002201020194105746a200341f0036a412010dd054101481b2102201720076b221741014b0d000b0b201020024105746a200341f0036a412010dd05450d030b41ebbec10021022008a70d010c0b0b200220114f0d06201a200241306c6a2217201741306a2002417f7320116a41306c10dc051a200341f0036a4280809aa6eaafe301420010c201200341c0036a41186a4200370300200341c0036a41106a22194200370300200341c0036a41086a22174200370300200342003703c00320034180016a41086a220241e5d6c500ad42808080808002841002220741086a29000037030020032007290000370380012007102c20172002290300370300200320032903800122083703f001200320083703c003200241a283c100ad42808080809001841002220741086a29000037030020032007290000370380012007102c2019200329038001220837030020034190026a41086a201729030037030020034190026a41106a200837030020034190026a41186a2002290300370300200320083703a001200320032903c00337039002200341003602a801200342013703a0012011417f6a2202200341a0016a10670240024020020d0020032802a801211720032802a401211920032802a00121070c010b201a200241306c6a2111201a210203402002200341a0016a109101200241286a2903002108200241206a29030021040240024020032802a401221920032802a80122176b4110490d0020032802a00121070c010b201741106a22072017490d11201941017422172007201720074b1b22104100480d110240024020190d002010102a21070c010b20032802a00120192010102e21070b2007450d15200320103602a401200320073602a00120032802a8012117201021190b200720176a22102008370008201020043700002003201741106a22173602a8012011200241306a2202470d000b0b20034190026aad42808080808004842017ad4220862007ad84100102402019450d002007102c0b410021022005a7450d0b201a102c0c0b0b2010102c0c090b200220114f0d05201020024105746a2217201741206a2002417f7320116a41057410dc051a200341f0036a4280809aa6eaafe301420010c201200341c0036a41186a4200370300200341c0036a41106a22194200370300200341c0036a41086a22174200370300200342003703c00320034180016a41086a220241e5d6c500ad42808080808002841002220741086a29000037030020032007290000370380012007102c20172002290300370300200320032903800122043703f001200320043703c0032002419883c100ad4280808080a001841002220741086a29000037030020032007290000370380012007102c2019200329038001220437030020034190026a41086a201729030037030020034190026a41106a200437030020034190026a41186a2002290300370300200320043703a001200320032903c00337039002200341003602a801200342013703a0012011417f6a2202200341a0016a106702402002450d00201141057441606a21172010210203402002200341a0016a109101200241206a2102201741606a22170d000b0b20032802a401210220034190026aad428080808080048420033502a80142208620032802a0012217ad84100102402002450d002017102c0b410021022008a7450d082010102c0c080b200341d8006a41026a2217200141076a2d00003a0000200341f0036a41086a2207200141146a290200370300200341f0036a41106a22192001411c6a290200370300200341f0036a41186a221a200141246a280200360200200320012f00053b015820032001410c6a2902003703f00320022d000120022d000072450d010b41b2b2c0002102411121170c120b200141086a280200210220012d00042101200341e0036a41026a20172d00003a000020034180016a41086a200729030037030020034180016a41106a201929030037030020034180016a41186a201a280200360200200320032f01583b01e003200320032903f003370380010240200141ff01714101460d00200341c0046a41026a200341e0036a41026a2d00003a0000200341f0016a41086a20034180016a41086a290300370300200341f0016a41106a20034180016a41106a290300370300200341f0016a41186a20034180016a41186a2d00003a0000200320032f01e0033b01c00420032003290380013703f0010c040b20034190026a20024106761091022003280290022101024002402003280298022002413f7122024b0d00410021170c010b200341c0046a41026a200120024105746a220241026a2d00003a0000200341f8016a2002410f6a29000037030020034180026a200241176a29000037030020034188026a2002411f6a2d00003a0000200320022f00003b01c004200320022900073703f00120022800032102410121170b0240200328029402450d002001102c0b20170d03410121010c040b200341f0036a4280809aa6eaafe301420010c2012003419d026a200341f8036a290300370000200341a5026a20034180046a290300370000200341ad026a20034188046a290300370000200341033a009402200341093a009002200320032903f00337009502410021024101410020034190026a1092010c050b418ab4c000411d41acfec5001036000b418ab4c000411d41acfec5001036000b20034198036a41026a200341c0046a41026a2d00003a000020034190026a41086a200341f0016a41086a29030037030020034190026a41106a200341f0016a41106a29030037030020034190026a41186a200341f0016a41186a2d00003a0000200320032f01c0043b019803200320032903f00137039002410021010b200341c0036a41026a20034198036a41026a2d00003a0000200341cf036a20034190026a41086a290300370000200341d7036a20034190026a41106a290300370000200341df036a20034190026a41186a2d00003a0000200320032f0198033b01c003200320023600c30320032003290390023700c70320010d07200341a0016a41186a200341c0036a41186a290100370300200341a0016a41106a200341c0036a41106a290100370300200341a0016a41086a200341c0036a41086a290100370300200320032901c0033703a00120034198036a200341a0016a10a502024020032d0098034101460d0020032d0099032101200341c8006a200341a0016a4280809aa6eaafe301420010bf012003290348200341c8006a41086a29030010a9012003419d026a200341a0016a41086a290300370000200341a5026a200341b0016a290300370000200341ad026a200341b8016a290300370000200341023a009402200341093a009002200320032903a00137009502410021024101410020034190026a10920102402001450d000c0e0b10cf010c0d0b200341a0036a2802002117200328029c0321020c0c0b2005a7450d00201a102c0b412e211720012802004101470d0a200141086a280200450d0a2001280204102c0c0a0b0240201920024105746a200341f0036a412010dd0522010d004101211a200221070c010b2001411f7620026a21070b02402008a7450d002019102c0b0240201a450d0041e7bdc1002102411e21170c090b4185bec100210241212117200341f0036a10a6020d0841a6bec1002102200341f0036a10a7020d0842002108200341c0006a200341f0036a4280809aa6eaafe301420010c10102402003280240450d0041c7bec1002102412421170c090b200329038804210420032d008704211920032d008604211a20032f018404211120032d008304211220032d008204211320032f018004211420032d00ff03211520032d00fe03210620032f01fc03210920032d00fb03210a20032d00fa03210b20032f01f803210c20032d00f703210d20032800f303210e20032d00f203210f20032f01f003211620034190026a41186a2218420037030020034190026a41106a221d420037030020034190026a41086a22014200370300200342003703900220034180016a41086a220241e5d6c500ad42808080808002841002221741086a29000037030020032017290000370380012017102c200120022903003703002003200329038001370390022002419883c100ad4280808080a001841002221741086a29000037030020032017290000370380012017102c200341c0036a41086a200229030022053703002003200329038001221b3703c0032010201b370000201041086a2005370000200341a0016a41086a2001290300370300200341a0016a41106a201d290300370300200341a0016a41186a201829030037030020032003290390023703a00120034190026a200341a0016a412010d0010240024020032802900222170d004100210241012117410021010c010b2003290294022208422088a721012008a721020b024020012007490d00024020012002470d0020022008a7470d00200241016a22102002490d02200241017422182010201820104b1b221041ffffff3f712010470d02201041057422184100480d020240024020020d002018102a21170c010b201720024105742018102e21170b2017450d062010ad21080b201720074105746a220241206a2002200120076b41057410dc051a20022004370018200220193a00172002201a3a0016200220113b0014200220123a0013200220133a0012200220143b0010200220153a000f200220063a000e200220093b000c2002200a3a000b2002200b3a000a2002200c3b00082002200d3a00072002200e3600032002200f3a0002200220163b0000200341c0036a41186a4200370300200341c0036a41106a221a4200370300200341c0036a41086a22074200370300200342003703c00320034180016a41086a220241e5d6c500ad42808080808002841002221941086a29000037030020032019290000370380012019102c20072002290300370300200320032903800122043703f001200320043703c0032002419883c100ad4280808080a001841002221941086a29000037030020032019290000370380012019102c201a200329038001220437030020034190026a41086a200729030037030020034190026a41106a200437030020034190026a41186a2002290300370300200320043703a001200320032903c00337039002024020170d0020034190026aad42808080808004841005410021020c0a0b200341003602a801200342013703a001200141016a2202200341a0016a106702402002450d00201720024105746a21012017210203402002200341a0016a1091012001200241206a2202470d000b0b2008a7210220032802a401210120034190026aad428080808080048420033502a80142208620032802a0012207ad84100102402001450d002007102c0b2002450d072017102c410021020c090b41ecb3c000411e41acfec5001036000b1035000b200341c0036a41026a200341c0046a41026a2d00003a0000200341a0016a41086a200341f0016a41086a290300370300200341a0016a41106a200341f0016a41106a290300370300200341a0016a41186a200341f0016a41186a2d00003a0000200320032f01c0043b01c003200320032903f0013703a001410021020b2003419f026a200341a0016a41086a290300370000200341a7026a200341a0016a41106a290300370000200341af026a200341a0016a41186a2d00003a0000200320032f01c0033b0190022003201736009302200320032903a001370097022003200341c2036a2d00003a00920220020d00200341f0036a41186a20034190026a41186a290300370300200341f0036a41106a20034190026a41106a290300370300200341f0036a41086a20034190026a41086a29030037030020032003290390023703f003024020034198036a200341f0036a412010dd050d0041bdbdc1002102411221170c060b024020034198036a109f020d0041cfbdc1002102411821170c060b02400240200341f0036a109f02450d0020034180016a41086a221041e5d6c500ad428080808080028422051002220241086a29000037030020032002290000370380012002102c200341f0016a41086a2201201029030037030020032003290380013703f001201041affbc000ad4280808080f000841002220241086a29000037030020032002290000370380012002102c200341a0016a41086a2212201029030037030020032003290380013703a001200341c0036a200341f0036a109f0141c000102a2202450d03200220032903f001370000200241086a2001290300370000200220032903a001370010200241186a2012290300370000200220032903c003370020200241286a200341c0036a41086a2214290300370000200241306a200341c0036a41106a290300370000200241386a200341c0036a41186a29030037000020034190026a200241c00010d0012002102c2003280290022202410120021b2215200329029402420020021b221b422088a74105746a211320034190026a41106a211120152119034020192013460d020240201910a6020d00201910a7020d0020034190026a41186a221742003703002011420037030020034190026a41086a220242003703002003420037039002201020051002220141086a29000037030020032001290000370380012001102c200220102903003703002003200329038001370390022010419883c100ad4280808080a001841002220141086a29000037030020032001290000370380012001102c201420102903002208370300200320032903800122043703c00320112004370000201141086a200837000020122002290300370300200341a0016a41106a2011290300370300200341a0016a41186a201729030037030020032003290390023703a00120034190026a200341a0016a412010d0012003280290022201410120011b211a41002102024002400240200329029402420020011b2208422088a7220141014b0d0020010e020201020b03402001410176221720026a22072002201a20074105746a2019412010dd054101481b2102200120176b220141014b0d000b0b201a20024105746a2019412010dd054521020b02402008a7450d00201a102c0b201941206a21192002450d010b0b201ba7450d002015102c0b200341306a20034198036a428080e983b1de16420010bf012003290330200341386a29030010a9014100210120034198036a21170c030b0240201ba7450d002015102c0b20034190026a200341f0036a20034198036a428080e983b1de16420010c00141012101200341f0036a21172003280290024101470d0220034198026a280200211720032802940221020c050b41dd8cc6002102410e21170c040b1033000b410021022017410010a4022003419d026a200341f0036a41086a290300370000200341a5026a200341f0036a41106a290300370000200341ad026a200341f0036a41186a290300370000200341b5026a200329039803370000200341bd026a20034198036a41086a290300370000200341c5026a20034198036a41106a290300370000200341cd026a20034198036a41186a290300370000200341d5026a20013a0000200341043a009402200341093a009002200320032903f003370095024101410020034190026a1092010c020b410021020c010b2007450d002001102c0b2000201736020420002002360200200341d0046a24000bd10201057f230041d0006b22012400200141306a41086a220241e5d6c500ad42808080808002841002220341086a290000370300200120032900003703302003102c200141106a41086a2204200229030037030020012001290330370310200241fdfbc000ad4280808080f000841002220341086a290000370300200120032900003703302003102c200141206a41086a2205200229030037030020012001290330370320200141306a2000109f01024041c000102a22030d001033000b200320012903103700002003200129032037001020032001290030370020200341086a2004290300370000200341186a2005290300370000200341286a2002290000370000200341306a200141c0006a290000370000200341386a200141306a41186a290000370000200141086a200341c000410141004100109701200128020821022003102c200141d0006a240020024101460be80b030a7f017e027f230041a0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022040d00200041023a000c0c010b200328021421052003200341106a41086a28020036026420032004360260200341e8006a200341e0006a10820102400240024020032802682206450d00200328026c2107024020032802642201450d00200341e8006a41086a280200210820032001417f6a220936026420032003280260220a41016a220b360260200a2d0000220141014b0d004100210c0240024020010e020100010b41002101200341003a0098020340024020092001470d0020034100360264200141ff0171450d03200341003a0098020c030b200341f8016a20016a200a20016a220241016a2d00003a00002003200241026a3602602003200141016a22023a0098022002210120024120470d000b200341b8016a41086a200341f8016a41086a290300220d37030020034198016a41186a200341f8016a41186a29030037030020034198016a41106a200341f8016a41106a29030037030020034198016a41086a200d3703002003200920026b2209360264200320032903f801220d3703b8012003200d370398014101210c200a20026a41016a210b0b200341f8006a41186a20034198016a41186a290300370300200341f8006a41106a20034198016a41106a290300370300200341f8006a41086a20034198016a41086a29030037030020032003290398013703782009450d0020032009417f6a22093602642003200b41016a360260200b2d0000220141014b0d00410021020240024020010e020100010b41002101200341003a0098020340024020092001470d0020034100360264200141ff0171450d03200341003a0098020c030b200341f8016a20016a200b20016a220241016a2d00003a00002003200241026a3602602003200141016a22023a0098022002210120024120470d000b200341b8016a41086a200341f8016a41086a290300220d37030020034198016a41186a200341f8016a41186a29030037030020034198016a41106a200341f8016a41106a29030037030020034198016a41086a200d3703002003200920026b360264200320032903f801220d3703b8012003200d37039801410121020b200341206a41186a220120034198016a41186a290300370300200341206a41106a220920034198016a41106a290300370300200341206a41086a220a20034198016a41086a290300370300200341c0006a41086a220b200341f8006a41086a290300370300200341c0006a41106a220e200341f8006a41106a290300370300200341c0006a41186a220f200341f8006a41186a290300370300200320032903980137032020032003290378370340200c4102460d02200020083602082000200736020420002006360200200341f8016a41086a2206200b290300370300200341f8016a41106a220b200e290300370300200341f8016a41186a2207200f290300370300200341d8016a41086a2208200a290300370300200341d8016a41106a220a2009290300370300200341d8016a41186a22092001290300370300200320032903403703f801200320032903203703d801200320032f011e3b01b801200041256a20072903003700002000411d6a200b290300370000200041156a2006290300370000200020032903f80137000d2000412d6a20023a00002000412e6a20032903d801370000200041366a20082903003700002000413e6a200a290300370000200041c6006a2009290300370000200041ce006a20032f01b8013b00000c030b2007450d002006102c0b4102210c0b200341003602e001200342013703d8012003410b3602bc012003200341086a3602b8012003200341d8016a360298012003418c026a4101360200200342013702fc01200341d0b0c2003602f8012003200341b8016a3602880220034198016a41c49ac500200341f8016a10391a20033502e00142208620033502d80184100420032802dc01450d0020032802d801102c0b2000200c3a000c2005450d002004102c0b200341a0026a24000bc30301027f20002d0000210202404101102a2203450d00200320023a000020002d00012102200341014102102e2203450d00200320023a000120002d00022102200341024104102e2203450d00200320023a0002200320002d00033a000320002d00042102200341044108102e2203450d00200320023a0004200320002d00053a0005200320002d00063a0006200320002d00073a000720002d00082102200341084110102e2203450d00200320023a0008200320002d00093a0009200320002d000a3a000a200320002d000b3a000b200320002d000c3a000c200320002d000d3a000d200320002d000e3a000e200320002d000f3a000f20002d00102102200341104120102e2203450d00200320023a0010200320002d00113a0011200320002d00123a0012200320002d00133a0013200320002d00143a0014200320002d00153a0015200320002d00163a0016200320002d00173a0017200320002d00183a0018200320002d00193a0019200320002d001a3a001a200320002d001b3a001b200320002d001c3a001c200320002d001d3a001d200320002d001e3a001e200320002d001f3a001f20012902002003ad428080808080048410012003102c0f0b1033000ba00501047f200141046a2802002102200141086a28020021030240024002400240200028020022040d000240024020022003460d00200128020021020c010b200341016a22022003490d04200341017422042002200420024b1b22044100480d040240024020030d002004102a21020c010b200128020020032004102e21020b2002450d0320012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a41003a00000c010b0240024020022003460d00200128020021020c010b200341016a22022003490d03200341017422052002200520024b1b22054100480d030240024020030d002005102a21020c010b200128020020032005102e21020b2002450d0220012002360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200220036a41013a0000200428020020011091010b200141046a2802002102200141086a28020021030240200028020422040d000240024020022003460d00200128020021000c010b200341016a22002003490d03200341017422022000200220004b1b22024100480d030240024020030d002002102a21000c010b200128020020032002102e21000b2000450d0220012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b0240024020022003460d00200128020021000c010b200341016a22002003490d02200341017422022000200220004b1b22024100480d020240024020030d002002102a21000c010b200128020020032002102e21000b2000450d0120012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41013a0000200420011091010f0b1033000b1035000bb50501037f024002400240024020002d00004101460d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41003a00000c010b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d03200241017422042003200420034b1b22044100480d030240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41013a0000200041016a20011091010b024020002d00214101460d0002400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d03200041017422032002200320024b1b22034100480d030240024020000d002003102a21020c010b200128020020002003102e21020b2002450d0220012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41003a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d02200241017422042003200420034b1b22044100480d020240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41013a0000200041226a20011091010f0b1033000b1035000bdb1505047f017e027f017e047f23004180046b22022400200241e0006a41086a220341e5d6c500ad42808080808002841002220441086a290000370300200220042900003703602004102c200241186a41086a2205200329030037030020022002290360370318200341affbc000ad4280808080f000841002220441086a290000370300200220042900003703602004102c200241a0026a41086a22042003290300370300200220022903603703a002200241f0026a2000109f01024041c000102a2203450d0020032002290318370000200320022903a002370010200320022900f002370020200341086a2005290300370000200341186a2004290300370000200341286a200241f0026a41086a290000370000200341306a20024180036a290000370000200341386a200241f0026a41186a290000370000200241f0026a200341c00010a002024020022d00fc0222044102460d002003ad428080808080088410050b20022902f402210620022802f0022107200241186a200241fd026a41c30010db051a200241e0006a200241186a41c30010db051a0240024020044102470d002003102c0c010b200220043a00a801200241a8016a410172200241e0006a41c10010db052108200241ca016a21050240024020022d00c9014101460d00200241003602f0010c010b200241f0016a200510840220022d00a80121040b02400240024002400240200441ff01714101460d0020024100360280020c010b20024180026a20081084022002280280020d010b024020022d00c9014101460d00200241f0026a10d20120023502f80242208620022802f0022204ad84100520022802f402450d022004102c0c020b200241f0026a10d20120022802f0022104200220022802f8023602a402200220043602a0022005200241a0026a10a10220022802f402450d012004102c0c010b20024190026a41086a20024180026a41086a28020022083602002002200229038002220937039002200241a0026a2009a7220a200810a0020240024020022d00ac024102470d00200241003602c803200242013703c003200241d0036a41146a410d360200200241dc036a410b360200200241103602ec03200241e5d6c5003602e8032002410b3602d403200241073602f403200241affbc0003602f003200220024190026a3602e0032002200241f0036a3602d8032002200241e8036a3602d0032002200241c0036a3602fc03200241f0026a41146a4103360200200242033702f402200241849dc5003602f0022002200241d0036a36028003200241fc036a41c49ac500200241f0026a10391a20023502c80342208620023502c00384100420022802c403450d0120022802c003102c0c010b200241f0026a200241a0026a41d00010db051a200241bd036a200241c9016a220441206a2d00003a0000200241b5036a200441186a290000370000200241ad036a200441106a290000370000200241a5036a200441086a2900003700002002419d036a2004290000370000200241003602d803200242013703d00320022802f002210420022802f8022205200241d0036a1067200241fc026a210b02402005450d002005410574210503402004200241d0036a109101200441206a2104200541606a22050d000b0b200b200241d0036a10a30220022802d40321042008ad422086200aad8420023502d80342208620022802d0032205ad84100102402004450d002005102c0b20022802f402450d0020022802f002102c0b0240200228029402450d00200228029002102c0b4101210a0c010b4100210a0b0240024020022802f00122080d00410021040c010b20024190026a41086a200241f0016a41086a280200220b360200200220022903f001220937039002200241a0026a2009a7220c200b10a0020240024020022d00ac024102470d00200241003602c803200242013703c003200241d0036a41146a410d360200200241dc036a410b360200200241103602ec03200241e5d6c5003602e8032002410b3602d403200241073602f403200241affbc0003602f003200220024190026a3602e0032002200241f0036a3602d8032002200241e8036a3602d0032002200241c0036a3602fc03200241f0026a41146a4103360200200242033702f402200241a89cc5003602f0022002200241d0036a36028003200241fc036a41c49ac500200241f0026a10391a20023502c80342208620023502c00384100420022802c403450d0120022802c003102c0c010b200241f0026a200241a0026a41d00010db051a2002419c036a200241a8016a41206a2d00003a000020024194036a200241c0016a2903003702002002418c036a200241b8016a29030037020020024184036a200241a8016a41086a290300370200200220022903a8013702fc02200241003602d803200242013703d00320022802f002210420022802f8022205200241d0036a1067200241fc026a210d02402005450d002005410574210503402004200241d0036a109101200441206a2104200541606a22050d000b0b200d200241d0036a10a30220022802d4032104200bad422086200cad8420023502d80342208620022802d0032205ad84100102402004450d002005102c0b20022802f402450d0020022802f002102c0b0240200228029402450d00200228029002102c0b410121040b0240200a200228028002220545720d00200228028402450d002005102c0b02402004200845720d0020022802f401450d002008102c0b2003102c2007450d002006a7450d002007410120071b102c0b200241e0006a41086a220441e5d6c500ad42808080808002841002220341086a290000370300200220032900003703602003102c200241186a41086a2205200429030037030020022002290360370318200441fdfbc000ad4280808080f000841002220341086a290000370300200220032900003703602003102c200241a0026a41086a22072004290300370300200220022903603703a002200241f0026a2000109f0141c000102a2203450d0020032002290318370000200320022903a002370010200320022900f002370020200341086a2005290300370000200341186a2007290300370000200341286a200241f0026a41086a2205290000370000200341306a200241f0026a41106a2208290000370000200341386a200241f0026a41186a220a2900003700002003ad428080808080088410052003102c200242f0d0c9abc6add9b1f400370310200a42003703002008420037030020054200370300200242003703f00220044191b0c200ad4280808080e000841002220341086a290000370300200220032900003703602003102c20052004290300370300200220022903603703f002200441acb0c200ad4280808080e000841002220341086a290000370300200220032900003703602003102c20082002290360220637030020072005290300370300200241a0026a41106a2006370300200241a0026a41186a200429030037030020022006370318200220022903f0023703a002200241086a200241a0026a41201094012002200228020c410020022802081b360260200241f0026a200010ae0120022802f402210420022802f002210320022802f802210820024184036a200241106a3602002002200320084105746a3602fc02200220033602f802200220043602f402200220033602f0022002200241e0006a36028003200241a0026a200241f0026a10860120052007280200360200200220022903a0023703f0022000200241f0026a10b00102402001450d002000428080e983b1de16420010c2010b20024180046a24000f0b1033000ba61b09057f017e027f027e027f037e017f057e017f230041c0016b22022400200241a0016a41186a4200370300200241a0016a41106a22034200370300200241a0016a41086a22044200370300200242003703a001200241206a41086a220541e5d6c500ad42808080808002841002220641086a290000370300200220062900003703202006102c20042005290300370300200220022903203703a001200541eae5c200ad4280808080f000841002220641086a290000370300200220062900003703202006102c20032002290320220737030020024180016a41086a200429030037030020024180016a41106a200737030020024180016a41186a200529030037030020022007370360200220022903a00137038001200241c0006a20024180016a10d101024002400240024002400240200228024022080d0041002109410821080c010b2002290244220aa721094100210502400240200a422088220ba7220c41014b0d00200c0e020201020b200c210403402004410176220620056a220d20052008200d41306c6a2001412010dd054101481b2105200420066b220441014b0d000b0b2008200541306c6a2001412010dd05450d010b200041013a0000200041086a410c360200200041046a41aeecc1003602002009450d012008102c0c010b02400240024002402005200c4f0d002008200541306c6a2204200441306a200c2005417f736a41306c10dc051a200241a0016a41186a22094200370300200241a0016a41106a220c4200370300200241a0016a41086a220d4200370300200242003703a001200241206a41086a220541e5d6c500ad428080808080028422071002220441086a290000370300200220042900003703202004102c200d2005290300370300200220022903203703a001200541a283c100ad4280808080900184220e1002220441086a290000370300200220042900003703202004102c200241e0006a41086a22042005290300220f37030020022002290320221037036020032010370000200341086a200f37000020024180016a41086a200d29030037030020024180016a41106a200c29030037030020024180016a41186a2009290300370300200220022903a00137038001200241a0016a20024180016a10d10120022802a0012206410820061b21110240024020022902a401420020061b220f422088221050450d00420021100c010b20092011201042ffffffff0f7c2210a741306c6a220641186a290300370300200c200641106a290300370300200d200641086a290300370300200220062903003703a0012010422086200f42ffffffff0f8384210f200641286a290300211220062903202113420121100b200241e0006a41186a4200370300200241e0006a41106a220c42003703002004420037030020024200370360200520071002220641086a290000370300200220062900003703202006102c2004200529030037030020022002290320220737038001200220073703602005200e1002220641086a290000370300200220062900003703202006102c200c20022903202207370300200241c0006a41086a2004290300370300200241c0006a41106a2007370300200241c0006a41186a20052903003703002002200737038001200220022903603703400240024020110d00200241c0006aad428080808080048410050c010b20024100360288012002420137038001200f422088a7220520024180016a10670240024020050d002002280288012104200228028401210d20022802800121060c010b2011200541306c6a2109201121050340200520024180016a109101200541286a2903002107200541206a290300210e02400240200228028401220d20022802880122046b4110490d0020022802800121060c010b200441106a22062004490d0a200d41017422042006200420064b1b22034100480d0a02400240200d0d002003102a21060c010b200228028001200d2003102e21060b2006450d092002200336028401200220063602800120022802880121042003210d0b200620046a220320073700082003200e3700002002200441106a2204360288012009200541306a2205470d000b0b200241c0006aad42808080808004842004ad4220862006ad8410010240200d450d002006102c0b200fa7450d002011102c0b200a42ffffffff0f83200b42ffffffff0f7c2214422086221584210b200241186a200241a0016a41186a2903002207370300200241106a200241a0016a41106a290300220e370300200241086a200241a0016a41086a290300220f370300200220022903a0012216370300200241206a41186a22052007370300200241206a41106a2204200e370300200241206a41086a2203200f370300200220163703200240201050450d00410021110c040b20024180016a41186a200529030037030020024180016a41106a200429030037030020024180016a41086a20032903003703002002200229032037038001410021050240024002402014a7220941014b0d0020090e020201020b2009210403402004410176220620056a220d20052008200d41306c6a20024180016a412010dd054101481b2105200420066b220441014b0d000b0b2008200541306c6a20024180016a412010dd052204450d022004411f7620056a21050b200241c0006a41186a20024180016a41186a2903002207370300200241c0006a41106a20024180016a41106a290300220e370300200241c0006a41086a20024180016a41086a290300220f37030020022002290380012210370340200241e0006a41186a2007370300200241e0006a41106a200e370300200241e0006a41086a200f37030020022010370360200241a0016a41186a2007370300200241a0016a41106a200e370300200241a0016a41086a200f370300200220103703a001200520094b0d0202402009200aa7470d00200941016a22042009490d07200941017422062004200620044b1bad220742307e220e422088a70d07200ea722044100480d070240024020090d002004102a21080c010b2008200941306c2004102e21080b2008450d062015200784210b0b2008200541306c6a220441306a2004200920056b41306c10dc051a200441286a201237030020042013370320200441186a200241a0016a41186a290300370300200441106a200241a0016a41106a290300370300200441086a200241a0016a41086a290300370300200420022903a001370300200b42ffffffff0f83200a4280808080708384210b410121110c030b418ab4c000411d41acfec5001036000b200241c0006a41186a20024180016a41186a290300370300200241c0006a41106a20024180016a41106a290300370300200241c0006a41086a20024180016a41086a2903003703002002200229038001370340410021110c010b41ecb3c000411e41acfec5001036000b200241e0006a41186a22064200370300200241e0006a41106a220d4200370300200241e0006a41086a2205420037030020024200370360200341e5d6c500ad42808080808002841002220441086a290000370300200220042900003703202004102c200520032903003703002002200229032022073703800120022007370360200341eae5c200ad4280808080f000841002220441086a290000370300200220042900003703202004102c20024180016a41086a2003290300220737030020022002290320220e37038001200c200e370000200c41086a2007370000200241c0006a41086a2005290300370300200241c0006a41106a200d290300370300200241c0006a41186a200629030037030020022002290360370340200241003602a801200242013703a001200b422088a7220c200241a0016a106702400240200c0d0020022802a801210420022802a401210d20022802a00121060c010b2008200c41306c6a21092008210503402005200241a0016a109101200541286a2903002107200541206a290300210e0240024020022802a401220d20022802a80122046b4110490d0020022802a00121060c010b200441106a22062004490d05200d41017422042006200420064b1b22034100480d0502400240200d0d002003102a21060c010b20022802a001200d2003102e21060b2006450d04200220033602a401200220063602a00120022802a80121042003210d0b200620046a220320073700082003200e3700002002200441106a22043602a8012009200541306a2205470d000b0b200241c0006aad42808080808004842004ad4220862006ad8410010240200d450d002006102c0b200c41306c220541306d2103410021060240024020050d0041012109410021030c010b200341ffffff3f712003470d03200341057422054100480d032005102a2209450d020b200ba721170240200c450d00200c41306c210d4100210620092105200821040340200441086a2900002107200441106a290000210e2004290000210a200541186a200441186a290000370000200541106a200e370000200541086a20073700002005200a370000200641016a2106200541206a2105200441306a2104200d41506a220d0d000b0b02402017450d002008102c0b200241a0016a41186a200141186a290000370300200241a0016a41106a200141106a290000370300200241a0016a41086a200141086a290000370300200220012900003703a001200241a0016a41012009200610dd01200020113a0001200041003a0000200041026a2002290180013701002000410a6a20024180016a41086a2f01003b01002003450d002009102c0b200241c0016a24000f0b1033000b1035000b960303057f017e017f230041e0006b22012400200141206a41186a4200370300200141206a41106a22024200370300200141206a41086a2203420037030020014200370320200141d0006a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200120052900003703502005102c2003200429030037030020012001290350370320200441eae5c200ad4280808080f000841002220541086a290000370300200120052900003703502005102c200220012903502206370300200141086a2003290300370300200141106a2006370300200141186a20042903003703002001200637034020012001290320370300200141206a200110d10120012802202203410820031b2107410021040240024002402001290224420020031b2206422088a7220341014b0d0020030e020201020b03402003410176220520046a220220042007200241306c6a2000412010dd054101481b2104200320056b220341014b0d000b0b2007200441306c6a2000412010dd054521040b02402006a7450d002007102c0b200141e0006a240020040b960303057f017e017f230041e0006b22012400200141206a41186a4200370300200141206a41106a22024200370300200141206a41086a2203420037030020014200370320200141d0006a41086a220441e5d6c500ad42808080808002841002220541086a290000370300200120052900003703502005102c2003200429030037030020012001290350370320200441a283c100ad42808080809001841002220541086a290000370300200120052900003703502005102c200220012903502206370300200141086a2003290300370300200141106a2006370300200141186a20042903003703002001200637034020012001290320370300200141206a200110d10120012802202203410820031b2107410021040240024002402001290224420020031b2206422088a7220341014b0d0020030e020201020b03402003410176220520046a220220042007200241306c6a2000412010dd054101481b2104200320056b220341014b0d000b0b2007200441306c6a2000412010dd054521040b02402006a7450d002007102c0b200141e0006a240020040bb309010a7f230041b0016b2202240041002103024020012802102204450d0020012802082205200128020c460d00200128021421062001200541246a360208200241c4006a41026a2207200541036a2d00003a0000200241286a41086a2208200541106a290000370300200241286a41106a2209200541186a290000370300200241286a41186a220a200541206a280000360200200220052f00013b01442002200541086a29000037032820052d0000220b4102460d00200541046a280000210520012004417f6a360210200241086a41026a20072d00003a000020024190016a41086a200829030037030020024190016a41106a200929030037030020024190016a41186a200a280200360200200220022f01443b01082002200229032837039001024002400240200b4101460d002002418c016a41026a200241086a41026a2d00003a0000200241f0006a41086a20024190016a41086a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41186a20024190016a41186a2d00003a0000200220022f01083b018c0120022002290390013703700c010b200241c8006a2005410676109102200228024821040240024020022802502005413f7122014b0d00410021010c010b2002418c016a41026a200420014105746a220141026a2d00003a0000200241f8006a2001410f6a29000037030020024180016a200141176a29000037030020024188016a2001411f6a2d00003a0000200220012f00003b018c012002200129000737037020012800032105410121010b0240200228024c450d002004102c0b20010d00410121010c010b200241ec006a41026a2002418c016a41026a2d00003a000020024190016a41086a200241f0006a41086a29030037030020024190016a41106a200241f0006a41106a29030037030020024190016a41186a200241f0006a41186a2d00003a0000200220022f018c013b016c2002200229037037039001410021010b200241e8006a41026a2204200241ec006a41026a2d00003a0000200241c8006a41086a220720024190016a41086a290300370300200241c8006a41106a220820024190016a41106a290300370300200241c8006a41186a220920024190016a41186a2d00003a0000200220022f016c3b016820022002290390013703480240024020010d002002418c016a41026a20042d00003a0000200241f0006a41086a2007290300370300200241f0006a41106a2008290300370300200241f0006a41186a20092d00003a0000200220022f01683b018c0120022002290348370370410121010c010b200641013a0000410021010b200241246a41026a22042002418c016a41026a2d00003a0000200241086a41086a2207200241f0006a41086a290300370300200241086a41106a2208200241f0006a41106a290300370300200241086a41186a2209200241f0006a41186a2d00003a0000200220022f018c013b0124200220022903703703082001450d00200020022f01243b0001200041046a2005360000200041086a2002290308370000200041036a20042d00003a0000200041106a2007290300370000200041186a2008290300370000200041206a20092d00003a0000410121030b200020033a0000200241b0016a24000bc30405057f017e017f017e067f230041f0016b22022400024002402000280200220320002802044f0d00200028020c2104200141086a210520024190016a4102722106024003402000200341016a36020020024190016a2000280208280200220310af0120022d0090014101460d012002290091012107200241086a2003107720022802082208450d01200229020c210920022007370300024002402001280200220a41d0e1c100460d002001280204210b0c010b2006410041da0010da051a200241086a410041840110da051a41e401102a220a450d044100210b200a4100360200200a41046a20024190016a41dc0010db051a200a41e0006a200241086a41840110db051a200141003602042001200a3602000b024002400340200a41086a210c200a2f0106220d41037421034100210e024003402003450d012002200c410810dd05220f450d03200341786a2103200e41016a210e200c41086a210c200f417f4a0d000b200e417f6a210d0b0240200b450d00200b417f6a210b200a200d4102746a41e4016a280200210a0c010b0b2002200737021c200220053602182002200d360214200220013602102002200a36020c2002410036020820022009370294012002200836029001200241086a20024190016a10aa020c010b200a200e410c6c6a220341e4006a220c280200210e200c2009370200200341e0006a220c2802002103200c20083602002003450d00200e450d002003102c0b200028020022032000280204490d000c020b0b200441013a00000b200241f0016a24000f0b1033000bcc1207027f017e057f027e017f017e0a7f230041b0036b2202240020002802102203200328020041016a36020020002902142104200028020c2103200028020821052000280200210620002802042100200241f0016a41086a2207200141086a280200360200200220012902003703f001024002400240024020002f01062201410b490d00200241d0026a410272410041da0010da051a200241386a410041840110da051a41e401102a2208450d0320084100360200200841046a200241d0026a41dc0010db051a200841e0006a200241386a41840110db052107200241386a41086a2209200041b0016a280200360200200220002902a8013703382000413c6a330000210a2000413e6a310000210b20002d003f210c2000350038210d200841086a200041c0006a20002f010641796a220141037410db05210e2007200041b4016a2001410c6c10db052107200041063b0106200820013b0106200241d0026a41086a2009280200360200200220022903383703d002200d200a200b4210868442208684210a0240024020034107490d002003410374200e6a41506a200e200341796a22094103746a220e200141ffff037120096b41037410dc051a200e20043700002003410c6c20076a220341b87f6a200341ac7f6a2203200841066a22012f010020096b410c6c10dc051a200341086a200241f0016a41086a280200360200200320022903f0013702000c010b200041086a20034103746a220741086a2007200041066a22012f010020036b41037410dc051a20072004370000200041e0006a2003410c6c6a2207410c6a200720012f010020036b410c6c10dc051a200741086a200241f0016a41086a280200360200200720022903f0013702000b200120012f010041016a3b0100200241286a41086a220f200241d0026a41086a22102802002203360200200241086a221120033602002002200c3a0017200220022903d00222043703282002200a3e02102002200a4230883c00162002200a4220883d011420022004370300200229031021042000280200220c450d0120002f01042112200241d0026a410272211303402002200641016a22063602202002200c360224200f201128020036020020022002290300370328201241ffff03712109024002400240200c2f01062200410b490d002013410041da0010da051a200241f0016a200241d0026a41dc0010db051a200241386a410041b40110da051a419402102a2207450d0720074100360200200741046a200241f0016a41dc0010db051a200741e0006a200241386a41b40110db052103200c41386a290000210a200241386a41086a2214200c41b0016a2802003602002002200c41a8016a290200370338200741086a200c41c0006a200c2f0106220141796a220041037410db0521152003200c41b4016a2000410c6c10db052116200741e4016a200c4180026a2001417a6a220e41027410db052117200c41063b0106200720003b01060240200e450d00410021002017210303402003280200220120003b010420012007360200200341046a2103200e200041016a2200470d000b0b20102014280200220036020020022002290338220b3703d002201420003602002002200b370338201241ffff037122034107490d0120152009417a6a22034103746a2015200941796a22004103746a220120072f010620006b41037410dc051a200120043700002009410c6c20166a220141b87f6a200141ac7f6a220120072f0106220e20006b410c6c10dc051a200141086a200f280200360200200120022903283702002007200e41016a22013b01062009410274221220176a416c6a201720034102746a220e200141ffff0371220920036b41027410dc051a200e200836020020092003490d02200720126a41cc016a2103034020032802002201200041016a22003b010420012007360200200341046a210320002009490d000c030b0b200c41086a2201200941016a22034103746a200120094103746a2201200020096b220741037410dc051a20012004370000200c2009410c6c6a220141ec006a200141e0006a220e2007410c6c10dc051a200141e8006a200241286a41086a280200360200200e2002290328370200200c200041016a22003b01062009410274200c41e4016a22016a41086a200120034102746a2201200041ffff0371220720036b41027410dc051a20012008360200201241ffff037120074f0d05200c2003417f6a22004102746a41e8016a2103034020032802002201200041016a22003b01042001200c360200200341046a210320002007490d000c060b0b200c41086a2200200941016a220e4103746a200020094103746a2200200c2f0106220120096b221241037410dc051a20002004370000200c41e0006a2009410c6c6a2200410c6a20002012410c6c10dc051a200041086a200f28020036020020002002290328370200200c200141016a22003b010620094102742217200c41e4016a22016a41086a2001200e4102746a2212200041ffff03712201200e6b41027410dc051a20122008360200200320014f0d00200c20176a41e8016a2100034020002802002203200941016a22093b01042003200c360200200041046a210020012009470d000b0b200241106a41086a2014280200220036020020112000360200200220022903382204370310200220043703000240200c28020022000d0020072108200a21040c030b200c2f010421122000210c200a2104200721080c000b0b200020034103746a220941106a200941086a2209200120036b41037410dc051a2009200437000020002003410c6c6a220141ec006a200141e0006a220920002f010620036b410c6c10dc051a200141e8006a2007280200360200200920022903f001370200200020002f010641016a3b01060c010b200241d0026a410272410041da0010da051a200241f0016a200241d0026a41dc0010db051a200241386a410041b40110da051a419402102a2200450d0120004100360200200041046a200241f0016a41dc0010db051a200041e0006a200241386a41b40110db0521012000200528020022033602e401200520003602002005200528020441016a360204200341003b010420032000360200200120002f01062203410c6c6a22012002290300370200200020034103746a41086a2004370000200141086a200241086a280200360200200041e4016a200341016a22034102746a2008360200200020033b0106200820033b0104200820003602000b200241b0036a24000f0b1033000b0900200042043702000bf10602027f067e230041d0016b220624000240200341ff0171450d00200641d0006a2001ad42004280c8afa025420010e005200641c0006a2002418094ebdc032002418094ebdc03491bad420042e807420010e00520064190016a41186a420037030020064190016a41106a2207420037030020064190016a41086a220342003703002006420037039001200641c0016a41086a2202418be9c500ad42808080808001841002220141086a290000370300200620012900003703c0012001102c20032002290300370300200620062903c0013703900120024193e9c500ad42808080809002841002220141086a290000370300200620012900003703c0012001102c200720062903c0012208370300200641f0006a41086a2003290300370300200641f0006a41106a2008370300200641f0006a41186a2002290300370300200620083703b0012006200629039001370370200641d0006a41086a290300200641c0006a41086a2903007c2006290350220820062903407c2209200854ad7c20094280a094a58d1d7c2208200954ad7c2109200641e0006a200641f0006a1098010240024020062802600d00410021024200210a0c010b2006290368220b200b423f87220a7c200a85210a200b42005521020b200641206a20082009428094ebdc03420010e105200641106a2006290320220b200641206a41086a290300220c4280ec94a37c427f10e005200641306a20082009200a428094ebdc0380220d420010e0052006200a200d4280ec94a37c7e7ca72203360290012006418094ebdc03360294012006200b200c20064190016a2003418094ebdc034b4102746a350200220a420010e005427f427f2009200641306a41086a290300200641086a2903007c2006290330220c20062903007c220b200c54ad7c200b200a200820062903107c7e220a200a428094ebdc0380220a4280ec94a37c7e7c4280cab5ee0156200aa76aad7c220a200b54ad7c220c7c2008200a7c220d2008542203ad7c220b2003200b200954200b2009511b22031b42002009200c7d2008200a54ad7d220b2008200a7d220a200856200b200956200b2009511b22011b20021b220820057c427f200d20031b4200200a20011b20021b220920047c22042009542202ad7c22092002200920085420092008511b22021b2105427f200420021b21040b2000200437030020002005370308200641d0016a24000bb9280a017f047e067f027e047f017e017f017e0b7f027e230041e0046b2201240002400240024020004180e101700d00200141a0036a10ae0220014190016a200141a0036a10b7012001420020014190016a41086a29030022022001290390012203428080e983b1de1654ad7d2204200342808097fccea1697c22052003562004200256200342ffffe883b1de16561b22061b22033703a80120014200200520061b22023703a001200141a0036a41186a22072003370300200141a0036a41106a22082002370300200141a0036a41086a220941013a00002001410c3a00a0034100210a41014100200141a0036a109201200141003a00b701200142003703c001200142003703b801200742003703002008420037030020094200370300200142003703a003200141c8016a41086a220b41a4e9c500ad4280808080800184220c1002220641086a290000370300200120062900003703c8012006102c2009200b290300370300200120012903c80122033703c002200120033703a003200b41b9e9c500ad4280808080900184220d1002220641086a290000370300200120062900003703c8012006102c200820012903c8012203370300200141d8016a41086a220e2009290300370300200141d8016a41106a220f2003370300200141d8016a41186a2210200b290300370300200120033703c002200120012903a0033703d801200141a0036a200141d8016a10960120012802a0032206410420061b2111024020012902a403420020061b2212422088a72213450d00200141c8016aad4280808080c000842114200141a9036a2115200141c0026a41c0006a2116200141e0026a2117410021184100210a41002106024003400240024002400240200a450d00201120064102746a21192011200620186a4102746a211a0340200620134f0d02200141d8016a2019280200221b10af0220012903d8014201520d04200141c0026a200e41e00010db051a20012903a001220420012903c002220554200141a0016a41086a2903002203200141c0026a41086a29030022025420032002511b450d03200141013a00b7010240201820066a221b20134f0d00201a2019280200360200201941046a2119201a41046a211a200641016a22062013490d010c070b0b41fcb4c000201b20131038000b201120064102746a21190340200620134f0d01200141d8016a2019280200221b10af0220012903d8014201520d03200141c0026a200e41e00010db051a20012903a001220420012903c00222055a200141a0016a41086a2903002203200141c0026a41086a29030022025a20032002511b0d02201941046a2119200141013a00b701200641016a22062013490d000b4100210a0c050b41a8b4c000200620131038000b2001200420057d3703a0012001200320027d2004200554ad7d3703a801200b200c1002221941086a290000370300200120192900003703c8012019102c200141a0046a41086a221a200b290300370300200120012903c8013703a004200b41e1e5c200ad42808080809001841002221941086a290000370300200120192900003703c8012019102c200141b0046a41086a221c200b290300370300200120012903c8013703b0042001201b3602c801200720141006221941186a2900003703002008201941106a2900003703002009201941086a290000370300200120192900003703a0032019102c200141c0046a41186a221d2007290300370300200141c0046a41106a221e2008290300370300200141c0046a41086a221f2009290300370300200120012903a0033703c00441c000102a2219450d06201920012903a004370000201941086a201a290300370000201920012903b004370010201941186a201c290300370000201920012903c004370020201941286a201f290300370000201941306a201e290300370000201941386a201d2903003700002019ad428080808080088410052019102c201720012903d002200141c0026a41186a29030010c20120014180016a201620012903c002200141c0026a41086a2219290300109d01200141b8016a41086a221a427f201a290300220320014180016a41086a2903007c20012903b80122022001290380017c2204200254221aad7c2202201a200220035420022003511b221a1b3703002001427f2004201a1b3703b80120012903c0022103200141a0036a41386a201929030037030020152016290000370000201541086a201641086a290000370000201541106a201641106a290000370000201541186a201641186a290000370000200120033703d003200141023a00a8032001410c3a00a0032001201b3602cc0341014100200141a0036a1092010b2018417f6a2118200a41016a210a200641016a22062013490d000b0b200a450d00200620134f0d00201120064102746a2219200a4102746b2019201320066b41027410dc051a0b200742003703002008420037030020094200370300200142003703a003200b200c1002220641086a290000370300200120062900003703c8012006102c2009200b290300370300200120012903c80122033703c002200120033703a003200b200d1002220641086a290000370300200120062900003703c8012006102c200141c0026a41086a200b2903002203370300200120012903c80122023703c00220082002370000200841086a2003370000200e2009290300370300200f200829030037030020102007290300370300200120012903a0033703d8010240024020110d00200141d8016aad428080808080048410050c010b200141003602a803200142013703a0032013200a6b2206200141a0036a10670240024020060d0020012802a803211320012802a403210e20012802a00321190c010b201120064102746a210b20012802a403210e20012802a80321062011211a0340201a280200211b02400240200e20066b4104490d00200641046a211320012802a00321190c010b200641046a22132006490d05200e41017422192013201920134b1b22184100480d0502400240200e0d002018102a21190c010b20012802a003200e2018102e21190b2019450d06200120183602a403200120193602a0032018210e0b200120133602a803201920066a201b36000020132106200b201a41046a221a470d000b0b2012a72106200141d8016aad42808080808004842013ad4220862019ad8410010240200e450d002019102c0b2006450d002011102c0b024020012d00b7010d00200141d8006a20012903a0012203200141a0016a41086a2206290300220242c0843d420010e105200141c8006a20012903582204200141d8006a41086a290300220542c0fb42427f10e005200141386a2004200542a0c21e420010e005200620022002200141386a41086a29030020012903382204200320012903487c220542a0c21e7e2005420188220542c0fb427e7c42a0c21e562005a76aad7c2205200454ad7c22042005200356200420025620042002511b22131b22047d20032003200520131b220254ad7d3703002001200320027d3703a001200141a0036a41186a22194200370300200141a0036a41106a221a4200370300200141a0036a41086a22134200370300200142003703a003200141c8016a41086a2206418be9c500ad428080808080018422051002220e41086a2900003703002001200e2900003703c801200e102c20132006290300370300200120012903c80122033703c004200120033703a003200641c9b5c000ad4280808080d00184220c1002220e41086a2900003703002001200e2900003703c801200e102c201a20012903c8012203370300200141d8016a41086a22182013290300370300200141d8016a41106a220b2003370300200141d8016a41186a22082006290300370300200120033703c004200120012903a0033703d801200141e8006a200141d8016a4120109e01200141e8006a41106a29030021032001290370210d2001280268210e20194200370300201a420037030020134200370300200142003703a003200620051002221b41086a2900003703002001201b2900003703c801201b102c20132006290300370300200120012903c80122053703c004200120053703a0032006200c1002221b41086a2900003703002001201b2900003703c801201b102c20192006290300220537030020182013290300370300200b20012903c801220c370300200820053703002001200c3703c004200120012903a0033703d8012001420020034200200e1b220320047d200d4200200e1b2205200254ad7d220c200520027d220d200556200c200356200c2003511b22061b3703a80320014200200d20061b3703a003200141d8016aad4280808080800484200141a0036aad42808080808002841001200141b8016a41086a220e427f200e290300220c2003200420061b7c20012903b80122032005200220061b7c22052003542206ad7c220320062003200c542003200c511b22061b3703002001427f200520061b3703b80120192004370300201a2002370300201341033a00002001410c3a00a00341014100200141a0036a1092010b200141c0026a10ae02200141d8016a200141c0026a20012903b8012203200141b8016a41086a2903002202410210ac010240024020012802d8010d00200141d8016a41106a290300210520012903e0012104200141a0036a41186a22194200370300200141a0036a41106a22064200370300200141a0036a41086a221a4200370300200142003703a003200141c8016a41086a2213418be9c500ad428080808080018422141002220e41086a2900003703002001200e2900003703c801200e102c201a2013290300370300200120012903c801220c3703a0042001200c3703a003201341c9b5c000ad4280808080d0018422201002220e41086a2900003703002001200e2900003703c801200e102c200620012903c801220c370300200141c0046a41086a201a290300370300200141c0046a41106a221a200c370300200141c0046a41186a220e20132903003703002001200c3703b004200120012903a0033703c004200141086a200141c0046a4120109e01200220057d2003200454ad7d200520027d2004200354ad7d20042003582005200258200520025122131b221b1b2121200320047d200420037d201b1b2112200141086a41106a29030042002001280208221b1b210c20012903104200201b1b210d024002402004200356200520025620131b0d002019420037030020064200370300200141a0036a41086a221b4200370300200142003703a003200141c8016a41086a221320141002221841086a290000370300200120182900003703c8012018102c201b2013290300370300200120012903c80122033703a004200120033703a003201320201002221841086a290000370300200120182900003703c8012018102c200141b0046a41086a20132903002203370300200120012903c80122023703b00420062002370000200641086a2003370000200141c0046a41086a201b290300370300201a2006290300370300200e2019290300370300200120012903a0033703c0042001427f200c20217c200d20127c2202200d542206ad7c220320062003200c542003200c511b22061b3703a8032001427f200220061b3703a003200141a0036a21060c010b2019420037030020064200370300200141a0036a41086a221b4200370300200142003703a003200141c8016a41086a221320141002221841086a290000370300200120182900003703c8012018102c201b2013290300370300200120012903c80122033703a004200120033703a003201320201002221841086a290000370300200120182900003703c8012018102c200141b0046a41086a20132903002203370300200120012903c80122023703b00420062002370000200641086a2003370000200141c0046a41086a201b290300370300201a2006290300370300200e2019290300370300200120012903a0033703c00420014200200c20217d200d201254ad7d2203200d20127d2202200d562003200c562003200c511b22061b3703a80320014200200220061b3703a003200141a0036a21060b200141c0046aad42808080808004842006ad428080808080028410010c010b41c9c5c100ad4280808080a009841004200141a0036a41186a22194200370300200141a0036a41106a221a4200370300200141a0036a41086a22134200370300200142003703a003200141c8016a41086a2206418be9c500ad428080808080018422051002220e41086a2900003703002001200e2900003703c801200e102c20132006290300370300200120012903c80122043703c004200120043703a003200641c9b5c000ad4280808080d00184220c1002220e41086a2900003703002001200e2900003703c801200e102c201a20012903c8012204370300200141d8016a41086a221b2013290300370300200141d8016a41106a22182004370300200141d8016a41186a220b2006290300370300200120043703c004200120012903a0033703d801200141206a200141d8016a4120109e01200141206a41106a29030021042001290328210d2001280220210e20194200370300201a420037030020134200370300200142003703a003200620051002221a41086a2900003703002001201a2900003703c801201a102c20132006290300370300200120012903c80122053703c004200120053703a0032006200c1002221a41086a2900003703002001201a2900003703c801201a102c201920062903002205370300201b2013290300370300201820012903c801220c370300200b20053703002001200c3703c004200120012903a0033703d8012001427f20044200200e1b220420027c200d4200200e1b220220037c22052002542206ad7c22032006200320045420032004511b22061b3703a8032001427f200520061b3703a003200141d8016aad4280808080800484200141a0036aad428080808080028410010b20012903a0012103200141b8036a200141a0016a41086a290300370300200141b0036a2003370300200141a0036a41086a41043a00002001410c3a00a00341014100200141a0036a1092010b2000108c01200141e0046a24000f0b1035000b1033000be70301067f230041d0006b22012400200141ed003a0008024002404101102a2202450d00200241ed003a0000200141ef003a0008200241014102102e2202450d00200241ef003a0001200141e4003a0008200241024104102e2202450d00200241e4003a0002200241ec003a0003200141f0003a0008200241044108102e2202450d00200241f0003a0004200241f9003a00052002412f3a0006200241f4003a0007200141f2003a0008200241084110102e2203450d00200341f2003a0008200341f3003a0009200341f2003a000a200341f9003a000b200141003a0048410c210220032104410021050340200141003a0008200141086a20042002410047220610db051a024020020d00200141003a00080b20022006490d02200141286a20056a20012d00083a00002001200541016a22053a0048200220066b2102200420066a210420054120470d000b200141086a41186a2202200141286a41186a290300370300200141086a41106a2205200141286a41106a290300370300200141086a41086a2206200141286a41086a290300370300200120012903283703082003102c200041186a2002290300370000200041106a2005290300370000200041086a200629030037000020002001290308370000200141d0006a24000f0b1033000b200620021047000b8d0402077f017e230041f0016b22022400200241086a220341a4e9c500ad42808080808001841002220441086a290000370300200220042900003703002004102c200241e8006a41086a2205200329030037030020022002290300370368200341e1e5c200ad42808080809001841002220441086a290000370300200220042900003703002004102c200241f8006a41086a2206200329030037030020022002290300370378200220013602ec01200241186a2201200241ec016aad4280808080c000841006220441186a290000370300200241106a2207200441106a2900003703002003200441086a290000370300200220042900003703002004102c20024188016a41186a2208200129030037030020024188016a41106a2201200729030037030020024188016a41086a220720032903003703002002200229030037038801024041c000102a2204450d0020042002290368370000200420022903783700102004200229038801370020200441086a2005290300370000200441186a2006290300370000200441286a2007290300370000200441306a2001290300370000200441386a20082903003700002002200441c00010b8022002290300210920024188016a200341e00010db051a0240024020094201510d00200042003703000c010b20004201370300200041086a20024188016a41e00010db051a0b2004102c200241f0016a24000f0b1033000b961b05067f017e047f017e277f230041c00d6b22032400200341106a41186a22044200370300200341106a41106a22054200370300200341106a41086a2206420037030020034200370310200341f00c6a41086a22074191b0c200ad4280808080e000841002220841086a290000370300200320082900003703f00c2008102c20062007290300370300200320032903f00c370310200741acb0c200ad4280808080e000841002220841086a290000370300200320082900003703f00c2008102c200520032903f00c2209370300200341a00d6a41086a220a2006290300370300200341a00d6a41106a220b2009370300200341a00d6a41186a220c2007290300370300200320093703900d200320032903103703a00d200341086a200341a00d6a4120109401200328020c21082003280208210d20044200370300200542003703002006420037030020034200370310200741c586c200ad42808080808003841002220541086a290000370300200320052900003703f00c2005102c20062007290300370300200320032903f00c37031020074193c6c100ad4280808080e001841002220541086a290000370300200320052900003703f00c2005102c200420072903002209370300200a2006290300370300200b20032903f00c220e370300200c20093703002003200e3703900d200320032903103703a00d200341106a200341a00d6a412010d00120032802102206410120061b210f024002402003290214420020061b2209422088a722040d0020004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b200341106a410041e00c10da051a2008417f6a41d100704130200d1b2106200241056a2110200f41206a2111200f20044105746a2112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f410021204100212141002122410021234100212441002125410021264100212741002128410021294100212a4100212b4100212c4100212d4100212e4100212f410021304100213141002132200f21084100213341d10021340240034020332105024002402006450d000240200f450d00200641016a2106034020112008220441206a22352004201246220d1b21082006417f6a22060d000b20112035200d1b2108200f2004200d1b220d0d020c040b200641016a2106034020122008460d04200841206a21082006417f6a22060d000b200841606a220d0d010c030b024020082012470d0020112108200f220d0d010c030b2008210d200841206a21080b02400240024002402010417f4c0d00024002402010450d002010102a2206450d0341002104200341003602a80d200320103602a40d200320063602a00d0c010b200341003602a80d200320103602a40d200341013602a00d4101102a2206450d02200341013602a40d200320063602a00d20032802a80d21040b2003200441016a3602a80d200620046a20053a00002002200341a00d6a10670240024020032802a40d220420032802a80d22066b2002490d0020032802a00d21040c010b200620026a22352006490d03200441017422062035200620354b1b22064100480d030240024020040d002006102a21040c010b20032802a00d20042006102e21040b2004450d02200320063602a40d200320043602a00d20032802a80d21060b2003200620026a3602a80d200420066a2001200210db051a2003200341a00d6a3602900d200d200341900d6a10940220032802a40d2104200c20033502a80d42208620032802a00d2233ad841006220641186a290000370300200b200641106a290000370300200a200641086a290000370300200320062900003703a00d2006102c200341f00c6a41186a220d200c290300370300200341f00c6a41106a2235200b2903003703002007200a290300370300200320032903a00d3703f00c02402004450d002033102c0b2034417f6a2134200541016a2133200341106a20054103704105746a220620032903f00c370000200641186a200d290300370000200641106a2035290300370000200641086a20072903003700004100210403402005200541036e220d417d6c6a4102470d04200341106a20046a220641df006a2d000022132006411f6a2d000022147120132014722006413f6a2d000071722132200641de006a2d000022132006411e6a2d000022147120132014722006413e6a2d000071722131200641dd006a2d000022132006411d6a2d000022147120132014722006413d6a2d000071722130200641dc006a2d000022132006411c6a2d000022147120132014722006413c6a2d00007172212f200641db006a2d000022132006411b6a2d000022147120132014722006413b6a2d00007172212e200641da006a2d000022132006411a6a2d000022147120132014722006413a6a2d00007172212d200641d9006a2d00002213200641196a2d00002214712013201472200641396a2d00007172212c200641d8006a2d00002213200641186a2d00002214712013201472200641386a2d00007172212b200641d7006a2d00002213200641176a2d00002214712013201472200641376a2d00007172212a200641d6006a2d00002213200641166a2d00002214712013201472200641366a2d000071722129200641d5006a2d00002213200641156a2d00002214712013201472200641356a2d000071722128200641d4006a2d00002213200641146a2d00002214712013201472200641346a2d000071722127200641d3006a2d00002213200641136a2d00002214712013201472200641336a2d000071722126200641d2006a2d00002213200641126a2d00002214712013201472200641326a2d000071722125200641d1006a2d00002213200641116a2d00002214712013201472200641316a2d000071722124200641d0006a2d00002213200641106a2d00002214712013201472200641306a2d000071722123200641cf006a2d000022132006410f6a2d000022147120132014722006412f6a2d000071722122200641ce006a2d000022132006410e6a2d000022147120132014722006412e6a2d000071722121200641cd006a2d000022132006410d6a2d000022147120132014722006412d6a2d000071722120200641cc006a2d000022132006410c6a2d000022147120132014722006412c6a2d00007172211f200641cb006a2d000022132006410b6a2d000022147120132014722006412b6a2d00007172211e200641ca006a2d000022132006410a6a2d000022147120132014722006412a6a2d00007172211d200641c9006a2d00002213200641096a2d00002214712013201472200641296a2d00007172211c200641c8006a2d00002213200641086a2d00002214712013201472200641286a2d00007172211b200641c7006a2d00002213200641076a2d00002214712013201472200641276a2d00007172211a200641c6006a2d00002213200641066a2d00002214712013201472200641266a2d000071722119200641c5006a2d00002213200641056a2d00002214712013201472200641256a2d000071722118200641c4006a2d00002213200641046a2d00002214712013201472200641246a2d000071722117200641c3006a2d00002213200641036a2d00002214712013201472200641236a2d000071722116200641c2006a2d00002213200641026a2d00002214712013201472200641226a2d000071722115200641c1006a2d00002213200641016a2d00002214712013201472200641216a2d000071722114200641c0006a2d0000221320062d00002235712013203572200641206a2d000071722113200441800c460d04200341106a2004200d410574200541096e41e0006c6b6a6a220641ff006a20323a0000200641fe006a20313a0000200641fd006a20303a0000200641fc006a202f3a0000200641fb006a202e3a0000200641fa006a202d3a0000200641f9006a202c3a0000200641f8006a202b3a0000200641f7006a202a3a0000200641f6006a20293a0000200641f5006a20283a0000200641f4006a20273a0000200641f3006a20263a0000200641f2006a20253a0000200641f1006a20243a0000200641f0006a20233a0000200641ef006a20223a0000200641ee006a20213a0000200641ed006a20203a0000200641ec006a201f3a0000200641eb006a201e3a0000200641ea006a201d3a0000200641e9006a201c3a0000200641e8006a201b3a0000200641e7006a201a3a0000200641e6006a20193a0000200641e5006a20183a0000200641e4006a20173a0000200641e3006a20163a0000200641e2006a20153a0000200641e1006a20143a0000200641e0006a20133a0000200d2105200441e0006a220441e00c470d000c040b0b103a000b1033000b1035000b4100210620340d000b0b200020323a001f200020313a001e200020303a001d2000202f3a001c2000202e3a001b2000202d3a001a2000202c3a00192000202b3a00182000202a3a0017200020293a0016200020283a0015200020273a0014200020263a0013200020253a0012200020243a0011200020233a0010200020223a000f200020213a000e200020203a000d2000201f3a000c2000201e3a000b2000201d3a000a2000201c3a00092000201b3a00082000201a3a0007200020193a0006200020183a0005200020173a0004200020163a0003200020153a0002200020143a0001200020133a00000b02402009a7450d00200f102c0b200341c00d6a24000bf40508017f017e047f017e017f017e037f017e230041f0016b22022400200241186a2000200110ce01200241186a41106a2903002101200229032021000240024020022903182203a7450d00200241e0006a10ae02200241e0006a20002001109c01200241f8006a2001370300200241e0006a41106a2000370300200241e8006a41053a00002002410c3a006041014100200241e0006a1092010c010b2003500d00200241e0006a41186a22044200370300200241e0006a41106a22054200370300200241e0006a41086a2206420037030020024200370360200241e0016a41086a2207418be9c500ad428080808080018422081002220941086a290000370300200220092900003703e0012009102c20062007290300370300200220022903e001220337035020022003370360200741c9b5c000ad4280808080d00184220a1002220941086a290000370300200220092900003703e0012009102c200520022903e0012203370300200241306a41086a220b2006290300370300200241306a41106a220c2003370300200241306a41186a220d200729030037030020022003370350200220022903603703302002200241306a4120109e01200241106a29030021032002290308210e2002280200210920044200370300200542003703002006420037030020024200370360200720081002220541086a290000370300200220052900003703e0012005102c20062007290300370300200220022903e0012208370350200220083703602007200a1002220541086a290000370300200220052900003703e0012005102c200420072903002208370300200b2006290300370300200c20022903e001220a370300200d20083703002002200a37035020022002290360370330200242002003420020091b220320017d200e420020091b2201200054ad7d2208200120007d2200200156200820035620082003511b22071b37036820024200200020071b370360200241306aad4280808080800484200241e0006aad428080808080028410010b200241f0016a24000b130020004103360204200041b4c6c1003602000b3400200041a4e9c50036020420004100360200200041146a4103360200200041106a419ccdc100360200200041086a42083702000b1300200041043602042000419cd1c1003602000b2e01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241a0c21e3600000b2e01017f02404104102a22020d001033000b20004284808080c0003702042000200236020020024180e1013600000b2e01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241d086033600000be90804067f027e077f027e230041e0016b220324002003200236020420032001360200200341086a2002ad4220862001ad841003108d0102400240200328020822040d00200042003703000c010b200341106a2802002105200328020c210641002101200341003a00d801200541706a2107024002400340024020052001470d00200141ff0171450d02200341003a00d8010c020b200341b8016a20016a200420016a2d00003a00002003200141016a22023a00d8012007417f6a21072002210120024120470d000b200341d8006a41086a200341b8016a41086a290300370300200341d8006a41106a200341b8016a41106a290300370300200341d8006a41186a200341b8016a41186a290300370300200320032903b801370358200520026b22084110490d00200420026a22052900002109200541086a290000210a41002101200341003a00d801200841706a21080340024020082001470d00200141ff0171450d02200341003a00d8010c020b200341b8016a20016a200520016a41106a2d00003a00002003200141016a22023a00d8012002210120024120470d000b200341f8006a41086a220b200341b8016a41086a2201290300370300200341f8006a41106a220c200341b8016a41106a2208290300370300200341f8006a41186a220d200341b8016a41186a220e290300370300200320032903b801370378200720026b410f4d0d00200341386a41086a2207200341d8006a41086a290300370300200341386a41106a220f200341d8006a41106a290300370300200341386a41186a2210200341d8006a41186a290300370300200341186a41086a2211200b290300370300200341186a41106a220b200c290300370300200341186a41186a220c200d2903003703002003200329035837033820032003290378370318200520026a220241106a2900002112200241186a2900002113200120072903003703002008200f290300370300200e201029030037030020034198016a41086a2202201129030037030020034198016a41106a2207200b29030037030020034198016a41186a2205200c290300370300200320032903383703b8012003200329031837039801200041206a2013370300200041186a2012370300200041106a200a37030020002009370308200041286a20032903b801370300200041306a2001290300370300200041386a2008290300370300200041c0006a200e290300370300200041c8006a200329039801370300200041d0006a2002290300370300200041d8006a2007290300370300200041e0006a2005290300370300420121090c010b200341003602a00120034201370398012003410b36027c20032003360278200320034198016a360258200341cc016a4101360200200342013702bc01200341d0b0c2003602b8012003200341f8006a3602c801200341d8006a41c49ac500200341b8016a10391a20033502a0014220862003350298018410040240200328029c01450d00200328029801102c0b420021090b200020093703002006450d002004102c0b200341e0016a24000bc70904067f017e047f017e230041b0016b22072400200741206a200242002003200410e005200741f0006a41186a22084200370300200741f0006a41106a22094200370300200741f0006a41086a220a420037030020074200370370200741a0016a41086a220b41e4d2c500ad428080808080018422041002220c41086a2900003703002007200c2900003703a001200c102c200a200b290300370300200720072903a00122033703900120072003370370200b41ecd2c500ad4280808080800184220d1002220c41086a2900003703002007200c2900003703a001200c102c200920072903a0012203370300200741d0006a41086a220c200a290300370300200741d0006a41106a220e2003370300200741d0006a41186a220f200b290300370300200720033703900120072007290370370350200741c0006a200741d0006a10980120072903482103200728024021102008420037030020094200370300200a420037030020074200370370200b20041002221141086a290000370300200720112900003703a0012011102c200a200b290300370300200720072903a00122043703900120072004370370200b200d1002221141086a290000370300200720112900003703a0012011102c2008200b2903002204370300200c200a290300370300200e20072903a001220d370300200f20043703002007200d37039001200720072903703703502007200120027d2003420020101b7c370370200741d0006aad42808080808004842204200741f0006aad220d42808080808001841001200741306a20002007290320200741206a41086a290300109d012005200729033022027d200220057d2002200558200741306a41086a290300220320065820032006511b22111b2101200620037d2005200254ad7d200320067d2002200554ad7d20111b2105024002402011450d002001200510a9010c010b2008420037030020094200370300200a420037030020074200370370200b418be9c500ad428080808080018422021002221141086a290000370300200720112900003703a0012011102c200a200b290300370300200720072903a00122063703900120072006370370200b41c9b5c000ad4280808080d0018422031002221141086a290000370300200720112900003703a0012011102c200920072903a0012206370300200c200a290300370300200e2006370300200f200b290300370300200720063703900120072007290370370350200741086a200741d0006a4120109e01200741086a41106a290300210620072903102112200728020821112008420037030020094200370300200a420037030020074200370370200b20021002220941086a290000370300200720092900003703a0012009102c200a200b290300370300200720072903a00122023703900120072002370370200b20031002220941086a290000370300200720092900003703a0012009102c2008200b2903002202370300200c200a290300370300200e20072903a0012203370300200f20023703002007200337039001200720072903703703502007427f2006420020111b220620057c2012420020111b220520017c2202200554220bad7c2205200b200520065420052006511b220b1b3703782007427f2002200b1b3703702004200d428080808080028410010b200741b0016a24000bdb2601067f20002d000021020240024002400240200141046a2203280200200141086a22042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0001210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0002210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0003210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0004210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0005210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0006210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0007210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0008210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0009210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000a210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000b210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000c210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000d210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000e210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d000f210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0010210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0011210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0012210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0013210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0014210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0015210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0016210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0017210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0018210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d0019210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001a210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001b210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001c210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001d210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001e210202400240200328020020042802002205460d00200128020021060c010b200541016a22062005490d02200541017422072006200720064b1b22074100480d020240024020050d002007102a21060c010b200128020020052007102e21060b2006450d0120012006360200200141046a2007360200200141086a28020021050b2004200541016a360200200620056a20023a000020002d001f210502400240200328020020042802002200460d00200128020021030c010b200041016a22032000490d02200041017422062003200620034b1b22064100480d020240024020000d002006102a21030c010b200128020020002006102e21030b2003450d0120012003360200200141046a2006360200200141086a28020021000b2004200041016a360200200320006a20053a00000f0b1033000b1035000b34002000418be9c50036020420004100360200200041146a4101360200200041106a41f0d6c100360200200041086a42083702000b130020004102360204200041e4d7c1003602000b3400200041c586c20036020420004100360200200041146a4101360200200041106a41f4d8c100360200200041086a42183702000bb80303017f017e027f230041d0006b2203240002402001200210252204422088a72201450d002004a722022d0000220541014b0d002001417f6a210602400240024020050e020001000b41002101200341003a0049200241016a21050340024020062001470d00200141ff0171450d04200341003a00490c040b200341286a20016a200520016a2d00003a00002003200141016a22023a00492002210120024121470d000b200341106a200341316a290000370300200341186a200341396a290000370300200341206a200341c1006a2900003703002003200329002937030820032d00282101410021020c010b2006450d0120022d0001220141034f0d01200341086a41186a200341286a41186a290000370300200341086a41106a200341286a41106a290000370300200341086a41086a200341286a41086a29000037030020032003290028370308410121020b200020013a0001200020023a0000200041026a20032903083700002000410a6a200341106a290300370000200041126a200341186a2903003700002000411a6a200341206a290300370000200341d0006a24000f0b41d88bc600412e200341286a41888cc600103b000b130020004102360204200041f4e9c5003602000bf80303097f017e017f230041e0026b22022400200141086a2802002103200028020421042000280200210520012802042106024020002802082207200028020c2208460d0020012802002100200241086a41096a2109200241d0016a410472210a0240034020072802002101200241c4006a200741046a418c0110db051a20014118460d01200220013602d001200a200241c4006a418c0110db051a200241003b0118200241086a200241d0016a200241186a10c1022002290308210b20022d00102101200241d0016a41026a220c200941026a2d00003a0000200220092f00003b01d001024020014102460d00200241186a41026a200c2d00003a0000200220022f01d0013b01180b200041086a20013a00002000200b370200200041096a20022f01183b00002000410b6a200241186a41026a2d00003a00002000410c6a2100200341016a210320074190016a22072008470d000b200821070c010b20074190016a21070b20062003360200024020072008460d00200241d0016a4104722101034020072802002100200241d0016a200741046a418c0110db051a20004118460d01200241c4006a200241d0016a418c0110db051a200220003602d0012001200241c4006a418c0110db051a200241d0016a107320074190016a22072008470d000b0b02402004450d002005102c0b200241e0026a24000bc4880308017f017e067f027e057f017e197f067e230041c00a6b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e180102000304001b1a19181716150e0d0c0b0a090800000007010b000b200141106a29030021042001410c6a280200210520022d0001210620022d00002102024002400240024002400240024002400240200141086a2802002207417f6a0e0708000102030405080b2004a7210702400240200241ff01710d00200641ff01714101460d010b2007450d3b2005102c0c3b0b2007450d362005102c0c360b200220067241ff01710d384108102a2202450d212002200437000041dddac200ad4280808080a001842002ad428080808080018410012002102c0c350b2004a721070240200220067241ff0171450d0020070d040c380b41e7dac200ad4280808080d000842004428080808070832005ad8410012007450d342005102c0c340b2004422088a721082004a721090240200220067241ff0171450d0002402008450d00200841186c21062005210203400240200241046a280200450d002002280200102c0b0240200241106a280200450d002002410c6a280200102c0b200241186a2102200641686a22060d000b0b410121064100210a4103210820090d320c330b0240200841186c2202450d00200520026a2106200521020340200241086a350200422086200235020084200241146a3502004220862002410c6a350200841001200241186a22022006470d000b0b02402008450d00200841186c21062005210203400240200241046a280200450d002002280200102c0b0240200241106a280200450d002002410c6a280200102c0b200241186a2102200641686a22060d000b0b410121064100210a4105210820090d310c320b2004422088a721082004a721090240200220067241ff0171450d0002402008450d002008410c6c21062005210203400240200241046a280200450d002002280200102c0b2002410c6a2102200641746a22060d000b0b410021064101210a410321082009450d320c310b02402008410c6c2202450d00200520026a2106200521020340200241086a35020042208620023502008410052002410c6a22022006470d000b0b02402008450d002008410c6c21062005210203400240200241046a280200450d002002280200102c0b2002410c6a2102200641746a22060d000b0b410021064101210a4105210820090d300c310b2004a72107200220067241ff0171450d012007450d340b2005102c0c330b2004428080808070832005ad84100d2007450d2f2005102c0c2f0b200220067241ff01710d310c2e0b2001410c6a2802002106200141086a280200210820012802042107024020022d000120022d000072450d0002402006450d0020064190016c21062007210203402002107320024190016a2102200641f07e6a22060d000b0b02402008450d002007102c0b20004181023b010820004111360204200041b2b2c000360200410021052000410a6a41003a0000410121070c350b41002105200341003602a806200342043703a00620064190016c22024190016d210a0240024020020d00410421060c010b200aad420c7e2204422088a70d0d2004a722064100480d0d2006102a2206450d1a2003200a3602a406200320063602a0060b2003200720026a3602bc09200320073602b80920032008ad4220862007ad843703b009200341a8076a41086a41003602002003200341a0066a41086a3602ac07200320063602a807200341b0096a200341a8076a10c002200341b0086a41086a200341a0066a41086a2802002202360200200320032903a00622043703b008200341b3076a2002360000200320043700ab07200341b0096a41086a200341af076a29000037000041012107200341013a00b009200320032900a8073700b10941014100200341b0096a109201200041023a00080c340b024020022d00000d0020022d000141ff01714102470d00200141086a2903002104200341c0036a41186a22054200370300200341c0036a41106a22024200370300200341c0036a41086a22074200370300200342003703c00341f9e8c500ad4280808080900184220b1002220628000321082006290007210c20062d000f210a20062f00002109200641026a2d0000210d2006102c2003200d3a00c203200320093b01c0032003200a3a00cf032003200c3700c703200320083600c3034182e9c500ad4280808080900184100222062d000f21082006280003210a2006290007210c20062f00002109200641026a2d0000210d2006102c200341d2036a220e200d3a0000200220093b0100200341a0036a41086a220920072903003703002003200c3700d7032003200a3600d303200341a0036a41106a220a2002290300370300200320083a00df03200341a0036a41186a22082005290300370300200320032903c0033703a003200341206a200341a0036a412041014100410010970120032802204101460d03200542003703002002420037030020074200370300200342003703c003200b10022206280003210d2006290007210b20062d000f210f20062f00002110200641026a2d000021112006102c200320113a00c203200320103b01c0032003200f3a00cf032003200b3700c7032003200d3600c303419db1c200ad42808080803084220b100222062d000f210d2006280003210f2006290007210c20062f00002110200641026a2d000021112006102c200e20113a0000200220103b0100200920072903003703002003200c3700d7032003200f3600d303200a20022903003703002003200d3a00df0320082005290300370300200320032903c0033703a003200341106a200341a0036a10980102402003290318500d002003280210450d00200341c0036a41186a22054200370300200341c0036a41106a22064200370300200341c0036a41086a22074200370300200342003703c00341f9e8c500ad42808080809001841002220228000321082002290007210c20022d000f210a20022f00002109200241026a2d0000210d2002102c2003200d3a00c203200320093b01c0032003200a3a00cf032003200c3700c703200320083600c303419db1c200ad42808080803084100222022d000f21082002280003210a2002290007210c20022f00002109200241026a2d0000210d2002102c200341d2036a200d3a0000200620093b0100200341a0036a41086a20072903003703002003200c3700d7032003200a3600d303200341a0036a41106a2006290300370300200320083a00df03200341a0036a41186a2005290300370300200320032903c0033703a0032003200341a0036a109801200329030842dc0b7c42dc0b20032802001b2004560d030b200341c0036a41186a22054200370300200341c0036a41106a22024200370300200341c0036a41086a22074200370300200342003703c00341f9e8c500ad4280808080900184220c1002220628000321082006290007211220062d000f210a20062f00002109200641026a2d0000210d2006102c2003200d3a00c203200320093b01c0032003200a3a00cf03200320123700c703200320083600c303200b100222062d000f21082006280003210a2006290007210b20062f00002109200641026a2d0000210d2006102c200341d2036a220e200d3a0000200220093b0100200341a0036a41086a220920072903003703002003200b3700d7032003200a3600d303200341a0036a41106a220a2002290300370300200320083a00df03200341a0036a41186a22082005290300370300200320032903c0033703a003200320043703b009200341a0036aad42808080808004842204200341b0096aad220b42808080808001841001200542003703002002420037030020074200370300200342003703c003200c10022206280003210d2006290007210c20062d000f210f20062f00002110200641026a2d000021112006102c200320113a00c203200320103b01c0032003200f3a00cf032003200c3700c7032003200d3600c3034182e9c500ad4280808080900184100222062d000f210d2006280003210f2006290007210c20062f00002110200641026a2d000021112006102c200e20113a0000200220103b0100200920072903003703002003200c3700d7032003200f3600d303200a20022903003703002003200d3a00df0320082005290300370300200320032903c0033703a00341012107200341013a00b0092004200b428080808010841001200041023a0008410121050c340b20004181063b01082000410f360204200041d6b2c0003602002000410a6a41003a00000c210b2001410c6a2802002106200141086a280200210f2001280204210a41d6b2c0002109410f210d20022d00000d2420022d000141ff01714102470d2402402006410b490d00410f210d41e4ecc10021090c260b41a4c6c500ad4280808080a00184220b1002220228000321052002290007210420022d000f210720022f00002108200241026a2d000021092002102c41aec6c500ad4280808080c00184221210022202280003210d2002290007210c20022d000f210e20022f00002110200241026a2d000021112002102c200341b0096a41126a221320113a0000200320103b01c009200320093a00b209200320083b01b0092003200e3a00cf092003200c3700c7092003200d3600c309200320073a00bf09200320043700b709200320053600b3090240200341b0096a109501220241ff01714102460d002002410171450d0041bd8fc2002109411c210d0c250b200b1002220228000321052002290007210420022d000f210720022f00002108200241026a2d000021092002102c201210022202280003210d2002290007210c20022d000f210e20022f00002110200241026a2d000021112002102c201320113a0000200320103b01c009200320093a00b209200320083b01b0092003200e3a00cf092003200c3700c7092003200d3600c309200320073a00bf09200320043700b709200320053600b309200341013a00a807200341b0096aad42808080808004842212200341a8076aad42808080801084100142002104200341a0066a41186a22074200370300200341a0066a41106a22024200370300200341a0066a41086a22084200370300200342003703a0064191b0c200ad4280808080e000841002220528000321092005290007210c20052d000f210d20052f0000210e200541026a2d000021102005102c200320103a00a2062003200e3b01a0062003200d3a00af062003200c3700a706200320093600a30641acb0c200ad4280808080e00084100222052d000f21092005280003210d2005290007210c20052f0000210e200541026a2d000021102005102c200341a0066a41126a221120103a00002002200e3b0100200341b0086a41086a220e20082903003703002003200c3700b7062003200d3600b306200341b0086a41106a220d2002290300370300200320093a00bf06200341b0086a41186a22092007290300370300200320032903a0063703b008200341306a200341b0086a41201094012003280234211020032802302113200742003703002002420037030020084200370300200342003703a006200b1002220528000321142005290007210b20052d000f211520052f00002116200541026a2d000021172005102c200320173a00a206200320163b01a006200320153a00af062003200b3700a706200320143600a30641f889c200ad4280808080e00084100222052d000f2114200528000321152005290007210b20052f00002116200541026a2d000021172005102c201120173a0000200220163b0100200e20082903003703002003200b3700b706200320153600b306200d2002290300370300200320143a00bf0620092007290300370300200320032903a0063703b008200341b0096a200341b0086a10e6010240024020032802b0092205450d00200320053602c00320032902b4092204422088a721022004a721070c010b41042105200341043602c00341002102410021070b0240024020022007460d002004422088210b0c010b024020022004a7470d00200241016a22072002490d0c200241017422082007200820074b1bad220b42c4007e220c422088a70d0c200ca722074100480d0c0240024020020d002007102a21050c010b2005200241c4006c2007102e21050b2005450d19200320053602c003200442808080807083200b8421040b2004422088220ba721020b2005200241c4006c6a220241003a000020022010410020131b360204200220032f00a8073b0001200241036a200341a8076a41026a2d00003a0000200220032902b009370208200241106a200341b0096a41086a2218290200370200200241186a200341b0096a41106a2219290200370200200241206a200341b0096a41186a290200370200200241286a200341b0096a41206a290200370200200241306a200341b0096a41286a290200370200200241386a200341b0096a41306a290200370200200241c0006a200341b0096a41386a280200360200200b422086200442ffffffff0f83844280808080107c2104200a200641f0006c6a2111024020060d00200a21070c230b200341b2066a211a200a210703402007280204210220072802002106200341b0096a200741086a41e80010db051a200741f0006a21072002450d23200341a8076a200341b0096a41e80010db051a200320023602b409200320063602b0092018200341a8076a41e80010db051a20032802c0032114200341a0066a41186a22084200370300200341a0066a41106a22064200370300200341a0066a41086a220e4200370300200342003703a0064191b0c200ad4280808080e000841002220228000321052002290007210b20022d000f210920022f0000210d200241026a2d000021102002102c200320103a00a2062003200d3b01a006200320093a00af062003200b3700a706200320053600a30641acb0c200ad4280808080e00084100222022d000f2105200228000321092002290007210b20022f0000210d200241026a2d000021102002102c201a20103a00002006200d3b0100200341b0086a41086a2213200e2903003703002003200b3700b706200320093600b306200341b0086a41106a2006290300370300200320053a00bf06200341b0086a41186a22152008290300370300200320032903a0063703b008200341286a200341b0086a412010940120032802282106200328022c2105200341b0086a200341b0096a10ee0202400240024020032802b00922020d0041ef8fc20021094110210d0c010b024020022005410020061b22064d0d00411a210d41ff8fc20021090c010b200341a0066a2002417f6a1093020240200341a0066a2019412010dd05450d004119210d419990c20021090c010b024020032802b009220941002006417b6a2202200220064b1b4f0d004126210d41b290c20021090c010b02400240201420142004422088220ba7221041c4006c22066a460d00201441016a2102034002402002417f6a2d00004101470d0041012105200341b0086a2002460d032002200341b0086a412010dd05450d030b200241c4006a2102200641bc7f6a22060d000b0b410021050b200341a0066a2009109302200341a0066a200341b0086a412010dd05210220034180046a41086a2216200341a0056a41086a221729020037030020034180046a41106a221b200341a0056a41106a221c290200370300200320032902a0053703800441d98fc20021094116210d20050d2420020d010c240b20034180046a41086a200341a0056a41086a29020037030020034180046a41106a200341a0056a41106a290200370300200320032902a005370380040c230b20034180056a410e6a220520034180046a410e6a29010037010020034180056a41086a2209201629030037030020032003290380043703800520034180046a200341b0096a10ee02200341a0056a41186a220d4200370300201c420037030020174200370300200342003703a00520154200370300200341b0086a41106a221d420037030020134200370300200342003703b00841c800102a2202450d18200341a0066a10e801200241186a2008290300370200200241106a200341a0066a41106a2206290300370200200241086a200e290300370200200220032903a0063702002002410236022020024101360244200220032903b0083700242002412c6a2013290300370000200241346a201d2903003700002002413c6a2015290300370000200320023602e00320034282808080203702e403200341e0036a10e9012008200d2903003703002006201c290300370300200e2017290300370300200320032903a0053703a006200341a0066a10ea01200e20162903003703002006201b290300370300200820034180046a41186a29030037030020132009290300370300200341b0086a410e6a2209200529010037010020032003290380043703a00620032003290380053703b0080240024020102004a7460d002004210c0c010b201041016a22022010490d0c200ba74101742205200220022005491bad220c42c4007e220b422088a70d0c200ba722024100480d0c0240024020100d002002102a21020c010b2014201041c4006c2002102e21020b2002450d19200320023602c0032004422088220ba721100b20032802c003201041c4006c6a220241013a0000200220032903a00637000120024116360028200241d98fc200360024200241003a0021200220032903b00837002c200241096a200e290300370000200241116a2006290300370000200241196a20082903003700002002413a6a2009290100370000200241346a2013290300370000200c42ffffffff0f832104200b422086210b024020032802bc092206450d0020032802b4092102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102c0c030b2002410c6a280200450d02200241086a280200102c0c020b2002410c6a280200450d01200241086a280200102c0c010b200241086a280200450d00200241046a280200102c0b200241246a21022006415c6a22060d000b0b200b2004842104024020032802b809450d0020032802b409102c0b20044280808080107c210420072011470d000c240b0b419cdbc20041ce0041acfec5001036000b41ecdac200413041acfec5001036000b2002410a6a2f010022084108762109200241066a2f0100220d410876211e200141106a28020022064118762113200641087621142002411a6a290100210b200241196a2d0000211f200241186a2d00002120200241166a2f01002121200241156a2d00002122200241146a2d00002123200241126a2f01002124200241116a2d00002125200241106a2d000021262002410e6a2f010021272002410d6a2d000021282002410c6a2d00002129200241096a2d00002105200241086a2d00002111200241056a2d0000210e200241046a2d00002110200241026a2f0100212a200141216a2900002104200141206a2d000021152001411d6a2f000021162001411c6a2d00002117200141196a2f0000211c200141186a2d0000211b200141156a2f0000211d200141146a2d000021182001410c6a2802002107200141086a280200210a20022d0001210f20022d0000210220012d001f211920012d001b211a20012d0017212b02400240024002400240024002400240024002400240024002400240024002400240024020012802040e050001020304000b200341b0096a41146a4101360200200342013702b409200341fcc4c5003602b009200341043602a406200341f4c4c5003602a0062003200341a0066a3602c009200341b0096a4184c5c5001041000b02400240200241ff01710d00200f41ff01714101460d010b4113210641c3b2c00021020c0c0b2003200b3703c0072003201f3a00bf07200320203a00be07200320213b01bc07200320223a00bb07200320233a00ba07200320243b01b807200320253a00b707200320263a00b607200320273b01b407200320283a00b307200320293a00b207200320083b01b007200320053a00af07200320103a00aa072003202a3b01a8072003200d410874201141187472200e723600ab070240200641034f0d004183b3c4002102410e21060c0c0b0240200641104d0d004191b3c4002102410d21060c0c0b41afb7c500ad4280808080c00084100222022d000f2105200229000721042002280003210820022f00002109200241026a2d0000210d2002102c41c4f9c300ad4280808080e00084100222022d000f210e2002290007210b2002280003210f20022f00002110200241026a2d000021112002102c200341a0036a200341a8076a109f0141c000102a2202450d24200220043700072002200836000320022009200d4110747222083b0000200241026a20084110763a0000200220053a000f2002200b3700172002200f3600132002201020114110747222053b0010200241126a20054110763a00002002200e3a001f200220032902a003370020200241286a200341a0036a41086a290200370000200241306a200341a0036a41106a290200370000200241386a200341a0036a41186a290200370000200341b0096a200241c00010ef02024020032802b00922050d002002102c42002104428080e983b1de16210b20034180036a200341a8076a428080e983b1de16420010c1012003280280032202450d0420032802840321060c0c0b200341b0096a41186a2903002104200341b0096a41106a290300210b20032802b40921082002102c200341b0096a41086a41003a0000200341b9096a20032903a807370000200341c9096a200341a8076a41106a290300370000200341d1096a200341a8076a41186a290300370000200341a8076a41086a290300210c200341113a00b009200341b0096a41116a200c37000041014100200341b0096a1092012008450d092005102c0c090b02400240200241ff01710d00200f41ff01714101470d00410021020c010b410121024102210e410021114100210d0b2003200b3702b8032003201f3a00b703200320203a00b603200320213b01b403200320223a00b303200320233a00b203200320243b01b003200320253a00af03200320263a00ae03200320273b01ac03200320283a00ab03200320293a00aa03200320083b01a803200320053a00a703200320103a00a2032003202a3b01a0032003200d410874201141187472200e7222053600a30302402002450d0041d6b2c0002102410f2106024002400240024020050e050001020310000b20032800a703210220032800ab0321060c0f0b41dd8cc6002102410e21060c0e0b41c3b2c0002102411321060c0d0b41b2b2c0002102411121060c0c0b200341a8076a41186a200341a0036a41186a290200370300200341a8076a41106a200341a0036a41106a290200370300200341a8076a41086a200341a0036a41086a290200370300200320032902a0033703a80741afb7c500ad4280808080c00084100222022d000f2106200229000721042002280003210520022f00002107200241026a2d000021082002102c41c4f9c300ad4280808080e00084100222022d000f210a2002290007210b2002280003210920022f0000210d200241026a2d0000210e2002102c200341c0036a200341a8076a109f0141c000102a2202450d2320022004370007200220053600032002200720084110747222053b0000200241026a20054110763a0000200220063a000f2002200b370017200220093600132002200d200e4110747222063b0010200241126a20064110763a00002002200a3a001f200220032902c003370020200241286a200341c8036a290200370000200241306a200341c0036a41106a290200370000200241386a200341c0036a41186a290200370000200341b0096a200241c00010ef02024020032802b0092206450d002002ad428080808080088410050b200341b0096a41186a2903002104200341c0096a290300210b20032802b40921052002102c2006450d0702402005450d002006102c0b200341a8076a200b200410c201200341e8096a2004370300200341e0096a200b370300200341b0096a41086a41033a0000200341b9096a20032903a807370000200341c9096a200341b8076a290300370000200341d1096a200341c0076a290300370000200341a8076a41086a2903002104200341113a00b009200341b0096a41116a200437000041014100200341b0096a1092010c0c0b024002400240200241ff017122114101460d00201e2109200d2108200e21050c010b2005210f201041ff01714101460d010b20114103460d00200f20027241ff0171450d00419eb3c4002102410a21060c0d0b0240200a41ff01714101460d00200a4118762109200a4108762105200a41107621080c050b200341b0096a200741067610910220032802b009210a0240024020032802b8092007413f7122024b0d00410021020c010b200a20024105746a22022f0000220541087621082002290018210420022d0017211520022d0016211920022f0014211620022d0013211720022d0012211a20022f0010211c20022d000f211b20022d000e212b20022f000c211d20022d000b211820022d000a211320022f0008211420022d000721062002280003210720022d00022109410121020b024020032802b409450d00200a102c0b20020d04410121050c050b200141346a2802002121200141306a28020021112001412c6a280200211f024002400240200241ff017122204101460d00201e2109200d2108200e21050c010b2005210f201041ff01714101460d010b20204103460d00200f20027241ff0171450d00419eb3c4002102410a21060c030b0240200a41ff01714101460d00200a4118762109200a4108762105200a41107621080c020b200341b0096a200741067610910220032802b009210a0240024020032802b8092007413f7122024b0d00410021020c010b200a20024105746a22022f0000220541087621082002290018210420022d0017211520022d0016211920022f0014211620022d0013211720022d0012211a20022f0010211c20022d000f211b20022d000e212b20022f000c211d20022d000b211820022d000a211320022f0008211420022d000721062002280003210720022d00022109410121020b024020032802b409450d00200a102c0b20020d0141dd8cc6002102410e21060c020b200341b0096a41086a41023a0000200341b9096a20032903a807370000200341a8076a41086a290300210c200341113a00b009200341b0096a41116a200c370000200341c9096a200341b8076a290300370000200341d1096a200341c0076a29030037000041014100200341b0096a1092010c050b200320043703c007200320153a00bf07200320193a00be07200320163b01bc07200320173a00bb072003201a3a00ba072003201c3b01b8072003201b3a00b7072003202b3a00b6072003201d3b01b407200320183a00b307200320133a00b207200320143b01b007200320063a00af07200320073600ab07200320093a00aa0720032008410874200541ff0171723b01a80741afb7c500ad4280808080c00084100222022d000f2106200229000721042002280003210520022f00002107200241026a2d000021082002102c41c4f9c300ad4280808080e00084100222022d000f210a2002290007210b2002280003210920022f0000210d200241026a2d0000210e2002102c200341c0036a200341a8076a109f0141c000102a2202450d1f20022004370007200220053600032002200720084110747222053b0000200241026a20054110763a0000200220063a000f2002200b370017200220093600132002200d200e4110747222063b0010200241126a20064110763a00002002200a3a001f200220032902c003370020200241286a200341c0036a41086a290200370000200241306a200341c0036a41106a290200370000200241386a200341c0036a41186a290200370000200341b0096a200241c00010ef02200341b0096a41186a22052903002104200341b0096a41106a290300210b20032802b409210720032802b00921062002102c0240024020060d004200210b420021040c010b2007450d002006102c0b200520043703002003200b3703c009200320213602b809200320113602b4092003201f3602b00941afb7c500ad4280808080c00084100222022d000f2106200229000721042002280003210520022f00002107200241026a2d000021082002102c41c4f9c300ad4280808080e00084100222022d000f210a2002290007210b2002280003210920022f0000210d200241026a2d0000210e2002102c200341a0036a200341a8076a109f0141c000102a2202450d1f20022004370007200220053600032002200720084110747222053b0000200241026a20054110763a0000200220063a000f2002200b370017200220093600132002200d200e4110747222063b0010200241126a20064110763a00002002200a3a001f200220032902a003370020200241286a200341a0036a41086a290200370000200241306a200341a0036a41106a290200370000200241386a200341a0036a41186a290200370000200341c0003602a406200320023602a006200341b0096a200341a0066a10792002102c02402011450d00201f102c0b200341b0096a41086a41013a0000200341b9096a20032903a807370000200341c9096a200341b8076a290300370000200341d1096a200341a8076a41186a290300370000200341a8076a41086a2903002104200341113a00b009200341b0096a41116a20043700004100210241014100200341b0096a1092010c050b2011450d06201f102c0c060b2008410874200541ff0171722102410021050b200320043702b803200320153a00b703200320193a00b603200320163b01b403200320173a00b3032003201a3a00b2032003201c3b01b0032003201b3a00af032003202b3a00ae032003201d3b01ac03200320183a00ab03200320133a00aa03200320143b01a803200320063a00a703200320073600a303200320093a00a203200320023b01a00302402005450d0041dd8cc6002102410e21060c070b200341a8076a41186a200341a0036a41186a290200370300200341a8076a41106a200341a0036a41106a290200370300200341a8076a41086a200341a0036a41086a290200370300200320032902a0033703a80741afb7c500ad4280808080c00084100222022d000f2106200229000721042002280003210520022f00002107200241026a2d000021082002102c41c4f9c300ad4280808080e00084100222022d000f210a2002290007210b2002280003210920022f0000210d200241026a2d0000210e2002102c200341c0036a200341a8076a109f0141c000102a2202450d1c20022004370007200220053600032002200720084110747222053b0000200241026a20054110763a0000200220063a000f2002200b370017200220093600132002200d200e4110747222063b0010200241126a20064110763a00002002200a3a001f200220032902c003370020200241286a200341c0036a41086a290200370000200241306a200341c0036a41106a290200370000200241386a200341c0036a41186a290200370000200341b0096a200241c00010ef02024020032802b0092206450d002002ad428080808080088410050b200341c8096a2903002104200341c0096a290300210b20032802b40921052002102c2006450d0002402005450d002006102c0b20034188036a200341a8076a200b200410bf0120032903880320034188036a41086a29030010b102200341e8096a2004370300200341e0096a200b370300200341b0096a41086a41043a0000200341b9096a20032903a807370000200341c9096a200341b8076a290300370000200341d1096a200341c0076a290300370000200341a8076a41086a2903002104200341113a00b009200341b0096a41116a200437000041014100200341b0096a1092010c050b41a8b3c4002102410921060c050b200341b0096a41186a20043703002003200b3703c009200320063602b809200320073602b4092003200a3602b00941afb7c500ad4280808080c00084100222022d000f2106200229000721042002280003210520022f00002108200241026a2d000021092002102c41c4f9c300ad4280808080e00084100222022d000f210d2002290007210b2002280003210e20022f0000210f200241026a2d000021102002102c200341c0036a200341a8076a109f0141c000102a2202450d1a20022004370007200220053600032002200820094110747222053b0000200241026a20054110763a0000200220063a000f2002200b3700172002200e3600132002200f20104110747222063b0010200241126a20064110763a00002002200d3a001f200220032902c003370020200241286a200341c8036a290200370000200241306a200341c0036a41106a290200370000200241386a200341c0036a41186a290200370000200341c0003602a406200320023602a006200341b0096a200341a0066a10792002102c02402007450d00200a102c0b410021020b0c010b2007450d00200a102c0b20020d010b200041023a00084100210d0c010b200041812e3b010820002006360204200020023602004100210d2000410a6a41003a00000b41012107410121054101210e4101210f4101211041012111410121134101211441012115410121084101210a4101210941012100410121060c3b0b2001411c6a280200210e200141186a2802002110200141146a280200210f2001410c6a2802002111200141086a280200211341d6b2c0002107410f21050240024020022d00000d0020022d000141ff01714102470d00200141246a2802002114200141106a2802002115200341a0036a41186a22054200370300200341a0036a41106a22064200370300200341a0036a41086a22074200370300200342003703a00341ecddc500ad4280808080f000841002220228000321082002290007210420022d000f210a20022f00002109200241026a2d0000210d2002102c2003200d3a00a203200320093b01a0032003200a3a00af03200320043700a703200320083600a30341f3ddc500ad4280808080c00184100222022d000f21082002280003210a2002290007210420022f00002109200241026a2d0000210d2002102c200341a0036a41126a200d3a0000200620093b0100200341e0036a41086a2007290300370300200320043700b7032003200a3600b303200341e0036a41106a2006290300370300200320083a00bf03200341e0036a41186a2005290300370300200320032903a0033703e003200341f8026a200341e0036a412010940120032802fc02210620032802f802210541a3dbc500ad4280808080800184100222022d000f2116200229000721042002280003211720022f0000211c200241026a2d0000211b2002102c41abdbc500ad4280808080a00284100222022d000f211d2002290007210b2002280003211820022f00002119200241026a2d0000211a2002102c20032006410020051b222b3602a807200341c0036a41186a2205200341a8076aad22124280808080c00084220c1006220241186a290000370300200341c0036a41106a2207200241106a290000370300200341c0036a41086a2208200241086a290000370300200320022900003703c0032002102c200341b0096a41186a220a2005290300370300200341b0096a41106a22092007290300370300200341b0096a41086a220d2008290300370300200320032903c0033703b00941c000102a2202450d1520022004370007200220173600032002201c201b4110747222063b0000200241026a20064110763a0000200220163a000f2002200b3700172002201836001320022019201a4110747222063b0010200241126a20064110763a00002002201d3a001f200220032903b009370020200241286a200d290300370000200241306a2009290300370000200241386a200a290300370000200320143602a8072005200c1006220641186a2900003703002007200641106a2900003703002008200641086a290000370300200320062900003703c0032006102c200a200529030037030020092007290300370300200d2008290300370300200320032903c0033703b009200241c000418001102e2202450d15200220032903b00937004041182105200241d8006a200341b0096a41186a290300370000200241d0006a200341b0096a41106a290300370000200241c8006a200341b0096a41086a290300370000200341f0026a200241e00041014100410010970120032802f00221072002102c200341a0036a41186a22084200370300200341a0036a41106a22064200370300200341a0036a41086a220a4200370300200342003703a00341a3dbc500ad42808080808001841002220228000321092002290007210420022d000f210d20022f00002116200241026a2d000021172002102c200320173a00a203200320163b01a0032003200d3a00af03200320043700a703200320093600a30341a0c6c500ad4280808080c00084100222022d000f21092002280003210d2002290007210420022f00002116200241026a2d000021172002102c200341b2036a20173a0000200620163b0100200341e0036a41086a200a290300370300200320043700b7032003200d3600b303200341e0036a41106a2006290300370300200320093a00bf03200341e0036a41186a2008290300370300200320032903a0033703e003200341b0096a200341e0036a10f00220032802b0092202410120021b211620032902b409420020021b210402400240024020074101470d0041e1c5c5002107411521050c010b201620144105746a410020142004422088a7491b22020d0141f6c5c50021070b2004a7450d012016102c0c010b200241086a290000210b200241106a290000210c2002290000212c200341a8076a41186a200241186a290000222d370300200341a8076a41106a200c370300200341a8076a41086a200b3703002003202c3703a807200341bd096a200b370000200341c5096a200c370000200341cd096a202d370000200341003a00b4092003410f3a00b0092003202c3700b50941014100200341b0096a109201200341003602b809200342013703b0092015200341b0096a10670240024020032802b409220620032802b80922026b2015490d0020032802b00921060c010b200220156a22052002490d09200641017422072005200720054b1b22054100480d090240024020060d002005102a21060c010b20032802b00920062005102e21060b2006450d16200320053602b409200320063602b0090b2003200220156a3602b809200620026a2013201510db051a200e200341b0096a106702400240200e450d00200f200e410c6c6a210d200f210603402006280200210a200641086a2802002202200341b0096a10670240024020032802b409220820032802b80922056b2002490d0020032802b00921070c010b200520026a22072005490d0c200841017422092007200920074b1b22094100480d0c0240024020080d002009102a21070c010b20032802b00920082009102e21070b2007450d19200320093602b409200320073602b009200921080b2003200520026a22093602b809200720056a200a200210db051a2006410c6a2206200d470d000c020b0b20032802b809210920032802b409210820032802b00921070b41a3dbc500ad4280808080800184100222022d000f21062002290007210b2002280003211520022f00002117200241026a2d0000211c2002102c41abdbc500ad4280808080a00284100222022d000f211b2002290007210c2002280003211d20022f00002118200241026a2d000021192002102c2003202b3602a807200341c0036a41186a220520124280808080c000841006220241186a290000370300200341c0036a41106a220a200241106a290000370300200341c0036a41086a220d200241086a290000370300200320022900003703c0032002102c200341b0096a41186a221a2005290300370300200341b0096a41106a222b200a290300370300200341b0096a41086a221f200d290300370300200320032903c0033703b00941c000102a2202450d152002201820194110747222183b001020022017201c4110747222173b00002002201b3a001f2002200c3700172002201d360013200220063a000f2002200b37000720022015360003200220032903b009370020200241126a20184110763a0000200241026a20174110763a0000200241286a201f290300370000200241306a202b290300370000200241386a201a290300370000200320143602b0092005200341b0096aad4280808080c000841006220641186a290000370300200a200641106a290000370300200d200641086a290000370300200320062900003703c0032006102c200341a0056a41186a2005290300370300200341a0056a41106a200a290300370300200341a0056a41086a200d290300370300200320032903c0033703a005200241c000418001102e2202450d15200220032903a005370040200241d8006a200341b8056a290300370000200241d0006a200341b0056a290300370000200241c8006a200341a8056a290300370000200341e0003602b409200320023602b00920072009200341b0096a10f1022002102c02402008450d002007102c0b02402004a7450d002016102c0b02402011450d002013102c0b0240200e450d00200e410c6c2106200f210203400240200241046a280200450d002002280200102c0b2002410c6a2102200641746a22060d000b0b02402010450d00200f102c0b200041023a0008410021060c010b02402011450d002013102c0b0240200e450d00200e410c6c2106200f210203400240200241046a280200450d002002280200102c0b2002410c6a2102200641746a22060d000b0b02402010450d00200f102c0b20004181263b01082000200536020420002007360200410021062000410a6a41003a00000b41012107410121054101210e4101210f4101211041012111410121134101211441012115410121084101210a41012109410121000c390b200141206a290200210c200141186a290200210b2002411a6a2901002104200241196a2d00002108200241186a2d0000210a200241166a2f01002109200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002116200241096a2d00002117200241086a2d0000211c200241066a2f0100211b200241056a2d0000211d200241046a2d00002118200241026a2f01002119200141286a2802002107200141106a29020021122001410c6a280200211a200141086a280200210620022d0001210520022d00002102024002400240024002400240024002400240024002400240024020012802040e0400010203000b200341b0096a41146a4101360200200342013702b409200341fcc4c5003602b009200341043602a406200341f4c4c5003602a0062003200341a0066a3602c009200341b0096a4184c5c5001041000b41002107200241ff01710d07200541ff01714101470d07200320043703b806200320083a00b7062003200a3a00b606200320093b01b4062003200d3a00b3062003200e3a00b2062003200f3b01b006200320103a00af06200320113a00ae06200320133b01ac06200320143a00ab06200320183a00a206200320193b01a006200320164108742017722015411874723600a7062003201b410874201d72201c411874723600a306200341c0036a41186a22074200370300200341c0036a41106a22054200370300200341c0036a41086a22084200370300200342003703c00341afb7c500ad4280808080c0008410022202280003210a2002290007210420022d000f210920022f0000210d200241026a2d0000210e2002102c2003200e3a00c2032003200d3b01c003200320093a00cf03200320043700c7032003200a3600c303418cb8c500ad42808080803084100222022d000f210a200228000321092002290007210420022f0000210d200241026a2d0000210e2002102c200341d2036a200e3a00002005200d3b0100200341a0036a41086a2008290300370300200320043700d703200320093600d303200341a0036a41106a20052903003703002003200a3a00df03200341a0036a41186a2007290300370300200320032903c0033703a003200341b0096a200341a0036a412010d30120032d00b00921022007200341c9096a2900003703002005200341c1096a2900003703002008200341b9096a290000370300200320032900b1093703c0030240024020024101460d00200341a8076a41186a4200370300200341a8076a41106a4200370300200341a8076a41086a4200370300200342003703a8070c010b200341a8076a41186a2007290300370300200341a8076a41106a2005290300370300200341a8076a41086a2008290300370300200320032903c0033703a8070b41022107200341a0066a200341a8076a412010dd050d07200341b0096a200641900110db051a200341003b01a807200341b0086a200341b0096a200341a8076a10c10241012102024020032d00b80822054102460d00200341b9086a310000210b20033100ba08210420033502b408210c20032802b008210741eb8cc600ad4280808080d00184100402402005450d00200b100e0b2004100e410021022007450d00200c4220862007ad8410040b200320023a00b2092003410e3b01b00941014100200341b0096a1092012006102c0c090b200320064118763a008205200320064108763b01800502400240200241ff01710d00200541ff01714101460d010b410021070c080b200320043703b806200320083a00b7062003200a3a00b606200320093b01b4062003200d3a00b3062003200e3a00b2062003200f3b01b006200320103a00af06200320113a00ae06200320133b01ac06200320143a00ab06200320183a00a206200320193b01a006200320164108742017722015411874723600a7062003201b410874201d72201c411874723600a306200341c0036a41186a22084200370300200341c0036a41106a22054200370300200341c0036a41086a220a4200370300200342003703c00341afb7c500ad4280808080c000841002220228000321092002290007210420022d000f210d20022f0000210e200241026a2d0000210f2002102c2003200f3a00c2032003200e3b01c0032003200d3a00cf03200320043700c703200320093600c303418cb8c500ad42808080803084100222022d000f21092002280003210d2002290007210420022f0000210e200241026a2d0000210f2002102c200341d2036a200f3a00002005200e3b0100200341a0036a41086a200a290300370300200320043700d7032003200d3600d303200341a0036a41106a2005290300370300200320093a00df03200341a0036a41186a2008290300370300200320032903c0033703a003200341b0096a200341a0036a412010d30120032d00b00921022008200341c9096a2900003703002005200341c1096a290000370300200a200341b9096a290000370300200320032900b1093703c0030240024020024101460d00200341a8076a41186a4200370300200341a8076a41106a4200370300200341a8076a41086a4200370300200342003703a8070c010b200341a8076a41186a2008290300370300200341a8076a41106a2005290300370300200341a8076a41086a200a290300370300200320032903c0033703a8070b200341a0066a200341a8076a412010dd050d010240200641ff01714101460d0020032f01800520032d00820541107472210a200b420888a72109200b422088a7210d200ba7210e0c060b200341b0096a201a41067610910220032802b00921060240024020032802b809201a413f7122024b0d00410021020c010b200620024105746a22022f0010200241126a2d000041107472210920022f0000200241026a2d000041107472210a20022d001f21072002290017210c2002280013210d20022d000f210e200229000721122002280003211a410121020b024020032802b409450d002006102c0b20020d05410121070c070b2001412c6a280200212b200341b0086a41106a200c3703002003200b3703b808200320073602c808200320123703b00802400240200241ff01710d00200541ff01714101460d010b202b109202410021070c040b200320043703b806200320083a00b7062003200a3a00b606200320093b01b4062003200d3a00b3062003200e3a00b2062003200f3b01b006200320103a00af06200320113a00ae06200320133b01ac06200320143a00ab06200320183a00a206200320193b01a006200320164108742017722015411874723600a7062003201b410874201d72201c411874723600a306200341c0036a41186a22074200370300200341c0036a41106a22054200370300200341c0036a41086a22084200370300200342003703c00341afb7c500ad4280808080c0008410022202280003210a2002290007210420022d000f210920022f0000210d200241026a2d0000210e2002102c2003200e3a00c2032003200d3b01c003200320093a00cf03200320043700c7032003200a3600c303418cb8c500ad42808080803084100222022d000f210a200228000321092002290007210420022f0000210d200241026a2d0000210e2002102c200341d2036a200e3a00002005200d3b0100200341a0036a41086a2008290300370300200320043700d703200320093600d303200341a0036a41106a20052903003703002003200a3a00df03200341a0036a41186a2007290300370300200320032903c0033703a003200341b0096a200341a0036a412010d30120032d00b00921022007200341c9096a2900003703002005200341c1096a2900003703002008200341b9096a290000370300200320032900b1093703c0030240024020024101460d00200341a8076a41186a4200370300200341a8076a41106a4200370300200341a8076a41086a4200370300200342003703a8070c010b200341a8076a41186a2007290300370300200341a8076a41106a2005290300370300200341a8076a41086a2008290300370300200320032903c0033703a8070b200341a0066a200341a8076a412010dd050d010240200641ff01714101460d0020064108762102200341c0086a290300210420032903b808220b420888a72106200b422088a72107200ba7210820032802c808210a20032903b008210b0c030b200341b0096a201a41067610910220032802b00921090240024020032802b809201a413f7122024b0d00410021050c010b200920024105746a22052f0010200541126a2d000041107472210620052f0000200541026a2d000041107472210220052d001f210a200529001721042005280013210720052d000f21082005290007210b2005280003211a410121050b024020032802b409450d002009102c0b20050d02202b109202410121070c030b410221070c050b202b109202410221070c010b200320063b01f003200341e0036a41126a20064110763a00002003200a3a00ff03200320043700f703200320073600f303200320083a00ef032003200b3700e7032003201a3600e303200320023b01e003200320024110763a00e203200341b0096a202b41900110db051a200341b2076a200341e8036a290300370100200341a8076a41126a20032903f003370100200341c2076a200341f8036a29030037010020034180023b01a807200320032903e0033701aa07200341a0056a200341b0096a200341a8076a10c10241012102024020032d00a80522064102460d00200341a9056a310000210b20033100aa05210420033502a405210c20032802a005210541eb8cc600ad4280808080d00184100402402006450d00200b100e0b2004100e410021022005450d00200c4220862005ad8410040b200320023a00b2092003418e043b01b00941014100200341b0096a109201410321070b202b102c0c020b200341c0036a41186a22054200370300200341c0036a41106a22064200370300200341c0036a41086a22084200370300200342003703c00341afb7c500ad4280808080c0008410022202280003210f2002290007210420022d000f211020022f00002111200241026a2d000021132002102c200320133a00c203200320113b01c003200320103a00cf03200320043700c7032003200f3600c303418cb8c500ad42808080803084100222022d000f210f200228000321102002290007210420022f00002111200241026a2d000021132002102c200341d2036a20133a0000200620113b0100200341a0036a41086a2008290300370300200320043700d703200320103600d303200341a0036a41106a20062903003703002003200f3a00df03200341a0036a41186a2005290300370300200320032903c0033703a003200341b0096a200341a0036a412010d30120032d00b00921022005200341c9096a2900003703002006200341c1096a2900003703002008200341b9096a290000370300200320032900b1093703c0030240024020024101460d00200341a0056a41186a4200370300200341a0056a41106a4200370300200341a0056a41086a4200370300200342003703a0050c010b200341a0056a41186a2005290300370300200341a0056a41106a2006290300370300200341a0056a41086a2008290300370300200320032903c0033703a0050b200341ba096a200341a8056a290300370100200341b0096a41126a2202200341a0056a41106a290300370100200341ca096a200341b8056a2903003701002003418e023b01b009200320032903a0053701b20941014100200341b0096a109201200320093b01c009200220094110763a0000200320073a00cf092003200c3700c7092003200d3600c3092003200e3a00bf09200320123700b7092003201a3600b3092003200a3b01b0092003200a4110763a00b20941afb7c500ad4280808080c000841002220228000321062002290007210420022d000f210520022f00002107200241026a2d000021082002102c418cb8c500ad4280808080308410022202280003210a2002290007210b20022d000f210920022f0000210d200241026a2d0000210e2002102c200341e0036a41126a200e3a00002003200d3b01f003200320083a00e203200320073b01e003200320093a00ff032003200b3700f7032003200a3600f303200320053a00ef03200320043700e703200320063600e303200341203602ac072003200341e0036a3602a807200341b0096a200341a8076a10a102410321070c010b20061092022006102c0b41cfe7c5002102410b21064102210502400240024020070e0400010203000b41c3b2c000210241132106410021050c010b41dd8cc6002102410e2106410121050b20004181243b010820002006360204200020023602002000410a6a20053a00000c010b200041023a00080b4100210041012107410121054101210e4101210f4101211041012111410121134101211441012115410121084101210a41012109410121060c380b200341b0096a200141086a41800110db051a200341a8076a41206a200241206a290200370300200341a8076a41186a200241186a290200370300200341a8076a41106a200241106a290200370300200341a8076a41086a200241086a290200370300200320022902003703a807200341e8026a200341b0096a200341a8076a10f2020240024020032802e80222020d00200041023a0008410021090c010b20032802ec02210620004181223b010820002002360200410021092000410a6a41003a0000200020063602040b41012107410121054101210e4101210f4101211041012111410121134101211441012115410121084101210a0c360b200341a0056a41086a220a2001411c6a290200370300200341a0056a41106a2209200141246a290200370300200341a0056a41186a220d2001412c6a2802003602002003200141146a2902003703a005200241086a2802002105200241046a28020021072001410c6a280200210820022d0000210602400240024002400240024002400240024002400240200141086a2802000e0400010203000b200341b0096a41146a4101360200200342013702b409200341fcc4c5003602b009200341043602a406200341f4c4c5003602a0062003200341a0066a3602c009200341b0096a4184c5c5001041000b200141386a290300210b200141306a29030021042002411a6a290100210c200241196a2d0000210f200241186a2d00002110200241166a2f01002111200241156a2d00002113200241146a2d00002114200241126a2f01002115200241116a2d00002116200241106a2d000021172002410e6a2f0100211c2002410d6a2d0000211b2002410c6a2d0000211d200241026a2f01002118200141106a280200210e20022d00012102200341b0086a41186a200d280200360200200341b0086a41106a2009290300370300200341b0086a41086a200a290300370300200320032903a0053703b00802400240200641ff01710d00200241ff01714101460d010b4113210641c3b2c0002105410021020c080b2003200c3703c0072003200f3a00bf07200320103a00be07200320113b01bc07200320133a00bb07200320143a00ba07200320153b01b807200320163a00b707200320173a00b6072003201c3b01b4072003201b3a00b307200320073a00aa07200320183b01a80720032005411076410874200541087641ff017172201d411874723600af0720032007411076410874200741087641ff0171722005411874723600ab0702400240200841ff01714101460d0020084108762107200341c0086a290300212c20032903b808220c420888a72108200c422088a72109200ca7210d20032802c808210f20032903b008212d0c010b200341b0096a200e41067610910220032802b00921060240024020032802b809200e413f7122024b0d00410021020c010b200620024105746a22022f0010200241126a2d000041107472210820022f0000200241026a2d000041107472210720022d001f210f2002290017212c2002280013210920022d000f210d2002290007212d2002280003210e410121020b024020032802b409450d002006102c0b2002450d060b200341b8026a2004200b42c0843d420010e105200341a8026a20032903b802220c200341b8026a41086a290300221242c0fb42427f10e00520034198026a200c201242d08603420010e005200341c8026a200341a8076a2003290398022212200420032903a8027c220c42d086037e200c421480220c42c0fb427e7c42a0c21e56200ca76aad7c220c428080e983b1de16200c428080e983b1de165620034198026a41086a290300200c201254ad7c220c420052200c501b22021b2212200c420020021b220c10c10120032802c8020d06200341e0036a41186a22054200370300200341e0036a41106a22064200370300200341e0036a41086a220a4200370300200342003703e00341a4e9c500ad4280808080800184222e1002220228000321102002290007212f20022d000f211120022f00002113200241026a2d000021142002102c200320143a00e203200320133b01e003200320113a00ef032003202f3700e703200320103600e30341ace9c500ad4280808080d00184222f100222022d000f2110200228000321112002290007213020022f00002113200241026a2d000021142002102c200341e0036a41126a221520143a0000200620133b0100200341a0036a41086a2213200a290300370300200320303700f703200320113600f303200341a0036a41106a22112006290300370300200320103a00ff03200341a0036a41186a22102005290300370300200320032903e0033703a00320034190026a200341a0036a4120109401200328029402211420032802900221162005420037030020064200370300200a4200370300200342003703e003202e1002220228000321172002290007213020022d000f211c20022f0000211b200241026a2d0000211d2002102c2003201d3a00e2032003201b3b01e0032003201c3a00ef03200320303700e703200320173600e303202f100222022d000f21172002280003211c2002290007212f20022f0000211b200241026a2d0000211d2002102c2015201d3a00002006201b3b01002013200a2903003703002003202f3700f7032003201c3600f30320112006290300370300200320173a00ff0320102005290300370300200320032903e0033703a00320032014410020161b221041016a3602b009200341a0036aad4280808080800484200341b0096aad4280808080c000841001200341820a6a20084110763a0000200341800a6a20083b0100200341b0096a41186a200c370300200341b0096a41386a200341a8076a41186a290300370300200341b0096a41306a200341a8076a41106a290300370300200341b0096a41286a200341a8076a41086a2903003703002003418f0a6a200f3a0000200341870a6a202c370000200341830a6a2009360000200341ff096a200d3a0000200341f7096a202d370000200341f3096a200e360000200320073b01f009200341f2096a20074110763a00002003200b3703b809200320043703b009200320123703c009200320032903a8073703d009202e100222022d000f2107200229000721042002280003210820022f00002109200241026a2d0000210d2002102c41e1e5c200ad4280808080900184100222022d000f210e2002290007210b2002280003210f20022f00002111200241026a2d000021132002102c200320103602a006200341c0036a41186a2214200341a0066aad4280808080c000841006220241186a290000370300200341c0036a41106a2215200241106a290000370300200341c0036a41086a2216200241086a290000370300200320022900003703c0032002102c2005201429030037030020062015290300370300200a2016290300370300200320032903c0033703e00341c000102a2202450d19200220043700072002200836000320022009200d4110747222083b0000200241026a20084110763a0000200220073a000f2002200b3700172002200f3600132002201120134110747222073b0010200241126a20074110763a00002002200e3a001f200220032903e003370020200241286a200341e0036a41086a290300370000200241306a2006290300370000200241386a2005290300370000200341003602a806200342013703a006200341b0096a41206a200341a0066a109101200341b0096a41086a290300210420032903b009210b0240024020032802a406220520032802a80622066b4110490d0020032802a00621050c010b200641106a22072006490d0d200541017422062007200620074b1b22064100480d0d0240024020050d002006102a21050c010b20032802a00620052006102e21050b2005450d1a200320063602a406200320053602a00620032802a80621060b200520066a220520043700082005200b3700002003200641106a3602a806200341b0096a41c0006a200341a0066a109101200341c8096a290300210420032903c009210b0240024020032802a406220720032802a80622056b4110490d0020032802a00621060c010b200541106a22062005490d0d200741017422052006200520064b1b22084100480d0d0240024020070d002008102a21060c010b20032802a00620072008102e21060b2006450d1a200320083602a406200320063602a00620032802a8062105200821070b200620056a220820043700082008200b3700002002ad4280808080800884200541106aad4220862006ad84100102402007450d002006102c0b2002102c200341b8096a41003a00002003410c3a00b009200341b0096a410c6a201036020041014100200341b0096a1092010c080b200641ff01714101470d0320054102490d03200741ff01710d0341a4e9c500ad4280808080800184100222022d000f2106200229000721042002280003210520022f00002107200241026a2d0000210a2002102c41e1e5c200ad4280808080900184100222022d000f21092002290007210b2002280003210d20022f0000210e200241026a2d0000210f2002102c200320083602b009200341c0036a41186a2208200341b0096aad4280808080c000841006220241186a290000370300200341c0036a41106a2210200241106a290000370300200341c0036a41086a2211200241086a290000370300200320022900003703c0032002102c200341a0036a41186a22132008290300370300200341a0036a41106a22082010290300370300200341a0036a41086a22102011290300370300200320032903c0033703a00341c000102a2202450d18200220043700072002200536000320022007200a4110747222053b0000200241026a20054110763a0000200220063a000f2002200b3700172002200d3600132002200e200f4110747222063b0010200241126a20064110763a0000200220093a001f200220032903a003370020200241286a2010290300370000200241306a2008290300370000200241386a2013290300370000200341b0096a200241c00010b802024020032903b00942015222060d002002ad428080808080088410050b20032903b8092104200341a0066a200341c0096a41d80010db051a200341b0096a200341a0066a41d80010db051a20060d01200341b0086a200341b0096a41d80010db051a2002102c200320043703a807200341a8076a41086a200341b0086a41d80010db051a200341d0026a200341c8076a20032903b807200341c0076a29030010bf0120032903d002200341d0026a41086a29030010a9010c070b200641ff01714101470d0220054104490d02200741ff01710d0241a4e9c500ad4280808080800184100222022d000f2106200229000721042002280003210520022f00002107200241026a2d0000210a2002102c41e1e5c200ad4280808080900184100222022d000f21092002290007210b2002280003210d20022f0000210e200241026a2d0000210f2002102c200320083602b009200341c0036a41186a2210200341b0096aad4280808080c000841006220241186a290000370300200341c0036a41106a2211200241106a290000370300200341c0036a41086a2213200241086a290000370300200320022900003703c0032002102c200341a0036a41186a22142010290300370300200341a0036a41106a22102011290300370300200341a0036a41086a22112013290300370300200320032903c0033703a00341c000102a2202450d17200220043700072002200536000320022007200a4110747222053b0000200241026a20054110763a0000200220063a000f2002200b3700172002200d3600132002200e200f4110747222063b0010200241126a20064110763a0000200220093a001f200220032903a003370020200241286a2011290300370000200241306a2010290300370000200241386a2014290300370000200341e0026a200241c00041014100410010970120032802e00221062002102c20064101470d01200341a0036a41186a22054200370300200341a0036a41106a22024200370300200341a0036a41086a22074200370300200342003703a00341a4e9c500ad4280808080800184220c10022206280003210a2006290007210420062d000f210920062f0000210d200641026a2d0000210e2006102c2003200e3a00a2032003200d3b01a003200320093a00af03200320043700a7032003200a3600a30341b9e9c500ad42808080809001842212100222062d000f210a200628000321092006290007210420062f0000210d200641026a2d0000210e2006102c200341a0036a41126a200e3a00002002200d3b0100200341e0036a41086a220d2007290300370300200320043700b703200320093600b303200341e0036a41106a220920022903003703002003200a3a00bf03200341e0036a41186a220a2005290300370300200320032903a0033703e003200341b0096a200341e0036a10960120032802b0092206410420061b210e024020032902b409420020061b2204422088220ba722062004a7470d00200641016a220f2006490d0b200ba722114101742210200f200f2010491b220f41ffffffff0371200f470d0b200f41027422104100480d0b0240024020060d002010102a210e0c010b200e20114102742010102e210e0b200e450d182004422088220ba72106200fad21040b200e20064102746a2008360200200542003703002002420037030020074200370300200342003703a003200c1002220628000321082006290007210c20062d000f210f20062f00002110200641026a2d000021112006102c200320113a00a203200320103b01a0032003200f3a00af032003200c3700a703200320083600a3032012100222062d000f21082006280003210f2006290007210c20062f00002110200641026a2d000021112006102c200341b2036a20113a0000200220103b0100200d20072903003703002003200c3700b7032003200f3600b30320092002290300370300200320083a00bf03200a2005290300370300200320032903a0033703e0030240200e0d00200341e0036aad428080808080048410050c070b200341003602b809200342013703b009200ba741016a2206200341b0096a10670240024020060d0020032802b809210a20032802b409210820032802b00921060c010b410020032802b80922026b2105200e20064102746a210d20032802b4092108200e210703402007280200210902400240200820056a4104490d0020032802b00921060c010b200241046a22062002490d0d2008410174220a2006200a20064b1b220a4100480d0d0240024020080d00200a102a21060c010b20032802b0092008200a102e21060b2006450d1a2003200a3602b409200320063602b009200a21080b2003200241046a220a3602b809200620026a20093600002005417c6a2105200a2102200d200741046a2207470d000b0b2004a72102200341e0036aad4280808080800484200aad4220862006ad84100102402008450d002006102c0b2002450d06200e102c0c060b2002102c0b41dee9c500210541142106410321020c030b410e210641cf8cc6002105410021020c020b41dd8cc6002105410e2106410121020c010b41c2e9c5002105411c2106410221020b20004181203b010820002006360204200020053602002000410a6a20023a00000c1a0b200041023a00080c190b200141086a28020021062001280204210502400240024020022d00000d0020022d000141ff01714101460d010b02402006450d002005102c0b200041811e3b010820004113360204200041c3b2c0003602004100210a2000410a6a41003a00000c010b02402006450d002005102c0b200041023a00084100210a0b41012107410121054101210e4101210f4101211041012111410121134101211441012115410121080c330b02400240024020022d00000d0020022d000141ff01714102470d0020012802042106200341e0036a41186a22074200370300200341e0036a41106a22054200370300200341e0036a41086a22084200370300200342003703e00341f9e8c500ad428080808090018410022202280003210a2002290007210420022d000f210920022f0000210d200241026a2d0000210e2002102c2003200e3a00e2032003200d3b01e003200320093a00ef03200320043700e7032003200a3600e30341de99c500ad4280808080e00084100222022d000f210a200228000321092002290007210420022f0000210d200241026a2d0000210e2002102c200341e0036a41126a200e3a00002005200d3b0100200341a0056a41086a2008290300370300200320043700f703200320093600f303200341a0056a41106a20052903003703002003200a3a00ff03200341a0056a41186a2007290300370300200320032903e0033703a00520034188026a200341a0056a41204101410041001097012003280288024101460d01200341c0036a41186a22074200370300200341c0036a41106a22054200370300200341c0036a41086a22084200370300200342003703c0034191b0c200ad4280808080e0008410022202280003210a2002290007210420022d000f210920022f0000210d200241026a2d0000210e2002102c2003200e3a00c2032003200d3b01c003200320093a00cf03200320043700c7032003200a3600c30341acb0c200ad4280808080e00084100222022d000f210a200228000321092002290007210420022f0000210d200241026a2d0000210e2002102c200341c0036a41126a200e3a00002005200d3b0100200341a0036a41086a2008290300370300200320043700d703200320093600d303200341a0036a41106a20052903003703002003200a3a00df03200341a0036a41186a2007290300370300200320032903c0033703a00320034180026a200341a0036a412010940120032802840241002003280280021b2006490d02200341e0036a41186a22074200370300200341e0036a41106a22054200370300200341e0036a41086a22084200370300200342003703e00341f9e8c500ad428080808090018410022202280003210a2002290007210420022d000f210920022f0000210d200241026a2d0000210e2002102c2003200e3a00e2032003200d3b01e003200320093a00ef03200320043700e7032003200a3600e30341de99c500ad4280808080e00084100222022d000f210a200228000321092002290007210420022f0000210d200241026a2d0000210e2002102c200341f2036a200e3a00002005200d3b0100200341a0056a41086a2008290300370300200320043700f703200320093600f303200341a0056a41106a20052903003703002003200a3a00ff03200341a0056a41186a2007290300370300200320032903e0033703a005200320063602b009200341a0056aad4280808080800484200341b0096aad4280808080c000841001200041023a00080c1a0b200041811c3b01082000410f360204200041d6b2c0003602002000410a6a41003a00000c190b41ef99c500413141acfec5001036000b41a09ac500412341acfec5001036000b20034180056a41026a220d200141076a2d00003a0000200341a8076a41086a220e2001411c6a290200370300200341a8076a41106a220f200141246a290200370300200341a8076a41186a2001412c6a290200370300200341c8076a200141346a290200370300200341d0076a2001413c6a290200370300200341d8076a200141c4006a2d00003a0000200320012f00053b0180052003200141146a2902003703a807200141086a28020021082001410c6a280200210a200141106a28020021052002410c6a2802002110200241086a280200210720022f0001200241036a2d0000411074722111200241046a280200211320022d000021060240024002400240024002400240024002400240024002400240024002400240024002400240024020012d000422090e06000102030405000b200341b0096a41146a4101360200200342013702b409200341fcc4c5003602b009200341043602a406200341f4c4c5003602a0062003200341a0066a3602c009200341b0096a4184c5c5001041000b200341b7066a200e290300370000200341bf066a200f2d00003a0000200320032f0180053b01a006200320053600ab062003200a3600a706200320083600a306200320032903a8073700af062003200d2d00003a00a206024002402006417f6a220241024b0d00024020020e03000102000b200741017420104d0d00201341ff0171450d010b200620117241ff01710d140b200341c0036a41186a22054200370300200341c0036a41106a22064200370300200341c0036a41086a22074200370300200342003703c00341e9eac100ad4280808080b0028410022202280003210d2002290007210420022d000f210e20022f0000210f200241026a2d000021102002102c200320103a00c2032003200f3b01c0032003200e3a00cf03200320043700c7032003200d3600c30341eae5c200ad4280808080f00084100222022d000f210d2002280003210e2002290007210420022f0000210f200241026a2d000021102002102c200341d2036a20103a00002006200f3b0100200341a0036a41086a2007290300370300200320043700d7032003200e3600d303200341a0036a41106a20062903003703002003200d3a00df03200341a0036a41186a2005290300370300200320032903c0033703a003200341b0096a200341a0036a412010d001024020032802b009220d0d004101210d20034101360280044100210f410021100c100b2003200d3602800420032802b409210f20032902b4092204a7211041002102024002402004422088a7220e41014b0d00200e0e021101110b200e210603402006410176220520026a22072002200d20074105746a200341a0066a412010dd054101481b2102200620056b220641014b0d000b0b0240200d20024105746a200341a0066a412010dd0522060d00419eecc10021052010450d12200d102c4110210f0c150b200341b0096a41186a200341a0066a41186a290300370300200341b0096a41106a200341a0066a41106a290300370300200341b0096a41086a200341a0066a41086a290300370300200320032903a0063703b00902402006411f7620026a2205200e4b0d00200341b0096a21060c110b41ecb3c000411e41acfec5001036000b200341b7066a200e290300370000200341bf066a200f2d00003a0000200320032f0180053b01a006200320053600ab062003200a3600a706200320083600a306200320032903a8073700af062003200d2d00003a00a206024002402006417f6a220241024b0d00024020020e03000102000b200741017420104d0d00201341ff0171450d010b200620117241ff01710d130b200341c0036a41186a22054200370300200341c0036a41106a22064200370300200341c0036a41086a22074200370300200342003703c00341e9eac100ad4280808080b0028410022202280003210d2002290007210420022d000f210e20022f0000210f200241026a2d000021102002102c200320103a00c2032003200f3b01c0032003200e3a00cf03200320043700c7032003200d3600c30341eae5c200ad4280808080f00084100222022d000f210d2002280003210e2002290007210420022f0000210f200241026a2d000021102002102c200341d2036a20103a00002006200f3b0100200341a0036a41086a2007290300370300200320043700d7032003200e3600d303200341a0036a41106a20062903003703002003200d3a00df03200341a0036a41186a2005290300370300200320032903c0033703a003200341b0096a200341a0036a412010d00120032802b0092206410120061b210d41002102024002400240024020032902b409420020061b2204422088a7220e41014b0d00200e0e020201020b200e210603402006410176220520026a22072002200d20074105746a200341a0066a412010dd054101481b2102200620056b220641014b0d000b0b200d20024105746a200341a0066a412010dd05450d010b41aeecc1002105410c210f2004a7450d14200d102c0c140b2002200e4f0d03200d20024105746a2206200641206a2002417f73200e6a41057410dc051a200341a0056a41186a22054200370300200341a0056a41106a22064200370300200341a0056a41086a22074200370300200342003703a00541e9eac100ad4280808080b0028410022202280003210f2002290007210b20022d000f211020022f00002111200241026a2d000021132002102c200320133a00a205200320113b01a005200320103a00af052003200b3700a7052003200f3600a30541eae5c200ad4280808080f00084100222022d000f210f200228000321102002290007210b20022f00002111200241026a2d000021132002102c200341b2056a20133a0000200620113b0100200341b0096a41086a20072903003703002003200b3700b705200320103600b305200341b0096a41106a20062903003703002003200f3a00bf05200341b0096a41186a2005290300370300200320032903a0053703b009200341003602b808200342013703b008200e417f6a2205200341b0086a106702402005450d00200e41057441606a2106200d210203402002200341b0086a109101200241206a2102200641606a22060d000b0b20032802b4082102200341b0096aad428080808080048420033502b80842208620032802b0082206ad84100102402002450d002006102c0b200341b0096a41186a200341a0066a41186a290300370300200341b0096a41106a200341a0066a41106a290300370300200341b0096a41086a200341a0066a41086a290300370300200320032903a0063703b009200341b0096a4101200d200510f3022003418a023b01b0094100210541014100200341b0096a1092012004a7450d0b200d102c0c0b0b200341c7086a200e290300370000200341cf086a200f2d00003a0000200320032f0180053b01b008200320053600bb082003200a3600b708200320083600b308200320032903a8073700bf082003200d2d00003a00b208200341a0066a41186a200341d1076a290000370300200341a0066a41106a200341c9076a290000370300200341a0066a41086a200341a8076a41196a290000370300200320032900b9073703a006024002402006417f6a220241024b0d00024020020e03000102000b200741017420104d0d00201341ff0171450d010b200620117241ff01710d120b0240200341b0086a200341a0066a412010dd050d00410021050c0b0b200341c0036a41186a22054200370300200341c0036a41106a22064200370300200341c0036a41086a22074200370300200342003703c00341e9eac100ad4280808080b0028410022202280003210d2002290007210420022d000f210e20022f0000210f200241026a2d000021102002102c200320103a00c2032003200f3b01c0032003200e3a00cf03200320043700c7032003200d3600c30341eae5c200ad4280808080f00084100222022d000f210d2002280003210e2002290007210420022f0000210f200241026a2d000021102002102c200341d2036a20103a00002006200f3b0100200341a0036a41086a2007290300370300200320043700d7032003200e3600d303200341a0036a41106a20062903003703002003200d3a00df03200341a0036a41186a2005290300370300200320032903c0033703a003200341b0096a200341a0036a412010d00120032802b0092206410120061b210741aeecc1002105410c210f410021020240024020032902b409420020061b2204422088a7221041014b0d0020100e020e010e0b2010210603402006410176220d20026a220e20022007200e4105746a200341b0086a412010dd054101481b21022006200d6b220641014b0d000b0b200720024105746a2211200341b0086a412010dd050d0c410021060240201041014b0d0020100e020a090a0b2010210503402005410176220d20066a220e20062007200e4105746a200341a0066a412010dd054101481b21062005200d6b220541014b0d000c090b0b024002402006417f6a220241024b0d00024020020e03000102000b200741017420104d0d00201341ff0171450d010b200620117241ff0171450d000240200a450d002008102c0b419eb3c4002105410a210f0c140b2008200510f402200341c0036a41186a22074200370300200341c0036a41106a22064200370300200341c0036a41086a220d4200370300200342003703c00341e9eac100ad4280808080b00284220410022202280003210e2002290007210b20022d000f210f20022f00002110200241026a2d000021112002102c200320113a00c203200320103b01c0032003200f3a00cf032003200b3700c7032003200e3600c30341eae5c200ad4280808080f00084220b100222022d000f210e2002280003210f2002290007210c20022f00002110200241026a2d000021112002102c200341c0036a41126a20113a0000200620103b0100200341a0036a41086a200d2903003703002003200c3700d7032003200f3600d303200341a0036a41106a20062903003703002003200e3a00df03200341a0036a41186a2007290300370300200320032903c0033703a003200341b0096a200341a0036a412010d0012008200520032802b0092202410120021b220620032902b409420020021b220c422088a710f5020240200ca7450d002006102c0b200341a0056a41186a22074200370300200341a0056a41106a22064200370300200341a0056a41086a220d4200370300200342003703a005200410022202280003210e2002290007210420022d000f210f20022f00002110200241026a2d000021112002102c200320113a00a205200320103b01a0052003200f3a00af05200320043700a7052003200e3600a305200b100222022d000f210e2002280003210f2002290007210420022f00002110200241026a2d000021112002102c200341a0056a41126a20113a0000200620103b0100200341b0096a41086a200d290300370300200320043700b7052003200f3600b305200341b0096a41106a20062903003703002003200e3a00bf05200341b0096a41186a2007290300370300200320032903a0053703b009200341003602a806200342013703a0062005200341a0066a106702402005450d00200541057421062008210203402002200341a0066a109101200241206a2102200641606a22060d000b0b20032802a4062102200341b0096aad428080808080048420033502a80642208620032802a0062206ad84100102402002450d002006102c0b0240200a450d002008102c0b2003418a063b01b009410021054101210241014100200341b0096a1092010c120b201041107621142010410876211520074110762116200741087621172002411a6a2901002104200241196a2d0000211b200241186a2d0000211d200241166a2f01002118200241156a2d00002119200241146a2d0000211a200241126a2f0100212b200241116a2d0000211f200241106a2d0000211c200341c7086a200e290300370000200341cf086a200f2d00003a0000200320032f0180053b01b008200320053600bb082003200a3600b708200320083600b308200320032903a8073700bf082003200d2d00003a00b208410220134108762007411874724102201141ff017141014622051b20061b21020240024020060d0020050d010b41d6b2c0002105410f210f024002400240024020020e050001020315000b201741ff01712016410874722010411874722105201541ff0171201441087472201c41187472210f0c140b41dd8cc6002105410e210f0c130b41c3b2c00021054113210f0c120b41b2b2c00021054111210f0c110b200320043703b8062003201b3a00b7062003201d3a00b606200320183b01b406200320193a00b3062003201a3a00b2062003202b3b01b0062003201f3a00af062003201c3a00ae06200320143b01ac06200320153a00ab06200320103a00aa06200320163b01a806200320173a00a706200320023600a306200320133a00a206200320114108763b01a006200341a0066a200341b0086a412010dd05450d03200341c0036a41186a22054200370300200341c0036a41106a22064200370300200341c0036a41086a22074200370300200342003703c00341e9eac100ad4280808080b0028410022202280003210d2002290007210420022d000f210e20022f0000210f200241026a2d000021102002102c200320103a00c2032003200f3b01c0032003200e3a00cf03200320043700c7032003200d3600c30341eae5c200ad4280808080f00084100222022d000f210d2002280003210e2002290007210420022f0000210f200241026a2d000021102002102c200341d2036a20103a00002006200f3b0100200341a0036a41086a2007290300370300200320043700d7032003200e3600d303200341a0036a41106a20062903003703002003200d3a00df03200341a0036a41186a2005290300370300200320032903c0033703a003200341b0096a200341a0036a412010d00120032802b0092206410120061b210741aeecc1002105410c210f410021020240024020032902b409420020061b2204422088a7221041014b0d0020100e020701070b2010210603402006410176220d20026a220e20022007200e4105746a200341a0066a412010dd054101481b21022006200d6b220641014b0d000b0b200720024105746a2211200341a0066a412010dd050d05410021060240201041014b0d0020100e020302030b2010210503402005410176220d20066a220e20062007200e4105746a200341b0086a412010dd054101481b21062005200d6b220541014b0d000c020b0b418ab4c000411d41acfec5001036000b200720064105746a200341b0086a412010dd050d00419eecc10021054110210f0c030b200341e0036a41186a2206200341b0086a41186a290300370300200341e0036a41106a2205200341b0086a41106a290300370300200341e0036a41086a220d200341b0086a41086a290300370300200320032903b0083703e003200220104f0d01201120032903e003370000201141186a2006290300370000201141106a2005290300370000201141086a200d2903003700002007201010f402200341a0056a41186a22054200370300200341a0056a41106a22064200370300200341a0056a41086a220d4200370300200342003703a00541e9eac100ad4280808080b0028410022202280003210e2002290007210b20022d000f210f20022f00002111200241026a2d000021132002102c200320133a00a205200320113b01a0052003200f3a00af052003200b3700a7052003200e3600a30541eae5c200ad4280808080f00084100222022d000f210e2002280003210f2002290007210b20022f00002111200241026a2d000021132002102c200341b2056a20133a0000200620113b0100200341b0096a41086a200d2903003703002003200b3700b7052003200f3600b305200341b0096a41106a20062903003703002003200e3a00bf05200341b0096a41186a2005290300370300200320032903a0053703b00941002102200341003602a805200342013703a0052010200341a0056a1067201041057421060340200720026a200341a0056a1091012006200241206a2202470d000b20032802a4052102200341b0096aad428080808080048420033502a80542208620032802a0052206ad84100102402002450d002006102c0b200341b0096a41186a200341a0066a41186a290300370300200341b0096a41106a200341a0066a41106a290300370300200341b0096a41086a200341a0066a41086a290300370300200320032903a0063703b009200341b0096a41012007201010f3022004a7450d002007102c0b2003418a083b01b0094100210541014100200341b0096a1092010c040b41a888c600200220101038000b2004a7450d0a2007102c0c0a0b200720064105746a200341a0066a412010dd050d00419eecc10021054110210f0c030b200341e0036a41186a2206200341a0066a41186a290300370300200341e0036a41106a2205200341a0066a41106a290300370300200341e0036a41086a220d200341a0066a41086a290300370300200320032903a0063703e003200220104f0d01201120032903e003370000201141186a2006290300370000201141106a2005290300370000201141086a200d2903003700002007201010f402200341a0056a41186a22054200370300200341a0056a41106a22064200370300200341a0056a41086a220d4200370300200342003703a00541e9eac100ad4280808080b0028410022202280003210e2002290007210b20022d000f210f20022f00002111200241026a2d000021132002102c200320133a00a205200320113b01a0052003200f3a00af052003200b3700a7052003200e3600a30541eae5c200ad4280808080f00084100222022d000f210e2002280003210f2002290007210b20022f00002111200241026a2d000021132002102c200341b2056a20133a0000200620113b0100200341b0096a41086a200d2903003703002003200b3700b7052003200f3600b305200341b0096a41106a20062903003703002003200e3a00bf05200341b0096a41186a2005290300370300200320032903a0053703b00941002102200341003602a805200342013703a0052010200341a0056a1067201041057421060340200720026a200341a0056a1091012006200241206a2202470d000b20032802a4052102200341b0096aad428080808080048420033502a80542208620032802a0052206ad84100102402002450d002006102c0b200341b0096a41186a200341b0086a41186a290300370300200341b0096a41106a200341b0086a41106a290300370300200341b0096a41086a200341b0086a41086a290300370300200320032903b0083703b009200341b0096a41012007201010f3022003418a043b01b0094100210541014100200341b0096a1092012004a7450d002007102c0b0c070b41a888c600200220101038000b2004a7450d052007102c0c050b200341b0096a41186a200341a0066a41186a290300370300200341b0096a41106a200341a0066a41106a290300370300200341b0096a41086a200341a0066a41086a290300370300200320032903a0063703b0094100210e200341b0096a2106410021050b02400240200e2010460d00200f21100c010b0240200f200e460d00200f21100c010b200f41016a2202200f490d02200f41017422072002200720024b1b221041ffffff3f712010470d02201041057422024100480d0202400240200f0d002002102a210d0c010b200d200f4105742002102e210d0b200d450d0f2003200d360280040b200d20054105746a220241206a2002200e20056b41057410dc051a200241186a200641186a290000370000200241106a200641106a290000370000200241086a200641086a29000037000020022006290000370000200341a0056a41186a22054200370300200341a0056a41106a22064200370300200341a0056a41086a22074200370300200342003703a00541e9eac100ad4280808080b0028410022202280003210d2002290007210420022d000f210f20022f00002111200241026a2d000021132002102c200320133a00a205200320113b01a0052003200f3a00af05200320043700a7052003200d3600a30541eae5c200ad4280808080f00084100222022d000f210d2002280003210f2002290007210420022f00002111200241026a2d000021132002102c200341b2056a20133a0000200620113b0100200341b0096a41086a2007290300370300200320043700b7052003200f3600b305200341b0096a41106a20062903003703002003200d3a00bf05200341b0096a41186a2005290300370300200320032903a0053703b0092003280280042102200341003602b808200342013703b008200e41016a2207200341b0086a106702402007200e490d00200e41057441206a210603402002200341b0086a109101200241206a2102200641606a22060d000b0b20032802b4082102200341b0096aad428080808080048420033502b80842208620032802b0082206ad84100102402002450d002006102c0b200341b0096a41186a200341a0066a41186a290300370300200341b0096a41106a200341a0066a41106a290300370300200341b0096a41086a200341a0066a41086a290300370300200320032903a0063703b00941002105410141002003280280042202200710f3022003410a3b01b00941014100200341b0096a1092012010450d002002102c0b4110210f0c020b1035000b419eb3c4002105410a210f0b410021020b024020094104470d002002200a45720d002008102c0b20050d00200041023a0008410021080c010b200041811a3b01082000200f36020420002005360200410021082000410a6a41003a00000b41012107410121054101210e4101210f41012110410121114101211341012114410121150c2a0b200341a8076a41206a200141286a290300370300200341a8076a41186a200141206a290300370300200341a8076a41106a200141186a290300370300200341a8076a41086a200141106a2903003703002003200141086a2903003703a807200341b0096a41206a200241206a290200370300200341b0096a41186a200241186a290200370300200341b0096a41106a200241106a290200370300200341b0096a41086a200241086a290200370300200320022902003703b009200341f8016a200341a8076a200341b0096a109e020240024020032802f80122020d00200041023a0008410021150c010b20032802fc01210620004181183b010820002002360200410021152000410a6a41003a0000200020063602040b41012107410121054101210e4101210f410121104101211141012113410121140c280b200341a8076a41206a200141246a290200370300200341a8076a41186a2001411c6a290200370300200341a8076a41106a200141146a290200370300200341a8076a41086a2001410c6a290200370300200320012902043703a807200341b0096a41206a200241206a290200370300200341b0096a41186a200241186a290200370300200341b0096a41106a200241106a290200370300200341b0096a41086a200241086a290200370300200320022902003703b009200341f0016a200341a8076a200341b0096a10f6020240024020032802f00122020d00200041023a0008410021140c010b20032802f401210620004181163b010820002002360200410021142000410a6a41003a0000200020063602040b41012107410121054101210e4101210f4101211041012111410121130c260b200341a8076a41206a200141246a290200370300200341a8076a41186a2001411c6a290200370300200341a8076a41106a200141146a290200370300200341a8076a41086a2001410c6a290200370300200320012902043703a807200341b0096a41206a200241206a290200370300200341b0096a41186a200241186a290200370300200341b0096a41106a200241106a290200370300200341b0096a41086a200241086a290200370300200320022902003703b009200341e8016a200341a8076a200341b0096a10f7020240024020032802e80122020d00200041023a0008410021130c010b20032802ec01210620004181143b010820002002360200410021132000410a6a41003a0000200020063602040b41012107410121054101210e4101210f41012110410121110c240b200341b0096a41306a200141386a290300370300200341b0096a41286a200141306a290300370300200341b0096a41206a200141286a290300370300200341b0096a41186a200141206a290300370300200341b0096a41106a200141186a290300370300200341b0096a41086a200141106a2903003703002003200141086a2903003703b009200341a8076a41206a200241206a290200370300200341a8076a41186a200241186a290200370300200341a8076a41106a200241106a290200370300200341a8076a41086a200241086a290200370300200320022902003703a807200341e0016a200341b0096a200341a8076a10f8020240024020032802e00122020d00200041023a0008410021110c010b20032802e401210620004181123b010820002002360200410021112000410a6a41003a0000200020063602040b41012107410121054101210e4101210f410121100c220b200141086a280200211120012802042116200341b0096a2001410c6a41840110db051a2002411a6a2901002104200241196a2d0000210f200241186a2d00002110200241166a2f01002113200241156a2d00002114200241146a2d00002115200241126a2f01002117200241116a2d0000211c200241106a2d000021072002410e6a2f010021082002410d6a2d0000210a2002410c6a2d000021092002410a6a2f0100210d200241096a2d0000210e200241046a2d0000211b200241026a2f0100211d200241056a280000210520022d0000210620022d0001210220034180046a200341b0096a41046a41800110db051a410220054102200241014622021b20061b21050240024002400240024020060d0020020d010b41d6b2c0002102410f2106024002400240024020050e050001020305000b200d410874200e7220094118747221022008410874200a7220074118747221060c040b41dd8cc6002102410e21060c030b41c3b2c0002102411321060c020b41b2b2c0002102411121060c010b200320043703c8082003200f3a00c708200320103a00c608200320133b01c408200320143a00c308200320153a00c208200320173b01c0082003201c3a00bf08200320073a00be08200320083b01bc082003200a3a00bb08200320093a00ba082003200d3b01b8082003200e3a00b708200320053600b3082003201b3a00b2082003201d3b01b008200341a8076a200341b0086a10f902024020032802c8072202450d00200341a0066a41106a200341e0076a290300370300200341a0066a41086a200341d8076a290300370300200341a0066a41186a200341e8076a290300370300200341c0066a200341f0076a280200360200200341c0036a41086a2206200341ac066a290200370300200341c0036a41106a2205200341b4066a290200370300200341c0036a41186a2207200341bc066a2902003703002003200341d0076a2903003703a006200320032902a4063703c003024020032802cc07450d002002102c0b20034180056a41086a200629030037030020034180056a41106a200529030037030020034180056a41186a2007290300370300200320032903c00337038005200341a0056a20034180046a41800110db051a200341e0036a20034180056a10a601200341a8076a20032802e003220620032802e80310a70120032d00a8072102200341b0086a200341a8076a41017241800110db051a0240024020024101460d00200341003a00a0060c010b200341013a00a006200341a0066a410172200341b0086a41800110db051a0b024020032802e403450d002006102c0b200341a0056a41206a2113200341e0056a211420034180066a2115200341c1066a2117200341e1066a211c20034181076a211b200341a0066a410172211d200341a8076a4101722105417021080340410021060240024002400240200841a4eec1006a280000220241e6e485f3064a220f0d00200241e2c289ab06460d0141012107200241e1ea91cb06470d0341202106201521070c030b200241e9dabdf306460d0141012107200241e7e485f306470d0241202106200341a0056a21070c020b41202106201321070c010b41202106201421070b200320063602b808200320073602b408200320023602b008200341c0036a200341b0086a10a801200341a8076a20032802c003220a20032802c80310d301200341a0036a41086a2209200541086a290000370300200341a0036a41106a220d200541106a290000370300200341a0036a41186a220e200541186a290000370300200320052900003703a0030240024020032d00a8074101470d00200341e0036a41186a2210200e290300370300200341e0036a41106a220e200d290300370300200341e0036a41086a220d2009290300370300200320032903a0033703e003024020032802c403450d00200a102c0b200341a8076a41186a2010290300370300200341a8076a41106a200e290300370300200341a8076a41086a200d290300370300200320032903e0033703a807200341a8076a20034180056a412010dd05450d0141bfbbc1002102411821060c040b20032802c403450d00200a102c0b0240024020032d00a0064101470d004100210a410121090240024002400240200f0d00200241e2c289ab06460d01200241e1ea91cb06470d034120210a201b21090c030b200241e9dabdf306460d01200241e7e485f306470d024120210a201d21090c020b4120210a201721090c010b4120210a201c21090b02402006200a470d0020072009460d0220072009200610dd05450d020b2003200a3602b007200320093602ac07200320023602a807200341b0086a200341a8076a10a80120033502b80842208620032802b008220aad84100520032802b408450d00200a102c0b200320063602b007200320073602ac07200320023602a807200341b0086a200341a8076a10a80120032802b0082102200320032802b8083602ac07200320023602a80720034180056a200341a8076a10a10220032802b408450d002002102c0b200841046a22080d000b200341b0086a20034180056a10a60120032802b008210220033502b8082104200341003602b007200342013703a807200341a0056a200341a8076a109101200341c0056a200341a8076a109101200341e0056a200341a8076a10910120034180066a200341a8076a10910120032802ac07210620044220862002ad8420033502b00742208620032802a8072205ad84100102402006450d002005102c0b024020032802b408450d002002102c0b2011450d022016102c0c020b4198bbc1002102412721060b02402011450d002016102c0b2002450d0020004181103b01082000200636020420002002360200410021102000410a6a41003a00000c010b200041023a0008410021100b41012107410121054101210e4101210f0c200b200341b0096a41306a200141386a290300370300200341b0096a41286a200141306a290300370300200341b0096a41206a200141286a290300370300200341b0096a41186a200141206a290300370300200341b0096a41106a200141186a290300370300200341b0096a41086a200141106a2903003703002003200141086a2903003703b009200341a8076a41206a200241206a290200370300200341a8076a41186a200241186a290200370300200341a8076a41106a200241106a290200370300200341a8076a41086a200241086a290200370300200320022902003703a807200341a0066a200341b0096a200341a8076a10fa02410c21020240024020032802a0062206410c470d00200041023a00080c010b4195e2c5002105410b210702400240024002400240024002400240024002400240024020060e0c000102030405060708090a0b000b20032802a4062105200341a8066a2802002102410021070c0a0b41dd8cc6002105410e2102410121070c090b4188e2c5002105410d2102410221070c080b4180e2c500210541082102410321070c070b41f3e1c5002105410d2102410421070c060b41e6e1c5002105410d2102410521070c050b41dde1c500210541092102410621070c040b41d1e1c5002105410721070c030b41c3e1c5002105410e2102410821070c020b41b2e1c500210541112102410921070c010b41a1e1c500210541112102410a21070b200041810e3b010820002002360204200020053602002000410a6a20073a00000b4100210f41012107410121054101210e0c1e0b2003419c036a41026a22072001410f6a2d00003a000020034180046a41086a22082001411c6a29020037030020034180046a41106a220a200141246a29020037030020034180046a41186a22092001412c6a280200360200200320012f000d3b019c032003200141146a29020037038004200141c8006a2903002112200141c0006a290300212c200141386a290300210c2002411a6a2901002104200241196a2d0000210f200241186a2d00002110200241166a2f01002111200241156a2d00002113200241146a2d00002114200241126a2f0100211541112106200241116a2d00002116200241106a2d000021172002410e6a2f0100211c2002410d6a2d0000211b2002410c6a2d0000211d2002410a6a2f01002118200241096a2d00002119200241086a2d0000211a200241066a2f0100212b200241056a2d0000211f200241046a2d00002120200241026a2f01002121200141106a28020021052001410c6a2d00002122200141306a290300210b20022d0001210d20022d0000210e0240024002400240024002400240024002400240024002400240024002400240200141086a2802000e050001020304000b200341b0096a41146a4101360200200342013702b409200341fcc4c5003602b009200341043602a406200341f4c4c5003602a0062003200341a0066a3602c009200341b0096a4184c5c5001041000b200341a0066a41086a2008290300370300200341a0066a41106a200a290300370300200341a0066a41186a2009280200360200200320032f019c033b01800520032003290380043703a006200320072d00003a008205200320043703b8052003200f3a00b705200320103a00b605200320113b01b405200320133a00b305200320143a00b205200320153b01b005200320163a00af05200320173a00ae052003201c3b01ac052003201b3a00ab052003201d3a00aa05200320183b01a805200320193a00a70520034102202b410874201f72201a411874724102200d41ff017141014622061b200e41ff017122021b22073600a305200320203a00a205200320213b01a0050240024020020d0020060d010b41d6b2c0002102410f210620070e050416050617040b200341a8076a41186a200341a0056a41186a290300370300200341a8076a41106a200341a0056a41106a290300370300200341a8076a41086a200341a0056a41086a290300370300200320032903a0053703a8070240202241ff01714101460d00200341a0066a41106a290300210420032f01800520032d00820541107472210220032903a8062212420888a721062012422088a721072012a7210820032802b806210a20032903a00621120c130b200341b0086a200541067610910220032802b00821090240024020032802b8082005413f7122024b0d004100210d0c010b200920024105746a22052f0010200541126a2d000041107472210620052f0000200541026a2d000041107472210220052d001f210a200529001721042005280013210720052d000f210820052900072112200528000321054101210d0b024020032802b408450d002009102c0b200d0d12410121090c130b200341a0066a41086a2008290300370300200341a0066a41106a200a290300370300200341a0066a41186a2009280200360200200320032f019c033b01b00820032003290380043703a006200320072d00003a00b20841b2b2c0002102200d200e7241ff01710d1502400240202241ff01714101460d00200341a0066a41106a290300210420032f01b00820032d00b20841107472210220032903a806222d420888a72106202d422088a72107202da7210820032802b806210a20032903a006212d0c010b200341b0096a200541067610910220032802b00921090240024020032802b8092005413f7122024b0d004100210d0c010b200920024105746a22052f0010200541126a2d000041107472210620052f0000200541026a2d000041107472210220052d001f210a200529001721042005280013210720052d000f21082005290007212d200528000321054101210d0b024020032802b409450d002009102c0b200d450d150b200320063b01b807200341a8076a41126a20064110763a00002003200a3a00c707200320043700bf07200320073600bb07200320083a00b7072003202d3700af07200320053600ab07200320023b01a807200320024110763a00aa07418be9c500ad4280808080800184100222022d000f2106200229000721042002280003210520022f00002107200241026a2d000021082002102c41d6b5c000ad4280808080b00184100222022d000f210a2002290007212d2002280003210920022f0000210d200241026a2d0000210e2002102c200341a0056a200341a8076a109f0141c000102a2202450d0d20022004370007200220053600032002200720084110747222053b0000200241026a20054110763a0000200220063a000f2002202d370017200220093600132002200d200e4110747222063b0010200241126a20064110763a00002002200a3a001f200220032903a005370020200241286a200341a0056a41086a290300370000200241306a200341a0056a41106a290300370000200241386a200341a0056a41186a290300370000200341b8016a200241c000109e01200341b8016a41106a290300212f20032903c001210420032802b80121062002102c4200200b200b428080e983b1de16544100200c501b22021b222d2004420020061b222e564200200c20021b2204202f420020061b220b562004200b5122021b0d06202d202e542004200b5420021b450d0c200341c0036a41186a22054200370300200341c0036a41106a22024200370300200341c0036a41086a22074200370300200342003703c003418be9c500ad4280808080800184220c1002220628000321082006290007212f20062d000f210a20062f00002109200641026a2d0000210d2006102c2003200d3a00c203200320093b01c0032003200a3a00cf032003202f3700c703200320083600c30341c9b5c000ad4280808080d00184222f100222062d000f21082006280003210a2006290007213020062f00002109200641026a2d0000210d2006102c200341d2036a220e200d3a0000200220093b0100200341a0036a41086a22092007290300370300200320303700d7032003200a3600d303200341a0036a41106a220a2002290300370300200320083a00df03200341a0036a41186a220d2005290300370300200320032903c0033703a003200341a0016a200341a0036a4120109e01200341a0016a41106a290300213020032903a801213120032802a0012108200542003703002002420037030020074200370300200342003703c003200c10022206280003210f2006290007210c20062d000f211020062f00002111200641026a2d000021132006102c200320133a00c203200320113b01c003200320103a00cf032003200c3700c7032003200f3600c303202f100222062d000f210f200628000321102006290007210c20062f00002111200641026a2d000021132006102c200e20133a0000200220113b0100200920072903003703002003200c3700d703200320103600d303200a20022903003703002003200f3a00df03200d2005290300370300200320032903c0033703a003200342002030420020081b220c202e202d54ad2004200b7d7c7c2031420020081b220b202e202d7d222f54ad7d222e200b202f7d222f200b56202e200c56202e200c511b22021b3703b80920034200202f20021b3703b009200341b0096a2102200341a0036a21060c0b0b200141e0006a2903002104200141d8006a290300212d200141d0006a290300212e200341a0066a41086a2008290300370300200341a0066a41106a200a290300370300200341a0066a41186a2009280200360200200320032f019c033b018005200320072d00003a00820520032003290380043703a00641b2b2c0002102200d200e7241ff01710d140240202241ff01714101460d00200341a0066a41106a290300212f20032f01800520032d00820541107472210220032903a8062230420888a721062030422088a721072030a7210820032802b806210a20032903a00621300c090b200341b0096a200541067610910220032802b00921090240024020032802b8092005413f7122024b0d004100210d0c010b200920024105746a22052f0010200541126a2d000041107472210620052f0000200541026a2d000041107472210220052d001f210a2005290017212f2005280013210720052d000f210820052900072130200528000321054101210d0b024020032802b409450d002009102c0b200d0d08410121090c090b200341b0086a41086a2008290300370300200341b0086a41106a200a290300370300200341b0086a41186a2009280200360200200320032f019c033b01800520032003290380043703b008200320072d00003a008205200320043703b8052003200f3a00b705200320103a00b605200320113b01b405200320133a00b305200320143a00b205200320153b01b005200320163a00af05200320173a00ae052003201c3b01ac052003201b3a00ab052003201d3a00aa05200320183b01a805200320193a00a70520034102202b410874201a41187472201f724102200d41ff017141014622061b200e41ff017122021b22073600a305200320203a00a205200320213b01a005024020020d0020060d040b41d6b2c0002102410f210620070e050012010213000b20032800a705210220032800ab0521060c120b41c3b2c0002102411321060c110b41b2b2c0002102411121060c100b200341a8076a41186a200341a0056a41186a290300370300200341a8076a41106a200341a0056a41106a290300370300200341a8076a41086a200341a0056a41086a290300370300200320032903a0053703a8070240202241ff01714101460d00200341b0086a41106a290300210420032f01800520032d00820541107472210220032903b8082212420888a721062012422088a721072012a7210820032802c808210a20032903b00821120c020b200341a0066a200541067610910220032802a00621090240024020032802a8062005413f7122024b0d004100210d0c010b200920024105746a22052f0010200541126a2d000041107472210620052f0000200541026a2d000041107472210220052d001f210a200529001721042005280013210720052d000f210820052900072112200528000321054101210d0b024020032802a406450d002009102c0b200d0d01410121090c020b200341c0036a41186a22054200370300200341c0036a41106a22024200370300200341c0036a41086a22074200370300200342003703c003418be9c500ad4280808080800184220c1002220628000321082006290007212f20062d000f210a20062f00002109200641026a2d0000210d2006102c2003200d3a00c203200320093b01c0032003200a3a00cf032003202f3700c703200320083600c30341c9b5c000ad4280808080d00184222f100222062d000f21082006280003210a2006290007213020062f00002109200641026a2d0000210d2006102c200341d2036a220e200d3a0000200220093b0100200341a0036a41086a22092007290300370300200320303700d7032003200a3600d303200341a0036a41106a220a2002290300370300200320083a00df03200341a0036a41186a220d2005290300370300200320032903c0033703a00320034188016a200341a0036a4120109e0120034188016a41106a290300213020032903900121312003280288012108200542003703002002420037030020074200370300200342003703c003200c10022206280003210f2006290007210c20062d000f211020062f00002111200641026a2d000021132006102c200320133a00c203200320113b01c003200320103a00cf032003200c3700c7032003200f3600c303202f100222062d000f210f200628000321102006290007210c20062f00002111200641026a2d000021132006102c200e20133a0000200220113b0100200920072903003703002003200c3700d703200320103600d303200a20022903003703002003200f3a00df03200d2005290300370300200320032903c0033703a0032003427f2030420020081b220c2004200b7d202d202e54ad7d7c2031420020081b220b202d202e7d7c222e200b542202ad7c220b2002200b200c54200b200c511b22021b3703b8092003427f202e20021b3703b009200341b0096a2102200341a0036a21060c040b410021090b200320063b01f003200341f2036a20064110763a00002003200a3a00ff03200320043700f703200320073600f303200320083a00ef03200320123700e703200320053600e303200320023b01e003200320024110763a00e20320090d0b200341b0096a41186a200341e0036a41186a290300370300200341b0096a41106a200341e0036a41106a290300370300200341b0096a41086a200341e0036a41086a290300370300200320032903e0033703b009200341d8016a200341a8076a200341b0096a200b200c410010cd01024020032802d8012202450d0020032802dc0121060c0d0b410021020c0c0b410021090b200320063b01b005200341b2056a20064110763a00002003200a3a00bf052003202f3700b705200320073600b305200320083a00af05200320303700a705200320053600a305200320023b01a005200320024110763a00a20520090d09200b422088a72105200341a8076a41186a200341a0056a41186a290300370300200341a8076a41106a200341a0056a41106a290300370300200341a8076a41086a200341a0056a41086a290300370300200320032903a0053703a807024002400240200ba741ff01714101460d00200b420888a72102202c420888a72106202c422088a72107202ea7210a202ca721080c010b200341b0086a200b422688a710910220032802b00821090240024020032802b8082005413f7122054b0d004100210d202f21122030210c0c010b200920054105746a22052f0010200541126a2d000041107472210620052f0000200541026a2d000041107472210220052d001f210a200529001721122005280013210720052d000f21082005290007210c200528000321054101210d0b024020032802b408450d002009102c0b200d0d00410121090c010b410021090b200320063b01f003200341f2036a20064110763a00002003200a3a00ff03200320123700f703200320073600f303200320083a00ef032003200c3700e703200320053600e303200320023b01e003200320024110763a00e20320090d09200341b0096a41186a200341e0036a41186a290300370300200341b0096a41106a200341e0036a41106a290300370300200341b0096a41086a200341e0036a41086a290300370300200320032903e0033703b009200341d0016a200341a8076a200341b0096a202d2004410110cd0120032802d0012202450d0820032802d40121060c0a0b2006ad42808080808004842002ad428080808080028410010b200341a8076a202d200410a201418be9c500ad4280808080800184100222022d000f21062002290007210b2002280003210520022f00002107200241026a2d000021082002102c41e1b5c000ad4280808080f00184100222022d000f210a2002290007210c2002280003210920022f0000210d200241026a2d0000210e2002102c200341e0036a200341a8076a109f0141c000102a2202450d002002200b370007200220053600032002200720084110747222053b0000200241026a20054110763a0000200220063a000f2002200c370017200220093600132002200d200e4110747222063b0010200241126a20064110763a00002002200a3a001f200220032903e003370020200241286a200341e0036a41086a290300370000200241306a200341e0036a41106a290300370000200241386a200341e0036a41186a290300370000200341f0006a200241c000109e01200341f0006a41106a290300212e2003290378210b200328027021062002102c4200202c202c428080e983b1de165441002012501b22021b220c200b420020061b222c564200201220021b220b202e420020061b221256200b20125122021b0d01200c202c54200b20125420021b450d03200341c0036a41186a22054200370300200341c0036a41106a22024200370300200341c0036a41086a22074200370300200342003703c003418be9c500ad4280808080800184222e1002220628000321082006290007212f20062d000f210a20062f00002109200641026a2d0000210d2006102c2003200d3a00c203200320093b01c0032003200a3a00cf032003202f3700c703200320083600c30341c9b5c000ad4280808080d00184222f100222062d000f21082006280003210a2006290007213020062f00002109200641026a2d0000210d2006102c200341d2036a220e200d3a0000200220093b0100200341a0036a41086a22092007290300370300200320303700d7032003200a3600d303200341a0036a41106a220a2002290300370300200320083a00df03200341a0036a41186a220d2005290300370300200320032903c0033703a003200341d8006a200341a0036a4120109e01200341d8006a41106a29030021302003290360213120032802582108200542003703002002420037030020074200370300200342003703c003202e10022206280003210f2006290007212e20062d000f211020062f00002111200641026a2d000021132006102c200320133a00c203200320113b01c003200320103a00cf032003202e3700c7032003200f3600c303202f100222062d000f210f200628000321102006290007212e20062f00002111200641026a2d000021132006102c200e20133a0000200220113b0100200920072903003703002003202e3700d703200320103600d303200a20022903003703002003200f3a00df03200d2005290300370300200320032903c0033703a003200342002030420020081b222e202c200c54ad200b20127d7c7c2031420020081b2212202c200c7d222f54ad7d222c2012202f7d222f201256202c202e56202c202e511b22021b3703b80920034200202f20021b3703b009200341b0096a2102200341a0036a21060c020b1033000b200341c0036a41186a22054200370300200341c0036a41106a22024200370300200341c0036a41086a22074200370300200342003703c003418be9c500ad4280808080800184222e1002220628000321082006290007212f20062d000f210a20062f00002109200641026a2d0000210d2006102c2003200d3a00c203200320093b01c0032003200a3a00cf032003202f3700c703200320083600c30341c9b5c000ad4280808080d00184222f100222062d000f21082006280003210a2006290007213020062f00002109200641026a2d0000210d2006102c200341c0036a41126a220e200d3a0000200220093b0100200341a0036a41086a22092007290300370300200320303700d7032003200a3600d303200341a0036a41106a220a2002290300370300200320083a00df03200341a0036a41186a220d2005290300370300200320032903c0033703a003200341c0006a200341a0036a4120109e01200341c0006a41106a29030021302003290348213120032802402108200542003703002002420037030020074200370300200342003703c003202e10022206280003210f2006290007212e20062d000f211020062f00002111200641026a2d000021132006102c200320133a00c203200320113b01c003200320103a00cf032003202e3700c7032003200f3600c303202f100222062d000f210f200628000321102006290007212e20062f00002111200641026a2d000021132006102c200e20133a0000200220113b0100200920072903003703002003202e3700d703200320103600d303200a20022903003703002003200f3a00df03200d2005290300370300200320032903c0033703a0032003427f2030420020081b222e200b20127d200c202c54ad7d7c2031420020081b2212200c202c7d7c222c2012542202ad7c221220022012202e542012202e511b22021b3703b8092003427f202c20021b3703b009200341b0096a2102200341a0036a21060b2006ad42808080808004842002ad428080808080028410010b200341a8076a200c200b10aa01200341f8096a200b370300200341f0096a200c370300200341e8096a2004370300200341e0096a202d370300200341b0096a41086a41033a0000200341b9096a20032903a807370000200341c1096a200341a8076a41086a290300370000200341c9096a200341b8076a290300370000200341d1096a200341c0076a290300370000200341033a00b0094100210241014100200341b0096a1092010c040b410021090b200320063b01f003200341f2036a20064110763a00002003200a3a00ff03200320043700f703200320073600f303200320083a00ef03200320123700e703200320053600e303200320023b01e003200320024110763a00e20320090d01200341b0096a41186a200341e0036a41186a290300370300200341b0096a41106a200341e0036a41106a290300370300200341b0096a41086a200341e0036a41086a290300370300200320032903e0033703b009200341386a200341a8076a200341b0096a200b200c410110cd0120032802382202450d00200328023c21060c020b410021020c010b41dd8cc6002102410e21060b024020020d00200041023a00080c010b200041810c3b010820002006360204200020023602002000410a6a41003a00000b41012107410121050c110b024020032802bc092206450d0020032802b4092102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102c0c030b2002410c6a280200450d02200241086a280200102c0c020b2002410c6a280200450d01200241086a280200102c0c010b200241086a280200450d00200241046a280200102c0b200241246a21022006415c6a22060d000b0b024020032802b809450d0020032802b409102c0b024020072011460d00034020072802042208450d01200741086a280200210e02402007410c6a2802002202450d00200241246c21062008210203400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102c0c030b2002410c6a280200450d02200241086a280200102c0c020b2002410c6a280200450d01200241086a280200102c0c010b200241086a280200450d00200241046a280200102c0b200241246a21022006415c6a22060d000b0b200741f0006a21070240200e450d002008102c0b20072011470d000b0b0240200f450d00200a102c0b2004a7450d052014102c0c050b20072011460d00034020072802042208450d01200741086a280200210902402007410c6a2802002202450d00200241246c21062008210203400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102c0c030b2002410c6a280200450d02200241086a280200102c0c020b2002410c6a280200450d01200241086a280200102c0c010b200241086a280200450d00200241046a280200102c0b200241246a21022006415c6a22060d000b0b200741f0006a210702402009450d002008102c0b20072011470d000b0b0240200f450d00200a102c0b41a4c6c500ad4280808080a001841002220228000321062002290007210b20022d000f210520022f00002107200241026a2d000021082002102c41f889c200ad4280808080e0008410022202280003210a2002290007210c20022d000f210920022f0000210d200241026a2d0000210e2002102c200341c2096a200e3a00002003200d3b01c009200320083a00b209200320073b01b009200320093a00cf092003200c3700c7092003200a3600c309200320053a00bf092003200b3700b709200320063600b309200341a8076a20032802c00322022004422088a710e701201220033502b00742208620032802a8072206ad841001024020032802ac07450d002006102c0b02402004a7450d002002102c0b200041023a00084100210e0c040b2006450d010b200a200641f0006c6a2108200a2107034002402007410c6a2802002206450d0020072802042102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102c0c030b2002410c6a280200450d02200241086a280200102c0c020b2002410c6a280200450d01200241086a280200102c0c010b200241086a280200450d00200241046a280200102c0b200241246a21022006415c6a22060d000b0b200741f0006a21020240200741086a280200450d002007280204102c0b2002210720022008470d000b0b200f450d00200a102c0b20004181083b01082000200d360204200020093602004100210e2000410a6a41003a00000b41012107410121050c0a0b2005102c0b0240024002402007417e6a220241054b0d000240024002400240024020020e06000501020304000b41000d062004a70d050c060b41000d052004a70d040c050b200a450d0402402004422088a72202450d00200241186c21062005210203400240200241046a280200450d002002280200102c0b0240200241106a280200450d002002410c6a280200102c0b200241186a2102200641686a22060d000b0b2004a70d030c040b2006450d0302402004422088a72202450d002002410c6c21062005210203400240200241046a280200450d002002280200102c0b2002410c6a2102200641746a22060d000b0b2004a70d020c030b41000d022004a70d010c020b02402007417f6a220241024b0d0020020e03020002020b2004a7450d010b2005102c0b41d6b2c0002102410f21064104210720080e06010204030500010b200041023a0008410121050c050b410021070c030b41dd8cc6002102410e2106410121070c020b41b2b2c000210241112106410321070c010b41c3b2c000210241132106410221070b41012105200041013b010820002006360204200020023602002000410a6a20073a00000b410021070b4101210e0b4101210f0b410121100b410121110b410121130b410121140b410121150b410121080b4101210a0b410121090b41012100410121060b4101210d0b024002402001280200220241134b0d000240024002400240024002400240024002400240024002400240024020020e1400010e0f020e0f030405060708090f0a0f0b0c0d000b2007450d0e200141086a10fb020c0e0b2005450d0d02402001410c6a2802002206450d002001280204210220064190016c210603402002107320024190016a2102200641f07e6a22060d000b0b200141086a280200450d0d2001280204102c0c0d0b200e450d0c02402001410c6a2802002202450d0020012802042207200241f0006c6a2100034002402007410c6a2802002206450d0020072802042102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102c0c030b2002410c6a280200450d02200241086a280200102c0c020b2002410c6a280200450d01200241086a280200102c0c010b200241086a280200450d00200241046a280200102c0b200241246a21022006415c6a22060d000b0b200741f0006a21020240200741086a280200450d002007280204102c0b2002210720022000470d000b0b200141086a280200450d0c2001280204102c0c0c0b200f450d0b0240200141086a2d00002202410f4b0d00410120027441bfbf03710d0c024020024106470d00200141106a280200450d0d2001410c6a280200102c0c0d0b200141106a280200450d0c2001410c6a280200102c0c0c0b200141146a280200450d0b200141106a280200102c0c0b0b2010450d0a200141086a280200450d0a2001280204102c0c0a0b2011450d09200141086a2d0000416d6a220241014b0d090240024020020e020001000b200141106a280200450d0a2001410c6a280200102c0c0a0b200141106a280200450d092001410c6a280200102c0c090b2013450d0820012d0004417f6a220241024b0d0802400240024020020e03000102000b2001410c6a280200450d0a200141086a280200102c0c0a0b200141086a220228020010fc022002280200102c0c090b2001410c6a220228020010fc022002280200102c0c080b2014450d0720012d0004417f6a220241024b0d0702400240024020020e03000102000b2001410c6a280200450d09200141086a280200102c0c090b200141086a220228020010fc022002280200102c0c080b2001410c6a220228020010fc022002280200102c0c070b2015450d06200141086a2802004101470d06200141106a280200450d062001410c6a280200102c0c060b2008450d0520012d00044104470d052001410c6a280200450d05200141086a280200102c0c050b200a450d04200141086a280200450d042001280204102c0c040b2009450d03200141086a2d0000417e6a220241024b0d0302400240024020020e03000102000b200141106a280200450d052001410c6a280200102c0c050b200141346a280200450d04200141306a280200102c0c040b200141306a280200450d032001412c6a280200102c0c030b2000450d0202402001280204220241024b0d00024020020e03040004040b200141086a220228020010fc022002280200102c0c030b2001412c6a220228020010fc022002280200102c0c020b2006450d0102402001410c6a280200450d00200141086a280200102c0b02402001411c6a2802002206450d00200141146a28020021022006410c6c210603400240200241046a280200450d002002280200102c0b2002410c6a2102200641746a22060d000b0b200141186a280200450d012001280214102c0c010b200d450d0002402001280204220241034b0d00024020020e0402000202020b2001410c6a280200450d01200141086a280200102c0c010b200141306a280200450d002001412c6a280200102c0b200341c00a6a24000bb50404057f017e017f017e0240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a3602000240200441037122064103460d00024002400240024020060e03000102000b2004410276ad21070c020b41012106024020050d000c050b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d04200141fcff0371410276ad21070c010b410121060240200541034f0d000c040b200341036a2d0000210520032f0001210820012002417c6a3602042001200341046a3602002008200541107472410874200472220141808004490d032001410276ad21070b410021060c020b02402004410276220841044b0d000240024020080e050002020201000b20054104490d022003350001210720012002417b6a3602042001200341056a36020020074280808080045421060c030b20054108490d01200329000121072001200241776a3602042001200341096a3602002007428080808080808080015421060c020b200841046a220541084b0d002002417e6a2102200341026a2103410021044200210741012106034002402002417f470d000c030b2003417f6a310000210920012002360204200120033602002002417f6a2102200341016a210320092004410374413871ad862007842107200441016a220441ff01712005490d000b2007427f412820084103746b413871ad885821060c010b410121060b2000200737030820002006ad3703000b810903017f017e057f230041e0006b22022400024002400240024020002903002203423f560d0002400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d04200041017422052004200520044b1b22054100480d040240024020000d002005102a21040c010b200128020020002005102e21040b2004450d0320012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a2003a74102743a00000c010b0240200342808001540d0002402003428080808004540d0002404108200379a741037622056b4104490d0002400240200141046a280200200141086a2802002204460d00200128020021060c010b200441016a22072004490d06200441017422062007200620074b1b22074100480d060240024020040d002007102a21060c010b200128020020042007102e21060b2006450d0520012006360200200141046a2007360200200141086a28020021040b200141086a2207200441016a360200200620046a411320054102746b3a0000200220002903002203370308200541786a2104200141046a2106034002400240200628020020072802002200460d00200128020021050c010b200041016a22052000490d07200041017422082005200820054b1b22084100480d070240024020000d002008102a21050c010b200128020020002008102e21050b2005450d062001200536020020062008360200200728020021000b2007200041016a360200200520006a2003a73a000020034208882103200441016a22002004492105200021042005450d000b200220033703082003500d03200241286a41146a4109360200200241346a410e360200200241106a41146a41033602002002200241086a360240200241d0e1c10036024420024203370214200241ec9fc6003602102002410e36022c200242043703582002420137024c200241d8e1c1003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a4184c5c5001041000b4196e1c100413641acfec5001036000b02400240200141046a2802002204200141086a28020022006b4104490d00200128020021040c010b200041046a22052000490d04200441017422002005200020054b1b22004100480d040240024020040d002000102a21040c010b200128020020042000102e21040b2004450d0320012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a2003a74102744102723600000c010b02400240200141046a2802002204200141086a28020022006b4102490d00200128020021040c010b200041026a22052000490d03200441017422002005200020054b1b22004100480d030240024020040d002000102a21040c010b200128020020042000102e21040b2004450d0220012004360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200420006a2003a74102744101723b00000b200241e0006a24000f0b1033000b1035000bbf0202027f017e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d01200441012001104221000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000b20024180016a240020000f0b20034180011047000b20034180011047000b810605027f027e017f027e027f230041a0016b220224002000280200210002400240024002400240024002400240200128020022034110710d00200041086a29030021042000290300210520034120710d0220054290ce005441002004501b450d012005a72103412721000c060b200041086a2903002105200029030021044180012100024003402000450d01200241206a20006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a210020044204882005423c8684220420054204882205844200520d000b0b20004181014f0d022001410141b087c0004102200241206a20006a41800120006b104521000c060b41272100200241186a21060340200241106a200520044290ce00420010e1052002200229031022072006290300220842f0b17f427f10e005200241206a20006a2203417c6a200520022903007ca7220941ffff037141e4006e220a41017441c284c0006a2f00003b00002003417e6a200a419c7f6c20096a41ffff037141017441c284c0006a2f00003b0000200542ffc1d72f56210320044200522109200450210a2000417c6a2100200721052008210420032009200a1b0d000c040b0b4180012100024003402000450d01200241206a20006a417f6a2005a7410f712203413072200341376a2003410a491b3a00002000417f6a210020054204882004423c8684220520044204882204844200520d000b0b20004181014f0d012001410141b087c0004102200241206a20006a41800120006b104521000c040b20004180011047000b20004180011047000b2007a721030b02400240200341e3004a0d00200321090c010b200241206a2000417e6a22006a2003200341ffff037141e4006e2209419c7f6c6a41ffff037141017441c284c0006a2f00003b00000b024002402009410a480d00200241206a2000417e6a22006a200941017441c284c0006a2f00003b00000c010b200241206a2000417f6a22006a200941306a3a00000b2001410141dc9ec6004100200241206a20006a412720006b104521000b200241a0016a240020000b130020004105360204200041b0e2c1003602000b3400200041e9eac10036020420004100360200200041146a4101360200200041106a41fceac100360200200041086a42133702000b8d0301027f230041e0006b22032400200341003a0005024002402000413f4b0d0041012104200341013a0005200320004102743a00000c010b02400240200041808001490d0020004180808080044f0d0141042104200341043a0005200320004102744102723602000c020b41022104200341023a0005200320004102744101723b01000c010b41052104200341053a0005200341033a0000200320003600010b024002402001280200220028020822012002490d0020002802002100200320023602082003200436020c20042002470d0120002003200210db051a200341e0006a24000f0b20022001103f000b200341286a41146a4109360200200341346a410c360200200341106a41146a410336020020034203370214200341ec9fc6003602102003410c36022c2003200341086a36024020032003410c6a360244200342043703582003420137024c200341c0a0c6003602482003200341286a3602202003200341c8006a3602382003200341c4006a3602302003200341c0006a360228200341106a41fca0c6001041000bb60201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001104221000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000b20024180016a240020000f0b20044180011047000b20044180011047000b130020004102360204200041ccb0c0003602000b130020004101360204200041f8eac5003602000b3400200041a4c6c50036020420004100360200200041146a4103360200200041106a41f087c200360200200041086a420a3702000b130020004101360204200041e486c2003602000b13002000410136020420004180dcc2003602000b130020004104360204200041f8b5c0003602000b130020004103360204200041b4f9c2003602000b130020004101360204200041a0dec5003602000b13002000411036020420004184b5c4003602000b130020004106360204200041f4ddc2003602000b13002000410536020420004184fcc0003602000b130020004106360204200041b8dbc1003602000b13002000410336020420004190d7c5003602000b130020004106360204200041a8bfc1003602000b130020004106360204200041c0e4c3003602000b130020004103360204200041e4a3c5003602000b13002000410336020420004190a6c5003602000b130020004101360204200041d8dbc5003602000b130020004105360204200041b8ddc3003602000bca2504027f027e087f037e230041b00d6b22072400024002400240024002400240024002402001280230200128024022082802b801460d002004420020042903082209200841c0006a2903007d220a200a20095622081b37030820080d02200741186a41186a200141e8006a290000370300200741186a41106a200141e0006a290000370300200741186a41086a200141d8006a29000037030020072001290050370318200741b0026a41186a220b2006280208220cad4220862006350200841006220841186a290000370300200741b0026a41106a220d200841106a290000370300200741b0026a41086a220e200841086a290000370300200720082900003703b0022008102c200741d00a6a41186a200b290300370300200741d00a6a41106a200d290300370300200741d00a6a41086a200e290300370300200720072903b0023703d00a4120102a22080d010c070b200041cf8bc20036020420004101360200200041086a41293602002000410c6a2006290200370200200041146a200641086a2802003602000c050b20082005290000370000200841186a200541186a290000370000200841106a200541106a290000370000200841086a200541086a2900003700002008412041c000102e2208450d05200820072903d00a370020200841386a200741d00a6a41186a290300370000200841306a200741d00a6a41106a290300370000200841286a200741d00a6a41086a290300370000200841c000418001102e2208450d0520082007290318370040200841d8006a200741186a41186a290300370000200841d0006a200741186a41106a290300370000200841c8006a200741186a41086a290300370000200741b0026a41186a220d2008ad4280808080800c841006220b41186a290000370300200741b0026a41106a220e200b41106a290000370300200741b0026a41086a220f200b41086a2900003703002007200b2900003703b002200b102c200741386a41186a220b200d290300370300200741386a41106a220d200e290300370300200741386a41086a220e200f290300370300200720072903b0023703382008102c20062902002109200741d8006a41d8006a200e290300370300200741b8016a200d290300370300200741c0016a200b29030037030020074194016a410036020020074184016a41f88bc200360200200741f8006a4200370300200741f4006a221041d0e1c10036020020072001360260200741d8006a41286a200141186a2211360200200720072903383703a8012007420837028c012007410036027020074100360264200720012802483602a00120072001290340370398012007200128023041016a360288012001290300210a2007200128024c3602a4012007200a370358200741c8016a41186a200541186a290000370300200741c8016a41106a200541106a290000370300200741c8016a41086a200541086a29000037030020074101360270200720052900003703c8012011200741386a10fd01210620072007280270417f6a2208360270024002400240024020060d0020080d012007417f36027020074190026a41186a200741386a41186a29030037030020074190026a41106a200741386a41106a29030037030020074190026a41086a200741386a41086a2903003703002007200729033837039002024002402007280274220e41d0e1c100460d002007280278210f0c010b4100210f200741d00a6a410041e00210da051a200741b0026a410041a00810da051a41880b102a220e450d0a200e41003b0106200e4100360200200e41086a200741d00a6a41e00210db051a200e41e8026a200741b0026a41a00810db051a200741003602782007200e3602740b024002400340200e41086a2108200e2f0106221241057421064100210b0240024003402006450d0120074190026a2008412010dd05220d450d02200641606a2106200b41016a210b200841206a2108200d417f4a0d000b200b417f6a21120b200f450d02200f417f6a210f200e20124102746a41880b6a280200210e0c010b0b200e200b41e0006c6a41e8026a21060c010b200741f0016a41186a20074190026a41186a290300220a370300200741f0016a41106a20074190026a41106a2903002213370300200741f0016a41086a20074190026a41086a2903002214370300200720072903900222153703f001200741ec0a6a2014370200200741d00a6a41246a2013370200200741fc0a6a200a3702002007200741d8006a41246a3602e00a200720123602dc0a200720103602d80a2007200e3602d40a200741003602d00a200720153702e40a200741e4026a4200370200200741003a00ec02200742003703b002200741003a008d03200741d0e1c1003602e002200742003703c802200741d00a6a200741b0026a10800221060b200741e0016a290300210a20064201370318200641013a003c200641286a427f370300200641206a427f3703002006413d6a20072903c801370000200641c5006a200741d0016a290300370000200641cd006a200741d8016a290300370000200641d5006a200a3700002007200728027041016a360270200741106a20044101200741186a200741386a20022003200741d8006a10de022007280210220e0d02200741b0026a200520072802a00128020010df02024020072802b0024101470d002009422088a72106200741b8026a280200210520072802b402210e2009a721010c080b20074190026a41186a200741b0026a410472220641186a2802002208360200200741d00a6a41106a200641086a290200370300200741d00a6a41186a200641106a290200370300200741f00a6a2008360200200741063602d40a200741b3cbc5003602d00a200720062902003703d80a200728029c0121062007200741d8006a3602c8022007290358210a20072802a4012108200741d8026a200741186a41086a290300370300200741e0026a200741186a41106a290300370300200741e8026a200741186a41186a290300370300200720033703b802200720023703b002200720083602cc022007200a3703c002200720072903183703d0022007200c3602f801200720093703f00120074190026a2006200741d00a6a200741b0026a200741f0016a200410e0022007419c026a290200210220074190026a41086a2802002112200728029402210f02402007280290024101470d002002422088a72106200741a4026a280200210c2002a7210120122105200f210e0c070b200728027041016a220c41004c0d032007200c360270200728027821040240024003402010280200220541086a210820052f0106220e41057421064100210b0240024003402006450d01200741386a2008412010dd05220d450d02200641606a2106200b41016a210b200841206a2108200d417f4a0d000b200b417f6a210e0b2004450d022004417f6a21042005200e4102746a41880b6a21100c010b0b2005200b41e0006c6a220641c5036a310000200641e8026a290300220320035022081ba7450d004200200641f8026a29030020081b21034200200641f0026a29030020081b21090c010b2007200728028001200741386a20072802840128021c110400200741086a2903002103200729030021092007280270210c0b2007200c417f6a3602702009200728029801220629037854200320064180016a29030022095420032009511b450d052002a7210c419c8cc200210e411e2105200f2101201221060c060b2009422088a721062009a7210141d3fbc000210e412a21050c060b41f089c6004110200741b0026a41f882c100103b000b200728021421052009422088a721062009a721010c040b41c689c6004118200741b0026a418883c100103b000b200041ba8cc20036020420004101360200200041086a412a3602002000410c6a2006290200370200200041146a200641086a2802003602000c030b20074190026a41086a2208200741186a41086a29030037030020074190026a41106a220b200741186a41106a29030037030020074190026a41186a220d200741186a41186a290300370300200741f0016a41086a2205200741386a41086a290300370300200741f0016a41106a2204200741386a41106a290300370300200741f0016a41186a220e200741386a41186a2903003703002007200729031837039002200720072903383703f001024002402007280294012206200728029001470d00200641016a220c2006490d0120064101742210200c2010200c4b1b220cad42b8017e2203422088a70d012003a722104100480d010240024020060d002010102a21060c010b200728028c01200641b8016c2010102e21060b2006450d052007200c360290012007200636028c0120072802940121060b200728028c01200641b8016c6a220641003a0000200620072f00ed013b0001200641013a00102006410036000c200642013700042006200729039002370011200620072903f001370031200641036a200741ef016a2d00003a0000200641196a2008290300370000200641216a200b290300370000200641296a200d290300370000200641396a2005290300370000200641c1006a2004290300370000200641c9006a200e290300370000200641e0006a200741d7016a290000370000200641d9006a200741c8016a41086a290000370000200620072900c801370051200641e8006a200741b0026a41d00010db051a200720072802940141016a2208360294010240200741d00a6a41186a280200450d00200741e40a6a280200102c20072802940121080b200728029001210e200728028c012105200728027c210c2007280278210d2007280274210602402007280264220b450d00200741e8006a280200450d00200b102c0b0240024020024280808080f01f8350450d002007200c3602b8022007200d3602b402200720063602b0022011200741b0026a10ff012007200e3602b402200720053602b00220072005200841b8016c22086a22043602bc0202400240200141386a280200220b2001413c6a28020022066b200841b8016d220d490d002001280234210b0c010b2006200d6a220e2006490d03200b4101742206200e2006200e4b1b2206ad42b8017e2203422088a70d032003a7220e4100480d0302400240200b0d00200e102a210b0c010b2001280234200b41b8016c200e102e210b0b200b450d072001200b360234200141386a20063602002001413c6a28020021060b200b200641b8016c6a2005200810db051a2001413c6a22062006280200200d6a360200200720043602b802200741b0026a10720c010b02402008450d00200841b8016c210441002108034002400240200520086a220b2d0000220141014b0d000240024020010e020001000b0240200b41086a280200450d00200b41046a280200102c0b200b41106a2d00004105490d02200b41386a280200450d02200b41346a280200102c0c020b200b41286a10730c010b200b41e8006a280200450d00200b41e4006a280200102c0b2004200841b8016a2208470d000b0b0240200e450d002005102c0b02400240200d0d00200621080c010b200d210b20062108034020082802880b2108200b417f6a220b0d000b0340200620062f01064102746a41880b6a2802002106200d417f6a220d0d000b0b200741cc026a20062f0106360200200741c8026a4100360200200741c4026a20063602002007200c3602d002200741003602c002200742003703b802200720083602b402200741003602b002200741b0026a10f9010b20002007290338370004200041003602002000412c6a2002370200200041286a2012360200200041246a200f3602002000411c6a200741d0006a290300370000200041146a200741c8006a2903003700002000410c6a200741c0006a2903003700000c030b1035000b200741e80a6a280200450d00200741e40a6a280200102c0b024020072802642208450d00200741e8006a280200450d002008102c0b2006ad2102200728027c21042007280274210602400240200728027822080d002006210b0c010b2008210d2006210b0340200b2802880b210b200d417f6a220d0d000b0340200620062f01064102746a41880b6a28020021062008417f6a22080d000b0b200242208621022001ad2103200741cc026a20062f010636020041002108200741c8026a4100360200200741c4026a2006360200200720043602d002200741003602c002200742003703b8022007200b3602b402200741003602b002200741b0026a10f90102402007280294012206450d00200728028c01210d200641b8016c2101034002400240200d20086a22062d0000220b41014b0d0002400240200b0e020001000b0240200641086a280200450d00200641046a280200102c0b200641106a2d00004105490d02200641386a280200450d02200641346a280200102c0c020b200641286a10730c010b200641e8006a280200450d00200641e4006a280200102c0b2001200841b8016a2208470d000b0b200220038421020240200728029001450d00200728028c01102c0b2000200e36020420004101360200200041146a200c3602002000410c6a2002370200200041086a20053602000b200741b00d6a24000f0b1033000bbc0d020b7f067e230041e0016b22082400024002400240024002400240200728021841016a220941004c0d00200741186a210a20072009360218200741206a280200210b2007411c6a220c210d024002400340200d280200220e41086a210f200e2f01062210410574210d41002111024002400340200d450d012004200f412010dd052212450d02200d41606a210d201141016a2111200f41206a210f2012417f4a0d000b2011417f6a21100b200b450d02200b417f6a210b200e20104102746a41880b6a210d0c010b0b200e201141e0006c6a220d41c5036a310000200d41e8026a2903002213201350220f1ba7450d004200200d41f8026a290300200f1b21144200200d41f0026a290300200f1b21150c010b200841306a200741286a28020020042007412c6a28020028021c110400200841386a290300211420072802182109200829033021150b20072009417f6a360218200141186a29030021132007280240210d20012903102116024002400240024041004101410220152014842217501b20021b0e03010200010b200d41a8016a210d0c020b200d4188016a210d0c010b200d4198016a210d0b20162013844200510d01200841206a200d290300200d41086a2903002016201310e10520014200200129030822132008290320427f200841206a41086a290300501b7d22162016201356220d1b3703080240200d450d0041e48cc200210d4122210f0c060b200a28020041016a220141004c0d02200720013602182007280220210b024002400340200c280200220e41086a210f200e2f01062210410574210d41002111024002400340200d450d012003200f412010dd052212450d02200d41606a210d201141016a2111200f41206a210f2012417f4a0d000b2011417f6a21100b200b450d02200b417f6a210b200e20104102746a41880b6a210c0c010b0b200e201141e0006c6a220d41c5036a310000200d41e8026a2903002213201350220f1ba7450d004200200d41f8026a290300200f1b21134200200d41f0026a290300200f1b21160c010b200841106a200741286a28020020032007412c6a28020028021c110400200841186a290300211320072802182101200829031021160b200a2001417f6a3602000240201620057d2218201656201320067d2016200554ad7d221620135620162013511b4101470d0041868dc200210d411d210f0c060b024020174200520d002007280240220d290378200556200d4180016a290300221320065620132006511b450d0041a38dc200210d411f210f0c060b200841086a200341022018201610ad0102402008280208220d450d00200828020c210f0c060b0240201520057c2217201554220d201420067c200dad7c221320145420132014511b450d0041c28dc200210d412d210f0c060b4100210d024020032004470d000c060b024020032004412010dd050d000c060b200a200320182016109602200a200420172013109602200841b8016a41086a2211200341086a290000370300200841b8016a41106a2212200341106a290000370300200841b8016a41186a220e200341186a29000037030020084198016a41086a220b200441086a29000037030020084198016a41106a2210200441106a29000037030020084198016a41186a2201200441186a290000370300200820032900003703b801200820042900003703980102402007413c6a280200220f200741386a280200470d00200f41016a220d200f490d05200f4101742204200d2004200d4b1b2204ad42b8017e2213422088a70d052013a7220d4100480d0502400240200f0d00200d102a210d0c010b2007280234200f41b8016c200d102e210d0b200d450d042007200d360234200741386a2004360200200728023c210f0b4100210d2007280234200f41b8016c6a220f41003a0000200f20082f00dd013b0001200f4200370008200f4101360004200f20082903b801370011200f200829039801370031200f41036a200841df016a2d00003a0000200f41106a41003a0000200f41196a2011290300370000200f41216a2012290300370000200f41296a200e290300370000200f41396a200b290300370000200f41c1006a2010290300370000200f41c9006a2001290300370000200f2005370358200f41e0006a2006370300200f41d4006a20084191016a41036a280000360000200f200828009101360051200f41e8006a200841c0006a41d00010db051a2007200728023c41016a36023c0c050b41c689c6004118200841c0006a418883c100103b000b41b0c5c100411941d890c2001036000b41c689c6004118200841c0006a418883c100103b000b1033000b1035000b2000200f3602042000200d360200200841e0016a24000b811402097f017e230041d0016b2203240020034198016a41086a220441e4d2c500ad42808080808001841002220541086a29000037030020032005290000370398012005102c20034188016a41086a220620042903003703002003200329039801370388012004419ee4c300ad4280808080b001841002220541086a29000037030020032005290000370398012005102c200341d8006a41086a22072004290300370300200320032903980137035820034198016a2001109f01024002400240024041c000102a2205450d002005200329038801370000200520032903583700102005200329009801370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341a8016a290000370000200541386a20034198016a41186a290000370000200341c0003602bc01200320053602b801200341186a2005ad42808080808008841003108d0102400240200328021822070d00410221040c010b200328021c21082003200341206a2802003602c401200320073602c001200341106a200341c0016a10750240024020032802100d0020032802142106200341086a200341c0016a107520032802080d00200328020c21092003200341c0016a107520032802000d0020032802c4012204450d002003280204210a20032004417f6a3602c401200320032802c001220441016a3602c00120042d0000220b41014b0d004100210402400240200b0e020100010b410121040b20034198016a200341c0016a1077200328029801450d00200341d8006a41086a20034198016a41086a280200220b360200200341f8006a41086a200b360200200341f4006a41026a20034188016a41026a2d00003a0000200320032f008801220b3b01cc0120032003290398013703782003200b3b01740c010b20034100360260200342013703582003410b36028c012003200341b8016a360288012003200341d8006a3602cc01200341ac016a41013602002003420137029c01200341d0b0c20036029801200320034188016a3602a801200341cc016a41c49ac50020034198016a10391a200335026042208620033502588410040240200328025c450d002003280258102c0b410221040b2008450d002007102c0b20034198016a41086a2207200341f8006a41086a280200360200200341d8006a41026a200341f4006a41026a2d00003a00002003200329037837039801200320032f01743b015802400240024020044102460d00200341c8006a41086a22082007280200360200200341c4006a41026a2207200341d8006a41026a2d00003a00002003200329039801370348200320032f01583b01442005102c200341386a41086a20082802002205360200200341346a41026a20072d000022073a0000200341186a41146a2005360200200341336a20073a000020032003290348220c3703382003200a3602202003200936021c200320043a00302003200c370224200320032f01443b003120032006360218200228025820064d0d0220034198016a41086a220441e4d2c500ad42808080808001841002220541086a29000037030020032005290000370398012005102c20034188016a41086a2206200429030037030020032003290398013703880120044192e4c300ad4280808080c001841002220541086a29000037030020032005290000370398012005102c200341d8006a41086a22072004290300370300200320032903980137035820034198016a2001109f0141c000102a2205450d032005200329038801370000200520032903583700102005200329009801370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200341a8016a290000370000200541386a20034198016a41186a29000037000020034198016a200541c00010bd03200329029c01210c20032802980121042005102c20040d01200041a1e8c20036020420004101360200200041086a411a3602000c050b2005102c200041086a411136020020004190e8c200360204200041013602000c050b20034198016a2004200c422088a7200210ff03200ca7210702402003280298014101470d002000200329029c01370204200041013602002007450d042004102c0c040b200341d8006a41186a220220034198016a410472220541186a280200360200200341d8006a41106a2209200541106a290200370300200341d8006a41086a2206200541086a290200370300200320052902003703580240200341186a41106a2205280200450d002003280224102c0b200341186a41186a200228020036020020052009290300370300200341186a41086a20062903003703002003200329035837031820034198016a41086a220541e4d2c500ad42808080808001841002220241086a29000037030020032002290000370398012002102c20034188016a41086a20052903003703002003200329039801370388012005419ee4c300ad4280808080b001841002220241086a29000037030020032002290000370398012002102c20062005290300370300200320032903980137035820034198016a2001109f0141c000102a2205450d012005200329038801370000200520032903583700102005200329009801370020200541086a20034188016a41086a290300370000200541186a200341d8006a41086a290300370000200541286a20034198016a41086a290000370000200541306a200341a8016a290000370000200541386a20034198016a41186a290000370000200341003602a0012003420137039801200341186a20034198016a108901200341186a41047220034198016a108901200341186a41086a20034198016a10890120032d0030210202400240200328029c0120032802a0012201460d0020032802980121060c010b200141016a22062001490d03200141017422092006200920064b1b22094100480d030240024020010d002009102a21060c010b20032802980120012009102e21060b2006450d022003200936029c0120032006360298010b2003200141016a3602a001200620016a20023a00002003280224210a2003412c6a280200220620034198016a106702400240200328029c01220920032802a00122026b2006490d0020032802980121010c010b200220066a22012002490d03200941017422082001200820014b1b22084100480d030240024020090d002008102a21010c010b20032802980120092008102e21010b2001450d022003200836029c012003200136029801200821090b200120026a200a200610db051a2005ad4280808080800884200220066aad4220862001ad84100102402009450d002001102c0b2005102c2007450d002004102c0b20002003290318370204200041003602002000411c6a200341306a280200360200200041146a200341286a2903003702002000410c6a200341206a2903003702000c030b1033000b1035000b200341286a280200450d002003280224102c0b200341d0016a24000bc71c04087f027e017f017e230041e0006b220624000240024002402002410c6a280200200241106a28020010102207417f460d00410c102a22080d010c020b109103000b200820073602082008428180808010370200200641186a420037030020064280808080c00037031020064204370308024002400240024002402008280200220741016a220941014d0d00200820093602002007417e460d002008200741026a3602000240200628021c22072006280218470d00200741016a22092007490d022007410174220a2009200a20094b1b220941ffffffff03712009470d022009410274220a4100480d020240024020070d00200a102a210a0c010b20062802142007410274200a102e210a0b200a450d06200620093602182006200a3602140b200628021420074102746a20083602002006200628021c41016a36021c2008280208210b4103102a2209450d05200941026a41002d009a86463a0000200941002f009886463b00004106102a220a450d05200a41046a41002f00d9b8453b0000200a41002800d5b845360000024020062802102207200628020c470d00200741016a220c2007490d022007410174220d200c200d200c4b1b220c41ffffff3f71200c470d02200c410574220d4100480d020240024020070d00200d102a210d0c010b20062802082007410574200d102e210d0b200d450d062006200c36020c2006200d3602080b200628020820074105746a220741013602182007200a36020c2007428380808030370204200720093602002007411c6a200b360200200741106a4286808080e0003702002006200628021041016a36021020082008280200417f6a2207360200024020070d002008280208101120082008280204417f6a220736020420070d002008102c0b200641086a419886c6004103419b86c6004103410f109303200641086a419886c60041034191d3c500410f4110109303200641086a419886c600410341a0d3c500410f4111109303200641086a419886c600410341afd3c50041084112109303200641086a419886c600410341b7d3c500410f4113109303200641086a419886c600410341c6d3c500410a4114109303200641086a419886c600410341d0d3c500410a4115109303200641086a419886c600410341dad3c500410b4116109303200641086a419886c600410341e5d3c500410d4117109303200641086a419886c600410341f2d3c500410c4118109303200641086a419886c600410341fed3c500410b4119109303200641086a419886c60041034189d4c5004115411a109303200641086a419886c6004103419ed4c500410a411b109303200641086a419886c600410341a8d4c5004107411c109303200641086a419886c600410341afd4c5004113411d109303200641086a419886c600410341c2d4c5004111411e109303200641086a419886c600410341d3d4c500410e411f109303200641086a419886c600410341e1d4c50041104120109303200641086a419886c600410341f1d4c50041104121109303200641086a419886c60041034181d5c50041114122109303200641086a419886c60041034192d5c50041114123109303200641086a419886c600410341a3d5c50041164124109303200641086a419886c600410341b9d5c50041124125109303200641086a419886c600410341cbd5c500410b4126109303200641086a419886c600410341d6d5c50041104127109303200641086a419886c600410341e6d5c50041174128109303200641206a410c6a200441086a280200360200200620033602204100210b2006410036023c20062005360238200620083602342006200429020037022420062001280200360230200241146a350200210e2002411c6a350200210f200628020821072006280210210820064100360258200642013703502008200641d0006a106702402008450d00200720084105746a2105034020072802002104200741086a2802002208200641d0006a1067024002402006280254220a200628025822096b2008490d002006280250210a0c010b200920086a22012009490d04200a41017422032001200320014b1b22014100480d0402400240200a0d002001102a210a0c010b2006280250200a2001102e210a0b200a450d08200620013602542006200a3602500b2006200920086a360258200a20096a2004200810db051a2007410c6a2802002103200741146a280200220a200641d0006a10670240024020062802542209200628025822046b200a490d00200628025021080c010b2004200a6a22082004490d04200941017422012008200120084b1b22014100480d040240024020090d002001102a21080c010b200628025020092001102e21080b2008450d082006200136025420062008360250200121090b20062004200a6a2201360258200820046a2003200a10db051a02400240200741186a2802004101460d000240024020092001460d002009210a0c010b200941016a220a2009490d0620094101742204200a2004200a4b1b220a4100480d060240024020090d00200a102a21080c010b20082009200a102e21080b2008450d0a2006200a360254200620083602500b2006200141016a2209360258200820016a41013a000020062007411c6a2802002204360248200641c8006a21010c010b0240024020092001460d002009210a0c010b200941016a220a2009490d0520094101742204200a2004200a4b1b220a4100480d050240024020090d00200a102a21080c010b20082009200a102e21080b2008450d092006200a360254200620083602500b2006200141016a2209360258200820016a41023a000020062007411c6a2802002204360248200641c8006a21010b0240200a20096b41034b0d00200941046a22042009490d04200a41017422032004200320044b1b22044100480d0402400240200a0d002004102a21080c010b2008200a2004102e21080b2008450d082006200436025420062008360250200128020021040b2006200941046a360258200820096a2004360000200741206a22072005470d000b0b2006280254210302404129200f422086200e8420063502584220862006280250220dad84200641206a1012220c41036a220841024b0d000240024020080e03000201000b4102210b0b41012104024020030d000c060b200d102c0c050b200628021c220541ffffffff03712005470d0220054102742207417f4c0d02200628021421080240024020070d00410421100c010b2007102a2210450d060b0240024020050d004100210a0c010b200541027421044100210a2010210703402008280200220928020041016a220141014d0d02200841046a21082009200136020020072009360200200a41016a210a200741046a21072004417c6a22040d000b0b02402003450d00200d102c0b2002350204210e2002350200210f20064100360258200642013703504100200641d0006a1067200635025821112006280254210920062802502107410a10302208450d050240024002400240200c200e422086200f8420114220862007ad842008410a200641206a101341036a220241034b0d004101210420020e0402000001020b41ac91c600412841acfec5001036000b2006410936024c410121042006200841016a36024820082d0000220241014b0d01410421010240024020020e020100010b200641d0006a200641c8006a10ae03200628025022014104460d02200628025421030b410021040b2008102c2009450d042007102c0c040b2008102c024020090d000c040b2007102c0c030b00000b1035000b103a000b200c10140240200a450d00200a4102742107201021080340200828020022092009280200417f6a3602000240200828020022092802000d0020092802081011200828020022092009280204417f6a360204200828020022092802040d002009102c0b200841046a21082007417c6a22070d000b0b4102210b2005450d002010102c0b200641206a41086a28020021072006280234210820062802242109024002400240024002400240024002400240200628023c220a0d002006412c6a290200210e20040d04200141044b0d0320010e050203030301020b2000200a36020420004100360200200041106a41003a0000200041086a200641c0006a29030037020002402007450d002009102c0b20082008280200417f6a220736020020070d072008280208101120082008280204417f6a22073602042007450d060c070b2000200936020441002109200041106a41003a00002000410c6a4100360200200041086a20073602000c040b20002009360204200041106a20033a00002000410c6a200e3e0200200041086a2007360200410021090c030b200041cfbcc500360204200041146a200e3e0200200041106a20073602002000410c6a2009360200200041086a41113602000c010b0240200b450d00200041f0bcc500360204200041146a200e3e0200200041106a20073602002000410c6a2009360200200041086a41103602000c010b200041e0bcc500360204200041146a200e3e0200200041106a20073602002000410c6a2009360200200041086a41103602000b410121090b2000200936020020082008280200417f6a220736020020070d012008280208101120082008280204417f6a220736020420070d010b2008102c0b024020062802102207450d00200628020821082007410574210703400240200841046a280200450d002008280200102c0b0240200841106a280200450d002008410c6a280200102c0b200841206a2108200741606a22070d000b0b0240200628020c450d002006280208102c0b0240200628021c2207450d0020062802142108200741027421070340200828020022092009280200417f6a3602000240200828020022092802000d0020092802081011200828020022092009280204417f6a360204200828020022092802040d002009102c0b200841046a21082007417c6a22070d000b0b02402006280218450d002006280214102c0b200641e0006a24000f0b1033000bc50101057f230041306b220124002000410c6a28020021022000280204210302400240200041086a28020022040d00200321000c010b2004210520032100034020002802880b21002005417f6a22050d000b0340200320032f01064102746a41880b6a28020021032004417f6a22040d000b0b200141246a20032f0106360200200141206a41003602002001411c6a20033602002001200236022820014100360218200142003703102001200036020c20014100360208200141086a10f901200141306a24000b8d2a020c7f037e230022072108200741800f6b41607122072400200720043703382007200337033020072005360244024002400240024002402001280230200128024022092802b801460d002005420020052903082203200941386a2903007d2204200420035622091b37030820090d0120074180046a20024100410110e302200741a4046a280200210a200741a0046a280200210b20072d008804220541037122094103460d0220090e03030203030b200041ef8dc20036020420004101360200200041086a41293602002000410c6a2006290200370200200041146a200641086a2802003602000c030b200041988ec20036020420004101360200200041086a41233602002000410c6a2006290200370200200041146a200641086a280200360200200824000f0b200041bb8ec20036020420004101360200200041086a41193602002000410c6a2006290200370200200041146a200641086a28020036020020050d01200a450d01200b102c200824000f0b200741a8046a2802002109200741c8006a41186a220c200141e8006a290000370300200741c8006a41106a220d200141e0006a290000370300200741c8006a41086a220e200141d8006a290000370300200720012900503703484100210f41002110024002400240024002400240024002400240024002400240024020050d002009417f4c0d010240024020090d002007420037038004410121100c010b2009102a2210450d0a200741003602840420072009360280040b20072009360284042010200b200910db051a2007290380042103200a450d00200b102c0b200741a4016a410036020020074194016a41f88bc200360200200741e8006a41206a420037030020074184016a41d0e1c100360200200741e8006a41106a2003370300200741e8006a41d8006a200241086a290000370300200741e8006a41e0006a200241106a290000370300200741e8006a41e8006a200241186a29000037030020072001360270200741e8006a41286a200141186a22113602002007420837029c01200741003602800120072010360274200720022900003703b801200720012802483602b001200720012903403703a8012007200128023041016a36029801200129030021032007200128024c3602b40120072003370368200741d8016a41206a200e290300370300200741d8016a41286a200d29030037030020074188026a200c290300370300200741ec016a200641086a280200360200200720023602e001200720072903483703f001200720062902003702e4012007200741c4006a3602dc012007200741306a3602d8010240024020072903302203200741306a41086a290300220484500d00200741286a20072802444100200741f0016a200220032004200741e8006a10de02200728022822060d01200728028001210f20072802e00121020b200f41016a220d41004c0d02200741d8016a41186a210e200741e4016a210f2007200d36028001200741e8006a41206a280200210a20074184016a2212210602400240024003402006280200220b41086a2105200b2f0106220c4105742106410021090240024003402006450d0120022005412010dd052210450d02200641606a2106200941016a2109200541206a21052010417f4a0d000b2009417f6a210c0b200a450d02200a417f6a210a200b200c4102746a41880b6a21060c010b0b200b200941e0006c6a220541e8026a210602400240200541c5036a2d00000d0020074180046a41086a2209200641c5006a29000037030020074180046a41106a2210200641cd006a29000037030020074180046a41186a220b200641d5006a29000037030020072006413d6a290000370380044102210520062d003c4101470d01200741a00c6a41186a200b290300370300200741a00c6a41106a2010290300370300200741a00c6a41086a200929030037030020072007290380043703a00c410121050c010b200741a80c6a200641c5006a290000370300200741b00c6a200641cd006a290000370300200741b80c6a200641d5006a29000037030020072006413d6a2900003703a00c20062d003c21050b200541ff01714102470d010b20074190026a2007280290012002200728029401280210110400200728028001210d20072d00900221050c010b20074199026a200741a80c6a290300370000200741a1026a200741b00c6a290300370000200741a9026a200741b80c6a290300370000200720053a009002200720072903a00c370091020b2007200d417f6a360280014101210a0240200541ff01714101470d00200741b8026a41186a200741a9026a290000370300200741b8026a41106a200741a1026a290000370300200741b8026a41086a20074199026a29000037030020072007290091023703b80220074180046a200741b8026a20072802b00128020010df0202402007280280044101470d0020072902e4012203422088a7210520074180046a41086a28020021092007280284042106200741ec016a28020021102003a721020c0e0b200741a00c6a41186a220520074180046a410472220641186a2802002209360200200741d8026a41106a200641086a290200370300200741d8026a41186a200641106a290200370300200741f8026a2009360200200741043602dc02200741afcbc5003602d802200720062902003703e00220072802ac0121062005200e41186a2900002203370300200741a00c6a41106a200e41106a2900002204370300200741a00c6a41086a2205200e41086a2900002213370300200741a8046a2013370300200741b0046a2004370300200741b8046a20033703002007200e29000022033703a00c200720033703a00420072802d801220941086a29030021032007200741e8006a36029804200929030021042007290368211320072802b4012109200720033703880420072004370380042007200936029c0420072013370390042005200f41086a2802003602002007200f2902003703a00c200741e0036a2006200741d8026a20074180046a200741a00c6a20072802dc0128020010e002200741ec036a2902002103200741e0036a41086a280200210c20072802e403210a024020072802e0034101470d002003422088a72105200741f4036a28020021102003a72102200c2109200a21060c0d0b20072802800141016a220f41004c0d0420072802e00121022007200f36028001200728028801210d201221060240024003402006280200220b41086a2105200b2f0106220e4105742106410021090240024003402006450d0120022005412010dd052210450d02200641606a2106200941016a2109200541206a21052010417f4a0d000b2009417f6a210e0b200d450d02200d417f6a210d200b200e4102746a41880b6a21060c010b0b200b200941e0006c6a220641c5036a310000200641e8026a290300220420045022051ba7450d004200200641f8026a29030020051b21044200200641f0026a29030020051b21130c010b200741186a200728029001200220072802940128021c110400200741206a290300210420072903182113200728028001210f0b2007200f417f6a221036028001201320072802a801220629037854200420064180016a29030022135420042013511b0d050c060b4100210c420021030240200741e8016a280200450d0020072802e401102c0b420021040c060b200728022c210920072902e4012203422088a721052003a72102200741ec016a28020021100c0b0b103a000b41c689c600411820074180046a418883c100103b000b41c689c600411820074180046a418883c100103b000b20072802702206450d020240024020072802e0012205200641d0006a2209460d0020092005412010dd05450d00034020062802082206450d022005200641d0006a2209460d0120092005412010dd050d000b0b2003a7211041d48ec200210641372109200c2105200a21020c070b20100d032007417f36028001200741003a00bc03200742003702b403200741013a009d03200741d0e1c1003602b003200741e0036a41186a200541186a290000370300200741e0036a41106a200541106a290000370300200741e0036a41086a200541086a290000370300200720052900003703e00302400240200728028401221041d0e1c100460d00200728028801210b0c010b200741a00c6a410041e00210da051a20074180046a410041a00810da051a41880b102a2210450d054100210b201041003b010620104100360200201041086a200741a00c6a41e00210db051a201041e8026a20074180046a41a00810db051a200741003602880120072010360284010b02400240034020102f0106220d4105742102410021064100210502400240034020022006460d01200741e0036a201020066a41086a412010dd052209450d02200641206a2106200541016a21052009417f4a0d000b2005417f6a210d0b200b450d02200b417f6a210b2010200d4102746a41880b6a28020021100c010b0b2010200541e0006c6a22064190036a20072903a80337030020064188036a20072903a003370300200641c0036a200729039803370000200641b8036a200729039003370000200641b0036a200729038803370000200641a8036a20072903800337000020064180036a4200370300200641e8026a2205290300211320054200370300200641a0036a22052802002102200520072903b80337030020064198036a22062903002104200620072903b0033703002004a721062004422088a721050c010b200741c0036a41186a200741e0036a41186a2903002204370300200741c0036a41106a200741e0036a41106a2903002213370300200741c0036a41086a200741e0036a41086a2903002214370300200720072903e00322153703c003200741bc0c6a2014370200200741a00c6a41246a2013370200200741cc0c6a20043702002007200741e8006a41246a3602b00c2007200d3602ac0c200720123602a80c200720103602a40c200741003602a00c200720153702b40c20074180046a41186a42003703002007420037038004200741b8046a20072903b803370300200741b0046a20072903b003370300200741a8046a20072903a803370300200741a0046a20072903a003370300200741d8046a200729039803370300200741d0046a200729039003370300200741c8046a200729038803370300200741c0046a200729038003370300200741a00c6a20074180046a1080021a420221130b024020134202510d000240024020050d00200621090c010b2005211020062109034020092802ec0321092010417f6a22100d000b0340200620062f01064102746a41ec036a28020021062005417f6a22050d000b0b2007419c046a20062f010636020020074198046a410036020020074194046a2006360200200720023602a004200741003602900420074200370388042007200936028404200741003602800420074180046a10f4010b200720072802800141016a360280010b0240200741f0026a280200450d00200741ec026a280200102c0b200342ffffffff0f83210420034280808080708321030b20072802a401210520072802a001210d200728029c01210b200728028c01210e20072802880121102007280284012106024020072802742209450d00200741f8006a280200450d002009102c0b200420038421040240024020034280808080f01f8350450d002007200e3602880420072010360284042007200636028004201120074180046a10ff012007200d360284042007200b360280042007200b200541b8016c22056a220236028c0402400240200141386a28020022092001413c6a28020022066b200541b8016d2210490d00200128023421090c010b200620106a220d2006490d0620094101742206200d2006200d4b1b2206ad42b8017e2203422088a70d062003a7220d4100480d060240024020090d00200d102a21090c010b2001280234200941b8016c200d102e21090b2009450d0520012009360234200141386a20063602002001413c6a28020021060b2009200641b8016c6a200b200510db051a2001413c6a2206200628020020106a360200200720023602880420074180046a10722000410c6a2004370200200041086a200c3602002000200a3602040c010b2000200a3602042000410c6a2004370200200041086a200c36020002402005450d00200541b8016c210141002105034002400240200b20056a22092d0000220241014b0d000240024020020e020001000b0240200941086a280200450d00200941046a280200102c0b200941106a2d00004105490d02200941386a280200450d02200941346a280200102c0c020b200941286a10730c010b200941e8006a280200450d00200941e4006a280200102c0b2001200541b8016a2205470d000b0b0240200d450d00200b102c0b0240024020100d00200621050c010b2010210920062105034020052802880b21052009417f6a22090d000b0340200620062f01064102746a41880b6a28020021062010417f6a22100d000b0b2007419c046a20062f010636020020074198046a410036020020074194046a20063602002007200e3602a004200741003602900420074200370388042007200536028404200741003602800420074180046a10f9010b20004100360200200824000f0b418b8fc20041321054000b41f089c600411020074180046a41f882c100103b000b1033000b1035000b200741f0026a280200450d00200741ec026a280200102c0b2000200636020420004101360200200041146a2010360200200041086a20093602002000410c6a2005ad4220862002ad84370200024020072802742206450d00200741f8006a280200450d002006102c0b200741e8006a411c6a2802002106200728028c0121000240024020072802880122050d00200621090c010b2005211020062109034020092802880b21092010417f6a22100d000b0340200620062f01064102746a41880b6a28020021062005417f6a22050d000b0b20074180046a411c6a20062f01063602004100210520074198046a410036020020074194046a2006360200200720003602a004200741003602900420074200370388042007200936028404200741003602800420074180046a10f901024020072802a4012206450d00200728029c012110200641b8016c2100034002400240201020056a22062d0000220941014b0d000240024020090e020001000b0240200641086a280200450d00200641046a280200102c0b200641106a2d00004105490d02200641386a280200450d02200641346a280200102c0c020b200641286a10730c010b200641e8006a280200450d00200641e4006a280200102c0b2000200541b8016a2205470d000b0b20072802a001450d00200728029c01102c200824000f0b200824000be71f07057f027e0c7f077e017f017e057f230041b0036b22042400200441a0016a200110ee010240024020042d00a0012205417f6a41ff017141024f0d00200041003a0000200041086a200441a0016a41d80010db051a0c010b200441f8016a41086a2206200441a0016a413c6a290200370300200441f8016a41106a2207200441a0016a41c4006a290200370300200441f8016a41186a2208200441a0016a41cc006a2902003703002004200441a0016a41346a2902003703f801200441a0016a41106a2903002109200441a0016a41086a290300210a200441a0016a41306a280200210b200441a0016a412c6a280200210c200441a0016a41246a280200210d200441a0016a41206a280200210e200441bc016a280200210f200441a0016a41186a2802002110200441a0016a41d4006a2802002111200441a0016a41286a280200211220044198026a41186a420037030020044198026a41106a2213420037030020044198026a41086a221442003703002004420037039802200441a0036a41086a22154191b0c200ad4280808080e000841002221641086a290000370300200420162900003703a0032016102c20142015290300370300200420042903a00337039802201541acb0c200ad4280808080e000841002221641086a290000370300200420162900003703a0032016102c201320042903a0032217370300200441f0026a41086a2014290300370300200441f0026a41106a2017370300200441f0026a41186a2015290300370300200420173703900320042004290398023703f00220044198016a200441f0026a4120109401024002400240024002400240024002400240024041004100200428029c0141002004280298011b221520026b2202200220154b1b220220126b2214201420024b1b2214450d0020044188016a200110b701200441f8006a200429038801221720044188016a41086a2903002218428080a8ec85afd1b101420010e1054200200dad22192004290378221a7d221b201b2019564200200441f8006a41086a2903002019201a54ad7c7d22194200522019501b22021b221a4200201920021b221984500d020240024002400240024002402017428080d287e2bc2d5441002018501b0d00200441e0006a2014ad4200201a201910e005200441d0006a2004290360200441e0006a41086a290300428080e983b1de16420010e005200441f0006a20014108420020172017428080aef89dc3527c2219200a200a201956200920182019201754ad7c427f7c22195620092019511b22021b221a2004290350221b201a201b542019200920021b221a200441d0006a41086a290300221954201a2019511b22021b221c7d221d201d2017562018201a201920021b221a7d2017201c54ad7d221720185620172018511b22141b4200201720141b10ad0120042802700d03024020020d002003450d030b20044198026a2001201c201a410810ac012004280298024101460d0a200441386a20044198026a41086a29030020044198026a41106a220629030010ce01200441386a41106a290300211a2004290340211720042903382218a7450d0120044198026a41186a220742003703002006420037030020044198026a41086a221642003703002004420037039802200441a0036a41086a2214418be9c500ad428080808080018422181002220841086a290000370300200420082900003703a0032008102c20162014290300370300200420042903a003221c370390032004201c37039802201441c9b5c000ad4280808080d00184221c1002220841086a290000370300200420082900003703a0032008102c20044190036a41086a221e2014290300221d370300200420042903a003221f370390032013201f370000201341086a2220201d370000200441f0026a41086a22212016290300370300200441f0026a41106a22222006290300370300200441f0026a41186a2223200729030037030020042004290398023703f002200441206a200441f0026a4120109e01200441206a41106a290300211d2004290328211f200428022021082007420037030020064200370300201642003703002004420037039802201420181002222441086a290000370300200420242900003703a0032024102c20162014290300370300200420042903a00322183703900320042018370398022014201c1002222441086a290000370300200420242900003703a0032024102c201e20142903002218370300200420042903a003221c370390032013201c3700002020201837000020212016290300370300202220062903003703002023200729030037030020042004290398023703f00220044200201d420020081b2218201a7d201f420020081b221a201754ad7d221c201a20177d2217201a56201c201856201c2018511b22141b3703a00220044200201720141b37039802200441f0026aad428080808080048420044198026aad428080808080028410010c020b200110f601200e41164d0d08200ead4220862010ad84200e41696aad422086201041176aad8441011007200041023a0008200041013a00000c030b2018500d0020044198026a41186a2206420037030020044198026a41106a2207420037030020044198026a41086a221642003703002004420037039802200441a0036a41086a2214418be9c500ad428080808080018422181002220841086a290000370300200420082900003703a0032008102c20162014290300370300200420042903a003221c370390032004201c37039802201441c9b5c000ad4280808080d00184221c1002220841086a290000370300200420082900003703a0032008102c20044190036a41086a221e2014290300221d370300200420042903a003221f370390032013201f370000201341086a2220201d370000200441f0026a41086a22212016290300370300200441f0026a41106a22222007290300370300200441f0026a41186a2223200629030037030020042004290398023703f002200441086a200441f0026a4120109e01200441086a41106a290300211d2004290310211f200428020821082006420037030020074200370300201642003703002004420037039802201420181002222441086a290000370300200420242900003703a0032024102c20162014290300370300200420042903a00322183703900320042018370398022014201c1002222441086a290000370300200420242900003703a0032024102c201e20142903002218370300200420042903a003221c370390032013201c3700002020201837000020212016290300370300202220072903003703002023200629030037030020042004290398023703f00220044200201d420020081b2218201a7d201f420020081b221a201754ad7d221c201a20177d2217201a56201c201856201c2018511b22141b3703a00220044200201720141b37039802200441f0026aad428080808080048420044198026aad428080808080028410010b20020d0020030d02200041003a0008200041023a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903f801370000200041c4006a20044180026a290300370000200041cc006a200441f8016a41106a290300370000200041d4006a200441f8016a41186a290300370000200041dc006a2011360000200541037122004103460d0420000e030d04040d0b200ead4220862010ad842209100f2117200441003602a803200442013703a0032017a722032017422088a72212200441a0036a1086030240024020042802a403221620042802a80322146b4120490d00201441206a211520042802a00321020c010b201441206a22152014490d09201641017422022015200220154b1b220d4100480d090240024020160d00200d102a21020c010b20042802a0032016200d102e21020b2002450d082004200d3602a403200420023602a003200d21160b200420153602a803200220146a221420042903f801370000201441086a200441f8016a41086a290300370000201441106a200441f8016a41106a290300370000201441186a200441f8016a41186a29030037000020044198026a41186a22142015ad4220862002ad841006221541186a29000037030020044198026a41106a220d201541106a29000037030020044198026a41086a2213201541086a29000037030020042015290000370398022015102c200441f0026a41186a22152014290300370300200441f0026a41106a2214200d290300370300200441f0026a41086a220d201329030037030020042004290398023703f00202402016450d002002102c0b200441b1026a2015290300370000200441a9026a2014290300370000200441a1026a200d290300370000200420042903f00237009902200441013a009802200120044198026a108703200e41164d0d092009200e41696aad422086201041176aad8441011007200041013a0000200041086a20044198026a41d80010db051a2012450d002003102c0b200f450d092010102c0c090b200441c8026a200b360200200441c4026a200c360200200441c0026a2015360200200441bc026a200d360200200441b8026a200e360200200441b4026a200f36020020044198026a41186a2010360200200441cc026a20042903f801370200200441d4026a200441f8016a41086a290300370200200441dc026a200441f8016a41106a290300370200200441e4026a200441f8016a41186a29030037020020044198026a41106a200920197d200a201b54ad7d370300200441003a0098022004200a201b7d3703a002200120044198026a108703200041023a0000200041086a20044198026a41d80010db051a0c080b200041003a0008200041003a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903f801370000200041c4006a2006290300370000200041cc006a2007290300370000200041d4006a2008290300370000200041dc006a20113600000c070b200f450d080c070b200041003a0008200041003a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903f801370000200041c4006a20044180026a290300370000200041cc006a200441f8016a41106a290300370000200041d4006a200441f8016a41186a290300370000200041dc006a20113600000c050b4117200e1047000b2004200429029c023703f00241aba9c20041fe00200441f0026a41acaac200103b000b1033000b1035000b4117200e1047000b0240200541037122004103460d0020000e03020000020b200f450d010b2010102c0b200441b0036a24000baf0201037f230041e0006b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022010d00200041003602000c010b200228021421032002200241186a28020036022420022001360220200241c8006a200241206a1083010240024020022802482204450d002000200229024c370204200020043602000c010b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241d0b0c2003602482002200241386a360258200241c4006a41c49ac500200241c8006a10391a2002350230422086200235022884100420004100360200200228022c450d002002280228102c0b2003450d002001102c0b200241e0006a24000bd20903067f017e057f230041f0016b22022400024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002005417f6a220541014b0d0520050e020102010b200041023a00000c050b20064104490d012004280001210720012003417b6a22053602042001200441056a36020020054108490d02200429000521082001200341736a36020420012004410d6a36020041002105200241003a00b001410d20036b2109200341726a210603400240200920056a0d000240200541ff0171450d00200241003a00b0010b200041023a00000c060b20024190016a20056a200420056a220a410d6a2d00003a0000200120063602042001200a410e6a3602002002200541016a220a3a00b0012006417f6a2106200a2105200a4120470d000b200241f0006a41186a20024190016a41186a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41086a20024190016a41086a290300370300200220022903900137037041002105200241003a00d0012004200a6a2109200a20036b410d6a210a03400240200a20056a0d000240200541ff0171450d00200241003a00d0010b200041023a00000c060b20024190016a20056a200920056a2204410d6a2d00003a00002001200636020420012004410e6a3602002002200541016a22043a00d0012006417f6a210620042105200441c000470d000b200241106a41386a220120024190016a41386a290300370300200241106a41306a220520024190016a41306a290300370300200241106a41286a220620024190016a41286a290300370300200241106a41206a220420024190016a41206a290300370300200241106a41186a220a20024190016a41186a290300370300200241106a41106a220320024190016a41106a290300370300200241106a41086a220920024190016a41086a290300370300200241d0006a41086a220b200241f0006a41086a290300370300200241d0006a41106a220c200241f0006a41106a290300370300200241d0006a41186a220d200241f0006a41186a290300370300200220022903900137031020022002290370370350200041003a000020002002290350370001200041096a200b290300370000200041116a200c290300370000200041196a200d290300370000200041216a2002290310370000200041296a2009290300370000200041316a2003290300370000200041396a200a290300370000200041c1006a2004290300370000200041c9006a2006290300370000200041d1006a2005290300370000200041d9006a2001290300370000200041e3006a2002410f6a2d00003a0000200041e1006a20022f000d3b0000200041e8006a2008370300200041e4006a20073602000c040b0240024020064104490d002004280001210620012003417b6a22053602042001200441056a360200200541084f0d010b200041023a00000c040b200041013a0000200020022f00103b0001200429000521082001200341736a36020420012004410d6a360200200041086a2008370300200041046a2006360200200041036a200241126a2d00003a0000200041106a20024190016a41e00010db051a0c030b200041023a00000c020b200041023a00000c010b200041023a00000b200241f0016a24000bf70101077f230041106b220124002001410036020820014201370300200110e60220012802042102200128020021030240024002400240200041046a2802002204200041086a28020022056b20012802082206490d00200028020021040c010b200520066a22072005490d02200441017422052007200520074b1b22054100480d020240024020040d002005102a21040c010b200028020020042005102e21040b2004450d0120002004360200200041046a2005360200200041086a28020021050b200041086a200520066a360200200420056a2003200610db051a02402002450d002003102c0b200141106a24000f0b1033000b1035000b931501067f230041106b220224000240024002400240024002400240024020012d00000e050003010204000b20024100360208200242013703004101102a2203450d05200242818080801037020420022003360200200341023a00002002200236020c200141016a2002410c6a1094020c040b20024100360208200242013703004101102a2203450d04200242818080801037020420022003360200200341043a000020012d0001210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d06200341017422062005200620054b1b22064100480d060240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0520022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0002210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d06200341017422062005200620054b1b22064100480d060240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0520022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0003210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d06200341017422062005200620054b1b22064100480d060240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0520022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0004210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d06200341017422062005200620054b1b22064100480d060240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0520022006360204200220053602000b2002200341016a360208200520036a20043a000020012802082104200141106a2802002201200210670240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d06200541017422072006200720064b1b22064100480d060240024020050d002006102a21050c010b200228020020052006102e21050b2005450d0520022006360204200220053602000b2002200320016a360208200520036a2004200110db051a0c030b20024100360208200242013703004101102a2203450d03200242818080801037020420022003360200200341053a000020012d0001210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d05200341017422062005200620054b1b22064100480d050240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0420022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0002210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d05200341017422062005200620054b1b22064100480d050240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0420022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0003210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d05200341017422062005200620054b1b22064100480d050240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0420022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0004210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d05200341017422062005200620054b1b22064100480d050240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0420022006360204200220053602000b2002200341016a360208200520036a20043a000020012802082104200141106a2802002201200210670240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d05200541017422072006200720064b1b22064100480d050240024020050d002006102a21050c010b200228020020052006102e21050b2005450d0420022006360204200220053602000b2002200320016a360208200520036a2004200110db051a0c020b20024100360208200242013703004101102a2203450d02200242818080801037020420022003360200200341063a000020012d0001210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d04200341017422062005200620054b1b22064100480d040240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0320022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0002210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d04200341017422062005200620054b1b22064100480d040240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0320022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0003210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d04200341017422062005200620054b1b22064100480d040240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0320022006360204200220053602000b2002200341016a360208200520036a20043a000020012d0004210402400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d04200341017422062005200620054b1b22064100480d040240024020030d002006102a21050c010b200228020020032006102e21050b2005450d0320022006360204200220053602000b2002200341016a360208200520036a20043a000020012802082104200141106a2802002201200210670240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d04200541017422072006200720064b1b22064100480d040240024020050d002006102a21050c010b200228020020052006102e21050b2005450d0320022006360204200220053602000b2002200320016a360208200520036a2004200110db051a0c010b20024100360208200242013703004101102a2203450d01200242818080801037020420022003360200200341003a0000200141046a28020021042001410c6a2802002201200210670240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d03200541017422072006200720064b1b22064100480d030240024020050d002006102a21050c010b200228020020052006102e21050b2005450d0220022006360204200220053602000b2002200320016a360208200520036a2004200110db051a0b200020022201290200370200200041086a200141086a280200360200200241106a24000f0b1033000b1035000bd70701047f230041106b2202240002400240024020002d0000417f6a220341034b0d00024002400240024020030e0400010203000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020421032000410c6a2802002200200110672000450d0320004105742100034020032001109101200341206a2103200041606a22000d000c040b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a000020002802042001108b010c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d04200341017422052004200520044b1b22054100480d040240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041046a200110890120002802082001108b010c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d03200341017422052004200520044b1b22054100480d030240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a00002002200136020c200041016a2002410c6a109402200041246a200110890120002d0021210402400240200141046a28020020052802002203460d00200128020021000c010b200341016a22002003490d03200341017422052000200520004b1b22054100480d030240024020030d002005102a21000c010b200128020020032005102e21000b2000450d0220012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a20043a00000b200241106a24000f0b1033000b1035000bcd1702047f017e200028025821020240024002400240200141046a2802002203200141086a28020022046b4104490d00200128020021030c010b200441046a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200320046a20023600002000290300210602400240200141046a2802002203200528020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290308210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290310210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290318210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290320210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290328210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290330210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290338210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290340210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290348210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290350210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a2006370000200028025c210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280260210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280264210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280268210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d02200341017422042002200420024b1b22044100480d020240024020030d002004102a21030c010b200128020020032004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a200536000020002d0070210502400240200141046a28020020022802002204460d00200128020021030c010b200441016a22032004490d02200441017422022003200220034b1b22024100480d020240024020040d002002102a21030c010b200128020020042002102e21030b2003450d0120012003360200200141046a2002360200200141086a28020021040b200141086a2202200441016a360200200320046a20053a0000200028026c210302400240200141046a2802002204200228020022006b4104490d00200128020021040c010b200041046a22022000490d02200441017422002002200020024b1b22004100480d020240024020040d002000102a21040c010b200128020020042000102e21040b2004450d0120012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a20033600000f0b1033000b1035000bb8be0102087f027e230041106b220224000240024002400240024020002d0000220341114b0d0002400240024002400240024002400240024002400240024002400240024002400240024020030e12000102030405060708090a0b0c0d0e0f1011000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00000240024020002802044101460d00200241003a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d16200341017422052004200520044b1b22054100480d160240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280208210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d16200441017422032005200320054b1b22034100480d160240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1520012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a20063600002000410c6a2103410721050c010b200241013a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000410021040240200041106a2d00004101470d00200241013a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d16200341017422062004200620044b1b22064100480d160240024020030d002006102a21040c010b200128020020032006102e21040b2004450d1520012004360200200141046a2006360200200141086a28020021030b200141086a200341016a360200200420036a41013a000020002d001121040b200220043a000002400240200141046a28020020052802002203460d00200128020021050c010b200341016a22052003490d15200341017422062005200620054b1b22064100480d150240024020030d002006102a21050c010b200128020020032006102e21050b2005450d1420012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a20043a00002002200041126a2d000022053a000002400240200141046a28020020062802002203460d00200128020021040c010b200341016a22042003490d15200341017422062004200620044b1b22064100480d150240024020030d002006102a21040c010b200128020020032006102e21040b2004450d1420012004360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200420036a20053a00002000280214210502400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22062003490d15200441017422032006200320064b1b22034100480d150240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1420012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a2005360000200041186a2103411321050b200220032d000022063a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422072004200720044b1b22074100480d140240024020030d002007102a21040c010b200128020020032007102e21040b2004450d1320012004360200200141046a2007360200200141086a28020021030b200141086a2207200341016a360200200420036a20063a00002002200020056a41066a2d000022043a000002400240200141046a28020020072802002200460d00200128020021030c010b200041016a22032000490d14200041017422052003200520034b1b22054100480d140240024020000d002005102a21030c010b200128020020002005102e21030b2003450d1320012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c110b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a28020020052802002204460d00200128020021050c010b200441016a22032004490d13200441017422052003200520034b1b22034100480d130240024020040d002003102a21050c010b200128020020042003102e21050b2005450d1220012005360200200141046a2003360200200141086a28020021040b200141086a2203200441016a360200200520046a41003a0000200028020421042000410c6a2802002200200110672000450d102000410c6c21082004410a6a2104200141046a210603404100210502402004417e6a22072d00004102460d00200241013a000002400240200628020020032802002200460d00200128020021050c010b200041016a22052000490d15200041017422092005200920054b1b22094100480d150240024020000d002009102a21050c010b200128020020002009102e21050b2005450d142001200536020020062009360200200328020021000b2003200041016a360200200520006a41013a000041002105024020072d00004101470d00200241013a000002400240200628020020032802002200460d00200128020021050c010b200041016a22052000490d16200041017422072005200720054b1b22074100480d160240024020000d002007102a21050c010b200128020020002007102e21050b2005450d152001200536020020062007360200200328020021000b2003200041016a360200200520006a41013a00002004417f6a2d000021050b200220053a000002400240200628020020032802002200460d00200128020021070c010b200041016a22072000490d15200041017422092007200920074b1b22094100480d150240024020000d002009102a21070c010b200128020020002009102e21070b2007450d142001200736020020062009360200200328020021000b2003200041016a360200200720006a20053a000020042d000021050b200220053a000002400240200628020020032802002200460d00200128020021070c010b200041016a22072000490d14200041017422092007200920074b1b22094100480d140240024020000d002009102a21070c010b200128020020002009102e21070b2007450d132001200736020020062009360200200328020021000b2003200041016a360200200720006a20053a00002004410c6a2104200841746a22080d000c110b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041086a20011091012000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d12200341017422002005200020054b1b22004100480d120240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1120012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002d0008220341034b0d0e0240024002400240024020030e0400010203000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041096a20011091012000290330210a2002200041386a2903003703082002200a3703000c030b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041096a20011091012000290330210a2002200041386a2903003703082002200a3703000c020b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200041096a2001109101200041296a2001109101200041d8006a290300210a2000290350210b02400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d13200441017422032005200320054b1b22034100480d130240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1220012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2203200a3700082003200b3700002000290360210a2002200041e8006a2903003703082002200a3703000c010b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041096a2001109101200041386a290300210a2000290330210b02400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d12200441017422032005200320054b1b22034100480d120240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1120012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2203200a3700082003200b3700002000290340210a2002200041c8006a2903003703082002200a3703000b2002210302400240200141046a2802002204200141086a28020022006b4110490d00200128020021040c010b200041106a22052000490d11200441017422002005200020054b1b22004100480d110240024020040d002000102a21040c010b200128020020042000102e21040b2004450d1020012004360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200420006a220141086a200341086a290000370000200120032900003700000c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a000020002d0008220341024b0d0d02400240024020030e03000102000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041186a290300210a2000290310210b02400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d12200441017422032005200320054b1b22034100480d120240024020040d002003102a21040c010b200128020020042003102e21040b2004450d1120012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a2203200a3700082003200b370000200041286a290300210a2000290320210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d12200341017422002004200020044b1b22004100480d120240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1120012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000c0f0b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041096a2001109101200041386a290300210a2000290330210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d11200341017422002004200020044b1b22004100480d110240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1020012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000c0e0b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d10200341017422002005200020054b1b22004100480d100240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0f20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0f200341017422002005200020054b1b22004100480d0f0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0e20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0c0b02400240200141046a2206280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d0e200341017422072005200720054b1b22074100480d0e0240024020030d002007102a21050c010b200128020020032007102e21050b2005450d0d20012005360200200141046a2007360200200141086a28020021030b2004200341016a360200200520036a41063a0000024002400240024002400240024002400240024002400240024002400240024020002d00080e10000102030405060708090a0b0c0d0e0f000b200241003a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d1d200341017422072005200720054b1b22074100480d1d0240024020030d002007102a21050c010b200128020020032007102e21050b2005450d1c20012005360200200141046a2007360200200141086a28020021030b2004200341016a360200200520036a41003a0000200028020c21070240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a22082003490d1d200541017422032008200320084b1b22034100480d1d0240024020050d002003102a21050c010b200128020020052003102e21050b2005450d1c20012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2007360000200041186a290300210a2000290310210b0240024020062802002203200428020022006b4110490d00200128020021030c010b200041106a22052000490d1d200341017422002005200020054b1b22004100480d1d0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1c20012003360200200141046a2000360200200141086a28020021000b2004200041106a360200200320006a2201200a3700082001200b3700000c1a0b200241013a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d1c200341017422072005200720054b1b22074100480d1c0240024020030d002007102a21050c010b200128020020032007102e21050b2005450d1b20012005360200200141046a2007360200200141086a28020021030b2004200341016a360200200520036a41013a0000200028020c21070240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a22082003490d1c200541017422032008200320084b1b22034100480d1c0240024020050d002003102a21050c010b200128020020052003102e21050b2005450d1b20012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2007360000200041286a290300210a2000290320210b0240024020062802002205200428020022036b4110490d00200128020021040c010b200341106a22042003490d1c200541017422032004200320044b1b22034100480d1c0240024020050d002003102a21040c010b200128020020052003102e21040b2004450d1b20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2203200a3700082003200b37000020002802102103200041186a2802002200200110672000450d1920004105742100034020032001109101200341206a2103200041606a22000d000c1a0b0b200241023a000002400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1b200041017422052003200520034b1b22054100480d1b0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d1a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c180b200241033a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d1a200341017422072005200720054b1b22074100480d1a0240024020030d002007102a21050c010b200128020020032007102e21050b2005450d1920012005360200200141046a2007360200200141086a28020021030b2004200341016a360200200520036a41033a0000200028020c21070240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a22082003490d1a200541017422032008200320084b1b22034100480d1a0240024020050d002003102a21050c010b200128020020052003102e21050b2005450d1920012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200736000020002d0009220041024b0d1702400240024020000e03000102000b200241003a000002400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1c200041017422052003200520034b1b22054100480d1c0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d1b20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41003a00000c190b200241013a000002400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1b200041017422052003200520034b1b22054100480d1b0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d1a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41013a00000c180b200241023a000002400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d1a200041017422052003200520034b1b22054100480d1a0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d1920012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c170b200241043a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d19200341017422072005200720054b1b22074100480d190240024020030d002007102a21050c010b200128020020032007102e21050b2005450d1820012005360200200141046a2007360200200141086a28020021030b2004200341016a360200200520036a41043a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d19200341017422002006200020064b1b22004100480d190240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1820012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c160b200241053a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d18200341017422072005200720054b1b22074100480d180240024020030d002007102a21050c010b200128020020032007102e21050b2005450d1720012005360200200141046a2007360200200141086a28020021030b2004200341016a360200200520036a41053a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d18200341017422002006200020064b1b22004100480d180240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1720012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c150b200241063a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d17200341017422072005200720054b1b22074100480d170240024020030d002007102a21050c010b200128020020032007102e21050b2005450d1620012005360200200141046a2007360200200141086a28020021030b2004200341016a360200200520036a41063a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d17200341017422002006200020064b1b22004100480d170240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1620012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c140b200241073a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d16200341017422072005200720054b1b22074100480d160240024020030d002007102a21050c010b200128020020032007102e21050b2005450d1520012005360200200141046a2007360200200141086a28020021030b2004200341016a360200200520036a41073a0000200028020c21070240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a22082003490d16200541017422032008200320084b1b22034100480d160240024020050d002003102a21050c010b200128020020052003102e21050b2005450d1520012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2007360000200220002d000922053a000002400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d16200041017422062003200620034b1b22064100480d160240024020000d002006102a21030c010b200128020020002006102e21030b2003450d1520012003360200200141046a2006360200200141086a28020021000b2004200041016a360200200320006a20053a00000c130b200241083a000002400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d15200341017422052004200520044b1b22054100480d150240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a0000200041096a2001109101200041296a20011091010c120b200241093a000002400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a0000200041096a20011091010c110b2002410a3a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d13200341017422062005200620054b1b22064100480d130240024020030d002006102a21050c010b200128020020032006102e21050b2005450d1220012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a410a3a0000200041096a200110910120022001360200200041296a2002109402200028024c210502400240200141046a2802002203200628020022006b4104490d00200128020021030c010b200041046a22062000490d13200341017422002006200020064b1b22004100480d130240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1220012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c100b2002410b3a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d12200341017422062005200620054b1b22064100480d120240024020030d002006102a21050c010b200128020020032006102e21050b2005450d1120012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a410b3a000020022001360200200041096a2002109402200041296a2001109101200041d8006a290300210a2000290350210b02400240200141046a2802002203200628020022006b4110490d00200128020021030c010b200041106a22052000490d12200341017422002005200020054b1b22004100480d120240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1120012003360200200141046a2000360200200141086a28020021000b2004200041106a360200200320006a2201200a3700082001200b3700000c0f0b2002410c3a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d11200341017422062005200620054b1b22064100480d110240024020030d002006102a21050c010b200128020020032006102e21050b2005450d1020012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a410c3a000020022001360200200041096a2002109402200041296a2001109101200041d8006a290300210a2000290350210b02400240200141046a2802002203200628020022006b4110490d00200128020021030c010b200041106a22052000490d11200341017422002005200020054b1b22004100480d110240024020030d002000102a21030c010b200128020020032000102e21030b2003450d1020012003360200200141046a2000360200200141086a28020021000b2004200041106a360200200320006a2201200a3700082001200b3700000c0e0b2002410d3a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d10200341017422062005200620054b1b22064100480d100240024020030d002006102a21050c010b200128020020032006102e21050b2005450d0f20012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a410d3a000020022001360200200041096a2002109402200028022c210502400240200141046a2802002203200628020022006b4104490d00200128020021030c010b200041046a22062000490d10200341017422002006200020064b1b22004100480d100240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0f20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0d0b2002410e3a000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d0f200341017422062005200620054b1b22064100480d0f0240024020030d002006102a21050c010b200128020020032006102e21050b2005450d0e20012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a410e3a000020022001360200200041096a2002109402200028022c210502400240200141046a2802002203200628020022006b4104490d00200128020021030c010b200041046a22062000490d0f200341017422002006200020064b1b22004100480d0f0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0e20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0c0b2002410f3a000002400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410f3a000020022001360200200041096a2002109402200041296a2001109101200041f8006a290300210a2000290370210b02400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d0e200441017422032005200320054b1b22034100480d0e0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0d20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2203200a3700082003200b370000200041c9006a20011091010c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200041046a200110eb020c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a0000200041046a200110eb020c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a000020002d0004220341044b0d080240024002400240024020030e050001020304000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102a21040c010b200128020020032005102e21040b2004450d1020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000020002802082103200041106a2802002200200110672000450d0c2003200041306c6a2108200141046a2106034020032001109101200341286a290300210a200341206a290300210b0240024020062802002204200528020022006b4110490d00200128020021040c010b200041106a22072000490d12200441017422002007200020074b1b22004100480d120240024020040d002000102a21040c010b200128020020042000102e21040b2004450d112001200436020020062000360200200528020021000b2005200041106a360200200420006a2200200a3700082000200b3700002008200341306a2203470d000c0d0b0b200241013a000002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d10200041017422042003200420034b1b22044100480d100240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0f20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c0b0b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041056a20011091010c0a0b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a0000200041056a20011091010c090b200141086a2802002103200241043a0000024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041056a2001109101200041256a2001109101200220002d004522043a000002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d0d200041017422052003200520034b1b22054100480d0d0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d0c20012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a000020002d0001220041054b0d07024002400240024002400240024020000e06000102030405000b410021030c050b410121030c040b410221030c030b410321030c020b410421030c010b410521030b200220033a000002400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d0c200041017422052004200520044b1b22054100480d0c0240024020000d002005102a21040c010b200128020020002005102e21040b2004450d0b20012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a20033a00000c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a00002000280204220341024b0d0602400240024020030e03000102000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000020002802082103200041106a2802002200200110672000450d082003200041286c6a2108200141046a2106034020032001109101200341206a290300210a0240024020062802002204200528020022006b4108490d00200128020021040c010b200041086a22072000490d0e200441017422002007200020074b1b22004100480d0e0240024020040d002000102a21040c010b200128020020042000102e21040b2004450d0d2001200436020020062000360200200528020021000b2005200041086a360200200420006a200a3700002008200341286a2203470d000c090b0b200241013a000002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0c200041017422042003200420034b1b22044100480d0c0240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0b20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c070b200241023a000002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0b200041017422042003200420034b1b22044100480d0b0240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a00000c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a000020002d0008220341054b0d0502400240024002400240024020030e06000102030405000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0f200341017422002005200020054b1b22004100480d0f0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0e20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0a0b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a290300210a2000290310210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d0e200341017422002004200020044b1b22004100480d0e0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0d20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000c090b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200028022c210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d0d200441017422032005200320054b1b22034100480d0d0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0c20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2006360000200041386a290300210a2000290330210b02400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d0d200441017422032005200320054b1b22034100480d0d0240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0c20012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2203200a3700082003200b370000200041096a20011091010c080b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041186a290300210a2000290310210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d0c200341017422002004200020044b1b22004100480d0c0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0b20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000c070b200141086a2802002103200241043a0000024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041186a290300210a2000290310210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d0b200341017422002004200020044b1b22004100480d0b0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0a20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000c060b200241053a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a0000200041186a290300210a2000290310210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d0a200341017422002004200020044b1b22004100480d0a0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0920012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410d3a000020002d0008220341054b0d0402400240024002400240024020030e06000102030405000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0e200341017422052004200520044b1b22054100480d0e0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041096a2001109101200041296a2001109101200041d8006a290300210a2000290350210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d0e200341017422002004200020044b1b22004100480d0e0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0d20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000c090b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0d200341017422052004200520044b1b22054100480d0d0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041096a2001109101200041296a20011091010c080b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c200341017422052004200520044b1b22054100480d0c0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a000020022001360200200041096a20021094020c070b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b200341017422052004200520044b1b22054100480d0b0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d0b200341017422002005200020054b1b22004100480d0b0240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0a20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c060b200141086a2802002103200241043a0000024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041096a2001109101200220002d002922043a000002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d0a200041017422052003200520034b1b22054100480d0a0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d0920012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c050b200241053a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a0000200041096a2001109101200028022c2106200041346a28020022002001106702400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d09200441017422032005200320054b1b22034100480d090240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010db051a0c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410e3a000020002d0001220341024b0d0302400240024020030e03000102000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200220002d000222043a000002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d0a200041017422052003200520034b1b22054100480d0a0240024020000d002005102a21030c010b200128020020002005102e21030b2003450d0920012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c050b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041026a20011091010c040b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200220002d000222043a000002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d08200041017422052003200520034b1b22054100480d080240024020000d002005102a21030c010b200128020020002005102e21030b2003450d0720012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410f3a000020002d0004220341024b0d0202400240024020030e03000102000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041056a20011091010c040b200241013a000002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d08200041017422042003200420034b1b22044100480d080240024020000d002004102a21030c010b200128020020002004102e21030b2003450d0720012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c030b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a000020002802082104200041106a2802002200200110672000450d022004200041d0006c6a21050340200420011091012002200441206a36020020022001108a012002200441306a36020020022001108a01200428024021002004280248220320011067200441d0006a210402402003450d00200341306c21030340200041106a20011091012002200036020020022001108a01200041306a2100200341506a22030d000b0b20052004470d000c030b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41103a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041106a200110ec02200028020421062000410c6a28020022032001106702400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d06200441017422002005200020054b1b22004100480d060240024020040d002000102a21040c010b200128020020042000102e21040b2004450d0520012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a2006200310db051a0c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41113a000020002d0008220341044b0d000240024002400240024020030e050001020304000b200241003a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041096a20011091010c040b200241013a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041096a20011091010c030b200241023a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041096a20011091010c020b200241033a000002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041096a2001109101200041386a290300210a2000290330210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d06200341017422002004200020044b1b22004100480d060240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0520012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000c010b200141086a2802002103200241043a0000024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041096a2001109101200041386a290300210a2000290330210b02400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d05200341017422002004200020044b1b22004100480d050240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0420012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a2201200a3700082001200b3700000b200241106a24000f0b1033000b1035000b1033000b1035000b8d1201057f230041106b2202240002400240024020002d0000220341054b0d0002400240024002400240024020030e06000102030405000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041016a20011091012000280244210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a20063600002002200136020c200041216a2002410c6a1094022000280248210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d08200341017422002005200020054b1b22004100480d080240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0720012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041016a20011091012002200136020c200041216a2002410c6a10940220002d0041210602400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20063a00002000280244210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d07200441017422032005200320054b1b22034100480d070240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0620012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a20063600002000280248210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d07200341017422002005200020054b1b22004100480d070240024020030d002000102a21030c010b200128020020032000102e21030b2003450d0620012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200136020c200041016a2002410c6a1094020c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002002200136020c200041016a2002410c6a1094020c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d04200341017422052004200520044b1b22054100480d040240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a00002002200136020c200041016a2002410c6a10940220002d0021210402400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d04200041017422052003200520034b1b22054100480d040240024020000d002005102a21030c010b200128020020002005102e21030b2003450d0320012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d03200341017422052004200520044b1b22054100480d030240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a00002002200136020c200041016a2002410c6a10940220002d0021210402400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d03200041017422052003200520034b1b22054100480d030240024020000d002005102a21030c010b200128020020002005102e21030b2003450d0220012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000b200241106a24000f0b1033000b1035000bb21401047f20002d000021020240024002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0001210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0002210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0003210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0004210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0005210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0006210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0007210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0008210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d0009210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d000a210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d000b210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d000c210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d000d210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d000e210202400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d02200341017422052004200520044b1b22054100480d020240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20023a000020002d000f210402400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d02200041017422022003200220034b1b22024100480d020240024020000d002002102a21030c010b200128020020002002102e21030b2003450d0120012003360200200141046a2002360200200141086a28020021000b200141086a200041016a360200200320006a20043a00000f0b1033000b1035000bea0b01037f230041306b210202400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e18000102030405060708090a0b0c0d0e0f1011121314151617000b417f2102024002400240200141086a280200417f6a220341064b0d0041012101024020030e0703010200020202030b41c09a0c21020c020b410021010b4190ce0021020b200041013a0005200020013a0004200020023602000f0b200041013b0104200041003602000f0b20004180023b010420004190ce003602000f0b20004181023b010420004190ce003602000f0b20004181023b010420004190ce003602000f0b20004180023b010420004190ce003602000f0b4100210202400240200141086a280200417f6a220341034b0d0041c0843d2101024020030e0402000202020b4101210241d0860321010c010b4190ce0021010b200041013a0005200020023a0004200020013602000f0b410121024100210302400240200141086a2d0000417f6a2204410f4b0d0041a0c21e210102400240024020040e1004040000010104040102020202020202040b4180b51821010c030b41b0e32d21010c020b4100210141012103410021020c010b4190ce0021010b200020023a0005200020033a0004200020013602000f0b20004180023b0104200041f093093602000f0b410021020240024002400240200141086a2d0000417f6a220341144b0d0041c096b1022101024002400240024020030e15070700000107070702020303060606050504060604070b41c09a0c21010c060b4101210241a0c21e21010c050b41c09a0c21010c040b410121020b4190ce0021010c020b41a0c21e21010c010b41a08d0621010b200041013a0005200020023a0004200020013602000f0b0240024020012d0004417f6a220341034b0d004101210241a08d0621010240024020030e0403030001030b41c096b10221010c020b41c09a0c21010c010b410021024190ce0021010b200041013a0005200020023a0004200020013602000f0b0240024020012d0004417f6a220341034b0d004101210241a08d0621010240024020030e0403030001030b41c096b10221010c020b41c09a0c21010c010b410021024190ce0021010b200041013a0005200020023a0004200020013602000f0b4100210202400240200141086a280200417f6a220341054b0d0041a08d06210102400240024020030e06040300010202040b41c0843d21010c030b41a0c21e21010c020b41012102418089fa0021010c010b4190ce0021010b200041013a0005200020023a0004200020013602000f0b20004180023b0104200041d086034190ce0020012d0004417f6a4107714105491b3602000f0b20004180023b010420004190ce003602000f0b20004180023b010420004190ce003602000f0b4100210202400240200141086a280200417f6a220341024b0d0041a0c21e2101024020030e03020000020b4101210241a08d0621010c010b4190ce0021010b200041013a0005200020023a0004200020013602000f0b02400240200141086a2d0000417f6a220341044b0d0020022101024002400240024020030e050500010203050b200241086a21010c040b200241106a21010c030b200241186a21010c020b200241206a21010c010b200241286a21010b2001428080808080e20937020020004180023b010420004190ce003602000f0b024002402001280204417f6a220441024b0d00410021014101210241002103024020040e03020100020b4101210241002101410121030c010b41012103410021024190ce0021010b200020033a0005200020023a0004200020013602000f0b20004180023b010420004190ce003602000f0b20004180023b010420004190ce003602000f0b20004180023b010420004190ce003602000f0b20004180023b010420004190ce003602000f0b4101210241002103024002402001280204417f6a220441034b0d0041d086032101024020040e0402010000020b4100210141012103410021020c010b4190ce0021010b200020023a0005200020033a0004200020013602000b880401077f230041306b22022400200241003602082002420137030020022002360210200141106a200241106a1094022001200210890120022002360210200141306a200241106a10940220022002360210200141d0006a200241106a109402200128020421032001410c6a2802002201200210670240024002402001450d00200141246c21040340200241106a200310e702200228021021050240024020022802042206200228020822016b20022802182207490d00200228020021060c010b200120076a22082001490d04200641017422012008200120084b1b22014100480d040240024020060d002001102a21060c010b200228020020062001102e21060b2006450d032002200136020420022006360200200228020821010b2002200120076a360208200620016a2005200710db051a02402002280214450d002005102c0b200341246a21032004415c6a22040d000b0b20022802042107200241106a41186a2203200235020842208620022802002204ad841006220141186a290000370300200241106a41106a2206200141106a290000370300200241106a41086a2205200141086a290000370300200220012900003703102001102c200041186a2003290300370000200041106a2006290300370000200041086a20052903003700002000200229031037000002402007450d002004102c0b200241306a24000f0b1033000b1035000b9d0302057f017e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041003602000c010b200328021421022003200341186a28020036022420032001360220200341c8006a200341206a10770240024020032802482204450d00200328024c21050240200328022422064110490d002003200641706a36022420032003280220220641106a360220200341c8006a41086a280200210720062900002108200041186a200641086a290000370300200041106a2008370300200041086a200736020020002005360204200020043602000c020b2005450d002004102c0b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341d0b0c2003602482003200341386a360258200341c4006a41c49ac500200341c8006a10391a2003350230422086200335022884100420004100360200200328022c450d002003280228102c0b2002450d002001102c0b200341e0006a24000be006010d7f23004190016b220224002002412036021420022001360210200241186a2001ad42808080808004841003108d0102400240200228021822030d00200041003602000c010b200228021c21042002200241206a28020036023c20022003360238200241086a200241386a1075024002400240024020022802080d0002400240200228023c22014160712205417f4c0d00200228020c210602400240200141057622070d00410121080c010b2005102a2208450d020b02402006450d004100210903402001210a200241003a0088012009220b41016a2109410021010240024002400340200a2001460d01200241e8006a20016a200228023822052d00003a00002002200541016a3602382002200141016a22053a0088012005210120054120470d000b200241c8006a41186a220c200241e8006a41186a290300370300200241c8006a41106a220d200241e8006a41106a290300370300200241c8006a41086a220e200241e8006a41086a290300370300200220022903683703482007200b470d020240200b41017422012009200120094b1b220741ffffff3f712007470d002007410574220141004e0d020b1035000b2002410036023c0240200141ff0171450d00200241003a0088010b200241003602282007450d072008102c0c070b02400240200b0d002001102a21080c010b2008200b4105742001102e21080b2008450d040b200a20056b21012008200b4105746a220b2002290348370000200b41186a200c290300370000200b41106a200d290300370000200b41086a200e29030037000020092006470d000b200241306a20063602002002200736022c200220083602282002200a20056b36023c0c050b200241306a20063602002002200736022c2002200836022820080d040c030b103a000b1033000b200241003602280b20024100360250200242013703482002410b36022c2002200241106a3602282002200241c8006a360244200241fc006a41013602002002420137026c200241d0b0c2003602682002200241286a360278200241c4006a41c49ac500200241e8006a10391a2002350250422086200235024884100420004100360200200228024c450d012002280248102c0c010b20002002290328370200200041086a200241286a41086a2802003602000b2004450d002003102c0b20024190016a24000b8f0201057f230041106b22032400024002400240200141046a2204417f4c0d000240024020040d00410121050c010b2004102a2205450d020b2003410036020820032004360204200320053602002001200310670240024020032802042206200328020822056b2001490d00200328020021040c010b200520016a22042005490d03200641017422072004200720044b1b22074100480d030240024020060d002007102a21040c010b200328020020062007102e21040b2004450d022003200736020420032004360200200721060b200420056a2000200110db051a2002290200200520016aad4220862004ad84100102402006450d002004102c0b200341106a24000f0b103a000b1033000b1035000bd46109027f017e047f027e047f017e0c7f0c7e117f230041900a6b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341c4026a4101360200200342013702b402200341fcc4c5003602b002200341043602b406200341f4c4c5003602b0062003200341b0066a3602c002200341b0026a4184c5c5001041000b200141e0006a2802002104200341b0066a200141086a41d80010db051a200341f8046a41186a200141fc006a28020036020020034188056a200141f4006a290200370300200341f8046a41086a200141ec006a2902003703002003200141e4006a2902003703f804024020022d000120022d000072450d0041b2b2c0002104411121020c110b41e4d2c500ad42808080808001842205100222022f0000210620022d000221072002280003210820022d000721092002290008210a2002102c41f4d2c500ad4280808080f00184220b100222022f0000210c20022d0002210d2002280003210e20022d0007210f200229000821102002102c20032010370390042003200f3a008f042003200e4118763a008e042003200e4108763b018c042003200e3a008b042003200d3a008a042003200c3b0188042003200a4238883c0087042003200a4230883c0086042003200a4220883d0184042003200a4218883c0083042003200a4210883c0082042003200a3d018004200320093a00ff03200320083600fb03200320073a00fa03200320063b01f803200341b0026a200341f8036a10e7030240410020032802880320032d00a0034102461b2004490d0041b1b3c4002104413521020c110b200341bc026a2004360200200341b0026a41086a41033a00002003410d3a00b00241014100200341b0026a109201200341b0026a200341b0066a41d80010db051a20034194036a200341f8046a41086a2903003702002003419c036a20034188056a290300370200200341a4036a200341f8046a41186a2802003602002003200436028803200320032903f80437028c032005100222022f0000210e20022d000221062002280003210720022d000721082002290008210a2002102c200b100222022f0000210920022d0002210c2002280003210420022d0007210d200229000821102002102c20032010370390042003200d3a008f04200320044118763a008e04200320044108763b018c04200320043a008b042003200c3a008a04200320093b0188042003200a4238883c0087042003200a4230883c0086042003200a4220883d0184042003200a4218883c0083042003200a4210883c0082042003200a3d018004200320083a00ff03200320073600fb03200320063a00fa032003200e3b01f803200341003602d008200342013703c808200341b0026a200341c8086a10e90220032802cc082102200341f8036aad428080808080048420033502d00842208620032802c8082204ad84100102402002450d002004102c0b410021040c0f0b2001410c6a2802002111200141086a2802002107200141046a2802002109200141106a290300210a2002411a6a2901002110200241196a2d00002112200241186a2d00002113200241166a2f01002114200241156a2d00002115200241146a2d00002116200241126a2f01002117200241116a2d00002118200241106a2d000021082002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210f2002410a6a2f01002119200241096a2d0000211a200241046a2d0000211b41022104200241026a2f0100211c0240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f0100210e200241086a2d00002102410021060c010b41012106410021024100210e0b200e41ffff0371410874200241187472200441ff017172210e02402006450d0041d6b2c0002104410f21020240024002400240200e0e050001020312000b2019410874201a72200f411874722104200c410874200d7220084118747221020c110b41dd8cc6002104410e21020c100b41c3b2c0002104411321020c0f0b41b2b2c0002104411121020c0e0b200320103703e008200320123a00df08200320133a00de08200320143b01dc08200320153a00db08200320163a00da08200320173b01d808200320183a00d708200320083a00d6082003200c3b01d4082003200d3a00d3082003200f3a00d208200320193b01d0082003201a3a00cf082003200e3600cb082003201b3a00ca082003201c3b01c80841e4d2c500ad4280808080800184100222022f0000210420022d0002210e2002280003210620022d00072108200229000821102002102c41b7e4c300ad4280808080800184100222022f0000210c20022d0002210d2002280003210f20022d00072119200229000821052002102c200320053701c806200320193a00c7062003200f3600c3062003200d3a00c2062003200c3b01c006200320103701b806200320083a00b706200320063600b3062003200e3a00b206200320043b01b006200341c0006a200341b0066a4120109e01420021050240024020032903484201200328024022021b2210200341d0006a290300420020021b220b8450450d004200211d0c010b200341206a200b4200200a420010e005200341306a20104200200a420010e005200341106a420042002010420010e00502402003290328200329031884420052200341386a2903002205200329032020032903107c7c221d20055472450d0041a7c4c1002104412721020c0f0b200329033021050b200341b0026a200341c8086a2005201d410810ac01024020032802b0024101470d0020032802b802210220032802b40221040c0e0b4110210e200341b0026a41106a290300211e20032903b802211f41e4d2c500ad4280808080800184100222022f0000210620022d000221082002280003210c20022d0007210d200229000821052002102c41f4d2c500ad4280808080f00184100222022f0000210f20022d000221192002280003210420022d0007211a2002290008211d2002102c2003201d370390042003201a3a008f04200320044118763a008e04200320044108763b018c04200320043a008b04200320193a008a042003200f3b018804200320054238883c008704200320054230883c008604200320054220883d018404200320054218883c008304200320054210883c008204200320053d0180042003200d3a00ff032003200c3600fb03200320083a00fa03200320063b01f803200341b0026a200341f8036a10e70320032903b002210520032903b802212020032903c002212120032903c802212220032903d002212320032903d802212420032903e002212520032903e802212620032903f002212720032903f8022128200329038003211d200328028803210d200328028c0321042003280290032106200328029403210f2003280298032108200328029c03210c20032d00a00321022003200341b0026a41f4006a2800003600fb03200320032800a1033602f8030240024020024102470d0042012105200342013703f806200342af013703f00620034287013703e806200342013703e006200342013703d806200342013703d006200342013703c806200342013703c006200342013703b806200342013703b0064100210220034100360288074120210c418080012108418080042106410421044201211d0c010b200341b0066a41f4006a20032800fb033600002003200d36028807200320283703f806200320273703f006200320263703e806200320253703e006200320243703d806200320233703d006200320223703c806200320213703c006200320203703b806200320053703b006200320032802f8033600a107200f210e0b2003200542002011ad2220420010e005200320023a00a0072003200c36029c0720032008360298072003200e3602940720032006360290072003200436028c072003201d370380074200200a427f200329030020032903084200521b7d22052005200a5622021b210502402002450d0041bbe8c2002104412c21020c0c0b200341b0026a20092011200341b0066a10ff03024020032802b0024101470d00200341b8026a280200210220032802b40221040c0c0b200341e8076a41186a2204200341b0026a410472220241186a280200360200200341e8076a41106a2206200241106a290200370300200341e8076a41086a2208200241086a290200370300200320022902003703e807200341f8046a41186a220e20204220862009ad841006220241186a290000370300200341f8046a41106a220d200241106a290000370300200341f8046a41086a220f200241086a290000370300200320022900003703f8042002102c20034192026a221920032d00fa043a0000200341d8096a41086a221a200341f8046a41136a290000370300200341e5096a2212200e290000370000200320032f01f8043b01900220032003290083053703d80920032800fb04210c20032800ff042102200341f8036a41186a2004280200360200200341f8036a41106a2006290300370300200341f8036a41086a22062008290300370300200320032903e8073703f803200320023600b7022003200c3600b302200320192d00003a00b202200320032f0190023b01b002200341b0026a41136a201a290300370000200341b0026a41186a2012290000370000200320032903d8093700bb0241e4d2c500ad428080808080018410022204290008211d20042d000721082004280003211920042d0002211a20042f000021122004102c419ee4c300ad4280808080b0018410022204290008212020042d000721132004280003211420042d0002211520042f000021162004102c200341f8046a200341b0026a109f0141c000102a2204450d0320042020370018200420133a001720042014360013200420153a0012200420163b00102004201d370008200420083a0007200420193600032004201a3a0002200420123b0000200420032903f804370020200441286a200f290300370000200441306a200d290300370000200441386a200e290300370000200341003602b802200342013703b002200341f8036a200341b0026a108901200341f8036a410472200341b0026a1089012006200341b0026a10890120032d00900421080240024020032802b40220032802b802220e460d0020032802b00221060c010b200e41016a2206200e490d05200e410174220d2006200d20064b1b220d4100480d0502400240200e0d00200d102a21060c010b20032802b002200e200d102e21060b2006450d042003200d3602b402200320063602b0020b2003200e41016a3602b8022006200e6a20083a0000200328028404210f2003418c046a2802002206200341b0026a10670240024020032802b402220d20032802b80222086b2006490d0020032802b002210e0c010b200820066a220e2008490d05200d4101742219200e2019200e4b1b22194100480d0502400240200d0d002019102a210e0c010b20032802b002200d2019102e210e0b200e450d04200320193602b4022003200e3602b0022019210d0b200e20086a200f200610db051a2004ad4280808080800884200820066aad422086200ead8410010240200d450d00200e102c0b2004102c024020034188046a280200450d00200f102c0b200341c3026a200341d8096a41086a290300370000200341b0026a41186a200341e5096a290000370000200320032f0190023b01b002200320023600b7022003200c3600b302200320032903d8093700bb02200320034192026a2d00003a00b20241e4d2c500ad428080808080018410022204290008211d20042d0007210e2004280003210620042d0002210820042f0000210d2004102c4192e4c300ad4280808080c0018410022204290008212020042d0007210f2004280003211920042d0002211a20042f000021122004102c200341f8046a200341b0026a109f0141c000102a2204450d03200420203700182004200f3a0017200420193600132004201a3a0012200420123b00102004201d3700082004200e3a000720042006360003200420083a00022004200d3b0000200420032903f804370020200441286a200341f8046a41086a290300370000200441306a200341f8046a41106a290300370000200441386a200341f8046a41186a290300370000200341c0003602b402200320043602b00220092011200341b0026a10f1022004102c02402007450d002009102c0b200341f8036a41026a20034190026a41026a2d000022043a0000200341f8046a41086a220e200341d8096a41086a290300370300200341f8046a410d6a2206200341d8096a410d6a290000370000200320032f01900222073b01f803200320032903d8093703f804200341b0026a41086a41023a0000200341b9026a20073b0000200341bb026a20043a0000200341b0026a41106a2002360200200341bc026a200c3602002003410d3a00b002200341c4026a20032903f804370200200341cc026a200e290300370200200341d1026a20062900003700004100210441014100200341b0026a109201200341c8086a200a20052010200b201f201e10b9020c0c0b200141c0006a2903002110200141386a29030021052002411a6a290100210b200241196a2d00002129200241186a2d0000212a200241166a2f0100212b200241156a2d0000212c200241146a2d0000212d200241126a2f0100212e200241116a2d0000212f200241106a2d000021302002410e6a2f010021312002410d6a2d000021322002410c6a2d000021332002410a6a2f01002134200241096a2d00002135200241046a2d0000213641022104200241026a2f01002137200141306a28020021382001412c6a2802002108200141286a28020021092001411d6a290000210a2001411c6a2d0000210c2001411b6a2d0000210d200141196a2f0000210f200141186a2d00002119200141176a2d0000211a200141156a2f00002112200141146a2d00002113200141136a2d00002114200141116a2f00002115200141106a2d000021162001410f6a2d000021172001410d6a2f000021182001410c6a2d0000211b200141086a280200210e200141076a2d0000211c200141056a2f00002111200141046a2d00002139200141c8006a290300211d0240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f01002106200241086a2d00002102410021070c010b4101210741002102410021060b200641ffff0371410874200241187472200441ff01717221060240024002402007450d0041d6b2c0002104410f210202400240024020060e05000401020f000b20344108742035722033411874722104203141087420327220304118747221020c0e0b41c3b2c0002104411321020c0d0b41b2b2c0002104411121020c0c0b203941ff01714101470d01200341b0026a200e41067610910220032802b00221040240024020032802b802200e413f7122024b0d00410021020c010b200420024105746a2202290018210a20022d0017210c20022d0016210d20022f0014210f20022d0013211920022d0012211a20022f0010211220022d000f211320022d000e211420022f000c211520022d000b211620022d000a211720022f0008211820022d0007211b2002280003210e20022d0002211c20022f00002111410121020b024020032802b402450d002004102c0b20020d010b41dd8cc6002104410e21020c0a0b2003200a370390042003200c3a008f042003200d3a008e042003200f3b018c04200320193a008b042003201a3a008a04200320123b018804200320133a008704200320143a008604200320153b018404200320163a008304200320173a008204200320183b0180042003201b3a00ff032003200e3600fb032003201c3a00fa03200320113b01f8032003200b3703c806200320293a00c7062003202a3a00c6062003202b3b01c4062003202c3a00c3062003202d3a00c2062003202e3b01c0062003202f3a00bf06200320303a00be06200320313b01bc06200320323a00bb06200320333a00ba06200320343b01b806200320353a00b706200320063600b306200320363a00b206200320373b01b006200341c8026a200329039004370300200341b0026a41106a200329038804370300200341b0026a41086a200329038004370300200320032903f8033703b002200320383602d008200320083602cc08200320093602c808200341f8046a200341b0066a200341b0026a20052010201d200341c8086a10d503024020032802f8044101460d00200341f8046a41086a280200450d0820032802fc04102c0c080b20032802fc042204450d07200341f8046a41086a2802002102200341f8046a41106a280200450d0820034184056a280200102c0c080b200141386a2903002105200141306a290300210b200141c0006a290300210a200341d0016a41186a200141196a290000370300200341d0016a41106a200141116a290000370300200341d0016a41086a200141096a290000370300200320012900013703d0012002411a6a2901002110200241196a2d00002112200241186a2d00002113200241166a2f01002114200241156a2d00002115200241146a2d00002116200241126a2f01002117200241116a2d00002118200241106a2d000021092002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210f2002410a6a2f01002119200241096a2d0000211a200241046a2d0000211b41022104200241026a2f0100211c2001412c6a2802002111200141286a280200210e200141246a28020021080240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f01002106200241086a2d00002102410021070c010b4101210741002106410021020b200641ffff0371410874200441ff017172200241187472210602402007450d0041d6b2c0002104410f21020240024002400240024020060e050001020304000b2019410874201a72200f411874722104200c410874200d7220094118747221020c030b41dd8cc6002104410e21020c020b41c3b2c0002104411321020c010b41b2b2c0002104411121020b200e450d062008102c0c060b2003201037038802200320123a008702200320133a008602200320143b018402200320153a008302200320163a008202200320173b018002200320183a00ff01200320093a00fe012003200c3b01fc012003200d3a00fb012003200f3a00fa01200320193b01f8012003201a3a00f701200320063600f3012003201b3a00f2012003201c3b01f00141e4d2c500ad4280808080800184100222022f0000210420022d000221062002280003210720022d00072109200229000821102002102c41b7e4c300ad4280808080800184100222022f0000210c20022d0002210d2002280003210f20022d000721192002290008211d2002102c2003201d3701c806200320193a00c7062003200f3600c3062003200d3a00c2062003200c3b01c006200320103701b806200320093a00b706200320073600b306200320063a00b206200320043b01b006200341a0016a200341b0066a4120109e014200211d024002400240024020032903a801420120032802a00122021b2210200341b0016a290300420020021b221f8450450d004200211e0c010b20034180016a201f4200200a420010e00520034190016a20104200200a420010e005200341f0006a420042002010420010e005024020032903880120032903788442005220034198016a290300221d20032903800120032903707c7c221e201d5472450d004127210241a7c4c10021040c020b200329039001211d0b200341b0026a200341f0016a201d201e410810ac0120032802b0024101470d0120032802b802210220032802b40221040b200e450d062008102c0c060b41102106200341b0026a41106a290300211e20032903b802211d20034190026a41186a201f370300200320103703a0022003200a370398022003200a3703900241e4d2c500ad4280808080800184100222022f0000210720022d000221092002280003210c20022d0007210d2002290008210a2002102c41f4d2c500ad4280808080f00184100222022f0000210f20022d000221192002280003210420022d0007211a200229000821102002102c20032010370390042003201a3a008f04200320044118763a008e04200320044108763b018c04200320043a008b04200320193a008a042003200f3b0188042003200a4238883c0087042003200a4230883c0086042003200a4220883d0184042003200a4218883c0083042003200a4210883c0082042003200a3d0180042003200d3a00ff032003200c3600fb03200320093a00fa03200320073b01f803200341b0066a200341f8036a10e70320032903b006211020032903b806211f20032903c006212020032903c806212120032903d006212220032903d806212320032903e006212420032903e806212520032903f006212620032903f8062127200329038007210a200328028807210d200328028c0721042003280290072107200328029407210f2003280298072109200328029c07210c20032d00a00721022003200341b0066a41f4006a2800003600fb03200320032800a1073602f8030240024020024102470d004201210a200342013703f802200342af013703f00220034287013703e802200342013703e002200342013703d802200342013703d002200342013703c802200342013703c002200342013703b802200342013703b0024100210220034100360288034120210c418080012109418080042107410421040c010b200341b0026a41f4006a20032800fb033600002003200d36028803200320273703f802200320263703f002200320253703e802200320243703e002200320233703d802200320223703d002200320213703c802200320203703c0022003201f3703b802200320103703b002200320032802f8033600a103200f21060b200341b0036a4200370300200341e0036a4200370300200341d0036a4200370300200341c0036a4200370300200320023a00a0032003200c36029c032003200936029803200320063602940320032007360290032003200436028c032003200a370380032003428080e983b1de163703a80320034280a094a58d1d3703d80320034280a094a58d1d3703c80320034280a094a58d1d3703b803200342a08080808080103703e8032003200341b0026a3602f0032003200341b0026a3602f403200341f8046a41186a2204200341f0016a41186a290300370300200341f8046a41106a2206200341f0016a41106a290300370300200341f8046a41086a2207200341f0016a41086a290300370300200320032903f0013703f80441f9e8c500ad4280808080900184100222022f0000210920022d0002210c2002280003210d20022d0007210f2002290008210a2002102c419db1c200ad42808080803084100222022f0000211920022d0002211a2002280003211220022d00072113200229000821102002102c200320103701c806200320133a00c706200320123600c3062003201a3a00c206200320193b01c0062003200a3701b8062003200f3a00b7062003200d3600b3062003200c3a00b206200320093b01b006200341e0006a200341b0066a1098012003290368210a200328026021094191b0c200ad4280808080e00084100222022f0000210c20022d0002210d2002280003210f20022d00072119200229000821102002102c41acb0c200ad4280808080e00084100222022f0000211a20022d000221122002280003211320022d000721142002290008211f2002102c2003201f3701c806200320143a00c706200320133600c306200320123a00c2062003201a3b01c006200320103701b806200320193a00b7062003200f3600b3062003200d3a00b2062003200c3b01b006200341d8006a200341b0066a4120109401200341b0046a4200370300200341f8036a412c6a41c0ecc1003602004101211b200341f8036a41286a410136020020034194046a41d0e1c100360200200341d0046a2007290300370300200341d8046a2006290300370300200341e0046a2004290300370300200341f8036a41206a42003703002003428080808080013703a8042003420037038004200320032903f8043703c80441002118200341003602900420032802582102200328025c21042003200341f4036a3602c0042003200341f0036a3602bc042003200341b0026a3602b80420032004410020021b3602c4042003200a420020091b3703f80320032011360280052003200e3602fc04200320083602f804200341b0066a200341f8036a200b200520034190026a200341d0016a200341f8046a10dd0220032802b0064101470d03200341b0066a41106a28020022114108762139200341bc066a2802002130200341b0066a41086a280200210220032802b406211c410121184101211b0c040b200141216a2d00002116200341e8076a41186a200141196a290000370300200341e8076a41106a200141116a290000370300200341e8076a41086a200141096a290000370300200320012900013703e807200341c8086a41186a2001413a6a290000370300200341c8086a41106a200141326a290000370300200341c8086a41086a2001412a6a2900003703002003200141226a2900003703c808200341b0026a41086a2002411e6a2801003602002003200241166a2901003703b00220022800012106200241156a2d00002107200241146a2d00002108200241126a2f01002109200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210f2002410d6a2d000021192002410c6a2d0000211a2002410a6a2f01002112200241096a2d00002113200241056a280000210e0240024020022d00002215450d00200e4118762117200e410876211841002114200341b0026a21022006211b0c010b20064118762115200341b0026a410472210241012114200e211b2013210e20122118201a211720192113200f2112200d211a200c21192009210f2008210d2007210c20032f01b002210920032d00b202210820032d00b30221070b2002290100210a200341f8036a41186a200341c8086a41186a290300370300200341f8036a41106a200341c8086a41106a290300370300200341f8036a41086a200341c8086a41086a290300370300200320032903c8083703f80341e6b3c400210441e90021022014450d0c02400240201641ff01714101460d00200641ff01714101470d0e20064108762102410221060c010b200641ff01714102470d0d41002106200329039004210a20032d008f04210720032d008e04210820032f018c04210920032d008b04210c20032d008a04210d20032f018804210f20032d008704211920032d008604211a20032f018404211220032d008304211320032d008204211720032f018004211820032d00ff03210e20032800fb03211b20032d00fa03211520032f01f80321020b2003200a37039005200320073a008f05200320083a008e05200320093b018c052003200c3a008b052003200d3a008a052003200f3b018805200320193a0087052003201a3a008605200320123b018405200320133a008305200320173a008205200320183b0180052003200e3a00ff042003201b3600fb04200320153a00fa04200320023b01f80441002104200341b0026a200341e8076a2006410010e30220032d00b0022102024020032d00b8020d00200341d4026a280200450d00200341d0026a280200102c0b200241ff01714101470d0b200341b0026a200341f8046a42808086bdbacdd21a420010b801024020032802b0024101470d0020032802b802210220032802b40221040c0d0b200341b0026a41106a290300211020032903b8022105418be9c500ad4280808080800184220a100222022f0000210e20022d000221062002280003210720022d000721082002290008210b2002102c41c9b5c000ad4280808080d00184221d100222022f0000210920022d0002210c2002280003210d20022d0007210f2002290008211f2002102c2003201f3701c8062003200f3a00c7062003200d3600c3062003200c3a00c206200320093b01c0062003200b3701b806200320083a00b706200320073600b306200320063a00b2062003200e3b01b006200341b8016a200341b0066a4120109e01200341b8016a41106a290300210b20032903c001211f20032802b801210e200a100222022f0000210620022d000221072002280003210820022d000721092002290008210a2002102c201d100222022f0000210c20022d0002210d2002280003210f20022d000721192002290008211d2002102c2003201d3701c806200320193a00c7062003200f3600c3062003200d3a00c2062003200c3b01c0062003200a3701b806200320093a00b706200320083600b306200320073a00b206200320063b01b0062003427f2010200b4200200e1b220a7c2005201f4200200e1b22107c22052010542202ad7c221020022010200a542010200a511b22021b370380042003427f200520021b3703f803200341b0066aad4280808080800484200341f8036aad428080808080028410010c0b0b1033000b1035000b200341e0066a28020022114108762139200341b0066a412c6a2802002130200341b0066a41286a2802002102200341d4066a280200211c201141ff01710d00200341b0066a41086a20034198046a290300370300200341f8046a41086a200341bc066a28020036020020032003290390043703b006200320032902b4063703f804200341880a6a200341f8046a10f10141002118410021114100211b0b200341f0016a20032903900220032903980220032903a00220034190026a41186a290300201d201e10b90220032802b404210e20032802b0042106200320032802ac0422043602f004200320063602ec04200320043602e80420032004200e41b8016c6a220f3602f4040240200e450d00200341c8086a4101722114200341ef076a2115200341e8076a4102722107200341b0066a41106a2116200341d8066a211320034194076a211a200341f1066a2108200341d1066a2109200341b0066a4101722119200341a8076a2117034020042d0000210e200341f8046a200441016a41b70110db051a02400240200e4103460d002003200e3a00b0062019200341f8046a41b70110db0521060240024002400240200e0e03000102000b20032802b806210d20032802bc06210620032802b406210e2015201641d80010db051a2003410d3a00c8082014200341e8076a41df0010db051a200e2006200341c8086a109201410121064100210c0240200d450d00200e102c0b4100210d0c020b20032f00b106210e20032d00b306210c20032802b406210d20032d00b806211220032900b906210a20032900c106211020032900c9062105200341c8086a201341900110db051a20072006290000370000200741086a200641086a290000370000200741106a200641106a290000370000200741186a200641186a29000037000020034180023b01e807200341d8096a200341c8086a200341e8076a10c102200320032d00e0094102463a00f108200320053700e908200320103700e1082003200a3700d908200320123a00d8082003200d3602d4082003200c3a00d3082003200e3b00d108200341043a00d0082003410d3a00c808410021064101210c41014100200341c8086a1092014100210d0c010b2017290300210a20032903a0072110200341d8096a41186a200641186a290000370300200341d8096a41106a200641106a290000370300200341d8096a41086a200641086a290000370300200320062900003703d809200341e8076a41186a200941186a290000370300200341e8076a41106a200941106a290000370300200341e8076a41086a200941086a290000370300200320092900003703e807200341c8086a41186a200841186a290000370300200341c8086a41106a200841106a290000370300200341c8086a41086a200841086a290000370300200320082900003703c808200341f8096a41086a201a41086a2802003602002003201a2902003703f809200341d8096a200341e8076a200341c8086a2010200a200341f8096a10c6044101210c410121064101210d0b024020032d00b006220e41014b0d0002400240200e0e020001000b200c450d03024020032802b806450d0020032802b406102c0b20032d00c0064105490d0320032802e806450d0320032802e406102c0c030b2006450d0220131092020c020b200d20032802980745720d01200328029407102c0c010b2003200441b8016a3602f0040c020b200441b8016a2204200f470d000b2003200f3602f0040b200341e8046a107202402003280284042204450d0020034188046a280200450d002004102c0b0240201b450d00200341f8036a411c6a2802002104200328029c0421080240024020032802980422060d002004210e0c010b200621072004210e0340200e2802880b210e2007417f6a22070d000b0340200420042f01064102746a41880b6a28020021042006417f6a22060d000b0b200341b0066a411c6a20042f0106360200200341c8066a4100360200200341c4066a2004360200200320083602d006200341003602c006200342003703b8062003200e3602b406200341003602b006200341b0066a10f9010b024020180d0041002104024020020d00410021020c020b201c102c0c010b0240201c0d00410021040c010b02402039410874201141ff017172450d002030102c0b201c21040b41002107410121060c080b410021040b41012107410021060c060b41012107410021062008450d052009102c0c050b02402007450d002009102c0b200341c8086a200a20052010200b201f201e10b9020b4100210841012106410121070c040b410021084101210602402007450d002009102c0b410121070c030b0b41012106410121070b410121080b024020012d0000417e6a220e41024b0d000240024002400240200e0e03000102000b2008450d03200141086a280200450d03200141046a280200102c0c030b20060d010c020b2007450d01200141286a280200450d01200141246a280200102c0c010b2001412c6a280200450d00200141286a280200102c0b2000200236020420002004360200200341900a6a24000b901008087f027e047f017e057f027e017f057e230022042105200441a0016b41607122042400024002400240200141ffffff3f712001470d0020014105742206417f4c0d000240024020060d00410121070c010b2006102a2207450d020b410021084100210602402001450d002001410574210820072106034020062000290000370000200641186a200041186a290000370000200641106a200041106a290000370000200641086a200041086a290000370000200641206a2106200041206a2100200841606a22080d000b200141057441606a41057641016a2106200121080b200420063602102004200836020c2004200736020820072006410041202006676b108903200441e0006a41186a22094200370300200441e0006a41106a220a4200370300200441e0006a41086a220b420037030020044200370360200441286a41086a220841cee5c200ad4280808080b00284220c1002220041086a290000370300200420002900003703282000102c200b200829030037030020042004290328370360200841e1e5c200ad42808080809001841002220041086a290000370300200420002900003703282000102c200a2004290328220d370300200441c0006a41086a220e200b290300370300200441c0006a41106a220f200d370300200441c0006a41186a221020082903003703002004200d3703900120042004290360370340200441e0006a200441c0006a412010d00120042802602200410120001b21112004290264420020001b2212422088a72200450d0220004105742113200441e0006a4114722114200441e0006a4108722115200441c0006a410c722116200441e0006a410c6a2117201121060340200641086a290000210d200641106a2900002118200629000021192009200641186a290000370300200a2018370300200b200d370300200420193703602008200c1002220041086a290000370300200420002900003703282000102c200441186a41086a2201200829030037030020042004290328370318200841f1e5c200ad4280808080e000841002220041086a290000370300200420002900003703282000102c20044190016a41086a220720082903003703002004200429032837039001200441c0006a200441e0006a109f0141c000102a2200450d0220002004290318370000200020042903900137001020002004290040370020200041086a2001290300370000200041186a2007290300370000200041286a200e290000370000200041306a200f290000370000200041386a2010290000370000200441e0006a200041c00010e5032008201741086a290200370300200441286a41106a221a201741106a28020036020020042017290200370328024020042802682201450d002004290360210d20162004290328370200201641086a2008290300370200201641106a201a2802003602002004200d3703400b20042001360248200441003602682004290358211920042004290378221b3703582004290350211c20042004290370221d3703502004290340211e2004200429036022183703402004290348210d20042004290368221f370348201fa7210102400240200da7221a0d00201f210d201d211c201b21190c010b2004201e3703602004200d3703682004201c370370200420193703782004201a201ca74105746a3602342004201a3602302004200d422088a736022c2004201a3602282004200441086a36023820044190016a200441286a108501201541086a200728020036020020152004290390013702002004201c422088a7221a2019422088a74105746a3602342004201a36023020042019a736022c2004201a3602282004200441086a36023820044190016a200441286a108501201441086a200728020036020020142004290390013702002004290368210d20042903602118200429037821192004290370211c02402001450d00201ba721070240201f422088a7450d002001102c0b2007450d00201d422088a7102c0b200420183703402004200d3703482004201c37035020042019370358200da721010b200420183703602004200d3703682004201c370370200da72107200420193703780240024020010d002000ad428080808080088410050c010b200441c00036022c20042000360228200441e0006a200441286a10fd030b02402007450d002019a721010240200d422088a7450d002007102c0b2001450d00201c422088a7102c0b200641206a21062000102c201341606a22130d000c030b0b103a000b1033000b02402012a7450d002011102c0b200441c0006a41186a4200370300200441c0006a41106a22014200370300200441c0006a41086a2206420037030020044200370340200441286a41086a220041cee5c200ad4280808080b002841002220841086a290000370300200420082900003703282008102c2006200029030037030020042004290328220d3703182004200d370340200041eae5c200ad4280808080f000841002220841086a290000370300200420082900003703282008102c20012004290328220d370300200441e0006a41086a2006290300370300200441e0006a41106a200d370300200441e0006a41186a20002903003703002004200d370390012004200429034037036020044100360248200442013703402003200441c0006a106702402003450d002003410574210003402002200441c0006a109101200241206a2102200041606a22000d000b0b20042802442100200441e0006aad4280808080800484200435024842208620042802402206ad84100102402000450d002006102c0b0240200428020c450d002004280208102c0b200524000bf71405177f017e017f027e047f230041206b220224000240024020014115490d00024002402001410176220341ffffff3f712003470d0020034105742204417f4c0d0041012105024002402004450d002004102a2205450d010b200041606a2106200041a07f6a210741002108410021094104210a4100210b2001210c034002400240200c220d417f6a220e0d004101210f4100210c0c010b0240024002400240024002402000200e4105746a200d410574221020006a41406a412010dd054100480d004102200d6b210e200720106a21044101210f03400240200e200f6a4101470d004100210c200d210f0c080b200f41016a210f200441206a2004412010dd052111200441606a21042011417f4a0d000b200d200f6b210e0c010b200720106a2104024003400240200e4101470d004100210e0c020b200e417f6a210e200441206a2004412010dd052111200441606a210420114100480d000b0b200d200e490d01200d20014b0d03200d200e6b220f4101762212450d00200620106a21042000200e4105746a21110340200241186a2210201141186a2213290000370300200241106a2214201141106a2215290000370300200241086a2216201141086a221729000037030020022011290000370300200441086a22182900002119200441106a221a290000211b200441186a220c290000211c201120042900003700002013201c3700002015201b37000020172019370000200c2010290300370000201a20142903003700002018201629030037000020042002290300370000200441606a2104201141206a21112012417f6a22120d000b0b0240200e0d00200e210c0c050b0240200f41094d0d00200e210c0c050b200d20014b0d01200d200e6b21122000200e4105746a21100340200d200e417f6a220c490d040240200d200c6b220f4102490d002000200e4105746a22042000200c4105746a220e412010dd05417f4a0d00200e2900002119200e2004290000370000200241186a2216200e41186a2211290000370300200241106a2217200e41106a2213290000370300200241086a2218200e41086a22142900003703002014200441086a2900003700002013200441106a2900003700002011200441186a29000037000020022019370300410121150240200f4103490d00200e41c0006a2002412010dd05417f4a0d00410221112010210402400340200441186a200441386a290000370000200441106a200441306a290000370000200441086a200441286a2900003700002004200441206a221329000037000020122011460d01200441c0006a21142011211520132104201141016a211120142002412010dd05417f4a0d020c000b0b201121150b200e20154105746a22042002290300370000200441186a2016290300370000200441106a2017290300370000200441086a20182903003700000b200c450d05201041606a2110201241016a2112200c210e200f410a4f0d050c000b0b200e200d1047000b200d200e417f6a220c490d010b200d2001103f000b200c200d1047000b0240200b2009470d0002400240200941016a22042009490d00200941017422112004201120044b1b220441ffffffff01712004470d002004410374221141004e0d010b1035000b0240024020090d002011102a210a0c010b200a20094103742011102e210a0b200a450d02200421092008210b0b200a200b4103746a2204200f3602042004200c360200200841016a220b21080240200b4102490d00024003400240024002400240200a200b417f6a22084103746a2204280200450d00200b410374200a6a220f41746a280200220e200428020422114d0d000240200b41024b0d00200b21084102210b200c450d0b0c080b200a200b417d6a22164103746a28020422042011200e6a4d0d010240200b41034b0d00200b21084103210b200c450d0b0c080b200f41646a2802002004200e6a4d0d01200b21080c060b200b4103490d0120042802042111200a200b417d6a22164103746a28020421040b20042011490d010b200b417e6a21160b024002400240024002400240200b201641016a221d4b221e450d00200b20164b221f450d01200a20164103746a2217280204222020172802006a2204200a201d4103746a2218280200221a490d02200420014b0d032000201a4105746a22142018280204221541057422116a210f2004410574210e2004201a6b220d20156b220420154f0d042005200f2004410574221110db05221320116a21120240024020154101480d00200441014e0d010b200f2104201321110c060b2006200e6a210e200f21040340200e200441606a220f201241606a220d200d200f412010dd0541004822101b2211290000370000200e41186a201141186a290000370000200e41106a201141106a290000370000200e41086a201141086a2900003700002012200d20101b211202402014200f200420101b2204490d00201321110c070b200e41606a210e2013211120132012490d000c060b0b41d087c600201d200b1038000b41d087c6002016200b1038000b201a20041047000b20042001103f000b20052014201110db05221320116a21120240024020154101480d00200d20154a0d010b20142104201321110c010b2000200e6a2110201321112014210403402004200f2011200f2011412010dd05410048220d1b220e290000370000200441186a200e41186a290000370000200441106a200e41106a290000370000200441086a200e41086a2900003700002011201141206a200d1b2111200441206a2104200f41206a200f200d1b220f20104f0d01201220114b0d000b0b20042011201220116b41607110db051a0240201f450d002017201a360200201741046a202020156a360200201e450d022018201841086a200b201d417f736a41037410dc051a2008210b200841014d0d030c010b0b41a888c6002016200b1038000b418ab4c000411d41acfec5001036000b200c450d030c000b0b1033000b103a000b02402009450d00200a102c0b2003450d012005102c0c010b20014102490d002001417f6a2111200141057420006a41206a2110410121120340024002400240024020112204417f6a221120014b0d00200120116b220e4102490d03200020044105746a2204200020114105746a220d412010dd05417f4a0d03200d2900002119200d2004290000370000200241186a2214200d41186a220f290000370300200241106a220b200d41106a2213290000370300200241086a2215200d41086a220a290000370300200a200441086a2900003700002013200441106a290000370000200f200441186a2900003700002002201937030041012104200e4103490d02200d41c0006a2002412010dd05417f4a0d0241002113201021040340200441406a220e200441606a220f290000370000200e41186a200f41186a290000370000200e41106a200f41106a290000370000200e41086a200f41086a29000037000020122013220e460d02200e417f6a211320042002412010dd05210f200441206a2104200f417f4a0d020c000b0b201120011047000b4102200e6b21040b200d20044105746a22042002290300370000200441186a2014290300370000200441106a200b290300370000200441086a20152903003700000b201041606a21102012417f6a211220110d000b0b200241206a24000ba00901177f230041206b220424002002410020031b21052000410020011b2106200241206a200220031b2107200041206a200020011b2108200020014105746a2109200220034105746a210a4100210b4100210c4101210d4100210e4100210f41012110024002400340200b4101742111200b41057421120240024002400340024020050d0020072113200d2114200c2115200b21160c020b2005210220072103200d2114200c2115200b2116201221172011211802400340024002402006450d0020022006460d0320022006412010dd052213450d032013417f4c0d01200321072014210d2015210c2016210b200221050c060b200441186a2203200541186a290000370300200441106a2216200541106a290000370300200441086a2206200541086a290000370300200420052900003703000240200b200c470d00200b41016a2202200b490d0a200b41017422172002201720024b1b220c41ffffff3f71200c470d0a200c41057422024100480d0a02400240200b0d002002102a210d0c010b200d200b4105742002102e210d0b200d450d090b200d200b4105746a22022004290300370000200241186a2003290300370000200241106a2016290300370000200241086a200629030037000041002106410020072007200a4622021b2105201141026a2111201241206a2112200b41016a210b2007200741206a20021b21070c030b200441186a2213200241186a290000370300200441106a2219200241106a290000370300200441086a221a200241086a29000037030020042002290000370300024020162015470d00201641016a22022016490d0920182002201820024b1b221541ffffff3f712015470d09201541057422024100480d090240024020160d002002102a21140c010b201420172002102e21140b2014450d080b201420176a22022004290300370000200241186a2013290300370000200241106a2019290300370000200241086a201a290300370000410020032003200a4622131b2102201841026a2118201741206a2117201641016a21162003200341206a20131b221321032002450d030c000b0b0b2014210d2015210c2016210b2003200341206a2003200a4622021b210741002008200820094622161b21064100200320021b21052008200841206a20161b21080c030b410021052006450d01201321072014210d2015210c2016210b0b200441186a2203200641186a290000370300200441106a2216200641106a290000370300200441086a2217200641086a290000370300200420062900003703000240200e200f470d00200e41016a2202200e490d04200e41017422062002200620024b1b220f41ffffff3f71200f470d04200f41057422024100480d0402400240200e0d002002102a21100c010b2010200e4105742002102e21100b2010450d030b2010200e4105746a22022004290300370000200241186a2003290300370000200241106a2016290300370000200241086a201729030037000041002008200820094622021b2106200e41016a210e2008200841206a20021b21080c010b0b201420162000200110f30202402015450d002014102c0b0240200f450d002010102c0b200441206a24000f0b1033000b1035000b896a07067f017e017f027e0f7f027e097f230041e0046b220324000240024002400240024002400240024002400240024002400240024002400240024020012d000022040e050001020304000b200341c4026a4101360200200342013702b402200341fcc4c5003602b002200341043602c403200341f4c4c5003602c0032003200341c0036a3602c002200341b0026a4184c5c5001041000b200141086a2802002104200141046a2802002105024020022d000120022d000072450d004111210241b2b2c00021062004450d0f2005102c0c0f0b20052001410c6a280200220210f402200341b0026a41186a22074200370300200341b0026a41106a22014200370300200341b0026a41086a22084200370300200342003703b002200341d0046a41086a220641cee5c200ad4280808080b0028422091002220a41086a2900003703002003200a2900003703d004200a102c20082006290300370300200320032903d0043703b002200641eae5c200ad4280808080f00084220b1002220a41086a2900003703002003200a2900003703d004200a102c200120032903d004220c370300200341c0036a41086a2008290300370300200341c0036a41106a200c370300200341c0036a41186a20062903003703002003200c370340200320032903b0023703c003200341b0026a200341c0036a412010d0012005200220032802b0022206410120061b220820032902b402420020061b220c422088a710f5020240200ca7450d002008102c0b2007420037030020014200370300200341b0026a41086a22084200370300200342003703b002200341d0046a41086a220620091002220a41086a2900003703002003200a2900003703d004200a102c20082006290300370300200320032903d004220c3703602003200c3703b0022006200b1002220a41086a2900003703002003200a2900003703d004200a102c200120032903d004220c370300200341c0006a41086a2008290300370300200341c0006a41106a200c370300200341c0006a41186a20062903003703002003200c370370200320032903b002370340200341003602b802200342013703b0022002200341b0026a106702402002450d00200241057421012005210203402002200341b0026a109101200241206a2102200141606a22010d000b0b20032802b4022102200341c0006aad428080808080048420033502b80242208620032802b0022201ad84100102402002450d002001102c0b4100210602402004450d002005102c0b0c0e0b200141046a28020021072002411a6a290100210c200241196a2d00002105200241186a2d00002108200241166a2f0100210a200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d000021132002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241046a2d0000211741022106200241026a2f010021180240024020022d00000d0020022d00014101470d00200241056a2d00002106200241066a2f01002119200241086a2d000021024100211a0c010b4101211a41002102410021190b2003200c3703c802200320053a00c702200320083a00c6022003200a3b01c4022003200d3a00c3022003200e3a00c2022003200f3b01c002200320103a00bf02200320113a00be02200320123b01bc02200320133a00bb02200320143a00ba02200320153b01b802200320163a00b702200320173a00b202200320183b01b0022003201941ffff0371410874200241187472200641ff01717222053600b3020240201a450d0041d6b2c0002106410f2102024002400240024020050e050001020310000b20032800b702210620032800bb0221020c0f0b41dd8cc6002106410e21020c0e0b41c3b2c0002106411321020c0d0b41b2b2c0002106411121020c0c0b20034180016a41186a200341b0026a41186a220629030037030020034180016a41106a200341b0026a41106a220529030037030020034180016a41086a200341b0026a41086a2202290300370300200320032903b00237038001200642003703002005420037030020024200370300200342003703b002200341d0046a41086a220641cee5c200ad4280808080b002841002220841086a290000370300200320082900003703d0042008102c20022006290300370300200320032903d0043703b002200641eae5c200ad4280808080f000841002220841086a290000370300200320082900003703d0042008102c200520032903d004220c370300200341c0036a41086a2002290300370300200341c0036a41106a200c370300200341c0036a41186a20062903003703002003200c370340200320032903b0023703c003200341b0026a200341c0036a412010d00120032902b402420020032802b00222021b220c422088a741057421062002410120021b220a210202400340024020060d00410021080c020b4101210820034180016a2002460d01200641606a2106200220034180016a412010dd052105200241206a210220050d000b0b0240200ca7450d00200a102c0b024020080d0041a0f7c2002106411521020c0c0b4100210a200341003602b802200342013703b0022007200341b0026a108b0120032802b4022106200341b0026a41186a220520033502b80242208620032802b002220fad841006220241186a290000370300200341b0026a41106a2208200241106a290000370300200341b0026a41086a220d200241086a290000370300200320022900003703b0022002102c200341a0016a41186a22022005290300370300200341a0016a41106a22052008290300370300200341a0016a41086a220e200d290300370300200320032903b0023703a00102402006450d00200f102c0b200341b0026a200741900110db051a200341c0036a410d6a20034180016a41086a290300370000200341c0036a41156a20034180016a41106a290300370000200341c0036a411d6a20034180016a41186a29030037000041012108200341013a00c40320032003290380013700c503200341023a00c003200341c0006a200341b0026a200341c0036a10c10220032d00482106200341b0026a410d6a200e290300370000200341b0026a41156a2005290300370000200341b0026a411d6a2002290300370000200341d5026a20064102463a0000200341053a00b402200341083a00b002200320032903a0013700b50241014100200341b0026a1092012007102c410021060c0c0b200141086a2802002107200141046a280200211b2002411a6a290100210c200241196a2d00002112200241186a2d00002113200241166a2f01002114200241156a2d00002115200241146a2d00002116200241126a2f01002117200241116a2d00002118200241106a2d0000210a2002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d00002111200241046a2d0000211941022106200241026a2f0100211a0240024020022d00000d0020022d00014101470d00200241056a2d00002106200241066a2f01002105200241086a2d00002102410021080c010b4101210841002105410021020b200541ffff0371410874200641ff017172200241187472210502402008450d0041d6b2c0002106410f2102024002400240024020050e05000102030e000b2010410874201172200f411874722106200d410874200e72200a4118747221020c0d0b41dd8cc6002106410e21020c0c0b41c3b2c0002106411321020c0b0b41b2b2c0002106411121020c0a0b2003200c37039801200320123a009701200320133a009601200320143b019401200320153a009301200320163a009201200320173b019001200320183a008f012003200a3a008e012003200d3b018c012003200e3a008b012003200f3a008a01200320103b018801200320113a0087012003200536008301200320193a0082012003201a3b018001200341b0026a41186a4200370300200341b0026a41106a220a4200370300200341b0026a41086a22064200370300200342003703b002200341d0046a41086a220241cee5c200ad4280808080b002841002220541086a290000370300200320052900003703d0042005102c20062002290300370300200320032903d0043703b002200241eae5c200ad4280808080f000841002220541086a290000370300200320052900003703d0042005102c200a20032903d004220c370300200341c0036a41086a2006290300370300200341c0036a41106a200c370300200341c0036a41186a20022903003703002003200c370340200320032903b0023703c003200341b0026a200341c0036a412010d00120032902b402420020032802b00222021b220c422088a741057421062002410120021b220d210202400340024020060d00410021080c020b4101210820034180016a2002460d01200641606a2106200220034180016a412010dd052105200241206a210220050d000b0b0240200ca7450d00200d102c0b024020080d0041a0f7c2002106411521020c0a0b200341003602b802200342013703b0022007200341b0026a108b0120032802b402210d200341b0026a41186a220620033502b80242208620032802b0022210ad841006220241186a290000370300200341b0026a41106a2205200241106a290000370300200341b0026a41086a2208200241086a290000370300200320022900003703b0022002102c200341a0016a41186a22022006290300370300200341a0016a41106a220e2005290300370300200341a0016a41086a220f2008290300370300200320032903b0023703a0010240200d450d002010102c0b200620022903003703002005200e2903003703002008200f290300370300200320032903a0013703b002200341d0046a41086a220241cee5c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a2002290300370300200320032903d004370360200241fcf0c200ad4280808080a001841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a2002290300370300200320032903d004370370200341c0006a200341b0026a109f0141c000102a2202450d0120022003290360370000200241086a200341e0006a41086a29030037000020022003290370370010200241186a200341f0006a41086a29030037000020022003290340370020200241286a200341c0006a41086a290300370000200241306a200341d0006a290300370000200241386a200341c0006a41186a290300370000200341186a200241c000410141004100109701200328021821062002102c20064101460d0202400240201b4102490d0042002109200341c0006a41186a220e4200370300200341c0006a41106a220f4200370300200341c0006a41086a2206420037030020034200370340200341d0046a41086a220241cee5c200ad4280808080b00284220c1002220541086a290000370300200320052900003703d0042005102c20062002290300370300200320032903d004220b3703602003200b370340200241ace9c500ad4280808080d00184220b1002220541086a290000370300200320052900003703d0042005102c200f20032903d004221c370300200341b0026a41086a22052006290300370300200341b0026a41106a2208201c370300200341b0026a41186a220d20022903003703002003201c370370200320032903403703b002200341106a200341b0026a41201094012003280214211120032802102112200e4200370300200f420037030020064200370300200342003703402002200c1002221041086a290000370300200320102900003703d0042010102c20062002290300370300200320032903d004221c3703602003201c3703402002200b1002221041086a290000370300200320102900003703d0042010102c200e2002290300221c37030020052006290300370300200820032903d004221d370300200d201c3703002003201d370370200320032903403703b002200341086a200341b0026a412010940120032802082110200328020c2113200e4200370300200f420037030020064200370300200342003703402002200c1002220f41086a2900003703002003200f2900003703d004200f102c20062002290300370300200320032903d004221c3703602003201c3703402002200b1002220f41086a2900003703002003200f2900003703d004200f102c200e2002290300220b37030020052006290300370300200820032903d004221c370300200d200b3703002003201c370370200320032903403703b0024101210e2003201341016a410120101b3602c003200341b0026aad4280808080800484200341c0036aad4280808080c000841001200d42003703002008420037030020054200370300200342003703b0022002200c1002220f41086a2900003703002003200f2900003703d004200f102c20052002290300370300200320032903d0043703b002200241e1e5c200ad42808080809001841002220f41086a2900003703002003200f2900003703d004200f102c20062002290300220c370300200320032903d004220b370340200a200b370000200a41086a200c370000200341c0036a41086a2005290300370300200341c0036a41106a2008290300370300200341c0036a41186a200d290300370300200320032903b0023703c003200341b0026a200341c0036a412010d0010240024020032802b002220a0d0041002106410021020c010b20032902b4022209422088a721022009a72106200a210e0b200d200341a0016a41186a2903003703002008200341a0016a41106a2903003703002005200341a0016a41086a290300370300200320032903a0013703b0020240024020022006460d002006210d0c010b024020062009a7220d470d00200641016a22022006490d08200641017422052002200520024b1b220d41ffffff3f71200d470d08200d41057422024100480d080240024020060d002002102a210e0c010b200e20064105742002102e210e0b200e450d0520094280808080708321090b2009422088a721020b200e20024105746a220620032903b002370000200641186a200341b0026a41186a2205290300370000200641106a200341b0026a41106a2208290300370000200641086a200341b0026a41086a2206290300370000200542003703002008420037030020064200370300200342003703b002200341d0046a41086a220541cee5c200ad4280808080b002841002220a41086a2900003703002003200a2900003703d004200a102c20062005290300370300200320032903d004220c3703602003200c3703b002200541e1e5c200ad42808080809001841002220a41086a2900003703002003200a2900003703d004200a102c200820032903d004220c370300200341c0006a41086a2006290300370300200341c0006a41106a200c370300200341c0006a41186a20052903003703002003200c370370200320032903b00237034002400240200e0d00200341c0006aad428080808080048410050c010b200341003602b802200342013703b002200241016a2206200341b0026a106702402006450d00200241057441206a2106200e210203402003200341b0026a3602c0032002200341c0036a109402200241206a2102200641606a22060d000b0b20032802b4022102200341c0006aad428080808080048420033502b80242208620032802b0022206ad84100102402002450d002006102c0b200d450d00200e102c0b200341b0026a200741900110db051a200341c0036a41186a200341a0016a41186a290300370300200341c0036a41106a200341a0016a41106a290300370300200341c0036a41086a200341a0016a41086a290300370300200320032903a0013703c003200341d0046a41086a220241cee5c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a22052002290300370300200320032903d004370360200241fcf0c200ad4280808080a001841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a22062002290300370300200320032903d004370370200341c0006a200341c0036a109f0141c000102a2202450d0320022003290360370000200241086a200529030037000020022003290370370010200241186a200629030037000020022003290340370020200241286a200341c0006a41086a290300370000200241306a200341c0006a41106a290300370000200241386a200341c0006a41186a290300370000200341003602c803200342013703c003200341b0026a200341c0036a108b0120032802c40321062002ad428080808080088420033502c80342208620032802c0032205ad84100102402006450d002005102c0b2002102c200341b0026a1092024120102a2206450d032006200329038001370000200641186a20034180016a41186a2208290300370000200641106a20034180016a41106a220a290300370000200641086a20034180016a41086a220d290300370000200341dc036a4100360200200341cc036a428180808010370200200342013702d403200320063602c8032003201b3602c40320032011410020121b220e3602c003200341b0026a41186a200341a0016a41186a220f290300370300200341b0026a41106a200341a0016a41106a2210290300370300200341b0026a41086a200341a0016a41086a2211290300370300200320032903a0013703b002200341d0046a41086a220241cee5c200ad4280808080b002841002220541086a290000370300200320052900003703d0042005102c200341e0006a41086a22122002290300370300200320032903d004370360200241f1e5c200ad4280808080e000841002220541086a290000370300200320052900003703d0042005102c200341f0006a41086a22052002290300370300200320032903d004370370200341c0006a200341b0026a109f0141c000102a2202450d0320022003290360370000200241086a201229030037000020022003290370370010200241186a200529030037000020022003290340370020200241286a200341c0006a41086a290300370000200241306a200341c0006a41106a290300370000200241386a200341c0006a41186a290300370000200341c0003602b402200320023602b002200341c0036a200341b0026a10fd032002102c2006102c200341bd026a200d290300370000200341c5026a200a290300370000200341cd026a2008290300370000200341d5026a20032903a001370000200341dd026a2011290300370000200341e5026a2010290300370000200341ed026a200f290300370000200341fc026a201b360200200341f8026a200e360200200341003a00b402200341083a00b00220032003290380013700b502200341b0026a21020c010b200341b0026a41186a22084200370300200341b0026a41106a220d4200370300200341b0026a41086a22064200370300200342003703b002200341d0046a41086a220241cee5c200ad4280808080b002841002220541086a290000370300200320052900003703d0042005102c20062002290300370300200320032903d0043703b002200241eae5c200ad4280808080f000841002220541086a290000370300200320052900003703d0042005102c200341c0006a41086a2002290300220c370300200320032903d0042209370340200a2009370000200a41086a200c370000200341c0036a41086a2006290300370300200341c0036a41106a200d290300370300200341c0036a41186a2008290300370300200320032903b0023703c003200341206a200341c0036a412010d00102400240200328022022060d00410021020c010b2003290224220c422088a72102200ca7450d002006102c0b200341b0026a200741900110db051a200341cc036a2002360200200341c0036a41086a4101360200200341003a00c403200341023a00c003200341c0006a200341b0026a200341c0036a10c10220032d00482102200341bd026a200341a0016a41086a290300370000200341c5026a200341b0016a290300370000200341cd026a200341b8016a290300370000200341d5026a20024102463a0000200341043a00b402200341083a00b002200320032903a0013700b502200341b0026a21020b410021084101210a4101410020021092012007102c410021060c0b0b200141216a2d0000211b200141246a280200211a200341206a41186a200141196a290000370300200341206a41106a200141116a290000370300200341206a41086a200141096a290000370300200320012900013703202002411a6a290100210c200241196a2d00002111200241186a2d00002112200241166a2f01002113200241156a2d00002114200241146a2d00002115200241126a2f01002116200241116a2d00002117200241106a2d0000210a2002410e6a2f010021072002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241046a2d0000211841022106200241026a2f010021190240024020022d00000d0020022d00014101470d00200241056a2d00002106200241066a2f01002105200241086a2d00002102410021080c010b4101210841002105410021020b200541ffff0371410874200641ff017172200241187472210502402008450d0041d6b2c0002106410f2102024002400240024020050e05000102030c000b200f410874201072200e4118747221062007410874200d72200a4118747221020c0b0b41dd8cc6002106410e21020c0a0b41c3b2c0002106411321020c090b41b2b2c0002106411121020c080b2003200c37039801200320113a009701200320123a009601200320133b019401200320143a009301200320153a009201200320163b019001200320173a008f012003200a3a008e01200320073b018c012003200d3a008b012003200e3a008a012003200f3b018801200320103a0087012003200536008301200320183a008201200320193b018001200341b0026a41186a4200370300200341b0026a41106a22074200370300200341b0026a41086a22064200370300200342003703b002200341d0046a41086a220241cee5c200ad4280808080b002841002220541086a290000370300200320052900003703d0042005102c20062002290300370300200320032903d0043703b002200241eae5c200ad4280808080f000841002220541086a290000370300200320052900003703d0042005102c200720032903d004220c370300200341c0036a41086a2006290300370300200341c0036a41106a200c370300200341c0036a41186a20022903003703002003200c370340200320032903b0023703c003200341b0026a200341c0036a412010d00120032902b402420020032802b00222021b220c422088a741057421062002410120021b220a210202400340024020060d00410021080c020b4101210820034180016a2002460d01200641606a2106200220034180016a412010dd052105200241206a210220050d000b0b0240200ca7450d00200a102c0b024020080d00418df8c2002106411221020c080b200341d0046a41086a220241cee5c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a22052002290300370300200320032903d004370360200241f1e5c200ad4280808080e000841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a22082002290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2206450d0020062003290360370000200641086a200529030037000020062003290370370010200641186a200829030037000020062003290040370020200641286a200341c0006a41086a29000037000041102102200641306a200341c0006a41106a290000370000200641386a200341c0006a41186a290000370000200341b0026a200641c00010e503200341cc026a2802002113200341b0026a41186a2802002111200341c4026a280200210a200341b0026a41106a280200211020032802bc02211220032802b802210f20032802b402211420032802b00221052006102c0240200f0d0041d4f7c2002106411321020c080b41e7f7c20021062005201a470d06201041057421064100211541002105200f21020240024003402006450d0220034180016a2002460d01200541016a2105200641606a2106200220034180016a412010dd052108200241206a210220080d000b20084541016a41017120056a417f6a21050b410121150b2013410574210d20034180016a200a6b210e410021164100210641002102024002400340200d2002460d02200e2002460d01200641016a2106200a20026a2108200241206a2102200820034180016a412010dd0522080d000b20084541016a41017120066a417f6a21060b410121160b024002400240201b41ff01710d002016450d010c080b20150d07200341b0026a41186a220820034180016a41186a290300370300200341b0026a41106a220d20034180016a41106a290300370300200341b0026a41086a220e20034180016a41086a29030037030020032003290380013703b0020240024020102012460d0020122105201021120c010b201241016a22022012490d06201241017422052002200520024b1b220541ffffff3f712005470d06200541057422024100480d060240024020120d002002102a210f0c010b200f20124105742002102e210f0b200f450d030b200f20124105746a220220032903b002370000200241186a2008290300370000200241106a200d290300370000200241086a200e290300370000201041016a21102016450d01201320064d0d04200a2013417f6a22134105746a2202290000210c200229000821092002290010210b200a20064105746a220641186a200241186a2900003700002006200b370010200620093700082006200c3700000c010b200329039801210c20032d009701210820032d009601210d20032f019401210e20032d009301211620032d009201211720032f019001211820032d008f01211920032d008e01211e20032f018c01211f20032d008b01212020032d008a01212120032f018801212220032d0087012123200328008301212420032d008201212520032f01800121260240024020132011460d0020112106201321110c010b201141016a22022011490d05201141017422062002200620024b1b220641ffffff3f712006470d05200641057422024100480d050240024020110d002002102a210a0c010b200a20114105742002102e210a0b200a450d020b200a20114105746a2202200c370018200220083a00172002200d3a00162002200e3b0014200220163a0013200220173a0012200220183b0010200220193a000f2002201e3a000e2002201f3b000c200220203a000b200220213a000a200220223b0008200220233a000720022024360003200220253a0002200220263b0000201341016a211302402015450d00201020054d0d06200f2010417f6a22104105746a2202290000210c200229000821092002290010210b200f20054105746a220541186a200241186a2900003700002005200b370010200520093700082005200c3700000b20062111201221050b200341d5026a2003290320370000200341c5026a20034180016a41106a290300370000200341cd026a20034180016a41186a290300370000200341e5026a200341206a41106a290300370000200341ed026a200341206a41186a290300370000200341083a00b002200341bd026a20034180016a41086a290300370000200341dd026a200341206a41086a290300370000200341013a00b40220032003290380013700b502200341fc026a2013360200200341f8026a2010360200200341f5026a201b3a00004100210641014100200341b0026a109201200341b0026a41186a220e4200370300200341b0026a41106a22124200370300200341b0026a41086a22084200370300200342003703b002200341d0046a41086a220241cee5c200ad4280808080b002841002220d41086a2900003703002003200d2900003703d004200d102c20082002290300370300200320032903d0043703b002200241eae5c200ad4280808080f000841002220d41086a2900003703002003200d2900003703d004200d102c200341c0006a41086a2002290300220c370300200320032903d004220937034020072009370000200741086a200c370000200341c0036a41086a2008290300370300200341c0036a41106a2012290300370300200341c0036a41186a200e290300370300200320032903b0023703c003200341a0016a200341c0036a412010d001024020032802a0012202450d0020032902a401220c422088a72106200ca7450d002002102c0b02400240201020144f22020d004100200620136b2208200820064b1b2014490d00200341cc026a2013360200200341b0026a41186a2011360200200341b0026a41106a2010360200200341bc026a20053602002003200a3602c4022003200f3602b802200320143602b4022003201a3602b002200341d0046a41086a220241cee5c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a22082002290300370300200320032903d004370360200241f1e5c200ad4280808080e000841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a22062002290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2202450d0220022003290360370000200241086a200829030037000020022003290370370010200241186a200629030037000020022003290040370020200241286a200341c0006a41086a290000370000200241306a200341c0006a41106a290000370000200241386a200341c0006a41186a290000370000200341c0003602c403200320023602c003200341b0026a200341c0036a10fd032002102c02402005450d00200f102c0b02402011450d00200a102c0b410021060c010b0240024020020d00200341d0046a41086a220241cee5c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a22082002290300370300200320032903d004370360200241fcf0c200ad4280808080a001841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a22062002290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2202450d0320022003290360370000200241086a200829030037000020022003290370370010200241186a200629030037000020022003290040370020200241286a200341c0006a41086a290000370000200241306a200341c0006a41106a290000370000200241386a200341c0006a41186a2900003700002002ad428080808080088410052002102c200341bd026a200341206a41086a290300370000200341c5026a200341206a41106a290300370000200341cd026a200341206a41186a290300370000200341033a00b402200341083a00b002200320032903203700b50241014100200341b0026a1092010c010b200341c5026a200341206a41106a290300370000200341cd026a200341206a41186a290300370000200341083a00b002200341bd026a200341206a41086a290300370000200341023a00b402200320032903203700b50241014100200341b0026a109201200341d0046a41086a220241cee5c200ad4280808080b002841002220841086a290000370300200320082900003703d0042008102c200341e0006a41086a220d2002290300370300200320032903d004370360200241fcf0c200ad4280808080a001841002220841086a290000370300200320082900003703d0042008102c200341f0006a41086a22082002290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2202450d0220022003290360370000200241086a200d29030037000020022003290370370010200241186a200829030037000020022003290040370020200241286a200341c0006a41086a290000370000200241306a200341c0006a41106a290000370000200241386a200341c0006a41186a290000370000200341b0026a200241c00010f40320032802b0022108200341c0036a200341b0026a410472220d418c0110db051a024020084118470d002002102c0c010b200341a0016a200341c0036a418c0110db051a2002102c200320083602b002200d200341a0016a418c0110db051a200341cc036a2006360200200341c0036a41086a2014360200200341003a00c403200341023a00c003200341c0006a200341b0026a200341c0036a10c10220032d00482102200341bd026a200341206a41086a290300370000200341c5026a200341306a290300370000200341cd026a200341386a290300370000200341d5026a20024102463a0000200341043a00b402200341083a00b002200320032903203700b50241014100200341b0026a1092010b200341d0046a41086a220641cee5c200ad4280808080b00284220c1002220241086a290000370300200320022900003703d0042002102c200341e0006a41086a22082006290300370300200320032903d004370360200641f1e5c200ad4280808080e000841002220241086a290000370300200320022900003703d0042002102c200341f0006a41086a220d2006290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2202450d0120022003290360370000200241086a200829030037000020022003290370370010200241186a200d29030037000020022003290040370020200241286a200341c0006a41086a220d290000370000200241306a200341c0006a41106a290000370000200241386a200341c0006a41186a2900003700002002ad428080808080088410052002102c200341b0026a41186a220e4200370300200341b0026a41106a22104200370300200341b0026a41086a22024200370300200342003703b0022006200c1002220841086a290000370300200320082900003703d0042008102c20022006290300370300200320032903d0043703b002200641e1e5c200ad42808080809001841002220841086a290000370300200320082900003703d0042008102c200d2006290300220c370300200320032903d004220937034020072009370000200741086a200c370000200341c0036a41086a2002290300370300200341c0036a41106a2010290300370300200341c0036a41186a200e290300370300200320032903b0023703c003200341b0026a200341c0036a412010d0010240024020032802b0022202450d00200320032902b4023702a401200320023602a0010c010b200341003602a801200342013703a0010b200341a0016a200341206a107a20032802a801210d20032802a401211020032802a0012107200341c0006a41186a4200370300200341c0006a41106a220e4200370300200341c0006a41086a2206420037030020034200370340200341d0046a41086a220241cee5c200ad4280808080b002841002220841086a290000370300200320082900003703d0042008102c20062002290300370300200320032903d004220c3703602003200c370340200241e1e5c200ad42808080809001841002220841086a290000370300200320082900003703d0042008102c200e20032903d004220c370300200341b0026a41086a2006290300370300200341b0026a41106a200c370300200341b0026a41186a20022903003703002003200c370370200320032903403703b0020240024020070d00200341b0026aad428080808080048410050c010b200341003602c803200342013703c003200d200341c0036a10670240200d450d00200d41057421062007210203402003200341c0036a3602402002200341c0006a109402200241206a2102200641606a22060d000b0b20032802c4032102200341b0026aad428080808080048420033502c80342208620032802c0032206ad84100102402002450d002006102c0b2010450d002007102c0b02402005450d00200f102c0b410021062011450d00200a102c0b0c070b1033000b41b5f7c2002106411f21020c060b41a888c600200620131038000b1035000b41a888c600200520101038000b41f7f7c2002106411621020b02402012450d00200f102c0b2011450d00200a102c0b4101210a410121080c020b20071092022007102c410021084101210a0c010b20071092022007102c410121084100210a0b2004417f6a220541024b0d0002400240024020050e03000102000b200141086a280200450d02200141046a280200102c0c020b200a450d01200141046a28020022011092022001102c0c010b2008450d00200141086a28020022011092022001102c0b2000200236020420002006360200200341e0046a24000bf46a05067f017e107f047e097f230041e0046b220324000240024002400240024002400240024002400240024002400240024002400240024020012d000022040e050001020304000b200341c4026a4101360200200342013702b402200341fcc4c5003602b002200341043602c403200341f4c4c5003602c0032003200341c0036a3602c002200341b0026a4184c5c5001041000b200141086a2802002104200141046a2802002105024020022d000120022d000072450d004111210241b2b2c00021062004450d0f2005102c0c0f0b20052001410c6a280200220210f402200341b0026a41186a4200370300200341b0026a41106a22064200370300200341b0026a41086a22074200370300200342003703b002200341d0046a41086a220141fde7c200ad4280808080b002841002220841086a290000370300200320082900003703d0042008102c20072001290300370300200320032903d0043703b002200141eae5c200ad4280808080f000841002220841086a290000370300200320082900003703d0042008102c200620032903d0042209370300200341c0036a41086a2007290300370300200341c0036a41106a2009370300200341c0036a41186a200129030037030020032009370340200320032903b0023703c003200341b0026a200341c0036a412010d001200341b0026a2005200220032802b0022201410120011b220720032902b402420020011b2209422088a710dc012006280200210120032802b402210620032802b002210820032802bc02220a200341c4026a2802002005200210dd0102402001450d00200a102c0b02402006450d002008102c0b02402009a7450d002007102c0b200341b0026a41186a4200370300200341b0026a41106a22084200370300200341b0026a41086a22064200370300200342003703b002200341d0046a41086a220141fde7c200ad4280808080b002841002220741086a290000370300200320072900003703d0042007102c20062001290300370300200320032903d0042209370360200320093703b002200141eae5c200ad4280808080f000841002220741086a290000370300200320072900003703d0042007102c200820032903d0042209370300200341c0006a41086a2006290300370300200341c0006a41106a2009370300200341c0006a41186a200129030037030020032009370370200320032903b002370340200341003602b802200342013703b0022002200341b0026a106702402002450d00200241057421012005210203402002200341b0026a109101200241206a2102200141606a22010d000b0b20032802b4022102200341c0006aad428080808080048420033502b80242208620032802b0022201ad84100102402002450d002001102c0b4100210602402004450d002005102c0b0c0e0b200141046a280200210a2002411a6a2901002109200241196a2d00002105200241186a2d00002107200241166a2f01002108200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241046a2d0000211541022106200241026a2f010021160240024020022d00000d0020022d00014101470d00200241056a2d00002106200241066a2f01002117200241086a2d00002102410021180c010b4101211841002102410021170b200320093703c802200320053a00c702200320073a00c602200320083b01c4022003200b3a00c3022003200c3a00c2022003200d3b01c0022003200e3a00bf022003200f3a00be02200320103b01bc02200320113a00bb02200320123a00ba02200320133b01b802200320143a00b702200320153a00b202200320163b01b0022003201741ffff0371410874200241187472200641ff01717222053600b30202402018450d0041d6b2c0002106410f2102024002400240024020050e050001020310000b20032800b702210620032800bb0221020c0f0b41dd8cc6002106410e21020c0e0b41c3b2c0002106411321020c0d0b41b2b2c0002106411121020c0c0b20034180016a41186a200341b0026a41186a220629030037030020034180016a41106a200341b0026a41106a220529030037030020034180016a41086a200341b0026a41086a2202290300370300200320032903b00237038001200642003703002005420037030020024200370300200342003703b002200341d0046a41086a220641fde7c200ad4280808080b002841002220741086a290000370300200320072900003703d0042007102c20022006290300370300200320032903d0043703b002200641eae5c200ad4280808080f000841002220741086a290000370300200320072900003703d0042007102c200520032903d0042209370300200341c0036a41086a2002290300370300200341c0036a41106a2009370300200341c0036a41186a200629030037030020032009370340200320032903b0023703c003200341b0026a200341c0036a412010d00120032902b402420020032802b00222021b2209422088a741057421062002410120021b2208210202400340024020060d00410021070c020b4101210720034180016a2002460d01200641606a2106200220034180016a412010dd052105200241206a210220050d000b0b02402009a7450d002008102c0b024020070d0041a0f7c2002106411521020c0c0b41002108200341003602b802200342013703b002200a200341b0026a108b0120032802b4022106200341b0026a41186a220520033502b80242208620032802b002220dad841006220241186a290000370300200341b0026a41106a2207200241106a290000370300200341b0026a41086a220b200241086a290000370300200320022900003703b0022002102c200341a0016a41186a22022005290300370300200341a0016a41106a22052007290300370300200341a0016a41086a220c200b290300370300200320032903b0023703a00102402006450d00200d102c0b200341b0026a200a41900110db051a200341c0036a410d6a20034180016a41086a290300370000200341c0036a41156a20034180016a41106a290300370000200341c0036a411d6a20034180016a41186a29030037000041012107200341013a00c40320032003290380013700c503200341013a00c003200341c0006a200341b0026a200341c0036a10c10220032d00482106200341b0026a410d6a200c290300370000200341b0026a41156a2005290300370000200341b0026a411d6a2002290300370000200341d5026a20064102463a0000200341053a00b402200341073a00b002200320032903a0013700b50241014100200341b0026a109201200a102c410021060c0c0b200141086a280200210a200141046a28020021192002411a6a2901002109200241196a2d00002110200241186a2d00002111200241166a2f01002112200241156a2d00002113200241146a2d00002114200241126a2f01002115200241116a2d00002116200241106a2d000021082002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241046a2d0000211741022106200241026a2f010021180240024020022d00000d0020022d00014101470d00200241056a2d00002106200241066a2f01002105200241086a2d00002102410021070c010b4101210741002105410021020b200541ffff0371410874200641ff017172200241187472210502402007450d0041d6b2c0002106410f2102024002400240024020050e05000102030e000b200e410874200f72200d411874722106200b410874200c7220084118747221020c0d0b41dd8cc6002106410e21020c0c0b41c3b2c0002106411321020c0b0b41b2b2c0002106411121020c0a0b2003200937039801200320103a009701200320113a009601200320123b019401200320133a009301200320143a009201200320153b019001200320163a008f01200320083a008e012003200b3b018c012003200c3a008b012003200d3a008a012003200e3b0188012003200f3a0087012003200536008301200320173a008201200320183b018001200341b0026a41186a4200370300200341b0026a41106a22084200370300200341b0026a41086a22064200370300200342003703b002200341d0046a41086a220241fde7c200ad4280808080b002841002220541086a290000370300200320052900003703d0042005102c20062002290300370300200320032903d0043703b002200241eae5c200ad4280808080f000841002220541086a290000370300200320052900003703d0042005102c200820032903d0042209370300200341c0036a41086a2006290300370300200341c0036a41106a2009370300200341c0036a41186a200229030037030020032009370340200320032903b0023703c003200341b0026a200341c0036a412010d00120032902b402420020032802b00222021b2209422088a741057421062002410120021b220b210202400340024020060d00410021070c020b4101210720034180016a2002460d01200641606a2106200220034180016a412010dd052105200241206a210220050d000b0b02402009a7450d00200b102c0b024020070d0041a0f7c2002106411521020c0a0b200341003602b802200342013703b002200a200341b0026a108b0120032802b402210b200341b0026a41186a220620033502b80242208620032802b002220ead841006220241186a290000370300200341b0026a41106a2205200241106a290000370300200341b0026a41086a2207200241086a290000370300200320022900003703b0022002102c200341a0016a41186a22022006290300370300200341a0016a41106a220c2005290300370300200341a0016a41086a220d2007290300370300200320032903b0023703a0010240200b450d00200e102c0b200620022903003703002005200c2903003703002007200d290300370300200320032903a0013703b002200341d0046a41086a220241fde7c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a2002290300370300200320032903d004370360200241fcf0c200ad4280808080a001841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a2002290300370300200320032903d004370370200341c0006a200341b0026a109f0141c000102a2202450d0120022003290360370000200241086a200341e0006a41086a29030037000020022003290370370010200241186a200341f0006a41086a29030037000020022003290340370020200241286a200341c0006a41086a290300370000200241306a200341d0006a290300370000200241386a200341c0006a41186a290300370000200341186a200241c000410141004100109701200328021821062002102c20064101460d020240024020194102490d004200211a200341c0006a41186a220c4200370300200341c0006a41106a220d4200370300200341c0006a41086a2206420037030020034200370340200341d0046a41086a220241fde7c200ad4280808080b0028422091002220541086a290000370300200320052900003703d0042005102c20062002290300370300200320032903d004221b3703602003201b370340200241ace9c500ad4280808080d00184221b1002220541086a290000370300200320052900003703d0042005102c200d20032903d004221c370300200341b0026a41086a22052006290300370300200341b0026a41106a2207201c370300200341b0026a41186a220b20022903003703002003201c370370200320032903403703b002200341106a200341b0026a41201094012003280214210f20032802102110200c4200370300200d42003703002006420037030020034200370340200220091002220e41086a2900003703002003200e2900003703d004200e102c20062002290300370300200320032903d004221c3703602003201c3703402002201b1002220e41086a2900003703002003200e2900003703d004200e102c200c2002290300221c37030020052006290300370300200720032903d004221d370300200b201c3703002003201d370370200320032903403703b002200341086a200341b0026a41201094012003280208210e200328020c2111200c4200370300200d42003703002006420037030020034200370340200220091002220d41086a2900003703002003200d2900003703d004200d102c20062002290300370300200320032903d004221c3703602003201c3703402002201b1002220d41086a2900003703002003200d2900003703d004200d102c200c2002290300221b37030020052006290300370300200720032903d004221c370300200b201b3703002003201c370370200320032903403703b0024101210c2003201141016a4101200e1b3602c003200341b0026aad4280808080800484200341c0036aad4280808080c000841001200b42003703002007420037030020054200370300200342003703b002200220091002220d41086a2900003703002003200d2900003703d004200d102c20052002290300370300200320032903d0043703b002200241e1e5c200ad42808080809001841002220d41086a2900003703002003200d2900003703d004200d102c200620022903002209370300200320032903d004221b3703402008201b370000200841086a2009370000200341c0036a41086a2005290300370300200341c0036a41106a2007290300370300200341c0036a41186a200b290300370300200320032903b0023703c003200341b0026a200341c0036a412010d0010240024020032802b00222080d0041002106410021020c010b20032902b402221a422088a72102201aa721062008210c0b200b200341a0016a41186a2903003703002007200341a0016a41106a2903003703002005200341a0016a41086a290300370300200320032903a0013703b0020240024020022006460d002006210b0c010b02402006201aa7220b470d00200641016a22022006490d08200641017422052002200520024b1b220b41ffffff3f71200b470d08200b41057422024100480d080240024020060d002002102a210c0c010b200c20064105742002102e210c0b200c450d05201a42808080807083211a0b201a422088a721020b200c20024105746a220620032903b002370000200641186a200341b0026a41186a2205290300370000200641106a200341b0026a41106a2207290300370000200641086a200341b0026a41086a2206290300370000200542003703002007420037030020064200370300200342003703b002200341d0046a41086a220541fde7c200ad4280808080b002841002220841086a290000370300200320082900003703d0042008102c20062005290300370300200320032903d0042209370360200320093703b002200541e1e5c200ad42808080809001841002220841086a290000370300200320082900003703d0042008102c200720032903d0042209370300200341c0006a41086a2006290300370300200341c0006a41106a2009370300200341c0006a41186a200529030037030020032009370370200320032903b00237034002400240200c0d00200341c0006aad428080808080048410050c010b200341003602b802200342013703b002200241016a2206200341b0026a106702402006450d00200241057441206a2106200c210203402003200341b0026a3602c0032002200341c0036a109402200241206a2102200641606a22060d000b0b20032802b4022102200341c0006aad428080808080048420033502b80242208620032802b0022206ad84100102402002450d002006102c0b200b450d00200c102c0b200341b0026a200a41900110db051a200341c0036a41186a200341a0016a41186a290300370300200341c0036a41106a200341a0016a41106a290300370300200341c0036a41086a200341a0016a41086a290300370300200320032903a0013703c003200341d0046a41086a220241fde7c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a22052002290300370300200320032903d004370360200241fcf0c200ad4280808080a001841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a22062002290300370300200320032903d004370370200341c0006a200341c0036a109f0141c000102a2202450d0320022003290360370000200241086a200529030037000020022003290370370010200241186a200629030037000020022003290340370020200241286a200341c0006a41086a290300370000200241306a200341c0006a41106a290300370000200241386a200341c0006a41186a290300370000200341003602c803200342013703c003200341b0026a200341c0036a108b0120032802c40321062002ad428080808080088420033502c80342208620032802c0032205ad84100102402006450d002005102c0b2002102c200341b0026a1092024120102a2206450d032006200329038001370000200641186a20034180016a41186a2207290300370000200641106a20034180016a41106a2208290300370000200641086a20034180016a41086a220b290300370000200341dc036a4100360200200341cc036a428180808010370200200342013702d403200320063602c803200320193602c4032003200f410020101b220c3602c003200341b0026a41186a200341a0016a41186a220d290300370300200341b0026a41106a200341a0016a41106a220e290300370300200341b0026a41086a200341a0016a41086a220f290300370300200320032903a0013703b002200341d0046a41086a220241fde7c200ad4280808080b002841002220541086a290000370300200320052900003703d0042005102c200341e0006a41086a22102002290300370300200320032903d004370360200241f1e5c200ad4280808080e000841002220541086a290000370300200320052900003703d0042005102c200341f0006a41086a22052002290300370300200320032903d004370370200341c0006a200341b0026a109f0141c000102a2202450d0320022003290360370000200241086a201029030037000020022003290370370010200241186a200529030037000020022003290340370020200241286a200341c0006a41086a290300370000200241306a200341c0006a41106a290300370000200241386a200341c0006a41186a290300370000200341c0003602b402200320023602b002200341c0036a200341b0026a10fd032002102c2006102c200341bd026a200b290300370000200341c5026a2008290300370000200341cd026a2007290300370000200341d5026a20032903a001370000200341dd026a200f290300370000200341e5026a200e290300370000200341ed026a200d290300370000200341fc026a2019360200200341f8026a200c360200200341003a00b402200341073a00b00220032003290380013700b502200341b0026a21020c010b200341b0026a41186a22074200370300200341b0026a41106a220b4200370300200341b0026a41086a22064200370300200342003703b002200341d0046a41086a220241fde7c200ad4280808080b002841002220541086a290000370300200320052900003703d0042005102c20062002290300370300200320032903d0043703b002200241eae5c200ad4280808080f000841002220541086a290000370300200320052900003703d0042005102c200341c0006a41086a20022903002209370300200320032903d004221a3703402008201a370000200841086a2009370000200341c0036a41086a2006290300370300200341c0036a41106a200b290300370300200341c0036a41186a2007290300370300200320032903b0023703c003200341206a200341c0036a412010d00102400240200328022022060d00410021020c010b20032902242209422088a721022009a7450d002006102c0b200341b0026a200a41900110db051a200341cc036a2002360200200341c0036a41086a4101360200200341003a00c403200341013a00c003200341c0006a200341b0026a200341c0036a10c10220032d00482102200341bd026a200341a0016a41086a290300370000200341c5026a200341b0016a290300370000200341cd026a200341b8016a290300370000200341d5026a20024102463a0000200341043a00b402200341073a00b002200320032903a0013700b502200341b0026a21020b4100210741012108410141002002109201200a102c410021060c0b0b200141216a2d00002119200141246a2802002118200341206a41186a200141196a290000370300200341206a41106a200141116a290000370300200341206a41086a200141096a290000370300200320012900013703202002411a6a2901002109200241196a2d0000210f200241186a2d00002110200241166a2f01002111200241156a2d00002112200241146a2d00002113200241126a2f01002114200241116a2d00002115200241106a2d000021082002410e6a2f0100210a2002410d6a2d0000210b2002410c6a2d0000210c2002410a6a2f0100210d200241096a2d0000210e200241046a2d0000211641022106200241026a2f010021170240024020022d00000d0020022d00014101470d00200241056a2d00002106200241066a2f01002105200241086a2d00002102410021070c010b4101210741002105410021020b200541ffff0371410874200641ff017172200241187472210502402007450d0041d6b2c0002106410f2102024002400240024020050e05000102030c000b200d410874200e72200c411874722106200a410874200b7220084118747221020c0b0b41dd8cc6002106410e21020c0a0b41c3b2c0002106411321020c090b41b2b2c0002106411121020c080b20032009370398012003200f3a009701200320103a009601200320113b019401200320123a009301200320133a009201200320143b019001200320153a008f01200320083a008e012003200a3b018c012003200b3a008b012003200c3a008a012003200d3b0188012003200e3a0087012003200536008301200320163a008201200320173b018001200341b0026a41186a4200370300200341b0026a41106a220a4200370300200341b0026a41086a22064200370300200342003703b002200341d0046a41086a220241fde7c200ad4280808080b002841002220541086a290000370300200320052900003703d0042005102c20062002290300370300200320032903d0043703b002200241eae5c200ad4280808080f000841002220541086a290000370300200320052900003703d0042005102c200a20032903d0042209370300200341c0036a41086a2006290300370300200341c0036a41106a2009370300200341c0036a41186a200229030037030020032009370340200320032903b0023703c003200341b0026a200341c0036a412010d00120032902b402420020032802b00222021b2209422088a741057421062002410120021b2208210202400340024020060d00410021070c020b4101210720034180016a2002460d01200641606a2106200220034180016a412010dd052105200241206a210220050d000b0b02402009a7450d002008102c0b024020070d00418df8c2002106411221020c080b200341d0046a41086a220241fde7c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a22052002290300370300200320032903d004370360200241f1e5c200ad4280808080e000841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a22072002290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2206450d0020062003290360370000200641086a200529030037000020062003290370370010200641186a200729030037000020062003290040370020200641286a200341c0006a41086a29000037000041102102200641306a200341c0006a41106a290000370000200641386a200341c0006a41186a290000370000200341b0026a200641c00010e503200341cc026a2802002111200341b0026a41186a280200210f200341c4026a2802002108200341b0026a41106a280200210e20032802bc02211020032802b802210d20032802b402211220032802b00221052006102c0240200d0d0041d4f7c2002106411321020c080b41e7f7c200210620052018470d06200e41057421064100211341002105200d21020240024003402006450d0220034180016a2002460d01200541016a2105200641606a2106200220034180016a412010dd052107200241206a210220070d000b20074541016a41017120056a417f6a21050b410121130b2011410574210b20034180016a20086b210c410021144100210641002102024002400340200b2002460d02200c2002460d01200641016a2106200820026a2107200241206a2102200720034180016a412010dd0522070d000b20074541016a41017120066a417f6a21060b410121140b024002400240201941ff01710d002014450d010c080b20130d07200341b0026a41186a220720034180016a41186a290300370300200341b0026a41106a220b20034180016a41106a290300370300200341b0026a41086a220c20034180016a41086a29030037030020032003290380013703b00202400240200e2010460d0020102105200e21100c010b201041016a22022010490d06201041017422052002200520024b1b220541ffffff3f712005470d06200541057422024100480d060240024020100d002002102a210d0c010b200d20104105742002102e210d0b200d450d030b200d20104105746a220220032903b002370000200241186a2007290300370000200241106a200b290300370000200241086a200c290300370000200e41016a210e2014450d01201120064d0d0420082011417f6a22114105746a220229000021092002290008211a2002290010211b200820064105746a220641186a200241186a2900003700002006201b3700102006201a370008200620093700000c010b200329039801210920032d009701210720032d009601210b20032f019401210c20032d009301211420032d009201211520032f019001211620032d008f01211720032d008e01211e20032f018c01211f20032d008b01212020032d008a01212120032f018801212220032d0087012123200328008301212420032d008201212520032f0180012126024002402011200f460d00200f21062011210f0c010b200f41016a2202200f490d05200f41017422062002200620024b1b220641ffffff3f712006470d05200641057422024100480d0502400240200f0d002002102a21080c010b2008200f4105742002102e21080b2008450d020b2008200f4105746a22022009370018200220073a00172002200b3a00162002200c3b0014200220143a0013200220153a0012200220163b0010200220173a000f2002201e3a000e2002201f3b000c200220203a000b200220213a000a200220223b0008200220233a000720022024360003200220253a0002200220263b0000201141016a211102402013450d00200e20054d0d06200d200e417f6a220e4105746a220229000021092002290008211a2002290010211b200d20054105746a220541186a200241186a2900003700002005201b3700102005201a370008200520093700000b2006210f201021050b200341d5026a2003290320370000200341bd026a20034180016a41086a290300370000200341c5026a20034180016a41106a290300370000200341cd026a20034180016a41186a290300370000200341dd026a200341206a41086a290300370000200341e5026a200341206a41106a290300370000200341ed026a200341206a41186a290300370000200341013a00b402200341073a00b00220032003290380013700b502200341fc026a2011360200200341f8026a200e360200200341f5026a20193a00004100210641014100200341b0026a109201200341b0026a41186a220c4200370300200341b0026a41106a22104200370300200341b0026a41086a22074200370300200342003703b002200341d0046a41086a220241fde7c200ad4280808080b002841002220b41086a2900003703002003200b2900003703d004200b102c20072002290300370300200320032903d0043703b002200241eae5c200ad4280808080f000841002220b41086a2900003703002003200b2900003703d004200b102c200341c0006a41086a20022903002209370300200320032903d004221a370340200a201a370000200a41086a2009370000200341c0036a41086a2007290300370300200341c0036a41106a2010290300370300200341c0036a41186a200c290300370300200320032903b0023703c003200341a0016a200341c0036a412010d001024020032802a0012202450d0020032902a4012209422088a721062009a7450d002002102c0b02400240200e20124f22020d004100200620116b2207200720064b1b2012490d00200341cc026a2011360200200341b0026a41186a200f360200200341b0026a41106a200e360200200341bc026a2005360200200320083602c4022003200d3602b802200320123602b402200320183602b002200341d0046a41086a220241fde7c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a22072002290300370300200320032903d004370360200241f1e5c200ad4280808080e000841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a22062002290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2202450d0220022003290360370000200241086a200729030037000020022003290370370010200241186a200629030037000020022003290040370020200241286a200341c0006a41086a290000370000200241306a200341c0006a41106a290000370000200241386a200341c0006a41186a290000370000200341c0003602c403200320023602c003200341b0026a200341c0036a10fd032002102c02402005450d00200d102c0b0240200f450d002008102c0b410021060c010b0240024020020d00200341d0046a41086a220241fde7c200ad4280808080b002841002220641086a290000370300200320062900003703d0042006102c200341e0006a41086a22072002290300370300200320032903d004370360200241fcf0c200ad4280808080a001841002220641086a290000370300200320062900003703d0042006102c200341f0006a41086a22062002290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2202450d0320022003290360370000200241086a200729030037000020022003290370370010200241186a200629030037000020022003290040370020200241286a200341c0006a41086a290000370000200241306a200341c0006a41106a290000370000200241386a200341c0006a41186a2900003700002002ad428080808080088410052002102c200341bd026a200341206a41086a290300370000200341c5026a200341206a41106a290300370000200341cd026a200341206a41186a290300370000200341033a00b402200341073a00b002200320032903203700b50241014100200341b0026a1092010c010b200341bd026a200341206a41086a290300370000200341c5026a200341206a41106a290300370000200341cd026a200341206a41186a290300370000200341023a00b402200341073a00b002200320032903203700b50241014100200341b0026a109201200341d0046a41086a220241fde7c200ad4280808080b002841002220741086a290000370300200320072900003703d0042007102c200341e0006a41086a220b2002290300370300200320032903d004370360200241fcf0c200ad4280808080a001841002220741086a290000370300200320072900003703d0042007102c200341f0006a41086a22072002290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2202450d0220022003290360370000200241086a200b29030037000020022003290370370010200241186a200729030037000020022003290040370020200241286a200341c0006a41086a290000370000200241306a200341c0006a41106a290000370000200241386a200341c0006a41186a290000370000200341b0026a200241c00010f40320032802b0022107200341c0036a200341b0026a410472220b418c0110db051a024020074118470d002002102c0c010b200341a0016a200341c0036a418c0110db051a2002102c200320073602b002200b200341a0016a418c0110db051a200341cc036a2006360200200341c0036a41086a2012360200200341003a00c403200341013a00c003200341c0006a200341b0026a200341c0036a10c10220032d00482102200341bd026a200341206a41086a290300370000200341c5026a200341306a290300370000200341cd026a200341386a290300370000200341d5026a20024102463a0000200341043a00b402200341073a00b002200320032903203700b50241014100200341b0026a1092010b200341d0046a41086a220641fde7c200ad4280808080b0028422091002220241086a290000370300200320022900003703d0042002102c200341e0006a41086a22072006290300370300200320032903d004370360200641f1e5c200ad4280808080e000841002220241086a290000370300200320022900003703d0042002102c200341f0006a41086a220b2006290300370300200320032903d004370370200341c0006a200341206a109f0141c000102a2202450d0120022003290360370000200241086a200729030037000020022003290370370010200241186a200b29030037000020022003290040370020200241286a200341c0006a41086a220b290000370000200241306a200341c0006a41106a290000370000200241386a200341c0006a41186a2900003700002002ad428080808080088410052002102c200341b0026a41186a220c4200370300200341b0026a41106a220e4200370300200341b0026a41086a22024200370300200342003703b002200620091002220741086a290000370300200320072900003703d0042007102c20022006290300370300200320032903d0043703b002200641e1e5c200ad42808080809001841002220741086a290000370300200320072900003703d0042007102c200b20062903002209370300200320032903d004221a370340200a201a370000200a41086a2009370000200341c0036a41086a2002290300370300200341c0036a41106a200e290300370300200341c0036a41186a200c290300370300200320032903b0023703c003200341b0026a200341c0036a412010d0010240024020032802b0022202450d00200320032902b4023702a401200320023602a0010c010b200341003602a801200342013703a0010b200341a0016a200341206a107a20032802a801210b20032802a401210e20032802a001210a200341c0006a41186a4200370300200341c0006a41106a220c4200370300200341c0006a41086a2206420037030020034200370340200341d0046a41086a220241fde7c200ad4280808080b002841002220741086a290000370300200320072900003703d0042007102c20062002290300370300200320032903d004220937036020032009370340200241e1e5c200ad42808080809001841002220741086a290000370300200320072900003703d0042007102c200c20032903d0042209370300200341b0026a41086a2006290300370300200341b0026a41106a2009370300200341b0026a41186a200229030037030020032009370370200320032903403703b00202400240200a0d00200341b0026aad428080808080048410050c010b200341003602c803200342013703c003200b200341c0036a10670240200b450d00200b4105742106200a210203402003200341c0036a3602402002200341c0006a109402200241206a2102200641606a22060d000b0b20032802c4032102200341b0026aad428080808080048420033502c80342208620032802c0032206ad84100102402002450d002006102c0b200e450d00200a102c0b02402005450d00200d102c0b41002106200f450d002008102c0b0c070b1033000b41b5f7c2002106411f21020c060b41a888c600200620111038000b1035000b41a888c6002005200e1038000b41f7f7c2002106411621020b02402010450d00200d102c0b200f450d002008102c0b41012108410121070c020b200a109202200a102c41002107410121080c010b200a109202200a102c41012107410021080b2004417f6a220541024b0d0002400240024020050e03000102000b200141086a280200450d02200141046a280200102c0c020b2008450d01200141046a28020022011092022001102c0c010b2007450d00200141086a28020022011092022001102c0b2000200236020420002006360200200341e0046a24000bc4a80205017f037e137f027e037f230041e0066b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e1600010205060708090a0b0c0d0e201d1c1b1a19181716000b200341e4036a4101360200200342013702d403200341fcc4c5003602d003200341043602e405200341f4c4c5003602e0052003200341e0056a3602e003200341d0036a4184c5c5001041000b200141306a2903002104200141286a2903002105200341c0026a41186a200141196a290000370300200341c0026a41106a200141116a290000370300200341c0026a41086a200141096a290000370300200320012900013703c0022002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d00012119200320063703d00341002102201941ff01714101460d010b410121024102211841002116410021170b200320063703a003200320073a009f03200320083a009e03200320093b019c032003200a3a009b032003200b3a009a032003200c3b0198032003200d3a0097032003200e3a0096032003200f3b019403200320103a009303200320113a009203200320123b019003200320133a008f03200320143a008a03200320153b0188032003201741ffff0371410874201641187472201841ff017172220936008b0302402002450d0041d6b2c0002108410f210720090e050220212233020b20034188056a41186a20034188036a41186a29030037030020034188056a41106a20034188036a41106a29030037030020034188056a41086a20034188036a41086a2903003703002003200329038803370388050240200542808084fea6dee1115441002004501b450d0041e695c5002108410d2107410121090c340b200341106a20034188056a2005200410c10102402003280210450d0041f395c5002108411a2107410121090c340b200341e0016a41186a22094200370300200341e0016a41106a22074200370300200341e0016a41086a22084200370300200342003703e001200341d0046a41086a220241bad6c500ad428080808090018422061002221641086a290000370300200320162900003703d0042016102c20082002290300370300200320032903d004221a370380022003201a3703e0012002419cd6c500ad4280808080f00184221b1002221641086a290000370300200320162900003703d0042016102c200720032903d004221a370300200341c0016a41086a22172008290300370300200341c0016a41106a2218201a370300200341c0016a41186a220a20022903003703002003201a37039002200320032903e0013703c001200341086a200341c0016a4120109401200328020c210b2003280208210c200942003703002007420037030020084200370300200342003703e001200220061002221641086a290000370300200320162900003703d0042016102c20082002290300370300200320032903d004221a370380022003201a3703e0012002201b1002221641086a290000370300200320162900003703d0042016102c20092002290300221a37030020172008290300370300201820032903d004221b370300200a201a3703002003201b37039002200320032903e0013703c0012003200b4100200c1b221641016a3602d003200341c0016aad4280808080800484221a200341d0036aad4280808080c000841001200320034188056a36028803200220061002221741086a290000370300200320172900003703d0042017102c20034180026a41086a22182002290300370300200320032903d00437038002200241e0c5c400ad42808080809001841002221741086a290000370300200320172900003703d0042017102c20034190026a41086a22172002290300370300200320032903d00437039002200320163602e005200341d0036a41186a220a200341e0056aad4280808080c000841006220241186a290000370300200341d0036a41106a220b200241106a290000370300200341d0036a41086a220c200241086a290000370300200320022900003703d0032002102c2009200a2903003703002007200b2903003703002008200c290300370300200320032903d0033703e00141c000102a2202450d352002200329038002370000200241086a20182903003700002002200329039002370010200241186a2017290300370000200220032903e001370020200241286a2008290300370000200241306a2007290300370000200241386a20092903003700004110102a2208450d3520082005370000200820043700082003429080808080023702d403200320083602d0034101200341d0036a1067200328028803200341d0036a10910120032802d40321082002ad428080808080088420033502d80342208620032802d0032209ad84100102402008450d002009102c0b2002102c200341ec056a200341c0026a41086a290300370200200341f4056a200341c0026a41106a290300370200200341fc056a200341c0026a41186a2903003702002003418c066a20034188056a41086a29030037020020034194066a20034188056a41106a2903003702002003419c066a20034188056a41186a290300370200200320163602e005200320032903c0023702e4052003200329038805370284062003200341e0056a3602d005200341e0016a41186a22174200370300200341e0016a41106a22184200370300200341e0016a41086a22084200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002220941086a290000370300200320092900003703d0042009102c20082002290300370300200320032903d004220637038002200320063703e001200241d5c5c400ad4280808080b001841002220941086a290000370300200320092900003703d0042009102c20034190026a41086a20022903002206370300200320032903d004221b370390022007201b370000200741086a2006370000200341c0016a41086a2008290300370300200341c0016a41106a2018290300370300200341c0016a41186a2017290300370300200320032903e0013703c00120034188036a201a1003108d01024002402003280288032208450d0020034188036a41086a2802002102200328028c0321090c010b200341003602d803200342013703d0034100200341d0036a106720032802d803210220032802d403210920032802d00321080b200320023602a802200320093602a402200320083602a002024002402002450d00200341d0036a20082002410110db0320032802d0034101470d0120032802a402450d3120032802a002102c0c310b4101200341a0026a106720032802d005220828020021170240024020032802a402220920032802a80222026b4104490d0020032802a00221090c010b200241046a22182002490d38200941017422022018200220184b1b22024100480d380240024020090d002002102a21090c010b20032802a00220092002102e21090b2009450d37200320023602a402200320093602a00220032802a80221020b2003200241046a3602a802200920026a20173600002003200341a0026a3602d003200841046a200341d0036a109402200841246a200341a0026a1091010c2e0b20032802d40321170240200341dc036a2802002202200341d8036a2802002208460d0020032802a802200220086b6a220941046a2218417f4c0d130240024020180d004101210a0c010b2018102a220a450d370b200320183602ec042003200a3602e804200320093602f0042003200341e8046a3602d0032017200341d0036a200210c80220092002490d1220032802f00422172009490d1120032802a80222172008490d1020032802e804211820032802a002210a2003200920026b2209360280022003201720086b22173602900220092017470d0f201820026a200a20086a200910db051a20032802d005220828020021170240024020032802ec04220920032802f00422026b4104490d0020032802e80421090c010b200241046a22182002490d38200941017422022018200220184b1b22024100480d380240024020090d002002102a21090c010b20032802e80420092002102e21090b2009450d37200320023602ec04200320093602e80420032802f00421020b2003200241046a3602f004200920026a20173600002003200341e8046a3602d003200841046a200341d0036a109402200841246a200341e8046a10910120032802f004210820032802ec04210920032802e804210220032802a402450d2f20032802a002102c0c2f0b2003200341a0026a3602d0032017200341d0036a200810c80220032802d005220828020021170240024020032802a402220920032802a80222026b4104490d0020032802a00221090c010b200241046a22182002490d37200941017422022018200220184b1b22024100480d370240024020090d002002102a21090c010b20032802a00220092002102e21090b2009450d36200320023602a402200320093602a00220032802a80221020b2003200241046a3602a802200920026a20173600002003200341a0026a3602d003200841046a200341d0036a109402200841246a200341a0026a1091010c2d0b200141046a28020021192002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d0001211c200320063703d00341002102201c41ff01714101460d010b410121024102211841002116410021170b200320063703a003200320073a009f03200320083a009e03200320093b019c032003200a3a009b032003200b3a009a032003200c3b0198032003200d3a0097032003200e3a0096032003200f3b019403200320103a009303200320113a009203200320123b019003200320133a008f03200320143a008a03200320153b0188032003201741ffff0371410874201641187472201841ff017172220936008b032002450d0141d6b2c0002108410f210720090e05001e1f2031000b200328008f0321082003280093032107410121090c310b200341e0056a41186a20034188036a41186a290300370300200341e0056a41106a20034188036a41106a290300370300200341e0056a41086a20034188036a41086a29030037030020032003290388033703e005200341d0036a201910cc04024020032802e00322090d00418d96c500210841242107410121090c310b200341d0036a41186a280200210720032802e4032102200341186a200341e0056a20032902d403220642208620033502d003842204200341dc036a350200422086200642208884220610c10120032802180d29200341c0016a41186a200341e0056a41186a290300370300200341c0016a41106a2208200341e0056a41106a290300370300200341c0016a41086a2217200341e0056a41086a290300370300200320032903e0053703c0010240024020072002460d0020022116200721020c010b200241016a22162002490d34200241017422182016201820164b1b221641ffffff3f712016470d34201641057422184100480d340240024020020d002018102a21090c010b200920024105742018102e21090b2009450d330b200920024105746a220220032903c001370000200241186a200341c0016a41186a290300370000200241106a2008290300370000200241086a2017290300370000200341d0046a41086a220241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20034180026a41086a2002290300370300200320032903d00437038002200241e0c5c400ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20034190026a41086a2002290300370300200320032903d004370390022003201936028805200341d0036a41186a220820034188056aad4280808080c000841006220241186a290000370300200341d0036a41106a2217200241106a290000370300200341d0036a41086a2218200241086a290000370300200320022900003703d0032002102c200341e0016a41186a22022008290300370300200341e0016a41106a2017290300370300200341e0016a41086a2018290300370300200320032903d0033703e00141c000102a2208450d322008200329038002370000200841086a20034180026a41086a2903003700002008200329039002370010200841186a20034190026a41086a290300370000200820032903e001370020200841286a200341e0016a41086a290300370000200841306a200341e0016a41106a290300370000200841386a20022903003700004110102a2202450d3220022004370000200220063700082003429080808080023702d403200320023602d003200741016a2202200341d0036a106702402002450d00200741057441206a21072009210203402002200341d0036a109101200241206a2102200741606a22070d000b0b20032802d40321022008ad428080808080088420033502d80342208620032802d0032207ad84100102402002450d002007102c0b2008102c2016450d282009102c0c280b200141026a2d00002119200141046a280200211c20012d0001211d2002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d0001211e200320063703d00341002102201e41ff01714101460d010b410121024102211841002116410021170b200320063703f801200320073a00f701200320083a00f601200320093b01f4012003200a3a00f3012003200b3a00f2012003200c3b01f0012003200d3a00ef012003200e3a00ee012003200f3b01ec01200320103a00eb01200320113a00ea01200320123b01e801200320133a00e701200320143a00e201200320153b01e0012003201741ffff0371410874201641187472201841ff01717222093600e30102402002450d0041d6b2c0002108410f210720090e05191c1d1e2f190b200341c0016a41186a200341e0016a41186a2903002206370300200341c0016a41106a200341e0016a41106a2903002204370300200341c0016a41086a200341e0016a41086a2903002205370300200320032903e001221a3703c001200341d0036a41186a2006370300200341d0036a41106a2004370300200341d0036a41086a20053703002003201a3703d003200341d0036a201c201d41ff0171410047201910e10421080c260b200141026a2d00002119200141046a280200211c20012d0001211d2002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d0001211e200320063703d00341002102201e41ff01714101460d010b410121024102211841002116410021170b200320063703d801200320073a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320133a00c701200320143a00c201200320153b01c0012003201741ffff0371410874201641187472201841ff01717222093600c30102402002450d0041d6b2c0002108410f210720090e051e1b1c1d2e1e0b200341d0036a41186a200341c0016a41186a290300370300200341d0036a41106a200341c0016a41106a290300370300200341d0036a41086a200341c0016a41086a290300370300200320032903c0013703d003200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a2002290300370300200320032903d0043703800220024188fbc400ad4280808080d000841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a2002290300370300200320032903d00437039002200341e0016a200341d0036a109f0141c000102a2202450d302002200329038002370000200241086a20034180026a41086a2903003700002002200329039002370010200241186a20034190026a41086a290300370000200220032903e001370020200241286a200341e0016a41086a2208290300370000200241306a200341e0016a41106a2209290300370000200241386a200341e0016a41186a2207290300370000200341d0036a200241c00010d3012008200341d9036a2900003703002009200341e1036a2900003703002007200341e9036a290000370300200320032900d1033703e001410121080240024020032d00d0034101460d00410021160c010b200341a2016a20032d00e2013a0000200341a0026a41086a200341f3016a290000370300200341ad026a2007290000370000200320032f01e0013b01a001200320032900eb013703a0024101211620032800e701210720032800e30121090b2002102c0240024020160d00410b210741cb96c50021090c010b200341d0056a41026a200341a0016a41026a2d00003a0000200341c0026a41086a200341a0026a41086a290300370300200341c0026a410d6a200341a0026a410d6a290000370000200320032f01a0013b01d005200320032903a0023703c002410021080b200341d0066a41026a2202200341d0056a41026a2d00003a0000200341e8046a41086a2216200341c0026a41086a290300370300200341e8046a41106a200341c0026a41106a290300370300200320032f01d0053b01d006200320032903c0023703e80402402008450d0020092108410121090c2f0b20034188056a41026a20022d000022023a0000200341e0056a41086a22082016290300370300200341e0056a410d6a2216200341e8046a410d6a290000370000200320032f01d00622173b018805200320032903e8043703e005200341e3036a2008290300370000200341e8036a2016290000370000200320023a00d203200320173b01d003200320073600d703200320093600d303200320032903e0053700db03200341d0036a201c201d41ff0171410047201910e10421080c250b41cf8cc6002108410e210720022d0000417f6a221741024b0d2c200141046a280200211841012109410121160240024020170e03003001000b200241046a2d00000d2d4101210941012116200241086a28020041036c2002410c6a280200410174490d2f0b200341d0036a201810d704024020032d00f8034103470d0041fb96c5002108410d2107410121090c2e0b200341e0056a41206a200341d0036a41286a280200360200200341e0056a41186a200341d0036a41206a2903002206370300200341e0056a41106a200341d0036a41186a22022903002204370300200341e0056a41086a200341d0036a41106a22072903002205370300200320032903d803221a3703e005200341c0016a41186a2006370300200341c0016a41106a2004370300200341c0016a41086a20053703002003201a3703c0012002200637030020072004370300200341d0036a41086a20053703002003201a3703d003200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a22082002290300370300200320032903d0043703800220024188fdc400ad4280808080d001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a22072002290300370300200320032903d00437039002200341e0016a200341d0036a109f0141c000102a2202450d2f2002200329038002370000200241086a20082903003700002002200329039002370010200241186a2007290300370000200220032903e001370020200241286a200341e0016a41086a290300370000200241306a200341e0016a41106a290300370000200241386a200341e0016a41186a29030037000041012109200341206a200241c000410141004100109701200328022021072002102c20074101460d0d200341d0036a41186a200341c0016a41186a290300370300200341d0036a41106a200341c0016a41106a290300370300200341d0036a41086a200341c0016a41086a290300370300200320032903c0013703d003200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a22082002290300370300200320032903d0043703800220024188fdc400ad4280808080d001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a22072002290300370300200320032903d00437039002200341e0016a200341d0036a109f0141c000102a2202450d2f2002200329038002370000200241086a20082903003700002002200329039002370010200241186a2007290300370000200220032903e001370020200241286a200341e0016a41086a290300370000200241306a200341e0016a41106a290300370000200241386a200341e0016a41186a29030037000041012109200341013a00d0032002ad4280808080800884200341d0036aad4280808080108410012002102c201810d20441002108410121160c2e0b200341a0056a200141196a29000037030020034198056a200141116a29000037030020034190056a200141096a290000370300200320012900013703880541cf8cc6002108410e210720022d0000417f6a220941024b0d2b0240024020090e03002d01000b200241086a2802004101742002410c6a280200490d2c200241046a28020041ff01710d2c0b200341e0016a41186a4200370300200341e0016a41106a22094200370300200341e0016a41086a22074200370300200342003703e001200341d0046a41086a220241bad6c500ad428080808090018422041002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d004220637038002200320063703e00120024184c6c400ad4280808080c001841002220841086a290000370300200320082900003703d0042008102c200920032903d0042206370300200341c0016a41086a2007290300370300200341c0016a41106a2006370300200341c0016a41186a20022903003703002003200637039002200320032903e0013703c001200341306a200341c0016a4120410141004100109701024020032802304101470d00418897c500210841152107410121090c2d0b200341d0036a41186a20034188056a41186a290300370300200341d0036a41106a20034188056a41106a290300370300200341d0036a41086a20034188056a41086a29030037030020032003290388053703d003200220041002220741086a290000370300200320072900003703d0042007102c20034180026a41086a2002290300370300200320032903d00437038002200241bcfcc400ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a2002290300370300200320032903d00437039002200341e0016a200341d0036a109f0141c000102a2202450d2e2002200329038002370000200241086a20034180026a41086a2903003700002002200329039002370010200241186a20034190026a41086a220b290300370000200220032903e001370020200241286a200341e0016a41086a2207290300370000200241306a200341e0016a41106a2216290300370000200241386a200341e0016a41186a2217290300370000200341d0036a200241c00010ed0320032802d003210c20032903d803210420032802d40321082002102c02402008450d00200341d0036a41186a4200370300200341d0036a41106a220d4200370300200341d0036a41086a22184200370300200342003703d003200341d0046a41086a22024191b0c200ad4280808080e000841002220a41086a2900003703002003200a2900003703d004200a102c20182002290300370300200320032903d0043703d003200241acb0c200ad4280808080e000841002220a41086a2900003703002003200a2900003703d004200a102c200d20032903d0042206370300200341e0056a41086a2018290300370300200341e0056a41106a2006370300200341e0056a41186a2002290300370300200320063703e001200320032903d0033703e005200341286a200341e0056a4120109401200328022c410020032802281b210202402004a7450d002008102c0b2002200c4f0d00419d97c5002108411a2107410121090c2d0b200341d0036a41186a20034188056a41186a290300370300200341d0036a41106a20034188056a41106a290300370300200341d0036a41086a20034188056a41086a29030037030020032003290388053703d003200341003a00f003201742003703002016420037030020074200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d004220637038002200320063703e00120024184c6c400ad4280808080c001841002220841086a290000370300200320082900003703d0042008102c200b20022903002206370300200320032903d00422043703900220092004370000200941086a2006370000200341c0016a41086a2007290300370300200341c0016a41106a2016290300370300200341c0016a41186a2017290300370300200320032903e0013703c001200341003602e805200342013703e0052003200341e0056a36028803200341d0036a20034188036a109402024020032d00f003220241024b0d00024002400240024020020e03000102000b410021070c020b410121070c010b410221070b200320073a00d0040240024020032802e40520032802e8052202460d0020032802e00521080c010b200241016a22072002490d31200241017422082007200820074b1b22074100480d310240024020020d002007102a21080c010b20032802e00520022007102e21080b2008450d30200320073602e405200320083602e00520032d00d004210720032802e80521020b2003200241016a3602e805200820026a20073a00000b20032802e4052102200341c0016aad428080808080048420033502e80542208620032802e0052207ad84100102402002450d002007102c0b410021080c2a0b200341f8056a200141196a290000370300200341f0056a200141116a290000370300200341e0056a41086a200141096a290000370300200320012900013703e00541cf8cc600210820022d0000417f6a220741024b0d210240024020070e03002301000b200241046a2d00000d22200241086a2802004102742002410c6a28020041036c490d220b200341d0036a41186a200341e0056a41186a290300370300200341d0036a41106a200341e0056a41106a290300370300200341d0036a41086a200341e0056a41086a290300370300200320032903e0053703d003200341023a00f003200341e0016a41186a4200370300200341e0016a41106a22094200370300200341e0016a41086a22074200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d004220637038002200320063703e00120024184c6c400ad4280808080c001841002220841086a290000370300200320082900003703d0042008102c200920032903d0042206370300200341c0016a41086a2007290300370300200341c0016a41106a2006370300200341c0016a41186a20022903003703002003200637039002200320032903e0013703c00120034100360290052003420137038805200320034188056a36028803200341d0036a20034188036a109402024020032d00f003220241024b0d00024002400240024020020e03000102000b410021070c020b410121070c010b410221070b200320073a00d00402400240200328028c052003280290052202460d0020032802880521080c010b200241016a22072002490d30200241017422082007200820074b1b22074100480d300240024020020d002007102a21080c010b20032802880520022007102e21080b2008450d2f2003200736028c05200320083602880520032d00d004210720032802900521020b2003200241016a36029005200820026a20073a00000b200328028c052102200341c0016aad42808080808004842003350290054220862003280288052207ad8410012002450d202007102c0c200b200341f8056a200141196a290000370300200341f0056a200141116a290000370300200341e8056a200141096a290000370300200320012900013703e00541cf8cc600210820022d0000417f6a220741024b0d200240024020070e03002201000b200241086a2802002002410c6a280200490d21200241046a28020041ff01710d210b200341d0036a41186a200341e0056a41186a290300370300200341d0036a41106a200341e0056a41106a290300370300200341d0036a41086a200341e0056a41086a290300370300200320032903e0053703d003200341013a00f003200341e0016a41186a4200370300200341e0016a41106a22094200370300200341e0016a41086a22074200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d004220637038002200320063703e00120024184c6c400ad4280808080c001841002220841086a290000370300200320082900003703d0042008102c200920032903d0042206370300200341c0016a41086a2007290300370300200341c0016a41106a2006370300200341c0016a41186a20022903003703002003200637039002200320032903e0013703c00120034100360290052003420137038805200320034188056a36028803200341d0036a20034188036a109402024020032d00f003220241024b0d00024002400240024020020e03000102000b410021070c020b410121070c010b410221070b200320073a00d00402400240200328028c052003280290052202460d0020032802880521080c010b200241016a22072002490d2f200241017422082007200820074b1b22074100480d2f0240024020020d002007102a21080c010b20032802880520022007102e21080b2008450d2e2003200736028c05200320083602880520032d00d004210720032802900521020b2003200241016a36029005200820026a20073a00000b200328028c052102200341c0016aad42808080808004842003350290054220862003280288052207ad8410012002450d1f2007102c0c1f0b200141286a280200210a200141246a2802002118200341a0036a200141196a29000037030020034198036a200141116a29000037030020034188036a41086a200141096a29000037030020032001290001370388034101210941cf8cc6002108410e210720022d0000417e6a221641014b0d290240024020160e020001000b200241046a2d00000d2a200241086a28020041036c2002410c6a280200410174490d2a0b200341e0016a41186a220b420037030041102107200341e0016a41106a22164200370300200341e0016a41086a22024200370300200342003703e001200341d0046a41086a220841bad6c500ad42808080809001841002221741086a290000370300200320172900003703d0042017102c20022008290300370300200320032903d004220637038002200320063703e00120084184c6c400ad4280808080c001841002221741086a290000370300200320172900003703d0042017102c201620032903d0042206370300200341c0016a41086a2002290300370300200341c0016a41106a2006370300200341c0016a41186a20082903003703002003200637039002200320032903e0013703c001200341d0036a200341c0016a10ea0320032d00f0032117200b200341d0036a41186a2903003703002016200341d0036a41106a2903003703002002200341d0036a41086a290300370300200320032903d0033703e0010240024020174103470d004101210241b797c50021080c010b200341a2016a20032d00e2013a0000200341a0026a41086a200341f3016a290000370300200341ad026a200b290000370000200320032f01e0013b01a001200320032900eb013703a0024100210220032800e701210720032800e30121080b200341d0056a41026a220b200341a0016a41026a2d00003a0000200341e0056a41086a200341a0026a41086a290300370300200341e0056a410d6a220c200341a0026a410d6a290000370000200320032f01a0013b01d005200320032903a0023703e00520020d292003419b056a200341e8056a290300370000200341a0056a200c290000370000200320032f01d0053b0188052003200736008f052003200836008b05200320032903e005370093052003200b2d00003a008a05024020170d0041c797c5002108412a21070c2a0b024020034188036a20034188056a412010dd05450d0041f197c5002108410c21070c2a0b200341e0016a41186a220b4200370300200341e0016a41106a220c4200370300200341e0016a41086a22074200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d004220637038002200320063703e00120024184c6c400ad4280808080c001841002220841086a290000370300200320082900003703d0042008102c20034190026a41086a20022903002206370300200320032903d00422043703900220162004370000201641086a2006370000200341c0016a41086a2007290300370300200341c0016a41106a200c290300370300200341c0016a41186a200b290300370300200320032903e0013703c001200341c0016aad42808080808004841005200341d0036a41186a220b4200370300200341d0036a41106a22084200370300200341d0036a41086a22074200370300200342003703d00320024191b0c200ad4280808080e000841002221641086a290000370300200320162900003703d0042016102c20072002290300370300200320032903d0043703d003200241acb0c200ad4280808080e000841002221641086a290000370300200320162900003703d0042016102c200820032903d0042206370300200341e0056a41086a2007290300370300200341e0056a41106a2006370300200341e0056a41186a2002290300370300200320063703e001200320032903d0033703e005200341386a200341e0056a4120109401200328023c210220032802382116200b20034188036a41186a290300370300200820034188036a41106a290300370300200720034188036a41086a29030037030020032003290388033703d003410021082002410020161b20184180a30520184180a3054b1b6a200341d0036a2017200a10ca040c290b200341d8026a200141196a290000370300200341c0026a41106a200141116a290000370300200341c0026a41086a200141096a290000370300200320012900013703c00241cf8cc6002108410e210720022d00004102470d27200241236a2d00002116200241216a2f000021172002411f6a2d000021182002411d6a2f0000210a2002410f6a2d0000210b2002410d6a2f0000210c2002410b6a2d0000210d200241096a2f0000210e200241076a2d0000210f200241056a2f00002110200241246a2802002111200241206a2d00002112200241116a2900002106200241106a2d000021132002410c6a2d00002114200241086a2d00002115200241046a2d000021092003200241196a2800003602d803200320063703d00320094101470d272003201720164110747222023b01a40541102107200341a6056a20024110763a00002003200a20184110747222023b01a005200341a2056a20024110763a00002003200c200b4110747222023b01900520034192056a20024110763a000020032006a722023b01940520034196056a20024110763a0000200320113a00a705200320123a00a305200320032902d40337039805200320133a009305200320143a008f05200320153a008b05200320064218883c0097052003200e200d4110747222023b018c05200320024110763a008e0520032010200f4110747222023b018805200320024110763a008a05200341e0016a41186a22174200370300200341e0016a41106a22094200370300200341e0016a41086a22024200370300200342003703e001200341d0046a41086a220841bad6c500ad42808080809001841002221641086a290000370300200320162900003703d0042016102c20022008290300370300200320032903d004220637038002200320063703e00120084184c6c400ad4280808080c001841002221641086a290000370300200320162900003703d0042016102c200920032903d0042206370300200341c0016a41086a2002290300370300200341c0016a41106a2006370300200341c0016a41186a20082903003703002003200637039002200320032903e0013703c001200341d0036a200341c0016a10ea0320032d00f00321082017200341d0036a41186a22162903003703002009200341d0036a41106a22182903003703002002200341d0036a41086a220a290300370300200320032903d0033703e00120084103460d0220034188036a41186a2017290300220637030020034188036a41106a2009290300220437030020034188036a41086a20022903002205370300200320032903e001221a370388032016200637030020182004370300200a20053703002003201a3703d003419198c5002108200341c0026a200341d0036a412010dd050d27200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a22082002290300370300200320032903d00437038002200241bcfcc400ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a22072002290300370300200320032903d00437039002200341e0016a200341c0026a109f0141c000102a2202450d2a2002200329038002370000200241086a20082903003700002002200329039002370010200241186a2007290300370000200220032903e001370020200241286a200341e0016a41086a290300370000200241306a200341e0016a41106a290300370000200241386a200341e0016a41186a290300370000200341d0036a200241c00010ed0320032903d803210620032802d803211820032802d40321172002102c41002107024020170d0041012117410021184100210a0c1c0b2006a7210a41002102024002402006422088a7220b41014b0d00200b0e021d011d0b200b210703402007410176220820026a22162002201720164105746a20034188056a412010dd054101481b2102200720086b220741014b0d000b0b0240201720024105746a20034188056a412010dd0522070d0041a198c500210841262107200a450d282017102c410121090c290b200341d0036a41186a20034188056a41186a290300370300200341d0036a41106a20034188056a41106a290300370300200341d0036a41086a20034188056a41086a29030037030020032003290388053703d00302402007411f7620026a2216200b4b0d00200341d0036a2108200b21070c1d0b41ecb3c000411e41acfec5001036000b4101210920022d000120022d0000720d19200141046a28020010d20441002108410121160c280b4101210920022d000120022d0000720d18200141046a2802002117200341d0036a41186a4200370300200341d0036a41106a22164200370300200341d0036a41086a22074200370300200342003703d003200341d0046a41086a220241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d0043703d003200241b6c5c400ad4280808080d001841002220841086a290000370300200320082900003703d0042008102c201620032903d0042206370300200341e0056a41086a2007290300370300200341e0056a41106a2006370300200341e0056a41186a2002290300370300200320063703e001200320032903d0033703e005200341d0036a200341e0056a10f00320032802d0032202410420021b210c0240024020032902d403420020021b2206422088a722160d004100210b0c010b200c41246a210d410021184100210b410021080240034002400240200b450d00200c200841286c6a2102200c200820186a41286c6a21070340200820164f0d1d2017200241246a280200460d020240201820086a220a20164f0d0020072002290200370200200741206a200241206a290200370200200741186a200241186a290200370200200741106a200241106a290200370200200741086a200241086a290200370200200741286a2107200241286a2102200841016a22082016490d010c050b0b41fcb4c000200a20161038000b200d200841286c6a21020340200820164f0d1c20172002280200460d01200241286a2102200841016a22082016490d000b4100210b0c030b2018417f6a2118200b41016a210b200841016a22082016490d000b0b200b450d00200820164f0d00200c200841286c6a22024100200b6b41286c6a2002201620086b41286c10dc051a0b02402016200b6b220720164f0d00200341e0016a41186a4200370300200341e0016a41106a22174200370300200341e0016a41086a22084200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002221641086a290000370300200320162900003703d0042016102c20082002290300370300200320032903d004220437038002200320043703e001200241b6c5c400ad4280808080d001841002221641086a290000370300200320162900003703d0042016102c201720032903d0042204370300200341c0016a41086a2008290300370300200341c0016a41106a2004370300200341c0016a41186a20022903003703002003200437039002200320032903e0013703c001200341203602d4032003200341c0016a3602d003200c2007200341d0036a10e204410021082006a7450d17200c102c410121160c280b41aa99c5002108411221072006a7450d26200c102c0c260b41fd97c500210841142107410121090c250b200341d0046a41146a4109360200200341dc046a410c36020020034188036a41146a41033602002003420337028c03200341ec9fc600360288032003410c3602d404200320034180026a3602a001200320034190026a3602e001200342043703e003200342013702d403200341c0a0c6003602d0032003200341d0046a360298032003200341d0036a3602e0042003200341e0016a3602d8042003200341a0016a3602d00420034188036a41fca0c6001041000b200820171047000b20092017103f000b200220091047000b103a000b41d696c5002108412521070c1f0b200341e8046a41186a200141196a290000370300200341e8046a41106a200141116a290000370300200341e8046a41086a200141096a290000370300200320012900013703e8042002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d00012119200320063703d00341002102201941ff01714101460d010b410121024100211741022118410021160b200320063701d801200320073a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320133a00c701200320143a00c201200320153b01c0012003201741ffff0371410874201841ff01717220164118747222093600c30102402002450d0041d6b2c0002108410f210702400240024020090e051100010221110b410e210741dd8cc6002108410121090c210b4113210741c3b2c0002108410121090c200b4111210741b2b2c0002108410121090c1f0b200341c0026a41186a200341c0016a41186a290100370300200341c0026a41106a200341c0016a41106a290100370300200341c0026a41086a200341c0016a41086a290100370300200320032901c0013703c002200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a2002290300370300200320032903d00437038002200241c3c5c400ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a2002290300370300200320032903d00437039002200341e0016a200341e8046a109f0141c000102a2202450d202002200329038002370000200241086a20034180026a41086a2903003700002002200329039002370010200241186a20034190026a41086a290300370000200220032901e001370020200241286a200341e0016a41086a290100370000200241306a200341e0016a41106a290100370000200241386a200341e0016a41186a290100370000200341d0036a200241c00010ef03200341e0056a41086a2216200341d0036a41206a290300370300200341e0056a41106a200341d0036a41286a290300370300200341e0056a41186a2208200341d0036a41306a290300370300200341e0056a41206a2207200341d0036a41386a2802003602002003200341d0036a41186a2903003703e005024020032802e0032217450d00200341d0036a410c6a35020021052003418c046a280200211820032902d403210420032802e403210a20032802d003210d20034188056a41206a220b200728020036020020034188056a41186a2207200829030037030020034188056a41106a2208200341e0056a41106a220c29030037030020034188056a41086a22092016290300370300200320032903e005370388052002102c20034188036a41206a200b28020036020020034188036a41186a200729030037030020034188036a41106a200829030037030020034188036a41086a20092903003703002003200329038805370388032007200341a4036a29020037030020082003419c036a290200370300200920034188036a410c6a2902003703002003200329028c03370388050240200a450d002017102c0b200341d0036a41186a22164200370300200341d0036a41106a22084200370300200341d0036a41086a22074200370300200342003703d003200341d0046a41086a22024191b0c200ad4280808080e000841002220941086a290000370300200320092900003703d0042009102c20072002290300370300200320032903d0043703d003200241acb0c200ad4280808080e000841002220941086a290000370300200320092900003703d0042009102c200820032903d0042206370300200341e0056a41086a22092007290300370300200c2006370300200341e0056a41186a22172002290300370300200320063703e001200320032903d0033703e00520034198016a200341e0056a41201094010240200328029c0141002003280298011b20184180de344100200341c0026a20034188056a412010dd051b6a41809c316a4f0d0041092107419099c5002108410121090c200b200542208620044220888421052004422086200dad84211a20164200370300200341d0036a41106a220a420037030020074200370300200342003703d003200241bad6c500ad42808080809001841002221841086a290000370300200320182900003703d0042018102c20072002290300370300200320032903d0043703d003200241b6c5c400ad4280808080d001841002221841086a290000370300200320182900003703d0042018102c200341e0016a41086a20022903002206370300200320032903d00422043703e00120082004370000200841086a200637000020092007290300370300200341e0056a41106a200a29030037030020172016290300370300200320032903d0033703e005200341d0036a200341e0056a10f00320032802d0032202410420021b221620032902d403420020021b2206422088a741286c6a21082016210202400240034020022008460d010240200341e8046a200241046a2207460d00200741246a21022007200341e8046a412010dd050d010b0b410821072006a70d01419999c5002108410121090c210b200341d0036a20034188056a200341c0026a201a200510c001200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a22082002290300370300200320032903d00437038002200241c3c5c400ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a22072002290300370300200320032903d00437039002200341e0016a200341e8046a109f0141c000102a2202450d222002200329038002370000200241086a20082903003700002002200329039002370010200241186a2007290300370000200220032901e001370020200241286a200341e0016a41086a290100370000200241306a200341e0016a41106a290100370000200241386a200341e0016a41186a2901003700002002ad428080808080088410052002102c200341d0036a41086a410f3a0000200341d9036a20032903e804370000200341e1036a200341e8046a41086a290300370000200341e9036a200341e8046a41106a290300370000200341f1036a200341e8046a41186a290300370000200341f9036a20032903880537000020034181046a20034188056a41086a29030037000020034189046a20034188056a41106a29030037000020034191046a20034188056a41186a290300370000200341063a00d003200341c0046a201a370300200341c8046a2005370300200341b1046a200341c0026a41186a290300370000200341a9046a200341c0026a41106a290300370000200341a1046a200341c0026a41086a29030037000020034199046a20032903c002370000410021084101210941014100200341d0036a1092012006a7450d102016102c410121160c210b2016102c419999c5002108410121090c1f0b2002102c41092107410121094101211641a199c50021080c1f0b2001410c6a280200211d200141086a280200211c200141046a280200210a2002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241046a2d00002115200241026a2f0100211902400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d0001211e200320063703d00341002102201e41ff01714101460d010b410121024100211741022118410021160b200320063701d801200320073a00d701200320083a00d601200320093b01d4012003200b3a00d3012003200c3a00d2012003200d3b01d0012003200e3a00cf012003200f3a00ce01200320103b01cc01200320113a00cb01200320123a00ca01200320133b01c801200320143a00c701200320153a00c201200320193b01c0012003201741ffff0371410874201841ff01717220164118747222093600c301024002402002450d0041d6b2c0002108410f2107024002400240024020090e050001020305000b20032800c701210820032800cb0121070c040b41dd8cc6002108410e21070c030b41c3b2c0002108411321070c020b41b2b2c0002108411121070c010b20034188036a41186a200341c0016a41186a29010037030020034188036a41106a200341c0016a41106a29010037030020034188036a41086a200341c0016a41086a290100370300200320032901c00137038803200341d0036a41186a2207201dad422086200aad841006220241186a290000370300200341d0036a41106a2208200241106a290000370300200341d0036a41086a2209200241086a290000370300200320022900003703d0032002102c20034188056a41186a200729030037030020034188056a41106a200829030037030020034188056a41086a2009290300370300200320032903d00337038805200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a2002290300370300200320032903d00437038002200241c3c5c400ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a2002290300370300200320032903d00437039002200341e0016a20034188056a109f0141c000102a2202450d202002200329038002370000200241086a20034180026a41086a2903003700002002200329039002370010200241186a20034190026a41086a290300370000200220032901e001370020200241286a200341e0016a41086a290100370000200241306a200341e0016a41106a290100370000200241386a200341e0016a41186a29010037000020034190016a200241c00041014100410010970120032802900121072002102c024020074101470d0041ee98c5002108411621070c010b200341d0036a41186a4200370300200341d0036a41106a22094200370300200341d0036a41086a22074200370300200342003703d003200341d0046a41086a220241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d0043703d003200241b6c5c400ad4280808080d001841002220841086a290000370300200320082900003703d0042008102c200920032903d0042206370300200341e0056a41086a2007290300370300200341e0056a41106a2006370300200341e0056a41186a2002290300370300200320063703e001200320032903d0033703e005200341d0036a200341e0056a10f00320032802d0032202410420021b221720032902d403420020021b2206422088a741286c6a2108201721020240034020022008460d01024020034188056a200241046a2207460d00200741246a2102200720034188056a412010dd050d010b0b200341d0036a41186a22084200370300200341d0036a41106a22184200370300200341d0036a41086a22024200370300200342003703d003200341d0046a41086a22074191b0c200ad4280808080e000841002221641086a290000370300200320162900003703d0042016102c20022007290300370300200320032903d0043703d003200741acb0c200ad4280808080e000841002221641086a290000370300200320162900003703d0042016102c200341e0016a41086a20072903002204370300200320032903d00422053703e00120092005370000200941086a2004370000200341e0056a41086a22072002290300370300200341e0056a41106a22092018290300370300200341e0056a41186a22162008290300370300200320032903d0033703e00520034188016a200341e0056a4120109401200328028c012118200328028801210b201620034188056a41186a220c290300370300200920034188056a41106a220d290300370300200720034188056a41086a220929030037030020032003290388053703e0052008201d360200200341e4036a201c360200200341f4036a20034188036a41086a2207290300370200200341fc036a20034188036a41106a220829030037020020034184046a20034188036a41186a220e290300370200200342003703d803200342003703d0032003200a3602e00320032003290388033702ec0341002116200320184100200b1b36028c04200341e0056a200341d0036a10e304200341a8046a4200370300200341a0046a42003703002002410b3a0000200341d9036a200329038805370000200341e1036a2009290300370000200341e9036a200d290300370000200341f1036a200c290300370000200341f9036a20032903880337000020034181046a200729030037000020034189046a200829030037000020034191046a200e290300370000200341063a00d0034101210941014100200341d0036a10920102402006a7450d002017102c0b410021080c200b418499c5002108410c21072006a7450d002017102c0b4100211641012109201c450d1e200a102c0c1e0b2001410c6a280200211d200141086a280200210b200141046a280200210a2002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241046a2d00002119200241026a2f0100211c02400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d0001211e200320063703d00341002102201e41ff01714101460d010b410121024100211741022118410021160b200320063701d801200320073a00d701200320083a00d601200320093b01d4012003200c3a00d3012003200d3a00d2012003200e3b01d0012003200f3a00cf01200320103a00ce01200320113b01cc01200320123a00cb01200320133a00ca01200320143b01c801200320153a00c701200320193a00c2012003201c3b01c0012003201741ffff0371410874201841ff01717220164118747222093600c301024002402002450d0041d6b2c0002108410f2107024002400240024020090e050001020305000b20032800c701210820032800cb0121070c040b41dd8cc6002108410e21070c030b41c3b2c0002108411321070c020b41b2b2c0002108411121070c010b20034188036a41186a200341c0016a41186a29010037030020034188036a41106a200341c0016a41106a29010037030020034188036a41086a200341c0016a41086a290100370300200320032901c00137038803200341d0036a41186a2207201dad2206422086200aad841006220241186a290000370300200341d0036a41106a2208200241106a290000370300200341d0036a41086a2209200241086a290000370300200320022900003703d0032002102c20034188056a41186a200729030037030020034188056a41106a200829030037030020034188056a41086a2009290300370300200320032903d00337038805200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a2002290300370300200320032903d00437038002200241c3c5c400ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a2002290300370300200320032903d00437039002200341e0016a20034188056a109f0141c000102a2202450d1f2002200329038002370000200241086a20034180026a41086a2903003700002002200329039002370010200241186a20034190026a41086a290300370000200220032901e001370020200241286a200341e0016a41086a290100370000200241306a200341e0016a41106a290100370000200241386a200341e0016a41186a29010037000020034180016a200241c00041014100410010970120032802800121072002102c024020074101470d0041ee98c5002108411621070c010b200341e8006a200642004280a094a58d1d420010e005200341f8006a20034188036a20032903682206200341e8006a41086a290300220410c101024020032802782208450d00200328027c21070c010b200341d0036a41186a22094200370300200341d0036a41106a22164200370300200341d0036a41086a22024200370300200342003703d003200341d0046a41086a22074191b0c200ad4280808080e000841002220841086a290000370300200320082900003703d0042008102c20022007290300370300200320032903d0043703d003200741acb0c200ad4280808080e000841002220841086a290000370300200320082900003703d0042008102c201620032903d0042205370300200341e0056a41086a22082002290300370300200341e0056a41106a22162005370300200341e0056a41186a22172007290300370300200320053703e001200320032903d0033703e005200341e0006a200341e0056a41201094012003280264210720032802602118201720034188056a41186a220c290300370300201620034188056a41106a2217290300370300200820034188056a41086a221629030037030020032003290388053703e0052009201d360200200341e4036a200b360200200341f4036a20034188036a41086a2208290300370200200341fc036a20034188036a41106a220b29030037020020034184046a20034188036a41186a220d290300370200200320043703d803200320063703d0032003200a3602e00320032003290388033702ec034100210920032007410020181b36028c04200341e0056a200341d0036a10e304200341a8046a2004370300200341a0046a20063703002002410b3a0000200341d9036a200329038805370000200341e1036a2016290300370000200341e9036a2017290300370000200341f1036a200c290300370000200341f9036a20032903880337000020034181046a200829030037000020034189046a200b29030037000020034191046a200d290300370000200341063a00d0034101211641014100200341d0036a109201410021080c1e0b4101211641002109200b450d1d200a102c0c1d0b4101210920022d000120022d0000720d0d200341e0016a41186a4200370300200341e0016a41106a22164200370300200341e0016a41086a22074200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d004220637038002200320063703e001200241d5c5c400ad4280808080b001841002220841086a290000370300200320082900003703d0042008102c201620032903d0042206370300200341c0016a41086a2007290300370300200341c0016a41106a2006370300200341c0016a41186a20022903003703002003200637039002200320032903e0013703c001200341c0016aad4280808080800484100541002108410121160c1c0b200241196a2d00002117200241186a2d00002118200241166a2f0100210a2002411a6a2901002106200241156a3100002104200241146a3100002105200241126a330100211a200241116a2d00002113200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d000021112002410c6a2d0000210d2002410a6a2f0100210e200241096a2d00002112200241046a2d0000211441022116200241026a2f01002115024002400240024020022d0000450d00200320063702d403200320173a00d303200320183a00d2032003200a3b01d003410121070c010b200241086a2d00002108200241066a2f01002109200241056a2d0000211d20022d00012102200320063703d00341012107200241ff01714101460d010b41002109410021080c010b2006423888a7211c2006422088a721102006421888a721192006a7210f41002107201d21160b200b411074200c41ffff037172210b200d411074200e41ffff037172210c2008411074200941ffff037172210202402007450d0041d6b2c0002108410f210702402002410874201641ff0171720e050008090a1b000b200c4108742012722108200b4108742011722107410121090c1b0b200320103b01bc02200341be026a20104110763a00002003200f3b01b802200341ba026a200f4110763a00002003200b3b01ac02200341ae026a200b4110763a00002003200c3b01a802200341aa026a200c4110763a0000200320143a00a202200320153b01a0022003201c3a00bf02200320193a00bb02200320133a00af02200320113a00ab02200320123a00a702200320163a00a302200320023b01a402200320024110763a00a60220032005421086201a84200442188684200aad42ffff0383422086842018ad42ff0183423086842017ad42ff0183423886843703b002200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a22082002290300370300200320032903d00437038002200241e0b4c400ad4280808080b001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a22072002290300370300200320032903d0043703900220034188036a200341a0026a109f0141c000102a2202450d1c2002200329038002370000200241086a20082903003700002002200329039002370010200241186a20072903003700002002200329038803370020200241286a20034188036a41086a290300370000200241306a20034198036a290300370000200241386a20034188036a41186a290300370000200341d8006a200241c000410141004100109701200328025821072002102c024020074101460d0041e198c5002108410d2107410121090c1b0b200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a22082002290300370300200320032903d00437038002200241e0b4c400ad4280808080b001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a22072002290300370300200320032903d0043703900220034188036a200341a0026a109f0141c000102a2202450d1c2002200329038002370000200241086a20082903003700002002200329039002370010200241186a20072903003700002002200329038803370020200241286a20034188036a41086a290300370000200241306a20034188036a41106a290300370000200241386a20034188036a41186a290300370000200341d0036a200241c00010e803024020032d00f103220841024622160d002002ad428080808080088410050b200341e8046a41186a2209200341d0036a41186a290300370300200341e8046a41106a2217200341d0036a41106a290300370300200341e8046a41086a2218200341d0036a41086a2207290300370300200320032903d0033703e80420032d00f003210a200341c0026a200341d0036a41226a41c10010db051a200341e0016a41086a220b2018290300370300200341e0016a41106a2017290300370300200341e0016a41186a2009290300370300200320032903e8043703e00120034188036a200341c0026a41c10010db051a41072109024020160d00200341c0016a41186a200341e0016a41186a290300370300200341c0016a41106a200341e0016a41106a290300370300200341c0016a41086a200b290300370300200320032903e0013703c001200320083a00880520034188056a41017220034188036a41c10010db05211620034188056a41226a21090240024020032d00a9054101460d00200341003602d0050c010b200341d0056a200910d50420032d00880521080b02400240024002400240200841ff01714101460d0020034100360280020c010b20034180026a201610d5042003280280020d010b024020032d00a9054101460d00200341d0036a10d00420033502d80342208620032802d0032208ad84100520032802d403450d022008102c0c020b200341d0036a10d00420032802d0032108200320032802d8033602e405200320083602e0052009200341e0056a10a10220032802d403450d012008102c0c010b20034190026a41086a20034180026a41086a28020022093602002003200329038002220637039002200341e0056a2006a72217200910e8030240024020032d0081064102470d00200341003602d804200342013703d004200341a0016a41146a410d360200200341ac016a410b360200200341093602cc06200341bad6c5003602c8062003410b3602a4012003410b3602d406200341e0b4c4003602d006200320034190026a3602b0012003200341d0066a3602a8012003200341c8066a3602a0012003200341d0046a3602dc06200341d0036a41146a4103360200200342033702d403200341849dc5003602d0032003200341a0016a3602e003200341dc066a41c49ac500200341d0036a10391a20033502d80442208620033502d00484100420032802d404450d0120032802d004102c0c010b200341d0036a200341e0056a41c20010db051a200341b2046a200341a9056a220841206a2d00003a0000200341aa046a200841186a290000370100200341a2046a200841106a2900003701002003419a046a200841086a290000370100200341d0036a41c2006a2008290000370100200341003602a801200342013703a001200341d0036a200341a0016a109101024020032d00f003220841064b0d000240024002400240024002400240024020080e0700010203040506000b410021160c060b410121160c050b410221160c040b410321160c030b410421160c020b410521160c010b410621160b200320163a00d0040240024020032802a40120032802a8012208460d0020032802a00121180c010b200841016a22162008490d23200841017422182016201820164b1b22164100480d230240024020080d002016102a21180c010b20032802a00120082016102e21180b2018450d22200320163602a401200320183602a00120032d00d004211620032802a80121080b2003200841016a3602a801201820086a20163a00000b200341f1036a200341a0016a10a30220032802a40121082009ad4220862017ad8420033502a80142208620032802a0012209ad8410012008450d002009102c0b0240200328029402450d00200328029002102c0b410121090c010b410021090b0240024020032802d00522080d00410021160c010b20034190026a41086a200341d0056a41086a2802002217360200200320032903d005220637039002200341e0056a2006a7220b201710e8030240024020032d0081064102470d00200341003602a801200342013703a001200341d0046a41146a410d360200200341dc046a410b360200200341093602cc06200341bad6c5003602c8062003410b3602d4042003410b3602d406200341e0b4c4003602d006200320034190026a3602e0042003200341d0066a3602d8042003200341c8066a3602d0042003200341a0016a3602dc06200341d0036a41146a4103360200200342033702d403200341a89cc5003602d0032003200341d0046a3602e003200341dc066a41c49ac500200341d0036a10391a20033502a80142208620033502a00184100420032802a401450d0120032802a001102c0c010b200341d0036a200341e0056a41e30010db051a20034191046a200341a8056a2d00003a000020034189046a200341a0056a29030037000020034181046a20034198056a290300370000200341f9036a20034188056a41086a29030037000020032003290388053700f103200341003602a801200342013703a001200341d0036a200341a0016a109101024020032d00f003221641064b0d000240024002400240024002400240024020160e0700010203040506000b410021180c060b410121180c050b410221180c040b410321180c030b410421180c020b410521180c010b410621180b200320183a00d0040240024020032802a40120032802a8012216460d0020032802a001210c0c010b201641016a22182016490d222016410174220c2018200c20184b1b22184100480d220240024020160d002018102a210c0c010b20032802a00120162018102e210c0b200c450d21200320183602a4012003200c3602a00120032d00d004211820032802a80121160b2003201641016a3602a801200c20166a20183a00000b200341f1036a200341a0016a10a30220032802a40121162017ad422086200bad8420033502a80142208620032802a0012217ad8410012016450d002017102c0b0240200328029402450d00200328029002102c0b410121160b02402009200328028002221745720d00200328028402450d002017102c0b02402016200845720d0020032802d405450d002008102c0b200a21090b2002102c200341d0036a41186a4200370300200341d0036a41106a2216420037030020074200370300200342003703d003200341d0046a41086a22024191b0c200ad4280808080e000841002220841086a290000370300200320082900003703d0042008102c20072002290300370300200320032903d0043703d003200241acb0c200ad4280808080e000841002220841086a290000370300200320082900003703d0042008102c201620032903d0042206370300200341e0056a41086a2007290300370300200341e0056a41106a2006370300200341e0056a41186a2002290300370300200320063703e001200320032903d0033703e005200341d0006a200341e0056a4120109401200342e4cab5fbb6ccdcb0e300370388054100210820034188056a200341a0026a427f427f41002009200941ff01714107461b4118744118754102744180d6c5006a2802004180de346c2003280254410020032802501b6a410210be01200741093a0000200341d0036a41096a20032903a002370000200341e1036a200341a0026a41086a290300370000200341e9036a200341a0026a41106a290300370000200341f1036a200341a0026a41186a290300370000200341063a00d00341014100200341d0036a1092010c180b200141216a2d00002116200341a0016a41186a200141196a290000370300200341a0016a41106a200141116a290000370300200341a0016a41086a200141096a290000370300200320012900013703a0012002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241046a2d00002115200241026a2f0100211902400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002117200241066a2f01002118200241056a2d0000210a20022d0001211c200320063703d00341002102201c41ff01714101460d010b41012102410021184102210a410021170b200320063703d801200320073a00d701200320083a00d601200320093b01d4012003200b3a00d3012003200c3a00d2012003200d3b01d0012003200e3a00cf012003200f3a00ce01200320103b01cc01200320113a00cb01200320123a00ca01200320133b01c801200320143a00c701200320153a00c201200320193b01c0012003201841ffff0371410874200a41ff01717220174118747222093600c30102402002450d0041d6b2c0002108410f210720090e050906070819090b200341a0026a41186a200341c0016a41186a290300370300200341a0026a41106a200341c0016a41106a290300370300200341a0026a41086a200341c0016a41086a290300370300200320032903c0013703a002200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a2002290300370300200320032903d00437038002200241e0b4c400ad4280808080b001841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a2002290300370300200320032903d00437039002200341e0016a200341a0026a109f0141c000102a2202450d1b2002200329038002370000200241086a20034180026a41086a2903003700002002200329039002370010200241186a20034190026a41086a290300370000200220032903e001370020200241286a200341e0016a41086a290300370000200241306a200341e0016a41106a290300370000200241386a200341e0016a41186a290300370000200341e0056a200241c00010e80302400240024020032d00810622074102470d002003200341a0026a3602d006200341d0036a10d004200341c0026a20032802d003220720032802d80310d301024020032802d403450d002007102c0b024020032d00c0020d00200341d0036a10d00420032802d0032107200320032802d80336028c052003200736028805200341a0026a20034188056a10a10220032802d403450d022007102c0c020b200341e8046a41186a200341d9026a290000370300200341e8046a41106a200341d1026a290000370300200341e8046a41086a200341c0026a41096a290000370300200320032900c1023703e804200341c0016a200341e8046a10d504200341d0036a20032802c001220920032802c801221710e803024020032d00f1034102470d0020034100360290032003420137038803200341d0046a41146a410d360200200341dc046a410b3602002003410936029402200341bad6c500360290022003410b3602d4042003410b3602e401200341e0b4c4003602e0012003200341c0016a3602e0042003200341e0016a3602d804200320034190026a3602d004200320034188036a3602800220034188056a41146a41033602002003420337028c05200341c09dc500360288052003200341d0046a3602980520034180026a41c49ac50020034188056a10391a20033502900342208620033502880384100420032802d006210820034188056a10d004200328028805210720032003280290053602e401200320073602e0012008200341e0016a10a1020240200328028c05450d002007102c0b0240200328028c03450d00200328028803102c0b20032802c401450d0220032802c001102c0c020b20034188056a200341f1036a41c20010db051a20032d00a905210720034188036a41206a2208200341d0036a41206a2d00003a000020034188036a41186a200341d0036a41186a29030037030020034188036a41106a200341d0036a41106a29030037030020034188036a41086a200341d0036a41086a290300370300200341b0036a200341aa056a410020074101461b360200200320032903d003370388032003200341d0066a3602ac03200341003602e801200342013703e00120034188036a200341e0016a109101024020082d0000220741064b0d000240024002400240024002400240024020070e0700010203040506000b410021080c060b410121080c050b410221080c040b410321080c030b410421080c020b410521080c010b410621080b200320083a00d0040240024020032802e40120032802e8012207460d0020032802e00121180c010b200741016a22082007490d21200741017422182008201820084b1b22084100480d210240024020070d002008102a21180c010b20032802e00120072008102e21180b2018450d20200320083602e401200320183602e00120032d00d004210820032802e80121070b2003200741016a3602e801201820076a20083a00000b200341ac036a200341e0016a10a20220032802e40121072017ad4220862009ad8420033502e80142208620032802e0012208ad84100102402007450d002008102c0b024020032802c401450d0020032802c001102c0b20032802d0062108200341d0036a10d00420032802d0032107200320032802d80336028c052003200736028805200820034188056a10a102024020032802d403450d002007102c0b20034188036a41086a200341e8046a41086a29030037030020034188036a41106a200341e8046a41106a29030037030020034188036a41186a200341e8046a41186a290300370300200320032903e8043703880341012108410021070c020b20034188056a41186a2003419a066a29010037030020034188056a41106a20034192066a29010037030020034188056a41086a2003418a066a29010037030020034188036a41086a200341ab066a29000037030020034188036a41106a200341b3066a29000037030020034188036a41186a200341bb066a2900003703002003200329018206370388052003200341a3066a29000037038803200341a2066a2d000021080c010b41002108410021070b200341d9036a200329038805370000200341f9036a20083a0000200341fa036a200329038803370100200341e1036a20034188056a41086a290300370000200341e9036a20034188056a41106a290300370000200341f1036a20034188056a41186a29030037000020034182046a20034188036a41086a2903003701002003418a046a20034188036a41106a29030037010020034192046a20034188036a41186a290300370100200320073a00d803200320163a00d4032003200341a0016a3602d003200341003602e805200342013703e005200341a0016a200341e0056a1091010240201641064b0d000240024002400240024002400240024020160e0700010203040506000b410021080c060b410121080c050b410221080c040b410321080c030b410421080c020b410521080c010b410621080b200320083a00d0040240024020032802e40520032802e8052207460d0020032802e00521090c010b200741016a22082007490d1e200741017422092008200920084b1b22084100480d1e0240024020070d002008102a21090c010b20032802e00520072008102e21090b2009450d1d200320083602e405200320093602e00520032d00d004210820032802e80521070b2003200741016a3602e805200920076a20083a00000b200341d0036a41086a200341e0056a10a30220032802e40521072002ad428080808080088420033502e80542208620032802e0052208ad84100102402007450d002008102c0b2002102c200342e4cab5fbb6ccdcb0e3003703d005200341d0056a200341a0026a417f10bd01200341d0036a41086a41083a0000200341d9036a20032903a002370000200341e1036a200341a0026a41086a290300370000200341e9036a200341a0026a41106a290300370000200341f1036a200341a0026a41186a290300370000200341f9036a20032903a00137000020034181046a200341a0016a41086a29030037000020034189046a200341a0016a41106a29030037000020034191046a200341a0016a41186a290300370000200341063a00d003410021084101210941014100200341d0036a109201410121160c1a0b20034188036a41186a200141196a29000037030020034188036a41106a200141116a29000037030020034188036a41086a200141096a29000037030020032001290001370388032002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d00012119200320063703d00341002102201941ff01714101460d010b410121024100211741022118410021160b200320063703d801200320073a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320133a00c701200320143a00c201200320153b01c0012003201741ffff0371410874201841ff01717220164118747222093600c30102402002450d0041d6b2c0002108410f210720090e050805060718080b20034188056a41186a200341c0016a41186a29030037030020034188056a41106a200341c0016a41106a29030037030020034188056a41086a200341c0016a41086a290300370300200320032903c00137038805200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a2002290300370300200320032903d0043703800220024188fbc400ad4280808080d000841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a2002290300370300200320032903d00437039002200341e0016a20034188036a109f0141c000102a2202450d1a2002200329038002370000200241086a20034180026a41086a2903003700002002200329039002370010200241186a20034190026a41086a290300370000200220032903e001370020200241286a200341e0016a41086a2208290300370000200241306a200341e0016a41106a2209290300370000200241386a200341e0016a41186a2207290300370000200341d0036a200241c00010d3012008200341d9036a2900003703002009200341e1036a2900003703002007200341e9036a290000370300200320032900d1033703e001410121090240024020032d00d0034101460d00410021160c010b200341a2016a20032d00e2013a0000200341a0026a41086a200341f3016a290000370300200341ad026a2007290000370000200320032f01e0013b01a001200320032900eb013703a0024101211620032800e701210720032800e30121080b2002102c0240024020160d00410b210741cb96c50021080c010b200341d0056a41026a200341a0016a41026a2d00003a0000200341c0026a41086a200341a0026a41086a290300370300200341c0026a410d6a200341a0026a410d6a290000370000200320032f01a0013b01d005200320032903a0023703c002410021090b200341d0066a41026a2202200341d0056a41026a2d00003a0000200341e8046a41086a2216200341c0026a41086a290300370300200341e8046a41106a200341c0026a41106a290300370300200320032f01d0053b01d006200320032903c0023703e80420090d17200341f3056a2016290300370000200341e0056a41186a200341f5046a290000370000200320032f01d0063b01e005200320073600e705200320083600e305200320032903e8043700eb05200320022d00003a00e2050240200341e0056a20034188056a412010dd05450d0041d698c5002108410b2107410121090c190b200341d0036a41186a20034188036a41186a290300370300200341d0036a41106a20034188036a41106a290300370300200341d0036a41086a20034188036a41086a29030037030020032003290388033703d003200341d0036a10e404410021080c160b2002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d00012119200320063703d00341002102201941ff01714101460d010b410121024100211741022118410021160b200320063703f801200320073a00f701200320083a00f601200320093b01f4012003200a3a00f3012003200b3a00f2012003200c3b01f0012003200d3a00ef012003200e3a00ee012003200f3b01ec01200320103a00eb01200320113a00ea01200320123b01e801200320133a00e701200320143a00e201200320153b01e0012003201741ffff0371410874201841ff01717220164118747222093600e3012002450d0141d6b2c0002108410f210720090e050003040516000b20032800e701210820032800eb012107410121090c160b200341c0016a41186a200341e0016a41186a2903002206370300200341c0016a41106a200341e0016a41106a2903002204370300200341c0016a41086a200341e0016a41086a2903002205370300200320032903e001221a3703c001200341d0036a41186a2006370300200341d0036a41106a2004370300200341d0036a41086a20053703002003201a3703d003200341d0036a10e4040c0d0b20034188056a41186a200141196a29000037030020034188056a41106a200141116a29000037030020034188056a41086a200141096a29000037030020032001290001370388052002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d00200320063702d403200320073a00d303200320083a00d203200320093b01d0030c010b200241086a2d00002116200241066a2f01002117200241056a2d0000211820022d00012119200320063703d00341002102201941ff01714101460d010b410121024100211741022118410021160b200320063703d801200320073a00d701200320083a00d601200320093b01d4012003200a3a00d3012003200b3a00d2012003200c3b01d0012003200d3a00cf012003200e3a00ce012003200f3b01cc01200320103a00cb01200320113a00ca01200320123b01c801200320133a00c701200320143a00c201200320153b01c0012003201741ffff0371410874201841ff01717220164118747222093600c30102402002450d0041d6b2c0002108410f210720090e050401020314040b20034188036a41186a200341c0016a41186a29030037030020034188036a41106a200341c0016a41106a29030037030020034188036a41086a200341c0016a41086a290300370300200320032903c00137038803200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20034180026a41086a2002290300370300200320032903d0043703800220024188fbc400ad4280808080d000841002220741086a290000370300200320072900003703d0042007102c20034190026a41086a2002290300370300200320032903d00437039002200341e0016a20034188056a109f0141c000102a2202450d162002200329038002370000200241086a20034180026a41086a22082903003700002002200329039002370010200241186a20034190026a41086a2209290300370000200220032903e001370020200241286a200341e0016a41086a290300370000200241306a200341e0016a41106a290300370000200241386a200341e0016a41186a290300370000200341c8006a200241c000410141004100109701200328024821072002102c024020074101470d0041c798c5002108410f2107410121090c150b200341e0056a41186a20034188036a41186a290300370300200341e0056a41106a20034188036a41106a290300370300200341e0056a41086a20034188036a41086a29030037030020032003290388033703e005200341d0036a41186a20034188056a41186a290300370300200341d0036a41106a20034188056a41106a290300370300200341d0036a41086a20034188056a41086a29030037030020032003290388053703d003200341d0046a41086a220241bad6c500ad42808080809001841002220741086a290000370300200320072900003703d0042007102c20082002290300370300200320032903d0043703800220024188fbc400ad4280808080d000841002220741086a290000370300200320072900003703d0042007102c20092002290300370300200320032903d00437039002200341e0016a200341d0036a109f0141c000102a2202450d162002200329038002370000200241086a20034180026a41086a2903003700002002200329039002370010200241186a20034190026a41086a290300370000200220032903e001370020200241286a200341e0016a41086a290300370000200241306a200341e0016a41106a290300370000200241386a200341e0016a41186a290300370000200341c0003602d403200320023602d003200341e0056a200341d0036a10a1022002102c410021080c120b41dd8cc6002108410e2107410121090c130b41c3b2c000210841132107410121090c120b41b2b2c000210841112107410121090c110b20032800c701210820032800cb012107410121090c100b410121160c100b41a8b4c000200820161038000b41b2b2c0002108411121070c0d0b200341d0036a41186a20034188056a41186a290300370300200341d0036a41106a20034188056a41106a290300370300200341d0036a41086a20034188056a41086a29030037030020032003290388053703d003200341d0036a2108410021160b024002402007200a460d002018210a0c010b024020182007460d002018210a0c010b201841016a22022018490d0f2018410174220a2002200a20024b1b220a41ffffff3f71200a470d0f200a41057422024100480d0f0240024020180d002002102a21170c010b201720184105742002102e21170b2017450d0e0b201720164105746a220241206a2002200720166b41057410dc051a200241186a200841186a290000370000200241106a200841106a290000370000200241086a200841086a29000037000020022008290000370000200341d0036a41186a4200370300200341d0036a41106a22184200370300200341d0036a41086a22084200370300200342003703d003200341d0046a41086a22024191b0c200ad4280808080e000841002221641086a290000370300200320162900003703d0042016102c20082002290300370300200320032903d0043703d003200241acb0c200ad4280808080e000841002221641086a290000370300200320162900003703d0042016102c201820032903d0042206370300200341e0056a41086a2008290300370300200341e0056a41106a2006370300200341e0056a41186a2002290300370300200320063703e001200320032903d0033703e005200341c0006a200341e0056a41201094012003280240211620032802442118200241bad6c500ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20034180026a41086a220b2002290300370300200320032903d00437038002200241bcfcc400ad42808080809001841002220841086a290000370300200320082900003703d0042008102c20034190026a41086a220c2002290300370300200320032903d00437039002200341e0016a200341c0026a109f0141c000102a2208450d0d2008200329038002370000200841086a200b2903003700002008200329039002370010200841186a200c290300370000200820032903e001370020200841286a200341e0016a41086a290300370000200841306a200341e0016a41106a290300370000200841386a200341e0016a41186a2903003700004104102a2202450d0d20034284808080c0003702d403200320023602d0032002201841809c316a41809c3120161b2216360000200741016a2202200341d0036a106702402002450d00200741057441206a21072017210203402002200341d0036a109101200241206a2102200741606a22070d000b0b20032802d40321022008ad428080808080088420033502d80342208620032802d0032207ad84100102402002450d002007102c0b2008102c0240200a450d002017102c0b200341d0036a41086a410a3a0000200341d9036a200329038805370000200341f9036a20032903c002370000200341e1036a20034188056a41086a290300370000200341e9036a20034188056a41106a290300370000200341f1036a20034188056a41186a29030037000020034181046a200341c0026a41086a29030037000020034189046a200341c0026a41106a29030037000020034191046a200341c0026a41186a290300370000200341063a00d0032003419c046a20163602004100210841014100200341d0036a109201200341e0016a41186a22174200370300200341e0016a41106a22184200370300200341e0016a41086a22074200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002221641086a290000370300200320162900003703d0042016102c20072002290300370300200320032903d004220637038002200320063703e00120024184c6c400ad4280808080c001841002221641086a290000370300200320162900003703d0042016102c20034190026a41086a20022903002206370300200320032903d00422043703900220092004370000200941086a2006370000200341c0016a41086a2007290300370300200341c0016a41106a2018290300370300200341c0016a41186a2017290300370300200320032903e0013703c001200341c0016aad428080808080048410050c090b410021080b410e2107410121090c090b41222107410121090c080b4100210841012109410121160c080b41b196c5002108411a21072002450d052009102c410121090c060b20032802a802210820032802a402210920032802a00221020b2002450d00201a2008ad4220862002ad8410012009450d012002102c0c010b200341e0016a41186a22174200370300200341e0016a41106a22184200370300200341e0016a41086a22084200370300200342003703e001200341d0046a41086a220241bad6c500ad42808080809001841002220941086a290000370300200320092900003703d0042009102c20082002290300370300200320032903d004220637038002200320063703e001200241d5c5c400ad4280808080b001841002220941086a290000370300200320092900003703d0042009102c20034190026a41086a20022903002206370300200320032903d004221b370390022007201b370000200741086a2006370000200341c0016a41086a2008290300370300200341c0016a41106a2018290300370300200341c0016a41186a2017290300370300200320032903e0013703c001200341003602d803200342013703d0034101200341d0036a106720032802d005220828020021090240024020032802d403220720032802d80322026b4104490d0020032802d00321070c010b200241046a22172002490d07200741017422022017200220174b1b22024100480d070240024020070d002002102a21070c010b20032802d00320072002102e21070b2007450d06200320023602d403200320073602d00320032802d80321020b2003200241046a3602d803200720026a20093600002003200341d0036a36028803200841046a20034188036a109402200841246a200341d0036a10910120032802d4032102201a20033502d80342208620032802d0032207ad8410012002450d002007102c0b200341e8036a2004370300200341e0036a2005370300200341dc036a201636020041002108200341d8036a41003a0000200341063a00d00341014100200341d0036a1092010b0b410121090b410121160b20012d0000221741736a220241074b0d0220020e080502050502020403050b1033000b1035000b2017416d6a220241014b0d020240024020020e020001000b200141086a280200450d03200141046a280200102c0c030b200141086a280200450d02200141046a280200102c0c020b2016450d01200141086a280200450d01200141046a280200102c0c010b2009450d00200141086a280200450d00200141046a280200102c0b2000200736020420002008360200200341e0066a24000b860501087f230041a0016b22022400200241086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703002004102c20024180016a41086a220520032903003703002002200229030037038001200341d9f8c200ad4280808080e000841002220441086a290000370300200220042900003703002004102c200241d0006a41086a220620032903003703002002200229030037035020022001109f01024041c000102a2204450d0020042002290380013700002004200229035037001020042002290000370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241106a2201290000370000200441386a200241186a22072900003700002002200441c00010e6032005200329030037030020024180016a41106a2205200129030037030020024180016a41186a2201200729030037030020062002412c6a290200370300200241d0006a41106a2206200241346a290200370300200241d0006a41186a22072002413c6a290200370300200241f0006a2208200241c4006a290200370300200241d0006a41286a2209200241cc006a280200360200200220022903003703800120022002290224370350024020022802202203450d00200020022903800137030020002002290350370224200041186a2001290300370300200041106a2005290300370300200041086a20024180016a41086a2903003703002000412c6a200241d0006a41086a290300370200200041346a20062903003702002000413c6a2007290300370200200041c4006a2008290300370200200041cc006a20092802003602000b200020033602202004102c200241a0016a24000f0b1033000b85c70105017f027e157f077e017f230041c0056b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e1100010203060708090a0b0c0d0e0f101112000b200341b4046a4101360200200342013702a404200341fcc4c5003602a0042003410436028c02200341f4c4c50036028802200320034188026a3602b004200341a0046a4184c5c5001041000b200141306a2903002104200141286a290300210520012d00012106200341e0026a41026a200141076a2d00003a0000200341d8036a41086a200141146a290200370300200341d8036a41106a2001411c6a290200370300200341d8036a41186a200141246a2802003602002003200141056a2f00003b01e00220032001410c6a2902003703d8030240024020022d00000d0020022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c220b200141046a2d00002107200141086a2802002108200241196a2d00002109200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211a20032002411a6a2901003703d001200320093a00cf012003200a3a00ce012003200b3b01cc012003200c3a00cb012003200d3a00ca012003200e3b01c8012003200f3a00c701200320103a00c601200320113b01c401200320123a00c301200320193a00ba012003201a3b01b801200320152014410874722013411874723600bf01200320182017410874722016411874723600bb01200341c0036a41086a22024196e0c500ad4280808080f000841002220941086a290000370300200320092900003703c0032009102c20034188016a41086a220a2002290300370300200320032903c00337038801200241d3f8c200ad4280808080e000841002220941086a290000370300200320092900003703c0032009102c20034188026a41086a22092002290300370300200320032903c00337038802200341f8046a200341b8016a109f0141c000102a2202450d232002200329038801370000200241086a200a2903003700002002200329038802370010200241186a2009290300370000200220032903f804370020200241286a200341f8046a41086a290300370000200241306a200341f8046a41106a290300370000200241386a200341f8046a41186a29030037000041012109200341206a200241c0004101410041001097012003280220210a2002102c200a4101460d11200341c0036a41026a2202200341e0026a41026a2d00003a0000200341a0046a41086a2209200341d8036a41086a290300370300200341a0046a41106a200341d8036a41106a290300370300200341a0046a41186a220a200341d8036a41186a280200360200200320032f01e0023b01c003200320032903d8033703a0040240200741ff01714101460d00200341a8016a41026a20022d00003a0000200341f8046a41086a2009290300370300200341f8046a41106a200341a0046a41106a290300370300200341f8046a41186a200a2d00003a0000200320032f01c0033b01a801200320032903a0043703f8040c1e0b200341a0036a200841067610910220032802a00321090240024020032802a8032008413f7122024b0d00410021020c010b200341a8016a41026a200920024105746a220241026a2d00003a000020034180056a2002410f6a29000037030020034188056a200241176a29000037030020034190056a2002411f6a2d00003a0000200320022f00003b01a801200320022900073703f80420022800032108410121020b024020032802a403450d002009102c0b20020d1d410121020c1e0b0240024020022d00000d0020022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c210b200141106a2903002104200141086a2903002105200241196a2d00002109200241186a2d00002106200241166a2f01002108200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f0100211820032002411a6a29010037039005200320093a008f05200320063a008e05200320083b018c052003200a3a008b052003200b3a008a052003200c3b0188052003200d3a0087052003200e3a0086052003200f3b018405200320103a008305200320173a00fa04200320183b01f804200320132012410874722011411874723600ff04200320162015410874722014411874723600fb04200341a0046a200341f8046a109804024020032d00a0044101460d00200041033602000c210b200341d8036a41086a200341a0046a41186a290300221b370300200341d8036a41106a2209200341c0046a2d000022023a00002003200341a0046a41106a290300221c3703d803200320032802a4043600bb01200320032d00a3043a00ba01200320032f00a1043b01b8012003200341a0046a41086a2903003700bf01200341d7016a20023a0000200341cf016a201b3700002003201c3700c701200341a0046a200341b8016a10f9020240024020032802c00422080d00410121060c010b20034188046a200341db046a29000037030020034180046a41106a200341e3046a29000037030020034180046a41186a200341eb046a2d00003a0000200320032900d304370380042003200341cc046a2f01003b01e0022003200341ce046a2d00003a00e202200341a0046a41186a290300211d200341c8046a280200210a200341cf046a280000210b20032903b004211c20032802c404210220032903a804211e20032903a004211b200341ec046a280200210c410021060b200341d8036a41086a220d20034180046a41086a290300370300200920034180046a41106a290300370300200341d8036a41186a220920034180046a41186a2d00003a0000200320032f01e0023b01a003200320032d00e2023a00a20320032003290380043703d80320060d0120034188026a41186a201d370300200341b0026a200a360200200341ac026a2002360200200341b6026a20032d00a2033a0000200341b7026a200b360000200341bb026a20032903d803370000200341c3026a200d290300370000200341cb026a200341e8036a290300370000200341d3026a20092d00003a00002003201c37039802200320083602a8022003201e370390022003201b37038802200320032f01a0033b01b4022003200c3602d402200341286a200341f8046a10b70102402003290328221b200329038802221f7d2220201b56200341286a41086a290300221e20032903900222217d201b201f54ad7d221b201e56201b201e511b0d002003200520202020200556201b200456201b2004511b22021b2205201c7c221c37039802200341a0026a2004201b20021b2204201d7c201c200554ad7c37030020032005201f7c221b370388022003200420217c201b200554ad7c37039002200341b8016a20034188026a10990420032802ac0221020b02402002450d0020032802a802102c0b2000410c3602000c200b0240024020022d00000d004101210920022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c200b200141106a290300211c200141086a290300211d200241196a2d00002106200241186a2d00002108200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920032002411a6a2901003703d001200320063a00cf01200320083a00ce012003200a3b01cc012003200b3a00cb012003200c3a00ca012003200d3b01c8012003200e3a00c7012003200f3a00c601200320103b01c401200320113a00c301200320183a00ba01200320193b01b801200320142013410874722012411874723600bf01200320172016410874722015411874723600bb01200341a0046a200341b8016a10f9020240024020032802c00422080d000c010b20034180046a41086a200341db046a29000037030020034190046a200341e3046a29000037030020034180046a41186a200341eb046a2d00003a0000200320032900d304370380042003200341cc046a2f01003b01e0022003200341ce046a2d00003a00e202200341a0046a41186a2903002104200341c8046a2802002106200341cf046a280000210a20032903b004210520032802c404210220032903a804211e20032903a004211b200341ec046a280200210b410021090b200341f8046a41086a20034180046a41086a290300370300200341f8046a41106a220c20034180046a41106a290300370300200341f8046a41186a20034180046a41186a2d00003a0000200320032f01e0023b01d803200320032d00e2023a00da0320032003290380043703f8042009450d012000201b370204200041023602000c1f0b2000201b370204200041023602000c1e0b20034188026a41186a2004370300200341b0026a2006360200200341ac026a2002360200200341b6026a20032d00da033a0000200341b7026a200a360000200341bb026a20032903f804370000200341c3026a20034180056a290300370000200341cb026a200c290300370000200341d3026a200341f8046a41186a2d00003a00002003200537039802200320083602a8022003201e370390022003201b37038802200320032f01d8033b01b4022003200b3602d40202400240024002402006411f4b0d002005201d2005201d542004201c542004201c511b22091b221b2004201c20091b221c84500d0320034188026a41186a42002004201c7d2005201b54ad7d221d2005201b7d221e428080e983b1de16544100201d501b22091b37030020034200201e20091b37039802200341a0046a41186a4200370300200341a0046a41106a220d4200370300200341a0046a41086a220b4200370300200342003703a004200341c0036a41086a220a4196e0c500ad4280808080f000841002220c41086a2900003703002003200c2900003703c003200c102c200b200a290300370300200320032903c003221d3703a8012003201d3703a004200a419de0c500ad4280808080a001841002220c41086a2900003703002003200c2900003703c003200c102c200d20032903c003221d370300200341f8046a41086a200b290300370300200341f8046a41106a201d370300200341f8046a41186a200a2903003703002003201d37038004200320032903a0043703f804200341386a200341f8046a4120109401200328023c210a2003280238210b20062002470d02200241016a22062002490d1c2002410174220c2006200c20064b1b220cad42187e221d422088a70d1c201da7220641004e0d010c1c0b2000410b3602002002450d202008102c0c200b0240024020020d002006102a21080c010b2008200241186c2006102e21080b2008450d212003200c3602ac02200320083602a80220032802b00221060b2008200641186c6a22022004201c20091b37030820022005201b20091b3703002002200a41a0056a41a005200b1b360210200320032802b00241016a3602b002200341b8016a20034188026a10990420032802ac0221020b02402002450d0020032802a802102c0b2000410c3602000c1d0b0240024020022d00000d004101210920022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c1d0b200241196a2d00002106200241186a2d00002108200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920032002411a6a2901003703f003200320063a00ef03200320083a00ee032003200a3b01ec032003200b3a00eb032003200c3a00ea032003200d3b01e8032003200e3a00e7032003200f3a00e603200320103b01e403200320113a00e303200320183a00da03200320193b01d803200320142013410874722012411874723600df03200320172016410874722015411874723600db03200341a0046a200341d8036a10f9020240024020032802c004220b0d004200211b420021040c010b20034180046a41086a200341db046a29000037030020034190046a200341e3046a29000037030020034180046a41186a200341eb046a2d00003a0000200320032900d304370380042003200341cc046a2f01003b01e0022003200341ce046a2d00003a00e202200341a0046a41186a290300211e200341cf046a280000210f200341c8046a280200210d20032903a80421044200211b20032903b004211d4100210920032802c404210e20032903a00421050b20034188026a41086a20034180046a41086a29030037030020034188026a41106a220220034180046a41106a29030037030020034188026a41186a20034180046a41186a2d00003a0000200320032f01e0023b01b801200320032d00e2023a00ba0120032003290380043703880202400240024020090d004108210c20034188016a41086a20034188026a41086a29030037030020034188016a41106a200229030037030020034188016a41186a20034188026a41186a2d00003a0000200320032d00ba013a00be05200320032f01b8013b01bc05200320032903880237038801200341a0046a41186a4200370300200341a0046a41106a22084200370300200341a0046a41086a22094200370300200342003703a004200341c0036a41086a22024196e0c500ad4280808080f000841002220641086a290000370300200320062900003703c0032006102c20092002290300370300200320032903c003221c3703a8012003201c3703a0042002419de0c500ad4280808080a001841002220641086a290000370300200320062900003703c0032006102c200820032903c003221c370300200341f8046a41086a2009290300370300200341f8046a41106a201c370300200341f8046a41186a20022903003703002003201c37038004200320032903a0043703f804200341c8006a200341f8046a4120109401201b2005842105024002400240200d41186c2202450d0041002109200328024c410020032802481b2108200b20026a210a0340200b20096a2202290300211b200241086a290300211c2008200241106a2802002206490d0242002004201c7d2005201b54ad7d221c2005201b7d221b200556201c200456201c2004511b22061b21044200201b20061b2105200941186a2109200241186a200a470d000b0b410021060240200e0d004100210d0c020b200b102c4100210d0c010b4118102a220c450d22200c201b370300200c2006360210200c201c37030802400240200d41186c41686a2009470d00410121064101210d0c010b200241186a2110200d41186c200b6a41686a2112410121064101210d03402010210202400340200241086a290300211c2002290300211b2008200241106a2802002209490d0142002004201c7d2005201b54ad7d221c2005201b7d221b200556201c200456201c2004511b22091b21044200201b20091b2105200241186a2202200a470d000c030b0b0240200d2006470d00200641016a220d2006490d1e20064101742210200d2010200d4b1b220dad42187e221f422088a70d1e201fa722104100480d1e0240024020060d002010102a210c0c010b200c200641186c2010102e210c0b200c450d250b200241186a2110200c200641186c6a2211201c3703082011201b37030020112009360210200641016a210620122002470d000b0b200e450d00200b102c0b200341ce046a20032d00be053a0000200341cf046a200f360000200341d3046a200329038801370000200341c8046a2006360200200341c4046a200d3602002003201d3703b004200341a0046a41186a201e370300200341db046a20034190016a290300370000200341e3046a20034198016a290300370000200341eb046a20034188016a41186a2d00003a0000200320053703a004200320032f01bc053b01cc042003200c3602c004200320043703a8040240201d201e844200520d002006450d020b200341d8036a200341a0046a1099040c020b20002005370204200041023602000c1e0b200341f8046a41186a200341cc046a220241186a290000370300200341f8046a41106a200241106a290000370300200341f8046a41086a200241086a290000370300200342f3e885db96cddbb3203703a003200320022900003703f80420034188026a41186a420037030020034188026a41106a2208420037030020034188026a41086a220242003703002003420037038802200341c0036a41086a22094191b0c200ad4280808080e000841002220641086a290000370300200320062900003703c0032006102c20022009290300370300200320032903c00337038802200941acb0c200ad4280808080e000841002220641086a290000370300200320062900003703c0032006102c200820032903c0032204370300200341b8016a41086a22062002290300370300200341b8016a41106a2004370300200341b8016a41186a2009290300370300200320043703800420032003290388023703b801200341c0006a200341b8016a412010940120032003280244410020032802401b3602800420034188026a200341f8046a10ae01200328028c0221082003280288022109200328029002210a2003419c026a200341a0036a36020020032009200a4105746a3602940220032009360290022003200836028c022003200936028802200320034180046a36029802200341b8016a20034188026a10860120022006280200360200200320032903b80137038802200341f8046a20034188026a10b001200341f8046a10a4010b024020032802c404450d0020032802c004102c0b2000410c3602000c1c0b200141046a280200210910a3010240024020022d00000d004101210620022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c1c0b200241196a2d00002108200241186a2d0000210a200241166a2f0100210b200241156a2d0000210c200241146a2d0000210d200241126a2f0100210e200241116a2d0000210f200241106a2d000021102002410e6a2f010021112002410d6a2d000021122002410c6a2d000021132002410a6a2f01002114200241096a2d00002115200241086a2d00002116200241066a2f01002117200241056a2d00002118200241046a2d00002119200241026a2f0100211a20032002411a6a29010037039803200320083a0097032003200a3a0096032003200b3b0194032003200c3a0093032003200d3a0092032003200e3b0190032003200f3a008f03200320103a008e03200320113b018c03200320123a008b03200320193a0082032003201a3b01800320032015201441087472201341187472360087032003201820174108747220164118747236008303200341a0046a20034180036a10f9020240024020032802c00422020d000c010b20034180046a41086a200341db046a29000037030020034190046a200341e3046a29000037030020034180046a41186a200341eb046a2d00003a0000200320032900d304370380042003200341cc046a2f01003b01e0022003200341ce046a2d00003a00e202200341a0046a41186a290300211c200341c8046a280200210a200341cf046a280000210b20032903b004211b20032802c404210820032903a804210520032903a0042104200341ec046a280200210c410021060b200341b8016a41086a20034180046a41086a290300370300200341b8016a41106a220d20034180046a41106a290300370300200341b8016a41186a20034180046a41186a2d00003a0000200320032f01e0023b01f804200320032d00e2023a00fa0420032003290380043703b801024020060d0020034188026a41186a201c37030020034188026a41286a200a360200200341ac026a2008360200200341b6026a20032d00fa043a0000200341b7026a200b360000200341bb026a20032903b801370000200341c3026a200341b8016a41086a290300370000200341cb026a200d290300370000200341d3026a200341b8016a41186a2d00003a00002003201b37039802200320023602a80220032005370390022003200437038802200320032f01f8043b01b4022003200c3602d402200341b4026a2208108704200341c0036a41086a22024196e0c500ad4280808080f000841002220641086a290000370300200320062900003703c0032006102c200341a8016a41086a220a2002290300370300200320032903c0033703a801200241c9f8c200ad4280808080a001841002220641086a290000370300200320062900003703c0032006102c20034180046a41086a22062002290300370300200320032903c00337038004200341a0046a2008109f0141c000102a2202450d1e200220032903a801370000200241086a200a2903003700002002200329038004370010200241186a2006290300370000200220032903a004370020200241286a200341a0046a41086a290300370000200241306a200341a0046a41106a290300370000200241386a200341a0046a41186a290300370000200341b8016a200241c00010f203024020032d00bc0122064102470d00200320083602bc05200341a0046a108a04200341d8036a20032802a004220620032802a80410d301024020032802a404450d002006102c0b024020032d00d8030d00200341a0046a108a0420032802a0042106200320032802a8043602fc04200320063602f8042008200341f8046a10a10220032802a404450d172006102c0c170b20034198046a200341f1036a29000037030020034190046a200341e9036a29000037030020034180046a41086a200341e1036a290000370300200320032900d90337038004200341e8006a20034180046a108904200341a0046a200328026822062003280270220810f203024020032d00a4044102470d00200341003602e802200342013703e002200341a0036a41146a410d360200200341ac036a410b360200200341073602c40320034196e0c5003602c0032003410b3602a4032003410a36028c01200341c9f8c200360288012003200341e8006a3602b003200320034188016a3602a8032003200341c0036a3602a0032003200341e0026a3602a801200341f8046a41146a4103360200200342033702fc04200341c09dc5003602f8042003200341a0036a36028805200341a8016a41c49ac500200341f8046a10391a20033502e80242208620033502e00284100420032802bc052108200341f8046a108a0420032802f804210620032003280280053602a403200320063602a0032008200341a0036a10a102024020032802fc04450d002006102c0b024020032802e402450d0020032802e002102c0b200328026c450d172003280268102c0c170b20032802a004210a200341f8046a200341a0046a41047241c20010db051a200341e0026a41086a2003419a056a410020032d0099054101461b3602002003200a3602e0022003200341bc056a3602e402200341003602a803200342013703a003200341e0026a200341a0036a108901200341e0026a410472200341a0036a10a20220032802a403210a2008ad4220862006ad8420033502a80342208620032802a0032206ad8410010240200a450d002006102c0b0240200328026c450d002003280268102c0b20032802bc052108200341a0046a108a0420032802a0042106200320032802a8043602fc04200320063602f8042008200341f8046a10a102024020032802a404450d002006102c0b200341a0036a41086a20034180046a41086a290300370300200341a0036a41106a20034180046a41106a290300370300200341a0036a41186a20034180046a41186a29030037030020032003290380043703a00341012108410021060c170b200341f8046a41186a200341d5016a290000370300200341f8046a41106a200341cd016a290000370300200341f8046a41086a200341c5016a290000370300200341a0036a41086a200341e6016a290100370300200341a0036a41106a200341ee016a290100370300200341a0036a41186a200341f6016a290100370300200320032900bd013703f8042003200341de016a2901003703a003200341dd016a2d000021080c160b20002004370204200041023602000c1b0b2001410c6a2802002109200141086a2802002108200141046a280200210a10a3010240024020022d00000d004101210620022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c120b200241196a2d0000210b200241186a2d0000210c200241166a2f0100210d200241156a2d0000210e200241146a2d0000210f200241126a2f01002110200241116a2d00002111200241106a2d000021122002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002116200241096a2d00002117200241086a2d00002118200241066a2f01002119200241056a2d0000211a200241046a2d00002107200241026a2f0100212220032002411a6a290100370398032003200b3a0097032003200c3a0096032003200d3b0194032003200e3a0093032003200f3a009203200320103b019003200320113a008f03200320123a008e03200320133b018c03200320143a008b03200320073a008203200320223b01800320032017201641087472201541187472360087032003201a20194108747220184118747236008303200341a0046a20034180036a10f9020240024020032802c004220b0d000c010b20034180046a41086a200341db046a29000037030020034190046a200341e3046a29000037030020034180046a41186a200341eb046a2d00003a0000200320032900d304370380042003200341cc046a2f01003b01e0022003200341ce046a2d00003a00e202200341a0046a41186a290300211c200341c8046a280200210c200341cf046a280000210d20032903b004211b20032802c404210220032903a804210520032903a0042104200341ec046a280200210e410021060b20034188026a41086a20034180046a41086a29030037030020034188026a41106a220f20034180046a41106a29030037030020034188026a41186a20034180046a41186a2d00003a0000200320032f01e0023b01f804200320032d00e2023a00fa0420032003290380043703880202400240024020060d00200341b8016a41186a201c370300200341e0016a200c360200200341b8016a41246a2002360200200341e6016a20032d00fa043a0000200341e7016a200d360000200341eb016a200329038802370000200341f3016a20034190026a290300370000200341fb016a200f29030037000020034183026a20034188026a41186a2d00003a00002003201b3703c8012003200b3602d801200320053703c001200320043703b801200320032f01f8043b01e4012003200e3602840202402009450d00200341003a008004200341103602e8032003200a200941246c6a3602e4032003200a3602e003200320083602dc032003200a3602d803200320034180046a3602ec03200341a0046a200341d8036a10a8020240024020032d00a0044101460d0020032802e403210620032802e003210202400340024020062002470d00200221080c020b20022d00002109200241246a2208210220094102470d000b0b200320083602e0034100210c4101210b024020032802dc030d00410021020c020b20032802d803102c410021020c010b4120102a220b450d21200b20032900a104370000200b41186a200341b9046a290000370000200b41106a200341b1046a290000370000200b41086a200341a9046a290000370000200341f8046a41106a200341d8036a41106a290300370300200341f8046a41086a200341d8036a41086a290300370300200320032903d8033703f804200341a0046a200341f8046a10a8020240024020032d00a0040d00410121024101210c0c010b200341a0046a41017221094102210a41202108410121024101210c034020034188026a41186a220d200941186a29000037030020034188026a41106a220e200941106a29000037030020034188026a41086a220f200941086a290000370300200320092900003703880202402002200c470d00200241016a22062002490d1d200a2006200a20064b1b220c41ffffff3f71200c470d1d200c41057422064100480d1d0240024020020d002006102a210b0c010b200b20082006102e210b0b200b450d240b200b20086a2206200329038802370000200641186a200d290300370000200641106a200e290300370000200641086a200f290300370000200a41026a210a200841206a2108200241016a2102200341a0046a200341f8046a10a80220032d00a0040d000b0b2003280284052108200328028005210902400340024020082009470d002009210a0c020b20092d00002106200941246a220a210920064102470d000b0b2003200a3602800520032802fc04450d0020032802f804102c0b20032d008004450d02200c450d03200b102c0c030b200041073602002002450d14200b102c0c140b20002004370204200041023602000c130b200b0d100b410121062000410136020020032802dc01450d1020032802d801102c0c100b0240024020022d00000d004101210920022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c1a0b200241196a2d00002106200241186a2d00002108200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920032002411a6a2901003703d001200320063a00cf01200320083a00ce012003200a3b01cc012003200b3a00cb012003200c3a00ca012003200d3b01c8012003200e3a00c7012003200f3a00c601200320103b01c401200320113a00c301200320183a00ba01200320193b01b801200320142013410874722012411874723600bf01200320172016410874722015411874723600bb01200341a0046a200341b8016a10f9020240024020032802c00422020d000c010b20034180046a41086a200341db046a29000037030020034190046a200341e3046a29000037030020034180046a41186a200341eb046a2d00003a0000200320032900d304370380042003200341cc046a2f01003b01e0022003200341ce046a2d00003a00e202200341a0046a41186a290300211c200341c8046a2802002108200341cf046a280000210a20032903b004211b20032802c404210620032903a804210520032903a0042104200341ec046a280200210b410021090b200341f8046a41086a20034180046a41086a290300370300200341f8046a41106a220c20034180046a41106a290300370300200341f8046a41186a20034180046a41186a2d00003a0000200320032f01e0023b01d803200320032d00e2023a00da0320032003290380043703f804024020090d0020034188026a41186a201c370300200341b0026a2008360200200341ac026a22092006360200200341b6026a20032d00da033a0000200341b7026a200a360000200341bb026a20032903f804370000200341c3026a20034180056a290300370000200341cb026a200c290300370000200341d3026a200341f8046a41186a2d00003a00002003201b37039802200320023602a80220032005370390022003200437038802200320032f01d8033b01b4022003200b3602d402200341b4026a2202108604200210870402402009280200450d0020032802a802102c0b2000410c3602000c1a0b20002004370204200041023602000c190b0240024020022d00000d004101210920022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c190b20012d0001211a200241196a2d00002106200241186a2d00002108200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920032002411a6a2901003703d001200320063a00cf01200320083a00ce012003200a3b01cc012003200b3a00cb012003200c3a00ca012003200d3b01c8012003200e3a00c7012003200f3a00c601200320103b01c401200320113a00c301200320183a00ba01200320193b01b801200320142013410874722012411874723600bf01200320172016410874722015411874723600bb01200341a0046a200341b8016a10f9020240024020032802c004220b0d000c010b20034180046a41086a200341db046a29000037030020034190046a200341e3046a29000037030020034180046a41186a200341eb046a2d00003a0000200320032900d304370380042003200341cc046a2f01003b01e0022003200341ce046a2d00003a00e202200341a0046a41186a290300211c200341c8046a2802002106200341cf046a280000210820032903b004211b20032802c404210220032903a804210520032903a0042104200341ec046a280200210a410021090b200341f8046a41086a20034180046a41086a290300370300200341f8046a41106a220c20034180046a41106a290300370300200341f8046a41186a20034180046a41186a2d00003a0000200320032f01e0023b01d803200320032d00e2023a00da0320032003290380043703f804024020090d0020034188026a41186a201c370300200341b0026a2006360200200341ac026a22092002360200200341b6026a20032d00da033a0000200341b7026a2008360000200341bb026a20032903f804370000200341c3026a20034180056a290300370000200341cb026a200c290300370000200341d3026a200341f8046a41186a2d00003a00002003201b370398022003200b3602a80220032005370390022003200437038802200320032f01d8033b01b4022003200a3602d402200341b4026a201a10a90402402009280200450d0020032802a802102c0b2000410c3602000c190b20002004370204200041023602000c180b200341d4036a41026a200141076a2d00003a0000200341e8006a41086a200141146a290200370300200341e8006a41106a2001411c6a290200370300200341e8006a41186a200141246a2802003602002003200141056a2f00003b01d40320032001410c6a2902003703680240024020022d00000d0020022d00014101460d010b200041c3b2c00036020420004100360200200041086a41133602000c180b200141046a2d0000211a200141086a2802002109200241196a2d00002106200241186a2d00002108200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920032002411a6a2901003703f802200320063a00f702200320083a00f6022003200a3b01f4022003200b3a00f3022003200c3a00f2022003200d3b01f0022003200e3a00ef022003200f3a00ee02200320103b01ec02200320113a00eb02200320183a00e202200320193b01e002200320142013410874722012411874723600e702200320172016410874722015411874723600e302200341a0046a200341e0026a109804024020032d00a0044101460d00200041033602000c180b200341d8036a41086a200341a0046a41186a22062903002204370300200341d8036a41106a200341c0046a2d000022083a00002003200341a0046a41106a220229030022053703d803200320032802a40436008303200320032d00a3043a008203200320032f00a1043b0180032003200341a0046a41086a220a290300370087032003419f036a20083a000020034197036a20043700002003200537008f03200341c0036a41026a2208200341d4036a41026a2d00003a0000200320032f01d4033b01c003200a200341e8006a41086a2903003703002002200341e8006a41106a2903003703002006200341e8006a41186a280200360200200320032903683703a0040240201a41ff01714101460d00200341a8016a41026a20082d00003a0000200341f8046a41086a200341a0046a41086a290300370300200341f8046a41106a2002290300370300200341f8046a41186a200341a0046a41186a2d00003a0000200320032f01c0033b01a801200320032903a0043703f8040c0b0b20034188026a20094106761091022003280288022106024002402003280290022009413f7122024b0d00410021020c010b200341a8016a41026a200620024105746a220241026a2d00003a000020034180056a2002410f6a29000037030020034188056a200241176a29000037030020034190056a2002411f6a2d00003a0000200320022f00003b01a801200320022900073703f80420022800032109410121020b0240200328028c02450d002006102c0b20020d0a410121020c0b0b024020022d000120022d000072450d00200041b2b2c00036020420004100360200200041086a41113602000c170b200141046a2802002108200341a0046a41186a4200370300200341a0046a41106a220a4200370300200341a0046a41086a22094200370300200342003703a004200341c0036a41086a22024196e0c500ad4280808080f000841002220641086a290000370300200320062900003703c0032006102c20092002290300370300200320032903c00322043703a801200320043703a004200241f3dfc500ad4280808080e001841002220641086a290000370300200320062900003703c0032006102c200a20032903c0032204370300200341f8046a41086a2009290300370300200341f8046a41106a2004370300200341f8046a41186a20022903003703002003200437038004200320032903a0043703f804200320083602a004200341f8046aad4280808080800484200341a0046aad4280808080c0008410012000410c3602000c160b024020022d000120022d000072450d00200041b2b2c00036020420004100360200200041086a41113602000c160b200341a0046a41186a4200370300200341a0046a41106a22084200370300200341a0046a41086a22094200370300200342003703a004200341c0036a41086a22024196e0c500ad4280808080f000841002220641086a290000370300200320062900003703c0032006102c20092002290300370300200320032903c00322043703a801200320043703a004200241d8e0c500ad42808080808001841002220641086a290000370300200320062900003703c0032006102c200820032903c0032204370300200341f8046a41086a2009290300370300200341f8046a41106a2004370300200341f8046a41186a20022903003703002003200437038004200320032903a0043703f804410121094101102a2202450d17200241023a0000200341f8046aad42808080808004842002ad4280808080108410012002102c2000410c36020041012106410121080c160b024020022d000120022d000072450d00200041b2b2c00036020420004100360200200041086a41113602000c150b200341a0046a41186a4200370300200341a0046a41106a22084200370300200341a0046a41086a22094200370300200342003703a004200341c0036a41086a22024196e0c500ad4280808080f000841002220641086a290000370300200320062900003703c0032006102c20092002290300370300200320032903c00322043703a801200320043703a004200241d8e0c500ad42808080808001841002220641086a290000370300200320062900003703c0032006102c200820032903c0032204370300200341f8046a41086a2009290300370300200341f8046a41106a2004370300200341f8046a41186a20022903003703002003200437038004200320032903a0043703f804410121094101102a2202450d16200241013a0000200341f8046aad42808080808004842002ad4280808080108410012002102c2000410c36020041012106410121080c150b200141086a2802002108200141046a280200210a024020022d000120022d000072450d00200041b2b2c0003602044100210620004100360200200041086a4111360200410121092008450d0c200a102c410121080c150b2001410c6a2802002109200341a0046a41186a4200370300200341a0046a41106a220c4200370300200341a0046a41086a22064200370300200342003703a004200341c0036a41086a22024196e0c500ad4280808080f000841002220b41086a2900003703002003200b2900003703c003200b102c20062002290300370300200320032903c00322043703a801200320043703a004200241dcc1c300ad4280808080d001841002220b41086a2900003703002003200b2900003703c003200b102c200c20032903c0032204370300200341f8046a41086a2006290300370300200341f8046a41106a2004370300200341f8046a41186a20022903003703002003200437038004200320032903a0043703f804200341003602a804200342013703a0042009200341a0046a106702402009450d0020094105742109200a210203402002200341a0046a109101200241206a2102200941606a22090d000b0b20032802a4042102200341f8046aad428080808080048420033502a80442208620032802a0042209ad84100102402002450d002009102c0b02402008450d00200a102c0b2000410c3602004100210641012109410121080c140b200341a0046a41186a200141196a290000370300200341a0046a41106a200141116a290000370300200341a0046a41086a200141096a290000370300200320012900013703a004024020022d000120022d000072450d00200041b2b2c000360204200041086a4111360200200041003602000c130b200342f3e885db96cddbb3203703f80420034188026a41186a420037030020034188026a41106a2208420037030020034188026a41086a220242003703002003420037038802200341c0036a41086a22094191b0c200ad4280808080e000841002220641086a290000370300200320062900003703c0032006102c20022009290300370300200320032903c00337038802200941acb0c200ad4280808080e000841002220641086a290000370300200320062900003703c0032006102c200820032903c0032204370300200341b8016a41086a22062002290300370300200341b8016a41106a2004370300200341b8016a41186a2009290300370300200320043703800420032003290388023703b801200341e0006a200341b8016a412010940120032003280264410020032802601b3602d80320034188026a200341a0046a10ae01200328028c0221082003280288022109200328029002210a2003419c026a200341f8046a36020020032009200a4105746a3602940220032009360290022003200836028c0220032009360288022003200341d8036a36029802200341b8016a20034188026a10860120022006280200360200200320032903b80137038802200341a0046a20034188026a10b001200341a0046a10a4012000410c3602000c120b024020022d000120022d000072450d00200041b2b2c00036020420004100360200200041086a41113602000c120b200341a0046a41186a4200370300200341a0046a41106a22084200370300200341a0046a41086a22094200370300200342003703a004200341c0036a41086a22024196e0c500ad4280808080f000841002220641086a290000370300200320062900003703c0032006102c20092002290300370300200320032903c00322043703a801200320043703a004200241d8e0c500ad42808080808001841002220641086a290000370300200320062900003703c0032006102c200820032903c0032204370300200341f8046a41086a2009290300370300200341f8046a41106a2004370300200341f8046a41186a20022903003703002003200437038004200320032903a0043703f804410121094101102a2202450d13200241033a0000200341f8046aad42808080808004842002ad4280808080108410012002102c2000410c36020041012106410121080c120b200241036a2d0000210820022f0001210a200141106a28020021092001410c6a2802002114200141086a2802002111200141046a28020021150240024020022d0000220b417f6a220641024b0d00024020060e03000102000b200241046a2d00000d00200241086a2802004102742002410c6a28020041036c4f0d010b200b200a2008411074727241ff0171450d002000410636020041002108410121092014450d032011102c0c030b20112009410041202009676b108d03200341c0036a41086a22024196e0c500ad4280808080f000841002220641086a290000370300200320062900003703c0032006102c200341a8016a41086a22082002290300370300200320032903c0033703a801200241d1fdc200ad42808080808002841002220641086a290000370300200320062900003703c0032006102c20034180046a41086a22062002290300370300200320032903c00337038004200320153602b80120034188026a41186a220a200341b8016aad22054280808080c000841006220241186a29000037030020034188026a41106a220b200241106a29000037030020034188026a41086a220c200241086a29000037030020032002290000370388022002102c200341a0046a41186a220d200a290300370300200341a0046a41106a220a200b290300370300200341a0046a41086a220b200c29030037030020032003290388023703a00441c000102a2202450d12200220032903a801370000200241086a20082903003700002002200329038004370010200241186a2006290300370000200220032903a004370020200241286a200b290300370000200241306a200a290300370000200241386a200d290300370000200341a0046a200241c00010e90320032902a404210420032802a00421062002102c2004420020061b21042006410820061b211220094102742213450d0141002109417f210b41002108410021060340024002400240201120096a280200220a20064f0d00410821020c010b2008200a6a22022004422088a7220c490d01410921020b2000200236020002402014450d002011102c0b02402004422088a72200450d00201241306a2102200041d8006c210003400240200241746a280200450d00200241706a280200102c0b02402002280200450d002002417c6a280200102c0b200241d8006a2102200041a87f6a22000d000b0b41002108410121092004a7450d042012102c0c040b2012200241d8006c6a220228022c210f20022802202110200241306a280200210d200241246a280200210e2002200241d8006a200b200c6a200a6b41d8006c10dc051a0240200e450d002010102c0b0240200d450d00200f102c0b200641016a210620044280808080707c2104200b41016a210b2008417f6a21082013200941046a2209470d000c020b0b2000410436020041012106410121080c100b02402014450d002011102c0b200341c0036a41086a22024196e0c500ad4280808080f000841002220941086a290000370300200320092900003703c0032009102c200341a8016a41086a22062002290300370300200320032903c0033703a801200241d1fdc200ad42808080808002841002220941086a290000370300200320092900003703c0032009102c20034180046a41086a22092002290300370300200320032903c00337038004200320153602b80120034188026a41186a220820054280808080c000841006220241186a29000037030020034188026a41106a220a200241106a29000037030020034188026a41086a220b200241086a29000037030020032002290000370388022002102c200341a0046a41186a220c2008290300370300200341a0046a41106a2208200a290300370300200341a0046a41086a220a200b29030037030020032003290388023703a00441c000102a2202450d10200220032903a801370000200241086a20062903003700002002200329038004370010200241186a2009290300370000200220032903a004370020200241286a200a290300370000200241306a2008290300370000200241386a200c290300370000200341a0046a20122004422088a72209109e042002ad428080808080088420033502a80442208620032802a0042206ad841001024020032802a404450d002006102c0b2002102c02402009450d00200941d8006c2109201241306a210203400240200241746a280200450d00200241706a280200102c0b02402002280200450d002002417c6a280200102c0b200241d8006a2102200941a87f6a22090d000b0b02402004a7450d002012102c0b2000410c36020041002108410121090b410121060c0e0b20034188026a41026a200341a8016a41026a2d00003a0000200341a0046a41086a200341f8046a41086a290300370300200341a0046a41106a200341f8046a41106a290300370300200341a0046a41186a200341f8046a41186a2d00003a0000200320032f01a8013b018802200320032903f8043703a004410021020b20034188016a41086a2206200341a0046a41086a29030037030020034188016a41106a2208200341a0046a41106a29030037030020034188016a41186a220a200341a0046a41186a2d00003a0000200320032f0188023b01bc05200320032903a0043703880120032003418a026a2d00003a00be0520020d09200341af036a2006290300370000200341b7036a2008290300370000200341bf036a200a2d00003a0000200320032d00be053a00a203200320032f01bc053b01a003200320093600a30320032003290388013700a703200341c0036a41086a22024196e0c500ad4280808080f000841002220941086a290000370300200320092900003703c0032009102c200341a8016a41086a2002290300370300200320032903c0033703a801200241d9f8c200ad4280808080e000841002220941086a290000370300200320092900003703c0032009102c20034180046a41086a2002290300370300200320032903c00337038004200341a0046a200341a0036a109f0141c000102a2202450d0d200220032903a801370000200241086a200341a8016a41086a2903003700002002200329038004370010200241186a20034180046a41086a290300370000200220032903a004370020200241286a200341a0046a41086a290300370000200241306a200341b0046a290300370000200241386a200341a0046a41186a29030037000041012109200341d8006a200241c000410141004100109701200328025821062002102c0240024020064101460d00200341a0036a20034180036a412010dd05450d01200341e0026a200341a0036a10aa04200341c0036a41086a22024196e0c500ad4280808080f000841002220941086a290000370300200320092900003703c0032009102c20034188016a41086a22062002290300370300200320032903c00337038801200241d9f8c200ad4280808080e000841002220941086a290000370300200320092900003703c0032009102c20034188026a41086a22092002290300370300200320032903c00337038802200341f8046a20034180036a109f0141c000102a2202450d0f2002200329038801370000200241086a20062903003700002002200329038802370010200241186a2009290300370000200220032903f804370020200241286a200341f8046a41086a290300370000200241306a200341f8046a41106a220a290300370000200241386a200341f8046a41186a220b290300370000200341a0046a200241c00010e603024020032802c0042206450d002002ad428080808080088410050b200341d8036a41186a220c200341a0046a41186a220d290300370300200341d8036a41106a220e200341a0046a41106a220f290300370300200341d8036a41086a2210200341a0046a41086a220929030037030020034188026a41086a2208200341cc046a221529020037030020034188026a41106a2211200341d4046a221629020037030020034188026a41186a2212200341dc046a221729020037030020034188026a41206a2213200341e4046a221829020037030020034188026a41286a2214200341ec046a2219280200360200200320032903a0043703d803200320032902c40437038802200341f8046a41086a221a2010290300370300200a200e290300370300200b200c29030037030020092008290300370300200f2011290300370300200d2012290300370300200341a0046a41206a220b2013290300370300200341a0046a41286a2014280200360200200320032903d8033703f80420032003290388023703a00402402006450d0020034180046a41186a220c200341f8046a41186a220d29030037030020034180046a41106a220e200341f8046a41106a220f29030037030020034180046a41086a2210201a290300370300200341b8016a41086a22112009290300370300200341b8016a41106a2212200341a0046a41106a220a290300370300200341b8016a41186a2213200341a0046a41186a2214290300370300200341b8016a41206a221a200b290300370300200341b8016a41286a220b200341a0046a41286a2207280200360200200320032903f80437038004200320032903a0043703b8012002102c2014200c290300370300200a200e29030037030020092010290300370300200341c4046a20032903b8013702002015201129030037020020162012290300370200201720132903003702002018201a2903003702002019200b28020036020020032003290380043703a004200320063602c004200341c0036a41086a22024196e0c500ad4280808080f000841002220941086a290000370300200320092900003703c0032009102c20034188016a41086a2002290300370300200320032903c00337038801200241d9f8c200ad4280808080e000841002220941086a290000370300200320092900003703c0032009102c20082002290300370300200320032903c00337038802200341f8046a200341a0036a109f0141c000102a2206450d102006200329038801370000200641086a20034188016a41086a2903003700002006200329038802370010200641186a20034188026a41086a290300370000200620032903f804370020200641286a200341f8046a41086a290300370000200641306a200f290300370000200641386a200d29030037000020034100360290022003420137038802200341cc046a20034188026a1091012003200341a0046a3602f804200341f8046a20034188026a108a012003200a3602f804200341f8046a20034188026a108a0120032802c00421022007280200220920034188026a106702402009450d002002200941186c6a21090340200320023602f804200341f8046a20034188026a108a01200241106a20034188026a1089012009200241186a2202470d000b0b200328028c0221022006ad42808080808008842003350290024220862003280288022209ad84100102402002450d002009102c0b2006102c20032802c404450d0220032802c004102c0c020b2002102c0c010b2000410536020041012106410121080c0d0b2000410c3602000c0b0b200341a0046a41186a220d4200370300200341a0046a41106a220a4200370300200341a0046a41086a22084200370300200342003703a004200341c0036a41086a22094196e0c500ad4280808080f0008422051002220641086a290000370300200320062900003703c0032006102c20082009290300370300200320032903c00322043703a801200320043703a0042009419de0c500ad4280808080a001841002220641086a290000370300200320062900003703c0032006102c200a20032903c0032204370300200341f8046a41086a2008290300370300200341f8046a41106a2004370300200341f8046a41186a20092903003703002003200437038004200320032903a0043703f804200341d0006a200341f8046a4120109401200320023602e8022003200c3602e4022003200b3602e002200341003a00f00220032003280254410020032802501b3602ec02200341e4016a220b108604200920051002220241086a290000370300200320022900003703c0032002102c200341a8016a41086a220c2009290300370300200320032903c0033703a801200941aff8c200ad4280808080a001841002220241086a290000370300200320022900003703c0032002102c20034180046a41086a22022009290300370300200320032903c00337038004200341a0046a200b109f0141c000102a2206450d0c200620032903a801370000200641086a200c2903003700002006200329038004370010200641186a2002290300370000200620032903a004370020200641286a2008290300370000200641306a200a290300370000200641386a200d29030037000020034188026a200641c00010ee030240024020032d0098024102460d00200341f8046a41086a200341a5026a290000370300200341f8046a41106a200341ad026a290000370300200341f8046a41186a200341b5026a290000370300200341a0036a41086a200341c6026a290100370300200341a0036a41106a200341ce026a290100370300200341a0036a41186a200341d6026a29010037030020032003419d026a2900003703f8042003200341be026a2901003703a003200341bd026a2d0000210220032d009c022109200328028c02450d01200328028802102c0c010b2003200b3602d403200341a0046a108404200341d8036a20032802a004220220032802a80410d301024020032802a404450d002002102c0b0240024020032d00d8030d00200341a0046a10840420032802a0042102200320032802a8043602fc04200320023602f804200b200341f8046a10a102024020032802a404450d002002102c0b410021020c010b20034180046a41186a200341f1036a29000037030020034180046a41106a200341e9036a29000037030020034180046a41086a200341e1036a290000370300200320032900d9033703800420034188016a20034180046a108b04200341a0046a2003280288012208200328029001220a10ee03024020032d00b0044102470d002003410036027020034201370368200341a0036a41146a410d360200200341ac036a410b360200200341073602ac0120034196e0c5003602a8012003410b3602a4032003410a3602c403200341aff8c2003602c003200320034188016a3602b0032003200341c0036a3602a8032003200341a8016a3602a0032003200341e8006a3602bc05200341f8046a41146a4103360200200342033702fc04200341c09dc5003602f8042003200341a0036a36028805200341bc056a41c49ac500200341f8046a10391a2003350270422086200335026884100420032802d4032109200341f8046a10840420032802f804210220032003280280053602a403200320023602a0032009200341a0036a10a102024020032802fc04450d002002102c0b0240200328026c450d002003280268102c0b0240200328028c01450d00200328028801102c0b410021020c010b200341f8046a200341a0046a41146a41c20010db051a20032d0099052102200341a0036a41106a200341a0046a41106a280200360200200341a0036a41086a200341a0046a41086a2903002204370300200341a0036a41186a2003419a056a410020024101461b360200200320032903a00422053703a0032003200341d4036a3602b40320034100360270200342013703682004a72202200341e8006a10672005a7210b02402002450d0020024105742109200b210203402002200341e8006a109101200241206a2102200941606a22090d000b0b20032802ac03210c02400240200328026c2209200328027022026b4104490d00200328026821090c010b200241046a220d2002490d0820094101742202200d2002200d4b1b22024100480d080240024020090d002002102a21090c010b200328026820092002102e21090b2009450d0f2003200236026c20032009360268200328027021020b2003200241046a360270200920026a200c36000020032d00b003210c02400240200328026c20032802702202460d00200328026821090c010b200241016a22092002490d082002410174220d2009200d20094b1b220d4100480d080240024020020d00200d102a21090c010b20032802682002200d102e21090b2009450d0f2003200d36026c20032009360268200328027021020b2003200241016a360270200920026a200c3a0000200341a0036a41146a200341e8006a10a202200328026c2102200aad4220862008ad84200335027042208620032802682209ad84100102402002450d002009102c0b024020032802a403450d00200b102c0b0240200328028c01450d00200328028801102c0b20032802d4032109200341a0046a10840420032802a0042102200320032802a8043602fc04200320023602f8042009200341f8046a10a102024020032802a404450d002002102c0b200341a0036a41086a20034180046a41086a290300370300200341a0036a41106a20034180046a41106a290300370300200341a0036a41186a20034180046a41186a29030037030020032003290380043703a003410121020b410021090b200341c5046a20023a0000200341c6046a20032903a003370100200341ad046a200341f8046a41086a290300370000200341b5046a200341f8046a41106a290300370000200341bd046a200341f8046a41186a290300370000200341ce046a200341a0036a41086a290300370100200341d6046a200341a0036a41106a290300370100200341de046a200341a0036a41186a290300370100200320093a00a404200320032903f8043700a5042003200341e0026a3602a0042003410036029002200342013703880220032802e002210220032802e802220920034188026a106702402009450d00200941057421090340200220034188026a109101200241206a2102200941606a22090d000b0b20032802ec02210802400240200328028c02220920032802900222026b4104490d0020032802880221090c010b200241046a220a2002490d0620094101742202200a2002200a4b1b22024100480d060240024020090d002002102a21090c010b20032802880220092002102e21090b2009450d0d2003200236028c02200320093602880220032802900221020b2003200241046a36029002200920026a200836000020032d00f002210802400240200328028c022003280290022202460d0020032802880221090c010b200241016a22092002490d062002410174220a2009200a20094b1b220a4100480d060240024020020d00200a102a21090c010b2003280288022002200a102e21090b2009450d0d2003200a36028c02200320093602880220032802900221020b2003200241016a36029002200920026a20083a0000200341a0046a41047220034188026a10a302200328028c0221022006ad42808080808008842003350290024220862003280288022209ad84100102402002450d002009102c0b2006102c024020032802e402450d0020032802e002102c0b024020032802dc01450d0020032802d801102c0b2000410c360200410121060b41002109410121080c0a0b41012106410021092008450d00200a102c0b410121080c080b41002108410021060b200341c5046a20083a0000200341c6046a20032903a003370100200341ad046a200341f8046a41086a290300370000200341b5046a200341f8046a41106a290300370000200341bd046a200341f8046a41186a290300370000200341ce046a200341a0036a41086a290300370100200341d6046a200341a0036a41106a290300370100200341de046a200341a0036a41186a290300370100200320063a00a404200320093602a004200320032903f8043700a504200341003602c001200342013703b801200341a0046a200341b8016a108901200341a0046a410472200341b8016a10a30220032802bc0121092002ad428080808080088420033502c00142208620032802b8012206ad84100102402009450d002006102c0b2002102c024020032802ac02450d0020032802a802102c0b2000410c3602000c050b1035000b200341a0036a41026a200341a8016a41026a2d00003a0000200341a0046a41086a200341f8046a41086a290300370300200341a0046a41106a200341f8046a41106a290300370300200341a0046a41186a200341f8046a41186a2d00003a0000200320032f01a8013b01a003200320032903f8043703a004410021020b20034180036a41026a220a200341a0036a41026a2d00003a000020034180046a41086a2209200341a0046a41086a29030037030020034180046a41106a220b200341a0046a41106a29030037030020034180046a41186a220c200341a0046a41186a2d00003a0000200320032f01a0033b018003200320032903a004370380042002450d010b410121092000410136020041012106410121080c020b20034197026a20092903003700002003419f026a200b290300370000200341a7026a200c2d00003a0000200320032f0180033b0188022003200836008b02200320032903800437008f022003200a2d00003a008a02200341c0036a41086a22024196e0c500ad4280808080f000841002220841086a290000370300200320082900003703c0032008102c200341a8016a41086a2002290300370300200320032903c0033703a801200241d9f8c200ad4280808080e000841002220841086a290000370300200320082900003703c0032008102c20092002290300370300200320032903c00337038004200341a0046a20034188026a109f0141c000102a2202450d02200220032903a801370000200241086a200341a8016a41086a2903003700002002200329038004370010200241186a20034180046a41086a290300370000200220032903a004370020200241286a200341a0046a41086a290300370000200241306a200341b0046a290300370000200241386a200341a0046a41186a29030037000041012109200341186a200241c000410141004100109701200328021821082002102c410521020240024020084101460d00410a2102200542ffffe883b1de165620044200522004501b0d010b2000200236020041012106410121080c020b200341b8016a20034188026a10aa04200341b8016a200610a904200341086a200341b8016a10b701200341086a41086a290300211b2003290308211c200341ce046a20032d00ba013a0000200341cf046a20032800bb01360000200341c8046a4100360200200341a0046a41186a201b2004201c200554201b200454201b2004511b22091b2204370300200341d3046a200341b8016a4107722202290000370000200341db046a200241086a290000370000200341e3046a200241106a290000370000200341eb046a200241186a2d00003a0000200320032f01b8013b01cc04200342083703c0042003201c200520091b22053703b004200320043703a804200320053703a00420034188026a200341a0046a1099040240200341c4046a280200450d0020032802c004102c0b2000410c3602000b4101210941012106410121080b024020012d00002200417f6a2202410f4b0d0002400240024020020e1005030303050003030503030301050302050b2009450d04200141086a280200450d04200141046a280200102c0c040b2006450d03200141086a280200450d03200141046a280200102c0c030b2008450d022001410c6a280200450d02200141086a280200102c0c020b02402000410f4b0d00410120007441bebf03710d02024020004106460d002000410d470d01200141086a280200450d03200141046a280200102c0c030b200141086a280200450d02200141046a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b1033000b200341c0056a24000bb20201027f024002402000280200220141064b0d00024002400240024020010e0705050005010203050b200041086a280200450d042000280204102c0f0b200041086a280200450d032000280204102c0f0b02402000410c6a2802002202450d0020002802042101200241186c210203400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141186a2101200241686a22020d000b0b200041086a280200450d022000280204102c0f0b02402000410c6a2802002202450d00200028020421012002410c6c210203400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b200041086a280200450d012000280204102c0c010b200041086a280200450d002000280204102c0f0b0b800a01057f024002402000280200220141164b0d000240024002400240024002400240024002400240024002400240024020010e1700010f0f020f0f030405060708090f0a0f0b0c0d0f0f0f000b200041086a10fb020f0b02402000410c6a2802002202450d002000280204210120024190016c210203402001107320014190016a2101200241f07e6a22020d000b0b200041086a280200450d0d2000280204102c0f0b02402000410c6a2802002201450d0020002802042203200141f0006c6a2104034002402003410c6a2802002202450d0020032802042101200241246c210203400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012002415c6a22020d000b0b200341f0006a21010240200341086a280200450d002003280204102c0b2001210320012004470d000b0b200041086a280200450d0c2000280204102c0f0b0240200041086a2d00002201410f4b0d00410120017441bfbf03710d0c024020014106470d00200041106a280200450d0d2000410c6a280200102c0f0b200041106a280200450d0c2000410c6a280200102c0f0b200041146a280200450d0b200041106a280200102c0f0b200041086a280200450d0a2000280204102c0f0b200041086a2d0000416d6a220141014b0d090240024020010e020001000b200041106a280200450d0a2000410c6a280200102c0f0b200041106a280200450d092000410c6a280200102c0f0b20002d0004417f6a220141024b0d0802400240024020010e03000102000b2000410c6a280200450d0a200041086a280200102c0f0b200041086a220128020010fc022001280200102c0f0b2000410c6a220128020010fc022001280200102c0f0b20002d0004417f6a220141024b0d0702400240024020010e03000102000b2000410c6a280200450d09200041086a280200102c0f0b200041086a220128020010fc022001280200102c0f0b2000410c6a220128020010fc022001280200102c0f0b200041086a2802004101470d06200041106a280200450d062000410c6a280200102c0f0b20002d00044104470d052000410c6a280200450d05200041086a280200102c0f0b200041086a280200450d042000280204102c0f0b200041086a2d0000417e6a220141024b0d0302400240024020010e03000102000b200041106a280200450d052000410c6a280200102c0f0b200041346a280200450d04200041306a280200102c0f0b200041306a280200450d032000412c6a280200102c0f0b02402000280204220141024b0d00024020010e03040004040b200041086a220128020010fc022001280200102c0f0b2000412c6a220128020010fc022001280200102c0f0b02402000410c6a280200450d00200041086a280200102c0b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b200041186a280200450d012000280214102c0c010b02402000280204220141034b0d00024020010e0402000202020b2000410c6a280200450d01200041086a280200102c0f0b200041306a280200450d002000412c6a280200102c0f0b0b8d0902067f047e230041e0026b220224000240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541034b0d0620050e0401020304010b200041053a00000c090b200241206a200110820120022802200d03200041053a00000c080b200241c0006a2001108f020240024020022802404118460d00200241d0016a200241c0006a41900110db051a419001102a22050d010c080b200041053a00000c080b2005200241d0016a41900110db052105200041023a0000200020022f00103b0001200041036a200241106a41026a2d00003a0000200041046a2005360200200041086a2002290220370200200041106a200241206a41086a290200370200200041186a200241206a41106a290200370200200041206a200241206a41186a2902003702000c070b20022001107520022802000d0420022802042105200241c0006a2001108f0220022802404118460d04200241d0016a200241c0006a41900110db051a419001102a2201450d052001200241d0016a41900110db052101200041033a0000200020022f00103b0001200041036a200241126a2d00003a0000200041086a2001360200200041046a20053602002000410c6a2002290220370200200041146a200241206a41086a2902003702002000411c6a200241306a290200370200200041246a200241386a2802003602000c060b41002105200241003a00f0012003417f6a21062003417e6a21030340024020062005470d00200541ff0171450d04200241003a00f0010c040b200241d0016a20056a200420056a220741016a2d00003a0000200120033602042001200741026a3602002002200541016a22073a00f0012003417f6a21032007210520074120470d000b200241c0006a41186a200241d0016a41186a290300370300200241c0006a41106a200241d0016a41106a290300370300200241c0006a41086a200241d0016a41086a290300370300200220022903d001370340200241086a2001107520022802080d0220012802042203450d02200228020c2104200128020022072d0000210520012003417f6a3602042001200741016a360200200541014b0d02410021010240024020050e020100010b410121010b200241206a41186a200241c0006a41186a2903002208370300200241206a41106a200241c0006a41106a2903002209370300200241206a41086a200241c0006a41086a290300220a37030020022002290340220b370320200041043a00002000200b370001200041096a200a370000200041116a2009370000200041196a2008370000200041246a2004360200200041216a20013a00000c050b200241cb006a200241206a41086a28020036000020022002290320370043200041013a000020002002290040370001200041086a200241c7006a290000370000200041106a20022902d001370200200041186a200241d0016a41086a290200370200200041206a200241d0016a41106a2902003702000c040b200041053a00000c030b200041053a00000c020b200041053a00000c010b1033000b200241e0026a24000bf10603057f0b7e067f230041106b21020240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a36020020064108490d00200429000421072001200341746a220636020420012004410c6a36020020064108490d00200429000c210820012003416c6a22063602042001200441146a36020020064108490d00200429001421092001200341646a220636020420012004411c6a36020020064108490d00200429001c210a20012003415c6a22063602042001200441246a36020020064108490d002004290024210b2001200341546a220636020420012004412c6a36020020064108490d00200429002c210c20012003414c6a22063602042001200441346a36020020064108490d002004290034210d2001200341446a220636020420012004413c6a36020020064108490d00200429003c210e2001200341bc7f6a22063602042001200441c4006a36020020064108490d002004290044210f2001200341b47f6a22063602042001200441cc006a36020020064108490d00200429004c21102001200341ac7f6a22063602042001200441d4006a36020020064108490d00200429005421112001200341a47f6a22063602042001200441dc006a36020020064104490d00200428005c21122001200341a07f6a22063602042001200441e0006a36020020064104490d002004280060211320012003419c7f6a22063602042001200441e4006a36020020064104490d00200428006421142001200341987f6a22063602042001200441e8006a36020020064104490d00200428006821152001200341947f6a22063602042001200441ec006a22043602002006450d0020042d000021062001200341937f6a22163602042001200441016a360200200641014b0d00410021170240024020060e020100010b410121170b20164104490d00200020173a00702000201536026820002014360264200020133602602000201236025c2000200536025820002011370350200020103703482000200f3703402000200e3703382000200d3703302000200c3703282000200b3703202000200a3703182000200937031020002008370308200020073703002004280001210620012003418f7f6a3602042001200441056a3602002000200636026c200041f4006a2002410c6a280000360000200020022800093600710f0b200041023a00700bcc07020e7f047e230041a0016b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022030d00200041003602000c010b200228021421042002200241186a280200360234200220033602302002200241306a1075024002400240024020022802000d00024002402002280234220541286e220641286c2201417f4c0d00200228020421070240024020010d00410821080c010b2001102a2208450d020b02402007450d00410021090340200241003a0098012009220a41016a2109410021010240024002400240034020052001460d01200241f8006a20016a2002280230220b2d00003a00002002200b41016a3602302002200141016a220c3a009801200c2101200c4120470d000b200241d8006a41086a220d200241f8006a41086a290300370300200241d8006a41106a220e200241f8006a41106a290300370300200241d8006a41186a220f200241f8006a41186a2903003703002002200229037837035820022005200c6b220136023420014108490d01200241386a41086a220c200d290300370300200241386a41106a220d200e290300370300200241386a41186a220e200f290300370300200220022903583703382002200b41096a3602302002200141786a2205360234200b29000121102006200a470d030240200a41017422012009200120094b1b2206ad42287e2211422088a70d002011a7220141004e0d030b1035000b20024100360234200141ff0171450d00200241003a0098010b200241003602202006450d072008102c0c070b02400240200a0d002001102a21080c010b2008200a41286c2001102e21080b2008450d040b2008200a41286c6a22012002290338370300200c2903002111200d2903002112200e290300211320012010370320200141186a2013370300200141106a2012370300200141086a201137030020092007470d000b200241286a200736020020022006360224200220083602200c050b200241286a2007360200200220063602242002200836022020080d040c030b103a000b1033000b200241003602200b20024100360260200242013703582002410b36023c2002200241086a3602382002200241d8006a3602202002418c016a41013602002002420137027c200241d0b0c2003602782002200241386a36028801200241206a41c49ac500200241f8006a10391a2002350260422086200235025884100420004100360200200228025c450d012002280258102c0c010b20002002290320370200200041086a200241206a41086a2802003602000b2004450d002003102c0b200241a0016a24000bd60302057f047e230041f0006b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022030d00200041003a00000c010b200241186a28020021042002280214210541002101200241003a006802400340024020042001470d000240200141ff0171450d00200241003a00680b4100210120024100360228200242013703202002410b3602442002200241086a3602402002200241206a36026c200241dc006a41013602002002420137024c200241d0b0c2003602482002200241c0006a360258200241ec006a41c49ac500200241c8006a10391a200235022842208620023502208410042002280224450d022002280220102c0c020b200241c8006a20016a200320016a2d00003a00002002200141016a22063a00682006210120064120470d000b200241206a41186a200241c8006a41186a2903002207370300200241206a41106a200241c8006a41106a2903002208370300200241206a41086a200241c8006a41086a290300220937030020022002290348220a370320200041196a2007370000200041116a2008370000200041096a20093700002000200a370001410121010b200020013a00002005450d002003102c0b200241f0006a24000b3400200041bac6c50036020420004100360200200041146a4109360200200041106a41dc91c200360200200041086a42043702000b130020004102360204200041c4a3c2003602000b2d01017f02404108102a22020d001033000b20004288808080800137020420002002360200200242b8173700000b2d01017f02404108102a22020d001033000b20004288808080800137020420002002360200200242c8013700000bb30c06017f027e057f017e037f017e230041f0016b22022400200241f8006a2000200110ce01200241f8006a41106a290300210020022903800121010240024020022903782203a7450d00200241c0006a200142004204420010e005200241306a420042002001420010e005200241d0006a2002290340200241c0006a41086a2903002203200042028620022903307c7c22044205420010e10542b3e6cc99b3e6cc99332002290350200042ffffffffffffffff3f8320005220022903384200527220042003547222051b220320012001200356200042b3e6cc99b3e6cc9933200241d0006a41086a29030020051b22035620002003511b22051b22042003200020051b220310b102200241e0006a200120047d200020037d2001200454ad7d10ce01200241e0006a41106a290300210120022903682100024020022903602203a7450d00200241b0016a10e801200241b0016a20002001109c010c020b2003500d01200241b0016a41186a22064200370300200241b0016a41106a22074200370300200241b0016a41086a22084200370300200242003703b001200241e0016a41086a2205418be9c500ad428080808080018422041002220941086a290000370300200220092900003703e0012009102c20082005290300370300200220022903e00122033703d001200220033703b001200541c9b5c000ad4280808080d00184220a1002220941086a290000370300200220092900003703e0012009102c200720022903e001220337030020024190016a41086a220b200829030037030020024190016a41106a220c200337030020024190016a41186a220d2005290300370300200220033703d001200220022903b00137039001200241186a20024190016a4120109e01200241186a41106a29030021032002290320210e20022802182109200642003703002007420037030020084200370300200242003703b001200520041002220741086a290000370300200220072900003703e0012007102c20082005290300370300200220022903e00122043703d001200220043703b0012005200a1002220741086a290000370300200220072900003703e0012007102c200620052903002204370300200b2008290300370300200c20022903e001220a370300200d20043703002002200a3703d001200220022903b00137039001200242002003420020091b220320017d200e420020091b2201200054ad7d2204200120007d2200200156200420035620042003511b22051b3703b80120024200200020051b3703b00120024190016aad4280808080800484200241b0016aad428080808080028410010c010b2003500d00200241b0016a41186a22064200370300200241b0016a41106a22074200370300200241b0016a41086a22084200370300200242003703b001200241e0016a41086a2205418be9c500ad428080808080018422041002220941086a290000370300200220092900003703e0012009102c20082005290300370300200220022903e00122033703d001200220033703b001200541c9b5c000ad4280808080d00184220a1002220941086a290000370300200220092900003703e0012009102c200720022903e001220337030020024190016a41086a220b200829030037030020024190016a41106a220c200337030020024190016a41186a220d2005290300370300200220033703d001200220022903b00137039001200220024190016a4120109e01200241106a29030021032002290308210e20022802002109200642003703002007420037030020084200370300200242003703b001200520041002220741086a290000370300200220072900003703e0012007102c20082005290300370300200220022903e00122043703d001200220043703b0012005200a1002220741086a290000370300200220072900003703e0012007102c200620052903002204370300200b2008290300370300200c20022903e001220a370300200d20043703002002200a3703d001200220022903b00137039001200242002003420020091b220320007d200e420020091b2200200154ad7d2204200020017d2201200056200420035620042003511b22051b3703b80120024200200120051b3703b00120024190016aad4280808080800484200241b0016aad428080808080028410010b200241f0016a24000ba40301057f230041106b22032400024002400240200141046a2204417f4c0d000240024020040d00410121050c010b2004102a2205450d020b2003410036020820032004360204200320053602002001200310670240024020032802042206200328020822056b2001490d00200328020021040c010b200520016a22042005490d03200641017422072004200720044b1b22074100480d030240024020060d002007102a21040c010b200328020020062007102e21040b2004450d022003200736020420032004360200200721060b200420056a2000200110db051a02400240200241046a2802002207200241086a28020022006b200520016a2201490d00200228020021050c010b200020016a22052000490d03200741017422002005200020054b1b22004100480d030240024020070d002000102a21050c010b200228020020072000102e21050b2005450d0220022005360200200241046a2000360200200241086a28020021000b200241086a200020016a360200200520006a2004200110db051a02402006450d002004102c0b200341106a24000f0b103a000b1033000b1035000beb0301057f230041c0006b22022400200241206a41086a220341e4d2c500ad42808080808001841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341a9e4c300ad4280808080e001841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2000109f01024041c000102a2204450d00200420022903003700002004200229031037001020042002290020370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241003602282002420137032020012d000021004101102a21030240024020004101460d002003450d02200242818080801037022420022003360220200341003a0000200141086a200241206a10b4040c010b2003450d01200242818080801037022420022003360220200341013a00002002200241206a360210200141016a200241106a1094020b200228022421032004ad4280808080800884200235022842208620022802202201ad84100102402003450d002001102c0b2004102c200241c0006a24000f0b1033000b02000be52003167f037e067f230041c0026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d0020002001108a032003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200a200a417f6a220d2000200a4105746a2000200d4105746a412010dd05220e410048220f1b2210200a41016a2211200d200a200f1b220a200020114105746a2000200a4105746a412010dd0541004822111b220a2000200a4105746a200020104105746a412010dd0522104100481b210a200c200c417f6a220d2000200c4105746a2000200d4105746a412010dd05221241004822131b2214200c4101722215200d200c20131b220c200020154105746a2000200c4105746a412010dd0522134100481b220c2000200c4105746a200020144105746a412010dd0522144100481b210c200b200b417f6a220d2000200b4105746a2000200d4105746a412010dd05221541004822161b2217200b41016a2218200d200b20161b220b200020184105746a2000200b4105746a412010dd05220d4100481b220b2000200b4105746a200020174105746a412010dd0522164100481b210b41024101200f1b200e411f7620111b2010411f766a2012411f766a2013411f766a2014411f766a2015411f766a200d411f766a2016411f766a210d0b2000200c4105746a2000200a4105746a412010dd05220f411f76200d6a2000200b4105746a2000200a200c200f410048220f1b220e4105746a412010dd052210411f766a210d2000200b200e20104100481b220b4105746a2000200c200a200f1b22194105746a412010dd05417f4c0d01200b21190c020b20002001108b030c0f0b200d41016a220d410c490d0002402001410176220b450d00200020014105746a41606a210a2000210c0340200441206a41186a220d200c41186a220f290000370300200441206a41106a220e200c41106a2210290000370300200441206a41086a2211200c41086a22122900003703002004200c290000370320200a41086a2213290000211a200a41106a2214290000211b200a41186a2215290000211c200c200a290000370000200f201c3700002010201b3700002012201a3700002015200d2903003700002014200e29030037000020132011290300370000200a2004290320370000200a41606a210a200c41206a210c200b417f6a220b0d000b0b20012019417f736a21194101210a0c010b200d45210a0b0240200a452009724101710d0020002001108c030d0d0b2002450d02201920014f0d0102402002200020194105746a220a412010dd0541004e0d0020002108200121070c040b200441206a41186a2212200041186a220e290000370300200441206a41106a2213200041106a2210290000370300200441206a41086a2214200041086a221129000037030020042000290000370320200a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2000200a290000370000200e201c3700002010201b3700002011201a370000200d2012290300370000200b2013290300370000200c2014290300370000200a2004290320370000200441c0016a41186a2217200e290000370300200441c0016a41106a22182010290000370300200441c0016a41086a22192011290000370300200420002900003703c001200041606a2115200041206a21164100210c2001210b03400240200c200b417f6a220d4f0d002016200c4105746a210a0340200441c0016a200a412010dd05417f4c0d01200a41206a210a200d200c41016a220c470d000b200d210c0b2015200b4105746a210a02400340200c200b417f6a220b4f0d01200441c0016a200a412010dd05210d200a41606a220f210a200d4100480d000b20122016200c4105746a220a41186a220d2900003703002013200a41106a221d2900003703002014200a41086a22062900003703002004200a290000370320200f41286a221e290000211a200f41306a221f290000211b200f41386a2220290000211c200a200f41206a220f290000370000200d201c370000201d201b3700002006201a37000020202012290300370000201f2013290300370000201e2014290300370000200f2004290320370000200c41016a210c0c010b0b200020042903c001370000200e2017290300370000201020182903003700002011201929030037000002402001200c41016a220a490d002000200a4105746a21002001200a6b220141154f0d010c0c0b0b200a20011047000b41c4ffc500201920011038000b2007450d010b201920074f0d01200441206a41186a2216200841186a221e290000370300200441206a41106a2217200841106a221f290000370300200441206a41086a2218200841086a222029000037030020042008290000370320200820194105746a220a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2008200a290000370000201e201c370000201f201b3700002020201a370000200d2016290300370000200b2017290300370000200c2018290300370000200a2004290320370000200441186a2205201e290000370300200441106a2209201f290000370300200441086a2221202029000037030020042008290000370300200841206a21014100211d2007417f6a220d450d022001210a0340200a2004412010dd0541004e0d03200a41206a210a200d201d41016a221d470d000b200d211d0c020b41f8fec500410041001038000b4188ffc500201920071038000b200820074105746a210c200d210b02400340200c2100200b220a201d4d22060d01200a417f6a210b200041606a220c2004412010dd05417f4a0d000b0b0240200a201d490d00200d200a490d0241800121144100210f410021124100210d4100211141800121152001201d4105746a2222210103400240200020016b220a419fc0004b22190d00200a410576220a41807f6a200a2012200f492011200d49220c72220b1b210a0240200b450d002015200a200c1b2115200a2014200c1b21140c010b200a200a41017622156b21140b02402011200d470d00024020150d00200441c0006a220d21110c010b4100210a200441c0006a2211210d2001210c0340200d200a3a0000200d200c2004412010dd05417f73411f766a210d200c41206a210c2015200a41016a220a470d000b0b02402012200f470d00024020140d00200441c0016a220f21120c010b200041606a210a4100210c200441c0016a2212210f0340200f200c3a0000200f200a2004412010dd05411f766a210f200a41606a210a2014200c41016a220c470d000b0b0240200f20126b220a200d20116b220c200c200a4b1b2213450d002016200120112d00004105746a220a41186a2900003703002017200a41106a2900003703002018200a41086a2900003703002004200a290000370320200120112d00004105746a220a200020122d0000417f734105746a220c290000370000200a41186a200c41186a290000370000200a41106a200c41106a290000370000200a41086a200c41086a290000370000024020134101460d004100210a034020002012200a6a220e2d0000417f734105746a220c20012011200a6a41016a22102d00004105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200120102d00004105746a220c2000200e41016a2d0000417f734105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200a41026a210c200a41016a220b210a200c2013490d000b2012200b6a21122011200b6a21110b200020122d0000417f734105746a220a2004290320370000200a41186a2016290300370000200a41106a2017290300370000200a41086a2018290300370000201241016a2112201141016a21110b200020144105746b20002012200f461b2100200120154105746a20012011200d461b210120190d000b024002402011200d4f0d002000210a034020162001200d417f6a220d2d00004105746a220c41186a220b2900003703002017200c41106a220f2900003703002018200c41086a22002900003703002004200c290000370320200a41606a220a41086a220e290000211a200a41106a2210290000211b200a41186a2212290000211c200c200a290000370000200b201c370000200f201b3700002000201a3700002012201629030037000020102017290300370000200e2018290300370000200a20042903203700002011200d490d000c020b0b2001210a2012200f4f0d000340200f417f6a220f2d0000210c2016200a41186a220b2900003703002017200a41106a220d2900003703002018200a41086a22012900003703002004200a2900003703202000200c417f734105746a220c41086a220e290000211a200c41106a2210290000211b200c41186a2211290000211c200a200c290000370000200b201c370000200d201b3700002001201a3700002011201629030037000020102017290300370000200e2018290300370000200c2004290320370000200a41206a210a2012200f490d000b0b20082004290300370000201e2005290300370000201f2009290300370000202020212903003700002007200a20226b410576201d6a22014d0d032016201e2900003703002017201f2900003703002018202029000037030020042008290000370320200820014105746a220a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2008200a290000370000201e201c370000201f201b3700002020201a370000200d2016290300370000200b2017290300370000200c2018290300370000200a2004290320370000200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41206a2100024002402001200c417f6a220c490d002000200c200a2003108903200821000c010b2008200120022003108903200a2102200c21010b200b200d4f2105200141154f0d010c050b0b201d200a1047000b200a200d103f000b4188ffc500200120071038000b4198ffc500411c41b4ffc5001036000b20014102490d00200041606a210f4101210b0340200b410574210a200b417f6a210c200b41016a210b02402000200a6a220a2000200c4105746a220d412010dd05417f4a0d00200441c0016a41186a220e200a41186a2210290000370300200441c0016a41106a2211200a41106a2212290000370300200441c0016a41086a2213200a41086a22142900003703002004200a2900003703c001200a200d2900003700002014200d41086a2900003700002012200d41106a2900003700002010200d41186a2900003700004100210d0240200c450d00200f210a03400240200441c0016a200a412010dd054100480d00200c210d0c020b200a41206a200a290000370000200a41386a200a41186a290000370000200a41306a200a41106a290000370000200a41286a200a41086a290000370000200a41606a210a200c417f6a220c0d000b0b2000200d4105746a220a20042903c001370000200a41186a200e290300370000200a41106a2011290300370000200a41086a20132903003700000b200f41206a210f200b2001470d000b0b200441c0026a24000beb050a067f017e017f017e017f017e017f017e017f017e230041206b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200020044105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c37000020052008370000024020032001490d00200321040c030b2006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d01200020034105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c370000200520083700002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200020044105746a22012900002108200020054105746a220041086a2205290000210a200041106a2204290000210c200041186a2203290000210e20012000290000370000200141186a220629000021102006200e370000200141106a2206290000210e2006200c370000200141086a2201290000210c2001200a370000200320103700002004200e3700002005200c370000200020083700000b200241206a24000f0b4188ffc500200520011038000b41f8fec500200420011038000be90609067f017e017f017e017f027e017f017e027f230041206b22022400024020014101762203450d0003402003417f6a2203210402400240024003402004410174220541017221060240200541026a220520014f0d00200620014f0d0220052006200020064105746a200020054105746a412010dd054100481b21060b200620014f0d03200420014f0d02200020044105746a2204200020064105746a2205412010dd0541004e0d03200541086a22072900002108200541106a2209290000210a200541186a220b290000210c2004290000210d20042005290000370000200441186a220e290000210f200e200c370000200441106a220e290000210c200e200a370000200441086a2204290000210a20042008370000200b200f3700002009200c3700002007200a3700002005200d370000200621040c000b0b41a080c600200620011038000b41b080c600200420011038000b20030d000b0b0240024020014102490d002001210703402007417f6a220720014f0d02200241186a2209200041186a2204290000370300200241106a220b200041106a2205290000370300200241086a220e200041086a2203290000370300200020074105746a220641086a2900002108200641106a290000210a200641186a290000210c2000290000210d200020062900003700002004200c3700002005200a370000200320083700002002200d37030041002105024002400240034020062002290300370000200641186a2009290300370000200641106a200b290300370000200641086a200e2903003700002005410174220641017221040240200641026a220620074f0d00200420074f0d0220062004200020044105746a200020064105746a412010dd054100481b21040b200420074f0d03200520074f0d02200020054105746a2205200020044105746a2206412010dd0541004e0d032009200541186a2203290000370300200b200541106a2210290000370300200e200541086a2211290000370300200641086a2900002108200641106a290000210a200641186a290000210c2005290000210d200520062900003700002003200c3700002010200a370000201120083700002002200d370300200421050c000b0b41a080c600200420071038000b41b080c600200520071038000b200741014b0d000b0b200241206a24000f0b4188ffc500200720011038000bdb08030a7f017e0a7f230041c0006b22022400200041a07f6a21032001417f6a2104200141324921054101210641002107024003400240024020062001490d00410021080c010b41012108200020064105746a2209200941606a412010dd054100480d0003404101210a20042006460d03200641016a2106200941206a220a2009412010dd052108200a21092008417f4a0d000b200620014921080b2006200146210a20050d0120062001460d0102400240024002402006417f6a220920014f0d002008450d0120002006410574220b6a220a290000210c200a200020094105746a22092900003700002009200c370000200a41086a220d290000210c200d200941086a220e290000370000200e200c370000200a41106a220f290000210c200f200941106a22102900003700002010200c370000200a41186a2211290000210c2011200941186a22122900003700002012200c37000020064102490d03200920002006417e6a22084105746a2213412010dd05417f4a0d032009290000210c20092013290000370000200241206a41186a22142012290000370300200241206a41106a22152010290000370300200241206a41086a2216200e290000370300200e201341086a2900003700002010201341106a2900003700002012201341186a2900003700002002200c3703204100210e2008450d022003200b6a210903400240200241206a2009412010dd054100480d002008210e0c040b200941206a2009290000370000200941386a200941186a290000370000200941306a200941106a290000370000200941286a200941086a290000370000200941606a21092008417f6a22080d000c030b0b41f8fec500200920011038000b4188ffc500200620011038000b2000200e4105746a22092002290320370000200941186a2014290300370000200941106a2015290300370000200941086a20162903003700000b200741016a21070240200120066b22104102490d00200a41206a2209200a412010dd05417f4a0d00200a290000210c200a2009290000370000200241206a41186a22122011290000370300200241206a41106a2213200f290000370300200241206a41086a220b200d290000370300200d200941086a290000370000200f200941106a2900003700002011200941186a2900003700002002200c3703204101210d024020104103490d00200a41c0006a200241206a412010dd05417f4a0d00410321084102210e0340200a200e4105746a220941606a220d2009290000370000200d41186a200941186a290000370000200d41106a200941106a290000370000200d41086a200941086a290000370000024020082010490d00200e210d0c020b20084105742109200e210d2008210e200841016a2108200a20096a200241206a412010dd054100480d000b0b200a200d4105746a22092002290320370000200941186a2012290300370000200941106a2013290300370000200941086a200b2903003700000b20074105470d000b4100210a0b200241c0006a2400200a0bc21301147f23004180026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d0020002001108e032003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200b200b417f6a220e2000200b4102746a280200220f2000200e4102746a280200221049220d1b2211200b41016a2212200e200b200d1b200020124102746a280200220b2010200f200d1b220e4922101b200b200e20101b200020114102746a2802004922131b210b200c200c417f6a220e2000200c4102746a28020022112000200e4102746a280200221249220f1b2214200c4101722215200e200c200f1b200020154102746a280200220c20122011200f1b220e4922111b200c200e20111b200020144102746a2802004922141b210c200a200a417f6a22122000200a4102746a2802002215200020124102746a280200220649220e1b2216200a41016a22172012200a200e1b200020174102746a280200220a20062015200e1b22154922121b200a201520121b200020164102746a2802004922151b210a41024101200e1b200e20121b20156a200f6a20116a20146a200d6a20106a20136a210d0b200d2000200c4102746a280200220f2000200a4102746a280200221049220e6a2000200b4102746a280200220d2010200f200e1b22114922106a210f200d201120101b2000200c200a200e1b220d4102746a280200490d01200b200a200c200e1b20101b210d0c020b20002001108f030c0f0b200f41016a220f410c490d0002402001410176220b450d00200020014102746a417c6a210a2000210c0340200c280200210e200c200a280200360200200a200e360200200c41046a210c200a417c6a210a200b417f6a220b0d000b0b2001200d417f736a210d4101210a0c010b200f45210a0b0240200a452009724101710d00200020011090030d0d0b2002450d02200d20014f0d01024020022802002000200d4102746a220a280200220c4f0d0020002108200121070c040b2000280200210b2000200c360200200a200b3602002000417c6a2110200041046a21112000280200210d4100210c2001210b03400240200c200b417f6a220e4f0d002011200c4102746a210a0340200d200a280200490d01200a41046a210a200e200c41016a220c470d000b200e210c0b2010200b4102746a210a02400340200c200b417f6a220b4f0d01200a280200210e200a417c6a220f210a200d200e490d000b2011200c4102746a220a2802002112200a200e360200200f41046a2012360200200c41016a210c0c010b0b2000200d36020002402001200c41016a220a490d002000200a4102746a21002001200a6b220141154f0d010c0c0b0b200a20011047000b41c4ffc500200d20011038000b2007450d010b200d20074f0d012008280200210a20082008200d4102746a220c280200360200200c200a360200200841046a210f20082802002111410021142007417f6a220d450d02200f210a0340200a28020020114f0d03200a41046a210a200d201441016a2214470d000b200d21140c020b41f8fec500410041001038000b4188ffc500200d20071038000b200820074102746a210c200d210b02400340200c210e200b220a20144d22060d01200a417f6a210b200e417c6a220c28020020114f0d000b0b0240200a2014490d00200d200a490d0241800121054100210b410021014100210c410021104180012109200f20144102746a2216210d03400240200e200d6b220a4183084b22130d00200a410276220a41807f6a200a2001200b492010200c49220f7222001b210a02402000450d002009200a200f1b2109200a2005200f1b21050c010b200a200a41017622096b21050b02402010200c470d00024020090d002004220c21100c010b4100210a20042210210c200d210f0340200c200a3a0000200c200f28020020114f6a210c200f41046a210f2009200a41016a220a470d000b0b02402001200b470d00024020050d0020044180016a220b21010c010b200e417c6a210a4100210f20044180016a2201210b0340200b200f3a0000200b200a2802002011496a210b200a417c6a210a2005200f41016a220f470d000b0b0240200b20016b220a200c20106b220f200f200a4b1b2212450d00200d20102d00004102746a220a2802002115200a200e20012d0000417f734102746a280200360200024020124101460d004100210a0340200e2001200a6a220f2d0000417f734102746a200d2010200a6a41016a22002d00004102746a280200360200200d20002d00004102746a200e200f41016a2d0000417f734102746a280200360200200a41026a210f200a41016a2200210a200f2012490d000b200120006a2101201020006a21100b200e20012d0000417f734102746a2015360200200141016a2101201041016a21100b200e20054102746b200e2001200b461b210e200d20094102746a200d2010200c461b210d20130d000b024002402010200c4f0d00200e210a0340200d200c417f6a220c2d00004102746a220b280200210e200b200a417c6a220a280200360200200a200e3602002010200c490d000c020b0b200d210a2001200b4f0d000340200a280200210c200a200e200b417f6a220b2d0000417f734102746a220d280200360200200d200c360200200a41046a210a2001200b490d000b0b200820113602002007200a20166b41027620146a22014d0d032008200820014102746a220a280200360200200a2011360200200720016b220c450d04200c20012001200c4b1b210b2007410376210e200a41046a2100024002402001200c417f6a220c490d002000200c200a2003108d03200821000c010b2008200120022003108d03200a2102200c21010b200b200e4f2105200141154f0d010c050b0b2014200a1047000b200a200d103f000b4188ffc500200120071038000b4198ffc500411c41b4ffc5001036000b20014102490d00200041746a210e4102210d4101210a0340200a41016a210c02402000200a4102746a2210280200220b2000200a417f6a22114102746a220f28020022124f0d002010201236020002402011450d00200b2000200a417e6a22104102746a221128020022124f0d00200f2012360200024020100d002011210f0c010b0240200b2000200a417d6a220a4102746a220f2802002210490d002011210f0c010b20112010360200200a450d00200d210f200e210a02400340200b200a28020022104f0d01200a41046a2010360200200a417c6a210a200f41016a2210200f4921112010210f2011450d000b0b200a41046a210f0b200f200b3602000b200d417f6a210d200e41046a210e200c210a200c2001470d000b0b20044180026a24000bf30201067f02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034102746a220328020021072003200020044102746a220428020036020020042007360200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024102746a220328020021072003200020044102746a2204280200360200200420073602002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034102746a220128020021022001200020044102746a2200280200360200200020023602000b0f0b4188ffc500200420011038000b41f8fec500200320011038000bc70301067f024020014101762202450d0003402002417f6a2202210302400240024003402003410174220441017221050240200441026a220420014f0d00200520014f0d0220042005200020054102746a280200200020044102746a280200491b21050b200520014f0d03200320014f0d02200020034102746a22032802002204200020054102746a220628020022074f0d032003200736020020062004360200200521030c000b0b41a080c600200520011038000b41b080c600200320011038000b20020d000b0b0240024020014102490d002001210403402004417f6a220420014f0d02200028020021052000200020044102746a2203280200360200200320053602004100210302400240024003402003410174220641017221050240200641026a220620044f0d00200520044f0d0220062005200020054102746a280200200020064102746a280200491b21050b200520044f0d03200320044f0d02200020034102746a22032802002206200020054102746a220728020022024f0d032003200236020020072006360200200521030c000b0b41a080c600200520041038000b41b080c600200320041038000b200441014b0d000b0b0f0b4188ffc500200420011038000b8a05010f7f2001417d6a2102200041086a21032000416c6a21042001417f6a2105200041046a2106410021072001413249210841012109024003400240024020092001490d004100210a0c010b4101210a20002009410274220b6a220c280200220d200c417c6a280200490d002006200b6a210a03404101210c20052009460d03200941016a2109200a280200220c200d4f210b200a41046a210a200c210d200b0d000b2009200149210a0b2009200146210c20080d0120092001460d0102400240024002402009417f6a220d20014f0d00200a450d012000200d4102746a220c280200210b200c20002009410274220e6a220a280200220d360200200a200b360200024020094102490d00200d20002009417e6a220b4102746a220f28020022104f0d00200c201036020002400240200b0d00200f210c0c010b0240200d20002009417d6a220b4102746a220c2802002210490d00200f210c0c010b200f2010360200200b450d00200d200a41706a280200220f4f0d002004200e6a2110024003402010220c41086a200f360200200b417f6a220b450d01200c417c6a2110200d200c280200220f490d000b0b200c41046a210c0b200c200d3602000b200741016a2107200120096b220b4102490d03200a280204220f200a280200220c4f0d03200a41046a210d200a200f360200200b4103490d02200a280208220f200c4f0d02200d200f3602000240200b41044f0d00200a41086a210d0c030b200220096b210a2003200e6a210d0340200d41046a220b280200220e200c4f0d03200d200e360200200b210d200a417f6a220a0d000b200b210d0c020b41f8fec500200d20011038000b4188ffc500200920011038000b200d200c3602000b20074105470d000b4100210c0b200c0b120041bcaac20041fc0041acfec5001036000b5101027e024002402003450d002002280200450d010b41b5abc50041f4031054000b2001280218220342002003290308220420023502047d2205200520045622021b37030820004105410420021b3602000bd60201047f0240024002402002417f4c0d000240024020020d00410121060c010b2002102a2206450d020b20062001200210db0521062004417f4c0d000240024020040d0041012101410021070c010b200421072004102a2201450d020b20012003200410db052103024020002802082201200041046a280200470d00200141016a22082001490d03200141017422092008200920084b1b220841ffffff3f712008470d03200841057422094100480d030240024020010d002009102a21010c010b200028020020014105742009102e21010b2001450d0220002001360200200041046a2008360200200028020821010b200028020020014105746a220141003602182001200336020c2001200236020820012002360204200120063602002001411c6a2005360200200141146a2004360200200141106a20073602002000200028020841016a3602080f0b103a000b1033000b1035000bfa0e05047f027e027f017e027f230041c00c6b22042400024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320022802042105200241246a2802002106200241346a28020021030240200241146a2802002207450d004105210220012802002802182802402802bc012003490d080b200441286a4200370300200441206a4200370300200441186a420037030020012802182202420020022903082208427f20012802102903482209420586200942ffffffffffffffff07832009521b7d22092009200856220a1b3703082004420037031041052102200a0d070240024020012802142802082005200441106a4120101e41026a220a41024b0d00200a0e03090001090b41ac91c600412841d491c6001036000b024002400240024020070d00410121034100210b0c010b2004200128021029034842002003ad220c420010e0052001280218220a4200200a2903082209427f200429030020042903084200521b7d22082008200956220a1b370308200a0d0a2003417f4c0d070240024020030d004101210b02402001280214280208200641014100101e41026a220341024b0d0020030e030d00020d0b41ac91c600412841d491c6001036000b20031030220b450d0a024020012802142802082006200b2003101e41026a220341024b0d0020030e03030001030b41ac91c600412841d491c6001036000b200c422086200c842109200b4521030b20012802002101200441306a41186a220a200441106a41186a290300370300200441306a41106a2205200441106a41106a290300370300200441306a41086a2206200441106a41086a290300370300200420042903103703302001280218210720030d0120072802402802bc012009422088a74f0d012009a7450d090b200b102c0c080b200441d0006a41186a200a290300370300200441d0006a41106a2005290300370300200441d0006a41086a20062903003703002004200429033037035020072802180d052007417f360218200441a8016a200741e8006a290000370300200441a0016a200741e0006a29000037030020044198016a200741d8006a2900003703002004200729005037039001024002402007411c6a220d280200220a41d0e1c100460d00200741206a28020021060c010b41002106200441e0096a410041e00210da051a200441c0016a410041a00810da051a41880b102a220a450d07200a41003b0106200a4100360200200a41086a200441e0096a41e00210db051a200a41e8026a200441c0016a41a00810db051a200741206a41003602002007200a36021c0b024002400340200a2f0106220e4105742105410021024100210302400240034020052002460d0120044190016a200a20026a41086a412010dd052201450d02200241206a2102200341016a21032001417f4a0d000b2003417f6a210e0b2006450d022006417f6a2106200a200e4102746a41880b6a280200210a0c010b0b200741246a2101410121020c010b200441f0006a41186a20044190016a41186a290300370300200441f0006a41106a20044190016a41106a290300370300200441f0006a41086a20044190016a41086a2903003703002004200429039001370370200741246a210141002106200e2103410021020b0240024020020d00200441fc096a200441f0006a41086a290300370200200441840a6a200441f0006a41106a2903003702002004418c0a6a200441f0006a41186a290300370200200420013602f009200420033602ec092004200d3602e8092004200a3602e409200420063602e009200420042903703702f409200441e0016a20042903b001370300200441e8016a200441b0016a41086a290300370300200441f4016a4200370200200442003703d801200442003703c001200441d0e1c1003602f001200441003a00fc01200441fd016a20042900900137000020044185026a20044190016a41086a2900003700002004418d026a20044190016a41106a29000037000020044195026a20044190016a41186a290000370000200441003a009d02200441e0096a200441c0016a10800221020c010b200441d8016a4200370300200441d4016a41d0e1c100360200200441003602e001200441003602d001200442003703c801200441d0e1c1003602c401200441003602c001200a200341e0006c6a41e8026a2102200441c0016a10f4010b200441c0016a41186a200441d0006a41186a290300370300200441c0016a41106a200441d0006a41106a290300370300200441c0016a41086a200441d0006a41086a290300370300200420042903503703c00120042009370294012004200b36029001200441e0096a200241306a200441c0016a20044190016a108102024020042802e009450d0020042802e4092202450d00200441e8096a280200450d002002102c0b2007200728021841016a360218410421020c070b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b103a000b41f089c6004110200441c0016a41f882c100103b000b1033000b20002002360200200441c00c6a24000b970302017f027e230041c0006b22042400024002402003450d0020022802000d0020022802042103200441186a4200370300200441106a4200370300200441086a420037030020012802182202420020022903082205427f20012802102903482206420586200642ffffffffffffffff07832006521b7d2206200620055622021b3703082004420037030002400240024020020d00024002402001280214280208200320044120101e41026a220241024b0d0020020e03020001020b41ac91c600412841d491c6001036000b200441206a2001280200280218220241186a200241d0006a2002410c6a4100200228020c1b200410fb012004280220450d01200441306a41086a2203200441206a41086a28020036020020042004290320370330200141046a21020240200141086a280200450d002002280200102c0b20022004290330370200200241086a2003280200360200410021010c020b200041053602000c030b2001410c6a4100360200410121010b20004100360200200020013602040c010b41b5abc50041f4031054000b200441c0006a24000ba20b05017f017e057f047e027f230041c0016b22042400024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d06200241286a2903002105200241346a2802002103200241c4006a2802002106200241d4006a2802002107200241e4006a2802002108200441d0006a20012002280204200241146a28020010ec04200441f8006a41086a2202200441d9006a290000370300200441f8006a41106a2209200441e1006a290000370300200441f8006a41186a220a200441e9006a29000037030020042004290051370378024020042d00504101460d00200441306a41186a200a290300370300200441306a41106a2009290300370300200441306a41086a200229030037030020042004290378370330200441186a20012003200610ee042004290318a70d00200441186a41106a290300210b2004290320210c200441086a200128021029034842002008ad420010e0052001280218220242002002290308220d427f200429030820042903104200521b7d220e200e200d5622021b37030820020d00200141046a21060240024020082001410c6a220928020022034b0d00200821020c010b02400240200141086a280200220220036b200820036b220f490d002006280200210a200321020c010b2003200f6a220a2003490d0b20024101742210200a2010200a4b1b22104100480d0b0240024020020d002010102a210a0c010b200628020020022010102e210a0b200a450d0a2001200a360204200141086a20103602002001410c6a28020021020b200a20026a211002400240200f4102490d002010410020082003417f7322036a220f10da051a200a200820026a20036a6a2110200f20026a21020c010b200f450d010b201041003a0000200241016a21020b20092002360200024002402001280214280208200720012802042002101e41026a220241024b0d0020020e03020001020b41ac91c600412841d491c6001036000b2001410c6a2202280200210a20024100360200200141086a2802002103200128020421092001420137020420012802182202290308220e210d024002402005500d002005210d200e2005540d010b2002200e200d7d37030820022903102105200441f8006a41186a200241186a2903003703002004200d370380012004200d370378200420053703880120012802002802182108200441d0006a41186a200441306a41186a290300370300200441d0006a41106a200441306a41106a290300370300200441d0006a41086a200441306a41086a290300370300200420042903303703502004200a3602b801200420033602b401200420093602b00120044198016a2008200441d0006a200c200b200441f8006a200441b0016a10e20241012107024002402004280298014101460d0020044198016a410472210920044198016a41106a2d0000210a200441a4016a2802002108200441a0016a2802002103410021070c010b200441a4016a2109200441ac016a280200210820044198016a41106a28020021034100210a0b20092802002109200220042903800120022903087c370308200141086a2802002102024020070d0002402002450d002006280200102c0b200620093602000c0c0b2002450d002006280200102c0b20062009360200418002210a410021080c0a0b200041053602000c0a0b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b1033000b1035000b2001410c6a2008360200200141086a2003360200200041003602002000200a3602040b200441c0016a24000bbd0c05017f017e057f047e037f230041d0016b220424000240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d06200241286a2903002105200241346a2802002103200241c4006a2802002106200241d4006a2802002107200241e4006a280200210820044198016a20012002280204200241146a28020010ed04200441e0006a41086a2202200441a1016a290000370300200441e0006a41106a2209200441a9016a290000370300200441e0006a41186a220a200441b1016a29000037030020042004290099013703600240024020042d0098014101460d00200441286a41186a200a290300370300200441286a41106a2009290300370300200441286a41086a200229030037030020042004290360370328200441106a20012003200610ee042004290310a70d00200441106a41106a290300210b2004290318210c2004200128021029034842002008ad420010e0052001280218220242002002290308220d427f200429030020042903084200521b7d220e200e200d5622021b37030820020d00200141046a210a0240024020082001410c6a220628020022034b0d00200821020c010b02400240200141086a280200220220036b200820036b220f490d00200a2802002109200321020c010b2003200f6a22092003490d0c200241017422102009201020094b1b22104100480d0c0240024020020d002010102a21090c010b200a28020020022010102e21090b2009450d0b20012009360204200141086a20103602002001410c6a28020021020b200920026a211002400240200f4102490d002010410020082003417f7322036a220f10da051a2009200820026a20036a6a2110200f20026a21020c010b200f450d010b201041003a0000200241016a21020b20062002360200024002402001280214280208200720012802042002101e41026a220241024b0d0020020e03020001020b41ac91c600412841d491c6001036000b2001410c6a2202280200210920024100360200200141086a2802002103200128020421062001420137020420012802182202290308220e210d0240024002402005500d002005210d200e2005540d010b2002200e200d7d37030820022903102105200441e0006a41186a200241186a2903003703002004200d3703682004200d370360200420053703702001280200280218210820042009360288012004200336028401200420063602800120044198016a2008200c200b200441e0006a200441286a20044180016a10dd0241012109024002402004280298014101460d0020044180016a41086a20044198016a41186a29030037030020044180016a41106a200441b8016a280200360200200420044198016a41106a29030037038001200441c8016a2d00002108200441c0016a2802002107200441bc016a280200210f200441a4016a280200211020044198016a41086a280200210341002109200428029c0121060c010b200441ac016a2802002110200441a8016a2802002103200441a4016a2802002106410021080b2002200429036820022903087c370308200441c8006a41086a220220044180016a41086a290300370300200441c8006a41106a221120044180016a41106a2802003602002004200429038001370348024020090d00200441ac016a2002290300370200200441b4016a2011280200360200200420103602a0012004200336029c012004200636029801200420042903483702a4010240200141086a280200450d00200a280200102c0b2001200f3602042001410c6a4100360200200141086a2007360200200841ff017122020d0220044198016a200a1091010c020b200141086a280200450d00200a280200102c0b200120063602042001410c6a4100360200200141086a200336020041800221020b20004100360200200020023602040c010b200041053602000b200441d0016a24000f0b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b1033000b1035000ba00503027f037e057f230041206b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441106a20012802102903184200200241146a2802002203ad2206420010e00520012802182202420020022903082207427f200429031020042903184200521b7d2208200820075622021b370308024020020d002004200128021029034842002006420010e00520012802182202420020022903082207427f200429030020042903084200521b7d2208200820075622021b37030820020d000240024020032001410c6a2209280200220a4b0d00200321020c010b02400240200141086a2802002202200a6b2003200a6b220b490d002001280204210c200a21020c010b200a200b6a220c200a490d062002410174220d200c200d200c4b1b220d4100480d060240024020020d00200d102a210c0c010b20012802042002200d102e210c0b200c450d052001200c360204200141086a200d3602002001410c6a28020021020b200c20026a210d02400240200b4102490d00200d41002003200a417f73220a6a220b10da051a200c200320026a200a6a6a210d200b20026a21020c010b200b450d010b200d41003a0000200241016a21020b20092002360200024002402001280214280208200520012802042002101e41026a220241024b0d0020020e03020001020b41ac91c600412841d491c6001036000b2001410c6a2202280200210320024100360200200141086a280200210220012802042105200142013702040240200128021c220a450d00200141206a280200450d00200a102c0b2001200536021c200141246a2003360200200141206a20023602000b20004105360200200441206a24000f0b41b5abc50041f4031054000b41b5abc50041f4031054000b1033000b1035000b23002001410c6a4100360200200128020041206a200141046a109101200041043602000b27002001410c6a4100360200200128020028021841d0006a200141046a109101200041043602000bd10102027f027e410021042001410c6a41003602002001280218220541186a2903002106200529031021070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102a21050c010b200128020420052004102e21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b1033000b1035000bbe0103017f017e017f410021042001410c6a4100360200200128021829030821050240024002400240200141086a28020022064108490d00200128020421060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102a21060c010b200128020420062004102e21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441086a360200200620046a2005370000200041043602000f0b1033000b1035000bb404020b7f027e230041206b220424002001410c6a41003602000240024002402001280200280218220528021841016a220641004c0d00200541d0006a2107200520063602182005411c6a2108200541206a28020021090240024003402008280200220a41086a210b200a2f0106220c41057421084100210d0240024003402008450d012007200b412010dd05220e450d02200841606a2108200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a210c0b2009450d022009417f6a2109200a200c4102746a41880b6a21080c010b0b200a200d41e0006c6a220841c5036a310000200841e8026a290300220f200f50220b1ba7450d004200200841f8026a290300200b1b210f4200200841f0026a290300200b1b21100c010b200441086a200541286a28020020072005412c6a28020028021c110400200441106a290300210f20052802182106200429030821100b20052006417f6a36021802400240200141086a280200220b2001410c6a28020022086b4110490d002001280204210b0c010b200841106a220d2008490d03200b4101742208200d2008200d4b1b22084100480d0302400240200b0d002008102a210b0c010b2001280204200b2008102e210b0b200b450d022001200b360204200141086a20083602002001410c6a28020021080b2001410c6a200841106a360200200b20086a2208200f3700082008201037000020004104360200200441206a24000f0b41c689c6004118200441186a418883c100103b000b1033000b1035000bd10102027f027e410021042001410c6a41003602002001280200220541086a2903002106200529030021070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102a21050c010b200128020420052004102e21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b1033000b1035000b900302047f027e230041c0006b220424000240024002402003450d0020022802000d0020034101460d0120022802100d01410521050240200241146a28020022032001280210220628026c4b0d0020022802042107200441086a200629034842002003ad420010e00520012802182202420020022903082208427f200429030820042903104200521b7d2209200920085622021b37030820020d002003417f4c0d0302400240024020030d004101210202402001280214280208200741014100101e41026a220641024b0d0020060e03040002040b41ac91c600412841d491c6001036000b0240200310302202450d0002402001280214280208200720022003101e41026a220641024b0d0020060e03030002030b41ac91c600412841d491c6001036000b1033000b2001410c6a4100360200200441186a2002200310b002410421052004200141046a36023c200441186a2004413c6a1094022003450d010b2002102c0b20002005360200200441c0006a24000f0b41b5abc50041f4031054000b41b5abc50041f4031054000b103a000bbe0103017f017e017f410021042001410c6a4100360200200128020029031021050240024002400240200141086a28020022064108490d00200128020421060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102a21060c010b200128020420062004102e21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441086a360200200620046a2005370000200041043602000f0b1033000b1035000bd80102027f027e410021042001410c6a4100360200200128020028021828024022054180016a2903002106200529037821070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102a21050c010b200128020420052004102e21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b1033000b1035000bba0803027f047e027f23004180056b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441286a20012802102903484200200241146a2802002202ad420010e00520012802182203420020032903082206427f200429032820042903304200521b7d2207200720065622031b3703080240024020030d002002417f4c0d0402400240024020020d004101210302402001280214280208200541014100101e41026a220541024b0d0020050e03040002040b41ac91c600412841d491c6001036000b200210302203450d0802402001280214280208200520032002101e41026a220541024b0d0020050e03020001020b41ac91c600412841d491c6001036000b2004200236023c20042003360238200441e8036a200441386a108f02024020042802e80322054118460d00200441d8026a200441e8036a410472418c0110db051a02402002450d002003102c0b200441c8016a200441d8026a418c0110db051a20042005360238200441386a410472200441c8016a418c0110db051a200441003602f003200442013703e803200441386a200441e8036a108b0120042802f0032103024020042802ec03450d0020042802e803102c0b200128021822022903102206200241186a2903002207844200510d07200441186a2003ad42004280c8afa025420010e005200441086a200429031822084280a094a58d1d7c2209200441186a41086a2903002009200854ad7c2006200710e10520024200200229030822062004290308427f200441086a41086a290300501b7d220720072006561b37030820072006580d03200441386a1092020c020b2002450d010b2003102c0b410521020c070b20012802002102200441d8026a200441386a41900110db051a200441c8016a41086a2002280218220241d8006a290000370300200441d8016a2203200241e0006a290000370300200441e0016a2205200241e8006a290000370300200420022900503703c801200441ef036a200441d8026a41900110db051a02402002413c6a2802002201200241386a280200470d00200141016a220a2001490d062001410174220b200a200b200a4b1b220aad42b8017e2206422088a70d062006a7220b4100480d060240024020010d00200b102a21010c010b2002280234200141b8016c200b102e21010b2001450d0520022001360234200241386a200a360200200228023c21010b2002280234200141b8016c6a220141013a0000200120042903c801370001200141096a200441d0016a290300370000200141116a2003290300370000200141196a2005290300370000200141216a200441e8036a41970110db051a2002200228023c41016a36023c410421020c060b41b5abc50041f4031054000b41b5abc50041f4031054000b103a000b41b0c5c100411941d890c2001036000b1033000b1035000b2000200236020020044180056a24000bce0f030c7f047e027f23004180026b220424000240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620034107460d0720022802700d07200241246a2802002105200241346a2802002106200241c4006a2802002107200241d4006a2802002108200241e4006a2802002109200241f4006a280200210a200441e0006a20012002280204200241146a28020010ec04200441e0016a41086a2203200441e9006a220b290000370300200441e0016a41106a220c200441f1006a220d290000370300200441e0016a41186a220e200441f9006a220f290000370300200420042900613703e0014105210220042d00604101460d0b200441206a41186a200e290300370300200441206a41106a200c290300370300200441206a41086a2003290300370300200420042903e001370320200441e0006a20012005200610ed042003200b290000370300200c200d290000370300200e200f290000370300200420042900613703e00120042d00604101460d0b200441c0006a41186a200441e0016a41186a290300370300200441c0006a41106a200441e0016a41106a290300370300200441c0006a41086a200441e0016a41086a290300370300200420042903e001370340200441086a20012007200810ee0420042802080d0b200441086a41106a29030021102004290310211102400240200a0d00410121054100210c4100210e0c010b200441e0016a41186a2103200441e0016a41106a2106200441e0016a41086a210b4100210f410021024100210c4100210e4101210503402003420037030020064200370300200b42003703002001280218220d4200200d2903082212427f20012802102903482213420586201342ffffffffffffffff07832013521b7d22132013201256220d1b370308200442003703e001200d0d0c024002402001280214280208200920026a220d200441e0016a4120101e41026a220741024b0d0020070e030e00010e0b41ac91c600412841d491c6001036000b200441e0006a41186a22082003290300370300200441e0006a41106a22142006290300370300200441e0006a41086a2215200b290300370300200420042903e0013703600240200c200e470d00200f200c41016a220e200f200e4b1b220e41ffffff3f71200e470d0c200e41057422074100480d0c02400240200c0d002007102a21050c010b200520022007102e21050b2005450d0b0b200520026a22072004290360370000200741186a2008290300370000200741106a2014290300370000200741086a2015290300370000200d41206a200d490d0c200f41026a210f200241206a2102200a200c41016a220c470d000b0b20012802002802182103200441c0016a41086a2201200441206a41086a290300370300200441c0016a41106a2206200441206a41106a290300370300200441c0016a41186a220b200441206a41186a290300370300200441e0016a41086a220d200341d8006a290000370300200441e0016a41106a220f200341e0006a290000370300200441e0016a41186a2207200341e8006a290000370300200420042903203703c001200420032900503703e001200441a0016a41186a2208200441c0006a41186a290300370300200441a0016a41106a220a200441c0006a41106a290300370300200441a0016a41086a2209200441c0006a41086a290300370300200420042903403703a00102402003413c6a2802002202200341386a280200470d00200241016a22142002490d0a200241017422152014201520144b1b2214ad42b8017e2213422088a70d0a2013a722154100480d0a0240024020020d002015102a21020c010b2003280234200241b8016c2015102e21020b2002450d0920032002360234200341386a2014360200200328023c21020b2003280234200241b8016c6a220241023a0000200220042903e001370001200220042903c001370021200241096a200d290300370000200241116a200f290300370000200241196a2007290300370000200241296a2001290300370000200241316a2006290300370000200241396a200b290300370000200220053600642002200e3600682002200c36006c20022011370370200241f8006a2010370300200220042903a001370041200241c9006a2009290300370000200241d1006a200a290300370000200241d9006a2008290300370000200220042f009d013b0061200241e3006a2004419d016a41026a2d00003a0000200220042903603703800120024188016a200441e0006a41086a29030037030020024190016a200441e0006a41106a29030037030020024198016a200441e0006a41186a290300370300200241a0016a20044180016a290300370300200241a8016a20044188016a290300370300200241b0016a20044190016a2903003703002003200328023c41016a36023c410421020c0b0b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b1033000b1035000b41052102200e450d002005102c0b2000200236020020044180026a24000b16002000410036020020002001410c6a2802003602040bb20202057f027e230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d024105210302402001410c6a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d0020022802042107200128020421082004200128021029035042002005ad420010e00520012802182202420020022903082209427f200429030020042903084200521b7d220a200a20095622021b37030820020d000240024020012802142802082007200820066a2005101f41026a220241024b0d0020020e03020001020b41ac91c600412841a892c6001036000b410421030b20002003360200200441106a24000f0b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000bfc0303027f027e067f230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002203ad420010e00520012802182202420020022903082206427f200429030020042903084200521b7d2207200720065622021b37030841052108024020020d000240024020032001410c6a2209280200220a4b0d00200321020c010b02400240200141086a2802002202200a6b2003200a6b220b490d002001280204210c200a21020c010b200a200b6a220c200a490d062002410174220d200c200d200c4b1b220d4100480d060240024020020d00200d102a210c0c010b20012802042002200d102e210c0b200c450d052001200c360204200141086a200d3602002001410c6a28020021020b200c20026a210d02400240200b4102490d00200d41002003200a417f73220a6a220b10da051a200c200320026a200a6a6a210d200b20026a21020c010b200b450d010b200d41003a0000200241016a21020b20092002360200024002402001280214280208200520012802042002101e41026a220141024b0d0020010e03020001020b41ac91c600412841d491c6001036000b410421080b20002008360200200441106a24000f0b41b5abc50041f4031054000b41b5abc50041f4031054000b1033000b1035000bc60b05047f027e037f027e027f230041f0016b220424000240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d03200241246a2802002105200241346a280200210602400240024002400240200241146a2802002203450d0020022802042107200441386a200128021029034842002003ad420010e00520012802182202420020022903082208427f200429033820042903404200521b7d22092009200856220a1b37030841052102200a0d0d2003417f4c0d0920031030220a450d0a024020012802142802082007200a2003101e41026a220741024b0d0020070e03040002040b41ac91c600412841d491c6001036000b4101210b410021074100210c0c010b2004200336029c012004200a36029801200441c8006a20044198016a108201200441d0006a2802002107200429024c2108200428024c210c2004280248210b200a102c200b450d0b200128021028025c2008422088a7490d0a0b200b2007410041202007676b108903024020074102490d00200b21022007210303402002200241206a220a412010dd05450d0b200a21022003417f6a220341024f0d000b0b200441286a200128021029034842002006ad220d420010e00520012802182202420020022903082208427f200429032820042903304200521b7d2209200920085622021b37030820020d092006417f4c0d060240024020060d004101210a02402001280214280208200541014100101e41026a220241024b0d0020020e030c00020c0b41ac91c600412841d491c6001036000b20061030220a450d080240024020012802142802082005200a2006101e41026a220241024b0d0020020e03010002010b41ac91c600412841d491c6001036000b200a102c0c0a0b200441086a2001280210220329032842002007ad420010e005200441186a20032903204200200d420010e00520012802182102427f2109024020042903204200520d0020042903104200520d002004290318220820042903087c220e2008540d00427f200e20032903307c22082008200e541b21090b200242002002290308220820097d220920092008561b37030820092008580d012006450d09200a102c0c090b200a102c0c090b200441c8016a41086a22062001280200280218220341d8006a290000370300200441c8016a41106a2201200341e0006a290000370300200441c8016a41186a2205200341e8006a290000370300200420032900503703c80102402003413c6a2802002202200341386a280200470d00200241016a220f2002490d0720024101742210200f2010200f4b1b220fad42b8017e2208422088a70d072008a722104100480d070240024020020d002010102a21020c010b2003280234200241b8016c2010102e21020b2002450d0620032002360234200341386a200f360200200328023c21020b2003280234200241b8016c6a220241003a0000200220042f00ed013b0001200241053a00102002200736000c2002200c3600082002200b360004200220042903c801370011200241036a200441ed016a41026a2d00003a0000200241196a2006290300370000200241216a2001290300370000200241296a20052903003700002002200a3600342002200d422086200d84370038200220042f00c5013b0031200241336a200441c5016a41026a2d00003a00002002200429039801370340200241c8006a20044198016a41086a290300370300200241d0006a20044198016a41106a290300370300200241d8006a20044198016a41186a290300370300200241e0006a200441b8016a290300370300200241e8006a200441c8006a41d00010db051a2003200328023c41016a36023c410421020c080b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b41b5abc50041f4031054000b103a000b1033000b1035000b41052102200c450d00200b102c0b20002002360200200441f0016a24000bbe0803027f027e057f230041f00b6b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d01200441086a20012002280204200241146a28020010ee044105210202402004290308a70d00200128020028021822052802180d03200441186a2903002106200429031021072005417f360218200441d8006a200541e8006a290000370300200441d0006a200541e0006a290000370300200441c8006a200541d8006a29000037030020042005290050370340024002402005411c6a2208280200220941d0e1c100460d00200541206a280200210a0c010b4100210a20044190096a410041e00210da051a200441f0006a410041a00810da051a41880b102a2209450d05200941003b010620094100360200200941086a20044190096a41e00210db051a200941e8026a200441f0006a41a00810db051a200541206a41003602002005200936021c0b02400240034020092f0106220b410574210c4100210241002103024002400340200c2002460d01200441c0006a200920026a41086a412010dd052201450d02200241206a2102200341016a21032001417f4a0d000b2003417f6a210b0b200a450d02200a417f6a210a2009200b4102746a41880b6a28020021090c010b0b200541246a2101410121020c010b200441206a41186a200441c0006a41186a290300370300200441206a41106a200441c0006a41106a290300370300200441206a41086a200441c0006a41086a29030037030020042004290340370320200541246a21014100210a200b2103410021020b0240024020020d00200441ac096a200441206a41086a290300370200200441b4096a200441206a41106a290300370200200441bc096a200441206a41186a290300370200200420013602a0092004200336029c09200420083602980920042009360294092004200a36029009200420042903203702a40920044190016a200429036037030020044198016a200441e0006a41086a290300370300200441a4016a4200370200200442003703880120044200370370200441d0e1c1003602a001200441003a00ac01200441ad016a2004290040370000200441b5016a200441c0006a41086a290000370000200441bd016a200441c0006a41106a290000370000200441c5016a200441c0006a41186a290000370000200441003a00cd0120044190096a200441f0006a10800221020c010b20044188016a420037030020044184016a41d0e1c1003602002004410036029001200441003602800120044200370378200441d0e1c100360274200441003602702009200341e0006c6a41e8026a2102200441f0006a10f4010b200241286a2006370300200241206a2007370300200242013703182005200528021841016a360218410421020b20002002360200200441f00b6a24000f0b41b5abc50041f4031054000b41b5abc50041f4031054000b41f089c6004110200441f0006a41f882c100103b000b1033000b9f0203037f027e027f230041206b220424002001410c6a22054100360200200441086a2001280200280218220641186a200641d0006a10fe01200441086a41106a290300210720042802082106200429031021080240024002400240200141086a2802002209200528020022056b4110490d00200128020421090c010b200541106a220a2005490d0220094101742205200a2005200a4b1b22054100480d020240024020090d002005102a21090c010b200128020420092005102e21090b2009450d0120012009360204200141086a20053602002001410c6a28020021050b2001410c6a200541106a360200200920056a22012007427f20061b37000820012008427f20061b37000020004104360200200441206a24000f0b1033000b1035000bf00203027f027e017f230041206b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002202ad420010e00520012802182203420020032903082206427f200429030020042903084200521b7d2207200720065622081b37030841052103024020080d002002417f4c0d0302400240024020020d004101210802402001280214280208200541014100101e41026a220141024b0d0020010e03040002040b41ac91c600412841d491c6001036000b0240200210302208450d0002402001280214280208200520082002101e41026a220141024b0d0020010e03030002030b41ac91c600412841d491c6001036000b1033000b200441106a200820021058024020042802100d00200429021410040b410421032002450d010b2008102c0b20002003360200200441206a24000f0b41b5abc50041f4031054000b41b5abc50041f4031054000b103a000bba0101037f410021042001410c6a4100360200200128020028021c21050240024002400240200141086a28020022064104490d00200128020421060c010b200641017422044104200441044b1b22044100480d020240024020060d002004102a21060c010b200128020420062004102e21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441046a360200200620046a2005360000200041043602000f0b1033000b1035000bea0503027f027e067f230041306b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002203ad420010e00520012802182202420020022903082206427f200429030020042903084200521b7d2207200720065622021b3703080240024020020d00200141046a21080240024020032001410c6a2209280200220a4b0d00200321020c010b02400240200141086a2802002202200a6b2003200a6b220b490d002008280200210c200a21020c010b200a200b6a220c200a490d072002410174220d200c200d200c4b1b220d4100480d070240024020020d00200d102a210c0c010b20082802002002200d102e210c0b200c450d062001200c360204200141086a200d3602002001410c6a28020021020b200c20026a210d02400240200b4102490d00200d41002003200a417f73220a6a220b10da051a200c200320026a200a6a6a210d200b20026a21020c010b200b450d010b200d41003a0000200241016a21020b20092002360200024002402001280214280208200520012802042002101e41026a220241024b0d0020020e03020001020b41ac91c600412841d491c6001036000b2001410c6a2202350200210620024100360200200141086a220328020021052001280204210220014201370204200441106a20064220862002ad841003108d010240024020042802100d0002402003280200450d002008280200102c0b200120023602042001410c6a4100360200200141086a2005360200410121010c010b200441206a41086a200441106a41086a2802003602002004200429031037032002402003280200450d002008280200102c0b20082004290320370200200841086a200441206a41086a280200360200410021012005450d002002102c0b20004100360200200020013602040c010b200041053602000b200441306a24000f0b41b5abc50041f4031054000b41b5abc50041f4031054000b1033000b1035000b9605020a7f017e230041c0006b220424002004200136020c20042000410120011b3602082004200441086a1075024020042802000d00024002400240200428020c22014170712200417f4c0d002004280204210502400240200141047622060d00410821070c010b2000102a2207450d020b02402005450d00200441206a4104722108410021094100210a410021000340200441206a200441086a10ae03200441306a41086a220b200841086a2802003602002004200829020037033002402004280220220c4104470d002006450d062007102c0c060b200041016a2101200441106a41086a220d200b28020036020020042004290330370310024020002006470d0020092001200920014b1b220641ffffffff00712006470d052006410474220b4100480d050240024020000d00200b102a21070c010b2007200a200b102e21070b2007450d040b2007200a6a2200200c360200200041046a20042903103702002000410c6a200d280200360200200941026a2109200a41106a210a2001210020052001470d000b0b2007450d03200441206a2002200720052003110600200428022021004101102a2201450d012004428180808010370234200420013602300240024020004105460d00200141003a0000200141014102102e2101024020004104470d002001450d04200141003a00012004428280808020370234200420013602304202210e0c020b2001450d03200141013a0001200442828080802037023420042001360230200441206a200441306a10ac042004350238210e200428023021010c010b200141013a00004201210e0b2001ad422086200e84210e02402006450d002007102c0b200441c0006a2400200e0f0b103a000b1033000b1035000b41c8ebc30041f000200441206a4194ebc300103b000bde0202047f017e02400240024002400240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a3602002004417f6a220441034b0d0520040e0401020304010b200041043602000f0b0240200541034b0d00200041043602000f0b200041003602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b024020054108490d0020004101360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b0240200541034b0d00200041043602000f0b200041023602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b024020054108490d0020004103360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b200041043602000bca1002077f027e230041106b220224002002410036020820024201370300410420021067024002400240024020022802042203200228020822046b4104490d00200441046a2105200228020021030c010b200441046a22052004490d02200341017422062005200620054b1b22064100480d020240024020030d002006102a21030c010b200228020020032006102e21030b2003450d0120022006360204200220033602000b20022005360208200320046a41eede91ab06360000410e200210670240024020022802042205200228020822066b410e490d002006410e6a2104200228020021030c010b2006410e6a22042006490d02200541017422032004200320044b1b22074100480d020240024020050d002007102a21030c010b200228020020052007102e21030b2003450d012002200736020420022003360200200721050b20022004360208200320066a220641002900f3ec41370000200641066a41002900f9ec413700000240200520046b41034b0d00200441046a22062004490d02200541017422072006200720064b1b22064100480d020240024020050d002006102a21030c010b200320052006102e21030b2003450d0120022006360204200220033602000b2002200441046a360208200320046a410a3600000240024020022802042203200228020822046b4104490d00200228020021030c010b200441046a22052004490d02200341017422062005200620054b1b22054100480d020240024020030d002005102a21030c010b200228020020032005102e21030b2003450d0120022005360204200220033602000b2002200441046a360208200320046a41c6013600000240024020022802042203200228020822046b4104490d00200228020021030c010b200441046a22052004490d02200341017422062005200620054b1b22054100480d020240024020030d002005102a21030c010b200228020020032005102e21030b2003450d0120022005360204200220033602000b2002200441046a360208200320046a41c601360000410c200210674184edc1002104034020042d0000210602400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422072005200720054b1b22074100480d030240024020030d002007102a21050c010b200228020020032007102e21050b2005450d0220022007360204200220053602000b2002200341016a360208200520036a20063a0000200441016a2d0000210602400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422072005200720054b1b22074100480d030240024020030d002007102a21050c010b200228020020032007102e21050b2005450d0220022007360204200220053602000b2002200341016a360208200520036a20063a0000200441026a2d0000210602400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422072005200720054b1b22074100480d030240024020030d002007102a21050c010b200228020020032007102e21050b2005450d0220022007360204200220053602000b2002200341016a360208200520036a20063a0000200441036a2d0000210602400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422072005200720054b1b22074100480d030240024020030d002007102a21050c010b200228020020032007102e21050b2005450d0220022007360204200220053602000b2002200341016a360208200520036a20063a0000200441046a2d0000210602400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422072005200720054b1b22074100480d030240024020030d002007102a21050c010b200228020020032007102e21050b2005450d0220022007360204200220053602000b2002200341016a360208200520036a20063a0000200441056a2d0000210602400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422072005200720054b1b22074100480d030240024020030d002007102a21050c010b200228020020032007102e21050b2005450d0220022007360204200220053602000b2002200341016a360208200520036a20063a0000200441066a2d0000210602400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422072005200720054b1b22074100480d030240024020030d002007102a21050c010b200228020020032007102e21050b2005450d0220022007360204200220053602000b2002200341016a360208200520036a20063a0000200441076a2d0000210602400240200228020420022802082203460d00200228020021050c010b200341016a22052003490d03200341017422072005200720054b1b22074100480d030240024020030d002007102a21050c010b200228020020032007102e21050b2005450d0220022007360204200220053602000b2002200341016a360208200520036a20063a0000200441086a28020021060240024020022802042205200228020822036b4104490d00200228020021050c010b200341046a22072003490d03200541017422082007200820074b1b22074100480d030240024020050d002007102a21050c010b200228020020052007102e21050b2005450d0220022007360204200220053602000b2002200341046a360208200520036a20063600002004410c6a22044194eec100470d000b200235020821092002350200210a200241106a2400200a2009422086840f0b1033000b1035000b9a1c05037f017e047f037e037f230041a00a6b22022400024002402001450d00200220003602100c010b200241013602100b20022001360214200241f8076a200241106a10b1030240024020022802fc07450d00200241186a200241f8076a41fc0010db051a20024198016a200241186a41fc0010db051a20024198016a10b20302402002280298012201450d00200241f8076a2001417f6a109302200241f8076a200241a8016a412010dd050d000240024020024190026a28020022030d004100210341042104410021010c010b024002402003ad420c7e2205422088a70d002005a722014100480d0020022802880221002001102a22040d011033000b1035000b200341a8026c210620034103742107200421010340200220003602c004200241f8076a200241c0046a108701200141086a200241f8076a41086a280200360200200120022903f8073702002001410c6a2101200041a8026a2100200641d87d6a22060d000b200741786a41037641016a21010b200220013602c804200220033602c404200220043602c004200241f8076a200241c0046a10b3030240200241e8016a2201200241f8076a412010dd05450d0041c18cc600ad4280808080e0018410042001ad42808080808004841015200241f8076aad428080808080048410150b02402001200241f8076a412010dd050d002002418c026a28020021082002280288022107200228029002210620024198026a20024198016a41f00010db051a2007200641a8026c6a2100200228029802210920072101024002402006450d00200241c0046a41f0006a210441eb8cc600ad4280808080d00184210a200721010240034020024190076a200141e80010db051a200141e8006a290300210520024188036a200141f0006a41b80110db051a20054203510d01200241c0046a20024190076a41e80010db051a200220053703a805200420024188036a41b80110db051a2002200241c0046a3602e806200241f8076a200241e8066a1087012002280280082106024020022802fc07450d0020022802f807102c0b200241f8076a200241c0046a41a80210db051a200241003602f806200241e8066a200241f8076a2006200241f8066a10b40320022d00e8064101460d03024020022d00f40622064102460d0020023100f606210520023100f506210b20023502f006210c20022802ec062103200a100402402006450d00200b100e0b2005100e2003450d00200c4220862003ad8410040b200141a8026a22012000470d000b200021010c010b200141a8026a21010b20012000460d0420024190096a2106200241f8076a41f0006a2103034020024188036a200141e80010db051a200141e8006a2903002105200241f8076a200141f0006a41b80110db051a20054203510d0520024190076a20024188036a41e80010db051a200241c0046a200241f8076a41b80110db051a200241f8076a20024190076a41e80010db051a200220053703e0082003200241c0046a41b80110db051a20061073200141a8026a22012000470d000c050b0b200241086a20022f00e90620022d00eb064110747210b5032002280208200228020c41acfec5001036000b41929ec500412441acfec5001036000b41f69dc500411c41acfec5001036000b20024194036a4104360200200241d4046a4102360200200242023702c40420024184adc2003602c0042002410436028c03200241fcacc200360288032002410036029c01200241dc9ec60036029801200220024188036a3602d004200220024198016a36029003200241c0046a4194adc2001041000b02402008450d002007102c0b20024181b0c2004110109401200228020421040240200228020022074101470d004181b0c200ad428080808080028410050b200241f8076a41186a22084200370300200241f8076a41106a22004200370300200241f8076a41086a22014200370300200242003703f807200241c0046a41086a22064191b0c200ad4280808080e000841002220341086a290000370300200220032900003703c0042003102c20012006290300370300200220022903c0043703f80720024188036a41086a220d41c8c2c200ad4280808080e001841002220341086a29000037030020022003290000370388032003102c2000200229038803220537030020062001290300370300200241c0046a41106a220e2005370300200241c0046a41186a220f200d2903003703002002200537039007200220022903f8073703c00420022004410020071b3602f807200241c0046aad4280808080800484220b200241f8076aad4280808080c000841001200842003703002000420037030020014200370300200242003703f80720024190076a41086a220341e4d2c500ad42808080808001841002220441086a29000037030020022004290000370390072004102c2001200329030037030020022002290390073703f807200341ecd2c500ad42808080808001841002220441086a29000037030020022004290000370390072004102c2000200229039007220537030020062001290300370300200e2005370300200f20032903003703002002200537038803200220022903f8073703c004200b1005200910ad02200241f8076a10b603200220024198026a410c6a280200220336028807200228029c0221072002200241f8076a410c6a280200220136028c07024020032001470d0002402003450d0020022802fc0721084100210641eadbc200ad4280808080c002842105034002400240024002400240024002400240200720066a22012d00002204200820066a22002d0000470d000240024002400240024020040e050001020304000b20012000460d09200141016a200041016a412010dd050d040c090b024020012000460d00200141016a280000200041016a280000470d040b200141106a2802002204200041106a280200470d03200141086a2802002209200041086a280200220d460d072009200d200410dd050d030c070b024020012000460d00200141016a280000200041016a280000470d030b200141106a2802002204200041106a280200470d02200141086a2802002209200041086a280200220d460d052009200d200410dd050d020c050b024020012000460d00200141016a280000200041016a280000470d020b200141106a2802002204200041106a280200470d01200141086a2802002209200041086a280200220d460d032009200d200410dd050d010c030b2001410c6a28020022042000410c6a280200470d00200141046a2802002209200041046a280200220d460d012009200d200410dd05450d010b20051004200241c0046a200110e70220023502c80442208620022802c0042204ad841015024020022802c404450d002004102c0b200241c0046a200010e70220023502c80442208620022802c0042204ad841015024020022802c404450d002004102c0b20012d000020002d00002204470d0520040e050403020100040b2001410c6a28020022042000410c6a280200470d04200141046a2802002201200041046a2802002200460d0520012000200410dd050d040c050b024020012000460d00200141016a280000200041016a280000470d040b200141106a2802002204200041106a280200470d03200141086a2802002201200041086a2802002200460d0420012000200410dd05450d040c030b024020012000460d00200141016a280000200041016a280000470d030b200141106a2802002204200041106a280200470d02200141086a2802002201200041086a2802002200460d0320012000200410dd050d020c030b024020012000460d00200141016a280000200041016a280000470d020b200141106a2802002204200041106a280200470d01200141086a2802002201200041086a2802002200460d0220012000200410dd050d010c020b20012000460d01200141016a200041016a412010dd05450d010b41c09ec500412741acfec5001036000b200641246a21062003417f6a22030d000b0b024020024198026a41306a2201200241f8076a41306a2200412010dd05450d0041c18cc600ad4280808080e0018410042001ad428080808080048410152000ad428080808080048410150b024020012000412010dd05450d0041e79ec500412841acfec5001036000b02402002280284082200450d0020022802fc072101200041246c210003400240024020012d0000220641034b0d0002400240024020060e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012000415c6a22000d000b0b024020024180086a280200450d0020022802fc07102c0b024020022802a4022200450d00200228029c022101200041246c210003400240024020012d0000220641034b0d0002400240024020060e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012000415c6a22000d000b0b0240200241a0026a280200450d00200228029c02102c0b200241a00a6a240042010f0b20024188036a41146a410936020020024188036a410c6a410c36020020024190076a41146a41033602002002420337029407200241ec9fc600360290072002410c36028c03200220024188076a3602f80620022002418c076a3602e806200242043703d004200242013702c404200241b89ec5003602c004200220024188036a3602a0072002200241c0046a360298032002200241e8066a360290032002200241f8066a3602880320024190076a4184c5c5001041000bdd05030c7f017e017f230041c0056b2202240020024198036a200110810102400240200228029c0322030d00200041003602040c010b200241a4036a280200210420022802a00321052002280298032106200241106a200241a8036a41e00010db051a200241086a20011075024020022802080d00024002400240200128020441a8026e220741a8026c2208417f4c0d00200228020c21090240024020080d004108210a0c010b2008102a220a450d020b024002402009450d004100210b410021084100210c034020024198036a2001108c022002290380044203510d02200c41016a210d200241f0006a20024198036a41a80210db051a0240200c2007470d00200b200d200b200d4b1b2207ad42a8027e220e422088a70d06200ea7220f4100480d0602400240200c0d00200f102a210a0c010b200a2008200f102e210a0b200a450d050b200a20086a200241f0006a41a80210db051a200b41026a210b200841a8026a2108200d210c2009200d470d000b0b200a450d0420024198036a200241106a41e00010db051a2000410c6a2004360200200020053602082000200336020420002006360200200041106a20024198036a41e00010db051a200041f8006a2009360200200041f4006a2007360200200041f0006a200a3602000c050b0240200c450d00200a4198016a210d0340200d1073200d41a8026a210d200841d87d6a22080d000b0b2007450d03200a102c0c030b103a000b1033000b1035000b2000410036020402402004450d00200441246c210d2003210803400240024020082d0000220c41034b0d00024002400240200c0e0404000102040b2008410c6a280200450d03200841086a280200102c0c030b2008410c6a280200450d02200841086a280200102c0c020b2008410c6a280200450d01200841086a280200102c0c010b200841086a280200450d00200841046a280200102c0b200841246a2108200d415c6a220d0d000b0b2005450d002003102c0b200241c0056a24000b9a740a0e7f027e017f037e1c7f017e027f0a7e017f027e230041d0066b2201240002400240024002400240024002402000410c6a28020041246c22020d004104210341002104410021050c010b200028020421064104210341002104410021050340024020062d00004101470d00200641106a2802002207417f4c0d03200641086a2802002108200641016a28000021090240024020070d004101210a4100210b0c010b2007210b2007102a220a450d060b200a2008200710db05210a20014180066a41026a220c200141d8056a41026a2d00003a0000200141b0046a41086a220d200141a8066a41086a290200370300200120012f00d8053b018006200120012902a8063703b004024020042005470d00200441016a22082004490d082004410174220e2008200e20084b1b2205ad42247e220f422088a70d08200fa722084100480d080240024020040d002008102a21030c010b2003200441246c2008102e21030b2003450d060b2003200441246c6a220841013a000020082009360001200820073600102008200b36000c2008200a360008200820012f0180063b0005200841076a200c2d00003a0000200820012903b0043702142008411c6a200d290300370200200441016a21040b200641246a21062002415c6a22020d000b0b200141003602b0044181b0c200ad4280808080800284200141b0046aad4280808080c0008422101001200141d8036a41186a22074200370300200141d8036a41106a22114200370300200141d8036a41086a22084200370300200142003703d803200141b0046a41086a22064191b0c200ad4280808080e00084220f1002220241086a290000370300200120022900003703b0042002102c20082006290300370300200120012903b00422123703f803200120123703d803200641acb0c200ad4280808080e000841002220241086a290000370300200120022900003703b0042002102c201120012903b0042212370300200141b8036a41086a22092008290300370300200141b8036a41106a220a2012370300200141b8036a41186a220b20062903003703002001201237038804200120012903d8033703b80320012000280200220d3602b004200141b8036aad4280808080800484221220101001200742003703002011420037030020084200370300200142003703d8032006200f1002220241086a290000370300200120022900003703b0042002102c20082006290300370300200120012903b00422133703f803200120133703d803200641cab0c200ad4280808080e000841002220241086a290000370300200120022900003703b0042002102c20072006290300221337030020092008290300370300200a20012903b0042214370300200b20133703002001201437038804200120012903d8033703b803200141203602b4042001200141b8036a3602b00420032004200141b0046a10da03200742003703002011420037030020084200370300200142003703d8032006200f1002220241086a290000370300200120022900003703b0042002102c20082006290300370300200120012903b00422133703f803200120133703d803200641b2b0c200ad4280808080a001841002220241086a290000370300200120022900003703b0042002102c20072006290300221337030020092008290300370300200a20012903b0042214370300200b20133703002001201437038804200120012903d8033703b803200141203602b4042001200141b8036a3602b004200041106a2215200141b0046a10be032006200f1002220241086a290000370300200120022900003703b0042002102c200141f8036a41086a22162006290300370300200120012903b0043703f803200641a3b0c200ad42808080809001841002220241086a290000370300200120022900003703b0042002102c20014188046a41086a220c2006290300370300200120012903b004370388042001200d417f6a3602b00420014180066a41186a220d20101006220241186a29000037030020014180066a41106a220e200241106a29000037030020014180066a41086a2217200241086a29000037030020012002290000370380062002102c2007200d2903003703002011200e2903003703002008201729030037030020012001290380063703d80341c000102a2202450d02200220012903f8033700002002200129038804370010200220012903d803370020200241086a2016290300370000200241186a200c290300370000200241286a2008290300370000200241306a2011290300370000200241386a2007290300370000200120023602b004200141c0003602b4042015200141b0046a10be032002102c200742003703002011420037030020084200370300200142003703d8032006200f1002220241086a290000370300200120022900003703b0042002102c20082006290300370300200120012903b00422103703f803200120103703d803200641bcb0c200ad4280808080e001841002220241086a290000370300200120022900003703b0042002102c200c20062903002210370300200120012903b00422133703880420112013370000201141086a2202201037000020092008290300370300200a2011290300370300200b2007290300370300200120012903d8033703b803200141203602b4042001200141b8036a3602b004200041d0006a200141b0046a10be03200742003703002011420037030020084200370300200142003703d8032006200f1002221541086a290000370300200120152900003703b0042015102c20082006290300370300200120012903b00422103703f803200120103703d803200641fdb1c200ad4280808080e000841002221541086a290000370300200120152900003703b0042015102c200c20062903002210370300200120012903b004221337038804201120133700002002201037000020092008290300370300200a2011290300370300200b2007290300370300200120012903d8033703b80320121005200742003703002011420037030020084200370300200142003703d8032006200f1002221541086a290000370300200120152900003703b0042015102c20082006290300370300200120012903b00422103703f803200120103703d803200641e4c4c200ad4280808080a001841002221541086a290000370300200120152900003703b0042015102c200c20062903002210370300200120012903b004221337038804201120133700002002201037000020092008290300370300200a2011290300370300200b2007290300370300200120012903d8033703b803201210052006200f1002220241086a290000370300200120022900003703b0042002102c20162006290300370300200120012903b0043703f80320064183b2c200ad4280808080b001841002220241086a290000370300200120022900003703b0042002102c200c2006290300370300200120012903b00437038804200d42011006220641186a290000370300200e200641106a2900003703002017200641086a29000037030020012006290000370380062006102c2007200d2903003703002011200e2903003703002008201729030037030020012001290380063703d80341c000102a2206450d02200620012903f8033700002006200129038804370010200620012903d803370020200641086a200141f8036a41086a290300370000200641186a20014188046a41086a290300370000200641286a200141d8036a41086a290300370000200641306a200141d8036a41106a290300370000200641386a200141d8036a41186a2903003700002006ad4280808080800884100d2006102c20002802002118200141a8066a41186a22094200370300200141a8066a41106a22064200370300200141a8066a41086a22084200370300200142003703a80620014198046a41086a22074191b0c200ad4280808080e000841002220241086a29000037030020012002290000370398042002102c2008200729030037030020012001290398043703a806200741b2b0c200ad4280808080a001841002220241086a29000037030020012002290000370398042002102c2006200129039804220f37030020014180066a41086a200829030037030020014180066a41106a200f37030020014180066a41186a20072903003703002001200f3703b004200120012903a80637038006200141b0046a20014180066a412010d30120012d00b00421072009200141c9046a2900003703002006200141c1046a2900003703002008200141b9046a290000370300200120012900b1043703a8060240024020074101460d00200141d8056a41186a4200370300200141d8056a41106a4200370300200141d8056a41086a4200370300200142003703d8050c010b200141d8056a41186a2009290300370300200141d8056a41106a2006290300370300200141d8056a41086a2008290300370300200120012903a8063703d8050b200141a8066a41186a22094200370300200141a8066a41106a220a4200370300200141a8066a41086a22024200370300200142003703a80620014198046a41086a220841c586c200ad42808080808003841002220741086a29000037030020012007290000370398042007102c2002200829030037030020012001290398043703a80620084193c6c100ad4280808080e001841002220741086a29000037030020012007290000370398042007102c200141b0046a41086a2008290300220f370300200120012903980422103703b00420062010370000200641086a200f37000020014180066a41086a200229030037030020014180066a41106a200a29030037030020014180066a41186a2009290300370300200120012903a80637038006200141b0056a20014180066a412010d0010240024002400240024020012802b00522070d002009200141d8056a41186a290300370300200a200141d8056a41106a2903003703002002200141d8056a41086a290300370300200120012903d8053703a8064101210741002102200141a8066a2106410021090c010b20012902b405220fa7210a0240200f422088a7220841d100490d00200141b0046a41186a2202200141d8056a41186a290300370300200141b0046a41106a2209200141d8056a41106a290300370300200141b0046a41086a220b200141d8056a41086a290300370300200120012903d8053703b0042018417f6a41d10070220620084f0d04200720064105746a220620012903b004370000200641186a2002290300370000200641106a2009290300370000200641086a200b290300370000200a21020c030b200141b0056a41086a280200210920012802b4052102200141a8066a41186a200141d8056a41186a290300370300200141a8066a41106a200141d8056a41106a290300370300200141a8066a41086a200141d8056a41086a290300370300200120012903d8053703a80602402008200a460d00200141a8066a2106200a2102200821090c020b200141a8066a210620022008470d010b200241016a22082002490d072002410174220a2008200a20084b1b220841ffffff3f712008470d072008410574220a4100480d070240024020020d00200a102a21070c010b20072002410574200a102e21070b2007450d05200821020b200720094105746a22082006290000370000200841186a200641186a290000370000200841106a200641106a290000370000200841086a200641086a290000370000200941016a21080b200141b0046a41186a4200370300200141b0046a41106a220b4200370300200141b0046a41086a22094200370300200142003703b00420014198046a41086a220641c586c200ad42808080808003841002220a41086a2900003703002001200a29000037039804200a102c2009200629030037030020012001290398043703b00420064193c6c100ad4280808080e001841002220a41086a2900003703002001200a29000037039804200a102c200b200129039804220f370300200141a8066a41086a2009290300370300200141a8066a41106a200f370300200141a8066a41186a20062903003703002001200f37038006200120012903b0043703a8060240024020070d00200141a8066aad428080808080048410050c010b200141003602b804200142013703b0042008200141b0046a106702402008450d00200841057421082007210603402001200141b0046a36028006200620014180066a109402200641206a2106200841606a22080d000b0b20012802b4042106200141a8066aad428080808080048420013502b80442208620012802b0042208ad84100102402006450d002008102c0b2002450d002007102c0b024020184180a70c700d0010cf010b02400240201841809c3170450d0020014180066a211920014188046a211a200141f8036a211b200141b0046a211c0c010b200141b0046a41186a4200370300200141b0046a41106a22024200370300200141b0046a41086a22084200370300200142003703b00420014198046a41086a220641bad6c500ad42808080809001841002220741086a29000037030020012007290000370398042007102c200820062903003703002001200129039804220f3703f8032001200f3703b004200641d0d6c500ad4280808080d002841002220741086a29000037030020012007290000370398042007102c2002200129039804220f37030020014180066a41086a200829030037030020014180066a41106a200f37030020014180066a41186a20062903003703002001200f37038804200120012903b004370380060240024020014180066a109501220641ff01714102460d0020014180066aad4280808080800484100520064101710d010b200141b0046a211c200141f8036a211b20014188046a211a20014180066a2119201810c904450d01201810cb041a0c010b200141b0046a211c200141f8036a211b20014188046a211a20014180066a2119201810cb04450d00201810c9041a0b200141b0046a41186a220c4200370300200141b0046a41106a221d4200370300200141b0046a41086a220a4200370300200142003703b00420014198046a41086a220641bad6c500ad4280808080900184220f1002220841086a29000037030020012008290000370398042008102c200141f8036a41086a2207200629030037030020012001290398043703f803201c41086a2202201b41086a2209290000370000201c201b290000370000200641c3d6c500ad4280808080d001841002220841086a29000037030020012008290000370398042008102c20014188046a41086a220b2006290300370300200120012903980437038804201d201a290000221037030020014180066a41086a2216200a29030037030020014180066a41106a2215201037030020014180066a41186a221e201a41086a220d290000370300200120012903b00437038006200141b0036a2019412010940120012802b403210e20012802b0032100200c4200370300201d4200370300200a4200370300200142003703b0042006200f1002220841086a29000037030020012008290000370398042008102c2007200629030037030020012001290398043703f80320022009290000370000201c201b290000370000200641abd6c500ad4280808080f001841002220841086a29000037030020012008290000370398042008102c200b2006290300370300200120012903980437038804200c200d290000220f3703002016200a2903003703002015201a290000370300201e200f370300200120012903b00437038006200141a8036a201941201094014100211f02400240200e410020001b220620012802ac03410020012802a8031b22074f0d00200141b0046a4104722108200141d9046a210b0340200141b0046a200610d704024020012d00d80422094103460d00200141a8066a41086a200841086a290200220f370300200141a8066a41106a200841106a2902002210370300200141a8066a41186a200841186a2902002212370300200141a8066a41206a200841206a2802002202360200200141b8036a41026a220d200b41026a2d00003a00002001200829020022133703a8062001200b2f00003b01b80320012802b004210e200a200f370300201d2010370300200c2012370300200141b0046a41206a22002002360200200120133703b004200141d8036a41026a2217200d2d00003a0000200120012f01b8033b01d803410321020240200e2018470d0020014180066a41206a2000280200360200201e200c2903003703002015201d2903003703002016200a29030037030020014198046a41026a20172d00003a0000200120012903b00437038006200120012f01d8033b01980420062120200921020b20024103470d030b2007200641016a2206470d000b0b41042121410021080c030b200141d8056a41206a20014180066a41206a2802002208360200200141d8056a41186a20014180066a41186a290300220f370300200141d8056a41106a20014180066a41106a2903002210370300200141d8056a41086a20014180066a41086a290300221237030020014188046a41026a220920014198046a41026a2d00003a0000200141b0056a41086a220a2012370300200141b0056a41106a220b2010370300200141b0056a41186a220c200f370300200141b0056a41206a220d20083602002001200129038006220f3703d805200120012f0198043b0188042001200f3703b005200141f8036a41026a220e20092d00003a0000200120012f0188043b01f8034130102a2221450d03410121082021201836020420212020360200202120012903b005370208202120023a002c202120012f01f8033b002d202141106a200a290300370200202141186a200b290300370200202141206a200c290300370200202141286a200d2802003602002021412f6a200e2d00003a00004101211f200641016a220620074f0d02200141b0046a4104722108200141d9046a210a02400340200141b0046a200610d704024020012d00d80422094103460d00200141a8066a41086a200841086a290200220f370300200141a8066a41106a200841106a2902002210370300200141a8066a41186a200841186a2902002212370300200141a8066a41206a200841206a2802002202360200200141b8036a41026a220b200a41026a2d00003a00002001200829020022133703a8062001200a2f00003b01b80320012802b004210c200141b0046a41086a220d200f370300200141b0046a41106a220e2010370300200141b0046a41186a22002012370300200141b0046a41206a22172002360200200120133703b004200141d8036a41026a2216200b2d00003a0000200120012f01b8033b01d803410321020240200c2018470d0020014180066a41206a201728020036020020014180066a41186a200029030037030020014180066a41106a200e29030037030020014180066a41086a200d29030037030020014198046a41026a20162d00003a0000200120012903b00437038006200120012f01d8033b01980420062115200921020b20024103470d020b2007200641016a2206470d000b410121084101211f0c030b200141d8056a41206a222220014180066a41206a22202802002208360200200141d8056a41186a222320014180066a41186a2224290300220f370300200141d8056a41106a222520014180066a41106a22262903002210370300200141d8056a41086a222720014180066a41086a2228290300221237030020014188046a41026a222920014198046a41026a222a2d00003a0000200141b0056a41086a222b2012370300200141b0056a41106a222c2010370300200141b0056a41186a222d200f370300200141b0056a41206a222e20083602002001200129038006220f3703d805200120012f0198043b0188042001200f3703b005200141f8036a41026a222f20292d00003a0000200120012f0188043b01f803200641016a2106200141b0046a4104722109200141d9046a210b410121084101211f0340200141b0046a41086a220e202b290300370300200141b0046a41106a2200202c290300370300200141b0046a41186a2217202d290300370300200141b0046a41206a2216202e280200360200200141a8066a41026a220c202f2d00003a0000200120012903b0053703b004200120012f01f8033b01a8060240201f2008470d00200841016a220a2008490d072008410174220d200a200d200a4b1b221fad42307e220f422088a70d07200fa7220a4100480d070240024020080d00200a102a21210c010b2021200841306c200a102e21210b2021450d050b2021200841306c6a220a2018360204200a20153602002016280200210d2017290300210f20002903002110200e290300211220012903b0042113200a412c6a20023a0000200a41086a2013370200200a41106a2012370200200a41186a2010370200200a41206a200f370200200a41286a200d360200200a412d6a20012f01a8063b0000200a412f6a200c2d00003a0000200841016a2108200620074f0d0302400340200141b0046a200610d704024020012d00d804220a4103460d00200141a8066a41086a200941086a290200220f370300200141a8066a41106a200941106a2902002210370300200141a8066a41186a200941186a2902002212370300200141a8066a41206a200941206a2802002202360200200141b8036a41026a220c200b41026a2d00003a00002001200929020022133703a8062001200b2f00003b01b80320012802b004210d200e200f370300200020103703002017201237030020162002360200200120133703b004200141d8036a41026a221e200c2d00003a0000200120012f01b8033b01d803410321020240200d2018470d002020201628020036020020242017290300370300202620002903003703002028200e290300370300202a201e2d00003a0000200120012903b00437038006200120012f01d8033b01980420062115200a21020b20024103470d020b2007200641016a2206470d000c050b0b20222020280200220a36020020232024290300220f3703002025202629030022103703002027202829030022123703002029202a2d00003a0000202b2012370300202c2010370300202d200f370300202e200a3602002001200129038006220f3703d805200120012f0198043b0188042001200f3703b005202f20292d00003a0000200120012f0188043b01f803200641016a21060c000b0b41a888c600200620081038000b103a000b2021200841306c6a21300240024020080d002021212e0c010b2019ad42808080808004842131200141b0046a4104722106200141b0046a41186a2117200141b0046a41106a21162021212e0340202e220841086a2802002125200828020021022017200841246a29020037030020162008411c6a290200370300200141b0046a41086a220e200841146a29020037030020012008410c6a2902003703b004200841306a212e2008412c6a2d000022244103460d01200141b0056a41186a2017290300220f370300200141b0056a41106a20162903002210370300200141b0056a41086a200e2903002212370300200120012903b00422133703b005200141d8056a41186a2227200f370300200141d8056a41106a22322010370300200141d8056a41086a22332012370300200120133703d805200141a8066a200210cd0420012802a806210b0240024020012802b00622080d004200213442002135420021364200213742002114420021380c010b2008410574210942002114200b21084200213842002136420021374200213442002135034020014198036a200810b10120014198036a41086a2903002110200129039803210f20062008290000370000200641086a200841086a290000370000200641106a200841106a290000370000200641186a200841186a290000370000200120023602b00420014190036a200141b0046a10ce0420012d00900341017121070240024020012d009103220a0d00200141d0026a200f2010420a420010e10520012903d0022212210f200141d0026a41086a290300221321100c010b200141f0026a20104200200aad2212420010e00520014180036a200f42002012420010e005200141e0026a42004200200f420010e005427f20014180036a41086a290300221220012903f00220012903e0027c7c221320012903f80220012903e80284420052201320125472220a1b2113427f200129038003200a1b21120b200841206a21084200201320071b20377c4200201220071b223920367c2236203954ad7c21372013420020071b20357c2012420020071b221220347c2234201254ad7c2135201020387c200f20147c2214200f54ad7c2138200941606a22090d000b0b024020012802ac06450d00200b102c0b200141a8066a200210cd0420012802a80621000240024020012802b00622080d00420021394200213a4200213b4200213c420021134200213d0c010b2008410574210942002113200021084200213d4200213b4200213c420021394200213a034020062008290000370000200641086a200841086a2207290000370000200641106a200841106a220a290000370000200641186a200841186a220b290000370000200120023602b004200141c8026a200141b0046a10ce0420012d00c802210c20012d00c902210d2017200b2900003703002016200a290000370300200e2007290000370300200120082900003703b004200141a8026a2002200141b0046a200d411010cf04200141a8026a41186a290300203d7c20012903b802220f20137c2213200f54ad7c213d4200200141a8026a41086a290300220f200c41017122071b203c7c420020012903a802221020071b2212203b7c223b201254ad7c213c200f420020071b203a7c2010420020071b220f20397c2239200f54ad7c213a200841206a2108200941606a22090d000b0b024020012802ac06450d002000102c0b200141d8036a41186a222b4200370300200141d8036a41106a222c4200370300200141d8036a41086a22294200370300200142003703d80320014198046a41086a222f418be9c500ad42808080808001841002220841086a29000037030020012008290000370398042008102c2029202f29030037030020012001290398043703d803202f41c9b5c000ad4280808080d001841002220841086a29000037030020012008290000370398042008102c200e202f290300220f370300200120012903980422103703b00420112010370000201141086a223e200f370000200141b8036a41086a22152029290300370300200141b8036a41106a221e202c290300370300200141b8036a41186a2220202b290300370300200120012903d8033703b80320014190026a200141b8036a4120109e0120014190026a41106a290300420020012802900222081b210f200129039802420020081b211002400240201320147c2212420288203d20387c2012201354ad7c2213423e868422142013420288223884500d002014201285203820138584500d00410021080240034020014180026a20122013200841046a41fe007110df05200841026a2108200129038002221420014180026a41086a290300223884500d01201420128520382013858450450d000b0b200141f0016a20122013200841fe007110df0520012903f001200141f0016a41086a29030084211442002138024020080d002014420052ad21140c020b2014420052ad21140340200141d0016a2012201341002008417e6a2207200720084b1b220841ff007110df05200141e0016a2014420186223f420184223d20384201862014423f88842238203d203810e005203f203d20012903e00120012903d00156200141e0016a41086a2903002214200141d0016a41086a29030022405620142040511b1b211420080d000c020b0b420021382012201384420052ad21140b024002402010420288200f423e86842212200f420288221384500d0020122010852013200f8584500d004100210802400340200141c0016a2010200f200841046a41fe007110df05200841026a210820012903c0012212200141c0016a41086a290300221384500d0120122010852013200f858450450d000b0b200141b0016a2010200f200841fe007110df0520012903b001200141b0016a41086a29030084211242002113024020080d002012420052ad21120c020b2012420052ad2112034020014190016a2010200f41002008417e6a2207200720084b1b220841ff007110df05200141a0016a2012420186223f420184223d20134201862012423f88842213203d201310e005203f203d20012903a00120012903900156200141a0016a41086a290300221220014190016a41086a29030022405620122040511b1b211220080d000c020b0b420021132010200f84420052ad21120b02400240024002400240201420388450450d00410021000c010b203c20377c203b20367c2210203b54ad7c213b203a20357c203920347c220f203954ad7c213902400240024020240e03010200010b200f2010562039203b562039203b511b21000c020b0340200141c0006a2010203b2014203810e1052012223420132235844200510d04200141c0006a41086a290300211220012903402113200141306a200f20392034203510e10541012100201320012903302236542012200141306a41086a290300223d542012203d5122081b0d0202402036201354203d20125420081b450d00410021000c030b200141206a201320122014203810e005200141106a2036203d2034203510e0050240200f200129031022127d22132039200141106a41086a2903007d200f201254ad7d223d84500d00203b200141206a41086a2903007d213620102001290320220f5421082010200f7d21122014210f2038213920132114203d2138203421102035213b201220362008ad7d221384500d030c010b0b410021000c010b03402038213d2014213420122013844200510d02200141f0006a200f20392034203d10e10520014180016a2010203b2012201310e105410121002001290380012235200129037022365420014180016a41086a2903002214200141f0006a41086a290300223854201420385122081b0d0102402036203554203820145420081b450d00410021000c020b200141e0006a203520142012201310e005200141d0006a203620382034203d10e0050240200f200129035022147d22382039200141d0006a41086a2903007d200f201454ad7d22358450450d00410021000c020b203b200141e0006a41086a2903007d213620102001290360220f5421082010200f7d21142012210f20132139203821122035211320342110203d213b201420362008ad7d2238844200520d000b0b200141b0046a200210cd0420012802b004212220012802b404212320012802b8042208450d022022200841057422246a212d202221080240034020014180066a41186a2207200841186a220b29000037030020014180066a41106a2209200841106a220c29000037030020014180066a41086a220a200841086a220d29000037030020012008290000370380062008290000210f200641186a2226200b2900003700002006200f370000200641086a2228200d290000370000200641106a222a200c290000370000200120023602b004200141086a200141b0046a10ce042015200a290300370300201e20092903003703002020200729030037030020012001290380063703b8030240200020012d000841017145734101470d0020012d0009210b200841206a21080c020b200841206a2108202441606a22240d000c040b0b0340200141a8066a41186a2020290300220f370300200141a8066a41106a201e2903002210370300200141a8066a41086a20152903002212370300200120012903b80322133703a8062017200f37030020162010370300200e2012370300200142e4cab5fbb6ccdcb0e3003703a804200120133703b004200141a8046a200141b0046a200b4118744118754102744180d6c5006a2802004180de346c20186a10bd012008202d460d03024003402007200841186a220b2900003703002009200841106a220c290000370300200a200841086a220d2900003703002001200829000037038006202b200b290000370300202c200c2900003703002029200d290000370300200120082900003703d803200120023602b004200d290000210f200c2900002110200829000021122026200b290000370000202a20103700002028200f370000200620123700002001200141b0046a10ce042015200a290300370300201e20092903003703002020200729030037030020012001290380063703b803200020012d000041017145730d01202d200841206a2208470d000c050b0b20012d0001210b200841206a21080c000b0b41b091c200411941d890c2001036000b41b091c200411941d890c2001036000b02402023450d002022102c0b200210d2040240024020000d00200120023602bc04200141053a00b804200141063a00b00441014100200141b0046a1092010c010b200120023602bc04200141043a00b804200141063a00b00441014100200141b0046a10920102400240024002402025450d00200141a8066a41186a22002027290300370300200141a8066a41106a22242032290300370300200141a8066a41086a22262033290300370300200120012903d8053703a806202b4200370300202c420037030020294200370300200142003703d803202f41bad6c500ad428080808090018422101002220841086a29000037030020012008290000370398042008102c2029202f29030037030020012001290398043703d803202f41b6c5c400ad4280808080d0018422121002220841086a29000037030020012008290000370398042008102c200e202f290300220f370300200120012903980422133703b00420112013370000203e200f37000020152029290300370300201e202c2903003703002020202b290300370300200120012903d8033703b803202520186a210c20014180066a200141b8036a10f0030240200128028006220b0d004104210b410021154200210f0c030b200129028406220fa72115410021080240200f422088a7220d41014b0d00200d0e020302030b200d2107034020082007410176220920086a220a200c200b200a41286c6a280200491b2108200720096b220741014b0d000c020b0b2017202729030037030020162032290300370300200e2033290300370300200120012903d8053703b004200141b0046a200210d4040c030b0240200c200b200841286c6a2802002207460d002008200c20074b6a21080b2017200029030037030020162024290300370300200e2026290300370300200120012903a8063703b0042008200d4d0d0141ecb3c000411e41acfec5001036000b2017200029030037030020162024290300370300200e2026290300370300200120012903a8063703b0044100210d410021080b0240200d2015470d00200d200fa7470d00200d41016a2207200d490d06200d41017422092007200920074b1bad220f42287e2213422088a70d062013a722074100480d0602400240200d0d002007102a210b0c010b200b200d41286c2007102e210b0b200b450d040b200b200841286c6a220741286a2007200d20086b41286c10dc051a2007200c360200200720012903b0043702042007410c6a200e290300370200200741146a20162903003702002007411c6a2017290300370200200720023602242017420037030020164200370300200e4200370300200142003703b004202f20101002220841086a29000037030020012008290000370398042008102c200141f8036a41086a202f29030037030020012001290398043703f803201c41086a201b41086a290000370000201c201b290000370000202f20121002220841086a29000037030020012008290000370398042008102c20014188046a41086a202f290300370300200120012903980437038804201d201a290000370000201d41086a201a41086a29000037000020014180066a41086a200e29030037030020014180066a41106a201629030037030020014180066a41186a2017290300370300200120012903b004370380060240200b0d00203110050c010b200141203602b404200120193602b004200b200d41016a200141b0046a10e204200fa7450d00200b102c0b202e2030470d000b2030212e0b2030202e6b2106024003402006450d01200641506a2106202e412c6a2108202e41306a212e20082d00004103470d000b0b0240201f450d002021102c0b200141d8036a41186a22094200370300200141d8036a41106a220a4200370300200141d8036a41086a22084200370300200142003703d80320014198046a41086a220641bad6c500ad42808080809001841002220741086a29000037030020012007290000370398042007102c2008200629030037030020012001290398043703d803200641b6c5c400ad4280808080d001841002220741086a29000037030020012007290000370398042007102c200141b0046a41086a22022006290300220f370300200120012903980422103703b00420112010370000201141086a200f370000200141b8036a41086a2008290300370300200141b8036a41106a200a290300370300200141b8036a41186a2009290300370300200120012903d8033703b803200141b0046a200141b8036a10f00320012802b0042206410420061b210c024020012902b404420020061b2213422088a7220d450d00200c200d41286c6a210941002108200141b0046a41186a210a200141b0046a41106a210b200c210602400340024020062802002018460d0020080d020c030b200641246a2802002107200641046a290000210f2006410c6a2900002110200641146a2900002112200a2006411c6a290000370300200b2012370300200220103703002001200f3703b004200141b0046a200710d404200841016a2108200641286a22062009470d000b0b2008200d4b0d02200141b0046a41186a22024200370300200141b0046a41106a22094200370300200141b0046a41086a220a4200370300200142003703b00420014198046a41086a220641bad6c500ad42808080809001841002220741086a29000037030020012007290000370398042007102c200141f8036a41086a200629030037030020012001290398043703f803201c41086a201b41086a290000370000201c201b290000370000200641b6c5c400ad4280808080d001841002220741086a29000037030020012007290000370398042007102c20014188046a41086a2006290300370300200120012903980437038804201d201a290000370000201d41086a201a41086a29000037000020014180066a41086a200a29030037030020014180066a41106a200929030037030020014180066a41186a2002290300370300200120012903b00437038006200141003602b804200142013703b004200d20086b2206200141b0046a106702402006450d00200c200d41286c6a210a200c200841286c6a21080340200828020021020240024020012802b404220720012802b80422066b4104490d0020012802b00421070c010b200641046a22092006490d06200741017422062009200620094b1b22064100480d060240024020070d002006102a21070c010b20012802b00420072006102e21070b2007450d04200120063602b404200120073602b00420012802b80421060b2001200641046a3602b804200720066a20023600002001200141b0046a3602a806200841046a2207200141a8066a109402200841246a28020021020240024020012802b404220820012802b80422066b4104490d0020012802b00421080c010b200641046a22092006490d06200841017422062009200620094b1b22064100480d060240024020080d002006102a21080c010b20012802b00420082006102e21080b2008450d04200120063602b404200120083602b00420012802b80421060b2001200641046a3602b804200820066a2002360000200741246a2208200a470d000b0b20012802b40421062019ad428080808080048420013502b80442208620012802b0042208ad8410012006450d002008102c0b02402013a7450d00200c102c0b201810df01410010e303410010e30302402004450d00200441246c21082003210603400240024020062d0000220741034b0d0002400240024020070e0404000102040b2006410c6a280200450d03200641086a280200102c0c030b2006410c6a280200450d02200641086a280200102c0c020b2006410c6a280200450d01200641086a280200102c0c010b200641086a280200450d00200641046a280200102c0b200641246a21062008415c6a22080d000b0b02402005450d002003102c0b200141d0066a24000f0b1033000b2008200d1047000b1035000b8404010b7f230041206b2202240020012802002103200128020821042002410036020820024201370300200420021067024002400240024020040d002002280208210520022802042106200228020021070c010b20032004410c6c6a21082003210903402009280200210a200941086a280200220b2002106702400240200228020422062002280208220c6b200b490d00200228020021070c010b200c200b6a2207200c490d04200641017422052007200520074b1b22054100480d040240024020060d002005102a21070c010b200228020020062005102e21070b2007450d032002200536020420022007360200200521060b2002200c200b6a22053602082007200c6a200a200b10db051a2009410c6a22092008470d000b0b200241186a22092005ad4220862007ad841029220b41186a290000370300200241106a220c200b41106a290000370300200241086a220a200b41086a2900003703002002200b290000370300200b102c200041186a2009290300370000200041106a200c290300370000200041086a200a2903003700002000200229030037000002402006450d002007102c0b02402004450d002004410c6c21092003210b03400240200b41046a280200450d00200b280200102c0b200b410c6a210b200941746a22090d000b0b0240200141046a280200450d002003102c0b200241206a24000f0b1033000b1035000bf81f08057f027e017f037e017f027e087f027e230041e0076b2204240020044188046a200141a80210db051a200441a0026a20044188046a109002410121050240024002400240024020042d00a0024101470d00200020042f00a1023b0001200041013a0000200041036a20042d00a3023a000020032802002106410021010c010b200441c0006a200441a0026a41086a41e00110db051a024020032802002206450d00200341086a280200210720032802042108200441386a4181b0c20041101094014100210520044188046a200428023c410020042802381b10bc03200428028804210120042004280290043602a402200420013602a00220062007200441a0026a10f1020240200428028c04450d002001102c0b2008450d002006102c0b200441b0066a200441c0006a41d0006a10ed0220044188046a200441c0006a41e00110db051a20042903b0062109024002400240024002400240024020042903a804220a4202520d004100210b20042802d8044113460d010c090b200441a0076a41186a20044188046a41186a290300370300200441a0076a41106a20044188046a41106a290300370300200441a0076a41086a20044188046a41086a29030037030020042004290388043703a00720044188046a41c0006a290300210c200441c0046a290300210d200441d0046a280200210720042903b004210e200441a0026a41186a4200370300200441a0026a41106a220f4200370300200441a0026a41086a22084200370300200442003703a002200441b8066a41086a22014191b0c200ad4280808080e0008422101002220b41086a2900003703002004200b2900003703b806200b102c20082001290300370300200420042903b80622113703c007200420113703a002200141acb0c200ad4280808080e000841002220b41086a2900003703002004200b2900003703b806200b102c200f20042903b8062211370300200441d8066a41086a2008290300370300200441d8066a41106a2011370300200441d8066a41186a2001290300370300200420113703d007200420042903a0023703d806200441306a200441d8066a41201094010240200a4201520d00200e4200510d020b200120101002220841086a290000370300200420082900003703b8062008102c200441c0076a41086a2001290300370300200420042903b8063703c00720014197b0c200ad4280808080c001841002220841086a290000370300200420082900003703b8062008102c200441d0076a41086a2001290300370300200420042903b8063703d007200441a0026a200441a0076a109f0141c000102a2201450d02200120042903c007370000200120042903d007370010200120042903a002370020200141086a200441c0076a41086a2212290300370000200141186a200441d0076a41086a2213290300370000200141286a200441a0026a41086a290300370000200141306a200441b0026a290300370000200141386a200441a0026a41186a290300370000200441286a200141c000109401200428022c210b200428022821142001102c41002108200b410020141b22012007470d03200441b8066a41086a22014191b0c200ad4280808080e00084220a1002220841086a290000370300200420082900003703b8062008102c20122001290300370300200420042903b8063703c00720014197b0c200ad4280808080c001841002220841086a290000370300200420082900003703b8062008102c20132001290300370300200420042903b8063703d007200441d8066a200441a0076a109f0141c000102a2201450d02200120042903c007370000200141086a200441c0076a41086a290300370000200120042903d007370010200141186a200441d0076a41086a2215290300370000200120042903d806370020200141286a200441d8066a41086a2212290300370000200141306a200441d8066a41106a2213290300370000200141386a200441d8066a41186a22162903003700002004200741016a3602a0022001ad4280808080800884200441a0026aad220e4280808080c00084221110012001102c200441a0026a41186a22174200370300200441a0026a41106a220b4200370300200441a0026a41086a22074200370300200442003703a002200441b8066a41086a2201200a1002220841086a290000370300200420082900003703b8062008102c20072001290300370300200420042903b8063703a00220014184c3c200ad428080808080028422101002220841086a290000370300200420082900003703b8062008102c200b20042903b806220a370300201220072903003703002013200a370300201620012903003703002004200a3703d007200420042903a0023703d806200441206a200441d8066a41201094014100210841062114417f2004280224410020042802201b221820026a221920192018491b221842808080c0f588fe064280808080f28ba80920094280808080f01f835022191b220a200a428094ebdc0380220a4280ec94a37c7e7c4280cab5ee0156200aa76a4b0d0420174200370300200b420037030020074200370300200442003703a00220014191b0c200ad4280808080e00084221a1002220841086a290000370300200420082900003703b8062008102c20072001290300370300200420042903b806220a3703c0072004200a3703a002200120101002220841086a290000370300200420082900003703b8062008102c200b20042903b806220a370300201220072903003703002013200a370300201620012903003703002004200a3703d007200420042903a0023703d806200420183602a002200441d8066aad428080808080048422102011100120174200370300200b420037030020074200370300200442003703a0022001201a1002220841086a290000370300200420082900003703b8062008102c20072001290300370300200420042903b806220a3703c0072004200a3703a002200141e0c2c200ad4280808080b00284221b1002220841086a290000370300200420082900003703b8062008102c20152001290300220a370300200420042903b80622113703d007200f2011370000200f41086a200a370000201220072903003703002013200b29030037030020162017290300370300200420042903a0023703d806200441186a200441d8066a412010940141002108417f200428021c410020042802181b220f4180afd0e502418094ebdc0320191b22012009a7220720012007491b6a22122012200f491b220f20014b0d04200441a0026a41186a22164200370300200441a0026a41106a22134200370300200441a0026a41086a22144200370300200442003703a002200441b8066a41086a2201201a1002221241086a290000370300200420122900003703b8062012102c20142001290300370300200420042903b806220a3703c0072004200a3703a0022001201b1002221241086a290000370300200420122900003703b8062012102c200441d0076a41086a2001290300220a370300200420042903b80622113703d007200b2011370000200b41086a200a370000200441d8066a41086a2014290300370300200441d8066a41106a2013290300370300200441d8066a41186a2016290300370300200420042903a0023703d8062004200f3602a0022010200e4280808080c000841001200441086a200220072009422888a7200d200c10ac0241012114200441a0026a200441a0076a2004290308200441086a41086a29030041014111200d200c84501b10ac0120042802a0024101460d0420042903a8022013290300108503200441a0026a20044188046a41d0006a10c703024020042d00a0024101460d00200441cc026a2802002107200441c8026a280200210f200441c4026a2802002108200441bc026a2802002114200441b8026a280200210b0240200441c0026a2802002201450d002001410c6c2102200b210103400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b02402014450d00200b102c0b02402007450d002007410c6c21022008210103400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b200f450d082008102c0c080b20042d00a10222084102460d0720042f01a20221140c040b200441a0026a200441dc046a10c603024020042d00a0024101460d00200441cc026a2802002107200441c8026a2802002114200441c4026a2802002108200441bc026a2802002112200441b8026a280200210f0240200441c0026a2802002201450d002001410c6c2102200f210103400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b02402012450d00200f102c0b02402007450d002007410c6c21022008210103400240200141046a280200450d002001280200102c0b2001410c6a2101200241746a22020d000b0b2014450d082008102c0c080b20042d00a10222014102460d0720042f01a20241087420017221010c040b41c090c600411941dc90c6001036000b1033000b41034102200120074b1b21140b201441087420087221010b200441d8046a109202200041036a20014110763a0000200020013b0001200041013a000020054521010b20010d022006450d02200341046a280200450d022006102c0c020b20044180076a41186a200441a0076a41186a29030037030020044180076a41106a200441a0076a41106a29030037030020044180076a41086a200441a0076a41086a290300370300200420042903a007370380074101210b0b200441b8066a41186a220820044180076a41186a2201290300370300200441b8066a41106a220f20044180076a41106a2202290300370300200441b8066a41086a221420044180076a41086a220729030037030020042004290380073703b806200441a0026a200441d8046a41900110db051a200441a0076a41186a22122008290300370300200441a0076a41106a2213200f290300370300200441a0076a41086a220f2014290300370300200420042903b8063703a007410221080240200b450d0020012012290300370300200220132903003703002007200f290300370300200420042903a00737038007410121080b200441e2066a2007290300370100200441ea066a2002290300370100200441f2066a2001290300370100200420083a00d90620042004290380073701da06200441003a00d806200441a0076a200441a0026a200441d8066a10c102200441ab076a2d0000210220042903a007210a20042d00a807210120042f00a90721072004419c046a200937020020044188046a41106a2001200720024110747241087472220236020020044188046a41086a2009200a20014102461b3703002004200141024736028c04200441003a0088044101410020044188046a10920120044181b0c20041101094012004200428020441016a410120042802001b360288044181b0c200ad428080808080028420044188046aad4280808080c0008410012000410c6a2002360200200041046a200a370200200041003a00002006450d002005450d00200341046a280200450d002006102c0b200441e0076a24000beb0101027f20014180feff077141087621020240024020014101710d00411f210341ff8ec60021010240024002400240024002400240200241ff01710e080006010203040508000b4120210341df8ec60021010c070b4127210341ff8dc60021010c060b4117210341e88dc60021010c050b41c98dc60021010c040b4126210341a38dc60021010c030b412b210341f88cc60021010c020b4139210341a68ec60021010c010b411f210341a090c600210102400240200241ff01710e03000102000b41c100210341df8fc60021010c010b41c1002103419e8fc60021010b20002003360204200020013602000bee1e09057f017e017f017e027f017e017f027e077f230041f0016b22012400200141a8016a41186a22024200370300200141a8016a41106a22034200370300200141a8016a41086a22044200370300200142003703a801200141c8016a41086a22054191b0c200ad4280808080e0008422061002220741086a290000370300200120072900003703c8012007102c20042005290300370300200120012903c801220837039801200120083703a801200541c8c2c200ad4280808080e001841002220741086a290000370300200120072900003703c8012007102c200320012903c8012208370300200141f8006a41086a22072004290300370300200141f8006a41106a22092008370300200141f8006a41186a220a200529030037030020012008370350200120012903a801370378200141f8006aad220b428080808080048422081005200242003703002003420037030020044200370300200142003703a801200520061002220c41086a2900003703002001200c2900003703c801200c102c20042005290300370300200120012903c801220d370398012001200d3703a801200541e0c2c200ad4280808080b002841002220c41086a2900003703002001200c2900003703c801200c102c20022005290300220d37030020072004290300370300200920012903c801220e370300200a200d3703002001200e370350200120012903a80137037820081005200242003703002003420037030020044200370300200142003703a801200520061002220c41086a2900003703002001200c2900003703c801200c102c20042005290300370300200120012903c801220d370398012001200d3703a80120054184c3c200ad42808080808002841002220c41086a2900003703002001200c2900003703c801200c102c20022005290300220d37030020072004290300370300200920012903c801220e370300200a200d3703002001200e370350200120012903a80137037820081005200242003703002003420037030020044200370300200142003703a801200520061002220c41086a2900003703002001200c2900003703c801200c102c20042005290300370300200120012903c801220d370398012001200d3703a801200541acb0c200ad4280808080e000841002220c41086a2900003703002001200c2900003703c801200c102c20022005290300220d37030020072004290300370300200920012903c801220e370300200a200d3703002001200e370350200120012903a801370378200141086a200141f8006a4120109401200128020c210f0240200128020822104101470d00200810050b200242003703002003420037030020044200370300200142003703a801200520061002220c41086a2900003703002001200c2900003703c801200c102c20042005290300370300200120012903c801220637039801200120063703a801200541b2b0c200ad4280808080a001841002220c41086a2900003703002001200c2900003703c801200c102c200141d0006a41086a20052903002206370300200120012903c801220d3703502003200d370000200341086a20063700002007200429030037030020092003290300370300200a2002290300370300200120012903a801370378200141c8016a200141f8006a412010d3010240024020012d00c8014101460d00200141106a41086a4200370300200141106a41106a4200370300200141106a41186a4200370300200141a8016a41186a200141e1016a290000370300200141a8016a41106a200141d9016a290000370300200141a8016a41086a200141d1016a290000370300200120012900c9013703a801200142003703100c010b20081005200141a8016a41186a200141e1016a2900002206370300200141a8016a41106a200141d9016a290000220d370300200141a8016a41086a200141d1016a290000220e370300200141106a41086a200e370300200141106a41106a200d370300200141106a41186a2006370300200120012900c90122063703a801200120063703100b200141a8016a41186a22024200370300200141a8016a41106a22074200370300200141a8016a41086a22044200370300200142003703a801200141c8016a41086a22054191b0c200ad4280808080e00084220d1002220941086a290000370300200120092900003703c8012009102c20042005290300370300200120012903c801220637039801200120063703a801200541cab0c200ad4280808080e000841002220941086a290000370300200120092900003703c8012009102c200141d0006a41086a221120052903002206370300200120012903c801220e3703502003200e370000200341086a22122006370000200141f8006a41086a22132004290300370300200141f8006a41106a22142007290300370300200141f8006a41186a22152002290300370300200120012903a801370378200141c8016a200141f8006a10e4020240024020012802c80122090d0041042109420021060c010b2008100520012902cc0121060b200f410020101b210a200242003703002007420037030020044200370300200142003703a8012005200d1002220c41086a2900003703002001200c2900003703c801200c102c20042005290300370300200120012903c801220d370398012001200d3703a801200541bcb0c200ad4280808080e001841002220c41086a2900003703002001200c2900003703c801200c102c20112005290300220d370300200120012903c801220e3703502003200e3700002012200d370000201320042903003703002014200729030037030020152002290300370300200120012903a801370378200141c8016a200141f8006a412010d3010240024020012d00c8014101460d00200141306a41086a4200370300200141306a41106a4200370300200141306a41186a4200370300200141a8016a41186a200141e1016a290000370300200141a8016a41106a200141d9016a290000370300200141a8016a41086a200141d1016a290000370300200120012900c9013703a801200142003703300c010b20081005200141a8016a41186a200141e1016a2900002208370300200141a8016a41106a200141d9016a290000220d370300200141a8016a41086a200141d1016a290000220e370300200141306a41086a200e370300200141306a41106a200d370300200141306a41186a2008370300200120012900c90122083703a801200120083703300b0240024002400240200a41fb01490d00200a41857e6a2203450d00200141c8016a41086a22054191b0c200ad4280808080e000841002220441086a290000370300200120042900003703c8012004102c20014198016a41086a22022005290300370300200120012903c80137039801200541a3b0c200ad42808080809001841002220441086a290000370300200120042900003703c8012004102c200141d0006a41086a22072005290300370300200120012903c80137035020012003360278200141c8016a41186a2203200b4280808080c000841006220441186a290000370300200141c8016a41106a220c200441106a2900003703002005200441086a290000370300200120042900003703c8012004102c200141a8016a41186a22042003290300370300200141a8016a41106a2203200c290300370300200141a8016a41086a220c2005290300370300200120012903c8013703a80141c000102a2205450d01200520012903980137000020052001290350370010200520012903a801370020200541086a2002290300370000200541186a2007290300370000200541286a200c290300370000200541306a2003290300370000200541386a20042903003700002005ad428080808080088410052005102c0b101b210841002105200141003a00e8012008422088a721022008a722072104034020022005460d03200141c8016a20056a20042d00003a00002001200541016a22033a00e801200441016a21042003210520034120470d000b200141d0006a41086a200141c8016a41086a290300370300200141d0006a41106a200141c8016a41106a290300370300200141d0006a41186a200141c8016a41186a290300370300200120012903c80137035002402002450d002007102c0b200141003602d001200142013703c8012001200141c8016a3602a801200141106a200141a8016a10940220012802cc01210520014198016a20013502d00142208620012802c8012204ad84101c108d0102402005450d002004102c0b02402001280298012203450d00200141a0016a2802002102200128029c01210c41002105200141003a00e8010340024020022005470d000240200541ff0171450d00200141003a00e8010b41dfd0c200412c200141c8016a418cd1c200103b000b200141c8016a20056a200320056a2d00003a00002001200541016a22043a00e8012004210520044120470d000b200141f8006a41086a200141c8016a41086a22042903002208370300200141f8006a41106a200141c8016a41106a2202290300220d370300200141f8006a41186a200141c8016a41186a2207290300220e370300200120012903c801220b370378200420083703002002200d3703002007200e3703002001200b3703c801200141a8016a41026a220f200141f5006a41026a2d00003a0000200120012f00753b01a8010240024020064220882208a722052006a7460d002006210d0c010b200541016a22102005490d032008a74101742211201020102011491bad220d42247e2208422088a70d032008a722104100480d030240024020050d002010102a21090c010b2009200541246c2010102e21090b2009450d0220064220882208a721050b2009200541246c6a220541003a0000200520012903c801370001200541096a2004290300370000200541116a2002290300370000200541196a2007290300370000200520012f01a8013b0021200541236a200f2d00003a00002008422086200d42ffffffff0f83844280808080107c2106200c450d002003102c0b200020012903103700102000200a36020020002001290350370030200041286a200141106a41186a290300370000200041206a200141106a41106a290300370000200041186a200141106a41086a290300370000200041386a200141d0006a41086a290300370000200041c0006a200141d0006a41106a290300370000200041c8006a200141d0006a41186a290300370000200041086a200637020020002009360204200041e8006a200141306a41186a290300370000200041e0006a200141306a41106a290300370000200041d8006a200141306a41086a29030037000020002001290330370050200141f0016a24000f0b1033000b1035000b0240200541ff0171450d00200141003a00e8010b41dfd0c200412c200141c8016a418cd1c200103b000ba20301027f23004180026b22022400024002402001450d00200220003602000c010b200241013602000b20022001360204200241f8006a20021081010240200228027c450d00200241086a200241f8006a41f00010db051a200241086a10b2030240200241086a410c6a2802002200450d00200228020c2101200041246c210003400240024020012d0000220341034b0d0002400240024020030e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012000415c6a22000d000b0b0240200241106a280200450d00200228020c102c0b20024180026a240042010f0b200241f4016a41043602002002411c6a41023602002002420237020c20024184adc200360208200241043602ec0120024184aec2003602e801200241003602fc01200241dc9ec6003602f8012002200241e8016a3602182002200241f8016a3602f001200241086a4194adc2001041000bd02a020b7f017e230041d0006b2202240020024100360228200242013703200240024002404104102a2203450d0020024284808080c00037022420022003360220200341edcad18b0636000002400240200228022420022802282203460d00200228022021040c010b200341016a22042003490d03200341017422052004200520044b1b22054100480d030240024020030d002005102a21040c010b200228022020032005102e21040b2004450d0120022005360224200220043602200b2002200341016a360228200420036a41093a00004119200241206a106741ccf0c100210603402006280204210720062802082203200241206a10670240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d04200541017422042008200420084b1b22044100480d040240024020050d002004102a21050c010b200228022020052004102e21050b2005450d022002200436022420022005360220200228022821040b2002200420036a360228200520046a2007200310db051a200228022421042002280228210302400240200628020c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200228022020032005102e21040b2004450d042002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200228022020032005102e21040b2004450d032002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628020c4101460d00200241306a20062802101103002002280234210720022802382203200241206a10670240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d06200541017422042008200420084b1b22044100480d060240024020050d002004102a21050c010b200228022020052004102e21050b2005450d042002200436022420022005360220200228022821040b2002200420036a360228200520046a2007200310db051a200228024021050240200228023c4101460d0020052002280244200241206a10680c020b200520022802482203200241206a106802402003450d00200341d8006c21074100210403400240200520046a220341346a280200450d002003413c6a280200450d00200341386a280200102c0b0240200341c4006a280200450d00200341cc006a280200450d00200341c8006a280200102c0b2007200441d8006a2204470d000b0b2002280244450d012005102c0c010b2006280214210720062802182203200241206a10670240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d05200541017422042008200420084b1b22044100480d050240024020050d002004102a21050c010b200228022020052004102e21050b2005450d032002200436022420022005360220200228022821040b2002200420036a360228200520046a2007200310db051a200628022021030240200628021c4101460d002003200641246a280200200241206a10680c010b20032006280228200241206a10680b200228022421042002280228210302400240200628022c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200228022020032005102e21040b2004450d042002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200228022020032005102e21040b2004450d032002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628022c4101460d00200241186a200628023011030020022802182104200228021c2203200241206a10672003450d012003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10670240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d0720074101742205200a2005200a4b1b22054100480d070240024020070d002005102a21070c010b200228022020072005102e21070b2007450d052002200536022420022007360220200228022821050b2002200520046a360228200720056a2009200410db051a200341706a200241206a10692003200241206a10662003412c6a2103200841546a22080d000c020b0b2006280230210420062802382203200241206a10672003450d002003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10670240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d0620074101742205200a2005200a4b1b22054100480d060240024020070d002005102a21070c010b200228022020072005102e21070b2007450d042002200536022420022007360220200228022821050b2002200520046a360228200720056a2009200410db051a200341706a200241206a10692003200241206a10662003412c6a2103200841546a22080d000b0b200228022421042002280228210302400240200628023c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102a21040c010b200228022020032005102e21040b2004450d042002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102a21040c010b200228022020032005102e21040b2004450d032002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628023c4101460d00200241106a20062802401103002002280210210420022802142203200241206a10672003450d012003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10670240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d0720074101742205200a2005200a4b1b22054100480d070240024020070d002005102a21070c010b200228022020072005102e21070b2007450d052002200536022420022007360220200228022821050b2002200520046a360228200720056a2009200410db051a200341706a200241206a10662003200241206a10662003412c6a2103200841546a22080d000c020b0b2006280240210420062802482203200241206a10672003450d002003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10670240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d0620074101742205200a2005200a4b1b22054100480d060240024020070d002005102a21070c010b200228022020072005102e21070b2007450d042002200536022420022007360220200228022821050b2002200520046a360228200720056a2009200410db051a200341706a200241206a10662003200241206a10662003412c6a2103200841546a22080d000b0b02400240200628024c4101460d00200241086a20062802501103002002280208210b200228020c2203200241206a10672003450d01200341386c210c410021070340200b20076a220341046a2802002109200341086a2802002204200241206a10670240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d0720084101742205200a2005200a4b1b22054100480d070240024020080d002005102a21080c010b200228022020082005102e21080b2008450d052002200536022420022008360220200228022821050b2002200520046a360228200820056a2009200410db051a200341106a2802002109200341146a2802002204200241206a10670240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d0720084101742205200a2005200a4b1b22054100480d070240024020080d002005102a21080c010b200228022020082005102e21080b2008450d052002200536022420022008360220200228022821050b2002200520046a360228200820056a2009200410db051a02400240200341186a2802004101460d00200241306a2003411c6a280200200341206a28020028020c1102002002280230210920022802382204200241206a10670240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d0920084101742205200a2005200a4b1b22054100480d090240024020080d002005102a21080c010b200228022020082005102e21080b2008450d072002200536022420022008360220200228022821050b2002200520046a360228200820056a2009200410db051a2002280234450d012009102c0c010b2003411c6a2802002109200341246a2802002204200241206a10670240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d0820084101742205200a2005200a4b1b22054100480d080240024020080d002005102a21080c010b200228022020082005102e21080b2008450d062002200536022420022008360220200228022821050b2002200520046a360228200820056a2009200410db051a0b200341286a200241206a1066200c200741386a2207470d000c020b0b2006280250210b20062802582203200241206a10672003450d00200341386c210c410021070340200b20076a220341046a2802002109200341086a2802002204200241206a10670240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d0620084101742205200a2005200a4b1b22054100480d060240024020080d002005102a21080c010b200228022020082005102e21080b2008450d042002200536022420022008360220200228022821050b2002200520046a360228200820056a2009200410db051a200341106a2802002109200341146a2802002204200241206a10670240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d0620084101742205200a2005200a4b1b22054100480d060240024020080d002005102a21080c010b200228022020082005102e21080b2008450d042002200536022420022008360220200228022821050b2002200520046a360228200820056a2009200410db051a02400240200341186a2802004101460d00200241306a2003411c6a280200200341206a28020028020c1102002002280230210920022802382204200241206a10670240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d0820084101742205200a2005200a4b1b22054100480d080240024020080d002005102a21080c010b200228022020082005102e21080b2008450d062002200536022420022008360220200228022821050b2002200520046a360228200820056a2009200410db051a2002280234450d012009102c0c010b2003411c6a2802002109200341246a2802002204200241206a10670240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d0720084101742205200a2005200a4b1b22054100480d070240024020080d002005102a21080c010b200228022020082005102e21080b2008450d052002200536022420022008360220200228022821050b2002200520046a360228200820056a2009200410db051a0b200341286a200241206a1066200c200741386a2207470d000b0b02400240200628025c4101460d00200220062802601103002002280200210420022802042203200241206a10672003450d012003411c6c21082004410c6a21030340200341786a28020021092003417c6a2802002204200241206a10670240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d0720074101742205200a2005200a4b1b22054100480d070240024020070d002005102a21070c010b200228022020072005102e21070b2007450d052002200536022420022007360220200228022821050b2002200520046a360228200720056a2009200410db051a2003200241206a10662003411c6a2103200841646a22080d000c020b0b2006280260210420062802682203200241206a10672003450d002003411c6c21082004410c6a21030340200341786a28020021092003417c6a2802002204200241206a10670240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d0620074101742205200a2005200a4b1b22054100480d060240024020070d002005102a21070c010b200228022020072005102e21070b2007450d042002200536022420022007360220200228022821050b2002200520046a360228200720056a2009200410db051a2003200241206a10662003411c6a2103200841646a22080d000b0b200641ec006a220641d885c200470d000b2002280228220341046a2204417f4c0d0120022802242108200228022021070240024020040d00410121050c010b2004102a2205450d010b2002410036023820022004360234200220053602302003200241306a10670240024020022802342205200228023822046b2003490d00200228023021050c010b200420036a22092004490d03200541017422062009200620094b1b22094100480d030240024020050d002009102a21050c010b200228023020052009102e21050b2005450d0120022009360234200220053602300b200520046a2007200310db051a200420036aad4220862005ad84210d02402008450d002007102c0b200241d0006a2400200d0f0b1033000b103a000b1035000ba80601047f230041b0076b22022400024002402001450d00200220003602000c010b200241013602000b20022001360204200241f8046a2002108c0202400240024020022903e0054203510d00200241186a200241f8046a41a80210db051a200241c0026a200241186a41a80210db051a2002200241c0026a3602f804200241e8046a200241f8046a10870120022802f0042101200241f8046a200241c0026a41a80210db051a200241a8076a20022802f004360200200220022903e8043703a007200241086a200241f8046a2001200241a0076a10b4034101410220022d000841014622031b2200102a2201450d012002410036028005200220003602fc04200220013602f8040240024020030d00200141003a00004102210320024102360280050240200241146a2d000022044102470d00200141003a00010c020b200141013a00010240024020044101470d00200141024104102e2201450d05200141013a000220024284808080303702fc04200220013602f8044103210320022d001521040c010b410221034100210420004102470d0041000d0520004101742204200041016a2205200420054b1b22044100480d05200120002004102e2201450d04200220043602fc04200220013602f804410021040b200120036a20043a00002002200341016a220036028005200241166a2d00002104024020022802fc042000470d0041000d0520004101742203200041016a2205200320054b1b22034100480d050240024020000d002003102a21010c010b200120002003102e21010b2001450d04200220033602fc04200220013602f8040b2002200041016a220336028005200120006a20043a00000c010b200141013a00002002410136028005200241086a410172200241f8046a10ba03200228028005210320022802f80421010b200241b0076a24002003ad4220862001ad840f0b200241246a4104360200200241d4026a4102360200200242023702c40220024184adc2003602c0022002410436021c2002419caec2003602182002410036020c200241dc9ec6003602082002200241186a3602d0022002200241086a360220200241c0026a4194adc2001041000b1033000b1035000ba00b01057f230041106b22022400200141046a2802002103200141086a2802002104024002400240024020002d00004101460d000240024020032004460d00200128020021050c010b200441016a22032004490d04200441017422052003200520034b1b22034100480d040240024020040d002003102a21050c010b200128020020042003102e21050b2005450d0320012005360200200141046a2003360200200141086a28020021040b200141086a2206200441016a36020041002103200520046a41003a000002400240024002400240024002400240024020002d00010e080700010203040506070b200241013a000f410121030c070b410221030c050b410321030c040b410421030c030b410521030c020b410621030c010b200241073a000f02400240200141046a28020020062802002204460d00200128020021030c010b200441016a22032004490d06200441017422052003200520034b1b22054100480d060240024020040d002005102a21030c010b200128020020042005102e21030b2003450d0520012003360200200141046a2005360200200141086a28020021040b200141086a200441016a360200200320046a41073a000020002d000221030b200220033a000f0b02400240200141046a280200200141086a2802002204460d00200128020021000c010b200441016a22002004490d04200441017422052000200520004b1b22054100480d040240024020040d002005102a21000c010b200128020020042005102e21000b2000450d0320012000360200200141046a2005360200200141086a28020021040b200141086a200441016a360200200020046a20033a00000c010b0240024020032004460d00200128020021030c010b200441016a22032004490d03200441017422052003200520034b1b22054100480d030240024020040d002005102a21030c010b200128020020042005102e21030b2003450d0220012003360200200141046a2005360200200141086a28020021040b200141086a200441016a360200200320046a41013a000020002d0001220441024b0d0002400240024020040e03000102000b02400240200141046a280200200141086a2802002204460d00200128020021000c010b200441016a22002004490d05200441017422032000200320004b1b22034100480d050240024020040d002003102a21000c010b200128020020042003102e21000b2000450d0420012000360200200141046a2003360200200141086a28020021040b200141086a200441016a360200200020046a41003a00000c020b02400240200141046a280200200141086a2802002204460d00200128020021000c010b200441016a22002004490d04200441017422032000200320004b1b22034100480d040240024020040d002003102a21000c010b200128020020042003102e21000b2000450d0320012000360200200141046a2003360200200141086a28020021040b200141086a200441016a360200200020046a41013a00000c010b02400240200141046a280200200141086a2802002204460d00200128020021030c010b200441016a22032004490d03200441017422052003200520034b1b22054100480d030240024020040d002005102a21030c010b200128020020042005102e21030b2003450d0220012003360200200141046a2005360200200141086a28020021040b200141086a2205200441016a360200200320046a41023a000020002d0002210302400240200141046a28020020052802002204460d00200128020021000c010b200441016a22002004490d03200441017422052000200520004b1b22054100480d030240024020040d002005102a21000c010b200128020020042005102e21000b2000450d0220012000360200200141046a2005360200200141086a28020021040b200141086a200441016a360200200020046a20033a00000b200241106a24000f0b1033000b1035000bdb1109077f017e017f027e027f017e057f017e037f23004190026b22022400200241186a4181b0c2004110109401200228021c21030240200228021822044101470d004181b0c200ad428080808080028410050b200241b0016a41186a22054200370300200241b0016a41106a22064200370300200241b0016a41086a22074200370300200242003703b001200241206a41086a22084191b0c200ad4280808080e0008422091002220a41086a2900003703002002200a290000370320200a102c20072008290300370300200220022903203703b001200841c8c2c200ad4280808080e00184220b1002220a41086a2900003703002002200a290000370320200a102c20062002290320220c37030020024190016a41086a220d200729030037030020024190016a41106a220a200c37030020024190016a41186a220e20082903003703002002200c3703d001200220022903b0013703900120022003410020041b36022020024190016aad4280808080800484220f200241206aad4280808080c000841001200241206a41186a22104200370300200241206a41106a220442003703002008420037030020024200370320200241d0016a41086a221120091002220341086a290000370300200220032900003703d0012003102c20082011290300370300200220022903d001370320201141acb0c200ad4280808080e000841002220341086a290000370300200220032900003703d0012003102c200420022903d001220c370300200241e0016a41086a22122008290300370300200241e0016a41106a200c370300200241e0016a41186a221320112903003703002002200c3703b001200220022903203703e001200241106a200241e0016a41201094012002280214210420022802102114200542003703002006420037030020074200370300200242003703b001201141e4d2c500ad42808080808001841002220341086a290000370300200220032900003703d0012003102c20072011290300370300200220022903d0013703b001201141ecd2c500ad42808080808001841002220341086a290000370300200220032900003703d0012003102c20052011290300220c370300200d2007290300370300200a20022903d0012215370300200e200c3703002002201537038002200220022903b00137039001200f10052004410020141b10ad02200542003703002006420037030020074200370300200242003703b001201120091002220341086a290000370300200220032900003703d0012003102c20072011290300370300200220022903d001220c370380022002200c3703b0012011200b1002220341086a290000370300200220032900003703d0012003102c20052011290300220c370300200d2007290300370300200a20022903d001220b370300200e200c3703002002200b37038002200220022903b00137039001200241086a20024190016a41201094010240024002400240200228020c410020022802081b22160d0041042117410021160c010b2016ad420c7e220c422088a70d01200ca7220a4100480d01200a102a2217450d024100210a201721030340200241e0016a200a10bc03200241206a20022802e001221420022802e801221810bd03024020022802202204450d002018ad4220862014ad8410050b200a41016a210a2002290224420020041b210c2004410120041b2104024020022802e401450d002014102c0b20032004360200200341046a200c3702002003410c6a21032016200a470d000b0b200220163602282002201636022420022017360220200241e0016a200241206a10b30320102013290300370300200241206a41106a2203200241e0016a41106a29030037030020082012290300370300200220022903e00137032020054200370300200241b0016a41106a2204420037030020074200370300200242003703b001201120091002220a41086a2900003703002002200a2900003703d001200a102c20072011290300370300200220022903d001220c370380022002200c3703b001201141bcb0c200ad4280808080e001841002220a41086a2900003703002002200a2900003703d001200a102c20024180026a41086a2011290300220c370300200220022903d00122093703800220062009370000200641086a200c370000200d200729030037030020024190016a41106a2004290300370300200e2005290300370300200220022903b00137039001200241203602b401200220024190016a3602b001200241206a200241b0016a10be03200241206a10b603200241003602b801200242013703b0012002200241b0016a3602e0012003200241e0016a109402200241206a200241b0016a1089012002200241b0016a3602e001200241d0006a200241e0016a1094022002200241b0016a3602e001200241f0006a200241e0016a109402200228022421042002412c6a280200220a200241b0016a10670240200a450d00200a41246c21160340200241e0016a200410e70220022802e00121180240024020022802b401221420022802b801220a6b20022802e8012203490d0020022802b00121140c010b200a20036a2211200a490d032014410174220a2011200a20114b1b220a4100480d030240024020140d00200a102a21140c010b20022802b0012014200a102e21140b2014450d042002200a3602b401200220143602b00120022802b801210a0b2002200a20036a3602b8012014200a6a2018200310db051a024020022802e401450d002018102c0b200441246a21042016415c6a22160d000b0b20023502b801422086210c20023502b00121090240200228022c2203450d002002280224210a200341246c2103034002400240200a2d0000220441034b0d0002400240024020040e0404000102040b200a410c6a280200450d03200a41086a280200102c0c030b200a410c6a280200450d02200a41086a280200102c0c020b200a410c6a280200450d01200a41086a280200102c0c010b200a41086a280200450d00200a41046a280200102c0b200a41246a210a2003415c6a22030d000b0b200c200984210c0240200241286a280200450d002002280224102c0b20024190026a2400200c0f0b1035000b1033000bcd0301067f230041f0006b22022400200241d0006a41086a22034191b0c200ad4280808080e000841002220441086a290000370300200220042900003703502004102c200241086a41086a2205200329030037030020022002290350370308200341b4c3c200ad4280808080d001841002220441086a290000370300200220042900003703502004102c200241186a41086a22062003290300370300200220022903503703182002200136024c200241d0006a41186a2201200241cc006aad4280808080c000841006220441186a290000370300200241d0006a41106a2207200441106a2900003703002003200441086a290000370300200220042900003703502004102c200241286a41186a22042001290300370300200241286a41106a22012007290300370300200241286a41086a2207200329030037030020022002290350370328024041c000102a22030d001033000b200320022903083700002003200229031837001020032002290328370020200042c0808080800837020420002003360200200341086a2005290300370000200341186a2006290300370000200341286a2007290300370000200341306a2001290300370000200341386a2004290300370000200241f0006a24000bbb0201017f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041003602000c010b200328021421022003200341106a41086a28020036022420032001360220200341c8006a200341206a1077024002402003280248450d0020002003290348370200200041086a200341c8006a41086a2802003602000c010b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341d0b0c2003602482003200341386a360258200341c4006a41c49ac500200341c8006a10391a2003350230422086200335022884100420004100360200200328022c450d002003280228102c0b2002450d002001102c0b200341e0006a24000bc30301027f20002d0000210202404101102a2203450d00200320023a000020002d00012102200341014102102e2203450d00200320023a000120002d00022102200341024104102e2203450d00200320023a0002200320002d00033a000320002d00042102200341044108102e2203450d00200320023a0004200320002d00053a0005200320002d00063a0006200320002d00073a000720002d00082102200341084110102e2203450d00200320023a0008200320002d00093a0009200320002d000a3a000a200320002d000b3a000b200320002d000c3a000c200320002d000d3a000d200320002d000e3a000e200320002d000f3a000f20002d00102102200341104120102e2203450d00200320023a0010200320002d00113a0011200320002d00123a0012200320002d00133a0013200320002d00143a0014200320002d00153a0015200320002d00163a0016200320002d00173a0017200320002d00183a0018200320002d00193a0019200320002d001a3a001a200320002d001b3a001b200320002d001c3a001c200320002d001d3a001d200320002d001e3a001e200320002d001f3a001f20012902002003ad428080808080048410012003102c0f0b1033000b932907017f017e027f017e0e7f027e077f230041f0036b22022400024002402001450d00200220003602200c010b200241013602200b20022001360224200241186a200241206a1075024020022802180d00200228021c21012002200241206a3602f801200241003a00d003200242003702e402200241d0e1c1003602e0022002200136023c200241003602382002200241d0036a3602442002200241f8016a360240200241386a200241e0026a10a90220022802e002210120022902e4022103024020022d00d003450d0020012003a72003422088a710c0030c010b2001450d002002200337022c20022001360228200241386a200241286a10c10302400240024002400240024020022802384101460d00200241386a41086a2903002103200241b8016a41186a4200370300200241b8016a41106a22044200370300200241b8016a41086a22004200370300200242003703b801200241e8016a41086a220141f9e8c500ad42808080809001841002220541086a290000370300200220052900003703e8012005102c20002001290300370300200220022903e8013703b8012001419db1c200ad428080808030841002220541086a290000370300200220052900003703e8012005102c200420022903e8012206370300200241d0036a41086a2000290300370300200241d0036a41106a2006370300200241d0036a41186a2001290300370300200220063703d801200220022903b8013703d003200241086a200241d0036a109801200229031021062002280208210141a802102a2207450d0420074103360298012007420237036820072003200642dc0b7c42dc0b20011b220620032006561b3703a001200241286a2101200228022c210803402001280200220941086a210020092f0106220a4103742101410021050240024003402001450d0141c991c2002000410810dd05220b450d02200141786a2101200541016a2105200041086a2100200b417f4a0d000b2005417f6a210a0b024020080d004101210c0c060b2008417f6a21082009200a4102746a41e4016a21010c010b0b200220092005410c6c6a220141e8006a2802003602e4022002200141e0006a2802003602e002200241386a200241e0026a10800102402002280238220d0d004101210c0c040b200228023c210e200241386a41086a2201280200220a450d01200241386a41186a22094200370300200241386a41106a220f42003703002001420037030020024200370338200241e8016a41086a220041a4c6c500ad4280808080a001841002220541086a290000370300200220052900003703e8012005102c20012000290300370300200220022903e801370338200041f889c200ad4280808080e000841002220541086a290000370300200220052900003703e8012005102c200f20022903e8012203370300200241d0036a41086a2001290300370300200241d0036a41106a2003370300200241d0036a41186a2000290300370300200220033703d801200220022903383703d003200241386a200241d0036a10e601200229023c4200200228023822011b2203a7210c2001410420011b22082100200821010240024002402003422088a72210450d002008201041c4006c6a21004100210502400340200820056a22012d0000210b200241386a200141016a41c30010db051a200b4102460d01200241b8016a41186a2009290000370300200241b8016a41106a200f290000370300200241b8016a41086a200241386a41086a290000370300200220022900383703b801200b4101460d03200541c4006a2105200141c4006a2000470d000b200021010c010b200141c4006a21010b0240034020002001460d0120012d00002105200141c4006a210120054102470d000b0b41012109410021110240200c0d00410021120c020b2008102c410021120c010b200241d0036a41086a220b200241b8016a41086a290300370300200241d0036a41106a2213200241b8016a41106a290300370300200241d0036a41186a2214200241b8016a41186a290300370300200220022903b80122033703f801200220033703d0034120102a2209450d05200920022903d003370000200941186a2014290300370000200941106a2013290300370000200941086a200b29030037000041012111024002400240201041c4006c41bc7f6a2005470d00410121120c010b200141c4006a2d00002105200241386a200141c5006a41c30010db051a20014188016a210b024020054102470d0041012112200b21010c020b41012111410121120340200b210102400340200241b8016a41186a220b200241386a41186a290000370300200241b8016a41106a2210200241386a41106a290000370300200241b8016a41086a2213200241386a41086a290000370300200220022900383703b801200541ff01714101460d0120002001460d0320012d00002105200241386a200141016a41c30010db051a200141c4006a210120054102460d040c000b0b200241d0036a41086a20132903002203370300200241d0036a41106a20102903002206370300200241d0036a41186a200b2903002215370300200220022903b80122163703d003200241f8016a41186a220b2015370300200241f8016a41106a22102006370300200241f8016a41086a22132003370300200220163703f801024020122011470d00201141016a22052011490d0a201141017422142005201420054b1b221241ffffff3f712012470d0a201241057422054100480d0a0240024020110d002005102a21090c010b200920114105742005102e21090b2009450d090b200920114105746a220520022903f801370000200541186a200b290300370000200541106a2010290300370000200541086a2013290300370000201141016a211120002001460d0120012d00002105200241386a200141016a41c30010db051a200141c4006a210b20054102470d000b200141c4006a21010c010b200021010b0240034020002001460d0120012d00002105200141c4006a210120054102470d000b0b200c450d002008102c0b200d200a41f0006c6a2114200241e0026a41106a2117200241e0026a41086a21184200211541042119200d210b0340200b2802042101200b2802002100200241386a200b41086a41e80010db051a200b41f0006a210b2001450d03200241f8016a200241386a41e80010db051a200220013602e402200220003602e0022018200241f8016a41e80010db051a200241386a41186a22104200370300200241386a41106a22134200370300200241386a41086a2205420037030020024200370338200241e8016a41086a22014191b0c200ad4280808080e000841002220041086a290000370300200220002900003703e8012000102c20052001290300370300200220022903e801370338200141acb0c200ad4280808080e000841002220041086a290000370300200220002900003703e8012000102c200241d8016a41086a20012903002203370300200220022903e80122063703d801200f2006370000200f41086a2003370000200241d0036a41086a221a2005290300370300200241d0036a41106a221b2013290300370300200241d0036a41186a221c2010290300370300200220022903383703d0032002200241d0036a41201094012002280200210120022802042100200241d0036a200241e0026a10ee0202400240024020022802e002417f6a22082000410020011b22014f0d00200241386a2008109302200241386a2017412010dd050d0020022802e002221d41002001417b6a2200200020014b1b490d0020114105742108200241d0036a20096b210c4100210102400340024020082001470d004100210a0c020b4101210a200c2001460d01200920016a2100200141206a21012000200241d0036a412010dd050d000b0b200241386a201d109302200241386a200241d0036a412010dd052101200a0d0020010d010b024020022802ec022200450d0020022802e4022101200041246c210003400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012000415c6a22000d000b0b20022802e802450d0120022802e402102c0c010b200241d0036a200241e0026a10ee02200241386a200241e0026a41f00010db051a0240024020154220882203a722012015a7460d00200121000c010b200141016a220a2001490d082003a72200410174220c200a200a200c491bad221542f0007e2203422088a70d082003a7220a4100480d080240024020010d00200a102a21190c010b2019200141f0006c200a102e21190b2019450d070b2019200041f0006c6a200241386a41f00010db051a2010201c2903003703002013201b2903003703002005201a290300370300200220022903d003370338024020112012470d00201141016a22012011490d082011410174220a2001200a20014b1b221241ffffff3f712012470d08201241057422014100480d080240024020110d002001102a21090c010b200920082001102e21090b2009450d070b201542ffffffff0f83200041016a2200ad422086842115200920086a22012002290338370000200141186a2010290300370000200141106a2013290300370000200141086a20052903003700002000410a460d04201141016a21110b200b2014470d000b2014210b0c020b2002200229023c3703e00241d5b1c2004128200241e0026a41a0b1c200103b000b4101210c200e450d01200d102c0c010b0240200b2014460d000340200b2802042208450d01200b41086a280200210a0240200b410c6a2802002201450d00200141246c21002008210103400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012000415c6a22000d000b0b200b41f0006a210b0240200a450d002008102c0b200b2014470d000b0b0240200e450d00200d102c0b02402012450d002009102c0b0240201542ffffffff0f560d004101210c2015a7450d012019102c0c010b024020190d004101210c0c010b200741a80241d004102e2207450d01200741a8026a200241e0026a41e80010db051a2007420237039003200720153703c803200720193602c403200741043602c003200720022903f80137039803200741a0036a20024180026a290300370300200741a8036a20024188026a290300370300200741b0036a20024190026a290300370300200741b8036a20024198026a290300370300200741d0036a200241386a41800110db051a4102210c0b200241286a2101200228022c210802400240024003402001280200220941086a210020092f0106220a4103742101410021050240024003402001450d0141d191c2002000410810dd05220b450d02200141786a2101200541016a2105200041086a2100200b417f4a0d000b2005417f6a210a0b2008450d022008417f6a21082009200a4102746a41e4016a21010c010b0b200941e0006a2005410c6c6a22012802084104490d0020012802002800002108200241b8016a41186a220b4200370300200241b8016a41106a22094200370300200241b8016a41086a22004200370300200242003703b801200241e8016a41086a220141f9e8c500ad42808080809001841002220541086a290000370300200220052900003703e8012005102c20002001290300370300200220022903e8013703b801200141e499c500ad4280808080b001841002220541086a290000370300200220052900003703e8012005102c200241d8016a41086a20012903002203370300200220022903e80122063703d80120042006370000200441086a2003370000200241d0036a41086a2000290300370300200241d0036a41106a2009290300370300200241d0036a41186a200b290300370300200220022903b8013703d003200241386a200241d0036a10960120022802382201410420011b2105410021000240200229023c420020011b2203422088a72201417f6a220b20014b0d00200b20014f0d002005200b4102746a2201450d00200128020020084721000b02402003a7450d002005102c0b20000d010b200c21100c010b2007200c41a8026c2201200c4101742200200c41016a2210200020104b1b41a8026c102e2207450d01200720016a200241e0026a41e80010db0522014202370368200120022903f801370370200141f8006a20024180026a29030037030020014180016a20024188026a29030037030020014188016a20024190026a29030037030020014190016a20024198026a2903003703002001419c016a20083602002001410e36029801200141a8016a200241386a41800110db051a0b2002280228200228022c200228023010c003200241003602e802200242013703e0022010200241e0026a1067201041a8026c210c20022802e402210820022802e8022101200721050340200220053602f801200241386a200241f8016a1087012002280238210a02400240200820016b20022802402209490d00200120096a210020022802e002210b0c010b200120096a22002001490d032008410174220b2000200b20004b1b220f4100480d030240024020080d00200f102a210b0c010b20022802e0022008200f102e210b0b200b450d022002200f3602e4022002200b3602e002200f21080b200220003602e802200b20016a200a200910db051a0240200228023c450d00200a102c0b200541a8026a210520002101200c41d87d6a220c0d000b201041a8026c210520074198016a21012000ad422086200bad842103034020011073200141a8026a2101200541d87d6a22050d000b2007102c200241f0036a240020030f0b1033000b1035000b200241ec026a4104360200200241cc006a41023602002002420237023c20024184adc200360238200241043602e402200241b4aec2003602e002200241003602fc01200241dc9ec6003602f8012002200241e0026a3602482002200241f8016a3602e802200241386a4194adc2001041000bd90303027f017e027f02402001450d00034020002802e40121002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d0020002001410c6c6a220441e4006a2902002105200441e0006a2802002104200141016a21010c010b02400240200028020022010d002003ad210541002106410021010c010b20003301044220862003ad842105410121060b2000102c2005a72103024002402005422088a7220720012f01064f0d00200121040c010b034002400240200128020022040d002003ad2105410021040c010b200641016a210620013301044220862003ad8421050b2001102c2005a72103200421012005422088a7220720042f01064f0d000b0b200741027420046a41e8016a280200210020042007410c6c6a220141e4006a2902002105200141e0006a280200210402402006417f6a2201450d00034020002802e40121002001417f6a22010d000b0b410021010b2004450d012002417f6a210202402005a7450d002004102c0b20020d000b0b0240200041d0e1c100460d00200028020021012000102c2001450d00200128020021042001102c2004450d00024020042802002201450d0003402004102c2001210420012802002200210120000d000b0b2004102c0b0bf00101067f2001280204210202400240024003402001280200220341086a210420032f01062205410374210141002106024003402001450d0141a0e8c5002004410810dd052207450d03200141786a2101200641016a2106200441086a21042007417f4a0d000b2006417f6a21050b02402002450d002002417f6a2102200320054102746a41e4016a21010c010b0b200041a8e8c500360204200041086a41283602000c010b200341e0006a2006410c6c6a220128020841074b0d01200041d0e8c500360204200041086a41293602000b200041013602000f0b200041086a2001280200290000370300200041003602000bec3006077f017e0c7f027e017f037e230041c0026b22022400024002402001450d00200220003602200c010b200241013602200b20022001360224200241c8006a200241206a10b1030240024002400240200228024c2203450d00200241c0016a2802002104200241bc016a2802002105200241b8016a2802002106200241c8006a410c6a280200210720022802502108200241186a200241206a107520022802180d02200228021c21012002200241206a3602d001200241003a0038200242003702e401200241d0e1c1003602e0012002200136024c200241003602482002200241386a3602542002200241d0016a360250200241c8006a200241e0016a10a90220022802e001210120022902e401210920022d0038450d0120012009a72009422088a710c0030c020b200241dc016a4104360200200241f4016a4102360200200242023702e40120024184adc2003602e001200241043602d401200241d0aec2003602d0012002410036023c200241dc9ec6003602382002200241d0016a3602f0012002200241386a3602d801200241e0016a4194adc2001041000b20010d010b200241e0016a410c6a4104360200200241dc006a41023602002002420237024c20024184adc200360248200241043602e401200241d0aec2003602e001200241003602d401200241dc9ec6003602d0012002200241e0016a3602582002200241d0016a3602e801200241c8006a4194adc2001041000b2002200937022c20022001360228200241013b01442002420037023c200241d0e1c100360238200241386a41086a210a02400240024002402004450d002006200441a8026c6a210b200241e0016a410272210c200241c8006a41106a210d2006210e024002400240024002400340200e41e8006a2903004202520d0602400240200e28029801220f41034722100d00200e2903a0012109200241286a2101200228022c211102400240024002400240024002400240024003402001280200221241086a210020122f010622134103742101410021140240024003402001450d0141e98ac6002000410810dd052215450d02200141786a2101201441016a2114200041086a21002015417f4a0d000b2014417f6a21130b2011450d022011417f6a2111201220134102746a41e4016a21010c010b0b201241e0006a2014410c6c6a220128020841074b0d0141f18ac6002113201642808080807083422984a721110c020b419a8bc6002113201642808080807083421c84a721110c010b200942b8178020012802002900002216510d014131211141b8abc20021130b0240024020022d0045450d00413121014196acc20021000c010b2002280238200228023c200228024010c0032002420037023c200241d0e1c100360238200242e2c289abb68edbb7f4003703d00141002101200241e0016a410272410041da0010da051a200241c8006a410041840110da051a41e401102a2215450d1120154100360200201541046a200241e0016a41dc0010db051a201541e0006a200241c8006a41840110db051a2002410036023c2002201536023820152f0106220e4103742112417f2100024002400340024020122001470d00200e21000c020b200241d0016a201520016a41086a410810dd052214450d02200141086a2101200041016a21002014417f4a0d000b0b200242e2c289abb68edbb7f40037025c2002200a360258200220003602542002201536024c200241003602482002200241386a360250201141046a2200417f4c0d03024002402000450d002000102a2201450d14200241003602bc02200220013602e0012011413f4b0d01200120114102743a0000410121140c110b200241003602bc0241012100200241013602e0014101102a2201450d13200141033a0000200241013602bc02200220013602e001410521140c0c0b201141808001490d0e2011418080808004490d0d0c090b412d210141e9abc20021000b2002200136024c2002200036024841c7acc2004122200241c8006a41ecacc200103b000b20100d05200e2903a0012117200241c8006a200241286a10c1030240024020022802484101470d0020023502502109200228024c21184101210f0c010b20022903502109200241c8006a41186a22154200370300200d4200370300200241c8006a41086a2200420037030020024200370348200241e0016a41086a220141f9e8c500ad42808080809001841002221441086a290000370300200220142900003703e0012014102c20002001290300370300200220022903e0013703482001419db1c200ad428080808030841002221441086a290000370300200220142900003703e0012014102c200241d0016a41086a20012903002219370300200220022903e001221a3703d001200d201a370000200d41086a201937000020012000290300370300200241e0016a41106a200d290300370300200241e0016a41186a2015290300370300200220022903483703e001200241086a200241e0016a10980102402017200942b0ea017c560d004100210f2017200229031042dc0b7c42dc0b20022802081b2209540d010c060b201b4280808080708342258421094101210f41b0b1c20021180b024020022d0045450d00413121014196acc20021000c040b0240200f450d002002280238200228023c200228024010c0032002420037023c200241d0e1c100360238200242f4d2b59bc7ae98b8303703d0010c020b20022802382112200242f4d2b59bc7ae98b8303703d001201241d0e1c100460d01200228023c21110c020b103a000b200c410041da0010da051a200241c8006a410041840110da051a41e401102a2212450d0d4100211120124100360200201241046a200241e0016a41dc0010db051a201241e0006a200241c8006a41840110db051a2002410036023c200220123602380b02400340201241086a210020122f01062213410374210141002114024003402001450d01200241d0016a2000410810dd052215450d03200141786a2101201441016a2114200041086a21002015417f4a0d000b2014417f6a21130b02402011450d002011417f6a2111201220134102746a41e4016a28020021120c010b0b200242f4d2b59bc7ae98b83037025c2002200a360258200220133602542002201236024c200241003602482002200241386a360250200241003602e801200242013703e0014101102a210102400240200f0d002001450d0f200141003a000020024281808080103702e401200220013602e001200141014109102e2201450d0f200120093700012002428980808090013702e401200220013602e0010c010b2001450d0e200141013a000020024281808080103702e401200220013602e0012009a72201200241e0016a10670240024020022802e401221420022802e80122006b2001490d0020022802e00121140c010b200020016a22152000490d10201441017422122015201220154b1b22154100480d100240024020140d002015102a21140c010b20022802e00120142015102e21140b2014450d0f200220153602e401200220143602e0010b2002200020016a3602e801201420006a2018200110db051a0b200241d0016a41086a200241e0016a41086a280200360200200220022903e0013703d001200241c8006a200241d0016a10aa022002200f3a0045200241003a00442009211b200f450d02200241e0016a41086a200241386a41086a290300370300200220022903383703e0010c0c0b412d210141e9abc20021000b200220003602482002200136024c41c7acc2004122200241c8006a41ecacc200103b000b200e28029801210f0b0240200f4104470d00200e41a4016a280200410b490d000240024020022d0045450d00413121014196acc20021000c010b2002280238200228023c200228024010c0032002420037023c200241d0e1c100360238200242f5dc8de3d6ec9c98303703d00141002101200241e0016a410272410041da0010da051a200241c8006a410041840110da051a41e401102a2215450d0b20154100360200201541046a200241e0016a41dc0010db051a201541e0006a200241c8006a41840110db051a2002410036023c2002201536023820152f010622114103742112417f2100024002400340024020122001470d00201121000c020b200241d0016a201520016a41086a410810dd052214450d02200141086a2101200041016a21002014417f4a0d000b0b200242f5dc8de3d6ec9c983037025c2002200a360258200220003602542002201536024c200241003602482002200241386a360250200241003602e801200242013703e0014101102a2201450d0c200141003a000020024281808080103702e401200220013602e001410f200241e0016a10670240024020022802e401221420022802e80122016b410f490d002001410f6a210020022802e00121140c010b2001410f6a22002001490d0e201441017422152000201520004b1b22154100480d0e0240024020140d002015102a21140c010b20022802e00120142015102e21140b2014450d0d200220153602e401200220143602e0010b200220003602e801201420016a220141002900e4ec41370000200141076a41002900ebec41370000200241d0016a41086a20022802e801360200200220022903e0013703d001200241c8006a200241d0016a10aa0220024180023b0144200241e0016a41086a200241386a41086a290300370300200220022903383703e0010c0b0b412d210141e9abc20021000b200220003602482002200136024c41c7acc2004122200241c8006a41ecacc200103b000b200e41a8026a220e200b470d010c070b0b200141033a0000200241013602bc022000417f6a41034b0d01200041017422144105201441054b1b22144100480d080b200120002014102e2201450d06200220013602e001201421000b20012011360001410521140c020b0240200041034b0d00200041017422144104201441044b1b22144100480d06200120002014102e2201450d05200220013602e001201421000b20012011410274410272360000410421140c010b0240200041014b0d0020012000200041017422144102201441024b1b2214102e2201450d04200220013602e001201421000b41022114200120114102744101723b00000b200220143602bc0202400240200020146b2011490d00200021150c010b201420116a22152014490d04200041017422122015201220154b1b22154100480d04200120002015102e2201450d03200220013602e0010b2002201420116a3602bc02200120146a2013201110db051a200220153602d401200220022802e0013602d001200220022802bc023602d801200241c8006a200241d0016a10aa0220024180023b0144200241e0016a41086a200241386a41086a290300370300200220022903383703e0010c010b200241e0016a41086a200a290300370300200220022903383703e0010b2002280228200228022c200228023010c00302402007450d00200741246c21002003210103400240024020012d0000221441034b0d0002400240024020140e0404000102040b2001410c6a280200450d03200141086a280200102c0c030b2001410c6a280200450d02200141086a280200102c0c020b2001410c6a280200450d01200141086a280200102c0c010b200141086a280200450d00200141046a280200102c0b200141246a21012000415c6a22000d000b0b02402008450d002003102c0b02402004450d00200441a8026c210020064198016a2101034020011073200141a8026a2101200041d87d6a22000d000b0b02402005450d002006102c0b200241003602502002420137034820022d00ec0121004101102a2201450d002002410136024c20022002280250221441016a36025020022001360248200120146a20003a000020022d00ed01211402400240200228024c20022802502201460d00200228024821000c010b200141016a22002001490d02200141017422152000201520004b1b22154100480d020240024020010d002015102a21000c010b200228024820012015102e21000b2000450d012002201536024c20022000360248200228025021010b2002200141016a360250200020016a20143a000020022802e801200241c8006a106720022802e00122142100024020022802e4012215450d002015210120142100034020002802e40121002001417f6a22010d000b0b0240024020022802e80122130d00410021010c010b200241e0016a211041002115034002400240201520002f01064f0d0020002015410c6c6a41e0006a2112200020154103746a41086a2101201541016a21150c010b02400240200028020022010d00201b428080808070832010ad84211b41002114410021010c010b20003301044220862010ad84211b410121140b201b2116201b21090240201b422088a7220020012f0106490d0003402009221642ffffffff0f832109201441016a211420012f01042200200128020022012f01064f0d000b0b20012000410c6c6a2115200120004103746a2111200041027420016a41e8016a28020021002016a7211002402014417f6a2201450d00034020002802e40121002001417f6a22010d000b0b201541e0006a2112201141086a2101410021150b20012d0000210e02400240200228024c20022802502214460d00200228024821110c010b201441016a22112014490d042014410174220f2011200f20114b1b220f4100480d040240024020140d00200f102a21110c010b20022802482014200f102e21110b2011450d032002200f36024c20022011360248200228025021140b2002201441016a360250201120146a200e3a000020012d0001210e02400240200228024c20022802502214460d00200228024821110c010b201441016a22112014490d042014410174220f2011200f20114b1b220f4100480d040240024020140d00200f102a21110c010b20022802482014200f102e21110b2011450d032002200f36024c20022011360248200228025021140b2002201441016a360250201120146a200e3a000020012d0002210e02400240200228024c20022802502214460d00200228024821110c010b201441016a22112014490d042014410174220f2011200f20114b1b220f4100480d040240024020140d00200f102a21110c010b20022802482014200f102e21110b2011450d032002200f36024c20022011360248200228025021140b2002201441016a360250201120146a200e3a000020012d0003210e02400240200228024c20022802502214460d00200228024821110c010b201441016a22112014490d042014410174220f2011200f20114b1b220f4100480d040240024020140d00200f102a21110c010b20022802482014200f102e21110b2011450d032002200f36024c20022011360248200228025021140b2002201441016a360250201120146a200e3a000020012d0004210e02400240200228024c20022802502214460d00200228024821110c010b201441016a22112014490d042014410174220f2011200f20114b1b220f4100480d040240024020140d00200f102a21110c010b20022802482014200f102e21110b2011450d032002200f36024c20022011360248200228025021140b2002201441016a360250201120146a200e3a000020012d0005210e02400240200228024c20022802502214460d00200228024821110c010b201441016a22112014490d042014410174220f2011200f20114b1b220f4100480d040240024020140d00200f102a21110c010b20022802482014200f102e21110b2011450d032002200f36024c20022011360248200228025021140b2002201441016a360250201120146a200e3a000020012d0006210e02400240200228024c20022802502214460d00200228024821110c010b201441016a22112014490d042014410174220f2011200f20114b1b220f4100480d040240024020140d00200f102a21110c010b20022802482014200f102e21110b2011450d032002200f36024c20022011360248200228025021140b2002201441016a360250201120146a200e3a000020012d0007211102400240200228024c20022802502201460d00200228024821140c010b200141016a22142001490d042001410174220e2014200e20144b1b220e4100480d040240024020010d00200e102a21140c010b20022802482001200e102e21140b2014450d032002200e36024c20022014360248200228025021010b2002200141016a360250201420016a20113a00002012280200211120122802082201200241c8006a106702400240200228024c2212200228025022146b2001490d00200228024821120c010b201420016a220e2014490d0420124101742214200e2014200e4b1b22144100480d040240024020120d002014102a21120c010b200228024820122014102e21120b2012450d032002201436024c20022012360248200228025021140b2002201420016a360250201220146a2011200110db051a2013417f6a22130d000b20022802e801210120022802e401211520022802e00121140b200235024821092002350250211620142015200110c003200241c0026a240020092016422086840f0b1033000b1035000b5702017f027e230041306b2202240020024101410010b00220024100360228200242013703202002200241206a36022c20022002412c6a1094022002350228210320023502202104200241306a240020042003422086840b9a4205077f027e027f047e067f230041a00d6b22022400024002402001450d00200220003602380c010b200241013602380b2002200136023c200241b0076a200241386a108c02024002400240024002400240024002402002290398084203510d00200241f8006a200241b0076a41a80210db051a200241a0036a200241f8006a41a80210db051a2002200241a0036a3602c805200241b0076a200241c8056a10870120022802b8072103024020022802b407450d0020022802b007102c0b200241b0076a200241a0036a41a80210db051a200241c8056a200241b0076a10900241012100024020022d00c8054101470d00200220022d00cb053a0043200220022f00c9053b0041200241013a00400c060b200241b0076a200241c8056a41086a220141e00110db051a200241d8096a20024180086a220410ed020240024020022903d0074202520d00200241c0006a41206a22014200370300200241c0006a41186a22004280808080c000370300200241013a0068200242043703502002427f37034820024200370340200241c8056a41206a22034200370300200241c8056a41186a22054280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241c00a6a200241c0006a200241c8056a10c503200241c0006a41286a2206200241c00a6a41286a2903003703002001200241c00a6a41206a2903003703002000200241c00a6a41186a290300370300200241c0006a41106a2207200241c00a6a41106a290300370300200241c0006a41086a2208200241c00a6a41086a290300370300200220022903c00a3703402003420037030020054280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241f00a6a200241c0006a200241c8056a10c5032006200241f00a6a41286a2903003703002001200241f00a6a41206a2903003703002000200241f00a6a41186a2903003703002007200241f00a6a41106a2903003703002008200241f00a6a41086a290300370300200220022903f00a3703402003420037030020054280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241a00b6a200241c0006a200241c8056a10c5032006200241a00b6a41286a2903003703002001200241a00b6a41206a2903003703002000200241a00b6a41186a2903003703002007200241a00b6a41106a2903003703002008200241a00b6a41086a290300370300200220022903a00b3703402003420037030020054280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241e00b6a200241c0006a200241c8056a10c5032006200241e00b6a41286a2903003703002001200241e00b6a41206a2903003703002000200241e00b6a41186a2903003703002007200241e00b6a41106a2903003703002008200241e00b6a41086a290300370300200220022903e00b3703402003420037030020054280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241900c6a200241c0006a200241c8056a10c5032006200241900c6a41286a2903003703002001200241900c6a41206a2903003703002000200241900c6a41186a2903003703002007200241900c6a41106a2903003703002008200241900c6a41086a290300370300200220022903900c3703402003420037030020054280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241c00c6a200241c0006a200241c8056a10c5032006200241c00c6a41286a2903003703002001200241c00c6a41206a2903003703002000200241c00c6a41186a2903003703002007200241c00c6a41106a2903003703002008200241c00c6a41086a290300370300200220022903c00c3703402003420037030020054280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241f00c6a200241c0006a200241c8056a10c5032002419c0a6a2200200241f00c6a41086a290300370200200220022903f00c3702940a200241840d6a2802002107200241f00c6a41186a2802002101200241f00c6a41206a2802002108200241940d6a280200210320022802800d2105200228028c0d210620022903980d2109200241e0096a41086a2000290200370300200220022902940a3703e0092002280280084113460d01200241003a00cb05418102210020024181023b00c905200241013a00c8050c050b20022903d809210a200241c0006a41206a22054200370300200241c0006a41186a22064280808080c000370300200241013a006820024204370350427f21092002427f37034820024200370340200241c8056a41206a22074200370300200241c8056a41186a22004280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241e0096a200241c0006a200241c8056a10c503200241c0006a41286a2208200241e0096a41286a2903003703002005200241e0096a41206a2903003703002006200241e0096a41186a290300370300200241c0006a41106a220b200241e0096a41106a290300370300200241c0006a41086a220c200241e0096a41086a290300370300200220022903e0093703402007420037030020004280808080c000370300200241013a00f005200242043703d8052002427f3703d005200242003703c805200241900a6a200241c0006a200241c8056a10c5032008200241900a6a41286a2903003703002005200241900a6a41206a2903003703002006200241900a6a41186a290300370300200b200241900a6a41106a290300370300200c200241900a6a41086a290300370300200220022903900a37034020004200370300200241c8056a41106a2208420037030020014200370300200242003703c805200241900c6a41086a22054191b0c200ad4280808080e00084220d1002220641086a290000370300200220062900003703900c2006102c20012005290300370300200220022903900c3703c805200541acb0c200ad4280808080e000841002220641086a290000370300200220062900003703900c2006102c200820022903900c220e370300200241f00c6a41086a2001290300370300200241f00c6a41106a2201200e370300200241f00c6a41186a220620052903003703002002200e3703c00c200220022903c8053703f00c200241306a200241f00c6a41201094012002280234410020022802301bad210e024020022903d0074201520d0020022903d80722094200510d03200e200241e0076a290300220f200f200e541b221020097c2010200f7d2009827d21090b2007420037030020004280808080c000370300200241013a00f005200242043703d805200242003703c805200242002009200e7d220e200e2009561b3703d005200241c00a6a200241c0006a200241c8056a10c503200241f00c6a41286a200241c00a6a41286a290300370300200241f00c6a41206a200241c00a6a41206a2903003703002006200241c00a6a41186a2903003703002001200241c00a6a41106a290300370300200241f00c6a41086a200241c00a6a41086a290300370300200220022903c00a3703f00c20022802f8072100200241900c6a41086a2201200d1002220541086a290000370300200220052900003703900c2005102c200241c0006a41086a22062001290300370300200220022903900c37034020014197b0c200ad4280808080c001841002220541086a290000370300200220052900003703900c2005102c200241e00b6a41086a22052001290300370300200220022903900c3703e00b200241c00c6a200241b0076a109f0141c000102a2201450d0720012002290340370000200120022903e00b370010200120022900c00c370020200141086a2006290300370000200141186a2005290300370000200141286a200241c00c6a41086a290000370000200141306a200241d00c6a290000370000200141386a200241c00c6a41186a290000370000200241286a200141c000109401200228022c2105200228022821062001102c02402005410020061b220720004d0d00200220022800a00b3602d80b2002200241a30b6a2800003600db0b200241003a004320024180063b0041200241013a004020022802800d21030240200241f00c6a41186a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b0240200241840d6a280200450d002003102c0b200228028c0d21030240200241940d6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b200241900d6a280200450d062003102c0c060b410c102a2205450d074104102a2201450d072002420437024420022001360240200241b0076a200241c0006a1091010240024020022802442206200228024822016b4104490d00200228024021080c010b200141046a22082001490d09200641017422012008200120084b1b22014100480d090240024020060d002001102a21080c010b200228024020062001102e21080b2008450d082002200136024420022008360240200228024821010b410421062002200141046a360248200820016a2000360000200241c00c6a41086a2208200228024822013602002002200229034022093703c00c200541086a20013602002005200937020041002101200720004f0d03410c102a2206450d074104102a2201450d072002420437024420022001360240200241b0076a200241c0006a1091010240024020022802442207200228024822016b4104490d00200228024021070c010b200141046a220b2001490d0920074101742201200b2001200b4b1b22014100480d090240024020070d002001102a21070c010b200228024020072001102e21070b2007450d082002200136024420022007360240200228024821010b2002200141046a360248200720016a2000417f6a360000200241c00c6a41086a200228024822013602002002200229034022093703c00c200641086a200136020020062009370200410121010c030b200241c8056a20024184086a10c603024020022d00c8054101470d0020022f00c90520022d00cb054110747221000c040b200241900c6a41286a2200200241c8056a41306a290300370300200241900c6a41206a220b200241c8056a41286a220c290300370300200241900c6a41186a2211200241c8056a41206a2212290300370300200241900c6a41106a2213200241c8056a41186a2214290300370300200241900c6a41086a2215200241c8056a41106a2216290300370300200220022903d0053703900c200241f00c6a41086a200241e0096a41086a290300370300200241940d6a2003360200200241f00c6a41206a2008360200200241f00c6a41186a2001360200200241840d6a2007360200200220022903e0093703f00c200220093703980d2002200636028c0d200220053602800d200c20002903003703002012200b2903003703002014201129030037030020162013290300370300200241c8056a41086a2015290300370300200220022903900c3703c805200241c00c6a200241f00c6a200241c8056a10c503200241c0006a41086a20022903c00c370300200241c0006a41106a200241c00c6a41086a290300370300200241c0006a41186a200241c00c6a41106a290300370300200241c0006a41206a200241c00c6a41186a290300370300200241c0006a41286a200241c00c6a41206a290300370300200241c0006a41306a200241c00c6a41286a290300370300200241003a00400c040b20024184016a4104360200200241b4036a4102360200200242023702a40320024184adc2003602a0032002410436027c200241e8aec200360278200241003602cc05200241dc9ec6003602c8052002200241f8006a3602b0032002200241c8056a36028001200241a0036a4194adc2001041000b41c090c600411941dc90c6001036000b200241c8056a41206a428180808010370300200241c8056a41186a2001360200200241dc056a2001360200200220022800a00b3602d80b2002200241a00b6a41036a2800003600db0b200241f4056a20022800db0b360000200241013a00f005200220053602e405200220063602d8052002427f3703d0052002200a42ffffffff0f833703c805200220022802d80b3600f105200241f00a6a200241f00c6a200241c8056a10c503200241f00c6a41286a200241f00a6a41286a290300370300200241f00c6a41206a200241f00a6a41206a290300370300200241f00c6a41186a2207200241f00a6a41186a290300370300200241f00c6a41106a200241f00a6a41106a290300370300200241f00c6a41086a200241f00a6a41086a290300370300200220022903f00a3703f00c200241c0006a41186a220b4200370300200241c0006a41106a22064200370300200241c0006a41086a2200420037030020024200370340200241900c6a41086a22014191b0c200ad4280808080e00084220e1002220541086a290000370300200220052900003703900c2005102c20002001290300370300200220022903900c37034020014184c3c200ad42808080808002841002220541086a290000370300200220052900003703900c2005102c200620022903900c220937030020082000290300370300200241c00c6a41106a22002009370300200241c00c6a41186a22082001290300370300200220093703e00b200220022903403703c00c200241206a200241c00c6a41201094010240417f2002280224410020022802201b220120036a220520052001491b4280808080f28ba80942808080c0f588fe06200a422088a7221141ff017122051b22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76a4b0d002008420037030020004200370300200241c00c6a41086a22084200370300200242003703c00c200241900c6a41086a2201200e1002220c41086a2900003703002002200c2900003703900c200c102c20082001290300370300200220022903900c2209370340200220093703c00c200141e0c2c200ad4280808080b002841002220c41086a2900003703002002200c2900003703900c200c102c200020022903900c2209370300200241c0006a41086a200829030037030020062009370300200b2001290300370300200220093703e00b200220022903c00c370340200241186a200241c0006a4120109401417f200228021c410020022802181b2206418094ebdc034180afd0e50220051b2201200aa7220020012000491b6a220520052006491b20014b0d00200241c8056a41206a22014200370300200241c8056a41186a22054280808080c000370300200220022800d80b3602d00b2002200241d80b6a41036a2800003600d30b200241f4056a220620022800d30b360000200242043703d805200241013a00f0052002427f3703d0052002427f200a42ffffffff0f83201141ff01714101461b3703c805200220022802d00b3600f105200241a00b6a200241f00c6a200241c8056a10c503200241f00c6a41286a200241a00b6a41286a290300370300200241f00c6a41206a200241a00b6a41206a290300370300200241f00c6a41186a2207200241a00b6a41186a290300370300200241f00c6a41106a200241a00b6a41106a290300370300200241f00c6a41086a200241a00b6a41086a290300370300200220022903a00b3703f00c200241086a20032000200a422888a720022903e8072209200241f0076a290300220e10ac02200241c00c6a200241b0076a2002290308220a200241086a41086a290300220d410141112009200e84501b10ac01024020022802c00c4101470d00200241003a004320024180023b0041200241013a004020022802800d2103024020072802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b0240200241840d6a280200450d002003102c0b200228028c0d21030240200241940d6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b200241900d6a280200450d032003102c0c030b20022903c80c200241c00c6a41106a22002903001085032001420037030020054280808080c0003703002006200241900c6a41036a280000360000200242043703d805200220022800900c3600f1052002427f3703d0052002200a427f200d501b3703c805200241013a00f005200241e00b6a200241f00c6a200241c8056a10c503200241c00c6a41286a200241e00b6a41286a290300370300200241c00c6a41206a200241e00b6a41206a290300370300200241c00c6a41186a200241e00b6a41186a2903003703002000200241e00b6a41106a290300370300200241c00c6a41086a200241e00b6a41086a290300370300200220022903e00b3703c00c200241c8056a200410c703024020022d00c8054101470d00200220022d00cb053a0043200220022f00c9053b0041200241013a004020022802d00c21030240200241d80c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b0240200241d40c6a280200450d002003102c0b20022802dc0c21030240200241e40c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b200241e00c6a280200450d032003102c0c030b200241f00c6a41286a200241c8056a41306a290300370300200241f00c6a41206a200241c8056a41286a290300370300200241f00c6a41186a200241c8056a41206a290300370300200241f00c6a41106a200241c8056a41186a290300370300200241f00c6a41086a200241c8056a41106a290300370300200220022903d0053703f00c200241900c6a200241c00c6a200241f00c6a10c503200241c0006a41086a20022903900c370300200241c0006a41106a200241900c6a41086a290300370300200241c0006a41186a200241900c6a41106a290300370300200241c0006a41206a200241900c6a41186a290300370300200241c0006a41286a200241900c6a41206a290300370300200241c0006a41306a200241900c6a41286a290300370300200241003a00400c020b200220022800d80b3602d00b2002200241d80b6a41036a2800003600d30b200241003a0043200241800c3b0041200241013a004020022802800d2103024020072802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b0240200241840d6a280200450d002003102c0b200228028c0d21030240200241940d6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b200241900d6a280200450d012003102c0c010b200241013a0040200220003b0041200220004110763a004302402001450d002001410c6c21002005210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b02402007450d002005102c0b02402003450d002003410c6c21002006210103400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b2008450d002006102c0b200410920220022d004021000b4101102a2201450d00200242013702b407200220013602b00702400240200041ff01714101460d00200241013602b807200141003a0000200241c8006a2903002109024020022802b4072200417f6a41074b0d00200041017422034109200341094b1b22034100480d04200120002003102e2201450d03200220033602b407200220013602b0070b200241093602b80720012009370001200241d8006a2802002100200241e0006a2802002201200241b0076a106702402001450d0020002001410c6c6a2108034020002802002106200041086a2802002201200241b0076a10670240024020022802b407220520022802b80722036b2001490d0020022802b00721050c010b200320016a22072003490d06200541017422042007200420074b1b22074100480d060240024020050d002007102a21050c010b20022802b00720052007102e21050b2005450d05200220073602b407200220053602b0070b2002200320016a3602b807200520036a2006200110db051a2000410c6a22002008470d000b0b200241e4006a2802002100200241ec006a2802002201200241b0076a10670240024020010d0020022802b407210620022802b80721080c010b20002001410c6c6a2104034020002802002107200041086a2802002201200241b0076a10670240024020022802b407220620022802b80722036b2001490d0020022802b00721050c010b200320016a22052003490d06200641017422082005200820054b1b22084100480d060240024020060d002008102a21050c010b20022802b00720062008102e21050b2005450d05200220083602b407200220053602b007200821060b2002200320016a22083602b807200520036a2007200110db051a2000410c6a22002004470d000b0b200241d0006a290300210902400240200620086b4108490d0020022802b00721010c010b200841086a22012008490d04200641017422002001200020014b1b22004100480d040240024020060d002000102a21010c010b20022802b00720062000102e21010b2001450d03200220003602b407200220013602b0070b2002200841086a3602b807200120086a2009370000200241f0006a2d00002105024020022802b40720022802b8072200470d00200041016a22032000490d04200041017422062003200620034b1b22034100480d040240024020000d002003102a21010c010b200120002003102e21010b2001450d03200220033602b407200220013602b0070b2002200041016a22033602b807200120006a20053a00000c010b200241013602b807200141013a0000200241c0006a410172200241b0076a10ba0320022802b807210320022802b00721010b2003ad4220862001ad842109024020022d00400d000240200241e0006a2802002200450d00200241d8006a28020021012000410c6c210003400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b0240200241dc006a280200450d002002280258102c0b0240200241ec006a2802002200450d00200241e4006a28020021012000410c6c210003400240200141046a280200450d002001280200102c0b2001410c6a2101200041746a22000d000b0b200241e8006a280200450d002002280264102c0b200241a00d6a240020090f0b1033000b1035000bc60505017f027e077f017e017f230041206b220324002002290300210420012903002105200141106a210620022802102107024002400240024002400240200141146a2802002208200141186a28020022096b200241186a280200220a490d00200628020021080c010b2009200a6a220b2009490d022008410174220c200b200c200b4b1b220bad420c7e220d422088a70d02200da7220c4100480d020240024020080d00200c102a21080c010b20062802002008410c6c200c102e21080b2008450d0120012008360210200141146a200b3602000b20082009410c6c6a2007200a410c6c10db051a200141186a2009200a6a36020020024100360218200341086a200641086a280200360200200320062902003703002001411c6a2106200228021c210b02400240200141206a2802002208200141246a28020022096b200241246a280200220a490d00200628020021080c010b2009200a6a220c2009490d022008410174220e200c200e200c4b1b220cad420c7e220d422088a70d02200da7220e4100480d020240024020080d00200e102a21080c010b20062802002008410c6c200e102e21080b2008450d012001200836021c200141206a200c3602000b427f200520047c220420042005541b210520082009410c6c6a200b200a410c6c10db051a200141246a2009200a6a36020020024100360224200341106a41086a200641086a28020036020020032006290200370310200229030822042001290308220d200d2004561b210420012d0028450d024101210120022d0028450d020c030b1033000b1035000b410021010b20002005370300200020032903003702102000200329031037021c200020013a002820002004370308200041186a200341086a280200360200200041246a200341106a41086a2802003602000240200241146a280200450d002007102c0b0240200241206a280200450d00200b102c0b200341206a24000bb91005067f017e017f017e067f230041f0006b2202240020012802202103200241306a41186a4200370300200241306a41106a22044200370300200241306a41086a2205420037030020024200370330200241e0006a41086a220641ecddc500ad4280808080f000841002220741086a290000370300200220072900003703602007102c2005200629030037030020022002290360370330200641c9f8c200ad4280808080a001841002220741086a290000370300200220072900003703602007102c200420022903602208370300200241106a41086a2005290300370300200241106a41106a2008370300200241106a41186a20062903003703002002200837035020022002290330370310200241306a200241106a412010d00120022802302206410120061b2105024002400240024002400240024002400240024020032002290234420020061b2208422088a7490d002008a7450d012005102c0c010b2003200520034105746a10cb03210602402008a7450d002005102c0b20060d010b200241306a41186a22054200370300200241306a41106a22074200370300200241306a41086a2203420037030020024200370330200241e0006a41086a220641ecddc500ad4280808080f000841002220941086a290000370300200220092900003703602009102c2003200629030037030020022002290360370330200641f3ddc500ad4280808080c001841002220941086a290000370300200220092900003703602009102c200241d0006a41086a22092006290300220837030020022002290360220a3703502004200a370000200441086a220b2008370000200241106a41086a220c2003290300370300200241106a41106a220d2007290300370300200241106a41186a220e200529030037030020022002290330370310200241086a200241106a4120109401200128021c200228020c410020022802081b220f470d0120054200370300200742003703002003420037030020024200370330200641a3dbc500ad42808080808001841002221041086a290000370300200220102900003703602010102c2003200629030037030020022002290360370330200641a0c6c500ad4280808080c000841002221041086a290000370300200220102900003703602010102c20092006290300220837030020022002290360220a3703502004200a370000200b2008370000200c2003290300370300200d2007290300370300200e200529030037030020022002290330370310200241306a200241106a10f00220022802302206410120061b210d200128022022032002290234420020061b2208422088a74f0d03200d20034105746a220e450d032002410036023820024201370330200128020021044104102a22060d020c070b20004180063b0001200041013a0000200041036a41003a00000c050b20004180063b0001200041013a0000200041036a41003a00000c040b20024284808080c0003702342002200636023020062004360000200128020421072001410c6a2802002206200241306a10670240024020022802342205200228023822046b2006490d00200228023021050c010b200420066a22092004490d032005410174220b2009200b20094b1b22094100480d030240024020050d002009102a21050c010b200228023020052009102e21050b2005450d0520022009360234200220053602300b2002200420066a360238200520046a2007200610db051a200141106a2802002104200141186a2802002206200241306a10670240024020060d002002280234210520022802382109200f21070c010b20042006410c6c6a210c03402004280200210b200441086a2802002206200241306a10670240024020022802342205200228023822036b2006490d00200228023021070c010b200320066a22072003490d05200541017422092007200920074b1b22094100480d050240024020050d002009102a21070c010b200228023020052009102e21070b2007450d072002200936023420022007360230200921050b2002200320066a2209360238200720036a200b200610db051a2004410c6a2204200c470d000b20012802202103200128021c21070b02400240200520096b4104490d00200941046a2104200228023021060c010b200941046a22042009490d03200541017422062004200620044b1b220b4100480d030240024020050d00200b102a21060c010b20022802302005200b102e21060b2006450d052002200b36023420022006360230200b21050b20022004360238200620096a200736000002400240200520046b41034d0d00200521070c010b200441046a22072004490d03200541017422092007200920074b1b22074100480d030240024020050d002007102a21060c010b200620052007102e21060b2006450d0520022007360234200220063602300b200620046a2003360000200141246a200441046aad4220862006ad84200e100c210402402007450d002006102c0b20044101460d010b20004180083b0001200041013a0000200041036a41003a00002008a7450d02200d102c0c020b410c102a2206450d024104102a2204450d0220024284808080c000370234200220043602302004200f360000200e200241306a109101200241106a41086a2002280238220436020020022002290330220a370310200641086a20043602002006200a370200200041306a41013a0000200041286a428180808010370200200041246a2006360200200041206a4100360200200041186a4204370300200041106a42e400370300200041086a427f370300200041316a2002280030360000200041346a200241336a280000360000200041003a00002008a7450d01200d102c0c010b1035000b200241f0006a24000f0b1033000bbd0502057f017e230041f0006b220224000240024020012802004111460d00200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c010b024002400240024002400240200141086a2d00000e06050402010004050b200141c8006a21030c020b200141d0006a21030c010b200141186a21030b200241306a41186a4200370300200241306a41106a22044200370300200241306a41086a2205420037030020024200370330200241e0006a41086a220141e4d2c500ad42808080808001841002220641086a290000370300200220062900003703602006102c2005200129030037030020022002290360370330200141ecd2c500ad42808080808001841002220641086a290000370300200220062900003703602006102c200420022903602207370300200241106a41086a2005290300370300200241106a41106a2007370300200241106a41186a200129030037030020022007370350200220022903303703102002200241106a109801024020032903004280ade20420022903087d4280ade20420022802001b560d00200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c030b200041800c3b0001200041013a0000200041036a41003a00000c020b200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c010b200241c4006a410136020020024201370234200241fcc4c50036023020024104360214200241a4ebc3003602102002200241106a360240200241306a4184c5c5001041000b200241f0006a24000bd13b07047f017e047f017e037f027e1a7f230041e0036b2202240002400240024002400240024002400240024020014104490d0020002800002103410041002802dca1462200410120001b3602dca1460240200041014b0d000240024020000e020001000b4100419cb0c0003602e4a146410041dc9ec6003602e0a146410041023602dca1460c010b034041002802dca1464101460d000b0b10164101470d06200241a0016a41186a4200370300200241a0016a41106a22044200370300200241a0016a41086a22014200370300200242003703a001200241206a41086a220041a3dbc500ad42808080808001841002220541086a290000370300200220052900003703202005102c20012000290300370300200220022903203703a00120004187a6c500ad42808080808001841002220541086a290000370300200220052900003703202005102c200420022903202206370300200241e0006a41086a2001290300370300200241e0006a41106a2006370300200241e0006a41186a2000290300370300200220063703c803200220022903a001370360200241106a200241e0006a4120109401200228021421002002280210210141002105200241a0016a41004190aac500ad4280808080e003841017108d012000410020011b21010240024020022802a00122000d00410121040c010b20022902a4012206422088a72205450d0320002d0000220441014b0d032005417f6a2105410021070240024020040e020100010b410121070b20054104490d032000280001210502400240024020070d0020052003460d0141002104200520034f0d02410121040c020b4101210420052001490d010b410021040b200021050b200120034f0d012004450d014101102a2200450d07200041003a0000200041014105102e2200450d07200020033600012002200536026020022006370264200241a0016a200241e0006a10c90320022802a401210141004190aac500ad4280808080e0038420023502a80142208620022802a0012207ad842000ad4280808080d000841018210402402001450d002007102c0b02402005450d002006a7450d002005102c0b2000102c4101210820044101470d0620022003360218200241a0016a41186a4200370300200241a0016a41106a22094200370300200241a0016a41086a22014200370300200242003703a001200241206a41086a220041a3dbc500ad42808080808001841002220541086a290000370300200220052900003703202005102c20012000290300370300200220022903203703a001200041a0c6c500ad4280808080c000841002220541086a290000370300200220052900003703202005102c200920022903202206370300200241e0006a41086a2001290300370300200241e0006a41106a2006370300200241e0006a41186a2000290300370300200220063703c803200220022903a001370360200241a0016a200241e0006a10f00220022802a001210a20022902a401210b200241a0016a41e9dabdf30610ca0320022802a001210320022802a40121070240024020022802a80122000d004100210c4100210d0c010b20004105742201410575220c41ffffff3f71200c470d09200c41057422054100480d092005102a2208450d08200320016a210e20004105742104410021000340200320006a22012900002106200141086a290000210f200141106a2900002110200820006a220541186a200141186a290000370000200541106a2010370000200541086a200f370000200520063700002004200041206a2200470d000b200e20036b41606a41057641016a210d0b02402007450d002003102c0b200d4115490d0402404101450d00200d41017622114105742200417f4c0d002000102a2212450d08200841606a2113200841a07f6a211441042115410021164100211741002118200d2119034020192107410021194101210402402007417f6a2205450d00024002400240024002400240200820054105746a2007410574220e20086a41406a412010dd054100480d002007417e6a21032014200e6a210041002119410021010340024020032001470d00200721040c080b200141016a2101200041206a2000412010dd052105200041606a21002005417f4a0d000b200141016a21042001417f7320076a21050c010b2014200e6a210002400340024020054101470d00410021050c020b2005417f6a2105200041206a2000412010dd052101200041606a210020014100480d000b0b20072005490d012007200d4b0d03200720056b22044101762203450d002013200e6a2100200820054105746a21010340200241a0016a41186a220e200141186a221a290000370300200241a0016a41106a221b200141106a221c290000370300200241a0016a41086a221d200141086a221e290000370300200220012900003703a001200041086a221f2900002106200041106a2220290000210f200041186a2219290000211020012000290000370000201a2010370000201c200f370000201e20063700002019200e2903003700002020201b290300370000201f201d290300370000200020022903a001370000200041606a2100200141206a21012003417f6a22030d000b0b024020050d00200521190c050b0240200441094d0d00200521190c050b2007200d4b0d01200720056b2103200820054105746a210e034020072005417f6a2219490d040240200720196b22044102490d00200820054105746a2200200820194105746a2205412010dd05417f4a0d00200241a0016a41186a221d200541186a2201290000370300200241a0016a41106a221e200541106a221a290000370300200241a0016a41086a221f200541086a221b290000370300200220052900003703a00120052000290000370000201b200041086a290000370000201a200041106a2900003700002001200041186a2900003700004101211c024020044103490d00200541c0006a200241a0016a412010dd05417f4a0d0041022101200e210002400340200041186a200041386a290000370000200041106a200041306a290000370000200041086a200041286a2900003700002000200041206a221a29000037000020032001460d01200041c0006a211b2001211c201a2100200141016a2101201b200241a0016a412010dd05417f4a0d020c000b0b2001211c0b2005201c4105746a220020022903a001370000200041186a201d290300370000200041106a201e290300370000200041086a201f2903003700000b2019450d05200e41606a210e200341016a2103201921052004410a4f0d050c000b0b200520071047000b20072005417f6a2219490d010b2007200d103f000b201920071047000b024020182016470d00201641016a22002016490d0b201641017422012000200120004b1b220041ffffffff01712000470d0b200041037422014100480d0b0240024020160d002001102a21150c010b201520164103742001102e21150b2015450d0a20002116201721180b201520184103746a2200200436020420002019360200201741016a22182117024020184102490d0002400340024002400240024020152018417f6a22174103746a2200280200450d00201841037420156a220341746a2802002205200028020422014d0d000240201841024b0d0020182117410221182019450d0d0c080b20152018417d6a221d4103746a2802042200200120056a4d0d010240201841034b0d0020182117410321182019450d0d0c080b200341646a280200200020056a4d0d01201821170c060b20184103490d012000280204210120152018417d6a221d4103746a28020421000b20002001490d010b2018417e6a211d0b0240024002400240024002402018201d41016a22214b2222450d002018201d4b2223450d012015201d4103746a221e2802042224201e2802006a2200201520214103746a221f2802002220490d022000200d4b0d03200820204105746a221b201f280204221c41057422016a210320004105742105200020206b2207201c6b2200201c4f0d04201220032000410574220110db05221a20016a210402400240201c4101480d00200041014e0d010b20032100201a21010c060b201320056a21052003210003402005200041606a2203200441606a220720072003412010dd05410048220e1b2201290000370000200541186a200141186a290000370000200541106a200141106a290000370000200541086a200141086a29000037000020042007200e1b21040240201b20032000200e1b2200490d00201a21010c070b200541606a2105201a2101201a2004490d000c060b0b41d087c600202120181038000b41d087c600201d20181038000b202020001047000b2000200d103f000b2012201b200110db05221a20016a210402400240201c4101480d002007201c4a0d010b201b2100201a21010c010b200820056a210e201a2101201b2100034020002003200120032001412010dd0541004822071b2205290000370000200041186a200541186a290000370000200041106a200541106a290000370000200041086a200541086a2900003700002001200141206a20071b2101200041206a2100200341206a200320071b2203200e4f0d01200420014b0d000b0b20002001200420016b41607110db051a02402023450d00201e2020360200201e41046a2024201c6a3602002022450d02201f201f41086a20182021417f736a41037410dc051a20172118201741014d0d030c010b0b41a888c600201d20181038000b418ab4c000411d41acfec5001036000b2019450d050c000b0b103a000b200241ec006a4104360200200241b4016a4102360200200242023702a40120024184adc2003602a0012002410436026420024184afc20036026020024100360224200241dc9ec6003602202002200241e0006a3602b0012002200241206a360268200241a0016a4194adc2001041000b2000450d042006a7450d042005102c0c040b02402006a7450d002000102c0b41c8dac500ad4280808080d0058410040c030b02402016450d002015102c0b2011450d012012102c0c010b200d4102490d002008200d417f6a22014105746a21044101210503400240024002400240200d20012200417f6a2201490d00200d20016b22074102490d03200820004105746a2200200820014105746a2203412010dd05417f4a0d03200241a0016a41186a2218200341186a220e290000370300200241a0016a41106a221c200341106a221a290000370300200241a0016a41086a2215200341086a221b290000370300200220032900003703a00120032000290000370000201b200041086a290000370000201a200041106a290000370000200e200041186a2900003700004101210020074103490d02200341c0006a200241a0016a412010dd05417f4a0d0241002107200421000340200041186a200041386a290000370000200041106a200041306a290000370000200041086a200041286a2900003700002000200041206a221a29000037000020052007220e460d02200e417f6a2107200041c0006a211b201a2100201b200241a0016a412010dd05417f4a0d020c000b0b2001200d1047000b4102200e6b21000b200320004105746a220020022903a001370000200041186a2018290300370000200041106a201c290300370000200041086a20152903003700000b200441606a21042005417f6a210520010d000b0b41012100200a4101200a1b2119200b4200200a1b2206a721230240024002402006422088a722010d0041002101410021030c010b201920014105746a211b200241b8026a2125200241a0016a410272211f200241e1026a21204100211e4100212141012117410021072019210403400240024002400240200d41014b0d004100210141002103410121000240200d0e020600060b0340200241a0016a41186a200441186a290000370300200241a0016a41106a200441106a290000370300200241a0016a41086a200441086a290000370300200220042900003703a0012008200241a0016a412010dd05450d03200741016a2107201b200441206a2204470d000c020b0b0340200241a0016a41186a200441186a290000370300200241a0016a41106a200441106a290000370300200241a0016a41086a200441086a290000370300200220042900003703a001200441206a21040240200d450d0041002100200d210103402001410176220520006a22032000200820034105746a200241a0016a412010dd054101481b2100200120056b220141014b0d000b200820004105746a200241a0016a412010dd05450d040b200741016a21072004201b470d000b0b201e210120212103201721000c030b200441206a2104410021000b0240200d20004b0d0041d087c6002000200d1038000b2002200736021c200241a0016a41186a22054200370300200241a0016a41106a22034200370300200241a0016a41086a22014200370300200242003703a001200241206a41086a221d41ecddc500ad4280808080f0008422101002220e41086a2900003703002002200e290000370320200e102c2001201d290300370300200220022903203703a001201d41c9f8c200ad4280808080a001841002220e41086a2900003703002002200e290000370320200e102c200241c8036a41086a2218201d290300220637030020022002290320220f3703c8032009200f370000200941086a221c2006370000200241e0006a41086a22122001290300370300200241e0006a41106a22162003290300370300200241e0006a41186a22132005290300370300200220022903a001370360200241a0016a200241e0006a412010d00120022802a001220e4101200e1b211a024002400240200720022902a4014200200e1b2206422088a7490d002006a7450d01201a102c0c010b2007201a20074105746a10cb03210e02402006a7450d00201a102c0b200e0d010b200241a0016a10cc030240024002400240024020022802a001220a450d0020022802b401212420022802b001212620022802ac01211420022802a801212220022802a401212720022802182111200542003703002003420037030020014200370300200242003703a001201d20101002220e41086a2900003703002002200e290000370320200e102c2001201d290300370300200220022903203703a001201d41f3ddc500ad4280808080c001841002220e41086a2900003703002002200e290000370320200e102c2018201d290300220637030020022002290320220f3703c8032009200f370000201c2006370000201220012903003703002016200329030037030020132005290300370300200220022903a001370360200241086a200241e0006a4120109401200228020c212820022802082129200228021c212a200242013703a001200241003602a8014104102a2201450d0a20024284808080c0003702a401200220013602a001200120113600002022200241a0016a10670240024020022802a401220520022802a80122016b2022490d0020022802a00121050c010b200120226a22032001490d0c2005410174220e2003200e20034b1b22034100480d0c0240024020050d002003102a21050c010b20022802a00120052003102e21050b2005450d0b200220033602a401200220053602a0010b2002200120226a3602a801200520016a200a202210db051a2024200241a0016a10672024450d0120142024410c6c6a211520142105034020052802002118200541086a2802002201200241a0016a10670240024020022802a401220e20022802a80122036b2001490d0020022802a001211a0c010b200320016a221a2003490d0d200e410174221c201a201c201a4b1b221c4100480d0d02400240200e0d00201c102a211a0c010b20022802a001200e201c102e211a0b201a450d0c2002201c3602a4012002201a3602a001201c210e0b2002200320016a221c3602a801201a20036a2018200110db051a2005410c6a22052015470d000c030b0b410221050c020b20022802a401210e20022802a801211c0b02400240200e201c6b4104490d0020022802a00121010c010b201c41046a2201201c490d09200e41017422052001200520014b1b22054100480d0902400240200e0d002005102a21010c010b20022802a001200e2005102e21010b2001450d08200220053602a401200220013602a0012005210e0b2002201c41046a22053602a8012001201c6a2028410020291b221a36000002400240200e20056b41034d0d00200e21030c010b200541046a22032005490d09200e41017422182003201820034b1b22034100480d0902400240200e0d002003102a21010c010b2001200e2003102e21010b2001450d08200220033602a401200220013602a0010b200120056a202a360000200241a0016a41e9dabdf306200820004105746a2001201c41086a10cd0320022d00a0014101460d0102402003450d002001102c0b02402027450d00200a102c0b02402024450d002024410c6c21012014210003400240200041046a280200450d002000280200102c0b2000410c6a2100200141746a22010d000b0b410121052026450d002014102c0b4100210102402023450d002019102c0b20212103201721000c040b201d201f41086a290000370300200241206a41106a2200201f41106a290000370300200241206a41186a2205201f41186a290000370300200241206a41206a220e201f41206a290000370300200241206a41286a2218201f41286a290000370300200241206a41306a221c201f41306a290000370300200241206a41376a2215201f41376a2900003700002002201f29000037032020022d00a101212802402003450d002001102c0b200241e0006a41376a22012015290000370000200241e0006a41306a2203201c290300370300200241e0006a41286a221c2018290300370300200241e0006a41206a2218200e29030037030020132005290300370300201620002903003703002012201d29030037030020022002290320370360024041002802d8a1464103490d002002412a3602d4032002412a3602cc032002200241186a3602d00320022002411c6a3602c80341002802e4a146210041002802e0a146210541002802dca146210e200241a7033602e001200242b5808080103703d801200241d8aac5003602d401200242103702cc01200241c8aac5003602c801200242023703c001200242023703b001200241b0aac5003602ac01200241083602a801200241c0aac5003602a401200241033602a001200041d4b3c000200e410246220e1b28021021002002200241c8036a3602bc01200541ecb3c000200e1b200241a0016a20001102000b20202002290360370000202041086a2012290300370000202041106a2016290300370000202041186a2013290300370000202041206a2018290300370000202041286a201c290300370000202041306a2003290300370000202041376a2001290000370000200220283a00e0022002202a3602dc022002201a3602d802200220243602d402200220263602d002200220143602cc02200220223602c802200220273602c4022002200a3602c002200220113602bc02200241133602b80220024202370388022002200241a0016a3602dc03200241c8036a200241dc036a10870120022802c80320022802cc0320022802d00310cf03210020251092020240201e2021470d00201e41016a2201201e490d07201e41017422052001200520014b1b22214100480d0702400240201e0d002021102a21170c010b2017201e2021102e21170b2017450d060b2017201e6a4103410420001b3a0000201e41016a211e0b200741016a2107201e210120212103201721002004201b470d000b0b02402023450d002019102c0b4104210502400240024002402001450d00024020002d00002207417c6a220441014b0d0020040e020201020b200721050b20030d010c020b0240024020014101470d00410421050c010b20002d00012205417c6a220441014b0d0041042105024020040e020001000b4102210403402004450d07024020012004470d00410421050c020b200020046a2107200441016a21044104210520072d000022074104460d000b20074105460d00200721050b2003450d010b2000102c0b4101210120054104470d00200228021821014101102a2200450d02200041013a0000200041014105102e2200450d022000200136000141004190aac500ad4280808080e003842000ad4280808080d0008410192000102c200c450d012008102c0c010b0240200c450d002008102c0b02402001200345720d002000102c0b412e210341f5dac5002100200241c8036a2101024002400240024020050e0400010203000b412d210341c8dac5002100200241206a21010c020b411f210341a9dac5002100200241e0006a21010c010b41fbd9c5002100200241a0016a21010b20012003360204200120003602002003ad4220862000ad8410040b200241e0036a240042010f0b1033000b1035000bff0201067f230041106b220224000240024002400240024002400240200128020022030d00410121040c010b0240200141086a28020041056a2204417f4c0d0020040d0120024100360208200242013703000c020b103a000b2004102a2205450d04200241003602082002200436020420022005360200024020030d00200541003a0000200241013602080c030b20040d010b4101102a2205450d0320024101360204200220053602000b200541013a000020024101360208200141086a2802002204200210670240024020022802042201200228020822056b2004490d00200228020021010c010b200520046a22062005490d02200141017422072006200720064b1b22064100480d020240024020010d002006102a21010c010b200228020020012006102e21010b2001450d0320022006360204200220013602000b2002200520046a360208200120056a2003200410db051a0b20002002290300370200200041086a200241086a280200360200200241106a24000f0b1035000b1033000bfd0403017f017e0a7f230041e0006b220224002002200136020c20022002410c6a102322034220883e0214200220033e02102002200241106a1075024020022802000d0002400240200228021422044160712205417f4c0d002002280204210602400240200441057622010d00410121070c010b2005102a2207450d020b2001ad2103024002402006450d0041002108034020042109200241003a0058200841016a210841002101024002400240034020092001460d01200241386a20016a200228021022052d00003a00002002200541016a3602102002200141016a22053a00582005210120054120470d000b200241186a41186a220a200241386a41186a290300370300200241186a41106a220b200241386a41106a290300370300200241186a41086a220c200241386a41086a290300370300200220022903383703182003a72003422088a72201470d020240200141016a22042001490d002001410174220d20042004200d491b220441ffffff3f712004470d002004410574220d41004e0d020b1035000b200241003602140240200141ff0171450d00200241003a00580b2003a7450d072007102c0c070b0240024020010d00200d102a21070c010b20072001410574200d102e21070b2007450d052003428080808070832004ad8421030b200920056b2104200720014105746a22012002290318370000200141186a200a290300370000200141106a200b290300370000200141086a200c29030037000020034280808080107c210320082006470d000b2002200920056b3602140c010b2007450d030b2000200337020420002007360200200241e0006a24000f0b103a000b1033000b41d88bc600412e200241386a41c88bc600103b000bd90b04067f017e067f017e23004190016b22022400200241f0006a41186a22034200370300200241f0006a41106a22044200370300200241f0006a41086a2205420037030020024200370370200241e0006a41086a220641ecddc500ad4280808080f000841002220741086a290000370300200220072900003703602007102c2005200629030037030020022002290360370370200641f3ddc500ad4280808080c001841002220741086a290000370300200220072900003703602007102c200420022903602208370300200241306a41086a22092005290300370300200241306a41106a220a2008370300200241306a41186a220b20062903003703002002200837035020022002290370370330200241186a200241306a4120109401200228021c210c2002280218210d200641a3dbc500ad42808080808001841002220741086a290000370300200220072900003703602007102c200241206a41086a220e200629030037030020022002290360370320200641abdbc500ad4280808080a002841002220741086a290000370300200220072900003703602007102c200241d0006a41086a22072006290300370300200220022903603703502002200c4100200d1b220c3602602003200241e0006aad220f4280808080c0008422081006220641186a2900003703002004200641106a2900003703002005200641086a290000370300200220062900003703702006102c200b2003290300370300200a20042903003703002009200529030037030020022002290370370330024041c000102a2206450d00200620022903203700002006200229035037001020062002290330370020200641086a200e290300370000200641186a2007290300370000200641286a2009290300370000200641306a200a290300370000200641386a200b29030037000020022000360260200320081006220741186a2900003703002004200741106a2900003703002005200741086a290000370300200220072900003703702007102c200b2003290300370300200a20042903003703002009200529030037030020022002290370370330200641c000418001102e2206450d0020062002290330370040200641d8006a200241306a41186a2203290300370000200641d0006a200241306a41106a2207290300370000200641c8006a200241306a41086a220929030037000041012105200241106a200641e000410141004100109701200228021021042006102c024020044101460d00200241e0006a41086a220641a3dbc500ad42808080808001841002220541086a290000370300200220052900003703602005102c200241206a41086a20062903003703002002200229036037032020064182aac500ad4280808080e001841002220541086a290000370300200220052900003703602005102c200241d0006a41086a2006290300370300200220022903603703502002200c360260200241f0006a41186a2205200f4280808080c000841006220641186a290000370300200241f0006a41106a2204200641106a290000370300200241f0006a41086a220a200641086a290000370300200220062900003703702006102c20032005290300370300200720042903003703002009200a2903003703002002200229037037033041c000102a2206450d01200620022903203700002006200229035037001020062002290330370020200641086a200241206a41086a290300370000200641186a200241d0006a41086a290300370000200641286a200241306a41086a290300370000200641306a200241306a41106a290300370000200641386a200241306a41186a290300370000200241f0006a2001109f01200641c000418001102e2206450d0120062002290070370040200641d8006a200241f0006a41186a290000370000200641d0006a200241f0006a41106a290000370000200641c8006a200241f0006a41086a290000370000200241086a200641e000109401200228020c2105200228020821042006102c200541004720044100477121050b20024190016a240020050f0b1033000bcb0405017f017e0b7f017e017f230041206b22012400200110222202a7220336020820012002422088a7220436020c02402004450d0020032d0000210520012004417f6a36020c2001200341016a360208200541014b0d00024002400240024002400240024020050e020001000b200141106a200141086a107720012802102206450d06200141186a2802002107200128021421082001200141086a107520012802000d05200128020c410c6e2209410c6c2203417f4c0d022001280204210a0240024020030d004104210b0c010b2003102a220b450d040b02400240200a450d004100210c41002104410021050340200141106a200141086a10772001280210220d450d02200541016a210320012902142102024020052009470d00200c2003200c20034b1b2209ad420c7e220e422088a70d08200ea7220f4100480d080240024020050d00200f102a210b0c010b200b2004200f102e210b0b200b450d070b200b20046a2205200d360200200541046a2002370200200c41026a210c2004410c6a210420032105200a2003470d000b0b200b450d0620060d020c070b02402005450d00200b210303400240200341046a280200450d002003280200102c0b2003410c6a2103200441746a22040d000b0b2009450d05200b102c0c050b410021060b2000200836020420002006360200200041146a200a360200200041106a20093602002000410c6a200b360200200041086a2007360200200141206a24000f0b103a000b1033000b1035000b2008450d002006102c0b41d88bc600412e200141106a41888cc600103b000b8e0402017f017e23004190016b22052400200520013602040240200541046a20022004ad4220862003ad8410242206422088a72201450d002006a722042d0000220341014b0d00410021020240024020030e020100010b41002102200541003a008801200441016a21042001417f6a21010340024020012002470d00200241ff0171450d03200541003a0088010c030b200541c8006a20026a200420026a2d00003a00002005200241016a22033a00880120032102200341c000470d000b200541086a41386a200541c8006a41386a290300370300200541086a41306a200541c8006a41306a290300370300200541086a41286a200541c8006a41286a290300370300200541086a41206a200541c8006a41206a290300370300200541086a41186a200541c8006a41186a290300370300200541086a41106a200541c8006a41106a290300370300200541086a41086a200541c8006a41086a29030037030020052005290348370308410121020b200020023a000020002005290308370001200041096a200541106a290300370000200041116a200541186a290300370000200041196a200541206a290300370000200041216a200541286a290300370000200041296a200541306a290300370000200041316a200541386a290300370000200041396a200541c0006a29030037000020054190016a24000f0b41d88bc600412e200541c8006a41888cc600103b000baf0201037f23004180016b2202240002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001104221000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000b20024180016a240020000f0b20044180011047000b20044180011047000b7603017f017e017f230041106b220324000240024002402002ad4220862000ad8410212204428080808010540d00410121022004a72d0000220541014b0d0020050e020102010b41d88bc600412e200341086a41888cc600103b000b410021020b02402001450d002000102c0b200341106a240020020b950703067f067e017f230041e0006b220224002002411436020c200241b5b5c000360208200241106a41b5b5c000ad4280808080c002841003108d01024002400240024020022802102203450d00200228021421042002200241186a2802002205360224200220033602200240024002402005450d0020022005417f6a3602242002200341016a36022020032d00002105200241c8006a200241206a107420022802482206450d00200228024c2107200541ff01714101460d012007450d002006102c0b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a36024441012105200241dc006a41013602002002420137024c200241d0b0c2003602482002200241386a360258200241c4006a41c49ac500200241c8006a10391a200235023042208620023502288410040240200228022c450d002002280228102c0b410221070c010b200241d0006a3502004220862007ad84210841012107410021050b02402004450d002003102c0b20050d0020074101460d01024020062802082205ad220942287e220a422088a70d00200aa72204417f4c0d00200628020021030240024020040d00410821060c010b2004102a2206450d040b0240024020050d004200210a0c010b200541286c21044200210a200621050340200341086a2903002108200341106a290300210b200341186a290300210c2003290300210d200541206a200341206a290300370300200541186a200c370300200541106a200b370300200541086a20083703002005200d370300200541286a2105200a4280808080107c210a200341286a2103200441586a22040d000b0b200a20098421080c020b103a000b42002108410821060b20024100360250200242013703482008422088a72203200241c8006a106702402003450d002006200341286c6a210e2006210503402005200241c8006a109101200541206a290300210a02400240200228024c2204200228025022036b4108490d00200228024821040c010b200341086a22072003490d04200441017422032007200320074b1b22034100480d040240024020040d002003102a21040c010b200228024820042003102e21040b2004450d032002200336024c20022004360248200228025021030b2002200341086a360250200420036a200a370000200e200541286a2205470d000b0b2002350250422086200235024884210a02402008a7450d002006102c0b200241e0006a2400200a0f0b1033000b1035000b9e0e06057f017e017f017e037f017e230041c0016b22022400200241086a41186a22034200370300200241086a41106a22044200370300200241086a41086a2205420037030020024200370308200241f8006a41086a220641bac6c500ad4280808080c0008422071002220841086a290000370300200220082900003703782008102c2005200629030037030020022002290378370308200641c8c6c500ad4280808080b001841002220841086a290000370300200220082900003703782008102c200420022903782209370300200241a0016a41086a220a2005290300370300200241a0016a41106a220b2009370300200241a0016a41186a220c200629030037030020022009370358200220022903083703a001200241086a200241a0016a10ff0220022802082108200229020c210920034200370300200442003703002005420037030020024200370308200620071002220441086a290000370300200220042900003703782004102c2005200629030037030020022002290378370308200641e9c6c500ad4280808080a001841002220441086a290000370300200220042900003703782004102c200320062903002207370300200a2005290300370300200b2002290378220d370300200c20073703002002200d370358200220022903083703a001200241f8006a200241a0016a10800320022d00782106200c20024191016a290000370300200b20024189016a290000370300200a20024181016a290000370300200220022900793703a0012009420020081b21092008410820081b21050240024020064101460d00200241d8006a41186a4200370300200241d8006a41106a4200370300200241d8006a41086a4200370300200242003703580c010b200241d8006a41186a200c290300370300200241d8006a41106a200b290300370300200241d8006a41086a200a290300370300200220022903a0013703580b2002412c6a2009370200200241086a41186a42043703002002413c6a200241d8006a41086a290300370200200241c4006a200241e8006a290300370200200241cc006a200241d8006a41186a2903003702002002200536022820024201370318200242c801370310200242b81737030820022002290358370234200241013a0054200241003602800120024201370378024002404108102a2206450d002002410836027c2002200228028001220541086a3602800120022006360278200620056a42b8173700002002290310210902400240200228027c220520022802800122066b4108490d00200228027821050c010b200641086a22082006490d02200541017422062008200620084b1b22064100480d020240024020050d002006102a21050c010b200228027820052006102e21050b2005450d012002200636027c2002200536027820022802800121060b2002200641086a36028001200520066a20093700002002290318210902400240200228027c220520022802800122066b4108490d00200228027821050c010b200641086a22082006490d02200541017422062008200620084b1b22064100480d020240024020050d002006102a21050c010b200228027820052006102e21050b2005450d012002200636027c2002200536027820022802800121060b2002200641086a36028001200520066a20093700002002290320210902400240200228027c220520022802800122066b4108490d00200228027821050c010b200641086a22082006490d02200541017422062008200620084b1b22064100480d020240024020050d002006102a21050c010b200228027820052006102e21050b2005450d012002200636027c2002200536027820022802800121060b2002200641086a36028001200520066a200937000020022802282105200241086a41286a2802002206200241f8006a106702402006450d002005200641286c6a210b03402005200241f8006a109101200541206a290300210902400240200228027c220820022802800122066b4108490d00200228027821080c010b200641086a220a2006490d0420084101742206200a2006200a4b1b22064100480d040240024020080d002006102a21080c010b200228027820082006102e21080b2008450d032002200636027c2002200836027820022802800121060b2002200641086a36028001200820066a2009370000200b200541286a2205470d000b0b200241346a200241f8006a10ba0220022d0054210802400240200228027c2002280280012206460d00200228027821050c010b200641016a22052006490d022006410174220a2005200a20054b1b220a4100480d020240024020060d00200a102a21050c010b20022802782006200a102e21050b2005450d012002200a36027c2002200536027820022802800121060b2002200641016a36028001200520066a20083a000020023502800142208620023502788421090240200228022c450d002002280228102c0b200241c0016a240020090f0b1033000b1035000bd90904057f017e097f017e230041b0016b2202240020024188016a41186a420037030020024188016a41106a2203420037030020024188016a41086a220442003703002002420037038801200241e8006a41086a2205418ec6c500ad4280808080a002841002220641086a290000370300200220062900003703682006102c200420052903003703002002200229036837038801200541a0c6c500ad4280808080c000841002220641086a290000370300200220062900003703682006102c200320022903682207370300200241106a41086a2004290300370300200241106a41106a2007370300200241106a41186a2005290300370300200220073703302002200229038801370310200241203602442002200241106a360240200241c8006a200241106aad42808080808004841003108d010240024002400240200228024822080d00410021030c010b200228024c21092002200241c8006a41086a28020036025c20022008360258200241086a200241d8006a107502400240024020022802080d00200228025c22054160712204417f4c0d04200228020c210a024002402005410576220b0d00410121030c010b2004102a2203450d060b0240200a450d004100210c034020052106200241003a00a801200c220d41016a210c41002105024002400240034020062005460d0120024188016a20056a200228025822042d00003a00002002200441016a3602582002200541016a22043a00a8012004210520044120470d000b200241e8006a41186a220e20024188016a41186a290300370300200241e8006a41106a220f20024188016a41106a290300370300200241e8006a41086a221020024188016a41086a2903003703002002200229038801370368200b200d470d020240200d4101742205200c2005200c4b1b220b41ffffff3f71200b470d00200b410574220541004e0d020b1035000b2002410036025c0240200541ff0171450d00200241003a00a8010b20024100360230200b450d052003102c0c050b02400240200d0d002005102a21030c010b2003200d4105742005102e21030b2003450d080b200620046b21052003200d4105746a220d2002290368370000200d41186a200e290300370000200d41106a200f290300370000200d41086a2010290300370000200c200a470d000b200241386a200a3602002002200b360234200220033602302002200620046b36025c200229023421070c030b200241386a200a3602002002200b360234200220033602302003450d01200229023421070c020b200241003602300b4100210320024100360270200242013703682002410b3602342002200241c0006a3602302002200241e8006a3602642002419c016a41013602002002420137028c01200241d0b0c200360288012002200241306a36029801200241e4006a41c49ac50020024188016a10391a200235027042208620023502688410040240200228026c450d002002280268102c0b0b2009450d002008102c0b200241003602900120024201370388012007420020031b2207422088a7220520024188016a10672003410120031b210602402005450d0020054105742104200621050340200520024188016a109101200541206a2105200441606a22040d000b0b20023502900142208620023502880184211102402007a7450d002006102c0b200241b0016a240020110f0b103a000b1033000bbd0503037f047e027f23004190016b2202240041002103200241003a00482000410120011b2104024002400240034020012003460d01200241286a20036a200420036a2d00003a00002002200341016a22003a00482000210320004120470d000b200241086a41186a200241286a41186a22012903002205370300200241086a41106a200241286a41106a22042903002206370300200241086a41086a200241286a41086a22002903002207370300200220022903282208370308200241d0006a41186a2005370300200241d0006a41106a2006370300200241d0006a41086a20073703002002200837035020004191b0c200ad4280808080e000841002220341086a290000370300200220032900003703282003102c200241f0006a41086a220920002903003703002002200229032837037020004197b0c200ad4280808080c001841002220341086a290000370300200220032900003703282003102c20024180016a41086a220a20002903003703002002200229032837038001200241286a200241d0006a109f0141c000102a22030d010c020b0240200341ff0171450d00200241003a00480b2002413c6a4102360200200241dc006a41043602002002420237022c20024184adc200360228200241043602542002419cafc2003602502002410036020c200241dc9ec6003602082002200241d0006a3602382002200241086a360258200241286a4194adc2001041000b20032002290370370000200320022903800137001020032002290028370020200341086a2009290300370000200341186a200a290300370000200341286a2000290000370000200341306a2004290000370000200341386a20012900003700002002200341c00010940120022802042100200228020021012003102c4104102a2203450d0020032000410020011b36000020024190016a24002003ad4280808080c000840f0b1033000ba50e03057f037e017f230041d0016b22022400024020010d00410121000b200220003602082002200136020c41002103200241003a008001200121040340024020012003470d002002410036020c0240200341ff0171450d00200241003a0080010b200241f4006a4102360200200241ac016a41043602002002420237026420024184adc200360260200241043602a401200241b4afc2003602a00120024100360234200241dc9ec6003602302002200241a0016a3602702002200241306a3602a801200241e0006a4194adc2001041000b200241e0006a20036a200020036a22052d00003a00002002200541016a3602082002200341016a22053a0080012004417f6a21042005210320054120470d000b200241106a41086a200241e0006a41086a290300370300200241106a41106a200241e0006a41106a290300370300200241106a41186a200241e0006a41186a2903003703002002200120056b220636020c2002200229036037031041002103200241003a008001200020056a21010340024020062003470d002002410036020c0240200341ff0171450d00200241003a0080010b200241f4006a4102360200200241ac016a41043602002002420237026420024184adc200360260200241043602a401200241b4afc2003602a00120024100360234200241dc9ec6003602302002200241a0016a3602702002200241306a3602a801200241e0006a4194adc2001041000b200241e0006a20036a200120036a22052d00003a00002002200541016a3602082002200341016a22053a0080012005210320054120470d000b200241306a41086a200241e0006a41086a290300370300200241306a41106a200241e0006a41106a290300370300200241306a41186a200241e0006a41186a290300370300200220022903603703302002200420056b220436020c02400240024020044110490d002002200120056a220341106a3602082002200441706a220536020c20054108490d0120032900002107200341086a29000021082002200441686a36020c2002200341186a360208200341106a290000210920024188016a200241086a10772002280288010d02200241ac016a4104360200200241f4006a41023602002002420237026420024184adc200360260200241043602a401200241b4afc2003602a001200241003602c401200241dc9ec6003602c0012002200241a0016a3602702002200241c0016a3602a801200241e0006a4194adc2001041000b200241ac016a4104360200200241f4006a41023602002002420237026420024184adc200360260200241043602a401200241b4afc2003602a0012002410036028c01200241dc9ec600360288012002200241a0016a360270200220024188016a3602a801200241e0006a4194adc2001041000b200241ac016a4104360200200241f4006a41023602002002420237026420024184adc200360260200241043602a401200241b4afc2003602a0012002410036028c01200241dc9ec600360288012002200241a0016a360270200220024188016a3602a801200241e0006a4194adc2001041000b200241d0006a41086a220320024188016a41086a22052802003602002002200229038801370350200241a0016a41186a200241106a41186a290300370300200241a0016a41106a200241106a41106a290300370300200241a0016a41086a200241106a41086a290300370300200220022903103703a001200241e0006a41186a200241306a41186a290300370300200241e0006a41106a200241306a41106a290300370300200241e0006a41086a200241306a41086a29030037030020022002290330370360200241c0016a41086a2003280200360200200220022903503703c00120024188016a200241a0016a200241e0006a200720082009200241c0016a10d503024002402002280288014101460d0020024194016a280200210420052802002100200228028c01210520022d00980121010c010b0240200228029801450d0020024194016a280200102c0b410021050b20024100360268200242013703604101102a210302400240024002402005450d002003450d02200341003a0000200242818080801037026420022003360260200341014102102e2203450d02200320013a00012002428280808020370264200220033602602004200241e0006a10670240024020022802642203200228026822016b2004490d00200228026021030c010b200120046a22062001490d042003410174220a2006200a20064b1b22064100480d040240024020030d002006102a21030c010b200228026020032006102e21030b2003450d0320022006360264200220033602600b2002200120046a2206360268200320016a2005200410db051a2006ad42208621070c010b2003450d01200341013a000020024281808080103702642002200336026042808080801021070b20072003ad84210702402000450d002005450d002005102c0b200241d0016a240020070f0b1033000b1035000baf1f05047f017e017f037e0e7f230041c0096b22072400200741e8006a41186a200141186a290000370300200741e8006a41106a200141106a290000370300200741e8006a41086a200141086a2900003703002007200129000037036820074188016a41186a200241186a29000037030020074188016a41106a200241106a29000037030020074188016a41086a200241086a290000370300200720022900003703880120062802002108200628020421092006280208210a4200210b200741e0056a41186a4200370300200741e0056a41106a22014200370300200741e0056a41086a22064200370300200742003703e00520074190036a41086a220241e4d2c500ad42808080808001841002220c41086a2900003703002007200c29000037039003200c102c2006200229030037030020072007290390033703e005200241b7e4c300ad42808080808001841002220c41086a2900003703002007200c29000037039003200c102c2001200729039003220d370300200741a8046a41086a2006290300370300200741a8046a41106a200d370300200741a8046a41186a20022903003703002007200d37039807200720072903e0053703a804200741d0006a200741a8046a4120109e010240024002400240024020072903584201200728025022021b220d200741d0006a41106a290300420020021b220e8450450d004200210f0c010b200741306a200e42002005420010e005200741c0006a200d42002005420010e005200741206a42004200200d420010e00502402007290338200729032884420052200741c0006a41086a290300220b200729033020072903207c7c220f200b5472450d004127210241a7c4c10021010c020b2007290340210b0b200741c8016a200741e8006a200b200f410810ac0120072802c8014101470d0120072802d001210220072802cc0121010b2000200136020420004101360200200041146a41003602002000410c6a4201370200200041086a20023602002009450d012008102c0c010b200741c8016a41106a2206290300210f20072903d001210b200741a8016a41186a200e3703002007200d3703b801200720053703b001200720053703a801200741c8016a41186a420037030020064200370300200741c8016a41086a220c4200370300200742003703c80120074190036a41086a220241e4d2c500ad42808080808001841002221041086a29000037030020072010290000370390032010102c200c200229030037030020072007290390033703c801200241f4d2c500ad4280808080f001841002221041086a29000037030020072010290000370390032010102c2006200729039003220d370300200741a8046a41086a200c290300370300200741a8046a41106a200d370300200741a8046a41186a20022903003703002007200d3703e005200720072903c8013703a804200741e0056a200741a8046a10e70320072d00d0062102200741a8046a200741e0056a41f00010db051a2007200741e0056a41f4006a2800003600fb07200720072800d1063602f8070240024020024102470d002007428080818080043703b0022007428080848080023703a80220074201370398022007420137039002200742af0137038802200742870137038002200742013703f801200742013703f001200742013703e801200742013703e001200742013703d801200742013703d001200742013703c80120074280808080c0003703a002410021020c010b200741c8016a200741a8046a41f00010db051a200741c8016a41f4006a20072800fb07360000200720072802f8073600b9020b200741c8026a4200370300200741f8026a4200370300200741e8026a4200370300200741d8026a4200370300200720023a00b8022007428080e983b1de163703c00220074280a094a58d1d3703f00220074280a094a58d1d3703e00220074280a094a58d1d3703d002200742a0808080808010370380032007200741c8016a360288032007200741c8016a36028c03200741f8076a41186a2211200741e8006a41186a290300370300200741f8076a41106a2212200741e8006a41106a290300370300200741f8076a41086a2213200741e8006a41086a290300370300200720072903683703f807200741e0056a41186a220c4200370300200741e0056a41106a22104200370300200741e0056a41086a22064200370300200742003703e00520074190036a41086a220241f9e8c500ad42808080809001841002221441086a29000037030020072014290000370390032014102c2006200229030037030020072007290390033703e0052002419db1c200ad428080808030841002221441086a29000037030020072014290000370390032014102c20074198076a41086a22152002290300220d370300200720072903900322053703980720012005370000200141086a2216200d370000200741a8046a41086a22172006290300370300200741a8046a41106a22182010290300370300200741a8046a41186a2219200c290300370300200720072903e0053703a804200741106a200741a8046a1098012007290318210d2007280210211a200c42003703002010420037030020064200370300200742003703e00520024191b0c200ad4280808080e000841002221441086a29000037030020072014290000370390032014102c2006200229030037030020072007290390033703e005200241acb0c200ad4280808080e000841002221441086a29000037030020072014290000370390032014102c2015200229030022053703002007200729039003220e370398072001200e3700002016200537000020172006290300370300201820102903003703002019200c290300370300200720072903e0053703a804200741086a200741a8046a4120109401200741c8036a4200370300200741bc036a41c0ecc1003602004101211b200741b8036a4101360200200741ac036a41d0e1c100360200200741e8036a2013290300370300200741f0036a2012290300370300200741f8036a201129030037030020074190036a41206a42003703002007428080808080013703c0032007420037039803200720072903f8073703e003200741003602a80320072802082102200728020c210120072007418c036a3602d803200720074188036a3602d4032007200741c8016a3602d00320072001410020021b3602dc032007200d4200201a1b37039003200c20074188016a41186a290300370300201020074188016a41106a290300370300200620074188016a41086a29030037030020072007290388013703e0052007200a3602b004200720093602ac04200720083602a80420074180046a20074190036a200741e0056a20032004200741a8016a200741a8046a10e20202402007280280040d0020074180046a41106a2d00000d00200741e0056a41086a200741b0036a290300370300200741a8046a41086a200741ec056a280200360200200720072903a8033703e005200720072902e4053703a804200741b8096a200741a8046a10f1014100211b0b200741e8006a20072903a80120072903b00120072903b801200741a8016a41186a290300200b200f10b90220072802cc03210120072802c8032106200720072802c40322023602a0042007200636029c04200720023602980420072002200141b8016c6a22113602a40402402001450d00200741f8076a41017221192007419f076a211a20074181086a210c20074198076a4102722109200741e0056a41106a211c20074188066a2118200741c4066a2113200741a1066a210820074181066a2110200741e0056a4101722112200741d8066a211d034020022d00002101200741a8046a200241016a41b70110db051a0240024020014103460d00200720013a00e0052012200741a8046a41b70110db052106024002400240024020010e03000102000b20072802e805211420072802ec05210620072802e4052101201a201c41d80010db051a2007410d3a00f807201920074198076a41df0010db051a20012006200741f8076a109201410121064100210a02402014450d002001102c0b410021140c020b20074188096a41186a2201200641186a220a29000037030020074188096a41106a2214200641106a221529000037030020074188096a41086a2216200641086a22172900003703002007200629000037038809200741f8076a201841900110db051a20092006290000370000200941086a2017290000370000200941106a2015290000370000200941186a200a29000037000020074180023b019807200741a8096a200741f8076a20074198076a10c10220072d00b0092106200c200729038809370000200c41086a2016290300370000200c41106a2014290300370000200c41186a2001290300370000200741043a0080082007410d3a00f807200720064102463a00a108410021064101210a41014100200741f8076a109201410021140c010b201d290300210d20072903d006210520074188096a41186a200641186a29000037030020074188096a41106a200641106a29000037030020074188096a41086a200641086a290000370300200720062900003703880920074198076a41186a201041186a29000037030020074198076a41106a201041106a29000037030020074198076a41086a201041086a2900003703002007201029000037039807200741f8076a41186a200841186a290000370300200741f8076a41106a200841106a290000370300200741f8076a41086a200841086a290000370300200720082900003703f807200741a8096a41086a201341086a280200360200200720132902003703a80920074188096a20074198076a200741f8076a2005200d200741a8096a10c6044101210a41012106410121140b024020072d00e005220141014b0d000240024020010e020001000b200a450d03024020072802e805450d0020072802e405102c0b20072d00f0054105490d03200728029806450d03200728029406102c0c030b2006450d0220181092020c020b201420072802c80645720d0120072802c406102c0c010b2007200241b8016a3602a0040c020b200241b8016a22022011470d000b200720113602a0040b20074198046a1072200041106a20074180046a41106a290300370200200041086a20074180046a41086a29030037020020002007290380043702000240200728029c032202450d0020074190036a41106a280200450d002002102c0b201b450d0020074190036a411c6a280200210220072802b403210c0240024020072802b00322060d00200221010c010b2006210020022101034020012802880b21012000417f6a22000d000b0340200220022f01064102746a41880b6a28020021022006417f6a22060d000b0b200741e0056a411c6a20022f0106360200200741f8056a4100360200200741f4056a20023602002007200c36028006200741003602f005200742003703e805200720013602e405200741003602e005200741e0056a10f9010b200741c0096a24000bdd1002077f017e23004180026b2202240041002103200241003a00a8012000410120011b21040240034020012003460d0120024188016a20036a200420036a2d00003a00002002200341016a22003a00a8012000210320004120470d000b200241086a41086a20024188016a41086a290300370300200241086a41106a20024188016a41106a290300370300200241086a41186a20024188016a41186a290300370300200220022903880137030841002103200241003a00a801200420006a2104200120006b21010340024020012003470d000240200341ff0171450d00200241003a00a8010b2002419c016a4102360200200241ec016a41043602002002420237028c0120024184adc20036028801200241043602e401200241bcafc2003602e0012002410036026c200241dc9ec6003602682002200241e0016a360298012002200241e8006a3602e80120024188016a4194adc2001041000b20024188016a20036a200420036a2d00003a00002002200341016a22003a00a8012000210320004120470d000b200241286a41086a220320024188016a41086a290300370300200241286a41106a220020024188016a41106a290300370300200241286a41186a220120024188016a41186a22042903003703002002200229038801370328200241e8006a41186a200241086a41186a290300370300200241e8006a41106a200241086a41106a290300370300200241e8006a41086a200241086a41086a29030037030020022002290308370368200241c8006a41186a2001290300370300200241c8006a41106a2000290300370300200241c8006a41086a20032903003703002002200229032837034820024188016a200241e8006a10ee01024002400240024002400240024020022d00880122034102460d004101210520030d01200241b4016a2802004102460d01200241a8016a280200220041164d0d03200241a4016a28020021062004280200210120024188016a41186a2207200241c8006aad42808080808004841006220341186a29000037030020024188016a41106a2208200341106a29000037030020024188016a41086a2204200341086a29000037030020022003290000370388012003102c200241e0016a41186a2007290300370300200241e0016a41106a2008290300370300200241e0016a41086a200429030037030020022002290388013703e00120024188016a2000ad4220862001ad84200041696aad422086200141176aad844101200241e0016aad42808080808004841008108d01200428020021042002280288012100200228028c01210802402006450d002001102c0b410021010c020b410021050b410121010b41012103024002400240024002400240024020010d00200441066a410220001b2203417f4c0d082003450d010b2003102a2206450d084100210720024100360290012002200336028c0120022006360288012001450d012002410136029001200641013a0000200228028c0121042002280290012103200541ff01714101460d0420042003460d0220022802880121040c030b200241003602900120024201370388014101102a2206450d072002410136028c01200220063602880120022802900121070b2002200741016a36029001200620076a41003a0000200228028c0121062002280290012103024020000d000240024020062003460d0020022802880121040c010b200341016a22042003490d09200341017422062004200620044b1b22064100480d090240024020030d002006102a21040c010b20022802880120032006102e21040b2004450d082002200636028c01200220043602880120022802900121030b2002200341016a36029001200420036a41003a00000c040b0240024020062003460d0020022802880121060c010b200341016a22062003490d08200341017422072006200720064b1b22074100480d080240024020030d002007102a21060c010b20022802880120032007102e21060b2006450d072002200736028c01200220063602880120022802900121030b2002200341016a36029001200620036a41013a0000200420024188016a106702400240200228028c01220620022802900122036b2004490d0020022802880121060c010b200320046a22072003490d08200641017422032007200320074b1b22034100480d080240024020060d002003102a21060c010b20022802880120062003102e21060b2006450d072002200336028c01200220063602880120022802900121030b2002200320046a36029001200620036a2000200410db051a0c030b200341016a22042003490d06200341017422062004200620044b1b22064100480d060240024020030d002006102a21040c010b20022802880120032006102e21040b2004450d052002200636028c01200220043602880120022802900121030b2002200341016a36029001200420036a41003a00000c010b0240024020042003460d0020022802880121040c010b200341016a22042003490d05200341017422062004200620044b1b22064100480d050240024020030d002006102a21040c010b20022802880120032006102e21040b2004450d042002200636028c01200220043602880120022802900121030b2002200341016a36029001200420036a41013a00000b200235029001422086200235028801842109024020010d002000450d002008450d002000102c0b20024180026a240020090f0b411720001047000b103a000b1033000b1035000b0240200341ff0171450d00200241003a00a8010b2002419c016a4102360200200241ec016a41043602002002420237028c0120024184adc20036028801200241043602e401200241bcafc2003602e0012002410036026c200241dc9ec6003602682002200241e0016a360298012002200241e8006a3602e80120024188016a4194adc2001041000bad0402027f027e23004180056b22022400024002402001450d00200220003602100c010b200241013602100b20022001360214200241d8026a200241106a108c020240024020022903c0034203510d00200241186a200241d8026a41a80210db051a0240200228021422014104490d0020022802102200280000210320022001417c6a3602142002200041046a360210200241d8026a200241186a41a80210db051a200241c0026a200241f0036a220110ed022002200320022903c0022204a722002004422888a74200420010ac02200241086a29030021042002290300210520022d00c402210320011092024104102a2201450d0220012000360000200141044108102e2201450d02200120033a0004200141084115102e2201450d02200120053700052001410d6a200437000020024180056a24002001ad4280808080d002840f0b200241cc026a4104360200200241ec026a4102360200200242023702dc0220024184adc2003602d802200241043602c402200241d0afc2003602c002200241003602d402200241dc9ec6003602d0022002200241c0026a3602e8022002200241d0026a3602c802200241d8026a4194adc2001041000b200241cc026a41043602002002412c6a41023602002002420237021c20024184adc200360218200241043602c402200241d0afc2003602c002200241003602d402200241dc9ec6003602d0022002200241c0026a3602282002200241d0026a3602c802200241186a4194adc2001041000b1033000bcc0c06017f017e017f027e057f017e230041a0026b220224000240024020010d002002200136020c200241013602080c010b20022001417f6a36020c2002200041016a36020820002d0000220141014b0d00410021000240024020010e020100010b200241106a200241086a107720022802102200450d01200229021421030b0240024002400240024020000d004100210442002105420021060c010b20034220882205a72201417f4c0d010240024020010d0042002106410121040c010b200521062001102a2204450d030b20042000200110db051a0b200220043602f001200220054220862006843702f401200241e7e485f3063602d001200241106a200241f0016a10c90320022802142107200241106a41186a2208200241d0016a200235021842208620022802102209ad84101a220141186a290000370300200241106a41106a220a200141106a290000370300200241106a41086a220b200141086a290000370300200220012900003703102001102c20024190016a41186a200829030037030020024190016a41106a200a29030037030020024190016a41086a200b290300370300200220022903103703900102402007450d002009102c0b02402004450d002006a7450d002004102c0b4100210142002105420021064200210c4100210402402000450d0020034220882206a72207417f4c0d010240024020070d004200210c410121040c010b2006210c2007102a2204450d030b20042000200710db051a0b2002200436021020022006422086200c84370214200241b0016a41e2c289ab06200241106a10d9034200210602402000450d0020034220882206a72204417f4c0d010240024020040d0042002106410121010c010b2004102a2201450d030b20012000200410db051a20034280808080708321050b2002200136021020022005200684370214200241d0016a41e9dabdf306200241106a10d9030240024020000d004200210641002101420021050c010b20034220882206a72204417f4c0d010240024020040d0041012101420021060c010b2004102a2201450d030b20012000200410db051a20034280808080708321050b20022001360290022002200520068437029402200241f0016a41e1ea91cb0620024190026a10d903200241106a41086a20024190016a41086a290300370300200241106a41106a20024190016a41106a290300370300200241106a41186a20024190016a41186a290300370300200241386a200241b0016a41086a290300370300200241c0006a200241b0016a41106a290300370300200241c8006a200241b0016a41186a290300370300200241d8006a200241d0016a41086a290300370300200241e0006a200241d0016a41106a290300370300200241e8006a200241d0016a41186a2903003703002002200229039001370310200220022903b001370330200220022903d00137035020024188016a200241f0016a41186a29030037030020024180016a200241f0016a41106a290300370300200241f8006a200241f0016a41086a290300370300200220022903f001370370200241003602f801200242013703f001200241106a200241f0016a109101200241306a200241f0016a109101200241d0006a200241f0016a109101200241f0006a200241f0016a10910120022802f801210120022802f401210820022802f001210702402000450d002003a7450d002000102c0b200141046a2200417f4c0d000240024020000d00410121040c010b2000102a2204450d020b2002410036021820022000360214200220043602102001200241106a10670240024020022802142204200228021822006b2001490d00200228021021040c010b200020016a220a2000490d032004410174220b200a200b200a4b1b220a4100480d030240024020040d00200a102a21040c010b20022802102004200a102e21040b2004450d022002200a360214200220043602100b200420006a2007200110db051a200020016aad4220862004ad84210302402008450d002007102c0b200241a0026a240020030f0b103a000b1033000b1035000b200241fc016a4104360200200241246a41023602002002420237021420024184adc200360210200241043602f401200241e4afc2003602f001200241003602d401200241dc9ec6003602d0012002200241f0016a3602202002200241d0016a3602f801200241106a4194adc2001041000b810201057f230041306b22032400200341086a200241086a280200360200200320022902003703002003200136020c200341106a200310c90320032802142101200341106a41186a22042003410c6a200335021842208620032802102205ad841020220241186a290000370300200341106a41106a2206200241106a290000370300200341106a41086a2207200241086a290000370300200320022900003703102002102c200041186a2004290300370000200041106a2006290300370000200041086a20072903003700002000200329031037000002402001450d002005102c0b024020032802002200450d002003280204450d002000102c0b200341306a24000bd00201087f230041206b220324002003410036020820034201370300200120031067024002400240024020010d002003280208210420032802042105200328020021060c010b200141246c210720032802042105200328020821010340200341106a200010e7022003280210210802400240200520016b20032802182209490d00200120096a2104200328020021060c010b200120096a22042001490d04200541017422062004200620044b1b220a4100480d040240024020050d00200a102a21060c010b20032802002005200a102e21060b2006450d032003200a36020420032006360200200a21050b20032004360208200620016a2008200910db051a02402003280214450d002008102c0b200041246a2100200421012007415c6a22070d000b0b20022902002004ad4220862006ad84100102402005450d002006102c0b200341206a24000f0b1033000b1035000bd40201027f0240024002402002450d002002417f6a2104024020012d0000220241037122054103460d000240024020050e03040001040b2004450d0220012d0001410874200272220241ffff0371418002490d02200241fcff037141027621020c040b20044103490d0120012f0001200141036a2d000041107472410874200272220241808004490d01200241027621020c030b200241034b0d0020044104490d002001280001220241ffffffff034b0d020b200041013602000f0b200241027621020b0240200220036a220120024f0d00200041013602000f0b41012103410121050240200241c000490d0041022105200241808001490d00410441052002418080808004491b21050b0240200141c000490d0041022103200141808001490d00410441052001418080808004491b21030b20002001360204200041003602002000410c6a2003360200200041086a20053602000be50401057f230041106b2202240002400240024002402000280280014101460d0002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d04200341017422052004200520044b1b22054100480d040240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028028401210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d04200441017422032005200320054b1b22034100480d040240024020040d002003102a21040c010b200128020020042003102e21040b2004450d0320012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a20063600000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d03200341017422052004200520044b1b22054100480d030240024020030d002005102a21040c010b200128020020032005102e21040b2004450d0220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00000b2000200110ea02200028028801210320004190016a28020022002001106702402000450d002000410574210003402002200136020c20032002410c6a109402200341206a2103200041606a22000d000b0b200241106a24000f0b1033000b1035000bfe0201027f024020002d0000417f6a2201410f4b0d00024002400240024002400240024020010e1000070707070107070207030704070506000b200041086a280200450d06200041046a280200102c0c060b200041086a2d00004101470d05200041146a280200450d05200041106a280200102c0c050b200041046a2d00000d042000410c6a280200450d04200041086a280200102c0c040b200041046a2802000d032000410c6a280200450d03200041086a280200102c0c030b200041086a2d00004105490d02200041306a280200450d022000412c6a280200102c0c020b200041046a2d00004102490d010240200041106a2802002201450d00200141d0006c2102200041086a28020041c0006a210103400240200141046a280200450d002001280200102c0b200141d0006a2101200241b07f6a22020d000b0b2000410c6a280200450d012000280208102c0c010b200041086a280200450d00200041046a280200102c0b02402000418c016a280200450d00200028028801102c0b0b13002000410736020420004190b2c2003602000b340020004191b0c20036020420004100360200200041146a410d360200200041106a41c0b9c200360200200041086a42063702000b5401017f230041206b22022400200241003602082002420837030020024100360218200242013703104100200241106a1067200041086a2002280218360200200020022903103702002002107d200241206a24000b7201017f230041306b22022400200241186a4200370300200241106a4200370300200241086a42003703002002420037030020024100360228200242013703202002200241206a36022c20022002412c6a109402200041086a200228022836020020002002290320370200200241306a24000b2b01017f02404101102a22020d001033000b200042818080801037020420002002360200200241003a00000bbb0405057f017e017f027e047f230041f0006b22012400200141306a41186a22024200370300200141306a41106a22034200370300200141306a41086a2204420037030020014200370330200141e0006a41086a22054191b0c200ad4280808080e0008422061002220741086a290000370300200120072900003703602007102c2004200529030037030020012001290360220837035020012008370330200541e0c2c200ad4280808080b0028422091002220741086a290000370300200120072900003703602007102c200320012903602208370300200141106a41086a22072004290300370300200141106a41106a220a2008370300200141106a41186a220b20052903003703002001200837035020012001290330370310200141086a200141106a4120109401200128020c210c2001280208210d20024200370300200342003703002004420037030020014200370330200520061002220341086a290000370300200120032900003703602003102c2004200529030037030020012001290360220837035020012008370330200520091002220341086a290000370300200120032900003703602003102c20022005290300220837030020072004290300370300200a20012903602206370300200b200837030020012006370350200120012903303703102001417f200c4100200d1b220520006a220420042005491b2205418094ebdc032005418094ebdc03491b360230200141106aad4280808080800484200141306aad4280808080c000841001200141f0006a24000bd90201047f230041e0006b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022010d00200041003602040c010b200228021421032002200241186a2802002204360224200220013602200240024020044104490d0020022004417c6a3602242002200141046a36022020012800002104200241c8006a200241206a107e20022802482205450d002000200229024c37020820002005360204200020043602000c010b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241d0b0c2003602482002200241386a360258200241c4006a41c49ac500200241c8006a10391a2002350230422086200235022884100420004100360204200228022c450d002002280228102c0b2003450d002001102c0b200241e0006a24000bfc0302077f017e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041003602080c010b200328021421042003200341186a28020022023602242003200136022002400240024020024104490d002003200141046a36022020032002417c6a220536022420054104490d00200128000021052003200241786a3602242003200141086a36022020012800042106200341c8006a200341206a10820120032802482202450d00200341c8006a41086a2802002107200328024c2108200341c8006a200341206a10820120032802480d012008450d002002102c0b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341d0b0c2003602482003200341386a360258200341c4006a41c49ac500200341c8006a10391a2003350230422086200335022884100420004100360208200328022c450d012003280228102c0c010b200341286a41086a200341c8006a41086a280200220936020020032003290348220a370328200041106a20073602002000200836020c200020023602082000200636020420002005360200200041146a200a3702002000411c6a20093602000b2004450d002001102c0b200341e0006a24000bdd0808047f047e057f027e017f017e017f017e230041f0016b220324002003200236026420032001360260200341e8006a2002ad4220862001ad841003108d0102400240200328026822040d00200041003602200c010b200328026c21052003200341f0006a280200220636029c01200320043602980141002101200341003a00e801024002400340024020062001470d002003410036029c01200141ff0171450d02200341003a00e8010c020b200341c8016a20016a200420016a22022d00003a00002003200241016a360298012003200141016a22023a00e8012002210120024120470d000b200341a8016a41086a200341c8016a41086a290300370300200341a8016a41106a200341c8016a41106a290300370300200341a8016a41186a200341c8016a41186a290300370300200320032903c8013703a8012003200620026b36029c01200341c8006a20034198016a108e022003290348a70d00200341c8006a41106a290300210720032903502108200341306a20034198016a108e022003290330a70d00200341306a41106a29030021092003290338210a200341286a20034198016a107520032802280d00024002400240200328029c0141186e220b41186c2201417f4c0d00200328022c210c0240024020010d004108210d0c010b2001102a220d450d020b0240200c450d00200341106a41106a210e4100210f41002106410021020340200341106a20034198016a108e02024002402003290310a70d00200e290300211020032903182111200341086a20034198016a10752003280208450d010b200b450d06200d102c0c060b200241016a2101200328020c211202402002200b470d00200f2001200f20014b1b220bad42187e2213422088a70d052013a722144100480d050240024020020d002014102a210d0c010b200d20062014102e210d0b200d450d040b200d20066a2202201037030820022011370300200241106a2012360200200f41026a210f200641186a210620012102200c2001470d000b0b200d450d03200341f8006a41186a200341a8016a41186a2903002210370300200341f8006a41106a200341a8016a41106a2903002211370300200341f8006a41086a200341a8016a41086a2903002213370300200320032903a8012215370378200041186a20093703002000200a37031020002007370308200020083703002000200cad422086200bad843702242000200d3602202000412c6a2015370200200041346a20133702002000413c6a2011370200200041c4006a20103702000c040b103a000b1033000b1035000b200341003602b001200342013703a8012003410b36027c2003200341e0006a3602782003200341a8016a3602a401200341dc016a4101360200200342013702cc01200341d0b0c2003602c8012003200341f8006a3602d801200341a4016a41c49ac500200341c8016a10391a20033502b00142208620033502a8018410042000410036022020032802ac01450d0020032802a801102c0b2005450d002004102c0b200341f0016a24000bf30201047f230041c0016b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022010d00200041023a00700c010b200228021421032002200241186a28020036029c012002200136029801200241206a20024198016a10fe020240024020022d00900122044102460d002000200241206a41f00010db0521052002200241206a41f4006a2800003600a30120022002280091013602a001200541f4006a20022800a301360000200520022802a0013600710c010b200241003602a801200242013703a0012002410b3602b4012002200241086a3602b0012002200241a0016a3602bc01200241346a410136020020024201370224200241d0b0c2003602202002200241b0016a360230200241bc016a41c49ac500200241206a10391a20023502a80142208620023502a00184100420022802a401450d0020022802a001102c0b200020043a00702003450d002001102c0b200241c0016a24000bee0d03077f017e067f230041c0026b220324002003200236020420032001360200200341086a2002ad4220862001ad841003108d0102400240200328020822040d00200041023a00210c010b200341106a2802002105200328020c210641002101200341003a00b8022005417e6a21070240024002400340024020052001470d00200141ff0171450d02200341003a00b8020c020b20034198026a20016a200420016a2d00003a00002003200141016a22023a00b8022007417f6a21072002210120024120470d000b200341f8016a41186a20034198026a41186a290300370300200341f8016a41106a20034198026a41106a290300370300200341f8016a41086a20034198026a41086a29030037030020032003290398023703f80120052002460d00200420026a22082d0000220941074f0d00200341f8006a41186a200341f8016a41186a290300370300200341f8006a41106a200341f8016a41106a290300370300200341f8006a41086a200341f8016a41086a290300370300200320032903f8013703782005417f6a2002460d00200841016a2d0000220141014b0d00200520026b210202400240024020010e020100010b41002101200341003a00b8022002417e6a21050340024020052001470d00200141ff0171450d04200341003a00b8020c040b20034198026a20016a200820016a41026a2d00003a00002003200141016a22023a00b8022002210120024120470d000b200341d8016a41086a20034198026a41086a290300220a370300200341b8016a41186a20034198026a41186a290300370300200341b8016a41106a20034198026a41106a290300370300200341b8016a41086a200a3703002003200329039802220a3703d8012003200a3703b801200720026b2107200820026a41026a2105410121010c010b200841026a21052002417e6a2107410021010b20034198016a41186a200341b8016a41186a29030037030020034198016a41106a200341b8016a41106a29030037030020034198016a41086a200341b8016a41086a290300370300200320032903b801370398012007450d0020052d0000220241014b0d00410021080240024020020e020100010b41002102200341003a00b802200541016a21082007417f6a21050340024020052002470d00200241ff0171450d03200341003a00b8020c030b20034198026a20026a200820026a2d00003a00002003200241016a22073a00b8022007210220074120470d000b200341d8016a41086a20034198026a41086a290300220a370300200341b8016a41186a20034198026a41186a290300370300200341b8016a41106a20034198026a41106a290300370300200341b8016a41086a200a3703002003200329039802220a3703d8012003200a3703b801410121080b200341186a41186a2202200341b8016a41186a290300370300200341186a41106a2207200341b8016a41106a290300370300200341186a41086a2205200341b8016a41086a290300370300200341386a41086a220b20034198016a41086a290300370300200341386a41106a220c20034198016a41106a290300370300200341386a41186a220d20034198016a41186a290300370300200320032903b8013703182003200329039801370338200341d8006a41186a220e200341f8006a41186a290300370300200341d8006a41106a220f200341f8006a41106a290300370300200341d8006a41086a2210200341f8006a41086a2903003703002003200329037837035820014102460d0120002003290358370000200020093a0020200041186a200e290300370000200041106a200f290300370000200041086a201029030037000020034198026a41086a2209200b29030037030020034198026a41106a220b200c29030037030020034198026a41186a220c200d2903003703002003200329033837039802200341f8016a41186a220d2002290300370300200341f8016a41106a22022007290300370300200341f8016a41086a22072005290300370300200320032903183703f8012000413a6a200c290300370000200041326a200b2903003700002000412a6a20092903003700002000200329039802370022200041c2006a20083a0000200041c3006a20032903f801370000200041cb006a2007290300370000200041d3006a2002290300370000200041db006a200d2903003700000c020b410221010b2003410036028002200342013703f8012003410b3602dc01200320033602d8012003200341f8016a3602b801200341ac026a41013602002003420137029c02200341d0b0c200360298022003200341d8016a3602a802200341b8016a41c49ac50020034198026a10391a20033502800242208620033502f80184100420032802fc01450d0020032802f801102c0b200020013a00212006450d002004102c0b200341c0026a24000b800b040e7f027e037f037e230041c0016b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022040d00200041003602000c010b200328021421052003200341186a280200360234200320043602302003200341306a107502400240024002400240024002400240024002400240024020032802000d002003280234220641d8006e220741d8006c2201417f4c0d02200328020421080240024020010d00410821090c010b2001102a2209450d040b2008450d014100210a4100210b0340200341003a00b801200b41016a210c4100210102400240034020062001460d0120034198016a20016a2003280230220d2d00003a00002003200d41016a3602302003200141016a22023a00b8012002210120024120470d000b200341f8006a41086a220e20034198016a41086a290300370300200341f8006a41106a220f20034198016a41106a290300370300200341f8006a41186a221020034198016a41186a29030037030020032003290398013703782003200620026b2201360234200141104f0d010c0c0b20034100360234200141ff0171450d0b200341003a00b8010c0b0b2003200d41116a3602302003200141706a360234200d41096a2900002111200d290001211220034198016a200341306a107f2003280298012202450d0a20032802a0012113200328029c01210d20034198016a200341306a1082012003280298012206450d09200328029c012114024020032802342201410f4b0d0020140d080c090b20032802a0012115200341d8006a41086a200e2903002216370300200341d8006a41106a200f2903002217370300200341d8006a41186a20102903002218370300200341386a41086a220e2016370300200341386a41106a220f2017370300200341386a41186a221020183703002003200329037822163703582003200141706a36023420032003280230220141106a36023020032016370338200141086a29000021162001290000211702402007200b470d00200b4101742201200c2001200c4b1b2207ad42d8007e2218422088a70d062018a722014100480d0602400240200b0d002001102a21090c010b2009200b41d8006c2001102e21090b2009450d050b2009200b41d8006c6a2201201737031020012011370308200120123703002001200636022c20012002360220200141186a2016370300200141346a2015360200200141306a2014360200200141286a2013360200200141246a200d36020020012003290338370338200141c0006a200e290300370300200141c8006a200f290300370300200141d0006a20102903003703000240200c2008470d00200341286a200836020020032007360224200320093602200c070b200a41d8006a210a20032802342106200c210b0c000b0b200341003602200c090b200341286a2008360200200320073602242003200936022020090d030c080b103a000b1033000b1035000b20002003290320370200200041086a200341206a41086a2802003602000c050b2006102c0b200d450d012002102c0c010b200d450d002002102c0b200341003602200240200b450d00200941306a210103400240200141746a280200450d00200141706a280200102c0b02402001280200450d002001417c6a280200102c0b200141d8006a2101200a41a87f6a220a0d000b0b2007450d002009102c0b2003410036028001200342013703782003410b36025c2003200341086a3602582003200341f8006a360238200341ac016a41013602002003420137029c01200341d0b0c200360298012003200341d8006a3602a801200341386a41c49ac50020034198016a10391a200335028001422086200335027884100420004100360200200328027c450d002003280278102c0b2005450d002004102c0b200341c0016a24000b800401057f230041f0006b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022030d00200041033a00200c010b200241186a28020021042002280214210541002101200241003a0068024002400340024020042001470d00200141ff0171450d02200241003a00680c020b200241c8006a20016a200320016a2d00003a00002002200141016a22063a00682006210120064120470d000b200241286a41186a200241c8006a41186a290300370300200241286a41106a200241c8006a41106a290300370300200241286a41086a200241c8006a41086a2903003703002002200229034837032820042006460d00200320066a2d0000220141034f0d0020002002290328370000200041186a200241286a41186a290300370000200041106a200241286a41106a290300370000200041086a200241286a41086a2903003700000c010b20024100360230200242013703282002410b3602242002200241086a3602202002200241286a36026c200241dc006a41013602002002420137024c200241d0b0c2003602482002200241206a360258200241ec006a41c49ac500200241c8006a10391a200235023042208620023502288410040240200228022c450d002002280228102c0b410321010b200020013a00202005450d002003102c0b200241f0006a24000bd205010d7f230041e0006b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022030d00200041003602000c010b200228021421042002200241186a280200360224200220033602202002200241206a1075024002400240024020022802000d0002400240200228022422054178712201417f4c0d002002280204210602400240200541037622070d00410421080c010b2001102a2208450d020b02402006450d00410021094100210a4100210b03402002410036022802400240024020054104490d0020022005417c6a220536022420022002280220220141046a3602202001280000210c2002410036022820054104490d00200b41016a210d20022005417c6a22053602242002200141086a36022020012800042101200b2007470d0202402009200d2009200d4b1b220741ffffffff01712007470d002007410374220e41004e0d020b1035000b200241003602482007450d072008102c0c070b02400240200b0d00200e102a21080c010b2008200a200e102e21080b2008450d040b2008200a6a220b200c360200200b41046a2001360200200941026a2109200a41086a210a200d210b2006200d470d000b200241d0006a20063602002002200736024c200220083602480c050b200241d0006a20063602002002200736024c2002200836024820080d040c030b103a000b1033000b200241003602480b20024100360230200242013703282002410b36023c2002200241086a3602382002200241286a360244200241dc006a41013602002002420137024c200241d0b0c2003602482002200241386a360258200241c4006a41c49ac500200241c8006a10391a2002350230422086200235022884100420004100360200200228022c450d012002280228102c0c010b20002002290348370200200041086a200241c8006a41086a2802003602000b2004450d002003102c0b200241e0006a24000b810201037f230041d0006b220124002001412036020420012000360200200141086a2000ad42808080808004841003108d0102400240200128020822020d00410421000c010b200128020c210302400240200141106a280200450d0020022d000022004104490d010b20014100360220200142013703182001410b36022c200120013602282001200141186a360234200141cc006a41013602002001420137023c200141d0b0c2003602382001200141286a360248200141346a41c49ac500200141386a10391a200135022042208620013502188410040240200128021c450d002001280218102c0b410421000b2003450d002002102c0b200141d0006a240020000bd90201037f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041003602040c010b200328021421042003200341186a2802002202360224200320013602200240024020024104490d0020032002417c6a3602242003200141046a36022020012800002102200341c8006a200341206a10820120032802482205450d002000200329024c37020820002005360204200020023602000c010b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341d0b0c2003602482003200341386a360258200341c4006a41c49ac500200341c8006a10391a2003350230422086200335022884100420004100360204200328022c450d002003280228102c0b2004450d002001102c0b200341e0006a24000b940e030c7f017e037f230041a0026b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041023a00100c010b200328021421042003200341106a41086a28020036026c20032001360268200341f8016a200341e8006a10820102400240024020032802f8012205450d0020032802fc01210602400240200328026c22074104490d00200341f8016a41086a280200210820032007417c6a220236026c20032003280268220941046a220a3602680240024002402002450d002009280000210b20032007417b6a220c36026c2003200a41016a360268200a2d0000220d41014b0d0041002102200d0e020201020b2006450d040c030b410121020b200341f4006a41026a200341d8016a41026a2d00003a0000200320032f00d8013b01740240200c450d0020032007417a6a220c36026c2003200a41026a220d360268200a2d0001220a41014b0d004100210e02400240200a0e020100010b4100210a200341003a0098022007417a6a210e4179210c03400240200e200a470d00200a41ff0171450d03200341003a0098020c030b200341f8016a200a6a2009200a6a220d41066a2d00003a000020032007200c6a36026c2003200d41076a3602682003200a41016a220d3a009802200c417f6a210c200d210a200d4120470d000b200341b8016a41086a200341f8016a41086a290300220f37030020034198016a41186a200341f8016a41186a29030037030020034198016a41106a200341f8016a41106a29030037030020034198016a41086a200f370300200320032903f801220f3703b8012003200f370398012007200d6b417a6a210c2009200d6a41066a210d4101210e0b200341f8006a41186a20034198016a41186a290300370300200341f8006a41106a20034198016a41106a290300370300200341f8006a41086a20034198016a41086a2903003703002003200329039801370378200c450d002003200c417f6a36026c2003200d41016a360268200d2d0000220a41014b0d004100210702400240200a0e020100010b4100210a200341003a009802200c417f6a2109200c417e6a2107034002402009200a470d00200a41ff0171450d03200341003a00980220060d050c060b200341f8016a200a6a200d200a6a220c41016a2d00003a00002003200c41026a3602682003200a41016a220c3a0098022003200736026c2007417f6a2107200c210a200c4120470d000b200341b8016a41086a200341f8016a41086a290300220f37030020034198016a41186a200341f8016a41186a29030037030020034198016a41106a200341f8016a41106a29030037030020034198016a41086a200f370300200320032903f801220f3703b8012003200f37039801410121070b200341206a41186a220a20034198016a41186a290300370300200341206a41106a220c20034198016a41106a290300370300200341206a41086a220d20034198016a41086a290300370300200341c0006a41086a2209200341f8006a41086a290300370300200341c0006a41106a2210200341f8006a41106a290300370300200341c0006a41186a2211200341f8006a41186a290300370300200320032903980137032020032003290378370340200341e4006a41026a2212200341f4006a41026a2d00003a0000200320032f01743b016420024102460d042000200b36020c200020083602082000200636020420002005360200200341b8016a41026a220520122d00003a0000200341f8016a41086a22062009290300370300200341f8016a41106a22092010290300370300200341f8016a41186a22082011290300370300200341d8016a41086a220b200d290300370300200341d8016a41106a220d200c290300370300200341d8016a41186a220c200a290300370300200320032f01643b01b801200320032903403703f801200320032903203703d801200320032f011e3b019801200041136a20052d00003a0000200020032f01b8013b0011200041146a200e3a0000200041156a20032903f8013700002000411d6a2006290300370000200041256a20092903003700002000412d6a2008290300370000200041356a20073a0000200041366a20032903d8013700002000413e6a200b290300370000200041c6006a200d290300370000200041ce006a200c290300370000200041d6006a20032f0198013b00000c050b20060d010c020b2006450d010b2005102c0b410221020b200341003602e001200342013703d8012003410b3602bc012003200341086a3602b8012003200341d8016a360298012003418c026a4101360200200342013702fc01200341d0b0c2003602f8012003200341b8016a3602880220034198016a41c49ac500200341f8016a10391a20033502e00142208620033502d80184100420032802dc01450d0020032802d801102c0b200020023a00102004450d002001102c0b200341a0026a24000bbb0603087f027e017f230041a0016b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022040d00200041003602100c010b200328021421052003200341106a41086a28020036024420032004360240200341c8006a200341c0006a10770240024020032802482206450d00200341c8006a41086a2802002107200328024c210841002101200341003a009801200328024421090240024002400240034020092001460d01200341f8006a20016a2003280240220a2d00003a00002003200a41016a3602402003200141016a22023a0098012002210120024120470d000b200341d8006a41086a200341f8006a41086a290300370300200341d8006a41106a200341f8006a41106a290300370300200341d8006a41186a200341f8006a41186a290300370300200320032903783703582003200920026b220136024420014110490d012003200a41116a3602402003200141706a2202360244200241044f0d032008450d040c020b200341003602440240200141ff0171450d00200341003a0098010b20080d010c030b2008450d020b2006102c0c010b200a41096a290000210b200a290001210c200341206a41086a2202200341d8006a41086a290300370300200341206a41106a2209200341d8006a41106a290300370300200341206a41186a220d200341d8006a41186a290300370300200320032903583703202003200a41156a36024020032001416c6a3602442006450d00200a28001121012000200c37030020002008360214200020063602102000200b370308200041186a20073602002000411c6a20032903203702002000413c6a2001360200200041246a20022903003702002000412c6a2009290300370200200041346a200d2903003702000c010b20034100360260200342013703582003410b3602242003200341086a3602202003200341d8006a3602482003418c016a41013602002003420137027c200341d0b0c2003602782003200341206a36028801200341c8006a41c49ac500200341f8006a10391a2003350260422086200335025884100420004100360210200328025c450d002003280258102c0b2005450d002004102c0b200341a0016a24000b810802107f017e230041a0016b220224002002412036020c20022001360208200241106a2001ad42808080808004841003108d0102400240200228021022030d00200041003602000c010b200228021421042002200241186a280200360234200220033602302002200241306a10750240024002400240024020022802000d000240024002402002280234220541286e220641286c2201417f4c0d00200228020421070240024020010d00410421080c010b2001102a2208450d020b02402007450d0041002109034020054104490d07200941016a210a20022005417c6a220b36023420022002280230220c41046a360230200c280000210d41002101200241003a00980103400240200b2001470d0020024100360234200141ff0171450d09200241003a0098010c090b200241f8006a20016a200c20016a220e41046a2d00003a00002002200e41056a3602302002200141016a220e3a009801200e2101200e4120470d000b200241d8006a41086a220b200241f8006a41086a290300370300200241d8006a41106a220f200241f8006a41106a290300370300200241d8006a41186a2210200241f8006a41186a2903003703002002200229037837035820022005200e6b2205417c6a220136023420014104490d07200241386a41086a2211200b290300370300200241386a41106a220b200f290300370300200241386a41186a220f2010290300370300200220022903583703382002200541786a22053602342002200c200e6a220141086a360230200141046a280000210e024020062009470d0020094101742201200a2001200a4b1b2206ad42287e2212422088a70d052012a722014100480d050240024020090d002001102a21080c010b2008200941286c2001102e21080b2008450d040b2008200941286c6a2201200d360200200120022903383702042001410c6a2011290300370200200141146a200b2903003702002001411c6a200f2903003702002001200e360224200a2109200a2007470d000b200241286a200736020020022006360224200220083602200c050b200241286a2007360200200220063602242002200836022020080d040c060b103a000b1033000b1035000b200241003602200c020b20002002290320370200200041086a200241206a41086a2802003602000c020b200241003602202006450d002008102c0b20024100360260200242013703582002410b36023c2002200241086a3602382002200241d8006a3602202002418c016a41013602002002420137027c200241d0b0c2003602782002200241386a36028801200241206a41c49ac500200241f8006a10391a2002350260422086200235025884100420004100360200200228025c450d002002280258102c0b2004450d002003102c0b200241a0016a24000b830301047f230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041003602080c010b200328021421042003200341186a2802002202360224200320013602200240024020024104490d002003200141046a36022020032002417c6a220536022420054104490d00200128000021052003200241786a3602242003200141086a36022020012800042102200341c8006a200341206a107e20032802482206450d002000200329024c37020c2000200636020820002002360204200020053602000c010b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341d0b0c2003602482003200341386a360258200341c4006a41c49ac500200341c8006a10391a2003350230422086200335022884100420004100360208200328022c450d002003280228102c0b2004450d002001102c0b200341e0006a24000bbc0b03097f017e027f23004190026b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022040d00200041023a00040c010b200328021421052003200341186a280200360264200320043602602003200341e0006a10754102210602400240024020032802000d0020032802642201450d002003280204210720032001417f6a220836026420032003280260220941016a220a36026020092d0000220141014b0d004100210b0240024020010e020100010b41002101200341003a0088020340024020082001470d0020034100360264200141ff0171450d03200341003a0088020c030b200341e8016a20016a200920016a220241016a2d00003a00002003200241026a3602602003200141016a22023a0088022002210120024120470d000b200341a8016a41086a200341e8016a41086a290300220c37030020034188016a41186a200341e8016a41186a29030037030020034188016a41106a200341e8016a41106a29030037030020034188016a41086a200c3703002003200820026b2208360264200320032903e801220c3703a8012003200c370388014101210b200920026a41016a210a0b200341e8006a41186a20034188016a41186a290300370300200341e8006a41106a20034188016a41106a290300370300200341e8006a41086a20034188016a41086a29030037030020032003290388013703682008450d0020032008417f6a22083602642003200a41016a360260200a2d0000220141014b0d00410021020240024020010e020100010b41002101200341003a0088020340024020082001470d0020034100360264200141ff0171450d03200341003a0088020c030b200341e8016a20016a200a20016a220241016a2d00003a00002003200241026a3602602003200141016a22023a0088022002210120024120470d000b200341a8016a41086a200341e8016a41086a290300220c37030020034188016a41186a200341e8016a41186a29030037030020034188016a41106a200341e8016a41106a29030037030020034188016a41086a200c3703002003200820026b360264200320032903e801220c3703a8012003200c37038801410121020b200341206a41186a220120034188016a41186a290300370300200341206a41106a220620034188016a41106a290300370300200341206a41086a220820034188016a41086a290300370300200341c0006a41086a2209200341e8006a41086a290300370300200341c0006a41106a220a200341e8006a41106a290300370300200341c0006a41186a220d200341e8006a41186a290300370300200320032903880137032020032003290368370340200b4102470d01200b21060b200341003602d001200342013703c8012003410b3602ac012003200341086a3602a8012003200341c8016a36028801200341fc016a4101360200200342013702ec01200341d0b0c2003602e8012003200341a8016a3602f80120034188016a41c49ac500200341e8016a10391a20033502d00142208620033502c80184100420032802cc01450d0120032802c801102c0c010b200341e8016a41186a220e200d290300370300200341e8016a41106a220d200a290300370300200341e8016a41086a220a2009290300370300200341c8016a41086a22092008290300370300200341c8016a41106a22082006290300370300200341c8016a41186a22062001290300370300200320032903403703e801200320032903203703c801200320032f011e3b01a80120002007360200200020032903e8013700052000410d6a200a290300370000200041156a200d2903003700002000411d6a200e290300370000200041256a20023a0000200041266a20032903c8013700002000412e6a2009290300370000200041366a20082903003700002000413e6a2006290300370000200041c6006a20032f01a8013b0000200b21060b200020063a00042005450d002004102c0b20034190026a24000bf30202027f037e230041e0006b220324002003200236020c20032001360208200341106a2002ad4220862001ad841003108d0102400240200328021022010d00200041003602100c010b200328021421042003200341106a41086a2802002202360224200320013602200240024020024110490d002003200241706a3602242003200141106a360220200141086a290000210520012900002106200341c8006a200341206a10820120032802482202450d00200329024c2107200020053703082000200637030020002007370214200020023602100c010b20034100360230200342013703282003410b36023c2003200341086a3602382003200341286a360244200341dc006a41013602002003420137024c200341d0b0c2003602482003200341386a360258200341c4006a41c49ac500200341c8006a10391a2003350230422086200335022884100420004100360210200328022c450d002003280228102c0b2004450d002001102c0b200341e0006a24000be70203017f017e017f230041d0026b220324002003200236029401200320013602900120034198016a2002ad4220862001ad8422041003108d010240024020032802980122010d00411821010c010b200328029c0121052003200341a0016a2802003602bc02200320013602b802200341a8016a200341b8026a108f020240024020032802a80122024118460d002003200341a8016a410472418c0110db051a0c010b20034100360208200342013703002003410b3602c402200320034190016a3602c002200320033602cc02200341bc016a4101360200200342013702ac01200341d0b0c2003602a8012003200341c0026a3602b801200341cc026a41c49ac500200341a8016a10391a200335020842208620033502008410042003280204450d002003280200102c0b02402005450d002001102c0b4118210120024118460d0020041005200221010b20002001360200200041046a2003418c0110db051a200341d0026a24000b1300200041013602042000419cd1c2003602000b3400200041f9e8c50036020420004100360200200041146a4102360200200041106a41fcd4c200360200200041086a42093702000b130020004101360204200041bcd7c2003602000b2d01017f02404108102a22020d001033000b20004288808080800137020420002002360200200242dc0b3700000b850401037f230041106b2202240020012d0000210302404101102a2204450d00200420033a000020012d00012103200441014102102e2204450d00200420033a000120012d00022103200441024104102e2204450d00200420033a0002200420012d00033a000320012d00042103200441044108102e2204450d00200420033a0004200420012d00053a0005200420012d00063a0006200420012d00073a000720012d00082103200441084110102e2204450d00200420033a0008200420012d00093a0009200420012d000a3a000a200420012d000b3a000b200420012d000c3a000c200420012d000d3a000d200420012d000e3a000e200420012d000f3a000f20012d00102103200441104120102e2204450d00200420033a0010200420012d00113a0011200420012d00123a0012200420012d00133a0013200420012d00143a0014200420012d00153a0015200420012d00163a0016200420012d00173a0017200420012d00183a0018200420012d00193a0019200420012d001a3a001a200420012d001b3a001b200420012d001c3a001c200420012d001d3a001d200420012d001e3a001e200420012d001f3a001f200241086a22032004ad42808080808004841002220141086a290000370300200220012900003703002001102c200041086a2003290300370000200020022903003700002004102c200241106a24000f0b1033000b130020004103360204200041e8b2c0003602000bd308030d7f017e017f230041a0016b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2205200128020422062f01064f0d01200241186a2207200620054105746a220341206a290000370300200241106a2208200341186a290000370300200241086a2209200341106a2900003703002002200341086a290000370300200241206a41286a220a2006200541306c6a22034190036a290300370300200241206a41206a220b20034188036a290300370300200241206a41186a220c20034180036a290300370300200241206a41106a220d200341f8026a290300370300200241206a41086a220e200341f0026a290300370300200341e8026a290300210f2001200541016a36020c20012004360208200120063602042002200f370320200241d0006a41186a2007290300370300200241d0006a41106a2008290300370300200241d0006a41086a200929030037030020022002290300370350200241d0006a41286a200e290300370300200241d0006a41306a200d29030037030020024188016a200c29030037030020024190016a200b29030037030020024198016a200a290300370300200220022903203703702000200241d0006a41d00010db051a0c020b200041003602400c010b2001280200210702400240200628020022030d002004ad210f410021030c010b200741016a210720063301044220862004ad84210f0b2006102c200fa7210502400240200f422088a7220420032f01064f0d00200321060c010b034002400240200328020022060d002005ad210f410021060c010b200741016a210720033301044220862005ad84210f0b2003102c200fa7210520062103200f422088a7220420062f01064f0d000b0b200241186a2208200620044105746a220341206a290000370300200241106a2209200341186a290000370300200241086a220a200341106a2900003703002002200341086a290000370300200241206a41286a220b2006200441306c6a22034190036a290300370300200241206a41206a220c20034188036a290300370300200241206a41186a220d20034180036a290300370300200241206a41106a220e200341f8026a290300370300200241206a41086a2210200341f0026a2903003703002002200341e8026a290300370320200441027420066a41fc066a280200210302402007417f6a2206450d00034020032802f80621032006417f6a22060d000b0b2001410036020c200120053602082001200336020420014100360200200241d0006a41186a2008290300370300200241d0006a41106a2009290300370300200241d0006a41086a200a290300370300200241d0006a41286a2010290300370300200241d0006a41306a200e29030037030020024188016a200d29030037030020024190016a200c29030037030020024198016a200b29030037030020022002290300370350200220022903203703702000200241d0006a41d00010db051a0b200241a0016a24000bda0401077f230041f0006b22022400200241d0006a41086a220341b5e5c200ad4280808080f000841002220441086a290000370300200220042900003703502004102c200241086a41086a2205200329030037030020022002290350370308200341c7e5c200ad4280808080f000841002220441086a290000370300200220042900003703502004102c200241186a41086a22062003290300370300200220022903503703182002200036024c200241d0006a41186a2200200241cc006aad4280808080c000841006220441186a290000370300200241d0006a41106a2207200441106a2900003703002003200441086a290000370300200220042900003703502004102c200241286a41186a22042000290300370300200241286a41106a22082007290300370300200241286a41086a2207200329030037030020022002290350370328024041c000102a2200450d00200020022903083700002000200229031837001020002002290328370020200041086a2005290300370000200041186a2006290300370000200041286a2007290300370000200041306a2008290300370000200041386a2004290300370000200128020021052001280208210320024100360258200242013703502003200241d0006a106702402003450d00200341057421042005210303402003200241d0006a109101200341206a2103200441606a22040d000b0b200228025421032000ad4280808080800884200235025842208620022802502204ad84100102402003450d002004102c0b2000102c0240200141046a280200450d002005102c0b200241f0006a24000f0b1033000b960301067f230041106b22022400200241003602082002420137030020002802002103024002404104102a2204450d0020024284808080c0003702042002200436020020042003360000200028020421050240024020022802042206200228020822046b4104490d00200441046a2103200228020021060c010b200441046a22032004490d02200641017422072003200720034b1b22074100480d020240024020060d002007102a21060c010b200228020020062007102e21060b2006450d0120022007360204200220063602000b20022003360208200620046a200536000020002802082104200041106a28020022032002106702402003450d0020034105742103034020042002109101200441206a2104200341606a22030d000b0b200028021421042000411c6a28020022032002106702402003450d0020034105742103034020042002109101200441206a2104200341606a22030d000b0b200228020421042001290200200235020842208620022802002203ad84100102402004450d002003102c0b200241106a24000f0b1033000b1035000b3400200041b5e5c20036020420004100360200200041146a4102360200200041106a41f8e5c200360200200041086a42073702000b8ea20106167f017e047f017e027f027e230041e0046b2204240041002105200441003602b002200420023602ac02200420013602a802024002400240024002400240024002400240024002400240200241034b0d0041012106200441013a0068200441e4036a4101360200200442013702d403200441f0f7c5003602d0032004412b36029402200420044190026a3602e0032004200441e8006a3602900220044180016a200441d0036a10372004280280012107200428028401210820042802880121094105210a4100210b0c010b200441043602b002024020012800004180c2cdeb06460d004101210a410121060c010b024002402002417c714104460d00200241074b0d0141082002103f000b41012106200441013a0068200441e4036a4101360200200442013702d403200441f0f7c5003602d0032004412b36029402200420044190026a3602e0032004200441e8006a3602900220044180016a200441d0036a10372004280280012107200428028401210820042802880121094105210a410021054100210b0c010b200441083602b002410121060240200128000422074101460d004102210a0c010b200441d0036a200441a8026a10f30402400240024020042802d0034101470d00410421084100210c410021090c010b200441d0036a410572210741042108412c210a410021064100210c410021094100210b0240034020044190026a41026a2201200741026a2d00003a0000200420072f00003b019002200428028004210d20042802fc03210e20042802f803210f20042802f403211020042802f003211120042802ec03211220042802e803211320042802e403211420042802e003211520042802dc03211620042802d8032117024020042d00d4032205417e6a41ff0171410b4b0d0041002118024002400240024002400240024002400240024002400240024020050e100c0c000102030405060708090a0b0c0c0c0b410121180c0b0b410221180c0a0b410321180c090b410421180c080b410521180c070b410621180c060b410721180c050b410821180c040b410921180c030b410a21180c020b410b21180c010b410c21180b0240200b41ff0171221920184d0d004113210a0c030b41002118024002400240024002400240024002400240024002400240024020050e100c0c000102030405060708090a0b0c0c0c0b410121180c0b0b410221180c0a0b410321180c090b410421180c080b410521180c070b410621180c060b410721180c050b410821180c040b410921180c030b410a21180c020b410b21180c010b410c21180b024020192018470d004114210a0c030b4100210b02400240024002400240024002400240024002400240024020050e100c0c000102030405060708090a0b0c0c0c0b4101210b0c0b0b4102210b0c0a0b4103210b0c090b4104210b0c080b4105210b0c070b4106210b0c060b4107210b0c050b4108210b0c040b4109210b0c030b410a210b0c020b410b210b0c010b410c210b0b20044180016a41026a221820012d00003a0000200420042f0190023b0180010240200c2009470d00200c41016a2201200c490d0720062001200620014b1b2209ad42307e221a422088a70d07201aa722014100480d0702400240200c0d002001102a21080c010b2008200a41546a2001102e21080b2008450d060b2008200a6a220141546a20053a00002001200d3602002001417c6a200e360200200141786a200f360200200141746a2010360200200141706a20113602002001416c6a2012360200200141686a2013360200200141646a2014360200200141606a20153602002001415c6a2016360200200141586a2017360200200141556a220120042f0180013b0000200141026a20182d00003a0000200641026a2106200a41306a210a200c41016a210c200441d0036a200441a8026a10f30420042802d0034101460d020c000b0b024002402005410e4b0d00024002400240024002400240024002400240024002400240024020050e0f0001020304050607080e090e0a0b0c000b2016450d0d2017102c0c0d0b02402016450d002017102c0b2013450d0c2014102c0c0c0b02402015450d00201541047421052017210103400240200141046a280200450d002001280200102c0b200141106a2101200541706a22050d000b0b2016450d0b2017102c0c0b0b02402015450d00201541286c21052017210103400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101200541586a22050d000b0b2016450d0a2017102c0c0a0b2016450d092017102c0c090b2016450d082017102c0c080b2016450d072017102c0c070b02402015450d00201720154104746a2113201721150340024020152802082205450d0020152802002101200541047421050340024020012d00004109470d000240200141046a2207280200220628020441ffffffff0371450d002006280200102c200728020021060b2006102c0b200141106a2101200541706a22050d000b0b201541106a21010240201541046a280200450d002015280200102c0b2001211520012013470d000b0b2016450d062017102c0c060b02402015450d00201541146c21052017210103400240200141046a280200450d002001280200102c0b200141146a21012005416c6a22050d000b0b2016450d052017102c0c050b02402015450d0020172015411c6c6a2113201721150340024020152802042201450d0002402015410c6a2802002205450d00200541047421050340024020012d00004109470d000240200141046a2207280200220628020441ffffffff0371450d002006280200102c200728020021060b2006102c0b200141106a2101200541706a22050d000b0b201541086a280200450d002015280204102c0b2015411c6a21010240201541146a280200450d002015280210102c0b2001211520012013470d000b0b2016450d042017102c0c040b02402015450d002017201541186c6a21132017211503400240201541046a280200450d002015280200102c0b0240201541146a2802002205450d00201528020c2101200541047421050340024020012d00004109470d000240200141046a2207280200220628020441ffffffff0371450d002006280200102c200728020021060b2006102c0b200141106a2101200541706a22050d000b0b201541186a21010240201541106a280200450d00201528020c102c0b2001211520012013470d000b0b2016450d032017102c0c030b02402015450d0020172015411c6c6a2113201721150340024020152802042201450d0002402015410c6a2802002205450d00200541047421050340024020012d00004109470d000240200141046a2207280200220628020441ffffffff0371450d002006280200102c200728020021060b2006102c0b200141106a2101200541706a22050d000b0b201541086a280200450d002015280204102c0b2015411c6a21010240201541146a280200450d002015280210102c0b2001211520012013470d000b0b2016450d022017102c0c020b02402017450d002016450d002017102c0b02402013450d0002402011450d002011410c6c2105201321010340024020012802002206450d00200141046a280200450d002006102c0b2001410c6a2101200541746a22050d000b0b2012450d002013102c0b200f450d010240200d450d00200f200d4104746a2116200f211703402017220741106a2117024020072802042201450d0002402007410c6a2802002205450d002005410c6c21050340024020012802002206450d00200141046a280200450d002006102c0b2001410c6a2101200541746a22050d000b0b200741086a280200450d002007280204102c0b20172016470d000b0b200e450d01200f102c0c010b02402016450d002017102c0b02402013450d002012450d002013102c0b200f450d002010102c0b0c010b024020042d00d4030d002008200c41306c6a21052008210102400340024020052001470d00410021070c020b20012d0000210b200141306a220a2101200b410c470d000b200a415c6a28020021070b2008200c41306c6a210520082101024003404100210a024020052001470d00410021010c020b20012d0000210b200141306a22062101200b4104470d000b200441e0006a200641546a10f404200428026421010b024020072001470d004101210741e100210b41f3da012105410021060c030b0240200c450d00200c41306c210c200821010340200110f504200141306a2101200c41506a220c0d000b0b41012106411a210a024020090d000c030b2008102c0c020b20042802d403220a4110762105200a410876210b200441d0036a41106a2802002117200441dc036a2802002116200441d0036a41086a28020021070b0240200c450d00200c41306c210c200821010340200110f504200141306a2101200c41506a220c0d000b0b4101210602402009450d002008102c0b20172109201621080b2005411074200b41ff017141087472200a41ff017172210502402006450d002008210b0c080b20042802b0022002470d06200441d0026a200c360200200441cc026a2009360200200420083602c802200420073602c402200420053602c002200441d0036a200441c0026a10f60420042802d00322010d052008200c41306c6a210b20082101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024102470d000b200441d8006a200a41546a10f40420042802582101200428025c21020b2002410020011b21132001410420011b210f2008200c41306c6a210b20082101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024108470d000b200441d0006a200a41546a10f40420042802502101200428025421020b2002410020011b21122001410420011b21172008200c41306c6a210b20082101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024104470d000b200441c8006a200a41546a10f40420042802482101200428024c21020b2002410020011b21162001410420011b21152008200c41306c6a210a2008210102400340410021020240200a2001470d00410021010c020b20012d0000210b200141306a22062101200b4103470d000b200441c0006a200641546a10f404200428024021012004280244210b0b0240200b410020011b220b450d00200b41286c210b2001410420011b41186a2101410021020340200220012d0000456a2102200141286a2101200b41586a220b0d000b0b024020120d00411e2101200041b9cbc5003602040c050b2017201241146c6a2112410021114100210d02400240034041d7cbc500210b41382101201741086a280200417c6a220641024b0d012017280200210a02400240024020060e03000401000b4101210d200a41afcbc500460d01200a28000041e3c2b1e306460d010c030b41012111200a41b3cbc500460d00200a41b3cbc500410610dd050d020b02402017410c6a280200450d0041132101200041d5ccc5003602040c080b0240201741106a280200220120026b220a20014d0d00412a2101200041e8ccc5003602040c080b41afccc500210b412621012016200a4d0d012015200a4102746a220a450d01418fccc500210b412021012013200a280200220a4d0d01200f200a4104746a220a450d014192cdc500210b411f2101200a2802080d01200a2d000d220a41077141044b0d010240200a0e050002020200000b201741146a22172012470d000b2011200d714101710d01411c411e201141017122021b2101200041b1cdc50041b9cbc50020021b3602040c060b2000200b3602040c050b2008200c41306c6a210b2008210102400340200b2001460d0120012d00002102200141306a220a210120024106470d000b200441386a200a41546a10f404200428023c450d00200041fdc8c500360204411f21010c050b2008200c41306c6a210b200328026821062008210102400340200b2001460d0120012d00002102200141306a220a210120024105470d000b200441306a200a41546a220110f4040240200428023441014d0d00411821012000419cc9c5003602040c060b200441286a200110f404200428022c450d0020042802282201450d00200128020020064d0d0041222101200041b4c9c5003602040c050b2008200c41306c6a210b2008210102400340200b2001460d0120012d00002102200141306a220a210120024107470d000b200441206a200a41546a10f4042004280220220120042802244104746a210b03402001200b460d012001450d012001410c6a2102200141106a210120022d0000410271450d000b41322101200041c0cac5003602040c050b2008200c41306c6a210b2008210102400340200b2001460d0120012d00002102200141306a220a21012002410c470d000b200a415c6a2802002201450d00200a41546a280200220a200141186c6a21060340200a220241186a210a2002280208410374210120022802002102024003402001450d01200141786a210120022d0004210b200241086a2102200b410271450d000b413121012000418fcac5003602040c070b200a2006470d000b0b2008200c41306c6a210b2008210102400340200b2001460d0120012d00002102200141306a220a210120024102470d000b200441186a200a41546a10f404200428021c2201450d002004280218220220014104746a211603402002450d01200241106a2117200420022d000d220b3a00d0032002280200220120022802086a2106410021024100200441d0036a200b4104461b210a024003400240024002400240200241ff01710e03000102000b20012006460d01410021022001210b200141016a21010c020b20012006460d03410121022001210b200141016a21010c010b200a450d0241022102200a210b4100210a0b200b2d0000410271450d000b41392101200041d6c9c5003602040c070b2017210220172016470d000b0b2008200c41306c6a210b20082101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024102470d000b200441106a200a41546a10f40420042802102101200428021421020b2002410020011b210f2001410420011b21122008200c41306c6a210b20082101024003400240200b2001470d00410021010c020b20012d00002102200141306a220a210120024103470d000b200441086a200a41546a10f40420042802082101200428020c210b0b2001410420011b2202200b410020011b41286c6a210a410021150340024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402002200a460d00412d21014198bac500210b20022802084103470d03024020022802002206419886c600460d002006419886c600410310dd050d040b200241286a2116411521064191b9c5002117411421014184bac500210b02400240024020022d00180e0400060118000b4136210641dbb8c5002117200f200228021c22014d0d17201220014104746a2213450d1720022802142106200228020c210220032d00700d012006410b470d014138210141ccb9c500210b200241cbd5c500460d05200241cbd5c500410b10dd05450d050c160b412f210141c5bac500210b20022802144106470d040240200228020c220641d5b8c500460d00200641d5b8c500410610dd050d050b02402015450d00411f2101200041f4bac5003602040c1e0b2002411c6a2115201621020c180b4126210141a6b9c500210b2006417d6a220641144b0d0302400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020060e15002121210e042107320b0a120114111b10210c191d000b2002419b86c600460d202002419b86c600410310dd05450d20419b86c6002002410310dd050d204101102a2217450d35201741003a000020132d000c41e000460d010c300b20024191d3c500460d014191d3c5002002410f10dd05450d01200241a0d3c500460d0341a0d3c5002002410f10dd05450d030240200241b7d3c500460d0041b7d3c5002002410f10dd050d200b4107102a2217450d3420174100360003201741013a0002201741003b000020132d000c41e000460d060c2e0b20132802084101470d2e0240201328020022112017460d0041002102034020024101460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d300c000b0b20132d000d4104470d2e2017102c201621020c320b4104102a2217450d322017410036000020132d000c41e000470d2b20132802084104470d2b0240201328020022112017460d0041002102034020024104460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d2d0c000b0b20132d000d4104470d2b2017102c201621020c310b0240200241afd3c500460d00200229000042e5f0d1fbb5ac98b6ec00520d1d0b4107102a2217450d3120174100360003201741013a0002201741003b000020132d000c41e000460d010c290b4101102a2217450d30201741003a000020132d000c41e000470d2720132802084101470d27201328020022112017460d2641002102034020024101460d27201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d280c000b0b20132802084107470d27201328020022112017460d2441002102034020024107460d25201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d280c000b0b200241c6d3c500460d0141c6d3c5002002410a10dd05450d010240200241d0d3c500460d0041d0d3c5002002410a10dd050d060b4126210641a6b9c500211720132d000c41e000470d2b20132802080d2b2016210220132d000d4104460d2d0c2b0b20132802084107470d27201328020022112017460d2141002102034020024107460d22201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d280c000b0b4102102a2217450d2c201741003b000020132d000c41e000470d1f20132802084102470d1f0240201328020022112017460d0041002102034020024102460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d210c000b0b20132d000d4104470d1f2017102c201621020c2b0b0240200241e5d3c500460d0041e5d3c5002002410d10dd050d170b4126210641a6b9c500211720132d000c41e000470d2820132802080d282016210220132d000d4104460d2a0c280b0240200241f2d3c500460d0041f2d3c5002002410c10dd050d160b4126210641a6b9c500211720132d000c41e000470d2720132802080d272016210220132d000d4104460d290c270b024020024189d4c500460d004189d4c5002002411510dd050d150b4126210641a6b9c500211720132d000c41e000470d2620132802080d262016210220132d000d4104460d280c260b02402002419ed4c500460d00419ed4c5002002410a10dd050d140b4102102a2217450d28201741003b000020132d000c41e000460d010c1a0b0240200241a8d4c500460d0041a8d4c5002002410710dd050d130b4126210641a6b9c500211720132d000c41e000470d2420132802080d242016210220132d000d4104460d260c240b20132802084102470d180240201328020022112017460d0041002102034020024102460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d1a0c000b0b20132d000d4104470d182017102c201621020c250b0240200241afd4c500460d0041afd4c5002002411310dd050d110b4126210641a6b9c500211720132d000c41e000470d2220132802080d222016210220132d000d4104460d240c220b200241c2d4c500460d0141c2d4c5002002411110dd05450d0120024181d5c500460d064181d5c5002002411110dd05450d06024020024192d5c500460d004192d5c5002002411110dd050d100b4104102a2217450d242017410036000020132d000c41e000460d080c150b0240200241d3d4c500460d0041d3d4c5002002410e10dd050d0f0b4108102a2217450d232017420037000020132d000c41e000460d020c130b4102102a2217450d22201741003b000020132d000c41e000470d1120132802084102470d110240201328020022112017460d0041002102034020024102460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d130c000b0b20132d000d4104470d112017102c201621020c210b200241e1d4c500460d0141e1d4c5002002411010dd05450d01200241f1d4c500460d0241f1d4c5002002411010dd05450d020240200241d6d5c500460d0041d6d5c5002002411010dd050d0d0b4126210641a6b9c500211720132d000c41e000470d1e20132802080d1e2016210220132d000d4104460d200c1e0b20132802084108470d100240201328020022112017460d0041002102034020024108460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d120c000b0b20132d000d4104470d102017102c201621020c1f0b4126210641a6b9c500211720132d000c41e000470d1c20132802080d1c20132d000d22014104460d1c20162102200141fb0171450d1e0c1c0b4103102a2217450d1e201741003a0002201741003b000020132d000c41e000470d0c20132802084103470d0c0240201328020022112017460d0041002102034020024103460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d0e0c000b0b20132d000d4104470d0c2017102c201621020c1d0b4102102a2217450d1d201741003b000020132d000c41e000470d0a20132802084102470d0a0240201328020022112017460d0041002102034020024102460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d0c0c000b0b20132d000d4104470d0a2017102c201621020c1c0b0240200241a3d5c500460d0041a3d5c5002002411610dd050d080b4102102a2217450d1c201741003b000020132d000c41e000460d020c080b20132802084104470d0c0240201328020022112017460d0041002102034020024104460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d0e0c000b0b20132d000d4104470d0c2017102c201621020c1a0b0240200241b9d5c500460d0041b9d5c5002002411210dd050d060b4126210641a6b9c500211720132d000c41e000470d1720132802080d172016210220132d000d4104460d190c170b20132802084102470d050240201328020022112017460d0041002102034020024102460d01201720026a210b201120026a2106200241016a210220062d0000200b2d0000470d070c000b0b20132d000d4104470d052017102c201621020c180b0240200241e6d5c500460d0041e6d5c5002002411710dd050d040b4102102a2211450d18201141003b000020132d000c41e000470d0220132802084102470d022013280200220d2011460d0141002102034020024102460d02201120026a2106200d20026a2117200241016a210220172d000020062d0000470d030c000b0b0240024020150d004100211b4100211c0c010b024020152802040d0020004193bbc500360204413221010c1d0b02402015280200221b201541086a280200221c4d0d00200041c5bbc50036020441c90021010c1d0b201c20032802644d0d002000418ebcc50036020441c10021010c1c0b200441d0036a41086a22024200370300200441d0e1c1003602d40320042003290308221aa7417f201a428080808010541b3602e00320042003290310221aa7417f201a428080808010541b3602d003200441d0036a4104722201410d10f7042001410c10f7042001410710f7042001410f10f704200441e8006a41106a20042802e003360200200441e8006a41086a2002290300370300200420042903d003370368200441d0036a41106a220b200c360200200441d0036a410c6a2009360200200420083602d803200420073602d403200420053602d00320044180016a200441d0036a10f8044101102a2201450d17200141003a0000200420042f01d003220c3b01c002200b41e0083b01002002428180808010370300200420013602d403200441013602d0032004200c3b01e20320044180016a200441d0036a10f90421054103102a2202450d17200241026a41002d009a86463a0000200241002f009886463b00004103102a220c450d17200c41026a41002d009d86463a0000200c41002f009b86463b0000200441c0026a41026a200441d0036a41026a220a2d000022083a0000200420042f00d00322093b01c00220044194016a280200210b20044180016a41106a2802002101200a20083a0000200420093b01d0030240200b2001470d00200141016a220b2001490d192001410174220a200b200a200b4b1b220bad42287e221a422088a70d19201aa7220a4100480d190240024020010d00200a102a21010c010b200428028c01200141286c200a102e21010b2001450d182004200b360290012004200136028c01200428029401210b0b200428028c01200b41286c6a220141003a00182001200c36020c200142838080803037020420012002360200200141106a428380808030370200200141196a20042f01d0033b00002001411b6a200441d2036a2d00003a00002001411c6a2005360200200420042802940141016a36029401200441d0036a20044180016a418c0110db051a20044190026a200441d0036a10fa0420044190026a41106a280200220941306c2101200428029802220841546a2102024003404100210c2001450d01200141506a21012002412c6a210b200241306a22052102200b2d00004103470d000b200541086a2802002201450d00200141286c2102200528020041186a21014100210c0340200c20012d0000456a210c200141286a2101200241586a22020d000b0b200941306c2101200841546a2102200c417f6a210b024003404100210c2001450d01200141506a21012002412c6a2105200241306a220a210220052d00004103470d000b200a41086a2802002201450d00200141286c2102200a28020041186a21014100210c0340200c20012d0000456a210c200141286a2101200241586a22020d000b0b200941306c21012008415c6a21020240034041002106024020010d00410021010c020b200141506a2101200241246a2105200241306a220a210220052d00004104470d000b200a28020021010b02400240024002402009450d002001200c6a21102008200941306c6a210f200441e8006a41047221194100211d4100210e0340024020082d000041786a220141044b0d00024002400240024020010e050301020400030b200828020c2201450d0320082802042205200141186c6a211e200e210103402001210e02402005220c2802144104742202450d00200c28020c21010340024020012d0000410b470d00200141046a2205280200220a200b490d002005200a41016a3602000b200141106a2101200241706a22020d000b0b200442003703e00320044280808080c0003703d803200442043703d0034110102a2201450d2120042802d8032102200420013602d003200441013602d403200120024104746a22014200370200200141056a4200370000200420042802d80341016a3602d8030240200c2802142214450d00410021162014210103400240024002400240024002400240201620014f0d00411021050240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200c28020c221820164104746a2d000022110eac010001020202020202020202020202020303030404050506060707080809090a0a0b0b0c0d0d0e0e0f0f1010111213131414151516161717181819191a1a1b1b1c1c1d1d1e1e1f1f2020212122222323242425252627272828292a2a2b2b2c2d2d2e2e2f2f303031313232333434353536363737383839393a3a3b3b3c3c3d3d3e3e3f3f40404141424243434444454546464747484a4a4a4a49494a4a4a4a4a4a4a4a4a4a4a4a4a4a4b4b4b4b000b411121050c4a0b411221050c490b410a21050c480b410821050c470b410821050c460b410421050c450b410421050c440b410421050c430b410421050c420b410421050c410b410421050c400b410421050c3f0b410521050c3e0b410521050c3d0b410521050c3c0b410521050c3b0b410521050c3a0b411321050c390b411421050c380b410621050c370b410721050c360b410b21050c350b410b21050c340b410b21050c330b410b21050c320b410b21050c310b410b21050c300b410b21050c2f0b410b21050c2e0b410b21050c2d0b410b21050c2c0b410b21050c2b0b410c21050c2a0b410c21050c290b410c21050c280b410c21050c270b410c21050c260b410c21050c250b410021050c240b410021050c230b410121050c220b410221050c210b410321050c200b410321050c1f0b410021050c1e0b410021050c1d0b410021050c1c0b410021050c1b0b410021050c1a0b410021050c190b410121050c180b410221050c170b410321050c160b410321050c150b410021050c140b410021050c130b410021050c120b410021050c110b410d21050c100b410d21050c0f0b410d21050c0e0b410d21050c0d0b410d21050c0c0b410d21050c0b0b410d21050c0a0b410d21050c090b410d21050c080b410d21050c070b410d21050c060b410d21050c050b410d21050c040b410d21050c030b410e21050c020b410e21050c010b410f21050b201641016a21122004280270211520192101024003402001280200220641086a211720062f0106210a41002102024002400340200a20022201460d01200141016a210202404100417f4101201720016a2d0000220720054b1b20072005461b41016a0e03000301000b0b2002417f6a210a0b024020150d00200441e8006a21020c030b2015417f6a21152006200a4102746a41ec006a21010c010b0b200441e8006a21020240200620014103746a41146a22012802000e0401070001010b200141046a21020b20022802002102024002400240024002400240024002402011417e6a220141084b0d0020010e090103020c0405050607010b20042802d8032201417f6a220520014f0d0c200520014b0d0c20042802d00320054104746a2205280208220120026a22022001490d0c200541086a20023602000c0d0b20042802d8032201417f6a220520014f0d0b200520014b0d0b20042802d00320054104746a2205280208220120026a22022001490d0b200541086a200236020020042802d8032201417f6a220520014f0d0b200520014b0d0b20042802d003220220054104746a280204210502400240200120042802d403460d002001210a0c010b200141016a220a2001490d3220014101742206200a2006200a4b1b220a41ffffffff0071200a470d32200a41047422064100480d32200220014104742006102e2202450d312004200a3602d403200420023602d00320042802d803210a0b2002200a4104746a220220093b000d200241003a000c20022005360204200220013602002002410f6a20094110763a0000200241086a4100360200200420042802d80341016a3602d8030c0c0b20042802d8032201417f6a220520014f0d0a200520014b0d0a20042802d00320054104746a2205280208220120026a22022001490d0a200541086a200236020020042802d803220221010240200220042802d403470d00200241016a22012002490d31200241017422052001200520014b1b220141ffffffff00712001470d31200141047422054100480d310240024020020d002005102a21050c010b20042802d00320024104742005102e21050b2005450d30200420013602d403200420053602d00320042802d80321010b20042802d00320014104746a220120093b000d200141003a000c20012012360204200120023602002001410f6a20094110763a0000200141086a4100360200200420042802d80341016a3602d8030c0b0b20042802d8032201417f6a220520014f0d09200520014b0d0920042802d00320054104746a2205280208220120026a22022001490d09200541086a200236020020042802d803220221010240200220042802d403470d00200241016a22012002490d30200241017422052001200520014b1b220141ffffffff00712001470d30200141047422054100480d300240024020020d002005102a21050c010b20042802d00320024104742005102e21050b2005450d2f200420013602d403200420053602d00320042802d80321010b20042802d00320014104746a220120093b000d200141013a000c20012012360204200120023602002001410f6a20094110763a0000200141086a4100360200200420042802d80341016a3602d8030c0a0b200441d0036a201610fb040d0820042802d8032202450d0820042002417f6a22013602d80320042802d003220520014104746a220a2d000c4102460d082001450d092002417e6a220220014f0d08200520024104746a2205200a280200220220052802002205200520024b1b360200200220014f0d09200441d0036a201610fb040d080c090b20042802d8032201417f6a220520014f0d07200520014b0d0720042802d00320054104746a2205280208220120026a22022001490d07201820164104746a41046a280200210a200541086a200236020020042802d8032201417f6a220220014b0d072002200a6b220120024b0d07200441d0036a201610fb040d0720042802d803220220014d0d0720042802d003220520014104746a2d000c0d08200241047420056a41706a2202200120022802002202200220014b1b3602000c080b20042802d8032201417f6a220520014f0d06200520014b0d0620042802d00320054104746a2205280208220120026a22022001490d06200541086a200236020020042802d8032201417f6a220720014b0d06201820164104746a41046a280200220128020421022001280200211120012802082101200441003a00c0020240200720016b220120074d0d00200441013a00c0020c070b4104102a2206450d2b20062001360200024020020d00410121054101210a0c040b200720112802006b221720074b0d0241022105200241027421184101210a4104210141022102034002402005417f6a2215200a470d00201541016a220a2015490d2e2002200a2002200a4b1b220a41ffffffff0371200a470d2e200a41027422154100480d2e0240024020020d002015102a21060c010b200620012015102e21060b2006450d2d0b200620016a201736020020182001460d04201120016a2117200541016a2105200241026a2102200141046a2101200720172802006b221720074d0d000b200441013a00c0020c040b20042802d8032201417f6a220520014f0d05200520014b0d0520042802d00320054104746a2205280208220120026a22022001490d05200541086a2002360200200441d0036a201610fb040d0520042802d8032201450d0520042802d00322022d000c0d06200141047420026a41706a41003602000c060b41a086c600201620011038000b4101210a200441013a00c0020c010b20042d00c0020d002006450d022005ad422086200aad84211a410121170240200441d0036a201610fb040d000240201a422088a72201450d002001410274210520062101034020042802d803220a200128020022024d0d02024020042802d003220720024104746a2d000c0d00200a41047420076a41706a220a2002200a280200220a200a20024b1b3602000b200141046a21012005417c6a22050d000b0b410021170b0240201aa7450d002006102c0b20170d020c030b200a450d012006102c0c010b200441d0036a201610fb04450d010b024020042802d403450d0020042802d003102c0b024020042802e003450d0020042802dc03102c0b4101211d0c070b20122014460d01200c2802142101201221160c000b0b20042802dc0320042802e4032201410041202001676b10fc0420042903e003211f20042802dc032118024020042802d403450d0020042802d003102c0b024020180d004101211d0c050b024002400240200c2802142202201f422088a722064101746a220141ffffffff00712001470d0020014104742205417f4c0d000240024020050d00410821050c010b2005102a2205450d25200c28021421020b200c4100360214200c28020c2120200c200536020c200c41106a220a2802002121200a2001360200202020024104746a2115201820064103746a211441022106024020020d0020182112202021010c020b410021012018211241002105202021020340200241016a2f0000200241036a2d0000411074722109024020022d0000220741ac01470d00200241106a21010c030b200241086a290000211a200241046a28000021170240024020064102470d00024020122014470d0041002106201421120c020b20122902002222422088a7210d2022a7211341012106201241086a21120b20064101470d0020052013470d0002402001200a280200470d00200141016a22062001490d28200141017422162006201620064b1b220641ffffffff00712006470d28200641047422164100480d280240024020010d002016102a21010c010b200c28020c20014104742016102e21010b2001450d27200c200136020c200a2006360200200c28021421010b200c28020c20014104746a220120042f00d0033b00012001412d3a00002001200d360204200141036a200441d0036a41026a2d00003a0000200c200c28021441016a220136021402402001200a280200470d00200141016a22062001490d28200141017422162006201620064b1b220641ffffffff00712006470d28200641047422164100480d280240024020010d002016102a21010c010b200c28020c20014104742016102e21010b2001450d27200c200136020c200a2006360200200c28021421010b200c28020c20014104746a220120042f00d0033b00012001410b3a00002001200b36020441022106200141036a200441d0036a41026a2d00003a0000200c200c28021441016a2201360214200521130b02402001200a280200470d00200141016a22162001490d27200141017422112016201120164b1b221641ffffffff00712016470d27201641047422114100480d270240024020010d002011102a21010c010b200c28020c20014104742011102e21010b2001450d26200c200136020c200a2016360200200c28021421010b200541016a2105200c28020c20014104746a2201201a37030820012017360204200120093b0001200120073a0000200141036a20094110763a0000200c200c28021441016a2201360214200241106a22022015470d000c030b0b103a000b20012015460d0003400240024020012d000022024109460d00200241ac01470d010c030b0240200141046a280200220228020441ffffffff0371450d002002280200102c0b2002102c0b200141106a22012015470d000b0b201fa7210102402021450d002020102c0b2012201447200620064102461b210202402001450d002018102c0b024020024101470d004101211d0c050b200c41186a2105024002402004280278450d00200c2802142202450d00200c28020c2101200241047421024100210c0340024020012d0000412c470d002001410b3a0000200141046a2010360200200c41016a210c0b200141106a2101200241706a22020d000b41012101200c0d010b200e21010b2005201e470d000b2001210e0c030b20082802042201200b490d022008200141016a3602040c020b200828020c2201450d01200828020422052001411c6c6a210a034020052201411c6a2105024020012802182202450d002001280210210120024102742102034002402001280200220c200b490d002001200c41016a3602000b200141046a21012002417c6a22020d000b0b2005200a460d020c000b0b200828020c2201450d00200141146c2102200828020441106a2101034002402001417c6a2802000d002001280200220c200b490d002001200c41016a3602000b200141146a21012002416c6a22020d000b0b200841306a2208200f470d000b201d4101710d02200e4101710d0120042802a002210620042802980221080b2004419c026a280200211520042802940221072004280290022117410021160c020b200441d0036a41106a20044190026a41106a280200360200200441d0036a41086a20044190026a41086a29030037030020042004290390023703d003200441c0026a200441d0036a10f8044110102a2202450d19200241063a00004101102a2201450d19200141003a00004101102a2205450d19200520012d00003a00002001102c4110102a220c450d19200c41063a000041f000102a2201450d19200141063a00602001412c3b01502001200b3602442001410b3a0040200141d8003a0030200120042802783602242001412d3a0020200141003602142001410f3a0010200141003602042001410f3a00000240200c2d00004109470d000240200c280204220b28020441ffffffff0371450d00200b280200102c200c280204210b0b200b102c0b200c102c024020022d00004109470d0002402002280204220c28020441ffffffff0371450d00200c280200102c2002280204210c0b200c102c0b2002102c200441f4036a4287808080f000370200200441f0036a2001360200200441ec036a4100360200200441d0036a410c6a4281808080800c370200200441d8036a4101360200200441003602fc03200442043702e403200420053602d403200441013602d003200441c0026a200441d0036a10fd04200441d0036a200441c0026a418c0110db051a200441a8026a200441d0036a10fa04200441a8026a410c6a2802002115200441b8026a280200210620042802a802211720042802ac02210720042802b0022108410021160c010b2004419c026a28020021152004280298022108024020042802a0022206450d00200641306c2102200821010340200110f504200141306a2101200241506a22020d000b0b41012116411a210741f2cac50021172015450d002008102c0b200441f4006a2802002109200428026c210c0240200441f0006a2802002201450d000340200c28026c210c2001417f6a22010d000b0b4100210b41002101024003402009450d01024002402001200c2f01064f0d00200c20014103746a41146a290200211a200141016a21010c010b02400240200c28020022010d00200bad211a41002105410021010c010b200c330104422086200bad84211a410121050b200c102c201aa7210b02400240201a422088a7220a20012f01064f0d00200121020c010b034002400240200128020022020d00200bad211a410021020c010b200541016a21052001330104422086200bad84211a0b2001102c201aa7210b20022101201a422088a7220a20022f01064f0d000b0b200a41027420026a41f0006a280200210c2002200a4103746a41146a290200211a02402005417f6a2201450d000340200c28026c210c2001417f6a22010d000b0b410021010b2009417f6a2109201aa74103470d000b0b0240200c41d0e1c100460d00200c2802002101200c102c2001450d00200128020021022001102c2002450d00024020022802002201450d0003402002102c200121022001280200220c2101200c0d000b0b2002102c0b02402016450d002000201736020420004101360200200041086a20073602000c210b200441c0026a41106a2006360200200441c0026a410c6a2015360200200420083602c802200420073602c402200420173602c002200441d0036a200441c0026a200328026010fe04024020042802d0034101470d000240200441d0036a41086a280200450d0020042802d403102c0b2000418ccbc50036020420004101360200200041086a41233602000c210b200441e4036a280200210c200441d0036a41106a2802002113200441d0036a410c6a2802002115200441d8036a280200210b20042802d40321022003280258210f200441003602b002200442013703a8024104102a2201450d17200441043602ac02200420042802b002220541046a3602b002200420013602a802200120056a20023600000240024020042802ac02220220042802b00222016b4104490d0020042802a80221020c010b200141046a22052001490d19200241017422012005200120054b1b22014100480d190240024020020d002001102a21020c010b20042802a80220022001102e21020b2002450d18200420013602ac02200420023602a80220042802b00221010b2004200141046a3602b002200220016a200b3600002015200c41306c22016a210b024002400240200c0d00201521010c010b200141506a2106200441d0036a4101722102200441d0036a41276a2105200441d0036a41206a210a200441d0036a41186a2108200441d0036a41086a2109201521010240034020012d0000210c2005200141286a290000370000200a200141216a2900003703002008200141196a290000370300200441d0036a41106a2207200141116a2900003703002009200141096a2900003703002004200141016a2900003703d0030240200c4110470d00200141306a21010c030b200441c0026a41276a22172005290000370000200441c0026a41206a2216200a290300370300200441c0026a41186a2008290300221a370300200441c0026a41106a20072903002222370300200441c0026a41086a2009290300221f370300200420042903d00322233703c00220022023370000200241086a201f370000200241106a2022370000200241186a201a370000200241206a2016290300370000200241276a20172900003700002004200c3a00d00320044180016a200441d0036a200441a8026a10ff0420042d008001220c411f470d01200641506a2106200141306a2201200b470d000b200b21010c010b2004280284012112200428028801210f02402006450d00200141306a2101200441d0036a4101722102200441d0036a41276a210a200441d0036a41206a2108200441d0036a41186a2109200441d0036a41086a2106034020012d00002105200a200141286a2900003700002008200141216a2900003703002009200141196a290000370300200441d0036a41106a2207200141116a2900003703002006200141096a2900003703002004200141016a2900003703d00320054110460d01200441c0026a41276a2217200a290000370000200441c0026a41206a22162008290300370300200441c0026a41186a2009290300221a370300200441c0026a41106a20072903002222370300200441c0026a41086a2006290300221f370300200420042903d00322233703c00220022023370000200241086a201f370000200241106a2022370000200241186a201a370000200241206a2016290300370000200241276a2017290000370000200420053a00d003200441d0036a10f504200141306a2201200b470d000b0b02402013450d002015102c0b024020042802ac02450d0020042802a802102c0b200c4105470d01200f450d012012102c0c010b02402001200b460d00200441d0036a4101722102200441d0036a41276a2105200441d0036a41206a210a200441d0036a41186a2108200441d0036a41086a2109034020012d0000210c2005200141286a290000370000200a200141216a2900003703002008200141196a290000370300200441d0036a41106a2206200141116a2900003703002009200141096a2900003703002004200141016a2900003703d003200c4110460d01200441c0026a41276a22072005290000370000200441c0026a41206a2217200a290300370300200441c0026a41186a2008290300221a370300200441c0026a41106a20062903002222370300200441c0026a41086a2009290300221f370300200420042903d00322233703c00220022023370000200241086a201f370000200241106a2022370000200241186a201a370000200241206a2017290300370000200241276a20072900003700002004200c3a00d003200441d0036a10f504200141306a2201200b470d000b0b02402013450d002015102c0b20042802a802210120042902ac02211a2000411c6a41003a0000200041146a201a370200200041106a20013602002000410c6a201c360200200041086a201b3602002000200f3602042000411d6a20042f0090023b0000200041003602002000411f6a20044192026a2d00003a00000c210b200041cdcdc50036020420004101360200200041086a41253602000c200b20132d000d22024104460d00200241fb01710d002011102c201621020c150b2011102c0b2000200b3602040c180b2017102c200041a6b9c5003602040c170b2017102c200041a6b9c5003602040c160b2017102c200041a6b9c5003602040c150b2017102c200041a6b9c5003602040c140b2017102c200041a6b9c5003602040c130b2017102c200041a6b9c5003602040c120b2017102c200041a6b9c5003602040c110b2017102c200041a6b9c5003602040c100b20132d000d22024104460d05200241fb01710d052017102c201621020c0a0b20132d000d22024104460d02200241fb01710d022017102c201621020c090b20132d000d22024104460d00200241fb01710d002017102c201621020c080b2017102c200041a6b9c5003602040c0c0b2017102c200041a6b9c5003602040c0b0b2017102c200041a6b9c5003602040c0a0b2017102c200041a6b9c5003602040c090b2017102c200041a6b9c5003602040c080b02400240200241dad3c500460d0041dad3c5002002410b10dd050d010b4126210641a6b9c500211720132d000c41e000470d0120132802080d012016210220132d000d4104460d030c010b0240200241fed3c500460d0041fed3c5002002410b10dd050d020b4126210641a6b9c500211720132d000c41e000470d0020132802080d002016210220132d000d4104460d020b20062101200020173602040c060b0240200241cbd5c500460d0041cbd5c5002002410b10dd050d050b4102102a2206450d01200641003b000020132d000c41e000470d0320132802084102470d030240201328020022172006460d0041002101034020014102460d01200620016a2102201720016a210b200141016a2101200b2d000020022d0000470d050c000b0b20132d000d4104470d032006102c201621020c000b0b1033000b1035000b2006102c0b41262101200041a6b9c5003602040b20004101360200200041086a20013602000240200c450d002008200c41306c6a21072008210a0340200a220541306a210a0240024020052d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200541086a280200450d0d200541046a280200102c0c0d0b0240200541086a280200450d00200541046a280200102c0b200541146a280200450d0c200541106a280200102c0c0c0b02402005410c6a2802002202450d00200541046a28020021012002410474210203400240200141046a280200450d002001280200102c0b200141106a2101200241706a22020d000b0b200541086a280200450d0b2005280204102c0c0b0b02402005410c6a2802002202450d00200541046a2802002101200241286c210203400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101200241586a22020d000b0b200541086a280200450d0a2005280204102c0c0a0b200541086a280200450d09200541046a280200102c0c090b200541086a280200450d08200541046a280200102c0c080b200541086a280200450d07200541046a280200102c0c070b02402005410c6a2802002201450d00200541046a280200220b20014104746a210603400240200b2802082202450d00200b2802002101200241047421020340024020012d00004109470d000240200141046a2200280200220c28020441ffffffff0371450d00200c280200102c2000280200210c0b200c102c0b200141106a2101200241706a22020d000b0b200b41106a21010240200b41046a280200450d00200b280200102c0b2001210b20012006470d000b0b200541086a280200450d062005280204102c0c060b02402005410c6a2802002202450d00200541046a2802002101200241146c210203400240200141046a280200450d002001280200102c0b200141146a21012002416c6a22020d000b0b200541086a280200450d052005280204102c0c050b02402005410c6a2802002201450d00200541046a280200220b2001411c6c6a210603400240200b2802042201450d000240200b410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2200280200220c28020441ffffffff0371450d00200c280200102c2000280200210c0b200c102c0b200141106a2101200241706a22020d000b0b200b41086a280200450d00200b280204102c0b200b411c6a21010240200b41146a280200450d00200b280210102c0b2001210b20012006470d000b0b200541086a280200450d042005280204102c0c040b02402005410c6a2802002201450d00200541046a280200220b200141186c6a210603400240200b41046a280200450d00200b280200102c0b0240200b41146a2802002202450d00200b28020c2101200241047421020340024020012d00004109470d000240200141046a2200280200220c28020441ffffffff0371450d00200c280200102c2000280200210c0b200c102c0b200141106a2101200241706a22020d000b0b200b41186a21010240200b41106a280200450d00200b28020c102c0b2001210b20012006470d000b0b200541086a280200450d032005280204102c0c030b02402005410c6a2802002201450d00200541046a280200220b2001411c6c6a210603400240200b2802042201450d000240200b410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2200280200220c28020441ffffffff0371450d00200c280200102c2000280200210c0b200c102c0b200141106a2101200241706a22020d000b0b200b41086a280200450d00200b280204102c0b200b411c6a21010240200b41146a280200450d00200b280210102c0b2001210b20012006470d000b0b200541086a280200450d022005280204102c0c020b0240200541046a2802002201450d00200541086a280200450d002001102c0b0240200541146a2802002201450d0002402005411c6a2802002202450d002002410c6c2102034002402001280200220c450d00200141046a280200450d00200c102c0b2001410c6a2101200241746a22020d000b0b200541186a280200450d002005280214102c0b200541246a280200220b450d0102402005412c6a2802002201450d00200b20014104746a21060340200b220041106a210b024020002802042201450d0002402000410c6a2802002202450d002002410c6c2102034002402001280200220c450d00200141046a280200450d00200c102c0b2001410c6a2101200241746a22020d000b0b200041086a280200450d002000280204102c0b200b2006470d000b0b200541286a280200450d012005280224102c0c010b0240200541086a280200450d00200541046a280200102c0b0240200541146a2802002201450d00200541186a280200450d002001102c0b200541246a280200450d00200541206a280200102c0b200a2007470d000b0b2009450d042008102c0c040b024020042802d403450d002001102c0b0240200c450d00200c41306c2102200821010340200110f504200141306a2101200241506a22020d000b0b41eac8c5002101411321022009450d022008102c0c020b200441003a0068200441e4036a4101360200200442013702d403200441f0f7c5003602d0032004412b36029402200420044190026a3602e0032004200441e8006a3602900220044180016a200441d0036a10372004280280012107200428028401210b0240200c450d00200c41306c2102200821010340200110f504200141306a2101200241506a22020d000b0b410521052009450d002008102c0b41d4c8c500210141162102200b450d00200541ff01714105470d002007102c0b2000200136020420004101360200200041086a20023602000b200441e0046a24000b130020004104360204200041e8e8c2003602000b3400200041cee5c20036020420004100360200200041146a4105360200200041106a41b8f3c200360200200041086a42133702000b3400200041fde7c20036020420004100360200200041146a4105360200200041106a41b8f3c200360200200041086a42133702000b02000bb30303047f017e017f230041d0006b22012400200141c0006a41086a22024196e0c500ad4280808080f000841002220341086a290000370300200120032900003703402003102c200141206a41086a22042002290300370300200120012903403703202002419ff8c200ad42808080808002841002220341086a290000370300200120032900003703402003102c200141306a41086a20022903002205370300200141086a2004290300370300200141186a20053703002001200129034022053703302001200129032037030020012005370310024002404101450d004120210402400240024002404120450d004120102a22020d010c050b411021044110102a2202450d04200141106a210320022001290300370000200241086a200141086a2903003700000c010b20022001290300370000200241086a200141086a290300370000200141106a21034120210641204110470d010b20022004200441017422064120200641204b1b2206102e2202450d020b20022003290000370010200241186a200341086a290000370000200041203602082000200636020420002002360200200141d0006a24000f0b103a000b1033000bb80801067f230041106b220224002002410036020820024201370300200028020022032802002104200328020822052002106702402005450d0020054105742105034020042002109101200441206a2104200541606a22050d000b0b200328020c2106024002400240024020022802042205200228020822046b4104490d00200228020021050c010b200441046a22072004490d02200541017422042007200420074b1b22044100480d020240024020050d002004102a21050c010b200228020020052004102e21050b2005450d012002200436020420022005360200200228020821040b2002200441046a360208200520046a200636000020032d0010210302400240200228020420022802082204460d00200228020021050c010b200441016a22052004490d02200441017422062005200620054b1b22064100480d020240024020040d002006102a21050c010b200228020020042006102e21050b2005450d012002200636020420022005360200200228020821040b2002200441016a360208200520046a20033a000002400240200028020422042d00004101460d0002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d04200541017422002003200020034b1b22004100480d040240024020050d002000102a21030c010b200228020020052000102e21030b2003450d032002200036020420022003360200200228020821050b2002200541016a360208200320056a41003a00000c010b02400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d03200541017422002003200020034b1b22004100480d030240024020050d002000102a21030c010b200228020020052000102e21030b2003450d022002200036020420022003360200200228020821050b2002200541016a360208200320056a41013a0000200441016a20021091010b0240024020042d00214101460d0002400240200228020420022802082204460d00200228020021050c010b200441016a22052004490d04200441017422032005200320054b1b22034100480d040240024020040d002003102a21050c010b200228020020042003102e21050b2005450d032002200336020420022005360200200228020821040b2002200441016a360208200520046a41003a00000c010b02400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d03200541017422002003200020034b1b22004100480d030240024020050d002000102a21030c010b200228020020052000102e21030b2003450d022002200036020420022003360200200228020821050b2002200541016a360208200320056a41013a0000200441226a20021091010b200228020421042001290200200235020842208620022802002205ad84100102402004450d002005102c0b200241106a24000f0b1033000b1035000ba80e03057f017e017f230041e0036b22012400200141d8026a41086a22024196e0c500ad4280808080f000841002220341086a290000370300200120032900003703d8022003102c200141d0006a41086a22042002290300370300200120012903d802370350200241c9f8c200ad4280808080a001841002220341086a290000370300200120032900003703d8022003102c20014190026a41086a22052002290300370300200120012903d80237039002200141d8026a2000109f010240024002400240024041c000102a2203450d00200320012903503700002003200129039002370010200320012900d802370020200341086a2004290300370000200341186a2005290300370000200341286a2002290000370000200341306a200141e8026a290000370000200341386a200141d8026a41186a290000370000200141d8026a200341c00010f203024020012d00dc02220241024622000d002003ad428080808080088410050b2001410d6a200141d8026a41057241c30010db051a200141d0006a2001410d6a41c30010db051a20000d04200120023a00980120014198016a410172200141d0006a41c10010db052104200141ba016a21000240024020012d00b9014101460d00200141003602e0010c010b200141e0016a200010890420012d00980121020b024002400240200241ff01714101460d00200141003602f0010c010b200141f0016a200410890420012802f0010d010b024020012d00b9014101460d00200141d8026a108a0420013502e00242208620012802d8022202ad84100520012802dc02450d042002102c0c040b200141d8026a108a0420012802d8022102200120012802e002360294022001200236029002200020014190026a10a10220012802dc02450d032002102c0c030b20014180026a41086a200141f0016a41086a2802002202360200200120012903f00122063703800220014190026a2006a72204200210f203024020012d0094024102470d00200141003602a803200142013703a003200141b0036a41146a410d360200200141bc036a410b360200200141073602cc0320014196e0c5003602c8032001410b3602b4032001410a3602d403200141c9f8c2003602d003200120014180026a3602c0032001200141d0036a3602b8032001200141c8036a3602b0032001200141a0036a3602dc03200141d8026a41146a4103360200200142033702dc02200141849dc5003602d8022001200141b0036a3602e802200141dc036a41c49ac500200141d8026a10391a20013502a80342208620013502a00384100420012802a403450d0220012802a003102c0c020b200141d8026a20014190026a41c80010db051a2001419d036a200141b9016a220041206a2d00003a000020014195036a200041186a2900003700002001418d036a200041106a29000037000020014185036a200041086a290000370000200141fd026a2000290000370000200141003602b803200142013703b003200141d8026a200141b0036a108901200141d8026a410472200141b0036a10a30220012802b40321002002ad4220862004ad8420013502b80342208620012802b0032202ad8410012000450d012002102c0c010b1033000b0240200128028402450d00200128028002102c0b410121000c010b410021000b0240024020012802e00122020d00410021040c010b20014180026a41086a200141e0016a41086a2802002204360200200120012903e00122063703800220014190026a2006a72205200410f2030240024020012d0094024102470d00200141003602a803200142013703a003200141b0036a41146a410d360200200141bc036a410b360200200141073602cc0320014196e0c5003602c8032001410b3602b4032001410a3602d403200141c9f8c2003602d003200120014180026a3602c0032001200141d0036a3602b8032001200141c8036a3602b0032001200141a0036a3602dc03200141d8026a41146a4103360200200142033702dc02200141a89cc5003602d8022001200141b0036a3602e802200141dc036a41c49ac500200141d8026a10391a20013502a80342208620013502a00384100420012802a403450d0120012802a003102c0c010b200141d8026a20014190026a41c80010db051a200141fc026a200141b8016a2d00003a0000200141f4026a200141b0016a290300370200200141ec026a200141a8016a290300370200200141e4026a20014198016a41086a29030037020020012001290398013702dc02200141003602b803200142013703b003200141d8026a200141b0036a108901200141d8026a410472200141b0036a10a30220012802b40321072004ad4220862005ad8420013502b80342208620012802b0032204ad8410012007450d002004102c0b0240200128028402450d00200128028002102c0b410121040b0240200020012802f001220545720d0020012802f401450d002005102c0b2004200245720d0020012802e401450d002002102c0b2003102c200141e0036a24000b840d05027f017e027f017e047f230041f0036b220124004196e0c500ad4280808080f0008410022202290008210320022800042104200228000021052002102c41aff8c200ad4280808080a0018410022202290008210620022800042107200228000021082002102c200141d8026a2000109f01024002400240024041c000102a2202450d00200220063700182002200736001420022008360010200220033700082002200436000420022005360000200220012900d802370020200241286a200141e0026a290000370000200241306a200141e8026a290000370000200241386a200141f0026a290000370000200141d8026a200241c00010ee03024020012d00e802220041024622040d002002ad428080808080088410050b20012802dc02210520012802d80221072001200141ec026a41c40010db05220141c4006a200141c40010db051a20040d0320014188016a200141c4006a41c20010db051a200141aa016a21040240024020012d00a9014101460d00200141003602d0010c010b200141d0016a2004108b040b02400240024020012d0088014101460d00200141003602e0010c010b200141e0016a20014188016a410172108b0420012802e0010d010b0240024020012d00a9014101460d00200141d8026a10840420013502e00242208620012802d8022204ad84100520012802dc02450d012004102c0c010b200141d8026a10840420012802d8022108200120012802e002360284022001200836028002200420014180026a10a10220012802dc02450d002008102c0b410021080c030b200141f0016a41086a200141e0016a41086a2802002204360200200120012903e00122033703f00120014180026a2003a72209200410ee03024020012d0090024102470d00200141003602b803200142013703b003200141c0036a41146a410d360200200141cc036a410b360200200141073602dc0320014196e0c5003602d8032001410b3602c4032001410a3602e403200141aff8c2003602e0032001200141f0016a3602d0032001200141e0036a3602c8032001200141d8036a3602c0032001200141b0036a3602ec03200141d8026a41146a4103360200200142033702dc02200141849dc5003602d8022001200141c0036a3602e802200141ec036a41c49ac500200141d8026a10391a20013502b80342208620013502b00384100420012802b403450d0220012802b003102c0c020b200141d8026a20014180026a41d80010db051a200141ad036a200141a9016a220841206a2d00003a0000200141a5036a200841186a2900003700002001419d036a200841106a29000037000020014195036a200841086a2900003700002001418d036a2008290000370000200120043602c403200120093602c003200141d8026a200141c0036a108c0420012802dc02450d0120012802d802102c0c010b1033000b024020012802f401450d0020012802f001102c0b410121080b0240024020012802d00122040d00410021090c010b200141f0016a41086a200141d0016a41086a2802002209360200200120012903d00122033703f00120014180026a2003a7220a200910ee030240024020012d0090024102470d00200141003602b803200142013703b003200141c0036a41146a410d360200200141cc036a410b360200200141073602dc0320014196e0c5003602d8032001410b3602c4032001410a3602e403200141aff8c2003602e0032001200141f0016a3602d0032001200141e0036a3602c8032001200141d8036a3602c0032001200141b0036a3602ec03200141d8026a41146a4103360200200142033702dc02200141a89cc5003602d8022001200141c0036a3602e802200141ec036a41c49ac500200141d8026a10391a20013502b80342208620013502b00384100420012802b403450d0120012802b003102c0c010b200141d8026a20014180026a41d80010db051a2001418c036a200141a8016a2d00003a000020014184036a200141a0016a290300370200200141fc026a20014198016a290300370200200141f4026a20014188016a41086a29030037020020012001290388013702ec02200120093602c4032001200a3602c003200141d8026a200141c0036a108c0420012802dc02450d0020012802d802102c0b024020012802f401450d0020012802f001102c0b410121090b0240200820012802e001220a45720d0020012802e401450d00200a102c0b2009200445720d0020012802d401450d002004102c0b2002102c024020004102460d002005450d002007102c0b200141f0036a24000bb10501067f230041e0006b22012400200141c0006a41086a22024196e0c500ad4280808080f000841002220341086a290000370300200120032900003703402003102c200141086a200229030037030020012001290340370300200241a8f9c200ad42808080809001841002220341086a290000370300200120032900003703402003102c200141106a41086a2002290300370300200120012903403703100240024002404104102a2202450d0020014204370244200120023602402000200141c0006a109101200028022021030240024020012802442200200128024822026b4104490d00200128024021000c010b200241046a22042002490d02200041017422022004200220044b1b22024100480d020240024020000d002002102a21000c010b200128024020002002102e21000b2000450d012001200236024420012000360240200128024821020b2001200241046a360248200020026a200336000020012802442100200141c0006a41186a2203200135024842208620012802402205ad841006220241186a290000370300200141c0006a41106a2204200241106a290000370300200141c0006a41086a2206200241086a290000370300200120022900003703402002102c200141206a41186a2003290300370300200141206a41106a2004290300370300200141206a41086a20062903003703002001200129034037032002402000450d002005102c0b41c000102a22020d020b1033000b1035000b200220012903003700002002200129031037001020022001290320370020200241086a200141086a290300370000200241186a200141106a41086a290300370000200241286a200141206a41086a290300370000200241306a200141306a290300370000200241386a200141206a41186a2903003700002002ad428080808080088410052002102c200141e0006a24000bbd0201057f230041c0006b22022400200241206a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341c9f8c200ad4280808080a001841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2001109f01024041c000102a22040d001033000b200420022903003700002004200229031037001020042002290020370020200042c0808080800837020420002004360200200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241c0006a24000bb30303047f017e017f230041d0006b22012400200141c0006a41086a22024196e0c500ad4280808080f000841002220341086a290000370300200120032900003703402003102c200141206a41086a2204200229030037030020012001290340370320200241b9f8c200ad42808080808002841002220341086a290000370300200120032900003703402003102c200141306a41086a20022903002205370300200141086a2004290300370300200141186a20053703002001200129034022053703302001200129032037030020012005370310024002404101450d004120210402400240024002404120450d004120102a22020d010c050b411021044110102a2202450d04200141106a210320022001290300370000200241086a200141086a2903003700000c010b20022001290300370000200241086a200141086a290300370000200141106a21034120210641204110470d010b20022004200441017422064120200641204b1b2206102e2202450d020b20022003290000370010200241186a200341086a290000370000200041203602082000200636020420002002360200200141d0006a24000f0b103a000b1033000bbd0201057f230041c0006b22022400200241206a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341aff8c200ad4280808080a001841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2001109f01024041c000102a22040d001033000b200420022903003700002004200229031037001020042002290020370020200042c0808080800837020420002004360200200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241c0006a24000bcc0301057f230041106b22022400200241003602082002420137030020002802002103200028020822042002106702402004450d0020044105742104034020032002109101200341206a2103200441606a22040d000b0b200028020c2105024002400240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22062003490d02200441017422032006200320064b1b22034100480d020240024020040d002003102a21040c010b200228020020042003102e21040b2004450d012002200336020420022004360200200228020821030b2002200341046a360208200420036a200536000020002d0010210502400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d02200341017422062004200620044b1b22064100480d020240024020030d002006102a21040c010b200228020020032006102e21040b2004450d012002200636020420022004360200200228020821030b2002200341016a360208200420036a20053a0000200041146a200210a302200228020421032001290200200235020842208620022802002204ad84100102402003450d002004102c0b200241106a24000f0b1033000b1035000b850401067f230041f0006b22032400200341d0006a41086a22044196e0c500ad4280808080f000841002220541086a290000370300200320052900003703502005102c200341086a41086a220620042903003703002003200329035037030820044188f9c200ad4280808080b002841002220541086a290000370300200320052900003703502005102c200341186a41086a22072004290300370300200320032903503703182003200136024c200341d0006a41186a2201200341cc006aad4280808080c000841006220541186a290000370300200341d0006a41106a2208200541106a2900003703002004200541086a290000370300200320052900003703502005102c200341286a41186a22052001290300370300200341286a41106a22012008290300370300200341286a41086a2208200429030037030020032003290350370328024041c000102a2204450d00200420032903083700002004200329031837001020042003290328370020200441086a2006290300370000200441186a2007290300370000200441286a2008290300370000200441306a2001290300370000200441386a2005290300370000200341d0006a200210f903200441c000418001102e2204450d0020042003290050370040200441c8006a200341d8006a29000037000020004280818080800a37020420002004360200200341f0006a24000f0b1033000b850401067f230041f0006b22032400200341d0006a41086a22044196e0c500ad4280808080f000841002220541086a290000370300200320052900003703502005102c200341086a41086a2206200429030037030020032003290350370308200441f5f8c200ad4280808080b002841002220541086a290000370300200320052900003703502005102c200341186a41086a22072004290300370300200320032903503703182003200136024c200341d0006a41186a2201200341cc006aad4280808080c000841006220541186a290000370300200341d0006a41106a2208200541106a2900003703002004200541086a290000370300200320052900003703502005102c200341286a41186a22052001290300370300200341286a41106a22012008290300370300200341286a41086a2208200429030037030020032003290350370328024041c000102a2204450d00200420032903083700002004200329031837001020042003290328370020200441086a2006290300370000200441186a2007290300370000200441286a2008290300370000200441306a2001290300370000200441386a2005290300370000200341d0006a200210f903200441c000418001102e2204450d0020042003290050370040200441c8006a200341d8006a29000037000020004280818080800a37020420002004360200200341f0006a24000f0b1033000be50201057f230041c0006b22022400200241206a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703202004102c200241086a22052003290300370300200220022903203703002003419bf9c200ad4280808080d001841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2001109f01024041c000102a2204450d00200420022903003700002004200229031037001020042002290020370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241206a200441c00010f103024020022802282203450d002000200229022c37020c200020022903203702000b200020033602082004102c200241c0006a24000f0b1033000be80201057f230041c0006b22022400200241206a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703202004102c200241086a22052003290300370300200220022903203703002003419bf9c200ad4280808080d001841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2001280200109f01024041c000102a2204450d00200420022903003700002004200229031037001020042002290020370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241206a200441c00010f103024020022802282203450d002000200229022c37020c200020022903203702000b200020033602082004102c200241c0006a24000f0b1033000bbe0501087f230041c0006b22022400200241206a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703202004102c200241086a22052003290300370300200220022903203703002003419bf9c200ad4280808080d001841002220441086a290000370300200220042900003703202004102c200241106a41086a2204200329030037030020022002290320370310200241206a2000109f010240024041c000102a2206450d00200620022903003700002006200229031037001020062002290020370020200641086a2005290300370000200641186a2004290300370000200641286a2003290000370000200641306a200241306a290000370000200641386a200241206a41186a2900003700002002410036022820024201370320200128020021044104102a2203450d0020024284808080c000370224200220033602202003200436000020012802042104200341044108102e2203450d00200242888080808001370224200320043600042002200336022020012802082104200141106a2802002201200241206a10670240024020010d002002280228210720022802242105200228022021030c010b200141027421084100200228022822016b21002002280224210503402004280200210902400240200520006a4104490d00200228022021030c010b200141046a22032001490d04200541017422072003200720034b1b22074100480d040240024020050d002007102a21030c010b200228022020052007102e21030b2003450d032002200736022420022003360220200721050b200441046a21042002200141046a2207360228200320016a20093600002000417c6a2100200721012008417c6a22080d000b0b2006ad42808080808008842007ad4220862003ad84100102402005450d002003102c0b2006102c200241c0006a24000f0b1033000b1035000bbe0701067f23004190016b22022400200241d0006a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703502004102c200241386a41086a2205200329030037030020022002290350370338200341dff8c200ad4280808080f000841002220441086a290000370300200220042900003703502004102c200241186a41086a2206200329030037030020022002290350370318200241d0006a2001109f01024041c000102a2204450d00200420022903383700002004200229031837001020042002290050370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241d0006a41106a2205290000370000200441386a200241d0006a41186a2206290000370000200241c00036024c20022004360248200241386a2004ad42808080808008841003108d0102400240200228023822010d00410021030c010b200228023c21072002200241386a41086a280200360284012002200136028001200241d0006a20024180016a10cc010240024020022802702203450d00200241186a41186a200241d0006a41186a290300370300200241186a41106a200241d0006a41106a290300370300200241186a41086a200241d0006a41086a290300370300200241086a41086a200241fc006a28020036020020022002290350370318200220022902743703080c010b4100210320024100360220200242013703182002410b36020c2002200241c8006a3602082002200241186a36028c01200241e4006a410136020020024201370254200241d0b0c2003602502002200241086a3602602002418c016a41c49ac500200241d0006a10391a20023502204220862002350218841004200228021c450d002002280218102c0b2007450d002001102c0b200241d0006a41086a2201200241186a41086a2903003703002005200241186a41106a2903003703002006200241186a41186a290300370300200241386a41086a2205200241086a41086a2802003602002002200229031837035020022002290308370338024002402003450d002000200229035037030020002003360220200041246a2002290338370200200041186a200241d0006a41186a290300370300200041106a200241d0006a41106a290300370300200041086a20012903003703002000412c6a20052802003602000c010b2000420037030020004208370320200041186a4200370300200041106a4200370300200041086a4200370300200041286a41003602000b2004102c20024190016a24000f0b1033000bf10e04057f017e197f027e230041f0026b22042400200441a0026a41086a22054196e0c500ad4280808080f000841002220641086a290000370300200420062900003703a0022006102c200441386a41086a22072005290300370300200420042903a002370338200541b5fdc200ad4280808080d000841002220641086a290000370300200420062900003703a0022006102c200441e0016a41086a22062005290300370300200420042903a0023703e001200441a0016a2001109f010240024002400240024041c000102a2205450d0020052004290338370000200520042903e001370010200520042900a001370020200541086a2007290300370000200541186a2006290300370000200541286a200441a0016a41086a290000370000200541306a200441b0016a290000370000200541386a200441a0016a41186a290000370000200441c00036027c20042005360278200441386a2005ad42808080808008841003108d01024020042802382206450d00200428023c210802400240200441c0006a280200450d0020062d000022074103490d010b200441003602e801200442013703e0012004410b36020c2004200441f8006a3602082004200441e0016a3602c001200441b4026a4101360200200442013702a402200441d0b0c2003602a0022004200441086a3602b002200441c0016a41c49ac500200441a0026a10391a20043502e80142208620043502e001841004024020042802e401450d0020042802e001102c0b410321070b02402008450d002006102c0b20074103470d020b2005102c0c020b1033000b2005102c0240024020070e03020001020b200441a0026a20012002200310b80120043502a0024201852102200441b0026a2903002109200441a8026a29030021030c030b200441a0026a200110980420042d00a0024101470d01200441f8016a200441b9026a290000370300200441e0016a41106a200441b1026a290000370300200441e0016a41086a200441a9026a290000370300200420042900a1023703e001200441386a200441e0016a2002200310b80120043502384201852102200441386a41106a2903002109200441386a41086a29030021030c020b200441f8006a200110980420042d00784101470d00200441c0016a41186a220720044191016a290000370300200441c0016a41106a220520044189016a290000370300200441c0016a41086a220620044181016a290000370300200420042900793703c001200441a0026a200441c0016a10f902200441a0016a41186a22082007290300370300200441a0016a41106a22072005290300370300200441a0016a41086a220a2006290300370300200420042903c0013703a00120042802c002220b450d00200441e0016a41186a220c2008290300370300200441e0016a41106a220d2007290300370300200441e0016a41086a220e200a290300370300200441e0016a41286a2207200441a0026a41086a2208290300370300200441e0016a41306a220a200441a0026a41106a220f290300370300200441e0016a41386a2210200441a0026a41186a2211290300370300200441086a41286a2212200441ec026a2213280200360200200441086a41206a2214200441e4026a2215290200370300200441086a41186a2216200441dc026a2217290200370300200441086a41106a2218200441d4026a2219290200370300200441086a41086a221a200441cc026a221b290200370300200420042903a0013703e001200420042903a00237038002200420042902c402370308200441386a41386a221c2010290300370300200441386a41306a221d200a290300370300200441386a41286a221e2007290300370300200441386a41206a221f200429038002370300200441386a41186a2220200c290300370300200441386a41106a2221200d290300370300200441386a41086a2222200e290300370300200420042903e0013703382010201c290300370300200a201d2903003703002007201e290300370300200441e0016a41206a221c201f290300370300200c2020290300370300200d2021290300370300200e2022290300370300200420042903383703e001200441f8006a41186a2020290300370300200441f8006a41106a2021290300370300200441f8006a41086a20222903003703002004200429033837037820112010290300370300200f200a290300370300200820072903003703002004200b3602c0022004201c2903003703a002200441c4026a22072004290308370200201b201a2903003702002019201829030037020020172016290300370200201520142903003702002013201228020036020020112903002109200f200f290300222320027c22243703002011200920037c2024202354ad7c37030020082903002109200420042903a002222320027c22243703a0022008200920037c2024202354ad7c370300200441c0016a20012002200310b80120043502c00121022005290300210920062903002103200441f8006a200441a0026a10990402402007280200450d0020042802c002102c0b200242018521020c010b420021020b2000200337030820002002370300200041106a2009370300200441f0026a24000baf0603037f047e037f230022022103200241a0026b41607122022400200141186a220429000021052004200229039801370000200129001021062001200229039001370010200129000821072001200229038801370008200241003a00800120012900002108200120022903800137000020022005370338200220063703302002200737032820022008370320200141206a2d0000210420024180016a41176a2209200537000020024180016a41106a220a200229003137030020024180016a41086a220b20022900293703002002200229002137038001024002402008a741ff01714101460d00200041003602000c010b200241176a2009290000370000200241106a200a290300370300200241086a200b2903003703002002200229038001370300200220043a001f200241f0006a200210890420024180016a20022802702204200228027810f203024020022d0084014102470d00200241003602e801200242013703e001200241f0016a41146a410d360200200241fc016a410b3602002002410736028c0220024196e0c500360288022002410b3602f4012002410a36029402200241c9f8c200360290022002200241f0006a36028002200220024190026a3602f801200220024188026a3602f0012002200241e0016a36029c02200241206a41146a410336020020024203370224200241a89cc5003602202002200241f0016a3602302002419c026a41c49ac500200241206a10391a20023502e80142208620023502e00184100420004100360200024020022802e401450d0020022802e001102c0b2002280274450d012002280270102c200324000f0b20024180016a4104722109200228028001210a02402002280274450d002004102c0b200241206a200941c20010db051a200141206a200241e1006a2d00003a0000200141186a200241d9006a290000370000200141106a200241d1006a290000370000200141086a200241c9006a29000037000020012002290041370000200020022903003700042000410c6a200241086a290300370000200041146a200241106a2903003700002000411c6a200241186a29030037000020004101360200200041246a200a360200200324000f0b200324000be50703037f047e037f230022022103200241a0036b41607122022400200141186a220429000021052004200229039802370000200129001021062001200229039002370010200129000821072001200229038802370008200241003a0080022001290000210820012002290380023700002002200537039801200220063703900120022007370388012002200837038001200141206a2d0000210420024180026a41176a2209200537000020024180026a41106a220a20022900910137030020024180026a41086a220b200229008901370300200220022900810137038002024002402008a741ff01714101460d00200041023a00300c010b200241186a41176a2009290000370000200241186a41106a200a290300370300200241186a41086a200b2903003703002002200229038002370318200220043a0037200241f0016a200241186a108b0420024180026a20022802f001220420022802f80110ee03024020022d0090024102470d00200241003602e802200242013703e002200241f0026a41146a410d360200200241fc026a410b3602002002410736028c0320024196e0c500360288032002410b3602f4022002410a36029403200241aff8c200360290032002200241f0016a36028003200220024190036a3602f802200220024188036a3602f0022002200241e0026a36029c03200241386a41146a41033602002002420337023c200241a89cc5003602382002200241f0026a3602482002419c036a41c49ac500200241386a10391a20023502e80242208620023502e002841004200041023a0030024020022802e402450d0020022802e002102c0b20022802f401450d0120022802f001102c200324000f0b20024180016a20024180026a41d80010db051a024020022802f401450d002004102c0b200241f0026a41106a220420024180016a41106a280200360200200241f0026a41086a220920024180016a41086a29030037030020022002290380013703f002200241386a20024194016a41c20010db051a200141206a200241f9006a2d00003a0000200141186a200241f1006a290000370000200141106a200241e9006a290000370000200141086a200241e1006a2900003700002001200229005937000020024180026a41186a200241186a41186a290300220537030020024180026a41106a200241186a41106a290300220837030020024180026a41086a200241186a41086a2903002206370300200020022903182207370200200041086a2006370200200041106a2008370200200041186a20053702002002200737038002200041206a20022903f002370200200041286a2009290300370200200041306a2004280200360200200324000f0b200324000bf30302047f027e230041c0016b22022400200241086a20011098040240024020022d00084101470d0020024180016a41186a200241216a29000037030020024180016a41106a200241196a29000037030020024180016a41086a200241116a2900003703002002200229000937038001200241306a41086a22034196e0c500ad4280808080f000841002220141086a290000370300200220012900003703302001102c200241a0016a41086a22042003290300370300200220022903303703a001200341d9f8c200ad4280808080e000841002220141086a290000370300200220012900003703302001102c200241b0016a41086a22052003290300370300200220022903303703b001200241306a20024180016a109f01024041c000102a2201450d00200120022903a001370000200120022903b00137001020012002290030370020200141086a2004290300370000200141186a2005290300370000200141286a2003290000370000200141306a200241306a41106a290000370000200141386a200241306a41186a2203290000370000200241306a200141c00010e603200329030021062002290340210720022802542104200228025021032001102c2003450d012004450d022003102c0c020b1033000b42002107420021060b2000200737030020002006370308200241c0016a24000bba1105017f047e017f057e047f230041c0026b22052400200541a0016a20001098040240024020052d00a0014101470d00200541306a41186a200541b9016a290000370300200541c0006a200541b1016a290000370300200541306a41086a200541a9016a290000370300200520052900a101370330200541a0016a200541306a10f90220052802c001450d00200541d0006a200541a0016a41d00010db051a200541d0006a41086a290300210620052903502107024002402005290360220820012008200154200541d0006a41186a290300220920025420092002511b220a1b220b20092002200a1b220c8450450d002007210d2006210e0c010b200541e8006a220a2009200c7d2008200b54ad7d220f37030020052008200b7d220d37036002400240200d428080e983b1de1656200f420052200f501b450d00200b2108200c21090c010b200a420037030020054200370360200f20027c200d20017c2201200d54ad7c21020b20054200200620097d2007200854ad7d220b200720087d220f200756200b200656200b2006511b220a1b220e37035820054200200f200a1b220d370350200220097d2001200854ad7d2102200120087d21010b02400240024002400240200541f8006a28020022100d004100210a410021100c010b2005280270210a201041186c21114100211003400240200a2903002208200120012008562002200a41086a221229030022095620022009511b22131b220b2009200220131b220c84500d00200a2008200b7d220d370300200a2009200c7d2008200b54ad7d220f37030802400240200d428080e983b1de1656200f420052200f501b450d002001210f200b2108200c21090c010b200a4200370308200a42003703002002200f7c2001200d7c220f200154ad7c21020b200541d0006a41086a221342002013290300220120097d2005290350220b200854ad7d220c200b20087d220d200b56200c200156200c2001511b22131b220e37030020054200200d20131b220d370350200220097d200f200854ad7d2102200f20087d210120122903002109200a29030021080b024020082009844200520d00200a41186a210a201041016a2110201141686a22110d010b0b2005280278220a2010490d010b200541003602780240200a20106b220a450d0002402010450d00200528027022132013201041186c6a200a41186c10dc051a200541d8006a290300210e2005290350210d0b2005200a3602780b42002007200d7d220820082007562006200e7d2007200d54ad7d220920065620092006511b220a1b220842002009200a1b22098450450d010c020b41dafec500411c41acfec5001036000b200541a0016a41086a2210418be9c500ad42808080808001841002220a41086a2900003703002005200a2900003703a001200a102c200541a0026a41086a22132010290300370300200520052903a0013703a002201041d6b5c000ad4280808080b001841002220a41086a2900003703002005200a2900003703a001200a102c200541b0026a41086a22112010290300370300200520052903a0013703b002200541a0016a2000109f0141c000102a220a450d02200a20052903a002370000200a20052903b002370010200a20052900a001370020200a41086a2013290300370000200a41186a2011290300370000200a41286a2010290000370000200a41306a200541a0016a41106a290000370000200a41386a200541a0016a41186a290000370000200541186a200a41c000109e01200541186a41106a29030021022005290320210120052802182110200a102c20002001420020101b22012008200120012008562002420020101b220b200956200b2009511b220a1b22027d200b2009200b200a1b220c7d2001200254ad7d10a20102400240200820027d220b2009200c7d2008200254ad7d220f844200520d002004427f2004290300220220087c22012001200254220a200441086a2210290300220220097c200aad7c220120025420012002511b220a1b3703002010427f2001200a1b3703000c010b200541a0016a41086a2210418be9c500ad42808080808001841002220a41086a2900003703002005200a2900003703a001200a102c200541a0026a41086a22132010290300370300200520052903a0013703a002201041e1b5c000ad4280808080f001841002220a41086a2900003703002005200a2900003703a001200a102c200541b0026a41086a22112010290300370300200520052903a0013703b002200541a0016a2000109f0141c000102a220a450d03200a20052903a002370000200a20052903b002370010200a20052900a001370020200a41086a2013290300370000200a41186a2011290300370000200a41286a2010290000370000200a41306a200541a0016a41106a290000370000200a41386a200541a0016a41186a2900003700002005200a41c000109e01200541106a29030021012005290308210d20052802002110200a102c2000200d420020101b220d200b200d200d200b562001420020101b220e200f56200e200f511b220a1b22017d200e200f200e200a1b22067d200d200154ad7d10aa012004427f2004290300220d200120027c220e7c22022002200d54220a200441086a221029030022022006200c7c200e200154ad7c7c200aad7c220c200254200c2002511b220a1b3703002010427f200c200a1b370300200b20017d2202200f20067d200b200154ad7d220f84500d00200342002003290300220120027d220b200b200156200341086a220a290300220b200f7d2001200254ad7d2202200b562002200b511b22101b370300200a4200200220101b3703000b200541306a200541d0006a109904200541d8016a2009370300200541d0016a2008370300200541a0016a41086a41013a0000200541a9016a2000290000370000200541b1016a200041086a290000370000200541b9016a200041106a290000370000200541c1016a200041186a290000370000200541043a00a00141014100200541a0016a1092010b200541f4006a280200450d002005280270102c0b200541c0026a24000f0b1033000be00301047f230041f0006b22022400200241086a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703082004102c200241306a41086a2205200329030037030020022002290308370330200341d3f8c200ad4280808080e000841002220441086a290000370300200220042900003703082004102c200241c0006a41086a2204200329030037030020022002290308370340200241d0006a2001109f01024041c000102a2203450d00200320022903303700002003200229034037001020032002290350370020200341086a2005290300370000200341186a2004290300370000200341286a200241d0006a41086a2205290300370000200341306a200241e0006a2204290300370000200341386a200241d0006a41186a2201290300370000200241086a200341c00010d3012005200241086a41096a2900003703002004200241086a41116a2900003703002001200241086a41196a290000370300200220022900093703500240024020022d00084101460d00200041003a00000c010b200041013a000020002002290350370001200041096a200241d8006a290300370000200041116a2004290300370000200041196a20012903003700000b2003102c200241f0006a24000f0b1033000bb30401067f230041d0006b22022400200242f3e885db96cddbb320370308200241086a2001412c6a22032001290300200141086a290300417f411f10be01200241306a41086a22044196e0c500ad4280808080f000841002220541086a290000370300200220052900003703302005102c200241106a41086a2206200429030037030020022002290330370310200441d9f8c200ad4280808080e000841002220541086a290000370300200220052900003703302005102c200241206a41086a2207200429030037030020022002290330370320200241306a2000109f01024041c000102a2205450d00200520022903103700002005200229032037001020052002290030370020200541086a2006290300370000200541186a2007290300370000200541286a2004290000370000200541306a200241306a41106a290000370000200541386a200241306a41186a29000037000020024100360238200242013703302003200241306a10910120022001360220200241206a200241306a108a012002200141106a360220200241206a200241306a108a0120012802202104200141286a2802002201200241306a106702402001450d002004200141186c6a2101034020022004360220200241206a200241306a108a01200441106a200241306a1089012001200441186a2204470d000b0b200228023421042005ad4280808080800884200235023842208620022802302201ad84100102402004450d002001102c0b2005102c200241d0006a24000f0b1033000b130020004110360204200041e4fdc2003602000bc90405057f017e017f027e037f230041e0006b22002400200041206a41186a22014200370300200041206a41106a22024200370300200041206a41086a2203420037030020004200370320200041d0006a41086a22044196e0c500ad4280808080f0008422051002220641086a290000370300200020062900003703502006102c2003200429030037030020002000290350220737034020002007370320200441d8e0c500ad428080808080018422081002220641086a290000370300200020062900003703502006102c200220002903502207370300200041086a22092003290300370300200041106a220a2007370300200041186a220b200429030037030020002007370340200020002903203703000240024002404100200010ec032206200641ff01714104461b41ff0171417f6a220641024b0d0020060e03010001010b20014200370300200242003703002003420037030020004200370320200420051002220641086a290000370300200020062900003703502006102c2003200429030037030020002000290350220737034020002007370320200420081002220641086a290000370300200020062900003703502006102c200041c0006a41086a2004290300220737030020002000290350220537034020022005370000200241086a200737000020092003290300370300200a2002290300370300200b2001290300370300200020002903203703004101102a2204450d01200441013a00002000ad42808080808004842004ad4280808080108410012004102c0b200041e0006a24000f0b1033000b340020004196e0c50036020420004100360200200041146a411a360200200041106a41ccafc300360200200041086a42073702000b5301017f02404110102a2202450d002002420037000820024200370000200241104120102e2202450d0020024200370010200042a0808080800437020420002002360200200241186a42003700000f0b1033000bff0503027f027e047f230041106b2203240020034100360208200342013703002002200310670240024002402002450d002001200241d8006c6a21040340200141386a2003109101200141086a2903002105200129030021060240024020032802042207200328020822026b4110490d00200328020021070c010b200241106a22082002490d04200741017422022008200220084b1b22024100480d040240024020070d002002102a21070c010b200328020020072002102e21070b2007450d032003200236020420032007360200200328020821020b200720026a22072005370008200720063700002003200241106a36020820012802202102200128022822072003106702402007450d002002200741306c6a2109034020022003109101200241286a2903002105200241206a29030021060240024020032802042208200328020822076b4110490d00200328020021080c010b200741106a220a2007490d0620084101742207200a2007200a4b1b22074100480d060240024020080d002007102a21080c010b200328020020082007102e21080b2008450d052003200736020420032008360200200328020821070b200820076a22082005370008200820063700002003200741106a3602082009200241306a2202470d000b0b200128022c2102200141346a28020022072003106702402007450d0020074105742107034020022003109101200241206a2102200741606a22070d000b0b200141186a2903002105200129031021060240024020032802042207200328020822026b4110490d00200328020021070c010b200241106a22082002490d04200741017422022008200220084b1b22024100480d040240024020070d002002102a21070c010b200328020020072002102e21070b2007450d032003200236020420032007360200200328020821020b200720026a22072005370008200720063700002003200241106a360208200141d8006a22012004470d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b1033000b1035000b6701027f230041106b22022400200241003602082002420137030002404104102a22030d001033000b2003410036000020024284808080c00037020420022003360200410020021067200041086a200228020836020020002002290300370200200241106a24000b8d0201037f230041c0006b22022400200241186a4200370300200241106a22034200370300200241086a4200370300200241286a22044100360200200242003703002002420837032020024100360238200242013703302002200236023c2002413c6a200241306a108a012002200336023c2002413c6a200241306a108a012002280220210320042802002204200241306a106702402004450d00200441306c21040340200341106a200241306a1091012002200336023c200341306a21032002413c6a200241306a108a01200441506a22040d000b0b20002002290330370200200041086a200241306a41086a28020036020002402002280224450d002002280220102c0b200241c0006a24000be20101047f230041106b220224002002410036020c02404101102a2203450d0002400240200228020c2204413f4b0d00200320044102743a0000410121050c010b0240200441808001490d0002402004418080808004490d00200341033a0000200228020c210441052105200341014105102e2203450d03200320043600010c020b41042105200341014104102e2203450d02200320044102744102723600000c010b41022105200341014102102e2203450d01200320044102744101723b00000b200020053602082000200536020420002003360200200241106a24000f0b1033000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241043600000b130020004102360204200041a0dbc3003602000b2d01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241a0053600000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241063600000b9f4312057f017e017f017e027f027e047f017e067f017e077f027e027f017e067f027e017f027e230041f0036b2205240010a301200541c8036a41186a22064200370300200541c8036a41106a22074200370300200541c8036a41086a22084200370300200542003703c80320054188036a41086a22094196e0c500ad4280808080f00084220a1002220b41086a2900003703002005200b29000037038803200b102c200820092903003703002005200529038803220c3703c8022005200c3703c803200941e0e0c500ad4280808080b002841002220b41086a2900003703002005200b29000037038803200b102c2007200529038803220c37030020054198036a41086a220b200829030037030020054198036a41106a220d200c37030020054198036a41186a220e20092903003703002005200c3703d802200520052903c80337039803200541203602ec01200520054198036a3602e80120054188026a20054198036aad220f428080808080048422101003108d010240024020052802880222110d00410021120c010b200528028c0221130240024020054188026a41086a2802004104490d0020112800002114410121120c010b41002112200541003602b002200542013703a8022005410b36028c032005200541e8016a360288032005200541a8026a3602d802200541dc036a4101360200200542013702cc03200541d0b0c2003602c803200520054188036a3602d803200541d8026a41c49ac500200541c8036a10391a20053502b00242208620053502a802841004024020052802ac02450d0020052802a802102c0b0b2013450d002011102c0b200642003703002007420037030020084200370300200542003703c8032009200a1002221141086a29000037030020052011290000370388032011102c200820092903003703002005200529038803220c3703c8022005200c3703c8032009419de0c500ad4280808080a001841002221141086a29000037030020052011290000370388032011102c200541d8026a41086a22132009290300220c370300200520052903880322153703d80220072015370000200741086a2216200c370000200b2008290300370300200d2007290300370300200e2006290300370300200520052903c80337039803200541e0016a20054198036a412010940120052802e401211720052802e0012118200642003703002007420037030020084200370300200542003703c8032009200a1002221141086a29000037030020052011290000370388032011102c200820092903003703002005200529038803220a3703c8022005200a3703c803200941a7e0c500ad4280808080b003841002221141086a29000037030020052011290000370388032011102c20132009290300220a3703002005200529038803220c3703d8022007200c3700002016200a370000200b2008290300370300200d2007290300370300200e2006290300370300200520052903c80337039803200541d8016a20054198036a41201094012017410020181b2219211702400240024020052802dc01410020052802d8011b20044d0d00200541c8036a41186a220b4200370300200541c8036a41106a220d4200370300200541c8036a41086a22084200370300200542003703c80320054188036a41086a22094196e0c500ad4280808080f000841002220641086a29000037030020052006290000370388032006102c200820092903003703002005200529038803220a3703c8022005200a3703c803200941f3e0c500ad4280808080a001841002220641086a29000037030020052006290000370388032006102c200541d8026a41086a2009290300220a3703002005200529038803220c3703d8022007200c370000200741086a200a37000020054198036a41086a200829030037030020054198036a41106a200d29030037030020054198036a41186a200b290300370300200520052903c80337039803200541c8036a20054198036a10eb0320052802c8032209410420091b220b20052902cc03420020091b220a422088a741037422096a210803402009450d02200941786a21092008417c6a2106200841786a2108200628020020044b0d000b200b20096a2802002117200aa7450d00200b102c0b200541c8036a41186a22184200370300200541c8036a41106a221a4200370300200541c8036a41086a22164200370300200542003703c80320054188036a41086a221b4196e0c500ad4280808080f00084221c1002220941086a29000037030020052009290000370388032009102c2016201b2903003703002005200529038803220a3703c8022005200a3703c803201b41fde0c500ad4280808080e00284220a1002220941086a29000037030020052009290000370388032009102c200541d8026a41086a221d201b290300220c370300200520052903880322153703d80220072015370000200741086a221e200c37000020054198036a41086a2213201629030037030020054198036a41106a221f201a29030037030020054198036a41186a22202018290300370300200520052903c80337039803200541d0016a20054198036a412010940120052802d401210820052802d001210620184200370300201a420037030020164200370300200542003703c803201b201c1002220941086a29000037030020052009290000370388032009102c2016201b2903003703002005200529038803220c3703c8022005200c3703c803201b200a1002220941086a29000037030020052009290000370388032009102c201d201b290300220a3703002005200529038803220c3703d8022007200c370000201e200a37000020132016290300370300201f201a29030037030020202018290300370300200520052903c8033703980320052008201920064101461b3602c8032010200541c8036aad4280808080c00084100120032001200120034b1b2221450d014100201941e07a6a2209200920194b1b21222014410020121b212320054188036aad4280808080c000842124200f42808080808002842125201941016a2126200021114100212702400240034020184200370300201a420037030020164200370300200542003703c803201b201c1002220941086a29000037030020052009290000370388032009102c2016201b2903003703002005200529038803220a3703c8022005200a3703c803201b41dcc1c300ad4280808080d001841002220941086a29000037030020052009290000370388032009102c201d201b290300220a3703002005200529038803220c3703d8022007200c370000201e200a37000020132016290300370300201f201a29030037030020202018290300370300200520052903c80337039803200541c8036a20054198036a412010d00120052902cc03420020052802c80322091b220a422088a741057421082027220641016a2127200220064102746a210e2000200641e0006c6a210b2009410120091b220d210902400340024020080d00410021040c020b4101210420112009460d012009200b412010dd052106200841606a2108200941206a210920060d000b0b0240200aa7450d00200d102c0b0240024020040d00200e2802002109200542003703d002200542003703c802200541c0016a200b290320220a200b41286a290300428094ebdc03420010e105200541a0016a200b290330220c200b41386a290300428094ebdc03420010e105200541b0016a20052903c0012210200541c0016a41086a290300220f4280ec94a37c427f10e005200541f0006a2010200f2009ad2215420010e00520054190016a20052903a0012210200541a0016a41086a290300220f4280ec94a37c427f10e00520054180016a2010200f2015420010e005200542003703e002200542003703d802200c2005290390017c20157e2210428094ebdc0380210c02400240024020052903704200200a20052903b0017c20157e220a200a428094ebdc0380220a4280ec94a37c7e7c4280cab5ee0156200aa76a2208ad7d85200541f0006a41086a29030042002008410047ad7d8584500d00200529038001210a20054180016a41086a290300212820054188026a2017200b108e042005280288022108200520052802900222063602ec01200520083602e801200541a8026a2006ad4220862008ad841003108d010240024020052802a80222060d004200210f0c010b20052802ac0221040240024020052802b002220d4104490d00200d417c6a410f4d0d00200628000021294201210f0c010b200541003602d003200542013703c8032005410b36028c032005200541e8016a360288032005200541c8036a3602ec03200541013602ac032005420137029c03200541d0b0c20036029803200520054188036a3602a803200541ec036a41c49ac50020054198036a10391a20053502d00342208620053502c803841004024020052802cc03450d0020052802c803102c0b4200210f0b2004450d002006102c0b0240200528028c02450d002008102c0b200920294100200f4200521b22034d0d0320054198036a2017200b108e0420053502a003210f20052802980321064110102a2208450d0420082009360000200841104120102e2209450d042009200a2010200c4280ec94a37c7e7c4280cab5ee0156200ca76aad7c220c3700042009410c6a2028200c200a54ad7c220a370000200f4220862006ad842009ad4280808080c0028410012009102c0240200528029c03450d002006102c0b200541a8026a200b108f0420052802b002450d0120054188026a41106a200541a8026a41106a28020036020020054188026a41086a200541a8026a41086a290300370300200520052903a802370388020c020b20054200370390032005420037038803200542003703f001200542003703e801200541a8026a200b108f040240024020052802b002450d0020054188026a41106a200541a8026a41106a28020036020020054188026a41086a200541a8026a41086a290300370300200520052903a802370388020c010b200541003602d803200542043703d003200520223602cc03200541003602c803200b200541c8036a10910420054188026a41106a20052802d80336020020054188026a41086a20052903d003370300200520052903c803370388020b2013200529038802370200201341086a20054188026a41086a290300370200201341106a20054188026a41106a280200360200200541003a00c0032005200b36029c032005202236029803200520233602bc032005200541e8016a3602b803200520054188036a3602b403200541c8036a20054198036a201710a704024020052802d0034102460d0020052802c803220d20052802a003470d00410021090240202620052802a40322064d0d00024020052802b003220820052802ac03470d00200841016a22092008490d09200841017422042009200420094b1b220941ffffffff03712009470d09200941027422044100480d090240024020080d002004102a21040c010b20052802a80320084102742004102e21040b2004450d06200520093602ac03200520043602a8030b20052802a803220941046a2009200841027410dc051a2009202620066b360200200520263602a403410121092005200841016a3602b0032005200d41016a220d3602a0030b200520093a00c003200b108604200b1087040240200b108a0241ff017122084102460d002008410171450d00109b040b2009450d0020052802a403210e02400240024020052802b0032201450d0020052802a80321082001410274210441002106200e210902400340200920224d0d01200641016a2106200920082802006b2109200841046a21082004417c6a22040d000c020b0b200120064f0d010b2005200e2022200e20224b1b3602a4030c010b2005200e2022200e20224b1b3602a403200520063602b00341000d00200d20016b200d20066b4f0d00410020016b210903402016200b41086a290200370300201a200b41106a2902003703002018200b41186a2902003703002005200b2902003703c8032005200d20096a3602e803200541c8036a1088042006200941016a22096a0d000b0b200b20131091040b20052802ac03450d0220052802a803102c0c020b200541003602d803200542043703d003200520223602cc03200541003602c803200b200541c8036a10910420054188026a41106a20052802d80336020020054188026a41086a20052903d003370300200520052903c803370388020b2013200529038802370200201341086a222a20054188026a41086a222b290300370200201341106a222c20054188026a41106a222d280200360200200541003a00c0032005200b36029c032005202236029803200520233602bc032005200541d8026a3602b8032005200541c8026a3602b403200541e8006a20054198036a2017200c200a10a80420052802a003210e02400240024020052802684101470d00200528026c2208200e460d010b20052d00c00321090c010b02400240202620052802a40322094d0d00024020052802b003220620052802ac03470d00200641016a22042006490d082006410174220d2004200d20044b1b220441ffffffff03712004470d082004410274220d4100480d080240024020060d00200d102a210d0c010b20052802a8032006410274200d102e210d0b200d450d05200520043602ac032005200d3602a8030b20052802a803220441046a2004200641027410dc051a2004202620096b360200200520263602a403410121092005200641016a3602b0032005200841016a22083602a0030c010b20052d00c00321090b200520093a00c003200b108604200b1087040240200b108a0241ff017122064102460d002006410171450d00109b040b2008210e0b0240200941ff0171450d0020052802a4032101200528029803210d02400240024020052802b0032212450d0020052802a8032108201241027421044100210620012109024003402009200d4d0d01200641016a2106200920082802006b2109200841046a21082004417c6a22040d000c020b0b201220064f0d010b20052001200d2001200d4b1b3602a4030c010b20052001200d2001200d4b1b3602a403200520063602b00341000d00200e20126b200e20066b4f0d00410020126b2108200528029c0321090340200941086a290000210a200941106a290000210c200929000021102018200941186a290000370300201a200c3703002016200a370300200520103703c8032005200e20086a3602e803200541c8036a1088042006200841016a22086a0d000b0b200528029c0320131091040b024020052802ac03450d0020052802a803102c0b4200210a200542003703900320054200370388030240024002400240200b41c8006a220928020022080d00410821120c010b2008ad220a42307e220c422088a70d07200ca722084100480d072008102a2212450d04200928020022090d010b4200210f420021280c010b200b41c0006a2802002201200941306c6a212e2003ad212f0340200542003703f001200542003703e801200541c0006a2001290300220f200141086a290300428094ebdc03420010e105200541306a2005290340220c200541c0006a41086a29030022104280ec94a37c427f10e005200541206a200c2010202f420010e005200541106a200c20102015420010e00520054198036a2017200141106a220d108d04200541d0006a200528029803220820052802a003109e014200200541106a41086a29030020052903102210200f20052903307c220f20157e220c200c428094ebdc0380220c4280ec94a37c7e7c4280cab5ee0156200ca76aad7c220c201054ad7c2210200541206a41086a29030020052903202228200f202f7e220f200f428094ebdc0380220f4280ec94a37c7e7c4280cab5ee0156200fa76aad7c220f202854ad7c7d200c200f54ad7d2228200c200f7d220f200c56202820105620282010511b22091b21104200200f20091b210c200541d0006a41106a290300210f20052903582128200528025021090240200528029c03450d002008102c0b200541c8036a2017200d108d0420052802c803210820053502d003213020052028420020091b2228200c7c220c370398032005200f420020091b20107c200c202854ad7c22103703a00320304220862008ad8420251001024020052802cc03450d002008102c0b200541a8026a200d108f040240024020052802b002450d00202d200541a8026a41106a280200360200202b200541a8026a41086a290300370300200520052903a802370388020c010b200541003602d803200542043703d003200520223602cc03200541003602c803200d200541c8036a109104202d20052802d803360200202b20052903d003370300200520052903c803370388020b2013200529038802370200202a202b290300370200202c202d280200360200200541003a00c0032005200d36029c032005202236029803200520233602bc032005200541e8016a3602b803200520054188036a3602b403200541086a20054198036a2017200c201010a80420052802a003210302400240024020052802084101470d00200528020c22062003460d010b20052d00c00321090c010b02400240202620052802a40322094d0d00024020052802b003220820052802ac03470d00200841016a22042008490d0a2008410174220e2004200e20044b1b220441ffffffff03712004470d0a2004410274220e4100480d0a0240024020080d00200e102a210e0c010b20052802a8032008410274200e102e210e0b200e450d07200520043602ac032005200e3602a8030b20052802a803220441046a2004200841027410dc051a2004202620096b360200200520263602a403410121092005200841016a3602b0032005200641016a22033602a0030c010b20052d00c0032109200621030b200520093a00c003200d108604200d1087040b0240200941ff0171450d0020052802a4032114200528029803210e02400240024020052802b0032231450d0020052802a8032108203141027421044100210620142109024003402009200e4d0d01200641016a2106200920082802006b2109200841046a21082004417c6a22040d000c020b0b203120064f0d010b20052014200e2014200e4b1b3602a4030c010b20052014200e2014200e4b1b3602a403200520063602b00341000d00200320316b200320066b4f0d00410020316b2108200528029c0321090340200941086a290000210c200941106a29000021102009290000210f2018200941186a290000370300201a20103703002016200c3703002005200f3703c8032005200320086a3602e803200541c8036a1088042006200841016a22086a0d000b0b200528029c0320131091040b024020052802ac03450d0020052802a803102c0b200d41086a290000210c200d29000021102020200d41186a290000370300201f200d41106a2900003703002013200c3703002005201037039803200541e8016a41086a290300210c20052903e801211002400240200a422088220fa72209200aa7460d00200921080c010b200941016a22062009490d07200fa722084101742204200620062004491bad220a42307e220f422088a70d07200fa722064100480d070240024020090d002006102a21120c010b2012200941306c2006102e21120b2012450d040b2013290300210f201f29030021282020290300213020052903980321322012200841306c6a2209201037032020092032370300200941286a200c370300200941186a2030370300200941106a2028370300200941086a200f370300200a42ffffffff0f83200841016aad42208684210a200141306a2201202e470d000b201b2903002128200529038803210f0b200541c8026a41086a2204290300211020052903c8022115200541e8016a41086a2209200b41086a290300370300200541e8016a41106a2208200b41106a290300370300200541e8016a41186a2206200b41186a2903003703002005200b2903003703e8012012450d00201d290300212f20052903d802213020054188026a41186a220e2006290300370300202d2008290300370300202b2009290300370300200520052903e80137038802200b280258220d41ffffff3f71200d470d03200d4105742206417f4c0d03200b28025021090240024020060d004101210b0c010b2006102a220b450d020b02400240200d0d00410021010c010b200b2108034020082009290000370000200841186a200941186a290000370000200841106a200941106a290000370000200841086a200941086a290000370000200841206a2108200941206a2109200641606a22060d000b200d41057441606a41057641016a21010b200541a8026a41186a2203200e290300370300200541a8026a41106a220e202d290300370300200541a8026a41086a2214202b29030037030020052005290388023703a802201b201c1002220941086a29000037030020052009290000370388032009102c2004201b29030037030020052005290388033703c802201b41d1fdc200ad42808080808002841002220941086a29000037030020052009290000370388032009102c201d201b29030037030020052005290388033703d8022005201936028803202020241006220941186a290000370300201f200941106a2900003703002013200941086a29000037030020052009290000370398032009102c20182020290300370300201a201f2903003703002016201329030037030020052005290398033703c80341c000102a2206450d01200620052903c802370000200620052903d802370010200620052903c80337002041082104200641086a200541c8026a41086a290300370000200641186a200541d8026a41086a290300370000200641286a200541c8036a41086a290300370000200641306a201a290300370000200641386a201829030037000020054198036a200641c00010e90302400240200528029803222b0d00410021084200210c410021090c010b200529029c03220c422088a72108200ca72109202b21040b20202003290300370300201f200e29030037030020132014290300370300200520052903a80237039803024020082009470d0002402008200ca7470d00200841016a22092008490d062008410174220e2009200e20094b1bad223242d8007e2233422088a70d062033a722094100480d060240024020080d002009102a21040c010b2004200841d8006c2009102e21040b2004450d03200c42808080807083203284210c0b200c422088a721080b2004200841d8006c220e6a22092015200f7c220f3703102009202f370308200920303703002009200b36022c20092012360220200941186a201020287c200f201554ad7c370300200941346a2001360200200941306a200d360200200941246a200a3702002009200529039803370338200941c0006a2013290300370300200941c8006a201f290300370300200941d0006a20202903003703000240024020040d002006ad428080808080088410050c010b20054198036a2004200841016a2209109e042006ad428080808080088420053502a0034220862005280298032208ad8410010240200528029c03450d002008102c0b200ca7210b02402009450d00200441306a2109200e41d8006a210803400240200941746a280200450d00200941706a280200102c0b02402009280200450d002009417c6a280200102c0b200941d8006a2109200841a87f6a22080d000b0b200b450d002004102c0b2006102c0b201141e0006a211120272021490d010c050b0b1033000b103a000b1035000b200aa7450d00200b102c0b200541f0036a24000bbd0101057f2001280208210302402001410c6a280200220420024d0d0002400240200141186a2802002205450d00200141106a2802002101200541027421062003417f6a2103034002402004200128020022076b220520024b0d00200420024b0d030b200141046a21012003417f6a2103200521042006417c6a22060d000b0b200041023602080f0b2000200736020c2000410136020820002005ad4220862003ad843702000f0b2000410036020820002004ad4220862003ad843702000bc91604027f037e057f047e230041e0026b22052400200541c8016a2001200210a7040240024020052802d0014102470d00410021020c010b20052802c80121062001280204220241086a2900002107200241106a290000210820022900002109200541c8016a41186a200241186a290000370300200541c8016a41106a2008370300200541c8016a41086a2007370300200520093703c801200520063602e801200541b0026a41086a22024196e0c500ad4280808080f000841002220a41086a2900003703002005200a2900003703b002200a102c200541f0016a41086a2002290300370300200520052903b0023703f001200241a8f9c200ad42808080809001841002220a41086a2900003703002005200a2900003703b002200a102c20054180026a41086a2002290300370300200520052903b00237038002024002404104102a2202450d00200542043702b402200520023602b002200541c8016a200541b0026a10910120052802e801210b0240024020052802b402220a20052802b80222026b4104490d0020052802b002210a0c010b200241046a220c2002490d02200a4101742202200c2002200c4b1b22024100480d0202400240200a0d002002102a210a0c010b20052802b002200a2002102e210a0b200a450d01200520023602b4022005200a3602b00220052802b80221020b2005200241046a3602b802200a20026a200b36000020052802b402210a200541b0026a41186a220b20053502b80242208620052802b002220dad841006220241186a290000370300200541b0026a41106a220c200241106a290000370300200541b0026a41086a220e200241086a290000370300200520022900003703b0022002102c20054190026a41186a200b29030037030020054190026a41106a200c29030037030020054190026a41086a200e290300370300200520052903b002370390020240200a450d00200d102c0b41c000102a2202450d00200220052903f00137000020022005290380023700102002200529039002370020200241086a200541f0016a41086a290300370000200241186a20054180026a41086a220b290300370000200241286a20054190026a41086a290300370000200241306a20054190026a41106a290300370000200241386a20054190026a41186a290300370000200541c0003602d402200520023602d00220054180026a2002ad42808080808008841003108d0102400240200528028002220a0d004200210f0c010b200528028402210c02400240200b280200220b4110490d00200b4170714110460d00200a41186a2900002108200a41086a2900002110200a2900102107200a29000021094201210f0c010b200541003602980220054201370390022005410b3602f4012005200541d0026a3602f001200520054190026a3602dc02200541c4026a4101360200200542013702b402200541d0b0c2003602b0022005200541f0016a3602c002200541dc026a41c49ac500200541b0026a10391a2005350298024220862005350290028410040240200528029402450d00200528029002102c0b4200210f0b200c450d00200a102c0b2002102c20084200200f42005222021b21082007420020021b21070240024002402009420020021b220f2003542010420020021b220920045420092004511b0d00200f20038520092004858450450d02200541b8016a20032004428094ebdc03420010e105200541a8016a20052903b8012209200541b8016a41086a290300220f4280ec94a37c427f10e00520054198016a2009200f20013502242210420010e00520054188016a4200200529039801220f201020052903a80120037c7e22092009428094ebdc038022094280ec94a37c7e7c4280cab5ee01562009a76aad7c220920077d2210201020095620054198016a41086a2903002009200f54ad7c220f20087d2009200754ad7d2209200f562009200f511b22021b220f4200200920021b428094ebdc03420010e105200541f8006a200529038801220920054188016a41086a29030022104280ec94a37c427f10e005200541e8006a200920104280cab5ee01420010e005200541e8006a41086a29030020052903682210200f20052903787c22094280cab5ee017e428094ebdc03824280cab5ee01562009420188a76aad7c2209201054ad7c210f410021020c010b200541c8006a20032004428094ebdc03420010e105200541d8006a20032004428094ebdc03420010e205200541386a2005290348200541c8006a41086a29030020013502242210420010e005200541286a420020052903382211201020052903587e22102010428094ebdc038022104280ec94a37c7e7c4280cab5ee01562010a76aad7c221020077d22122012201056200541386a41086a2903002010201154ad7c221120087d2010200754ad7d221020115620102011511b22021b22114200201020021b428094ebdc03420010e105200541186a20052903282210200541286a41086a29030022124280ec94a37c427f10e005200541086a201020124280cab5ee01420010e005200141206a28020022022003200f7d221020022903007c2212370300200241086a2202200420097d2003200f54ad7d20022903007c2012201054ad7c370300200541086a41086a2903002005290308220f201120052903187c22094280cab5ee017e428094ebdc03824280cab5ee01562009420188a76aad7c2209200f54ad7c210f410121020b024002402009200f84500d00200128021c22022002290300221020097c2211370300200241086a22022002290300200f7c2011201054ad7c3703002008200f7c200720097c2209200754ad7c2108200921070c010b2002450d010b200141013a0028200541b0026a41086a22024196e0c500ad4280808080f000841002220141086a290000370300200520012900003703b0022001102c200541f0016a41086a2002290300370300200520052903b0023703f001200241a8f9c200ad42808080809001841002220141086a290000370300200520012900003703b0022001102c20054180026a41086a2002290300370300200520052903b002370380024104102a2202450d01200542043702b402200520023602b002200541c8016a200541b0026a10910120052802e801210a0240024020052802b402220120052802b80222026b4104490d0020052802b00221010c010b200241046a220b2002490d0320014101742202200b2002200b4b1b22024100480d030240024020010d002002102a21010c010b20052802b00220012002102e21010b2001450d02200520023602b402200520013602b00220052802b80221020b2005200241046a3602b802200120026a200a36000020052802b4022101200541b0026a41186a220a20053502b80242208620052802b002220ead841006220241186a290000370300200541b0026a41106a220b200241106a290000370300200541b0026a41086a220c200241086a290000370300200520022900003703b0022002102c20054190026a41186a200a29030037030020054190026a41106a200b29030037030020054190026a41086a200c290300370300200520052903b0023703900202402001450d00200e102c0b41c000102a2202450d01200220052903f00137000020022005290380023700102002200529039002370020200241086a200541f0016a41086a290300370000200241186a20054180026a41086a290300370000200241286a20054190026a41086a290300370000200241306a20054190026a41106a290300370000200241386a20054190026a41186a2903003700004110102a2201450d012001200337000020012004370008200141104120102e2201450d0120012007370010200141186a20083700002002ad42808080808008842001ad428080808080048410012001102c2002102c0b410121020c020b1033000b1035000b2000200636020420002002360200200541e0026a24000bb80302057f017e230041c0006b22022400200241206a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341b5fdc200ad4280808080d000841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2000109f01024041c000102a2204450d00200420022903003700002004200229031037001020042002290020370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a29000037000002400240200141ff0171220341024d0d004101210342002107410121010c010b024002400240024020030e03000102000b410021010c020b410121010c010b410221010b200220013a00204101102a2203450d01200320013a00004100210142808080801021070b2004ad428080808080088420072003ad841001024020010d002003102c0b2004102c200241c0006a24000f0b1033000bc70201057f230041c0006b22022400200241206a41086a22034196e0c500ad4280808080f000841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341d3f8c200ad4280808080e000841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2000109f01024041c000102a22040d001033000b200420022903003700002004200229031037001020042002290020370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241c000360224200220043602202001200241206a10a1022004102c200241c0006a24000b13002000410a360204200041a4e2c5003602000bba0a02037f017e02400240024002400240024020002802000e0400010203000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d05200241017422002004200020044b1b22004100480d050240024020020d002000102a21020c010b200128020020022000102e21020b2002450d0420012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d04200241017422042003200420034b1b22044100480d040240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d04200241017422002003200020034b1b22004100480d040240024020020d002000102a21020c010b200128020020022000102e21020b2002450d0320012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d03200241017422042003200420034b1b22044100480d030240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d03200241017422002004200020044b1b22004100480d030240024020020d002000102a21020c010b200128020020022000102e21020b2002450d0220012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d02200241017422042003200420034b1b22044100480d020240024020020d002004102a21030c010b200128020020022004102e21030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41043a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d02200241017422002003200020034b1b22004100480d020240024020020d002000102a21020c010b200128020020022000102e21020b2002450d0120012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b1033000b1035000b130020004104360204200041b8ecc3003602000b3400200041afb7c50036020420004100360200200041146a4101360200200041106a41ecf8c300360200200041086a42043702000b4b01027f230041106b2202240002404101102a22030d001033000b200341003a0000200041086a4101360200200241013602042002200336020020002002290300370200200241106a24000b13002000410336020420004198fac3003602000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241103600000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241033600000b3901017f02404110102a22020d001033000b200242003700082002428080e983b1de16370000200042908080808002370204200020023602000be50902067f027e230041106b2202240020002802102103200041186a2802002204200110670240024002400240200141046a2802002205200141086a28020022066b2004490d00200128020021050c010b200620046a22072006490d02200541017422062007200620074b1b22064100480d020240024020050d002006102a21050c010b200128020020052006102e21050b2005450d0120012005360200200141046a2006360200200141086a28020021060b200141086a2207200620046a360200200520066a2003200410db051a200028021c210502400240200141046a2802002206200728020022046b4104490d00200128020021060c010b200441046a22032004490d02200641017422042003200420034b1b22044100480d020240024020060d002004102a21060c010b200128020020062004102e21060b2006450d0120012006360200200141046a2004360200200141086a28020021040b200141086a2203200441046a360200200620046a20053600002002200136020c2000412c6a2002410c6a109402200041086a29030021082000290300210902400240200141046a2802002206200328020022046b4110490d00200128020021060c010b200441106a22052004490d02200641017422042005200420054b1b22044100480d020240024020060d002004102a21060c010b200128020020062004102e21060b2006450d0120012006360200200141046a2004360200200141086a28020021040b200141086a2205200441106a360200200620046a22042008370008200420093700002000280220210302400240200141046a2802002206200528020022046b4104490d00200128020021060c010b200441046a22052004490d02200641017422042005200420054b1b22044100480d020240024020060d002004102a21060c010b200128020020062004102e21060b2006450d0120012006360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200620046a20033600000240024020002802244101460d0002400240200141046a28020020052802002200460d00200128020021040c010b200041016a22042000490d04200041017422062004200620044b1b22064100480d040240024020000d002006102a21040c010b200128020020002006102e21040b2004450d0320012004360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200420006a41003a00000c010b02400240200141046a28020020052802002204460d00200128020021060c010b200441016a22062004490d03200441017422052006200520064b1b22054100480d030240024020040d002005102a21060c010b200128020020042005102e21060b2006450d0220012006360200200141046a2005360200200141086a28020021040b200141086a2205200441016a360200200620046a41013a00002000280228210602400240200141046a2802002204200528020022006b4104490d00200128020021040c010b200041046a22052000490d03200441017422002005200020054b1b22004100480d030240024020040d002000102a21040c010b200128020020042000102e21040b2004450d0220012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a20063600000b200241106a24000f0b1033000b1035000b130020004101360204200041f8fcc3003602000b1300200041053602042000419cfec3003602000b3400200041e4d2c50036020420004100360200200041146a4107360200200041106a41f490c400360200200041086a42083702000b3301017f02404110102a22020d001033000b2002420037000820024201370000200042908080808002370204200020023602000b2201017f230041106b22022400200241003602002000200210c903200241106a24000bc70101017f23004190016b22022400200241003a00782002428080848080023703682002420137035820024201370350200242af0137034820024287013703402002420137033820024201370330200242013703282002420137032020024201370318200242013703102002420137030820024280808080c00037036020024280808180800437037020024100360288012002420137038001200241086a20024180016a10e902200041086a200228028801360200200020022903800137020020024190016a24000b130020004110360204200041f899c4003602000b2f01017f02404108102a22020d001033000b2000428880808080013702042000200236020020024280ade2043700000b2e01017f02404104102a22020d001033000b20004284808080c000370204200020023602002002418080013600000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241203600000b2d01017f02404108102a22020d001033000b20004288808080800137020420002002360200200242e8073700000b3801017f02404110102a22020d001033000b2002420037000820024280a094a58d1d370000200042908080808002370204200020023602000b3701017f02404110102a22020d001033000b2002420037000820024280c8afa025370000200042908080808002370204200020023602000b3a01017f02404110102a22020d001033000b20024200370008200242808086bdbacdd21a370000200042908080808002370204200020023602000b3b01017f02404110102a22020d001033000b200242003700082002428080a8ec85afd1b101370000200042908080808002370204200020023602000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241083600000b2c01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241023600000ba02a04127f017e017f067e230041f0036b22062400200641d0026a200010ee01410221070240024020062d00d00222084102470d0041012108413421094102210a0c010b200641d0036a41086a220b200641e4026a290200370300200641d0036a41106a220a200641ec026a290200370300200641d0036a41186a220c200641f4026a290200370300200641a8036a41086a220d20064188036a290300370300200641a8036a41106a220e20064190036a290300370300200641a8036a41186a220f20064198036a290300370300200641a8036a41206a2210200641a0036a2903003703002006200641dc026a2902003703d003200620064180036a2903003703a803200641d0026a41086a2802002109024020080d00200641fc026a2802002107200641a0026a41186a200c290300370300200641a0026a41106a200a290300370300200641a0026a41086a200b290300370300200641f8016a41086a200d290300370300200641f8016a41106a200e290300370300200641f8016a41186a200f290300370300200641f8016a41206a2010290300370300200620062903d0033703a002200620062903a8033703f8010b4102210a024020074102470d0041012108413421090c010b200641a8036a41186a200641a0026a41186a290300370300200641a8036a41106a200641a0026a41106a290300370300200641a8036a41086a200641a0026a41086a290300370300200641d0026a41086a200641f8016a41086a290300370300200641d0026a41106a200641f8016a41106a290300370300200641d0026a41186a200641f8016a41186a290300370300200641d0026a41206a200641f8016a41206a290300370300200620062903a0023703a803200620062903f8013703d002410021082007210a0b200641d8016a41086a220c200641a8036a41086a220d290300370300200641d8016a41106a220e200641a8036a41106a220f290300370300200641d8016a41186a2210200641a8036a41186a2211290300370300200641b0016a41086a2212200641d0026a41086a2207290300370300200641b0016a41106a2213200641d0026a41106a220b290300370300200641b0016a41186a2214200641d0026a41186a2215290300370300200641b0016a41206a2216200641d0026a41206a290300370300200620062903a8033703d801200620062903d0023703b0010240024020080d0020064188016a221720062903b001370300200641ec006a200c290300370200200641f4006a200e290300370200200641fc006a201029030037020020064190016a201229030037030020064198016a2013290300370300200641a0016a2014290300370300200641a8016a201629030037030020062009360260200620062903d8013702642006200a3602840120154200370300200b420037030020074200370300200642003703d002200641a0026a41086a22084191b0c200ad4280808080e000841002220941086a290000370300200620092900003703a0022009102c20072008290300370300200620062903a0023703d002200841acb0c200ad4280808080e000841002220941086a290000370300200620092900003703a0022009102c200b20062903a0022218370300200d2007290300370300200f201837030020112008290300370300200620183703d801200620062903d0023703a803200641d8006a200641a8036a4120109401200628025c410020062802581b210c41012107024002402006280284014101470d002017280200200c460d010b200641d0026a200110ee010240024020062d00d002220a4102470d00412e210d41d5b2c400210e0c010b200641a0026a41026a20062d00d3023a0000200641a8036a41086a2207200641e4026a280200360200200620062f00d1023b01a0022006200641dc026a2902003703a803200641ec026a2802002108200641e8026a28020021090240200a0d0041012107412e210d41d5b2c400210e024020080d000c020b2009102c0c010b200641d0026a41086a280200210d20062802d402210e200641d8016a41026a200641a0026a41026a2d00003a0000200641f8016a41086a2007280200360200200620062f01a0023b01d801200620062903a8033703f801200641f0026a2d0000210f410021070b200641c0026a41026a200641d8016a41026a2d00003a0000200641b0016a41086a220a200641f8016a41086a280200360200200620062f01d8013b01c002200620062903f8013703b00120070d00200641e3036a200a280200360000200620062f01c0023b01d0032006200d3600d7032006200e3600d303200620062903b0013700db032006200f3a00ef03200620083600eb03200620093600e7032006200641c2026a2d00003a00d2032006280284012116200628028801211720062005280200220e200541086a280200221241057422086a3602b4012006200e3602b0012006200641e0006a3602b801024002400240024002400240024002402012450d00200e210703402006200741206a22093602b001200641d0026a200a200710c70420062802d00222070d0220092107200841606a22080d000b0b41002110200641003602c802200642043703c0024104210f410021110c010b200641a8036a41086a2209200641d0026a410c6a280200360200200620062902d4023703a8034110102a220f450d01200f2007360200200f20062903a803370204200f410c6a20092802003602002009200641b0016a41086a280200360200200620062903b00122183703a803024002402018a7220820062802ac03220a470d0041012110410121110c010b200641d0026a4104722113200a41606a21154101211041012111034020082107024003402006200741206a22083602a803200641d0026a2009200710c70420062802d002220d0d0120082107200a2008470d000c030b0b200641f8016a41086a201341086a28020022083602002006201329020022183703f801200641d0026a41086a22192008360200200620183703d002024020112010470d00201041016a22082010490d05201041017422112008201120084b1b221141ffffffff00712011470d05201141047422084100480d050240024020100d002008102a210f0c010b200f20104104742008102e210f0b200f450d040b200741206a2108200f20104104746a2214200d360200201420062903d0023702042014410c6a2019280200360200201041016a211020152007470d000b0b200620103602c802200620113602c4022006200f3602c0020b200641f8006a350200422086200635027084100f2118200641003602b003200642013703a8032018a722152018422088a7220d200641a8036a1086030240024020062802ac03220a20062802b00322096b4120490d00200941206a210720062802a80321080c010b200941206a22072009490d02200a41017422082007200820074b1b22134100480d0202400240200a0d002013102a21080c010b20062802a803200a2013102e21080b2008450d01200620133602ac03200620083602a8032013210a0b200620073602b003200820096a22092002290000370000200941086a200241086a290000370000200941106a200241106a290000370000200941186a200241186a290000370000200641d0026a41186a22092007ad4220862008ad841006220741186a290000370300200641d0026a41106a2213200741106a290000370300200641d0026a41086a2214200741086a290000370300200620072900003703d0022007102c200641b0016a41186a2009290300370300200641b0016a41106a2013290300370300200641b0016a41086a2014290300370300200620062903d0023703b0010240200a450d002008102c0b0240200d450d002015102c0b0240200641b0016a200641d0036a412010dd050d00200c201720121b210a4101201620121b2112200641f0006a210d4100210802402010450d0020104104742109200f410c6a2107410021080340200728020020086a2108200741106a2107200941706a22090d000b0b2006200628027c20086b36027c200010f601200641d0026a41106a2209200437030020064180036a200a360200200641fc026a2012360200200641f8026a200c360200200641f4026a200628027c360200200641d0026a41186a220a200d290300370300200641d0026a41206a200d41086a28020036020020064184036a20022900003702002006418c036a200241086a29000037020020064194036a200241106a2900003702002006419c036a200241186a290000370200200620033703d802200641003a00d0022001200641d0026a10f801200641c8006a200010b701200641c8006a41086a290300211a2006290348211b200641f8016a20004200420010a00120062903f801211c200a420037030020094200370300200641d0026a41086a22084200370300200642003703d002200641a0026a41086a2207418be9c500ad4280808080800184221d1002220041086a290000370300200620002900003703a0022000102c20082007290300370300200620062903a00222183703d801200620183703d002200741c9b5c000ad4280808080d00184221e1002220041086a290000370300200620002900003703a0022000102c200641d8016a41086a220020072903002218370300200620062903a00222033703d801200b2003370000200b41086a22022018370000200641a8036a41086a220c2008290300370300200641a8036a41106a220d2009290300370300200641a8036a41186a2212200a290300370300200620062903d0023703a803200641306a200641a8036a4120109e01200641306a41106a2903004200200628023022131b21182006290338420020131b2103200641f8016a41106a290300211f200629038002210402400240201c4200520d00200a42003703002009420037030020084200370300200642003703d0022007201d1002221341086a290000370300200620132900003703a0022013102c20082007290300370300200620062903a002221c3703d8012006201c3703d0022007201e1002221341086a290000370300200620132900003703a0022013102c20002007290300221c370300200620062903a002221d3703d801200b201d3700002002201c370000200c2008290300370300200d20092903003703002012200a290300370300200620062903d0023703a8032006427f2018201f7c200320047c22042003542207ad7c22032007200320185420032018511b22071b3703d8022006427f200420071b3703d002200641d0026a21070c010b200a42003703002009420037030020084200370300200642003703d0022007201d1002221341086a290000370300200620132900003703a0022013102c20082007290300370300200620062903a002221c3703d8012006201c3703d0022007201e1002221341086a290000370300200620132900003703a0022013102c20002007290300221c370300200620062903a002221d3703d801200b201d3700002002201c370000200c2008290300370300200d20092903003703002012200a290300370300200620062903d0023703a803200642002018201f7d2003200454ad7d221c200320047d2204200356201c201856201c2018511b22071b3703d80220064200200420071b3703d002200641d0026a21070b200641a8036aad428080808080048422042007ad42808080808002841001200641206a2001201b201a109d01200641206a41086a29030021032006290320211a200641d0026a41186a22094200370300200641d0026a41106a22004200370300200641d0026a41086a22084200370300200642003703d002200641a0026a41086a2207418be9c500ad428080808080018422181002220a41086a2900003703002006200a2900003703a002200a102c20082007290300370300200620062903a002221b3703d8012006201b3703d002200741c9b5c000ad4280808080d00184221b1002220a41086a2900003703002006200a2900003703a002200a102c200641d8016a41086a220c2007290300221c370300200620062903a002221d3703d801200b201d370000200b41086a220d201c370000200641a8036a41086a22122008290300370300200641a8036a41106a22132000290300370300200641a8036a41186a22142009290300370300200620062903d0023703a803200641086a200641a8036a4120109e01200641086a41106a290300211c2006290310211d2006280208210a200942003703002000420037030020084200370300200642003703d002200720181002220241086a290000370300200620022900003703a0022002102c20082007290300370300200620062903a00222183703d801200620183703d0022007201b1002220241086a290000370300200620022900003703a0022002102c200c20072903002218370300200620062903a002221b3703d801200b201b370000200d2018370000201220082903003703002013200029030037030020142009290300370300200620062903d0023703a8032006427f2003201c4200200a1b22187c201a201d4200200a1b22037c221a2003542207ad7c22032007200320185420032018511b22071b3703d8022006427f201a20071b3703d0022004200641d0026aad4280808080800284100102402010450d0020104104742108200f41046a210703400240200741046a280200450d002007280200102c0b200741106a2107200841706a22080d000b0b02402011450d00200f102c0b200541046a280200450d08200e102c0c080b200f20104104746a210e200f21072010450d03200641a8036aad42808080808004842103200f210703400240200728020022080d00200741106a21070c050b2006280278220941164d0d03200741046a28020021002006280270210b200741086a280200210a2007410c6a3502002118200641d0026a41186a22022008ad42808080808004841006220841186a290000370300200641d0026a41106a220c200841106a290000370300200641d0026a41086a220d200841086a290000370300200620082900003703d0022008102c200641a8036a41186a2002290300370300200641a8036a41106a200c290300370300200641a8036a41086a200d290300370300200620062903d0023703a8032009ad422086200bad84200941696aad422086200b41176aad844101200320184220862000ad84100a0240200a450d002000102c0b200741106a2207200e470d000c050b0b1033000b1035000b411720091047000b2007200e460d0003402007280200450d010240200741086a280200450d00200741046a280200102c0b200741106a2207200e470d000b0b2011450d00200f102c0b200641f4006a280200450d002006280270102c0b200541046a280200450d002005280200102c0b200641f0036a24000b9d0403057f017e027f230041f0006b22032400024002402001280200220441186a280200220541164d0d0020042802102106200341d0006a41186a22072002ad428080808080048422081006220441186a290000370300200341d0006a41106a2209200441106a290000370300200341d0006a41086a220a200441086a290000370300200320042900003703502004102c200341106a41186a2007290300370300200341106a41106a2009290300370300200341106a41086a200a2903003703002003200329035037031020032005ad4220862006ad84200541696aad422086200641176aad844101200341106aad42808080808004841008108d010240024020032802000d00200041003602000c010b20012802002204280218220541164d0d0220042802102106200341d0006a41186a220120081006220441186a290000370300200341d0006a41106a2207200441106a290000370300200341d0006a41086a2209200441086a290000370300200320042900003703502004102c200341306a41186a2001290300370300200341306a41106a2007290300370300200341306a41086a2009290300370300200320032903503703302005ad4220862006ad84200541696aad422086200641176aad844101200341306aad4280808080800484100920002002360200200020032903003702042000410c6a200341086a2802003602000b200341f0006a24000f0b411720051047000b411720051047000bc00201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d0020002d0000210420034120710d012004ad42ff018341012001104221000c020b20002d00002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000b20024180016a240020000f0b20044180011047000b20044180011047000bfd0506057f017e017f017e097f017e230041f0016b22012400200141c0006a41186a22024200370300200141c0006a41106a22034200370300200141c0006a41086a2204420037030020014200370340200141f0006a41086a220541bad6c500ad428080808090018422061002220741086a290000370300200120072900003703702007102c200420052903003703002001200129037022083703602001200837034020054184c6c400ad4280808080c001841002220741086a290000370300200120072900003703702007102c200320012903702208370300200141206a41086a22072004290300370300200141206a41106a22092008370300200141206a41186a220a20052903003703002001200837036020012001290340370320200141f0006a200141206a10ea030240024020012d009001220b4103470d004190c6c40021040c010b200141206aad428080808080048422081005200141086a220c2005290300370300200141106a220d200141f0006a41106a220e290300370300200141186a220f200141f0006a41186a22102903003703002001200129037037030020024200370300200342003703002004420037030020014200370340200520061002221141086a290000370300200120112900003703702011102c2004200529030037030020012001290370220637036020012006370340200541d0d6c500ad4280808080d002841002221141086a290000370300200120112900003703702011102c200141e0006a41086a2005290300220637030020012001290370221237036020032012370000200341086a20063700002007200429030037030020092003290300370300200a200229030037030020012001290340370320200141013a00702008200141f0006aad428080808010841001200541023a0000200141063a00704100210441014100200141f0006a1092012010200f290300370300200e200d2903003703002005200c29030037030020012001290300370370200041809c316a200141f0006a200b4180de3410ca040b200141f0016a240020040bbf0c05057f017e017f027e057f230041f0016b22042400200441086a41186a22054200370300200441086a41106a22064200370300200441086a41086a2207420037030020044200370308200441d0016a41086a220841bad6c500ad428080808090018422091002220a41086a2900003703002004200a2900003703d001200a102c20072008290300370300200420042903d001220b3703282004200b370308200841abd6c500ad4280808080f00184220c1002220a41086a2900003703002004200a2900003703d001200a102c200620042903d001220b370300200441c8006a41086a220d2007290300370300200441c8006a41106a220a200b370300200441c8006a41186a220e20082903003703002004200b370338200420042903083703482004200441c8006a41201094012004280204210f2004280200211020054200370300200642003703002007420037030020044200370308200820091002221141086a290000370300200420112900003703d0012011102c20072008290300370300200420042903d001220b3703282004200b3703082008200c1002221141086a290000370300200420112900003703d0012011102c20052008290300220b370300200d2007290300370300200a20042903d001220c370300200e200b3703002004200c370338200420042903083703482004200f410020101b221141016a3602d001200441c8006aad4280808080800484200441d0016aad4280808080c000841001200a200141086a290000370300200e200141106a290000370300200441c8006a41206a200141186a2900003703002004200336024c20042000360248200420023a007020042001290000370350200820091002220141086a290000370300200420012900003703d0012001102c200441286a41086a220a2008290300370300200420042903d001370328200841ebb4c400ad42808080808002841002220141086a290000370300200420012900003703d0012001102c200441386a41086a220e2008290300370300200420042903d001370338200420113602cc01200441d0016a41186a2200200441cc016aad4280808080c000841006220141186a290000370300200441d0016a41106a2203200141106a2900003703002008200141086a290000370300200420012900003703d0012001102c200520002903003703002006200329030037030020072008290300370300200420042903d0013703080240024041c000102a2208450d0020082004290328370000200841086a200a2903003700002008200429033837001020082004290308370020200841186a200e290300370000200841286a2007290300370000200841306a2006290300370000200841386a200529030037000020042802482101200441003602d801200442013703d0014104102a2207450d00200441043602d401200420042802d801220541046a3602d801200420073602d001200720056a20013600002004200441d0016a360208200441d0006a200441086a109402024020042d0070220741024b0d00024002400240024020070e03000102000b410021010c020b410121010c010b410221010b200420013a00080240024020042802d40120042802d8012207460d0020042802d00121050c010b200741016a22052007490d03200741017422062005200620054b1b22064100480d030240024020070d002006102a21050c010b20042802d00120072006102e21050b2005450d02200420063602d401200420053602d00120042802d80121070b2004200741016a3602d801200520076a20013a00000b200428024c21050240024020042802d401220120042802d80122076b4104490d0020042802d00121010c010b200741046a22062007490d02200141017422072006200720064b1b22074100480d020240024020010d002007102a21010c010b20042802d00120012007102e21010b2001450d01200420073602d401200420013602d00120042802d80121070b2004200741046a3602d801200120076a200536000020042802d40121072008ad428080808080088420043502d80142208620042802d0012201ad84100102402007450d002001102c0b2008102c200441d4006a2011360200200441d1006a20023a0000200441d0006a41033a0000200441063a004841014100200441c8006a109201200441f0016a24000f0b1033000b1035000b9f2004067f027e117f097e230022012102200141a0046b41607122012400200141e0006a41186a4200370300200141e0006a41106a22034200370300200141e0006a41086a220442003703002001420037036020014180046a41086a220541bad6c500ad42808080809001841002220641086a29000037030020012006290000370380042006102c20042005290300370300200120012903800422073703a00320012007370360200541d5c5c400ad4280808080b001841002220641086a29000037030020012006290000370380042006102c20032001290380042207370300200141c0006a41086a2004290300370300200141c0006a41106a2007370300200141c0006a41186a2005290300370300200120073703c00320012001290360370340200141203602f4012001200141c0006a3602f001200141f8016a200141c0006aad428080808080048422081003108d010240024002400240024020012802f80122090d004100210a0c010b20012802fc01210b2001200141f8016a41086a28020036029c022001200936029802200141386a20014198026a107502400240024020012802380d000240200128029c02220c41c4006e220d41c4006c2205417f4c0d00200128023c210e0240024020050d004104210a0c010b2005102a220a450d060b0240200e450d004100210f034002400240200c4104490d002001200c417c6a220636029c022001200128029802221041046a360298022010280000211141002105200141003a008001024002400340024020062005470d002001410036029c02200541ff01710d020c030b200141e0006a20056a201020056a220441046a2d00003a00002001200441056a360298022001200541016a22043a0080012004210520044120470d000b200141c0036a41086a2212200141e0006a41086a2213290300370300200141c0036a41106a2214200141e0006a41106a2215290300370300200141c0036a41186a2216200141e0006a41186a22172903003703002001200620046b36029c02200120012903603703c00341002105200141003a008001201020046a21182004200c6b41046a210c03400240200c20056a0d002001410036029c02200541ff0171450d030c020b200141e0006a20056a201820056a221041046a2d00003a00002001201041056a360298022001200541016a22103a0080012006417f6a21062010210520104120470d000b200141e0036a41086a22052013290300370300200141e0036a41106a22102015290300370300200141e0036a41186a22182017290300370300200141a0036a41086a22192012290300370300200141a0036a41106a22122014290300370300200141a0036a41186a221420162903003703002001200620046b220c36029c02200120012903603703e003200120012903c0033703a003201720142903003703002015201229030037030020132019290300370300200120012903a00337036020014180046a41186a201829030037030020014180046a41106a201029030037030020014180046a41086a2005290300370300200120012903e0033703800441002105201121190c030b200141003a0080010b4100210c0b410121050b20014180036a41086a2206200141e0006a41086a29030037030020014180036a41106a2210200141e0006a41106a29030037030020014180036a41186a2218200141e0006a41186a290300370300200141e0026a41086a221120014180046a41086a290300370300200141e0026a41106a221320014180046a41106a290300370300200141e0026a41186a221520014180046a41186a290300370300200120012903603703800320012001290380043703e00202402005450d002001410036028802200d450d05200a102c0c050b200f41016a2104200141c0026a41186a22172018290300370300200141c0026a41106a22182010290300370300200141c0026a41086a22102006290300370300200141a0026a41086a22062011290300370300200141a0026a41106a22112013290300370300200141a0026a41186a2213201529030037030020012001290380033703c002200120012903e0023703a0020240200d200f470d00200f41017422052004200520044b1b220dad42c4007e2207422088a70d0a2007a722054100480d0a02400240200f0d002005102a210a0c010b200a200f41c4006c2005102e210a0b200a450d080b200a200f41c4006c6a22052019360200200520012903c0023702042005410c6a2010290300370200200541146a20182903003702002005411c6a2017290300370200200520012903a0023702242005412c6a2006290300370200200541346a20112903003702002005413c6a20132903003702002004210f2004200e470d000b0b20014190026a200e3602002001200d36028c022001200a36028802200a450d02200129028c0221070c030b103a000b20014100360288020b4100210a200141003602880420014201370380042001410b3602e4032001200141f0016a3602e003200120014180046a3602c003200141f4006a410136020020014201370264200141d0b0c2003602602001200141e0036a360270200141c0036a41c49ac500200141e0006a10391a2001350288044220862001350280048410040240200128028404450d00200128028004102c0b0b200b450d002009102c0b200a4104200a1b211802400240024020074200200a1b221a422088a72211450d002018201141c4006c6a2105200141e0006a201828020010cc04201841c4006a210f02400240200128027022040d004200211b420021070c010b200141286a2001290360200141e0006a41086a290300200141f8006a350200420010e005200141286a41086a29030021072001290328211b2001280274450d002004102c0b0240200f2005470d002001201b3703604100211020014100360270200120073703680c020b201141c4006c41bc7f6a210a410021102018210c410121040340200141e0006a200f220628020010cc0402400240200128027022050d004200211c4200211d0c010b200141186a2001290360200141e0006a41086a2903002001350278420010e005200141186a41086a290300211d2001290318211c2001280274450d002005102c0b200641c4006a210f2007201d201b201c562007201d562007201d511b22051b2107201b201c20051b211b200c200620051b210c2010200420051b2110200441016a2104200a41bc7f6a220a0d000b2001201b3703602001201036027020012007370368200c0d010b41e9c5c4002101201aa7450d012018102c2002240041e9c5c4000f0b201020114f0d022018201041c4006c6a220541186a2206290200211d20182011417f6a220441c4006c6a220c41c0006a2802002110200c41206a290200211b200c41286a290200211c200c41306a290200211e200c41386a290200211f200c2902002120200c2902082107200c29021021212006200c41186a290200370200200529021021222005202137021020052902082121200520073702082005290200210720052020370200200541386a201f370200200541306a201e370200200541286a201c370200200541206a220628020021112006201b370200200541c0006a20103602002001202237037020012021370368200120073703602001201d370378200141e0036a41186a200128027c360200200141e0036a41106a2001290274370300200141e0036a41086a200129026c370300200120012902643703e003200141e0006a41186a220f4200370300200141e0006a41106a220a4200370300200141e0006a41086a220642003703002001420037036020014180046a41086a220541bad6c500ad42808080809001841002221041086a29000037030020012010290000370380042010102c200620052903003703002001200129038004221d3703a0032001201d370360200541d5c5c400ad4280808080b001841002221041086a29000037030020012010290000370380042010102c200141c0036a41086a2005290300221d3703002001200129038004221b3703c0032003201b370000200341086a201d370000200141c0006a41086a2006290300370300200141c0006a41106a200a290300370300200141c0006a41186a200f2903003703002001200129036037034020014100360268200142013703602004200141e0006a106702402004450d00201821050340200528020021100240024020012802642206200128026822046b4104490d00200128026021060c010b200441046a220f2004490d0620064101742204200f2004200f4b1b22044100480d060240024020060d002004102a21060c010b200128026020062004102e21060b2006450d042001200436026420012006360260200128026821040b2001200441046a360268200620046a20103600002001200141e0006a36028004200541046a20014180046a109402200541246a200141e0006a109101200541c4006a2205200c470d000b0b200128026421052008200135026842208620012802602204ad84100102402005450d002004102c0b2007a721100240201aa7450d002018102c0b20014180046a41086a220541bad6c500ad42808080809001841002220441086a29000037030020012004290000370380042004102c200141a0036a41086a2206200529030037030020012001290380043703a003200541e0c5c400ad42808080809001841002220441086a29000037030020012004290000370380042004102c200141c0036a41086a220f200529030037030020012001290380043703c003200120103602800320014180046a41186a220c20014180036aad4280808080c000841006220441186a29000037030020014180046a41106a220a200441106a2900003703002005200441086a29000037030020012004290000370380042004102c200141e0006a41186a2204200c290300370300200141e0006a41106a220c200a290300370300200141e0006a41086a220a2005290300370300200120012903800437036041c000102a2205450d01200520012903a003370000200520012903c00337001020052001290360370020200541086a2006290300370000200541186a200f290300370000200541286a200a290300370000200541306a200c290300370000200541386a2004290300370000200141e0006a200541c00010f303024020012802702206450d002005ad428080808080088410050b200141e8006a2903002107200141f8006a280200210f2001290360211d2001280274210c2005102c02402006450d000240200f4105742204450d002006210503402005201d200710c201200541206a2105200441606a22040d000b0b20014188016a200737030020014180016a201d370300200141e0006a41186a2205200f360200200141f4006a200c360200200141e0006a41106a22042006360200200141ec006a2010360200200141e0006a41086a220641013a0000200141063a006041014100200141e0006a1092012005200141e0036a41186a2802003602002004200141e0036a41106a2903003703002006200141e0036a41086a290300370300200120012903e0033703602001201136027c200041809c316a200141e0006a41004180de3410ca040b410021010b2002240020010f0b1033000b41a888c600201020111038000b1035000bcb0401087f230041f0006b22022400200241d0006a41086a220341bad6c500ad42808080809001841002220441086a290000370300200220042900003703502004102c200241086a41086a2205200329030037030020022002290350370308200341e0c5c400ad42808080809001841002220441086a290000370300200220042900003703502004102c200241186a41086a22062003290300370300200220022903503703182002200136024c200241d0006a41186a2201200241cc006aad4280808080c000841006220441186a290000370300200241d0006a41106a2207200441106a2900003703002003200441086a290000370300200220042900003703502004102c200241286a41186a22082001290300370300200241286a41106a22092007290300370300200241286a41086a2201200329030037030020022002290350370328024041c000102a2204450d00200420022903083700002004200229031837001020042002290328370020200441086a2005290300370000200441186a2006290300370000200441286a2001290300370000200441306a2009290300370000200441386a2008290300370000200241d0006a200441c00010f303200120032903003703002006200241d0006a411c6a2802003602002002200229035037032820022002290264370318024020022802602203450d002000200229032837030020002002290318370214200041086a200241286a41086a2903003703002000411c6a200241186a41086a2802003602000b200020033602102004102c200241f0006a24000f0b1033000bff0301067f230041f0006b22022400200241d0006a41086a220341bad6c500ad42808080809001841002220441086a290000370300200220042900003703502004102c200241086a41086a2205200329030037030020022002290350370308200341ccc5c400ad42808080809001841002220441086a290000370300200220042900003703502004102c200241186a41086a22062003290300370300200220022903503703182002200136024c200241d0006a41186a2201200241cc006aad4280808080c000841006220441186a290000370300200241d0006a41106a2207200441106a2900003703002003200441086a290000370300200220042900003703502004102c200241286a41186a22042001290300370300200241286a41106a22012007290300370300200241286a41086a2207200329030037030020022002290350370328024041c000102a2203450d00200320022903083700002003200229031837001020032002290328370020200341086a2005290300370000200341186a2006290300370000200341286a2007290300370000200341306a2001290300370000200341386a2004290300370000200241d0006a200341c00010d0010240024020022802502204450d0020002002290254370204200020043602000c010b20004100360208200042013702000b2003102c200241f0006a24000f0b1033000b860701067f23004190016b22022400200241206a200141206a280200360200200241186a200141186a290200370300200241106a200141106a290200370300200241086a200141086a29020037030020022001290200370300200241e8006a41086a220141bad6c500ad42808080809001841002220341086a290000370300200220032900003703682003102c200241286a41086a200129030037030020022002290368370328200141fbb4c400ad4280808080e000841002220341086a290000370300200220032900003703682003102c200241386a41086a20012903003703002002200229036837033802404104102a2203450d0020024284808080c00037026c20022003360268200320022802003600002002410472200241e8006a109101200228026c2104200241e8006a41186a2205200235027042208620022802682206ad841006220341186a290000370300200241e8006a41106a2207200341106a2900003703002001200341086a290000370300200220032900003703682003102c200241c8006a41186a2005290300370300200241c8006a41106a2007290300370300200241c8006a41086a20012903003703002002200229036837034802402004450d002006102c0b41c000102a2201450d00200120022903283700002001200229033837001020012002290348370020200141086a200241286a41086a290300370000200141186a200241386a41086a290300370000200141286a200241c8006a41086a2204290300370000200141306a200241d8006a290300370000200141386a200241c8006a41186a290300370000200241c00036022c20022001360228200241c8006a2001ad42808080808008841003108d0102400240200228024822030d0041002103410021040c010b200228024c2107024002402004280200450d0020032d0000220441ff0071220541064b0d00200441077621040c010b20024100360270200242013703682002410b36023c2002200241286a3602382002200241e8006a36028c01200241146a410136020020024201370204200241d0b0c2003602002002200241386a3602102002418c016a41c49ac500200210391a200235027042208620023502688410040240200228026c450d002002280268102c0b410221040b02402007450d002003102c0b4100200520044102461b2103200441017121040b2001102c200020033a0001200020043a000020024190016a24000f0b1033000bb70d04017f047e137f087e230041a0046b2205240002400240024020040d00420021064200210742002108420021090c010b200541e8016a10d004200541b0026a20052802e801220a20052802f00110d301024020052802ec01450d00200a102c0b20054198016a41086a200541b0026a41086a290300220637030020054198016a41106a200541b0026a41106a290300220737030020054198016a41186a200541b0026a41186a220b290300220837030020054198016a41206a200541b0026a41206a220c2d0000220a3a0000200520052903b002220937039801200541c0016a41206a200a3a0000200541c0016a41186a2008370300200541c0016a41106a2007370300200541c0016a41086a2006370300200520093703c001200541e8016a200541c0016a10d1044200210842002109420021064200210720052d00a8024107460d002004417f6a210d20054198036a410472210e200541b0026a41c0006a210f420021064200210742002108420021090340200b2007370300200520063703c002200520083703b002200520093703b802200c200541e8016a41c10010db05211002400240200f2002460d00200f2002412010dd050d010b200e2010290200370200200e41086a201041086a2211290200370200200e41106a201041106a2212290200370200200e41186a201041186a2213290200370200200520013602980320054180046a41086a220a41bad6c500ad42808080809001841002220441086a29000037030020052004290000370380042004102c200541c0036a41086a2214200a29030037030020052005290380043703c003200a41fbb4c400ad4280808080e000841002220441086a29000037030020052004290000370380042004102c200541d0036a41086a2215200a29030037030020052005290380043703d0034104102a2204450d0320054284808080c0003702840420052004360280042004200528029803360000200e20054180046a109101200528028404211620054180046a41186a22172005350288044220862005280280042218ad841006220441186a29000037030020054180046a41106a2219200441106a290000370300200a200441086a29000037030020052004290000370380042004102c200541e0036a41186a221a2017290300370300200541e0036a41106a221b2019290300370300200541e0036a41086a221c200a29030037030020052005290380043703e00302402016450d002018102c0b41c000102a2204450d03200420052903c003370000200420052903d003370010200420052903e003370020200441086a2014290300370000200441186a2015290300370000200441286a201c290300370000200441306a201b290300370000200441386a201a29030037000020054190016a200441c00041014100410010970120052802900121142004102c20144101460d0020052d00900321042017201329000037030020192012290000370300200a2011290000370300200520102900003703800420054180016a20054180046a10b10120054180016a41086a290300211d200529038001211e02400240200420032004200341ff0171491b220441ff01710d002005201e201d420a420010e10520054198036a41186a201729030037030020054198036a41106a201929030037030020054198036a41086a200a290300370300200520052903800437039803200541106a200120054198036a4100200d10cf04200541106a41186a290300211f200541106a41086a2903002120200529032021212005290310212220052903002223211e200541086a2903002224211d0c010b200541c0006a201d42002004ad42ff01832223420010e005200541d0006a201e42002023420010e00520054198036a41186a201729030037030020054198036a41106a201929030037030020054198036a41086a200a290300370300200520052903800437039803200541e0006a200120054198036a2004200d10cf04200541306a42004200201e420010e005427f200541d0006a41086a2903002223200529034020052903307c7c221f2005290348200529033884420052201f2023547222041b2124427f200529035020041b2123200541e0006a41186a290300211f200541e0006a41086a290300212020052903702121200529036021220b201d20077c201e20067c2207201e54ad7c201f7c200720217c2206200754ad7c2107202420097c202320087c2209202354ad7c20207c200920227c2208200954ad7c21090b200541e8016a200541c0016a10d10420052d00a8024107470d000b0b2000200637031020002008370300200041186a200737030020002009370308200541a0046a24000f0b1033000bb30303047f017e017f230041d0006b22012400200141c0006a41086a220241bad6c500ad42808080809001841002220341086a290000370300200120032900003703402003102c200141206a41086a2204200229030037030020012001290340370320200241cfb4c400ad42808080809002841002220341086a290000370300200120032900003703402003102c200141306a41086a20022903002205370300200141086a2004290300370300200141186a20053703002001200129034022053703302001200129032037030020012005370310024002404101450d004120210402400240024002404120450d004120102a22020d010c050b411021044110102a2202450d04200141106a210320022001290300370000200241086a200141086a2903003700000c010b20022001290300370000200241086a200141086a290300370000200141106a21034120210641204110470d010b20022004200441017422064120200641204b1b2206102e2202450d020b20022003290000370010200241186a200341086a290000370000200041203602082000200636020420002002360200200141d0006a24000f0b103a000b1033000b820803037f047e067f230022022103200241c0036b41607122022400200141186a22042900002105200420022903b80237000020012900102106200120022903b00237001020012900082107200120022903a802370008200241003a00a00220012900002108200120022903a002370000200220053703b801200220063703b001200220073703a801200220083703a001200141206a2d00002104200241a0026a41176a22092005370000200241a0026a41106a220a20022900b101370300200241a0026a41086a220b20022900a901370300200220022900a1013703a002024002402008a741ff01714101460d00200041073a00400c010b200241106a41176a2009290000370000200241106a41106a200a290300370300200241106a41086a200b290300370300200220022903a002370310200220043a002f20024190026a200241106a10d504200241a0026a200228029002220420022802980210e803024020022d00c1024102470d00200241003602a0032002420137039803200241306a41146a410d3602002002413c6a410b360200200241093602ac03200241bad6c5003602a8032002410b3602342002410b3602b403200241e0b4c4003602b003200220024190026a3602402002200241b0036a3602382002200241a8036a360230200220024198036a3602bc03200241d8006a41146a41033602002002420337025c200241a89cc5003602582002200241306a360268200241bc036a41c49ac500200241d8006a10391a20023502a003422086200235029803841004200041073a00400240200228029c03450d00200228029803102c0b200228029402450d01200228029002102c200324000f0b200241a0016a200241a0026a41e30010db051a0240200228029402450d002004102c0b200241306a41206a2204200241a0026a41206a2d00003a0000200241306a41186a2209200241a0026a41186a220a290300370300200241306a41106a220b200241a0026a41106a220c290300370300200241306a41086a220d200241a0026a41086a220e290300370300200220022903a002370330200241d8006a200241c1016a41c20010db051a200141206a200241d8006a41c1006a2d00003a0000200141186a20024191016a290000370000200141106a20024189016a290000370000200141086a20024181016a29000037000020012002290079370000200a200241106a41186a290300370300200c200241106a41106a290300370300200e200241106a41086a290300370300200220022903103703a002200241c8026a200d290300370300200241d0026a200b290300370300200241d8026a2009290300370300200241e0026a20042d00003a0000200220022903303703c0022000200241a0026a41c10010db051a200324000f0b200324000bd31309027f017e047f017e057f027e027f017e017f230041c0016b22012400200141a0016a41086a220241bad6c500ad428080808090018422031002220441086a290000370300200120042900003703a0012004102c200141386a41086a22052002290300370300200120012903a001370338200241ebb4c400ad42808080808002841002220441086a290000370300200120042900003703a0012004102c200141c8006a41086a22062002290300370300200120012903a001370348200120003602a001200141f8006a41186a2207200141a0016aad22084280808080c000841006220441186a290000370300200141f8006a41106a2209200441106a290000370300200141f8006a41086a220a200441086a290000370300200120042900003703782004102c200141d8006a41186a220b2007290300370300200141d8006a41106a220c2009290300370300200141d8006a41086a220d200a29030037030020012001290378370358024041c000102a2204450d00200420012903383700002004200129034837001020042001290358370020200441086a2005290300370000200441186a2006290300370000200441286a200d290300370000200441306a200c290300370000200441386a200b2903003700002004ad428080808080088410052004102c200b4200370300200c4200370300200d420037030020014200370358200220031002220441086a290000370300200120042900003703a0012004102c200d2002290300370300200120012903a001220337033820012003370358200241c3d6c500ad4280808080d00184220e1002220441086a290000370300200120042900003703a0012004102c200c20012903a0012203370300200a200d29030037030020092003370300200720022903003703002001200337034820012001290358370378200141106a200141f8006a412010940102402001280214410020012802101b22042000470d00200141d8006a41186a22074200370300200141d8006a41106a22094200370300200141d8006a41086a2202420037030020014200370358200141a0016a41086a220441bad6c500ad42808080809001841002220d41086a2900003703002001200d2900003703a001200d102c20022004290300370300200120012903a001220337033820012003370358200441abd6c500ad4280808080f001841002220d41086a2900003703002001200d2900003703a001200d102c200141c8006a41086a20042903002203370300200120012903a001220f370348200c200f370000200c41086a2003370000200141f8006a41086a2002290300370300200141f8006a41106a2009290300370300200141f8006a41186a200729030037030020012001290358370378200141086a200141f8006a412010940120012802082102200128020c210d200041016a220410d30421072004200d410020021b220d4f0d0020070d000340200441016a220410d30421022004200d4f0d012002450d000b0b200141d8006a41186a22074200370300200141d8006a41106a22094200370300200141d8006a41086a220d420037030020014200370358200141a0016a41086a220241bad6c500ad428080808090018422031002220a41086a2900003703002001200a2900003703a001200a102c200d2002290300370300200120012903a001220f3703382001200f3703582002200e1002220a41086a2900003703002001200a2900003703a001200a102c200141c8006a41086a220a2002290300220e370300200120012903a001220f370348200c200f370000200c41086a200e370000200141f8006a41086a220c200d290300370300200141f8006a41106a220b2009290300370300200141f8006a41186a2205200729030037030020012001290358370378200120043602a001200141f8006aad428080808080048420084280808080c0008422081001200220031002220441086a290000370300200120042900003703a0012004102c200141386a41086a22062002290300370300200120012903a001370338200241ccc5c400ad42808080809001841002220441086a290000370300200120042900003703a0012004102c200a2002290300370300200120012903a001370348200120003602a001200520081006220441186a290000370300200b200441106a290000370300200c200441086a290000370300200120042900003703782004102c200720052903003703002009200b290300370300200d200c2903003703002001200129037837035841c000102a2204450d00200420012903383700002004200129034837001020042001290358370020200441086a2006290300370000200441186a200a290300370000200441286a200d290300370000200441306a2009290300370000200441386a20072903003700002004ad428080808080088410052004102c200141f8006a200010cd04200128027c21102001280278211102402001280280012204450d0020044105742107200141f8006a410472210d41bad6c500ad42808080809001842112201121020340200141186a41186a200241186a2900002203370300200141186a41106a200241106a2900002208370300200141186a41086a200241086a290000220e37030020012002290000220f370318200d200f370200200d41086a200e370200200d41106a2008370200200d41186a200337020020012000360278200141a0016a41086a220420121002220c41086a2900003703002001200c2900003703a001200c102c200141386a41086a22092004290300370300200120012903a001370338200441fbb4c400ad4280808080e000841002220c41086a2900003703002001200c2900003703a001200c102c200141c8006a41086a220a2004290300370300200120012903a0013703484104102a220c450d0220014284808080c0003702a4012001200c3602a001200c2001280278360000200d200141a0016a10910120012802a401210b200141a0016a41186a220520013502a80142208620012802a0012213ad841006220c41186a290000370300200141a0016a41106a2206200c41106a2900003703002004200c41086a2900003703002001200c2900003703a001200c102c200141d8006a41186a220c2005290300370300200141d8006a41106a22052006290300370300200141d8006a41086a22062004290300370300200120012903a0013703580240200b450d002013102c0b41c000102a2204450d02200241206a2102200420012903383700002004200129034837001020042001290358370020200441086a2009290300370000200441186a200a290300370000200441286a2006290300370000200441306a2005290300370000200441386a200c2903003700002004ad428080808080088410052004102c200741606a22070d000b0b02402010450d002011102c0b200141c0016a24000f0b1033000bda0301067f230041f0006b22012400200141d0006a41086a220241bad6c500ad42808080809001841002220341086a290000370300200120032900003703502003102c200141086a41086a2204200229030037030020012001290350370308200241ebb4c400ad42808080808002841002220341086a290000370300200120032900003703502003102c200141186a41086a22052002290300370300200120012903503703182001200036024c200141d0006a41186a2200200141cc006aad4280808080c000841006220341186a290000370300200141d0006a41106a2206200341106a2900003703002002200341086a290000370300200120032900003703502003102c200141286a41186a22032000290300370300200141286a41106a22002006290300370300200141286a41086a2206200229030037030020012001290350370328024041c000102a22020d001033000b200220012903083700002002200129031837001020022001290328370020200241086a2004290300370000200241186a2005290300370000200241286a2006290300370000200241306a2000290300370000200241386a20032903003700002001200241c000410141004100109701200128020021032002102c200141f0006a240020034101460ba30a05067f057e017f017e017f230041b0036b22022400200241f8016a41086a220341bad6c500ad42808080809001841002220441086a290000370300200220042900003703f8012004102c20024188036a41086a22052003290300370300200220022903f80137038803200341c3c5c400ad42808080809001841002220441086a290000370300200220042900003703f8012004102c200241d0006a41086a22062003290300370300200220022903f801370350200241f8016a2000109f01024002400240024041c000102a2204450d00200420022903880337000020042002290350370010200420022900f801370020200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241f8016a41106a2207290000370000200441386a200241f8016a41186a2205290000370000200241f8016a200441c00010ef0302402002280288022203450d002004ad428080808080088410050b200241d0006a41086a2002419c026a2902002208370300200241d0006a41106a200241a4026a2902002209370300200241d0006a41186a200241ac026a290200220a370300200220024194026a290200220b370350200241f8016a41086a2206290300210c2005280200210d20022903f801210e200228028c02210f2005200a37030020072009370300200620083703002002200b3703f80102402003450d00200241106a41186a200241f8016a41186a290300370300200241106a41106a200241f8016a41106a290300370300200241106a41086a2006290300370300200220022903f8013703100b2004102c024020030d00200241f8016a41086a410e3a000020024181026a2000290000370000200241a4026a200136020020024189026a200041086a29000037000020024191026a200041106a29000037000020024199026a200041186a290000370000200241063a00f80141014100200241f8016a1092010c040b200241306a41186a2204200241106a41186a290300370300200241306a41106a2205200241106a41106a290300370300200241306a41086a2206200241106a41086a290300370300200220022903103703302002200d3602e401200220033602e001200241d0006a200241e0016a108f0220022802504118460d01200241306a200e200c10c201200241d0026a200c370300200241c8026a200e370300200241f8016a41086a2207410c3a0000200241a1026a2002290330370000200241a9026a2006290300370000200241b1026a2005290300370000200241b9026a200429030037000020024181026a2204200029000037000020024189026a200041086a29000037000020024191026a200041106a29000037000020024199026a200041186a290000370000200241063a00f80141014100200241f8016a109201200241f8016a200241d0006a41900110db051a200241003b018803200241e8016a200241f8016a20024188036a10c10220022d00f0012100200241f8016a410c6a2001360200200420004102463a0000200741073a0000200241063a00f80141014100200241f8016a1092010c020b1033000b2002200241306a200e200c10bf012002290300200241086a29030010b102200241f8016a41086a410d3a0000200241a4026a200136020020024181026a200029000037000020024189026a200041086a29000037000020024191026a200041106a29000037000020024199026a200041186a290000370000200241063a00f80141014100200241f8016a1092010b200f450d002003102c0b200241b0036a24000bbd0201057f230041c0006b22022400200241206a41086a220341bad6c500ad42808080809001841002220441086a290000370300200220042900003703202004102c200241086a2205200329030037030020022002290320370300200341e0b4c400ad4280808080b001841002220441086a290000370300200220042900003703202004102c200241106a41086a2206200329030037030020022002290320370310200241206a2001109f01024041c000102a22040d001033000b200420022903003700002004200229031037001020042002290020370020200042c0808080800837020420002004360200200441086a2005290300370000200441186a2006290300370000200441286a2003290000370000200441306a200241306a290000370000200441386a200241206a41186a290000370000200241c0006a24000b130020004115360204200041acc6c4003602000bca0a02087f037e230041b0016b2202240020024188016a41086a220341bad6c500ad42808080809001841002220441086a29000037030020022004290000370388012004102c200241086a41086a220520032903003703002002200229038801370308200341ebb4c400ad42808080808002841002220441086a29000037030020022004290000370388012004102c200241e0006a41086a22062003290300370300200220022903880137036020022001360250200241286a41186a2201200241d0006aad4280808080c000841006220441186a290000370300200241286a41106a2207200441106a290000370300200241286a41086a2208200441086a290000370300200220042900003703282004102c20024188016a41186a2204200129030037030020024188016a41106a22092007290300370300200320082903003703002002200229032837038801024002400240024041c000102a2201450d0020012002290308370000200120022903603700102001200229038801370020200141086a2005290300370000200141186a2006290300370000200141286a2003290300370000200141306a2009290300370000200141386a2004290300370000200241c00036024c20022001360248200241d0006a2001ad42808080808008841003108d010240200228025022050d00410321030c040b20022802542108200241d8006a28020022094104490d012005280000210741002103200241003a00a8012009417c6a21060340024020062003470d00200341ff0171450d03200241003a00a8010c030b20024188016a20036a200520036a41046a2d00003a00002002200341016a22043a00a8012004210320044120470d000b200241286a41186a20024188016a41186a290300370300200241286a41106a20024188016a41106a290300370300200241286a41086a20024188016a41086a29030037030020022002290388013703282009417c6a2004460d01200520046a220641046a2d0000220341034f0d01200920046b417b6a41034d0d01200241e0006a41086a200241286a41086a290300220a370300200241e0006a41106a200241286a41106a290300220b370300200241e0006a41186a200241286a41186a290300220c370300200241dc006a41026a220920024185016a41026a2d00003a0000200241086a41086a200a370300200241086a41106a200b370300200241086a41186a200c37030020022002290328220a370360200220022f0085013b015c2002200a370308200641056a2800002104200241286a41026a20092d00003a0000200220022f015c3b01280c020b1033000b20024100360268200242013703602002410b36022c2002200241c8006a3602282002200241e0006a3602082002419c016a41013602002002420137028c01200241d0b0c200360288012002200241286a36029801200241086a41c49ac50020024188016a10391a2002350268422086200235026084100402402002280264450d002002280260102c0b410321030b2008450d002005102c0b20024188016a41086a2205200241086a41086a29030037030020024188016a41106a2206200241086a41106a29030037030020024188016a41186a2208200241086a41186a290300370300200241e0006a41026a2209200241286a41026a2d00003a00002002200229030837038801200220022f01283b0160024020034103460d0020002004360204200020073602002000200229038801370208200020022f01603b0029200041106a2005290300370200200041186a2006290300370200200041206a20082903003702002000412b6a20092d00003a00000b200020033a00282001102c200241b0016a24000b3400200041bad6c50036020420004100360200200041146a4110360200200041106a41b0ecc400360200200041086a42093702000bf90201057f230041c0006b22022400200241206a4200370300200241186a4200370300200241086a41086a4200370300200241003a0028200242003703082002410036023820024201370330200241086a200241306a10910102400240024020022d0028220341064b0d000240024002400240024002400240024020030e0700010203040506000b410021040c060b410121040c050b410221040c040b410321040c030b410421040c020b410521040c010b410621040b200220043a003f02400240200228023420022802382203460d00200228023021050c010b200341016a22052003490d03200341017422062005200620054b1b22064100480d030240024020030d002006102a21050c010b200228023020032006102e21050b2005450d022002200636023420022005360230200228023821030b2002200341016a360238200520036a20043a00000b20002002290330370200200041086a200241306a41086a280200360200200241c0006a24000f0b1033000b1035000b3f01017f230041106b220224002002410036020820024201370300410020021067200041086a200228020836020020002002290300370200200241106a24000b6f01027f230041d0006b220224002002410036021002404101102a2203450d00200341003a0000200041086a4101360200200241013602442002200336024020002002290340370200024020022802102200450d002002280214450d002000102c0b200241d0006a24000f0b1033000b130020004107360204200041fc8ac5003602000b2e01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241809c313600000b2e01017f02404104102a22020d001033000b20004284808080c0003702042000200236020020024180a3053600000b3a01017f02404110102a22020d001033000b20024200370008200242808084fea6dee111370000200042908080808002370204200020023602000b2e01017f02404104102a22020d001033000b20004284808080c0003702042000200236020020024180de343600000bd71604097f017e017f017e230041a0016b2204240041bc99c500210502400240200110d304450d0020044180016a41086a220641bad6c500ad42808080809001841002220541086a29000037030020042005290000370380012005102c200441186a41086a20062903003703002004200429038001370318200641fbb4c400ad4280808080e000841002220541086a29000037030020042005290000370380012005102c200441e0006a41086a200629030037030020042004290380013703604104102a2205450d0120044284808080c00037028401200420053602800120052001360000200020044180016a109101200428028401210720044180016a41186a22082004350288014220862004280280012209ad841006220541186a29000037030020044180016a41106a220a200541106a2900003703002006200541086a29000037030020042005290000370380012005102c200441286a41186a2008290300370300200441286a41106a200a290300370300200441286a41086a2006290300370300200420042903800137032802402007450d002009102c0b41c000102a2206450d01200620042903183700002006200429036037001020062004290328370020200641086a200441186a41086a2207290300370000200641186a200441e0006a41086a2208290300370000200641286a200441286a41086a220a290300370000200641306a200441286a41106a2209290300370000200641386a200441286a41186a220b290300370000200441086a200641c000410141004100109701200428020821052006102c024020054101460d002004200036021420044180016a41086a220641bad6c500ad42808080809001841002220541086a29000037030020042005290000370380012005102c200720062903003703002004200429038001370318200641ccc5c400ad42808080809001841002220541086a29000037030020042005290000370380012005102c2008200629030037030020042004290380013703602004200136024820044180016a41186a220c200441c8006aad220d4280808080c000841006220541186a29000037030020044180016a41106a220e200541106a2900003703002006200541086a29000037030020042005290000370380012005102c200b200c2903003703002009200e290300370300200a2006290300370300200420042903800137032841c000102a2206450d02200620042903183700002006200429036037001020062004290328370020200641086a200441186a41086a290300370000200641186a200441e0006a41086a290300370000200641286a200441286a41086a2205290300370000200641306a200441386a290300370000200641386a200441286a41186a290300370000200441286a2006ad4280808080800884220f1003108d01024002402004280228220a450d0020052802002105200428022c21090c010b20044100360288012004420137038001410020044180016a106720042802880121052004280284012109200428028001210a0b200420053602502004200936024c2004200a360248024002400240024002402005450d0020044180016a200a2005410110db032004280280014101470d01200428024c450d042004280248102c0c040b4101200441c8006a10672004280214200441c8006a1091010c010b200428028401210b0240024002400240024002402004418c016a280200220520044188016a280200220a460d0020042802502005200a6b6a220941046a220c417f4c0d0102400240200c0d004101210e0c010b200c102a220e450d0c0b2004200c36021c2004200e360218200420093602202004200441186a36028001200b20044180016a200510c80220092005490d022004280220220b2009490d032004280250220b200a490d042004280218210c2004280248210e2004200920056b22093602582004200b200a6b220b36025c2009200b470d05200c20056a200e200a6a200910db051a2004280214200441186a1091012004280220210a200428021c210920042802182105200428024c450d072004280248102c0c070b2004200441c8006a36028001200b20044180016a200a10c8022004280214200441c8006a1091010c050b103a000b200520091047000b2009200b103f000b200a200b1047000b200441286a41146a4109360200200441346a410c360200200441e0006a41146a410336020020044203370264200441ec9fc6003602602004410c36022c2004200441d8006a3602782004200441dc006a36027c20044204370390012004420137028401200441c0a0c600360280012004200441286a360270200420044180016a3602382004200441fc006a3602302004200441f8006a360228200441e0006a41fca0c6001041000b2004280250210a200428024c2109200428024821050b2005450d00200f200aad4220862005ad84100102402009450d002005102c0b2006102c0c010b2006102c20044180016a41086a220641bad6c500ad42808080809001841002220541086a29000037030020042005290000370380012005102c200441186a41086a220a20062903003703002004200429038001370318200641ccc5c400ad42808080809001841002220541086a29000037030020042005290000370380012005102c200441e0006a41086a2209200629030037030020042004290380013703602004200136024820044180016a41186a220b200d4280808080c000841006220541186a29000037030020044180016a41106a220c200541106a2900003703002006200541086a29000037030020042005290000370380012005102c200441286a41186a2205200b290300370300200441286a41106a220b200c290300370300200441286a41086a220c2006290300370300200420042903800137032841c000102a2206450d02200620042903183700002006200429036037001020062004290328370020200641086a200a290300370000200641186a2009290300370000200641286a200c290300370000200641306a200b290300370000200641386a200529030037000020044100360288012004420137038001410120044180016a1067200428021420044180016a10910120042802840121052006ad4280808080800884200435028801422086200428028001220aad84100102402005450d00200a102c0b2006102c0b20044180016a41086a220641bad6c500ad42808080809001841002220541086a29000037030020042005290000370380012005102c200720062903003703002004200429038001370318200641fbb4c400ad4280808080e000841002220541086a29000037030020042005290000370380012005102c2008200629030037030020042004290380013703604104102a2206450d0120044284808080c00037028401200420063602800120062001360000200020044180016a109101200428028401210120044180016a41186a22052004350288014220862004280280012208ad841006220641186a29000037030020044180016a41106a2200200641106a29000037030020044180016a41086a2207200641086a29000037030020042006290000370380012006102c200441286a41186a2005290300370300200441286a41106a2000290300370300200441286a41086a2007290300370300200420042903800137032802402001450d002008102c0b41c000102a2206450d01200620042903183700002006200429036037001020062004290328370020200641086a200441186a41086a290300370000200641186a200441e0006a41086a290300370000200641286a200441286a41086a290300370000200641306a200441386a290300370000200641386a200441286a41186a2903003700004101102a2201450d0141002105200141807f410020021b2003723a00002006ad42808080808008842001ad4280808080108410012001102c2006102c0b200441a0016a240020050f0b1033000bcc0301057f230041106b2203240020034100360208200342013703002001200310670240024002402001450d002000200141286c6a21040340200028020021050240024020032802042206200328020822016b4104490d00200328020021060c010b200141046a22072001490d04200641017422012007200120074b1b22014100480d040240024020060d002001102a21060c010b200328020020062001102e21060b2006450d032003200136020420032006360200200328020821010b2003200141046a360208200620016a20053600002003200336020c200041046a22062003410c6a109402200041246a28020021050240024020032802042200200328020822016b4104490d00200328020021000c010b200141046a22072001490d04200041017422012007200120074b1b22014100480d040240024020000d002001102a21000c010b200328020020002001102e21000b2000450d032003200136020420032000360200200328020821010b2003200141046a360208200020016a2005360000200641246a22002004470d000b0b200328020421012002290200200335020842208620032802002200ad84100102402001450d002000102c0b200341106a24000f0b1033000b1035000bf70702067f027e230041e0006b22022400200241186a200041186a290000370300200241106a200041106a290000370300200241086a200041086a29000037030020022000290000370300200241c0006a41086a220341bad6c500ad42808080809001841002220041086a290000370300200220002900003703402000102c200241206a41086a2204200329030037030020022002290340370320200341c3c5c400ad42808080809001841002220041086a290000370300200220002900003703402000102c200241306a41086a2205200329030037030020022002290340370330200241c0006a2002109f0102400240024041c000102a2200450d00200020022903203700002000200229033037001020002002290040370020200041086a2004290300370000200041186a2005290300370000200041286a2003290000370000200041306a200241c0006a41106a290000370000200041386a200241c0006a41186a290000370000200141186a280200220341186a2204417f4c0d010240024020040d00410121050c010b2004102a2205450d01200128021821030b200241003602482002200436024420022005360240200128021021062003200241c0006a10670240024020022802442205200228024822046b2003490d00200228024021050c010b200420036a22072004490d03200541017422042007200420074b1b22044100480d030240024020050d002004102a21050c010b200228024020052004102e21050b2005450d012002200436024420022005360240200228024821040b2002200420036a360248200520046a2006200310db051a2001411c6a200241c0006a109101200141086a2903002108200129030021090240024020022802442205200228024822046b4110490d00200228024021030c010b200441106a22032004490d03200541017422042003200420034b1b22064100480d030240024020050d002006102a21030c010b200228024020052006102e21030b2003450d01200220063602442002200336024020022802482104200621050b200320046a22062008370008200620093700002002200441106a2204360248200128023c21060240200520046b41034b0d00200441046a22072004490d03200541017422042007200420074b1b22044100480d030240024020050d002004102a21030c010b200320052004102e21030b2003450d012002200436024420022003360240200228024821040b2002200441046a360248200320046a2006360000200228024421032000ad4280808080800884200235024842208620022802402204ad84100102402003450d002004102c0b2000102c0240200141146a280200450d002001280210102c0b200241e0006a24000f0b1033000b103a000b1035000bff0201047f230041e0006b22012400200141186a200041186a290000370300200141106a200041106a290000370300200141086a200041086a29000037030020012000290000370300200141c0006a41086a220241bad6c500ad42808080809001841002220041086a290000370300200120002900003703402000102c200141206a41086a220320022903003703002001200129034037032020024188fbc400ad4280808080d000841002220041086a290000370300200120002900003703402000102c200141306a41086a2204200229030037030020012001290340370330200141c0006a2001109f01024041c000102a22000d001033000b200020012903203700002000200129033037001020002001290040370020200041086a2003290300370000200041186a2004290300370000200041286a2002290000370000200041306a200141c0006a41106a290000370000200041386a200141c0006a41186a2900003700002000ad428080808080088410052000102c200141e0006a24000bbc0101037f02400240024002402000280200220041046a2802002203200041086a28020022046b2002490d00200028020021030c010b200420026a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102a21030c010b200028020020032004102e21030b2003450d0120002003360200200041046a2004360200200041086a28020021040b200041086a200420026a360200200320046a2001200210db051a41000f0b1033000b1035000ba70301047f230041106b22022400200028020021002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b0240024002400240200041046a2802002203200041086a28020022046b2001490d00200028020021030c010b200420016a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102a21030c010b200028020020032004102e21030b2003450d0120002003360200200041046a2004360200200041086a28020021040b200041086a200420016a360200200320046a2002410c6a200110db051a200241106a240041000f0b1033000b1035000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41c49ac500200241086a10392101200241206a240020010b130020004101360204200041c49fc5003602000b13002000410236020420004198a1c5003602000b2d01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241e8073600000b2d01017f02404104102a22020d001033000b20004284808080c00037020420002002360200200241e5003600000bfa0304027f027e017f027e230041e0006b22042400200441086a200128021029034842002003ad420010e00520012802182205420020052903082206427f200429030820042903104200521b7d2207200720065622051b37030802400240024020050d002003417f4c0d0102400240024020030d004101210802402001280214280208200241014100101e41026a220141024b0d0020010e03040002040b41ac91c600412841d491c6001036000b0240200310302208450d0002402001280214280208200220082003101e41026a220141024b0d0020010e03030002030b41ac91c600412841d491c6001036000b1033000b41002101200441003a005802400240034020032001460d01200441386a20016a200820016a2d00003a00002004200141016a22053a00582005210120054120470d000b200441186a41186a200441386a41186a2903002206370300200441186a41106a200441386a41106a2903002207370300200441186a41086a200441386a41086a290300220937030020042004290338220a370318200041196a2006370000200041116a2007370000200041096a20093700002000200a370001410021010c010b0240200141ff0171450d00200441003a00580b410121010b200020013a00002003450d032008102c0c030b2008102c0b200041013a00000c010b103a000b200441e0006a24000bfa0304027f027e017f027e230041e0006b22042400200441086a200128021029034842002003ad420010e00520012802182205420020052903082206427f200429030820042903104200521b7d2207200720065622051b37030802400240024020050d002003417f4c0d0102400240024020030d004101210802402001280214280208200241014100101e41026a220141024b0d0020010e03040002040b41ac91c600412841d491c6001036000b0240200310302208450d0002402001280214280208200220082003101e41026a220141024b0d0020010e03030002030b41ac91c600412841d491c6001036000b1033000b41002101200441003a005802400240034020032001460d01200441386a20016a200820016a2d00003a00002004200141016a22053a00582005210120054120470d000b200441186a41186a200441386a41186a2903002206370300200441186a41106a200441386a41106a2903002207370300200441186a41086a200441386a41086a290300220937030020042004290338220a370318200041196a2006370000200041116a2007370000200041096a20093700002000200a370001410021010c010b0240200141ff0171450d00200441003a00580b410121010b200020013a00002003450d032008102c0c030b2008102c0b200041013a00000c010b103a000b200441e0006a24000bd40202027f037e230041106b220424002004200128021029034842002003ad420010e00520012802182205420020052903082206427f200429030020042903084200521b7d2207200720065622051b37030842012106024002400240024020050d002003417f4c0d02024020030d0002402001280214280208200241014100101e41026a220341024b0d00420021074200210820030e03050005050b41ac91c600412841d491c6001036000b02400240200310302205450d0002402001280214280208200220052003101e41026a220141024b0d0020010e03020004020b41ac91c600412841d491c6001036000b1033000b2005102c0b0c020b0240200341104f0d004200210742012106420021082005102c0c020b200541086a290000210820052900002107420021062005102c0c010b103a000b2000200737030820002006370300200041106a2008370300200441106a24000b130020004103360204200041acafc5003602000b3400200041afb7c50036020420004100360200200041146a4101360200200041106a41b4b7c500360200200041086a42043702000b990101017f02404101102a2202450d00200241003a0000200241014102102e2202450d00200241003a0001200241024104102e2202450d00200241003b0002200241044108102e2202450d0020024100360004200241084110102e2202450d0020024200370008200241104120102e2202450d002002420037001820024200370010200042a08080808004370204200020023602000f0b1033000bd30101017f230041106b22022400024002400240024020002d00000e03010200010b200220012802184183f8c500410b2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b20022001280218418ef8c500410c2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b20022001280218419af8c500410d2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000be8cf0106067f017e057f017e117f027e2300419081046b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280204220320012802082204460d00200441016a22052004490d02200320054f0d0120052003103f000b200241013a0030200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103720022802f88004210420022802fc8004210120004101360200200041003a00042001450d2a2004102c0c2a0b200128020020046a2d00002104200120053602082004410c4b0d0302400240024020040e0d0001151413121110050c0b0a04000b200241e8006a200110920541012106200228026c2107024020022802684101470d0020074108762101200241f8006a2802002104200241e8006a41086a29030021080c250b41002109200241e8006a41004180800110da051a410021034100210a2007450d1f410021054100210a410121064100210b0340024002402001280204220c200128020822036b2007200b6b220441808001200441808001491b2204490d00200320046a220d2003490d04200c200d4f0d01200d200c103f000b200241013a00e880042002418c81046a4101360200200242013702fc8004200241f0f7c5003602f880042002412b36021c2002200241186a36028881042002200241e880046a360218200241306a200241f880046a10372002290330210820022802382104410521070240200a450d002006102c0b0c260b200241e8006a200128020020036a200410db051a2001200d36020802400240200a20056b2004490d00200520046a21030c010b200520046a22032005490d22200a410174220d2003200d20034b1b220d4100480d2202400240200a0d00200d102a21060c010b2006200a200d102e21060b2006450d2a200d210a0b200620056a200241e8006a200410db051a2003210520072004200b6a220b4b0d000c200b0b200241e8006a2001109905024020022802684101470d00200228026c22044108762105200241e8006a41086a2903002208422088210e200241f8006a28020021030c1e0b200241fc006a280200210f200241f8006a2802002101200241f4006a2802002103200241f0006a2802002110200228026c210b4100210441002109024002400240034002402004411f4d0d00410f21040c020b0240024020032001460d002001417f460d052003200141016a22054f0d01200141016a2003103f000b200241013a0030200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241c8006a200241e8006a1037410521040c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b20044120490d01410d210420064110490d010b200241f880046a41086a200241c8006a41086a28020022033602002002200229034822083703f880042008422088a721092008a721060c1e0b20024100360260200242043703580240024020090d00410421010c010b410020036b2111200b41026a2112410120036b21134100210a410421014100211441002115410021160340201621170240024002400240024002400240024020032005460d00200541016a22042005490d0120032004490d060240200b20056a2d0000220441e000460d00411821050c260b201741016a211641022118200541026a210441002106410321192012211a4100211b024002400340201a21072019210c2018210d02402006411f4d0d00410f21050c020b02400240201320046a4102460d002004450d07200320044f0d0120042003103f000b200241013a00302002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1037200241206a41086a200241f880046a41086a280200360200200220022903f88004370320410521050c020b200b20046a417f6a2d0000221c41ff00712006411f7174201b72211b200d41016a2118200c41016a2119200741016a211a200441016a2104200641076a2106201c418001710d000b20064120490d01201c4110490d01410d21050b200241e880046a41086a200241206a41086a28020022033602002002200229032022083703e880042008a721064100210420022802ec800421090c250b41002119200241003602382002420137033002400240201b0d002004417f6a21064101211c4100211a4100211d0c010b201120056a211e410021184101211c4100211a034002400240201e200d6a450d002005200c6a2204450d07200320044f0d0120042003103f000b200220183602342002201a3602382002201c360230200241013a00e880042002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103720022802f88004210620022802fc80042109200228028081042103410521050c260b200720056a2c000022044100480d0602400240200441c00071450d00200441807f72220441ff017141fb014b0d010b200220183602342002201a3602382002201c360230410621050c250b02400240201a2018460d002018211d201a21180c010b201841016a22062018490d2d2018410174221d2006201d20064b1b221d4100480d2d0240024020180d00201d102a211c0c010b201c2018201d102e211c0b201c450d350b201c20186a2004417f733a0000200d41016a210d200c41016a210c200741016a2107201d2118201b201a41016a221a470d000b2002201d3602342002201a3602382002201c3602302005200d6a21060b201c411076411074221b201c41087641ff0171410874221872201c41ff0171221c72210c4100210d03404100210402402019411f4d0d00410f21050c230b0240024020032006460d002006417f460d082003200641016a22054f0d01200641016a2003103f000b200241013a00302002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103720022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050c230b200b20066a2d0000220741ff00712019411f7174200d72210d201941076a2119200521062007418001710d000b20194120490d072007410f4d0d07410d21050c210b200241013a00302002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103720022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050c240b417f20041047000b417f20041047000b417f20041047000b200220183602342002201a3602382002201c360230411921050c1d0b417f200641016a1047000b20042003103f000b0240200d41014d0d004104210541f2cdc5002106412421090c190b024002400240200d0e020001000b410421060c010b20032005460d18024002400240200541016a220d2005490d002003200d490d010240200b20056a2c0000220441004e0d00411921050c1e0b41062105200441c00071450d02200441807f72220441ff017141fb014d0d022004417f732106200d21050c030b417f200541016a1047000b200541016a2003103f000b0c1a0b024020172015470d00024020142015460d00201421150c010b201441016a22042014490d232014410174220d2004200d20044b1b221541ffffffff00712015470d23201541047422044100480d230240024020140d002004102a21010c010b200120144104742004102e21010b2001450d2b2002201536025c20022001360258201521140b200120174104746a2204201f4180807c71200641ff01714108747241e00072221f36020c2004201a3602082004201d36020420042018201c72201b72360200200a41106a210a2002201636026020162009470d000b0b2005200f462104200229025c2208422088210e02402010450d00200b102c0b200ea721052008a721092004450d1c2005ad4220862009ad842108410221030c270b417f200141016a1047000b2003200d1047000b417f20051047000b200241e8006a2001109905024020022802684101470d00200041013602002000200241e8006a41047222012902003702042000410c6a200141086a2902003702000c280b200241fc006a280200210d200241f8006a2802002104200241f4006a2802002105200241f0006a280200210a200228026c210b410021034100210102400240034002402003411f4d0d00410f21040c080b20052004460d062004417f460d012005200441016a2206490d02200b20046a2d0000220941ff00712003411f71742001722101200341076a2103200621042009418001710d000b20034120490d04410d21042009410f4b0d060c040b417f200441016a1047000b200441016a2005103f000b200241e8006a2001109905024020022802684101470d00200041013602002000200241e8006a41047222012902003702042000410c6a200141086a2902003702000c270b200241fc006a280200210d200241f8006a2802002104200241f4006a2802002105200241f0006a280200210a200228026c210b410021034100210102400240034002402003411f4d0d00410f21040c0d0b20052004460d0b2004417f460d012005200441016a2206490d02200b20046a2d0000220941ff00712003411f71742001722101200341076a2103200621042009418001710d000b20034120490d09410d21042009410f4b0d0b0c090b417f200441016a1047000b200441016a2005103f000b200041123a000420004101360200200041056a20043a00000c250b200d20064621040240200a450d00200b102c0b02402004450d00410b21030c210b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a10372002418381046a200241386a280200360000200220022903303700fb8004200041053a0004200020022900f880043700052000410c6a200241ff80046a290000370000200041013602000c240b200241013a0030200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1037410521040b2000200436020420004101360200200041086a20022903f88004370200200041106a200241f880046a41086a280200360200200a450d22200b102c0c220b200241e8006a20011099050240024020022802684101470d00200228026c22014108762106200241e8006a41086a2903002208422088210e200241f8006a280200210b0c010b200241c0006a200241fc006a280200360200200241386a200241f4006a2902003703002002200229026c37033041002101410021050240024002400240024002400240034002402001411f4d0d00410f210d0c020b0240024020022802382209200228023c2204460d00200441016a22032004490d05200920034f0d0120032009103f000b200241013a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241c8006a200241e8006a10374105210d0c020b200228023020046a2d000021042002200336023c200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210d20044110490d010b200241f880046a41086a200241c8006a41086a280200220b3602002002200229034822083703f880042008422088a721072008a7210c410021060c040b20024100360250200242043703480240024020050d00410421010c010b4100210d0340200d41016a210d41002101410021090240024002400240024002400240034002402001411f4d0d00410f210d0c030b20022802382206200228023c2204460d01200441016a22032004490d0420062003490d06200228023020046a2d000021042002200336023c200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d022004410f4d0d02410d210d0c010b200241013a00582002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241f880046a200241e8006a1037200241e880046a41086a200241f880046a41086a280200360200200220022903f8800422083703e880042008a7210c4105210d0b20022802f08004210b20022802ec80042107410021060c090b200241e8006a200241306a108a05024020022802684101470d00200228026c220d41087621062002280278210b200228027421072002280270210c0c090b200228027421192002280270211c200228026c211a410021044100210b02400240034002402004411f4d0d00410f210d0c020b0240024020022802382206200228023c2203460d00200341016a22012003490d06200620014f0d0120012006103f000b200241013a00e880042002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a1037200241206a41086a200241f880046a41086a280200360200200220022903f8800422083703202008a7210c4105210d0c030b2002280230220a20036a2d000021032002200136023c200341ff00712004411f7174200b72210b200441076a21042003418001710d000b20044120490d0520034110490d05410d210d0b0b2002280228210b200228022421070c070b417f20031047000b417f20011047000b20032006103f000b4100211b200241e8006a41004180800410da051a02400240200b0d00410121184100210c0c010b4100211b4101211841002103410021070240034002400240200620016b200b20076b220441808004200441808004491b2204490d00200120046a220c2001490d032006200c4f0d01200c2006103f000b200241013a00202002410136028c8104200242013702fc8004200241f0f7c5003602f880042002412b36021c2002200241186a36028881042002200241206a360218200241e880046a200241f880046a103720022802e88004210c20022802ec8004210720022802f08004210b4105210d201b450d072018102c0c070b200241e8006a200a20016a200410db051a2002200c36023c02400240201b20036b2004490d00200320046a210c0c010b200320046a220c2003490d22201b4101742201200c2001200c4b1b22014100480d2202400240201b0d002001102a21180c010b2018201b2001102e21180b2018450d2a2001211b0b201820036a200241e8006a200410db051a200b200420076a22074d0d02200228023c2101200228023821062002280230210a200c21030c000b0b2001200c1047000b024020022802502203200228024c470d00200341016a22012003490d1f200341017422042001200420014b1b2204ad421c7e2208422088a70d1f2008a722014100480d1f0240024020030d002001102a21010c010b20022802482003411c6c2001102e21010b2001450d272002200436024c200220013602480b200228024822012003411c6c6a2204200941087622063b0001200420183602102004201a360204200420093a0000200441036a20064110763a0000200441186a200c360200200441146a201b3602002004410c6a2019360200200441086a201c3602002002200341016a360250200d2005470d000b0b200228023c2002280240462104200229024c2208422088210e02402002280234450d002002280230102c0b20014108762105200ea721032008a7210a2004450d042005410874200141ff01717221012003ad422086200aad842108410d21030c230b417f20031047000b02402019450d0020194104742104201a21010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102c200528020021030b2003102c0b200141106a2101200441706a22040d000b0b41002106201c450d00201a102c0b2002280248211b024020022802502201450d00201b2001411c6c6a210a201b21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102c200528020021030b2003102c0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102c0b2009411c6a21010240200941146a280200450d002009280210102c0b200121092001200a470d000b0b200228024c450d00201b102c0b2006410874200d41ff01717221012007ad220e422086200cad8421082002280234450d012002280230102c0c010b2005410874200141ff017172210d20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103720022903f88004210820022802808104210b02402003450d00200d2003411c6c6a2106200d21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102c200528020021030b2003102c0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102c0b2009411c6a21010240200941146a280200450d002009280210102c0b2001210920012006470d000b0b2008422088210e4105210141002106200a450d00200d102c0b20004101360200200041106a200b360200200041086a200e422086200842ffffffff0f838437020020002006410874200141ff0171723602040c210b200241e8006a20011099050240024020022802684101470d00200228026c220a4108762104200241e8006a41086a2903002208422088210e200241f8006a280200210d0c010b200241fc006a280200211b200241f8006a2802002101200241f4006a2802002105200241f0006a2802002107200228026c210b410021044100210902400240024002400240024002400240024002400240034002402004411f4d0d00410f210a0c020b0240024020052001460d002001417f460d052005200141016a22034f0d01200141016a2005103f000b200241013a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a10374105210a0c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200321012006418001710d000b20044120490d01410d210a20064110490d010b200241306a41086a200241f880046a41086a280200220d360200200220022903f8800422083703302008422088a7210c2008a7211b0c080b20024100360260200242043703580240024020090d00410421010c010b200241f1006a21104100211c0340201c41016a211c4100210141002106024002400240024002400240024002400240024002400240034002402001411f4d0d00410f210a0c020b0240024020052003460d002003417f460d062005200341016a22044f0d01200341016a2005103f000b200241013a00f880042002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241f880046a360218200241c8006a200241e8006a10374105210a2002280248211b0c030b200b20036a2d0000220a41ff00712001411f71742006722106200141076a210120042103200a418001710d000b20014120490d02200a4110490d02410d210a0b0b2002280250210d200228024c210c0c120b4100210c200241e8006a41004180800110da051a410121180240024020060d00200421034100211a4100210a0c010b4100210d4100211a41002119034002400240200520046b200620196b220141808001200141808001491b2201490d00200420016a22032004490d05200520034f0d0120032005103f000b200241013a00482002410136028c8104200242013702fc8004200241f0f7c5003602f880042002412b36021c2002200241186a36028881042002200241c8006a360218200241e880046a200241f880046a103720022802e88004211b20022802ec8004210c20022802f08004210d4105210a201a450d142018102c0c140b200241e8006a200b20046a200110db051a02400240201a200d6b2001490d00200d20016a210a0c010b200d20016a220a200d490d2d201a4101742204200a2004200a4b1b22044100480d2d02400240201a0d002004102a21180c010b2018201a2004102e21180b2018450d352004211a0b2018200d6a200241e8006a200110db051a20032104200a210d2006200120196a22194b0d000b0b2002200a3602402002410036023c2002200a3602382002201aad4220862018ad84370330410021014100210d02400240034002402001411f4d0d00410f210a0c020b02400240200a200c460d00200c417f460d07200a200c41016a22064f0d01200c41016a200a103f000b200241013a00482002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241f880046a200241e8006a1037200241206a41086a200241f880046a41086a280200360200200220022903f880043703204105210a0c020b2018200c6a2d000021042002200636023c200441ff00712001411f7174200d72210d200141076a21012006210c2004418001710d000b20014120490d0120044110490d01410d210a0b200241e880046a41086a200241206a41086a280200220d3602002002200229032022083703e880042008a7211b20022802ec8004210c0c110b4100210c200241003602f08004200242043703e8800402400240200d0d0041042116410021174100210f0c010b41002117410421164100210f03402017211d200f221441016a210f4100210141002118024002400240034002402001411f4d0d00410f21040c020b0240024020022802382219200228023c2204460d00200441016a22062004490d0b201920064f0d0120062019103f000b200241013a00f880042002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241f880046a360218200241c8006a200241e8006a1037410521042002280248211b0c030b2002280230221a20046a2d0000210a2002200636023c200a41ff00712001411f71742018722118200141076a2101200a418001710d000b20014120490d02200a4110490d02410d21040b0b2002280250210d200228024c210c410021010c0a0b02400240024020192006460d00200441026a21042006417f460d0920192004490d0a201a20066a2c000021012002200436023c0240200141004e0d00411921040c0d0b41062104200141c00071450d0b200141807f72220141ff017141fb014d0d0b2014201d460d01201d21172014211d0c020b200241013a00482002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241f880046a200241e8006a103720022802f88004211b20022802fc8004210c20022802808104210d410521040c0b0b201d41016a2204201d490d2d201d41017422062004200620044b1b221741ffffffff01712017470d2d201741037422044100480d2d02400240201d0d002004102a21160c010b2016201d4103742004102e21160b2016450d35200220163602e880040b2016201d4103746a2204201341807e712001417f7341ff01717222133a000420042018360200200f200d470d000b200220173602ec80042002200f3602f080040b2016200f4103746a210a201621010340200a2001460d09200c20012802006a2204200c492106200141086a21012004210c20060d0e0c000b0b417f200341016a1047000b200420031047000b417f200c41016a1047000b417f20061047000b417f20041047000b20042019103f000b0b2002201d3602ec8004200220143602f08004200141ff0171410874200472210a201d0d070c080b4101210a4100210441082119410021060340200241e8006a200241306a108b05024020022802684101470d002002280278210d2002280274210c2002280270211b200228026c210a0c050b200241f880046a41026a2201201041026a2d00003a0000200220102f00003b01f880042002280274211a200229037821080240024002400240024020022d0070220d4106470d00200a417f6a210a0c010b200d417e6a41034f0d00200a41016a220c200a4f2118200c210a20180d004115210c419ec7c500211b4104210a200d4109460d010c080b200241e8006a41026a220c20012d00003a0000200220022f01f880043b016820062004460d01200421180c020b0240201a28020441ffffffff0371450d00201a280200102c0b201a102c0c060b200441016a22012004490d23200441017422062001200620014b1b221841ffffffff00712018470d23201841047422014100480d230240024020040d002001102a21190c010b201920044104742001102e21190b2019450d2b20042106201821040b201920064104746a2201200d3a0000200120083703082001201a360204200120022f01683b0001200141036a200c2d00003a0000200641016a2106200a0d000b200228023c200228024046210102402002280234450d002002280230102c0b0240024002402001450d002002280260220a200228025c470d02200a41016a2201200a490d24200a41017422042001200420014b1b2204ad42187e2208422088a70d242008a7220141004e0d010c240b20024103410220011b3a00e880042002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103720022802f88004211b20022802fc8004210c20022802808104210d02402006450d0020064104742104201921010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102c200528020021030b2003102c0b200141106a2101200441706a22040d000b0b02402018450d002019102c0b4105210a2017450d0a2016102c0c0a0b02400240200a0d002001102a21010c010b2002280258200a41186c2001102e21010b2001450d2a2002200436025c200220013602580b20022802582201200a41186c6a2204201936020c2004200f3602082004201736020420042016360200200441146a2006360200200441106a20183602002002200a41016a360260201c2009470d000b0b2003201b462104200229025c2208422088210e02402007450d00200b102c0b200ea721032008a721072004450d082003ad4220862007ad842108410c21030c260b417f200141016a1047000b02402006450d0020064104742103201921010340024020012d00004109470d000240200141046a2209280200220528020441ffffffff0371450d002005280200102c200928020021050b2005102c0b200141106a2101200341706a22030d000b0b2004450d012019102c0c010b20022802808104210d20022802fc8004210c411c210a0b2017450d010b2016102c0b2002280234450d002002280230102c0b20022802582118024020022802602201450d002018200141186c6a21062018210903400240200941046a280200450d002009280200102c0b0240200941146a2802002204450d00200928020c2101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102c200528020021030b2003102c0b200141106a2101200441706a22040d000b0b200941186a21010240200941106a280200450d00200928020c102c0b2001210920012006470d000b0b200228025c450d002018102c0b200a4108762104200cad220e422086201bad8421082007450d01200b102c0c010b20024103410220041b3a0030200241e8006a41146a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103720022903f88004210820022802808104210d02402003450d002001200341186c6a210b2001210603400240200641046a280200450d002006280200102c0b0240200641146a2802002203450d00200628020c2104200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102c200928020021050b2005102c0b200441106a2104200341706a22030d000b0b200641186a21040240200641106a280200450d00200628020c102c0b200421062004200b470d000b0b2008422088210e4105210a410021042007450d002001102c0b20004101360200200041106a200d360200200041086a200e422086200842ffffffff0f838437020020002004410874200a41ff0171723602040c200b200241e8006a20011099050240024020022802684101470d00200228026c22044108762106200241e8006a41086a2903002208422088210e200241f8006a280200210b0c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f8800441002101410021050240024002400240024002400240034002402001411f4d0d00410f210d0c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103f000b200241013a0058200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200241e880046a41086a200241306a41086a280200360200200220022903303703e880044105210d0c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210d20044110490d010b200241c8006a41086a200241e880046a41086a280200220b360200200220022903e8800422083703482008422088a721072008a7210c410021060c040b200241003602f08004200242043703e880040240024020050d00410421010c010b4100210b0340200b41016a210b410021014100210902400240024002400240034002402001411f4d0d00410f210d0c030b200228028081042206200228028481042204460d01200441016a22032004490d0920062003490d0a20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d022004410f4d0d02410d210d0c010b200241013a00582002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200241206a41086a200241306a41086a2802003602002002200229033022083703202008a7210c4105210d0b2002280228210b20022802242107410021060c010b200241e8006a200241f880046a108a05024020022802684101470d00200228026c220d41087621062002280278210b200228027421072002280270210c0c010b2002280274211b20022802702119200228026c2118200241e8006a200241f880046a108c0520022802684101470d01200228026c210d2002280278210b200228027421072002280270210c0240201b450d00201b4104742104201821010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102c200528020021030b2003102c0b200141106a2101200441706a22040d000b0b200d41087621062019450d002018102c0b20022802e88004211b024020022802f080042201450d00201b2001411c6c6a210a201b21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102c200528020021030b2003102c0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102c0b2009411c6a21010240200941146a280200450d002009280210102c0b200121092001200a470d000b0b20022802ec8004450d06201b102c0c060b4100210a2002280270210c200228026c2107024002402002280274220141027422030d004104210d410021060c010b2003410275220641ffffffff03712006470d1d200641027422044100480d1d2004102a220d450d250b02402001450d002003417c6a210a200d210120072104034020012004280200360200200141046a2101200441046a21042003417c6a22030d000b200a41027641016a210a0b0240200c450d002007102c0b024020022802f08004220320022802ec8004470d00200341016a22012003490d1d200341017422042001200420014b1b2204ad421c7e2208422088a70d1d2008a722014100480d1d0240024020030d002001102a21010c010b20022802e880042003411c6c2001102e21010b2001450d25200220043602ec8004200220013602e880040b20022802e8800422012003411c6c6a2204200941087622073b00012004200d36021020042018360204200420093a0000200441036a20074110763a0000200441186a200a360200200441146a20063602002004410c6a201b360200200441086a20193602002002200341016a3602f08004200b2005470d000b0b200228028481042002280288810446210420022902ec80042208422088210e024020022802fc8004450d0020022802f88004102c0b200ea721032008a7210d2004450d042003ad422086200dad842108410a21030c210b417f20031047000b417f20031047000b20032006103f000b2006410874200d41ff01717221042007ad220e422086200cad84210820022802fc8004450d0120022802f88004102c0c010b20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1037200229033021082002280238210b02402003450d0020012003411c6c6a210a200121060340024020062802042204450d0002402006410c6a2802002203450d00200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102c200928020021050b2005102c0b200441106a2104200341706a22030d000b0b200641086a280200450d002006280204102c0b2006411c6a21040240200641146a280200450d002006280210102c0b200421062004200a470d000b0b2008422088210e4105210441002106200d450d002001102c0b20004101360200200041106a200b360200200041086a200e422086200842ffffffff0f838437020020002006410874200441ff0171723602040c1f0b200d20064621040240200a450d00200b102c0b02402004450d00410921030c1b0b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a10372002418381046a200241386a280200360000200220022903303700fb8004200041053a0004200020022900f880043700052000410c6a200241ff80046a290000370000200041013602000c1e0b200241013a0030200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1037410521040b2000200436020420004101360200200041086a20022903f88004370200200041106a200241f880046a41086a280200360200200a450d1c200b102c0c1c0b200241e8006a20011099050240024020022802684101470d00200228026c22034108762104200241e8006a41086a2903002208422088210e200241f8006a28020021090c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f88004410021014100210502400240024002400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f21030c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103f000b200241013a0058200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200241206a41086a200241306a41086a28020036020020022002290330370320410521030c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210320044110490d010b200241e880046a41086a200241206a41086a28020022093602002002200229032022083703e880042008422088a721062008a7210b0c0f0b20024100360260200242043703584104210102402005450d004100211b4100210c4100211a0340200241e8006a200241f880046a108e05024020022802684101470d002002200229027422083703e880042002280270210b200228026c21032008a721060c0f0b20022802702118200228026c211902400240200228028081042203200228028481042209460d00200941016a22042009490d05200320044f0d0120042003103f000b200241013a00482002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10370c0c0b2002280274211c20022802f88004220620096a2d000021072002200436028481040240200741034d0d00410a21040c0e0b0240024002400240024020070e0400010203000b410021074100210b4100210903400240200b411f4d0d00410f21040c130b20032004460d112004417f460d092003200441016a220d490d0d200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41002107200b4120490d03200a410f4d0d03410d21040c110b4100210b410021090340200b411f4b0d0e0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103f000b200241013a00482002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10370c100b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41012107200b4120490d02200a410f4d0d020c0c0b4100210b410021090340200b411f4b0d0d0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103f000b200241013a00482002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10370c0f0b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41022107200b4120490d01200a410f4b0d0b0c010b4100210b410021090340200b411f4b0d0c0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103f000b200241013a00482002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10370c0e0b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41032107200b4120490d00200a410f4b0d0a0b200220093602f08004200220073602ec800420022902ec8004210802400240200c201b460d00201b21030c010b201b41016a2204201b490d23201b41017422032004200320044b1b2203ad42147e220e422088a70d23200ea722044100480d2302400240201b0d002004102a21010c010b2001201b41146c2004102e21010b2001450d2b20022001360258201b210c2003211b0b2001200c41146c6a2204200837020c2004201c3602082004201836020420042019360200200c41016a210c201a41016a221a2005470d000b2002200336025c2002200c3602600b2002280284810420022802888104462104200229025c2208422088210e024020022802fc8004450d0020022802f88004102c0b200ea721032008a721052004450d0d2003ad4220862005ad842108410821030c270b417f20031047000b417f20041047000b417f200441016a1047000b417f200441016a1047000b417f200441016a1047000b417f200441016a1047000b200441016a2003103f000b410d2104410021070c030b410f2104410021070c020b2002280230210b2002290234210841052104410021070c010b200241013a00482002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10372002280230210b20022902342108410521040b20074108742004722103200220083703e880042008a721062018450d002019102c0b2002200c3602602002201b36025c20022802ec800421090240200c450d00200c41146c21052001210403400240200441046a280200450d002004280200102c0b200441146a21042005416c6a22050d000b0b201b450d012001102c0c010b20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1037200229033021082002280238210902402003450d00200341146c21032001210403400240200441046a280200450d002004280200102c0b200441146a21042003416c6a22030d000b0b2008422088210e41052103410021042005450d012001102c0c010b200341087621042006ad220e422086200bad84210820022802fc8004450d0020022802f88004102c0b20004101360200200041106a2009360200200041086a200e422086200842ffffffff0f838437020020002004410874200341ff0171723602040c1b0b200241e8006a20011099050240024020022802684101470d00200228026c220b4108762104200241e8006a41086a2903002208422088210e200241f8006a28020021060c010b200241c0006a200241fc006a280200360200200241386a200241f4006a2902003703002002200229026c3703304100210141002109024002400240024002400240024002400240024002400240034002402001411f4d0d00410f210b0c020b0240024020022802382205200228023c2204460d00200441016a22032004490d05200520034f0d0120032005103f000b200241013a0058200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241f880046a200241e8006a1037200241206a41086a200241f880046a41086a280200360200200220022903f880043703204105210b0c020b2002280230220620046a2d000021042002200336023c200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d01410d210b20044110490d010b200241e880046a41086a200241206a41086a28020022063602002002200229032022083703e880042008422088a721072008a7210d0c0a0b20024100360260200242043703580240024020090d00410421010c010b2009417f6a211b4104210141042110410421094104211c4104211a4100210a4100210c03400240024020052003460d00200341016a220b2003490d052005200b4f0d01200b2005103f000b2002200a36025c2002200c360260200241013a0048200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241e880046a200241e8006a103720022802e88004210d20022802ec8004210720022802f080042106410521010c080b200620036a2c000021042002200b36023c20044100480d0402400240200441c00071450d00200441807f72220441ff017141fb014b0d010b2002200a36025c2002200c360260410621010c070b024002400240024002402005200b460d00200341026a210d200b417f460d0a2005200d4f0d01200d2005103f000b2002200a36025c2002200c360260200241013a0048200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241c8006a360218200241e880046a200241e8006a103720022802e88004210d20022802ec8004210720022802f080042106410521010c010b2006200b6a2d000021032002200d36023c0240200341014b0d004100210520030e020302030b2002200a36025c2002200c360260410c21010b2002418881046a20063602002002418481046a20073602002002418081046a200d360200200220033a00fd8004200220013a00fc80040c0a0b41800221050b200241e8006a200241306a108a05200228027421072002280270210d200228026c210b024020022802684101470d002002200a36025c2002200c360260200241f8006a28020021060c0a0b02400240200c200a460d00200a2118200c210a0c010b200a41016a2201200a490d1d200a41017422032001200320014b1b221841ffffffff00712018470d1d201841047422014100480d1d02400240200a0d002001102a21010c010b201c200a4104742001102e21010b2001450d252002200136025820012110200121092001211c2001211a0b201a200a4104746a220320194180807c712004417f7341ff017172200572221936020c200320073602082003200d3602042003200b360200200a41016a210c0240201b450d00201b417f6a211b200228023c210320022802382105200228023021062018210a0c010b0b2002201836025c2002200c3602600b200228023c2002280240462104200229025c2208422088210e02402002280234450d002002280230102c0b200ea721032008a7210d2004450d082003ad422086200dad842108410721030c210b417f20031047000b417f200b1047000b2002200a36025c2002200c360260411921010c010b417f200d1047000b0b2002418881046a20063602002002418481046a20073602002002418081046a200d360200200220043a00fd8004200220013a00fc80040b200241013a00f8800420022802fc8004210b0b0240200c450d002009200c4104746a210c0340024020092802082204450d0020092802002101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102c200528020021030b2003102c0b200141106a2101200441706a22040d000b0b200941106a21010240200941046a280200450d002009280200102c0b200121092001200c470d000b0b200a450d012010102c0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103720022903f88004210820022802808104210602402003450d00200120034104746a210a2001210b03400240200b2802082203450d00200b2802002104200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102c200928020021050b2005102c0b200441106a2104200341706a22030d000b0b200b41106a21040240200b41046a280200450d00200b280200102c0b2004210b2004200a470d000b0b2008422088210e4105210b41002104200d450d012001102c0c010b200b41087621042007ad220e422086200dad8421082002280234450d002002280230102c0b20004101360200200041106a2006360200200041086a200e422086200842ffffffff0f838437020020002004410874200b41ff0171723602040c1a0b200241e8006a20011099050240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a29020022083703002002200229026c220e3703f88004200ea7210b2008a721054100210420022802848104210141002103024002400240024002400240024003402004411f4b0d010240024020052001460d002001417f460d072005200141016a22094f0d01200141016a2005103f000b200220053602848104200241013a0058200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200241206a41086a200241306a41086a280200360200200220022903303703204105210b0c030b200b20016a2d0000220641ff00712004411f71742003722103200441076a2104200921012006418001710d000b200220093602848104024020044120490d00410d210b2006410f4b0d020b200241003602382002420437033020030d02410421010c030b200220013602848104410f210b0b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008422088a7210a2008a7210d410021090c030b4104210141002105410021060340200241e8006a200241f880046a10910520022f006d20022d006f4110747221092002280274210a2002280270210d20022d006c210b024020022802684101470d002002200536023420022006360238200241f8006a28020021042005450d042001102c0c040b0240024020062005460d0020052107200621040c010b200541016a22042005490d15200541017422072004200720044b1b2207ad420c7e2208422088a70d152008a722044100480d150240024020050d002004102a21010c010b20012005410c6c2004102e21010b2001450d1d2002200136023020052104200721050b20012004410c6c6a220420093b00012004200d3602042004200b3a0000200441036a20094110763a0000200441086a200a3602002003200641016a2206470d000b20022007360234200220063602380b200228028481042002280288810446210420022902342108024020022802fc8004450d0020022802f88004102c0b2008a721092004450d022008422088a7ad4220862009ad842108410621030c190b417f200141016a1047000b200941ffffff07712205410874200b41ff0171722103200aad220e422086200dad84210820022802fc8004450d0120022802f88004102c0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a103720022903302208422088210e2002280238210441052103410021052009450d002001102c0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c190b200241e8006a20011099050240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a29020022083703002002200229026c220e3703f88004200ea7210b2008a72103410021042002280284810421014100210902400240024002400240024002400240024003402004411f4b0d010240024020032001460d002001417f460d072003200141016a22054f0d01200141016a2003103f000b200220033602848104200241013a0058200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200241206a41086a200241306a41086a280200360200200220022903303703204105210a0c030b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b200220053602848104024020044120490d00410d210a2006410f4b0d020b41002107200241003602f08004200242043703e8800420090d02410421014100210d0c030b200220013602848104410f210a0b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008a7210b4100210320022802ec8004210d0c050b4104210141012107410021060340024002400240024020032005460d00200541016a22042005490d0720032004490d08200b20056a2c000021032002200436028481040240200341004e0d004119210a0c020b4107210a0240200341c000710d000c020b200341807f7222034170470d02200241e8006a200241f880046a10910520022f006d20022d006f41107472210320022d006c210a20022802684101470d0320034180feff07714108762105200228027821042002280274210d2002280270210b0c020b200241013a00582002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10372002280230210b2002280234210d200228023821044105210a0b0b200220063602ec800420022007417f6a3602f080042005410874200341ff01717221032006450d062001102c0c060b200228027421052002280270210b024002402007417f6a22042006460d002006210d200421060c010b200641016a22042006490d162006410174220d2004200d20044b1b220dad420c7e2208422088a70d162008a722044100480d160240024020060d002004102a21010c010b20012006410c6c2004102e21010b2001450d1e200220013602e880040b20012006410c6c6a220420033b0001200420053602082004200b3602042004200a3a0000200441036a20034110763a0000024020092007460d00200741016a210720022802848104210520022802808104210320022802f88004210b200d21060c010b0b2002200d3602ec8004200220073602f080040b2002280284810420022802888104462104024020022802fc8004450d0020022802f88004102c0b2004450d042007ad422086200dad842108410521030c1a0b417f200141016a1047000b417f20041047000b20042003103f000b200341ffffff07712205410874200a41ff0171722103200dad220e422086200bad84210820022802fc8004450d0120022802f88004102c0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a103720022903302208422088210e200228023821044105210341002105200d450d002001102c0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c180b200241e8006a20011099050240024020022802684101470d00200228026c22044108762105200241e8006a41086a2903002208422088210e200241f8006a28020021030c010b200241fc006a280200210c200241f8006a2802002101200241f4006a2802002103200241f0006a2802002107200228026c210b4100210441002109024002400240024002400240024002400240034002402004411f4d0d00410f21040c020b0240024020032001460d002001417f460d052003200141016a22054f0d01200141016a2003103f000b200241013a0030200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1037200241206a41086a200241f880046a41086a280200360200200220022903f88004370320410521040c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b20044120490d01410d210420064110490d010b200241e880046a41086a200241206a41086a28020022033602002002200229032022083703e880042008a7210520022802ec800421090c060b4100211b20024100360238200242043703300240024020090d0041042101410021060c010b41042101410021064100211b034020062118201b221941016a211b20052104410021064100210a03402006411f4b0d050240024020032004460d002004417f460d062003200441016a22054f0d01200441016a2003103f000b2002201836023420022019360238200241013a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103720022802f88004210520022802fc80042109200228028081042103410521040c080b200b20046a2d0000220d41ff00712006411f7174200a72210a200641076a210620052104200d418001710d000b024020064120490d00200d410f4d0d002002201836023420022019360238410d21040c060b0240024020192018460d0020182106201921180c010b201841016a22042018490d17201841017422062004200620044b1b220641ffffffff03712006470d17200641027422044100480d170240024020180d002004102a21010c010b200120184102742004102e21010b2001450d1f200220013602300b200120184102746a200a360200201b2009470d000b200220063602342002201b3602380b2005200c46210402402007450d00200b102c0b2004450d06201bad4220862006ad842108410421030c1b0b417f200141016a1047000b417f200441016a1047000b2002201836023420022019360238410f21040b0b2018450d002001102c0b2009ad220e4220862005ad842108410021052007450d01200b102c0c010b20024103410220041b3a0030200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103720022903f880042208422088210e20022802808104210341052104410021052006450d002001102c0b20004101360200200041106a2003360200200041086a200e422086200842ffffffff0f838437020020002005410874200441ff0171723602040c170b200241e8006a20011099050240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f8800441002101410021050240024002400240024002400240024002400240034002402001411f4d0d00410f21030c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103f000b200241013a0058200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200241206a41086a200241306a41086a28020036020020022002290330370320410521030c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210320044110490d010b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008422088a721092008a721060c080b200241003602f08004200242043703e880040240024020050d00410421010c010b20022802ec8004210720022802f08004210d410021100340200241e8006a200241f880046a108e052002280274210920022802702118200228026c211a024020022802684101470d002002280278210420182106201a21030c080b200241e8006a200241f880046a108e052002280274211320022802702119200228026c211c024020022802684101470d00200228027821042019210620132109201c21030c070b0240024002400240024002400240024002400240024002400240024002400240200228028081042203200228028481042206460d00200641016a22012006490d02200320014f0d0120012003103f000b200241013a00582002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200228023021062002290234210e4105210a4100211b410021030c140b20022802f88004220c20066a2d000021042002200136028481044100211b0240200441034d0d004109210a410021030c140b024002400240024020040e0400010203000b4100211b410021044100210a034002402004411f4d0d00410f210a0c160b0240024020032001460d002001417f460d072003200141016a220b4f0d01200141016a2003103f000b200241013a00582002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200228023021062002290234210e4105210a4100211b0c170b200c20016a2d000021062002200b3602848104200641ff00712004411f7174200a72210a200441076a2104200b21012006418001710d000b4100211b20044120490d0f2006410f4d0d0f410d210a0c140b0240024020032001460d00200641026a21042001417f460d0620032004490d07200c20016a2c0000210120022004360284810402402001417f4a0d00411921030c0e0b200141c000710d010c0c0b200241013a00582002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10372002290330210820022802382104410521030c0c0b200141807f7222014170470d0a200241e8006a200241f880046a10910520022903702108200228026c210a024020022802684101470d00200228027821040c0d0b4101211b0c0f0b200241e8006a200241f880046a10910520022903702108200228026c210a024020022802684101460d004102211b0c0f0b20022002280278360270200a418080807871211b200a4180807c712103200a41087621040c0c0b0240024020032001460d00200641026a210b2001417f460d062003200b490d08200c20016a2c000021042002200b36028481040240200441004e0d004119210a410021030c160b200441c000710d010c090b200241013a00582002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10374105210a2002290234210e20022802302106410021030c140b200441807f72220441ff017141fc01490d07024002402003200b460d00200641036a2101200b417f460d07200320014f0d0120012003103f000b200241013a00582002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1037200228023021062002290234210e4105210a410021030c140b200c200b6a2d0000210b200220013602848104410021030240200b41014d0d00410c210a4100211b200b21040c140b2004417f7321064103211b0240200b0e020e000e0b410121030c0d0b417f20011047000b417f200141016a1047000b417f20041047000b20042003103f000b417f200b1047000b417f20011047000b200b2003103f000b4106210a410021030c0b0b410721030b200141ff0171410874200372210a0b20022004360270200a418080807871211b200a4180807c712103200a41087621040b20022008370368200229026c210e2008a721060c070b0b02400240200d2007460d002007210b0c010b200741016a22012007490d17200741017422042001200420014b1b220bad42287e220e422088a70d17200ea722014100480d170240024020070d002001102a21010c010b20022802e88004200741286c2001102e21010b2001450d1f200220013602e880042007210d200b21070b20022802e880042201200d41286c6a2204201c36020c20042009360208200420183602042004201a360200200441206a20083702002004411c6a200a3602002004411a6a20033a0000200441196a20063a0000200441186a201b3a0000200441146a2013360200200441106a2019360200200d41016a210d201041016a22102005470d000b2002200b3602ec80042002200d3602f080040b200228028481042002280288810446210420022902ec80042208422088210e024020022802fc8004450d0020022802f88004102c0b200ea721032008a721092004450d062003ad4220862009ad842108410321030c1b0b417f20031047000b0b41002103410021040b200a41ff0171200441ff0171410874722003418080fc077172201b722103200e422088a72104200ea721092019450d00201c102c0b2018450d00201a102c0b200220073602ec80042002200d3602f0800420022802e88004210b0240200d450d00200d41286c2105200b210103400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101200541586a22050d000b0b2007450d01200b102c0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1037200229033021082002280238210402402003450d00200341286c21052001210303400240200341046a280200450d002003280200102c0b0240200341106a280200450d002003410c6a280200102c0b200341286a2103200541586a22050d000b0b2008422088210e41052103410021052009450d012001102c0c010b200341087621052009ad220e4220862006ad84210820022802fc8004450d0020022802f88004102c0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c160b200241013a00302002410136027c2002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103720022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050b0b201d450d03200c102c0c030b0b2018450d00201c102c0b2003411076210d200341087621070b200741ff0171410874200341ff0171722103200d411074210d200441ff0171410874210702402017450d002001210403400240200441046a280200450d002004280200102c0b200441106a2104200a41706a220a0d000b0b2003200d722103200720057221042014450d012001102c0c010b20024103410220041b3a0030200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103720022903f88004210820022802808104210302402005450d00200541047421052001210403400240200441046a280200450d002004280200102c0b200441106a2104200541706a22050d000b0b2008422088210e41052104410021052009450d012001102c0c010b200441087621052009ad220e4220862006ad8421082010450d00200b102c0b20004101360200200041106a2003360200200041086a200e422086200842ffffffff0f838437020020002005410874200441ff0171723602040c0c0b41002101410021040240024002400340024020094105470d00410f21070c020b0240024020032009460d00200320094b0d01200941016a2003103f000b200241013a00f88004200241fc006a41013602002002420137026c200241f0f7c5003602682002412b36021c2002200241186a3602782002200241f880046a360218200241206a200241e8006a103741052107200229032021080c030b200620096a2d0000220541ff00712001411f71742004722104200141076a2101200941016a220b21092005418001710d000b20014120490d0220054110490d02410d21070b0b2008422088a72109200228022821042008a7210d0c040b024020040d00410021054101211b410021094100210d0c070b200241e8006a410041800810da051a410021054100210d4101211b410021070340024002402003200b6b200420076b22014180082001418008491b2201490d00200b20016a220c200b490d042003200c4f0d01200c2003103f000b200241013a00e880042002418c81046a4101360200200242013702fc8004200241f0f7c5003602f880042002412b36021c2002200241186a36028881042002200241e880046a360218200241306a200241f880046a103720022903302208422088a72109200228023821042008a72101410521070240200d450d00201b102c0b2001210d0c050b200241e8006a2006200b6a200110db051a02400240200d20056b2001490d00200520016a21090c010b200520016a22092005490d02200d410174220b2009200b20094b1b220b4100480d0202400240200d0d00200b102a211b0c010b201b200d200b102e211b0b201b450d0a200b210d0b201b20056a200241e8006a200110db051a20092105200c210b2004200120076a22074d0d030c000b0b1035000b200b200c1047000b200241e8006a201b2009105820022802684101470d02410821070240200d450d00201b102c0b0b2009ad422086200dad84210841002101200a450d002006102c0b20004101360200200041106a2004360200200041086a200837020020002001410874200741ff0171723602040c060b201b4108762105200c210b0b2003200b490d022003200b6b2201417f4c0d030240024020010d00410121040c010b2001102a2204450d020b2009ad4220862108200dad210e20042006200b6a200110db051a2001ad222042208621210240200a450d002006102c0b2008200e8421082021202084210e2005410874201b41ff0171722101410121030b200020033a000420004100360200200041056a20022f00153b0000200041186a200e370200200041146a20043602002000410c6a2008370200200041086a2001360200200041206a2002290200370200200041076a200241176a2d00003a0000200041286a200241086a290200370200200041306a200241106a2802003602000c030b1033000b200b20031047000b103a000b2002419081046a24000b160020002001280208360204200020012802003602000bb20c01067f0240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a280200102c0f0b0240200041086a280200450d00200041046a280200102c0b200041146a280200450d0c200041106a280200102c0f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d002001280200102c0b200141106a2101200241706a22020d000b0b200041086a280200450d0b2000280204102c0f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101200241586a22020d000b0b200041086a280200450d0a2000280204102c0f0b200041086a280200450d09200041046a280200102c0f0b200041086a280200450d08200041046a280200102c0f0b200041086a280200450d07200041046a280200102c0f0b02402000410c6a2802002201450d00200041046a280200220320014104746a21040340024020032802082202450d0020032802002101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102c200528020021060b2006102c0b200141106a2101200241706a22020d000b0b200341106a21010240200341046a280200450d002003280200102c0b2001210320012004470d000b0b200041086a280200450d062000280204102c0f0b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d002001280200102c0b200141146a21012002416c6a22020d000b0b200041086a280200450d052000280204102c0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102c200528020021060b2006102c0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102c0b2003411c6a21010240200341146a280200450d002003280210102c0b2001210320012004470d000b0b200041086a280200450d042000280204102c0f0b02402000410c6a2802002201450d00200041046a2802002203200141186c6a210403400240200341046a280200450d002003280200102c0b0240200341146a2802002202450d00200328020c2101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102c200528020021060b2006102c0b200141106a2101200241706a22020d000b0b200341186a21010240200341106a280200450d00200328020c102c0b2001210320012004470d000b0b200041086a280200450d032000280204102c0f0b200041046a2201109805200041086a280200450d022001280200102c0f0b0240200041046a2802002201450d00200041086a280200450d002001102c0b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102c0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102c0b200041246a2802002203450d0102402000412c6a2802002201450d00200320014104746a210403402003220541106a2103024020052802042201450d0002402005410c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102c0b2001410c6a2101200241746a22020d000b0b200541086a280200450d002005280204102c0b20032004470d000b0b200041286a280200450d012000280224102c0c010b0240200041086a280200450d00200041046a280200102c0b0240200041146a2802002201450d00200041186a280200450d002001102c0b200041246a280200450d00200041206a280200102c0f0b0be34c04177f017e047f017e230041e0026b22022400200128020841546a2103200141106a28020041306c2104024002400240024002400240024002400240024002400240024003402004450d01200441506a21042003412c6a2105200341306a2206210320052d00004102470d000b200241e8006a200610f40441042107200228026c2208450d01200841047422044100480d0c200228026821032004102a2207450d052008410474210641002109200721040340200341086a2802002205417f4c0d042003410c6a2d0000210a2003280200210b0240024020050d004101210c0c010b2005102a220c450d070b200c200b200510db05210b2004410d6a2003410d6a2d00003a00002004410c6a200a3a0000200441086a2005360200200441046a20053602002004200b360200200441106a2104200941016a2109200341106a2103200641706a22060d000b20070d020b410421070b41002109410021080b200128021041306c2104200128020841546a2103024003404100210c4104210a024020040d0041042103410021040c020b200441506a21042003412c6a2105200341306a2206210320052d00004103470d000b200241e0006a200610f404410421034100210420022802602205450d0020022802642104200521030b024020040d004101210d4100210e410021034100210f4100210b41002110410121114100210541002112410421134100210641002114410421150c020b200441286c21162003411c6a21044104210a4100210c4100210e4101210d410021034100210f4100210b41002110410121114100210541002112410421134100210641002114410421150340024002400240024002402004417c6a2d00000e0400010203000b2004280200211702402003200f470d00200341016a220f2003490d0f20034101742218200f2018200f4b1b220f41ffffffff0371200f470d0f200f41027422184100480d0f0240024020030d002018102a210a0c010b200a20034102742018102e210a0b200a450d080b200a20034102746a2017360200200341016a21030c030b200241b8016a41086a2217200441086a280200360200200220042902003703b801024020052012470d00200541016a22122005490d0e200541017422182012201820124b1b2212ad420c7e2219422088a70d0e2019a722184100480d0e0240024020050d002018102a21130c010b20132005410c6c2018102e21130b2013450d070b20132005410c6c6a221820022903b801370200201841086a2017280200360200200541016a21050c020b200241b8016a41086a2217200441086a280200360200200220042902003703b801024020062014470d00200641016a22182006490d0d2006410174221a2018201a20184b1b2214ad420c7e2219422088a70d0d2019a722184100480d0d0240024020060d002018102a21150c010b20152006410c6c2018102e21150b2015450d060b20152006410c6c6a221820022903b801370200201841086a2017280200360200200641016a21060c010b2004417e6a22172d000021182004417d6a221a2d0000211b0240200b2010470d00200b41016a2210200b490d0c200b410174221c2010201c20104b1b221020106a221d2010490d0c201d4100480d0c02400240200b0d00201d102a21110c010b2011201c201d102e21110b2011450d050b2011200b4101746a221d20184101713a0001201d201b3a000020172d00002117201a2d000021180240200c200e470d00200c41016a221a200c490d0c200c410174221b201a201b201a4b1b220e200e6a221a200e490d0c201a4100480d0c02400240200c0d00201a102a210d0c010b200d201b201a102e210d0b200d450d050b200b41016a210b200d200c4101746a221a20174101713a0001201a20183a0000200c41016a210c0b200441286a2104201641586a2216450d020c000b0b103a000b2001280210221b41306c211820012802082116410021040240034020182004460d01201620046a2117200441306a221a210420172d00004104470d000b200241d8006a2016201a6a41546a10f404200228025c2204450d002002280258211620044102742118200341017421172003410274210403402016280200211a02402003200f470d00200341016a220f2003490d0a2017200f2017200f4b1b220f41ffffffff0371200f470d0a200f410274221b4100480d0a0240024020030d00201b102a210a0c010b200a2004201b102e210a0b200a450d030b201641046a2116200a20046a201a360200201741026a2117200441046a2104200341016a21032018417c6a22180d000b200128020821162001280210211b0b2016201b41306c6a2118201621040240034020182004460d0120042d00002117200441306a221a210420174105470d000b200241d0006a201a41546a10f4042002280254410c6c221a450d0020022802502104200541017421172005410c6c21160340200441086a2118024002400240200441046a2802004101470d0020022018280200221b3602a0022004280200221d201b4b0d010b200241003602700c010b200241023602cc01200242023702bc012002418c98c6003602b801200241013602d402200241013602cc022002201d3602b0022002200241c8026a3602c8012002200241b0026a3602d0022002200241a0026a3602c802200241f0006a200241b8016a10372002280270450d00200241f0006a21040c080b20042902002119200241b8016a41086a221b2018280200360200200220193703b801024020052012470d00200541016a22122005490d0a20172012201720124b1b2212ad420c7e2219422088a70d0a2019a722184100480d0a0240024020050d002018102a21130c010b201320162018102e21130b2013450d030b2004410c6a2104201320166a221820022903b801370200201841086a201b280200360200201741026a21172016410c6a2116200541016a2105201a41746a221a0d000b200128020821162001280210211b0b2016201b41306c6a2118201621040240034020182004460d0120042d00002117200441306a221a210420174106470d000b200241c8006a201a41546a10f404200228024c2217450d00200228024821042017410c6c2118200641017421172006410c6c21160340200241b8016a2004109f05024020022802b801450d00200241b8016a21040c080b20042902002119200241b8016a41086a221a200441086a280200360200200220193703b801024020062014470d00200641016a22142006490d0a20172014201720144b1b2214ad420c7e2219422088a70d0a2019a7221b4100480d0a0240024020060d00201b102a21150c010b20152016201b102e21150b2015450d030b2004410c6a2104201520166a221b20022903b801370200201b41086a201a280200360200201741026a21172016410c6a2116200641016a2106201841746a22180d000b200128020821162001280210211b0b2016201b41306c6a2118201621040240034020182004460d0120042d00002117200441306a221a210420174107470d000b200241c0006a201a41546a10f40420022802442217450d002002280240220420174104746a211d200b4101742116200241b8016a410472211b0340200241b8016a2004200d200c10a00502400240024020022d00b8014101460d00200220022d00b90122173a00a002024020172004410c6a2d00002218470d00200241003602700c030b200241023602cc01200242023702bc01200241a099c6003602b8012002412c3602d4022002412c3602cc02200220183a00b0022002200241c8026a3602c8012002200241a0026a3602d0022002200241b0026a3602c802200241f0006a200241b8016a10370c010b200241f0006a41086a201b41086a2802003602002002201b2902003703700b02402002280270450d00200241f0006a21040c090b2004410c6a2d000021170b2004410d6a2d000021180240200b2010470d00200b41016a2210200b490d0a20162010201620104b1b221020106a221a2010490d0a201a4100480d0a02400240200b0d00201a102a21110c010b20112016201a102e21110b2011450d030b201120166a221a20173a0000201a41016a20184101713a0000201641026a2116200b41016a210b200441106a2204201d470d000b200128020821162001280210211b0b200241a8016a2003360200200241a4016a200f3602002002419c016a200936020020024198016a200836020020024190016a200b3602002002418c016a201036020020024184016a200536020020024180016a20123602002002200a3602a001200220073602940120022011360288012002201336027c2002200636027820022014360274200220153602702016201b41306c6a21052016210402400340024020052004470d004100210a0c020b20042d00002103200441306a2206210420034104470d000b200241386a200641546a10f404200228023c210a0b2002200a3602ac012016201b41306c6a21052016210402400340024020052004470d00410021040c020b20042d00002103200441306a220621042003410c470d000b2006415c6a28020021040b200220043602b001200a2004470d0202400240024002400240200a450d002016201b41306c6a210520162104034020052004460d0320042d00002103200441306a2206210420034104470d000b2016201b41306c6a210a201621040340200a2004460d0220042d00002103200441306a220521042003410c470d000b200241306a200641546a10f40420022802342204450d002002280230220c20044102746a21132005415c6a2116200541546a210f200241f1016a21184100210b03402002200b3602b40120162802002104200f2802002105200242013702bc0120024194cfc5003602b801200241013602b402200241013602cc012002200241b0026a3602c8012002200241b4016a3602b002200241c8026a200241b8016a103720022802c802210320022902cc0221190240024002400240024002402004200b4d0d0002402019a7450d002003102c0b2002200c28020022043602a0020240200228029c0120044b0d00200241013602cc01200242023702bc01200241ac9cc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103720022902cc022219422088a7210420022802c80221062019a721030c040b2005200b41186c6a22032802142209450d0120022802940120044104746a22052d000d211720052802002112200328020c210420032802002110200528020822152106024020032802082211450d002011410374210a201521032010210503400240200320052802006a220620034f0d004120102a2206450d0f200641186a410029008c9f46370000200641106a41002900849f46370000200641086a41002900fc9e46370000200641002900f49e463700000c050b200541086a210520062103200a41786a220a0d000b0b4108102a2203450d0c20032017ad42ff0183422886370200200241b0026a41026a2205200241c8026a41026a2d00003a0000200220022f00c8023b01b002200220173a00f0012002418080013602ec0120024281808080103702e401200220033602e001200242808080808080103703d801200242013703d001200220063602cc01200220113602c801200220103602c401200220153602c001200220123602bc012002200241f0006a3602b801201820022f01b0023b0000201841026a20052d00003a000020094104742105410021030340200220033602f801200220043602fc0120024180026a200241b8016a200410a2050240200228028002450d00200241a0026a41086a20024180026a41086a28020036020020022002290380023703a002200241033602c402200242033702b402200241f8c7c5003602b0022002412d3602dc02200241013602d4022002412e3602cc022002200241c8026a3602c0022002200241a0026a3602d8022002200241f8016a3602d0022002200241fc016a3602c80220024190026a200241b0026a1037024020022802a402450d0020022802a002102c0b2002280290022206450d002002290294022119024020022802d401450d0020022802d001102c0b2019422088211e024020022802e401450d0020022802e001102c0b201ea721042019a721030c060b200441106a2104200341016a2103200541706a22050d000b024020022802e8010d00024020022802d401450d0020022802d001102c0b20022802e401450d0620022802e001102c0c060b4190c8c500413041acfec5001036000b20002003360200200020193702040c0f0b4120102a2206450d0a200641186a41002900efc745370000200641106a41002900e7c745370000200641086a41002900dfc745370000200641002900d7c7453700000b41202103412021040b2006450d010b200220063602b00220022004ad4220862003ad843702b4022002200241b0026a36029002200241023602cc01200242023702bc012002419ccfc5003602b8012002412f3602d402200241013602cc022002200241c8026a3602c801200220024190026a3602d0022002200241b4016a3602c802200241a0026a200241b8016a1037024020022802b402450d0020022802b002102c0b20022802a0022204450d0020022902a402211920002004360200200020193702040c0b0b200b41016a210b200c41046a220c2013470d000b200128020821162001280210211b0b2016201b41306c6a2105201621040240034020052004460d0120042d00002103200441306a2206210420034109470d000b2002200641546a280200220436029002024020022802a80120044b0d00200241cc016a4101360200200242023702bc01200241889cc6003602b801200241013602b4022002200241b0026a3602c801200220024190026a3602b002200241c8026a200241b8016a10370c090b200220022802a00120044102746a28020022043602a0020240200228029c0120044b0d00200241cc016a4101360200200242023702bc01200241ac9cc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a10370c090b20022802940120044104746a220431000d4220862004350208844280808080c000510d00412d102a2204450d05200441256a41002900d1cf45370000200441206a41002900cccf45370000200441186a41002900c4cf45370000200441106a41002900bccf45370000200441086a41002900b4cf45370000200441002900accf45370000200042ad808080d005370204200020043602000c090b2016201b41306c6a2103034020032016460d0420162d00002104201641306a2205211620044108470d000b200241286a200541546a220f10f404200228022821044100210502400240200228022c22030d004104210a410021160c010b200341ffffffff01712003470d0c200341037422064100480d0c2006102a220a450d05200321160b02402003450d002004200341146c6a21062003410274417c6a210b200a2103034020042802002105200341046a200441086a28020036020020032005360200200341086a2103200441146a22042006470d000b200b41027641016a21050b200a2005200241b8016a410041202005676b109a05200a20054103746a2206200a460d0241012105200a2104200a21030340024002402005450d00200620046b41037620054d0d05200420054103746a22040d010c050b20062004460d040b200220033602a00202400240200341046a2802002205200441046a280200470d002003280200220b2004280200220c460d01200b200c200510dd05450d010b200441086a210441002105200341086a22032006470d010c040b0b200241cc016a4101360200200242013702bc01200241dccfc5003602b801200241303602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a1037200041086a200241c8026a41086a280200360200200020022903c8023702000c050b41cacec50041c8001054000b41accec500411e1054000b200241206a200f10f404024020022802242204450d00200441146c2103200228022041106a2104024002400340024002400240024002402004417c6a2802000e0400030201000b2002200428020022053602900202400240024020022802a80120054b0d00200241cc016a4101360200200242023702bc01200241889cc6003602b801200241013602b4022002200241b0026a3602c801200220024190026a3602b002200241c8026a200241b8016a10370c010b200220022802a00120054102746a28020022053602a002200228029c0120054b0d01200241013602cc01200242023702bc01200241ac9cc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a10370b20022802c8022104200020022902cc02370204200020043602000c0b0b2019428080808080608320022802940120054104746a220535020884200531000d4220868421190c030b2002200428020022053602a002024020022802900120054b0d00200241cc016a4101360200200242023702bc01200241cc9cc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a10370c060b20022802880120054101746a2d0001450d02200241cc016a4101360200200242023702bc01200241ec9cc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a10370c050b2002200428020022053602a002200228027820054b0d01200241013602cc01200242023702bc01200241b89bc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103720022802c8022205450d01200020022902cc02370204200020053602000c080b2002200428020022053602a00220022802840120054d0d020b200441146a21042003416c6a22030d000c030b0b200241cc016a4101360200200242023702bc01200241e89bc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103720022802c8022104200020022902cc02370204200020043602000c040b20022802c8022104200020022902cc02370204200020043602000c030b2016450d00200a102c0b2001280210220b41306c21042001280208220c41546a21030240024002400240024002400240024002400240024003402004450d01200441506a21042003412c6a2105200341306a2206210320052d00004103470d000b200241186a200610f404200228021c2204450d0020022802182105200441286c210641002104034002400240024002400240200520046a220341186a2d00000e0400030201000b20022003411c6a28020022033602a002200228029c0120034b0d03200241cc016a4101360200200242023702bc01200241ac9cc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103720022802c8022104200020022902cc02370204200020043602000c140b2003411a6a2d0000450d022003410c6a2802002104200341146a2802002103200241b8016a41146a4101360200200220033602b402200220043602b002200241043602a402200242013702bc01200241e4cfc5003602b8012002200241b0026a3602a0022002200241a0026a3602c801200241c8026a200241b8016a1037200041086a200241c8026a41086a280200360200200020022903c8023702000c130b200241b8016a2003411c6a109f0520022802b801450d01200020022903b801370200200041086a200241b8016a41086a2802003602000c120b200341206a2802004101470d002003411c6a280200210a2002200341246a280200220336029002200a20034d0d00200241023602cc01200242023702bc012002418c98c6003602b801200241013602d402200241013602cc022002200a3602a0022002200241c8026a3602c8012002200241a0026a3602d002200220024190026a3602c802200241b0026a200241b8016a103720022802b00222030d030b2006200441286a2204470d000b0b200228028401220441014b0d072002280278220441014b0d08200b41306c2104200c41546a2103024003402004450d01200441506a21042003412c6a2105200341306a2206210320052d0000410d470d000b200241106a200610f404200228021022042002280214411c6c6a2105034020042005460d012002200428020022033602a0020240200228027820034b0d00200241013602cc01200242023702bc01200241b89bc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103720022802c80222030d040b200441046a2204280200450d04200241b8016a200420022802880120022802900110a00520022d00b8014101460d05200441186a210420022d00b901450d000b4120102a2204450d0b200441186a4100290094d045370000200441106a410029008cd045370000200441086a4100290084d045370000200441002900fccf45370000200042a08080808004370204200020043602000c0f0b200b41306c2104200c41546a2103024003402004450d01200441506a21042003412c6a2105200341306a2206210320052d0000410a470d000b200241086a200610f404200228020c2204450d002002280208220a2004411c6c6a210b02400340200a450d022002200a28020022043602a00220022802840120044d0d07200a280204450d08200241b8016a200a41046a20022802880120022802900110a00520022d00b8014101460d0920022d00b9010d0c2002200a10a4050240024020022802042204450d00200228020021032004410274210520022802a80121060340200220032802002204360290020240200620044b0d00200241cc016a4101360200200242023702bc01200241889cc6003602b801200241013602b4022002200241b0026a3602c801200220024190026a3602b002200241c8026a200241b8016a10370c050b200220022802a00120044102746a28020022043602a002200228029c0120044d0d022019428080808080608320022802940120044104746a220435020884200431000d422086842119200341046a21032005417c6a22050d000b0b200a411c6a220a200b460d030c010b0b200241013602cc01200242023702bc01200241ac9cc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a10370b20022802c8022104200020022902cc02370204200020043602000c0f0b2000410036020002402002280274450d002002280270102c0b0240200228028001450d00200228027c102c0b0240200228028c01450d00200228028801102c0b0240200228029c012203450d0020022802940121042003410474210303400240200441046a280200450d002004280200102c0b200441106a2104200341706a22030d000b0b0240200228029801450d00200228029401102c0b024020022802a401450d0020022802a001102c0b200e450d10200d102c0c100b200020022902b402370204200020033602000c0d0b200020022902cc02370204200020033602000c0c0b4129102a2204450d07200441286a41002d00c4d0453a0000200441206a41002900bcd045370000200441186a41002900b4d045370000200441106a41002900acd045370000200441086a41002900a4d0453700002004410029009cd045370000200042a98080809005370204200020043602000c0b0b200020022902bc01370200200041086a200241c4016a2802003602000c0a0b200241cc016a4101360200200242023702bc01200241e89bc6003602b801200241013602b4022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a103720022802c8022104200020022902cc02370204200020043602000c090b412a102a2204450d04200441286a41002f00edd0453b0000200441206a41002900e5d045370000200441186a41002900ddd045370000200441106a41002900d5d045370000200441086a41002900cdd045370000200441002900c5d045370000200042aa808080a005370204200020043602000c080b200020022902bc01370200200041086a200241c4016a2802003602000c070b200241cc016a4101360200200242013702bc01200241eccfc5003602b801200241013602b402200220043602a0022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a1037200041086a200241c8026a41086a280200360200200020022903c8023702000c060b200241cc016a4101360200200242013702bc01200241f4cfc5003602b801200241013602b402200220043602a0022002200241b0026a3602c8012002200241a0026a3602b002200241c8026a200241b8016a1037200041086a200241c8026a41086a280200360200200020022903c8023702000c050b4120102a2204450d00200441186a4100290094d045370000200441106a410029008cd045370000200441086a4100290084d045370000200441002900fccf45370000200042a08080808004370204200020043602000c040b1033000b2016450d02200a102c0c020b200241cc016a4102360200200241d4026a4101360200200242023702bc012002419ccec5003602b801200241013602cc022002200241c8026a3602c8012002200241b0016a3602d0022002200241ac016a3602c802200241b0026a200241b8016a1037200041086a200241b0026a41086a280200360200200020022903b0023702000c010b20022802c8022104200020022902cc02370204200020043602000b02402002280274450d002002280270102c0b0240200228028001450d00200228027c102c0b0240200228028c01450d00200228028801102c0b0240200228029c012203450d0020022802940121042003410474210303400240200441046a280200450d002004280200102c0b200441106a2104200341706a22030d000b0b0240200228029801450d00200228029401102c0b024020022802a401450d0020022802a001102c0b200e450d01200d102c0c010b20002004290200370200200041086a200441086a2802003602000240200e450d00200d102c0b02402014450d002015102c0b02402012450d002013102c0b02402010450d002011102c0b02402009450d00200941047421032007210403400240200441046a280200450d002004280200102c0b200441106a2104200341706a22030d000b0b02402008450d002007102c0b200f450d00200a102c0b200241e0026a24000f0b1035000bac1301177f23004190026b220224000240024002402000280200220341d0e1c100460d00200028020421040c010b41002104200241b8016a410041d80010da051a2002411f6a220542003700002002420037011a41ec00102a2203450d0120034100360200200320022902183702042003410b6a2005290000370000200341136a200241b7016a41d90010db051a20004100360204200020033602000b200141ff01712106024002400340200341066a210720032f01062108410c21094100210502400240034020082005460d01200320056a210a200941086a2109200541016a210502404100417f4101200a41086a2d0000220a20064b1b200a2006461b41016a0e03000301000b0b2005417f6a21080b2004450d022004417f6a2104200320084102746a41ec006a28020021030c010b0b200320096a42013702000c010b2000200028020841016a36020802400240024020072f01002205410b490d00200241276a41016a410041d80010da051a200241003a001941ec00102a220b450d04200b4100360200200b410036000f200b4200370007200b20022f01183b0005200b41136a200241276a41d90010db051a2003410e6a2d0000210c2003280248210d2003280244210e200b41086a2003410f6a20032f010641796a220510db052109200b41146a200341cc006a200541037410db052106200341063b0106200b20053b010620084107490d0120092008417a6a220a6a2009200841796a22086a2209200541ffff037120086b10dc051a200920013a00002006200a4103746a200620084103746a2205200b41066a22072f010020086b41037410dc051a2005410136020020072f010021050c020b200341086a2209200841016a22066a200920086a2209200520086b220a10dc051a200920013a0000200341146a220920064103746a200920084103746a2209200a41037410dc051a200941013602002003200541016a3b01060c020b200341086a2205200841016a22096a200520086a220620072f0100220520086b220a10dc051a200620013a0000200341146a220620094103746a200620084103746a2209200a41037410dc051a200941013602000b2007200541016a3b010002402003280200220a450d00200341046a2105200241276a41016a210f200241a8016a2101200241a0016a211020024198016a211120024190016a211220024180016a41086a2113034020052f01002106024002400240200a2f01062205410b490d00200f410041d80010da051a200241003a0019200220022f01183b0108200241b7016a200241276a41d90010db051a20014200370300201042003703002011420037030020124200370300201342003703002002420037038001419c01102a2209450d06200941003602002009410036000f20094200370007200920022f01083b0005200941136a200241b7016a41d90010db051a20094194016a20012903003702002009418c016a201029030037020020094184016a2011290300370200200941fc006a2012290300370200200941f4006a2013290300370200200920022903800137026c200a41c8006a2802002114200a41c4006a2802002115200a410e6a2d00002116200941086a200a410f6a200a2f0106220341796a220510db052117200941146a200a41cc006a200541037410db052118200941ec006a200a4188016a2003417a6a220441027410db052107200a41063b0106200920053b010602402004450d00410021052007210303402003280200220820053b010420082009360200200341046a21032004200541016a2205470d000b0b20064107490d0120172006417a6a22036a2017200641796a22056a220820092f010620056b10dc051a2008200c3a0000201820034103746a201820054103746a220820092f010620056b41037410dc051a2008200e3602002008200d360204200920092f010641016a22083b01062006410274220c20076a416c6a200720034102746a2204200841ffff0371220620036b41027410dc051a2004200b36020020062003490d022009200c6a41d4006a2103034020032802002208200541016a22053b010420082009360200200341046a210320052006490d000c030b0b200a41086a2209200641016a22036a200920066a2209200520066b220810dc051a2009200c3a0000200a41146a220920034103746a200920064103746a2209200841037410dc051a2009200e3602002009200d360204200a200541016a22053b01062006410274200a41ec006a22096a41086a200920034102746a2209200541ffff0371220820036b41027410dc051a2009200b360200200620084f0d04200a2003417f6a22054102746a41f0006a2103034020032802002209200541016a22053b01042009200a360200200341046a210320052008490d000c050b0b200a41086a2203200641016a22056a200320066a2203200a2f0106220820066b220410dc051a2003200c3a0000200a41146a220320054103746a200320064103746a2203200441037410dc051a2003200e3602002003200d360204200a200841016a22033b010620064102742207200a41ec006a22086a41086a200820054102746a2204200341ffff0371220820056b41027410dc051a2004200b360200200620084f0d00200a20076a41f0006a2105034020052802002203200641016a22063b01042003200a360200200541046a210520082006470d000b0b0240200a28020022030d002009210b2014210d2015210e2016210c0c020b200a41046a21052003210a2016210c2015210e2014210d2009210b0c000b0b200241b7016a41016a410041d80010da051a2002411f6a220542003700002002420037011a200220022902183703082002200529000037000f200241276a200241b7016a41d90010db051a200241a8016a22034200370300200241a0016a2209420037030020024180016a41186a2208420037030020024190016a2206420037030020024180016a41086a220a42003703002002420037038001419c01102a2205450d0120054100360200200520022903083702042005410b6a200229000f370000200541136a200241276a41d90010db051a20054194016a20032903003702002005418c016a200929030037020020054184016a2008290300370200200541fc006a2006290300370200200541f4006a200a290300370200200520022903800137026c20052000280200220336026c200020053602002000200028020441016a360204200341003b010420032005360200200520052f010622034103746a220941186a200d360200200941146a200e360200200520036a41086a200c3a0000200541ec006a200341016a22034102746a200b360200200520033b0106200b20033b0104200b20053602000b20024190026a24000f0b1033000b842701377f2001410c6a28020021022001280208210341002104024002400240200141106a28020022050d00410021064100210741002108410021094100210a4100210b4100210c4100210d4100210e410021050c010b410021044100210e4100210d4100210c4100210b4100210a4100210941002108410021074100210f4100211002400340200121112010210620032005417f6a220541306c6a220128002c2112200128002821132001280024211420012800202115200128001c2116200128001821172001280014211820012800102119200128000c211a2001280008211b2001280004211c41012110024002400240024002400240024020012d0000221d417e6a221e410e4d0d004101211f0c010b4101211f4101212041012121410121224101212341012124201c21010240024002400240024002400240024002400240024002400240024002400240024002400240201e0e0f00010203040506180717080917171a000b0240200f0d002006211020112101201c210f201b2125201a21260c180b02402026450d0020264104742110200f210103400240200141046a280200450d002001280200102c0b200141106a2101201041706a22100d000b0b41002124410121102025450d11200f102c0c110b024020070d002006211020112101201c2107201b2127201a21280c170b02402028450d00202841286c21102007210103400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101201041586a22100d000b0b41002123410121102027450d0f2007102c0c0f0b2029450d0d2008450d0d2008102c0c0d0b202a450d0b2009450d0b2009102c0c0b0b202b450d09200a450d09200a102c0c090b0240200b0d002006211020112101201c210b201b212c201a212d0c130b0240202d450d00200b202d4104746a2122200b21210340024020212802082210450d0020212802002101201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141106a21010240202141046a280200450d002021280200102c0b2001212120012022470d000b0b4101211f41002110202c450d07200b102c0c070b0240200c0d002006211020112101201c210c201b212e201a212f0c120b0240202f450d00202f41146c2110200c210103400240200141046a280200450d002001280200102c0b200141146a21012010416c6a22100d000b0b4100211f41012110202e450d05200c102c0c050b0240200d0d002006211020112101201c210d201b2130201a21310c110b02402031450d00200d2031411c6c6a2122200d21210340024020212802042201450d0002402021410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141086a280200450d002021280204102c0b2021411c6a21010240202141146a280200450d002021280210102c0b2001212120012022470d000b0b41002120410121102030450d03200d102c0c030b0240200e0d002006211020112101201c210e201b2132201a21330c100b02402033450d00200e203341186c6a2122200e212103400240202141046a280200450d002021280200102c0b0240202141146a2802002210450d00202128020c2101201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141186a21010240202141106a280200450d00202128020c102c0b2001212120012022470d000b0b41002121410121102032450d01200e102c0c010b024020040d002006211020112101201a2134201b2135201c21040c0f0b02402034450d0020042034411c6c6a2122200421210340024020212802042201450d0002402021410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141086a280200450d002021280204102c0b2021411c6a21010240202141146a280200450d002021280210102c0b2001212120012022470d000b0b410021224101211002402035450d002004102c0b201c2104201b2135201a21344101211f41012120410121210c0c0b201a2133201b2132201c210e4101211f410121200c0a0b201a2131201b2130201c210d4101211f0c080b201a212f201b212e201c210c0c060b201a212d201b212c201c210b0c050b2006211020112101201c210a201b212b201a21360c090b2006211020112101201c2109201b212a201a21370c080b2006211020112101201c2108201b2129201a21380c070b201a2128201b2127201c21074101211f410121204101212141012122410121240c050b201a2126201b2125201c210f4101211f410121204101212141012122410121230c040b410121200b410121210b410121220b41012123410121240b024002400240201e410b4b0d000240024002400240024002400240024002400240201e0e0c000102030405060a070a0809000b2024450d0b0240201a450d00201a4104742110201c210103400240200141046a280200450d002001280200102c0b200141106a2101201041706a22100d000b0b201b450d0b0c0a0b2023450d0a0240201a450d00201a41286c2110201c210103400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101201041586a22100d000b0b201b0d090c0a0b41000d09201b0d080c090b41000d08201b0d070c080b41000d07201b0d060c070b2010450d060240201a450d00201c201a4104746a211e201c21210340024020212802082210450d0020212802002101201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141106a21010240202141046a280200450d002021280200102c0b200121212001201e470d000b0b201b0d050c060b201f450d050240201a450d00201a41146c2110201c210103400240200141046a280200450d002001280200102c0b200141146a21012010416c6a22100d000b0b201b0d040c050b2020450d040240201a450d00201c201a411c6c6a211e201c21210340024020212802042201450d0002402021410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141086a280200450d002021280204102c0b2021411c6a21010240202141146a280200450d002021280210102c0b200121212001201e470d000b0b201b0d030c040b2021450d030240201a450d00201c201a41186c6a211e201c212103400240202141046a280200450d002021280200102c0b0240202141146a2802002210450d00202128020c2101201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141186a21010240202141106a280200450d00202128020c102c0b200121212001201e470d000b0b201b0d020c030b2022450d020240201a450d00201c201a411c6c6a211e201c21210340024020212802042201450d0002402021410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141086a280200450d002021280204102c0b2021411c6a21010240202141146a280200450d002021280210102c0b200121212001201e470d000b0b201b0d010c020b0240201d410e4b0d00200621102011210102400240024002400240024002400240024002400240201d0e0f0001020304040405060e070e08090a000b201b0d0b0c0c0b0240201b450d00201c102c0b2018450d0b2019102c0c0b0b0240201a450d00201a4104742110201c210103400240200141046a280200450d002001280200102c0b200141106a2101201041706a22100d000b0b201b0d090c0a0b201a450d00201a41286c2110201c210103400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101201041586a22100d000b0b201b0d070c080b0240201a450d00201c201a4104746a211e201c21210340024020212802082210450d0020212802002101201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141106a21010240202141046a280200450d002021280200102c0b200121212001201e470d000b0b201b0d060c070b0240201a450d00201a41146c2110201c210103400240200141046a280200450d002001280200102c0b200141146a21012010416c6a22100d000b0b201b0d050c060b0240201a450d00201c201a411c6c6a211e201c21210340024020212802042201450d0002402021410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141086a280200450d002021280204102c0b2021411c6a21010240202141146a280200450d002021280210102c0b200121212001201e470d000b0b201b0d040c050b0240201a450d00201c201a41186c6a211e201c212103400240202141046a280200450d002021280200102c0b0240202141146a2802002210450d00202128020c2101201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141186a21010240202141106a280200450d00202128020c102c0b200121212001201e470d000b0b201b0d030c040b0240201a450d00201c201a411c6c6a211e201c21210340024020212802042201450d0002402021410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a2220280200221f28020441ffffffff0371450d00201f280200102c2020280200211f0b201f102c0b200141106a2101201041706a22100d000b0b202141086a280200450d002021280204102c0b2021411c6a21010240202141146a280200450d002021280210102c0b200121212001201e470d000b0b201b0d020c030b0240201c450d00201b450d00201c102c0b02402018450d0002402016450d002016410c6c211020182101034002402001280200221f450d00200141046a280200450d00201f102c0b2001410c6a2101201041746a22100d000b0b2017450d002018102c0b2014450d0202402012450d00201420124104746a211c2014212103402021222041106a2121024020202802042201450d0002402020410c6a2802002210450d002010410c6c2110034002402001280200221f450d00200141046a280200450d00201f102c0b2001410c6a2101201041746a22100d000b0b202041086a280200450d002020280204102c0b2021201c470d000b0b2013450d022014102c0c020b0240201b450d00201c102c0b02402018450d002017450d002018102c0b2014450d012015102c0c010b201c102c0b20062110201121010b20050d000b4100210520012111201021060b200f0d010b4104210f41002125410021260b20002003360280012000200636025420002026360208200020253602042000200f36020020004188016a200536020020004184016a2002360200200041fc006a2034410020041b360200200041f8006a2035410020041b36020020002004410420041b360274200041f0006a20334100200e1b360200200041ec006a20324100200e1b3602002000200e4104200e1b360268200041e4006a20314100200d1b360200200041e0006a20304100200d1b3602002000200d4104200d1b36025c200041d8006a2011360200200041d0006a202f4100200c1b360200200041cc006a202e4100200c1b3602002000200c4104200c1b360248200041c4006a202d4100200b1b360200200041c0006a202c4100200b1b3602002000200b4104200b1b36023c200041386a20364100200a1b360200200041346a202b4100200a1b3602002000200a4104200a1b3602302000412c6a2037410020091b360200200041286a202a410020091b36020020002009410420091b360224200041206a2038410020081b3602002000411c6a2029410020081b36020020002008410420081b360218200041146a2028410020071b360200200041106a2027410020071b36020020002007410420071b36020c0ba705010e7f230041106b2202240002400240024020012802004101470d00200141106a2d000021032001410c6a2802002104200141086a280200210520012f0112210620012d0011210720012802042108200241086a200010f40402400240200228020c2209450d002002280208220120094104746a210a0240200741ff0171220b4104460d004100210c200341ff0171210d0340024020012d000c200d470d0020012802082004470d000240200128020022092008460d002004450d002004210e2008210f034020092d0000200f2d0000470d02200941016a2109200f41016a210f200e417f6a220e0d000b0b20012d000d2209200b470d0020094104470d040b200c41016a210c200141106a2201200a470d000c020b0b4100210c200341ff0171210d0340024020012d000c200d470d0020012802082004470d000240200128020022092008460d002004450d002004210e2008210f034020092d0000200f2d0000470d02200941016a2109200f41016a210f200e417f6a220e0d000b0b20012d000d4104460d030b200c41016a210c200141106a2201200a470d000b0b0240024020002802082201200041046a280200470d00200141016a22092001490d012001410174220f2009200f20094b1b220941ffffffff00712009470d012009410474220f4100480d010240024020010d00200f102a21010c010b20002802002001410474200f102e21010b2001450d0420002001360200200041046a2009360200200028020821010b200028020020014104746a220120063b010e200120073a000d200120033a000c2001200436020820012005360204200120083602002000200028020841016a3602082002200010f4042002280204417f6a210c0c040b1035000b2005450d022008102c0c020b2001280204210c0c010b1033000b200241106a2400200c0b8322022d7f017e230041306b220224002002410436020020012802042103200128020021044101210502400240024002400240200128020822060d0041002107410121080c010b4130102a2207450d012007200636000c200720033600082007200436000420022007360200200741023a000041002108410121070b200141106a2802002109200128020c210a02400240200141146a280200220b0d002007210c0c010b2007410174220d200741016a220c200d200c4b1b220c41306c210d0240024020070d00200d102a210d0c010b2002280200200741306c200d102e210d0b200d450d012002200d360200200d200741306c6a220d41033a0000200d20022f002d3b0001200d200b36000c200d2009360008200d200a360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021050b2001411c6a280200210e2001280218210f4100211002400240200141206a28020022110d00200c2112410021130c010b024002402007200c460d00200c21120c010b41000d0341000d03200c410174220d200c41016a2212200d20124b1b2212ad42307ea7220d4100480d0302400240200c0d00200d102a210d0c010b2002280200200c41306c200d102e210d0b200d450d022002200d3602000b2002280200200741306c6a220d41043a0000200d20022f002d3b0001200d201136000c200d200e360008200d200f360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012113200741016a21070b200141286a280200211420012802242115024002402001412c6a28020022110d002012210c0c010b0240024020072012460d002012210c0c010b41000d0341000d032012410174220d201241016a220c200d200c4b1b220cad42307ea7220d4100480d030240024020120d00200d102a210d0c010b2002280200201241306c200d102e210d0b200d450d022002200d3602000b2002280200200741306c6a220d41053a0000200d20022f002d3b0001200d201136000c200d2014360008200d2015360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012110200741016a21070b200141346a28020021162001280230211702400240200141386a28020022120d00410021180c010b02402007200c470d0041000d0341000d03200c410174220d200c41016a2211200d20114b1b2211ad42307ea7220d4100480d0302400240200c0d00200d102a210d0c010b2002280200200c41306c200d102e210d0b200d450d022002200d3602002011210c0b2002280200200741306c6a220d41063a0000200d20022f002d3b0001200d201236000c200d2016360008200d2017360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012118200741016a21070b200141c0006a2802002119200128023c211a4101211b02400240200141c4006a280200221c0d00200c21124101211d0c010b024002402007200c460d00200c21120c010b41000d0341000d03200c410174220d200c41016a2212200d20124b1b2212ad42307ea7220d4100480d0302400240200c0d00200d102a210d0c010b2002280200200c41306c200d102e210d0b200d450d022002200d3602000b2002280200200741306c6a220d41073a0000200d20022f002d3b0001200d201c36000c200d2019360008200d201a360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a21074100211d0b200141cc006a280200211e2001280248211f02400240200141d0006a28020022200d00201221110c010b0240024020072012460d00201221110c010b41000d0341000d032012410174220d201241016a220c200d200c4b1b2211ad42307ea7220d4100480d030240024020120d00200d102a210d0c010b2002280200201241306c200d102e210d0b200d450d022002200d3602000b2002280200200741306c6a220d41083a0000200d20022f002d3b0001200d202036000c200d201e360008200d201f360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a200241046a41086a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a21074100211b0b410121210240024020012802544101460d002011210c0c010b200141d8006a28020021120240024020072011460d002011210c0c010b41000d0341000d032011410174220d201141016a220c200d200c4b1b220cad42307ea7220d4100480d030240024020110d00200d102a210d0c010b2002280200201141306c200d102e210d0b200d450d022002200d3602000b2002280200200741306c6a220d41093a0000200d20022f002d3b0001200d2012360204200d2002290204370208200d41036a2002412f6a2d00003a0000200d41106a2002410c6a290200370200200d41186a200241046a41106a290200370200200d41206a200241046a41186a290200370200200d41286a200241046a41206a290200370200200741016a21070b200141e0006a2802002122200128025c212302400240200141e4006a28020022240d00200c21120c010b024002402007200c460d00200c21120c010b41000d0341000d03200c410174220d200c41016a2212200d20124b1b2212ad42307ea7220d4100480d0302400240200c0d00200d102a210d0c010b2002280200200c41306c200d102e210d0b200d450d022002200d3602000b2002280200200741306c6a220d410a3a0000200d20022f002d3b0001200d202436000c200d2022360008200d2023360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021210b200141ec006a2802002125200128026821264101212702400240200141f0006a28020022280d0020122111410121290c010b0240024020072012460d00201221110c010b41000d0341000d032012410174220d201241016a220c200d200c4b1b2211ad42307ea7220d4100480d030240024020120d00200d102a210d0c010b2002280200201241306c200d102e210d0b200d450d022002200d3602000b2002280200200741306c6a220d410c3a0000200d20022f002d3b0001200d202836000c200d2025360008200d2026360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021290b200141f8006a280200212a2001280274212b02400240200141fc006a280200222c0d002011210c0c010b0240024020072011460d002011210c0c010b41000d0341000d032011410174220d201141016a220c200d200c4b1b220cad42307ea7220d4100480d030240024020110d00200d102a210d0c010b2002280200201141306c200d102e210d0b200d450d022002200d3602000b2002280200200741306c6a220d410d3a0000200d20022f002d3b0001200d202c36000c200d202a360008200d202b360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021270b20014184016a2802002111200128028001210d02400240200c20076b20014188016a28020041306c222d41306d2212490d00200228020021010c010b200720126a22012007490d02200c410174222e2001202e20014b1b222ead42307e222f422088a70d02202fa722014100480d0202400240200c0d002001102a21010c010b2002280200200c41306c2001102e21010b2001450d0120022001360200202e210c0b2001200741306c6a200d202d10db051a200720126a210702402011450d00200d102c0b2000200136020820004280c2cdeb16370200200041106a20073602002000410c6a200c3602002027450d020240202c450d00202b202c411c6c6a2112202b21000340024020002802042201450d0002402000410c6a2802002207450d00200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102c200c280200210d0b200d102c0b200141106a2101200741706a22070d000b0b200041086a280200450d002000280204102c0b2000411c6a21010240200041146a280200450d002000280210102c0b2001210020012012470d000b0b202a450d02202b102c0c020b1033000b1035000b02402029450d0002402028450d002026202841186c6a21122026210003400240200041046a280200450d002000280200102c0b0240200041146a2802002207450d00200028020c2101200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102c200c280200210d0b200d102c0b200141106a2101200741706a22070d000b0b200041186a21010240200041106a280200450d00200028020c102c0b2001210020012012470d000b0b2025450d002026102c0b02402021450d0002402024450d0020232024411c6c6a2112202321000340024020002802042201450d0002402000410c6a2802002207450d00200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102c200c280200210d0b200d102c0b200141106a2101200741706a22070d000b0b200041086a280200450d002000280204102c0b2000411c6a21010240200041146a280200450d002000280210102c0b2001210020012012470d000b0b2022450d002023102c0b0240201b450d0002402020450d00202041146c2107201f210103400240200141046a280200450d002001280200102c0b200141146a21012007416c6a22070d000b0b201e450d00201f102c0b0240201d450d000240201c450d00201a201c4104746a2112201a21000340024020002802082207450d0020002802002101200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102c200c280200210d0b200d102c0b200141106a2101200741706a22070d000b0b200041106a21010240200041046a280200450d002000280200102c0b2001210020012012470d000b0b2019450d00201a102c0b02402016410047201841017371450d002017102c0b02402014410047201041017371450d002015102c0b0240200e410047201341017371450d00200f102c0b02402005450d000240200b450d00200b41286c2107200a210103400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101200741586a22070d000b0b2009450d00200a102c0b02402008450d0002402006450d00200641047421072004210103400240200141046a280200450d002001280200102c0b200141106a2101200741706a22070d000b0b2003450d002004102c0b200241306a24000bea0203037f017e027f410121020240024002400240200041086a2802002203417f6a220420034f0d00200420034b0d00200028020020044104746a220329020421052003200141016aad3702042005a721012005422088a721030240200041086a28020022024101460d002002450d0220002802002002417e6a4104746a22022802042001470d002002200228020820036a36020841000f0b410021022003450d000240200041146a2802002204200041106a280200470d00200441016a22062004490d04200441017422072006200720064b1b220641ffffffff01712006470d04200641037422074100480d040240024020040d002007102a21040c010b200028020c20044103742007102e21040b2004450d032000200436020c200041106a2006360200200028021421040b200028020c20044103746a22042003360204200420013602002000200028021441016a3602140b20020f0b418e87c600413f1054000b1033000b1035000b911302147f027e23004180026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d0020002001109b052003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200b200b417f6a220d2000200b4103746a280200220e2000200d4103746a280200220f4922101b2211200b41016a2212200d200b20101b200020124103746a280200220b200f200e20101b220d49220f1b200b200d200f1b200020114103746a2802004922131b210b200c200c417f6a220d2000200c4103746a28020022112000200d4103746a280200221249220e1b2214200c4101722206200d200c200e1b200020064103746a280200220c20122011200e1b220d4922111b200c200d20111b200020144103746a2802004922141b210c200a200a417f6a22122000200a4103746a2802002206200020124103746a280200221549220d1b2216200a41016a22172012200a200d1b200020174103746a280200220a20152006200d1b22064922121b200a200620121b200020164103746a2802004922061b210a41024101200d1b200d20121b20066a200e6a20116a20146a20106a200f6a20136a210d0b200d2000200c4103746a280200220e2000200a4103746a280200220f4922106a2000200b4103746a280200220d200f200e20101b221149220f6a210e200d2011200f1b2000200c200a20101b220d4103746a280200490d01200b200a200c20101b200f1b210d0c020b2000200110b5050c0f0b200e41016a220e410c490d0002402001410176220b450d00200020014103746a41786a210a2000210c0340200c2902002118200c200a290200370200200a2018370200200c41086a210c200a41786a210a200b417f6a220b0d000b0b2001200d417f736a210d4101210a0c010b200e45210a0b0240200a452009724101710d002000200110b6050d0d0b2002450d02200d20014f0d01024020022802002000200d4103746a220a2802004f0d0020002108200121070c040b200029020021182000200a290200370200200a2018370200200041786a210f200041086a211120002902002218a721104100210c2001210b03400240200c200b417f6a220d4f0d002011200c4103746a210a0340200a28020020104b0d01200a41086a210a200d200c41016a220c470d000b200d210c0b200f200b4103746a210a02400340200c200b417f6a220b4f0d01200a280200210d200a41786a220e210a200d20104b0d000b2011200c4103746a220a2902002119200a200e41086a220d290200370200200d2019370200200c41016a210c0c010b0b2000201837020002402001200c41016a220a490d002000200a4103746a21002001200a6b220141154f0d010c0c0b0b200a20011047000b41c4ffc500200d20011038000b2007450d010b200d20074f0d012008290200211820082008200d4103746a220a290200370200200a2018370200200841086a210e20082902002219a72111410021142007417f6a2210450d02200e210a0340200a28020020114f0d03200a41086a210a2010201441016a2214470d000b201021140c020b41f8fec500410041001038000b4188ffc500200d20071038000b200820074103746a210c2010210b02400340200c210d200b220a20144d22060d01200a417f6a210b200d41786a220c28020020114f0d000b0b0240200a2014490d002010200a490d0241800121054100210b410021014100210c4100210f4180012109200e20144103746a2215211003400240200d20106b220a4187104b22130d00200a410376220a41807f6a200a2001200b49200f200c49220e7222001b210a02402000450d002009200a200e1b2109200a2005200e1b21050c010b200a200a41017622096b21050b0240200f200c470d00024020090d002004220c210f0c010b4100210a2004220f210c2010210e0340200c200a3a0000200c200e28020020114f6a210c200e41086a210e2009200a41016a220a470d000b0b02402001200b470d00024020050d0020044180016a220b21010c010b200d41786a210a4100210e20044180016a2201210b0340200b200e3a0000200b200a2802002011496a210b200a41786a210a2005200e41016a220e470d000b0b0240200b20016b220a200c200f6b220e200e200a4b1b2212450d002010200f2d00004103746a220a2902002118200a200d20012d0000417f734103746a290200370200024020124101460d004100210a0340200d2001200a6a220e2d0000417f734103746a2010200f200a6a41016a22002d00004103746a290200370200201020002d00004103746a200d200e41016a2d0000417f734103746a290200370200200a41026a210e200a41016a2200210a200e2012490d000b200120006a2101200f20006a210f0b200d20012d0000417f734103746a2018370200200141016a2101200f41016a210f0b200d20054103746b200d2001200b461b210d201020094103746a2010200f200c461b211020130d000b02400240200f200c4f0d00200d210a03402010200c417f6a220c2d00004103746a220b2902002118200b200a41786a220a290200370200200a2018370200200f200c490d000c020b0b2010210a2001200b4f0d000340200a2902002118200a200d200b417f6a220b2d0000417f734103746a220c290200370200200c2018370200200a41086a210a2001200b490d000b0b200820193702002007200a20156b41037620146a22014d0d032008200820014103746a220a290200370200200a2019370200200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41086a2100024002402001200c417f6a220c490d002000200c200a200310fc04200821000c010b200820012002200310fc04200a2102200c21010b200b200d4f2105200141154f0d010c050b0b2014200a1047000b200a2010103f000b4188ffc500200120071038000b4198ffc500411c41b4ffc5001036000b20014102490d00200041786a21104100210e4101210b0340200b410374210c200b417f6a210a200b41016a210b02402000200c6a220d2802002000200a4103746a220f2802004f0d00200d2902002118200d200f2902003702000240200a450d00200e210c2010210a200d41706a2802002018a7220d4d0d00024002400340200a41086a200a290200370200200c4101460d01200c417f6a210c200a41786a220a280200200d4b0d000c020b0b4100210c0b2000200c4103746a210f0b200f20183702000b200e41016a210e201041086a2110200b2001470d000b0b20044180026a24000bd20402097f017e230041306b22022400200241106a2203200141246a290200370300200241086a22042001411c6a29020037030020022001290214370300200241186a41106a2205200141106a280200360200200241186a41086a2206200141086a290200370300200220012902003703182000200241186a10f9042107024002400240200041206a28020022082000411c6a280200470d00200841016a22092008490d022008410174220a2009200a20094b1b220941ffffffff03712009470d022009410274220a4100480d020240024020080d00200a102a21080c010b20002802182008410274200a102e21080b2008450d01200020083602182000411c6a2009360200200028022021080b200028021820084102746a20073602002000200028022041016a3602202005200329030037030020062004290300370300200220022903003703180240200041f0006a22032802002208200041ec006a280200470d00200841016a22042008490d02200841017422052004200520044b1b2204ad42187e220b422088a70d02200ba722054100480d020240024020080d002005102a21080c010b2000280268200841186c2005102e21080b2008450d0120002008360268200041ec006a2004360200200041f0006a28020021080b2000280268200841186c6a22082002290318370200200841106a200241186a41106a290300370200200841086a200241186a41086a29030037020020032003280200220841016a360200024020012d002c450d0020004101360254200041d8006a20083602000b200241306a24000f0b1033000b1035000bb47805077f017e217f037e157f230022032104200341e0086b41607122032400024002400240024002404110102a2205450d00200541063a00004120102a2206450d00200641063a001020064100360204200620032f00d0053b00012006412d3a0000200641036a200341d2056a2d00003a0000024020052d00004109470d0002402005280204220728020441ffffffff0371450d002007280200102c200528020421070b2007102c0b2005102c200141106a28020041306c2105200128020841546a210702400340024020050d004110102a2207450d0320074180023b010c200742828080802037020420072006360200200720032f01b0033b010e0240200128021022052001410c6a280200470d00200541016a22082005490d08200541017422092008200920084b1b2208ad42307e220a422088a70d08200aa722094100480d080240024020050d002009102a21050c010b2001280208200541306c2009102e21050b2005450d04200120053602082001410c6a2008360200200128021021050b2001280208200541306c6a220520032f00c0043b0001200541073a0000200542818080801037000820052007360004200520032902d005370210200541036a200341c2046a2d00003a0000200541186a200341d8056a290200370200200541206a200341e0056a290200370200200541286a200341d0056a41186a2902003702002001200128021041016a220b3602104100210c0c020b200541506a21052007412c6a2108200741306a2209210720082d00004107470d000b200320032f01b0033b01d0050240200941086a22072802002205200941046a280200470d00200541016a22082005490d062005410174220d2008200d20084b1b220841ffffffff00712008470d062008410474220d4100480d060240024020050d00200d102a21050c010b20092802002005410474200d102e21050b2005450d0220092005360200200941046a2008360200200941086a28020021050b200928020020054104746a22054180023b010c200542828080802037020420052006360200200520032f01d0053b010e2007200728020041016a360200200341306a200910f4042003280234417f6a210c2001280210210b0b200b41306c21052001280208220e41546a210702400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200b41306c2105200e41546a210702400340410021092005450d01200541506a21052007412c6a2106200741306a220d210720062d00004103470d000b200d41086a2802002205450d00200541286c2107200d28020041186a2105410021090340200920052d0000456a2109200541286a2105200741586a22070d000b0b200b41306c2105200e415c6a2107024003404100210f024020050d00410021050c020b200541506a2105200741246a2106200741306a220d210720062d00004104470d000b200d28020021050b200341003602c00402400240200520096a220b0d0041042110410021110c010b0240024002402008450d00200342003703d005410021050c010b200341d0056a4100200110ab0520032802d405210520032802d0054101470d00200341d8056a290300210a024020032802c0042207450d0020032802c404450d002007102c0b2003200a3702c404200320053602c00441002111410421104100210f0c010b4104102a2210450d022010200536020002400240200b4102490d000240024020084102490d00200342003703d0054100210d0c010b200341d0056a4101200110ab0520032802d405210d20032802d0054101470d00200341d8056a290300210a024020032802c004450d0020032802c404450d0020032802c004102c0b2003200a3702c4042003200d3602c0040c010b410221064104210741012109410121110340200941016a2105024020092011470d0020062005200620054b1b221141ffffffff03712011470d0a2011410274220e4100480d0a20102007200e102e2210450d060b201020076a200d360200024002402005200b4f0d000240200820054d0d00200342003703d0054100210d0c020b200341d0056a2005200110ab0520032802d405210d20032802d0054101470d0120032903d805210a024020032802c004450d0020032802c404450d0020032802c004102c0b200941016a210f2003200a3702c4042003200d3602c0040c040b200941016a210f0c030b200641026a2106200741046a2107200521090c000b0b4101210f410121110b20032802c00421050b2005450d0020032902c404210a02402011450d002010102c0b2000200536020420004101360200200041086a200a3702000c030b024020012802102205450d0020012802082212200541306c6a2113200341c0046a41146a2114200341c0076a2115200341f4056a211620034184066a211720034194066a2118200341a4066a2119200341b4066a211a200341c4066a211b200341d4066a211c200341e4066a211d200341f4066a211e20034184076a211f20034194076a2120200341a4076a2121200341b4076a2122024002400340024020122d0000410c470d00201228020c2205450d0020122802042206200541186c6a212303400240200641146a220e2802002205450d002006410c6a212441002109024002400340200920054f0d014101210502402024280200200941047422256a22072d0000410b470d002003200741046a22073602a00220072802002207200f4f0d03201020074102746a2802002208450d002003200c3602b407200341133a00b007200341d7003a00a00720032008360294072003412d3a0090072003200c36028407200341123a008007200320073602f4062003410b3a00f006200341063a00e006200341003a00d00620034184083b01c006200341373a00b006200320023602a4062003412d3a00a0062003200c36029406200341123a0090062003200c36028406200341133a008006200341d6003a00f005200320083602e4052003412d3a00e0052003200c3602d405200341123a00d005200e280200222620094d0d09200e2009360200200628020c2105200320153602d804200320243602d0042003200520256a220b41106a220d3602c8042003200941016a22273602c0042003202620276b22283602c40420032005202741047422296a222a3602cc042003200341d0056a3602d404200d21050240200b2d0000220841ac01460d004100210502400340200b20056a21070240200841ff01714109470d000240200741046a280200220828020441ffffffff0371450d002008280200102c0b2008102c0b2005450d012003200741206a3602c804200541106a2105200741106a2d0000220841ac01470d000b200b20056a41106a21050c010b200741106a21050b02402005202a460d0003402003200541106a22073602c80420052d0000220841ac01460d01024020084109470d000240200541046a280200220528020441ffffffff0371450d002005280200102c0b2005102c0b20072105200d2007470d000b0b02400240024002402028450d000240202720062802142205470d00200341d0056a21052015210b0c030b2025200541047422056b2108200628020c20056a2107200341d0056a21052015210d0340024002402005200d470d00410021050c010b2003200541106a3602d4040b200341b0036a200510ac0520032d00b00341ac01460d04200720032903b003370300200741086a200341b0036a41086a2903003703002006200628021441016a3602142008450d02200741106a2107200841706a210820032802d804210d20032802d40421050c000b0b2024201410ad050c020b20032802d804210b20032802d40421050b0240200b20056b2207450d000240024020032802d004220d41046a222a280200222520266b20074104762208490d00200d28020021070c010b202620086a22072026490d12202541017422262007202620074b1b222641ffffffff00712026470d12202641047422074100480d120240024020250d002007102a21070c010b200d28020020254104742007102e21070b2007450d0e200d2007360200202a20263602000b2007202720086a22254104746a200720296a202841047410dc051a200320253602c0042025200d2802082207460d00200920086a410474200741047422076b2108200d28020020076a21070340024002402005200b470d00410021050c010b2003200541106a3602d4040b200341b0036a200510ac0520032d00b00341ac01460d02200720032903b003370300200741086a200341b0036a41086a290300370300200d200d28020841016a3602082008450d01200741106a2107200841706a210820032802d804210b20032802d40421050c000b0b200341003602b803200342083703b003200341b0036a201410ad0520032802b003222820032802b8032207410474220b6a210d20032802b40321292028210502402007450d000240024020032802d004222541046a222a280200220520032802c404222720032802c00422076a22266b200b4104752208490d00202528020021050c010b202620086a222b2026490d1220054101742226202b2026202b4b1b222641ffffffff00712026470d122026410474222b4100480d120240024020050d00202b102a21050c010b20252802002005410474202b102e21050b2005450d0e20252005360200202a20263602000b2005200720086a220841047422266a200520074104746a202741047410dc051a200320083602c00420282105200820252802082207460d002025280200220520266a212a200520074104746a21082028210703400240200b0d00200d21050c020b200341b0036a41026a2205200741036a2d00003a0000200320072f00013b01b003024020072d0000222741ac01470d00200741106a21050c020b200741046a2802002126200741086a290300210a200820273a0000200841086a200a370300200841046a202636020020032f01b0032127200841036a20052d00003a0000200841016a20273b00002025202528020841016a360208200b41706a210b200741106a22052107200841106a2208202a470d000b0b02402005200d460d0003400240024020052d000022074109460d00200741ac01470d010c030b0240200541046a280200220728020441ffffffff0371450d002007280200102c0b2007102c0b200541106a2205200d470d000b0b2029450d002028102c0b024020032802c804220520032802cc04220d460d0003402003200541106a22073602c80420052d0000220841ac01460d01024020084109470d000240200541046a280200220528020441ffffffff0371450d002005280200102c0b2005102c0b20072105200d2007470d000b0b024020032802c4042205450d00024020032802c004220d20032802d004220b41086a22082802002207460d00200b280200220b20074104746a200b200d4104746a200541047410dc051a0b2008200520076a3602000b024020032d00d0054109470d00024020032802d405220528020441ffffffff0371450d002005280200102c20032802d40521050b2005102c0b024020032d00e0054109470d000240200341d0056a41146a280200220528020441ffffffff0371450d002005280200102c20032802e40521050b2005102c0b024020032d00f0054109470d0002402016280200220528020441ffffffff0371450d002005280200102c20032802f40521050b2005102c0b024020032d0080064109470d0002402017280200220528020441ffffffff0371450d002005280200102c20032802840621050b2005102c0b024020032d0090064109470d0002402018280200220528020441ffffffff0371450d002005280200102c20032802940621050b2005102c0b024020032d00a0064109470d0002402019280200220528020441ffffffff0371450d002005280200102c20032802a40621050b2005102c0b024020032d00b0064109470d000240201a280200220528020441ffffffff0371450d002005280200102c20032802b40621050b2005102c0b024020032d00c0064109470d000240201b280200220528020441ffffffff0371450d002005280200102c20032802c40621050b2005102c0b024020032d00d0064109470d000240201c280200220528020441ffffffff0371450d002005280200102c20032802d40621050b2005102c0b024020032d00e0064109470d000240201d280200220528020441ffffffff0371450d002005280200102c20032802e40621050b2005102c0b024020032d00f0064109470d000240201e280200220528020441ffffffff0371450d002005280200102c20032802f40621050b2005102c0b024020032d0080074109470d000240201f280200220528020441ffffffff0371450d002005280200102c20032802840721050b2005102c0b024020032d0090074109470d0002402020280200220528020441ffffffff0371450d002005280200102c20032802940721050b2005102c0b024020032d00a0074109470d0002402021280200220528020441ffffffff0371450d002005280200102c20032802a40721050b2005102c0b024020032d00b0074109470d0002402022280200220528020441ffffffff0371450d002005280200102c20032802b40721050b2005102c0b410f21050b200520096a2209200e2802002205490d000c030b0b41a8f8c500200920051038000b200341013602e405200342013702d405200341b8f8c5003602d005200341313602b4032003200341b0036a3602e0052003200341a0026a3602b003200341c0046a200341d0056a103720032802c00422050d040b200641186a22062023470d000b0b201241306a22122013470d000c030b0b20032902c404210a2000200536020420004101360200200041086a200a3702002011450d042010102c0c040b41dafec500411c41acfec5001036000b200341386a41106a200141106a280200221e360200200341386a41086a200141086a290200220a37030020032001290200370338201e41306c2105200aa7222041546a210702400340024020050d00410021050c020b200541506a21052007412c6a2108200741306a2209210720082d00004108470d000b200341286a200910f40420032802282105200328022c21070b2007410020051b210b201e41306c2107202041546a21082005410420051b210502400340024020070d00410021090c020b200741506a21072008412c6a2109200841306a2206210820092d0000410a470d000b200341206a200610f40420032802202109200328022421070b2007410020091b210e201e41306c2107202041546a21082009410420091b212a02400340024020070d004100210d0c020b200741506a21072008412c6a2109200841306a2206210820092d00004109470d000b200628020021084101210d0b20034200370254200341d0e1c1003602502005200b41146c6a2107202a200e411c6c6a211f200341c0046a410272221a41266a2121201a41206a2122201a41186a212b201a41106a2112201a41086a2101200341c0046a41286a21134104212341002115410021284100211d41002118410021170240024002400240410041ff01710e03000102000b410021090c020b410221090c010b410121090b02400240024003400240024002400240024002400240024002400240024002400240024002400240024020090e03000104040b0240201841ff01710e03020300020b201d4101470d06410021090c090b4100212941002114200d0d0b0c110b0240034020072005460d012005410c6a2109200541146a2206210520092802000d000b20062105200d2129200821142006417c6a28020021080c0b0b201d4101470d02410021090c090b0340024020072005470d00410221170c0c0b2005410c6a2109200541146a2206210520092802000d000b20062105200d2129200821142006417c6a28020021080c090b024002400240201841ff01710e03010200010b201d4101470d05410021090c060b0240034020072005460d012005410c6a2109200541146a2206210520092802000d000b20062105200d2129200821142006417c6a28020021080c0a0b201d4101470d02410021090c070b034020052007460d0f2005410c6a2109200541146a2206210520092802000d000b20062105200d2129200821142006417c6a28020021080c080b410121090c060b410121090c040b410121090c020b410121090b0340024002400240024020090e020001010b2027201c470d01410121090c030b202a201f460d0c200341186a202a10a40520032802182227450d0c202a411c6a212a2027200328021c4102746a211c0c010b2027450d0b202728020021094101211d202741046a2127200d212920082114200921080c050b410021090c000b0b0340024002400240024020090e020001010b2027201c470d014101211d410121090c030b0240202a201f470d00410221170c070b200341086a202a10a405202a411c6a212a0240200328020822090d00410221170c070b2009200328020c4102746a211c200921270c010b202741046a2109024020270d00410221174101211d200921270c060b202728020021064101211d20092127200d212920082114200621080c040b410021090c000b0b0340024002400240024020090e020001010b2027201c470d01410121090c030b202a201f460d0a200341106a202a10a40520032802102227450d0a202a411c6a212a202720032802144102746a211c0c010b2027450d0920272802002109410221184101211d202741046a2127200d212920082114200921080c030b410021090c000b0b0340024002400240024020090e020001010b2027201c470d014101211d410121090c030b410221180240202a201f470d00410221170c050b2003202a10a405202a411c6a212a0240200328020022090d00410221170c050b200920032802044102746a211c200921270c010b202741046a2109024020270d00410221184101211d20092127410221170c040b20272802002106410221184101211d20092127200d212920082114200621080c020b410021090c000b0b2003200836025c02402008200f490d00200341013602e405200342023702d405200341c8fcc5003602d005200341013602b4032003200341b0036a3602e0052003200341dc006a3602b003200341c0046a200341d0056a103720032902c404220a422088a7210820032802c0042124200aa7211b0c050b0240201020084102746a2802002209450d000240024020282015460d0020152116202821150c010b201541016a22062015490d0d2015410174220d2006200d20064b1b221641ffffffff03712016470d0d201641027422064100480d0d0240024020150d002006102a21230c010b202320154102742006102e21230b2023450d090b202320154102746a2008360200200341d0056a200328025c220b200341386a10af0520032802d805211b20032802d4052124024020032802d00522194101470d0020032802dc052108201621150c060b20242802082208417f4c0d072024280200210620242d000c210d0240024020080d004101210e0c010b2008102a220e450d090b200e2006200810db0521062003200836026820032008360264200320063602602003200d3a006c200320242d000d3a006d200341003602702003200328025c3602782003200936027c024002402003280250220941d0e1c100460d00200328025421260c010b2021420037010020224200370100202b42003701002012420037010020014200370100201a4200370100200341d0056a410041e00210da051a419403102a2209450d094100212620094100360200200920032903c0043702042009410c6a200341c0046a41086a290300370200200941146a200341c0046a41106a2903003702002009411c6a200341c0046a41186a290300370200200941246a200341c0046a41206a2903003702002009412c6a2013290300370200200941346a200341d0056a41e00210db051a20034100360254200320093602500b202841016a21280240034020092f010622154102742125410021084114210d417f210602400340024020252008470d00201521060c020b200920086a210e200641016a2106200d41206a210d200841046a21080240417f200e41086a280200220e200b47200e200b4b1b41016a0e03020001020b0b2009200d6a220828020421062008280200210d20082003290360370200200841186a200329037837020020082802102109200820032903703702102008200329036837020820094102460d022006450d02200d102c0c020b02402026450d002026417f6a2126200920064102746a4194036a28020021090c010b0b2003200328025841016a3602582003290378210a2003290370212c2003290368212d2003290360212e0240024020092f0106220d410b490d002021420037010020224200370100202b42003701002012420037010020014200370100201a4200370100200341d0056a410041e00210da051a419403102a2208450d0b20084100360200200820032903c0043702042008410c6a200341c0046a41086a222f290300370200200841146a200341c0046a41106a22302903003702002008411c6a200341c0046a41186a2231290300370200200841246a200341c0046a41206a22322903003702002008412c6a2013290300370200200841346a200341d0056a41e00210db05210e200341d0056a41086a2226200941fc016a290200370300200341d0056a41106a221520094184026a290200370300200341d0056a41186a22332009418c026a290200370300200320092902f4013703d00520092802202134200841086a200941246a20092f010641796a220d41027410db052125200e20094194026a200d41057410db05210e200941063b01062008200d3b01062031203329030037030020302015290300370300202f2026290300370300200320032903d0053703c0040240024020064107490d0020252006417a6a22354102746a2025200641796a22364102746a2206200d41ffff037120366b41027410dc051a2006200b360200200e20354105746a200e20364105746a2206200841066a220d2f010020366b41057410dc051a200641186a200a3702002006202c3702102006202d3702082006202e370200200d2f0100210e0c010b200941086a220d200641016a22254102746a200d20064102746a2236200941066a220d2f0100220e20066b223541027410dc051a2036200b360200200941346a220b20254105746a200b20064105746a2206203541057410dc051a200641186a200a3702002006202c3702102006202d3702082006202e3702000b200d200e41016a3b0100200341b0036a41186a22372031290300220a370300200341b0036a41106a22382030290300222c370300200341b0036a41086a2239202f290300222d37030020034190016a41186a223a200a37030020034190016a41106a223b202c37030020034190016a41086a223c202d370300200320032903c004220a3703b0032003200a3703900102402009280200220e0d00200821060c020b20092f010421362008213d0340200341a0026a41186a223e203a290300370300200341a0026a41106a223f203b290300370300200341a0026a41086a2240203c29030037030020032003290390013703a002203641ffff0371210b024002400240200e2f01062208410b490d002021420037010020224200370100202b42003701002012420037010020014200370100201a42003701002039202f2903003703002038203029030037030020372031290300370300200341b0036a41206a22082032290300370300200341b0036a41286a22092013290300370300200320032903c0043703b003200341d0056a410041900310da051a41c403102a2206450d0f20064100360200200620032903b0033702042006410c6a2039290300370200200641146a20382903003702002006411c6a2037290300370200200641246a20082903003702002006412c6a2009290300370200200641346a200341d0056a41900310db052109200e41206a28020021412033200e418c026a2902003703002015200e4184026a2902003703002026200e41fc016a2902003703002003200e41f4016a2902003703d005200641086a200e41246a200e2f0106220d41796a220841027410db0521422009200e4194026a200841057410db05214320064194036a200e41b0036a200d417a6a222541027410db052135200e41063b0106200620083b010602402025450d00410021082035210903402009280200220d20083b0104200d2006360200200941046a21092025200841016a2208470d000b0b20312033290300220a37030020302015290300222c370300202f2026290300222d370300200320032903d005222e3703c0042033200a3703002015202c3703002026202d3703002003202e3703d005203641ffff037122094107490d012042200b417a6a220d41027422256a2042200b41796a22084102746a220920062f010620086b41027410dc051a200920343602002043200d4105746a204320084105746a220920062f010620086b41057410dc051a200941186a203e290300370200200941106a203f290300370200200941086a2040290300370200200920032903a002370200200620062f010641016a22093b0106200b410274223620356a416c6a203520256a2225200941ffff0371220b200d6b41027410dc051a2025203d360200200b200d490d02200620366a41fc026a210903402009280200220d200841016a22083b0104200d2006360200200941046a21092008200b490d000c030b0b200e41086a2209200b41016a2206410274220d6a2009200b41027422256a22092008200b6b222641027410dc051a20092034360200200e41346a220920064105746a2009200b4105746a2209202641057410dc051a200941186a203e290300370200200941106a203f290300370200200941086a2040290300370200200920032903a002370200200e200841016a22083b01062025200e4194036a22096a41086a2009200d6a2209200841ffff0371220d20066b41027410dc051a2009203d360200200b200d4f0d05200e2006417f6a22084102746a4198036a2109034020092802002206200841016a22083b01042006200e360200200941046a21092008200d490d000c060b0b200e41086a2208200b41016a2225410274220d6a2008200b41027422366a2208200e2f01062235200b6b224241027410dc051a20082034360200200e41346a220820254105746a2008200b4105746a2208204241057410dc051a200841186a203e290300370200200841106a203f290300370200200841086a2040290300370200200820032903a002370200200e203541016a22083b01062036200e4194036a22356a41086a2035200d6a2235200841ffff0371220d20256b41027410dc051a2035203d3602002009200d4f0d00200e20366a4198036a2108034020082802002209200b41016a220b3b01042009200e360200200841046a2108200d200b470d000b0b203a2033290300370300203b2015290300370300203c2026290300370300200320032903d005370390010240200e28020022080d00204121340c030b200e2f010421362008210e204121342006213d0c000b0b200941086a2208200641016a220e4102746a200820064102746a2208200d20066b222541027410dc051a2008200b360200200941346a2208200e4105746a200820064105746a2208202541057410dc051a200841186a200a3702002008202c3702102008202d3702082008202e3702002009200d41016a3b01060c010b2021420037010020224200370100202b42003701002012420037010020014200370100201a42003701002039202f2903003703002038203029030037030020372031290300370300200341b0036a41206a22092032290300370300200341b0036a41286a220d2013290300370300200320032903c0043703b003200341d0056a410041900310da051a41c403102a2208450d0920084100360200200820032903b0033702042008410c6a2039290300370200200841146a20382903003702002008411c6a2037290300370200200841246a20092903003702002008412c6a200d290300370200200841346a200341d0056a41900310db05210b20082003280250220936029403200320083602502003200328025441016a36025420092008360200200941003b0104200b20082f0106220d4105746a2209200329039001370200200941186a203a290300370200200941106a203b290300370200200941086a203c2903003702002008200d4102746a41086a203436020020084194036a200d41016a22094102746a2006360200200820093b0106200620093b0104200620083602000b02402019450d00201b450d002024102c0b201621150b2029210d20142108201741ff01710e03010200010b410121090c020b410021090c010b410221090c000b0b20032802502003280254200328025810b00502402015450d002023102c0b0240201e450d00201e41306c2107202021050340200510b105200541306a2105200741506a22070d000b0b0240200341c4006a280200450d002020102c0b2000202436020420004101360200200041086a2008ad422086201bad843702002011450d052010102c200424000f0b2003280248220d41306c21052003280240220b41546a210720032802582134200328025421272003280250212602400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200d41306c2105200b415c6a210702400340024020050d00410021050c020b200541506a2105200741246a2109200741306a2206210720092d00004104470d000b200628020021050b200341d0056a41106a2229200341386a41106a280200360200200341d0056a41086a200341386a41086a290300370300200320032903383703d00520034190016a200341d0056a10f8042028450d02202320284102746a2114200520086a2124200341d0056a41e0016a2116200341d0056a41d0016a2117200341d0056a41c0016a2118200341d0056a41b0016a2119200341d0056a41a0016a211a200341d0056a4190016a211b200341d0056a4180016a211c200341d0056a41f0006a211d200341d0056a41e0006a211e200341d0056a41d0006a211f200341d0056a41c0006a2120200341d0056a41306a2121200341d0056a41206a2122200341c7046a212b20034184066a211220034194066a2101200341a4066a2113200341b4066a2133200341c4066a2136200341d4066a2135200341e4066a212f200341f4066a213020034184076a213120034194076a2137200341a4076a2138200341b4076a21392023212803402028220541046a212820052802002106202621082027210e034020082f0106222a410274210b41002109417f210741002105024003400240200b2005470d00202a21070c020b200820056a210d200741016a2107200941206a2109200541046a21050240417f200d41086a280200220d200647200d20064b1b41016a0e03020001020b0b200820096a220e412c6a2802002107200e41306a28020021052003200c3602b407200341133a00b007200341d7003a00a00720032005360294072003412d3a0090072003200c36028407200341123a008007200320073602f4062003410b3a00f006200341063a00e006200341003a00d00620034184083b01c006200341373a00b006200320023602a4062003412d3a00a0062003200c36029406200341123a0090062003200c36028406200341133a008006200341d6003a00f005200320053602e4052003412d3a00e0052003200c3602d405200341123a00d005200e411c6a222a280200220d41106a220541ffffffff00712005470d0320054104742207417f4c0d030240024020070d00410821060c010b2007102a2206450d05202a280200210d0b02400240200d0d00410021080c010b41002109410021070340024020072005470d00200541016a22082005490d0b2005410174220b2008200b20084b1b220841ffffffff00712008470d0b2008410474220b4100480d0b0240024020050d00200b102a21060c010b20062005410474200b102e21060b2006450d07200821050b200620096a2208410f3a0000200841046a2007360200200841016a20032f01b0033b0000200841036a200341b0036a41026a2d00003a0000200941106a2109200741016a22082107200d2008470d000b0b02400240200520086b410e4d0d00200521090c010b2008410f6a22072008490d09200541017422092007200920074b1b220941ffffffff00712009470d09200941047422074100480d090240024020050d002007102a21060c010b200620054104742007102e21060b2006450d050b200341c0046a200341d0056a10b205200620084104746a220520032903c004370300200541086a200341c0046a41086a2207290300370300200341c0046a202910b205200541186a2007290300370300200520032903c004370310200341c0046a202210b205200541286a2007290300370300200541206a20032903c004370300200341c0046a202110b205200541386a2007290300370300200541306a20032903c004370300200341c0046a202010b205200541c8006a2007290300370300200541c0006a20032903c004370300200341c0046a201f10b205200541d8006a2007290300370300200541d0006a20032903c004370300200341c0046a201e10b205200541e8006a2007290300370300200541e0006a20032903c004370300200341c0046a201d10b205200541f8006a2007290300370300200541f0006a20032903c004370300200341c0046a201c10b20520054188016a200729030037030020054180016a20032903c004370300200341c0046a201b10b20520054198016a200729030037030020054190016a20032903c004370300200341c0046a201a10b205200541a8016a2007290300370300200541a0016a20032903c004370300200341c0046a201910b205200541b8016a2007290300370300200541b0016a20032903c004370300200341c0046a201810b205200541c8016a2007290300370300200541c0016a20032903c004370300200341c0046a201710b205200541d8016a2007290300370300200541d0016a20032903c004370300200341c0046a201610b205200541e8016a2007290300370300200541e0016a20032903c004370300024002402008410f6a22052009460d002009210d200521090c010b200941016a22052009490d09200941017422072005200720054b1b220d41ffffffff0071200d470d09200d41047422054100480d090240024020090d002005102a21060c010b200620094104742005102e21060b2006450d050b200620094104746a220541063a0000200520032900c004370001200541086a202b290000370000200341c0046a20034190016a418c0110db051a4110102a2207450d04200741063a0000200341b0036a200341c0046a418c0110db051a202a2802002205417f4c0d03200e41146a280200212a410121094101210b02402005450d002005102a220b450d050b200b202a200510db05210b0240024020050d004100212a0c010b2005102a2209450d052005212a0b2009200b200510db05210f02402005450d00200b102c0b200341c0046a200341b0036a418c0110db051a200e41216a310000212c200341b0036a200341c0046a418c0110db051a200341c0046a200341b0036a418c0110db051a200341a0026a200341c0046a418c0110db051a4110102a2209450d04200841106a2108202541807e712125200a428080808080804083220a2005ad84202c422886844280808080800c84212c200941063a00002009102c200341b0036a200341a0026a418c0110db051a200341c0046a200341b0036a418c0110db051a024020072d00004109470d0002402007280204220528020441ffffffff0371450d002005280200102c200728020421050b2005102c0b2007102c200341a0026a200341c0046a418c0110db051a200341c0046a200341a0026a418c0110db051a200320253602dc03200320083602d8032003200d3602d403200320063602d003200341003602cc03200342043702c4032003202c3702bc032003202a3602b8032003200f3602b403200341013602b003200341c0046a200341b0036a10fd0420034190016a200341c0046a418c0110db051a200e41286a2024360200200e41246a4101360200024020032d00d0054109470d00024020032802d405220528020441ffffffff0371450d002005280200102c20032802d40521050b2005102c0b024020032d00e0054109470d000240200341d0056a41146a280200220528020441ffffffff0371450d002005280200102c20032802e40521050b2005102c0b024020032d00f0054109470d000240200341d0056a41246a280200220528020441ffffffff0371450d002005280200102c20032802f40521050b2005102c0b024020032d0080064109470d0002402012280200220528020441ffffffff0371450d002005280200102c20032802840621050b2005102c0b024020032d0090064109470d0002402001280200220528020441ffffffff0371450d002005280200102c20032802940621050b2005102c0b024020032d00a0064109470d0002402013280200220528020441ffffffff0371450d002005280200102c20032802a40621050b2005102c0b024020032d00b0064109470d0002402033280200220528020441ffffffff0371450d002005280200102c20032802b40621050b2005102c0b024020032d00c0064109470d0002402036280200220528020441ffffffff0371450d002005280200102c20032802c40621050b2005102c0b024020032d00d0064109470d0002402035280200220528020441ffffffff0371450d002005280200102c20032802d40621050b2005102c0b024020032d00e0064109470d000240202f280200220528020441ffffffff0371450d002005280200102c20032802e40621050b2005102c0b024020032d00f0064109470d0002402030280200220528020441ffffffff0371450d002005280200102c20032802f40621050b2005102c0b024020032d0080074109470d0002402031280200220528020441ffffffff0371450d002005280200102c20032802840721050b2005102c0b024020032d0090074109470d0002402037280200220528020441ffffffff0371450d002005280200102c20032802940721050b2005102c0b024020032d00a0074109470d0002402038280200220528020441ffffffff0371450d002005280200102c20032802a40721050b2005102c0b024020032d00b0074109470d0002402039280200220528020441ffffffff0371450d002005280200102c20032802b40721050b2005102c0b200a4280808080808c0184210a202441016a212420282014470d020c050b0240200e450d00200e417f6a210e200820074102746a4194036a28020021080c010b0b0b41d8fcc5004180011054000b103a000b1033000b02402015450d002023102c0b200341d0056a20034190016a418c0110db051a200341c0046a200341d0056a10fa040240200341c0046a41106a2802002205450d0020032802c8042215200541306c6a21290340024020152d000041786a220541024b0d0002400240024020050e03000102000b201528020c2205450d0220152802042208200541146c6a212403400240200828020c0d002008280210210e202621062027210c0340200641286a2109200641086a210720062f010622254102742105417f210d02400340024020050d002025210d0c020b2007280200210b200d41016a210d200941206a21092005417c6a2105200741046a21070240417f200b200e47200b200e4b1b41016a0e03020001020b0b02402009417c6a280200450d00200820092802003602100c030b41d8fdc50041351054000b200c450d01200c417f6a210c2006200d4102746a4194036a28020021060c000b0b200841146a22082024470d000c030b0b2015280204210b202621092027210e0340200941286a2108200941086a210720092f0106220c4102742105417f210602400340024020050d00200c21060c020b2007280200210d200641016a2106200841206a21082005417c6a2105200741046a21070240417f200d200b47200d200b4b1b41016a0e03020001020b0b02402008417c6a280200450d00201520082802003602040c040b41d8fdc50041351054000b200e450d02200e417f6a210e200920064102746a4194036a28020021090c000b0b201528020c2205450d002015280204222a2005411c6c6a210f03400240202a2802182205450d00202a280210220c20054102746a21280340200c222441046a210c2024280200210b202621092027210e0340200941286a2108200941086a210720092f010622254102742105417f2106024002400340024020050d00202521060c020b2007280200210d200641016a2106200841206a21082005417c6a2105200741046a21070240417f200d200b47200d200b4b1b41016a0e03020001020b0b02402008417c6a280200450d00202420082802003602000c020b41d8fdc50041351054000b200e450d00200e417f6a210e200920064102746a4194036a28020021090c010b0b200c2028470d000b0b202a411c6a222a200f470d000b0b201541306a22152029470d000b0b200341cc046a290200210a20032802c004210520032902c404212c20262027203410b005200041106a200a370200200041086a202c37020020002005360204200041003602002011450d012010102c200424000f0b024020012802102205450d0020012802082103200541306c21050340200310b105200341306a2103200541506a22050d000b0b2001410c6a280200450d002001280208102c0b200424000f0b1035000bfa820204117f017e0b7f017e230041e0006b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e100100021211100f0e0d0b090a06050403010b200141186a2802002104200141146a2802002105200141106a28020021062001410c6a2802002107200141086a2802002108200141046a28020021090240200241046a280200200241086a280200220a460d002002280200210b0c190b200a41016a220b200a490d15200a410174220c200b200c200b4b1b220c4100480d1502400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d142002200b360200200241046a200c360200200241086a280200210a0c180b2001410c6a280200210b200141086a2802002105200141046a280200210420012d0001210d02400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d15200a4101742206200c2006200c4b1b22064100480d1502400240200a0d002006102a210c0c010b2002280200200a2006102e210c0b200c450d142002200c360200200241046a2006360200200241086a280200210a0b200241086a2206200a41016a360200200c200a6a200d3a000002400240200241046a280200220c2006280200220a6b200b490d002002280200210c0c010b200a200b6a220d200a490d15200c410174220a200d200a200d4b1b220a4100480d1502400240200c0d00200a102a210c0c010b2002280200200c200a102e210c0b200c450d142002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2004200b10db051a4100210b4101210d024020050d004101210c0c220b2004102c4101210c0c210b2001410c6a2802002106200141086a280200210e200141046a280200210f02400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d14200a410174220c200b200c200b4b1b220c4100480d1402400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d132002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41013a0000200f20064104746a21104100210c4100210b41002105410121042006210a03400240200b2005470d00200c200b41016a220d200c200d4b1b22054100480d1502400240200c0d002005102a21040c010b2004200b2005102e21040b2004450d140b2004200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b024020060d00200f21080c110b200f210a0340200a41106a2108200a2d000d22114105460d11200a2d000c210c200a2802082109200a2802042112200a280200211302402005200b470d00200b41016a220a200b490d15200b410174220d200a200d200a4b1b22054100480d1502400240200b0d002005102a21040c010b2004200b2005102e21040b2004450d140b2004200b6a200c3a0000200b41016a210a200b410174220b41046a2107200b41026a210c2009210b0340200721060240200a2005470d00200a41016a220d200a490d16200c200d200c200d4b1b22054100480d1602400240200a0d002005102a21040c010b2004200a2005102e21040b2004450d150b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200641026a2107200c41026a210c200a41016a210a200d210b200d0d000b0240024020090d00200a210b0c010b4100210c0340200a200c6a210b41fc00210d02400240024002402013200c6a2d00000e050200010305020b41fe00210d0c020b41fd00210d0c010b41ff00210d0b0240200b2005470d00200b41016a2205200b490d1720062005200620054b1b22054100480d1702400240200b0d002005102a21040c010b2004200b2005102e21040b2004450d160b2004200a6a200c6a200d3a0000200641026a21062009200c41016a220c470d000b200a200c6a210b0b02402012450d002013102c0b4100210a024020114104460d0002402005200b470d00200b41016a220a200b490d16200b410174220c200a200c200a4b1b22054100480d1602400240200b0d002005102a21040c010b2004200b2005102e21040b2004450d150b2004200b6a41013a0000200b41016a210b201141077141ff0073210a0b02402005200b470d00200b41016a220c200b490d15200b410174220d200c200d200c4b1b22054100480d1502400240200b0d002005102a21040c010b2004200b2005102e21040b2004450d140b2004200b6a200a3a0000200b41016a210b2008210a20082010470d000c120b0b200141286a2802002113200141246a280200210f200141206a28020021082001411c6a2802002107200141186a2802002110200141146a28020021092001410c6a2902002114200141086a2802002112200141046a280200211102400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d05200a410174220c200b200c200b4b1b220c4100480d0502400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d042002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41003a0000200341dc006a410036020020034201370254200320023602502014422088a7210d4100210a4100210b2014a72206210c034002400240200a200b460d002003280254210a0c010b200a41016a2204200a490d06200a41017422052004200520044b1b22044100480d0602400240200a0d002004102a210a0c010b2003280254200a2004102e210a0b200a450d05200320043602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c41077622041b3a00002003280258210a200328025c210b2004210c20040d000b02400240200a200b6b2006490d00200328025421040c010b200b20066a220c200b490d05200a4101742204200c2004200c4b1b220c4100480d0502400240200a0d00200c102a21040c010b2003280254200a200c102e21040b2004450d042003200c36025820032004360254200c210a0b2003200b20066a220c36025c2004200b6a2011200610db051a02402012450d002011102c0b034002400240200a200c460d002003280254210a0c010b200a41016a220b200a490d06200a4101742204200b2004200b4b1b220b4100480d0602400240200a0d00200b102a210a0c010b2003280254200a200b102e210a0b200a450d052003200b3602582003200a3602540b2003200c41016a36025c200a200c6a200d41807f72200d41ff0071200d410776220b1b3a00000240200b450d002003280258210a200328025c210c200b210d0c010b0b4101211202402009450d002007210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d07200a410174220d200c200d200c4b1b220d4100480d0702400240200a0d00200d102a210c0c010b2003280254200a200d102e210c0b200c450d062003200d3602582003200c3602540b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2007490d002003280254210b0c010b200a20076a220c200a490d06200b410174220d200c200d200c4b1b220c4100480d0602400240200b0d00200c102a210b0c010b2003280254200b200c102e210b0b200b450d052003200c3602582003200b3602540b2003200a20076a36025c200b200a6a2009200710db051a410021122010450d002009102c0b200820134104746a21062013210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d06200a410174220d200c200d200c4b1b220d4100480d0602400240200a0d00200d102a210c0c010b2003280254200a200d102e210c0b200c450d052003200d3602582003200c3602540b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b200821040240024002402013450d00411021072008210403402004220b41106a2104200b280200220c4108460d01200b410c6a2802002102200b41086a280200210a200b280204210b024002400240024002400240024002400240200c0e080001020304050607000b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d11200c4101742205200d2005200d4b1b22054100480d1102400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d10200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41003a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d12200c4101742205200d2005200d4b1b22054100480d1202400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d11200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d12200b410174220d200c200d200c4b1b220d4100480d1202400240200b0d00200d102a210c0c010b2003280254200b200d102e210c0b200c450d112003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c080b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d10200c4101742205200d2005200d4b1b22054100480d1002400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0f200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41013a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d11200c4101742205200d2005200d4b1b22054100480d1102400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d10200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d11200b410174220d200c200d200c4b1b220d4100480d1102400240200b0d00200d102a210c0c010b2003280254200b200d102e210c0b200c450d102003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c070b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0f200c4101742205200d2005200d4b1b22054100480d0f02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0e200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41023a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d10200c4101742205200d2005200d4b1b22054100480d1002400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0f200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d10200b410174220d200c200d200c4b1b220d4100480d1002400240200b0d00200d102a210c0c010b2003280254200b200d102e210c0b200c450d0f2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c060b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0e200c4101742205200d2005200d4b1b22054100480d0e02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0d200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41033a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0f200c4101742205200d2005200d4b1b22054100480d0f02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0e200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d0f200b410174220d200c200d200c4b1b220d4100480d0f02400240200b0d00200d102a210c0c010b2003280254200b200d102e210c0b200c450d0e2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10880520032d0000220a411f460d0420032f000120032d000341107472210d0c070b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0d200c4101742205200d2005200d4b1b22054100480d0d02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0c200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41043a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0e200c4101742205200d2005200d4b1b22054100480d0e02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0d200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d0e200b410174220d200c200d200c4b1b220d4100480d0e02400240200b0d00200d102a210c0c010b2003280254200b200d102e210c0b200c450d0d2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10880520032d0000220a411f460d0320032f000120032d000341107472210d0c060b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0c200c4101742205200d2005200d4b1b22054100480d0c02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0b200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41053a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0d200c4101742205200d2005200d4b1b22054100480d0d02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0c200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d0d200b410174220d200c200d200c4b1b220d4100480d0d02400240200b0d00200d102a210c0c010b2003280254200b200d102e210c0b200c450d0c2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10880520032d0000220a411f460d0220032f000120032d000341107472210d0c050b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0b200c4101742205200d2005200d4b1b22054100480d0b02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0a200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41063a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0c200c4101742205200d2005200d4b1b22054100480d0c02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0b200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d0c200b410174220d200c200d200c4b1b220d4100480d0c02400240200b0d00200d102a210c0c010b2003280254200b200d102e210c0b200c450d0b2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c020b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0a200c4101742205200d2005200d4b1b22054100480d0a02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d09200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41073a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d0b200c4101742205200d2005200d4b1b22054100480d0b02400240200c0d002005102a210d0c010b2003280254200c2005102e210d0b200d450d0a200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d0b200b410174220d200c200d200c4b1b220d4100480d0b02400240200b0d00200d102a210c0c010b2003280254200b200d102e210c0b200c450d0a2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b0b200741106a210720042006470d000b200621040b0240034020062004460d012004280200210a200441106a2104200a4108470d000b0b0240200f450d002008102c0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d08200a4101742206200c2006200c4b1b22064100480d0802400240200a0d002006102a210c0c010b2004280200200a2006102e210c0b200c450d072004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d07200b410174220a200c200a200c4b1b220a4100480d0702400240200b0d00200a102a210b0c010b2004280200200b200a102e210b0b200b450d062004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a2002200710db051a02402008450d002002102c0b410021114101210d2009450d012012450d012010450d012009102c0c010b20032903082114200328020421042013410474210c02400340200c2007460d01200820076a210b200741106a2107200b2802004108470d000b0b0240200f450d002008102c0b02402003280258450d002003280254102c0b02402009450d002012450d002010450d002009102c0b200a411f470d15410021114101210d0b4101210b4101210c410121044101210641012112410121104101210541012107410121024101210841012109410121130c380b2001412c6a280200210e200141286a2802002115200141246a2802002111200141206a28020021162001411c6a2802002117200141186a2802002118200141146a28020021102001410c6a2902002114200141086a2802002119200141046a280200211202400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d04200a410174220c200b200c200b4b1b220c4100480d0402400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d032002200b360200200241046a200c360200200241086a280200210a0b4101210d200241086a200a41016a36020041002104200b200a6a41003a00004104102a220f450d02200f41eec2b5ab063600000240024020120d00410021134100211a0c010b410121064100210a410021042014a72205210b034002400240200a2004460d00200a210d2004210a0c010b200a41016a220c200a490d06200a410174220d200c200d200c4b1b220d4100480d0602400240200a0d00200d102a21060c010b2006200a200d102e21060b2006450d050b2006200a6a200b41807f72200b41ff0071200b410776220c1b3a0000200a41016a2104200d210a200c210b200c0d000b02400240200d20046b2005490d00200d21080c010b200420056a220a2004490d05200d410174220b200a200b200a4b1b22084100480d050240200d0d002008102a22060d010c050b2006200d2008102e2206450d040b200620046a2012200510db051a02402019450d002012102c0b4101102a220d450d03200d41003a00004101210a4101210b200420056a2207210c034002400240200a200b460d00200a21040c010b200a41016a220b200a490d06200a4101742204200b2004200b4b1b22044100480d0602400240200a0d002004102a210d0c010b200d200a2004102e210d0b200d450d05200a210b2004210a0b200d200b6a200c41807f72200c41ff0071200c41077622051b3a0000200b41016a210b2005210c20050d000b02402004200b6b20074f0d00200b20076a220a200b490d052004410174220c200a200c200a4b1b220a4100480d050240024020040d00200a102a210d0c010b200d2004200a102e210d0b200d450d04200a21040b200d200b6a2006200710db051a200b20076a21134101211a2008450d002006102c0b0240024002400240024002400240024020100d004101211b0c010b4100211b20034100360240200342013703382003410c6a2017360200200341086a201836020020032010360204200320144220883e0200200341d0006a2003200341386a109305024020032d00502209411f460d0020032f005120032d0053411074722108200341d0006a41086a290300211420032802542116200328023c0d020c030b0240024020042013460d002004210a0c010b200441016a220a2004490d0b2004410174220b200a200b200a4b1b220a4100480d0b0240024020040d00200a102a210d0c010b200d2004200a102e210d0b200d450d0a200421130b200d20136a41013a0000201341016a210b20032802402206210c034002400240200a200b460d00200a21040c010b200a41016a220b200a490d0c200a4101742204200b2004200b4b1b22044100480d0c02400240200a0d002004102a210d0c010b200d200a2004102e210d0b200d450d0b200a210b2004210a0b200d200b6a200c41807f72200c41ff0071200c41077622051b3a0000200b41016a210b2005210c20050d000b2003280238210a02402004200b6b20064f0d00200b20066a220c200b490d0b20044101742205200c2005200c4b1b220c4100480d0b0240024020040d00200c102a210d0c010b200d2004200c102e210d0b200d450d0a200c21040b200d200b6a200a200610db051a0240200328023c450d00200a102c0b200b20066a21134100211b0b0240024020110d00410021050c010b2003410036024020034201370338410121064100210c4100210a2016210b03400240200a200c470d00200c41016a2205200c490d0c200c41017422072005200720054b1b22054100480d0c02400240200c0d002005102a21060c010b2006200c2005102e21060b2006450d0b2003200536023c200320063602382005210c0b2003200a41016a22073602402006200a6a200b41807f72200b41ff0071200b41077622051b3a00002007210a2005210b20050d000b2011200e4104746a210802400240024020160d00201121050c010b20112105200e450d00200841706a211c4100210a2011211d02400340201d210502400340200541046a28020022090d01200a41016a210a2008200541106a2205470d000c050b0b200541106a211d200a41016a211e2016417f6a2116200541086a29020021142005280200211f200328023c210c2003280240210b034002400240200b200c460d00200328023821060c010b200c41016a2206200c490d10200c41017422072006200720064b1b22074100480d1002400240200c0d002007102a21060c010b2003280238200c2007102e21060b2006450d0f2003200736023c200320063602382007210c0b2003200b41016a22073602402006200b6a200a41807f72200a41ff0071200a41077622061b3a00002007210b2006210a20060d000b20032014370308200320093602042003201f360200200341d0006a2003200341386a109305024020032d00502209411f470d002016450d02201e210a201c2005470d010c020b0b20032d0053211d20032f0051211f20032802542116200329035821140240200841706a2005460d00200541106a210503402005220a41106a21050240200a2802042206450d00200a28020821070240200a410c6a280200220a450d00200a410c6c210b2006210a03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b2007450d002006102c0b20052008470d000b0b201d411074210a02402015450d002011102c0b201f200a72210841012105200328023c450d062003280238102c0c060b200541106a21050b20052008460d0003402005220a41106a21050240200a2802042206450d00200a28020821070240200a410c6a280200220a450d00200a410c6c210b2006210a03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b2007450d002006102c0b20052008470d000b0b02402015450d002011102c0b0240024020042013460d002004210a0c010b200441016a220a2004490d0b2004410174220b200a200b200a4b1b220a4100480d0b0240024020040d00200a102a210d0c010b200d2004200a102e210d0b200d450d0a200421130b200d20136a41023a0000201341016a210b20032802402206210c034002400240200a200b460d00200a21040c010b200a41016a220b200a490d0c200a4101742204200b2004200b4b1b22044100480d0c02400240200a0d002004102a210d0c010b200d200a2004102e210d0b200d450d0b200a210b2004210a0b200d200b6a200c41807f72200c41ff0071200c41077622051b3a0000200b41016a210b2005210c20050d000b2003280238210a02402004200b6b20064f0d00200b20066a220c200b490d0b20044101742205200c2005200c4b1b220c4100480d0b0240024020040d00200c102a210d0c010b200d2004200c102e210d0b200d450d0a200c21040b200d200b6a200a200610db051a0240200328023c450d00200a102c0b200b20066a2113410121050b0240201a201245720d002019450d002012102c0b02402010450d00201b4101730d0002402017450d002017410c6c210b2010210a03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b2018450d002010102c0b2005201145720d030240200e450d002011200e4104746a21072011210603402006220541106a210602402005280204220a450d0002402005410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b200541086a280200450d002005280204102c0b20062007470d000b0b2015450d032011102c0c030b2003280238102c0b410021050b0240201a201245720d002019450d002012102c0b02402010450d00201b4101730d0002402017450d002017410c6c210b2010210a03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b2018450d002010102c0b02402005201145720d000240200e450d002011200e4104746a21072011210603402006220541106a210602402005280204220a450d0002402005410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b200541086a280200450d002005280204102c0b20062007470d000b0b2015450d002011102c0b2009411f460d002008410874200972210a02402004450d00200d102c0b2000200a360200200041086a2014370200200041046a2016360200200f102c0c010b200341146a2013360200200341106a20043602002003200d36020c20034284808080c0003702042003200f360200200341d0006a20032002109405200320032900513703382003200341d0006a41086a29000037003f20032d0050220a411f460d012000200a3a000020002003290338370001200041086a200329003f3700000b410021084101210d4101210c410121044101210541012106410121074101210b41012102410121090c1d0b410021134101210d4101210b4101210c4101210441012106410121124101211041012105410121074101210241012108410121090c360b2001410c6a2802002105200141086a2802002107200141046a280200210602400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d03200a410174220c200b200c200b4b1b220c4100480d0302400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d022002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a410b3a0000200341c4006a41003602002003420137023c2003200236023820062005411c6c6a21114100210a4100210b2005210c034002400240200a200b460d00200328023c210a0c010b200a41016a220d200a490d04200a4101742204200d2004200d4b1b220d4100480d0402400240200a0d00200d102a210a0c010b200328023c200a200d102e210a0b200a450d032003200d3602402003200a36023c0b2003200b41016a360244200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210a2003280244210b200c210c0c010b0b2003201136025c20032006360258200320073602542003200636025002402005450d00034020032006220a411c6a2206360258200a2802102207450d01200a410c6a2802002102200a41086a2802002108200a2802042105200a41146a2902002114200a280200210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d06200a410174220d200c200d200c4b1b220d4100480d0602400240200a0d00200d102a210c0c010b200328023c200a200d102e210c0b200c450d052003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b0240024002400240024020050d00410121130c010b200320023602302003200836022c200320053602282003200341286a200341386a10850520032d0000220a411f470d01410021130b2014a721092014422088a72204210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d09200a410174220d200c200d200c4b1b220d4100480d0902400240200a0d00200d102a210c0c010b200328023c200a200d102e210c0b200c450d082003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280240220b2003280244220a6b2004490d00200328023c210b0c010b200a20046a220c200a490d08200b410174220a200c200a200c4b1b220a4100480d0802400240200b0d00200a102a210b0c010b200328023c200b200a102e210b0b200b450d072003200a3602402003200b36023c2003280244210a0b2003200a20046a360244200b200a6a2007200410db051a02402009450d002007102c0b2005450d0220130d010c020b20032d0003411074210b20032f0001210c200329030821202003280204210d02402014a7450d002007102c0b200c200b72210b200341d0006a10950502402003280240450d00200328023c102c0b2000200b3b00012000200a3a0000200041036a200b4110763a0000200041086a2020370000200041046a200d360000410021024101210d4101210c410121044101210541012106410121074101210b0c1e0b02402002450d002002410474210b2005210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b2008450d002005102c0b20062011470d000b0b200341d0006a10950520032802402108200328023c21022003280238220441086a210d200441046a210520032802442207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d04200a4101742206200c2006200c4b1b22064100480d0402400240200a0d002006102a210c0c010b2004280200200a2006102e210c0b200c450d032004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d03200b410174220a200c200a200c4b1b220a4100480d0302400240200b0d00200a102a210b0c010b2004280200200b200a102e210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a2002200710db051a02402008450d002002102c0b410021094101210d4101210b4101210c4101210441012106410121124101211041012105410121074101210241012108410121130c350b2001410c6a2802002106200141086a2802002107200141046a280200210d02400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d10200a410174220c200b200c200b4b1b220c4100480d1002400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d0f2002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a410a3a0000200341246a41003602002003420137021c20032002360218200d200641186c6a210f4100210a4100210b2006210c034002400240200a200b460d00200328021c210a0c010b200a41016a2204200a490d11200a41017422052004200520044b1b22044100480d1102400240200a0d002004102a210a0c010b200328021c200a2004102e210a0b200a450d10200320043602202003200a36021c0b2003200b41016a360224200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280220210a2003280224210b200c210c0c010b0b2003200f3602342003200d3602302003200736022c2003200d36022802402006450d0020034101722102200341026a210703402003200d41186a2213360230200d2802002208450d01200d41146a2802002111200d41106a2802002110200d28020c2109200d280208210c200d28020421124100210b200341003602442003420137023c2008200c4103746a21062003200341186a3602384100210a034002400240200b200a460d00200328023c210b0c010b200b41016a220a200b490d13200b410174220d200a200d200a4b1b220a4100480d1302400240200b0d00200a102a210b0c010b200328023c200b200a102e210b0b200b450d122003200a3602402003200b36023c2003280244210a0b2003200a41016a360244200b200a6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210b2003280244210a200c210c0c010b0b0240024020062008470d00200821040c010b2008210a0340200a41086a2104200a2902002214422088a7220a41ff01714104460d01200a41187441187521052014a7210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d07200a410174220d200c200d200c4b1b220d4100480d0702400240200a0d00200d102a210c0c010b200328023c200a200d102e210c0b200c450d142003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b0240024020032802402003280244220a460d00200328023c210b0c010b200a41016a220b200a490d06200a410174220c200b200c200b4b1b220c4100480d0602400240200a0d00200c102a210b0c010b200328023c200a200c102e210b0b200b450d052003200c3602402003200b36023c2003280244210a0b2003200a41016a360244200b200a6a2005417f73220a413f7141c00072200a2005417f4a1b3a00002004210a20042006470d000b200621040b0240034020062004460d0120042d0004210a200441086a2104200a4104470d000b0b02402012450d002008102c0b20092011410474220a6a210c024002400240024020110d002009210a0c010b200a41706a210d2009210a0340200a2d0000210b2007200a41036a2d00003a00002003200a41016a2f00003b01000240200b41ac01470d00200a41106a210a0c020b200341cc006a41026a20072d000022043a0000200320032f010022053b014c200a41046a2802002106200a41086a2903002114200220053b0000200241026a20043a00002003200b3a00002003201437030820032006360204200341d0006a2003200341386a108d05024020032d00502204411f46220b450d00200d41706a210d200a41106a220a200c470d010c030b0b20032d0053210520032f0051210620032802542108200329035821140240200d450d00200a41106a210a034002400240200a2d0000220d4109460d00200d41ac01470d010c030b0240200a41046a280200220d28020441ffffffff0371450d00200d280200102c0b200d102c0b200a41106a220a200c470d000b0b02402010450d002009102c0b02402003280240450d00200328023c102c0b200b0d022006200541107472210a200341286a10960502402003280220450d00200328021c102c0b2000200a3b0001200020043a0000200041036a200a4110763a0000200041086a2014370000200041046a20083600004100210b4101210d4101210c410121044101210541012106410121070c1d0b200a200c460d00034002400240200a2d0000220b4109460d00200b41ac01470d010c030b0240200a41046a280200220b28020441ffffffff0371450d00200b280200102c0b200b102c0b200a41106a220a200c470d000b0b02402010450d002009102c0b20032802402111200328023c21092003280238210c20032802442208210b034002400240200c41086a2205280200200c410c6a2204280200220a460d00200c280204210d0c010b200a41016a220d200a490d06200a4101742206200d2006200d4b1b22064100480d0602400240200a0d002006102a210d0c010b200c280204200a2006102e210d0b200d450d05200c200d360204200520063602002004280200210a0b2004200a41016a360200200d200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402005280200220b2004280200220a6b2008490d00200c280204210b0c010b200a20086a220d200a490d05200b410174220a200d200a200d4b1b220a4100480d0502400240200b0d00200a102a210b0c010b200c280204200b200a102e210b0b200b450d04200c200b3602042005200a3602002004280200210a0b2004200a20086a360200200b200a6a2009200810db051a2011450d002009102c0b2013210d2013200f470d000b0b200341286a10960520032802202108200328021c21022003280218220441086a210d200441046a210520032802242207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d03200a4101742206200c2006200c4b1b22064100480d0302400240200a0d002006102a210c0c010b2004280200200a2006102e210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d02200b410174220a200c200a200c4b1b220a4100480d0202400240200b0d00200a102a210b0c010b2004280200200b200a102e210b0b200b450d012004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a2002200710db051a02402008450d002002102c0b410021084101210d4101210b4101210c410121044101210641012112410121104101210541012107410121020c240b1033000b1035000b2001410c6a2802002105200141086a2802002106200141046a280200210802400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d0d200a410174220c200b200c200b4b1b220c4100480d0d02400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d0c2002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41093a0000200341c4006a41003602002003420137023c2003200236023820082005411c6c6a21124100210a4100210b2005210c034002400240200a200b460d00200328023c210a0c010b200a41016a220d200a490d0e200a4101742204200d2004200d4b1b220d4100480d0e02400240200a0d00200d102a210a0c010b200328023c200a200d102e210a0b200a450d0d2003200d3602402003200a36023c0b2003200b41016a360244200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210a2003280244210b200c210c0c010b0b2003201236025c20032008360258200320063602542003200836025002402005450d00034020032008220a411c6a2208360258200a2802102206450d01200a410c6a2802002102200a41086a2802002109200a2802042107200a41146a2902002114200a280200210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d10200a410174220d200c200d200c4b1b220d4100480d1002400240200a0d00200d102a210c0c010b200328023c200a200d102e210c0b200c450d0f2003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b0240024002400240024020070d00410121110c010b200320023602302003200936022c200320073602282003200341286a200341386a10850520032d0000220a411f470d01410021110b20062014422088a7220b4102746a21052014a7211303400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d13200a410174220d200c200d200c4b1b220d4100480d1302400240200a0d00200d102a210c0c010b200328023c200a200d102e210c0b200c450d122003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024020052006460d002006210403402004280200210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d15200a410174220d200c200d200c4b1b220d4100480d1502400240200a0d00200d102a210c0c010b200328023c200a200d102e210c0b200c450d142003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b200441046a22042005470d000b0b02402013450d002006102c0b2007450d0220110d010c020b20032d0003411074210b20032f0001210c200329030821202003280204210d02402014a7450d002006102c0b200c200b72210b200341d0006a10970502402003280240450d00200328023c102c0b2000200b3b00012000200a3a0000200041036a200b4110763a0000200041086a2020370000200041046a200d360000410021074101210d4101210c4101210441012105410121060c180b02402002450d002002410474210b2007210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b2009450d002007102c0b20082012470d000b0b200341d0006a10970520032802402108200328023c21022003280238220441086a210d200441046a210520032802442207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d0e200a4101742206200c2006200c4b1b22064100480d0e02400240200a0d002006102a210c0c010b2004280200200a2006102e210c0b200c450d0d2004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d0d200b410174220a200c200a200c4b1b220a4100480d0d02400240200b0d00200a102a210b0c010b2004280200200b200a102e210b0b200b450d0c2004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a2002200710db051a02402008450d002002102c0b410021024101210d4101210b4101210c4101210441012106410121124101211041012105410121070c200b200141046a280200210a02400240200241046a280200200241086a280200220b460d002002280200210c0c010b200b41016a220c200b490d0c200b410174220d200c200d200c4b1b220d4100480d0c02400240200b0d00200d102a210c0c010b2002280200200b200d102e210c0b200c450d0b2002200c360200200241046a200d360200200241086a280200210b0b200241086a200b41016a360200200c200b6a410c3a00004100210c4100210b410021064101210503400240200b2006470d00200c200b41016a220d200c200d4b1b22064100480d0d02400240200c0d002006102a21050c010b2005200b2006102e21050b2005450d0c0b2005200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b200b417f6a2109200241086a2104200241046a2107200b210c03400240024020072802002004280200220a460d002002280200210d0c010b200a41016a220d200a490d0d200a4101742208200d2008200d4b1b22084100480d0d02400240200a0d002008102a210d0c010b2002280200200a2008102e210d0b200d450d0c2002200d360200200720083602002004280200210a0b2004200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b20094d0d002002280200210c0c010b200a200b6a220d200a490d0c200c410174220a200d200a200d4b1b220a4100480d0c02400240200c0d00200a102a210c0c010b2002280200200c200a102e210c0b200c450d0b2002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2005200b10db051a4101210d2006450d012005102c0c010b200141046a280200210a02400240200241046a280200200241086a280200220b460d002002280200210c0c010b200b41016a220c200b490d0b200b410174220d200c200d200c4b1b220d4100480d0b02400240200b0d00200d102a210c0c010b2002280200200b200d102e210c0b200c450d0a2002200c360200200241046a200d360200200241086a280200210b0b200241086a200b41016a360200200c200b6a41083a00004100210c4100210b410021064101210503400240200b2006470d00200c200b41016a220d200c200d4b1b22064100480d0c02400240200c0d002006102a21050c010b2005200b2006102e21050b2005450d0b0b2005200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b200b417f6a2109200241086a2104200241046a2107200b210c03400240024020072802002004280200220a460d002002280200210d0c010b200a41016a220d200a490d0c200a4101742208200d2008200d4b1b22084100480d0c02400240200a0d002008102a210d0c010b2002280200200a2008102e210d0b200d450d0b2002200d360200200720083602002004280200210a0b2004200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b20094d0d002002280200210c0c010b200a200b6a220d200a490d0b200c410174220a200d200a200d4b1b220a4100480d0b02400240200c0d00200a102a210c0c010b2002280200200c200a102e210c0b200c450d0a2002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2005200b10db051a4101210d2006450d002005102c0b4101210b4101210c0c160b2001410c6a2802002106200141086a280200210f200141046a280200211002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d09200a410174220c200b200c200b4b1b220c4100480d0902400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d082002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41073a00002010200641146c6a2112410021044100210a4100210c4101210b2006210d03400240200a200c470d002004200a41016a220c2004200c4b1b220c4100480d0a0240024020040d00200c102a210b0c010b200b200a200c102e210b0b200b450d090b200b200a6a200d41807f72200d41ff0071200d41077622051b3a0000200441026a2104200a41016a210a2005210d20050d000b02400240024020060d00201021080c010b201021040340200441146a2108200428020c22134104460d012004280204211120042802002109200a4101742105200441106a280200210d20042802082207210403400240200a200c470d00200a41016a220c200a490d0d2005200c2005200c4b1b220c4100480d0d02400240200a0d00200c102a210b0c010b200b200a200c102e210b0b200b450d0c0b200b200a6a200441807f72200441ff0071200441077622061b3a0000200541026a2105200a41016a210a2006210420060d000b02400240200c200a6b2007490d00200c21040c010b200a20076a2204200a490d0c200c41017422052004200520044b1b22044100480d0c02400240200c0d002004102a210b0c010b200b200c2004102e210b0b200b450d0b0b200b200a6a2009200710db051a200720046b200a6a210c02402011450d002009102c0b02400240200c450d002004210c0c010b200441016a220c2004490d0c20044101742205200c2005200c4b1b220c4100480d0c0240024020040d00200c102a210b0c010b200b2004200c102e210b0b200b450d0b0b200b20076a200a6a20133a00002007200a6a41016a210a03400240200a200c470d00200a41016a220c200a490d0d200a4101742204200c2004200c4b1b220c4100480d0d02400240200a0d00200c102a210b0c010b200b200a200c102e210b0b200b450d0c0b200b200a6a200d41807f72200d41ff0071200d41077622041b3a0000200a41016a210a2004210d20040d000b2008210420082012470d000c020b0b20082012460d0003402008410c6a2802004104460d010240200841046a280200450d002008280200102c0b200841146a22082012470d000b0b0240200f450d002010102c0b200241086a2106200241046a2107200a210403400240024020072802002006280200220d460d00200228020021050c010b200d41016a2205200d490d0a200d41017422082005200820054b1b22084100480d0a02400240200d0d002008102a21050c010b2002280200200d2008102e21050b2005450d0920022005360200200720083602002006280200210d0b2006200d41016a3602002005200d6a200441807f72200441ff00712004410776220d1b3a0000200d2104200d0d000b02400240200241046a2802002204200241086a280200220d6b200a490d00200228020021040c010b200d200a6a2205200d490d092004410174220d2005200d20054b1b220d4100480d090240024020040d00200d102a21040c010b20022802002004200d102e21040b2004450d0820022004360200200241046a200d360200200241086a280200210d0b200241086a200d200a6a3602002004200d6a200b200a10db051a410021074101210d0240200c450d00200b102c0b4101210b4101210c41012104410121064101211241012110410121050c1b0b2001410c6a2802002105200141086a2802002112200141046a280200210802400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d08200a410174220c200b200c200b4b1b220c4100480d0802400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d072002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41063a0000200341dc006a41003602002003420137025420032002360250200820054104746a21134100210a4100210b2005210c034002400240200a200b460d002003280254210a0c010b200a41016a220d200a490d09200a4101742204200d2004200d4b1b220d4100480d0902400240200a0d00200d102a210a0c010b2003280254200a200d102e210a0b200a450d082003200d3602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280258210a200328025c210b200c210c0c010b0b20082104024002402005450d00200541047421114100210c034002402008200c6a220b410d6a2d000022044102470d00200b41106a21040c020b200b2802002105200b41086a2802002106200b41046a2802002107200b410c6a2d00002102024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d0b200a4101742209200d2009200d4b1b22094100480d0b02400240200a0d002009102a210d0c010b2003280254200a2009102e210d0b200d450d0a200320093602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a200241ff00733a0000024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d0b200a4101742202200d2002200d4b1b22024100480d0b02400240200a0d002002102a210d0c010b2003280254200a2002102e210d0b200d450d0a200320023602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a20043a0000200320063602402003200736023c200320053602382003200341386a200341d0006a108505024020032d00002205411f470d002011200c41106a220c470d010c030b0b20032d0003210220032f0001210920032802042111200329030821140240200b41106a2013460d00200b41106a210403402004410d6a2d00004102460d01200428020421072004280200210602402004280208220a450d00200a410474210b2006210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b200441106a210402402007450d002006102c0b20042013470d000b0b2002411074210a02402012450d002008102c0b2009200a72210a02402003280258450d002003280254102c0b2000200a3b0001200020053a0000200041036a200a4110763a0000200041086a2014370000200041046a2011360000410021064101210d4101210c41012104410121050c100b20042013460d0003402004410d6a2d00004102460d01200428020421062004280200210502402004280208220a450d00200a410474210b2005210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b200441106a210402402006450d002005102c0b20042013470d000b0b02402012450d002008102c0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d09200a4101742206200c2006200c4b1b22064100480d0902400240200a0d002006102a210c0c010b2004280200200a2006102e210c0b200c450d082004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d08200b410174220a200c200a200c4b1b220a4100480d0802400240200b0d00200a102a210b0c010b2004280200200b200a102e210b0b200b450d072004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a2002200710db051a02402008450d002002102c0b410021054101210d4101210b4101210c410121044101210641012112410121100c190b2001410c6a2802002107200141086a2802002108200141046a280200210602400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d07200a410174220c200b200c200b4b1b220c4100480d0702400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d062002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41053a0000200341d0006a410c6a4100360200200342013702542003200236025020062007410c6c6a2102410121054100210a4100210b2007210c034002400240200b200a460d00200a21040c010b200a41016a220d200a490d08200a4101742204200d2004200d4b1b22044100480d0802400240200a0d002004102a21050c010b2005200a2004102e21050b2005450d070b2005200b6a200c41807f72200c41ff0071200c410776220d1b3a0000200b41016a210b2004210a200d210c200d0d000b200320043602582003200b36025c200320053602542006210a02402007450d002007410c6c210d4100210b034002402006200b6a220a41046a280200220c4102470d00200a410c6a210a0c020b2003200a280200200c200a41086a280200200341d0006a109005024020032d00002204411f460d0020032f000120032d00034110747221052003290308211420032802042107200a410c6a210c200d200b6b41746a210a02400340200a450d01200a41746a210a200c280204210b200c410c6a210c200b4102470d000b0b02402008450d002006102c0b02402003280258450d002003280254102c0b200020053b0001200020043a0000200041036a20054110763a0000200041086a2014370000200041046a2007360000410021054101210d4101210c410121040c0f0b200d200b410c6a220b470d000b2002210a0b200a410020076b410c6c6a210b024003402006200b460d01200b410c6a210b200a280204210c200a410c6a210a200c4102470d000b0b02402008450d002006102c0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d08200a4101742206200c2006200c4b1b22064100480d0802400240200a0d002006102a210c0c010b2004280200200a2006102e210c0b200c450d072004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d07200b410174220a200c200a200c4b1b220a4100480d0702400240200b0d00200a102a210b0c010b2004280200200b200a102e210b0b200b450d062004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a2002200710db051a02402008450d002002102c0b410021104101210d4101210b4101210c4101210441012106410121120c170b2001410c6a2802002109200141086a2802002113200141046a280200210602400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d06200a410174220c200b200c200b4b1b220c4100480d0602400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d052002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41043a0000200341d0006a410c6a4100360200200342013702542003200236025020062009410c6c6a2111410121054100210a4100210b2009210c034002400240200b200a460d00200a21040c010b200a41016a220d200a490d07200a4101742204200d2004200d4b1b22044100480d0702400240200a0d002004102a21050c010b2005200a2004102e21050b2005450d060b2005200b6a200c41807f72200c41ff0071200c410776220d1b3a0000200b41016a210b2004210a200d210c200d0d000b200320043602582003200b36025c200320053602542006210a02402009450d002009410c6c21084100210c034002402006200c6a220b41046a28020022044102470d00200b410c6a210a0c020b200b2802002105200b41086a2802002107024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d08200a4101742202200d2002200d4b1b22024100480d0802400240200a0d002002102a210d0c010b2003280254200a2002102e210d0b200d450d07200320023602582003200d3602540b2003200a41016a36025c200d200a6a41f0003a00002003200520042007200341d0006a109005024020032d0000220d411f460d0020032f000120032d00034110747221042003290308211420032802042105200b410c6a210b2008200c6b41746a210a02400340200a450d01200a41746a210a200b280204210c200b410c6a210b200c4102470d000b0b02402013450d002006102c0b02402003280258450d002003280254102c0b200020043b00012000200d3a0000200041036a20044110763a0000200041086a2014370000200041046a2005360000410021044101210d4101210c0c0d0b2008200c410c6a220c470d000b2011210a0b200a410020096b410c6c6a210b024003402006200b460d01200b410c6a210b200a280204210c200a410c6a210a200c4102470d000b0b02402013450d002006102c0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d07200a4101742206200c2006200c4b1b22064100480d0702400240200a0d002006102a210c0c010b2004280200200a2006102e210c0b200c450d062004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d06200b410174220a200c200a200c4b1b220a4100480d0602400240200b0d00200a102a210b0c010b2004280200200b200a102e210b0b200b450d052004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a2002200710db051a02402008450d002002102c0b410021124101210d4101210b4101210c41012104410121060c150b2001410c6a2802002106200141086a2802002109200141046a280200210802400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d05200a410174220c200b200c200b4b1b220c4100480d0502400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d042002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41033a0000200820064102746a21074100210c4100210a41002105410121042006210b03400240200a2005470d00200c200a41016a220d200c200d4b1b22054100480d0602400240200c0d002005102a21040c010b2004200a2005102e21040b2004450d050b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200c41026a210c200a41016a210a200d210b200d0d000b02402006450d00200821060340200a410174210c2006280200210b03400240200a2005470d00200a41016a220d200a490d08200c200d200c200d4b1b22054100480d0802400240200a0d002005102a21040c010b2004200a2005102e21040b2004450d070b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200c41026a210c200a41016a210a200d210b200d0d000b200641046a22062007470d000b0b02402009450d002008102c0b200241086a2106200241046a2107200a210c03400240024020072802002006280200220b460d002002280200210d0c010b200b41016a220d200b490d06200b4101742208200d2008200d4b1b22084100480d0602400240200b0d002008102a210d0c010b2002280200200b2008102e210d0b200d450d052002200d360200200720083602002006280200210b0b2006200b41016a360200200d200b6a200c41807f72200c41ff0071200c410776220b1b3a0000200b210c200b0d000b02400240200241046a280200220c200241086a280200220b6b200a490d002002280200210c0c010b200b200a6a220d200b490d05200c410174220b200d200b200d4b1b220b4100480d0502400240200c0d00200b102a210c0c010b2002280200200c200b102e210c0b200c450d042002200c360200200241046a200b360200200241086a280200210b0b200241086a200b200a6a360200200c200b6a2004200a10db051a410021064101210d02402005450d002004102c0b4101210b4101210c410121040c130b2001410c6a2802002106200141086a280200210e200141046a280200210f02400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d04200a410174220c200b200c200b4b1b220c4100480d0402400240200a0d00200c102a210b0c010b2002280200200a200c102e210b0b200b450d032002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41023a0000200341dc006a41003602002003420137025420032002360250200f200641286c6a21094100210a4100210b2006210c034002400240200a200b460d002003280254210a0c010b200a41016a220d200a490d05200a4101742204200d2004200d4b1b220d4100480d0502400240200a0d00200d102a210a0c010b2003280254200a200d102e210a0b200a450d042003200d3602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280258210a200328025c210b200c210c0c010b0b200f2105024002402006450d00200f210503402005220a41286a2105200a2d001822134104460d01200a41196a2f0000200a411b6a2d0000411074722110200a41206a2900002114200a411c6a2800002104200a41146a2802002106200a41106a2802002112200a28020c2108200a2802042111200a2802002102200a2802082207210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d08200a410174220d200c200d200c4b1b220d4100480d0802400240200a0d00200d102a210c0c010b2003280254200a200d102e210c0b200c450d072003200d3602582003200c360254200328025c210a0b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2007490d002003280254210b0c010b200a20076a220c200a490d07200b410174220a200c200a200c4b1b220a4100480d0702400240200b0d00200a102a210b0c010b2003280254200b200a102e210b0b200b450d062003200a3602582003200b360254200328025c210a0b2003200a20076a36025c200b200a6a2002200710db051a02402011450d002002102c0b2006210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d08200a410174220d200c200d200c4b1b220d4100480d0802400240200a0d00200d102a210c0c010b2003280254200a200d102e210c0b200c450d072003200d3602582003200c360254200328025c210a0b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2006490d002003280254210b0c010b200a20066a220c200a490d07200b410174220a200c200a200c4b1b220a4100480d0702400240200b0d00200a102a210b0c010b2003280254200b200a102e210b0b200b450d062003200a3602582003200b360254200328025c210a0b2003200a20066a36025c200b200a6a2008200610db051a02402012450d002008102c0b02400240024002400240024020130e0400010203000b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d0c200a410174220c200b200c200b4b1b220c4100480d0c02400240200a0d00200c102a210b0c010b2003280254200a200c102e210b0b200b450d0b2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41003a00000340024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d0d200a410174220c200b200c200b4b1b220c4100480d0d02400240200a0d00200c102a210b0c010b2003280254200a200c102e210b0b200b450d0c2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a200441807f72200441ff00712004410776220a1b3a0000200a2104200a0d000c040b0b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d0b200a410174220c200b200c200b4b1b220c4100480d0b02400240200a0d00200c102a210b0c010b2003280254200a200c102e210b0b200b450d0a2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41013a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d0b200a410174220c200b200c200b4b1b220c4100480d0b02400240200a0d00200c102a210b0c010b2003280254200a200c102e210b0b200b450d0a2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41f0003a0000200320042014a72014422088a7200341d0006a10900520032d0000220a411f460d0220032f000120032d000341107472210d0c030b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d0a200a410174220c200b200c200b4b1b220c4100480d0a02400240200a0d00200c102a210b0c010b2003280254200a200c102e210b0b200b450d092003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41023a0000200320042014a72014422088a7200341d0006a10900520032d0000220a411f460d0120032f000120032d000341107472210d0c020b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d09200a410174220c200b200c200b4b1b220c4100480d0902400240200a0d00200c102a210b0c010b2003280254200a200c102e210b0b200b450d082003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41033a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d09200a410174220c200b200c200b4b1b220c4100480d0902400240200a0d00200c102a210b0c010b2003280254200a200c102e210b0b200b450d082003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a2010417f73220a413f7141c00072200a2010411874411875417f4a1b3a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d09200a410174220c200b200c200b4b1b220c4100480d0902400240200a0d00200c102a210b0c010b2003280254200a200c102e210b0b200b450d082003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a20104180fe03714100473a00000b20052009470d010c030b0b2003290308211420032802042104024020052009460d000340200541186a2d00004104460d01200541106a280200210b2005410c6a280200210c0240200541046a280200450d002005280200102c0b0240200b450d00200c102c0b200541286a22052009470d000b0b0240200e450d00200f102c0b02402003280258450d002003280254102c0b2000200d3b00012000200a3a0000200041036a200d4110763a0000200041086a2014370000200041046a20043600004100210c4101210d0c090b20052009460d000340200541186a2d00004104460d01200541106a280200210a2005410c6a280200210b0240200541046a280200450d002005280200102c0b0240200a450d00200b102c0b200541286a22052009470d000b0b0240200e450d00200f102c0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d05200a4101742206200c2006200c4b1b22064100480d0502400240200a0d002006102a210c0c010b2004280200200a2006102e210c0b200c450d042004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d04200b410174220a200c200a200c4b1b220a4100480d0402400240200b0d00200a102a210b0c010b2004280200200b200a102e210b0b200b450d032004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a2002200710db051a02402008450d002002102c0b410021044101210d4101210b4101210c0c110b20082010460d0003402008410d6a2d00004105460d010240200841046a280200450d002008280200102c0b200841106a22082010470d000b0b0240200e450d00200f102c0b200241086a2106200241046a2107200b210c03400240024020072802002006280200220a460d002002280200210d0c010b200a41016a220d200a490d03200a4101742208200d2008200d4b1b22084100480d0302400240200a0d002008102a210d0c010b2002280200200a2008102e210d0b200d450d022002200d360200200720083602002006280200210a0b2006200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b200b490d002002280200210c0c010b200a200b6a220d200a490d02200c410174220a200d200a200d4b1b220a4100480d0202400240200c0d00200a102a210c0c010b2002280200200c200a102e210c0b200c450d012002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2004200b10db051a4100210c4101210d2005450d022004102c0c020b1033000b1035000b4101210b0c0b0b2000200d3b00012000200a3a0000200041036a200d4110763a0000200041086a2014370000200041046a2004360000410021094101210d4101210c410121044101210541012106410121074101210b41012102410121080c080b4101210c200241086a200a41016a3602004100210d200b200a6a41003a0000200341146a2004360200200341106a20053602002003200636020c200320073602082003200836020420032009360200200341d0006a20032002109405200320032900513703382003200341d0006a41086a29000037003f20032d0050220a411f460d082000200a3a000020002003290338370001200041086a200329003f3700000b410121040b410121050b410121060b410121070b4101210b0b410121020b41012108410121090b20012d0000220a410f4b0d18200a0e100a0b0c0d0e0f101112181318141516170a0b4101210b4100210d4101210c0b410121040b410121060b410121120b410121100b410121050b410121070b410121020b410121080b41012109410121130c0f0b200141086a280200450d10200141046a280200102c0c100b200d450d0f0240200141086a280200450d00200141046a280200102c0b200141146a280200450d0f200141106a280200102c0c0f0b02402001410c6a280200220b450d00200141046a280200210a200b410474210b03400240200a41046a280200450d00200a280200102c0b200a41106a210a200b41706a220b0d000b0b200141086a280200450d0e2001280204102c0c0e0b200c450d0d02402001410c6a280200220b450d00200141046a280200210a200b41286c210b03400240200a41046a280200450d00200a280200102c0b0240200a41106a280200450d00200a410c6a280200102c0b200a41286a210a200b41586a220b0d000b0b200141086a280200450d0d2001280204102c0c0d0b200141086a280200450d0c200141046a280200102c0c0c0b2004450d0b200141086a280200450d0b200141046a280200102c0c0b0b2005450d0a200141086a280200450d0a200141046a280200102c0c0a0b2006450d0902402001410c6a280200220a450d00200141046a2802002204200a4104746a2105034002402004280208220b450d002004280200210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b200441106a210a0240200441046a280200450d002004280200102c0b200a2104200a2005470d000b0b200141086a280200450d092001280204102c0c090b02402001410c6a280200220b450d00200141046a280200210a200b41146c210b03400240200a41046a280200450d00200a280200102c0b200a41146a210a200b416c6a220b0d000b0b200141086a280200450d082001280204102c0c080b2007450d0702402001410c6a280200220a450d00200141046a2802002204200a411c6c6a2105034002402004280204220a450d0002402004410c6a280200220b450d00200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b200441086a280200450d002004280204102c0b2004411c6a210a0240200441146a280200450d002004280210102c0b200a2104200a2005470d000b0b200141086a280200450d072001280204102c0c070b200b450d0602402001410c6a280200220a450d00200141046a2802002204200a41186c6a210503400240200441046a280200450d002004280200102c0b0240200441146a280200220b450d00200428020c210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b200441186a210a0240200441106a280200450d00200428020c102c0b200a2104200a2005470d000b0b200141086a280200450d062001280204102c0c060b2002450d05200141046a220a109805200141086a280200450d05200a280200102c0c050b2008450d040240200141046a280200220a450d00200141086a280200450d00200a102c0b0240200141146a280200220a450d0002402001411c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b200141186a280200450d002001280214102c0b200141246a2802002204450d0402402001412c6a280200220a450d002004200a4104746a210503402004220d41106a21040240200d280204220a450d000240200d410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b200d41086a280200450d00200d280204102c0b20042005470d000b0b200141286a280200450d042001280224102c0c040b2009450d030240200141086a280200450d00200141046a280200102c0b0240200141146a280200220a450d00200141186a280200450d00200a102c0b200141246a280200450d03200141206a280200102c0c030b200110f5040c020b410121110b2000411f3a0000024020012d0000220a410f4b0d0002400240024002400240024002400240024002400240024002400240200a0e100001020304050607080e090e0a0b0c0d000b200b450d0e200141086a280200450d0e200141046a280200102c0c0e0b200d450d0d0240200141086a280200450d00200141046a280200102c0b200141146a280200450d0d200141106a280200102c0c0d0b200c450d0c02402001410c6a280200220b450d00200141046a280200210a200b410474210b03400240200a41046a280200450d00200a280200102c0b200a41106a210a200b41706a220b0d000b0b200141086a280200450d0c2001280204102c0c0c0b2004450d0b02402001410c6a280200220b450d00200141046a280200210a200b41286c210b03400240200a41046a280200450d00200a280200102c0b0240200a41106a280200450d00200a410c6a280200102c0b200a41286a210a200b41586a220b0d000b0b200141086a280200450d0b2001280204102c0c0b0b2006450d0a200141086a280200450d0a200141046a280200102c0c0a0b2012450d09200141086a280200450d09200141046a280200102c0c090b2010450d08200141086a280200450d08200141046a280200102c0c080b2005450d0702402001410c6a280200220a450d00200141046a2802002204200a4104746a2105034002402004280208220b450d002004280200210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b200441106a210a0240200441046a280200450d002004280200102c0b200a2104200a2005470d000b0b200141086a280200450d072001280204102c0c070b2007450d0602402001410c6a280200220b450d00200141046a280200210a200b41146c210b03400240200a41046a280200450d00200a280200102c0b200a41146a210a200b416c6a220b0d000b0b200141086a280200450d062001280204102c0c060b2002450d0502402001410c6a280200220a450d00200141046a2802002204200a411c6c6a2105034002402004280204220a450d0002402004410c6a280200220b450d00200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b200441086a280200450d002004280204102c0b2004411c6a210a0240200441146a280200450d002004280210102c0b200a2104200a2005470d000b0b200141086a280200450d052001280204102c0c050b2008450d0402402001410c6a280200220a450d00200141046a2802002204200a41186c6a210503400240200441046a280200450d002004280200102c0b0240200441146a280200220b450d00200428020c210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102c200d280200210c0b200c102c0b200a41106a210a200b41706a220b0d000b0b200441186a210a0240200441106a280200450d00200428020c102c0b200a2104200a2005470d000b0b200141086a280200450d042001280204102c0c040b2009450d03200141046a220a109805200141086a280200450d03200a280200102c0c030b2013450d020240200141046a280200220a450d00200141086a280200450d00200a102c0b0240200141146a280200220a450d0002402001411c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b200141186a280200450d002001280214102c0b200141246a2802002204450d0202402001412c6a280200220a450d002004200a4104746a210503402004220d41106a21040240200d280204220a450d000240200d410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102c0b200a410c6a210a200b41746a220b0d000b0b200d41086a280200450d00200d280204102c0b20042005470d000b0b200141286a280200450d022001280224102c0c020b2011450d010240200141086a280200450d00200141046a280200102c0b0240200141146a280200220a450d00200141186a280200450d00200a102c0b200141246a280200450d01200141206a280200102c0c010b200110f5040b200341e0006a24000b13002000410136020420004180bdc5003602000b3400200041a3dbc50036020420004100360200200041146a4104360200200041106a41bcbec500360200200041086a42083702000b130020004101360204200041dce7c5003602000b0c00200028020020011084050bc76501037f230041206b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00000eac010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab0100010b200220012802184193ecc50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000cab010b2002200128021841a4ecc500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000caa010b2002200128021841afecc50041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca9010b2002200128021841b2ecc50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41b8ecc500106121000ca8010b2002200128021841c8ecc50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41b8ecc500106121000ca7010b2002200128021841ccecc50041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41b8ecc500106121000ca6010b2002200128021841ceecc50041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca5010b2002200128021841d2ecc50041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca4010b2002200128021841d5ecc50041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000ca3010b2002200128021841d7ecc50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000ca2010b2002200128021841dbecc50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41e4ecc500106121000ca1010b2002200128021841f4ecc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca0010b2002200128021841faecc50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000c9f010b2002200128021841feecc500410c2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041016a36020c20012002410c6a418cedc500106121000c9e010b20022001280218419cedc50041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9d010b2002200128021841a0edc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9c010b2002200128021841a6edc50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000c9b010b2002200128021841aeedc50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000c9a010b2002200128021841b6edc50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000c99010b2002200128021841beedc50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000c98010b2002200128021841c7edc50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000c97010b2002200128021841d0edc50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c96010b2002200128021841d7edc50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c95010b2002200128021841deedc50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c94010b2002200128021841e5edc50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c93010b2002200128021841ecedc50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c92010b2002200128021841f5edc50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c91010b2002200128021841feedc500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c90010b200220012802184188eec500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c8f010b200220012802184192eec50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c8e010b20022001280218419beec50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c8d010b2002200128021841a4eec500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c8c010b2002200128021841aeeec500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c8b010b2002200128021841b8eec500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c8a010b2002200128021841c2eec500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c89010b2002200128021841cceec50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c88010b2002200128021841d4eec50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c87010b2002200128021841dceec50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c86010b2002200128021841e4eec50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c85010b2002200128021841eceec50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c84010b2002200128021841f5eec500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c83010b2002200128021841ffeec50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c82010b200220012802184188efc500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c81010b200220012802184192efc500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121012002200041086a36020c20012002410c6a41dcebc500106121000c80010b20022001280218419cefc500410d2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a418cedc500106121000c7f0b2002200128021841a9efc500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a418cedc500106121000c7e0b2002200128021841b3efc50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41bcefc500106121000c7d0b2002200128021841ccefc50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41d4efc500106121000c7c0b2002200128021841e4efc50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41dcebc500106121000c7b0b2002200128021841ecefc50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41f4efc500106121000c7a0b200220012802184184f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c790b20022001280218418af0c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c780b20022001280218418ff0c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c770b200220012802184194f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c760b20022001280218419af0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c750b2002200128021841a0f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c740b2002200128021841a6f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c730b2002200128021841acf0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c720b2002200128021841b2f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c710b2002200128021841b8f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c700b2002200128021841bef0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6f0b2002200128021841c4f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6e0b2002200128021841caf0c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6d0b2002200128021841cff0c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6c0b2002200128021841d4f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6b0b2002200128021841daf0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6a0b2002200128021841e0f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c690b2002200128021841e6f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c680b2002200128021841ecf0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c670b2002200128021841f2f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c660b2002200128021841f8f0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c650b2002200128021841fef0c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c640b200220012802184184f1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c630b200220012802184189f1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c620b20022001280218418ef1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c610b200220012802184193f1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c600b200220012802184198f1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5f0b20022001280218419df1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5e0b2002200128021841a2f1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5d0b2002200128021841a7f1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5c0b2002200128021841acf1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5b0b2002200128021841b1f1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5a0b2002200128021841b6f1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c590b2002200128021841bbf1c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c580b2002200128021841c0f1c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c570b2002200128021841c6f1c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c560b2002200128021841ccf1c50041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c550b2002200128021841d5f1c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c540b2002200128021841dbf1c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c530b2002200128021841e1f1c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c520b2002200128021841e7f1c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c510b2002200128021841eef1c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c500b2002200128021841f5f1c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4f0b2002200128021841fcf1c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4e0b200220012802184183f2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4d0b200220012802184189f2c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4c0b20022001280218418ef2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4b0b200220012802184194f2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4a0b20022001280218419af2c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c490b2002200128021841a1f2c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c480b2002200128021841a8f2c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c470b2002200128021841aff2c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c460b2002200128021841b6f2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c450b2002200128021841bcf2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c440b2002200128021841c2f2c50041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c430b2002200128021841cbf2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c420b2002200128021841d1f2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c410b2002200128021841d7f2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c400b2002200128021841ddf2c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3f0b2002200128021841e4f2c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3e0b2002200128021841ebf2c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3d0b2002200128021841f2f2c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3c0b2002200128021841f9f2c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3b0b2002200128021841fff2c50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3a0b200220012802184184f3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c390b20022001280218418af3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c380b200220012802184190f3c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c370b200220012802184197f3c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c360b20022001280218419ef3c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c350b2002200128021841a5f3c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c340b2002200128021841acf3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c330b2002200128021841b2f3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c320b2002200128021841b8f3c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c310b2002200128021841bff3c50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c300b2002200128021841c7f3c50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2f0b2002200128021841cff3c500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2e0b2002200128021841d9f3c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2d0b2002200128021841e0f3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2c0b2002200128021841e6f3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2b0b2002200128021841ecf3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2a0b2002200128021841f2f3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c290b2002200128021841f8f3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c280b2002200128021841fef3c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c270b200220012802184184f4c500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c260b20022001280218418ff4c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c250b200220012802184195f4c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c240b20022001280218419bf4c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c230b2002200128021841a2f4c50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c220b2002200128021841aaf4c50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c210b2002200128021841b2f4c500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c200b2002200128021841bcf4c50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1f0b2002200128021841c3f4c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1e0b2002200128021841c9f4c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1d0b2002200128021841cff4c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1c0b2002200128021841d5f4c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1b0b2002200128021841dbf4c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1a0b2002200128021841e1f4c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c190b2002200128021841e7f4c500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c180b2002200128021841f2f4c500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c170b2002200128021841fcf4c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c160b200220012802184188f5c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c150b200220012802184194f5c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c140b2002200128021841a0f5c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c130b2002200128021841acf5c500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c120b2002200128021841b9f5c500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c110b2002200128021841c6f5c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c100b2002200128021841d2f5c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0f0b2002200128021841def5c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0e0b2002200128021841eaf5c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0d0b2002200128021841f6f5c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0c0b200220012802184184f6c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0b0b200220012802184192f6c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0a0b2002200128021841a0f6c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c090b2002200128021841aef6c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c080b2002200128021841baf6c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c070b2002200128021841c8f6c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c060b2002200128021841d6f6c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c050b2002200128021841e4f6c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c040b2002200128021841f2f6c500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c030b2002200128021841fff6c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c020b200220012802184190f7c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c010b2002200128021841a1f7c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000b20002d00082101024020002802042203450d00200141ff0171210441012101024020040d00024020034101470d0020002d0009450d00200028020022042d00004104710d004101210120042802184198b0c00041012004411c6a28020028020c1100000d010b2000280200220128021841ec94c60041012001411c6a28020028020c11000021010b200020013a00080b200241206a2400200141ff01714100470bbe04020d7f017e230041c0006b22032400200128020022042001280208220541047422066a210720012802042108200421010240024002402005450d00200641706a2109200341306a410172210a200341306a41026a2106200341206a410172220b41076a210c20042101034020012d000021052006200141036a2d00003a00002003200141016a2f00003b01300240200541ac01470d00200141106a21010c020b2003410c6a41026a20062d0000220d3a0000200320032f0130220e3b010c200141046a280200210f200141086a2903002110200a200e3b0000200a41026a200d3a0000200320053a0030200320103703382003200f360234200341206a200341306a20021086052003200b2900003703102003200c290000370017024020032d00202205411f470d00200941706a2109200141106a22012007470d010c030b0b200020053a000020002003290310370001200041086a200329001737000002402009450d00200141106a210103400240024020012d000022054109460d00200541ac01470d010c030b0240200141046a280200220528020441ffffffff0371450d002005280200102c0b2005102c0b200141106a22012007470d000b0b2008450d022004102c0c020b20012007460d0003400240024020012d000022054109460d00200541ac01470d010c030b0240200141046a280200220528020441ffffffff0371450d002005280200102c0b2005102c0b200141106a22012007470d000b0b02402008450d002004102c0b2000411f3a00000b200341c0006a24000bb4c10202097f017e230041106b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae01200441017422062005200620054b1b22064100480dae010240024020040d002006102a21050c010b200228020420042006102e21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad01200441017422062005200620054b1b22064100480dad010240024020040d002006102a21050c010b200228020420042006102e21050b2005450dac0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dac01200441017422082005200820054b1b22084100480dac010240024020040d002008102a21050c010b200628020020042008102e21050b2005450dab0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490dac01200441017422082005200820054b1b22084100480dac010240024020040d002008102a21050c010b200628020020042008102e21050b2005450dab0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d002008102a21050c010b200628020020042008102e21050b2005450daa0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d002008102a21050c010b200628020020042008102e21050b2005450daa0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d002008102a21050c010b200628020020042008102e21050b2005450da90120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d002008102a21050c010b200628020020042008102e21050b2005450da90120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da901200441017422062005200620054b1b22064100480da9010240024020040d002006102a21050c010b200228020420042006102e21050b2005450da80120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da801200441017422062005200620054b1b22064100480da8010240024020040d002006102a21050c010b200228020420042006102e21050b2005450da70120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da701200441017422072006200720064b1b22074100480da7010240024020040d002007102a21060c010b200928020020042007102e21060b2006450da60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da8012004410174220a2006200a20064b1b220a4100480da8010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da701200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da601200441017422072006200720064b1b22074100480da6010240024020040d002007102a21060c010b200928020020042007102e21060b2006450da50120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da7012004410174220a2006200a20064b1b220a4100480da7010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da501200441017422062005200620054b1b22064100480da5010240024020040d002006102a21050c010b200928020020042006102e21050b2005450da40120022005360204200241086a20063602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a410e3a0000200320012802042204280204220520042802002204200420054102746a20021087052003210420032d0000411f470dab0120012802042802082105200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da6012004410174220a2006200a20064b1b220a4100480da6010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da401200441017422062005200620054b1b22064100480da4010240024020040d002006102a21050c010b200228020420042006102e21050b2005450da30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da301200441017422072006200720064b1b22074100480da3010240024020040d002007102a21060c010b200928020020042007102e21060b2006450da20120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da4012004410174220a2006200a20064b1b220a4100480da4010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da201200441017422072006200720064b1b22074100480da2010240024020040d002007102a21060c010b200928020020042007102e21060b2006450da10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da3012004410174220a2006200a20064b1b220a4100480da3010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da201200441017422062005200620054b1b22064100480da2010240024020040d002006102a21050c010b200928020020042006102e21050b2005450da10120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da101200441017422062005200620054b1b22064100480da1010240024020040d002006102a21050c010b200228020420042006102e21050b2005450da00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da001200441017422062005200620054b1b22064100480da0010240024020040d002006102a21050c010b200228020420042006102e21050b2005450d9f0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9f01200441017422072006200720064b1b22074100480d9f010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9e0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da0012004410174220a2006200a20064b1b220a4100480da0010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9f01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9e01200441017422072006200720064b1b22074100480d9e010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9d0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9f012004410174220a2006200a20064b1b220a4100480d9f010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9e01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9d01200441017422072006200720064b1b22074100480d9d010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9c0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9e012004410174220a2006200a20064b1b220a4100480d9e010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9d01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9c01200441017422072006200720064b1b22074100480d9c010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9b0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9d012004410174220a2006200a20064b1b220a4100480d9d010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9c01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9b01200441017422072006200720064b1b22074100480d9b010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9a0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9c012004410174220a2006200a20064b1b220a4100480d9c010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9b01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a01200441017422082007200820074b1b22084100480d9a010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d990120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b012004410174220b2007200b20074b1b220b4100480d9b010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9a01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b01200441017422092006200920064b1b22094100480d9b010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d9a012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9901200441017422082007200820074b1b22084100480d99010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d980120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a012004410174220b2007200b20074b1b220b4100480d9a010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a01200441017422092006200920064b1b22094100480d9a010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d99012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9801200441017422082007200820074b1b22084100480d98010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d970120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d99012004410174220b2007200b20074b1b220b4100480d99010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9901200441017422092006200920064b1b22094100480d99010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d98012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9701200441017422082007200820074b1b22084100480d97010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d960120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d98012004410174220b2007200b20074b1b220b4100480d98010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9801200441017422092006200920064b1b22094100480d98010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d97012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d950120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d97012004410174220b2007200b20074b1b220b4100480d97010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9701200441017422092006200920064b1b22094100480d97010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d96012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d940120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d96012004410174220b2007200b20074b1b220b4100480d96010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9601200441017422092005200920054b1b22094100480d96010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d95012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c93010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9401200441017422082007200820074b1b22084100480d94010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d930120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d95012004410174220b2007200b20074b1b220b4100480d95010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9501200441017422092005200920054b1b22094100480d95010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d94012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9301200441017422082007200820074b1b22084100480d93010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d920120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d94012004410174220b2007200b20074b1b220b4100480d94010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9401200441017422092006200920064b1b22094100480d94010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d93012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9201200441017422082007200820074b1b22084100480d92010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d910120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d93012004410174220b2007200b20074b1b220b4100480d93010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9301200441017422092006200920064b1b22094100480d93010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d92012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9101200441017422082007200820074b1b22084100480d91010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d900120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d92012004410174220b2007200b20074b1b220b4100480d92010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9201200441017422092005200920054b1b22094100480d92010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d91012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c8f010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9001200441017422082007200820074b1b22084100480d90010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8f0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d91012004410174220b2007200b20074b1b220b4100480d91010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9101200441017422092005200920054b1b22094100480d91010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d90012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8f01200441017422082007200820074b1b22084100480d8f010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8e0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d90012004410174220b2007200b20074b1b220b4100480d90010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8f01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9001200441017422092006200920064b1b22094100480d90010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8f012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8e01200441017422082007200820074b1b22084100480d8e010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8d0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8f012004410174220b2007200b20074b1b220b4100480d8f010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8e01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8f01200441017422092006200920064b1b22094100480d8f010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8e012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8c0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8f012004410174220b2007200b20074b1b220b4100480d8f010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8d01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8f01200441017422092006200920064b1b22094100480d8f010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d90012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8e0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8e012004410174220b2007200b20074b1b220b4100480d8e010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8f01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8e01200441017422092006200920064b1b22094100480d8e010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8f012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8c01200441017422082007200820074b1b22084100480d8c010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8d0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8d012004410174220b2007200b20074b1b220b4100480d8d010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8e01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8d01200441017422092005200920054b1b22094100480d8d010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d8e012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8b01200441017422082007200820074b1b22084100480d8b010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8c0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8c012004410174220b2007200b20074b1b220b4100480d8c010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8d01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8c01200441017422092006200920064b1b22094100480d8c010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8d012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8a01200441017422082007200820074b1b22084100480d8a010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8b0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8b012004410174220b2007200b20074b1b220b4100480d8b010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8c01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8b01200441017422092005200920054b1b22094100480d8b010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d8c012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c87010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8901200441017422082007200820074b1b22084100480d89010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8a0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8a012004410174220b2007200b20074b1b220b4100480d8a010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8b01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8a01200441017422092005200920054b1b22094100480d8a010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d8b012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8801200441017422082007200820074b1b22084100480d88010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d890120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d89012004410174220b2007200b20074b1b220b4100480d89010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8a01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8901200441017422092006200920064b1b22094100480d89010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8a012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8701200441017422082007200820074b1b22084100480d87010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d880120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d88012004410174220b2007200b20074b1b220b4100480d88010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8801200441017422092006200920064b1b22094100480d88010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d89012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8601200441017422082007200820074b1b22084100480d86010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d870120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d87012004410174220b2007200b20074b1b220b4100480d87010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8701200441017422092006200920064b1b22094100480d87010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d88012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8501200441017422082007200820074b1b22084100480d85010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d860120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d86012004410174220b2007200b20074b1b220b4100480d86010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8601200441017422092006200920064b1b22094100480d86010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d87012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8401200441017422082005200820054b1b22084100480d84010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d850120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d8401200441017422082005200820054b1b22084100480d84010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d850120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d840120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d840120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8201200441017422072005200720054b1b22074100480d82010240024020040d002007102a21050c010b200228020420042007102e21050b2005450d830120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a00002003200620021088052003210420032d0000411f470d87010c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8101200441017422062005200620054b1b22064100480d81010240024020040d002006102a21050c010b200228020420042006102e21050b2005450d820120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c20021089052003210420032d0000411f470d86010c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8001200441017422082005200820054b1b22084100480d80010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d810120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d8001200541017422042008200420084b1b22044100480d80010240024020050d002004102a21050c010b200628020020052004102e21050b2005450d810120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d7f200441017422072005200720054b1b22074100480d7f0240024020040d002007102a21050c010b200628020020042007102e21050b2005450d800120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d7f200541017422042007200420074b1b22044100480d7f0240024020050d002004102a21050c010b200628020020052004102e21050b2005450d800120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7e200441017422062005200620054b1b22064100480d7e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7d200441017422062005200620054b1b22064100480d7d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7c200441017422062005200620054b1b22064100480d7c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7b200441017422062005200620054b1b22064100480d7b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7a200441017422062005200620054b1b22064100480d7a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d79200441017422062005200620054b1b22064100480d790240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d78200441017422062005200620054b1b22064100480d780240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d77200441017422062005200620054b1b22064100480d770240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d76200441017422062005200620054b1b22064100480d760240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d75200441017422062005200620054b1b22064100480d750240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d74200441017422062005200620054b1b22064100480d740240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d73200441017422062005200620054b1b22064100480d730240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d72200441017422062005200620054b1b22064100480d720240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d71200441017422062005200620054b1b22064100480d710240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d70200441017422062005200620054b1b22064100480d700240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6f200441017422062005200620054b1b22064100480d6f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6e200441017422062005200620054b1b22064100480d6e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6d200441017422062005200620054b1b22064100480d6d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6c200441017422062005200620054b1b22064100480d6c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6b200441017422062005200620054b1b22064100480d6b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6a200441017422062005200620054b1b22064100480d6a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d69200441017422062005200620054b1b22064100480d690240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d68200441017422062005200620054b1b22064100480d680240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d67200441017422062005200620054b1b22064100480d670240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d66200441017422062005200620054b1b22064100480d660240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d65200441017422062005200620054b1b22064100480d650240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d64200441017422062005200620054b1b22064100480d640240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d63200441017422062005200620054b1b22064100480d630240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d62200441017422062005200620054b1b22064100480d620240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d61200441017422062005200620054b1b22064100480d610240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d60200441017422062005200620054b1b22064100480d600240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5f200441017422062005200620054b1b22064100480d5f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5e200441017422062005200620054b1b22064100480d5e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5d200441017422062005200620054b1b22064100480d5d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5a200441017422062005200620054b1b22064100480d5a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d59200441017422062005200620054b1b22064100480d590240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d58200441017422062005200620054b1b22064100480d580240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d57200441017422062005200620054b1b22064100480d570240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d56200441017422062005200620054b1b22064100480d560240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d55200441017422062005200620054b1b22064100480d550240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d54200441017422062005200620054b1b22064100480d540240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d53200441017422062005200620054b1b22064100480d530240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d52200441017422062005200620054b1b22064100480d520240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d51200441017422062005200620054b1b22064100480d510240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d50200441017422062005200620054b1b22064100480d500240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4f200441017422062005200620054b1b22064100480d4f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4e200441017422062005200620054b1b22064100480d4e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4d200441017422062005200620054b1b22064100480d4d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4c200441017422062005200620054b1b22064100480d4c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4b200441017422062005200620054b1b22064100480d4b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4a200441017422062005200620054b1b22064100480d4a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d49200441017422062005200620054b1b22064100480d490240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d48200441017422062005200620054b1b22064100480d480240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d47200441017422062005200620054b1b22064100480d470240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d46200441017422062005200620054b1b22064100480d460240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d45200441017422062005200620054b1b22064100480d450240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d44200441017422062005200620054b1b22064100480d440240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d43200441017422062005200620054b1b22064100480d430240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d42200441017422062005200620054b1b22064100480d420240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d41200441017422062005200620054b1b22064100480d410240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d40200441017422062005200620054b1b22064100480d400240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3f200441017422062005200620054b1b22064100480d3f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3e200441017422062005200620054b1b22064100480d3e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3d200441017422062005200620054b1b22064100480d3d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3c200441017422062005200620054b1b22064100480d3c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3b200441017422062005200620054b1b22064100480d3b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3a200441017422062005200620054b1b22064100480d3a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d39200441017422062005200620054b1b22064100480d390240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d38200441017422062005200620054b1b22064100480d380240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d37200441017422062005200620054b1b22064100480d370240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d36200441017422062005200620054b1b22064100480d360240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d35200441017422062005200620054b1b22064100480d350240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d34200441017422062005200620054b1b22064100480d340240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d33200441017422062005200620054b1b22064100480d330240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d32200441017422062005200620054b1b22064100480d320240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d31200441017422062005200620054b1b22064100480d310240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d30200441017422062005200620054b1b22064100480d300240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2f200441017422062005200620054b1b22064100480d2f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2e200441017422062005200620054b1b22064100480d2e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2d200441017422062005200620054b1b22064100480d2d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2c200441017422062005200620054b1b22064100480d2c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2b200441017422062005200620054b1b22064100480d2b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2a200441017422062005200620054b1b22064100480d2a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d29200441017422062005200620054b1b22064100480d290240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d28200441017422062005200620054b1b22064100480d280240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d27200441017422062005200620054b1b22064100480d270240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d26200441017422062005200620054b1b22064100480d260240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d25200441017422062005200620054b1b22064100480d250240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d24200441017422062005200620054b1b22064100480d240240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d23200441017422062005200620054b1b22064100480d230240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d22200441017422062005200620054b1b22064100480d220240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d20200441017422062005200620054b1b22064100480d200240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1f200441017422062005200620054b1b22064100480d1f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1e200441017422062005200620054b1b22064100480d1e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1d200441017422062005200620054b1b22064100480d1d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1c200441017422062005200620054b1b22064100480d1c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1b200441017422062005200620054b1b22064100480d1b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1a200441017422062005200620054b1b22064100480d1a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d19200441017422062005200620054b1b22064100480d190240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d18200441017422062005200620054b1b22064100480d180240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d17200441017422062005200620054b1b22064100480d170240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d16200441017422062005200620054b1b22064100480d160240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d15200441017422062005200620054b1b22064100480d150240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d11200441017422062005200620054b1b22064100480d110240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d10200441017422062005200620054b1b22064100480d100240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0f200441017422062005200620054b1b22064100480d0f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0e200441017422062005200620054b1b22064100480d0e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0d200441017422062005200620054b1b22064100480d0d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0c200441017422062005200620054b1b22064100480d0c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0b200441017422062005200620054b1b22064100480d0b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0a200441017422062005200620054b1b22064100480d0a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d09200441017422062005200620054b1b22064100480d090240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411f3a000020012d00004109470d090240200141046a280200220228020441ffffffff0371450d002002280200102c200128020421020b2002102c0c090b1033000b1035000b1035000b1033000b1035000b1033000b1033000b1035000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d002002280200102c200128020421020b2002102c0b200341106a24000ba80301057f2004410c6a2105200441086a210602400240034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d03200741017422092008200920084b1b22094100480d030240024020070d002009102a21080c010b200428020420072009102e21080b2008450d022004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b024020022003460d002004410c6a2105200441086a2106034020022802002101034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d05200741017422092008200920084b1b22094100480d050240024020070d002009102a21080c010b200428020420072009102e21080b2008450d042004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b200241046a22022003470d000b0b2000411f3a00000f0b1033000b1035000ba10301067f02400240024020014107752203200141c00071220472452003417f4720044572460d002002410c6a2105200241086a2106034002400240200628020020052802002204460d00200228020421070c010b200441016a22072004490d04200441017422082007200820074b1b22084100480d040240024020040d002008102a21070c010b200228020420042008102e21070b2007450d032002200736020420062008360200200528020021040b2005200441016a360200200720046a200141807f723a0000200341c000712104200321012003410775220721032007200472452007417f4720044572470d000b0b02400240200241086a2802002002410c6a2802002204460d00200228020421030c010b200441016a22032004490d02200441017422072003200720034b1b22074100480d020240024020040d002007102a21030c010b200228020420042007102e21030b2003450d0120022003360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200320046a200141ff00713a00002000411f3a00000f0b1033000b1035000ba50302017e067f02400240024020014207872203502001a7220441c00071452205712003427f52200572460d002002410c6a2106200241086a2107034002400240200728020020062802002205460d00200228020421080c010b200541016a22082005490d04200541017422092008200920084b1b22094100480d040240024020050d002009102a21080c010b200228020420052009102e21080b2008450d032002200836020420072009360200200628020021050b2006200541016a360200200820056a200441807f723a00002003a72104200342078722012103200150200441c00071452205712001427f52200572470d000b0b02400240200241086a2802002002410c6a2802002205460d00200228020421080c010b200541016a22082005490d02200541017422062008200620084b1b22064100480d020240024020050d002006102a21080c010b200228020420052006102e21080b2008450d0120022008360204200241086a20063602002002410c6a28020021050b2002410c6a200541016a360200200820056a200441ff00713a00002000411f3a00000f0b1033000b1035000bdd03010a7f230041306b22022400200241216a220341076a210441002105410021064100210741002108410821090240024002400340200241186a2001108b05024020022802184101470d002000200229021c370204200041013602002000410c6a200241186a410c6a29020037020002402007450d00200921070340024020072d00004109470d000240200741046a220a280200220528020441ffffffff0371450d002005280200102c200a28020021050b2005102c0b200741106a2107200641706a22060d000b0b2008450d042009102c0c040b200220032900003703082002200429000037000f20022d0020210a2002200229000f37001f200220022903083703180240024020072008470d00200741016a220b2007490d032005200b2005200b4b1b220841ffffffff00712008470d032008410474220b4100480d030240024020070d00200b102a21090c010b20092006200b102e21090b2009450d010b200920066a220b200a3a0000200b41016a2002290318370000200b41086a200229001f370000200541026a2105200641106a2106200741016a2107200a41ff01714106460d030c010b0b1033000b1035000b20002009360204200041003602002000410c6a2007360200200041086a20083602000b200241306a24000bedb501020b7f017e230041f0006b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d02200320054f0d0120052003103f000b200241013a0048200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1037200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c630b2001280200220620046a2d000021072001410c6a2208200536020002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200741bf014b0d0020070ec001b802b802010203b80200000000000405060708090a00000000000000000b0c000000000d0e0f101100000012131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901b8020b2000410b3a000420004101360200200041056a20073a00000cbb020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da202200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410221070cbe020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1037200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbe020b4102210a410221070cb9020b4103210a410221070cb8020b4101210a0b410221070cb6020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da202200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410321070cbd020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1037200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbd020b4102210a410321070cb8020b4103210a410321070cb7020b4101210a0b410321070cb5020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da202200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410421070cbc020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1037200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbc020b4102210a410421070cb7020b4103210a410421070cb6020b4101210a0b410421070cb4020b410621070cb3020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cb7020b410721070cb2020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cb6020b410821070cb1020b200241d8006a2001108c054104210a200228025822074101460da201200241e0006a280200210b41002106200228025c210c02400240200241e4006a280200220941027422050d00410021040c010b2005410275220441ffffffff03712004470dd901200441027422034100480dd9012003102a220a450db2020b02402009450d00200941027421032005417c6a2106200a2109200c2105034020092005280200360200200941046a2109200541046a21052003417c6a22030d000b200641027641016a21060b0240200b450d00200c102c0b20022d005c4105470daf022007450daf0220022802640da3010caf020b410a21070caf020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cb3020b410b21070cae020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22044f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210720082004360200200741ff00712001411f71742009722109200141076a2101200421052007418001710d000b20014120490d01410d210120074110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cb2020b0240024020032004460d00200441016a22012004490dda01200320014f0d0120012003103f000b200241013a0048200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1037200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000cb2020b200620046a2d0000210520082001360200024020050d00410c21074100210a0cae020b200041163a000420004101360200200041056a20053a00000cb1020b410d21070cac020b410e21070cab020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddb012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000caf020b410f21070caa020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddb012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cae020b411021070ca9020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddb012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cad020b411121070ca8020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddb012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cac020b411221070ca7020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddb012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000cab020b411321070ca6020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddc01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000caa020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9c010b20032001460d9a012001417f460dd8012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9b010b200aad210d411421070ca5020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddd01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca9020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9d010b20032001460d9b012001417f460dd9012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9c010b200aad210d411521070ca4020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dde01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca8020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9e010b20032001460d9c012001417f460dda012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9d010b200aad210d411621070ca3020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddf01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca7020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9f010b20032001460d9d012001417f460ddb012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9e010b200aad210d411721070ca2020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de001200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca6020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca0010b20032001460d9e012001417f460ddc012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9f010b200aad210d411821070ca1020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de101200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca5020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca1010b20032001460d9f012001417f460ddd012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da0010b200aad210d411921070ca0020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de201200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca4020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca2010b20032001460da0012001417f460dde012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da1010b200aad210d411a21070c9f020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de301200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca3020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca3010b20032001460da1012001417f460ddf012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da2010b200aad210d411b21070c9e020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de401200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca2020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca4010b20032001460da2012001417f460de0012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da3010b200aad210d411c21070c9d020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de501200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca1020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca5010b20032001460da3012001417f460de1012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da4010b200aad210d411d21070c9c020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de601200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca0020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca6010b20032001460da4012001417f460de2012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da5010b200aad210d411e21070c9b020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de701200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9f020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca7010b20032001460da5012001417f460de3012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da6010b200aad210d411f21070c9a020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de801200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9e020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca8010b20032001460da6012001417f460de4012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b41202107024020054120490d00410d21012004410f4b0da7010b200aad210d0c99020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de901200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9d020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca9010b20032001460da7012001417f460de5012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da8010b200aad210d412121070c98020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dea01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010caa010b20032001460da8012001417f460de6012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da9010b200aad210d412221070c97020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450deb01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9b020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cab010b20032001460da9012001417f460de7012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0daa010b200aad210d412321070c96020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dec01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9a020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cac010b20032001460daa012001417f460de8012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dab010b200aad210d412421070c95020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ded01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c99020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cad010b20032001460dab012001417f460de9012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dac010b200aad210d412521070c94020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dee01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c98020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cae010b20032001460dac012001417f460dea012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dad010b200aad210d412621070c93020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450def01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c97020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010caf010b20032001460dad012001417f460deb012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dae010b200aad210d412721070c92020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df001200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c96020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb0010b20032001460dae012001417f460dec012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0daf010b200aad210d412821070c91020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df101200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c95020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb1010b20032001460daf012001417f460ded012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0db0010b200aad210d412921070c90020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df201200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c94020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb2010b20032001460db0012001417f460dee012003200141016a2207490d8e02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0db1010b200aad210d412a21070c8f020b0240024020032005460d00200441026a21012005417f460def01200320014f0d0120012003103f000b200241013a0048200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1037200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c93020b200620056a2d0000210920082001360200024020090d00412b21074100210a0c8f020b200041153a000420004101360200200041056a20093a00000c92020b0240024020032005460d00200441026a21012005417f460def01200320014f0d0120012003103f000b200241013a0048200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1037200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c92020b200620056a2d0000210920082001360200024020090d00412c21074100210a0c8e020b200041153a000420004101360200200041056a20093a00000c91020b41002101410021090240024002400340410d210a2001411f4b0d010240024020032005460d002005417f460df3012003200541016a22074f0d01200541016a2003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10374105210a0c020b200620056a2c0000210420082007360200200441ff00712001411f71742009722109200141076a21012007210520044100480d000b200441c00071210502402001411f4b0d0020050d020b0240024020014120490d0020050d010b200441ff01714108490d0320014120490d032005450d010c030b20044180017241ff017141f7014b0d020b2000200a36020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c92020b2009417f2001411f71747221090b412d21070c8c020b4200210d4100210102400240024002400340410e21072001413f4b0d010240024020032005460d002005417f460df4012003200541016a22094f0d01200541016a2003103f000b200241013a0008200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241086a360238200241286a200241d8006a10372002290328210d20022802302101410521070c030b200620056a2d0000210420082009360200200441ff0071220aad2001413f71ad86200d84210d200141076a210120092105200441187441187522094100480d000b200941c00071210502402001413f4b0d0020050d030b02400240200141c000490d0020050d010b200141c000490d0420090d010c040b200a41ff00460d030b0b200020073a0004200020022f00183b000520004101360200200041106a2001360200200041086a200d370200200041076a2002411a6a2d00003a00000c91020b200d427f2001413f71ad8684210d0b412e21070c8b020b02400240200320056b4104490d00200441056a21012005417b4b0def01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a103720004281808080d000370300200041086a2002290328370200200041106a200241286a41086a2802003602000c8f020b200620056a280000210920082001360200412f21070c8a020b02400240200320056b4108490d00200441096a2101200541774b0def01200320014f0d0120012003103f000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10372002290328210d200041106a2002280230360200200041086a200d37020020004281808080d0003703000c8e020b200620056a290000210d20082001360200413021070c89020b413121070c88020b413221070c87020b413321070c86020b413421070c85020b413521070c84020b413621070c83020b413721070c82020b413821070c81020b413921070c80020b413a21070cff010b413b21070cfe010b413c21070cfd010b413d21070cfc010b413e21070cfb010b413f21070cfa010b41c00021070cf9010b41c10021070cf8010b41c20021070cf7010b41c30021070cf6010b41c40021070cf5010b41c50021070cf4010b41c60021070cf3010b41c70021070cf2010b41c80021070cf1010b41c90021070cf0010b41ca0021070cef010b41cb0021070cee010b41cc0021070ced010b41cd0021070cec010b41ce0021070ceb010b41cf0021070cea010b41d00021070ce9010b41d10021070ce8010b41d20021070ce7010b41d30021070ce6010b41d40021070ce5010b41d50021070ce4010b41d60021070ce3010b41d70021070ce2010b41d80021070ce1010b41d90021070ce0010b41da0021070cdf010b41db0021070cde010b41dc0021070cdd010b41dd0021070cdc010b41de0021070cdb010b41df0021070cda010b41e00021070cd9010b41e10021070cd8010b41e20021070cd7010b41e30021070cd6010b41e40021070cd5010b41e50021070cd4010b41e60021070cd3010b41e70021070cd2010b41e80021070cd1010b41e90021070cd0010b41ea0021070ccf010b41eb0021070cce010b41ec0021070ccd010b41ed0021070ccc010b41ee0021070ccb010b41ef0021070cca010b41f00021070cc9010b41f10021070cc8010b41f20021070cc7010b41f30021070cc6010b41f40021070cc5010b41f50021070cc4010b41f60021070cc3010b41f70021070cc2010b41f80021070cc1010b41f90021070cc0010b41fa0021070cbf010b41fb0021070cbe010b41fc0021070cbd010b41fd0021070cbc010b41fe0021070cbb010b41ff0021070cba010b41800121070cb9010b41810121070cb8010b41820121070cb7010b41830121070cb6010b41840121070cb5010b41850121070cb4010b41860121070cb3010b41870121070cb2010b41880121070cb1010b41890121070cb0010b418a0121070caf010b418b0121070cae010b418c0121070cad010b418d0121070cac010b418e0121070cab010b418f0121070caa010b41900121070ca9010b41910121070ca8010b41920121070ca7010b41930121070ca6010b41940121070ca5010b41950121070ca4010b41960121070ca3010b41970121070ca2010b41980121070ca1010b41990121070ca0010b419a0121070c9f010b419b0121070c9e010b419c0121070c9d010b419d0121070c9c010b419e0121070c9b010b419f0121070c9a010b41a00121070c99010b41a10121070c98010b41a20121070c97010b41a30121070c96010b41a40121070c95010b41a50121070c94010b41a60121070c93010b41a70121070c92010b41a80121070c91010b41a90121070c90010b41aa0121070c8f010b41ab0121070c8e010b200041013602002000200241d8006a41047222012902003702042000410c6a200141086a2902003702000c91010b2002280260102c0c8b010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8e010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8c010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c8a010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c88010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c86010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c84010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c82010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c80010b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c7e0b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c7c0b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c7a0b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c780b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c760b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c740b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c720b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c700b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c6e0b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c6c0b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c6a0b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c680b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c660b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c640b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a2802003602000c620b417f20051047000b417f20091047000b417f20091047000b417f20091047000b417f200541016a1047000b417f200541016a1047000b1035000b417f200541016a1047000b417f200541016a1047000b417f20011047000b417f200541016a1047000b417f200541016a1047000b417f200541016a1047000b417f200541016a1047000b417f200541016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f200141016a1047000b417f20011047000b417f20011047000b417f200541016a1047000b417f200541016a1047000b200520011047000b200520011047000b20092003103f000b20092003103f000b20092003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b200141016a2003103f000b0240024002400240024020042006460d0020042006490d01024020060d00024020040d004104210a0c020b200a102c4104210a0c010b200a20044102742006410274102e220a450d060b4100210941002104034002402009411f4d0d00410f21010c090b20012802082207200128020c2205460d07200541016a22032005490d0220072003490d03200128020020056a2d0000210520082003360200200541ff00712009411f71742004722104200941076a21092005418001710d000b20094120490d03410d21012005410f4b0d070c030b41b3c7c500412441acfec5001036000b417f20031047000b20032007103f000b410c102a2209450d0120092004360208200920063602042009200a360200410921070b20004100360200200041106a200d3703002000410c6a2009360200200041096a200a3a0000200041086a20073a00000c030b1033000b200241013a0018200241ec006a41013602002002420137025c200241f0f7c5003602582002412b36023c2002200241386a3602682002200241186a360238200241286a200241d8006a1037410521010b2000200136020420004101360200200041086a2002290328370200200041106a200241286a41086a280200360200200641ffffffff0371450d00200a102c0b200241f0006a24000bd20703067f017e067f230041d0006b220224004100210341002104024002400240024002400240024002400240024002400240034002402003411f4d0d00410f21030c020b0240024020012802082205200128020c2206460d00200641016a22072006490d05200520074f0d0120072005103f000b200241013a0027200241cc006a41013602002002420137023c200241f0f7c5003602382002412b36021c2002200241186a3602482002200241276a360218200241286a200241386a1037410521030c020b200128020020066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b20034120490d01410d210320064110490d010b200241086a41086a200241286a41086a280200220136020020022002290328220837030820002003360204200041086a2008370200200041106a2001360200200041013602000c0a0b20024100360210200242043703082004450d0841042109410021034100210a03402003210b200a220c41016a210a410021034100210503402003411f4b0d04024002402001280208220d200128020c2206460d00200641016a22072006490d05200d20074f0d012007200d103f000b2002200b36020c2002200c360210200241013a0027200241cc006a41013602002002420137023c200241f0f7c5003602382002412b36021c2002200241186a3602482002200241276a360218200241286a200241386a103720022802282103200228022c2106200228023021074100210e410521010c090b200128020020066a2d000021062001200736020c200641ff00712003411f71742005722105200341076a21032006418001710d000b024020034120490d002006410f4d0d002002200b36020c2002200c360210410d21010c070b02400240200c200b460d00200b2103200c210b0c010b200b41016a2203200b490d06200b41017422062003200620034b1b220341ffffffff03712003470d06200341027422064100480d0602400240200b0d002006102a21090c010b2009200b4102742006102e21090b2009450d05200220093602080b2005410876210e2009200b4102746a2005360200200a2004460d080c000b0b417f20071047000b417f20071047000b2002200b36020c2002200c360210410f21010c020b1033000b1035000b0b20004101360200200041106a20073602002000410c6a2006360200200041086a20033602002000200e410874200172360204200b450d022009102c0c020b2002200336020c2002200a3602100b20002002290308370204200041003602002000410c6a200241106a2802003602000b200241d0006a24000bb4c10202097f017e230041106b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae01200441017422062005200620054b1b22064100480dae010240024020040d002006102a21050c010b200228020420042006102e21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad01200441017422062005200620054b1b22064100480dad010240024020040d002006102a21050c010b200228020420042006102e21050b2005450dac0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dac01200441017422082005200820054b1b22084100480dac010240024020040d002008102a21050c010b200628020020042008102e21050b2005450dab0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490dac01200441017422082005200820054b1b22084100480dac010240024020040d002008102a21050c010b200628020020042008102e21050b2005450dab0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d002008102a21050c010b200628020020042008102e21050b2005450daa0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490dab01200441017422082005200820054b1b22084100480dab010240024020040d002008102a21050c010b200628020020042008102e21050b2005450daa0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d002008102a21050c010b200628020020042008102e21050b2005450da90120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490daa01200441017422082005200820054b1b22084100480daa010240024020040d002008102a21050c010b200628020020042008102e21050b2005450da90120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da901200441017422062005200620054b1b22064100480da9010240024020040d002006102a21050c010b200228020420042006102e21050b2005450da80120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da801200441017422062005200620054b1b22064100480da8010240024020040d002006102a21050c010b200228020420042006102e21050b2005450da70120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da701200441017422072006200720064b1b22074100480da7010240024020040d002007102a21060c010b200928020020042007102e21060b2006450da60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da8012004410174220a2006200a20064b1b220a4100480da8010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da701200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da601200441017422072006200720064b1b22074100480da6010240024020040d002007102a21060c010b200928020020042007102e21060b2006450da50120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da7012004410174220a2006200a20064b1b220a4100480da7010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da501200441017422062005200620054b1b22064100480da5010240024020040d002006102a21050c010b200928020020042006102e21050b2005450da40120022005360204200241086a20063602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a410e3a0000200320012802042204280204220520042802002204200420054102746a20021087052003210420032d0000411f470dab0120012802042802082105200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da6012004410174220a2006200a20064b1b220a4100480da6010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da401200441017422062005200620054b1b22064100480da4010240024020040d002006102a21050c010b200228020420042006102e21050b2005450da30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da301200441017422072006200720064b1b22074100480da3010240024020040d002007102a21060c010b200928020020042007102e21060b2006450da20120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da4012004410174220a2006200a20064b1b220a4100480da4010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490da201200441017422072006200720064b1b22074100480da2010240024020040d002007102a21060c010b200928020020042007102e21060b2006450da10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da3012004410174220a2006200a20064b1b220a4100480da3010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450da201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490da201200441017422062005200620054b1b22064100480da2010240024020040d002006102a21050c010b200928020020042006102e21050b2005450da10120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da101200441017422062005200620054b1b22064100480da1010240024020040d002006102a21050c010b200228020420042006102e21050b2005450da00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da001200441017422062005200620054b1b22064100480da0010240024020040d002006102a21050c010b200228020420042006102e21050b2005450d9f0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9f01200441017422072006200720064b1b22074100480d9f010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9e0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490da0012004410174220a2006200a20064b1b220a4100480da0010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9f01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9e01200441017422072006200720064b1b22074100480d9e010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9d0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9f012004410174220a2006200a20064b1b220a4100480d9f010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9e01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9d01200441017422072006200720064b1b22074100480d9d010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9c0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9e012004410174220a2006200a20064b1b220a4100480d9e010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9d01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9c01200441017422072006200720064b1b22074100480d9c010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9b0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9d012004410174220a2006200a20064b1b220a4100480d9d010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9c01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490d9b01200441017422072006200720064b1b22074100480d9b010240024020040d002007102a21060c010b200928020020042007102e21060b2006450d9a0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490d9c012004410174220a2006200a20064b1b220a4100480d9c010240024020040d00200a102a21060c010b20092802002004200a102e21060b2006450d9b01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a01200441017422082007200820074b1b22084100480d9a010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d990120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b012004410174220b2007200b20074b1b220b4100480d9b010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9a01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b01200441017422092006200920064b1b22094100480d9b010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d9a012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9901200441017422082007200820074b1b22084100480d99010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d980120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a012004410174220b2007200b20074b1b220b4100480d9a010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a01200441017422092006200920064b1b22094100480d9a010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d99012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9801200441017422082007200820074b1b22084100480d98010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d970120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d99012004410174220b2007200b20074b1b220b4100480d99010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9901200441017422092006200920064b1b22094100480d99010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d98012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9701200441017422082007200820074b1b22084100480d97010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d960120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d98012004410174220b2007200b20074b1b220b4100480d98010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9801200441017422092006200920064b1b22094100480d98010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d97012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9601200441017422082007200820074b1b22084100480d96010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d950120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d97012004410174220b2007200b20074b1b220b4100480d97010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9701200441017422092006200920064b1b22094100480d97010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d96012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9501200441017422082007200820074b1b22084100480d95010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d940120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d96012004410174220b2007200b20074b1b220b4100480d96010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9601200441017422092005200920054b1b22094100480d96010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d95012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c93010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9401200441017422082007200820074b1b22084100480d94010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d930120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d95012004410174220b2007200b20074b1b220b4100480d95010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9501200441017422092005200920054b1b22094100480d95010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d94012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9301200441017422082007200820074b1b22084100480d93010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d920120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d94012004410174220b2007200b20074b1b220b4100480d94010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9401200441017422092006200920064b1b22094100480d94010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d93012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9201200441017422082007200820074b1b22084100480d92010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d910120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d93012004410174220b2007200b20074b1b220b4100480d93010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9301200441017422092006200920064b1b22094100480d93010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d92012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9101200441017422082007200820074b1b22084100480d91010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d900120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d92012004410174220b2007200b20074b1b220b4100480d92010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9201200441017422092005200920054b1b22094100480d92010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d91012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c8f010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9001200441017422082007200820074b1b22084100480d90010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8f0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d91012004410174220b2007200b20074b1b220b4100480d91010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d9001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9101200441017422092005200920054b1b22094100480d91010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d90012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8f01200441017422082007200820074b1b22084100480d8f010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8e0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d90012004410174220b2007200b20074b1b220b4100480d90010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8f01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9001200441017422092006200920064b1b22094100480d90010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8f012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8e01200441017422082007200820074b1b22084100480d8e010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8d0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8f012004410174220b2007200b20074b1b220b4100480d8f010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8e01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8f01200441017422092006200920064b1b22094100480d8f010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8e012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8c0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8f012004410174220b2007200b20074b1b220b4100480d8f010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8d01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8f01200441017422092006200920064b1b22094100480d8f010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d90012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8d01200441017422082007200820074b1b22084100480d8d010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8e0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8e012004410174220b2007200b20074b1b220b4100480d8e010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8f01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8e01200441017422092006200920064b1b22094100480d8e010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8f012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8c01200441017422082007200820074b1b22084100480d8c010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8d0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8d012004410174220b2007200b20074b1b220b4100480d8d010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8e01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8d01200441017422092005200920054b1b22094100480d8d010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d8e012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8b01200441017422082007200820074b1b22084100480d8b010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8c0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8c012004410174220b2007200b20074b1b220b4100480d8c010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8d01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8c01200441017422092006200920064b1b22094100480d8c010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8d012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8a01200441017422082007200820074b1b22084100480d8a010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8b0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8b012004410174220b2007200b20074b1b220b4100480d8b010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8c01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8b01200441017422092005200920054b1b22094100480d8b010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d8c012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c87010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8901200441017422082007200820074b1b22084100480d89010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d8a0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d8a012004410174220b2007200b20074b1b220b4100480d8a010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8b01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d8a01200441017422092005200920054b1b22094100480d8a010240024020040d002009102a21050c010b200a28020020042009102e21050b2005450d8b012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8801200441017422082007200820074b1b22084100480d88010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d890120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d89012004410174220b2007200b20074b1b220b4100480d89010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8a01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8901200441017422092006200920064b1b22094100480d89010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d8a012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8701200441017422082007200820074b1b22084100480d87010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d880120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d88012004410174220b2007200b20074b1b220b4100480d88010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8801200441017422092006200920064b1b22094100480d88010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d89012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8601200441017422082007200820074b1b22084100480d86010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d870120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d87012004410174220b2007200b20074b1b220b4100480d87010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8701200441017422092006200920064b1b22094100480d87010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d88012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d8501200441017422082007200820074b1b22084100480d85010240024020040d002008102a21070c010b200a28020020042008102e21070b2007450d860120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d86012004410174220b2007200b20074b1b220b4100480d86010240024020040d00200b102a21070c010b200a2802002004200b102e21070b2007450d8701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d8601200441017422092006200920064b1b22094100480d86010240024020040d002009102a21060c010b200a28020020042009102e21060b2006450d87012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8401200441017422082005200820054b1b22084100480d84010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d850120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d8401200441017422082005200820054b1b22084100480d84010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d850120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d840120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d8301200441017422082005200820054b1b22084100480d83010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d840120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8201200441017422072005200720054b1b22074100480d82010240024020040d002007102a21050c010b200228020420042007102e21050b2005450d830120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a00002003200620021088052003210420032d0000411f470d87010c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8101200441017422062005200620054b1b22064100480d81010240024020040d002006102a21050c010b200228020420042006102e21050b2005450d820120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c20021089052003210420032d0000411f470d86010c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d8001200441017422082005200820054b1b22084100480d80010240024020040d002008102a21050c010b200628020020042008102e21050b2005450d810120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d8001200541017422042008200420084b1b22044100480d80010240024020050d002004102a21050c010b200628020020052004102e21050b2005450d810120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d7f200441017422072005200720054b1b22074100480d7f0240024020040d002007102a21050c010b200628020020042007102e21050b2005450d800120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d7f200541017422042007200420074b1b22044100480d7f0240024020050d002004102a21050c010b200628020020052004102e21050b2005450d800120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7e200441017422062005200620054b1b22064100480d7e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7d200441017422062005200620054b1b22064100480d7d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7c200441017422062005200620054b1b22064100480d7c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7b200441017422062005200620054b1b22064100480d7b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d7a200441017422062005200620054b1b22064100480d7a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d79200441017422062005200620054b1b22064100480d790240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d78200441017422062005200620054b1b22064100480d780240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d77200441017422062005200620054b1b22064100480d770240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d76200441017422062005200620054b1b22064100480d760240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d75200441017422062005200620054b1b22064100480d750240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d74200441017422062005200620054b1b22064100480d740240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d73200441017422062005200620054b1b22064100480d730240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d72200441017422062005200620054b1b22064100480d720240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d71200441017422062005200620054b1b22064100480d710240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d70200441017422062005200620054b1b22064100480d700240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6f200441017422062005200620054b1b22064100480d6f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d7020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6e200441017422062005200620054b1b22064100480d6e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6d200441017422062005200620054b1b22064100480d6d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6c200441017422062005200620054b1b22064100480d6c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6b200441017422062005200620054b1b22064100480d6b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d6a200441017422062005200620054b1b22064100480d6a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d69200441017422062005200620054b1b22064100480d690240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d68200441017422062005200620054b1b22064100480d680240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d67200441017422062005200620054b1b22064100480d670240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d66200441017422062005200620054b1b22064100480d660240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d65200441017422062005200620054b1b22064100480d650240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d64200441017422062005200620054b1b22064100480d640240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d63200441017422062005200620054b1b22064100480d630240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d62200441017422062005200620054b1b22064100480d620240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d61200441017422062005200620054b1b22064100480d610240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d60200441017422062005200620054b1b22064100480d600240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5f200441017422062005200620054b1b22064100480d5f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d6020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5e200441017422062005200620054b1b22064100480d5e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5d200441017422062005200620054b1b22064100480d5d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5c200441017422062005200620054b1b22064100480d5c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5b200441017422062005200620054b1b22064100480d5b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d5a200441017422062005200620054b1b22064100480d5a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d59200441017422062005200620054b1b22064100480d590240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d58200441017422062005200620054b1b22064100480d580240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d57200441017422062005200620054b1b22064100480d570240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d56200441017422062005200620054b1b22064100480d560240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d55200441017422062005200620054b1b22064100480d550240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d54200441017422062005200620054b1b22064100480d540240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d53200441017422062005200620054b1b22064100480d530240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d52200441017422062005200620054b1b22064100480d520240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d51200441017422062005200620054b1b22064100480d510240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d50200441017422062005200620054b1b22064100480d500240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4f200441017422062005200620054b1b22064100480d4f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d5020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4e200441017422062005200620054b1b22064100480d4e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4d200441017422062005200620054b1b22064100480d4d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4c200441017422062005200620054b1b22064100480d4c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4b200441017422062005200620054b1b22064100480d4b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d4a200441017422062005200620054b1b22064100480d4a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d49200441017422062005200620054b1b22064100480d490240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d48200441017422062005200620054b1b22064100480d480240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d47200441017422062005200620054b1b22064100480d470240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d46200441017422062005200620054b1b22064100480d460240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d45200441017422062005200620054b1b22064100480d450240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d44200441017422062005200620054b1b22064100480d440240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d43200441017422062005200620054b1b22064100480d430240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d42200441017422062005200620054b1b22064100480d420240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d41200441017422062005200620054b1b22064100480d410240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d40200441017422062005200620054b1b22064100480d400240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3f200441017422062005200620054b1b22064100480d3f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d4020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3e200441017422062005200620054b1b22064100480d3e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3d200441017422062005200620054b1b22064100480d3d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3c200441017422062005200620054b1b22064100480d3c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3b200441017422062005200620054b1b22064100480d3b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d3a200441017422062005200620054b1b22064100480d3a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d39200441017422062005200620054b1b22064100480d390240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d38200441017422062005200620054b1b22064100480d380240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d37200441017422062005200620054b1b22064100480d370240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d36200441017422062005200620054b1b22064100480d360240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d35200441017422062005200620054b1b22064100480d350240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d34200441017422062005200620054b1b22064100480d340240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d33200441017422062005200620054b1b22064100480d330240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d32200441017422062005200620054b1b22064100480d320240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d31200441017422062005200620054b1b22064100480d310240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d30200441017422062005200620054b1b22064100480d300240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2f200441017422062005200620054b1b22064100480d2f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d3020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2e200441017422062005200620054b1b22064100480d2e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2d200441017422062005200620054b1b22064100480d2d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2c200441017422062005200620054b1b22064100480d2c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2b200441017422062005200620054b1b22064100480d2b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d2a200441017422062005200620054b1b22064100480d2a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d29200441017422062005200620054b1b22064100480d290240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d28200441017422062005200620054b1b22064100480d280240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d27200441017422062005200620054b1b22064100480d270240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d26200441017422062005200620054b1b22064100480d260240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d25200441017422062005200620054b1b22064100480d250240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d24200441017422062005200620054b1b22064100480d240240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d23200441017422062005200620054b1b22064100480d230240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d22200441017422062005200620054b1b22064100480d220240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d20200441017422062005200620054b1b22064100480d200240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1f200441017422062005200620054b1b22064100480d1f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d2020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1e200441017422062005200620054b1b22064100480d1e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1d200441017422062005200620054b1b22064100480d1d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1c200441017422062005200620054b1b22064100480d1c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1b200441017422062005200620054b1b22064100480d1b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d1a200441017422062005200620054b1b22064100480d1a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d19200441017422062005200620054b1b22064100480d190240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d18200441017422062005200620054b1b22064100480d180240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d17200441017422062005200620054b1b22064100480d170240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d16200441017422062005200620054b1b22064100480d160240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1720022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d15200441017422062005200620054b1b22064100480d150240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1620022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1520022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1420022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1320022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d14200441017422062005200620054b1b22064100480d140240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d13200441017422062005200620054b1b22064100480d130240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1220022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d12200441017422062005200620054b1b22064100480d120240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d11200441017422062005200620054b1b22064100480d110240024020040d002006102a21050c010b200228020420042006102e21050b2005450d1020022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d10200441017422062005200620054b1b22064100480d100240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0f20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0f200441017422062005200620054b1b22064100480d0f0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0e20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0e200441017422062005200620054b1b22064100480d0e0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0d20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0d200441017422062005200620054b1b22064100480d0d0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0c20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0c200441017422062005200620054b1b22064100480d0c0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0b20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0b200441017422062005200620054b1b22064100480d0b0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0a20022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d0a200441017422062005200620054b1b22064100480d0a0240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0920022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d09200441017422062005200620054b1b22064100480d090240024020040d002006102a21050c010b200228020420042006102e21050b2005450d0820022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411f3a000020012d00004109470d090240200141046a280200220228020441ffffffff0371450d002002280200102c200128020421020b2002102c0c090b1033000b1035000b1035000b1033000b1035000b1033000b1033000b1035000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d002002280200102c200128020421020b2002102c0b200341106a24000b8207010b7f230041d0086b22022400410021034100210402400240024002400240024002400240034002402003411f4d0d00410f21030c020b0240024020012802082205200128020c2206460d00200641016a22072006490d05200520074f0d0120072005103f000b200241013a0089082002411c6a41013602002002420137020c200241f0f7c5003602082002412b36029c08200220024198086a360218200220024189086a36029808200241b8086a200241086a1037410521030c020b2001280200220820066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b20034120490d01410d210320064110490d010b2000200336020420004101360200200041086a20022903b808370200200041106a200241b8086a41086a2802003602000c060b024020040d002000428080808010370200200041086a42003702000c060b200241086a410041800810da051a41002106410021094101210a4100210b034002400240200520076b2004200b6b22034180082003418008491b2203490d00200720036a220c2007490d042005200c4f0d01200c2005103f000b200241013a00a708200241cc086a4101360200200242013702bc08200241f0f7c5003602b8082002412b36029c08200220024198086a3602c8082002200241a7086a36029808200241a8086a200241b8086a103720024194086a200241b0086a280200360000200220022903a80837008c08200041053a000420002002290089083700052000410c6a20024190086a290000370000200041013602002009450d07200a102c0c070b200241086a200820076a200310db051a2001200c36020c02400240200920066b2003490d00200620036a210c0c010b200620036a220c2006490d0520094101742207200c2007200c4b1b22074100480d050240024020090d002007102a210a0c010b200a20092007102e210a0b200a450d04200721090b200a20066a200241086a200310db051a20042003200b6a220b4d0d05200128020c21072001280208210520012802002108200c21060c000b0b417f20071047000b2007200c1047000b1033000b1035000b200241086a200a200c1058024020022802084101470d0002402009450d00200a102c0b200041083a0004200041013602000c010b2000200a3602042000410c6a200c360200200041086a2009360200200041003602000b200241d0086a24000b1500200120002802002200280200200028020810480bb30401067f200441046a21050240024002400240200441086a2802002004410c6a2802002206460d00200528020021070c010b200641016a22072006490d02200641017422082007200820074b1b22084100480d020240024020060d002008102a21070c010b200528020020062008102e21070b2007450d0120042007360204200441086a20083602002004410c6a28020021060b2004410c6a2208200641016a360200200720066a20024101463a0000200441086a2109034002400240200928020020082802002206460d00200528020021070c010b200641016a22072006490d032006410174220a2007200a20074b1b220a4100480d030240024020060d00200a102a21070c010b20052802002006200a102e21070b2007450d02200420073602042009200a360200200828020021060b2008200641016a360200200720066a200141807f72200141ff0071200141077622061b3a00002006210120060d000b024020024101470d002004410c6a2107200441086a2108034002400240200828020020072802002206460d00200528020021010c010b200641016a22012006490d04200641017422092001200920014b1b22094100480d040240024020060d002009102a21010c010b200528020020062009102e21010b2001450d032004200136020420082009360200200728020021060b2007200641016a360200200120066a200341807f72200341ff0071200341077622061b3a00002006210320060d000b0b2000411f3a00000f0b1033000b1035000bb007010a7f230041d0006b2202240002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d02200320054f0d0120052003103f000b200241013a001f200241cc006a41013602002002420137023c200241f0f7c5003602382002412b3602342002200241306a36024820022002411f6a360230200241206a200241386a10372002411b6a200241286a28020036000020022002290320370013200220022900103703002002200241176a290000370007200041053a0004200020022903003700052000410c6a2002290007370000200041013602000c040b2001280200220620046a2d000021072001200536020c024020074102490d00200041173a000420004101360200200041056a20073a00000c040b410120036b2108200441026a2104410021054100210902400240034002402005411f4d0d00410f21050c020b02400240200820046a4102460d002004450d06200320044f0d0120042003103f000b200241013a0000200241cc006a41013602002002420137023c200241f0f7c5003602382002412b3602342002200241306a36024820022002360230200241106a200241386a1037410521050c020b200620046a417f6a2d0000210a2001200436020c200a41ff00712005411f71742009722109200441016a2104200541076a2105200a418001710d000b20054120490d01410d2105200a4110490d010b2000200536020420004101360200200041086a2002290310370200200041106a200241106a41086a2802003602000c040b4100210502402007410171450d002004417f6a2104410021054100210b02400240034002402005411f4d0d00410f21040c020b0240024020032004460d002004417f460d082003200441016a22084f0d01200441016a2003103f000b200241013a0000200241cc006a41013602002002420137023c200241f0f7c5003602382002412b3602342002200241306a36024820022002360230200241106a200241386a1037410521040c020b200620046a2d0000210a2001200836020c200a41ff00712005411f7174200b72210b200541076a210520082104200a418001710d000b20054120490d01410d2104200a4110490d010b2000200436020420004101360200200041086a2002290310370200200041106a200241106a41086a2802003602000c050b410121050b20002009360204200041003602002000410c6a200b360200200041086a20053602000c030b417f20051047000b417f20041047000b417f200441016a1047000b200241d0006a24000bee0201067f230041c0006b2202240041002103410021040240024003400240024002402003411f4b0d002001280204220520012802082206460d01200641016a22072006490d04200520074f0d0220072005103f000b200041013602002000410f3a00040c040b200241013a000f200241346a410136020020024201370224200241f0f7c5003602202002412b36023c2002200241386a36023020022002410f6a360238200241106a200241206a10372002410b6a200241186a28020036000020022002290310370003200041053a0004200020022900003700052000410c6a200241076a290000370000200041013602000c030b200128020020066a2d0000210620012007360208200641ff00712003411f71742004722104200341076a21032006418001710d000b0240024020034120490d002006410f4b0d010b20004100360200200020043602040c020b200041013602002000410d3a00040c010b417f20071047000b200241c0006a24000bd307030e7f017e017f200241086a2103200241046a210420012802002205210602400240024002400240034002400240200428020020032802002207460d00200228020021080c010b200741016a22082007490d03200741017422092008200920084b1b22094100480d030240024020070d002009102a21080c010b200228020020072009102e21080b2008450d022002200836020020042009360200200328020021070b2003200741016a360200200820076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b2001280204220a2001410c6a2802002206410c6c6a210b200141086a280200210c200a21072006450d03200a21072005450d03200b41746a210d200241086a210841002107200a210e0340200e2103024003402003280200220f0d01200741016a2107200b2003410c6a2203470d000c070b0b2003410c6a210e200741016a21102005417f6a2105200341046a2902002111034002400240200241046a220428020020082802002206460d00200228020021090c010b200641016a22092006490d04200641017422012009200120094b1b22014100480d040240024020060d002001102a21090c010b200228020020062001102e21090b2009450d032002200936020020042001360200200828020021060b2008200641016a360200200920066a200741807f72200741ff0071200741077622061b3a00002006210720060d000b2011422088a722122106034002400240200428020020082802002207460d00200228020021090c010b200741016a22092007490d04200741017422012009200120094b1b22014100480d040240024020070d002001102a21090c010b200228020020072001102e21090b2009450d032002200936020020042001360200200828020021070b2008200741016a360200200920076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b0240024020042802002206200828020022076b2012490d00200228020021060c010b200720126a22092007490d03200641017422072009200720094b1b22074100480d030240024020060d002007102a21060c010b200228020020062007102e21060b2006450d022002200636020020042007360200200828020021070b2008200720126a360200200620076a200f201210db051a02402011a7450d00200f102c0b200d2003460d032010210720050d000c030b0b1033000b1035000b2003410c6a21070b2007200b460d000340024020072802002206450d00200741046a280200450d002006102c0b2007410c6a2207200b470d000b0b0240200c450d00200a102c0b2000411f3a00000baf06010a7f20012802042103200128020021044100210541002106410021074101210820012802082209210a024002400340024020062007470d002005200641016a220b2005200b4b1b22074100480d030240024020060d002007102a21080c010b200820062007102e21080b2008450d020b200820066a200a41807f72200a41ff0071200a410776220b1b3a0000200541026a2105200641016a2106200b210a200b0d000b02400240200720066b2009490d002007210a0c010b200620096a220a2006490d0220074101742205200a2005200a4b1b220a4100480d020240024020070d00200a102a21080c010b20082007200a102e21080b2008450d010b200820066a2004200910db051a02402003450d002004102c0b200128020c210302400240200a20096b20066b200141146a2802002205490d00200920056a20066a2104200a210c0c010b200920066a220b20056a2204200b490d02200a410174220b2004200b20044b1b220c4100480d0202400240200a0d00200c102a21080c010b2008200a200c102e21080b2008450d010b200820096a20066a2003200510db051a200241086a210b200241046a21072004210a0340024002402007280200200b2802002206460d00200228020021050c010b200641016a22052006490d03200641017422092005200920054b1b22094100480d030240024020060d002009102a21050c010b200228020020062009102e21050b2005450d022002200536020020072009360200200b28020021060b200b200641016a360200200520066a200a41807f72200a41ff0071200a41077622061b3a00002006210a20060d000b02400240200241046a280200220a200241086a28020022066b2004490d002002280200210a0c010b200620046a22052006490d02200a41017422062005200620054b1b22064100480d0202400240200a0d002006102a210a0c010b2002280200200a2006102e210a0b200a450d012002200a360200200241046a2006360200200241086a28020021060b200241086a200620046a360200200a20066a2008200410db051a0240200c450d002008102c0b2000411f3a00000240200141106a280200450d002003102c0b0f0b1033000b1035000bf20103027f017e057f024020002802082201200028020c460d00034020002001411c6a36020820012802102202450d01200141146a2902002103024020012802042204450d00200141086a280200210502402001410c6a2802002201450d0020014104742106200421010340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102c200728020021080b2008102c0b200141106a2101200641706a22060d000b0b2005450d002004102c0b02402003a7450d002002102c0b20002802082201200028020c470d000b0b02402000280204450d002000280200102c0b0be50101067f024020002802082201200028020c460d0003402000200141186a36020820012802002202450d01200141146a2802002103200141106a2802002104200128020c210502402001280204450d002002102c0b02402003450d0020034104742103200521010340024020012d00004109470d000240200141046a2206280200220228020441ffffffff0371450d002002280200102c200628020021020b2002102c0b200141106a2101200341706a22030d000b0b02402004450d002005102c0b20002802082201200028020c470d000b0b02402000280204450d002000280200102c0b0bf20103027f017e057f024020002802082201200028020c460d00034020002001411c6a36020820012802102202450d01200141146a2902002103024020012802042204450d00200141086a280200210502402001410c6a2802002201450d0020014104742106200421010340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102c200728020021080b2008102c0b200141106a2101200641706a22060d000b0b2005450d002004102c0b02402003a7450d002002102c0b20002802082201200028020c470d000b0b02402000280204450d002000280200102c0b0bce0101057f024020002802082201450d00200028020022022001411c6c6a21030340024020022802042200450d0002402002410c6a2802002201450d00200141047421010340024020002d00004109470d000240200041046a2204280200220528020441ffffffff0371450d002005280200102c200428020021050b2005102c0b200041106a2100200141706a22010d000b0b200241086a280200450d002002280204102c0b2002411c6a21000240200241146a280200450d002002280210102c0b2000210220002003470d000b0b0bef04010b7f230041c080016b2202240020022001109205410121030240024020022802004101470d0020002002290204370204200041013602002000410c6a2002410c6a2902003702000c010b20022802042104200241004180800110da052105410021064100210702400240024002402004450d00410021084100210641012103410021090340024002402001280204220a200128020822076b200420096b220b41808001200b41808001491b220b490d002007200b6a220c2007490d04200a200c4f0d01200c200a103f000b200541013a008f8001200541b480016a4101360200200542013702a48001200541f0f7c5003602a080012005412b3602bc80012005200541b880016a3602b0800120052005418f80016a3602b880012005419080016a200541a080016a10372005418b80016a2005419880016a2802003600002005200529039080013700838001200041053a00042000200529008080013700052000410c6a2005418780016a290000370000200041013602002006450d062003102c0c060b2005200128020020076a200b10db05210a2001200c36020802400240200620086b200b490d002008200b6a21070c010b2008200b6a22072008490d052006410174220c2007200c20074b1b220c4100480d050240024020060d00200c102a21030c010b20032006200c102e21030b2003450d04200c21060b200320086a200a200b10db051a200721082004200b20096a22094b0d000b0b2000200336020420004100360200200041146a2007360200200041106a41003602002000410c6a2007360200200041086a20063602000c030b2007200c1047000b1033000b1035000b200241c080016a24000b8f1f03127f017e037f23004180026b220524000240024020014115490d00410121064101210702400240034020012108200021092006200771410173210a024002400240034002400240024002402004450d00024020064101710d0020002001109b052004417f6a21040b2001410276220741036c210b2007410174210c4100210d20014132490d03200741016a210e200020074103746a220f28020020002007417f6a220d4103746a2210280200201041046a2802002210200f41046a280200220f200f20104b1b10dd052211450d01417f410120114100481b21100c020b20002001109c050c0b0b417f200f201047200f2010491b21100b2007200d2010417f4622101b210f024002402000200e4103746a22112802002000200d200720101b22124103746a2207280200200741046a2802002207201141046a280200220d200d20074b1b10dd052211450d00417f410120114100481b21070c010b417f200d200747200d2007491b21070b4102410120101b20102007417f4622071b210d024002402000200e201220071b22114103746a22102802002000200f4103746a2207280200200741046a2802002207201041046a2802002210201020074b1b10dd05220e450d00417f4101200e4100481b21100c010b417f201020074720102007491b21100b200c4101722107200d2010417f4622126a2113024002402000200c4103746a220d2802002000200c417f6a22104103746a220e280200200e41046a280200220e200d41046a280200220d200d200e4b1b10dd052214450d00417f410120144100481b210e0c010b417f200d200e47200d200e491b210e0b200c2010200e417f46220e1b210d2013200e6a211302400240200020074103746a221428020020002010200c200e1b220e4103746a220c280200200c41046a280200220c201441046a28020022102010200c4b1b10dd052214450d00417f410120144100481b210c0c010b417f2010200c472010200c491b210c0b2013200c417f46220c6a21100240024020002007200e200c1b22134103746a220c2802002000200d4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b10dd05220e450d00417f4101200e4100481b210c0c010b417f200c200747200c2007491b210c0b200b41016a21072010200c417f4622146a2115024002402000200b4103746a220e2802002000200b417f6a220c4103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b10dd052216450d00417f410120164100481b21100c010b417f200e201047200e2010491b21100b200b200c2010417f4622101b210e201520106a211502400240200020074103746a22162802002000200c200b20101b22104103746a220c280200200c41046a280200220c201641046a280200220b200b200c4b1b10dd052216450d00417f410120164100481b210c0c010b417f200b200c47200b200c491b210c0b2015200c417f46220c6a211502400240200020072010200c1b220b4103746a220c2802002000200e4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b10dd052210450d00417f410120104100481b21100c010b417f200c200747200c2007491b21100b200f201120121b2107200d201320141b210c200e200b2010417f4622101b210b201520106a210d0b024002402000200c4103746a220e280200200020074103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b10dd05220f450d00417f4101200f4100481b21100c010b417f200e201047200e2010491b21100b200c20072010417f46220e1b2110200d200e6a210d024002402000200b4103746a220f28020020002007200c200e1b220e4103746a2207280200200741046a2802002207200f41046a280200220c200c20074b1b10dd05220f450d00417f4101200f4100481b21070c010b417f200c200747200c2007491b21070b200d2007417f46220c6a2107024002400240024002402000200b200e200c1b220d4103746a220b280200200020104103746a220c280200200c41046a280200220c200b41046a280200220b200b200c4b1b10dd05220e450d00200e4100480d010c020b200b200c4f0d010b200741016a2207410c490d0102402001410176220b450d00200020014103746a41786a21072000210c0340200c2902002117200c200729020037020020072017370200200c41086a210c200741786a2107200b417f6a220b0d000b0b20012010417f736a2110410121070c020b200d21100b20074521070b0240200745200a724101710d0020002001109d050d090b2003450d010240201020014f0d00024002402003280200200020104103746a2207280200200741046a280200220c200341046a280200220b200b200c4b1b10dd05220e450d00200e41004e0d010c050b200b200c490d040b200029020021172000200729020037020020072017370200200041786a21122000410c6a2113200041086a2114200028020421072000280200210d4100210b2001210e0340024002400240200b200e417f6a22114f0d002013200b4103746a210c034002400240200d200c417c6a280200200c28020022102007200720104b1b10dd05220f450d00200f4100480d030c010b20072010490d020b200c41086a210c2011200b41016a220b470d000c020b0b0240200b20114f0d002012200e4103746a210c2011210e034002400240200d200c280200200c41046a28020022102007200720104b1b10dd05220f450d00200f4100480d010c050b200720104f0d040b200c41786a210c200b200e417f6a220e490d000b0b200b21110b200020073602042000200d36020002402001201141016a2207490d00200020074103746a2100200120076b220141154f0d040c0b0b200720011047000b2014200b4103746a221029020021172010200c290200370200200c2017370200200b41016a210b0c000b0b0b41c4ffc500201020011038000b20080d0141f8fec500410041001038000b20002109200121080b201020084f0d02200929020021172009200920104103746a2207290200370200200720173702002009280204210c2009280200211241002100410021184100211902402008417f6a220e450d002009410c6a21074100211803400240024002402007417c6a2802002012200c2007280200220b200b200c4b1b10dd052210450d00201041004e0d010c020b200b200c490d010b200e21190240200e20184d0d00200920084103746a41786a2107200e211903400240024020072802002012200c200741046a280200220b200b200c4b1b10dd052210450d00201041004e0d010c030b200b200c490d020b200741786a21072019417f6a221920184b0d000b0b0240024020192018490d00200e2019490d010c040b201820191047000b2019200e103f000b200741086a2107200e201841016a2218470d000b200e2118200e21190b200941086a220720194103746a210e41800121144100211141002110410021014180012106200720184103746a221a210d03400240200e200d6b22074187104b220a0d002007410376220741807f6a200720112000492001201049220b72220f1b21070240200f450d0020062007200b1b210620072014200b1b21140c010b2007200741017622066b21140b024020012010470d00024020060d002005221021010c010b4100210720052110200d210b0340201020073a0000200741016a210702400240200b2802002012200c200b41046a280200220f200f200c4b1b10dd052201450d00417f410120014100481b210f0c010b417f200f200c47200f200c491b210f0b200b41086a210b2010200f417f476a211020062007470d000b200521010b024020112000470d00024020140d0020054180016a220021110c010b200e41786a21074100210b20054180016a210003402000200b3a0000200b41016a210b0240024020072802002012200c200741046a280200220f200f200c4b1b10dd052211450d00417f410120114100481b210f0c010b417f200f200c47200f200c491b210f0b200741786a21072000200f417f466a21002014200b470d000b20054180016a21110b0240200020116b2207201020016b220b200b20074b1b2213450d00200d20012d00004103746a22072802042115200728020021162007200e20112d0000417f734103746a290200370200024020134101460d00410021070340200e201120076a220b2d0000417f734103746a200d200120076a41016a220f2d00004103746a290200370200200d200f2d00004103746a200e200b41016a2d0000417f734103746a290200370200200741026a210b200741016a220f2107200b2013490d000b2011200f6a21112001200f6a21010b200e20112d0000417f734103746a2207201536020420072016360200201141016a2111200141016a21010b200e20144103746b200e20112000461b210e200d20064103746a200d20012010461b210d200a0d000b02400240200120104f0d00200e21070340200d2010417f6a22102d00004103746a220b2902002117200b200741786a22072902003702002007201737020020012010490d000c020b0b200d2107201120004f0d000340200729020021172007200e2000417f6a22002d0000417f734103746a220b290200370200200b2017370200200741086a210720112000490d000b0b2009200c36020420092012360200024020082007201a6b41037620186a22014d0d00200929020021172009200920014103746a220729020037020020072017370200200820016b220c450d02200c20012001200c4b1b210b20084103762110200741086a2100024002402001200c417f6a220c490d002000200c200220072004109a05200921000c010b20092001200220032004109a0520072103200c21010b200b20104f2106201920184d2107200141154f0d010c040b0b4188ffc500200120081038000b4198ffc500411c41b4ffc5001036000b4188ffc500201020081038000b20014102490d00200041786a211341002114410121120340201241037421072012417f6a2110201241016a2112024002400240200020076a22072802002211200020104103746a220f280200200f41046a280200220c200741046a280200220b200b200c4b1b10dd05220e450d00200e4100480d010c020b200b200c4f0d010b2007200f29020037020002402010450d002014210c20132107024003400240024020112007280200200741046a280200220e200b200b200e4b1b10dd05220d450d00200d4100480d010c030b200b200e4f0d030b20002010417f6a22104103746a210f200741086a2007290200370200200741786a2107200c41016a220e200c49210d200e210c200d450d000b0b200741086a210f0b200f200b360204200f20113602000b2014417f6a2114201341086a211320122001470d000b0b20054180026a24000bf50202057f017e02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034103746a220329020021072003200020044103746a220429020037020020042007370200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024103746a220329020021072003200020044103746a2204290200370200200420073702002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034103746a220129020021072001200020044103746a2200290200370200200020073702000b0f0b4188ffc500200420011038000b41f8fec500200320011038000bb20102037f017e024020014101762202450d00200020012002417f6a109e052002417e6a210203402002417f460d01200020012002109e052002417f6a21020c000b0b0240024020014102490d00200141037420006a41786a21022001210303402003417f6a220420014f0d02200029020021052000200229020037020020022005370200200020044100109e05200241786a210220042103200441014b0d000b0b0f0b4188ffc5002003417f6a20011038000b9a06050a7f017e017f017e037f200041686a2102200041786a2103200141324921044101210541002106024003400240024020052001490d00410021070c010b200320054103746a210841012107034002400240200841086a22092802002008280200200841046a280200220a2008410c6a28020022082008200a4b1b10dd05220b450d00200b4100480d030c010b2008200a490d020b4101210a200541016a220520014921072009210820012005470d000c030b0b2005200146210a20040d0120052001460d01024002400240024002402005417f6a220820014f0d002007410171450d01200020084103746a2208290200210c200820002005410374220d6a220b290200220e370200200b200c37020020054102490d0402400240200ea7220f20002005417e6a220a4103746a2210280200201041046a2802002207200841046a2802002209200920074b1b10dd052211450d0020114100480d010c060b200920074f0d050b20082010290200370200200a450d032002200d6a2108034002400240200f2008280200200841046a28020022072009200920074b1b10dd05220d450d00200d4100480d010c050b200920074f0d050b2000200a417f6a220a4103746a2110200841086a2008290200370200200841786a2108200a0d000c030b0b41f8fec500200820011038000b4188ffc500200520011038000b200841086a21100b201020093602042010200f3602000b200641016a21060240200120056b220d4102490d0002400240200b280208200b280200220f200b41046a2802002209200b410c6a2802002208200820094b1b10dd05220a450d00200a4100480d010c020b200820094f0d010b200b41086a2111200b200b2902083702000240200d4103490d004103210a41022107034002400240200b20074103746a2208280200200f2009200841046a2802002207200720094b1b10dd052210450d00201041004e0d030c010b200720094f0d020b200841786a20082902003702000240200a200d4f0d00200a2107200a41016a210a200821110c010b0b200821110b2011200f360200201120093602040b20064105470d000b4100210a0b200a0bb60202057f017e03402002410174220341017221040240024002400240200341026a220320014f0d00200420014f0d0102400240200020044103746a2205280200200020034103746a2206280200200641046a2802002206200541046a2802002205200520064b1b10dd052207450d00417f410120074100481b21060c010b417f200520064720052006491b21060b200320042006417f461b21040b0240200420014f0d00200220014f0d020240200020024103746a2202280200200020044103746a2203280200200341046a2802002206200241046a2802002205200520064b1b10dd052207450d00200741004e0d010c040b20052006490d030b0f0b41a080c600200420011038000b41b080c600200220011038000b200229020021082002200329020037020020032008370200200421020c000b0b8d0302037f017e230041c0006b22022400200141086a28020021032001280204210420022001280200220136020002400240024002402001418080044b0d002004450d022002200336020402400240200120034b0d002003418080044d0d042002413c6a41013602002002420237022c2002419c98c6003602282002410136020c200241f897c6003602082002200241086a360238200241186a200241286a1037200241186a21010c010b2002413c6a4102360200200241246a41013602002002420237022c2002418c98c6003602282002410136021c2002200241186a360238200220023602202002200241046a360218200241086a200241286a1037200241086a21010b20012902042105200128020021010c010b2002413c6a41013602002002420237022c200241fc97c6003602282002410136020c200241f897c6003602082002200241086a360238200241186a200241286a103720022802182101200229021c21050b2001450d0020002005370204200020013602000c010b200041003602000b200241c0006a24000be00501037f230041f0006b2204240002400240024020012802084102460d00412e102a2201450d01200041013a0000200141266a41002900909a46370000200141206a410029008a9a46370000200141186a41002900829a46370000200141106a41002900fa9946370000200141086a41002900f29946370000200141002900ea9946370000200041086a42ae808080e005370200200041046a20013602000c020b0240024002400240024002400240200128020022052d0000416e6a2201411e4b0d004100210620010e1f03000000000000000000000000000000000000000000000000000006040102030b4120102a2201450d06200041013a0000200141186a41002900b09a46370000200141106a41002900a89a46370000200141086a41002900a09a46370000200141002900989a46370000200041086a42a08080808004370200200041046a20013602000c070b410221060c040b410321060c030b20042005280204220136020c0240024020012003490d0041b89ac6002105200441e8006a2103200441d0006a2101200441c0006a21020c010b200220014101746a22012d0001450d0241c89ac6002105200441386a2103200441206a2101200441106a21020b20034101360204200141146a410136020020012003360210200142023702042001200536020020032004410c6a360200200220011037200041013a00002000410c6a200241086a280200360200200041046a20022902003702000c040b410121060c010b20012d000021060b0240200541106a2d00004106470d00200041003a0000200020063a00010c020b4129102a2201450d00200041013a0000200141286a41002d00809b463a0000200141206a41002900f89a46370000200141186a41002900f09a46370000200141106a41002900e89a46370000200141086a41002900e09a46370000200141002900d89a46370000200041086a42a98080809005370200200041046a20013602000c010b1033000b200441f0006a24000b8f0201017f230041106b220224000240024002400240024020002d00000e0401020300010b2002200128021841e4f7c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c030b2002200128021841e7f7c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b2002200128021841eaf7c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841edf7c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000bfac00103087f027e017f230041f0006b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022d00000eac0100c1010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01000b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102a2200450dbe012003421837025c20032000360258200341d8006a4100411810c80520032003280260220041186a3602602000200328025822016a411841ba9dc600411810c9052003200329025c37025c2003200136025841b892c600413b200341d8006a41f492c600103b000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490dc0012007410174220a2009200a20094b1b22094100480dc0010240024020070d002009102a21070c010b200128021820072009102e21070b2007450dbf01200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a220210da051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060cc0010b0240200141306a2802002204200141346a22052802004f0d002002310001210b200141206a350200210c024020042001412c6a280200470d00200441016a22022004490dbf01200441017422052002200520024b1b220241ffffffff01712002470dbf01200241037422054100480dbf010240024020040d002005102a21040c010b200128022820044103742005102e21040b2004450dbe01200120043602282001412c6a2002360200200141306a28020021040b200128022820044103746a200b422886200c84370200200141306a2201200128020041016a3602000cc0010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200536020020032003360268200341106a200341d8006a103720032802102202450dbf012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450dbf012000200b370204200020013602000cc0010b0240200141306a2802002204200141346a22052802004f0d002002310001210b200141206a350200210c024020042001412c6a280200470d00200441016a22022004490dbe01200441017422052002200520024b1b220241ffffffff01712002470dbe01200241037422054100480dbe010240024020040d002005102a21040c010b200128022820044103742005102e21040b2004450dbd01200120043602282001412c6a2002360200200141306a28020021040b200128022820044103746a200b422886200c8442808080803084370200200141306a2201200128020041016a3602000cbf010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200536020020032003360268200341106a200341d8006a103720032802102202450dbe012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450dbe012000200b370204200020013602000cbf010b2002310001210b200341d8006a200141186a200141286a2204410010ca05024020032d00584101470d002000200329025c370200200041086a200341e4006a2802003602000cbf010b0240200141306a2802002202200141346a22052802004f0d00200141206a350200210c024020022001412c6a280200470d00200241016a22052002490dbd01200241017422062005200620054b1b220541ffffffff01712005470dbd01200541037422064100480dbd010240024020020d002006102a21020c010b200428020020024103742006102e21020b2002450dbc01200120023602282001412c6a2005360200200141306a28020021020b200128022820024103746a200b422886200c8442808080801084370200200141306a2201200128020041016a3602000cbe010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200536020020032003360268200341106a200341d8006a103720032802102202450dbd012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450dbd012000200b370204200020013602000cbe010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102a2200450dba012003421837025c20032000360258200341d8006a4100411810c80520032003280260220041186a3602602000200328025822016a411841ba9dc600411810c9052003200329025c37025c20032001360258418493c6004134200341d8006a41f492c600103b000b02400240200141286a220228020020044103746a22042d00044101470d002004310005210b200341d8006a200141186a200210cb052003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cbf010b411a102a2201450dba01200141186a41002f00d093463b0000200141106a41002900c89346370000200141086a41002900c09346370000200141002900b893463700002000429a808080a003370204200020013602000cbe010b0240200141306a2802002204200141346a22052802004f0d00200141206a350200210c024020042001412c6a280200470d00200441016a22052004490dbc01200441017422062005200620054b1b220541ffffffff01712005470dbc01200541037422064100480dbc010240024020040d002006102a21020c010b200228020020044103742006102e21020b2002450dbb01200120023602282001412c6a2005360200200141306a28020021040b200128022820044103746a200b422886200c8442808080802084370200200141306a2201200128020041016a3602000cbd010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200536020020032003360268200341106a200341d8006a103720032802102202450dbc012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450dbc012000200b370204200020013602000cbd010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102a2200450db9012003421837025c20032000360258200341d8006a4100411810c80520032003280260220041186a3602602000200328025822016a411841ba9dc600411810c9052003200329025c37025c20032001360258418493c6004134200341d8006a41f492c600103b000b200141286a220628020020044103746a22042d00052105024020042d00044101470d00200541ff01714104470da6010b0240024020024101460d00200341d8006a200141186a2202200610cb052003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cbe010b20012d003822024104460dbb01200341d8006a200141186a22052006200210ca050240024020032d00584101460d000240200141206a2802002204200141246a22072802004f0d00024020042001411c6a280200470d00200441016a22072004490dbe01200441017422082007200820074b1b22074100480dbe010240024020040d002007102a21040c010b200528020020042007102e21040b2004450dbd01200120043602182001411c6a2007360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cbe010b200341ec006a220241013602002003420137025c200341b49ec6003602582003410136023c200320073602382003200341386a360268200341106a200341d8006a103720032802102204450dbd012003200329021437023c20032004360238200241013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b20020d010cbd010b200328025c2202450dbc01200341e0006a290300210b0b2000200b370204200020023602000cbd010b200541ff01714104460dbb010240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490dbb01200441017422072006200720064b1b22064100480dbb010240024020040d002006102a21020c010b200228020020042006102e21020b2002450dba01200120023602182001411c6a2006360200200141206a28020021040b200128021820046a20053a0000200141206a2201200128020041016a3602000cbc010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200636020020032003360268200341106a200341d8006a103720032802102202450dbb012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450dbb012000200b370204200020013602000cbc010b2003200241046a2802002202360248024002400240200141306a280200220420024d0d0020042002417f736a22022004490d0141969ec600411d1054000b200341ec006a220241023602002003411c6a41013602002003420237025c200341d49dc60036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1037200328023821042003200329023c37023c20032004360238200241013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b20020d010cb8010b200141286a220428020020024103746a22022d00044103460db70120022d0005220241ff01714104460db701200341d8006a200141186a22052004200210ca05024020032d00584101460d000240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490dbc01200441017422072006200720064b1b22064100480dbc010240024020040d002006102a21040c010b200528020020042006102e21040b2004450dbb01200120043602182001411c6a2006360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cb9010b200341ec006a220241013602002003420137025c200341b49ec6003602582003410136023c200320063602382003200341386a360268200341106a200341d8006a103720032802102204450db8012003200329021437023c20032004360238200241013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b2002450db8010c010b200328025c2202450db701200341e0006a290300210b0b2000200b370204200020023602000cbb010b200241046a2802002102200341d8006a200141186a2206200141286a2205410010ca05024020032d00584101470d00200341e0006a290300210b200328025c21010cb4010b200141306a28020021042003200236024802400240200420024d0d0020042002417f736a22022004490d0141969ec600411d1054000b200341ec006a220141023602002003411c6a41013602002003420237025c200341d49dc60036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1037200328023821022003200329023c37023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b200328023c450db4012003280238102c20010db5010cba010b200528020020024103746a22022d00044103460db90120022d0005220241ff01714104460db901200341d8006a20062005200210ca05024020032d00584101460d000240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490dba01200441017422072005200720054b1b22054100480dba010240024020040d002005102a21040c010b200628020020042005102e21040b2004450db901200120043602182001411c6a2005360200200141206a28020021040b200128021820046a20023a0000200141206a2201200128020041016a3602000cbb010b200341ec006a220141013602002003420137025c200341b49ec6003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103720032802102202450dba012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b20010db5010cba010b200328025c2201450db901200341e0006a290300210b0cb4010b200241046a280200220228020421062002280200210420032002280208220536024802400240200141306a280200220220054d0d0020022005417f736a22052002490d0141969ec600411d1054000b200341ec006a220441023602002003411c6a41013602002003420237025c200341d49dc60036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1037200328023821022003200329023c37023c20032002360238200441013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b2003200b370204200320023602000cb1010b410421090240200141286a220d280200220720054103746a22052d00044103460d0020052d000521090b200320093a00302006450dac01200941ff0171220a4104460dab01200641027421060340200320042802002205360248200220054d0dae0120022005417f736a220520024f0db201200720054103746a22052d00044103460daf0120052d000522084104460daf01200a2008470daf01200441046a21042006417c6a22060d000cad010b0b20012d003822024104460da901200341d8006a200141186a2205200141286a200210ca050240024020032d00584101460d000240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490db901200441017422072006200720064b1b22064100480db9010240024020040d002006102a21040c010b200528020020042006102e21040b2004450db801200120043602182001411c6a2006360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cac010b200341ec006a220241013602002003420137025c200341b49ec6003602582003410136023c200320063602382003200341386a360268200341106a200341d8006a103720032802102204450dab012003200329021437023c20032004360238200241013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b20020d010cab010b200328025c2202450daa01200341e0006a290300210b0b2000200b370204200020023602000cb8010b200128020021042003200241046a2802002202360254024002400240200441386a28020020024b0d00200341ec006a41013602002003420237025c200341889cc600360258200341013602342003200341306a3602682003200341d4006a360230200341386a200341d8006a1037200341186a200329023c370300200341013602102003200328023822043602140c010b2003200428023020024102746a2802002202360200024002402004412c6a28020020024b0d0041012105200341ec006a41013602002003420237025c200341ac9cc6003602582003410136024c2003200341c8006a36026820032003360248200341386a200341d8006a1037200341186a200329023c220b370300200b422088a7210720032802382104200ba721020c010b2003411c6a200428022420024104746a22042d000d22073a0000200341186a2004280208220236020020042802002104410021050b20032005360210200320043602142005450d010b200341186a21010ca7010b02402002450d002004417f6a2104200141286a2105200141186a21060340200341d8006a20062005200420026a2d000010ca05024020032d00584101470d00200341e0006a2101200328025c21040ca9010b2002417f6a22020d000b0b200741ff01714104460db6010240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db601200241017422052004200520044b1b22044100480db6010240024020020d002004102a21020c010b200128021820022004102e21020b2002450db501200120023602182001411c6a2004360200200141206a28020021020b200128021820026a20073a0000200141206a2201200128020041016a3602000cb7010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200436020020032003360268200341106a200341d8006a103720032802102202450db6012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021042003290214210b0240200328023c450d002003280238102c0b2004450db6010ca7010b200241046a280200210620012802002102200341003602380240024002400240200241146a2802000d00200341d8006a41146a41013602002003420237025c200341e89bc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10370c010b200341d8006a200141186a2204200141286a2205410010ca05024020032d00584101470d00200341e0006a290300210b200328025c21010c030b20012802002207412c6a280200210220032006360238200220064b0d01200341ec006a41013602002003420237025c200341ac9cc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10370b200328021021012003290214210b0c010b200728022420064104746a22062d000d2107024020062802082202450d002006280200417f6a21060340200341d8006a20042005200620026a2d000010ca05024020032d00584101470d00200341e0006a290300210b200328025c21010c030b2002417f6a22020d000b0b200741ff01714104460db6010240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490db601200241017422062005200620054b1b22054100480db6010240024020020d002005102a21020c010b200428020020022005102e21020b2002450db501200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20073a0000200141206a2201200128020041016a3602000cb7010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200536020020032003360268200341106a200341d8006a103720032802102202450db6012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b200328023c450d002003280238102c0b2001450db5012000200b370204200020013602000cb6010b200341d8006a200141186a200141286a410410ca0520032d00584101470db401200328025c2201450db4012000200341e0006a290300370204200020013602000cb5010b200341d8006a200141186a2204200141286a2205410010ca05200341d8006a21020240024020032d00584101460d00200341d8006a20042005410410ca05200341d8006a210220032d00584101460d00200341d8006a2004200520032d0059220610ca05200341d8006a210220032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490db501200241017422072005200720054b1b22054100480db5010240024020020d002005102a21020c010b200428020020022005102e21020b2002450db401200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20063a0000200141206a2201200128020041016a3602000cb6010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200536020020032003360268200341106a200341d8006a103720032802102202450db5012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b20010d010cb5010b200241046a2802002201450db401200241086a290200210b0b2000200b370204200020013602000cb4010b200341d8006a200141046a200241046a28020010cc050240024020032d00584101460d000240200141206a2802002202200141246a22042802004f0d0020032d00592104024020022001411c6a280200470d00200241016a22052002490db401200241017422062005200620054b1b22054100480db4010240024020020d002005102a21020c010b200128021820022005102e21020b2002450db301200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cb5010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200436020020032003360268200341106a200341d8006a103720032802102202450db4012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b20010d010cb4010b200328025c2201450db301200341e0006a290300210b0b2000200b370204200020013602000cb3010b2003200241046a2802002202360200200341d8006a200141046a200210cc05024020032d00584101470d002003200328025c22013602382003200341e0006a290300220b37023c0ca1010b200320032d005922023a0030200341d8006a200141186a200141286a410410ca05024020032d00584101470d00200341c0006a200341e4006a2802003602002003200329025c3703380ca0010b200320032d005922013a004820014104460db101200241ff01712001460db101200341106a41146a41323602002003411c6a412c360200200341d8006a41146a41033602002003420337025c200341f493c600360258200341013602142003200341106a3602682003200341c8006a3602202003200341306a36021820032003360210200341386a200341d8006a10370c9f010b200341d8006a200141046a200241046a28020010cc050240024020032d00584101460d00200341d8006a200141186a2205200141286a20032d0059220410ca05024020032d00584101460d000240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490db301200241017422072006200720064b1b22064100480db3010240024020020d002006102a21020c010b200528020020022006102e21020b2002450db201200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cb4010b200341ec006a220141013602002003420137025c200341b49ec6003602582003410136023c200320063602382003200341386a360268200341106a200341d8006a103720032802102202450db3012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b20010d020cb3010b200328025c2201450db201200341e0006a290300210b0c010b200328025c2201450db101200341e0006a290300210b0b2000200b370204200020013602000cb1010b200128020021042003200241046a280200220236023802400240200441206a28020020024d0d000240200141206a2802002205200141246a22062802004f0d00200428021820024101746a2d00002102024020052001411c6a280200470d00200541016a22042005490db101200541017422062004200620044b1b22044100480db1010240024020050d002004102a21050c010b200128021820052004102e21050b2005450db001200120053602182001411c6a2004360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000cb2010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200636020020032003360268200341106a200341d8006a103720032802102202450db1012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b20010d010cb1010b200341ec006a41013602002003420237025c200341cc9cc6003602582003410136024c2003200341c8006a3602682003200341386a360248200341106a200341d8006a103720032802102201450db0012003290214210b0b2000200b370204200020013602000cb0010b2003200241046a28020022023602282001280200210420032002360254024002400240200441206a28020020024b0d00200341ec006a41013602002003420237025c200341cc9cc6003602582003410136024c2003200341c8006a3602682003200341d4006a360248200341106a200341d8006a10370c010b200428021820024101746a22022d00010d01200341ec006a41013602002003420237025c200341dc9cc60036025820034101360204200320033602682003200341d4006a360200200341106a200341d8006a10370b2003280210210120032003290214220b37023c200320013602380c9c010b200320022d000022023a002f200341d8006a200141186a200141286a410410ca05024020032d00584101470d00200341c0006a200341e4006a2802003602002003200329025c3703380c9b010b200320032d005922013a00002001200241ff0171460dae0120014104460dae01200341106a41146a41323602002003411c6a4132360200200341d8006a41146a41033602002003420337025c2003418c94c600360258200341013602142003200341106a3602682003200336022020032003412f6a3602182003200341286a360210200341386a200341d8006a10370c9a010b200341d8006a2001200241046a2802004104410010ce052003280258450dad0120002003290358370200200041086a200341d8006a41086a2802003602000cae010b200341d8006a2001200241046a2802004108410110ce052003280258450dac0120002003290358370200200041086a200341d8006a41086a2802003602000cad010b200341d8006a2001200241046a2802004104410210ce052003280258450dab0120002003290358370200200041086a200341d8006a41086a2802003602000cac010b200341d8006a2001200241046a2802004108410310ce052003280258450daa0120002003290358370200200041086a200341d8006a41086a2802003602000cab010b200341d8006a2001200241046a2802004101410010ce052003280258450da90120002003290358370200200041086a200341d8006a41086a2802003602000caa010b200341d8006a2001200241046a2802004101410010ce052003280258450da80120002003290358370200200041086a200341d8006a41086a2802003602000ca9010b200341d8006a2001200241046a2802004102410010ce052003280258450da70120002003290358370200200041086a200341d8006a41086a2802003602000ca8010b200341d8006a2001200241046a2802004102410010ce052003280258450da60120002003290358370200200041086a200341d8006a41086a2802003602000ca7010b200341d8006a2001200241046a2802004101410110ce052003280258450da50120002003290358370200200041086a200341d8006a41086a2802003602000ca6010b200341d8006a2001200241046a2802004101410110ce052003280258450da40120002003290358370200200041086a200341d8006a41086a2802003602000ca5010b200341d8006a2001200241046a2802004102410110ce052003280258450da30120002003290358370200200041086a200341d8006a41086a2802003602000ca4010b200341d8006a2001200241046a2802004102410110ce052003280258450da20120002003290358370200200041086a200341d8006a41086a2802003602000ca3010b200341d8006a2001200241046a2802004104410110ce052003280258450da10120002003290358370200200041086a200341d8006a41086a2802003602000ca2010b200341d8006a2001200241046a2802004104410110ce052003280258450da00120002003290358370200200041086a200341d8006a41086a2802003602000ca1010b200341d8006a2001200241046a2802004104410010cf052003280258450d9f0120002003290358370200200041086a200341d8006a41086a2802003602000ca0010b200341d8006a2001200241046a2802004108410110cf052003280258450d9e0120002003290358370200200041086a200341d8006a41086a2802003602000c9f010b200341d8006a2001200241046a2802004104410210cf052003280258450d9d0120002003290358370200200041086a200341d8006a41086a2802003602000c9e010b200341d8006a2001200241046a2802004108410310cf052003280258450d9c0120002003290358370200200041086a200341d8006a41086a2802003602000c9d010b200341d8006a2001200241046a2802004101410010cf052003280258450d9b0120002003290358370200200041086a200341d8006a41086a2802003602000c9c010b200341d8006a2001200241046a2802004102410010cf052003280258450d9a0120002003290358370200200041086a200341d8006a41086a2802003602000c9b010b200341d8006a2001200241046a2802004101410110cf052003280258450d990120002003290358370200200041086a200341d8006a41086a2802003602000c9a010b200341d8006a2001200241046a2802004102410110cf052003280258450d980120002003290358370200200041086a200341d8006a41086a2802003602000c99010b200341d8006a2001200241046a2802004104410110cf052003280258450d970120002003290358370200200041086a200341d8006a41086a2802003602000c98010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c200341b89bc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103720032802102202450d002003290214210b0c010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9701200241017422052004200520044b1b22044100480d97010240024020020d002004102a21020c010b200128021820022004102e21020b2002450d9601200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c98010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200436020020032003360268200341106a200341d8006a103720032802102202450d97012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b2002450d97010b2000200b370204200020023602000c97010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c200341b89bc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103720032802102202450d002003290214210b0c010b200341d8006a200141186a2204200141286a410010ca05024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d9701200241017422062005200620054b1b22054100480d97010240024020020d002005102a21020c010b200428020020022005102e21020b2002450d9601200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c98010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200536020020032003360268200341106a200341d8006a103720032802102202450d97012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b20020d010c97010b200328025c2202450d9601200341e0006a290300210b0b2000200b370204200020023602000c96010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9401200241017422052004200520044b1b22044100480d94010240024020020d002004102a21020c010b200128021820022004102e21020b2002450d9301200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c95010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200436020020032003360268200341106a200341d8006a103720032802102202450d94012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450d94012000200b370204200020013602000c95010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9301200241017422052004200520044b1b22044100480d93010240024020020d002004102a21020c010b200128021820022004102e21020b2002450d9201200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000c94010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200436020020032003360268200341106a200341d8006a103720032802102202450d93012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450d93012000200b370204200020013602000c94010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9201200241017422052004200520044b1b22044100480d92010240024020020d002004102a21020c010b200128021820022004102e21020b2002450d9101200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000c93010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200436020020032003360268200341106a200341d8006a103720032802102202450d92012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450d92012000200b370204200020013602000c93010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490d9101200241017422052004200520044b1b22044100480d91010240024020020d002004102a21020c010b200128021820022004102e21020b2002450d9001200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000c92010b200341ec006a220141013602002003420137025c200341b49ec600360258200341013602042003200436020020032003360268200341106a200341d8006a103720032802102202450d91012003200329021437023c20032002360238200141013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021012003290214210b0240200328023c450d002003280238102c0b2001450d91012000200b370204200020013602000c92010b200341d8006a2001410010d0052003280258450d900120002003290358370200200041086a200341d8006a41086a2802003602000c91010b200341d8006a2001410010d1052003280258450d8f0120002003290358370200200041086a200341d8006a41086a2802003602000c90010b200341d8006a2001410010d1052003280258450d8e0120002003290358370200200041086a200341d8006a41086a2802003602000c8f010b200341d8006a2001410010d1052003280258450d8d0120002003290358370200200041086a200341d8006a41086a2802003602000c8e010b200341d8006a2001410010d1052003280258450d8c0120002003290358370200200041086a200341d8006a41086a2802003602000c8d010b200341d8006a2001410010d1052003280258450d8b0120002003290358370200200041086a200341d8006a41086a2802003602000c8c010b200341d8006a2001410010d1052003280258450d8a0120002003290358370200200041086a200341d8006a41086a2802003602000c8b010b200341d8006a2001410010d1052003280258450d890120002003290358370200200041086a200341d8006a41086a2802003602000c8a010b200341d8006a2001410010d1052003280258450d880120002003290358370200200041086a200341d8006a41086a2802003602000c89010b200341d8006a2001410010d1052003280258450d870120002003290358370200200041086a200341d8006a41086a2802003602000c88010b200341d8006a2001410010d1052003280258450d860120002003290358370200200041086a200341d8006a41086a2802003602000c87010b200341d8006a2001410110d0052003280258450d850120002003290358370200200041086a200341d8006a41086a2802003602000c86010b200341d8006a2001410110d1052003280258450d840120002003290358370200200041086a200341d8006a41086a2802003602000c85010b200341d8006a2001410110d1052003280258450d830120002003290358370200200041086a200341d8006a41086a2802003602000c84010b200341d8006a2001410110d1052003280258450d820120002003290358370200200041086a200341d8006a41086a2802003602000c83010b200341d8006a2001410110d1052003280258450d810120002003290358370200200041086a200341d8006a41086a2802003602000c82010b200341d8006a2001410110d1052003280258450d800120002003290358370200200041086a200341d8006a41086a2802003602000c81010b200341d8006a2001410110d1052003280258450d7f20002003290358370200200041086a200341d8006a41086a2802003602000c80010b200341d8006a2001410110d1052003280258450d7e20002003290358370200200041086a200341d8006a41086a2802003602000c7f0b200341d8006a2001410110d1052003280258450d7d20002003290358370200200041086a200341d8006a41086a2802003602000c7e0b200341d8006a2001410110d1052003280258450d7c20002003290358370200200041086a200341d8006a41086a2802003602000c7d0b200341d8006a2001410110d1052003280258450d7b20002003290358370200200041086a200341d8006a41086a2802003602000c7c0b200341d8006a2001410210d1052003280258450d7a20002003290358370200200041086a200341d8006a41086a2802003602000c7b0b200341d8006a2001410210d1052003280258450d7920002003290358370200200041086a200341d8006a41086a2802003602000c7a0b200341d8006a2001410210d1052003280258450d7820002003290358370200200041086a200341d8006a41086a2802003602000c790b200341d8006a2001410210d1052003280258450d7720002003290358370200200041086a200341d8006a41086a2802003602000c780b200341d8006a2001410210d1052003280258450d7620002003290358370200200041086a200341d8006a41086a2802003602000c770b200341d8006a2001410210d1052003280258450d7520002003290358370200200041086a200341d8006a41086a2802003602000c760b200341d8006a2001410310d1052003280258450d7420002003290358370200200041086a200341d8006a41086a2802003602000c750b200341d8006a2001410310d1052003280258450d7320002003290358370200200041086a200341d8006a41086a2802003602000c740b200341d8006a2001410310d1052003280258450d7220002003290358370200200041086a200341d8006a41086a2802003602000c730b200341d8006a2001410310d1052003280258450d7120002003290358370200200041086a200341d8006a41086a2802003602000c720b200341d8006a2001410310d1052003280258450d7020002003290358370200200041086a200341d8006a41086a2802003602000c710b200341d8006a2001410310d1052003280258450d6f20002003290358370200200041086a200341d8006a41086a2802003602000c700b200341d8006a2001410010d2052003280258450d6e20002003290358370200200041086a200341d8006a41086a2802003602000c6f0b200341d8006a2001410010d2052003280258450d6d20002003290358370200200041086a200341d8006a41086a2802003602000c6e0b200341d8006a2001410010d2052003280258450d6c20002003290358370200200041086a200341d8006a41086a2802003602000c6d0b200341d8006a2001410010d3052003280258450d6b20002003290358370200200041086a200341d8006a41086a2802003602000c6c0b200341d8006a2001410010d3052003280258450d6a20002003290358370200200041086a200341d8006a41086a2802003602000c6b0b200341d8006a2001410010d3052003280258450d6920002003290358370200200041086a200341d8006a41086a2802003602000c6a0b200341d8006a2001410010d3052003280258450d6820002003290358370200200041086a200341d8006a41086a2802003602000c690b200341d8006a2001410010d3052003280258450d6720002003290358370200200041086a200341d8006a41086a2802003602000c680b200341d8006a2001410010d3052003280258450d6620002003290358370200200041086a200341d8006a41086a2802003602000c670b200341d8006a2001410010d3052003280258450d6520002003290358370200200041086a200341d8006a41086a2802003602000c660b200341d8006a2001410010d3052003280258450d6420002003290358370200200041086a200341d8006a41086a2802003602000c650b200341d8006a2001410010d3052003280258450d6320002003290358370200200041086a200341d8006a41086a2802003602000c640b200341d8006a2001410010d3052003280258450d6220002003290358370200200041086a200341d8006a41086a2802003602000c630b200341d8006a2001410010d3052003280258450d6120002003290358370200200041086a200341d8006a41086a2802003602000c620b200341d8006a2001410010d3052003280258450d6020002003290358370200200041086a200341d8006a41086a2802003602000c610b200341d8006a2001410010d3052003280258450d5f20002003290358370200200041086a200341d8006a41086a2802003602000c600b200341d8006a2001410010d3052003280258450d5e20002003290358370200200041086a200341d8006a41086a2802003602000c5f0b200341d8006a2001410010d3052003280258450d5d20002003290358370200200041086a200341d8006a41086a2802003602000c5e0b200341d8006a2001410110d2052003280258450d5c20002003290358370200200041086a200341d8006a41086a2802003602000c5d0b200341d8006a2001410110d2052003280258450d5b20002003290358370200200041086a200341d8006a41086a2802003602000c5c0b200341d8006a2001410110d2052003280258450d5a20002003290358370200200041086a200341d8006a41086a2802003602000c5b0b200341d8006a2001410110d3052003280258450d5920002003290358370200200041086a200341d8006a41086a2802003602000c5a0b200341d8006a2001410110d3052003280258450d5820002003290358370200200041086a200341d8006a41086a2802003602000c590b200341d8006a2001410110d3052003280258450d5720002003290358370200200041086a200341d8006a41086a2802003602000c580b200341d8006a2001410110d3052003280258450d5620002003290358370200200041086a200341d8006a41086a2802003602000c570b200341d8006a2001410110d3052003280258450d5520002003290358370200200041086a200341d8006a41086a2802003602000c560b200341d8006a2001410110d3052003280258450d5420002003290358370200200041086a200341d8006a41086a2802003602000c550b200341d8006a2001410110d3052003280258450d5320002003290358370200200041086a200341d8006a41086a2802003602000c540b200341d8006a2001410110d3052003280258450d5220002003290358370200200041086a200341d8006a41086a2802003602000c530b200341d8006a2001410110d3052003280258450d5120002003290358370200200041086a200341d8006a41086a2802003602000c520b200341d8006a2001410110d3052003280258450d5020002003290358370200200041086a200341d8006a41086a2802003602000c510b200341d8006a2001410110d3052003280258450d4f20002003290358370200200041086a200341d8006a41086a2802003602000c500b200341d8006a2001410110d3052003280258450d4e20002003290358370200200041086a200341d8006a41086a2802003602000c4f0b200341d8006a2001410110d3052003280258450d4d20002003290358370200200041086a200341d8006a41086a2802003602000c4e0b200341d8006a2001410110d3052003280258450d4c20002003290358370200200041086a200341d8006a41086a2802003602000c4d0b200341d8006a2001410110d3052003280258450d4b20002003290358370200200041086a200341d8006a41086a2802003602000c4c0b200341d8006a2001410210d2052003280258450d4a20002003290358370200200041086a200341d8006a41086a2802003602000c4b0b200341d8006a2001410210d2052003280258450d4920002003290358370200200041086a200341d8006a41086a2802003602000c4a0b200341d8006a2001410210d2052003280258450d4820002003290358370200200041086a200341d8006a41086a2802003602000c490b200341d8006a2001410210d2052003280258450d4720002003290358370200200041086a200341d8006a41086a2802003602000c480b200341d8006a2001410210d2052003280258450d4620002003290358370200200041086a200341d8006a41086a2802003602000c470b200341d8006a2001410210d2052003280258450d4520002003290358370200200041086a200341d8006a41086a2802003602000c460b200341d8006a2001410210d2052003280258450d4420002003290358370200200041086a200341d8006a41086a2802003602000c450b200341d8006a2001410210d3052003280258450d4320002003290358370200200041086a200341d8006a41086a2802003602000c440b200341d8006a2001410210d3052003280258450d4220002003290358370200200041086a200341d8006a41086a2802003602000c430b200341d8006a2001410210d3052003280258450d4120002003290358370200200041086a200341d8006a41086a2802003602000c420b200341d8006a2001410210d3052003280258450d4020002003290358370200200041086a200341d8006a41086a2802003602000c410b200341d8006a2001410210d3052003280258450d3f20002003290358370200200041086a200341d8006a41086a2802003602000c400b200341d8006a2001410210d3052003280258450d3e20002003290358370200200041086a200341d8006a41086a2802003602000c3f0b200341d8006a2001410210d3052003280258450d3d20002003290358370200200041086a200341d8006a41086a2802003602000c3e0b200341d8006a2001410310d2052003280258450d3c20002003290358370200200041086a200341d8006a41086a2802003602000c3d0b200341d8006a2001410310d2052003280258450d3b20002003290358370200200041086a200341d8006a41086a2802003602000c3c0b200341d8006a2001410310d2052003280258450d3a20002003290358370200200041086a200341d8006a41086a2802003602000c3b0b200341d8006a2001410310d2052003280258450d3920002003290358370200200041086a200341d8006a41086a2802003602000c3a0b200341d8006a2001410310d2052003280258450d3820002003290358370200200041086a200341d8006a41086a2802003602000c390b200341d8006a2001410310d2052003280258450d3720002003290358370200200041086a200341d8006a41086a2802003602000c380b200341d8006a2001410310d2052003280258450d3620002003290358370200200041086a200341d8006a41086a2802003602000c370b200341d8006a2001410310d3052003280258450d3520002003290358370200200041086a200341d8006a41086a2802003602000c360b200341d8006a2001410310d3052003280258450d3420002003290358370200200041086a200341d8006a41086a2802003602000c350b200341d8006a2001410310d3052003280258450d3320002003290358370200200041086a200341d8006a41086a2802003602000c340b200341d8006a2001410310d3052003280258450d3220002003290358370200200041086a200341d8006a41086a2802003602000c330b200341d8006a2001410310d3052003280258450d3120002003290358370200200041086a200341d8006a41086a2802003602000c320b200341d8006a2001410310d3052003280258450d3020002003290358370200200041086a200341d8006a41086a2802003602000c310b200341d8006a2001410310d3052003280258450d2f20002003290358370200200041086a200341d8006a41086a2802003602000c300b200341d8006a20014101410010d4052003280258450d2e20002003290358370200200041086a200341d8006a41086a2802003602000c2f0b200341d8006a20014102410010d4052003280258450d2d20002003290358370200200041086a200341d8006a41086a2802003602000c2e0b200341d8006a20014102410010d4052003280258450d2c20002003290358370200200041086a200341d8006a41086a2802003602000c2d0b200341d8006a20014103410010d4052003280258450d2b20002003290358370200200041086a200341d8006a41086a2802003602000c2c0b200341d8006a20014103410010d4052003280258450d2a20002003290358370200200041086a200341d8006a41086a2802003602000c2b0b200341d8006a20014100410110d4052003280258450d2920002003290358370200200041086a200341d8006a41086a2802003602000c2a0b200341d8006a20014100410110d4052003280258450d2820002003290358370200200041086a200341d8006a41086a2802003602000c290b200341d8006a20014102410110d4052003280258450d2720002003290358370200200041086a200341d8006a41086a2802003602000c280b200341d8006a20014102410110d4052003280258450d2620002003290358370200200041086a200341d8006a41086a2802003602000c270b200341d8006a20014103410110d4052003280258450d2520002003290358370200200041086a200341d8006a41086a2802003602000c260b200341d8006a20014103410110d4052003280258450d2420002003290358370200200041086a200341d8006a41086a2802003602000c250b200341d8006a20014100410210d4052003280258450d2320002003290358370200200041086a200341d8006a41086a2802003602000c240b200341d8006a20014100410210d4052003280258450d2220002003290358370200200041086a200341d8006a41086a2802003602000c230b200341d8006a20014101410210d4052003280258450d2120002003290358370200200041086a200341d8006a41086a2802003602000c220b200341d8006a20014101410210d4052003280258450d2020002003290358370200200041086a200341d8006a41086a2802003602000c210b200341d8006a20014103410210d4052003280258450d1f20002003290358370200200041086a200341d8006a41086a2802003602000c200b200341d8006a20014100410310d4052003280258450d1e20002003290358370200200041086a200341d8006a41086a2802003602000c1f0b200341d8006a20014100410310d4052003280258450d1d20002003290358370200200041086a200341d8006a41086a2802003602000c1e0b200341d8006a20014101410310d4052003280258450d1c20002003290358370200200041086a200341d8006a41086a2802003602000c1d0b200341d8006a20014101410310d4052003280258450d1b20002003290358370200200041086a200341d8006a41086a2802003602000c1c0b200341d8006a20014102410310d4052003280258450d1a20002003290358370200200041086a200341d8006a41086a2802003602000c1b0b200341d8006a20014102410010d4052003280258450d1920002003290358370200200041086a200341d8006a41086a2802003602000c1a0b200341d8006a20014103410110d4052003280258450d1820002003290358370200200041086a200341d8006a41086a2802003602000c190b200341d8006a20014100410210d4052003280258450d1720002003290358370200200041086a200341d8006a41086a2802003602000c180b200341d8006a20014101410310d40520032802580d010c160b200341ec006a41013602002003420237025c200341d493c6003602582003413336023c2003200441056a3602382003200341386a360268200341106a200341d8006a1037200041086a200341106a41086a280200360200200020032903103702000c160b20002003290358370200200041086a200341d8006a41086a2802003602000c150b200329023c210b200328023821010b2001450d122000200b370204200020013602000c130b200329023c210b200328023821010b2001450d102000200b370204200020013602000c110b2004450d0f2001290200210b0b2000200b370204200020043602000c0f0b024002400240200141306a2802002202417f6a220420024f0d00200420024b0d00200128022820044103746a22052802002204200141206a220628020022024b0d01200421010c020b4118102a2200450d0c2003421837025c20032000360258200341d8006a4100411810c80520032003280260220041186a3602602000200328025822016a411841ba9dc600411810c9052003200329025c37025c2003200136025841b892c600413b200341d8006a41f492c600103b000b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d0d2007410174220a2009200a20094b1b22094100480d0d0240024020070d002009102a21070c010b200128021820072009102e21070b2007450d0c200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a220210da051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c0d0b200641027421060340200320042802002205360248200220054d0d0220022005417f736a220520024f0d060240200720054103746a22052d00044103460d0020052d00054104470d040b200441046a21042006417c6a22060d000b410421090b200341d8006a200141186a2202200d410010ca0520032d00584101470d02200341086a200341e4006a2802003602002003200329025c3703000c030b200341ec006a220441023602002003411c6a41013602002003420237025c200341d49dc60036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1037200328023821022003200329023c37023c20032002360238200441013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b2003200b370204200320023602000c020b2003411c6a4133360200200341ec006a41023602002003420237025c200341e493c6003602582003200541056a360218200341333602142003200341106a3602682003200341306a3602102003200341d8006a10370c010b0240200941ff01714104460d00200341d8006a2002200d200910ca050240024020032d00584101460d000240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490d0b200441017422062005200620054b1b22054100480d0b0240024020040d002005102a21020c010b200228020020042005102e21020b2002450d0a200120023602182001411c6a2005360200200141206a28020021040b200128021820046a20093a0000200141206a2202200228020041016a3602000c030b200341ec006a220241013602002003420137025c200341b49ec6003602582003410136023c200320053602382003200341386a360268200341106a200341d8006a103720032802102204450d022003200329021437023c20032004360238200241013602002003420137025c200341e897c6003602582003412d360204200320033602682003200341386a360200200341106a200341d8006a1037200328021021022003290214210b0240200328023c450d002003280238102c0b20020d010c020b200328025c2202450d01200341e0006a290300210b0b2003200b370204200320023602000c010b200341003602000b024020032802002202450d0020002003290204370204200020023602000c090b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b4118102a2200450d052003421837025c20032000360258200341d8006a4100411810c80520032003280260220041186a3602602000200328025822016a411841ba9dc600411810c9052003200329025c37025c2003200136025841b892c600413b200341d8006a41f492c600103b000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d072007410174220a2009200a20094b1b22094100480d070240024020070d002009102a21070c010b200128021820072009102e21070b2007450d06200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a220210da051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c070b41969ec600411d1054000b2001450d050b2000200b370204200020013602000c050b024002400240200141306a2802002202417f6a220420024f0d00200420024b0d00200128022820044103746a22052802002204200141206a220628020022024b0d01200421010c020b4118102a2200450d022003421837025c20032000360258200341d8006a4100411810c80520032003280260220041186a3602602000200328025822016a411841ba9dc600411810c9052003200329025c37025c2003200136025841b892c600413b200341d8006a41f492c600103b000b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d032007410174220a2009200a20094b1b22094100480d030240024020070d002009102a21070c010b200128021820072009102e21070b2007450d02200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a220210da051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c030b1033000b1035000b200341d8006a200141186a200610cb052003280258450d0020002003290358370200200041086a200341d8006a41086a2802003602000c010b200041003602000b200341f0006a24000b6401017f230041206b2202240020024134360204200220003602002001411c6a2802002100200128021821012002411c6a41013602002002420137020c200241d49ec6003602082002200236021820012000200241086a10392101200241206a240020010b19002000200141186a280200360204200020012802103602000bc50201037f230041206b2202240002400240200028020022002d00004104470d002002200128021841c4f7c50041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841ccf7c50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a41d4f7c5001061210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d004101210020042802184198b0c00041012004411c6a28020028020c1100000d010b2001280200220028021841ec94c60041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470bc00201037f230041206b220224000240024020002d00004104470d002002200128021841c4f7c50041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841ccf7c50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a41d4f7c5001061210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d004101210020042802184198b0c00041012004411c6a28020028020c1100000d010b2001280200220028021841ec94c60041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470bcd0202027f027e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d0120042004423f8722057c2005852004427f552001104221000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000b20024180016a240020000f0b20034180011047000b20034180011047000bcd0203027f017e017f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210020034120710d012000ac22042004423f8722047c2004852000417f73411f762001104221000c020b20002802002103410021000340200220006a41ff006a2003410f712205413072200541d7006a2005410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d022001410141b087c0004102200220006a4180016a410020006b104521000c010b410021030340200220036a41ff006a2000410f712205413072200541376a2005410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141b087c0004102200220036a4180016a410020036b104521000b20024180016a240020000f0b20034180011047000b20004180011047000b8a0201027f230041106b2202240020002802002802002100200128021841ecebc500410b2001411c6a28020028020c1100002103200241003a0005200220033a0004200220013602002002200036020c200241f7ebc50041052002410c6a41fcebc500106021012002200041086a36020c2001418cecc50041072002410c6a41dcebc50010601a20022d00042101024020022d0005450d00200141ff0171210041012101024020000d0020022802002201411c6a28020028020c210020012802182103024020012d00004104710d0020034192b0c0004102200011000021010c010b20034194b0c0004101200011000021010b200220013a00040b200241106a2400200141ff01714100470bcc0101047f230041106b220224002000280200220041046a28020021032000280200210041012104200128021841d1afc00041012001411c6a28020028020c1100002105200241003a0005200220053a00042002200136020002402003450d002003410274210103402002200036020c20022002410c6a41b4f7c50010621a200041046a21002001417c6a22010d000b20022d000421050b0240200541ff01710d002002280200220028021841d2afc00041012000411c6a28020028020c11000021040b200241106a240020040bc60501087f230041106b220324002002280208220441546a2105200241106a280200220641306c210702400340410021082007450d01200741506a21072005412c6a2109200541306a220a210520092d00004103470d000b200a41086a2802002207450d00200741286c2105200a28020041186a2107410021080340200820072d0000456a2108200741286a2107200541586a22050d000b0b0240024002400240024002400240200120086b220a20014b0d00200641306c2107200441546a210503402007450d02200741506a21072005412c6a2108200541306a2209210520082d0000410c470d000b200941086a280200200a4b0d02411e102a2207450d062000200736020420004101360200200741166a41002900bafa45370000200741106a41002900b4fa45370000200741086a41002900acfa45370000200741002900a4fa45370000200041086a429e808080e0033702000c050b412c102a22070d020c050b412c102a2207450d042000200736020420004101360200200741286a41002800a0fa45360000200741206a4100290098fa45370000200741186a4100290090fa45370000200741106a4100290088fa45370000200741086a4100290080fa45370000200741002900f8f945370000200041086a42ac808080c0053702000c030b2009280200200a41186c6a28020821072003200a200210b30520032802004101460d0120032802042105200041003602002000200520076a3602040c020b2000200736020420004101360200200741286a41002800f4f945360000200741206a41002900ecf945370000200741186a41002900e4f945370000200741106a41002900dcf945370000200741086a41002900d4f945370000200741002900ccf945370000200041086a42ac808080c0053702000c010b20002003290204370204200041013602002000410c6a2003410c6a2802003602000b200341106a24000f0b1033000bdf0902067f017e024020010d00200041ac013a00000f0b02400240024002400240024020012d00002202414f6a41fb004f0d000c010b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e312c2c0001022c2c0304052c06072c2c08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292c0b20012d00012103410221020c2b0b20012d00012103410321020c2a0b20012d00012103410421020c290b200141046a2802002104410721020c270b200141046a2802002104410821020c260b200141046a2802002105410c102a2204450d272005280204220641ffffffff03712006470d2820064102742201417f4c0d280240024020010d00410421070c010b2001102a2207450d280b02402006450d00200528020021012006410274210320072102034020022001280200360200200241046a2102200141046a21012003417c6a22030d000b0b200420063602042004200736020020042005280208360208410921020c250b200141046a2802002104410b21020c240b200141046a280200210420012d00012103410c21020c240b200141046a2802002104410f21020c220b200141046a2802002104411021020c210b200141046a2802002104411121020c200b200141046a2802002104411221020c1f0b200141046a2802002104411321020c1e0b200141046a280200210420013502082108411421020c1d0b200141046a280200210420013502082108411521020c1c0b200141046a280200210420013502082108411621020c1b0b200141046a280200210420013502082108411721020c1a0b200141046a280200210420013502082108411821020c190b200141046a280200210420013502082108411921020c180b200141046a280200210420013502082108411a21020c170b200141046a280200210420013502082108411b21020c160b200141046a280200210420013502082108411c21020c150b200141046a280200210420013502082108411d21020c140b200141046a280200210420013502082108411e21020c130b200141046a280200210420013502082108411f21020c120b200141046a280200210420013502082108412021020c110b200141046a280200210420013502082108412121020c100b200141046a280200210420013502082108412221020c0f0b200141046a280200210420013502082108412321020c0e0b200141046a280200210420013502082108412421020c0d0b200141046a280200210420013502082108412521020c0c0b200141046a280200210420013502082108412621020c0b0b200141046a280200210420013502082108412721020c0a0b200141046a280200210420013502082108412821020c090b200141046a280200210420013502082108412921020c080b200141046a280200210420013502082108412a21020c070b20012d00012103412b21020c070b20012d00012103412c21020c060b200141046a2802002104412d21020c040b20012903082108412e21020c020b200141046a2802002104412f21020c020b20012903082108413021020b0b0b200020033a0001200020023a0000200041086a2008370300200041046a20043602000f0b1033000b103a000b890301067f230041106b220224000240024002400240200041046a2802002203200041086a28020022046b20012802042205200128020022066b4104762207490d00200028020021030c010b200420076a22062004490d02200341017422052006200520064b1b220641ffffffff00712006470d02200641047422054100480d020240024020030d002005102a21030c010b200028020020034104742005102e21030b2003450d0120002003360200200041046a2006360200200041086a280200210420012802042105200128020021060b0240024020062005470d00410021060c010b2001200641106a3602000b2002200610ac05024020022d000041ac01460d00200320044104746a2106034020062002290300370300200641086a200241086a29030037030002400240200128020022052001280204470d00410021050c010b2001200541106a3602000b200441016a2104200641106a21062002200510ac0520022d000041ac01470d000b0b200041086a2004360200200241106a24000f0b1033000b1035000b100020002802003502004101200110420ba607010b7f230041e0006b22032400200320013602202002280208220441546a2105200241106a280200220641306c210202400340024020020d00410021070c020b200241506a21022005412c6a2107200541306a2208210520072d00004102470d000b200341186a200810f40420032802182107200328021c21020b2002410020071b2109200641306c2102200441546a21052007410420071b210a02400340024020020d004100210b0c020b200241506a21022005412c6a2107200541306a2208210520072d00004104470d000b200341106a200810f4042003280210210b2003280214210c0b200641306c2102200441546a2105200b4104200b1b210d02400240024002400240024002400240024003402002450d01200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200841086a2802002202450d00200241286c2107200828020041186a2102410021050340200520022d0000456a2105200241286a2102200741586a22070d000b200520014d0d01200641306c2102200441546a210503402002450d07200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200341086a200810f404200328020c220b41286c210520032802082204210703402005450d08200541586a2105200741186a2108200741286a2202210720082d00000d000b20010d02200241586a21020c030b410021050b0240200c4100200b1b200120056b22024d0d00200d20024102746a22020d030b200341cc006a41013602002003420237023c200341e4fbc5003602382003410136022c2003200341286a3602482003200341206a360228200341d0006a200341386a1037200341d0006a21020c030b2004200b41286c6a210803402001417f6a2101034020082002460d06200241186a2105200241286a2207210220052d00000d000b2007210220010d000b200741586a21020b2002411c6a21020b2003200228020022023602240240200920024d0d00200a20024104746a2202450d0020002002360204410021020c040b200341cc006a4102360200200341dc006a41013602002003420337023c200341f4fbc500360238200341013602542003200341d0006a3602482003200341206a3602582003200341246a360250200341286a200341386a1037200341286a21020b20022802002105200041086a200229020437020020002005360204410121020c020b41c2fac50041c2001054000b4184fbc50041dd001054000b20002002360200200341e0006a24000bea0302057f017e02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d00200020014105746a220441c4006a2802002105200441386a2802002106200441346a2802002107200141016a21010c010b02400240200028020022010d002003ad210841002104410021010c010b20003301044220862003ad842108410121040b2000102c2008a72103024002402008422088a7220620012f01064f0d00200121050c010b034002400240200128020022050d002003ad2108410021050c010b200441016a210420013301044220862003ad8421080b2001102c2008a72103200521012008422088a7220620052f01064f0d000b0b200641027420056a4198036a2802002100200520064105746a220141c4006a2802002105200141386a2802002106200141346a280200210702402004417f6a2201450d00034020002802940321002001417f6a22010d000b0b410021010b20054102460d012002417f6a210202402006450d002007102c0b20020d000b0b0240200041d0e1c100460d00200028020021012000102c2001450d00200128020021052001102c2005450d00024020052802002201450d0003402005102c2001210520012802002200210120000d000b0b2005102c0b0bf80d01067f0240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a280200102c0f0b0240200041086a280200450d00200041046a280200102c0b200041146a280200450d0c200041106a280200102c0f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d002001280200102c0b200141106a2101200241706a22020d000b0b200041086a280200450d0b2000280204102c0f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d002001280200102c0b0240200141106a280200450d002001410c6a280200102c0b200141286a2101200241586a22020d000b0b200041086a280200450d0a2000280204102c0f0b200041086a280200450d09200041046a280200102c0f0b200041086a280200450d08200041046a280200102c0f0b200041086a280200450d07200041046a280200102c0f0b02402000410c6a2802002201450d00200041046a280200220320014104746a21040340024020032802082202450d0020032802002101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102c200528020021060b2006102c0b200141106a2101200241706a22020d000b0b200341106a21010240200341046a280200450d002003280200102c0b2001210320012004470d000b0b200041086a280200450d062000280204102c0f0b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d002001280200102c0b200141146a21012002416c6a22020d000b0b200041086a280200450d052000280204102c0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102c200528020021060b2006102c0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102c0b2003411c6a21010240200341146a280200450d002003280210102c0b2001210320012004470d000b0b200041086a280200450d042000280204102c0f0b02402000410c6a2802002201450d00200041046a2802002203200141186c6a210403400240200341046a280200450d002003280200102c0b0240200341146a2802002202450d00200328020c2101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102c200528020021060b2006102c0b200141106a2101200241706a22020d000b0b200341186a21010240200341106a280200450d00200328020c102c0b2001210320012004470d000b0b200041086a280200450d032000280204102c0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102c200528020021060b2006102c0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102c0b2003411c6a21010240200341146a280200450d002003280210102c0b2001210320012004470d000b0b200041086a280200450d022000280204102c0f0b0240200041046a2802002201450d00200041086a280200450d002001102c0b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102c0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102c0b200041246a2802002203450d0102402000412c6a2802002201450d00200320014104746a210403402003220541106a2103024020052802042201450d0002402005410c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102c0b2001410c6a2101200241746a22020d000b0b200541086a280200450d002005280204102c0b20032004470d000b0b200041286a280200450d012000280224102c0c010b0240200041086a280200450d00200041046a280200102c0b0240200041146a2802002201450d00200041186a280200450d002001102c0b200041246a280200450d00200041206a280200102c0f0b0bd20a01067f02400240024020012d00002202414f6a41fb00490d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e312a2a0001022a2a0304052a06072a2a08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a0b200020012d00013a0001200041023a00000f0b200020012d00013a0001200041033a00000f0b200020012d00013a0001200041043a00000f0b200041046a200141046a280200360200200041073a00000f0b200041046a200141046a280200360200200041083a00000f0b200141046a2802002103410c102a2204450d252003280204220541ffffffff03712005470d2620054102742201417f4c0d260240024020010d00410421060c010b2001102a2206450d260b02402005450d00200328020021012005410274210720062102034020022001280200360200200241046a2102200141046a21012007417c6a22070d000b0b200420053602042004200636020020042003280208360208200041046a2004360200200041093a00000f0b200041046a200141046a2802003602002000410b3a00000f0b200020012d00013a0001200041046a200141046a2802003602002000410c3a00000f0b200041046a200141046a2802003602002000410f3a00000f0b200041046a200141046a280200360200200041103a00000f0b200041046a200141046a280200360200200041113a00000f0b200041046a200141046a280200360200200041123a00000f0b200041046a200141046a280200360200200041133a00000f0b200041046a200141046a290200370200200041143a00000f0b200041046a200141046a290200370200200041153a00000f0b200041046a200141046a290200370200200041163a00000f0b200041046a200141046a290200370200200041173a00000f0b200041046a200141046a290200370200200041183a00000f0b200041046a200141046a290200370200200041193a00000f0b200041046a200141046a2902003702002000411a3a00000f0b200041046a200141046a2902003702002000411b3a00000f0b200041046a200141046a2902003702002000411c3a00000f0b200041046a200141046a2902003702002000411d3a00000f0b200041046a200141046a2902003702002000411e3a00000f0b200041046a200141046a2902003702002000411f3a00000f0b200041046a200141046a290200370200200041203a00000f0b200041046a200141046a290200370200200041213a00000f0b200041046a200141046a290200370200200041223a00000f0b200041046a200141046a290200370200200041233a00000f0b200041046a200141046a290200370200200041243a00000f0b200041046a200141046a290200370200200041253a00000f0b200041046a200141046a290200370200200041263a00000f0b200041046a200141046a290200370200200041273a00000f0b200041046a200141046a290200370200200041283a00000f0b200041046a200141046a290200370200200041293a00000f0b200041046a200141046a2902003702002000412a3a00000f0b200020012d00013a00012000412b3a00000f0b200020012d00013a00012000412c3a00000f0b200041046a200141046a2802003602002000412d3a00000f0b200041086a200141086a2903003703002000412e3a00000f0b200041046a200141046a2802003602002000412f3a00000f0b200041086a200141086a290300370300413021020b200020023a00000f0b1033000b103a000bda60010c7f230041a0016b22032400200320013602242002280208220441546a2105200241106a280200220641306c210102400240024002400240024002400240024003402001450d01200141506a21012005412c6a2107200541306a2208210520072d00004104470d000b200641306c2101200441546a210503402001450d02200141506a21012005412c6a2107200541306a2209210520072d0000410c470d000b200641306c2101200441546a210503402001450d03200141506a21012005412c6a2107200541306a2204210520072d00004102470d000b024041002802d8a1464105490d00200341013602442003200341246a36024041002802e4a146210141002802e0a146210541002802dca146210720034198016a41980136020020034190016a42ee808080103703002003418c016a41b483c60036020020034184016a422537020020034180016a41ac84c600360200200341f8006a4201370300200341e8006a4201370300200341e0006a410a360200200341f4006a200341c0006a360200200341cc81c600360264200341a284c60036025c20034105360258200541ecb3c000200741024622071b200341d8006a200141d4b3c00020071b2802101102000b200341186a200810f404200328021c200328022422014d0d03200328021820014102746a2201450d03200341106a200410f40402402003280214200128020022014d0d00200328021020014104746a22010d050b4125102a2201450d052001411d6a41002900f18146370000200141186a41002900ec8146370000200141106a41002900e48146370000200141086a41002900dc8146370000200141002900d48146370000200041086a42a5808080d00437020020002001360204200041013602000c080b4113102a2201450d042001410f6a41002800a78146360000200141086a41002900a08146370000200141002900988146370000200041086a4293808080b00237020020002001360204200041013602000c070b410f102a2201450d03200141076a41002900b28146370000200141002900ab8146370000200041086a428f808080f00137020020002001360204200041013602000c060b410f102a2201450d02200141076a41002900c18146370000200141002900ba8146370000200041086a428f808080f00137020020002001360204200041013602000c050b4125102a2201450d012001411d6a41002900f18146370000200141186a41002900ec8146370000200141106a41002900e48146370000200141086a41002900dc8146370000200141002900d48146370000200041086a42a5808080d00437020020002001360204200041013602000c040b0240200941086a280200200328022422054b0d004127102a2201450d012001411f6a41002900988246370000200141186a41002900918246370000200141106a41002900898246370000200141086a41002900818246370000200141002900f98146370000200041086a42a7808080f00437020020002001360204200041013602000c040b20092802002109200341286a41086a420037030020034280808080c00037032820012d000d2107410021012003410036024820032007410447220a3602442003200a360240200341003a004c024002400240024041002802d8a14641044b0d00200341d8006a41086a200341c0006a41086a29030037030020032003290340370358200341286a410472210b200341d8006a21070c010b200341353602542003200341c0006a36025041002802e4a146210141002802e0a146210741002802dca146210820034198016a41cb0036020020034190016a42ee808080103703002003418c016a41b483c60036020020034184016a422537020020034180016a41ac84c600360200200341f8006a4201370300200341e8006a4201370300200341d8006a41086a2206410a360200200341f4006a200341d0006a360200200341a082c600360264200341a284c60036025c20034105360258200741ecb3c000200841024622081b200341d8006a200141d4b3c00020081b28021011020020032802342108200328023021012006200341c0006a41086a29030037030020032003290340370358200341286a410472210b200341d8006a210720082001470d010b200141016a22082001490d01200141017422062008200620084b1b220841ffffffff00712008470d01200841047422064100480d010240024020010d002006102a21010c010b200b28020020014104742006102e21010b2001450d02200b200136020020032008360230200328023421080b200b28020020084104746a22012007290200370200200141086a200741086a2902003702002003200328023441016a360234410021072009200541186c6a2201280214450d022009200541186c6a410c6a2109200141146a2108200341d8006a410472210c410021074100210103400240200328022820074d0d00200341d8006a200341286a410010ba05024020032802584101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c060b20072003280228200328025c2d000c1b21070b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001200828020022054f0d002003200928020020014104746a220536023c024041002802d8a1464105490d002003412e36024420032003413c6a36024041002802e4a146210541002802e0a146210641002802dca146210d200341c90136029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d49ec6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328023c21050b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020052d000022060eac0102310000003101030405060708090a0b0c0d0e0f1010101010101010101010101010111111111111111111121314141414151616161616161616161615161616161616161616161616161616161616161616161717171818181818181818181818181818181717171818181818181818181818181818181717171717171718181818181818171717171717171818181818181819191919191919191919191919191919191919191919191919020b20052d000121052003200328022836024820032005410447220536024020032006410347200571360244200341003a004c024041002802d8a1464105490d00200341353602542003200341c0006a36025041002802e4a146210541002802e0a146210641002802dca146210d200341cb0036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341a082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341d0006a360274200641ecb3c000200d1b200341d8006a20051102000b200341d8006a41086a2206200341c0006a41086a290300370300200320032903403703580240200328023422052003280230470d00200541016a220d2005490d332005410174220e200d200e200d4b1b220d41ffffffff0071200d470d33200d410474220e4100480d330240024020050d00200e102a21050c010b200b2802002005410474200e102e21050b2005450d34200b20053602002003200d360230200328023421050b200b28020020054104746a22052003290358370200200541086a20062903003702002003200328023441016a3602340c300b41002105024041002802d8a1464105490d00024020032802342206417f6a220d20064b0d00200b280200200d4104746a4100200d2006491b21050b20034136360254200320053602402003200341c0006a36025041002802e4a146210541002802e0a146210641002802dca146210d200341d30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341a882c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341d0006a360274200641ecb3c000200d1b200341d8006a20051102000b024020032802342205450d0020032005417f6a2205360234200b28020020054104746a22052d000c4102470d1a0b4117102a2201450d322001410f6a41002900bf8246370000200141086a41002900b88246370000200141002900b08246370000200041086a4297808080f00237020020002001360204200041013602000c340b024041002802d8a1464105490d0041002802e4a146210541002802e0a146210641002802dca146210d200341c10036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003410036027c2003420437027420034201370368200341c882c6003602642003410a360260200341a284c60036025c20034105360258200641ecb3c000200d410246220d1b200341d8006a200541d4b3c000200d1b2802101102000b024020032802342205417f6a220620054f0d00200620054d0d180b4117102a2201450d312001410f6a41002900bf8246370000200141086a41002900b88246370000200141002900b08246370000200041086a4297808080f00237020020002001360204200041013602000c330b200341d8006a200341286a200541046a28020010ba05024020032802584101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c330b200341d8006a200341286a200328025c28020410bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c330b024041002802d8a1464105490d0041002802e4a146210541002802e0a146210641002802dca146210d200341c10036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003410036027c2003420437027420034201370368200341c882c6003602642003410a360260200341a284c60036025c20034105360258200641ecb3c000200d410246220d1b200341d8006a200541d4b3c000200d1b2802101102000b024020032802342205417f6a220620054f0d00200620054d0d1a0b4117102a2201450d302001410f6a41002900bf8246370000200141086a41002900b88246370000200141002900b08246370000200041086a4297808080f00237020020002001360204200041013602000c320b200341d8006a200341286a200541046a28020010ba05024020032802584101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c320b200341d8006a200341286a200328025c280204220510bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c320b200341d8006a200341286a410110bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c320b20032005360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d19410e102a2201450d2f200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c310b200341d8006a200341286a200541046a28020028020810ba05024020032802584101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c310b200328025c280204210d2005280204220628020441027421052006280200210602400340024020050d00200341d8006a200341286a200d10bc052003280258450d0220002003290358370204200041013602002000410c6a200341e0006a2802003602000c330b200341d8006a200341286a200628020010ba05024020032802584101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c330b2005417c6a2105200641046a2106200328025c280204200d460d000b4127102a2201450d2f2001411f6a41002900858346370000200141186a41002900fe8246370000200141106a41002900f68246370000200141086a41002900ee8246370000200141002900e68246370000200041086a42a7808080f00437020020002001360204200041013602000c310b024041002802d8a1464105490d0041002802e4a146210541002802e0a146210641002802dca146210d200341c10036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003410036027c2003420437027420034201370368200341c882c6003602642003410a360260200341a284c60036025c20034105360258200641ecb3c000200d410246220d1b200341d8006a200541d4b3c000200d1b2802101102000b024020032802342205417f6a220620054f0d00200620054d0d1a0b4117102a2201450d2e2001410f6a41002900bf8246370000200141086a41002900b88246370000200141002900b08246370000200041086a4297808080f00237020020002001360204200041013602000c300b200341d8006a200341286a200a10bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c300b024041002802d8a1464105490d0041002802e4a146210541002802e0a146210641002802dca146210d200341c10036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003410036027c2003420437027420034201370368200341c882c6003602642003410a360260200341a284c60036025c20034105360258200641ecb3c000200d410246220d1b200341d8006a200541d4b3c000200d1b2802101102000b024020032802342205417f6a220620054f0d00200620054d0d1a0b4117102a2201450d2d2001410f6a41002900bf8246370000200141086a41002900b88246370000200141002900b08246370000200041086a4297808080f00237020020002001360204200041013602000c2f0b200341d8006a200541046a280200200210af05024020032802584101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c2f0b200341d8006a200341286a200328025c220528020810bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c2f0b200320052d000d4104472205360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d19410e102a2201450d2c200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c2e0b200341086a200410f40402400240200328020c200541046a28020022054d0d002003280208220620054104746a220d0d010b410e102a2201450d2c200141066a410029009383463700002001410029008d8346370000200041086a428e808080e00137020020002001360204200041013602000c2e0b200341d8006a200341286a200620054104746a28020810bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c2e0b2003200d2d000d4104472205360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d19410e102a2201450d2b200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c2d0b200341d8006a200341286a410110bc052003280258450d2720002003290358370204200041013602002000410c6a200341e0006a2802003602000c2c0b200341d8006a200341286a410210bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c2c0b41012105200341d8006a200341286a410110bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c2c0b20034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d18410e102a2201450d29200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c2b0b4101210520034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d18410e102a2201450d28200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c2a0b200341d8006a200341286a410110bc052003280258450d2420002003290358370204200041013602002000410c6a200341e0006a2802003602000c290b41012105200341d8006a200341286a410110bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c290b20034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d17410e102a2201450d26200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c280b4101210520034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d17410e102a2201450d25200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c270b200341d8006a200341286a410110bc052003280258450d2120002003290358370204200041013602002000410c6a200341e0006a2802003602000c260b41012105200341d8006a200341286a410110bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c260b20034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d16410e102a2201450d23200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c250b200341d8006a200341286a410210bc052003280258450d1f20002003290358370204200041013602002000410c6a200341e0006a2802003602000c240b4101210520034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d15410e102a2201450d21200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c230b41012105200341d8006a200341286a410110bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c230b20034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d15410e102a2201450d20200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c220b4101210520034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d15410e102a2201450d1f200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c210b41012105200341d8006a200341286a410110bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c210b20034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d15410e102a2201450d1e200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c200b200341d8006a200341286a410210bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c200b4101210520034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d15410e102a2201450d1d200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c1f0b41012105200341d8006a200341286a410110bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c1f0b20034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d15410e102a2201450d1c200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c1e0b200341d8006a200341286a410210bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c1e0b4101210520034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d15410e102a2201450d1b200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c1d0b41012105200341d8006a200341286a410110bc0502402003280258450d0020002003290358370204200041013602002000410c6a200341e0006a2802003602000c1d0b20034101360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a2005110200200328025021050b2003280228220620056a220520064f0d15410e102a2201450d1a200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c1c0b200b28020020064104746a41013a000c0c160b20052802002106200320052802082205360240024041002802d8a1464105490d00200341013602542003200341c0006a36025041002802e4a146210541002802e0a146210d41002802dca146210e200341db0036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c6003602800120034201370378200342013703682003419c83c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200e410246220e1b28021021052003200341d0006a360274200d41ecb3c000200e1b200341d8006a2005110200200328024021050b2003200536022820032006360250024041002802d8a1464105490d00200341013602442003200341d0006a36024041002802e4a146210541002802e0a146210641002802dca146210d200341e30036029801200342ee8080801037039001200341b483c60036028c012003422537028401200341ac84c600360280012003420137037820034201370368200341d082c6003602642003410a360260200341a284c60036025c20034105360258200541d4b3c000200d410246220d1b28021021052003200341c0006a360274200641ecb3c000200d1b200341d8006a200511020020032802282105200328025021060b200520066a220620054f0d14410e102a2201450d18200141066a41002900de8246370000200141002900d88246370000200041086a428e808080e00137020020002001360204200041013602000c1a0b41a483c600200120051038000b200b28020020064104746a41013a000c0c130b200320053602280c120b200b28020020064104746a41013a000c0c110b200b28020020064104746a41013a000c0c100b200320053602280c0f0b200320053602280c0e0b200320053602280c0d0b200320053602280c0c0b200320053602280c0b0b200320053602280c0a0b200320053602280c090b200320053602280c080b200320053602280c070b200320053602280c060b200320053602280c050b200320053602280c040b200320053602280c030b200320053602280c020b200320053602280c010b200320063602280b200141016a22012008280200490d000c030b0b1035000b1033000b20004100360200200020073602042003280230450d01200b280200102c0c010b2003280230450d00200b280200102c0b200341a0016a24000b2200200141b2aec00041adaec00020002802002d000022001b4104410520001b10480bd50302047f017e024020014101762202450d0003402002417f6a2202210302400240024003402003410174220441017221050240200441026a220420014f0d00200520014f0d0220042005200020054103746a280200200020044103746a280200491b21050b200520014f0d03200320014f0d02200020034103746a2203280200200020054103746a22042802004f0d03200329020021062003200429020037020020042006370200200521030c000b0b41a080c600200520011038000b41b080c600200320011038000b20020d000b0b0240024020014102490d002001210403402004417f6a220420014f0d02200029020021062000200020044103746a2205290200370200200520063702004100210302400240024003402003410174220241017221050240200241026a220220044f0d00200520044f0d0220022005200020054103746a280200200020024103746a280200491b21050b200520044f0d03200320044f0d02200020034103746a2203280200200020054103746a22022802004f0d03200329020021062003200229020037020020022006370200200521030c000b0b41a080c600200520041038000b41b080c600200320041038000b200441014b0d000b0b0f0b4188ffc500200420011038000bea04050a7f017e017f017e027f200041686a21022001417f6a2103200041086a2104410021052001413249210641012107024003400240024020072001490d00410021080c010b410121082000200741037422096a220a280200220b200a41786a280200490d00200420096a210803404101210a20032007460d03200741016a21072008280200220a200b4f2109200841086a2108200a210b20090d000b200720014921080b2007200146210a20060d0120072001460d010240024002400240024002402007417f6a220b20014f0d002008450d012000200b4103746a220b290200210c200b20002007410374220d6a2208290200220e3702002008200c37020020074102490d0520002007417e6a220a4103746a220f280200200ea722094d0d05200b200f290200370200200a450d0420002007417d6a220a4103746a28020020094d0d042002200d6a210b0340200b41086a200b290200370200200a450d03200a417f6a210a200b41786a220b28020020094b0d000b200a41016a210b0c030b41f8fec500200b20011038000b4188ffc500200720011038000b4100210b0b2000200b4103746a210f0b200f200e3702000b200541016a21050240200120076b220a4102490d00200828020820082802004f0d002008290200210c20082008290208370200200841086a210f0240200a4103490d002008280210200ca722104f0d00200841106a21094103210b4102210d0340200d41037420086a220f41786a2009290200370200200b200a4f0d01200b4103742109200b210d200b41016a210b200820096a22092802002010490d000b0b200f200c3702000b20054105470d000b4100210a0b200a0b02000bcc0201027f230041106b2202240020002802002802002100200128021841c080c60041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c200241c580c600410e2002410c6a41d480c600106021012002200036020c200141e480c60041092002410c6a41f080c600106021012002200041046a36020c2001418081c600410c2002410c6a41f080c600106021012002200041086a36020c2001418c81c600410c2002410c6a41f080c60010601a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d0020034192b0c0004102200111000021000c010b20034194b0c0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470bc20201027f230041106b22022400200128021841c080c60041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c200241c580c600410e2002410c6a41d480c600106021012002200036020c200141e480c60041092002410c6a41f080c600106021012002200041046a36020c2001418081c600410c2002410c6a41f080c600106021012002200041086a36020c2001418c81c600410c2002410c6a41f080c60010601a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d0020034192b0c0004102200111000021000c010b20034194b0c0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470b8d0201027f02400240024002402001410c6a2802002203417f6a220420034d0d004116102a2201450d01200020013602042001410e6a41002900c58546370000200141086a41002900bf8546370000200141002900b78546370000200041086a4296808080e0023702000c030b0240200420026b220220044d0d00411b102a2201450d0120002001360204200141176a41002800e48546360000200141106a41002900dd8546370000200141086a41002900d58546370000200141002900cd8546370000200041086a429b808080b0033702000c030b200320024d0d012000200128020420024104746a360204200041003602000f0b1033000b41d087c600200220031038000b200041013602000bba0201037f230041106b220224000240024020002802000d002002200128021841fe85c60041042001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b20022001280218418286c60041042001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a418886c6001061210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d004101210020042802184198b0c00041012004411c6a28020028020c1100000d010b2001280200220028021841ec94c60041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470bd10401037f230041e0006b220324002003200236020c024041002802d8a1464105490d002003410136021420032003410c6a36021041002802e4a146210241002802e0a146210441002802dca1462105200341d8006a41ef00360200200341d0006a42ee80808010370300200341cc006a41b483c600360200200341c4006a4225370200200341c0006a41ac84c600360200200341386a4201370300200341286a4201370300200341206a410a360200200341346a200341106a360200200341e084c600360224200341a284c60036021c20034105360218200441ecb3c000200541024622051b200341186a200241d4b3c00020051b280210110200200328020c21020b0240024002402002450d00200341186a2001410010ba0520032802184101470d012000200341186a4104722202290200370200200041086a200241086a2802003602000c020b200041003602000c010b024002400240024020012802002202200328021c2204280208460d002002200328020c6b220420024d0d02410f102a22020d010c030b024020042d000c0d004125102a2202450d03200042a5808080d004370204200020023602002002411d6a41002900858546370000200241186a41002900808546370000200241106a41002900f88446370000200241086a41002900f08446370000200241002900e884463700000c040b200041003602000c030b2000428f808080f00137020420002002360200200241076a410029009485463700002002410029008d85463700000c020b20004100360200200120043602000c010b1033000b200341e0006a24000ba30201077f0240024002400240200041086a2802002201450d00410020014102746b2102417f210320002802002204210503402002450d01200341016a2103200241046a210220052802002106200541046a21052006450d000b4100200641004741016a41017122056b2003460d002001200520036a2207490d012001200641004741016a4101716b20036b220541ffffffff03712005470d0220054102742203417f4c0d020240024020030d00410421030c010b2003102a2203450d040b2003200420074102746a4104200641004741016a41017141027420026a6b10db0521020240200041046a280200450d002000280200102c0b20002002360200200041086a2005360200200041046a20053602000b0f0b200720011047000b103a000b1033000bbb0403067f017e097f02400240024002400240200141086a2802002203200241086a2802002204200320044b1b220541016a22064101200641014b1b220741ffffffff03712007470d0020074102742206417f4c0d000240024020060d00410421080c010b200610302208450d020b024020050d00420021090c040b2004417f6a220a20044b210b2002280200210c2003417f6a220d20034b0d022001280200210e20082007417f6a22024102746a210f410021064200210903404100211002402003200d20066b22114d0d00410021102011200d4b0d00200e20114102746a28020021100b410021110240200b0d002004200a20066b22124d0d002012200a4b0d00200c20124102746a28020021110b200720024d0d05200f20092010ad7c2011ad7c22093e0200200f417c6a210f2002417f6a210220094220882109200641016a22062005490d000c040b0b103a000b1033000b20082007417f6a22024102746a21104100210f420021090340410021060240200b0d00410021062004200a200f6b22114d0d00410021062011200a4b0d00200c20114102746a28020021060b200720024d0d02201020092006ad7c22093e02002010417c6a21102002417f6a210220094220882109200f41016a220f2005490d000b0b024020072005417f736a220220074f0d00200020073602082000200736020420002008360200200820024102746a20093e02000240200141046a280200450d002001280200102c0b0f0b41a888c600200220071038000b41a888c600200220071038000bbb04030d7f017e017f02400240200241086a2802002203200141086a28020022046a22054101200541014b1b220641ffffffff03712006470d0020064102742205417f4c0d0002400240024020050d00410421070c010b200510302207450d010b2004450d022001280200210802400240024020030d0020082004417f6a22054102746a210320072006417f6a22024102746a21090340200420054d0d0302402003280200450d00200620024d0d03200941003602000b2003417c6a21032009417c6a21092002417f6a21022005417f6a2205417f470d000c060b0b200641027420076a417c6a210a200341027420022802006a417c6a210b4100210c2006210d03402004200c417f736a220520044f0d020240200820054102746a220e280200220f450d0042002110417f2105200a2102200b2109024003402006200d20056a22114d0d0120022009350200200fad7e20107c20023502007c22103e0200201042208821100240200320056a0d002006200c20036a417f736a220220064f0d05200720024102746a20103e02000c030b2002417c6a21022009417c6a2109200e280200210f20032005417f6a22056a22112003490d000b41d087c600201120031038000b41d087c600201120061038000b200a417c6a210a200d417f6a210d200c41016a220c2004460d050c000b0b41a888c600200220061038000b41d087c600200520041038000b1033000b103a000b2000200636020820002006360204200020073602000240200141046a280200450d002001280200102c0b0bb60302097f017e230041106b2201240002400240024002400240024002402000280200220228020041016a41004c0d002000280204220328020041016a41004c0d012000280208220441086a28020022054101200028020c22062802006b22076a220820054f0d02200720002802142802006b22052000280210220741086a28020022006a220920054f0d03024002402002290308220a42ffffffff0f560d0041002100200a200428020020084102746a3502007e2003290308422086200728020020094102746a35020084580d010b20022802000d052002410036020020022002290308427f7c370308200441086a2802002200200020062802006b22024d0d0620032802000d07200428020020024102746a350200210a200341003602002003200a20032903087c370308410121000b200141106a240020000f0b41c689c6004118200141086a41e089c600103b000b41c689c6004118200141086a41e089c600103b000b41d087c600200820051038000b41d087c600200920001038000b41f089c6004110200141086a41808ac600103b000b41d087c600200220001038000b41f089c6004110200141086a41808ac600103b000b9e0301087f200028020822024102742103410021042000280200220521000240024003402003450d012004417f6a21042003417c6a210320002802002106200041046a21002006450d000b410121072004417f73200641004741016a4101716a21080c010b41002107410020046b21080b200128020822094102742103410021042001280200220121000240024003402003450d012004417f6a21042003417c6a210320002802002106200041046a21002006450d000b410021032004417f73200641004741016a4101716a21000c010b410020046b2100410121030b024020070d00410020034101736b0f0b4101210402400240024020030d0020022008490d0120092000490d02417f200220086b2203200920006b22064720032006491b22040d0020062003200320064b1b2107200120004102746a2103200520084102746a2100417f210103400240200141016a22012007490d0041000f0b2003280200210420002802002106200341046a2103200041046a2100417f200620044720062004491b2204450d000b0b20040f0b200820021047000b200020091047000b100020002802002000280204200110640bfb05010d7f200128000c21022001280204210320012802002104024002400240024002400240024020012d000822054102470d00200320044f0d010c020b20054101710d010b4100210602400240024002404100200320046b2201200120034b1b220741016a220120074f0d000240200420034b200520054102461b22014102460d002001410171450d004104210841002101410021060c070b2003417f732109200241086a210a41002107200321054104210841002106410021010340200920016a220b200a280200220c6a220d200b4f0d022004200549210b2002280200200d4102746a280200210d024020012006470d002006417f417f41002005200b6b220c20046b220e200e200c4b1b220c41016a220e200e200c491b4100200b1b220c41016a220e200e200c491b6a220c2006490d052006410174220e200c200e200c4b1b220c41ffffffff0371200c470d05200c410274220e4100480d050240024020060d00200e102a21080c010b20082006410274200e102e21080b2008450d04200c21060b200820076a200d360200200741046a21072005417f6a2105200141016a2101200b0d000c070b0b024020010d00410421080c050b200141ffffffff03712001470d02200141027422064100480d022006102a2208450d01200121060c040b41d087c600200120036b200c6a417f6a200c1038000b1033000b1035000b41042108410021060b410021012003200449200520054102461b4101710d0002400240200320044d0d002003417f732101200241086a210d200821052003210703402001200d280200220c6a220b20014f0d0420052002280200200b4102746a280200360200200141016a2101200541046a210520042007417f6a2207490d000b200320046b41016a21010c010b20032004470d0141012101200821050b200241086a28020022072004417f736a220420074f0d022005200228020020044102746a2802003602000b2000200136020820002006360204200020083602000f0b41d087c600200b200c1038000b41d087c600200420071038000b7301027f230041106b2203240002404110102a22040d001033000b200420013e020c200420014220883e0208200420023e0204200420024220883e020020034284808080c00037020420032004360200200310bd05200041086a200328020836020020002003290300370200200341106a24000b1c00200128021841b68bc600410f2001411c6a28020028020c1100000bb00301047f230041c0006b2202240020002802002103410121000240200128021841cfaec000410c2001411c6a28020028020c1100000d0002400240200328020822000d0020032802002200200328020428020c11070042e4aec285979ba58811520d012002200036020c2002413036021420022002410c6a36021020012802182104200128021c2105410121002002413c6a41013602002002420237022c200241dcaec0003602282002200241106a36023820042005200241286a10390d020c010b2002200036020c2002410836021420022002410c6a36021020012802182104200128021c2105410121002002413c6a41013602002002420237022c200241dcaec0003602282002200241106a36023820042005200241286a10390d010b200328020c2100200241106a41146a4101360200200241106a410c6a410136020020022000410c6a3602202002200041086a360218200241043602142002200036021020012802182100200128021c2101200241286a41146a41033602002002420337022c200241ecaec0003602282002200241106a36023820002001200241286a103921000b200241c0006a240020000b21002000417f6a41ff01712002ad4220862001ad842004ad4220862003ad8410000b7d01017f024002400240200041046a280200220320016b20024f0d00200120026a22022001490d02200341017422012002200120024b1b22014100480d020240024020030d002001102a21020c010b200028020020032001102e21020b2002450d0120002002360200200041046a20013602000b0f0b1033000b1035000bd90101017f230041e0006b22042400200420013602082004200336020c024020012003470d0020002002200110db051a200441e0006a24000f0b200441286a41146a4109360200200441346a410c360200200441106a41146a410336020020044203370214200441ec9fc6003602102004410c36022c2004200441086a36024020042004410c6a360244200442043703582004420137024c200441c0a0c6003602482004200441286a3602202004200441c8006a3602382004200441c4006a3602302004200441c0006a360228200441106a41fca0c6001041000ba20601037f230041d0006b22042400200420033a000f024002400240024020022802082205417f6a220620054f0d00200620054d0d010b4118102a2202450d012004421837023420042002360230200441306a4100411810c80520042004280238220241186a3602382002200428023022056a411841ba9dc600411810c9052004200429023437023420042005360230418493c6004134200441306a41f492c600103b000b200141086a2802002105200228020020064103746a2206280200210202400240024020062d0006450d0020052002460d010b02400240200520024d0d00200141086a2005417f6a2202360200200128020020026a2d00002205417c6a220241014b0d01024020020e020300030b4118102a2202450d04200241106a41002900ca9d46370000200241086a41002900c29d46370000200241002900ba9d4637000020044298808080800337022420042002360220200441c4006a410136020020044201370234200441e897c6003602302004412d36024c2004200441c8006a3602402004200441206a360248200441106a200441306a103702402004280224450d002004280220102c0b200041013a0000200041046a20042903103702002000410c6a200441106a41086a2802003602000c050b412b102a2202450d03200041013a0000200241276a41002800a29746360000200241206a410029009b9746370000200241186a41002900939746370000200241106a410029008b9746370000200241086a41002900839746370000200241002900fb9646370000200041086a42ab808080b005370200200041046a20023602000c040b0240200341ff017122024104460d0020052002470d020b200041003a0000200020053a00010c030b20004180083b01000c020b200420053a0048200441c4006a4102360200200441206a410c6a413236020020044202370234200441a897c600360230200441323602242004200441206a3602402004200441c8006a36022820042004410f6a360220200441106a200441306a10372000410c6a200441186a280200360200200041046a2004290310370200200041013a00000c010b1033000b200441d0006a24000bef0502047f017e230041d0006b2203240002400240024002400240200241086a2802002204417f6a220520044f0d00200520044d0d010b4118102a2202450d01200241106a41002900ca9d46370000200241086a41002900c29d46370000200241002900ba9d4637000020034298808080800337021420032002360210200341cc006a41013602002003420137023c200341e897c6003602382003412d3602342003200341306a3602482003200341106a360230200341206a200341386a1037200041086a200341206a41086a280200360200200020032903203702002003280214450d032003280210102c0c030b0240024002402002280200220620054103746a2d000522054104460d00200341386a20012002200510ca05024020032d00384101470d002000200329023c370200200041086a200341c4006a2802003602000c060b200241086a2802002204450d01200228020021060b200241086a2004417f6a2202360200200620024103746a290200220742808080808080c0ff0083428080808080808001520d010b4118102a2202450d01200241106a41002900ca9d46370000200241086a41002900c29d46370000200241002900ba9d4637000020034298808080800337021420032002360210200341cc006a41013602002003420137023c200341e897c6003602382003412d3602342003200341306a3602482003200341106a360230200341206a200341386a1037200041086a200341206a41086a280200360200200020032903203702002003280214450d032003280210102c0c030b200141086a28020021022003200737030820022007a7470d01200041003602000c020b1033000b200341cc006a41023602002003412c6a41013602002003420237023c200341c896c60036023820034101360224200320023602302003200341206a3602482003200341086a3602282003200341306a360220200341106a200341386a1037200041086a200341106a41086a280200360200200020032903103702000b200341d0006a24000ba80301057f230041c0006b2203240020032002360200024002402001280204220420024b0d002001280208417c6a21052001410c6a280200410374210102400340024020010d00200320043602042003412c6a4102360200200341306a410c6a41013602002003420337021c200341949fc600360218200341013602342003200341306a3602282003200341046a36023820032003360230200341086a200341186a10372000410c6a200341106a280200360200200041046a2003290308370200200041013a00000c040b02402004200541046a2802006a220620044f0d004120102a2204450d02200041013a0000200441186a410029008c9f46370000200441106a41002900849f46370000200441086a41002900fc9e46370000200441002900f49e46370000200041086a42a08080808004370200200041046a20043602000c040b200141786a2101200541086a2105200420024b21072006210420070d0020062104200620024d0d000b20052d00002104200041003a0000200020043a00010c020b1033000b200041003a00002000200128020020026a2d00003a00010b200341c0006a24000bbd0201037f230041106b220224000240024020002d00004104470d002002200128021841a595c60041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841a895c60041082001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41b095c6001061210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d004101210020042802184198b0c00041012004411c6a28020028020c1100000d010b2001280200220028021841ec94c60041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470b820602037f017e230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200541386a200141186a2203200141286a410010ca0520052d00384101470d012000200529023c370200200041086a200541c4006a2802003602000c020b200541cc006a41023602002005411c6a41013602002005420337023c200541a494c600360238200541013602142005200541106a36024820052005410c6a3602182005200541086a360210200541206a200541386a1037200041086a200541206a41086a280200360200200020052903203702000c010b2001280200210220054100360220024020022802080d00200541cc006a41013602002005420237023c200541b89bc600360238200541013602342005200541306a3602482005200541206a360230200541106a200541386a103720052802102202450d0020002005290214370204200020023602000c010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d03200241017422072006200720064b1b22064100480d030240024020020d002006102a21020c010b200328020020022006102e21020b2002450d02200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2202200228020041016a3602000c030b200541cc006a220241013602002005420137023c200541b49ec60036023820054101360234200520063602302005200541306a360248200541106a200541386a103720052802102201450d022005200529021437022420052001360220200241013602002005420137023c200541e897c6003602382005412d3602342005200541306a3602482005200541206a360230200541106a200541386a1037200528021021022005290214210802402005280224450d002005280220102c0b2002450d0220002008370204200020023602000c030b1033000b1035000b200041003602000b200541d0006a24000bae0301017f230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200128020021022005410036023420022802080d01200541cc006a41013602002005420237023c200541b89bc600360238200541013602142005200541106a3602482005200541346a360210200541206a200541386a103720052802202202450d0120002005290224370204200020023602000c020b200541cc006a41023602002005412c6a41013602002005420337023c200541a494c600360238200541013602242005200541206a36024820052005410c6a3602282005200541086a360220200541106a200541386a1037200041086a200541106a41086a280200360200200020052903103702000c010b200541386a200141186a2202200141286a2203200410ca05024020052d00384101470d002000200529023c370200200041086a200541c4006a2802003602000c010b200541386a20022003410010ca05024020052d00384101470d002000200529023c370200200041086a200541c4006a2802003602000c010b200041003602000b200541d0006a24000be90302047f017e230041c0006b22032400200341286a200141186a2204200141286a200210ca050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d03200241017422062005200620054b1b22054100480d030240024020020d002005102a21020c010b200428020020022005102e21020b2002450d02200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c200341b49ec60036022820034101360214200320053602102003200341106a360238200341186a200341286a103720032802182202450d022003200329021c37020420032002360200200141013602002003420137022c200341e897c6003602282003412d3602142003200341106a36023820032003360210200341186a200341286a103720032802182101200329021c210702402003280204450d002003280200102c0b2001450d0220002007370204200020013602000c030b1033000b1035000b200041003602000b200341c0006a24000ba20402047f017e230041c0006b22032400200341286a200141186a2204200141286a2205200210ca050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b200341286a20042005200210ca05024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d03200241017422062005200620054b1b22054100480d030240024020020d002005102a21020c010b200428020020022005102e21020b2002450d02200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c200341b49ec60036022820034101360214200320053602102003200341106a360238200341186a200341286a103720032802182202450d022003200329021c37020420032002360200200141013602002003420137022c200341e897c6003602282003412d3602142003200341106a36023820032003360210200341186a200341286a103720032802182101200329021c210702402003280204450d002003280200102c0b2001450d0220002007370204200020013602000c030b1033000b1035000b200041003602000b200341c0006a24000be90302057f017e230041c0006b22032400200341286a200141186a2204200141286a200210ca050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d03200541017422072006200720064b1b22064100480d030240024020050d002006102a21050c010b200428020020052006102e21050b2005450d02200120053602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c200341b49ec60036022820034101360214200320063602102003200341106a360238200341186a200341286a103720032802182202450d022003200329021c37020420032002360200200141013602002003420137022c200341e897c6003602282003412d3602142003200341106a36023820032003360210200341186a200341286a103720032802182101200329021c210802402003280204450d002003280200102c0b2001450d0220002008370204200020013602000c030b1033000b1035000b200041003602000b200341c0006a24000ba20402057f017e230041c0006b22032400200341286a200141186a2204200141286a2205200210ca050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b200341286a20042005200210ca05024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d03200541017422072006200720064b1b22064100480d030240024020050d002006102a21040c010b200428020020052006102e21040b2004450d02200120043602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c200341b49ec60036022820034101360214200320063602102003200341106a360238200341186a200341286a103720032802182202450d022003200329021c37020420032002360200200141013602002003420137022c200341e897c6003602282003412d3602142003200341106a36023820032003360210200341186a200341286a103720032802182101200329021c210802402003280204450d002003280200102c0b2001450d0220002008370204200020013602000c030b1033000b1035000b200041003602000b200341c0006a24000be90302047f017e230041c0006b22042400200441286a200141186a2205200141286a200210ca050240024020042d00284101470d002000200429022c370200200041086a200441346a2802003602000c010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d03200241017422072006200720064b1b22064100480d030240024020020d002006102a21020c010b200528020020022006102e21020b2002450d02200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20033a0000200141206a2201200128020041016a3602000c030b2004413c6a220141013602002004420137022c200441b49ec60036022820044101360214200420063602102004200441106a360238200441186a200441286a103720042802182202450d022004200429021c37020420042002360200200141013602002004420137022c200441e897c6003602282004412d3602142004200441106a36023820042004360210200441186a200441286a103720042802182101200429021c210802402004280204450d002004280200102c0b2001450d0220002008370204200020013602000c030b1033000b1035000b200041003602000b200441c0006a24000b17000240200041046a280200450d002000280200102c0b0b0c002000280200200110a1050b1500200028020022002802002000280208200110640b100020012000280200200028020810480bfb0101027f230041106b220224002002200128021841dc9ec60041052001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41e49ec60010611a20022d00082101024020022802042203450d00200141ff0171210041012101024020000d00024020034101470d0020022d000941ff0171450d00200228020022002d00004104710d004101210120002802184198b0c00041012000411c6a28020028020c1100000d010b2002280200220128021841ec94c60041012001411c6a28020028020c11000021010b200220013a00080b200241106a2400200141ff01714100470b2c01017f02402002450d00200021030340200320013a0000200341016a21032002417f6a22020d000b0b20000b3601017f02402002450d00200021030340200320012d00003a0000200341016a2103200141016a21012002417f6a22020d000b0b20000b7101017f0240024020012000490d002002450d01200021030340200320012d00003a0000200141016a2101200341016a21032002417f6a22020d000c020b0b2002450d002001417f6a21012000417f6a21030340200320026a200120026a2d00003a00002002417f6a22020d000b0b20000b4a01037f4100210302402002450d000240034020002d0000220420012d00002205470d01200041016a2100200141016a21012002417f6a2202450d020c000b0b200420056b21030b20030b5701017e02400240200341c000710d002003450d012001410020036b413f71ad8820022003413f71ad220486842102200120048621010c010b20012003413f71ad862102420021010b20002001370300200020023703080b5701017e02400240200341c000710d002003450d0120012003413f71ad2204882002410020036b413f71ad86842101200220048821020c010b20022003413f71ad882101420021020b20002001370300200020023703080b7501027e200020034220882205200142208822067e200320027e7c200420017e7c200342ffffffff0f832203200142ffffffff0f8322017e2204422088200320067e7c22034220887c200342ffffffff0f83200520017e7c22034220887c37030820002003422086200442ffffffff0f83843703000b3e01017f230041106b2205240020052001200220032004410010e305200529030021012000200541086a29030037030820002001370300200541106a24000b4c01017f230041206b22052400200542003703182005420037031020052001200220032004200541106a10e305200529031021012000200529031837030820002001370300200541206a24000be20502037f067e230041306b2206240002400240024002400240024002400240024002402002500d002003500d012004500d02200479a7200279a76b2207413f4b0d0341ff0020076b2108200741016a21070c080b02402004500d0020050d040c060b024002402005450d0020034200510d0620054200370308200520012003823703000c010b20034200510d050b200120038021010c060b2004500d030240024002402001500d0020047b4201510d01200479a7200279a76b2207413e4b0d0241ff0020076b2108200741016a21070c090b02402005450d0020054200370300200520022004823703080b200220048021010c070b02402005450d002005200137030020052004427f7c2002833703080b200220047a423f838821010c060b2005450d040c020b024020037b4201510d0041bf7f200379a7200279a76b22076b2108200741c1006a21070c060b02402005450d002005420037030820052003427f7c2001833703000b20034201510d06200641206a2001200220037aa710df05200641286a2903002102200629032021010c060b2005450d020b2005200137030020052002370308420021010c020b00000b420021010b420021020c010b200620012002200841ff007110de05200641106a20012002200741ff007110df05200641086a2903002102200641106a41086a2903002109200629030021012006290310210a0240024020070d004200210b4200210c0c010b4200210c4200210d03402009420186200a423f8884220b200b427f8520047c200a4201862002423f8884220a427f85220b20037c200b54ad7c423f87220b2004837d200a200b200383220e54ad7d2109200a200e7d210a420020024201862001423f8884842102200d2001420186842101200b420183220b210d2007417f6a22070d000b0b02402005450d002005200a370300200520093703080b200c20024201862001423f8884842102200b20014201868421010b2000200137030020002002370308200641306a24000b0b80a2060300418080c0000bd5a1066361706163697479206f766572666c6f77000000240010001700000009030000050000007372632f6c6962616c6c6f632f7261775f7665632e727300a8001000460000005a0100001300000037000000040000000400000038000000390000003a0000006120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f72003b00000000000000010000003c0000002f72757374632f373661323532656139653762653933613631666664663333623335333365323461396366343539642f7372632f6c6962636f72652f666d742f6d6f642e7273010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020202020202020202020202020202020202020202020202020202020203030303030303030303030303030303040404040400000000000000000000000000100210002000000030021000120000003b00000000000000010000003d000000696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e646578206973203030303130323033303430353036303730383039313031313132313331343135313631373138313932303231323232333234323532363237323832393330333133323333333433353336333733383339343034313432343334343435343634373438343935303531353235333534353535363537353835393630363136323633363436353636363736383639373037313732373337343735373637373738373938303831383238333834383538363837383838393930393139323933393439353936393739383939000044031000060000004a031000220000002c03100018000000690a0000050000007372632f6c6962636f72652f736c6963652f6d6f642e7273696e64657820206f7574206f662072616e676520666f7220736c696365206f66206c656e677468208c03100016000000a20310000d0000002c031000180000006f0a000005000000736c69636520696e64657820737461727473206174202062757420656e6473206174206030785b2e2e2e5d009a0410000b0000001717100016000000af0310000100000084041000160000000408000009000000f51610000e00000003171000040000000717100010000000af031000010000008404100016000000080800000500000063616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c756500e0161000150000007d010000150000009a0410000b000000a504100026000000cb04100008000000d304100006000000af03100001000000840410001600000015080000050000007372632f6c6962636f72652f7374722f6d6f642e72736279746520696e64657820206973206e6f742061206368617220626f756e646172793b20697420697320696e7369646520202862797465732029206f6620600000001a0510000200000004051000160000005e04000028000000040510001600000053040000280000007372632f6c6962636f72652f666d742f6d6f642e72732e2e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000f8030000000000000000000000000000000000000000000000000000000000000000feffffffffbfb6000000000000000000ff070000000000f8ffff0000010000000000000000000000c09f9f3d0000000002000000ffffff0700000000000000000000c0ff01000000000000f80f20c01010004a0000001013100000020000101510003a00000000010203040506070809080a0b0c0d0e0f10111213140215161718191a1b1c1d1e1f2002020202020202020202210202020202020202020202020202222324252602270228020202292a2b022c2d2e2f300202310202023202020202020202023302023402020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023502360237020202020202020238023902020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023a3b3c020202023d02023e3f4041424344454602020247020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202024802020202020202020202024902020202023b020001020202020302020202040205060202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020207020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200010305050606030706080809110a1c0b190c140d120e0d0f0410031212130916011705180219031a071c021d011f1620032b042c022d0b2e01300331023201a702a902aa04ab08fa02fb05fd04fe03ff09ad78798b8da23057588b8c901c1ddd0e0f4b4cfbfc2e2f3f5c5d5fb5e2848d8e9192a9b1babbc5c6c9cadee4e5ff00041112293134373a3b3d494a5d848e92a9b1b4babbc6cacecfe4e500040d0e11122931343a3b4546494a5e646584919b9dc9cecf0d112945495764658d91a9b4babbc5c9dfe4e5f0040d1145496465808184b2bcbebfd5d7f0f183858ba4a6bebfc5c7cecfdadb4898bdcdc6cecf494e4f57595e5f898e8fb1b6b7bfc1c6c7d71116175b5cf6f7feff800d6d71dedf0e0f1f6e6f1c1d5f7d7eaeafbbbcfa16171e1f46474e4f585a5c5e7e7fb5c5d4d5dcf0f1f572738f747596972f5f262e2fa7afb7bfc7cfd7df9a409798308f1fc0c1ceff4e4f5a5b07080f10272feeef6e6f373d3f42459091feff536775c8c9d0d1d8d9e7feff00205f2282df048244081b04061181ac0e80ab351e1580e003190801042f043404070301070607110a500f1207550802041c0a090308030703020303030c0405030b06010e15053a0311070605100757070207150d500443032d03010411060f0c3a041d255f206d046a2580c80582b0031a0682fd035907150b1709140c140c6a060a061a0659072b05460a2c040c040103310b2c041a060b0380ac060a061f414c042d0374083c030f033c0738082b0582ff1118082f112d032010210f808c048297190b158894052f053b07020e180980b030740c80d61a0c0580ff0580b605240c9bc60ad23010848d033709815c1480b80880c73035040a06380846080c06740b1e035a0459098083181c0a16094808808a06aba40c170431a10481da26070c050580a511816d1078282a064c04808d0480be031b030f0d0006010103010402080809020a050b02100111041205131114021502170219041c051d0824016a036b02bc02d102d40cd509d602d702da01e005e102e802ee20f004f906fa020c273b3e4e4f8f9e9e9f060709363d3e56f3d0d104141836375657bd35cecfe01287898e9e040d0e11122931343a4546494a4e4f64655a5cb6b71b1ca8a9d8d909379091a8070a3b3e66698f926f5feeef5a629a9b2728559da0a1a3a4a7a8adbabcc4060b0c151d3a3f4551a6a7cccda007191a22253e3fc5c604202325262833383a484a4c50535556585a5c5e606365666b73787d7f8aa4aaafb0c0d00c72a3a4cbcc6e6f5e227b0503042d036504012f2e80821d03310f1c0424091e052b0544040e2a80aa06240424042808340b018090813709160a088098390363080930160521031b05014038044b052f040a070907402027040c0936033a051a07040c07504937330d33072e080a81261f808128082a808617094e041e0f430e19070a0647092709750b3f412a063b050a0651060105100305808b602048080a80a65e22450b0a060d1339070a362c041080c03c64530c0180a0451b4808531d398107460a1d03474937030e080a0639070a81361980c7320d839b66750b80c48abc842f8fd18247a1b98239072a040260260a460a28051382b05b654b0439071140041c97f80882f3a50d811f3103110408818c89046b050d03090710936080f60a73086e1746809a140c570919808781470385420f1585502b80d52d031a040281703a0501850080d7294c040a04028311444c3d80c23c06010455051b3402810e2c04640c560a0d035d033d391d0d2c040907020e06809a83d60a0d030b05740c59070c140c0438080a0628081e527703310380a60c14040305030d06856a000000a0101000200000002700000019000000a0101000200000002800000020000000a0101000200000002a00000019000000a0101000200000002b00000018000000a0101000200000002c000000200000007372632f6c6962636f72652f756e69636f64652f626f6f6c5f747269652e72730000c0fbef3e00000000000e0000000000000000000000000000f8fffbffffff0700000000000014fe21fe000c00000002000000000000501e2080000c00004006000000000000108639020000002300be2100000c0000fc02000000000000d01e20c0000c0000000400000000000040012080000000000011000000000000c0c13d60000c0000000200000000000090443060000c00000003000000000000581e2080000c00000000845c8000000000000000000000f207807f000000000000000000000000f21f003f000000000000000000030000a002000000000000fe7fdfe0fffeffffff1f40000000000000000000000000e0fd66000000c301001e006420002000000000000000e00000000000001c0000001c0000000c0000000c00000000000000b03f40fe0f200000000000380000000000006000000000020000000000008701040e00008009000000000000407fe51ff89f000000000000ff7f0f0000000000f0170400000000f80f00030000003c3b00000000000040a303000000000000f0cf000000f7fffd211003fffffffffffffffb00100000000000000000ffffffff01000000000000800300000000000000008000000000ffffffff0000000000fc00000000000600000000000000000080f73f000000c0000000000000000000000300440800006000000030000000ffff038000000000c03f000080ff030000000000070000000000c833000000002000000000000000007e660008100000000000100000000000009dc1020000000030400000000000202100000000004000000000ffff0000ffff00000000000000000001000000020003000000000000000000000000000000000000000000000000000004000005000000000000000006000000000000000007000008090a000b0c0d0e0f000010111200001314151600001718191a1b001c0000001d0000000000001e1f202100000000002200230024252600000000270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002829000000000000000000000000000000002a2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000002d2e00002f0000000000000000000000000000000000000000000000000000000000003031320000000000000000000000000000000000000000003300000029000000000000340000000000000000000000000000000000000000000000350036000000000000000000000000000000000000000000000000000037380000383838390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000001000000000000000000c0076ef0000000000087000000006000000000000000f0000000c0ff01000000000002000000000000ff7f0000000000008003000000000078060700000080ef1f000000000000000800030000000000c07f001e000000000000000000000080d34000000080f8070000030000000000005801008000c01f1f0000000000000000ff5c00004000000000000000000000f9a50d000000000000000000000000803cb00100003000000000000000000000f8a70100000000000000000000000028bf00000000e0bc0f0000000000000080ff060000f00c01000000fe0700000000f87980007e0e0000000000fc7f03000000000000000000007fbf0000fcfffffc6d000000000000007eb4bf000000000000000000a3000000000000000000000018000000000000001f000000000000007f0000800000000000000080070000000000000000600000000000000000a0c307f8e70f0000003c00001c00000000000000ffffffffffff7ff8ffffffffff1f2000100000f8feff00007ffffff9db0700000000000000f0000000007f0000000000f00700000000000000000000ffffffffffffffffffffffffffffffffffff00007372632f6c6962636f72652f6f7074696f6e2e7273626567696e203c3d20656e642028203c3d2029207768656e20736c6963696e672060206973206f7574206f6620626f756e6473206f66206066616c736574727565426f72726f774572726f72426f72726f774d75744572726f7270616e69636b65642061742000851710000100000086171000030000005c8f110000000000841710000100000084171000010000003a27272c20000000e016100015000000a4040000050000005c8f110000000000f596100002000000bc17100015000000a5040000050000007372632f6c6962636f72652f726573756c742e72735b5d0a3e0000000c000000040000003f00000040000000410000002c0a2c2037000000040000000400000042000000430000004400000020202020207b20207b0a207d7d28280a2c0000003b000000000000000100000045000000460000004700000037000000040000000400000048000000490000004a00000000000000a41810001000000000000000b4181000010000000000000000000000bc181000010000000000000000000000c41810000f00000000000000d4181000020000000000000000000000e4181000010000000000000045787472696e73696353756363657373011910000c0000000d1910002500000045787472696e7369634661696c6564006b8611000d000000011910000c000000ec1810001500000020416e2065787472696e736963206661696c65642e4469737061746368496e666f20416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e52657175697265526f6f744f726967696e526571756972655369676e65644f726967696e526571756972654e6f4f726967696e000000000000004319100013000000000000005c8f11000000000000000000000000003219100011000000000000005c8f1100000000000000000000000000561910000f000000000000005c8f110000000000000000003b00000000000000010000004b0000004c000000470000003b00000000000000010000004b0000004c00000047000000617373657274696f6e206661696c65643a20696e646578203c3d206c656e617373657274696f6e206661696c65643a20696e646578203c206c656e00381a100043000000310b0000300000002f72757374632f373661323532656139653762653933613631666664663333623335333365323461396366343539642f7372632f6c6962616c6c6f632f7665632e727300381a1000430000003d0b00002c00000062656e6566696369617279206163636f756e74206d757374207072652d65786973745374616c6c65643a6772616e6470615f617574686f726974696573546f74616c49737375616e63654672656542616c616e6365526573657276656442616c616e63654c6f636b7300000000000000a81b10000a00000000000000d8ef1000020000000000000000000000b41b1000010000000000000000000000bc1b10000d00000000000000d8ef1000020000000000000000000000cc1b100001000000000000000000000048f310000800000000000000d41b1000040000000000000000000000f41b1000010000000000000000000000fc1b10000a00000000000000081c1000030000000000000000000000201c100001000000000000004e65774163636f756e7400009c1c10001b0000005265617065644163636f756e74000000851c100017000000e252110009000000e2521100090000009b1f1100070000009b1f110007000000591c10002c00000042616c616e63655365740000e2521100090000009b1f1100070000009b1f110007000000281c10003100000020412062616c616e6365207761732073657420627920726f6f74202877686f2c20667265652c207265736572766564292e205472616e7366657220737563636565646564202866726f6d2c20746f2c2076616c75652c2066656573292e20416e206163636f756e7420776173207265617065642e2041206e6577206163636f756e742077617320637265617465642e5265706f72747350656e64696e674368616e67655374617465746f6f2066657720667265652066756e647320696e206163636f756e747061796d656e7420776f756c64206b696c6c206163636f756e7456657374696e676163636f756e74206c6971756964697479207265737472696374696f6e732070726576656e74207769746864726177616c76657374696e672062616c616e636520746f6f206869676820746f2073656e642076616c75650000004d00000008000000040000004e0000004f00000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d00000008000000040000004e0000004f00000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e657874466f72636564000000000000b81f10001200000000000000cc1f1000010000000000000000000000e41f100001000000000000007265706f72745f6d69736265686176696f72000000000000052010000700000000000000e960110007000000ec1f100019000000205265706f727420736f6d65206d69736265686176696f722e5f7265706f727400000000486311000b0000000000000000000000c76c11000d000000000000000000000000000000000000000000000000000000000000005c8f11003c3b100000000000000000007422100004000000000000000100000000000000cb1c1000050000000000000000000000942210001b000000000000000000000000000000000000000000000000000000000000005c8f1100b02210000000000000000000c022100001000000000000000100000000000000be1c10000d0000000000000000000000c822100023000000000000000000000000000000000000000000000000000000000000005c8f1100fc3a10000000000000000000ec22100001000000000000000000000000000000801f10000a00000000000000000000009c6011000e000000000000000000000000000000000000000000000000000000000000005c8f11005c2310000000000000000000f422100001000000000000000000000000000000ae1a1000070000000000000000000000fc22100020000000000000000000000000000000000000000000000000000000000000005c8f11001c23100000000000000000002c23100001000000000000000000000000000000d46c11000c00000000000000000000003423100005000000000000000000000000000000000000000000000000000000000000005c8f11003c23100000000000000000004c23100002000000000000000100000000000000ef6c11000c0000000101000000000000342310000500000000000000e76f11000c000000000000000000000000000000000000005c8f11005c23100000000000000000006c231000010000000000000000000000142510000b0000005c8f1100000000001f25100058000000772510002500000053746f72656453746174653c543a3a426c6f636b4e756d6265723e003b000000000000000100000051000000f02410002400000053746f72656450656e64696e674368616e67653c543a3a426c6f636b4e756d6265723e00bf24100031000000902410002f00000028543a3a426c6f636b4e756d6265722c20543a3a426c6f636b4e756d626572293b0000000000000001000000520000006c2410002400000053657449640000003b000000000000000100000053000000e4231000570000003b241000310000003b00000000000000010000005200000074231000700000002041206d617070696e672066726f6d206772616e6470612073657420494420746f2074686520696e646578206f6620746865202a6d6f737420726563656e742a2073657373696f6e20666f7220776869636820697473206d656d62657273207765726520726573706f6e7369626c652e20546865206e756d626572206f66206368616e6765732028626f746820696e207465726d73206f66206b65797320616e6420756e6465726c79696e672065636f6e6f6d696320726573706f6e736962696c69746965732920696e20746865202273657422206f66204772616e6470612076616c696461746f72732066726f6d2067656e657369732e20607472756560206966207765206172652063757272656e746c79207374616c6c65642e206e65787420626c6f636b206e756d6265722077686572652077652063616e20666f7263652061206368616e67652e2050656e64696e67206368616e67653a20287369676e616c65642061742c207363686564756c6564206368616e6765292e205374617465206f66207468652063757272656e7420617574686f72697479207365742e20444550524543415445442054686973207573656420746f2073746f7265207468652063757272656e7420617574686f72697479207365742c20776869636820686173206265656e206d6967726174656420746f207468652077656c6c2d6b6e6f776e204752414e4450415f415554484f52495445535f4b455920756e686173686564206b65792e6e6f7420656e6f75676820667265652066756e6473000000000000006426100008000000000000006c2610000200000000000000000000009c261000190000000000000000000000642710000b0000000000000070271000030000000000000000000000b82710000d0000000000000000000000202810000e0000000000000030281000030000000000000000000000782810000200000000000000000000008828100013000000000000006c2610000200000000000000000000009c28100006000000000000007472616e7366657200000000560311000400000000000000b55a11002300000000000000143611000500000000000000f529100013000000cf2b1000360000005c8f110000000000052c100042000000472c1000480000008f2c100045000000d42c10002d0000005c8f110000000000012d1000460000005c8f1100000000002d5a11000b000000472d10004c000000932d100033000000c62d10005a0000005c8f110000000000202e1000130000005c8f110000000000332e100054000000872e10004b000000d22e100035000000072f1000370000003e2f100056000000942f100052000000e62f10003e0000005c8f110000000000a65a11000c0000007365745f62616c616e63650000000000b25a11000300000000000000b55a11002300000000000000bb2b10000800000000000000f52910001300000000000000c32b10000c00000000000000f529100013000000082a1000250000005c8f1100000000002d2a100048000000752a100042000000b72a100046000000fd2a1000400000005c8f1100000000003d2b10002d0000005c8f1100000000002d5a11000b0000006a2b1000200000008a2b100031000000a65a11000c000000666f7263655f7472616e73666572000000000000ef2910000600000000000000b55a11002300000000000000560311000400000000000000b55a11002300000000000000143611000500000000000000f5291000130000009029100054000000e42910000b0000007472616e736665725f6b6565705f616c69766500cc2810005400000020291000100000005c8f110000000000302910002f0000005c8f1100000000005f291000310000002053616d6520617320746865205b607472616e73666572605d2063616c6c2c206275742077697468206120636865636b207468617420746865207472616e736665722077696c6c206e6f74206b696c6c20746865206f726967696e206163636f756e742e20393925206f66207468652074696d6520796f752077616e74205b607472616e73666572605d20696e73746561642e205b607472616e73666572605d3a207374727563742e4d6f64756c652e68746d6c236d6574686f642e7472616e736665722045786163746c7920617320607472616e73666572602c2065786365707420746865206f726967696e206d75737420626520726f6f7420616e642074686520736f75726365206163636f756e74206d6179206265207370656369666965642e736f75726365436f6d706163743c543a3a42616c616e63653e20536574207468652062616c616e636573206f66206120676976656e206163636f756e742e20546869732077696c6c20616c74657220604672656542616c616e63656020616e642060526573657276656442616c616e63656020696e2073746f726167652e2069742077696c6c20616c736f2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d202860546f74616c49737375616e636560292e20496620746865206e65772066726565206f722072657365727665642062616c616e63652069732062656c6f7720746865206578697374656e7469616c206465706f7369742c2069742077696c6c20726573657420746865206163636f756e74206e6f6e63652028606672616d655f73797374656d3a3a4163636f756e744e6f6e636560292e20546865206469737061746368206f726967696e20666f7220746869732063616c6c2069732060726f6f74602e202d20496e646570656e64656e74206f662074686520617267756d656e74732e202d20436f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e64207772697465732e6e65775f667265656e65775f7265736572766564205472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572206163636f756e742e20607472616e73666572602077696c6c207365742074686520604672656542616c616e636560206f66207468652073656e64657220616e642072656365697665722e2049742077696c6c2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d2062792074686520605472616e73666572466565602e204966207468652073656e6465722773206163636f756e742069732062656c6f7720746865206578697374656e7469616c206465706f736974206173206120726573756c74206f6620746865207472616e736665722c20746865206163636f756e742077696c6c206265207265617065642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605369676e65646020627920746865207472616e736163746f722e202d20446570656e64656e74206f6e20617267756d656e747320627574206e6f7420637269746963616c2c20676976656e2070726f70657220696d706c656d656e746174696f6e7320666f72202020696e70757420636f6e6669672074797065732e205365652072656c617465642066756e6374696f6e732062656c6f772e202d20497420636f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e642077726974657320696e7465726e616c6c7920616e64206e6f20636f6d706c657820636f6d7075746174696f6e2e2052656c617465642066756e6374696f6e733a2020202d2060656e737572655f63616e5f77697468647261776020697320616c776179732063616c6c656420696e7465726e616c6c792062757420686173206120626f756e64656420636f6d706c65786974792e2020202d205472616e7366657272696e672062616c616e63657320746f206163636f756e7473207468617420646964206e6f74206578697374206265666f72652077696c6c20636175736520202020202060543a3a4f6e4e65774163636f756e743a3a6f6e5f6e65775f6163636f756e746020746f2062652063616c6c65642e2020202d2052656d6f76696e6720656e6f7567682066756e64732066726f6d20616e206163636f756e742077696c6c2074726967676572202020202060543a3a4475737452656d6f76616c3a3a6f6e5f756e62616c616e6365646020616e642060543a3a4f6e4672656542616c616e63655a65726f3a3a6f6e5f667265655f62616c616e63655f7a65726f602e2020202d20607472616e736665725f6b6565705f616c6976656020776f726b73207468652073616d652077617920617320607472616e73666572602c206275742068617320616e206164646974696f6e616c2020202020636865636b207468617420746865207472616e736665722077696c6c206e6f74206b696c6c20746865206f726967696e206163636f756e742e00000000c91a10000d0000000000000000000000dc3110000a000000000000000000000000000000000000000000000000000000000000005c8f11008c3210000000000000000000e831100001000000000000000100000000000000071d10000700000001010000000000000f5c11000c00000000000000f03110002b000000000000000000000000000000000000005c8f11001c32100000000000000000002c32100001000000000000000000000000000000d61a10000b00000001010000000000000f5c11000c00000000000000dc3110000a000000000000000000000000000000000000005c8f11008c3210000000000000000000343210000b000000000000000100000000000000e11a10000f00000001010000000000000f5c11000c00000000000000dc3110000a000000000000000000000000000000000000005c8f11008c32100000000000000000009c3210000b000000000000000100000000000000f01a10000500000001010000000000000f5c11000c00000000000000f43210002c000000000000000000000000000000000000005c8f110020331000000000000000000030331000010000000000000001000000543a3a42616c616e636500006d3810002600000056657374696e675363686564756c653c543a3a42616c616e63652c20543a3a426c6f636b4e756d6265723e003b0000000000000001000000520000003738100036000000b7351000270000005c8f110000000000de351000500000002e3610005d0000008b36100055000000e03610004f0000002f3710005100000080371000150000005c8f110000000000953710005d000000f2371000450000003b000000000000000100000054000000663310005d000000c3331000270000005c8f110000000000ea3310005b00000045341000490000005c8f1100000000008e3410005d000000eb3410002d0000005c8f110000000000183510005900000071351000460000005665633c42616c616e63654c6f636b3c543a3a42616c616e63652c20543a3a426c6f636b4e756d6265723e3e3b000000000000000100000055000000383310002e00000020416e79206c6971756964697479206c6f636b73206f6e20736f6d65206163636f756e742062616c616e6365732e2054686520616d6f756e74206f66207468652062616c616e6365206f66206120676976656e206163636f756e7420746861742069732065787465726e616c6c792072657365727665643b20746869732063616e207374696c6c2067657420736c61736865642c20627574206765747320736c6173686564206c617374206f6620616c6c2e20546869732062616c616e63652069732061202772657365727665272062616c616e63652074686174206f746865722073756273797374656d732075736520696e206f7264657220746f2073657420617369646520746f6b656e73207468617420617265207374696c6c20276f776e65642720627920746865206163636f756e7420686f6c6465722c20627574207768696368206172652073757370656e6461626c652e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e2074686973202772657365727665206163636f756e74272069732064656c657465643a207370656369666963616c6c792c2060526573657276656442616c616e6365602e20606672616d655f73797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c6574656420696620604672656542616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e2920546865202766726565272062616c616e6365206f66206120676976656e206163636f756e742e205468697320697320746865206f6e6c792062616c616e63652074686174206d61747465727320696e207465726d73206f66206d6f7374206f7065726174696f6e73206f6e20746f6b656e732e20497420616c6f6e65206973207573656420746f2064657465726d696e65207468652062616c616e6365207768656e20696e2074686520636f6e747261637420657865637574696f6e20656e7669726f6e6d656e742e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e20746865202763757272656e74206163636f756e74272069732064656c657465643a207370656369666963616c6c7920604672656542616c616e6365602e20467572746865722c2074686520604f6e4672656542616c616e63655a65726f602063616c6c6261636b20697320696e766f6b65642c20676976696e672061206368616e636520746f2065787465726e616c206d6f64756c657320746f20636c65616e2075702064617461206173736f6369617465642077697468207468652064656c65746564206163636f756e742e20606672616d655f73797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c657465642069662060526573657276656442616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e20496e666f726d6174696f6e20726567617264696e67207468652076657374696e67206f66206120676976656e206163636f756e742e2054686520746f74616c20756e6974732069737375656420696e207468652073797374656d2e00000000003c3910001200000000000000dc3110000a000000000000005c8f110050391000000000000000000060391000010000000000000000000000b81111000b00000000000000dc3110000a000000000000005c8f1100683910000000000000000000c4111100010000000000000000000000cc1111000b00000000000000dc3110000a000000000000005c8f1100683910000000000000000000d811110001000000000000004578697374656e7469616c4465706f73697400003b00000000000000010000005600000078391000350000003b00000000000000010000005700000020546865206d696e696d756d20616d6f756e7420726571756972656420746f206b65657020616e206163636f756e74206f70656e2e00000000000000b71c1000070000000101000000000000b83a10000d00000000000000c53a100034000000000000000000000000000000000000005c8f1100fc3a100000000000000000000c3b100001000000000000000000000000000000143b1000160000000201010000000000cf6e11000400000000000000d36e11000e000000000000002a3b100012000000000000005c8f11003c3b100000000000000000004c3b100001000000000000000100000000000000c56d1100120000000101000000000000cf6e11000400000000000000e960110007000000000000000000000000000000000000005c8f1100543b10000000000000000000643b10000600000000000000010000005265706f727449644f663c543e4f6666656e636544657461696c733c543a3a4163636f756e7449642c20543a3a4964656e74696669636174696f6e5475706c653e0000003b000000000000000100000052000000fd3c100052000000436f6e63757272656e745265706f727473496e6465785665633c5265706f727449644f663c543e3e3b000000000000000100000055000000b33c10004a0000003b000000000000000100000058000000943b1000440000005c8f110000000000d83b10002f0000005c8f110000000000073c100052000000593c10005a00000020456e756d65726174657320616c6c207265706f727473206f662061206b696e6420616c6f6e672077697468207468652074696d6520746865792068617070656e65642e20416c6c207265706f7274732061726520736f72746564206279207468652074696d65206f66206f6666656e63652e204e6f74652074686174207468652061637475616c2074797065206f662074686973206d617070696e6720697320605665633c75383e602c207468697320697320626563617573652076616c756573206f6620646966666572656e7420747970657320617265206e6f7420737570706f7274656420617420746865206d6f6d656e7420736f2077652061726520646f696e6720746865206d616e75616c2073657269616c697a6174696f6e2e204120766563746f72206f66207265706f727473206f66207468652073616d65206b696e6420746861742068617070656e6564206174207468652073616d652074696d6520736c6f742e20546865207072696d61727920737472756374757265207468617420686f6c647320616c6c206f6666656e6365207265636f726473206b65796564206279207265706f7274206964656e746966696572732e696d2d6f6e6c696e653a6f66666c696e676f74206f766572666c6f7720616674657220616464696e6720612066656520746f2076616c75657472616e7366657220776f756c64206b696c6c206163636f756e74486561644f66566f7465734f66566f7465734f663a73657373696f6e3a6b6579734e6578744b6579734b65794f776e6572416c69766520636f6e7472616374206f7220746f6d6273746f6e6520616c7265616479206578697374735374616b654f6600000000e03e10000700000000000000e83e1000010000000000000000000000f03e1000020000000000000000000000003f100009000000000000005c8f11000000000000000000000000000c3f1000010000000000000000000000143f10000c000000000000008c521100010000000000000000000000203f1000020000000000000000000000303f10000f000000000000008c521100010000000000000000000000403f1000010000000000000000000000483f10000d00000000000000583f1000030000000000000000000000703f100002000000000000004e65775465726d005d41100019000000b7401000550000000c41100051000000456d7074795465726d00000081401000360000004d656d6265724b69636b65642340100051000000744010000d0000004d656d62657252656e6f756e63656400fb3f100028000000566f7465725265706f72746564000000e252110009000000e2521100090000000353110004000000803f100058000000d83f100023000000204120766f7465722028666972737420656c656d656e742920776173207265706f72746564202862797420746865207365636f6e6420656c656d656e742920776974682074686520746865207265706f7274206265696e67207375636365737366756c206f72206e6f742028746869726420656c656d656e74292e2041206d656d626572206861732072656e6f756e6365642074686569722063616e6469646163792e2041206d656d62657220686173206265656e2072656d6f7665642e20546869732073686f756c6420616c7761797320626520666f6c6c6f7765642062792065697468657220604e65775465726d60206f742060456d7074795465726d602e204e6f20286f72206e6f7420656e6f756768292063616e64696461746573206578697374656420666f72207468697320726f756e642e2041206e6577207465726d2077697468206e6577206d656d626572732e205468697320696e64696361746573207468617420656e6f7567682063616e6469646174657320657869737465642c206e6f74207468617420656e6f756768206861766520686173206265656e20656c65637465642e2054686520696e6e65722076616c7565206d757374206265206578616d696e656420666f72207468697320707572706f73652e5665633c284163636f756e7449642c2042616c616e6365293e00003b0000000000000001000000590000003b00000000000000010000005a00000043616e6469646174657352756e6e65727355705175657565644b657973636f6e74726163742073756273797374656d20726573756c74696e6720696e20706f73697469766520696d62616c616e636521000000001442100008000000000000001c4210000200000000000000000000004c4210000a000000000000007365745f6b65797300000000c59b10000400000000000000a54310000700000000000000ac4310000500000000000000e9601100070000009c42100039000000d5421000480000001d431000310000005c8f1100000000004e431000350000005c8f1100000000002d5a11000b0000008343100022000000df2e110016000000a65a11000c0000002053657473207468652073657373696f6e206b6579287329206f66207468652066756e6374696f6e2063616c6c657220746f20606b6579602e20416c6c6f777320616e206163636f756e7420746f20736574206974732073657373696f6e206b6579207072696f7220746f206265636f6d696e6720612076616c696461746f722e205468697320646f65736e27742074616b652065666665637420756e74696c20746865206e6578742073657373696f6e2e20546865206469737061746368206f726967696e206f6620746869732066756e6374696f6e206d757374206265207369676e65642e202d204f286c6f67206e2920696e206e756d626572206f66206163636f756e74732e543a3a4b65797370726f6f660000000000000049bc10000a00000000000000000000001c46100013000000000000000000000000000000000000000000000000000000000000005c8f1100f859100000000000000000003046100001000000000000000100000000000000f36e11000c0000000000000000000000e76f11000c000000000000000000000000000000000000000000000000000000000000005c8f1100c059100000000000000000003846100001000000000000000100000000000000ff6e11000d00000000000000000000000353110004000000000000000000000000000000000000000000000000000000000000005c8f11004046100000000000000000005046100002000000000000000100000000000000ab4110000a0000000000000000000000604610001e000000000000000000000000000000000000000000000000000000000000005c8f110080461000000000000000000090461000020000000000000001000000000000000c6f11001200000000000000000000005bc9100008000000000000000000000000000000000000000000000000000000000000005c8f1100f85910000000000000000000a046100003000000000000000100000000000000c33d1000080000000204010000000000e96011000700000000000000106111000e00000000000000a543100007000000000000005c8f1100b84610000000000000000000c846100004000000000000000000000000000000cb3d1000080000000204010000000000e96011000700000000000000e84610001400000000000000106111000e000000000000005c8f1100fc46100000000000000000000c4710000400000000000000000000005665633c543a3a56616c696461746f7249643e00d34910001f000000b54910001e0000003b0000000000000001000000520000003e4910004e0000008c491000290000005665633c28543a3a56616c696461746f7249642c20543a3a4b657973293e00003b000000000000000100000055000000b74810004f00000006491000380000004a481000200000005c8f1100000000006a4810004d0000003b00000000000000010000005200000023481000270000005c8f1100000000007547100056000000cb47100058000000284b65795479706549642c205665633c75383e293b0000000000000001000000520000002c471000490000005c8f1100000000007547100056000000cb4710005800000020546865206f776e6572206f662061206b65792e20546865207365636f6e64206b65792069732074686520604b657954797065496460202b2074686520656e636f646564206b65792e20546865206669727374206b657920697320616c77617973206044454455505f4b45595f5052454649586020746f206861766520616c6c20746865206461746120696e207468652073616d65206272616e6368206f662074686520747269652e20486176696e6720616c6c206461746120696e207468652073616d65206272616e63682073686f756c642070726576656e7420736c6f77696e6720646f776e206f7468657220717565726965732e20546865206e6578742073657373696f6e206b65797320666f7220612076616c696461746f722e20496e6469636573206f662064697361626c65642076616c696461746f72732e205468652073657420697320636c6561726564207768656e20606f6e5f73657373696f6e5f656e64696e67602072657475726e732061206e657720736574206f66206964656e7469746965732e2054686520717565756564206b65797320666f7220746865206e6578742073657373696f6e2e205768656e20746865206e6578742073657373696f6e20626567696e732c207468657365206b6579732077696c6c206265207573656420746f2064657465726d696e65207468652076616c696461746f7227732073657373696f6e206b6579732e20547275652069662074686520756e6465726c79696e672065636f6e6f6d6963206964656e746974696573206f7220776569676874696e6720626568696e64207468652076616c696461746f727320686173206368616e67656420696e20746865207175657565642076616c696461746f72207365742e2043757272656e7420696e646578206f66207468652073657373696f6e2e205468652063757272656e7420736574206f662076616c696461746f72732e0000000000002c4a100010000000000000003c4a100005000000000000005c8f1100444a10000000000000000000544a1000020000000000000044454455505f4b45595f505245464958265b75385d0000003b00000000000000010000005b000000644a100059000000bd4a10000d0000002055736564206173206669727374206b657920666f7220604e6578744b6579736020616e6420604b65794f776e65726020746f2070757420616c6c20746865206461746120696e746f207468652073616d65206272616e6368206f662074686520747269652e000000000000802711000400000000000000d44b1000020000000000000000000000044c10000f00000000000000000000007c4c10000c000000000000005c8f1100000000000000000000000000884c1000070000000000000000000000c04c10001400000000000000f0f71000010000000000000000000000d44c10000d00000000000000000000003c4d100010000000000000005c8f11000000000000000000000000004c4d10000d0000000000000000000000b44d100012000000000000005c8f1100000000000000000000000000c84d1000090000000000000000000000487210000d00000000000000104e1000010000000000000000000000284e10000d00000000000000000000007657100005000000000000000c3d110011000000000000001436110005000000000000001936110015000000dc551000410000005c8f1100000000001d561000140000003156100012000000435610002b0000005c8f1100000000006e56100057000000c5561000570000001c571000280000005c8f1100000000002d5a11000b000000eb4f10000b000000d05510000c0000004457100032000000a65a11000c00000072656d6f76655f766f74657288551000480000005c8f1100000000002d5a11000b000000eb4f10000b000000d05510000c000000cf5310000d000000a65a11000c0000007265706f72745f646566756e63745f766f746572dc5310005700000033541000570000008a541000170000005c8f110000000000a154100022000000c354100053000000165510002d0000005c8f1100000000002d5a11000b000000eb4f10000b0000004355100045000000cf5310000d000000a65a11000c0000007375626d69745f63616e6469646163798d5210001e0000005c8f110000000000ab52100019000000c45210003b000000ff5210004b0000004a531000550000009f5310000d0000005c8f1100000000002d5a11000b000000eb4f10000b000000ac53100023000000cf5310000d000000a65a11000c00000072656e6f756e63655f63616e6469646163790000235010005400000077501000100000008750100050000000d75010003d00000014511000560000006a511000210000008b51100053000000de51100056000000345210005900000000000000b25a11000300000000000000b55a110023000000904e100057000000e74e1000200000005c8f110000000000074f1000560000005d4f10003d0000005c8f1100000000009a4f1000510000005c8f1100000000002d5a11000b000000eb4f10000b000000f64f1000160000000c50100017000000a65a11000c0000002052656d6f7665206120706172746963756c6172206d656d6265722066726f6d20746865207365742e20546869732069732065666665637469766520696d6d6564696174656c7920616e642074686520626f6e64206f6620746865206f7574676f696e67206d656d62657220697320736c61736865642e20496620612072756e6e65722d757020697320617661696c61626c652c207468656e2074686520626573742072756e6e65722d75702077696c6c2062652072656d6f76656420616e64207265706c6163657320746865206f7574676f696e67206d656d6265722e204f74686572776973652c2061206e65772070687261676d656e20726f756e6420697320737461727465642e204e6f74652074686174207468697320646f6573206e6f7420616666656374207468652064657369676e6174656420626c6f636b206e756d626572206f6620746865206e65787420656c656374696f6e2e20232323232053746174652052656164733a204f28646f5f70687261676d656e29205772697465733a204f28646f5f70687261676d656e292052656e6f756e6365206f6e65277320696e74656e74696f6e20746f20626520612063616e64696461746520666f7220746865206e65787420656c656374696f6e20726f756e642e203320706f74656e7469616c206f7574636f6d65732065786973743a202d20606f726967696e6020697320612063616e64696461746520616e64206e6f7420656c656374656420696e20616e79207365742e20496e207468697320636173652c2074686520626f6e64206973202020756e72657365727665642c2072657475726e656420616e64206f726967696e2069732072656d6f76656420617320612063616e6469646174652e202d20606f726967696e6020697320612063757272656e742072756e6e65722075702e20496e207468697320636173652c2074686520626f6e6420697320756e72657365727665642c2072657475726e656420616e642020206f726967696e2069732072656d6f76656420617320612072756e6e65722e202d20606f726967696e6020697320612063757272656e74206d656d6265722e20496e207468697320636173652c2074686520626f6e6420697320756e726573657276656420616e64206f726967696e20697320202072656d6f7665642061732061206d656d6265722c20636f6e73657175656e746c79206e6f74206265696e6720612063616e64696461746520666f7220746865206e65787420726f756e6420616e796d6f72652e20202053696d696c617220746f205b6072656d6f76655f766f746572605d2c206966207265706c6163656d656e742072756e6e657273206578697374732c20746865792061726520696d6d6564696174656c7920757365642e205375626d6974206f6e6573656c6620666f722063616e6469646163792e20412063616e6469646174652077696c6c206569746865723a2020202d204c6f73652061742074686520656e64206f6620746865207465726d20616e6420666f7266656974207468656972206465706f7369742e2020202d2057696e20616e64206265636f6d652061206d656d6265722e204d656d626572732077696c6c206576656e7475616c6c7920676574207468656972207374617368206261636b2e2020202d204265636f6d6520612072756e6e65722d75702e2052756e6e6572732d75707320617265207265736572766564206d656d6265727320696e2063617365206f6e65206765747320666f72636566756c6c79202020202072656d6f7665642e2052656164733a204f284c6f674e2920476976656e204e2063616e646964617465732e205772697465733a204f283129205265706f727420607461726765746020666f72206265696e6720616e20646566756e637420766f7465722e20496e2063617365206f6620612076616c6964207265706f72742c20746865207265706f727465722069732072657761726465642062792074686520626f6e6420616d6f756e74206f662060746172676574602e204f74686572776973652c20746865207265706f7274657220697473656c662069732072656d6f76656420616e6420746865697220626f6e6420697320736c61736865642e204120646566756e637420766f74657220697320646566696e656420746f2062653a2020202d206120766f7465722077686f73652063757272656e74207375626d697474656420766f7465732061726520616c6c20696e76616c69642e20692e652e20616c6c206f66207468656d20617265206e6f20202020206c6f6e67657220612063616e646964617465206e6f7220616e20616374697665206d656d6265722e2052656164733a204f284e4c6f674d2920676976656e204d2063757272656e742063616e6469646174657320616e64204e20766f74657320666f722060746172676574602e2052656d6f766520606f726967696e60206173206120766f7465722e20546869732072656d6f76657320746865206c6f636b20616e642072657475726e732074686520626f6e642e2052656164733a204f28312920566f746520666f72206120736574206f662063616e6469646174657320666f7220746865207570636f6d696e6720726f756e64206f6620656c656374696f6e2e205468652060766f746573602073686f756c643a2020202d206e6f7420626520656d7074792e2020202d206265206c657373207468616e20746865206e756d626572206f662063616e646964617465732e2055706f6e20766f74696e672c206076616c75656020756e697473206f66206077686f6027732062616c616e6365206973206c6f636b656420616e64206120626f6e6420616d6f756e742069732072657365727665642e2049742069732074686520726573706f6e736962696c697479206f66207468652063616c6c657220746f206e6f7420706c61636520616c6c206f662074686569722062616c616e636520696e746f20746865206c6f636b20616e64206b65657020736f6d6520666f722066757274686572207472616e73616374696f6e732e205772697465733a204f28562920676976656e2060566020766f7465732e205620697320626f756e6465642062792031362e766f7465730000000000eab210000700000000000000000000008c59100021000000000000000000000000000000000000000000000000000000000000005c8f1100f85910000000000000000000b059100001000000000000000100000000000000a24110000900000000000000000000008c59100021000000000000000000000000000000000000000000000000000000000000005c8f1100f85910000000000000000000b859100001000000000000000100000000000000756b11000e00000000000000000000001e61110003000000000000000000000000000000000000000000000000000000000000005c8f1100c05910000000000000000000d059100001000000000000000100000000000000af3d10000700000001010100000000000f5c11000c000000000000000c3d110011000000000000000000000000000000000000005c8f1100f85910000000000000000000d859100001000000000000000100000000000000fd3d10000700000001010000000000000f5c11000c00000000000000824711000c000000000000000000000000000000000000005c8f1100e05910000000000000000000f059100001000000000000000100000000000000984110000a00000000000000000000000c3d110011000000000000000000000000000000000000000000000000000000000000005c8f1100f85910000000000000000000085a10000200000000000000010000005665633c28543a3a4163636f756e7449642c2042616c616e63654f663c543e293e000000ac5b10003c0000005a5b1000520000003b00000000000000010000005c0000000a5b100050000000ca5a1000400000003b000000000000000100000054000000b15a1000190000003b000000000000000100000055000000185a100059000000715a100040000000205468652070726573656e742063616e646964617465206c6973742e20536f72746564206261736564206f6e206163636f756e742069642e20412063757272656e74206d656d6265722063616e206e6576657220656e746572207468697320766563746f7220616e6420697320616c7761797320696d706c696369746c7920617373756d656420746f20626520612063616e6469646174652e204c6f636b6564207374616b65206f66206120766f7465722e20566f746573206f66206120706172746963756c617220766f7465722c20776974682074686520726f756e6420696e646578206f662074686520766f7465732e2054686520746f74616c206e756d626572206f6620766f746520726f756e6473207468617420686176652068617070656e65642c206578636c7564696e6720746865207570636f6d696e67206f6e652e205468652063757272656e742072756e6e6572735f75702e20536f72746564206261736564206f6e206c6f7720746f2068696768206d657269742028776f72736520746f20626573742072756e6e6572292e205468652063757272656e7420656c6563746564206d656d626572736869702e20536f72746564206261736564206f6e206163636f756e742069642e00000000005d10000d00000000000000824711000c000000000000005c8f1100105d100000000000000000005c8f1100000000000000000000000000205d10000a00000000000000824711000c000000000000005c8f11002c5d100000000000000000005c8f11000000000000000000000000003c5d10000e000000000000001e61110003000000000000005c8f11004c5d100000000000000000005c8f11000000000000000000000000005c5d100010000000000000001e61110003000000000000005c8f11006c5d100000000000000000005c8f11000000000000000000000000007c5d10000c000000000000009c6011000e000000000000005c8f1100885d100000000000000000005c8f1100000000000000000043616e646964616379426f6e640000003b00000000000000010000005d000000566f74696e67426f6e6400003b000000000000000100000056000000446573697265644d656d6265727300003b00000000000000010000005e0000004465736972656452756e6e65727355703b00000000000000010000005f0000005465726d4475726174696f6e3b0000000000000001000000600000006e6f206173736f6369617465642076616c696461746f7220494420666f72206163636f756e742e72656769737465726564206475706c6963617465206b657963616e6e6f7420766f7465207768656e206e6f2063616e64696461746573206f72206d656d6265727320657869737463616e6e6f7420766f7465206d6f7265207468616e2063616e6469646174657363616e6e6f7420766f7465206d6f7265207468616e206d6178696d756d20616c6c6f7765646d75737420766f746520666f72206174206c65617374206f6e652063616e6469646174652e63616e6e6f7420766f74652077697468207374616b65206c657373207468616e206d696e696d756d2062616c616e6365766f7465722063616e206e6f742070617920766f74696e6720626f6e6463616e6e6f74207265706f72742073656c667265706f72746572206d757374206265206120766f7465726475706c69636174652063616e646964617465207375626d697373696f6e6d656d6265722063616e6e6f742072652d7375626d69742063616e64696461637972756e6e65722063616e6e6f742072652d7375626d69742063616e64696461637963616e64696461746520646f6573206e6f74206861766520656e6f7567682066756e64736f726967696e206973206e6f7420612063616e6469646174652c206d656d626572206f7220612072756e6e65722e6d757374206265206120766f74657200000000441d11000800000000000000b0601000010000000000000000000000b8601000010000000000000000000000c06010000800000000000000c8601000010000000000000000000000d0601000010000000000000000000000d86010000700000000000000e0601000030000000000000000000000f8601000010000000000000000000000006110000500000000000000c860100001000000000000000000000008611000010000000000000000000000106110000800000000000000c860100001000000000000000000000018611000010000000000000000000000206110000700000000000000c8601000010000000000000000000000286110000100000000000000a8b210000d000000196210000e0000005370656e64696e679b1f110007000000df6110003a0000004177617264656400a8b210000d0000009b1f110007000000e252110009000000bf611000200000004275726e740000009c61100023000000526f6c6c6f766572506110004c0000004465706f73697400306110002000000020536f6d652066756e64732068617665206265656e206465706f73697465642e205370656e64696e67206861732066696e69736865643b20746869732069732074686520616d6f756e74207468617420726f6c6c73206f76657220756e74696c206e657874207370656e642e20536f6d65206f66206f75722066756e64732068617665206265656e206275726e742e20536f6d652066756e64732068617665206265656e20616c6c6f63617465642e205765206861766520656e6465642061207370656e6420706572696f6420616e642077696c6c206e6f7720616c6c6f636174652066756e64732e204e65772070726f706f73616c2e6f766572666c6f77206d756c7469706c79696e6720676173206c696d6974206279207072696365656e74697265206e65775f7365742077617320676976656e20746f206275696c645f737570706f72745f6d61703b20656e20656e747279206d757374206265206372656174656420666f722065616368206974656d3b207165640000000000000000617474656d707420746f20646976696465206279207a65726f496e636f6e73697374656e74207374617465202d20636f756c646e277420736574746c6520696d62616c616e636520666f722066756e6473207370656e7420627920747265617375727952616e646f6d4d6174657269616c486973746f726963616c53657373696f6e730000000000b86310000d00000000000000c8631000020000000000000000000000f8631000090000000000000000000000406410000f000000000000005064100001000000000000000000000068641000070000000000000000000000a0641000100000000000000050641000010000000000000000000000b0641000080000000000000070726f706f73655f7370656e64000000000000001436110005000000000000001936110015000000000000008e6610000b00000000000000b55a110023000000bc6510004b000000076610004d00000054661000150000005c8f1100000000002d5a11000b000000385a110008000000405a1100190000006966100025000000a65a11000c00000072656a6563745f70726f706f73616c0000000000b16510000b00000000000000c9b6100016000000726510003f0000005c8f1100000000002d5a11000b000000385a110008000000405a110019000000312f110010000000a65a11000c000000617070726f76655f70726f706f73616cf064100057000000476510002b0000005c8f1100000000002d5a11000b000000385a110008000000405a1100190000004d5b110011000000a65a11000c00000020417070726f766520612070726f706f73616c2e2041742061206c617465722074696d652c207468652070726f706f73616c2077696c6c20626520616c6c6f636174656420746f207468652062656e656669636961727920616e6420746865206f726967696e616c206465706f7369742077696c6c2062652072657475726e65642e2052656a65637420612070726f706f736564207370656e642e20546865206f726967696e616c206465706f7369742077696c6c20626520736c61736865642e70726f706f73616c5f69642050757420666f727761726420612073756767657374696f6e20666f72207370656e64696e672e2041206465706f7369742070726f706f7274696f6e616c20746f207468652076616c756520697320726573657276656420616e6420736c6173686564206966207468652070726f706f73616c2069732072656a65637465642e2049742069732072657475726e6564206f6e6365207468652070726f706f73616c20697320617761726465642e202d204f6e65204442206368616e67652c206f6e6520657874726120444220656e7472792e62656e656669636961727900000000000000ac7411000d0000000000000000000000a8b210000d000000000000000000000000000000000000000000000000000000000000005c8f1100a46710000000000000000000b467100001000000000000000100000000000000e1b21000090000000101000000000000a8b210000d00000000000000bc67100024000000000000000000000000000000000000005c8f1100e06710000000000000000000f067100001000000000000000000000000000000b9741100090000000000000000000000f867100012000000000000000000000000000000000000000000000000000000000000005c8f1100cc6c100000000000000000000c6810000100000000000000010000003b00000000000000010000005c000000716810002900000050726f706f73616c3c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3b000000000000000100000052000000526810001f0000005665633c50726f706f73616c496e6465783e0000146810003e0000002050726f706f73616c20696e646963657320746861742068617665206265656e20617070726f76656420627574206e6f742079657420617761726465642e2050726f706f73616c7320746861742068617665206265656e206d6164652e204e756d626572206f662070726f706f73616c7320746861742068617665206265656e206d6164652e0000000000007c6910000c000000000000008869100007000000000000005c8f1100906910000000000000000000a0691000020000000000000000000000b06910001300000000000000824711000c000000000000005c8f1100c46910000000000000000000d4691000010000000000000000000000dc6910000b000000000000009c6011000e000000000000005c8f1100e86910000000000000000000f8691000010000000000000000000000006a100004000000000000008869100007000000000000005c8f1100046a10000000000000000000146a1000010000000000000050726f706f73616c426f6e645065726d696c6c003b000000000000000100000061000000d46a100055000000296b10004400000050726f706f73616c426f6e644d696e696d756d003b000000000000000100000056000000826a1000520000005370656e64506572696f64003b000000000000000100000062000000606a1000220000004275726e3b0000000000000001000000630000001c6a1000440000002050657263656e74616765206f662073706172652066756e64732028696620616e7929207468617420617265206275726e7420706572207370656e6420706572696f642e20506572696f64206265747765656e2073756363657373697665207370656e64732e204d696e696d756d20616d6f756e74206f662066756e647320746861742073686f756c6420626520706c6163656420696e2061206465706f73697420666f72206d616b696e6720612070726f706f73616c2e204672616374696f6e206f6620612070726f706f73616c27732076616c756520746861742073686f756c6420626520626f6e64656420696e206f7264657220746f20706c616365207468652070726f706f73616c2e20416e2061636365707465642070726f706f73616c2067657473207468657365206261636b2e20412072656a65637465642070726f706f73616c20646f6573206e6f742e0000000000000093741100110000000000000000000000c86b10000a000000000000000000000000000000000000000000000000000000000000005c8f1100d46b100000000000000000005c8f11000000000000000000010000004d756c7469706c69657200003b00000000000000010000005300000000000000e01111001200000000000000824711000c000000000000005c8f1100546c10000000000000000000f4111100010000000000000000000000fc1111001200000000000000824711000c000000000000005c8f1100646c100000000000000000002012110001000000000000003b0000000000000001000000570000003b00000000000000010000006400000000000000136310000e000000000000000000000067b810000c000000000000000000000000000000000000000000000000000000000000005c8f1100cc6c10000000000000000000dc6c10000300000000000000010000003b000000000000000100000055000000f46c1000580000004c6d100058000000a46d10001100000020536572696573206f6620626c6f636b20686561646572732066726f6d20746865206c61737420383120626c6f636b73207468617420616374732061732072616e646f6d2073656564206d6174657269616c2e205468697320697320617272616e67656420617320612072696e672062756666657220776974682060626c6f636b5f6e756d626572202520383160206265696e672074686520696e64657820696e746f20746865206056656360206f6620746865206f6c6465737420686173682e00000000000000c06e10000b000000000000005c8f1100000000000000000000000000cc6e1000010000000000000000000000d46e10000d000000000000005c8f1100000000000000000000000000e46e1000010000000000000000000000ec6e10000e000000000000005c8f1100000000000000000000000000fc6e1000010000000000000000000000046f10000c000000000000005c8f1100000000000000000000000000106f1000010000000000000000000000805211000a000000000000005c8f1100000000000000000000000000186f1000010000000000000000000000206f10000500000000000000286f1000010000000000000000000000306f100001000000000000004d656d6265724164646564005d701000390000004d656d62657252656d6f766564000000227010003b0000004d656d62657273537761707065640000eb6f1000370000004d656d626572735265736574a56f100046000000836f10002200000044756d6d79000000546f10002f000000386f10001c000000205068616e746f6d206d656d6265722c206e6576657220757365642e73705f7374643a3a6d61726b65723a3a5068616e746f6d446174613c284163636f756e7449642c204576656e74293e204f6e65206f6620746865206d656d6265727327206b657973206368616e6765642e20546865206d656d62657273686970207761732072657365743b2073656520746865207472616e73616374696f6e20666f722077686f20746865206e6577207365742069732e2054776f206d656d62657273207765726520737761707065643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732072656d6f7665643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732061646465643b2073656520746865207472616e73616374696f6e20666f722077686f2e50726576696f7573206d617463682061726d206d61746368657320616e7974696e67206c657373207468616e20325e33303b20716564000000000000000000000000e07010003d000000736869667465642073756666696369656e74206269747320726967687420746f206c656164206f6e6c79206c656164696e67207a65726f733b2071656400000000000000000000000000000000000000000000000c7210000a000000000000001872100001000000000000000000000030721000030000000000000000000000487210000d000000000000001872100001000000000000000000000058721000030000000000000000000000707210000b000000000000007c721000020000000000000000000000ac721000030000000000000000000000c47210000d00000000000000d4721000010000000000000000000000ec7210000400000000000000000000000c7310000a00000000000000187310000100000000000000000000003073100003000000000000006164645f6d656d626572000000000000b25a110003000000000000000f5c11000c0000001d7510001f0000005c8f1100000000003c7510002d00000072656d6f76655f6d656d626572000000c9741000240000005c8f110000000000ed74100030000000737761705f6d656d6265720000000000c074100006000000000000000f5c11000c00000000000000c674100003000000000000000f5c11000c00000062741000300000005c8f110000000000927410002e00000072657365745f6d656d62657273000000000000005b74100007000000000000000c3d110011000000bb73100056000000117410001b0000005c8f1100000000002c7410002f0000006368616e67655f6b65790000000000005e5b110003000000000000000f5c11000c00000048731000360000005c8f1100000000007e7310003d0000002053776170206f7574207468652073656e64696e67206d656d62657220666f7220736f6d65206f74686572206b657920606e6577602e204d6179206f6e6c792062652063616c6c65642066726f6d20605369676e656460206f726967696e206f6620612063757272656e74206d656d6265722e204368616e676520746865206d656d6265727368697020746f2061206e6577207365742c20646973726567617264696e6720746865206578697374696e67206d656d626572736869702e204265206e69636520616e64207061737320606d656d6265727360207072652d736f727465642e204d6179206f6e6c792062652063616c6c65642066726f6d206052657365744f726967696e60206f7220726f6f742e6d656d626572732053776170206f7574206f6e65206d656d626572206072656d6f76656020666f7220616e6f746865722060616464602e204d6179206f6e6c792062652063616c6c65642066726f6d2060537761704f726967696e60206f7220726f6f742e72656d6f76656164642052656d6f76652061206d656d626572206077686f602066726f6d20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d206052656d6f76654f726967696e60206f7220726f6f742e204164642061206d656d626572206077686f6020746f20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d20604164644f726967696e60206f7220726f6f742e496e7374616e6365314d656d6265727368697000000000eab210000700000000000000000000000c3d110011000000000000000000000000000000000000000000000000000000000000005c8f1100d47510000000000000000000e47510000100000000000000010000003b000000000000000100000055000000ec75100032000000205468652063757272656e74206d656d626572736869702c2073746f72656420617320616e206f726465726564205665632e616c72656164792061206d656d6265726e6f742061206d656d626572417574686f723b000000000000000100000065000000660000006700000068000000690000006a000000546f6f206d616e7920756e636c65737375627374726174652d6e6f6465000000df6acb689907609b0200000037e397fc7c91f5e40100000040fe3ad401f8959a04000000d2bc9897eed08f1501000000f78b278be53f454c01000000ed99c5acb25eedf502000000cbca25e39f14238701000000687ad44ad37f03c201000000bc9d89904f5b923f0100000068b66ba122c93fa70100000037c8bb1350a9a2a801000000ab3c0572291feb8b010000006772616e62616265696d6f6e617564690000000040787d010065cd1d00e1f505d85aae1ec0542205b0508f1f38e4750488467020d853e903603c5121d0bf760338323222a8591903402013236039cd02480ef423a82a8f0268f8d42470955c02b8dab525c05a3302d8c4962648bd1102e0b27727a855f601e8a05828e8fedf0180773929c0cacd01586d1a2af8f1be019053fb2a50d8b201d00edc2be0fca80138edbc2c48f2a001e06d9d2d80669a01c80d7e2e500f9501c0575e2f08b6900140323f30e0278d0148202031b0418a0108a3ff3120e8870120bedf32f0fb85013856c03398698401f0fda03478218301b8d87f35d8178201d8c26036183d8101b8223e37508d800188d21c38c8fc7f0168b5f93898877f01a829d139d8297f0120d6ab3ab8db7e0168ae803b389d7e0100ca9a3b68957e01000000001198100006000000000000006b000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000006d0000000000000000000000000000006e0000000000000000000000000000006f000000000000000000000000000000d88210000700000002000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000710000000000000000000000000000006e0000000000000000000000000000006e0000000000000000000000000000003a631100040000000000000072000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000200000000000000000000000000000000000000730000000000000000000000000000006e00000000000000000000000000000079741100090000000000000074000000000000000000000000000000000000000000000000000000000000007500000000000000000000000200000000000000000000000000000000000000760000000000000000000000000000006e000000000000000000000000000000246311000a00000000000000770000000000000000000000000000000000000000000000000000000000000078000000000000000000000002000000000000000000000000000000000000006e0000000000000000000000000000006e000000000000000000000000000000b5b21000070000000000000079000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000007a0000000000000000000000000000006e0000000000000000000000000000006e0000000000000000000000000000008b74110008000000000000007b000000000000000000000000000000000000000000000000000000000000007c0000000000000000000000000000007d0000000000000000000000000000007e0000000000000000000000000000006e000000000000000000000000000000df82100012000000000000007f000000000000000000000000000000000000000000000000000000020000000000000000000000000000000200000000000000000000000000000000000000800000000000000000000000000000006e000000000000000000000000000000167011000700000000000000810000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000830000000000000000000000000000008400000000000000000000000000000085000000000000000000000000000000ec6e1100070000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000088000000000000000000000000000000890000000000000000000000000000006e0000000000000000000000000000003a6b110009000000000000008a000000000000000000000000000000000000000000000000000000000000008b0000000000000000000000000000008c0000000000000000000000000000008d0000000000000000000000000000006e000000000000000000000000000000f182100007000000000000008e000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000900000000000000000000000000000006e0000000000000000000000000000006e000000000000000000000000000000f8821000120000000000000091000000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000900000000000000000000000000000006e0000000000000000000000000000006e0000000000000000000000000000000a831000090000000000000092000000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000094000000000000000000000000000000950000000000000000000000000000006e000000000000000000000000000000138310001300000000000000960000000000000000000000000000000000000000000000000000000000000097000000000000000000000000000000980000000000000000000000000000006e0000000000000000000000000000006e000000000000000000000000000000268310000f00000002000000000000000000000000000000000000000000000000000000000000000000000099000000000000000000000002000000000000000000000000000000000000009a0000000000000000000000000000006e0000000000000000000000000000003583100007000000000000009b000000000000000000000000000000000000000000000000000000000000009c0000000000000000000000000000009d0000000000000000000000000000006e0000000000000000000000000000006e000000000000000000000000000000a474110008000000000000009e000000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000a0000000000000000000000000000000a1000000000000000000000000000000a20000000000000000000000000000003c8310000900000000000000a300000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000000000a5000000000000000000000000000000a60000000000000000000000000000006e000000000000000000000000000000af5b11000400000000000000a700000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000a90000000000000000000000000000006e000000000000000000000000000000aa000000000000000000000000000000a36d11000800000000000000ab00000000000000000000000000000000000000000000000000000000000000ac000000000000000000000000000000ad0000000000000000000000000000006e0000000000000000000000000000006e0000000000000000000000000000000e631100120000000200000000000000000000000000000000000000000000000000000000000000000000006e000000000000000000000002000000000000000000000000000000000000006e0000000000000000000000000000006e000000000000000000000000000000bd6d11000800000000000000ae000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000af0000000000000000000000000000006e0000000000000000000000000000006e000000000000000000000000000000458310001800000000000000b0000000000000000000000000000000000000000000000000000000000000006e000000000000000000000002000000000000000000000000000000000000006e0000000000000000000000000000006e0000000000000000000000000000005d8310000500000000000000b100000000000000000000000000000000000000000000000000000000000000b2000000000000000000000000000000b3000000000000000000000000000000b40000000000000000000000000000006e00000000000000000000005574696c6974795472616e73616374696f6e5061796d656e74436f756e63696c546563686e6963616c436f6d6d6974746565456c656374696f6e73546563686e6963616c4d656d6265727368697046696e616c697479547261636b65724772616e647061436f6e74726163747352616e646f6d6e657373436f6c6c656374697665466c69704e69636b73000000000000908310000a000000000000009c831000010000000000000000000000b483100001000000000000007365745f756e636c6573000000000000d58310000a00000000000000df8310000e000000bc831000190000002050726f76696465206120736574206f6620756e636c65732e6e65775f756e636c65735665633c543a3a4865616465723e00000000000000f8841000060000000000000000000000fe8410003a000000000000000000000000000000000000000000000000000000000000005c8f110038851000000000000000000048851000010000000000000001000000000000003a7610000600000000000000000000000f5c11000c000000000000000000000000000000000000000000000000000000000000005c8f110050851000000000000000000060851000010000000000000000000000000000002e6311000c00000000000000000000000353110004000000000000000000000000000000000000000000000000000000000000005c8f110068851000000000000000000078851000010000000000000001000000556e636c65735665633c556e636c65456e7472794974656d3c543a3a426c6f636b4e756d6265722c20543a3a486173682c20543a3a4163636f756e7449643e3e3b000000000000000100000055000000c8851000070000003b000000000000000100000052000000af851000190000003b000000000000000100000052000000808510002f000000205768657468657220756e636c6573207765726520616c72656164792073657420696e207468697320626c6f636b2e20417574686f72206f662063757272656e7420626c6f636b2e20556e636c657372656163686564206d6178696d756d2064657074682c2063616e6e6f7420696e7374616e7469617465b50000001800000004000000b6000000b7000000b8000000b9000000ba000000bb000000696e73756666696369656e742072656d61696e696e672062616c616e63656e6f7420656e6f7567682067617320746f20706179206261736520696e7374616e7469617465206665656e6f7420656e6f7567682067617320746f20706179207472616e736665722066656562616c616e636520746f6f206c6f7720746f2073656e642076616c756576616c756520746f6f206c6f7720746f20637265617465206163636f756e7464657374696e6174696f6e2062616c616e636520746f6f206869676820746f20726563656976652076616c756572656163686564206d6178696d756d2064657074682c2063616e6e6f74206d616b6520612063616c6c6e6f7420656e6f7567682067617320746f2070617920626173652063616c6c20666565636f6e747261637420686173206265656e2065766963746564636f6e74726163742063616e6e6f742062652064657374726f79656420647572696e672072656375727369766520657865637574696f6e61206e657374656420657865637574696f6e20636f6e74657874206d7573742068617665206120706172656e743b20716564556e636c657320616c72656164792073657420696e20626c6f636b2e756e636c6520616c726561647920696e636c75646564756e636c652069732067656e65736973756e636c6520697320746f6f206869676820696e20636861696e756e636c6520706172656e74206e6f7420696e20636861696e756e636c65206e6f7420726563656e7420656e6f75676820746f20626520696e636c756465646888100048000000bb0100002d0000002f72757374632f373661323532656139653762653933613631666664663333623335333365323461396366343539642f7372632f6c6962636f72652f6f70732f61726974682e7273617474656d707420746f20646976696465206279207a65726f756e636c6573303066696e616c6e756d000000000000003e6311000a0000000000000000000000480b110003000000000000000000000000000000000000000000000000000000000000005c8f11004c8c10000000000000000000f48b100001000000000000000100000000000000486311000b0000000000000000000000fc8b100027000000000000000000000000000000000000000000000000000000000000005c8f1100248c10000000000000000000348c100001000000000000000100000000000000536311000b0000000000000000000000480b110003000000000000000000000000000000000000000000000000000000000000005c8f11004c8c100000000000000000003c8c1000020000000000000001000000000000005e6311000b0000000000000000000000480b110003000000000000000000000000000000000000000000000000000000000000005c8f11004c8c100000000000000000005c8c100001000000000000000100000000000000696311000a0000000000000000000000648c100008000000000000000000000000000000000000000000000000000000000000005c8f1100bc8c100000000000000000006c8c10000a000000000000000100000000000000736311000e0000000000000000000000648c100008000000000000000000000000000000000000000000000000000000000000005c8f1100bc8c10000000000000000000cc8c100001000000000000000100000000000000816311000c00000000000000000000001e61110003000000000000000000000000000000000000000000000000000000000000005c8f1100d48c10000000000000000000e48c1000090000000000000001000000000000008d6311001100000001010000000000001e61110003000000000000002c8d10000d000000000000000000000000000000000000005c8f11003c8d100000000000000000005c8f110000000000000000000100000000000000836b11000b00000000000000000000004c8d100008000000000000000000000000000000000000000000000000000000000000005c8f1100548d10000000000000000000648d1000020000000000000000000000af911000150000005665633c28417574686f7269747949642c2042616265417574686f72697479576569676874293e003b000000000000000100000055000000949110001b000000329110003e00000070911000240000003b0000000000000001000000530000001d911000150000005b75383b2033325d578f10002e0000005c8f110000000000858f10000b0000005c8f110000000000908f100041000000d18f10003e0000000f9010004500000054901000450000009990100041000000da901000430000003b0000000000000001000000bc000000408f1000170000003b00000000000000010000005c000000fb8d10001f0000005c8f1100000000001a8e10003d000000578e100040000000978e1000250000005c8f110000000000bc8e10003b000000f78e100042000000398f1000070000005665633c5b75383b2033325d3e0000003b0000000000000001000000550000004d617962655672663b000000000000000100000052000000748d100040000000b48d1000470000002054656d706f726172792076616c75652028636c656172656420617420626c6f636b2066696e616c697a6174696f6e292077686963682069732060536f6d6560206966207065722d626c6f636b20696e697469616c697a6174696f6e2068617320616c7265616479206265656e2063616c6c656420666f722063757272656e7420626c6f636b2e2052616e646f6d6e65737320756e64657220636f6e737472756374696f6e2e205765206d616b6520612074726164656f6666206265747765656e2073746f7261676520616363657373657320616e64206c697374206c656e6774682e2057652073746f72652074686520756e6465722d636f6e737472756374696f6e2072616e646f6d6e65737320696e207365676d656e7473206f6620757020746f2060554e4445525f434f4e535452554354494f4e5f5345474d454e545f4c454e475448602e204f6e63652061207365676d656e7420726561636865732074686973206c656e6774682c20776520626567696e20746865206e657874206f6e652e20576520726573657420616c6c207365676d656e747320616e642072657475726e20746f206030602061742074686520626567696e6e696e67206f662065766572792065706f63682e204e6578742065706f63682072616e646f6d6e6573732e205468652065706f63682072616e646f6d6e65737320666f7220746865202a63757272656e742a2065706f63682e20232053656375726974792054686973204d555354204e4f54206265207573656420666f722067616d626c696e672c2061732069742063616e20626520696e666c75656e6365642062792061206d616c6963696f75732076616c696461746f7220696e207468652073686f7274207465726d2e204974204d4159206265207573656420696e206d616e792063727970746f677261706869632070726f746f636f6c732c20686f77657665722c20736f206c6f6e67206173206f6e652072656d656d626572732074686174207468697320286c696b652065766572797468696e6720656c7365206f6e2d636861696e29206974206973207075626c69632e20466f72206578616d706c652c2069742063616e20626520757365642077686572652061206e756d626572206973206e656564656420746861742063616e6e6f742068617665206265656e2063686f73656e20627920616e206164766572736172792c20666f7220707572706f7365732073756368206173207075626c69632d636f696e207a65726f2d6b6e6f776c656467652070726f6f66732e2043757272656e7420736c6f74206e756d6265722e2054686520736c6f74206174207768696368207468652066697273742065706f63682061637475616c6c7920737461727465642e2054686973206973203020756e74696c2074686520666972737420626c6f636b206f662074686520636861696e2e2043757272656e742065706f636820617574686f7269746965732e2043757272656e742065706f636820696e6465782e00000000349210000d00000000000000480b110003000000000000005c8f1100449210000000000000000000549210000200000000000000000000006492100011000000000000002cab100009000000000000005c8f110078921000000000000000000088921000050000000000000045706f63684475726174696f6e0000003b0000000000000001000000bd000000e093100043000000239410003f0000004578706563746564426c6f636b54696d650000003b0000000000000001000000be000000b092100041000000f19210004400000035931000410000007693100042000000b89310002800000020546865206578706563746564206176657261676520626c6f636b2074696d6520617420776869636820424142452073686f756c64206265206372656174696e6720626c6f636b732e2053696e636520424142452069732070726f626162696c6973746963206974206973206e6f74207472697669616c20746f20666967757265206f7574207768617420746865206578706563746564206176657261676520626c6f636b2074696d652073686f756c64206265206261736564206f6e2074686520736c6f74206475726174696f6e20616e642074686520736563757269747920706172616d657465722060636020287768657265206031202d20636020726570726573656e7473207468652070726f626162696c697479206f66206120736c6f74206265696e6720656d707479292e20546865206e756d626572206f66202a2a736c6f74732a2a207468617420616e2065706f63682074616b65732e20576520636f75706c652073657373696f6e7320746f2065706f6368732c20692e652e2077652073746172742061206e65772073657373696f6e206f6e636520746865206e65772065706f636820626567696e732e65706f636820696e64696365732077696c6c206e6576657220726561636820325e3634206265666f726520746865206465617468206f662074686520756e6976657273653b20716564576974686472617720686173206265656e20636865636b65642061626f76653b0a090909647565735f6c696d69746564203c2072656e745f627564676574203c2062616c616e6365202d2073756273697374656e6365203c2062616c616e6365202d206578697374656e7469616c5f6465706f7369743b0a0909097165640000004d0000000800000004000000bf000000657865632e7072656661625f6d6f64756c652e696e697469616c2063616e27742062652067726561746572207468616e20657865632e7072656661625f6d6f64756c652e6d6178696d756d3b0a09090909090974687573204d656d6f72793a3a6e6577206d757374206e6f74206661696c3b0a09090909090971656474696d657374616d702073657420696e20626c6f636b20646f65736e2774206d6174636820736c6f7420696e207365616c496e686572656e7420776974682073616d65206964656e74696669657220616c726561647920657869737473214e6f206f74686572206572726f72732061726520616363657074656420616674657220616e2068617264206572726f72215468657265206973206f6e6c79206f6e6520666174616c206572726f723b207165640000004d0000000800000004000000c0000000f79610000d000000da9610001b000000f596100002000000a4961000360000003d020000010000002f686f6d652f6461766964642f6465762f7375627374726174652f62696e2f6e6f64652f72756e74696d652f7372632f6c69622e727342616420696e70757420646174612070726f766964656420746f203a20657865637574655f626c6f636b0c97100010000000696e697469616c697a655f626c6f636b249710000f0000006170706c795f65787472696e736963003c97100013000000696e686572656e745f65787472696e7369637300589710000f000000636865636b5f696e686572656e747300709710001400000076616c69646174655f7472616e73616374696f6e8c9710000f0000006f6666636861696e5f776f726b657200a49710000d0000006163636f756e745f6e6f6e6365000000af65110004000000c49710000b0000006765745f73746f7261676500d89710000a00000071756572795f696e666f0000ec9710001500000067656e65726174655f73657373696f6e5f6b6579733a65787472696e7369635f696e64657853797374656d4163636f756e744e6f6e6365426c6f636b486173684e756d626572506172656e744861736845787472696e73696373526f6f74446967657374589810001a0000004552524f523a20436f727275707465642073746174652061742054696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b4e6f774d0000000800000004000000bf00000054696d657374616d7020746f6f2066617220696e2066757475726520746f206163636570744765747320616e64206465636f6465732074696d657374616d7020696e686572656e7420646174614576656e74734576656e74546f70696373000000000000449a10000a000000000000005c8f1100000000000000000000000000509a1000010000000000000000000000589a10000600000000000000609a1000010000000000000000000000789a1000010000000000000000000000809a10000e00000000000000909a1000010000000000000000000000a89a1000010000000000000000000000b09a10000800000000000000b89a1000010000000000000000000000d09a1000010000000000000000000000d89a10000b00000000000000e49a1000010000000000000000000000fc9a1000010000000000000000000000049b10000c00000000000000109b1000010000000000000000000000289b1000010000000000000000000000309b10000b000000000000003c9b1000010000000000000000000000549b1000010000000000000066696c6c5f626c6f636b0000769c10004800000072656d61726b0000000000006f9c10000700000000000000e960110007000000549c10001b0000007365745f686561705f70616765730000000000004f9c10000500000000000000480b110003000000109c10003f0000007365745f636f6465000000005e5b11000300000000000000e960110007000000fe9b1000120000007365745f73746f726167650000000000ec9b10000500000000000000f19b10000d000000d19b10001b0000006b696c6c5f73746f7261676500000000c59b10000400000000000000c99b100008000000a79b10001e0000006b696c6c5f7072656669780000000000a19b100006000000000000000c5c1100030000005c9b100045000000204b696c6c20616c6c2073746f72616765206974656d7320776974682061206b657920746861742073746172747320776974682074686520676976656e207072656669782e707265666978204b696c6c20736f6d65206974656d732066726f6d2073746f726167652e6b6579735665633c4b65793e2053657420736f6d65206974656d73206f662073746f726167652e6974656d735665633c4b657956616c75653e2053657420746865206e657720636f64652e2053657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e7061676573204d616b6520736f6d65206f6e2d636861696e2072656d61726b2e5f72656d61726b20412062696720646973706174636820746861742077696c6c20646973616c6c6f7720616e79206f74686572207472616e73616374696f6e20746f20626520696e636c756465642e000000000000179810000c00000001010000000000000f5c11000c0000000000000038a1100008000000000000000000000000000000000000005c8f110078a21000000000000000000040a110000100000000000000010000000000000048a110000e00000000000000000000001e61110003000000000000000000000000000000000000000000000000000000000000005c8f110094a11000000000000000000058a110000100000000000000000000000000000060a1100013000000000000000000000073a1100006000000000000000000000000000000000000000000000000000000000000005c8f110094a1100000000000000000007ca110000100000000000000000000000000000084a110001000000000000000000000001e61110003000000000000000000000000000000000000000000000000000000000000005c8f110094a110000000000000000000a4a1100001000000000000000000000000000000239810000900000001010000000000009c6011000e000000000000005932110007000000000000000000000000000000000000005c8f1100eca110000000000000000000aca1100001000000000000000100000000000000b4a110000d00000001010000000000001e6111000300000000000000e960110007000000000000000000000000000000000000005c8f1100c4a110000000000000000000d4a11000010000000000000001000000000000002c9810000600000000000000000000009c6011000e000000000000000000000000000000000000000000000000000000000000005c8f110078a210000000000000000000dca1100001000000000000000100000000000000329810000a00000000000000000000005932110007000000000000000000000000000000000000000000000000000000000000005c8f1100eca110000000000000000000e4a11000010000000000000001000000000000003c9810000e00000000000000000000005932110007000000000000000000000000000000000000000000000000000000000000005c8f1100eca110000000000000000000fca11000010000000000000001000000000000004a98100006000000000000000000000004a210000b000000000000000000000000000000000000000000000000000000000000005c8f110010a21000000000000000000020a2100001000000000000000100000000000000fd98100006000000000000000000000028a2100023000000000000000000000000000000000000000000000000000000000000005c8f11004ca2100000000000000000005ca210000100000000000000010000000000000064a210000a00000000000000000000006ea210000a000000000000000000000000000000000000000000000000000000000000005c8f110078a21000000000000000000088a2100001000000000000000100000000000000039910000b000000020101000000000090a21000020000000000000059321100070000000000000092a2100021000000000000005c8f1100b4a210000000000000000000c4a210000d0000000000000001000000543a3a496e64657840a810001f00000045787472696e736963436f756e74000012a810002e000000416c6c45787472696e73696373576569676874576569676874000000cda7100045000000416c6c45787472696e736963734c656e3b0000000000000001000000520000007da710005000000057a710002600000045787472696e736963446174610000003b00000000000000010000005800000008a710004f000000c6a6100042000000aaa610001c0000003b0000000000000001000000c100000065a61000450000004469676573744f663c543e003b00000000000000010000005500000029a610003c0000005665633c4576656e745265636f72643c543a3a4576656e742c20543a3a486173683e3e003b0000000000000001000000c200000001a61000280000004576656e74436f756e744576656e74496e6465783b00000000000000010000005c000000d3a510002e00000028295665633c28543a3a426c6f636b4e756d6265722c204576656e74496e646578293e003b0000000000000001000000550000002ca310004900000075a31000250000005c8f1100000000009aa310004b000000e5a310002a0000005c8f1100000000000fa410005400000063a4100051000000b4a41000390000005c8f110000000000eda410005300000040a510005300000093a5100040000000204d617070696e67206265747765656e206120746f7069632028726570726573656e74656420627920543a3a486173682920616e64206120766563746f72206f6620696e6465786573206f66206576656e747320696e2074686520603c4576656e74733c543e3e60206c6973742e20546865206669727374206b657920736572766573206e6f20707572706f73652e2054686973206669656c64206973206465636c6172656420617320646f75626c655f6d6170206a75737420666f7220636f6e76656e69656e6365206f66207573696e67206072656d6f76655f707265666978602e20416c6c20746f70696320766563746f727320686176652064657465726d696e69737469632073746f72616765206c6f636174696f6e7320646570656e64696e67206f6e2074686520746f7069632e205468697320616c6c6f7773206c696768742d636c69656e747320746f206c6576657261676520746865206368616e67657320747269652073746f7261676520747261636b696e67206d656368616e69736d20616e6420696e2063617365206f66206368616e67657320666574636820746865206c697374206f66206576656e7473206f6620696e7465726573742e205468652076616c756520686173207468652074797065206028543a3a426c6f636b4e756d6265722c204576656e74496e646578296020626563617573652069662077652075736564206f6e6c79206a7573742074686520604576656e74496e64657860207468656e20696e20636173652069662074686520746f70696320686173207468652073616d6520636f6e74656e7473206f6e20746865206e65787420626c6f636b206e6f206e6f74696669636174696f6e2077696c6c20626520747269676765726564207468757320746865206576656e74206d69676874206265206c6f73742e20546865206e756d626572206f66206576656e747320696e2074686520604576656e74733c543e60206c6973742e204576656e7473206465706f736974656420666f72207468652063757272656e7420626c6f636b2e20446967657374206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2045787472696e7369637320726f6f74206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2048617368206f66207468652070726576696f757320626c6f636b2e205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e2045787472696e73696373206461746120666f72207468652063757272656e7420626c6f636b20286d61707320616e2065787472696e736963277320696e64657820746f206974732064617461292e204d6170206f6620626c6f636b206e756d6265727320746f20626c6f636b206861736865732e20546f74616c206c656e6774682028696e2062797465732920666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2077656967687420666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2065787472696e7369637320636f756e7420666f72207468652063757272656e7420626c6f636b2e2045787472696e73696373206e6f6e636520666f72206163636f756e74732e4e6f646520697320636f6e6669677572656420746f20757365207468652073616d6520686173683b20716564003b00000000000000010000003c00000000000000c8a810000300000000000000cca81000010000000000000000000000e4a810000900000000000000736574000000000066aa1000030000000000000069aa1000120000002ca91000160000005c8f11000000000042a910005600000098a91000360000005c8f110000000000cea91000510000001faa1000110000005c8f11000000000030aa10003600000020536574207468652063757272656e742074696d652e20546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6e2070686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e205468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e742073706563696669656420627920604d696e696d756d506572696f64602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652060496e686572656e74602e6e6f77436f6d706163743c543a3a4d6f6d656e743e00000000009d9810000300000000000000000000002cab100009000000000000000000000000000000000000000000000000000000000000005c8f110038ab1000000000000000000048ab100001000000000000000100000000000000827411000900000000000000000000000353110004000000000000000000000000000000000000000000000000000000000000005c8f110050ab1000000000000000000060ab1000010000000000000001000000543a3a4d6f6d656e740000003b00000000000000010000005300000095ab1000240000003b00000000000000010000005200000068ab10002d00000020446964207468652074696d657374616d7020676574207570646174656420696e207468697320626c6f636b3f2043757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e00000000000000f4ab10000d000000000000002cab100009000000000000005c8f110004ac1000000000000000000014ac100004000000000000004d696e696d756d506572696f640000003b0000000000000001000000c300000034ac10005a0000008eac10005a000000e8ac10005900000041ad10001c00000020546865206d696e696d756d20706572696f64206265747765656e20626c6f636b732e204265776172652074686174207468697320697320646966666572656e7420746f20746865202a65787065637465642a20706572696f6420746861742074686520626c6f636b2070726f64756374696f6e206170706172617475732070726f76696465732e20596f75722063686f73656e20636f6e73656e7375732073797374656d2077696c6c2067656e6572616c6c7920776f726b2077697468207468697320746f2064657465726d696e6520612073656e7369626c6520626c6f636b2074696d652e20652e672e20466f7220417572612c2069742077696c6c20626520646f75626c65207468697320706572696f64206f6e2064656661756c742073657474696e67732e3a6865617070616765733a636f646554696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b54696d657374616d70206d75737420696e6372656d656e74206279206174206c65617374203c4d696e696d756d506572696f643e206265747765656e2073657175656e7469616c20626c6f636b734469676573744974656d206e6f7420657175616c0000000000002cae10000f000000000000003cae10000200000000000000000000004cae100004000000000000004e65774163636f756e74496e64657800e252110009000000e7ae10000c0000006cae1000220000005c8f1100000000008eae100041000000cfae1000180000002041206e6577206163636f756e7420696e646578207761732061737369676e65642e2054686973206576656e74206973206e6f7420747269676765726564207768656e20616e206578697374696e6720696e64657820697320726561737369676e656420746f20616e6f7468657220604163636f756e744964602e4163636f756e74496e6465780000000000441d11000800000000000000fcaf10000400000000000000000000001cb010000200000000000000000000002cb01000050000000000000034b010000500000000000000000000005cb010000200000000000000000000006cb01000080000000000000090f3100001000000000000000000000074b010000100000000000000000000007cb010000b0000000000000090f3100001000000000000000000000088b01000010000000000000000000000041e1100080000000000000090b01000020000000000000000000000a0b01000010000000000000000000000a8b010000e0000000000000090b01000020000000000000000000000b8b010000100000000000000e252110009000000a8b210000d000000971f1100040000003ab210000b00000045b210005300000098b2100010000000566f746564000000e252110009000000971f11000400000003531100040000003ab210000b0000003ab210000b000000b2b1100042000000f4b1100046000000417070726f76656481b1100031000000446973617070726f766564004cb1100035000000971f11000400000003531100040000000bb11000410000004d656d62657245786563757465640000c0b010004b00000020412073696e676c65206d656d6265722064696420736f6d6520616374696f6e3b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e207761732065786563757465643b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e20776173206e6f7420617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2077617320617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2028676976656e20686173682920686173206265656e20766f746564206f6e20627920676976656e206163636f756e742c206c656176696e6720612074616c6c79202879657320766f74657320616e64206e6f20766f74657320676976656e20726573706563746976656c7920617320604d656d626572436f756e7460292e4d656d626572436f756e742041206d6f74696f6e2028676976656e20686173682920686173206265656e2070726f706f7365642028627920676976656e206163636f756e742920776974682061207468726573686f6c642028676976656e20604d656d626572436f756e7460292e50726f706f73616c496e646578496e64696365734e657874456e756d536574456e756d536574496e7374616e636532436f6c6c65637469766550726f706f73616c734d656d62657273566f74696e670000000000bcb210000b0000000000000000000000a8b310000f000000000000000000000000000000000000000000000000000000000000005c8f110080bb10000000000000000000b8b3100001000000000000000100000000000000c7b21000070000000101000000000000a8b310000f000000000000000c3d110011000000000000000000000000000000000000005c8f110090bb10000000000000000000c0b31000010000000000000001000000543a3a4163636f756e74496e64657800deb310001f000000c8b31000160000002054686520656e756d65726174696f6e20736574732e20546865206e657874206672656520656e756d65726174696f6e207365742e496e7374616e636531436f6c6c656374697665636f6465206973206e6f7420666f756e647072697374696e6520636f6465206973206e6f7420666f756e647468657265206973206e6f7420656e6f7567682067617320666f722073746f72696e672074686520636f6465000000000018b510000b0000000000000024b510000100000000000000000000003cb510000400000000000000000000005cb51000070000000000000064b510000100000000000000000000007cb51000030000000000000000000000c8261100070000000000000094b51000020000000000000000000000c4b51000040000000000000000000000802711000400000000000000e4b510000300000000000000000000002cb6100004000000000000007365745f6d656d6265727300000000005cb810000b000000000000000c3d110011000000dbb71000540000002fb81000170000005c8f11000000000046b8100016000000657865637574650000000000d85a1100080000000000000055b710001e00000073b710003d0000005c8f110000000000b0b710002b0000000000000038b71000090000000000000041b710001400000000000000d85a1100080000000000000055b710001e0000002d5a11000b000000e6b61000240000000ab710002e000000a65a11000c00000000000000d85a11000800000000000000593211000700000000000000c4b610000500000000000000c9b610001600000000000000dfb61000070000000000000003531100040000002d5a11000b0000004cb61000230000006fb6100055000000a65a11000c000000202d20426f756e6465642073746f72616765207265616420616e64207772697465732e202d2057696c6c20626520736c696768746c792068656176696572206966207468652070726f706f73616c20697320617070726f766564202f20646973617070726f7665642061667465722074686520766f74652e696e646578436f6d706163743c50726f706f73616c496e6465783e617070726f7665202d20426f756e6465642073746f7261676520726561647320616e64207772697465732e202d20417267756d656e7420607468726573686f6c6460206861732062656172696e67206f6e207765696768742e7468726573686f6c64436f6d706163743c4d656d626572436f756e743e426f783c3c542061732054726169743c493e3e3a3a50726f706f73616c3e20446973706174636820612070726f706f73616c2066726f6d2061206d656d626572207573696e672074686520604d656d62657260206f726967696e2e204f726967696e206d7573742062652061206d656d626572206f662074686520636f6c6c6563746976652e205365742074686520636f6c6c6563746976652773206d656d62657273686970206d616e75616c6c7920746f20606e65775f6d656d62657273602e204265206e69636520746f2074686520636861696e20616e642070726f76696465206974207072652d736f727465642e20526571756972657320726f6f74206f726967696e2e6e65775f6d656d626572735665633c543a3a486173683e0094b910002400000050726f706f73616c4f663c542061732054726169743c493e3e3a3a50726f706f73616c0061b9100033000000566f7465733c543a3a4163636f756e7449643e0034b910002d00000022b9100012000000d4b810004e000000205468652063757272656e74206d656d62657273206f662074686520636f6c6c6563746976652e20546869732069732073746f72656420736f7274656420286a7573742062792076616c7565292e2050726f706f73616c7320736f206661722e20566f746573206f6e206120676976656e2070726f706f73616c2c206966206974206973206f6e676f696e672e2041637475616c2070726f706f73616c20666f72206120676976656e20686173682c20696620697427732063757272656e742e2054686520686173686573206f6620746865206163746976652070726f706f73616c732e00000000e1b2100009000000000000000000000067b810000c000000000000000000000000000000000000000000000000000000000000005c8f110090bb1000000000000000000074b81000010000000000000001000000000000007cb810000a000000010100000000000059321100070000000000000086b8100019000000000000000000000000000000000000005c8f110070bb10000000000000000000a0b8100001000000000000000000000000000000f1b21000060000000101000000000000593211000700000000000000a8b8100013000000000000000000000000000000000000005c8f110070bb10000000000000000000bcb8100001000000000000000000000000000000ac7411000d00000000000000000000001e61110003000000000000000000000000000000000000000000000000000000000000005c8f110080bb10000000000000000000c4b8100001000000000000000100000000000000eab210000700000000000000000000000c3d110011000000000000000000000000000000000000000000000000000000000000005c8f110090bb10000000000000000000ccb810000100000000000000010000003b0000000000000001000000520000003b00000000000000010000005c0000003b00000000000000010000005500000070726f706f736572206e6f742061206d656d6265726475706c69636174652070726f706f73616c73206e6f7420616c6c6f77656470726f706f73616c206d7573742065786973746d69736d61746368656420696e6465786475706c696361746520766f74652069676e6f726564766f746572206e6f742061206d656d626572486561644f664e6f6d696e61746f72734e6f6d696e61746f7273486561644f6656616c696461746f727356616c696461746f7273426f6e6465644c65646765725374616b65727343757272656e74457261537461727456616c696461746f72536c617368496e4572614e6f6d696e61746f72536c617368496e457261536c617368696e675370616e735370616e536c6173680000000000000038bd1000060000000000000040bd100002000000000000000000000050bd100002000000000000000000000060bd10000500000000000000d8ef100002000000000000000000000068bd100001000000000000000000000070bd10001a00000000000000586f11000100000000000000000000008cbd1000020000000000000052657761726400009b1f1100070000009b1f1100070000003ebe10005400000092be100023000000536c617368000000f5bd1000490000004f6c64536c617368696e675265706f727444697363617264656400009cbd100047000000e3bd10001200000020416e206f6c6420736c617368696e67207265706f72742066726f6d2061207072696f72206572612077617320646973636172646564206265636175736520697420636f756c64206e6f742062652070726f6365737365642e204f6e652076616c696461746f722028616e6420697473206e6f6d696e61746f72732920686173206265656e20736c61736865642062792074686520676976656e20616d6f756e742e20416c6c2076616c696461746f72732068617665206265656e207265776172646564206279207468652066697273742062616c616e63653b20746865207365636f6e64206973207468652072656d61696e6465722066726f6d20746865206d6178696d756d20616d6f756e74206f66207265776172642e506179656543757272656e74456c6563746564536c6f745374616b65556e6170706c696564536c617368657300000000000000a4c110000400000000000000a8c11000030000000000000000000000f0c110000f000000000000000000000068c210000a0000000000000074c210000100000000000000000000008cc210000e0000000000000000000000fcc21000060000000000000004c310000100000000000000000000001cc31000170000000000000000000000d4c3100011000000000000005c8f1100000000000000000000000000e8c3100010000000000000000000000068c41000080000000000000070c4100001000000000000000000000088c410000b0000000000000000000000e0c410000800000000000000e8c4100001000000000000000000000000c510000b000000000000000000000058c5100005000000000000005c8f110000000000000000000000000060c510000b0000000000000000000000b8c510000900000000000000c4c51000010000000000000000000000dcc510000b000000000000000000000034c610000e0000000000000044c610000100000000000000000000005cc610000b0000000000000000000000b4c610001300000000000000c8c61000010000000000000000000000e0c61000010000000000000000000000e8c610000d000000000000005c8f1100000000000000000000000000f8c6100005000000000000000000000020c710000d000000000000005c8f110000000000000000000000000030c7100006000000000000000000000060c71000110000000000000074c710000100000000000000000000008cc7100001000000000000000000000094c710000d00000000000000a4c71000010000000000000000000000bcc71000010000000000000000000000c4c7100014000000000000005c8f1100000000000000000000000000d8c7100005000000000000000000000000c81000150000000000000018c8100002000000000000000000000048c810000700000000000000626f6e640000000062cc10000a00000000000000b55a11002300000000000000143611000500000000000000193611001500000000000000efcc10000500000000000000f4cc100011000000c7d510005900000020d61000210000005c8f11000000000041d610004c0000005c8f1100000000008dd61000490000005c8f1100000000002d5a11000b000000d6d6100035000000385a1100080000000bd710001a0000005c8f11000000000025d710005b00000080d7100049000000a65a11000c000000626f6e645f6578747261000000000000b9d510000e00000000000000193611001500000093d4100059000000ecd410000d0000005c8f110000000000f9d41000540000004dd5100059000000a6d51000130000005c8f1100000000007bcb1000550000005c8f1100000000002d5a11000b000000d0cb10003a000000385a110008000000d235110010000000a65a11000c000000756e626f6e640000000000001436110005000000000000001936110015000000b8d01000550000000dd11000400000004dd11000490000005c8f11000000000096d1100052000000e8d11000300000005c8f11000000000018d210004f00000067d210004f000000b6d210003f0000005c8f1100000000009acc1000550000005c8f110000000000f5d21000260000005c8f1100000000002d5a11000b0000001bd31000500000000acc1000260000006bd3100059000000c4d310005c00000020d4100069000000d23511001000000089d410000a00000077697468647261775f756e626f6e646564000000b1ce10004b0000005c8f110000000000fcce10004d00000049cf1000130000005c8f1100000000009acc1000550000005c8f1100000000005ccf10001b0000005c8f1100000000002d5a11000b00000077cf100055000000cccf1000510000001dd010003d0000005ad010005e00000030cc100032000000a65a11000c00000076616c6964617465000000009ece10000500000000000000a3ce10000e00000064ce10003a0000005c8f11000000000044cb1000370000005c8f1100000000009acc1000550000005c8f1100000000002d5a11000b000000d0cb10003a0000000acc10002600000030cc100032000000a65a11000c0000006e6f6d696e6174650000000035ce100007000000000000003cce1000280000004ccd1000440000005c8f11000000000044cb1000370000005c8f1100000000009acc1000550000005c8f1100000000002d5a11000b00000090cd100049000000d9cd100026000000ffcd100036000000a65a11000c0000006368696c6c00000005cd1000320000005c8f11000000000044cb1000370000005c8f1100000000009acc1000550000005c8f1100000000002d5a11000b000000d0cb10003a00000037cd10001500000030cc100032000000a65a11000c0000007365745f706179656500000000000000efcc10000500000000000000f4cc1000110000006ccc10002e0000005c8f11000000000044cb1000370000005c8f1100000000009acc1000550000005c8f1100000000002d5a11000b000000d0cb10003a0000000acc10002600000030cc100032000000a65a11000c0000007365745f636f6e74726f6c6c657200000000000062cc10000a00000000000000b55a11002300000020cb1000240000005c8f11000000000044cb1000370000005c8f1100000000007bcb1000550000005c8f1100000000002d5a11000b000000d0cb10003a0000000acc10002600000030cc100032000000a65a11000c0000007365745f76616c696461746f725f636f756e7400000000005e5b1100030000000000000014cb10000c000000f4ca100020000000666f7263655f6e6f5f65726173000000c8ca10002c0000005c8f1100000000002d5a11000b000000b8ca100010000000a65a11000c000000666f7263655f6e65775f6572610000003dca10005300000090ca1000280000005c8f1100000000002d5a11000b000000b8ca100010000000a65a11000c0000007365745f696e76756c6e657261626c65730000000000000033ca10000a000000000000000c3d11001100000000ca100033000000666f7263655f756e7374616b6500000000000000fbc9100005000000000000000f5c11000c000000b8c9100043000000666f7263655f6e65775f6572615f616c7761797363c91000410000005c8f1100000000002d5a11000b000000a4c9100014000000a65a11000c00000063616e63656c5f64656665727265645f736c6173680000000000000043c91000030000000000000046c9100008000000000000004ec910000d000000000000005bc910000800000080c8100051000000d1c810001c000000edc81000410000005c8f1100000000002d5a11000b0000002ec9100015000000a65a11000c0000002043616e63656c20656e6163746d656e74206f66206120646566657272656420736c6173682e2043616e2062652063616c6c6564206279206569746865722074686520726f6f74206f726967696e206f72207468652060543a3a536c61736843616e63656c4f726967696e602e2070617373696e67207468652065726120616e6420696e6469636573206f662074686520736c617368657320666f7220746861742065726120746f206b696c6c2e202d204f6e652073746f726167652077726974652e657261457261496e646578736c6173685f696e64696365735665633c7533323e20466f72636520746865726520746f2062652061206e6577206572612061742074686520656e64206f662073657373696f6e7320696e646566696e6974656c792e202d204f6e652073746f7261676520777269746520466f72636520612063757272656e74207374616b657220746f206265636f6d6520636f6d706c6574656c7920756e7374616b65642c20696d6d6564696174656c792e737461736820536574207468652076616c696461746f72732077686f2063616e6e6f7420626520736c61736865642028696620616e79292e76616c696461746f727320466f72636520746865726520746f2062652061206e6577206572612061742074686520656e64206f6620746865206e6578742073657373696f6e2e20416674657220746869732c2069742077696c6c20626520726573657420746f206e6f726d616c20286e6f6e2d666f7263656429206265686176696f75722e202d204e6f20617267756d656e74732e20466f72636520746865726520746f206265206e6f206e6577206572617320696e646566696e6974656c792e2054686520696465616c206e756d626572206f662076616c696461746f72732e436f6d706163743c7533323e202852652d297365742074686520636f6e74726f6c6c6572206f6620612073746173682e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f206279207468652073746173682c206e6f742074686520636f6e74726f6c6c65722e202d20496e646570656e64656e74206f662074686520617267756d656e74732e20496e7369676e69666963616e7420636f6d706c65786974792e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732e202d2057726974657320617265206c696d6974656420746f2074686520606f726967696e60206163636f756e74206b65792e636f6e74726f6c6c6572202852652d2973657420746865207061796d656e742074617267657420666f72206120636f6e74726f6c6c65722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2062792074686520636f6e74726f6c6c65722c206e6f74207468652073746173682e706179656552657761726444657374696e6174696f6e204465636c617265206e6f2064657369726520746f206569746865722076616c6964617465206f72206e6f6d696e6174652e202d20436f6e7461696e73206f6e6520726561642e204465636c617265207468652064657369726520746f206e6f6d696e6174652060746172676574736020666f7220746865206f726967696e20636f6e74726f6c6c65722e202d20546865207472616e73616374696f6e277320636f6d706c65786974792069732070726f706f7274696f6e616c20746f207468652073697a65206f66206074617267657473602c2077686963682069732063617070656420617420604d41585f4e4f4d494e4154494f4e53602e202d20426f74682074686520726561647320616e642077726974657320666f6c6c6f7720612073696d696c6172207061747465726e2e746172676574735665633c3c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f757263653e204465636c617265207468652064657369726520746f2076616c696461746520666f7220746865206f726967696e20636f6e74726f6c6c65722e707265667356616c696461746f7250726566732052656d6f766520616e7920756e6c6f636b6564206368756e6b732066726f6d207468652060756e6c6f636b696e67602071756575652066726f6d206f7572206d616e6167656d656e742e205468697320657373656e7469616c6c7920667265657320757020746861742062616c616e636520746f206265207573656420627920746865207374617368206163636f756e7420746f20646f2077686174657665722069742077616e74732e2053656520616c736f205b6043616c6c3a3a756e626f6e64605d2e202d20436f756c6420626520646570656e64656e74206f6e2074686520606f726967696e6020617267756d656e7420616e6420686f77206d7563682060756e6c6f636b696e6760206368756e6b732065786973742e2020497420696d706c6965732060636f6e736f6c69646174655f756e6c6f636b656460207768696368206c6f6f7073206f76657220604c65646765722e756e6c6f636b696e67602c2077686963682069732020696e6469726563746c7920757365722d636f6e74726f6c6c65642e20536565205b60756e626f6e64605d20666f72206d6f72652064657461696c2e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732c20796574207468652073697a65206f6620776869636820636f756c64206265206c61726765206261736564206f6e20606c6564676572602e205363686564756c65206120706f7274696f6e206f662074686520737461736820746f20626520756e6c6f636b656420726561647920666f72207472616e73666572206f75742061667465722074686520626f6e6420706572696f6420656e64732e2049662074686973206c656176657320616e20616d6f756e74206163746976656c7920626f6e646564206c657373207468616e20543a3a43757272656e63793a3a6d696e696d756d5f62616c616e636528292c207468656e20697420697320696e6372656173656420746f207468652066756c6c20616d6f756e742e204f6e63652074686520756e6c6f636b20706572696f6420697320646f6e652c20796f752063616e2063616c6c206077697468647261775f756e626f6e6465646020746f2061637475616c6c79206d6f7665207468652066756e6473206f7574206f66206d616e6167656d656e7420726561647920666f72207472616e736665722e204e6f206d6f7265207468616e2061206c696d69746564206e756d626572206f6620756e6c6f636b696e67206368756e6b73202873656520604d41585f554e4c4f434b494e475f4348554e4b5360292063616e20636f2d657869737473206174207468652073616d652074696d652e20496e207468617420636173652c205b6043616c6c3a3a77697468647261775f756e626f6e646564605d206e65656420746f2062652063616c6c656420666972737420746f2072656d6f766520736f6d65206f6620746865206368756e6b732028696620706f737369626c65292e2053656520616c736f205b6043616c6c3a3a77697468647261775f756e626f6e646564605d2e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204c696d697465642062757420706f74656e7469616c6c79206578706c6f697461626c6520636f6d706c65786974792e202d20456163682063616c6c20287265717569726573207468652072656d61696e646572206f662074686520626f6e6465642062616c616e636520746f2062652061626f766520606d696e696d756d5f62616c616e6365602920202077696c6c2063617573652061206e657720656e74727920746f20626520696e73657274656420696e746f206120766563746f722028604c65646765722e756e6c6f636b696e676029206b65707420696e2073746f726167652e202020546865206f6e6c792077617920746f20636c65616e207468652061666f72656d656e74696f6e65642073746f72616765206974656d20697320616c736f20757365722d636f6e74726f6c6c656420766961206077697468647261775f756e626f6e646564602e203c2f7765696768743e2041646420736f6d6520657874726120616d6f756e742074686174206861766520617070656172656420696e207468652073746173682060667265655f62616c616e63656020696e746f207468652062616c616e636520757020666f72207374616b696e672e20557365207468697320696620746865726520617265206164646974696f6e616c2066756e647320696e20796f7572207374617368206163636f756e74207468617420796f75207769736820746f20626f6e642e20556e6c696b65205b60626f6e64605d206f72205b60756e626f6e64605d20746869732066756e6374696f6e20646f6573206e6f7420696d706f736520616e79206c696d69746174696f6e206f6e2074686520616d6f756e7420746861742063616e2062652061646465642e6d61785f6164646974696f6e616c2054616b6520746865206f726967696e206163636f756e74206173206120737461736820616e64206c6f636b207570206076616c756560206f66206974732062616c616e63652e2060636f6e74726f6c6c6572602077696c6c20626520746865206163636f756e74207468617420636f6e74726f6c732069742e206076616c756560206d757374206265206d6f7265207468616e2074686520606d696e696d756d5f62616c616e636560207370656369666965642062792060543a3a43757272656e6379602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20627920746865207374617368206163636f756e742e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204d6f64657261746520636f6d706c65786974792e202d20546872656520657874726120444220656e74726965732e204e4f54453a2054776f206f66207468652073746f726167652077726974657320286053656c663a3a626f6e646564602c206053656c663a3a7061796565602920617265205f6e657665725f20636c65616e656420756e6c6573732074686520606f726967696e602066616c6c732062656c6f77205f6578697374656e7469616c206465706f7369745f20616e6420676574732072656d6f76656420617320647573742e00000000000000f36f11000e00000000000000000000001e61110003000000000000000000000000000000000000000000000000000000000000005c8f11009ce410000000000000000000bce0100001000000000000000100000000000000017011001500000000000000000000001e61110003000000000000000000000000000000000000000000000000000000000000005c8f1100c4e010000000000000000000d4e0100001000000000000000100000000000000dce010000d00000000000000000000000c3d110011000000000000000000000000000000000000000000000000000000000000005c8f110084e310000000000000000000ece010000300000000000000010000000000000053bc10000600000001010000000000000f5c11000c000000000000000f5c11000c000000000000000000000000000000000000005c8f110038e11000000000000000000004e110000100000000000000000000000000000059bc10000600000001010000000000000f5c11000c000000000000000ce1100029000000000000000000000000000000000000005c8f110038e11000000000000000000048e1100001000000000000000000000000000000b5be10000500000001010000000000000f5c11000c00000000000000f4cc100011000000000000000000000000000000000000005c8f110050e11000000000000000000060e110000100000000000000010000000000000049bc10000a00000001010100000000000f5c11000c00000000000000a3ce10000e000000000000000000000000000000000000005c8f110068e11000000000000000000078e11000010000000000000001000000000000002fbc10000a00000001010100000000000f5c11000c0000000000000080e1100019000000000000000000000000000000000000005c8f11009ce110000000000000000000ace11000040000000000000000000000000000005fbc10000700000001010000000000000f5c11000c00000000000000cce1100024000000000000000000000000000000000000005c8f1100f0e11000000000000000000000e2100004000000000000000100000000000000babe10000e00000000000000000000000c3d110011000000000000000000000000000000000000000000000000000000000000005c8f110084e31000000000000000000020e21000010000000000000001000000000000001d7011000a000000000000000000000046c9100008000000000000000000000000000000000000000000000000000000000000005c8f11009ce41000000000000000000028e210000100000000000000010000000000000066bc10000f000000000000000000000030e210000b000000000000000000000000000000000000000000000000000000000000005c8f11003ce2100000000000000000004ce2100001000000000000000100000000000000277011001b0000000000000000000000e76f11000c000000000000000000000000000000000000000000000000000000000000005c8f11009ce41000000000000000000054e2100001000000000000000100000000000000427011001600000000000000000000005ce2100009000000000000000000000000000000000000000000000000000000000000005c8f110068e21000000000000000000078e2100001000000000000000100000000000000c8be1000090000000000000000000000824711000c000000000000000000000000000000000000000000000000000000000000005c8f1100fce21000000000000000000080e21000030000000000000001000000000000005870110008000000000000000000000098e2100007000000000000000000000000000000000000000000000000000000000000005c8f1100a0e210000000000000000000b0e210000100000000000000010000000000000060701100130000000000000000000000b8e2100007000000000000000000000000000000000000000000000000000000000000005c8f1100c0e210000000000000000000d0e2100003000000000000000100000000000000e8e21000130000000000000000000000824711000c000000000000000000000000000000000000000000000000000000000000005c8f1100fce2100000000000000000000ce3100002000000000000000100000000000000d1be100010000000010100000000000046c9100008000000000000001ce310002f000000000000000000000000000000000000005c8f11004ce3100000000000000000005ce3100001000000000000000100000000000000737011000a000000000000000000000064e310001d000000000000000000000000000000000000000000000000000000000000005c8f110084e31000000000000000000094e310000100000000000000010000000000000075bc100013000000020102000000000046c9100008000000000000000f5c11000c000000000000009ce3100017000000000000005c8f1100b4e310000000000000000000c4e310000200000000000000000000000000000088bc100013000000020102000000000046c9100008000000000000000f5c11000c00000000000000824711000c000000000000005c8f1100d4e310000000000000000000e4e31000010000000000000000000000000000009bbc10000d00000001010000000000000f5c11000c00000000000000ece3100017000000000000000000000000000000000000005c8f110004e41000000000000000000014e4100001000000000000000000000000000000a8bc10000900000001010000000000001ce4100023000000000000003fe4100022000000000000000000000000000000000000005c8f110064e41000000000000000000074e41000020000000000000001000000000000007d70110016000000000000000000000046c9100008000000000000000000000000000000000000000000000000000000000000005c8f110084e41000000000000000000094e4100001000000000000000000000000000000937011000e00000000000000000000001e61110003000000000000000000000000000000000000000000000000000000000000005c8f11009ce410000000000000000000ace4100001000000000000000100000073ed10002a0000003b0000000000000001000000c400000023ed100050000000496e76756c6e657261626c65730000004fec100056000000a5ec100053000000f8ec10002b0000000fec1000400000005374616b696e674c65646765723c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e0000003b000000000000000100000052000000beeb1000510000003b00000000000000010000005200000085eb1000390000003b0000000000000001000000c500000034eb1000510000004e6f6d696e6174696f6e733c543a3a4163636f756e7449643e0000003b00000000000000010000005200000058ea1000590000005c8f110000000000b1ea10004d000000feea1000360000004578706f737572653c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3b0000000000000001000000c60000009be9100053000000eee91000460000005c8f11000000000034ea1000240000005ce910003f00000045e91000170000004d6f6d656e744f663c543e003b00000000000000010000005300000027e910001e000000f3e8100034000000457261506f696e74730000003b0000000000000001000000c7000000b0e810004300000034e810004c0000005c8f11000000000080e8100030000000466f7263696e67003b000000000000000100000052000000ede710004700000050657262696c6c003b00000000000000010000005c00000076e710003e0000005c8f110000000000b4e710003900000043616e63656c6564536c6173685061796f7574003b000000000000000100000054000000f6e61000450000003be710003b0000005665633c556e6170706c696564536c6173683c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3e003b000000000000000100000055000000c5e61000310000005665633c28457261496e6465782c2053657373696f6e496e646578293e0000003b0000000000000001000000550000007ce61000490000002850657262696c6c2c2042616c616e63654f663c543e29003b0000000000000001000000520000000fe610005100000060e610001c0000003b000000000000000100000052000000b7e5100058000000736c617368696e673a3a536c617368696e675370616e73003b00000000000000010000005200000094e510002300000028543a3a4163636f756e7449642c20736c617368696e673a3a5370616e496e64657829736c617368696e673a3a5370616e5265636f72643c42616c616e63654f663c543e3e0000003b0000000000000001000000c800000017e510004f00000066e510002e0000003b000000000000000100000052000000d8e410003f0000003b00000000000000010000005c000000b4e4100024000000205468652076657273696f6e206f662073746f7261676520666f7220757067726164652e20546865206561726c696573742065726120666f72207768696368207765206861766520612070656e64696e672c20756e6170706c69656420736c6173682e205265636f72647320696e666f726d6174696f6e2061626f757420746865206d6178696d756d20736c617368206f6620612073746173682077697468696e206120736c617368696e67207370616e2c2061732077656c6c20617320686f77206d7563682072657761726420686173206265656e2070616964206f75742e20536c617368696e67207370616e7320666f72207374617368206163636f756e74732e20416c6c20736c617368696e67206576656e7473206f6e206e6f6d696e61746f72732c206d61707065642062792065726120746f20746865206869676865737420736c6173682076616c7565206f6620746865206572612e20416c6c20736c617368696e67206576656e7473206f6e2076616c696461746f72732c206d61707065642062792065726120746f20746865206869676865737420736c6173682070726f706f7274696f6e20616e6420736c6173682076616c7565206f6620746865206572612e2041206d617070696e672066726f6d207374696c6c2d626f6e646564206572617320746f207468652066697273742073657373696f6e20696e646578206f662074686174206572612e20416c6c20756e6170706c69656420736c61736865732074686174206172652071756575656420666f72206c617465722e2054686520616d6f756e74206f662063757272656e637920676976656e20746f207265706f7274657273206f66206120736c617368206576656e74207768696368207761732063616e63656c65642062792065787472616f7264696e6172792063697263756d7374616e6365732028652e672e20676f7665726e616e6365292e205468652070657263656e74616765206f662074686520736c617368207468617420697320646973747269627574656420746f207265706f72746572732e205468652072657374206f662074686520736c61736865642076616c75652069732068616e646c6564206279207468652060536c617368602e205472756520696620746865206e6578742073657373696f6e206368616e67652077696c6c2062652061206e657720657261207265676172646c657373206f6620696e6465782e2054686520616d6f756e74206f662062616c616e6365206163746976656c79206174207374616b6520666f7220656163682076616c696461746f7220736c6f742c2063757272656e746c792e2054686973206973207573656420746f20646572697665207265776172647320616e642070756e6973686d656e74732e205265776172647320666f72207468652063757272656e74206572612e205573696e6720696e6469636573206f662063757272656e7420656c6563746564207365742e205468652073657373696f6e20696e646578206174207768696368207468652063757272656e742065726120737461727465642e20546865207374617274206f66207468652063757272656e74206572612e205468652063757272656e742065726120696e6465782e205468652063757272656e746c7920656c65637465642076616c696461746f7220736574206b65796564206279207374617368206163636f756e742049442e204e6f6d696e61746f727320666f72206120706172746963756c6172206163636f756e74207468617420697320696e20616374696f6e207269676874206e6f772e20596f752063616e27742069746572617465207468726f7567682076616c696461746f727320686572652c2062757420796f752063616e2066696e64207468656d20696e207468652053657373696f6e206d6f64756c652e2054686973206973206b6579656420627920746865207374617368206163636f756e742e20546865206d61702066726f6d206e6f6d696e61746f72207374617368206b657920746f2074686520736574206f66207374617368206b657973206f6620616c6c2076616c696461746f727320746f206e6f6d696e6174652e204e4f54453a206973207072697661746520736f20746861742077652063616e20656e73757265207570677261646564206265666f726520616c6c207479706963616c2061636365737365732e204469726563742073746f7261676520415049732063616e207374696c6c2062797061737320746869732070726f74656374696f6e2e20546865206d61702066726f6d202877616e6e616265292076616c696461746f72207374617368206b657920746f2074686520707265666572656e636573206f6620746861742076616c696461746f722e2057686572652074686520726577617264207061796d656e742073686f756c64206265206d6164652e204b657965642062792073746173682e204d61702066726f6d20616c6c2028756e6c6f636b6564292022636f6e74726f6c6c657222206163636f756e747320746f2074686520696e666f20726567617264696e6720746865207374616b696e672e204d61702066726f6d20616c6c206c6f636b65642022737461736822206163636f756e747320746f2074686520636f6e74726f6c6c6572206163636f756e742e20416e792076616c696461746f72732074686174206d6179206e6576657220626520736c6173686564206f7220666f726369626c79206b69636b65642e20497427732061205665632073696e63652074686579277265206561737920746f20696e697469616c697a6520616e642074686520706572666f726d616e636520686974206973206d696e696d616c2028776520657870656374206e6f206d6f7265207468616e20666f757220696e76756c6e657261626c65732920616e64207265737472696374656420746f20746573746e6574732e204d696e696d756d206e756d626572206f66207374616b696e67207061727469636970616e7473206265666f726520656d657267656e637920636f6e646974696f6e732061726520696d706f7365642e2054686520696465616c206e756d626572206f66207374616b696e67207061727469636970616e74732e0000000000000010ee10000e00000000000000e76f11000c000000000000005c8f110020ee1000000000000000000030ee100001000000000000000000000038ee10000f0000000000000046c9100008000000000000005c8f110048ee1000000000000000000058ee1000010000000000000053657373696f6e7350657245726100003b0000000000000001000000c900000099ee10001c000000426f6e64696e674475726174696f6e003b0000000000000001000000ca00000060ee100039000000204e756d626572206f6620657261732074686174207374616b65642066756e6473206d7573742072656d61696e20626f6e64656420666f722e204e756d626572206f662073657373696f6e7320706572206572612e0000000000000094ef100007000000000000008c5211000100000000000000000000009cef1000010000000000000000000000a4ef10000a000000000000008c521100010000000000000000000000b0ef1000010000000000000000000000b8ef10000b000000000000008c521100010000000000000000000000c4ef1000010000000000000000000000ccef10000b00000000000000d8ef1000020000000000000000000000e8ef1000010000000000000000000000f0ef10000a00000000000000d8ef1000020000000000000000000000fcef100001000000000000004e616d655365740097f01000100000004e616d65466f7263656400007ef01000190000004e616d654368616e676564006af01000140000004e616d65436c656172656400e2521100090000009b1f11000700000036f01000340000004e616d654b696c6c6564000004f01000320000002041206e616d65207761732072656d6f76656420616e642074686520676976656e2062616c616e636520736c61736865642e2041206e616d652077617320636c65617265642c20616e642074686520676976656e2062616c616e63652072657475726e65642e2041206e616d6520776173206368616e6765642e2041206e616d652077617320666f726369626c79207365742e2041206e616d6520776173207365742e71202f2028712f246d617829203c202832202a20246d6178292e204d6163726f2070726576656e747320616e792074797065206265696e672063726561746564207468617420646f6573206e6f74207361746973667920746869733b207165640018f11000420000006f000000210000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f61726974686d657469632f7372632f7065725f7468696e67732e7273000000000000617474656d707420746f20646976696465206279207a65726f4661696c656420746f20636f6e76657274456e636f756e7465726564206572726f7220696e206d6967726174696f6e206f66205374616b696e673a3a4e6f6d696e61746f7273206d61702e5374616b696e673a3a4e6f6d696e61746f7273206d6170207265696e697469616c697a656446696e6973686564206d6967726174696e67205374616b696e672073746f7261676520746f2076312e5072697374696e65436f6465436f646553746f72616765436f6e7472616374496e666f4f664761735072696365000000000048f31000080000000000000050f3100003000000000000000000000068f3100001000000000000000000000070f310000c00000000000000301e11000200000000000000000000007cf3100001000000000000000000000084f310000a0000000000000090f3100001000000000000000000000098f31000010000000000000000000000a0f310000f00000000000000b0f31000010000000000000000000000b8f31000010000000000000000000000c0f310000a00000000000000ccf31000020000000000000000000000dcf31000020000000000000000000000646911000800000000000000ecf31000020000000000000000000000fcf3100001000000000000005472616e73666572e252110009000000e2521100090000009b1f11000700000027f510005a000000496e7374616e746961746564f0f4100037000000436f646553746f7265640000971f110004000000c2f410002e0000005363686564756c6555706461746564001e6111000300000092f4100030000000446973706174636865640000e252110009000000035311000400000027f410004e00000075f410001d000000e252110009000000e96011000700000004f410002300000020416e206576656e742066726f6d20636f6e7472616374206f66206163636f756e742e20412063616c6c2077617320646973706174636865642066726f6d2074686520676976656e206163636f756e742e2054686520626f6f6c207369676e616c73207768657468657220697420776173207375636365737366756c20657865637574696f6e206f72206e6f742e20547269676765726564207768656e207468652063757272656e74207363686564756c6520697320757064617465642e20436f646520776974682074686520737065636966696564206861736820686173206265656e2073746f7265642e20436f6e7472616374206465706c6f7965642062792061646472657373206174207468652073706563696669656420616464726573732e205472616e736665722068617070656e6564206066726f6d6020746f2060746f60207769746820676976656e206076616c7565602061732070617274206f662061206063616c6c60206f722060696e7374616e7469617465602e0000004d0000000800000004000000bf0000003b00000000000000010000003c000000acf510001c00000056617269616e74206973206e6576657220636f6e737472756374656473657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a09090971656400000000e8f610000800000000000000f0f6100001000000000000000000000008f7100010000000000000000000000088f710000a000000000000005c8f110000000000000000000000000094f710000a0000000000000000000000e4f710000900000000000000f0f7100001000000000000000000000008f810000d000000000000000000000070f810000a000000000000007cf81000020000000000000000000000acf810000c000000000000007365745f6e616d6500000000166711000400000000000000e96011000700000042fb10005700000099fb1000130000005c8f110000000000acfb1000580000005c8f11000000000004fc1000570000005bfc1000100000005c8f110000000000f9591100340000005c8f1100000000002d5a11000b000000385a110008000000b2f9100021000000d3f910001a000000edf910000d000000a65a11000c000000636c6561725f6e616d650000d5fa1000540000005c8f110000000000f9591100340000005c8f1100000000002d5a11000b000000385a11000800000029fb100019000000d3f910001a000000edf910000d000000a65a11000c0000006b696c6c5f6e616d6500000000000000faf910000600000000000000b55a11002300000000fa1000390000005c8f11000000000039fa1000520000008bfa1000130000005c8f11000000000066f910004c0000005c8f1100000000002d5a11000b000000385a1100080000009efa100037000000d3f910001a000000edf910000d000000a65a11000c000000666f7263655f6e616d65000000000000faf910000600000000000000b55a11002300000000000000166711000400000000000000e9601100070000000cf91000320000005c8f1100000000003ef91000280000005c8f11000000000066f910004c0000005c8f1100000000002d5a11000b000000385a110008000000b2f9100021000000d3f910001a000000edf910000d000000a65a11000c0000002053657420612074686972642d7061727479206163636f756e742773206e616d652077697468206e6f206465706f7369742e204e6f206c656e67746820636865636b696e6720697320646f6e65206f6e20746865206e616d652e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f526f6f745f206f72206d617463682060543a3a466f7263654f726967696e602e202d204174206d6f7374206f6e652062616c616e6365206f7065726174696f6e2e202d204f6e652073746f7261676520726561642f77726974652e202d204f6e65206576656e742e7461726765742052656d6f766520616e206163636f756e742773206e616d6520616e642074616b6520636861726765206f6620746865206465706f7369742e204661696c73206966206077686f6020686173206e6f74206265656e206e616d65642e20546865206465706f736974206973206465616c742077697468207468726f7567682060543a3a536c61736865646020696d62616c616e63652068616e646c65722e202d204f6e6520756e62616c616e6365642068616e646c6572202870726f6261626c7920612062616c616e6365207472616e736665722920436c65617220616e206163636f756e742773206e616d6520616e642072657475726e20746865206465706f7369742e204661696c7320696620746865206163636f756e7420776173206e6f74206e616d65642e202d204f6e652062616c616e6365206f7065726174696f6e2e2053657420616e206163636f756e742773206e616d652e20546865206e616d652073686f756c642062652061205554462d382d656e636f64656420737472696e6720627920636f6e76656e74696f6e2c2074686f75676820776520646f6e277420636865636b2069742e20546865206e616d65206d6179206e6f74206265206d6f7265207468616e2060543a3a4d61784c656e677468602062797465732c206e6f72206c657373207468616e2060543a3a4d696e4c656e677468602062797465732e20496620746865206163636f756e7420646f65736e277420616c726561647920686176652061206e616d652c207468656e206120666565206f6620605265736572766174696f6e4665656020697320726573657276656420696e20746865206163636f756e742e0000000000c4fc10000600000001010000000000000f5c11000c00000000000000cafc100017000000000000000000000000000000000000005c8f1100e4fc10000000000000000000f4fc10000100000000000000000000004e616d654f66285665633c75383e2c2042616c616e63654f663c543e290000003b0000000000000001000000cb000000fcfc10001c00000020546865206c6f6f6b7570207461626c6520666f72206e616d65732e00000000c0fd10000e00000000000000824711000c000000000000005c8f1100141111000000000000000000d0fd1000010000000000000000000000d8fd100009000000000000001e61110003000000000000005c8f1100e4fd10000000000000000000f4fd1000010000000000000000000000fcfd100009000000000000001e61110003000000000000005c8f110008fe1000000000000000000018fe100001000000000000005265736572766174696f6e466565000064fe1000110000004d696e4c656e6774680000003b0000000000000001000000cc00000042fe1000220000004d61784c656e6774680000003b0000000000000001000000cd00000020fe10002200000020546865206d6178696d756d206c656e6774682061206e616d65206d61792062652e20546865206d696e696d756d206c656e6774682061206e616d65206d61792062652e205265736572766174696f6e206665652e00000000000000a4fe10000500000000000000acfe1000010000000000000000000000c4fe10000100000000000000626174636800000000000000f8fe10000500000000000000fdfe100017000000ccfe10002c0000002053656e642061206261746368206f662064697370617463682063616c6c7320286f6e6c7920726f6f74292e63616c6c735665633c3c542061732054726169743e3a3a43616c6c3e64656661756c743a00000000f8ff10000f0000000000000008001100010000000000000000000000200011000300000000000000000000003800110008000000000000004000110002000000000000000000000070001100020000000000000000000000af651100040000000000000080001100040000000000000000000000e0001100070000000000000000000000180111000b0000000000000024011100040000000000000000000000840111000a0000000000000000000000d40111000f00000000000000e40111000200000000000000000000001402110005000000000000007570646174655f7363686564756c6500000000006408110008000000000000006c08110008000000f40711002d0000005c8f11000000000021081100430000007075745f636f646500000000a20511000900000000000000ab0511000c00000000000000f00711000400000000000000e9601100070000006407110057000000bb0711003500000000000000560311000400000000000000b55a11002300000000000000143611000500000000000000193611001500000000000000a20511000900000000000000ab0511000c00000000000000cb0511000400000000000000e960110007000000cf051100420000005c8f110000000000110611004a0000005b0611002c0000008706110046000000cd061100520000001f07110045000000696e7374616e74696174650000000000990511000900000000000000193611001500000000000000a20511000900000000000000ab0511000c00000000000000b70511000900000000000000c00511000b00000000000000cb0511000400000000000000e960110007000000780311006f0000005c8f110000000000e7031100260000005c8f1100000000000d041100500000005d041100410000009e0411005b000000f904110057000000500511002a0000007a0511001f000000636c61696d5f73757263686172676500000000005603110004000000000000000f5c11000c000000000000005a0311000a0000000000000064031100140000003c0211005c00000098021100450000005c8f110000000000dd0211004e0000002b0311002b00000020416c6c6f777320626c6f636b2070726f64756365727320746f20636c61696d206120736d616c6c2072657761726420666f72206576696374696e67206120636f6e74726163742e204966206120626c6f636b2070726f6475636572206661696c7320746f20646f20736f2c206120726567756c61722075736572732077696c6c20626520616c6c6f77656420746f20636c61696d20746865207265776172642e20496620636f6e7472616374206973206e6f742065766963746564206173206120726573756c74206f6620746869732063616c6c2c206e6f20616374696f6e73206172652074616b656e20616e64207468652073656e646572206973206e6f7420656c696769626c6520666f7220746865207265776172642e646573746175785f73656e6465724f7074696f6e3c543a3a4163636f756e7449643e20496e7374616e7469617465732061206e657720636f6e74726163742066726f6d207468652060636f646568617368602067656e65726174656420627920607075745f636f6465602c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e20496e7374616e74696174696f6e20697320657865637574656420617320666f6c6c6f77733a202d205468652064657374696e6174696f6e206164647265737320697320636f6d7075746564206261736564206f6e207468652073656e64657220616e642068617368206f662074686520636f64652e202d2054686520736d6172742d636f6e7472616374206163636f756e7420697320637265617465642061742074686520636f6d707574656420616464726573732e202d20546865206063746f725f636f64656020697320657865637574656420696e2074686520636f6e74657874206f6620746865206e65776c792d63726561746564206163636f756e742e204275666665722072657475726e656420202061667465722074686520657865637574696f6e206973207361766564206173207468652060636f646560206f6620746865206163636f756e742e205468617420636f64652077696c6c20626520696e766f6b656420202075706f6e20616e792063616c6c2072656365697665642062792074686973206163636f756e742e202d2054686520636f6e747261637420697320696e697469616c697a65642e656e646f776d656e746761735f6c696d6974436f6d706163743c4761733e636f64655f68617368436f6465486173683c543e64617461204d616b657320612063616c6c20746f20616e206163636f756e742c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e202a20496620746865206163636f756e74206973206120736d6172742d636f6e7472616374206163636f756e742c20746865206173736f63696174656420636f64652077696c6c20626520657865637574656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e202a20496620746865206163636f756e74206973206120726567756c6172206163636f756e742c20616e792076616c75652077696c6c206265207472616e736665727265642e202a204966206e6f206163636f756e742065786973747320616e64207468652063616c6c2076616c7565206973206e6f74206c657373207468616e20606578697374656e7469616c5f6465706f736974602c206120726567756c6172206163636f756e742077696c6c206265206372656174656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e2053746f7265732074686520676976656e2062696e617279205761736d20636f646520696e746f2074686520636861696e27732073746f7261676520616e642072657475726e73206974732060636f646568617368602e20596f752063616e20696e7374616e746961746520636f6e747261637473206f6e6c7920776974682073746f72656420636f64652e636f6465205570646174657320746865207363686564756c6520666f72206d65746572696e6720636f6e7472616374732e20546865207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652073746f726564207363686564756c652e7363686564756c655363686564756c65000000006c691100080000000000000000000000dc0a110003000000000000000000000000000000000000000000000000000000000000005c8f11004c0b11000000000000000000e00a110001000000000000000100000000000000746911000f00000000000000000000006c08110008000000000000000000000000000000000000000000000000000000000000005c8f1100e80a11000000000000000000f80a11000100000000000000010000000000000012f210000c0000000101000000000000c00511000b00000000000000e960110007000000000000000000000000000000000000005c8f1100000b11000000000000000000100b1100010000000000000000000000000000001ef210000b0000000101000000000000c00511000b00000000000000180b110016000000000000000000000000000000000000005c8f1100300b11000000000000000000400b110001000000000000000000000000000000836911000e0000000000000000000000480b110003000000000000000000000000000000000000000000000000000000000000005c8f11004c0b110000000000000000005c0b11000100000000000000010000000000000029f210000e00000001010000000000000f5c11000c00000000000000640b11000f000000000000000000000000000000000000005c8f1100740b11000000000000000000840b11000100000000000000000000000000000037f21000080000000000000000000000824711000c000000000000000000000000000000000000000000000000000000000000005c8f11008c0b110000000000000000009c0b110001000000000000000100000047617300d80c1100200000003b0000000000000001000000ce000000b30c1100250000003b0000000000000001000000cf0000005a0c1100590000007761736d3a3a5072656661625761736d4d6f64756c6500003b000000000000000100000052000000010c110059000000753634003b000000000000000100000053000000ec0b110015000000436f6e7472616374496e666f3c543e003b000000000000000100000052000000c20b11002a0000003b0000000000000001000000d0000000a40b11001e00000020546865207072696365206f66206f6e6520756e6974206f66206761732e2054686520636f6465206173736f6369617465642077697468206120676976656e206163636f756e742e20546865207375627472696520636f756e7465722e2041206d617070696e67206265747765656e20616e206f726967696e616c20636f6465206861736820616e6420696e737472756d656e746564207761736d20636f64652c20726561647920666f7220657865637574696f6e2e2041206d617070696e672066726f6d20616e206f726967696e616c20636f6465206861736820746f20746865206f726967696e616c20636f64652c20756e746f756368656420627920696e737472756d656e746174696f6e2e2043757272656e7420636f7374207363686564756c6520666f7220636f6e7472616374732e20476173207370656e7420736f2066617220696e207468697320626c6f636b2e000000007810110013000000000000009c6011000e000000000000005c8f11008c10110000000000000000009c101100040000000000000000000000bc1011001000000000000000824711000c000000000000005c8f1100141111000000000000000000cc101100010000000000000000000000d410110011000000000000001e61110003000000000000005c8f1100e81011000000000000000000f8101100020000000000000000000000081111000b00000000000000824711000c000000000000005c8f1100141111000000000000000000241111000100000000000000000000002c1111001100000000000000824711000c000000000000005c8f110040111100000000000000000050111100070000000000000000000000881111000f00000000000000824711000c000000000000005c8f1100981111000000000000000000a8111100020000000000000000000000b81111000b00000000000000824711000c000000000000005c8f1100341211000000000000000000c4111100010000000000000000000000cc1111000b00000000000000824711000c000000000000005c8f1100341211000000000000000000d8111100010000000000000000000000e01111001200000000000000824711000c000000000000005c8f1100341211000000000000000000f4111100010000000000000000000000fc1111001200000000000000824711000c000000000000005c8f110010121100000000000000000020121100010000000000000000000000281211000b00000000000000824711000c000000000000005c8f110034121100000000000000000044121100020000000000000000000000541211000b00000000000000dc0a110003000000000000005c8f110084121100000000000000000060121100020000000000000000000000701211001200000000000000dc0a110003000000000000005c8f110084121100000000000000000094121100020000000000000000000000a412110008000000000000001e61110003000000000000005c8f1100ac1211000000000000000000bc121100020000000000000000000000cc1211000c000000000000001e61110003000000000000005c8f1100d81211000000000000000000e8121100010000000000000000000000f01211000d00000000000000dc0a110003000000000000005c8f11000013110000000000000000001013110002000000000000005369676e6564436c61696d48616e6469636170003b0000000000000001000000d1000000c0181100380000005c8f110000000000f8181100430000003b1911001a000000546f6d6273746f6e654465706f7369748b1811003500000053746f7261676553697a654f66667365740000003b0000000000000001000000d20000000e18110054000000621811002900000052656e7442797465466565003b000000000000000100000056000000c11711004d00000052656e744465706f7369744f66667365740000003b0000000000000001000000d300000049161100410000008a161100160000005c8f110000000000a01611005a000000fa161100560000005017110053000000a31711001e000000537572636861726765526577617264003b0000000000000001000000d4000000f6151100390000002f1611001a0000005472616e7366657246656500d1151100250000004372656174696f6e46656500aa151100270000005472616e73616374696f6e42617365466565000073151100370000005472616e73616374696f6e4279746546656500003b0000000000000001000000640000003015110043000000436f6e7472616374466565003b000000000000000100000057000000d914110050000000291511000700000043616c6c42617365466565008414110047000000cb1411000e000000496e7374616e74696174654261736546656500003b0000000000000001000000d50000002e1411004e0000007c141100080000004d617844657074683b0000000000000001000000d6000000d41311004c000000201411000e0000004d617856616c756553697a653b0000000000000001000000d7000000861311004e000000426c6f636b4761734c696d69740000003b0000000000000001000000d80000002013110049000000691311001d00000020546865206d6178696d756d20616d6f756e74206f6620676173207468617420636f756c6420626520657870656e6465642070657220626c6f636b2e204120726561736f6e61626c652064656661756c742076616c75652069732031305f3030305f3030302e20546865206d6178696d756d2073697a65206f6620612073746f726167652076616c756520696e2062797465732e204120726561736f6e61626c652064656661756c74206973203136204b69422e20546865206d6178696d756d206e657374696e67206c6576656c206f6620612063616c6c2f696e7374616e746961746520737461636b2e204120726561736f6e61626c652064656661756c742076616c7565206973203130302e20546865206261736520666565206368617267656420666f7220696e7374616e74696174696e67206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203137352e20546865206261736520666565206368617267656420666f722063616c6c696e6720696e746f206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203133352e205468652066656520726571756972656420746f20696e7374616e7469617465206120636f6e747261637420696e7374616e63652e204120726561736f6e61626c652064656661756c742076616c75652069732032312e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b20746865207065722d6279746520706f7274696f6e2e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b2074686520626173652e205468652066656520726571756972656420746f2063726561746520616e206163636f756e742e205468652066656520726571756972656420746f206d616b652061207472616e736665722e205265776172642074686174206973207265636569766564206279207468652070617274792077686f736520746f75636820686173206c656420746f2072656d6f76616c206f66206120636f6e74726163742e2054686520616d6f756e74206f662066756e6473206120636f6e74726163742073686f756c64206465706f73697420696e206f7264657220746f206f66667365742074686520636f7374206f66206f6e6520627974652e204c6574277320737570706f736520746865206465706f73697420697320312c303030204255202862616c616e636520756e697473292f6279746520616e64207468652072656e7420697320312042552f627974652f6461792c207468656e206120636f6e7472616374207769746820312c3030302c3030302042552074686174207573657320312c303030206279746573206f662073746f7261676520776f756c6420706179206e6f2072656e742e20427574206966207468652062616c616e6365207265647563656420746f203530302c30303020425520616e64207468652073746f7261676520737461796564207468652073616d6520617420312c3030302c207468656e20697420776f756c6420706179203530302042552f6461792e205072696365206f6620612062797465206f662073746f7261676520706572206f6e6520626c6f636b20696e74657276616c2e2053686f756c642062652067726561746572207468616e20302e2053697a65206f66206120636f6e7472616374206174207468652074696d65206f6620696e7374616e746961696f6e2e205468697320697320612073696d706c652077617920746f20656e73757265207468617420656d70747920636f6e747261637473206576656e7475616c6c7920676574732064656c657465642e20546865206d696e696d756d20616d6f756e7420726571756972656420746f2067656e6572617465206120746f6d6273746f6e652e204e756d626572206f6620626c6f636b2064656c617920616e2065787472696e73696320636c61696d20737572636861726765206861732e205768656e20636c61696d207375726368617267652069732063616c6c656420627920616e2065787472696e736963207468652072656e7420697320636865636b656420666f722063757272656e745f626c6f636b202d2064656c617943616e6e6f7420726573746f726520746f20696e6578697374696e67206f7220616c69766520636f6e74726163744e616d6520746f6f2073686f72744e616d6520746f6f206c6f6e67626164206f726967696e4e6f74206e616d65646e6577207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e2063757272656e74496e76616c69642073757263686172676520636c61696d3a206f726967696e206d757374206265207369676e6564206f7220696e686572656e7420616e6420617578696c696172792073656e646572206f6e6c792070726f7669646564206f6e20696e686572656e74486561644f6644656c65676174696f6e7344656c65676174696f6e735265666572656e64756d496e666f4f66566f74654f6600000000000000441d110008000000000000004c1d11000200000000000000000000005c1d1100010000000000000000000000641d110006000000000000006c1d1100030000000000000000000000841d11000100000000000000000000008c1d11000e000000000000005c8f11000000000000000000000000009c1d1100010000000000000000000000a41d11000700000000000000ac1d1100020000000000000000000000bc1d1100010000000000000000000000c41d11000600000000000000cc1d1100010000000000000000000000d41d1100010000000000000000000000dc1d11000900000000000000cc1d1100010000000000000000000000e81d1100010000000000000000000000f01d11000900000000000000cc1d1100010000000000000000000000fc1d1100010000000000000000000000041e110008000000000000000c1e11000200000000000000000000001c1e1100010000000000000000000000241e11000900000000000000301e1100020000000000000000000000401e1100010000000000000000000000481e11000b000000000000008c521100010000000000000000000000541e11000100000000000000000000005c1e11000600000000000000641e11000300000000000000000000007c1e1100010000000000000000000000841e11000d00000000000000941e1100030000000000000000000000ac1e1100010000000000000000000000b41e11000c00000000000000941e1100030000000000000000000000c01e1100010000000000000000000000c81e11000f00000000000000d81e1100020000000000000000000000e81e1100010000000000000000000000f01e11000f00000000000000d81e1100020000000000000000000000001f1100010000000000000000000000081f11000e00000000000000181f1100040000000000000000000000381f1100010000000000000050726f706f7365646f221100090000009b1f11000700000086221100300000005461626c656400006f221100090000009b1f110007000000782211000e000000382211003700000045787465726e616c5461626c6564000012221100260000005374617274656400282011000f000000052211000d000000ed211100180000005061737365640000282011000f000000c12111002c0000004e6f74506173736564000000952111002c00000043616e63656c6c656400000074211100210000004578656375746564282011000f0000000353110004000000572111001d00000044656c656761746564000000e252110009000000e2521100090000001f21110038000000556e64656c65676174656400e52011003a0000005665746f65640000e252110009000000971f110004000000da2011000b000000b420110026000000507265696d6167654e6f746564000000971f110004000000e2521100090000009b1f1100070000007c20110038000000507265696d616765557365643720110045000000507265696d616765496e76616c696400971f110004000000282011000f000000e51f110043000000507265696d6167654d697373696e6700a21f110043000000507265696d6167655265617065640000971f110004000000e2521100090000009b1f110007000000e252110009000000401f1100570000002041207265676973746572656420707265696d616765207761732072656d6f76656420616e6420746865206465706f73697420636f6c6c6563746564206279207468652072656170657220286c617374206974656d292e4861736842616c616e636520412070726f706f73616c20636f756c64206e6f7420626520657865637574656420626563617573652069747320707265696d61676520776173206d697373696e672e20412070726f706f73616c20636f756c64206e6f7420626520657865637574656420626563617573652069747320707265696d6167652077617320696e76616c69642e5265666572656e64756d496e64657820412070726f706f73616c20707265696d616765207761732072656d6f76656420616e6420757365642028746865206465706f736974207761732072657475726e6564292e20412070726f706f73616c277320707265696d61676520776173206e6f7465642c20616e6420746865206465706f7369742074616b656e2e20416e2065787465726e616c2070726f706f73616c20686173206265656e207665746f65642e426c6f636b4e756d62657220416e206163636f756e74206861732063616e63656c6c656420612070726576696f75732064656c65676174696f6e206f7065726174696f6e2e20416e206163636f756e74206861732064656c65676174656420746865697220766f746520746f20616e6f74686572206163636f756e742e20412070726f706f73616c20686173206265656e20656e61637465642e2041207265666572656e64756d20686173206265656e2063616e63656c6c65642e20412070726f706f73616c20686173206265656e2072656a6563746564206279207265666572656e64756d2e20412070726f706f73616c20686173206265656e20617070726f766564206279207265666572656e64756d2e2041207265666572656e64756d2068617320626567756e2e566f74655468726573686f6c6420416e2065787465726e616c2070726f706f73616c20686173206265656e207461626c65642e2041207075626c69632070726f706f73616c20686173206265656e207461626c656420666f72207265666572656e64756d20766f74652e50726f70496e6465785665633c4163636f756e7449643e2041206d6f74696f6e20686173206265656e2070726f706f7365642062792061207075626c6963206163636f756e742e44697370617463685175657565507265696d61676573566f74657273466f725075626c696350726f70734465706f7369744f664e6f207075626c69632070726f706f73616c732077616974696e674e65787445787465726e616c4e6f2065787465726e616c2070726f706f73616c2077616974696e6700000000c82611000700000000000000d026110002000000000000000000000000271100060000000000000000000000302711000600000000000000382711000100000000000000000000005027110006000000000000000000000080271100040000000000000084271100020000000000000000000000b4271100070000000000000000000000ec2711000a0000000000000084271100020000000000000000000000f827110007000000000000000000000030281100100000000000000040281100010000000000000000000000582811000200000000000000000000006828110010000000000000007828110001000000000000000000000090281100020000000000000000000000a0281100190000000000000078281100010000000000000000000000bc281100050000000000000000000000e4281100180000000000000078281100010000000000000000000000fc281100050000000000000000000000242911000a000000000000003029110003000000000000000000000078291100090000000000000000000000c02911000d0000000000000078281100010000000000000000000000d0291100010000000000000000000000d82911001100000000000000ec291100010000000000000000000000042a11000100000000000000000000000c2a11000d000000000000001c2a1100010000000000000000000000342a11000100000000000000000000003c2a11000900000000000000482a1100010000000000000000000000602a1100050000000000000000000000882a11000c000000000000005c8f1100000000000000000000000000942a1100050000000000000000000000bc2a11000c00000000000000482a1100010000000000000000000000c82a1100050000000000000000000000f02a11000800000000000000f82a1100020000000000000000000000282b1100050000000000000000000000502b11000a000000000000005c8f11000000000000000000000000005c2b1100050000000000000000000000842b110016000000000000005c8f11000000000000000000000000009c2b1100010000000000000000000000a42b11000d00000000000000b42b1100010000000000000000000000cc2b1100020000000000000000000000dc2b11001600000000000000b42b1100010000000000000000000000f42b1100020000000000000000000000042c11000d0000000000000078281100010000000000000000000000142c1100050000000000000070726f706f736500000000004c3211000d000000000000005932110007000000000000001436110005000000000000001936110015000000aa351100280000005c8f1100000000002d5a11000b000000385a110008000000f435110020000000a65a11000c0000007365636f6e64000000000000d85a11000800000000000000e235110012000000aa351100280000005c8f1100000000002d5a11000b000000385a110008000000d235110010000000a65a11000c000000766f746500000000d42f11000900000000000000dd2f11001800000000000000802711000400000000000000a6351100040000002a3511004d000000773511002f0000005c8f1100000000002d5a11000b000000385a1100080000000b3511001f000000a65a11000c00000070726f78795f766f746500007934110054000000cd3411003e0000005c8f1100000000002d5a11000b000000385a1100080000000b3511001f000000a65a11000c000000656d657267656e63795f63616e63656c00000000d42f11000900000000000000282011000f0000002534110054000000193411000c00000065787465726e616c5f70726f706f7365000000004c3211000d000000000000005932110007000000cd3311004c000000193411000c00000065787465726e616c5f70726f706f73655f6d616a6f726974790000005f33110056000000b5331100180000005c8f110000000000e532110053000000383311002700000065787465726e616c5f70726f706f73655f64656661756c747232110052000000c4321100210000005c8f110000000000e5321100530000003833110027000000666173745f747261636b0000000000004c3211000d00000000000000593211000700000000000000603211000d000000000000009c6011000e000000000000006d32110005000000000000009c6011000e00000024301100540000007830110059000000d13011003b0000005c8f1100000000000c3111003e0000004a31110058000000a231110026000000c8311100550000001d3211002f0000007665746f5f65787465726e616c000000f52f11002f00000063616e63656c5f7265666572656e64756d00000000000000d42f11000900000000000000dd2f110018000000bf2f11001500000063616e63656c5f71756575656400000000000000ba2f11000500000000000000282011000f000000922f1100280000007365745f70726f7879000000000000008d2f110005000000000000000f5c11000c000000672f1100260000005c8f1100000000002d5a11000b000000df2e110016000000a65a11000c00000072657369676e5f70726f7879412f1100260000005c8f1100000000002d5a11000b000000312f110010000000a65a11000c00000072656d6f76655f70726f78790b2f1100260000005c8f1100000000002d5a11000b000000312f110010000000a65a11000c00000064656c656761746500000000f52e110002000000000000000f5c11000c00000000000000f72e11000a00000000000000012f11000a000000d02e11000f0000005c8f1100000000002d5a11000b000000df2e110016000000a65a11000c000000756e64656c65676174650000bf2e1100110000005c8f1100000000002d5a11000b000000385a110008000000a65a11000c000000636c6561725f7075626c69635f70726f706f73616c7300007f2e1100400000006e6f74655f707265696d616765000000000000006f2e11001000000000000000e960110007000000ce2d110058000000262e1100490000006e6f74655f696d6d696e656e745f707265696d6167650000502d110051000000a12d11002d000000726561705f707265696d6167650000003c2c11003d0000005c8f110000000000792c110054000000cd2c110057000000242d11002c0000002052656d6f766520616e20657870697265642070726f706f73616c20707265696d61676520616e6420636f6c6c65637420746865206465706f7369742e20546869732077696c6c206f6e6c7920776f726b2061667465722060566f74696e67506572696f646020626c6f636b732066726f6d207468652074696d6520746861742074686520707265696d61676520776173206e6f7465642c2069662069742773207468652073616d65206163636f756e7420646f696e672069742e2049662069742773206120646966666572656e74206163636f756e742c207468656e206974276c6c206f6e6c7920776f726b20616e206164646974696f6e616c2060456e6163746d656e74506572696f6460206c617465722e2052656769737465722074686520707265696d61676520666f7220616e207570636f6d696e672070726f706f73616c2e2054686973207265717569726573207468652070726f706f73616c20746f20626520696e207468652064697370617463682071756575652e204e6f206465706f736974206973206e65656465642e2052656769737465722074686520707265696d61676520666f7220616e207570636f6d696e672070726f706f73616c2e205468697320646f65736e27742072657175697265207468652070726f706f73616c20746f20626520696e207468652064697370617463682071756575652062757420646f657320726571756972652061206465706f7369742c2072657475726e6564206f6e636520656e61637465642e656e636f6465645f70726f706f73616c205665746f20616e6420626c61636b6c697374207468652070726f706f73616c20686173682e204d7573742062652066726f6d20526f6f74206f726967696e2e20556e64656c656761746520766f74652e2044656c656761746520766f74652e202d204f6e6520657874726120444220656e7472792e746f636f6e76696374696f6e436f6e76696374696f6e20436c656172207468652070726f78792e2043616c6c6564206279207468652073746173682e202d204f6e6520444220636c6561722e20436c656172207468652070726f78792e2043616c6c6564206279207468652070726f78792e205370656369667920612070726f78792e2043616c6c6564206279207468652073746173682e70726f78792043616e63656c20612070726f706f73616c2071756575656420666f7220656e6163746d656e742e77686963682052656d6f76652061207265666572656e64756d2e7265665f696e646578436f6d706163743c5265666572656e64756d496e6465783e205665746f20616e6420626c61636b6c697374207468652065787465726e616c2070726f706f73616c20686173682e205363686564756c65207468652063757272656e746c792065787465726e616c6c792d70726f706f736564206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c656420696d6d6564696174656c792e204966207468657265206973206e6f2065787465726e616c6c792d70726f706f736564207265666572656e64756d2063757272656e746c792c206f72206966207468657265206973206f6e6520627574206974206973206e6f742061206d616a6f726974792d63617272696573207265666572656e64756d207468656e206974206661696c732e202d206070726f706f73616c5f68617368603a205468652068617368206f66207468652063757272656e742065787465726e616c2070726f706f73616c2e202d2060766f74696e675f706572696f64603a2054686520706572696f64207468617420697320616c6c6f77656420666f7220766f74696e67206f6e20746869732070726f706f73616c2e20496e6372656173656420746f20202060456d657267656e6379566f74696e67506572696f646020696620746f6f206c6f772e202d206064656c6179603a20546865206e756d626572206f6620626c6f636b20616674657220766f74696e672068617320656e64656420696e20617070726f76616c20616e6420746869732073686f756c64206265202020656e61637465642e205468697320646f65736e277420686176652061206d696e696d756d20616d6f756e742e70726f706f73616c5f68617368543a3a48617368766f74696e675f706572696f6464656c6179205363686564756c652061206e656761746976652d7475726e6f75742d62696173207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20556e6c696b65206065787465726e616c5f70726f706f7365602c20626c61636b6c697374696e6720686173206e6f20656666656374206f6e207468697320616e64206974206d6179207265706c6163652061207072652d7363686564756c6564206065787465726e616c5f70726f706f7365602063616c6c2e205363686564756c652061206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e205363686564756c652061207265666572656e64756d20746f206265207461626c6564206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e205363686564756c6520616e20656d657267656e63792063616e63656c6c6174696f6e206f662061207265666572656e64756d2e2043616e6e6f742068617070656e20747769636520746f207468652073616d6520566f746520696e2061207265666572656e64756d206f6e20626568616c66206f6620612073746173682e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b20206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e202d204f6e65204442206368616e67652c206f6e6520444220656e7472792e20566f746520696e2061207265666572656e64756d2e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e566f74652050726f706f736520612073656e73697469766520616374696f6e20746f2062652074616b656e2e202d204f6e6520444220656e7472792e436f6d706163743c50726f70496e6465783e202d2054776f204442206368616e6765732c206f6e6520444220656e7472792e76616c7565436f6d706163743c42616c616e63654f663c543e3e0000000000001c6b11000f00000000000000000000006f22110009000000000000000000000000000000000000000000000000000000000000005c8f1100843c11000000000000000000b03b110001000000000000000100000000000000d52211000b0000000000000000000000b83b110027000000000000000000000000000000000000000000000000000000000000005c8f1100203d11000000000000000000e03b110001000000000000000100000000000000c3221100090000000101000000000000593211000700000000000000e83b110035000000000000000000000000000000000000005c8f1100203c11000000000000000000303c110002000000000000000000000000000000e02211000900000001010000000000006f2211000900000000000000403c110021000000000000000000000000000000000000005c8f1100643c11000000000000000000743c1100010000000000000000000000000000002b6b11000f0000000000000000000000282011000f000000000000000000000000000000000000000000000000000000000000005c8f1100843c110000000000000000007c3c110001000000000000000100000000000000436b11000d0000000000000000000000282011000f000000000000000000000000000000000000000000000000000000000000005c8f1100843c11000000000000000000943c1100020000000000000001000000000000006b1a1100100000000101000000000000282011000f00000000000000a43c110027000000000000000000000000000000000000005c8f1100903d11000000000000000000cc3c110001000000000000000000000000000000b62211000d0000000000000000000000d43c11002f000000000000000000000000000000000000000000000000000000000000005c8f1100203d11000000000000000000043d110001000000000000000100000000000000cc221100090000000101000000000000282011000f000000000000000c3d110011000000000000000000000000000000000000005c8f1100203d11000000000000000000303d1100010000000000000001000000000000007b1a1100060000000101000000000000383d11001f00000000000000a635110004000000000000000000000000000000000000005c8f1100583d11000000000000000000683d110004000000000000000100000000000000883d11000500000001010000000000000f5c11000c000000000000000f5c11000c000000000000000000000000000000000000005c8f1100903d11000000000000000000a03d110002000000000000000000000000000000601a11000b00000001010100000000000f5c11000c00000000000000b03d11001a000000000000000000000000000000000000005c8f1100cc3d11000000000000000000dc3d110001000000000000000100000000000000506b11001500000000000000000000000353110004000000000000000000000000000000000000000000000000000000000000005c8f1100983e11000000000000000000e43d110002000000000000000100000000000000042311000c0000000000000000000000f43d110018000000000000000000000000000000000000000000000000000000000000005c8f11000c3e110000000000000000001c3e1100040000000000000000000000000000003c3e1100090000000101000000000000593211000700000000000000453e110023000000000000000000000000000000000000005c8f1100683e11000000000000000000783e110002000000000000000000000000000000883e11000d00000001010000000000005932110007000000000000000353110004000000000000000000000000000000000000005c8f1100983e11000000000000000000a83e11000100000000000000010000003f4511003d0000005665633c2850726f70496e6465782c20543a3a486173682c20543a3a4163636f756e744964293e00f744110048000000285665633c75383e2c20543a3a4163636f756e7449642c2042616c616e63654f663c543e2c20543a3a426c6f636b4e756d626572290000003b0000000000000001000000d90000006644110058000000be441100390000002842616c616e63654f663c543e2c205665633c543a3a4163636f756e7449643e290000003b0000000000000001000000cb0000004544110021000000f94311004c0000003b00000000000000010000005c0000007943110049000000c2431100370000005265666572656e64756d496e666f3c543a3a426c6f636b4e756d6265722c20543a3a486173683e004c4311002d0000005665633c28543a3a426c6f636b4e756d6265722c20543a3a486173682c205265666572656e64756d496e646578293e00fc421100500000005665633c543a3a4163636f756e7449643e0000003b000000000000000100000055000000d342110029000000285265666572656e64756d496e6465782c20543a3a4163636f756e74496429003b0000000000000001000000520000009441110058000000ec411100530000003f42110057000000964211003d00000050726f78790000003b000000000000000100000052000000264111004c000000724111002200000028543a3a4163636f756e7449642c20436f6e76696374696f6e2900003b0000000000000001000000da000000d6401100500000007640110056000000cc4011000a00000028543a3a486173682c20566f74655468726573686f6c64293b000000000000000100000052000000883f110056000000de3f11005500000033401100290000005c4011001a000000426c61636b6c69737428543a3a426c6f636b4e756d6265722c205665633c543a3a4163636f756e7449643e293b0000000000000001000000cb000000fa3e1100540000004e3f11003a00000043616e63656c6c6174696f6e730000003b000000000000000100000052000000b03e11004a000000205265636f7264206f6620616c6c2070726f706f73616c7320746861742068617665206265656e207375626a65637420746f20656d657267656e63792063616e63656c6c6174696f6e2e2041207265636f7264206f662077686f207665746f656420776861742e204d6170732070726f706f73616c206861736820746f206120706f737369626c65206578697374656e7420626c6f636b206e756d6265722028756e74696c207768656e206974206d6179206e6f742062652072657375626d69747465642920616e642077686f207665746f65642069742e20546865207265666572656e64756d20746f206265207461626c6564207768656e6576657220697420776f756c642062652076616c696420746f207461626c6520616e2065787465726e616c2070726f706f73616c2e20546869732068617070656e73207768656e2061207265666572656e64756d206e6565647320746f206265207461626c656420616e64206f6e65206f662074776f20636f6e646974696f6e7320617265206d65743a202d20604c6173745461626c656457617345787465726e616c60206973206066616c7365603b206f72202d20605075626c696350726f70736020697320656d7074792e205472756520696620746865206c617374207265666572656e64756d207461626c656420776173207375626d69747465642065787465726e616c6c792e2046616c7365206966206974207761732061207075626c69632070726f706f73616c2e2047657420746865206163636f756e742028616e64206c6f636b20706572696f64732920746f20776869636820616e6f74686572206163636f756e742069732064656c65676174696e6720766f74652e2057686f2069732061626c6520746f20766f746520666f722077686f6d2e2056616c7565206973207468652066756e642d686f6c64696e67206163636f756e742c206b65792069732074686520766f74652d7472616e73616374696f6e2d73656e64696e67206163636f756e742e204765742074686520766f746520696e206120676976656e207265666572656e64756d206f66206120706172746963756c617220766f7465722e2054686520726573756c74206973206d65616e696e6766756c206f6e6c792069662060766f746572735f666f726020696e636c756465732074686520766f746572207768656e2063616c6c6564207769746820746865207265666572656e64756d2028796f75276c6c20676574207468652064656661756c742060566f7465602076616c7565206f7468657277697365292e20496620796f7520646f6e27742077616e7420746f20636865636b2060766f746572735f666f72602c207468656e20796f752063616e20616c736f20636865636b20666f722073696d706c65206578697374656e636520776974682060566f74654f663a3a657869737473602066697273742e204765742074686520766f7465727320666f72207468652063757272656e742070726f706f73616c2e205175657565206f66207375636365737366756c207265666572656e646120746f20626520646973706174636865642e2053746f726564206f72646572656420627920626c6f636b206e756d6265722e20496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e20546865206c6f77657374207265666572656e64756d20696e64657820726570726573656e74696e6720616e20756e62616b6564207265666572656e64756d2e20457175616c20746f20605265666572656e64756d436f756e74602069662074686572652069736e2774206120756e62616b6564207265666572656e64756d2e20546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e6461207374617274656420736f206661722e2054686f73652077686f2068617665206c6f636b65642061206465706f7369742e204d6170206f662068617368657320746f207468652070726f706f73616c20707265696d6167652c20616c6f6e6720776974682077686f207265676973746572656420697420616e64207468656972206465706f7369742e2054686520626c6f636b206e756d6265722069732074686520626c6f636b20617420776869636820697420776173206465706f73697465642e20546865207075626c69632070726f706f73616c732e20556e736f727465642e20546865207365636f6e64206974656d206973207468652070726f706f73616c277320686173682e20546865206e756d626572206f6620287075626c6963292070726f706f73616c7320746861742068617665206265656e206d61646520736f206661722e00000000044711000f000000000000009c6011000e000000000000005c8f1100144711000000000000000000244711000500000000000000000000004c4711000c000000000000009c6011000e000000000000005c8f1100e8471100000000000000000058471100010000000000000000000000604711000c000000000000009c6011000e000000000000005c8f1100e847110000000000000000006c471100010000000000000000000000744711000e00000000000000824711000c000000000000005c8f1100904711000000000000000000a0471100010000000000000000000000a847110015000000000000009c6011000e000000000000005c8f1100c04711000000000000000000d0471100010000000000000000000000d84711000d000000000000009c6011000e000000000000005c8f1100e84711000000000000000000f8471100010000000000000000000000004811001300000000000000824711000c000000000000005c8f1100144811000000000000000000244811000100000000000000456e6163746d656e74506572696f64003b0000000000000001000000db000000bd4911005c0000005c8f110000000000194a11004c000000654a11005a000000bf4a1100270000004c61756e6368506572696f648449110039000000566f74696e67506572696f64564911002e0000004d696e696d756d4465706f73697442616c616e63654f663c543e00003b0000000000000001000000dc000000094911004d000000456d657267656e6379566f74696e67506572696f640000003b0000000000000001000000dd000000ce4811003b000000436f6f6c6f6666506572696f640000003b0000000000000001000000de0000007648110058000000507265696d616765427974654465706f736974003b0000000000000001000000570000002c4811004a0000002054686520616d6f756e74206f662062616c616e63652074686174206d757374206265206465706f7369746564207065722062797465206f6620707265696d6167652073746f7265642e20506572696f6420696e20626c6f636b7320776865726520616e2065787465726e616c2070726f706f73616c206d6179206e6f742062652072652d7375626d6974746564206166746572206265696e67207665746f65642e204d696e696d756d20766f74696e6720706572696f6420616c6c6f77656420666f7220616e20656d657267656e6379207265666572656e64756d2e20546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e20486f77206f6674656e2028696e20626c6f636b7329206e6577207075626c6963207265666572656e646120617265206c61756e636865642e20546865206d696e696d756d20706572696f64206f66206c6f636b696e6720616e642074686520706572696f64206265747765656e20612070726f706f73616c206265696e6720617070726f76656420616e6420656e61637465642e2049742073686f756c642067656e6572616c6c792062652061206c6974746c65206d6f7265207468616e2074686520756e7374616b6520706572696f6420746f20656e73757265207468617420766f74696e67207374616b657273206861766520616e206f70706f7274756e69747920746f2072656d6f7665207468656d73656c7665732066726f6d207468652073797374656d20696e207468652063617365207768657265207468657920617265206f6e20746865206c6f73696e672073696465206f66206120766f74652e76616c756520746f6f206c6f7770726f706f73657227732062616c616e636520746f6f206c6f7763616e206f6e6c79207365636f6e6420616e206578697374696e672070726f706f73616c7365636f6e64657227732062616c616e636520746f6f206c6f776e6f7420612070726f787963616e6e6f742063616e63656c207468652073616d652070726f706f73616c207477696365756e6b6e6f776e20696e64657870726f706f73616c20616c7265616479206d61646570726f706f73616c207374696c6c20626c61636b6c69737465646e6f2070726f706f73616c206d6164656e6578742065787465726e616c2070726f706f73616c206e6f742073696d706c65206d616a6f72697479696e76616c696420686173686e6f2065787465726e616c2070726f706f73616c756e6b6e6f776e2070726f706f73616c6964656e74697479206d6179206e6f74207665746f20612070726f706f73616c207477696365616c726561647920612070726f787977726f6e672070726f78796e6f742064656c656761746564707265696d61676520616c7265616479206e6f7465646e6f7420696d6d696e656e74746f6f206561726c79696d6d696e656e746e6f7420666f756e6470726f706f73616c206e6f7420666f756e64766f746520676976656e20666f7220696e76616c6964207265666572656e64756d2e557064617465526563656e7448696e747346696e616c2068696e74206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b46696e616c697a6564206865696768742061626f766520626c6f636b206e756d62657200370000000400000004000000df000000e0000000e1000000370000000400000004000000e20000004f72646572656448696e74734d656469616e616c77617973206174206c65617374206f6e6520726563656e742073616d706c653b20716564726563656e7420616e64206f72646572656420636f6e7461696e207468652073616d65206974656d733b2071656400003700000004000000040000002a0000007072756e696e672064696374617465642062792077696e646f775f73697a6520776869636820697320616c776179732073617475726174656420617420313b2071656400404e1100230000005c8f110000000000634e11001e0000004552524f523a20436f727275707465642073746174653a206c696e6b6564206d6170203a206e6578742076616c756520646f65736e277420657869737420617420000000404e1100230000005c8f1100000000009c4e1100220000003a2070726576696f75732076616c756520646f65736e2774206578697374206174200000404e1100230000005c8f110000000000d84e11001e0000003a20686561642076616c756520646f65736e277420657869737420617420506172656e7420686173682073686f756c642062652076616c69642e5472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642e00008f4f110032000000446967657374206974656d206d757374206d6174636820746861742063616c63756c617465642e53746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e4e756d626572206f6620646967657374206974656d73206d757374206d6174636820746861742063616c63756c617465642e00000000000000f04f11000a00000000000000fc4f110001000000000000000000000014501100020000000000000066696e616c5f68696e740000000000007c50110004000000000000008050110017000000245011003d000000615011001b0000002048696e7420746861742074686520617574686f72206f66207468697320626c6f636b207468696e6b732074686520626573742066696e616c697a656420626c6f636b2069732074686520676976656e206e756d6265722e68696e74436f6d706163743c543a3a426c6f636b4e756d6265723e0000000000085111000a000000000000009c6011000e000000000000005c8f1100145111000000000000000000245111000100000000000000000000002c5111000d000000000000009c6011000e000000000000005c8f11003c51110000000000000000004c511100010000000000000057696e646f7753697a6500003b0000000000000001000000e30000009b511100460000005265706f72744c6174656e63790000003b0000000000000001000000e40000005451110047000000205468652064656c617920616674657220776869636820706f696e74207468696e6773206265636f6d6520737573706963696f75732e2044656661756c7420697320313030302e20546865206e756d626572206f6620726563656e742073616d706c657320746f206b6565702066726f6d207468697320636861696e2e2044656661756c74206973203130312e000000000000006852110005000000000000007052110001000000000000000000000078521100010000000000000000000000805211000a000000000000008c521100010000000000000000000000945211000100000000000000000000009c5211000a000000000000007052110001000000000000000000000078521100010000000000000053756469640000000353110004000000eb521100180000004b65794368616e6765640000e252110009000000a65211003c0000005375646f4173446f6e6520546865207375646f6572206a757374207377697463686564206964656e746974793b20746865206f6c64206b657920697320737570706c6965642e4163636f756e7449642041207375646f206a75737420746f6f6b20706c6163652e626f6f6c476f7373697041740000000000945311001100000000000000a8531100010000000000000000000000b0531100010000000000000000000000b853110007000000000000005c8f1100000000000000000000000000c0531100010000000000000000000000c85311000b00000000000000d4531100010000000000000000000000dc53110001000000000000004865617274626561745265636569766564000000ad5411000b0000007d54110030000000416c6c476f6f64004854110035000000536f6d654f66666c696e65003054110018000000e45311004c0000002041742074686520656e64206f66207468652073657373696f6e2c206174206c65617374206f6e63652076616c696461746f722077617320666f756e6420746f206265206f66666c696e652e5665633c4964656e74696669636174696f6e5475706c653e2041742074686520656e64206f66207468652073657373696f6e2c206e6f206f6666656e63652077617320636f6d6d69747465642e2041206e657720686561727462656174207761732072656365697665642066726f6d2060417574686f72697479496460417574686f726974794964c85411003a00000033000000120000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f72756e74696d652f7372632f63757276652e7273417574686f726564426c6f636b737061726974792f696d2d6f6e6c696e652d776f726b65722d73746174757300008d551100080000009555110020000000696d6f6e6c696e6570616c6c65745f696d5f6f6e6c696e652f686f6d652f6461766964642f6465762f7375627374726174652f6672616d652f696d2d6f6e6c696e652f7372632f6c69622e72735b696e6465783a205d205265706f7274696e6720696d2d6f6e6c696e6520617420626c6f636b3a20707265636f6e646974696f6e3a20616c6c20696d706f7274732073686f756c6420626520636865636b656420616761696e737420746865207369676e617475726573206f6620636f72726573706f6e64696e670a09090909090966756e6374696f6e7320646566696e65642062792060646566696e655f656e762160206d6163726f206279207468652075736572206f6620746865206d6163726f3b0a0909090909097369676e617475726573206f662074686573652066756e6374696f6e7320646566696e6564206279206024706172616d73603b0a09090909090963616c6c7320616c77617973206d616465207769746820617267756d656e7473207479706573206f662077686963682061726520646566696e65642062792074686520636f72726573706f6e64696e6720696d706f7274733b0a09090909090974687573207479706573206f6620617267756d656e74732073686f756c6420626520657175616c20746f2074797065206c69737420696e206024706172616d736020616e640a0909090909096c656e677468206f6620617267756d656e74206c69737420616e642024706172616d732073686f756c6420626520657175616c3b0a0909090909097468757320746869732063616e206e6576657220626520604e6f6e65603b0a0909090909097165643b0a09090909090900000000000000305811000400000000000000345811000100000000000000000000004c5811000a00000000000000000000009c5811000700000000000000a4581100010000000000000000000000bc5811000900000000000000000000000459110007000000000000000c5911000200000000000000000000003c5911000b000000000000007375646f00000000d85a11000800000000000000e05a110010000000615b11004e0000005c8f110000000000f9591100340000005c8f1100000000002d5a11000b000000385a110008000000405a110019000000595a110018000000715a110035000000a65a11000c0000007365745f6b657900000000005e5b11000300000000000000b55a110023000000f05a11005d0000005c8f110000000000f9591100340000005c8f1100000000002d5a11000b000000385a110008000000405a1100190000004d5b110011000000a65a11000c0000007375646f5f61730000000000b25a11000300000000000000b55a11002300000000000000d85a11000800000000000000e05a1100100000009459110054000000e8591100110000005c8f110000000000f9591100340000005c8f1100000000002d5a11000b000000385a110008000000405a110019000000595a110018000000715a110035000000a65a11000c0000002041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c207769746820605369676e656460206f726967696e2066726f6d206120676976656e206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2e2023203c7765696768743e202d204f2831292e202d204c696d697465642073746f726167652072656164732e202d204f6e6520444220777269746520286576656e74292e202d20556e6b6e6f776e20776569676874206f662064657269766174697665206070726f706f73616c6020657865637574696f6e2e2023203c2f7765696768743e77686f3c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f7572636570726f706f73616c426f783c543a3a50726f706f73616c3e2041757468656e74696361746573207468652063757272656e74207375646f206b657920616e6420736574732074686520676976656e204163636f756e7449642028606e6577602920617320746865206e6577207375646f206b65792e202d204f6e65204442206368616e67652e6e65772041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c20776974682060526f6f7460206f726967696e2e5375646f00000000000c5c11000300000000000000000000000f5c11000c000000000000000000000000000000000000000000000000000000000000005c8f11001c5c110000000000000000002c5c11000100000000000000010000004b6579543a3a4163636f756e744964003b0000000000000001000000bc000000345c1100210000002054686520604163636f756e74496460206f6620746865207375646f206b65792e6d656d6f727976616c69646174696f6e3a20696d706f727420656e74727920706f696e747320746f2061206e6f6e2d6578697374656e74207479706543616e6e6f7420696d706f727420676c6f62616c736d6f64756c6520696d706f7274732061206e6f6e2d6578697374656e742066756e6374696f6e6d6f64756c6520696d706f72747320606578745f7072696e746c6e60206275742064656275672066656174757265732064697361626c656443616e6e6f7420696d706f7274207461626c65736d6f64756c652068617320696d706f7274732066726f6d2061206e6f6e2d27656e7627206e616d6573706163654d656d6f727920696d706f7274206d757374206861766520746865206669656c64206e616d6520276d656d6f7279274d756c7469706c65206d656d6f727920696d706f72747320646566696e65644d6178696d756d206e756d626572206f662070616765732073686f756c6420626520616c77617973206465636c617265642e52657175657374656420696e697469616c206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520726571756573746564206d6178696d756d4d6178696d756d206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520636f6e66696775726564206d6178696d756d2e72657475726e2074797065206572726f7276616c69646174696f6e206572726f72647572696e6720657865637574696f6e00000000ac5e11000900000000000000b85e11000200000000000000000000005c8f1100000000000000000068656172746265617400000000000000ac5e11000900000000000000e85e11001900000000000000015f11000a000000000000000b5f11002f0000004865617274626561743c543a3a426c6f636b4e756d6265723e5f7369676e61747572653c543a3a417574686f7269747949642061732052756e74696d654170705075626c69633e3a3a5369676e6174757265000000000000075311000800000000000000000000009c6011000e000000000000000000000000000000000000000000000000000000000000005c8f1100246111000000000000000000ac6011000100000000000000010000000000000020631100040000000000000000000000b460110013000000000000000000000000000000000000000000000000000000000000005c8f1100c86011000000000000000000d860110001000000000000000100000000000000ab6d1100120000000201010000000000e76f11000c00000000000000e06011000900000000000000e960110007000000000000005c8f1100f060110000000000000000000061110002000000000000000000000000000000025511000e0000000201010000000000e76f11000c00000000000000106111000e000000000000001e61110003000000000000005c8f110024611100000000000000000034611100020000000000000001000000543a3a426c6f636b4e756d62657200004b621100280000005665633c543a3a417574686f7269747949643e003b000000000000000100000055000000176211003400000041757468496e6465785665633c75383e3b0000000000000001000000cf000000bb61110039000000f461110023000000543a3a56616c696461746f7249647533320000003b00000000000000010000005c0000004461110045000000896111003200000020466f7220656163682073657373696f6e20696e6465782c207765206b6565702061206d617070696e67206f662060543a3a56616c696461746f7249646020746f20746865206e756d626572206f6620626c6f636b7320617574686f7265642062792074686520676976656e20617574686f726974792e20466f7220656163682073657373696f6e20696e6465782c207765206b6565702061206d617070696e67206f66206041757468496e6465786020746f20606f6666636861696e3a3a4f70617175654e6574776f726b5374617465602e205468652063757272656e7420736574206f66206b6579732074686174206d61792069737375652061206865617274626561742e2054686520626c6f636b206e756d626572207768656e2077652073686f756c6420676f737369702e00be62110023000000946211002a0000003c7f11001e0000000600000032000000696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64653a205f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e4475706c696361746564206865617274626561742e4e6f6e206578697374656e74207075626c6963206b65792e417574686f72697479446973636f766572794b657973417574686f7273686970446964536574556e636c65734261626545706f6368496e646578417574686f72697469657347656e65736973536c6f7443757272656e74536c6f7452616e646f6d6e6573734e65787452616e646f6d6e6573735365676d656e74496e646578556e646572436f6e737472756374696f6e746f6f206d616e7920696e737472756374696f6e73547269656420746f20736872696e6b20746f2061206c61726765722063617061636974794e6f6e2d656d7074792066756e6374696f6e20626f647920657870656374656400406411000f0000004f641100020000005164110003000000617373657274696f6e206661696c65643a20636f6e746578742e6672616d655f737461636b2e69735f656d7074792829417420696e737472756374696f6e202840293a2043616e2774206465636f6465207761736d20636f64654d6f64756c65206973206e6f742076616c69646d6f64756c65206465636c6172657320696e7465726e616c206d656d6f72796d756c7469706c65207461626c6573206465636c617265647461626c652065786365656473206d6178696d756d2073697a6520616c6c6f776564757365206f6620666c6f6174696e6720706f696e74207479706520696e2066756e6374696f6e20747970657320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e206c6f63616c7320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e20676c6f62616c7320697320666f7262696464656e67617320696e737472756d656e746174696f6e206661696c6564737461636b2068656967687420696e737472756d656e746174696f6e206661696c656463616c6c6465706c6f796465706c6f792066756e6374696f6e2069736e2774206578706f72746564756e6b6e6f776e206578706f72743a20657870656374696e67206f6e6c79206465706c6f7920616e642063616c6c2066756e6374696f6e7366756e6374696f6e206861732061206e6f6e2d6578697374656e7420747970656578706f72742072656665727320746f206e6f6e2d6578697374656e742066756e6374696f6e657870656374656420612066756e6374696f6e656e74727920706f696e7420706f696e747320746f20616e20696d706f727465642066756e6374696f6e656e74727920706f696e74206861732077726f6e67207369676e617475726563616c6c2066756e6374696f6e2069736e2774206578706f727465646572726f722073657269616c697a696e6720696e737472756d656e746564206d6f64756c6552657475726e207479706573206c656e6774682073686f756c642062652030206f7220316e616d650000276911001e000000456911001f00000066756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2071656466756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2066756e6374696f6e5f73656374696f6e5f6c656e203d3d20636f64655f73656374696f6e5f6c656e3b2071656400000d6911001a000000e86811000a000000f26811001b00000073746172742066756e6374696f6e20657870656374656420746f20686176652074797065205b5d202d3e205b5d000000d768110011000000b76811002000000097681100200000006f681100280000007365676d656e74206f66667365742073686f756c642072657475726e2049333270617373697665206d656d6f7279207365676d656e747320617265206e6f7420737570706f727465647061737369766520656c656d656e74207365676d656e747320617265206e6f7420737570706f72746564746f6f206d616e79206d656d6f727920726567696f6e7320696e20696e6465782073706163653a20746f6f206d616e79207461626c657320696e20696e6465782073706163653a20747279696e6720746f20696d706f7274206d757461626c6520676c6f62616c206475706c6963617465206578706f72742046756e6374696f6e20232072656164696e672f76616c69646174696f6e206572726f723a204d697373696e6720626f647920666f722066756e6374696f6e206c656e677468206f662066756e6374696f6e2073656374696f6e206973202c207768696c65206c656e206f6620636f64652073656374696f6e20697320436f6e74726163744761735370656e7443757272656e745363686564756c654163636f756e74436f756e7465726578745f7365745f73746f726167656578745f6765745f73746f726167656578745f63616c6c6578745f696e7374616e74696174656578745f72657475726e6578745f63616c6c65726578745f616464726573736578745f6761735f70726963656578745f6761735f6c6566746578745f62616c616e63656578745f76616c75655f7472616e736665727265646578745f72616e646f6d6578745f6e6f776578745f6d696e696d756d5f62616c616e63656578745f64697370617463685f63616c6c6578745f726573746f72655f746f6578745f736372617463685f73697a656578745f736372617463685f726561646578745f736372617463685f77726974656578745f6465706f7369745f6576656e746578745f7365745f72656e745f616c6c6f77616e63656578745f72656e745f616c6c6f77616e63656578745f7072696e746c6e6578745f626c6f636b5f6e756d6265726578745f6765745f72756e74696d655f73746f72616765000000000000000100000002000000040000000800000010000000200000005075626c696350726f70436f756e745265666572656e64756d436f756e7444656d6f63726163794c6f77657374556e62616b65644c6173745461626c656457617345787465726e616c50687261676d656e456c656374696f6e456c656374696f6e526f756e6473496e697469616c697a6564000000000000146c11000e00000000000000246c11000100000000000000000000002c6c1100010000000000000000000000346c110006000000000000005c8f11000000000000000000000000003c6c1100010000000000000000000000446c110007000000000000005c8f11000000000000000000000000004c6c110001000000000000004e6577417574686f7269746965730000c76c11000d000000a36c11002400000050617573656400007c6c110027000000526573756d656400546c1100280000002043757272656e7420617574686f726974792073657420686173206265656e20726573756d65642e2043757272656e7420617574686f726974792073657420686173206265656e207061757365642e204e657720617574686f726974792073657420686173206265656e206170706c6965642e417574686f726974794c69737443757272656e7453657449644772616e64706146696e616c697479536574496453657373696f6e4f6666636861696e206572726f723a206665746368696e67206e6574776f726b207374617465206661696c6564214f6666636861696e206572726f723a207369676e696e67206661696c6564214f6666636861696e206572726f723a206465636f64696e6720576f726b6572537461747573206661696c6564214f6666636861696e206572726f723a207375626d697474696e67207472616e73616374696f6e206661696c656421496d4f6e6c696e655265636569766564486561727462656174734f6666656e6365735265706f72747342794b696e64496e6465780000000000046e110007000000000000000c6e11000200000000000000000000001c6e110002000000000000004f6666656e636500cf6e110004000000d36e11000e0000002c6e110055000000816e11004e00000020546865726520697320616e206f6666656e6365207265706f72746564206f662074686520676976656e20606b696e64602068617070656e656420617420746865206073657373696f6e5f696e6465786020616e6420286b696e642d7370656369666963292074696d6520736c6f742e2054686973206576656e74206973206e6f74206465706f736974656420666f72206475706c696361746520736c61736865732e4b696e644f706171756554696d65536c6f7453746f72656452616e676553657373696f6e43757272656e74496e6465785175657565644368616e67656444697361626c656456616c696461746f72730000000000004c6f11000a00000000000000586f1100010000000000000000000000606f110002000000000000004e657753657373696f6e0000e76f11000c000000706f110055000000c56f110022000000204e65772073657373696f6e206861732068617070656e65642e204e6f746520746861742074686520617267756d656e74206973207468652073657373696f6e20696e6465782c206e6f742074686520626c6f636b206e756d626572206173207468652074797065206d6967687420737567676573742e53657373696f6e496e64657856616c696461746f72436f756e744d696e696d756d56616c696461746f72436f756e745374616b696e6743757272656e7445726143757272656e74457261537461727453657373696f6e496e64657843757272656e74457261506f696e74734561726e6564466f726365457261536c6173685265776172644672616374696f6e426f6e646564457261734561726c69657374556e6170706c696564536c61736853746f7261676556657273696f6e496e73756666696369656e7456616c7565496e76616c6964536c617368496e6465784475706c6963617465496e646578456d707479546172676574734261644f726967696e416c7265616479506169726564416c7265616479426f6e6465644e6f7453746173684e6f74436f6e74726f6c6c65724e6f4d6f72654368756e6b7300000000000000087111000d000000000000003c72110001000000000000000000000000711100080000000000000044721100010000000000000000000000f37011000d000000000000004c721100010000000000000000000000e67011000d0000000000000054721100010000000000000000000000dd70110009000000000000005c721100010000000000000000000000d17011000c0000000000000064721100010000000000000000000000c37011000e000000000000006c721100010000000000000000000000b2701100110000000000000074721100010000000000000000000000a170110011000000000000007c721100010000000000000000000000157111000c00000000000000847211000100000000000000b57311001a000000a0731100150000008773110019000000697311001e000000307311003900000017731100190000000673110011000000e472110022000000b1721100330000008c721100250000002043616e206e6f74207363686564756c65206d6f726520756e6c6f636b206368756e6b732e2043616e206e6f7420626f6e6420776974682076616c7565206c657373207468616e206d696e696d756d2062616c616e63652e20536c617368207265636f726420696e646578206f7574206f6620626f756e64732e204475706c696361746520696e6465782e20546172676574732063616e6e6f7420626520656d7074792e2053686f756c642062652074686520726f6f74206f726967696e206f72207468652060543a3a536c61736843616e63656c4f726967696e602e20436f6e74726f6c6c657220697320616c7265616479207061697265642e20537461736820697320616c726561647920626f6e6465642e204e6f742061207374617368206163636f756e742e204e6f74206120636f6e74726f6c6c6572206163636f756e742e526571756972655375646f000000000000cf7311000b00000000000000f8731100010000000000000000741100200000002053656e646572206d75737420626520746865205375646f206163636f756e7474696d737461703054696d657374616d7020696e686572656e742064617461206973206e6f742070726f76696465642e496e76616c69642074696d657374616d7020696e686572656e74206461746120656e636f64696e672e54696d657374616d7044696455706461746542616c616e6365734e6578744665654d756c7469706c696572547265617375727950726f706f73616c436f756e74417070726f76616c73496e73756666696369656e7450726f706f7365727342616c616e6365496e76616c696450726f706f73616c496e646578000000000000c27411001c000000000000002c751100010000000000000000000000de7411001400000000000000347511000100000000000000577511001f0000003c7511001b000000204e6f2070726f706f73616c206174207468617420696e6465782e2050726f706f73657227732062616c616e636520697320746f6f206c6f772e000000000000a47511000d00000000000000b47511000100000000000000000000005c8f1100000000000000000042617463684578656375746564000000bc7511001e0000005665633c526573756c743c28292c2044697370617463684572726f723e3e00003700000004000000040000000c00000042725461626c65446174617461626c65370000000400000004000000e500000064656661756c744636345265696e74657270726574493634556e726561636861626c654e6f70426c6f636b00370000000400000004000000e60000004c6f6f704966456c7365456e6442724272496642725461626c650000370000000400000004000000e700000052657475726e43616c6c43616c6c496e6469726563740000370000000400000004000000e200000044726f7053656c6563744765744c6f63616c5365744c6f63616c5465654c6f63616c476574476c6f62616c536574476c6f62616c4933324c6f61644936344c6f61644633324c6f61644636344c6f61644933324c6f616438534933324c6f616438554933324c6f61643136534933324c6f61643136554936344c6f616438534936344c6f616438554936344c6f61643136534936344c6f61643136554936344c6f61643332534936344c6f616433325549333253746f726549363453746f726546333253746f726546363453746f726549333253746f72653849333253746f7265313649363453746f72653849363453746f7265313649363453746f7265333243757272656e744d656d6f727947726f774d656d6f7279493332436f6e737400370000000400000004000000e8000000493634436f6e7374370000000400000004000000e9000000463332436f6e7374463634436f6e73743700000004000000040000000e00000049333245717a49333245714933324e654933324c74534933324c74554933324774534933324774554933324c65534933324c655549333247655349333247655549363445717a49363445714936344e654936344c74534936344c74554936344774534936344774554936344c65534936344c655549363447655349363447655546333245714633324e654633324c7446333247744633324c65463332476546363445714636344e654636344c7446363447744636344c654636344765493332436c7a49333243747a493332506f70636e744933324164644933325375624933324d756c493332446976534933324469765549333252656d5349333252656d55493332416e644933324f72493332586f7249333253686c4933325368725349333253687255493332526f746c493332526f7472493634436c7a49363443747a493634506f70636e744936344164644936345375624936344d756c493634446976534936344469765549363452656d5349363452656d55493634416e644936344f72493634586f7249363453686c4936345368725349363453687255493634526f746c493634526f74724633324162734633324e65674633324365696c463332466c6f6f724633325472756e634633324e656172657374463332537172744633324164644633325375624633324d756c4633324469764633324d696e4633324d6178463332436f70797369676e4636344162734636344e65674636344365696c463634466c6f6f724636345472756e634636344e656172657374463634537172744636344164644636345375624636344d756c4636344469764636344d696e4636344d6178463634436f70797369676e493332577261704936344933325472756e63534633324933325472756e63554633324933325472756e63534636344933325472756e6355463634493634457874656e6453493332493634457874656e64554933324936345472756e63534633324936345472756e63554633324936345472756e63534636344936345472756e6355463634463332436f6e7665727453493332463332436f6e7665727455493332463332436f6e7665727453493634463332436f6e766572745549363446333244656d6f7465463634463634436f6e7665727453493332463634436f6e7665727455493332463634436f6e7665727453493634463634436f6e766572745549363446363450726f6d6f74654633324933325265696e746572707265744633324936345265696e746572707265744636344633325265696e7465727072657449333200003700000004000000040000000c0000004e6f526573756c7456616c7565000000370000000400000004000000ea000000463634493332493634463332f87b11000b000000492f4f204572726f723a20496e76616c696444617461547261696c696e6744617461556e6578706563746564456f6600657c1100670000001001000020000000407c11002500000043616c6c20746f2066756e6374696f6e2074686174206f75742d6f662d626f756e64733a202f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f737461636b5f6865696768742f6d6f642e7273546869732073686f756c64206265206120696e646578206f66206120646566696e65642066756e6374696f6e44756520746f2076616c69646174696f6e20636f64652073656374696f6e2073686f756c642065786973747346756e6374696f6e20626f6479206973206f7574206f6620626f756e647366756e6374696f6e20696d706f727420636f756e74206973206e6f74207a65726f3b20696d706f72742073656374696f6e206d757374206578697374733b2071656466756e635f696478206973206c657373207468616e2066756e6374696f6e20696d706f72747320636f756e743b0a090909096e74682066756e6374696f6e20696d706f7274206d7573742062652060536f6d65603b0a09090909716564000000188e110012000000397e11000f0000000c7e11000a000000167e1100140000002a7e11000f0000005369676e61747572652020287370656369666965642062792066756e6320292069736e277420646566696e6564206973206e6f7420646566696e65640d7f1100120000001f7f11000c0000006066756e635f696478602073686f756c6420636f6d652066726f6d20606e6565645f7468756e6b73603b0a09090909606e6565645f7468756e6b736020697320706f70756c617465642077697468207468652073616d65206974656d73207468617420696e20607265706c6163656d656e745f6d6170603b0a090909097165644174207468697320706f696e7420616e20696e646578206d7573742062652061737369676e656420746f2065616368207468756e6b66756e6374696f6e207769746820696478202069736e277420666f756e64003c7f11001e000000030000000a0000003c3a3a636f72653a3a6d6163726f733a3a70616e6963206d6163726f733e617373657274696f6e206661696c65643a20656e64203c3d206c656e0000e0831100480000000302000023000000e0831100480000000402000023000000617373657274696f6e206661696c65643a206d6964203c3d206c656e8c901100490000000f00000028000000d47f1100490000008e0200001d0000002f72757374632f373661323532656139653762653933613631666664663333623335333365323461396366343539642f7372632f6c6962636f72652f736c6963652f736f72742e7273000000d47f110049000000a100000030000000d47f110049000000a4000000300000004672616d6569735f706f6c796d6f727068696300370000000400000004000000eb000000656e645f61726974790000003700000004000000040000000c0000006272616e63685f617269747973746172745f6865696768744e6f2066756e6374696f6e2073656374696f6e4e6f20636f64652073656374696f6e4e6f20747970652073656374696f6e000000f48211000a00000046756e6374696f6e206973206e6f7420666f756e6420696e2066756e632073656374696f6e46756e6374696f6e20626f647920666f722074686520696e6465782069736e277420666f756e64e88211000c000000ac8211000b000000737461636b206d757374206265206e6f6e2d656d70747900a18211000b0000005882110006000000737461636b206f766572666c6f774172697479206f6620616c6c206a756d702d74617267657473206d75737420626520657175616c54797065206e6f7420666f756e64005182110007000000b48111006e000000c8000000170000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f737461636b5f6865696768742f6d61785f6865696768742e72736d61785f686569676874707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768747472756e633a20707573683a2000009c82110005000000747279696e6720746f20706f70206d6f72652076616c756573207468616e20707573686564737461636b20756e646572666c6f77706f703a20756e726561636861626c65706f705f6672616d653a20636f6e74726f6c20737461636b20697320656d707479636f6e74726f6c20737461636b206f75742d6f662d626f756e6473707573685f6672616d653a2066756e635f6964783a204e6f6e65536f6d650000370000000400000004000000ec000000656e766761730000308311005e000000120100001c0000002f686f6d652f6461766964642f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31322e302f7372632f6761732f6d6f642e72736c6173745f696e6465782069732067726561746572207468616e20303b206c6173745f696e64657820697320737461636b2073697a65202d20313b20716564000000e083110048000000ed0a00000a0000002f72757374632f373661323532656139653762653933613631666664663333623335333365323461396366343539642f7372632f6c6962636f72652f736c6963652f6d6f642e7273e083110048000000f30a00000e000000488411003f000000440000000d0000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f61726974686d657469632f7372632f62696775696e742e7273000000000000000000617474656d707420746f20646976696465206279207a65726f63616e6e6f74206669742061206e756d62657220696e746f2075313238616c7265616479206d757461626c7920626f72726f77656400003b00000000000000010000005a000000616c726561647920626f72726f7765643b00000000000000010000005900000072656d696e646572206f6620646976206279206320697320616c77617973206c657373207468616e20633b20716564004d0000000800000004000000bf000000726573756c742063616e6e6f742066697420696e207531323862616265736c6f74436f756c64206e6f74206465636f64652072657175657374656420696e686572656e742074797065214241424520696e686572656e742064617461206e6f7420666f756e643c7761736d3a73747269707065643e0000003b00000000000000010000003c000000486f737420746f207761736d2076616c7565732061726520656e636f64656420636f72726563746c793b2071656400003b00000000000000010000003c00000072756e74696d6552756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e6748617368206e6f7420657175616c496e76616c6964206f726967696e43616e206e6f74206c6f6f6b757044697370617463684572726f725472616e73616374696f6e20776f756c642065786861757374732074686520626c6f636b206c696d6974735472616e73616374696f6e2068617320616e20616e6369656e7420626972746820626c6f636b5472616e73616374696f6e20686173206120626164207369676e61747572655472616e73616374696f6e206973206f757464617465645472616e73616374696f6e2077696c6c2062652076616c696420696e2074686520667574757265496e6162696c69747920746f2070617920736f6d6520666565732028652e672e206163636f756e742062616c616e636520746f6f206c6f77295472616e73616374696f6e2063616c6c206973206e6f74206578706563746564496e76616c69645472616e73616374696f6e20637573746f6d206572726f72436f756c64206e6f742066696e6420616e20756e7369676e65642076616c696461746f7220666f722074686520756e7369676e6564207472616e73616374696f6e436f756c64206e6f74206c6f6f6b757020696e666f726d6174696f6e20726571756972656420746f2076616c696461746520746865207472616e73616374696f6e556e6b6e6f776e5472616e73616374696f6e20637573746f6d206572726f7200617474656d707420746f20646976696465206279207a65726f0000006c88110040000000580000002b0000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f72756e74696d652f7372632f67656e657269632f6572612e7273696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f6465e4881100430000005a000000120000002f686f6d652f6461766964642f6465762f7375627374726174652f7072696d6974697665732f73616e64626f782f7372632f2e2e2f776974686f75745f7374642e727300e48811004300000068000000120000006d616b655f746f705f6672616d655f706f6c796d6f72706869632069732063616c6c6564207769746820656d707479206672616d6520737461636b00ed0000000c00000004000000ee000000746869732066756e6374696f6e2063616e27742062652063616c6c6564207769746820656d707479206672616d6520737461636b4d6973706c6163656420656c736520696e737472756374696f6e0000fc8a110047000000438b110005000000c08a110037000000f78a1100050000008e8a110017000000858a110009000000d68c1100140000006d8a110018000000858a110009000000d68c1100140000003c8a11001d000000598a1100130000006c8a110001000000546f6f206c61726765206d656d6f727920616c69676e6d656e7420325e20286578706563746564206174206d6f73742029547279696e6720746f2075706461746520676c6f62616c20206f66207479706520547279696e6720746f20757064617465206c6f63616c20416e795370656369666963370000000400000004000000ea0000004c6162656c7320696e2062725f7461626c6520706f696e747320746f20626c6f636b206f6620646966666572656e742074797065733a2020616e6420496620626c6f636b20776974686f757420656c736520726571756972656420746f2068617665204e6f526573756c7420626c6f636b20747970652e2042757420697420686173202074797065588b110018000000708b11000b000000556e657870656374656420737461636b20686569676874202c20657870656374656420547279696e6720746f2061636365737320706172656e74206672616d6520737461636b2076616c7565732e0000b88b110017000000cf8b11001600000045787065637465642076616c7565206f66207479706520206f6e20746f70206f6620737461636b2e20476f7420000000f08b110007000000537461636b3a2000000001007a8c110024000000508c110006000000568c11000e000000648c1100160000002c8c110024000000508c1100060000006d6178696d756d206d656d6f72792073697a65206d757374206265206174206d6f7374202070616765736d6178696d756d206c696d697420206973206c657373207468616e206d696e696d756d20696e697469616c206d656d6f72792073697a65206d757374206265206174206d6f7374200000b08c110026000000d68c110014000000547279696e6720746f20696e697469616c697a65207661726961626c65206f6620747970652020776974682076616c7565206f66207479706520496e69742065787072657373696f6e2073686f756c6420616c776179732062652077697468206c656e67746820324e6f6e20636f6e7374616e74206f70636f646520696e20696e69742065787072818d110007000000938d110022000000818d110007000000888d11000b00000045787072657373696f6e20646f65736e277420656e647320776974682060656e6460206f70636f6465476c6f62616c20206973206d757461626c6520646f65736e277420657869737473206f72206e6f742079657420646566696e6564000000c88d110010000000d88d11000f0000004d656d6f727920617420696e6465782020646f65736e27742065786973747300f88d11000f000000d88d11000f0000005461626c6520617420696e6465782000188e110012000000d88d11000f00000046756e6374696f6e20617420696e6465782000003c8e11000e000000d88d11000f0000005479706520617420696e646578200000aa8e110010000000d88d11000f0000007c8e1100100000009c8e11000e0000007c8e1100100000008c8e110010000000457870656374656420676c6f62616c2020746f20626520696d6d757461626c6520746f206265206d757461626c65476c6f62616c20617420696e646578206e6f6e2d656d70747920737461636b2065787065637465640000e48e110020000000048f110012000000747279696e6720746f206765742076616c756520617420706f736974696f6e20206f6e20737461636b206f662073697a6520636865636b656420636f75706c65206f66206c696e65732061626f7665003c8f110015000000657863656564656420737461636b206c696d6974200000005c8f1100000000004572726f72000000370000000400000004000000ef0000004c6f63616c732072616e6765206e6f7420696e2033322d6269742072616e6765ac8f110022000000ce8f110015000000e38f110007000000547279696e6720746f20616363657373206c6f63616c207769746820696e64657820207768656e20746865726520617265206f6e6c7920206c6f63616c730000049011002d000000319011000c0000003d90110003000000617373657274696f6e206661696c65643a2060286c656674203d3d20726967687429600a20206c6566743a2060602c0a2072696768743a2060603a20489011003400000064657374696e6174696f6e20616e6420736f7572636520736c69636573206861766520646966666572656e74206c656e677468738c90110049000000170000000d0000002f72757374632f373661323532656139653762653933613631666664663333623335333365323461396366343539642f7372632f6c6962636f72652f6d6163726f732f6d6f642e72730041d8a1c6000b0800000000000000000041e0a1c6000b08e0901100bc19100000b2e003046e616d6501a9e003e40500196578745f6c6f6767696e675f6c6f675f76657273696f6e5f3101196578745f73746f726167655f7365745f76657273696f6e5f31021e6578745f68617368696e675f74776f785f3132385f76657273696f6e5f3103196578745f73746f726167655f6765745f76657273696f6e5f31041d6578745f6d6973635f7072696e745f757466385f76657273696f6e5f31051b6578745f73746f726167655f636c6561725f76657273696f6e5f3106206578745f68617368696e675f626c616b65325f3235365f76657273696f6e5f3107286578745f73746f726167655f6368696c645f73746f726167655f6b696c6c5f76657273696f6e5f31081f6578745f73746f726167655f6368696c645f6765745f76657273696f6e5f3109216578745f73746f726167655f6368696c645f636c6561725f76657273696f6e5f310a1f6578745f73746f726167655f6368696c645f7365745f76657273696f6e5f310b236578745f63727970746f5f656432353531395f7665726966795f76657273696f6e5f310c236578745f63727970746f5f737232353531395f7665726966795f76657273696f6e5f310d226578745f73746f726167655f636c6561725f7072656669785f76657273696f6e5f310e1c6578745f6d6973635f7072696e745f6e756d5f76657273696f6e5f310f206578745f73746f726167655f6368696c645f726f6f745f76657273696f6e5f3110206578745f73616e64626f785f6d656d6f72795f6e65775f76657273696f6e5f3111256578745f73616e64626f785f6d656d6f72795f74656172646f776e5f76657273696f6e5f3112216578745f73616e64626f785f696e7374616e74696174655f76657273696f6e5f31131c6578745f73616e64626f785f696e766f6b655f76657273696f6e5f3114276578745f73616e64626f785f696e7374616e63655f74656172646f776e5f76657273696f6e5f31151c6578745f6d6973635f7072696e745f6865785f76657273696f6e5f3116236578745f6f6666636861696e5f69735f76616c696461746f725f76657273696f6e5f3117286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f6765745f76657273696f6e5f3118346578745f6f6666636861696e5f6c6f63616c5f73746f726167655f636f6d706172655f616e645f7365745f76657273696f6e5f3119286578745f6f6666636861696e5f6c6f63616c5f73746f726167655f7365745f76657273696f6e5f311a256578745f63727970746f5f656432353531395f67656e65726174655f76657273696f6e5f311b1a6578745f73746f726167655f726f6f745f76657273696f6e5f311c226578745f73746f726167655f6368616e6765735f726f6f745f76657273696f6e5f311d1d6578745f68617368696e675f74776f785f36345f76657273696f6e5f311e206578745f73616e64626f785f6d656d6f72795f6765745f76657273696f6e5f311f206578745f73616e64626f785f6d656d6f72795f7365745f76657273696f6e5f3120256578745f63727970746f5f737232353531395f67656e65726174655f76657273696f6e5f3121296578745f6f6666636861696e5f7375626d69745f7472616e73616374696f6e5f76657273696f6e5f3122246578745f6f6666636861696e5f6e6574776f726b5f73746174655f76657273696f6e5f3123286578745f63727970746f5f737232353531395f7075626c69635f6b6579735f76657273696f6e5f3124216578745f63727970746f5f737232353531395f7369676e5f76657273696f6e5f3125376578745f63727970746f5f736563703235366b315f65636473615f7265636f7665725f636f6d707265737365645f76657273696f6e5f31261e6578745f616c6c6f6361746f725f6d616c6c6f635f76657273696f6e5f31271c6578745f616c6c6f6361746f725f667265655f76657273696f6e5f31281a6578745f73746f726167655f726561645f76657273696f6e5f31292a6578745f747269655f626c616b65325f3235365f6f7264657265645f726f6f745f76657273696f6e5f312a0c5f5f727573745f616c6c6f632b0a5f5f72675f616c6c6f632c0e5f5f727573745f6465616c6c6f632d0c5f5f72675f6465616c6c6f632e0e5f5f727573745f7265616c6c6f632f0c5f5f72675f7265616c6c6f6330135f5f727573745f616c6c6f635f7a65726f656431115f5f72675f616c6c6f635f7a65726f65643209686173685f746573743333616c6c6f633a3a616c6c6f633a3a68616e646c655f616c6c6f635f6572726f723a3a68386531316436663965343234316133633408727573745f6f6f6d3534616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a68646433393266313964303139366331643629636f72653a3a70616e69636b696e673a3a70616e69633a3a68646239663362643439353762376130343725616c6c6f633a3a666d743a3a666f726d61743a3a68323034353933636463626239393462643836636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68383631343133363633386239663665333923636f72653a3a666d743a3a77726974653a3a68323037613236633066373832626466643a48616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303061333839343366393039313364663b2e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a68356539626632666462336331346131313c3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68653462323430393966333136316432613d3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68646135323030363563363762376437333e3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68386133653436393862303536393134353f34636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a6864616535356635386637356233376335404e636f72653a3a666d743a3a6e756d3a3a696d703a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207533323e3a3a666d743a3a6861356364353334633165353832626330412d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a6833343531616266633263663866643735422f636f72653a3a666d743a3a6e756d3a3a696d703a3a666d745f7536343a3a68396430343437333539653330323562384311727573745f626567696e5f756e77696e6444313c5420617320636f72653a3a616e793a3a416e793e3a3a747970655f69643a3a68306465666264653633353865346532624535636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a68346231353362333663363261326539304643636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a77726974655f7072656669783a3a68636435663263333739613934326338624736636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a6865633531326337336339393435393139482c636f72653a3a666d743a3a466f726d61747465723a3a7061643a3a6830653165663266646261323032306339492e636f72653a3a7374723a3a736c6963655f6572726f725f6661696c3a3a68373830313030333831333434633333394a323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68346132653465636539373166306565394b4a3c636f72653a3a6f70733a3a72616e67653a3a52616e67653c4964783e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68373230346333363939396432316363634c323c6368617220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68626461316437313164366434313734314d3d636f72653a3a756e69636f64653a3a626f6f6c5f747269653a3a426f6f6c547269653a3a6c6f6f6b75703a3a68666531353763343132326361303534664e49636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a68386432353364353564646635356463334f34636f72653a3a666d743a3a417267756d656e7456313a3a73686f775f7573697a653a3a686664636138363230366231666565383350453c636f72653a3a63656c6c3a3a426f72726f774572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686437356263616161353161356536653451483c636f72653a3a63656c6c3a3a426f72726f774d75744572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686637323137353036303339613963333352323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683236663030343139663436303834303753323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6830323766613761636633313939313735542e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a683439346633653534346562303365373455303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832356262626661663335303532346239562e636f72653a3a736c6963653a3a6d656d6368723a3a6d656d6368723a3a6831356139303835666665633534316165578001636f72653a3a7374723a3a7472616974733a3a3c696d706c20636f72653a3a736c6963653a3a536c696365496e6465783c7374723e20666f7220636f72653a3a6f70733a3a72616e67653a3a52616e67653c7573697a653e3e3a3a696e6465783a3a7b7b636c6f737572657d7d3a3a68333162396631303565353862363261395827636f72653a3a7374723a3a66726f6d5f757466383a3a68656463376239663161653061646539615930636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68303962326434393262333033623434345a533c636f72653a3a666d743a3a6275696c646572733a3a5061644164617074657220617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68386534373166643833366665303436665b2f636f72653a3a666d743a3a57726974653a3a77726974655f636861723a3a68653166356333646239303739356662375c2e636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a68363861383934353839633935346236615d3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68393133616132333339376339373630325e3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68393861383665653265633764393334315f3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a6837396235343665393130333134623937603a636f72653a3a666d743a3a6275696c646572733a3a44656275675374727563743a3a6669656c643a3a68323563343366303238653764323136666139636f72653a3a666d743a3a6275696c646572733a3a44656275675475706c653a3a6669656c643a3a68383635363362393137383131326630396237636f72653a3a666d743a3a6275696c646572733a3a44656275675365743a3a656e7472793a3a683461306636396564643136396633346563443c636f72653a3a666d743a3a417267756d656e747320617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683565343066323335616130366263633564313c73747220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6863343364336165393861333631646132653e3c636f72653a3a666d743a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683762303032383162323938653331643366693c6672616d655f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6864343430383733363131356130633333676c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683563363237343830623738666134613768483c5b545d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683534613837376637396264383661373669693c6672616d655f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68353838343739663861376132386538656a4d3c6672616d655f737570706f72743a3a64656275673a3a52756e74696d654c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a68306165386636316336346635393039636b493c6672616d655f737570706f72743a3a64656275673a3a52756e74696d654c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a68636135366365623135366332353863386c3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68343163306264623062363166373063656d3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68343862663330313635306635396266346e3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68363930353432666233643862626361326f383c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a683238313862343662313536303564313170343c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a683530616236323939313234333733653571363c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a666c7573683a3a6862333164356661343665313662356464724b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68356638396639326435623838623831617330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a686430336463636430323333346132666674543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6832376266333161303562363034313761756b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6834663964643130383738383938396561767d7061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72202851302c205230293e3a3a6465636f64653a3a683963323330666231336239363963616377543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a686132333061656531323733353565396178393c54206173206672616d655f737570706f72743a3a7472616974733a3a4c656e3e3a3a6c656e3a3a6837303736356164313330663732323566794a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a68613563343263613066653263313232617a2d616c6c6f633a3a7665633a3a5665633c543e3a3a72657461696e3a3a68613736356662626464666338336134657b403c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68656361313432613134626131383236367c443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68376361336166633531303464366639337d463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68633033353738633737313032626635637e543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68316131303639313834623832666537357f543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68363736666236393566383833643263658001543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68373666366465396330333062333733648101723c73705f72756e74696d653a3a67656e657269633a3a6865616465723a3a4865616465723c4e756d6265722c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68393336333530306432633264646338618201543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68623331376664363636316662316262648301543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68663965323763373066663536396232328401513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68313138666430336633636335386634328501513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68346665353961383762616439643537628601513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a686230306437376562393535646164373687013e73705f72756e74696d653a3a67656e657269633a3a656e636f64655f776974685f7665635f7072656669783a3a686661393233643238653238363565326188017d3c70616c6c65745f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a686566353136646634663031643561663089016f3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68386132626663373539386166616136318a01723c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68653765663236356634633638323963338b016e6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a656e636f64655f746f3a3a68333165333064613830356366643963638c016f3c285475706c65456c656d656e74302c205475706c65456c656d656e7431292061732073705f72756e74696d653a3a7472616974733a3a4f6e46696e616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c697a653a3a68356437666435663339663164366533348d017c3c73705f72756e74696d655f696e746572666163653a3a706173735f62793a3a436f6465633c543e2061732073705f72756e74696d655f696e746572666163653a3a706173735f62793a3a506173734279496d706c3c543e3e3a3a66726f6d5f6666695f76616c75653a3a68343565663838613839626633363333348e01303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68333133343437643730316638633436328f013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68643463343531313334656566616433619001376672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6c6f673a3a68333663316437343066623935393036309101463c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68646638643435363731306139376631629201416672616d655f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6576656e745f696e64657865643a3a683063306530376265623663663736393493013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68316333333739613964356239633365359401386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68343039646236663363313730333932619501386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68383837333831363130646230393937649601386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686664373162643435326636626166633397014373705f696f3a3a73746f726167653a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a726561643a3a68316565333932626133303539613138379801386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68343239313931373365623761383630309901386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68346465323032383337353963386430319a01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68316430333866653335663138343932329b013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68323531633533623431656561633261319c01446672616d655f737570706f72743a3a7472616974733a3a43757272656e63793a3a7265736f6c76655f6372656174696e673a3a68386131333538353331323161373439389d018d013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6465706f7369745f6372656174696e673a3a68376438313366343566316431623337669e01386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68303566356530623734396639383534649f01437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6839393662316237393066316664663535a00191013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6d616b655f667265655f62616c616e63655f62653a3a6839313638653738306565656265666462a10183013c70616c6c65745f696e64696365733a3a4d6f64756c653c543e206173206672616d655f73797374656d3a3a4f6e4e65774163636f756e743c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f6e65775f6163636f756e743a3a6864383836383962386530353632353663a2014170616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7365745f667265655f62616c616e63653a3a6835313338666439643032343535653336a301796672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a76616c75653a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f7261676556616c75653c543e20666f7220473e3a3a6d75746174653a3a6832393134633039333462623539366235a4013870616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6b696c6c5f73746173683a3a6861393137663161336164346338636530a501386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6834666137636264363863373563303066a601706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6864326666393133363139633065626565a701386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863616530373036613163663531666330a801706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6832356264383036636436653834313164a901456672616d655f737570706f72743a3a7472616974733a3a4f6e556e62616c616e6365643a3a6f6e5f756e62616c616e6365643a3a6835353866363337383464643333383330aa014570616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7365745f72657365727665645f62616c616e63653a3a6865613039313337393166386465653463ab01776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6835646435383164333166636465353034ac0185013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a77697468647261773a3a6837616632363936303335623533333161ad0190013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a656e737572655f63616e5f77697468647261773a3a6839303834316230313031376132323431ae013670616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6c6f636b733a3a6838343861326564663865306137313235af01483c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830633634376237643965376530353838b001776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6838613531316630623236636436626466b1018a013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a746f74616c5f62616c616e63653a3a6837653632643137636262613031363264b201776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6833663666656339323366646235353365b3013d70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a7363686564756c655f6368616e67653a3a6831396134393664386334366635333363b401683c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a73697a655f68696e743a3a6831666337613661653736333430396562b501633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6835323864633166373339646430613361b6013e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6835333665613433393335653135326561b70189013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a667265655f62616c616e63653a3a6836633938613336373464663634663534b80192013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6465706f7369745f696e746f5f6578697374696e673a3a6833373963363530306566633534626163b9013c70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6862613731393030316333636235353931ba013e70616c6c65745f6772616e6470613a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6839313861363639386532326433656638bb01703c70616c6c65745f6772616e6470613a3a5f5f4765744279746553747275637443757272656e7453657449643c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861633863303363336665323039623830bc01693c70616c6c65745f6772616e6470613a3a5f5f4765744279746553747275637453746174653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832323033643161306237326538383833bd0190013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a657874656e645f6c6f636b3a3a6834666336626662336636623965383362be018d013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7365745f6c6f636b3a3a6836323838666362353063333662653965bf0195013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736c6173685f72657365727665643a3a6836616164653437646433383931663430c0019a013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a726570617472696174655f72657365727665643a3a6866663332393036376463656235623036c1018e013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a726573657276653a3a6865383861633262363230396161626338c20190013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a756e726573657276653a3a6861626632363534646137316161336362c3013f70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6838353262383938643261313131386230c4014170616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6861653137373131353038303663663230c501723c70616c6c65745f62616c616e6365733a3a5f5f476574427974655374727563744672656542616c616e63653c542c493e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836636338326639363038623535666235c6014a70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6837653634303939613038666261616462c7013f70616c6c65745f6f6666656e6365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6839633661663564663930343838303761c801773c70616c6c65745f6f6666656e6365733a3a5f5f476574427974655374727563745265706f72747342794b696e64496e6465783c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839373966343965326137613666333836c901706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6864656233636538633232653064336636ca014a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6836393761353266313665356235363837cb0168636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a6834336138663865626633343830376161cc01860170616c6c65745f7374616b696e673a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f7374616b696e673a3a4578706f737572653c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6862636165323734326330623233636332cd0185013c70616c6c65745f62616c616e6365733a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a43757272656e63793c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7472616e736665723a3a6861333563393834306164333133353438ce01743c70616c6c65745f62616c616e6365733a3a696d62616c616e6365733a3a4e65676174697665496d62616c616e63653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a54727944726f703e3a3a7472795f64726f703a3a6866653235313532623831613833616438cf014470616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a646f5f70687261676d656e3a3a6838393933303861396138313564666163d001386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6832663162306263633063333765366435d101386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6834656131616437666564626435636635d2016e6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f686561645f6b65793a3a6865366636363230616261353632656662d301386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6837346339313132626362363661323931d40185013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6838366339616330333039633436386531d50148616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6864353233663731656436383432353734d6014870616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6c6f636b65645f7374616b655f6f663a3a6832343030366632663731346530666135d7014673705f61726974686d657469633a3a68656c706572735f3132386269743a3a6d756c7469706c795f62795f726174696f6e616c3a3a6835353134353535393430316334656634d801533c73705f61726974686d657469633a3a726174696f6e616c3132383a3a526174696f6e616c31323820617320636f72653a3a636d703a3a4f72643e3a3a636d703a3a6831633661663234643933396130393434d901583c73705f61726974686d657469633a3a726174696f6e616c3132383a3a526174696f6e616c31323820617320636f72653a3a636d703a3a5061727469616c45713e3a3a65713a3a6832363364383365343337653038643535da01613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833323065356263636333643861343734db0148616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6861666263663262616239656236626335dc014d6672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733a3a636f6d707574655f6d656d626572735f646966663a3a6831633864336535646266353436643366dd0199013c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a6862336630313761623035303839376230de01613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833306536346338363934613533343132df01733c285475706c65456c656d656e74302c205475706c65456c656d656e7431292061732073705f72756e74696d653a3a7472616974733a3a4f6e496e697469616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6865333733346237316534633632636134e0013870616c6c65745f626162653a3a4d6f64756c653c543e3a3a646f5f696e697469616c697a653a3a6836356330663230316131316330623838e10196013c70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e2061732070616c6c65745f73657373696f6e3a3a4f6e6553657373696f6e48616e646c65723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f6265666f72655f73657373696f6e5f656e64696e673a3a6834623665653766326266386666646534e201726e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a53657373696f6e4b6579733e3a3a6465636f64653a3a6832623337306433613839663666613738e3013970616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6e65775f73657373696f6e3a3a6865353938663265303631393834333735e401386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862343339336363643832313933366332e50187013c70616c6c65745f626162653a3a4d6f64756c653c543e2061732070616c6c65745f73657373696f6e3a3a4f6e6553657373696f6e48616e646c65723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f6e65775f73657373696f6e3a3a6831623032666539306562663966383164e601386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6833643538343436636663663433313933e7013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6861613966336337326535356131323332e8013770616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a617574686f723a3a6830383231323761346165303661383062e9013b70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a7265776172645f62795f6964733a3a6833333663663933643630623863613637ea013f70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a6e6f74655f617574686f72736869703a3a6838363339633762643938353137653461eb017d3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6866623263616263396637653238303166ec017d3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6837616365356537623535356139303035ed017f3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6863303566386538333236373334306236ee01746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a6831646434646235393136353739663061ef0181013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6866326235313861376333653837303932f00184013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a6832643964383865383738303837363964f101783c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6866363831343764636563336139643037f201723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6839623062393265626536373434313032f301456672616d655f737570706f72743a3a7472616974733a3a5369676e6564496d62616c616e63653c422c503e3a3a6d657267653a3a6831366664393266316161316438353633f401613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6830633566643861636234323761356139f50196013c70616c6c65745f636f6e7472616374733a3a54726965496446726f6d506172656e74436f756e7465723c543e2061732070616c6c65745f636f6e7472616374733a3a54726965496447656e657261746f723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a747269655f69643a3a6830656262386435363030646633653331f601776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6831623066646536306331353062356163f701723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6836663861356565363432666334616339f801776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6834326638633139646663613434336364f901613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6830633532663431626531363739316133fa0181013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6838346232396366343662383265613533fb0181013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6835663963333639386637653338633532fc0183013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6835646363363638383833663163383931fd0185013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6835333465366564356464636463366332fe0188013c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a6830376435323430336631613735326331ff017c3c70616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732070616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a686636663262333930623631386261663880024b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6839366133636637323237386133306636810248616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a68336433636531333435613337633766308202426672616d655f737570706f72743a3a7472616974733a3a496d62616c616e63653a3a6d617962655f73756273756d653a3a686365316264316139636432376131366383024a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a68363034336263316162313030386135378402696672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a683935626565376362613661393064616185023c70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a686638626533366239636336633339336586023e70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68316635333935303932383531343538318702703c70616c6c65745f73657373696f6e3a3a5f5f4765744279746553747275637443757272656e74496e6465783c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a683535356365333037303664633938306288024770616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a683537323865366234303564636364636289029c013c70616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a44454455505f4b45595f50524546495844656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68666365643239303736623636336130368a023570616c6c65745f73657373696f6e3a3a4d6f64756c653c543e3a3a64697361626c653a3a68376164303935376433636637643430668b023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68623939646631636533663966336630318c029c013c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68663162613064613234393664636137628d027a3c70616c6c65745f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68306339313234356565393162613239368e026c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68613132346132366335316664353964658f026b6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a6465636f64653a3a686134653362626437616133643133643690029f013c73705f72756e74696d653a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e2061732073705f72756e74696d653a3a7472616974733a3a436865636b61626c653c4c6f6f6b75703e3e3a3a636865636b3a3a683962313166663134646265373937643691023670616c6c65745f696e64696365733a3a4d6f64756c653c543e3a3a656e756d5f7365743a3a6865373731353265303436643333623936920230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68643033646363643032333334613266669302366672616d655f73797374656d3a3a4d6f64756c653c543e3a3a626c6f636b5f686173683a3a68376162623261356538376234333866639402437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68333264616665366438373961376165659502553c73705f72756e74696d653a3a4d756c74695369676e61747572652061732073705f72756e74696d653a3a7472616974733a3a5665726966793e3a3a7665726966793a3a686330663565643636316364343664643196025170616c6c65745f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e3a3a7365745f62616c616e63653a3a686231356533386139626134646536343697024770616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683237383538393530633536326533343998024970616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a686166373832353964653639336236333799025270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68663939343634393139373635656637389a02a3013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5465726d4475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68326266396533313137333434363862319b02a7013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4465736972656452756e6e657273557044656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68616535376537303165613565633631639c02a5013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a446573697265644d656d6265727344656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68616566333731353238383435343965319d02a4013c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616e646964616379426f6e6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68323632633136616330303534666337309e02653c70616c6c65745f656c656374696f6e735f70687261676d656e3a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68326166326165363135363135646263659f024170616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a69735f766f7465723a3a6839653766623264353832613137613039a002386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6839666261323937346333363839353562a1024a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6832383066636230396133363439623830a202cc016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e636f64654c696b654c696e6b6167653c504b65792c4e4b65792c4b65793e3e3a3a656e636f64655f746f3a3a6837616239353965363534613436613562a302b8016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4c696e6b6167653c4b65793e3e3a3a656e636f64655f746f3a3a6835343933663330366666313836376332a4024870616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a646f5f72656d6f76655f766f7465723a3a6834323836356565613761663365323365a5025270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a72656d6f76655f616e645f7265706c6163655f6d656d6265723a3a6830653732313137623839386433666261a6024270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a69735f6d656d6265723a3a6834653237666566623235646165613763a7024270616c6c65745f656c656374696f6e735f70687261676d656e3a3a4d6f64756c653c543e3a3a69735f72756e6e65723a3a6866396530623538656364363336363066a8026b3c636f72653a3a697465723a3a61646170746572733a3a526573756c745368756e743c492c453e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6865396537393336343463356635336534a9026f3c636f72653a3a697465723a3a61646170746572733a3a526573756c745368756e743c492c453e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a7472795f666f6c643a3a6831336330666431616562646432623034aa024b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6834663465346364346331653531663065ab02723c70616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6838616562633439663335306236353433ac025770616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4368617267655472616e73616374696f6e5061796d656e743c543e3a3a636f6d707574655f6665653a3a6865303130633637393339303039333763ad026f3c285475706c65456c656d656e74302c205475706c65456c656d656e7431292061732073705f72756e74696d653a3a7472616974733a3a4f6e46696e616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c697a653a3a6836633638626630333532336330343961ae023970616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6163636f756e745f69643a3a6839386530376138626365323066613534af023870616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a70726f706f73616c733a3a6864323337643334373831656534646261b00290013c70616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a4d6f64756c653c543e206173206672616d655f737570706f72743a3a7472616974733a3a52616e646f6d6e6573733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a486173683e3e3a3a72616e646f6d3a3a6833336433376433663530353965666461b102456672616d655f737570706f72743a3a7472616974733a3a4f6e556e62616c616e6365643a3a6f6e5f756e62616c616e6365643a3a6832333666613966323330316633313666b2023d70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6861393935656264303538663035333430b3023f70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6833326362346434613366326261333066b4024870616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6837373862666536366461323532396538b50291013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4275726e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836653732326264303864666666393963b60298013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5370656e64506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833353562653966313964306563666265b70299013c70616c6c65745f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a50726f706f73616c426f6e6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865663432333231366431353432373162b802386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6832353765396366343065666263363530b9023b70616c6c65745f636f6e7472616374733a3a6761733a3a726566756e645f756e757365645f6761733a3a6863643435613230393965383736653137ba024b3c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6865393737336338636431623037646231bb024a70616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863386239313130306632663938643236bc025370616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6833363963616137666635383631393135bd025170616c6c65745f72616e646f6d6e6573735f636f6c6c6563746976655f666c69703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863323731396665323735326164646135be026073705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a736563703235366b315f65636473615f7265636f7665725f636f6d707265737365643a3a6866313630303365646533616235313934bf02603c70616c6c65745f74726561737572793a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6862363864373562646461373130353038c002633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a666f6c643a3a6834353636383533386430663333633839c102553c6e6f64655f72756e74696d653a3a43616c6c2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6837353535376334616233343963343864c2026b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6839343866616433343436333763333337c302713c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6864326561656139613733633032376562c402303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834373363636133666137363238323564c502303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6865376430626436666265346263613032c6024170616c6c65745f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6839353731313363643838396633313431c7024370616c6c65745f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6866363737333036626461616265393838c802703c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6830313763613562653063653830613935c902303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832313435353564666632323365643464ca02466e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6672616d655f73797374656d3a3a6830633334326234616237303465636130cb02486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7574696c6974793a3a6865373134633731386536633331383937cc024170616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6835656566616537343233313161383933cd023f70616c6c65745f617574686f72736869703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6836393161346461326239343762303465ce02486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f696e64696365733a3a6833303730386534323631333464373165cf02496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f62616c616e6365733a3a6831303733353438323565633533643134d002486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7374616b696e673a3a6865643064653264313332323239646531d102486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f73657373696f6e3a3a6833356533353435376435343530353037d2024a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f64656d6f63726163793a3a6832313562303339653333316436656537d302556e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f636f6c6c6563746976655f496e7374616e6365313a3a6836393034363861373333643238613238d402536e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f656c656374696f6e735f70687261676d656e3a3a6831313032646137343336663764623938d502556e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6d656d626572736869705f496e7374616e6365313a3a6862613534353538353861323662386135d602486e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6772616e6470613a3a6861326334613865323935353039616635d702496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f74726561737572793a3a6839326631656130363733383261316562d8024a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f636f6e7472616374733a3a6831393337636661376532613237323361d902456e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f7375646f3a3a6836353032636337663735616564626437da024a6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f696d5f6f6e6c696e653a3a6834653435613762353063343464316438db02496e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6f6666656e6365733a3a6834636332373330353961626437303761dc02466e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f70616c6c65745f6e69636b733a3a6835366535306539333064373565306561dd024f70616c6c65745f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a696e7374616e74696174653a3a6832326261373632396366303536666431de023370616c6c65745f636f6e7472616374733a3a657865633a3a7472616e736665723a3a6835623733373830633633313532376363df023b70616c6c65745f636f6e7472616374733a3a7761736d3a3a636f64655f63616368653a3a6c6f61643a3a6861346530616266646562646265343466e0025d3c70616c6c65745f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732070616c6c65745f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a6833373936663431656533643961633530e10230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6839323739363932333931323433613236e2024870616c6c65745f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a63616c6c3a3a6864633033316339313961306537383037e3024470616c6c65745f636f6e7472616374733a3a72656e743a3a7472795f65766963745f6f725f616e645f7061795f72656e743a3a6861343032333062343565633764656264e402386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836666363343934373036333932653965e502910173705f636f6e73656e7375735f626162653a3a6469676573743a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f636f6e73656e7375735f626162653a3a6469676573743a3a526177426162655072654469676573743e3a3a6465636f64653a3a6839333935336436386439373737303663e6023f7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64655f746f3a3a6830636466336164383938616363636664e7026f3c73705f72756e74696d653a3a67656e657269633a3a6469676573743a3a4469676573744974656d3c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6838303337333562623237333834313037e8027d70616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a656e636f64655f746f3a3a6835323530623238376538306164306265e9027a70616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6e7472616374733a3a5363686564756c653e3a3a656e636f64655f746f3a3a6863663938333065643336333531353234ea026f6e6f64655f72756e74696d653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a656e636f64655f746f3a3a6836376137386661376662656332326335eb028e0170616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6c6c6563746976653a3a5261774576656e743c486173682c4163636f756e7449642c493e3e3a3a656e636f64655f746f3a3a6861373230613961613666326630393362ec024b3c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6833626266343637623864633662303832ed02653c6e6f64655f72756e74696d653a3a43616c6c206173206672616d655f737570706f72743a3a776569676874733a3a4765744469737061746368496e666f3e3a3a6765745f64697370617463685f696e666f3a3a6832336466666435336636333730616331ee02437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6863346363376138366466373739383636ef02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862303236633536616239323834363663f002386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6835656561343837333266623931653131f102437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6837303930386466633335336336656432f2025c3c70616c6c65745f636f6e7472616374733a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6865656235363639326634346438386137f30299013c70616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e206173206672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a6834346165646331333637666330393339f4022b616c6c6f633a3a736c6963653a3a6d657267655f736f72743a3a6835333462383435623435303537353761f5024b6672616d655f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733a3a7365745f6d656d626572735f736f727465643a3a6864316561613432636663376433366638f6025f3c70616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6833326136393365633364343535313964f7025f3c70616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6839303833346133343935386263613330f8025c3c70616c6c65745f64656d6f63726163793a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6833393336356538306530666639646331f9023470616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6c65646765723a3a6832303532323437303062333262343964fa025a3c70616c6c65745f7374616b696e673a3a43616c6c3c543e2061732073705f72756e74696d653a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6836636334343831613130323332643866fb0230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6837656437626162356632326133613931fc0234636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68643033646363643032333334613266662e333032fd027a70616c6c65745f636f6c6c6563746976653a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a6465636f64653a3a6832306261393063323066613839316239fe027770616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722070616c6c65745f636f6e7472616374733a3a5363686564756c653e3a3a6465636f64653a3a6831366564303661643435383133356237ff02386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68383165663961363833346332666166308003386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686532663531626239326664363532653881033b70616c6c65745f626162653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a683238326332373939613238356632656482034470616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a686261376330356538333437363534353083039a013c70616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4578706563746564426c6f636b54696d6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838666661626565313437643830336339840396013c70616c6c65745f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a45706f63684475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68633430313361616334626436636236378503456672616d655f737570706f72743a3a7472616974733a3a4f6e556e62616c616e6365643a3a6f6e5f756e62616c616e6365643a3a68346332306664653937643966323939308603437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68323965316233633266346264313065378703776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6861643534363365383561386433373535880330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a683061373435383062333938666135663989032d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a68316537316164363532346138636331338a0334636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a68356562633662353438653161663466308b032e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a68373863666134393263663635343736398c033c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a68613030356137656437373332353862398d032d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a68396662356535353162363438653036668e0334636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a68306466626330333061643634633136308f032e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a686532616435636463613333656165366590033c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a683737643433363532356235353363353191036a3c70616c6c65745f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732070616c6c65745f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a7b7b636c6f737572657d7d3a3a6834363165613835636565373439396237920381013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6761733a3a683832393736663563613931663533353493035273705f73616e64626f783a3a696d703a3a456e7669726f6e6d656e74446566696e6974696f6e4275696c6465723c543e3a3a6164645f686f73745f66756e633a3a683164653662653434383832323761346494038d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f73746f726167653a3a683365663032343431623732303636343795038d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f73746f726167653a3a6835323430353163376662313831646436960386013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c3a3a683766626664346462313633636138656597038d013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f696e7374616e74696174653a3a6833363832333539313136343336653838980388013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72657475726e3a3a6862636335363630623237373137353964990388013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c65723a3a68633566633035393861633235646461669a0389013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f616464726573733a3a68333563373261613262323631363563369b038b013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f70726963653a3a68616436363866353038396565626366339c038a013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f6c6566743a3a68623266616534376136306534363761399d0389013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f62616c616e63653a3a68393638633730313562363535383131369e0393013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f76616c75655f7472616e736665727265643a3a68326138323661303064616435326361339f0388013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72616e646f6d3a3a6835393831313365656364343137373933a00385013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6e6f773a3a6836333537613832623763353033646637a10391013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6d696e696d756d5f62616c616e63653a3a6836383937636139333363346435333239a2038f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f64697370617463685f63616c6c3a3a6838376337626633363366346235646130a3038c013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f726573746f72655f746f3a3a6830323930633465396639323162386332a4038e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f73697a653a3a6862393135363631396136383463643830a5038e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f726561643a3a6836333231346432376530313835306265a6038f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f77726974653a3a6861313535393136363233303965343461a7038f013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6465706f7369745f6576656e743a3a6839353962356334663832636563306165a80394013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f72656e745f616c6c6f77616e63653a3a6832623434366361313532383235666436a90390013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72656e745f616c6c6f77616e63653a3a6866643134383939303937653061666534aa0389013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7072696e746c6e3a3a6830633039663066346632343861356434ab038e013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f626c6f636b5f6e756d6265723a3a6866616661353534323463333564356231ac0395013c70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732070616c6c65745f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f72756e74696d655f73746f726167653a3a6831346233643664396239353666613662ad033273705f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a6839666663363561336466386264343632ae037973705f636f72653a3a73616e64626f783a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f636f72653a3a73616e64626f783a3a547970656456616c75653e3a3a6465636f64653a3a6837393965313263323335366439656639af030c436f72655f76657273696f6eb00312436f72655f657865637574655f626c6f636bb1039a0173705f72756e74696d653a3a67656e657269633a3a626c6f636b3a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073705f72756e74696d653a3a67656e657269633a3a626c6f636b3a3a426c6f636b3c4865616465722c45787472696e7369633e3e3a3a6465636f64653a3a6834656533356236393861636630643063b203726672616d655f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a696e697469616c697a655f626c6f636b3a3a6865356133393765316565633933613035b3035373705f696f3a3a747269653a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a626c616b65325f3235365f6f7264657265645f726f6f743a3a6865366435356138333535383030323261b4037a6672616d655f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a6170706c795f65787472696e7369635f776974685f6c656e3a3a6863373833666135386161613735636262b503363c5420617320636f72653a3a636f6e766572743a3a496e746f3c553e3e3a3a696e746f3a3a6863633038376137646234363939363637b603346672616d655f73797374656d3a3a4d6f64756c653c543e3a3a66696e616c697a653a3a6832316139643461343938383062326630b70315436f72655f696e697469616c697a655f626c6f636bb803114d657461646174615f6d65746164617461b9031c426c6f636b4275696c6465725f6170706c795f65787472696e736963ba03aa0173705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a5472616e73616374696f6e56616c69646974794572726f723e3a3a656e636f64655f746f3a3a6862646264323936626664623835636135bb031b426c6f636b4275696c6465725f66696e616c697a655f626c6f636bbc035c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a53746f726167654d61703a3a73746f726167655f6d61705f66696e616c5f6b65793a3a6832653263383839613739633763303037bd03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6836373237343262313464303862323462be03437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6835643265366138386162343861346338bf0320426c6f636b4275696c6465725f696e686572656e745f65787472696e73696373c003613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6862353832313833323536613864313866c1033a70616c6c65745f74696d657374616d703a3a657874726163745f696e686572656e745f646174613a3a6838366334646165306539353435363935c2031c426c6f636b4275696c6465725f636865636b5f696e686572656e7473c30318426c6f636b4275696c6465725f72616e646f6d5f73656564c4032b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6ec5035373705f72756e74696d653a3a7472616e73616374696f6e5f76616c69646974793a3a56616c69645472616e73616374696f6e3a3a636f6d62696e655f776974683a3a6863306664353332653331666262396139c6036b3c70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e2061732073705f72756e74696d653a3a7472616974733a3a56616c6964617465556e7369676e65643e3a3a76616c69646174655f756e7369676e65643a3a6865656463666265653935343636383731c7036d3c70616c6c65745f636f6e7472616374733a3a436865636b426c6f636b4761734c696d69743c543e2061732073705f72756e74696d653a3a7472616974733a3a5369676e6564457874656e73696f6e3e3a3a76616c69646174653a3a6862373862356461653538383232653237c803214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b6572c9033c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6834306363316462656531303931313862ca035173705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a737232353531395f7075626c69635f6b6579733a3a6865376563383264373331366537633634cb033d70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a69735f6f6e6c696e655f6175783a3a6862356231353765633561616434363865cc034d73705f696f3a3a6f6666636861696e3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a6e6574776f726b5f73746174653a3a6830396534323362366564323963366166cd034a73705f696f3a3a63727970746f3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a737232353531395f7369676e3a3a6836663434363937383765343964373930ce0347636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207533323e3a3a666d743a3a6838363464316333323636306339633731cf035273705f696f3a3a6f6666636861696e3a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a7375626d69745f7472616e73616374696f6e3a3a6838623566663034306534376665376361d0031e4772616e6470614170695f6772616e6470615f617574686f726974696573d10315426162654170695f636f6e66696775726174696f6ed20321417574686f72697479446973636f766572794170695f617574686f726974696573d3031d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e6365d40311436f6e7472616374734170695f63616c6cd5033970616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a626172655f63616c6c3a3a6837303661643265393163653731303739d60318436f6e7472616374734170695f6765745f73746f72616765d703205472616e73616374696f6e5061796d656e744170695f71756572795f696e666fd8032153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b657973d903920173705f6170706c69636174696f6e5f63727970746f3a3a737232353531393a3a3c696d706c2073705f6170706c69636174696f6e5f63727970746f3a3a7472616974733a3a52756e74696d655075626c696320666f722073705f636f72653a3a737232353531393a3a5075626c69633e3a3a67656e65726174655f706169723a3a6834303163333038393536343766666465da03437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6837633730653935383335323639393465db03497061726974795f7363616c655f636f6465633a3a656e636f64655f617070656e643a3a657874726163745f6c656e6774685f646174613a3a6865353662303462383663623635643834dc03463c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6831343538373833363663336562346432dd0330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6864353433303538313032363234343937de033a6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6864386131663131646266646566643135df033c6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6865313863353962636230613764663333e003683c6672616d655f73797374656d3a3a5f5f476574427974655374727563744576656e74733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830376635316334636261383861316336e103703c6672616d655f73797374656d3a3a5f5f4765744279746553747275637445787472696e73696373526f6f743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864353537633762386430363766396665e203703c6672616d655f73797374656d3a3a5f5f4765744279746553747275637445787472696e736963436f756e743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831333131323135376233363736306466e3034b6672616d655f73797374656d3a3a4d6f64756c653c543e3a3a72656769737465725f65787472615f7765696768745f756e636865636b65643a3a6864623034623866663233326632656236e403386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831336139376131376261393035653865e503386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6834333832353964653862613233333933e603386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6834616230366132303635383439323666e703386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6838306363633039626364303834363063e803386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6838316464346630313863333664393166e903386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6838343164666663366435386465313038ea03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861313831336636616462323432333937eb03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862303162393434313733366532333434ec03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6862656434366233353038643332323461ed03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863343437613134666339636461616164ee03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863393339373530323237373636313161ef03386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6863643837313837313063313765643835f003386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864373336326161363435613535306166f103386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864623862613366623331313731343035f203386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864663661393936393464326133626263f303386672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6866643363336564353837393337626265f403396672616d655f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6830376334313532326432363264313631f5033e70616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6862346565376563393533383465616432f6034070616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838313838306265303166623134316334f7034970616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864383162383264323863313066363434f8039b013c70616c6c65745f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839353334396631633866373439626262f9034a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6834303334303333333138636638653365fa035d3c6672616d655f73797374656d3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6862316332303035363335656234623235fb03723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6832313031333834656538356435323836fc03776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6836623432633266666538326130393866fd034a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6833393338393133666462613939666539fe033e70616c6c65745f696e64696365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6831613130346635343136366432353737ff034470616c6c65745f636f6e7472616374733a3a7761736d3a3a707265706172653a3a707265706172655f636f6e74726163743a3a683062356338306265333761343262613180044170616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a683531363032653633613730653236616681044370616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a683035656363373730386634623631336182044370616c6c65745f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6862313966353235666338366535656539830430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a683031303437313639323337323264663284046e6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f686561645f6b65793a3a68316234363762666335363161616266308504437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6831613234626632616361366335656232860484016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654c696e6b65644d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6862373866643537386630656261663333870484016672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654c696e6b65644d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a68396430333035346632326238363964358804776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a68613265636165656463316132646130648904696672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a68393765326535326461646531313536388a046e6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f686561645f6b65793a3a68343563643637353933386238346335358b04696672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a68306261336131353364303737316631318c04437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68393466646431643731623663303066358d04706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68613862643263393662326637613766308e04706672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68653134613631346330636165323331648f04746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a68636564386664313431313161366366379004746672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a68643164663436356636613637383938659104776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a683464666138653137313464393066313792043570616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a7374616b6572733a3a686139383637323666383336303063383093043970616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d616b655f7061796f75743a3a6864313637336162613732663965646539940485013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6836346435353062393966643230353330950485013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a683937613039363566656465613331623796044270616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a736c61736861626c655f62616c616e63655f6f663a3a683535343366383963303735303564346197043570616c6c65745f7374616b696e673a3a736c617368696e673a3a646f5f736c6173683a3a686332363038393237623837383538336498043470616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a626f6e6465643a3a683839663636636233353533643030313499043b70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a7570646174655f6c65646765723a3a68646265616666346136653666363566309a043c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68656530343266313432613835356430369b043c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a656e737572655f6e65775f6572613a3a68373430373663333833663033646235379c043e70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68346266656333613839663137323063379d046d3c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563745370616e536c6173683c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68613037346162393261303431376566319e043c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68336365633735643661396262626639669f047a3c70616c6c65745f7374616b696e673a3a5f5f4765744279746553747275637443757272656e74457261506f696e74734561726e65643c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863376631626132613433653963313162a0046b3c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563745374616b6572733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865613366653531333364636535633362a1046e3c70616c6c65745f7374616b696e673a3a5f5f4765744279746553747275637456616c696461746f72733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838373665646230666362636430336631a204793c70616c6c65745f7374616b696e673a3a5f5f476574427974655374727563744d696e696d756d56616c696461746f72436f756e743c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862336465636164303365366134386538a3044770616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6863666165643262356336623965333535a4049b013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426f6e64696e674475726174696f6e44656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830313235303663353735643265623565a5049a013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53657373696f6e7350657245726144656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865373262353738313634366363633364a604f4013c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e2061732073705f7374616b696e673a3a6f6666656e63653a3a4f6e4f6666656e636548616e646c65723c3c54206173206672616d655f73797374656d3a3a54726169743e3a3a4163636f756e7449642c283c542061732070616c6c65745f73657373696f6e3a3a54726169743e3a3a56616c696461746f7249642c203c542061732070616c6c65745f73657373696f6e3a3a686973746f726963616c3a3a54726169743e3a3a46756c6c4964656e74696669636174696f6e293e3e3a3a6f6e5f6f6666656e63653a3a6866613737366239346465303632306339a7044970616c6c65745f7374616b696e673a3a736c617368696e673a3a496e7370656374696e675370616e733c543e3a3a6572615f7370616e3a3a6838366262383863623937303464393733a8045e70616c6c65745f7374616b696e673a3a736c617368696e673a3a496e7370656374696e675370616e733c543e3a3a636f6d706172655f616e645f7570646174655f7370616e5f736c6173683a3a6863383939623233616464333339653162a904776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6863376632353462353864303266356330aa04776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6832653435393235636238343838363964ab045f3c70616c6c65745f7374616b696e673a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a6864663361383665313165326330613131ac047c73705f636f72653a3a73616e64626f783a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073705f636f72653a3a73616e64626f783a3a547970656456616c75653e3a3a656e636f64655f746f3a3a6835303033393930366337346337653133ad043a70616c6c65745f6e69636b733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6830626331323832373834343462343430ae043c70616c6c65745f6e69636b733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6833653564386563643561636636636336af04683c70616c6c65745f6e69636b733a3a5f5f476574427974655374727563744e616d654f663c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862373963653062303932373566306235b0044570616c6c65745f6e69636b733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6836633639623331633931363235663061b10493013c70616c6c65745f6e69636b733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d61784c656e67746844656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866613266376537333166366463353638b20493013c70616c6c65745f6e69636b733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e4c656e67746844656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862346636666664633532313932643738b30498013c70616c6c65745f6e69636b733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5265736572766174696f6e46656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865326236636531313333333639636137b404a40170616c6c65745f636f6e7472616374733a3a5f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722070616c6c65745f636f6e7472616374733a3a526177416c697665436f6e7472616374496e666f3c436f6465486173682c42616c616e63652c426c6f636b4e756d6265723e3e3a3a656e636f64655f746f3a3a6863383832643532316638353366336564b5043c70616c6c65745f7574696c6974793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6837373430346561386338353634373830b6043e70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6863613130306165323039653137616436b7044070616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863643030636266656532613462616236b8046e3c70616c6c65745f636f6e7472616374733a3a5f5f4765744279746553747275637447617350726963653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836396639353733343466633536306164b904723c70616c6c65745f636f6e7472616374733a3a5f5f476574427974655374727563745072697374696e65436f64653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833656262313563313335653839326638ba04753c70616c6c65745f636f6e7472616374733a3a5f5f4765744279746553747275637443757272656e745363686564756c653c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832626137366163666262306131396463bb044970616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6833303766643630326438633661326466bc049b013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426c6f636b4761734c696d697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835313236386638363365303435313833bd049a013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d617856616c756553697a6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834613938616562663836336338363061be0496013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178446570746844656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861336134353736323263333766643566bf0499013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616c6c4261736546656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836316236636438383737666230316232c00499013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a436f6e747261637446656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861656638353163396466666538323832c104a0013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5472616e73616374696f6e4279746546656544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865376265633864323265386236313134c2049d013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53757263686172676552657761726444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832616164666265346461626362623061c3049f013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744465706f7369744f666673657444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865613235623931646333386633323436c4049f013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53746f7261676553697a654f666673657444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833656334373565343933356334366131c504a1013c70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5369676e6564436c61696d48616e646963617044656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837666165316435346538656638616566c6043a70616c6c65745f636f6e7472616374733a3a4d6f64756c653c543e3a3a726573746f72655f746f3a3a6838383834303261633336356464333330c70468636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a6832373033646335626530613563333033c804303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6861373566643361323861303633323135c9043f70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f65787465726e616c3a3a6830663338303335366563386530383330ca044170616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a696e6a6563745f7265666572656e64756d3a3a6863663632336438373165656632373862cb043d70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f7075626c69633a3a6866666638326166383835356230343433cc043a70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6465706f7369745f6f663a3a6830636466323965663165326236616236cd043a70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f746572735f666f723a3a6863393337643463373266393363303938ce043770616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f74655f6f663a3a6837616261373761373133353661316435cf043f70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a64656c6567617465645f766f7465733a3a6837653665313337336138376332386463d0046e6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f686561645f6b65793a3a6866623666376164373336386265346461d10485013c6672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6832623939396139363062356566346663d2044070616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a636c6561725f7265666572656e64756d3a3a6838626462356637316233626435393362d3044470616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a69735f6163746976655f7265666572656e64756d3a3a6864656636333939636537613131353738d4043e70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a656e6163745f70726f706f73616c3a3a6835303134363437616661373438303239d504696672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4b6579466f726d61743a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a6861656338393461373934303038363231d6043e70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6830353630323331353563613139343066d7043f70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a7265666572656e64756d5f696e666f3a3a6831303532303362366331396534373361d8044070616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6830366365626437653266396564343636d904713c70616c6c65745f64656d6f63726163793a3a5f5f4765744279746553747275637444656c65676174696f6e733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864366330356464303430663562363266da04713c70616c6c65745f64656d6f63726163793a3a5f5f476574427974655374727563745075626c696350726f70733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833313064376238666434646530376638db046f3c70616c6c65745f64656d6f63726163793a3a5f5f47657442797465537472756374507265696d616765733c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834313733393265306238336530343933dc044970616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6833306361623563323430306330623664dd049a013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4c61756e6368506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830383238616561626231663365663036de04a3013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456d657267656e6379566f74696e67506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830626362633230313966633365356432df049c013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d4465706f73697444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834613932643534346539323537613938e0049d013c70616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456e6163746d656e74506572696f6444656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834663232623435376330356432373666e1043770616c6c65745f64656d6f63726163793a3a4d6f64756c653c543e3a3a646f5f766f74653a3a6864626337643035373335343236353864e204437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6831656534623862623665633334346631e304776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6839363738326133363232653334376463e404776672616d655f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c206672616d655f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6831373361303363333334633331623939e5043a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6831363961323463373930356537373064e6043b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a6832323266643037313766353134613637e7043a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a6866636663633838663537623765663538e8044570616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6863646134666362383933396130613263e9045070616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6861326334356566666537623665313533ea04a2013c70616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5265706f72744c6174656e637944656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831313036343934373861303836643466eb049f013c70616c6c65745f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a57696e646f7753697a6544656661756c74427974654765747465723c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836326333306430656431383863383162ec044a70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a726561645f73616e64626f785f6d656d6f72795f61733a3a6834366661323064396162383430356133ed044a70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a726561645f73616e64626f785f6d656d6f72795f61733a3a6831386161383632633430323835326432ee044a70616c6c65745f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a726561645f73616e64626f785f6d656d6f72795f61733a3a6866333037336461633765393935323731ef043970616c6c65745f7375646f3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6863306334643364653439363339646466f0043b70616c6c65745f7375646f3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6863326633323438653436373337626635f104643c70616c6c65745f7375646f3a3a5f5f476574427974655374727563744b65793c543e206173206672616d655f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832346365323165376132336166616565f204443c7061726974795f7761736d3a3a696f3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862626330636137626662343333633462f3046f3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6831376163326630616264656532346361f404467061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a436f646553656374696f6e3a3a626f646965733a3a6838663764663834333537393666356633f50430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6835633232633265326565653635323932f604347761736d695f76616c69646174696f6e3a3a76616c69646174655f6d6f64756c653a3a6833396334343731636535336563363663f70448616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6837616265383962626632303261346162f8043c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a66726f6d5f6d6f64756c653a3a6834306534616135306130366163616237f904537061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a7265736f6c76655f747970655f7265663a3a6837643333376361303561343432653738fa04a9017061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c6553636166666f6c643e20666f72207061726974795f7761736d3a3a656c656d656e74733a3a6d6f64756c653a3a4d6f64756c653e3a3a66726f6d3a3a6866353238366462353563323464653737fb0444707761736d5f7574696c733a3a6761733a3a436f756e7465723a3a66696e616c697a655f6d6574657265645f626c6f636b3a3a6833616433383030346633386133663463fc042d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6838333631616236366561303832663361fd04507061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a707573685f66756e6374696f6e3a3a6865333838353439346263393466356437fe043c707761736d5f7574696c733a3a737461636b5f6865696768743a3a696e6a6563745f6c696d697465723a3a6838396563663863636434633736616265ff046b3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683431306363396531343663366661356580053e70616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683862623464633534353962353932323281054070616c6c65745f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a686239366639303363363762306263393482055c3c70616c6c65745f7375646f3a3a4d6f64756c653c543e206173206672616d655f6d657461646174613a3a4d6f64756c654572726f724d657461646174613e3a3a6d657461646174613a3a68333839643666653565376237396532318305303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68636638346162623137383237333932658405553c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68353835616362326562383932396166368505683c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683434333430343439303938323330653286056b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683739376236316561353161393636306487057d3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973745772697465723c492c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683132623563316331616266643862333888056f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683366663537313539366537653830643189056f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743634206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68343431346439393861623137653161628a056c3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68386164666635666263623432383264668b056f3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68666337353863623432333063353062628c05793c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973743c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68313137336462633139616635663038318d056b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68623664626331363265343535626432658e0586017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a646573657269616c697a653a3a68323631383336326636313263303634628f05323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68303764636439303837313166363931669005783c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a686164626337643961663935386636383491057c3c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68663132633033646138343339623933639205743c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a68303638333134363932333033646137319305713c7061726974795f7761736d3a3a656c656d656e74733a3a696e6465785f6d61703a3a496e6465784d61703c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68393831386362616434633834303464369405713c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a437573746f6d53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683436313830336638343234393335633995054b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a686235616630386664353539396565333896054b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683739653534613964373562336230393497054b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68376361323533356363396132313638629805463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68366231383362343032303964383865319905457061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e5265616465723a3a6e65773a3a68346661663864393066613365313638389a052d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a68626139663135616136343161653235309b0534636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a68353336393865613838643861663834399c052e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a68323633326161326239646165356337649d053c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a68623365383161303365383166636338339e053b636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a7b7b636c6f737572657d7d3a3a68323763393165626334386634386465659f05397761736d695f76616c69646174696f6e3a3a76616c69646174655f6d656d6f72795f747970653a3a6864663634333332633766626438633432a005347761736d695f76616c69646174696f6e3a3a657870725f636f6e73745f747970653a3a6832326664316639356333636231313630a105553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839666437616538373835366430316461a2054a7761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a737465703a3a6862323839316131316434336364343133a305473c7761736d695f76616c69646174696f6e3a3a4572726f7220617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6864643662363530323039323935373533a405457061726974795f7761736d3a3a656c656d656e74733a3a7365676d656e743a3a446174615365676d656e743a3a76616c75653a3a6862303131346363663262366537353533a505303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831303336616631333137333866666463a605553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a426c6f636b5479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830653437616536336563303965633565a705303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831383035343164353436333434636436a805303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832366364303465616461616238646562a905303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830303337623063666334356336633536aa05303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6866633234323466343564323330653732ab0540707761736d5f7574696c733a3a737461636b5f6865696768743a3a636f6d707574655f737461636b5f636f73743a3a6861383435386566663533663265363332ac0533636f72653a3a6f7074696f6e3a3a4f7074696f6e3c26543e3a3a636c6f6e65643a3a6836626434623761383039383537363662ad05533c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a737065635f657874656e643a3a6863343831386165383834306263313032ae05323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6833616433306430653031313762633766af053f707761736d5f7574696c733a3a737461636b5f6865696768743a3a7265736f6c76655f66756e635f747970653a3a6834366532623066383536386231623661b00530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6831623135336435366235333338356637b10530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6862363832646630613931653164303464b205593c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6863653837306165633766323261613863b30541707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a636f6d707574653a3a6863333935303935633464373936653564b405303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836393136343230633165356432373138b5052e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6835623233343736336633653430343262b6053c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6830613931333337636638393664353239b70530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6830343934303264626232626362326331b805303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830346632616164323362303163316266b9055a3c707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a4672616d6520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839316133646631363939373530393563ba0546707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a6672616d653a3a6830633432373339383166336635333338bb05453c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834393962336539376330626639376535bc054b707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a706f705f76616c7565733a3a6862333162626434643036653964336633bd053a73705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6c73747269703a3a6834376664393665323232663766656339be053773705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6164643a3a6863323963646631616334313266336164bf053773705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6d756c3a3a6865353262376135316538336335656365c0054473705f61726974686d657469633a3a62696775696e743a3a42696755696e743a3a6469763a3a7b7b636c6f737572657d7d3a3a6861346666653066363462623436643663c1054b3c73705f61726974686d657469633a3a62696775696e743a3a42696755696e7420617320636f72653a3a636d703a3a4f72643e3a3a636d703a3a6865623666666435386536323939363233c205303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862323133643330653933653133656533c305513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6835626265366330386465393138313139c4053d73705f61726974686d657469633a3a68656c706572735f3132386269743a3a746f5f6269675f75696e743a3a6862373932666633323261643264313838c505413c73705f696e686572656e74733a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835353763303239663963616564323235c605323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6837393630363235643632323430633336c7054273705f696f3a3a6c6f6767696e673a3a65787465726e5f686f73745f66756e6374696f6e5f696d706c733a3a6c6f673a3a6837386534633336393930333566653861c80537616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6830636362626338393566386263633566c9053b636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f70795f66726f6d5f736c6963653a3a6864663963663731393765306431373335ca05347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f76616c75653a3a6834353137643035633663613263643834cb05347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f6c6162656c3a3a6838613333333461353062306330353431cc05407761736d695f76616c69646174696f6e3a3a7574696c3a3a4c6f63616c733a3a747970655f6f665f6c6f63616c3a3a6833313733656330356634666330323965cd05543c7761736d695f76616c69646174696f6e3a3a66756e633a3a537461636b56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839363837303466613037393139383633ce05537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6c6f61643a3a6861373464623266646363333161353135cf05547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f73746f72653a3a6866373436643436323235303932383130d005557761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f746573746f703a3a6838653431343333313362383138613731d105547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f72656c6f703a3a6837393565626431333832336662373036d205537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f756e6f703a3a6830313438353937363834636364613539d305547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f62696e6f703a3a6837643766643064373634313036636463d405547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6376746f703a3a6839633331373666373462333563383835d50530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6834373766646265336435653437383130d605303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6833356532653635376130666438323431d705303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837303936346436613136313366643164d805453c616c6c6f633a3a737472696e673a3a537472696e6720617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6832373633323236316338353530643631d9054c3c7761736d695f76616c69646174696f6e3a3a737461636b3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6866306332323565353935633565313530da05066d656d736574db05066d656d637079dc05076d656d6d6f7665dd050462636d70de05095f5f6173686c746933df05095f5f6c736872746933e005085f5f6d756c746933e105095f5f75646976746933e205095f5f756d6f64746933e3050c5f5f756469766d6f6474693400550970726f64756365727302086c616e6775616765010452757374000c70726f6365737365642d62790105727573746325312e34312e302d6e696768746c79202837366132353265613920323031392d31322d303929", + "0x2099d7f109d6e535fb000bba623fd4409f99a2ce711f3a31b2fc05604c93f179": "0x10c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479e225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41ee410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86cfe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310a", + "0x5c0d1176a568c1f92944340dbfed9e9c530ebca703c85910e7164cb7d1c9e47b": "0xcc2a4f3c61e593c5c704149f3ee3c3028b3b382ba9f42ee767b1953c5fcb8f1f", + "0xc2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b46b1ab1274bcbe3a4176e17eb2917654904f19b3261911ec3f7a30a473a04dcc8": "0x00407a10f35a00000000000000000000", + "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7": "0x08000000000002006d6f646c70792f747273727900000000000000000000000000000000000000000500000000000000000003006d6f646c70792f7472737279000000000000000000000000000000000000000000407a10f35a0000000000000000000000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973952c9ffc8f4d8900648af298fd29c4312871633ff0e759d98574f05e67ec56bc": "0xcafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367", + "0xf2794c22e353e9a839f12faab03a911b7f17cdfbfa73331856cca0acddd7842e": "0x00000000", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb39fe6329cc0b39e09343a73657373696f6e3a6b657973e4fe34f5c8499d222649809260ad8db63c739e091b73cda907a2df171176070a": "0x7e8a1b8e637a062656eff12dc94bbbc3e254d9bb93bd44972f0a96c7fdde5b4de225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41ee225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41ee225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41e", + "0xf2794c22e353e9a839f12faab03a911be2f6cb0456905c189bcb0458f9440f13": "0x00000000", + "0x5f3e4907f716ac89b6347d15ececedcac29a0310e1bb45d20cace77ccb62c97d": "0x00e1f505", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc685268962a32b3f1cffce32ce1e5f6d6d3d633f7e21fd4e659402a2c62cab64ca": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff1f", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe7066e551402e9db966f769da2a411eff2face196c91278147bbfcf405002e875ac": "0xc2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973ddaecd8f3d7c1d983083cdb5cbd354701308d13ec10c81d42da58c5eb1d15264": "0xcafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc604615f785492f37abe2b14d3f286778c2c9752548ca2d011e952c455b2733bfe": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff1f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b6579737e0c1544454d51abcabc70ab73b47a3b401c92709958ddab7740094a7135ae16": "0xcafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367", + "0x8985776095addd4789fccbce8ca77b23ba7fb8745735dc3be2a2c61a72c39e78": "0x046e51d621d637695a1c4214ff5b85fb0063fe3908f8b39c380c582011c3807078", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973dfa2eac750730cfcb981664732807d8dff47c246f7d78f6f8bbaaca9f15fd3b0": "0xf417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e29", + "0x5f3e4907f716ac89b6347d15ececedcab49a2738eeb30896aacb8b3fb46471bd": "0x04000000", + "0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac": "0x01000000", + "0x5f3e4907f716ac89b6347d15ececedca28dccb559b95c40168a1b2696581b5a7": "0x00000000000000000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1": "0x04000000", + "0x5f3e4907f716ac89b6347d15ececedca0ea0ecac76457d0f9b39b981dd107012": "0x10cafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367f417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e292a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761dc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a", + "0x34b9dcaacddd89d5a94929dccb7131534a9d2f70e9ee596bc867d128cd9ec759": "0x00ca9a3b000000000000000000000000", + "0xc2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80": "0x00401eae822458363600000000000000", + "0xc2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4e0f0f8a6ceacf3a6c5f142248962532609453d6bbff30954e62c7267960c4624": "0x0000a0dec5adc9353600000000000000", + "0xcec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903": "0x10cafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367f417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e292a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761dc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a", + "0x26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc": "0x4545454545454545454545454545454545454545454545454545454545454545", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e1690304615f785492f37abe2b14d3f286778c2c9752548ca2d011e952c455b2733bfe": "0x0001f417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e2901dc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a", + "0x1cb6f36e027abb2091cfb5110ab5087f66e8f035c8adbe7f1547b43c51e6f8a4": "0x00000000", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb39fe6329cc0b39e09343a73657373696f6e3a6b65797385268962a32b3f1cffce32ce1e5f6d6d3d633f7e21fd4e659402a2c62cab64ca": "0xf6e62e9231c0424c1b747ffb5ccaedcb9fd6fddc2bfcb2db963c02db74c0c84dfe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310afe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310afe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310a", + "0x5f3e4907f716ac89b6347d15ececedca308ce9615de0775a82f8a94dc3d285a1": "0x01000000", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe70e4fe34f5c8499d222649809260ad8db63c739e091b73cda907a2df171176070a": "0xe225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41e", + "0x2b06af9719ac64d755623cda8ddd9b949f99a2ce711f3a31b2fc05604c93f179": "0x10c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479e225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41ee410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86cfe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310a", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc4f6ba35a8ebc8b98cc00cf8bebd411ecde353b5cc097d55297f372120235907d6": "0x2a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b227610f0000c16ff286230f0000c16ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca83e585bbc5fdcec57219c0dc81ef5ff4e4fe34f5c8499d222649809260ad8db63c739e091b73cda907a2df171176070a": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0xc2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4e4fe34f5c8499d222649809260ad8db63c739e091b73cda907a2df171176070a": "0x0000c16ff28623000000000000000000", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb39fe6329cc0b39e09343a73657373696f6e3a6b65797304615f785492f37abe2b14d3f286778c2c9752548ca2d011e952c455b2733bfe": "0x5202d3e9c3bf075b44615f9ac4c28b8627079a219ff66e01655487c3bde52eb8e410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86ce410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86ce410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86c", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb39fe6329cc0b39e09343a73657373696f6e3a6b65797366e551402e9db966f769da2a411eff2face196c91278147bbfcf405002e875ac": "0xe23578cbc267982cfc0bf7be54cd952fa3c07631850880ca88e395e25f4812c7c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb8842303479", + "0x1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d": "0x10c2ecc9feda5c727ce1f77e6a662efd98f39212fea555b286b702eb88423034790100000000000000e225a23a02d254dee5384fe46fc083306e597a85b31c75f4e8674349d8f7a41e0100000000000000e410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86c0100000000000000fe451858d3bff3683df83e029f44d62cc4f285f7a1004542679ffa35ed68310a0100000000000000", + "0x3a65787472696e7369635f696e646578": "0x00000000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc44bb3d65784ee237cb19a67a937611263a136c75414ebcc385bda1a5c4ceb1edf": "0xf417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e290f0000c16ff286230f0000c16ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca83e585bbc5fdcec57219c0dc81ef5ff466e551402e9db966f769da2a411eff2face196c91278147bbfcf405002e875ac": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca83e585bbc5fdcec57219c0dc81ef5ff485268962a32b3f1cffce32ce1e5f6d6d3d633f7e21fd4e659402a2c62cab64ca": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca6a93112633bb3354e67952fcdd740cd5": "0xcafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc666e551402e9db966f769da2a411eff2face196c91278147bbfcf405002e875ac": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff1f", + "0xc2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b485268962a32b3f1cffce32ce1e5f6d6d3d633f7e21fd4e659402a2c62cab64ca": "0x0000c16ff28623000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedca5579297f4dfb9609e7e4c2ebab9ce40a": "0x10dc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a2a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761f417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e29cafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e16903e4fe34f5c8499d222649809260ad8db63c739e091b73cda907a2df171176070a": "0x0001cafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367012a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973a9e863aa4e88bfe99fb4f5250d395dfc9ad8361f732d3f33f982630685e1b467": "0xf417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e29", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797333a25791b4e76010f327045d60a8a9b6cbaa4175acec26fc9c64923cb2ed0b33": "0xcafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd367", + "0x34b9dcaacddd89d5a94929dccb713153d2d505c0e6f76fd7ce0796ebe187401c": "0x0000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000008700000000000000af0000000000000001000000000000000100000000000000040000000000010010000000004000000120000000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797358c81ce9d318af53a0c8e04a468dbe3d064a96be56550cde6a930f94d820eef4": "0x2a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761", + "0x5f3e4907f716ac89b6347d15ececedca83e585bbc5fdcec57219c0dc81ef5ff404615f785492f37abe2b14d3f286778c2c9752548ca2d011e952c455b2733bfe": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade98e4fe34f5c8499d222649809260ad8db63c739e091b73cda907a2df171176070a": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc4370973789ee011f45a1b1a15e8ca4cb78a4c6002b9dc5c7454f0ddc806bf0415": "0xdc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a0f0000c16ff286230f0000c16ff2862300", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973bb0478b410b24d65023203a9b253562f2dac70ebbbce3493919331ba6d09510e": "0xf417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e29", + "0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850": "0x02000000", + "0x5f3e4907f716ac89b6347d15ececedca422adb579f1dbf4f3886c5cfa3bb8cc473d92918a8bc8bb6704158faa13f857c8503f88a105844949122c4ae959b09ba": "0xcafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd3670f0000c16ff286230f0000c16ff2862300", + "0x5f3e4907f716ac89b6347d15ececedca9cbd2f0b29a008a36009ac44cca0c969": "0xf6ffc06ff28623000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e1690385268962a32b3f1cffce32ce1e5f6d6d3d633f7e21fd4e659402a2c62cab64ca": "0x00012a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b2276100", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b65797395a5c6fffae0bd453a2681fc02f692a2ce7e7b27a8b53de6741bccabd205d271": "0x2a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973573bf64cfb7e8c308bcf0394ae44b7cbf6c3d1f3574a78f3c565015d96ea9c15": "0x2a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761", + "0xc2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b466e551402e9db966f769da2a411eff2face196c91278147bbfcf405002e875ac": "0x0000c16ff28623000000000000000000", + "0xf2794c22e353e9a839f12faab03a911bbdcb0c5143a8617ed38ae3810dd45bc6": "0x00000000", + "0x492a52699edf49c972c21db794cfcf57ba7fb8745735dc3be2a2c61a72c39e78": "0x00", + "0x5f3e4907f716ac89b6347d15ececedca3ed14b45ed20d054f05e37e2542cfe7004615f785492f37abe2b14d3f286778c2c9752548ca2d011e952c455b2733bfe": "0xe410a5800082ee863e06344590e83ef0b60fb6ea2126086ea9bc5c579ff4b86c", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973f301a28bea294f7ef32e6577fe7067ce573431f351098b6d032a3319ecfe571a": "0x2a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade9866e551402e9db966f769da2a411eff2face196c91278147bbfcf405002e875ac": "0x00", + "0x5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3": "0x00", + "0xc2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b404615f785492f37abe2b14d3f286778c2c9752548ca2d011e952c455b2733bfe": "0x0000c16ff28623000000000000000000", + "0x1a736d37504c2e3fb73dad160c55b291b35b5a09b938edfd10fcbacc615abb0c": "0x00000000", + "0x5f3e4907f716ac89b6347d15ececedca88dcde934c658227ee1dfafcd6e1690366e551402e9db966f769da2a411eff2face196c91278147bbfcf405002e875ac": "0x000001f417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e29", + "0x11f3ba2e1cdd6d62f2ff9b5589e7ff81ba7fb8745735dc3be2a2c61a72c39e78": "0x046e51d621d637695a1c4214ff5b85fb0063fe3908f8b39c380c582011c3807078", + "0xc2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6e4fe34f5c8499d222649809260ad8db63c739e091b73cda907a2df171176070a": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff1f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b6579734d9b18cf80e6a057b2af8cf177dcae65db7aecaf46b2787909eb9f3bcdb662dc": "0xdc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade9804615f785492f37abe2b14d3f286778c2c9752548ca2d011e952c455b2733bfe": "0x00", + "0x26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c11874611da6d1f761ddf9bdb4c9d6e5303ebd41f61858d0a5647a1a7bfe089bf921be9": "0x4545454545454545454545454545454545454545454545454545454545454545", + "0x3a6772616e6470615f617574686f726974696573": "0x0110e23578cbc267982cfc0bf7be54cd952fa3c07631850880ca88e395e25f4812c701000000000000007e8a1b8e637a062656eff12dc94bbbc3e254d9bb93bd44972f0a96c7fdde5b4d01000000000000005202d3e9c3bf075b44615f9ac4c28b8627079a219ff66e01655487c3bde52eb80100000000000000f6e62e9231c0424c1b747ffb5ccaedcb9fd6fddc2bfcb2db963c02db74c0c84d0100000000000000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973a1243cfbda382a96e2fffd4d8c847b04aa4ac7719037b42dc283987272fb6852": "0xdc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973b84da33d6821a3ecdab06fb5517b5338b39edf649f3c0cdebf9a6322e2976a2f": "0xdc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973caf51cb2812dec8599a1e85e56ec7627cced6492a6a60f1e70ddcd14e06ae799": "0xdc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a", + "0x1a736d37504c2e3fb73dad160c55b2917ac6a308d645671864cda07d358e751211da6d1f761ddf9bdb4c9d6e5303ebd41f61858d0a5647a1a7bfe089bf921be9": "0x186e51d621d637695a1c4214ff5b85fb0063fe3908f8b39c380c582011c3807078dc94ff7f625d9ef7824766f90a5eb8aa03f99b7b28664585950221d0d2358e3a2a009220d327910e8ffd89167b7d96eb8871a37c374ec0adfdf1b6c384b22761f417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e29cafad6120836227e4660c07c046c2b56e8fba10cbf3fcfdcc566d774e14fd3676d6f646c70792f74727372790000000000000000000000000000000000000000", + "0x5f3e4907f716ac89b6347d15ececedca9220e172bed316605f73f1ff7b4ade9885268962a32b3f1cffce32ce1e5f6d6d3d633f7e21fd4e659402a2c62cab64ca": "0x00", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509fe6329cc0b39e09343a73657373696f6e3a6b657973fdc59ca6b20d398f03a062a5e1bc32e350fe13cda745936e92daa3a75acb8853": "0xf417395797ff444345d7c25355bbab14de5ca8857104a028d969147a4fbd6e29" + }, + "children": {} + } + } +} diff --git a/bin/node/cli/src/browser.rs b/bin/node/cli/src/browser.rs new file mode 100644 index 0000000000000..9747a583c7808 --- /dev/null +++ b/bin/node/cli/src/browser.rs @@ -0,0 +1,56 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::ChainSpec; +use log::info; +use wasm_bindgen::prelude::*; +use sc_service::Configuration; +use browser_utils::{ + Transport, Client, + browser_configuration, set_console_error_panic_hook, init_console_log, +}; + +/// Starts the client. +#[wasm_bindgen] +pub async fn start_client(wasm_ext: Transport) -> Result { + start_inner(wasm_ext) + .await + .map_err(|err| JsValue::from_str(&err.to_string())) +} + +async fn start_inner(wasm_ext: Transport) -> Result> { + set_console_error_panic_hook(); + init_console_log(log::Level::Info)?; + + let chain_spec = ChainSpec::FlamingFir.load() + .map_err(|e| format!("{:?}", e))?; + + let config: Configuration<(), _, _> = browser_configuration(wasm_ext, chain_spec) + .await?; + + info!("Substrate browser node"); + info!(" version {}", config.full_version()); + info!(" by Parity Technologies, 2017-2019"); + info!("Chain specification: {}", config.chain_spec.name()); + info!("Node name: {}", config.name); + info!("Roles: {:?}", config.roles); + + // Create the service. This is the most heavy initialization step. + let service = crate::service::new_light(config) + .map_err(|e| format!("{:?}", e))?; + + Ok(browser_utils::start_client(service)) +} diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs new file mode 100644 index 0000000000000..26b1f6d2949e3 --- /dev/null +++ b/bin/node/cli/src/chain_spec.rs @@ -0,0 +1,406 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate chain configurations. + +use sc_chain_spec::ChainSpecExtension; +use sp_core::{Pair, Public, crypto::UncheckedInto, sr25519}; +use serde::{Serialize, Deserialize}; +use node_runtime::{ + AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, + GrandpaConfig, ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig, + SystemConfig, TechnicalCommitteeConfig, WASM_BINARY, +}; +use node_runtime::Block; +use node_runtime::constants::currency::*; +use sc_service; +use hex_literal::hex; +use sc_telemetry::TelemetryEndpoints; +use grandpa_primitives::{AuthorityId as GrandpaId}; +use sp_consensus_babe::{AuthorityId as BabeId}; +use pallet_im_online::sr25519::{AuthorityId as ImOnlineId}; +use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; +use sp_runtime::{Perbill, traits::{Verify, IdentifyAccount}}; + +pub use node_primitives::{AccountId, Balance, Signature}; +pub use node_runtime::GenesisConfig; + +type AccountPublic = ::Signer; + +const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; + +/// Node `ChainSpec` extensions. +/// +/// Additional parameters for some Substrate core modules, +/// customizable from the chain spec. +#[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)] +#[serde(rename_all = "camelCase")] +pub struct Extensions { + /// Block numbers with known hashes. + pub fork_blocks: sc_client::ForkBlocks, + /// Known bad block hashes. + pub bad_blocks: sc_client::BadBlocks, +} + +/// Specialized `ChainSpec`. +pub type ChainSpec = sc_service::ChainSpec< + GenesisConfig, + Extensions, +>; +/// Flaming Fir testnet generator +pub fn flaming_fir_config() -> Result { + ChainSpec::from_json_bytes(&include_bytes!("../res/flaming-fir.json")[..]) +} + +fn session_keys( + grandpa: GrandpaId, + babe: BabeId, + im_online: ImOnlineId, + authority_discovery: AuthorityDiscoveryId, +) -> SessionKeys { + SessionKeys { grandpa, babe, im_online, authority_discovery } +} + +fn staging_testnet_config_genesis() -> GenesisConfig { + // stash, controller, session-key + // generated with secret: + // for i in 1 2 3 4 ; do for j in stash controller; do subkey inspect "$secret"/fir/$j/$i; done; done + // and + // for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 inspect "$secret"//fir//$j//$i; done; done + + let initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)> = vec![( + // 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy + hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].into(), + // 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq + hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].into(), + // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC + hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), + // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 + hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), + // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 + hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), + // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 + hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), + ),( + // 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2 + hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].into(), + // 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF + hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].into(), + // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE + hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), + // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ + hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), + // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ + hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), + // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ + hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), + ),( + // 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp + hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].into(), + // 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9 + hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].into(), + // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d + hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), + // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH + hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), + // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH + hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), + // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH + hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), + ),( + // 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9 + hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].into(), + // 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn + hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].into(), + // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 + hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), + // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x + hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), + // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x + hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), + // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x + hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), + )]; + + // generated with secret: subkey inspect "$secret"/fir + let root_key: AccountId = hex![ + // 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo + "9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809" + ].into(); + + let endowed_accounts: Vec = vec![root_key.clone()]; + + testnet_genesis( + initial_authorities, + root_key, + Some(endowed_accounts), + false, + ) +} + +/// Staging testnet config. +pub fn staging_testnet_config() -> ChainSpec { + let boot_nodes = vec![]; + ChainSpec::from_genesis( + "Staging Testnet", + "staging_testnet", + staging_testnet_config_genesis, + boot_nodes, + Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)])), + None, + None, + Default::default(), + ) +} + +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId where + AccountPublic: From<::Public> +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Helper function to generate stash, controller and session key from seed +pub fn get_authority_keys_from_seed(seed: &str) -> ( + AccountId, + AccountId, + GrandpaId, + BabeId, + ImOnlineId, + AuthorityDiscoveryId, +) { + ( + get_account_id_from_seed::(&format!("{}//stash", seed)), + get_account_id_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + ) +} + +/// Helper function to create GenesisConfig for testing +pub fn testnet_genesis( + initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)>, + root_key: AccountId, + endowed_accounts: Option>, + enable_println: bool, +) -> GenesisConfig { + let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(|| { + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ] + }); + let num_endowed_accounts = endowed_accounts.len(); + + const ENDOWMENT: Balance = 10_000_000 * DOLLARS; + const STASH: Balance = 100 * DOLLARS; + + GenesisConfig { + frame_system: Some(SystemConfig { + code: WASM_BINARY.to_vec(), + changes_trie_config: Default::default(), + }), + pallet_balances: Some(BalancesConfig { + balances: endowed_accounts.iter().cloned() + .map(|k| (k, ENDOWMENT)) + .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) + .collect(), + vesting: vec![], + }), + pallet_indices: Some(IndicesConfig { + ids: endowed_accounts.iter().cloned() + .chain(initial_authorities.iter().map(|x| x.0.clone())) + .collect::>(), + }), + pallet_session: Some(SessionConfig { + keys: initial_authorities.iter().map(|x| { + (x.0.clone(), session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone())) + }).collect::>(), + }), + pallet_staking: Some(StakingConfig { + current_era: 0, + validator_count: initial_authorities.len() as u32 * 2, + minimum_validator_count: initial_authorities.len() as u32, + stakers: initial_authorities.iter().map(|x| { + (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator) + }).collect(), + invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), + slash_reward_fraction: Perbill::from_percent(10), + .. Default::default() + }), + pallet_democracy: Some(DemocracyConfig::default()), + pallet_collective_Instance1: Some(CouncilConfig { + members: endowed_accounts.iter().cloned() + .collect::>()[..(num_endowed_accounts + 1) / 2].to_vec(), + phantom: Default::default(), + }), + pallet_collective_Instance2: Some(TechnicalCommitteeConfig { + members: endowed_accounts.iter().cloned() + .collect::>()[..(num_endowed_accounts + 1) / 2].to_vec(), + phantom: Default::default(), + }), + pallet_contracts: Some(ContractsConfig { + current_schedule: pallet_contracts::Schedule { + enable_println, // this should only be enabled on development chains + ..Default::default() + }, + gas_price: 1 * MILLICENTS, + }), + pallet_sudo: Some(SudoConfig { + key: root_key, + }), + pallet_babe: Some(BabeConfig { + authorities: vec![], + }), + pallet_im_online: Some(ImOnlineConfig { + keys: vec![], + }), + pallet_authority_discovery: Some(AuthorityDiscoveryConfig { + keys: vec![], + }), + pallet_grandpa: Some(GrandpaConfig { + authorities: vec![], + }), + pallet_membership_Instance1: Some(Default::default()), + pallet_treasury: Some(Default::default()), + } +} + +fn development_config_genesis() -> GenesisConfig { + testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + ], + get_account_id_from_seed::("Alice"), + None, + true, + ) +} + +/// Development config (single validator Alice) +pub fn development_config() -> ChainSpec { + ChainSpec::from_genesis( + "Development", + "dev", + development_config_genesis, + vec![], + None, + None, + None, + Default::default(), + ) +} + +fn local_testnet_genesis() -> GenesisConfig { + testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + get_authority_keys_from_seed("Bob"), + ], + get_account_id_from_seed::("Alice"), + None, + false, + ) +} + +/// Local testnet config (multivalidator Alice + Bob) +pub fn local_testnet_config() -> ChainSpec { + ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + local_testnet_genesis, + vec![], + None, + None, + None, + Default::default(), + ) +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + use crate::service::{new_full, new_light}; + use sc_service_test; + + fn local_testnet_genesis_instant_single() -> GenesisConfig { + testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + ], + get_account_id_from_seed::("Alice"), + None, + false, + ) + } + + /// Local testnet config (single validator - Alice) + pub fn integration_test_config_with_single_authority() -> ChainSpec { + ChainSpec::from_genesis( + "Integration Test", + "test", + local_testnet_genesis_instant_single, + vec![], + None, + None, + None, + Default::default(), + ) + } + + /// Local testnet config (multivalidator Alice + Bob) + pub fn integration_test_config_with_two_authorities() -> ChainSpec { + ChainSpec::from_genesis( + "Integration Test", + "test", + local_testnet_genesis, + vec![], + None, + None, + None, + Default::default(), + ) + } + + #[test] + #[ignore] + fn test_connectivity() { + sc_service_test::connectivity( + integration_test_config_with_two_authorities(), + |config| new_full(config), + |config| new_light(config), + ); + } +} diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs new file mode 100644 index 0000000000000..8fb95bed687bb --- /dev/null +++ b/bin/node/cli/src/cli.rs @@ -0,0 +1,208 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +pub use sc_cli::VersionInfo; +use tokio::prelude::Future; +use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; +use sc_cli::{IntoExit, NoCustom, SharedParams, ImportParams, error}; +use sc_service::{AbstractService, Roles as ServiceRoles, Configuration}; +use log::info; +use structopt::StructOpt; +use sc_cli::{display_role, parse_and_prepare, GetSharedParams, ParseAndPrepare}; +use crate::{service, ChainSpec, load_spec}; +use crate::factory_impl::FactoryState; +use node_transaction_factory::RuntimeAdapter; + +/// Custom subcommands. +#[derive(Clone, Debug, StructOpt)] +pub enum CustomSubcommands { + /// The custom factory subcommmand for manufacturing transactions. + #[structopt( + name = "factory", + about = "Manufactures num transactions from Alice to random accounts. \ + Only supported for development or local testnet." + )] + Factory(FactoryCmd), +} + +impl GetSharedParams for CustomSubcommands { + fn shared_params(&self) -> Option<&SharedParams> { + match self { + CustomSubcommands::Factory(cmd) => Some(&cmd.shared_params), + } + } +} + +/// The `factory` command used to generate transactions. +/// Please note: this command currently only works on an empty database! +#[derive(Debug, StructOpt, Clone)] +pub struct FactoryCmd { + /// How often to repeat. This option only has an effect in mode `MasterToNToM`. + #[structopt(long="rounds", default_value = "1")] + pub rounds: u64, + + /// MasterToN: Manufacture `num` transactions from the master account + /// to `num` randomly created accounts, one each. + /// + /// MasterTo1: Manufacture `num` transactions from the master account + /// to exactly one other randomly created account. + /// + /// MasterToNToM: Manufacture `num` transactions from the master account + /// to `num` randomly created accounts. + /// From each of these randomly created accounts manufacture + /// a transaction to another randomly created account. + /// Repeat this `rounds` times. If `rounds` = 1 the behavior + /// is the same as `MasterToN`.{n} + /// A -> B, A -> C, A -> D, ... x `num`{n} + /// B -> E, C -> F, D -> G, ...{n} + /// ... x `rounds` + /// + /// These three modes control manufacturing. + #[structopt(long="mode", default_value = "MasterToN")] + pub mode: node_transaction_factory::Mode, + + /// Number of transactions to generate. In mode `MasterNToNToM` this is + /// the number of transactions per round. + #[structopt(long="num", default_value = "8")] + pub num: u64, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub import_params: ImportParams, +} + +/// Parse command line arguments into service configuration. +pub fn run(args: I, exit: E, version: sc_cli::VersionInfo) -> error::Result<()> where + I: IntoIterator, + T: Into + Clone, + E: IntoExit, +{ + type Config = Configuration<(), A, B>; + + match parse_and_prepare::(&version, "substrate-node", args) { + ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, + |exit, _cli_args, _custom_args, config: Config<_, _>| { + info!("{}", version.name); + info!(" version {}", config.full_version()); + info!(" by Parity Technologies, 2017-2019"); + info!("Chain specification: {}", config.chain_spec.name()); + info!("Node name: {}", config.name); + info!("Roles: {}", display_role(&config)); + let runtime = RuntimeBuilder::new().name_prefix("main-tokio-").build() + .map_err(|e| format!("{:?}", e))?; + match config.roles { + ServiceRoles::LIGHT => run_until_exit( + runtime, + service::new_light(config)?, + exit + ), + _ => run_until_exit( + runtime, + service::new_full(config)?, + exit + ), + } + }), + ParseAndPrepare::BuildSpec(cmd) => cmd.run::(load_spec), + ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_, _>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), + ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_, _>| + Ok(new_full_start!(config).0), load_spec), + ParseAndPrepare::CustomCommand(CustomSubcommands::Factory(cli_args)) => { + let mut config: Config<_, _> = sc_cli::create_config_with_db_path( + load_spec, + &cli_args.shared_params, + &version, + )?; + + sc_cli::fill_import_params(&mut config, &cli_args.import_params, ServiceRoles::FULL)?; + + match ChainSpec::from(config.chain_spec.id()) { + Some(ref c) if c == &ChainSpec::Development || c == &ChainSpec::LocalTestnet => {}, + _ => panic!("Factory is only supported for development and local testnet."), + } + + let factory_state = FactoryState::new( + cli_args.mode.clone(), + cli_args.num, + cli_args.rounds, + ); + + let service_builder = new_full_start!(config).0; + node_transaction_factory::factory::, _, _, _, _, _>( + factory_state, + service_builder.client(), + service_builder.select_chain() + .expect("The select_chain is always initialized by new_full_start!; QED") + ).map_err(|e| format!("Error in transaction factory: {}", e))?; + + Ok(()) + } + } +} + +fn run_until_exit( + mut runtime: Runtime, + service: T, + e: E, +) -> error::Result<()> +where + T: AbstractService, + E: IntoExit, +{ + use futures::{FutureExt, TryFutureExt, channel::oneshot, future::select, compat::Future01CompatExt}; + + let (exit_send, exit) = oneshot::channel(); + + let informant = sc_cli::informant::build(&service); + + let future = select(informant, exit) + .map(|_| Ok(())) + .compat(); + + runtime.executor().spawn(future); + + // we eagerly drop the service so that the internal exit future is fired, + // but we need to keep holding a reference to the global telemetry guard + let _telemetry = service.telemetry(); + + let service_res = { + let exit = e.into_exit(); + let service = service + .map_err(|err| error::Error::Service(err)) + .compat(); + let select = select(service, exit) + .map(|_| Ok(())) + .compat(); + runtime.block_on(select) + }; + + let _ = exit_send.send(()); + + // TODO [andre]: timeout this future #1318 + let _ = runtime.shutdown_on_idle().wait(); + + service_res +} diff --git a/node/cli/src/factory_impl.rs b/bin/node/cli/src/factory_impl.rs similarity index 86% rename from node/cli/src/factory_impl.rs rename to bin/node/cli/src/factory_impl.rs index 48fb7b237f1e6..a1c5a5f4e050f 100644 --- a/node/cli/src/factory_impl.rs +++ b/bin/node/cli/src/factory_impl.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,21 +22,21 @@ use rand::{Rng, SeedableRng}; use rand::rngs::StdRng; use codec::{Encode, Decode}; -use keyring::sr25519::Keyring; +use sp_keyring::sr25519::Keyring; use node_runtime::{ Call, CheckedExtrinsic, UncheckedExtrinsic, SignedExtra, BalancesCall, ExistentialDeposit, MinimumPeriod }; use node_primitives::Signature; -use primitives::{sr25519, crypto::Pair}; -use sr_primitives::{ +use sp_core::{sr25519, crypto::Pair}; +use sp_runtime::{ generic::Era, traits::{Block as BlockT, Header as HeaderT, SignedExtension, Verify, IdentifyAccount} }; -use transaction_factory::RuntimeAdapter; -use transaction_factory::modes::Mode; -use inherents::InherentData; -use timestamp; -use finality_tracker; +use node_transaction_factory::RuntimeAdapter; +use node_transaction_factory::modes::Mode; +use sp_inherents::InherentData; +use sp_timestamp; +use sp_finality_tracker; type AccountPublic = ::Signer; @@ -56,12 +56,12 @@ type Number = <::Header as HeaderT>::Number; impl FactoryState { fn build_extra(index: node_primitives::Index, phase: u64) -> node_runtime::SignedExtra { ( - system::CheckVersion::new(), - system::CheckGenesis::new(), - system::CheckEra::from(Era::mortal(256, phase)), - system::CheckNonce::from(index), - system::CheckWeight::new(), - transaction_payment::ChargeTransactionPayment::from(0), + frame_system::CheckVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::mortal(256, phase)), + frame_system::CheckNonce::from(index), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(0), Default::default(), ) } @@ -71,7 +71,7 @@ impl RuntimeAdapter for FactoryState { type AccountId = node_primitives::AccountId; type Balance = node_primitives::Balance; type Block = node_primitives::Block; - type Phase = sr_primitives::generic::Phase; + type Phase = sp_runtime::generic::Phase; type Secret = sr25519::Pair; type Index = node_primitives::Index; @@ -149,7 +149,7 @@ impl RuntimeAdapter for FactoryState { signed: Some((sender.clone(), Self::build_extra(index, phase))), function: Call::Balances( BalancesCall::transfer( - indices::address::Address::Id(destination.clone().into()), + pallet_indices::address::Address::Id(destination.clone().into()), (*amount).into() ) ) @@ -160,9 +160,9 @@ impl RuntimeAdapter for FactoryState { let timestamp = (self.block_no as u64 + 1) * MinimumPeriod::get(); let mut inherent = InherentData::new(); - inherent.put_data(timestamp::INHERENT_IDENTIFIER, ×tamp) + inherent.put_data(sp_timestamp::INHERENT_IDENTIFIER, ×tamp) .expect("Failed putting timestamp inherent"); - inherent.put_data(finality_tracker::INHERENT_IDENTIFIER, &self.block_no) + inherent.put_data(sp_finality_tracker::INHERENT_IDENTIFIER, &self.block_no) .expect("Failed putting finalized number inherent"); inherent } @@ -247,13 +247,13 @@ fn sign( let payload = (xt.function, extra.clone(), additional_signed); let signature = payload.using_encoded(|b| { if b.len() > 256 { - key.sign(&sr_io::blake2_256(b)) + key.sign(&sp_io::hashing::blake2_256(b)) } else { key.sign(b) } }).into(); UncheckedExtrinsic { - signature: Some((indices::address::Address::Id(signed), signature, extra)), + signature: Some((pallet_indices::address::Address::Id(signed), signature, extra)), function: payload.0, } } diff --git a/bin/node/cli/src/lib.rs b/bin/node/cli/src/lib.rs new file mode 100644 index 0000000000000..d3fbf9c1ea5cd --- /dev/null +++ b/bin/node/cli/src/lib.rs @@ -0,0 +1,88 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate CLI library. +//! +//! This package has two Cargo features: +//! +//! - `cli` (default): exposes functions that parse command-line options, then start and run the +//! node as a CLI application. +//! +//! - `browser`: exposes the content of the `browser` module, which consists of exported symbols +//! that are meant to be passed through the `wasm-bindgen` utility and called from JavaScript. +//! Despite its name the produced WASM can theoretically also be used from NodeJS, although this +//! hasn't been tested. + +#![warn(missing_docs)] +#![warn(unused_extern_crates)] + +pub mod chain_spec; + +#[macro_use] +mod service; +#[cfg(feature = "browser")] +mod browser; +#[cfg(feature = "cli")] +mod cli; +#[cfg(feature = "cli")] +mod factory_impl; + +#[cfg(feature = "browser")] +pub use browser::*; +#[cfg(feature = "cli")] +pub use cli::*; + +/// The chain specification option. +#[derive(Clone, Debug, PartialEq)] +pub enum ChainSpec { + /// Whatever the current runtime is, with just Alice as an auth. + Development, + /// Whatever the current runtime is, with simple Alice/Bob auths. + LocalTestnet, + /// The Flaming Fir testnet. + FlamingFir, + /// Whatever the current runtime is with the "global testnet" defaults. + StagingTestnet, +} + +/// Get a chain config from a spec setting. +impl ChainSpec { + pub(crate) fn load(self) -> Result { + Ok(match self { + ChainSpec::FlamingFir => chain_spec::flaming_fir_config()?, + ChainSpec::Development => chain_spec::development_config(), + ChainSpec::LocalTestnet => chain_spec::local_testnet_config(), + ChainSpec::StagingTestnet => chain_spec::staging_testnet_config(), + }) + } + + pub(crate) fn from(s: &str) -> Option { + match s { + "dev" => Some(ChainSpec::Development), + "local" => Some(ChainSpec::LocalTestnet), + "" | "fir" | "flaming-fir" => Some(ChainSpec::FlamingFir), + "staging" => Some(ChainSpec::StagingTestnet), + _ => None, + } + } +} + +fn load_spec(id: &str) -> Result, String> { + Ok(match ChainSpec::from(id) { + Some(spec) => Some(spec.load()?), + None => None, + }) +} diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs new file mode 100644 index 0000000000000..a17865308a55b --- /dev/null +++ b/bin/node/cli/src/service.rs @@ -0,0 +1,636 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![warn(unused_extern_crates)] + +//! Service implementation. Specialized wrapper over substrate service. + +use std::sync::Arc; + +use sc_consensus_babe; +use sc_client::{self, LongestChain}; +use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; +use node_executor; +use node_primitives::Block; +use node_runtime::{GenesisConfig, RuntimeApi}; +use sc_service::{ + AbstractService, ServiceBuilder, config::Configuration, error::{Error as ServiceError}, +}; +use sp_inherents::InherentDataProviders; +use sc_network::construct_simple_protocol; + +use sc_service::{Service, NetworkStatus}; +use sc_client::{Client, LocalCallExecutor}; +use sc_client_db::Backend; +use sp_runtime::traits::Block as BlockT; +use node_executor::NativeExecutor; +use sc_network::NetworkService; +use sc_offchain::OffchainWorkers; + +construct_simple_protocol! { + /// Demo protocol attachment for substrate. + pub struct NodeProtocol where Block = Block { } +} + +/// Starts a `ServiceBuilder` for a full service. +/// +/// Use this macro if you don't actually need the full service, but just the builder in order to +/// be able to perform chain operations. +macro_rules! new_full_start { + ($config:expr) => {{ + type RpcExtension = jsonrpc_core::IoHandler; + let mut import_setup = None; + let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + + let builder = sc_service::ServiceBuilder::new_full::< + node_primitives::Block, node_runtime::RuntimeApi, node_executor::Executor + >($config)? + .with_select_chain(|_config, backend| { + Ok(sc_client::LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client, _fetcher| { + let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); + let pool = sc_transaction_pool::BasicPool::new(config, pool_api); + let maintainer = sc_transaction_pool::FullBasicPoolMaintainer::new(pool.pool().clone(), client); + let maintainable_pool = sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer); + Ok(maintainable_pool) + })? + .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { + let select_chain = select_chain.take() + .ok_or_else(|| sc_service::Error::SelectChainRequired)?; + let (grandpa_block_import, grandpa_link) = grandpa::block_import( + client.clone(), + &*client, + select_chain, + )?; + let justification_import = grandpa_block_import.clone(); + + let (block_import, babe_link) = sc_consensus_babe::block_import( + sc_consensus_babe::Config::get_or_compute(&*client)?, + grandpa_block_import, + client.clone(), + client.clone(), + )?; + + let import_queue = sc_consensus_babe::import_queue( + babe_link.clone(), + block_import.clone(), + Some(Box::new(justification_import)), + None, + client.clone(), + client, + inherent_data_providers.clone(), + )?; + + import_setup = Some((block_import, grandpa_link, babe_link)); + Ok(import_queue) + })? + .with_rpc_extensions(|client, pool, _backend, fetcher, _remote_blockchain| -> Result { + Ok(node_rpc::create(client, pool, node_rpc::LightDeps::none(fetcher))) + })?; + + (builder, import_setup, inherent_data_providers) + }} +} + +/// Creates a full service from the configuration. +/// +/// We need to use a macro because the test suit doesn't work with an opaque service. It expects +/// concrete types instead. +macro_rules! new_full { + ($config:expr, $with_startup_data: expr) => {{ + use futures::{ + stream::StreamExt, + future::{FutureExt, TryFutureExt}, + }; + use sc_network::Event; + + let ( + is_authority, + force_authoring, + name, + disable_grandpa, + sentry_nodes, + ) = ( + $config.roles.is_authority(), + $config.force_authoring, + $config.name.clone(), + $config.disable_grandpa, + $config.network.sentry_nodes.clone(), + ); + + // sentry nodes announce themselves as authorities to the network + // and should run the same protocols authorities do, but it should + // never actively participate in any consensus process. + let participates_in_consensus = is_authority && !$config.sentry_mode; + + let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config); + + let service = builder.with_network_protocol(|_| Ok(crate::service::NodeProtocol::new()))? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, client)) as _) + )? + .build()?; + + let (block_import, grandpa_link, babe_link) = import_setup.take() + .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); + + ($with_startup_data)(&block_import, &babe_link); + + if participates_in_consensus { + let proposer = sc_basic_authority::ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }; + + let client = service.client(); + let select_chain = service.select_chain() + .ok_or(sc_service::Error::SelectChainRequired)?; + + let can_author_with = + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + + let babe_config = sc_consensus_babe::BabeParams { + keystore: service.keystore(), + client, + select_chain, + env: proposer, + block_import, + sync_oracle: service.network(), + inherent_data_providers: inherent_data_providers.clone(), + force_authoring, + babe_link, + can_author_with, + }; + + let babe = sc_consensus_babe::start_babe(babe_config)?; + service.spawn_essential_task(babe); + + let network = service.network(); + let dht_event_stream = network.event_stream().filter_map(|e| async move { match e { + Event::Dht(e) => Some(e), + _ => None, + }}).boxed(); + let authority_discovery = sc_authority_discovery::AuthorityDiscovery::new( + service.client(), + network, + sentry_nodes, + service.keystore(), + dht_event_stream, + ); + let future01_authority_discovery = authority_discovery.map(|x| Ok(x)).compat(); + + service.spawn_task(future01_authority_discovery); + } + + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if participates_in_consensus { + Some(service.keystore()) + } else { + None + }; + + let config = grandpa::Config { + // FIXME #1578 make this available through chainspec + gossip_duration: std::time::Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: true, + keystore, + is_authority, + }; + + match (is_authority, disable_grandpa) { + (false, false) => { + // start the lightweight GRANDPA observer + service.spawn_task(grandpa::run_grandpa_observer( + config, + grandpa_link, + service.network(), + service.on_exit(), + service.spawn_task_handle(), + )?.unit_error().compat()); + }, + (true, false) => { + // start the full GRANDPA voter + let grandpa_config = grandpa::GrandpaParams { + config: config, + link: grandpa_link, + network: service.network(), + inherent_data_providers: inherent_data_providers.clone(), + on_exit: service.on_exit(), + telemetry_on_connect: Some(service.telemetry_on_connect_stream()), + voting_rule: grandpa::VotingRulesBuilder::default().build(), + executor: service.spawn_task_handle(), + }; + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + service.spawn_essential_task(grandpa::run_grandpa_voter(grandpa_config)? + .map(|()| Ok::<(), ()>(())).compat()); + }, + (_, true) => { + grandpa::setup_disabled_grandpa( + service.client(), + &inherent_data_providers, + service.network(), + )?; + }, + } + + Ok((service, inherent_data_providers)) + }}; + ($config:expr) => {{ + new_full!($config, |_, _| {}) + }} +} + +#[allow(dead_code)] +type ConcreteBlock = node_primitives::Block; +#[allow(dead_code)] +type ConcreteClient = + Client< + Backend, + LocalCallExecutor, + NativeExecutor>, + ConcreteBlock, + node_runtime::RuntimeApi + >; +#[allow(dead_code)] +type ConcreteBackend = Backend; +#[allow(dead_code)] +type ConcreteTransactionPool = sp_transaction_pool::MaintainableTransactionPool< + sc_transaction_pool::BasicPool< + sc_transaction_pool::FullChainApi, + ConcreteBlock + >, + sc_transaction_pool::FullBasicPoolMaintainer< + ConcreteClient, + sc_transaction_pool::FullChainApi + > +>; + +/// A specialized configuration object for setting up the node.. +pub type NodeConfiguration = Configuration; + +/// Builds a new service for a full client. +pub fn new_full(config: NodeConfiguration) +-> Result< + Service< + ConcreteBlock, + ConcreteClient, + LongestChain, + NetworkStatus, + NetworkService::Hash>, + ConcreteTransactionPool, + OffchainWorkers< + ConcreteClient, + >::OffchainStorage, + ConcreteBlock, + > + >, + ServiceError, +> +{ + new_full!(config).map(|(service, _)| service) +} + +/// Builds a new service for a light client. +pub fn new_light(config: NodeConfiguration) +-> Result { + type RpcExtension = jsonrpc_core::IoHandler; + let inherent_data_providers = InherentDataProviders::new(); + + let service = ServiceBuilder::new_light::(config)? + .with_select_chain(|_config, backend| { + Ok(LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client, fetcher| { + let fetcher = fetcher + .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; + let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); + let pool = sc_transaction_pool::BasicPool::new(config, pool_api); + let maintainer = sc_transaction_pool::LightBasicPoolMaintainer::with_defaults(pool.pool().clone(), client, fetcher); + let maintainable_pool = sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer); + Ok(maintainable_pool) + })? + .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { + let fetch_checker = fetcher + .map(|fetcher| fetcher.checker().clone()) + .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; + let grandpa_block_import = grandpa::light_block_import::<_, _, _, RuntimeApi>( + client.clone(), + backend, + &*client, + Arc::new(fetch_checker), + )?; + + let finality_proof_import = grandpa_block_import.clone(); + let finality_proof_request_builder = + finality_proof_import.create_finality_proof_request_builder(); + + let (babe_block_import, babe_link) = sc_consensus_babe::block_import( + sc_consensus_babe::Config::get_or_compute(&*client)?, + grandpa_block_import, + client.clone(), + client.clone(), + )?; + + let import_queue = sc_consensus_babe::import_queue( + babe_link, + babe_block_import, + None, + Some(Box::new(finality_proof_import)), + client.clone(), + client, + inherent_data_providers.clone(), + )?; + + Ok((import_queue, finality_proof_request_builder)) + })? + .with_network_protocol(|_| Ok(NodeProtocol::new()))? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) + )? + .with_rpc_extensions(|client, pool, _backend, fetcher, remote_blockchain| -> Result { + let fetcher = fetcher + .ok_or_else(|| "Trying to start node RPC without active fetcher")?; + let remote_blockchain = remote_blockchain + .ok_or_else(|| "Trying to start node RPC without active remote blockchain")?; + + let light_deps = node_rpc::LightDeps { remote_blockchain, fetcher }; + Ok(node_rpc::create(client, pool, Some(light_deps))) + })? + .build()?; + + Ok(service) +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + use sc_consensus_babe::CompatibleDigestItem; + use sp_consensus::{ + Environment, Proposer, BlockImportParams, BlockOrigin, ForkChoiceStrategy, BlockImport, + RecordProof, + }; + use node_primitives::{Block, DigestItem, Signature}; + use node_runtime::{BalancesCall, Call, UncheckedExtrinsic, Address}; + use node_runtime::constants::{currency::CENTS, time::SLOT_DURATION}; + use codec::{Encode, Decode}; + use sp_core::{crypto::Pair as CryptoPair, H256}; + use sp_runtime::{ + generic::{BlockId, Era, Digest, SignedPayload}, + traits::Block as BlockT, + traits::Verify, + OpaqueExtrinsic, + }; + use sp_timestamp; + use sp_finality_tracker; + use sp_keyring::AccountKeyring; + use sc_service::AbstractService; + use crate::service::{new_full, new_light}; + use sp_runtime::traits::IdentifyAccount; + + type AccountPublic = ::Signer; + + #[cfg(feature = "rhd")] + fn test_sync() { + use sp_core::ed25519::Pair; + + use {service_test, Factory}; + use sc_client::{BlockImportParams, BlockOrigin}; + + let alice: Arc = Arc::new(Keyring::Alice.into()); + let bob: Arc = Arc::new(Keyring::Bob.into()); + let validators = vec![alice.public().0.into(), bob.public().0.into()]; + let keys: Vec<&ed25519::Pair> = vec![&*alice, &*bob]; + let dummy_runtime = ::tokio::runtime::Runtime::new().unwrap(); + let block_factory = |service: &::FullService| { + let block_id = BlockId::number(service.client().chain_info().best_number); + let parent_header = service.client().header(&block_id).unwrap().unwrap(); + let consensus_net = ConsensusNetwork::new(service.network(), service.client().clone()); + let proposer_factory = consensus::ProposerFactory { + client: service.client().clone(), + transaction_pool: service.transaction_pool().clone(), + network: consensus_net, + force_delay: 0, + handle: dummy_runtime.executor(), + }; + let (proposer, _, _) = proposer_factory.init(&parent_header, &validators, alice.clone()).unwrap(); + let block = proposer.propose().expect("Error making test block"); + BlockImportParams { + origin: BlockOrigin::File, + justification: Vec::new(), + internal_justification: Vec::new(), + finalized: false, + body: Some(block.extrinsics), + storage_changes: None, + header: block.header, + auxiliary: Vec::new(), + } + }; + let extrinsic_factory = + |service: &SyncService<::FullService>| + { + let payload = ( + 0, + Call::Balances(BalancesCall::transfer(RawAddress::Id(bob.public().0.into()), 69.into())), + Era::immortal(), + service.client().genesis_hash() + ); + let signature = alice.sign(&payload.encode()).into(); + let id = alice.public().0.into(); + let xt = UncheckedExtrinsic { + signature: Some((RawAddress::Id(id), signature, payload.0, Era::immortal())), + function: payload.1, + }.encode(); + let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); + OpaqueExtrinsic(v) + }; + sc_service_test::sync( + sc_chain_spec::integration_test_config(), + |config| new_full(config), + |mut config| new_light(config), + block_factory, + extrinsic_factory, + ); + } + + #[test] + #[ignore] + fn test_sync() { + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); + let keystore = sc_keystore::Store::open(keystore_path.path(), None) + .expect("Creates keystore"); + let alice = keystore.write().insert_ephemeral_from_seed::("//Alice") + .expect("Creates authority pair"); + + let chain_spec = crate::chain_spec::tests::integration_test_config_with_single_authority(); + + // For the block factory + let mut slot_num = 1u64; + + // For the extrinsics factory + let bob = Arc::new(AccountKeyring::Bob.pair()); + let charlie = Arc::new(AccountKeyring::Charlie.pair()); + let mut index = 0; + + sc_service_test::sync( + chain_spec, + |config| { + let mut setup_handles = None; + new_full!(config, | + block_import: &sc_consensus_babe::BabeBlockImport<_, _, Block, _, _, _>, + babe_link: &sc_consensus_babe::BabeLink, + | { + setup_handles = Some((block_import.clone(), babe_link.clone())); + }).map(move |(node, x)| (node, (x, setup_handles.unwrap()))) + }, + |config| new_light(config), + |service, &mut (ref inherent_data_providers, (ref mut block_import, ref babe_link))| { + let mut inherent_data = inherent_data_providers + .create_inherent_data() + .expect("Creates inherent data."); + inherent_data.replace_data(sp_finality_tracker::INHERENT_IDENTIFIER, &1u64); + + let parent_id = BlockId::number(service.client().chain_info().best_number); + let parent_header = service.client().header(&parent_id).unwrap().unwrap(); + let mut proposer_factory = sc_basic_authority::ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }; + + let mut digest = Digest::::default(); + + // even though there's only one authority some slots might be empty, + // so we must keep trying the next slots until we can claim one. + let babe_pre_digest = loop { + inherent_data.replace_data(sp_timestamp::INHERENT_IDENTIFIER, &(slot_num * SLOT_DURATION)); + if let Some(babe_pre_digest) = sc_consensus_babe::test_helpers::claim_slot( + slot_num, + &parent_header, + &*service.client(), + &keystore, + &babe_link, + ) { + break babe_pre_digest; + } + + slot_num += 1; + }; + + digest.push(::babe_pre_digest(babe_pre_digest)); + + let mut proposer = proposer_factory.init(&parent_header).unwrap(); + let new_block = futures::executor::block_on(proposer.propose( + inherent_data, + digest, + std::time::Duration::from_secs(1), + RecordProof::Yes, + )).expect("Error making test block").block; + + let (new_header, new_body) = new_block.deconstruct(); + let pre_hash = new_header.hash(); + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let to_sign = pre_hash.encode(); + let signature = alice.sign(&to_sign[..]); + let item = ::babe_seal( + signature.into(), + ); + slot_num += 1; + + let params = BlockImportParams { + origin: BlockOrigin::File, + header: new_header, + justification: None, + post_digests: vec![item], + body: Some(new_body), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + + block_import.import_block(params, Default::default()) + .expect("error importing test block"); + }, + |service, _| { + let amount = 5 * CENTS; + let to: Address = AccountPublic::from(bob.public()).into_account().into(); + let from: Address = AccountPublic::from(charlie.public()).into_account().into(); + let genesis_hash = service.client().block_hash(0).unwrap().unwrap(); + let best_block_id = BlockId::number(service.client().chain_info().best_number); + let version = service.client().runtime_version_at(&best_block_id).unwrap().spec_version; + let signer = charlie.clone(); + + let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); + + let check_version = frame_system::CheckVersion::new(); + let check_genesis = frame_system::CheckGenesis::new(); + let check_era = frame_system::CheckEra::from(Era::Immortal); + let check_nonce = frame_system::CheckNonce::from(index); + let check_weight = frame_system::CheckWeight::new(); + let payment = pallet_transaction_payment::ChargeTransactionPayment::from(0); + let extra = ( + check_version, + check_genesis, + check_era, + check_nonce, + check_weight, + payment, + Default::default(), + ); + let raw_payload = SignedPayload::from_raw( + function, + extra, + (version, genesis_hash, genesis_hash, (), (), (), ()) + ); + let signature = raw_payload.using_encoded(|payload| { + signer.sign(payload) + }); + let (function, extra, _) = raw_payload.deconstruct(); + let xt = UncheckedExtrinsic::new_signed( + function, + from.into(), + signature.into(), + extra, + ).encode(); + let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); + + index += 1; + OpaqueExtrinsic(v) + }, + ); + } + + #[test] + #[ignore] + fn test_consensus() { + sc_service_test::consensus( + crate::chain_spec::tests::integration_test_config_with_two_authorities(), + |config| new_full(config), + |config| new_light(config), + vec![ + "//Alice".into(), + "//Bob".into(), + ], + ) + } +} diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml new file mode 100644 index 0000000000000..3aa7ad780a8db --- /dev/null +++ b/bin/node/executor/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "node-executor" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Substrate node implementation in Rust." +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0" } +node-primitives = { version = "2.0.0", path = "../primitives" } +node-runtime = { version = "2.0.0", path = "../runtime" } +sc-executor = { version = "2.0.0", path = "../../../client/executor" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-io = { version = "2.0.0", path = "../../../primitives/io" } +sp-state-machine = { version = "2.0.0", path = "../../../primitives/state-machine" } +sp-trie = { version = "2.0.0", path = "../../../primitives/trie" } +trie-root = "0.15.2" + +[dev-dependencies] +criterion = "0.3.0" +frame-support = { version = "2.0.0", path = "../../../frame/support" } +frame-system = { version = "2.0.0", path = "../../../frame/system" } +node-testing = { version = "2.0.0", path = "../testing" } +pallet-balances = { version = "2.0.0", path = "../../../frame/balances" } +pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" } +pallet-grandpa = { version = "2.0.0", path = "../../../frame/grandpa" } +pallet-im-online = { version = "2.0.0", path = "../../../frame/im-online" } +pallet-indices = { version = "2.0.0", path = "../../../frame/indices" } +pallet-session = { version = "2.0.0", path = "../../../frame/session" } +pallet-timestamp = { version = "2.0.0", path = "../../../frame/timestamp" } +pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" } +pallet-treasury = { version = "2.0.0", path = "../../../frame/treasury" } +sp-application-crypto = { version = "2.0.0", path = "../../../primitives/application-crypto" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +substrate-test-client = { version = "2.0.0", path = "../../../test-utils/client" } +wabt = "0.9.2" + +[features] +wasmtime = [ + "sc-executor/wasmtime", +] +wasmi-errno = [ + "sc-executor/wasmi-errno", +] +stress-test = [] + +[[bench]] +name = "bench" +harness = false diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs new file mode 100644 index 0000000000000..034c7c6759e11 --- /dev/null +++ b/bin/node/executor/benches/bench.rs @@ -0,0 +1,196 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::{Decode, Encode}; +use criterion::{BatchSize, Criterion, criterion_group, criterion_main}; +use node_executor::Executor; +use node_primitives::{BlockNumber, Hash}; +use node_runtime::{ + Block, BuildStorage, Call, CheckedExtrinsic, GenesisConfig, Header, UncheckedExtrinsic, +}; +use node_runtime::constants::currency::*; +use node_testing::keyring::*; +use sp_core::{Blake2Hasher, NativeOrEncoded, NeverNativeValue}; +use sp_core::storage::well_known_keys; +use sp_core::traits::CodeExecutor; +use frame_support::Hashable; +use sp_state_machine::TestExternalities as CoreTestExternalities; +use sc_executor::{NativeExecutor, RuntimeInfo, WasmExecutionMethod, Externalities}; + +criterion_group!(benches, bench_execute_block); +criterion_main!(benches); + +/// The wasm runtime code. +const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; + +const GENESIS_HASH: [u8; 32] = [69u8; 32]; + +const VERSION: u32 = node_runtime::VERSION.spec_version; + +const HEAP_PAGES: u64 = 20; + +type TestExternalities = CoreTestExternalities; + +#[derive(Debug)] +enum ExecutionMethod { + Native, + Wasm(WasmExecutionMethod), +} + +fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { + node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) +} + +fn new_test_ext(genesis_config: &GenesisConfig) -> TestExternalities { + let mut test_ext = TestExternalities::new_with_code( + COMPACT_CODE, + genesis_config.build_storage().unwrap(), + ); + test_ext.ext().place_storage(well_known_keys::HEAP_PAGES.to_vec(), Some(HEAP_PAGES.encode())); + test_ext +} + +fn construct_block( + executor: &NativeExecutor, + ext: &mut E, + number: BlockNumber, + parent_hash: Hash, + extrinsics: Vec, +) -> (Vec, Hash) { + use sp_trie::{TrieConfiguration, trie_types::Layout}; + + // sign extrinsics. + let extrinsics = extrinsics.into_iter().map(sign).collect::>(); + + // calculate the header fields that we can. + let extrinsics_root = Layout::::ordered_trie_root( + extrinsics.iter().map(Encode::encode) + ).to_fixed_bytes() + .into(); + + let header = Header { + parent_hash, + number, + extrinsics_root, + state_root: Default::default(), + digest: Default::default(), + }; + + // execute the block to get the real header. + executor.call::<_, NeverNativeValue, fn() -> _>( + ext, + "Core_initialize_block", + &header.encode(), + true, + None, + ).0.unwrap(); + + for i in extrinsics.iter() { + executor.call::<_, NeverNativeValue, fn() -> _>( + ext, + "BlockBuilder_apply_extrinsic", + &i.encode(), + true, + None, + ).0.unwrap(); + } + + let header = match executor.call::<_, NeverNativeValue, fn() -> _>( + ext, + "BlockBuilder_finalize_block", + &[0u8;0], + true, + None, + ).0.unwrap() { + NativeOrEncoded::Native(_) => unreachable!(), + NativeOrEncoded::Encoded(h) => Header::decode(&mut &h[..]).unwrap(), + }; + + let hash = header.blake2_256(); + (Block { header, extrinsics }.encode(), hash.into()) +} + + +fn test_blocks(genesis_config: &GenesisConfig, executor: &NativeExecutor) + -> Vec<(Vec, Hash)> +{ + let mut test_ext = new_test_ext(genesis_config); + let mut block1_extrinsics = vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(42 * 1000)), + }, + ]; + block1_extrinsics.extend((0..20).map(|i| { + CheckedExtrinsic { + signed: Some((alice(), signed_extra(i, 0))), + function: Call::Balances(pallet_balances::Call::transfer(bob().into(), 1 * DOLLARS)), + } + })); + let block1 = construct_block( + executor, + &mut test_ext.ext(), + 1, + GENESIS_HASH.into(), + block1_extrinsics, + ); + + vec![block1] +} + +fn bench_execute_block(c: &mut Criterion) { + c.bench_function_over_inputs( + "execute blocks", + |b, strategy| { + let genesis_config = node_testing::genesis::config(false, Some(COMPACT_CODE)); + let (use_native, wasm_method) = match strategy { + ExecutionMethod::Native => (true, WasmExecutionMethod::Interpreted), + ExecutionMethod::Wasm(wasm_method) => (false, *wasm_method), + }; + let executor = NativeExecutor::new(wasm_method, None); + + // Get the runtime version to initialize the runtimes cache. + { + let mut test_ext = new_test_ext(&genesis_config); + executor.runtime_version(&mut test_ext.ext()); + } + + let blocks = test_blocks(&genesis_config, &executor); + + b.iter_batched_ref( + || new_test_ext(&genesis_config), + |test_ext| { + for block in blocks.iter() { + executor.call::<_, NeverNativeValue, fn() -> _>( + &mut test_ext.ext(), + "Core_execute_block", + &block.0, + use_native, + None, + ).0.unwrap(); + } + }, + BatchSize::LargeInput, + ); + }, + vec![ + ExecutionMethod::Native, + ExecutionMethod::Wasm(WasmExecutionMethod::Interpreted), + #[cfg(feature = "wasmtime")] + ExecutionMethod::Wasm(WasmExecutionMethod::Compiled), + ], + ); +} diff --git a/bin/node/executor/src/lib.rs b/bin/node/executor/src/lib.rs new file mode 100644 index 0000000000000..812c018502f1b --- /dev/null +++ b/bin/node/executor/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A `CodeExecutor` specialization which uses natively compiled runtime when the wasm to be +//! executed is equivalent to the natively compiled code. + +pub use sc_executor::NativeExecutor; +use sc_executor::native_executor_instance; + +// Declare an instance of the native executor named `Executor`. Include the wasm binary as the +// equivalent wasm code. +native_executor_instance!( + pub Executor, + node_runtime::api::dispatch, + node_runtime::native_version +); diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs new file mode 100644 index 0000000000000..817ebbb173933 --- /dev/null +++ b/bin/node/executor/tests/basic.rs @@ -0,0 +1,836 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::{Encode, Decode, Joiner}; +use frame_support::{ + StorageValue, StorageMap, + traits::Currency, + weights::{GetDispatchInfo, DispatchInfo, DispatchClass}, +}; +use sp_core::{ + Blake2Hasher, NeverNativeValue, map, + traits::Externalities, + storage::{well_known_keys, Storage}, +}; +use sp_runtime::{ + ApplyExtrinsicResult, Fixed64, + traits::{Hash as HashT, Convert}, + transaction_validity::InvalidTransaction, +}; +use pallet_contracts::ContractAddressFor; +use frame_system::{self, EventRecord, Phase}; + +use node_runtime::{ + Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, + System, TransactionPayment, Event, + TransferFee, TransactionBaseFee, TransactionByteFee, + constants::currency::*, +}; +use node_primitives::{Balance, Hash}; +use wabt; +use node_testing::keyring::*; + +pub mod common; +use self::common::{*, sign}; + +/// The wasm runtime binary which hasn't undergone the compacting process. +/// +/// The idea here is to pass it as the current runtime code to the executor so the executor will +/// have to execute provided wasm code instead of the native equivalent. This trick is used to +/// test code paths that differ between native and wasm versions. +pub const BLOATY_CODE: &[u8] = node_runtime::WASM_BINARY_BLOATY; + +/// Default transfer fee +fn transfer_fee(extrinsic: &E, fee_multiplier: Fixed64) -> Balance { + let length_fee = TransactionByteFee::get() * (extrinsic.encode().len() as Balance); + + let weight = default_transfer_call().get_dispatch_info().weight; + let weight_fee = + ::WeightToFee::convert(weight); + + let base_fee = TransactionBaseFee::get(); + base_fee + fee_multiplier.saturated_multiply_accumulate(length_fee + weight_fee) + TransferFee::get() +} + +fn xt() -> UncheckedExtrinsic { + sign(CheckedExtrinsic { + signed: Some((alice(), signed_extra(0, 0))), + function: Call::Balances(default_transfer_call()), + }) +} + +fn set_heap_pages(ext: &mut E, heap_pages: u64) { + ext.place_storage(well_known_keys::HEAP_PAGES.to_vec(), Some(heap_pages.encode())); +} + +fn changes_trie_block() -> (Vec, Hash) { + construct_block( + &mut new_test_ext(COMPACT_CODE, true), + 1, + GENESIS_HASH.into(), + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(42 * 1000)), + }, + CheckedExtrinsic { + signed: Some((alice(), signed_extra(0, 0))), + function: Call::Balances(pallet_balances::Call::transfer(bob().into(), 69 * DOLLARS)), + }, + ] + ) +} + + +/// 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(pallet_timestamp::Call::set(42 * 1000)), + }, + CheckedExtrinsic { + signed: Some((alice(), signed_extra(0, 0))), + function: Call::Balances(pallet_balances::Call::transfer(bob().into(), 69 * DOLLARS)), + }, + ] + ); + let block2 = construct_block( + &mut t, + 2, + block1.1.clone(), + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(52 * 1000)), + }, + CheckedExtrinsic { + signed: Some((bob(), signed_extra(0, 0))), + function: Call::Balances(pallet_balances::Call::transfer(alice().into(), 5 * DOLLARS)), + }, + CheckedExtrinsic { + signed: Some((alice(), signed_extra(1, 0))), + function: Call::Balances(pallet_balances::Call::transfer(bob().into(), 15 * DOLLARS)), + } + ] + ); + + // session change => consensus authorities change => authorities change digest item appears + let digest = Header::decode(&mut &block2.0[..]).unwrap().digest; + assert_eq!(digest.logs().len(), 0); + + (block1, block2) +} + +fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec, Hash) { + construct_block( + &mut new_test_ext(COMPACT_CODE, false), + 1, + GENESIS_HASH.into(), + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(time * 1000)), + }, + CheckedExtrinsic { + signed: Some((alice(), signed_extra(nonce, 0))), + function: Call::System(frame_system::Call::remark(vec![0; size])), + } + ] + ) +} + +#[test] +fn panic_execution_with_foreign_code_gives_error() { + let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { + top: map![ + >::hashed_key_for(alice()) => { + 69_u128.encode() + }, + >::hashed_key().to_vec() => { + 69_u128.encode() + }, + >::hashed_key().to_vec() => { + 0_u128.encode() + }, + >::hashed_key_for(0) => { + vec![0u8; 32] + } + ], + children: map![], + }); + + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + None, + ).0; + assert!(r.is_ok()); + let v = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + true, + None, + ).0.unwrap(); + let r = ApplyExtrinsicResult::decode(&mut &v.as_encoded()[..]).unwrap(); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); +} + +#[test] +fn bad_extrinsic_with_native_equivalent_code_gives_error() { + let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { + top: map![ + >::hashed_key_for(alice()) => { + 69_u128.encode() + }, + >::hashed_key().to_vec() => { + 69_u128.encode() + }, + >::hashed_key().to_vec() => { + 0_u128.encode() + }, + >::hashed_key_for(0) => { + vec![0u8; 32] + } + ], + children: map![], + }); + + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + None, + ).0; + assert!(r.is_ok()); + let v = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + true, + None, + ).0.unwrap(); + let r = ApplyExtrinsicResult::decode(&mut &v.as_encoded()[..]).unwrap(); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); +} + +#[test] +fn successful_execution_with_native_equivalent_code_gives_ok() { + let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { + top: map![ + >::hashed_key_for(alice()) => { + (111 * DOLLARS).encode() + }, + >::hashed_key().to_vec() => { + (111 * DOLLARS).encode() + }, + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] + ], + children: map![], + }); + + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + None, + ).0; + assert!(r.is_ok()); + + let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + let r = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + true, + None, + ).0; + assert!(r.is_ok()); + + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); + assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); + }); +} + +#[test] +fn successful_execution_with_foreign_code_gives_ok() { + let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { + top: map![ + >::hashed_key_for(alice()) => { + (111 * DOLLARS).encode() + }, + >::hashed_key().to_vec() => { + (111 * DOLLARS).encode() + }, + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] + ], + children: map![], + }); + + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + None, + ).0; + assert!(r.is_ok()); + + let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + let r = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + true, + None, + ).0; + assert!(r.is_ok()); + + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); + assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); + }); +} + +#[test] +fn full_native_block_import_works() { + let mut t = new_test_ext(COMPACT_CODE, false); + + let (block1, block2) = blocks(); + + let mut alice_last_known_balance: Balance = Default::default(); + let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + executor_call:: _>( + &mut t, + "Core_execute_block", + &block1.0, + true, + None, + ).0.unwrap(); + + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); + assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); + alice_last_known_balance = Balances::total_balance(&alice()); + let events = vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: Event::system(frame_system::Event::ExtrinsicSuccess( + DispatchInfo { weight: 10000, class: DispatchClass::Operational, pays_fee: true } + )), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(1984800000000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::pallet_balances(pallet_balances::RawEvent::Transfer( + alice().into(), + bob().into(), + 69 * DOLLARS, + 1 * CENTS, + )), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::system(frame_system::Event::ExtrinsicSuccess( + DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true } + )), + topics: vec![], + }, + ]; + assert_eq!(System::events(), events); + }); + + fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + executor_call:: _>( + &mut t, + "Core_execute_block", + &block2.0, + true, + None, + ).0.unwrap(); + + t.execute_with(|| { + assert_eq!( + Balances::total_balance(&alice()), + alice_last_known_balance - 10 * DOLLARS - transfer_fee(&xt(), fm), + ); + assert_eq!( + Balances::total_balance(&bob()), + 179 * DOLLARS - transfer_fee(&xt(), fm), + ); + let events = vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: Event::system(frame_system::Event::ExtrinsicSuccess( + DispatchInfo { weight: 10000, class: DispatchClass::Operational, pays_fee: true } + )), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(1984788199392)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::pallet_balances( + pallet_balances::RawEvent::Transfer( + bob().into(), + alice().into(), + 5 * DOLLARS, + 1 * CENTS, + ) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::system(frame_system::Event::ExtrinsicSuccess( + DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true } + )), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + event: Event::pallet_treasury(pallet_treasury::RawEvent::Deposit(1984788199392)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + event: Event::pallet_balances( + pallet_balances::RawEvent::Transfer( + alice().into(), + bob().into(), + 15 * DOLLARS, + 1 * CENTS, + ) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + event: Event::system(frame_system::Event::ExtrinsicSuccess( + DispatchInfo { weight: 1000000, class: DispatchClass::Normal, pays_fee: true } + )), + topics: vec![], + }, + ]; + assert_eq!(System::events(), events); + }); +} + +#[test] +fn full_wasm_block_import_works() { + let mut t = new_test_ext(COMPACT_CODE, false); + + let (block1, block2) = blocks(); + + let mut alice_last_known_balance: Balance = Default::default(); + let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + executor_call:: _>( + &mut t, + "Core_execute_block", + &block1.0, + false, + None, + ).0.unwrap(); + + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); + assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); + alice_last_known_balance = Balances::total_balance(&alice()); + }); + + fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + executor_call:: _>( + &mut t, + "Core_execute_block", + &block2.0, + false, + None, + ).0.unwrap(); + + t.execute_with(|| { + assert_eq!( + Balances::total_balance(&alice()), + alice_last_known_balance - 10 * DOLLARS - transfer_fee(&xt(), fm), + ); + assert_eq!( + Balances::total_balance(&bob()), + 179 * DOLLARS - 1 * transfer_fee(&xt(), fm), + ); + }); +} + +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" "ext_scratch_size" (func $ext_scratch_size (result i32))) +(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) +(import "env" "memory" (memory 1 1)) +(func (export "deploy") +) +(func (export "call") + (block $fail + ;; load and check the input data (which is stored in the scratch buffer). + ;; fail if the input size is not != 4 + (br_if $fail + (i32.ne + (i32.const 4) + (call $ext_scratch_size) + ) + ) + + (call $ext_scratch_read + (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) + ) + ) + + (drop + (call $ext_call + (i32.const 4) ;; Pointer to "callee" address. + (i32.const 32) ;; Length of "callee" address. + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 36) ;; Pointer to the buffer with value to transfer + (i32.const 16) ;; Length of the buffer with value to transfer. + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + ) + + (return) + ) + unreachable +) +;; Destination AccountId to transfer the funds. +;; Represented by H256 (32 bytes long) in little endian. +(data (i32.const 4) + "\09\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" + "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" + "\00\00\00\00" +) +;; Amount of value to transfer. +;; Represented by u128 (16 bytes long) in little endian. +(data (i32.const 36) + "\06\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" + "\00\00" +) +) +"#; + +#[test] +fn deploying_wasm_contract_should_work() { + let transfer_code = wabt::wat2wasm(CODE_TRANSFER).unwrap(); + let transfer_ch = ::Hashing::hash(&transfer_code); + + let addr = ::DetermineContractAddress::contract_address_for( + &transfer_ch, + &[], + &charlie(), + ); + + let b = construct_block( + &mut new_test_ext(COMPACT_CODE, false), + 1, + GENESIS_HASH.into(), + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(42 * 1000)), + }, + CheckedExtrinsic { + signed: Some((charlie(), signed_extra(0, 0))), + function: Call::Contracts( + pallet_contracts::Call::put_code::(10_000, transfer_code) + ), + }, + CheckedExtrinsic { + signed: Some((charlie(), signed_extra(1, 0))), + function: Call::Contracts( + pallet_contracts::Call::instantiate::(1 * DOLLARS, 10_000, transfer_ch, Vec::new()) + ), + }, + CheckedExtrinsic { + signed: Some((charlie(), signed_extra(2, 0))), + function: Call::Contracts( + pallet_contracts::Call::call::( + pallet_indices::address::Address::Id(addr.clone()), + 10, + 10_000, + vec![0x00, 0x01, 0x02, 0x03] + ) + ), + }, + ] + ); + + let mut t = new_test_ext(COMPACT_CODE, false); + + executor_call:: _>( + &mut t, + "Core_execute_block", + &b.0, + false, + None, + ).0.unwrap(); + + t.execute_with(|| { + // Verify that the contract constructor worked well and code of TRANSFER contract is actually deployed. + assert_eq!( + &pallet_contracts::ContractInfoOf::::get(addr) + .and_then(|c| c.get_alive()) + .unwrap() + .code_hash, + &transfer_ch + ); + }); +} + +#[test] +fn wasm_big_block_import_fails() { + let mut t = new_test_ext(COMPACT_CODE, false); + + set_heap_pages(&mut t.ext(), 4); + + let result = executor_call:: _>( + &mut t, + "Core_execute_block", + &block_with_size(42, 0, 120_000).0, + false, + None, + ).0; + assert!(result.is_err()); // Err(Wasmi(Trap(Trap { kind: Host(AllocatorOutOfSpace) }))) +} + +#[test] +fn native_big_block_import_succeeds() { + let mut t = new_test_ext(COMPACT_CODE, false); + + executor_call:: _>( + &mut t, + "Core_execute_block", + &block_with_size(42, 0, 120_000).0, + true, + None, + ).0.unwrap(); +} + +#[test] +fn native_big_block_import_fails_on_fallback() { + let mut t = new_test_ext(COMPACT_CODE, false); + + assert!( + executor_call:: _>( + &mut t, + "Core_execute_block", + &block_with_size(42, 0, 120_000).0, + false, + None, + ).0.is_err() + ); +} + +#[test] +fn panic_execution_gives_error() { + let mut t = TestExternalities::::new_with_code(BLOATY_CODE, Storage { + top: map![ + >::hashed_key_for(alice()) => { + 0_u128.encode() + }, + >::hashed_key().to_vec() => { + 0_u128.encode() + }, + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] + ], + children: map![], + }); + + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + false, + None, + ).0; + assert!(r.is_ok()); + let r = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + false, + None, + ).0.unwrap().into_encoded(); + let r = ApplyExtrinsicResult::decode(&mut &r[..]).unwrap(); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); +} + +#[test] +fn successful_execution_gives_ok() { + let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { + top: map![ + >::hashed_key_for(alice()) => { + (111 * DOLLARS).encode() + }, + >::hashed_key().to_vec() => { + (111 * DOLLARS).encode() + }, + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] + ], + children: map![], + }); + + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + false, + None, + ).0; + assert!(r.is_ok()); + let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + let r = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + false, + None, + ).0.unwrap().into_encoded(); + ApplyExtrinsicResult::decode(&mut &r[..]) + .unwrap() + .expect("Extrinsic could be applied") + .expect("Extrinsic did not fail"); + + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt(), fm)); + assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); + }); +} + +#[test] +fn full_native_block_import_works_with_changes_trie() { + 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_call:: _>( + &mut t, + "Core_execute_block", + &block.encode(), + true, + None, + ).0.unwrap(); + + assert!(t.ext().storage_changes_root(&GENESIS_HASH).unwrap().is_some()); +} + +#[test] +fn full_wasm_block_import_works_with_changes_trie() { + let block1 = changes_trie_block(); + + let mut t = new_test_ext(COMPACT_CODE, true); + executor_call:: _>( + &mut t, + "Core_execute_block", + &block1.0, + false, + None, + ).0.unwrap(); + + assert!(t.ext().storage_changes_root(&GENESIS_HASH).unwrap().is_some()); +} + +#[test] +fn should_import_block_with_test_client() { + use node_testing::client::{ + ClientBlockImportExt, TestClientBuilderExt, TestClientBuilder, + sp_consensus::BlockOrigin, + }; + + let mut client = TestClientBuilder::new().build(); + let block1 = changes_trie_block(); + let block_data = block1.0; + let block = node_primitives::Block::decode(&mut &block_data[..]).unwrap(); + + client.import(BlockOrigin::Own, block).unwrap(); +} + + diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs new file mode 100644 index 0000000000000..52f8b65654096 --- /dev/null +++ b/bin/node/executor/tests/common.rs @@ -0,0 +1,152 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::{Encode, Decode}; +use frame_support::Hashable; +use sp_state_machine::TestExternalities as CoreTestExternalities; +use sp_core::{ + Blake2Hasher, NeverNativeValue, NativeOrEncoded, + traits::CodeExecutor, +}; +use sp_runtime::traits::Header as HeaderT; +use sc_executor::{NativeExecutor, WasmExecutionMethod}; +use sc_executor::error::Result; + +use node_executor::Executor; +use node_runtime::{ + Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Runtime, BuildStorage, + constants::currency::*, +}; +use node_primitives::{Hash, BlockNumber}; +use node_testing::keyring::*; + +/// The wasm runtime code. +/// +/// `compact` since it is after post-processing with wasm-gc which performs tree-shaking thus +/// making the binary slimmer. There is a convention to use compact version of the runtime +/// as canonical. This is why `native_executor_instance` also uses the compact version of the +/// runtime. +pub const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; + +pub const GENESIS_HASH: [u8; 32] = [69u8; 32]; + +pub const VERSION: u32 = node_runtime::VERSION.spec_version; + +pub type TestExternalities = CoreTestExternalities; + +pub fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { + node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) +} + +pub fn default_transfer_call() -> pallet_balances::Call { + pallet_balances::Call::transfer::(bob().into(), 69 * DOLLARS) +} + +pub fn from_block_number(n: u32) -> Header { + Header::new(n, Default::default(), Default::default(), [69; 32].into(), Default::default()) +} + +pub fn executor() -> NativeExecutor { + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) +} + +pub fn executor_call< + R:Decode + Encode + PartialEq, + NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe +>( + t: &mut TestExternalities, + method: &str, + data: &[u8], + use_native: bool, + native_call: Option, +) -> (Result>, bool) { + let mut t = t.ext(); + executor().call::<_, R, NC>( + &mut t, + method, + data, + use_native, + native_call, + ) +} + +pub fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities { + let mut ext = TestExternalities::new_with_code( + code, + node_testing::genesis::config(support_changes_trie, Some(code)).build_storage().unwrap(), + ); + ext.changes_trie_storage().insert(0, GENESIS_HASH.into(), Default::default()); + ext +} + +pub fn construct_block( + env: &mut TestExternalities, + number: BlockNumber, + parent_hash: Hash, + extrinsics: Vec, +) -> (Vec, Hash) { + use sp_trie::{TrieConfiguration, trie_types::Layout}; + + // sign extrinsics. + let extrinsics = extrinsics.into_iter().map(sign).collect::>(); + + // calculate the header fields that we can. + let extrinsics_root = Layout::::ordered_trie_root( + extrinsics.iter().map(Encode::encode) + ).to_fixed_bytes() + .into(); + + let header = Header { + parent_hash, + number, + extrinsics_root, + state_root: Default::default(), + digest: Default::default(), + }; + + // execute the block to get the real header. + executor_call:: _>( + env, + "Core_initialize_block", + &header.encode(), + true, + None, + ).0.unwrap(); + + for i in extrinsics.iter() { + executor_call:: _>( + env, + "BlockBuilder_apply_extrinsic", + &i.encode(), + true, + None, + ).0.unwrap(); + } + + let header = match executor_call:: _>( + env, + "BlockBuilder_finalize_block", + &[0u8;0], + true, + None, + ).0.unwrap() { + NativeOrEncoded::Native(_) => unreachable!(), + NativeOrEncoded::Encoded(h) => Header::decode(&mut &h[..]).unwrap(), + }; + + let hash = header.blake2_256(); + (Block { header, extrinsics }.encode(), hash.into()) +} diff --git a/bin/node/executor/tests/fees.rs b/bin/node/executor/tests/fees.rs new file mode 100644 index 0000000000000..ca34452031780 --- /dev/null +++ b/bin/node/executor/tests/fees.rs @@ -0,0 +1,332 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::{Encode, Joiner}; +use frame_support::{ + StorageValue, StorageMap, + traits::Currency, + weights::GetDispatchInfo, +}; +use sp_core::{ + Blake2Hasher, NeverNativeValue, map, + storage::Storage, +}; +use sp_runtime::{ + Fixed64, + traits::Convert, +}; +use node_runtime::{ + CheckedExtrinsic, Call, Runtime, Balances, + TransactionPayment, TransferFee, TransactionBaseFee, TransactionByteFee, + WeightFeeCoefficient, constants::currency::*, +}; +use node_runtime::impls::LinearWeightToFee; +use node_primitives::Balance; +use node_testing::keyring::*; + +pub mod common; +use self::common::{*, sign}; + +#[test] +fn fee_multiplier_increases_and_decreases_on_big_weight() { + let mut t = new_test_ext(COMPACT_CODE, false); + + // initial fee multiplier must be zero + let mut prev_multiplier = Fixed64::from_parts(0); + + t.execute_with(|| { + assert_eq!(TransactionPayment::next_fee_multiplier(), prev_multiplier); + }); + + let mut tt = new_test_ext(COMPACT_CODE, false); + + // big one in terms of weight. + let block1 = construct_block( + &mut tt, + 1, + GENESIS_HASH.into(), + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(42 * 1000)), + }, + CheckedExtrinsic { + signed: Some((charlie(), signed_extra(0, 0))), + function: Call::System(frame_system::Call::fill_block()), + } + ] + ); + + // small one in terms of weight. + let block2 = construct_block( + &mut tt, + 2, + block1.1.clone(), + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(52 * 1000)), + }, + CheckedExtrinsic { + signed: Some((charlie(), signed_extra(1, 0))), + function: Call::System(frame_system::Call::remark(vec![0; 1])), + } + ] + ); + + println!("++ Block 1 size: {} / Block 2 size {}", block1.0.encode().len(), block2.0.encode().len()); + + // execute a big block. + executor_call:: _>( + &mut t, + "Core_execute_block", + &block1.0, + true, + None, + ).0.unwrap(); + + // weight multiplier is increased for next block. + t.execute_with(|| { + let fm = TransactionPayment::next_fee_multiplier(); + println!("After a big block: {:?} -> {:?}", prev_multiplier, fm); + assert!(fm > prev_multiplier); + prev_multiplier = fm; + }); + + // execute a big block. + executor_call:: _>( + &mut t, + "Core_execute_block", + &block2.0, + true, + None, + ).0.unwrap(); + + // weight multiplier is increased for next block. + t.execute_with(|| { + let fm = TransactionPayment::next_fee_multiplier(); + println!("After a small block: {:?} -> {:?}", prev_multiplier, fm); + assert!(fm < prev_multiplier); + }); +} + +#[test] +fn transaction_fee_is_correct_ultimate() { + // This uses the exact values of substrate-node. + // + // weight of transfer call as of now: 1_000_000 + // if weight of the cheapest weight would be 10^7, this would be 10^9, which is: + // - 1 MILLICENTS in substrate node. + // - 1 milli-dot based on current polkadot runtime. + // (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`) + let mut t = TestExternalities::::new_with_code(COMPACT_CODE, Storage { + top: map![ + >::hashed_key_for(alice()) => { + (100 * DOLLARS).encode() + }, + >::hashed_key_for(bob()) => { + (10 * DOLLARS).encode() + }, + >::hashed_key().to_vec() => { + (110 * DOLLARS).encode() + }, + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] + ], + children: map![], + }); + + let tip = 1_000_000; + let xt = sign(CheckedExtrinsic { + signed: Some((alice(), signed_extra(0, tip))), + function: Call::Balances(default_transfer_call()), + }); + + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + None, + ).0; + + assert!(r.is_ok()); + let r = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt.clone()), + true, + None, + ).0; + assert!(r.is_ok()); + + t.execute_with(|| { + assert_eq!(Balances::total_balance(&bob()), (10 + 69) * DOLLARS); + // Components deducted from alice's balances: + // - Weight fee + // - Length fee + // - Tip + // - Creation-fee of bob's account. + let mut balance_alice = (100 - 69) * DOLLARS; + + let length_fee = TransactionBaseFee::get() + + TransactionByteFee::get() * + (xt.clone().encode().len() as Balance); + balance_alice -= length_fee; + + let weight = default_transfer_call().get_dispatch_info().weight; + let weight_fee = LinearWeightToFee::::convert(weight); + + // we know that weight to fee multiplier is effect-less in block 1. + assert_eq!(weight_fee as Balance, MILLICENTS); + balance_alice -= weight_fee; + + balance_alice -= tip; + balance_alice -= TransferFee::get(); + + assert_eq!(Balances::total_balance(&alice()), balance_alice); + }); +} + +#[test] +#[should_panic] +#[cfg(feature = "stress-test")] +fn block_weight_capacity_report() { + // Just report how many transfer calls you could fit into a block. The number should at least + // be a few hundred (250 at the time of writing but can change over time). Runs until panic. + use node_primitives::Index; + + // execution ext. + let mut t = new_test_ext(COMPACT_CODE, false); + // setup ext. + let mut tt = new_test_ext(COMPACT_CODE, false); + + let factor = 50; + let mut time = 10; + let mut nonce: Index = 0; + let mut block_number = 1; + let mut previous_hash: Hash = GENESIS_HASH.into(); + + loop { + let num_transfers = block_number * factor; + let mut xts = (0..num_transfers).map(|i| CheckedExtrinsic { + signed: Some((charlie(), signed_extra(nonce + i as Index, 0))), + function: Call::Balances(pallet_balances::Call::transfer(bob().into(), 0)), + }).collect::>(); + + xts.insert(0, CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(time * 1000)), + }); + + // NOTE: this is super slow. Can probably be improved. + let block = construct_block( + &mut tt, + block_number, + previous_hash, + xts + ); + + let len = block.0.len(); + print!( + "++ Executing block with {} transfers. Block size = {} bytes / {} kb / {} mb", + num_transfers, + len, + len / 1024, + len / 1024 / 1024, + ); + + let r = executor_call:: _>( + &mut t, + "Core_execute_block", + &block.0, + true, + None, + ).0; + + println!(" || Result = {:?}", r); + assert!(r.is_ok()); + + previous_hash = block.1; + nonce += num_transfers; + time += 10; + block_number += 1; + } +} + +#[test] +#[should_panic] +#[cfg(feature = "stress-test")] +fn block_length_capacity_report() { + // Just report how big a block can get. Executes until panic. Should be ignored unless if + // manually inspected. The number should at least be a few megabytes (5 at the time of + // writing but can change over time). + use node_primitives::Index; + + // execution ext. + let mut t = new_test_ext(COMPACT_CODE, false); + // setup ext. + let mut tt = new_test_ext(COMPACT_CODE, false); + + let factor = 256 * 1024; + let mut time = 10; + let mut nonce: Index = 0; + let mut block_number = 1; + let mut previous_hash: Hash = GENESIS_HASH.into(); + + loop { + // NOTE: this is super slow. Can probably be improved. + let block = construct_block( + &mut tt, + block_number, + previous_hash, + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(pallet_timestamp::Call::set(time * 1000)), + }, + CheckedExtrinsic { + signed: Some((charlie(), signed_extra(nonce, 0))), + function: Call::System(frame_system::Call::remark(vec![0u8; (block_number * factor) as usize])), + }, + ] + ); + + let len = block.0.len(); + print!( + "++ Executing block with big remark. Block size = {} bytes / {} kb / {} mb", + len, + len / 1024, + len / 1024 / 1024, + ); + + let r = executor_call:: _>( + &mut t, + "Core_execute_block", + &block.0, + true, + None, + ).0; + + println!(" || Result = {:?}", r); + assert!(r.is_ok()); + + previous_hash = block.1; + nonce += 1; + time += 10; + block_number += 1; + } +} diff --git a/bin/node/executor/tests/submit_transaction.rs b/bin/node/executor/tests/submit_transaction.rs new file mode 100644 index 0000000000000..9e91ffc76b38f --- /dev/null +++ b/bin/node/executor/tests/submit_transaction.rs @@ -0,0 +1,184 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use node_runtime::{ + Call, Executive, Indices, Runtime, SubmitTransaction, UncheckedExtrinsic, +}; +use sp_application_crypto::AppKey; +use sp_core::testing::KeyStore; +use sp_core::traits::KeystoreExt; +use sp_core::offchain::{ + TransactionPoolExt, + testing::TestTransactionPoolExt, +}; +use frame_system::offchain::{SubmitSignedTransaction, SubmitUnsignedTransaction}; +use pallet_im_online::sr25519::AuthorityPair as Key; +use codec::Decode; + +pub mod common; +use self::common::*; + +#[test] +fn should_submit_unsigned_transaction() { + let mut t = new_test_ext(COMPACT_CODE, false); + let (pool, state) = TestTransactionPoolExt::new(); + t.register_extension(TransactionPoolExt::new(pool)); + + t.execute_with(|| { + let signature = Default::default(); + let heartbeat_data = pallet_im_online::Heartbeat { + block_number: 1, + network_state: Default::default(), + session_index: 1, + authority_index: 0, + }; + + let call = pallet_im_online::Call::heartbeat(heartbeat_data, signature); + > + ::submit_unsigned(call) + .unwrap(); + + assert_eq!(state.read().transactions.len(), 1) + }); +} + +const PHRASE: &str = "news slush supreme milk chapter athlete soap sausage put clutch what kitten"; + +#[test] +fn should_submit_signed_transaction() { + let mut t = new_test_ext(COMPACT_CODE, false); + let (pool, state) = TestTransactionPoolExt::new(); + t.register_extension(TransactionPoolExt::new(pool)); + + let keystore = KeyStore::new(); + keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter2", PHRASE))).unwrap(); + keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter3", PHRASE))).unwrap(); + t.register_extension(KeystoreExt(keystore)); + + t.execute_with(|| { + let keys = > + ::find_all_local_keys(); + assert_eq!(keys.len(), 3, "Missing keys: {:?}", keys); + + let can_sign = > + ::can_sign(); + assert!(can_sign, "Since there are keys, `can_sign` should return true"); + + let call = pallet_balances::Call::transfer(Default::default(), Default::default()); + let results = + >::submit_signed(call); + + let len = results.len(); + assert_eq!(len, 3); + assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); + assert_eq!(state.read().transactions.len(), len); + }); +} + +#[test] +fn should_submit_signed_twice_from_the_same_account() { + let mut t = new_test_ext(COMPACT_CODE, false); + let (pool, state) = TestTransactionPoolExt::new(); + t.register_extension(TransactionPoolExt::new(pool)); + + let keystore = KeyStore::new(); + keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); + t.register_extension(KeystoreExt(keystore)); + + t.execute_with(|| { + let call = pallet_balances::Call::transfer(Default::default(), Default::default()); + let results = + >::submit_signed(call); + + let len = results.len(); + assert_eq!(len, 1); + assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); + assert_eq!(state.read().transactions.len(), 1); + + // submit another one from the same account. The nonce should be incremented. + let call = pallet_balances::Call::transfer(Default::default(), Default::default()); + let results = + >::submit_signed(call); + + let len = results.len(); + assert_eq!(len, 1); + assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); + assert_eq!(state.read().transactions.len(), 2); + + // now check that the transaction nonces are not equal + let s = state.read(); + fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { + let extra = tx.signature.unwrap().2; + extra.3 + } + let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); + let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); + assert!( + nonce1 != nonce2, + "Transactions should have different nonces. Got: {:?}", nonce1 + ); + }); +} + +#[test] +fn submitted_transaction_should_be_valid() { + use codec::Encode; + use frame_support::storage::StorageMap; + use sp_runtime::transaction_validity::ValidTransaction; + use sp_runtime::traits::StaticLookup; + + let mut t = new_test_ext(COMPACT_CODE, false); + let (pool, state) = TestTransactionPoolExt::new(); + t.register_extension(TransactionPoolExt::new(pool)); + + let keystore = KeyStore::new(); + keystore.write().sr25519_generate_new(Key::ID, Some(&format!("{}/hunter1", PHRASE))).unwrap(); + t.register_extension(KeystoreExt(keystore)); + + t.execute_with(|| { + let call = pallet_balances::Call::transfer(Default::default(), Default::default()); + let results = + >::submit_signed(call); + let len = results.len(); + assert_eq!(len, 1); + assert_eq!(results.into_iter().filter_map(|x| x.1.ok()).count(), len); + }); + + // check that transaction is valid, but reset environment storage, + // since CreateTransaction increments the nonce + let tx0 = state.read().transactions[0].clone(); + let mut t = new_test_ext(COMPACT_CODE, false); + t.execute_with(|| { + let extrinsic = UncheckedExtrinsic::decode(&mut &*tx0).unwrap(); + // add balance to the account + let author = extrinsic.signature.clone().unwrap().0; + let address = Indices::lookup(author).unwrap(); + >::insert(&address, 5_000_000_000_000); + + // check validity + let res = Executive::validate_transaction(extrinsic); + + assert_eq!(res.unwrap(), ValidTransaction { + priority: 2_411_002_000_000, + requires: vec![], + provides: vec![(address, 0).encode()], + longevity: 127, + propagate: true, + }); + }); +} + diff --git a/bin/node/primitives/Cargo.toml b/bin/node/primitives/Cargo.toml new file mode 100644 index 0000000000000..1ecfd76792cc6 --- /dev/null +++ b/bin/node/primitives/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "node-primitives" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-core = { version = "2.0.0", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" } + +[dev-dependencies] +sp-serializer = { version = "2.0.0", path = "../../../primitives/serializer" } +pretty_assertions = "0.6.1" + +[features] +default = ["std"] +std = [ + "sp-core/std", + "sp-runtime/std", +] diff --git a/bin/node/primitives/src/lib.rs b/bin/node/primitives/src/lib.rs new file mode 100644 index 0000000000000..97e8f50c27145 --- /dev/null +++ b/bin/node/primitives/src/lib.rs @@ -0,0 +1,64 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Low-level types used throughout the Substrate code. + +#![warn(missing_docs)] + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_runtime::{ + generic, traits::{Verify, BlakeTwo256, IdentifyAccount}, OpaqueExtrinsic, MultiSignature +}; + +/// An index to a block. +pub type BlockNumber = u32; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// The type for looking up accounts. We don't expect more than 4 billion of them. +pub type AccountIndex = u32; + +/// Balance of an account. +pub type Balance = u128; + +/// Type used for expressing timestamp. +pub type Moment = u64; + +/// Index of a transaction in the chain. +pub type Index = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// A timestamp: milliseconds since the unix epoch. +/// `u64` is enough to represent a duration of half a billion years, when the +/// time scale is milliseconds. +pub type Timestamp = u64; + +/// Digest item type. +pub type DigestItem = generic::DigestItem; +/// Header type. +pub type Header = generic::Header; +/// Block type. +pub type Block = generic::Block; +/// Block ID. +pub type BlockId = generic::BlockId; diff --git a/bin/node/rpc-client/Cargo.toml b/bin/node/rpc-client/Cargo.toml new file mode 100644 index 0000000000000..5ef9d1e99d16c --- /dev/null +++ b/bin/node/rpc-client/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "node-rpc-client" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +env_logger = "0.7.0" +futures = "0.1.29" +hyper = "0.12.35" +jsonrpc-core-client = { version = "14.0.3", features = ["http", "ws"] } +log = "0.4.8" +node-primitives = { version = "2.0.0", path = "../primitives" } +sc-rpc = { version = "2.0.0", path = "../../../client/rpc" } diff --git a/bin/node/rpc-client/src/main.rs b/bin/node/rpc-client/src/main.rs new file mode 100644 index 0000000000000..b28c9f8ff6392 --- /dev/null +++ b/bin/node/rpc-client/src/main.rs @@ -0,0 +1,70 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![warn(missing_docs)] + +//! Example substrate RPC client code. +//! +//! This module shows how you can write a Rust RPC client that connects to a running +//! substrate node and use staticly typed RPC wrappers. + +use futures::Future; +use hyper::rt; +use node_primitives::Hash; +use sc_rpc::author::{ + AuthorClient, + hash::ExtrinsicOrHash, +}; +use jsonrpc_core_client::{ + transports::http, + RpcError, +}; + +fn main() { + env_logger::init(); + + rt::run(rt::lazy(|| { + let uri = "http://localhost:9933"; + + http::connect(uri) + .and_then(|client: AuthorClient| { + remove_all_extrinsics(client) + }) + .map_err(|e| { + println!("Error: {:?}", e); + }) + })) +} + +/// Remove all pending extrinsics from the node. +/// +/// The example code takes `AuthorClient` and first: +/// 1. Calls the `pending_extrinsics` method to get all extrinsics in the pool. +/// 2. Then calls `remove_extrinsic` passing the obtained raw extrinsics. +/// +/// As the resul of running the code the entire content of the transaction pool is going +/// to be removed and the extrinsics are going to be temporarily banned. +fn remove_all_extrinsics(client: AuthorClient) -> impl Future { + client.pending_extrinsics() + .and_then(move |pending| { + client.remove_extrinsic( + pending.into_iter().map(|tx| ExtrinsicOrHash::Extrinsic(tx.into())).collect() + ) + }) + .map(|removed| { + println!("Removed extrinsics: {:?}", removed); + }) +} diff --git a/bin/node/rpc/Cargo.toml b/bin/node/rpc/Cargo.toml new file mode 100644 index 0000000000000..8c96542a8e6bd --- /dev/null +++ b/bin/node/rpc/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "node-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sc-client = { version = "2.0.0", path = "../../../client/" } +jsonrpc-core = "14.0.3" +node-primitives = { version = "2.0.0", path = "../primitives" } +node-runtime = { version = "2.0.0", path = "../runtime" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +pallet-contracts-rpc = { version = "2.0.0", path = "../../../frame/contracts/rpc/" } +pallet-transaction-payment-rpc = { version = "2.0.0", path = "../../../frame/transaction-payment/rpc/" } +substrate-frame-rpc-system = { version = "2.0.0", path = "../../../utils/frame/rpc/system" } +sp-transaction-pool = { version = "2.0.0", path = "../../../primitives/transaction-pool" } diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs new file mode 100644 index 0000000000000..a473b43a7f189 --- /dev/null +++ b/bin/node/rpc/src/lib.rs @@ -0,0 +1,101 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A collection of node-specific RPC methods. +//! +//! Since `substrate` core functionality makes no assumptions +//! about the modules used inside the runtime, so do +//! RPC methods defined in `sc-rpc` crate. +//! It means that `client/rpc` can't have any methods that +//! need some strong assumptions about the particular runtime. +//! +//! The RPCs available in this crate however can make some assumptions +//! about how the runtime is constructed and what `SRML` modules +//! are part of it. Therefore all node-runtime-specific RPCs can +//! be placed here or imported from corresponding `SRML` RPC definitions. + +#![warn(missing_docs)] + +use std::sync::Arc; + +use node_primitives::{Block, AccountId, Index, Balance}; +use node_runtime::UncheckedExtrinsic; +use sp_api::ProvideRuntimeApi; +use sp_transaction_pool::TransactionPool; + +/// Light client extra dependencies. +pub struct LightDeps { + /// Remote access to the blockchain (async). + pub remote_blockchain: Arc>, + /// Fetcher instance. + pub fetcher: Arc, +} + +impl LightDeps { + /// Create empty `LightDeps` with given `F` type. + /// + /// This is a convenience method to be used in the service builder, + /// to make sure the type of the `LightDeps` is matching. + pub fn none(_: Option>) -> Option { + None + } +} + +/// Instantiate all RPC extensions. +/// +/// If you provide `LightDeps`, the system is configured for light client. +pub fn create( + client: Arc, + pool: Arc

, + light_deps: Option>, +) -> jsonrpc_core::IoHandler where + C: ProvideRuntimeApi, + C: sc_client::blockchain::HeaderBackend, + C: Send + Sync + 'static, + C::Api: substrate_frame_rpc_system::AccountNonceApi, + C::Api: pallet_contracts_rpc::ContractsRuntimeApi, + C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, + F: sc_client::light::fetcher::Fetcher + 'static, + P: TransactionPool + 'static, + M: jsonrpc_core::Metadata + Default, +{ + use substrate_frame_rpc_system::{FullSystem, LightSystem, SystemApi}; + use pallet_contracts_rpc::{Contracts, ContractsApi}; + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; + + let mut io = jsonrpc_core::IoHandler::default(); + + if let Some(LightDeps { remote_blockchain, fetcher }) = light_deps { + io.extend_with( + SystemApi::::to_delegate(LightSystem::new(client, remote_blockchain, fetcher, pool)) + ); + } else { + io.extend_with( + SystemApi::to_delegate(FullSystem::new(client.clone(), pool)) + ); + + // Making synchronous calls in light client freezes the browser currently, + // more context: https://github.com/paritytech/substrate/pull/3480 + // These RPCs should use an asynchronous caller instead. + io.extend_with( + ContractsApi::to_delegate(Contracts::new(client.clone())) + ); + io.extend_with( + TransactionPaymentApi::to_delegate(TransactionPayment::new(client)) + ); + } + io +} diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml new file mode 100644 index 0000000000000..a8f26d13cba40 --- /dev/null +++ b/bin/node/runtime/Cargo.toml @@ -0,0 +1,122 @@ +[package] +name = "node-runtime" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" + +[dependencies] +# third-party dependencies +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } +integer-sqrt = { version = "0.1.2" } +safe-mix = { version = "1.0", default-features = false } +rustc-hex = { version = "2.0", optional = true } +serde = { version = "1.0.102", optional = true } + +# primitives +sp-authority-discovery = { version = "2.0.0", default-features = false, path = "../../../primitives/authority-discovery" } +sp-consensus-babe = { version = "0.8", default-features = false, path = "../../../primitives/consensus/babe" } +sp-block-builder = { path = "../../../primitives/block-builder", default-features = false} +sp-inherents = { version = "2.0.0", default-features = false, path = "../../../primitives/inherents" } +node-primitives = { version = "2.0.0", default-features = false, path = "../primitives" } +sp-offchain = { version = "2.0.0", default-features = false, path = "../../../primitives/offchain" } +sp-core = { version = "2.0.0", default-features = false, path = "../../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" } +sp-api = { version = "2.0.0", default-features = false, path = "../../../primitives/api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-staking = { version = "2.0.0", default-features = false, path = "../../../primitives/staking" } +sp-keyring = { version = "2.0.0", optional = true, path = "../../../primitives/keyring" } +sp-session = { version = "2.0.0", default-features = false, path = "../../../primitives/session" } +sp-transaction-pool = { version = "2.0.0", default-features = false, path = "../../../primitives/transaction-pool" } +sp-version = { version = "2.0.0", default-features = false, path = "../../../primitives/version" } + +# frame dependencies +frame-executive = { version = "2.0.0", default-features = false, path = "../../../frame/executive" } +frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" } +frame-system = { version = "2.0.0", default-features = false, path = "../../../frame/system" } +frame-system-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } +pallet-authority-discovery = { version = "2.0.0", default-features = false, path = "../../../frame/authority-discovery" } +pallet-authorship = { version = "2.0.0", default-features = false, path = "../../../frame/authorship" } +pallet-babe = { version = "2.0.0", default-features = false, path = "../../../frame/babe" } +pallet-balances = { version = "2.0.0", default-features = false, path = "../../../frame/balances" } +pallet-collective = { version = "2.0.0", default-features = false, path = "../../../frame/collective" } +pallet-contracts = { version = "2.0.0", default-features = false, path = "../../../frame/contracts" } +pallet-contracts-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } +pallet-democracy = { version = "2.0.0", default-features = false, path = "../../../frame/democracy" } +pallet-elections-phragmen = { version = "2.0.0", default-features = false, path = "../../../frame/elections-phragmen" } +pallet-finality-tracker = { version = "2.0.0", default-features = false, path = "../../../frame/finality-tracker" } +pallet-grandpa = { version = "2.0.0", default-features = false, path = "../../../frame/grandpa" } +pallet-im-online = { version = "2.0.0", default-features = false, path = "../../../frame/im-online" } +pallet-indices = { version = "2.0.0", default-features = false, path = "../../../frame/indices" } +pallet-membership = { version = "2.0.0", default-features = false, path = "../../../frame/membership" } +pallet-nicks = { version = "2.0.0", default-features = false, path = "../../../frame/nicks" } +pallet-offences = { version = "2.0.0", default-features = false, path = "../../../frame/offences" } +pallet-randomness-collective-flip = { version = "2.0.0", default-features = false, path = "../../../frame/randomness-collective-flip" } +pallet-session = { version = "2.0.0", features = ["historical"], path = "../../../frame/session", default-features = false } +pallet-staking = { version = "2.0.0", features = ["migrate"], path = "../../../frame/staking", default-features = false } +pallet-staking-reward-curve = { version = "2.0.0", path = "../../../frame/staking/reward-curve" } +pallet-sudo = { version = "2.0.0", default-features = false, path = "../../../frame/sudo" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../../frame/timestamp" } +pallet-treasury = { version = "2.0.0", default-features = false, path = "../../../frame/treasury" } +pallet-utility = { version = "2.0.0", default-features = false, path = "../../../frame/utility" } +pallet-transaction-payment = { version = "2.0.0", default-features = false, path = "../../../frame/transaction-payment" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } + +[build-dependencies] +wasm-builder-runner = { version = "1.0.4", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } + +[dev-dependencies] +sp-io = { version = "2.0.0", path = "../../../primitives/io" } + +[features] +default = ["std"] +std = [ + "sp-authority-discovery/std", + "pallet-authority-discovery/std", + "pallet-authorship/std", + "sp-consensus-babe/std", + "pallet-babe/std", + "pallet-balances/std", + "sp-block-builder/std", + "codec/std", + "pallet-collective/std", + "pallet-contracts-rpc-runtime-api/std", + "pallet-contracts/std", + "pallet-democracy/std", + "pallet-elections-phragmen/std", + "frame-executive/std", + "pallet-finality-tracker/std", + "pallet-grandpa/std", + "pallet-im-online/std", + "pallet-indices/std", + "sp-inherents/std", + "pallet-membership/std", + "pallet-nicks/std", + "node-primitives/std", + "sp-offchain/std", + "pallet-offences/std", + "sp-core/std", + "pallet-randomness-collective-flip/std", + "sp-std/std", + "rustc-hex", + "safe-mix/std", + "serde", + "pallet-session/std", + "sp-api/std", + "sp-runtime/std", + "sp-staking/std", + "pallet-staking/std", + "sp-keyring", + "sp-session/std", + "pallet-sudo/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-treasury/std", + "sp-transaction-pool/std", + "pallet-utility/std", + "sp-version/std", +] diff --git a/bin/node/runtime/build.rs b/bin/node/runtime/build.rs new file mode 100644 index 0000000000000..1ed2fa43e685c --- /dev/null +++ b/bin/node/runtime/build.rs @@ -0,0 +1,30 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; + +fn main() { + build_current_project_with_rustflags( + "wasm_binary.rs", + WasmBuilderSource::CratesOrPath { + path: "../../../utils/wasm-builder", + version: "1.0.8", + }, + // This instructs LLD to export __heap_base as a global variable, which is used by the + // external memory allocator. + "-Clink-arg=--export=__heap_base", + ); +} diff --git a/node/runtime/src/constants.rs b/bin/node/runtime/src/constants.rs similarity index 98% rename from node/runtime/src/constants.rs rename to bin/node/runtime/src/constants.rs index fba4c7ac79e56..b2c880c08bbf8 100644 --- a/node/runtime/src/constants.rs +++ b/bin/node/runtime/src/constants.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/bin/node/runtime/src/impls.rs b/bin/node/runtime/src/impls.rs new file mode 100644 index 0000000000000..646dc24f578de --- /dev/null +++ b/bin/node/runtime/src/impls.rs @@ -0,0 +1,364 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Some configurable implementations as associated type for the substrate runtime. + +use node_primitives::Balance; +use sp_runtime::traits::{Convert, Saturating}; +use sp_runtime::{Fixed64, Perbill}; +use frame_support::{traits::{OnUnbalanced, Currency, Get}, weights::Weight}; +use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance}; + +pub struct Author; +impl OnUnbalanced for Author { + fn on_nonzero_unbalanced(amount: NegativeImbalance) { + Balances::resolve_creating(&Authorship::author(), amount); + } +} + +/// Struct that handles the conversion of Balance -> `u64`. This is used for staking's election +/// calculation. +pub struct CurrencyToVoteHandler; + +impl CurrencyToVoteHandler { + fn factor() -> Balance { (Balances::total_issuance() / u64::max_value() as Balance).max(1) } +} + +impl Convert for CurrencyToVoteHandler { + fn convert(x: Balance) -> u64 { (x / Self::factor()) as u64 } +} + +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> Balance { x * Self::factor() } +} + +/// Convert from weight to balance via a simple coefficient multiplication +/// The associated type C encapsulates a constant in units of balance per weight +pub struct LinearWeightToFee(sp_std::marker::PhantomData); + +impl> Convert for LinearWeightToFee { + fn convert(w: Weight) -> Balance { + // substrate-node a weight of 10_000 (smallest non-zero weight) to be mapped to 10^7 units of + // fees, hence: + let coefficient = C::get(); + Balance::from(w).saturating_mul(coefficient) + } +} + +/// Update the given multiplier based on the following formula +/// +/// diff = (previous_block_weight - target_weight) +/// v = 0.00004 +/// next_weight = weight * (1 + (v . diff) + (v . diff)^2 / 2) +/// +/// Where `target_weight` must be given as the `Get` implementation of the `T` generic type. +/// https://research.web3.foundation/en/latest/polkadot/Token%20Economics/#relay-chain-transaction-fees +pub struct TargetedFeeAdjustment(sp_std::marker::PhantomData); + +impl> Convert for TargetedFeeAdjustment { + fn convert(multiplier: Fixed64) -> Fixed64 { + let block_weight = System::all_extrinsics_weight(); + let max_weight = MaximumBlockWeight::get(); + let target_weight = (T::get() * max_weight) as u128; + let block_weight = block_weight as u128; + + // determines if the first_term is positive + let positive = block_weight >= target_weight; + let diff_abs = block_weight.max(target_weight) - block_weight.min(target_weight); + // diff is within u32, safe. + let diff = Fixed64::from_rational(diff_abs as i64, max_weight as u64); + let diff_squared = diff.saturating_mul(diff); + + // 0.00004 = 4/100_000 = 40_000/10^9 + let v = Fixed64::from_rational(4, 100_000); + // 0.00004^2 = 16/10^10 ~= 2/10^9. Taking the future /2 into account, then it is just 1 + // parts from a billionth. + let v_squared_2 = Fixed64::from_rational(1, 1_000_000_000); + + let first_term = v.saturating_mul(diff); + // It is very unlikely that this will exist (in our poor perbill estimate) but we are giving + // it a shot. + let second_term = v_squared_2.saturating_mul(diff_squared); + + if positive { + // Note: this is merely bounded by how big the multiplier and the inner value can go, + // not by any economical reasoning. + let excess = first_term.saturating_add(second_term); + multiplier.saturating_add(excess) + } else { + // Proof: first_term > second_term. Safe subtraction. + let negative = first_term - second_term; + multiplier.saturating_sub(negative) + // despite the fact that apply_to saturates weight (final fee cannot go below 0) + // it is crucially important to stop here and don't further reduce the weight fee + // multiplier. While at -1, it means that the network is so un-congested that all + // transactions have no weight fee. We stop here and only increase if the network + // became more busy. + .max(Fixed64::from_rational(-1, 1)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::assert_eq_error_rate; + use crate::{MaximumBlockWeight, AvailableBlockRatio, Runtime}; + use crate::{constants::currency::*, TransactionPayment, TargetBlockFullness}; + use frame_support::weights::Weight; + + fn max() -> Weight { + MaximumBlockWeight::get() + } + + fn target() -> Weight { + TargetBlockFullness::get() * max() + } + + // poc reference implementation. + fn fee_multiplier_update(block_weight: Weight, previous: Fixed64) -> Fixed64 { + let block_weight = block_weight as f32; + let v: f32 = 0.00004; + + // maximum tx weight + let m = max() as f32; + // Ideal saturation in terms of weight + let ss = target() as f32; + // Current saturation in terms of weight + let s = block_weight; + + let fm = v * (s/m - ss/m) + v.powi(2) * (s/m - ss/m).powi(2) / 2.0; + let addition_fm = Fixed64::from_parts((fm * 1_000_000_000_f32).round() as i64); + previous.saturating_add(addition_fm) + } + + fn feemul(parts: i64) -> Fixed64 { + Fixed64::from_parts(parts) + } + + fn run_with_system_weight(w: Weight, assertions: F) where F: Fn() -> () { + let mut t: sp_io::TestExternalities = + frame_system::GenesisConfig::default().build_storage::().unwrap().into(); + t.execute_with(|| { + System::set_block_limits(w, 0); + assertions() + }); + } + + #[test] + fn fee_multiplier_update_poc_works() { + let fm = Fixed64::from_rational(0, 1); + let test_set = vec![ + (0, fm.clone()), + (100, fm.clone()), + (target(), fm.clone()), + (max() / 2, fm.clone()), + (max(), fm.clone()), + ]; + test_set.into_iter().for_each(|(w, fm)| { + run_with_system_weight(w, || { + assert_eq_error_rate!( + fee_multiplier_update(w, fm).into_inner(), + TargetedFeeAdjustment::::convert(fm).into_inner(), + 5, + ); + }) + }) + } + + #[test] + fn empty_chain_simulation() { + // just a few txs per_block. + let block_weight = 0; + run_with_system_weight(block_weight, || { + let mut fm = Fixed64::default(); + let mut iterations: u64 = 0; + loop { + let next = TargetedFeeAdjustment::::convert(fm); + fm = next; + if fm == Fixed64::from_rational(-1, 1) { break; } + iterations += 1; + } + println!("iteration {}, new fm = {:?}. Weight fee is now zero", iterations, fm); + assert!(iterations > 50_000, "This assertion is just a warning; Don't panic. \ + Current substrate/polkadot node are configured with a _slow adjusting fee_ \ + mechanism. Hence, it is really unlikely that fees collapse to zero even on an \ + empty chain in less than at least of couple of thousands of empty blocks. But this \ + simulation indicates that fees collapsed to zero after {} almost-empty blocks. \ + Check it", + iterations, + ); + }) + } + + #[test] + #[ignore] + fn congested_chain_simulation() { + // `cargo test congested_chain_simulation -- --nocapture` to get some insight. + + // almost full. The entire quota of normal transactions is taken. + let block_weight = AvailableBlockRatio::get() * max() - 100; + + // Default substrate minimum. + let tx_weight = 10_000; + + run_with_system_weight(block_weight, || { + // initial value configured on module + let mut fm = Fixed64::default(); + assert_eq!(fm, TransactionPayment::next_fee_multiplier()); + + let mut iterations: u64 = 0; + loop { + let next = TargetedFeeAdjustment::::convert(fm); + // if no change, panic. This should never happen in this case. + if fm == next { panic!("The fee should ever increase"); } + fm = next; + iterations += 1; + let fee = ::WeightToFee::convert(tx_weight); + let adjusted_fee = fm.saturated_multiply_accumulate(fee); + println!( + "iteration {}, new fm = {:?}. Fee at this point is: {} units / {} millicents, \ + {} cents, {} dollars", + iterations, + fm, + adjusted_fee, + adjusted_fee / MILLICENTS, + adjusted_fee / CENTS, + adjusted_fee / DOLLARS, + ); + } + }); + } + + #[test] + fn stateless_weight_mul() { + run_with_system_weight(target() / 4, || { + // Light block. Fee is reduced a little. + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(-7500), + ); + }); + run_with_system_weight(target() / 2, || { + // a bit more. Fee is decreased less, meaning that the fee increases as the block grows. + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(-5000), + ); + + }); + run_with_system_weight(target(), || { + // ideal. Original fee. No changes. + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(0), + ); + }); + run_with_system_weight(target() * 2, || { + // // More than ideal. Fee is increased. + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(10000), + ); + }); + } + + #[test] + fn stateful_weight_mul_grow_to_infinity() { + run_with_system_weight(target() * 2, || { + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(10000) + ); + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(10000)), + feemul(20000) + ); + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(20000)), + feemul(30000) + ); + // ... + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(1_000_000_000)), + feemul(1_000_000_000 + 10000) + ); + }); + } + + #[test] + fn stateful_weight_mil_collapse_to_minus_one() { + run_with_system_weight(0, || { + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(-10000) + ); + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(-10000)), + feemul(-20000) + ); + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(-20000)), + feemul(-30000) + ); + // ... + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(1_000_000_000 * -1)), + feemul(-1_000_000_000) + ); + }) + } + + #[test] + fn weight_to_fee_should_not_overflow_on_large_weights() { + let kb = 1024 as Weight; + let mb = kb * kb; + let max_fm = Fixed64::from_natural(i64::max_value()); + + // check that for all values it can compute, correctly. + vec![ + 0, + 1, + 10, + 1000, + kb, + 10 * kb, + 100 * kb, + mb, + 10 * mb, + Weight::max_value() / 2, + Weight::max_value(), + ].into_iter().for_each(|i| { + run_with_system_weight(i, || { + let next = TargetedFeeAdjustment::::convert(Fixed64::default()); + let truth = fee_multiplier_update(i, Fixed64::default()); + assert_eq_error_rate!(truth.into_inner(), next.into_inner(), 5); + }); + }); + + // Some values that are all above the target and will cause an increase. + let t = target(); + vec![t + 100, t * 2, t * 4] + .into_iter() + .for_each(|i| { + run_with_system_weight(i, || { + let fm = TargetedFeeAdjustment::::convert(max_fm); + // won't grow. The convert saturates everything. + assert_eq!(fm, max_fm); + }) + }); + } +} diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs new file mode 100644 index 0000000000000..4266ad7459e65 --- /dev/null +++ b/bin/node/runtime/src/lib.rs @@ -0,0 +1,816 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! The Substrate runtime. This can be compiled with ``#[no_std]`, ready for Wasm. + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit="256"] + +use sp_std::prelude::*; +use frame_support::{ + construct_runtime, parameter_types, debug, + weights::Weight, + traits::{SplitTwoWays, Currency, Randomness}, +}; +use sp_core::u32_trait::{_1, _2, _3, _4}; +use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Moment, Signature}; +use sp_api::impl_runtime_apis; +use sp_runtime::{ + Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str +}; +use sp_runtime::curve::PiecewiseLinear; +use sp_runtime::transaction_validity::TransactionValidity; +use sp_runtime::traits::{ + self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion, + OpaqueKeys, +}; +use sp_version::RuntimeVersion; +#[cfg(any(feature = "std", test))] +use sp_version::NativeVersion; +use sp_core::OpaqueMetadata; +use pallet_grandpa::AuthorityList as GrandpaAuthorityList; +use pallet_grandpa::fg_primitives; +use pallet_im_online::sr25519::{AuthorityId as ImOnlineId}; +use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; +use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; +use pallet_contracts_rpc_runtime_api::ContractExecResult; +use frame_system::offchain::TransactionSubmitter; +use sp_inherents::{InherentData, CheckInherentsResult}; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use pallet_timestamp::Call as TimestampCall; +pub use pallet_balances::Call as BalancesCall; +pub use pallet_contracts::Gas; +pub use frame_support::StorageValue; +pub use pallet_staking::StakerStatus; + +/// Implementations of some helper traits passed into runtime modules as associated types. +pub mod impls; +use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustment}; + +/// Constant values used within the runtime. +pub mod constants; +use constants::{time::*, currency::*}; + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +/// Runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("node"), + impl_name: create_runtime_str!("substrate-node"), + authoring_version: 10, + // Per convention: if the runtime behavior changes, increment spec_version + // and set impl_version to equal spec_version. If only runtime + // implementation changes and behavior does not, then leave spec_version as + // is and increment impl_version. + spec_version: 203, + impl_version: 203, + apis: RUNTIME_API_VERSIONS, +}; + +/// Native version. +#[cfg(any(feature = "std", test))] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +type NegativeImbalance = >::NegativeImbalance; + +pub type DealWithFees = SplitTwoWays< + Balance, + NegativeImbalance, + _4, Treasury, // 4 parts (80%) goes to the treasury. + _1, Author, // 1 part (20%) goes to the block author. +>; + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub const MaximumBlockWeight: Weight = 1_000_000_000; + pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const Version: RuntimeVersion = VERSION; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); +} + +impl frame_system::Trait for Runtime { + type Origin = Origin; + type Call = Call; + type Index = Index; + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = Indices; + type Header = generic::Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = Version; + type ModuleToIndex = ModuleToIndex; +} + +parameter_types! { + // One storage item; value is size 4+4+16+32 bytes = 56 bytes. + pub const MultisigDepositBase: Balance = 30 * CENTS; + // Additional storage item size of 32 bytes. + pub const MultisigDepositFactor: Balance = 5 * CENTS; + pub const MaxSignatories: u16 = 100; +} + +impl pallet_utility::Trait for Runtime { + type Event = Event; + type Call = Call; + type Currency = Balances; + type MultisigDepositBase = MultisigDepositBase; + type MultisigDepositFactor = MultisigDepositFactor; + type MaxSignatories = MaxSignatories; +} + +parameter_types! { + pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS; + pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK; +} + +impl pallet_babe::Trait for Runtime { + type EpochDuration = EpochDuration; + type ExpectedBlockTime = ExpectedBlockTime; + type EpochChangeTrigger = pallet_babe::ExternalTrigger; +} + +impl pallet_indices::Trait for Runtime { + type AccountIndex = AccountIndex; + type IsDeadAccount = Balances; + type ResolveHint = pallet_indices::SimpleResolveHint; + type Event = Event; +} + +parameter_types! { + pub const ExistentialDeposit: Balance = 1 * DOLLARS; + pub const TransferFee: Balance = 1 * CENTS; + pub const CreationFee: Balance = 1 * CENTS; +} + +impl pallet_balances::Trait for Runtime { + type Balance = Balance; + type OnFreeBalanceZero = ((Staking, Contracts), Session); + type OnReapAccount = System; + type OnNewAccount = Indices; + type Event = Event; + type DustRemoval = (); + type TransferPayment = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} + +parameter_types! { + pub const TransactionBaseFee: Balance = 1 * CENTS; + pub const TransactionByteFee: Balance = 10 * MILLICENTS; + // setting this to zero will disable the weight fee. + pub const WeightFeeCoefficient: Balance = 1_000; + // for a sane configuration, this should always be less than `AvailableBlockRatio`. + pub const TargetBlockFullness: Perbill = Perbill::from_percent(25); +} + +impl pallet_transaction_payment::Trait for Runtime { + type Currency = Balances; + type OnTransactionPayment = DealWithFees; + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = LinearWeightToFee; + type FeeMultiplierUpdate = TargetedFeeAdjustment; +} + +parameter_types! { + pub const MinimumPeriod: Moment = SLOT_DURATION / 2; +} +impl pallet_timestamp::Trait for Runtime { + type Moment = Moment; + type OnTimestampSet = Babe; + type MinimumPeriod = MinimumPeriod; +} + +parameter_types! { + pub const UncleGenerations: BlockNumber = 5; +} + +impl pallet_authorship::Trait for Runtime { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type UncleGenerations = UncleGenerations; + type FilterUncle = (); + type EventHandler = (Staking, ImOnline); +} + +impl_opaque_keys! { + pub struct SessionKeys { + pub grandpa: Grandpa, + pub babe: Babe, + pub im_online: ImOnline, + pub authority_discovery: AuthorityDiscovery, + } +} + +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); +} + +impl pallet_session::Trait for Runtime { + type OnSessionEnding = Staking; + type SessionHandler = ::KeyTypeIdProviders; + type ShouldEndSession = Babe; + type Event = Event; + type Keys = SessionKeys; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_staking::StashOf; + type SelectInitialValidators = Staking; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; +} + +impl pallet_session::historical::Trait for Runtime { + type FullIdentification = pallet_staking::Exposure; + type FullIdentificationOf = pallet_staking::ExposureOf; +} + +pallet_staking_reward_curve::build! { + const REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000, + max_inflation: 0_100_000, + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} + +parameter_types! { + pub const SessionsPerEra: sp_staking::SessionIndex = 6; + pub const BondingDuration: pallet_staking::EraIndex = 24 * 28; + pub const SlashDeferDuration: pallet_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. + pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; +} + +impl pallet_staking::Trait for Runtime { + type Currency = Balances; + type Time = Timestamp; + type CurrencyToVote = CurrencyToVoteHandler; + type RewardRemainder = Treasury; + type Event = Event; + type Slash = Treasury; // send the slashed funds to the treasury. + type Reward = (); // rewards are minted from the void + type SessionsPerEra = SessionsPerEra; + type BondingDuration = BondingDuration; + type SlashDeferDuration = SlashDeferDuration; + /// A super-majority of the council can cancel the slash. + type SlashCancelOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; + type SessionInterface = Self; + type RewardCurve = RewardCurve; +} + +parameter_types! { + pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES; + pub const MinimumDeposit: Balance = 100 * DOLLARS; + pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; + pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + // One cent: $10,000 / MB + pub const PreimageByteDeposit: Balance = 1 * CENTS; +} + +impl pallet_democracy::Trait for Runtime { + type Proposal = Call; + type Event = Event; + type Currency = Balances; + type EnactmentPeriod = EnactmentPeriod; + type LaunchPeriod = LaunchPeriod; + type VotingPeriod = VotingPeriod; + type EmergencyVotingPeriod = EmergencyVotingPeriod; + type MinimumDeposit = MinimumDeposit; + /// A straight majority of the council can decide what their next motion is. + type ExternalOrigin = pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>; + /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; + /// A unanimous council can have the next scheduled referendum be a straight default-carries + /// (NTB) vote. + type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>; + /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote + /// be tabled immediately and with a shorter voting/enactment period. + type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>; + // To cancel a proposal which has been passed, 2/3 of the council must agree to it. + type CancellationOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>; + // Any single technical committee member may veto a coming council proposal, however they can + // only do it once and it lasts only for the cooloff period. + type VetoOrigin = pallet_collective::EnsureMember; + type CooloffPeriod = CooloffPeriod; + type PreimageByteDeposit = PreimageByteDeposit; + type Slash = Treasury; +} + +type CouncilCollective = pallet_collective::Instance1; +impl pallet_collective::Trait for Runtime { + type Origin = Origin; + type Proposal = Call; + type Event = Event; +} + +parameter_types! { + pub const CandidacyBond: Balance = 10 * DOLLARS; + pub const VotingBond: Balance = 1 * DOLLARS; + pub const TermDuration: BlockNumber = 7 * DAYS; + pub const DesiredMembers: u32 = 13; + pub const DesiredRunnersUp: u32 = 7; +} + +impl pallet_elections_phragmen::Trait for Runtime { + type Event = Event; + type Currency = Balances; + type CurrencyToVote = CurrencyToVoteHandler; + type CandidacyBond = CandidacyBond; + type VotingBond = VotingBond; + type TermDuration = TermDuration; + type DesiredMembers = DesiredMembers; + type DesiredRunnersUp = DesiredRunnersUp; + type LoserCandidate = (); + type BadReport = (); + type KickedMember = (); + type ChangeMembers = Council; +} + +type TechnicalCollective = pallet_collective::Instance2; +impl pallet_collective::Trait for Runtime { + type Origin = Origin; + type Proposal = Call; + type Event = Event; +} + +impl pallet_membership::Trait for Runtime { + type Event = Event; + type AddOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type RemoveOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type SwapOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type ResetOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type MembershipInitialized = TechnicalCommittee; + type MembershipChanged = TechnicalCommittee; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 1 * DOLLARS; + pub const SpendPeriod: BlockNumber = 1 * DAYS; + pub const Burn: Permill = Permill::from_percent(50); + pub const TipCountdown: BlockNumber = 1 * DAYS; + pub const TipFindersFee: Percent = Percent::from_percent(20); + pub const TipReportDepositBase: Balance = 1 * DOLLARS; + pub const TipReportDepositPerByte: Balance = 1 * CENTS; +} + +impl pallet_treasury::Trait for Runtime { + type Currency = Balances; + type ApproveOrigin = pallet_collective::EnsureMembers<_4, AccountId, CouncilCollective>; + type RejectOrigin = pallet_collective::EnsureMembers<_2, AccountId, CouncilCollective>; + type Event = Event; + type ProposalRejection = (); + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type SpendPeriod = SpendPeriod; + type Burn = Burn; + type Tippers = Elections; + type TipCountdown = TipCountdown; + type TipFindersFee = TipFindersFee; + type TipReportDepositBase = TipReportDepositBase; + type TipReportDepositPerByte = TipReportDepositPerByte; +} + +parameter_types! { + pub const ContractTransferFee: Balance = 1 * CENTS; + pub const ContractCreationFee: Balance = 1 * CENTS; + pub const ContractTransactionBaseFee: Balance = 1 * CENTS; + pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS; + pub const ContractFee: Balance = 1 * CENTS; + pub const TombstoneDeposit: Balance = 1 * DOLLARS; + pub const RentByteFee: Balance = 1 * DOLLARS; + pub const RentDepositOffset: Balance = 1000 * DOLLARS; + pub const SurchargeReward: Balance = 150 * DOLLARS; +} + +impl pallet_contracts::Trait for Runtime { + type Currency = Balances; + type Time = Timestamp; + type Randomness = RandomnessCollectiveFlip; + type Call = Call; + type Event = Event; + type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminator; + type ComputeDispatchFee = pallet_contracts::DefaultDispatchFeeComputor; + type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter; + type GasPayment = (); + type RentPayment = (); + type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap; + type TombstoneDeposit = TombstoneDeposit; + type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset; + type RentByteFee = RentByteFee; + type RentDepositOffset = RentDepositOffset; + type SurchargeReward = SurchargeReward; + type TransferFee = ContractTransferFee; + type CreationFee = ContractCreationFee; + type TransactionBaseFee = ContractTransactionBaseFee; + type TransactionByteFee = ContractTransactionByteFee; + type ContractFee = ContractFee; + type CallBaseFee = pallet_contracts::DefaultCallBaseFee; + type InstantiateBaseFee = pallet_contracts::DefaultInstantiateBaseFee; + type MaxDepth = pallet_contracts::DefaultMaxDepth; + type MaxValueSize = pallet_contracts::DefaultMaxValueSize; + type BlockGasLimit = pallet_contracts::DefaultBlockGasLimit; +} + +impl pallet_sudo::Trait for Runtime { + type Event = Event; + type Proposal = Call; +} + +/// A runtime transaction submitter. +pub type SubmitTransaction = TransactionSubmitter; + +parameter_types! { + pub const SessionDuration: BlockNumber = EPOCH_DURATION_IN_SLOTS as _; +} + +impl pallet_im_online::Trait for Runtime { + type AuthorityId = ImOnlineId; + type Call = Call; + type Event = Event; + type SubmitTransaction = SubmitTransaction; + type ReportUnresponsiveness = Offences; + type SessionDuration = SessionDuration; +} + +impl pallet_offences::Trait for Runtime { + type Event = Event; + type IdentificationTuple = pallet_session::historical::IdentificationTuple; + type OnOffenceHandler = Staking; +} + +impl pallet_authority_discovery::Trait for Runtime {} + +impl pallet_grandpa::Trait for Runtime { + type Event = Event; +} + +parameter_types! { + pub const WindowSize: BlockNumber = 101; + pub const ReportLatency: BlockNumber = 1000; +} + +impl pallet_finality_tracker::Trait for Runtime { + type OnFinalizationStalled = Grandpa; + type WindowSize = WindowSize; + type ReportLatency = ReportLatency; +} + +parameter_types! { + pub const ReservationFee: Balance = 1 * DOLLARS; + pub const MinLength: usize = 3; + pub const MaxLength: usize = 16; +} + +impl pallet_nicks::Trait for Runtime { + type Event = Event; + type Currency = Balances; + type ReservationFee = ReservationFee; + type Slashed = Treasury; + type ForceOrigin = pallet_collective::EnsureMember; + type MinLength = MinLength; + type MaxLength = MaxLength; +} + +impl frame_system::offchain::CreateTransaction for Runtime { + type Public = ::Signer; + type Signature = Signature; + + fn create_transaction>( + call: Call, + public: Self::Public, + account: AccountId, + index: Index, + ) -> Option<(Call, ::SignaturePayload)> { + // take the biggest period possible. + let period = BlockHashCount::get() + .checked_next_power_of_two() + .map(|c| c / 2) + .unwrap_or(2) as u64; + let current_block = System::block_number() + .saturated_into::() + // The `System::block_number` is initialized with `n+1`, + // so the actual block number is `n`. + .saturating_sub(1); + let tip = 0; + let extra: SignedExtra = ( + frame_system::CheckVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), + frame_system::CheckNonce::::from(index), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + Default::default(), + ); + let raw_payload = SignedPayload::new(call, extra).map_err(|e| { + debug::warn!("Unable to create signed payload: {:?}", e); + }).ok()?; + let signature = TSigner::sign(public, &raw_payload)?; + let address = Indices::unlookup(account); + let (call, extra, _) = raw_payload.deconstruct(); + Some((call, (address, signature, extra))) + } +} + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = node_primitives::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Module, Call, Storage, Config, Event}, + Utility: pallet_utility::{Module, Call, Storage, Event}, + Babe: pallet_babe::{Module, Call, Storage, Config, Inherent(Timestamp)}, + Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, + Authorship: pallet_authorship::{Module, Call, Storage, Inherent}, + Indices: pallet_indices, + Balances: pallet_balances, + TransactionPayment: pallet_transaction_payment::{Module, Storage}, + Staking: pallet_staking, + Session: pallet_session::{Module, Call, Storage, Event, Config}, + Democracy: pallet_democracy::{Module, Call, Storage, Config, Event}, + Council: pallet_collective::::{Module, Call, Storage, Origin, Event, Config}, + TechnicalCommittee: pallet_collective::::{Module, Call, Storage, Origin, Event, Config}, + Elections: pallet_elections_phragmen::{Module, Call, Storage, Event}, + TechnicalMembership: pallet_membership::::{Module, Call, Storage, Event, Config}, + FinalityTracker: pallet_finality_tracker::{Module, Call, Inherent}, + Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, + Treasury: pallet_treasury::{Module, Call, Storage, Config, Event}, + Contracts: pallet_contracts, + Sudo: pallet_sudo, + ImOnline: pallet_im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, + AuthorityDiscovery: pallet_authority_discovery::{Module, Call, Config}, + Offences: pallet_offences::{Module, Call, Storage, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, + Nicks: pallet_nicks::{Module, Call, Storage, Event}, + } +); + +/// The address format for describing accounts. +pub type Address = ::Source; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, + pallet_contracts::CheckBlockGasLimit, +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive, Runtime, AllModules>; + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + Runtime::metadata().into() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_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 { + RandomnessCollectiveFlip::random_seed() + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { + Executive::validate_transaction(tx) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + } + + impl sp_consensus_babe::BabeApi for Runtime { + fn configuration() -> sp_consensus_babe::BabeConfiguration { + // The choice of `c` parameter (where `1 - c` represents the + // probability of a slot being empty), is done in accordance to the + // slot duration and expected target block time, for safely + // resisting network delays of maximum two seconds. + // + sp_consensus_babe::BabeConfiguration { + slot_duration: Babe::slot_duration(), + epoch_length: EpochDuration::get(), + c: PRIMARY_PROBABILITY, + genesis_authorities: Babe::authorities(), + randomness: Babe::randomness(), + secondary_slots: true, + } + } + } + + impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { + fn authorities() -> Vec { + AuthorityDiscovery::authorities() + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl pallet_contracts_rpc_runtime_api::ContractsApi for Runtime { + fn call( + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: u64, + input_data: Vec, + ) -> ContractExecResult { + let exec_result = Contracts::bare_call( + origin, + dest.into(), + value, + gas_limit, + input_data, + ); + match exec_result { + Ok(v) => ContractExecResult::Success { + status: v.status, + data: v.data, + }, + Err(_) => ContractExecResult::Error, + } + } + + fn get_storage( + address: AccountId, + key: [u8; 32], + ) -> pallet_contracts_rpc_runtime_api::GetStorageResult { + Contracts::get_storage(address, key).map_err(|rpc_err| { + use pallet_contracts::GetStorageError; + use pallet_contracts_rpc_runtime_api::{GetStorageError as RpcGetStorageError}; + /// Map the contract error into the RPC layer error. + match rpc_err { + GetStorageError::ContractDoesntExist => RpcGetStorageError::ContractDoesntExist, + GetStorageError::IsTombstone => RpcGetStorageError::IsTombstone, + } + }) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< + Block, + Balance, + UncheckedExtrinsic, + > for Runtime { + fn query_info(uxt: UncheckedExtrinsic, len: u32) -> RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + SessionKeys::generate(seed) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_system::offchain::{SignAndSubmitTransaction, SubmitSignedTransaction}; + + #[test] + fn validate_transaction_submitter_bounds() { + fn is_submit_signed_transaction() where + T: SubmitSignedTransaction< + Runtime, + Call, + >, + {} + + fn is_sign_and_submit_transaction() where + T: SignAndSubmitTransaction< + Runtime, + Call, + Extrinsic=UncheckedExtrinsic, + CreateTransaction=Runtime, + Signer=ImOnlineId, + >, + {} + + is_submit_signed_transaction::(); + is_sign_and_submit_transaction::(); + } + + #[test] + fn block_hooks_weight_should_not_exceed_limits() { + use frame_support::weights::WeighBlock; + let check_for_block = |b| { + let block_hooks_weight = + >::on_initialize(b) + + >::on_finalize(b); + + assert_eq!( + block_hooks_weight, + 0, + "This test might fail simply because the value being compared to has increased to a \ + module declaring a new weight for a hook or call. In this case update the test and \ + happily move on.", + ); + + // Invariant. Always must be like this to have a sane chain. + assert!(block_hooks_weight < MaximumBlockWeight::get()); + + // Warning. + if block_hooks_weight > MaximumBlockWeight::get() / 2 { + println!( + "block hooks weight is consuming more than a block's capacity. You probably want \ + to re-think this. This test will fail now." + ); + assert!(false); + } + }; + + let _ = (0..100_000).for_each(check_for_block); + } +} diff --git a/bin/node/testing/Cargo.toml b/bin/node/testing/Cargo.toml new file mode 100644 index 0000000000000..4449c7bd22d47 --- /dev/null +++ b/bin/node/testing/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "node-testing" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Test utilities for Substrate node." +edition = "2018" + +[dependencies] +pallet-balances = { version = "2.0.0", path = "../../../frame/balances" } +sc-client = { version = "2.0.0", path = "../../../client/" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" } +pallet-grandpa = { version = "2.0.0", path = "../../../frame/grandpa" } +pallet-indices = { version = "2.0.0", path = "../../../frame/indices" } +sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" } +node-executor = { version = "2.0.0", path = "../executor" } +node-primitives = { version = "2.0.0", path = "../primitives" } +node-runtime = { version = "2.0.0", path = "../runtime" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-io = { version = "2.0.0", path = "../../../primitives/io" } +frame-support = { version = "2.0.0", path = "../../../frame/support" } +pallet-session = { version = "2.0.0", path = "../../../frame/session" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +pallet-staking = { version = "2.0.0", path = "../../../frame/staking" } +sc-executor = { version = "2.0.0", path = "../../../client/executor" } +frame-system = { version = "2.0.0", path = "../../../frame/system" } +substrate-test-client = { version = "2.0.0", path = "../../../test-utils/client" } +pallet-timestamp = { version = "2.0.0", path = "../../../frame/timestamp" } +pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" } +pallet-treasury = { version = "2.0.0", path = "../../../frame/treasury" } +wabt = "0.9.2" diff --git a/bin/node/testing/src/client.rs b/bin/node/testing/src/client.rs new file mode 100644 index 0000000000000..140d1cbfc3337 --- /dev/null +++ b/bin/node/testing/src/client.rs @@ -0,0 +1,73 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Utilites to build a `TestClient` for `node-runtime`. + +use sp_runtime::BuildStorage; + +/// Re-export test-client utilities. +pub use substrate_test_client::*; + +/// Call executor for `node-runtime` `TestClient`. +pub type Executor = sc_executor::NativeExecutor; + +/// Default backend type. +pub type Backend = sc_client_db::Backend; + +/// Test client type. +pub type Client = sc_client::Client< + Backend, + sc_client::LocalCallExecutor, + node_primitives::Block, + node_runtime::RuntimeApi, +>; + +/// Genesis configuration parameters for `TestClient`. +#[derive(Default)] +pub struct GenesisParameters { + support_changes_trie: bool, +} + +impl substrate_test_client::GenesisInit for GenesisParameters { + fn genesis_storage(&self) -> Storage { + crate::genesis::config(self.support_changes_trie, None).build_storage().unwrap() + } +} + +/// A `test-runtime` extensions to `TestClientBuilder`. +pub trait TestClientBuilderExt: Sized { + /// Create test client builder. + fn new() -> Self; + + /// Build the test client. + fn build(self) -> Client; +} + +impl TestClientBuilderExt for substrate_test_client::TestClientBuilder< + sc_client::LocalCallExecutor, + Backend, + GenesisParameters, +> { + fn new() -> Self{ + Self::default() + } + + fn build(self) -> Client { + self.build_with_native_executor(None).0 + } +} + + diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs new file mode 100644 index 0000000000000..44dd79a7f438a --- /dev/null +++ b/bin/node/testing/src/genesis.rs @@ -0,0 +1,100 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Genesis Configuration. + +use crate::keyring::*; +use sp_keyring::{Ed25519Keyring, Sr25519Keyring}; +use node_runtime::{ + GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, SystemConfig, + GrandpaConfig, IndicesConfig, ContractsConfig, WASM_BINARY, +}; +use node_runtime::constants::currency::*; +use sp_core::ChangesTrieConfiguration; +use sp_runtime::Perbill; + + +/// Create genesis runtime configuration for tests. +pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig { + GenesisConfig { + frame_system: Some(SystemConfig { + changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration { + digest_interval: 2, + digest_levels: 2, + }) } else { None }, + code: code.map(|x| x.to_vec()).unwrap_or_else(|| WASM_BINARY.to_vec()), + }), + pallet_indices: Some(IndicesConfig { + ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()], + }), + pallet_balances: Some(BalancesConfig { + balances: vec![ + (alice(), 111 * DOLLARS), + (bob(), 100 * DOLLARS), + (charlie(), 100_000_000 * DOLLARS), + (dave(), 111 * DOLLARS), + (eve(), 101 * DOLLARS), + (ferdie(), 100 * DOLLARS), + ], + vesting: vec![], + }), + pallet_session: Some(SessionConfig { + keys: vec![ + (alice(), to_session_keys( + &Ed25519Keyring::Alice, + &Sr25519Keyring::Alice, + )), + (bob(), to_session_keys( + &Ed25519Keyring::Bob, + &Sr25519Keyring::Bob, + )), + (charlie(), to_session_keys( + &Ed25519Keyring::Charlie, + &Sr25519Keyring::Charlie, + )), + ] + }), + pallet_staking: Some(StakingConfig { + current_era: 0, + stakers: vec![ + (dave(), alice(), 111 * DOLLARS, pallet_staking::StakerStatus::Validator), + (eve(), bob(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator), + (ferdie(), charlie(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator) + ], + validator_count: 3, + minimum_validator_count: 0, + slash_reward_fraction: Perbill::from_percent(10), + invulnerables: vec![alice(), bob(), charlie()], + .. Default::default() + }), + pallet_contracts: Some(ContractsConfig { + current_schedule: Default::default(), + gas_price: 1 * MILLICENTS, + }), + pallet_babe: Some(Default::default()), + pallet_grandpa: Some(GrandpaConfig { + authorities: vec![], + }), + pallet_im_online: Some(Default::default()), + pallet_authority_discovery: Some(Default::default()), + pallet_democracy: Some(Default::default()), + pallet_collective_Instance1: Some(Default::default()), + pallet_collective_Instance2: Some(Default::default()), + pallet_membership_Instance1: Some(Default::default()), + pallet_sudo: Some(Default::default()), + pallet_treasury: Some(Default::default()), + } +} diff --git a/node/testing/src/keyring.rs b/bin/node/testing/src/keyring.rs similarity index 77% rename from node/testing/src/keyring.rs rename to bin/node/testing/src/keyring.rs index ca44a53880fc1..6b0d06875d692 100644 --- a/node/testing/src/keyring.rs +++ b/bin/node/testing/src/keyring.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,14 +16,16 @@ //! Test accounts. -use keyring::{AccountKeyring, Sr25519Keyring, Ed25519Keyring}; +use sp_keyring::{AccountKeyring, Sr25519Keyring, Ed25519Keyring}; use node_primitives::{AccountId, Balance, Index}; use node_runtime::{CheckedExtrinsic, UncheckedExtrinsic, SessionKeys, SignedExtra}; -use sr_primitives::generic::Era; +use sp_runtime::generic::Era; use codec::Encode; /// Alice's account id. -pub fn alice() -> AccountId { AccountKeyring::Alice.into() } +pub fn alice() -> AccountId { + AccountKeyring::Alice.into() +} /// Bob's account id. pub fn bob() -> AccountId { @@ -59,18 +61,19 @@ pub fn to_session_keys( grandpa: ed25519_keyring.to_owned().public().into(), babe: sr25519_keyring.to_owned().public().into(), im_online: sr25519_keyring.to_owned().public().into(), + authority_discovery: sr25519_keyring.to_owned().public().into(), } } /// Returns transaction extra. pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { ( - system::CheckVersion::new(), - system::CheckGenesis::new(), - system::CheckEra::from(Era::mortal(256, 0)), - system::CheckNonce::from(nonce), - system::CheckWeight::new(), - transaction_payment::ChargeTransactionPayment::from(extra_fee), + frame_system::CheckVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::mortal(256, 0)), + frame_system::CheckNonce::from(nonce), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(extra_fee), Default::default(), ) } @@ -83,13 +86,13 @@ pub fn sign(xt: CheckedExtrinsic, version: u32, genesis_hash: [u8; 32]) -> Unche let key = AccountKeyring::from_account_id(&signed).unwrap(); let signature = payload.using_encoded(|b| { if b.len() > 256 { - key.sign(&sr_io::blake2_256(b)) + key.sign(&sp_io::hashing::blake2_256(b)) } else { key.sign(b) } }).into(); UncheckedExtrinsic { - signature: Some((indices::address::Address::Id(signed), signature, extra)), + signature: Some((pallet_indices::address::Address::Id(signed), signature, extra)), function: payload.0, } } @@ -99,4 +102,3 @@ pub fn sign(xt: CheckedExtrinsic, version: u32, genesis_hash: [u8; 32]) -> Unche }, } } - diff --git a/bin/node/testing/src/lib.rs b/bin/node/testing/src/lib.rs new file mode 100644 index 0000000000000..f4a5e75e492d3 --- /dev/null +++ b/bin/node/testing/src/lib.rs @@ -0,0 +1,24 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A set of testing utilities for Substrate Node. + +#![warn(missing_docs)] + +pub mod client; +pub mod genesis; +pub mod keyring; + diff --git a/bin/node/transaction-factory/Cargo.toml b/bin/node/transaction-factory/Cargo.toml new file mode 100644 index 0000000000000..8b10e10f41f81 --- /dev/null +++ b/bin/node/transaction-factory/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "node-transaction-factory" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-block-builder = { version = "2.0.0", path = "../../../primitives/block-builder" } +sc-cli = { version = "2.0.0", path = "../../../client/cli" } +sc-client-api = { version = "2.0.0", path = "../../../client/api" } +sc-client = { version = "2.0.0", path = "../../../client" } +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +log = "0.4.8" +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sc-service = { version = "2.0.0", path = "../../../client/service" } +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } diff --git a/test-utils/transaction-factory/src/complex_mode.rs b/bin/node/transaction-factory/src/complex_mode.rs similarity index 87% rename from test-utils/transaction-factory/src/complex_mode.rs rename to bin/node/transaction-factory/src/complex_mode.rs index ed76a66b09083..6d7e60c8d3c1f 100644 --- a/test-utils/transaction-factory/src/complex_mode.rs +++ b/bin/node/transaction-factory/src/complex_mode.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -41,12 +41,11 @@ use std::sync::Arc; use log::info; -use client::Client; -use client::block_builder::api::BlockBuilder; -use client::runtime_api::ConstructRuntimeApi; -use primitives::{Blake2Hasher, Hasher}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{Block as BlockT, ProvideRuntimeApi, One, Zero}; +use sc_client::Client; +use sp_block_builder::BlockBuilder; +use sp_api::{ConstructRuntimeApi, ProvideRuntimeApi}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{Block as BlockT, One, Zero}; use crate::{RuntimeAdapter, create_block}; @@ -59,11 +58,13 @@ pub fn next( prior_block_id: BlockId, ) -> Option where - Block: BlockT::Out>, - Exec: client::CallExecutor + Send + Sync + Clone, - Backend: client::backend::Backend + Send, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilder, + Block: BlockT, + Exec: sc_client::CallExecutor + Send + Sync + Clone, + Backend: sc_client_api::backend::Backend + Send, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + BlockBuilder + + sp_api::ApiExt, RtApi: ConstructRuntimeApi> + Send + Sync, RA: RuntimeAdapter, { diff --git a/bin/node/transaction-factory/src/lib.rs b/bin/node/transaction-factory/src/lib.rs new file mode 100644 index 0000000000000..f3dcdb0875002 --- /dev/null +++ b/bin/node/transaction-factory/src/lib.rs @@ -0,0 +1,210 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Simple transaction factory which distributes tokens from a master +//! account to a specified number of newly created accounts. +//! +//! The factory currently only works on an empty database! + +use std::collections::HashMap; +use std::sync::Arc; +use std::cmp::PartialOrd; +use std::fmt::Display; + +use log::info; + +use sc_client::Client; +use sp_block_builder::BlockBuilder; +use sp_api::{ConstructRuntimeApi, ProvideRuntimeApi, ApiExt}; +use sp_consensus::{ + BlockOrigin, BlockImportParams, InherentData, ForkChoiceStrategy, + SelectChain +}; +use sp_consensus::block_import::BlockImport; +use codec::{Decode, Encode}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{ + Block as BlockT, Header as HeaderT, SimpleArithmetic, One, Zero, +}; +pub use crate::modes::Mode; + +pub mod modes; +mod complex_mode; +mod simple_modes; + +pub trait RuntimeAdapter { + type AccountId: Display; + type Balance: Display + SimpleArithmetic + From; + type Block: BlockT; + type Index: Copy; + type Number: Display + PartialOrd + SimpleArithmetic + Zero + One; + type Phase: Copy; + type Secret; + + fn new(mode: Mode, rounds: u64, start_number: u64) -> Self; + + fn block_no(&self) -> Self::Number; + fn block_in_round(&self) -> Self::Number; + fn mode(&self) -> &Mode; + fn num(&self) -> Self::Number; + fn rounds(&self) -> Self::Number; + fn round(&self) -> Self::Number; + fn start_number(&self) -> Self::Number; + + fn set_block_in_round(&mut self, val: Self::Number); + fn set_block_no(&mut self, val: Self::Number); + fn set_round(&mut self, val: Self::Number); + + fn transfer_extrinsic( + &self, + sender: &Self::AccountId, + key: &Self::Secret, + destination: &Self::AccountId, + amount: &Self::Balance, + version: u32, + genesis_hash: &::Hash, + prior_block_hash: &::Hash, + ) -> ::Extrinsic; + + fn inherent_extrinsics(&self) -> InherentData; + + fn minimum_balance() -> Self::Balance; + fn master_account_id() -> Self::AccountId; + fn master_account_secret() -> Self::Secret; + fn extract_index(&self, account_id: &Self::AccountId, block_hash: &::Hash) -> Self::Index; + fn extract_phase(&self, block_hash: ::Hash) -> Self::Phase; + fn gen_random_account_id(seed: &Self::Number) -> Self::AccountId; + fn gen_random_account_secret(seed: &Self::Number) -> Self::Secret; +} + +/// Manufactures transactions. The exact amount depends on +/// `mode`, `num` and `rounds`. +pub fn factory( + mut factory_state: RA, + client: &Arc>, + select_chain: &Sc, +) -> sc_cli::error::Result<()> +where + Block: BlockT, + Exec: sc_client::CallExecutor + Send + Sync + Clone, + Backend: sc_client_api::backend::Backend + Send, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + BlockBuilder + + ApiExt, + RtApi: ConstructRuntimeApi> + Send + Sync, + Sc: SelectChain, + RA: RuntimeAdapter, + Block::Hash: From, +{ + if *factory_state.mode() != Mode::MasterToNToM && factory_state.rounds() > RA::Number::one() { + let msg = "The factory can only be used with rounds set to 1 in this mode.".into(); + return Err(sc_cli::error::Error::Input(msg)); + } + + let best_header: Result<::Header, sc_cli::error::Error> = + select_chain.best_chain().map_err(|e| format!("{:?}", e).into()); + let mut best_hash = best_header?.hash(); + let mut best_block_id = BlockId::::hash(best_hash); + let version = client.runtime_version_at(&best_block_id)?.spec_version; + let genesis_hash = client.block_hash(Zero::zero())? + .expect("Genesis block always exists; qed").into(); + + while let Some(block) = match factory_state.mode() { + Mode::MasterToNToM => complex_mode::next::( + &mut factory_state, + &client, + version, + genesis_hash, + best_hash.into(), + best_block_id, + ), + _ => simple_modes::next::( + &mut factory_state, + &client, + version, + genesis_hash, + best_hash.into(), + best_block_id, + ), + } { + best_hash = block.header().hash(); + best_block_id = BlockId::::hash(best_hash); + import_block(client.clone(), block); + + info!("Imported block at {}", factory_state.block_no()); + } + + Ok(()) +} + +/// Create a baked block from a transfer extrinsic and timestamp inherent. +pub fn create_block( + client: &Arc>, + transfer: ::Extrinsic, + inherent_extrinsics: Vec<::Extrinsic>, +) -> Block +where + Block: BlockT, + Exec: sc_client::CallExecutor + Send + Sync + Clone, + Backend: sc_client_api::backend::Backend + Send, + Client: ProvideRuntimeApi, + RtApi: ConstructRuntimeApi> + Send + Sync, + as ProvideRuntimeApi>::Api: + BlockBuilder + + ApiExt, + RA: RuntimeAdapter, +{ + let mut block = client.new_block(Default::default()).expect("Failed to create new block"); + block.push( + Decode::decode(&mut &transfer.encode()[..]) + .expect("Failed to decode transfer extrinsic") + ).expect("Failed to push transfer extrinsic into block"); + + for inherent in inherent_extrinsics { + block.push(inherent).expect("Failed ..."); + } + + block.build().expect("Failed to bake block").block +} + +fn import_block( + mut client: Arc>, + block: Block +) -> () where + Block: BlockT, + Exec: sc_client::CallExecutor + Send + Sync + Clone, + Backend: sc_client_api::backend::Backend + Send, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + sp_api::Core + + ApiExt, +{ + let import = BlockImportParams { + origin: BlockOrigin::File, + header: block.header().clone(), + post_digests: Vec::new(), + body: Some(block.extrinsics().to_vec()), + storage_changes: None, + finalized: false, + justification: None, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + client.import_block(import, HashMap::new()).expect("Failed to import block"); +} diff --git a/test-utils/transaction-factory/src/modes.rs b/bin/node/transaction-factory/src/modes.rs similarity index 95% rename from test-utils/transaction-factory/src/modes.rs rename to bin/node/transaction-factory/src/modes.rs index a212d6aed8c31..5deab7635e114 100644 --- a/test-utils/transaction-factory/src/modes.rs +++ b/bin/node/transaction-factory/src/modes.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/test-utils/transaction-factory/src/simple_modes.rs b/bin/node/transaction-factory/src/simple_modes.rs similarity index 81% rename from test-utils/transaction-factory/src/simple_modes.rs rename to bin/node/transaction-factory/src/simple_modes.rs index bcbb91200657f..fba328731a98f 100644 --- a/test-utils/transaction-factory/src/simple_modes.rs +++ b/bin/node/transaction-factory/src/simple_modes.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -36,12 +36,11 @@ use std::sync::Arc; use log::info; -use client::Client; -use client::block_builder::api::BlockBuilder; -use client::runtime_api::ConstructRuntimeApi; -use primitives::{Blake2Hasher, Hasher}; -use sr_primitives::traits::{Block as BlockT, ProvideRuntimeApi, One}; -use sr_primitives::generic::BlockId; +use sc_client::Client; +use sp_block_builder::BlockBuilder; +use sp_api::{ConstructRuntimeApi, ProvideRuntimeApi}; +use sp_runtime::traits::{Block as BlockT, One}; +use sp_runtime::generic::BlockId; use crate::{Mode, RuntimeAdapter, create_block}; @@ -54,11 +53,13 @@ pub fn next( prior_block_id: BlockId, ) -> Option where - Block: BlockT::Out>, - Exec: client::CallExecutor + Send + Sync + Clone, - Backend: client::backend::Backend + Send, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilder, + Block: BlockT, + Exec: sc_client::CallExecutor + Send + Sync + Clone, + Backend: sc_client_api::backend::Backend + Send, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + BlockBuilder + + sp_api::ApiExt, RtApi: ConstructRuntimeApi> + Send + Sync, RA: RuntimeAdapter, { diff --git a/bin/utils/chain-spec-builder/Cargo.toml b/bin/utils/chain-spec-builder/Cargo.toml new file mode 100644 index 0000000000000..c8d79afbced11 --- /dev/null +++ b/bin/utils/chain-spec-builder/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "chain-spec-builder" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" + +[dependencies] +ansi_term = "0.12.1" +sc-keystore = { version = "2.0.0", path = "../../../client/keystore" } +node-cli = { version = "2.0.0", path = "../../node/cli" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +rand = "0.7.2" +structopt = "=0.3.7" diff --git a/bin/utils/chain-spec-builder/build.rs b/bin/utils/chain-spec-builder/build.rs new file mode 100644 index 0000000000000..513cc234d4363 --- /dev/null +++ b/bin/utils/chain-spec-builder/build.rs @@ -0,0 +1,23 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::env; + +fn main() { + if let Ok(profile) = env::var("PROFILE") { + println!("cargo:rustc-cfg=build_type=\"{}\"", profile); + } +} diff --git a/bin/utils/chain-spec-builder/src/main.rs b/bin/utils/chain-spec-builder/src/main.rs new file mode 100644 index 0000000000000..b1eab2ebe5486 --- /dev/null +++ b/bin/utils/chain-spec-builder/src/main.rs @@ -0,0 +1,273 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{fs, path::{Path, PathBuf}}; + +use ansi_term::Style; +use rand::{Rng, distributions::Alphanumeric, rngs::OsRng}; +use structopt::StructOpt; + +use sc_keystore::{Store as Keystore}; +use node_cli::chain_spec::{self, AccountId}; +use sp_core::{sr25519, crypto::{Public, Ss58Codec}, traits::BareCryptoStore}; + +/// A utility to easily create a testnet chain spec definition with a given set +/// of authorities and endowed accounts and/or generate random accounts. +#[derive(StructOpt)] +#[structopt(rename_all = "kebab-case")] +enum ChainSpecBuilder { + /// Create a new chain spec with the given authorities, endowed and sudo + /// accounts. + New { + /// Authority key seed. + #[structopt(long, short, required = true)] + authority_seeds: Vec, + /// Endowed account address (SS58 format). + #[structopt(long, short)] + endowed_accounts: Vec, + /// Sudo account address (SS58 format). + #[structopt(long, short)] + sudo_account: String, + /// The path where the chain spec should be saved. + #[structopt(long, short, default_value = "./chain_spec.json")] + chain_spec_path: PathBuf, + }, + /// Create a new chain spec with the given number of authorities and endowed + /// accounts. Random keys will be generated as required. + Generate { + /// The number of authorities. + #[structopt(long, short)] + authorities: usize, + /// The number of endowed accounts. + #[structopt(long, short, default_value = "0")] + endowed: usize, + /// The path where the chain spec should be saved. + #[structopt(long, short, default_value = "./chain_spec.json")] + chain_spec_path: PathBuf, + /// Path to use when saving generated keystores for each authority. + /// + /// At this path, a new folder will be created for each authority's + /// keystore named `auth-$i` where `i` is the authority index, i.e. + /// `auth-0`, `auth-1`, etc. + #[structopt(long, short)] + keystore_path: Option, + }, +} + +impl ChainSpecBuilder { + /// Returns the path where the chain spec should be saved. + fn chain_spec_path(&self) -> &Path { + match self { + ChainSpecBuilder::New { chain_spec_path, .. } => + chain_spec_path.as_path(), + ChainSpecBuilder::Generate { chain_spec_path, .. } => + chain_spec_path.as_path(), + } + } +} + +fn genesis_constructor( + authority_seeds: &[String], + endowed_accounts: &[AccountId], + sudo_account: &AccountId, +) -> chain_spec::GenesisConfig { + let authorities = authority_seeds + .iter() + .map(AsRef::as_ref) + .map(chain_spec::get_authority_keys_from_seed) + .collect::>(); + + let enable_println = true; + + chain_spec::testnet_genesis( + authorities, + sudo_account.clone(), + Some(endowed_accounts.to_vec()), + enable_println, + ) +} + +fn generate_chain_spec( + authority_seeds: Vec, + endowed_accounts: Vec, + sudo_account: String, +) -> Result { + let parse_account = |address: &String| { + AccountId::from_string(address) + .map_err(|err| format!("Failed to parse account address: {:?}", err)) + }; + + let endowed_accounts = endowed_accounts + .iter() + .map(parse_account) + .collect::, String>>()?; + + let sudo_account = parse_account(&sudo_account)?; + + let chain_spec = chain_spec::ChainSpec::from_genesis( + "Custom", + "custom", + move || genesis_constructor(&authority_seeds, &endowed_accounts, &sudo_account), + vec![], + None, + None, + None, + Default::default(), + ); + + chain_spec.to_json(false).map_err(|err| err.to_string()) +} + +fn generate_authority_keys_and_store( + seeds: &[String], + keystore_path: &Path, +) -> Result<(), String> { + for (n, seed) in seeds.into_iter().enumerate() { + let keystore = Keystore::open( + keystore_path.join(format!("auth-{}", n)), + None, + ).map_err(|err| err.to_string())?; + + let (_, _, grandpa, babe, im_online, authority_discovery) = + chain_spec::get_authority_keys_from_seed(seed); + + let insert_key = |key_type, public| { + keystore.write().insert_unknown( + key_type, + &format!("//{}", seed), + public, + ).map_err(|_| format!("Failed to insert key: {}", grandpa)) + }; + + insert_key( + sp_core::crypto::key_types::BABE, + babe.as_slice(), + )?; + + insert_key( + sp_core::crypto::key_types::GRANDPA, + grandpa.as_slice(), + )?; + + insert_key( + sp_core::crypto::key_types::IM_ONLINE, + im_online.as_slice(), + )?; + + insert_key( + sp_core::crypto::key_types::AUTHORITY_DISCOVERY, + authority_discovery.as_slice(), + )?; + } + + Ok(()) +} + +fn print_seeds( + authority_seeds: &[String], + endowed_seeds: &[String], + sudo_seed: &str, +) { + let header = Style::new().bold().underline(); + let entry = Style::new().bold(); + + println!("{}", header.paint("Authority seeds")); + + for (n, seed) in authority_seeds.iter().enumerate() { + println!("{} //{}", + entry.paint(format!("auth-{}:", n)), + seed, + ); + } + + println!(); + + if !endowed_seeds.is_empty() { + println!("{}", header.paint("Endowed seeds")); + for (n, seed) in endowed_seeds.iter().enumerate() { + println!("{} //{}", + entry.paint(format!("endowed-{}:", n)), + seed, + ); + } + + println!(); + } + + println!("{}", header.paint("Sudo seed")); + println!("//{}", sudo_seed); +} + +fn main() -> Result<(), String> { + #[cfg(build_type="debug")] + println!( + "The chain spec builder builds a chain specification that includes a Substrate runtime compiled as WASM. To \ + ensure proper functioning of the included runtime compile (or run) the chain spec builder binary in \ + `--release` mode.\n", + ); + + let builder = ChainSpecBuilder::from_args(); + let chain_spec_path = builder.chain_spec_path().to_path_buf(); + + let (authority_seeds, endowed_accounts, sudo_account) = match builder { + ChainSpecBuilder::Generate { authorities, endowed, keystore_path, .. } => { + let authorities = authorities.max(1); + let rand_str = || -> String { + OsRng.sample_iter(&Alphanumeric) + .take(32) + .collect() + }; + + let authority_seeds = (0..authorities).map(|_| rand_str()).collect::>(); + let endowed_seeds = (0..endowed).map(|_| rand_str()).collect::>(); + let sudo_seed = rand_str(); + + print_seeds( + &authority_seeds, + &endowed_seeds, + &sudo_seed, + ); + + if let Some(keystore_path) = keystore_path { + generate_authority_keys_and_store( + &authority_seeds, + &keystore_path, + )?; + } + + let endowed_accounts = endowed_seeds.iter().map(|seed| { + chain_spec::get_account_id_from_seed::(seed) + .to_ss58check() + }).collect(); + + let sudo_account = chain_spec::get_account_id_from_seed::(&sudo_seed) + .to_ss58check(); + + (authority_seeds, endowed_accounts, sudo_account) + }, + ChainSpecBuilder::New { authority_seeds, endowed_accounts, sudo_account, .. } => { + (authority_seeds, endowed_accounts, sudo_account) + }, + }; + + let json = generate_chain_spec( + authority_seeds, + endowed_accounts, + sudo_account, + )?; + + fs::write(chain_spec_path, json).map_err(|err| err.to_string()) +} diff --git a/bin/utils/subkey/Cargo.toml b/bin/utils/subkey/Cargo.toml new file mode 100644 index 0000000000000..b4398d9f8b2f3 --- /dev/null +++ b/bin/utils/subkey/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "subkey" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +futures = "0.1.29" +sp-core = { version = "*", path = "../../../primitives/core" } +node-runtime = { version = "*", path = "../../node/runtime" } +node-primitives = { version = "*", path = "../../node/primitives" } +sp-runtime = { version = "*", path = "../../../primitives/runtime" } +rand = "0.7.2" +clap = "2.33.0" +tiny-bip39 = "0.6.2" +rustc-hex = "2.0.1" +substrate-bip39 = "0.3.1" +hex = "0.4.0" +hex-literal = "0.2.1" +codec = { package = "parity-scale-codec", version = "1.0.0" } +frame-system = { version = "2.0.0", path = "../../../frame/system" } +pallet-balances = { version = "2.0.0", path = "../../../frame/balances" } +pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" } +rpassword = "4.0.1" +itertools = "0.8.2" +derive_more = { version = "0.99.2" } +sc-rpc = { version = "2.0.0", path = "../../../client/rpc" } +jsonrpc-core-client = { version = "14.0.3", features = ["http"] } +hyper = "0.12.35" + +[features] +bench = [] diff --git a/subkey/README.adoc b/bin/utils/subkey/README.adoc similarity index 100% rename from subkey/README.adoc rename to bin/utils/subkey/README.adoc diff --git a/bin/utils/subkey/src/main.rs b/bin/utils/subkey/src/main.rs new file mode 100644 index 0000000000000..c2fd7e28c2548 --- /dev/null +++ b/bin/utils/subkey/src/main.rs @@ -0,0 +1,699 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![cfg_attr(feature = "bench", feature(test))] +#[cfg(feature = "bench")] +extern crate test; + +use bip39::{Language, Mnemonic, MnemonicType}; +use clap::{App, ArgMatches, SubCommand}; +use codec::{Decode, Encode}; +use hex_literal::hex; +use itertools::Itertools; +use node_primitives::{Balance, Hash, Index, AccountId, Signature}; +use node_runtime::{BalancesCall, Call, Runtime, SignedPayload, UncheckedExtrinsic, VERSION}; +use sp_core::{ + crypto::{set_default_ss58_version, Ss58AddressFormat, Ss58Codec}, + ed25519, sr25519, ecdsa, Pair, Public, H256, hexdisplay::HexDisplay, +}; +use sp_runtime::{traits::{IdentifyAccount, Verify}, generic::Era}; +use std::{ + convert::{TryInto, TryFrom}, io::{stdin, Read}, str::FromStr, path::PathBuf, fs, fmt, +}; + +mod rpc; +mod vanity; + +trait Crypto: Sized { + type Pair: Pair; + type Public: Public + Ss58Codec + AsRef<[u8]> + std::hash::Hash; + fn pair_from_suri(suri: &str, password: Option<&str>) -> Self::Pair { + Self::Pair::from_string(suri, password).expect("Invalid phrase") + } + fn ss58_from_pair(pair: &Self::Pair) -> String where + ::Public: PublicT, + { + pair.public().into_runtime().into_account().to_ss58check() + } + fn public_from_pair(pair: &Self::Pair) -> Self::Public { + pair.public() + } + fn print_from_uri( + uri: &str, + password: Option<&str>, + network_override: Option, + ) where + ::Public: PublicT, + { + if let Ok((pair, seed)) = Self::Pair::from_phrase(uri, password) { + let public_key = Self::public_from_pair(&pair); + println!("Secret phrase `{}` is account:\n \ + Secret seed: {}\n \ + Public key (hex): {}\n \ + Account ID: {}\n \ + SS58 Address: {}", + uri, + format_seed::(seed), + format_public_key::(public_key.clone()), + format_account_id::(public_key), + Self::ss58_from_pair(&pair) + ); + } else if let Ok((pair, seed)) = Self::Pair::from_string_with_seed(uri, password) { + let public_key = Self::public_from_pair(&pair); + println!("Secret Key URI `{}` is account:\n \ + Secret seed: {}\n \ + Public key (hex): {}\n \ + Account ID: {}\n \ + SS58 Address: {}", + uri, + if let Some(seed) = seed { format_seed::(seed) } else { "n/a".into() }, + format_public_key::(public_key.clone()), + format_account_id::(public_key), + Self::ss58_from_pair(&pair) + ); + } else if let Ok((public_key, v)) = + ::Public::from_string_with_version(uri) + { + let v = network_override.unwrap_or(v); + println!("Public Key URI `{}` is account:\n \ + Network ID/version: {}\n \ + Public key (hex): {}\n \ + Account ID: {}\n \ + SS58 Address: {}", + uri, + String::from(v), + format_public_key::(public_key.clone()), + format_account_id::(public_key.clone()), + public_key.to_ss58check_with_version(v) + ); + } else { + println!("Invalid phrase/URI given"); + } + } +} + +struct Ed25519; + +impl Crypto for Ed25519 { + type Pair = ed25519::Pair; + type Public = ed25519::Public; + + fn pair_from_suri(suri: &str, password_override: Option<&str>) -> Self::Pair { + ed25519::Pair::from_legacy_string(suri, password_override) + } +} + +struct Sr25519; + +impl Crypto for Sr25519 { + type Pair = sr25519::Pair; + type Public = sr25519::Public; +} + +struct Ecdsa; + +impl Crypto for Ecdsa { + type Pair = ecdsa::Pair; + type Public = ecdsa::Public; +} + +type SignatureOf = <::Pair as Pair>::Signature; +type PublicOf = <::Pair as Pair>::Public; +type SeedOf = <::Pair as Pair>::Seed; +type AccountPublic = ::Signer; + +trait SignatureT: AsRef<[u8]> + AsMut<[u8]> + Default { + /// Converts the signature into a runtime account signature, if possible. If not possible, bombs out. + fn into_runtime(self) -> Signature { + panic!("This cryptography isn't supported for this runtime.") + } +} +trait PublicT: Sized + AsRef<[u8]> + Ss58Codec { + /// Converts the public key into a runtime account public key, if possible. If not possible, bombs out. + fn into_runtime(self) -> AccountPublic { + panic!("This cryptography isn't supported for this runtime.") + } +} + +impl SignatureT for sr25519::Signature { fn into_runtime(self) -> Signature { self.into() } } +impl SignatureT for ed25519::Signature { fn into_runtime(self) -> Signature { self.into() } } +impl SignatureT for ecdsa::Signature { fn into_runtime(self) -> Signature { self.into() } } +impl PublicT for sr25519::Public { fn into_runtime(self) -> AccountPublic { self.into() } } +impl PublicT for ed25519::Public { fn into_runtime(self) -> AccountPublic { self.into() } } +impl PublicT for ecdsa::Public { fn into_runtime(self) -> AccountPublic { self.into() } } + +fn get_usage() -> String { + let networks = Ss58AddressFormat::all().iter().cloned().map(String::from).join("/"); + let default_network = String::from(Ss58AddressFormat::default()); + format!(" + -e, --ed25519 'Use Ed25519/BIP39 cryptography' + -k, --secp256k1 'Use SECP256k1/ECDSA/BIP39 cryptography' + -s, --sr25519 'Use Schnorr/Ristretto x25519/BIP39 cryptography' + [network] -n, --network 'Specify a network. One of {}. Default is {}' + [password] -p, --password 'The password for the key' + --password-interactive 'You will be prompted for the password for the key.' + ", networks, default_network) +} + +fn get_app<'a, 'b>(usage: &'a str) -> App<'a, 'b> { + App::new("subkey") + .author("Parity Team ") + .about("Utility for generating and restoring with Substrate keys") + .version(env!("CARGO_PKG_VERSION")) + .args_from_usage(usage) + .subcommands(vec![ + SubCommand::with_name("generate") + .about("Generate a random account") + .args_from_usage("[words] -w, --words \ + 'The number of words in the phrase to generate. One of 12 \ + (default), 15, 18, 21 and 24.' + "), + SubCommand::with_name("inspect") + .about("Gets a public key and a SS58 address from the provided Secret URI") + .args_from_usage("[uri] 'A Key URI to be inspected. May be a secret seed, \ + secret URI (with derivation paths and password), SS58 or public URI. \ + If the value is a file, the file content is used as URI. \ + If not given, you will be prompted for the URI.' + "), + SubCommand::with_name("sign") + .about("Sign a message, provided on STDIN, with a given (secret) key") + .args_from_usage(" + -h, --hex 'The message on STDIN is hex-encoded data' + 'The secret key URI. \ + If the value is a file, the file content is used as URI. \ + If not given, you will be prompted for the URI.' + "), + SubCommand::with_name("sign-transaction") + .about("Sign transaction from encoded Call. Returns a signed and encoded \ + UncheckedMortalCompactExtrinsic as hex.") + .args_from_usage(" + -c, --call 'The call, hex-encoded.' + -n, --nonce 'The nonce.' + -p, --password 'The password for the key.' + -h, --prior-block-hash 'The prior block hash, hex-encoded.' + -s, --suri 'The secret key URI.' + "), + SubCommand::with_name("transfer") + .about("Author and sign a Node pallet_balances::Transfer transaction with a given (secret) key") + .args_from_usage(" + -g, --genesis 'The genesis hash or a recognised \ + chain identifier (dev, elm, alex).' + 'The signing secret key URI.' + 'The destination account public key URI.' + 'The number of units to transfer.' + 'The signing account's transaction index.' + "), + SubCommand::with_name("vanity") + .about("Generate a seed that provides a vanity address") + .args_from_usage(" + -n, --number 'Number of keys to generate' + 'Desired pattern' + "), + SubCommand::with_name("verify") + .about("Verify a signature for a message, provided on STDIN, with a given \ + (public or secret) key") + .args_from_usage(" + -h, --hex 'The message on STDIN is hex-encoded data' + 'Signature, hex-encoded.' + 'The public or secret key URI. \ + If the value is a file, the file content is used as URI. \ + If not given, you will be prompted for the URI.' + "), + SubCommand::with_name("insert") + .about("Insert a key to the keystore of a node") + .args_from_usage(" + 'The secret key URI. \ + If the value is a file, the file content is used as URI. \ + If not given, you will be prompted for the URI.' + 'Key type, examples: \"gran\", or \"imon\" ' + [node-url] 'Node JSON-RPC endpoint, default \"http:://localhost:9933\"' + "), + ]) +} + +fn main() -> Result<(), Error> { + let usage = get_usage(); + let matches = get_app(&usage).get_matches(); + + if matches.is_present("ed25519") { + return execute::(matches); + } + if matches.is_present("secp256k1") { + return execute::(matches) + } + return execute::(matches) +} + +/// Get `URI` from CLI or prompt the user. +/// +/// `URI` is extracted from `matches` by using `match_name`. +/// +/// If the `URI` given as CLI argument is a file, the file content is taken as `URI`. +/// If no `URI` is given to the CLI, the user is prompted for it. +fn get_uri(match_name: &str, matches: &ArgMatches) -> Result { + let uri = if let Some(uri) = matches.value_of(match_name) { + let file = PathBuf::from(uri); + if file.is_file() { + fs::read_to_string(uri)? + .trim_end() + .into() + } else { + uri.into() + } + } else { + rpassword::read_password_from_tty(Some("URI: "))? + }; + + Ok(uri) +} + +#[derive(derive_more::Display, derive_more::From)] +enum Error { + Static(&'static str), + Io(std::io::Error), + Formatted(String), +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +fn static_err(msg: &'static str) -> Result<(), Error> { + Err(Error::Static(msg)) +} + +fn execute(matches: ArgMatches) -> Result<(), Error> +where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + let password_interactive = matches.is_present("password-interactive"); + let password = matches.value_of("password"); + + let password = if password.is_some() && password_interactive { + return static_err("`--password` given and `--password-interactive` selected!"); + } else if password_interactive { + Some( + rpassword::read_password_from_tty(Some("Key password: "))? + ) + } else { + password.map(Into::into) + }; + let password = password.as_ref().map(String::as_str); + + let maybe_network: Option = match matches.value_of("network").map(|network| { + network + .try_into() + .map_err(|_| Error::Static("Invalid network name. See --help for available networks.")) + }) { + Some(Err(e)) => return Err(e), + Some(Ok(v)) => Some(v), + None => None, + }; + + if let Some(network) = maybe_network { + set_default_ss58_version(network); + } + match matches.subcommand() { + ("generate", Some(matches)) => { + let mnemonic = generate_mnemonic(matches)?; + C::print_from_uri(mnemonic.phrase(), password, maybe_network); + } + ("inspect", Some(matches)) => { + C::print_from_uri(&get_uri("uri", &matches)?, password, maybe_network); + } + ("sign", Some(matches)) => { + let suri = get_uri("suri", &matches)?; + let should_decode = matches.is_present("hex"); + + let message = read_message_from_stdin(should_decode)?; + let signature = do_sign::(&suri, message, password)?; + println!("{}", signature); + } + ("verify", Some(matches)) => { + let uri = get_uri("uri", &matches)?; + let should_decode = matches.is_present("hex"); + + let message = read_message_from_stdin(should_decode)?; + let is_valid_signature = do_verify::(matches, &uri, message)?; + if is_valid_signature { + println!("Signature verifies correctly."); + } else { + return static_err("Signature invalid."); + } + } + ("vanity", Some(matches)) => { + let desired: String = matches + .value_of("pattern") + .map(str::to_string) + .unwrap_or_default(); + let result = vanity::generate_key::(&desired)?; + let formated_seed = format_seed::(result.seed); + C::print_from_uri(&formated_seed, None, maybe_network); + } + ("transfer", Some(matches)) => { + let signer = read_pair::(matches.value_of("from"), password)?; + let index = read_required_parameter::(matches, "index")?; + let genesis_hash = read_genesis_hash(matches)?; + + let to: AccountId = read_account_id(matches.value_of("to")); + let amount = read_required_parameter::(matches, "amount")?; + let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); + + let extrinsic = create_extrinsic::(function, index, signer, genesis_hash); + + print_extrinsic(extrinsic); + } + ("sign-transaction", Some(matches)) => { + let signer = read_pair::(matches.value_of("suri"), password)?; + let index = read_required_parameter::(matches, "nonce")?; + let genesis_hash = read_genesis_hash(matches)?; + + let call = matches.value_of("call").expect("call is required; qed"); + let function: Call = hex::decode(&call) + .ok() + .and_then(|x| Decode::decode(&mut &x[..]).ok()) + .unwrap(); + + let extrinsic = create_extrinsic::(function, index, signer, genesis_hash); + + print_extrinsic(extrinsic); + } + ("insert", Some(matches)) => { + let suri = get_uri("suri", &matches)?; + let pair = read_pair::(Some(&suri), password)?; + let node_url = matches.value_of("node-url").unwrap_or("http://localhost:9933"); + let key_type = matches.value_of("key-type").ok_or(Error::Static("Key type id is required"))?; + + // Just checking + let _key_type_id = sp_core::crypto::KeyTypeId::try_from(key_type) + .map_err(|_| Error::Static("Cannot convert argument to keytype: argument should be 4-character string"))?; + + let rpc = rpc::RpcClient::new(node_url.to_string()); + + rpc.insert_key( + key_type.to_string(), + suri, + sp_core::Bytes(pair.public().as_ref().to_vec()), + ); + } + _ => print_usage(&matches), + } + + Ok(()) +} + +/// Creates a new randomly generated mnemonic phrase. +fn generate_mnemonic(matches: &ArgMatches) -> Result { + let words = match matches.value_of("words") { + Some(words) => { + let num = usize::from_str(words).map_err(|_| Error::Static("Invalid number given for --words"))?; + MnemonicType::for_word_count(num) + .map_err(|_| Error::Static("Invalid number of words given for phrase: must be 12/15/18/21/24"))? + }, + None => MnemonicType::Words12, + }; + Ok(Mnemonic::new(words, Language::English)) +} + +fn do_sign(suri: &str, message: Vec, password: Option<&str>) -> Result +where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + let pair = read_pair::(Some(suri), password)?; + let signature = pair.sign(&message); + Ok(format_signature::(&signature)) +} + +fn do_verify(matches: &ArgMatches, uri: &str, message: Vec) -> Result +where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + + let signature = read_signature::(matches)?; + let pubkey = read_public_key::(Some(uri)); + Ok(<::Pair as Pair>::verify(&signature, &message, &pubkey)) +} + +fn decode_hex>(message: T) -> Result, Error> { + hex::decode(message).map_err(|e| Error::Formatted(format!("Invalid hex ({})", e))) +} + +fn read_message_from_stdin(should_decode: bool) -> Result, Error> { + let mut message = vec![]; + stdin() + .lock() + .read_to_end(&mut message)?; + if should_decode { + message = decode_hex(&message)?; + } + Ok(message) +} + +fn read_required_parameter(matches: &ArgMatches, name: &str) -> Result where + ::Err: std::fmt::Debug, +{ + let str_value = matches + .value_of(name) + .expect("parameter is required; thus it can't be None; qed"); + str::parse::(str_value).map_err(|_| + Error::Formatted(format!("Invalid `{}' parameter; expecting an integer.", name)) + ) +} + +fn read_genesis_hash(matches: &ArgMatches) -> Result { + let genesis_hash: Hash = match matches.value_of("genesis").unwrap_or("alex") { + "elm" => hex!["10c08714a10c7da78f40a60f6f732cf0dba97acfb5e2035445b032386157d5c3"].into(), + "alex" => hex!["dcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b"].into(), + h => Decode::decode(&mut &decode_hex(h)?[..]) + .expect("Invalid genesis hash or unrecognised chain identifier"), + }; + println!( + "Using a genesis hash of {}", + HexDisplay::from(&genesis_hash.as_ref()) + ); + Ok(genesis_hash) +} + +fn read_signature(matches: &ArgMatches) -> Result, Error> +where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + let sig_data = matches + .value_of("sig") + .expect("signature parameter is required; thus it can't be None; qed"); + let mut signature = <::Pair as Pair>::Signature::default(); + let sig_data = decode_hex(sig_data)?; + if sig_data.len() != signature.as_ref().len() { + return Err(Error::Formatted(format!( + "signature has an invalid length. read {} bytes, expected {} bytes", + sig_data.len(), + signature.as_ref().len(), + ))); + } + signature.as_mut().copy_from_slice(&sig_data); + Ok(signature) +} + +fn read_public_key(matched_uri: Option<&str>) -> PublicOf +where + PublicOf: PublicT, +{ + let uri = matched_uri.expect("parameter is required; thus it can't be None; qed"); + let uri = if uri.starts_with("0x") { + &uri[2..] + } else { + uri + }; + if let Ok(pubkey_vec) = hex::decode(uri) { + ::Public::from_slice(pubkey_vec.as_slice()) + } else { + ::Public::from_string(uri) + .ok() + .expect("Invalid URI; expecting either a secret URI or a public URI.") + } +} + +fn read_account_id(matched_uri: Option<&str>) -> AccountId { + let uri = matched_uri.expect("parameter is required; thus it can't be None; qed"); + let uri = if uri.starts_with("0x") { + &uri[2..] + } else { + uri + }; + if let Ok(data_vec) = hex::decode(uri) { + AccountId::try_from(data_vec.as_slice()) + .expect("Invalid hex length for account ID; should be 32 bytes") + } else { + AccountId::from_ss58check(uri).ok() + .expect("Invalid SS58-check address given for account ID.") + } +} + +fn read_pair( + matched_suri: Option<&str>, + password: Option<&str>, +) -> Result<::Pair, Error> where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + let suri = matched_suri.ok_or(Error::Static("parameter is required; thus it can't be None; qed"))?; + Ok(C::pair_from_suri(suri, password)) +} + +fn format_signature(signature: &SignatureOf) -> String { + format!("{}", hex::encode(signature)) +} + +fn format_seed(seed: SeedOf) -> String { + format!("0x{}", HexDisplay::from(&seed.as_ref())) +} + +fn format_public_key(public_key: PublicOf) -> String { + format!("0x{}", HexDisplay::from(&public_key.as_ref())) +} + +fn format_account_id(public_key: PublicOf) -> String where + PublicOf: PublicT, +{ + format!("0x{}", HexDisplay::from(&public_key.into_runtime().into_account().as_ref())) +} + +fn create_extrinsic( + function: Call, + index: Index, + signer: C::Pair, + genesis_hash: H256, +) -> UncheckedExtrinsic where + PublicOf: PublicT, + SignatureOf: SignatureT, +{ + let extra = |i: Index, f: Balance| { + ( + frame_system::CheckVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::Immortal), + frame_system::CheckNonce::::from(i), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(f), + Default::default(), + ) + }; + let raw_payload = SignedPayload::from_raw( + function, + extra(index, 0), + ( + VERSION.spec_version as u32, + genesis_hash, + genesis_hash, + (), + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)).into_runtime(); + let signer = signer.public().into_runtime(); + let (function, extra, _) = raw_payload.deconstruct(); + + UncheckedExtrinsic::new_signed( + function, + signer.into_account().into(), + signature, + extra, + ) +} + +fn print_extrinsic(extrinsic: UncheckedExtrinsic) { + println!("0x{}", hex::encode(&extrinsic.encode())); +} + +fn print_usage(matches: &ArgMatches) { + println!("{}", matches.usage()); +} + +#[cfg(test)] +mod tests { + use super::*; + + fn test_generate_sign_verify() + where + SignatureOf: SignatureT, + PublicOf: PublicT, + { + let usage = get_usage(); + let app = get_app(&usage); + let password = None; + + // Generate public key and seed. + let arg_vec = vec!["subkey", "generate"]; + + let matches = app.clone().get_matches_from(arg_vec); + let matches = matches.subcommand().1.unwrap(); + let mnemonic = generate_mnemonic(matches).expect("generate failed"); + + let (pair, seed) = + <::Pair as Pair>::from_phrase(mnemonic.phrase(), password) + .unwrap(); + let public_key = CryptoType::public_from_pair(&pair); + let public_key = format_public_key::(public_key); + let seed = format_seed::(seed); + let message = "Blah Blah\n".as_bytes().to_vec(); + + let signature = do_sign::(&seed, message.clone(), password).expect("signing failed"); + + // Verify the previous signature. + let arg_vec = vec!["subkey", "verify", &signature[..], &public_key[..]]; + + let matches = get_app(&usage).get_matches_from(arg_vec); + let matches = matches.subcommand().1.unwrap(); + + assert!(do_verify::(matches, &public_key, message).expect("verify failed")); + } + + #[test] + fn generate_sign_verify_should_work_for_ed25519() { + test_generate_sign_verify::(); + } + + #[test] + fn generate_sign_verify_should_work_for_sr25519() { + test_generate_sign_verify::(); + } + + #[test] + fn should_work() { + let s = "0123456789012345678901234567890123456789012345678901234567890123"; + + let d1: Hash = hex::decode(s) + .ok() + .and_then(|x| Decode::decode(&mut &x[..]).ok()) + .unwrap(); + + let d2: Hash = { + let mut gh: [u8; 32] = Default::default(); + gh.copy_from_slice(hex::decode(s).unwrap().as_ref()); + Hash::from(gh) + }; + + assert_eq!(d1, d2); + } +} diff --git a/bin/utils/subkey/src/rpc.rs b/bin/utils/subkey/src/rpc.rs new file mode 100644 index 0000000000000..7b3cde595867b --- /dev/null +++ b/bin/utils/subkey/src/rpc.rs @@ -0,0 +1,49 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Helper to run commands against current node RPC + +use futures::Future; +use hyper::rt; +use node_primitives::Hash; +use sc_rpc::author::AuthorClient; +use jsonrpc_core_client::transports::http; +use sp_core::Bytes; + +pub struct RpcClient { url: String } + +impl RpcClient { + pub fn new(url: String) -> Self { Self { url } } + + pub fn insert_key( + &self, + key_type: String, + suri: String, + public: Bytes, + ) { + let url = self.url.clone(); + + rt::run( + http::connect(&url) + .and_then(|client: AuthorClient| { + client.insert_key(key_type, suri, public).map(|_| ()) + }) + .map_err(|e| { + println!("Error inserting key: {:?}", e); + }) + ); + } +} diff --git a/subkey/src/vanity.rs b/bin/utils/subkey/src/vanity.rs similarity index 96% rename from subkey/src/vanity.rs rename to bin/utils/subkey/src/vanity.rs index 835001a0aa9d0..ff8703a9905ce 100644 --- a/subkey/src/vanity.rs +++ b/bin/utils/subkey/src/vanity.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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 . use super::{PublicOf, PublicT, Crypto}; -use primitives::Pair; +use sp_core::Pair; use rand::{rngs::OsRng, RngCore}; fn good_waypoint(done: u64) -> u64 { @@ -62,7 +62,7 @@ fn calculate_score(_desired: &str, key: &str) -> usize { 0 } -pub(super) fn generate_key(desired: &str) -> Result, &str> where +pub(super) fn generate_key(desired: &str) -> Result, &'static str> where PublicOf: PublicT, { if desired.is_empty() { @@ -110,7 +110,7 @@ pub(super) fn generate_key(desired: &str) -> Result, &str> mod tests { use super::super::Ed25519; use super::*; - use primitives::{crypto::Ss58Codec, Pair}; + use sp_core::{crypto::Ss58Codec, Pair}; #[cfg(feature = "bench")] use test::Bencher; diff --git a/build.rs b/build.rs deleted file mode 100644 index 273700c525c88..0000000000000 --- a/build.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015-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 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/ci/script.sh b/ci/script.sh deleted file mode 100755 index b1b7dd3edf356..0000000000000 --- a/ci/script.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -set -eux - -# Enable warnings about unused extern crates -export RUSTFLAGS=" -W unused-extern-crates" - -# Install rustup and the specified rust toolchain. -curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain=$RUST_TOOLCHAIN -y - -# Load cargo environment. Specifically, put cargo into PATH. -source ~/.cargo/env - -rustc --version -rustup --version -cargo --version - -case $TARGET in - "native") - sudo apt-get -y update - sudo apt-get install -y cmake pkg-config libssl-dev - - cargo test --all --release --locked "$@" - ;; - - "wasm") - # Install prerequisites and build all wasm projects - ./scripts/init.sh - ./scripts/build.sh "$@" - ;; -esac diff --git a/client/Cargo.toml b/client/Cargo.toml new file mode 100644 index 0000000000000..eaddd9f3dcfe6 --- /dev/null +++ b/client/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "sc-client" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sc-block-builder = { version = "2.0.0", path = "block-builder" } +sc-client-api = { version = "2.0.0", path = "api" } +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } +sp-consensus = { version = "0.8", path = "../primitives/consensus/common" } +derive_more = { version = "0.99.2" } +sc-executor = { version = "2.0.0", path = "executor" } +sp-externalities = { version = "2.0.0", path = "../primitives/externalities" } +fnv = { version = "1.0.6" } +futures = { version = "0.3.1", features = ["compat"] } +hash-db = { version = "0.15.2" } +hex-literal = { version = "0.2.1" } +sp-inherents = { version = "2.0.0", path = "../primitives/inherents" } +sp-keyring = { version = "2.0.0", path = "../primitives/keyring" } +kvdb = "0.3.0" +log = { version = "0.4.8" } +parking_lot = { version = "0.9.0" } +sp-core = { version = "2.0.0", path = "../primitives/core" } +sp-std = { version = "2.0.0", path = "../primitives/std" } +sp-version = { version = "2.0.0", path = "../primitives/version" } +sp-api = { version = "2.0.0", path = "../primitives/api" } +sp-runtime = { version = "2.0.0", path = "../primitives/runtime" } +sp-blockchain = { version = "2.0.0", path = "../primitives/blockchain" } +sp-state-machine = { version = "2.0.0", path = "../primitives/state-machine" } +sc-telemetry = { version = "2.0.0", path = "telemetry" } +sp-trie = { version = "2.0.0", path = "../primitives/trie" } +tracing = "0.1.10" + +[dev-dependencies] +env_logger = "0.7.0" +tempfile = "3.1.0" +substrate-test-runtime-client = { version = "2.0.0", path = "../test-utils/runtime/client" } +kvdb-memorydb = "0.3.0" +sp-panic-handler = { version = "2.0.0", path = "../primitives/panic-handler" } diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml new file mode 100644 index 0000000000000..36360a6fb8d20 --- /dev/null +++ b/client/api/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "sc-client-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" } +derive_more = { version = "0.99.2" } +sc-executor = { version = "2.0.0", path = "../executor" } +sp-externalities = { version = "2.0.0", path = "../../primitives/externalities" } +fnv = { version = "1.0.6" } +futures = { version = "0.3.1" } +hash-db = { version = "0.15.2", default-features = false } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +hex-literal = { version = "0.2.1" } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } +kvdb = "0.3.0" +log = { version = "0.4.8" } +parking_lot = { version = "0.9.0" } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-version = { version = "2.0.0", default-features = false, path = "../../primitives/version" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } +sc-telemetry = { version = "2.0.0", path = "../telemetry" } +sp-trie = { version = "2.0.0", path = "../../primitives/trie" } +sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } + +[dev-dependencies] +sp-test-primitives = { version = "2.0.0", path = "../../primitives/test-primitives" } diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs new file mode 100644 index 0000000000000..292031a4cb9de --- /dev/null +++ b/client/api/src/backend.rs @@ -0,0 +1,366 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate Client data backend + +use std::sync::Arc; +use std::collections::HashMap; +use sp_core::ChangesTrieConfiguration; +use sp_core::offchain::OffchainStorage; +use sp_runtime::{generic::BlockId, Justification, Storage}; +use sp_runtime::traits::{Block as BlockT, NumberFor, HasherFor}; +use sp_state_machine::{ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieTransaction}; +use crate::{ + blockchain::{ + Backend as BlockchainBackend, well_known_cache_keys + }, + light::RemoteBlockchain, + UsageInfo, +}; +use sp_blockchain; +use sp_consensus::BlockOrigin; +use parking_lot::RwLock; + +pub use sp_state_machine::Backend as StateBackend; + +/// Extracts the state backend type for the given backend. +pub type StateBackendFor = >::State; + +/// Extracts the transaction for the given state backend. +pub type TransactionForSB = >>::Transaction; + +/// Extracts the transaction for the given backend. +pub type TransactionFor = TransactionForSB, Block>; + +/// In memory array of storage values. +pub type StorageCollection = Vec<(Vec, Option>)>; + +/// In memory arrays of storage values for multiple child tries. +pub type ChildStorageCollection = Vec<(Vec, StorageCollection)>; + +/// Import operation summary. +/// +/// Contains information about the block that just got imported, +/// including storage changes, reorged blocks, etc. +pub struct ImportSummary { + /// Block hash of the imported block. + pub hash: Block::Hash, + /// Import origin. + pub origin: BlockOrigin, + /// Header of the imported block. + pub header: Block::Header, + /// Is this block a new best block. + pub is_new_best: bool, + /// Optional storage changes. + pub storage_changes: Option<(StorageCollection, ChildStorageCollection)>, + /// Blocks that got retracted because of this one got imported. + pub retracted: Vec, +} + +/// Import operation wrapper +pub struct ClientImportOperation> { + /// DB Operation. + pub op: B::BlockImportOperation, + /// Summary of imported block. + pub notify_imported: Option>, + /// A list of hashes of blocks that got finalized. + pub notify_finalized: Vec, +} + +/// State of a new block. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum NewBlockState { + /// Normal block. + Normal, + /// New best block. + Best, + /// Newly finalized block (implicitly best). + Final, +} + +impl NewBlockState { + /// Whether this block is the new best block. + pub fn is_best(self) -> bool { + match self { + NewBlockState::Best | NewBlockState::Final => true, + 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. +pub trait BlockImportOperation { + /// Associated state backend type. + type State: StateBackend>; + + /// Returns pending state. + /// + /// Returns None for backends with locally-unavailable state data. + fn state(&self) -> sp_blockchain::Result>; + + /// Append block data to the transaction. + fn set_block_data( + &mut self, + header: Block::Header, + body: Option>, + justification: Option, + state: NewBlockState, + ) -> sp_blockchain::Result<()>; + + /// Update cached data. + fn update_cache(&mut self, cache: HashMap>); + + /// Inject storage data into the database. + fn update_db_storage( + &mut self, + update: TransactionForSB, + ) -> sp_blockchain::Result<()>; + + /// Inject storage data into the database replacing any existing data. + fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result; + + /// Set storage changes. + fn update_storage( + &mut self, + update: StorageCollection, + child_update: ChildStorageCollection, + ) -> sp_blockchain::Result<()>; + + /// Inject changes trie data into the database. + fn update_changes_trie( + &mut self, + update: ChangesTrieTransaction, NumberFor>, + ) -> sp_blockchain::Result<()>; + + /// Insert auxiliary keys. + /// + /// Values are `None` if should be deleted. + fn insert_aux(&mut self, ops: I) -> sp_blockchain::Result<()> + where I: IntoIterator, Option>)>; + + /// Mark a block as finalized. + fn mark_finalized( + &mut self, + id: BlockId, + justification: Option, + ) -> sp_blockchain::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) -> sp_blockchain::Result<()>; +} + +/// Finalize Facilities +pub trait Finalizer> { + /// Mark all blocks up to given as finalized in operation. + /// + /// If `justification` is provided it is stored with the given finalized + /// block (any other finalized blocks are left unjustified). + /// + /// If the block being finalized is on a different fork from the current + /// best block the finalized block is set as best, this might be slightly + /// inaccurate (i.e. outdated). Usages that require determining an accurate + /// best block should use `SelectChain` instead of the client. + fn apply_finality( + &self, + operation: &mut ClientImportOperation, + id: BlockId, + justification: Option, + notify: bool, + ) -> sp_blockchain::Result<()>; + + + /// Finalize a block. + /// + /// This will implicitly finalize all blocks up to it and + /// fire finality notifications. + /// + /// If the block being finalized is on a different fork from the current + /// best block, the finalized block is set as best. This might be slightly + /// inaccurate (i.e. outdated). Usages that require determining an accurate + /// best block should use `SelectChain` instead of the client. + /// + /// Pass a flag to indicate whether finality notifications should be propagated. + /// This is usually tied to some synchronization state, where we don't send notifications + /// while performing major synchronization work. + fn finalize_block( + &self, + id: BlockId, + justification: Option, + notify: bool, + ) -> sp_blockchain::Result<()>; + +} + +/// Provides access to an auxiliary database. +pub trait AuxStore { + /// Insert auxiliary data into key-value store. + /// + /// Deletions occur after insertions. + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> sp_blockchain::Result<()>; + + /// Query auxiliary data from key-value store. + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>>; +} + +/// Client backend. +/// +/// Manages the data layer. +/// +/// Note on state pruning: while an object from `state_at` is alive, the state +/// should not be pruned. The backend should internally reference-count +/// its state objects. +/// +/// The same applies for live `BlockImportOperation`s: while an import operation building on a +/// parent `P` is alive, the state for `P` should not be pruned. +pub trait Backend: AuxStore + Send + Sync { + /// Associated block insertion operation type. + type BlockImportOperation: BlockImportOperation; + /// Associated blockchain backend type. + type Blockchain: BlockchainBackend; + /// Associated state backend type. + type State: StateBackend> + Send; + /// Changes trie storage. + type ChangesTrieStorage: PrunableStateChangesTrieStorage; + /// Offchain workers local storage. + type OffchainStorage: OffchainStorage; + + /// Begin a new block insertion transaction with given parent block id. + /// + /// When constructing the genesis, this is called with all-zero hash. + fn begin_operation(&self) -> sp_blockchain::Result; + + /// Note an operation to contain state transition. + fn begin_state_operation( + &self, + operation: &mut Self::BlockImportOperation, + block: BlockId, + ) -> sp_blockchain::Result<()>; + + /// Commit block insertion. + fn commit_operation(&self, transaction: Self::BlockImportOperation) -> sp_blockchain::Result<()>; + + /// Finalize block with given Id. + /// + /// This should only be called if the parent of the given block has been finalized. + fn finalize_block( + &self, + block: BlockId, + justification: Option, + ) -> sp_blockchain::Result<()>; + + /// Returns reference to blockchain backend. + fn blockchain(&self) -> &Self::Blockchain; + + /// Returns current usage statistics. + fn usage_info(&self) -> Option; + + /// Returns reference to changes trie storage. + fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage>; + + /// Returns a handle to offchain storage. + fn offchain_storage(&self) -> Option; + + /// Returns true if state for given block is available. + fn have_state_at(&self, hash: &Block::Hash, _number: NumberFor) -> bool { + self.state_at(BlockId::Hash(hash.clone())).is_ok() + } + + /// Returns state backend with post-state of given block. + fn state_at(&self, block: BlockId) -> sp_blockchain::Result; + + /// Destroy state and save any useful data, such as cache. + fn destroy_state(&self, _state: Self::State) -> sp_blockchain::Result<()> { + Ok(()) + } + + /// Attempts to revert the chain by `n` blocks. If `revert_finalized` is set + /// it will attempt to revert past any finalized block, this is unsafe and + /// can potentially leave the node in an inconsistent state. + /// + /// Returns the number of blocks that were successfully reverted. + fn revert( + &self, + n: NumberFor, + revert_finalized: bool, + ) -> sp_blockchain::Result>; + + /// Insert auxiliary data into key-value store. + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> + { + AuxStore::insert_aux(self, insert, delete) + } + /// Query auxiliary data from key-value store. + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { + AuxStore::get_aux(self, key) + } + + /// Gain access to the import lock around this backend. + /// + /// _Note_ Backend isn't expected to acquire the lock by itself ever. Rather + /// the using components should acquire and hold the lock whenever they do + /// something that the import of a block would interfere with, e.g. importing + /// a new block or calculating the best head. + fn get_import_lock(&self) -> &RwLock<()>; +} + +/// Changes trie storage that supports pruning. +pub trait PrunableStateChangesTrieStorage: + StateChangesTrieStorage, NumberFor> +{ + /// Get number block of oldest, non-pruned changes trie. + fn oldest_changes_trie_block( + &self, + config: &ChangesTrieConfiguration, + best_finalized: NumberFor, + ) -> NumberFor; +} + +/// Mark for all Backend implementations, that are making use of state data, stored locally. +pub trait LocalBackend: Backend {} + +/// Mark for all Backend implementations, that are fetching required state data from remote nodes. +pub trait RemoteBackend: Backend { + /// Returns true if the state for given block is available locally. + fn is_local_state_available(&self, block: &BlockId) -> bool; + + /// Returns reference to blockchain backend. + /// + /// Returned backend either resolves blockchain data + /// locally, or prepares request to fetch that data from remote node. + fn remote_blockchain(&self) -> Arc>; +} diff --git a/client/api/src/call_executor.rs b/client/api/src/call_executor.rs new file mode 100644 index 0000000000000..aff38a26aadd6 --- /dev/null +++ b/client/api/src/call_executor.rs @@ -0,0 +1,120 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A method call executor interface. + +use std::{panic::UnwindSafe, result, cell::RefCell}; +use codec::{Encode, Decode}; +use sp_runtime::{ + generic::BlockId, traits::{Block as BlockT, HasherFor}, +}; +use sp_state_machine::{ + OverlayedChanges, ExecutionManager, ExecutionStrategy, StorageProof, +}; +use sc_executor::{RuntimeVersion, NativeVersion}; +use sp_externalities::Extensions; +use sp_core::NativeOrEncoded; + +use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache}; + +/// Method call executor. +pub trait CallExecutor { + /// Externalities error type. + type Error: sp_state_machine::Error; + + /// The backend used by the node. + type Backend: crate::backend::Backend; + + /// Execute a call to a contract on top of state in a block of given hash. + /// + /// No changes are made. + fn call( + &self, + id: &BlockId, + method: &str, + call_data: &[u8], + strategy: ExecutionStrategy, + extensions: Option, + ) -> Result, sp_blockchain::Error>; + + /// Execute a contextual call on top of state in a block of a given hash. + /// + /// No changes are made. + /// Before executing the method, passed header is installed as the current header + /// of the execution context. + fn contextual_call< + 'a, + IB: Fn() -> sp_blockchain::Result<()>, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >( + &self, + initialize_block_fn: IB, + at: &BlockId, + method: &str, + call_data: &[u8], + changes: &RefCell, + storage_transaction_cache: Option<&RefCell< + StorageTransactionCache>::State>, + >>, + initialize_block: InitializeBlock<'a, B>, + execution_manager: ExecutionManager, + native_call: Option, + proof_recorder: &Option>, + extensions: Option, + ) -> sp_blockchain::Result> where ExecutionManager: Clone; + + /// Extract RuntimeVersion of given block + /// + /// No changes are made. + fn runtime_version(&self, id: &BlockId) -> Result; + + /// Execute a call to a contract on top of given state, gathering execution proof. + /// + /// No changes are made. + fn prove_at_state>>( + &self, + mut state: S, + overlay: &mut OverlayedChanges, + method: &str, + call_data: &[u8] + ) -> Result<(Vec, StorageProof), sp_blockchain::Error> { + let trie_state = state.as_trie_backend() + .ok_or_else(|| + Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof) + as Box + )?; + self.prove_at_trie_state(trie_state, overlay, method, call_data) + } + + /// Execute a call to a contract on top of given trie state, gathering execution proof. + /// + /// No changes are made. + fn prove_at_trie_state>>( + &self, + trie_state: &sp_state_machine::TrieBackend>, + overlay: &mut OverlayedChanges, + method: &str, + call_data: &[u8] + ) -> Result<(Vec, StorageProof), sp_blockchain::Error>; + + /// Get runtime version if supported. + fn native_runtime_version(&self) -> Option<&NativeVersion>; +} diff --git a/client/api/src/client.rs b/client/api/src/client.rs new file mode 100644 index 0000000000000..65952ce787bb2 --- /dev/null +++ b/client/api/src/client.rs @@ -0,0 +1,181 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A set of APIs supported by the client along with their primitives. + +use std::{fmt, collections::HashSet}; +use futures::channel::mpsc; +use sp_core::storage::StorageKey; +use sp_runtime::{ + traits::{Block as BlockT, NumberFor}, + generic::BlockId +}; +use sp_consensus::BlockOrigin; + +use crate::blockchain::Info; +use crate::notifications::StorageEventStream; +use sp_blockchain; + +/// Type that implements `futures::Stream` of block import events. +pub type ImportNotifications = mpsc::UnboundedReceiver>; + +/// A stream of block finality notifications. +pub type FinalityNotifications = mpsc::UnboundedReceiver>; + +/// Expected hashes of blocks at given heights. +/// +/// This may be used as chain spec extension to set trusted checkpoints, i.e. +/// the client will refuse to import a block with a different hash at the given +/// height. +pub type ForkBlocks = Option, ::Hash)>>; + +/// Known bad block hashes. +/// +/// This may be used as chain spec extension to filter out known, unwanted forks. +pub type BadBlocks = Option::Hash>>; + +/// Figure out the block type for a given type (for now, just a `Client`). +pub trait BlockOf { + /// The type of the block. + type Type: BlockT; +} + +/// A source of blockchain events. +pub trait BlockchainEvents { + /// Get block import event stream. Not guaranteed to be fired for every + /// imported block. + fn import_notification_stream(&self) -> ImportNotifications; + + /// Get a stream of finality notifications. Not guaranteed to be fired for every + /// finalized block. + fn finality_notification_stream(&self) -> FinalityNotifications; + + /// Get storage changes event stream. + /// + /// Passing `None` as `filter_keys` subscribes to all storage changes. + fn storage_changes_notification_stream( + &self, + filter_keys: Option<&[StorageKey]>, + child_filter_keys: Option<&[(StorageKey, Option>)]>, + ) -> sp_blockchain::Result>; +} + +/// Fetch block body by ID. +pub trait BlockBody { + /// Get block body by ID. Returns `None` if the body is not stored. + fn block_body(&self, + id: &BlockId + ) -> sp_blockchain::Result::Extrinsic>>>; +} + +/// Provide a list of potential uncle headers for a given block. +pub trait ProvideUncles { + /// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors. + fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) + -> sp_blockchain::Result>; +} + +/// Client info +#[derive(Debug)] +pub struct ClientInfo { + /// Best block hash. + pub chain: Info, + /// Usage info, if backend supports this. + pub usage: Option, +} + +/// Memory statistics for client instance. +#[derive(Default, Clone, Debug)] +pub struct MemoryInfo { + /// Size of state cache. + pub state_cache: usize, + /// Size of backend database cache. + pub database_cache: usize, +} + +/// I/O statistics for client instance. +#[derive(Default, Clone, Debug)] +pub struct IoInfo { + /// Number of transactions. + pub transactions: u64, + /// Total bytes read from disk. + pub bytes_read: u64, + /// Total bytes written to disk. + pub bytes_written: u64, + /// Total key writes to disk. + pub writes: u64, + /// Total key reads from disk. + pub reads: u64, + /// Average size of the transaction. + pub average_transaction_size: u64, + /// State reads (keys) + pub state_reads: u64, + /// State reads (keys) from cache. + pub state_reads_cache: u64, +} + +/// Usage statistics for running client instance. +/// +/// Returning backend determines the scope of these stats, +/// but usually it is either from service start or from previous +/// gathering of the statistics. +#[derive(Default, Clone, Debug)] +pub struct UsageInfo { + /// Memory statistics. + pub memory: MemoryInfo, + /// I/O statistics. + pub io: IoInfo, +} + +impl fmt::Display for UsageInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, + "caches: ({} state, {} db overlay), i/o: ({} tx, {} write, {} read, {} avg tx, {}/{} key cache reads/total)", + self.memory.state_cache, + self.memory.database_cache, + self.io.transactions, + self.io.bytes_written, + self.io.bytes_read, + self.io.average_transaction_size, + self.io.state_reads_cache, + self.io.state_reads, + ) + } +} + +/// Summary of an imported block +#[derive(Clone, Debug)] +pub struct BlockImportNotification { + /// Imported block header hash. + pub hash: Block::Hash, + /// Imported block origin. + pub origin: BlockOrigin, + /// Imported block header. + pub header: Block::Header, + /// Is this the new best block. + pub is_new_best: bool, + /// List of retracted blocks ordered by block number. + pub retracted: Vec, +} + +/// Summary of a finalized block. +#[derive(Clone, Debug)] +pub struct FinalityNotification { + /// Imported block header hash. + pub hash: Block::Hash, + /// Imported block header. + pub header: Block::Header, +} diff --git a/client/api/src/execution_extensions.rs b/client/api/src/execution_extensions.rs new file mode 100644 index 0000000000000..1a986a23a47dc --- /dev/null +++ b/client/api/src/execution_extensions.rs @@ -0,0 +1,205 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Execution extensions for runtime calls. +//! +//! This module is responsible for defining the execution +//! strategy for the runtime calls and provide the right `Externalities` +//! extensions to support APIs for particular execution context & capabilities. + +use std::sync::{Weak, Arc}; +use codec::Decode; +use sp_core::{ + ExecutionContext, + offchain::{self, OffchainExt, TransactionPoolExt}, + traits::{BareCryptoStorePtr, KeystoreExt}, +}; +use sp_runtime::{ + generic::BlockId, + traits, +}; +use sp_state_machine::{ExecutionStrategy, ExecutionManager, DefaultHandler}; +use sp_externalities::Extensions; +use parking_lot::RwLock; + +/// 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 for offchain workers. + pub offchain_worker: 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, + offchain_worker: ExecutionStrategy::NativeWhenPossible, + other: ExecutionStrategy::NativeElseWasm, + } + } +} + +/// Generate the starting set of ExternalitiesExtensions based upon the given capabilities +pub trait ExtensionsFactory: Send + Sync { + /// Make `Extensions` for given Capapbilities + fn extensions_for(&self, capabilities: offchain::Capabilities) -> Extensions; +} + +impl ExtensionsFactory for () { + fn extensions_for(&self, _capabilities: offchain::Capabilities) -> Extensions { + Extensions::new() + } +} + +/// A producer of execution extensions for offchain calls. +/// +/// This crate aggregates extensions available for the offchain calls +/// and is responsbile to produce a right `Extensions` object +/// for each call, based on required `Capabilities`. +pub struct ExecutionExtensions { + strategies: ExecutionStrategies, + keystore: Option, + // FIXME: these two are only RwLock because of https://github.com/paritytech/substrate/issues/4587 + // remove when fixed. + transaction_pool: RwLock>>>, + extensions_factory: RwLock>, +} + +impl Default for ExecutionExtensions { + fn default() -> Self { + Self { + strategies: Default::default(), + keystore: None, + transaction_pool: RwLock::new(None), + extensions_factory: RwLock::new(Box::new(())), + } + } +} + +impl ExecutionExtensions { + /// Create new `ExecutionExtensions` given a `keystore` and `ExecutionStrategies`. + pub fn new( + strategies: ExecutionStrategies, + keystore: Option, + ) -> Self { + let transaction_pool = RwLock::new(None); + let extensions_factory = Box::new(()); + Self { strategies, keystore, extensions_factory: RwLock::new(extensions_factory), transaction_pool } + } + + /// Get a reference to the execution strategies. + pub fn strategies(&self) -> &ExecutionStrategies { + &self.strategies + } + + /// Set the new extensions_factory + pub fn set_extensions_factory(&self, maker: Box) { + *self.extensions_factory.write() = maker; + } + + /// Register transaction pool extension. + /// + /// To break retain cycle between `Client` and `TransactionPool` we require this + /// extension to be a `Weak` reference. + /// That's also the reason why it's being registered lazily instead of + /// during initialisation. + pub fn register_transaction_pool(&self, pool: Weak>) { + *self.transaction_pool.write() = Some(pool); + } + + /// Create `ExecutionManager` and `Extensions` for given offchain call. + /// + /// Based on the execution context and capabilities it produces + /// the right manager and extensions object to support desired set of APIs. + pub fn manager_and_extensions( + &self, + at: &BlockId, + context: ExecutionContext, + ) -> ( + ExecutionManager>, + Extensions, + ) { + let manager = match context { + ExecutionContext::BlockConstruction => + self.strategies.block_construction.get_manager(), + ExecutionContext::Syncing => + self.strategies.syncing.get_manager(), + ExecutionContext::Importing => + self.strategies.importing.get_manager(), + ExecutionContext::OffchainCall(Some((_, capabilities))) if capabilities.has_all() => + self.strategies.offchain_worker.get_manager(), + ExecutionContext::OffchainCall(_) => + self.strategies.other.get_manager(), + }; + + let capabilities = context.capabilities(); + + let mut extensions = self.extensions_factory.read().extensions_for(capabilities); + + if capabilities.has(offchain::Capability::Keystore) { + if let Some(keystore) = self.keystore.as_ref() { + extensions.register(KeystoreExt(keystore.clone())); + } + } + + if capabilities.has(offchain::Capability::TransactionPool) { + if let Some(pool) = self.transaction_pool.read().as_ref().and_then(|x| x.upgrade()) { + extensions.register(TransactionPoolExt(Box::new(TransactionPoolAdapter { + at: *at, + pool, + }) as _)); + } + } + + if let ExecutionContext::OffchainCall(Some(ext)) = context { + extensions.register( + OffchainExt::new(offchain::LimitedExternalities::new(capabilities, ext.0)) + ) + } + + (manager, extensions) + } +} + +/// A wrapper type to pass `BlockId` to the actual transaction pool. +struct TransactionPoolAdapter { + at: BlockId, + pool: Arc>, +} + +impl offchain::TransactionPool for TransactionPoolAdapter { + fn submit_transaction(&mut self, data: Vec) -> Result<(), ()> { + let xt = match Block::Extrinsic::decode(&mut &*data) { + Ok(xt) => xt, + Err(e) => { + log::warn!("Unable to decode extrinsic: {:?}: {}", data, e.what()); + return Err(()); + }, + }; + + self.pool.submit_at(&self.at, xt) + } +} diff --git a/client/api/src/lib.rs b/client/api/src/lib.rs new file mode 100644 index 0000000000000..69d0c94ac2b8b --- /dev/null +++ b/client/api/src/lib.rs @@ -0,0 +1,77 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate client interfaces. +#![warn(missing_docs)] + +pub mod backend; +pub mod call_executor; +pub mod client; +pub mod execution_extensions; +pub mod light; +pub mod notifications; + +pub use sp_blockchain as blockchain; +pub use backend::*; +pub use notifications::*; +pub use call_executor::*; +pub use client::*; +pub use light::*; +pub use notifications::*; + +pub use sp_state_machine::{StorageProof, ExecutionStrategy}; + +/// Utility methods for the client. +pub mod utils { + use sp_blockchain::{HeaderBackend, HeaderMetadata, Error}; + use sp_runtime::traits::Block as BlockT; + use std::borrow::Borrow; + + /// Returns a function for checking block ancestry, the returned function will + /// return `true` if the given hash (second parameter) is a descendent of the + /// 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, Block: BlockT, T>( + client: &'a T, + current: Option<(Block::Hash, Block::Hash)>, + ) -> impl Fn(&Block::Hash, &Block::Hash) -> Result + 'a + where T: HeaderBackend + HeaderMetadata, + { + move |base, hash| { + if base == hash { return Ok(false); } + + let current = current.as_ref().map(|(c, p)| (c.borrow(), p.borrow())); + + let mut hash = hash; + if let Some((current_hash, current_parent_hash)) = current { + if base == current_hash { return Ok(false); } + if hash == current_hash { + if base == current_parent_hash { + return Ok(true); + } else { + hash = current_parent_hash; + } + } + } + + let ancestor = sp_blockchain::lowest_common_ancestor(client, *hash, *base)?; + + Ok(ancestor.hash == *base) + } + } +} diff --git a/client/api/src/light.rs b/client/api/src/light.rs new file mode 100644 index 0000000000000..fb3aeeab7c733 --- /dev/null +++ b/client/api/src/light.rs @@ -0,0 +1,354 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate light client interfaces + +use std::sync::Arc; +use std::collections::{BTreeMap, HashMap}; +use std::future::Future; + +use sp_runtime::{ + traits::{ + Block as BlockT, Header as HeaderT, NumberFor, + }, + generic::BlockId +}; +use sp_core::ChangesTrieConfiguration; +use sp_state_machine::StorageProof; +use sp_blockchain::{ + HeaderMetadata, well_known_cache_keys, HeaderBackend, Cache as BlockchainCache, + Error as ClientError, Result as ClientResult, +}; +use crate::{backend::{AuxStore, NewBlockState}, UsageInfo}; + +/// Remote call request. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct RemoteCallRequest { + /// Call at state of given block. + pub block: Header::Hash, + /// Header of block at which call is performed. + pub header: Header, + /// Method to call. + pub method: String, + /// Call data. + pub call_data: Vec, + /// Number of times to retry request. None means that default RETRY_COUNT is used. + pub retry_count: Option, +} + +/// Remote canonical header request. +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +pub struct RemoteHeaderRequest { + /// The root of CHT this block is included in. + pub cht_root: Header::Hash, + /// Number of the header to query. + pub block: Header::Number, + /// Number of times to retry request. None means that default RETRY_COUNT is used. + pub retry_count: Option, +} + +/// Remote storage read request. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct RemoteReadRequest { + /// Read at state of given block. + pub block: Header::Hash, + /// Header of block at which read is performed. + pub header: Header, + /// Storage key to read. + pub keys: Vec>, + /// Number of times to retry request. None means that default RETRY_COUNT is used. + pub retry_count: Option, +} + +/// Remote storage read child request. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct RemoteReadChildRequest { + /// Read at state of given block. + pub block: Header::Hash, + /// Header of block at which read is performed. + pub header: Header, + /// Storage key for child. + pub storage_key: Vec, + /// Child trie source information. + pub child_info: Vec, + /// Child type, its required to resolve `child_info` + /// content and choose child implementation. + pub child_type: u32, + /// Child storage key to read. + pub keys: Vec>, + /// Number of times to retry request. None means that default RETRY_COUNT is used. + pub retry_count: Option, +} + +/// Remote key changes read request. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct RemoteChangesRequest { + /// Changes trie configuration. + pub changes_trie_config: ChangesTrieConfiguration, + /// Query changes from range of blocks, starting (and including) with this hash... + pub first_block: (Header::Number, Header::Hash), + /// ...ending (and including) with this hash. Should come after first_block and + /// be the part of the same fork. + pub last_block: (Header::Number, Header::Hash), + /// Only use digests from blocks up to this hash. Should be last_block OR come + /// after this block and be the part of the same fork. + pub max_block: (Header::Number, Header::Hash), + /// Known changes trie roots for the range of blocks [tries_roots.0..max_block]. + /// Proofs for roots of ascendants of tries_roots.0 are provided by the remote node. + pub tries_roots: (Header::Number, Header::Hash, Vec), + /// Optional Child Storage key to read. + pub storage_key: Option>, + /// Storage key to read. + pub key: Vec, + /// Number of times to retry request. None means that default RETRY_COUNT is used. + pub retry_count: Option, +} + +/// Key changes read proof. +#[derive(Debug, PartialEq, Eq)] +pub struct ChangesProof { + /// Max block that has been used in changes query. + pub max_block: Header::Number, + /// All touched nodes of all changes tries. + pub proof: Vec>, + /// All changes tries roots that have been touched AND are missing from + /// the requester' node. It is a map of block number => changes trie root. + pub roots: BTreeMap, + /// The proofs for all changes tries roots that have been touched AND are + /// missing from the requester' node. It is a map of CHT number => proof. + pub roots_proof: StorageProof, +} + +/// Remote block body request +#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] +pub struct RemoteBodyRequest { + /// Header of the requested block body + pub header: Header, + /// Number of times to retry request. None means that default RETRY_COUNT is used. + pub retry_count: Option, +} + +/// Light client data fetcher. Implementations of this trait must check if remote data +/// is correct (see FetchedDataChecker) and return already checked data. +pub trait Fetcher: Send + Sync { + /// Remote header future. + type RemoteHeaderResult: Future> + Unpin + Send + 'static; + /// Remote storage read future. + type RemoteReadResult: Future, Option>>, + ClientError, + >> + Unpin + Send + 'static; + /// Remote call result future. + type RemoteCallResult: Future, + ClientError, + >> + Unpin + Send + 'static; + /// Remote changes result future. + type RemoteChangesResult: Future, u32)>, + ClientError, + >> + Unpin + Send + 'static; + /// Remote block body result future. + type RemoteBodyResult: Future, + ClientError, + >> + Unpin + Send + 'static; + + /// Fetch remote header. + fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult; + /// Fetch remote storage value. + fn remote_read( + &self, + request: RemoteReadRequest + ) -> Self::RemoteReadResult; + /// Fetch remote storage child value. + fn remote_read_child( + &self, + request: RemoteReadChildRequest + ) -> Self::RemoteReadResult; + /// Fetch remote call result. + fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult; + /// Fetch remote changes ((block number, extrinsic index)) where given key has been changed + /// at a given blocks range. + fn remote_changes(&self, request: RemoteChangesRequest) -> Self::RemoteChangesResult; + /// Fetch remote block body + fn remote_body(&self, request: RemoteBodyRequest) -> Self::RemoteBodyResult; +} + +/// Light client remote data checker. +/// +/// Implementations of this trait should not use any prunable blockchain data +/// except that is passed to its methods. +pub trait FetchChecker: Send + Sync { + /// Check remote header proof. + fn check_header_proof( + &self, + request: &RemoteHeaderRequest, + header: Option, + remote_proof: StorageProof, + ) -> ClientResult; + /// Check remote storage read proof. + fn check_read_proof( + &self, + request: &RemoteReadRequest, + remote_proof: StorageProof, + ) -> ClientResult, Option>>>; + /// Check remote storage read proof. + fn check_read_child_proof( + &self, + request: &RemoteReadChildRequest, + remote_proof: StorageProof, + ) -> ClientResult, Option>>>; + /// Check remote method execution proof. + fn check_execution_proof( + &self, + request: &RemoteCallRequest, + remote_proof: StorageProof, + ) -> ClientResult>; + /// Check remote changes query proof. + fn check_changes_proof( + &self, + request: &RemoteChangesRequest, + proof: ChangesProof + ) -> ClientResult, u32)>>; + /// Check remote body proof. + fn check_body_proof( + &self, + request: &RemoteBodyRequest, + body: Vec + ) -> ClientResult>; +} + + +/// Light client blockchain storage. +pub trait Storage: AuxStore + HeaderBackend + HeaderMetadata { + /// Store new header. Should refuse to revert any finalized blocks. + /// + /// Takes new authorities, the leaf state of the new block, and + /// any auxiliary storage updates to place in the same operation. + fn import_header( + &self, + header: Block::Header, + cache: HashMap>, + 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<()>; + + /// Get last finalized header. + fn last_finalized(&self) -> ClientResult; + + /// Get headers CHT root for given block. Returns None if the block is not pruned (not a part of any CHT). + fn header_cht_root( + &self, + cht_size: NumberFor, + block: NumberFor, + ) -> ClientResult>; + + /// Get changes trie CHT root for given block. Returns None if the block is not pruned (not a part of any CHT). + fn changes_trie_cht_root( + &self, + cht_size: NumberFor, + block: NumberFor, + ) -> ClientResult>; + + /// Get storage cache. + fn cache(&self) -> Option>>; + + /// Get storage usage statistics. + fn usage_info(&self) -> Option; +} + +/// Remote header. +#[derive(Debug)] +pub enum LocalOrRemote { + /// When data is available locally, it is returned. + Local(Data), + /// When data is unavailable locally, the request to fetch it from remote node is returned. + Remote(Request), + /// When data is unknown. + Unknown, +} + +/// Futures-based blockchain backend that either resolves blockchain data +/// locally, or fetches required data from remote node. +pub trait RemoteBlockchain: Send + Sync { + /// Get block header. + fn header(&self, id: BlockId) -> ClientResult, + >>; +} + + + +#[cfg(test)] +pub mod tests { + use futures::future::Ready; + use parking_lot::Mutex; + use sp_blockchain::Error as ClientError; + use sp_test_primitives::{Block, Header, Extrinsic}; + use super::*; + + pub type OkCallFetcher = Mutex>; + + fn not_implemented_in_tests() -> Ready> + where + E: std::convert::From<&'static str>, + { + futures::future::ready(Err("Not implemented on test node".into())) + } + + impl Fetcher for OkCallFetcher { + type RemoteHeaderResult = Ready>; + type RemoteReadResult = Ready, Option>>, ClientError>>; + type RemoteCallResult = Ready, ClientError>>; + type RemoteChangesResult = Ready, u32)>, ClientError>>; + type RemoteBodyResult = Ready, ClientError>>; + + fn remote_header(&self, _request: RemoteHeaderRequest

) -> Self::RemoteHeaderResult { + not_implemented_in_tests() + } + + fn remote_read(&self, _request: RemoteReadRequest
) -> Self::RemoteReadResult { + not_implemented_in_tests() + } + + fn remote_read_child(&self, _request: RemoteReadChildRequest
) -> Self::RemoteReadResult { + not_implemented_in_tests() + } + + fn remote_call(&self, _request: RemoteCallRequest
) -> Self::RemoteCallResult { + futures::future::ready(Ok((*self.lock()).clone())) + } + + fn remote_changes(&self, _request: RemoteChangesRequest
) -> Self::RemoteChangesResult { + not_implemented_in_tests() + } + + fn remote_body(&self, _request: RemoteBodyRequest
) -> Self::RemoteBodyResult { + not_implemented_in_tests() + } + } +} diff --git a/core/client/src/notifications.rs b/client/api/src/notifications.rs similarity index 94% rename from core/client/src/notifications.rs rename to client/api/src/notifications.rs index 37f90dcc0ba64..13bf06396d163 100644 --- a/core/client/src/notifications.rs +++ b/client/api/src/notifications.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,9 +22,9 @@ use std::{ }; use fnv::{FnvHashSet, FnvHashMap}; -use futures03::channel::mpsc; -use primitives::storage::{StorageKey, StorageData}; -use sr_primitives::traits::Block as BlockT; +use futures::channel::mpsc; +use sp_core::storage::{StorageKey, StorageData}; +use sp_runtime::traits::Block as BlockT; /// Storage change set #[derive(Debug)] @@ -307,7 +307,7 @@ impl StorageNotifications { #[cfg(test)] mod tests { - use sr_primitives::testing::{H256 as Hash, Block as RawBlock, ExtrinsicWrapper}; + use sp_runtime::testing::{H256 as Hash, Block as RawBlock, ExtrinsicWrapper}; use super::*; use std::iter::{empty, Empty}; @@ -347,7 +347,7 @@ mod tests { // given let mut notifications = StorageNotifications::::default(); let child_filter = [(StorageKey(vec![4]), None)]; - let mut recv = futures03::executor::block_on_stream( + let mut recv = futures::executor::block_on_stream( notifications.listen(None, Some(&child_filter[..])) ); @@ -382,13 +382,13 @@ mod tests { // given let mut notifications = StorageNotifications::::default(); let child_filter = [(StorageKey(vec![4]), Some(vec![StorageKey(vec![5])]))]; - let mut recv1 = futures03::executor::block_on_stream( + let mut recv1 = futures::executor::block_on_stream( notifications.listen(Some(&[StorageKey(vec![1])]), None) ); - let mut recv2 = futures03::executor::block_on_stream( + let mut recv2 = futures::executor::block_on_stream( notifications.listen(Some(&[StorageKey(vec![2])]), None) ); - let mut recv3 = futures03::executor::block_on_stream( + let mut recv3 = futures::executor::block_on_stream( notifications.listen(Some(&[]), Some(&child_filter)) ); @@ -429,16 +429,16 @@ mod tests { let mut notifications = StorageNotifications::::default(); { let child_filter = [(StorageKey(vec![4]), Some(vec![StorageKey(vec![5])]))]; - let _recv1 = futures03::executor::block_on_stream( + let _recv1 = futures::executor::block_on_stream( notifications.listen(Some(&[StorageKey(vec![1])]), None) ); - let _recv2 = futures03::executor::block_on_stream( + let _recv2 = futures::executor::block_on_stream( notifications.listen(Some(&[StorageKey(vec![2])]), None) ); - let _recv3 = futures03::executor::block_on_stream( + let _recv3 = futures::executor::block_on_stream( notifications.listen(None, None) ); - let _recv4 = futures03::executor::block_on_stream( + let _recv4 = futures::executor::block_on_stream( notifications.listen(None, Some(&child_filter)) ); assert_eq!(notifications.listeners.len(), 2); @@ -465,7 +465,7 @@ mod tests { // given let mut recv = { let mut notifications = StorageNotifications::::default(); - let recv = futures03::executor::block_on_stream(notifications.listen(None, None)); + let recv = futures::executor::block_on_stream(notifications.listen(None, None)); // when let changeset = vec![]; diff --git a/client/authority-discovery/Cargo.toml b/client/authority-discovery/Cargo.toml new file mode 100644 index 0000000000000..767be822d7858 --- /dev/null +++ b/client/authority-discovery/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "sc-authority-discovery" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" + +[build-dependencies] +prost-build = "0.5.0" + +[dependencies] +bytes = "0.4.12" +codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" } +derive_more = "0.99.2" +futures = "0.3.1" +futures-timer = "2.0" +libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["secp256k1", "libp2p-websocket"] } +log = "0.4.8" +prost = "0.5.0" +rand = "0.7.2" +sc-client-api = { version = "2.0.0", path = "../api" } +sc-keystore = { version = "2.0.0", path = "../keystore" } +sc-network = { version = "0.8", path = "../network" } +serde_json = "1.0.41" +sp-authority-discovery = { version = "2.0.0", path = "../../primitives/authority-discovery" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } + +[dev-dependencies] +env_logger = "0.7.0" +quickcheck = "0.9.0" +sc-peerset = { version = "2.0.0", path = "../peerset" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client"} diff --git a/core/authority-discovery/build.rs b/client/authority-discovery/build.rs similarity index 100% rename from core/authority-discovery/build.rs rename to client/authority-discovery/build.rs diff --git a/client/authority-discovery/src/addr_cache.rs b/client/authority-discovery/src/addr_cache.rs new file mode 100644 index 0000000000000..96f589c5d3c02 --- /dev/null +++ b/client/authority-discovery/src/addr_cache.rs @@ -0,0 +1,200 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use rand::{rngs::StdRng, seq::SliceRandom, Rng, SeedableRng}; +use std::{ + clone::Clone, + cmp::{Eq, Ord, PartialEq}, + collections::BTreeMap, + convert::AsRef, + hash::Hash, +}; + +/// The maximum number of authority connections initialized through the authority discovery module. +/// +/// In other words the maximum size of the `authority` peer set priority group. +const MAX_NUM_AUTHORITY_CONN: usize = 10; + +/// Cache of Multiaddresses of authority nodes or their sentry nodes. +// +// The network peerset interface for priority groups lets us only set an entire group, but we +// retrieve the addresses of other authorities one by one from the network. To use the peerset +// interface we need to cache the addresses and always overwrite the entire peerset priority +// group. To ensure this map doesn't grow indefinitely `purge_old_authorities_from_cache` +// function is called each time we add a new entry. +pub(super) struct AddrCache { + cache: BTreeMap>, + + /// Random number to seed address selection RNG. + /// + /// A node should only try to connect to a subset of all authorities. To choose this subset one + /// uses randomness. The choice should differ between nodes to prevent hot spots, but not within + /// each node between each update to prevent connection churn. Thus before each selection we + /// seed an RNG with the same seed. + rand_addr_selection_seed: u64, +} + +impl AddrCache +where + Id: Clone + Eq + Hash + Ord, + Addr: Clone + PartialEq + AsRef<[u8]>, +{ + pub fn new() -> Self { + AddrCache { + cache: BTreeMap::new(), + rand_addr_selection_seed: rand::thread_rng().gen(), + } + } + + pub fn insert(&mut self, id: Id, mut addresses: Vec) { + if addresses.is_empty() { + return; + } + + addresses.sort_unstable_by(|a, b| a.as_ref().cmp(b.as_ref())); + self.cache.insert(id, addresses); + } + + // Each node should connect to a subset of all authorities. In order to prevent hot spots, this + // selection is based on randomness. Selecting randomly each time we alter the address cache + // would result in connection churn. To reduce this churn a node generates a seed on startup and + // uses this seed for a new rng on each update. (One could as well use ones peer id as a seed. + // Given that the peer id is publicly known, it would make this process predictable by others, + // which might be used as an attack.) + pub fn get_subset(&self) -> Vec { + let mut rng = StdRng::seed_from_u64(self.rand_addr_selection_seed); + + let mut addresses = self + .cache + .iter() + .map(|(_peer_id, addresses)| { + addresses + .choose(&mut rng) + .expect("an empty address vector is never inserted into the cache") + }) + .cloned() + .collect::>(); + + addresses.dedup(); + addresses.sort_unstable_by(|a, b| a.as_ref().cmp(b.as_ref())); + + addresses + .choose_multiple(&mut rng, MAX_NUM_AUTHORITY_CONN) + .cloned() + .collect() + } + + pub fn retain_ids(&mut self, ids: &Vec) { + let to_remove = self + .cache + .iter() + .filter(|(id, _addresses)| !ids.contains(id)) + .map(|entry| entry.0) + .cloned() + .collect::>(); + + for key in to_remove { + self.cache.remove(&key); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use quickcheck::{QuickCheck, TestResult}; + + #[test] + fn returns_addresses_of_same_authorities_on_repeated_calls() { + fn property(input: Vec<(u32, Vec)>) -> TestResult { + // Expect less than 1000 authorities. + if input.len() > 1000 { + return TestResult::discard(); + } + + // Expect less than 100 addresses per authority. + for i in &input { + if i.1.len() > 100 { + return TestResult::discard(); + } + } + + let mut c = AddrCache::new(); + + for (id, addresses) in input { + c.insert(id, addresses); + } + + let result = c.get_subset(); + assert!(result.len() <= MAX_NUM_AUTHORITY_CONN); + + for _ in 1..100 { + assert_eq!(c.get_subset(), result); + } + + TestResult::passed() + } + + QuickCheck::new() + .max_tests(10) + .quickcheck(property as fn(Vec<(u32, Vec)>) -> TestResult) + } + + #[test] + fn returns_same_addresses_of_first_authority_when_second_authority_changes() { + let mut c = AddrCache::new(); + + // Insert addresses of first authority. + let addresses = (1..100) + .map(|i| format!("{:?}", i)) + .collect::>(); + c.insert(1, addresses); + let first_subset = c.get_subset(); + assert_eq!(1, first_subset.len()); + + // Insert address of second authority. + c.insert(2, vec!["a".to_string()]); + let second_subset = c.get_subset(); + assert_eq!(2, second_subset.len()); + + // Expect same address of first authority. + assert!(second_subset.contains(&first_subset[0])); + + // Alter address of second authority. + c.insert(2, vec!["b".to_string()]); + let second_subset = c.get_subset(); + assert_eq!(2, second_subset.len()); + + // Expect same address of first authority. + assert!(second_subset.contains(&first_subset[0])); + } + + #[test] + fn retains_only_entries_of_provided_ids() { + let mut cache = AddrCache::new(); + + cache.insert(1, vec![vec![10]]); + cache.insert(2, vec![vec![20]]); + cache.insert(3, vec![vec![30]]); + + cache.retain_ids(&vec![1, 3]); + + let mut subset = cache.get_subset(); + subset.sort(); + + assert_eq!(vec![vec![10], vec![30]], subset); + } +} diff --git a/client/authority-discovery/src/error.rs b/client/authority-discovery/src/error.rs new file mode 100644 index 0000000000000..d62281c0c2829 --- /dev/null +++ b/client/authority-discovery/src/error.rs @@ -0,0 +1,49 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Authority discovery errors. + +/// AuthorityDiscovery Result. +pub type Result = std::result::Result; + +/// Error type for the authority discovery module. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Received dht value found event with records with different keys. + ReceivingDhtValueFoundEventWithDifferentKeys, + /// Received dht value found event with no records. + ReceivingDhtValueFoundEventWithNoRecords, + /// Failed to verify a dht payload with the given signature. + VerifyingDhtPayload, + /// Failed to hash the authority id to be used as a dht key. + HashingAuthorityId(libp2p::core::multiaddr::multihash::EncodeError), + /// Failed calling into the Substrate runtime. + CallingRuntime(sp_blockchain::Error), + /// From the Dht we only get the hashed authority id. In order to retrieve the actual authority id and to ensure it + /// is actually an authority, we match the hash against the hash of the authority id of all other authorities. This + /// error is the result of the above failing. + MatchingHashedAuthorityIdWithAuthorityId, + /// Failed to set the authority discovery peerset priority group in the peerset module. + SettingPeersetPriorityGroup(String), + /// Failed to encode a protobuf payload. + EncodingProto(prost::EncodeError), + /// Failed to decode a protobuf payload. + DecodingProto(prost::DecodeError), + /// Failed to encode or decode scale payload + EncodingDecodingScale(codec::Error), + /// Failed to parse a libp2p multi address. + ParsingMultiaddress(libp2p::core::multiaddr::Error), +} diff --git a/client/authority-discovery/src/lib.rs b/client/authority-discovery/src/lib.rs new file mode 100644 index 0000000000000..ee2b655b925a6 --- /dev/null +++ b/client/authority-discovery/src/lib.rs @@ -0,0 +1,515 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![warn(missing_docs)] + +//! Substrate authority discovery. +//! +//! This crate enables Substrate authorities to directly connect to other authorities. +//! [`AuthorityDiscovery`] implements the Future trait. By polling [`AuthorityDiscovery`] an +//! authority: +//! +//! +//! 1. **Makes itself discoverable** +//! +//! 1. Retrieves its external addresses. +//! +//! 2. Adds its network peer id to the addresses. +//! +//! 3. Signs the above. +//! +//! 4. Puts the signature and the addresses on the libp2p Kademlia DHT. +//! +//! +//! 2. **Discovers other authorities** +//! +//! 1. Retrieves the current set of authorities. +//! +//! 2. Starts DHT queries for the ids of the authorities. +//! +//! 3. Validates the signatures of the retrieved key value pairs. +//! +//! 4. Adds the retrieved external addresses as priority nodes to the peerset. +use std::collections::{HashMap, HashSet}; +use std::convert::TryInto; +use std::marker::PhantomData; +use std::pin::Pin; +use std::sync::Arc; +use std::time::{Duration, Instant}; + +use futures::task::{Context, Poll}; +use futures::{Future, FutureExt, Stream, StreamExt}; +use futures_timer::Delay; + +use codec::{Decode, Encode}; +use error::{Error, Result}; +use libp2p::Multiaddr; +use log::{debug, error, log_enabled, warn}; +use prost::Message; +use sc_client_api::blockchain::HeaderBackend; +use sc_network::specialization::NetworkSpecialization; +use sc_network::{DhtEvent, ExHashT, NetworkStateInfo}; +use sp_authority_discovery::{AuthorityDiscoveryApi, AuthorityId, AuthoritySignature, AuthorityPair}; +use sp_core::crypto::{key_types, Pair}; +use sp_core::traits::BareCryptoStorePtr; +use sp_runtime::{traits::Block as BlockT, generic::BlockId}; +use sp_api::ProvideRuntimeApi; +use addr_cache::AddrCache; + +#[cfg(test)] +mod tests; + +mod error; +mod addr_cache; +/// Dht payload schemas generated from Protobuf definitions via Prost crate in build.rs. +mod schema { + include!(concat!(env!("OUT_DIR"), "/authority_discovery.rs")); +} + +type Interval = Box + Unpin + Send + Sync>; + +/// Upper bound estimation on how long one should wait before accessing the Kademlia DHT. +const LIBP2P_KADEMLIA_BOOTSTRAP_TIME: Duration = Duration::from_secs(30); + +/// Name of the Substrate peerset priority group for authorities discovered through the authority +/// discovery module. +const AUTHORITIES_PRIORITY_GROUP_NAME: &'static str = "authorities"; + +/// An `AuthorityDiscovery` makes a given authority discoverable and discovers other authorities. +pub struct AuthorityDiscovery +where + Block: BlockT + 'static, + Network: NetworkProvider, + Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, + >::Api: AuthorityDiscoveryApi, +{ + client: Arc, + + network: Arc, + /// List of sentry node public addresses. + // + // There are 3 states: + // - None: No addresses were specified. + // - Some(vec![]): Addresses were specified, but none could be parsed as proper + // Multiaddresses. + // - Some(vec![a, b, c, ...]): Valid addresses were specified. + sentry_nodes: Option>, + /// Channel we receive Dht events on. + dht_event_rx: Pin + Send>>, + + key_store: BareCryptoStorePtr, + + /// Interval to be proactive, publishing own addresses. + publish_interval: Interval, + /// Interval on which to query for addresses of other authorities. + query_interval: Interval, + + addr_cache: addr_cache::AddrCache, + + phantom: PhantomData, +} + +impl AuthorityDiscovery +where + Block: BlockT + Unpin + 'static, + Network: NetworkProvider, + Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, + >::Api: + AuthorityDiscoveryApi, + Self: Future, +{ + /// Return a new authority discovery. + /// + /// Note: When specifying `sentry_nodes` this module will not advertise the public addresses of + /// the node itself but only the public addresses of its sentry nodes. + pub fn new( + client: Arc, + network: Arc, + sentry_nodes: Vec, + key_store: BareCryptoStorePtr, + dht_event_rx: Pin + Send>>, + ) -> Self { + // Kademlia's default time-to-live for Dht records is 36h, republishing records every 24h. + // Given that a node could restart at any point in time, one can not depend on the + // republishing process, thus publishing own external addresses should happen on an interval + // < 36h. + let publish_interval = interval_at( + Instant::now() + LIBP2P_KADEMLIA_BOOTSTRAP_TIME, + Duration::from_secs(12 * 60 * 60), + ); + + // External addresses of other authorities can change at any given point in time. The + // interval on which to query for external addresses of other authorities is a trade off + // between efficiency and performance. + let query_interval = interval_at( + Instant::now() + LIBP2P_KADEMLIA_BOOTSTRAP_TIME, + Duration::from_secs(10 * 60), + ); + + let sentry_nodes = if !sentry_nodes.is_empty() { + let addrs = sentry_nodes.into_iter().filter_map(|a| match a.parse() { + Ok(addr) => Some(addr), + Err(e) => { + error!( + target: "sub-authority-discovery", + "Failed to parse sentry node public address '{:?}', continuing anyways.", e, + ); + None + } + }).collect::>(); + + Some(addrs) + } else { + None + }; + + let addr_cache = AddrCache::new(); + + AuthorityDiscovery { + client, + network, + sentry_nodes, + dht_event_rx, + key_store, + publish_interval, + query_interval, + addr_cache, + phantom: PhantomData, + } + } + + /// Publish either our own or if specified the public addresses of our sentry nodes. + fn publish_ext_addresses(&mut self) -> Result<()> { + let addresses = match &self.sentry_nodes { + Some(addrs) => addrs.clone().into_iter() + .map(|a| a.to_vec()) + .collect(), + None => self.network.external_addresses() + .into_iter() + .map(|a| a.with(libp2p::core::multiaddr::Protocol::P2p( + self.network.local_peer_id().into(), + ))) + .map(|a| a.to_vec()) + .collect(), + }; + + let mut serialized_addresses = vec![]; + schema::AuthorityAddresses { addresses } + .encode(&mut serialized_addresses) + .map_err(Error::EncodingProto)?; + + for key in self.get_priv_keys_within_authority_set()?.into_iter() { + let signature = key.sign(&serialized_addresses); + + let mut signed_addresses = vec![]; + schema::SignedAuthorityAddresses { + addresses: serialized_addresses.clone(), + signature: signature.encode(), + } + .encode(&mut signed_addresses) + .map_err(Error::EncodingProto)?; + + self.network.put_value( + hash_authority_id(key.public().as_ref())?, + signed_addresses, + ); + } + + Ok(()) + } + + fn request_addresses_of_others(&mut self) -> Result<()> { + let id = BlockId::hash(self.client.info().best_hash); + + let authorities = self + .client + .runtime_api() + .authorities(&id) + .map_err(Error::CallingRuntime)?; + + for authority_id in authorities.iter() { + self.network + .get_value(&hash_authority_id(authority_id.as_ref())?); + } + + Ok(()) + } + + fn handle_dht_events(&mut self, cx: &mut Context) -> Result<()> { + while let Poll::Ready(Some(event)) = self.dht_event_rx.poll_next_unpin(cx) { + match event { + DhtEvent::ValueFound(v) => { + if log_enabled!(log::Level::Debug) { + let hashes = v.iter().map(|(hash, _value)| hash.clone()); + debug!( + target: "sub-authority-discovery", + "Value for hash '{:?}' found on Dht.", hashes, + ); + } + + self.handle_dht_value_found_event(v)?; + } + DhtEvent::ValueNotFound(hash) => debug!( + target: "sub-authority-discovery", + "Value for hash '{:?}' not found on Dht.", hash + ), + DhtEvent::ValuePut(hash) => debug!( + target: "sub-authority-discovery", + "Successfully put hash '{:?}' on Dht.", hash), + DhtEvent::ValuePutFailed(hash) => warn!( + target: "sub-authority-discovery", + "Failed to put hash '{:?}' on Dht.", hash + ), + } + } + + Ok(()) + } + + fn handle_dht_value_found_event( + &mut self, + values: Vec<(libp2p::kad::record::Key, Vec)>, + ) -> Result<()> { + // Ensure `values` is not empty and all its keys equal. + let remote_key = values.iter().fold(Ok(None), |acc, (key, _)| { + match acc { + Ok(None) => Ok(Some(key.clone())), + Ok(Some(ref prev_key)) if prev_key != key => Err( + Error::ReceivingDhtValueFoundEventWithDifferentKeys + ), + x @ Ok(_) => x, + Err(e) => Err(e), + } + })?.ok_or(Error::ReceivingDhtValueFoundEventWithNoRecords)?; + + let authorities = { + let block_id = BlockId::hash(self.client.info().best_hash); + // From the Dht we only get the hashed authority id. In order to retrieve the actual + // authority id and to ensure it is actually an authority, we match the hash against the + // hash of the authority id of all other authorities. + let authorities = self.client.runtime_api().authorities(&block_id)?; + self.addr_cache.retain_ids(&authorities); + authorities + .into_iter() + .map(|id| hash_authority_id(id.as_ref()).map(|h| (h, id))) + .collect::>>()? + }; + + // Check if the event origins from an authority in the current authority set. + let authority_id: &AuthorityId = authorities + .get(&remote_key) + .ok_or(Error::MatchingHashedAuthorityIdWithAuthorityId)?; + + let remote_addresses: Vec = values.into_iter() + .map(|(_k, v)| { + let schema::SignedAuthorityAddresses { + signature, + addresses, + } = schema::SignedAuthorityAddresses::decode(v).map_err(Error::DecodingProto)?; + let signature = AuthoritySignature::decode(&mut &signature[..]) + .map_err(Error::EncodingDecodingScale)?; + + if !AuthorityPair::verify(&signature, &addresses, authority_id) { + return Err(Error::VerifyingDhtPayload); + } + + let addresses: Vec = schema::AuthorityAddresses::decode(addresses) + .map(|a| a.addresses) + .map_err(Error::DecodingProto)? + .into_iter() + .map(|a| a.try_into()) + .collect::>() + .map_err(Error::ParsingMultiaddress)?; + + Ok(addresses) + }) + .collect::>>>()? + .into_iter().flatten().collect(); + + if !remote_addresses.is_empty() { + self.addr_cache.insert(authority_id.clone(), remote_addresses); + self.update_peer_set_priority_group()?; + } + + Ok(()) + } + + /// Retrieve all local authority discovery private keys that are within the current authority + /// set. + fn get_priv_keys_within_authority_set(&mut self) -> Result> { + let keys = self.get_own_public_keys_within_authority_set()? + .into_iter() + .map(std::convert::Into::into) + .filter_map(|pub_key| { + self.key_store.read().sr25519_key_pair(key_types::AUTHORITY_DISCOVERY, &pub_key) + }) + .map(std::convert::Into::into) + .collect(); + + Ok(keys) + } + + /// Retrieve our public keys within the current authority set. + // + // A node might have multiple authority discovery keys within its keystore, e.g. an old one and + // one for the upcoming session. In addition it could be participating in the current authority + // set with two keys. The function does not return all of the local authority discovery public + // keys, but only the ones intersecting with the current authority set. + fn get_own_public_keys_within_authority_set(&mut self) -> Result> { + let local_pub_keys = self.key_store + .read() + .sr25519_public_keys(key_types::AUTHORITY_DISCOVERY) + .into_iter() + .collect::>(); + + let id = BlockId::hash(self.client.info().best_hash); + let current_authorities = self + .client + .runtime_api() + .authorities(&id) + .map_err(Error::CallingRuntime)? + .into_iter() + .map(std::convert::Into::into) + .collect::>(); + + let intersection = local_pub_keys.intersection(¤t_authorities) + .cloned() + .map(std::convert::Into::into) + .collect(); + + Ok(intersection) + } + + /// Update the peer set 'authority' priority group. + // + fn update_peer_set_priority_group(&self) -> Result<()>{ + let addresses = self.addr_cache.get_subset(); + + debug!( + target: "sub-authority-discovery", + "Applying priority group {:?} to peerset.", addresses, + ); + self.network + .set_priority_group(AUTHORITIES_PRIORITY_GROUP_NAME.to_string(), addresses.into_iter().collect()) + .map_err(Error::SettingPeersetPriorityGroup)?; + + Ok(()) + } +} + +impl Future for AuthorityDiscovery +where + Block: BlockT + Unpin + 'static, + Network: NetworkProvider, + Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, + >::Api: + AuthorityDiscoveryApi, +{ + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let mut inner = || -> Result<()> { + // Process incoming events before triggering new ones. + self.handle_dht_events(cx)?; + + if let Poll::Ready(_) = self.publish_interval.poll_next_unpin(cx) { + // Make sure to call interval.poll until it returns Async::NotReady once. Otherwise, + // in case one of the function calls within this block do a `return`, we don't call + // `interval.poll` again and thereby the underlying Tokio task is never registered + // with Tokio's Reactor to be woken up on the next interval tick. + while let Poll::Ready(_) = self.publish_interval.poll_next_unpin(cx) {} + + self.publish_ext_addresses()?; + } + + if let Poll::Ready(_) = self.query_interval.poll_next_unpin(cx) { + // Make sure to call interval.poll until it returns Async::NotReady once. Otherwise, + // in case one of the function calls within this block do a `return`, we don't call + // `interval.poll` again and thereby the underlying Tokio task is never registered + // with Tokio's Reactor to be woken up on the next interval tick. + while let Poll::Ready(_) = self.query_interval.poll_next_unpin(cx) {} + + self.request_addresses_of_others()?; + } + + Ok(()) + }; + + match inner() { + Ok(()) => {} + Err(e) => error!(target: "sub-authority-discovery", "Poll failure: {:?}", e), + }; + + // Make sure to always return NotReady as this is a long running task with the same lifetime + // as the node itself. + Poll::Pending + } +} + +/// NetworkProvider provides AuthorityDiscovery with all necessary hooks into the underlying +/// Substrate networking. Using this trait abstraction instead of NetworkService directly is +/// necessary to unit test AuthorityDiscovery. +pub trait NetworkProvider: NetworkStateInfo { + /// Modify a peerset priority group. + fn set_priority_group( + &self, + group_id: String, + peers: HashSet, + ) -> std::result::Result<(), String>; + + /// Start putting a value in the Dht. + fn put_value(&self, key: libp2p::kad::record::Key, value: Vec); + + /// Start getting a value from the Dht. + fn get_value(&self, key: &libp2p::kad::record::Key); +} + +impl NetworkProvider for sc_network::NetworkService +where + B: BlockT + 'static, + S: NetworkSpecialization, + H: ExHashT, +{ + fn set_priority_group( + &self, + group_id: String, + peers: HashSet, + ) -> std::result::Result<(), String> { + self.set_priority_group(group_id, peers) + } + fn put_value(&self, key: libp2p::kad::record::Key, value: Vec) { + self.put_value(key, value) + } + fn get_value(&self, key: &libp2p::kad::record::Key) { + self.get_value(key) + } +} + +fn hash_authority_id(id: &[u8]) -> Result { + libp2p::multihash::encode(libp2p::multihash::Hash::SHA2256, id) + .map(|k| libp2p::kad::record::Key::new(&k)) + .map_err(Error::HashingAuthorityId) +} + +fn interval_at(start: Instant, duration: Duration) -> Interval { + let stream = futures::stream::unfold(start, move |next| { + let time_until_next = next.saturating_duration_since(Instant::now()); + + Delay::new(time_until_next).map(move |_| Some(((), next + duration))) + }); + + Box::new(stream) +} diff --git a/core/authority-discovery/src/schema/dht.proto b/client/authority-discovery/src/schema/dht.proto similarity index 100% rename from core/authority-discovery/src/schema/dht.proto rename to client/authority-discovery/src/schema/dht.proto diff --git a/client/authority-discovery/src/tests.rs b/client/authority-discovery/src/tests.rs new file mode 100644 index 0000000000000..07e1c943be638 --- /dev/null +++ b/client/authority-discovery/src/tests.rs @@ -0,0 +1,401 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{iter::FromIterator, sync::{Arc, Mutex}}; + +use futures::channel::mpsc::channel; +use futures::executor::block_on; +use futures::future::poll_fn; +use libp2p::{kad, PeerId}; + +use sp_api::{ApiExt, ApiErrorExt, Core, RuntimeVersion, StorageProof, ProvideRuntimeApi, ApiRef}; +use sp_core::{testing::KeyStore, ExecutionContext, NativeOrEncoded}; +use sp_runtime::traits::{Zero, Block as BlockT, NumberFor}; +use substrate_test_runtime_client::runtime::Block; + +use super::*; + +#[test] +fn interval_at_with_start_now() { + let start = Instant::now(); + + let mut interval = interval_at( + std::time::Instant::now(), + std::time::Duration::from_secs(10), + ); + + futures::executor::block_on(async { + interval.next().await; + }); + + assert!( + Instant::now().saturating_duration_since(start) < Duration::from_secs(1), + "Expected low resolution instant interval to fire within less than a second.", + ); +} + +#[test] +fn interval_at_is_queuing_ticks() { + let start = Instant::now(); + + let interval = interval_at(start, std::time::Duration::from_millis(100)); + + // Let's wait for 200ms, thus 3 elements should be queued up (1st at 0ms, 2nd at 100ms, 3rd + // at 200ms). + std::thread::sleep(Duration::from_millis(200)); + + futures::executor::block_on(async { + interval.take(3).collect::>().await; + }); + + // Make sure we did not wait for more than 300 ms, which would imply that `at_interval` is + // not queuing ticks. + assert!( + Instant::now().saturating_duration_since(start) < Duration::from_millis(300), + "Expect interval to /queue/ events when not polled for a while.", + ); +} + +#[test] +fn interval_at_with_initial_delay() { + let start = Instant::now(); + + let mut interval = interval_at( + std::time::Instant::now() + Duration::from_millis(100), + std::time::Duration::from_secs(10), + ); + + futures::executor::block_on(async { + interval.next().await; + }); + + assert!( + Instant::now().saturating_duration_since(start) > Duration::from_millis(100), + "Expected interval with initial delay not to fire right away.", + ); +} + +#[derive(Clone)] +struct TestApi { + authorities: Vec, +} + +impl ProvideRuntimeApi for TestApi { + type Api = RuntimeApi; + + fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { + RuntimeApi { + authorities: self.authorities.clone(), + } + .into() + } +} + +/// Blockchain database header backend. Does not perform any validation. +impl HeaderBackend for TestApi { + fn header( + &self, + _id: BlockId, + ) -> std::result::Result, sp_blockchain::Error> { + Ok(None) + } + + fn info(&self) -> sc_client_api::blockchain::Info { + sc_client_api::blockchain::Info { + best_hash: Default::default(), + best_number: Zero::zero(), + finalized_hash: Default::default(), + finalized_number: Zero::zero(), + genesis_hash: Default::default(), + } + } + + fn status( + &self, + _id: BlockId, + ) -> std::result::Result { + Ok(sc_client_api::blockchain::BlockStatus::Unknown) + } + + fn number( + &self, + _hash: Block::Hash, + ) -> std::result::Result>, sp_blockchain::Error> { + Ok(None) + } + + fn hash( + &self, + _number: NumberFor, + ) -> std::result::Result, sp_blockchain::Error> { + Ok(None) + } +} + +struct RuntimeApi { + authorities: Vec, +} + +impl Core for RuntimeApi { + fn Core_version_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> std::result::Result, sp_blockchain::Error> { + unimplemented!("Not required for testing!") + } + + fn Core_execute_block_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option, + _: Vec, + ) -> std::result::Result, sp_blockchain::Error> { + unimplemented!("Not required for testing!") + } + + fn Core_initialize_block_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<&::Header>, + _: Vec, + ) -> std::result::Result, sp_blockchain::Error> { + unimplemented!("Not required for testing!") + } +} + +impl ApiErrorExt for RuntimeApi { + type Error = sp_blockchain::Error; +} + +impl ApiExt for RuntimeApi { + type StateBackend = < + substrate_test_runtime_client::Backend as sc_client_api::backend::Backend + >::State; + + fn map_api_result std::result::Result, R, E>( + &self, + _: F + ) -> std::result::Result { + unimplemented!("Not required for testing!") + } + + fn runtime_version_at( + &self, + _: &BlockId, + ) -> std::result::Result { + unimplemented!("Not required for testing!") + } + + fn record_proof(&mut self) { + unimplemented!("Not required for testing!") + } + + fn extract_proof(&mut self) -> Option { + unimplemented!("Not required for testing!") + } + + fn into_storage_changes< + T: sp_api::ChangesTrieStorage, sp_api::NumberFor> + >( + &self, + _: &Self::StateBackend, + _: Option<&T>, + _: ::Hash, + ) -> std::result::Result, String> + where Self: Sized + { + unimplemented!("Not required for testing!") + } +} + +impl AuthorityDiscoveryApi for RuntimeApi { + fn AuthorityDiscoveryApi_authorities_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> std::result::Result>, sp_blockchain::Error> { + return Ok(NativeOrEncoded::Native(self.authorities.clone())); + } +} + +#[derive(Default)] +struct TestNetwork { + // Whenever functions on `TestNetwork` are called, the function arguments are added to the + // vectors below. + pub put_value_call: Arc)>>>, + pub get_value_call: Arc>>, + pub set_priority_group_call: Arc)>>>, +} + +impl NetworkProvider for TestNetwork { + fn set_priority_group( + &self, + group_id: String, + peers: HashSet, + ) -> std::result::Result<(), String> { + self.set_priority_group_call + .lock() + .unwrap() + .push((group_id, peers)); + Ok(()) + } + fn put_value(&self, key: kad::record::Key, value: Vec) { + self.put_value_call.lock().unwrap().push((key, value)); + } + fn get_value(&self, key: &kad::record::Key) { + self.get_value_call.lock().unwrap().push(key.clone()); + } +} + +impl NetworkStateInfo for TestNetwork { + fn local_peer_id(&self) -> PeerId { + PeerId::random() + } + + fn external_addresses(&self) -> Vec { + vec![] + } +} + +#[test] +fn publish_ext_addresses_puts_record_on_dht() { + let (_dht_event_tx, dht_event_rx) = channel(1000); + let network: Arc = Arc::new(Default::default()); + let key_store = KeyStore::new(); + let public = key_store + .write() + .sr25519_generate_new(key_types::AUTHORITY_DISCOVERY, None) + .unwrap(); + let test_api = Arc::new(TestApi { + authorities: vec![public.into()], + }); + + let mut authority_discovery = AuthorityDiscovery::new( + test_api, + network.clone(), + vec![], + key_store, + dht_event_rx.boxed(), + ); + + authority_discovery.publish_ext_addresses().unwrap(); + + // Expect authority discovery to put a new record onto the dht. + assert_eq!(network.put_value_call.lock().unwrap().len(), 1); +} + +#[test] +fn request_addresses_of_others_triggers_dht_get_query() { + let _ = ::env_logger::try_init(); + let (_dht_event_tx, dht_event_rx) = channel(1000); + + // Generate authority keys + let authority_1_key_pair = AuthorityPair::from_seed_slice(&[1; 32]).unwrap(); + let authority_2_key_pair = AuthorityPair::from_seed_slice(&[2; 32]).unwrap(); + + let test_api = Arc::new(TestApi { + authorities: vec![authority_1_key_pair.public(), authority_2_key_pair.public()], + }); + + let network: Arc = Arc::new(Default::default()); + let key_store = KeyStore::new(); + + let mut authority_discovery = AuthorityDiscovery::new( + test_api, + network.clone(), + vec![], + key_store, + dht_event_rx.boxed(), + ); + + authority_discovery.request_addresses_of_others().unwrap(); + + // Expect authority discovery to request new records from the dht. + assert_eq!(network.get_value_call.lock().unwrap().len(), 2); +} + +#[test] +fn handle_dht_events_with_value_found_should_call_set_priority_group() { + let _ = ::env_logger::try_init(); + // Create authority discovery. + + let (mut dht_event_tx, dht_event_rx) = channel(1000); + let key_pair = AuthorityPair::from_seed_slice(&[1; 32]).unwrap(); + let test_api = Arc::new(TestApi { + authorities: vec![key_pair.public()], + }); + let network: Arc = Arc::new(Default::default()); + let key_store = KeyStore::new(); + + let mut authority_discovery = AuthorityDiscovery::new( + test_api, + network.clone(), + vec![], + key_store, + dht_event_rx.boxed(), + ); + + // Create sample dht event. + + let authority_id_1 = hash_authority_id(key_pair.public().as_ref()).unwrap(); + let address_1: Multiaddr = "/ip6/2001:db8::".parse().unwrap(); + + let mut serialized_addresses = vec![]; + schema::AuthorityAddresses { + addresses: vec![address_1.to_vec()], + } + .encode(&mut serialized_addresses) + .unwrap(); + + let signature = key_pair.sign(serialized_addresses.as_ref()).encode(); + let mut signed_addresses = vec![]; + schema::SignedAuthorityAddresses { + addresses: serialized_addresses, + signature: signature, + } + .encode(&mut signed_addresses) + .unwrap(); + + let dht_event = sc_network::DhtEvent::ValueFound(vec![(authority_id_1, signed_addresses)]); + dht_event_tx.try_send(dht_event).unwrap(); + + // Make authority discovery handle the event. + let f = |cx: &mut Context<'_>| -> Poll<()> { + authority_discovery.handle_dht_events(cx).unwrap(); + + // Expect authority discovery to set the priority set. + assert_eq!(network.set_priority_group_call.lock().unwrap().len(), 1); + + assert_eq!( + network.set_priority_group_call.lock().unwrap()[0], + ( + "authorities".to_string(), + HashSet::from_iter(vec![address_1.clone()].into_iter()) + ) + ); + + Poll::Ready(()) + }; + + let _ = block_on(poll_fn(f)); +} diff --git a/client/basic-authorship/Cargo.toml b/client/basic-authorship/Cargo.toml new file mode 100644 index 0000000000000..4cdef01afd46b --- /dev/null +++ b/client/basic-authorship/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "sc-basic-authority" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4.8" +futures = "0.3.1" +codec = { package = "parity-scale-codec", version = "1.0.0" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +sc-client = { version = "2.0.0", path = "../" } +sc-client-api = { version = "2.0.0", path = "../api" } +sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0", path = "../../primitives/inherents" } +sc-telemetry = { version = "2.0.0", path = "../telemetry" } +sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } +sc-block-builder = { version = "2.0.0", path = "../block-builder" } +tokio-executor = { version = "0.2.0-alpha.6", features = ["blocking"] } + +[dev-dependencies] +sc-transaction-pool = { version = "2.0.0", path = "../../client/transaction-pool" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } +parking_lot = "0.9" diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs new file mode 100644 index 0000000000000..543428b073478 --- /dev/null +++ b/client/basic-authorship/src/basic_authorship.rs @@ -0,0 +1,385 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A consensus proposer for "basic" chains which use the primitive inherent-data. + +// FIXME #1021 move this into sp-consensus + +use std::{time, sync::Arc}; +use sc_client_api::{CallExecutor, backend}; +use sc_client::Client as SubstrateClient; +use codec::Decode; +use sp_consensus::{evaluation, Proposal, RecordProof}; +use sp_inherents::InherentData; +use log::{error, info, debug, trace}; +use sp_core::ExecutionContext; +use sp_runtime::{ + traits::{Block as BlockT, Hash as HashT, Header as HeaderT, DigestFor, BlakeTwo256}, + generic::BlockId, +}; +use sp_transaction_pool::{TransactionPool, InPoolTransaction}; +use sc_telemetry::{telemetry, CONSENSUS_INFO}; +use sc_block_builder::BlockBuilderApi; +use sp_api::{ProvideRuntimeApi, ApiExt}; + +/// Proposer factory. +pub struct ProposerFactory where A: TransactionPool { + /// The client instance. + pub client: Arc, + /// The transaction pool. + pub transaction_pool: Arc, +} + +impl ProposerFactory, A> + where + A: TransactionPool + 'static, + B: backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + Clone + 'static, + Block: BlockT, + RA: Send + Sync + 'static, + SubstrateClient: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + BlockBuilderApi + + ApiExt>, +{ + pub fn init_with_now( + &mut self, + parent_header: &::Header, + now: Box time::Instant + Send + Sync>, + ) -> Result, A>, sp_blockchain::Error> { + let parent_hash = parent_header.hash(); + + let id = BlockId::hash(parent_hash); + + info!("Starting consensus session on top of parent {:?}", parent_hash); + + let proposer = Proposer { + inner: Arc::new(ProposerInner { + client: self.client.clone(), + parent_hash, + parent_id: id, + parent_number: *parent_header.number(), + transaction_pool: self.transaction_pool.clone(), + now, + }), + }; + + Ok(proposer) + } +} + +impl sp_consensus::Environment for + ProposerFactory, A> + where + A: TransactionPool + 'static, + B: backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + Clone + 'static, + Block: BlockT, + RA: Send + Sync + 'static, + SubstrateClient: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + BlockBuilderApi + + ApiExt>, +{ + type Proposer = Proposer, A>; + type Error = sp_blockchain::Error; + + fn init( + &mut self, + parent_header: &::Header, + ) -> Result { + self.init_with_now(parent_header, Box::new(time::Instant::now)) + } +} + +/// The proposer logic. +pub struct Proposer { + inner: Arc>, +} + +/// Proposer inner, to wrap parameters under Arc. +struct ProposerInner { + client: Arc, + parent_hash: ::Hash, + parent_id: BlockId, + parent_number: <::Header as HeaderT>::Number, + transaction_pool: Arc, + now: Box time::Instant + Send + Sync>, +} + +impl sp_consensus::Proposer for + Proposer, A> + where + A: TransactionPool + 'static, + B: backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + Clone + 'static, + Block: BlockT, + RA: Send + Sync + 'static, + SubstrateClient: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + BlockBuilderApi + + ApiExt>, +{ + type Transaction = backend::TransactionFor; + type Proposal = tokio_executor::blocking::Blocking< + Result, Self::Error> + >; + type Error = sp_blockchain::Error; + + fn propose( + &mut self, + inherent_data: InherentData, + inherent_digests: DigestFor, + max_duration: time::Duration, + record_proof: RecordProof, + ) -> Self::Proposal { + let inner = self.inner.clone(); + tokio_executor::blocking::run(move || { + // leave some time for evaluation and block finalization (33%) + let deadline = (inner.now)() + max_duration - max_duration / 3; + inner.propose_with(inherent_data, inherent_digests, deadline, record_proof) + }) + } +} + +impl ProposerInner, A> where + A: TransactionPool, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + Clone + 'static, + Block: BlockT, + RA: Send + Sync + 'static, + SubstrateClient: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + BlockBuilderApi + + ApiExt>, +{ + fn propose_with( + &self, + inherent_data: InherentData, + inherent_digests: DigestFor, + deadline: time::Instant, + record_proof: RecordProof, + ) -> Result>, sp_blockchain::Error> { + /// 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 utilization. + const MAX_SKIPPED_TRANSACTIONS: usize = 8; + + let mut block_builder = self.client.new_block_at( + &self.parent_id, + inherent_digests, + record_proof, + )?; + + // We don't check the API versions any further here since the dispatch compatibility + // check should be enough. + for extrinsic in self.client.runtime_api() + .inherent_extrinsics_with_context( + &self.parent_id, + ExecutionContext::BlockConstruction, + inherent_data + )? + { + block_builder.push(extrinsic)?; + } + + // proceed with transactions + let mut is_first = true; + let mut skipped = 0; + let mut unqueue_invalid = Vec::new(); + let pending_iterator = self.transaction_pool.ready(); + + debug!("Attempting to push transactions from the pool."); + for pending_tx in pending_iterator { + if (self.now)() > deadline { + debug!( + "Consensus deadline reached when pushing block transactions, \ + proceeding with proposing." + ); + break; + } + + let pending_tx_data = pending_tx.data().clone(); + let pending_tx_hash = pending_tx.hash().clone(); + trace!("[{:?}] Pushing to the block.", pending_tx_hash); + match sc_block_builder::BlockBuilder::push(&mut block_builder, pending_tx_data) { + Ok(()) => { + debug!("[{:?}] Pushed to the block.", pending_tx_hash); + } + Err(sp_blockchain::Error::ApplyExtrinsicFailed(sp_blockchain::ApplyExtrinsicFailed::Validity(e))) + if e.exhausted_resources() => { + if is_first { + debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending_tx_hash); + unqueue_invalid.push(pending_tx_hash); + } else if skipped < MAX_SKIPPED_TRANSACTIONS { + 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) => { + debug!("[{:?}] Invalid transaction: {}", pending_tx_hash, e); + unqueue_invalid.push(pending_tx_hash); + } + } + + is_first = false; + } + + self.transaction_pool.remove_invalid(&unqueue_invalid); + + let (block, storage_changes, proof) = block_builder.build()?.into_inner(); + + info!("Prepared block for proposing at {} [hash: {:?}; parent_hash: {}; extrinsics: [{}]]", + block.header().number(), + ::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" => ?::Hash::from(block.header().hash()), + ); + + if Decode::decode(&mut block.encode().as_slice()).as_ref() != Ok(&block) { + error!("Failed to verify block encoding/decoding"); + } + + if let Err(err) = evaluation::evaluate_initial(&block, &self.parent_hash, self.parent_number) { + error!("Failed to evaluate authored block: {:?}", err); + } + + Ok(Proposal { block, proof, storage_changes }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use parking_lot::Mutex; + use sp_consensus::Proposer; + use substrate_test_runtime_client::{ + runtime::{Extrinsic, Transfer}, AccountKeyring, DefaultTestClientBuilderExt, + TestClientBuilderExt, + }; + use sc_transaction_pool::{BasicPool, FullChainApi}; + use sp_api::Core; + use backend::Backend; + use sp_blockchain::HeaderBackend; + + fn extrinsic(nonce: u64) -> Extrinsic { + Transfer { + amount: Default::default(), + nonce, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx() + } + + #[test] + fn should_cease_building_block_when_deadline_is_reached() { + // given + let client = Arc::new(substrate_test_runtime_client::new()); + let txpool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); + + futures::executor::block_on( + txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)]) + ).unwrap(); + + let mut proposer_factory = ProposerFactory { + client: client.clone(), + transaction_pool: txpool.clone(), + }; + + let cell = Mutex::new(time::Instant::now()); + let mut proposer = proposer_factory.init_with_now( + &client.header(&BlockId::number(0)).unwrap().unwrap(), + Box::new(move || { + let mut value = cell.lock(); + let old = *value; + let new = old + time::Duration::from_secs(2); + *value = new; + old + }) + ).unwrap(); + + // when + let deadline = time::Duration::from_secs(3); + let block = futures::executor::block_on( + proposer.propose(Default::default(), Default::default(), deadline, RecordProof::No) + ).map(|r| r.block).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); + } + + #[test] + fn proposed_storage_changes_should_match_execute_block_storage_changes() { + let (client, backend) = substrate_test_runtime_client::TestClientBuilder::new() + .build_with_backend(); + let client = Arc::new(client); + let txpool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); + let genesis_hash = client.info().best_hash; + let block_id = BlockId::Hash(genesis_hash); + + futures::executor::block_on( + txpool.submit_at(&BlockId::number(0), vec![extrinsic(0)]), + ).unwrap(); + + let mut proposer_factory = ProposerFactory { + client: client.clone(), + transaction_pool: txpool.clone(), + }; + + let mut proposer = proposer_factory.init_with_now( + &client.header(&block_id).unwrap().unwrap(), + Box::new(move || time::Instant::now()), + ).unwrap(); + + let deadline = time::Duration::from_secs(9); + let proposal = futures::executor::block_on( + proposer.propose(Default::default(), Default::default(), deadline, RecordProof::No), + ).unwrap(); + + assert_eq!(proposal.block.extrinsics().len(), 1); + + let api = client.runtime_api(); + api.execute_block(&block_id, proposal.block).unwrap(); + + let state = backend.state_at(block_id).unwrap(); + let changes_trie_storage = backend.changes_trie_storage(); + + let storage_changes = api.into_storage_changes(&state, changes_trie_storage, genesis_hash) + .unwrap(); + + assert_eq!( + proposal.storage_changes.transaction_storage_root, + storage_changes.transaction_storage_root, + ); + } +} diff --git a/client/basic-authorship/src/lib.rs b/client/basic-authorship/src/lib.rs new file mode 100644 index 0000000000000..cf77c8a3f341a --- /dev/null +++ b/client/basic-authorship/src/lib.rs @@ -0,0 +1,58 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Basic implementation of block-authoring logic. +//! +//! # Example +//! +//! ``` +//! # use sc_basic_authority::ProposerFactory; +//! # use sp_consensus::{Environment, Proposer, RecordProof}; +//! # use sp_runtime::generic::BlockId; +//! # use std::{sync::Arc, time::Duration}; +//! # use substrate_test_runtime_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; +//! # use sc_transaction_pool::{BasicPool, FullChainApi}; +//! # let client = Arc::new(substrate_test_runtime_client::new()); +//! # let txpool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); +//! // The first step is to create a `ProposerFactory`. +//! let mut proposer_factory = ProposerFactory { +//! client: client.clone(), +//! transaction_pool: txpool.clone(), +//! }; +//! +//! // From this factory, we create a `Proposer`. +//! let mut proposer = proposer_factory.init( +//! &client.header(&BlockId::number(0)).unwrap().unwrap(), +//! ).unwrap(); +//! +//! // This `Proposer` allows us to create a block proposition. +//! // The proposer will grab transactions from the transaction pool, and put them into the block. +//! let future = proposer.propose( +//! Default::default(), +//! Default::default(), +//! Duration::from_secs(2), +//! RecordProof::Yes, +//! ); +//! +//! // We wait until the proposition is performed. +//! let block = futures::executor::block_on(future).unwrap(); +//! println!("Generated block: {:?}", block.block); +//! ``` +//! + +mod basic_authorship; + +pub use crate::basic_authorship::{ProposerFactory, Proposer}; diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml new file mode 100644 index 0000000000000..1dcc9b05f5eb9 --- /dev/null +++ b/client/block-builder/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sc-block-builder" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } +sp-consensus = { version = "0.8.0", path = "../../primitives/consensus/common" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-block-builder = { version = "2.0.0", path = "../../primitives/block-builder" } +sc-client-api = { version = "2.0.0", path = "../api" } +codec = { package = "parity-scale-codec", version = "1.0.6", features = ["derive"] } diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs new file mode 100644 index 0000000000000..f59f88f5ba237 --- /dev/null +++ b/client/block-builder/src/lib.rs @@ -0,0 +1,217 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate block builder +//! +//! This crate provides the [`BlockBuilder`] utility and the corresponding runtime api +//! [`BlockBuilder`](api::BlockBuilder).Error +//! +//! The block builder utility is used in the node as an abstraction over the runtime api to +//! initialize a block, to push extrinsics and to finalize a block. + +#![warn(missing_docs)] + +use codec::Encode; + +use sp_runtime::{ + generic::BlockId, + traits::{ + Header as HeaderT, Hash, Block as BlockT, HashFor, DigestFor, NumberFor, One, HasherFor, + }, +}; +use sp_blockchain::{ApplyExtrinsicFailed, Error}; +use sp_core::ExecutionContext; +use sp_api::{Core, ApiExt, ApiErrorFor, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof}; +use sp_consensus::RecordProof; + +pub use sp_block_builder::BlockBuilder as BlockBuilderApi; + +use sc_client_api::backend; + +/// A block that was build by [`BlockBuilder`] plus some additional data. +/// +/// This additional data includes the `storage_changes`, these changes can be applied to the +/// backend to get the state of the block. Furthermore an optional `proof` is included which +/// can be used to proof that the build block contains the expected data. The `proof` will +/// only be set when proof recording was activated. +pub struct BuiltBlock>> { + /// The actual block that was build. + pub block: Block, + /// The changes that need to be applied to the backend to get the state of the build block. + pub storage_changes: StorageChanges, + /// An optional proof that was recorded while building the block. + pub proof: Option, +} + +impl>> BuiltBlock { + /// Convert into the inner values. + pub fn into_inner(self) -> (Block, StorageChanges, Option) { + (self.block, self.storage_changes, self.proof) + } +} + +/// Utility for building new (valid) blocks from a stream of extrinsics. +pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi, B> { + extrinsics: Vec, + api: ApiRef<'a, A::Api>, + block_id: BlockId, + parent_hash: Block::Hash, + backend: &'a B, +} + +impl<'a, Block, A, B> BlockBuilder<'a, Block, A, B> +where + Block: BlockT, + A: ProvideRuntimeApi + 'a, + A::Api: BlockBuilderApi + + ApiExt>, + B: backend::Backend, +{ + /// Create a new instance of builder based on the given `parent_hash` and `parent_number`. + /// + /// While proof recording is enabled, all accessed trie nodes are saved. + /// These recorded trie nodes can be used by a third party to prove the + /// output of this block builder without having access to the full storage. + pub fn new( + api: &'a A, + parent_hash: Block::Hash, + parent_number: NumberFor, + record_proof: RecordProof, + inherent_digests: DigestFor, + backend: &'a B, + ) -> Result> { + let header = <::Header as HeaderT>::new( + parent_number + One::one(), + Default::default(), + Default::default(), + parent_hash, + inherent_digests, + ); + + let mut api = api.runtime_api(); + + if record_proof.yes() { + api.record_proof(); + } + + let block_id = BlockId::Hash(parent_hash); + + api.initialize_block_with_context( + &block_id, ExecutionContext::BlockConstruction, &header, + )?; + + Ok(Self { + parent_hash, + extrinsics: Vec::new(), + api, + block_id, + backend, + }) + } + + /// 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) -> Result<(), ApiErrorFor> { + let block_id = &self.block_id; + let extrinsics = &mut self.extrinsics; + + if self + .api + .has_api_with::>, _>( + block_id, + |version| version < 4, + )? + { + // Run compatibility fallback for v3. + self.api.map_api_result(|api| { + #[allow(deprecated)] + match api.apply_extrinsic_before_version_4_with_context( + block_id, + ExecutionContext::BlockConstruction, + xt.clone(), + )? { + Ok(_) => { + extrinsics.push(xt); + Ok(()) + } + Err(e) => Err(ApplyExtrinsicFailed::from(e).into()), + } + }) + } else { + self.api.map_api_result(|api| { + match api.apply_extrinsic_with_context( + block_id, + ExecutionContext::BlockConstruction, + xt.clone(), + )? { + Ok(_) => { + extrinsics.push(xt); + Ok(()) + } + Err(tx_validity) => Err(ApplyExtrinsicFailed::Validity(tx_validity).into()), + } + }) + } + } + + /// Consume the builder to build a valid `Block` containing all pushed extrinsics. + /// + /// Returns the build `Block`, the changes to the storage and an optional `StorageProof` + /// supplied by `self.api`, combined as [`BuiltBlock`]. + /// The storage proof will be `Some(_)` when proof recording was enabled. + pub fn build(mut self) -> Result< + BuiltBlock>, + ApiErrorFor + > { + let header = self.api.finalize_block_with_context( + &self.block_id, ExecutionContext::BlockConstruction + )?; + + debug_assert_eq!( + header.extrinsics_root().clone(), + HashFor::::ordered_trie_root( + self.extrinsics.iter().map(Encode::encode).collect(), + ), + ); + + let proof = self.api.extract_proof(); + + let state = self.backend.state_at(self.block_id)?; + let changes_trie_storage = self.backend.changes_trie_storage(); + let parent_hash = self.parent_hash; + + // The unsafe is required because the consume requires that we drop/consume the inner api + // (what we do here). + let storage_changes = self.api.into_storage_changes( + &state, + changes_trie_storage, + parent_hash, + ); + + // We need to destroy the state, before we check if `storage_changes` is `Ok(_)` + { + let _lock = self.backend.get_import_lock().read(); + self.backend.destroy_state(state)?; + } + + Ok(BuiltBlock { + block: ::new(header, self.extrinsics), + storage_changes: storage_changes?, + proof, + }) + } +} diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml new file mode 100644 index 0000000000000..fee166df32266 --- /dev/null +++ b/client/chain-spec/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "sc-chain-spec" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sc-chain-spec-derive = { version = "2.0.0", path = "./derive" } +impl-trait-for-tuples = "0.1.3" +sc-network = { version = "0.8", path = "../network" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.41" +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sc-telemetry = { version = "2.0.0", path = "../telemetry" } diff --git a/client/chain-spec/derive/Cargo.toml b/client/chain-spec/derive/Cargo.toml new file mode 100644 index 0000000000000..108644066496f --- /dev/null +++ b/client/chain-spec/derive/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sc-chain-spec-derive" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +proc-macro-crate = "0.1.4" +proc-macro2 = "1.0.6" +quote = "1.0.2" +syn = "1.0.7" + +[dev-dependencies] diff --git a/client/chain-spec/derive/src/impls.rs b/client/chain-spec/derive/src/impls.rs new file mode 100644 index 0000000000000..2caf1c5a9c3eb --- /dev/null +++ b/client/chain-spec/derive/src/impls.rs @@ -0,0 +1,190 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{DeriveInput, Ident, Error}; +use proc_macro_crate::crate_name; + +const CRATE_NAME: &str = "sc-chain-spec"; +const ATTRIBUTE_NAME: &str = "forks"; + +/// Implements `Extension's` `Group` accessor. +/// +/// The struct that derives this implementation will be usable within the `ChainSpec` file. +/// The derive implements a by-type accessor method. +pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { + derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types, fields| { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let forks = fields.named.iter().find_map(|f| { + if f.attrs.iter().any(|attr| attr.path.is_ident(ATTRIBUTE_NAME)) { + let typ = &f.ty; + Some(quote! { #typ }) + } else { + None + } + }).unwrap_or_else(|| quote! { #crate_name::NoExtension }); + + quote! { + impl #impl_generics #crate_name::Extension for #name #ty_generics #where_clause { + type Forks = #forks; + + fn get(&self) -> Option<&T> { + use std::any::{Any, TypeId}; + + match TypeId::of::() { + #( x if x == TypeId::of::<#field_types>() => Any::downcast_ref(&self.#field_names) ),*, + _ => None, + } + } + } + } + }) +} + + +/// Implements required traits and creates `Fork` structs for `ChainSpec` custom parameter group. +pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { + derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types, _fields| { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let fork_name = Ident::new(&format!("{}Fork", name), Span::call_site()); + + let fork_fields = generate_fork_fields(&crate_name, &field_names, &field_types); + let to_fork = generate_base_to_fork(&fork_name, &field_names); + let combine_with = generate_combine_with(&field_names); + let to_base = generate_fork_to_base(name, &field_names); + + quote! { + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + pub struct #fork_name #ty_generics #where_clause { + #fork_fields + } + + impl #impl_generics #crate_name::Group for #name #ty_generics #where_clause { + type Fork = #fork_name #ty_generics; + + fn to_fork(self) -> Self::Fork { + use #crate_name::Group; + #to_fork + } + } + + impl #impl_generics #crate_name::Fork for #fork_name #ty_generics #where_clause { + type Base = #name #ty_generics; + + fn combine_with(&mut self, other: Self) { + use #crate_name::Fork; + #combine_with + } + + fn to_base(self) -> Option { + use #crate_name::Fork; + #to_base + } + } + } + }) +} + +pub fn derive( + ast: &DeriveInput, + derive: impl Fn( + &Ident, &Ident, &syn::Generics, Vec<&Ident>, Vec<&syn::Type>, &syn::FieldsNamed, + ) -> TokenStream, +) -> proc_macro::TokenStream { + let err = || { + let err = Error::new( + Span::call_site(), + "ChainSpecGroup is only avaible for structs with named fields." + ).to_compile_error(); + quote!( #err ).into() + }; + + let data = match &ast.data { + syn::Data::Struct(ref data) => data, + _ => return err(), + }; + + let fields = match &data.fields { + syn::Fields::Named(ref named) => named, + _ => return err(), + }; + + const PROOF: &str = "CARGO_PKG_NAME always defined when compiling; qed"; + let name = &ast.ident; + let crate_name = match crate_name(CRATE_NAME) { + Ok(chain_spec_name) => chain_spec_name, + Err(e) => if std::env::var("CARGO_PKG_NAME").expect(PROOF) == CRATE_NAME { + // we return the name of the crate here instead of `crate` to support doc tests. + CRATE_NAME.replace("-", "_") + } else { + let err = Error::new(Span::call_site(), &e).to_compile_error(); + return quote!( #err ).into() + }, + }; + let crate_name = Ident::new(&crate_name, Span::call_site()); + let field_names = fields.named.iter().flat_map(|x| x.ident.as_ref()).collect::>(); + let field_types = fields.named.iter().map(|x| &x.ty).collect::>(); + + derive(&crate_name, name, &ast.generics, field_names, field_types, fields).into() +} + +fn generate_fork_fields( + crate_name: &Ident, + names: &[&Ident], + types: &[&syn::Type], +) -> TokenStream { + let crate_name = std::iter::repeat(crate_name); + quote! { + #( pub #names: Option<<#types as #crate_name::Group>::Fork>, )* + } +} + +fn generate_base_to_fork( + fork_name: &Ident, + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + #fork_name { + #( #names: Some(self.#names2.to_fork()), )* + } + } +} + +fn generate_combine_with( + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + #( self.#names.combine_with(other.#names2); )* + } +} + +fn generate_fork_to_base( + fork: &Ident, + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + Some(#fork { + #( #names: self.#names2?.to_base()?, )* + }) + } +} diff --git a/client/chain-spec/derive/src/lib.rs b/client/chain-spec/derive/src/lib.rs new file mode 100644 index 0000000000000..4648e3f78a04e --- /dev/null +++ b/client/chain-spec/derive/src/lib.rs @@ -0,0 +1,39 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Macros to derive chain spec extension traits implementation. + +extern crate proc_macro; + +mod impls; + +use proc_macro::TokenStream; + +#[proc_macro_derive(ChainSpecGroup)] +pub fn group_derive(input: TokenStream) -> TokenStream { + match syn::parse(input) { + Ok(ast) => impls::group_derive(&ast), + Err(e) => e.to_compile_error().into(), + } +} + +#[proc_macro_derive(ChainSpecExtension, attributes(forks))] +pub fn extensions_derive(input: TokenStream) -> TokenStream { + match syn::parse(input) { + Ok(ast) => impls::extension_derive(&ast), + Err(e) => e.to_compile_error().into(), + } +} diff --git a/core/chain-spec/res/chain_spec.json b/client/chain-spec/res/chain_spec.json similarity index 100% rename from core/chain-spec/res/chain_spec.json rename to client/chain-spec/res/chain_spec.json diff --git a/core/chain-spec/res/chain_spec2.json b/client/chain-spec/res/chain_spec2.json similarity index 100% rename from core/chain-spec/res/chain_spec2.json rename to client/chain-spec/res/chain_spec2.json diff --git a/client/chain-spec/src/chain_spec.rs b/client/chain-spec/src/chain_spec.rs new file mode 100644 index 0000000000000..6e58083e8cc2e --- /dev/null +++ b/client/chain-spec/src/chain_spec.rs @@ -0,0 +1,366 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate chain configurations. + +use std::borrow::Cow; +use std::collections::HashMap; +use std::fs::File; +use std::path::PathBuf; +use std::rc::Rc; +use serde::{Serialize, Deserialize}; +use sp_core::storage::{StorageKey, StorageData, ChildInfo, Storage, StorageChild}; +use sp_runtime::BuildStorage; +use serde_json as json; +use crate::RuntimeGenesis; +use sc_network::Multiaddr; +use sc_telemetry::TelemetryEndpoints; + +enum GenesisSource { + File(PathBuf), + Binary(Cow<'static, [u8]>), + Factory(Rc G>), +} + +impl Clone for GenesisSource { + fn clone(&self) -> Self { + match *self { + GenesisSource::File(ref path) => GenesisSource::File(path.clone()), + GenesisSource::Binary(ref d) => GenesisSource::Binary(d.clone()), + GenesisSource::Factory(ref f) => GenesisSource::Factory(f.clone()), + } + } +} + +impl GenesisSource { + fn resolve(&self) -> Result, String> { + #[derive(Serialize, Deserialize)] + struct GenesisContainer { + genesis: Genesis, + } + + match self { + GenesisSource::File(path) => { + let file = File::open(path) + .map_err(|e| format!("Error opening spec file: {}", e))?; + let genesis: GenesisContainer = json::from_reader(file) + .map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(genesis.genesis) + }, + GenesisSource::Binary(buf) => { + let genesis: GenesisContainer = json::from_reader(buf.as_ref()) + .map_err(|e| format!("Error parsing embedded file: {}", e))?; + Ok(genesis.genesis) + }, + GenesisSource::Factory(f) => Ok(Genesis::Runtime(f())), + } + } +} + +impl<'a, G: RuntimeGenesis, E> BuildStorage for &'a ChainSpec { + fn build_storage(&self) -> Result { + match self.genesis.resolve()? { + Genesis::Runtime(gc) => gc.build_storage(), + Genesis::Raw(RawGenesis { top: map, children: children_map }) => Ok(Storage { + top: map.into_iter().map(|(k, v)| (k.0, v.0)).collect(), + children: children_map.into_iter().map(|(sk, child_content)| { + let child_info = ChildInfo::resolve_child_info( + child_content.child_type, + child_content.child_info.as_slice(), + ).expect("chain spec contains correct content").to_owned(); + ( + sk.0, + StorageChild { + data: child_content.data.into_iter().map(|(k, v)| (k.0, v.0)).collect(), + child_info, + }, + ) + }).collect(), + }), + } + } + + fn assimilate_storage( + &self, + _: &mut Storage, + ) -> Result<(), String> { + Err("`assimilate_storage` not implemented for `ChainSpec`.".into()) + } +} + +type GenesisStorage = HashMap; + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +struct ChildRawStorage { + data: GenesisStorage, + child_info: Vec, + child_type: u32, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +/// Storage content for genesis block. +struct RawGenesis { + pub top: GenesisStorage, + pub children: HashMap, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +enum Genesis { + Runtime(G), + Raw(RawGenesis), +} + +/// A configuration of a client. Does not include runtime storage initialization. +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +struct ClientSpec { + pub name: String, + pub id: String, + pub boot_nodes: Vec, + pub telemetry_endpoints: Option, + pub protocol_id: Option, + pub properties: Option, + #[serde(flatten)] + pub extensions: E, + // Never used, left only for backward compatibility. + consensus_engine: (), + #[serde(skip_serializing)] + genesis: serde::de::IgnoredAny, +} + +/// Arbitrary properties defined in chain spec as a JSON object +pub type Properties = json::map::Map; + +/// A type denoting empty extensions. +/// +/// We use `Option` here since `()` is not flattenable by serde. +pub type NoExtension = Option<()>; + +/// A configuration of a chain. Can be used to build a genesis block. +pub struct ChainSpec { + client_spec: ClientSpec, + genesis: GenesisSource, +} + +impl Clone for ChainSpec { + fn clone(&self) -> Self { + ChainSpec { + client_spec: self.client_spec.clone(), + genesis: self.genesis.clone(), + } + } +} + +impl ChainSpec { + /// A list of bootnode addresses. + pub fn boot_nodes(&self) -> &[String] { + &self.client_spec.boot_nodes + } + + /// Spec name. + pub fn name(&self) -> &str { + &self.client_spec.name + } + + /// Spec id. + pub fn id(&self) -> &str { + &self.client_spec.id + } + + /// Telemetry endpoints (if any) + pub fn telemetry_endpoints(&self) -> &Option { + &self.client_spec.telemetry_endpoints + } + + /// Network protocol id. + pub fn protocol_id(&self) -> Option<&str> { + self.client_spec.protocol_id.as_ref().map(String::as_str) + } + + /// Additional loosly-typed properties of the chain. + /// + /// Returns an empty JSON object if 'properties' not defined in config + pub fn properties(&self) -> Properties { + self.client_spec.properties.as_ref().unwrap_or(&json::map::Map::new()).clone() + } + + /// Add a bootnode to the list. + pub fn add_boot_node(&mut self, addr: Multiaddr) { + self.client_spec.boot_nodes.push(addr.to_string()) + } + + /// Returns a reference to defined chain spec extensions. + pub fn extensions(&self) -> &E { + &self.client_spec.extensions + } + + /// Create hardcoded spec. + pub fn from_genesis G + 'static>( + name: &str, + id: &str, + constructor: F, + boot_nodes: Vec, + telemetry_endpoints: Option, + protocol_id: Option<&str>, + properties: Option, + extensions: E, + ) -> Self { + let client_spec = ClientSpec { + name: name.to_owned(), + id: id.to_owned(), + boot_nodes, + telemetry_endpoints, + protocol_id: protocol_id.map(str::to_owned), + properties, + extensions, + consensus_engine: (), + genesis: Default::default(), + }; + + ChainSpec { + client_spec, + genesis: GenesisSource::Factory(Rc::new(constructor)), + } + } +} + +impl ChainSpec { + /// Parse json content into a `ChainSpec` + pub fn from_json_bytes(json: impl Into>) -> Result { + let json = json.into(); + let client_spec = json::from_slice(json.as_ref()) + .map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(ChainSpec { + client_spec, + genesis: GenesisSource::Binary(json), + }) + } + + /// Parse json file into a `ChainSpec` + pub fn from_json_file(path: PathBuf) -> Result { + let file = File::open(&path) + .map_err(|e| format!("Error opening spec file: {}", e))?; + let client_spec = json::from_reader(file) + .map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(ChainSpec { + client_spec, + genesis: GenesisSource::File(path), + }) + } +} + +impl ChainSpec { + /// Dump to json string. + pub fn to_json(self, raw: bool) -> Result { + #[derive(Serialize, Deserialize)] + struct Container { + #[serde(flatten)] + client_spec: ClientSpec, + genesis: Genesis, + + }; + let genesis = match (raw, self.genesis.resolve()?) { + (true, Genesis::Runtime(g)) => { + let storage = g.build_storage()?; + let top = storage.top.into_iter() + .map(|(k, v)| (StorageKey(k), StorageData(v))) + .collect(); + let children = storage.children.into_iter() + .map(|(sk, child)| { + let info = child.child_info.as_ref(); + let (info, ci_type) = info.info(); + ( + StorageKey(sk), + ChildRawStorage { + data: child.data.into_iter() + .map(|(k, v)| (StorageKey(k), StorageData(v))) + .collect(), + child_info: info.to_vec(), + child_type: ci_type, + }, + )}) + .collect(); + + Genesis::Raw(RawGenesis { top, children }) + }, + (_, genesis) => genesis, + }; + let container = Container { + client_spec: self.client_spec, + genesis, + }; + json::to_string_pretty(&container) + .map_err(|e| format!("Error generating spec json: {}", e)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug, Serialize, Deserialize)] + struct Genesis(HashMap); + + impl BuildStorage for Genesis { + fn assimilate_storage( + &self, + storage: &mut Storage, + ) -> Result<(), String> { + storage.top.extend( + self.0.iter().map(|(a, b)| (a.clone().into_bytes(), b.clone().into_bytes())) + ); + Ok(()) + } + } + + type TestSpec = ChainSpec; + + #[test] + fn should_deserailize_example_chain_spec() { + let spec1 = TestSpec::from_json_bytes(Cow::Owned( + include_bytes!("../res/chain_spec.json").to_vec() + )).unwrap(); + let spec2 = TestSpec::from_json_file( + PathBuf::from("./res/chain_spec.json") + ).unwrap(); + + assert_eq!(spec1.to_json(false), spec2.to_json(false)); + } + + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + struct Extension1 { + my_property: String, + } + + type TestSpec2 = ChainSpec; + + #[test] + fn should_deserialize_chain_spec_with_extensions() { + let spec = TestSpec2::from_json_bytes(Cow::Owned( + include_bytes!("../res/chain_spec2.json").to_vec() + )).unwrap(); + + assert_eq!(spec.extensions().my_property, "Test Extension"); + } +} diff --git a/core/chain-spec/src/extension.rs b/client/chain-spec/src/extension.rs similarity index 95% rename from core/chain-spec/src/extension.rs rename to client/chain-spec/src/extension.rs index bf98ced04d63f..fb73eec9d8abd 100644 --- a/core/chain-spec/src/extension.rs +++ b/client/chain-spec/src/extension.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -253,9 +253,9 @@ impl Extension for Forks where #[cfg(test)] mod tests { use super::*; - use chain_spec_derive::{ChainSpecGroup, ChainSpecExtension}; + use sc_chain_spec_derive::{ChainSpecGroup, ChainSpecExtension}; // Make the proc macro work for tests and doc tests. - use crate as substrate_chain_spec; + use crate as sc_chain_spec; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup)] #[serde(deny_unknown_fields)] @@ -289,7 +289,9 @@ mod tests { fn forks_should_work_correctly() { use super::Extension as _ ; - let ext: Ext2 = serde_json::from_str(r#" + // We first need to deserialize into a `Value` because of the following bug: + // https://github.com/serde-rs/json/issues/505 + let ext_val: serde_json::Value = serde_json::from_str(r#" { "test": 11, "forkable": { @@ -314,6 +316,8 @@ mod tests { } "#).unwrap(); + let ext: Ext2 = serde_json::from_value(ext_val).unwrap(); + assert_eq!(ext.get::(), Some(&Extension1 { test: 11 })); diff --git a/client/chain-spec/src/lib.rs b/client/chain-spec/src/lib.rs new file mode 100644 index 0000000000000..cce9d5007f891 --- /dev/null +++ b/client/chain-spec/src/lib.rs @@ -0,0 +1,123 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate chain configurations. +//! +//! This crate contains structs and utilities to declare +//! a runtime-specific configuration file (a.k.a chain spec). +//! +//! Basic chain spec type containing all required parameters is +//! [`ChainSpec`](./struct.ChainSpec.html). It can be extended with +//! additional options that contain configuration specific to your chain. +//! Usually the extension is going to be an amalgamate of types exposed +//! by Substrate core modules. To allow the core modules to retrieve +//! their configuration from your extension you should use `ChainSpecExtension` +//! macro exposed by this crate. +//! +//! ```rust +//! use std::collections::HashMap; +//! use serde::{Serialize, Deserialize}; +//! use sc_chain_spec::{ChainSpec, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] +//! pub struct MyExtension { +//! pub known_blocks: HashMap, +//! } +//! +//! pub type MyChainSpec = ChainSpec; +//! ``` +//! +//! Some parameters may require different values depending on the +//! current blockchain height (a.k.a. forks). You can use `ChainSpecGroup` +//! macro and provided [`Forks`](./struct.Forks.html) structure to put +//! such parameters to your chain spec. +//! This will allow to override a single parameter starting at specific +//! block number. +//! +//! ```rust +//! use serde::{Serialize, Deserialize}; +//! use sc_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct ClientParams { +//! max_block_size: usize, +//! max_extrinsic_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct PoolParams { +//! max_transaction_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +//! pub struct Extension { +//! pub client: ClientParams, +//! pub pool: PoolParams, +//! } +//! +//! pub type BlockNumber = u64; +//! +//! /// A chain spec supporting forkable `ClientParams`. +//! pub type MyChainSpec1 = ChainSpec>; +//! +//! /// A chain spec supporting forkable `Extension`. +//! pub type MyChainSpec2 = ChainSpec>; +//! ``` +//! +//! It's also possible to have a set of parameters that is allowed to change +//! with block numbers (i.e. is forkable), and another set that is not subject to changes. +//! This is also possible by declaring an extension that contains `Forks` within it. +//! +//! +//! ```rust +//! use serde::{Serialize, Deserialize}; +//! use sc_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct ClientParams { +//! max_block_size: usize, +//! max_extrinsic_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct PoolParams { +//! max_transaction_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] +//! pub struct Extension { +//! pub client: ClientParams, +//! #[forks] +//! pub pool: Forks, +//! } +//! +//! pub type MyChainSpec = ChainSpec; +//! ``` + + +mod chain_spec; +mod extension; + +pub use chain_spec::{ChainSpec, Properties, NoExtension}; +pub use extension::{Group, Fork, Forks, Extension}; +pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; + +use serde::{Serialize, de::DeserializeOwned}; +use sp_runtime::BuildStorage; + +/// A set of traits for the runtime genesis config. +pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} +impl RuntimeGenesis for T {} diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml new file mode 100644 index 0000000000000..460cc2a05a32e --- /dev/null +++ b/client/cli/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "sc-cli" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Substrate CLI interface." +edition = "2018" + +[dependencies] +clap = "2.33.0" +derive_more = "0.99.2" +env_logger = "0.7.0" +log = "0.4.8" +atty = "0.2.13" +regex = "1.3.1" +time = "0.1.42" +ansi_term = "0.12.1" +lazy_static = "1.4.0" +app_dirs = "1.2.1" +tokio = "0.2.1" +futures = { version = "0.3.1", features = ["compat"] } +fdlimit = "0.1.1" +serde_json = "1.0.41" +sp-panic-handler = { version = "2.0.0", path = "../../primitives/panic-handler" } +sc-client-api = { version = "2.0.0", path = "../api" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +sc-network = { version = "0.8", path = "../network" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sc-service = { version = "2.0.0", default-features = false, path = "../service" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } +sc-telemetry = { version = "2.0.0", path = "../telemetry" } +sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } +names = "0.11.0" +structopt = "=0.3.7" +sc-tracing = { version = "2.0.0", path = "../tracing" } + +[target.'cfg(not(target_os = "unknown"))'.dependencies] +rpassword = "4.0.1" + +[dev-dependencies] +tempfile = "3.1.0" + +[features] +wasmtime = [ + "sc-service/wasmtime", +] diff --git a/core/cli/README.adoc b/client/cli/README.adoc similarity index 100% rename from core/cli/README.adoc rename to client/cli/README.adoc diff --git a/client/cli/src/error.rs b/client/cli/src/error.rs new file mode 100644 index 0000000000000..074cb353c3a0a --- /dev/null +++ b/client/cli/src/error.rs @@ -0,0 +1,64 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Initialization errors. + +/// Result type alias for the CLI. +pub type Result = std::result::Result; + +/// Error type for the CLI. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Io error + Io(std::io::Error), + /// Cli error + Cli(clap::Error), + /// Service error + Service(sc_service::Error), + /// Client error + Client(sp_blockchain::Error), + /// Input error + #[from(ignore)] + Input(String), + /// Invalid listen multiaddress + #[display(fmt="Invalid listen multiaddress")] + InvalidListenMultiaddress, + /// Other uncategorized error. + #[from(ignore)] + Other(String), +} + +/// Must be implemented explicitly because `derive_more` won't generate this +/// case due to conflicting derive for `Other(String)`. +impl std::convert::From for Error { + fn from(s: String) -> Error { + Error::Input(s) + } +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Io(ref err) => Some(err), + Error::Cli(ref err) => Some(err), + Error::Service(ref err) => Some(err), + Error::Client(ref err) => Some(err), + Error::Input(_) => None, + Error::InvalidListenMultiaddress => None, + Error::Other(_) => None, + } + } +} diff --git a/core/cli/src/execution_strategy.rs b/client/cli/src/execution_strategy.rs similarity index 95% rename from core/cli/src/execution_strategy.rs rename to client/cli/src/execution_strategy.rs index 93236227e5d64..fe353da80ddef 100644 --- a/core/cli/src/execution_strategy.rs +++ b/client/cli/src/execution_strategy.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/client/cli/src/informant.rs b/client/cli/src/informant.rs new file mode 100644 index 0000000000000..de7c376f09fee --- /dev/null +++ b/client/cli/src/informant.rs @@ -0,0 +1,89 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Console informant. Prints sync progress and block events. Runs on the calling thread. + +use sc_client_api::BlockchainEvents; +use futures::{StreamExt, TryStreamExt, FutureExt, future, compat::Stream01CompatExt}; +use log::{info, warn, trace}; +use sp_runtime::traits::Header; +use sc_service::AbstractService; +use std::time::Duration; + +mod display; + +/// Creates an informant in the form of a `Future` that must be polled regularly. +pub fn build(service: &impl AbstractService) -> impl futures::Future { + let client = service.client(); + + let mut display = display::InformantDisplay::new(); + + let display_notifications = service + .network_status(Duration::from_millis(5000)) + .compat() + .try_for_each(move |(net_status, _)| { + let info = client.usage_info(); + if let Some(ref usage) = info.usage { + trace!(target: "usage", "Usage statistics: {}", usage); + } else { + trace!(target: "usage", "Usage statistics not displayed as backend does not provide it") + } + display.display(&info, net_status); + future::ok(()) + }); + + let client = service.client(); + let mut last_best = { + let info = client.usage_info(); + Some((info.chain.best_number, info.chain.best_hash)) + }; + + let display_block_import = client.import_notification_stream().for_each(move |n| { + // detect and log reorganizations. + if let Some((ref last_num, ref last_hash)) = last_best { + if n.header.parent_hash() != last_hash && n.is_new_best { + let maybe_ancestor = sp_blockchain::lowest_common_ancestor( + &*client, + last_hash.clone(), + n.hash, + ); + + match maybe_ancestor { + Ok(ref ancestor) if ancestor.hash != *last_hash => info!( + "Reorg from #{},{} to #{},{}, common ancestor #{},{}", + last_num, last_hash, + n.header.number(), n.hash, + ancestor.number, ancestor.hash, + ), + Ok(_) => {}, + Err(e) => warn!("Error computing tree route: {}", e), + } + } + } + + if n.is_new_best { + last_best = Some((n.header.number().clone(), n.hash.clone())); + } + + info!(target: "substrate", "Imported #{} ({})", n.header.number(), n.hash); + future::ready(()) + }); + + future::join( + display_notifications, + display_block_import + ).map(|_| ()) +} diff --git a/core/cli/src/informant/display.rs b/client/cli/src/informant/display.rs similarity index 95% rename from core/cli/src/informant/display.rs rename to client/cli/src/informant/display.rs index c7cf9bfc930b9..199635e7c7883 100644 --- a/core/cli/src/informant/display.rs +++ b/client/cli/src/informant/display.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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 . use ansi_term::Colour; -use client::ClientInfo; +use sc_client_api::ClientInfo; use log::info; -use network::SyncState; -use sr_primitives::traits::{Block as BlockT, CheckedDiv, NumberFor, Zero, Saturating}; -use service::NetworkStatus; +use sc_network::SyncState; +use sp_runtime::traits::{Block as BlockT, CheckedDiv, NumberFor, Zero, Saturating}; +use sc_service::NetworkStatus; use std::{convert::{TryFrom, TryInto}, fmt, time}; /// State of the informant display system. diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs new file mode 100644 index 0000000000000..620a90c514d00 --- /dev/null +++ b/client/cli/src/lib.rs @@ -0,0 +1,1256 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate CLI library. + +#![warn(missing_docs)] +#![warn(unused_extern_crates)] + +#[macro_use] +mod traits; +mod params; +mod execution_strategy; +pub mod error; +pub mod informant; + +use sc_client_api::execution_extensions::ExecutionStrategies; +use sc_service::{ + config::{Configuration, DatabaseConfig, KeystoreConfig}, + ServiceBuilderCommand, + RuntimeGenesis, ChainSpecExtension, PruningMode, ChainSpec, +}; +use sc_network::{ + self, + multiaddr::Protocol, + config::{ + NetworkConfiguration, TransportConfig, NonReservedPeerMode, NodeKeyConfig, build_multiaddr + }, +}; +use sp_core::H256; + +use std::{ + io::{Write, Read, Seek, Cursor, stdin, stdout, ErrorKind}, iter, fmt::Debug, fs::{self, File}, + net::{Ipv4Addr, SocketAddr}, path::{Path, PathBuf}, str::FromStr, pin::Pin, task::Poll +}; + +use names::{Generator, Name}; +use regex::Regex; +use structopt::{StructOpt, StructOptInternal, clap::AppSettings}; +#[doc(hidden)] +pub use structopt::clap::App; +use params::{ + RunCmd, PurgeChainCmd, RevertCmd, ImportBlocksCmd, ExportBlocksCmd, BuildSpecCmd, + NetworkConfigurationParams, MergeParameters, TransactionPoolParams, + NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd, +}; +pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy}; +pub use traits::GetSharedParams; +use app_dirs::{AppInfo, AppDataType}; +use log::info; +use lazy_static::lazy_static; +use futures::{Future, compat::Future01CompatExt, executor::block_on}; +use sc_telemetry::TelemetryEndpoints; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; + +/// default sub directory to store network config +const DEFAULT_NETWORK_CONFIG_PATH : &'static str = "network"; +/// default sub directory to store database +const DEFAULT_DB_CONFIG_PATH : &'static str = "db"; +/// default sub directory for the key store +const DEFAULT_KEYSTORE_CONFIG_PATH : &'static str = "keystore"; + +/// The maximum number of characters for a node name. +const NODE_NAME_MAX_LENGTH: usize = 32; + +/// The file name of the node's Ed25519 secret key inside the chain-specific +/// network config directory, if neither `--node-key` nor `--node-key-file` +/// is specified in combination with `--node-key-type=ed25519`. +const NODE_KEY_ED25519_FILE: &str = "secret_ed25519"; + +/// Executable version. Used to pass version information from the root crate. +#[derive(Clone)] +pub struct VersionInfo { + /// Implementaiton name. + pub name: &'static str, + /// Implementation version. + pub version: &'static str, + /// SCM Commit hash. + pub commit: &'static str, + /// Executable file name. + pub executable_name: &'static str, + /// Executable file description. + pub description: &'static str, + /// Executable file author. + pub author: &'static str, + /// Support URL. + pub support_url: &'static str, +} + +/// Something that can be converted into an exit signal. +pub trait IntoExit { + /// Exit signal type. + type Exit: Future + Unpin + Send + 'static; + /// Convert into exit signal. + fn into_exit(self) -> Self::Exit; +} + +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 < NODE_NAME_MAX_LENGTH { + break node_name + } + }; + + result +} + +/// Load spec give shared params and spec factory. +pub fn load_spec(cli: &SharedParams, factory: F) -> error::Result> where + G: RuntimeGenesis, + E: ChainSpecExtension, + F: FnOnce(&str) -> Result>, String>, +{ + let chain_key = get_chain_key(cli); + let spec = match factory(&chain_key)? { + Some(spec) => spec, + None => ChainSpec::from_json_file(PathBuf::from(chain_key))? + }; + Ok(spec) +} + +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") + ) +} + +/// Check whether a node name is considered as valid +fn is_node_name_valid(_name: &str) -> Result<(), &str> { + let name = _name.to_string(); + if name.chars().count() >= NODE_NAME_MAX_LENGTH { + return Err("Node name too long"); + } + + let invalid_chars = r"[\\.@]"; + let re = Regex::new(invalid_chars).unwrap(); + if re.is_match(&name) { + return Err("Node name should not contain invalid chars such as '.' and '@'"); + } + + let invalid_patterns = r"(https?:\\/+)?(www)+"; + let re = Regex::new(invalid_patterns).unwrap(); + if re.is_match(&name) { + return Err("Node name should not contain urls"); + } + + Ok(()) +} + +/// Parse command line interface arguments and prepares the command for execution. +/// +/// Before returning, this function performs various initializations, such as initializing the +/// panic handler and the logger, or increasing the limit for file descriptors. +/// +/// # Remarks +/// +/// `CC` is a custom subcommand. This needs to be an `enum`! If no custom subcommand is required, +/// `NoCustom` can be used as type here. +/// +/// `RP` are custom parameters for the run command. This needs to be a `struct`! The custom +/// parameters are visible to the user as if they were normal run command parameters. If no custom +/// parameters are required, `NoCustom` can be used as type here. +pub fn parse_and_prepare<'a, CC, RP, I>( + version: &'a VersionInfo, + impl_name: &'static str, + args: I, +) -> ParseAndPrepare<'a, CC, RP> +where + CC: StructOpt + Clone + GetSharedParams, + RP: StructOpt + Clone + StructOptInternal, + I: IntoIterator, + ::Item: Into + Clone, +{ + let full_version = sc_service::config::full_version_from_strs( + version.version, + version.commit + ); + + sp_panic_handler::set(version.support_url, &full_version); + let matches = CoreParams::::clap() + .name(version.executable_name) + .author(version.author) + .about(version.description) + .version(&(full_version + "\n")[..]) + .setting(AppSettings::GlobalVersion) + .setting(AppSettings::ArgsNegateSubcommands) + .setting(AppSettings::SubcommandsNegateReqs) + .get_matches_from(args); + let cli_args = CoreParams::::from_clap(&matches); + fdlimit::raise_fd_limit(); + + let args = match cli_args { + params::CoreParams::Run(params) => ParseAndPrepare::Run( + ParseAndPrepareRun { params, impl_name, version } + ), + params::CoreParams::BuildSpec(params) => ParseAndPrepare::BuildSpec( + ParseAndPrepareBuildSpec { params, version } + ), + params::CoreParams::ExportBlocks(params) => ParseAndPrepare::ExportBlocks( + ParseAndPrepareExport { params, version } + ), + params::CoreParams::ImportBlocks(params) => ParseAndPrepare::ImportBlocks( + ParseAndPrepareImport { params, version } + ), + params::CoreParams::CheckBlock(params) => ParseAndPrepare::CheckBlock( + CheckBlock { params, version } + ), + params::CoreParams::PurgeChain(params) => ParseAndPrepare::PurgeChain( + ParseAndPreparePurge { params, version } + ), + params::CoreParams::Revert(params) => ParseAndPrepare::RevertChain( + ParseAndPrepareRevert { params, version } + ), + params::CoreParams::Custom(params) => ParseAndPrepare::CustomCommand(params), + }; + init_logger(args.shared_params().and_then(|p| p.log.as_ref()).map(|v| v.as_ref()).unwrap_or("")); + args +} + +/// Returns a string displaying the node role, special casing the sentry mode +/// (returning `SENTRY`), since the node technically has an `AUTHORITY` role but +/// doesn't participate. +pub fn display_role(config: &Configuration) -> String { + if config.sentry_mode { + "SENTRY".to_string() + } else { + format!("{:?}", config.roles) + } +} + +/// Output of calling `parse_and_prepare`. +#[must_use] +pub enum ParseAndPrepare<'a, CC, RP> { + /// Command ready to run the main client. + Run(ParseAndPrepareRun<'a, RP>), + /// Command ready to build chain specs. + BuildSpec(ParseAndPrepareBuildSpec<'a>), + /// Command ready to export the chain. + ExportBlocks(ParseAndPrepareExport<'a>), + /// Command ready to import the chain. + ImportBlocks(ParseAndPrepareImport<'a>), + /// Command to check a block. + CheckBlock(CheckBlock<'a>), + /// Command ready to purge the chain. + PurgeChain(ParseAndPreparePurge<'a>), + /// Command ready to revert the chain. + RevertChain(ParseAndPrepareRevert<'a>), + /// An additional custom command passed to `parse_and_prepare`. + CustomCommand(CC), +} + +impl<'a, CC, RP> ParseAndPrepare<'a, CC, RP> where CC: GetSharedParams { + /// Return common set of parameters shared by all commands. + pub fn shared_params(&self) -> Option<&SharedParams> { + match self { + ParseAndPrepare::Run(c) => Some(&c.params.left.shared_params), + ParseAndPrepare::BuildSpec(c) => Some(&c.params.shared_params), + ParseAndPrepare::ExportBlocks(c) => Some(&c.params.shared_params), + ParseAndPrepare::ImportBlocks(c) => Some(&c.params.shared_params), + ParseAndPrepare::CheckBlock(c) => Some(&c.params.shared_params), + ParseAndPrepare::PurgeChain(c) => Some(&c.params.shared_params), + ParseAndPrepare::RevertChain(c) => Some(&c.params.shared_params), + ParseAndPrepare::CustomCommand(c) => c.shared_params(), + } + } +} + +/// Command ready to run the main client. +pub struct ParseAndPrepareRun<'a, RP> { + params: MergeParameters, + impl_name: &'static str, + version: &'a VersionInfo, +} + +impl<'a, RP> ParseAndPrepareRun<'a, RP> { + /// Runs the command and runs the main client. + pub fn run( + self, + spec_factory: S, + exit: Exit, + run_service: RS, + ) -> error::Result<()> + where + S: FnOnce(&str) -> Result>, String>, + E: Into, + RP: StructOpt + Clone, + C: Default, + G: RuntimeGenesis, + CE: ChainSpecExtension, + Exit: IntoExit, + RS: FnOnce(Exit, RunCmd, RP, Configuration) -> Result<(), E> + { + let config = create_run_node_config( + self.params.left.clone(), spec_factory, self.impl_name, self.version, + )?; + + run_service(exit, self.params.left, self.params.right, config).map_err(Into::into) + } +} + +/// Command ready to build chain specs. +pub struct ParseAndPrepareBuildSpec<'a> { + params: BuildSpecCmd, + version: &'a VersionInfo, +} + +impl<'a> ParseAndPrepareBuildSpec<'a> { + /// Runs the command and build the chain specs. + pub fn run( + self, + spec_factory: S + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + { + info!("Building chain spec"); + let raw_output = self.params.raw; + let mut spec = load_spec(&self.params.shared_params, spec_factory)?; + + if spec.boot_nodes().is_empty() && !self.params.disable_default_bootnode { + let base_path = base_path(&self.params.shared_params, self.version); + let cfg = sc_service::Configuration::::default_with_spec_and_base_path( + spec.clone(), + Some(base_path), + ); + let node_key = node_key_config( + self.params.node_key_params, + &Some(cfg.in_chain_config_dir(DEFAULT_NETWORK_CONFIG_PATH).expect("We provided a base_path")) + )?; + let keys = node_key.into_keypair()?; + let peer_id = keys.public().into_peer_id(); + let addr = build_multiaddr![ + Ip4([127, 0, 0, 1]), + Tcp(30333u16), + P2p(peer_id) + ]; + spec.add_boot_node(addr) + } + + let json = sc_service::chain_ops::build_spec(spec, raw_output)?; + + print!("{}", json); + + Ok(()) + } +} + +/// Command ready to export the chain. +pub struct ParseAndPrepareExport<'a> { + params: ExportBlocksCmd, + version: &'a VersionInfo, +} + +impl<'a> ParseAndPrepareExport<'a> { + /// Runs the command and exports from the chain. + pub fn run_with_builder( + self, + builder: F, + spec_factory: S, + exit: Exit, + ) -> error::Result<()> + where S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, + B: ServiceBuilderCommand, + <<<::Block as BlockT>::Header as HeaderT> + ::Number as FromStr>::Err: Debug, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + Exit: IntoExit + { + let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; + + if let DatabaseConfig::Path { ref path, .. } = &config.database { + info!("DB path: {}", path.display()); + } + let from = self.params.from.and_then(|f| f.parse().ok()).unwrap_or(1); + let to = self.params.to.and_then(|t| t.parse().ok()); + + let json = self.params.json; + + let file: Box = match self.params.output { + Some(filename) => Box::new(File::create(filename)?), + None => Box::new(stdout()), + }; + + // Note: while we would like the user to handle the exit themselves, we handle it here + // for backwards compatibility reasons. + let (exit_send, exit_recv) = std::sync::mpsc::channel(); + let exit = exit.into_exit(); + std::thread::spawn(move || { + block_on(exit); + let _ = exit_send.send(()); + }); + + let mut export_fut = builder(config)? + .export_blocks(file, from.into(), to, json) + .compat(); + let fut = futures::future::poll_fn(|cx| { + if exit_recv.try_recv().is_ok() { + return Poll::Ready(Ok(())); + } + Pin::new(&mut export_fut).poll(cx) + }); + + let mut runtime = tokio::runtime::Runtime::new().unwrap(); + runtime.block_on(fut)?; + Ok(()) + } +} + +/// Command ready to import the chain. +pub struct ParseAndPrepareImport<'a> { + params: ImportBlocksCmd, + version: &'a VersionInfo, +} + +impl<'a> ParseAndPrepareImport<'a> { + /// Runs the command and imports to the chain. + pub fn run_with_builder( + self, + builder: F, + spec_factory: S, + exit: Exit, + ) -> error::Result<()> + where S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, + B: ServiceBuilderCommand, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + Exit: IntoExit + { + let mut config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; + fill_import_params(&mut config, &self.params.import_params, sc_service::Roles::FULL)?; + + let file: Box = match self.params.input { + Some(filename) => Box::new(File::open(filename)?), + None => { + let mut buffer = Vec::new(); + stdin().read_to_end(&mut buffer)?; + Box::new(Cursor::new(buffer)) + }, + }; + + // Note: while we would like the user to handle the exit themselves, we handle it here + // for backwards compatibility reasons. + let (exit_send, exit_recv) = std::sync::mpsc::channel(); + let exit = exit.into_exit(); + std::thread::spawn(move || { + block_on(exit); + let _ = exit_send.send(()); + }); + + let mut import_fut = builder(config)? + .import_blocks(file, false) + .compat(); + let fut = futures::future::poll_fn(|cx| { + if exit_recv.try_recv().is_ok() { + return Poll::Ready(Ok(())); + } + Pin::new(&mut import_fut).poll(cx) + }); + + let mut runtime = tokio::runtime::Runtime::new().unwrap(); + runtime.block_on(fut)?; + Ok(()) + } +} + +/// Command to check a block. +pub struct CheckBlock<'a> { + params: CheckBlockCmd, + version: &'a VersionInfo, +} + +impl<'a> CheckBlock<'a> { + /// Runs the command and imports to the chain. + pub fn run_with_builder( + self, + builder: F, + spec_factory: S, + _exit: Exit, + ) -> error::Result<()> + where S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, + B: ServiceBuilderCommand, + <::Block as BlockT>::Hash: FromStr, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + Exit: IntoExit + { + let mut config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; + fill_import_params(&mut config, &self.params.import_params, sc_service::Roles::FULL)?; + + let input = if self.params.input.starts_with("0x") { &self.params.input[2..] } else { &self.params.input[..] }; + let block_id = match FromStr::from_str(input) { + Ok(hash) => BlockId::hash(hash), + Err(_) => match self.params.input.parse::() { + Ok(n) => BlockId::number((n as u32).into()), + Err(_) => return Err(error::Error::Input("Invalid hash or number specified".into())), + } + }; + + let start = std::time::Instant::now(); + let check = builder(config)? + .check_block(block_id) + .compat(); + let mut runtime = tokio::runtime::Runtime::new().unwrap(); + runtime.block_on(check)?; + println!("Completed in {} ms.", start.elapsed().as_millis()); + Ok(()) + } +} + +/// Command ready to purge the chain. +pub struct ParseAndPreparePurge<'a> { + params: PurgeChainCmd, + version: &'a VersionInfo, +} + +impl<'a> ParseAndPreparePurge<'a> { + /// Runs the command and purges the chain. + pub fn run( + self, + spec_factory: S + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + G: RuntimeGenesis, + E: ChainSpecExtension, + { + let config = create_config_with_db_path::<(), _, _, _>( + spec_factory, &self.params.shared_params, self.version + )?; + let db_path = match config.database { + DatabaseConfig::Path { path, .. } => path, + _ => { + eprintln!("Cannot purge custom database implementation"); + return Ok(()); + } + }; + + if !self.params.yes { + print!("Are you sure to remove {:?}? [y/N]: ", &db_path); + 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(()); + }, + } + } + + match fs::remove_dir_all(&db_path) { + Result::Ok(_) => { + println!("{:?} removed.", &db_path); + Ok(()) + }, + Result::Err(ref err) if err.kind() == ErrorKind::NotFound => { + eprintln!("{:?} did not exist.", &db_path); + Ok(()) + }, + Result::Err(err) => Result::Err(err.into()) + } + } +} + +/// Command ready to revert the chain. +pub struct ParseAndPrepareRevert<'a> { + params: RevertCmd, + version: &'a VersionInfo, +} + +impl<'a> ParseAndPrepareRevert<'a> { + /// Runs the command and reverts the chain. + pub fn run_with_builder( + self, + builder: F, + spec_factory: S + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, + B: ServiceBuilderCommand, + <<<::Block as BlockT>::Header as HeaderT> + ::Number as FromStr>::Err: Debug, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + { + let config = create_config_with_db_path( + spec_factory, &self.params.shared_params, self.version + )?; + let blocks = self.params.num.parse()?; + builder(config)?.revert_chain(blocks)?; + Ok(()) + } +} + +/// Create a `NodeKeyConfig` from the given `NodeKeyParams` in the context +/// of an optional network config storage directory. +fn node_key_config

(params: NodeKeyParams, net_config_dir: &Option

) + -> error::Result +where + P: AsRef +{ + match params.node_key_type { + NodeKeyType::Ed25519 => + params.node_key.as_ref().map(parse_ed25519_secret).unwrap_or_else(|| + Ok(params.node_key_file + .or_else(|| net_config_file(net_config_dir, NODE_KEY_ED25519_FILE)) + .map(sc_network::config::Secret::File) + .unwrap_or(sc_network::config::Secret::New))) + .map(NodeKeyConfig::Ed25519) + } +} + +fn net_config_file

(net_config_dir: &Option

, name: &str) -> Option +where + P: AsRef +{ + net_config_dir.as_ref().map(|d| d.as_ref().join(name)) +} + +/// Create an error caused by an invalid node key argument. +fn invalid_node_key(e: impl std::fmt::Display) -> error::Error { + error::Error::Input(format!("Invalid node key: {}", e)) +} + +/// Parse a Ed25519 secret key from a hex string into a `sc_network::Secret`. +fn parse_ed25519_secret(hex: &String) -> error::Result { + H256::from_str(&hex).map_err(invalid_node_key).and_then(|bytes| + sc_network::config::identity::ed25519::SecretKey::from_bytes(bytes) + .map(sc_network::config::Secret::Input) + .map_err(invalid_node_key)) +} + +/// Fill the given `PoolConfiguration` by looking at the cli parameters. +fn fill_transaction_pool_configuration( + options: &mut Configuration, + 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, + config_path: PathBuf, + config: &mut NetworkConfiguration, + client_id: String, + is_dev: bool, +) -> error::Result<()> { + config.boot_nodes.extend(cli.bootnodes.into_iter()); + config.config_path = Some(config_path.to_string_lossy().into()); + config.net_config_path = config.config_path.clone(); + + config.reserved_nodes.extend(cli.reserved_nodes.into_iter()); + if cli.reserved_only { + config.non_reserved_mode = NonReservedPeerMode::Deny; + } + + config.sentry_nodes.extend(cli.sentry_nodes.into_iter()); + + for addr in cli.listen_addr.iter() { + let addr = addr.parse().ok().ok_or(error::Error::InvalidListenMultiaddress)?; + 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.node_key = node_key_config(cli.node_key_params, &config.net_config_path)?; + + config.in_peers = cli.in_peers; + config.out_peers = cli.out_peers; + + config.transport = TransportConfig::Normal { + enable_mdns: !is_dev && !cli.no_mdns, + allow_private_ipv4: !cli.no_private_ipv4, + wasm_external_transport: None, + }; + + config.max_parallel_downloads = cli.max_parallel_downloads; + + Ok(()) +} + +#[cfg(not(target_os = "unknown"))] +fn input_keystore_password() -> Result { + rpassword::read_password_from_tty(Some("Keystore password: ")) + .map_err(|e| format!("{:?}", e)) +} + +/// Fill the password field of the given config instance. +fn fill_config_keystore_password_and_path( + config: &mut sc_service::Configuration, + cli: &RunCmd, +) -> Result<(), String> { + let password = if cli.password_interactive { + #[cfg(not(target_os = "unknown"))] + { + Some(input_keystore_password()?.into()) + } + #[cfg(target_os = "unknown")] + None + } else if let Some(ref file) = cli.password_filename { + Some(fs::read_to_string(file).map_err(|e| format!("{}", e))?.into()) + } else if let Some(ref password) = cli.password { + Some(password.clone().into()) + } else { + None + }; + + let path = cli.keystore_path.clone().or( + config.in_chain_config_dir(DEFAULT_KEYSTORE_CONFIG_PATH) + ); + + config.keystore = KeystoreConfig::Path { + path: path.ok_or_else(|| "No `base_path` provided to create keystore path!")?, + password, + }; + + Ok(()) +} + +/// Put block import CLI params into `config` object. +pub fn fill_import_params( + config: &mut Configuration, + cli: &ImportParams, + role: sc_service::Roles, +) -> error::Result<()> + where + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, +{ + match config.database { + DatabaseConfig::Path { ref mut cache_size, .. } => + *cache_size = Some(cli.database_cache_size), + DatabaseConfig::Custom(_) => {}, + } + + config.state_cache_size = cli.state_cache_size; + + // by default we disable pruning if the node is an authority (i.e. + // `ArchiveAll`), otherwise we keep state for the last 256 blocks. if the + // node is an authority and pruning is enabled explicitly, then we error + // unless `unsafe_pruning` is set. + config.pruning = match &cli.pruning { + Some(ref s) if s == "archive" => PruningMode::ArchiveAll, + None if role == sc_service::Roles::AUTHORITY => PruningMode::ArchiveAll, + None => PruningMode::default(), + Some(s) => { + if role == sc_service::Roles::AUTHORITY && !cli.unsafe_pruning { + return Err(error::Error::Input( + "Validators should run with state pruning disabled (i.e. archive). \ + You can ignore this check with `--unsafe-pruning`.".to_string() + )); + } + + PruningMode::keep_blocks(s.parse() + .map_err(|_| error::Error::Input("Invalid pruning mode specified".to_string()))? + ) + }, + }; + + config.wasm_method = cli.wasm_method.into(); + + let exec = &cli.execution_strategies; + let exec_all_or = |strat: ExecutionStrategy| exec.execution.unwrap_or(strat).into(); + config.execution_strategies = ExecutionStrategies { + syncing: exec_all_or(exec.execution_syncing), + importing: exec_all_or(exec.execution_import_block), + block_construction: exec_all_or(exec.execution_block_construction), + offchain_worker: exec_all_or(exec.execution_offchain_worker), + other: exec_all_or(exec.execution_other), + }; + Ok(()) +} + +fn create_run_node_config( + cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo, +) -> error::Result> +where + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + S: FnOnce(&str) -> Result>, String>, +{ + let mut config = create_config_with_db_path(spec_factory, &cli.shared_params, &version)?; + + fill_config_keystore_password_and_path(&mut config, &cli)?; + + let is_dev = cli.shared_params.dev; + let is_authority = cli.validator || cli.sentry || is_dev || cli.keyring.account.is_some(); + let role = + if cli.light { + sc_service::Roles::LIGHT + } else if is_authority { + sc_service::Roles::AUTHORITY + } else { + sc_service::Roles::FULL + }; + + fill_import_params(&mut config, &cli.import_params, role)?; + + config.impl_name = impl_name; + config.impl_commit = version.commit; + config.impl_version = version.version; + + config.name = match cli.name.or(cli.keyring.account.map(|a| a.to_string())) { + None => generate_node_name(), + Some(name) => name, + }; + match is_node_name_valid(&config.name) { + Ok(_) => (), + Err(msg) => Err( + error::Error::Input( + format!("Invalid node name '{}'. Reason: {}. If unsure, use none.", + config.name, + msg + ) + ) + )? + } + + // set sentry mode (i.e. act as an authority but **never** actively participate) + config.sentry_mode = cli.sentry; + + config.offchain_worker = match (cli.offchain_worker, role) { + (params::OffchainWorkerEnabled::WhenValidating, sc_service::Roles::AUTHORITY) => true, + (params::OffchainWorkerEnabled::Always, _) => true, + (params::OffchainWorkerEnabled::Never, _) => false, + (params::OffchainWorkerEnabled::WhenValidating, _) => false, + }; + + config.roles = role; + config.disable_grandpa = cli.no_grandpa; + + let client_id = config.client_id(); + fill_network_configuration( + cli.network_config, + config.in_chain_config_dir(DEFAULT_NETWORK_CONFIG_PATH).expect("We provided a basepath"), + &mut config.network, + client_id, + is_dev, + )?; + + fill_transaction_pool_configuration(&mut config, cli.pool_config)?; + + config.dev_key_seed = cli.keyring.account + .map(|a| format!("//{}", a)).or_else(|| { + if is_dev { + Some("//Alice".into()) + } else { + None + } + }); + + let rpc_interface: &str = interface_str(cli.rpc_external, cli.unsafe_rpc_external, cli.validator)?; + let ws_interface: &str = interface_str(cli.ws_external, cli.unsafe_ws_external, cli.validator)?; + let grafana_interface: &str = if cli.grafana_external { "0.0.0.0" } else { "127.0.0.1" }; + + 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)?); + config.grafana_port = Some( + parse_address(&format!("{}:{}", grafana_interface, 9955), cli.grafana_port)? + ); + + config.rpc_ws_max_connections = cli.ws_max_connections; + config.rpc_cors = cli.rpc_cors.unwrap_or_else(|| if is_dev { + log::warn!("Running in --dev mode, RPC CORS has been disabled."); + Cors::All + } else { + Cors::List(vec![ + "http://localhost:*".into(), + "http://127.0.0.1:*".into(), + "https://localhost:*".into(), + "https://127.0.0.1:*".into(), + "https://polkadot.js.org".into(), + "https://substrate-ui.parity.io".into(), + ]) + }).into(); + + // Override telemetry + if cli.no_telemetry { + config.telemetry_endpoints = None; + } else if !cli.telemetry_endpoints.is_empty() { + config.telemetry_endpoints = Some(TelemetryEndpoints::new(cli.telemetry_endpoints)); + } + + config.tracing_targets = cli.tracing_targets.into(); + config.tracing_receiver = cli.tracing_receiver.into(); + + // Imply forced authoring on --dev + config.force_authoring = cli.shared_params.dev || cli.force_authoring; + + Ok(config) +} + +fn interface_str( + is_external: bool, + is_unsafe_external: bool, + is_validator: bool, +) -> Result<&'static str, error::Error> { + if is_external && is_validator { + return Err(error::Error::Input("--rpc-external and --ws-external options shouldn't be \ + used if the node is running as a validator. Use `--unsafe-rpc-external` if you understand \ + the risks. See the options description for more information.".to_owned())); + } + + if is_external || is_unsafe_external { + log::warn!("It isn't safe to expose RPC publicly without a proxy server that filters \ + available set of RPC methods."); + + Ok("0.0.0.0") + } else { + Ok("127.0.0.1") + } +} + +/// Creates a configuration including the database path. +pub fn create_config_with_db_path( + spec_factory: S, cli: &SharedParams, version: &VersionInfo, +) -> error::Result> +where + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + S: FnOnce(&str) -> Result>, String>, +{ + let spec = load_spec(cli, spec_factory)?; + let base_path = base_path(cli, version); + + let mut config = sc_service::Configuration::default_with_spec_and_base_path( + spec.clone(), + Some(base_path), + ); + + config.database = DatabaseConfig::Path { + path: config.in_chain_config_dir(DEFAULT_DB_CONFIG_PATH).expect("We provided a base_path."), + cache_size: None, + }; + + Ok(config) +} + +/// Internal trait used to cast to a dynamic type that implements Read and Seek. +trait ReadPlusSeek: Read + Seek {} + +impl ReadPlusSeek for T {} + +fn parse_address( + address: &str, + port: Option, +) -> Result { + let mut address: SocketAddr = address.parse().map_err( + |_| format!("Invalid address: {}", address) + )?; + if let Some(port) = port { + address.set_port(port); + } + + Ok(address) +} + +fn init_logger(pattern: &str) { + use ansi_term::Colour; + + let mut builder = env_logger::Builder::new(); + // Disable info logging by default for some modules: + builder.filter(Some("ws"), log::LevelFilter::Off); + builder.filter(Some("hyper"), log::LevelFilter::Warn); + builder.filter(Some("cranelift_wasm"), log::LevelFilter::Warn); + // Always log the special target `sc_tracing`, overrides global level + builder.filter(Some("sc_tracing"), log::LevelFilter::Info); + // Enable info for others. + builder.filter(None, log::LevelFilter::Info); + + if let Ok(lvl) = std::env::var("RUST_LOG") { + builder.parse_filters(&lvl); + } + + builder.parse_filters(pattern); + let isatty = atty::is(atty::Stream::Stderr); + let enable_color = isatty; + + builder.format(move |buf, record| { + let now = time::now(); + let timestamp = + time::strftime("%Y-%m-%d %H:%M:%S", &now) + .expect("Error formatting log timestamp"); + + 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))); + 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 !isatty && record.level() <= log::Level::Info && atty::is(atty::Stream::Stdout) { + // duplicate INFO/WARN output to console + println!("{}", output); + } + + if !enable_color { + output = kill_color(output.as_ref()); + } + + writeln!(buf, "{}", output) + }); + + if builder.try_init().is_err() { + info!("Not registering Substrate logger, as there is already a global logger registered!"); + } +} + +fn kill_color(s: &str) -> String { + lazy_static! { + static ref RE: Regex = Regex::new("\x1b\\[[^m]+m").expect("Error initializing color regex"); + } + RE.replace_all(s, "").to_string() +} + +#[cfg(test)] +mod tests { + use super::*; + use sc_network::config::identity::ed25519; + + #[test] + fn tests_node_name_good() { + assert!(is_node_name_valid("short name").is_ok()); + } + + #[test] + fn tests_node_name_bad() { + assert!(is_node_name_valid("long names are not very cool for the ui").is_err()); + assert!(is_node_name_valid("Dots.not.Ok").is_err()); + assert!(is_node_name_valid("http://visit.me").is_err()); + assert!(is_node_name_valid("https://visit.me").is_err()); + assert!(is_node_name_valid("www.visit.me").is_err()); + assert!(is_node_name_valid("email@domain").is_err()); + } + + #[test] + fn test_node_key_config_input() { + fn secret_input(net_config_dir: Option) -> error::Result<()> { + NodeKeyType::variants().into_iter().try_for_each(|t| { + let node_key_type = NodeKeyType::from_str(t).unwrap(); + let sk = match node_key_type { + NodeKeyType::Ed25519 => ed25519::SecretKey::generate().as_ref().to_vec() + }; + let params = NodeKeyParams { + node_key_type, + node_key: Some(format!("{:x}", H256::from_slice(sk.as_ref()))), + node_key_file: None + }; + node_key_config(params, &net_config_dir).and_then(|c| match c { + NodeKeyConfig::Ed25519(sc_network::config::Secret::Input(ref ski)) + if node_key_type == NodeKeyType::Ed25519 && + &sk[..] == ski.as_ref() => Ok(()), + _ => Err(error::Error::Input("Unexpected node key config".into())) + }) + }) + } + + assert!(secret_input(None).is_ok()); + assert!(secret_input(Some("x".to_string())).is_ok()); + } + + #[test] + fn test_node_key_config_file() { + fn secret_file(net_config_dir: Option) -> error::Result<()> { + NodeKeyType::variants().into_iter().try_for_each(|t| { + let node_key_type = NodeKeyType::from_str(t).unwrap(); + let tmp = tempfile::Builder::new().prefix("alice").tempdir()?; + let file = tmp.path().join(format!("{}_mysecret", t)).to_path_buf(); + let params = NodeKeyParams { + node_key_type, + node_key: None, + node_key_file: Some(file.clone()) + }; + node_key_config(params, &net_config_dir).and_then(|c| match c { + NodeKeyConfig::Ed25519(sc_network::config::Secret::File(ref f)) + if node_key_type == NodeKeyType::Ed25519 && f == &file => Ok(()), + _ => Err(error::Error::Input("Unexpected node key config".into())) + }) + }) + } + + assert!(secret_file(None).is_ok()); + assert!(secret_file(Some("x".to_string())).is_ok()); + } + + #[test] + fn test_node_key_config_default() { + fn with_def_params(f: F) -> error::Result<()> + where + F: Fn(NodeKeyParams) -> error::Result<()> + { + NodeKeyType::variants().into_iter().try_for_each(|t| { + let node_key_type = NodeKeyType::from_str(t).unwrap(); + f(NodeKeyParams { + node_key_type, + node_key: None, + node_key_file: None + }) + }) + } + + fn no_config_dir() -> error::Result<()> { + with_def_params(|params| { + let typ = params.node_key_type; + node_key_config::(params, &None) + .and_then(|c| match c { + NodeKeyConfig::Ed25519(sc_network::config::Secret::New) + if typ == NodeKeyType::Ed25519 => Ok(()), + _ => Err(error::Error::Input("Unexpected node key config".into())) + }) + }) + } + + fn some_config_dir(net_config_dir: String) -> error::Result<()> { + with_def_params(|params| { + let dir = PathBuf::from(net_config_dir.clone()); + let typ = params.node_key_type; + node_key_config(params, &Some(net_config_dir.clone())) + .and_then(move |c| match c { + NodeKeyConfig::Ed25519(sc_network::config::Secret::File(ref f)) + if typ == NodeKeyType::Ed25519 && + f == &dir.join(NODE_KEY_ED25519_FILE) => Ok(()), + _ => Err(error::Error::Input("Unexpected node key config".into())) + }) + }) + } + + assert!(no_config_dir().is_ok()); + assert!(some_config_dir("x".to_string()).is_ok()); + } + + #[test] + fn keystore_path_is_generated_correctly() { + let chain_spec = ChainSpec::from_genesis( + "test", + "test-id", + || (), + Vec::new(), + None, + None, + None, + None, + ); + + let version_info = VersionInfo { + name: "test", + version: "42", + commit: "234234", + executable_name: "test", + description: "cool test", + author: "universe", + support_url: "com", + }; + + for keystore_path in vec![None, Some("/keystore/path")] { + let mut run_cmds = RunCmd::from_args(); + run_cmds.shared_params.base_path = Some(PathBuf::from("/test/path")); + run_cmds.keystore_path = keystore_path.clone().map(PathBuf::from); + + let node_config = create_run_node_config::<(), _, _, _>( + run_cmds.clone(), + |_| Ok(Some(chain_spec.clone())), + "test", + &version_info, + ).unwrap(); + + let expected_path = match keystore_path { + Some(path) => PathBuf::from(path), + None => PathBuf::from("/test/path/chains/test-id/keystore"), + }; + + assert_eq!(expected_path, node_config.keystore.path().unwrap().to_owned()); + } + } +} diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs new file mode 100644 index 0000000000000..07fbe9b73885c --- /dev/null +++ b/client/cli/src/params.rs @@ -0,0 +1,991 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::traits::GetSharedParams; + +use std::{str::FromStr, path::PathBuf}; +use structopt::{StructOpt, StructOptInternal, clap::{arg_enum, App, AppSettings, SubCommand, Arg}}; + +pub use crate::execution_strategy::ExecutionStrategy; + +impl Into for ExecutionStrategy { + fn into(self) -> sc_client_api::ExecutionStrategy { + match self { + ExecutionStrategy::Native => sc_client_api::ExecutionStrategy::NativeWhenPossible, + ExecutionStrategy::Wasm => sc_client_api::ExecutionStrategy::AlwaysWasm, + ExecutionStrategy::Both => sc_client_api::ExecutionStrategy::Both, + ExecutionStrategy::NativeElseWasm => sc_client_api::ExecutionStrategy::NativeElseWasm, + } + } +} + +arg_enum! { + /// How to execute Wasm runtime code + #[allow(missing_docs)] + #[derive(Debug, Clone, Copy)] + pub enum WasmExecutionMethod { + // Uses an interpreter. + Interpreted, + // Uses a compiled runtime. + Compiled, + } +} + +impl WasmExecutionMethod { + /// Returns list of variants that are not disabled by feature flags. + fn enabled_variants() -> Vec<&'static str> { + Self::variants() + .iter() + .cloned() + .filter(|&name| cfg!(feature = "wasmtime") || name != "Compiled") + .collect() + } +} + +impl Into for WasmExecutionMethod { + fn into(self) -> sc_service::config::WasmExecutionMethod { + match self { + WasmExecutionMethod::Interpreted => sc_service::config::WasmExecutionMethod::Interpreted, + #[cfg(feature = "wasmtime")] + WasmExecutionMethod::Compiled => sc_service::config::WasmExecutionMethod::Compiled, + #[cfg(not(feature = "wasmtime"))] + WasmExecutionMethod::Compiled => panic!( + "Substrate must be compiled with \"wasmtime\" feature for compiled Wasm execution" + ), + } + } +} + +arg_enum! { + /// Whether off-chain workers are enabled. + #[allow(missing_docs)] + #[derive(Debug, Clone)] + pub enum OffchainWorkerEnabled { + Always, + Never, + WhenValidating, + } +} + +/// 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, + + /// Sets a custom logging filter. + #[structopt(short = "l", long = "log", value_name = "LOG_PATTERN")] + pub log: Option, +} + +/// Parameters for block import. +#[derive(Debug, StructOpt, Clone)] +pub struct ImportParams { + /// Specify the state pruning mode, a number of blocks to keep or 'archive'. + /// + /// Default is to keep all block states if the node is running as a + /// validator (i.e. 'archive'), otherwise state is only kept for the last + /// 256 blocks. + #[structopt(long = "pruning", value_name = "PRUNING_MODE")] + pub pruning: Option, + + /// Force start with unsafe pruning settings. + /// + /// When running as a validator it is highly recommended to disable state + /// pruning (i.e. 'archive') which is the default. The node will refuse to + /// start as a validator if pruning is enabled unless this option is set. + #[structopt(long = "unsafe-pruning")] + pub unsafe_pruning: bool, + + /// Method for executing Wasm runtime code. + #[structopt( + long = "wasm-execution", + value_name = "METHOD", + possible_values = &WasmExecutionMethod::enabled_variants(), + case_insensitive = true, + default_value = "Interpreted" + )] + pub wasm_method: WasmExecutionMethod, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub execution_strategies: ExecutionStrategies, + + /// Limit the memory the database cache can use. + #[structopt(long = "db-cache", value_name = "MiB", default_value = "1024")] + pub database_cache_size: u32, + + /// Specify the state cache size. + #[structopt(long = "state-cache-size", value_name = "Bytes", default_value = "67108864")] + pub state_cache_size: usize, +} + +/// 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, + + /// Whether to only allow connections to/from reserved nodes. + /// + /// If you are a validator your node might still connect to other validator + /// nodes regardless of whether they are defined as reserved nodes. + #[structopt(long = "reserved-only")] + pub reserved_only: bool, + + /// Specify a list of sentry node public addresses. + #[structopt( + long = "sentry-nodes", + value_name = "URL", + conflicts_with_all = &[ "sentry" ] + )] + pub sentry_nodes: Vec, + + /// Listen on this multiaddress. + #[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")] + pub listen_addr: Vec, + + /// Specify p2p protocol TCP port. + /// + /// Only used if --listen-addr is not specified. + #[structopt(long = "port", value_name = "PORT")] + pub port: Option, + + /// Allow connecting to private IPv4 addresses (as specified in + /// [RFC1918](https://tools.ietf.org/html/rfc1918)), unless the address was passed with + /// `--reserved-nodes` or `--bootnodes`. + #[structopt(long = "no-private-ipv4")] + pub no_private_ipv4: bool, + + /// Specify the number of outgoing connections we're trying to maintain. + #[structopt(long = "out-peers", value_name = "COUNT", default_value = "25")] + pub out_peers: u32, + + /// Specify the maximum number of incoming connections we're accepting. + #[structopt(long = "in-peers", value_name = "COUNT", default_value = "25")] + pub in_peers: u32, + + /// Disable mDNS discovery. + /// + /// By default, the network will use mDNS to discover other nodes on the + /// local network. This disables it. Automatically implied when using --dev. + #[structopt(long = "no-mdns")] + pub no_mdns: bool, + + /// Maximum number of peers to ask the same blocks in parallel. + /// + /// This allows downlading announced blocks from multiple peers. Decrease to save + /// traffic and risk increased latency. + #[structopt(long = "max-parallel-downloads", value_name = "COUNT", default_value = "5")] + pub max_parallel_downloads: u32, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub node_key_params: NodeKeyParams, +} + +arg_enum! { + #[allow(missing_docs)] + #[derive(Debug, Copy, Clone, PartialEq, Eq)] + pub enum NodeKeyType { + Ed25519 + } +} + +/// Parameters used to create the `NodeKeyConfig`, which determines the keypair +/// used for libp2p networking. +#[derive(Debug, StructOpt, Clone)] +pub struct NodeKeyParams { + /// The secret key to use for libp2p networking. + /// + /// The value is a string that is parsed according to the choice of + /// `--node-key-type` as follows: + /// + /// `ed25519`: + /// The value is parsed as a hex-encoded Ed25519 32 bytes secret key, + /// i.e. 64 hex characters. + /// + /// The value of this option takes precedence over `--node-key-file`. + /// + /// WARNING: Secrets provided as command-line arguments are easily exposed. + /// Use of this option should be limited to development and testing. To use + /// an externally managed secret key, use `--node-key-file` instead. + #[structopt(long = "node-key", value_name = "KEY")] + pub node_key: Option, + + /// The type of secret key to use for libp2p networking. + /// + /// The secret key of the node is obtained as follows: + /// + /// * If the `--node-key` option is given, the value is parsed as a secret key + /// according to the type. See the documentation for `--node-key`. + /// + /// * If the `--node-key-file` option is given, the secret key is read from the + /// specified file. See the documentation for `--node-key-file`. + /// + /// * Otherwise, the secret key is read from a file with a predetermined, + /// type-specific name from the chain-specific network config directory + /// inside the base directory specified by `--base-dir`. If this file does + /// not exist, it is created with a newly generated secret key of the + /// chosen type. + /// + /// The node's secret key determines the corresponding public key and hence the + /// node's peer ID in the context of libp2p. + #[structopt( + long = "node-key-type", + value_name = "TYPE", + possible_values = &NodeKeyType::variants(), + case_insensitive = true, + default_value = "Ed25519" + )] + pub node_key_type: NodeKeyType, + + /// The file from which to read the node's secret key to use for libp2p networking. + /// + /// The contents of the file are parsed according to the choice of `--node-key-type` + /// as follows: + /// + /// `ed25519`: + /// The file must contain an unencoded 32 bytes Ed25519 secret key. + /// + /// If the file does not exist, it is created with a newly generated secret key of + /// the chosen type. + #[structopt(long = "node-key-file", value_name = "FILE")] + pub node_key_file: Option, +} + +/// 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, +} + +arg_enum! { + #[allow(missing_docs)] + #[derive(Debug, Copy, Clone, PartialEq, Eq)] + pub enum TracingReceiver { + Log, + Telemetry, + Grafana, + } +} + +impl Into for TracingReceiver { + fn into(self) -> sc_tracing::TracingReceiver { + match self { + TracingReceiver::Log => sc_tracing::TracingReceiver::Log, + TracingReceiver::Telemetry => sc_tracing::TracingReceiver::Telemetry, + TracingReceiver::Grafana => sc_tracing::TracingReceiver::Grafana, + } + } +} + +/// Execution strategies parameters. +#[derive(Debug, StructOpt, Clone)] +pub struct ExecutionStrategies { + /// The means of execution used when calling into the runtime while syncing blocks. + #[structopt( + long = "execution-syncing", + value_name = "STRATEGY", + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "NativeElseWasm" + )] + pub execution_syncing: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while importing blocks. + #[structopt( + long = "execution-import-block", + value_name = "STRATEGY", + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "NativeElseWasm" + )] + pub execution_import_block: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while constructing blocks. + #[structopt( + long = "execution-block-construction", + value_name = "STRATEGY", + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "Wasm" + )] + pub execution_block_construction: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while using an off-chain worker. + #[structopt( + long = "execution-offchain-worker", + value_name = "STRATEGY", + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "Native" + )] + pub execution_offchain_worker: ExecutionStrategy, + + /// The means of execution used when calling into the runtime while not syncing, importing or constructing blocks. + #[structopt( + long = "execution-other", + value_name = "STRATEGY", + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "Native" + )] + pub execution_other: ExecutionStrategy, + + /// The execution strategy that should be used by all execution contexts. + #[structopt( + long = "execution", + value_name = "STRATEGY", + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + conflicts_with_all = &[ + "execution-other", + "execution-offchain-worker", + "execution-block-construction", + "execution-import-block", + "execution-syncing", + ] + )] + pub execution: Option, +} + +/// The `run` command used to run a node. +#[derive(Debug, StructOpt, Clone)] +pub struct RunCmd { + /// Enable validator mode. + /// + /// The node will be started with the authority role and actively + /// participate in any consensus task that it can (e.g. depending on + /// availability of local keys). + #[structopt( + long = "validator", + conflicts_with_all = &[ "sentry" ] + )] + pub validator: bool, + + /// Enable sentry mode. + /// + /// The node will be started with the authority role and participate in + /// consensus tasks as an "observer", it will never actively participate + /// regardless of whether it could (e.g. keys are available locally). This + /// mode is useful as a secure proxy for validators (which would run + /// detached from the network), since we want this node to participate in + /// the full consensus protocols in order to have all needed consensus data + /// available to relay to private nodes. + #[structopt( + long = "sentry", + conflicts_with_all = &[ "validator" ] + )] + pub sentry: bool, + + /// Disable GRANDPA voter when running in validator mode, otherwise disables the GRANDPA observer. + #[structopt(long = "no-grandpa")] + pub no_grandpa: bool, + + /// Experimental: Run in light client mode. + #[structopt(long = "light")] + pub light: bool, + + /// Listen to all RPC interfaces. + /// + /// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use a RPC proxy + /// server to filter out dangerous methods. More details: https://github.com/paritytech/substrate/wiki/Public-RPC. + /// Use `--unsafe-rpc-external` to suppress the warning if you understand the risks. + #[structopt(long = "rpc-external")] + pub rpc_external: bool, + + /// Listen to all RPC interfaces. + /// + /// Same as `--rpc-external`. + #[structopt(long = "unsafe-rpc-external")] + pub unsafe_rpc_external: bool, + + /// Listen to all Websocket interfaces. + /// + /// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use a RPC proxy + /// server to filter out dangerous methods. More details: https://github.com/paritytech/substrate/wiki/Public-RPC. + /// Use `--unsafe-ws-external` to suppress the warning if you understand the risks. + #[structopt(long = "ws-external")] + pub ws_external: bool, + + /// Listen to all Websocket interfaces. + /// + /// Same as `--ws-external`. + #[structopt(long = "unsafe-ws-external")] + pub unsafe_ws_external: bool, + + /// Listen to all Grafana data source interfaces. + /// + /// Default is local. + #[structopt(long = "grafana-external")] + pub grafana_external: bool, + + /// Specify HTTP RPC server TCP port. + #[structopt(long = "rpc-port", value_name = "PORT")] + pub rpc_port: Option, + + /// Specify WebSockets RPC server TCP port. + #[structopt(long = "ws-port", value_name = "PORT")] + pub ws_port: Option, + + /// Maximum number of WS RPC server connections. + #[structopt(long = "ws-max-connections", value_name = "COUNT")] + pub ws_max_connections: Option, + + /// Specify browser Origins allowed to access the HTTP & WS RPC servers. + /// + /// A comma-separated list of origins (protocol://domain or special `null` + /// value). Value of `all` will disable origin validation. Default is to + /// allow localhost, https://polkadot.js.org and + /// https://substrate-ui.parity.io origins. When running in --dev mode the + /// default is to allow all origins. + #[structopt(long = "rpc-cors", value_name = "ORIGINS", parse(try_from_str = parse_cors))] + pub rpc_cors: Option, + + /// Specify Grafana data source server TCP Port. + #[structopt(long = "grafana-port", value_name = "PORT")] + pub grafana_port: Option, + + /// The human-readable name for this node. + /// + /// The node name will be reported to the telemetry server, if enabled. + #[structopt(long = "name", value_name = "NAME")] + pub name: Option, + + /// Disable connecting to the Substrate telemetry server. + /// + /// Telemetry is on by default on global chains. + #[structopt(long = "no-telemetry")] + pub no_telemetry: bool, + + /// The URL of the telemetry server to connect to. + /// + /// This flag can be passed multiple times as a mean to specify multiple + /// telemetry endpoints. Verbosity levels range from 0-9, with 0 denoting + /// the least verbosity. If no verbosity level is specified the default is + /// 0. + #[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = parse_telemetry_endpoints))] + pub telemetry_endpoints: Vec<(String, u8)>, + + /// Should execute offchain workers on every block. + /// + /// By default it's only enabled for nodes that are authoring new blocks. + #[structopt( + long = "offchain-worker", + value_name = "ENABLED", + possible_values = &OffchainWorkerEnabled::variants(), + case_insensitive = true, + default_value = "WhenValidating" + )] + pub offchain_worker: OffchainWorkerEnabled, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub import_params: ImportParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub network_config: NetworkConfigurationParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub pool_config: TransactionPoolParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub keyring: Keyring, + + /// Enable authoring even when offline. + #[structopt(long = "force-authoring")] + pub force_authoring: bool, + + /// Comma separated list of targets for tracing + #[structopt(long = "tracing-targets", value_name = "TARGETS")] + pub tracing_targets: Option, + + /// Receiver to process tracing messages + #[structopt( + long = "tracing-receiver", + value_name = "RECEIVER", + possible_values = &TracingReceiver::variants(), + case_insensitive = true, + default_value = "Log" + )] + pub tracing_receiver: TracingReceiver, + + /// Specify custom keystore path. + #[structopt(long = "keystore-path", value_name = "PATH", parse(from_os_str))] + pub keystore_path: Option, + + /// Use interactive shell for entering the password used by the keystore. + #[structopt( + long = "password-interactive", + conflicts_with_all = &[ "password", "password-filename" ] + )] + pub password_interactive: bool, + + /// Password used by the keystore. + #[structopt( + long = "password", + conflicts_with_all = &[ "password-interactive", "password-filename" ] + )] + pub password: Option, + + /// File that contains the password used by the keystore. + #[structopt( + long = "password-filename", + value_name = "PATH", + parse(from_os_str), + conflicts_with_all = &[ "password-interactive", "password" ] + )] + pub password_filename: Option +} + +/// Stores all required Cli values for a keyring test account. +struct KeyringTestAccountCliValues { + help: String, + conflicts_with: Vec, + name: String, + variant: sp_keyring::Sr25519Keyring, +} + +lazy_static::lazy_static! { + /// The Cli values for all test accounts. + static ref TEST_ACCOUNTS_CLI_VALUES: Vec = { + sp_keyring::Sr25519Keyring::iter().map(|a| { + let help = format!( + "Shortcut for `--name {} --validator` with session keys for `{}` added to keystore.", + a, + a, + ); + let conflicts_with = sp_keyring::Sr25519Keyring::iter() + .filter(|b| a != *b) + .map(|b| b.to_string().to_lowercase()) + .chain(std::iter::once("name".to_string())) + .collect::>(); + let name = a.to_string().to_lowercase(); + + KeyringTestAccountCliValues { + help, + conflicts_with, + name, + variant: a, + } + }).collect() + }; +} + +/// Wrapper for exposing the keyring test accounts into the Cli. +#[derive(Debug, Clone)] +pub struct Keyring { + pub account: Option, +} + +impl StructOpt for Keyring { + fn clap<'a, 'b>() -> App<'a, 'b> { + unimplemented!("Should not be called for `TestAccounts`.") + } + + fn from_clap(m: &structopt::clap::ArgMatches) -> Self { + Keyring { + account: TEST_ACCOUNTS_CLI_VALUES.iter().find(|a| m.is_present(&a.name)).map(|a| a.variant), + } + } +} + +impl StructOptInternal for Keyring { + fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { + TEST_ACCOUNTS_CLI_VALUES.iter().fold(app, |app, a| { + let conflicts_with_strs = a.conflicts_with.iter().map(|s| s.as_str()).collect::>(); + + app.arg( + Arg::with_name(&a.name) + .long(&a.name) + .help(&a.help) + .conflicts_with_all(&conflicts_with_strs) + .takes_value(false) + ) + }) + } +} + +/// Default to verbosity level 0, if none is provided. +fn parse_telemetry_endpoints(s: &str) -> Result<(String, u8), Box> { + let pos = s.find(' '); + match pos { + None => { + Ok((s.to_owned(), 0)) + }, + Some(pos_) => { + let verbosity = s[pos_ + 1..].parse()?; + let url = s[..pos_].parse()?; + Ok((url, verbosity)) + } + } +} + +/// CORS setting +/// +/// The type is introduced to overcome `Option>` +/// handling of `structopt`. +#[derive(Clone, Debug)] +pub enum Cors { + /// All hosts allowed + All, + /// Only hosts on the list are allowed. + List(Vec), +} + +impl From for Option> { + fn from(cors: Cors) -> Self { + match cors { + Cors::All => None, + Cors::List(list) => Some(list), + } + } +} + +/// Parse cors origins +fn parse_cors(s: &str) -> Result> { + let mut is_all = false; + let mut origins = Vec::new(); + for part in s.split(',') { + match part { + "all" | "*" => { + is_all = true; + break; + }, + other => origins.push(other.to_owned()), + } + } + + Ok(if is_all { Cors::All } else { Cors::List(origins) }) +} + +/// 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, + + /// Disable adding the default bootnode to the specification. + /// + /// By default the `/ip4/127.0.0.1/tcp/30333/p2p/NODE_PEER_ID` bootnode is added to the + /// specification when no bootnode exists. + #[structopt(long = "disable-default-bootnode")] + pub disable_default_bootnode: bool, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub node_key_params: NodeKeyParams, +} + +/// Wrapper type of `String` which holds an arbitary sized unsigned integer formatted as decimal. +#[derive(Debug, Clone)] +pub struct BlockNumber(String); + +impl FromStr for BlockNumber { + type Err = String; + + fn from_str(block_number: &str) -> Result { + if block_number.chars().any(|d| !d.is_digit(10)) { + Err(format!( + "Invalid block number: {}, expected decimal formatted unsigned integer", + block_number + )) + } else { + Ok(Self(block_number.to_owned())) + } + } +} + +impl BlockNumber { + /// Wrapper on top of `std::str::parse` but with `Error` as a `String` + /// + /// See `https://doc.rust-lang.org/std/primitive.str.html#method.parse` for more elaborate + /// documentation. + pub fn parse(&self) -> Result + where + N: FromStr, + N::Err: std::fmt::Debug, + { + self.0 + .parse() + .map_err(|e| format!("BlockNumber: {} parsing failed because of {:?}", self.0, e)) + } +} + +/// 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. + /// + /// Default is 1. + #[structopt(long = "from", value_name = "BLOCK")] + pub from: Option, + + /// Specify last block number. + /// + /// Default is best block. + #[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, +} + +/// 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, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub import_params: ImportParams, +} + +/// The `check-block` command used to validate blocks. +#[derive(Debug, StructOpt, Clone)] +pub struct CheckBlockCmd { + /// Block hash or number + #[structopt(value_name = "HASH or NUMBER")] + pub input: String, + + /// 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, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub import_params: ImportParams, +} + +/// The `revert` command used revert the chain to a previous state. +#[derive(Debug, StructOpt, Clone)] +pub struct RevertCmd { + /// Number of blocks to revert. + #[structopt(default_value = "256")] + pub num: BlockNumber, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, +} + +/// 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, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, +} + +/// 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. + ImportBlocks(ImportBlocksCmd), + + /// Validte a single block. + CheckBlock(CheckBlockCmd), + + /// Revert chain to the previous state. + Revert(RevertCmd), + + /// Remove the whole chain data. + PurgeChain(PurgeChainCmd), + + /// Further custom subcommands. + Custom(CC), +} + +impl StructOpt for CoreParams where + CC: StructOpt + GetSharedParams, + RP: StructOpt + StructOptInternal, +{ + 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, outputting to stdout.") + ) + .subcommand( + ExportBlocksCmd::augment_clap(SubCommand::with_name("export-blocks")) + .about("Export blocks to a file. This file can only be re-imported \ + if it is in binary format (not JSON!)." + ) + ) + .subcommand( + ImportBlocksCmd::augment_clap(SubCommand::with_name("import-blocks")) + .about("Import blocks from file.") + ) + .subcommand( + CheckBlockCmd::augment_clap(SubCommand::with_name("check-block")) + .about("Re-validate a known block.") + ) + .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)), + ("check-block", Some(matches)) => + CoreParams::CheckBlock(CheckBlockCmd::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)), + } + } +} + +/// 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, Default)] +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 StructOptInternal for NoCustom { + fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { + app + } +} + +impl GetSharedParams for NoCustom { + fn shared_params(&self) -> Option<&SharedParams> { + 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 + StructOptInternal, 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/client/cli/src/traits.rs b/client/cli/src/traits.rs new file mode 100644 index 0000000000000..96216a172b970 --- /dev/null +++ b/client/cli/src/traits.rs @@ -0,0 +1,23 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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::params::SharedParams; + +/// Supports getting common params. +pub trait GetSharedParams { + /// Returns shared params if any. + fn shared_params(&self) -> Option<&SharedParams>; +} diff --git a/client/consensus/aura/Cargo.toml b/client/consensus/aura/Cargo.toml new file mode 100644 index 0000000000000..ddae989b4170f --- /dev/null +++ b/client/consensus/aura/Cargo.toml @@ -0,0 +1,43 @@ +[package] +name = "sc-consensus-aura" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "Aura consensus algorithm for substrate" +edition = "2018" + +[dependencies] +sp-application-crypto = { version = "2.0.0", path = "../../../primitives/application-crypto" } +sp-consensus-aura = { version = "0.8", path = "../../../primitives/consensus/aura" } +sp-block-builder = { version = "2.0.0", path = "../../../primitives/block-builder" } +sc-client = { version = "2.0.0", path = "../../" } +sc-client-api = { version = "2.0.0", path = "../../api" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +derive_more = "0.99.2" +futures = { version = "0.3.1", features = ["compat"] } +futures01 = { package = "futures", version = "0.1" } +futures-timer = "0.4.0" +sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } +sc-keystore = { version = "2.0.0", path = "../../keystore" } +log = "0.4.8" +parking_lot = "0.9.0" +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } +sp-io = { version = "2.0.0", path = "../../../primitives/io" } +sp-version = { version = "2.0.0", path = "../../../primitives/version" } +sc-consensus-slots = { version = "0.8", path = "../slots" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-timestamp = { version = "2.0.0", path = "../../../primitives/timestamp" } +sc-telemetry = { version = "2.0.0", path = "../../telemetry" } + +[dev-dependencies] +sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" } +sc-executor = { version = "2.0.0", path = "../../executor" } +sc-network = { version = "0.8", path = "../../network" } +sc-network-test = { version = "2.0.0", path = "../../network/test" } +sc-service = { version = "2.0.0", path = "../../service" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } +tokio = "0.1.22" +env_logger = "0.7.0" +tempfile = "3.1.0" diff --git a/client/consensus/aura/src/digest.rs b/client/consensus/aura/src/digest.rs new file mode 100644 index 0000000000000..8dd42fc01def2 --- /dev/null +++ b/client/consensus/aura/src/digest.rs @@ -0,0 +1,65 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Aura (Authority-Round) digests +//! +//! This implements the digests for AuRa, to allow the private +//! `CompatibleDigestItem` trait to appear in public interfaces. + +use sp_core::Pair; +use sp_consensus_aura::AURA_ENGINE_ID; +use sp_runtime::generic::{DigestItem, OpaqueDigestItemId}; +use codec::{Encode, Codec}; +use std::fmt::Debug; + +type Signature

=

::Signature; + +/// A digest item which is usable with aura consensus. +pub trait CompatibleDigestItem: Sized { + /// Construct a digest item which contains a signature on the hash. + fn aura_seal(signature: Signature

) -> Self; + + /// If this item is an Aura seal, return the signature. + fn as_aura_seal(&self) -> Option>; + + /// Construct a digest item which contains the slot number + fn aura_pre_digest(slot_num: u64) -> Self; + + /// If this item is an AuRa pre-digest, return the slot number + fn as_aura_pre_digest(&self) -> Option; +} + +impl CompatibleDigestItem

for DigestItem where + P: Pair, + Signature

: Codec, + Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static +{ + fn aura_seal(signature: Signature

) -> Self { + DigestItem::Seal(AURA_ENGINE_ID, signature.encode()) + } + + fn as_aura_seal(&self) -> Option> { + self.try_to(OpaqueDigestItemId::Seal(&AURA_ENGINE_ID)) + } + + fn aura_pre_digest(slot_num: u64) -> Self { + DigestItem::PreRuntime(AURA_ENGINE_ID, slot_num.encode()) + } + + fn as_aura_pre_digest(&self) -> Option { + self.try_to(OpaqueDigestItemId::PreRuntime(&AURA_ENGINE_ID)) + } +} diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs new file mode 100644 index 0000000000000..13a4c5a777144 --- /dev/null +++ b/client/consensus/aura/src/lib.rs @@ -0,0 +1,1047 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Aura (Authority-round) consensus in substrate. +//! +//! Aura works by having a list of authorities A who are expected to roughly +//! agree on the current time. Time is divided up into discrete slots of t +//! seconds each. For each slot s, the author of that slot is A[s % |A|]. +//! +//! The author is allowed to issue one block but not more during that slot, +//! and it will be built upon the longest valid chain that has been seen. +//! +//! Blocks from future steps will be either deferred or rejected depending on how +//! far in the future they are. +//! +//! NOTE: Aura itself is designed to be generic over the crypto used. +#![forbid(missing_docs, unsafe_code)] +use std::{ + sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug, pin::Pin, + collections::HashMap +}; + +use futures::prelude::*; +use parking_lot::Mutex; +use log::{debug, info, trace}; + +use codec::{Encode, Decode, Codec}; + +use sp_consensus::{ + self, BlockImport, Environment, Proposer, CanAuthorWith, ForkChoiceStrategy, BlockImportParams, + BlockOrigin, Error as ConsensusError, SelectChain, SlotData, BlockCheckParams, ImportResult +}; +use sp_consensus::import_queue::{ + Verifier, BasicQueue, BoxJustificationImport, BoxFinalityProofImport, +}; +use sc_client_api::backend::AuxStore; +use sc_client::BlockOf; +use sp_blockchain::{ + self, Result as CResult, well_known_cache_keys::{self, Id as CacheKeyId}, + ProvideCache, HeaderBackend, +}; +use sp_block_builder::BlockBuilder as BlockBuilderApi; +use sp_runtime::{generic::{BlockId, OpaqueDigestItemId}, Justification}; +use sp_runtime::traits::{Block as BlockT, Header, DigestItemFor, Zero, Member}; +use sp_api::ProvideRuntimeApi; + +use sp_core::crypto::Pair; +use sp_inherents::{InherentDataProviders, InherentData}; +use sp_timestamp::{ + TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError +}; +use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO}; + +use sc_consensus_slots::{ + CheckedHeader, SlotWorker, SlotInfo, SlotCompatible, StorageChanges, check_equivocation, +}; + +use sc_keystore::KeyStorePtr; +use sp_api::ApiExt; + +pub use sp_consensus_aura::{ + ConsensusLog, AuraApi, AURA_ENGINE_ID, + inherents::{ + InherentType as AuraInherent, + AuraInherentData, INHERENT_IDENTIFIER, InherentDataProvider, + }, +}; +pub use sp_consensus::SyncOracle; +pub use digest::CompatibleDigestItem; + +mod digest; + +type AuthorityId

=

::Public; + +/// A slot duration. Create with `get_or_compute`. +#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct SlotDuration(sc_consensus_slots::SlotDuration); + +impl SlotDuration { + /// Either fetch the slot duration from disk or compute it from the genesis + /// state. + pub fn get_or_compute(client: &C) -> CResult + where + A: Codec, + B: BlockT, + C: AuxStore + ProvideRuntimeApi, + C::Api: AuraApi, + { + sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)).map(Self) + } + + /// Get the slot duration in milliseconds. + pub fn get(&self) -> u64 { + self.0.get() + } +} + +/// Get slot author for given block along with authorities. +fn slot_author(slot_num: u64, authorities: &[AuthorityId

]) -> Option<&AuthorityId

> { + if authorities.is_empty() { return None } + + let idx = slot_num % (authorities.len() as u64); + assert!( + idx <= usize::max_value() as u64, + "It is impossible to have a vector with length beyond the address space; qed", + ); + + let current_author = authorities.get(idx as usize) + .expect("authorities not empty; index constrained to list length;\ + this is a valid index; qed"); + + Some(current_author) +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +struct AuraSlotCompatible; + +impl SlotCompatible for AuraSlotCompatible { + fn extract_timestamp_and_slot( + &self, + data: &InherentData + ) -> Result<(TimestampInherent, AuraInherent, std::time::Duration), sp_consensus::Error> { + data.timestamp_inherent_data() + .and_then(|t| data.aura_inherent_data().map(|a| (t, a))) + .map_err(Into::into) + .map_err(sp_consensus::Error::InherentData) + .map(|(x, y)| (x, y, Default::default())) + } +} + +/// Start the aura worker. The returned future should be run in a futures executor. +pub fn start_aura( + slot_duration: SlotDuration, + client: Arc, + select_chain: SC, + block_import: I, + env: E, + sync_oracle: SO, + inherent_data_providers: InherentDataProviders, + force_authoring: bool, + keystore: KeyStorePtr, + can_author_with: CAW, +) -> Result, sp_consensus::Error> where + B: BlockT, + C: ProvideRuntimeApi + BlockOf + ProvideCache + AuxStore + Send + Sync, + C::Api: AuraApi>, + SC: SelectChain, + E: Environment + Send + Sync + 'static, + E::Proposer: Proposer>, + P: Pair + Send + Sync, + P::Public: Hash + Member + Encode + Decode, + P::Signature: Hash + Member + Encode + Decode, + I: BlockImport> + Send + Sync + 'static, + Error: std::error::Error + Send + From + 'static, + SO: SyncOracle + Send + Sync + Clone, + CAW: CanAuthorWith + Send, +{ + let worker = AuraWorker { + client: client.clone(), + block_import: Arc::new(Mutex::new(block_import)), + env, + keystore, + sync_oracle: sync_oracle.clone(), + force_authoring, + _key_type: PhantomData::

, + }; + register_aura_inherent_data_provider( + &inherent_data_providers, + slot_duration.0.slot_duration() + )?; + Ok(sc_consensus_slots::start_slot_worker::<_, _, _, _, _, AuraSlotCompatible, _>( + slot_duration.0, + select_chain, + worker, + sync_oracle, + inherent_data_providers, + AuraSlotCompatible, + can_author_with, + ).map(|()| Ok::<(), ()>(())).compat()) +} + +struct AuraWorker { + client: Arc, + block_import: Arc>, + env: E, + keystore: KeyStorePtr, + sync_oracle: SO, + force_authoring: bool, + _key_type: PhantomData

, +} + +impl sc_consensus_slots::SimpleSlotWorker for AuraWorker where + B: BlockT, + C: ProvideRuntimeApi + BlockOf + ProvideCache + Sync, + C::Api: AuraApi>, + E: Environment, + E::Proposer: Proposer>, + I: BlockImport> + Send + Sync + 'static, + P: Pair + Send + Sync, + P::Public: Member + Encode + Decode + Hash, + P::Signature: Member + Encode + Decode + Hash + Debug, + SO: SyncOracle + Send + Clone, + Error: std::error::Error + Send + From + 'static, +{ + type BlockImport = I; + type SyncOracle = SO; + type Proposer = E::Proposer; + type Claim = P; + type EpochData = Vec>; + + fn logging_target(&self) -> &'static str { + "aura" + } + + fn block_import(&self) -> Arc> { + self.block_import.clone() + } + + fn epoch_data( + &self, + header: &B::Header, + _slot_number: u64, + ) -> Result { + authorities(self.client.as_ref(), &BlockId::Hash(header.hash())) + } + + fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize { + epoch_data.len() + } + + fn claim_slot( + &self, + _header: &B::Header, + slot_number: u64, + epoch_data: &Self::EpochData, + ) -> Option { + let expected_author = slot_author::

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

(&p, sp_application_crypto::key_types::AURA).ok() + }) + } + + fn pre_digest_data( + &self, + slot_number: u64, + _claim: &Self::Claim, + ) -> Vec> { + vec![ + as CompatibleDigestItem

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

>::aura_seal(signature); + + BlockImportParams { + origin: BlockOrigin::Own, + header, + justification: None, + post_digests: vec![signature_digest_item], + body: Some(body), + storage_changes: Some(storage_changes), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + } + }) + } + + fn force_authoring(&self) -> bool { + self.force_authoring + } + + fn sync_oracle(&mut self) -> &mut Self::SyncOracle { + &mut self.sync_oracle + } + + fn proposer(&mut self, block: &B::Header) -> Result { + self.env.init(block).map_err(|e| { + sp_consensus::Error::ClientImport(format!("{:?}", e)).into() + }) + } + + fn proposing_remaining_duration( + &self, + head: &B::Header, + slot_info: &SlotInfo + ) -> Option { + // never give more than 20 times more lenience. + const BACKOFF_CAP: u64 = 20; + + let slot_remaining = self.slot_remaining_duration(slot_info); + let parent_slot = match find_pre_digest::(head) { + Err(_) => return Some(slot_remaining), + Ok(d) => d, + }; + + // we allow a lenience of the number of slots since the head of the + // chain was produced, minus 1 (since there is always a difference of at least 1) + // + // linear back-off. + // in normal cases we only attempt to issue blocks up to the end of the slot. + // when the chain has been stalled for a few slots, we give more lenience. + let slot_lenience = slot_info.number.saturating_sub(parent_slot + 1); + let slot_lenience = std::cmp::min(slot_lenience, BACKOFF_CAP); + let slot_lenience = Duration::from_secs(slot_lenience * slot_info.duration); + Some(slot_lenience + slot_remaining) + } +} + +impl SlotWorker for AuraWorker where + B: BlockT, + C: ProvideRuntimeApi + BlockOf + ProvideCache + Sync + Send, + C::Api: AuraApi>, + E: Environment + Send + Sync, + E::Proposer: Proposer>, + I: BlockImport> + Send + Sync + 'static, + P: Pair + Send + Sync, + P::Public: Member + Encode + Decode + Hash, + P::Signature: Member + Encode + Decode + Hash + Debug, + SO: SyncOracle + Send + Sync + Clone, + Error: std::error::Error + Send + From + 'static, +{ + type OnSlot = Pin> + Send>>; + + fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot { + >::on_slot(self, chain_head, slot_info) + } +} + +fn aura_err(error: Error) -> Error { + debug!(target: "aura", "{}", error); + error +} + +#[derive(derive_more::Display, Debug)] +enum Error { + #[display(fmt = "Multiple Aura pre-runtime headers")] + MultipleHeaders, + #[display(fmt = "No Aura pre-runtime digest found")] + NoDigestFound, + #[display(fmt = "Header {:?} is unsealed", _0)] + HeaderUnsealed(B::Hash), + #[display(fmt = "Header {:?} has a bad seal", _0)] + HeaderBadSeal(B::Hash), + #[display(fmt = "Slot Author not found")] + SlotAuthorNotFound, + #[display(fmt = "Bad signature on {:?}", _0)] + BadSignature(B::Hash), + #[display(fmt = "Rejecting block too far in future")] + TooFarInFuture, + Client(sp_blockchain::Error), + DataProvider(String), + Runtime(String), + #[display(fmt = "Slot number must increase: parent slot: {}, this slot: {}", _0, _1)] + SlotNumberMustIncrease(u64, u64), + #[display(fmt = "Parent ({}) of {} unavailable. Cannot import", _0, _1)] + ParentUnavailable(B::Hash, B::Hash), +} + +impl std::convert::From> for String { + fn from(error: Error) -> String { + error.to_string() + } +} + +fn find_pre_digest(header: &B::Header) -> Result> + where DigestItemFor: CompatibleDigestItem

, + P::Signature: Decode, + P::Public: Encode + Decode + PartialEq + Clone, +{ + if header.number().is_zero() { + return Ok(0); + } + + let mut pre_digest: Option = None; + for log in header.digest().logs() { + trace!(target: "aura", "Checking log {:?}", log); + match (log.as_aura_pre_digest(), pre_digest.is_some()) { + (Some(_), true) => Err(aura_err(Error::MultipleHeaders))?, + (None, _) => trace!(target: "aura", "Ignoring digest not meant for us"), + (s, false) => pre_digest = s, + } + } + pre_digest.ok_or_else(|| aura_err(Error::NoDigestFound)) +} + +/// check a header has been signed by the right key. If the slot is too far in the future, an error will be returned. +/// if it's successful, returns the pre-header and the digest item containing the seal. +/// +/// This digest item will always return `Some` when used with `as_aura_seal`. +// +// FIXME #1018 needs misbehavior types. The `transaction_pool` parameter will be +// used to submit such misbehavior reports. +fn check_header( + client: &C, + slot_now: u64, + mut header: B::Header, + hash: B::Hash, + authorities: &[AuthorityId

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

, + P::Signature: Decode, + C: sc_client_api::backend::AuxStore, + P::Public: Encode + Decode + PartialEq + Clone, + T: Send + Sync + 'static, +{ + let seal = match header.digest_mut().pop() { + Some(x) => x, + None => return Err(Error::HeaderUnsealed(hash)), + }; + + let sig = seal.as_aura_seal().ok_or_else(|| { + aura_err(Error::HeaderBadSeal(hash)) + })?; + + let slot_num = find_pre_digest::(&header)?; + + if slot_num > slot_now { + header.digest_mut().push(seal); + Ok(CheckedHeader::Deferred(header, slot_num)) + } else { + // check the signature is valid under the expected authority and + // chain state. + let expected_author = match slot_author::

(slot_num, &authorities) { + None => return Err(Error::SlotAuthorNotFound), + Some(author) => author, + }; + + let pre_hash = header.hash(); + + if P::verify(&sig, pre_hash.as_ref(), expected_author) { + if let Some(equivocation_proof) = check_equivocation( + client, + slot_now, + slot_num, + &header, + expected_author, + ).map_err(Error::Client)? { + info!( + "Slot author is equivocating at slot {} with headers {:?} and {:?}", + slot_num, + equivocation_proof.fst_header().hash(), + equivocation_proof.snd_header().hash(), + ); + } + + Ok(CheckedHeader::Checked(header, (slot_num, seal))) + } else { + Err(Error::BadSignature(hash)) + } + } +} + +/// A verifier for Aura blocks. +pub struct AuraVerifier { + client: Arc, + phantom: PhantomData

, + inherent_data_providers: sp_inherents::InherentDataProviders, + transaction_pool: Option>, +} + +impl AuraVerifier + where P: Send + Sync + 'static +{ + fn check_inherents( + &self, + block: B, + block_id: BlockId, + inherent_data: InherentData, + timestamp_now: u64, + ) -> Result<(), Error> + where C: ProvideRuntimeApi, C::Api: BlockBuilderApi + { + const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; + + let inherent_res = self.client.runtime_api().check_inherents( + &block_id, + block, + inherent_data, + ).map_err(Error::Client)?; + + if !inherent_res.ok() { + inherent_res + .into_errors() + .try_for_each(|(i, e)| match TIError::try_from(&i, &e) { + Some(TIError::ValidAtTimestamp(timestamp)) => { + // halt import until timestamp is valid. + // reject when too far ahead. + if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { + return Err(Error::TooFarInFuture); + } + + 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(Error::Runtime(e.into())), + None => Err(Error::DataProvider( + self.inherent_data_providers.error_to_string(&i, &e) + )), + }) + } else { + Ok(()) + } + } +} + +#[forbid(deprecated)] +impl Verifier for AuraVerifier where + C: ProvideRuntimeApi + + Send + + Sync + + sc_client_api::backend::AuxStore + + ProvideCache + + BlockOf, + C::Api: BlockBuilderApi + AuraApi> + ApiExt, + DigestItemFor: CompatibleDigestItem

, + P: Pair + Send + Sync + 'static, + P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + 'static, + P::Signature: Encode + Decode, + T: Send + Sync + 'static, +{ + fn verify( + &mut self, + origin: BlockOrigin, + header: B::Header, + justification: Option, + mut body: Option>, + ) -> Result<(BlockImportParams, Option)>>), String> { + let mut inherent_data = self.inherent_data_providers + .create_inherent_data() + .map_err(|e| e.into_string())?; + 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 = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash)) + .map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?; + + // we add one to allow for some small drift. + // FIXME #1019 in the future, alter this queue to allow deferring of + // headers + let checked_header = check_header::( + &self.client, + slot_now + 1, + header, + hash, + &authorities[..], + self.transaction_pool.as_ref().map(|x| &**x), + ).map_err(|e| e.to_string())?; + match checked_header { + CheckedHeader::Checked(pre_header, (slot_num, seal)) => { + // if the body is passed through, we need to use the runtime + // to check that the internally-set timestamp in the inherents + // actually matches the slot set in the seal. + if let Some(inner_body) = body.take() { + inherent_data.aura_replace_inherent_data(slot_num); + let block = B::new(pre_header.clone(), inner_body); + + // skip the inherents verification if the runtime API is old. + if self.client + .runtime_api() + .has_api_with::, _>( + &BlockId::Hash(parent_hash), + |v| v >= 2, + ) + .map_err(|e| format!("{:?}", e))? + { + self.check_inherents( + block.clone(), + BlockId::Hash(parent_hash), + inherent_data, + timestamp_now, + ).map_err(|e| e.to_string())?; + } + + let (_, inner_body) = block.deconstruct(); + body = Some(inner_body); + } + + trace!(target: "aura", "Checked {:?}; importing.", pre_header); + telemetry!(CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header); + + // Look for an authorities-change log. + let maybe_keys = pre_header.digest() + .logs() + .iter() + .filter_map(|l| l.try_to::>>( + OpaqueDigestItemId::Consensus(&AURA_ENGINE_ID) + )) + .find_map(|l| match l { + ConsensusLog::AuthoritiesChange(a) => Some( + vec![(well_known_cache_keys::AUTHORITIES, a.encode())] + ), + _ => None, + }); + + let block_import_params = BlockImportParams { + origin, + header: pre_header, + post_digests: vec![seal], + body, + storage_changes: None, + finalized: false, + justification, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + + Ok((block_import_params, maybe_keys)) + } + CheckedHeader::Deferred(a, b) => { + 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)) + } + } + } +} + +fn initialize_authorities_cache(client: &C) -> Result<(), ConsensusError> where + A: Codec, + B: BlockT, + C: ProvideRuntimeApi + BlockOf + ProvideCache, + C::Api: AuraApi, +{ + // no cache => no initialization + let cache = match client.cache() { + Some(cache) => cache, + None => return Ok(()), + }; + + // check if we already have initialized the cache + let genesis_id = BlockId::Number(Zero::zero()); + let genesis_authorities: Option> = cache + .get_at(&well_known_cache_keys::AUTHORITIES, &genesis_id) + .and_then(|(_, _, v)| Decode::decode(&mut &v[..]).ok()); + if genesis_authorities.is_some() { + return Ok(()); + } + + let map_err = |error| sp_consensus::Error::from(sp_consensus::Error::ClientImport( + format!( + "Error initializing authorities cache: {}", + error, + ))); + let genesis_authorities = authorities(client, &genesis_id)?; + cache.initialize(&well_known_cache_keys::AUTHORITIES, genesis_authorities.encode()) + .map_err(map_err)?; + + Ok(()) +} + +#[allow(deprecated)] +fn authorities(client: &C, at: &BlockId) -> Result, ConsensusError> where + A: Codec, + B: BlockT, + C: ProvideRuntimeApi + BlockOf + ProvideCache, + C::Api: AuraApi, +{ + client + .cache() + .and_then(|cache| cache + .get_at(&well_known_cache_keys::AUTHORITIES, at) + .and_then(|(_, _, v)| Decode::decode(&mut &v[..]).ok()) + ) + .or_else(|| AuraApi::authorities(&*client.runtime_api(), at).ok()) + .ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet.into()) +} + +/// The Aura import queue type. +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<(), sp_consensus::Error> { + if !inherent_data_providers.has_provider(&INHERENT_IDENTIFIER) { + inherent_data_providers + .register_provider(InherentDataProvider::new(slot_duration)) + .map_err(Into::into) + .map_err(sp_consensus::Error::InherentData) + } else { + Ok(()) + } +} + +/// A block-import handler for Aura. +pub struct AuraBlockImport, P> { + inner: I, + client: Arc, + _phantom: PhantomData<(Block, P)>, +} + +impl, P> Clone for AuraBlockImport { + fn clone(&self) -> Self { + AuraBlockImport { + inner: self.inner.clone(), + client: self.client.clone(), + _phantom: PhantomData, + } + } +} + +impl, P> AuraBlockImport { + /// New aura block import. + pub fn new( + inner: I, + client: Arc, + ) -> Self { + Self { + inner, + client, + _phantom: PhantomData, + } + } +} + +impl BlockImport for AuraBlockImport where + I: BlockImport> + Send + Sync, + I::Error: Into, + C: HeaderBackend + ProvideRuntimeApi, + P: Pair + Send + Sync + 'static, + P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode, + P::Signature: Encode + Decode, +{ + type Error = ConsensusError; + type Transaction = sp_api::TransactionFor; + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + self.inner.check_block(block).map_err(Into::into) + } + + fn import_block( + &mut self, + block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { + let hash = block.post_header().hash(); + let slot_number = find_pre_digest::(&block.header) + .expect("valid Aura headers must contain a predigest; \ + header has been already verified; qed"); + + let parent_hash = *block.header.parent_hash(); + let parent_header = self.client.header(BlockId::Hash(parent_hash)) + .map_err(|e| ConsensusError::ChainLookup(e.to_string()))? + .ok_or_else(|| ConsensusError::ChainLookup(aura_err( + Error::::ParentUnavailable(parent_hash, hash) + ).into()))?; + + let parent_slot = find_pre_digest::(&parent_header) + .expect("valid Aura headers contain a pre-digest; \ + parent header has already been verified; qed"); + + // make sure that slot number is strictly increasing + if slot_number <= parent_slot { + return Err( + ConsensusError::ClientImport(aura_err( + Error::::SlotNumberMustIncrease(parent_slot, slot_number) + ).into()) + ); + } + + self.inner.import_block(block, new_cache).map_err(Into::into) + } +} + +/// Start an import queue for the Aura consensus algorithm. +pub fn import_queue( + slot_duration: SlotDuration, + block_import: I, + justification_import: Option>, + finality_proof_import: Option>, + client: Arc, + inherent_data_providers: InherentDataProviders, + transaction_pool: Option>, +) -> Result>, sp_consensus::Error> where + B: BlockT, + C::Api: BlockBuilderApi + AuraApi> + ApiExt, + C: 'static + ProvideRuntimeApi + BlockOf + ProvideCache + Send + Sync + AuxStore + HeaderBackend, + I: BlockImport> + Send + Sync + 'static, + DigestItemFor: CompatibleDigestItem

, + P: Pair + Send + Sync + 'static, + P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode, + P::Signature: Encode + Decode, + T: Send + Sync + 'static, +{ + register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?; + initialize_authorities_cache(&*client)?; + + let verifier = AuraVerifier { + client: client.clone(), + inherent_data_providers, + phantom: PhantomData, + transaction_pool, + }; + Ok(BasicQueue::new( + verifier, + Box::new(block_import), + justification_import, + finality_proof_import, + )) +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_consensus::{NoNetwork as DummyOracle, Proposal, RecordProof}; + use sc_network_test::{Block as TestBlock, *}; + use sp_runtime::traits::{Block as BlockT, DigestFor}; + use sc_network::config::ProtocolConfig; + use parking_lot::Mutex; + use tokio::runtime::current_thread; + use sp_keyring::sr25519::Keyring; + use sc_client::BlockchainEvents; + use sp_consensus_aura::sr25519::AuthorityPair; + + type Error = sp_blockchain::Error; + + type TestClient = sc_client::Client< + substrate_test_runtime_client::Backend, + substrate_test_runtime_client::Executor, + TestBlock, + substrate_test_runtime_client::runtime::RuntimeApi + >; + + struct DummyFactory(Arc); + struct DummyProposer(u64, Arc); + + impl Environment for DummyFactory { + type Proposer = DummyProposer; + type Error = Error; + + fn init(&mut self, parent_header: &::Header) + -> Result + { + Ok(DummyProposer(parent_header.number + 1, self.0.clone())) + } + } + + impl Proposer for DummyProposer { + type Error = Error; + type Transaction = sc_client_api::TransactionFor< + substrate_test_runtime_client::Backend, + TestBlock + >; + type Proposal = future::Ready, Error>>; + + fn propose( + &mut self, + _: InherentData, + digests: DigestFor, + _: Duration, + _: RecordProof, + ) -> Self::Proposal { + let r = self.1.new_block(digests).unwrap().build().map_err(|e| e.into()); + + future::ready(r.map(|b| Proposal { + block: b.block, + proof: b.proof, + storage_changes: b.storage_changes, + })) + } + } + + const SLOT_DURATION: u64 = 1000; + + pub struct AuraTestNet { + peers: Vec>, + } + + impl TestNetFactory for AuraTestNet { + 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(), + } + } + + fn make_verifier(&self, client: PeersClient, _cfg: &ProtocolConfig, _peer_data: &()) + -> Self::Verifier + { + match client { + PeersClient::Full(client, _) => { + 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.get(), SLOT_DURATION); + AuraVerifier { + client, + inherent_data_providers, + transaction_pool: Default::default(), + phantom: Default::default(), + } + }, + PeersClient::Light(_, _) => unreachable!("No (yet) tests for light client + Aura"), + } + } + + fn peer(&mut self, i: usize) -> &mut Peer { + &mut self.peers[i] + } + + fn peers(&self) -> &Vec> { + &self.peers + } + + fn mut_peers>)>(&mut self, closure: F) { + closure(&mut self.peers); + } + } + + #[test] + #[allow(deprecated)] + fn authoring_blocks() { + let _ = env_logger::try_init(); + let net = AuraTestNet::new(3); + + let peers = &[ + (0, Keyring::Alice), + (1, Keyring::Bob), + (2, Keyring::Charlie), + ]; + + let net = Arc::new(Mutex::new(net)); + let mut import_notifications = Vec::new(); + + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut keystore_paths = Vec::new(); + for (peer_id, key) in peers { + let mut net = net.lock(); + let peer = net.peer(*peer_id); + let client = peer.client().as_full().expect("full clients are created").clone(); + let select_chain = peer.select_chain().expect("full client has a select chain"); + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); + let keystore = sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore."); + + keystore.write().insert_ephemeral_from_seed::(&key.to_seed()) + .expect("Creates authority key"); + keystore_paths.push(keystore_path); + + let environ = DummyFactory(client.clone()); + import_notifications.push( + client.import_notification_stream() + .take_while(|n| future::ready(!(n.origin != BlockOrigin::Own && n.header.number() < &5))) + .for_each(move |_| future::ready(())) + ); + + 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::<_, _, _, _, _, AuthorityPair, _, _, _>( + slot_duration, + client.clone(), + select_chain, + client, + environ, + DummyOracle, + inherent_data_providers, + false, + keystore, + sp_consensus::AlwaysCanAuthor, + ).expect("Starts aura"); + + runtime.spawn(aura); + } + + runtime.spawn(futures01::future::poll_fn(move || { + net.lock().poll(); + Ok::<_, ()>(futures01::Async::NotReady::<()>) + })); + + runtime.block_on(future::join_all(import_notifications) + .map(|_| Ok::<(), ()>(())).compat()).unwrap(); + } + + #[test] + fn authorities_call_works() { + let client = substrate_test_runtime_client::new(); + + assert_eq!(client.chain_info().best_number, 0); + assert_eq!(authorities(&client, &BlockId::Number(0)).unwrap(), vec![ + Keyring::Alice.public().into(), + Keyring::Bob.public().into(), + Keyring::Charlie.public().into() + ]); + } +} diff --git a/client/consensus/babe/Cargo.toml b/client/consensus/babe/Cargo.toml new file mode 100644 index 0000000000000..eb2875b3d37ff --- /dev/null +++ b/client/consensus/babe/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "sc-consensus-babe" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "BABE consensus algorithm for substrate" +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } +sp-consensus-babe = { version = "0.8", path = "../../../primitives/consensus/babe" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-application-crypto = { version = "2.0.0", path = "../../../primitives/application-crypto" } +num-bigint = "0.2.3" +num-rational = "0.2.2" +num-traits = "0.2.8" +sp-version = { version = "2.0.0", path = "../../../primitives/version" } +sp-io = { version = "2.0.0", path = "../../../primitives/io" } +sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } +sp-timestamp = { version = "2.0.0", path = "../../../primitives/timestamp" } +sc-telemetry = { version = "2.0.0", path = "../../telemetry" } +sc-keystore = { version = "2.0.0", path = "../../keystore" } +sc-client-api = { version = "2.0.0", path = "../../api" } +sc-client = { version = "2.0.0", path = "../../" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +sp-block-builder = { version = "2.0.0", path = "../../../primitives/block-builder" } +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +sc-consensus-uncles = { version = "0.8", path = "../uncles" } +sc-consensus-slots = { version = "0.8", path = "../slots" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +fork-tree = { version = "2.0.0", path = "../../../utils/fork-tree" } +futures = { version = "0.3.1", features = ["compat"] } +futures01 = { package = "futures", version = "0.1" } +futures-timer = "0.4.0" +parking_lot = "0.9.0" +log = "0.4.8" +schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated"] } +rand = "0.7.2" +merlin = "1.2.1" +pdqselect = "0.1.0" +derive_more = "0.99.2" + +[dev-dependencies] +sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" } +sc-executor = { version = "2.0.0", path = "../../executor" } +sc-network = { version = "0.8", path = "../../network" } +sc-network-test = { version = "2.0.0", path = "../../network/test" } +sc-service = { version = "2.0.0", path = "../../service" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } +sc-block-builder = { version = "2.0.0", path = "../../block-builder" } +tokio = "0.1.22" +env_logger = "0.7.0" +tempfile = "3.1.0" + +[features] +test-helpers = [] diff --git a/core/consensus/babe/src/authorship.rs b/client/consensus/babe/src/authorship.rs similarity index 94% rename from core/consensus/babe/src/authorship.rs rename to client/consensus/babe/src/authorship.rs index 93405ff7776e6..62667ef3978c0 100644 --- a/core/consensus/babe/src/authorship.rs +++ b/client/consensus/babe/src/authorship.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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 @@ //! BABE authority selection and slot claiming. use merlin::Transcript; -use babe_primitives::{AuthorityId, BabeAuthorityWeight, BABE_ENGINE_ID, BABE_VRF_PREFIX}; -use babe_primitives::{Epoch, SlotNumber, AuthorityPair, BabePreDigest, BabeConfiguration}; -use primitives::{U256, blake2_256}; +use sp_consensus_babe::{AuthorityId, BabeAuthorityWeight, BABE_ENGINE_ID, BABE_VRF_PREFIX}; +use sp_consensus_babe::{Epoch, SlotNumber, AuthorityPair, BabePreDigest, BabeConfiguration}; +use sp_core::{U256, blake2_256}; use codec::Encode; use schnorrkel::vrf::VRFInOut; -use primitives::Pair; -use keystore::KeyStorePtr; +use sp_core::Pair; +use sc_keystore::KeyStorePtr; /// Calculates the primary selection threshold for a given authority, taking /// into account `c` (`1 - c` represents the probability of a slot being empty). @@ -162,8 +162,8 @@ pub(super) fn claim_slot( } fn get_keypair(q: &AuthorityPair) -> &schnorrkel::Keypair { - use primitives::crypto::IsWrappedBy; - primitives::sr25519::Pair::from_ref(q).as_ref() + use sp_core::crypto::IsWrappedBy; + sp_core::sr25519::Pair::from_ref(q).as_ref() } /// Claim a primary slot if it is our turn. Returns `None` if it is not our turn. diff --git a/client/consensus/babe/src/aux_schema.rs b/client/consensus/babe/src/aux_schema.rs new file mode 100644 index 0000000000000..170c2bf42d4e0 --- /dev/null +++ b/client/consensus/babe/src/aux_schema.rs @@ -0,0 +1,107 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Schema for BABE epoch changes in the aux-db. + +use log::info; +use codec::{Decode, Encode}; + +use sc_client_api::backend::AuxStore; +use sp_blockchain::{Result as ClientResult, Error as ClientError}; +use sp_runtime::traits::Block as BlockT; +use sp_consensus_babe::BabeBlockWeight; + +use super::{epoch_changes::EpochChangesFor, SharedEpochChanges}; + +const BABE_EPOCH_CHANGES: &[u8] = b"babe_epoch_changes"; + +fn block_weight_key(block_hash: H) -> Vec { + (b"block_weight", block_hash).encode() +} + +fn load_decode(backend: &B, key: &[u8]) -> ClientResult> + where + B: AuxStore, + T: Decode, +{ + let corrupt = |e: codec::Error| { + ClientError::Backend(format!("BABE DB is corrupted. Decode error: {}", e.what())) + }; + match backend.get_aux(key)? { + None => Ok(None), + Some(t) => T::decode(&mut &t[..]).map(Some).map_err(corrupt) + } +} + +/// Load or initialize persistent epoch change data from backend. +pub(crate) fn load_epoch_changes( + backend: &B, +) -> ClientResult> { + let epoch_changes = load_decode::<_, EpochChangesFor>(backend, BABE_EPOCH_CHANGES)? + .map(Into::into) + .unwrap_or_else(|| { + info!(target: "babe", + "Creating empty BABE epoch changes on what appears to be first startup." + ); + SharedEpochChanges::new() + }); + + // rebalance the tree after deserialization. this isn't strictly necessary + // since the tree is now rebalanced on every update operation. but since the + // tree wasn't rebalanced initially it's useful to temporarily leave it here + // to avoid having to wait until an import for rebalancing. + epoch_changes.lock().rebalance(); + + Ok(epoch_changes) +} + +/// Update the epoch changes on disk after a change. +pub(crate) fn write_epoch_changes( + epoch_changes: &EpochChangesFor, + write_aux: F, +) -> R where + F: FnOnce(&[(&'static [u8], &[u8])]) -> R, +{ + let encoded_epoch_changes = epoch_changes.encode(); + write_aux( + &[(BABE_EPOCH_CHANGES, encoded_epoch_changes.as_slice())], + ) +} + +/// Write the cumulative chain-weight of a block ot aux storage. +pub(crate) fn write_block_weight( + block_hash: H, + block_weight: &BabeBlockWeight, + write_aux: F, +) -> R where + F: FnOnce(&[(Vec, &[u8])]) -> R, +{ + + let key = block_weight_key(block_hash); + block_weight.using_encoded(|s| + write_aux( + &[(key, s)], + ) + ) +} + +/// Load the cumulative chain-weight associated with a block. +pub(crate) fn load_block_weight( + backend: &B, + block_hash: H, +) -> ClientResult> { + load_decode(backend, block_weight_key(block_hash).as_slice()) +} diff --git a/core/consensus/babe/src/epoch_changes.rs b/client/consensus/babe/src/epoch_changes.rs similarity index 95% rename from core/consensus/babe/src/epoch_changes.rs rename to client/consensus/babe/src/epoch_changes.rs index 09a14d286426d..01e957c4998ed 100644 --- a/core/consensus/babe/src/epoch_changes.rs +++ b/client/consensus/babe/src/epoch_changes.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,16 +20,13 @@ //! persistent DAG superimposed over the forks of the blockchain. use std::sync::Arc; -use babe_primitives::{Epoch, SlotNumber, NextEpochDescriptor}; +use sp_consensus_babe::{Epoch, SlotNumber, NextEpochDescriptor}; use fork_tree::ForkTree; use parking_lot::{Mutex, MutexGuard}; -use sr_primitives::traits::{Block as BlockT, NumberFor, One, Zero}; +use sp_runtime::traits::{Block as BlockT, NumberFor, One, Zero}; use codec::{Encode, Decode}; -use client::error::Error as ClientError; -use client::utils as client_utils; -use client::blockchain::HeaderBackend; -use header_metadata::HeaderMetadata; -use primitives::H256; +use sc_client_api::utils::is_descendent_of; +use sp_blockchain::{HeaderMetadata, HeaderBackend, Error as ClientError}; use std::ops::Add; /// A builder for `is_descendent_of` functions. @@ -59,20 +56,18 @@ pub(crate) fn descendent_query(client: &H) -> HeaderBackendDescendentB /// `IsDescendentOfBuilder` for header backends. pub(crate) struct HeaderBackendDescendentBuilder(H, std::marker::PhantomData); -// TODO: relying on Hash = H256 is awful. -// https://github.com/paritytech/substrate/issues/3624 -impl<'a, H, Block> IsDescendentOfBuilder +impl<'a, H, Block> IsDescendentOfBuilder for HeaderBackendDescendentBuilder<&'a H, Block> where H: HeaderBackend + HeaderMetadata, - Block: BlockT, + Block: BlockT, { type Error = ClientError; - type IsDescendentOf = Box Result + 'a>; + type IsDescendentOf = Box Result + 'a>; - fn build_is_descendent_of(&self, current: Option<(H256, H256)>) + fn build_is_descendent_of(&self, current: Option<(Block::Hash, Block::Hash)>) -> Self::IsDescendentOf { - Box::new(client_utils::is_descendent_of(self.0, current)) + Box::new(is_descendent_of(self.0, current)) } } @@ -190,6 +185,12 @@ impl EpochChanges where EpochChanges { inner: ForkTree::new() } } + /// Rebalances the tree of epoch changes so that it is sorted by length of + /// fork (longest fork first). + pub fn rebalance(&mut self) { + self.inner.rebalance() + } + /// Prune out finalized epochs, except for the ancestor of the finalized /// block. The given slot should be the slot number at which the finalized /// block was authored. diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs new file mode 100644 index 0000000000000..bbf19b706601f --- /dev/null +++ b/client/consensus/babe/src/lib.rs @@ -0,0 +1,1274 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # BABE (Blind Assignment for Blockchain Extension) +//! +//! BABE is a slot-based block production mechanism which uses a VRF PRNG to +//! randomly perform the slot allocation. On every slot, all the authorities +//! generate a new random number with the VRF function and if it is lower than a +//! given threshold (which is proportional to their weight/stake) they have a +//! right to produce a block. The proof of the VRF function execution will be +//! used by other peer to validate the legitimacy of the slot claim. +//! +//! The engine is also responsible for collecting entropy on-chain which will be +//! used to seed the given VRF PRNG. An epoch is a contiguous number of slots +//! under which we will be using the same authority set. During an epoch all VRF +//! outputs produced as a result of block production will be collected on an +//! on-chain randomness pool. Epoch changes are announced one epoch in advance, +//! i.e. when ending epoch N, we announce the parameters (randomness, +//! authorities, etc.) for epoch N+2. +//! +//! Since the slot assignment is randomized, it is possible that a slot is +//! assigned to multiple validators in which case we will have a temporary fork, +//! or that a slot is assigned to no validator in which case no block is +//! produced. Which means that block times are not deterministic. +//! +//! The protocol has a parameter `c` [0, 1] for which `1 - c` is the probability +//! of a slot being empty. The choice of this parameter affects the security of +//! the protocol relating to maximum tolerable network delays. +//! +//! In addition to the VRF-based slot assignment described above, which we will +//! call primary slots, the engine also supports a deterministic secondary slot +//! assignment. Primary slots take precedence over secondary slots, when +//! authoring the node starts by trying to claim a primary slot and falls back +//! to a secondary slot claim attempt. The secondary slot assignment is done +//! by picking the authority at index: +//! +//! `blake2_256(epoch_randomness ++ slot_number) % authorities_len`. +//! +//! The fork choice rule is weight-based, where weight equals the number of +//! primary blocks in the chain. We will pick the heaviest chain (more primary +//! blocks) and will go with the longest one in case of a tie. +//! +//! An in-depth description and analysis of the protocol can be found here: +//! + +#![forbid(unsafe_code)] +#![warn(missing_docs)] +pub use sp_consensus_babe::{ + BabeApi, ConsensusLog, BABE_ENGINE_ID, BabePreDigest, SlotNumber, BabeConfiguration, + CompatibleDigestItem, +}; +pub use sp_consensus::SyncOracle; +use std::{collections::HashMap, sync::Arc, u64, pin::Pin, time::{Instant, Duration}}; +use sp_consensus_babe; +use sp_consensus::{ImportResult, CanAuthorWith}; +use sp_consensus::import_queue::{ + BoxJustificationImport, BoxFinalityProofImport, +}; +use sp_runtime::{ + generic::{BlockId, OpaqueDigestItemId}, Justification, + traits::{Block as BlockT, Header, DigestItemFor, Zero}, +}; +use sp_api::ProvideRuntimeApi; +use sc_keystore::KeyStorePtr; +use parking_lot::Mutex; +use sp_core::Pair; +use sp_inherents::{InherentDataProviders, InherentData}; +use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG}; +use sp_consensus::{ + self, BlockImport, Environment, Proposer, BlockCheckParams, + ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError, + SelectChain, SlotData, +}; +use sp_consensus_babe::inherents::BabeInherentData; +use sp_timestamp::{TimestampInherentData, InherentType as TimestampInherent}; +use sp_consensus::import_queue::{Verifier, BasicQueue, CacheKeyId}; +use sc_client_api::{ + backend::{AuxStore, Backend}, + call_executor::CallExecutor, + BlockchainEvents, ProvideUncles, +}; +use sc_client::Client; + +use sp_block_builder::BlockBuilder as BlockBuilderApi; + +use futures::prelude::*; +use log::{warn, debug, info, trace}; +use sc_consensus_slots::{ + SlotWorker, SlotInfo, SlotCompatible, StorageChanges, CheckedHeader, check_equivocation, +}; +use epoch_changes::descendent_query; +use sp_blockchain::{ + Result as ClientResult, Error as ClientError, + HeaderBackend, ProvideCache, HeaderMetadata +}; +use schnorrkel::SignatureError; + +use sp_api::ApiExt; + +mod aux_schema; +mod verification; +mod epoch_changes; +mod authorship; +#[cfg(test)] +mod tests; +pub use sp_consensus_babe::{ + AuthorityId, AuthorityPair, AuthoritySignature, Epoch, NextEpochDescriptor, +}; +pub use epoch_changes::{EpochChanges, EpochChangesFor, SharedEpochChanges}; + + +#[derive(derive_more::Display, Debug)] +enum Error { + #[display(fmt = "Multiple BABE pre-runtime digests, rejecting!")] + MultiplePreRuntimeDigests, + #[display(fmt = "No BABE pre-runtime digest found")] + NoPreRuntimeDigest, + #[display(fmt = "Multiple BABE epoch change digests, rejecting!")] + MultipleEpochChangeDigests, + #[display(fmt = "Could not extract timestamp and slot: {:?}", _0)] + Extraction(sp_consensus::Error), + #[display(fmt = "Could not fetch epoch at {:?}", _0)] + FetchEpoch(B::Hash), + #[display(fmt = "Header {:?} rejected: too far in the future", _0)] + TooFarInFuture(B::Hash), + #[display(fmt = "Parent ({}) of {} unavailable. Cannot import", _0, _1)] + ParentUnavailable(B::Hash, B::Hash), + #[display(fmt = "Slot number must increase: parent slot: {}, this slot: {}", _0, _1)] + SlotNumberMustIncrease(u64, u64), + #[display(fmt = "Header {:?} has a bad seal", _0)] + HeaderBadSeal(B::Hash), + #[display(fmt = "Header {:?} is unsealed", _0)] + HeaderUnsealed(B::Hash), + #[display(fmt = "Slot author not found")] + SlotAuthorNotFound, + #[display(fmt = "Secondary slot assignments are disabled for the current epoch.")] + SecondarySlotAssignmentsDisabled, + #[display(fmt = "Bad signature on {:?}", _0)] + BadSignature(B::Hash), + #[display(fmt = "Invalid author: Expected secondary author: {:?}, got: {:?}.", _0, _1)] + InvalidAuthor(AuthorityId, AuthorityId), + #[display(fmt = "No secondary author expected.")] + NoSecondaryAuthorExpected, + #[display(fmt = "VRF verification of block by author {:?} failed: threshold {} exceeded", _0, _1)] + VRFVerificationOfBlockFailed(AuthorityId, u128), + #[display(fmt = "VRF verification failed: {:?}", _0)] + VRFVerificationFailed(SignatureError), + #[display(fmt = "Could not fetch parent header: {:?}", _0)] + FetchParentHeader(sp_blockchain::Error), + #[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)] + ExpectedEpochChange(B::Hash, u64), + #[display(fmt = "Could not look up epoch: {:?}", _0)] + CouldNotLookUpEpoch(Box>), + #[display(fmt = "Block {} is not valid under any epoch.", _0)] + BlockNotValid(B::Hash), + #[display(fmt = "Unexpected epoch change")] + UnexpectedEpochChange, + #[display(fmt = "Parent block of {} has no associated weight", _0)] + ParentBlockNoAssociatedWeight(B::Hash), + #[display(fmt = "Checking inherents failed: {}", _0)] + CheckInherents(String), + Client(sp_blockchain::Error), + Runtime(sp_inherents::Error), + ForkTree(Box>), +} + +impl std::convert::From> for String { + fn from(error: Error) -> String { + error.to_string() + } +} + +fn babe_err(error: Error) -> Error { + debug!(target: "babe", "{}", error); + error +} + +macro_rules! babe_info { + ($($i: expr),+) => { + { + info!(target: "babe", $($i),+); + format!($($i),+) + } + }; +} + +/// A slot duration. Create with `get_or_compute`. +// FIXME: Once Rust has higher-kinded types, the duplication between this +// and `super::babe::Config` can be eliminated. +// https://github.com/paritytech/substrate/issues/2434 +#[derive(Clone)] +pub struct Config(sc_consensus_slots::SlotDuration); + +impl Config { + /// Either fetch the slot duration from disk or compute it from the genesis + /// state. + pub fn get_or_compute(client: &C) -> ClientResult where + C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi, + { + trace!(target: "babe", "Getting slot duration"); + match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) { + Ok(s) => Ok(s), + Err(s) => { + warn!(target: "babe", "Failed to get slot duration"); + Err(s) + } + } + } + + /// Create the genesis epoch (epoch #0). This is defined to start at the slot of + /// the first block, so that has to be provided. + pub fn genesis_epoch(&self, slot_number: SlotNumber) -> Epoch { + Epoch { + epoch_index: 0, + start_slot: slot_number, + duration: self.epoch_length, + authorities: self.genesis_authorities.clone(), + randomness: self.randomness.clone(), + } + } +} + +impl std::ops::Deref for Config { + type Target = BabeConfiguration; + + fn deref(&self) -> &BabeConfiguration { + &*self.0 + } +} + +/// Parameters for BABE. +pub struct BabeParams { + /// The keystore that manages the keys of the node. + pub keystore: KeyStorePtr, + + /// The client to use + pub client: Arc, + + /// The SelectChain Strategy + pub select_chain: SC, + + /// The environment we are producing blocks for. + pub env: E, + + /// The underlying block-import object to supply our produced blocks to. + /// This must be a `BabeBlockImport` or a wrapper of it, otherwise + /// critical consensus logic will be omitted. + pub block_import: I, + + /// A sync oracle + pub sync_oracle: SO, + + /// Providers for inherent data. + pub inherent_data_providers: InherentDataProviders, + + /// Force authoring of blocks even if we are offline + pub force_authoring: bool, + + /// The source of timestamps for relative slots + pub babe_link: BabeLink, + + /// Checks if the current native implementation can author with a runtime at a given block. + pub can_author_with: CAW, +} + +/// Start the babe worker. The returned future should be run in a tokio runtime. +pub fn start_babe(BabeParams { + keystore, + client, + select_chain, + env, + block_import, + sync_oracle, + inherent_data_providers, + force_authoring, + babe_link, + can_author_with, +}: BabeParams) -> Result< + impl futures01::Future, + sp_consensus::Error, +> where + B: BlockT, + C: ProvideRuntimeApi + ProvideCache + ProvideUncles + BlockchainEvents + + HeaderBackend + HeaderMetadata + Send + Sync + 'static, + C::Api: BabeApi, + SC: SelectChain + 'static, + E: Environment + Send + Sync, + E::Proposer: Proposer>, + I: BlockImport> + Send + + Sync + 'static, + Error: std::error::Error + Send + From + From + 'static, + SO: SyncOracle + Send + Sync + Clone, + CAW: CanAuthorWith + Send, +{ + let config = babe_link.config; + let worker = BabeWorker { + client: client.clone(), + block_import: Arc::new(Mutex::new(block_import)), + env, + sync_oracle: sync_oracle.clone(), + force_authoring, + keystore, + epoch_changes: babe_link.epoch_changes.clone(), + config: config.clone(), + }; + + register_babe_inherent_data_provider(&inherent_data_providers, config.slot_duration())?; + sc_consensus_uncles::register_uncles_inherent_data_provider( + client.clone(), + select_chain.clone(), + &inherent_data_providers, + )?; + + babe_info!("Starting BABE Authorship worker"); + let slot_worker = sc_consensus_slots::start_slot_worker( + config.0, + select_chain, + worker, + sync_oracle, + inherent_data_providers, + babe_link.time_source, + can_author_with, + ); + + Ok(slot_worker.map(|_| Ok::<(), ()>(())).compat()) +} + +struct BabeWorker { + client: Arc, + block_import: Arc>, + env: E, + sync_oracle: SO, + force_authoring: bool, + keystore: KeyStorePtr, + epoch_changes: SharedEpochChanges, + config: Config, +} + +impl sc_consensus_slots::SimpleSlotWorker for BabeWorker where + B: BlockT, + C: ProvideRuntimeApi + + ProvideCache + + HeaderBackend + + HeaderMetadata, + C::Api: BabeApi, + E: Environment, + E::Proposer: Proposer>, + I: BlockImport> + Send + Sync + 'static, + SO: SyncOracle + Send + Clone, + Error: std::error::Error + Send + From + From + 'static, +{ + type EpochData = Epoch; + type Claim = (BabePreDigest, AuthorityPair); + type SyncOracle = SO; + type Proposer = E::Proposer; + type BlockImport = I; + + fn logging_target(&self) -> &'static str { + "babe" + } + + fn block_import(&self) -> Arc> { + self.block_import.clone() + } + + fn epoch_data( + &self, + parent: &B::Header, + slot_number: u64, + ) -> Result { + self.epoch_changes.lock().epoch_for_child_of( + descendent_query(&*self.client), + &parent.hash(), + parent.number().clone(), + slot_number, + |slot| self.config.genesis_epoch(slot) + ) + .map_err(|e| ConsensusError::ChainLookup(format!("{:?}", e)))? + .map(|e| e.into_inner()) + .ok_or(sp_consensus::Error::InvalidAuthoritiesSet) + } + + fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize { + epoch_data.authorities.len() + } + + fn claim_slot( + &self, + _parent_header: &B::Header, + slot_number: SlotNumber, + epoch_data: &Epoch, + ) -> Option { + debug!(target: "babe", "Attempting to claim slot {}", slot_number); + let s = authorship::claim_slot( + slot_number, + epoch_data, + &*self.config, + &self.keystore, + ); + + if let Some(_) = s { + debug!(target: "babe", "Claimed slot {}", slot_number); + } + + s + } + + fn pre_digest_data( + &self, + _slot_number: u64, + claim: &Self::Claim, + ) -> Vec> { + vec![ + as CompatibleDigestItem>::babe_pre_digest(claim.0.clone()), + ] + } + + fn block_import_params(&self) -> Box, + StorageChanges, + Self::Claim, + ) -> sp_consensus::BlockImportParams + Send> { + Box::new(|header, header_hash, body, storage_changes, (_, pair)| { + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let signature = pair.sign(header_hash.as_ref()); + let digest_item = as CompatibleDigestItem>::babe_seal(signature); + + BlockImportParams { + origin: BlockOrigin::Own, + header, + justification: None, + post_digests: vec![digest_item], + body: Some(body), + storage_changes: Some(storage_changes), + finalized: false, + auxiliary: Vec::new(), // block-weight is written in block import. + // TODO: block-import handles fork choice and this shouldn't even have the + // option to specify one. + // https://github.com/paritytech/substrate/issues/3623 + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + } + }) + } + + fn force_authoring(&self) -> bool { + self.force_authoring + } + + fn sync_oracle(&mut self) -> &mut Self::SyncOracle { + &mut self.sync_oracle + } + + fn proposer(&mut self, block: &B::Header) -> Result { + self.env.init(block).map_err(|e| { + sp_consensus::Error::ClientImport(format!("{:?}", e)) + }) + } + + fn proposing_remaining_duration( + &self, + head: &B::Header, + slot_info: &SlotInfo + ) -> Option { + // never give more than 2^this times the lenience. + const BACKOFF_CAP: u64 = 8; + + // how many slots it takes before we double the lenience. + const BACKOFF_STEP: u64 = 2; + + let slot_remaining = self.slot_remaining_duration(slot_info); + let parent_slot = match find_pre_digest::(head) { + Err(_) => return Some(slot_remaining), + Ok(d) => d.slot_number(), + }; + + // we allow a lenience of the number of slots since the head of the + // chain was produced, minus 1 (since there is always a difference of at least 1) + // + // exponential back-off. + // in normal cases we only attempt to issue blocks up to the end of the slot. + // when the chain has been stalled for a few slots, we give more lenience. + let slot_lenience = slot_info.number.saturating_sub(parent_slot + 1); + + let slot_lenience = std::cmp::min(slot_lenience, BACKOFF_CAP); + let slot_duration = slot_info.duration << (slot_lenience / BACKOFF_STEP); + + if slot_lenience >= 1 { + debug!(target: "babe", "No block for {} slots. Applying 2^({}/{}) lenience", + slot_lenience, slot_lenience, BACKOFF_STEP); + } + + let slot_lenience = Duration::from_secs(slot_duration); + Some(slot_lenience + slot_remaining) + } +} + +impl SlotWorker for BabeWorker where + B: BlockT, + C: ProvideRuntimeApi + + ProvideCache + + HeaderBackend + + HeaderMetadata + Send + Sync, + C::Api: BabeApi, + E: Environment + Send + Sync, + E::Proposer: Proposer>, + I: BlockImport> + Send + Sync + 'static, + SO: SyncOracle + Send + Sync + Clone, + Error: std::error::Error + Send + From + From + 'static, +{ + type OnSlot = Pin> + Send>>; + + fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot { + >::on_slot(self, chain_head, slot_info) + } +} + +/// Extract the BABE pre digest from the given header. Pre-runtime digests are +/// mandatory, the function will return `Err` if none is found. +fn find_pre_digest(header: &B::Header) -> Result> +{ + // genesis block doesn't contain a pre digest so let's generate a + // dummy one to not break any invariants in the rest of the code + if header.number().is_zero() { + return Ok(BabePreDigest::Secondary { + slot_number: 0, + authority_index: 0, + }); + } + + let mut pre_digest: Option<_> = None; + for log in header.digest().logs() { + trace!(target: "babe", "Checking log {:?}, looking for pre runtime digest", log); + match (log.as_babe_pre_digest(), pre_digest.is_some()) { + (Some(_), true) => return Err(babe_err(Error::MultiplePreRuntimeDigests)), + (None, _) => trace!(target: "babe", "Ignoring digest not meant for us"), + (s, false) => pre_digest = s, + } + } + pre_digest.ok_or_else(|| babe_err(Error::NoPreRuntimeDigest)) +} + +/// Extract the BABE epoch change digest from the given header, if it exists. +fn find_next_epoch_digest(header: &B::Header) + -> Result, Error> + where DigestItemFor: CompatibleDigestItem, +{ + let mut epoch_digest: Option<_> = None; + for log in header.digest().logs() { + trace!(target: "babe", "Checking log {:?}, looking for epoch change digest.", log); + let log = log.try_to::(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)); + match (log, epoch_digest.is_some()) { + (Some(ConsensusLog::NextEpochData(_)), true) => return Err(babe_err(Error::MultipleEpochChangeDigests)), + (Some(ConsensusLog::NextEpochData(epoch)), false) => epoch_digest = Some(epoch), + _ => trace!(target: "babe", "Ignoring digest not meant for us"), + } + } + + Ok(epoch_digest) +} + + +#[derive(Default, Clone)] +struct TimeSource(Arc, Vec<(Instant, u64)>)>>); + +impl SlotCompatible for TimeSource { + fn extract_timestamp_and_slot( + &self, + data: &InherentData, + ) -> Result<(TimestampInherent, u64, std::time::Duration), sp_consensus::Error> { + trace!(target: "babe", "extract timestamp"); + data.timestamp_inherent_data() + .and_then(|t| data.babe_inherent_data().map(|a| (t, a))) + .map_err(Into::into) + .map_err(sp_consensus::Error::InherentData) + .map(|(x, y)| (x, y, self.0.lock().0.take().unwrap_or_default())) + } +} + +/// State that must be shared between the import queue and the authoring logic. +#[derive(Clone)] +pub struct BabeLink { + time_source: TimeSource, + epoch_changes: SharedEpochChanges, + config: Config, +} +/// A verifier for Babe blocks. +pub struct BabeVerifier { + client: Arc>, + api: Arc, + inherent_data_providers: sp_inherents::InherentDataProviders, + config: Config, + epoch_changes: SharedEpochChanges, + time_source: TimeSource, +} + +impl BabeVerifier { + fn check_inherents( + &self, + block: Block, + block_id: BlockId, + inherent_data: InherentData, + ) -> Result<(), Error> + where + PRA: ProvideRuntimeApi, + PRA::Api: BlockBuilderApi + { + let inherent_res = self.api.runtime_api().check_inherents( + &block_id, + block, + inherent_data, + ).map_err(Error::Client)?; + + if !inherent_res.ok() { + inherent_res + .into_errors() + .try_for_each(|(i, e)| { + Err(Error::CheckInherents(self.inherent_data_providers.error_to_string(&i, &e))) + }) + } else { + Ok(()) + } + } +} + +#[allow(dead_code)] +fn median_algorithm( + median_required_blocks: u64, + slot_duration: u64, + slot_number: u64, + slot_now: u64, + time_source: &mut (Option, Vec<(Instant, u64)>), +) { + let num_timestamps = time_source.1.len(); + if num_timestamps as u64 >= median_required_blocks && median_required_blocks > 0 { + let mut new_list: Vec<_> = time_source.1.iter().map(|&(t, sl)| { + let offset: u128 = u128::from(slot_duration) + .checked_mul(1_000_000u128) // self.config.slot_duration returns milliseconds + .and_then(|x| { + x.checked_mul(u128::from(slot_number).saturating_sub(u128::from(sl))) + }) + .expect("we cannot have timespans long enough for this to overflow; qed"); + + const NANOS_PER_SEC: u32 = 1_000_000_000; + let nanos = (offset % u128::from(NANOS_PER_SEC)) as u32; + let secs = (offset / u128::from(NANOS_PER_SEC)) as u64; + + t + Duration::new(secs, nanos) + }).collect(); + + // Use a partial sort to move the median timestamp to the middle of the list + pdqselect::select(&mut new_list, num_timestamps / 2); + + let &median = new_list + .get(num_timestamps / 2) + .expect("we have at least one timestamp, so this is a valid index; qed"); + + let now = Instant::now(); + if now >= median { + time_source.0.replace(now - median); + } + + time_source.1.clear(); + } else { + time_source.1.push((Instant::now(), slot_now)) + } +} + +impl Verifier for BabeVerifier where + Block: BlockT, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + RA: Send + Sync, + PRA: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache, + PRA::Api: BlockBuilderApi + + BabeApi, +{ + fn verify( + &mut self, + origin: BlockOrigin, + header: Block::Header, + justification: Option, + mut body: Option>, + ) -> Result<(BlockImportParams, Option)>>), String> { + trace!( + target: "babe", + "Verifying origin: {:?} header: {:?} justification: {:?} body: {:?}", + origin, + header, + justification, + body, + ); + + debug!(target: "babe", "We have {:?} logs in this header", header.digest().logs().len()); + let mut inherent_data = self + .inherent_data_providers + .create_inherent_data() + .map_err( Error::::Runtime)?; + + let (_, slot_now, _) = self.time_source.extract_timestamp_and_slot(&inherent_data) + .map_err(Error::::Extraction)?; + + let hash = header.hash(); + let parent_hash = *header.parent_hash(); + + let parent_header_metadata = self.client.header_metadata(parent_hash) + .map_err(Error::::FetchParentHeader)?; + + let pre_digest = find_pre_digest::(&header)?; + let epoch = { + let epoch_changes = self.epoch_changes.lock(); + epoch_changes.epoch_for_child_of( + descendent_query(&*self.client), + &parent_hash, + parent_header_metadata.number, + pre_digest.slot_number(), + |slot| self.config.genesis_epoch(slot), + ) + .map_err(|e| Error::::ForkTree(Box::new(e)))? + .ok_or_else(|| Error::::FetchEpoch(parent_hash))? + }; + + // We add one to the current slot to allow for some small drift. + // FIXME #1019 in the future, alter this queue to allow deferring of headers + let v_params = verification::VerificationParams { + header: header.clone(), + pre_digest: Some(pre_digest.clone()), + slot_now: slot_now + 1, + epoch: epoch.as_ref(), + config: &self.config, + }; + + match verification::check_header::(v_params)? { + CheckedHeader::Checked(pre_header, verified_info) => { + let babe_pre_digest = verified_info.pre_digest.as_babe_pre_digest() + .expect("check_header always returns a pre-digest digest item; qed"); + + let slot_number = babe_pre_digest.slot_number(); + + let author = verified_info.author; + + // the header is valid but let's check if there was something else already + // proposed at the same slot by the given author + if let Some(equivocation_proof) = check_equivocation( + &*self.api, + slot_now, + babe_pre_digest.slot_number(), + &header, + &author, + ).map_err(|e| e.to_string())? { + info!( + "Slot author {:?} is equivocating at slot {} with headers {:?} and {:?}", + author, + babe_pre_digest.slot_number(), + equivocation_proof.fst_header().hash(), + equivocation_proof.snd_header().hash(), + ); + } + + // if the body is passed through, we need to use the runtime + // to check that the internally-set timestamp in the inherents + // actually matches the slot set in the seal. + if let Some(inner_body) = body.take() { + inherent_data.babe_replace_inherent_data(slot_number); + let block = Block::new(pre_header.clone(), inner_body); + + self.check_inherents( + block.clone(), + BlockId::Hash(parent_hash), + inherent_data, + )?; + + let (_, inner_body) = block.deconstruct(); + body = Some(inner_body); + } + + trace!(target: "babe", "Checked {:?}; importing.", pre_header); + telemetry!( + CONSENSUS_TRACE; + "babe.checked_and_importing"; + "pre_header" => ?pre_header); + + let block_import_params = BlockImportParams { + origin, + header: pre_header, + post_digests: vec![verified_info.seal], + body, + storage_changes: None, + finalized: false, + justification, + auxiliary: Vec::new(), + // TODO: block-import handles fork choice and this shouldn't even have the + // option to specify one. + // https://github.com/paritytech/substrate/issues/3623 + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + + Ok((block_import_params, Default::default())) + } + CheckedHeader::Deferred(a, b) => { + debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); + telemetry!(CONSENSUS_DEBUG; "babe.header_too_far_in_future"; + "hash" => ?hash, "a" => ?a, "b" => ?b + ); + Err(Error::::TooFarInFuture(hash).into()) + } + } + } +} + +/// The BABE import queue type. +pub type BabeImportQueue = BasicQueue; + +/// Register the babe inherent data provider, if not registered already. +fn register_babe_inherent_data_provider( + inherent_data_providers: &InherentDataProviders, + slot_duration: u64, +) -> Result<(), sp_consensus::Error> { + debug!(target: "babe", "Registering"); + if !inherent_data_providers.has_provider(&sp_consensus_babe::inherents::INHERENT_IDENTIFIER) { + inherent_data_providers + .register_provider(sp_consensus_babe::inherents::InherentDataProvider::new(slot_duration)) + .map_err(Into::into) + .map_err(sp_consensus::Error::InherentData) + } else { + Ok(()) + } +} + +/// A block-import handler for BABE. +/// +/// This scans each imported block for epoch change signals. The signals are +/// tracked in a tree (of all forks), and the import logic validates all epoch +/// change transitions, i.e. whether a given epoch change is expected or whether +/// it is missing. +/// +/// The epoch change tree should be pruned as blocks are finalized. +pub struct BabeBlockImport { + inner: I, + client: Arc>, + api: Arc, + epoch_changes: SharedEpochChanges, + config: Config, +} + +impl Clone for BabeBlockImport { + fn clone(&self) -> Self { + BabeBlockImport { + inner: self.inner.clone(), + client: self.client.clone(), + api: self.api.clone(), + epoch_changes: self.epoch_changes.clone(), + config: self.config.clone(), + } + } +} + +impl BabeBlockImport { + fn new( + client: Arc>, + api: Arc, + epoch_changes: SharedEpochChanges, + block_import: I, + config: Config, + ) -> Self { + BabeBlockImport { + client, + api, + inner: block_import, + epoch_changes, + config, + } + } +} + +impl BlockImport for BabeBlockImport where + Block: BlockT, + I: BlockImport> + Send + Sync, + I::Error: Into, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + Client: AuxStore, + RA: Send + Sync, + PRA: ProvideRuntimeApi + ProvideCache, + PRA::Api: BabeApi + ApiExt, +{ + type Error = ConsensusError; + type Transaction = sp_api::TransactionFor; + + fn import_block( + &mut self, + mut block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { + let hash = block.post_header().hash(); + let number = block.header.number().clone(); + + // early exit if block already in chain, otherwise the check for + // epoch changes will error when trying to re-import an epoch change + match self.client.status(BlockId::Hash(hash)) { + Ok(sp_blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), + Ok(sp_blockchain::BlockStatus::Unknown) => {}, + Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), + } + + let pre_digest = find_pre_digest::(&block.header) + .expect("valid babe headers must contain a predigest; \ + header has been already verified; qed"); + let slot_number = pre_digest.slot_number(); + + let parent_hash = *block.header.parent_hash(); + let parent_header = self.client.header(&BlockId::Hash(parent_hash)) + .map_err(|e| ConsensusError::ChainLookup(e.to_string()))? + .ok_or_else(|| ConsensusError::ChainLookup(babe_err( + Error::::ParentUnavailable(parent_hash, hash) + ).into()))?; + + let parent_slot = find_pre_digest::(&parent_header) + .map(|d| d.slot_number()) + .expect("parent is non-genesis; valid BABE headers contain a pre-digest; \ + header has already been verified; qed"); + + // make sure that slot number is strictly increasing + if slot_number <= parent_slot { + return Err( + ConsensusError::ClientImport(babe_err( + Error::::SlotNumberMustIncrease(parent_slot, slot_number) + ).into()) + ); + } + + let mut epoch_changes = self.epoch_changes.lock(); + + // check if there's any epoch change expected to happen at this slot. + // `epoch` is the epoch to verify the block under, and `first_in_epoch` is true + // if this is the first block in its chain for that epoch. + // + // also provides the total weight of the chain, including the imported block. + let (epoch, first_in_epoch, parent_weight) = { + let parent_weight = if *parent_header.number() == Zero::zero() { + 0 + } else { + aux_schema::load_block_weight(&*self.client, parent_hash) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))? + .ok_or_else(|| ConsensusError::ClientImport( + babe_err(Error::::ParentBlockNoAssociatedWeight(hash)).into() + ))? + }; + + let epoch = epoch_changes.epoch_for_child_of( + descendent_query(&*self.client), + &parent_hash, + *parent_header.number(), + slot_number, + |slot| self.config.genesis_epoch(slot), + ) + .map_err(|e: fork_tree::Error| ConsensusError::ChainLookup( + babe_err(Error::::CouldNotLookUpEpoch(Box::new(e))).into() + ))? + .ok_or_else(|| ConsensusError::ClientImport( + babe_err(Error::::BlockNotValid(hash)).into() + ))?; + + let first_in_epoch = parent_slot < epoch.as_ref().start_slot; + (epoch, first_in_epoch, parent_weight) + }; + + let total_weight = parent_weight + pre_digest.added_weight(); + + // search for this all the time so we can reject unexpected announcements. + let next_epoch_digest = find_next_epoch_digest::(&block.header) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; + + match (first_in_epoch, next_epoch_digest.is_some()) { + (true, true) => {}, + (false, false) => {}, + (true, false) => { + return Err( + ConsensusError::ClientImport( + babe_err(Error::::ExpectedEpochChange(hash, slot_number)).into(), + ) + ); + }, + (false, true) => { + return Err(ConsensusError::ClientImport(Error::::UnexpectedEpochChange.into())); + }, + } + + // if there's a pending epoch we'll save the previous epoch changes here + // this way we can revert it if there's any error + let mut old_epoch_changes = None; + + let info = self.client.chain_info(); + + if let Some(next_epoch_descriptor) = next_epoch_digest { + let next_epoch = epoch.increment(next_epoch_descriptor); + + old_epoch_changes = Some(epoch_changes.clone()); + + babe_info!("New epoch {} launching at block {} (block slot {} >= start slot {}).", + epoch.as_ref().epoch_index, hash, slot_number, epoch.as_ref().start_slot); + babe_info!("Next epoch starts at slot {}", next_epoch.as_ref().start_slot); + + // prune the tree of epochs not part of the finalized chain or + // that are not live anymore, and then track the given epoch change + // in the tree. + // NOTE: it is important that these operations are done in this + // order, otherwise if pruning after import the `is_descendent_of` + // used by pruning may not know about the block that is being + // imported. + let prune_and_import = || { + prune_finalized( + &self.client, + &mut epoch_changes, + )?; + + epoch_changes.import( + descendent_query(&*self.client), + hash, + number, + *block.header.parent_hash(), + next_epoch, + ).map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))?; + + Ok(()) + }; + + if let Err(e) = prune_and_import() { + debug!(target: "babe", "Failed to launch next epoch: {:?}", e); + *epoch_changes = old_epoch_changes.expect("set `Some` above and not taken; qed"); + return Err(e); + } + + crate::aux_schema::write_epoch_changes::( + &*epoch_changes, + |insert| block.auxiliary.extend( + insert.iter().map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) + ) + ); + } + + aux_schema::write_block_weight( + hash, + &total_weight, + |values| block.auxiliary.extend( + values.iter().map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) + ), + ); + + // The fork choice rule is that we pick the heaviest chain (i.e. + // more primary blocks), if there's a tie we go with the longest + // chain. + block.fork_choice = { + let (last_best, last_best_number) = (info.best_hash, info.best_number); + + let last_best_weight = if &last_best == block.header.parent_hash() { + // the parent=genesis case is already covered for loading parent weight, + // so we don't need to cover again here. + parent_weight + } else { + aux_schema::load_block_weight(&*self.client, last_best) + .map_err(|e| ConsensusError::ChainLookup(format!("{:?}", e)))? + .ok_or_else( + || ConsensusError::ChainLookup(format!("No block weight for parent header.")) + )? + }; + + ForkChoiceStrategy::Custom(if total_weight > last_best_weight { + true + } else if total_weight == last_best_weight { + number > last_best_number + } else { + false + }) + }; + + let import_result = self.inner.import_block(block, new_cache); + + // revert to the original epoch changes in case there's an error + // importing the block + if let Err(_) = import_result { + if let Some(old_epoch_changes) = old_epoch_changes { + *epoch_changes = old_epoch_changes; + } + } + + import_result.map_err(Into::into) + } + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + self.inner.check_block(block).map_err(Into::into) + } +} + +/// Gets the best finalized block and its slot, and prunes the given epoch tree. +fn prune_finalized( + client: &Client, + epoch_changes: &mut EpochChangesFor, +) -> Result<(), ConsensusError> where + Block: BlockT, + E: CallExecutor + Send + Sync, + B: Backend, + RA: Send + Sync, +{ + let info = client.chain_info(); + + let finalized_slot = { + let finalized_header = client.header(&BlockId::Hash(info.finalized_hash)) + .map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))? + .expect("best finalized hash was given by client; \ + finalized headers must exist in db; qed"); + + find_pre_digest::(&finalized_header) + .expect("finalized header must be valid; \ + valid blocks have a pre-digest; qed") + .slot_number() + }; + + epoch_changes.prune_finalized( + descendent_query(&*client), + &info.finalized_hash, + info.finalized_number, + finalized_slot, + ).map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))?; + + Ok(()) +} + +/// Produce a BABE block-import object to be used later on in the construction of +/// an import-queue. +/// +/// Also returns a link object used to correctly instantiate the import queue +/// and background worker. +pub fn block_import( + config: Config, + wrapped_block_import: I, + client: Arc>, + api: Arc, +) -> ClientResult<(BabeBlockImport, BabeLink)> where + B: Backend, + E: CallExecutor + Send + Sync, + RA: Send + Sync, + Client: AuxStore, +{ + let epoch_changes = aux_schema::load_epoch_changes(&*client)?; + let link = BabeLink { + epoch_changes: epoch_changes.clone(), + time_source: Default::default(), + config: config.clone(), + }; + + // NOTE: this isn't entirely necessary, but since we didn't use to prune the + // epoch tree it is useful as a migration, so that nodes prune long trees on + // startup rather than waiting until importing the next epoch change block. + prune_finalized( + &client, + &mut epoch_changes.lock(), + )?; + + let import = BabeBlockImport::new( + client, + api, + epoch_changes, + wrapped_block_import, + config, + ); + + Ok((import, link)) +} + +/// Start an import queue for the BABE consensus algorithm. +/// +/// This method returns the import queue, some data that needs to be passed to the block authoring +/// logic (`BabeLink`), and a future that must be run to +/// completion and is responsible for listening to finality notifications and +/// pruning the epoch changes tree. +/// +/// The block import object provided must be the `BabeBlockImport` or a wrapper +/// of it, otherwise crucial import logic will be omitted. +pub fn import_queue( + babe_link: BabeLink, + block_import: I, + justification_import: Option>, + finality_proof_import: Option>, + client: Arc>, + api: Arc, + inherent_data_providers: InherentDataProviders, +) -> ClientResult>> where + B: Backend + 'static, + I: BlockImport> + + Send + Sync + 'static, + E: CallExecutor + Clone + Send + Sync + 'static, + RA: Send + Sync + 'static, + PRA: ProvideRuntimeApi + ProvideCache + Send + Sync + AuxStore + 'static, + PRA::Api: BlockBuilderApi + BabeApi + ApiExt, +{ + register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?; + + let verifier = BabeVerifier { + client: client.clone(), + api, + inherent_data_providers, + config: babe_link.config, + epoch_changes: babe_link.epoch_changes, + time_source: babe_link.time_source, + }; + + Ok(BasicQueue::new( + verifier, + Box::new(block_import), + justification_import, + finality_proof_import, + )) +} + +/// BABE test helpers. Utility methods for manually authoring blocks. +#[cfg(feature = "test-helpers")] +pub mod test_helpers { + use super::*; + + /// Try to claim the given slot and return a `BabePreDigest` if + /// successful. + pub fn claim_slot( + slot_number: u64, + parent: &B::Header, + client: &C, + keystore: &KeyStorePtr, + link: &BabeLink, + ) -> Option where + B: BlockT, + C: ProvideRuntimeApi + + ProvideCache + + HeaderBackend + + HeaderMetadata, + C::Api: BabeApi, + { + let epoch = link.epoch_changes.lock().epoch_for_child_of( + descendent_query(client), + &parent.hash(), + parent.number().clone(), + slot_number, + |slot| link.config.genesis_epoch(slot), + ).unwrap().unwrap(); + + authorship::claim_slot( + slot_number, + epoch.as_ref(), + &link.config, + keystore, + ).map(|(digest, _)| digest) + } +} diff --git a/client/consensus/babe/src/tests.rs b/client/consensus/babe/src/tests.rs new file mode 100644 index 0000000000000..2ddb67fe4796e --- /dev/null +++ b/client/consensus/babe/src/tests.rs @@ -0,0 +1,796 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! BABE testsuite + +// FIXME #2532: need to allow deprecated until refactor is done +// https://github.com/paritytech/substrate/issues/2532 +#![allow(deprecated)] +use super::*; +use authorship::claim_slot; + +use sp_consensus_babe::{AuthorityPair, SlotNumber}; +use sc_block_builder::BlockBuilder; +use sp_consensus::{ + NoNetwork as DummyOracle, Proposal, RecordProof, + import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport}, +}; +use sc_network_test::*; +use sc_network_test::{Block as TestBlock, PeersClient}; +use sc_network::config::{BoxFinalityProofRequestBuilder, ProtocolConfig}; +use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}}; +use tokio::runtime::current_thread; +use sc_client_api::{BlockchainEvents, backend::TransactionFor}; +use log::debug; +use std::{time::Duration, cell::RefCell}; + +type Item = DigestItem; + +type Error = sp_blockchain::Error; + +type TestClient = sc_client::Client< + substrate_test_runtime_client::Backend, + substrate_test_runtime_client::Executor, + TestBlock, + substrate_test_runtime_client::runtime::RuntimeApi, +>; + +#[derive(Copy, Clone, PartialEq)] +enum Stage { + PreSeal, + PostSeal, +} + +type Mutator = Arc; + +#[derive(Clone)] +struct DummyFactory { + client: Arc, + epoch_changes: crate::SharedEpochChanges, + config: Config, + mutator: Mutator, +} + +struct DummyProposer { + factory: DummyFactory, + parent_hash: Hash, + parent_number: u64, + parent_slot: SlotNumber, +} + +impl Environment for DummyFactory { + type Proposer = DummyProposer; + type Error = Error; + + fn init(&mut self, parent_header: &::Header) + -> Result + { + + let parent_slot = crate::find_pre_digest::(parent_header) + .expect("parent header has a pre-digest") + .slot_number(); + + Ok(DummyProposer { + factory: self.clone(), + parent_hash: parent_header.hash(), + parent_number: *parent_header.number(), + parent_slot, + }) + } +} + +impl DummyProposer { + fn propose_with(&mut self, pre_digests: DigestFor) + -> future::Ready< + Result< + Proposal< + TestBlock, + sc_client_api::TransactionFor + >, + Error + > + > + { + use codec::Encode; + let block_builder = self.factory.client.new_block_at( + &BlockId::Hash(self.parent_hash), + pre_digests, + false, + ).unwrap(); + + let mut block = match block_builder.build().map_err(|e| e.into()) { + Ok(b) => b.block, + Err(e) => return future::ready(Err(e)), + }; + + let this_slot = crate::find_pre_digest::(block.header()) + .expect("baked block has valid pre-digest") + .slot_number(); + + // figure out if we should add a consensus digest, since the test runtime + // doesn't. + let epoch_changes = self.factory.epoch_changes.lock(); + let epoch = epoch_changes.epoch_for_child_of( + descendent_query(&*self.factory.client), + &self.parent_hash, + self.parent_number, + this_slot, + |slot| self.factory.config.genesis_epoch(slot), + ) + .expect("client has data to find epoch") + .expect("can compute epoch for baked block") + .into_inner(); + + let first_in_epoch = self.parent_slot < epoch.start_slot; + if first_in_epoch { + // push a `Consensus` digest signalling next change. + // we just reuse the same randomness and authorities as the prior + // epoch. this will break when we add light client support, since + // that will re-check the randomness logic off-chain. + let digest_data = ConsensusLog::NextEpochData(NextEpochDescriptor { + authorities: epoch.authorities.clone(), + randomness: epoch.randomness.clone(), + }).encode(); + let digest = DigestItem::Consensus(BABE_ENGINE_ID, digest_data); + block.header.digest_mut().push(digest) + } + + // mutate the block header according to the mutator. + (self.factory.mutator)(&mut block.header, Stage::PreSeal); + + future::ready(Ok(Proposal { block, proof: None, storage_changes: Default::default() })) + } +} + +impl Proposer for DummyProposer { + type Error = Error; + type Transaction = sc_client_api::TransactionFor; + type Proposal = future::Ready, Error>>; + + fn propose( + &mut self, + _: InherentData, + pre_digests: DigestFor, + _: Duration, + _: RecordProof, + ) -> Self::Proposal { + self.propose_with(pre_digests) + } +} + +thread_local! { + static MUTATOR: RefCell = RefCell::new(Arc::new(|_, _|())); +} + +#[derive(Clone)] +struct PanickingBlockImport(B); + +impl> BlockImport for PanickingBlockImport { + type Error = B::Error; + type Transaction = B::Transaction; + + fn import_block( + &mut self, + block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { + Ok(self.0.import_block(block, new_cache).expect("importing block failed")) + } + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + Ok(self.0.check_block(block).expect("checking block failed")) + } +} + +pub struct BabeTestNet { + peers: Vec, DummySpecialization>>, +} + +type TestHeader = ::Header; +type TestExtrinsic = ::Extrinsic; + +pub struct TestVerifier { + inner: BabeVerifier< + substrate_test_runtime_client::Backend, + substrate_test_runtime_client::Executor, + TestBlock, + substrate_test_runtime_client::runtime::RuntimeApi, + PeersFullClient, + >, + mutator: Mutator, +} + +impl Verifier for TestVerifier { + /// Verify the given data and return the BlockImportParams 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( + &mut self, + origin: BlockOrigin, + mut header: TestHeader, + justification: Option, + body: Option>, + ) -> Result<(BlockImportParams, Option)>>), String> { + // apply post-sealing mutations (i.e. stripping seal, if desired). + (self.mutator)(&mut header, Stage::PostSeal); + Ok(self.inner.verify(origin, header, justification, body).expect("verification failed!")) + } +} + +pub struct PeerData { + link: BabeLink, + inherent_data_providers: InherentDataProviders, + block_import: Mutex< + Option>> + >, +} + +impl TestNetFactory for BabeTestNet { + type Specialization = DummySpecialization; + type Verifier = TestVerifier; + type PeerData = Option; + + /// Create new test network with peers and given config. + fn from_config(_config: &ProtocolConfig) -> Self { + debug!(target: "babe", "Creating test network from config"); + BabeTestNet { + peers: Vec::new(), + } + } + + fn make_block_import(&self, client: PeersClient) + -> ( + BlockImportAdapter, + Option>, + Option>, + Option>, + Option, + ) + { + let client = client.as_full().expect("only full clients are tested"); + let inherent_data_providers = InherentDataProviders::new(); + + let config = Config::get_or_compute(&*client).expect("config available"); + let (block_import, link) = crate::block_import( + config, + client.clone(), + client.clone(), + client.clone(), + ).expect("can initialize block-import"); + + let block_import = PanickingBlockImport(block_import); + + let data_block_import = Mutex::new( + Some(Box::new(block_import.clone()) as BoxBlockImport<_, _>) + ); + ( + BlockImportAdapter::new_full(block_import), + None, + None, + None, + Some(PeerData { link, inherent_data_providers, block_import: data_block_import }), + ) + } + + fn make_verifier( + &self, + client: PeersClient, + _cfg: &ProtocolConfig, + maybe_link: &Option, + ) + -> Self::Verifier + { + let client = client.as_full().expect("only full clients are used in test"); + trace!(target: "babe", "Creating a verifier"); + + // ensure block import and verifier are linked correctly. + let data = maybe_link.as_ref().expect("babe link always provided to verifier instantiation"); + + TestVerifier { + inner: BabeVerifier { + client: client.clone(), + api: client, + inherent_data_providers: data.inherent_data_providers.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + time_source: data.link.time_source.clone(), + }, + mutator: MUTATOR.with(|m| m.borrow().clone()), + } + } + + fn peer(&mut self, i: usize) -> &mut Peer { + trace!(target: "babe", "Retreiving a peer"); + &mut self.peers[i] + } + + fn peers(&self) -> &Vec> { + trace!(target: "babe", "Retreiving peers"); + &self.peers + } + + fn mut_peers>)>( + &mut self, + closure: F, + ) { + closure(&mut self.peers); + } +} + +#[test] +#[should_panic] +fn rejects_empty_block() { + env_logger::try_init().unwrap(); + let mut net = BabeTestNet::new(3); + let block_builder = |builder: BlockBuilder<_, _, _>| { + builder.build().unwrap().block + }; + net.mut_peers(|peer| { + peer[0].generate_blocks(1, BlockOrigin::NetworkInitialSync, block_builder); + }) +} + +fn run_one_test( + mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static, +) { + let _ = env_logger::try_init(); + let mutator = Arc::new(mutator) as Mutator; + + MUTATOR.with(|m| *m.borrow_mut() = mutator.clone()); + let net = BabeTestNet::new(3); + + let peers = &[ + (0, "//Alice"), + (1, "//Bob"), + (2, "//Charlie"), + ]; + + let net = Arc::new(Mutex::new(net)); + let mut import_notifications = Vec::new(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut keystore_paths = Vec::new(); + + for (peer_id, seed) in peers { + let mut net = net.lock(); + let peer = net.peer(*peer_id); + let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let select_chain = peer.select_chain().expect("Full client has select_chain"); + + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); + let keystore = sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); + keystore.write().insert_ephemeral_from_seed::(seed).expect("Generates authority key"); + keystore_paths.push(keystore_path); + + let mut got_own = false; + let mut got_other = false; + + let data = peer.data.as_ref().expect("babe link set up during initialization"); + + let environ = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: mutator.clone(), + }; + + import_notifications.push( + // run each future until we get one of our own blocks with number higher than 5 + // that was produced locally. + client.import_notification_stream() + .take_while(move |n| future::ready(n.header.number() < &5 || { + if n.origin == BlockOrigin::Own { + got_own = true; + } else { + got_other = true; + } + + // continue until we have at least one block of our own + // and one of another peer. + !(got_own && got_other) + })) + .for_each(|_| future::ready(()) ) + ); + + + runtime.spawn(start_babe(BabeParams { + block_import: data.block_import.lock().take().expect("import set up during init"), + select_chain, + client, + env: environ, + sync_oracle: DummyOracle, + inherent_data_providers: data.inherent_data_providers.clone(), + force_authoring: false, + babe_link: data.link.clone(), + keystore, + can_author_with: sp_consensus::AlwaysCanAuthor, + }).expect("Starts babe")); + } + + runtime.spawn(futures01::future::poll_fn(move || { + net.lock().poll(); + Ok::<_, ()>(futures01::Async::NotReady::<()>) + })); + + runtime.block_on(future::join_all(import_notifications) + .map(|_| Ok::<(), ()>(())).compat()).unwrap(); +} + +#[test] +fn authoring_blocks() { + run_one_test(|_, _| ()) +} + +#[test] +#[should_panic] +fn rejects_missing_inherent_digest() { + run_one_test(|header: &mut TestHeader, stage| { + let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); + header.digest_mut().logs = v.into_iter() + .filter(|v| stage == Stage::PostSeal || v.as_babe_pre_digest().is_none()) + .collect() + }) +} + +#[test] +#[should_panic] +fn rejects_missing_seals() { + run_one_test(|header: &mut TestHeader, stage| { + let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); + header.digest_mut().logs = v.into_iter() + .filter(|v| stage == Stage::PreSeal || v.as_babe_seal().is_none()) + .collect() + }) +} + +#[test] +#[should_panic] +fn rejects_missing_consensus_digests() { + run_one_test(|header: &mut TestHeader, stage| { + let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); + header.digest_mut().logs = v.into_iter() + .filter(|v| stage == Stage::PostSeal || v.as_next_epoch_descriptor().is_none()) + .collect() + }); +} + +#[test] +fn wrong_consensus_engine_id_rejected() { + let _ = env_logger::try_init(); + let sig = AuthorityPair::generate().0.sign(b""); + let bad_seal: Item = DigestItem::Seal([0; 4], sig.to_vec()); + assert!(bad_seal.as_babe_pre_digest().is_none()); + assert!(bad_seal.as_babe_seal().is_none()) +} + +#[test] +fn malformed_pre_digest_rejected() { + let _ = env_logger::try_init(); + let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, [0; 64].to_vec()); + assert!(bad_seal.as_babe_pre_digest().is_none()); +} + +#[test] +fn sig_is_not_pre_digest() { + let _ = env_logger::try_init(); + let sig = AuthorityPair::generate().0.sign(b""); + let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig.to_vec()); + assert!(bad_seal.as_babe_pre_digest().is_none()); + assert!(bad_seal.as_babe_seal().is_some()) +} + +#[test] +fn can_author_block() { + let _ = env_logger::try_init(); + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); + let keystore = sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); + let pair = keystore.write().insert_ephemeral_from_seed::("//Alice") + .expect("Generates authority pair"); + + let mut i = 0; + let epoch = Epoch { + start_slot: 0, + authorities: vec![(pair.public(), 1)], + randomness: [0; 32], + epoch_index: 1, + duration: 100, + }; + + let mut config = crate::BabeConfiguration { + slot_duration: 1000, + epoch_length: 100, + c: (3, 10), + genesis_authorities: Vec::new(), + randomness: [0; 32], + secondary_slots: true, + }; + + // with secondary slots enabled it should never be empty + match claim_slot(i, &epoch, &config, &keystore) { + None => i += 1, + Some(s) => debug!(target: "babe", "Authored block {:?}", s.0), + } + + // otherwise with only vrf-based primary slots we might need to try a couple + // of times. + config.secondary_slots = false; + loop { + match claim_slot(i, &epoch, &config, &keystore) { + None => i += 1, + Some(s) => { + debug!(target: "babe", "Authored block {:?}", s.0); + break; + } + } + } +} + +// Propose and import a new BABE block on top of the given parent. +fn propose_and_import_block( + parent: &TestHeader, + slot_number: Option, + proposer_factory: &mut DummyFactory, + block_import: &mut BoxBlockImport, +) -> sp_core::H256 { + let mut proposer = proposer_factory.init(parent).unwrap(); + + let slot_number = slot_number.unwrap_or_else(|| { + let parent_pre_digest = find_pre_digest::(parent).unwrap(); + parent_pre_digest.slot_number() + 1 + }); + + let pre_digest = sp_runtime::generic::Digest { + logs: vec![ + Item::babe_pre_digest( + BabePreDigest::Secondary { + authority_index: 0, + slot_number, + }, + ), + ], + }; + + let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap().block; + + let seal = { + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let pair = AuthorityPair::from_seed(&[1; 32]); + let pre_hash = block.header.hash(); + let signature = pair.sign(pre_hash.as_ref()); + Item::babe_seal(signature) + }; + + let post_hash = { + block.header.digest_mut().push(seal.clone()); + let h = block.header.hash(); + block.header.digest_mut().pop(); + h + }; + + let import_result = block_import.import_block( + BlockImportParams { + origin: BlockOrigin::Own, + header: block.header, + justification: None, + post_digests: vec![seal], + body: Some(block.extrinsics), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }, + Default::default(), + ).unwrap(); + + match import_result { + ImportResult::Imported(_) => {}, + _ => panic!("expected block to be imported"), + } + + post_hash +} + +#[test] +fn importing_block_one_sets_genesis_epoch() { + let mut net = BabeTestNet::new(1); + + let peer = net.peer(0); + let data = peer.data.as_ref().expect("babe link set up during initialization"); + let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + + let mut proposer_factory = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: Arc::new(|_, _| ()), + }; + + let mut block_import = data.block_import.lock().take().expect("import set up during init"); + + let genesis_header = client.header(&BlockId::Number(0)).unwrap().unwrap(); + + let block_hash = propose_and_import_block( + &genesis_header, + Some(999), + &mut proposer_factory, + &mut block_import, + ); + + let genesis_epoch = data.link.config.genesis_epoch(999); + + let epoch_changes = data.link.epoch_changes.lock(); + let epoch_for_second_block = epoch_changes.epoch_for_child_of( + descendent_query(&*client), + &block_hash, + 1, + 1000, + |slot| data.link.config.genesis_epoch(slot), + ).unwrap().unwrap().into_inner(); + + assert_eq!(epoch_for_second_block, genesis_epoch); +} + +#[test] +fn importing_epoch_change_block_prunes_tree() { + use sc_client_api::Finalizer; + + let mut net = BabeTestNet::new(1); + + let peer = net.peer(0); + let data = peer.data.as_ref().expect("babe link set up during initialization"); + + let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let mut block_import = data.block_import.lock().take().expect("import set up during init"); + let epoch_changes = data.link.epoch_changes.clone(); + + let mut proposer_factory = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: Arc::new(|_, _| ()), + }; + + // This is just boilerplate code for proposing and importing n valid BABE + // blocks that are built on top of the given parent. The proposer takes care + // of producing epoch change digests according to the epoch duration (which + // is set to 6 slots in the test runtime). + let mut propose_and_import_blocks = |parent_id, n| { + let mut hashes = Vec::new(); + let mut parent_header = client.header(&parent_id).unwrap().unwrap(); + + for _ in 0..n { + let block_hash = propose_and_import_block( + &parent_header, + None, + &mut proposer_factory, + &mut block_import, + ); + hashes.push(block_hash); + parent_header = client.header(&BlockId::Hash(block_hash)).unwrap().unwrap(); + } + + hashes + }; + + // This is the block tree that we're going to use in this test. Each node + // represents an epoch change block, the epoch duration is 6 slots. + // + // *---- F (#7) + // / *------ G (#19) - H (#25) + // / / + // A (#1) - B (#7) - C (#13) - D (#19) - E (#25) + // \ + // *------ I (#25) + + // Create and import the canon chain and keep track of fork blocks (A, C, D) + // from the diagram above. + let canon_hashes = propose_and_import_blocks(BlockId::Number(0), 30); + + // Create the forks + let fork_1 = propose_and_import_blocks(BlockId::Hash(canon_hashes[0]), 10); + let fork_2 = propose_and_import_blocks(BlockId::Hash(canon_hashes[12]), 15); + let fork_3 = propose_and_import_blocks(BlockId::Hash(canon_hashes[18]), 10); + + // We should be tracking a total of 9 epochs in the fork tree + assert_eq!( + epoch_changes.lock().tree().iter().count(), + 9, + ); + + // And only one root + assert_eq!( + epoch_changes.lock().tree().roots().count(), + 1, + ); + + // We finalize block #13 from the canon chain, so on the next epoch + // change the tree should be pruned, to not contain F (#7). + client.finalize_block(BlockId::Hash(canon_hashes[12]), None, false).unwrap(); + propose_and_import_blocks(BlockId::Hash(client.chain_info().best_hash), 7); + + // at this point no hashes from the first fork must exist on the tree + assert!( + !epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_1.contains(h)), + ); + + // but the epoch changes from the other forks must still exist + assert!( + epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_2.contains(h)) + ); + + assert!( + epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_3.contains(h)), + ); + + // finalizing block #25 from the canon chain should prune out the second fork + client.finalize_block(BlockId::Hash(canon_hashes[24]), None, false).unwrap(); + propose_and_import_blocks(BlockId::Hash(client.chain_info().best_hash), 8); + + // at this point no hashes from the second fork must exist on the tree + assert!( + !epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_2.contains(h)), + ); + + // while epoch changes from the last fork should still exist + assert!( + epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_3.contains(h)), + ); +} + +#[test] +#[should_panic] +fn verify_slots_are_strictly_increasing() { + let mut net = BabeTestNet::new(1); + + let peer = net.peer(0); + let data = peer.data.as_ref().expect("babe link set up during initialization"); + + let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let mut block_import = data.block_import.lock().take().expect("import set up during init"); + + let mut proposer_factory = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: Arc::new(|_, _| ()), + }; + + let genesis_header = client.header(&BlockId::Number(0)).unwrap().unwrap(); + + // we should have no issue importing this block + let b1 = propose_and_import_block( + &genesis_header, + Some(999), + &mut proposer_factory, + &mut block_import, + ); + + let b1 = client.header(&BlockId::Hash(b1)).unwrap().unwrap(); + + // we should fail to import this block since the slot number didn't increase. + // we will panic due to the `PanickingBlockImport` defined above. + propose_and_import_block( + &b1, + Some(999), + &mut proposer_factory, + &mut block_import, + ); +} diff --git a/core/consensus/babe/src/verification.rs b/client/consensus/babe/src/verification.rs similarity index 95% rename from core/consensus/babe/src/verification.rs rename to client/consensus/babe/src/verification.rs index 36e34dfb9578b..ee5a99ec9d533 100644 --- a/core/consensus/babe/src/verification.rs +++ b/client/consensus/babe/src/verification.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,11 +16,11 @@ //! Verification for BABE headers. use schnorrkel::vrf::{VRFOutput, VRFProof}; -use sr_primitives::{traits::Header, traits::DigestItemFor}; -use primitives::{Pair, Public}; -use babe_primitives::{Epoch, BabePreDigest, CompatibleDigestItem, AuthorityId}; -use babe_primitives::{AuthoritySignature, SlotNumber, AuthorityIndex, AuthorityPair}; -use slots::CheckedHeader; +use sp_runtime::{traits::Header, traits::DigestItemFor}; +use sp_core::{Pair, Public}; +use sp_consensus_babe::{Epoch, BabePreDigest, CompatibleDigestItem, AuthorityId}; +use sp_consensus_babe::{AuthoritySignature, SlotNumber, AuthorityIndex, AuthorityPair}; +use sc_consensus_slots::CheckedHeader; use log::{debug, trace}; use super::{find_pre_digest, babe_err, BlockT, Error}; use super::authorship::{make_transcript, calculate_primary_threshold, check_primary_threshold, secondary_slot_author}; diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml new file mode 100644 index 0000000000000..bf0efa6c08cd8 --- /dev/null +++ b/client/consensus/pow/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sc-consensus-pow" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "PoW consensus algorithm for substrate" +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +sc-client-api = { version = "2.0.0", path = "../../api" } +sp-block-builder = { version = "2.0.0", path = "../../../primitives/block-builder" } +sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } +sp-consensus-pow = { version = "0.8", path = "../../../primitives/consensus/pow" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +log = "0.4.8" +futures = { version = "0.3.1", features = ["compat"] } +sp-timestamp = { version = "2.0.0", path = "../../../primitives/timestamp" } +derive_more = "0.99.2" diff --git a/client/consensus/pow/src/lib.rs b/client/consensus/pow/src/lib.rs new file mode 100644 index 0000000000000..5c491057e576c --- /dev/null +++ b/client/consensus/pow/src/lib.rs @@ -0,0 +1,568 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Proof of work consensus for Substrate. +//! +//! To use this engine, you can need to have a struct that implements +//! `PowAlgorithm`. After that, pass an instance of the struct, along +//! with other necessary client references to `import_queue` to setup +//! the queue. Use the `start_mine` function for basic CPU mining. +//! +//! The auxiliary storage for PoW engine only stores the total difficulty. +//! For other storage requirements for particular PoW algorithm (such as +//! the actual difficulty for each particular blocks), you can take a client +//! reference in your `PowAlgorithm` implementation, and use a separate prefix +//! for the auxiliary storage. It is also possible to just use the runtime +//! as the storage, but it is not recommended as it won't work well with light +//! clients. + +use std::sync::Arc; +use std::thread; +use std::collections::HashMap; +use sc_client_api::{BlockOf, backend::AuxStore}; +use sp_blockchain::{HeaderBackend, ProvideCache, well_known_cache_keys::Id as CacheKeyId}; +use sp_block_builder::BlockBuilder as BlockBuilderApi; +use sp_runtime::{Justification, RuntimeString}; +use sp_runtime::generic::{BlockId, Digest, DigestItem}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; +use sp_api::ProvideRuntimeApi; +use sp_consensus_pow::{Seal, TotalDifficulty, POW_ENGINE_ID}; +use sp_inherents::{InherentDataProviders, InherentData}; +use sp_consensus::{ + BlockImportParams, BlockOrigin, ForkChoiceStrategy, SyncOracle, Environment, Proposer, + SelectChain, Error as ConsensusError, CanAuthorWith, RecordProof, +}; +use sp_consensus::import_queue::{BoxBlockImport, BasicQueue, Verifier}; +use codec::{Encode, Decode}; +use sc_client_api; +use log::*; +use sp_timestamp::{InherentError as TIError, TimestampInherentData}; + +#[derive(derive_more::Display, Debug)] +pub enum Error { + #[display(fmt = "Header uses the wrong engine {:?}", _0)] + WrongEngine([u8; 4]), + #[display(fmt = "Header {:?} is unsealed", _0)] + HeaderUnsealed(B::Hash), + #[display(fmt = "PoW validation error: invalid seal")] + InvalidSeal, + #[display(fmt = "Rejecting block too far in future")] + TooFarInFuture, + #[display(fmt = "Fetching best header failed using select chain: {:?}", _0)] + BestHeaderSelectChain(ConsensusError), + #[display(fmt = "Fetching best header failed: {:?}", _0)] + BestHeader(sp_blockchain::Error), + #[display(fmt = "Best header does not exist")] + NoBestHeader, + #[display(fmt = "Block proposing error: {:?}", _0)] + BlockProposingError(String), + #[display(fmt = "Fetch best hash failed via select chain: {:?}", _0)] + BestHashSelectChain(ConsensusError), + #[display(fmt = "Error with block built on {:?}: {:?}", _0, _1)] + BlockBuiltError(B::Hash, ConsensusError), + #[display(fmt = "Creating inherents failed: {}", _0)] + CreateInherents(sp_inherents::Error), + #[display(fmt = "Checking inherents failed: {}", _0)] + CheckInherents(String), + Client(sp_blockchain::Error), + Codec(codec::Error), + Environment(String), + Runtime(RuntimeString) +} + +impl std::convert::From> for String { + fn from(error: Error) -> String { + error.to_string() + } +} + +/// Auxiliary storage prefix for PoW engine. +pub const POW_AUX_PREFIX: [u8; 4] = *b"PoW:"; + +/// Get the auxiliary storage key used by engine to store total difficulty. +fn aux_key>(hash: &T) -> Vec { + POW_AUX_PREFIX.iter().chain(hash.as_ref()).copied().collect() +} + +/// Auxiliary storage data for PoW. +#[derive(Encode, Decode, Clone, Debug, Default)] +pub struct PowAux { + /// Difficulty of the current block. + pub difficulty: Difficulty, + /// Total difficulty up to current block. + pub total_difficulty: Difficulty, +} + +impl PowAux where + Difficulty: Decode + Default, +{ + /// Read the auxiliary from client. + pub fn read(client: &C, hash: &B::Hash) -> Result> { + let key = aux_key(&hash); + + match client.get_aux(&key).map_err(Error::Client)? { + Some(bytes) => Self::decode(&mut &bytes[..]).map_err(Error::Codec), + None => Ok(Self::default()), + } + } +} + +/// Algorithm used for proof of work. +pub trait PowAlgorithm { + /// Difficulty for the algorithm. + type Difficulty: TotalDifficulty + Default + Encode + Decode + Ord + Clone + Copy; + + /// Get the next block's difficulty. + fn difficulty(&self, parent: &BlockId) -> Result>; + /// Verify proof of work against the given difficulty. + fn verify( + &self, + parent: &BlockId, + pre_hash: &B::Hash, + seal: &Seal, + difficulty: Self::Difficulty, + ) -> Result>; + /// Mine a seal that satisfies the given difficulty. + fn mine( + &self, + parent: &BlockId, + pre_hash: &B::Hash, + difficulty: Self::Difficulty, + round: u32, + ) -> Result, Error>; +} + +/// A verifier for PoW blocks. +pub struct PowVerifier { + client: Arc, + algorithm: Algorithm, + inherent_data_providers: sp_inherents::InherentDataProviders, + select_chain: Option, + check_inherents_after: <::Header as HeaderT>::Number, +} + +impl PowVerifier { + pub fn new( + client: Arc, + algorithm: Algorithm, + check_inherents_after: <::Header as HeaderT>::Number, + select_chain: Option, + inherent_data_providers: sp_inherents::InherentDataProviders, + ) -> Self { + Self { client, algorithm, inherent_data_providers, select_chain, check_inherents_after } + } + + fn check_header( + &self, + mut header: B::Header, + parent_block_id: BlockId, + ) -> Result<(B::Header, Algorithm::Difficulty, DigestItem), Error> where + Algorithm: PowAlgorithm, + { + let hash = header.hash(); + + let (seal, inner_seal) = match header.digest_mut().pop() { + Some(DigestItem::Seal(id, seal)) => { + if id == POW_ENGINE_ID { + (DigestItem::Seal(id, seal.clone()), seal) + } else { + return Err(Error::WrongEngine(id)) + } + }, + _ => return Err(Error::HeaderUnsealed(hash)), + }; + + let pre_hash = header.hash(); + let difficulty = self.algorithm.difficulty(&parent_block_id)?; + + if !self.algorithm.verify( + &parent_block_id, + &pre_hash, + &inner_seal, + difficulty, + )? { + return Err(Error::InvalidSeal); + } + + Ok((header, difficulty, seal)) + } + + fn check_inherents( + &self, + block: B, + block_id: BlockId, + inherent_data: InherentData, + timestamp_now: u64, + ) -> Result<(), Error> where + C: ProvideRuntimeApi, C::Api: BlockBuilderApi + { + const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; + + if *block.header().number() < self.check_inherents_after { + return Ok(()) + } + + let inherent_res = self.client.runtime_api().check_inherents( + &block_id, + block, + inherent_data, + ).map_err(Error::Client)?; + + if !inherent_res.ok() { + inherent_res + .into_errors() + .try_for_each(|(i, e)| match TIError::try_from(&i, &e) { + Some(TIError::ValidAtTimestamp(timestamp)) => { + if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { + return Err(Error::TooFarInFuture); + } + + Ok(()) + }, + Some(TIError::Other(e)) => Err(Error::Runtime(e)), + None => Err(Error::CheckInherents( + self.inherent_data_providers.error_to_string(&i, &e) + )), + }) + } else { + Ok(()) + } + } +} + +impl Verifier for PowVerifier where + C: ProvideRuntimeApi + Send + Sync + HeaderBackend + AuxStore + ProvideCache + BlockOf, + C::Api: BlockBuilderApi, + S: SelectChain, + Algorithm: PowAlgorithm + Send + Sync, +{ + fn verify( + &mut self, + origin: BlockOrigin, + header: B::Header, + justification: Option, + mut body: Option>, + ) -> Result<(BlockImportParams, Option)>>), String> { + let inherent_data = self.inherent_data_providers + .create_inherent_data().map_err(|e| e.into_string())?; + let timestamp_now = inherent_data.timestamp_inherent_data().map_err(|e| e.into_string())?; + + let best_hash = match self.select_chain.as_ref() { + Some(select_chain) => select_chain.best_chain() + .map_err(|e| format!("Fetch best chain failed via select chain: {:?}", e))? + .hash(), + None => self.client.info().best_hash, + }; + let hash = header.hash(); + let parent_hash = *header.parent_hash(); + let best_aux = PowAux::read::<_, B>(self.client.as_ref(), &best_hash)?; + let mut aux = PowAux::read::<_, B>(self.client.as_ref(), &parent_hash)?; + + let (checked_header, difficulty, seal) = self.check_header( + header, + BlockId::Hash(parent_hash), + )?; + aux.difficulty = difficulty; + aux.total_difficulty.increment(difficulty); + + if let Some(inner_body) = body.take() { + let block = B::new(checked_header.clone(), inner_body); + + self.check_inherents( + block.clone(), + BlockId::Hash(parent_hash), + inherent_data, + timestamp_now + )?; + + body = Some(block.deconstruct().1); + } + + let key = aux_key(&hash); + let import_block = BlockImportParams { + origin, + header: checked_header, + post_digests: vec![seal], + body, + storage_changes: None, + finalized: false, + justification, + auxiliary: vec![(key, Some(aux.encode()))], + fork_choice: ForkChoiceStrategy::Custom( + aux.total_difficulty > best_aux.total_difficulty + ), + allow_missing_state: false, + import_existing: false, + }; + + Ok((import_block, None)) + } +} + +/// Register the PoW inherent data provider, if not registered already. +pub fn register_pow_inherent_data_provider( + inherent_data_providers: &InherentDataProviders, +) -> Result<(), sp_consensus::Error> { + if !inherent_data_providers.has_provider(&sp_timestamp::INHERENT_IDENTIFIER) { + inherent_data_providers + .register_provider(sp_timestamp::InherentDataProvider) + .map_err(Into::into) + .map_err(sp_consensus::Error::InherentData) + } else { + Ok(()) + } +} + +/// The PoW import queue type. +pub type PowImportQueue = BasicQueue; + +/// Import queue for PoW engine. +pub fn import_queue( + block_import: BoxBlockImport>, + client: Arc, + algorithm: Algorithm, + check_inherents_after: <::Header as HeaderT>::Number, + select_chain: Option, + inherent_data_providers: InherentDataProviders, +) -> Result< + PowImportQueue>, + sp_consensus::Error +> where + B: BlockT, + C: ProvideRuntimeApi + HeaderBackend + BlockOf + ProvideCache + AuxStore, + C: Send + Sync + AuxStore + 'static, + C::Api: BlockBuilderApi, + Algorithm: PowAlgorithm + Send + Sync + 'static, + S: SelectChain + 'static, +{ + register_pow_inherent_data_provider(&inherent_data_providers)?; + + let verifier = PowVerifier::new( + client.clone(), + algorithm, + check_inherents_after, + select_chain, + inherent_data_providers, + ); + + Ok(BasicQueue::new( + verifier, + block_import, + None, + None + )) +} + +/// Start the background mining thread for PoW. Note that because PoW mining +/// is CPU-intensive, it is not possible to use an async future to define this. +/// However, it's not recommended to use background threads in the rest of the +/// codebase. +/// +/// `preruntime` is a parameter that allows a custom additional pre-runtime +/// digest to be inserted for blocks being built. This can encode authorship +/// information, or just be a graffiti. `round` is for number of rounds the +/// CPU miner runs each time. This parameter should be tweaked so that each +/// mining round is within sub-second time. +pub fn start_mine( + mut block_import: BoxBlockImport>, + client: Arc, + algorithm: Algorithm, + mut env: E, + preruntime: Option>, + round: u32, + mut sync_oracle: SO, + build_time: std::time::Duration, + select_chain: Option, + inherent_data_providers: sp_inherents::InherentDataProviders, + can_author_with: CAW, +) where + C: HeaderBackend + AuxStore + ProvideRuntimeApi + 'static, + Algorithm: PowAlgorithm + Send + Sync + 'static, + E: Environment + Send + Sync + 'static, + E::Error: std::fmt::Debug, + E::Proposer: Proposer>, + SO: SyncOracle + Send + Sync + 'static, + S: SelectChain + 'static, + CAW: CanAuthorWith + Send + 'static, +{ + if let Err(_) = register_pow_inherent_data_provider(&inherent_data_providers) { + warn!("Registering inherent data provider for timestamp failed"); + } + + thread::spawn(move || { + loop { + match mine_loop( + &mut block_import, + client.as_ref(), + &algorithm, + &mut env, + preruntime.as_ref(), + round, + &mut sync_oracle, + build_time.clone(), + select_chain.as_ref(), + &inherent_data_providers, + &can_author_with, + ) { + Ok(()) => (), + Err(e) => error!( + "Mining block failed with {:?}. Sleep for 1 second before restarting...", + e + ), + } + std::thread::sleep(std::time::Duration::new(1, 0)); + } + }); +} + +fn mine_loop( + block_import: &mut BoxBlockImport>, + client: &C, + algorithm: &Algorithm, + env: &mut E, + preruntime: Option<&Vec>, + round: u32, + sync_oracle: &mut SO, + build_time: std::time::Duration, + select_chain: Option<&S>, + inherent_data_providers: &sp_inherents::InherentDataProviders, + can_author_with: &CAW, +) -> Result<(), Error> where + C: HeaderBackend + AuxStore + ProvideRuntimeApi, + Algorithm: PowAlgorithm, + E: Environment, + E::Proposer: Proposer>, + E::Error: std::fmt::Debug, + SO: SyncOracle, + S: SelectChain, + sp_api::TransactionFor: 'static, + CAW: CanAuthorWith, +{ + 'outer: loop { + if sync_oracle.is_major_syncing() { + debug!(target: "pow", "Skipping proposal due to sync."); + std::thread::sleep(std::time::Duration::new(1, 0)); + continue 'outer + } + + let (best_hash, best_header) = match select_chain { + Some(select_chain) => { + let header = select_chain.best_chain() + .map_err(Error::BestHeaderSelectChain)?; + let hash = header.hash(); + (hash, header) + }, + None => { + let hash = client.info().best_hash; + let header = client.header(BlockId::Hash(hash)) + .map_err(Error::BestHeader)? + .ok_or(Error::NoBestHeader)?; + (hash, header) + }, + }; + + if let Err(err) = can_author_with.can_author_with(&BlockId::Hash(best_hash)) { + warn!( + target: "pow", + "Skipping proposal `can_author_with` returned: {} \ + Probably a node update is required!", + err, + ); + std::thread::sleep(std::time::Duration::from_secs(1)); + continue 'outer + } + + let mut aux = PowAux::read(client, &best_hash)?; + let mut proposer = env.init(&best_header) + .map_err(|e| Error::Environment(format!("{:?}", e)))?; + + let inherent_data = inherent_data_providers + .create_inherent_data().map_err(Error::CreateInherents)?; + let mut inherent_digest = Digest::default(); + if let Some(preruntime) = &preruntime { + inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, preruntime.to_vec())); + } + let proposal = futures::executor::block_on(proposer.propose( + inherent_data, + inherent_digest, + build_time.clone(), + RecordProof::No, + )).map_err(|e| Error::BlockProposingError(format!("{:?}", e)))?; + + let (header, body) = proposal.block.deconstruct(); + let (difficulty, seal) = { + let difficulty = algorithm.difficulty( + &BlockId::Hash(best_hash), + )?; + + loop { + let seal = algorithm.mine( + &BlockId::Hash(best_hash), + &header.hash(), + difficulty, + round, + )?; + + if let Some(seal) = seal { + break (difficulty, seal) + } + + if best_hash != client.info().best_hash { + continue 'outer + } + } + }; + + aux.difficulty = difficulty; + aux.total_difficulty.increment(difficulty); + let hash = { + let mut header = header.clone(); + header.digest_mut().push(DigestItem::Seal(POW_ENGINE_ID, seal.clone())); + header.hash() + }; + + let key = aux_key(&hash); + let best_hash = match select_chain { + Some(select_chain) => select_chain.best_chain() + .map_err(Error::BestHashSelectChain)? + .hash(), + None => client.info().best_hash, + }; + let best_aux = PowAux::::read(client, &best_hash)?; + + // if the best block has changed in the meantime drop our proposal + if best_aux.total_difficulty > aux.total_difficulty { + continue 'outer + } + + let import_block = BlockImportParams { + origin: BlockOrigin::Own, + header, + justification: None, + post_digests: vec![DigestItem::Seal(POW_ENGINE_ID, seal)], + body: Some(body), + storage_changes: Some(proposal.storage_changes), + finalized: false, + auxiliary: vec![(key, Some(aux.encode()))], + fork_choice: ForkChoiceStrategy::Custom(true), + allow_missing_state: false, + import_existing: false, + }; + + block_import.import_block(import_block, HashMap::default()) + .map_err(|e| Error::BlockBuiltError(best_hash, e))?; + } +} diff --git a/client/consensus/slots/Cargo.toml b/client/consensus/slots/Cargo.toml new file mode 100644 index 0000000000000..3f1a572249899 --- /dev/null +++ b/client/consensus/slots/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "sc-consensus-slots" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "Generic slots-based utilities for consensus" +edition = "2018" +build = "build.rs" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0" } +sc-client-api = { version = "2.0.0", path = "../../api" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-state-machine = { version = "2.0.0", path = "../../../primitives/state-machine" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +sc-telemetry = { version = "2.0.0", path = "../../telemetry" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } +futures = "0.3.1" +futures-timer = "2.0" +parking_lot = "0.9.0" +log = "0.4.8" + +[dev-dependencies] +substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } diff --git a/client/consensus/slots/build.rs b/client/consensus/slots/build.rs new file mode 100644 index 0000000000000..513cc234d4363 --- /dev/null +++ b/client/consensus/slots/build.rs @@ -0,0 +1,23 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::env; + +fn main() { + if let Ok(profile) = env::var("PROFILE") { + println!("cargo:rustc-cfg=build_type=\"{}\"", profile); + } +} diff --git a/client/consensus/slots/src/aux_schema.rs b/client/consensus/slots/src/aux_schema.rs new file mode 100644 index 0000000000000..df4772a8e92a1 --- /dev/null +++ b/client/consensus/slots/src/aux_schema.rs @@ -0,0 +1,265 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Schema for slots in the aux-db. + +use codec::{Encode, Decode}; +use sc_client_api::backend::AuxStore; +use sp_blockchain::{Result as ClientResult, Error as ClientError}; +use sp_runtime::traits::Header; + +const SLOT_HEADER_MAP_KEY: &[u8] = b"slot_header_map"; +const SLOT_HEADER_START: &[u8] = b"slot_header_start"; + +/// We keep at least this number of slots in database. +pub const MAX_SLOT_CAPACITY: u64 = 1000; +/// We prune slots when they reach this number. +pub const PRUNING_BOUND: u64 = 2 * MAX_SLOT_CAPACITY; + +fn load_decode(backend: &C, key: &[u8]) -> ClientResult> + where + C: AuxStore, + T: Decode, +{ + match backend.get_aux(key)? { + None => Ok(None), + Some(t) => T::decode(&mut &t[..]) + .map_err( + |e| ClientError::Backend(format!("Slots DB is corrupted. Decode error: {}", e.what())), + ) + .map(Some) + } +} + +/// Represents an equivocation proof. +#[derive(Debug, Clone)] +pub struct EquivocationProof { + slot: u64, + fst_header: H, + snd_header: H, +} + +impl EquivocationProof { + /// Get the slot number where the equivocation happened. + pub fn slot(&self) -> u64 { + self.slot + } + + /// Get the first header involved in the equivocation. + pub fn fst_header(&self) -> &H { + &self.fst_header + } + + /// Get the second header involved in the equivocation. + pub fn snd_header(&self) -> &H { + &self.snd_header + } +} + +/// Checks if the header is an equivocation and returns the proof in that case. +/// +/// Note: it detects equivocations only when slot_now - slot <= MAX_SLOT_CAPACITY. +pub fn check_equivocation( + backend: &C, + slot_now: u64, + slot: u64, + header: &H, + signer: &P, +) -> ClientResult>> + where + H: Header, + C: AuxStore, + P: Clone + Encode + Decode + PartialEq, +{ + // We don't check equivocations for old headers out of our capacity. + if slot_now - slot > MAX_SLOT_CAPACITY { + return Ok(None) + } + + // Key for this slot. + let mut curr_slot_key = SLOT_HEADER_MAP_KEY.to_vec(); + slot.using_encoded(|s| curr_slot_key.extend(s)); + + // Get headers of this slot. + let mut headers_with_sig = load_decode::<_, Vec<(H, P)>>(backend, &curr_slot_key[..])? + .unwrap_or_else(Vec::new); + + // Get first slot saved. + let slot_header_start = SLOT_HEADER_START.to_vec(); + let first_saved_slot = load_decode::<_, u64>(backend, &slot_header_start[..])? + .unwrap_or(slot); + + for (prev_header, prev_signer) in headers_with_sig.iter() { + // A proof of equivocation consists of two headers: + // 1) signed by the same voter, + if prev_signer == signer { + // 2) with different hash + if header.hash() != prev_header.hash() { + return Ok(Some(EquivocationProof { + slot, // 3) and mentioning the same slot. + fst_header: prev_header.clone(), + snd_header: header.clone(), + })); + } else { + // We don't need to continue in case of duplicated header, + // since it's already saved and a possible equivocation + // would have been detected before. + return Ok(None) + } + } + } + + let mut keys_to_delete = vec![]; + let mut new_first_saved_slot = first_saved_slot; + + if slot_now - first_saved_slot >= PRUNING_BOUND { + let prefix = SLOT_HEADER_MAP_KEY.to_vec(); + new_first_saved_slot = slot_now.saturating_sub(MAX_SLOT_CAPACITY); + + for s in first_saved_slot..new_first_saved_slot { + let mut p = prefix.clone(); + s.using_encoded(|s| p.extend(s)); + keys_to_delete.push(p); + } + } + + headers_with_sig.push((header.clone(), signer.clone())); + + backend.insert_aux( + &[ + (&curr_slot_key[..], headers_with_sig.encode().as_slice()), + (&slot_header_start[..], new_first_saved_slot.encode().as_slice()), + ], + &keys_to_delete.iter().map(|k| &k[..]).collect::>()[..], + )?; + + Ok(None) +} + +#[cfg(test)] +mod test { + use sp_core::{sr25519, Pair}; + use sp_core::hash::H256; + use sp_runtime::testing::{Header as HeaderTest, Digest as DigestTest}; + use substrate_test_runtime_client; + + use super::{MAX_SLOT_CAPACITY, PRUNING_BOUND, check_equivocation}; + + fn create_header(number: u64) -> HeaderTest { + // so that different headers for the same number get different hashes + let parent_hash = H256::random(); + + let header = HeaderTest { + parent_hash, + number, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: DigestTest { logs: vec![], }, + }; + + header + } + + #[test] + fn check_equivocation_works() { + let client = substrate_test_runtime_client::new(); + let (pair, _seed) = sr25519::Pair::generate(); + let public = pair.public(); + + let header1 = create_header(1); // @ slot 2 + let header2 = create_header(2); // @ slot 2 + let header3 = create_header(2); // @ slot 4 + let header4 = create_header(3); // @ slot MAX_SLOT_CAPACITY + 4 + let header5 = create_header(4); // @ slot MAX_SLOT_CAPACITY + 4 + let header6 = create_header(3); // @ slot 4 + + // It's ok to sign same headers. + assert!( + check_equivocation( + &client, + 2, + 2, + &header1, + &public, + ).unwrap().is_none(), + ); + + assert!( + check_equivocation( + &client, + 3, + 2, + &header1, + &public, + ).unwrap().is_none(), + ); + + // But not two different headers at the same slot. + assert!( + check_equivocation( + &client, + 4, + 2, + &header2, + &public, + ).unwrap().is_some(), + ); + + // Different slot is ok. + assert!( + check_equivocation( + &client, + 5, + 4, + &header3, + &public, + ).unwrap().is_none(), + ); + + // Here we trigger pruning and save header 4. + assert!( + check_equivocation( + &client, + PRUNING_BOUND + 2, + MAX_SLOT_CAPACITY + 4, + &header4, + &public, + ).unwrap().is_none(), + ); + + // This fails because header 5 is an equivocation of header 4. + assert!( + check_equivocation( + &client, + PRUNING_BOUND + 3, + MAX_SLOT_CAPACITY + 4, + &header5, + &public, + ).unwrap().is_some(), + ); + + // This is ok because we pruned the corresponding header. Shows that we are pruning. + assert!( + check_equivocation( + &client, + PRUNING_BOUND + 4, + 4, + &header6, + &public, + ).unwrap().is_none(), + ); + } +} diff --git a/client/consensus/slots/src/lib.rs b/client/consensus/slots/src/lib.rs new file mode 100644 index 0000000000000..a69c710a7e944 --- /dev/null +++ b/client/consensus/slots/src/lib.rs @@ -0,0 +1,477 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Slots functionality for Substrate. +//! +//! Some consensus algorithms have a concept of *slots*, which are intervals in +//! time during which certain events can and/or must occur. This crate +//! provides generic functionality for slots. + +#![deny(warnings)] +#![forbid(unsafe_code, missing_docs)] + +mod slots; +mod aux_schema; + +pub use slots::{SignedDuration, SlotInfo}; +use slots::Slots; +pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND}; + +use codec::{Decode, Encode}; +use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData, RecordProof}; +use futures::{prelude::*, future::{self, Either}}; +use futures_timer::Delay; +use sp_inherents::{InherentData, InherentDataProviders}; +use log::{debug, error, info, warn}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{Block as BlockT, Header, HasherFor, NumberFor}; +use sp_api::{ProvideRuntimeApi, ApiRef}; +use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc, time::{Instant, Duration}}; +use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; +use parking_lot::Mutex; + +/// The changes that need to applied to the storage to create the state for a block. +/// +/// See [`state_machine::StorageChanges`] for more information. +pub type StorageChanges = + sp_state_machine::StorageChanges, NumberFor>; + +/// A worker that should be invoked at every new slot. +pub trait SlotWorker { + /// The type of the future that will be returned when a new slot is + /// triggered. + type OnSlot: Future>; + + /// Called when a new slot is triggered. + fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot; +} + +/// A skeleton implementation for `SlotWorker` which tries to claim a slot at +/// its beginning and tries to produce a block if successfully claimed, timing +/// out if block production takes too long. +pub trait SimpleSlotWorker { + /// A handle to a `BlockImport`. + type BlockImport: BlockImport>::Transaction> + + Send + 'static; + + /// A handle to a `SyncOracle`. + type SyncOracle: SyncOracle; + + /// The type of proposer to use to build blocks. + type Proposer: Proposer; + + /// Data associated with a slot claim. + type Claim: Send + 'static; + + /// Epoch data necessary for authoring. + type EpochData; + + /// The logging target to use when logging messages. + fn logging_target(&self) -> &'static str; + + /// A handle to a `BlockImport`. + fn block_import(&self) -> Arc>; + + /// Returns the epoch data necessary for authoring. For time-dependent epochs, + /// use the provided slot number as a canonical source of time. + fn epoch_data(&self, header: &B::Header, slot_number: u64) -> Result; + + /// Returns the number of authorities given the epoch data. + fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize; + + /// Tries to claim the given slot, returning an object with claim data if successful. + fn claim_slot( + &self, + header: &B::Header, + slot_number: u64, + epoch_data: &Self::EpochData, + ) -> Option; + + /// Return the pre digest data to include in a block authored with the given claim. + fn pre_digest_data( + &self, + slot_number: u64, + claim: &Self::Claim, + ) -> Vec>; + + /// Returns a function which produces a `BlockImportParams`. + fn block_import_params(&self) -> Box< + dyn Fn( + B::Header, + &B::Hash, + Vec, + StorageChanges<>::Transaction, B>, + Self::Claim, + ) -> sp_consensus::BlockImportParams< + B, + >::Transaction + > + + Send + >; + + /// Whether to force authoring if offline. + fn force_authoring(&self) -> bool; + + /// Returns a handle to a `SyncOracle`. + fn sync_oracle(&mut self) -> &mut Self::SyncOracle; + + /// Returns a `Proposer` to author on top of the given block. + fn proposer(&mut self, block: &B::Header) -> Result; + + /// Remaining duration of the slot. + fn slot_remaining_duration(&self, slot_info: &SlotInfo) -> Duration { + let now = Instant::now(); + if now < slot_info.ends_at { + slot_info.ends_at.duration_since(now) + } else { + Duration::from_millis(0) + } + } + + /// Remaining duration for proposing. None means unlimited. + fn proposing_remaining_duration( + &self, + _head: &B::Header, + slot_info: &SlotInfo + ) -> Option { + Some(self.slot_remaining_duration(slot_info)) + } + + /// Implements the `on_slot` functionality from `SlotWorker`. + fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) + -> Pin> + Send>> where + Self: Send + Sync, + >::Proposal: Unpin + Send + 'static, + { + let (timestamp, slot_number, slot_duration) = + (slot_info.timestamp, slot_info.number, slot_info.duration); + + { + let slot_now = SignedDuration::default().slot_now(slot_duration); + if slot_now > slot_number { + // if this is behind, return. + debug!(target: self.logging_target(), + "Skipping proposal slot {} since our current view is {}", + slot_number, slot_now, + ); + + return Box::pin(future::ready(Ok(()))); + } + } + + let epoch_data = match self.epoch_data(&chain_head, slot_number) { + Ok(epoch_data) => epoch_data, + Err(err) => { + warn!("Unable to fetch epoch data at block {:?}: {:?}", chain_head.hash(), err); + + telemetry!( + CONSENSUS_WARN; "slots.unable_fetching_authorities"; + "slot" => ?chain_head.hash(), + "err" => ?err, + ); + + return Box::pin(future::ready(Ok(()))); + } + }; + + let authorities_len = self.authorities_len(&epoch_data); + + if !self.force_authoring() && self.sync_oracle().is_offline() && authorities_len > 1 { + debug!(target: self.logging_target(), "Skipping proposal slot. Waiting for the network."); + telemetry!( + CONSENSUS_DEBUG; + "slots.skipping_proposal_slot"; + "authorities_len" => authorities_len, + ); + + return Box::pin(future::ready(Ok(()))); + } + + let claim = match self.claim_slot(&chain_head, slot_number, &epoch_data) { + None => return Box::pin(future::ready(Ok(()))), + Some(claim) => claim, + }; + + debug!( + target: self.logging_target(), "Starting authorship at slot {}; timestamp = {}", + slot_number, + timestamp, + ); + + telemetry!(CONSENSUS_DEBUG; "slots.starting_authorship"; + "slot_num" => slot_number, + "timestamp" => timestamp, + ); + + let mut proposer = match self.proposer(&chain_head) { + Ok(proposer) => proposer, + Err(err) => { + warn!("Unable to author block in slot {:?}: {:?}", slot_number, err); + + telemetry!(CONSENSUS_WARN; "slots.unable_authoring_block"; + "slot" => slot_number, "err" => ?err + ); + + return Box::pin(future::ready(Ok(()))); + }, + }; + + let slot_remaining_duration = self.slot_remaining_duration(&slot_info); + let proposing_remaining_duration = self.proposing_remaining_duration(&chain_head, &slot_info); + let logs = self.pre_digest_data(slot_number, &claim); + + // deadline our production to approx. the end of the slot + let proposing = proposer.propose( + slot_info.inherent_data, + sp_runtime::generic::Digest { + logs, + }, + slot_remaining_duration, + RecordProof::No, + ).map_err(|e| sp_consensus::Error::ClientImport(format!("{:?}", e))); + let delay: Box + Unpin + Send> = match proposing_remaining_duration { + Some(r) => Box::new(Delay::new(r)), + None => Box::new(future::pending()), + }; + + let proposal_work = + Box::new(futures::future::select(proposing, delay).map(move |v| match v { + futures::future::Either::Left((b, _)) => b.map(|b| (b, claim)), + futures::future::Either::Right(_) => { + info!("Discarding proposal for slot {}; block production took too long", slot_number); + // If the node was compiled with debug, tell the user to use release optimizations. + #[cfg(build_type="debug")] + info!("Recompile your node in `--release` mode to mitigate this problem."); + telemetry!(CONSENSUS_INFO; "slots.discarding_proposal_took_too_long"; + "slot" => slot_number, + ); + Err(sp_consensus::Error::ClientImport("Timeout in the Slots proposer".into())) + }, + })); + + let block_import_params_maker = self.block_import_params(); + let block_import = self.block_import(); + let logging_target = self.logging_target(); + + Box::pin(proposal_work.map_ok(move |(proposal, claim)| { + let (header, body) = proposal.block.deconstruct(); + let header_num = *header.number(); + let header_hash = header.hash(); + let parent_hash = *header.parent_hash(); + + let block_import_params = block_import_params_maker( + header, + &header_hash, + body, + proposal.storage_changes, + claim, + ); + + info!( + "Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", + header_num, + block_import_params.post_header().hash(), + header_hash, + ); + + telemetry!(CONSENSUS_INFO; "slots.pre_sealed_block"; + "header_num" => ?header_num, + "hash_now" => ?block_import_params.post_header().hash(), + "hash_previously" => ?header_hash, + ); + + if let Err(err) = block_import.lock().import_block(block_import_params, Default::default()) { + warn!(target: logging_target, + "Error with block built on {:?}: {:?}", + parent_hash, + err, + ); + + telemetry!(CONSENSUS_WARN; "slots.err_with_block_built_on"; + "hash" => ?parent_hash, "err" => ?err, + ); + } + })) + } +} + +/// Slot compatible inherent data. +pub trait SlotCompatible { + /// Extract timestamp and slot from inherent data. + fn extract_timestamp_and_slot( + &self, + inherent: &InherentData, + ) -> Result<(u64, u64, std::time::Duration), sp_consensus::Error>; + + /// Get the difference between chain time and local time. Defaults to + /// always returning zero. + fn time_offset() -> SignedDuration { Default::default() } +} + +/// Start a new slot worker. +/// +/// Every time a new slot is triggered, `worker.on_slot` is called and the future it returns is +/// polled until completion, unless we are major syncing. +pub fn start_slot_worker( + slot_duration: SlotDuration, + client: C, + mut worker: W, + mut sync_oracle: SO, + inherent_data_providers: InherentDataProviders, + timestamp_extractor: SC, + can_author_with: CAW, +) -> impl Future +where + B: BlockT, + C: SelectChain, + W: SlotWorker, + W::OnSlot: Unpin, + SO: SyncOracle + Send, + SC: SlotCompatible + Unpin, + T: SlotData + Clone, + CAW: CanAuthorWith + Send, +{ + let SlotDuration(slot_duration) = slot_duration; + + // rather than use a timer interval, we schedule our waits ourselves + Slots::::new( + slot_duration.slot_duration(), + inherent_data_providers, + timestamp_extractor, + ).inspect_err(|e| debug!(target: "slots", "Faulty timer: {:?}", e)) + .try_for_each(move |slot_info| { + // only propose when we are not syncing. + if sync_oracle.is_major_syncing() { + debug!(target: "slots", "Skipping proposal slot due to sync."); + return Either::Right(future::ready(Ok(()))); + } + + let slot_num = slot_info.number; + let chain_head = match client.best_chain() { + Ok(x) => x, + Err(e) => { + warn!(target: "slots", "Unable to author block in slot {}. \ + no best block header: {:?}", slot_num, e); + return Either::Right(future::ready(Ok(()))); + } + }; + + if let Err(err) = can_author_with.can_author_with(&BlockId::Hash(chain_head.hash())) { + warn!( + target: "slots", + "Unable to author block in slot {},. `can_author_with` returned: {} \ + Probably a node update is required!", + slot_num, + err, + ); + Either::Right(future::ready(Ok(()))) + } else { + Either::Left( + worker.on_slot(chain_head, slot_info) + .map_err(|e| { + warn!(target: "slots", "Encountered consensus error: {:?}", e); + }) + .or_else(|_| future::ready(Ok(()))) + ) + } + }).then(|res| { + if let Err(err) = res { + warn!(target: "slots", "Slots stream terminated with an error: {:?}", err); + } + future::ready(()) + }) +} + +/// 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. + /// + /// Includes the digest item that encoded the seal. + Checked(H, S), +} + +/// A slot duration. Create with `get_or_compute`. +// The internal member should stay private here to maintain invariants of +// `get_or_compute`. +#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct SlotDuration(T); + +impl Deref for SlotDuration { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} + +impl SlotData for SlotDuration { + /// Get the slot duration in milliseconds. + fn slot_duration(&self) -> u64 + where T: SlotData, + { + self.0.slot_duration() + } + + const SLOT_KEY: &'static [u8] = T::SLOT_KEY; +} + +impl SlotDuration { + /// Either fetch the slot duration from disk or compute it from the + /// genesis state. + /// + /// `slot_key` is marked as `'static`, as it should really be a + /// compile-time constant. + pub fn get_or_compute(client: &C, cb: CB) -> sp_blockchain::Result where + C: sc_client_api::backend::AuxStore, + C: ProvideRuntimeApi, + CB: FnOnce(ApiRef, &BlockId) -> sp_blockchain::Result, + T: SlotData + Encode + Decode + Debug, + { + match client.get_aux(T::SLOT_KEY)? { + Some(v) => ::decode(&mut &v[..]) + .map(SlotDuration) + .map_err(|_| { + sp_blockchain::Error::Backend({ + error!(target: "slots", "slot duration kept in invalid format"); + "slot duration kept in invalid format".to_string() + }) + }), + None => { + use sp_runtime::traits::Zero; + let genesis_slot_duration = + cb(client.runtime_api(), &BlockId::number(Zero::zero()))?; + + info!( + "Loaded block-time = {:?} milliseconds from genesis on first-launch", + genesis_slot_duration + ); + + genesis_slot_duration + .using_encoded(|s| client.insert_aux(&[(T::SLOT_KEY, &s[..])], &[]))?; + + Ok(SlotDuration(genesis_slot_duration)) + } + } + } + + /// Returns slot data value. + pub fn get(&self) -> T { + self.0.clone() + } +} diff --git a/core/consensus/slots/src/slots.rs b/client/consensus/slots/src/slots.rs similarity index 88% rename from core/consensus/slots/src/slots.rs rename to client/consensus/slots/src/slots.rs index 98310bbf2e27c..17a931b7c4154 100644 --- a/core/consensus/slots/src/slots.rs +++ b/client/consensus/slots/src/slots.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,9 +19,9 @@ //! This is used instead of `futures_timer::Interval` because it was unreliable. use super::SlotCompatible; -use consensus_common::Error; +use sp_consensus::Error; use futures::{prelude::*, task::Context, task::Poll}; -use inherents::{InherentData, InherentDataProviders}; +use sp_inherents::{InherentData, InherentDataProviders}; use std::{pin::Pin, time::{Duration, Instant}}; use futures_timer::Delay; @@ -71,6 +71,8 @@ pub fn time_until_next(now: Duration, slot_duration: u64) -> Duration { pub struct SlotInfo { /// The slot number. pub number: u64, + /// The last slot number produced. + pub last_number: u64, /// Current timestamp. pub timestamp: u64, /// The instant at which the slot ends. @@ -81,18 +83,6 @@ pub struct SlotInfo { 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_millis(0) - } - } -} - /// A stream that returns every time there is a new slot. pub(crate) struct Slots { last_slot: u64, @@ -137,8 +127,7 @@ impl Stream for Slots { if let Some(ref mut inner_delay) = self.inner_delay { match Future::poll(Pin::new(inner_delay), cx) { Poll::Pending => return Poll::Pending, - Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(Error::FaultyTimer(err)))), - Poll::Ready(Ok(())) => {} + Poll::Ready(()) => {} } } @@ -146,7 +135,7 @@ impl Stream for Slots { let inherent_data = match self.inherent_data_providers.create_inherent_data() { Ok(id) => id, - Err(err) => return Poll::Ready(Some(Err(consensus_common::Error::InherentData(err.into_owned())))), + Err(err) => return Poll::Ready(Some(Err(sp_consensus::Error::InherentData(err)))), }; let result = self.timestamp_extractor.extract_timestamp_and_slot(&inherent_data); let (timestamp, slot_num, offset) = match result { @@ -161,11 +150,13 @@ impl Stream for Slots { // never yield the same slot twice. if slot_num > self.last_slot { + let last_slot = self.last_slot; self.last_slot = slot_num; break Poll::Ready(Some(Ok(SlotInfo { number: slot_num, duration: self.slot_duration, + last_number: last_slot, timestamp, ends_at, inherent_data, diff --git a/client/consensus/uncles/Cargo.toml b/client/consensus/uncles/Cargo.toml new file mode 100644 index 0000000000000..54789c57944a1 --- /dev/null +++ b/client/consensus/uncles/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "sc-consensus-uncles" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "Generic uncle inclusion utilities for consensus" +edition = "2018" + +[dependencies] +sc-client-api = { version = "2.0.0", path = "../../api" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-authorship = { version = "2.0.0", path = "../../../primitives/authorship" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } +log = "0.4.8" diff --git a/client/consensus/uncles/src/lib.rs b/client/consensus/uncles/src/lib.rs new file mode 100644 index 0000000000000..2a129b200063b --- /dev/null +++ b/client/consensus/uncles/src/lib.rs @@ -0,0 +1,65 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Uncles functionality for Substrate. +#![forbid(unsafe_code, missing_docs)] + +use sp_consensus::SelectChain; +use sp_inherents::{InherentDataProviders}; +use log::warn; +use sc_client_api::ProvideUncles; +use sp_runtime::traits::{Block as BlockT, Header}; +use std::sync::Arc; +use sp_authorship; + +/// Maximum uncles generations we may provide to the runtime. +const MAX_UNCLE_GENERATIONS: u32 = 8; + +/// Register uncles inherent data provider, if not registered already. +pub fn register_uncles_inherent_data_provider( + client: Arc, + select_chain: SC, + inherent_data_providers: &InherentDataProviders, +) -> Result<(), sp_consensus::Error> where + B: BlockT, + C: ProvideUncles + Send + Sync + 'static, + SC: SelectChain + 'static, +{ + if !inherent_data_providers.has_provider(&sp_authorship::INHERENT_IDENTIFIER) { + inherent_data_providers + .register_provider(sp_authorship::InherentDataProvider::new(move || { + { + let chain_head = match select_chain.best_chain() { + Ok(x) => x, + Err(e) => { + warn!(target: "uncles", "Unable to get chain head: {:?}", e); + return Vec::new(); + } + }; + match client.uncles(chain_head.hash(), MAX_UNCLE_GENERATIONS.into()) { + Ok(uncles) => uncles, + Err(e) => { + warn!(target: "uncles", "Unable to get uncles: {:?}", e); + Vec::new() + } + } + } + })) + .map_err(|err| sp_consensus::Error::InherentData(err.into()))?; + } + Ok(()) +} + diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml new file mode 100644 index 0000000000000..d34b04a17edd3 --- /dev/null +++ b/client/db/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "sc-client-db" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +parking_lot = "0.9.0" +log = "0.4.8" +kvdb = "0.3.0" +kvdb-rocksdb = { version = "0.4", optional = true } +kvdb-memorydb = "0.3.0" +linked-hash-map = "0.5.2" +hash-db = "0.15.2" +parity-util-mem = { version = "0.4", default-features = false, features = ["std"] } +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } + +sc-client-api = { version = "2.0.0", path = "../api" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sc-client = { version = "2.0.0", path = "../" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } +sc-executor = { version = "2.0.0", path = "../executor" } +sc-state-db = { version = "2.0.0", path = "../state-db" } +sp-trie = { version = "2.0.0", path = "../../primitives/trie" } +sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } + +[dev-dependencies] +sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } +env_logger = "0.7.0" +quickcheck = "0.9" + +[features] +default = [] +test-helpers = [] diff --git a/core/client/db/src/cache/list_cache.rs b/client/db/src/cache/list_cache.rs similarity index 99% rename from core/client/db/src/cache/list_cache.rs rename to client/db/src/cache/list_cache.rs index 7a4fcc448e0e5..6345486f17f94 100644 --- a/core/client/db/src/cache/list_cache.rs +++ b/client/db/src/cache/list_cache.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -43,8 +43,8 @@ use std::collections::{BTreeSet, BTreeMap}; use log::warn; -use client::error::{Error as ClientError, Result as ClientResult}; -use sr_primitives::traits::{ +use sp_blockchain::{Error as ClientError, Result as ClientResult}; +use sp_runtime::traits::{ Block as BlockT, NumberFor, Zero, Bounded, CheckedSub }; @@ -651,7 +651,7 @@ pub fn destroy_fork, Tx: Stor /// Blockchain related functions. mod chain { - use sr_primitives::traits::Header as HeaderT; + use sp_runtime::traits::Header as HeaderT; use super::*; /// Is the block1 connected both ends of the range. @@ -724,9 +724,9 @@ fn read_forks>( #[cfg(test)] pub mod tests { - use test_client::runtime::H256; - use sr_primitives::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; - use sr_primitives::traits::Header as HeaderT; + use substrate_test_runtime_client::runtime::H256; + use sp_runtime::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; + use sp_runtime::traits::Header as HeaderT; use crate::cache::list_storage::tests::{DummyStorage, FaultyStorage, DummyTransaction}; use super::*; diff --git a/core/client/db/src/cache/list_entry.rs b/client/db/src/cache/list_entry.rs similarity index 97% rename from core/client/db/src/cache/list_entry.rs rename to client/db/src/cache/list_entry.rs index 6de369ecf56d2..d3f7dd57693c1 100644 --- a/core/client/db/src/cache/list_entry.rs +++ b/client/db/src/cache/list_entry.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,8 +16,8 @@ //! List-cache storage entries. -use client::error::Result as ClientResult; -use sr_primitives::traits::{Block as BlockT, NumberFor}; +use sp_blockchain::Result as ClientResult; +use sp_runtime::traits::{Block as BlockT, NumberFor}; use codec::{Encode, Decode}; use crate::cache::{CacheItemT, ComplexBlockId}; diff --git a/core/client/db/src/cache/list_storage.rs b/client/db/src/cache/list_storage.rs similarity index 97% rename from core/client/db/src/cache/list_storage.rs rename to client/db/src/cache/list_storage.rs index 4fd9ecaced25e..9cd3b1049a4f8 100644 --- a/core/client/db/src/cache/list_storage.rs +++ b/client/db/src/cache/list_storage.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,10 +20,10 @@ use std::sync::Arc; use kvdb::{KeyValueDB, DBTransaction}; -use client::error::{Error as ClientError, Result as ClientResult}; +use sp_blockchain::{Error as ClientError, Result as ClientResult}; use codec::{Encode, Decode}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use crate::utils::{self, db_err, meta_keys}; use crate::cache::{CacheItemT, ComplexBlockId}; @@ -84,13 +84,13 @@ pub trait StorageTransaction { #[derive(Debug)] pub struct DbColumns { /// Column holding cache meta. - pub meta: Option, + pub meta: u32, /// Column holding the mapping of { block number => block hash } for blocks of the best chain. - pub key_lookup: Option, + pub key_lookup: u32, /// Column holding the mapping of { block hash => block header }. - pub header: Option, + pub header: u32, /// Column holding cache entries. - pub cache: Option, + pub cache: u32, } /// Database-backed list cache storage. diff --git a/client/db/src/cache/mod.rs b/client/db/src/cache/mod.rs new file mode 100644 index 0000000000000..bef8d9a7919d3 --- /dev/null +++ b/client/db/src/cache/mod.rs @@ -0,0 +1,371 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! DB-backed cache of blockchain data. + +use std::{sync::Arc, collections::HashMap}; +use parking_lot::RwLock; + +use kvdb::{KeyValueDB, DBTransaction}; + +use sc_client_api::blockchain::{well_known_cache_keys::{self, Id as CacheKeyId}, Cache as BlockchainCache}; +use sp_blockchain::Result as ClientResult; +use codec::{Encode, Decode}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; +use crate::utils::{self, COLUMN_META, db_err}; + +use self::list_cache::{ListCache, PruningStrategy}; + +mod list_cache; +mod list_entry; +mod list_storage; + +/// Minimal post-finalization age of finalized blocks before they'll pruned. +const PRUNE_DEPTH: u32 = 1024; + +/// The type of entry that is inserted to the cache. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum EntryType { + /// Non-final entry. + NonFinal, + /// Final entry. + Final, + /// Genesis entry (inserted during cache initialization). + Genesis, +} + +/// Block identifier that holds both hash and number. +#[derive(Clone, Debug, Encode, Decode, PartialEq)] +pub struct ComplexBlockId { + hash: Block::Hash, + number: NumberFor, +} + +impl ComplexBlockId { + /// Create new complex block id. + pub fn new(hash: Block::Hash, number: NumberFor) -> Self { + ComplexBlockId { hash, number } + } +} + +impl ::std::cmp::PartialOrd for ComplexBlockId { + fn partial_cmp(&self, other: &ComplexBlockId) -> Option<::std::cmp::Ordering> { + self.number.partial_cmp(&other.number) + } +} + +/// All cache items must implement this trait. +pub trait CacheItemT: Clone + Decode + Encode + PartialEq {} + +impl CacheItemT for T where T: Clone + Decode + Encode + PartialEq {} + +/// Database-backed blockchain data cache. +pub struct DbCache { + cache_at: HashMap, self::list_storage::DbStorage>>, + db: Arc, + key_lookup_column: u32, + header_column: u32, + authorities_column: u32, + genesis_hash: Block::Hash, + best_finalized_block: ComplexBlockId, +} + +impl DbCache { + /// Create new cache. + pub fn new( + db: Arc, + key_lookup_column: u32, + header_column: u32, + authorities_column: u32, + genesis_hash: Block::Hash, + best_finalized_block: ComplexBlockId, + ) -> Self { + Self { + cache_at: HashMap::new(), + db, + key_lookup_column, + header_column, + authorities_column, + genesis_hash, + best_finalized_block, + } + } + + /// Set genesis block hash. + pub fn set_genesis_hash(&mut self, genesis_hash: Block::Hash) { + self.genesis_hash = genesis_hash; + } + + /// Begin cache transaction. + pub fn transaction<'a>(&'a mut self, tx: &'a mut DBTransaction) -> DbCacheTransaction<'a, Block> { + DbCacheTransaction { + cache: self, + tx, + cache_at_op: HashMap::new(), + best_finalized_block: None, + } + } + + /// Run post-commit cache operations. + pub fn commit(&mut self, ops: DbCacheTransactionOps) { + for (name, op) in ops.cache_at_op.into_iter() { + self.get_cache(name).on_transaction_commit(op); + } + if let Some(best_finalized_block) = ops.best_finalized_block { + self.best_finalized_block = best_finalized_block; + } + } + + /// Creates `ListCache` with the given name or returns a reference to the existing. + fn get_cache(&mut self, name: CacheKeyId) -> &mut ListCache, self::list_storage::DbStorage> { + get_cache_helper( + &mut self.cache_at, + name, + &self.db, + self.key_lookup_column, + self.header_column, + self.authorities_column, + &self.best_finalized_block + ) + } +} + +// This helper is needed because otherwise the borrow checker will require to +// clone all parameters outside of the closure. +fn get_cache_helper<'a, Block: BlockT>( + cache_at: &'a mut HashMap, self::list_storage::DbStorage>>, + name: CacheKeyId, + db: &Arc, + key_lookup: u32, + header: u32, + cache: u32, + best_finalized_block: &ComplexBlockId, +) -> &'a mut ListCache, self::list_storage::DbStorage> { + cache_at.entry(name).or_insert_with(|| { + ListCache::new( + self::list_storage::DbStorage::new(name.to_vec(), db.clone(), + self::list_storage::DbColumns { + meta: COLUMN_META, + key_lookup, + header, + cache, + }, + ), + cache_pruning_strategy(name), + best_finalized_block.clone(), + ) + }) +} + +/// Cache operations that are to be committed after database transaction is committed. +pub struct DbCacheTransactionOps { + cache_at_op: HashMap>>, + best_finalized_block: 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, + cache_at_op: HashMap>>, + best_finalized_block: Option>, +} + +impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { + /// Convert transaction into post-commit operations set. + pub fn into_ops(self) -> DbCacheTransactionOps { + DbCacheTransactionOps { + cache_at_op: self.cache_at_op, + best_finalized_block: self.best_finalized_block, + } + } + + /// When new block is inserted into database. + pub fn on_block_insert( + mut self, + parent: ComplexBlockId, + block: ComplexBlockId, + data_at: HashMap>, + entry_type: EntryType, + ) -> ClientResult { + assert!(self.cache_at_op.is_empty()); + + // prepare list of caches that are not update + // (we might still need to do some cache maintenance in this case) + let missed_caches = self.cache.cache_at.keys() + .filter(|cache| !data_at.contains_key(*cache)) + .cloned() + .collect::>(); + + let mut insert_op = |name: CacheKeyId, value: Option>| -> Result<(), sp_blockchain::Error> { + let cache = self.cache.get_cache(name); + let op = cache.on_block_insert( + &mut self::list_storage::DbStorageTransaction::new( + cache.storage(), + &mut self.tx, + ), + parent.clone(), + block.clone(), + value, + entry_type, + )?; + if let Some(op) = op { + self.cache_at_op.insert(name, op); + } + Ok(()) + }; + + data_at.into_iter().try_for_each(|(name, data)| insert_op(name, Some(data)))?; + missed_caches.into_iter().try_for_each(|name| insert_op(name, None))?; + + match entry_type { + EntryType::Final | EntryType::Genesis => + self.best_finalized_block = Some(block), + EntryType::NonFinal => (), + } + + Ok(self) + } + + /// When previously inserted block is finalized. + pub fn on_block_finalize( + mut self, + parent: ComplexBlockId, + block: ComplexBlockId + ) -> ClientResult { + assert!(self.cache_at_op.is_empty()); + + for (name, cache_at) in self.cache.cache_at.iter() { + let op = cache_at.on_block_finalize( + &mut self::list_storage::DbStorageTransaction::new( + cache_at.storage(), + &mut self.tx + ), + parent.clone(), + block.clone(), + )?; + + if let Some(op) = op { + self.cache_at_op.insert(name.to_owned(), op); + } + } + + self.best_finalized_block = Some(block); + + Ok(self) + } + + /// When block is reverted. + pub fn on_block_revert( + mut self, + reverted_block: &ComplexBlockId, + ) -> ClientResult { + for (name, cache) in self.cache.cache_at.iter() { + let op = cache.on_block_revert( + &mut self::list_storage::DbStorageTransaction::new( + cache.storage(), + &mut self.tx + ), + reverted_block, + )?; + + assert!(!self.cache_at_op.contains_key(name)); + self.cache_at_op.insert(name.to_owned(), op); + } + + Ok(self) + } +} + +/// Synchronous implementation of database-backed blockchain data cache. +pub struct DbCacheSync(pub RwLock>); + +impl BlockchainCache for DbCacheSync { + fn initialize(&self, key: &CacheKeyId, data: Vec) -> ClientResult<()> { + let mut cache = self.0.write(); + let genesis_hash = cache.genesis_hash; + let cache_contents = vec![(*key, data)].into_iter().collect(); + let db = cache.db.clone(); + let mut dbtx = DBTransaction::new(); + let tx = cache.transaction(&mut dbtx); + let tx = tx.on_block_insert( + ComplexBlockId::new(Default::default(), Zero::zero()), + ComplexBlockId::new(genesis_hash, Zero::zero()), + cache_contents, + EntryType::Genesis, + )?; + let tx_ops = tx.into_ops(); + db.write(dbtx).map_err(db_err)?; + cache.commit(tx_ops); + Ok(()) + } + + fn get_at( + &self, + key: &CacheKeyId, + at: &BlockId, + ) -> Option<((NumberFor, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)> { + let mut cache = self.0.write(); + let storage = cache.get_cache(*key).storage(); + let db = storage.db(); + let columns = storage.columns(); + let at = match *at { + BlockId::Hash(hash) => { + let header = utils::read_header::( + &**db, + columns.key_lookup, + columns.header, + BlockId::Hash(hash.clone())).ok()??; + ComplexBlockId::new(hash, *header.number()) + }, + BlockId::Number(number) => { + let hash = utils::read_header::( + &**db, + columns.key_lookup, + columns.header, + BlockId::Number(number.clone())).ok()??.hash(); + ComplexBlockId::new(hash, number) + }, + }; + + cache.cache_at + .get(key)? + .value_at_block(&at) + .map(|block_and_value| block_and_value.map(|(begin_block, end_block, value)| + ( + (begin_block.number, begin_block.hash), + end_block.map(|end_block| (end_block.number, end_block.hash)), + value, + ))) + .ok()? + } +} + +/// Get pruning strategy for given cache. +fn cache_pruning_strategy>(cache: CacheKeyId) -> PruningStrategy { + // the cache is mostly used to store data from consensus engines + // this kind of data is only required for non-finalized blocks + // => by default we prune finalized cached entries + + match cache { + // we need to keep changes tries configurations forever (or at least until changes tries, + // that were built using this configuration, are pruned) to make it possible to refer + // to old changes tries + well_known_cache_keys::CHANGES_TRIE_CONFIG => PruningStrategy::NeverPrune, + _ => PruningStrategy::ByDepth(PRUNE_DEPTH.into()), + } +} diff --git a/client/db/src/children.rs b/client/db/src/children.rs new file mode 100644 index 0000000000000..c90af66027fdc --- /dev/null +++ b/client/db/src/children.rs @@ -0,0 +1,120 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Functionality for reading and storing children hashes from db. + +use kvdb::{KeyValueDB, DBTransaction}; +use codec::{Encode, Decode}; +use sp_blockchain; +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: &dyn KeyValueDB, column: u32, prefix: &[u8], parent_hash: K) -> sp_blockchain::Result> { + let mut buf = prefix.to_vec(); + parent_hash.using_encoded(|s| buf.extend(s)); + + let raw_val_opt = match db.get(column, &buf[..]) { + Ok(raw_val_opt) => raw_val_opt, + Err(_) => return Err(sp_blockchain::Error::Backend("Error reading value from database".into())), + }; + + let raw_val = match raw_val_opt { + Some(val) => val, + None => return Ok(Vec::new()), + }; + + let children: Vec = match Decode::decode(&mut &raw_val[..]) { + Ok(children) => children, + Err(_) => return Err(sp_blockchain::Error::Backend("Error decoding children".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: u32, + 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: u32, + 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(1); + + let mut tx = DBTransaction::new(); + + let mut children1 = Vec::new(); + children1.push(1_3); + children1.push(1_5); + write_children(&mut tx, 0, PREFIX, 1_1, children1); + + let mut children2 = Vec::new(); + children2.push(1_4); + children2.push(1_6); + write_children(&mut tx, 0, PREFIX, 1_2, children2); + + db.write(tx.clone()).expect("(2) Commiting transaction failed"); + + let r1: Vec = read_children(&db, 0, PREFIX, 1_1).expect("(1) Getting r1 failed"); + let r2: Vec = read_children(&db, 0, PREFIX, 1_2).expect("(1) Getting r2 failed"); + + assert_eq!(r1, vec![1_3, 1_5]); + assert_eq!(r2, vec![1_4, 1_6]); + + remove_children(&mut tx, 0, PREFIX, 1_2); + db.write(tx).expect("(2) Commiting transaction failed"); + + let r1: Vec = read_children(&db, 0, PREFIX, 1_1).expect("(2) Getting r1 failed"); + let r2: Vec = read_children(&db, 0, PREFIX, 1_2).expect("(2) Getting r2 failed"); + + assert_eq!(r1, vec![1_3, 1_5]); + assert_eq!(r2.len(), 0); + } +} diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs new file mode 100644 index 0000000000000..06d0dc18ffa36 --- /dev/null +++ b/client/db/src/lib.rs @@ -0,0 +1,2604 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Client backend that uses RocksDB database as storage. +//! +//! # Canonicality vs. Finality +//! +//! Finality indicates that a block will not be reverted, according to the consensus algorithm, +//! while canonicality indicates that the block may be reverted, but we will be unable to do so, +//! having discarded heavy state that will allow a chain reorganization. +//! +//! Finality implies canonicality but not vice-versa. + +#![warn(missing_docs)] + +pub mod light; +pub mod offchain; + +mod children; +mod cache; +mod storage_cache; +mod utils; +mod stats; + +use std::sync::Arc; +use std::path::PathBuf; +use std::io; +use std::collections::{HashMap, HashSet}; + +use sc_client_api::{execution_extensions::ExecutionExtensions, ForkBlocks, UsageInfo, MemoryInfo, BadBlocks, IoInfo}; +use sc_client_api::backend::NewBlockState; +use sc_client_api::backend::{StorageCollection, ChildStorageCollection}; +use sp_blockchain::{ + Result as ClientResult, Error as ClientError, + well_known_cache_keys, HeaderBackend, +}; +use codec::{Decode, Encode}; +use hash_db::Prefix; +use kvdb::{KeyValueDB, DBTransaction}; +use sp_trie::{MemoryDB, PrefixedMemoryDB, prefixed_key}; +use parking_lot::{Mutex, RwLock}; +use sp_core::{ChangesTrieConfiguration, convert_hash, traits::CodeExecutor}; +use sp_core::storage::{well_known_keys, ChildInfo}; +use sp_runtime::{ + generic::{BlockId, DigestItem}, Justification, Storage, + BuildStorage, +}; +use sp_runtime::traits::{ + Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion, HasherFor, +}; +use sc_executor::RuntimeInfo; +use sp_state_machine::{ + DBValue, ChangesTrieTransaction, ChangesTrieCacheAction, ChangesTrieBuildCache, + backend::Backend as StateBackend, UsageInfo as StateUsageInfo, +}; +use crate::utils::{Meta, db_err, meta_keys, read_db, read_meta}; +use sc_client::leaves::{LeafSet, FinalizationDisplaced}; +use sc_state_db::StateDb; +use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache}; +use crate::storage_cache::{CachingState, SharedCache, new_shared_cache}; +use crate::stats::StateUsageStats; +use log::{trace, debug, warn}; +pub use sc_state_db::PruningMode; + +#[cfg(feature = "test-helpers")] +use sc_client::in_mem::Backend as InMemoryBackend; + +const CANONICALIZATION_DELAY: u64 = 4096; +const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR: u32 = 32768; + +/// Default value for storage cache child ratio. +const DEFAULT_CHILD_RATIO: (usize, usize) = (1, 10); + +/// DB-backed patricia trie state, transaction type is an overlay of changes to commit. +pub type DbState = sp_state_machine::TrieBackend< + Arc>>, HasherFor +>; + +/// Re-export the KVDB trait so that one can pass an implementation of it. +pub use kvdb; + +/// A reference tracking state. +/// +/// It makes sure that the hash we are using stays pinned in storage +/// until this structure is dropped. +pub struct RefTrackingState { + state: DbState, + storage: Arc>, + parent_hash: Option, +} + +impl RefTrackingState { + fn new(state: DbState, storage: Arc>, parent_hash: Option) -> Self { + RefTrackingState { + state, + parent_hash, + storage, + } + } +} + +impl Drop for RefTrackingState { + fn drop(&mut self) { + if let Some(hash) = &self.parent_hash { + self.storage.state_db.unpin(hash); + } + } +} + +impl std::fmt::Debug for RefTrackingState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Block {:?}", self.parent_hash) + } +} + +impl StateBackend> for RefTrackingState { + type Error = as StateBackend>>::Error; + type Transaction = as StateBackend>>::Transaction; + type TrieBackendStorage = as StateBackend>>::TrieBackendStorage; + + fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + self.state.storage(key) + } + + fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { + self.state.storage_hash(key) + } + + fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.state.child_storage(storage_key, child_info, key) + } + + fn exists_storage(&self, key: &[u8]) -> Result { + self.state.exists_storage(key) + } + + fn exists_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result { + self.state.exists_child_storage(storage_key, child_info, key) + } + + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + self.state.next_storage_key(key) + } + + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.state.next_child_storage_key(storage_key, child_info, key) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + self.state.for_keys_with_prefix(prefix, f) + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.state.for_key_values_with_prefix(prefix, f) + } + + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + f: F, + ) { + self.state.for_keys_in_child_storage(storage_key, child_info, f) + } + + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + f: F, + ) { + self.state.for_child_keys_with_prefix(storage_key, child_info, prefix, f) + } + + fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) + where + I: IntoIterator, Option>)> + { + self.state.storage_root(delta) + } + + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (B::Hash, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + { + self.state.child_storage_root(storage_key, child_info, delta) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + self.state.pairs() + } + + fn keys(&self, prefix: &[u8]) -> Vec> { + self.state.keys(prefix) + } + + fn child_keys( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + ) -> Vec> { + self.state.child_keys(storage_key, child_info, prefix) + } + + fn as_trie_backend(&mut self) + -> Option<&sp_state_machine::TrieBackend>> + { + self.state.as_trie_backend() + } +} + +/// Database settings. +pub struct DatabaseSettings { + /// State cache size. + pub state_cache_size: usize, + /// Ratio of cache size dedicated to child tries. + pub state_cache_child_ratio: Option<(usize, usize)>, + /// Pruning mode. + pub pruning: PruningMode, + /// Where to find the database. + pub source: DatabaseSettingsSrc, +} + +/// Where to find the database.. +pub enum DatabaseSettingsSrc { + /// Load a database from a given path. Recommended for most uses. + Path { + /// Path to the database. + path: PathBuf, + /// Cache size in bytes. If `None` default is used. + cache_size: Option, + }, + + /// Use a custom already-open database. + Custom(Arc), +} + +/// Create an instance of db-backed client. +pub fn new_client( + settings: DatabaseSettings, + executor: E, + genesis_storage: S, + fork_blocks: ForkBlocks, + bad_blocks: BadBlocks, + execution_extensions: ExecutionExtensions, +) -> Result<( + sc_client::Client< + Backend, + sc_client::LocalCallExecutor, E>, + Block, + RA, + >, + Arc>, + ), + sp_blockchain::Error, +> + where + Block: BlockT, + E: CodeExecutor + RuntimeInfo, + S: BuildStorage, +{ + let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); + let executor = sc_client::LocalCallExecutor::new(backend.clone(), executor); + Ok(( + sc_client::Client::new( + backend.clone(), + executor, + genesis_storage, + fork_blocks, + bad_blocks, + execution_extensions, + )?, + backend, + )) +} + +pub(crate) mod columns { + pub const META: u32 = crate::utils::COLUMN_META; + pub const STATE: u32 = 1; + pub const STATE_META: u32 = 2; + /// maps hashes to lookup keys and numbers to canon hashes. + pub const KEY_LOOKUP: u32 = 3; + pub const HEADER: u32 = 4; + pub const BODY: u32 = 5; + pub const JUSTIFICATION: u32 = 6; + pub const CHANGES_TRIE: u32 = 7; + pub const AUX: u32 = 8; + /// Offchain workers local storage + pub const OFFCHAIN: u32 = 9; +} + +struct PendingBlock { + header: Block::Header, + justification: Option, + body: Option>, + leaf_state: NewBlockState, +} + +// wrapper that implements trait required for state_db +struct StateMetaDb<'a>(&'a dyn KeyValueDB); + +impl<'a> sc_state_db::MetaDb for StateMetaDb<'a> { + type Error = io::Error; + + fn get_meta(&self, key: &[u8]) -> Result>, Self::Error> { + self.0.get(columns::STATE_META, key).map(|r| r.map(|v| v.to_vec())) + } +} + +/// Block database +pub struct BlockchainDb { + db: Arc, + meta: Arc, Block::Hash>>>, + leaves: RwLock>>, + header_metadata_cache: HeaderMetadataCache, +} + +impl BlockchainDb { + fn new(db: Arc) -> ClientResult { + let meta = read_meta::(&*db, columns::META, columns::HEADER)?; + let leaves = LeafSet::read_from_db(&*db, columns::META, meta_keys::LEAF_PREFIX)?; + Ok(BlockchainDb { + db, + leaves: RwLock::new(leaves), + meta: Arc::new(RwLock::new(meta)), + header_metadata_cache: HeaderMetadataCache::default(), + }) + } + + fn update_meta( + &self, + hash: Block::Hash, + number: ::Number, + is_best: bool, + is_finalized: bool + ) { + let mut meta = self.meta.write(); + if number.is_zero() { + meta.genesis_hash = hash; + meta.finalized_hash = hash; + } + + if is_best { + meta.best_number = number; + meta.best_hash = hash; + } + + if is_finalized { + meta.finalized_number = number; + meta.finalized_hash = hash; + } + } +} + +impl sc_client::blockchain::HeaderBackend for BlockchainDb { + fn header(&self, id: BlockId) -> ClientResult> { + utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) + } + + fn info(&self) -> sc_client::blockchain::Info { + let meta = self.meta.read(); + sc_client::blockchain::Info { + best_hash: meta.best_hash, + best_number: meta.best_number, + genesis_hash: meta.genesis_hash, + finalized_hash: meta.finalized_hash, + finalized_number: meta.finalized_number, + } + } + + fn status(&self, id: BlockId) -> ClientResult { + let exists = match id { + BlockId::Hash(_) => read_db( + &*self.db, + columns::KEY_LOOKUP, + columns::HEADER, + id + )?.is_some(), + BlockId::Number(n) => n <= self.meta.read().best_number, + }; + match exists { + true => Ok(sc_client::blockchain::BlockStatus::InChain), + false => Ok(sc_client::blockchain::BlockStatus::Unknown), + } + } + + fn number(&self, hash: Block::Hash) -> ClientResult>> { + Ok(self.header_metadata(hash).ok().map(|header_metadata| header_metadata.number)) + } + + fn hash(&self, number: NumberFor) -> ClientResult> { + self.header(BlockId::Number(number)).and_then(|maybe_header| match maybe_header { + Some(header) => Ok(Some(header.hash().clone())), + None => Ok(None), + }) + } +} + +impl sc_client::blockchain::Backend for BlockchainDb { + fn body(&self, id: BlockId) -> ClientResult>> { + match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? { + Some(body) => match Decode::decode(&mut &body[..]) { + Ok(body) => Ok(Some(body)), + Err(err) => return Err(sp_blockchain::Error::Backend( + format!("Error decoding body: {}", err) + )), + } + None => Ok(None), + } + } + + fn justification(&self, id: BlockId) -> ClientResult> { + match read_db(&*self.db, columns::KEY_LOOKUP, columns::JUSTIFICATION, id)? { + Some(justification) => match Decode::decode(&mut &justification[..]) { + Ok(justification) => Ok(Some(justification)), + Err(err) => return Err(sp_blockchain::Error::Backend( + format!("Error decoding justification: {}", err) + )), + } + None => Ok(None), + } + } + + fn last_finalized(&self) -> ClientResult { + Ok(self.meta.read().finalized_hash.clone()) + } + + fn cache(&self) -> Option>> { + None + } + + fn leaves(&self) -> ClientResult> { + Ok(self.leaves.read().hashes()) + } + + fn children(&self, parent_hash: Block::Hash) -> ClientResult> { + children::read_children(&*self.db, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash) + } +} + +impl sc_client::blockchain::ProvideCache for BlockchainDb { + fn cache(&self) -> Option>> { + None + } +} + +impl HeaderMetadata for BlockchainDb { + type Error = sp_blockchain::Error; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.header_metadata_cache.header_metadata(hash).or_else(|_| { + self.header(BlockId::hash(hash))?.map(|header| { + let header_metadata = CachedHeaderMetadata::from(&header); + self.header_metadata_cache.insert_header_metadata( + header_metadata.hash, + header_metadata.clone(), + ); + header_metadata + }).ok_or(ClientError::UnknownBlock(format!("header not found in db: {}", hash))) + }) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.header_metadata_cache.insert_header_metadata(hash, metadata) + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.header_metadata_cache.remove_header_metadata(hash); + } +} + +/// Database transaction +pub struct BlockImportOperation { + old_state: CachingState, Block>, + db_updates: PrefixedMemoryDB>, + storage_updates: StorageCollection, + child_storage_updates: ChildStorageCollection, + changes_trie_updates: MemoryDB>, + changes_trie_cache_update: Option>>, + pending_block: Option>, + aux_ops: Vec<(Vec, Option>)>, + finalized_blocks: Vec<(BlockId, Option)>, + set_head: Option>, + commit_state: bool, +} + +impl BlockImportOperation { + fn apply_aux(&mut self, transaction: &mut DBTransaction) { + for (key, maybe_val) in self.aux_ops.drain(..) { + match maybe_val { + Some(val) => transaction.put_vec(columns::AUX, &key, val), + None => transaction.delete(columns::AUX, &key), + } + } + } +} + +impl sc_client_api::backend::BlockImportOperation for BlockImportOperation { + type State = CachingState, Block>; + + fn state(&self) -> ClientResult> { + Ok(Some(&self.old_state)) + } + + fn set_block_data( + &mut self, + header: Block::Header, + body: Option>, + justification: Option, + leaf_state: NewBlockState, + ) -> ClientResult<()> { + assert!(self.pending_block.is_none(), "Only one block per operation is allowed"); + self.pending_block = Some(PendingBlock { + header, + body, + justification, + leaf_state, + }); + Ok(()) + } + + fn update_cache(&mut self, _cache: HashMap>) { + // Currently cache isn't implemented on full nodes. + } + + fn update_db_storage(&mut self, update: PrefixedMemoryDB>) -> ClientResult<()> { + self.db_updates = update; + Ok(()) + } + + fn reset_storage( + &mut self, + storage: Storage, + ) -> ClientResult { + + if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { + return Err(sp_blockchain::Error::GenesisInvalid.into()); + } + + for child_key in storage.children.keys() { + if !well_known_keys::is_child_storage_key(&child_key) { + return Err(sp_blockchain::Error::GenesisInvalid.into()); + } + } + + let child_delta = storage.children.into_iter().map(|(storage_key, child_content)| ( + storage_key, + child_content.data.into_iter().map(|(k, v)| (k, Some(v))), child_content.child_info), + ); + + let (root, transaction) = self.old_state.full_storage_root( + storage.top.into_iter().map(|(k, v)| (k, Some(v))), + child_delta + ); + + self.db_updates = transaction; + self.commit_state = true; + Ok(root) + } + + fn update_changes_trie( + &mut self, + update: ChangesTrieTransaction, NumberFor>, + ) -> ClientResult<()> { + self.changes_trie_updates = update.0; + self.changes_trie_cache_update = Some(update.1); + Ok(()) + } + + fn insert_aux(&mut self, ops: I) -> ClientResult<()> + where I: IntoIterator, Option>)> + { + self.aux_ops.append(&mut ops.into_iter().collect()); + Ok(()) + } + + fn update_storage( + &mut self, + update: StorageCollection, + child_update: ChildStorageCollection, + ) -> ClientResult<()> { + self.storage_updates = update; + self.child_storage_updates = child_update; + Ok(()) + } + + fn mark_finalized( + &mut self, + block: BlockId, + justification: Option, + ) -> ClientResult<()> { + self.finalized_blocks.push((block, justification)); + Ok(()) + } + + fn mark_head(&mut self, block: BlockId) -> ClientResult<()> { + assert!(self.set_head.is_none(), "Only one set head per operation is allowed"); + self.set_head = Some(block); + Ok(()) + } +} + +struct StorageDb { + pub db: Arc, + pub state_db: StateDb>, +} + +impl sp_state_machine::Storage> for StorageDb { + fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result, String> { + let key = prefixed_key::>(key, prefix); + self.state_db.get(&key, self) + .map_err(|e| format!("Database backend error: {:?}", e)) + } +} + +impl sc_state_db::NodeDb for StorageDb { + type Error = io::Error; + type Key = [u8]; + + fn get(&self, key: &[u8]) -> Result>, Self::Error> { + self.db.get(columns::STATE, key).map(|r| r.map(|v| v.to_vec())) + } +} + +struct DbGenesisStorage(pub Block::Hash); + +impl DbGenesisStorage { + pub fn new() -> Self { + let mut root = Block::Hash::default(); + let mut mdb = MemoryDB::>::default(); + sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); + DbGenesisStorage(root) + } +} + +impl sp_state_machine::Storage> for DbGenesisStorage { + fn get(&self, _key: &Block::Hash, _prefix: Prefix) -> Result, String> { + Ok(None) + } +} + +/// A database wrapper for changes tries. +pub struct DbChangesTrieStorage { + db: Arc, + meta: Arc, Block::Hash>>>, + min_blocks_to_keep: Option, + cache: RwLock>>, +} + +impl DbChangesTrieStorage { + /// Commit new changes trie. + pub fn commit(&self, tx: &mut DBTransaction, mut changes_trie: MemoryDB>) { + for (key, (val, _)) in changes_trie.drain() { + tx.put(columns::CHANGES_TRIE, key.as_ref(), &val); + } + } + + /// Commit changes into changes trie build cache. + pub fn commit_cache(&self, cache_update: ChangesTrieCacheAction>) { + self.cache.write().perform(cache_update); + } + + /// Prune obsolete changes tries. + pub fn prune( + &self, + config: &ChangesTrieConfiguration, + tx: &mut DBTransaction, + block_hash: Block::Hash, + block_num: NumberFor, + ) { + // never prune on archive nodes + let min_blocks_to_keep = match self.min_blocks_to_keep { + Some(min_blocks_to_keep) => min_blocks_to_keep, + None => return, + }; + + sp_state_machine::prune_changes_tries( + config, + &*self, + min_blocks_to_keep.into(), + &sp_state_machine::ChangesTrieAnchorBlockId { + hash: convert_hash(&block_hash), + number: block_num, + }, + |node| tx.delete(columns::CHANGES_TRIE, node.as_ref())); + } +} + +impl sc_client_api::backend::PrunableStateChangesTrieStorage + for DbChangesTrieStorage +{ + fn oldest_changes_trie_block( + &self, + config: &ChangesTrieConfiguration, + best_finalized_block: NumberFor, + ) -> NumberFor { + match self.min_blocks_to_keep { + Some(min_blocks_to_keep) => sp_state_machine::oldest_non_pruned_changes_trie( + config, + min_blocks_to_keep.into(), + best_finalized_block, + ), + None => One::one(), + } + } +} + +impl sp_state_machine::ChangesTrieRootsStorage, NumberFor> + for DbChangesTrieStorage +{ + fn build_anchor( + &self, + hash: Block::Hash, + ) -> Result>, String> { + utils::read_header::( + &*self.db, + columns::KEY_LOOKUP, + columns::HEADER, + BlockId::Hash(hash), + ) + .map_err(|e| e.to_string()) + .and_then(|maybe_header| maybe_header.map(|header| + sp_state_machine::ChangesTrieAnchorBlockId { + hash, + number: *header.number(), + } + ).ok_or_else(|| format!("Unknown header: {}", hash))) + } + + fn root( + &self, + anchor: &sp_state_machine::ChangesTrieAnchorBlockId>, + block: NumberFor, + ) -> Result, String> { + // 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 { + // if block is finalized, we could just read canonical hash + BlockId::Number(block) + } else { + // 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::( + &*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Number(current_num) + ).map_err(|e| e.to_string())?; + if maybe_anchor_header.hash() == current_hash { + // if anchor is canonicalized, then the block is also canonicalized + BlockId::Number(block) + } else { + // else (block is not finalized + anchor is not canonicalized): + // => 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::( + &*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Hash(current_hash) + ).map_err(|e| e.to_string())?; + + current_hash = *current_header.parent_hash(); + current_num = current_num - One::one(); + } + + BlockId::Hash(current_hash) + } + }; + + 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) + .cloned() + ) + } +} + +impl sp_state_machine::ChangesTrieStorage, NumberFor> + for DbChangesTrieStorage +{ + fn as_roots_storage(&self) + -> &dyn sp_state_machine::ChangesTrieRootsStorage, NumberFor> + { + self + } + + fn with_cached_changed_keys( + &self, + root: &Block::Hash, + functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool { + self.cache.read().with_changed_keys(root, functor) + } + + fn get(&self, key: &Block::Hash, _prefix: Prefix) -> Result, String> { + self.db.get(columns::CHANGES_TRIE, key.as_ref()).map_err(|err| format!("{}", err)) + } +} + +/// Frozen `value` at time `at`. +/// +/// Used as inner structure under lock in `FrozenForDuration`. +struct Frozen { + at: std::time::Instant, + value: T, +} + +/// Some value frozen for period of time. +/// +/// If time `duration` not passed since the value was instantiated, +/// current frozen value is returned. Otherwise, you have to provide +/// a new value which will be again frozen for `duration`. +pub(crate) struct FrozenForDuration { + duration: std::time::Duration, + value: RwLock>, +} + +impl FrozenForDuration { + fn new(duration: std::time::Duration, initial: T) -> Self { + Self { + duration, + value: Frozen { at: std::time::Instant::now(), value: initial }.into(), + } + } + + fn take_or_else(&self, f: F) -> T where F: FnOnce() -> T { + if self.value.read().at.elapsed() > self.duration { + let mut write_lock = self.value.write(); + let new_value = f(); + write_lock.at = std::time::Instant::now(); + write_lock.value = new_value.clone(); + new_value + } else { + self.value.read().value.clone() + } + } +} + +/// Disk backend. +/// +/// Disk backend keps data in a key-value store. In archive mode, trie nodes are kept from all blocks. +/// Otherwise, trie nodes are kept only from some recent blocks. +pub struct Backend { + storage: Arc>, + offchain_storage: offchain::LocalStorage, + changes_tries_storage: DbChangesTrieStorage, + /// None<*> means that the value hasn't been cached yet. Some(*) means that the value (either None or + /// Some(*)) has been cached and is valid. + changes_trie_config: Mutex>>, + blockchain: BlockchainDb, + canonicalization_delay: u64, + shared_cache: SharedCache, + import_lock: RwLock<()>, + is_archive: bool, + io_stats: FrozenForDuration<(kvdb::IoStats, StateUsageInfo)>, + state_usage: StateUsageStats, +} + +impl Backend { + /// Create a new instance of database backend. + /// + /// The pruning window is how old a block must be before the state is pruned. + pub fn new(config: DatabaseSettings, canonicalization_delay: u64) -> ClientResult { + let db = crate::utils::open_database(&config, columns::META, "full")?; + Self::from_kvdb(db as Arc<_>, canonicalization_delay, &config) + } + + /// Create new memory-backed client backend for tests. + #[cfg(any(test, feature = "test-helpers"))] + pub fn new_test(keep_blocks: u32, canonicalization_delay: u64) -> Self { + let db = Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)); + let db_setting = DatabaseSettings { + state_cache_size: 16777216, + state_cache_child_ratio: Some((50, 100)), + pruning: PruningMode::keep_blocks(keep_blocks), + source: DatabaseSettingsSrc::Custom(db), + }; + + Self::new(db_setting, canonicalization_delay).expect("failed to create test-db") + } + + fn from_kvdb( + db: Arc, + canonicalization_delay: u64, + config: &DatabaseSettings, + ) -> ClientResult { + let is_archive_pruning = config.pruning.is_archive(); + let blockchain = BlockchainDb::new(db.clone())?; + let meta = blockchain.meta.clone(); + let map_e = |e: sc_state_db::Error| sp_blockchain::Error::from( + format!("State database error: {:?}", e) + ); + let state_db: StateDb<_, _> = StateDb::new(config.pruning.clone(), &StateMetaDb(&*db)) + .map_err(map_e)?; + let storage_db = StorageDb { + db: db.clone(), + state_db, + }; + let offchain_storage = offchain::LocalStorage::new(db.clone()); + let changes_tries_storage = DbChangesTrieStorage { + db, + meta, + min_blocks_to_keep: if is_archive_pruning { + None + } else { + Some(MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR) + }, + cache: RwLock::new(ChangesTrieBuildCache::new()), + }; + + Ok(Backend { + storage: Arc::new(storage_db), + offchain_storage, + changes_tries_storage, + changes_trie_config: Mutex::new(None), + blockchain, + canonicalization_delay, + shared_cache: new_shared_cache( + config.state_cache_size, + config.state_cache_child_ratio.unwrap_or(DEFAULT_CHILD_RATIO), + ), + import_lock: Default::default(), + is_archive: is_archive_pruning, + io_stats: FrozenForDuration::new(std::time::Duration::from_secs(1), (kvdb::IoStats::empty(), StateUsageInfo::empty())), + state_usage: StateUsageStats::new(), + }) + } + + /// Returns in-memory blockchain that contains the same set of blocks as self. + #[cfg(feature = "test-helpers")] + pub fn as_in_memory(&self) -> InMemoryBackend { + use sc_client_api::backend::{Backend as ClientBackend, BlockImportOperation}; + use sc_client::blockchain::Backend as BlockchainBackend; + + let inmem = InMemoryBackend::::new(); + + // get all headers hashes && sort them by number (could be duplicate) + let mut headers: Vec<(NumberFor, Block::Hash, Block::Header)> = Vec::new(); + for (_, header) in self.blockchain.db.iter(columns::HEADER) { + let header = Block::Header::decode(&mut &header[..]).unwrap(); + let hash = header.hash(); + let number = *header.number(); + let pos = headers.binary_search_by(|item| item.0.cmp(&number)); + match pos { + Ok(pos) => headers.insert(pos, (number, hash, header)), + Err(pos) => headers.insert(pos, (number, hash, header)), + } + } + + // insert all other headers + bodies + justifications + let info = self.blockchain.info(); + for (number, hash, header) in headers { + let id = BlockId::Hash(hash); + let justification = self.blockchain.justification(id).unwrap(); + let body = self.blockchain.body(id).unwrap(); + let state = self.state_at(id).unwrap().pairs(); + + let new_block_state = if number.is_zero() { + NewBlockState::Final + } else if hash == info.best_hash { + NewBlockState::Best + } else { + NewBlockState::Normal + }; + let mut op = inmem.begin_operation().unwrap(); + op.set_block_data(header, body, justification, new_block_state).unwrap(); + op.update_db_storage(vec![(None, state.into_iter().map(|(k, v)| (k, Some(v))).collect())]) + .unwrap(); + inmem.commit_operation(op).unwrap(); + } + + // and now finalize the best block we have + inmem.finalize_block(BlockId::Hash(info.finalized_hash), None).unwrap(); + + inmem + } + + /// Returns total numbet of blocks (headers) in the block DB. + #[cfg(feature = "test-helpers")] + pub fn blocks_count(&self) -> u64 { + self.blockchain.db.iter(columns::HEADER).count() as u64 + } + + /// Read (from storage or cache) changes trie config. + /// + /// Currently changes tries configuration is set up once (at genesis) and could not + /// be changed. Thus, we'll actually read value once and then just use cached value. + fn changes_trie_config(&self, block: Block::Hash) -> ClientResult> { + let mut cached_changes_trie_config = self.changes_trie_config.lock(); + match cached_changes_trie_config.clone() { + Some(cached_changes_trie_config) => Ok(cached_changes_trie_config), + None => { + use sc_client_api::backend::Backend; + let changes_trie_config = self + .state_at(BlockId::Hash(block))? + .storage(well_known_keys::CHANGES_TRIE_CONFIG)? + .and_then(|v| Decode::decode(&mut &*v).ok()); + *cached_changes_trie_config = Some(changes_trie_config.clone()); + Ok(changes_trie_config) + }, + } + } + + /// 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), + ) -> ClientResult<(Vec, Vec)> { + 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 = sp_blockchain::tree_route( + &self.blockchain, + meta.best_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(::sp_blockchain::Error::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, + ) -> ClientResult<()> { + let last_finalized = last_finalized.unwrap_or_else(|| self.blockchain.meta.read().finalized_hash); + if *header.parent_hash() != last_finalized { + return Err(::sp_blockchain::Error::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>>, + ) -> ClientResult<(Block::Hash, ::Number, bool, bool)> { + // 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 importing a non-finalized block. + fn force_delayed_canonicalize( + &self, + transaction: &mut DBTransaction, + hash: Block::Hash, + number: NumberFor, + ) + -> ClientResult<()> + { + let number_u64 = number.saturated_into::(); + if number_u64 > self.canonicalization_delay { + let new_canonical = number_u64 - self.canonicalization_delay; + + if new_canonical <= self.storage.state_db.best_canonical().unwrap_or(0) { + return Ok(()) + } + + let hash = if new_canonical == number_u64 { + hash + } else { + ::sc_client::blockchain::HeaderBackend::hash(&self.blockchain, new_canonical.saturated_into())? + .expect("existence of block with number `new_canonical` \ + implies existence of blocks with all numbers before it; qed") + }; + + trace!(target: "db", "Canonicalize block #{} ({:?})", new_canonical, hash); + let commit = self.storage.state_db.canonicalize_block(&hash) + .map_err(|e: sc_state_db::Error| sp_blockchain::Error::from(format!("State database error: {:?}", e)))?; + apply_state_commit(transaction, commit); + }; + + Ok(()) + } + + fn try_commit_operation(&self, mut operation: BlockImportOperation) + -> ClientResult<()> + { + let mut transaction = DBTransaction::new(); + let mut finalization_displaced_leaves = None; + + operation.apply_aux(&mut transaction); + + let mut meta_updates = Vec::with_capacity(operation.finalized_blocks.len()); + let mut last_finalized_hash = self.blockchain.meta.read().finalized_hash; + + for (block, justification) in operation.finalized_blocks { + let block_hash = self.blockchain.expect_block_hash_from_id(&block)?; + let block_header = self.blockchain.expect_header(BlockId::Hash(block_hash))?; + + meta_updates.push(self.finalize_block_with_transaction( + &mut transaction, + &block_hash, + &block_header, + Some(last_finalized_hash), + justification, + &mut 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, + )?; + + let header_metadata = CachedHeaderMetadata::from(&pending_block.header); + self.blockchain.insert_header_metadata( + header_metadata.hash, + header_metadata, + ); + + transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode()); + if let Some(body) = &pending_block.body { + transaction.put(columns::BODY, &lookup_key, &body.encode()); + } + 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 finalized = if operation.commit_state { + let mut changeset: sc_state_db::ChangeSet> = sc_state_db::ChangeSet::default(); + let mut ops: u64 = 0; + let mut bytes: u64 = 0; + for (key, (val, rc)) in operation.db_updates.drain() { + if rc > 0 { + ops += 1; + bytes += key.len() as u64 + val.len() as u64; + + changeset.inserted.push((key, val.to_vec())); + } else if rc < 0 { + ops += 1; + bytes += key.len() as u64; + + changeset.deleted.push(key); + } + } + self.state_usage.tally_writes(ops, bytes); + + let number_u64 = number.saturated_into::(); + let commit = self.storage.state_db.insert_block(&hash, number_u64, &pending_block.header.parent_hash(), changeset) + .map_err(|e: sc_state_db::Error| sp_blockchain::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(); + finalized + } else { + false + }; + + 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); + let cache = operation.old_state.release(); // release state reference so that it can be finalized + + 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, cache)) + } else { + None + }; + + let cache_update = if let Some(set_head) = operation.set_head { + if let Some(header) = ::sc_client::blockchain::HeaderBackend::header(&self.blockchain, set_head)? { + let number = header.number(); + let hash = header.hash(); + + let (enacted, retracted) = self.set_head_with_transaction( + &mut transaction, + hash.clone(), + (number.clone(), hash.clone()) + )?; + meta_updates.push((hash, *number, true, false)); + Some((enacted, retracted)) + } else { + return Err(sp_blockchain::Error::UnknownBlock(format!("Cannot set head {:?}", set_head))) + } + } else { + None + }; + + let write_result = self.storage.db.write(transaction).map_err(db_err); + + if let Some(changes_trie_cache_update) = operation.changes_trie_cache_update { + self.changes_tries_storage.commit_cache(changes_trie_cache_update); + } + + if let Some((number, hash, enacted, retracted, displaced_leaf, is_best, mut cache)) = imported { + if let Err(e) = write_result { + let mut leaves = self.blockchain.leaves.write(); + let mut undo = leaves.undo(); + if let Some(displaced_leaf) = displaced_leaf { + undo.undo_import(displaced_leaf); + } + + if let Some(finalization_displaced) = finalization_displaced_leaves { + undo.undo_finalization(finalization_displaced); + } + + return Err(e) + } + + cache.sync_cache( + &enacted, + &retracted, + operation.storage_updates, + operation.child_storage_updates, + Some(hash), + Some(number), + is_best, + ); + } + + if let Some((enacted, retracted)) = cache_update { + self.shared_cache.lock().sync(&enacted, &retracted); + } + + 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. + fn note_finalized( + &self, + transaction: &mut DBTransaction, + f_header: &Block::Header, + f_hash: Block::Hash, + displaced: &mut Option>> + ) -> ClientResult<()> { + let f_num = f_header.number().clone(); + + if self.storage.state_db.best_canonical().map(|c| f_num.saturated_into::() > c).unwrap_or(true) { + let parent_hash = f_header.parent_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) + .map_err(|e: sc_state_db::Error| sp_blockchain::Error::from(format!("State database error: {:?}", e)))?; + apply_state_commit(transaction, commit); + + let changes_trie_config = self.changes_trie_config(parent_hash)?; + if let Some(changes_trie_config) = changes_trie_config { + 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(()) + } +} + +fn apply_state_commit(transaction: &mut DBTransaction, commit: sc_state_db::CommitSet>) { + for (key, val) in commit.data.inserted.into_iter() { + transaction.put(columns::STATE, &key[..], &val); + } + for key in commit.data.deleted.into_iter() { + transaction.delete(columns::STATE, &key[..]); + } + for (key, val) in commit.meta.inserted.into_iter() { + transaction.put(columns::STATE_META, &key[..], &val); + } + for key in commit.meta.deleted.into_iter() { + transaction.delete(columns::STATE_META, &key[..]); + } +} + +impl sc_client_api::backend::AuxStore for Backend where Block: BlockT { + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> ClientResult<()> { + let mut transaction = DBTransaction::new(); + for (k, v) in insert { + transaction.put(columns::AUX, k, v); + } + for k in delete { + transaction.delete(columns::AUX, k); + } + self.storage.db.write(transaction).map_err(db_err)?; + Ok(()) + } + + fn get_aux(&self, key: &[u8]) -> ClientResult>> { + Ok(self.storage.db.get(columns::AUX, key).map(|r| r.map(|v| v.to_vec())).map_err(db_err)?) + } +} + +impl sc_client_api::backend::Backend for Backend { + type BlockImportOperation = BlockImportOperation; + type Blockchain = BlockchainDb; + type State = CachingState, Block>; + type ChangesTrieStorage = DbChangesTrieStorage; + type OffchainStorage = offchain::LocalStorage; + + fn begin_operation(&self) -> ClientResult { + let old_state = self.state_at(BlockId::Hash(Default::default()))?; + Ok(BlockImportOperation { + pending_block: None, + old_state, + db_updates: PrefixedMemoryDB::default(), + storage_updates: Default::default(), + child_storage_updates: Default::default(), + changes_trie_updates: MemoryDB::default(), + changes_trie_cache_update: None, + aux_ops: Vec::new(), + finalized_blocks: Vec::new(), + set_head: None, + commit_state: false, + }) + } + + fn begin_state_operation( + &self, + operation: &mut Self::BlockImportOperation, + block: BlockId, + ) -> ClientResult<()> { + operation.old_state = self.state_at(block)?; + operation.commit_state = true; + Ok(()) + } + + fn commit_operation(&self, operation: Self::BlockImportOperation) + -> ClientResult<()> + { + let usage = operation.old_state.usage_info(); + self.state_usage.merge_sm(usage); + + match self.try_commit_operation(operation) { + Ok(_) => { + self.storage.state_db.apply_pending(); + Ok(()) + }, + e @ Err(_) => { + self.storage.state_db.revert_pending(); + e + } + } + } + + fn finalize_block(&self, block: BlockId, justification: Option) + -> ClientResult<()> + { + 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, number, is_best, is_finalized); + Ok(()) + }; + match commit(&mut displaced) { + Ok(()) => self.storage.state_db.apply_pending(), + e @ Err(_) => { + self.storage.state_db.revert_pending(); + if let Some(displaced) = displaced { + self.blockchain.leaves.write().undo().undo_finalization(displaced); + } + return e; + } + } + Ok(()) + } + + fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage> { + Some(&self.changes_tries_storage) + } + + fn offchain_storage(&self) -> Option { + Some(self.offchain_storage.clone()) + } + + + fn usage_info(&self) -> Option { + let (io_stats, state_stats) = self.io_stats.take_or_else(|| + ( + self.storage.db.io_stats(kvdb::IoStatsKind::SincePrevious), + self.state_usage.take(), + ) + ); + let database_cache = parity_util_mem::malloc_size(&*self.storage.db); + let state_cache = (*&self.shared_cache).lock().used_storage_cache_size(); + + Some(UsageInfo { + memory: MemoryInfo { + state_cache, + database_cache, + }, + io: IoInfo { + transactions: io_stats.transactions, + bytes_read: io_stats.bytes_read, + bytes_written: io_stats.bytes_written, + writes: io_stats.writes, + reads: io_stats.reads, + average_transaction_size: io_stats.avg_transaction_size() as u64, + state_reads: state_stats.reads.ops, + state_reads_cache: state_stats.cache_reads.ops, + }, + }) + } + + fn revert(&self, n: NumberFor, revert_finalized: bool) -> ClientResult> { + let mut best_number = self.blockchain.info().best_number; + let mut best_hash = self.blockchain.info().best_hash; + + let finalized = self.blockchain.info().finalized_number; + + let revertible = best_number - finalized; + let n = if !revert_finalized && revertible < n { + revertible + } else { + n + }; + + let mut revert_blocks = || -> ClientResult> { + for c in 0 .. n.saturated_into::() { + if best_number.is_zero() { + return Ok(c.saturated_into::>()) + } + let mut transaction = DBTransaction::new(); + match self.storage.state_db.revert_one() { + Some(commit) => { + apply_state_commit(&mut transaction, commit); + let removed = self.blockchain.header(BlockId::Number(best_number))?.ok_or_else( + || sp_blockchain::Error::UnknownBlock( + format!("Error reverting to {}. Block hash not found.", best_number)))?; + + best_number -= One::one(); // prev block + best_hash = self.blockchain.hash(best_number)?.ok_or_else( + || sp_blockchain::Error::UnknownBlock( + format!("Error reverting to {}. Block hash not found.", best_number)))?; + + let update_finalized = best_number < finalized; + + let key = utils::number_and_hash_to_lookup_key(best_number.clone(), &best_hash)?; + transaction.put(columns::META, meta_keys::BEST_BLOCK, &key); + if update_finalized { + transaction.put(columns::META, meta_keys::FINALIZED_BLOCK, &key); + } + transaction.delete(columns::KEY_LOOKUP, removed.hash().as_ref()); + children::remove_children(&mut transaction, columns::META, meta_keys::CHILDREN_PREFIX, best_hash); + self.storage.db.write(transaction).map_err(db_err)?; + self.blockchain.update_meta(best_hash, best_number, true, update_finalized); + } + None => return Ok(c.saturated_into::>()) + } + } + + Ok(n) + }; + + let reverted = revert_blocks()?; + + let revert_leaves = || -> ClientResult<()> { + let mut transaction = DBTransaction::new(); + let mut leaves = self.blockchain.leaves.write(); + + leaves.revert(best_hash, best_number); + leaves.prepare_transaction(&mut transaction, columns::META, meta_keys::LEAF_PREFIX); + self.storage.db.write(transaction).map_err(db_err)?; + + Ok(()) + }; + + revert_leaves()?; + + Ok(reverted) + } + + fn blockchain(&self) -> &BlockchainDb { + &self.blockchain + } + + fn state_at(&self, block: BlockId) -> ClientResult { + use sc_client::blockchain::HeaderBackend as BcHeaderBackend; + + // special case for genesis initialization + match block { + BlockId::Hash(h) if h == Default::default() => { + let genesis_storage = DbGenesisStorage::::new(); + let root = genesis_storage.0.clone(); + let db_state = DbState::::new(Arc::new(genesis_storage), root); + let state = RefTrackingState::new(db_state, self.storage.clone(), None); + return Ok(CachingState::new(state, self.shared_cache.clone(), None)); + }, + _ => {} + } + + match self.blockchain.header(block) { + Ok(Some(ref hdr)) => { + let hash = hdr.hash(); + if !self.have_state_at(&hash, *hdr.number()) { + return Err( + sp_blockchain::Error::UnknownBlock( + format!("State already discarded for {:?}", block) + ) + ) + } + if let Ok(()) = self.storage.state_db.pin(&hash) { + let root = hdr.state_root(); + let db_state = DbState::::new(self.storage.clone(), *root); + let state = RefTrackingState::new( + db_state, + self.storage.clone(), + Some(hash.clone()), + ); + Ok(CachingState::new(state, self.shared_cache.clone(), Some(hash))) + } else { + Err( + sp_blockchain::Error::UnknownBlock( + format!("State already discarded for {:?}", block) + ) + ) + } + }, + Ok(None) => Err( + sp_blockchain::Error::UnknownBlock( + format!("Unknown state for block {:?}", block) + ) + ), + Err(e) => Err(e), + } + } + + fn have_state_at(&self, hash: &Block::Hash, number: NumberFor) -> bool { + if self.is_archive { + match self.blockchain.header(BlockId::Hash(hash.clone())) { + Ok(Some(header)) => { + sp_state_machine::Storage::get( + self.storage.as_ref(), + &header.state_root(), + (&[], None), + ).unwrap_or(None).is_some() + }, + _ => false, + } + } else { + !self.storage.state_db.is_pruned(hash, number.saturated_into::()) + } + } + + fn destroy_state(&self, state: Self::State) -> ClientResult<()> { + if let Some(hash) = state.cache.parent_hash.clone() { + let is_best = self.blockchain.meta.read().best_hash == hash; + state.release().sync_cache(&[], &[], vec![], vec![], None, None, is_best); + } + Ok(()) + } + + fn get_import_lock(&self) -> &RwLock<()> { + &self.import_lock + } +} + +impl sc_client_api::backend::LocalBackend for Backend {} + +/// TODO: remove me in #3201 +pub fn unused_sink(cache_tx: crate::cache::DbCacheTransaction) { + cache_tx.on_block_revert(&crate::cache::ComplexBlockId::new(Default::default(), 0.into())).unwrap(); + unimplemented!() +} + +#[cfg(test)] +mod tests { + use hash_db::{HashDB, EMPTY_PREFIX}; + use super::*; + use crate::columns; + use sp_core::{Blake2Hasher, H256}; + use sc_client_api::backend::{Backend as BTrait, BlockImportOperation as Op}; + use sc_client::blockchain::Backend as BLBTrait; + use sp_runtime::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; + use sp_runtime::traits::{Hash, BlakeTwo256}; + use sp_state_machine::{TrieMut, TrieDBMut, ChangesTrieRootsStorage, ChangesTrieStorage}; + use sp_blockchain::{lowest_common_ancestor, tree_route}; + + type Block = RawBlock>; + + fn prepare_changes(changes: Vec<(Vec, Vec)>) -> (H256, MemoryDB) { + let mut changes_root = H256::default(); + let mut changes_trie_update = MemoryDB::::default(); + { + let mut trie = TrieDBMut::::new( + &mut changes_trie_update, + &mut changes_root + ); + for (key, value) in changes { + trie.insert(&key, &value).unwrap(); + } + } + + (changes_root, changes_trie_update) + } + + fn insert_header( + backend: &Backend, + number: u64, + parent_hash: H256, + changes: Vec<(Vec, Vec)>, + extrinsics_root: H256, + ) -> H256 { + use sp_runtime::testing::Digest; + let (changes_root, changes_trie_update) = prepare_changes(changes); + let digest = Digest { + logs: vec![ + DigestItem::ChangesTrieRoot(changes_root), + ], + }; + let header = Header { + number, + parent_hash, + state_root: BlakeTwo256::trie_root(Vec::new()), + digest, + extrinsics_root, + }; + let header_hash = header.hash(); + + let block_id = if number == 0 { + BlockId::Hash(Default::default()) + } else { + BlockId::Number(number - 1) + }; + let mut op = backend.begin_operation().unwrap(); + backend.begin_state_operation(&mut op, block_id).unwrap(); + op.set_block_data(header, Some(Vec::new()), None, NewBlockState::Best).unwrap(); + op.update_changes_trie((changes_trie_update, ChangesTrieCacheAction::Clear)).unwrap(); + backend.commit_operation(op).unwrap(); + + header_hash + } + + #[test] + fn block_hash_inserted_correctly() { + let backing = { + let db = Backend::::new_test(1, 0); + for i in 0..10 { + assert!(db.blockchain().hash(i).unwrap().is_none()); + + { + let id = if i == 0 { + BlockId::Hash(Default::default()) + } else { + BlockId::Number(i - 1) + }; + + 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 { + Default::default() + } else { + db.blockchain.hash(i - 1).unwrap().unwrap() + }, + state_root: Default::default(), + digest: Default::default(), + extrinsics_root: Default::default(), + }; + + op.set_block_data( + header, + Some(vec![]), + None, + NewBlockState::Best, + ).unwrap(); + db.commit_operation(op).unwrap(); + } + + assert!(db.blockchain().hash(i).unwrap().is_some()) + } + db.storage.db.clone() + }; + + let backend = Backend::::new(DatabaseSettings { + state_cache_size: 16777216, + state_cache_child_ratio: Some((50, 100)), + pruning: PruningMode::keep_blocks(1), + source: DatabaseSettingsSrc::Custom(backing), + }, 0).unwrap(); + assert_eq!(backend.blockchain().info().best_number, 9); + for i in 0..10 { + assert!(backend.blockchain().hash(i).unwrap().is_some()) + } + } + + #[test] + fn set_state_data() { + let db = Backend::::new_test(2, 0); + let hash = { + 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(), + state_root: Default::default(), + digest: Default::default(), + extrinsics_root: Default::default(), + }; + + let storage = vec![ + (vec![1, 3, 5], vec![2, 4, 6]), + (vec![1, 2, 3], vec![9, 9, 9]), + ]; + + header.state_root = op.old_state.storage_root(storage + .iter() + .cloned() + .map(|(x, y)| (x, Some(y))) + ).0.into(); + let hash = header.hash(); + + op.reset_storage(Storage { + top: storage.iter().cloned().collect(), + children: Default::default(), + }).unwrap(); + op.set_block_data( + header.clone(), + Some(vec![]), + None, + NewBlockState::Best, + ).unwrap(); + + db.commit_operation(op).unwrap(); + + let state = db.state_at(BlockId::Number(0)).unwrap(); + + assert_eq!(state.storage(&[1, 3, 5]).unwrap(), Some(vec![2, 4, 6])); + assert_eq!(state.storage(&[1, 2, 3]).unwrap(), Some(vec![9, 9, 9])); + assert_eq!(state.storage(&[5, 5, 5]).unwrap(), None); + + hash + }; + + { + 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, + state_root: Default::default(), + digest: Default::default(), + extrinsics_root: Default::default(), + }; + + let storage = vec![ + (vec![1, 3, 5], None), + (vec![5, 5, 5], Some(vec![4, 5, 6])), + ]; + + let (root, overlay) = op.old_state.storage_root(storage.iter().cloned()); + op.update_db_storage(overlay).unwrap(); + header.state_root = root.into(); + + op.set_block_data( + header, + Some(vec![]), + None, + NewBlockState::Best, + ).unwrap(); + + db.commit_operation(op).unwrap(); + + let state = db.state_at(BlockId::Number(1)).unwrap(); + + assert_eq!(state.storage(&[1, 3, 5]).unwrap(), None); + assert_eq!(state.storage(&[1, 2, 3]).unwrap(), Some(vec![9, 9, 9])); + assert_eq!(state.storage(&[5, 5, 5]).unwrap(), Some(vec![4, 5, 6])); + } + } + + #[test] + fn delete_only_when_negative_rc() { + let _ = ::env_logger::try_init(); + let key; + let backend = Backend::::new_test(1, 0); + + let hash = { + 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(), + 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(); + let hash = header.hash(); + + op.reset_storage(Storage { + top: storage.iter().cloned().collect(), + children: Default::default(), + }).unwrap(); + + key = op.db_updates.insert(EMPTY_PREFIX, b"hello"); + op.set_block_data( + header, + Some(vec![]), + None, + NewBlockState::Best, + ).unwrap(); + + backend.commit_operation(op).unwrap(); + assert_eq!(backend.storage.db.get( + columns::STATE, + &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) + ).unwrap().unwrap(), &b"hello"[..]); + hash + }; + + let hash = { + 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, + 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(); + let hash = header.hash(); + + op.db_updates.insert(EMPTY_PREFIX, b"hello"); + op.db_updates.remove(&key, EMPTY_PREFIX); + op.set_block_data( + header, + Some(vec![]), + None, + NewBlockState::Best, + ).unwrap(); + + backend.commit_operation(op).unwrap(); + assert_eq!(backend.storage.db.get( + columns::STATE, + &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) + ).unwrap().unwrap(), &b"hello"[..]); + hash + }; + + 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, + 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(); + let hash = header.hash(); + + op.db_updates.remove(&key, EMPTY_PREFIX); + op.set_block_data( + header, + Some(vec![]), + None, + NewBlockState::Best, + ).unwrap(); + + backend.commit_operation(op).unwrap(); + + + assert!(backend.storage.db.get( + columns::STATE, + &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) + ).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, + &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) + ).unwrap().is_none()); + } + + backend.finalize_block(BlockId::Number(1), None).unwrap(); + backend.finalize_block(BlockId::Number(2), None).unwrap(); + backend.finalize_block(BlockId::Number(3), None).unwrap(); + assert!(backend.storage.db.get( + columns::STATE, + &sp_trie::prefixed_key::(&key, EMPTY_PREFIX) + ).unwrap().is_none()); + } + + #[test] + fn changes_trie_storage_works() { + let backend = Backend::::new_test(1000, 100); + backend.changes_tries_storage.meta.write().finalized_number = 1000; + + + let check_changes = |backend: &Backend, block: u64, changes: Vec<(Vec, Vec)>| { + let (changes_root, mut changes_trie_update) = prepare_changes(changes); + let anchor = sp_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() { + assert_eq!(backend.changes_trie_storage().unwrap().get(&key, EMPTY_PREFIX), Ok(Some(val))); + } + }; + + let changes0 = vec![(b"key_at_0".to_vec(), b"val_at_0".to_vec())]; + let changes1 = vec![ + (b"key_at_1".to_vec(), b"val_at_1".to_vec()), + (b"another_key_at_1".to_vec(), b"another_val_at_1".to_vec()), + ]; + let changes2 = vec![(b"key_at_2".to_vec(), b"val_at_2".to_vec())]; + + let block0 = insert_header(&backend, 0, Default::default(), changes0.clone(), Default::default()); + let block1 = insert_header(&backend, 1, block0, changes1.clone(), Default::default()); + let _ = insert_header(&backend, 2, block1, changes2.clone(), Default::default()); + + // check that the storage contains tries for all blocks + check_changes(&backend, 0, changes0); + check_changes(&backend, 1, changes1); + check_changes(&backend, 2, changes2); + } + + #[test] + fn changes_trie_storage_works_with_forks() { + let backend = Backend::::new_test(1000, 100); + + let changes0 = vec![(b"k0".to_vec(), b"v0".to_vec())]; + let changes1 = vec![(b"k1".to_vec(), b"v1".to_vec())]; + let changes2 = vec![(b"k2".to_vec(), b"v2".to_vec())]; + let block0 = insert_header(&backend, 0, Default::default(), changes0.clone(), Default::default()); + let block1 = insert_header(&backend, 1, block0, changes1.clone(), Default::default()); + let block2 = insert_header(&backend, 2, block1, changes2.clone(), Default::default()); + + let changes2_1_0 = vec![(b"k3".to_vec(), b"v3".to_vec())]; + let changes2_1_1 = vec![(b"k4".to_vec(), b"v4".to_vec())]; + let block2_1_0 = insert_header(&backend, 3, block2, changes2_1_0.clone(), Default::default()); + let block2_1_1 = insert_header(&backend, 4, block2_1_0, changes2_1_1.clone(), Default::default()); + + let changes2_2_0 = vec![(b"k5".to_vec(), b"v5".to_vec())]; + let changes2_2_1 = vec![(b"k6".to_vec(), b"v6".to_vec())]; + let block2_2_0 = insert_header(&backend, 3, block2, changes2_2_0.clone(), Default::default()); + let block2_2_1 = insert_header(&backend, 4, block2_2_0, changes2_2_1.clone(), Default::default()); + + // finalize block1 + backend.changes_tries_storage.meta.write().finalized_number = 1; + + // branch1: when asking for finalized block hash + let (changes1_root, _) = prepare_changes(changes1); + let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; + assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root))); + + // branch2: when asking for finalized block hash + let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 }; + assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root))); + + // branch1: when asking for non-finalized block hash (search by traversal) + let (changes2_1_0_root, _) = prepare_changes(changes2_1_0); + let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; + assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_1_0_root))); + + // branch2: when asking for non-finalized block hash (search using canonicalized hint) + let (changes2_2_0_root, _) = prepare_changes(changes2_2_0); + let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 }; + assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); + + // finalize first block of branch2 (block2_2_0) + backend.changes_tries_storage.meta.write().finalized_number = 3; + + // branch2: when asking for finalized block of this branch + assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); + + // branch1: when asking for finalized block of other branch + // => result is incorrect (returned for the block of branch1), but this is expected, + // because the other fork is abandoned (forked before finalized header) + let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; + assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); + } + + #[test] + fn changes_tries_with_digest_are_pruned_on_finalization() { + let mut backend = Backend::::new_test(1000, 100); + backend.changes_tries_storage.min_blocks_to_keep = Some(8); + let config = ChangesTrieConfiguration { + digest_interval: 2, + digest_levels: 2, + }; + + // insert some blocks + let block0 = insert_header(&backend, 0, Default::default(), vec![(b"key_at_0".to_vec(), b"val_at_0".to_vec())], Default::default()); + let block1 = insert_header(&backend, 1, block0, vec![(b"key_at_1".to_vec(), b"val_at_1".to_vec())], Default::default()); + let block2 = insert_header(&backend, 2, block1, vec![(b"key_at_2".to_vec(), b"val_at_2".to_vec())], Default::default()); + let block3 = insert_header(&backend, 3, block2, vec![(b"key_at_3".to_vec(), b"val_at_3".to_vec())], Default::default()); + let block4 = insert_header(&backend, 4, block3, vec![(b"key_at_4".to_vec(), b"val_at_4".to_vec())], Default::default()); + let block5 = insert_header(&backend, 5, block4, vec![(b"key_at_5".to_vec(), b"val_at_5".to_vec())], Default::default()); + let block6 = insert_header(&backend, 6, block5, vec![(b"key_at_6".to_vec(), b"val_at_6".to_vec())], Default::default()); + let block7 = insert_header(&backend, 7, block6, vec![(b"key_at_7".to_vec(), b"val_at_7".to_vec())], Default::default()); + let block8 = insert_header(&backend, 8, block7, vec![(b"key_at_8".to_vec(), b"val_at_8".to_vec())], Default::default()); + 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 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 = sp_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() + } + let root1 = read_changes_trie_root(&backend, 1); assert_eq!(backend.changes_tries_storage.root(&anchor, 1).unwrap(), Some(root1)); + let root2 = read_changes_trie_root(&backend, 2); assert_eq!(backend.changes_tries_storage.root(&anchor, 2).unwrap(), Some(root2)); + let root3 = read_changes_trie_root(&backend, 3); assert_eq!(backend.changes_tries_storage.root(&anchor, 3).unwrap(), Some(root3)); + let root4 = read_changes_trie_root(&backend, 4); assert_eq!(backend.changes_tries_storage.root(&anchor, 4).unwrap(), Some(root4)); + let root5 = read_changes_trie_root(&backend, 5); assert_eq!(backend.changes_tries_storage.root(&anchor, 5).unwrap(), Some(root5)); + let root6 = read_changes_trie_root(&backend, 6); assert_eq!(backend.changes_tries_storage.root(&anchor, 6).unwrap(), Some(root6)); + let root7 = read_changes_trie_root(&backend, 7); assert_eq!(backend.changes_tries_storage.root(&anchor, 7).unwrap(), Some(root7)); + let root8 = read_changes_trie_root(&backend, 8); assert_eq!(backend.changes_tries_storage.root(&anchor, 8).unwrap(), Some(root8)); + let root9 = read_changes_trie_root(&backend, 9); assert_eq!(backend.changes_tries_storage.root(&anchor, 9).unwrap(), Some(root9)); + let root10 = read_changes_trie_root(&backend, 10); assert_eq!(backend.changes_tries_storage.root(&anchor, 10).unwrap(), Some(root10)); + let root11 = read_changes_trie_root(&backend, 11); assert_eq!(backend.changes_tries_storage.root(&anchor, 11).unwrap(), Some(root11)); + let root12 = read_changes_trie_root(&backend, 12); assert_eq!(backend.changes_tries_storage.root(&anchor, 12).unwrap(), Some(root12)); + + // now simulate finalization of block#12, causing prune of tries at #1..#4 + let mut tx = DBTransaction::new(); + backend.changes_tries_storage.prune(&config, &mut tx, Default::default(), 12); + backend.storage.db.write(tx).unwrap(); + assert!(backend.changes_tries_storage.get(&root1, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root2, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root3, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root4, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root5, EMPTY_PREFIX).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root6, EMPTY_PREFIX).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root7, EMPTY_PREFIX).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root8, EMPTY_PREFIX).unwrap().is_some()); + + // now simulate finalization of block#16, causing prune of tries at #5..#8 + let mut tx = DBTransaction::new(); + backend.changes_tries_storage.prune(&config, &mut tx, Default::default(), 16); + backend.storage.db.write(tx).unwrap(); + assert!(backend.changes_tries_storage.get(&root5, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root6, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root7, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root8, EMPTY_PREFIX).unwrap().is_none()); + + // now "change" pruning mode to archive && simulate finalization of block#20 + // => no changes tries are pruned, because we never prune in archive mode + backend.changes_tries_storage.min_blocks_to_keep = None; + let mut tx = DBTransaction::new(); + backend.changes_tries_storage.prune(&config, &mut tx, Default::default(), 20); + backend.storage.db.write(tx).unwrap(); + assert!(backend.changes_tries_storage.get(&root9, EMPTY_PREFIX).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root10, EMPTY_PREFIX).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root11, EMPTY_PREFIX).unwrap().is_some()); + assert!(backend.changes_tries_storage.get(&root12, EMPTY_PREFIX).unwrap().is_some()); + } + + #[test] + fn changes_tries_without_digest_are_pruned_on_finalization() { + let mut backend = Backend::::new_test(1000, 100); + backend.changes_tries_storage.min_blocks_to_keep = Some(4); + let config = ChangesTrieConfiguration { + digest_interval: 0, + digest_levels: 0, + }; + + // insert some blocks + let block0 = insert_header(&backend, 0, Default::default(), vec![(b"key_at_0".to_vec(), b"val_at_0".to_vec())], Default::default()); + let block1 = insert_header(&backend, 1, block0, vec![(b"key_at_1".to_vec(), b"val_at_1".to_vec())], Default::default()); + let block2 = insert_header(&backend, 2, block1, vec![(b"key_at_2".to_vec(), b"val_at_2".to_vec())], Default::default()); + let block3 = insert_header(&backend, 3, block2, vec![(b"key_at_3".to_vec(), b"val_at_3".to_vec())], Default::default()); + let block4 = insert_header(&backend, 4, block3, vec![(b"key_at_4".to_vec(), b"val_at_4".to_vec())], Default::default()); + let block5 = insert_header(&backend, 5, block4, vec![(b"key_at_5".to_vec(), b"val_at_5".to_vec())], Default::default()); + let block6 = insert_header(&backend, 6, block5, vec![(b"key_at_6".to_vec(), b"val_at_6".to_vec())], Default::default()); + + // check that roots of all tries are in the columns::CHANGES_TRIE + let anchor = sp_state_machine::ChangesTrieAnchorBlockId { hash: block6, number: 6 }; + 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() + } + + let root1 = read_changes_trie_root(&backend, 1); assert_eq!(backend.changes_tries_storage.root(&anchor, 1).unwrap(), Some(root1)); + let root2 = read_changes_trie_root(&backend, 2); assert_eq!(backend.changes_tries_storage.root(&anchor, 2).unwrap(), Some(root2)); + let root3 = read_changes_trie_root(&backend, 3); assert_eq!(backend.changes_tries_storage.root(&anchor, 3).unwrap(), Some(root3)); + let root4 = read_changes_trie_root(&backend, 4); assert_eq!(backend.changes_tries_storage.root(&anchor, 4).unwrap(), Some(root4)); + let root5 = read_changes_trie_root(&backend, 5); assert_eq!(backend.changes_tries_storage.root(&anchor, 5).unwrap(), Some(root5)); + let root6 = read_changes_trie_root(&backend, 6); assert_eq!(backend.changes_tries_storage.root(&anchor, 6).unwrap(), Some(root6)); + + // now simulate finalization of block#5, causing prune of trie at #1 + let mut tx = DBTransaction::new(); + backend.changes_tries_storage.prune(&config, &mut tx, block5, 5); + backend.storage.db.write(tx).unwrap(); + assert!(backend.changes_tries_storage.get(&root1, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root2, EMPTY_PREFIX).unwrap().is_some()); + + // now simulate finalization of block#6, causing prune of tries at #2 + let mut tx = DBTransaction::new(); + backend.changes_tries_storage.prune(&config, &mut tx, block6, 6); + backend.storage.db.write(tx).unwrap(); + assert!(backend.changes_tries_storage.get(&root2, EMPTY_PREFIX).unwrap().is_none()); + assert!(backend.changes_tries_storage.get(&root3, EMPTY_PREFIX).unwrap().is_some()); + } + + #[test] + fn tree_route_works() { + let backend = Backend::::new_test(1000, 100); + let blockchain = backend.blockchain(); + let block0 = insert_header(&backend, 0, Default::default(), Vec::new(), Default::default()); + + // fork from genesis: 3 prong. + let a1 = insert_header(&backend, 1, block0, Vec::new(), Default::default()); + let a2 = insert_header(&backend, 2, a1, Vec::new(), Default::default()); + let a3 = insert_header(&backend, 3, a2, Vec::new(), Default::default()); + + // fork from genesis: 2 prong. + let b1 = insert_header(&backend, 1, block0, Vec::new(), H256::from([1; 32])); + let b2 = insert_header(&backend, 2, b1, Vec::new(), Default::default()); + + { + let tree_route = tree_route(blockchain, a3, b2).unwrap(); + + assert_eq!(tree_route.common_block().hash, block0); + assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2, a1]); + assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![b1, b2]); + } + + { + let tree_route = tree_route(blockchain, a1, a3).unwrap(); + + assert_eq!(tree_route.common_block().hash, a1); + assert!(tree_route.retracted().is_empty()); + assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![a2, a3]); + } + + { + let tree_route = tree_route(blockchain, a3, a1).unwrap(); + + assert_eq!(tree_route.common_block().hash, a1); + assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2]); + assert!(tree_route.enacted().is_empty()); + } + + { + let tree_route = tree_route(blockchain, a2, a2).unwrap(); + + assert_eq!(tree_route.common_block().hash, a2); + assert!(tree_route.retracted().is_empty()); + assert!(tree_route.enacted().is_empty()); + } + } + + #[test] + fn tree_route_child() { + let backend = Backend::::new_test(1000, 100); + let blockchain = backend.blockchain(); + + 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 = tree_route(blockchain, block0, 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 lowest_common_ancestor_works() { + let backend = Backend::::new_test(1000, 100); + let blockchain = backend.blockchain(); + let block0 = insert_header(&backend, 0, Default::default(), Vec::new(), Default::default()); + + // fork from genesis: 3 prong. + let a1 = insert_header(&backend, 1, block0, Vec::new(), Default::default()); + let a2 = insert_header(&backend, 2, a1, Vec::new(), Default::default()); + let a3 = insert_header(&backend, 3, a2, Vec::new(), Default::default()); + + // fork from genesis: 2 prong. + let b1 = insert_header(&backend, 1, block0, Vec::new(), H256::from([1; 32])); + let b2 = insert_header(&backend, 2, b1, Vec::new(), Default::default()); + + { + let lca = lowest_common_ancestor(blockchain, a3, b2).unwrap(); + + assert_eq!(lca.hash, block0); + assert_eq!(lca.number, 0); + } + + { + let lca = lowest_common_ancestor(blockchain, a1, a3).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(blockchain, a3, a1).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(blockchain, a2, a3).unwrap(); + + assert_eq!(lca.hash, a2); + assert_eq!(lca.number, 2); + } + + { + let lca = lowest_common_ancestor(blockchain, a2, a1).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(blockchain, a2, a2).unwrap(); + + assert_eq!(lca.hash, a2); + assert_eq!(lca.number, 2); + } + } + + #[test] + fn test_tree_route_regression() { + // NOTE: this is a test for a regression introduced in #3665, the result + // of tree_route would be erroneously computed, since it was taking into + // account the `ancestor` in `CachedHeaderMetadata` for the comparison. + // in this test we simulate the same behavior with the side-effect + // triggering the issue being eviction of a previously fetched record + // from the cache, therefore this test is dependent on the LRU cache + // size for header metadata, which is currently set to 5000 elements. + let backend = Backend::::new_test(10000, 10000); + let blockchain = backend.blockchain(); + + let genesis = insert_header(&backend, 0, Default::default(), Vec::new(), Default::default()); + + let block100 = (1..=100).fold(genesis, |parent, n| { + insert_header(&backend, n, parent, Vec::new(), Default::default()) + }); + + let block7000 = (101..=7000).fold(block100, |parent, n| { + insert_header(&backend, n, parent, Vec::new(), Default::default()) + }); + + // This will cause the ancestor of `block100` to be set to `genesis` as a side-effect. + lowest_common_ancestor(blockchain, genesis, block100).unwrap(); + + // While traversing the tree we will have to do 6900 calls to + // `header_metadata`, which will make sure we will exhaust our cache + // which only takes 5000 elements. In particular, the `CachedHeaderMetadata` struct for + // block #100 will be evicted and will get a new value (with ancestor set to its parent). + let tree_route = tree_route(blockchain, block100, block7000).unwrap(); + + assert!(tree_route.retracted().is_empty()); + } + + #[test] + fn test_leaves_with_complex_block_tree() { + let backend: Arc> = Arc::new(Backend::new_test(20, 20)); + substrate_test_runtime_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)); + substrate_test_runtime_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)); + substrate_test_runtime_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); + assert!(backend.get_aux(b"test").unwrap().is_none()); + backend.insert_aux(&[(&b"test"[..], &b"hello"[..])], &[]).unwrap(); + assert_eq!(b"hello", &backend.get_aux(b"test").unwrap().unwrap()[..]); + backend.insert_aux(&[], &[&b"test"[..]]).unwrap(); + assert!(backend.get_aux(b"test").unwrap().is_none()); + } + + #[test] + fn test_finalize_block_with_justification() { + use sc_client::blockchain::{Backend as BlockChainBackend}; + + let backend = Backend::::new_test(10, 10); + + 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(1), justification.clone()).unwrap(); + + assert_eq!( + 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/client/db/src/light.rs b/client/db/src/light.rs new file mode 100644 index 0000000000000..8277f20b8d8ea --- /dev/null +++ b/client/db/src/light.rs @@ -0,0 +1,1184 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! RocksDB-based light client blockchain storage. + +use std::{sync::Arc, collections::HashMap}; +use std::convert::TryInto; +use parking_lot::RwLock; + +use kvdb::{KeyValueDB, DBTransaction}; + +use sc_client_api::{backend::{AuxStore, NewBlockState}, UsageInfo}; +use sc_client::blockchain::{ + BlockStatus, Cache as BlockchainCache,Info as BlockchainInfo, +}; +use sc_client::cht; +use sp_blockchain::{ + CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache, + Error as ClientError, Result as ClientResult, + HeaderBackend as BlockchainHeaderBackend, + well_known_cache_keys, +}; +use sc_client::light::blockchain::Storage as LightBlockchainStorage; +use codec::{Decode, Encode}; +use sp_runtime::generic::{DigestItem, BlockId}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor, HasherFor}; +use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType}; +use crate::utils::{self, meta_keys, Meta, db_err, read_db, block_id_to_lookup_key, read_meta}; +use crate::{DatabaseSettings, FrozenForDuration}; +use log::{trace, warn, debug}; + +pub(crate) mod columns { + pub const META: u32 = crate::utils::COLUMN_META; + pub const KEY_LOOKUP: u32 = 1; + pub const HEADER: u32 = 2; + pub const CACHE: u32 = 3; + pub const CHT: u32 = 4; + pub const AUX: u32 = 5; +} + +/// Prefix for headers CHT. +const HEADER_CHT_PREFIX: u8 = 0; +/// Prefix for changes tries roots CHT. +const CHANGES_TRIE_CHT_PREFIX: u8 = 1; + +/// Light blockchain storage. Stores most recent headers + CHTs for older headers. +/// Locks order: meta, cache. +pub struct LightStorage { + db: Arc, + meta: RwLock, Block::Hash>>, + cache: Arc>, + header_metadata_cache: HeaderMetadataCache, + + #[cfg(not(target_os = "unknown"))] + io_stats: FrozenForDuration, +} + +impl LightStorage + where + Block: BlockT, +{ + /// Create new storage with given settings. + pub fn new(config: DatabaseSettings) -> ClientResult { + let db = crate::utils::open_database(&config, columns::META, "light")?; + Self::from_kvdb(db as Arc<_>) + } + + /// Create new memory-backed `LightStorage` for tests. + #[cfg(any(test, feature = "test-helpers"))] + pub fn new_test() -> Self { + use utils::NUM_COLUMNS; + + let db = Arc::new(::kvdb_memorydb::create(NUM_COLUMNS)); + + Self::from_kvdb(db as Arc<_>).expect("failed to create test-db") + } + + fn from_kvdb(db: Arc) -> ClientResult { + let meta = read_meta::(&*db, columns::META, columns::HEADER)?; + let cache = DbCache::new( + db.clone(), + columns::KEY_LOOKUP, + columns::HEADER, + columns::CACHE, + meta.genesis_hash, + ComplexBlockId::new(meta.finalized_hash, meta.finalized_number), + ); + + Ok(LightStorage { + db, + meta: RwLock::new(meta), + cache: Arc::new(DbCacheSync(RwLock::new(cache))), + header_metadata_cache: HeaderMetadataCache::default(), + #[cfg(not(target_os = "unknown"))] + io_stats: FrozenForDuration::new(std::time::Duration::from_secs(1), kvdb::IoStats::empty()), + }) + } + + #[cfg(test)] + pub(crate) fn cache(&self) -> &DbCacheSync { + &self.cache + } + + fn update_meta( + &self, + hash: Block::Hash, + number: NumberFor, + is_best: bool, + is_finalized: bool, + ) { + let mut meta = self.meta.write(); + + if number.is_zero() { + meta.genesis_hash = hash; + meta.finalized_hash = hash; + } + + if is_best { + meta.best_number = number; + meta.best_hash = hash; + } + + if is_finalized { + meta.finalized_number = number; + meta.finalized_hash = hash; + } + } +} + +impl BlockchainHeaderBackend for LightStorage + where + Block: BlockT, +{ + fn header(&self, id: BlockId) -> ClientResult> { + utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) + } + + fn info(&self) -> BlockchainInfo { + let meta = self.meta.read(); + BlockchainInfo { + best_hash: meta.best_hash, + best_number: meta.best_number, + genesis_hash: meta.genesis_hash, + finalized_hash: meta.finalized_hash, + finalized_number: meta.finalized_number, + } + } + + fn status(&self, id: BlockId) -> ClientResult { + let exists = match id { + BlockId::Hash(_) => read_db( + &*self.db, + columns::KEY_LOOKUP, + columns::HEADER, + id + )?.is_some(), + BlockId::Number(n) => n <= self.meta.read().best_number, + }; + match exists { + true => Ok(BlockStatus::InChain), + false => Ok(BlockStatus::Unknown), + } + } + + 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)?; + Ok(Some(number)) + } else { + Ok(None) + } + } + + fn hash(&self, number: NumberFor) -> ClientResult> { + Ok(self.header(BlockId::Number(number))?.map(|header| header.hash().clone())) + } +} + +impl HeaderMetadata for LightStorage { + type Error = ClientError; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.header_metadata_cache.header_metadata(hash).or_else(|_| { + self.header(BlockId::hash(hash))?.map(|header| { + let header_metadata = CachedHeaderMetadata::from(&header); + self.header_metadata_cache.insert_header_metadata( + header_metadata.hash, + header_metadata.clone(), + ); + header_metadata + }).ok_or(ClientError::UnknownBlock(format!("header not found in db: {}", hash))) + }) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.header_metadata_cache.insert_header_metadata(hash, metadata) + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.header_metadata_cache.remove_header_metadata(hash); + } +} + +impl LightStorage { + // Get block changes trie root, if available. + fn changes_trie_root(&self, block: BlockId) -> ClientResult> { + self.header(block) + .map(|header| header.and_then(|header| + header.digest().log(DigestItem::as_changes_trie_root) + .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), + ) -> ClientResult<()> { + let lookup_key = utils::number_and_hash_to_lookup_key(best_to.0, &best_to.1)?; + + // handle reorg. + let meta = self.meta.read(); + if meta.best_hash != Default::default() { + let tree_route = sp_blockchain::tree_route(self, meta.best_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, + ) -> ClientResult<()> { + let meta = self.meta.read(); + if &meta.finalized_hash != header.parent_hash() { + return Err(::sp_blockchain::Error::NonSequentialFinalization( + format!("Last finalized {:?} not parent of {:?}", + meta.finalized_hash, hash), + ).into()) + } + + 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 + if let Some(new_cht_number) = cht::is_build_required(cht::size(), *header.number()) { + let new_cht_start: NumberFor = cht::start_number(cht::size(), new_cht_number); + + let mut current_num = new_cht_start; + let cht_range = ::std::iter::from_fn(|| { + let old_current_num = current_num; + current_num = current_num + One::one(); + Some(old_current_num) + }); + + let new_header_cht_root = cht::compute_root::, _>( + cht::size(), new_cht_number, cht_range.map(|num| self.hash(num)) + )?; + transaction.put( + columns::CHT, + &cht_key(HEADER_CHT_PREFIX, new_cht_start)?, + new_header_cht_root.as_ref() + ); + + // if the header includes changes trie root, let's build a changes tries roots CHT + if header.digest().log(DigestItem::as_changes_trie_root).is_some() { + let mut current_num = new_cht_start; + let cht_range = ::std::iter::from_fn(|| { + let old_current_num = current_num; + current_num = current_num + One::one(); + Some(old_current_num) + }); + let new_changes_trie_cht_root = cht::compute_root::, _>( + cht::size(), new_cht_number, cht_range + .map(|num| self.changes_trie_root(BlockId::Number(num))) + )?; + transaction.put( + columns::CHT, + &cht_key(CHANGES_TRIE_CHT_PREFIX, new_cht_start)?, + new_changes_trie_cht_root.as_ref() + ); + } + + // prune headers that are replaced with CHT + let mut prune_block = new_cht_start; + let new_cht_end = cht::end_number(cht::size(), new_cht_number); + trace!(target: "db", "Replacing blocks [{}..{}] with CHT#{}", + new_cht_start, new_cht_end, new_cht_number); + + while prune_block <= new_cht_end { + 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( + transaction, + columns::KEY_LOOKUP, + prune_block, + hash + )?; + transaction.delete(columns::HEADER, &lookup_key); + } + prune_block += One::one(); + } + } + + Ok(()) + } + + /// Read CHT root of given type for the block. + fn read_cht_root( + &self, + cht_type: u8, + cht_size: NumberFor, + block: NumberFor + ) -> ClientResult> { + let no_cht_for_block = || ClientError::Backend(format!("Missing CHT for block {}", block)); + + let meta = self.meta.read(); + let max_cht_number = cht::max_cht_number(cht_size, meta.finalized_number); + let cht_number = cht::block_to_cht_number(cht_size, block).ok_or_else(no_cht_for_block)?; + match max_cht_number { + Some(max_cht_number) if cht_number <= max_cht_number => (), + _ => return Ok(None), + } + + let cht_start = cht::start_number(cht_size, cht_number); + self.db.get(columns::CHT, &cht_key(cht_type, cht_start)?).map_err(db_err)? + .ok_or_else(no_cht_for_block) + .and_then(|hash| Block::Hash::decode(&mut &*hash).map_err(|_| no_cht_for_block())) + .map(Some) + } +} + +impl AuxStore for LightStorage + where Block: BlockT, +{ + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> ClientResult<()> { + let mut transaction = DBTransaction::new(); + for (k, v) in insert { + transaction.put(columns::AUX, k, v); + } + for k in delete { + transaction.delete(columns::AUX, k); + } + self.db.write(transaction).map_err(db_err) + } + + fn get_aux(&self, key: &[u8]) -> ClientResult>> { + self.db.get(columns::AUX, key).map(|r| r.map(|v| v.to_vec())).map_err(db_err) + } +} + +impl LightBlockchainStorage for LightStorage + where Block: BlockT, +{ + fn import_header( + &self, + header: Block::Header, + cache_at: HashMap>, + leaf_state: NewBlockState, + aux_ops: Vec<(Vec, Option>)>, + ) -> ClientResult<()> { + let mut transaction = DBTransaction::new(); + + let hash = header.hash(); + let number = *header.number(); + let parent_hash = *header.parent_hash(); + + for (key, maybe_val) in aux_ops { + match maybe_val { + Some(val) => transaction.put_vec(columns::AUX, &key, val), + None => transaction.delete(columns::AUX, &key), + } + } + + // blocks are keyed by number + hash. + let lookup_key = utils::number_and_hash_to_lookup_key(number, &hash)?; + + if leaf_state.is_best() { + self.set_head_with_transaction(&mut transaction, parent_hash, (number, hash))?; + } + + utils::insert_hash_to_key_mapping( + &mut transaction, + columns::KEY_LOOKUP, + number, + hash, + )?; + transaction.put(columns::HEADER, &lookup_key, &header.encode()); + + let header_metadata = CachedHeaderMetadata::from(&header); + self.header_metadata_cache.insert_header_metadata( + header.hash().clone(), + header_metadata, + ); + + let is_genesis = number.is_zero(); + if is_genesis { + self.cache.0.write().set_genesis_hash(hash); + 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, + )?; + } + + { + let mut cache = self.cache.0.write(); + let cache_ops = cache.transaction(&mut transaction) + .on_block_insert( + ComplexBlockId::new(*header.parent_hash(), if number.is_zero() { Zero::zero() } else { number - One::one() }), + ComplexBlockId::new(hash, number), + cache_at, + if finalized { CacheEntryType::Final } else { CacheEntryType::NonFinal }, + )? + .into_ops(); + + debug!("Light DB Commit {:?} ({})", hash, number); + self.db.write(transaction).map_err(db_err)?; + cache.commit(cache_ops); + } + + self.update_meta(hash, number, leaf_state.is_best(), finalized); + + 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)?; + self.update_meta(hash, header.number().clone(), true, false); + Ok(()) + } else { + Err(ClientError::UnknownBlock(format!("Cannot set head {:?}", id))) + } + } + + fn header_cht_root( + &self, + cht_size: NumberFor, + block: NumberFor, + ) -> ClientResult> { + self.read_cht_root(HEADER_CHT_PREFIX, cht_size, block) + } + + fn changes_trie_cht_root( + &self, + cht_size: NumberFor, + block: NumberFor, + ) -> ClientResult> { + self.read_cht_root(CHANGES_TRIE_CHT_PREFIX, cht_size, block) + } + + fn finalize_header(&self, id: BlockId) -> ClientResult<()> { + if let Some(header) = self.header(id)? { + let mut transaction = DBTransaction::new(); + let hash = header.hash(); + let number = *header.number(); + self.note_finalized(&mut transaction, &header, hash.clone())?; + { + let mut cache = self.cache.0.write(); + let cache_ops = cache.transaction(&mut transaction) + .on_block_finalize( + ComplexBlockId::new(*header.parent_hash(), if number.is_zero() { Zero::zero() } else { number - One::one() }), + ComplexBlockId::new(hash, number) + )? + .into_ops(); + + self.db.write(transaction).map_err(db_err)?; + cache.commit(cache_ops); + } + self.update_meta(hash, header.number().clone(), false, true); + + Ok(()) + } else { + Err(ClientError::UnknownBlock(format!("Cannot finalize block {:?}", id))) + } + } + + fn last_finalized(&self) -> ClientResult { + Ok(self.meta.read().finalized_hash.clone()) + } + + fn cache(&self) -> Option>> { + Some(self.cache.clone()) + } + + #[cfg(not(target_os = "unknown"))] + fn usage_info(&self) -> Option { + use sc_client_api::{MemoryInfo, IoInfo}; + + let database_cache = parity_util_mem::malloc_size(&*self.db); + let io_stats = self.io_stats.take_or_else(|| self.db.io_stats(kvdb::IoStatsKind::SincePrevious)); + + Some(UsageInfo { + memory: MemoryInfo { + database_cache, + state_cache: 0, + }, + io: IoInfo { + transactions: io_stats.transactions, + bytes_read: io_stats.bytes_read, + bytes_written: io_stats.bytes_written, + writes: io_stats.writes, + reads: io_stats.reads, + average_transaction_size: io_stats.avg_transaction_size() as u64, + // Light client does not track those + state_reads: 0, + state_reads_cache: 0, + } + }) + } + + #[cfg(target_os = "unknown")] + fn usage_info(&self) -> Option { + None + } +} + +/// Build the key for inserting header-CHT at given block. +fn cht_key>(cht_type: u8, block: N) -> ClientResult<[u8; 5]> { + let mut key = [cht_type; 5]; + key[1..].copy_from_slice(&utils::number_index_key(block)?); + Ok(key) +} + +#[cfg(test)] +pub(crate) mod tests { + use sc_client::cht; + use sp_runtime::generic::DigestItem; + use sp_runtime::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper}; + use sp_blockchain::{lowest_common_ancestor, tree_route}; + use super::*; + + type Block = RawBlock>; + type AuthorityId = sp_core::ed25519::Public; + + pub fn default_header(parent: &Hash, number: u64) -> Header { + Header { + number: number.into(), + parent_hash: *parent, + state_root: Hash::random(), + digest: Default::default(), + extrinsics_root: Default::default(), + } + } + + fn header_with_changes_trie(parent: &Hash, number: u64) -> Header { + let mut header = default_header(parent, number); + header.digest.logs.push(DigestItem::ChangesTrieRoot([(number % 256) as u8; 32].into())); + header + } + + fn header_with_extrinsics_root(parent: &Hash, number: u64, extrinsics_root: Hash) -> Header { + let mut header = default_header(parent, number); + header.extrinsics_root = extrinsics_root; + header + } + + pub fn insert_block Header>( + db: &LightStorage, + cache: HashMap>, + mut header: F, + ) -> Hash { + let header = header(); + let hash = header.hash(); + db.import_header(header, cache, NewBlockState::Best, Vec::new()).unwrap(); + hash + } + + fn insert_final_block Header>( + db: &LightStorage, + cache: HashMap>, + header: F, + ) -> Hash { + let header = header(); + let hash = header.hash(); + db.import_header(header, cache, NewBlockState::Final, Vec::new()).unwrap(); + hash + } + + fn insert_non_best_block Header>( + db: &LightStorage, + cache: HashMap>, + header: F, + ) -> Hash { + let header = header(); + let hash = header.hash(); + db.import_header(header, cache, NewBlockState::Normal, Vec::new()).unwrap(); + hash + } + + #[test] + fn returns_known_header() { + let db = LightStorage::new_test(); + let known_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); + let header_by_hash = db.header(BlockId::Hash(known_hash)).unwrap().unwrap(); + let header_by_number = db.header(BlockId::Number(0)).unwrap().unwrap(); + assert_eq!(header_by_hash, header_by_number); + } + + #[test] + fn does_not_return_unknown_header() { + let db = LightStorage::::new_test(); + assert!(db.header(BlockId::Hash(Hash::from_low_u64_be(1))).unwrap().is_none()); + assert!(db.header(BlockId::Number(0)).unwrap().is_none()); + } + + #[test] + fn returns_info() { + let db = LightStorage::new_test(); + let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); + let info = db.info(); + assert_eq!(info.best_hash, genesis_hash); + assert_eq!(info.best_number, 0); + assert_eq!(info.genesis_hash, genesis_hash); + let best_hash = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); + let info = db.info(); + assert_eq!(info.best_hash, best_hash); + assert_eq!(info.best_number, 1); + assert_eq!(info.genesis_hash, genesis_hash); + } + + #[test] + fn returns_block_status() { + let db = LightStorage::new_test(); + let genesis_hash = insert_block(&db, HashMap::new(), || 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(Hash::from_low_u64_be(1))).unwrap(), BlockStatus::Unknown); + assert_eq!(db.status(BlockId::Number(1)).unwrap(), BlockStatus::Unknown); + } + + #[test] + fn returns_block_hash() { + let db = LightStorage::new_test(); + let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); + assert_eq!(db.hash(0).unwrap(), Some(genesis_hash)); + assert_eq!(db.hash(1).unwrap(), None); + } + + #[test] + fn import_header_works() { + let db = LightStorage::new_test(); + + let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); + assert_eq!(db.db.iter(columns::HEADER).count(), 1); + assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), 2); + + let _ = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); + assert_eq!(db.db.iter(columns::HEADER).count(), 2); + assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), 4); + } + + #[test] + fn finalized_ancient_headers_are_replaced_with_cht() { + fn insert_headers Header>(header_producer: F) -> LightStorage { + let db = LightStorage::new_test(); + let cht_size: u64 = cht::size(); + let ucht_size: usize = cht_size as _; + + // insert genesis block header (never pruned) + let mut prev_hash = insert_final_block(&db, HashMap::new(), || header_producer(&Default::default(), 0)); + + // insert SIZE blocks && ensure that nothing is pruned + + for number in 0..cht::size() { + prev_hash = insert_block(&db, HashMap::new(), || header_producer(&prev_hash, 1 + number)); + } + assert_eq!(db.db.iter(columns::HEADER).count(), 1 + ucht_size); + assert_eq!(db.db.iter(columns::CHT).count(), 0); + + // insert next SIZE blocks && ensure that nothing is pruned + for number in 0..(cht_size as _) { + prev_hash = insert_block( + &db, + HashMap::new(), + || header_producer(&prev_hash, 1 + cht_size + number), + ); + } + assert_eq!(db.db.iter(columns::HEADER).count(), 1 + ucht_size + ucht_size); + assert_eq!(db.db.iter(columns::CHT).count(), 0); + + // insert block #{2 * cht::size() + 1} && check that new CHT is created + headers of this CHT are pruned + // nothing is yet finalized, so nothing is pruned. + prev_hash = insert_block( + &db, + HashMap::new(), + || header_producer(&prev_hash, 1 + cht_size + cht_size), + ); + assert_eq!(db.db.iter(columns::HEADER).count(), 2 + ucht_size + ucht_size); + assert_eq!(db.db.iter(columns::CHT).count(), 0); + + // now finalize the block. + for i in (0..(ucht_size + ucht_size)).map(|i| i + 1) { + db.finalize_header(BlockId::Number(i as _)).unwrap(); + } + db.finalize_header(BlockId::Hash(prev_hash)).unwrap(); + db + } + + // when headers are created without changes tries roots + let db = insert_headers(default_header); + let cht_size: u64 = cht::size(); + assert_eq!(db.db.iter(columns::HEADER).count(), (1 + cht_size + 1) as usize); + assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), (2 * (1 + cht_size + 1)) as usize); + assert_eq!(db.db.iter(columns::CHT).count(), 1); + assert!((0..cht_size as _).all(|i| db.header(BlockId::Number(1 + i)).unwrap().is_none())); + assert!(db.header_cht_root(cht_size, cht_size / 2).unwrap().is_some()); + assert!(db.header_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); + assert!(db.changes_trie_cht_root(cht_size, cht_size / 2).is_err()); + assert!(db.changes_trie_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); + + // when headers are created with changes tries roots + let db = insert_headers(header_with_changes_trie); + assert_eq!(db.db.iter(columns::HEADER).count(), (1 + cht_size + 1) as usize); + assert_eq!(db.db.iter(columns::CHT).count(), 2); + assert!((0..cht_size as _).all(|i| db.header(BlockId::Number(1 + i)).unwrap().is_none())); + assert!(db.header_cht_root(cht_size, cht_size / 2).unwrap().is_some()); + assert!(db.header_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); + assert!(db.changes_trie_cht_root(cht_size, cht_size / 2).unwrap().is_some()); + assert!(db.changes_trie_cht_root(cht_size, cht_size + cht_size / 2).unwrap().is_none()); + } + + #[test] + fn get_cht_fails_for_genesis_block() { + assert!(LightStorage::::new_test().header_cht_root(cht::size(), 0).is_err()); + } + + #[test] + fn get_cht_fails_for_non_existant_cht() { + let cht_size: u64 = cht::size(); + assert!(LightStorage::::new_test().header_cht_root(cht_size, cht_size / 2).unwrap().is_none()); + } + + #[test] + fn get_cht_works() { + let db = LightStorage::new_test(); + + // insert 1 + SIZE + SIZE + 1 blocks so that CHT#0 is created + let mut prev_hash = insert_final_block(&db, HashMap::new(), || header_with_changes_trie(&Default::default(), 0)); + let cht_size: u64 = cht::size(); + let ucht_size: usize = cht_size as _; + for i in 1..1 + ucht_size + ucht_size + 1 { + prev_hash = insert_block(&db, HashMap::new(), || header_with_changes_trie(&prev_hash, i as u64)); + db.finalize_header(BlockId::Hash(prev_hash)).unwrap(); + } + + let cht_root_1 = db.header_cht_root(cht_size, cht::start_number(cht_size, 0)).unwrap().unwrap(); + let cht_root_2 = db.header_cht_root(cht_size, cht::start_number(cht_size, 0) + cht_size / 2).unwrap().unwrap(); + let cht_root_3 = db.header_cht_root(cht_size, cht::end_number(cht_size, 0)).unwrap().unwrap(); + assert_eq!(cht_root_1, cht_root_2); + assert_eq!(cht_root_2, cht_root_3); + + let cht_root_1 = db.changes_trie_cht_root(cht_size, cht::start_number(cht_size, 0)).unwrap().unwrap(); + let cht_root_2 = db.changes_trie_cht_root( + cht_size, + cht::start_number(cht_size, 0) + cht_size / 2, + ).unwrap().unwrap(); + let cht_root_3 = db.changes_trie_cht_root(cht_size, cht::end_number(cht_size, 0)).unwrap().unwrap(); + assert_eq!(cht_root_1, cht_root_2); + assert_eq!(cht_root_2, cht_root_3); + } + + #[test] + fn tree_route_works() { + let db = LightStorage::new_test(); + let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); + + // fork from genesis: 3 prong. + let a1 = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); + let a2 = insert_block(&db, HashMap::new(), || default_header(&a1, 2)); + let a3 = insert_block(&db, HashMap::new(), || default_header(&a2, 3)); + + // fork from genesis: 2 prong. + let b1 = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block0, 1, Hash::from([1; 32]))); + let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); + + { + let tree_route = tree_route(&db, a3, b2).unwrap(); + + assert_eq!(tree_route.common_block().hash, block0); + assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2, a1]); + assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![b1, b2]); + } + + { + let tree_route = tree_route(&db, a1, a3).unwrap(); + + assert_eq!(tree_route.common_block().hash, a1); + assert!(tree_route.retracted().is_empty()); + assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![a2, a3]); + } + + { + let tree_route = tree_route(&db, a3, a1).unwrap(); + + assert_eq!(tree_route.common_block().hash, a1); + assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2]); + assert!(tree_route.enacted().is_empty()); + } + + { + let tree_route = tree_route(&db, a2, a2).unwrap(); + + assert_eq!(tree_route.common_block().hash, a2); + assert!(tree_route.retracted().is_empty()); + assert!(tree_route.enacted().is_empty()); + } + } + + #[test] + fn lowest_common_ancestor_works() { + let db = LightStorage::new_test(); + let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); + + // fork from genesis: 3 prong. + let a1 = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); + let a2 = insert_block(&db, HashMap::new(), || default_header(&a1, 2)); + let a3 = insert_block(&db, HashMap::new(), || default_header(&a2, 3)); + + // fork from genesis: 2 prong. + let b1 = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block0, 1, Hash::from([1; 32]))); + let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); + + { + let lca = lowest_common_ancestor(&db, a3, b2).unwrap(); + + assert_eq!(lca.hash, block0); + assert_eq!(lca.number, 0); + } + + { + let lca = lowest_common_ancestor(&db, a1, a3).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(&db, a3, a1).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(&db, a2, a3).unwrap(); + + assert_eq!(lca.hash, a2); + assert_eq!(lca.number, 2); + } + + { + let lca = lowest_common_ancestor(&db, a2, a1).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(&db, a2, a2).unwrap(); + + assert_eq!(lca.hash, a2); + assert_eq!(lca.number, 2); + } + } + + #[test] + fn authorities_are_cached() { + let db = LightStorage::new_test(); + + fn run_checks(db: &LightStorage, max: u64, checks: &[(u64, Option>)]) { + for (at, expected) in checks.iter().take_while(|(at, _)| *at <= max) { + let actual = get_authorities(db.cache(), BlockId::Number(*at)); + assert_eq!(*expected, actual); + } + } + + fn same_authorities() -> HashMap> { + HashMap::new() + } + + fn make_authorities(authorities: Vec) -> HashMap> { + let mut map = HashMap::new(); + map.insert(well_known_cache_keys::AUTHORITIES, authorities.encode()); + map + } + + fn get_authorities(cache: &dyn BlockchainCache, at: BlockId) -> Option> { + cache.get_at(&well_known_cache_keys::AUTHORITIES, &at) + .and_then(|(_, _, val)| Decode::decode(&mut &val[..]).ok()) + } + + let auth1 = || AuthorityId::from_raw([1u8; 32]); + let auth2 = || AuthorityId::from_raw([2u8; 32]); + let auth3 = || AuthorityId::from_raw([3u8; 32]); + let auth4 = || AuthorityId::from_raw([4u8; 32]); + let auth5 = || AuthorityId::from_raw([5u8; 32]); + let auth6 = || AuthorityId::from_raw([6u8; 32]); + + let (hash2, hash6) = { + // first few blocks are instantly finalized + // B0(None) -> B1(None) -> B2(1) -> B3(1) -> B4(1, 2) -> B5(1, 2) -> B6(1, 2) + let checks = vec![ + (0, None), + (1, None), + (2, Some(vec![auth1()])), + (3, Some(vec![auth1()])), + (4, Some(vec![auth1(), auth2()])), + (5, Some(vec![auth1(), auth2()])), + (6, Some(vec![auth1(), auth2()])), + ]; + + let hash0 = insert_final_block(&db, same_authorities(), || default_header(&Default::default(), 0)); + run_checks(&db, 0, &checks); + let hash1 = insert_final_block(&db, same_authorities(), || default_header(&hash0, 1)); + run_checks(&db, 1, &checks); + let hash2 = insert_final_block(&db, make_authorities(vec![auth1()]), || default_header(&hash1, 2)); + run_checks(&db, 2, &checks); + let hash3 = insert_final_block(&db, make_authorities(vec![auth1()]), || default_header(&hash2, 3)); + run_checks(&db, 3, &checks); + let hash4 = insert_final_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash3, 4)); + run_checks(&db, 4, &checks); + let hash5 = insert_final_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash4, 5)); + run_checks(&db, 5, &checks); + let hash6 = insert_final_block(&db, same_authorities(), || default_header(&hash5, 6)); + run_checks(&db, 6, &checks); + + (hash2, hash6) + }; + + { + // 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, make_authorities(vec![auth1()]), || default_header(&hash2, 3)); + assert_eq!(None, get_authorities(db.cache(), BlockId::Hash(hash2_1))); + let hash2_2 = insert_non_best_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash2_1, 4)); + assert_eq!(None, get_authorities(db.cache(), BlockId::Hash(hash2_2))); + } + + let (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) = { + // inserting non-finalized blocks + // B6(None) -> B7(3) -> B8(3) + // \> B6_1(4) -> B6_2(4) + // \> B6_1_1(5) + // \> B6_1_2(6) -> B6_1_3(7) + + let hash7 = insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash6, 7)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + let hash8 = insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash7, 8)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + let hash6_1 = insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6, 7)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + let hash6_1_1 = insert_non_best_block(&db, make_authorities(vec![auth5()]), || default_header(&hash6_1, 8)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + let hash6_1_2 = insert_non_best_block(&db, make_authorities(vec![auth6()]), || default_header(&hash6_1, 8)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + let hash6_2 = insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6_1, 8)); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); + + (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) + }; + + { + // finalize block hash6_1 + db.finalize_header(BlockId::Hash(hash6_1)).unwrap(); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); + // finalize block hash6_2 + db.finalize_header(BlockId::Hash(hash6_2)).unwrap(); + assert_eq!( + get_authorities(db.cache(), BlockId::Hash(hash6)), + Some(vec![auth1(), auth2()]), + ); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), None); + assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); + } + } + + #[test] + fn database_is_reopened() { + let db = LightStorage::new_test(); + let hash0 = insert_final_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); + assert_eq!(db.info().best_hash, hash0); + assert_eq!(db.header(BlockId::Hash(hash0)).unwrap().unwrap().hash(), hash0); + + let db = db.db; + let db = LightStorage::from_kvdb(db).unwrap(); + assert_eq!(db.info().best_hash, hash0); + assert_eq!(db.header(BlockId::Hash::(hash0)).unwrap().unwrap().hash(), hash0); + } + + #[test] + fn aux_store_works() { + let db = LightStorage::::new_test(); + + // insert aux1 + aux2 using direct store access + db.insert_aux(&[(&[1][..], &[101][..]), (&[2][..], &[102][..])], ::std::iter::empty()).unwrap(); + + // check aux values + assert_eq!(db.get_aux(&[1]).unwrap(), Some(vec![101])); + assert_eq!(db.get_aux(&[2]).unwrap(), Some(vec![102])); + assert_eq!(db.get_aux(&[3]).unwrap(), None); + + // delete aux1 + insert aux3 using import operation + db.import_header(default_header(&Default::default(), 0), HashMap::new(), NewBlockState::Best, vec![ + (vec![3], Some(vec![103])), + (vec![1], None), + ]).unwrap(); + + // check aux values + assert_eq!(db.get_aux(&[1]).unwrap(), None); + assert_eq!(db.get_aux(&[2]).unwrap(), Some(vec![102])); + assert_eq!(db.get_aux(&[3]).unwrap(), Some(vec![103])); + } + + #[test] + fn cache_can_be_initialized_after_genesis_inserted() { + let (genesis_hash, storage) = { + let db = LightStorage::::new_test(); + + // before cache is initialized => None + assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), None); + + // insert genesis block (no value for cache is provided) + let mut genesis_hash = None; + insert_block(&db, HashMap::new(), || { + let header = default_header(&Default::default(), 0); + genesis_hash = Some(header.hash()); + header + }); + + // after genesis is inserted => None + assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), None); + + // initialize cache + db.cache().initialize(b"test", vec![42]).unwrap(); + + // after genesis is inserted + cache is initialized => Some + assert_eq!( + db.cache().get_at(b"test", &BlockId::Number(0)), + Some(((0, genesis_hash.unwrap()), None, vec![42])), + ); + + (genesis_hash, db.db) + }; + + // restart && check that after restart value is read from the cache + let db = LightStorage::::from_kvdb(storage as Arc<_>).expect("failed to create test-db"); + assert_eq!( + db.cache().get_at(b"test", &BlockId::Number(0)), + Some(((0, genesis_hash.unwrap()), None, vec![42])), + ); + } +} diff --git a/client/db/src/offchain.rs b/client/db/src/offchain.rs new file mode 100644 index 0000000000000..3d0f8c6795a94 --- /dev/null +++ b/client/db/src/offchain.rs @@ -0,0 +1,148 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! RocksDB-based offchain workers local storage. + +use std::{ + collections::HashMap, + sync::Arc, +}; + +use crate::columns; +use kvdb::KeyValueDB; +use parking_lot::Mutex; + +/// Offchain local storage +#[derive(Clone)] +pub struct LocalStorage { + db: Arc, + locks: Arc, Arc>>>>, +} + +impl std::fmt::Debug for LocalStorage { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.debug_struct("LocalStorage") + .finish() + } +} + +impl LocalStorage { + /// Create new offchain storage for tests (backed by memorydb) + #[cfg(any(test, feature = "test-helpers"))] + pub fn new_test() -> Self { + let db = Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)); + Self::new(db as _) + } + + /// Create offchain local storage with given `KeyValueDB` backend. + pub fn new(db: Arc) -> Self { + Self { + db, + locks: Default::default(), + } + } +} + +impl sp_core::offchain::OffchainStorage for LocalStorage { + fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { + let key: Vec = prefix.iter().chain(key).cloned().collect(); + let mut tx = self.db.transaction(); + tx.put(columns::OFFCHAIN, &key, value); + + if let Err(e) = self.db.write(tx) { + log::warn!("Error writing to the offchain DB: {:?}", e); + } + } + + fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { + let key: Vec = prefix.iter().chain(key).cloned().collect(); + self.db.get(columns::OFFCHAIN, &key) + .ok() + .and_then(|x| x) + .map(|v| v.to_vec()) + } + + fn compare_and_set( + &mut self, + prefix: &[u8], + item_key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool { + let key: Vec = prefix.iter().chain(item_key).cloned().collect(); + let key_lock = { + let mut locks = self.locks.lock(); + locks.entry(key.clone()).or_default().clone() + }; + + let is_set; + { + let _key_guard = key_lock.lock(); + let val = self.db.get(columns::OFFCHAIN, &key) + .ok() + .and_then(|x| x); + is_set = val.as_ref().map(|x| &**x) == old_value; + + if is_set { + self.set(prefix, item_key, new_value) + } + } + + // clean the lock map if we're the only entry + let mut locks = self.locks.lock(); + { + drop(key_lock); + let key_lock = locks.get_mut(&key); + if let Some(_) = key_lock.and_then(Arc::get_mut) { + locks.remove(&key); + } + } + is_set + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::offchain::OffchainStorage; + + #[test] + fn should_compare_and_set_and_clear_the_locks_map() { + let mut storage = LocalStorage::new_test(); + let prefix = b"prefix"; + let key = b"key"; + let value = b"value"; + + storage.set(prefix, key, value); + assert_eq!(storage.get(prefix, key), Some(value.to_vec())); + + assert_eq!(storage.compare_and_set(prefix, key, Some(value), b"asd"), true); + assert_eq!(storage.get(prefix, key), Some(b"asd".to_vec())); + assert!(storage.locks.lock().is_empty(), "Locks map should be empty!"); + } + + #[test] + fn should_compare_and_set_on_empty_field() { + let mut storage = LocalStorage::new_test(); + let prefix = b"prefix"; + let key = b"key"; + + assert_eq!(storage.compare_and_set(prefix, key, None, b"asd"), true); + assert_eq!(storage.get(prefix, key), Some(b"asd".to_vec())); + assert!(storage.locks.lock().is_empty(), "Locks map should be empty!"); + } + +} diff --git a/client/db/src/stats.rs b/client/db/src/stats.rs new file mode 100644 index 0000000000000..805a0f498f7fc --- /dev/null +++ b/client/db/src/stats.rs @@ -0,0 +1,102 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Database usage statistics + +use std::sync::atomic::{AtomicU64, Ordering as AtomicOrdering}; + +/// Accumulated usage statistics for state queries. +pub struct StateUsageStats { + started: std::time::Instant, + reads: AtomicU64, + bytes_read: AtomicU64, + writes: AtomicU64, + bytes_written: AtomicU64, + reads_cache: AtomicU64, + bytes_read_cache: AtomicU64, +} + +impl StateUsageStats { + /// New empty usage stats. + pub fn new() -> Self { + Self { + started: std::time::Instant::now(), + reads: 0.into(), + bytes_read: 0.into(), + writes: 0.into(), + bytes_written: 0.into(), + reads_cache: 0.into(), + bytes_read_cache: 0.into(), + } + } + + /// Tally one read operation, of some length. + pub fn tally_read(&self, data_bytes: u64, cache: bool) { + self.reads.fetch_add(1, AtomicOrdering::Relaxed); + self.bytes_read.fetch_add(data_bytes, AtomicOrdering::Relaxed); + if cache { + self.reads_cache.fetch_add(1, AtomicOrdering::Relaxed); + self.bytes_read_cache.fetch_add(data_bytes, AtomicOrdering::Relaxed); + } + } + + /// Tally one key read. + pub fn tally_key_read(&self, key: &[u8], val: Option<&Vec>, cache: bool) { + self.tally_read(key.len() as u64 + val.as_ref().map(|x| x.len() as u64).unwrap_or(0), cache); + } + + /// Tally one child key read. + pub fn tally_child_key_read(&self, key: &(Vec, Vec), val: Option>, cache: bool) -> Option> { + self.tally_read(key.0.len() as u64 + key.1.len() as u64 + val.as_ref().map(|x| x.len() as u64).unwrap_or(0), cache); + val + } + + /// Tally some write operations, including their byte count. + pub fn tally_writes(&self, ops: u64, data_bytes: u64) { + self.writes.fetch_add(ops, AtomicOrdering::Relaxed); + self.bytes_written.fetch_add(data_bytes, AtomicOrdering::Relaxed); + } + + /// Merge state machine usage info. + pub fn merge_sm(&self, info: sp_state_machine::UsageInfo) { + self.reads.fetch_add(info.reads.ops, AtomicOrdering::Relaxed); + self.bytes_read.fetch_add(info.reads.bytes, AtomicOrdering::Relaxed); + self.writes.fetch_add(info.writes.ops, AtomicOrdering::Relaxed); + self.bytes_written.fetch_add(info.writes.bytes, AtomicOrdering::Relaxed); + self.reads_cache.fetch_add(info.cache_reads.ops, AtomicOrdering::Relaxed); + self.bytes_read_cache.fetch_add(info.cache_reads.bytes, AtomicOrdering::Relaxed); + } + + pub fn take(&self) -> sp_state_machine::UsageInfo { + use sp_state_machine::UsageUnit; + + fn unit(ops: &AtomicU64, bytes: &AtomicU64) -> UsageUnit { + UsageUnit { ops: ops.swap(0, AtomicOrdering::Relaxed), bytes: bytes.swap(0, AtomicOrdering::Relaxed) } + } + + sp_state_machine::UsageInfo { + reads: unit(&self.reads, &self.bytes_read), + writes: unit(&self.writes, &self.bytes_written), + cache_reads: unit(&self.reads_cache, &self.bytes_read_cache), + // TODO: Proper tracking state of memory footprint here requires + // imposing `MallocSizeOf` requirement on half of the codebase, + // so it is an open question how to do it better + memory: 0, + started: self.started, + span: self.started.elapsed(), + } + } +} diff --git a/client/db/src/storage_cache.rs b/client/db/src/storage_cache.rs new file mode 100644 index 0000000000000..4f7e906a0ae28 --- /dev/null +++ b/client/db/src/storage_cache.rs @@ -0,0 +1,1662 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Global cache state. + +use std::collections::{VecDeque, HashSet, HashMap}; +use std::sync::Arc; +use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; +use linked_hash_map::{LinkedHashMap, Entry}; +use hash_db::Hasher; +use sp_runtime::traits::{Block as BlockT, Header, HasherFor, NumberFor}; +use sp_core::hexdisplay::HexDisplay; +use sp_core::storage::ChildInfo; +use sp_state_machine::{backend::Backend as StateBackend, TrieBackend}; +use log::trace; +use sc_client_api::backend::{StorageCollection, ChildStorageCollection}; +use std::hash::Hash as StdHash; +use crate::stats::StateUsageStats; + +const STATE_CACHE_BLOCKS: usize = 12; + +type StorageKey = Vec; +type ChildStorageKey = (Vec, Vec); +type StorageValue = Vec; + +/// Shared canonical state cache. +pub struct Cache { + /// Storage cache. `None` indicates that key is known to be missing. + lru_storage: LRUMap>, + /// Storage hashes cache. `None` indicates that key is known to be missing. + lru_hashes: LRUMap>, + /// Storage cache for child trie. `None` indicates that key is known to be missing. + lru_child_storage: LRUMap>, + /// Information on the modifications in recently committed blocks; specifically which keys + /// changed in which block. Ordered by block number. + modifications: VecDeque>, +} + +struct LRUMap(LinkedHashMap, usize, usize); + +/// Internal trait similar to `heapsize` but using +/// a simply estimation. +/// +/// This should not be made public, it is implementation +/// detail trait. If it need to become public please +/// consider using `malloc_size_of`. +trait EstimateSize { + /// Return a size estimation of additional size needed + /// to cache this struct (in bytes). + fn estimate_size(&self) -> usize; +} + +impl EstimateSize for Vec { + fn estimate_size(&self) -> usize { + self.capacity() + } +} + +impl EstimateSize for Option> { + fn estimate_size(&self) -> usize { + self.as_ref().map(|v|v.capacity()).unwrap_or(0) + } +} + +struct OptionHOut>(Option); + +impl> EstimateSize for OptionHOut { + fn estimate_size(&self) -> usize { + // capacity would be better + self.0.as_ref().map(|v|v.as_ref().len()).unwrap_or(0) + } +} + +impl EstimateSize for (T, T) { + fn estimate_size(&self) -> usize { + self.0.estimate_size() + self.1.estimate_size() + } +} + +impl LRUMap { + fn remove(&mut self, k: &K) { + let map = &mut self.0; + let storage_used_size = &mut self.1; + if let Some(v) = map.remove(k) { + *storage_used_size -= k.estimate_size(); + *storage_used_size -= v.estimate_size(); + } + } + + fn add(&mut self, k: K, v: V) { + let lmap = &mut self.0; + let storage_used_size = &mut self.1; + let limit = self.2; + let klen = k.estimate_size(); + *storage_used_size += v.estimate_size(); + // TODO assert k v size fit into limit?? to avoid insert remove? + match lmap.entry(k) { + Entry::Occupied(mut entry) => { + // note that in this case we are not running pure lru as + // it would require to remove first + *storage_used_size -= entry.get().estimate_size(); + entry.insert(v); + }, + Entry::Vacant(entry) => { + *storage_used_size += klen; + entry.insert(v); + }, + }; + + while *storage_used_size > limit { + if let Some((k,v)) = lmap.pop_front() { + *storage_used_size -= k.estimate_size(); + *storage_used_size -= v.estimate_size(); + } else { + // can happen fairly often as we get value from multiple lru + // and only remove from a single lru + break; + } + } + } + + fn get(&mut self, k: &Q) -> Option<&mut V> + where K: std::borrow::Borrow, + Q: StdHash + Eq { + self.0.get_refresh(k) + } + + fn used_size(&self) -> usize { + self.1 + } + fn clear(&mut self) { + self.0.clear(); + self.1 = 0; + } + +} + +impl Cache { + /// Returns the used memory size of the storage cache in bytes. + pub fn used_storage_cache_size(&self) -> usize { + self.lru_storage.used_size() + + self.lru_child_storage.used_size() + // ignore small hashes storage and self.lru_hashes.used_size() + } + + /// Synchronize the shared cache with the best block state. + /// + /// This function updates the shared cache by removing entries + /// that are invalidated by chain reorganization. It should be called + /// externally when chain reorg happens without importing a new block. + pub fn sync(&mut self, enacted: &[B::Hash], retracted: &[B::Hash]) { + trace!("Syncing shared cache, enacted = {:?}, retracted = {:?}", enacted, retracted); + + // Purge changes from re-enacted and retracted blocks. + let mut clear = false; + for block in enacted { + clear = clear || { + if let Some(m) = self.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 {:?}", HexDisplay::from(a)); + self.lru_storage.remove(a); + } + for a in &m.child_storage { + trace!("Reverting enacted child key {:?}", a); + self.lru_child_storage.remove(a); + } + false + } else { + true + } + }; + } + + for block in retracted { + clear = clear || { + if let Some(m) = self.modifications.iter_mut().find(|m| &m.hash == block) { + trace!("Retracting block {:?}", block); + m.is_canon = false; + for a in &m.storage { + trace!("Retracted key {:?}", HexDisplay::from(a)); + self.lru_storage.remove(a); + } + for a in &m.child_storage { + trace!("Retracted child key {:?}", a); + self.lru_child_storage.remove(a); + } + false + } else { + true + } + }; + } + if clear { + // We don't know anything about the block; clear everything + trace!("Wiping cache"); + self.lru_storage.clear(); + self.lru_child_storage.clear(); + self.lru_hashes.clear(); + self.modifications.clear(); + } + } +} + +pub type SharedCache = Arc>>; + +/// Fix lru storage size for hash (small 64ko). +const FIX_LRU_HASH_SIZE: usize = 65_536; + +/// Create a new shared cache instance with given max memory usage. +pub fn new_shared_cache( + shared_cache_size: usize, + child_ratio: (usize, usize), +) -> SharedCache { + let top = child_ratio.1.saturating_sub(child_ratio.0); + Arc::new( + Mutex::new( + Cache { + lru_storage: LRUMap( + LinkedHashMap::new(), 0, shared_cache_size * top / child_ratio.1 + ), + lru_hashes: LRUMap(LinkedHashMap::new(), 0, FIX_LRU_HASH_SIZE), + lru_child_storage: LRUMap( + LinkedHashMap::new(), 0, shared_cache_size * child_ratio.0 / child_ratio.1 + ), + 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, + /// A set of modified child storage keys. + child_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>, + /// Child storage cache. + /// + /// `None` indicates that key is known to be missing. + child_storage: HashMap>, +} + +/// Cache changes. +pub struct CacheChanges { + /// 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, +} + +/// State cache 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: BlockT> { + /// Usage statistics + usage: StateUsageStats, + /// Backing state. + state: S, + /// Cache data. + pub cache: CacheChanges, +} + +impl>, B: BlockT> std::fmt::Debug for CachingState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Block {:?}", self.cache.parent_hash) + } +} + +impl CacheChanges { + /// Propagate local cache into the shared cache and synchronize + /// the shared cache with the best block state. + /// + /// 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( + &mut self, + enacted: &[B::Hash], + retracted: &[B::Hash], + changes: StorageCollection, + child_changes: ChildStorageCollection, + commit_hash: Option, + commit_number: Option>, + is_best: bool, + ) { + let mut cache = self.shared_cache.lock(); + trace!( + "Syncing cache, id = (#{:?}, {:?}), parent={:?}, best={}", + commit_number, + commit_hash, + self.parent_hash, + is_best, + ); + let cache = &mut *cache; + // Filter out commiting block if any. + let enacted: Vec<_> = enacted + .iter() + .filter(|h| commit_hash.as_ref().map_or(true, |p| *h != p)) + .cloned() + .collect(); + cache.sync(&enacted, retracted); + // 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 root entries, {} modified child entries", + local_cache.storage.len(), + local_cache.hashes.len(), + changes.len(), + child_changes.iter().map(|v|v.1.len()).sum::(), + ); + for (k, v) in local_cache.storage.drain() { + cache.lru_storage.add(k, v); + } + for (k, v) in local_cache.child_storage.drain() { + cache.lru_child_storage.add(k, v); + } + for (k, v) in local_cache.hashes.drain() { + cache.lru_hashes.add(k, OptionHOut(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(); + let mut child_modifications = HashSet::new(); + child_changes.into_iter().for_each(|(sk, changes)| + for (k, v) in changes.into_iter() { + let k = (sk.clone(), k); + if is_best { + cache.lru_child_storage.add(k.clone(), v); + } + child_modifications.insert(k); + } + ); + for (k, v) in changes.into_iter() { + if is_best { + cache.lru_hashes.remove(&k); + cache.lru_storage.add(k.clone(), v); + } + modifications.insert(k); + } + + // Save modified storage. These are ordered by the block number in reverse. + let block_changes = BlockChanges { + storage: modifications, + child_storage: child_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); + } + } + } + +} + +impl>, B: BlockT> CachingState { + /// Create a new instance wrapping generic State and shared cache. + pub fn new(state: S, shared_cache: SharedCache, parent_hash: Option) -> Self { + CachingState { + usage: StateUsageStats::new(), + state, + cache: CacheChanges { + shared_cache, + local_cache: RwLock::new(LocalCache { + storage: Default::default(), + hashes: Default::default(), + child_storage: Default::default(), + }), + parent_hash: parent_hash, + }, + } + } + + /// 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: Option<&[u8]>, + child_key: Option<&ChildStorageKey>, + parent_hash: &Option, + modifications: &VecDeque> + ) -> bool + { + let mut parent = match *parent_hash { + None => { + trace!("Cache lookup skipped for {:?}: no parent hash", key.as_ref().map(HexDisplay::from)); + return false; + } + Some(ref parent) => parent, + }; + // Ignore all storage entries 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 parents 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 let Some(key) = key { + if m.storage.contains(key) { + trace!("Cache lookup skipped for {:?}: modified in a later block", HexDisplay::from(&key)); + return false; + } + } + if let Some(child_key) = child_key { + if m.child_storage.contains(child_key) { + trace!("Cache lookup skipped for {:?}: modified in a later block", child_key); + return false; + } + } + } + trace!("Cache lookup skipped for {:?}: parent hash is unknown", key.as_ref().map(HexDisplay::from)); + false + } + + /// Dispose state and return cache data. + pub fn release(self) -> CacheChanges { + self.cache + } +} + +impl>, B: BlockT> 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.cache.local_cache.upgradable_read(); + // Note that local cache makes that lru is not refreshed + if let Some(entry) = local_cache.storage.get(key).cloned() { + trace!("Found in local cache: {:?}", HexDisplay::from(&key)); + self.usage.tally_key_read(key, entry.as_ref(), true); + + return Ok(entry) + } + let mut cache = self.cache.shared_cache.lock(); + if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) { + if let Some(entry) = cache.lru_storage.get(key).map(|a| a.clone()) { + trace!("Found in shared cache: {:?}", HexDisplay::from(&key)); + self.usage.tally_key_read(key, entry.as_ref(), true); + return Ok(entry) + } + } + trace!("Cache miss: {:?}", HexDisplay::from(&key)); + let value = self.state.storage(key)?; + RwLockUpgradableReadGuard::upgrade(local_cache).storage.insert(key.to_vec(), value.clone()); + self.usage.tally_key_read(key, value.as_ref(), false); + Ok(value) + } + + fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { + let local_cache = self.cache.local_cache.upgradable_read(); + if let Some(entry) = local_cache.hashes.get(key).cloned() { + trace!("Found hash in local cache: {:?}", HexDisplay::from(&key)); + return Ok(entry) + } + let mut cache = self.cache.shared_cache.lock(); + if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) { + if let Some(entry) = cache.lru_hashes.get(key).map(|a| a.0.clone()) { + trace!("Found hash in shared cache: {:?}", HexDisplay::from(&key)); + return Ok(entry) + } + } + trace!("Cache hash miss: {:?}", HexDisplay::from(&key)); + let hash = self.state.storage_hash(key)?; + RwLockUpgradableReadGuard::upgrade(local_cache).hashes.insert(key.to_vec(), hash); + Ok(hash) + } + + fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + let key = (storage_key.to_vec(), key.to_vec()); + let local_cache = self.cache.local_cache.upgradable_read(); + if let Some(entry) = local_cache.child_storage.get(&key).cloned() { + trace!("Found in local cache: {:?}", key); + return Ok( + self.usage.tally_child_key_read(&key, entry, true) + ) + } + let mut cache = self.cache.shared_cache.lock(); + if Self::is_allowed(None, Some(&key), &self.cache.parent_hash, &cache.modifications) { + if let Some(entry) = cache.lru_child_storage.get(&key).map(|a| a.clone()) { + trace!("Found in shared cache: {:?}", key); + return Ok( + self.usage.tally_child_key_read(&key, entry, true) + ) + } + } + trace!("Cache miss: {:?}", key); + let value = self.state.child_storage(storage_key, child_info, &key.1[..])?; + + // just pass it through the usage counter + let value = self.usage.tally_child_key_read(&key, value, false); + + RwLockUpgradableReadGuard::upgrade(local_cache).child_storage.insert(key, value.clone()); + Ok(value) + } + + fn exists_storage(&self, key: &[u8]) -> Result { + Ok(self.storage(key)?.is_some()) + } + + fn exists_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result { + self.state.exists_child_storage(storage_key, child_info, key) + } + + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + f: F, + ) { + self.state.for_keys_in_child_storage(storage_key, child_info, f) + } + + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + self.state.next_storage_key(key) + } + + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.state.next_child_storage_key(storage_key, child_info, key) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + self.state.for_keys_with_prefix(prefix, f) + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.state.for_key_values_with_prefix(prefix, f) + } + + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + f: F, + ) { + self.state.for_child_keys_with_prefix(storage_key, child_info, prefix, f) + } + + fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) + where + I: IntoIterator, Option>)>, + { + self.state.storage_root(delta) + } + + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (B::Hash, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + { + self.state.child_storage_root(storage_key, child_info, delta) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + self.state.pairs() + } + + fn keys(&self, prefix: &[u8]) -> Vec> { + self.state.keys(prefix) + } + + fn child_keys( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + ) -> Vec> { + self.state.child_keys(storage_key, child_info, prefix) + } + + fn as_trie_backend(&mut self) -> Option<&TrieBackend>> { + self.state.as_trie_backend() + } + + fn usage_info(&self) -> sp_state_machine::UsageInfo { + self.usage.take() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; + use sp_state_machine::InMemoryBackend; + use sp_core::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, (0, 1)); + + // blocks [ 3a(c) 2a(c) 2b 1b 1a(c) 0 ] + // state [ 5 5 4 3 2 2 ] + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(root_parent), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![2]))], + vec![], + Some(h0), + Some(0), + true, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h0), + ); + s.cache.sync_cache(&[], &[], vec![], vec![], Some(h1a), Some(1), true); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h0), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![3]))], + vec![], + Some(h1b), + Some(1), + false, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1b), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![4]))], + vec![], + Some(h2b), + Some(2), + false, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1a), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![5]))], + vec![], + Some(h2a), + Some(2), + true, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h2a), + ); + s.cache.sync_cache(&[], &[], vec![], vec![], Some(h3a), Some(3), true); + + let s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h3a), + ); + assert_eq!(s.storage(&key).unwrap().unwrap(), vec![5]); + + let s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1a), + ); + assert!(s.storage(&key).unwrap().is_none()); + + let s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h2b), + ); + assert!(s.storage(&key).unwrap().is_none()); + + let s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1b), + ); + 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( + InMemoryBackend::::default(), + shared.clone(), + Some(h2b), + ); + s.cache.sync_cache( + &[h1b, h2b, h3b], + &[h1a, h2a, h3a], + vec![], + vec![], + Some(h3b), + Some(3), + true, + ); + let s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h3a), + ); + assert!(s.storage(&key).unwrap().is_none()); + } + + #[test] + fn simple_fork() { + let _ = ::env_logger::try_init(); + + let root_parent = H256::random(); + let key = H256::random()[..].to_vec(); + let h1 = H256::random(); + let h2a = H256::random(); + let h2b = H256::random(); + let h3b = H256::random(); + + let shared = new_shared_cache::(256*1024, (0,1)); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(root_parent), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![2]))], + vec![], + Some(h1), + Some(1), + true, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1), + ); + s.cache.sync_cache(&[], &[], vec![], vec![], Some(h2a), Some(2), true); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![3]))], + vec![], + Some(h2b), + Some(2), + false, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h2b), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![3]))], + vec![], + Some(h3b), + Some(2), + false, + ); + + let s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h2a), + ); + assert_eq!(s.storage(&key).unwrap().unwrap(), vec![2]); + } + + #[test] + fn double_fork() { + let root_parent = H256::random(); + let key = H256::random()[..].to_vec(); + let h1 = 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, (0,1)); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(root_parent), + ); + s.cache.sync_cache(&[], &[], vec![], vec![], Some(h1), Some(1), true); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1), + ); + s.cache.sync_cache(&[], &[], vec![], vec![], Some(h2a), Some(2), true); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h2a), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![2]))], + vec![], + Some(h3a), + Some(3), + true, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1), + ); + s.cache.sync_cache(&[], &[], vec![], vec![], Some(h2b), Some(2), false); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h2b), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![3]))], + vec![], + Some(h3b), + Some(3), + false, + ); + + let s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h3a), + ); + assert_eq!(s.storage(&key).unwrap().unwrap(), vec![2]); + } + + #[test] + fn should_track_used_size_correctly() { + let root_parent = H256::random(); + let shared = new_shared_cache::(109, ((109-36), 109)); + let h0 = H256::random(); + + let mut s = CachingState::new( + InMemoryBackend::::default(), shared.clone(), Some(root_parent.clone()), + ); + + let key = H256::random()[..].to_vec(); + let s_key = H256::random()[..].to_vec(); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![1, 2, 3]))], + vec![], + Some(h0), + Some(0), + true, + ); + // 32 key, 3 byte size + assert_eq!(shared.lock().used_storage_cache_size(), 35 /* bytes */); + + let key = H256::random()[..].to_vec(); + s.cache.sync_cache( + &[], + &[], + vec![], + vec![(s_key.clone(), vec![(key.clone(), Some(vec![1, 2]))])], + Some(h0), + Some(0), + true, + ); + // 35 + (2 * 32) key, 2 byte size + assert_eq!(shared.lock().used_storage_cache_size(), 101 /* bytes */); + } + + #[test] + fn should_remove_lru_items_based_on_tracking_used_size() { + let root_parent = H256::random(); + let shared = new_shared_cache::(36*3, (2,3)); + let h0 = H256::random(); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(root_parent), + ); + + let key = H256::random()[..].to_vec(); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![1, 2, 3, 4]))], + vec![], + Some(h0), + Some(0), + true, + ); + // 32 key, 4 byte size + assert_eq!(shared.lock().used_storage_cache_size(), 36 /* bytes */); + + let key = H256::random()[..].to_vec(); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![1, 2]))], + vec![], + Some(h0), + Some(0), + true, + ); + // 32 key, 2 byte size + assert_eq!(shared.lock().used_storage_cache_size(), 34 /* bytes */); + } + + #[test] + fn fix_storage_mismatch_issue() { + let _ = ::env_logger::try_init(); + let root_parent = H256::random(); + + let key = H256::random()[..].to_vec(); + + let h0 = H256::random(); + let h1 = H256::random(); + + let shared = new_shared_cache::(256 * 1024, (0, 1)); + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(root_parent.clone()), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![2]))], + vec![], + Some(h0.clone()), + Some(0), + true, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h0), + ); + s.cache.sync_cache( + &[], + &[], + vec![(key.clone(), Some(vec![3]))], + vec![], + Some(h1), + Some(1), + true, + ); + + let mut s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1), + ); + assert_eq!(s.storage(&key).unwrap(), Some(vec![3])); + + // Restart (or unknown block?), clear caches. + { + let mut cache = s.cache.shared_cache.lock(); + let cache = &mut *cache; + cache.lru_storage.clear(); + cache.lru_hashes.clear(); + cache.lru_child_storage.clear(); + cache.modifications.clear(); + } + + // New value is written because of cache miss. + s.cache.local_cache.write().storage.insert(key.clone(), Some(vec![42])); + + // New value is propagated. + s.cache.sync_cache(&[], &[], vec![], vec![], None, None, true); + + let s = CachingState::new( + InMemoryBackend::::default(), + shared.clone(), + Some(h1), + ); + assert_eq!(s.storage(&key).unwrap(), None); + } +} + +#[cfg(test)] +mod qc { + use std::collections::{HashMap, hash_map::Entry}; + + use quickcheck::{quickcheck, TestResult, Arbitrary}; + + use super::*; + use sp_runtime::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; + use sp_state_machine::InMemoryBackend; + use sp_core::Blake2Hasher; + + type Block = RawBlock>; + + type KeySet = Vec<(Vec, Option>)>; + + type KeyMap = HashMap, Option>>; + + #[derive(Debug, Clone)] + struct Node { + hash: H256, + parent: H256, + state: KeyMap, + changes: KeySet, + } + + impl Node { + fn new_next(&self, hash: H256, changes: KeySet) -> Self { + let mut state = self.state.clone(); + + for (k, v) in self.state.iter() { state.insert(k.clone(), v.clone()); } + for (k, v) in changes.clone().into_iter() { state.insert(k, v); } + + Self { + hash, + parent: self.hash, + changes, + state, + } + } + + fn new(hash: H256, parent: H256, changes: KeySet) -> Self { + let mut state = KeyMap::new(); + + for (k, v) in changes.clone().into_iter() { state.insert(k, v); } + + Self { + hash, + parent, + state, + changes, + } + } + + fn purge(&mut self, other_changes: &KeySet) { + for (k, _) in other_changes.iter() { + self.state.remove(k); + } + } + } + + #[derive(Debug, Clone)] + enum Action { + Next { hash: H256, changes: KeySet }, + Fork { depth: usize, hash: H256, changes: KeySet }, + ReorgWithImport { depth: usize, hash: H256 }, + FinalizationReorg { fork_depth: usize, depth: usize }, + } + + impl Arbitrary for Action { + fn arbitrary(gen: &mut G) -> Self { + let path = gen.next_u32() as u8; + let mut buf = [0u8; 32]; + + match path { + 0..=175 => { + gen.fill_bytes(&mut buf[..]); + Action::Next { + hash: H256::from(&buf), + changes: { + let mut set = Vec::new(); + for _ in 0..gen.next_u32()/(64*256*256*256) { + set.push((vec![gen.next_u32() as u8], Some(vec![gen.next_u32() as u8]))); + } + set + } + } + }, + 176..=220 => { + gen.fill_bytes(&mut buf[..]); + Action::Fork { + hash: H256::from(&buf), + depth: ((gen.next_u32() as u8) / 32) as usize, + changes: { + let mut set = Vec::new(); + for _ in 0..gen.next_u32()/(64*256*256*256) { + set.push((vec![gen.next_u32() as u8], Some(vec![gen.next_u32() as u8]))); + } + set + } + } + }, + 221..=240 => { + gen.fill_bytes(&mut buf[..]); + Action::ReorgWithImport { + hash: H256::from(&buf), + depth: ((gen.next_u32() as u8) / 32) as usize, // 0-7 + } + }, + _ => { + gen.fill_bytes(&mut buf[..]); + Action::FinalizationReorg { + fork_depth: ((gen.next_u32() as u8) / 32) as usize, // 0-7 + depth: ((gen.next_u32() as u8) / 64) as usize, // 0-3 + } + }, + } + } + } + + struct Mutator { + shared: SharedCache, + canon: Vec, + forks: HashMap>, + } + + impl Mutator { + fn new_empty() -> Self { + let shared = new_shared_cache::(256*1024, (0,1)); + + Self { + shared, + canon: vec![], + forks: HashMap::new(), + } + } + + fn head_state(&self, hash: H256) -> CachingState, Block> { + CachingState::new( + InMemoryBackend::::default(), + self.shared.clone(), + Some(hash) + ) + } + + fn canon_head_state(&self) -> CachingState, Block> { + self.head_state(self.canon.last().expect("Expected to be one commit").hash) + } + + fn mutate_static( + &mut self, + action: Action, + ) -> CachingState, Block> { + self.mutate(action).expect("Expected to provide only valid actions to the mutate_static") + } + + fn canon_len(&self) -> usize { + return self.canon.len(); + } + + fn head_storage_ref(&self) -> &KeyMap { + &self.canon.last().expect("Expected to be one commit").state + } + + fn key_permutations() -> Vec> { + (0u8..255).map(|x| vec![x]).collect() + } + + fn mutate( + &mut self, + action: Action, + ) -> Result, Block>, ()> { + let state = match action { + Action::Fork { depth, hash, changes } => { + let pos = self.canon.len() as isize - depth as isize; + if pos < 0 || self.canon.len() == 0 || pos >= (self.canon.len()-1) as isize + // no fork on top also, thus len-1 + { + return Err(()); + } + + let pos = pos as usize; + + let fork_at = self.canon[pos].hash; + + let (total_h, parent) = match self.forks.entry(fork_at) { + Entry::Occupied(occupied) => { + let chain = occupied.into_mut(); + let parent = chain.last().expect("No empty forks are ever created").clone(); + let mut node = parent.new_next(hash, changes.clone()); + + for earlier in chain.iter() { + node.purge(&earlier.changes.clone()); + } + + chain.push(node); + + (pos + chain.len(), parent.hash) + }, + Entry::Vacant(vacant) => { + let canon_parent = &self.canon[pos]; + vacant.insert(vec![canon_parent.new_next(hash, changes.clone())]); + + (pos + 1, fork_at) + } + }; + + let mut state = CachingState::new( + InMemoryBackend::::default(), + self.shared.clone(), + Some(parent) + ); + + state.cache.sync_cache( + &[], + &[], + changes, + vec![], + Some(hash), + Some(total_h as u64), + false, + ); + + state + }, + Action::Next { hash, changes } => { + let (next, parent_hash) = match self.canon.last() { + None => { + let parent_hash = H256::from(&[0u8; 32]); + (Node::new(hash, parent_hash, changes.clone()), parent_hash) + }, + Some(parent) => { + (parent.new_next(hash, changes.clone()), parent.hash) + } + }; + + // delete cache entries for earlier + for node in self.canon.iter_mut() { + node.purge(&next.changes); + if let Some(fork) = self.forks.get_mut(&node.hash) { + for node in fork.iter_mut() { + node.purge(&next.changes); + } + } + } + + let mut state = CachingState::new( + InMemoryBackend::::default(), + self.shared.clone(), + Some(parent_hash) + ); + + state.cache.sync_cache( + &[], + &[], + next.changes.clone(), + vec![], + Some(hash), + Some(self.canon.len() as u64 + 1), + true, + ); + + self.canon.push(next); + + state + }, + Action::ReorgWithImport { depth, hash } => { + let pos = self.canon.len() as isize - depth as isize; + if pos < 0 || pos+1 >= self.canon.len() as isize { return Err(()); } + let fork_at = self.canon[pos as usize].hash; + let pos = pos as usize; + + match self.forks.get_mut(&fork_at) { + Some(chain) => { + let mut new_fork = self.canon.drain(pos+1..).collect::>(); + + let retracted: Vec = new_fork.iter().map(|node| node.hash).collect(); + let enacted: Vec = chain.iter().map(|node| node.hash).collect(); + + std::mem::swap(chain, &mut new_fork); + + let mut node = new_fork.last().map( + |node| node.new_next(hash, vec![]) + ).expect("No empty fork ever created!"); + + for invalidators in chain.iter().chain(new_fork.iter()) { + node.purge(&invalidators.changes); + } + + self.canon.extend(new_fork.into_iter()); + + self.canon.push(node); + + let mut state = CachingState::new( + InMemoryBackend::::default(), + self.shared.clone(), + Some(fork_at) + ); + + let height = pos as u64 + enacted.len() as u64 + 2; + state.cache.sync_cache( + &enacted[..], + &retracted[..], + vec![], + vec![], + Some(hash), + Some(height), + true, + ); + + state + } + None => { + return Err(()); // no reorg without a fork atm! + }, + } + }, + Action::FinalizationReorg { fork_depth, depth } => { + let pos = self.canon.len() as isize - fork_depth as isize; + if pos < 0 || pos+1 >= self.canon.len() as isize { return Err(()); } + let fork_at = self.canon[pos as usize].hash; + let pos = pos as usize; + + match self.forks.get_mut(&fork_at) { + Some(fork_chain) => { + let sync_pos = fork_chain.len() as isize - fork_chain.len() as isize - depth as isize; + if sync_pos < 0 || sync_pos >= fork_chain.len() as isize { return Err (()); } + let sync_pos = sync_pos as usize; + + let mut new_fork = self.canon.drain(pos+1..).collect::>(); + + let retracted: Vec = new_fork.iter().map(|node| node.hash).collect(); + let enacted: Vec = fork_chain.iter().take(sync_pos+1).map(|node| node.hash).collect(); + + std::mem::swap(fork_chain, &mut new_fork); + + self.shared.lock().sync(&retracted, &enacted); + + self.head_state( + self.canon.last() + .expect("wasn't forking to emptiness so there shoud be one!") + .hash + ) + }, + None => { + return Err(()); // no reorg to nothing pls! + } + } + + }, + }; + + Ok(state) + } + } + + #[test] + fn smoke() { + 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 mut mutator = Mutator::new_empty(); + mutator.mutate_static(Action::Next { hash: h0, changes: vec![(key.clone(), Some(vec![2]))] }); + mutator.mutate_static(Action::Next { hash: h1a, changes: vec![] }); + mutator.mutate_static(Action::Fork { depth: 2, hash: h1b, changes: vec![(key.clone(), Some(vec![3]))] }); + mutator.mutate_static(Action::Fork { depth: 2, hash: h2b, changes: vec![(key.clone(), Some(vec![4]))] }); + mutator.mutate_static(Action::Next { hash: h2a, changes: vec![(key.clone(), Some(vec![5]))] }); + mutator.mutate_static(Action::Next { hash: h3a, changes: vec![] }); + + assert_eq!(mutator.head_state(h3a).storage(&key).unwrap().expect("there should be a value"), vec![5]); + assert!(mutator.head_state(h1a).storage(&key).unwrap().is_none()); + assert!(mutator.head_state(h2b).storage(&key).unwrap().is_none()); + assert!(mutator.head_state(h1b).storage(&key).unwrap().is_none()); + + mutator.mutate_static(Action::ReorgWithImport { depth: 4, hash: h3b }); + assert!(mutator.head_state(h3a).storage(&key).unwrap().is_none()); + } + + fn is_head_match(mutator: &Mutator) -> bool { + let head_state = mutator.canon_head_state(); + + for key in Mutator::key_permutations() { + match (head_state.storage(&key).unwrap(), mutator.head_storage_ref().get(&key)) { + (Some(x), Some(y)) => { + if Some(&x) != y.as_ref() { + eprintln!("{:?} != {:?}", x, y); + return false; + } + }, + (None, Some(_y)) => { + // TODO: cache miss is not tracked atm + }, + (Some(x), None) => { + eprintln!("{:?} != ", x); + return false; + }, + _ => continue, + } + } + true + } + + fn is_canon_match(mutator: &Mutator) -> bool { + for node in mutator.canon.iter() { + let head_state = mutator.head_state(node.hash); + for key in Mutator::key_permutations() { + match (head_state.storage(&key).unwrap(), node.state.get(&key)) { + (Some(x), Some(y)) => { + if Some(&x) != y.as_ref() { + eprintln!("at [{}]: {:?} != {:?}", node.hash, x, y); + return false; + } + }, + (None, Some(_y)) => { + // cache miss is not tracked atm + }, + (Some(x), None) => { + eprintln!("at [{}]: {:?} != ", node.hash, x); + return false; + }, + _ => continue, + } + } + } + true + } + + #[test] + fn reorg() { + let key = H256::random()[..].to_vec(); + let h0 = H256::random(); + let h1 = H256::random(); + let h2 = H256::random(); + let h1b = H256::random(); + let h2b = H256::random(); + + let mut mutator = Mutator::new_empty(); + mutator.mutate_static(Action::Next { hash: h0, changes: vec![] }); + mutator.mutate_static(Action::Next { hash: h1, changes: vec![] }); + mutator.mutate_static(Action::Next { hash: h2, changes: vec![(key.clone(), Some(vec![2]))] }); + mutator.mutate_static(Action::Fork { depth: 2, hash: h1b, changes: vec![(key.clone(), Some(vec![3]))] }); + mutator.mutate_static(Action::ReorgWithImport { depth: 2, hash: h2b }); + + assert!(is_head_match(&mutator)) + } + + fn key(k: u8) -> Vec { vec![k] } + fn val(v: u8) -> Option> { Some(vec![v]) } + fn keyval(k: u8, v: u8) -> KeySet { vec![(key(k), val(v))] } + + #[test] + fn reorg2() { + let h0 = H256::random(); + let h1a = H256::random(); + let h1b = H256::random(); + let h2b = H256::random(); + let h2a = H256::random(); + let h3a = H256::random(); + + let mut mutator = Mutator::new_empty(); + mutator.mutate_static(Action::Next { hash: h0, changes: keyval(1, 1) }); + mutator.mutate_static(Action::Next { hash: h1a, changes: keyval(1, 1) }); + mutator.mutate_static(Action::Fork { depth: 2, hash: h1b, changes: keyval(2, 2 ) }); + + mutator.mutate_static(Action::Next { hash: h2a, changes: keyval(3, 3) }); + mutator.mutate_static(Action::Next { hash: h3a, changes: keyval(4, 4) }); + mutator.mutate_static(Action::ReorgWithImport { depth: 4, hash: h2b }); + + assert!(is_head_match(&mutator)) + } + + #[test] + fn fork2() { + let h1 = H256::random(); + let h2a = H256::random(); + let h2b = H256::random(); + let h3a = H256::random(); + let h3b = H256::random(); + + let mut mutator = Mutator::new_empty(); + mutator.mutate_static(Action::Next { hash: h1, changes: vec![] }); + mutator.mutate_static(Action::Next { hash: h2a, changes: vec![] }); + mutator.mutate_static(Action::Next { hash: h3a, changes: keyval(1, 1) }); + + mutator.mutate_static(Action::Fork { depth: 2, hash: h2b, changes: vec![] }); + mutator.mutate_static(Action::Fork { depth: 2, hash: h3b, changes: keyval(1, 2) }); + + assert!(is_head_match(&mutator)) + } + + #[test] + fn fork3() { + let h1 = H256::random(); + let h2a = H256::random(); + let h2b = H256::random(); + let h3a = H256::random(); + + let mut mutator = Mutator::new_empty(); + mutator.mutate_static(Action::Next { hash: h1, changes: keyval(1, 1) }); + mutator.mutate_static(Action::Next { hash: h2a, changes: keyval(2, 2) }); + mutator.mutate_static(Action::Next { hash: h3a, changes: keyval(3, 3) }); + + mutator.mutate_static(Action::Fork { depth: 2, hash: h2b, changes: keyval(1, 3) }); + + assert!(is_canon_match(&mutator)) + } + + quickcheck! { + fn head_complete(actions: Vec) -> TestResult { + let mut mutator = Mutator::new_empty(); + + for action in actions.into_iter() { + if let Err(_) = mutator.mutate(action) { + return TestResult::discard(); + } + } + + if mutator.canon_len() == 0 { + return TestResult::discard(); + } + + TestResult::from_bool(is_head_match(&mutator)) + } + + fn canon_complete(actions: Vec) -> TestResult { + let mut mutator = Mutator::new_empty(); + + for action in actions.into_iter() { + if let Err(_) = mutator.mutate(action) { + return TestResult::discard(); + } + } + + if mutator.canon_len() == 0 { + return TestResult::discard(); + } + + TestResult::from_bool(is_canon_match(&mutator)) + } + } +} diff --git a/client/db/src/utils.rs b/client/db/src/utils.rs new file mode 100644 index 0000000000000..ed7b2220aacd5 --- /dev/null +++ b/client/db/src/utils.rs @@ -0,0 +1,371 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Db-based backend utility structures and functions, used by both +//! full and light storages. + +use std::sync::Arc; +use std::{io, convert::TryInto}; + +use kvdb::{KeyValueDB, DBTransaction}; +#[cfg(feature = "kvdb-rocksdb")] +use kvdb_rocksdb::{Database, DatabaseConfig}; +use log::debug; + +use codec::Decode; +use sp_trie::DBValue; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{ + Block as BlockT, Header as HeaderT, Zero, + UniqueSaturatedFrom, UniqueSaturatedInto, +}; +use crate::{DatabaseSettings, DatabaseSettingsSrc}; + +/// Number of columns in the db. Must be the same for both full && light dbs. +/// Otherwise RocksDb will fail to open database && check its type. +pub const NUM_COLUMNS: u32 = 10; +/// Meta column. The set of keys in the column is shared by full && light storages. +pub const COLUMN_META: u32 = 0; + +/// Keys of entries in COLUMN_META. +pub mod meta_keys { + /// Type of storage (full or light). + pub const TYPE: &[u8; 4] = b"type"; + /// Best block key. + pub const BEST_BLOCK: &[u8; 4] = b"best"; + /// Last finalized block key. + pub const FINALIZED_BLOCK: &[u8; 5] = b"final"; + /// Meta information prefix for list-based caches. + pub const CACHE_META_PREFIX: &[u8; 5] = b"cache"; + /// Genesis block hash. + 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. +#[derive(Debug)] +pub struct Meta { + /// Hash of the best known block. + pub best_hash: H, + /// Number of the best known block. + pub best_number: N, + /// Hash of the best finalized block. + pub finalized_hash: H, + /// Number of the best finalized block. + pub finalized_number: N, + /// Hash of the genesis block. + pub genesis_hash: H, +} + +/// A block lookup key: used for canonical lookup from block number to hash +pub type NumberIndexKey = [u8; 4]; + +/// Convert block number into short lookup key (LE representation) for +/// blocks that are in the canonical chain. +/// +/// In the current database schema, this kind of key is only used for +/// lookups into an index, NOT for storing header data or others. +pub fn number_index_key>(n: N) -> sp_blockchain::Result { + let n = n.try_into().map_err(|_| + sp_blockchain::Error::Backend("Block number cannot be converted to u32".into()) + )?; + + Ok([ + (n >> 24) as u8, + ((n >> 16) & 0xff) as u8, + ((n >> 8) & 0xff) as u8, + (n & 0xff) as u8 + ]) +} + +/// Convert number and hash into long lookup key for blocks that are +/// not in the canonical chain. +pub fn number_and_hash_to_lookup_key( + number: N, + hash: H, +) -> sp_blockchain::Result> where + N: TryInto, + H: AsRef<[u8]>, +{ + let mut lookup_key = number_index_key(number)?.to_vec(); + lookup_key.extend_from_slice(hash.as_ref()); + Ok(lookup_key) +} + +/// Convert block lookup key into block number. +/// all block lookup keys start with the block number. +pub fn lookup_key_to_number(key: &[u8]) -> sp_blockchain::Result where + N: From +{ + if key.len() < 4 { + return Err(sp_blockchain::Error::Backend("Invalid block key".into())); + } + Ok((key[0] as u32) << 24 + | (key[1] as u32) << 16 + | (key[2] as u32) << 8 + | (key[3] as u32)).map(Into::into) +} + +/// Delete number to hash mapping in DB transaction. +pub fn remove_number_to_key_mapping>( + transaction: &mut DBTransaction, + key_lookup_col: u32, + number: N, +) -> sp_blockchain::Result<()> { + transaction.delete(key_lookup_col, number_index_key(number)?.as_ref()); + Ok(()) +} + +/// Remove key mappings. +pub fn remove_key_mappings, H: AsRef<[u8]>>( + transaction: &mut DBTransaction, + key_lookup_col: u32, + number: N, + hash: H, +) -> sp_blockchain::Result<()> { + remove_number_to_key_mapping(transaction, key_lookup_col, number)?; + transaction.delete(key_lookup_col, hash.as_ref()); + Ok(()) +} + +/// Place a number mapping into the database. This maps number to current perceived +/// block hash at that position. +pub fn insert_number_to_key_mapping + Clone, H: AsRef<[u8]>>( + transaction: &mut DBTransaction, + key_lookup_col: u32, + number: N, + hash: H, +) -> sp_blockchain::Result<()> { + transaction.put_vec( + key_lookup_col, + number_index_key(number.clone())?.as_ref(), + number_and_hash_to_lookup_key(number, hash)?, + ); + Ok(()) +} + +/// Insert a hash to key mapping in the database. +pub fn insert_hash_to_key_mapping, H: AsRef<[u8]> + Clone>( + transaction: &mut DBTransaction, + key_lookup_col: u32, + number: N, + hash: H, +) -> sp_blockchain::Result<()> { + transaction.put_vec( + key_lookup_col, + hash.clone().as_ref(), + number_and_hash_to_lookup_key(number, hash)?, + ); + Ok(()) +} + +/// Convert block id to block lookup key. +/// block lookup key is the DB-key header, block and justification are stored under. +/// looks up lookup key by hash from DB as necessary. +pub fn block_id_to_lookup_key( + db: &dyn KeyValueDB, + key_lookup_col: u32, + id: BlockId +) -> Result>, sp_blockchain::Error> where + Block: BlockT, + ::sp_runtime::traits::NumberFor: UniqueSaturatedFrom + UniqueSaturatedInto, +{ + let res = match id { + BlockId::Number(n) => db.get( + key_lookup_col, + number_index_key(n)?.as_ref(), + ), + BlockId::Hash(h) => db.get(key_lookup_col, h.as_ref()), + }; + + res.map_err(db_err) +} + +/// Maps database error to client error +pub fn db_err(err: io::Error) -> sp_blockchain::Error { + sp_blockchain::Error::Backend(format!("{}", err)) +} + +/// Open RocksDB database. +pub fn open_database( + config: &DatabaseSettings, + col_meta: u32, + db_type: &str +) -> sp_blockchain::Result> { + let db: Arc = match &config.source { + #[cfg(feature = "kvdb-rocksdb")] + DatabaseSettingsSrc::Path { path, cache_size } => { + let mut db_config = DatabaseConfig::with_columns(NUM_COLUMNS); + + if let Some(cache_size) = cache_size { + let state_col_budget = (*cache_size as f64 * 0.9) as usize; + let other_col_budget = (cache_size - state_col_budget) / (NUM_COLUMNS as usize - 1); + + let mut memory_budget = std::collections::HashMap::new(); + for i in 0..NUM_COLUMNS { + if i == crate::columns::STATE { + memory_budget.insert(i, state_col_budget); + } else { + memory_budget.insert(i, other_col_budget); + } + } + + db_config.memory_budget = memory_budget; + } + let path = path.to_str() + .ok_or_else(|| sp_blockchain::Error::Backend("Invalid database path".into()))?; + Arc::new(Database::open(&db_config, &path).map_err(db_err)?) + }, + #[cfg(not(feature = "kvdb-rocksdb"))] + DatabaseSettingsSrc::Path { .. } => { + let msg = "Try to open RocksDB database with RocksDB disabled".into(); + return Err(sp_blockchain::Error::Backend(msg)); + }, + DatabaseSettingsSrc::Custom(db) => db.clone(), + }; + + // check database type + match db.get(col_meta, meta_keys::TYPE).map_err(db_err)? { + Some(stored_type) => { + if db_type.as_bytes() != &*stored_type { + return Err(sp_blockchain::Error::Backend( + format!("Unexpected database type. Expected: {}", db_type)).into()); + } + }, + None => { + let mut transaction = DBTransaction::new(); + transaction.put(col_meta, meta_keys::TYPE, db_type.as_bytes()); + db.write(transaction).map_err(db_err)?; + }, + } + + Ok(db) +} + +/// Read database column entry for the given block. +pub fn read_db( + db: &dyn KeyValueDB, + col_index: u32, + col: u32, + id: BlockId +) -> sp_blockchain::Result> + where + Block: BlockT, +{ + block_id_to_lookup_key(db, col_index, id).and_then(|key| match key { + Some(key) => db.get(col, key.as_ref()).map_err(db_err), + None => Ok(None), + }) +} + +/// Read a header from the database. +pub fn read_header( + db: &dyn KeyValueDB, + col_index: u32, + col: u32, + id: BlockId, +) -> sp_blockchain::Result> { + match read_db(db, col_index, col, id)? { + Some(header) => match Block::Header::decode(&mut &header[..]) { + Ok(header) => Ok(Some(header)), + Err(_) => return Err( + sp_blockchain::Error::Backend("Error decoding header".into()) + ), + } + None => Ok(None), + } +} + +/// Required header from the database. +pub fn require_header( + db: &dyn KeyValueDB, + col_index: u32, + col: u32, + id: BlockId, +) -> sp_blockchain::Result { + read_header(db, col_index, col, id) + .and_then(|header| header.ok_or_else(|| sp_blockchain::Error::UnknownBlock(format!("{}", id)))) +} + +/// Read meta from the database. +pub fn read_meta(db: &dyn KeyValueDB, col_meta: u32, col_header: u32) -> Result< + Meta<<::Header as HeaderT>::Number, Block::Hash>, + sp_blockchain::Error, +> + where + Block: BlockT, +{ + let genesis_hash: Block::Hash = match db.get(col_meta, meta_keys::GENESIS_HASH).map_err(db_err)? { + Some(h) => match Decode::decode(&mut &h[..]) { + Ok(h) => h, + Err(err) => return Err(sp_blockchain::Error::Backend( + format!("Error decoding genesis hash: {}", err) + )), + }, + None => return Ok(Meta { + best_hash: Default::default(), + best_number: Zero::zero(), + finalized_hash: Default::default(), + finalized_number: Zero::zero(), + genesis_hash: Default::default(), + }), + }; + + let load_meta_block = |desc, key| -> Result<_, sp_blockchain::Error> { + if let Some(Some(header)) = db.get(col_meta, key).and_then(|id| + match id { + Some(id) => db.get(col_header, &id).map(|h| h.map(|b| Block::Header::decode(&mut &b[..]).ok())), + None => Ok(None), + }).map_err(db_err)? + { + let hash = header.hash(); + debug!("DB Opened blockchain db, fetched {} = {:?} ({})", desc, hash, header.number()); + Ok((hash, *header.number())) + } else { + Ok((genesis_hash.clone(), Zero::zero())) + } + }; + + let (best_hash, best_number) = load_meta_block("best", meta_keys::BEST_BLOCK)?; + let (finalized_hash, finalized_number) = load_meta_block("final", meta_keys::FINALIZED_BLOCK)?; + + Ok(Meta { + best_hash, + best_number, + finalized_hash, + finalized_number, + genesis_hash, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper}; + type Block = RawBlock>; + + #[test] + fn number_index_key_doesnt_panic() { + let id = BlockId::::Number(72340207214430721); + match id { + BlockId::Number(n) => number_index_key(n).expect_err("number should overflow u32"), + _ => unreachable!(), + }; + } +} diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml new file mode 100644 index 0000000000000..a2f6ebaac0e3c --- /dev/null +++ b/client/executor/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "sc-executor" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +derive_more = "0.99.2" +codec = { package = "parity-scale-codec", version = "1.0.0" } +sp-io = { version = "2.0.0", path = "../../primitives/io" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-trie = { version = "2.0.0", path = "../../primitives/trie" } +sp-serializer = { version = "2.0.0", path = "../../primitives/serializer" } +sp-version = { version = "2.0.0", path = "../../primitives/version" } +sp-panic-handler = { version = "2.0.0", path = "../../primitives/panic-handler" } +wasmi = "0.6.2" +parity-wasm = "0.41.0" +lazy_static = "1.4.0" +sp-wasm-interface = { version = "2.0.0", path = "../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0", path = "../../primitives/runtime-interface" } +sp-externalities = { version = "2.0.0", path = "../../primitives/externalities" } +sc-executor-common = { version = "2.0.0", path = "common" } +sc-executor-wasmi = { version = "2.0.0", path = "wasmi" } +sc-executor-wasmtime = { version = "2.0.0", path = "wasmtime", optional = true } +parking_lot = "0.9.0" +log = "0.4.8" +libsecp256k1 = "0.3.4" + +[dev-dependencies] +assert_matches = "1.3.0" +wabt = "0.9.2" +hex-literal = "0.2.1" +sc-runtime-test = { version = "2.0.0", path = "runtime-test" } +substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } +test-case = "0.3.3" + +[features] +default = [ "std" ] +# This crate does not have `no_std` support, we just require this for tests +std = [] +wasm-extern-trace = [] +wasmtime = [ + "sc-executor-wasmtime", +] +wasmi-errno = [ + "wasmi/errno" +] diff --git a/client/executor/common/Cargo.toml b/client/executor/common/Cargo.toml new file mode 100644 index 0000000000000..ddd40de62bbb1 --- /dev/null +++ b/client/executor/common/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "sc-executor-common" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4.8" +derive_more = "0.99.2" +codec = { package = "parity-scale-codec", version = "1.0.0" } +wasmi = "0.6.2" +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-wasm-interface = { version = "2.0.0", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0", path = "../../../primitives/runtime-interface" } +sp-serializer = { version = "2.0.0", path = "../../../primitives/serializer" } + +[features] +default = [] diff --git a/core/executor/src/allocator.rs b/client/executor/common/src/allocator.rs similarity index 98% rename from core/executor/src/allocator.rs rename to client/executor/common/src/allocator.rs index 523499db71c6b..feab044f69c32 100644 --- a/core/executor/src/allocator.rs +++ b/client/executor/common/src/allocator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -50,7 +50,7 @@ use crate::error::{Error, Result}; use log::trace; use std::convert::{TryFrom, TryInto}; use std::ops::Range; -use wasm_interface::{Pointer, WordSize}; +use sp_wasm_interface::{Pointer, WordSize}; // The pointers need to be aligned to 8 bytes. This is because the // maximum value type handled by wasm32 is u64. @@ -69,6 +69,9 @@ const MIN_POSSIBLE_ALLOCATION: u32 = 8; // to which it belongs. const PREFIX_SIZE: u32 = 8; +/// An implementation of freeing bump allocator. +/// +/// Refer to the module-level documentation for further details. pub struct FreeingBumpHeapAllocator { bumper: u32, heads: [u32; N], diff --git a/client/executor/common/src/error.rs b/client/executor/common/src/error.rs new file mode 100644 index 0000000000000..fca17bd88c8ea --- /dev/null +++ b/client/executor/common/src/error.rs @@ -0,0 +1,135 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Rust executor possible errors. + +use sp_serializer; +use wasmi; + +/// Result type alias. +pub type Result = std::result::Result; + +/// Error type. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Unserializable Data + InvalidData(sp_serializer::Error), + /// Trap occured during execution + Trap(wasmi::Trap), + /// Wasmi loading/instantiating error + Wasmi(wasmi::Error), + /// Error in the API. Parameter is an error message. + #[from(ignore)] + ApiError(String), + /// Method is not found + #[display(fmt="Method not found: '{}'", _0)] + #[from(ignore)] + MethodNotFound(String), + /// Code is invalid (expected single byte) + #[display(fmt="Invalid Code: {}", _0)] + #[from(ignore)] + InvalidCode(String), + /// Could not get runtime version. + #[display(fmt="On-chain runtime does not specify version")] + VersionInvalid, + /// Externalities have failed. + #[display(fmt="Externalities error")] + Externalities, + /// Invalid index. + #[display(fmt="Invalid index provided")] + InvalidIndex, + /// Invalid return type. + #[display(fmt="Invalid type returned (should be u64)")] + InvalidReturn, + /// Runtime failed. + #[display(fmt="Runtime error")] + Runtime, + /// Invalid memory reference. + #[display(fmt="Invalid memory reference")] + InvalidMemoryReference, + /// The runtime must provide a global named `__heap_base` of type i32 for specifying where the + /// allocator is allowed to place its data. + #[display(fmt="The runtime doesn't provide a global named `__heap_base`")] + HeapBaseNotFoundOrInvalid, + /// The runtime WebAssembly module is not allowed to have the `start` function. + #[display(fmt="The runtime has the `start` function")] + RuntimeHasStartFn, + /// Some other error occurred + #[from(ignore)] + Other(String), + /// Some error occurred in the allocator + #[display(fmt="Error in allocator: {}", _0)] + Allocator(&'static str), + /// The allocator ran out of space. + #[display(fmt="Allocator ran out of space")] + AllocatorOutOfSpace, + /// Someone tried to allocate more memory than the allowed maximum per allocation. + #[display(fmt="Requested allocation size is too large")] + RequestedAllocationTooLarge, + /// Execution of a host function failed. + #[display(fmt="Host function {} execution failed with: {}", _0, _1)] + FunctionExecution(String, String), +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::InvalidData(ref err) => Some(err), + Error::Trap(ref err) => Some(err), + Error::Wasmi(ref err) => Some(err), + _ => None, + } + } +} + +impl wasmi::HostError for Error {} + +impl From for Error { + fn from(err: String) -> Error { + Error::Other(err) + } +} + +impl From for Error { + fn from(err: WasmError) -> Error { + Error::Other(err.to_string()) + } +} + +/// Type for errors occurring during Wasm runtime construction. +#[derive(Debug, derive_more::Display)] +pub enum WasmError { + /// Code could not be read from the state. + CodeNotFound, + /// Failure to reinitialize runtime instance from snapshot. + ApplySnapshotFailed, + /// Failure to erase the wasm memory. + /// + /// Depending on the implementation might mean failure of allocating memory. + ErasingFailed(String), + /// Wasm code failed validation. + InvalidModule, + /// Wasm code could not be deserialized. + CantDeserializeWasm, + /// The module does not export a linear memory named `memory`. + InvalidMemory, + /// The number of heap pages requested is disallowed by the module. + InvalidHeapPages, + /// Instantiation error. + Instantiation(String), + /// Other error happenend. + Other(String), +} diff --git a/client/executor/common/src/lib.rs b/client/executor/common/src/lib.rs new file mode 100644 index 0000000000000..69f6a710b316c --- /dev/null +++ b/client/executor/common/src/lib.rs @@ -0,0 +1,24 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A set of common definitions that are needed for defining execution engines. + +#![warn(missing_docs)] + +pub mod sandbox; +pub mod allocator; +pub mod error; +pub mod wasm_runtime; diff --git a/client/executor/common/src/sandbox.rs b/client/executor/common/src/sandbox.rs new file mode 100644 index 0000000000000..e48afd4891721 --- /dev/null +++ b/client/executor/common/src/sandbox.rs @@ -0,0 +1,585 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This module implements sandboxing support in the runtime. +//! +//! Sandboxing is baked by wasmi at the moment. In future, however, we would like to add/switch to +//! a compiled execution engine. + +use crate::error::{Result, Error}; +use std::{collections::HashMap, rc::Rc}; +use codec::{Decode, Encode}; +use sp_core::sandbox as sandbox_primitives; +use wasmi::{ + Externals, ImportResolver, MemoryInstance, MemoryRef, Module, ModuleInstance, + ModuleRef, RuntimeArgs, RuntimeValue, Trap, TrapKind, memory_units::Pages, +}; +use sp_wasm_interface::{Pointer, WordSize}; + +/// Index of a function inside the supervisor. +/// +/// This is a typically an index in the default table of the supervisor, however +/// the exact meaning of this index is depends on the implementation of dispatch function. +#[derive(Copy, Clone, Debug, PartialEq)] +pub struct SupervisorFuncIndex(usize); + +impl From for usize { + fn from(index: SupervisorFuncIndex) -> Self { + index.0 + } +} + +/// Index of a function within guest index space. +/// +/// This index is supposed to be used with as index for `Externals`. +#[derive(Copy, Clone, Debug, PartialEq)] +struct GuestFuncIndex(usize); + +/// This struct holds a mapping from guest index space to supervisor. +struct GuestToSupervisorFunctionMapping { + funcs: Vec, +} + +impl GuestToSupervisorFunctionMapping { + fn new() -> GuestToSupervisorFunctionMapping { + GuestToSupervisorFunctionMapping { funcs: Vec::new() } + } + + fn define(&mut self, supervisor_func: SupervisorFuncIndex) -> GuestFuncIndex { + let idx = self.funcs.len(); + self.funcs.push(supervisor_func); + GuestFuncIndex(idx) + } + + fn func_by_guest_index(&self, guest_func_idx: GuestFuncIndex) -> Option { + self.funcs.get(guest_func_idx.0).cloned() + } +} + +struct Imports { + func_map: HashMap<(Vec, Vec), GuestFuncIndex>, + memories_map: HashMap<(Vec, Vec), MemoryRef>, +} + +impl ImportResolver for Imports { + fn resolve_func( + &self, + module_name: &str, + field_name: &str, + signature: &::wasmi::Signature, + ) -> std::result::Result { + let key = ( + module_name.as_bytes().to_owned(), + field_name.as_bytes().to_owned(), + ); + let idx = *self.func_map.get(&key).ok_or_else(|| { + wasmi::Error::Instantiation(format!( + "Export {}:{} not found", + module_name, field_name + )) + })?; + Ok(wasmi::FuncInstance::alloc_host(signature.clone(), idx.0)) + } + + fn resolve_memory( + &self, + module_name: &str, + field_name: &str, + _memory_type: &::wasmi::MemoryDescriptor, + ) -> std::result::Result { + let key = ( + module_name.as_bytes().to_vec(), + field_name.as_bytes().to_vec(), + ); + let mem = self.memories_map + .get(&key) + .ok_or_else(|| { + wasmi::Error::Instantiation(format!( + "Export {}:{} not found", + module_name, field_name + )) + })? + .clone(); + Ok(mem) + } + + fn resolve_global( + &self, + module_name: &str, + field_name: &str, + _global_type: &::wasmi::GlobalDescriptor, + ) -> std::result::Result { + Err(wasmi::Error::Instantiation(format!( + "Export {}:{} not found", + module_name, field_name + ))) + } + + fn resolve_table( + &self, + module_name: &str, + field_name: &str, + _table_type: &::wasmi::TableDescriptor, + ) -> std::result::Result { + Err(wasmi::Error::Instantiation(format!( + "Export {}:{} not found", + module_name, field_name + ))) + } +} + +/// This trait encapsulates sandboxing capabilities. +/// +/// Note that this functions are only called in the `supervisor` context. +pub trait SandboxCapabilities { + /// Represents a function reference into the supervisor environment. + type SupervisorFuncRef; + + /// Returns a reference to an associated sandbox `Store`. + fn store(&self) -> &Store; + + /// Returns a mutable reference to an associated sandbox `Store`. + fn store_mut(&mut self) -> &mut Store; + + /// 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: WordSize) -> 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: Pointer) -> Result<()>; + + /// Write `data` into the supervisor memory at offset specified by `ptr`. + /// + /// # Errors + /// + /// Returns `Err` if `ptr + data.len()` is out of bounds. + fn write_memory(&mut self, ptr: Pointer, data: &[u8]) -> Result<()>; + + /// Read `len` bytes from the supervisor memory. + /// + /// # Errors + /// + /// Returns `Err` if `ptr + len` is out of bounds. + fn read_memory(&self, ptr: Pointer, len: WordSize) -> Result>; + + /// Invoke a function in the supervisor environment. + /// + /// This first invokes the dispatch_thunk function, passing in the function index of the + /// desired function to call and serialized arguments. The thunk calls the desired function + /// with the deserialized arguments, then serializes the result into memory and returns + /// reference. The pointer to and length of the result in linear memory is encoded into an i64, + /// with the upper 32 bits representing the pointer and the lower 32 bits representing the + /// length. + /// + /// # Errors + /// + /// Returns `Err` if the dispatch_thunk function has an incorrect signature or traps during + /// execution. + fn invoke( + &mut self, + dispatch_thunk: &Self::SupervisorFuncRef, + invoke_args_ptr: Pointer, + invoke_args_len: WordSize, + state: u32, + func_idx: SupervisorFuncIndex, + ) -> Result; +} + +/// Implementation of [`Externals`] that allows execution of guest module with +/// [externals][`Externals`] that might refer functions defined by supervisor. +/// +/// [`Externals`]: ../wasmi/trait.Externals.html +pub struct GuestExternals<'a, FE: SandboxCapabilities + 'a> { + supervisor_externals: &'a mut FE, + sandbox_instance: &'a SandboxInstance, + state: u32, +} + +fn trap(msg: &'static str) -> Trap { + TrapKind::Host(Box::new(Error::Other(msg.into()))).into() +} + +fn deserialize_result(serialized_result: &[u8]) -> std::result::Result, Trap> { + use self::sandbox_primitives::{HostError, ReturnValue}; + let result_val = std::result::Result::::decode(&mut &serialized_result[..]) + .map_err(|_| trap("Decoding Result failed!"))?; + + match result_val { + Ok(return_value) => Ok(match return_value { + ReturnValue::Unit => None, + ReturnValue::Value(typed_value) => Some(RuntimeValue::from(typed_value)), + }), + Err(HostError) => Err(trap("Supervisor function returned sandbox::HostError")), + } +} + +impl<'a, FE: SandboxCapabilities + 'a> Externals for GuestExternals<'a, FE> { + fn invoke_index( + &mut self, + index: usize, + args: RuntimeArgs, + ) -> std::result::Result, Trap> { + // Make `index` typesafe again. + let index = GuestFuncIndex(index); + + let func_idx = self.sandbox_instance + .guest_to_supervisor_mapping + .func_by_guest_index(index) + .expect( + "`invoke_index` is called with indexes registered via `FuncInstance::alloc_host`; + `FuncInstance::alloc_host` is called with indexes that was obtained from `guest_to_supervisor_mapping`; + `func_by_guest_index` called with `index` can't return `None`; + qed" + ); + + // Serialize arguments into a byte vector. + let invoke_args_data: Vec = args.as_ref() + .iter() + .cloned() + .map(sandbox_primitives::TypedValue::from) + .collect::>() + .encode(); + + let state = self.state; + + // Move serialized arguments inside the memory and invoke dispatch thunk and + // then free allocated memory. + let invoke_args_len = invoke_args_data.len() as WordSize; + let invoke_args_ptr = self.supervisor_externals.allocate(invoke_args_len)?; + self.supervisor_externals.write_memory(invoke_args_ptr, &invoke_args_data)?; + let result = self.supervisor_externals.invoke( + &self.sandbox_instance.dispatch_thunk, + invoke_args_ptr, + invoke_args_len, + state, + func_idx, + )?; + self.supervisor_externals.deallocate(invoke_args_ptr)?; + + // dispatch_thunk returns pointer to serialized arguments. + // Unpack pointer and len of the serialized result data. + let (serialized_result_val_ptr, serialized_result_val_len) = { + // Cast to u64 to use zero-extension. + let v = result as u64; + let ptr = (v as u64 >> 32) as u32; + let len = (v & 0xFFFFFFFF) as u32; + (Pointer::new(ptr), len) + }; + + let serialized_result_val = self.supervisor_externals + .read_memory(serialized_result_val_ptr, serialized_result_val_len)?; + self.supervisor_externals + .deallocate(serialized_result_val_ptr)?; + + deserialize_result(&serialized_result_val) + } +} + +fn with_guest_externals( + supervisor_externals: &mut FE, + sandbox_instance: &SandboxInstance, + state: u32, + f: F, +) -> R +where + FE: SandboxCapabilities, + F: FnOnce(&mut GuestExternals) -> R, +{ + let mut guest_externals = GuestExternals { + supervisor_externals, + sandbox_instance, + state, + }; + f(&mut guest_externals) +} + +/// Sandboxed instance of a wasm module. +/// +/// It's primary purpose is to [`invoke`] exported functions on it. +/// +/// All imports of this instance are specified at the creation time and +/// imports are implemented by the supervisor. +/// +/// Hence, in order to invoke an exported function on a sandboxed module instance, +/// it's required to provide supervisor externals: it will be used to execute +/// code in the supervisor context. +/// +/// This is generic over a supervisor function reference type. +/// +/// [`invoke`]: #method.invoke +pub struct SandboxInstance { + instance: ModuleRef, + dispatch_thunk: FR, + guest_to_supervisor_mapping: GuestToSupervisorFunctionMapping, +} + +impl SandboxInstance { + /// Invoke an exported function by a name. + /// + /// `supervisor_externals` is required to execute the implementations + /// of the syscalls that published to a sandboxed module instance. + /// + /// The `state` parameter can be used to provide custom data for + /// these syscall implementations. + pub fn invoke>( + &self, + export_name: &str, + args: &[RuntimeValue], + supervisor_externals: &mut FE, + state: u32, + ) -> std::result::Result, wasmi::Error> { + with_guest_externals( + supervisor_externals, + self, + state, + |guest_externals| { + self.instance + .invoke_export(export_name, args, guest_externals) + }, + ) + } +} + +/// Error occurred during instantiation of a sandboxed module. +pub enum InstantiationError { + /// Something wrong with the environment definition. It either can't + /// be decoded, have a reference to a non-existent or torn down memory instance. + EnvironmentDefinitionCorrupted, + /// Provided module isn't recognized as a valid webassembly binary. + ModuleDecoding, + /// Module is a well-formed webassembly binary but could not be instantiated. This could + /// happen because, e.g. the module imports entries not provided by the environment. + Instantiation, + /// Module is well-formed, instantiated and linked, but while executing the start function + /// a trap was generated. + StartTrapped, +} + +fn decode_environment_definition( + raw_env_def: &[u8], + memories: &[Option], +) -> std::result::Result<(Imports, GuestToSupervisorFunctionMapping), InstantiationError> { + let env_def = sandbox_primitives::EnvironmentDefinition::decode(&mut &raw_env_def[..]) + .map_err(|_| InstantiationError::EnvironmentDefinitionCorrupted)?; + + let mut func_map = HashMap::new(); + let mut memories_map = HashMap::new(); + let mut guest_to_supervisor_mapping = GuestToSupervisorFunctionMapping::new(); + + for entry in &env_def.entries { + let module = entry.module_name.clone(); + let field = entry.field_name.clone(); + + match entry.entity { + sandbox_primitives::ExternEntity::Function(func_idx) => { + let externals_idx = + guest_to_supervisor_mapping.define(SupervisorFuncIndex(func_idx as usize)); + func_map.insert((module, field), externals_idx); + } + sandbox_primitives::ExternEntity::Memory(memory_idx) => { + let memory_ref = memories + .get(memory_idx as usize) + .cloned() + .ok_or_else(|| InstantiationError::EnvironmentDefinitionCorrupted)? + .ok_or_else(|| InstantiationError::EnvironmentDefinitionCorrupted)?; + memories_map.insert((module, field), memory_ref); + } + } + } + + Ok(( + Imports { + func_map, + memories_map, + }, + guest_to_supervisor_mapping, + )) +} + +/// Instantiate a guest module and return it's index in the store. +/// +/// The guest module's code is specified in `wasm`. Environment that will be available to +/// guest module is specified in `raw_env_def` (serialized version of [`EnvironmentDefinition`]). +/// `dispatch_thunk` is used as function that handle calls from guests. +/// +/// # Errors +/// +/// Returns `Err` if any of the following conditions happens: +/// +/// - `raw_env_def` can't be deserialized as a [`EnvironmentDefinition`]. +/// - Module in `wasm` is invalid or couldn't be instantiated. +/// +/// [`EnvironmentDefinition`]: ../sandbox/struct.EnvironmentDefinition.html +pub fn instantiate( + supervisor_externals: &mut FE, + dispatch_thunk: FE::SupervisorFuncRef, + wasm: &[u8], + raw_env_def: &[u8], + state: u32, +) -> std::result::Result { + let (imports, guest_to_supervisor_mapping) = + decode_environment_definition(raw_env_def, &supervisor_externals.store().memories)?; + + let module = Module::from_buffer(wasm).map_err(|_| InstantiationError::ModuleDecoding)?; + let instance = ModuleInstance::new(&module, &imports).map_err(|_| InstantiationError::Instantiation)?; + + let sandbox_instance = Rc::new(SandboxInstance { + // In general, it's not a very good idea to use `.not_started_instance()` for anything + // but for extracting memory and tables. But in this particular case, we are extracting + // for the purpose of running `start` function which should be ok. + instance: instance.not_started_instance().clone(), + dispatch_thunk, + guest_to_supervisor_mapping, + }); + + with_guest_externals( + supervisor_externals, + &sandbox_instance, + state, + |guest_externals| { + instance + .run_start(guest_externals) + .map_err(|_| InstantiationError::StartTrapped) + }, + )?; + + // At last, register the instance. + let instance_idx = supervisor_externals + .store_mut() + .register_sandbox_instance(sandbox_instance); + Ok(instance_idx) +} + +/// This struct keeps track of all sandboxed components. +/// +/// This is generic over a supervisor function reference type. +pub struct Store { + // Memories and instances are `Some` untill torndown. + instances: Vec>>>, + memories: Vec>, +} + +impl Store { + /// Create a new empty sandbox store. + pub fn new() -> Self { + Store { + instances: Vec::new(), + memories: Vec::new(), + } + } + + /// Create a new memory instance and return it's index. + /// + /// # Errors + /// + /// Returns `Err` if the memory couldn't be created. + /// Typically happens if `initial` is more than `maximum`. + pub fn new_memory(&mut self, initial: u32, maximum: u32) -> Result { + let maximum = match maximum { + sandbox_primitives::MEM_UNLIMITED => None, + specified_limit => Some(Pages(specified_limit as usize)), + }; + + let mem = + MemoryInstance::alloc( + Pages(initial as usize), + maximum, + )?; + + let mem_idx = self.memories.len(); + self.memories.push(Some(mem)); + Ok(mem_idx as u32) + } + + /// Returns `SandboxInstance` by `instance_idx`. + /// + /// # Errors + /// + /// Returns `Err` If `instance_idx` isn't a valid index of an instance or + /// instance is already torndown. + pub fn instance(&self, instance_idx: u32) -> Result>> { + self.instances + .get(instance_idx as usize) + .cloned() + .ok_or_else(|| "Trying to access a non-existent instance")? + .ok_or_else(|| "Trying to access a torndown instance".into()) + } + + /// Returns reference to a memory instance by `memory_idx`. + /// + /// # Errors + /// + /// Returns `Err` If `memory_idx` isn't a valid index of an memory or + /// if memory has been torn down. + pub fn memory(&self, memory_idx: u32) -> Result { + self.memories + .get(memory_idx as usize) + .cloned() + .ok_or_else(|| "Trying to access a non-existent sandboxed memory")? + .ok_or_else(|| "Trying to access a torndown sandboxed memory".into()) + } + + /// Tear down the memory at the specified index. + /// + /// # Errors + /// + /// Returns `Err` if `memory_idx` isn't a valid index of an memory or + /// if it has been torn down. + pub fn memory_teardown(&mut self, memory_idx: u32) -> Result<()> { + match self.memories.get_mut(memory_idx as usize) { + None => Err("Trying to teardown a non-existent sandboxed memory".into()), + Some(None) => Err("Double teardown of a sandboxed memory".into()), + Some(memory) => { + *memory = None; + Ok(()) + } + } + } + + /// Tear down the instance at the specified index. + /// + /// # Errors + /// + /// Returns `Err` if `instance_idx` isn't a valid index of an instance or + /// if it has been torn down. + pub fn instance_teardown(&mut self, instance_idx: u32) -> Result<()> { + match self.instances.get_mut(instance_idx as usize) { + None => Err("Trying to teardown a non-existent instance".into()), + Some(None) => Err("Double teardown of an instance".into()), + Some(instance) => { + *instance = None; + Ok(()) + } + } + } + + fn register_sandbox_instance(&mut self, sandbox_instance: Rc>) -> u32 { + let instance_idx = self.instances.len(); + self.instances.push(Some(sandbox_instance)); + instance_idx as u32 + } +} diff --git a/client/executor/common/src/wasm_runtime.rs b/client/executor/common/src/wasm_runtime.rs new file mode 100644 index 0000000000000..78c05c4c29b68 --- /dev/null +++ b/client/executor/common/src/wasm_runtime.rs @@ -0,0 +1,39 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Definitions for a wasm runtime. + +use crate::error::Error; +use sp_core::traits::Externalities; +use sp_wasm_interface::Function; + +/// A trait that defines an abstract wasm runtime. +/// +/// This can be implemented by an execution engine. +pub trait WasmRuntime { + /// Attempt to update the number of heap pages available during execution. + /// + /// Returns false if the update cannot be applied. The function is guaranteed to return true if + /// the heap pages would not change from its current value. + fn update_heap_pages(&mut self, heap_pages: u64) -> bool; + + /// Return the host functions that are registered for this Wasm runtime. + fn host_functions(&self) -> &[&'static dyn Function]; + + /// Call a method in the Substrate runtime by name. Returns the encoded result on success. + fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) + -> Result, Error>; +} diff --git a/client/executor/runtime-test/Cargo.toml b/client/executor/runtime-test/Cargo.toml new file mode 100644 index 0000000000000..ba88550a92ef7 --- /dev/null +++ b/client/executor/runtime-test/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "sc-runtime-test" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" + +[dependencies] +sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../../primitives/io" } +sp-sandbox = { version = "2.0.0", default-features = false, path = "../../../primitives/sandbox" } +sp-core = { version = "2.0.0", default-features = false, path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" } + +[build-dependencies] +wasm-builder-runner = { version = "1.0.4", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } + +[features] +default = [ "std" ] +std = ["sp-io/std", "sp-sandbox/std", "sp-std/std"] diff --git a/client/executor/runtime-test/build.rs b/client/executor/runtime-test/build.rs new file mode 100644 index 0000000000000..1ed2fa43e685c --- /dev/null +++ b/client/executor/runtime-test/build.rs @@ -0,0 +1,30 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; + +fn main() { + build_current_project_with_rustflags( + "wasm_binary.rs", + WasmBuilderSource::CratesOrPath { + path: "../../../utils/wasm-builder", + version: "1.0.8", + }, + // This instructs LLD to export __heap_base as a global variable, which is used by the + // external memory allocator. + "-Clink-arg=--export=__heap_base", + ); +} diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs new file mode 100644 index 0000000000000..a8d329cdd9607 --- /dev/null +++ b/client/executor/runtime-test/src/lib.rs @@ -0,0 +1,274 @@ +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "strict", deny(warnings))] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +#[cfg(not(feature = "std"))] +use sp_std::{vec::Vec, vec}; + +#[cfg(not(feature = "std"))] +use sp_io::{ + storage, hashing::{blake2_128, blake2_256, sha2_256, twox_128, twox_256}, + crypto::{ed25519_verify, sr25519_verify}, +}; +#[cfg(not(feature = "std"))] +use sp_runtime::{print, traits::{BlakeTwo256, Hash}}; +#[cfg(not(feature = "std"))] +use sp_core::{ed25519, sr25519}; + +extern "C" { + #[allow(dead_code)] + fn missing_external(); + + #[allow(dead_code)] + fn yet_another_missing_external(); +} + +sp_core::wasm_export_functions! { + fn test_calling_missing_external() { + unsafe { missing_external() } + } + + fn test_calling_yet_another_missing_external() { + unsafe { yet_another_missing_external() } + } + + fn test_data_in(input: Vec) -> Vec { + print("set_storage"); + storage::set(b"input", &input); + + print("storage"); + let foo = storage::get(b"foo").unwrap(); + + print("set_storage"); + storage::set(b"baz", &foo); + + print("finished!"); + b"all ok!".to_vec() + } + + fn test_clear_prefix(input: Vec) -> Vec { + storage::clear_prefix(&input); + b"all ok!".to_vec() + } + + fn test_empty_return() {} + + fn test_exhaust_heap() -> Vec { Vec::with_capacity(16777216) } + + fn test_panic() { panic!("test panic") } + + fn test_conditional_panic(input: Vec) -> Vec { + if input.len() > 0 { + panic!("test panic") + } + + input + } + + fn test_blake2_256(input: Vec) -> Vec { + blake2_256(&input).to_vec() + } + + fn test_blake2_128(input: Vec) -> Vec { + blake2_128(&input).to_vec() + } + + fn test_sha2_256(input: Vec) -> Vec { + sha2_256(&input).to_vec() + } + + fn test_twox_256(input: Vec) -> Vec { + twox_256(&input).to_vec() + } + + fn test_twox_128(input: Vec) -> Vec { + twox_128(&input).to_vec() + } + + fn test_ed25519_verify(input: Vec) -> bool { + let mut pubkey = [0; 32]; + let mut sig = [0; 64]; + + pubkey.copy_from_slice(&input[0..32]); + sig.copy_from_slice(&input[32..96]); + + let msg = b"all ok!"; + ed25519_verify(&ed25519::Signature(sig), &msg[..], &ed25519::Public(pubkey)) + } + + fn test_sr25519_verify(input: Vec) -> bool { + let mut pubkey = [0; 32]; + let mut sig = [0; 64]; + + pubkey.copy_from_slice(&input[0..32]); + sig.copy_from_slice(&input[32..96]); + + let msg = b"all ok!"; + sr25519_verify(&sr25519::Signature(sig), &msg[..], &sr25519::Public(pubkey)) + } + + fn test_ordered_trie_root() -> Vec { + BlakeTwo256::ordered_trie_root( + vec![ + b"zero"[..].into(), + b"one"[..].into(), + b"two"[..].into(), + ], + ).as_ref().to_vec() + } + + fn test_sandbox(code: Vec) -> bool { + execute_sandboxed(&code, &[]).is_ok() + } + + fn test_sandbox_args(code: Vec) -> bool { + execute_sandboxed( + &code, + &[ + sp_sandbox::TypedValue::I32(0x12345678), + sp_sandbox::TypedValue::I64(0x1234567887654321), + ], + ).is_ok() + } + + fn test_sandbox_return_val(code: Vec) -> bool { + let ok = match execute_sandboxed( + &code, + &[ + sp_sandbox::TypedValue::I32(0x1336), + ] + ) { + Ok(sp_sandbox::ReturnValue::Value(sp_sandbox::TypedValue::I32(0x1337))) => true, + _ => false, + }; + + ok + } + + fn test_sandbox_instantiate(code: Vec) -> u8 { + let env_builder = sp_sandbox::EnvironmentDefinitionBuilder::new(); + let code = match sp_sandbox::Instance::new(&code, &env_builder, &mut ()) { + Ok(_) => 0, + Err(sp_sandbox::Error::Module) => 1, + Err(sp_sandbox::Error::Execution) => 2, + Err(sp_sandbox::Error::OutOfBounds) => 3, + }; + + code + } + + fn test_offchain_local_storage() -> bool { + let kind = sp_core::offchain::StorageKind::PERSISTENT; + assert_eq!(sp_io::offchain::local_storage_get(kind, b"test"), None); + sp_io::offchain::local_storage_set(kind, b"test", b"asd"); + assert_eq!(sp_io::offchain::local_storage_get(kind, b"test"), Some(b"asd".to_vec())); + + let res = sp_io::offchain::local_storage_compare_and_set( + kind, + b"test", + Some(b"asd".to_vec()), + b"", + ); + assert_eq!(sp_io::offchain::local_storage_get(kind, b"test"), Some(b"".to_vec())); + res + } + + fn test_offchain_local_storage_with_none() { + let kind = sp_core::offchain::StorageKind::PERSISTENT; + assert_eq!(sp_io::offchain::local_storage_get(kind, b"test"), None); + + let res = sp_io::offchain::local_storage_compare_and_set(kind, b"test", None, b"value"); + assert_eq!(res, true); + assert_eq!(sp_io::offchain::local_storage_get(kind, b"test"), Some(b"value".to_vec())); + } + + fn test_offchain_http() -> bool { + use sp_core::offchain::HttpRequestStatus; + let run = || -> Option<()> { + let id = sp_io::offchain::http_request_start( + "POST", + "http://localhost:12345", + &[], + ).ok()?; + sp_io::offchain::http_request_add_header(id, "X-Auth", "test").ok()?; + sp_io::offchain::http_request_write_body(id, &[1, 2, 3, 4], None).ok()?; + sp_io::offchain::http_request_write_body(id, &[], None).ok()?; + let status = sp_io::offchain::http_response_wait(&[id], None); + assert!(status == vec![HttpRequestStatus::Finished(200)], "Expected Finished(200) status."); + let headers = sp_io::offchain::http_response_headers(id); + assert_eq!(headers, vec![(b"X-Auth".to_vec(), b"hello".to_vec())]); + let mut buffer = vec![0; 64]; + let read = sp_io::offchain::http_response_read_body(id, &mut buffer, None).ok()?; + assert_eq!(read, 3); + assert_eq!(&buffer[0..read as usize], &[1, 2, 3]); + let read = sp_io::offchain::http_response_read_body(id, &mut buffer, None).ok()?; + assert_eq!(read, 0); + + Some(()) + }; + + run().is_some() + } + } + +#[cfg(not(feature = "std"))] +fn execute_sandboxed( + code: &[u8], + args: &[sp_sandbox::TypedValue], +) -> Result { + struct State { + counter: u32, + } + + fn env_assert( + _e: &mut State, + args: &[sp_sandbox::TypedValue], + ) -> Result { + if args.len() != 1 { + return Err(sp_sandbox::HostError); + } + let condition = args[0].as_i32().ok_or_else(|| sp_sandbox::HostError)?; + if condition != 0 { + Ok(sp_sandbox::ReturnValue::Unit) + } else { + Err(sp_sandbox::HostError) + } + } + fn env_inc_counter( + e: &mut State, + args: &[sp_sandbox::TypedValue], + ) -> Result { + if args.len() != 1 { + return Err(sp_sandbox::HostError); + } + let inc_by = args[0].as_i32().ok_or_else(|| sp_sandbox::HostError)?; + e.counter += inc_by as u32; + Ok(sp_sandbox::ReturnValue::Value(sp_sandbox::TypedValue::I32(e.counter as i32))) + } + + let mut state = State { counter: 0 }; + + let env_builder = { + let mut env_builder = sp_sandbox::EnvironmentDefinitionBuilder::new(); + env_builder.add_host_func("env", "assert", env_assert); + env_builder.add_host_func("env", "inc_counter", env_inc_counter); + let memory = match sp_sandbox::Memory::new(1, Some(16)) { + Ok(m) => m, + Err(_) => unreachable!(" + Memory::new() can return Err only if parameters are borked; \ + We passing params here explicitly and they're correct; \ + Memory::new() can't return a Error qed" + ), + }; + env_builder.add_memory("env", "memory", memory.clone()); + env_builder + }; + + let mut instance = sp_sandbox::Instance::new(code, &env_builder, &mut state)?; + let result = instance.invoke("call", args, &mut state); + + result.map_err(|_| sp_sandbox::HostError) +} diff --git a/client/executor/src/deprecated_host_interface.rs b/client/executor/src/deprecated_host_interface.rs new file mode 100644 index 0000000000000..6ea0b11f5a909 --- /dev/null +++ b/client/executor/src/deprecated_host_interface.rs @@ -0,0 +1,941 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Definition and implementation of the old and deprecated Substrate runtime interface for the host. + +use codec::Encode; +use std::{convert::TryFrom, str}; +use sp_core::{ + blake2_128, blake2_256, twox_64, twox_128, twox_256, ed25519, sr25519, keccak_256, Blake2Hasher, Pair, + crypto::KeyTypeId, offchain, +}; +use sp_trie::{TrieConfiguration, trie_types::Layout}; +use sp_wasm_interface::{ + Pointer, WordSize, WritePrimitive, ReadPrimitive, FunctionContext, Result as WResult, +}; + +#[cfg(feature="wasm-extern-trace")] +macro_rules! debug_trace { + ( $( $x:tt )* ) => ( trace!( $( $x )* ) ) +} + +#[cfg(not(feature="wasm-extern-trace"))] +macro_rules! debug_trace { + ( $( $x:tt )* ) => () +} + +/// The old and deprecated Substrate externals. These are still required for backwards compatibility +/// reasons. +pub struct SubstrateExternals; + +enum RecoverResult { + Invalid(u32), + Valid(secp256k1::PublicKey), +} + +fn secp256k1_recover( + context: &mut dyn FunctionContext, + msg_data: Pointer, + sig_data: Pointer, +) -> WResult { + let mut sig = [0u8; 65]; + context.read_memory_into(sig_data, &mut sig[..]) + .map_err(|_| "Invalid attempt to get signature in ext_secp256k1_ecdsa_recover")?; + let rs = match secp256k1::Signature::parse_slice(&sig[0..64]) { + Ok(rs) => rs, + _ => return Ok(RecoverResult::Invalid(1)), + }; + + let recovery_id = if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8; + let v = match secp256k1::RecoveryId::parse(recovery_id) { + Ok(v) => v, + _ => return Ok(RecoverResult::Invalid(2)), + }; + + let mut msg = [0u8; 32]; + context.read_memory_into(msg_data, &mut msg[..]) + .map_err(|_| "Invalid attempt to get message in ext_secp256k1_ecdsa_recover")?; + + Ok(match secp256k1::recover(&secp256k1::Message::parse(&msg), &rs, &v) { + Ok(pubkey) => RecoverResult::Valid(pubkey), + Err(_) => RecoverResult::Invalid(3), + }) +} + +impl_wasm_host_interface! { + impl SubstrateExternals where context { + ext_malloc(size: WordSize) -> Pointer { + let r = context.allocate_memory(size)?; + debug_trace!(target: "sp-io", "malloc {} bytes at {:?}", size, r); + Ok(r) + } + + ext_free(addr: Pointer) { + context.deallocate_memory(addr)?; + debug_trace!(target: "sp-io", "free {:?}", addr); + Ok(()) + } + + ext_sandbox_instantiate( + dispatch_thunk_idx: u32, + wasm_ptr: Pointer, + wasm_len: WordSize, + imports_ptr: Pointer, + imports_len: WordSize, + state: u32, + ) -> u32 { + let wasm = context.read_memory(wasm_ptr, wasm_len) + .map_err(|_| "OOB while ext_sandbox_instantiate: wasm")?; + let raw_env_def = context.read_memory(imports_ptr, imports_len) + .map_err(|_| "OOB while ext_sandbox_instantiate: imports")?; + + context.sandbox().instance_new(dispatch_thunk_idx, &wasm, &raw_env_def, state) + } + + ext_sandbox_instance_teardown(instance_idx: u32) { + context.sandbox().instance_teardown(instance_idx) + } + + ext_sandbox_invoke( + instance_idx: u32, + export_ptr: Pointer, + export_len: WordSize, + args_ptr: Pointer, + args_len: WordSize, + return_val_ptr: Pointer, + return_val_len: WordSize, + state: u32, + ) -> u32 { + let export = context.read_memory(export_ptr, export_len) + .map_err(|_| "OOB while ext_sandbox_invoke: export") + .and_then(|b| + String::from_utf8(b) + .map_err(|_| "Export name should be a valid utf-8 sequence") + )?; + + // Deserialize arguments and convert them into wasmi types. + let serialized_args = context.read_memory(args_ptr, args_len) + .map_err(|_| "OOB while ext_sandbox_invoke: args")?; + + context.sandbox().invoke( + instance_idx, + &export, + &serialized_args, + return_val_ptr, + return_val_len, + state, + ) + } + + ext_sandbox_memory_new(initial: WordSize, maximum: WordSize) -> u32 { + context.sandbox().memory_new(initial, maximum) + } + + ext_sandbox_memory_get( + memory_idx: u32, + offset: WordSize, + buf_ptr: Pointer, + buf_len: WordSize, + ) -> u32 { + context.sandbox().memory_get(memory_idx, offset, buf_ptr, buf_len) + } + + ext_sandbox_memory_set( + memory_idx: u32, + offset: WordSize, + val_ptr: Pointer, + val_len: WordSize, + ) -> u32 { + context.sandbox().memory_set(memory_idx, offset, val_ptr, val_len) + } + + ext_sandbox_memory_teardown(memory_idx: u32) { + context.sandbox().memory_teardown(memory_idx) + } + + ext_print_utf8(utf8_data: Pointer, utf8_len: WordSize) { + if let Ok(utf8) = context.read_memory(utf8_data, utf8_len) { + sp_io::misc::print_utf8(&utf8); + } + Ok(()) + } + + ext_print_hex(data: Pointer, len: WordSize) { + if let Ok(hex) = context.read_memory(data, len) { + sp_io::misc::print_hex(&hex); + } + Ok(()) + } + + ext_print_num(number: u64) { + sp_io::misc::print_num(number); + Ok(()) + } + + ext_log( + level: u32, + target_data: Pointer, + target_len: WordSize, + message_data: Pointer, + message_len: WordSize, + ) { + let target = context.read_memory(target_data, target_len) + .map_err(|_| "Invalid attempt to determine target in ext_log")?; + let message = context.read_memory(message_data, message_len) + .map_err(|_| "Invalid attempt to determine message in ext_log")?; + + let target_str = std::str::from_utf8(&target) + .map_err(|_| "Target invalid utf8 in ext_log")?; + + sp_io::logging::log(level.into(), &target_str, &message); + Ok(()) + } + + ext_set_storage( + key_data: Pointer, + key_len: WordSize, + value_data: Pointer, + value_len: WordSize, + ) { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_set_storage")?; + let value = context.read_memory(value_data, value_len) + .map_err(|_| "Invalid attempt to determine value in ext_set_storage")?; + Ok(sp_io::storage::set(&key, &value)) + } + + ext_clear_storage(key_data: Pointer, key_len: WordSize) { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_clear_storage")?; + Ok(sp_io::storage::clear(&key)) + } + + ext_exists_storage(key_data: Pointer, key_len: WordSize) -> u32 { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_exists_storage")?; + Ok(if sp_io::storage::exists(&key) { 1 } else { 0 }) + } + + ext_clear_prefix(prefix_data: Pointer, prefix_len: WordSize) { + let prefix = context.read_memory(prefix_data, prefix_len) + .map_err(|_| "Invalid attempt to determine prefix in ext_clear_prefix")?; + Ok(sp_io::storage::clear_prefix(&prefix)) + } + + ext_get_allocated_storage( + key_data: Pointer, + key_len: WordSize, + written_out: Pointer, + ) -> Pointer { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_get_allocated_storage")?; + + if let Some(value) = sp_io::storage::get(&key) { + let offset = context.allocate_memory(value.len() as u32)?; + context.write_memory(offset, &value) + .map_err(|_| "Invalid attempt to set memory in ext_get_allocated_storage")?; + context.write_primitive(written_out, value.len() as u32) + .map_err(|_| "Invalid attempt to write written_out in ext_get_allocated_storage")?; + Ok(offset) + } else { + context.write_primitive(written_out, u32::max_value()) + .map_err(|_| "Invalid attempt to write failed written_out in ext_get_allocated_storage")?; + Ok(Pointer::null()) + } + } + + ext_get_storage_into( + key_data: Pointer, + key_len: WordSize, + value_data: Pointer, + value_len: WordSize, + value_offset: WordSize, + ) -> WordSize { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to get key in ext_get_storage_into")?; + + if let Some(value) = sp_io::storage::get(&key) { + let data = &value[value.len().min(value_offset as usize)..]; + let written = std::cmp::min(value_len as usize, data.len()); + context.write_memory(value_data, &data[..written]) + .map_err(|_| "Invalid attempt to set value in ext_get_storage_into")?; + Ok(value.len() as u32) + } else { + Ok(u32::max_value()) + } + } + + ext_storage_root(result: Pointer) { + context.write_memory(result, sp_io::storage::root().as_ref()) + .map_err(|_| "Invalid attempt to set memory in ext_storage_root".into()) + } + + ext_storage_changes_root( + parent_hash_data: Pointer, + _len: WordSize, + result: Pointer, + ) -> u32 { + let mut parent_hash = [0u8; 32]; + context.read_memory_into(parent_hash_data, &mut parent_hash[..]) + .map_err(|_| "Invalid attempt to get parent_hash in ext_storage_changes_root")?; + + if let Some(r) = sp_io::storage::changes_root(&parent_hash) { + context.write_memory(result, &r[..]) + .map_err(|_| "Invalid attempt to set memory in ext_storage_changes_root")?; + Ok(1) + } else { + Ok(0) + } + } + + ext_blake2_256_enumerated_trie_root( + values_data: Pointer, + lens_data: Pointer, + lens_len: WordSize, + result: Pointer, + ) { + let values = (0..lens_len) + .map(|i| context.read_primitive(lens_data.offset(i).ok_or("Pointer overflow")?)) + .collect::, _>>()? + .into_iter() + .scan(0u32, |acc, v| { let o = *acc; *acc += v; Some((o, v)) }) + .map(|(offset, len)| + context.read_memory(values_data.offset(offset).ok_or("Pointer overflow")?, len) + .map_err(|_| + "Invalid attempt to get memory in ext_blake2_256_enumerated_trie_root" + ) + ) + .collect::, _>>()?; + let r = Layout::::ordered_trie_root(values.into_iter()); + context.write_memory(result, &r[..]) + .map_err(|_| "Invalid attempt to set memory in ext_blake2_256_enumerated_trie_root")?; + Ok(()) + } + + ext_chain_id() -> u64 { + Ok(sp_io::misc::chain_id()) + } + + ext_twox_64(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 8] = if len == 0 { + let hashed = twox_64(&[0u8; 0]); + hashed + } else { + let key = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get key in ext_twox_64")?; + let hashed_key = twox_64(&key); + hashed_key + }; + + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_twox_64")?; + Ok(()) + } + + ext_twox_128(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 16] = if len == 0 { + let hashed = twox_128(&[0u8; 0]); + hashed + } else { + let key = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get key in ext_twox_128")?; + let hashed_key = twox_128(&key); + hashed_key + }; + + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_twox_128")?; + Ok(()) + } + + ext_twox_256(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 32] = if len == 0 { + twox_256(&[0u8; 0]) + } else { + let mem = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get data in ext_twox_256")?; + twox_256(&mem) + }; + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_twox_256")?; + Ok(()) + } + + ext_blake2_128(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 16] = if len == 0 { + let hashed = blake2_128(&[0u8; 0]); + hashed + } else { + let key = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get key in ext_blake2_128")?; + let hashed_key = blake2_128(&key); + hashed_key + }; + + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_blake2_128")?; + Ok(()) + } + + ext_blake2_256(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 32] = if len == 0 { + blake2_256(&[0u8; 0]) + } else { + let mem = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get data in ext_blake2_256")?; + blake2_256(&mem) + }; + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_blake2_256")?; + Ok(()) + } + + ext_keccak_256(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 32] = if len == 0 { + keccak_256(&[0u8; 0]) + } else { + let mem = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get data in ext_keccak_256")?; + keccak_256(&mem) + }; + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_keccak_256")?; + Ok(()) + } + + ext_ed25519_public_keys(id_data: Pointer, result_len: Pointer) -> Pointer { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_ed25519_public_keys")?; + let key_type = KeyTypeId(id); + + let keys = sp_io::crypto::ed25519_public_keys(key_type).encode(); + + let len = keys.len() as u32; + let offset = context.allocate_memory(len)?; + + context.write_memory(offset, keys.as_ref()) + .map_err(|_| "Invalid attempt to set memory in ext_ed25519_public_keys")?; + context.write_primitive(result_len, len) + .map_err(|_| "Invalid attempt to write result_len in ext_ed25519_public_keys")?; + + Ok(offset) + } + + ext_ed25519_verify( + msg_data: Pointer, + msg_len: WordSize, + sig_data: Pointer, + pubkey_data: Pointer, + ) -> u32 { + let mut sig = [0u8; 64]; + context.read_memory_into(sig_data, &mut sig[..]) + .map_err(|_| "Invalid attempt to get signature in ext_ed25519_verify")?; + let mut pubkey = [0u8; 32]; + context.read_memory_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| "Invalid attempt to get pubkey in ext_ed25519_verify")?; + let msg = context.read_memory(msg_data, msg_len) + .map_err(|_| "Invalid attempt to get message in ext_ed25519_verify")?; + + Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) { + 0 + } else { + 1 + }) + } + + ext_ed25519_generate( + id_data: Pointer, + seed: Pointer, + seed_len: WordSize, + out: Pointer, + ) { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_ed25519_generate")?; + let key_type = KeyTypeId(id); + + let seed = if seed_len == 0 { + None + } else { + Some( + context.read_memory(seed, seed_len) + .map_err(|_| "Invalid attempt to get seed in ext_ed25519_generate")? + ) + }; + + let pubkey = sp_io::crypto::ed25519_generate(key_type, seed); + + context.write_memory(out, pubkey.as_ref()) + .map_err(|_| "Invalid attempt to set out in ext_ed25519_generate".into()) + } + + ext_ed25519_sign( + id_data: Pointer, + pubkey_data: Pointer, + msg_data: Pointer, + msg_len: WordSize, + out: Pointer, + ) -> u32 { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_ed25519_sign")?; + let key_type = KeyTypeId(id); + + let mut pubkey = [0u8; 32]; + context.read_memory_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| "Invalid attempt to get pubkey in ext_ed25519_sign")?; + + let msg = context.read_memory(msg_data, msg_len) + .map_err(|_| "Invalid attempt to get message in ext_ed25519_sign")?; + + let pub_key = ed25519::Public::try_from(pubkey.as_ref()) + .map_err(|_| "Invalid `ed25519` public key")?; + + let signature = sp_io::crypto::ed25519_sign(key_type, &pub_key, &msg); + + match signature { + Some(signature) => { + context.write_memory(out, signature.as_ref()) + .map_err(|_| "Invalid attempt to set out in ext_ed25519_sign")?; + Ok(0) + }, + None => Ok(1), + } + } + + ext_sr25519_public_keys(id_data: Pointer, result_len: Pointer) -> Pointer { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_sr25519_public_keys")?; + let key_type = KeyTypeId(id); + + let keys = sp_io::crypto::sr25519_public_keys(key_type).encode(); + + let len = keys.len() as u32; + let offset = context.allocate_memory(len)?; + + context.write_memory(offset, keys.as_ref()) + .map_err(|_| "Invalid attempt to set memory in ext_sr25519_public_keys")?; + context.write_primitive(result_len, len) + .map_err(|_| "Invalid attempt to write result_len in ext_sr25519_public_keys")?; + + Ok(offset) + } + + ext_sr25519_verify( + msg_data: Pointer, + msg_len: WordSize, + sig_data: Pointer, + pubkey_data: Pointer, + ) -> u32 { + let mut sig = [0u8; 64]; + context.read_memory_into(sig_data, &mut sig[..]) + .map_err(|_| "Invalid attempt to get signature in ext_sr25519_verify")?; + let mut pubkey = [0u8; 32]; + context.read_memory_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| "Invalid attempt to get pubkey in ext_sr25519_verify")?; + let msg = context.read_memory(msg_data, msg_len) + .map_err(|_| "Invalid attempt to get message in ext_sr25519_verify")?; + + Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) { + 0 + } else { + 1 + }) + } + + ext_sr25519_generate( + id_data: Pointer, + seed: Pointer, + seed_len: WordSize, + out: Pointer, + ) { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_sr25519_generate")?; + let key_type = KeyTypeId(id); + let seed = if seed_len == 0 { + None + } else { + Some( + context.read_memory(seed, seed_len) + .map_err(|_| "Invalid attempt to get seed in ext_sr25519_generate")? + ) + }; + + let pubkey = sp_io::crypto::sr25519_generate(key_type, seed); + + context.write_memory(out, pubkey.as_ref()) + .map_err(|_| "Invalid attempt to set out in ext_sr25519_generate".into()) + } + + ext_sr25519_sign( + id_data: Pointer, + pubkey_data: Pointer, + msg_data: Pointer, + msg_len: WordSize, + out: Pointer, + ) -> u32 { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_sr25519_sign")?; + let key_type = KeyTypeId(id); + + let mut pubkey = [0u8; 32]; + context.read_memory_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| "Invalid attempt to get pubkey in ext_sr25519_sign")?; + + let msg = context.read_memory(msg_data, msg_len) + .map_err(|_| "Invalid attempt to get message in ext_sr25519_sign")?; + + let pub_key = sr25519::Public::try_from(pubkey.as_ref()) + .map_err(|_| "Invalid `sr25519` public key")?; + + let signature = sp_io::crypto::sr25519_sign(key_type, &pub_key, &msg); + + match signature { + Some(signature) => { + context.write_memory(out, signature.as_ref()) + .map_err(|_| "Invalid attempt to set out in ext_sr25519_sign")?; + Ok(0) + }, + None => Ok(1), + } + } + + ext_secp256k1_ecdsa_recover( + msg_data: Pointer, + sig_data: Pointer, + pubkey_data: Pointer, + ) -> u32 { + match secp256k1_recover(context, msg_data, sig_data)? { + RecoverResult::Invalid(c) => Ok(c), + RecoverResult::Valid(pubkey) => { + context.write_memory(pubkey_data, &pubkey.serialize()[1..65]) + .map_err(|_| "Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover")?; + Ok(0) + } + } + } + + ext_secp256k1_ecdsa_recover_compressed( + msg_data: Pointer, + sig_data: Pointer, + pubkey_data: Pointer, + ) -> u32 { + match secp256k1_recover(context, msg_data, sig_data)? { + RecoverResult::Invalid(c) => Ok(c), + RecoverResult::Valid(pubkey) => { + context.write_memory(pubkey_data, &pubkey.serialize_compressed()[..]) + .map_err(|_| "Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover")?; + Ok(0) + } + } + } + + ext_is_validator() -> u32 { + if sp_io::offchain::is_validator() { Ok(1) } else { Ok(0) } + } + + ext_submit_transaction(msg_data: Pointer, len: WordSize) -> u32 { + let extrinsic = context.read_memory(msg_data, len) + .map_err(|_| "OOB while ext_submit_transaction: wasm")?; + + let res = sp_io::offchain::submit_transaction(extrinsic); + + Ok(if res.is_ok() { 0 } else { 1 }) + } + + ext_network_state(written_out: Pointer) -> Pointer { + let res = sp_io::offchain::network_state(); + + let encoded = res.encode(); + let len = encoded.len() as u32; + let offset = context.allocate_memory(len)?; + context.write_memory(offset, &encoded) + .map_err(|_| "Invalid attempt to set memory in ext_network_state")?; + + context.write_primitive(written_out, len) + .map_err(|_| "Invalid attempt to write written_out in ext_network_state")?; + + Ok(offset) + } + + ext_timestamp() -> u64 { + Ok(sp_io::offchain::timestamp().unix_millis()) + } + + ext_sleep_until(deadline: u64) { + sp_io::offchain::sleep_until(offchain::Timestamp::from_unix_millis(deadline)); + Ok(()) + } + + ext_random_seed(seed_data: Pointer) { + // NOTE the runtime as assumptions about seed size. + let seed = sp_io::offchain::random_seed(); + + context.write_memory(seed_data, &seed) + .map_err(|_| "Invalid attempt to set value in ext_random_seed")?; + Ok(()) + } + + ext_local_storage_set( + kind: u32, + key: Pointer, + key_len: WordSize, + value: Pointer, + value_len: WordSize, + ) { + let kind = offchain::StorageKind::try_from(kind) + .map_err(|_| "storage kind OOB while ext_local_storage_set: wasm")?; + let key = context.read_memory(key, key_len) + .map_err(|_| "OOB while ext_local_storage_set: wasm")?; + let value = context.read_memory(value, value_len) + .map_err(|_| "OOB while ext_local_storage_set: wasm")?; + + sp_io::offchain::local_storage_set(kind, &key, &value); + + Ok(()) + } + + ext_local_storage_get( + kind: u32, + key: Pointer, + key_len: WordSize, + value_len: Pointer, + ) -> Pointer { + let kind = offchain::StorageKind::try_from(kind) + .map_err(|_| "storage kind OOB while ext_local_storage_get: wasm")?; + let key = context.read_memory(key, key_len) + .map_err(|_| "OOB while ext_local_storage_get: wasm")?; + + let maybe_value = sp_io::offchain::local_storage_get(kind, &key); + + let (offset, len) = if let Some(value) = maybe_value { + let offset = context.allocate_memory(value.len() as u32)?; + context.write_memory(offset, &value) + .map_err(|_| "Invalid attempt to set memory in ext_local_storage_get")?; + (offset, value.len() as u32) + } else { + (Pointer::null(), u32::max_value()) + }; + + context.write_primitive(value_len, len) + .map_err(|_| "Invalid attempt to write value_len in ext_local_storage_get")?; + + Ok(offset) + } + + ext_local_storage_compare_and_set( + kind: u32, + key: Pointer, + key_len: WordSize, + old_value: Pointer, + old_value_len: WordSize, + new_value: Pointer, + new_value_len: WordSize, + ) -> u32 { + let kind = offchain::StorageKind::try_from(kind) + .map_err(|_| "storage kind OOB while ext_local_storage_compare_and_set: wasm")?; + let key = context.read_memory(key, key_len) + .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; + let new_value = context.read_memory(new_value, new_value_len) + .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; + + let old_value = if old_value_len == u32::max_value() { + None + } else { + Some( + context.read_memory(old_value, old_value_len) + .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")? + ) + }; + + let res = sp_io::offchain::local_storage_compare_and_set( + kind, + &key, + old_value, + &new_value, + ); + + Ok(if res { 0 } else { 1 }) + } + + ext_http_request_start( + method: Pointer, + method_len: WordSize, + url: Pointer, + url_len: WordSize, + meta: Pointer, + meta_len: WordSize, + ) -> u32 { + let method = context.read_memory(method, method_len) + .map_err(|_| "OOB while ext_http_request_start: wasm")?; + let url = context.read_memory(url, url_len) + .map_err(|_| "OOB while ext_http_request_start: wasm")?; + let meta = context.read_memory(meta, meta_len) + .map_err(|_| "OOB while ext_http_request_start: wasm")?; + + let method_str = str::from_utf8(&method) + .map_err(|_| "invalid str while ext_http_request_start: wasm")?; + let url_str = str::from_utf8(&url) + .map_err(|_| "invalid str while ext_http_request_start: wasm")?; + + let id = sp_io::offchain::http_request_start(method_str, url_str, &meta); + + if let Ok(id) = id { + Ok(id.into()) + } else { + Ok(u32::max_value()) + } + } + + ext_http_request_add_header( + request_id: u32, + name: Pointer, + name_len: WordSize, + value: Pointer, + value_len: WordSize, + ) -> u32 { + let name = context.read_memory(name, name_len) + .map_err(|_| "OOB while ext_http_request_add_header: wasm")?; + let value = context.read_memory(value, value_len) + .map_err(|_| "OOB while ext_http_request_add_header: wasm")?; + + let name_str = str::from_utf8(&name) + .map_err(|_| "Invalid str while ext_http_request_add_header: wasm")?; + let value_str = str::from_utf8(&value) + .map_err(|_| "Invalid str while ext_http_request_add_header: wasm")?; + + let res = sp_io::offchain::http_request_add_header( + offchain::HttpRequestId(request_id as u16), + name_str, + value_str, + ); + + Ok(if res.is_ok() { 0 } else { 1 }) + } + + ext_http_request_write_body( + request_id: u32, + chunk: Pointer, + chunk_len: WordSize, + deadline: u64, + ) -> u32 { + let chunk = context.read_memory(chunk, chunk_len) + .map_err(|_| "OOB while ext_http_request_write_body: wasm")?; + + let res = sp_io::offchain::http_request_write_body( + offchain::HttpRequestId(request_id as u16), + &chunk, + deadline_to_timestamp(deadline), + ); + + Ok(match res { + Ok(()) => 0, + Err(e) => e.into(), + }) + } + + ext_http_response_wait( + ids: Pointer, + ids_len: WordSize, + statuses: Pointer, + deadline: u64, + ) { + let ids = (0..ids_len) + .map(|i| + context.read_primitive(ids.offset(i).ok_or("Point overflow")?) + .map(|id: u32| offchain::HttpRequestId(id as u16)) + .map_err(|_| "OOB while ext_http_response_wait: wasm") + ) + .collect::, _>>()?; + + let res = sp_io::offchain::http_response_wait(&ids, deadline_to_timestamp(deadline)) + .into_iter() + .map(|status| u32::from(status)) + .enumerate() + // make sure to take up to `ids_len` to avoid exceeding the mem. + .take(ids_len as usize); + + for (i, status) in res { + context.write_primitive(statuses.offset(i as u32).ok_or("Point overflow")?, status) + .map_err(|_| "Invalid attempt to set memory in ext_http_response_wait")?; + } + + Ok(()) + } + + ext_http_response_headers( + request_id: u32, + written_out: Pointer, + ) -> Pointer { + use codec::Encode; + + let headers = sp_io::offchain::http_response_headers( + offchain::HttpRequestId(request_id as u16), + ); + + let encoded = headers.encode(); + let len = encoded.len() as u32; + let offset = context.allocate_memory(len)?; + + context.write_memory(offset, &encoded) + .map_err(|_| "Invalid attempt to set memory in ext_http_response_headers")?; + context.write_primitive(written_out, len) + .map_err(|_| "Invalid attempt to write written_out in ext_http_response_headers")?; + + Ok(offset) + } + + ext_http_response_read_body( + request_id: u32, + buffer: Pointer, + buffer_len: WordSize, + deadline: u64, + ) -> WordSize { + let mut internal_buffer = Vec::with_capacity(buffer_len as usize); + internal_buffer.resize(buffer_len as usize, 0); + + let res = sp_io::offchain::http_response_read_body( + offchain::HttpRequestId(request_id as u16), + &mut internal_buffer, + deadline_to_timestamp(deadline), + ); + + Ok(match res { + Ok(read) => { + context.write_memory(buffer, &internal_buffer[..read as usize]) + .map_err(|_| "Invalid attempt to set memory in ext_http_response_read_body")?; + + read as u32 + }, + Err(err) => { + u32::max_value() - u32::from(err) + 1 + } + }) + } + } +} + +fn deadline_to_timestamp(deadline: u64) -> Option { + if deadline == 0 { + None + } else { + Some(offchain::Timestamp::from_unix_millis(deadline)) + } +} diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs new file mode 100644 index 0000000000000..2d39cac414545 --- /dev/null +++ b/client/executor/src/integration_tests/mod.rs @@ -0,0 +1,582 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +mod sandbox; + +use codec::{Encode, Decode}; +use hex_literal::hex; +use sp_core::{ + Blake2Hasher, blake2_128, blake2_256, ed25519, sr25519, map, Pair, + offchain::{OffchainExt, testing}, + traits::Externalities, +}; +use sc_runtime_test::WASM_BINARY; +use sp_state_machine::TestExternalities as CoreTestExternalities; +use test_case::test_case; +use sp_trie::{TrieConfiguration, trie_types::Layout}; + +use crate::WasmExecutionMethod; + +pub type TestExternalities = CoreTestExternalities; + +#[cfg(feature = "wasmtime")] +mod wasmtime_missing_externals { + use sp_wasm_interface::{Function, FunctionContext, HostFunctions, Result, Signature, Value}; + + pub struct WasmtimeHostFunctions; + + impl HostFunctions for WasmtimeHostFunctions { + fn host_functions() -> Vec<&'static dyn Function> { + vec![MISSING_EXTERNAL_FUNCTION, YET_ANOTHER_MISSING_EXTERNAL_FUNCTION] + } + } + + struct MissingExternalFunction(&'static str); + + impl Function for MissingExternalFunction { + fn name(&self) -> &str { self.0 } + + fn signature(&self) -> Signature { + Signature::new(vec![], None) + } + + fn execute( + &self, + _context: &mut dyn FunctionContext, + _args: &mut dyn Iterator, + ) -> Result> { + panic!("should not be called"); + } + } + + static MISSING_EXTERNAL_FUNCTION: &'static MissingExternalFunction = + &MissingExternalFunction("missing_external"); + static YET_ANOTHER_MISSING_EXTERNAL_FUNCTION: &'static MissingExternalFunction = + &MissingExternalFunction("yet_another_missing_external"); +} + +#[cfg(feature = "wasmtime")] +type HostFunctions = + (wasmtime_missing_externals::WasmtimeHostFunctions, sp_io::SubstrateHostFunctions); + +#[cfg(not(feature = "wasmtime"))] +type HostFunctions = sp_io::SubstrateHostFunctions; + +fn call_in_wasm( + function: &str, + call_data: &[u8], + execution_method: WasmExecutionMethod, + ext: &mut E, + code: &[u8], + heap_pages: u64, +) -> crate::error::Result> { + crate::call_in_wasm::( + function, + call_data, + execution_method, + ext, + code, + heap_pages, + true, + ) +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn returning_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let output = call_in_wasm( + "test_empty_return", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); + assert_eq!(output, vec![0u8; 0]); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +#[should_panic(expected = "Function `missing_external` is only a stub. Calling a stub is not allowed.")] +#[cfg(not(feature = "wasmtime"))] +fn call_not_existing_function(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + call_in_wasm( + "test_calling_missing_external", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +#[should_panic(expected = "Function `yet_another_missing_external` is only a stub. Calling a stub is not allowed.")] +#[cfg(not(feature = "wasmtime"))] +fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + call_in_wasm( + "test_calling_yet_another_missing_external", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn panicking_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let output = call_in_wasm( + "test_panic", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ); + assert!(output.is_err()); + + let output = call_in_wasm( + "test_conditional_panic", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ); + assert_eq!(Decode::decode(&mut &output.unwrap()[..]), Ok(Vec::::new())); + + let output = call_in_wasm( + "test_conditional_panic", + &vec![2].encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ); + assert!(output.is_err()); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn storage_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + + { + let mut ext = ext.ext(); + ext.set_storage(b"foo".to_vec(), b"bar".to_vec()); + let test_code = WASM_BINARY; + + let output = call_in_wasm( + "test_data_in", + &b"Hello world".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); + + assert_eq!(output, b"all ok!".to_vec().encode()); + } + + let expected = TestExternalities::new(sp_core::storage::Storage { + top: map![ + b"input".to_vec() => b"Hello world".to_vec(), + b"foo".to_vec() => b"bar".to_vec(), + b"baz".to_vec() => b"bar".to_vec() + ], + children: map![], + }); + assert_eq!(ext, expected); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn clear_prefix_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + { + let mut ext = ext.ext(); + ext.set_storage(b"aaa".to_vec(), b"1".to_vec()); + ext.set_storage(b"aab".to_vec(), b"2".to_vec()); + ext.set_storage(b"aba".to_vec(), b"3".to_vec()); + ext.set_storage(b"abb".to_vec(), b"4".to_vec()); + ext.set_storage(b"bbb".to_vec(), b"5".to_vec()); + let test_code = WASM_BINARY; + + // This will clear all entries which prefix is "ab". + let output = call_in_wasm( + "test_clear_prefix", + &b"ab".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); + + assert_eq!(output, b"all ok!".to_vec().encode()); + } + + let expected = TestExternalities::new(sp_core::storage::Storage { + top: map![ + b"aaa".to_vec() => b"1".to_vec(), + b"aab".to_vec() => b"2".to_vec(), + b"bbb".to_vec() => b"5".to_vec() + ], + children: map![], + }); + assert_eq!(expected, ext); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn blake2_256_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_blake2_256", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + blake2_256(&b""[..]).to_vec().encode(), + ); + assert_eq!( + call_in_wasm( + "test_blake2_256", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + blake2_256(&b"Hello world!"[..]).to_vec().encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn blake2_128_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_blake2_128", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + blake2_128(&b""[..]).to_vec().encode(), + ); + assert_eq!( + call_in_wasm( + "test_blake2_128", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + blake2_128(&b"Hello world!"[..]).to_vec().encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn sha2_256_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_sha2_256", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ) + .unwrap(), + hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + .to_vec() + .encode(), + ); + assert_eq!( + call_in_wasm( + "test_sha2_256", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ) + .unwrap(), + hex!("c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a") + .to_vec() + .encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn twox_256_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_twox_256", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + hex!( + "99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a" + ).to_vec().encode(), + ); + assert_eq!( + call_in_wasm( + "test_twox_256", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + hex!( + "b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74" + ).to_vec().encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn twox_128_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_twox_128", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + hex!("99e9d85137db46ef4bbea33613baafd5").to_vec().encode(), + ); + assert_eq!( + call_in_wasm( + "test_twox_128", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + hex!("b27dfd7f223f177f2a13647b533599af").to_vec().encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn ed25519_verify_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + let key = ed25519::Pair::from_seed(&blake2_256(b"test")); + let sig = key.sign(b"all ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(sig.as_ref()); + + assert_eq!( + call_in_wasm( + "test_ed25519_verify", + &calldata.encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + + let other_sig = key.sign(b"all is not ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(other_sig.as_ref()); + + assert_eq!( + call_in_wasm( + "test_ed25519_verify", + &calldata.encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + false.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn sr25519_verify_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + let key = sr25519::Pair::from_seed(&blake2_256(b"test")); + let sig = key.sign(b"all ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(sig.as_ref()); + + assert_eq!( + call_in_wasm( + "test_sr25519_verify", + &calldata.encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + + let other_sig = key.sign(b"all is not ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(other_sig.as_ref()); + + assert_eq!( + call_in_wasm( + "test_sr25519_verify", + &calldata.encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + false.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn ordered_trie_root_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let trie_input = vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()]; + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_ordered_trie_root", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + Layout::::ordered_trie_root(trie_input.iter()).as_bytes().encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn offchain_local_storage_should_work(wasm_method: WasmExecutionMethod) { + use sp_core::offchain::OffchainStorage; + + let mut ext = TestExternalities::default(); + let (offchain, state) = testing::TestOffchainExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + let test_code = WASM_BINARY; + let mut ext = ext.ext(); + assert_eq!( + call_in_wasm( + "test_offchain_local_storage", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + assert_eq!(state.read().persistent_storage.get(b"", b"test"), Some(vec![])); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn offchain_http_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let (offchain, state) = testing::TestOffchainExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + state.write().expect_request( + 0, + testing::PendingRequest { + method: "POST".into(), + uri: "http://localhost:12345".into(), + body: vec![1, 2, 3, 4], + headers: vec![("X-Auth".to_owned(), "test".to_owned())], + sent: true, + response: Some(vec![1, 2, 3]), + response_headers: vec![("X-Auth".to_owned(), "hello".to_owned())], + ..Default::default() + }, + ); + + let test_code = WASM_BINARY; + let mut ext = ext.ext(); + assert_eq!( + call_in_wasm( + "test_offchain_http", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); +} diff --git a/client/executor/src/integration_tests/sandbox.rs b/client/executor/src/integration_tests/sandbox.rs new file mode 100644 index 0000000000000..9a9b33608d702 --- /dev/null +++ b/client/executor/src/integration_tests/sandbox.rs @@ -0,0 +1,360 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use super::{TestExternalities, call_in_wasm}; +use crate::WasmExecutionMethod; + +use codec::Encode; +use sc_runtime_test::WASM_BINARY; +use test_case::test_case; +use wabt; + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn sandbox_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (import "env" "inc_counter" (func $inc_counter (param i32) (result i32))) + (func (export "call") + (drop + (call $inc_counter (i32.const 5)) + ) + + (call $inc_counter (i32.const 3)) + ;; current counter value is on the stack + + ;; check whether current == 8 + i32.const 8 + i32.eq + + call $assert + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn sandbox_trap(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (func (export "call") + i32.const 0 + call $assert + ) + ) + "#).unwrap(); + + assert_eq!( + call_in_wasm( + "test_sandbox", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + vec![0], + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +#[should_panic(expected = "Allocator ran out of space")] +fn sandbox_should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (func (export "call") + i32.const 0 + call $assert + ) + ) + "#).unwrap().encode(); + + call_in_wasm( + "test_exhaust_heap", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn start_called(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (import "env" "inc_counter" (func $inc_counter (param i32) (result i32))) + + ;; Start function + (start $start) + (func $start + ;; Increment counter by 1 + (drop + (call $inc_counter (i32.const 1)) + ) + ) + + (func (export "call") + ;; Increment counter by 1. The current value is placed on the stack. + (call $inc_counter (i32.const 1)) + + ;; Counter is incremented twice by 1, once there and once in `start` func. + ;; So check the returned value is equal to 2. + i32.const 2 + i32.eq + call $assert + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn invoke_args(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + + (func (export "call") (param $x i32) (param $y i64) + ;; assert that $x = 0x12345678 + (call $assert + (i32.eq + (get_local $x) + (i32.const 0x12345678) + ) + ) + + (call $assert + (i64.eq + (get_local $y) + (i64.const 0x1234567887654321) + ) + ) + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_args", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn return_val(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (func (export "call") (param $x i32) (result i32) + (i32.add + (get_local $x) + (i32.const 1) + ) + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_return_val", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn unlinkable_module(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "non-existent" (func)) + + (func (export "call") + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_instantiate", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + 1u8.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn corrupted_module(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + // Corrupted wasm file + let code = vec![0u8, 0, 0, 0, 1, 0, 0, 0].encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_instantiate", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + 1u8.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn start_fn_ok(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (func (export "call") + ) + + (func $start + ) + + (start $start) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_instantiate", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + 0u8.encode(), + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn start_fn_traps(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (func (export "call") + ) + + (func $start + unreachable + ) + + (start $start) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_instantiate", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + 2u8.encode(), + ); +} diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs new file mode 100644 index 0000000000000..1908eb3688ea3 --- /dev/null +++ b/client/executor/src/lib.rs @@ -0,0 +1,112 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A crate that provides means of executing/dispatching calls into the runtime. +//! +//! There are a few responsibilities of this crate at the moment: +//! +//! - It provides an implementation of a common entrypoint for calling into the runtime, both +//! wasm and compiled. +//! - It defines the environment for the wasm execution, namely the host functions that are to be +//! provided into the wasm runtime module. +//! - It also provides the required infrastructure for executing the current wasm runtime (specified +//! by the current value of `:code` in the provided externalities), i.e. interfacing with +//! wasm engine used, instance cache. + +#![warn(missing_docs)] +#![recursion_limit="128"] + +#[macro_use] +mod wasm_utils; +#[macro_use] +mod native_executor; +pub mod deprecated_host_interface; +mod wasm_runtime; +#[cfg(test)] +mod integration_tests; + +pub use wasmi; +pub use native_executor::{with_native_environment, NativeExecutor, NativeExecutionDispatch}; +pub use sp_version::{RuntimeVersion, NativeVersion}; +pub use codec::Codec; +#[doc(hidden)] +pub use sp_core::traits::Externalities; +#[doc(hidden)] +pub use sp_wasm_interface; +pub use wasm_runtime::WasmExecutionMethod; + +pub use sc_executor_common::{error, allocator, sandbox}; + +/// Call the given `function` in the given wasm `code`. +/// +/// The signature of `function` needs to follow the default Substrate function signature. +/// +/// - `call_data`: Will be given as input parameters to `function` +/// - `execution_method`: The execution method to use. +/// - `ext`: The externalities that should be set while executing the wasm function. +/// - `heap_pages`: The number of heap pages to allocate. +/// +/// Returns the `Vec` that contains the return value of the function. +pub fn call_in_wasm( + function: &str, + call_data: &[u8], + execution_method: WasmExecutionMethod, + ext: &mut E, + code: &[u8], + heap_pages: u64, + allow_missing_imports: bool, +) -> error::Result> { + let mut instance = wasm_runtime::create_wasm_runtime_with_code( + execution_method, + heap_pages, + code, + HF::host_functions(), + allow_missing_imports, + )?; + instance.call(ext, function, call_data) +} + +/// Provides runtime information. +pub trait RuntimeInfo { + /// Native runtime information. + fn native_version(&self) -> &NativeVersion; + + /// Extract RuntimeVersion of given :code block + fn runtime_version (&self, ext: &mut E) -> error::Result; +} + +#[cfg(test)] +mod tests { + use super::*; + use sc_runtime_test::WASM_BINARY; + use sp_io::TestExternalities; + + #[test] + fn call_in_interpreted_wasm_works() { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let res = call_in_wasm::<_, sp_io::SubstrateHostFunctions>( + "test_empty_return", + &[], + WasmExecutionMethod::Interpreted, + &mut ext, + &WASM_BINARY, + 8, + true, + ).unwrap(); + assert_eq!(res, vec![0u8; 0]); + } +} diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs new file mode 100644 index 0000000000000..86b274eea0bb9 --- /dev/null +++ b/client/executor/src/native_executor.rs @@ -0,0 +1,361 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::{ + RuntimeInfo, error::{Error, Result}, + wasm_runtime::{RuntimesCache, WasmExecutionMethod}, +}; +use sp_version::{NativeVersion, RuntimeVersion}; +use codec::{Decode, Encode}; +use sp_core::{NativeOrEncoded, traits::{CodeExecutor, Externalities}}; +use log::trace; +use std::{result, cell::RefCell, panic::{UnwindSafe, AssertUnwindSafe}}; +use sp_wasm_interface::{HostFunctions, Function}; +use sc_executor_common::wasm_runtime::WasmRuntime; + +thread_local! { + static RUNTIMES_CACHE: RefCell = RefCell::new(RuntimesCache::new()); +} + +/// Default num of pages for the heap +const DEFAULT_HEAP_PAGES: u64 = 1024; + +pub(crate) fn safe_call(f: F) -> Result + where F: UnwindSafe + FnOnce() -> U +{ + // Substrate uses custom panic hook that terminates process on panic. Disable + // termination for the native call. + let _guard = sp_panic_handler::AbortGuard::force_unwind(); + std::panic::catch_unwind(f).map_err(|_| Error::Runtime) +} + +/// Set up the externalities and safe calling environment to execute calls to a native runtime. +/// +/// If the inner closure panics, it will be caught and return an error. +pub fn with_native_environment(ext: &mut dyn Externalities, f: F) -> Result + where F: UnwindSafe + FnOnce() -> U +{ + sp_externalities::set_and_run_with_externalities(ext, move || safe_call(f)) +} + +/// Delegate for dispatching a CodeExecutor call. +/// +/// By dispatching we mean that we execute a runtime function specified by it's name. +pub trait NativeExecutionDispatch: Send + Sync { + /// Host functions for custom runtime interfaces that should be callable from within the runtime + /// besides the default Substrate runtime interfaces. + type ExtendHostFunctions: HostFunctions; + + /// Dispatch a method in the runtime. + /// + /// If the method with the specified name doesn't exist then `Err` is returned. + fn dispatch(ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result>; + + /// Provide native runtime version. + fn native_version() -> NativeVersion; +} + +/// A generic `CodeExecutor` implementation that uses a delegate to determine wasm code equivalence +/// and dispatch to native code when possible, falling back on `WasmExecutor` when not. +pub struct NativeExecutor { + /// Dummy field to avoid the compiler complaining about us not using `D`. + _dummy: std::marker::PhantomData, + /// Method used to execute fallback Wasm code. + fallback_method: WasmExecutionMethod, + /// Native runtime version info. + native_version: NativeVersion, + /// The number of 64KB pages to allocate for Wasm execution. + default_heap_pages: u64, + /// The host functions registered with this instance. + host_functions: Vec<&'static dyn Function>, +} + +impl NativeExecutor { + /// Create new instance. + /// + /// # Parameters + /// + /// `fallback_method` - Method used to execute fallback Wasm code. + /// + /// `default_heap_pages` - Number of 64KB pages to allocate for Wasm execution. + /// Defaults to `DEFAULT_HEAP_PAGES` if `None` is provided. + pub fn new(fallback_method: WasmExecutionMethod, default_heap_pages: Option) -> Self { + let mut host_functions = sp_io::SubstrateHostFunctions::host_functions(); + // Add the old and deprecated host functions as well, so that we support old wasm runtimes. + host_functions.extend( + crate::deprecated_host_interface::SubstrateExternals::host_functions(), + ); + + // Add the custom host functions provided by the user. + host_functions.extend(D::ExtendHostFunctions::host_functions()); + + NativeExecutor { + _dummy: Default::default(), + fallback_method, + native_version: D::native_version(), + default_heap_pages: default_heap_pages.unwrap_or(DEFAULT_HEAP_PAGES), + host_functions, + } + } + + /// Execute the given closure `f` with the latest runtime (based on the `CODE` key in `ext`). + /// + /// The closure `f` is expected to return `Err(_)` when there happened a `panic!` in native code + /// while executing the runtime in Wasm. If a `panic!` occurred, the runtime is invalidated to + /// prevent any poisoned state. Native runtime execution does not need to report back + /// any `panic!`. + /// + /// # Safety + /// + /// `runtime` and `ext` are given as `AssertUnwindSafe` to the closure. As described above, the + /// runtime is invalidated on any `panic!` to prevent a poisoned state. `ext` is already + /// implicitly handled as unwind safe, as we store it in a global variable while executing the + /// native runtime. + fn with_runtime( + &self, + ext: &mut E, + f: impl for<'a> FnOnce( + AssertUnwindSafe<&'a mut (dyn WasmRuntime + 'static)>, + &'a RuntimeVersion, + AssertUnwindSafe<&'a mut E>, + ) -> Result>, + ) -> Result where E: Externalities { + RUNTIMES_CACHE.with(|cache| { + let mut cache = cache.borrow_mut(); + let (runtime, version, code_hash) = cache.fetch_runtime( + ext, + self.fallback_method, + self.default_heap_pages, + &self.host_functions, + )?; + + let runtime = AssertUnwindSafe(runtime); + let ext = AssertUnwindSafe(ext); + + match f(runtime, version, ext) { + Ok(res) => res, + Err(e) => { + cache.invalidate_runtime(self.fallback_method, code_hash); + Err(e) + } + } + }) + } +} + +impl Clone for NativeExecutor { + fn clone(&self) -> Self { + NativeExecutor { + _dummy: Default::default(), + fallback_method: self.fallback_method, + native_version: D::native_version(), + default_heap_pages: self.default_heap_pages, + host_functions: self.host_functions.clone(), + } + } +} + +impl RuntimeInfo for NativeExecutor { + fn native_version(&self) -> &NativeVersion { + &self.native_version + } + + fn runtime_version( + &self, + ext: &mut E, + ) -> Result { + self.with_runtime(ext, |_runtime, version, _ext| Ok(Ok(version.clone()))) + } +} + +impl CodeExecutor for NativeExecutor { + type Error = Error; + + fn call + < + E: Externalities, + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >( + &self, + ext: &mut E, + method: &str, + data: &[u8], + use_native: bool, + native_call: Option, + ) -> (Result>, bool){ + let mut used_native = false; + let result = self.with_runtime(ext, |mut runtime, onchain_version, mut ext| { + match ( + use_native, + onchain_version.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, + ); + + safe_call( + move || runtime.call(&mut **ext, method, data).map(NativeOrEncoded::Encoded) + ) + } + (false, _, _) => { + safe_call( + move || runtime.call(&mut **ext, method, data).map(NativeOrEncoded::Encoded) + ) + }, + (true, true, Some(call)) => { + trace!( + target: "executor", + "Request for native execution with native call succeeded (native: {}, chain: {}).", + self.native_version.runtime_version, + onchain_version, + ); + + used_native = true; + let res = with_native_environment(&mut **ext, move || (call)()) + .and_then(|r| r + .map(NativeOrEncoded::Native) + .map_err(|s| Error::ApiError(s.to_string())) + ); + + Ok(res) + } + _ => { + trace!( + target: "executor", + "Request for native execution succeeded (native: {}, chain: {})", + self.native_version.runtime_version, + onchain_version + ); + + used_native = true; + Ok(D::dispatch(&mut **ext, method, data).map(NativeOrEncoded::Encoded)) + } + } + }); + (result, used_native) + } +} + +/// Implements a `NativeExecutionDispatch` for provided parameters. +/// +/// # Example +/// +/// ``` +/// sc_executor::native_executor_instance!( +/// pub MyExecutor, +/// substrate_test_runtime::api::dispatch, +/// substrate_test_runtime::native_version, +/// ); +/// ``` +/// +/// # With custom host functions +/// +/// When you want to use custom runtime interfaces from within your runtime, you need to make the +/// executor aware of the host functions for these interfaces. +/// +/// ``` +/// # use sp_runtime_interface::runtime_interface; +/// +/// #[runtime_interface] +/// trait MyInterface { +/// fn say_hello_world(data: &str) { +/// println!("Hello world from: {}", data); +/// } +/// } +/// +/// sc_executor::native_executor_instance!( +/// pub MyExecutor, +/// substrate_test_runtime::api::dispatch, +/// substrate_test_runtime::native_version, +/// my_interface::HostFunctions, +/// ); +/// ``` +/// +/// When you have multiple interfaces, you can give the host functions as a tuple e.g.: +/// `(my_interface::HostFunctions, my_interface2::HostFunctions)` +/// +#[macro_export] +macro_rules! native_executor_instance { + ( $pub:vis $name:ident, $dispatcher:path, $version:path $(,)?) => { + /// A unit struct which implements `NativeExecutionDispatch` feeding in the + /// hard-coded runtime. + $pub struct $name; + $crate::native_executor_instance!(IMPL $name, $dispatcher, $version, ()); + }; + ( $pub:vis $name:ident, $dispatcher:path, $version:path, $custom_host_functions:ty $(,)?) => { + /// A unit struct which implements `NativeExecutionDispatch` feeding in the + /// hard-coded runtime. + $pub struct $name; + $crate::native_executor_instance!( + IMPL $name, $dispatcher, $version, $custom_host_functions + ); + }; + (IMPL $name:ident, $dispatcher:path, $version:path, $custom_host_functions:ty) => { + impl $crate::NativeExecutionDispatch for $name { + type ExtendHostFunctions = $custom_host_functions; + + fn dispatch( + ext: &mut dyn $crate::Externalities, + method: &str, + data: &[u8] + ) -> $crate::error::Result> { + $crate::with_native_environment(ext, move || $dispatcher(method, data))? + .ok_or_else(|| $crate::error::Error::MethodNotFound(method.to_owned())) + } + + fn native_version() -> $crate::NativeVersion { + $version() + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime_interface::runtime_interface; + + #[runtime_interface] + trait MyInterface { + fn say_hello_world(data: &str) { + println!("Hello world from: {}", data); + } + } + + native_executor_instance!( + pub MyExecutor, + substrate_test_runtime::api::dispatch, + substrate_test_runtime::native_version, + (my_interface::HostFunctions, my_interface::HostFunctions), + ); + + #[test] + fn native_executor_registers_custom_interface() { + let executor = NativeExecutor::::new(WasmExecutionMethod::Interpreted, None); + my_interface::HostFunctions::host_functions().iter().for_each(|function| { + assert_eq!( + executor.host_functions.iter().filter(|f| f == &function).count(), + 2, + ); + }); + } +} diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs new file mode 100644 index 0000000000000..eef73097f6e7b --- /dev/null +++ b/client/executor/src/wasm_runtime.rs @@ -0,0 +1,252 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Traits and accessor functions for calling into the Substrate Wasm runtime. +//! +//! The primary means of accessing the runtimes is through a cache which saves the reusable +//! components of the runtime that are expensive to initialize. + +use crate::error::{Error, WasmError}; +use log::{trace, warn}; +use codec::Decode; +use sp_core::{storage::well_known_keys, traits::Externalities}; +use sp_version::RuntimeVersion; +use std::{collections::hash_map::{Entry, HashMap}, panic::AssertUnwindSafe}; +use sc_executor_common::wasm_runtime::WasmRuntime; + +use sp_wasm_interface::Function; + +/// Specification of different methods of executing the runtime Wasm code. +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +pub enum WasmExecutionMethod { + /// Uses the Wasmi interpreter. + Interpreted, + /// Uses the Wasmtime compiled runtime. + #[cfg(feature = "wasmtime")] + Compiled, +} + +/// A Wasm runtime object along with its cached runtime version. +struct VersionedRuntime { + runtime: Box, + /// Runtime version according to `Core_version`. + version: RuntimeVersion, +} + +/// Cache for the runtimes. +/// +/// When an instance is requested for the first time it is added to this cache. Metadata is kept +/// with the instance so that it can be efficiently reinitialized. +/// +/// When using the Wasmi interpreter execution method, the metadata includes the initial memory and +/// values of mutable globals. Follow-up requests to fetch a runtime return this one instance with +/// the memory reset to the initial memory. So, one runtime instance is reused for every fetch +/// request. +/// +/// For now the cache grows indefinitely, but that should be fine for now since runtimes can only be +/// upgraded rarely and there are no other ways to make the node to execute some other runtime. +pub struct RuntimesCache { + /// A cache of runtime instances along with metadata, ready to be reused. + /// + /// Instances are keyed by the Wasm execution method and the hash of their code. + instances: HashMap<(WasmExecutionMethod, Vec), Result>, +} + +impl RuntimesCache { + /// Creates a new instance of a runtimes cache. + pub fn new() -> RuntimesCache { + RuntimesCache { + instances: HashMap::new(), + } + } + + /// Fetches an instance of the runtime. + /// + /// On first use we create a new runtime instance, save it to the cache + /// and persist its initial memory. + /// + /// Each subsequent request will return this instance, with its memory restored + /// to the persisted initial memory. Thus, we reuse one single runtime instance + /// for every `fetch_runtime` invocation. + /// + /// # Parameters + /// + /// `ext` - Externalities to use for the runtime. This is used for setting + /// up an initial runtime instance. + /// + /// `default_heap_pages` - Number of 64KB pages to allocate for Wasm execution. + /// + /// `host_functions` - The host functions that should be registered for the Wasm runtime. + /// + /// # Return value + /// + /// If no error occurred a tuple `(&mut WasmRuntime, H256)` is + /// returned. `H256` is the hash of the runtime code. + /// + /// In case of failure one of two errors can be returned: + /// + /// `Err::InvalidCode` is returned for runtime code issues. + /// + /// `Error::InvalidMemoryReference` is returned if no memory export with the + /// identifier `memory` can be found in the runtime. + pub fn fetch_runtime( + &mut self, + ext: &mut E, + wasm_method: WasmExecutionMethod, + default_heap_pages: u64, + host_functions: &[&'static dyn Function], + ) -> Result<(&mut (dyn WasmRuntime + 'static), &RuntimeVersion, Vec), Error> { + let code_hash = ext + .original_storage_hash(well_known_keys::CODE) + .ok_or(Error::InvalidCode("`CODE` not found in storage.".into()))?; + + let heap_pages = ext + .storage(well_known_keys::HEAP_PAGES) + .and_then(|pages| u64::decode(&mut &pages[..]).ok()) + .unwrap_or(default_heap_pages); + + let result = match self.instances.entry((wasm_method, code_hash.clone())) { + Entry::Occupied(o) => { + let result = o.into_mut(); + if let Ok(ref mut cached_runtime) = result { + let heap_pages_changed = !cached_runtime.runtime.update_heap_pages(heap_pages); + let host_functions_changed = cached_runtime.runtime.host_functions() + != host_functions; + if heap_pages_changed || host_functions_changed { + let changed = if heap_pages_changed { + "heap_pages" + } else { + "host functions" + }; + + trace!( + target: "runtimes_cache", + "{} were changed. Reinstantiating the instance", + changed, + ); + *result = create_versioned_wasm_runtime( + ext, + wasm_method, + heap_pages, + host_functions.into(), + ); + if let Err(ref err) = result { + warn!(target: "runtimes_cache", "cannot create a runtime: {:?}", err); + } + } + } + result + }, + Entry::Vacant(v) => { + trace!(target: "runtimes_cache", "no instance found in cache, creating now."); + let result = create_versioned_wasm_runtime( + ext, + wasm_method, + heap_pages, + host_functions.into(), + ); + if let Err(ref err) = result { + warn!(target: "runtimes_cache", "cannot create a runtime: {:?}", err); + } + v.insert(result) + } + }; + + result.as_mut() + .map(|entry| (entry.runtime.as_mut(), &entry.version, code_hash)) + .map_err(|ref e| Error::InvalidCode(format!("{:?}", e))) + } + + /// Invalidate the runtime for the given `wasm_method` and `code_hash`. + /// + /// Invalidation of a runtime is useful when there was a `panic!` in native while executing it. + /// The `panic!` maybe have brought the runtime into a poisoned state and so, it is better to + /// invalidate this runtime instance. + pub fn invalidate_runtime( + &mut self, + wasm_method: WasmExecutionMethod, + code_hash: Vec, + ) { + // Just remove the instance, it will be re-created the next time it is requested. + self.instances.remove(&(wasm_method, code_hash)); + } +} + +/// Create a wasm runtime with the given `code`. +pub fn create_wasm_runtime_with_code( + wasm_method: WasmExecutionMethod, + heap_pages: u64, + code: &[u8], + host_functions: Vec<&'static dyn Function>, + allow_missing_imports: bool, +) -> Result, WasmError> { + match wasm_method { + WasmExecutionMethod::Interpreted => + sc_executor_wasmi::create_instance(code, heap_pages, host_functions, allow_missing_imports) + .map(|runtime| -> Box { Box::new(runtime) }), + #[cfg(feature = "wasmtime")] + WasmExecutionMethod::Compiled => + sc_executor_wasmtime::create_instance(code, heap_pages, host_functions) + .map(|runtime| -> Box { Box::new(runtime) }), + } +} + +fn create_versioned_wasm_runtime( + ext: &mut E, + wasm_method: WasmExecutionMethod, + heap_pages: u64, + host_functions: Vec<&'static dyn Function>, +) -> Result { + let code = ext + .original_storage(well_known_keys::CODE) + .ok_or(WasmError::CodeNotFound)?; + let mut runtime = create_wasm_runtime_with_code(wasm_method, heap_pages, &code, host_functions, false)?; + + // Call to determine runtime version. + let version_result = { + // `ext` is already implicitly handled as unwind safe, as we store it in a global variable. + let mut ext = AssertUnwindSafe(ext); + + // The following unwind safety assertion is OK because if the method call panics, the + // runtime will be dropped. + let mut runtime = AssertUnwindSafe(runtime.as_mut()); + crate::native_executor::safe_call( + move || runtime.call(&mut **ext, "Core_version", &[]) + ).map_err(|_| WasmError::Instantiation("panic in call to get runtime version".into()))? + }; + let encoded_version = version_result + .map_err(|e| WasmError::Instantiation(format!("failed to call \"Core_version\": {}", e)))?; + let version = RuntimeVersion::decode(&mut encoded_version.as_slice()) + .map_err(|_| WasmError::Instantiation("failed to decode \"Core_version\" result".into()))?; + + Ok(VersionedRuntime { + runtime, + version, + }) +} + +#[cfg(test)] +mod tests { + use sp_wasm_interface::HostFunctions; + + #[test] + fn host_functions_are_equal() { + let host_functions = sp_io::SubstrateHostFunctions::host_functions(); + + let equal = &host_functions[..] == &host_functions[..]; + assert!(equal, "Host functions are not equal"); + } +} diff --git a/core/executor/src/wasm_utils.rs b/client/executor/src/wasm_utils.rs similarity index 79% rename from core/executor/src/wasm_utils.rs rename to client/executor/src/wasm_utils.rs index b217350ac6fc4..539e210a9467e 100644 --- a/core/executor/src/wasm_utils.rs +++ b/client/executor/src/wasm_utils.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,22 +20,22 @@ #[macro_export] macro_rules! convert_args { () => ([]); - ( $( $t:ty ),* ) => ( [ $( <$t as $crate::wasm_interface::IntoValue>::VALUE_TYPE, )* ] ); + ( $( $t:ty ),* ) => ( [ $( <$t as $crate::sp_wasm_interface::IntoValue>::VALUE_TYPE, )* ] ); } /// Generates a WASM signature for given list of parameters. #[macro_export] macro_rules! gen_signature { ( ( $( $params: ty ),* ) ) => ( - $crate::wasm_interface::Signature { + $crate::sp_wasm_interface::Signature { args: std::borrow::Cow::Borrowed(&convert_args!( $( $params ),* )[..]), return_value: None, } ); ( ( $( $params: ty ),* ) -> $returns:ty ) => ( - $crate::wasm_interface::Signature { + $crate::sp_wasm_interface::Signature { args: std::borrow::Cow::Borrowed(&convert_args!( $( $params ),* )[..]), - return_value: Some(<$returns as $crate::wasm_interface::IntoValue>::VALUE_TYPE), + return_value: Some(<$returns as $crate::sp_wasm_interface::IntoValue>::VALUE_TYPE), } ); } @@ -45,7 +45,7 @@ macro_rules! gen_functions { { $( $generated:tt )* } $context:ident, ) => ( - &[ $( $generated )* ] + vec![ $( $generated )* ] ); (@INTERNAL { $( $generated:tt )* } @@ -61,18 +61,18 @@ macro_rules! gen_functions { struct $name; #[allow(unused)] - impl $crate::wasm_interface::Function for $name { + impl $crate::sp_wasm_interface::Function for $name { fn name(&self) -> &str { stringify!($name) } - fn signature(&self) -> $crate::wasm_interface::Signature { + fn signature(&self) -> $crate::sp_wasm_interface::Signature { gen_signature!( ( $( $params ),* ) $( -> $returns )? ) } fn execute( &self, - context: &mut dyn $crate::wasm_interface::FunctionContext, - args: &mut dyn Iterator, - ) -> ::std::result::Result, String> { + context: &mut dyn $crate::sp_wasm_interface::FunctionContext, + args: &mut dyn Iterator, + ) -> ::std::result::Result, String> { let mut $context = context; marshall! { args, @@ -81,7 +81,7 @@ macro_rules! gen_functions { } } - &$name as &dyn $crate::wasm_interface::Function + &$name as &dyn $crate::sp_wasm_interface::Function }, } $context, @@ -101,7 +101,7 @@ macro_rules! unmarshall_args { $( let $names : $params = $args_iter.next() - .and_then(|val| <$params as $crate::wasm_interface::TryFromValue>::try_from_value(val)) + .and_then(|val| <$params as $crate::sp_wasm_interface::TryFromValue>::try_from_value(val)) .expect( "`$args_iter` comes from an argument of Externals::execute_function; args to an external call always matches the signature of the external; @@ -138,7 +138,7 @@ macro_rules! marshall { unmarshall_args!($body, $args_iter, $( $names : $params ),*) }); let r = body()?; - return Ok(Some($crate::wasm_interface::IntoValue::into_value(r))) + return Ok(Some($crate::sp_wasm_interface::IntoValue::into_value(r))) }); ( $args_iter:ident, ( $( $names:ident : $params:ty ),* ) => $body:tt ) => ({ let body = $crate::wasm_utils::constrain_closure::<(), _>(|| { @@ -160,9 +160,9 @@ macro_rules! impl_wasm_host_interface { )* } ) => ( - impl $crate::wasm_interface::HostFunctions for $interface_name { + impl $crate::sp_wasm_interface::HostFunctions for $interface_name { #[allow(non_camel_case_types)] - fn functions() -> &'static [&'static dyn $crate::wasm_interface::Function] { + fn host_functions() -> Vec<&'static dyn $crate::sp_wasm_interface::Function> { gen_functions!( $context, $( $name( $( $names: $params ),* ) $( -> $returns )? { $( $body )* } )* diff --git a/client/executor/wasmi/Cargo.toml b/client/executor/wasmi/Cargo.toml new file mode 100644 index 0000000000000..7a13d7ea97e26 --- /dev/null +++ b/client/executor/wasmi/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sc-executor-wasmi" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4.8" +wasmi = "0.6.2" +parity-wasm = "0.41.0" +codec = { package = "parity-scale-codec", version = "1.0.0" } +sc-executor-common = { version = "2.0.0", path = "../common" } +sp-wasm-interface = { version = "2.0.0", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0", path = "../../../primitives/runtime-interface" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-externalities = { version = "2.0.0", path = "../../../primitives/externalities" } diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs new file mode 100644 index 0000000000000..7c6141d6c835f --- /dev/null +++ b/client/executor/wasmi/src/lib.rs @@ -0,0 +1,679 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This crate provides an implementation of `WasmRuntime` that is baked by wasmi. + +use sc_executor_common::{ + error::{Error, WasmError}, + sandbox, + allocator, +}; +use std::{str, mem, cell::RefCell}; +use wasmi::{ + Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, + memory_units::Pages, RuntimeValue::{I32, I64, self}, +}; +use codec::{Encode, Decode}; +use sp_core::{sandbox as sandbox_primitives, traits::Externalities}; +use log::{error, trace}; +use parity_wasm::elements::{deserialize_buffer, DataSegment, Instruction, Module as RawModule}; +use sp_wasm_interface::{ + FunctionContext, Pointer, WordSize, Sandbox, MemoryId, Result as WResult, Function, +}; +use sp_runtime_interface::unpack_ptr_and_len; +use sc_executor_common::wasm_runtime::WasmRuntime; + +struct FunctionExecutor<'a> { + sandbox_store: sandbox::Store, + heap: allocator::FreeingBumpHeapAllocator, + memory: MemoryRef, + table: Option, + host_functions: &'a [&'static dyn Function], + allow_missing_imports: bool, + missing_functions: &'a [String], +} + +impl<'a> FunctionExecutor<'a> { + fn new( + m: MemoryRef, + heap_base: u32, + t: Option, + host_functions: &'a [&'static dyn Function], + allow_missing_imports: bool, + missing_functions: &'a [String], + ) -> Result { + Ok(FunctionExecutor { + sandbox_store: sandbox::Store::new(), + heap: allocator::FreeingBumpHeapAllocator::new(heap_base), + memory: m, + table: t, + host_functions, + allow_missing_imports, + missing_functions, + }) + } +} + +impl<'a> sandbox::SandboxCapabilities for FunctionExecutor<'a> { + type SupervisorFuncRef = wasmi::FuncRef; + + fn store(&self) -> &sandbox::Store { + &self.sandbox_store + } + fn store_mut(&mut self) -> &mut sandbox::Store { + &mut self.sandbox_store + } + fn allocate(&mut self, len: WordSize) -> Result, Error> { + let heap = &mut self.heap; + self.memory.with_direct_access_mut(|mem| { + heap.allocate(mem, len) + }) + } + fn deallocate(&mut self, ptr: Pointer) -> Result<(), Error> { + let heap = &mut self.heap; + self.memory.with_direct_access_mut(|mem| { + heap.deallocate(mem, ptr) + }) + } + fn write_memory(&mut self, ptr: Pointer, data: &[u8]) -> Result<(), Error> { + self.memory.set(ptr.into(), data).map_err(Into::into) + } + fn read_memory(&self, ptr: Pointer, len: WordSize) -> Result, Error> { + self.memory.get(ptr.into(), len as usize).map_err(Into::into) + } + + fn invoke( + &mut self, + dispatch_thunk: &Self::SupervisorFuncRef, + invoke_args_ptr: Pointer, + invoke_args_len: WordSize, + state: u32, + func_idx: sandbox::SupervisorFuncIndex, + ) -> Result + { + let result = wasmi::FuncInstance::invoke( + dispatch_thunk, + &[ + RuntimeValue::I32(u32::from(invoke_args_ptr) as i32), + RuntimeValue::I32(invoke_args_len as i32), + RuntimeValue::I32(state as i32), + RuntimeValue::I32(usize::from(func_idx) as i32), + ], + self, + ); + match result { + Ok(Some(RuntimeValue::I64(val))) => Ok(val), + Ok(_) => return Err("Supervisor function returned unexpected result!".into()), + Err(err) => Err(Error::Trap(err)), + } + } +} + +impl<'a> FunctionContext for FunctionExecutor<'a> { + fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> WResult<()> { + self.memory.get_into(address.into(), dest).map_err(|e| e.to_string()) + } + + fn write_memory(&mut self, address: Pointer, data: &[u8]) -> WResult<()> { + self.memory.set(address.into(), data).map_err(|e| e.to_string()) + } + + fn allocate_memory(&mut self, size: WordSize) -> WResult> { + let heap = &mut self.heap; + self.memory.with_direct_access_mut(|mem| { + heap.allocate(mem, size).map_err(|e| e.to_string()) + }) + } + + fn deallocate_memory(&mut self, ptr: Pointer) -> WResult<()> { + let heap = &mut self.heap; + self.memory.with_direct_access_mut(|mem| { + heap.deallocate(mem, ptr).map_err(|e| e.to_string()) + }) + } + + fn sandbox(&mut self) -> &mut dyn Sandbox { + self + } +} + +impl<'a> Sandbox for FunctionExecutor<'a> { + fn memory_get( + &mut self, + memory_id: MemoryId, + offset: WordSize, + buf_ptr: Pointer, + buf_len: WordSize, + ) -> WResult { + let sandboxed_memory = self.sandbox_store.memory(memory_id).map_err(|e| e.to_string())?; + + match MemoryInstance::transfer( + &sandboxed_memory, + offset as usize, + &self.memory, + buf_ptr.into(), + buf_len as usize, + ) { + Ok(()) => Ok(sandbox_primitives::ERR_OK), + Err(_) => Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + } + } + + fn memory_set( + &mut self, + memory_id: MemoryId, + offset: WordSize, + val_ptr: Pointer, + val_len: WordSize, + ) -> WResult { + let sandboxed_memory = self.sandbox_store.memory(memory_id).map_err(|e| e.to_string())?; + + match MemoryInstance::transfer( + &self.memory, + val_ptr.into(), + &sandboxed_memory, + offset as usize, + val_len as usize, + ) { + Ok(()) => Ok(sandbox_primitives::ERR_OK), + Err(_) => Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + } + } + + fn memory_teardown(&mut self, memory_id: MemoryId) -> WResult<()> { + self.sandbox_store.memory_teardown(memory_id).map_err(|e| e.to_string()) + } + + fn memory_new( + &mut self, + initial: u32, + maximum: u32, + ) -> WResult { + self.sandbox_store.new_memory(initial, maximum).map_err(|e| e.to_string()) + } + + fn invoke( + &mut self, + instance_id: u32, + export_name: &str, + args: &[u8], + return_val: Pointer, + return_val_len: WordSize, + state: u32, + ) -> WResult { + trace!(target: "sp-sandbox", "invoke, instance_idx={}", instance_id); + + // Deserialize arguments and convert them into wasmi types. + let args = Vec::::decode(&mut &args[..]) + .map_err(|_| "Can't decode serialized arguments for the invocation")? + .into_iter() + .map(Into::into) + .collect::>(); + + let instance = self.sandbox_store.instance(instance_id).map_err(|e| e.to_string())?; + let result = instance.invoke(export_name, &args, self, state); + + match result { + Ok(None) => Ok(sandbox_primitives::ERR_OK), + Ok(Some(val)) => { + // Serialize return value and write it back into the memory. + sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| { + if val.len() > return_val_len as usize { + Err("Return value buffer is too small")?; + } + self.write_memory(return_val, val).map_err(|_| "Return value buffer is OOB")?; + Ok(sandbox_primitives::ERR_OK) + }) + } + Err(_) => Ok(sandbox_primitives::ERR_EXECUTION), + } + } + + fn instance_teardown(&mut self, instance_id: u32) -> WResult<()> { + self.sandbox_store.instance_teardown(instance_id).map_err(|e| e.to_string()) + } + + fn instance_new( + &mut self, + dispatch_thunk_id: u32, + wasm: &[u8], + raw_env_def: &[u8], + state: u32, + ) -> WResult { + // Extract a dispatch thunk from instance's table by the specified index. + let dispatch_thunk = { + let table = self.table.as_ref() + .ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")?; + table.get(dispatch_thunk_id) + .map_err(|_| "dispatch_thunk_idx is out of the table bounds")? + .ok_or_else(|| "dispatch_thunk_idx points on an empty table entry")? + .clone() + }; + + let instance_idx_or_err_code = + match sandbox::instantiate(self, dispatch_thunk, wasm, raw_env_def, state) { + Ok(instance_idx) => instance_idx, + Err(sandbox::InstantiationError::StartTrapped) => + sandbox_primitives::ERR_EXECUTION, + Err(_) => sandbox_primitives::ERR_MODULE, + }; + + Ok(instance_idx_or_err_code as u32) + } +} + +struct Resolver<'a> { + host_functions: &'a[&'static dyn Function], + allow_missing_imports: bool, + missing_functions: RefCell>, +} + +impl<'a> Resolver<'a> { + fn new(host_functions: &'a[&'static dyn Function], allow_missing_imports: bool) -> Resolver<'a> { + Resolver { + host_functions, + allow_missing_imports, + missing_functions: RefCell::new(Vec::new()), + } + } +} + +impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { + fn resolve_func(&self, name: &str, signature: &wasmi::Signature) + -> std::result::Result + { + let signature = sp_wasm_interface::Signature::from(signature); + for (function_index, function) in self.host_functions.iter().enumerate() { + if name == function.name() { + if signature == function.signature() { + return Ok( + wasmi::FuncInstance::alloc_host(signature.into(), function_index), + ) + } else { + return Err(wasmi::Error::Instantiation( + format!( + "Invalid signature for function `{}` expected `{:?}`, got `{:?}`", + function.name(), + signature, + function.signature(), + ), + )) + } + } + } + + if self.allow_missing_imports { + trace!(target: "wasm-executor", "Could not find function `{}`, a stub will be provided instead.", name); + let id = self.missing_functions.borrow().len() + self.host_functions.len(); + self.missing_functions.borrow_mut().push(name.to_string()); + + Ok(wasmi::FuncInstance::alloc_host(signature.into(), id)) + } else { + Err(wasmi::Error::Instantiation( + format!("Export {} not found", name), + )) + } + } +} + +impl<'a> wasmi::Externals for FunctionExecutor<'a> { + fn invoke_index(&mut self, index: usize, args: wasmi::RuntimeArgs) + -> Result, wasmi::Trap> + { + let mut args = args.as_ref().iter().copied().map(Into::into); + + if let Some(function) = self.host_functions.get(index) { + function.execute(self, &mut args) + .map_err(|msg| Error::FunctionExecution(function.name().to_string(), msg)) + .map_err(wasmi::Trap::from) + .map(|v| v.map(Into::into)) + } else if self.allow_missing_imports + && index >= self.host_functions.len() + && index < self.host_functions.len() + self.missing_functions.len() + { + Err(Error::from(format!( + "Function `{}` is only a stub. Calling a stub is not allowed.", + self.missing_functions[index - self.host_functions.len()], + )).into()) + } else { + Err(Error::from(format!("Could not find host function with index: {}", index)).into()) + } + } +} + +fn get_mem_instance(module: &ModuleRef) -> Result { + Ok(module + .export_by_name("memory") + .ok_or_else(|| Error::InvalidMemoryReference)? + .as_memory() + .ok_or_else(|| Error::InvalidMemoryReference)? + .clone()) +} + +/// Find the global named `__heap_base` in the given wasm module instance and +/// tries to get its value. +fn get_heap_base(module: &ModuleRef) -> Result { + let heap_base_val = module + .export_by_name("__heap_base") + .ok_or_else(|| Error::HeapBaseNotFoundOrInvalid)? + .as_global() + .ok_or_else(|| Error::HeapBaseNotFoundOrInvalid)? + .get(); + + match heap_base_val { + wasmi::RuntimeValue::I32(v) => Ok(v as u32), + _ => Err(Error::HeapBaseNotFoundOrInvalid), + } +} + +/// Call a given method in the given wasm-module runtime. +fn call_in_wasm_module( + ext: &mut dyn Externalities, + module_instance: &ModuleRef, + method: &str, + data: &[u8], + host_functions: &[&'static dyn Function], + allow_missing_imports: bool, + missing_functions: &Vec, +) -> Result, Error> { + // extract a reference to a linear memory, optional reference to a table + // and then initialize FunctionExecutor. + let memory = get_mem_instance(module_instance)?; + let table: Option = module_instance + .export_by_name("__indirect_function_table") + .and_then(|e| e.as_table().cloned()); + let heap_base = get_heap_base(module_instance)?; + + let mut fec = FunctionExecutor::new( + memory.clone(), + heap_base, + table, + host_functions, + allow_missing_imports, + missing_functions, + )?; + + // Write the call data + let offset = fec.allocate_memory(data.len() as u32)?; + fec.write_memory(offset, data)?; + + let result = sp_externalities::set_and_run_with_externalities( + ext, + || module_instance.invoke_export( + method, + &[I32(u32::from(offset) as i32), I32(data.len() as i32)], + &mut fec, + ), + ); + + match result { + Ok(Some(I64(r))) => { + let (ptr, length) = unpack_ptr_and_len(r as u64); + memory.get(ptr.into(), length as usize).map_err(|_| Error::Runtime) + }, + Err(e) => { + trace!( + target: "wasm-executor", + "Failed to execute code with {} pages", + memory.current_size().0 + ); + Err(e.into()) + }, + _ => Err(Error::InvalidReturn), + } +} + +/// Prepare module instance +fn instantiate_module( + heap_pages: usize, + module: &Module, + host_functions: &[&'static dyn Function], + allow_missing_imports: bool, +) -> Result<(ModuleRef, Vec), Error> { + let resolver = Resolver::new(host_functions, allow_missing_imports); + // start module instantiation. Don't run 'start' function yet. + let intermediate_instance = ModuleInstance::new( + module, + &ImportsBuilder::new().with_resolver("env", &resolver), + )?; + + // Verify that the module has the heap base global variable. + let _ = get_heap_base(intermediate_instance.not_started_instance())?; + + // Extract a reference to a linear memory. + let memory = get_mem_instance(intermediate_instance.not_started_instance())?; + memory.grow(Pages(heap_pages)).map_err(|_| Error::Runtime)?; + + if intermediate_instance.has_start() { + // Runtime is not allowed to have the `start` function. + Err(Error::RuntimeHasStartFn) + } else { + Ok((intermediate_instance.assert_no_start(), resolver.missing_functions.into_inner())) + } +} + +/// A state snapshot of an instance taken just after instantiation. +/// +/// It is used for restoring the state of the module after execution. +#[derive(Clone)] +struct StateSnapshot { + /// The offset and the content of the memory segments that should be used to restore the snapshot + data_segments: Vec<(u32, Vec)>, + /// The list of all global mutable variables of the module in their sequential order. + global_mut_values: Vec, + heap_pages: u64, +} + +impl StateSnapshot { + // Returns `None` if instance is not valid. + fn take( + module_instance: &ModuleRef, + data_segments: Vec, + heap_pages: u64, + ) -> Option { + let prepared_segments = data_segments + .into_iter() + .map(|mut segment| { + // Just replace contents of the segment since the segments will be discarded later + // anyway. + let contents = mem::replace(segment.value_mut(), vec![]); + + let init_expr = match segment.offset() { + Some(offset) => offset.code(), + // Return if the segment is passive + None => return None + }; + + // [op, End] + if init_expr.len() != 2 { + return None; + } + let offset = match init_expr[0] { + Instruction::I32Const(v) => v as u32, + Instruction::GetGlobal(idx) => { + let global_val = module_instance.globals().get(idx as usize)?.get(); + match global_val { + RuntimeValue::I32(v) => v as u32, + _ => return None, + } + } + _ => return None, + }; + + Some((offset, contents)) + }) + .collect::>>()?; + + // Collect all values of mutable globals. + let global_mut_values = module_instance + .globals() + .iter() + .filter(|g| g.is_mutable()) + .map(|g| g.get()) + .collect(); + + Some(Self { + data_segments: prepared_segments, + global_mut_values, + heap_pages, + }) + } + + /// Reset the runtime instance to the initial version by restoring + /// the preserved memory and globals. + /// + /// Returns `Err` if applying the snapshot is failed. + fn apply(&self, instance: &ModuleRef) -> Result<(), WasmError> { + let memory = instance + .export_by_name("memory") + .ok_or(WasmError::ApplySnapshotFailed)? + .as_memory() + .cloned() + .ok_or(WasmError::ApplySnapshotFailed)?; + + // First, erase the memory and copy the data segments into it. + memory + .erase() + .map_err(|e| WasmError::ErasingFailed(e.to_string()))?; + for (offset, contents) in &self.data_segments { + memory + .set(*offset, contents) + .map_err(|_| WasmError::ApplySnapshotFailed)?; + } + + // Second, restore the values of mutable globals. + for (global_ref, global_val) in instance + .globals() + .iter() + .filter(|g| g.is_mutable()) + .zip(self.global_mut_values.iter()) + { + // the instance should be the same as used for preserving and + // we iterate the same way it as we do it for preserving values that means that the + // types should be the same and all the values are mutable. So no error is expected/ + global_ref + .set(*global_val) + .map_err(|_| WasmError::ApplySnapshotFailed)?; + } + Ok(()) + } +} + +/// A runtime along with its initial state snapshot. +#[derive(Clone)] +pub struct WasmiRuntime { + /// A wasm module instance. + instance: ModuleRef, + /// The snapshot of the instance's state taken just after the instantiation. + state_snapshot: StateSnapshot, + /// The host functions registered for this instance. + host_functions: Vec<&'static dyn Function>, + /// Enable stub generation for functions that are not available in `host_functions`. + /// These stubs will error when the wasm blob tries to call them. + allow_missing_imports: bool, + /// List of missing functions detected during function resolution + missing_functions: Vec, +} + +impl WasmRuntime for WasmiRuntime { + fn update_heap_pages(&mut self, heap_pages: u64) -> bool { + self.state_snapshot.heap_pages == heap_pages + } + + fn host_functions(&self) -> &[&'static dyn Function] { + &self.host_functions + } + + fn call( + &mut self, + ext: &mut dyn Externalities, + method: &str, + data: &[u8], + ) -> Result, Error> { + self.state_snapshot.apply(&self.instance) + .map_err(|e| { + // Snapshot restoration failed. This is pretty unexpected since this can happen + // if some invariant is broken or if the system is under extreme memory pressure + // (so erasing fails). + error!(target: "wasm-executor", "snapshot restoration failed: {}", e); + e + })?; + call_in_wasm_module( + ext, + &self.instance, + method, + data, + &self.host_functions, + self.allow_missing_imports, + &self.missing_functions, + ) + } +} + +pub fn create_instance( + code: &[u8], + heap_pages: u64, + host_functions: Vec<&'static dyn Function>, + allow_missing_imports: bool, +) -> Result { + let module = Module::from_buffer(&code).map_err(|_| WasmError::InvalidModule)?; + + // Extract the data segments from the wasm code. + // + // A return of this error actually indicates that there is a problem in logic, since + // we just loaded and validated the `module` above. + let data_segments = extract_data_segments(&code)?; + + // Instantiate this module. + let (instance, missing_functions) = instantiate_module( + heap_pages as usize, + &module, + &host_functions, + allow_missing_imports, + ).map_err(|e| WasmError::Instantiation(e.to_string()))?; + + // Take state snapshot before executing anything. + let state_snapshot = StateSnapshot::take(&instance, data_segments, heap_pages) + .expect( + "`take` returns `Err` if the module is not valid; + we already loaded module above, thus the `Module` is proven to be valid at this point; + qed + ", + ); + + Ok(WasmiRuntime { + instance, + state_snapshot, + host_functions, + allow_missing_imports, + missing_functions, + }) +} + +/// Extract the data segments from the given wasm code. +/// +/// Returns `Err` if the given wasm code cannot be deserialized. +fn extract_data_segments(wasm_code: &[u8]) -> Result, WasmError> { + let raw_module: RawModule = deserialize_buffer(wasm_code) + .map_err(|_| WasmError::CantDeserializeWasm)?; + + let segments = raw_module + .data_section() + .map(|ds| ds.entries()) + .unwrap_or(&[]) + .to_vec(); + Ok(segments) +} diff --git a/client/executor/wasmtime/Cargo.toml b/client/executor/wasmtime/Cargo.toml new file mode 100644 index 0000000000000..0d6bede016e66 --- /dev/null +++ b/client/executor/wasmtime/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "sc-executor-wasmtime" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4.8" +wasmi = "0.6.2" +parity-wasm = "0.41.0" +codec = { package = "parity-scale-codec", version = "1.0.0" } +sc-executor-common = { version = "2.0.0", path = "../common" } +sp-wasm-interface = { version = "2.0.0", path = "../../../primitives/wasm-interface" } +sp-runtime-interface = { version = "2.0.0", path = "../../../primitives/runtime-interface" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-externalities = { version = "2.0.0", path = "../../../primitives/externalities" } + +cranelift-codegen = "0.50" +cranelift-entity = "0.50" +cranelift-frontend = "0.50" +cranelift-native = "0.50" +cranelift-wasm = "0.50" +wasmtime-environ = "0.8" +wasmtime-jit = "0.8" +wasmtime-runtime = "0.8" + +[dev-dependencies] +assert_matches = "1.3.0" diff --git a/client/executor/wasmtime/src/function_executor.rs b/client/executor/wasmtime/src/function_executor.rs new file mode 100644 index 0000000000000..b398ea8476d8b --- /dev/null +++ b/client/executor/wasmtime/src/function_executor.rs @@ -0,0 +1,387 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sc_executor_common::allocator::FreeingBumpHeapAllocator; +use sc_executor_common::error::{Error, Result}; +use sc_executor_common::sandbox::{self, SandboxCapabilities, SupervisorFuncIndex}; +use crate::util::{ + checked_range, cranelift_ir_signature, read_memory_into, write_memory_from, +}; + +use codec::{Decode, Encode}; +use cranelift_codegen::ir; +use cranelift_codegen::isa::TargetFrontendConfig; +use log::trace; +use sp_core::sandbox as sandbox_primitives; +use std::{cmp, mem, ptr}; +use wasmtime_environ::translate_signature; +use wasmtime_jit::{ActionError, Compiler}; +use wasmtime_runtime::{Export, VMCallerCheckedAnyfunc, VMContext, wasmtime_call_trampoline}; +use sp_wasm_interface::{ + FunctionContext, MemoryId, Pointer, Result as WResult, Sandbox, Signature, Value, ValueType, + WordSize, +}; + +/// Wrapper type for pointer to a Wasm table entry. +/// +/// The wrapper type is used to ensure that the function reference is valid as it must be unsafely +/// dereferenced from within the safe method `::invoke`. +#[derive(Clone, Copy)] +pub struct SupervisorFuncRef(*const VMCallerCheckedAnyfunc); + +/// The state required to construct a FunctionExecutor context. The context only lasts for one host +/// call, whereas the state is maintained for the duration of a Wasm runtime call, which may make +/// many different host calls that must share state. +/// +/// This is stored as part of the host state of the "env" Wasmtime instance. +pub struct FunctionExecutorState { + sandbox_store: sandbox::Store, + heap: FreeingBumpHeapAllocator, +} + +impl FunctionExecutorState { + /// Constructs a new `FunctionExecutorState`. + pub fn new(heap_base: u32) -> Self { + FunctionExecutorState { + sandbox_store: sandbox::Store::new(), + heap: FreeingBumpHeapAllocator::new(heap_base), + } + } + + /// Returns a mutable reference to the heap allocator. + pub fn heap(&mut self) -> &mut FreeingBumpHeapAllocator { + &mut self.heap + } +} + +/// A `FunctionExecutor` implements `FunctionContext` for making host calls from a Wasmtime +/// runtime. The `FunctionExecutor` exists only for the lifetime of the call and borrows state from +/// a longer-living `FunctionExecutorState`. +pub struct FunctionExecutor<'a> { + compiler: &'a mut Compiler, + sandbox_store: &'a mut sandbox::Store, + heap: &'a mut FreeingBumpHeapAllocator, + memory: &'a mut [u8], + table: Option<&'a [VMCallerCheckedAnyfunc]>, +} + +impl<'a> FunctionExecutor<'a> { + /// Construct a new `FunctionExecutor`. + /// + /// The vmctx MUST come from a call to a function in the "env" module. + /// The state MUST be looked up from the host state of the "env" module. + pub unsafe fn new( + vmctx: *mut VMContext, + compiler: &'a mut Compiler, + state: &'a mut FunctionExecutorState, + ) -> Result + { + let memory = match (*vmctx).lookup_global_export("memory") { + Some(Export::Memory { definition, vmctx: _, memory: _ }) => + std::slice::from_raw_parts_mut( + (*definition).base, + (*definition).current_length, + ), + _ => return Err(Error::InvalidMemoryReference), + }; + let table = match (*vmctx).lookup_global_export("__indirect_function_table") { + Some(Export::Table { definition, vmctx: _, table: _ }) => + Some(std::slice::from_raw_parts( + (*definition).base as *const VMCallerCheckedAnyfunc, + (*definition).current_elements as usize, + )), + _ => None, + }; + Ok(FunctionExecutor { + compiler, + sandbox_store: &mut state.sandbox_store, + heap: &mut state.heap, + memory, + table, + }) + } +} + +impl<'a> SandboxCapabilities for FunctionExecutor<'a> { + type SupervisorFuncRef = SupervisorFuncRef; + + fn store(&self) -> &sandbox::Store { + &self.sandbox_store + } + + fn store_mut(&mut self) -> &mut sandbox::Store { + &mut self.sandbox_store + } + + fn allocate(&mut self, len: WordSize) -> Result> { + self.heap.allocate(self.memory, len) + } + + fn deallocate(&mut self, ptr: Pointer) -> Result<()> { + self.heap.deallocate(self.memory, ptr) + } + + fn write_memory(&mut self, ptr: Pointer, data: &[u8]) -> Result<()> { + write_memory_from(self.memory, ptr, data) + } + + fn read_memory(&self, ptr: Pointer, len: WordSize) -> Result> { + let mut output = vec![0; len as usize]; + read_memory_into(self.memory, ptr, output.as_mut())?; + Ok(output) + } + + fn invoke( + &mut self, + dispatch_thunk: &Self::SupervisorFuncRef, + invoke_args_ptr: Pointer, + invoke_args_len: WordSize, + state: u32, + func_idx: SupervisorFuncIndex, + ) -> Result + { + let func_ptr = unsafe { (*dispatch_thunk.0).func_ptr }; + let vmctx = unsafe { (*dispatch_thunk.0).vmctx }; + + // The following code is based on the wasmtime_jit::Context::invoke. + let value_size = mem::size_of::(); + let (signature, mut values_vec) = generate_signature_and_args( + &[ + Value::I32(u32::from(invoke_args_ptr) as i32), + Value::I32(invoke_args_len as i32), + Value::I32(state as i32), + Value::I32(usize::from(func_idx) as i32), + ], + Some(ValueType::I64), + self.compiler.frontend_config(), + ); + + // Get the trampoline to call for this function. + let exec_code_buf = self.compiler + .get_published_trampoline(func_ptr, &signature, value_size) + .map_err(ActionError::Setup) + .map_err(|e| Error::Other(e.to_string()))?; + + // Call the trampoline. + if let Err(message) = unsafe { + wasmtime_call_trampoline( + vmctx, + exec_code_buf, + values_vec.as_mut_ptr() as *mut u8, + ) + } { + return Err(Error::Other(message)); + } + + // Load the return value out of `values_vec`. + Ok(unsafe { ptr::read(values_vec.as_ptr() as *const i64) }) + } +} + +impl<'a> FunctionContext for FunctionExecutor<'a> { + fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> WResult<()> { + read_memory_into(self.memory, address, dest).map_err(|e| e.to_string()) + } + + fn write_memory(&mut self, address: Pointer, data: &[u8]) -> WResult<()> { + write_memory_from(self.memory, address, data).map_err(|e| e.to_string()) + } + + fn allocate_memory(&mut self, size: WordSize) -> WResult> { + self.heap.allocate(self.memory, size).map_err(|e| e.to_string()) + } + + fn deallocate_memory(&mut self, ptr: Pointer) -> WResult<()> { + self.heap.deallocate(self.memory, ptr).map_err(|e| e.to_string()) + } + + fn sandbox(&mut self) -> &mut dyn Sandbox { + self + } +} + +impl<'a> Sandbox for FunctionExecutor<'a> { + fn memory_get( + &mut self, + memory_id: MemoryId, + offset: WordSize, + buf_ptr: Pointer, + buf_len: WordSize, + ) -> WResult + { + let sandboxed_memory = self.sandbox_store.memory(memory_id) + .map_err(|e| e.to_string())?; + sandboxed_memory.with_direct_access(|memory| { + let len = buf_len as usize; + let src_range = match checked_range(offset as usize, len, memory.len()) { + Some(range) => range, + None => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + }; + let dst_range = match checked_range(buf_ptr.into(), len, self.memory.len()) { + Some(range) => range, + None => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + }; + &mut self.memory[dst_range].copy_from_slice(&memory[src_range]); + Ok(sandbox_primitives::ERR_OK) + }) + } + + fn memory_set( + &mut self, + memory_id: MemoryId, + offset: WordSize, + val_ptr: Pointer, + val_len: WordSize, + ) -> WResult + { + let sandboxed_memory = self.sandbox_store.memory(memory_id) + .map_err(|e| e.to_string())?; + sandboxed_memory.with_direct_access_mut(|memory| { + let len = val_len as usize; + let src_range = match checked_range(val_ptr.into(), len, self.memory.len()) { + Some(range) => range, + None => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + }; + let dst_range = match checked_range(offset as usize, len, memory.len()) { + Some(range) => range, + None => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + }; + &mut memory[dst_range].copy_from_slice(&self.memory[src_range]); + Ok(sandbox_primitives::ERR_OK) + }) + } + + fn memory_teardown(&mut self, memory_id: MemoryId) + -> WResult<()> + { + self.sandbox_store.memory_teardown(memory_id).map_err(|e| e.to_string()) + } + + fn memory_new(&mut self, initial: u32, maximum: MemoryId) -> WResult { + self.sandbox_store.new_memory(initial, maximum).map_err(|e| e.to_string()) + } + + fn invoke( + &mut self, + instance_id: u32, + export_name: &str, + args: &[u8], + return_val: Pointer, + return_val_len: u32, + state: u32, + ) -> WResult { + trace!(target: "sp-sandbox", "invoke, instance_idx={}", instance_id); + + // Deserialize arguments and convert them into wasmi types. + let args = Vec::::decode(&mut &args[..]) + .map_err(|_| "Can't decode serialized arguments for the invocation")? + .into_iter() + .map(Into::into) + .collect::>(); + + let instance = self.sandbox_store.instance(instance_id).map_err(|e| e.to_string())?; + let result = instance.invoke(export_name, &args, self, state); + + match result { + Ok(None) => Ok(sandbox_primitives::ERR_OK), + Ok(Some(val)) => { + // Serialize return value and write it back into the memory. + sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| { + if val.len() > return_val_len as usize { + Err("Return value buffer is too small")?; + } + FunctionContext::write_memory(self, return_val, val)?; + Ok(sandbox_primitives::ERR_OK) + }) + } + Err(_) => Ok(sandbox_primitives::ERR_EXECUTION), + } + } + + fn instance_teardown(&mut self, instance_id: u32) -> WResult<()> { + self.sandbox_store.instance_teardown(instance_id).map_err(|e| e.to_string()) + } + + fn instance_new(&mut self, dispatch_thunk_id: u32, wasm: &[u8], raw_env_def: &[u8], state: u32) + -> WResult + { + // Extract a dispatch thunk from instance's table by the specified index. + let dispatch_thunk = { + let table = self.table.as_ref() + .ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")?; + let func_ref = table.get(dispatch_thunk_id as usize) + .ok_or_else(|| "dispatch_thunk_idx is out of the table bounds")?; + SupervisorFuncRef(func_ref) + }; + + let instance_idx_or_err_code = + match sandbox::instantiate(self, dispatch_thunk, wasm, raw_env_def, state) { + Ok(instance_idx) => instance_idx, + Err(sandbox::InstantiationError::StartTrapped) => + sandbox_primitives::ERR_EXECUTION, + Err(_) => sandbox_primitives::ERR_MODULE, + }; + + Ok(instance_idx_or_err_code as u32) + } +} + +// The storage for a Wasmtime invocation argument. +#[derive(Debug, Default, Copy, Clone)] +#[repr(C, align(8))] +struct VMInvokeArgument([u8; 8]); + +fn generate_signature_and_args( + args: &[Value], + result_type: Option, + frontend_config: TargetFrontendConfig, +) -> (ir::Signature, Vec) +{ + // This code is based on the wasmtime_jit::Context::invoke. + + let param_types = args.iter() + .map(|arg| arg.value_type()) + .collect::>(); + let signature = translate_signature( + cranelift_ir_signature( + Signature::new(param_types, result_type), + &frontend_config.default_call_conv + ), + frontend_config.pointer_type() + ); + + let mut values_vec = vec![ + VMInvokeArgument::default(); + cmp::max(args.len(), result_type.iter().len()) + ]; + + // Store the argument values into `values_vec`. + for (index, arg) in args.iter().enumerate() { + unsafe { + let ptr = values_vec.as_mut_ptr().add(index); + + match arg { + Value::I32(x) => ptr::write(ptr as *mut i32, *x), + Value::I64(x) => ptr::write(ptr as *mut i64, *x), + Value::F32(x) => ptr::write(ptr as *mut u32, *x), + Value::F64(x) => ptr::write(ptr as *mut u64, *x), + } + } + } + + (signature, values_vec) +} + diff --git a/client/executor/wasmtime/src/lib.rs b/client/executor/wasmtime/src/lib.rs new file mode 100644 index 0000000000000..244fca8f842a3 --- /dev/null +++ b/client/executor/wasmtime/src/lib.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +///! Defines a `WasmRuntime` that uses the Wasmtime JIT to execute. + +mod function_executor; +mod runtime; +mod trampoline; +mod util; + +pub use runtime::create_instance; + diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs new file mode 100644 index 0000000000000..ae4739d1f1d3f --- /dev/null +++ b/client/executor/wasmtime/src/runtime.rs @@ -0,0 +1,373 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Defines the compiled Wasm runtime that uses Wasmtime internally. + +use crate::function_executor::FunctionExecutorState; +use crate::trampoline::{EnvState, make_trampoline}; +use crate::util::{cranelift_ir_signature, read_memory_into, write_memory_from}; + +use sc_executor_common::{ + error::{Error, Result, WasmError}, + wasm_runtime::WasmRuntime, +}; +use sp_core::traits::Externalities; +use sp_wasm_interface::{Pointer, WordSize, Function}; +use sp_runtime_interface::unpack_ptr_and_len; + +use std::cell::RefCell; +use std::collections::HashMap; +use std::convert::TryFrom; +use std::rc::Rc; + +use cranelift_codegen::ir; +use cranelift_codegen::isa::TargetIsa; +use cranelift_entity::{EntityRef, PrimaryMap}; +use cranelift_frontend::FunctionBuilderContext; +use cranelift_wasm::DefinedFuncIndex; +use wasmtime_environ::{Module, translate_signature}; +use wasmtime_jit::{ + ActionOutcome, CodeMemory, CompilationStrategy, CompiledModule, Compiler, Context, RuntimeValue, +}; +use wasmtime_runtime::{Export, Imports, InstanceHandle, VMFunctionBody}; + +/// A `WasmRuntime` implementation using the Wasmtime JIT to compile the runtime module to native +/// and execute the compiled code. +pub struct WasmtimeRuntime { + module: CompiledModule, + context: Context, + max_heap_pages: Option, + heap_pages: u32, + /// The host functions registered for this instance. + host_functions: Vec<&'static dyn Function>, +} + +impl WasmRuntime for WasmtimeRuntime { + fn update_heap_pages(&mut self, heap_pages: u64) -> bool { + match heap_pages_valid(heap_pages, self.max_heap_pages) { + Some(heap_pages) => { + self.heap_pages = heap_pages; + true + } + None => false, + } + } + + fn host_functions(&self) -> &[&'static dyn Function] { + &self.host_functions + } + + fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result> { + call_method( + &mut self.context, + &mut self.module, + ext, + method, + data, + self.heap_pages, + ) + } +} + +/// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to +/// machine code, which can be computationally heavy. +pub fn create_instance( + code: &[u8], + heap_pages: u64, + host_functions: Vec<&'static dyn Function>, +) -> std::result::Result { + let (compiled_module, context) = create_compiled_unit(code, &host_functions)?; + + // Inspect the module for the min and max memory sizes. + let (min_memory_size, max_memory_size) = { + let module = compiled_module.module_ref(); + let memory_index = match module.exports.get("memory") { + Some(wasmtime_environ::Export::Memory(memory_index)) => *memory_index, + _ => return Err(WasmError::InvalidMemory), + }; + let memory_plan = module.memory_plans.get(memory_index) + .expect("memory_index is retrieved from the module's exports map; qed"); + (memory_plan.memory.minimum, memory_plan.memory.maximum) + }; + + // Check that heap_pages is within the allowed range. + let max_heap_pages = max_memory_size.map(|max| max.saturating_sub(min_memory_size)); + let heap_pages = heap_pages_valid(heap_pages, max_heap_pages) + .ok_or_else(|| WasmError::InvalidHeapPages)?; + + Ok(WasmtimeRuntime { + module: compiled_module, + context, + max_heap_pages, + heap_pages, + host_functions, + }) +} + +fn create_compiled_unit( + code: &[u8], + host_functions: &[&'static dyn Function], +) -> std::result::Result<(CompiledModule, Context), WasmError> { + let compilation_strategy = CompilationStrategy::Cranelift; + + let compiler = new_compiler(compilation_strategy)?; + let mut context = Context::new(Box::new(compiler)); + + // Enable/disable producing of debug info. + context.set_debug_info(false); + + // Instantiate and link the env module. + let global_exports = context.get_global_exports(); + let compiler = new_compiler(compilation_strategy)?; + let env_module = instantiate_env_module(global_exports, compiler, host_functions)?; + context.name_instance("env".to_owned(), env_module); + + // Compile the wasm module. + let module = context.compile_module(&code) + .map_err(|e| WasmError::Other(format!("module compile error: {}", e)))?; + + Ok((module, context)) +} + +/// Call a function inside a precompiled Wasm module. +fn call_method( + context: &mut Context, + module: &mut CompiledModule, + ext: &mut dyn Externalities, + method: &str, + data: &[u8], + heap_pages: u32, +) -> Result> { + // Old exports get clobbered in `InstanceHandle::new` if we don't explicitly remove them first. + // + // The global exports mechanism is temporary in Wasmtime and expected to be removed. + // https://github.com/CraneStation/wasmtime/issues/332 + clear_globals(&mut *context.get_global_exports().borrow_mut()); + + let mut instance = module.instantiate() + .map_err(|e| Error::Other(e.to_string()))?; + + // Ideally there would be a way to set the heap pages during instantiation rather than + // growing the memory after the fact. Currently this may require an additional mmap and copy. + // However, the wasmtime API doesn't support modifying the size of memory on instantiation + // at this time. + grow_memory(&mut instance, heap_pages)?; + + // Initialize the function executor state. + let heap_base = get_heap_base(&instance)?; + let executor_state = FunctionExecutorState::new(heap_base); + reset_env_state_and_take_trap(context, Some(executor_state))?; + + // Write the input data into guest memory. + let (data_ptr, data_len) = inject_input_data(context, &mut instance, data)?; + let args = [RuntimeValue::I32(u32::from(data_ptr) as i32), RuntimeValue::I32(data_len as i32)]; + + // Invoke the function in the runtime. + let outcome = sp_externalities::set_and_run_with_externalities(ext, || { + context + .invoke(&mut instance, method, &args[..]) + .map_err(|e| Error::Other(format!("error calling runtime: {}", e))) + })?; + let trap_error = reset_env_state_and_take_trap(context, None)?; + let (output_ptr, output_len) = match outcome { + ActionOutcome::Returned { values } => match values.as_slice() { + [RuntimeValue::I64(retval)] => unpack_ptr_and_len(*retval as u64), + _ => return Err(Error::InvalidReturn), + } + ActionOutcome::Trapped { message } => return Err(trap_error.unwrap_or_else( + || format!("Wasm execution trapped: {}", message).into() + )), + }; + + // Read the output data from guest memory. + let mut output = vec![0; output_len as usize]; + let memory = get_memory_mut(&mut instance)?; + read_memory_into(memory, Pointer::new(output_ptr), &mut output)?; + Ok(output) +} + +/// The implementation is based on wasmtime_wasi::instantiate_wasi. +fn instantiate_env_module( + global_exports: Rc>>>, + compiler: Compiler, + host_functions: &[&'static dyn Function], +) -> std::result::Result +{ + let isa = target_isa()?; + let pointer_type = isa.pointer_type(); + let call_conv = isa.default_call_conv(); + + let mut fn_builder_ctx = FunctionBuilderContext::new(); + let mut module = Module::new(); + let mut finished_functions = >::new(); + let mut code_memory = CodeMemory::new(); + + for function in host_functions { + let sig = translate_signature( + cranelift_ir_signature(function.signature(), &call_conv), + pointer_type + ); + let sig_id = module.signatures.push(sig.clone()); + let func_id = module.functions.push(sig_id); + module + .exports + .insert(function.name().to_string(), wasmtime_environ::Export::Function(func_id)); + + let trampoline = make_trampoline( + isa.as_ref(), + &mut code_memory, + &mut fn_builder_ctx, + func_id.index() as u32, + &sig, + )?; + finished_functions.push(trampoline); + } + + code_memory.publish(); + + let imports = Imports::none(); + let data_initializers = Vec::new(); + let signatures = PrimaryMap::new(); + let env_state = EnvState::new(code_memory, compiler, host_functions); + + let result = InstanceHandle::new( + Rc::new(module), + global_exports, + finished_functions.into_boxed_slice(), + imports, + &data_initializers, + signatures.into_boxed_slice(), + None, + Box::new(env_state), + ); + result.map_err(|e| WasmError::Other(format!("cannot instantiate env: {}", e))) +} + +/// Build a new TargetIsa for the host machine. +fn target_isa() -> std::result::Result, WasmError> { + let isa_builder = cranelift_native::builder() + .map_err(|e| WasmError::Other(format!("missing compiler support: {}", e)))?; + let flag_builder = cranelift_codegen::settings::builder(); + Ok(isa_builder.finish(cranelift_codegen::settings::Flags::new(flag_builder))) +} + +fn new_compiler(strategy: CompilationStrategy) -> std::result::Result { + let isa = target_isa()?; + Ok(Compiler::new(isa, strategy)) +} + +fn clear_globals(global_exports: &mut HashMap>) { + global_exports.remove("memory"); + global_exports.remove("__heap_base"); + global_exports.remove("__indirect_function_table"); +} + +fn grow_memory(instance: &mut InstanceHandle, pages: u32) -> Result<()> { + // This is safe to wrap in an unsafe block as: + // - The result of the `lookup_immutable` call is not mutated + // - The definition pointer is returned by a lookup on a valid instance + let memory_index = unsafe { + match instance.lookup_immutable("memory") { + Some(Export::Memory { definition, vmctx: _, memory: _ }) => + instance.memory_index(&*definition), + _ => return Err(Error::InvalidMemoryReference), + } + }; + instance.memory_grow(memory_index, pages) + .map(|_| ()) + .ok_or_else(|| "requested heap_pages would exceed maximum memory size".into()) +} + +fn get_env_state(context: &mut Context) -> Result<&mut EnvState> { + let env_instance = context.get_instance("env") + .map_err(|err| format!("cannot find \"env\" module: {}", err))?; + env_instance + .host_state() + .downcast_mut::() + .ok_or_else(|| "cannot get \"env\" module host state".into()) +} + +fn reset_env_state_and_take_trap( + context: &mut Context, + executor_state: Option, +) -> Result> +{ + let env_state = get_env_state(context)?; + env_state.executor_state = executor_state; + Ok(env_state.take_trap()) +} + +fn inject_input_data( + context: &mut Context, + instance: &mut InstanceHandle, + data: &[u8], +) -> Result<(Pointer, WordSize)> { + let env_state = get_env_state(context)?; + let executor_state = env_state.executor_state + .as_mut() + .ok_or_else(|| "cannot get \"env\" module executor state")?; + + let memory = get_memory_mut(instance)?; + + let data_len = data.len() as WordSize; + let data_ptr = executor_state.heap().allocate(memory, data_len)?; + write_memory_from(memory, data_ptr, data)?; + Ok((data_ptr, data_len)) +} + +fn get_memory_mut(instance: &mut InstanceHandle) -> Result<&mut [u8]> { + match instance.lookup("memory") { + // This is safe to wrap in an unsafe block as: + // - The definition pointer is returned by a lookup on a valid instance and thus points to + // a valid memory definition + Some(Export::Memory { definition, vmctx: _, memory: _ }) => unsafe { + Ok(std::slice::from_raw_parts_mut( + (*definition).base, + (*definition).current_length, + )) + }, + _ => Err(Error::InvalidMemoryReference), + } +} + +fn get_heap_base(instance: &InstanceHandle) -> Result { + // This is safe to wrap in an unsafe block as: + // - The result of the `lookup_immutable` call is not mutated + // - The definition pointer is returned by a lookup on a valid instance + // - The defined value is checked to be an I32, which can be read safely as a u32 + unsafe { + match instance.lookup_immutable("__heap_base") { + Some(Export::Global { definition, vmctx: _, global }) + if global.ty == ir::types::I32 => + Ok(*(*definition).as_u32()), + _ => return Err(Error::HeapBaseNotFoundOrInvalid), + } + } +} + +/// Checks whether the heap_pages parameter is within the valid range and converts it to a u32. +/// Returns None if heaps_pages in not in range. +fn heap_pages_valid(heap_pages: u64, max_heap_pages: Option) + -> Option +{ + let heap_pages = u32::try_from(heap_pages).ok()?; + if let Some(max_heap_pages) = max_heap_pages { + if heap_pages > max_heap_pages { + return None; + } + } + Some(heap_pages) +} diff --git a/client/executor/wasmtime/src/trampoline.rs b/client/executor/wasmtime/src/trampoline.rs new file mode 100644 index 0000000000000..8a2147760921b --- /dev/null +++ b/client/executor/wasmtime/src/trampoline.rs @@ -0,0 +1,361 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! The trampoline is the dynamically generated entry point to a runtime host call. +//! +//! This code is based on and large parts are copied from wasmtime's +//! wasmtime-api/src/trampoline/func.rs. + +use crate::function_executor::{FunctionExecutorState, FunctionExecutor}; +use sc_executor_common::error::{Error, WasmError}; + +use cranelift_codegen::{Context, binemit, ir, isa}; +use cranelift_codegen::ir::{InstBuilder, StackSlotData, StackSlotKind, TrapCode}; +use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; +use cranelift_codegen::print_errors::pretty_error; +use wasmtime_jit::{CodeMemory, Compiler}; +use wasmtime_environ::CompiledFunction; +use wasmtime_runtime::{VMContext, VMFunctionBody}; +use sp_wasm_interface::{Function, Value, ValueType}; +use std::{cmp, panic::{self, AssertUnwindSafe}, ptr}; + +const CALL_SUCCESS: u32 = 0; +const CALL_FAILED_WITH_ERROR: u32 = 1; +const CALL_WITH_BAD_HOST_STATE: u32 = 2; + +/// A code to trap with that indicates a host call error. +const TRAP_USER_CODE: u16 = 0; + +/// The only Wasm types allowed in host function signatures (I32, I64, F32, F64) are all +/// represented in at most 8 bytes. +const MAX_WASM_TYPE_SIZE: usize = 8; + +/// The top-level host state of the "env" module. This state is used by the trampoline function to +/// construct a `FunctionExecutor` which can execute the host call. +pub struct EnvState { + host_functions: Vec<&'static dyn Function>, + compiler: Compiler, + // The code memory must be kept around on the state to prevent it from being dropped. + #[allow(dead_code)] + code_memory: CodeMemory, + trap: Option, + /// The executor state stored across host calls during a single Wasm runtime call. + /// During a runtime call, this MUST be `Some`. + pub executor_state: Option, +} + +impl EnvState { + /// Construct a new `EnvState` which owns the given code memory. + pub fn new( + code_memory: CodeMemory, + compiler: Compiler, + host_functions: &[&'static dyn Function], + ) -> Self { + EnvState { + trap: None, + compiler, + code_memory, + executor_state: None, + host_functions: host_functions.to_vec(), + } + } + + /// Resets the trap error to None and returns the current value. + pub fn take_trap(&mut self) -> Option { + self.trap.take() + } +} + +/// This is called by the dynamically generated trampoline taking the function index and reference +/// to the call arguments on the stack as arguments. Returns zero on success and a non-zero value +/// on failure. +unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, func_index: u32, values_vec: *mut i64) -> u32 { + if let Some(state) = (*vmctx).host_state().downcast_mut::() { + match stub_fn_inner( + vmctx, + &state.host_functions, + &mut state.compiler, + state.executor_state.as_mut(), + func_index, + values_vec, + ) { + Ok(()) => CALL_SUCCESS, + Err(err) => { + state.trap = Some(err); + CALL_FAILED_WITH_ERROR + } + } + } else { + // Well, we can't even set a trap message, so we'll just exit without one. + CALL_WITH_BAD_HOST_STATE + } +} + +/// Implements most of the logic in `stub_fn` but returning a `Result` instead of an integer error +/// for the sake of readability. +unsafe fn stub_fn_inner( + vmctx: *mut VMContext, + externals: &[&dyn Function], + compiler: &mut Compiler, + executor_state: Option<&mut FunctionExecutorState>, + func_index: u32, + values_vec: *mut i64, +) -> Result<(), Error> { + let func = externals.get(func_index as usize) + .ok_or_else(|| format!("call to undefined external function with index {}", func_index))?; + let executor_state = executor_state + .ok_or_else(|| "executor state is None during call to external function")?; + + // Build the external function context. + let mut context = FunctionExecutor::new(vmctx, compiler, executor_state)?; + let mut context = AssertUnwindSafe(&mut context); + + // Execute and write output back to the stack. + let return_val = panic::catch_unwind(move || { + let signature = func.signature(); + + // Read the arguments from the stack. + let mut args = signature.args.iter() + .enumerate() + .map(|(i, ¶m_type)| read_value_from(values_vec.offset(i as isize), param_type)); + + func.execute(&mut **context, &mut args) + }); + + match return_val { + Ok(ret_val) => { + if let Some(val) = ret_val + .map_err(|e| Error::FunctionExecution(func.name().to_string(), e))? { + write_value_to(values_vec, val); + } + + Ok(()) + }, + Err(e) => { + let message = if let Some(err) = e.downcast_ref::() { + err.to_string() + } else if let Some(err) = e.downcast_ref::<&str>() { + err.to_string() + } else { + "Panicked without any further information!".into() + }; + + Err(Error::FunctionExecution(func.name().to_string(), message)) + } + } +} + +/// Create a trampoline for invoking a host function. +/// +/// The trampoline is a dynamically generated entry point to a runtime host call. The function is +/// generated by manually constructing Cranelift IR and using the Cranelift compiler. The +/// trampoline embeds the function index as a constant and delegates to a stub function in Rust, +/// which takes the function index and a memory reference to the stack arguments and return value +/// slots. +/// +/// This code is of modified copy of wasmtime's wasmtime-api/src/trampoline/func.rs. +pub fn make_trampoline( + isa: &dyn isa::TargetIsa, + code_memory: &mut CodeMemory, + fn_builder_ctx: &mut FunctionBuilderContext, + func_index: u32, + signature: &ir::Signature, +) -> Result<*const VMFunctionBody, WasmError> { + // Mostly reverse copy of the similar method from wasmtime's + // wasmtime-jit/src/compiler.rs. + let pointer_type = isa.pointer_type(); + let mut stub_sig = ir::Signature::new(isa.frontend_config().default_call_conv); + + // Ensure that the first parameter of the generated function is the `VMContext` pointer. + assert_eq!( + signature.params[0], + ir::AbiParam::special(pointer_type, ir::ArgumentPurpose::VMContext) + ); + + // Add the `vmctx` parameter. + stub_sig.params.push(ir::AbiParam::special( + pointer_type, + ir::ArgumentPurpose::VMContext, + )); + + // Add the `func_index` parameter. + stub_sig.params.push(ir::AbiParam::new(ir::types::I32)); + + // Add the `values_vec` parameter. + stub_sig.params.push(ir::AbiParam::new(pointer_type)); + + // Add error/trap return. + stub_sig.returns.push(ir::AbiParam::new(ir::types::I32)); + + // Each parameter and return value gets a 64-bit (8-byte) wide slot on the stack, as that is + // large enough to fit all Wasm primitive types that can be used in host function signatures. + // The `VMContext` pointer, which is a parameter of the function signature, is excluded as it + // is passed directly to the stub function rather than being looked up on the caller stack from + // the `values_vec` pointer. + let values_vec_len = cmp::max(signature.params.len() - 1, signature.returns.len()); + let values_vec_size = (MAX_WASM_TYPE_SIZE * values_vec_len) as u32; + + let mut context = Context::new(); + context.func = + ir::Function::with_name_signature(ir::ExternalName::user(0, 0), signature.clone()); + + let ss = context.func.create_stack_slot(StackSlotData::new( + StackSlotKind::ExplicitSlot, + values_vec_size, + )); + + { + let mut builder = FunctionBuilder::new(&mut context.func, fn_builder_ctx); + let block0 = builder.create_ebb(); + + builder.append_ebb_params_for_function_params(block0); + builder.switch_to_block(block0); + builder.seal_block(block0); + + let values_vec_ptr_val = builder.ins().stack_addr(pointer_type, ss, 0); + let mflags = ir::MemFlags::trusted(); + for i in 1..signature.params.len() { + let val = builder.func.dfg.ebb_params(block0)[i]; + builder.ins().store( + mflags, + val, + values_vec_ptr_val, + ((i - 1) * MAX_WASM_TYPE_SIZE) as i32, + ); + } + + let vmctx_ptr_val = builder.func.dfg.ebb_params(block0)[0]; + let func_index_val = builder.ins().iconst(ir::types::I32, func_index as i64); + + let callee_args = vec![vmctx_ptr_val, func_index_val, values_vec_ptr_val]; + + let new_sig = builder.import_signature(stub_sig.clone()); + + let callee_value = builder + .ins() + .iconst(pointer_type, stub_fn as *const VMFunctionBody as i64); + let call = builder + .ins() + .call_indirect(new_sig, callee_value, &callee_args); + + let call_result = builder.func.dfg.inst_results(call)[0]; + builder.ins().trapnz(call_result, TrapCode::User(TRAP_USER_CODE)); + + let mflags = ir::MemFlags::trusted(); + let mut results = Vec::new(); + for (i, r) in signature.returns.iter().enumerate() { + let load = builder.ins().load( + r.value_type, + mflags, + values_vec_ptr_val, + (i * MAX_WASM_TYPE_SIZE) as i32, + ); + results.push(load); + } + builder.ins().return_(&results); + builder.finalize() + } + + let mut code_buf: Vec = Vec::new(); + let mut reloc_sink = RelocSink; + let mut trap_sink = binemit::NullTrapSink {}; + let mut stackmap_sink = binemit::NullStackmapSink {}; + context + .compile_and_emit( + isa, + &mut code_buf, + &mut reloc_sink, + &mut trap_sink, + &mut stackmap_sink, + ) + .map_err(|e| { + WasmError::Instantiation(format!( + "failed to compile trampoline: {}", + pretty_error(&context.func, Some(isa), e) + )) + })?; + + let mut unwind_info = Vec::new(); + context.emit_unwind_info(isa, &mut unwind_info); + + let func_ref = code_memory + .allocate_for_function(&CompiledFunction { + body: code_buf, + jt_offsets: context.func.jt_offsets, + unwind_info, + }) + .map_err(|e| WasmError::Instantiation(format!("failed to allocate code memory: {}", e)))?; + + Ok(func_ref.as_ptr()) +} + +/// We don't expect trampoline compilation to produce any relocations, so +/// this `RelocSink` just asserts that it doesn't recieve any. +struct RelocSink; + +impl binemit::RelocSink for RelocSink { + fn reloc_ebb( + &mut self, + _offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _ebb_offset: binemit::CodeOffset, + ) { + panic!("trampoline compilation should not produce ebb relocs"); + } + fn reloc_external( + &mut self, + _offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _name: &ir::ExternalName, + _addend: binemit::Addend, + ) { + panic!("trampoline compilation should not produce external symbol relocs"); + } + fn reloc_constant( + &mut self, + _code_offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _constant_offset: ir::ConstantOffset, + ) { + panic!("trampoline compilation should not produce constant relocs"); + } + fn reloc_jt( + &mut self, + _offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _jt: ir::JumpTable, + ) { + panic!("trampoline compilation should not produce jump table relocs"); + } +} + +unsafe fn write_value_to(p: *mut i64, val: Value) { + match val { + Value::I32(i) => ptr::write(p as *mut i32, i), + Value::I64(i) => ptr::write(p as *mut i64, i), + Value::F32(u) => ptr::write(p as *mut u32, u), + Value::F64(u) => ptr::write(p as *mut u64, u), + } +} + +unsafe fn read_value_from(p: *const i64, ty: ValueType) -> Value { + match ty { + ValueType::I32 => Value::I32(ptr::read(p as *const i32)), + ValueType::I64 => Value::I64(ptr::read(p as *const i64)), + ValueType::F32 => Value::F32(ptr::read(p as *const u32)), + ValueType::F64 => Value::F64(ptr::read(p as *const u64)), + } +} diff --git a/client/executor/wasmtime/src/util.rs b/client/executor/wasmtime/src/util.rs new file mode 100644 index 0000000000000..551295911a9cf --- /dev/null +++ b/client/executor/wasmtime/src/util.rs @@ -0,0 +1,113 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sc_executor_common::error::{Error, Result}; + +use cranelift_codegen::{ir, isa}; +use std::ops::Range; +use sp_wasm_interface::{Pointer, Signature, ValueType}; + +/// Read data from a slice of memory into a destination buffer. +/// +/// Returns an error if the read would go out of the memory bounds. +pub fn read_memory_into(memory: &[u8], address: Pointer, dest: &mut [u8]) -> Result<()> { + let range = checked_range(address.into(), dest.len(), memory.len()) + .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; + dest.copy_from_slice(&memory[range]); + Ok(()) +} + +/// Write data to a slice of memory. +/// +/// Returns an error if the write would go out of the memory bounds. +pub fn write_memory_from(memory: &mut [u8], address: Pointer, data: &[u8]) -> Result<()> { + let range = checked_range(address.into(), data.len(), memory.len()) + .ok_or_else(|| Error::Other("memory write is out of bounds".into()))?; + &mut memory[range].copy_from_slice(data); + Ok(()) +} + +/// Construct a range from an offset to a data length after the offset. +/// Returns None if the end of the range would exceed some maximum offset. +pub fn checked_range(offset: usize, len: usize, max: usize) -> Option> { + let end = offset.checked_add(len)?; + if end <= max { + Some(offset..end) + } else { + None + } +} + +/// Convert a wasm_interface Signature into a cranelift_codegen Signature. +pub fn cranelift_ir_signature(signature: Signature, call_conv: &isa::CallConv) -> ir::Signature { + ir::Signature { + params: signature.args.iter() + .map(cranelift_ir_type) + .map(ir::AbiParam::new) + .collect(), + returns: signature.return_value.iter() + .map(cranelift_ir_type) + .map(ir::AbiParam::new) + .collect(), + call_conv: call_conv.clone(), + } +} + +/// Convert a wasm_interface ValueType into a cranelift_codegen Type. +pub fn cranelift_ir_type(value_type: &ValueType) -> ir::types::Type { + match value_type { + ValueType::I32 => ir::types::I32, + ValueType::I64 => ir::types::I64, + ValueType::F32 => ir::types::F32, + ValueType::F64 => ir::types::F64, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use assert_matches::assert_matches; + + #[test] + fn test_read_memory_into() { + let mut memory = [0; 20]; + let mut dest = [0; 5]; + + &mut memory[15..20].copy_from_slice(b"hello"); + + read_memory_into(&memory[..], Pointer::new(15), &mut dest[..]).unwrap(); + + // Test that out of bounds read fails. + assert_matches!( + read_memory_into(&memory[..], Pointer::new(16), &mut dest[..]), + Err(Error::Other(_)) + ) + } + + #[test] + fn test_write_memory_from() { + let mut memory = [0; 20]; + let data = b"hello"; + + write_memory_from(&mut memory[..], Pointer::new(15), data).unwrap(); + + // Test that out of bounds write fails. + assert_matches!( + write_memory_from(&mut memory[..], Pointer::new(16), data), + Err(Error::Other(_)) + ) + } +} diff --git a/client/finality-grandpa/Cargo.toml b/client/finality-grandpa/Cargo.toml new file mode 100644 index 0000000000000..9d3ad74483208 --- /dev/null +++ b/client/finality-grandpa/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "sc-finality-grandpa" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +fork-tree = { version = "2.0.0", path = "../../utils/fork-tree" } +futures = "0.3.1" +futures01 = { package = "futures", version = "0.1.29" } +futures-timer = "2.0.2" +log = "0.4.8" +parking_lot = "0.9.0" +rand = "0.7.2" +parity-scale-codec = { version = "1.0.0", features = ["derive"] } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sc-telemetry = { version = "2.0.0", path = "../telemetry" } +sc-keystore = { version = "2.0.0", path = "../keystore" } +serde_json = "1.0.41" +sc-client-api = { version = "2.0.0", path = "../api" } +sc-client = { version = "2.0.0", path = "../" } +sp-inherents = { version = "2.0.0", path = "../../primitives/inherents" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +sc-network = { version = "0.8", path = "../network" } +sc-network-gossip = { version = "2.0.0", path = "../network-gossip" } +sp-finality-tracker = { version = "2.0.0", path = "../../primitives/finality-tracker" } +sp-finality-grandpa = { version = "2.0.0", path = "../../primitives/finality-grandpa" } +# See https://github.com/paritytech/finality-grandpa/pull/100 +finality-grandpa = { git = "https://github.com/expenses/finality-grandpa", branch = "future", features = ["derive-codec"] } + +[dev-dependencies] +finality-grandpa = { git = "https://github.com/expenses/finality-grandpa", branch = "future", features = ["derive-codec", "test-helpers"] } +sc-network = { version = "0.8", path = "../network" } +sc-network-test = { version = "2.0.0", path = "../network/test" } +sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } +sp-consensus-babe = { version = "0.8", path = "../../primitives/consensus/babe" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } +env_logger = "0.7.0" +tokio = "0.1.22" +tempfile = "3.1.0" +sp-api = { version = "2.0.0", path = "../../primitives/api" } diff --git a/core/finality-grandpa/src/authorities.rs b/client/finality-grandpa/src/authorities.rs similarity index 92% rename from core/finality-grandpa/src/authorities.rs rename to client/finality-grandpa/src/authorities.rs index 9b83c9feb6871..5e295d0baee7a 100644 --- a/core/finality-grandpa/src/authorities.rs +++ b/client/finality-grandpa/src/authorities.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,11 +18,11 @@ use fork_tree::ForkTree; use parking_lot::RwLock; -use grandpa::voter_set::VoterSet; -use codec::{Encode, Decode}; +use finality_grandpa::voter_set::VoterSet; +use parity_scale_codec::{Encode, Decode}; use log::{debug, info}; -use substrate_telemetry::{telemetry, CONSENSUS_INFO}; -use fg_primitives::AuthorityId; +use sc_telemetry::{telemetry, CONSENSUS_INFO}; +use sp_finality_grandpa::{AuthorityId, AuthorityList}; use std::cmp::Ord; use std::fmt::Debug; @@ -51,9 +51,10 @@ impl SharedAuthoritySet where N: Add + Ord + Clone + Debug, H: Clone + Debug { - /// Get the earliest limit-block number, if any. - pub(crate) fn current_limit(&self) -> Option { - self.inner.read().current_limit() + /// Get the earliest limit-block number that's higher or equal to the given + /// min number, if any. + pub(crate) fn current_limit(&self, min: N) -> Option { + self.inner.read().current_limit(min) } /// Get the current set ID. This is incremented every time the set changes. @@ -86,7 +87,7 @@ pub(crate) struct Status { /// A set of authorities. #[derive(Debug, Clone, Encode, Decode, PartialEq)] pub(crate) struct AuthoritySet { - pub(crate) current_authorities: Vec<(AuthorityId, u64)>, + pub(crate) current_authorities: AuthorityList, 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 @@ -103,7 +104,7 @@ where H: PartialEq, N: Ord, { /// Get a genesis set with given authorities. - pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self { + pub(crate) fn genesis(initial: AuthorityList) -> Self { AuthoritySet { current_authorities: initial, set_id: 0, @@ -224,10 +225,13 @@ where /// 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 + /// different branches) that is higher or equal to the given min number. + /// + /// 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 { + pub(crate) fn current_limit(&self, min: N) -> Option { self.pending_standard_changes.roots() + .filter(|&(_, _, c)| c.effective_number() >= min) .min_by_key(|&(_, _, c)| c.effective_number()) .map(|(_, _, c)| c.effective_number()) } @@ -258,7 +262,7 @@ where // check if the given best block is in the same branch as the block that signaled the change. if is_descendent_of(&change.canon_hash, &best_hash)? { // apply this change: make the set canonical - info!(target: "finality", "Applying authority set change forced at block #{:?}", + info!(target: "afg", "Applying authority set change forced at block #{:?}", change.canon_height); telemetry!(CONSENSUS_INFO; "afg.applying_forced_authority_set_change"; "block" => ?change.canon_height @@ -324,7 +328,7 @@ where self.pending_forced_changes.clear(); if let Some(change) = change { - info!(target: "finality", "Applying authority set change scheduled at block #{:?}", + info!(target: "afg", "Applying authority set change scheduled at block #{:?}", change.canon_height); telemetry!(CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change"; "block" => ?change.canon_height @@ -390,7 +394,7 @@ pub(crate) enum DelayKind { #[derive(Debug, Clone, Encode, PartialEq)] pub(crate) struct PendingChange { /// The new authorities and weights to apply. - pub(crate) next_authorities: Vec<(AuthorityId, u64)>, + pub(crate) next_authorities: AuthorityList, /// How deep in the chain the announcing block must be /// before the change is applied. pub(crate) delay: N, @@ -403,7 +407,7 @@ pub(crate) struct PendingChange { } impl Decode for PendingChange { - fn decode(value: &mut I) -> Result { + fn decode(value: &mut I) -> Result { let next_authorities = Decode::decode(value)?; let delay = Decode::decode(value)?; let canon_height = Decode::decode(value)?; @@ -431,7 +435,7 @@ impl + Clone> PendingChange { #[cfg(test)] mod tests { use super::*; - use primitives::crypto::Public; + use sp_core::crypto::Public; fn static_is_descendent_of(value: bool) -> impl Fn(&A, &A) -> Result @@ -445,6 +449,51 @@ mod tests { move |base, hash| Ok(f(base, hash)) } + #[test] + fn current_limit_filters_min() { + let mut authorities = AuthoritySet { + current_authorities: Vec::new(), + set_id: 0, + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + }; + + let change = |height| { + PendingChange { + next_authorities: Vec::new(), + delay: 0, + canon_height: height, + canon_hash: height.to_string(), + delay_kind: DelayKind::Finalized, + } + }; + + let is_descendent_of = static_is_descendent_of(false); + + authorities.add_pending_change(change(1), &is_descendent_of).unwrap(); + authorities.add_pending_change(change(2), &is_descendent_of).unwrap(); + + assert_eq!( + authorities.current_limit(0), + Some(1), + ); + + assert_eq!( + authorities.current_limit(1), + Some(1), + ); + + assert_eq!( + authorities.current_limit(2), + Some(2), + ); + + assert_eq!( + authorities.current_limit(3), + None, + ); + } + #[test] fn changes_iterated_in_pre_order() { let mut authorities = AuthoritySet { diff --git a/client/finality-grandpa/src/aux_schema.rs b/client/finality-grandpa/src/aux_schema.rs new file mode 100644 index 0000000000000..525a4a99bab58 --- /dev/null +++ b/client/finality-grandpa/src/aux_schema.rs @@ -0,0 +1,649 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Schema for stuff in the aux-db. + +use std::fmt::Debug; +use std::sync::Arc; +use parity_scale_codec::{Encode, Decode}; +use sc_client_api::backend::AuxStore; +use sp_blockchain::{Result as ClientResult, Error as ClientError}; +use fork_tree::ForkTree; +use finality_grandpa::round::State as RoundState; +use sp_runtime::traits::{Block as BlockT, NumberFor}; +use log::{info, warn}; +use sp_finality_grandpa::{AuthorityList, SetId, RoundNumber}; + +use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind}; +use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges}; +use crate::environment::{ + CompletedRound, CompletedRounds, CurrentRounds, HasVoted, SharedVoterSetState, VoterSetState, +}; +use crate::NewAuthoritySet; + +const VERSION_KEY: &[u8] = b"grandpa_schema_version"; +const SET_STATE_KEY: &[u8] = b"grandpa_completed_round"; +const CONCLUDED_ROUNDS: &[u8] = b"grandpa_concluded_rounds"; +const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; +const CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; + +const CURRENT_VERSION: u32 = 2; + +/// The voter set state. +#[derive(Debug, Clone, Encode, Decode)] +#[cfg_attr(test, derive(PartialEq))] +pub enum V1VoterSetState { + /// The voter set state, currently paused. + Paused(RoundNumber, RoundState), + /// The voter set state, currently live. + Live(RoundNumber, RoundState), +} + +type V0VoterSetState = (RoundNumber, RoundState); + +#[derive(Debug, Clone, Encode, Decode, PartialEq)] +struct V0PendingChange { + next_authorities: AuthorityList, + delay: N, + canon_height: N, + canon_hash: H, +} + +#[derive(Debug, Clone, Encode, Decode, PartialEq)] +struct V0AuthoritySet { + current_authorities: AuthorityList, + set_id: SetId, + 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 + } + } +} + +pub(crate) fn load_decode(backend: &B, key: &[u8]) -> ClientResult> { + match backend.get_aux(key)? { + None => Ok(None), + Some(t) => T::decode(&mut &t[..]) + .map_err( + |e| ClientError::Backend(format!("GRANDPA DB is corrupted: {}", e.what())), + ) + .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: SharedVoterSetState, +} + +fn migrate_from_version0( + backend: &B, + genesis_round: &G, +) -> ClientResult>, + VoterSetState, +)>> where B: AuxStore, + G: Fn() -> RoundState>, +{ + 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 (last_round_number, last_round_state) = match load_decode::<_, V0VoterSetState>>( + backend, + SET_STATE_KEY, + )? { + Some((number, state)) => (number, state), + None => (0, genesis_round()), + }; + + let set_id = new_set.current().0; + + let base = last_round_state.prevote_ghost + .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); + + let mut current_rounds = CurrentRounds::new(); + current_rounds.insert(last_round_number + 1, HasVoted::No); + + let set_state = VoterSetState::Live { + completed_rounds: CompletedRounds::new( + CompletedRound { + number: last_round_number, + state: last_round_state, + votes: Vec::new(), + base, + }, + set_id, + &new_set, + ), + current_rounds, + }; + + backend.insert_aux(&[(SET_STATE_KEY, set_state.encode().as_slice())], &[])?; + + return Ok(Some((new_set, set_state))); + } + + Ok(None) +} + +fn migrate_from_version1( + backend: &B, + genesis_round: &G, +) -> ClientResult>, + VoterSetState, +)>> where B: AuxStore, + G: Fn() -> RoundState>, +{ + CURRENT_VERSION.using_encoded(|s| + backend.insert_aux(&[(VERSION_KEY, s)], &[]) + )?; + + if let Some(set) = load_decode::<_, AuthoritySet>>( + backend, + AUTHORITY_SET_KEY, + )? { + let set_id = set.current().0; + + let completed_rounds = |number, state, base| CompletedRounds::new( + CompletedRound { + number, + state, + votes: Vec::new(), + base, + }, + set_id, + &set, + ); + + let set_state = match load_decode::<_, V1VoterSetState>>( + backend, + SET_STATE_KEY, + )? { + Some(V1VoterSetState::Paused(last_round_number, set_state)) => { + let base = set_state.prevote_ghost + .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); + + VoterSetState::Paused { + completed_rounds: completed_rounds(last_round_number, set_state, base), + } + }, + Some(V1VoterSetState::Live(last_round_number, set_state)) => { + let base = set_state.prevote_ghost + .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); + + let mut current_rounds = CurrentRounds::new(); + current_rounds.insert(last_round_number + 1, HasVoted::No); + + VoterSetState::Live { + completed_rounds: completed_rounds(last_round_number, set_state, base), + current_rounds, + } + }, + None => { + let set_state = genesis_round(); + let base = set_state.prevote_ghost + .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); + + VoterSetState::live( + set_id, + &set, + base, + ) + }, + }; + + backend.insert_aux(&[(SET_STATE_KEY, set_state.encode().as_slice())], &[])?; + + return Ok(Some((set, set_state))); + } + + Ok(None) +} + +/// Load or initialize persistent data from backend. +pub(crate) fn load_persistent( + backend: &B, + genesis_hash: Block::Hash, + genesis_number: NumberFor, + genesis_authorities: G, +) + -> ClientResult> + where + B: AuxStore, + 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 => { + if let Some((new_set, set_state)) = migrate_from_version0::(backend, &make_genesis_round)? { + return Ok(PersistentData { + authority_set: new_set.into(), + consensus_changes: Arc::new(consensus_changes.into()), + set_state: set_state.into(), + }); + } + }, + Some(1) => { + if let Some((new_set, set_state)) = migrate_from_version1::(backend, &make_genesis_round)? { + return Ok(PersistentData { + authority_set: new_set.into(), + consensus_changes: Arc::new(consensus_changes.into()), + set_state: set_state.into(), + }); + } + }, + Some(2) => { + 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 => { + let state = make_genesis_round(); + let base = state.prevote_ghost + .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); + + VoterSetState::live( + set.current().0, + &set, + base, + ) + } + }; + + return Ok(PersistentData { + authority_set: set.into(), + consensus_changes: Arc::new(consensus_changes.into()), + set_state: set_state.into(), + }); + } + } + Some(other) => return Err(ClientError::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_authorities = genesis_authorities()?; + let genesis_set = AuthoritySet::genesis(genesis_authorities.clone()); + let state = make_genesis_round(); + let base = state.prevote_ghost + .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); + + let genesis_state = VoterSetState::live( + 0, + &genesis_set, + base, + ); + + 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.into(), + consensus_changes: Arc::new(consensus_changes.into()), + }) +} + +/// Update the authority set on disk after a change. +/// +/// If there has just been a handoff, pass a `new_set` parameter that describes the +/// handoff. `set` in all cases should reflect the current authority set, with all +/// changes and handoffs applied. +pub(crate) fn update_authority_set( + set: &AuthoritySet>, + new_set: Option<&NewAuthoritySet>>, + write_aux: F +) -> R where + 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 set_state = VoterSetState::::live( + new_set.set_id, + &set, + (new_set.canon_hash, new_set.canon_number), + ); + 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<()> { + backend.insert_aux( + &[(SET_STATE_KEY, state.encode().as_slice())], + &[] + ) +} + +/// Write concluded round. +pub(crate) fn write_concluded_round( + backend: &B, + round_data: &CompletedRound, +) -> ClientResult<()> { + let mut key = CONCLUDED_ROUNDS.to_vec(); + let round_number = round_data.number; + round_number.using_encoded(|n| key.extend(n)); + + backend.insert_aux(&[(&key[..], round_data.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") +} + +#[cfg(test)] +mod test { + use sp_finality_grandpa::AuthorityId; + use sp_core::H256; + use substrate_test_runtime_client; + use super::*; + + #[test] + fn load_decode_from_v0_migrates_data_format() { + let client = substrate_test_runtime_client::new(); + + let authorities = vec![(AuthorityId::default(), 100)]; + let set_id = 3; + let round_number: RoundNumber = 42; + let round_state = RoundState:: { + prevote_ghost: Some((H256::random(), 32)), + finalized: None, + estimate: None, + completable: false, + }; + + { + let authority_set = V0AuthoritySet:: { + current_authorities: authorities.clone(), + pending_changes: Vec::new(), + set_id, + }; + + let voter_set_state = (round_number, round_state.clone()); + + client.insert_aux( + &[ + (AUTHORITY_SET_KEY, authority_set.encode().as_slice()), + (SET_STATE_KEY, voter_set_state.encode().as_slice()), + ], + &[], + ).unwrap(); + } + + assert_eq!( + load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), + None, + ); + + // should perform the migration + load_persistent::( + &client, + H256::random(), + 0, + || unreachable!(), + ).unwrap(); + + assert_eq!( + load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), + Some(2), + ); + + let PersistentData { authority_set, set_state, .. } = load_persistent::( + &client, + H256::random(), + 0, + || unreachable!(), + ).unwrap(); + + assert_eq!( + *authority_set.inner().read(), + AuthoritySet { + current_authorities: authorities.clone(), + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + set_id, + }, + ); + + let mut current_rounds = CurrentRounds::new(); + current_rounds.insert(round_number + 1, HasVoted::No); + + assert_eq!( + &*set_state.read(), + &VoterSetState::Live { + completed_rounds: CompletedRounds::new( + CompletedRound { + number: round_number, + state: round_state.clone(), + base: round_state.prevote_ghost.unwrap(), + votes: vec![], + }, + set_id, + &*authority_set.inner().read(), + ), + current_rounds, + }, + ); + } + + #[test] + fn load_decode_from_v1_migrates_data_format() { + let client = substrate_test_runtime_client::new(); + + let authorities = vec![(AuthorityId::default(), 100)]; + let set_id = 3; + let round_number: RoundNumber = 42; + let round_state = RoundState:: { + prevote_ghost: Some((H256::random(), 32)), + finalized: None, + estimate: None, + completable: false, + }; + + { + let authority_set = AuthoritySet:: { + current_authorities: authorities.clone(), + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + set_id, + }; + + let voter_set_state = V1VoterSetState::Live(round_number, round_state.clone()); + + client.insert_aux( + &[ + (AUTHORITY_SET_KEY, authority_set.encode().as_slice()), + (SET_STATE_KEY, voter_set_state.encode().as_slice()), + (VERSION_KEY, 1u32.encode().as_slice()), + ], + &[], + ).unwrap(); + } + + assert_eq!( + load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), + Some(1), + ); + + // should perform the migration + load_persistent::( + &client, + H256::random(), + 0, + || unreachable!(), + ).unwrap(); + + assert_eq!( + load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), + Some(2), + ); + + let PersistentData { authority_set, set_state, .. } = load_persistent::( + &client, + H256::random(), + 0, + || unreachable!(), + ).unwrap(); + + assert_eq!( + *authority_set.inner().read(), + AuthoritySet { + current_authorities: authorities.clone(), + pending_standard_changes: ForkTree::new(), + pending_forced_changes: Vec::new(), + set_id, + }, + ); + + let mut current_rounds = CurrentRounds::new(); + current_rounds.insert(round_number + 1, HasVoted::No); + + assert_eq!( + &*set_state.read(), + &VoterSetState::Live { + completed_rounds: CompletedRounds::new( + CompletedRound { + number: round_number, + state: round_state.clone(), + base: round_state.prevote_ghost.unwrap(), + votes: vec![], + }, + set_id, + &*authority_set.inner().read(), + ), + current_rounds, + }, + ); + } + + #[test] + fn write_read_concluded_rounds() { + let client = substrate_test_runtime_client::new(); + let hash = H256::random(); + let round_state = RoundState::genesis((hash, 0)); + + let completed_round = CompletedRound:: { + number: 42, + state: round_state.clone(), + base: round_state.prevote_ghost.unwrap(), + votes: vec![], + }; + + assert!(write_concluded_round(&client, &completed_round).is_ok()); + + let round_number = completed_round.number; + let mut key = CONCLUDED_ROUNDS.to_vec(); + round_number.using_encoded(|n| key.extend(n)); + + assert_eq!( + load_decode::<_, CompletedRound::>(&client, &key).unwrap(), + Some(completed_round), + ); + } +} diff --git a/client/finality-grandpa/src/communication/gossip.rs b/client/finality-grandpa/src/communication/gossip.rs new file mode 100644 index 0000000000000..b549c1f4ba946 --- /dev/null +++ b/client/finality-grandpa/src/communication/gossip.rs @@ -0,0 +1,2354 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Gossip and politeness for polite-grandpa. +//! +//! This module implements the following message types: +//! #### Neighbor Packet +//! +//! The neighbor packet is sent to only our neighbors. It contains this information +//! +//! - Current Round +//! - Current voter set ID +//! - Last finalized hash from commit messages. +//! +//! If a peer is at a given voter set, it is impolite to send messages from +//! an earlier voter set. It is extremely impolite to send messages +//! from a future voter set. "future-set" messages can be dropped and ignored. +//! +//! If a peer is at round r, is impolite to send messages about r-2 or earlier and extremely +//! impolite to send messages about r+1 or later. "future-round" messages can +//! be dropped and ignored. +//! +//! It is impolite to send a neighbor packet which moves backwards in protocol state. +//! +//! This is beneficial if it conveys some progress in the protocol state of the peer. +//! +//! #### Prevote / Precommit +//! +//! These are votes within a round. Noting that we receive these messages +//! from our peers who are not necessarily voters, we have to account the benefit +//! based on what they might have seen. +//! +//! #### Propose +//! +//! This is a broadcast by a known voter of the last-round estimate. +//! +//! #### Commit +//! +//! These are used to announce past agreement of finality. +//! +//! It is impolite to send commits which are earlier than the last commit +//! sent. It is especially impolite to send commits which are invalid, or from +//! a different Set ID than the receiving peer has indicated. +//! +//! Sending a commit is polite when it may finalize something that the receiving peer +//! was not aware of. +//! +//! #### Catch Up +//! +//! These allow a peer to request another peer, which they perceive to be in a +//! later round, to provide all the votes necessary to complete a given round +//! `R`. +//! +//! It is impolite to send a catch up request for a round `R` to a peer whose +//! announced view is behind `R`. It is also impolite to send a catch up request +//! to a peer in a new different Set ID. +//! +//! The logic for issuing and tracking pending catch up requests is implemented +//! in the `GossipValidator`. A catch up request is issued anytime we see a +//! neighbor packet from a peer at a round `CATCH_UP_THRESHOLD` higher than at +//! we are. +//! +//! ## Expiration +//! +//! We keep some amount of recent rounds' messages, but do not accept new ones from rounds +//! older than our current_round - 1. +//! +//! ## Message Validation +//! +//! We only send polite messages to peers, + +use sp_runtime::traits::{NumberFor, Block as BlockT, Zero}; +use sc_network_gossip::{GossipEngine, MessageIntent, ValidatorContext}; +use sc_network::{config::Roles, PeerId, ReputationChange}; +use parity_scale_codec::{Encode, Decode}; +use sp_finality_grandpa::AuthorityId; + +use sc_telemetry::{telemetry, CONSENSUS_DEBUG}; +use log::{trace, debug}; +use futures::prelude::*; +use futures::channel::mpsc; +use rand::seq::SliceRandom; + +use crate::{environment, CatchUp, CompactCommit, SignedMessage}; +use super::{cost, benefit, Round, SetId}; + +use std::collections::{HashMap, VecDeque, HashSet}; +use std::time::{Duration, Instant}; +use std::pin::Pin; +use std::task::{Poll, Context}; + +const REBROADCAST_AFTER: Duration = Duration::from_secs(60 * 5); +const CATCH_UP_REQUEST_TIMEOUT: Duration = Duration::from_secs(45); +const CATCH_UP_PROCESS_TIMEOUT: Duration = Duration::from_secs(30); +/// Maximum number of rounds we are behind a peer before issuing a +/// catch up request. +const CATCH_UP_THRESHOLD: u64 = 2; + +const PROPAGATION_ALL: u32 = 4; //in rounds; +const PROPAGATION_ALL_AUTHORITIES: u32 = 2; //in rounds; +const PROPAGATION_SOME_NON_AUTHORITIES: u32 = 3; //in rounds; +const ROUND_DURATION: u32 = 4; // measured in gossip durations + +const MIN_LUCKY: usize = 5; + +type Report = (PeerId, ReputationChange); + +/// An outcome of examining a message. +#[derive(Debug, PartialEq, Clone, Copy)] +enum Consider { + /// Accept the message. + Accept, + /// Message is too early. Reject. + RejectPast, + /// Message is from the future. Reject. + RejectFuture, + /// Message cannot be evaluated. Reject. + RejectOutOfScope, +} + +/// A view of protocol state. +#[derive(Debug)] +struct View { + round: Round, // the current round we are at. + set_id: SetId, // the current voter set id. + last_commit: Option, // commit-finalized block height, if any. +} + +impl Default for View { + fn default() -> Self { + View { + round: Round(1), + set_id: SetId(0), + last_commit: None, + } + } +} + +impl View { + /// Update the set ID. implies a reset to round 0. + fn update_set(&mut self, set_id: SetId) { + if set_id != self.set_id { + self.set_id = set_id; + self.round = Round(1); + } + } + + /// Consider a round and set ID combination under a current view. + fn consider_vote(&self, round: Round, set_id: SetId) -> Consider { + // only from current set + if set_id < self.set_id { return Consider::RejectPast } + if set_id > self.set_id { return Consider::RejectFuture } + + // only r-1 ... r+1 + if round.0 > self.round.0.saturating_add(1) { return Consider::RejectFuture } + if round.0 < self.round.0.saturating_sub(1) { return Consider::RejectPast } + + Consider::Accept + } + + /// Consider a set-id global message. Rounds are not taken into account, but are implicitly + /// because we gate on finalization of a further block than a previous commit. + fn consider_global(&self, set_id: SetId, number: N) -> Consider { + // only from current set + if set_id < self.set_id { return Consider::RejectPast } + if set_id > self.set_id { return Consider::RejectFuture } + + // only commits which claim to prove a higher block number than + // the one we're aware of. + match self.last_commit { + None => Consider::Accept, + Some(ref num) => if num < &number { + Consider::Accept + } else { + Consider::RejectPast + } + } + } +} + +const KEEP_RECENT_ROUNDS: usize = 3; + +/// Tracks gossip topics that we are keeping messages for. We keep topics of: +/// +/// - the last `KEEP_RECENT_ROUNDS` complete GRANDPA rounds, +/// +/// - the topic for the current and next round, +/// +/// - and a global topic for commit and catch-up messages. +struct KeepTopics { + current_set: SetId, + rounds: VecDeque<(Round, SetId)>, + reverse_map: HashMap, SetId)> +} + +impl KeepTopics { + fn new() -> Self { + KeepTopics { + current_set: SetId(0), + rounds: VecDeque::with_capacity(KEEP_RECENT_ROUNDS + 2), + reverse_map: HashMap::new(), + } + } + + fn push(&mut self, round: Round, set_id: SetId) { + self.current_set = std::cmp::max(self.current_set, set_id); + + // under normal operation the given round is already tracked (since we + // track one round ahead). if we skip rounds (with a catch up) the given + // round topic might not be tracked yet. + if !self.rounds.contains(&(round, set_id)) { + self.rounds.push_back((round, set_id)); + } + + // we also accept messages for the next round + self.rounds.push_back((Round(round.0.saturating_add(1)), set_id)); + + // the 2 is for the current and next round. + while self.rounds.len() > KEEP_RECENT_ROUNDS + 2 { + let _ = self.rounds.pop_front(); + } + + let mut map = HashMap::with_capacity(KEEP_RECENT_ROUNDS + 3); + map.insert(super::global_topic::(self.current_set.0), (None, self.current_set)); + + for &(round, set) in &self.rounds { + map.insert( + super::round_topic::(round.0, set.0), + (Some(round), set) + ); + } + + self.reverse_map = map; + } + + fn topic_info(&self, topic: &B::Hash) -> Option<(Option, SetId)> { + self.reverse_map.get(topic).cloned() + } +} + +// topics to send to a neighbor based on their view. +fn neighbor_topics(view: &View>) -> Vec { + let s = view.set_id; + let mut topics = vec![ + super::global_topic::(s.0), + super::round_topic::(view.round.0, s.0), + ]; + + if view.round.0 != 0 { + let r = Round(view.round.0 - 1); + topics.push(super::round_topic::(r.0, s.0)) + } + + topics +} + +/// Grandpa gossip message type. +/// This is the root type that gets encoded and sent on the network. +#[derive(Debug, Encode, Decode)] +pub(super) enum GossipMessage { + /// Grandpa message with round and set info. + Vote(VoteMessage), + /// Grandpa commit message with round and set info. + Commit(FullCommitMessage), + /// A neighbor packet. Not repropagated. + Neighbor(VersionedNeighborPacket>), + /// Grandpa catch up request message with round and set info. Not repropagated. + CatchUpRequest(CatchUpRequestMessage), + /// Grandpa catch up message with round and set info. Not repropagated. + CatchUp(FullCatchUpMessage), +} + +impl From>> for GossipMessage { + fn from(neighbor: NeighborPacket>) -> Self { + GossipMessage::Neighbor(VersionedNeighborPacket::V1(neighbor)) + } +} + +/// Network level vote message with topic information. +#[derive(Debug, Encode, Decode)] +pub(super) struct VoteMessage { + /// The round this message is from. + pub(super) round: Round, + /// The voter set ID this message is from. + pub(super) set_id: SetId, + /// The message itself. + pub(super) message: SignedMessage, +} + +/// Network level commit message with topic information. +#[derive(Debug, Encode, Decode)] +pub(super) struct FullCommitMessage { + /// The round this message is from. + pub(super) round: Round, + /// The voter set ID this message is from. + pub(super) set_id: SetId, + /// The compact commit message. + pub(super) message: CompactCommit, +} + +/// V1 neighbor packet. Neighbor packets are sent from nodes to their peers +/// and are not repropagated. These contain information about the node's state. +#[derive(Debug, Encode, Decode, Clone)] +pub(super) struct NeighborPacket { + /// The round the node is currently at. + pub(super) round: Round, + /// The set ID the node is currently at. + pub(super) set_id: SetId, + /// The highest finalizing commit observed. + pub(super) commit_finalized_height: N, +} + +/// A versioned neighbor packet. +#[derive(Debug, Encode, Decode)] +pub(super) enum VersionedNeighborPacket { + #[codec(index = "1")] + V1(NeighborPacket), +} + +impl VersionedNeighborPacket { + fn into_neighbor_packet(self) -> NeighborPacket { + match self { + VersionedNeighborPacket::V1(p) => p, + } + } +} + +/// A catch up request for a given round (or any further round) localized by set id. +#[derive(Clone, Debug, Encode, Decode)] +pub(super) struct CatchUpRequestMessage { + /// The round that we want to catch up to. + pub(super) round: Round, + /// The voter set ID this message is from. + pub(super) set_id: SetId, +} + +/// Network level catch up message with topic information. +#[derive(Debug, Encode, Decode)] +pub(super) struct FullCatchUpMessage { + /// The voter set ID this message is from. + pub(super) set_id: SetId, + /// The compact commit message. + pub(super) message: CatchUp, +} + +/// Misbehavior that peers can perform. +/// +/// `cost` gives a cost that can be used to perform cost/benefit analysis of a +/// peer. +#[derive(Clone, Copy, Debug, PartialEq)] +pub(super) enum Misbehavior { + // invalid neighbor message, considering the last one. + InvalidViewChange, + // could not decode neighbor message. bytes-length of the packet. + UndecodablePacket(i32), + // Bad catch up message (invalid signatures). + BadCatchUpMessage { + signatures_checked: i32, + }, + // Bad commit message + BadCommitMessage { + signatures_checked: i32, + blocks_loaded: i32, + equivocations_caught: i32, + }, + // A message received that's from the future relative to our view. + // always misbehavior. + FutureMessage, + // A message received that cannot be evaluated relative to our view. + // This happens before we have a view and have sent out neighbor packets. + // always misbehavior. + OutOfScopeMessage, +} + +impl Misbehavior { + pub(super) fn cost(&self) -> ReputationChange { + use Misbehavior::*; + + match *self { + InvalidViewChange => cost::INVALID_VIEW_CHANGE, + UndecodablePacket(bytes) => ReputationChange::new( + bytes.saturating_mul(cost::PER_UNDECODABLE_BYTE), + "Grandpa: Bad packet", + ), + BadCatchUpMessage { signatures_checked } => ReputationChange::new( + cost::PER_SIGNATURE_CHECKED.saturating_mul(signatures_checked), + "Grandpa: Bad cath-up message", + ), + BadCommitMessage { signatures_checked, blocks_loaded, equivocations_caught } => { + let cost = cost::PER_SIGNATURE_CHECKED + .saturating_mul(signatures_checked) + .saturating_add(cost::PER_BLOCK_LOADED.saturating_mul(blocks_loaded)); + + let benefit = equivocations_caught.saturating_mul(benefit::PER_EQUIVOCATION); + + ReputationChange::new((benefit as i32).saturating_add(cost as i32), "Grandpa: Bad commit") + }, + FutureMessage => cost::FUTURE_MESSAGE, + OutOfScopeMessage => cost::OUT_OF_SCOPE_MESSAGE, + } + } +} + +struct PeerInfo { + view: View, + roles: Roles, +} + +impl PeerInfo { + fn new(roles: Roles) -> Self { + PeerInfo { + view: View::default(), + roles, + } + } +} + +/// The peers we're connected do in gossip. +struct Peers { + inner: HashMap>, + lucky_peers: HashSet, + lucky_authorities: HashSet, +} + +impl Default for Peers { + fn default() -> Self { + Peers { + inner: HashMap::new(), + lucky_peers: HashSet::new(), + lucky_authorities: HashSet::new(), + } + } +} + +impl Peers { + fn new_peer(&mut self, who: PeerId, roles: Roles) { + if roles.is_authority() && self.lucky_authorities.len() < MIN_LUCKY { + self.lucky_authorities.insert(who.clone()); + } + if !roles.is_authority() && self.lucky_peers.len() < MIN_LUCKY { + self.lucky_peers.insert(who.clone()); + } + self.inner.insert(who, PeerInfo::new(roles)); + } + + fn peer_disconnected(&mut self, who: &PeerId) { + self.inner.remove(who); + // This does not happen often enough compared to round duration, + // so we don't reshuffle. + self.lucky_peers.remove(who); + self.lucky_authorities.remove(who); + } + + // returns a reference to the new view, if the peer is known. + fn update_peer_state(&mut self, who: &PeerId, update: NeighborPacket) + -> Result>, Misbehavior> + { + let peer = match self.inner.get_mut(who) { + None => return Ok(None), + Some(p) => p, + }; + + let invalid_change = peer.view.set_id > update.set_id + || peer.view.round > update.round && peer.view.set_id == update.set_id + || peer.view.last_commit.as_ref() > Some(&update.commit_finalized_height); + + if invalid_change { + return Err(Misbehavior::InvalidViewChange); + } + + peer.view = View { + round: update.round, + set_id: update.set_id, + last_commit: Some(update.commit_finalized_height), + }; + + trace!(target: "afg", "Peer {} updated view. Now at {:?}, {:?}", + who, peer.view.round, peer.view.set_id); + + Ok(Some(&peer.view)) + } + + fn update_commit_height(&mut self, who: &PeerId, new_height: N) -> Result<(), Misbehavior> { + let peer = match self.inner.get_mut(who) { + None => return Ok(()), + Some(p) => p, + }; + + // this doesn't allow a peer to send us unlimited commits with the + // same height, because there is still a misbehavior condition based on + // sending commits that are <= the best we are aware of. + if peer.view.last_commit.as_ref() > Some(&new_height) { + return Err(Misbehavior::InvalidViewChange); + } + + peer.view.last_commit = Some(new_height); + + Ok(()) + } + + fn peer<'a>(&'a self, who: &PeerId) -> Option<&'a PeerInfo> { + self.inner.get(who) + } + + fn authorities(&self) -> usize { + self.inner.iter().filter(|(_, info)| info.roles.is_authority()).count() + } + + fn non_authorities(&self) -> usize { + self.inner.iter().filter(|(_, info)| !info.roles.is_authority()).count() + } + + fn reshuffle(&mut self) { + let mut lucky_peers: Vec<_> = self.inner + .iter() + .filter_map(|(id, info)| if !info.roles.is_authority() { Some(id.clone()) } else { None }) + .collect(); + let mut lucky_authorities: Vec<_> = self.inner + .iter() + .filter_map(|(id, info)| if info.roles.is_authority() { Some(id.clone()) } else { None }) + .collect(); + + let num_non_authorities = ((lucky_peers.len() as f32).sqrt() as usize) + .max(MIN_LUCKY) + .min(lucky_peers.len()); + + let num_authorities = ((lucky_authorities.len() as f32).sqrt() as usize) + .max(MIN_LUCKY) + .min(lucky_authorities.len()); + + lucky_peers.partial_shuffle(&mut rand::thread_rng(), num_non_authorities); + lucky_peers.truncate(num_non_authorities); + + lucky_authorities.partial_shuffle(&mut rand::thread_rng(), num_authorities); + lucky_authorities.truncate(num_authorities); + + self.lucky_peers.clear(); + self.lucky_peers.extend(lucky_peers.into_iter()); + + self.lucky_authorities.clear(); + self.lucky_authorities.extend(lucky_authorities.into_iter()); + } +} + +#[derive(Debug, PartialEq)] +pub(super) enum Action { + // repropagate under given topic, to the given peers, applying cost/benefit to originator. + Keep(H, ReputationChange), + // discard and process. + ProcessAndDiscard(H, ReputationChange), + // discard, applying cost/benefit to originator. + Discard(ReputationChange), +} + +/// State of catch up request handling. +#[derive(Debug)] +enum PendingCatchUp { + /// No pending catch up requests. + None, + /// Pending catch up request which has not been answered yet. + Requesting { + who: PeerId, + request: CatchUpRequestMessage, + instant: Instant, + }, + /// Pending catch up request that was answered and is being processed. + Processing { + instant: Instant, + }, +} + +/// Configuration for the round catch-up mechanism. +enum CatchUpConfig { + /// Catch requests are enabled, our node will issue them whenever it sees a + /// neighbor packet for a round further than `CATCH_UP_THRESHOLD`. If + /// `only_from_authorities` is set, the node will only send catch-up + /// requests to other authorities it is connected to. This is useful if the + /// GRANDPA observer protocol is live on the network, in which case full + /// nodes (non-authorities) don't have the necessary round data to answer + /// catch-up requests. + Enabled { only_from_authorities: bool }, + /// Catch-up requests are disabled, our node will never issue them. This is + /// useful for the GRANDPA observer mode, where we are only interested in + /// commit messages and don't need to follow the full round protocol. + Disabled, +} + +impl CatchUpConfig { + fn enabled(only_from_authorities: bool) -> CatchUpConfig { + CatchUpConfig::Enabled { only_from_authorities } + } + + fn disabled() -> CatchUpConfig { + CatchUpConfig::Disabled + } + + fn request_allowed(&self, peer: &PeerInfo) -> bool { + match self { + CatchUpConfig::Disabled => false, + CatchUpConfig::Enabled { only_from_authorities, .. } => + !only_from_authorities || peer.roles.is_authority(), + } + } +} + +struct Inner { + local_view: Option>>, + peers: Peers>, + live_topics: KeepTopics, + round_start: Instant, + authorities: Vec, + config: crate::Config, + next_rebroadcast: Instant, + pending_catch_up: PendingCatchUp, + catch_up_config: CatchUpConfig, +} + +type MaybeMessage = Option<(Vec, NeighborPacket>)>; + +impl Inner { + fn new(config: crate::Config) -> Self { + let catch_up_config = if config.observer_enabled { + if config.is_authority { + // since the observer protocol is enabled, we will only issue + // catch-up requests if we are an authority (and only to other + // authorities). + CatchUpConfig::enabled(true) + } else { + // otherwise, we are running the observer protocol and don't + // care about catch-up requests. + CatchUpConfig::disabled() + } + } else { + // if the observer protocol isn't enabled, then any full node should + // be able to answer catch-up requests. + CatchUpConfig::enabled(false) + }; + + Inner { + local_view: None, + peers: Peers::default(), + live_topics: KeepTopics::new(), + round_start: Instant::now(), + next_rebroadcast: Instant::now() + REBROADCAST_AFTER, + authorities: Vec::new(), + pending_catch_up: PendingCatchUp::None, + catch_up_config, + config, + } + } + + /// Note a round in the current set has started. + fn note_round(&mut self, round: Round) -> MaybeMessage { + { + let local_view = match self.local_view { + None => return None, + Some(ref mut v) => if v.round == round { + return None + } else { + v + }, + }; + + let set_id = local_view.set_id; + + debug!(target: "afg", "Voter {} noting beginning of round {:?} to network.", + self.config.name(), (round, set_id)); + + local_view.round = round; + + self.live_topics.push(round, set_id); + self.round_start = Instant::now(); + self.peers.reshuffle(); + } + self.multicast_neighbor_packet() + } + + /// Note that a voter set with given ID has started. Does nothing if the last + /// call to the function was with the same `set_id`. + fn note_set(&mut self, set_id: SetId, authorities: Vec) -> MaybeMessage { + { + let local_view = match self.local_view { + ref mut x @ None => x.get_or_insert(View { + round: Round(1), + set_id, + last_commit: None, + }), + Some(ref mut v) => if v.set_id == set_id { + return None + } else { + v + }, + }; + + local_view.update_set(set_id); + self.live_topics.push(Round(1), set_id); + self.authorities = authorities; + } + self.multicast_neighbor_packet() + } + + /// Note that we've imported a commit finalizing a given block. + fn note_commit_finalized(&mut self, finalized: NumberFor) -> MaybeMessage { + { + match self.local_view { + None => return None, + Some(ref mut v) => if v.last_commit.as_ref() < Some(&finalized) { + v.last_commit = Some(finalized); + } else { + return None + }, + }; + } + + self.multicast_neighbor_packet() + } + + fn consider_vote(&self, round: Round, set_id: SetId) -> Consider { + self.local_view.as_ref().map(|v| v.consider_vote(round, set_id)) + .unwrap_or(Consider::RejectOutOfScope) + } + + fn consider_global(&self, set_id: SetId, number: NumberFor) -> Consider { + self.local_view.as_ref().map(|v| v.consider_global(set_id, number)) + .unwrap_or(Consider::RejectOutOfScope) + } + + fn cost_past_rejection(&self, _who: &PeerId, _round: Round, _set_id: SetId) -> ReputationChange { + // hardcoded for now. + cost::PAST_REJECTION + } + + fn validate_round_message(&self, who: &PeerId, full: &VoteMessage) + -> Action + { + match self.consider_vote(full.round, full.set_id) { + Consider::RejectFuture => return Action::Discard(Misbehavior::FutureMessage.cost()), + Consider::RejectOutOfScope => return Action::Discard(Misbehavior::OutOfScopeMessage.cost()), + Consider::RejectPast => + return Action::Discard(self.cost_past_rejection(who, full.round, full.set_id)), + Consider::Accept => {}, + } + + // ensure authority is part of the set. + if !self.authorities.contains(&full.message.id) { + telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); + return Action::Discard(cost::UNKNOWN_VOTER); + } + + if let Err(()) = super::check_message_sig::( + &full.message.message, + &full.message.id, + &full.message.signature, + full.round.0, + full.set_id.0, + ) { + debug!(target: "afg", "Bad message signature {}", full.message.id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); + return Action::Discard(cost::BAD_SIGNATURE); + } + + let topic = super::round_topic::(full.round.0, full.set_id.0); + Action::Keep(topic, benefit::ROUND_MESSAGE) + } + + fn validate_commit_message(&mut self, who: &PeerId, full: &FullCommitMessage) + -> Action + { + + if let Err(misbehavior) = self.peers.update_commit_height(who, full.message.target_number) { + return Action::Discard(misbehavior.cost()); + } + + match self.consider_global(full.set_id, full.message.target_number) { + Consider::RejectFuture => return Action::Discard(Misbehavior::FutureMessage.cost()), + Consider::RejectPast => + return Action::Discard(self.cost_past_rejection(who, full.round, full.set_id)), + Consider::RejectOutOfScope => return Action::Discard(Misbehavior::OutOfScopeMessage.cost()), + Consider::Accept => {}, + } + + 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 Action::Discard(cost::MALFORMED_COMMIT); + } + + // always discard commits initially and rebroadcast after doing full + // checking. + let topic = super::global_topic::(full.set_id.0); + Action::ProcessAndDiscard(topic, benefit::BASIC_VALIDATED_COMMIT) + } + + fn validate_catch_up_message(&mut self, who: &PeerId, full: &FullCatchUpMessage) + -> Action + { + match &self.pending_catch_up { + PendingCatchUp::Requesting { who: peer, request, instant } => { + if peer != who { + return Action::Discard(Misbehavior::OutOfScopeMessage.cost()); + } + + if request.set_id != full.set_id { + return Action::Discard(cost::MALFORMED_CATCH_UP); + } + + if request.round.0 > full.message.round_number { + return Action::Discard(cost::MALFORMED_CATCH_UP); + } + + if full.message.prevotes.is_empty() || full.message.precommits.is_empty() { + return Action::Discard(cost::MALFORMED_CATCH_UP); + } + + // move request to pending processing state, we won't push out + // any catch up requests until we import this one (either with a + // success or failure). + self.pending_catch_up = PendingCatchUp::Processing { + instant: instant.clone(), + }; + + // always discard catch up messages, they're point-to-point + let topic = super::global_topic::(full.set_id.0); + Action::ProcessAndDiscard(topic, benefit::BASIC_VALIDATED_CATCH_UP) + }, + _ => Action::Discard(Misbehavior::OutOfScopeMessage.cost()), + } + } + + fn note_catch_up_message_processed(&mut self) { + match &self.pending_catch_up { + PendingCatchUp::Processing { .. } => { + self.pending_catch_up = PendingCatchUp::None; + }, + state => trace!(target: "afg", + "Noted processed catch up message when state was: {:?}", + state, + ), + } + } + + fn handle_catch_up_request( + &mut self, + who: &PeerId, + request: CatchUpRequestMessage, + set_state: &environment::SharedVoterSetState, + ) -> (Option>, Action) { + let local_view = match self.local_view { + None => return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())), + Some(ref view) => view, + }; + + if request.set_id != local_view.set_id { + // NOTE: When we're close to a set change there is potentially a + // race where the peer sent us the request before it observed that + // we had transitioned to a new set. In this case we charge a lower + // cost. + if request.set_id.0.saturating_add(1) == local_view.set_id.0 && + local_view.round.0.saturating_sub(CATCH_UP_THRESHOLD) == 0 + { + return (None, Action::Discard(cost::HONEST_OUT_OF_SCOPE_CATCH_UP)); + } + + return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())); + } + + match self.peers.peer(who) { + None => + return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())), + Some(peer) if peer.view.round >= request.round => + return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())), + _ => {}, + } + + let last_completed_round = set_state.read().last_completed_round(); + if last_completed_round.number < request.round.0 { + return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())); + } + + trace!(target: "afg", "Replying to catch-up request for round {} from {} with round {}", + request.round.0, + who, + last_completed_round.number, + ); + + let mut prevotes = Vec::new(); + let mut precommits = Vec::new(); + + // NOTE: the set of votes stored in `LastCompletedRound` is a minimal + // set of votes, i.e. at most one equivocation is stored per voter. The + // code below assumes this invariant is maintained when creating the + // catch up reply since peers won't accept catch-up messages that have + // too many equivocations (we exceed the fault-tolerance bound). + for vote in last_completed_round.votes { + match vote.message { + finality_grandpa::Message::Prevote(prevote) => { + prevotes.push(finality_grandpa::SignedPrevote { + prevote, + signature: vote.signature, + id: vote.id, + }); + }, + finality_grandpa::Message::Precommit(precommit) => { + precommits.push(finality_grandpa::SignedPrecommit { + precommit, + signature: vote.signature, + id: vote.id, + }); + }, + _ => {}, + } + } + + let (base_hash, base_number) = last_completed_round.base; + + let catch_up = CatchUp:: { + round_number: last_completed_round.number, + prevotes, + precommits, + base_hash, + base_number, + }; + + let full_catch_up = GossipMessage::CatchUp::(FullCatchUpMessage { + set_id: request.set_id, + message: catch_up, + }); + + (Some(full_catch_up), Action::Discard(cost::CATCH_UP_REPLY)) + } + + fn try_catch_up(&mut self, who: &PeerId) -> (Option>, Option) { + let mut catch_up = None; + let mut report = None; + + // if the peer is on the same set and ahead of us by a margin bigger + // than `CATCH_UP_THRESHOLD` then we should ask it for a catch up + // message. we only send catch-up requests to authorities, observers + // won't be able to reply since they don't follow the full GRANDPA + // protocol and therefore might not have the vote data available. + if let (Some(peer), Some(local_view)) = (self.peers.peer(who), &self.local_view) { + if self.catch_up_config.request_allowed(&peer) && + peer.view.set_id == local_view.set_id && + peer.view.round.0.saturating_sub(CATCH_UP_THRESHOLD) > local_view.round.0 + { + // send catch up request if allowed + let round = peer.view.round.0 - 1; // peer.view.round is > 0 + let request = CatchUpRequestMessage { + set_id: peer.view.set_id, + round: Round(round), + }; + + let (catch_up_allowed, catch_up_report) = self.note_catch_up_request(who, &request); + + if catch_up_allowed { + trace!(target: "afg", "Sending catch-up request for round {} to {}", + round, + who, + ); + + catch_up = Some(GossipMessage::::CatchUpRequest(request)); + } + + report = catch_up_report; + } + } + + (catch_up, report) + } + + fn import_neighbor_message(&mut self, who: &PeerId, update: NeighborPacket>) + -> (Vec, Action, Option>, Option) + { + let update_res = self.peers.update_peer_state(who, update); + + let (cost_benefit, topics) = match update_res { + Ok(view) => + (benefit::NEIGHBOR_MESSAGE, view.map(|view| neighbor_topics::(view))), + Err(misbehavior) => + (misbehavior.cost(), None), + }; + + let (catch_up, report) = match update_res { + Ok(_) => self.try_catch_up(who), + _ => (None, None), + }; + + let neighbor_topics = topics.unwrap_or_default(); + + // always discard neighbor messages, it's only valid for one hop. + let action = Action::Discard(cost_benefit); + + (neighbor_topics, action, catch_up, report) + } + + fn multicast_neighbor_packet(&self) -> MaybeMessage { + self.local_view.as_ref().map(|local_view| { + let packet = NeighborPacket { + round: local_view.round, + set_id: local_view.set_id, + commit_finalized_height: local_view.last_commit.unwrap_or(Zero::zero()), + }; + + let peers = self.peers.inner.keys().cloned().collect(); + (peers, packet) + }) + } + + fn note_catch_up_request( + &mut self, + who: &PeerId, + catch_up_request: &CatchUpRequestMessage, + ) -> (bool, Option) { + let report = match &self.pending_catch_up { + PendingCatchUp::Requesting { who: peer, instant, .. } => + if instant.elapsed() <= CATCH_UP_REQUEST_TIMEOUT { + return (false, None); + } else { + // report peer for timeout + Some((peer.clone(), cost::CATCH_UP_REQUEST_TIMEOUT)) + }, + PendingCatchUp::Processing { instant, .. } => + if instant.elapsed() < CATCH_UP_PROCESS_TIMEOUT { + return (false, None); + } else { + None + }, + _ => None, + }; + + self.pending_catch_up = PendingCatchUp::Requesting { + who: who.clone(), + request: catch_up_request.clone(), + instant: Instant::now(), + }; + + (true, report) + } + + /// The initial logic for filtering round messages follows the given state + /// transitions: + /// + /// - State 0: not allowed to anyone (only if our local node is not an authority) + /// - State 1: allowed to random `sqrt(authorities)` + /// - State 2: allowed to all authorities + /// - State 3: allowed to random `sqrt(non-authorities)` + /// - State 4: allowed to all non-authorities + /// + /// Transitions will be triggered on repropagation attempts by the + /// underlying gossip layer, which should happen every 30 seconds. + fn round_message_allowed(&self, who: &PeerId, peer: &PeerInfo) -> bool { + let round_duration = self.config.gossip_duration * ROUND_DURATION; + let round_elapsed = self.round_start.elapsed(); + + + if !self.config.is_authority + && round_elapsed < round_duration * PROPAGATION_ALL + { + // non-authority nodes don't gossip any messages right away. we + // assume that authorities (and sentries) are strongly connected, so + // it should be unnecessary for non-authorities to gossip all + // messages right away. + return false; + } + + if peer.roles.is_authority() { + let authorities = self.peers.authorities(); + + // the target node is an authority, on the first round duration we start by + // sending the message to only `sqrt(authorities)` (if we're + // connected to at least `MIN_LUCKY`). + if round_elapsed < round_duration * PROPAGATION_ALL_AUTHORITIES + && authorities > MIN_LUCKY + { + self.peers.lucky_authorities.contains(who) + } else { + // otherwise we already went through the step above, so + // we won't filter the message and send it to all + // authorities for whom it is polite to do so + true + } + } else { + // the node is not an authority so we apply stricter filters + if round_elapsed >= round_duration * PROPAGATION_ALL { + // if we waited for 3 (or more) rounds + // then it is allowed to be sent to all peers. + true + } else if round_elapsed >= round_duration * PROPAGATION_SOME_NON_AUTHORITIES { + // otherwise we only send it to `sqrt(non-authorities)`. + self.peers.lucky_peers.contains(who) + } else { + false + } + } + } + + /// The initial logic for filtering global messages follows the given state + /// transitions: + /// + /// - State 0: send to `sqrt(authorities)` ++ `sqrt(non-authorities)`. + /// - State 1: send to all authorities + /// - State 2: send to all non-authorities + /// + /// We are more lenient with global messages since there should be a lot + /// less global messages than round messages (just commits), and we want + /// these to propagate to non-authorities fast enough so that they can + /// observe finality. + /// + /// Transitions will be triggered on repropagation attempts by the + /// underlying gossip layer, which should happen every 30 seconds. + fn global_message_allowed(&self, who: &PeerId, peer: &PeerInfo) -> bool { + let round_duration = self.config.gossip_duration * ROUND_DURATION; + let round_elapsed = self.round_start.elapsed(); + + if peer.roles.is_authority() { + let authorities = self.peers.authorities(); + + // the target node is an authority, on the first round duration we start by + // sending the message to only `sqrt(authorities)` (if we're + // connected to at least `MIN_LUCKY`). + if round_elapsed < round_duration * PROPAGATION_ALL_AUTHORITIES + && authorities > MIN_LUCKY + { + self.peers.lucky_authorities.contains(who) + } else { + // otherwise we already went through the step above, so + // we won't filter the message and send it to all + // authorities for whom it is polite to do so + true + } + } else { + let non_authorities = self.peers.non_authorities(); + + // the target node is not an authority, on the first and second + // round duration we start by sending the message to only + // `sqrt(non_authorities)` (if we're connected to at least + // `MIN_LUCKY`). + if round_elapsed < round_duration * PROPAGATION_SOME_NON_AUTHORITIES + && non_authorities > MIN_LUCKY + { + self.peers.lucky_peers.contains(who) + } else { + // otherwise we already went through the step above, so + // we won't filter the message and send it to all + // non-authorities for whom it is polite to do so + true + } + } + } +} + +/// A validator for GRANDPA gossip messages. +pub(super) struct GossipValidator { + inner: parking_lot::RwLock>, + set_state: environment::SharedVoterSetState, + report_sender: mpsc::UnboundedSender, +} + +impl GossipValidator { + /// Create a new gossip-validator. The current set is initialized to 0. If + /// `catch_up_enabled` is set to false then the validator will not issue any + /// catch up requests (useful e.g. when running just the GRANDPA observer). + pub(super) fn new( + config: crate::Config, + set_state: environment::SharedVoterSetState, + ) -> (GossipValidator, ReportStream) { + let (tx, rx) = mpsc::unbounded(); + let val = GossipValidator { + inner: parking_lot::RwLock::new(Inner::new(config)), + set_state, + report_sender: tx, + }; + + (val, ReportStream { reports: rx }) + } + + /// Note a round in the current set has started. + pub(super) fn note_round(&self, round: Round, send_neighbor: F) + where F: FnOnce(Vec, NeighborPacket>) + { + let maybe_msg = self.inner.write().note_round(round); + if let Some((to, msg)) = maybe_msg { + send_neighbor(to, msg); + } + } + + /// Note that a voter set with given ID has started. Updates the current set to given + /// value and initializes the round to 0. + pub(super) fn note_set(&self, set_id: SetId, authorities: Vec, send_neighbor: F) + where F: FnOnce(Vec, NeighborPacket>) + { + let maybe_msg = self.inner.write().note_set(set_id, authorities); + if let Some((to, msg)) = maybe_msg { + send_neighbor(to, msg); + } + } + + /// Note that we've imported a commit finalizing a given block. + pub(super) fn note_commit_finalized(&self, finalized: NumberFor, send_neighbor: F) + where F: FnOnce(Vec, NeighborPacket>) + { + let maybe_msg = self.inner.write().note_commit_finalized(finalized); + if let Some((to, msg)) = maybe_msg { + send_neighbor(to, msg); + } + } + + /// Note that we've processed a catch up message. + pub(super) fn note_catch_up_message_processed(&self) { + self.inner.write().note_catch_up_message_processed(); + } + + fn report(&self, who: PeerId, cost_benefit: ReputationChange) { + let _ = self.report_sender.unbounded_send(PeerReport { who, cost_benefit }); + } + + pub(super) fn do_validate(&self, who: &PeerId, mut data: &[u8]) + -> (Action, Vec, Option>) + { + let mut broadcast_topics = Vec::new(); + let mut peer_reply = None; + + let action = { + match GossipMessage::::decode(&mut data) { + Ok(GossipMessage::Vote(ref message)) + => self.inner.write().validate_round_message(who, message), + Ok(GossipMessage::Commit(ref message)) => self.inner.write().validate_commit_message(who, message), + Ok(GossipMessage::Neighbor(update)) => { + let (topics, action, catch_up, report) = self.inner.write().import_neighbor_message( + who, + update.into_neighbor_packet(), + ); + + if let Some((peer, cost_benefit)) = report { + self.report(peer, cost_benefit); + } + + broadcast_topics = topics; + peer_reply = catch_up; + action + } + Ok(GossipMessage::CatchUp(ref message)) + => self.inner.write().validate_catch_up_message(who, message), + Ok(GossipMessage::CatchUpRequest(request)) => { + let (reply, action) = self.inner.write().handle_catch_up_request( + who, + request, + &self.set_state, + ); + + peer_reply = reply; + action + } + Err(e) => { + debug!(target: "afg", "Error decoding message: {}", e.what()); + telemetry!(CONSENSUS_DEBUG; "afg.err_decoding_msg"; "" => ""); + + let len = std::cmp::min(i32::max_value() as usize, data.len()) as i32; + Action::Discard(Misbehavior::UndecodablePacket(len).cost()) + } + } + }; + + (action, broadcast_topics, peer_reply) + } +} + +impl sc_network_gossip::Validator for GossipValidator { + fn new_peer(&self, context: &mut dyn ValidatorContext, who: &PeerId, roles: Roles) { + let packet = { + let mut inner = self.inner.write(); + inner.peers.new_peer(who.clone(), roles); + + inner.local_view.as_ref().map(|v| { + NeighborPacket { + round: v.round, + set_id: v.set_id, + commit_finalized_height: v.last_commit.unwrap_or(Zero::zero()), + } + }) + }; + + if let Some(packet) = packet { + let packet_data = GossipMessage::::from(packet).encode(); + context.send_message(who, packet_data); + } + } + + fn peer_disconnected(&self, _context: &mut dyn ValidatorContext, who: &PeerId) { + self.inner.write().peers.peer_disconnected(who); + } + + fn validate(&self, context: &mut dyn ValidatorContext, who: &PeerId, data: &[u8]) + -> sc_network_gossip::ValidationResult + { + let (action, broadcast_topics, peer_reply) = self.do_validate(who, data); + + // not with lock held! + if let Some(msg) = peer_reply { + context.send_message(who, msg.encode()); + } + + for topic in broadcast_topics { + context.send_topic(who, topic, false); + } + + match action { + Action::Keep(topic, cb) => { + self.report(who.clone(), cb); + context.broadcast_message(topic, data.to_vec(), false); + sc_network_gossip::ValidationResult::ProcessAndKeep(topic) + } + Action::ProcessAndDiscard(topic, cb) => { + self.report(who.clone(), cb); + sc_network_gossip::ValidationResult::ProcessAndDiscard(topic) + } + Action::Discard(cb) => { + self.report(who.clone(), cb); + sc_network_gossip::ValidationResult::Discard + } + } + } + + fn message_allowed<'a>(&'a self) + -> Box bool + 'a> + { + let (inner, do_rebroadcast) = { + use parking_lot::RwLockWriteGuard; + + let mut inner = self.inner.write(); + let now = Instant::now(); + let do_rebroadcast = if now >= inner.next_rebroadcast { + inner.next_rebroadcast = now + REBROADCAST_AFTER; + true + } else { + false + }; + + // downgrade to read-lock. + (RwLockWriteGuard::downgrade(inner), do_rebroadcast) + }; + + Box::new(move |who, intent, topic, mut data| { + if let MessageIntent::PeriodicRebroadcast = intent { + return do_rebroadcast; + } + + let peer = match inner.peers.peer(who) { + None => return false, + Some(x) => x, + }; + + // if the topic is not something we're keeping at the moment, + // do not send. + let (maybe_round, set_id) = match inner.live_topics.topic_info(&topic) { + None => return false, + Some(x) => x, + }; + + if let MessageIntent::Broadcast = intent { + if maybe_round.is_some() { + if !inner.round_message_allowed(who, peer) { + // early return if the vote message isn't allowed at this stage. + return false; + } + } else { + if !inner.global_message_allowed(who, peer) { + // early return if the global message isn't allowed at this stage. + return false; + } + } + } + + // if the topic is not something the peer accepts, discard. + if let Some(round) = maybe_round { + return peer.view.consider_vote(round, set_id) == Consider::Accept + } + + // global message. + let local_view = match inner.local_view { + Some(ref v) => v, + None => return false, // cannot evaluate until we have a local view. + }; + + let our_best_commit = local_view.last_commit; + let peer_best_commit = peer.view.last_commit; + + match GossipMessage::::decode(&mut data) { + Err(_) => false, + Ok(GossipMessage::Commit(full)) => { + // we only broadcast our best commit and only if it's + // better than last received by peer. + Some(full.message.target_number) == our_best_commit && + Some(full.message.target_number) > peer_best_commit + } + Ok(GossipMessage::Neighbor(_)) => false, + Ok(GossipMessage::CatchUpRequest(_)) => false, + Ok(GossipMessage::CatchUp(_)) => false, + Ok(GossipMessage::Vote(_)) => false, // should not be the case. + } + }) + } + + fn message_expired<'a>(&'a self) -> Box bool + 'a> { + let inner = self.inner.read(); + Box::new(move |topic, mut data| { + // if the topic is not one of the ones that we are keeping at the moment, + // it is expired. + match inner.live_topics.topic_info(&topic) { + None => return true, + Some((Some(_), _)) => return false, // round messages don't require further checking. + Some((None, _)) => {}, + }; + + let local_view = match inner.local_view { + Some(ref v) => v, + None => return true, // no local view means we can't evaluate or hold any topic. + }; + + // global messages -- only keep the best commit. + let best_commit = local_view.last_commit; + + match GossipMessage::::decode(&mut data) { + Err(_) => true, + Ok(GossipMessage::Commit(full)) + => Some(full.message.target_number) != best_commit, + Ok(_) => true, + } + }) + } +} + +struct PeerReport { + who: PeerId, + cost_benefit: ReputationChange, +} + +// wrapper around a stream of reports. +#[must_use = "The report stream must be consumed"] +pub(super) struct ReportStream { + reports: mpsc::UnboundedReceiver, +} + +impl ReportStream { + /// Consume the report stream, converting it into a future that + /// handles all reports. + pub(super) fn consume(self, net: GossipEngine) + -> impl Future + Send + 'static + Unpin + where + B: BlockT, + { + ReportingTask { + reports: self.reports, + net, + } + } +} + +/// A future for reporting peers. +#[must_use = "Futures do nothing unless polled"] +struct ReportingTask { + reports: mpsc::UnboundedReceiver, + net: GossipEngine, +} + +impl Future for ReportingTask { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> { + loop { + match Stream::poll_next(Pin::new(&mut self.reports), cx) { + Poll::Ready(None) => return Poll::Ready(()), + Poll::Ready(Some(PeerReport { who, cost_benefit })) => + self.net.report(who, cost_benefit), + Poll::Pending => return Poll::Pending, + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use super::environment::SharedVoterSetState; + use sc_network_gossip::Validator as GossipValidatorT; + use sc_network_test::Block; + use sp_core::{crypto::Public, H256}; + + // some random config (not really needed) + fn config() -> crate::Config { + crate::Config { + gossip_duration: Duration::from_millis(10), + justification_period: 256, + keystore: None, + name: None, + is_authority: true, + observer_enabled: true, + } + } + + // dummy voter set state + fn voter_set_state() -> SharedVoterSetState { + use crate::authorities::AuthoritySet; + use crate::environment::VoterSetState; + + let base = (H256::zero(), 0); + let voters = AuthoritySet::genesis(Vec::new()); + let set_state = VoterSetState::live( + 0, + &voters, + base, + ); + + set_state.into() + } + + #[test] + fn view_vote_rules() { + let view = View { round: Round(100), set_id: SetId(1), last_commit: Some(1000u64) }; + + assert_eq!(view.consider_vote(Round(98), SetId(1)), Consider::RejectPast); + assert_eq!(view.consider_vote(Round(1), SetId(0)), Consider::RejectPast); + assert_eq!(view.consider_vote(Round(1000), SetId(0)), Consider::RejectPast); + + assert_eq!(view.consider_vote(Round(99), SetId(1)), Consider::Accept); + assert_eq!(view.consider_vote(Round(100), SetId(1)), Consider::Accept); + assert_eq!(view.consider_vote(Round(101), SetId(1)), Consider::Accept); + + assert_eq!(view.consider_vote(Round(102), SetId(1)), Consider::RejectFuture); + assert_eq!(view.consider_vote(Round(1), SetId(2)), Consider::RejectFuture); + assert_eq!(view.consider_vote(Round(1000), SetId(2)), Consider::RejectFuture); + } + + #[test] + fn view_global_message_rules() { + let view = View { round: Round(100), set_id: SetId(2), last_commit: Some(1000u64) }; + + assert_eq!(view.consider_global(SetId(3), 1), Consider::RejectFuture); + assert_eq!(view.consider_global(SetId(3), 1000), Consider::RejectFuture); + assert_eq!(view.consider_global(SetId(3), 10000), Consider::RejectFuture); + + assert_eq!(view.consider_global(SetId(1), 1), Consider::RejectPast); + assert_eq!(view.consider_global(SetId(1), 1000), Consider::RejectPast); + assert_eq!(view.consider_global(SetId(1), 10000), Consider::RejectPast); + + assert_eq!(view.consider_global(SetId(2), 1), Consider::RejectPast); + assert_eq!(view.consider_global(SetId(2), 1000), Consider::RejectPast); + assert_eq!(view.consider_global(SetId(2), 1001), Consider::Accept); + assert_eq!(view.consider_global(SetId(2), 10000), Consider::Accept); + } + + #[test] + fn unknown_peer_cannot_be_updated() { + let mut peers = Peers::default(); + let id = PeerId::random(); + + let update = NeighborPacket { + round: Round(5), + set_id: SetId(10), + commit_finalized_height: 50, + }; + + let res = peers.update_peer_state(&id, update.clone()); + assert!(res.unwrap().is_none()); + + // connect & disconnect. + peers.new_peer(id.clone(), Roles::AUTHORITY); + peers.peer_disconnected(&id); + + let res = peers.update_peer_state(&id, update.clone()); + assert!(res.unwrap().is_none()); + } + + #[test] + fn update_peer_state() { + let update1 = NeighborPacket { + round: Round(5), + set_id: SetId(10), + commit_finalized_height: 50u32, + }; + + let update2 = NeighborPacket { + round: Round(6), + set_id: SetId(10), + commit_finalized_height: 60, + }; + + let update3 = NeighborPacket { + round: Round(2), + set_id: SetId(11), + commit_finalized_height: 61, + }; + + let update4 = NeighborPacket { + round: Round(3), + set_id: SetId(11), + commit_finalized_height: 80, + }; + + let mut peers = Peers::default(); + let id = PeerId::random(); + + peers.new_peer(id.clone(), Roles::AUTHORITY); + + let mut check_update = move |update: NeighborPacket<_>| { + let view = peers.update_peer_state(&id, update.clone()).unwrap().unwrap(); + assert_eq!(view.round, update.round); + assert_eq!(view.set_id, update.set_id); + assert_eq!(view.last_commit, Some(update.commit_finalized_height)); + }; + + check_update(update1); + check_update(update2); + check_update(update3); + check_update(update4); + } + + #[test] + fn invalid_view_change() { + let mut peers = Peers::default(); + + let id = PeerId::random(); + peers.new_peer(id.clone(), Roles::AUTHORITY); + + peers.update_peer_state(&id, NeighborPacket { + round: Round(10), + set_id: SetId(10), + commit_finalized_height: 10, + }).unwrap().unwrap(); + + let mut check_update = move |update: NeighborPacket<_>| { + let err = peers.update_peer_state(&id, update.clone()).unwrap_err(); + assert_eq!(err, Misbehavior::InvalidViewChange); + }; + + // round moves backwards. + check_update(NeighborPacket { + round: Round(9), + set_id: SetId(10), + commit_finalized_height: 10, + }); + // commit finalized height moves backwards. + check_update(NeighborPacket { + round: Round(10), + set_id: SetId(10), + commit_finalized_height: 9, + }); + // set ID moves backwards. + check_update(NeighborPacket { + round: Round(10), + set_id: SetId(9), + commit_finalized_height: 10, + }); + } + + #[test] + fn messages_not_expired_immediately() { + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + let set_id = 1; + + val.note_set(SetId(set_id), Vec::new(), |_, _| {}); + + for round_num in 1u64..10 { + val.note_round(Round(round_num), |_, _| {}); + } + + { + let mut is_expired = val.message_expired(); + let last_kept_round = 10u64 - KEEP_RECENT_ROUNDS as u64 - 1; + + // messages from old rounds are expired. + for round_num in 1u64..last_kept_round { + let topic = crate::communication::round_topic::(round_num, 1); + assert!(is_expired(topic, &[1, 2, 3])); + } + + // messages from not-too-old rounds are not expired. + for round_num in last_kept_round..10 { + let topic = crate::communication::round_topic::(round_num, 1); + assert!(!is_expired(topic, &[1, 2, 3])); + } + } + } + + #[test] + fn message_from_unknown_authority_discarded() { + assert!(cost::UNKNOWN_VOTER != cost::BAD_SIGNATURE); + + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + let set_id = 1; + let auth = AuthorityId::from_slice(&[1u8; 32]); + let peer = PeerId::random(); + + val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); + val.note_round(Round(1), |_, _| {}); + + let inner = val.inner.read(); + let unknown_voter = inner.validate_round_message(&peer, &VoteMessage { + round: Round(1), + set_id: SetId(set_id), + message: SignedMessage:: { + message: finality_grandpa::Message::Prevote(finality_grandpa::Prevote { + target_hash: Default::default(), + target_number: 10, + }), + signature: Default::default(), + id: AuthorityId::from_slice(&[2u8; 32]), + } + }); + + let bad_sig = inner.validate_round_message(&peer, &VoteMessage { + round: Round(1), + set_id: SetId(set_id), + message: SignedMessage:: { + message: finality_grandpa::Message::Prevote(finality_grandpa::Prevote { + target_hash: Default::default(), + target_number: 10, + }), + signature: Default::default(), + id: auth.clone(), + } + }); + + assert_eq!(unknown_voter, Action::Discard(cost::UNKNOWN_VOTER)); + assert_eq!(bad_sig, Action::Discard(cost::BAD_SIGNATURE)); + } + + #[test] + fn unsolicited_catch_up_messages_discarded() { + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + let set_id = 1; + let auth = AuthorityId::from_slice(&[1u8; 32]); + let peer = PeerId::random(); + + val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); + val.note_round(Round(1), |_, _| {}); + + let validate_catch_up = || { + let mut inner = val.inner.write(); + inner.validate_catch_up_message(&peer, &FullCatchUpMessage { + set_id: SetId(set_id), + message: finality_grandpa::CatchUp { + round_number: 10, + prevotes: Default::default(), + precommits: Default::default(), + base_hash: Default::default(), + base_number: Default::default(), + } + }) + }; + + // the catch up is discarded because we have no pending request + assert_eq!(validate_catch_up(), Action::Discard(cost::OUT_OF_SCOPE_MESSAGE)); + + let noted = val.inner.write().note_catch_up_request( + &peer, + &CatchUpRequestMessage { + set_id: SetId(set_id), + round: Round(10), + } + ); + + assert!(noted.0); + + // catch up is allowed because we have requested it, but it's rejected + // because it's malformed (empty prevotes and precommits) + assert_eq!(validate_catch_up(), Action::Discard(cost::MALFORMED_CATCH_UP)); + } + + #[test] + fn unanswerable_catch_up_requests_discarded() { + // create voter set state with round 2 completed + let set_state: SharedVoterSetState = { + let mut completed_rounds = voter_set_state().read().completed_rounds(); + + completed_rounds.push(environment::CompletedRound { + number: 2, + state: finality_grandpa::round::State::genesis(Default::default()), + base: Default::default(), + votes: Default::default(), + }); + + let mut current_rounds = environment::CurrentRounds::new(); + current_rounds.insert(3, environment::HasVoted::No); + + let set_state = environment::VoterSetState::::Live { + completed_rounds, + current_rounds, + }; + + set_state.into() + }; + + let (val, _) = GossipValidator::::new( + config(), + set_state.clone(), + ); + + let set_id = 1; + let auth = AuthorityId::from_slice(&[1u8; 32]); + let peer = PeerId::random(); + + val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); + val.note_round(Round(3), |_, _| {}); + + // add the peer making the request to the validator, + // otherwise it is discarded + let mut inner = val.inner.write(); + inner.peers.new_peer(peer.clone(), Roles::AUTHORITY); + + let res = inner.handle_catch_up_request( + &peer, + CatchUpRequestMessage { + set_id: SetId(set_id), + round: Round(10), + }, + &set_state, + ); + + // we're at round 3, a catch up request for round 10 is out of scope + assert!(res.0.is_none()); + assert_eq!(res.1, Action::Discard(cost::OUT_OF_SCOPE_MESSAGE)); + + let res = inner.handle_catch_up_request( + &peer, + CatchUpRequestMessage { + set_id: SetId(set_id), + round: Round(2), + }, + &set_state, + ); + + // a catch up request for round 2 should be answered successfully + match res.0.unwrap() { + GossipMessage::CatchUp(catch_up) => { + assert_eq!(catch_up.set_id, SetId(set_id)); + assert_eq!(catch_up.message.round_number, 2); + + assert_eq!(res.1, Action::Discard(cost::CATCH_UP_REPLY)); + }, + _ => panic!("expected catch up message"), + }; + } + + #[test] + fn detects_honest_out_of_scope_catch_requests() { + let set_state = voter_set_state(); + let (val, _) = GossipValidator::::new( + config(), + set_state.clone(), + ); + + // the validator starts at set id 2 + val.note_set(SetId(2), Vec::new(), |_, _| {}); + + // add the peer making the request to the validator, + // otherwise it is discarded + let peer = PeerId::random(); + val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); + + let send_request = |set_id, round| { + let mut inner = val.inner.write(); + inner.handle_catch_up_request( + &peer, + CatchUpRequestMessage { + set_id: SetId(set_id), + round: Round(round), + }, + &set_state, + ) + }; + + let assert_res = |res: (Option<_>, Action<_>), honest| { + assert!(res.0.is_none()); + assert_eq!( + res.1, + if honest { + Action::Discard(cost::HONEST_OUT_OF_SCOPE_CATCH_UP) + } else { + Action::Discard(Misbehavior::OutOfScopeMessage.cost()) + }, + ); + }; + + // the validator is at set id 2 and round 0. requests for set id 1 + // should not be answered but they should be considered an honest + // mistake + assert_res( + send_request(1, 1), + true, + ); + + assert_res( + send_request(1, 10), + true, + ); + + // requests for set id 0 should be considered out of scope + assert_res( + send_request(0, 1), + false, + ); + + assert_res( + send_request(0, 10), + false, + ); + + // after the validator progresses further than CATCH_UP_THRESHOLD in set + // id 2, any request for set id 1 should no longer be considered an + // honest mistake. + val.note_round(Round(3), |_, _| {}); + + assert_res( + send_request(1, 1), + false, + ); + + assert_res( + send_request(1, 2), + false, + ); + } + + #[test] + fn issues_catch_up_request_on_neighbor_packet_import() { + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // add the peer making the request to the validator, + // otherwise it is discarded. + let peer = PeerId::random(); + val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); + + let import_neighbor_message = |set_id, round| { + let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( + &peer, + NeighborPacket { + round: Round(round), + set_id: SetId(set_id), + commit_finalized_height: 42, + }, + ); + + catch_up_request + }; + + // importing a neighbor message from a peer in the same set in a later + // round should lead to a catch up request for the previous round. + match import_neighbor_message(1, 42) { + Some(GossipMessage::CatchUpRequest(request)) => { + assert_eq!(request.set_id, SetId(1)); + assert_eq!(request.round, Round(41)); + }, + _ => panic!("expected catch up message"), + } + + // we note that we're at round 41. + val.note_round(Round(41), |_, _| {}); + + // if we import a neighbor message within CATCH_UP_THRESHOLD then we + // won't request a catch up. + match import_neighbor_message(1, 42) { + None => {}, + _ => panic!("expected no catch up message"), + } + + // or if the peer is on a lower round. + match import_neighbor_message(1, 40) { + None => {}, + _ => panic!("expected no catch up message"), + } + + // we also don't request a catch up if the peer is in a different set. + match import_neighbor_message(2, 42) { + None => {}, + _ => panic!("expected no catch up message"), + } + } + + #[test] + fn doesnt_send_catch_up_requests_when_disabled() { + // we create a gossip validator with catch up requests disabled. + let config = { + let mut c = config(); + + // if the observer protocol is enabled and we are not an authority, + // then we don't issue any catch-up requests. + c.is_authority = false; + c.observer_enabled = true; + + c + }; + + let (val, _) = GossipValidator::::new( + config, + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // add the peer making the request to the validator, + // otherwise it is discarded. + let peer = PeerId::random(); + val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); + + // importing a neighbor message from a peer in the same set in a later + // round should lead to a catch up request but since they're disabled + // we should get `None`. + let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( + &peer, + NeighborPacket { + round: Round(42), + set_id: SetId(1), + commit_finalized_height: 50, + }, + ); + + match catch_up_request { + None => {}, + _ => panic!("expected no catch up message"), + } + } + + #[test] + fn doesnt_send_catch_up_requests_to_non_authorities_when_observer_enabled() { + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // add the peers making the requests to the validator, + // otherwise it is discarded. + let peer_authority = PeerId::random(); + let peer_full = PeerId::random(); + + val.inner.write().peers.new_peer(peer_authority.clone(), Roles::AUTHORITY); + val.inner.write().peers.new_peer(peer_full.clone(), Roles::FULL); + + let import_neighbor_message = |peer| { + let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( + &peer, + NeighborPacket { + round: Round(42), + set_id: SetId(1), + commit_finalized_height: 50, + }, + ); + + catch_up_request + }; + + // importing a neighbor message from a peer in the same set in a later + // round should lead to a catch up request but since the node is not an + // authority we should get `None`. + if import_neighbor_message(peer_full).is_some() { + panic!("expected no catch up message"); + } + + // importing the same neighbor message from a peer who is an authority + // should lead to a catch up request. + match import_neighbor_message(peer_authority) { + Some(GossipMessage::CatchUpRequest(request)) => { + assert_eq!(request.set_id, SetId(1)); + assert_eq!(request.round, Round(41)); + }, + _ => panic!("expected catch up message"), + } + } + + #[test] + fn sends_catch_up_requests_to_non_authorities_when_observer_disabled() { + let config = { + let mut c = config(); + + // if the observer protocol is disable any full-node should be able + // to answer catch-up requests. + c.observer_enabled = false; + + c + }; + + let (val, _) = GossipValidator::::new( + config, + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // add the peer making the requests to the validator, otherwise it is + // discarded. + let peer_full = PeerId::random(); + val.inner.write().peers.new_peer(peer_full.clone(), Roles::FULL); + + let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( + &peer_full, + NeighborPacket { + round: Round(42), + set_id: SetId(1), + commit_finalized_height: 50, + }, + ); + + // importing a neighbor message from a peer in the same set in a later + // round should lead to a catch up request, the node is not an + // authority, but since the observer protocol is disabled we should + // issue a catch-up request to it anyway. + match catch_up_request { + Some(GossipMessage::CatchUpRequest(request)) => { + assert_eq!(request.set_id, SetId(1)); + assert_eq!(request.round, Round(41)); + }, + _ => panic!("expected catch up message"), + } + } + + #[test] + fn doesnt_expire_next_round_messages() { + // NOTE: this is a regression test + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // we are at round 10 + val.note_round(Round(9), |_, _| {}); + val.note_round(Round(10), |_, _| {}); + + let mut is_expired = val.message_expired(); + + // we accept messages from rounds 9, 10 and 11 + // therefore neither of those should be considered expired + for round in &[9, 10, 11] { + assert!( + !is_expired( + crate::communication::round_topic::(*round, 1), + &[], + ) + ) + } + } + + #[test] + fn progressively_gossips_to_more_peers() { + let mut config = config(); + config.gossip_duration = Duration::from_secs(300); // Set to high value to prevent test race + let round_duration = config.gossip_duration * ROUND_DURATION; + + let (val, _) = GossipValidator::::new( + config, + voter_set_state(), + ); + + // the validator start at set id 0 + val.note_set(SetId(0), Vec::new(), |_, _| {}); + + // add 60 peers, 30 authorities and 30 full nodes + let mut authorities = Vec::new(); + authorities.resize_with(30, || PeerId::random()); + + let mut full_nodes = Vec::new(); + full_nodes.resize_with(30, || PeerId::random()); + + for i in 0..30 { + val.inner.write().peers.new_peer(authorities[i].clone(), Roles::AUTHORITY); + val.inner.write().peers.new_peer(full_nodes[i].clone(), Roles::FULL); + } + + let test = |num_round, peers| { + // rewind n round durations + val.inner.write().round_start = Instant::now() - round_duration * num_round; + let mut message_allowed = val.message_allowed(); + + move || { + let mut allowed = 0; + for peer in peers { + if message_allowed( + peer, + MessageIntent::Broadcast, + &crate::communication::round_topic::(1, 0), + &[], + ) { + allowed += 1; + } + } + allowed + } + }; + + fn trial usize>(mut test: F) -> usize { + let mut results = Vec::new(); + let n = 1000; + + for _ in 0..n { + results.push(test()); + } + + let n = results.len(); + let sum: usize = results.iter().sum(); + + sum / n + } + + // on the first attempt we will only gossip to `sqrt(authorities)`, + // which should average out to 5 peers after a couple of trials + assert_eq!(trial(test(1, &authorities)), 5); + + // on the second (and subsequent attempts) we should gossip to all + // authorities we're connected to. + assert_eq!(trial(test(2, &authorities)), 30); + assert_eq!(trial(test(3, &authorities)), 30); + + // we should only gossip to non-authorities after the third attempt + assert_eq!(trial(test(1, &full_nodes)), 0); + assert_eq!(trial(test(2, &full_nodes)), 0); + + // and only to `sqrt(non-authorities)` + assert_eq!(trial(test(3, &full_nodes)), 5); + + // only on the fourth attempt should we gossip to all non-authorities + assert_eq!(trial(test(4, &full_nodes)), 30); + } + + #[test] + fn only_restricts_gossip_to_authorities_after_a_minimum_threshold() { + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + // the validator start at set id 0 + val.note_set(SetId(0), Vec::new(), |_, _| {}); + + let mut authorities = Vec::new(); + for _ in 0..5 { + let peer_id = PeerId::random(); + val.inner.write().peers.new_peer(peer_id.clone(), Roles::AUTHORITY); + authorities.push(peer_id); + } + + let mut message_allowed = val.message_allowed(); + + // since we're only connected to 5 authorities, we should never restrict + // sending of gossip messages, and instead just allow them to all + // non-authorities on the first attempt. + for authority in &authorities { + assert!( + message_allowed( + authority, + MessageIntent::Broadcast, + &crate::communication::round_topic::(1, 0), + &[], + ) + ); + } + } + + #[test] + fn non_authorities_never_gossip_messages_on_first_round_duration() { + let mut config = config(); + config.gossip_duration = Duration::from_secs(300); // Set to high value to prevent test race + config.is_authority = false; + let round_duration = config.gossip_duration * ROUND_DURATION; + + let (val, _) = GossipValidator::::new( + config, + voter_set_state(), + ); + + // the validator start at set id 0 + val.note_set(SetId(0), Vec::new(), |_, _| {}); + + let mut authorities = Vec::new(); + for _ in 0..100 { + let peer_id = PeerId::random(); + val.inner.write().peers.new_peer(peer_id.clone(), Roles::AUTHORITY); + authorities.push(peer_id); + } + + { + let mut message_allowed = val.message_allowed(); + // since our node is not an authority we should **never** gossip any + // messages on the first attempt. + for authority in &authorities { + assert!( + !message_allowed( + authority, + MessageIntent::Broadcast, + &crate::communication::round_topic::(1, 0), + &[], + ) + ); + } + } + + { + val.inner.write().round_start = Instant::now() - round_duration * 4; + let mut message_allowed = val.message_allowed(); + // on the fourth round duration we should allow messages to authorities + // (on the second we would do `sqrt(authorities)`) + for authority in &authorities { + assert!( + message_allowed( + authority, + MessageIntent::Broadcast, + &crate::communication::round_topic::(1, 0), + &[], + ) + ); + } + } + } +} diff --git a/client/finality-grandpa/src/communication/mod.rs b/client/finality-grandpa/src/communication/mod.rs new file mode 100644 index 0000000000000..4f98e8c8d6a0a --- /dev/null +++ b/client/finality-grandpa/src/communication/mod.rs @@ -0,0 +1,919 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Communication streams for the polite-grandpa networking protocol. +//! +//! GRANDPA nodes communicate over a gossip network, where messages are not sent to +//! peers until they have reached a given round. +//! +//! Rather than expressing protocol rules, +//! polite-grandpa just carries a notion of impoliteness. Nodes which pass some arbitrary +//! threshold of impoliteness are removed. Messages are either costly, or beneficial. +//! +//! For instance, it is _impolite_ to send the same message more than once. +//! In the future, there will be a fallback for allowing sending the same message +//! under certain conditions that are used to un-stick the protocol. + +use std::{pin::Pin, sync::Arc, task::{Poll, Context}}; + +use futures::{prelude::*, channel::mpsc, future::select, task::SpawnExt}; +use finality_grandpa::Message::{Prevote, Precommit, PrimaryPropose}; +use finality_grandpa::{voter, voter_set::VoterSet}; +use log::{debug, trace}; +use sc_network::{NetworkService, ReputationChange}; +use sc_network_gossip::{GossipEngine, Network as GossipNetwork}; +use parity_scale_codec::{Encode, Decode}; +use sp_core::Pair; +use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, NumberFor}; +use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; + +use crate::{ + CatchUp, Commit, CommunicationIn, CommunicationOutH, + CompactCommit, Error, Message, SignedMessage, +}; +use crate::environment::HasVoted; +use gossip::{ + GossipMessage, FullCatchUpMessage, FullCommitMessage, VoteMessage, GossipValidator +}; +use sp_finality_grandpa::{ + AuthorityPair, AuthorityId, AuthoritySignature, SetId as SetIdNumber, RoundNumber, +}; + +pub mod gossip; +mod periodic; + +#[cfg(test)] +mod tests; + +pub use sp_finality_grandpa::GRANDPA_ENGINE_ID; + +// cost scalars for reporting peers. +mod cost { + use sc_network::ReputationChange as Rep; + pub(super) const PAST_REJECTION: Rep = Rep::new(-50, "Grandpa: Past message"); + pub(super) const BAD_SIGNATURE: Rep = Rep::new(-100, "Grandpa: Bad signature"); + pub(super) const MALFORMED_CATCH_UP: Rep = Rep::new(-1000, "Grandpa: Malformed cath-up"); + pub(super) const MALFORMED_COMMIT: Rep = Rep::new(-1000, "Grandpa: Malformed commit"); + pub(super) const FUTURE_MESSAGE: Rep = Rep::new(-500, "Grandpa: Future message"); + pub(super) const UNKNOWN_VOTER: Rep = Rep::new(-150, "Grandpa: Uknown voter"); + + pub(super) const INVALID_VIEW_CHANGE: Rep = Rep::new(-500, "Grandpa: Invalid view change"); + pub(super) const PER_UNDECODABLE_BYTE: i32 = -5; + pub(super) const PER_SIGNATURE_CHECKED: i32 = -25; + pub(super) const PER_BLOCK_LOADED: i32 = -10; + pub(super) const INVALID_CATCH_UP: Rep = Rep::new(-5000, "Grandpa: Invalid catch-up"); + pub(super) const INVALID_COMMIT: Rep = Rep::new(-5000, "Grandpa: Invalid commit"); + pub(super) const OUT_OF_SCOPE_MESSAGE: Rep = Rep::new(-500, "Grandpa: Out-of-scope message"); + pub(super) const CATCH_UP_REQUEST_TIMEOUT: Rep = Rep::new(-200, "Grandpa: Catch-up reqeust timeout"); + + // cost of answering a catch up request + pub(super) const CATCH_UP_REPLY: Rep = Rep::new(-200, "Grandpa: Catch-up reply"); + pub(super) const HONEST_OUT_OF_SCOPE_CATCH_UP: Rep = Rep::new(-200, "Grandpa: Out-of-scope catch-up"); +} + +// benefit scalars for reporting peers. +mod benefit { + use sc_network::ReputationChange as Rep; + pub(super) const NEIGHBOR_MESSAGE: Rep = Rep::new(100, "Grandpa: Neighbor message"); + pub(super) const ROUND_MESSAGE: Rep = Rep::new(100, "Grandpa: Round message"); + pub(super) const BASIC_VALIDATED_CATCH_UP: Rep = Rep::new(200, "Grandpa: Catch-up message"); + pub(super) const BASIC_VALIDATED_COMMIT: Rep = Rep::new(100, "Grandpa: Commit"); + pub(super) const PER_EQUIVOCATION: i32 = 10; +} + +/// A handle to the network. +/// +/// Something that provides both the capabilities needed for the `gossip_network::Network` trait as +/// well as the ability to set a fork sync request for a particular block. +pub trait Network: GossipNetwork + Clone + Send + 'static { + /// Notifies the sync service to try and sync the given block from the given + /// peers. + /// + /// If the given vector of peers is empty then the underlying implementation + /// should make a best effort to fetch the block from any peers it is + /// connected to (NOTE: this assumption will change in the future #3629). + fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor); +} + +impl Network for Arc> where + B: BlockT, + S: sc_network::specialization::NetworkSpecialization, + H: sc_network::ExHashT, +{ + fn set_sync_fork_request(&self, peers: Vec, hash: B::Hash, number: NumberFor) { + NetworkService::set_sync_fork_request(self, peers, hash, number) + } +} + +/// Create a unique topic for a round and set-id combo. +pub(crate) fn round_topic(round: RoundNumber, set_id: SetIdNumber) -> B::Hash { + <::Hashing as HashT>::hash(format!("{}-{}", set_id, round).as_bytes()) +} + +/// Create a unique topic for global messages on a set ID. +pub(crate) fn global_topic(set_id: SetIdNumber) -> B::Hash { + <::Hashing as HashT>::hash(format!("{}-GLOBAL", set_id).as_bytes()) +} + +/// Bridge between the underlying network service, gossiping consensus messages and Grandpa +pub(crate) struct NetworkBridge> { + service: N, + gossip_engine: GossipEngine, + validator: Arc>, + neighbor_sender: periodic::NeighborPacketSender, +} + +impl> NetworkBridge + where + B::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, +{ + /// Create a new NetworkBridge to the given NetworkService. Returns the service + /// handle. + /// On creation it will register previous rounds' votes with the gossip + /// service taken from the VoterSetState. + pub(crate) fn new( + service: N, + config: crate::Config, + set_state: crate::environment::SharedVoterSetState, + executor: &impl futures::task::Spawn, + on_exit: impl futures::Future + Clone + Send + Unpin + 'static, + ) -> Self { + let (validator, report_stream) = GossipValidator::new( + config, + set_state.clone(), + ); + + let validator = Arc::new(validator); + let gossip_engine = GossipEngine::new(service.clone(), executor, GRANDPA_ENGINE_ID, validator.clone()); + + { + // register all previous votes with the gossip service so that they're + // available to peers potentially stuck on a previous round. + let completed = set_state.read().completed_rounds(); + let (set_id, voters) = completed.set_info(); + validator.note_set(SetId(set_id), voters.to_vec(), |_, _| {}); + for round in completed.iter() { + let topic = round_topic::(round.number, set_id); + + // we need to note the round with the gossip validator otherwise + // messages will be ignored. + validator.note_round(Round(round.number), |_, _| {}); + + for signed in round.votes.iter() { + let message = gossip::GossipMessage::Vote( + gossip::VoteMessage:: { + message: signed.clone(), + round: Round(round.number), + set_id: SetId(set_id), + } + ); + + gossip_engine.register_gossip_message( + topic, + message.encode(), + ); + } + + trace!(target: "afg", + "Registered {} messages for topic {:?} (round: {}, set_id: {})", + round.votes.len(), + topic, + round.number, + set_id, + ); + } + } + + let (rebroadcast_job, neighbor_sender) = periodic::neighbor_packet_worker(gossip_engine.clone()); + let reporting_job = report_stream.consume(gossip_engine.clone()); + + let bridge = NetworkBridge { service, gossip_engine, validator, neighbor_sender }; + + executor.spawn(select(on_exit.clone(), rebroadcast_job).map(drop)) + .expect("failed to spawn grandpa rebroadcast job task"); + executor.spawn(select(on_exit.clone(), reporting_job).map(drop)) + .expect("failed to spawn grandpa reporting job task"); + + bridge + } + + /// Note the beginning of a new round to the `GossipValidator`. + pub(crate) fn note_round( + &self, + round: Round, + set_id: SetId, + voters: &VoterSet, + ) { + // is a no-op if currently in that set. + self.validator.note_set( + set_id, + voters.voters().iter().map(|(v, _)| v.clone()).collect(), + |to, neighbor| self.neighbor_sender.send(to, neighbor), + ); + + self.validator.note_round( + round, + |to, neighbor| self.neighbor_sender.send(to, neighbor), + ); + } + + /// Get a stream of signature-checked round messages from the network as well as a sink for round messages to the + /// network all within the current set. + pub(crate) fn round_communication( + &self, + round: Round, + set_id: SetId, + voters: Arc>, + local_key: Option, + has_voted: HasVoted, + ) -> ( + impl Stream, Error>>, + impl Sink, Error = Error> + Unpin, + ) { + self.note_round( + round, + set_id, + &*voters, + ); + + let locals = local_key.and_then(|pair| { + let id = pair.public(); + if voters.contains_key(&id) { + Some((pair, id)) + } else { + None + } + }); + + let topic = round_topic::(round.0, set_id.0); + let incoming = self.gossip_engine.messages_for(topic) + .filter_map(|notification| { + let decoded = GossipMessage::::decode(&mut ¬ification.message[..]); + if let Err(ref e) = decoded { + debug!(target: "afg", "Skipping malformed message {:?}: {}", notification, e); + } + future::ready(decoded.ok()) + }) + .filter_map(move |msg| { + match msg { + GossipMessage::Vote(msg) => { + // check signature. + if !voters.contains_key(&msg.message.id) { + debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); + return future::ready(None); + } + + match &msg.message.message { + PrimaryPropose(propose) => { + telemetry!(CONSENSUS_INFO; "afg.received_propose"; + "voter" => ?format!("{}", msg.message.id), + "target_number" => ?propose.target_number, + "target_hash" => ?propose.target_hash, + ); + }, + 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, + ); + }, + }; + + future::ready(Some(msg.message)) + } + _ => { + debug!(target: "afg", "Skipping unknown message type"); + future::ready(None) + } + } + }) + .map(Ok); + + let (tx, out_rx) = mpsc::unbounded(); + let outgoing = OutgoingMessages:: { + round: round.0, + set_id: set_id.0, + network: self.gossip_engine.clone(), + locals, + sender: tx, + has_voted, + }; + + let out_rx = out_rx.map(Result::Ok).map_err(move |()| Error::Network( + format!("Failed to receive on unbounded receiver for round {}", round.0) + )); + + // Combine incoming votes from external GRANDPA nodes with outgoing + // votes from our own GRANDPA voter to have a single + // vote-import-pipeline. + let incoming = stream::select(incoming, out_rx); + + (incoming, outgoing) + } + + /// Set up the global communication streams. + pub(crate) fn global_communication( + &self, + set_id: SetId, + voters: Arc>, + is_voter: bool, + ) -> ( + impl Stream, Error>>, + impl Sink, Error = Error> + Unpin, + ) { + self.validator.note_set( + set_id, + voters.voters().iter().map(|(v, _)| v.clone()).collect(), + |to, neighbor| self.neighbor_sender.send(to, neighbor), + ); + + let service = self.gossip_engine.clone(); + let topic = global_topic::(set_id.0); + let incoming = incoming_global( + service, + topic, + voters, + self.validator.clone(), + self.neighbor_sender.clone(), + ); + + let outgoing = CommitsOut::::new( + self.gossip_engine.clone(), + set_id.0, + is_voter, + self.validator.clone(), + self.neighbor_sender.clone(), + ); + + let outgoing = outgoing.with(|out| { + let voter::CommunicationOut::Commit(round, commit) = out; + future::ok((round, commit)) + }); + + (incoming, outgoing) + } +} + +impl> NetworkBridge { + /// Notifies the sync service to try and sync the given block from the given + /// peers. + /// + /// If the given vector of peers is empty then the underlying implementation + /// should make a best effort to fetch the block from any peers it is + /// connected to (NOTE: this assumption will change in the future #3629). + pub(crate) fn set_sync_fork_request( + &self, + peers: Vec, + hash: B::Hash, + number: NumberFor + ) { + Network::set_sync_fork_request(&self.service, peers, hash, number) + } +} + +fn incoming_global( + mut gossip_engine: GossipEngine, + topic: B::Hash, + voters: Arc>, + gossip_validator: Arc>, + neighbor_sender: periodic::NeighborPacketSender, +) -> impl Stream, Error>> { + let process_commit = move | + msg: FullCommitMessage, + mut notification: sc_network_gossip::TopicNotification, + gossip_engine: &mut GossipEngine, + gossip_validator: &Arc>, + voters: &VoterSet, + | { + 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.clone(), + "target_hash" => ?msg.message.target_hash.clone(), + ); + + if let Err(cost) = check_compact_commit::( + &msg.message, + voters, + msg.round, + msg.set_id, + ) { + if let Some(who) = notification.sender { + gossip_engine.report(who, cost); + } + + return None; + } + + let round = msg.round.0; + let commit = msg.message; + let finalized_number = commit.target_number; + let gossip_validator = gossip_validator.clone(); + let gossip_engine = gossip_engine.clone(); + let neighbor_sender = neighbor_sender.clone(); + let cb = move |outcome| match outcome { + voter::CommitProcessingOutcome::Good(_) => { + // if it checks out, gossip it. not accounting for + // any discrepancy between the actual ghost and the claimed + // finalized number. + gossip_validator.note_commit_finalized( + finalized_number, + |to, neighbor| neighbor_sender.send(to, neighbor), + ); + + gossip_engine.gossip_message(topic, notification.message.clone(), false); + } + voter::CommitProcessingOutcome::Bad(_) => { + // report peer and do not gossip. + if let Some(who) = notification.sender.take() { + gossip_engine.report(who, cost::INVALID_COMMIT); + } + } + }; + + let cb = voter::Callback::Work(Box::new(cb)); + + Some(voter::CommunicationIn::Commit(round, commit, cb)) + }; + + let process_catch_up = move | + msg: FullCatchUpMessage, + mut notification: sc_network_gossip::TopicNotification, + gossip_engine: &mut GossipEngine, + gossip_validator: &Arc>, + voters: &VoterSet, + | { + let gossip_validator = gossip_validator.clone(); + let gossip_engine = gossip_engine.clone(); + + if let Err(cost) = check_catch_up::( + &msg.message, + voters, + msg.set_id, + ) { + if let Some(who) = notification.sender { + gossip_engine.report(who, cost); + } + + return None; + } + + let cb = move |outcome| { + if let voter::CatchUpProcessingOutcome::Bad(_) = outcome { + // report peer + if let Some(who) = notification.sender.take() { + gossip_engine.report(who, cost::INVALID_CATCH_UP); + } + } + + gossip_validator.note_catch_up_message_processed(); + }; + + let cb = voter::Callback::Work(Box::new(cb)); + + Some(voter::CommunicationIn::CatchUp(msg.message, cb)) + }; + + gossip_engine.messages_for(topic) + .filter_map(|notification| { + // this could be optimized by decoding piecewise. + let decoded = GossipMessage::::decode(&mut ¬ification.message[..]); + if let Err(ref e) = decoded { + trace!(target: "afg", "Skipping malformed commit message {:?}: {}", notification, e); + } + future::ready(decoded.map(move |d| (notification, d)).ok()) + }) + .filter_map(move |(notification, msg)| { + future::ready(match msg { + GossipMessage::Commit(msg) => + process_commit(msg, notification, &mut gossip_engine, &gossip_validator, &*voters), + GossipMessage::CatchUp(msg) => + process_catch_up(msg, notification, &mut gossip_engine, &gossip_validator, &*voters), + _ => { + debug!(target: "afg", "Skipping unknown message type"); + None + } + }) + }) + .map(Ok) +} + +impl> Clone for NetworkBridge { + fn clone(&self) -> Self { + NetworkBridge { + service: self.service.clone(), + gossip_engine: self.gossip_engine.clone(), + validator: Arc::clone(&self.validator), + neighbor_sender: self.neighbor_sender.clone(), + } + } +} + +pub(crate) fn localized_payload(round: RoundNumber, set_id: SetIdNumber, message: &E) -> Vec { + (message, round, set_id).encode() +} + +/// Type-safe wrapper around a round number. +#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)] +pub struct Round(pub RoundNumber); + +/// Type-safe wrapper around a set ID. +#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)] +pub struct SetId(pub SetIdNumber); + +// check a message. +pub(crate) fn check_message_sig( + message: &Message, + id: &AuthorityId, + signature: &AuthoritySignature, + round: RoundNumber, + set_id: SetIdNumber, +) -> Result<(), ()> { + let as_public = id.clone(); + let encoded_raw = localized_payload(round, set_id, message); + if AuthorityPair::verify(signature, &encoded_raw, &as_public) { + Ok(()) + } else { + debug!(target: "afg", "Bad signature on message from {:?}", id); + Err(()) + } +} + +/// A sink for outgoing messages to the network. Any messages that are sent will +/// be replaced, as appropriate, according to the given `HasVoted`. +/// NOTE: The votes are stored unsigned, which means that the signatures need to +/// be "stable", i.e. we should end up with the exact same signed message if we +/// use the same raw message and key to sign. This is currently true for +/// `ed25519` and `BLS` signatures (which we might use in the future), care must +/// be taken when switching to different key types. +struct OutgoingMessages { + round: RoundNumber, + set_id: SetIdNumber, + locals: Option<(AuthorityPair, AuthorityId)>, + sender: mpsc::UnboundedSender>, + network: GossipEngine, + has_voted: HasVoted, +} + +impl Sink> for OutgoingMessages + where + Block::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, +{ + type Error = Error; + + fn poll_ready(self: Pin<&mut Self>, _: &mut Context) -> Poll> { + Poll::Ready(Ok(())) + } + + fn start_send(self: Pin<&mut Self>, mut msg: Message) -> Result<(), Self::Error> { + // if we've voted on this round previously under the same key, send that vote instead + match &mut msg { + finality_grandpa::Message::PrimaryPropose(ref mut vote) => + if let Some(propose) = self.has_voted.propose() { + *vote = propose.clone(); + }, + finality_grandpa::Message::Prevote(ref mut vote) => + if let Some(prevote) = self.has_voted.prevote() { + *vote = prevote.clone(); + }, + finality_grandpa::Message::Precommit(ref mut vote) => + if let Some(precommit) = self.has_voted.precommit() { + *vote = precommit.clone(); + }, + } + + // when locals exist, sign messages on import + if let Some((ref pair, ref local_id)) = self.locals { + let encoded = localized_payload(self.round, self.set_id, &msg); + let signature = pair.sign(&encoded[..]); + + let target_hash = msg.target().0.clone(); + let signed = SignedMessage:: { + message: msg, + signature, + id: local_id.clone(), + }; + + let message = GossipMessage::Vote(VoteMessage:: { + message: signed.clone(), + round: Round(self.round), + set_id: SetId(self.set_id), + }); + + debug!( + target: "afg", + "Announcing block {} to peers which we voted on in round {} in set {}", + target_hash, + self.round, + self.set_id, + ); + + telemetry!( + CONSENSUS_DEBUG; "afg.announcing_blocks_to_voted_peers"; + "block" => ?target_hash, "round" => ?self.round, "set_id" => ?self.set_id, + ); + + // announce the block we voted on to our peers. + self.network.announce(target_hash, Vec::new()); + + // propagate the message to peers + let topic = round_topic::(self.round, self.set_id); + self.network.gossip_message(topic, message.encode(), false); + + // forward the message to the inner sender. + let _ = self.sender.unbounded_send(signed); + } + + Ok(()) + } + + fn poll_flush(self: Pin<&mut Self>, _: &mut Context) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll_close(self: Pin<&mut Self>, _: &mut Context) -> Poll> { + // ignore errors since we allow this inner sender to be closed already. + Pin::into_inner(self).sender.disconnect(); + Poll::Ready(Ok(())) + } +} + +// checks a compact commit. returns the cost associated with processing it if +// the commit was bad. +fn check_compact_commit( + msg: &CompactCommit, + voters: &VoterSet, + round: Round, + set_id: SetId, +) -> Result<(), ReputationChange> { + // 4f + 1 = equivocations from f voters. + let f = voters.total_weight() - voters.threshold(); + let full_threshold = voters.total_weight() + f; + + // check total weight is not out of range. + let mut total_weight = 0; + for (_, ref id) in &msg.auth_data { + if let Some(weight) = voters.info(id).map(|info| info.weight()) { + total_weight += weight; + if total_weight > full_threshold { + return Err(cost::MALFORMED_COMMIT); + } + } else { + debug!(target: "afg", "Skipping commit containing unknown voter {}", id); + return Err(cost::MALFORMED_COMMIT); + } + } + + if total_weight < voters.threshold() { + return Err(cost::MALFORMED_COMMIT); + } + + // check signatures on all contained precommits. + for (i, (precommit, &(ref sig, ref id))) in msg.precommits.iter() + .zip(&msg.auth_data) + .enumerate() + { + use crate::communication::gossip::Misbehavior; + use finality_grandpa::Message as GrandpaMessage; + + if let Err(()) = check_message_sig::( + &GrandpaMessage::Precommit(precommit.clone()), + id, + sig, + round.0, + set_id.0, + ) { + debug!(target: "afg", "Bad commit message signature {}", id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_commit_msg_signature"; "id" => ?id); + let cost = Misbehavior::BadCommitMessage { + signatures_checked: i as i32, + blocks_loaded: 0, + equivocations_caught: 0, + }.cost(); + + return Err(cost); + } + } + + Ok(()) +} + +// checks a catch up. returns the cost associated with processing it if +// the catch up was bad. +fn check_catch_up( + msg: &CatchUp, + voters: &VoterSet, + set_id: SetId, +) -> Result<(), ReputationChange> { + // 4f + 1 = equivocations from f voters. + let f = voters.total_weight() - voters.threshold(); + let full_threshold = voters.total_weight() + f; + + // check total weight is not out of range for a set of votes. + fn check_weight<'a>( + voters: &'a VoterSet, + votes: impl Iterator, + full_threshold: u64, + ) -> Result<(), ReputationChange> { + let mut total_weight = 0; + + for id in votes { + if let Some(weight) = voters.info(&id).map(|info| info.weight()) { + total_weight += weight; + if total_weight > full_threshold { + return Err(cost::MALFORMED_CATCH_UP); + } + } else { + debug!(target: "afg", "Skipping catch up message containing unknown voter {}", id); + return Err(cost::MALFORMED_CATCH_UP); + } + } + + if total_weight < voters.threshold() { + return Err(cost::MALFORMED_CATCH_UP); + } + + Ok(()) + }; + + check_weight( + voters, + msg.prevotes.iter().map(|vote| &vote.id), + full_threshold, + )?; + + check_weight( + voters, + msg.precommits.iter().map(|vote| &vote.id), + full_threshold, + )?; + + fn check_signatures<'a, B, I>( + messages: I, + round: RoundNumber, + set_id: SetIdNumber, + mut signatures_checked: usize, + ) -> Result where + B: BlockT, + I: Iterator, &'a AuthorityId, &'a AuthoritySignature)>, + { + use crate::communication::gossip::Misbehavior; + + for (msg, id, sig) in messages { + signatures_checked += 1; + + if let Err(()) = check_message_sig::( + &msg, + id, + sig, + round, + set_id, + ) { + debug!(target: "afg", "Bad catch up message signature {}", id); + telemetry!(CONSENSUS_DEBUG; "afg.bad_catch_up_msg_signature"; "id" => ?id); + + let cost = Misbehavior::BadCatchUpMessage { + signatures_checked: signatures_checked as i32, + }.cost(); + + return Err(cost); + } + } + + Ok(signatures_checked) + } + + // check signatures on all contained prevotes. + let signatures_checked = check_signatures::( + msg.prevotes.iter().map(|vote| { + (finality_grandpa::Message::Prevote(vote.prevote.clone()), &vote.id, &vote.signature) + }), + msg.round_number, + set_id.0, + 0, + )?; + + // check signatures on all contained precommits. + let _ = check_signatures::( + msg.precommits.iter().map(|vote| { + (finality_grandpa::Message::Precommit(vote.precommit.clone()), &vote.id, &vote.signature) + }), + msg.round_number, + set_id.0, + signatures_checked, + )?; + + Ok(()) +} + +/// An output sink for commit messages. +struct CommitsOut { + network: GossipEngine, + set_id: SetId, + is_voter: bool, + gossip_validator: Arc>, + neighbor_sender: periodic::NeighborPacketSender, +} + +impl CommitsOut { + /// Create a new commit output stream. + pub(crate) fn new( + network: GossipEngine, + set_id: SetIdNumber, + is_voter: bool, + gossip_validator: Arc>, + neighbor_sender: periodic::NeighborPacketSender, + ) -> Self { + CommitsOut { + network, + set_id: SetId(set_id), + is_voter, + gossip_validator, + neighbor_sender, + } + } +} + +impl Sink<(RoundNumber, Commit)> for CommitsOut { + type Error = Error; + + fn poll_ready(self: Pin<&mut Self>, _: &mut Context) -> Poll> { + Poll::Ready(Ok(())) + } + + fn start_send(self: Pin<&mut Self>, input: (RoundNumber, Commit)) -> Result<(), Self::Error> { + if !self.is_voter { + return Ok(()); + } + + let (round, commit) = input; + let round = Round(round); + + telemetry!(CONSENSUS_DEBUG; "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(); + + let compact_commit = CompactCommit:: { + target_hash: commit.target_hash, + target_number: commit.target_number, + precommits, + auth_data + }; + + let message = GossipMessage::Commit(FullCommitMessage:: { + round: round, + set_id: self.set_id, + message: compact_commit, + }); + + let topic = global_topic::(self.set_id.0); + + // the gossip validator needs to be made aware of the best commit-height we know of + // before gossiping + self.gossip_validator.note_commit_finalized( + commit.target_number, + |to, neighbor| self.neighbor_sender.send(to, neighbor), + ); + self.network.gossip_message(topic, message.encode(), false); + + Ok(()) + } + + fn poll_close(self: Pin<&mut Self>, _: &mut Context) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll_flush(self: Pin<&mut Self>, _: &mut Context) -> Poll> { + Poll::Ready(Ok(())) + } +} diff --git a/client/finality-grandpa/src/communication/periodic.rs b/client/finality-grandpa/src/communication/periodic.rs new file mode 100644 index 0000000000000..6994d0a53a9d9 --- /dev/null +++ b/client/finality-grandpa/src/communication/periodic.rs @@ -0,0 +1,108 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Periodic rebroadcast of neighbor packets. + +use std::time::{Instant, Duration}; +use std::pin::Pin; +use std::task::Poll; + +use parity_scale_codec::Encode; +use futures::prelude::*; +use futures::channel::mpsc; +use futures_timer::Delay; +use log::debug; + +use sc_network::PeerId; +use sc_network_gossip::GossipEngine; +use sp_runtime::traits::{NumberFor, Block as BlockT}; +use super::gossip::{NeighborPacket, GossipMessage}; + +// how often to rebroadcast, if no other +const REBROADCAST_AFTER: Duration = Duration::from_secs(2 * 60); + +fn rebroadcast_instant() -> Instant { + Instant::now() + REBROADCAST_AFTER +} + +/// A sender used to send neighbor packets to a background job. +#[derive(Clone)] +pub(super) struct NeighborPacketSender( + mpsc::UnboundedSender<(Vec, NeighborPacket>)> +); + +impl NeighborPacketSender { + /// Send a neighbor packet for the background worker to gossip to peers. + pub fn send( + &self, + who: Vec, + neighbor_packet: NeighborPacket>, + ) { + if let Err(err) = self.0.unbounded_send((who, neighbor_packet)) { + debug!(target: "afg", "Failed to send neighbor packet: {:?}", err); + } + } +} + +/// Does the work of sending neighbor packets, asynchronously. +/// +/// It may rebroadcast the last neighbor packet periodically when no +/// progress is made. +pub(super) fn neighbor_packet_worker(net: GossipEngine) -> ( + impl Future + Unpin + Send + 'static, + NeighborPacketSender, +) where + B: BlockT, +{ + let mut last = None; + let (tx, mut rx) = mpsc::unbounded::<(Vec, NeighborPacket>)>(); + let mut delay = Delay::new(REBROADCAST_AFTER); + + let work = futures::future::poll_fn(move |cx| { + loop { + match Pin::new(&mut rx).poll_next(cx) { + Poll::Ready(None) => return Poll::Ready(()), + Poll::Ready(Some((to, packet))) => { + // send to peers. + net.send_message(to.clone(), GossipMessage::::from(packet.clone()).encode()); + + // rebroadcasting network. + delay.reset(rebroadcast_instant()); + last = Some((to, packet)); + } + Poll::Pending => break, + } + } + + // has to be done in a loop because it needs to be polled after + // re-scheduling. + loop { + match Pin::new(&mut delay).poll(cx) { + Poll::Ready(()) => { + delay.reset(rebroadcast_instant()); + + if let Some((ref to, ref packet)) = last { + // send to peers. + net.send_message(to.clone(), GossipMessage::::from(packet.clone()).encode()); + } + } + Poll::Pending => return Poll::Pending, + } + } + }); + + (work, NeighborPacketSender(tx)) +} diff --git a/client/finality-grandpa/src/communication/tests.rs b/client/finality-grandpa/src/communication/tests.rs new file mode 100644 index 0000000000000..95e5c1054a632 --- /dev/null +++ b/client/finality-grandpa/src/communication/tests.rs @@ -0,0 +1,505 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the communication portion of the GRANDPA crate. + +use futures::channel::mpsc; +use futures::prelude::*; +use sc_network::{Event as NetworkEvent, PeerId, config::Roles}; +use sc_network_test::{Block, Hash}; +use sc_network_gossip::Validator; +use std::sync::Arc; +use sp_keyring::Ed25519Keyring; +use parity_scale_codec::Encode; +use sp_runtime::{ConsensusEngineId, traits::NumberFor}; +use std::{pin::Pin, task::{Context, Poll}}; +use crate::environment::SharedVoterSetState; +use sp_finality_grandpa::{AuthorityList, GRANDPA_ENGINE_ID}; +use super::gossip::{self, GossipValidator}; +use super::{AuthorityId, VoterSet, Round, SetId}; + +enum Event { + EventStream(mpsc::UnboundedSender), + WriteNotification(sc_network::PeerId, Vec), + Report(sc_network::PeerId, sc_network::ReputationChange), + Announce(Hash), +} + +#[derive(Clone)] +struct TestNetwork { + sender: mpsc::UnboundedSender, +} + +impl TestNetwork { + fn event_stream_03(&self) -> Pin + Send>> { + let (tx, rx) = mpsc::unbounded(); + let _ = self.sender.unbounded_send(Event::EventStream(tx)); + Box::pin(rx) + } +} + +impl sc_network_gossip::Network for TestNetwork { + fn event_stream(&self) -> Box + Send> { + Box::new( + self.event_stream_03().map(Ok::<_, ()>).compat() + ) + } + + fn report_peer(&self, who: sc_network::PeerId, cost_benefit: sc_network::ReputationChange) { + let _ = self.sender.unbounded_send(Event::Report(who, cost_benefit)); + } + + fn disconnect_peer(&self, _: PeerId) {} + + fn write_notification(&self, who: PeerId, _: ConsensusEngineId, message: Vec) { + let _ = self.sender.unbounded_send(Event::WriteNotification(who, message)); + } + + fn register_notifications_protocol(&self, _: ConsensusEngineId) {} + + fn announce(&self, block: Hash, _associated_data: Vec) { + let _ = self.sender.unbounded_send(Event::Announce(block)); + } +} + +impl super::Network for TestNetwork { + fn set_sync_fork_request( + &self, + _peers: Vec, + _hash: Hash, + _number: NumberFor, + ) {} +} + +impl sc_network_gossip::ValidatorContext for TestNetwork { + fn broadcast_topic(&mut self, _: Hash, _: bool) { } + + fn broadcast_message(&mut self, _: Hash, _: Vec, _: bool) { } + + fn send_message(&mut self, who: &sc_network::PeerId, data: Vec) { + >::write_notification( + self, + who.clone(), + GRANDPA_ENGINE_ID, + data, + ); + } + + fn send_topic(&mut self, _: &sc_network::PeerId, _: Hash, _: bool) { } +} + +struct Tester { + net_handle: super::NetworkBridge, + gossip_validator: Arc>, + events: mpsc::UnboundedReceiver, +} + +impl Tester { + fn filter_network_events(self, mut pred: F) -> impl Future + where F: FnMut(Event) -> bool + { + let mut s = Some(self); + futures::future::poll_fn(move |cx| loop { + match Stream::poll_next(Pin::new(&mut s.as_mut().unwrap().events), cx) { + Poll::Ready(None) => panic!("concluded early"), + Poll::Ready(Some(item)) => if pred(item) { + return Poll::Ready(s.take().unwrap()) + }, + Poll::Pending => return Poll::Pending, + } + }) + } +} + +// some random config (not really needed) +fn config() -> crate::Config { + crate::Config { + gossip_duration: std::time::Duration::from_millis(10), + justification_period: 256, + keystore: None, + name: None, + is_authority: true, + observer_enabled: true, + } +} + +// dummy voter set state +fn voter_set_state() -> SharedVoterSetState { + use crate::authorities::AuthoritySet; + use crate::environment::VoterSetState; + use finality_grandpa::round::State as RoundState; + use sp_core::H256; + + let state = RoundState::genesis((H256::zero(), 0)); + let base = state.prevote_ghost.unwrap(); + let voters = AuthoritySet::genesis(Vec::new()); + let set_state = VoterSetState::live( + 0, + &voters, + base, + ); + + set_state.into() +} + +// needs to run in a tokio runtime. +fn make_test_network(executor: &impl futures::task::Spawn) -> ( + impl Future, + TestNetwork, +) { + let (tx, rx) = mpsc::unbounded(); + let net = TestNetwork { sender: tx }; + + #[derive(Clone)] + struct Exit; + + impl futures::Future for Exit { + type Output = (); + + fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<()> { + Poll::Pending + } + } + + let bridge = super::NetworkBridge::new( + net.clone(), + config(), + voter_set_state(), + executor, + Exit, + ); + + ( + futures::future::ready(Tester { + gossip_validator: bridge.validator.clone(), + net_handle: bridge, + events: rx, + }), + net, + ) +} + +fn make_ids(keys: &[Ed25519Keyring]) -> AuthorityList { + keys.iter() + .map(|key| key.clone().public().into()) + .map(|id| (id, 1)) + .collect() +} + +struct NoopContext; + +impl sc_network_gossip::ValidatorContext for NoopContext { + fn broadcast_topic(&mut self, _: Hash, _: bool) { } + fn broadcast_message(&mut self, _: Hash, _: Vec, _: bool) { } + fn send_message(&mut self, _: &sc_network::PeerId, _: Vec) { } + fn send_topic(&mut self, _: &sc_network::PeerId, _: Hash, _: bool) { } +} + +#[test] +fn good_commit_leads_to_relay() { + let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let public = make_ids(&private[..]); + let voter_set = Arc::new(public.iter().cloned().collect::>()); + + let round = 1; + let set_id = 1; + + let commit = { + let target_hash: Hash = [1; 32].into(); + let target_number = 500; + + let precommit = finality_grandpa::Precommit { target_hash: target_hash.clone(), target_number }; + let payload = super::localized_payload( + round, set_id, &finality_grandpa::Message::Precommit(precommit.clone()) + ); + + let mut precommits = Vec::new(); + let mut auth_data = Vec::new(); + + for (i, key) in private.iter().enumerate() { + precommits.push(precommit.clone()); + + let signature = sp_finality_grandpa::AuthoritySignature::from(key.sign(&payload[..])); + auth_data.push((signature, public[i].0.clone())) + } + + finality_grandpa::CompactCommit { + target_hash, + target_number, + precommits, + auth_data, + } + }; + + let encoded_commit = gossip::GossipMessage::::Commit(gossip::FullCommitMessage { + round: Round(round), + set_id: SetId(set_id), + message: commit, + }).encode(); + + let id = sc_network::PeerId::random(); + let global_topic = super::global_topic::(set_id); + + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + let test = make_test_network(&threads_pool).0 + .then(move |tester| { + // register a peer. + tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::FULL); + future::ready((tester, id)) + }) + .then(move |(tester, id)| { + // start round, dispatch commit, and wait for broadcast. + let (commits_in, _) = tester.net_handle.global_communication(SetId(1), voter_set, false); + + { + let (action, ..) = tester.gossip_validator.do_validate(&id, &encoded_commit[..]); + match action { + gossip::Action::ProcessAndDiscard(t, _) => assert_eq!(t, global_topic), + _ => panic!("wrong expected outcome from initial commit validation"), + } + } + + let commit_to_send = encoded_commit.clone(); + + // asking for global communication will cause the test network + // to send us an event asking us for a stream. use it to + // send a message. + let sender_id = id.clone(); + let send_message = tester.filter_network_events(move |event| match event { + Event::EventStream(sender) => { + // Add the sending peer and send the commit + let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { + remote: sender_id.clone(), + engine_id: GRANDPA_ENGINE_ID, + roles: Roles::FULL, + }); + + let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived { + remote: sender_id.clone(), + messages: vec![(GRANDPA_ENGINE_ID, commit_to_send.clone().into())], + }); + + // Add a random peer which will be the recipient of this message + let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { + remote: sc_network::PeerId::random(), + engine_id: GRANDPA_ENGINE_ID, + roles: Roles::FULL, + }); + + true + } + _ => false, + }); + + // when the commit comes in, we'll tell the callback it was good. + let handle_commit = commits_in.into_future() + .map(|(item, _)| { + match item.unwrap().unwrap() { + finality_grandpa::voter::CommunicationIn::Commit(_, _, mut callback) => { + callback.run(finality_grandpa::voter::CommitProcessingOutcome::good()); + }, + _ => panic!("commit expected"), + } + }); + + // once the message is sent and commit is "handled" we should have + // a repropagation event coming from the network. + future::join(send_message, handle_commit).then(move |(tester, ())| { + tester.filter_network_events(move |event| match event { + Event::WriteNotification(_, data) => { + data == encoded_commit + } + _ => false, + }) + }) + .map(|_| ()) + }); + + futures::executor::block_on(test); +} + +#[test] +fn bad_commit_leads_to_report() { + env_logger::init(); + let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let public = make_ids(&private[..]); + let voter_set = Arc::new(public.iter().cloned().collect::>()); + + let round = 1; + let set_id = 1; + + let commit = { + let target_hash: Hash = [1; 32].into(); + let target_number = 500; + + let precommit = finality_grandpa::Precommit { target_hash: target_hash.clone(), target_number }; + let payload = super::localized_payload( + round, set_id, &finality_grandpa::Message::Precommit(precommit.clone()) + ); + + let mut precommits = Vec::new(); + let mut auth_data = Vec::new(); + + for (i, key) in private.iter().enumerate() { + precommits.push(precommit.clone()); + + let signature = sp_finality_grandpa::AuthoritySignature::from(key.sign(&payload[..])); + auth_data.push((signature, public[i].0.clone())) + } + + finality_grandpa::CompactCommit { + target_hash, + target_number, + precommits, + auth_data, + } + }; + + let encoded_commit = gossip::GossipMessage::::Commit(gossip::FullCommitMessage { + round: Round(round), + set_id: SetId(set_id), + message: commit, + }).encode(); + + let id = sc_network::PeerId::random(); + let global_topic = super::global_topic::(set_id); + + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + let test = make_test_network(&threads_pool).0 + .map(move |tester| { + // register a peer. + tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::FULL); + (tester, id) + }) + .then(move |(tester, id)| { + // start round, dispatch commit, and wait for broadcast. + let (commits_in, _) = tester.net_handle.global_communication(SetId(1), voter_set, false); + + { + let (action, ..) = tester.gossip_validator.do_validate(&id, &encoded_commit[..]); + match action { + gossip::Action::ProcessAndDiscard(t, _) => assert_eq!(t, global_topic), + _ => panic!("wrong expected outcome from initial commit validation"), + } + } + + let commit_to_send = encoded_commit.clone(); + + // asking for global communication will cause the test network + // to send us an event asking us for a stream. use it to + // send a message. + let sender_id = id.clone(); + let send_message = tester.filter_network_events(move |event| match event { + Event::EventStream(sender) => { + let _ = sender.unbounded_send(NetworkEvent::NotificationStreamOpened { + remote: sender_id.clone(), + engine_id: GRANDPA_ENGINE_ID, + roles: Roles::FULL, + }); + let _ = sender.unbounded_send(NetworkEvent::NotificationsReceived { + remote: sender_id.clone(), + messages: vec![(GRANDPA_ENGINE_ID, commit_to_send.clone().into())], + }); + + true + } + _ => false, + }); + + // when the commit comes in, we'll tell the callback it was good. + let handle_commit = commits_in.into_future() + .map(|(item, _)| { + match item.unwrap().unwrap() { + finality_grandpa::voter::CommunicationIn::Commit(_, _, mut callback) => { + callback.run(finality_grandpa::voter::CommitProcessingOutcome::bad()); + }, + _ => panic!("commit expected"), + } + }); + + // once the message is sent and commit is "handled" we should have + // a report event coming from the network. + future::join(send_message, handle_commit).then(move |(tester, ())| { + tester.filter_network_events(move |event| match event { + Event::Report(who, cost_benefit) => { + who == id && cost_benefit == super::cost::INVALID_COMMIT + } + _ => false, + }) + }) + .map(|_| ()) + }); + + futures::executor::block_on(test); +} + +#[test] +fn peer_with_higher_view_leads_to_catch_up_request() { + let id = sc_network::PeerId::random(); + + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + let (tester, mut net) = make_test_network(&threads_pool); + let test = tester + .map(move |tester| { + // register a peer with authority role. + tester.gossip_validator.new_peer(&mut NoopContext, &id, sc_network::config::Roles::AUTHORITY); + ((tester, id)) + }) + .then(move |(tester, id)| { + // send neighbor message at round 10 and height 50 + let result = tester.gossip_validator.validate( + &mut net, + &id, + &gossip::GossipMessage::::from(gossip::NeighborPacket { + set_id: SetId(0), + round: Round(10), + commit_finalized_height: 50, + }).encode(), + ); + + // neighbor packets are always discard + match result { + sc_network_gossip::ValidationResult::Discard => {}, + _ => panic!("wrong expected outcome from neighbor validation"), + } + + // a catch up request should be sent to the peer for round - 1 + tester.filter_network_events(move |event| match event { + Event::WriteNotification(peer, message) => { + assert_eq!( + peer, + id, + ); + + assert_eq!( + message, + gossip::GossipMessage::::CatchUpRequest( + gossip::CatchUpRequestMessage { + set_id: SetId(0), + round: Round(9), + } + ).encode(), + ); + + true + }, + _ => false, + }) + .map(|_| ()) + }); + + futures::executor::block_on(test); +} diff --git a/core/finality-grandpa/src/consensus_changes.rs b/client/finality-grandpa/src/consensus_changes.rs similarity index 92% rename from core/finality-grandpa/src/consensus_changes.rs rename to client/finality-grandpa/src/consensus_changes.rs index 4d942248920f7..1ce7b551d0d7c 100644 --- a/core/finality-grandpa/src/consensus_changes.rs +++ b/client/finality-grandpa/src/consensus_changes.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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 . use std::sync::Arc; -use codec::{Encode, Decode}; +use parity_scale_codec::{Encode, Decode}; /// Consensus-related data changes tracker. #[derive(Clone, Debug, Encode, Decode)] @@ -47,11 +47,11 @@ impl ConsensusChanges { /// 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>>( + pub(crate) fn finalize ::sp_blockchain::Result>>( &mut self, block: (N, H), canonical_at_height: F, - ) -> ::client::error::Result<(bool, bool)> { + ) -> ::sp_blockchain::Result<(bool, bool)> { let (split_idx, has_finalized_changes) = self.pending_changes.iter() .enumerate() .take_while(|(_, &(at_height, _))| at_height <= block.0) diff --git a/core/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs similarity index 84% rename from core/finality-grandpa/src/environment.rs rename to client/finality-grandpa/src/environment.rs index b6f4e25ee1103..893a20b04bb75 100644 --- a/core/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,42 +21,49 @@ use std::sync::Arc; use std::time::Duration; use log::{debug, warn, info}; -use codec::{Decode, Encode}; +use parity_scale_codec::{Decode, Encode}; use futures::prelude::*; use futures_timer::Delay; use parking_lot::RwLock; - -use client::{ - backend::Backend, apply_aux, BlockchainEvents, CallExecutor, - Client, error::Error as ClientError, utils::is_descendent_of, - blockchain::HeaderBackend, backend::Finalizer, +use sp_blockchain::{HeaderBackend, Error as ClientError}; + +use sc_client_api::{ + BlockchainEvents, + backend::{AuxStore, Backend}, + Finalizer, + call_executor::CallExecutor, + utils::is_descendent_of, +}; +use sc_client::{ + apply_aux, Client, }; -use grandpa::{ +use finality_grandpa::{ BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState, voter, voter_set::VoterSet, }; -use primitives::{Blake2Hasher, H256, Pair}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ +use sp_core::Pair; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, NumberFor, One, Zero, }; -use substrate_telemetry::{telemetry, CONSENSUS_INFO}; +use sc_telemetry::{telemetry, CONSENSUS_INFO}; use crate::{ - CommandOrError, Commit, Config, Error, Network, Precommit, Prevote, + CommandOrError, Commit, Config, Error, Precommit, Prevote, PrimaryPropose, SignedMessage, NewAuthoritySet, VoterCommand, }; -use consensus_common::SelectChain; +use sp_consensus::SelectChain; use crate::authorities::{AuthoritySet, SharedAuthoritySet}; +use crate::communication::Network as NetworkT; use crate::consensus_changes::SharedConsensusChanges; use crate::justification::GrandpaJustification; use crate::until_imported::UntilVoteTargetImported; use crate::voting_rule::VotingRule; -use fg_primitives::{AuthorityId, AuthoritySignature, SetId, RoundNumber}; +use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId, RoundNumber}; -type HistoricalVotes = grandpa::HistoricalVotes< +type HistoricalVotes = finality_grandpa::HistoricalVotes< ::Hash, NumberFor, AuthoritySignature, @@ -99,10 +106,10 @@ impl Encode for CompletedRounds { } } -impl codec::EncodeLike for CompletedRounds {} +impl parity_scale_codec::EncodeLike for CompletedRounds {} impl Decode for CompletedRounds { - fn decode(value: &mut I) -> Result { + fn decode(value: &mut I) -> Result { <(Vec>, SetId, Vec)>::decode(value) .map(|(rounds, set_id, voters)| CompletedRounds { rounds: rounds.into(), @@ -370,7 +377,7 @@ impl SharedVoterSetState { } /// The environment we run GRANDPA in. -pub(crate) struct Environment, RA, SC, VR> { +pub(crate) struct Environment, RA, SC, VR> { pub(crate) client: Arc>, pub(crate) select_chain: SC, pub(crate) voters: Arc>, @@ -383,7 +390,7 @@ pub(crate) struct Environment, RA, SC, VR pub(crate) voting_rule: VR, } -impl, RA, SC, VR> Environment { +impl, RA, SC, VR> Environment { /// Updates the voter set state using the given closure. The write lock is /// held during evaluation of the closure and the environment's voter set /// state is set to its result if successful. @@ -399,15 +406,14 @@ impl, RA, SC, VR> Environment, B, E, N, RA, SC, VR> - grandpa::Chain> +impl + finality_grandpa::Chain> for Environment where Block: 'static, - B: Backend + 'static, - E: CallExecutor + Send + Sync + 'static, - N: Network + 'static, - N::In: 'static, + B: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + N: NetworkT + 'static + Send, SC: SelectChain + 'static, VR: VotingRule>, RA: Send + Sync, @@ -426,32 +432,26 @@ where return None; } + let base_header = match self.client.header(&BlockId::Hash(block)).ok()? { + Some(h) => h, + None => { + debug!(target: "afg", "Encountered error finding best chain containing {:?}: couldn't find base block", block); + 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(); + // the limit, if any, is guaranteed to be higher than or equal to the given base number. + let limit = self.authority_set.current_limit(*base_header.number()); debug!(target: "afg", "Finding best chain containing block {:?} with number limit {:?}", block, limit); match self.select_chain.finality_target(block, None) { Ok(Some(best_hash)) => { - let base_header = self.client.header(&BlockId::Hash(block)).ok()? - .expect("Header known to exist after `best_containing` call; qed"); - - if let Some(limit) = limit { - // 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 best_header = self.client.header(&BlockId::Hash(best_hash)).ok()? - .expect("Header known to exist after `best_containing` call; qed"); + .expect("Header known to exist after `finality_target` call; qed"); // check if our vote is currently being limited due to a pending change let limit = limit.filter(|limit| limit < best_header.number()); @@ -475,7 +475,7 @@ where } target_header = self.client.header(&BlockId::Hash(*target_header.parent_hash())).ok()? - .expect("Header known to exist after `best_containing` call; qed"); + .expect("Header known to exist after `finality_target` call; qed"); } target = target_header; @@ -492,8 +492,18 @@ where // note that we pass the original `best_header`, i.e. before the // authority set limit filter, which can be considered a // mandatory/implicit voting rule. + // + // we also make sure that the restricted vote is higher than the + // round base (i.e. last finalized), otherwise the value + // returned by the given voting rule is ignored and the original + // target is used instead. self.voting_rule .restrict_vote(&*self.client, &base_header, &best_header, target_header) + .filter(|(_, restricted_number)| { + // we can only restrict votes within the interval [base, target] + restricted_number >= base_header.number() && + restricted_number < target_header.number() + }) .or(Some((target_header.hash(), *target_header.number()))) }, Ok(None) => { @@ -509,17 +519,17 @@ where } -pub(crate) fn ancestry, E, RA>( +pub(crate) fn ancestry( client: &Client, base: Block::Hash, block: Block::Hash, ) -> Result, GrandpaError> where - B: Backend, - E: CallExecutor, + B: Backend, + E: CallExecutor, { if base == block { return Err(GrandpaError::NotDescendent) } - let tree_route_res = header_metadata::tree_route(client, block, base); + let tree_route_res = sp_blockchain::tree_route(client, block, base); let tree_route = match tree_route_res { Ok(tree_route) => tree_route, @@ -540,19 +550,21 @@ pub(crate) fn ancestry, E, RA>( Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect()) } -impl, N, RA, SC, VR> +impl voter::Environment> for Environment where Block: 'static, - B: Backend + 'static, - E: CallExecutor + 'static + Send + Sync, - N: Network + 'static + Send, - N::In: 'static + Send, + B: Backend + 'static, + E: CallExecutor + 'static + Send + Sync, + N: NetworkT + 'static + Send + Unpin, RA: 'static + Send + Sync, SC: SelectChain + 'static, VR: VotingRule>, NumberFor: BlockNumberOps, + Client: AuxStore, + Block::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, { type Timer = Pin> + Send>>; type Id = AuthorityId; @@ -560,13 +572,10 @@ where // regular round message streams type In = Pin, Self::Signature, Self::Id>, - Self::Error - > + Item = Result<::finality_grandpa::SignedMessage, Self::Signature, Self::Id>, Self::Error> > + Send>>; type Out = Pin>, + ::finality_grandpa::Message>, Error = Self::Error, > + Send>>; @@ -615,8 +624,8 @@ where voter::RoundData { voter_id: local_key.map(|pair| pair.public()), - prevote_timer: Box::pin(prevote_timer.map_err(|e| Error::Timer(e).into())), - precommit_timer: Box::pin(precommit_timer.map_err(|e| Error::Timer(e).into())), + prevote_timer: Box::pin(prevote_timer.map(Ok)), + precommit_timer: Box::pin(precommit_timer.map(Ok)), incoming, outgoing, } @@ -784,7 +793,7 @@ where let mut completed_rounds = completed_rounds.clone(); // TODO: Future integration will store the prevote and precommit index. See #2611. - let votes = historical_votes.seen().clone(); + let votes = historical_votes.seen().to_vec(); completed_rounds.push(CompletedRound { number: round, @@ -811,6 +820,62 @@ where Ok(()) } + fn concluded( + &self, + round: RoundNumber, + state: RoundState>, + _base: (Block::Hash, NumberFor), + historical_votes: &HistoricalVotes, + ) -> Result<(), Self::Error> { + debug!( + target: "afg", "Voter {} concluded 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.update_voter_set_state(|voter_set_state| { + // NOTE: we don't use `with_current_round` here, because a concluded + // round is completed and cannot be current. + let (completed_rounds, current_rounds) = + if let VoterSetState::Live { completed_rounds, current_rounds } = voter_set_state { + (completed_rounds, current_rounds) + } else { + let msg = "Voter acting while in paused state."; + return Err(Error::Safety(msg.to_string())); + }; + + let mut completed_rounds = completed_rounds.clone(); + + if let Some(already_completed) = completed_rounds.rounds + .iter_mut().find(|r| r.number == round) + { + let n_existing_votes = already_completed.votes.len(); + + // the interface of Environment guarantees that the previous `historical_votes` + // from `completable` is a prefix of what is passed to `concluded`. + already_completed.votes.extend( + historical_votes.seen().iter().skip(n_existing_votes).cloned() + ); + already_completed.state = state; + crate::aux_schema::write_concluded_round(&*self.client, &already_completed)?; + } + + let set_state = VoterSetState::::Live { + completed_rounds, + current_rounds: current_rounds.clone(), + }; + + crate::aux_schema::write_voter_set_state(&*self.client, &set_state)?; + + Ok(Some(set_state)) + })?; + + Ok(()) + } + fn finalize_block( &self, hash: Block::Hash, @@ -834,13 +899,13 @@ where //random between 0-1 seconds. let delay: u64 = thread_rng().gen_range(0, 1000); - Box::pin(Delay::new(Duration::from_millis(delay)).map_err(|e| Error::Timer(e).into())) + Box::pin(Delay::new(Duration::from_millis(delay)).map(Ok)) } fn prevote_equivocation( &self, _round: RoundNumber, - equivocation: ::grandpa::Equivocation, Self::Signature> + equivocation: ::finality_grandpa::Equivocation, Self::Signature> ) { warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation); // nothing yet; this could craft misbehavior reports of some kind. @@ -877,7 +942,7 @@ impl From> for JustificationOrCommit< /// 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>( +pub(crate) fn finalize_block( client: &Client, authority_set: &SharedAuthoritySet>, consensus_changes: &SharedConsensusChanges>, @@ -886,8 +951,8 @@ pub(crate) fn finalize_block, E, RA>( number: NumberFor, justification_or_commit: JustificationOrCommit, ) -> Result<(), CommandOrError>> where - B: Backend, - E: CallExecutor + Send + Sync, + B: Backend, + E: CallExecutor + Send + Sync, RA: Send + Sync, { // NOTE: lock must be held through writing to DB to avoid race. this lock @@ -895,7 +960,7 @@ pub(crate) fn finalize_block, E, RA>( // below. let mut authority_set = authority_set.inner().write(); - let status = client.info().chain; + let status = client.chain_info(); if number <= status.finalized_number && client.hash(number)? == Some(hash) { // This can happen after a forced change (triggered by the finality tracker when finality is stalled), since // the voter will be restarted at the median last finalized block, which can be lower than the local best @@ -925,7 +990,7 @@ pub(crate) fn finalize_block, E, RA>( let status = authority_set.apply_standard_changes( hash, number, - &is_descendent_of::<_, _, Block::Hash>(client, None), + &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 @@ -941,8 +1006,8 @@ pub(crate) fn finalize_block, E, RA>( ); 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."); + warn!(target: "afg", "Failed to write updated consensus changes to disk. Bailing."); + warn!(target: "afg", "Node is in a potentially inconsistent state."); return Err(e.into()); } @@ -968,7 +1033,7 @@ pub(crate) fn finalize_block, E, RA>( // finalization to remote nodes if !justification_required { if let Some(justification_period) = justification_period { - let last_finalized_number = client.info().chain.finalized_number; + let last_finalized_number = client.chain_info().finalized_number; justification_required = (!last_finalized_number.is_zero() || number - last_finalized_number == justification_period) && (last_finalized_number / justification_period != number / justification_period); @@ -994,7 +1059,7 @@ pub(crate) fn finalize_block, E, RA>( // 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); + warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e); e })?; telemetry!(CONSENSUS_INFO; "afg.finalized_blocks_up_to"; @@ -1034,8 +1099,8 @@ pub(crate) fn finalize_block, E, RA>( ); 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."); + warn!(target: "afg", "Failed to write updated authority set to disk. Bailing."); + warn!(target: "afg", "Node is in a potentially inconsistent state."); return Err(e.into()); } @@ -1061,8 +1126,8 @@ pub(crate) fn finalize_block, E, RA>( /// Using the given base get the block at the given height on this chain. The /// target block must be an ancestor of base, therefore `height <= base.height`. -pub(crate) fn canonical_at_height, C: HeaderBackend>( - provider: C, +pub(crate) fn canonical_at_height>( + provider: &C, base: (Block::Hash, NumberFor), base_is_canonical: bool, height: NumberFor, diff --git a/core/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs similarity index 77% rename from core/finality-grandpa/src/finality_proof.rs rename to client/finality-grandpa/src/finality_proof.rs index da5732f2f6fc8..fb0f7fd4a9bab 100644 --- a/core/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -34,23 +34,25 @@ //! finality proof (that finalizes some block C that is ancestor of the B and descendant //! of the U) could be returned. +use std::iter; use std::sync::Arc; use log::{trace, warn}; -use client::{ - backend::Backend, blockchain::Backend as BlockchainBackend, CallExecutor, Client, - error::{Error as ClientError, Result as ClientResult}, - light::fetcher::{FetchChecker, RemoteCallRequest}, ExecutionStrategy, +use sp_blockchain::{Backend as BlockchainBackend, Error as ClientError, Result as ClientResult}; +use sc_client_api::{ + backend::Backend, CallExecutor, StorageProof, + light::{FetchChecker, RemoteReadRequest}, }; -use codec::{Encode, Decode}; -use grandpa::BlockNumberOps; -use sr_primitives::{ +use sc_client::Client; +use parity_scale_codec::{Encode, Decode}; +use finality_grandpa::BlockNumberOps; +use sp_runtime::{ Justification, generic::BlockId, traits::{NumberFor, Block as BlockT, Header as HeaderT, One}, }; -use primitives::{H256, Blake2Hasher}; -use substrate_telemetry::{telemetry, CONSENSUS_INFO}; -use fg_primitives::AuthorityId; +use sp_core::storage::StorageKey; +use sc_telemetry::{telemetry, CONSENSUS_INFO}; +use sp_finality_grandpa::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY}; use crate::justification::GrandpaJustification; @@ -59,46 +61,41 @@ const MAX_FRAGMENTS_IN_PROOF: usize = 8; /// GRANDPA authority set related methods for the finality proof provider. pub trait AuthoritySetForFinalityProver: Send + Sync { - /// Call GrandpaApi::grandpa_authorities at given block. - fn authorities(&self, block: &BlockId) -> ClientResult>; - /// Prove call of GrandpaApi::grandpa_authorities at given block. - fn prove_authorities(&self, block: &BlockId) -> ClientResult>>; + /// Read GRANDPA_AUTHORITIES_KEY from storage at given block. + fn authorities(&self, block: &BlockId) -> ClientResult; + /// Prove storage read of GRANDPA_AUTHORITIES_KEY at given block. + fn prove_authorities(&self, block: &BlockId) -> ClientResult; } /// Client-based implementation of AuthoritySetForFinalityProver. -impl, RA> AuthoritySetForFinalityProver for Client +impl AuthoritySetForFinalityProver for Client where - B: Backend + Send + Sync + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, + B: Backend + Send + Sync + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, RA: Send + Sync, { - fn authorities(&self, block: &BlockId) -> ClientResult> { - self.executor().call( - block, - "GrandpaApi_grandpa_authorities", - &[], - ExecutionStrategy::NativeElseWasm, - None, - ).and_then(|call_result| Decode::decode(&mut &call_result[..]) - .map_err(|err| ClientError::CallResultDecode( - "failed to decode GRANDPA authorities set proof".into(), err - ))) - } - - fn prove_authorities(&self, block: &BlockId) -> ClientResult>> { - self.execution_proof(block, "GrandpaApi_grandpa_authorities",&[]).map(|(_, proof)| proof) + fn authorities(&self, block: &BlockId) -> ClientResult { + let storage_key = StorageKey(GRANDPA_AUTHORITIES_KEY.to_vec()); + self.storage(block, &storage_key)? + .and_then(|encoded| VersionedAuthorityList::decode(&mut encoded.0.as_slice()).ok()) + .map(|versioned| versioned.into()) + .ok_or(ClientError::InvalidAuthoritiesSet) + } + + fn prove_authorities(&self, block: &BlockId) -> ClientResult { + self.read_proof(block, iter::once(GRANDPA_AUTHORITIES_KEY)) } } /// GRANDPA authority set related methods for the finality proof checker. pub trait AuthoritySetForFinalityChecker: Send + Sync { - /// Check execution proof of Grandpa::grandpa_authorities at given block. + /// Check storage read proof of GRANDPA_AUTHORITIES_KEY at given block. fn check_authorities_proof( &self, hash: Block::Hash, header: Block::Header, - proof: Vec>, - ) -> ClientResult>; + proof: StorageProof, + ) -> ClientResult; } /// FetchChecker-based implementation of AuthoritySetForFinalityChecker. @@ -107,35 +104,43 @@ impl AuthoritySetForFinalityChecker for Arc>, - ) -> ClientResult> { - let request = RemoteCallRequest { + proof: StorageProof, + ) -> ClientResult { + let storage_key = GRANDPA_AUTHORITIES_KEY.to_vec(); + let request = RemoteReadRequest { block: hash, header, - method: "GrandpaApi_grandpa_authorities".into(), - call_data: vec![], + keys: vec![storage_key.clone()], retry_count: None, }; - self.check_execution_proof(&request, proof) - .and_then(|authorities| { - let authorities: Vec<(AuthorityId, u64)> = Decode::decode(&mut &authorities[..]) - .map_err(|err| ClientError::CallResultDecode( - "failed to decode GRANDPA authorities set proof".into(), err - ))?; - Ok(authorities.into_iter().collect()) + self.check_read_proof(&request, proof) + .and_then(|results| { + let maybe_encoded = results.get(&storage_key) + .expect( + "storage_key is listed in the request keys; \ + check_read_proof must return a value for each requested key; + qed" + ); + maybe_encoded + .as_ref() + .and_then(|encoded| { + VersionedAuthorityList::decode(&mut encoded.as_slice()).ok() + }) + .map(|versioned| versioned.into()) + .ok_or(ClientError::InvalidAuthoritiesSet) }) } } /// Finality proof provider for serving network requests. -pub struct FinalityProofProvider> { +pub struct FinalityProofProvider { backend: Arc, authority_provider: Arc>, } -impl> FinalityProofProvider - where B: Backend + Send + Sync + 'static +impl FinalityProofProvider + where B: Backend + Send + Sync + 'static { /// Create new finality proof provider using: /// @@ -149,11 +154,11 @@ impl> FinalityProofProvider } } -impl network::FinalityProofProvider for FinalityProofProvider +impl sc_network::FinalityProofProvider for FinalityProofProvider where - Block: BlockT, + Block: BlockT, NumberFor: BlockNumberOps, - B: Backend + Send + Sync + 'static, + B: Backend + Send + Sync + 'static, { fn prove_finality( &self, @@ -162,7 +167,7 @@ impl network::FinalityProofProvider for FinalityProofProvider Result>, ClientError> { let request: FinalityProofRequest = Decode::decode(&mut &request[..]) .map_err(|e| { - warn!(target: "finality", "Unable to decode finality proof request: {}", e.what()); + warn!(target: "afg", "Unable to decode finality proof request: {}", e.what()); ClientError::Backend(format!("Invalid finality proof request")) })?; match request { @@ -189,7 +194,7 @@ pub struct FinalityEffects { /// New authorities set id that should be applied starting from block. pub new_set_id: u64, /// New authorities set that should be applied starting from block. - pub new_authorities: Vec<(AuthorityId, u64)>, + pub new_authorities: AuthorityList, } /// Single fragment of proof-of-finality. @@ -206,8 +211,8 @@ struct FinalityProofFragment { pub justification: Vec, /// The set of headers in the range (U; F] that we believe are unknown to the caller. Ordered. pub unknown_headers: Vec

, - /// Optional proof of execution of GRANDPA::authorities(). - pub authorities_proof: Option>>, + /// Optional proof of execution of GRANDPA::authorities() at the `block`. + pub authorities_proof: Option, } /// Proof of finality is the ordered set of finality fragments, where: @@ -247,13 +252,13 @@ pub(crate) fn make_finality_proof_request(last_finalized: H, /// It is assumed that the caller already knows all blocks in the range (begin; end]. /// /// Returns None if there are no finalized blocks unknown to the caller. -pub(crate) fn prove_finality, B: BlockchainBackend, J>( +pub(crate) fn prove_finality, J>( blockchain: &B, authorities_provider: &dyn AuthoritySetForFinalityProver, authorities_set_id: u64, begin: Block::Hash, end: Block::Hash, -) -> ::client::error::Result>> +) -> ::sp_blockchain::Result>> where J: ProvableJustification, { @@ -264,7 +269,7 @@ pub(crate) fn prove_finality, B: BlockchainBackend, B: BlockchainBackend, B: BlockchainBackend, B: BlockchainBackend, B: BlockchainBackend, B: BlockchainBackend, B: BlockchainBackend, B>( +pub(crate) fn check_finality_proof( blockchain: &B, current_set_id: u64, - current_authorities: Vec<(AuthorityId, u64)>, + current_authorities: AuthorityList, authorities_provider: &dyn AuthoritySetForFinalityChecker, remote_proof: Vec, ) -> ClientResult> @@ -424,10 +429,10 @@ pub(crate) fn check_finality_proof, B>( remote_proof) } -fn do_check_finality_proof, B, J>( +fn do_check_finality_proof( blockchain: &B, current_set_id: u64, - current_authorities: Vec<(AuthorityId, u64)>, + current_authorities: AuthorityList, authorities_provider: &dyn AuthoritySetForFinalityChecker, remote_proof: Vec, ) -> ClientResult> @@ -479,7 +484,7 @@ fn do_check_finality_proof, B, J>( } /// Check finality proof for the single block. -fn check_finality_proof_fragment, B, J>( +fn check_finality_proof_fragment( blockchain: &B, authority_set: AuthoritiesOrEffects, authorities_provider: &dyn AuthoritySetForFinalityChecker, @@ -498,13 +503,17 @@ fn check_finality_proof_fragment, B, J>( // and now verify new authorities proof (if provided) if let Some(new_authorities_proof) = proof_fragment.authorities_proof { - // it is safe to query header here, because its non-finality proves that it can't be pruned - let header = blockchain.expect_header(BlockId::Hash(proof_fragment.block))?; - let parent_hash = *header.parent_hash(); - let parent_header = blockchain.expect_header(BlockId::Hash(parent_hash))?; + // the proof is either generated using known header and it is safe to query header + // here, because its non-finality proves that it can't be pruned + // or it is generated using last unknown header (because it is the one who has + // justification => we only generate proofs for headers with justifications) + let header = match proof_fragment.unknown_headers.iter().rev().next().cloned() { + Some(header) => header, + None => blockchain.expect_header(BlockId::Hash(proof_fragment.block))?, + }; current_authorities = authorities_provider.check_authorities_proof( - parent_hash, - parent_header, + proof_fragment.block, + header, new_authorities_proof, )?; @@ -522,12 +531,12 @@ fn check_finality_proof_fragment, B, J>( /// Authorities set from initial authorities set or finality effects. enum AuthoritiesOrEffects { - Authorities(u64, Vec<(AuthorityId, u64)>), + Authorities(u64, AuthorityList), Effects(FinalityEffects
), } impl AuthoritiesOrEffects
{ - pub fn extract_authorities(self) -> (u64, Vec<(AuthorityId, u64)>) { + pub fn extract_authorities(self) -> (u64, AuthorityList) { match self { AuthoritiesOrEffects::Authorities(set_id, authorities) => (set_id, authorities), AuthoritiesOrEffects::Effects(effects) => (effects.new_set_id, effects.new_authorities), @@ -560,7 +569,7 @@ pub(crate) trait ProvableJustification: Encode + Decode { } } -impl> ProvableJustification for GrandpaJustification +impl ProvableJustification for GrandpaJustification where NumberFor: BlockNumberOps, { @@ -571,24 +580,24 @@ impl> ProvableJustification for GrandpaJ #[cfg(test)] pub(crate) mod tests { - use test_client::runtime::{Block, Header, H256}; - use test_client::client::{backend::NewBlockState}; - use test_client::client::in_mem::Blockchain as InMemoryBlockchain; + use substrate_test_runtime_client::runtime::{Block, Header, H256}; + use sc_client_api::NewBlockState; + use substrate_test_runtime_client::sc_client::in_mem::Blockchain as InMemoryBlockchain; use super::*; - use primitives::crypto::Public; + use sp_core::crypto::Public; type FinalityProof = super::FinalityProof
; impl AuthoritySetForFinalityProver for (GetAuthorities, ProveAuthorities) where - GetAuthorities: Send + Sync + Fn(BlockId) -> ClientResult>, - ProveAuthorities: Send + Sync + Fn(BlockId) -> ClientResult>>, + GetAuthorities: Send + Sync + Fn(BlockId) -> ClientResult, + ProveAuthorities: Send + Sync + Fn(BlockId) -> ClientResult, { - fn authorities(&self, block: &BlockId) -> ClientResult> { + fn authorities(&self, block: &BlockId) -> ClientResult { self.0(*block) } - fn prove_authorities(&self, block: &BlockId) -> ClientResult>> { + fn prove_authorities(&self, block: &BlockId) -> ClientResult { self.1(*block) } } @@ -597,28 +606,28 @@ pub(crate) mod tests { impl AuthoritySetForFinalityChecker for ClosureAuthoritySetForFinalityChecker where - Closure: Send + Sync + Fn(H256, Header, Vec>) -> ClientResult>, + Closure: Send + Sync + Fn(H256, Header, StorageProof) -> ClientResult, { fn check_authorities_proof( &self, hash: H256, header: Header, - proof: Vec>, - ) -> ClientResult> { + proof: StorageProof, + ) -> ClientResult { self.0(hash, header, proof) } } #[derive(Debug, PartialEq, Encode, Decode)] - pub struct TestJustification(pub bool, pub Vec); + pub struct TestJustification(pub (u64, AuthorityList), pub Vec); impl ProvableJustification
for TestJustification { - fn verify(&self, _set_id: u64, _authorities: &[(AuthorityId, u64)]) -> ClientResult<()> { - if self.0 { - Ok(()) - } else { - Err(ClientError::BadJustification("test".into())) + fn verify(&self, set_id: u64, authorities: &[(AuthorityId, u64)]) -> ClientResult<()> { + if (self.0).0 != set_id || (self.0).1 != authorities { + return Err(ClientError::BadJustification("test".into())); } + + Ok(()) } } @@ -747,8 +756,9 @@ pub(crate) mod tests { #[test] fn finality_proof_works_without_authorities_change() { let blockchain = test_blockchain(); - let just4 = TestJustification(true, vec![4]).encode(); - let just5 = TestJustification(true, vec![5]).encode(); + let authorities = vec![(AuthorityId::from_slice(&[1u8; 32]), 1u64)]; + let just4 = TestJustification((0, authorities.clone()), vec![4]).encode(); + let just5 = TestJustification((0, authorities.clone()), vec![5]).encode(); blockchain.insert(header(4).hash(), header(4), Some(just4), None, NewBlockState::Final).unwrap(); blockchain.insert(header(5).hash(), header(5), Some(just5.clone()), None, NewBlockState::Final).unwrap(); @@ -757,7 +767,7 @@ pub(crate) mod tests { let proof_of_5: FinalityProof = Decode::decode(&mut &prove_finality::<_, _, TestJustification>( &blockchain, &( - |_| Ok(vec![(AuthorityId::from_slice(&[1u8; 32]), 1u64)]), + |_| Ok(authorities.clone()), |_| unreachable!("should return before calling ProveAuthorities"), ), 0, @@ -801,31 +811,32 @@ pub(crate) mod tests { #[test] fn finality_proof_works_with_authorities_change() { let blockchain = test_blockchain(); - let just4 = TestJustification(true, vec![4]).encode(); - let just5 = TestJustification(true, vec![5]).encode(); - let just7 = TestJustification(true, vec![7]).encode(); + let auth3 = vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)]; + let auth5 = vec![(AuthorityId::from_slice(&[5u8; 32]), 1u64)]; + let auth7 = vec![(AuthorityId::from_slice(&[7u8; 32]), 1u64)]; + let just4 = TestJustification((0, auth3.clone()), vec![4]).encode(); + let just5 = TestJustification((0, auth3.clone()), vec![5]).encode(); + let just7 = TestJustification((1, auth5.clone()), vec![7]).encode(); blockchain.insert(header(4).hash(), header(4), Some(just4), None, NewBlockState::Final).unwrap(); blockchain.insert(header(5).hash(), header(5), Some(just5.clone()), None, NewBlockState::Final).unwrap(); blockchain.insert(header(6).hash(), header(6), None, None, NewBlockState::Final).unwrap(); blockchain.insert(header(7).hash(), header(7), Some(just7.clone()), None, NewBlockState::Final).unwrap(); - // when querying for finality of 6, we assume that the #6 is the last block known to the requester + // when querying for finality of 6, we assume that the #3 is the last block known to the requester // => since we only have justification for #7, we provide #7 let proof_of_6: FinalityProof = Decode::decode(&mut &prove_finality::<_, _, TestJustification>( &blockchain, &( |block_id| match block_id { - BlockId::Hash(h) if h == header(3).hash() => Ok( - vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)] - ), - BlockId::Number(3) => Ok(vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)]), - BlockId::Number(4) => Ok(vec![(AuthorityId::from_slice(&[4u8; 32]), 1u64)]), - BlockId::Number(6) => Ok(vec![(AuthorityId::from_slice(&[6u8; 32]), 1u64)]), + BlockId::Hash(h) if h == header(3).hash() => Ok(auth3.clone()), + BlockId::Number(4) => Ok(auth3.clone()), + BlockId::Number(5) => Ok(auth5.clone()), + BlockId::Number(7) => Ok(auth7.clone()), _ => unreachable!("no other authorities should be fetched: {:?}", block_id), }, |block_id| match block_id { - BlockId::Number(4) => Ok(vec![vec![40]]), - BlockId::Number(6) => Ok(vec![vec![60]]), + BlockId::Number(5) => Ok(StorageProof::new(vec![vec![50]])), + BlockId::Number(7) => Ok(StorageProof::new(vec![vec![70]])), _ => unreachable!("no other authorities should be proved: {:?}", block_id), }, ), @@ -833,7 +844,7 @@ pub(crate) mod tests { header(3).hash(), header(6).hash(), ).unwrap().unwrap()[..]).unwrap(); - // initial authorities set (which start acting from #4) is [3; 32] + // initial authorities set (which start acting from #0) is [3; 32] assert_eq!(proof_of_6, vec![ // new authorities set starts acting from #5 => we do not provide fragment for #4 // first fragment provides justification for #5 && authorities set that starts acting from #5 @@ -841,16 +852,43 @@ pub(crate) mod tests { block: header(5).hash(), justification: just5, unknown_headers: Vec::new(), - authorities_proof: Some(vec![vec![40]]), + authorities_proof: Some(StorageProof::new(vec![vec![50]])), }, // last fragment provides justification for #7 && unknown#7 FinalityProofFragment { block: header(7).hash(), - justification: just7, + justification: just7.clone(), unknown_headers: vec![header(7)], - authorities_proof: Some(vec![vec![60]]), + authorities_proof: Some(StorageProof::new(vec![vec![70]])), }, ]); + + // now let's verify finality proof + let blockchain = test_blockchain(); + blockchain.insert(header(4).hash(), header(4), None, None, NewBlockState::Final).unwrap(); + blockchain.insert(header(5).hash(), header(5), None, None, NewBlockState::Final).unwrap(); + blockchain.insert(header(6).hash(), header(6), None, None, NewBlockState::Final).unwrap(); + let effects = do_check_finality_proof::<_, _, TestJustification>( + &blockchain, + 0, + auth3, + &ClosureAuthoritySetForFinalityChecker( + |hash, _header, proof: StorageProof| match proof.clone().iter_nodes().next().map(|x| x[0]) { + Some(50) => Ok(auth5.clone()), + Some(70) => Ok(auth7.clone()), + _ => unreachable!("no other proofs should be checked: {}", hash), + } + ), + proof_of_6.encode(), + ).unwrap(); + + assert_eq!(effects, FinalityEffects { + headers_to_import: vec![header(7)], + block: header(7).hash(), + justification: TestJustification((1, auth5.clone()), vec![7]).encode(), + new_set_id: 2, + new_authorities: auth7, + }); } #[test] @@ -886,19 +924,20 @@ pub(crate) mod tests { let blockchain = test_blockchain(); // when intermediate (#0) fragment has non-empty unknown headers + let authorities = vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)]; do_check_finality_proof::<_, _, TestJustification>( &blockchain, 1, - vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)], + authorities.clone(), &ClosureAuthoritySetForFinalityChecker(|_, _, _| unreachable!("returns before CheckAuthoritiesProof")), vec![FinalityProofFragment { block: header(4).hash(), - justification: TestJustification(true, vec![7]).encode(), + justification: TestJustification((0, authorities.clone()), vec![7]).encode(), unknown_headers: vec![header(4)], - authorities_proof: Some(vec![vec![42]]), + authorities_proof: Some(StorageProof::new(vec![vec![42]])), }, FinalityProofFragment { block: header(5).hash(), - justification: TestJustification(true, vec![8]).encode(), + justification: TestJustification((0, authorities), vec![8]).encode(), unknown_headers: vec![header(5)], authorities_proof: None, }].encode(), @@ -910,19 +949,20 @@ pub(crate) mod tests { let blockchain = test_blockchain(); // when intermediate (#0) fragment has empty authorities proof + let authorities = vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)]; do_check_finality_proof::<_, _, TestJustification>( &blockchain, 1, - vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)], + authorities.clone(), &ClosureAuthoritySetForFinalityChecker(|_, _, _| unreachable!("returns before CheckAuthoritiesProof")), vec![FinalityProofFragment { block: header(4).hash(), - justification: TestJustification(true, vec![7]).encode(), + justification: TestJustification((0, authorities.clone()), vec![7]).encode(), unknown_headers: Vec::new(), authorities_proof: None, }, FinalityProofFragment { block: header(5).hash(), - justification: TestJustification(true, vec![8]).encode(), + justification: TestJustification((0, authorities), vec![8]).encode(), unknown_headers: vec![header(5)], authorities_proof: None, }].encode(), @@ -933,19 +973,21 @@ pub(crate) mod tests { fn finality_proof_check_works() { let blockchain = test_blockchain(); + let initial_authorities = vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)]; + let next_authorities = vec![(AuthorityId::from_slice(&[4u8; 32]), 1u64)]; let effects = do_check_finality_proof::<_, _, TestJustification>( &blockchain, 1, - vec![(AuthorityId::from_slice(&[3u8; 32]), 1u64)], - &ClosureAuthoritySetForFinalityChecker(|_, _, _| Ok(vec![(AuthorityId::from_slice(&[4u8; 32]), 1u64)])), + initial_authorities.clone(), + &ClosureAuthoritySetForFinalityChecker(|_, _, _| Ok(next_authorities.clone())), vec![FinalityProofFragment { block: header(2).hash(), - justification: TestJustification(true, vec![7]).encode(), + justification: TestJustification((1, initial_authorities.clone()), vec![7]).encode(), unknown_headers: Vec::new(), - authorities_proof: Some(vec![vec![42]]), + authorities_proof: Some(StorageProof::new(vec![vec![42]])), }, FinalityProofFragment { block: header(4).hash(), - justification: TestJustification(true, vec![8]).encode(), + justification: TestJustification((2, next_authorities.clone()), vec![8]).encode(), unknown_headers: vec![header(4)], authorities_proof: None, }].encode(), @@ -953,7 +995,7 @@ pub(crate) mod tests { assert_eq!(effects, FinalityEffects { headers_to_import: vec![header(4)], block: header(4).hash(), - justification: TestJustification(true, vec![8]).encode(), + justification: TestJustification((2, next_authorities.clone()), vec![8]).encode(), new_set_id: 2, new_authorities: vec![(AuthorityId::from_slice(&[4u8; 32]), 1u64)], }); @@ -966,7 +1008,7 @@ pub(crate) mod tests { // => justification verification will fail on light node anyways, so we do not return // finality proof at all let blockchain = test_blockchain(); - let just4 = TestJustification(false, vec![4]).encode(); // false makes verification fail + let just4 = TestJustification((0, vec![(AuthorityId::from_slice(&[42u8; 32]), 1u64)]), vec![4]).encode(); blockchain.insert(header(4).hash(), header(4), Some(just4), None, NewBlockState::Final).unwrap(); let proof_of_4 = prove_finality::<_, _, TestJustification>( diff --git a/core/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs similarity index 85% rename from core/finality-grandpa/src/import.rs rename to client/finality-grandpa/src/import.rs index 57bca084b7d63..64fc62bfe7a8b 100644 --- a/core/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,26 +17,24 @@ use std::{sync::Arc, collections::HashMap}; use log::{debug, trace, info}; -use codec::Encode; +use parity_scale_codec::Encode; use futures::channel::mpsc; use parking_lot::RwLockWriteGuard; -use client::{blockchain, CallExecutor, Client, well_known_cache_keys}; -use client::blockchain::HeaderBackend; -use client::backend::Backend; -use client::utils::is_descendent_of; -use consensus_common::{ +use sp_blockchain::{HeaderBackend, BlockStatus, well_known_cache_keys}; +use sc_client_api::{backend::{TransactionFor, Backend}, CallExecutor, utils::is_descendent_of}; +use sc_client::Client; +use sp_consensus::{ BlockImport, Error as ConsensusError, BlockCheckParams, BlockImportParams, ImportResult, JustificationImport, SelectChain, }; -use fg_primitives::{GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog}; -use sr_primitives::Justification; -use sr_primitives::generic::{BlockId, OpaqueDigestItemId}; -use sr_primitives::traits::{ - Block as BlockT, DigestFor, Header as HeaderT, NumberFor, +use sp_finality_grandpa::{GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog}; +use sp_runtime::Justification; +use sp_runtime::generic::{BlockId, OpaqueDigestItemId}; +use sp_runtime::traits::{ + Block as BlockT, DigestFor, Header as HeaderT, NumberFor, Zero, }; -use primitives::{H256, Blake2Hasher}; use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange}; @@ -53,7 +51,7 @@ use crate::justification::GrandpaJustification; /// /// When using GRANDPA, the block import worker should be using this block import /// object. -pub struct GrandpaBlockImport, RA, SC> { +pub struct GrandpaBlockImport { inner: Arc>, select_chain: SC, authority_set: SharedAuthoritySet>, @@ -61,7 +59,7 @@ pub struct GrandpaBlockImport, RA, SC> { consensus_changes: SharedConsensusChanges>, } -impl, RA, SC: Clone> Clone for +impl Clone for GrandpaBlockImport { fn clone(&self) -> Self { @@ -75,11 +73,11 @@ impl, RA, SC: Clone> Clone for } } -impl, RA, SC> JustificationImport +impl JustificationImport for GrandpaBlockImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, RA: Send + Sync, SC: SelectChain, @@ -88,7 +86,7 @@ impl, RA, SC> JustificationImport fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor)> { let mut out = Vec::new(); - let chain_info = self.inner.info().chain; + let chain_info = self.inner.chain_info(); // request justifications for all pending changes for which change blocks have already been imported let authorities = self.authority_set.inner().read(); @@ -97,10 +95,14 @@ impl, RA, SC> JustificationImport pending_change.effective_number() > chain_info.finalized_number && pending_change.effective_number() <= chain_info.best_number { - let effective_block_hash = self.select_chain.finality_target( - pending_change.canon_hash, - Some(pending_change.effective_number()), - ); + let effective_block_hash = if !pending_change.delay.is_zero() { + self.select_chain.finality_target( + pending_change.canon_hash, + Some(pending_change.effective_number()), + ) + } else { + Ok(Some(pending_change.canon_hash)) + }; if let Ok(Some(hash)) = effective_block_hash { if let Ok(Some(header)) = self.inner.header(&BlockId::Hash(hash)) { @@ -198,12 +200,12 @@ fn find_forced_change(header: &B::Header) header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) } -impl, RA, SC> +impl GrandpaBlockImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, RA: Send + Sync, { @@ -233,9 +235,11 @@ where }) } - fn make_authorities_changes<'a>(&'a self, block: &mut BlockImportParams, hash: Block::Hash) - -> Result, ConsensusError> - { + fn make_authorities_changes<'a>( + &'a self, + block: &mut BlockImportParams>, + 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. @@ -282,7 +286,7 @@ where // returns a function for checking whether a block is a descendent of another // consistent with querying client directly after importing the block. let parent_hash = *block.header.parent_hash(); - let is_descendent_of = is_descendent_of(&*self.inner, Some((&hash, &parent_hash))); + let is_descendent_of = is_descendent_of(&*self.inner, Some((hash, parent_hash))); let mut guard = InnerGuard { guard: Some(self.authority_set.inner().write()), @@ -321,7 +325,7 @@ where // for the canon block the new authority set should start // with. we use the minimum between the median and the local // best finalized block. - let best_finalized_number = self.inner.info().chain.finalized_number; + let best_finalized_number = self.inner.chain_info().finalized_number; let canon_number = best_finalized_number.min(median_last_finalized_number); let canon_hash = self.inner.header(&BlockId::Number(canon_number)) @@ -376,19 +380,22 @@ where } } -impl, RA, SC> BlockImport +impl BlockImport for GrandpaBlockImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, RA: Send + Sync, + for<'a> &'a Client: + BlockImport>, { type Error = ConsensusError; + type Transaction = TransactionFor; fn import_block( &mut self, - mut block: BlockImportParams, + mut block: BlockImportParams, new_cache: HashMap>, ) -> Result { let hash = block.post_header().hash(); @@ -397,8 +404,8 @@ impl, RA, SC> BlockImport // early exit if block already in chain, otherwise the check for // authority changes will error when trying to re-import a change block match self.inner.status(BlockId::Hash(hash)) { - Ok(blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), - Ok(blockchain::BlockStatus::Unknown) => {}, + Ok(BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), + Ok(BlockStatus::Unknown) => {}, Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), } @@ -413,12 +420,20 @@ impl, RA, SC> BlockImport match import_result { Ok(ImportResult::Imported(aux)) => aux, Ok(r) => { - debug!(target: "afg", "Restoring old authority set after block import result: {:?}", 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); + debug!( + target: "afg", + "Restoring old authority set after block import error: {:?}", + e, + ); pending_changes.revert(); return Err(ConsensusError::ClientImport(e.to_string()).into()); }, @@ -469,7 +484,7 @@ impl, RA, SC> BlockImport Some(justification) => { self.import_justification(hash, number, justification, needs_justification).unwrap_or_else(|err| { if needs_justification || enacts_consensus_change { - debug!(target: "finality", "Imported block #{} that enacts authority set change with \ + debug!(target: "afg", "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; @@ -479,7 +494,7 @@ impl, RA, SC> BlockImport None => { if needs_justification { trace!( - target: "finality", + target: "afg", "Imported unjustified block #{} that enacts authority set change, waiting for finality for enactment.", number, ); @@ -506,9 +521,7 @@ impl, RA, SC> BlockImport } } -impl, RA, SC> - GrandpaBlockImport -{ +impl GrandpaBlockImport { pub(crate) fn new( inner: Arc>, select_chain: SC, @@ -526,12 +539,12 @@ impl, RA, SC> } } -impl, RA, SC> +impl GrandpaBlockImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, RA: Send + Sync, { @@ -570,7 +583,7 @@ where match result { Err(CommandOrError::VoterCommand(command)) => { - info!(target: "finality", "Imported justification for block #{} that triggers \ + info!(target: "afg", "Imported justification for block #{} that triggers \ command {}, signaling voter.", number, command); // send the command to the voter diff --git a/core/finality-grandpa/src/justification.rs b/client/finality-grandpa/src/justification.rs similarity index 85% rename from core/finality-grandpa/src/justification.rs rename to client/finality-grandpa/src/justification.rs index f5965df3e1228..308056725f67b 100644 --- a/core/finality-grandpa/src/justification.rs +++ b/client/finality-grandpa/src/justification.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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 @@ use std::collections::{HashMap, HashSet}; -use client::{CallExecutor, Client}; -use client::backend::Backend; -use client::error::Error as ClientError; -use codec::{Encode, Decode}; -use grandpa::voter_set::VoterSet; -use grandpa::{Error as GrandpaError}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{NumberFor, Block as BlockT, Header as HeaderT}; -use primitives::{H256, Blake2Hasher}; -use fg_primitives::AuthorityId; +use sc_client::Client; +use sc_client_api::{CallExecutor, backend::Backend}; +use sp_blockchain::Error as ClientError; +use parity_scale_codec::{Encode, Decode}; +use finality_grandpa::voter_set::VoterSet; +use finality_grandpa::{Error as GrandpaError}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT}; +use sp_finality_grandpa::AuthorityId; use crate::{Commit, Error}; use crate::communication; @@ -45,7 +44,7 @@ pub struct GrandpaJustification { votes_ancestries: Vec, } -impl> GrandpaJustification { +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( @@ -53,8 +52,8 @@ impl> GrandpaJustification { round: u64, commit: Commit, ) -> Result, Error> where - B: Backend, - E: CallExecutor + Send + Sync, + B: Backend, + E: CallExecutor + Send + Sync, RA: Send + Sync, { let mut votes_ancestries_hashes = HashSet::new(); @@ -98,7 +97,7 @@ impl> GrandpaJustification { set_id: u64, voters: &VoterSet, ) -> Result, ClientError> where - NumberFor: grandpa::BlockNumberOps, + NumberFor: finality_grandpa::BlockNumberOps, { let justification = GrandpaJustification::::decode(&mut &*encoded) @@ -115,13 +114,13 @@ impl> GrandpaJustification { /// Validate the commit and the votes' ancestry proofs. pub(crate) fn verify(&self, set_id: u64, voters: &VoterSet) -> Result<(), ClientError> where - NumberFor: grandpa::BlockNumberOps, + NumberFor: finality_grandpa::BlockNumberOps, { - use grandpa::Chain; + use finality_grandpa::Chain; let ancestry_chain = AncestryChain::::new(&self.votes_ancestries); - match grandpa::validate_commit( + match finality_grandpa::validate_commit( &self.commit, voters, &ancestry_chain, @@ -136,7 +135,7 @@ impl> GrandpaJustification { 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()), + &finality_grandpa::Message::Precommit(signed.precommit.clone()), &signed.id, &signed.signature, self.round, @@ -179,7 +178,7 @@ impl> GrandpaJustification { } } -/// A utility trait implementing `grandpa::Chain` using a given set of headers. +/// A utility trait implementing `finality_grandpa::Chain` using a given set of headers. /// This is useful when validating commits, using the given set of headers to /// verify a valid ancestry route to the target commit block. struct AncestryChain { @@ -198,8 +197,8 @@ impl AncestryChain { } } -impl grandpa::Chain> for AncestryChain where - NumberFor: grandpa::BlockNumberOps +impl finality_grandpa::Chain> for AncestryChain where + NumberFor: finality_grandpa::BlockNumberOps { fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { let mut route = Vec::new(); diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs new file mode 100644 index 0000000000000..8a442c6534c43 --- /dev/null +++ b/client/finality-grandpa/src/lib.rs @@ -0,0 +1,962 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! 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 +//! +//! First, create a block-import wrapper with the `block_import` function. The +//! GRANDPA worker needs to be linked together with this block import object, so +//! a `LinkHalf` is returned as well. All blocks imported (from network or +//! consensus or otherwise) must pass through this wrapper, otherwise consensus +//! is likely to break in unexpected ways. +//! +//! Next, use the `LinkHalf` and a local configuration to `run_grandpa_voter`. +//! This requires a `Network` implementation. The returned future should be +//! driven to completion and will finalize blocks in the background. +//! +//! # Changing authority sets +//! +//! The rough idea behind changing authority sets in GRANDPA is that at some point, +//! we obtain agreement for some maximum block height that the current set can +//! finalize, and once a block with that height is finalized the next set will +//! pick up finalization from there. +//! +//! Technically speaking, this would be implemented as a voting rule which says, +//! "if there is a signal for a change in N blocks in block B, only vote on +//! chains with length NUM(B) + N if they contain B". This conditional-inclusion +//! 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 (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 log::{debug, info}; +use futures::channel::mpsc; +use sc_client_api::{BlockchainEvents, CallExecutor, backend::{AuxStore, Backend}, ExecutionStrategy}; +use sp_blockchain::{HeaderBackend, Error as ClientError}; +use sc_client::Client; +use parity_scale_codec::{Decode, Encode}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT, DigestFor, Zero}; +use sc_keystore::KeyStorePtr; +use sp_inherents::InherentDataProviders; +use sp_consensus::SelectChain; +use sp_core::Pair; +use sc_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG}; +use serde_json; + +use sp_finality_tracker; + +use finality_grandpa::Error as GrandpaError; +use finality_grandpa::{voter, BlockNumberOps, voter_set::VoterSet}; + +use std::{fmt, io}; +use std::sync::Arc; +use std::time::Duration; +use std::pin::Pin; +use std::task::{Poll, Context}; + +mod authorities; +mod aux_schema; +mod communication; +mod consensus_changes; +mod environment; +mod finality_proof; +mod import; +mod justification; +mod light_import; +mod observer; +mod until_imported; +mod voting_rule; + +pub use finality_proof::FinalityProofProvider; +pub use justification::GrandpaJustification; +pub use light_import::light_block_import; +pub use observer::run_grandpa_observer; +pub use voting_rule::{ + BeforeBestBlock, ThreeQuartersOfTheUnfinalizedChain, VotingRule, VotingRulesBuilder +}; + +use aux_schema::PersistentData; +use environment::{Environment, VoterSetState}; +use import::GrandpaBlockImport; +use until_imported::UntilGlobalMessageBlocksImported; +use communication::{NetworkBridge, Network as NetworkT}; +use sp_finality_grandpa::{AuthorityList, AuthorityPair, AuthoritySignature, SetId}; + +// Re-export these two because it's just so damn convenient. +pub use sp_finality_grandpa::{AuthorityId, ScheduledChange}; + +#[cfg(test)] +mod tests; + +/// A GRANDPA message for a substrate chain. +pub type Message = finality_grandpa::Message<::Hash, NumberFor>; +/// A signed message. +pub type SignedMessage = finality_grandpa::SignedMessage< + ::Hash, + NumberFor, + AuthoritySignature, + AuthorityId, +>; + +/// A primary propose message for this chain's block type. +pub type PrimaryPropose = finality_grandpa::PrimaryPropose<::Hash, NumberFor>; +/// A prevote message for this chain's block type. +pub type Prevote = finality_grandpa::Prevote<::Hash, NumberFor>; +/// A precommit message for this chain's block type. +pub type Precommit = finality_grandpa::Precommit<::Hash, NumberFor>; +/// A catch up message for this chain's block type. +pub type CatchUp = finality_grandpa::CatchUp< + ::Hash, + NumberFor, + AuthoritySignature, + AuthorityId, +>; +/// A commit message for this chain's block type. +pub type Commit = finality_grandpa::Commit< + ::Hash, + NumberFor, + AuthoritySignature, + AuthorityId, +>; +/// A compact commit message for this chain's block type. +pub type CompactCommit = finality_grandpa::CompactCommit< + ::Hash, + NumberFor, + AuthoritySignature, + AuthorityId, +>; +/// A global communication input stream for commits and catch up messages. Not +/// exposed publicly, used internally to simplify types in the communication +/// layer. +type CommunicationIn = finality_grandpa::voter::CommunicationIn< + ::Hash, + NumberFor, + AuthoritySignature, + AuthorityId, +>; + +/// Global communication input stream for commits and catch up messages, with +/// the hash type not being derived from the block, useful for forcing the hash +/// to some type (e.g. `H256`) when the compiler can't do the inference. +type CommunicationInH = finality_grandpa::voter::CommunicationIn< + H, + NumberFor, + AuthoritySignature, + AuthorityId, +>; + +/// A global communication sink for commits. Not exposed publicly, used +/// internally to simplify types in the communication layer. +type CommunicationOut = finality_grandpa::voter::CommunicationOut< + ::Hash, + NumberFor, + AuthoritySignature, + AuthorityId, +>; + +/// Global communication sink for commits with the hash type not being derived +/// from the block, useful for forcing the hash to some type (e.g. `H256`) when +/// the compiler can't do the inference. +type CommunicationOutH = finality_grandpa::voter::CommunicationOut< + H, + NumberFor, + AuthoritySignature, + AuthorityId, +>; + +/// 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: u32, + /// Whether the GRANDPA observer protocol is live on the network and thereby + /// a full-node not running as a validator is running the GRANDPA observer + /// protocol (we will only issue catch-up requests to authorities when the + /// observer protocol is enabled). + pub observer_enabled: bool, + /// Whether the node is running as an authority (i.e. running the full GRANDPA protocol). + pub is_authority: bool, + /// Some local identifier of the voter. + pub name: Option, + /// The keystore that manages the keys of this node. + pub keystore: Option, +} + +impl Config { + fn name(&self) -> &str { + self.name.as_ref().map(|s| s.as_str()).unwrap_or("") + } +} + +/// Errors that can occur while voting in GRANDPA. +#[derive(Debug)] +pub enum Error { + /// An error within grandpa. + Grandpa(GrandpaError), + /// A network error. + Network(String), + /// A blockchain 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(io::Error), +} + +impl From for Error { + fn from(e: GrandpaError) -> Self { + Error::Grandpa(e) + } +} + +impl From for Error { + fn from(e: ClientError) -> Self { + Error::Client(e) + } +} + +/// Something which can determine if a block is known. +pub(crate) trait BlockStatus { + /// Return `Ok(Some(number))` or `Ok(None)` depending on whether the block + /// is definitely known and has been imported. + /// If an unexpected error occurs, return that. + fn block_number(&self, hash: Block::Hash) -> Result>, Error>; +} + +impl BlockStatus for Arc> where + B: Backend, + E: CallExecutor + Send + Sync, + RA: Send + Sync, + NumberFor: BlockNumberOps, +{ + fn block_number(&self, hash: Block::Hash) -> Result>, Error> { + self.block_number_from_id(&BlockId::Hash(hash)) + .map_err(|e| Error::Blockchain(format!("{:?}", e))) + } +} + +/// Something that one can ask to do a block sync request. +pub(crate) trait BlockSyncRequester { + /// Notifies the sync service to try and sync the given block from the given + /// peers. + /// + /// If the given vector of peers is empty then the underlying implementation + /// should make a best effort to fetch the block from any peers it is + /// connected to (NOTE: this assumption will change in the future #3629). + fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor); +} + +impl BlockSyncRequester for NetworkBridge where + Block: BlockT, + Network: NetworkT, +{ + fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor) { + NetworkBridge::set_sync_fork_request(self, peers, hash, number) + } +} + +/// A new authority set along with the canonical block it changed at. +#[derive(Debug)] +pub(crate) struct NewAuthoritySet { + pub(crate) canon_number: N, + pub(crate) canon_hash: H, + pub(crate) set_id: SetId, + pub(crate) authorities: AuthorityList, +} + +/// Commands issued to the voter. +#[derive(Debug)] +pub(crate) enum VoterCommand { + /// Pause the voter for given reason. + Pause(String), + /// New authorities. + ChangeAuthorities(NewAuthoritySet) +} + +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"), + } + } +} + +/// Signals either an early exit of a voter or an error. +#[derive(Debug)] +pub(crate) enum CommandOrError { + /// An error occurred. + Error(Error), + /// A command to the voter. + VoterCommand(VoterCommand), +} + +impl From for CommandOrError { + fn from(e: Error) -> Self { + CommandOrError::Error(e) + } +} + +impl From for CommandOrError { + fn from(e: ClientError) -> Self { + CommandOrError::Error(Error::Client(e)) + } +} + +impl From for CommandOrError { + fn from(e: finality_grandpa::Error) -> Self { + CommandOrError::Error(Error::from(e)) + } +} + +impl From> for CommandOrError { + fn from(e: VoterCommand) -> Self { + CommandOrError::VoterCommand(e) + } +} + +impl ::std::error::Error for CommandOrError { } + +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), + } + } +} + +pub struct LinkHalf { + client: Arc>, + select_chain: SC, + persistent_data: PersistentData, + voter_commands_rx: mpsc::UnboundedReceiver>>, +} + +/// Provider for the Grandpa authority set configured on the genesis block. +pub trait GenesisAuthoritySetProvider { + /// Get the authority set at the genesis block. + fn get(&self) -> Result; +} + +impl GenesisAuthoritySetProvider for Client + where + B: Backend + Send + Sync + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + RA: Send + Sync, +{ + fn get(&self) -> Result { + // This implementation uses the Grandpa runtime API instead of reading directly from the + // `GRANDPA_AUTHORITIES_KEY` as the data may have been migrated since the genesis block of + // the chain, whereas the runtime API is backwards compatible. + self.executor() + .call( + &BlockId::Number(Zero::zero()), + "GrandpaApi_grandpa_authorities", + &[], + ExecutionStrategy::NativeElseWasm, + None, + ) + .and_then(|call_result| { + Decode::decode(&mut &call_result[..]) + .map_err(|err| ClientError::CallResultDecode( + "failed to decode GRANDPA authorities set proof".into(), err + )) + }) + } +} + +/// Make block importer and link half necessary to tie the background voter +/// to it. +pub fn block_import( + client: Arc>, + genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, + select_chain: SC, +) -> Result<( + GrandpaBlockImport, + LinkHalf + ), ClientError> +where + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + RA: Send + Sync, + SC: SelectChain, + Client: AuxStore, +{ + let chain_info = client.chain_info(); + let genesis_hash = chain_info.genesis_hash; + + let persistent_data = aux_schema::load_persistent( + &*client, + genesis_hash, + >::zero(), + || { + let authorities = genesis_authorities_provider.get()?; + telemetry!(CONSENSUS_DEBUG; "afg.loading_authorities"; + "authorities_len" => ?authorities.len() + ); + Ok(authorities) + } + )?; + + let (voter_commands_tx, voter_commands_rx) = mpsc::unbounded(); + + Ok(( + GrandpaBlockImport::new( + client.clone(), + select_chain.clone(), + persistent_data.authority_set.clone(), + voter_commands_tx, + persistent_data.consensus_changes.clone(), + ), + LinkHalf { + client, + select_chain, + persistent_data, + voter_commands_rx, + }, + )) +} + +fn global_communication( + set_id: SetId, + voters: &Arc>, + client: &Arc>, + network: &NetworkBridge, + keystore: &Option, +) -> ( + impl Stream< + Item = Result, CommandOrError>>, + >, + impl Sink< + CommunicationOutH, + Error = CommandOrError>, + > + Unpin, +) where + B: Backend, + E: CallExecutor + Send + Sync, + N: NetworkT + Unpin, + RA: Send + Sync, + NumberFor: BlockNumberOps, + Block::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, +{ + let is_voter = is_voter(voters, keystore).is_some(); + + // verification stream + let (global_in, global_out) = network.global_communication( + communication::SetId(set_id), + voters.clone(), + is_voter, + ); + + // block commit and catch up messages until relevant blocks are imported. + let global_in = UntilGlobalMessageBlocksImported::new( + client.import_notification_stream(), + network.clone(), + client.clone(), + global_in, + "global", + ); + + let global_in = global_in.map_err(CommandOrError::from); + let global_out = global_out.sink_map_err(CommandOrError::from); + + (global_in, global_out) +} + +/// Register the finality tracker inherent data provider (which is used by +/// GRANDPA), if not registered already. +fn register_finality_tracker_inherent_data_provider( + client: Arc>, + inherent_data_providers: &InherentDataProviders, +) -> Result<(), sp_consensus::Error> where + B: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + RA: Send + Sync + 'static, +{ + if !inherent_data_providers.has_provider(&sp_finality_tracker::INHERENT_IDENTIFIER) { + inherent_data_providers + .register_provider(sp_finality_tracker::InherentDataProvider::new(move || { + #[allow(deprecated)] + { + let info = client.chain_info(); + telemetry!(CONSENSUS_INFO; "afg.finalized"; + "finalized_number" => ?info.finalized_number, + "finalized_hash" => ?info.finalized_hash, + ); + Ok(info.finalized_number) + } + })) + .map_err(|err| sp_consensus::Error::InherentData(err.into())) + } else { + Ok(()) + } +} + +/// Parameters used to run Grandpa. +pub struct GrandpaParams { + /// Configuration for the GRANDPA service. + pub config: Config, + /// A link to the block import worker. + pub link: LinkHalf, + /// The Network instance. + pub network: N, + /// The inherent data providers. + pub inherent_data_providers: InherentDataProviders, + /// Handle to a future that will resolve on exit. + pub on_exit: X, + /// If supplied, can be used to hook on telemetry connection established events. + pub telemetry_on_connect: Option>, + /// A voting rule used to potentially restrict target votes. + pub voting_rule: VR, + /// How to spawn background tasks. + pub executor: Sp, +} + +/// Run a GRANDPA voter as a task. Provide configuration and a link to a +/// block import worker that has already been instantiated with `block_import`. +pub fn run_grandpa_voter( + grandpa_params: GrandpaParams, +) -> sp_blockchain::Result + Unpin + Send + 'static> where + Block::Hash: Ord + Unpin, + B: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + N: NetworkT + Send + Sync + Clone + Unpin + 'static, + SC: SelectChain + 'static, + VR: VotingRule> + Clone + 'static, + NumberFor: BlockNumberOps, + DigestFor: Encode, + RA: Send + Sync + 'static, + X: futures::Future + Clone + Send + Unpin + 'static, + Client: AuxStore, + Sp: futures::task::Spawn + 'static, + <::Header as HeaderT>::Number: Unpin, +{ + let GrandpaParams { + config, + link, + network, + inherent_data_providers, + on_exit, + telemetry_on_connect, + voting_rule, + executor, + } = grandpa_params; + + let LinkHalf { + client, + select_chain, + persistent_data, + voter_commands_rx, + } = link; + + let network = NetworkBridge::new( + network, + config.clone(), + persistent_data.set_state.clone(), + &executor, + on_exit.clone(), + ); + + register_finality_tracker_inherent_data_provider(client.clone(), &inherent_data_providers)?; + + let conf = config.clone(); + let telemetry_task = if let Some(telemetry_on_connect) = telemetry_on_connect { + let authorities = persistent_data.authority_set.clone(); + let events = telemetry_on_connect + .for_each(move |_| { + let curr = authorities.current_authorities(); + let mut auths = curr.voters().into_iter().map(|(p, _)| p); + let maybe_authority_id = authority_id(&mut auths, &conf.keystore) + .unwrap_or(Default::default()); + + telemetry!(CONSENSUS_INFO; "afg.authority_set"; + "authority_id" => maybe_authority_id.to_string(), + "authority_set_id" => ?authorities.set_id(), + "authorities" => { + let authorities: Vec = curr.voters() + .iter().map(|(id, _)| id.to_string()).collect(); + serde_json::to_string(&authorities) + .expect("authorities is always at least an empty vector; elements are always of type string") + } + ); + future::ready(()) + }) + .then(|_| { future::ready(()) }); + future::Either::Left(events) + } else { + future::Either::Right(future::pending()) + }; + + let voter_work = VoterWork::new( + client, + config, + network, + select_chain, + voting_rule, + persistent_data, + voter_commands_rx, + ); + + let voter_work = voter_work + .map(|_| ()); + + // Make sure that `telemetry_task` doesn't accidentally finish and kill grandpa. + let telemetry_task = telemetry_task + .then(|_| future::pending::<()>()); + + Ok(future::select(future::select(voter_work, on_exit), telemetry_task).map(drop)) +} + +/// Future that powers the voter. +#[must_use] +struct VoterWork, RA, SC, VR> { + voter: Pin>>> + Send>>, + env: Arc>, + voter_commands_rx: mpsc::UnboundedReceiver>>, +} + +impl VoterWork +where + Block: BlockT, + N: NetworkT + Sync + Unpin, + NumberFor: BlockNumberOps, + RA: 'static + Send + Sync, + E: CallExecutor + Send + Sync + 'static, + B: Backend + 'static, + SC: SelectChain + 'static, + VR: VotingRule> + Clone + 'static, + Client: AuxStore, + ::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, +{ + fn new( + client: Arc>, + config: Config, + network: NetworkBridge, + select_chain: SC, + voting_rule: VR, + persistent_data: PersistentData, + voter_commands_rx: mpsc::UnboundedReceiver>>, + ) -> Self { + + let voters = persistent_data.authority_set.current_authorities(); + let env = Arc::new(Environment { + client, + select_chain, + voting_rule, + voters: Arc::new(voters), + config, + network, + set_id: persistent_data.authority_set.set_id(), + authority_set: persistent_data.authority_set.clone(), + consensus_changes: persistent_data.consensus_changes.clone(), + voter_set_state: persistent_data.set_state.clone(), + }); + + let mut work = VoterWork { + // `voter` is set to a temporary value and replaced below when + // calling `rebuild_voter`. + voter: Box::pin(future::pending()), + env, + voter_commands_rx, + }; + work.rebuild_voter(); + work + } + + /// Rebuilds the `self.voter` field using the current authority set + /// state. This method should be called when we know that the authority set + /// has changed (e.g. as signalled by a voter command). + fn rebuild_voter(&mut self) { + debug!(target: "afg", "{}: Starting new voter with set ID {}", self.env.config.name(), self.env.set_id); + + let authority_id = is_voter(&self.env.voters, &self.env.config.keystore) + .map(|ap| ap.public()) + .unwrap_or(Default::default()); + + telemetry!(CONSENSUS_DEBUG; "afg.starting_new_voter"; + "name" => ?self.env.config.name(), + "set_id" => ?self.env.set_id, + "authority_id" => authority_id.to_string(), + ); + + let chain_info = self.env.client.chain_info(); + telemetry!(CONSENSUS_INFO; "afg.authority_set"; + "number" => ?chain_info.finalized_number, + "hash" => ?chain_info.finalized_hash, + "authority_id" => authority_id.to_string(), + "authority_set_id" => ?self.env.set_id, + "authorities" => { + let authorities: Vec = self.env.voters.voters() + .iter().map(|(id, _)| id.to_string()).collect(); + serde_json::to_string(&authorities) + .expect("authorities is always at least an empty vector; elements are always of type string") + }, + ); + + match &*self.env.voter_set_state.read() { + VoterSetState::Live { completed_rounds, .. } => { + let last_finalized = ( + chain_info.finalized_hash, + chain_info.finalized_number, + ); + + let global_comms = global_communication( + self.env.set_id, + &self.env.voters, + &self.env.client, + &self.env.network, + &self.env.config.keystore, + ); + + let last_completed_round = completed_rounds.last(); + + let voter = voter::Voter::new( + self.env.clone(), + (*self.env.voters).clone(), + global_comms, + last_completed_round.number, + last_completed_round.votes.clone(), + last_completed_round.base.clone(), + last_finalized, + ); + + self.voter = Box::pin(voter); + }, + VoterSetState::Paused { .. } => + self.voter = Box::pin(future::pending()), + }; + } + + fn handle_voter_command( + &mut self, + command: VoterCommand> + ) -> Result<(), Error> { + match command { + VoterCommand::ChangeAuthorities(new) => { + let voters: Vec = new.authorities.iter().map(move |(a, _)| { + format!("{}", a) + }).collect(); + telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities"; + "number" => ?new.canon_number, + "hash" => ?new.canon_hash, + "voters" => ?voters, + "set_id" => ?new.set_id, + ); + + self.env.update_voter_set_state(|_| { + // start the new authority set using the block where the + // set changed (not where the signal happened!) as the base. + let set_state = VoterSetState::live( + new.set_id, + &*self.env.authority_set.inner().read(), + (new.canon_hash, new.canon_number), + ); + + aux_schema::write_voter_set_state(&*self.env.client, &set_state)?; + Ok(Some(set_state)) + })?; + + self.env = Arc::new(Environment { + voters: Arc::new(new.authorities.into_iter().collect()), + set_id: new.set_id, + voter_set_state: self.env.voter_set_state.clone(), + // Fields below are simply transferred and not updated. + client: self.env.client.clone(), + select_chain: self.env.select_chain.clone(), + config: self.env.config.clone(), + authority_set: self.env.authority_set.clone(), + consensus_changes: self.env.consensus_changes.clone(), + network: self.env.network.clone(), + voting_rule: self.env.voting_rule.clone(), + }); + + self.rebuild_voter(); + Ok(()) + } + VoterCommand::Pause(reason) => { + info!(target: "afg", "Pausing old validator set: {}", reason); + + // not racing because old voter is shut down. + self.env.update_voter_set_state(|voter_set_state| { + let completed_rounds = voter_set_state.completed_rounds(); + let set_state = VoterSetState::Paused { completed_rounds }; + + aux_schema::write_voter_set_state(&*self.env.client, &set_state)?; + Ok(Some(set_state)) + })?; + + self.rebuild_voter(); + Ok(()) + } + } + } +} + +impl Future for VoterWork +where + Block: BlockT, + Block::Hash: Unpin, + N: NetworkT + Sync + Unpin, + NumberFor: BlockNumberOps, + RA: 'static + Send + Sync, + E: CallExecutor + Send + Sync + 'static, + B: Backend + 'static, + SC: SelectChain + 'static, + VR: VotingRule> + Clone + 'static, + Client: AuxStore, + <::Header as HeaderT>::Number: Unpin, +{ + type Output = Result<(), Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + match Future::poll(Pin::new(&mut self.voter), cx) { + Poll::Pending => {} + Poll::Ready(Ok(())) => { + // voters don't conclude naturally + return Poll::Ready(Err(Error::Safety("GRANDPA voter has concluded.".into()))) + } + Poll::Ready(Err(CommandOrError::Error(e))) => { + // return inner observer error + return Poll::Ready(Err(e)) + } + Poll::Ready(Err(CommandOrError::VoterCommand(command))) => { + // some command issued internally + self.handle_voter_command(command)?; + cx.waker().wake_by_ref(); + } + } + + match Stream::poll_next(Pin::new(&mut self.voter_commands_rx), cx) { + Poll::Pending => {} + Poll::Ready(None) => { + // the `voter_commands_rx` stream should never conclude since it's never closed. + return Poll::Ready(Ok(())) + } + Poll::Ready(Some(command)) => { + // some command issued externally + self.handle_voter_command(command)?; + cx.waker().wake_by_ref(); + } + } + + Poll::Pending + } +} + +#[deprecated(since = "1.1.0", note = "Please switch to run_grandpa_voter.")] +pub fn run_grandpa( + grandpa_params: GrandpaParams, +) -> sp_blockchain::Result + Send + 'static> where + Block::Hash: Ord + Unpin, + B: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + N: NetworkT + Send + Sync + Clone + Unpin + 'static, + SC: SelectChain + 'static, + NumberFor: BlockNumberOps, + DigestFor: Encode, + RA: Send + Sync + 'static, + VR: VotingRule> + Clone + 'static, + X: futures::Future + Clone + Send + Unpin + 'static, + Client: AuxStore, + Sp: futures::task::Spawn + 'static, + <::Header as HeaderT>::Number: Unpin, +{ + run_grandpa_voter(grandpa_params) +} + +/// When GRANDPA is not initialized we still need to register the finality +/// tracker inherent provider which might be expected by the runtime for block +/// authoring. Additionally, we register a gossip message validator that +/// discards all GRANDPA messages (otherwise, we end up banning nodes that send +/// us a `Neighbor` message, since there is no registered gossip validator for +/// the engine id defined in the message.) +pub fn setup_disabled_grandpa( + client: Arc>, + inherent_data_providers: &InherentDataProviders, + network: N, +) -> Result<(), sp_consensus::Error> where + B: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + RA: Send + Sync + 'static, + N: NetworkT + Send + Clone + 'static, +{ + register_finality_tracker_inherent_data_provider( + client, + inherent_data_providers, + )?; + + // We register the GRANDPA protocol so that we don't consider it an anomaly + // to receive GRANDPA messages on the network. We don't process the + // messages. + network.register_notifications_protocol(communication::GRANDPA_ENGINE_ID); + + Ok(()) +} + +/// Checks if this node is a voter in the given voter set. +/// +/// Returns the key pair of the node that is being used in the current voter set or `None`. +fn is_voter( + voters: &Arc>, + keystore: &Option, +) -> Option { + match keystore { + Some(keystore) => voters.voters().iter() + .find_map(|(p, _)| keystore.read().key_pair::(&p).ok()), + None => None, + } +} + +/// Returns the authority id of this node, if available. +fn authority_id<'a, I>( + authorities: &mut I, + keystore: &Option, +) -> Option where + I: Iterator, +{ + match keystore { + Some(keystore) => { + authorities + .find_map(|p| { + keystore.read().key_pair::(&p) + .ok() + .map(|ap| ap.public()) + }) + } + None => None, + } +} diff --git a/client/finality-grandpa/src/light_import.rs b/client/finality-grandpa/src/light_import.rs new file mode 100644 index 0000000000000..0da2248778922 --- /dev/null +++ b/client/finality-grandpa/src/light_import.rs @@ -0,0 +1,814 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::collections::HashMap; +use std::sync::Arc; +use log::{info, trace, warn}; +use parking_lot::RwLock; +use sc_client::Client; +use sc_client_api::{CallExecutor, backend::{AuxStore, Backend, Finalizer, TransactionFor}}; +use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys}; +use parity_scale_codec::{Encode, Decode}; +use sp_consensus::{ + import_queue::Verifier, + BlockOrigin, BlockImport, FinalityProofImport, BlockImportParams, ImportResult, ImportedAux, + BlockCheckParams, Error as ConsensusError, +}; +use sc_network::config::{BoxFinalityProofRequestBuilder, FinalityProofRequestBuilder}; +use sp_runtime::Justification; +use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT, DigestFor}; +use sp_finality_grandpa::{self, AuthorityList}; +use sp_runtime::generic::BlockId; + +use crate::GenesisAuthoritySetProvider; +use crate::aux_schema::load_decode; +use crate::consensus_changes::ConsensusChanges; +use crate::environment::canonical_at_height; +use crate::finality_proof::{ + AuthoritySetForFinalityChecker, ProvableJustification, make_finality_proof_request, +}; +use crate::justification::GrandpaJustification; + +/// LightAuthoritySet is saved under this key in aux storage. +const LIGHT_AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; +/// ConsensusChanges is saver under this key in aux storage. +const LIGHT_CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; + +/// Create light block importer. +pub fn light_block_import( + client: Arc>, + backend: Arc, + genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, + authority_set_provider: Arc>, +) -> Result, ClientError> + where + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + RA: Send + Sync, + Client: AuxStore, +{ + let info = client.info(); + let import_data = load_aux_import_data( + info.finalized_hash, + &*client, + genesis_authorities_provider, + )?; + Ok(GrandpaLightBlockImport { + client, + backend, + authority_set_provider, + data: Arc::new(RwLock::new(import_data)), + }) +} + +/// A light block-import handler for GRANDPA. +/// +/// It is responsible for: +/// - checking GRANDPA justifications; +/// - fetching finality proofs for blocks that are enacting consensus changes. +pub struct GrandpaLightBlockImport { + client: Arc>, + backend: Arc, + authority_set_provider: Arc>, + data: Arc>>, +} + +impl Clone for GrandpaLightBlockImport { + fn clone(&self) -> Self { + GrandpaLightBlockImport { + client: self.client.clone(), + backend: self.backend.clone(), + authority_set_provider: self.authority_set_provider.clone(), + data: self.data.clone(), + } + } +} + +/// Mutable data of light block importer. +struct LightImportData { + last_finalized: Block::Hash, + authority_set: LightAuthoritySet, + consensus_changes: ConsensusChanges>, +} + +/// Latest authority set tracker. +#[derive(Debug, Encode, Decode)] +struct LightAuthoritySet { + set_id: u64, + authorities: AuthorityList, +} + +impl GrandpaLightBlockImport { + /// Create finality proof request builder. + pub fn create_finality_proof_request_builder(&self) -> BoxFinalityProofRequestBuilder { + Box::new(GrandpaFinalityProofRequestBuilder(self.data.clone())) as _ + } +} + +impl BlockImport + for GrandpaLightBlockImport where + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + DigestFor: Encode, + RA: Send + Sync, + for<'a> &'a Client: + BlockImport> + + Finalizer + + AuxStore, +{ + type Error = ConsensusError; + type Transaction = TransactionFor; + + fn import_block( + &mut self, + block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { + do_import_block::<_, _, _, GrandpaJustification>( + &*self.client, &mut *self.data.write(), block, new_cache + ) + } + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + self.client.check_block(block) + } +} + +impl FinalityProofImport + for GrandpaLightBlockImport where + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + DigestFor: Encode, + RA: Send + Sync, + for<'a> &'a Client: + BlockImport> + + Finalizer + + AuxStore, +{ + type Error = ConsensusError; + + fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor)> { + let mut out = Vec::new(); + let chain_info = self.client.chain_info(); + + let data = self.data.read(); + for (pending_number, pending_hash) in data.consensus_changes.pending_changes() { + if *pending_number > chain_info.finalized_number + && *pending_number <= chain_info.best_number + { + out.push((pending_hash.clone(), *pending_number)); + } + } + + out + } + + fn import_finality_proof( + &mut self, + hash: Block::Hash, + number: NumberFor, + finality_proof: Vec, + verifier: &mut dyn Verifier, + ) -> Result<(Block::Hash, NumberFor), Self::Error> { + do_import_finality_proof::<_, _, _, GrandpaJustification>( + &*self.client, + self.backend.clone(), + &*self.authority_set_provider, + &mut *self.data.write(), + hash, + number, + finality_proof, + verifier, + ) + } +} + +impl LightAuthoritySet { + /// Get a genesis set with given authorities. + pub fn genesis(initial: AuthorityList) -> Self { + LightAuthoritySet { + set_id: sp_finality_grandpa::SetId::default(), + authorities: initial, + } + } + + /// Get latest set id. + pub fn set_id(&self) -> u64 { + self.set_id + } + + /// Get latest authorities set. + pub fn authorities(&self) -> AuthorityList { + self.authorities.clone() + } + + /// Set new authorities set. + pub fn update(&mut self, set_id: u64, authorities: AuthorityList) { + self.set_id = set_id; + std::mem::replace(&mut self.authorities, authorities); + } +} + +struct GrandpaFinalityProofRequestBuilder(Arc>>); + +impl FinalityProofRequestBuilder for GrandpaFinalityProofRequestBuilder { + fn build_request_data(&mut self, _hash: &B::Hash) -> Vec { + let data = self.0.read(); + make_finality_proof_request( + data.last_finalized, + data.authority_set.set_id(), + ) + } +} + +/// Try to import new block. +fn do_import_block( + mut client: C, + data: &mut LightImportData, + mut block: BlockImportParams>, + new_cache: HashMap>, +) -> Result + where + C: HeaderBackend + + AuxStore + + Finalizer + + BlockImport> + + Clone, + B: Backend + 'static, + NumberFor: finality_grandpa::BlockNumberOps, + DigestFor: Encode, + J: ProvableJustification, +{ + let hash = block.post_header().hash(); + let number = block.header.number().clone(); + + // we don't want to finalize on `inner.import_block` + let justification = block.justification.take(); + let enacts_consensus_change = !new_cache.is_empty(); + let import_result = client.import_block(block, new_cache); + + let mut imported_aux = match import_result { + Ok(ImportResult::Imported(aux)) => aux, + Ok(r) => return Ok(r), + Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), + }; + + match justification { + Some(justification) => { + trace!( + target: "afg", + "Imported block {}{}. Importing justification.", + if enacts_consensus_change { " which enacts consensus changes" } else { "" }, + hash, + ); + + do_import_justification::<_, _, _, J>(client, data, hash, number, justification) + }, + None if enacts_consensus_change => { + trace!( + target: "afg", + "Imported block {} which enacts consensus changes. Requesting finality proof.", + hash, + ); + + // remember that we need finality proof for this block + imported_aux.needs_finality_proof = true; + data.consensus_changes.note_change((number, hash)); + Ok(ImportResult::Imported(imported_aux)) + }, + None => Ok(ImportResult::Imported(imported_aux)), + } +} + +/// Try to import finality proof. +fn do_import_finality_proof( + client: C, + backend: Arc, + authority_set_provider: &dyn AuthoritySetForFinalityChecker, + data: &mut LightImportData, + _hash: Block::Hash, + _number: NumberFor, + finality_proof: Vec, + verifier: &mut dyn Verifier, +) -> Result<(Block::Hash, NumberFor), ConsensusError> + where + C: HeaderBackend + + AuxStore + + Finalizer + + BlockImport> + + Clone, + B: Backend + 'static, + DigestFor: Encode, + NumberFor: finality_grandpa::BlockNumberOps, + J: ProvableJustification, +{ + let authority_set_id = data.authority_set.set_id(); + let authorities = data.authority_set.authorities(); + let finality_effects = crate::finality_proof::check_finality_proof( + backend.blockchain(), + authority_set_id, + authorities, + authority_set_provider, + finality_proof, + ).map_err(|e| ConsensusError::ClientImport(e.to_string()))?; + + // try to import all new headers + let block_origin = BlockOrigin::NetworkBroadcast; + for header_to_import in finality_effects.headers_to_import { + let (block_to_import, new_authorities) = verifier.verify( + block_origin, + header_to_import, + None, + None, + ).map_err(|e| ConsensusError::ClientImport(e))?; + assert!( + block_to_import.justification.is_none(), + "We have passed None as justification to verifier.verify", + ); + + let mut cache = HashMap::new(); + if let Some(authorities) = new_authorities { + cache.insert(well_known_cache_keys::AUTHORITIES, authorities.encode()); + } + do_import_block::<_, _, _, J>( + client.clone(), + data, + block_to_import.convert_transaction(), + cache, + )?; + } + + // try to import latest justification + let finalized_block_hash = finality_effects.block; + let finalized_block_number = backend.blockchain() + .expect_block_number_from_id(&BlockId::Hash(finality_effects.block)) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; + do_finalize_block( + client, + data, + finalized_block_hash, + finalized_block_number, + finality_effects.justification.encode(), + )?; + + // apply new authorities set + data.authority_set.update( + finality_effects.new_set_id, + finality_effects.new_authorities, + ); + + Ok((finalized_block_hash, finalized_block_number)) +} + +/// Try to import justification. +fn do_import_justification( + client: C, + data: &mut LightImportData, + hash: Block::Hash, + number: NumberFor, + justification: Justification, +) -> Result + where + C: HeaderBackend + + AuxStore + + Finalizer + + Clone, + B: Backend + 'static, + NumberFor: finality_grandpa::BlockNumberOps, + J: ProvableJustification, +{ + // with justification, we have two cases + // + // optimistic: the same GRANDPA authorities set has generated intermediate justification + // => justification is verified using current authorities set + we could proceed further + // + // pessimistic scenario: the GRANDPA authorities set has changed + // => we need to fetch new authorities set (i.e. finality proof) from remote node + + // first, try to behave optimistically + let authority_set_id = data.authority_set.set_id(); + let justification = J::decode_and_verify( + &justification, + authority_set_id, + &data.authority_set.authorities(), + ); + + // BadJustification error means that justification has been successfully decoded, but + // it isn't valid within current authority set + let justification = match justification { + Err(ClientError::BadJustification(_)) => { + trace!( + target: "afg", + "Justification for {} is not valid within current authorities set. Requesting finality proof.", + hash, + ); + + let mut imported_aux = ImportedAux::default(); + imported_aux.needs_finality_proof = true; + return Ok(ImportResult::Imported(imported_aux)); + }, + Err(e) => { + trace!( + target: "afg", + "Justification for {} is not valid. Bailing.", + hash, + ); + + return Err(ConsensusError::ClientImport(e.to_string()).into()); + }, + Ok(justification) => { + trace!( + target: "afg", + "Justification for {} is valid. Finalizing the block.", + hash, + ); + + justification + }, + }; + + // finalize the block + do_finalize_block(client, data, hash, number, justification.encode()) +} + +/// Finalize the block. +fn do_finalize_block( + client: C, + data: &mut LightImportData, + hash: Block::Hash, + number: NumberFor, + justification: Justification, +) -> Result + where + C: HeaderBackend + + AuxStore + + Finalizer + + Clone, + B: Backend + 'static, + NumberFor: finality_grandpa::BlockNumberOps, +{ + // finalize the block + client.finalize_block(BlockId::Hash(hash), Some(justification), true).map_err(|e| { + warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e); + ConsensusError::ClientImport(e.to_string()) + })?; + + // forget obsoleted consensus changes + let consensus_finalization_res = data.consensus_changes + .finalize( + (number, hash), + |at_height| canonical_at_height(&client, (hash, number), true, at_height) + ); + match consensus_finalization_res { + Ok((true, _)) => require_insert_aux( + &client, + LIGHT_CONSENSUS_CHANGES_KEY, + &data.consensus_changes, + "consensus changes", + )?, + Ok(_) => (), + Err(error) => return Err(on_post_finalization_error(error, "consensus changes")), + } + + // update last finalized block reference + data.last_finalized = hash; + + // we just finalized this block, so if we were importing it, it is now the new best + Ok(ImportResult::imported(true)) +} + +/// Load light import aux data from the store. +fn load_aux_import_data( + last_finalized: Block::Hash, + aux_store: &B, + genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, +) -> Result, ClientError> + where + B: AuxStore, + Block: BlockT, +{ + let authority_set = match load_decode(aux_store, LIGHT_AUTHORITY_SET_KEY)? { + Some(authority_set) => authority_set, + 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 + let genesis_authorities = genesis_authorities_provider.get()?; + + let authority_set = LightAuthoritySet::genesis(genesis_authorities); + let encoded = authority_set.encode(); + aux_store.insert_aux(&[(LIGHT_AUTHORITY_SET_KEY, &encoded[..])], &[])?; + + authority_set + }, + }; + + let consensus_changes = match load_decode(aux_store, LIGHT_CONSENSUS_CHANGES_KEY)? { + Some(consensus_changes) => consensus_changes, + None => { + let consensus_changes = ConsensusChanges::>::empty(); + + let encoded = authority_set.encode(); + aux_store.insert_aux(&[(LIGHT_CONSENSUS_CHANGES_KEY, &encoded[..])], &[])?; + + consensus_changes + }, + }; + + Ok(LightImportData { + last_finalized, + authority_set, + consensus_changes, + }) +} + +/// Insert into aux store. If failed, return error && show inconsistency warning. +fn require_insert_aux( + store: &A, + key: &[u8], + value: &T, + value_type: &str, +) -> Result<(), ConsensusError> { + let encoded = value.encode(); + let update_res = store.insert_aux(&[(key, &encoded[..])], &[]); + if let Err(error) = update_res { + return Err(on_post_finalization_error(error, value_type)); + } + + Ok(()) +} + +/// Display inconsistency warning. +fn on_post_finalization_error(error: ClientError, value_type: &str) -> ConsensusError { + warn!(target: "afg", "Failed to write updated {} to disk. Bailing.", value_type); + warn!(target: "afg", "Node is in a potentially inconsistent state."); + ConsensusError::ClientImport(error.to_string()) +} + +#[cfg(test)] +pub mod tests { + use super::*; + use sp_consensus::ForkChoiceStrategy; + use sp_finality_grandpa::AuthorityId; + use sp_core::{H256, crypto::Public}; + use substrate_test_runtime_client::sc_client::in_mem::Blockchain as InMemoryAuxStore; + use substrate_test_runtime_client::runtime::{Block, Header}; + use crate::tests::TestApi; + use crate::finality_proof::tests::TestJustification; + + pub struct NoJustificationsImport( + pub GrandpaLightBlockImport + ); + + impl Clone + for NoJustificationsImport where + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + DigestFor: Encode, + RA: Send + Sync, + { + fn clone(&self) -> Self { + NoJustificationsImport(self.0.clone()) + } + } + + impl BlockImport + for NoJustificationsImport where + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + DigestFor: Encode, + RA: Send + Sync, + for<'a> &'a Client: + BlockImport> + + Finalizer + + AuxStore, + { + type Error = ConsensusError; + type Transaction = TransactionFor; + + fn import_block( + &mut self, + mut block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { + block.justification.take(); + self.0.import_block(block, new_cache) + } + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + self.0.check_block(block) + } + } + + impl FinalityProofImport + for NoJustificationsImport where + NumberFor: finality_grandpa::BlockNumberOps, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + DigestFor: Encode, + RA: Send + Sync, + for<'a> &'a Client: + BlockImport> + + Finalizer + + AuxStore, + { + type Error = ConsensusError; + + fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor)> { + self.0.on_start() + } + + fn import_finality_proof( + &mut self, + hash: Block::Hash, + number: NumberFor, + finality_proof: Vec, + verifier: &mut dyn Verifier, + ) -> Result<(Block::Hash, NumberFor), Self::Error> { + self.0.import_finality_proof(hash, number, finality_proof, verifier) + } + } + + /// Creates light block import that ignores justifications that came outside of finality proofs. + pub fn light_block_import_without_justifications( + client: Arc>, + backend: Arc, + genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, + authority_set_provider: Arc>, + ) -> Result, ClientError> + where + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + RA: Send + Sync, + Client: BlockImport + + Finalizer + + AuxStore, + { + light_block_import(client, backend, genesis_authorities_provider, authority_set_provider) + .map(NoJustificationsImport) + } + + fn import_block( + new_cache: HashMap>, + justification: Option, + ) -> ImportResult { + let (client, _backend) = substrate_test_runtime_client::new_light(); + let mut import_data = LightImportData { + last_finalized: Default::default(), + authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 1)]), + consensus_changes: ConsensusChanges::empty(), + }; + let block = BlockImportParams { + origin: BlockOrigin::Own, + header: Header { + number: 1, + parent_hash: client.chain_info().best_hash, + state_root: Default::default(), + digest: Default::default(), + extrinsics_root: Default::default(), + }, + justification, + post_digests: Vec::new(), + body: None, + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: true, + import_existing: false, + }; + do_import_block::<_, _, _, TestJustification>( + &client, + &mut import_data, + block, + new_cache, + ).unwrap() + } + + #[test] + fn finality_proof_not_required_when_consensus_data_does_not_changes_and_no_justification_provided() { + assert_eq!(import_block(HashMap::new(), None), ImportResult::Imported(ImportedAux { + clear_justification_requests: false, + needs_justification: false, + bad_justification: false, + needs_finality_proof: false, + is_new_best: true, + header_only: false, + })); + } + + #[test] + fn finality_proof_not_required_when_consensus_data_does_not_changes_and_correct_justification_provided() { + let justification = TestJustification((0, vec![(AuthorityId::from_slice(&[1; 32]), 1)]), Vec::new()).encode(); + assert_eq!(import_block(HashMap::new(), Some(justification)), ImportResult::Imported(ImportedAux { + clear_justification_requests: false, + needs_justification: false, + bad_justification: false, + needs_finality_proof: false, + is_new_best: true, + header_only: false, + })); + } + + #[test] + fn finality_proof_required_when_consensus_data_changes_and_no_justification_provided() { + let mut cache = HashMap::new(); + cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode()); + assert_eq!(import_block(cache, None), ImportResult::Imported(ImportedAux { + clear_justification_requests: false, + needs_justification: false, + bad_justification: false, + needs_finality_proof: true, + is_new_best: true, + header_only: false, + })); + } + + #[test] + fn finality_proof_required_when_consensus_data_changes_and_incorrect_justification_provided() { + let justification = TestJustification((0, vec![]), Vec::new()).encode(); + let mut cache = HashMap::new(); + cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode()); + assert_eq!( + import_block(cache, Some(justification)), + ImportResult::Imported(ImportedAux { + clear_justification_requests: false, + needs_justification: false, + bad_justification: false, + needs_finality_proof: true, + is_new_best: false, + header_only: false, + }, + )); + } + + + #[test] + fn aux_data_updated_on_start() { + let aux_store = InMemoryAuxStore::::new(); + let api = TestApi::new(vec![(AuthorityId::from_slice(&[1; 32]), 1)]); + + // when aux store is empty initially + assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_none()); + assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_none()); + + // it is updated on importer start + load_aux_import_data(Default::default(), &aux_store, &api).unwrap(); + assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_some()); + assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_some()); + } + + #[test] + fn aux_data_loaded_on_restart() { + let aux_store = InMemoryAuxStore::::new(); + let api = TestApi::new(vec![(AuthorityId::from_slice(&[1; 32]), 1)]); + + // when aux store is non-empty initially + let mut consensus_changes = ConsensusChanges::::empty(); + consensus_changes.note_change((42, Default::default())); + aux_store.insert_aux( + &[ + ( + LIGHT_AUTHORITY_SET_KEY, + LightAuthoritySet::genesis( + vec![(AuthorityId::from_slice(&[42; 32]), 2)] + ).encode().as_slice(), + ), + ( + LIGHT_CONSENSUS_CHANGES_KEY, + consensus_changes.encode().as_slice(), + ), + ], + &[], + ).unwrap(); + + // importer uses it on start + let data = load_aux_import_data(Default::default(), &aux_store, &api).unwrap(); + assert_eq!(data.authority_set.authorities(), vec![(AuthorityId::from_slice(&[42; 32]), 2)]); + assert_eq!(data.consensus_changes.pending_changes(), &[(42, Default::default())]); + } +} diff --git a/core/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs similarity index 77% rename from core/finality-grandpa/src/observer.rs rename to client/finality-grandpa/src/observer.rs index 450f4a4ca5d7f..d6f50a8f201e5 100644 --- a/core/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,33 +18,33 @@ use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll}; -use futures::{prelude::*, channel::mpsc, compat::Compat01As03}; +use futures::{prelude::*, channel::mpsc}; -use grandpa::{ +use finality_grandpa::{ BlockNumberOps, Error as GrandpaError, voter, voter_set::VoterSet }; use log::{debug, info, warn}; -use consensus_common::SelectChain; -use client::{CallExecutor, Client, backend::Backend}; -use sr_primitives::traits::{NumberFor, Block as BlockT}; -use primitives::{H256, Blake2Hasher}; +use sp_consensus::SelectChain; +use sc_client_api::{CallExecutor, backend::{Backend, AuxStore}}; +use sc_client::Client; +use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT}; use crate::{ global_communication, CommandOrError, CommunicationIn, Config, environment, - LinkHalf, Network, Error, aux_schema::PersistentData, VoterCommand, VoterSetState, + LinkHalf, Error, aux_schema::PersistentData, VoterCommand, VoterSetState, }; use crate::authorities::SharedAuthoritySet; -use crate::communication::NetworkBridge; +use crate::communication::{Network as NetworkT, NetworkBridge}; use crate::consensus_changes::SharedConsensusChanges; -use fg_primitives::AuthorityId; +use sp_finality_grandpa::AuthorityId; struct ObserverChain<'a, Block: BlockT, B, E, RA>(&'a Client); -impl<'a, Block: BlockT, B, E, RA> grandpa::Chain> +impl<'a, Block: BlockT, B, E, RA> finality_grandpa::Chain> for ObserverChain<'a, Block, B, E, RA> where - B: Backend, - E: CallExecutor, + B: Backend, + E: CallExecutor, NumberFor: BlockNumberOps, { fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { @@ -57,7 +57,7 @@ impl<'a, Block: BlockT, B, E, RA> grandpa::Chain, RA, S, F>( +fn grandpa_observer( client: &Arc>, authority_set: &SharedAuthoritySet>, consensus_changes: &SharedConsensusChanges>, @@ -65,10 +65,10 @@ fn grandpa_observer, RA, S, F>( last_finalized_number: NumberFor, commits: S, note_round: F, -) -> impl Future>>> where +) -> impl Future>>> where NumberFor: BlockNumberOps, - B: Backend, - E: CallExecutor + Send + Sync, + B: Backend, + E: CallExecutor + Send + Sync, RA: Send + Sync, S: Stream< Item = Result, CommandOrError>>, @@ -83,7 +83,7 @@ fn grandpa_observer, RA, S, F>( let observer = commits.try_fold(last_finalized_number, move |last_finalized_number, global| { let (round, commit, callback) = match global { voter::CommunicationIn::Commit(round, commit, callback) => { - let commit = grandpa::Commit::from(commit); + let commit = finality_grandpa::Commit::from(commit); (round, commit, callback) }, voter::CommunicationIn::CatchUp(..) => { @@ -98,7 +98,7 @@ fn grandpa_observer, RA, S, F>( return future::ok(last_finalized_number); } - let validation_result = match grandpa::validate_commit( + let validation_result = match finality_grandpa::validate_commit( &commit, &voters, &ObserverChain(&*client), @@ -129,14 +129,14 @@ fn grandpa_observer, RA, S, F>( // and that implies that the next round has started. note_round(round + 1); - grandpa::process_commit_validation_result(validation_result, callback); + finality_grandpa::process_commit_validation_result(validation_result, callback); // proceed processing with new finalized block number future::ok(finalized_number) } else { debug!(target: "afg", "Received invalid commit: ({:?}, {:?})", round, commit); - grandpa::process_commit_validation_result(validation_result, callback); + finality_grandpa::process_commit_validation_result(validation_result, callback); // commit is invalid, continue processing commits with the current state future::ok(last_finalized_number) @@ -150,19 +150,23 @@ fn grandpa_observer, RA, S, F>( /// listening for and validating GRANDPA commits instead of following the full /// protocol. Provide configuration and a link to a block import worker that has /// already been instantiated with `block_import`. -pub fn run_grandpa_observer, N, RA, SC>( +pub fn run_grandpa_observer( config: Config, link: LinkHalf, network: N, - on_exit: impl futures01::Future + Clone + Unpin + Send + 'static, -) -> ::client::error::Result + Unpin + Send + 'static> where - B: Backend + 'static, - E: CallExecutor + Send + Sync + 'static, - N: Network + Send + Sync + 'static, - N::In: Send + 'static, + on_exit: impl futures::Future + Clone + Send + Unpin + 'static, + executor: Sp, +) -> sp_blockchain::Result + Unpin + Send + 'static> where + B: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + N: NetworkT + Send + Clone + Unpin + 'static, SC: SelectChain + 'static, NumberFor: BlockNumberOps, RA: Send + Sync + 'static, + Sp: futures::task::Spawn + 'static, + Client: AuxStore, + ::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, { let LinkHalf { client, @@ -171,12 +175,12 @@ pub fn run_grandpa_observer, N, RA, SC>( voter_commands_rx, } = link; - let (network, network_startup) = NetworkBridge::new( + let network = NetworkBridge::new( network, config.clone(), persistent_data.set_state.clone(), + &executor, on_exit.clone(), - false, ); let observer_work = ObserverWork::new( @@ -193,37 +197,37 @@ pub fn run_grandpa_observer, N, RA, SC>( warn!("GRANDPA Observer failed: {:?}", e); }); - let observer_work = network_startup.then(move |()| future::ready(observer_work)); - - Ok(future::select(observer_work, Compat01As03::new(on_exit)).map(|_| ())) + Ok(future::select(observer_work, on_exit).map(drop)) } /// Future that powers the observer. #[must_use] -struct ObserverWork, N: Network, E, Backend, RA> { +struct ObserverWork, E, Backend, RA> { observer: Pin>>> + Send>>, client: Arc>, network: NetworkBridge, persistent_data: PersistentData, - keystore: Option, + keystore: Option, voter_commands_rx: mpsc::UnboundedReceiver>>, } impl ObserverWork where - B: BlockT, - N: Network, - N::In: Send + 'static, + B: BlockT, + N: NetworkT + Unpin, NumberFor: BlockNumberOps, RA: 'static + Send + Sync, - E: CallExecutor + Send + Sync + 'static, - Bk: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + Bk: Backend + 'static, + Client: AuxStore, + B::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, { fn new( client: Arc>, network: NetworkBridge, persistent_data: PersistentData, - keystore: Option, + keystore: Option, voter_commands_rx: mpsc::UnboundedReceiver>>, ) -> Self { @@ -257,7 +261,7 @@ where &self.keystore, ); - let last_finalized_number = self.client.info().chain.finalized_number; + let last_finalized_number = self.client.chain_info().finalized_number; // NOTE: since we are not using `round_communication` we have to // manually note the round with the gossip validator, otherwise we won't @@ -327,18 +331,22 @@ where impl Future for ObserverWork where - B: BlockT, - N: Network, - N::In: Send + 'static, + B: BlockT, + N: NetworkT + Unpin, NumberFor: BlockNumberOps, RA: 'static + Send + Sync, - E: CallExecutor + Send + Sync + 'static, - Bk: Backend + 'static, + E: CallExecutor + Send + Sync + 'static, + Bk: Backend + 'static, + Client: AuxStore, + B::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, { type Output = Result<(), Error>; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - match Future::poll(Pin::new(&mut self.observer), cx) { + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let this = Pin::into_inner(self); + + match Future::poll(Pin::new(&mut this.observer), cx) { Poll::Pending => {} Poll::Ready(Ok(())) => { // observer commit stream doesn't conclude naturally; this could reasonably be an error. @@ -350,12 +358,12 @@ where } Poll::Ready(Err(CommandOrError::VoterCommand(command))) => { // some command issued internally - self.handle_voter_command(command)?; + this.handle_voter_command(command)?; cx.waker().wake_by_ref(); } } - match Stream::poll_next(Pin::new(&mut self.voter_commands_rx), cx) { + match Stream::poll_next(Pin::new(&mut this.voter_commands_rx), cx) { Poll::Pending => {} Poll::Ready(None) => { // the `voter_commands_rx` stream should never conclude since it's never closed. @@ -363,7 +371,7 @@ where } Poll::Ready(Some(command)) => { // some command issued externally - self.handle_voter_command(command)?; + this.handle_voter_command(command)?; cx.waker().wake_by_ref(); } } @@ -371,7 +379,3 @@ where Poll::Pending } } - -impl, N: Network, E, Backend, RA> Unpin for -ObserverWork { -} diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs new file mode 100644 index 0000000000000..13cd78d553134 --- /dev/null +++ b/client/finality-grandpa/src/tests.rs @@ -0,0 +1,1857 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests and test helpers for GRANDPA. + +use super::*; +use environment::HasVoted; +use sc_network_test::{ + Block, DummySpecialization, Hash, TestNetFactory, BlockImportAdapter, Peer, + PeersClient, PassThroughVerifier, +}; +use sc_network::config::{ProtocolConfig, Roles, BoxFinalityProofRequestBuilder}; +use parking_lot::Mutex; +use futures_timer::Delay; +use tokio::runtime::current_thread; +use sp_keyring::Ed25519Keyring; +use sc_client::LongestChain; +use sc_client_api::backend::TransactionFor; +use sp_blockchain::Result; +use sp_api::{ApiRef, ApiErrorExt, Core, RuntimeVersion, ApiExt, StorageProof, ProvideRuntimeApi}; +use substrate_test_runtime_client::runtime::BlockNumber; +use sp_consensus::{ + BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult, BlockImport, + import_queue::{BoxJustificationImport, BoxFinalityProofImport}, +}; +use std::collections::{HashMap, HashSet}; +use std::result; +use parity_scale_codec::Decode; +use sp_runtime::traits::{Header as HeaderT, HasherFor}; +use sp_runtime::generic::{BlockId, DigestItem}; +use sp_core::{H256, NativeOrEncoded, ExecutionContext, crypto::Public}; +use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, GrandpaApi}; +use sp_state_machine::{InMemoryBackend, prove_read, read_proof_check}; +use std::{pin::Pin, task}; +use futures01::Async; +use futures::compat::Future01CompatExt; + +use authorities::AuthoritySet; +use finality_proof::{ + FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker, +}; +use consensus_changes::ConsensusChanges; + +type PeerData = + Mutex< + Option< + LinkHalf< + substrate_test_runtime_client::Backend, + substrate_test_runtime_client::Executor, + Block, + substrate_test_runtime_client::runtime::RuntimeApi, + LongestChain + > + > + >; +type GrandpaPeer = Peer; + +struct GrandpaTestNet { + peers: Vec, + test_config: TestApi, +} + +impl GrandpaTestNet { + fn new(test_config: TestApi, n_peers: usize) -> Self { + let mut net = GrandpaTestNet { + peers: Vec::with_capacity(n_peers), + test_config, + }; + let config = Self::default_config(); + for _ in 0..n_peers { + net.add_full_peer(&config); + } + net + } +} + +impl TestNetFactory for GrandpaTestNet { + type Specialization = DummySpecialization; + type Verifier = PassThroughVerifier; + type PeerData = PeerData; + + /// Create new test network with peers and given config. + fn from_config(_config: &ProtocolConfig) -> Self { + GrandpaTestNet { + peers: Vec::new(), + test_config: Default::default(), + } + } + + fn default_config() -> ProtocolConfig { + // the authority role ensures gossip hits all nodes here. + let mut config = ProtocolConfig::default(); + config.roles = Roles::AUTHORITY; + config + } + + fn make_verifier( + &self, + _client: PeersClient, + _cfg: &ProtocolConfig, + _: &PeerData, + ) -> Self::Verifier { + PassThroughVerifier(false) // use non-instant finality. + } + + fn make_block_import(&self, client: PeersClient) + -> ( + BlockImportAdapter, + Option>, + Option>, + Option>, + PeerData, + ) + { + match client { + PeersClient::Full(ref client, ref backend) => { + let (import, link) = block_import( + client.clone(), + &self.test_config, + LongestChain::new(backend.clone()), + ).expect("Could not create block import for fresh peer."); + let justification_import = Box::new(import.clone()); + ( + BlockImportAdapter::new_full(import), + Some(justification_import), + None, + None, + Mutex::new(Some(link)), + ) + }, + PeersClient::Light(ref client, ref backend) => { + use crate::light_import::tests::light_block_import_without_justifications; + + let authorities_provider = Arc::new(self.test_config.clone()); + // forbid direct finalization using justification that cames with the block + // => light clients will try to fetch finality proofs + let import = light_block_import_without_justifications( + client.clone(), + backend.clone(), + &self.test_config, + authorities_provider, + ).expect("Could not create block import for fresh peer."); + let finality_proof_req_builder = import.0.create_finality_proof_request_builder(); + let proof_import = Box::new(import.clone()); + ( + BlockImportAdapter::new_light(import), + None, + Some(proof_import), + Some(finality_proof_req_builder), + Mutex::new(None), + ) + }, + } + } + + fn make_finality_proof_provider( + &self, + client: PeersClient + ) -> Option>> { + match client { + PeersClient::Full(_, ref backend) => { + let authorities_provider = Arc::new(self.test_config.clone()); + Some(Arc::new(FinalityProofProvider::new(backend.clone(), authorities_provider))) + }, + PeersClient::Light(_, _) => None, + } + } + + fn peer(&mut self, i: usize) -> &mut GrandpaPeer { + &mut self.peers[i] + } + + fn peers(&self) -> &Vec { + &self.peers + } + + fn mut_peers)>(&mut self, closure: F) { + closure(&mut self.peers); + } +} + +#[derive(Clone)] +struct Exit; + +impl futures::Future for Exit { + type Output = (); + + fn poll(self: Pin<&mut Self>, _: &mut task::Context) -> task::Poll<()> { + task::Poll::Pending + } +} + +#[derive(Default, Clone)] +pub(crate) struct TestApi { + genesis_authorities: AuthorityList, +} + +impl TestApi { + pub fn new(genesis_authorities: AuthorityList) -> Self { + TestApi { + genesis_authorities, + } + } +} + +pub(crate) struct RuntimeApi { + inner: TestApi, +} + +impl ProvideRuntimeApi for TestApi { + type Api = RuntimeApi; + + fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { + RuntimeApi { inner: self.clone() }.into() + } +} + +impl Core for RuntimeApi { + fn Core_version_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> Result> { + unimplemented!("Not required for testing!") + } + + fn Core_execute_block_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option, + _: Vec, + ) -> Result> { + unimplemented!("Not required for testing!") + } + + fn Core_initialize_block_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<&::Header>, + _: Vec, + ) -> Result> { + unimplemented!("Not required for testing!") + } +} + +impl ApiErrorExt for RuntimeApi { + type Error = sp_blockchain::Error; +} + +impl ApiExt for RuntimeApi { + type StateBackend = < + substrate_test_runtime_client::Backend as sc_client_api::backend::Backend + >::State; + + fn map_api_result result::Result, R, E>( + &self, + _: F + ) -> result::Result { + unimplemented!("Not required for testing!") + } + + fn runtime_version_at(&self, _: &BlockId) -> Result { + unimplemented!("Not required for testing!") + } + + fn record_proof(&mut self) { + unimplemented!("Not required for testing!") + } + + fn extract_proof(&mut self) -> Option { + unimplemented!("Not required for testing!") + } + + fn into_storage_changes< + T: sp_api::ChangesTrieStorage, sp_api::NumberFor> + >( + &self, + _: &Self::StateBackend, + _: Option<&T>, + _: ::Hash, + ) -> std::result::Result, String> + where Self: Sized + { + unimplemented!("Not required for testing!") + } +} + +impl GrandpaApi for RuntimeApi { + fn GrandpaApi_grandpa_authorities_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> Result> { + Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) + } +} + +impl GenesisAuthoritySetProvider for TestApi { + fn get(&self) -> Result { + Ok(self.genesis_authorities.clone()) + } +} + +impl AuthoritySetForFinalityProver for TestApi { + fn authorities(&self, _block: &BlockId) -> Result { + Ok(self.genesis_authorities.clone()) + } + + fn prove_authorities(&self, block: &BlockId) -> Result { + let authorities = self.authorities(block)?; + let backend = >>::from(vec![ + (None, vec![(b"authorities".to_vec(), Some(authorities.encode()))]) + ]); + let proof = prove_read(backend, vec![b"authorities"]) + .expect("failure proving read from in-memory storage backend"); + Ok(proof) + } +} + +impl AuthoritySetForFinalityChecker for TestApi { + fn check_authorities_proof( + &self, + _hash: ::Hash, + header: ::Header, + proof: StorageProof, + ) -> Result { + let results = read_proof_check::, _>( + *header.state_root(), proof, vec![b"authorities"] + ) + .expect("failure checking read proof for authorities"); + let encoded = results.get(&b"authorities"[..]) + .expect("returned map must contain all proof keys") + .as_ref() + .expect("authorities in proof is None"); + let authorities = Decode::decode(&mut &encoded[..]) + .expect("failure decoding authorities read from proof"); + Ok(authorities) + } +} + +const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500); + +fn make_ids(keys: &[Ed25519Keyring]) -> AuthorityList { + keys.iter().map(|key| key.clone().public().into()).map(|id| (id, 1)).collect() +} + +fn create_keystore(authority: Ed25519Keyring) -> (KeyStorePtr, tempfile::TempDir) { + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); + let keystore = sc_keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); + keystore.write().insert_ephemeral_from_seed::(&authority.to_seed()) + .expect("Creates authority key"); + + (keystore, keystore_path) +} + +fn block_until_complete(future: impl Future + Unpin, net: &Arc>, runtime: &mut current_thread::Runtime) { + let drive_to_completion = futures01::future::poll_fn(|| { + net.lock().poll(); Ok::, ()>(Async::NotReady) + }); + runtime.block_on( + future::select(future, drive_to_completion.compat()) + .map(|_| Ok::<(), ()>(())) + .compat() + ); +} + +// 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( + runtime: &mut current_thread::Runtime, + threads_pool: &futures::executor::ThreadPool, + blocks: u64, + net: Arc>, + peers: &[Ed25519Keyring], + with: F, +) -> u64 where + F: FnOnce(current_thread::Handle) -> Option>>> +{ + use parking_lot::RwLock; + + let mut wait_for = Vec::new(); + + let highest_finalized = Arc::new(RwLock::new(0)); + + if let Some(f) = (with)(runtime.handle()) { + wait_for.push(f); + }; + + let mut keystore_paths = Vec::new(); + for (peer_id, key) in peers.iter().enumerate() { + let (keystore, keystore_path) = create_keystore(*key); + keystore_paths.push(keystore_path); + + let highest_finalized = highest_finalized.clone(); + let (client, net_service, link) = { + let net = net.lock(); + // temporary needed for some reason + let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed"); + ( + net.peers[peer_id].client().clone(), + net.peers[peer_id].network_service().clone(), + link, + ) + }; + + wait_for.push( + Box::pin( + client.finality_notification_stream() + .take_while(move |n| { + let mut highest_finalized = highest_finalized.write(); + if *n.header.number() > *highest_finalized { + *highest_finalized = *n.header.number(); + } + future::ready(n.header.number() < &blocks) + }) + .collect::>() + .map(|_| ()) + ) + ); + + fn assert_send(_: &T) { } + + let grandpa_params = GrandpaParams { + config: Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore: Some(keystore), + name: Some(format!("peer#{}", peer_id)), + is_authority: true, + observer_enabled: true, + }, + link: link, + network: net_service, + inherent_data_providers: InherentDataProviders::new(), + on_exit: Exit, + telemetry_on_connect: None, + voting_rule: (), + executor: threads_pool.clone(), + }; + let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); + + assert_send(&voter); + + runtime.spawn(voter.unit_error().compat()); + } + + // wait for all finalized on each. + let wait_for = ::futures::future::join_all(wait_for); + + block_until_complete(wait_for, &net, runtime); + let highest_finalized = *highest_finalized.read(); + highest_finalized +} + +fn run_to_completion( + runtime: &mut current_thread::Runtime, + threads_pool: &futures::executor::ThreadPool, + blocks: u64, + net: Arc>, + peers: &[Ed25519Keyring] +) -> u64 { + run_to_completion_with(runtime, threads_pool, blocks, net, peers, |_| None) +} + +fn add_scheduled_change(block: &mut Block, change: ScheduledChange) { + block.header.digest_mut().push(DigestItem::Consensus( + GRANDPA_ENGINE_ID, + sp_finality_grandpa::ConsensusLog::ScheduledChange(change).encode(), + )); +} + +fn add_forced_change( + block: &mut Block, + median_last_finalized: BlockNumber, + change: ScheduledChange, +) { + block.header.digest_mut().push(DigestItem::Consensus( + GRANDPA_ENGINE_ID, + sp_finality_grandpa::ConsensusLog::ForcedChange(median_last_finalized, change).encode(), + )); +} + +#[test] +fn finalize_3_voters_no_observers() { + let _ = env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let voters = make_ids(peers); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); + net.peer(0).push_blocks(20, false); + net.block_until_sync(&mut runtime); + + for i in 0..3 { + assert_eq!(net.peer(i).client().info().best_number, 20, + "Peer #{} failed to sync", i); + } + + let net = Arc::new(Mutex::new(net)); + run_to_completion(&mut runtime, &threads_pool, 20, net.clone(), peers); + + // normally there's no justification for finalized blocks + assert!( + net.lock().peer(0).client().justification(&BlockId::Number(20)).unwrap().is_none(), + "Extra justification for block#1", + ); +} + +#[test] +fn finalize_3_voters_1_full_observer() { + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + + let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let voters = make_ids(peers); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 4); + net.peer(0).push_blocks(20, false); + net.block_until_sync(&mut runtime); + + let net = Arc::new(Mutex::new(net)); + let mut finality_notifications = Vec::new(); + + let all_peers = peers.iter() + .cloned() + .map(Some) + .chain(std::iter::once(None)); + + let mut keystore_paths = Vec::new(); + + let mut voters = Vec::new(); + + for (peer_id, local_key) in all_peers.enumerate() { + let (client, net_service, link) = { + 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(), + net.peers[peer_id].network_service().clone(), + link, + ) + }; + finality_notifications.push( + client.finality_notification_stream() + .take_while(|n| future::ready(n.header.number() < &20)) + .for_each(move |_| future::ready(())) + ); + + let keystore = if let Some(local_key) = local_key { + let (keystore, keystore_path) = create_keystore(local_key); + keystore_paths.push(keystore_path); + Some(keystore) + } else { + None + }; + + let grandpa_params = GrandpaParams { + config: Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore, + name: Some(format!("peer#{}", peer_id)), + is_authority: true, + observer_enabled: true, + }, + link: link, + network: net_service, + inherent_data_providers: InherentDataProviders::new(), + on_exit: Exit, + telemetry_on_connect: None, + voting_rule: (), + executor: threads_pool.clone(), + }; + + voters.push(run_grandpa_voter(grandpa_params).expect("all in order with client and network")); + } + + for voter in voters { + runtime.spawn(voter.unit_error().compat()); + } + + // wait for all finalized on each. + let wait_for = futures::future::join_all(finality_notifications) + .map(|_| ()); + + block_until_complete(wait_for, &net, &mut runtime); +} + +#[test] +fn transition_3_voters_twice_1_full_observer() { + let _ = env_logger::try_init(); + let peers_a = &[ + Ed25519Keyring::Alice, + Ed25519Keyring::Bob, + Ed25519Keyring::Charlie, + ]; + + let peers_b = &[ + Ed25519Keyring::Dave, + Ed25519Keyring::Eve, + Ed25519Keyring::Ferdie, + ]; + + let peers_c = &[ + Ed25519Keyring::Alice, + Ed25519Keyring::Eve, + Ed25519Keyring::Two, + ]; + + let observer = &[Ed25519Keyring::One]; + + let genesis_voters = make_ids(peers_a); + + let api = TestApi::new(genesis_voters); + let net = Arc::new(Mutex::new(GrandpaTestNet::new(api, 8))); + + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + + net.lock().peer(0).push_blocks(1, false); + net.lock().block_until_sync(&mut runtime); + + for (i, peer) in net.lock().peers().iter().enumerate() { + let full_client = peer.client().as_full().expect("only full clients are used in test"); + assert_eq!(full_client.chain_info().best_number, 1, + "Peer #{} failed to sync", i); + + let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); + + assert_eq!(set.current(), (0, make_ids(peers_a).as_slice())); + assert_eq!(set.pending_changes().count(), 0); + } + + { + let net = net.clone(); + let client = net.lock().peers[0].client().clone(); + let peers_c = peers_c.clone(); + + // wait for blocks to be finalized before generating new ones + let block_production = client.finality_notification_stream() + .take_while(|n| future::ready(n.header.number() < &30)) + .for_each(move |n| { + match n.header.number() { + 1 => { + // first 14 blocks. + net.lock().peer(0).push_blocks(13, false); + }, + 14 => { + // generate transition at block 15, applied at 20. + net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + let mut block = builder.build().unwrap().block; + add_scheduled_change(&mut block, ScheduledChange { + next_authorities: make_ids(peers_b), + delay: 4, + }); + + block + }); + net.lock().peer(0).push_blocks(5, false); + }, + 20 => { + // at block 21 we do another transition, but this time instant. + // add more until we have 30. + net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + let mut block = builder.build().unwrap().block; + add_scheduled_change(&mut block, ScheduledChange { + next_authorities: make_ids(&peers_c), + delay: 0, + }); + + block + }); + net.lock().peer(0).push_blocks(9, false); + }, + _ => {}, + } + + future::ready(()) + }); + + runtime.spawn(block_production.unit_error().compat()); + } + + let mut finality_notifications = Vec::new(); + let all_peers = peers_a.iter() + .chain(peers_b) + .chain(peers_c) + .chain(observer) + .cloned() + .collect::>() // deduplicate + .into_iter() + .enumerate(); + + let mut keystore_paths = Vec::new(); + for (peer_id, local_key) in all_peers { + let (keystore, keystore_path) = create_keystore(local_key); + keystore_paths.push(keystore_path); + + let (client, net_service, link) = { + 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(), + net.peers[peer_id].network_service().clone(), + link, + ) + }; + + finality_notifications.push( + client.finality_notification_stream() + .take_while(|n| future::ready(n.header.number() < &30)) + .for_each(move |_| future::ready(())) + .map(move |()| { + let full_client = client.as_full().expect("only full clients are used in test"); + let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); + + assert_eq!(set.current(), (2, make_ids(peers_c).as_slice())); + assert_eq!(set.pending_changes().count(), 0); + }) + ); + + let grandpa_params = GrandpaParams { + config: Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore: Some(keystore), + name: Some(format!("peer#{}", peer_id)), + is_authority: true, + observer_enabled: true, + }, + link: link, + network: net_service, + inherent_data_providers: InherentDataProviders::new(), + on_exit: Exit, + telemetry_on_connect: None, + voting_rule: (), + executor: threads_pool.clone(), + }; + let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); + + runtime.spawn(voter.unit_error().compat()); + } + + // wait for all finalized on each. + let wait_for = ::futures::future::join_all(finality_notifications); + + block_until_complete(wait_for, &net, &mut runtime); +} + +#[test] +fn justification_is_emitted_when_consensus_data_changes() { + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3); + + // import block#1 WITH consensus data change + let new_authorities = vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])]; + net.peer(0).push_authorities_change_block(new_authorities); + net.block_until_sync(&mut runtime); + let net = Arc::new(Mutex::new(net)); + run_to_completion(&mut runtime, &threads_pool, 1, net.clone(), peers); + + // ... and check that there's justification for block#1 + assert!(net.lock().peer(0).client().justification(&BlockId::Number(1)).unwrap().is_some(), + "Missing justification for block#1"); +} + +#[test] +fn justification_is_generated_periodically() { + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let voters = make_ids(peers); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); + net.peer(0).push_blocks(32, false); + net.block_until_sync(&mut runtime); + + let net = Arc::new(Mutex::new(net)); + run_to_completion(&mut runtime, &threads_pool, 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().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 mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; + let voters = make_ids(peers_b); + + // 4 peers, 3 of them are authorities and participate in grandpa + let api = TestApi::new(voters); + 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 mut block = builder.build().unwrap().block; + add_scheduled_change(&mut block, 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.block_until_sync(&mut runtime); + + for i in 0..4 { + assert_eq!(net.peer(i).client().info().best_number, 25, + "Peer #{} failed to sync", i); + } + + let net = Arc::new(Mutex::new(net)); + run_to_completion(&mut runtime, &threads_pool, 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 + futures::executor::block_on(futures::future::poll_fn(move |_| { + if net.lock().peer(3).client().justification(&BlockId::Number(21)).unwrap().is_none() { + net.lock().poll(); + Poll::Pending + } else { + Poll::Ready(()) + } + })) +} + +#[test] +fn finalizes_multiple_pending_changes_in_order() { + let _ = env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + + let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let peers_b = &[Ed25519Keyring::Dave, Ed25519Keyring::Eve, Ed25519Keyring::Ferdie]; + let peers_c = &[Ed25519Keyring::Dave, Ed25519Keyring::Alice, Ed25519Keyring::Bob]; + + let all_peers = &[ + Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie, + Ed25519Keyring::Dave, Ed25519Keyring::Eve, Ed25519Keyring::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 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 mut block = builder.build().unwrap().block; + add_scheduled_change(&mut block, 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 mut block = builder.build().unwrap().block; + add_scheduled_change(&mut block, 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.block_until_sync(&mut runtime); + + // all peers imported both change blocks + for i in 0..6 { + assert_eq!(net.peer(i).client().info().best_number, 30, + "Peer #{} failed to sync", i); + } + + let net = Arc::new(Mutex::new(net)); + run_to_completion(&mut runtime, &threads_pool, 30, net.clone(), all_peers); +} + +#[test] +fn force_change_to_new_set() { + let _ = env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + // two of these guys are offline. + let genesis_authorities = &[ + Ed25519Keyring::Alice, + Ed25519Keyring::Bob, + Ed25519Keyring::Charlie, + Ed25519Keyring::One, + Ed25519Keyring::Two, + ]; + let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let api = TestApi::new(make_ids(genesis_authorities)); + + let voters = make_ids(peers_a); + let net = GrandpaTestNet::new(api, 3); + let net = Arc::new(Mutex::new(net)); + + net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + let mut block = builder.build().unwrap().block; + + // add a forced transition at block 12. + add_forced_change(&mut block, 0, ScheduledChange { + next_authorities: voters.clone(), + delay: 10, + }); + + // add a normal transition too to ensure that forced changes take priority. + add_scheduled_change(&mut block, ScheduledChange { + next_authorities: make_ids(genesis_authorities), + delay: 5, + }); + + block + }); + + net.lock().peer(0).push_blocks(25, false); + net.lock().block_until_sync(&mut runtime); + + for (i, peer) in net.lock().peers().iter().enumerate() { + assert_eq!(peer.client().info().best_number, 26, + "Peer #{} failed to sync", i); + + let full_client = peer.client().as_full().expect("only full clients are used in test"); + let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).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(&mut runtime, &threads_pool, 25, net, peers_a); +} + +#[test] +fn allows_reimporting_change_blocks() { + let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; + let voters = make_ids(peers_a); + let api = TestApi::new(voters); + let mut net = GrandpaTestNet::new(api.clone(), 3); + + let client = net.peer(0).client().clone(); + let (mut block_import, ..) = net.make_block_import::< + TransactionFor + >( + client.clone(), + ); + + let full_client = client.as_full().unwrap(); + let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + let mut block = builder.build().unwrap().block; + add_scheduled_change(&mut block, ScheduledChange { + next_authorities: make_ids(peers_b), + delay: 0, + }); + + let block = || { + let block = block.clone(); + BlockImportParams { + origin: BlockOrigin::File, + header: block.header, + justification: None, + post_digests: Vec::new(), + body: Some(block.extrinsics), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + } + }; + + assert_eq!( + block_import.import_block(block(), HashMap::new()).unwrap(), + ImportResult::Imported(ImportedAux { + needs_justification: true, + clear_justification_requests: false, + bad_justification: false, + needs_finality_proof: false, + is_new_best: true, + header_only: false, + }), + ); + + assert_eq!( + block_import.import_block(block(), HashMap::new()).unwrap(), + ImportResult::AlreadyInChain + ); +} + +#[test] +fn test_bad_justification() { + let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; + let voters = make_ids(peers_a); + let api = TestApi::new(voters); + let mut net = GrandpaTestNet::new(api.clone(), 3); + + let client = net.peer(0).client().clone(); + let (mut block_import, ..) = net.make_block_import::< + TransactionFor + >( + client.clone(), + ); + + let full_client = client.as_full().expect("only full clients are used in test"); + let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + let mut block = builder.build().unwrap().block; + + add_scheduled_change(&mut block, ScheduledChange { + next_authorities: make_ids(peers_b), + delay: 0, + }); + + let block = || { + let block = block.clone(); + BlockImportParams { + origin: BlockOrigin::File, + header: block.header, + justification: Some(Vec::new()), + post_digests: Vec::new(), + body: Some(block.extrinsics), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + } + }; + + assert_eq!( + block_import.import_block(block(), HashMap::new()).unwrap(), + ImportResult::Imported(ImportedAux { + needs_justification: true, + clear_justification_requests: false, + bad_justification: true, + is_new_best: true, + ..Default::default() + }), + ); + + assert_eq!( + block_import.import_block(block(), HashMap::new()).unwrap(), + ImportResult::AlreadyInChain + ); +} + +#[test] +#[ignore] +fn voter_persists_its_votes() { + use std::iter::FromIterator; + use std::sync::atomic::{AtomicUsize, Ordering}; + use futures::future; + use futures::channel::mpsc; + + let _ = env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + + // we have two authorities but we'll only be running the voter for alice + // we are going to be listening for the prevotes it casts + let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; + let voters = make_ids(peers); + + // alice has a chain with 20 blocks + let mut net = GrandpaTestNet::new(TestApi::new(voters.clone()), 2); + net.peer(0).push_blocks(20, false); + net.block_until_sync(&mut runtime); + + assert_eq!(net.peer(0).client().info().best_number, 20, + "Peer #{} failed to sync", 0); + + + let peer = net.peer(0); + let client = peer.client().clone(); + let net = Arc::new(Mutex::new(net)); + + // channel between the voter and the main controller. + // sending a message on the `voter_tx` restarts the voter. + let (voter_tx, voter_rx) = mpsc::unbounded::<()>(); + + let mut keystore_paths = Vec::new(); + + // startup a grandpa voter for alice but also listen for messages on a + // channel. whenever a message is received the voter is restarted. when the + // sender is dropped the voter is stopped. + { + let (keystore, keystore_path) = create_keystore(peers[0]); + keystore_paths.push(keystore_path); + + struct ResettableVoter { + voter: Pin + Send + Unpin>>, + voter_rx: mpsc::UnboundedReceiver<()>, + net: Arc>, + client: PeersClient, + keystore: KeyStorePtr, + threads_pool: futures::executor::ThreadPool, + } + + impl Future for ResettableVoter { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let this = Pin::into_inner(self); + + if let Poll::Ready(()) = Pin::new(&mut this.voter).poll(cx) { + panic!("error in the voter"); + } + + match Pin::new(&mut this.voter_rx).poll_next(cx) { + Poll::Pending => return Poll::Pending, + Poll::Ready(None) => return Poll::Ready(()), + Poll::Ready(Some(())) => { + let (_block_import, _, _, _, link) = + this.net.lock() + .make_block_import::< + TransactionFor + >(this.client.clone()); + let link = link.lock().take().unwrap(); + + let grandpa_params = GrandpaParams { + config: Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore: Some(this.keystore.clone()), + name: Some(format!("peer#{}", 0)), + is_authority: true, + observer_enabled: true, + }, + link, + network: this.net.lock().peers[0].network_service().clone(), + inherent_data_providers: InherentDataProviders::new(), + on_exit: Exit, + telemetry_on_connect: None, + voting_rule: VotingRulesBuilder::default().build(), + executor: this.threads_pool.clone(), + }; + + let voter = run_grandpa_voter(grandpa_params) + .expect("all in order with client and network") + .map(move |r| { + // we need to keep the block_import alive since it owns the + // sender for the voter commands channel, if that gets dropped + // then the voter will stop + drop(_block_import); + r + }); + + this.voter = Box::pin(voter); + // notify current task in order to poll the voter + cx.waker().wake_by_ref(); + } + }; + + Poll::Pending + } + } + + // we create a "dummy" voter by setting it to `pending` and triggering the `tx`. + // this way, the `ResettableVoter` will reset its `voter` field to a value ASAP. + voter_tx.unbounded_send(()).unwrap(); + runtime.spawn(ResettableVoter { + voter: Box::pin(futures::future::pending()), + voter_rx, + net: net.clone(), + client: client.clone(), + keystore, + threads_pool: threads_pool.clone(), + }.unit_error().compat()); + } + + let (exit_tx, exit_rx) = futures::channel::oneshot::channel::<()>(); + + // create the communication layer for bob, but don't start any + // voter. instead we'll listen for the prevote that alice casts + // and cast our own manually + { + let (keystore, keystore_path) = create_keystore(peers[1]); + keystore_paths.push(keystore_path); + + let config = Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore: Some(keystore), + name: Some(format!("peer#{}", 1)), + is_authority: true, + observer_enabled: true, + }; + + let set_state = { + let (_, _, _, _, link) = net.lock() + .make_block_import::< + TransactionFor + >(client); + let LinkHalf { persistent_data, .. } = link.lock().take().unwrap(); + let PersistentData { set_state, .. } = persistent_data; + set_state + }; + + let network = communication::NetworkBridge::new( + net.lock().peers[1].network_service().clone(), + config.clone(), + set_state, + &threads_pool, + Exit, + ); + + let (round_rx, round_tx) = network.round_communication( + communication::Round(1), + communication::SetId(0), + Arc::new(VoterSet::from_iter(voters)), + Some(peers[1].pair().into()), + HasVoted::No, + ); + + let round_tx = Arc::new(Mutex::new(round_tx)); + let exit_tx = Arc::new(Mutex::new(Some(exit_tx))); + + let net = net.clone(); + let state = Arc::new(AtomicUsize::new(0)); + + runtime.spawn(round_rx.try_for_each(move |signed| { + let net2 = net.clone(); + let net = net.clone(); + let voter_tx = voter_tx.clone(); + let round_tx = round_tx.clone(); + let state = state.clone(); + let exit_tx = exit_tx.clone(); + + async move { + if state.compare_and_swap(0, 1, Ordering::SeqCst) == 0 { + // the first message we receive should be a prevote from alice. + let prevote = match signed.message { + finality_grandpa::Message::Prevote(prevote) => prevote, + _ => panic!("voter should prevote."), + }; + + // its chain has 20 blocks and the voter targets 3/4 of the + // unfinalized chain, so the vote should be for block 15 + assert!(prevote.target_number == 15); + + // we push 20 more blocks to alice's chain + net.lock().peer(0).push_blocks(20, false); + + let interval = futures::stream::unfold(Delay::new(Duration::from_millis(200)), |delay| + Box::pin(async move { + delay.await; + Some(((), Delay::new(Duration::from_millis(200)))) + }) + ); + + interval + .take_while(move |_| { + future::ready(net2.lock().peer(1).client().info().best_number != 40) + }) + .for_each(|_| future::ready(())) + .await; + + let block_30_hash = + net.lock().peer(0).client().as_full().unwrap().hash(30).unwrap().unwrap(); + + // we restart alice's voter + voter_tx.unbounded_send(()).unwrap(); + + // and we push our own prevote for block 30 + let prevote = finality_grandpa::Prevote { + target_number: 30, + target_hash: block_30_hash, + }; + + // TODO: figure out why this doesn't compile. + // Pin::new(&mut *round_tx.lock()).start_send(finality_grandpa::Message::Prevote(prevote)).unwrap(); + } else if state.compare_and_swap(1, 2, Ordering::SeqCst) == 1 { + // the next message we receive should be our own prevote + let prevote = match signed.message { + finality_grandpa::Message::Prevote(prevote) => prevote, + _ => panic!("We should receive our own prevote."), + }; + + // targeting block 30 + assert!(prevote.target_number == 30); + + // after alice restarts it should send its previous prevote + // therefore we won't ever receive it again since it will be a + // known message on the gossip layer + + } else if state.compare_and_swap(2, 3, Ordering::SeqCst) == 2 { + // we then receive a precommit from alice for block 15 + // even though we casted a prevote for block 30 + let precommit = match signed.message { + finality_grandpa::Message::Precommit(precommit) => precommit, + _ => panic!("voter should precommit."), + }; + + assert!(precommit.target_number == 15); + + // signal exit + exit_tx.clone().lock().take().unwrap().send(()).unwrap(); + } else { + panic!() + } + + Ok(()) + } + }).map_err(drop).boxed().compat()); + } + + block_until_complete(exit_rx.into_future(), &net, &mut runtime); +} + +#[test] +fn finalize_3_voters_1_light_observer() { + let _ = env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + let authorities = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let voters = make_ids(authorities); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 4); + net.peer(0).push_blocks(20, false); + net.block_until_sync(&mut runtime); + + for i in 0..4 { + assert_eq!(net.peer(i).client().info().best_number, 20, + "Peer #{} failed to sync", i); + } + + let net = Arc::new(Mutex::new(net)); + let link = net.lock().peer(3).data.lock().take().expect("link initialized on startup; qed"); + + let finality_notifications = net.lock().peer(3).client().finality_notification_stream() + .take_while(|n| future::ready(n.header.number() < &20)) + .collect::>(); + + run_to_completion_with(&mut runtime, &threads_pool, 20, net.clone(), authorities, |executor| { + executor.spawn( + run_grandpa_observer( + Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore: None, + name: Some("observer".to_string()), + is_authority: false, + observer_enabled: true, + }, + link, + net.lock().peers[3].network_service().clone(), + Exit, + threads_pool.clone(), + ).unwrap().unit_error().compat() + ).unwrap(); + + Some(Box::pin(finality_notifications.map(|_| ()))) + }); +} + +#[test] +fn finality_proof_is_fetched_by_light_client_when_consensus_data_changes() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + + let peers = &[Ed25519Keyring::Alice]; + let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 1); + net.add_light_peer(&GrandpaTestNet::default_config()); + + // import block#1 WITH consensus data change. Light client ignores justification + // && instead fetches finality proof for block #1 + net.peer(0).push_authorities_change_block(vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])]); + let net = Arc::new(Mutex::new(net)); + run_to_completion(&mut runtime, &threads_pool, 1, net.clone(), peers); + net.lock().block_until_sync(&mut runtime); + + // check that the block#1 is finalized on light client + let mut runtime = current_thread::Runtime::new().unwrap(); + let _ = runtime.block_on(futures::future::poll_fn(move |_| { + if net.lock().peer(1).client().info().finalized_number == 1 { + Poll::Ready(()) + } else { + net.lock().poll(); + Poll::Pending + } + }).unit_error().compat()); +} + +#[test] +fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_different() { + // for debug: to ensure that without forced change light client will sync finality proof + const FORCE_CHANGE: bool = true; + + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + + // two of these guys are offline. + let genesis_authorities = if FORCE_CHANGE { + vec![ + Ed25519Keyring::Alice, + Ed25519Keyring::Bob, + Ed25519Keyring::Charlie, + Ed25519Keyring::One, + Ed25519Keyring::Two, + ] + } else { + vec![ + Ed25519Keyring::Alice, + Ed25519Keyring::Bob, + Ed25519Keyring::Charlie, + ] + }; + let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; + let api = TestApi::new(make_ids(&genesis_authorities)); + + let voters = make_ids(peers_a); + let net = GrandpaTestNet::new(api, 3); + let net = Arc::new(Mutex::new(net)); + + // best is #1 + net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + // add a forced transition at block 5. + let mut block = builder.build().unwrap().block; + if FORCE_CHANGE { + add_forced_change(&mut block, 0, ScheduledChange { + next_authorities: voters.clone(), + delay: 3, + }); + } + block + }); + + // ensure block#10 enacts authorities set change => justification is generated + // normally it will reach light client, but because of the forced change, it will not + net.lock().peer(0).push_blocks(8, false); // best is #9 + net.lock().peer(0).push_authorities_change_block( + vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])] + ); // #10 + net.lock().peer(0).push_blocks(1, false); // best is #11 + net.lock().block_until_sync(&mut runtime); + + // finalize block #11 on full clients + run_to_completion(&mut runtime, &threads_pool, 11, net.clone(), peers_a); + + // request finalization by light client + net.lock().add_light_peer(&GrandpaTestNet::default_config()); + net.lock().block_until_sync(&mut runtime); + + // check block, finalized on light client + assert_eq!( + net.lock().peer(3).client().info().finalized_number, + if FORCE_CHANGE { 0 } else { 10 }, + ); +} + +#[test] +fn voter_catches_up_to_latest_round_when_behind() { + let _ = env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + + let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; + let voters = make_ids(peers); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); + net.peer(0).push_blocks(50, false); + net.block_until_sync(&mut runtime); + + let net = Arc::new(Mutex::new(net)); + let mut finality_notifications = Vec::new(); + + let voter = |keystore, peer_id, link, net: Arc>| -> Pin + Send>> { + let grandpa_params = GrandpaParams { + config: Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore, + name: Some(format!("peer#{}", peer_id)), + is_authority: true, + observer_enabled: true, + }, + link, + network: net.lock().peer(peer_id).network_service().clone(), + inherent_data_providers: InherentDataProviders::new(), + on_exit: Exit, + telemetry_on_connect: None, + voting_rule: (), + executor: threads_pool.clone(), + }; + + Box::pin(run_grandpa_voter(grandpa_params).expect("all in order with client and network")) + }; + + let mut keystore_paths = Vec::new(); + + // spawn authorities + for (peer_id, key) in peers.iter().enumerate() { + let (client, link) = { + 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(), + link, + ) + }; + + finality_notifications.push( + client.finality_notification_stream() + .take_while(|n| future::ready(n.header.number() < &50)) + .for_each(move |_| future::ready(())) + ); + + let (keystore, keystore_path) = create_keystore(*key); + keystore_paths.push(keystore_path); + + let voter = voter(Some(keystore), peer_id, link, net.clone()); + + runtime.spawn(voter.unit_error().compat()); + } + + // wait for them to finalize block 50. since they'll vote on 3/4 of the + // unfinalized chain it will take at least 4 rounds to do it. + let wait_for_finality = ::futures::future::join_all(finality_notifications) + .map(|_| ()); + + // spawn a new voter, it should be behind by at least 4 rounds and should be + // able to catch up to the latest round + let test = { + let net = net.clone(); + let runtime = runtime.handle(); + + wait_for_finality.then(move |_| { + let peer_id = 2; + let link = { + let net = net.lock(); + let mut link = net.peers[peer_id].data.lock(); + link.take().expect("link initialized at startup; qed") + }; + + let set_state = link.persistent_data.set_state.clone(); + + let voter = voter(None, peer_id, link, net); + + runtime.spawn(voter.unit_error().compat()).unwrap(); + + let start_time = std::time::Instant::now(); + let timeout = Duration::from_secs(5 * 60); + let wait_for_catch_up = futures::future::poll_fn(move |_| { + // The voter will start at round 1 and since everyone else is + // already at a later round the only way to get to round 4 (or + // later) is by issuing a catch up request. + if set_state.read().last_completed_round().number >= 4 { + Poll::Ready(()) + } else if start_time.elapsed() > timeout { + panic!("Timed out while waiting for catch up to happen") + } else { + Poll::Pending + } + }); + + wait_for_catch_up + }) + }; + + let drive_to_completion = futures01::future::poll_fn(|| { + net.lock().poll(); Ok::, ()>(Async::NotReady) + }); + runtime.block_on( + future::select(test, drive_to_completion.compat()) + .map(|_| Ok::<(), ()>(())) + .compat() + ); +} + +#[test] +fn grandpa_environment_respects_voting_rules() { + use finality_grandpa::Chain; + use sc_network_test::TestClient; + + let threads_pool = futures::executor::ThreadPool::new().unwrap(); + + let peers = &[Ed25519Keyring::Alice]; + let voters = make_ids(peers); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 1); + let peer = net.peer(0); + let network_service = peer.network_service().clone(); + let link = peer.data.lock().take().unwrap(); + + // create a voter environment with a given voting rule + let environment = |voting_rule: Box>| { + let PersistentData { + ref authority_set, + ref consensus_changes, + ref set_state, + .. + } = link.persistent_data; + + let config = Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore: None, + name: None, + is_authority: true, + observer_enabled: true, + }; + + let network = NetworkBridge::new( + network_service.clone(), + config.clone(), + set_state.clone(), + &threads_pool, + Exit, + ); + + Environment { + authority_set: authority_set.clone(), + config: config.clone(), + consensus_changes: consensus_changes.clone(), + client: link.client.clone(), + select_chain: link.select_chain.clone(), + set_id: authority_set.set_id(), + voter_set_state: set_state.clone(), + voters: Arc::new(authority_set.current_authorities()), + network, + voting_rule, + } + }; + + // add 20 blocks + peer.push_blocks(20, false); + + // create an environment with no voting rule restrictions + let unrestricted_env = environment(Box::new(())); + + // another with 3/4 unfinalized chain voting rule restriction + let three_quarters_env = environment(Box::new( + voting_rule::ThreeQuartersOfTheUnfinalizedChain + )); + + // and another restricted with the default voting rules: i.e. 3/4 rule and + // always below best block + let default_env = environment(Box::new( + VotingRulesBuilder::default().build() + )); + + // the unrestricted environment should just return the best block + assert_eq!( + unrestricted_env.best_chain_containing( + peer.client().info().finalized_hash + ).unwrap().1, + 20, + ); + + // both the other environments should return block 15, which is 3/4 of the + // way in the unfinalized chain + assert_eq!( + three_quarters_env.best_chain_containing( + peer.client().info().finalized_hash + ).unwrap().1, + 15, + ); + + assert_eq!( + default_env.best_chain_containing( + peer.client().info().finalized_hash + ).unwrap().1, + 15, + ); + + // we finalize block 19 with block 20 being the best block + peer.client().finalize_block(BlockId::Number(19), None, false).unwrap(); + + // the 3/4 environment should propose block 20 for voting + assert_eq!( + three_quarters_env.best_chain_containing( + peer.client().info().finalized_hash + ).unwrap().1, + 20, + ); + + // while the default environment will always still make sure we don't vote + // on the best block + assert_eq!( + default_env.best_chain_containing( + peer.client().info().finalized_hash + ).unwrap().1, + 19, + ); + + // we finalize block 20 with block 20 being the best block + peer.client().finalize_block(BlockId::Number(20), None, false).unwrap(); + + // even though the default environment will always try to not vote on the + // best block, there's a hard rule that we can't cast any votes lower than + // the given base (#20). + assert_eq!( + default_env.best_chain_containing( + peer.client().info().finalized_hash + ).unwrap().1, + 20, + ); +} + +#[test] +fn imports_justification_for_regular_blocks_on_import() { + // NOTE: this is a regression test since initially we would only import + // justifications for authority change blocks, and would discard any + // existing justification otherwise. + let peers = &[Ed25519Keyring::Alice]; + let voters = make_ids(peers); + let api = TestApi::new(voters); + let mut net = GrandpaTestNet::new(api.clone(), 1); + + let client = net.peer(0).client().clone(); + let (mut block_import, ..) = net.make_block_import::< + TransactionFor + >(client.clone()); + + let full_client = client.as_full().expect("only full clients are used in test"); + let builder = full_client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + let block = builder.build().unwrap().block; + + let block_hash = block.hash(); + + // create a valid justification, with one precommit targeting the block + let justification = { + let round = 1; + let set_id = 0; + + let precommit = finality_grandpa::Precommit { + target_hash: block_hash, + target_number: *block.header.number(), + }; + + let msg = finality_grandpa::Message::Precommit(precommit.clone()); + let encoded = communication::localized_payload(round, set_id, &msg); + let signature = peers[0].sign(&encoded[..]).into(); + + let precommit = finality_grandpa::SignedPrecommit { + precommit, + signature, + id: peers[0].public().into(), + }; + + let commit = finality_grandpa::Commit { + target_hash: block_hash, + target_number: *block.header.number(), + precommits: vec![precommit], + }; + + GrandpaJustification::from_commit( + &full_client, + round, + commit, + ).unwrap() + }; + + // we import the block with justification attached + let block = BlockImportParams { + origin: BlockOrigin::File, + header: block.header, + justification: Some(justification.encode()), + post_digests: Vec::new(), + body: Some(block.extrinsics), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + + assert_eq!( + block_import.import_block(block, HashMap::new()).unwrap(), + ImportResult::Imported(ImportedAux { + needs_justification: false, + clear_justification_requests: false, + bad_justification: false, + is_new_best: true, + ..Default::default() + }), + ); + + // the justification should be imported and available from the client + assert!( + client.justification(&BlockId::Hash(block_hash)).unwrap().is_some(), + ); +} diff --git a/core/finality-grandpa/src/until_imported.rs b/client/finality-grandpa/src/until_imported.rs similarity index 91% rename from core/finality-grandpa/src/until_imported.rs rename to client/finality-grandpa/src/until_imported.rs index 2e5e04f595387..c95b3d6eef5b6 100644 --- a/core/finality-grandpa/src/until_imported.rs +++ b/client/finality-grandpa/src/until_imported.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -29,19 +29,21 @@ use super::{ }; use log::{debug, warn}; -use client::ImportNotifications; -use futures::{prelude::*, stream::Fuse}; -use grandpa::voter; +use sc_client_api::{BlockImportNotification, ImportNotifications}; +use futures::prelude::*; +use futures::stream::Fuse; +use futures_timer::Delay; +use futures::channel::mpsc::UnboundedReceiver; +use finality_grandpa::voter; use parking_lot::Mutex; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use futures_timer::Interval; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use std::collections::{HashMap, VecDeque}; use std::pin::Pin; use std::sync::{atomic::{AtomicUsize, Ordering}, Arc}; use std::task::{Context, Poll}; use std::time::{Duration, Instant}; -use fg_primitives::AuthorityId; +use sp_finality_grandpa::AuthorityId; const LOG_PENDING_INTERVAL: Duration = Duration::from_secs(15); @@ -71,12 +73,12 @@ pub(crate) trait BlockUntilImported: Sized { /// Buffering imported messages until blocks with given hashes are imported. pub(crate) struct UntilImported> { - import_notifications: Fuse>, + import_notifications: Fuse>>, block_sync_requester: BlockSyncRequester, status_check: BlockStatus, inner: Fuse, ready: VecDeque, - check_pending: Interval, + check_pending: Pin> + Send>>, /// Mapping block hashes to their block number, the point in time it was /// first encountered (Instant) and a list of GRANDPA messages referencing /// the block hash. @@ -86,9 +88,13 @@ pub(crate) struct UntilImported UntilImported where Block: BlockT, - BlockStatus: BlockStatusT, - M: BlockUntilImported, - I: Stream, + BlockStatus: BlockStatusT + Unpin, + BlockSyncRequester: BlockSyncRequesterT + Unpin, + I: Stream> + Unpin, + M: BlockUntilImported + Unpin, + Block::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, + M::Blocked: Unpin, { /// Create a new `UntilImported` wrapper. pub(crate) fn new( @@ -105,13 +111,19 @@ impl UntilImported UntilImported Stream for UntilImported where Block: BlockT, - BStatus: BlockStatusT, - BSyncRequester: BlockSyncRequesterT, + BStatus: BlockStatusT + Unpin, + BSyncRequester: BlockSyncRequesterT + Unpin, I: Stream> + Unpin, - M: BlockUntilImported, + M: BlockUntilImported + Unpin, + Block::Hash: Unpin, + <::Header as HeaderT>::Number: Unpin, + M::Blocked: Unpin, { type Item = Result; - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { // We are using a `this` variable in order to allow multiple simultaneous mutable borrow // to `self`. - let this = &mut *self; + let this = Pin::into_inner(self); loop { match Stream::poll_next(Pin::new(&mut this.inner), cx) { @@ -174,7 +189,7 @@ impl Stream for UntilImported Stream for UntilImported> Unpin for -UntilImported { -} - fn warn_authority_wrong_target(hash: H, id: AuthorityId) { warn!( target: "afg", @@ -473,12 +483,13 @@ pub(crate) type UntilGlobalMessageBlocksImported for TestBlockSyncRequester { - fn set_sync_fork_request(&self, _peers: Vec, hash: Hash, number: NumberFor) { + fn set_sync_fork_request(&self, _peers: Vec, hash: Hash, number: NumberFor) { self.requests.lock().push((hash, number)); } } @@ -733,10 +744,10 @@ mod tests { let h3 = make_header(7); let signed_prevote = |header: &Header| { - grandpa::SignedPrevote { + finality_grandpa::SignedPrevote { id: Default::default(), signature: Default::default(), - prevote: grandpa::Prevote { + prevote: finality_grandpa::Prevote { target_hash: header.hash(), target_number: *header.number(), }, @@ -744,10 +755,10 @@ mod tests { }; let signed_precommit = |header: &Header| { - grandpa::SignedPrecommit { + finality_grandpa::SignedPrecommit { id: Default::default(), signature: Default::default(), - precommit: grandpa::Precommit { + precommit: finality_grandpa::Precommit { target_hash: header.hash(), target_number: *header.number(), }, @@ -764,7 +775,7 @@ mod tests { signed_precommit(&h2), ]; - let unknown_catch_up = grandpa::CatchUp { + let unknown_catch_up = finality_grandpa::CatchUp { round_number: 1, prevotes, precommits, @@ -799,10 +810,10 @@ mod tests { let h3 = make_header(7); let signed_prevote = |header: &Header| { - grandpa::SignedPrevote { + finality_grandpa::SignedPrevote { id: Default::default(), signature: Default::default(), - prevote: grandpa::Prevote { + prevote: finality_grandpa::Prevote { target_hash: header.hash(), target_number: *header.number(), }, @@ -810,10 +821,10 @@ mod tests { }; let signed_precommit = |header: &Header| { - grandpa::SignedPrecommit { + finality_grandpa::SignedPrecommit { id: Default::default(), signature: Default::default(), - precommit: grandpa::Precommit { + precommit: finality_grandpa::Precommit { target_hash: header.hash(), target_number: *header.number(), }, @@ -830,7 +841,7 @@ mod tests { signed_precommit(&h2), ]; - let unknown_catch_up = grandpa::CatchUp { + let unknown_catch_up = finality_grandpa::CatchUp { round_number: 1, prevotes, precommits, @@ -929,7 +940,7 @@ mod tests { let test = future::select(assert, timeout).map(|res| match res { Either::Left(_) => {}, Either::Right(_) => panic!("timed out waiting for block sync request"), - }); + }).map(drop); futures::executor::block_on(test); } diff --git a/core/finality-grandpa/src/voting_rule.rs b/client/finality-grandpa/src/voting_rule.rs similarity index 97% rename from core/finality-grandpa/src/voting_rule.rs rename to client/finality-grandpa/src/voting_rule.rs index 355fa0cd2d080..8ba52f30f7b0f 100644 --- a/core/finality-grandpa/src/voting_rule.rs +++ b/client/finality-grandpa/src/voting_rule.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,9 +22,9 @@ use std::sync::Arc; -use client::blockchain::HeaderBackend; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{Block as BlockT, Header, NumberFor, One, Zero}; +use sc_client_api::blockchain::HeaderBackend; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{Block as BlockT, Header, NumberFor, One, Zero}; /// A trait for custom voting rules in GRANDPA. pub trait VotingRule: Send + Sync where diff --git a/client/keystore/Cargo.toml b/client/keystore/Cargo.toml new file mode 100644 index 0000000000000..cdc69349fb8b8 --- /dev/null +++ b/client/keystore/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "sc-keystore" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +derive_more = "0.99.2" +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-application-crypto = { version = "2.0.0", path = "../../primitives/application-crypto" } +hex = "0.4.0" +rand = "0.7.2" +serde_json = "1.0.41" +subtle = "2.1.1" +parking_lot = "0.9.0" + +[dev-dependencies] +tempfile = "3.1.0" diff --git a/client/keystore/src/lib.rs b/client/keystore/src/lib.rs new file mode 100644 index 0000000000000..f8794aa05e8f6 --- /dev/null +++ b/client/keystore/src/lib.rs @@ -0,0 +1,454 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Keystore (and session key management) for ed25519 based chains like Polkadot. + +#![warn(missing_docs)] + +use std::{collections::HashMap, path::PathBuf, fs::{self, File}, io::{self, Write}, sync::Arc}; + +use sp_core::{ + crypto::{KeyTypeId, Pair as PairT, Public, IsWrappedBy, Protected}, traits::BareCryptoStore, +}; + +use sp_application_crypto::{AppKey, AppPublic, AppPair, ed25519, sr25519}; + +use parking_lot::RwLock; + +/// Keystore pointer +pub type KeyStorePtr = Arc>; + +/// Keystore error. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// IO error. + Io(io::Error), + /// JSON error. + Json(serde_json::Error), + /// Invalid password. + #[display(fmt="Invalid password")] + InvalidPassword, + /// Invalid BIP39 phrase + #[display(fmt="Invalid recovery phrase (BIP39) data")] + InvalidPhrase, + /// Invalid seed + #[display(fmt="Invalid seed")] + InvalidSeed, + /// Keystore unavailable + #[display(fmt="Keystore unavailable")] + Unavailable, +} + +/// Keystore Result +pub type Result = std::result::Result; + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Io(ref err) => Some(err), + Error::Json(ref err) => Some(err), + _ => None, + } + } +} + +/// Key store. +/// +/// Stores key pairs in a file system store + short lived key pairs in memory. +/// +/// Every pair that is being generated by a `seed`, will be placed in memory. +pub struct Store { + path: Option, + additional: HashMap<(KeyTypeId, Vec), Vec>, + password: Option>, +} + +impl Store { + /// Open the store at the given path. + /// + /// Optionally takes a password that will be used to encrypt/decrypt the keys. + pub fn open>(path: T, password: Option>) -> Result { + let path = path.into(); + fs::create_dir_all(&path)?; + + let instance = Self { path: Some(path), additional: HashMap::new(), password }; + Ok(Arc::new(RwLock::new(instance))) + } + + /// Create a new in-memory store. + pub fn new_in_memory() -> KeyStorePtr { + Arc::new(RwLock::new(Self { + path: None, + additional: HashMap::new(), + password: None + })) + } + + /// Get the public/private key pair for the given public key and key type. + fn get_additional_pair( + &self, + public: &Pair::Public, + key_type: KeyTypeId, + ) -> Result> { + let key = (key_type, public.to_raw_vec()); + self.additional + .get(&key) + .map(|bytes| Pair::from_seed_slice(bytes).map_err(|_| Error::InvalidSeed)) + .transpose() + } + + /// Insert the given public/private key pair with the given key type. + /// + /// Does not place it into the file system store. + fn insert_ephemeral_pair(&mut self, pair: &Pair, key_type: KeyTypeId) { + let key = (key_type, pair.public().to_raw_vec()); + self.additional.insert(key, pair.to_raw_vec()); + } + + /// Insert a new key with anonymous crypto. + /// + /// Places it into the file system store. + fn insert_unknown(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<()> { + if let Some(path) = self.key_file_path(public, key_type) { + let mut file = File::create(path).map_err(Error::Io)?; + serde_json::to_writer(&file, &suri).map_err(Error::Json)?; + file.flush().map_err(Error::Io)?; + } + Ok(()) + } + + /// Insert a new key. + /// + /// Places it into the file system store. + pub fn insert_by_type(&self, key_type: KeyTypeId, suri: &str) -> Result { + let pair = Pair::from_string( + suri, + self.password.as_ref().map(|p| &***p) + ).map_err(|_| Error::InvalidSeed)?; + self.insert_unknown(key_type, suri, pair.public().as_slice()) + .map_err(|_| Error::Unavailable)?; + Ok(pair) + } + + /// Insert a new key. + /// + /// Places it into the file system store. + pub fn insert(&self, suri: &str) -> Result { + self.insert_by_type::(Pair::ID, suri).map(Into::into) + } + + /// Generate a new key. + /// + /// Places it into the file system store. + pub fn generate_by_type(&self, key_type: KeyTypeId) -> Result { + let (pair, phrase, _) = Pair::generate_with_phrase(self.password.as_ref().map(|p| &***p)); + if let Some(path) = self.key_file_path(pair.public().as_slice(), key_type) { + let mut file = File::create(path)?; + serde_json::to_writer(&file, &phrase)?; + file.flush()?; + } + Ok(pair) + } + + /// Generate a new key. + /// + /// Places it into the file system store. + pub fn generate(&self) -> Result { + self.generate_by_type::(Pair::ID).map(Into::into) + } + + /// Create a new key from seed. + /// + /// Does not place it into the file system store. + pub fn insert_ephemeral_from_seed_by_type( + &mut self, + seed: &str, + key_type: KeyTypeId, + ) -> Result { + let pair = Pair::from_string(seed, None).map_err(|_| Error::InvalidSeed)?; + self.insert_ephemeral_pair(&pair, key_type); + Ok(pair) + } + + /// Create a new key from seed. + /// + /// Does not place it into the file system store. + pub fn insert_ephemeral_from_seed(&mut self, seed: &str) -> Result { + self.insert_ephemeral_from_seed_by_type::(seed, Pair::ID).map(Into::into) + } + + /// Get a key pair for the given public key and key type. + pub fn key_pair_by_type(&self, + public: &Pair::Public, + key_type: KeyTypeId, + ) -> Result { + if let Some(pair) = self.get_additional_pair(public, key_type)? { + return Ok(pair) + } + + let path = self.key_file_path(public.as_slice(), key_type) + .ok_or_else(|| Error::Unavailable)?; + let file = File::open(path)?; + + let phrase: String = serde_json::from_reader(&file)?; + let pair = Pair::from_string( + &phrase, + self.password.as_ref().map(|p| &***p), + ).map_err(|_| Error::InvalidPhrase)?; + + if &pair.public() == public { + Ok(pair) + } else { + Err(Error::InvalidPassword) + } + } + + /// Get a key pair for the given public key. + pub fn key_pair(&self, public: &::Public) -> Result { + self.key_pair_by_type::(IsWrappedBy::from_ref(public), Pair::ID).map(Into::into) + } + + /// Get public keys of all stored keys that match the given key type. + pub fn public_keys_by_type(&self, key_type: KeyTypeId) -> Result> { + let mut public_keys: Vec = self.additional.keys() + .filter_map(|(ty, public)| { + if *ty == key_type { + Some(TPublic::from_slice(public)) + } else { + None + } + }) + .collect(); + + if let Some(path) = &self.path { + for entry in fs::read_dir(&path)? { + let entry = entry?; + let path = entry.path(); + + // skip directories and non-unicode file names (hex is unicode) + if let Some(name) = path.file_name().and_then(|n| n.to_str()) { + match hex::decode(name) { + Ok(ref hex) if hex.len() > 4 => { + if &hex[0..4] != &key_type.0 { continue } + let public = TPublic::from_slice(&hex[4..]); + public_keys.push(public); + } + _ => continue, + } + } + } + } + + Ok(public_keys) + } + + /// Get public keys of all stored keys that match the key type. + /// + /// This will just use the type of the public key (a list of which to be returned) in order + /// to determine the key type. Unless you use a specialised application-type public key, then + /// this only give you keys registered under generic cryptography, and will not return keys + /// registered under the application type. + pub fn public_keys(&self) -> Result> { + self.public_keys_by_type::(Public::ID) + .map(|v| v.into_iter().map(Into::into).collect()) + } + + /// Returns the file path for the given public key and key type. + fn key_file_path(&self, public: &[u8], key_type: KeyTypeId) -> Option { + let mut buf = self.path.as_ref()?.clone(); + let key_type = hex::encode(key_type.0); + let key = hex::encode(public); + buf.push(key_type + key.as_str()); + Some(buf) + } +} + +impl BareCryptoStore for Store { + fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec { + self.public_keys_by_type::(key_type).unwrap_or_default() + } + + fn sr25519_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> std::result::Result { + let pair = match seed { + Some(seed) => self.insert_ephemeral_from_seed_by_type::(seed, id), + None => self.generate_by_type::(id), + }.map_err(|e| e.to_string())?; + + Ok(pair.public()) + } + + fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option { + self.key_pair_by_type::(pub_key, id).ok() + } + + fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec { + self.public_keys_by_type::(key_type).unwrap_or_default() + } + + fn ed25519_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> std::result::Result { + let pair = match seed { + Some(seed) => self.insert_ephemeral_from_seed_by_type::(seed, id), + None => self.generate_by_type::(id), + }.map_err(|e| e.to_string())?; + + Ok(pair.public()) + } + + fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option { + self.key_pair_by_type::(pub_key, id).ok() + } + + fn insert_unknown(&mut self, key_type: KeyTypeId, suri: &str, public: &[u8]) + -> std::result::Result<(), ()> + { + Store::insert_unknown(self, key_type, suri, public).map_err(|_| ()) + } + + fn password(&self) -> Option<&str> { + self.password.as_ref().map(|x| x.as_str()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::TempDir; + use sp_core::{testing::{SR25519}, crypto::{Ss58Codec}}; + + #[test] + fn basic_store() { + let temp_dir = TempDir::new().unwrap(); + let store = Store::open(temp_dir.path(), None).unwrap(); + + assert!(store.read().public_keys::().unwrap().is_empty()); + + let key: ed25519::AppPair = store.write().generate().unwrap(); + let key2: ed25519::AppPair = store.read().key_pair(&key.public()).unwrap(); + + assert_eq!(key.public(), key2.public()); + + assert_eq!(store.read().public_keys::().unwrap()[0], key.public()); + } + + #[test] + fn test_insert_ephemeral_from_seed() { + let temp_dir = TempDir::new().unwrap(); + let store = Store::open(temp_dir.path(), None).unwrap(); + + let pair: ed25519::AppPair = store + .write() + .insert_ephemeral_from_seed("0x3d97c819d68f9bafa7d6e79cb991eebcd77d966c5334c0b94d9e1fa7ad0869dc") + .unwrap(); + assert_eq!( + "5DKUrgFqCPV8iAXx9sjy1nyBygQCeiUYRFWurZGhnrn3HJCA", + pair.public().to_ss58check() + ); + + drop(store); + let store = Store::open(temp_dir.path(), None).unwrap(); + // Keys generated from seed should not be persisted! + assert!(store.read().key_pair::(&pair.public()).is_err()); + } + + #[test] + fn password_being_used() { + let password = String::from("password"); + let temp_dir = TempDir::new().unwrap(); + let store = Store::open(temp_dir.path(), Some(password.clone().into())).unwrap(); + + let pair: ed25519::AppPair = store.write().generate().unwrap(); + assert_eq!( + pair.public(), + store.read().key_pair::(&pair.public()).unwrap().public(), + ); + + // Without the password the key should not be retrievable + let store = Store::open(temp_dir.path(), None).unwrap(); + assert!(store.read().key_pair::(&pair.public()).is_err()); + + let store = Store::open(temp_dir.path(), Some(password.into())).unwrap(); + assert_eq!( + pair.public(), + store.read().key_pair::(&pair.public()).unwrap().public(), + ); + } + + #[test] + fn public_keys_are_returned() { + let temp_dir = TempDir::new().unwrap(); + let store = Store::open(temp_dir.path(), None).unwrap(); + + let mut public_keys = Vec::new(); + for i in 0..10 { + public_keys.push(store.write().generate::().unwrap().public()); + public_keys.push(store.write().insert_ephemeral_from_seed::( + &format!("0x3d97c819d68f9bafa7d6e79cb991eebcd7{}d966c5334c0b94d9e1fa7ad0869dc", i), + ).unwrap().public()); + } + + // Generate a key of a different type + store.write().generate::().unwrap(); + + public_keys.sort(); + let mut store_pubs = store.read().public_keys::().unwrap(); + store_pubs.sort(); + + assert_eq!(public_keys, store_pubs); + } + + #[test] + fn store_unknown_and_extract_it() { + let temp_dir = TempDir::new().unwrap(); + let store = Store::open(temp_dir.path(), None).unwrap(); + + let secret_uri = "//Alice"; + let key_pair = sr25519::AppPair::from_string(secret_uri, None).expect("Generates key pair"); + + store.write().insert_unknown( + SR25519, + secret_uri, + key_pair.public().as_ref(), + ).expect("Inserts unknown key"); + + let store_key_pair = store.read().key_pair_by_type::( + &key_pair.public(), + SR25519, + ).expect("Gets key pair from keystore"); + + assert_eq!(key_pair.public(), store_key_pair.public()); + } + + #[test] + fn store_ignores_files_with_invalid_name() { + let temp_dir = TempDir::new().unwrap(); + let store = Store::open(temp_dir.path(), None).unwrap(); + + let file_name = temp_dir.path().join(hex::encode(&SR25519.0[..2])); + fs::write(file_name, "test").expect("Invalid file is written"); + + assert!( + store.read().public_keys_by_type::(SR25519).unwrap().is_empty(), + ); + } +} diff --git a/client/network-gossip/Cargo.toml b/client/network-gossip/Cargo.toml new file mode 100644 index 0000000000000..cf8d31c6d36e5 --- /dev/null +++ b/client/network-gossip/Cargo.toml @@ -0,0 +1,18 @@ +[package] +description = "Gossiping for the Substrate network protocol" +name = "sc-network-gossip" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4.8" +futures01 = { package = "futures", version = "0.1.29" } +futures = { version = "0.3.1", features = ["compat"] } +futures-timer = "0.4.0" +lru = "0.1.2" +libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["libp2p-websocket"] } +sc-network = { version = "0.8", path = "../network" } +parking_lot = "0.9.0" +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } diff --git a/client/network-gossip/src/bridge.rs b/client/network-gossip/src/bridge.rs new file mode 100644 index 0000000000000..2b0b19b876166 --- /dev/null +++ b/client/network-gossip/src/bridge.rs @@ -0,0 +1,232 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::{Network, Validator}; +use crate::state_machine::{ConsensusGossip, TopicNotification}; + +use sc_network::message::generic::ConsensusMessage; +use sc_network::{Event, ReputationChange}; + +use futures::{prelude::*, channel::mpsc, compat::Compat01As03, task::SpawnExt as _}; +use libp2p::PeerId; +use parking_lot::Mutex; +use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; +use std::{sync::Arc, time::Duration}; + +/// Wraps around an implementation of the `Network` crate and provides gossiping capabilities on +/// top of it. +pub struct GossipEngine { + inner: Arc>>, + engine_id: ConsensusEngineId, +} + +struct GossipEngineInner { + state_machine: ConsensusGossip, + network: Box + Send>, +} + +impl GossipEngine { + /// Create a new instance. + pub fn new + Send + Clone + 'static>( + mut network: N, + executor: &impl futures::task::Spawn, + engine_id: ConsensusEngineId, + validator: Arc>, + ) -> Self where B: 'static { + let mut state_machine = ConsensusGossip::new(); + + // We grab the event stream before registering the notifications protocol, otherwise we + // might miss events. + let event_stream = network.event_stream(); + + network.register_notifications_protocol(engine_id); + state_machine.register_validator(&mut network, engine_id, validator); + + let inner = Arc::new(Mutex::new(GossipEngineInner { + state_machine, + network: Box::new(network), + })); + + let gossip_engine = GossipEngine { + inner: inner.clone(), + engine_id, + }; + + let res = executor.spawn({ + let inner = Arc::downgrade(&inner); + async move { + loop { + let _ = futures_timer::Delay::new(Duration::from_millis(1100)).await; + if let Some(inner) = inner.upgrade() { + let mut inner = inner.lock(); + let inner = &mut *inner; + inner.state_machine.tick(&mut *inner.network); + } else { + // We reach this branch if the `Arc` has no reference + // left. We can now let the task end. + break; + } + } + } + }); + + // Note: we consider the chances of an error to spawn a background task almost null. + if res.is_err() { + log::error!(target: "gossip", "Failed to spawn background task"); + } + + let res = executor.spawn(async move { + let mut stream = Compat01As03::new(event_stream); + while let Some(Ok(event)) = stream.next().await { + match event { + Event::NotificationStreamOpened { remote, engine_id: msg_engine_id, roles } => { + if msg_engine_id != engine_id { + continue; + } + let mut inner = inner.lock(); + let inner = &mut *inner; + inner.state_machine.new_peer(&mut *inner.network, remote, roles); + } + Event::NotificationsStreamClosed { remote, engine_id: msg_engine_id } => { + if msg_engine_id != engine_id { + continue; + } + let mut inner = inner.lock(); + let inner = &mut *inner; + inner.state_machine.peer_disconnected(&mut *inner.network, remote); + }, + Event::NotificationsReceived { remote, messages } => { + let mut inner = inner.lock(); + let inner = &mut *inner; + inner.state_machine.on_incoming( + &mut *inner.network, + remote, + messages.into_iter() + .filter_map(|(engine, data)| if engine == engine_id { + Some(ConsensusMessage { engine_id: engine, data: data.to_vec() }) + } else { None }) + .collect() + ); + }, + Event::Dht(_) => {} + } + } + }); + + // Note: we consider the chances of an error to spawn a background task almost null. + if res.is_err() { + log::error!(target: "gossip", "Failed to spawn background task"); + } + + gossip_engine + } + + pub fn report(&self, who: PeerId, reputation: ReputationChange) { + self.inner.lock().network.report_peer(who, reputation); + } + + /// Registers a message without propagating it to any peers. The message + /// becomes available to new peers or when the service is asked to gossip + /// the message's topic. No validation is performed on the message, if the + /// message is already expired it should be dropped on the next garbage + /// collection. + pub fn register_gossip_message( + &self, + topic: B::Hash, + message: Vec, + ) { + let message = ConsensusMessage { + engine_id: self.engine_id, + data: message, + }; + + self.inner.lock().state_machine.register_message(topic, message); + } + + /// Broadcast all messages with given topic. + pub fn broadcast_topic(&self, topic: B::Hash, force: bool) { + let mut inner = self.inner.lock(); + let inner = &mut *inner; + inner.state_machine.broadcast_topic(&mut *inner.network, topic, force); + } + + /// Get data of valid, incoming messages for a topic (but might have expired meanwhile). + pub fn messages_for(&self, topic: B::Hash) + -> mpsc::UnboundedReceiver + { + self.inner.lock().state_machine.messages_for(self.engine_id, topic) + } + + /// Send all messages with given topic to a peer. + pub fn send_topic( + &self, + who: &PeerId, + topic: B::Hash, + force: bool + ) { + let mut inner = self.inner.lock(); + let inner = &mut *inner; + inner.state_machine.send_topic(&mut *inner.network, who, topic, self.engine_id, force) + } + + /// Multicast a message to all peers. + pub fn gossip_message( + &self, + topic: B::Hash, + message: Vec, + force: bool, + ) { + let message = ConsensusMessage { + engine_id: self.engine_id, + data: message, + }; + + let mut inner = self.inner.lock(); + let inner = &mut *inner; + inner.state_machine.multicast(&mut *inner.network, topic, message, force) + } + + /// Send addressed message to the given peers. The message is not kept or multicast + /// later on. + pub fn send_message(&self, who: Vec, data: Vec) { + let mut inner = self.inner.lock(); + let inner = &mut *inner; + + for who in &who { + inner.state_machine.send_message(&mut *inner.network, who, ConsensusMessage { + engine_id: self.engine_id, + data: data.clone(), + }); + } + } + + /// Notify everyone we're connected to that we have the given block. + /// + /// Note: this method isn't strictly related to gossiping and should eventually be moved + /// somewhere else. + pub fn announce(&self, block: B::Hash, associated_data: Vec) { + self.inner.lock().network.announce(block, associated_data); + } +} + +impl Clone for GossipEngine { + fn clone(&self) -> Self { + GossipEngine { + inner: self.inner.clone(), + engine_id: self.engine_id.clone(), + } + } +} diff --git a/client/network-gossip/src/lib.rs b/client/network-gossip/src/lib.rs new file mode 100644 index 0000000000000..705a27210ac53 --- /dev/null +++ b/client/network-gossip/src/lib.rs @@ -0,0 +1,126 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Polite gossiping. +//! +//! This crate provides gossiping capabilities on top of a network. +//! +//! Gossip messages are separated by two categories: "topics" and consensus engine ID. +//! The consensus engine ID is sent over the wire with the message, while the topic is not, +//! with the expectation that the topic can be derived implicitly from the content of the +//! message, assuming it is valid. +//! +//! Topics are a single 32-byte tag associated with a message, used to group those messages +//! in an opaque way. Consensus code can invoke `broadcast_topic` to attempt to send all messages +//! under a single topic to all peers who don't have them yet, and `send_topic` to +//! send all messages under a single topic to a specific peer. +//! +//! # Usage +//! +//! - Implement the `Network` trait, representing the low-level networking primitives. It is +//! already implemented on `sc_network::NetworkService`. +//! - Implement the `Validator` trait. See the section below. +//! - Decide on a `ConsensusEngineId`. Each gossiping protocol should have a different one. +//! - Build a `GossipEngine` using these three elements. +//! - Use the methods of the `GossipEngine` in order to send out messages and receive incoming +//! messages. +//! +//! # What is a validator? +//! +//! The primary role of a `Validator` is to process incoming messages from peers, and decide +//! whether to discard them or process them. It also decides whether to re-broadcast the message. +//! +//! The secondary role of the `Validator` is to check if a message is allowed to be sent to a given +//! peer. All messages, before being sent, will be checked against this filter. +//! This enables the validator to use information it's aware of about connected peers to decide +//! whether to send messages to them at any given moment in time - In particular, to wait until +//! peers can accept and process the message before sending it. +//! +//! Lastly, the fact that gossip validators can decide not to rebroadcast messages +//! opens the door for neighbor status packets to be baked into the gossip protocol. +//! These status packets will typically contain light pieces of information +//! used to inform peers of a current view of protocol state. + +pub use self::bridge::GossipEngine; +pub use self::state_machine::TopicNotification; +pub use self::validator::{DiscardAll, MessageIntent, Validator, ValidatorContext, ValidationResult}; + +use futures::prelude::*; +use sc_network::{specialization::NetworkSpecialization, Event, ExHashT, NetworkService, PeerId, ReputationChange}; +use sp_runtime::{traits::Block as BlockT, ConsensusEngineId}; +use std::sync::Arc; + +mod bridge; +mod state_machine; +mod validator; + +/// Abstraction over a network. +pub trait Network { + /// Returns a stream of events representing what happens on the network. + fn event_stream(&self) -> Box + Send>; + + /// Adjust the reputation of a node. + fn report_peer(&self, peer_id: PeerId, reputation: ReputationChange); + + /// Force-disconnect a peer. + fn disconnect_peer(&self, who: PeerId); + + /// Send a notification to a peer. + fn write_notification(&self, who: PeerId, engine_id: ConsensusEngineId, message: Vec); + + /// Registers a notifications protocol. + /// + /// See the documentation of [`NetworkService:register_notifications_protocol`] for more information. + fn register_notifications_protocol( + &self, + engine_id: ConsensusEngineId + ); + + /// Notify everyone we're connected to that we have the given block. + /// + /// Note: this method isn't strictly related to gossiping and should eventually be moved + /// somewhere else. + fn announce(&self, block: B::Hash, associated_data: Vec); +} + +impl, H: ExHashT> Network for Arc> { + fn event_stream(&self) -> Box + Send> { + Box::new(NetworkService::event_stream(self).map(|v| Ok::<_, ()>(v)).compat()) + } + + fn report_peer(&self, peer_id: PeerId, reputation: ReputationChange) { + NetworkService::report_peer(self, peer_id, reputation); + } + + fn disconnect_peer(&self, who: PeerId) { + NetworkService::disconnect_peer(self, who) + } + + fn write_notification(&self, who: PeerId, engine_id: ConsensusEngineId, message: Vec) { + NetworkService::write_notification(self, who, engine_id, message) + } + + fn register_notifications_protocol( + &self, + engine_id: ConsensusEngineId, + ) { + NetworkService::register_notifications_protocol(self, engine_id) + } + + fn announce(&self, block: B::Hash, associated_data: Vec) { + NetworkService::announce_block(self, block, associated_data) + } +} diff --git a/client/network-gossip/src/state_machine.rs b/client/network-gossip/src/state_machine.rs new file mode 100644 index 0000000000000..d1931b1bd29d8 --- /dev/null +++ b/client/network-gossip/src/state_machine.rs @@ -0,0 +1,644 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::{Network, MessageIntent, Validator, ValidatorContext, ValidationResult}; + +use std::collections::{HashMap, HashSet, hash_map::Entry}; +use std::sync::Arc; +use std::iter; +use std::time; +use log::{trace, debug}; +use futures::channel::mpsc; +use lru::LruCache; +use libp2p::PeerId; +use sp_runtime::traits::{Block as BlockT, Hash, HashFor}; +use sp_runtime::ConsensusEngineId; +pub use sc_network::message::generic::{Message, ConsensusMessage}; +use sc_network::config::Roles; + +// FIXME: Add additional spam/DoS attack protection: https://github.com/paritytech/substrate/issues/1115 +const KNOWN_MESSAGES_CACHE_SIZE: usize = 4096; + +const REBROADCAST_INTERVAL: time::Duration = time::Duration::from_secs(30); + +mod rep { + use sc_network::ReputationChange as Rep; + /// Reputation change when a peer sends us a gossip message that we didn't know about. + pub const GOSSIP_SUCCESS: Rep = Rep::new(1 << 4, "Successfull gossip"); + /// Reputation change when a peer sends us a gossip message that we already knew about. + pub const DUPLICATE_GOSSIP: Rep = Rep::new(-(1 << 2), "Duplicate gossip"); + /// Reputation change when a peer sends us a gossip message for an unknown engine, whatever that + /// means. + pub const UNKNOWN_GOSSIP: Rep = Rep::new(-(1 << 6), "Unknown gossup message engine id"); + /// Reputation change when a peer sends a message from a topic it isn't registered on. + pub const UNREGISTERED_TOPIC: Rep = Rep::new(-(1 << 10), "Unregistered gossip message topic"); +} + +struct PeerConsensus { + known_messages: HashSet, + roles: Roles, +} + +/// Topic stream message with sender. +#[derive(Debug, Eq, PartialEq)] +pub struct TopicNotification { + /// Message data. + pub message: Vec, + /// Sender if available. + pub sender: Option, +} + +struct MessageEntry { + message_hash: B::Hash, + topic: B::Hash, + message: ConsensusMessage, + sender: Option, +} + +/// Local implementation of `ValidatorContext`. +struct NetworkContext<'g, 'p, B: BlockT> { + gossip: &'g mut ConsensusGossip, + network: &'p mut dyn Network, + engine_id: ConsensusEngineId, +} + +impl<'g, 'p, B: BlockT> ValidatorContext for NetworkContext<'g, 'p, B> { + /// Broadcast all messages with given topic to peers that do not have it yet. + fn broadcast_topic(&mut self, topic: B::Hash, force: bool) { + self.gossip.broadcast_topic(self.network, topic, force); + } + + /// Broadcast a message to all peers that have not received it previously. + fn broadcast_message(&mut self, topic: B::Hash, message: Vec, force: bool) { + self.gossip.multicast( + self.network, + topic, + ConsensusMessage{ data: message, engine_id: self.engine_id.clone() }, + force, + ); + } + + /// Send addressed message to a peer. + fn send_message(&mut self, who: &PeerId, message: Vec) { + self.network.write_notification(who.clone(), self.engine_id, message); + } + + /// Send all messages with given topic to a peer. + fn send_topic(&mut self, who: &PeerId, topic: B::Hash, force: bool) { + self.gossip.send_topic(self.network, who, topic, self.engine_id, force); + } +} + +fn propagate<'a, B: BlockT, I>( + network: &mut dyn Network, + messages: I, + intent: MessageIntent, + peers: &mut HashMap>, + validators: &HashMap>>, +) + // (msg_hash, topic, message) + where I: Clone + IntoIterator, +{ + let mut check_fns = HashMap::new(); + let mut message_allowed = move |who: &PeerId, intent: MessageIntent, topic: &B::Hash, message: &ConsensusMessage| { + let engine_id = 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 false, // treat all messages with no validator as not allowed + Some(validator) => vacant.insert(validator.message_allowed()), + } + }; + + (check_fn)(who, intent, topic, &message.data) + }; + + for (id, ref mut peer) in peers.iter_mut() { + for (message_hash, topic, message) in messages.clone() { + let intent = match intent { + MessageIntent::Broadcast { .. } => + if peer.known_messages.contains(&message_hash) { + continue; + } else { + MessageIntent::Broadcast + }, + MessageIntent::PeriodicRebroadcast => + if peer.known_messages.contains(&message_hash) { + MessageIntent::PeriodicRebroadcast + } else { + // peer doesn't know message, so the logic should treat it as an + // initial broadcast. + MessageIntent::Broadcast + }, + other => other, + }; + + if !message_allowed(id, intent, &topic, &message) { + continue; + } + + peer.known_messages.insert(message_hash.clone()); + + trace!(target: "gossip", "Propagating to {}: {:?}", id, message); + network.write_notification(id.clone(), message.engine_id, message.data.clone()); + } + } +} + +/// Consensus network protocol handler. Manages statements and candidate requests. +pub struct ConsensusGossip { + peers: HashMap>, + live_message_sinks: HashMap<(ConsensusEngineId, B::Hash), Vec>>, + messages: Vec>, + known_messages: LruCache, + validators: HashMap>>, + next_broadcast: time::Instant, +} + +impl ConsensusGossip { + /// Create a new instance. + pub fn new() -> Self { + ConsensusGossip { + peers: HashMap::new(), + live_message_sinks: HashMap::new(), + messages: Default::default(), + known_messages: LruCache::new(KNOWN_MESSAGES_CACHE_SIZE), + validators: Default::default(), + next_broadcast: time::Instant::now() + REBROADCAST_INTERVAL, + } + } + + /// Register message validator for a message type. + pub fn register_validator( + &mut self, + network: &mut dyn Network, + engine_id: ConsensusEngineId, + validator: Arc> + ) { + self.register_validator_internal(engine_id, validator.clone()); + let peers: Vec<_> = self.peers.iter().map(|(id, peer)| (id.clone(), peer.roles)).collect(); + for (id, roles) in peers { + let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() }; + validator.new_peer(&mut context, &id, roles); + } + } + + fn register_validator_internal(&mut self, engine_id: ConsensusEngineId, validator: Arc>) { + self.validators.insert(engine_id, validator.clone()); + } + + /// Handle new connected peer. + pub fn new_peer(&mut self, network: &mut dyn Network, who: PeerId, roles: Roles) { + // light nodes are not valid targets for consensus gossip messages + if !roles.is_full() { + return; + } + + trace!(target:"gossip", "Registering {:?} {}", roles, who); + self.peers.insert(who.clone(), PeerConsensus { + known_messages: HashSet::new(), + roles, + }); + for (engine_id, v) in self.validators.clone() { + let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() }; + v.new_peer(&mut context, &who, roles); + } + } + + fn register_message_hashed( + &mut self, + message_hash: B::Hash, + topic: B::Hash, + message: ConsensusMessage, + sender: Option, + ) { + if self.known_messages.put(message_hash.clone(), ()).is_none() { + self.messages.push(MessageEntry { + message_hash, + topic, + message, + sender, + }); + } + } + + /// Registers a message without propagating it to any peers. The message + /// becomes available to new peers or when the service is asked to gossip + /// the message's topic. No validation is performed on the message, if the + /// message is already expired it should be dropped on the next garbage + /// collection. + pub fn register_message( + &mut self, + topic: B::Hash, + message: ConsensusMessage, + ) { + let message_hash = HashFor::::hash(&message.data[..]); + self.register_message_hashed(message_hash, topic, message, None); + } + + /// Call when a peer has been disconnected to stop tracking gossip status. + pub fn peer_disconnected(&mut self, network: &mut dyn Network, who: PeerId) { + for (engine_id, v) in self.validators.clone() { + let mut context = NetworkContext { gossip: self, network, engine_id: engine_id.clone() }; + v.peer_disconnected(&mut context, &who); + } + } + + /// Perform periodic maintenance + pub fn tick(&mut self, network: &mut dyn Network) { + self.collect_garbage(); + if time::Instant::now() >= self.next_broadcast { + self.rebroadcast(network); + self.next_broadcast = time::Instant::now() + REBROADCAST_INTERVAL; + } + } + + /// Rebroadcast all messages to all peers. + fn rebroadcast(&mut self, network: &mut dyn Network) { + let messages = self.messages.iter() + .map(|entry| (&entry.message_hash, &entry.topic, &entry.message)); + propagate(network, messages, MessageIntent::PeriodicRebroadcast, &mut self.peers, &self.validators); + } + + /// Broadcast all messages with given topic. + pub fn broadcast_topic(&mut self, network: &mut dyn Network, topic: B::Hash, force: bool) { + let messages = self.messages.iter() + .filter_map(|entry| + if entry.topic == topic { Some((&entry.message_hash, &entry.topic, &entry.message)) } else { None } + ); + let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; + propagate(network, messages, intent, &mut self.peers, &self.validators); + } + + /// Prune old or no longer relevant consensus messages. Provide a predicate + /// for pruning, which returns `false` when the items with a given topic should be pruned. + pub fn collect_garbage(&mut self) { + self.live_message_sinks.retain(|_, sinks| { + sinks.retain(|sink| !sink.is_closed()); + !sinks.is_empty() + }); + + let known_messages = &mut self.known_messages; + let before = self.messages.len(); + let validators = &self.validators; + + let mut check_fns = HashMap::new(); + let mut message_expired = move |entry: &MessageEntry| { + let engine_id = entry.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| !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| known_messages.contains(h)); + } + } + + /// 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_mut() + .filter(|e| e.topic == topic && e.message.engine_id == engine_id) + { + tx.unbounded_send(TopicNotification { + message: entry.message.data.clone(), + sender: entry.sender.clone(), + }) + .expect("receiver known to be live; qed"); + } + + self.live_message_sinks.entry((engine_id, topic)).or_default().push(tx); + + rx + } + + /// Handle an incoming ConsensusMessage for topic by who via protocol. Discard message if topic + /// already known, the message is old, its source peers isn't a registered peer or the connection + /// to them is broken. Return `Some(topic, message)` if it was added to the internal queue, `None` + /// in all other cases. + pub fn on_incoming( + &mut self, + network: &mut dyn Network, + who: PeerId, + messages: Vec, + ) { + trace!(target:"gossip", "Received {} messages from peer {}", messages.len(), who); + for message in messages { + let message_hash = HashFor::::hash(&message.data[..]); + + if self.known_messages.contains(&message_hash) { + trace!(target:"gossip", "Ignored already known message from {}", who); + network.report_peer(who.clone(), rep::DUPLICATE_GOSSIP); + continue; + } + + let engine_id = message.engine_id; + // validate the message + let validation = self.validators.get(&engine_id) + .cloned() + .map(|v| { + let mut context = NetworkContext { gossip: self, network, engine_id }; + v.validate(&mut context, &who, &message.data) + }); + + let validation_result = match validation { + Some(ValidationResult::ProcessAndKeep(topic)) => Some((topic, true)), + Some(ValidationResult::ProcessAndDiscard(topic)) => Some((topic, false)), + Some(ValidationResult::Discard) => None, + None => { + trace!(target:"gossip", "Unknown message engine id {:?} from {}", engine_id, who); + network.report_peer(who.clone(), rep::UNKNOWN_GOSSIP); + network.disconnect_peer(who.clone()); + continue; + } + }; + + if let Some((topic, keep)) = validation_result { + network.report_peer(who.clone(), rep::GOSSIP_SUCCESS); + if let Some(ref mut peer) = self.peers.get_mut(&who) { + peer.known_messages.insert(message_hash); + if let Entry::Occupied(mut entry) = self.live_message_sinks.entry((engine_id, topic)) { + debug!(target: "gossip", "Pushing consensus message to sinks for {}.", topic); + entry.get_mut().retain(|sink| { + if let Err(e) = sink.unbounded_send(TopicNotification { + message: message.data.clone(), + sender: Some(who.clone()) + }) { + trace!(target: "gossip", "Error broadcasting message notification: {:?}", e); + } + !sink.is_closed() + }); + if entry.get().is_empty() { + entry.remove_entry(); + } + } + if keep { + self.register_message_hashed(message_hash, topic, message, Some(who.clone())); + } + } else { + trace!(target:"gossip", "Ignored statement from unregistered peer {}", who); + network.report_peer(who.clone(), rep::UNREGISTERED_TOPIC); + } + } else { + trace!(target:"gossip", "Handled valid one hop message from peer {}", who); + } + } + } + + /// Send all messages with given topic to a peer. + pub fn send_topic( + &mut self, + network: &mut dyn Network, + who: &PeerId, + topic: B::Hash, + engine_id: ConsensusEngineId, + force: bool + ) { + let validator = self.validators.get(&engine_id); + let mut message_allowed = match validator { + None => return, // treat all messages with no validator as not allowed + Some(validator) => validator.message_allowed(), + }; + + if let Some(ref mut peer) = self.peers.get_mut(who) { + for entry in self.messages.iter().filter(|m| m.topic == topic && m.message.engine_id == engine_id) { + let intent = if force { + MessageIntent::ForcedBroadcast + } else { + MessageIntent::Broadcast + }; + + if !force && peer.known_messages.contains(&entry.message_hash) { + continue; + } + + if !message_allowed(who, intent, &entry.topic, &entry.message.data) { + continue; + } + + peer.known_messages.insert(entry.message_hash.clone()); + + trace!(target: "gossip", "Sending topic message to {}: {:?}", who, entry.message); + network.write_notification(who.clone(), engine_id, entry.message.data.clone()); + } + } + } + + /// Multicast a message to all peers. + pub fn multicast( + &mut self, + network: &mut dyn Network, + topic: B::Hash, + message: ConsensusMessage, + force: bool, + ) { + let message_hash = HashFor::::hash(&message.data); + self.register_message_hashed(message_hash, topic, message.clone(), None); + let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; + propagate(network, iter::once((&message_hash, &topic, &message)), intent, &mut self.peers, &self.validators); + } + + /// Send addressed message to a peer. The message is not kept or multicast + /// later on. + pub fn send_message( + &mut self, + network: &mut dyn Network, + who: &PeerId, + message: ConsensusMessage, + ) { + let peer = match self.peers.get_mut(who) { + None => return, + Some(peer) => peer, + }; + + let message_hash = HashFor::::hash(&message.data); + + trace!(target: "gossip", "Sending direct to {}: {:?}", who, message); + + peer.known_messages.insert(message_hash); + network.write_notification(who.clone(), message.engine_id, message.data); + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + use sp_runtime::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; + use futures::executor::block_on_stream; + + use super::*; + + type Block = RawBlock>; + + macro_rules! push_msg { + ($consensus:expr, $topic:expr, $hash: expr, $m:expr) => { + if $consensus.known_messages.put($hash, ()).is_none() { + $consensus.messages.push(MessageEntry { + message_hash: $hash, + topic: $topic, + message: ConsensusMessage { data: $m, engine_id: [0, 0, 0, 0]}, + sender: None, + }); + } + } + } + + struct AllowAll; + impl Validator for AllowAll { + fn validate( + &self, + _context: &mut dyn ValidatorContext, + _sender: &PeerId, + _data: &[u8], + ) -> ValidationResult { + ValidationResult::ProcessAndKeep(H256::default()) + } + } + + #[test] + fn collects_garbage() { + struct AllowOne; + impl Validator for AllowOne { + fn validate( + &self, + _context: &mut dyn ValidatorContext, + _sender: &PeerId, + data: &[u8], + ) -> ValidationResult { + if data[0] == 1 { + ValidationResult::ProcessAndKeep(H256::default()) + } else { + ValidationResult::Discard + } + } + + fn message_expired<'a>(&'a self) -> Box bool + 'a> { + Box::new(move |_topic, data| data[0] != 1) + } + } + + let prev_hash = H256::random(); + let best_hash = H256::random(); + let mut consensus = ConsensusGossip::::new(); + let m1_hash = H256::random(); + let m2_hash = H256::random(); + let m1 = vec![1, 2, 3]; + let m2 = vec![4, 5, 6]; + + push_msg!(consensus, prev_hash, m1_hash, m1); + push_msg!(consensus, best_hash, m2_hash, m2); + consensus.known_messages.put(m1_hash, ()); + consensus.known_messages.put(m2_hash, ()); + + let test_engine_id = Default::default(); + consensus.register_validator_internal(test_engine_id, Arc::new(AllowAll)); + consensus.collect_garbage(); + assert_eq!(consensus.messages.len(), 2); + assert_eq!(consensus.known_messages.len(), 2); + + consensus.register_validator_internal(test_engine_id, Arc::new(AllowOne)); + + // m2 is expired + consensus.collect_garbage(); + assert_eq!(consensus.messages.len(), 1); + // known messages are only pruned based on size. + assert_eq!(consensus.known_messages.len(), 2); + assert!(consensus.known_messages.contains(&m2_hash)); + } + + #[test] + fn message_stream_include_those_sent_before_asking_for_stream() { + let mut consensus = ConsensusGossip::::new(); + consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); + + let message = ConsensusMessage { data: vec![4, 5, 6], engine_id: [0, 0, 0, 0] }; + let topic = HashFor::::hash(&[1,2,3]); + + consensus.register_message(topic, message.clone()); + let mut stream = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); + + assert_eq!(stream.next(), Some(TopicNotification { message: message.data, sender: None })); + } + + #[test] + fn can_keep_multiple_messages_per_topic() { + let mut consensus = ConsensusGossip::::new(); + + 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, 0] }; + + consensus.register_message(topic, msg_a); + consensus.register_message(topic, msg_b); + + assert_eq!(consensus.messages.len(), 2); + } + + #[test] + fn can_keep_multiple_subscribers_per_topic() { + let mut consensus = ConsensusGossip::::new(); + consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); + + let data = vec![4, 5, 6]; + let message = ConsensusMessage { data: data.clone(), engine_id: [0, 0, 0, 0] }; + let topic = HashFor::::hash(&[1, 2, 3]); + + consensus.register_message(topic, message.clone()); + + let mut stream1 = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); + let mut stream2 = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); + + assert_eq!(stream1.next(), Some(TopicNotification { message: data.clone(), sender: None })); + assert_eq!(stream2.next(), Some(TopicNotification { message: data, sender: None })); + } + + #[test] + fn topics_are_localized_to_engine_id() { + let mut consensus = ConsensusGossip::::new(); + consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); + + let topic = [1; 32].into(); + let msg_a = 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(topic, msg_a); + consensus.register_message(topic, msg_b); + + let mut stream = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); + + assert_eq!(stream.next(), Some(TopicNotification { message: vec![1, 2, 3], sender: None })); + + let _ = consensus.live_message_sinks.remove(&([0, 0, 0, 0], topic)); + assert_eq!(stream.next(), None); + } +} diff --git a/client/network-gossip/src/validator.rs b/client/network-gossip/src/validator.rs new file mode 100644 index 0000000000000..74b5307ee9cdc --- /dev/null +++ b/client/network-gossip/src/validator.rs @@ -0,0 +1,103 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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 sc_network::{config::Roles, PeerId}; +use sp_runtime::traits::Block as BlockT; + +/// Validates consensus messages. +pub trait Validator: Send + Sync { + /// New peer is connected. + fn new_peer(&self, _context: &mut dyn ValidatorContext, _who: &PeerId, _roles: Roles) { + } + + /// New connection is dropped. + fn peer_disconnected(&self, _context: &mut dyn ValidatorContext, _who: &PeerId) { + } + + /// Validate consensus message. + fn validate( + &self, + context: &mut dyn ValidatorContext, + sender: &PeerId, + 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| false) + } + + /// Produce a closure for filtering egress messages. + fn message_allowed<'a>(&'a self) -> Box bool + 'a> { + Box::new(move |_who, _intent, _topic, _data| true) + } +} + +/// Validation context. Allows reacting to incoming messages by sending out further messages. +pub trait ValidatorContext { + /// Broadcast all messages with given topic to peers that do not have it yet. + fn broadcast_topic(&mut self, topic: B::Hash, force: bool); + /// Broadcast a message to all peers that have not received it previously. + fn broadcast_message(&mut self, topic: B::Hash, message: Vec, force: bool); + /// Send addressed message to a peer. + fn send_message(&mut self, who: &PeerId, message: Vec); + /// Send all messages with given topic to a peer. + fn send_topic(&mut self, who: &PeerId, topic: B::Hash, force: bool); +} + +/// The reason for sending out the message. +#[derive(Eq, PartialEq, Copy, Clone)] +#[cfg_attr(test, derive(Debug))] +pub enum MessageIntent { + /// Requested broadcast. + Broadcast, + /// Requested broadcast to all peers. + ForcedBroadcast, + /// Periodic rebroadcast of all messages to all peers. + PeriodicRebroadcast, +} + +/// Message validation result. +pub enum ValidationResult { + /// Message should be stored and propagated under given topic. + ProcessAndKeep(H), + /// Message should be processed, but not propagated. + ProcessAndDiscard(H), + /// Message should be ignored. + Discard, +} + +/// A gossip message validator that discards all messages. +pub struct DiscardAll; + +impl Validator for DiscardAll { + fn validate( + &self, + _context: &mut dyn ValidatorContext, + _sender: &PeerId, + _data: &[u8], + ) -> ValidationResult { + ValidationResult::Discard + } + + fn message_expired<'a>(&'a self) -> Box bool + 'a> { + Box::new(move |_topic, _data| true) + } + + fn message_allowed<'a>(&'a self) -> Box bool + 'a> { + Box::new(move |_who, _intent, _topic, _data| false) + } +} diff --git a/client/network/Cargo.toml b/client/network/Cargo.toml new file mode 100644 index 0000000000000..d24f986f4cd21 --- /dev/null +++ b/client/network/Cargo.toml @@ -0,0 +1,61 @@ +[package] +description = "Substrate network protocol" +name = "sc-network" +version = "0.8.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +bytes = "0.5.0" +derive_more = "0.99.2" +either = "1.5.3" +log = "0.4.8" +parking_lot = "0.9.0" +bitflags = "1.2.0" +fnv = "1.0.6" +futures = "0.3.1" +futures_codec = "0.3.3" +futures-timer = "0.4.0" +linked-hash-map = "0.5.2" +linked_hash_set = "0.1.3" +lru = "0.4.0" +rustc-hex = "2.0.1" +rand = "0.7.2" +libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["libp2p-websocket"] } +fork-tree = { version = "2.0.0", path = "../../utils/fork-tree" } +sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" } +sc-client = { version = "2.0.0", path = "../" } +sc-client-api = { version = "2.0.0", path = "../api" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-arithmetic = { version = "2.0.0", path = "../../primitives/arithmetic" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sc-block-builder = { version = "2.0.0", path = "../block-builder" } +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } +sc-peerset = { version = "2.0.0", path = "../peerset" } +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.41" +slog = { version = "2.5.2", features = ["nested-values"] } +slog_derive = "0.2.0" +smallvec = "0.6.10" +unsigned-varint = { version = "0.3.0", features = ["codec"] } +sp-keyring = { version = "2.0.0", optional = true, path = "../../primitives/keyring" } +substrate-test-client = { version = "2.0.0", optional = true, path = "../../test-utils/client" } +substrate-test-runtime-client = { version = "2.0.0", optional = true, path = "../../test-utils/runtime/client" } +erased-serde = "0.3.9" +void = "1.0.2" +zeroize = "1.0.0" +sp-consensus-babe = { version = "0.8", path = "../../primitives/consensus/babe" } + +[dev-dependencies] +sp-test-primitives = { version = "2.0.0", path = "../../primitives/test-primitives" } +env_logger = "0.7.0" +sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } +quickcheck = "0.9.0" +rand = "0.7.2" +tempfile = "3.1.0" + +[features] +default = [] +test-helpers = ["sp-keyring", "substrate-test-runtime-client"] diff --git a/client/network/src/behaviour.rs b/client/network/src/behaviour.rs new file mode 100644 index 0000000000000..7cc9eee74d6d5 --- /dev/null +++ b/client/network/src/behaviour.rs @@ -0,0 +1,221 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::{ + debug_info, discovery::DiscoveryBehaviour, discovery::DiscoveryOut, DiscoveryNetBehaviour, + Event, protocol::event::DhtEvent +}; +use crate::{ExHashT, specialization::NetworkSpecialization}; +use crate::protocol::{CustomMessageOutcome, Protocol}; +use libp2p::NetworkBehaviour; +use libp2p::core::{Multiaddr, PeerId, PublicKey}; +use libp2p::kad::record; +use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess}; +use libp2p::core::{nodes::Substream, muxing::StreamMuxerBox}; +use log::{debug, warn}; +use sp_consensus::{BlockOrigin, import_queue::{IncomingBlock, Origin}}; +use sp_runtime::{traits::{Block as BlockT, NumberFor}, Justification}; +use std::{iter, task::Context, task::Poll}; +use void; + +/// General behaviour of the network. Combines all protocols together. +#[derive(NetworkBehaviour)] +#[behaviour(out_event = "BehaviourOut", poll_method = "poll")] +pub struct Behaviour, H: ExHashT> { + /// All the substrate-specific protocols. + substrate: Protocol, + /// Periodically pings and identifies the nodes we are connected to, and store information in a + /// cache. + debug_info: debug_info::DebugInfoBehaviour>, + /// Discovers nodes of the network. + discovery: DiscoveryBehaviour>, + + /// Queue of events to produce for the outside. + #[behaviour(ignore)] + events: Vec>, +} + +/// Event generated by `Behaviour`. +pub enum BehaviourOut { + BlockImport(BlockOrigin, Vec>), + JustificationImport(Origin, B::Hash, NumberFor, Justification), + FinalityProofImport(Origin, B::Hash, NumberFor, Vec), + Event(Event), +} + +impl, H: ExHashT> Behaviour { + /// Builds a new `Behaviour`. + pub async fn new( + substrate: Protocol, + user_agent: String, + local_public_key: PublicKey, + known_addresses: Vec<(PeerId, Multiaddr)>, + enable_mdns: bool, + allow_private_ipv4: bool, + ) -> Self { + Behaviour { + substrate, + debug_info: debug_info::DebugInfoBehaviour::new(user_agent, local_public_key.clone()), + discovery: DiscoveryBehaviour::new( + local_public_key, + known_addresses, + enable_mdns, + allow_private_ipv4 + ).await, + events: Vec::new(), + } + } + + /// Returns the list of nodes that we know exist in the network. + pub fn known_peers(&mut self) -> impl Iterator { + self.discovery.known_peers() + } + + /// Adds a hard-coded address for the given peer, that never expires. + pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) { + self.discovery.add_known_address(peer_id, addr) + } + + /// Borrows `self` and returns a struct giving access to the information about a node. + /// + /// Returns `None` if we don't know anything about this node. Always returns `Some` for nodes + /// we're connected to, meaning that if `None` is returned then we're not connected to that + /// node. + pub fn node(&self, peer_id: &PeerId) -> Option { + self.debug_info.node(peer_id) + } + + /// Returns a shared reference to the user protocol. + pub fn user_protocol(&self) -> &Protocol { + &self.substrate + } + + /// Returns a mutable reference to the user protocol. + pub fn user_protocol_mut(&mut self) -> &mut Protocol { + &mut self.substrate + } + + /// Start querying a record from the DHT. Will later produce either a `ValueFound` or a `ValueNotFound` event. + pub fn get_value(&mut self, key: &record::Key) { + self.discovery.get_value(key); + } + + /// Starts putting a record into DHT. Will later produce either a `ValuePut` or a `ValuePutFailed` event. + pub fn put_value(&mut self, key: record::Key, value: Vec) { + self.discovery.put_value(key, value); + } +} + +impl, H: ExHashT> NetworkBehaviourEventProcess for +Behaviour { + fn inject_event(&mut self, event: void::Void) { + void::unreachable(event) + } +} + +impl, H: ExHashT> NetworkBehaviourEventProcess> for +Behaviour { + fn inject_event(&mut self, event: CustomMessageOutcome) { + match event { + CustomMessageOutcome::BlockImport(origin, blocks) => + self.events.push(BehaviourOut::BlockImport(origin, blocks)), + CustomMessageOutcome::JustificationImport(origin, hash, nb, justification) => + self.events.push(BehaviourOut::JustificationImport(origin, hash, nb, justification)), + CustomMessageOutcome::FinalityProofImport(origin, hash, nb, proof) => + self.events.push(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)), + CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles } => + for engine_id in protocols { + self.events.push(BehaviourOut::Event(Event::NotificationStreamOpened { + remote: remote.clone(), + engine_id, + roles, + })); + }, + CustomMessageOutcome::NotificationsStreamClosed { remote, protocols } => + for engine_id in protocols { + self.events.push(BehaviourOut::Event(Event::NotificationsStreamClosed { + remote: remote.clone(), + engine_id, + })); + }, + CustomMessageOutcome::NotificationsReceived { remote, messages } => { + let ev = Event::NotificationsReceived { remote, messages }; + self.events.push(BehaviourOut::Event(ev)); + }, + CustomMessageOutcome::None => {} + } + } +} + +impl, H: ExHashT> NetworkBehaviourEventProcess + for Behaviour { + fn inject_event(&mut self, event: debug_info::DebugInfoEvent) { + let debug_info::DebugInfoEvent::Identified { peer_id, mut info } = event; + if !info.protocol_version.contains("substrate") { + warn!(target: "sub-libp2p", "Connected to a non-Substrate node: {:?}", info); + } + if info.listen_addrs.len() > 30 { + debug!(target: "sub-libp2p", "Node {:?} has reported more than 30 addresses; \ + it is identified by {:?} and {:?}", peer_id, info.protocol_version, + info.agent_version + ); + info.listen_addrs.truncate(30); + } + for addr in &info.listen_addrs { + self.discovery.add_self_reported_address(&peer_id, addr.clone()); + } + self.substrate.add_discovered_nodes(iter::once(peer_id.clone())); + } +} + +impl, H: ExHashT> NetworkBehaviourEventProcess + for Behaviour { + fn inject_event(&mut self, out: DiscoveryOut) { + match out { + DiscoveryOut::UnroutablePeer(_peer_id) => { + // Obtaining and reporting listen addresses for unroutable peers back + // to Kademlia is handled by the `Identify` protocol, part of the + // `DebugInfoBehaviour`. See the `NetworkBehaviourEventProcess` + // implementation for `DebugInfoEvent`. + } + DiscoveryOut::Discovered(peer_id) => { + self.substrate.add_discovered_nodes(iter::once(peer_id)); + } + DiscoveryOut::ValueFound(results) => { + self.events.push(BehaviourOut::Event(Event::Dht(DhtEvent::ValueFound(results)))); + } + DiscoveryOut::ValueNotFound(key) => { + self.events.push(BehaviourOut::Event(Event::Dht(DhtEvent::ValueNotFound(key)))); + } + DiscoveryOut::ValuePut(key) => { + self.events.push(BehaviourOut::Event(Event::Dht(DhtEvent::ValuePut(key)))); + } + DiscoveryOut::ValuePutFailed(key) => { + self.events.push(BehaviourOut::Event(Event::Dht(DhtEvent::ValuePutFailed(key)))); + } + } + } +} + +impl, H: ExHashT> Behaviour { + fn poll(&mut self, _: &mut Context) -> Poll>> { + if !self.events.is_empty() { + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(self.events.remove(0))) + } + + Poll::Pending + } +} diff --git a/client/network/src/chain.rs b/client/network/src/chain.rs new file mode 100644 index 0000000000000..b991a0e65208c --- /dev/null +++ b/client/network/src/chain.rs @@ -0,0 +1,183 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Blockchain access trait + +use sc_client::Client as SubstrateClient; +use sp_blockchain::{Error, Info as BlockchainInfo}; +use sc_client_api::{ChangesProof, StorageProof, CallExecutor}; +use sp_consensus::{BlockImport, BlockStatus, Error as ConsensusError}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; +use sp_runtime::generic::{BlockId}; +use sp_runtime::Justification; +use sp_core::storage::{StorageKey, ChildInfo}; + +/// Local client abstraction for the network. +pub trait Client: Send + Sync { + /// Get blockchain info. + fn info(&self) -> BlockchainInfo; + + /// Get block status. + fn block_status(&self, id: &BlockId) -> Result; + + /// Get block hash by number. + fn block_hash(&self, block_number: NumberFor) -> Result, Error>; + + /// Get block header. + fn header(&self, id: &BlockId) -> Result, Error>; + + /// Get block body. + fn body(&self, id: &BlockId) -> Result>, Error>; + + /// Get block justification. + fn justification(&self, id: &BlockId) -> Result, Error>; + + /// Get block header proof. + fn header_proof(&self, block_number: NumberFor) + -> Result<(Block::Header, StorageProof), Error>; + + /// Get storage read execution proof. + fn read_proof(&self, block: &Block::Hash, keys: &[Vec]) -> Result; + + /// Get child storage read execution proof. + fn read_child_proof( + &self, + block: &Block::Hash, + storage_key: &[u8], + child_info: ChildInfo, + keys: &[Vec], + ) -> Result; + + /// Get method execution proof. + fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, StorageProof), Error>; + + /// Get key changes proof. + fn key_changes_proof( + &self, + first: Block::Hash, + last: Block::Hash, + min: Block::Hash, + max: Block::Hash, + storage_key: Option<&StorageKey>, + 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; +} + +/// Finality proof provider. +pub trait FinalityProofProvider: Send + Sync { + /// Prove finality of the block. + fn prove_finality(&self, for_block: Block::Hash, request: &[u8]) -> Result>, Error>; +} + +impl FinalityProofProvider for () { + fn prove_finality(&self, _for_block: Block::Hash, _request: &[u8]) -> Result>, Error> { + Ok(None) + } +} + +impl Client for SubstrateClient where + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static, + Self: BlockImport, + Block: BlockT, + RA: Send + Sync +{ + fn info(&self) -> BlockchainInfo { + (self as &SubstrateClient).chain_info() + } + + fn block_status(&self, id: &BlockId) -> Result { + (self as &SubstrateClient).block_status(id) + } + + fn block_hash( + &self, + block_number: ::Number, + ) -> Result, Error> { + (self as &SubstrateClient).block_hash(block_number) + } + + fn header(&self, id: &BlockId) -> Result, Error> { + (self as &SubstrateClient).header(id) + } + + fn body(&self, id: &BlockId) -> Result>, Error> { + (self as &SubstrateClient).body(id) + } + + fn justification(&self, id: &BlockId) -> Result, Error> { + (self as &SubstrateClient).justification(id) + } + + fn header_proof(&self, block_number: ::Number) + -> Result<(Block::Header, StorageProof), Error> + { + (self as &SubstrateClient).header_proof(&BlockId::Number(block_number)) + } + + fn read_proof(&self, block: &Block::Hash, keys: &[Vec]) -> Result { + (self as &SubstrateClient).read_proof(&BlockId::Hash(block.clone()), keys) + } + + fn read_child_proof( + &self, + block: &Block::Hash, + storage_key: &[u8], + child_info: ChildInfo, + keys: &[Vec], + ) -> Result { + (self as &SubstrateClient) + .read_child_proof(&BlockId::Hash(block.clone()), storage_key, child_info, keys) + } + + fn execution_proof( + &self, + block: &Block::Hash, + method: &str, + data: &[u8], + ) -> Result<(Vec, StorageProof), Error> { + (self as &SubstrateClient).execution_proof( + &BlockId::Hash(block.clone()), + method, + data, + ) + } + + fn key_changes_proof( + &self, + first: Block::Hash, + last: Block::Hash, + min: Block::Hash, + max: Block::Hash, + storage_key: Option<&StorageKey>, + key: &StorageKey, + ) -> Result, Error> { + (self as &SubstrateClient).key_changes_proof(first, last, min, max, storage_key, key) + } + + fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result { + if base == block { + return Ok(false); + } + + let ancestor = sp_blockchain::lowest_common_ancestor(self, *block, *base)?; + + Ok(ancestor.hash == *base) + } +} diff --git a/client/network/src/config.rs b/client/network/src/config.rs new file mode 100644 index 0000000000000..6a2062ddbf253 --- /dev/null +++ b/client/network/src/config.rs @@ -0,0 +1,546 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Configuration of the networking layer. +//! +//! The [`Params`] struct is the struct that must be passed in order to initialize the networking. +//! See the documentation of [`Params`]. + +pub use crate::protocol::ProtocolConfig; +pub use libp2p::{identity, core::PublicKey, wasm_ext::ExtTransport, build_multiaddr}; + +use crate::chain::{Client, FinalityProofProvider}; +use crate::on_demand_layer::OnDemand; +use crate::service::{ExHashT, TransactionPool}; +use bitflags::bitflags; +use sp_consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; +use sp_runtime::traits::{Block as BlockT}; +use libp2p::identity::{Keypair, ed25519}; +use libp2p::wasm_ext; +use libp2p::{PeerId, Multiaddr, multiaddr}; +use core::{fmt, iter}; +use std::{error::Error, fs, io::{self, Write}, net::Ipv4Addr, path::{Path, PathBuf}, sync::Arc}; +use zeroize::Zeroize; + +/// Network initialization parameters. +pub struct Params { + /// Assigned roles for our node (full, light, ...). + pub roles: Roles, + + /// Network layer configuration. + pub network_config: NetworkConfiguration, + + /// Client that contains the blockchain. + pub chain: Arc>, + + /// Finality proof provider. + /// + /// This object, if `Some`, is used when a node on the network requests a proof of finality + /// from us. + pub finality_proof_provider: Option>>, + + /// How to build requests for proofs of finality. + /// + /// This object, if `Some`, is used when we need a proof of finality from another node. + pub finality_proof_request_builder: Option>, + + /// The `OnDemand` object acts as a "receiver" for block data requests from the client. + /// If `Some`, the network worker will process these requests and answer them. + /// Normally used only for light clients. + pub on_demand: Option>>, + + /// Pool of transactions. + /// + /// The network worker will fetch transactions from this object in order to propagate them on + /// the network. + pub transaction_pool: Arc>, + + /// Name of the protocol to use on the wire. Should be different for each chain. + pub protocol_id: ProtocolId, + + /// Import queue to use. + /// + /// The import queue is the component that verifies that blocks received from other nodes are + /// valid. + pub import_queue: Box>, + + /// Customization of the network. Use this to plug additional networking capabilities. + pub specialization: S, + + /// Type to check incoming block announcements. + pub block_announce_validator: Box + Send>, +} + +bitflags! { + /// Bitmask of the roles that a node fulfills. + pub struct Roles: u8 { + /// No network. + const NONE = 0b00000000; + /// Full node, does not participate in consensus. + const FULL = 0b00000001; + /// Light client node. + const LIGHT = 0b00000010; + /// Act as an authority + const AUTHORITY = 0b00000100; + } +} + +impl Roles { + /// Does this role represents a client that holds full chain data locally? + pub fn is_full(&self) -> bool { + self.intersects(Roles::FULL | Roles::AUTHORITY) + } + + /// Does this role represents a client that does not participates in the consensus? + pub fn is_authority(&self) -> bool { + *self == Roles::AUTHORITY + } + + /// Does this role represents a client that does not hold full chain data locally? + pub fn is_light(&self) -> bool { + !self.is_full() + } +} + +impl codec::Encode for Roles { + fn encode_to(&self, dest: &mut T) { + dest.push_byte(self.bits()) + } +} + +impl codec::EncodeLike for Roles {} + +impl codec::Decode for Roles { + fn decode(input: &mut I) -> Result { + Self::from_bits(input.read_byte()?).ok_or_else(|| codec::Error::from("Invalid bytes")) + } +} + +/// Finality proof request builder. +pub trait FinalityProofRequestBuilder: Send { + /// Build data blob, associated with the request. + fn build_request_data(&mut self, hash: &B::Hash) -> Vec; +} + +/// Implementation of `FinalityProofRequestBuilder` that builds a dummy empty request. +#[derive(Debug, Default)] +pub struct DummyFinalityProofRequestBuilder; + +impl FinalityProofRequestBuilder for DummyFinalityProofRequestBuilder { + fn build_request_data(&mut self, _: &B::Hash) -> Vec { + Vec::new() + } +} + +/// Shared finality proof request builder struct used by the queue. +pub type BoxFinalityProofRequestBuilder = Box + Send + Sync>; + +/// Name of a protocol, transmitted on the wire. Should be unique for each chain. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ProtocolId(smallvec::SmallVec<[u8; 6]>); + +impl<'a> From<&'a [u8]> for ProtocolId { + fn from(bytes: &'a [u8]) -> ProtocolId { + ProtocolId(bytes.into()) + } +} + +impl ProtocolId { + /// Exposes the `ProtocolId` as bytes. + pub fn as_bytes(&self) -> &[u8] { + self.0.as_ref() + } +} + +/// Parses a string address and splits it into Multiaddress and PeerId, if +/// valid. +/// +/// # Example +/// +/// ``` +/// # use sc_network::{Multiaddr, PeerId, config::parse_str_addr}; +/// let (peer_id, addr) = parse_str_addr( +/// "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV" +/// ).unwrap(); +/// assert_eq!(peer_id, "QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".parse::().unwrap()); +/// assert_eq!(addr, "/ip4/198.51.100.19/tcp/30333".parse::().unwrap()); +/// ``` +/// +pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> { + let addr: Multiaddr = addr_str.parse()?; + parse_addr(addr) +} + +/// Splits a Multiaddress into a Multiaddress and PeerId. +pub fn parse_addr(mut addr: Multiaddr)-> Result<(PeerId, Multiaddr), ParseErr> { + let who = match addr.pop() { + Some(multiaddr::Protocol::P2p(key)) => PeerId::from_multihash(key) + .map_err(|_| ParseErr::InvalidPeerId)?, + _ => 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(multiaddr::Error), + /// 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 std::error::Error for ParseErr { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + ParseErr::MultiaddrParse(err) => Some(err), + ParseErr::InvalidPeerId => None, + ParseErr::PeerIdMissing => None, + } + } +} + +impl From for ParseErr { + fn from(err: multiaddr::Error) -> ParseErr { + ParseErr::MultiaddrParse(err) + } +} + +/// Network service configuration. +#[derive(Clone, Debug)] +pub struct NetworkConfiguration { + /// Directory path to store general network configuration. None means nothing will be saved. + pub config_path: Option, + /// Directory path to store network-specific configuration. None means nothing will be saved. + pub net_config_path: Option, + /// Multiaddresses to listen for incoming connections. + pub listen_addresses: Vec, + /// Multiaddresses to advertise. Detected automatically if empty. + pub public_addresses: Vec, + /// List of initial node addresses + pub boot_nodes: Vec, + /// The node key configuration, which determines the node's network identity keypair. + pub node_key: NodeKeyConfig, + /// Maximum allowed number of incoming connections. + pub in_peers: u32, + /// Number of outgoing connections we're trying to maintain. + pub out_peers: u32, + /// List of reserved node addresses. + pub reserved_nodes: Vec, + /// The non-reserved peer mode. + pub non_reserved_mode: NonReservedPeerMode, + /// List of sentry node public addresses. + pub sentry_nodes: Vec, + /// 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, + /// Configuration for the transport layer. + pub transport: TransportConfig, + /// Maximum number of peers to ask the same blocks in parallel. + pub max_parallel_downloads: u32, +} + +impl Default for NetworkConfiguration { + fn default() -> Self { + NetworkConfiguration { + config_path: None, + net_config_path: None, + listen_addresses: Vec::new(), + public_addresses: Vec::new(), + boot_nodes: Vec::new(), + node_key: NodeKeyConfig::Ed25519(Secret::New), + in_peers: 25, + out_peers: 75, + reserved_nodes: Vec::new(), + non_reserved_mode: NonReservedPeerMode::Accept, + sentry_nodes: Vec::new(), + client_version: "unknown".into(), + node_name: "unknown".into(), + transport: TransportConfig::Normal { + enable_mdns: false, + allow_private_ipv4: true, + wasm_external_transport: None, + }, + max_parallel_downloads: 5, + } + } +} + +impl NetworkConfiguration { + /// Create a new instance of default settings. + pub fn new() -> Self { + Self::default() + } + + /// Create new default configuration for localhost-only connection with random port (useful for testing) + pub fn new_local() -> NetworkConfiguration { + let mut config = NetworkConfiguration::new(); + config.listen_addresses = vec![ + iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) + .chain(iter::once(multiaddr::Protocol::Tcp(0))) + .collect() + ]; + config + } + + /// Create new default configuration for localhost-only connection with random port (useful for testing) + pub fn new_memory() -> NetworkConfiguration { + let mut config = NetworkConfiguration::new(); + config.listen_addresses = vec![ + iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) + .chain(iter::once(multiaddr::Protocol::Tcp(0))) + .collect() + ]; + config + } +} + +/// Configuration for the transport layer. +#[derive(Clone, Debug)] +pub enum TransportConfig { + /// Normal transport mode. + Normal { + /// If true, the network will use mDNS to discover other libp2p nodes on the local network + /// and connect to them if they support the same chain. + enable_mdns: bool, + + /// If true, allow connecting to private IPv4 addresses (as defined in + /// [RFC1918](https://tools.ietf.org/html/rfc1918)), unless the address has been passed in + /// [`NetworkConfiguration::reserved_nodes`] or [`NetworkConfiguration::boot_nodes`]. + allow_private_ipv4: bool, + + /// Optional external implementation of a libp2p transport. Used in WASM contexts where we + /// need some binding between the networking provided by the operating system or environment + /// and libp2p. + /// + /// This parameter exists whatever the target platform is, but it is expected to be set to + /// `Some` only when compiling for WASM. + wasm_external_transport: Option, + }, + + /// Only allow connections within the same process. + /// Only addresses of the form `/memory/...` will be supported. + MemoryOnly, +} + +/// The policy for connections to non-reserved peers. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum NonReservedPeerMode { + /// Accept them. This is the default. + Accept, + /// Deny them. + Deny, +} + +impl NonReservedPeerMode { + /// Attempt to parse the peer mode from a string. + pub fn parse(s: &str) -> Option { + match s { + "accept" => Some(NonReservedPeerMode::Accept), + "deny" => Some(NonReservedPeerMode::Deny), + _ => None, + } + } +} + +/// The configuration of a node's secret key, describing the type of key +/// and how it is obtained. A node's identity keypair is the result of +/// the evaluation of the node key configuration. +#[derive(Clone, Debug)] +pub enum NodeKeyConfig { + /// A Ed25519 secret key configuration. + Ed25519(Secret) +} + +/// The options for obtaining a Ed25519 secret key. +pub type Ed25519Secret = Secret; + +/// The configuration options for obtaining a secret key `K`. +#[derive(Clone)] +pub enum Secret { + /// Use the given secret key `K`. + Input(K), + /// Read the secret key from a file. If the file does not exist, + /// it is created with a newly generated secret key `K`. The format + /// of the file is determined by `K`: + /// + /// * `ed25519::SecretKey`: An unencoded 32 bytes Ed25519 secret key. + File(PathBuf), + /// Always generate a new secret key `K`. + New +} + +impl fmt::Debug for Secret { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Secret::Input(_) => f.debug_tuple("Secret::Input").finish(), + Secret::File(path) => f.debug_tuple("Secret::File").field(path).finish(), + Secret::New => f.debug_tuple("Secret::New").finish(), + } + } +} + +impl NodeKeyConfig { + /// Evaluate a `NodeKeyConfig` to obtain an identity `Keypair`: + /// + /// * If the secret is configured as input, the corresponding keypair is returned. + /// + /// * If the secret is configured as a file, it is read from that file, if it exists. + /// Otherwise a new secret is generated and stored. In either case, the + /// keypair obtained from the secret is returned. + /// + /// * If the secret is configured to be new, it is generated and the corresponding + /// keypair is returned. + pub fn into_keypair(self) -> io::Result { + use NodeKeyConfig::*; + match self { + Ed25519(Secret::New) => + Ok(Keypair::generate_ed25519()), + + Ed25519(Secret::Input(k)) => + Ok(Keypair::Ed25519(k.into())), + + Ed25519(Secret::File(f)) => + get_secret(f, + |mut b| ed25519::SecretKey::from_bytes(&mut b), + ed25519::SecretKey::generate, + |b| b.as_ref().to_vec()) + .map(ed25519::Keypair::from) + .map(Keypair::Ed25519), + } + } +} + +/// Load a secret key from a file, if it exists, or generate a +/// new secret key and write it to that file. In either case, +/// the secret key is returned. +fn get_secret(file: P, parse: F, generate: G, serialize: W) -> io::Result +where + P: AsRef, + F: for<'r> FnOnce(&'r mut [u8]) -> Result, + G: FnOnce() -> K, + E: Error + Send + Sync + 'static, + W: Fn(&K) -> Vec, +{ + std::fs::read(&file) + .and_then(|mut sk_bytes| + parse(&mut sk_bytes) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))) + .or_else(|e| { + if e.kind() == io::ErrorKind::NotFound { + file.as_ref().parent().map_or(Ok(()), fs::create_dir_all)?; + let sk = generate(); + let mut sk_vec = serialize(&sk); + write_secret_file(file, &sk_vec)?; + sk_vec.zeroize(); + Ok(sk) + } else { + Err(e) + } + }) +} + +/// Write secret bytes to a file. +fn write_secret_file

(path: P, sk_bytes: &[u8]) -> io::Result<()> +where + P: AsRef +{ + let mut file = open_secret_file(&path)?; + file.write_all(sk_bytes) +} + +/// Opens a file containing a secret key in write mode. +#[cfg(unix)] +fn open_secret_file

(path: P) -> io::Result +where + P: AsRef +{ + use std::os::unix::fs::OpenOptionsExt; + fs::OpenOptions::new() + .write(true) + .create_new(true) + .mode(0o600) + .open(path) +} + +/// Opens a file containing a secret key in write mode. +#[cfg(not(unix))] +fn open_secret_file

(path: P) -> Result +where + P: AsRef +{ + fs::OpenOptions::new() + .write(true) + .create_new(true) + .open(path) +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::TempDir; + + fn tempdir_with_prefix(prefix: &str) -> TempDir { + tempfile::Builder::new().prefix(prefix).tempdir().unwrap() + } + + fn secret_bytes(kp: &Keypair) -> Vec { + match kp { + Keypair::Ed25519(p) => p.secret().as_ref().iter().cloned().collect(), + Keypair::Secp256k1(p) => p.secret().to_bytes().to_vec(), + _ => panic!("Unexpected keypair.") + } + } + + #[test] + fn test_secret_file() { + let tmp = tempdir_with_prefix("x"); + std::fs::remove_dir(tmp.path()).unwrap(); // should be recreated + let file = tmp.path().join("x").to_path_buf(); + let kp1 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap(); + let kp2 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap(); + assert!(file.is_file() && secret_bytes(&kp1) == secret_bytes(&kp2)) + } + + #[test] + fn test_secret_input() { + let sk = ed25519::SecretKey::generate(); + let kp1 = NodeKeyConfig::Ed25519(Secret::Input(sk.clone())).into_keypair().unwrap(); + let kp2 = NodeKeyConfig::Ed25519(Secret::Input(sk)).into_keypair().unwrap(); + assert!(secret_bytes(&kp1) == secret_bytes(&kp2)); + } + + #[test] + fn test_secret_new() { + let kp1 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap(); + let kp2 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap(); + assert!(secret_bytes(&kp1) != secret_bytes(&kp2)); + } +} diff --git a/core/network/src/debug_info.rs b/client/network/src/debug_info.rs similarity index 80% rename from core/network/src/debug_info.rs rename to client/network/src/debug_info.rs index 3b0d5513ef281..9cc39baae6237 100644 --- a/core/network/src/debug_info.rs +++ b/client/network/src/debug_info.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,18 +16,18 @@ use fnv::FnvHashMap; use futures::prelude::*; -use futures03::{StreamExt as _, TryStreamExt as _}; use libp2p::Multiaddr; use libp2p::core::{ConnectedPoint, either::EitherOutput, PeerId, PublicKey}; use libp2p::swarm::{IntoProtocolsHandler, IntoProtocolsHandlerSelect, ProtocolsHandler}; use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use libp2p::identify::{Identify, IdentifyEvent, protocol::IdentifyInfo}; +use libp2p::identify::{Identify, IdentifyEvent, IdentifyInfo}; use libp2p::ping::{Ping, PingConfig, PingEvent, PingSuccess}; use log::{debug, trace, error}; use std::collections::hash_map::Entry; +use std::pin::Pin; +use std::task::{Context, Poll}; use std::time::{Duration, Instant}; -use tokio_io::{AsyncRead, AsyncWrite}; -use futures_timer::Interval; +use crate::utils::interval; /// Time after we disconnect from a node before we purge its information from the cache. const CACHE_EXPIRE: Duration = Duration::from_secs(10 * 60); @@ -44,7 +44,7 @@ pub struct DebugInfoBehaviour { /// Information that we know about all nodes. nodes_info: FnvHashMap, /// Interval at which we perform garbage collection in `nodes_info`. - garbage_collect: Box + Send>, + garbage_collect: Pin + Send>>, } /// Information about a node we're connected to. @@ -76,7 +76,7 @@ impl DebugInfoBehaviour { ping: Ping::new(PingConfig::new()), identify, nodes_info: FnvHashMap::default(), - garbage_collect: Box::new(Interval::new(GARBAGE_COLLECT_INTERVAL).map(|()| Ok(())).compat()), + garbage_collect: Box::pin(interval(GARBAGE_COLLECT_INTERVAL)), } } @@ -149,7 +149,7 @@ pub enum DebugInfoEvent { } impl NetworkBehaviour for DebugInfoBehaviour -where TSubstream: AsyncRead + AsyncWrite { +where TSubstream: AsyncRead + AsyncWrite + Unpin + Send + 'static { type ProtocolsHandler = IntoProtocolsHandlerSelect< as NetworkBehaviour>::ProtocolsHandler, as NetworkBehaviour>::ProtocolsHandler @@ -253,72 +253,71 @@ where TSubstream: AsyncRead + AsyncWrite { fn poll( &mut self, + cx: &mut Context, params: &mut impl PollParameters - ) -> Async< + ) -> Poll< NetworkBehaviourAction< <::Handler as ProtocolsHandler>::InEvent, Self::OutEvent > > { loop { - match self.ping.poll(params) { - Async::NotReady => break, - Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => { + match self.ping.poll(cx, params) { + Poll::Pending => break, + Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => { if let PingEvent { peer, result: Ok(PingSuccess::Ping { rtt }) } = ev { self.handle_ping_report(&peer, rtt) } }, - Async::Ready(NetworkBehaviourAction::DialAddress { address }) => - return Async::Ready(NetworkBehaviourAction::DialAddress { address }), - Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => - return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => - return Async::Ready(NetworkBehaviourAction::SendEvent { + Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => + return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), + Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => + return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event: EitherOutput::First(event) }), - Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => - return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), + Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => + return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), } } loop { - match self.identify.poll(params) { - Async::NotReady => break, - Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => { + match self.identify.poll(cx, params) { + Poll::Pending => break, + Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)) => { match event { - IdentifyEvent::Identified { peer_id, info, .. } => { + IdentifyEvent::Received { peer_id, info, .. } => { self.handle_identify_report(&peer_id, &info); let event = DebugInfoEvent::Identified { peer_id, info }; - return Async::Ready(NetworkBehaviourAction::GenerateEvent(event)); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); } - IdentifyEvent::Error { .. } => {} - IdentifyEvent::SendBack { result: Err(ref err), ref peer_id } => - debug!(target: "sub-libp2p", "Error when sending back identify info \ - to {:?} => {}", peer_id, err), - IdentifyEvent::SendBack { .. } => {} + IdentifyEvent::Error { peer_id, error } => + debug!(target: "sub-libp2p", "Identification with peer {:?} failed => {}", peer_id, error), + IdentifyEvent::Sent { .. } => {} } }, - Async::Ready(NetworkBehaviourAction::DialAddress { address }) => - return Async::Ready(NetworkBehaviourAction::DialAddress { address }), - Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => - return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => - return Async::Ready(NetworkBehaviourAction::SendEvent { + Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => + return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), + Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => + return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event: EitherOutput::Second(event) }), - Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => - return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), + Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => + return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), } } - while let Ok(Async::Ready(Some(_))) = self.garbage_collect.poll() { + while let Poll::Ready(Some(())) = self.garbage_collect.poll_next_unpin(cx) { self.nodes_info.retain(|_, node| { node.info_expire.as_ref().map(|exp| *exp >= Instant::now()).unwrap_or(true) }); } - Async::NotReady + Poll::Pending } } diff --git a/core/network/src/discovery.rs b/client/network/src/discovery.rs similarity index 77% rename from core/network/src/discovery.rs rename to client/network/src/discovery.rs index a9cf61d040f0f..11f687616e649 100644 --- a/core/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -47,7 +47,6 @@ use futures::prelude::*; use futures_timer::Delay; -use futures03::{compat::Compat, TryFutureExt as _}; use libp2p::core::{ConnectedPoint, Multiaddr, PeerId, PublicKey}; use libp2p::swarm::{ProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; use libp2p::kad::{Kademlia, KademliaEvent, Quorum, Record}; @@ -62,7 +61,8 @@ use libp2p::mdns::{Mdns, MdnsEvent}; use libp2p::multiaddr::Protocol; use log::{debug, info, trace, warn}; use std::{cmp, collections::VecDeque, time::Duration}; -use tokio_io::{AsyncRead, AsyncWrite}; +use std::task::{Context, Poll}; +use sp_core::hexdisplay::HexDisplay; /// Implementation of `NetworkBehaviour` that discovers the nodes on the network. pub struct DiscoveryBehaviour { @@ -75,7 +75,7 @@ pub struct DiscoveryBehaviour { #[cfg(not(target_os = "unknown"))] mdns: Toggle>>, /// Stream that fires when we need to perform the next random Kademlia query. - next_kad_random_query: Compat, + next_kad_random_query: Delay, /// After `next_kad_random_query` triggers, the next one triggers after this duration. duration_to_next_kad: Duration, /// Discovered nodes to return. @@ -84,16 +84,20 @@ pub struct DiscoveryBehaviour { local_peer_id: PeerId, /// Number of nodes we're currently connected to. num_connections: u64, + /// If false, `addresses_of_peer` won't return any private IPv4 address, except for the ones + /// stored in `user_defined`. + allow_private_ipv4: bool, } impl DiscoveryBehaviour { /// Builds a new `DiscoveryBehaviour`. /// /// `user_defined` is a list of known address for nodes that never expire. - pub fn new( + pub async fn new( local_public_key: PublicKey, user_defined: Vec<(PeerId, Multiaddr)>, - enable_mdns: bool + enable_mdns: bool, + allow_private_ipv4: bool, ) -> Self { if enable_mdns { #[cfg(target_os = "unknown")] @@ -110,14 +114,15 @@ impl DiscoveryBehaviour { DiscoveryBehaviour { user_defined, kademlia, - next_kad_random_query: Delay::new(Duration::new(0, 0)).compat(), + next_kad_random_query: Delay::new(Duration::new(0, 0)), duration_to_next_kad: Duration::from_secs(1), discoveries: VecDeque::new(), local_peer_id: local_public_key.into_peer_id(), num_connections: 0, + allow_private_ipv4, #[cfg(not(target_os = "unknown"))] mdns: if enable_mdns { - match Mdns::new() { + match Mdns::new().await { Ok(mdns) => Some(mdns).into(), Err(err) => { warn!(target: "sub-libp2p", "Failed to initialize mDNS: {:?}", err); @@ -200,7 +205,7 @@ pub enum DiscoveryOut { impl NetworkBehaviour for DiscoveryBehaviour where - TSubstream: AsyncRead + AsyncWrite, + TSubstream: AsyncRead + AsyncWrite + Unpin, { type ProtocolsHandler = as NetworkBehaviour>::ProtocolsHandler; type OutEvent = DiscoveryOut; @@ -213,9 +218,27 @@ where let mut list = self.user_defined.iter() .filter_map(|(p, a)| if p == peer_id { Some(a.clone()) } else { None }) .collect::>(); - list.extend(self.kademlia.addresses_of_peer(peer_id)); - #[cfg(not(target_os = "unknown"))] - list.extend(self.mdns.addresses_of_peer(peer_id)); + + { + let mut list_to_filter = self.kademlia.addresses_of_peer(peer_id); + #[cfg(not(target_os = "unknown"))] + list_to_filter.extend(self.mdns.addresses_of_peer(peer_id)); + + if !self.allow_private_ipv4 { + list_to_filter.retain(|addr| { + if let Some(Protocol::Ip4(addr)) = addr.iter().next() { + if addr.is_private() { + return false; + } + } + + true + }); + } + + list.extend(list_to_filter); + } + trace!(target: "sub-libp2p", "Addresses of {:?} are {:?}", peer_id, list); if list.is_empty() { if self.kademlia.kbuckets_entries().any(|p| p == peer_id) { @@ -263,8 +286,9 @@ where fn poll( &mut self, + cx: &mut Context, params: &mut impl PollParameters, - ) -> Async< + ) -> Poll< NetworkBehaviourAction< ::InEvent, Self::OutEvent, @@ -273,59 +297,49 @@ where // Immediately process the content of `discovered`. if let Some(peer_id) = self.discoveries.pop_front() { let ev = DiscoveryOut::Discovered(peer_id); - return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } // 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", "Libp2p <= Starting random Kademlia request for \ - {:?}", random_peer_id); - - self.kademlia.get_closest_peers(random_peer_id); - - // Schedule the next random query with exponentially increasing delay, - // capped at 60 seconds. - self.next_kad_random_query = Delay::new(self.duration_to_next_kad).compat(); - self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2, - Duration::from_secs(60)); - }, - Err(err) => { - warn!(target: "sub-libp2p", "Kademlia query timer errored: {:?}", err); - break - } - } + while let Poll::Ready(_) = self.next_kad_random_query.poll_unpin(cx) { + let random_peer_id = PeerId::random(); + debug!(target: "sub-libp2p", "Libp2p <= Starting random Kademlia request for \ + {:?}", random_peer_id); + + self.kademlia.get_closest_peers(random_peer_id); + + // Schedule the next random query with exponentially increasing delay, + // capped at 60 seconds. + self.next_kad_random_query = Delay::new(self.duration_to_next_kad); + self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2, + Duration::from_secs(60)); } // Poll Kademlia. - loop { - match self.kademlia.poll(params) { - Async::NotReady => break, - Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => match ev { + while let Poll::Ready(ev) = self.kademlia.poll(cx, params) { + match ev { + NetworkBehaviourAction::GenerateEvent(ev) => match ev { KademliaEvent::UnroutablePeer { peer, .. } => { let ev = DiscoveryOut::UnroutablePeer(peer); - return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } KademliaEvent::RoutingUpdated { peer, .. } => { let ev = DiscoveryOut::Discovered(peer); - return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } KademliaEvent::GetClosestPeersResult(res) => { match res { Err(GetClosestPeersError::Timeout { key, peers }) => { - warn!(target: "sub-libp2p", - "Libp2p => Query for {:?} timed out with {:?} results", - key, peers.len()); + debug!(target: "sub-libp2p", + "Libp2p => Query for {:?} timed out with {} results", + HexDisplay::from(&key), peers.len()); }, Ok(ok) => { trace!(target: "sub-libp2p", "Libp2p => Query for {:?} yielded {:?} results", - ok.key, ok.peers.len()); + HexDisplay::from(&ok.key), ok.peers.len()); if ok.peers.is_empty() && self.num_connections != 0 { - warn!(target: "sub-libp2p", "Libp2p => Random Kademlia query has yielded empty \ + debug!(target: "sub-libp2p", "Libp2p => Random Kademlia query has yielded empty \ results"); } } @@ -345,7 +359,7 @@ where DiscoveryOut::ValueNotFound(e.into_key()) } }; - return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } KademliaEvent::PutRecordResult(res) => { let ev = match res { @@ -354,7 +368,7 @@ where DiscoveryOut::ValuePutFailed(e.into_key()) } }; - return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } KademliaEvent::RepublishRecordResult(res) => { match res { @@ -374,46 +388,45 @@ where warn!(target: "sub-libp2p", "Libp2p => Unhandled Kademlia event: {:?}", e) } }, - Async::Ready(NetworkBehaviourAction::DialAddress { address }) => - return Async::Ready(NetworkBehaviourAction::DialAddress { address }), - Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => - return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => - return Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }), - Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => - return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), + NetworkBehaviourAction::DialAddress { address } => + return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), + NetworkBehaviourAction::DialPeer { peer_id } => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), + NetworkBehaviourAction::SendEvent { peer_id, event } => + return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }), + NetworkBehaviourAction::ReportObservedAddr { address } => + return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), } } // Poll mDNS. #[cfg(not(target_os = "unknown"))] - loop { - match self.mdns.poll(params) { - Async::NotReady => break, - Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => { + while let Poll::Ready(ev) = self.mdns.poll(cx, params) { + match ev { + NetworkBehaviourAction::GenerateEvent(event) => { match event { MdnsEvent::Discovered(list) => { self.discoveries.extend(list.into_iter().map(|(peer_id, _)| peer_id)); if let Some(peer_id) = self.discoveries.pop_front() { let ev = DiscoveryOut::Discovered(peer_id); - return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)); + return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)); } }, MdnsEvent::Expired(_) => {} } }, - Async::Ready(NetworkBehaviourAction::DialAddress { address }) => - return Async::Ready(NetworkBehaviourAction::DialAddress { address }), - Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => - return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - Async::Ready(NetworkBehaviourAction::SendEvent { event, .. }) => + NetworkBehaviourAction::DialAddress { address } => + return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), + NetworkBehaviourAction::DialPeer { peer_id } => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), + NetworkBehaviourAction::SendEvent { event, .. } => match event {}, // `event` is an enum with no variant - Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => - return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), + NetworkBehaviourAction::ReportObservedAddr { address } => + return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), } } - Async::NotReady + Poll::Pending } } @@ -426,7 +439,7 @@ mod tests { use libp2p::core::transport::{Transport, MemoryTransport}; use libp2p::core::upgrade::{InboundUpgradeExt, OutboundUpgradeExt}; use libp2p::swarm::Swarm; - use std::collections::HashSet; + use std::{collections::HashSet, task::Poll}; use super::{DiscoveryBehaviour, DiscoveryOut}; #[test] @@ -436,19 +449,33 @@ mod tests { // Build swarms whose behaviour is `DiscoveryBehaviour`. let mut swarms = (0..25).map(|_| { let keypair = Keypair::generate_ed25519(); + let keypair2 = keypair.clone(); let transport = MemoryTransport - .with_upgrade(libp2p::secio::SecioConfig::new(keypair.clone())) .and_then(move |out, endpoint| { - let peer_id = out.remote_key.into_peer_id(); + let secio = libp2p::secio::SecioConfig::new(keypair2); + libp2p::core::upgrade::apply( + out, + secio, + endpoint, + upgrade::Version::V1 + ) + }) + .and_then(move |(peer_id, stream), endpoint| { let peer_id2 = peer_id.clone(); let upgrade = libp2p::yamux::Config::default() .map_inbound(move |muxer| (peer_id, muxer)) .map_outbound(move |muxer| (peer_id2, muxer)); - upgrade::apply(out.stream, upgrade, endpoint) + upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1) }); - let behaviour = DiscoveryBehaviour::new(keypair.public(), user_defined.clone(), false); + let behaviour = futures::executor::block_on({ + let user_defined = user_defined.clone(); + let keypair_public = keypair.public(); + async move { + DiscoveryBehaviour::new(keypair_public, user_defined, false, true).await + } + }); let mut swarm = Swarm::new(transport, behaviour, keypair.public().into_peer_id()); let listen_addr: Multiaddr = format!("/memory/{}", rand::random::()).parse().unwrap(); @@ -467,11 +494,11 @@ mod tests { .collect::>() }).collect::>(); - let fut = futures::future::poll_fn::<_, (), _>(move || { + let fut = futures::future::poll_fn(move |cx| { 'polling: loop { for swarm_n in 0..swarms.len() { - match swarms[swarm_n].0.poll().unwrap() { - Async::Ready(Some(e)) => { + match swarms[swarm_n].0.poll_next_unpin(cx) { + Poll::Ready(Some(e)) => { match e { DiscoveryOut::UnroutablePeer(other) => { // Call `add_self_reported_address` to simulate identify happening. @@ -498,12 +525,12 @@ mod tests { } if to_discover.iter().all(|l| l.is_empty()) { - Ok(Async::Ready(())) + Poll::Ready(()) } else { - Ok(Async::NotReady) + Poll::Pending } }); - tokio::runtime::Runtime::new().unwrap().block_on(fut).unwrap(); + futures::executor::block_on(fut); } } diff --git a/client/network/src/error.rs b/client/network/src/error.rs new file mode 100644 index 0000000000000..ba5d5c2d0d2b5 --- /dev/null +++ b/client/network/src/error.rs @@ -0,0 +1,65 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate network possible errors. + +use libp2p::{PeerId, Multiaddr}; + +use std::fmt; + +/// Result type alias for the network. +pub type Result = std::result::Result; + +/// Error type for the network. +#[derive(derive_more::Display, derive_more::From)] +pub enum Error { + /// Io error + Io(std::io::Error), + /// Client error + Client(sp_blockchain::Error), + /// The same bootnode (based on address) is registered with two different peer ids. + #[display( + fmt = "The same bootnode (`{}`) is registered with two different peer ids: `{}` and `{}`", + address, + first_id, + second_id, + )] + DuplicateBootnode { + /// The address of the bootnode. + address: Multiaddr, + /// The first peer id that was found for the bootnode. + first_id: PeerId, + /// The second peer id that was found for the bootnode. + second_id: PeerId, + }, +} + +// Make `Debug` use the `Display` implementation. +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Io(ref err) => Some(err), + Error::Client(ref err) => Some(err), + Error::DuplicateBootnode { .. } => None, + } + } +} diff --git a/client/network/src/lib.rs b/client/network/src/lib.rs new file mode 100644 index 0000000000000..dd156360330ac --- /dev/null +++ b/client/network/src/lib.rs @@ -0,0 +1,305 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![warn(unused_extern_crates)] +#![warn(missing_docs)] + +//! Substrate-specific P2P networking. +//! +//! **Important**: This crate is unstable and the API and usage may change. +//! +//! # Node identities and addresses +//! +//! In a decentralized network, each node possesses a network private key and a network public key. +//! In Substrate, the keys are based on the ed25519 curve. +//! +//! From a node's public key, we can derive its *identity*. In Substrate and libp2p, a node's +//! identity is represented with the [`PeerId`] struct. All network communications between nodes on +//! the network use encryption derived from both sides's keys, which means that **identities cannot +//! be faked**. +//! +//! A node's identity uniquely identifies a machine on the network. If you start two or more +//! clients using the same network key, large interferences will happen. +//! +//! # Substrate's network protocol +//! +//! Substrate's networking protocol is based upon libp2p. It is at the moment not possible and not +//! planned to permit using something else than the libp2p network stack and the rust-libp2p +//! library. However the libp2p framework is very flexible and the rust-libp2p library could be +//! extended to support a wider range of protocols than what is offered by libp2p. +//! +//! ## Discovery mechanisms +//! +//! In order for our node to join a peer-to-peer network, it has to know a list of nodes that are +//! part of said network. This includes nodes identities and their address (how to reach them). +//! Building such a list is called the **discovery** mechanism. There are three mechanisms that +//! Substrate uses: +//! +//! - Bootstrap nodes. These are hard-coded node identities and addresses passed alongside with +//! the network configuration. +//! - mDNS. We perform a UDP broadcast on the local network. Nodes that listen may respond with +//! their identity. More info [here](https://github.com/libp2p/specs/blob/master/discovery/mdns.md). +//! mDNS can be disabled in the network configuration. +//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests in +//! order for nodes to propagate to us their view of the network. More information about Kademlia +//! can be found [on Wikipedia](https://en.wikipedia.org/wiki/Kademlia). +//! +//! ## Connection establishment +//! +//! When node Alice knows node Bob's identity and address, it can establish a connection with Bob. +//! All connections must always use encryption and multiplexing. While some node addresses (eg. +//! addresses using `/quic`) already imply which encryption and/or multiplexing to use, for others +//! the **multistream-select** protocol is used in order to negotiate an encryption layer and/or a +//! multiplexing layer. +//! +//! The connection establishment mechanism is called the **transport**. +//! +//! As of the writing of this documentation, the following base-layer protocols are supported by +//! Substrate: +//! +//! - TCP/IP for addresses of the form `/ip4/1.2.3.4/tcp/5`. Once the TCP connection is open, an +//! encryption and a multiplexing layer are negotiated on top. +//! - WebSockets for addresses of the form `/ip4/1.2.3.4/tcp/5/ws`. A TCP/IP connection is open and +//! the WebSockets protocol is negotiated on top. Communications then happen inside WebSockets data +//! frames. Encryption and multiplexing are additionally negotiated again inside this channel. +//! - DNS for addresses of the form `/dns4/example.com/tcp/5` or `/dns4/example.com/tcp/5/ws`. A +//! node's address can contain a domain name. +//! +//! The following encryption protocols are supported: +//! +//! - [Secio](https://github.com/libp2p/specs/tree/master/secio). A TLS-1.2-like protocol but +//! without certificates. Support for secio will likely be deprecated in the far future. +//! - [Noise](https://noiseprotocol.org/). Support for noise is very experimental. The details are +//! very blurry and may change at any moment. +//! +//! The following multiplexing protocols are supported: +//! +//! - [Mplex](https://github.com/libp2p/specs/tree/master/mplex). Support for mplex will likely +//! be deprecated in the future. +//! - [Yamux](https://github.com/hashicorp/yamux/blob/master/spec.md). +//! +//! ## Substreams +//! +//! Once a connection has been established and uses multiplexing, substreams can be opened. When +//! a substream is open, the **multistream-select** protocol is used to negotiate which protocol to +//! use on that given substream. In practice, Substrate opens the following substreams: +//! +//! - We periodically open an ephemeral substream in order to ping the remote and check whether the +//! connection is still alive. Failure for the remote to reply leads to a disconnection. This uses +//! the libp2p ping protocol. +//! - We periodically open an ephemeral substream in order to ask information from the remote. This +//! is called [the `identify` protocol](https://github.com/libp2p/specs/tree/master/identify). +//! - We periodically open ephemeral substreams for Kademlia random walk queries. Each Kademlia +//! query is done in a new separate substream. This uses the +//! [standard libp2p Kademlia protocol](https://github.com/libp2p/specs/pull/108). +//! - We optionally keep a substream alive for all Substrate-based communications. The name of the +//! protocol negotiated is based on the *protocol ID* passed as part of the network configuration. +//! This protocol ID should be unique for each chain and prevents nodes from different chains from +//! connecting to each other. More information below. +//! +//! ## The Substrate substream +//! +//! Substrate uses a component named the **peerset manager (PSM)**. Through the discovery +//! mechanism, the PSM is aware of the nodes that are part of the network and decides which nodes +//! we should perform Substrate-based communications with. For these nodes, we open a connection +//! if necessary and open a unique substream for Substrate-based communications. If the PSM decides +//! that we should disconnect a node, then that substream is closed. +//! +//! For more information about the PSM, see the *sc-peerset* crate. +//! +//! Note that at the moment there is no mechanism in place to solve the issues that arise where the +//! two sides of a connection open the unique substream simultaneously. In order to not run into +//! issues, only the dialer of a connection is allowed to open the unique substream. When the +//! substream is closed, the entire connection is closed as well. This is a bug, and should be +//! fixed by improving the protocol. +//! +//! Within the unique Substrate substream, messages encoded using +//! [*parity-scale-codec*](https://github.com/paritytech/parity-scale-codec) are exchanged. +//! The detail of theses messages is not totally in place, but they can be found in the +//! `message.rs` file. +//! +//! Once the substream is open, the first step is an exchange of a *status* message from both +//! sides, containing information such as the chain root hash, head of chain, and so on. +//! +//! Communications within this substream include: +//! +//! - Syncing. Blocks are announced and requested from other nodes. +//! - Light-client requests. When a light client requires information, a random node we have a +//! substream open with is chosen, and the information is requested from it. +//! - Gossiping. Used for example by grandpa. +//! - Network specialization. The network protocol can be specialized through a template parameter +//! of the network service. This specialization is free to send and receive messages with the +//! remote. This is meant to be used by the chain that is being built on top of Substrate +//! (eg. Polkadot). +//! +//! It is intended that in the future each of these components gets more isolated, so that they +//! are free to open and close their own substreams, and so that syncing and light client requests +//! are able to communicate with nodes outside of the range of the PSM. +//! +//! # Usage +//! +//! Using the `sc-network` crate is done through the [`NetworkWorker`] struct. Create this +//! struct by passing a [`config::Params`], then poll it as if it was a `Future`. You can extract an +//! `Arc` from the `NetworkWorker`, which can be shared amongst multiple places +//! in order to give orders to the networking. +//! +//! See the [`config`] module for more information about how to configure the networking. +//! +//! After the `NetworkWorker` has been created, the important things to do are: +//! +//! - Calling `NetworkWorker::poll` in order to advance the network. +//! - Calling `on_block_import` whenever a block is added to the client. +//! - Calling `on_block_finalized` whenever a block is finalized. +//! - Calling `trigger_repropagate` when a transaction is added to the pool. +//! +//! More precise usage details are still being worked on and will likely change in the future. +//! + +mod behaviour; +mod chain; +mod debug_info; +mod discovery; +mod on_demand_layer; +mod protocol; +mod service; +mod transport; +mod utils; + +pub mod config; +pub mod error; + +pub use chain::{Client as ClientHandle, FinalityProofProvider}; +pub use service::{ + NetworkService, NetworkWorker, TransactionPool, ExHashT, ReportHandle, + NetworkStateInfo, +}; +pub use protocol::{PeerInfo, Context, ProtocolConfig, message, specialization}; +pub use protocol::event::{Event, DhtEvent}; +pub use protocol::sync::SyncState; +pub use libp2p::{Multiaddr, PeerId}; +#[doc(inline)] +pub use libp2p::multiaddr; + +pub use message::{generic as generic_message, RequestId, Status as StatusMessage}; +pub use on_demand_layer::{OnDemand, RemoteResponse}; +pub use sc_peerset::ReputationChange; + +// Used by the `construct_simple_protocol!` macro. +#[doc(hidden)] +pub use sp_runtime::traits::Block as BlockT; + +use libp2p::core::ConnectedPoint; +use serde::{Deserialize, Serialize}; +use slog_derive::SerdeValue; +use std::{collections::{HashMap, HashSet}, time::Duration}; + +/// Extension trait for `NetworkBehaviour` that also accepts discovering nodes. +pub trait DiscoveryNetBehaviour { + /// Notify the protocol that we have learned about the existence of nodes. + /// + /// Can (or most likely will) be called multiple times with the same `PeerId`s. + /// + /// Also note that there is no notification for expired nodes. The implementer must add a TTL + /// system, or remove nodes that will fail to reach. + fn add_discovered_nodes(&mut self, nodes: impl Iterator); +} + +/// Returns general information about the networking. +/// +/// Meant for general diagnostic purposes. +/// +/// **Warning**: This API is not stable. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SerdeValue)] +#[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, + /// List of addresses the node knows it can be reached as. + pub external_addresses: HashSet, + /// 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, + /// State of the peerset manager. + pub peerset: serde_json::Value, +} + +/// Part of the `NetworkState` struct. Unstable. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[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, + /// If true, the peer is "open", which means that we have a Substrate-related protocol + /// with this peer. + pub open: bool, + /// List of addresses known for this node. + pub known_addresses: HashSet, +} + +/// Part of the `NetworkState` struct. Unstable. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct NetworkStateNotConnectedPeer { + /// List of addresses known for this node. + pub known_addresses: HashSet, + /// Node information, as provided by the node itself, if we were ever connected to this node. + pub version_string: Option, + /// Latest ping duration with this node, if we were ever connected to this node. + pub latest_ping_time: Option, +} + +/// Part of the `NetworkState` struct. Unstable. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum NetworkStatePeerEndpoint { + /// We are dialing the given address. + Dialing(Multiaddr), + /// We are listening. + Listening { + /// Local address of the connection. + local_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 { local_addr, send_back_addr } => + NetworkStatePeerEndpoint::Listening { + local_addr, + send_back_addr + } + } + } +} diff --git a/client/network/src/on_demand_layer.rs b/client/network/src/on_demand_layer.rs new file mode 100644 index 0000000000000..d672ed0b7f569 --- /dev/null +++ b/client/network/src/on_demand_layer.rs @@ -0,0 +1,147 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! On-demand requests service. + +use crate::protocol::light_dispatch::RequestData; +use std::{collections::HashMap, pin::Pin, sync::Arc, task::Context, task::Poll}; +use futures::{prelude::*, channel::mpsc, channel::oneshot}; +use parking_lot::Mutex; +use sp_blockchain::Error as ClientError; +use sc_client_api::{ + Fetcher, FetchChecker, RemoteHeaderRequest, RemoteCallRequest, RemoteReadRequest, + RemoteChangesRequest, RemoteReadChildRequest, RemoteBodyRequest, +}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; + +/// Implements the `Fetcher` trait of the client. Makes it possible for the light client to perform +/// network requests for some state. +/// +/// This implementation stores all the requests in a queue. The network, in parallel, is then +/// responsible for pulling elements out of that queue and fulfilling them. +pub struct OnDemand { + /// Objects that checks whether what has been retrieved is correct. + checker: Arc>, + + /// Queue of requests. Set to `Some` at initialization, then extracted by the network. + /// + /// Note that a better alternative would be to use a MPMC queue here, and add a `poll` method + /// from the `OnDemand`. However there exists no popular implementation of MPMC channels in + /// asynchronous Rust at the moment + requests_queue: Mutex>>>, + + /// Sending side of `requests_queue`. + requests_send: mpsc::UnboundedSender>, +} + +impl OnDemand where + B::Header: HeaderT, +{ + /// Creates new on-demand service. + pub fn new(checker: Arc>) -> Self { + let (requests_send, requests_queue) = mpsc::unbounded(); + let requests_queue = Mutex::new(Some(requests_queue)); + + OnDemand { + checker, + requests_queue, + requests_send, + } + } + + /// Get checker reference. + pub fn checker(&self) -> &Arc> { + &self.checker + } + + /// Extracts the queue of requests. + /// + /// Whenever one of the methods of the `Fetcher` trait is called, an element is pushed on this + /// channel. + /// + /// If this function returns `None`, that means that the receiver has already been extracted in + /// the past, and therefore that something already handles the requests. + pub(crate) fn extract_receiver(&self) -> Option>> { + self.requests_queue.lock().take() + } +} + +impl Fetcher for OnDemand where + B: BlockT, + B::Header: HeaderT, +{ + type RemoteHeaderResult = RemoteResponse; + type RemoteReadResult = RemoteResponse, Option>>>; + type RemoteCallResult = RemoteResponse>; + type RemoteChangesResult = RemoteResponse, u32)>>; + type RemoteBodyResult = RemoteResponse>; + + fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult { + let (sender, receiver) = oneshot::channel(); + let _ = self.requests_send.unbounded_send(RequestData::RemoteHeader(request, sender)); + RemoteResponse { receiver } + } + + fn remote_read(&self, request: RemoteReadRequest) -> Self::RemoteReadResult { + let (sender, receiver) = oneshot::channel(); + let _ = self.requests_send.unbounded_send(RequestData::RemoteRead(request, sender)); + RemoteResponse { receiver } + } + + fn remote_read_child( + &self, + request: RemoteReadChildRequest + ) -> Self::RemoteReadResult { + let (sender, receiver) = oneshot::channel(); + let _ = self.requests_send.unbounded_send(RequestData::RemoteReadChild(request, sender)); + RemoteResponse { receiver } + } + + fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult { + let (sender, receiver) = oneshot::channel(); + let _ = self.requests_send.unbounded_send(RequestData::RemoteCall(request, sender)); + RemoteResponse { receiver } + } + + fn remote_changes(&self, request: RemoteChangesRequest) -> Self::RemoteChangesResult { + let (sender, receiver) = oneshot::channel(); + let _ = self.requests_send.unbounded_send(RequestData::RemoteChanges(request, sender)); + RemoteResponse { receiver } + } + + fn remote_body(&self, request: RemoteBodyRequest) -> Self::RemoteBodyResult { + let (sender, receiver) = oneshot::channel(); + let _ = self.requests_send.unbounded_send(RequestData::RemoteBody(request, sender)); + RemoteResponse { receiver } + } +} + +/// Future for an on-demand remote call response. +pub struct RemoteResponse { + receiver: oneshot::Receiver>, +} + +impl Future for RemoteResponse { + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + match self.receiver.poll_unpin(cx) { + Poll::Ready(Ok(res)) => Poll::Ready(res), + Poll::Ready(Err(_)) => Poll::Ready(Err(From::from(ClientError::RemoteFetchCancelled))), + Poll::Pending => Poll::Pending, + } + } +} diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs new file mode 100644 index 0000000000000..b712ebe515512 --- /dev/null +++ b/client/network/src/protocol.rs @@ -0,0 +1,1985 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::{DiscoveryNetBehaviour, config::ProtocolId}; +use legacy_proto::{LegacyProto, LegacyProtoOut}; +use crate::utils::interval; +use bytes::{Bytes, BytesMut}; +use futures::prelude::*; +use libp2p::{Multiaddr, PeerId}; +use libp2p::core::{ConnectedPoint, nodes::Substream, muxing::StreamMuxerBox}; +use libp2p::swarm::{ProtocolsHandler, IntoProtocolsHandler}; +use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; +use sp_core::storage::{StorageKey, ChildInfo}; +use sp_consensus::{ + BlockOrigin, + block_validation::BlockAnnounceValidator, + import_queue::{BlockImportResult, BlockImportError, IncomingBlock, Origin} +}; +use codec::{Decode, Encode}; +use sp_runtime::{generic::BlockId, ConsensusEngineId, Justification}; +use sp_runtime::traits::{ + Block as BlockT, Header as HeaderT, NumberFor, One, Zero, CheckedSub +}; +use sp_arithmetic::traits::SaturatedConversion; +use message::{BlockAnnounce, BlockAttributes, Direction, FromBlock, Message, RequestId}; +use message::generic::{Message as GenericMessage, ConsensusMessage}; +use light_dispatch::{LightDispatch, LightDispatchNetwork, RequestData}; +use specialization::NetworkSpecialization; +use sync::{ChainSync, SyncState}; +use crate::service::{TransactionPool, ExHashT}; +use crate::config::{BoxFinalityProofRequestBuilder, Roles}; +use rustc_hex::ToHex; +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::sync::Arc; +use std::fmt::Write; +use std::{cmp, num::NonZeroUsize, pin::Pin, task::Poll, time}; +use log::{log, Level, trace, debug, warn, error}; +use crate::chain::{Client, FinalityProofProvider}; +use sc_client_api::{FetchChecker, ChangesProof, StorageProof}; +use crate::error; +use util::LruHashSet; + +mod legacy_proto; +mod util; + +pub mod message; +pub mod event; +pub mod light_dispatch; +pub mod specialization; +pub mod sync; + +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); + +/// Maximim number of known block hashes to keep for a peer. +const MAX_KNOWN_BLOCKS: usize = 1024; // ~32kb per peer + LruHashSet overhead +/// Maximim number of known extrinsic hashes to keep for a peer. +const MAX_KNOWN_EXTRINSICS: usize = 4096; // ~128kb per peer + overhead + +/// Current protocol version. +pub(crate) const CURRENT_VERSION: u32 = 5; +/// Lowest version we support +pub(crate) const MIN_VERSION: u32 = 3; + +// Maximum allowed entries in `BlockResponse` +const MAX_BLOCK_DATA_RESPONSE: u32 = 128; +/// When light node connects to the full node and the full node is behind light node +/// for at least `LIGHT_MAXIMAL_BLOCKS_DIFFERENCE` blocks, we consider it unuseful +/// and disconnect to free connection slot. +const LIGHT_MAXIMAL_BLOCKS_DIFFERENCE: u64 = 8192; + +mod rep { + use sc_peerset::ReputationChange as Rep; + /// Reputation change when a peer is "clogged", meaning that it's not fast enough to process our + /// messages. + pub const CLOGGED_PEER: Rep = Rep::new(-(1 << 12), "Clogged message queue"); + /// Reputation change when a peer doesn't respond in time to our messages. + pub const TIMEOUT: Rep = Rep::new(-(1 << 10), "Request timeout"); + /// Reputation change when a peer sends us a status message while we already received one. + pub const UNEXPECTED_STATUS: Rep = Rep::new(-(1 << 20), "Unexpected status message"); + /// Reputation change when we are a light client and a peer is behind us. + pub const PEER_BEHIND_US_LIGHT: Rep = Rep::new(-(1 << 8), "Useless for a light peer"); + /// Reputation change when a peer sends us an extrinsic that we didn't know about. + pub const GOOD_EXTRINSIC: Rep = Rep::new(1 << 7, "Good extrinsic"); + /// Reputation change when a peer sends us a bad extrinsic. + pub const BAD_EXTRINSIC: Rep = Rep::new(-(1 << 12), "Bad extrinsic"); + /// We sent an RPC query to the given node, but it failed. + pub const RPC_FAILED: Rep = Rep::new(-(1 << 12), "Remote call failed"); + /// We received a message that failed to decode. + pub const BAD_MESSAGE: Rep = Rep::new(-(1 << 12), "Bad message"); + /// We received an unexpected response. + pub const UNEXPECTED_RESPONSE: Rep = Rep::new_fatal("Unexpected response packet"); + /// We received an unexpected extrinsic packet. + pub const UNEXPECTED_EXTRINSICS: Rep = Rep::new_fatal("Unexpected extrinsics packet"); + /// We received an unexpected light node request. + pub const UNEXPECTED_REQUEST: Rep = Rep::new_fatal("Unexpected block request packet"); + /// Peer has different genesis. + pub const GENESIS_MISMATCH: Rep = Rep::new_fatal("Genesis mismatch"); + /// Peer is on unsupported protocol version. + pub const BAD_PROTOCOL: Rep = Rep::new_fatal("Unsupported protocol"); + /// Peer role does not match (e.g. light peer connecting to another light peer). + pub const BAD_ROLE: Rep = Rep::new_fatal("Unsupported role"); +} + +// Lock must always be taken in order declared here. +pub struct Protocol, H: ExHashT> { + /// Interval at which we call `tick`. + tick_timeout: Pin + Send>>, + /// Interval at which we call `propagate_extrinsics`. + propagate_timeout: Pin + Send>>, + config: ProtocolConfig, + /// Handler for light client requests. + light_dispatch: LightDispatch, + genesis_hash: B::Hash, + sync: ChainSync, + specialization: S, + context_data: ContextData, + /// List of nodes for which we perform additional logging because they are important for the + /// user. + important_peers: HashSet, + // Connected peers pending Status message. + handshaking_peers: HashMap, + /// Used to report reputation changes. + peerset_handle: sc_peerset::PeersetHandle, + transaction_pool: Arc>, + /// When asked for a proof of finality, we use this struct to build one. + finality_proof_provider: Option>>, + /// Handles opening the unique substream and sending and receiving raw messages. + behaviour: LegacyProto>, + /// List of notification protocols that have been registered. + registered_notif_protocols: HashSet, +} + +#[derive(Default)] +struct PacketStats { + bytes_in: u64, + bytes_out: u64, + count_in: u64, + count_out: u64, +} + +/// A peer that we are connected to +/// and from whom we have not yet received a Status message. +struct HandshakingPeer { + timestamp: time::Instant, +} + +/// Peer information +#[derive(Debug, Clone)] +struct Peer { + 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: LruHashSet, + /// Holds a set of blocks known to this peer. + known_blocks: LruHashSet, + /// Request counter, + next_request_id: message::RequestId, +} + +/// Info about a peer's known state. +#[derive(Clone, Debug)] +pub struct PeerInfo { + /// Roles + pub roles: Roles, + /// Protocol version + pub protocol_version: u32, + /// Peer best block hash + pub best_hash: B::Hash, + /// Peer best block number + pub best_number: ::Number, +} + +struct LightDispatchIn<'a> { + behaviour: &'a mut LegacyProto>, + peerset: sc_peerset::PeersetHandle, +} + +impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a> { + fn report_peer(&mut self, who: &PeerId, reputation: sc_peerset::ReputationChange) { + self.peerset.report_peer(who.clone(), reputation) + } + + fn disconnect_peer(&mut self, who: &PeerId) { + self.behaviour.disconnect_peer(who) + } + + fn send_header_request(&mut self, who: &PeerId, id: RequestId, block: <::Header as HeaderT>::Number) { + let message: Message = message::generic::Message::RemoteHeaderRequest(message::RemoteHeaderRequest { + id, + block, + }); + + self.behaviour.send_packet(who, message.encode()) + } + + fn send_read_request( + &mut self, + who: &PeerId, + id: RequestId, + block: ::Hash, + keys: Vec>, + ) { + let message: Message = message::generic::Message::RemoteReadRequest(message::RemoteReadRequest { + id, + block, + keys, + }); + + self.behaviour.send_packet(who, message.encode()) + } + + fn send_read_child_request( + &mut self, + who: &PeerId, + id: RequestId, + block: ::Hash, + storage_key: Vec, + child_info: Vec, + child_type: u32, + keys: Vec>, + ) { + let message: Message = message::generic::Message::RemoteReadChildRequest(message::RemoteReadChildRequest { + id, + block, + storage_key, + child_info, + child_type, + keys, + }); + + self.behaviour.send_packet(who, message.encode()) + } + + fn send_call_request( + &mut self, + who: &PeerId, + id: RequestId, + block: ::Hash, + method: String, + data: Vec + ) { + let message: Message = message::generic::Message::RemoteCallRequest(message::RemoteCallRequest { + id, + block, + method, + data, + }); + + self.behaviour.send_packet(who, message.encode()) + } + + fn send_changes_request( + &mut self, + who: &PeerId, + id: RequestId, + first: ::Hash, + last: ::Hash, + min: ::Hash, + max: ::Hash, + storage_key: Option>, + key: Vec, + ) { + let message: Message = message::generic::Message::RemoteChangesRequest(message::RemoteChangesRequest { + id, + first, + last, + min, + max, + storage_key, + key, + }); + + self.behaviour.send_packet(who, message.encode()) + } + + fn send_body_request( + &mut self, + who: &PeerId, + id: RequestId, + fields: BlockAttributes, + from: FromBlock<::Hash, <::Header as HeaderT>::Number>, + to: Option<::Hash>, + direction: Direction, + max: Option + ) { + let message: Message = message::generic::Message::BlockRequest(message::BlockRequest:: { + id, + fields, + from, + to, + direction, + max, + }); + + self.behaviour.send_packet(who, message.encode()) + } +} + +/// Context for a network-specific handler. +pub trait Context { + /// Adjusts the reputation of the peer. Use this to point out that a peer has been malign or + /// irresponsible or appeared lazy. + fn report_peer(&mut self, who: PeerId, reputation: sc_peerset::ReputationChange); + + /// Force disconnecting from a peer. Use this when a peer misbehaved. + fn disconnect_peer(&mut self, who: PeerId); + + /// Send a chain-specific message to a peer. + fn send_chain_specific(&mut self, who: PeerId, message: Vec); +} + +/// Protocol context. +struct ProtocolContext<'a, B: 'a + BlockT, H: 'a + ExHashT> { + behaviour: &'a mut LegacyProto>, + context_data: &'a mut ContextData, + peerset_handle: &'a sc_peerset::PeersetHandle, +} + +impl<'a, B: BlockT + 'a, H: 'a + ExHashT> ProtocolContext<'a, B, H> { + fn new( + context_data: &'a mut ContextData, + behaviour: &'a mut LegacyProto>, + peerset_handle: &'a sc_peerset::PeersetHandle, + ) -> Self { + ProtocolContext { context_data, peerset_handle, behaviour } + } +} + +impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context for ProtocolContext<'a, B, H> { + fn report_peer(&mut self, who: PeerId, reputation: sc_peerset::ReputationChange) { + self.peerset_handle.report_peer(who, reputation) + } + + fn disconnect_peer(&mut self, who: PeerId) { + self.behaviour.disconnect_peer(&who) + } + + fn send_chain_specific(&mut self, who: PeerId, message: Vec) { + send_message:: ( + self.behaviour, + &mut self.context_data.stats, + &who, + GenericMessage::ChainSpecific(message) + ) + } +} + +/// Data necessary to create a context. +struct ContextData { + // All connected peers + peers: HashMap>, + stats: HashMap<&'static str, PacketStats>, + pub chain: Arc>, +} + +/// Configuration for the Substrate-specific part of the networking layer. +#[derive(Clone)] +pub struct ProtocolConfig { + /// Assigned roles. + pub roles: Roles, + /// Maximum number of peers to ask the same blocks in parallel. + pub max_parallel_downloads: u32, +} + +impl Default for ProtocolConfig { + fn default() -> ProtocolConfig { + ProtocolConfig { + roles: Roles::FULL, + max_parallel_downloads: 5, + } + } +} + +impl, H: ExHashT> Protocol { + /// Create a new instance. + pub fn new( + config: ProtocolConfig, + chain: Arc>, + checker: Arc>, + specialization: S, + transaction_pool: Arc>, + finality_proof_provider: Option>>, + finality_proof_request_builder: Option>, + protocol_id: ProtocolId, + peerset_config: sc_peerset::PeersetConfig, + block_announce_validator: Box + Send> + ) -> error::Result<(Protocol, sc_peerset::PeersetHandle)> { + let info = chain.info(); + let sync = ChainSync::new( + config.roles, + chain.clone(), + &info, + finality_proof_request_builder, + block_announce_validator, + config.max_parallel_downloads, + ); + + let important_peers = { + let mut imp_p = HashSet::new(); + for reserved in &peerset_config.reserved_nodes { + imp_p.insert(reserved.clone()); + } + imp_p.shrink_to_fit(); + imp_p + }; + + let (peerset, peerset_handle) = sc_peerset::Peerset::from_config(peerset_config); + let versions = &((MIN_VERSION as u8)..=(CURRENT_VERSION as u8)).collect::>(); + let behaviour = LegacyProto::new(protocol_id, versions, peerset); + + let protocol = Protocol { + tick_timeout: Box::pin(interval(TICK_TIMEOUT)), + propagate_timeout: Box::pin(interval(PROPAGATE_TIMEOUT)), + config, + context_data: ContextData { + peers: HashMap::new(), + stats: HashMap::new(), + chain, + }, + light_dispatch: LightDispatch::new(checker), + genesis_hash: info.genesis_hash, + sync, + specialization, + handshaking_peers: HashMap::new(), + important_peers, + transaction_pool, + finality_proof_provider, + peerset_handle: peerset_handle.clone(), + behaviour, + registered_notif_protocols: HashSet::new(), + }; + + Ok((protocol, peerset_handle)) + } + + /// Returns the list of all the peers we have an open channel to. + pub fn open_peers(&self) -> impl Iterator { + self.behaviour.open_peers() + } + + /// Returns true if we have a channel open with this node. + pub fn is_open(&self, peer_id: &PeerId) -> bool { + self.behaviour.is_open(peer_id) + } + + /// Disconnects the given peer if we are connected to it. + pub fn disconnect_peer(&mut self, peer_id: &PeerId) { + self.behaviour.disconnect_peer(peer_id) + } + + /// Returns true if we try to open protocols with the given peer. + pub fn is_enabled(&self, peer_id: &PeerId) -> bool { + self.behaviour.is_enabled(peer_id) + } + + /// Returns the state of the peerset manager, for debugging purposes. + pub fn peerset_debug_info(&mut self) -> serde_json::Value { + self.behaviour.peerset_debug_info() + } + + /// Returns the number of peers we're connected to. + pub fn num_connected_peers(&self) -> usize { + self.context_data.peers.values().count() + } + + /// Returns the number of peers we're connected to and that are being queried. + pub fn num_active_peers(&self) -> usize { + self.context_data + .peers + .values() + .filter(|p| p.block_request.is_some()) + .count() + } + + /// Current global sync state. + pub fn sync_state(&self) -> SyncState { + self.sync.status().state + } + + /// Target sync block number. + pub fn best_seen_block(&self) -> Option> { + self.sync.status().best_seen_block + } + + /// Number of peers participating in syncing. + pub fn num_sync_peers(&self) -> u32 { + self.sync.status().num_peers + } + + /// Number of blocks in the import queue. + pub fn num_queued_blocks(&self) -> u32 { + self.sync.status().queued_blocks + } + + /// Number of active sync requests. + pub fn num_sync_requests(&self) -> usize { + self.sync.num_sync_requests() + } + + /// Starts a new data demand request. + /// + /// The parameter contains a `Sender` where the result, once received, must be sent. + pub(crate) fn add_light_client_request(&mut self, rq: RequestData) { + self.light_dispatch.add_request(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, rq); + } + + fn is_light_response(&self, who: &PeerId, response_id: message::RequestId) -> bool { + self.light_dispatch.is_light_response(&who, response_id) + } + + fn handle_response( + &mut self, + who: PeerId, + response: &message::BlockResponse + ) -> Option> { + if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { + if let Some(_) = peer.obsolete_requests.remove(&response.id) { + trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", who, response.id); + return None; + } + // Clear the request. If the response is invalid peer will be disconnected anyway. + let request = peer.block_request.take(); + if request.as_ref().map_or(false, |(_, r)| r.id == response.id) { + return request.map(|(_, r)| r) + } + trace!(target: "sync", "Unexpected response packet from {} ({})", who, response.id); + self.peerset_handle.report_peer(who.clone(), rep::UNEXPECTED_RESPONSE); + self.behaviour.disconnect_peer(&who); + } + None + } + + fn update_peer_info(&mut self, who: &PeerId) { + if let Some(info) = self.sync.peer_info(who) { + if let Some(ref mut peer) = self.context_data.peers.get_mut(who) { + peer.info.best_hash = info.best_hash; + peer.info.best_number = info.best_number; + } + } + } + + /// Returns information about all the peers we are connected to after the handshake message. + pub fn peers_info(&self) -> impl Iterator)> { + self.context_data.peers.iter().map(|(id, peer)| (id, &peer.info)) + } + + pub fn on_custom_message( + &mut self, + who: PeerId, + data: BytesMut, + ) -> CustomMessageOutcome { + + let message = match as Decode>::decode(&mut &data[..]) { + Ok(message) => message, + Err(err) => { + debug!(target: "sync", "Couldn't decode packet sent by {}: {:?}: {}", who, data, err.what()); + self.peerset_handle.report_peer(who.clone(), rep::BAD_MESSAGE); + return CustomMessageOutcome::None; + } + }; + + let mut stats = self.context_data.stats.entry(message.id()).or_default(); + stats.bytes_in += data.len() as u64; + stats.count_in += 1; + + match message { + GenericMessage::Status(s) => return self.on_status_message(who, s), + GenericMessage::BlockRequest(r) => self.on_block_request(who, r), + GenericMessage::BlockResponse(r) => { + // Note, this is safe because only `ordinary bodies` and `remote bodies` are received in this matter. + if self.is_light_response(&who, r.id) { + self.on_remote_body_response(who, r); + } else { + if let Some(request) = self.handle_response(who.clone(), &r) { + let outcome = self.on_block_response(who.clone(), request, r); + self.update_peer_info(&who); + return outcome + } + } + }, + GenericMessage::BlockAnnounce(announce) => { + let outcome = self.on_block_announce(who.clone(), announce); + self.update_peer_info(&who); + return outcome; + }, + 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::FinalityProofRequest(request) => + self.on_finality_proof_request(who, request), + GenericMessage::FinalityProofResponse(response) => + return self.on_finality_proof_response(who, response), + GenericMessage::RemoteReadChildRequest(request) => + self.on_remote_read_child_request(who, request), + GenericMessage::Consensus(msg) => + return if self.registered_notif_protocols.contains(&msg.engine_id) { + CustomMessageOutcome::NotificationsReceived { + remote: who.clone(), + messages: vec![(msg.engine_id, From::from(msg.data))], + } + } else { + warn!(target: "sync", "Received message on non-registered protocol: {:?}", msg.engine_id); + CustomMessageOutcome::None + }, + GenericMessage::ConsensusBatch(messages) => { + let messages = messages + .into_iter() + .filter_map(|msg| { + if self.registered_notif_protocols.contains(&msg.engine_id) { + Some((msg.engine_id, From::from(msg.data))) + } else { + warn!(target: "sync", "Received message on non-registered protocol: {:?}", msg.engine_id); + None + } + }) + .collect::>(); + + return if !messages.is_empty() { + CustomMessageOutcome::NotificationsReceived { + remote: who.clone(), + messages, + } + } else { + CustomMessageOutcome::None + }; + }, + GenericMessage::ChainSpecific(msg) => self.specialization.on_message( + &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle), + who, + msg, + ), + } + + CustomMessageOutcome::None + } + + fn send_request(&mut self, who: &PeerId, message: Message) { + send_request::( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + who, + message, + ); + } + + fn send_message(&mut self, who: &PeerId, message: Message) { + send_message::( + &mut self.behaviour, + &mut self.context_data.stats, + who, + message, + ); + } + + /// Locks `self` and returns a context plus the network specialization. + pub fn specialization_lock<'a>( + &'a mut self, + ) -> (impl Context + 'a, &'a mut S) { + let context = ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle); + (context, &mut self.specialization) + } + + /// Called when a new peer is connected + pub fn on_peer_connected(&mut self, who: PeerId) { + trace!(target: "sync", "Connecting {}", who); + self.handshaking_peers.insert(who.clone(), HandshakingPeer { timestamp: time::Instant::now() }); + self.send_status(who); + } + + /// Called by peer when it is disconnecting + pub fn on_peer_disconnected(&mut self, peer: PeerId) { + if self.important_peers.contains(&peer) { + warn!(target: "sync", "Reserved peer {} disconnected", peer); + } else { + trace!(target: "sync", "{} disconnected", peer); + } + + // lock all the the peer lists so that add/remove peer events are in order + let removed = { + self.handshaking_peers.remove(&peer); + self.context_data.peers.remove(&peer) + }; + if let Some(_peer_data) = removed { + let mut context = ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle); + self.sync.peer_disconnected(peer.clone()); + self.specialization.on_disconnect(&mut context, peer.clone()); + self.light_dispatch.on_disconnect(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, peer); + } + } + + /// 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: PeerId, _msg: Option>) { + self.peerset_handle.report_peer(who.clone(), rep::CLOGGED_PEER); + + // Print some diagnostics. + if let Some(peer) = self.context_data.peers.get(&who) { + debug!(target: "sync", "Clogged peer {} (protocol_version: {:?}; roles: {:?}; \ + known_extrinsics: {:?}; known_blocks: {:?}; best_hash: {:?}; best_number: {:?})", + who, peer.info.protocol_version, peer.info.roles, peer.known_extrinsics, peer.known_blocks, + 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: PeerId, + request: message::BlockRequest + ) { + trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", + request.id, + peer, + request.from, + request.to, + request.max); + + // sending block requests to the node that is unable to serve it is considered a bad behavior + if !self.config.roles.is_full() { + trace!(target: "sync", "Peer {} is trying to sync from the light node", peer); + self.behaviour.disconnect_peer(&peer); + self.peerset_handle.report_peer(peer, rep::UNEXPECTED_REQUEST); + return; + } + + 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; + 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); + 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 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 + }, + receipt: None, + message_queue: None, + justification, + }; + blocks.push(block_data); + match request.direction { + message::Direction::Ascending => id = BlockId::Number(number + One::one()), + message::Direction::Descending => { + if number.is_zero() { + break; + } + id = BlockId::Hash(parent_hash) + } + } + } + let response = message::generic::BlockResponse { + id: request.id, + blocks: blocks, + }; + trace!(target: "sync", "Sending BlockResponse with {} blocks", response.blocks.len()); + self.send_message(&peer, GenericMessage::BlockResponse(response)) + } + + /// Adjusts the reputation of a node. + pub fn report_peer(&self, who: PeerId, reputation: sc_peerset::ReputationChange) { + self.peerset_handle.report_peer(who, reputation) + } + + fn on_block_response( + &mut self, + peer: PeerId, + request: message::BlockRequest, + response: message::BlockResponse, + ) -> CustomMessageOutcome { + 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())), + ) { + (Some(first), Some(last)) if first != last => format!(" ({}..{})", first, last), + (Some(first), Some(_)) => format!(" ({})", first), + _ => Default::default(), + }; + trace!(target: "sync", "BlockResponse {} from {} with {} blocks {}", + response.id, + peer, + response.blocks.len(), + blocks_range + ); + + // TODO [andre]: move this logic to the import queue so that + // justifications are imported asynchronously (#1482) + if request.fields == message::BlockAttributes::JUSTIFICATION { + match self.sync.on_block_justification(peer, response) { + Ok(sync::OnBlockJustification::Nothing) => CustomMessageOutcome::None, + Ok(sync::OnBlockJustification::Import { peer, hash, number, justification }) => + CustomMessageOutcome::JustificationImport(peer, hash, number, justification), + Err(sync::BadPeer(id, repu)) => { + self.behaviour.disconnect_peer(&id); + self.peerset_handle.report_peer(id, repu); + CustomMessageOutcome::None + } + } + } else { + match self.sync.on_block_data(peer, Some(request), response) { + Ok(sync::OnBlockData::Import(origin, blocks)) => + CustomMessageOutcome::BlockImport(origin, blocks), + Ok(sync::OnBlockData::Request(peer, req)) => { + self.send_request(&peer, GenericMessage::BlockRequest(req)); + CustomMessageOutcome::None + } + Err(sync::BadPeer(id, repu)) => { + self.behaviour.disconnect_peer(&id); + self.peerset_handle.report_peer(id, repu); + CustomMessageOutcome::None + } + } + } + } + + /// Perform time based maintenance. + /// + /// > **Note**: This method normally doesn't have to be called except for testing purposes. + pub fn tick(&mut self) { + self.maintain_peers(); + self.light_dispatch.maintain_peers(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }); + } + + fn maintain_peers(&mut self) { + let tick = time::Instant::now(); + let mut aborting = Vec::new(); + { + 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) { + log!( + target: "sync", + if self.important_peers.contains(&who) { Level::Warn } else { Level::Trace }, + "Request timeout {}", who + ); + aborting.push(who.clone()); + } else if peer.obsolete_requests.values().any(|t| (tick - *t).as_secs() > REQUEST_TIMEOUT_SEC) { + log!( + target: "sync", + if self.important_peers.contains(&who) { Level::Warn } else { Level::Trace }, + "Obsolete timeout {}", who + ); + aborting.push(who.clone()); + } + } + for (who, _) in self.handshaking_peers.iter() + .filter(|(_, handshaking)| (tick - handshaking.timestamp).as_secs() > REQUEST_TIMEOUT_SEC) + { + log!( + target: "sync", + if self.important_peers.contains(&who) { Level::Warn } else { Level::Trace }, + "Handshake timeout {}", who + ); + aborting.push(who.clone()); + } + } + + self.specialization.maintain_peers( + &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle) + ); + for p in aborting { + self.behaviour.disconnect_peer(&p); + self.peerset_handle.report_peer(p, rep::TIMEOUT); + } + } + + /// Called by peer to report status + fn on_status_message(&mut self, who: PeerId, status: message::Status) -> CustomMessageOutcome { + trace!(target: "sync", "New peer {} {:?}", who, status); + let _protocol_version = { + if self.context_data.peers.contains_key(&who) { + log!( + target: "sync", + if self.important_peers.contains(&who) { Level::Warn } else { Level::Debug }, + "Unexpected status packet from {}", who + ); + self.peerset_handle.report_peer(who, rep::UNEXPECTED_STATUS); + return CustomMessageOutcome::None; + } + if status.genesis_hash != self.genesis_hash { + log!( + target: "sync", + if self.important_peers.contains(&who) { Level::Warn } else { Level::Trace }, + "Peer is on different chain (our genesis: {} theirs: {})", + self.genesis_hash, status.genesis_hash + ); + self.peerset_handle.report_peer(who.clone(), rep::GENESIS_MISMATCH); + self.behaviour.disconnect_peer(&who); + return CustomMessageOutcome::None; + } + if status.version < MIN_VERSION && CURRENT_VERSION < status.min_supported_version { + log!( + target: "sync", + if self.important_peers.contains(&who) { Level::Warn } else { Level::Trace }, + "Peer {:?} using unsupported protocol version {}", who, status.version + ); + self.peerset_handle.report_peer(who.clone(), rep::BAD_PROTOCOL); + self.behaviour.disconnect_peer(&who); + return CustomMessageOutcome::None; + } + + if self.config.roles.is_light() { + // we're not interested in light peers + if status.roles.is_light() { + debug!(target: "sync", "Peer {} is unable to serve light requests", who); + self.peerset_handle.report_peer(who.clone(), rep::BAD_ROLE); + self.behaviour.disconnect_peer(&who); + return CustomMessageOutcome::None; + } + + // we don't interested in peers that are far behind us + let self_best_block = self + .context_data + .chain + .info() + .best_number; + let blocks_difference = self_best_block + .checked_sub(&status.best_number) + .unwrap_or_else(Zero::zero) + .saturated_into::(); + if blocks_difference > LIGHT_MAXIMAL_BLOCKS_DIFFERENCE { + debug!(target: "sync", "Peer {} is far behind us and will unable to serve light requests", who); + self.peerset_handle.report_peer(who.clone(), rep::PEER_BEHIND_US_LIGHT); + self.behaviour.disconnect_peer(&who); + return CustomMessageOutcome::None; + } + } + + let info = match self.handshaking_peers.remove(&who) { + Some(_handshaking) => { + PeerInfo { + protocol_version: status.version, + roles: status.roles, + best_hash: status.best_hash, + best_number: status.best_number + } + }, + None => { + error!(target: "sync", "Received status from previously unconnected node {}", who); + return CustomMessageOutcome::None; + }, + }; + + let peer = Peer { + info, + block_request: None, + known_extrinsics: LruHashSet::new(NonZeroUsize::new(MAX_KNOWN_EXTRINSICS) + .expect("Constant is nonzero")), + known_blocks: LruHashSet::new(NonZeroUsize::new(MAX_KNOWN_BLOCKS) + .expect("Constant is nonzero")), + next_request_id: 0, + obsolete_requests: HashMap::new(), + }; + self.context_data.peers.insert(who.clone(), peer); + + debug!(target: "sync", "Connected {}", who); + status.version + }; + + let info = self.context_data.peers.get(&who).expect("We just inserted above; QED").info.clone(); + self.light_dispatch.on_connect(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, who.clone(), status.roles, status.best_number); + if info.roles.is_full() { + match self.sync.new_peer(who.clone(), info.best_hash, info.best_number) { + Ok(None) => (), + Ok(Some(req)) => self.send_request(&who, GenericMessage::BlockRequest(req)), + Err(sync::BadPeer(id, repu)) => { + self.behaviour.disconnect_peer(&id); + self.peerset_handle.report_peer(id, repu) + } + } + } + + let mut context = ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle); + self.specialization.on_connect(&mut context, who.clone(), status); + + // Notify all the notification protocols as open. + CustomMessageOutcome::NotificationStreamOpened { + remote: who, + protocols: self.registered_notif_protocols.iter().cloned().collect(), + roles: info.roles, + } + } + + /// Send a notification to the given peer we're connected to. + /// + /// Doesn't do anything if we don't have a notifications substream for that protocol with that + /// peer. + pub fn write_notification( + &mut self, + target: PeerId, + engine_id: ConsensusEngineId, + message: impl Into> + ) { + if !self.registered_notif_protocols.contains(&engine_id) { + error!( + target: "sub-libp2p", + "Sending a notification with a protocol that wasn't registered: {:?}", + engine_id + ); + } + + self.send_message(&target, GenericMessage::Consensus(ConsensusMessage { + engine_id, + data: message.into(), + })); + } + + /// Registers a new notifications protocol. + /// + /// You are very strongly encouraged to call this method very early on. Any connection open + /// will retain the protocols that were registered then, and not any new one. + pub fn register_notifications_protocol( + &mut self, + engine_id: ConsensusEngineId, + ) -> Vec { + if !self.registered_notif_protocols.insert(engine_id) { + error!(target: "sub-libp2p", "Notifications protocol already registered: {:?}", engine_id); + } + + // Registering a protocol while we already have open connections isn't great, but for now + // we handle it by notifying that we opened channels with everyone. + self.context_data.peers.iter() + .map(|(peer_id, peer)| + event::Event::NotificationStreamOpened { + remote: peer_id.clone(), + engine_id, + roles: peer.info.roles, + }) + .collect() + } + + /// Called when peer sends us new extrinsics + fn on_extrinsics( + &mut self, + who: PeerId, + extrinsics: message::Transactions + ) { + // sending extrinsic to light node is considered a bad behavior + if !self.config.roles.is_full() { + trace!(target: "sync", "Peer {} is trying to send extrinsic to the light node", who); + self.behaviour.disconnect_peer(&who); + self.peerset_handle.report_peer(who, rep::UNEXPECTED_EXTRINSICS); + return; + } + + // Accept extrinsics only when fully synced + 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); + if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { + for t in extrinsics { + let hash = self.transaction_pool.hash_of(&t); + peer.known_extrinsics.insert(hash); + + self.transaction_pool.import( + self.peerset_handle.clone().into(), + who.clone(), + rep::GOOD_EXTRINSIC, + rep::BAD_EXTRINSIC, + t, + ); + } + } + } + + /// Call when we must propagate ready extrinsics to peers. + pub fn propagate_extrinsics( + &mut self, + ) { + debug!(target: "sync", "Propagating extrinsics"); + + // Accept transactions only when fully synced + if self.sync.status().state != SyncState::Idle { + return; + } + + let extrinsics = self.transaction_pool.transactions(); + let mut propagated_to = HashMap::new(); + for (who, peer) in self.context_data.peers.iter_mut() { + // never send extrinsics to the light node + if !peer.info.roles.is_full() { + continue; + } + + let (hashes, to_send): (Vec<_>, Vec<_>) = extrinsics + .iter() + .filter(|&(ref hash, _)| peer.known_extrinsics.insert(hash.clone())) + .cloned() + .unzip(); + + if !to_send.is_empty() { + for hash in hashes { + propagated_to + .entry(hash) + .or_insert_with(Vec::new) + .push(who.to_base58()); + } + trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), who); + send_message:: ( + &mut self.behaviour, + &mut self.context_data.stats, + &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, data: Vec) { + 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; + } + }; + + // don't announce genesis block since it will be ignored + if header.number().is_zero() { + return; + } + + let is_best = self.context_data.chain.info().best_hash == hash; + debug!(target: "sync", "Reannouncing block {:?}", hash); + self.send_announcement(&header, data, is_best, true) + } + + fn send_announcement(&mut self, header: &B::Header, data: Vec, is_best: bool, force: bool) { + let hash = header.hash(); + + for (who, ref mut peer) in self.context_data.peers.iter_mut() { + trace!(target: "sync", "Announcing block {:?} to {}", hash, who); + let inserted = peer.known_blocks.insert(hash); + if inserted || force { + let message: Message = GenericMessage::BlockAnnounce(message::BlockAnnounce { + header: header.clone(), + state: if peer.info.protocol_version >= 4 { + if is_best { + Some(message::BlockState::Best) + } else { + Some(message::BlockState::Normal) + } + } else { + None + }, + data: if peer.info.protocol_version >= 4 { + Some(data.clone()) + } else { + None + }, + }); + + send_message:: ( + &mut self.behaviour, + &mut self.context_data.stats, + &who, + message, + ) + } + } + } + + /// Send Status message + fn send_status(&mut self, who: PeerId) { + let info = self.context_data.chain.info(); + let status = message::generic::Status { + version: CURRENT_VERSION, + min_supported_version: MIN_VERSION, + genesis_hash: info.genesis_hash, + roles: self.config.roles.into(), + best_number: info.best_number, + best_hash: info.best_hash, + chain_status: self.specialization.status(), + }; + + self.send_message(&who, GenericMessage::Status(status)) + } + + fn on_block_announce(&mut self, who: PeerId, announce: BlockAnnounce) -> CustomMessageOutcome { + let hash = announce.header.hash(); + if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { + peer.known_blocks.insert(hash.clone()); + } + self.light_dispatch.update_best_number(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, who.clone(), *announce.header.number()); + + let is_their_best = match announce.state.unwrap_or(message::BlockState::Best) { + message::BlockState::Best => true, + message::BlockState::Normal => false, + }; + + match self.sync.on_block_announce(who.clone(), hash, &announce, is_their_best) { + sync::OnBlockAnnounce::Nothing => { + // `on_block_announce` returns `OnBlockAnnounce::ImportHeader` + // when we have all data required to import the block + // in the BlockAnnounce message. This is only when: + // 1) we're on light client; + // AND + // 2) parent block is already imported and not pruned. + return CustomMessageOutcome::None + } + sync::OnBlockAnnounce::ImportHeader => () // We proceed with the import. + } + + // to import header from announced block let's construct response to request that normally would have + // been sent over network (but it is not in our case) + let blocks_to_import = self.sync.on_block_data( + who.clone(), + None, + message::generic::BlockResponse { + id: 0, + blocks: vec![ + message::generic::BlockData { + hash: hash, + header: Some(announce.header), + body: None, + receipt: None, + message_queue: None, + justification: None, + }, + ], + }, + ); + match blocks_to_import { + Ok(sync::OnBlockData::Import(origin, blocks)) => CustomMessageOutcome::BlockImport(origin, blocks), + Ok(sync::OnBlockData::Request(peer, req)) => { + self.send_request(&peer, GenericMessage::BlockRequest(req)); + CustomMessageOutcome::None + } + Err(sync::BadPeer(id, repu)) => { + self.behaviour.disconnect_peer(&id); + self.peerset_handle.report_peer(id, repu); + CustomMessageOutcome::None + } + } + } + + /// Call this when a block has been imported in the import queue and we should announce it on + /// the network. + pub fn on_block_imported(&mut self, hash: B::Hash, header: &B::Header, data: Vec, is_best: bool) { + if is_best { + self.sync.update_chain_info(header); + } + self.specialization.on_block_imported( + &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle), + hash.clone(), + header, + ); + + // blocks are not announced by light clients + if self.config.roles.is_light() { + return; + } + + // send out block announcements + self.send_announcement(header, data, is_best, false); + } + + /// Call this when a block has been finalized. The sync layer may have some additional + /// requesting to perform. + pub fn on_block_finalized(&mut self, hash: B::Hash, header: &B::Header) { + self.sync.on_block_finalized(&hash, *header.number()) + } + + fn on_remote_call_request( + &mut self, + who: PeerId, + 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, + ) { + Ok((_, proof)) => proof, + Err(error) => { + trace!(target: "sync", "Remote call request {} from {} ({} at {}) failed with: {}", + request.id, + who, + request.method, + request.block, + error + ); + self.peerset_handle.report_peer(who.clone(), rep::RPC_FAILED); + StorageProof::empty() + } + }; + + self.send_message( + &who, + GenericMessage::RemoteCallResponse(message::RemoteCallResponse { + id: request.id, + proof, + }), + ); + } + + /// Request a justification for the given block. + /// + /// Uses `protocol` to queue a new justification request and tries to dispatch all pending + /// requests. + pub fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { + self.sync.request_justification(&hash, number) + } + + /// Request syncing for the given block from given set of peers. + /// Uses `protocol` to queue a new block download request and tries to dispatch all pending + /// requests. + pub fn set_sync_fork_request(&mut self, peers: Vec, hash: &B::Hash, number: NumberFor) { + self.sync.set_sync_fork_request(peers, hash, number) + } + + /// A batch of blocks have been processed, with or without errors. + /// Call this when a batch of blocks have been processed by the importqueue, with or without + /// errors. + pub fn blocks_processed( + &mut self, + imported: usize, + count: usize, + results: Vec<(Result>, BlockImportError>, B::Hash)> + ) { + let results = self.sync.on_blocks_processed( + imported, + count, + results, + ); + for result in results { + match result { + Ok((id, req)) => { + let msg = GenericMessage::BlockRequest(req); + send_request( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + &id, + msg + ) + } + Err(sync::BadPeer(id, repu)) => { + self.behaviour.disconnect_peer(&id); + self.peerset_handle.report_peer(id, repu) + } + } + } + } + + /// Call this when a justification has been processed by the import queue, with or without + /// errors. + pub fn justification_import_result(&mut self, hash: B::Hash, number: NumberFor, success: bool) { + self.sync.on_justification_import(hash, number, success) + } + + /// Request a finality proof for the given block. + /// + /// Queues a new finality proof request and tries to dispatch all pending requests. + pub fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { + self.sync.request_finality_proof(&hash, number) + } + + pub fn finality_proof_import_result( + &mut self, + request_block: (B::Hash, NumberFor), + finalization_result: Result<(B::Hash, NumberFor), ()>, + ) { + self.sync.on_finality_proof_import(request_block, finalization_result) + } + + fn on_remote_call_response( + &mut self, + who: PeerId, + response: message::RemoteCallResponse + ) { + trace!(target: "sync", "Remote call response {} from {}", response.id, who); + self.light_dispatch.on_remote_call_response(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, who, response); + } + + fn on_remote_read_request( + &mut self, + who: PeerId, + request: message::RemoteReadRequest, + ) { + let keys_str = || match request.keys.len() { + 1 => request.keys[0].to_hex::(), + _ => format!( + "{}..{}", + request.keys[0].to_hex::(), + request.keys[request.keys.len() - 1].to_hex::(), + ), + }; + + trace!(target: "sync", "Remote read request {} from {} ({} at {})", + request.id, who, keys_str(), request.block); + let proof = match self.context_data.chain.read_proof(&request.block, &request.keys) { + Ok(proof) => proof, + Err(error) => { + trace!(target: "sync", "Remote read request {} from {} ({} at {}) failed with: {}", + request.id, + who, + keys_str(), + request.block, + error + ); + StorageProof::empty() + } + }; + self.send_message( + &who, + GenericMessage::RemoteReadResponse(message::RemoteReadResponse { + id: request.id, + proof, + }), + ); + } + + fn on_remote_read_child_request( + &mut self, + who: PeerId, + request: message::RemoteReadChildRequest, + ) { + let keys_str = || match request.keys.len() { + 1 => request.keys[0].to_hex::(), + _ => format!( + "{}..{}", + request.keys[0].to_hex::(), + request.keys[request.keys.len() - 1].to_hex::(), + ), + }; + + trace!(target: "sync", "Remote read child request {} from {} ({} {} at {})", + request.id, who, request.storage_key.to_hex::(), keys_str(), request.block); + let proof = if let Some(child_info) = ChildInfo::resolve_child_info(request.child_type, &request.child_info[..]) { + match self.context_data.chain.read_child_proof( + &request.block, + &request.storage_key, + child_info, + &request.keys, + ) { + Ok(proof) => proof, + Err(error) => { + trace!(target: "sync", "Remote read child request {} from {} ({} {} at {}) failed with: {}", + request.id, + who, + request.storage_key.to_hex::(), + keys_str(), + request.block, + error + ); + StorageProof::empty() + } + } + } else { + trace!(target: "sync", "Remote read child request {} from {} ({} {} at {}) failed with: {}", + request.id, + who, + request.storage_key.to_hex::(), + keys_str(), + request.block, + "invalid child info and type", + ); + + StorageProof::empty() + }; + self.send_message( + &who, + GenericMessage::RemoteReadResponse(message::RemoteReadResponse { + id: request.id, + proof, + }), + ); + } + + fn on_remote_read_response( + &mut self, + who: PeerId, + response: message::RemoteReadResponse + ) { + trace!(target: "sync", "Remote read response {} from {}", response.id, who); + self.light_dispatch.on_remote_read_response(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, who, response); + } + + fn on_remote_header_request( + &mut self, + who: PeerId, + 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) { + Ok((header, proof)) => (Some(header), proof), + Err(error) => { + trace!(target: "sync", "Remote header proof request {} from {} ({}) failed with: {}", + request.id, + who, + request.block, + error + ); + (Default::default(), StorageProof::empty()) + } + }; + self.send_message( + &who, + GenericMessage::RemoteHeaderResponse(message::RemoteHeaderResponse { + id: request.id, + header, + proof, + }), + ); + } + + fn on_remote_header_response( + &mut self, + who: PeerId, + response: message::RemoteHeaderResponse, + ) { + trace!(target: "sync", "Remote header proof response {} from {}", response.id, who); + self.light_dispatch.on_remote_header_response(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, who, response); + } + + fn on_remote_changes_request( + &mut self, + who: PeerId, + request: message::RemoteChangesRequest, + ) { + trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{})", + request.id, + who, + if let Some(sk) = request.storage_key.as_ref() { + format!("{} : {}", sk.to_hex::(), request.key.to_hex::()) + } else { + request.key.to_hex::() + }, + request.first, + request.last + ); + let storage_key = request.storage_key.map(|sk| StorageKey(sk)); + let key = StorageKey(request.key); + let proof = match self.context_data.chain.key_changes_proof( + request.first, + request.last, + request.min, + request.max, + storage_key.as_ref(), + &key, + ) { + Ok(proof) => proof, + Err(error) => { + trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{}) failed with: {}", + request.id, + who, + if let Some(sk) = storage_key { + format!("{} : {}", sk.0.to_hex::(), key.0.to_hex::()) + } else { + key.0.to_hex::() + }, + request.first, + request.last, + error + ); + ChangesProof:: { + max_block: Zero::zero(), + proof: vec![], + roots: BTreeMap::new(), + roots_proof: StorageProof::empty(), + } + } + }; + 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( + &mut self, + who: PeerId, + response: message::RemoteChangesResponse, B::Hash>, + ) { + trace!(target: "sync", "Remote changes proof response {} from {} (max={})", + response.id, + who, + response.max + ); + self.light_dispatch.on_remote_changes_response(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, who, response); + } + + fn on_finality_proof_request( + &mut self, + who: PeerId, + request: message::FinalityProofRequest, + ) { + trace!(target: "sync", "Finality proof request from {} for {}", who, request.block); + let finality_proof = self.finality_proof_provider.as_ref() + .ok_or_else(|| String::from("Finality provider is not configured")) + .and_then(|provider| + provider.prove_finality(request.block, &request.request).map_err(|e| e.to_string()) + ); + let finality_proof = match finality_proof { + Ok(finality_proof) => finality_proof, + Err(error) => { + trace!(target: "sync", "Finality proof request from {} for {} failed with: {}", + who, + request.block, + error + ); + None + }, + }; + self.send_message( + &who, + GenericMessage::FinalityProofResponse(message::FinalityProofResponse { + id: 0, + block: request.block, + proof: finality_proof, + }), + ); + } + + fn on_finality_proof_response( + &mut self, + who: PeerId, + response: message::FinalityProofResponse, + ) -> CustomMessageOutcome { + trace!(target: "sync", "Finality proof response from {} for {}", who, response.block); + match self.sync.on_block_finality_proof(who, response) { + Ok(sync::OnBlockFinalityProof::Nothing) => CustomMessageOutcome::None, + Ok(sync::OnBlockFinalityProof::Import { peer, hash, number, proof }) => + CustomMessageOutcome::FinalityProofImport(peer, hash, number, proof), + Err(sync::BadPeer(id, repu)) => { + self.behaviour.disconnect_peer(&id); + self.peerset_handle.report_peer(id, repu); + CustomMessageOutcome::None + } + } + } + + fn on_remote_body_response( + &mut self, + peer: PeerId, + response: message::BlockResponse + ) { + self.light_dispatch.on_remote_body_response(LightDispatchIn { + behaviour: &mut self.behaviour, + peerset: self.peerset_handle.clone(), + }, peer, response); + } + + fn format_stats(&self) -> String { + let mut out = String::new(); + for (id, stats) in &self.context_data.stats { + let _ = writeln!( + &mut out, + "{}: In: {} bytes ({}), Out: {} bytes ({})", + id, + stats.bytes_in, + stats.count_in, + stats.bytes_out, + stats.count_out, + ); + } + out + } +} + +/// Outcome of an incoming custom message. +#[derive(Debug)] +pub enum CustomMessageOutcome { + BlockImport(BlockOrigin, Vec>), + JustificationImport(Origin, B::Hash, NumberFor, Justification), + FinalityProofImport(Origin, B::Hash, NumberFor, Vec), + /// Notification protocols have been opened with a remote. + NotificationStreamOpened { remote: PeerId, protocols: Vec, roles: Roles }, + /// Notification protocols have been closed with a remote. + NotificationsStreamClosed { remote: PeerId, protocols: Vec }, + /// Messages have been received on one or more notifications protocols. + NotificationsReceived { remote: PeerId, messages: Vec<(ConsensusEngineId, Bytes)> }, + None, +} + +fn send_request( + behaviour: &mut LegacyProto>, + stats: &mut HashMap<&'static str, PacketStats>, + peers: &mut HashMap>, + who: &PeerId, + 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())); + } + } + send_message::(behaviour, stats, who, message) +} + +fn send_message( + behaviour: &mut LegacyProto>, + stats: &mut HashMap<&'static str, PacketStats>, + who: &PeerId, + message: Message, +) { + let encoded = message.encode(); + let mut stats = stats.entry(message.id()).or_default(); + stats.bytes_out += encoded.len() as u64; + stats.count_out += 1; + behaviour.send_packet(who, encoded); +} + +impl, H: ExHashT> NetworkBehaviour for +Protocol { + type ProtocolsHandler = > as NetworkBehaviour>::ProtocolsHandler; + type OutEvent = CustomMessageOutcome; + + fn new_handler(&mut self) -> Self::ProtocolsHandler { + self.behaviour.new_handler() + } + + fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { + self.behaviour.addresses_of_peer(peer_id) + } + + fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { + self.behaviour.inject_connected(peer_id, endpoint) + } + + fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + self.behaviour.inject_disconnected(peer_id, endpoint) + } + + fn inject_node_event( + &mut self, + peer_id: PeerId, + event: <::Handler as ProtocolsHandler>::OutEvent, + ) { + self.behaviour.inject_node_event(peer_id, event) + } + + fn poll( + &mut self, + cx: &mut std::task::Context, + params: &mut impl PollParameters, + ) -> Poll< + NetworkBehaviourAction< + <::Handler as ProtocolsHandler>::InEvent, + Self::OutEvent + > + > { + while let Poll::Ready(Some(())) = self.tick_timeout.poll_next_unpin(cx) { + self.tick(); + } + + while let Poll::Ready(Some(())) = self.propagate_timeout.poll_next_unpin(cx) { + self.propagate_extrinsics(); + } + + for (id, r) in self.sync.block_requests() { + send_request( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + &id, + GenericMessage::BlockRequest(r) + ) + } + for (id, r) in self.sync.justification_requests() { + send_request( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + &id, + GenericMessage::BlockRequest(r) + ) + } + for (id, r) in self.sync.finality_proof_requests() { + send_request( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + &id, + GenericMessage::FinalityProofRequest(r)) + } + + let event = match self.behaviour.poll(cx, params) { + Poll::Pending => return Poll::Pending, + Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => ev, + Poll::Ready(NetworkBehaviourAction::DialAddress { address }) => + return Poll::Ready(NetworkBehaviourAction::DialAddress { address }), + Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => + return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }), + Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => + return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }), + Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => + return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), + }; + + let outcome = match event { + LegacyProtoOut::CustomProtocolOpen { peer_id, version, .. } => { + debug_assert!( + version <= CURRENT_VERSION as u8 + && version >= MIN_VERSION as u8 + ); + self.on_peer_connected(peer_id.clone()); + CustomMessageOutcome::None + } + LegacyProtoOut::CustomProtocolClosed { peer_id, .. } => { + self.on_peer_disconnected(peer_id.clone()); + // Notify all the notification protocols as closed. + CustomMessageOutcome::NotificationsStreamClosed { + remote: peer_id, + protocols: self.registered_notif_protocols.iter().cloned().collect(), + } + }, + LegacyProtoOut::CustomMessage { peer_id, message } => + self.on_custom_message(peer_id, message), + LegacyProtoOut::Clogged { peer_id, messages } => { + debug!(target: "sync", "{} clogging messages:", messages.len()); + for msg in messages.into_iter().take(5) { + let message: Option> = Decode::decode(&mut &msg[..]).ok(); + debug!(target: "sync", "{:?}", message); + self.on_clogged_peer(peer_id.clone(), message); + } + CustomMessageOutcome::None + } + }; + + if let CustomMessageOutcome::None = outcome { + Poll::Pending + } else { + Poll::Ready(NetworkBehaviourAction::GenerateEvent(outcome)) + } + } + + fn inject_replaced(&mut self, peer_id: PeerId, closed_endpoint: ConnectedPoint, new_endpoint: ConnectedPoint) { + self.behaviour.inject_replaced(peer_id, closed_endpoint, new_endpoint) + } + + fn inject_addr_reach_failure( + &mut self, + peer_id: Option<&PeerId>, + addr: &Multiaddr, + error: &dyn std::error::Error + ) { + self.behaviour.inject_addr_reach_failure(peer_id, addr, error) + } + + fn inject_dial_failure(&mut self, peer_id: &PeerId) { + self.behaviour.inject_dial_failure(peer_id) + } + + fn inject_new_listen_addr(&mut self, addr: &Multiaddr) { + self.behaviour.inject_new_listen_addr(addr) + } + + fn inject_expired_listen_addr(&mut self, addr: &Multiaddr) { + self.behaviour.inject_expired_listen_addr(addr) + } + + fn inject_new_external_addr(&mut self, addr: &Multiaddr) { + self.behaviour.inject_new_external_addr(addr) + } +} + +impl, H: ExHashT> DiscoveryNetBehaviour for Protocol { + fn add_discovered_nodes(&mut self, peer_ids: impl Iterator) { + self.behaviour.add_discovered_nodes(peer_ids) + } +} + +impl, H: ExHashT> Drop for Protocol { + fn drop(&mut self) { + debug!(target: "sync", "Network stats:\n{}", self.format_stats()); + } +} diff --git a/client/network/src/protocol/event.rs b/client/network/src/protocol/event.rs new file mode 100644 index 0000000000000..47bf057505db7 --- /dev/null +++ b/client/network/src/protocol/event.rs @@ -0,0 +1,78 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Network event types. These are are not the part of the protocol, but rather +//! events that happen on the network like DHT get/put results received. + +use crate::config::Roles; +use bytes::Bytes; +use libp2p::core::PeerId; +use libp2p::kad::record::Key; +use sp_runtime::ConsensusEngineId; + +/// Events generated by DHT as a response to get_value and put_value requests. +#[derive(Debug, Clone)] +#[must_use] +pub enum DhtEvent { + /// The value was found. + ValueFound(Vec<(Key, Vec)>), + + /// The requested record has not been found in the DHT. + ValueNotFound(Key), + + /// The record has been successfully inserted into the DHT. + ValuePut(Key), + + /// An error has occured while putting a record into the DHT. + ValuePutFailed(Key), +} + +/// Type for events generated by networking layer. +#[derive(Debug, Clone)] +#[must_use] +pub enum Event { + /// Event generated by a DHT. + Dht(DhtEvent), + + /// Opened a substream with the given node with the given notifications protocol. + /// + /// The protocol is always one of the notification protocols that have been registered. + NotificationStreamOpened { + /// Node we opened the substream with. + remote: PeerId, + /// The concerned protocol. Each protocol uses a different substream. + engine_id: ConsensusEngineId, + /// Roles that the remote . + roles: Roles, + }, + + /// Closed a substream with the given node. Always matches a corresponding previous + /// `NotificationStreamOpened` message. + NotificationsStreamClosed { + /// Node we closed the substream with. + remote: PeerId, + /// The concerned protocol. Each protocol uses a different substream. + engine_id: ConsensusEngineId, + }, + + /// Received one or more messages from the given node using the given protocol. + NotificationsReceived { + /// Node we received the message from. + remote: PeerId, + /// Concerned protocol and associated message. + messages: Vec<(ConsensusEngineId, Bytes)>, + }, +} diff --git a/client/network/src/protocol/legacy_proto.rs b/client/network/src/protocol/legacy_proto.rs new file mode 100644 index 0000000000000..434782f7d5065 --- /dev/null +++ b/client/network/src/protocol/legacy_proto.rs @@ -0,0 +1,28 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of libp2p's `NetworkBehaviour` trait that opens a single substream with the +//! remote and then allows any communication with them. +//! +//! The `Protocol` struct uses `LegacyProto` in order to open substreams with the rest of the +//! network, then performs the Substrate protocol handling on top. + +pub use self::behaviour::{LegacyProto, LegacyProtoOut}; + +mod behaviour; +mod handler; +mod upgrade; +mod tests; diff --git a/client/network/src/protocol/legacy_proto/behaviour.rs b/client/network/src/protocol/legacy_proto/behaviour.rs new file mode 100644 index 0000000000000..b4047f320ac2a --- /dev/null +++ b/client/network/src/protocol/legacy_proto/behaviour.rs @@ -0,0 +1,1027 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::{DiscoveryNetBehaviour, config::ProtocolId}; +use crate::protocol::legacy_proto::handler::{CustomProtoHandlerProto, CustomProtoHandlerOut, CustomProtoHandlerIn}; +use crate::protocol::legacy_proto::upgrade::RegisteredProtocol; +use bytes::BytesMut; +use fnv::FnvHashMap; +use futures::prelude::*; +use libp2p::core::{ConnectedPoint, Multiaddr, PeerId}; +use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; +use log::{debug, error, trace, warn}; +use rand::distributions::{Distribution as _, Uniform}; +use smallvec::SmallVec; +use std::{borrow::Cow, collections::hash_map::Entry, cmp, error, marker::PhantomData, mem, pin::Pin}; +use std::time::{Duration, Instant}; +use std::task::{Context, Poll}; + +/// Network behaviour that handles opening substreams for custom protocols with other nodes. +/// +/// ## How it works +/// +/// The role of the `LegacyProto` is to synchronize the following components: +/// +/// - The libp2p swarm that opens new connections and reports disconnects. +/// - The connection handler (see `handler.rs`) that handles individual connections. +/// - The peerset manager (PSM) that requests links to nodes to be established or broken. +/// - The external API, that requires knowledge of the links that have been established. +/// +/// Each connection handler can be in four different states: Enabled+Open, Enabled+Closed, +/// Disabled+Open, or Disabled+Closed. The Enabled/Disabled component must be in sync with the +/// peerset manager. For example, if the peerset manager requires a disconnection, we disable the +/// existing handler. The Open/Closed component must be in sync with the external API. +/// +/// However a connection handler only exists if we are actually connected to a node. What this +/// means is that there are six possible states for each node: Disconnected, Dialing (trying to +/// reach it), Enabled+Open, Enabled+Closed, Disabled+open, Disabled+Closed. Most notably, the +/// Dialing state must correspond to a "link established" state in the peerset manager. In other +/// words, the peerset manager doesn't differentiate whether we are dialing a node or connected +/// to it. +/// +/// Additionally, there also exists a "banning" system. If we fail to dial a node, we "ban" it for +/// a few seconds. If the PSM requests a node that is in the "banned" state, then we delay the +/// actual dialing attempt until after the ban expires, but the PSM will still consider the link +/// to be established. +/// Note that this "banning" system is not an actual ban. If a "banned" node tries to connect to +/// us, we accept the connection. The "banning" system is only about delaying dialing attempts. +/// +pub struct LegacyProto< TSubstream> { + /// List of protocols to open with peers. Never modified. + protocol: RegisteredProtocol, + + /// Receiver for instructions about who to connect to or disconnect from. + peerset: sc_peerset::Peerset, + + /// List of peers in our state. + peers: FnvHashMap, + + /// List of incoming messages we have sent to the peer set manager and that are waiting for an + /// answer. + incoming: SmallVec<[IncomingPeer; 6]>, + + /// We generate indices to identify incoming connections. This is the next value for the index + /// to use when a connection is incoming. + next_incoming_index: sc_peerset::IncomingIndex, + + /// Events to produce from `poll()`. + events: SmallVec<[NetworkBehaviourAction; 4]>, + + /// Marker to pin the generics. + marker: PhantomData, +} + +/// State of a peer we're connected to. +#[derive(Debug)] +enum PeerState { + /// State is poisoned. This is a temporary state for a peer and we should always switch back + /// to it later. If it is found in the wild, that means there was either a panic or a bug in + /// the state machine code. + Poisoned, + + /// The peer misbehaved. If the PSM wants us to connect to this node, we will add an artificial + /// delay to the connection. + Banned { + /// Until when the node is banned. + until: Instant, + }, + + /// The peerset requested that we connect to this peer. We are not connected to this node. + PendingRequest { + /// When to actually start dialing. + timer: futures_timer::Delay, + /// When the `timer` will trigger. + timer_deadline: Instant, + }, + + /// The peerset requested that we connect to this peer. We are currently dialing this peer. + Requested, + + /// We are connected to this peer but the peerset refused it. This peer can still perform + /// Kademlia queries and such, but should get disconnected in a few seconds. + Disabled { + /// How we are connected to this peer. + connected_point: ConnectedPoint, + /// If true, we still have a custom protocol open with it. It will likely get closed in + /// a short amount of time, but we need to keep the information in order to not have a + /// state mismatch. + open: bool, + /// If `Some`, the node is banned until the given `Instant`. + banned_until: Option, + }, + + /// We are connected to this peer but we are not opening any Substrate substream. The handler + /// will be enabled when `timer` fires. This peer can still perform Kademlia queries and such, + /// but should get disconnected in a few seconds. + DisabledPendingEnable { + /// How we are connected to this peer. + connected_point: ConnectedPoint, + /// If true, we still have a custom protocol open with it. It will likely get closed in + /// a short amount of time, but we need to keep the information in order to not have a + /// state mismatch. + open: bool, + /// When to enable this remote. + timer: futures_timer::Delay, + /// When the `timer` will trigger. + timer_deadline: Instant, + }, + + /// We are connected to this peer and the peerset has accepted it. The handler is in the + /// enabled state. + Enabled { + /// How we are connected to this peer. + connected_point: ConnectedPoint, + /// If true, we have a custom protocol open with this peer. + open: bool, + }, + + /// We are connected to this peer, and we sent an incoming message to the peerset. The handler + /// is in initialization mode. We are waiting for the Accept or Reject from the peerset. There + /// is a corresponding entry in `incoming`. + Incoming { + /// How we are connected to this peer. + connected_point: ConnectedPoint, + }, +} + +impl PeerState { + /// True if we have an open channel with that node. + fn is_open(&self) -> bool { + match self { + PeerState::Poisoned => false, + PeerState::Banned { .. } => false, + PeerState::PendingRequest { .. } => false, + PeerState::Requested => false, + PeerState::Disabled { open, .. } => *open, + PeerState::DisabledPendingEnable { open, .. } => *open, + PeerState::Enabled { open, .. } => *open, + PeerState::Incoming { .. } => false, + } + } +} + +/// State of an "incoming" message sent to the peer set manager. +#[derive(Debug)] +struct IncomingPeer { + /// Id of the node that is concerned. + peer_id: PeerId, + /// If true, this "incoming" still corresponds to an actual connection. If false, then the + /// connection corresponding to it has been closed or replaced already. + alive: bool, + /// Id that the we sent to the peerset. + incoming_id: sc_peerset::IncomingIndex, +} + +/// Event that can be emitted by the `LegacyProto`. +#[derive(Debug)] +pub enum LegacyProtoOut { + /// Opened a custom protocol with the remote. + CustomProtocolOpen { + /// 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, + /// Reason why the substream closed, for debugging purposes. + reason: Cow<'static, str>, + }, + + /// Receives a message on a custom protocol substream. + CustomMessage { + /// Id of the peer the message came from. + peer_id: PeerId, + /// Message that has been received. + message: BytesMut, + }, + + /// 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, + /// Copy of the messages that are within the buffer, for further diagnostic. + messages: Vec>, + }, +} + +impl LegacyProto { + /// Creates a `CustomProtos`. + pub fn new( + protocol: impl Into, + versions: &[u8], + peerset: sc_peerset::Peerset, + ) -> Self { + let protocol = RegisteredProtocol::new(protocol, versions); + + LegacyProto { + protocol, + peerset, + peers: FnvHashMap::default(), + incoming: SmallVec::new(), + next_incoming_index: sc_peerset::IncomingIndex(0), + events: SmallVec::new(), + marker: PhantomData, + } + } + + /// Returns the list of all the peers we have an open channel to. + pub fn open_peers<'a>(&'a self) -> impl Iterator + 'a { + self.peers.iter().filter(|(_, state)| state.is_open()).map(|(id, _)| id) + } + + /// Returns true if we have a channel open with this node. + pub fn is_open(&self, peer_id: &PeerId) -> bool { + self.peers.get(peer_id).map(|p| p.is_open()).unwrap_or(false) + } + + /// Disconnects the given peer if we are connected to it. + pub fn disconnect_peer(&mut self, peer_id: &PeerId) { + debug!(target: "sub-libp2p", "External API => Disconnect {:?}", peer_id); + self.disconnect_peer_inner(peer_id, None); + } + + /// Inner implementation of `disconnect_peer`. If `ban` is `Some`, we ban the node for the + /// specific duration. + fn disconnect_peer_inner(&mut self, peer_id: &PeerId, ban: Option) { + let mut entry = if let Entry::Occupied(entry) = self.peers.entry(peer_id.clone()) { + entry + } else { + return + }; + + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + // We're not connected anyway. + st @ PeerState::Disabled { .. } => *entry.into_mut() = st, + st @ PeerState::Requested => *entry.into_mut() = st, + st @ PeerState::PendingRequest { .. } => *entry.into_mut() = st, + st @ PeerState::Banned { .. } => *entry.into_mut() = st, + + // DisabledPendingEnable => Disabled. + PeerState::DisabledPendingEnable { open, connected_point, timer_deadline, .. } => { + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id.clone()); + let banned_until = Some(if let Some(ban) = ban { + cmp::max(timer_deadline, Instant::now() + ban) + } else { + timer_deadline + }); + *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until } + }, + + // Enabled => Disabled. + PeerState::Enabled { open, connected_point } => { + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id.clone()); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtoHandlerIn::Disable, + }); + let banned_until = ban.map(|dur| Instant::now() + dur); + *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until } + }, + + // Incoming => Disabled. + PeerState::Incoming { connected_point, .. } => { + let inc = if let Some(inc) = self.incoming.iter_mut() + .find(|i| i.peer_id == *entry.key() && i.alive) { + inc + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in \ + incoming for incoming peer"); + return + }; + + inc.alive = false; + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtoHandlerIn::Disable, + }); + let banned_until = ban.map(|dur| Instant::now() + dur); + *entry.into_mut() = PeerState::Disabled { open: false, connected_point, banned_until } + }, + + PeerState::Poisoned => + error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), + } + } + + /// Returns true if we try to open protocols with the given peer. + pub fn is_enabled(&self, peer_id: &PeerId) -> bool { + match self.peers.get(peer_id) { + None => false, + Some(PeerState::Disabled { .. }) => false, + Some(PeerState::DisabledPendingEnable { .. }) => false, + Some(PeerState::Enabled { .. }) => true, + Some(PeerState::Incoming { .. }) => false, + Some(PeerState::Requested) => false, + Some(PeerState::PendingRequest { .. }) => false, + Some(PeerState::Banned { .. }) => false, + Some(PeerState::Poisoned) => false, + } + } + + /// Sends a message to a peer. + /// + /// 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, message: Vec) { + if !self.is_open(target) { + return; + } + + trace!(target: "sub-libp2p", "External API => Packet for {:?}", target); + trace!(target: "sub-libp2p", "Handler({:?}) <= Packet", target); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: target.clone(), + event: CustomProtoHandlerIn::SendCustomMessage { + message, + } + }); + } + + /// Returns the state of the peerset manager, for debugging purposes. + pub fn peerset_debug_info(&mut self) -> serde_json::Value { + self.peerset.debug_info() + } + + /// Function that is called when the peerset wants us to connect to a node. + fn peerset_report_connect(&mut self, peer_id: PeerId) { + let mut occ_entry = match self.peers.entry(peer_id) { + Entry::Occupied(entry) => entry, + Entry::Vacant(entry) => { + // If there's no entry in `self.peers`, start dialing. + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Starting to connect", entry.key()); + debug!(target: "sub-libp2p", "Libp2p <= Dial {:?}", entry.key()); + self.events.push(NetworkBehaviourAction::DialPeer { peer_id: entry.key().clone() }); + entry.insert(PeerState::Requested); + return; + } + }; + + match mem::replace(occ_entry.get_mut(), PeerState::Poisoned) { + PeerState::Banned { ref until } if *until > Instant::now() => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Will start to connect at \ + until {:?}", occ_entry.key(), until); + *occ_entry.into_mut() = PeerState::PendingRequest { + timer: futures_timer::Delay::new_at(until.clone()), + timer_deadline: until.clone(), + }; + }, + + PeerState::Banned { .. } => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Starting to connect", occ_entry.key()); + debug!(target: "sub-libp2p", "Libp2p <= Dial {:?}", occ_entry.key()); + self.events.push(NetworkBehaviourAction::DialPeer { peer_id: occ_entry.key().clone() }); + *occ_entry.into_mut() = PeerState::Requested; + }, + + PeerState::Disabled { open, ref connected_point, banned_until: Some(ref banned) } + if *banned > Instant::now() => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Has idle connection through \ + {:?} but node is banned until {:?}", occ_entry.key(), connected_point, banned); + *occ_entry.into_mut() = PeerState::DisabledPendingEnable { + connected_point: connected_point.clone(), + open, + timer: futures_timer::Delay::new_at(banned.clone()), + timer_deadline: banned.clone(), + }; + }, + + PeerState::Disabled { open, connected_point, banned_until: _ } => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling previously-idle \ + connection through {:?}", occ_entry.key(), connected_point); + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: occ_entry.key().clone(), + event: CustomProtoHandlerIn::Enable, + }); + *occ_entry.into_mut() = PeerState::Enabled { connected_point, open }; + }, + + PeerState::Incoming { connected_point, .. } => { + debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling incoming \ + connection through {:?}", occ_entry.key(), connected_point); + if let Some(inc) = self.incoming.iter_mut() + .find(|i| i.peer_id == *occ_entry.key() && i.alive) { + inc.alive = false; + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in \ + incoming for incoming peer") + } + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: occ_entry.key().clone(), + event: CustomProtoHandlerIn::Enable, + }); + *occ_entry.into_mut() = PeerState::Enabled { connected_point, open: false }; + }, + + st @ PeerState::Enabled { .. } => { + warn!(target: "sub-libp2p", "PSM => Connect({:?}): Already connected to this \ + peer", occ_entry.key()); + *occ_entry.into_mut() = st; + }, + st @ PeerState::DisabledPendingEnable { .. } => { + warn!(target: "sub-libp2p", "PSM => Connect({:?}): Already have an idle \ + connection to this peer and waiting to enable it", occ_entry.key()); + *occ_entry.into_mut() = st; + }, + st @ PeerState::Requested { .. } | st @ PeerState::PendingRequest { .. } => { + warn!(target: "sub-libp2p", "PSM => Connect({:?}): Received a previous \ + request for that peer", occ_entry.key()); + *occ_entry.into_mut() = st; + }, + + PeerState::Poisoned => + error!(target: "sub-libp2p", "State of {:?} is poisoned", occ_entry.key()), + } + } + + /// Function that is called when the peerset wants us to disconnect from a node. + fn peerset_report_disconnect(&mut self, peer_id: PeerId) { + let mut entry = match self.peers.entry(peer_id) { + Entry::Occupied(entry) => entry, + Entry::Vacant(entry) => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Node already disabled", entry.key()); + return + } + }; + + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + st @ PeerState::Disabled { .. } | st @ PeerState::Banned { .. } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Node already disabled", entry.key()); + *entry.into_mut() = st; + }, + + PeerState::DisabledPendingEnable { open, connected_point, timer_deadline, .. } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Interrupting pending \ + enable", entry.key()); + *entry.into_mut() = PeerState::Disabled { + open, + connected_point, + banned_until: Some(timer_deadline), + }; + }, + + PeerState::Enabled { open, connected_point } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Disabling connection", entry.key()); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", entry.key()); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: entry.key().clone(), + event: CustomProtoHandlerIn::Disable, + }); + *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until: None } + }, + st @ PeerState::Incoming { .. } => { + error!(target: "sub-libp2p", "PSM => Drop({:?}): Was in incoming mode", + entry.key()); + *entry.into_mut() = st; + }, + PeerState::Requested => { + // We don't cancel dialing. Libp2p doesn't expose that on purpose, as other + // sub-systems (such as the discovery mechanism) may require dialing this node as + // well at the same time. + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Was not yet connected", entry.key()); + entry.remove(); + }, + PeerState::PendingRequest { timer_deadline, .. } => { + debug!(target: "sub-libp2p", "PSM => Drop({:?}): Was not yet connected", entry.key()); + *entry.into_mut() = PeerState::Banned { until: timer_deadline } + }, + + PeerState::Poisoned => + error!(target: "sub-libp2p", "State of {:?} is poisoned", entry.key()), + } + } + + /// Function that is called when the peerset wants us to accept an incoming node. + fn peerset_report_accept(&mut self, index: sc_peerset::IncomingIndex) { + let incoming = if let Some(pos) = self.incoming.iter().position(|i| i.incoming_id == index) { + self.incoming.remove(pos) + } else { + error!(target: "sub-libp2p", "PSM => Accept({:?}): Invalid index", index); + return + }; + + if !incoming.alive { + debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Obsolete incoming, + sending back dropped", index, incoming.peer_id); + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", incoming.peer_id); + self.peerset.dropped(incoming.peer_id.clone()); + return + } + + let state = if let Some(state) = self.peers.get_mut(&incoming.peer_id) { + state + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in peers \ + corresponding to an alive incoming"); + return + }; + + let connected_point = if let PeerState::Incoming { connected_point } = state { + connected_point.clone() + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: entry in peers corresponding \ + to an alive incoming is not in incoming state"); + return + }; + + debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Enabling connection \ + through {:?}", index, incoming.peer_id, connected_point); + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", incoming.peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: incoming.peer_id, + event: CustomProtoHandlerIn::Enable, + }); + + *state = PeerState::Enabled { open: false, connected_point }; + } + + /// Function that is called when the peerset wants us to reject an incoming node. + fn peerset_report_reject(&mut self, index: sc_peerset::IncomingIndex) { + let incoming = if let Some(pos) = self.incoming.iter().position(|i| i.incoming_id == index) { + self.incoming.remove(pos) + } else { + error!(target: "sub-libp2p", "PSM => Reject({:?}): Invalid index", index); + return + }; + + if !incoming.alive { + error!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Obsolete incoming, \ + ignoring", index, incoming.peer_id); + return + } + + let state = if let Some(state) = self.peers.get_mut(&incoming.peer_id) { + state + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in peers \ + corresponding to an alive incoming"); + return + }; + + let connected_point = if let PeerState::Incoming { connected_point } = state { + connected_point.clone() + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: entry in peers corresponding \ + to an alive incoming is not in incoming state"); + return + }; + + debug!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Rejecting connection through \ + {:?}", index, incoming.peer_id, connected_point); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", incoming.peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: incoming.peer_id, + event: CustomProtoHandlerIn::Disable, + }); + *state = PeerState::Disabled { open: false, connected_point, banned_until: None }; + } +} + +impl DiscoveryNetBehaviour for LegacyProto { + fn add_discovered_nodes(&mut self, peer_ids: impl Iterator) { + self.peerset.discovered(peer_ids.into_iter().map(|peer_id| { + debug!(target: "sub-libp2p", "PSM <= Discovered({:?})", peer_id); + peer_id + })); + } +} + +impl NetworkBehaviour for LegacyProto +where + TSubstream: AsyncRead + AsyncWrite + Unpin, +{ + type ProtocolsHandler = CustomProtoHandlerProto; + type OutEvent = LegacyProtoOut; + + fn new_handler(&mut self) -> Self::ProtocolsHandler { + CustomProtoHandlerProto::new(self.protocol.clone()) + } + + fn addresses_of_peer(&mut self, _: &PeerId) -> Vec { + Vec::new() + } + + fn inject_connected(&mut self, peer_id: PeerId, connected_point: ConnectedPoint) { + match (self.peers.entry(peer_id.clone()).or_insert(PeerState::Poisoned), connected_point) { + (st @ &mut PeerState::Requested, connected_point) | + (st @ &mut PeerState::PendingRequest { .. }, connected_point) => { + debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Connection \ + requested by PSM (through {:?})", peer_id, connected_point + ); + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtoHandlerIn::Enable, + }); + *st = PeerState::Enabled { open: false, connected_point }; + } + + // Note: it may seem weird that "Banned" nodes get treated as if there were absent. + // This is because the word "Banned" means "temporarily prevent outgoing connections to + // this node", and not "banned" in the sense that we would refuse the node altogether. + (st @ &mut PeerState::Poisoned, connected_point @ ConnectedPoint::Listener { .. }) | + (st @ &mut PeerState::Banned { .. }, connected_point @ ConnectedPoint::Listener { .. }) => { + let incoming_id = self.next_incoming_index.clone(); + self.next_incoming_index.0 = match self.next_incoming_index.0.checked_add(1) { + Some(v) => v, + None => { + error!(target: "sub-libp2p", "Overflow in next_incoming_index"); + return + } + }; + debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Incoming connection", + peer_id); + debug!(target: "sub-libp2p", "PSM <= Incoming({:?}, {:?}): Through {:?}", + incoming_id, peer_id, connected_point); + self.peerset.incoming(peer_id.clone(), incoming_id); + self.incoming.push(IncomingPeer { + peer_id: peer_id.clone(), + alive: true, + incoming_id, + }); + *st = PeerState::Incoming { connected_point }; + } + + (st @ &mut PeerState::Poisoned, connected_point) | + (st @ &mut PeerState::Banned { .. }, connected_point) => { + let banned_until = if let PeerState::Banned { until } = st { + Some(*until) + } else { + None + }; + debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Requested by something \ + else than PSM, disabling", peer_id); + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtoHandlerIn::Disable, + }); + *st = PeerState::Disabled { open: false, connected_point, banned_until }; + } + + st => { + // This is a serious bug either in this state machine or in libp2p. + error!(target: "sub-libp2p", "Received inject_connected for \ + already-connected node; state is {:?}", st + ); + } + } + } + + fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + match self.peers.remove(peer_id) { + None | Some(PeerState::Requested) | Some(PeerState::PendingRequest { .. }) | + Some(PeerState::Banned { .. }) => + // This is a serious bug either in this state machine or in libp2p. + error!(target: "sub-libp2p", "Received inject_disconnected for non-connected \ + node {:?}", peer_id), + + Some(PeerState::Disabled { open, banned_until, .. }) => { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \ + (through {:?})", peer_id, endpoint); + if let Some(until) = banned_until { + self.peers.insert(peer_id.clone(), PeerState::Banned { until }); + } + if open { + debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); + let event = LegacyProtoOut::CustomProtocolClosed { + peer_id: peer_id.clone(), + reason: "Disconnected by libp2p".into(), + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + } + + Some(PeerState::DisabledPendingEnable { open, timer_deadline, .. }) => { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \ + (through {:?}) but pending enable", peer_id, endpoint); + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id.clone()); + self.peers.insert(peer_id.clone(), PeerState::Banned { until: timer_deadline }); + if open { + debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); + let event = LegacyProtoOut::CustomProtocolClosed { + peer_id: peer_id.clone(), + reason: "Disconnected by libp2p".into(), + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + } + + Some(PeerState::Enabled { open, .. }) => { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was enabled \ + (through {:?})", peer_id, endpoint); + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id.clone()); + + let ban_dur = Uniform::new(5, 10).sample(&mut rand::thread_rng()); + self.peers.insert(peer_id.clone(), PeerState::Banned { + until: Instant::now() + Duration::from_secs(ban_dur) + }); + + if open { + debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); + let event = LegacyProtoOut::CustomProtocolClosed { + peer_id: peer_id.clone(), + reason: "Disconnected by libp2p".into(), + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + } + + // In the incoming state, we don't report "Dropped". Instead we will just ignore the + // corresponding Accept/Reject. + Some(PeerState::Incoming { .. }) => { + if let Some(state) = self.incoming.iter_mut().find(|i| i.peer_id == *peer_id) { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was in incoming \ + mode (id {:?}, through {:?})", peer_id, state.incoming_id, endpoint); + state.alive = false; + } else { + error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in incoming \ + corresponding to an incoming state in peers") + } + } + + Some(PeerState::Poisoned) => + error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), + } + } + + fn inject_addr_reach_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn error::Error) { + trace!(target: "sub-libp2p", "Libp2p => Reach failure for {:?} through {:?}: {:?}", peer_id, addr, error); + } + + fn inject_dial_failure(&mut self, peer_id: &PeerId) { + if let Entry::Occupied(mut entry) = self.peers.entry(peer_id.clone()) { + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + // The node is not in our list. + st @ PeerState::Banned { .. } => { + trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); + *entry.into_mut() = st; + }, + + // "Basic" situation: we failed to reach a node that the peerset requested. + PeerState::Requested | PeerState::PendingRequest { .. } => { + debug!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); + *entry.into_mut() = PeerState::Banned { + until: Instant::now() + Duration::from_secs(5) + }; + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); + self.peerset.dropped(peer_id.clone()) + }, + + // We can still get dial failures even if we are already connected to the node, + // as an extra diagnostic for an earlier attempt. + st @ PeerState::Disabled { .. } | st @ PeerState::Enabled { .. } | + st @ PeerState::DisabledPendingEnable { .. } | st @ PeerState::Incoming { .. } => { + debug!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); + *entry.into_mut() = st; + }, + + PeerState::Poisoned => + error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), + } + + } else { + // The node is not in our list. + trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); + } + } + + fn inject_node_event( + &mut self, + source: PeerId, + event: CustomProtoHandlerOut, + ) { + match event { + CustomProtoHandlerOut::CustomProtocolClosed { reason } => { + debug!(target: "sub-libp2p", "Handler({:?}) => Closed: {}", source, reason); + + let mut entry = if let Entry::Occupied(entry) = self.peers.entry(source.clone()) { + entry + } else { + error!(target: "sub-libp2p", "State mismatch in the custom protos handler"); + return + }; + + debug!(target: "sub-libp2p", "External API <= Closed({:?})", source); + let event = LegacyProtoOut::CustomProtocolClosed { + reason, + peer_id: source.clone(), + }; + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + + match mem::replace(entry.get_mut(), PeerState::Poisoned) { + PeerState::Enabled { open, connected_point } => { + debug_assert!(open); + + debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", source); + self.peerset.dropped(source.clone()); + + debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", source); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: source.clone(), + event: CustomProtoHandlerIn::Disable, + }); + + *entry.into_mut() = PeerState::Disabled { + open: false, + connected_point, + banned_until: None + }; + }, + PeerState::Disabled { open, connected_point, banned_until } => { + debug_assert!(open); + *entry.into_mut() = PeerState::Disabled { open: false, connected_point, banned_until }; + }, + PeerState::DisabledPendingEnable { open, connected_point, timer, timer_deadline } => { + debug_assert!(open); + *entry.into_mut() = PeerState::DisabledPendingEnable { + open: false, + connected_point, + timer, + timer_deadline + }; + }, + _ => error!(target: "sub-libp2p", "State mismatch in the custom protos handler"), + } + } + + CustomProtoHandlerOut::CustomProtocolOpen { version } => { + debug!(target: "sub-libp2p", "Handler({:?}) => Open: version {:?}", source, version); + let endpoint = match self.peers.get_mut(&source) { + Some(PeerState::Enabled { ref mut open, ref connected_point }) | + Some(PeerState::DisabledPendingEnable { ref mut open, ref connected_point, .. }) | + Some(PeerState::Disabled { ref mut open, ref connected_point, .. }) if !*open => { + *open = true; + connected_point.clone() + } + _ => { + error!(target: "sub-libp2p", "State mismatch in the custom protos handler"); + return + } + }; + + debug!(target: "sub-libp2p", "External API <= Open({:?})", source); + let event = LegacyProtoOut::CustomProtocolOpen { + version, + peer_id: source, + endpoint, + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + + CustomProtoHandlerOut::CustomMessage { message } => { + debug_assert!(self.is_open(&source)); + trace!(target: "sub-libp2p", "Handler({:?}) => Message", source); + trace!(target: "sub-libp2p", "External API <= Message({:?})", source); + let event = LegacyProtoOut::CustomMessage { + peer_id: source, + message, + }; + + self.events.push(NetworkBehaviourAction::GenerateEvent(event)); + } + + CustomProtoHandlerOut::Clogged { messages } => { + debug_assert!(self.is_open(&source)); + trace!(target: "sub-libp2p", "Handler({:?}) => Clogged", source); + trace!(target: "sub-libp2p", "External API <= Clogged({:?})", source); + warn!(target: "sub-libp2p", "Queue of packets to send to {:?} is \ + pretty large", source); + self.events.push(NetworkBehaviourAction::GenerateEvent(LegacyProtoOut::Clogged { + peer_id: source, + messages, + })); + } + + // Don't do anything for non-severe errors except report them. + CustomProtoHandlerOut::ProtocolError { is_severe, ref error } if !is_severe => { + debug!(target: "sub-libp2p", "Handler({:?}) => Benign protocol error: {:?}", + source, error) + } + + CustomProtoHandlerOut::ProtocolError { error, .. } => { + debug!(target: "sub-libp2p", "Handler({:?}) => Severe protocol error: {:?}", + source, error); + // A severe protocol error happens when we detect a "bad" node, such as a node on + // a different chain, or a node that doesn't speak the same protocol(s). We + // decrease the node's reputation, hence lowering the chances we try this node + // again in the short term. + self.peerset.report_peer( + source.clone(), + sc_peerset::ReputationChange::new(i32::min_value(), "Protocol error") + ); + self.disconnect_peer_inner(&source, Some(Duration::from_secs(5))); + } + } + } + + fn poll( + &mut self, + cx: &mut Context, + _params: &mut impl PollParameters, + ) -> Poll< + NetworkBehaviourAction< + CustomProtoHandlerIn, + Self::OutEvent, + >, + > { + // Poll for instructions from the peerset. + // Note that the peerset is a *best effort* crate, and we have to use defensive programming. + loop { + match futures::Stream::poll_next(Pin::new(&mut self.peerset), cx) { + Poll::Ready(Some(sc_peerset::Message::Accept(index))) => { + self.peerset_report_accept(index); + } + Poll::Ready(Some(sc_peerset::Message::Reject(index))) => { + self.peerset_report_reject(index); + } + Poll::Ready(Some(sc_peerset::Message::Connect(id))) => { + self.peerset_report_connect(id); + } + Poll::Ready(Some(sc_peerset::Message::Drop(id))) => { + self.peerset_report_disconnect(id); + } + Poll::Ready(None) => { + error!(target: "sub-libp2p", "Peerset receiver stream has returned None"); + break; + } + Poll::Pending => break, + } + } + + for (peer_id, peer_state) in self.peers.iter_mut() { + match mem::replace(peer_state, PeerState::Poisoned) { + PeerState::PendingRequest { mut timer, timer_deadline } => { + if let Poll::Pending = Pin::new(&mut timer).poll(cx) { + *peer_state = PeerState::PendingRequest { timer, timer_deadline }; + continue; + } + + debug!(target: "sub-libp2p", "Libp2p <= Dial {:?} now that ban has expired", peer_id); + self.events.push(NetworkBehaviourAction::DialPeer { peer_id: peer_id.clone() }); + *peer_state = PeerState::Requested; + } + + PeerState::DisabledPendingEnable { mut timer, connected_point, open, timer_deadline } => { + if let Poll::Pending = Pin::new(&mut timer).poll(cx) { + *peer_state = PeerState::DisabledPendingEnable { + timer, + connected_point, + open, + timer_deadline + }; + continue; + } + + debug!(target: "sub-libp2p", "Handler({:?}) <= Enable now that ban has expired", peer_id); + self.events.push(NetworkBehaviourAction::SendEvent { + peer_id: peer_id.clone(), + event: CustomProtoHandlerIn::Enable, + }); + *peer_state = PeerState::Enabled { connected_point, open }; + } + + st @ _ => *peer_state = st, + } + } + + if !self.events.is_empty() { + return Poll::Ready(self.events.remove(0)) + } + + Poll::Pending + } +} diff --git a/core/network/src/legacy_proto/handler.rs b/client/network/src/protocol/legacy_proto/handler.rs similarity index 83% rename from core/network/src/legacy_proto/handler.rs rename to client/network/src/protocol/legacy_proto/handler.rs index 3fe88d3cfd410..f042d1b88925f 100644 --- a/core/network/src/legacy_proto/handler.rs +++ b/client/network/src/protocol/legacy_proto/handler.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,10 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::legacy_proto::upgrade::{RegisteredProtocol, RegisteredProtocolEvent, RegisteredProtocolSubstream}; -use crate::protocol::message::Message; +use super::upgrade::{RegisteredProtocol, RegisteredProtocolEvent, RegisteredProtocolSubstream}; +use bytes::BytesMut; use futures::prelude::*; -use futures03::{compat::Compat, TryFutureExt as _}; use futures_timer::Delay; use libp2p::core::{ConnectedPoint, PeerId, Endpoint}; use libp2p::core::upgrade::{InboundUpgrade, OutboundUpgrade}; @@ -29,10 +28,9 @@ use libp2p::swarm::{ SubstreamProtocol, }; use log::{debug, error}; -use sr_primitives::traits::Block as BlockT; use smallvec::{smallvec, SmallVec}; use std::{borrow::Cow, error, fmt, io, marker::PhantomData, mem, time::Duration}; -use tokio_io::{AsyncRead, AsyncWrite}; +use std::{pin::Pin, task::{Context, Poll}}; /// Implements the `IntoProtocolsHandler` trait of libp2p. /// @@ -88,21 +86,20 @@ use tokio_io::{AsyncRead, AsyncWrite}; /// We consider that we are now "closed" if the remote closes all the existing substreams. /// Re-opening it can then be performed by closing all active substream and re-opening one. /// -pub struct CustomProtoHandlerProto { +pub struct CustomProtoHandlerProto { /// Configuration for the protocol upgrade to negotiate. - protocol: RegisteredProtocol, + protocol: RegisteredProtocol, /// Marker to pin the generic type. marker: PhantomData, } -impl CustomProtoHandlerProto +impl CustomProtoHandlerProto where - TSubstream: AsyncRead + AsyncWrite, - B: BlockT, + TSubstream: AsyncRead + AsyncWrite + Unpin, { /// Builds a new `CustomProtoHandlerProto`. - pub fn new(protocol: RegisteredProtocol) -> Self { + pub fn new(protocol: RegisteredProtocol) -> Self { CustomProtoHandlerProto { protocol, marker: PhantomData, @@ -110,14 +107,13 @@ where } } -impl IntoProtocolsHandler for CustomProtoHandlerProto +impl IntoProtocolsHandler for CustomProtoHandlerProto where - TSubstream: AsyncRead + AsyncWrite, - B: BlockT, + TSubstream: AsyncRead + AsyncWrite + Unpin, { - type Handler = CustomProtoHandler; + type Handler = CustomProtoHandler; - fn inbound_protocol(&self) -> RegisteredProtocol { + fn inbound_protocol(&self) -> RegisteredProtocol { self.protocol.clone() } @@ -128,7 +124,7 @@ where remote_peer_id: remote_peer_id.clone(), state: ProtocolState::Init { substreams: SmallVec::new(), - init_deadline: Delay::new(Duration::from_secs(5)).compat() + init_deadline: Delay::new(Duration::from_secs(5)) }, events_queue: SmallVec::new(), } @@ -136,12 +132,12 @@ where } /// The actual handler once the connection has been established. -pub struct CustomProtoHandler { +pub struct CustomProtoHandler { /// Configuration for the protocol upgrade to negotiate. - protocol: RegisteredProtocol, + protocol: RegisteredProtocol, /// State of the communications with the remote. - state: ProtocolState, + state: ProtocolState, /// Identifier of the node we're talking to. Used only for logging purposes and shouldn't have /// any influence on the behaviour. @@ -155,33 +151,33 @@ pub struct CustomProtoHandler { /// /// This queue must only ever be modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent, (), CustomProtoHandlerOut>; 16]>, + events_queue: SmallVec<[ProtocolsHandlerEvent; 16]>, } /// State of the handler. -enum ProtocolState { +enum ProtocolState { /// Waiting for the behaviour to tell the handler whether it is enabled or disabled. Init { /// List of substreams opened by the remote but that haven't been processed yet. - substreams: SmallVec<[RegisteredProtocolSubstream; 6]>, + substreams: SmallVec<[RegisteredProtocolSubstream; 6]>, /// Deadline after which the initialization is abnormally long. - init_deadline: Compat, + 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: Compat, + deadline: Delay, }, /// Normal operating mode. Contains the substreams that are open. /// If we are in this state, we have sent a `CustomProtocolOpen` message to the outside. Normal { /// The substreams where bidirectional communications happen. - substreams: SmallVec<[RegisteredProtocolSubstream; 4]>, + substreams: SmallVec<[RegisteredProtocolSubstream; 4]>, /// Contains substreams which are being shut down. - shutdown: SmallVec<[RegisteredProtocolSubstream; 4]>, + shutdown: SmallVec<[RegisteredProtocolSubstream; 4]>, }, /// We are disabled. Contains substreams that are being closed. @@ -189,7 +185,7 @@ enum ProtocolState { /// outside or we have never sent any `CustomProtocolOpen` in the first place. Disabled { /// List of substreams to shut down. - shutdown: SmallVec<[RegisteredProtocolSubstream; 6]>, + shutdown: SmallVec<[RegisteredProtocolSubstream; 6]>, /// If true, we should reactivate the handler after all the substreams in `shutdown` have /// been closed. @@ -210,7 +206,7 @@ enum ProtocolState { /// Event that can be received by a `CustomProtoHandler`. #[derive(Debug)] -pub enum CustomProtoHandlerIn { +pub enum CustomProtoHandlerIn { /// The node should start using custom protocols. Enable, @@ -220,13 +216,13 @@ pub enum CustomProtoHandlerIn { /// Sends a message through a custom protocol substream. SendCustomMessage { /// The message to send. - message: Message, + message: Vec, }, } /// Event that can be emitted by a `CustomProtoHandler`. #[derive(Debug)] -pub enum CustomProtoHandlerOut { +pub enum CustomProtoHandlerOut { /// Opened a custom protocol with the remote. CustomProtocolOpen { /// Version of the protocol that has been opened. @@ -242,14 +238,14 @@ pub enum CustomProtoHandlerOut { /// Receives a message on a custom protocol substream. CustomMessage { /// Message that has been received. - message: Message, + message: BytesMut, }, /// A substream to the remote is clogged. The send buffer is very large, and we should print /// a diagnostic message and/or avoid sending more data. Clogged { /// Copy of the messages that are within the buffer, for further diagnostic. - messages: Vec>, + messages: Vec>, }, /// An error has happened on the protocol level with this node. @@ -261,10 +257,9 @@ pub enum CustomProtoHandlerOut { }, } -impl CustomProtoHandler +impl CustomProtoHandler where - TSubstream: AsyncRead + AsyncWrite, - B: BlockT, + TSubstream: AsyncRead + AsyncWrite + Unpin, { /// Enables the handler. fn enable(&mut self) { @@ -284,7 +279,7 @@ where }); } ProtocolState::Opening { - deadline: Delay::new(Duration::from_secs(60)).compat() + deadline: Delay::new(Duration::from_secs(60)) } } else { @@ -341,8 +336,8 @@ where /// Polls the state for events. Optionally returns an event to produce. #[must_use] - fn poll_state(&mut self) - -> Option, (), CustomProtoHandlerOut>> { + fn poll_state(&mut self, cx: &mut Context) + -> Option> { match mem::replace(&mut self.state, ProtocolState::Poisoned) { ProtocolState::Poisoned => { error!(target: "sub-libp2p", "Handler with {:?} is in poisoned state", @@ -352,14 +347,14 @@ where } ProtocolState::Init { substreams, mut init_deadline } => { - match init_deadline.poll() { - Ok(Async::Ready(())) => { - init_deadline = Delay::new(Duration::from_secs(60)).compat(); + match Pin::new(&mut init_deadline).poll(cx) { + Poll::Ready(Ok(())) => { + init_deadline = Delay::new(Duration::from_secs(60)); error!(target: "sub-libp2p", "Handler initialization process is too long \ with {:?}", self.remote_peer_id) }, - Ok(Async::NotReady) => {} - Err(_) => error!(target: "sub-libp2p", "Tokio timer has errored") + Poll::Pending => {} + Poll::Ready(Err(_)) => error!(target: "sub-libp2p", "Tokio timer has errored") } self.state = ProtocolState::Init { substreams, init_deadline }; @@ -367,9 +362,9 @@ where } ProtocolState::Opening { mut deadline } => { - match deadline.poll() { - Ok(Async::Ready(())) => { - deadline = Delay::new(Duration::from_secs(60)).compat(); + match Pin::new(&mut deadline).poll(cx) { + Poll::Ready(Ok(())) => { + deadline = Delay::new(Duration::from_secs(60)); let event = CustomProtoHandlerOut::ProtocolError { is_severe: true, error: "Timeout when opening protocol".to_string().into(), @@ -377,13 +372,13 @@ where self.state = ProtocolState::Opening { deadline }; Some(ProtocolsHandlerEvent::Custom(event)) }, - Ok(Async::NotReady) => { + Poll::Pending => { self.state = ProtocolState::Opening { deadline }; None }, - Err(_) => { + Poll::Ready(Err(_)) => { error!(target: "sub-libp2p", "Tokio timer has errored"); - deadline = Delay::new(Duration::from_secs(60)).compat(); + deadline = Delay::new(Duration::from_secs(60)); self.state = ProtocolState::Opening { deadline }; None }, @@ -393,9 +388,9 @@ where ProtocolState::Normal { mut substreams, mut shutdown } => { for n in (0..substreams.len()).rev() { let mut substream = substreams.swap_remove(n); - match substream.poll() { - Ok(Async::NotReady) => substreams.push(substream), - Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => { + match Pin::new(&mut substream).poll_next(cx) { + Poll::Pending => substreams.push(substream), + Poll::Ready(Some(Ok(RegisteredProtocolEvent::Message(message)))) => { let event = CustomProtoHandlerOut::CustomMessage { message }; @@ -403,7 +398,7 @@ where self.state = ProtocolState::Normal { substreams, shutdown }; return Some(ProtocolsHandlerEvent::Custom(event)); }, - Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { messages }))) => { + Poll::Ready(Some(Ok(RegisteredProtocolEvent::Clogged { messages }))) => { let event = CustomProtoHandlerOut::Clogged { messages, }; @@ -411,7 +406,7 @@ where self.state = ProtocolState::Normal { substreams, shutdown }; return Some(ProtocolsHandlerEvent::Custom(event)); } - Ok(Async::Ready(None)) => { + Poll::Ready(None) => { shutdown.push(substream); if substreams.is_empty() { let event = CustomProtoHandlerOut::CustomProtocolClosed { @@ -424,7 +419,7 @@ where return Some(ProtocolsHandlerEvent::Custom(event)); } } - Err(err) => { + Poll::Ready(Some(Err(err))) => { if substreams.is_empty() { let event = CustomProtoHandlerOut::CustomProtocolClosed { reason: format!("Error on the last substream: {:?}", err).into(), @@ -447,12 +442,12 @@ where } ProtocolState::Disabled { mut shutdown, reenable } => { - shutdown_list(&mut shutdown); + shutdown_list(&mut shutdown, cx); // If `reenable` is `true`, that means we should open the substreams system again // after all the substreams are closed. if reenable && shutdown.is_empty() { self.state = ProtocolState::Opening { - deadline: Delay::new(Duration::from_secs(60)).compat() + deadline: Delay::new(Duration::from_secs(60)) }; Some(ProtocolsHandlerEvent::OutboundSubstreamRequest { protocol: SubstreamProtocol::new(self.protocol.clone()), @@ -471,7 +466,7 @@ where /// Called by `inject_fully_negotiated_inbound` and `inject_fully_negotiated_outbound`. fn inject_fully_negotiated( &mut self, - mut substream: RegisteredProtocolSubstream + mut substream: RegisteredProtocolSubstream ) { self.state = match mem::replace(&mut self.state, ProtocolState::Poisoned) { ProtocolState::Poisoned => { @@ -516,7 +511,7 @@ where } /// Sends a message to the remote. - fn send_message(&mut self, message: Message) { + fn send_message(&mut self, message: Vec) { match self.state { ProtocolState::Normal { ref mut substreams, .. } => substreams[0].send_message(message), @@ -527,14 +522,14 @@ where } } -impl ProtocolsHandler for CustomProtoHandler -where TSubstream: AsyncRead + AsyncWrite, B: BlockT { - type InEvent = CustomProtoHandlerIn; - type OutEvent = CustomProtoHandlerOut; +impl ProtocolsHandler for CustomProtoHandler +where TSubstream: AsyncRead + AsyncWrite + Unpin { + type InEvent = CustomProtoHandlerIn; + type OutEvent = CustomProtoHandlerOut; type Substream = TSubstream; type Error = ConnectionKillError; - type InboundProtocol = RegisteredProtocol; - type OutboundProtocol = RegisteredProtocol; + type InboundProtocol = RegisteredProtocol; + type OutboundProtocol = RegisteredProtocol; type OutboundOpenInfo = (); fn listen_protocol(&self) -> SubstreamProtocol { @@ -556,7 +551,7 @@ where TSubstream: AsyncRead + AsyncWrite, B: BlockT { self.inject_fully_negotiated(proto); } - fn inject_event(&mut self, message: CustomProtoHandlerIn) { + fn inject_event(&mut self, message: CustomProtoHandlerIn) { match message { CustomProtoHandlerIn::Disable => self.disable(), CustomProtoHandlerIn::Enable => self.enable(), @@ -589,33 +584,33 @@ where TSubstream: AsyncRead + AsyncWrite, B: BlockT { fn poll( &mut self, + cx: &mut Context, ) -> Poll< - ProtocolsHandlerEvent, - Self::Error, + ProtocolsHandlerEvent > { // Flush the events queue if necessary. if !self.events_queue.is_empty() { let event = self.events_queue.remove(0); - return Ok(Async::Ready(event)) + return Poll::Ready(event) } // Kill the connection if needed. if let ProtocolState::KillAsap = self.state { - return Err(ConnectionKillError); + return Poll::Ready(ProtocolsHandlerEvent::Close(ConnectionKillError)); } // Process all the substreams. - if let Some(event) = self.poll_state() { - return Ok(Async::Ready(event)) + if let Some(event) = self.poll_state(cx) { + return Poll::Ready(event) } - Ok(Async::NotReady) + Poll::Pending } } -impl fmt::Debug for CustomProtoHandler +impl fmt::Debug for CustomProtoHandler where - TSubstream: AsyncRead + AsyncWrite, + TSubstream: AsyncRead + AsyncWrite + Unpin, { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { f.debug_struct("CustomProtoHandler") @@ -625,16 +620,17 @@ where /// Given a list of substreams, tries to shut them down. The substreams that have been successfully /// shut down are removed from the list. -fn shutdown_list - (list: &mut SmallVec>>) -where TSubstream: AsyncRead + AsyncWrite, B: BlockT { +fn shutdown_list + (list: &mut SmallVec>>, + cx: &mut Context) +where TSubstream: AsyncRead + AsyncWrite + Unpin { '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, + match substream.poll_next_unpin(cx) { + Poll::Ready(Some(Ok(_))) => {} + Poll::Pending => break, + Poll::Ready(Some(Err(_))) | Poll::Ready(None) => continue 'outer, } } list.push(substream); diff --git a/client/network/src/protocol/legacy_proto/tests.rs b/client/network/src/protocol/legacy_proto/tests.rs new file mode 100644 index 0000000000000..6a2174f30c937 --- /dev/null +++ b/client/network/src/protocol/legacy_proto/tests.rs @@ -0,0 +1,410 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![cfg(test)] + +use futures::{prelude::*, ready}; +use codec::{Encode, Decode}; +use libp2p::core::nodes::Substream; +use libp2p::core::{ConnectedPoint, transport::boxed::Boxed, muxing::StreamMuxerBox}; +use libp2p::swarm::{Swarm, ProtocolsHandler, IntoProtocolsHandler}; +use libp2p::swarm::{PollParameters, NetworkBehaviour, NetworkBehaviourAction}; +use libp2p::{PeerId, Multiaddr, Transport}; +use rand::seq::SliceRandom; +use std::{io, task::Context, task::Poll, time::Duration}; +use crate::message::Message; +use crate::protocol::legacy_proto::{LegacyProto, LegacyProtoOut}; +use sp_test_primitives::Block; + +/// Builds two nodes that have each other as bootstrap nodes. +/// This is to be used only for testing, and a panic will happen if something goes wrong. +fn build_nodes() +-> ( + Swarm, CustomProtoWithAddr>, + Swarm, CustomProtoWithAddr> +) { + let mut out = Vec::with_capacity(2); + + let keypairs: Vec<_> = (0..2).map(|_| libp2p::identity::Keypair::generate_ed25519()).collect(); + let addrs: Vec = (0..2) + .map(|_| format!("/memory/{}", rand::random::()).parse().unwrap()) + .collect(); + + for index in 0 .. 2 { + let keypair = keypairs[index].clone(); + let transport = libp2p::core::transport::MemoryTransport + .and_then(move |out, endpoint| { + let secio = libp2p::secio::SecioConfig::new(keypair); + libp2p::core::upgrade::apply( + out, + secio, + endpoint, + libp2p::core::upgrade::Version::V1 + ) + }) + .and_then(move |(peer_id, stream), endpoint| { + libp2p::core::upgrade::apply( + stream, + libp2p::yamux::Config::default(), + endpoint, + libp2p::core::upgrade::Version::V1 + ) + .map_ok(|muxer| (peer_id, libp2p::core::muxing::StreamMuxerBox::new(muxer))) + }) + .timeout(Duration::from_secs(20)) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) + .boxed(); + + let (peerset, _) = sc_peerset::Peerset::from_config(sc_peerset::PeersetConfig { + in_peers: 25, + out_peers: 25, + bootnodes: if index == 0 { + keypairs + .iter() + .skip(1) + .map(|keypair| keypair.public().into_peer_id()) + .collect() + } else { + vec![] + }, + reserved_only: false, + reserved_nodes: Vec::new(), + }); + + let behaviour = CustomProtoWithAddr { + inner: LegacyProto::new(&b"test"[..], &[1], peerset), + addrs: addrs + .iter() + .enumerate() + .filter_map(|(n, a)| if n != index { + Some((keypairs[n].public().into_peer_id(), a.clone())) + } else { + None + }) + .collect(), + }; + + let mut swarm = Swarm::new( + transport, + behaviour, + keypairs[index].public().into_peer_id() + ); + Swarm::listen_on(&mut swarm, addrs[index].clone()).unwrap(); + out.push(swarm); + } + + // Final output + let mut out_iter = out.into_iter(); + let first = out_iter.next().unwrap(); + let second = out_iter.next().unwrap(); + (first, second) +} + +/// Wraps around the `CustomBehaviour` network behaviour, and adds hardcoded node addresses to it. +struct CustomProtoWithAddr { + inner: LegacyProto>, + addrs: Vec<(PeerId, Multiaddr)>, +} + +impl std::ops::Deref for CustomProtoWithAddr { + type Target = LegacyProto>; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl std::ops::DerefMut for CustomProtoWithAddr { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl NetworkBehaviour for CustomProtoWithAddr { + type ProtocolsHandler = + > as NetworkBehaviour>::ProtocolsHandler; + type OutEvent = > as NetworkBehaviour>::OutEvent; + + fn new_handler(&mut self) -> Self::ProtocolsHandler { + self.inner.new_handler() + } + + fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { + let mut list = self.inner.addresses_of_peer(peer_id); + for (p, a) in self.addrs.iter() { + if p == peer_id { + list.push(a.clone()); + } + } + list + } + + fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { + self.inner.inject_connected(peer_id, endpoint) + } + + fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { + self.inner.inject_disconnected(peer_id, endpoint) + } + + fn inject_node_event( + &mut self, + peer_id: PeerId, + event: <::Handler as ProtocolsHandler>::OutEvent + ) { + self.inner.inject_node_event(peer_id, event) + } + + fn poll( + &mut self, + cx: &mut Context, + params: &mut impl PollParameters + ) -> Poll< + NetworkBehaviourAction< + <::Handler as ProtocolsHandler>::InEvent, + Self::OutEvent + > + > { + self.inner.poll(cx, params) + } + + fn inject_replaced(&mut self, peer_id: PeerId, closed_endpoint: ConnectedPoint, new_endpoint: ConnectedPoint) { + self.inner.inject_replaced(peer_id, closed_endpoint, new_endpoint) + } + + fn inject_addr_reach_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn std::error::Error) { + self.inner.inject_addr_reach_failure(peer_id, addr, error) + } + + fn inject_dial_failure(&mut self, peer_id: &PeerId) { + self.inner.inject_dial_failure(peer_id) + } + + fn inject_new_listen_addr(&mut self, addr: &Multiaddr) { + self.inner.inject_new_listen_addr(addr) + } + + fn inject_expired_listen_addr(&mut self, addr: &Multiaddr) { + self.inner.inject_expired_listen_addr(addr) + } + + fn inject_new_external_addr(&mut self, addr: &Multiaddr) { + self.inner.inject_new_external_addr(addr) + } +} + +#[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) = build_nodes(); + + let fut1 = future::poll_fn(move |cx| -> Poll<()> { + loop { + match ready!(service1.poll_next_unpin(cx)) { + Some(LegacyProtoOut::CustomProtocolOpen { peer_id, .. }) => { + for n in 0 .. NUM_PACKETS { + service1.send_packet( + &peer_id, + Message::::ChainSpecific(vec![(n % 256) as u8]).encode() + ); + } + }, + _ => panic!(), + } + } + }); + + let mut packet_counter = 0u32; + let fut2 = future::poll_fn(move |cx| { + loop { + match ready!(service2.poll_next_unpin(cx)) { + Some(LegacyProtoOut::CustomProtocolOpen { .. }) => {}, + Some(LegacyProtoOut::CustomMessage { message, .. }) => { + match Message::::decode(&mut &message[..]).unwrap() { + Message::::ChainSpecific(message) => { + assert_eq!(message.len(), 1); + packet_counter += 1; + if packet_counter == NUM_PACKETS { + return Poll::Ready(()) + } + }, + _ => panic!(), + } + } + _ => panic!(), + } + } + }); + + futures::executor::block_on(async move { + future::select(fut1, fut2).await; + }); +} + +#[test] +fn basic_two_nodes_requests_in_parallel() { + let (mut service1, mut service2) = build_nodes(); + + // Generate random messages with or without a request id. + let mut to_send = { + let mut to_send = Vec::new(); + for _ in 0..200 { // Note: don't make that number too high or the CPU usage will explode. + let msg = (0..10).map(|_| rand::random::()).collect::>(); + to_send.push(Message::::ChainSpecific(msg)); + } + to_send + }; + + // 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 |cx| -> Poll<()> { + loop { + match ready!(service1.poll_next_unpin(cx)) { + Some(LegacyProtoOut::CustomProtocolOpen { peer_id, .. }) => { + for msg in to_send.drain(..) { + service1.send_packet(&peer_id, msg.encode()); + } + }, + _ => panic!(), + } + } + }); + + let fut2 = future::poll_fn(move |cx| { + loop { + match ready!(service2.poll_next_unpin(cx)) { + Some(LegacyProtoOut::CustomProtocolOpen { .. }) => {}, + Some(LegacyProtoOut::CustomMessage { message, .. }) => { + let pos = to_receive.iter().position(|m| m.encode() == message).unwrap(); + to_receive.remove(pos); + if to_receive.is_empty() { + return Poll::Ready(()) + } + } + _ => panic!(), + } + } + }); + + futures::executor::block_on(async move { + future::select(fut1, fut2).await; + }); +} + +#[test] +fn reconnect_after_disconnect() { + // We connect two nodes together, then force a disconnect (through the API of the `Service`), + // check that the disconnect worked, and finally check whether they successfully reconnect. + + let (mut service1, mut service2) = build_nodes(); + + // For this test, the services can be in the following states. + #[derive(Debug, Copy, Clone, PartialEq, Eq)] + enum ServiceState { NotConnected, FirstConnec, Disconnected, ConnectedAgain } + let mut service1_state = ServiceState::NotConnected; + let mut service2_state = ServiceState::NotConnected; + + // Run the events loops. + futures::executor::block_on(future::poll_fn(|cx| -> Poll> { + loop { + let mut service1_not_ready = false; + + match service1.poll_next_unpin(cx) { + Poll::Ready(Some(LegacyProtoOut::CustomProtocolOpen { .. })) => { + match service1_state { + ServiceState::NotConnected => { + service1_state = ServiceState::FirstConnec; + if service2_state == ServiceState::FirstConnec { + service1.disconnect_peer(Swarm::local_peer_id(&service2)); + } + }, + ServiceState::Disconnected => service1_state = ServiceState::ConnectedAgain, + ServiceState::FirstConnec | ServiceState::ConnectedAgain => panic!(), + } + }, + Poll::Ready(Some(LegacyProtoOut::CustomProtocolClosed { .. })) => { + match service1_state { + ServiceState::FirstConnec => service1_state = ServiceState::Disconnected, + ServiceState::ConnectedAgain| ServiceState::NotConnected | + ServiceState::Disconnected => panic!(), + } + }, + Poll::Pending => service1_not_ready = true, + _ => panic!() + } + + match service2.poll_next_unpin(cx) { + Poll::Ready(Some(LegacyProtoOut::CustomProtocolOpen { .. })) => { + match service2_state { + ServiceState::NotConnected => { + service2_state = ServiceState::FirstConnec; + if service1_state == ServiceState::FirstConnec { + service1.disconnect_peer(Swarm::local_peer_id(&service2)); + } + }, + ServiceState::Disconnected => service2_state = ServiceState::ConnectedAgain, + ServiceState::FirstConnec | ServiceState::ConnectedAgain => panic!(), + } + }, + Poll::Ready(Some(LegacyProtoOut::CustomProtocolClosed { .. })) => { + match service2_state { + ServiceState::FirstConnec => service2_state = ServiceState::Disconnected, + ServiceState::ConnectedAgain| ServiceState::NotConnected | + ServiceState::Disconnected => panic!(), + } + }, + Poll::Pending if service1_not_ready => break, + Poll::Pending => {} + _ => panic!() + } + } + + if service1_state == ServiceState::ConnectedAgain && service2_state == ServiceState::ConnectedAgain { + Poll::Ready(Ok(())) + } else { + Poll::Pending + } + })).unwrap(); + + // Do a second 3-seconds run to make sure we don't get disconnected immediately again. + let mut delay = futures_timer::Delay::new(Duration::from_secs(3)); + futures::executor::block_on(future::poll_fn(|cx| -> Poll> { + match service1.poll_next_unpin(cx) { + Poll::Pending => {}, + _ => panic!() + } + + match service2.poll_next_unpin(cx) { + Poll::Pending => {}, + _ => panic!() + } + + if let Poll::Ready(Ok(_)) = delay.poll_unpin(cx) { + Poll::Ready(Ok(())) + } else { + Poll::Pending + } + })).unwrap(); +} diff --git a/client/network/src/protocol/legacy_proto/upgrade.rs b/client/network/src/protocol/legacy_proto/upgrade.rs new file mode 100644 index 0000000000000..c021d5917f413 --- /dev/null +++ b/client/network/src/protocol/legacy_proto/upgrade.rs @@ -0,0 +1,298 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::config::ProtocolId; +use bytes::BytesMut; +use futures::prelude::*; +use futures_codec::Framed; +use libp2p::core::{Negotiated, Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName}; +use std::{collections::VecDeque, io, pin::Pin, vec::IntoIter as VecIntoIter}; +use std::task::{Context, Poll}; +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: Vec, + /// 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: impl Into, versions: &[u8]) + -> Self { + let protocol = protocol.into(); + let mut base_name = b"/substrate/".to_vec(); + base_name.extend_from_slice(protocol.as_bytes()); + 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 + }, + } + } +} + +impl Clone for RegisteredProtocol { + fn clone(&self) -> Self { + RegisteredProtocol { + id: self.id.clone(), + base_name: self.base_name.clone(), + supported_versions: self.supported_versions.clone(), + } + } +} + +/// 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_flush: bool, + /// The underlying substream. + inner: stream::Fuse, UviBytes>>, + /// 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, +} + +impl RegisteredProtocolSubstream { + /// Returns the version of the protocol that was negotiated. + 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 + } + + /// 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: Vec) { + if self.is_closing { + return + } + + self.send_queue.push_back(From::from(&data[..])); + } +} + +/// Event produced by the `RegisteredProtocolSubstream`. +#[derive(Debug, Clone)] +pub enum RegisteredProtocolEvent { + /// Received a message from the remote. + Message(BytesMut), + + /// Diagnostic event indicating that the connection is clogged and we should avoid sending too + /// many messages to it. + Clogged { + /// Copy of the messages that are within the buffer, for further diagnostic. + messages: Vec>, + }, +} + +impl Stream for RegisteredProtocolSubstream +where TSubstream: AsyncRead + AsyncWrite + Unpin { + type Item = Result; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + // Flushing the local queue. + while !self.send_queue.is_empty() { + match Pin::new(&mut self.inner).poll_ready(cx) { + Poll::Ready(Ok(())) => {}, + Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err))), + Poll::Pending => break, + } + + if let Some(packet) = self.send_queue.pop_front() { + Pin::new(&mut self.inner).start_send(packet)?; + self.requires_poll_flush = true; + } + } + + // If we are closing, close as soon as the Sink is closed. + if self.is_closing { + return match Pin::new(&mut self.inner).poll_close(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(Ok(_)) => Poll::Ready(None), + Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))), + } + } + + // 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 Poll::Ready(Some(Ok(RegisteredProtocolEvent::Clogged { + messages: self.send_queue.iter() + .map(|m| m.clone().to_vec()) + .collect(), + }))) + } + } else { + self.clogged_fuse = false; + } + + // Flushing if necessary. + if self.requires_poll_flush { + if let Poll::Ready(()) = Pin::new(&mut self.inner).poll_flush(cx)? { + self.requires_poll_flush = false; + } + } + + // Receiving incoming packets. + // Note that `inner` is wrapped in a `Fuse`, therefore we can poll it forever. + match Pin::new(&mut self.inner).poll_next(cx)? { + Poll::Ready(Some(data)) => { + Poll::Ready(Some(Ok(RegisteredProtocolEvent::Message(data)))) + } + Poll::Ready(None) => + if !self.requires_poll_flush && self.send_queue.is_empty() { + Poll::Ready(None) + } else { + Poll::Pending + } + Poll::Pending => Poll::Pending, + } + } +} + +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().map(|&version| { + let num = version.to_string(); + + let mut name = self.base_name.clone(); + name.extend_from_slice(num.as_bytes()); + RegisteredProtocolName { + name, + version, + } + }).collect::>().into_iter() + } +} + +/// Implementation of `ProtocolName` for a custom protocol. +#[derive(Debug, Clone)] +pub struct RegisteredProtocolName { + /// Protocol name, as advertised on the wire. + name: Vec, + /// Version number. Stored in string form in `name`, but duplicated here for easier retrieval. + version: u8, +} + +impl ProtocolName for RegisteredProtocolName { + fn protocol_name(&self) -> &[u8] { + &self.name + } +} + +impl InboundUpgrade for RegisteredProtocol +where TSubstream: AsyncRead + AsyncWrite + Unpin, +{ + type Output = RegisteredProtocolSubstream; + type Future = future::Ready>; + type Error = io::Error; + + fn upgrade_inbound( + self, + socket: Negotiated, + info: Self::Info, + ) -> Self::Future { + let framed = { + let mut codec = UviBytes::default(); + codec.set_max_len(16 * 1024 * 1024); // 16 MiB hard limit for packets. + Framed::new(socket, codec) + }; + + future::ok(RegisteredProtocolSubstream { + is_closing: false, + endpoint: Endpoint::Listener, + send_queue: VecDeque::new(), + requires_poll_flush: false, + inner: framed.fuse(), + protocol_version: info.version, + clogged_fuse: false, + }) + } +} + +impl OutboundUpgrade for RegisteredProtocol +where TSubstream: AsyncRead + AsyncWrite + Unpin, +{ + type Output = >::Output; + type Future = >::Future; + type Error = >::Error; + + fn upgrade_outbound( + self, + socket: Negotiated, + info: Self::Info, + ) -> Self::Future { + let framed = Framed::new(socket, UviBytes::default()); + + future::ok(RegisteredProtocolSubstream { + is_closing: false, + endpoint: Endpoint::Dialer, + send_queue: VecDeque::new(), + requires_poll_flush: false, + inner: framed.fuse(), + protocol_version: info.version, + clogged_fuse: false, + }) + } +} diff --git a/core/network/src/protocol/light_dispatch.rs b/client/network/src/protocol/light_dispatch.rs similarity index 93% rename from core/network/src/protocol/light_dispatch.rs rename to client/network/src/protocol/light_dispatch.rs index 33ff23c909d10..dd94abc2a46fd 100644 --- a/core/network/src/protocol/light_dispatch.rs +++ b/client/network/src/protocol/light_dispatch.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -23,16 +23,17 @@ use std::collections::{HashMap, VecDeque}; use std::sync::Arc; use std::time::{Instant, Duration}; use log::{trace, info}; -use futures::sync::oneshot::{Sender as OneShotSender}; +use futures::channel::oneshot::{Sender as OneShotSender}; use linked_hash_map::{Entry, LinkedHashMap}; -use client::error::Error as ClientError; -use client::light::fetcher::{FetchChecker, RemoteHeaderRequest, +use sp_blockchain::Error as ClientError; +use sc_client_api::{FetchChecker, RemoteHeaderRequest, RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof, - RemoteReadChildRequest, RemoteBodyRequest}; + RemoteReadChildRequest, RemoteBodyRequest, StorageProof}; use crate::message::{self, BlockAttributes, Direction, FromBlock, RequestId}; use libp2p::PeerId; use crate::config::Roles; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; +use sc_peerset::ReputationChange; /// Remote request timeout. const REQUEST_TIMEOUT: Duration = Duration::from_secs(15); @@ -44,7 +45,7 @@ const TIMEOUT_REPUTATION_CHANGE: i32 = -(1 << 8); /// Trait used by the `LightDispatch` service to communicate messages back to the network. pub trait LightDispatchNetwork { /// Adjusts the reputation of the given peer. - fn report_peer(&mut self, who: &PeerId, reputation_change: i32); + fn report_peer(&mut self, who: &PeerId, reputation_change: ReputationChange); /// Disconnect from the given peer. Used in case of misbehaviour. fn disconnect_peer(&mut self, who: &PeerId); @@ -68,6 +69,8 @@ pub trait LightDispatchNetwork { id: RequestId, block: ::Hash, storage_key: Vec, + child_info: Vec, + child_type: u32, keys: Vec>, ); @@ -174,7 +177,7 @@ impl FetchChecker for AlwaysBadChecker { &self, _request: &RemoteHeaderRequest, _remote_header: Option, - _remote_proof: Vec> + _remote_proof: StorageProof, ) -> Result { Err(ClientError::Msg("AlwaysBadChecker".into())) } @@ -182,7 +185,7 @@ impl FetchChecker for AlwaysBadChecker { fn check_read_proof( &self, _request: &RemoteReadRequest, - _remote_proof: Vec> + _remote_proof: StorageProof, ) -> Result,Option>>, ClientError> { Err(ClientError::Msg("AlwaysBadChecker".into())) } @@ -190,7 +193,7 @@ impl FetchChecker for AlwaysBadChecker { fn check_read_child_proof( &self, _request: &RemoteReadChildRequest, - _remote_proof: Vec> + _remote_proof: StorageProof, ) -> Result, Option>>, ClientError> { Err(ClientError::Msg("AlwaysBadChecker".into())) } @@ -198,7 +201,7 @@ impl FetchChecker for AlwaysBadChecker { fn check_execution_proof( &self, _request: &RemoteCallRequest, - _remote_proof: Vec> + _remote_proof: StorageProof, ) -> Result, ClientError> { Err(ClientError::Msg("AlwaysBadChecker".into())) } @@ -267,7 +270,7 @@ impl LightDispatch where Some(request) => request, None => { info!("Invalid remote {} response from peer {}", rtype, peer); - network.report_peer(&peer, i32::min_value()); + network.report_peer(&peer, ReputationChange::new_fatal("Invalid remote response")); network.disconnect_peer(&peer); self.remove_peer(peer); return; @@ -279,7 +282,7 @@ impl LightDispatch where Accept::Ok => (retry_count, None), Accept::CheckFailed(error, retry_request_data) => { info!("Failed to check remote {} response from peer {}: {}", rtype, peer, error); - network.report_peer(&peer, i32::min_value()); + network.report_peer(&peer, ReputationChange::new_fatal("Failed remote response check")); network.disconnect_peer(&peer); self.remove_peer(peer); @@ -293,7 +296,7 @@ impl LightDispatch where }, Accept::Unexpected(retry_request_data) => { info!("Unexpected response to remote {} from peer", rtype); - network.report_peer(&peer, i32::min_value()); + network.report_peer(&peer, ReputationChange::new_fatal("Unexpected remote response")); network.disconnect_peer(&peer); self.remove_peer(peer); @@ -350,7 +353,7 @@ impl LightDispatch where let (bad_peer, request) = self.active_peers.pop_front().expect("front() is Some as checked above"); self.pending_requests.push_front(request); - network.report_peer(&bad_peer, TIMEOUT_REPUTATION_CHANGE); + network.report_peer(&bad_peer, ReputationChange::new(TIMEOUT_REPUTATION_CHANGE, "Light request timeout")); network.disconnect_peer(&bad_peer); } @@ -621,6 +624,8 @@ impl Request { self.id, data.block, data.storage_key.clone(), + data.child_info.clone(), + data.child_type, data.keys.clone(), ), RequestData::RemoteCall(ref data, _) => @@ -675,17 +680,18 @@ pub mod tests { use std::collections::{HashMap, HashSet}; use std::sync::Arc; use std::time::Instant; - use futures::{Future, sync::oneshot}; - use sr_primitives::traits::{Block as BlockT, NumberFor, Header as HeaderT}; - use client::{error::{Error as ClientError, Result as ClientResult}}; - use client::light::fetcher::{FetchChecker, RemoteHeaderRequest, + use futures::channel::oneshot; + use sp_core::storage::ChildInfo; + use sp_runtime::traits::{Block as BlockT, NumberFor, Header as HeaderT}; + use sp_blockchain::{Error as ClientError, Result as ClientResult}; + use sc_client_api::{FetchChecker, RemoteHeaderRequest, ChangesProof, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest, RemoteChangesRequest, RemoteBodyRequest}; use crate::config::Roles; use crate::message::{self, BlockAttributes, Direction, FromBlock, RequestId}; use libp2p::PeerId; - use super::{REQUEST_TIMEOUT, LightDispatch, LightDispatchNetwork, RequestData}; - use test_client::runtime::{changes_trie_config, Block, Extrinsic, Header}; + use super::{REQUEST_TIMEOUT, LightDispatch, LightDispatchNetwork, RequestData, StorageProof}; + use sp_test_primitives::{changes_trie_config, Block, Extrinsic, Header}; struct DummyFetchChecker { ok: bool } @@ -694,7 +700,7 @@ pub mod tests { &self, _request: &RemoteHeaderRequest

, header: Option
, - _remote_proof: Vec> + _remote_proof: StorageProof, ) -> ClientResult
{ match self.ok { true if header.is_some() => Ok(header.unwrap()), @@ -705,7 +711,7 @@ pub mod tests { fn check_read_proof( &self, request: &RemoteReadRequest
, - _: Vec>, + _: StorageProof, ) -> ClientResult, Option>>> { match self.ok { true => Ok(request.keys @@ -721,7 +727,7 @@ pub mod tests { fn check_read_child_proof( &self, request: &RemoteReadChildRequest
, - _: Vec> + _: StorageProof, ) -> ClientResult, Option>>> { match self.ok { true => Ok(request.keys @@ -734,7 +740,7 @@ pub mod tests { } } - fn check_execution_proof(&self, _: &RemoteCallRequest
, _: Vec>) -> ClientResult> { + fn check_execution_proof(&self, _: &RemoteCallRequest
, _: StorageProof) -> ClientResult> { match self.ok { true => Ok(vec![42]), false => Err(ClientError::Backend("Test error".into())), @@ -780,7 +786,7 @@ pub mod tests { ) { light_dispatch.on_remote_call_response(network_interface, peer, message::RemoteCallResponse { id: id, - proof: vec![vec![2]], + proof: StorageProof::empty(), }); } @@ -800,14 +806,14 @@ pub mod tests { } impl<'a, B: BlockT> LightDispatchNetwork for &'a mut DummyNetwork { - fn report_peer(&mut self, _: &PeerId, _: i32) {} + fn report_peer(&mut self, _: &PeerId, _: crate::ReputationChange) {} fn disconnect_peer(&mut self, who: &PeerId) { self.disconnected_peers.insert(who.clone()); } fn send_header_request(&mut self, _: &PeerId, _: RequestId, _: <::Header as HeaderT>::Number) {} fn send_read_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: Vec>) {} fn send_read_child_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: Vec, - _: Vec>) {} + _: Vec, _: u32, _: Vec>) {} fn send_call_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: String, _: Vec) {} fn send_changes_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: ::Hash, _: ::Hash, _: ::Hash, _: Option>, _: Vec) {} @@ -943,7 +949,7 @@ pub mod tests { light_dispatch.on_remote_read_response(&mut network_interface, peer0.clone(), message::RemoteReadResponse { id: 0, - proof: vec![vec![2]], + proof: StorageProof::empty(), }); assert_disconnected_peer(&network_interface); assert_eq!(light_dispatch.pending_requests.len(), 1); @@ -993,7 +999,7 @@ pub mod tests { }, tx)); receive_call_response(&mut network_interface, &mut light_dispatch, peer0.clone(), 0); - assert_eq!(response.wait().unwrap().unwrap(), vec![42]); + assert_eq!(futures::executor::block_on(response).unwrap().unwrap(), vec![42]); } #[test] @@ -1013,9 +1019,12 @@ pub mod tests { light_dispatch.on_remote_read_response(&mut network_interface, peer0.clone(), message::RemoteReadResponse { id: 0, - proof: vec![vec![2]], + proof: StorageProof::empty(), }); - assert_eq!(response.wait().unwrap().unwrap().remove(b":key".as_ref()).unwrap(), Some(vec![42])); + assert_eq!( + futures::executor::block_on(response).unwrap().unwrap().remove(b":key".as_ref()).unwrap(), + Some(vec![42]) + ); } #[test] @@ -1026,10 +1035,14 @@ pub mod tests { light_dispatch.on_connect(&mut network_interface, peer0.clone(), Roles::FULL, 1000); let (tx, response) = oneshot::channel(); + let child_info = ChildInfo::new_default(b"unique_id_1"); + let (child_info, child_type) = child_info.info(); light_dispatch.add_request(&mut network_interface, RequestData::RemoteReadChild(RemoteReadChildRequest { header: dummy_header(), block: Default::default(), storage_key: b":child_storage:sub".to_vec(), + child_info: child_info.to_vec(), + child_type, keys: vec![b":key".to_vec()], retry_count: None, }, tx)); @@ -1037,9 +1050,9 @@ pub mod tests { light_dispatch.on_remote_read_response(&mut network_interface, peer0.clone(), message::RemoteReadResponse { id: 0, - proof: vec![vec![2]], + proof: StorageProof::empty(), }); - assert_eq!(response.wait().unwrap().unwrap().remove(b":key".as_ref()).unwrap(), Some(vec![42])); + assert_eq!(futures::executor::block_on(response).unwrap().unwrap().remove(b":key".as_ref()).unwrap(), Some(vec![42])); } #[test] @@ -1065,10 +1078,10 @@ pub mod tests { extrinsics_root: Default::default(), digest: Default::default(), }), - proof: vec![vec![2]], + proof: StorageProof::empty(), }); assert_eq!( - response.wait().unwrap().unwrap().hash(), + futures::executor::block_on(response).unwrap().unwrap().hash(), "6443a0b46e0412e626363028115a9f2cf963eeed526b8b33e5316f08b50d0dc3".parse().unwrap(), ); } @@ -1097,9 +1110,9 @@ pub mod tests { max: 1000, proof: vec![vec![2]], roots: vec![], - roots_proof: vec![], + roots_proof: StorageProof::empty(), }); - assert_eq!(response.wait().unwrap().unwrap(), vec![(100, 2)]); + assert_eq!(futures::executor::block_on(response).unwrap().unwrap(), vec![(100, 2)]); } #[test] @@ -1145,7 +1158,7 @@ pub mod tests { light_dispatch.on_remote_header_response(&mut network_interface, peer1.clone(), message::RemoteHeaderResponse { id: 0, header: Some(dummy_header()), - proof: vec![], + proof: StorageProof::empty(), }); assert!(!light_dispatch.idle_peers.iter().any(|_| true)); @@ -1223,7 +1236,7 @@ pub mod tests { assert_eq!(light_dispatch.active_peers.len(), 1); let block = message::BlockData:: { - hash: primitives::H256::random(), + hash: sp_core::H256::random(), header: None, body: Some(Vec::new()), message_queue: None, @@ -1261,7 +1274,7 @@ pub mod tests { let response = { let blocks: Vec<_> = (0..3).map(|_| message::BlockData:: { - hash: primitives::H256::random(), + hash: sp_core::H256::random(), header: None, body: Some(Vec::new()), message_queue: None, diff --git a/core/network/src/protocol/message.rs b/client/network/src/protocol/message.rs similarity index 86% rename from core/network/src/protocol/message.rs rename to client/network/src/protocol/message.rs index 6560ed0f13a52..30f0c34175aa5 100644 --- a/core/network/src/protocol/message.rs +++ b/client/network/src/protocol/message.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 @@ //! Network packet message types. These get serialized and put into the lower level protocol payload. use bitflags::bitflags; -use sr_primitives::{ConsensusEngineId, traits::{Block as BlockT, Header as HeaderT}}; +use sp_runtime::{ConsensusEngineId, traits::{Block as BlockT, Header as HeaderT}}; use codec::{Encode, Decode, Input, Output, Error}; pub use self::generic::{ BlockAnnounce, RemoteCallRequest, RemoteReadRequest, @@ -26,6 +26,7 @@ pub use self::generic::{ FinalityProofRequest, FinalityProofResponse, FromBlock, RemoteReadChildRequest, }; +use sc_client_api::StorageProof; /// A unique ID of a request. pub type RequestId = u64; @@ -103,7 +104,7 @@ impl Decode for BlockAttributes { pub enum Direction { /// Enumerate in ascending order (from child to parent). Ascending = 0, - /// Enumerate in descendfing order (from parent to canonical child). + /// Enumerate in descending order (from parent to canonical child). Descending = 1, } @@ -122,7 +123,7 @@ pub struct RemoteCallResponse { /// Id of a request this response was made for. pub id: RequestId, /// Execution proof. - pub proof: Vec>, + pub proof: StorageProof, } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -131,18 +132,18 @@ pub struct RemoteReadResponse { /// Id of a request this response was made for. pub id: RequestId, /// Read proof. - pub proof: Vec>, + pub proof: StorageProof, } /// Generic types. pub mod generic { use codec::{Encode, Decode, Input, Output}; - use sr_primitives::Justification; + use sp_runtime::Justification; use crate::config::Roles; use super::{ RemoteReadResponse, Transactions, Direction, RequestId, BlockAttributes, RemoteCallResponse, ConsensusEngineId, - BlockState, + BlockState, StorageProof, }; /// Consensus is mostly opaque to us #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -216,11 +217,40 @@ pub mod generic { FinalityProofRequest(FinalityProofRequest), /// Finality proof reponse. FinalityProofResponse(FinalityProofResponse), + /// Batch of consensus protocol messages. + ConsensusBatch(Vec), /// Chain-specific message. #[codec(index = "255")] ChainSpecific(Vec), } + impl Message { + /// Message id useful for logging. + pub fn id(&self) -> &'static str { + match self { + Message::Status(_) => "Status", + Message::BlockRequest(_) => "BlockRequest", + Message::BlockResponse(_) => "BlockResponse", + Message::BlockAnnounce(_) => "BlockAnnounce", + Message::Transactions(_) => "Transactions", + Message::Consensus(_) => "Consensus", + Message::RemoteCallRequest(_) => "RemoteCallRequest", + Message::RemoteCallResponse(_) => "RemoteCallResponse", + Message::RemoteReadRequest(_) => "RemoteReadRequest", + Message::RemoteReadResponse(_) => "RemoteReadResponse", + Message::RemoteHeaderRequest(_) => "RemoteHeaderRequest", + Message::RemoteHeaderResponse(_) => "RemoteHeaderResponse", + Message::RemoteChangesRequest(_) => "RemoteChangesRequest", + Message::RemoteChangesResponse(_) => "RemoteChangesResponse", + Message::RemoteReadChildRequest(_) => "RemoteReadChildRequest", + Message::FinalityProofRequest(_) => "FinalityProofRequest", + Message::FinalityProofResponse(_) => "FinalityProofResponse", + Message::ConsensusBatch(_) => "ConsensusBatch", + Message::ChainSpecific(_) => "ChainSpecific", + } + } + } + /// Status sent on connection. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub struct Status { @@ -338,6 +368,11 @@ pub mod generic { pub block: H, /// Child Storage key. pub storage_key: Vec, + /// Child trie source information. + pub child_info: Vec, + /// Child type, its required to resolve `child_info` + /// content and choose child implementation. + pub child_type: u32, /// Storage key. pub keys: Vec>, } @@ -359,7 +394,7 @@ pub mod generic { /// Header. None if proof generation has failed (e.g. header is unknown). pub header: Option
, /// Header proof. - pub proof: Vec>, + pub proof: StorageProof, } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -395,7 +430,7 @@ pub mod generic { /// Changes tries roots missing on the requester' node. pub roots: Vec<(N, H)>, /// Missing changes tries roots proof. - pub roots_proof: Vec>, + pub roots_proof: StorageProof, } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] diff --git a/core/network/src/protocol/specialization.rs b/client/network/src/protocol/specialization.rs similarity index 95% rename from core/network/src/protocol/specialization.rs rename to client/network/src/protocol/specialization.rs index e2c444ea889d6..9b1452160e535 100644 --- a/core/network/src/protocol/specialization.rs +++ b/client/network/src/protocol/specialization.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 @@ pub use crate::protocol::event::{DhtEvent, Event}; use crate::protocol::Context; use libp2p::PeerId; -use sr_primitives::traits::Block as BlockT; +use sp_runtime::traits::Block as BlockT; /// A specialization of the substrate network protocol. Handles events and sends messages. pub trait NetworkSpecialization: Send + Sync + 'static { @@ -42,7 +42,8 @@ pub trait NetworkSpecialization: Send + Sync + 'static { ); /// Called when a network-specific event arrives. - fn on_event(&mut self, event: Event); + #[deprecated(note = "This method is never called; please use `with_dht_event_tx` when building the service")] + fn on_event(&mut self, _event: Event) {} /// Called on abort. #[deprecated(note = "This method is never called; aborting corresponds to dropping the object")] diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs new file mode 100644 index 0000000000000..8929fc75f8dd8 --- /dev/null +++ b/client/network/src/protocol/sync.rs @@ -0,0 +1,1355 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. +// +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Contains the state of the chain synchronization process +//! +//! At any given point in time, a running node tries as much as possible to be at the head of the +//! chain. This module handles the logic of which blocks to request from remotes, and processing +//! responses. It yields blocks to check and potentially move to the database. +//! +//! # Usage +//! +//! The `ChainSync` struct maintains the state of the block requests. Whenever something happens on +//! the network, or whenever a block has been successfully verified, call the appropriate method in +//! order to update it. +//! + +use blocks::BlockCollection; +use sp_blockchain::{Error as ClientError, Info as BlockchainInfo}; +use sp_consensus::{BlockOrigin, BlockStatus, + block_validation::{BlockAnnounceValidator, Validation}, + import_queue::{IncomingBlock, BlockImportResult, BlockImportError} +}; +use crate::{ + config::{Roles, BoxFinalityProofRequestBuilder}, + message::{self, generic::FinalityProofRequest, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse, + FinalityProofResponse}, +}; +use either::Either; +use extra_requests::ExtraRequests; +use libp2p::PeerId; +use log::{debug, trace, warn, info, error}; +use sp_runtime::{ + Justification, + generic::BlockId, + traits::{Block as BlockT, Header, NumberFor, Zero, One, CheckedSub, SaturatedConversion} +}; +use std::{fmt, ops::Range, collections::{HashMap, HashSet, VecDeque}, sync::Arc}; + +mod blocks; +mod extra_requests; + +/// 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; + +/// Maximum blocks to download ahead of any gap. +const MAX_DOWNLOAD_AHEAD: u32 = 2048; + +/// We use a heuristic that with a high likelihood, by the time +/// `MAJOR_SYNC_BLOCKS` have been imported we'll be on the same +/// chain as (or at least closer to) the peer so we want to delay +/// the ancestor search to not waste time doing that when we are +/// so far behind. +const MAJOR_SYNC_BLOCKS: u8 = 5; + +/// Number of recently announced blocks to track for each peer. +const ANNOUNCE_HISTORY_SIZE: usize = 64; + +mod rep { + use sc_peerset::ReputationChange as Rep; + /// Reputation change when a peer sent us a message that led to a + /// database read error. + pub const BLOCKCHAIN_READ_ERROR: Rep = Rep::new(-(1 << 16), "DB Error"); + + /// Reputation change when a peer sent us a status message with a different + /// genesis than us. + pub const GENESIS_MISMATCH: Rep = Rep::new(i32::min_value(), "Genesis mismatch"); + + /// Reputation change for peers which send us a block with an incomplete header. + pub const INCOMPLETE_HEADER: Rep = Rep::new(-(1 << 20), "Incomplete header"); + + /// Reputation change for peers which send us a block which we fail to verify. + pub const VERIFICATION_FAIL: Rep = Rep::new(-(1 << 20), "Block verification failed"); + + /// Reputation change for peers which send us a known bad block. + pub const BAD_BLOCK: Rep = Rep::new(-(1 << 29), "Bad block"); + + /// Reputation change for peers which send us a block with bad justifications. + pub const BAD_JUSTIFICATION: Rep = Rep::new(-(1 << 16), "Bad justification"); + + /// Reputation change for peers which send us a block with bad finality proof. + pub const BAD_FINALITY_PROOF: Rep = Rep::new(-(1 << 16), "Bad finality proof"); + + /// Reputation change when a peer sent us invlid ancestry result. + pub const UNKNOWN_ANCESTOR:Rep = Rep::new(-(1 << 16), "DB Error"); +} + +/// The main data structure which contains all the state for a chains +/// active syncing strategy. +pub struct ChainSync { + /// Chain client. + client: Arc>, + /// The active peers that we are using to sync and their PeerSync status + peers: HashMap>, + /// A `BlockCollection` of blocks that are being downloaded from peers + blocks: BlockCollection, + /// The best block number in our queue of blocks to import + best_queued_number: NumberFor, + /// The best block hash in our queue of blocks to import + best_queued_hash: B::Hash, + /// The role of this node, e.g. light or full + role: Roles, + /// What block attributes we require for this node, usually derived from + /// what role we are, but could be customized + required_block_attributes: message::BlockAttributes, + /// Any extra finality proof requests. + extra_finality_proofs: ExtraRequests, + /// Any extra justification requests. + extra_justifications: ExtraRequests, + /// A set of hashes of blocks that are being downloaded or have been + /// downloaded and are queued for import. + queue_blocks: HashSet, + /// The best block number that was successfully imported into the chain. + /// This can not decrease. + best_imported_number: NumberFor, + /// Finality proof handler. + request_builder: Option>, + /// Fork sync targets. + fork_targets: HashMap>, + /// A flag that caches idle state with no pending requests. + is_idle: bool, + /// A type to check incoming block announcements. + block_announce_validator: Box + Send>, + /// Maximum number of peers to ask the same blocks in parallel. + max_parallel_downloads: u32, +} + +/// All the data we have about a Peer that we are trying to sync with +#[derive(Debug, Clone)] +pub struct PeerSync { + /// The common number is the block number that is a common point of + /// ancestry for both our chains (as far as we know). + pub common_number: NumberFor, + /// The hash of the best block that we've seen for this peer. + pub best_hash: B::Hash, + /// The number of the best block that we've seen for this peer. + pub best_number: NumberFor, + /// The state of syncing this peer is in for us, generally categories + /// into `Available` or "busy" with something as defined by `PeerSyncState`. + pub state: PeerSyncState, + /// A queue of blocks that this peer has announced to us, should only + /// contain `ANNOUNCE_HISTORY_SIZE` entries. + pub recently_announced: VecDeque +} + +/// The sync status of a peer we are trying to sync with +#[derive(Debug)] +pub struct PeerInfo { + /// Their best block hash. + pub best_hash: B::Hash, + /// Their best block number. + pub best_number: NumberFor +} + +struct ForkTarget { + number: NumberFor, + parent_hash: Option, + peers: HashSet, +} + +/// The state of syncing between a Peer and ourselves. +/// +/// Generally two categories, "busy" or `Available`. If busy, the enum +/// defines what we are busy with. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum PeerSyncState { + /// Available for sync requests. + Available, + /// Searching for ancestors the Peer has in common with us. + AncestorSearch(NumberFor, AncestorSearchState), + /// Actively downloading new blocks, starting from the given Number. + DownloadingNew(NumberFor), + /// Downloading a stale block with given Hash. Stale means that it is a + /// block with a number that is lower than our best number. It might be + /// from a fork and not necessarily already imported. + DownloadingStale(B::Hash), + /// Downloading justification for given block hash. + DownloadingJustification(B::Hash), + /// Downloading finality proof for given block hash. + DownloadingFinalityProof(B::Hash) +} + +impl PeerSyncState { + pub fn is_available(&self) -> bool { + if let PeerSyncState::Available = self { + true + } else { + false + } + } +} + +/// Reported sync state. +#[derive(Clone, Eq, PartialEq, Debug)] +pub enum SyncState { + /// Initial sync is complete, keep-up sync is active. + Idle, + /// Actively catching up with the chain. + Downloading +} + +/// Syncing status and statistics. +#[derive(Clone)] +pub struct Status { + /// Current global sync state. + pub state: SyncState, + /// Target sync block number. + pub best_seen_block: Option>, + /// Number of peers participating in syncing. + pub num_peers: u32, + /// Number of blocks queued for import + pub queued_blocks: u32, +} + +/// A peer did not behave as expected and should be reported. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BadPeer(pub PeerId, pub sc_peerset::ReputationChange); + +impl fmt::Display for BadPeer { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Bad peer {}; Reputation change: {:?}", self.0, self.1) + } +} + +impl std::error::Error for BadPeer {} + +/// Result of [`ChainSync::on_block_data`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum OnBlockData { + /// The block should be imported. + Import(BlockOrigin, Vec>), + /// A new block request needs to be made to the given peer. + Request(PeerId, BlockRequest) +} + +/// Result of [`ChainSync::on_block_announce`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum OnBlockAnnounce { + /// The announcement does not require further handling. + Nothing, + /// The announcement header should be imported. + ImportHeader, +} + +/// Result of [`ChainSync::on_block_justification`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum OnBlockJustification { + /// The justification needs no further handling. + Nothing, + /// The justification should be imported. + Import { + peer: PeerId, + hash: B::Hash, + number: NumberFor, + justification: Justification + } +} + +/// Result of [`ChainSync::on_block_finality_proof`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum OnBlockFinalityProof { + /// The proof needs no further handling. + Nothing, + /// The proof should be imported. + Import { + peer: PeerId, + hash: B::Hash, + number: NumberFor, + proof: Vec + } +} + +impl ChainSync { + /// Create a new instance. + pub fn new( + role: Roles, + client: Arc>, + info: &BlockchainInfo, + request_builder: Option>, + block_announce_validator: Box + Send>, + max_parallel_downloads: u32, + ) -> Self { + let mut required_block_attributes = BlockAttributes::HEADER | BlockAttributes::JUSTIFICATION; + + if role.is_full() { + required_block_attributes |= BlockAttributes::BODY + } + + ChainSync { + client, + peers: HashMap::new(), + blocks: BlockCollection::new(), + best_queued_hash: info.best_hash, + best_queued_number: info.best_number, + best_imported_number: info.best_number, + extra_finality_proofs: ExtraRequests::new(), + extra_justifications: ExtraRequests::new(), + role, + required_block_attributes, + queue_blocks: Default::default(), + request_builder, + fork_targets: Default::default(), + is_idle: false, + block_announce_validator, + max_parallel_downloads, + } + } + + /// Returns the state of the sync of the given peer. + /// + /// Returns `None` if the peer is unknown. + pub fn peer_info(&self, who: &PeerId) -> Option> { + self.peers.get(who).map(|p| PeerInfo { best_hash: p.best_hash, best_number: p.best_number }) + } + + /// Returns the current sync status. + pub fn status(&self) -> Status { + let best_seen = self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number); + let sync_state = + if let Some(n) = best_seen { + // A chain is classified as downloading if the provided best block is + // more than `MAJOR_SYNC_BLOCKS` behind the best queued block. + if n > self.best_queued_number && n - self.best_queued_number > MAJOR_SYNC_BLOCKS.into() { + SyncState::Downloading + } else { + SyncState::Idle + } + } else { + SyncState::Idle + }; + + Status { + state: sync_state, + best_seen_block: best_seen, + num_peers: self.peers.len() as u32, + queued_blocks: self.queue_blocks.len() as u32, + } + } + + /// Number of active sync requests. + pub fn num_sync_requests(&self) -> usize { + self.fork_targets.len() + } + + /// Handle a new connected peer. + /// + /// Call this method whenever we connect to a new peer. + pub fn new_peer(&mut self, who: PeerId, best_hash: B::Hash, best_number: NumberFor) + -> Result>, BadPeer> + { + // There is nothing sync can get from the node that has no blockchain data. + match self.block_status(&best_hash) { + Err(e) => { + debug!(target:"sync", "Error reading blockchain: {:?}", e); + Err(BadPeer(who, rep::BLOCKCHAIN_READ_ERROR)) + } + Ok(BlockStatus::KnownBad) => { + info!("New peer with known bad best block {} ({}).", best_hash, best_number); + Err(BadPeer(who, rep::BAD_BLOCK)) + } + Ok(BlockStatus::Unknown) => { + if best_number.is_zero() { + info!("New peer with unknown genesis hash {} ({}).", best_hash, best_number); + return Err(BadPeer(who, rep::GENESIS_MISMATCH)); + } + // If there are more than `MAJOR_SYNC_BLOCKS` in the import queue then we have + // enough to do in the import queue that it's not worth kicking off + // an ancestor search, which is what we do in the next match case below. + if self.queue_blocks.len() > MAJOR_SYNC_BLOCKS.into() { + 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, + best_number, + state: PeerSyncState::Available, + recently_announced: Default::default() + }); + return Ok(None) + } + + // If we are at genesis, just start downloading. + if self.best_queued_number.is_zero() { + debug!(target:"sync", "New peer with best hash {} ({}).", best_hash, best_number); + self.peers.insert(who.clone(), PeerSync { + common_number: Zero::zero(), + best_hash, + best_number, + state: PeerSyncState::Available, + recently_announced: Default::default(), + }); + self.is_idle = false; + return Ok(None) + } + + let common_best = std::cmp::min(self.best_queued_number, best_number); + + debug!(target:"sync", + "New peer with unknown best hash {} ({}), searching for common ancestor.", + best_hash, + best_number + ); + + self.peers.insert(who, PeerSync { + common_number: Zero::zero(), + best_hash, + best_number, + state: PeerSyncState::AncestorSearch( + common_best, + AncestorSearchState::ExponentialBackoff(One::one()) + ), + recently_announced: Default::default() + }); + self.is_idle = false; + + Ok(Some(ancestry_request::(common_best))) + } + Ok(BlockStatus::Queued) | Ok(BlockStatus::InChainWithState) | Ok(BlockStatus::InChainPruned) => { + debug!(target:"sync", "New peer with known best hash {} ({}).", best_hash, best_number); + self.peers.insert(who.clone(), PeerSync { + common_number: best_number, + best_hash, + best_number, + state: PeerSyncState::Available, + recently_announced: Default::default(), + }); + self.is_idle = false; + Ok(None) + } + } + } + + /// Signal that `best_header` has been queued for import and update the + /// `ChainSync` state with that information. + pub fn update_chain_info(&mut self, best_header: &B::Header) { + self.on_block_queued(&best_header.hash(), *best_header.number()) + } + + /// Schedule a justification request for the given block. + pub fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { + let client = &self.client; + self.extra_justifications.schedule((*hash, number), |base, block| { + client.is_descendent_of(base, block) + }) + } + + /// Schedule a finality proof request for the given block. + pub fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { + let client = &self.client; + self.extra_finality_proofs.schedule((*hash, number), |base, block| { + client.is_descendent_of(base, block) + }) + } + + /// Request syncing for the given block from given set of peers. + // The implementation is similar to on_block_announce with unknown parent hash. + pub fn set_sync_fork_request(&mut self, mut peers: Vec, hash: &B::Hash, number: NumberFor) { + if peers.is_empty() { + debug!( + target: "sync", + "Explicit sync request for block {:?} with no peers specified. \ + Syncing from all connected peers {:?} instead.", + hash, peers, + ); + + peers = self.peers.iter() + // Only request blocks from peers who are ahead or on a par. + .filter(|(_, peer)| peer.best_number >= number) + .map(|(id, _)| id.clone()) + .collect(); + } else { + debug!(target: "sync", "Explicit sync request for block {:?} with {:?}", hash, peers); + } + + if self.is_known(&hash) { + debug!(target: "sync", "Refusing to sync known hash {:?}", hash); + return; + } + + trace!(target: "sync", "Downloading requested old fork {:?}", hash); + self.is_idle = false; + for peer_id in &peers { + if let Some(peer) = self.peers.get_mut(peer_id) { + if let PeerSyncState::AncestorSearch(_, _) = peer.state { + continue; + } + + if number > peer.best_number { + peer.best_number = number; + peer.best_hash = hash.clone(); + } + } + } + + self.fork_targets + .entry(hash.clone()) + .or_insert_with(|| ForkTarget { + number, + peers: Default::default(), + parent_hash: None, + }) + .peers.extend(peers); + } + + /// Get an iterator over all scheduled justification requests. + pub fn justification_requests(&mut self) -> impl Iterator)> + '_ { + let peers = &mut self.peers; + let mut matcher = self.extra_justifications.matcher(); + std::iter::from_fn(move || { + if let Some((peer, request)) = matcher.next(&peers) { + peers.get_mut(&peer) + .expect("`Matcher::next` guarantees the `PeerId` comes from the given peers; qed") + .state = PeerSyncState::DownloadingJustification(request.0); + let req = message::generic::BlockRequest { + id: 0, + fields: BlockAttributes::JUSTIFICATION, + from: message::FromBlock::Hash(request.0), + to: None, + direction: message::Direction::Ascending, + max: Some(1) + }; + Some((peer, req)) + } else { + None + } + }) + } + + /// Get an iterator over all scheduled finality proof requests. + pub fn finality_proof_requests(&mut self) -> impl Iterator)> + '_ { + let peers = &mut self.peers; + let request_builder = &mut self.request_builder; + let mut matcher = self.extra_finality_proofs.matcher(); + std::iter::from_fn(move || { + if let Some((peer, request)) = matcher.next(&peers) { + peers.get_mut(&peer) + .expect("`Matcher::next` guarantees the `PeerId` comes from the given peers; qed") + .state = PeerSyncState::DownloadingFinalityProof(request.0); + let req = message::generic::FinalityProofRequest { + id: 0, + block: request.0, + request: request_builder.as_mut() + .map(|builder| builder.build_request_data(&request.0)) + .unwrap_or_default() + }; + Some((peer, req)) + } else { + None + } + }) + } + + /// Get an iterator over all block requests of all peers. + pub fn block_requests(&mut self) -> impl Iterator)> + '_ { + if self.is_idle { + return Either::Left(std::iter::empty()) + } + if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { + trace!(target: "sync", "Too many blocks in the queue."); + return Either::Left(std::iter::empty()) + } + let major_sync = self.status().state == SyncState::Downloading; + let blocks = &mut self.blocks; + let attrs = &self.required_block_attributes; + let fork_targets = &mut self.fork_targets; + let mut have_requests = false; + let last_finalized = self.client.info().finalized_number; + let best_queued = self.best_queued_number; + let client = &self.client; + let queue = &self.queue_blocks; + let max_parallel = if major_sync { 1 } else { self.max_parallel_downloads }; + let iter = self.peers.iter_mut().filter_map(move |(id, peer)| { + if !peer.state.is_available() { + trace!(target: "sync", "Peer {} is busy", id); + return None + } + if let Some((range, req)) = peer_block_request( + id, + peer, + blocks, + attrs, + max_parallel, + last_finalized, + best_queued, + ) { + peer.state = PeerSyncState::DownloadingNew(range.start); + trace!( + target: "sync", + "New block request for {}, (best:{}, common:{}) {:?}", + id, + peer.best_number, + peer.common_number, + req, + ); + have_requests = true; + Some((id.clone(), req)) + } else if let Some((hash, req)) = fork_sync_request( + id, + fork_targets, + best_queued, + last_finalized, + attrs, + |hash| if queue.contains(hash) { + BlockStatus::Queued + } else { + client.block_status(&BlockId::Hash(*hash)).unwrap_or(BlockStatus::Unknown) + }, + ) { + trace!(target: "sync", "Downloading fork {:?} from {}", hash, id); + peer.state = PeerSyncState::DownloadingStale(hash); + have_requests = true; + Some((id.clone(), req)) + } else { + None + } + }); + if !have_requests { + self.is_idle = true; + } + Either::Right(iter) + } + + /// Handle a response from the remote to a block request that we made. + /// + /// `request` must be the original request that triggered `response`. + /// or `None` if data comes from the block announcement. + /// + /// If this corresponds to a valid block, this outputs the block that + /// must be imported in the import queue. + pub fn on_block_data + (&mut self, who: PeerId, request: Option>, response: BlockResponse) -> Result, BadPeer> + { + let new_blocks: Vec> = + if let Some(peer) = self.peers.get_mut(&who) { + let mut blocks = response.blocks; + if request.as_ref().map_or(false, |r| r.direction == message::Direction::Descending) { + trace!(target: "sync", "Reversing incoming block list"); + blocks.reverse() + } + self.is_idle = false; + if request.is_some() { + match &mut peer.state { + PeerSyncState::DownloadingNew(start_block) => { + self.blocks.clear_peer_download(&who); + self.blocks.insert(*start_block, blocks, who); + peer.state = PeerSyncState::Available; + self.blocks + .drain(self.best_queued_number + One::one()) + .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, + allow_missing_state: true, + import_existing: false, + } + }).collect() + } + PeerSyncState::DownloadingStale(_) => { + peer.state = PeerSyncState::Available; + blocks.into_iter().map(|b| { + IncomingBlock { + hash: b.hash, + header: b.header, + body: b.body, + justification: b.justification, + origin: Some(who.clone()), + allow_missing_state: true, + import_existing: false, + } + }).collect() + } + PeerSyncState::AncestorSearch(num, state) => { + let matching_hash = match (blocks.get(0), self.client.block_hash(*num)) { + (Some(block), Ok(maybe_our_block_hash)) => { + trace!(target: "sync", "Got ancestry block #{} ({}) from peer {}", num, block.hash, who); + maybe_our_block_hash.filter(|x| x == &block.hash) + }, + (None, _) => { + debug!(target: "sync", "Invalid response when searching for ancestor from {}", who); + return Err(BadPeer(who, rep::UNKNOWN_ANCESTOR)) + }, + (_, Err(e)) => { + info!("Error answering legitimate blockchain query: {:?}", e); + return Err(BadPeer(who, rep::BLOCKCHAIN_READ_ERROR)) + } + }; + if matching_hash.is_some() && peer.common_number < *num { + peer.common_number = *num; + } + if matching_hash.is_none() && num.is_zero() { + trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); + return Err(BadPeer(who, rep::GENESIS_MISMATCH)) + } + if let Some((next_state, next_num)) = handle_ancestor_search_state(state, *num, matching_hash.is_some()) { + peer.state = PeerSyncState::AncestorSearch(next_num, next_state); + return Ok(OnBlockData::Request(who, ancestry_request::(next_num))) + } else { + // Ancestry search is complete. Check if peer is on a stale fork unknown to us and + // add it to sync targets if necessary. + trace!(target: "sync", "Ancestry search complete. Ours={} ({}), Theirs={} ({}), Common={:?} ({})", + self.best_queued_hash, + self.best_queued_number, + peer.best_hash, + peer.best_number, + matching_hash, + peer.common_number, + ); + if peer.common_number < peer.best_number + && peer.best_number < self.best_queued_number + { + trace!(target: "sync", "Added fork target {} for {}" , peer.best_hash, who); + self.fork_targets + .entry(peer.best_hash.clone()) + .or_insert_with(|| ForkTarget { + number: peer.best_number, + parent_hash: None, + peers: Default::default(), + }) + .peers.insert(who); + } + peer.state = PeerSyncState::Available; + Vec::new() + } + } + + | PeerSyncState::Available + | PeerSyncState::DownloadingJustification(..) + | PeerSyncState::DownloadingFinalityProof(..) => Vec::new() + } + } else { + // When request.is_none() just acccept blocks + blocks.into_iter().map(|b| { + IncomingBlock { + hash: b.hash, + header: b.header, + body: b.body, + justification: b.justification, + origin: Some(who.clone()), + allow_missing_state: true, + import_existing: false, + } + }).collect() + } + } else { + Vec::new() + }; + + 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((h, n)) = new_blocks.last().and_then(|b| b.header.as_ref().map(|h| (&b.hash, *h.number()))) { + trace!(target:"sync", "Accepted {} blocks ({:?}) with origin {:?}", new_blocks.len(), h, origin); + self.on_block_queued(h, n) + } + + self.queue_blocks.extend(new_blocks.iter().map(|b| b.hash)); + + Ok(OnBlockData::Import(origin, new_blocks)) + } + + /// Handle a response from the remote to a justification request that we made. + /// + /// `request` must be the original request that triggered `response`. + /// + /// Returns `Some` if this produces a justification that must be imported + /// into the import queue. + pub fn on_block_justification + (&mut self, who: PeerId, response: BlockResponse) -> Result, BadPeer> + { + let peer = + if let Some(peer) = self.peers.get_mut(&who) { + peer + } else { + error!(target: "sync", "Called on_block_justification with a bad peer ID"); + return Ok(OnBlockJustification::Nothing) + }; + + self.is_idle = false; + if let PeerSyncState::DownloadingJustification(hash) = peer.state { + peer.state = PeerSyncState::Available; + + // We only request one justification at a time + if let Some(block) = response.blocks.into_iter().next() { + if hash != block.hash { + info!( + target: "sync", + "Invalid block justification provided by {}: requested: {:?} got: {:?}", who, hash, block.hash + ); + return Err(BadPeer(who, rep::BAD_JUSTIFICATION)); + } + if let Some((peer, hash, number, j)) = self.extra_justifications.on_response(who, block.justification) { + return Ok(OnBlockJustification::Import { peer, hash, number, justification: j }) + } + } else { + // 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) + } + } + + Ok(OnBlockJustification::Nothing) + } + + /// Handle new finality proof data. + pub fn on_block_finality_proof + (&mut self, who: PeerId, resp: FinalityProofResponse) -> Result, BadPeer> + { + let peer = + if let Some(peer) = self.peers.get_mut(&who) { + peer + } else { + error!(target: "sync", "Called on_block_finality_proof_data with a bad peer ID"); + return Ok(OnBlockFinalityProof::Nothing) + }; + + self.is_idle = false; + if let PeerSyncState::DownloadingFinalityProof(hash) = peer.state { + peer.state = PeerSyncState::Available; + + // We only request one finality proof at a time. + if hash != resp.block { + info!( + target: "sync", + "Invalid block finality proof provided: requested: {:?} got: {:?}", + hash, + resp.block + ); + return Err(BadPeer(who, rep::BAD_FINALITY_PROOF)); + } + + if let Some((peer, hash, number, p)) = self.extra_finality_proofs.on_response(who, resp.proof) { + return Ok(OnBlockFinalityProof::Import { peer, hash, number, proof: p }) + } + } + + Ok(OnBlockFinalityProof::Nothing) + } + + /// A batch of blocks have been processed, with or without errors. + /// + /// Call this when a batch of blocks have been processed by the import + /// queue, with or without errors. + /// + /// `peer_info` is passed in case of a restart. + pub fn on_blocks_processed<'a>( + &'a mut self, + imported: usize, + count: usize, + results: Vec<(Result>, BlockImportError>, B::Hash)>, + ) -> impl Iterator), BadPeer>> + 'a { + trace!(target: "sync", "Imported {} of {}", imported, count); + + let mut output = Vec::new(); + + 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; + } + + match result { + Ok(BlockImportResult::ImportedKnown(_number)) => {} + Ok(BlockImportResult::ImportedUnknown(number, aux, who)) => { + if aux.clear_justification_requests { + trace!( + target: "sync", + "Block imported clears all pending justification requests {}: {:?}", + number, + hash + ); + self.extra_justifications.reset() + } + + if aux.needs_justification { + trace!(target: "sync", "Block imported but requires justification {}: {:?}", number, hash); + self.request_justification(&hash, number); + } + + if aux.bad_justification { + if let Some(peer) = who { + info!("Sent block with bad justification to import"); + output.push(Err(BadPeer(peer, rep::BAD_JUSTIFICATION))); + } + } + + if aux.needs_finality_proof { + trace!(target: "sync", "Block imported but requires finality proof {}: {:?}", number, hash); + self.request_finality_proof(&hash, number); + } + + if number > self.best_imported_number { + self.best_imported_number = number; + } + }, + Err(BlockImportError::IncompleteHeader(who)) => { + if let Some(peer) = who { + info!("Peer sent block with incomplete header to import"); + output.push(Err(BadPeer(peer, rep::INCOMPLETE_HEADER))); + output.extend(self.restart()); + } + }, + Err(BlockImportError::VerificationFailed(who, e)) => { + if let Some(peer) = who { + info!("Verification failed from peer: {}", e); + output.push(Err(BadPeer(peer, rep::VERIFICATION_FAIL))); + output.extend(self.restart()); + } + }, + Err(BlockImportError::BadBlock(who)) => { + if let Some(peer) = who { + info!("Block received from peer has been blacklisted"); + output.push(Err(BadPeer(peer, rep::BAD_BLOCK))); + output.extend(self.restart()); + } + }, + Err(BlockImportError::MissingState) => { + // This may happen if the chain we were requesting upon has been discarded + // in the meantime becasue other chain has been finalized. + // Don't mark it as bad as it still may be synced if explicitly requested. + trace!(target: "sync", "Obsolete block"); + }, + Err(BlockImportError::UnknownParent) | + Err(BlockImportError::Cancelled) | + Err(BlockImportError::Other(_)) => { + output.extend(self.restart()); + }, + }; + } + + for hash in hashes { + self.queue_blocks.remove(&hash); + } + + self.is_idle = false; + output.into_iter() + } + + /// Call this when a justification has been processed by the import queue, + /// with or without errors. + pub fn on_justification_import(&mut self, hash: B::Hash, number: NumberFor, success: bool) { + let finalization_result = if success { Ok((hash, number)) } else { Err(()) }; + self.extra_justifications.try_finalize_root((hash, number), finalization_result, true); + self.is_idle = false; + } + + pub fn on_finality_proof_import(&mut self, req: (B::Hash, NumberFor), res: Result<(B::Hash, NumberFor), ()>) { + self.extra_finality_proofs.try_finalize_root(req, res, true); + self.is_idle = false; + } + + /// Notify about finalization of the given block. + pub fn on_block_finalized(&mut self, hash: &B::Hash, number: NumberFor) { + let client = &self.client; + let r = self.extra_finality_proofs.on_block_finalized(hash, number, |base, block| { + client.is_descendent_of(base, block) + }); + + if let Err(err) = r { + warn!(target: "sync", "Error cleaning up pending extra finality proof data requests: {:?}", err) + } + + let client = &self.client; + let r = self.extra_justifications.on_block_finalized(hash, number, |base, block| { + client.is_descendent_of(base, block) + }); + + if let Err(err) = r { + warn!(target: "sync", "Error cleaning up pending extra justification data requests: {:?}", err); + } + } + + /// Called when a block has been queued for import. + /// + /// Updates our internal state for best queued block and then goes + /// through all peers to update our view of their state as well. + fn on_block_queued(&mut self, hash: &B::Hash, number: NumberFor) { + if let Some(_) = self.fork_targets.remove(&hash) { + trace!(target: "sync", "Completed fork sync {:?}", hash); + } + if number > self.best_queued_number { + self.best_queued_number = number; + self.best_queued_hash = *hash; + // Update common blocks + for (n, peer) in self.peers.iter_mut() { + if let PeerSyncState::AncestorSearch(_, _) = peer.state { + // Wait for ancestry search to complete first. + continue; + } + let new_common_number = if peer.best_number >= number { + number + } else { + peer.best_number + }; + trace!( + target: "sync", + "Updating peer {} info, ours={}, common={}->{}, their best={}", + n, + number, + peer.common_number, + new_common_number, + peer.best_number, + ); + peer.common_number = new_common_number; + } + } + self.is_idle = false; + } + + /// Call when a node announces a new block. + /// + /// If `OnBlockAnnounce::ImportHeader` is returned, then the caller MUST try to import passed + /// header (call `on_block_data`). The network request isn't sent + /// in this case. Both hash and header is passed as an optimization + /// to avoid rehashing the header. + pub fn on_block_announce(&mut self, who: PeerId, hash: B::Hash, announce: &BlockAnnounce, is_best: bool) + -> OnBlockAnnounce + { + let header = &announce.header; + let number = *header.number(); + debug!(target: "sync", "Received block announcement {:?} with number {:?} from {}", hash, number, who); + if number.is_zero() { + warn!(target: "sync", "Ignored genesis block (#0) announcement from {}: {}", who, hash); + return OnBlockAnnounce::Nothing + } + let parent_status = self.block_status(header.parent_hash()).ok().unwrap_or(BlockStatus::Unknown); + let known_parent = parent_status != BlockStatus::Unknown; + let ancient_parent = parent_status == BlockStatus::InChainPruned; + + let known = self.is_known(&hash); + let peer = if let Some(peer) = self.peers.get_mut(&who) { + peer + } else { + error!(target: "sync", "Called on_block_announce with a bad peer ID"); + return OnBlockAnnounce::Nothing + }; + while peer.recently_announced.len() >= ANNOUNCE_HISTORY_SIZE { + peer.recently_announced.pop_front(); + } + peer.recently_announced.push_back(hash.clone()); + if is_best { + // update their best block + peer.best_number = number; + peer.best_hash = hash; + } + if let PeerSyncState::AncestorSearch(_, _) = peer.state { + return OnBlockAnnounce::Nothing + } + // If the announced block is the best they have seen, our common number + // is either one further ahead or it's the one they just announced, if we know about it. + if is_best { + if known { + peer.common_number = number + } else if header.parent_hash() == &self.best_queued_hash || known_parent { + peer.common_number = number - One::one(); + } + } + self.is_idle = false; + + // known block case + if known || self.is_already_downloading(&hash) { + trace!(target: "sync", "Known block announce from {}: {}", who, hash); + if let Some(target) = self.fork_targets.get_mut(&hash) { + target.peers.insert(who); + } + return OnBlockAnnounce::Nothing + } + + // Let external validator check the block announcement. + let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice()); + match self.block_announce_validator.validate(&header, assoc_data) { + Ok(Validation::Success) => (), + Ok(Validation::Failure) => { + debug!(target: "sync", "Block announcement validation of block {} from {} failed", hash, who); + return OnBlockAnnounce::Nothing + } + Err(e) => { + error!(target: "sync", "Block announcement validation errored: {}", e); + return OnBlockAnnounce::Nothing + } + } + + if ancient_parent { + trace!(target: "sync", "Ignored ancient block announced from {}: {} {:?}", who, hash, header); + return OnBlockAnnounce::Nothing + } + + let requires_additional_data = !self.role.is_light() || !known_parent; + if !requires_additional_data { + trace!(target: "sync", "Importing new header announced from {}: {} {:?}", who, hash, header); + return OnBlockAnnounce::ImportHeader + } + + if number <= self.best_queued_number { + trace!( + target: "sync", + "Added sync target for block announced from {}: {} {:?}", who, hash, header + ); + self.fork_targets + .entry(hash.clone()) + .or_insert_with(|| ForkTarget { + number, + parent_hash: Some(header.parent_hash().clone()), + peers: Default::default(), + }) + .peers.insert(who); + } + + OnBlockAnnounce::Nothing + } + + /// Call when a peer has disconnected. + pub fn peer_disconnected(&mut self, who: PeerId) { + self.blocks.clear_peer_download(&who); + self.peers.remove(&who); + self.extra_justifications.peer_disconnected(&who); + self.extra_finality_proofs.peer_disconnected(&who); + self.is_idle = false; + } + + /// Restart the sync process. + fn restart<'a>(&'a mut self) -> impl Iterator), BadPeer>> + 'a + { + self.queue_blocks.clear(); + self.blocks.clear(); + let info = self.client.info(); + self.best_queued_hash = info.best_hash; + self.best_queued_number = std::cmp::max(info.best_number, self.best_imported_number); + self.is_idle = false; + debug!(target:"sync", "Restarted with {} ({})", self.best_queued_number, self.best_queued_hash); + let old_peers = std::mem::replace(&mut self.peers, HashMap::new()); + old_peers.into_iter().filter_map(move |(id, p)| { + match self.new_peer(id.clone(), p.best_hash, p.best_number) { + Ok(None) => None, + Ok(Some(x)) => Some(Ok((id, x))), + Err(e) => Some(Err(e)) + } + }) + } + + /// What is the status of the block corresponding to the given hash? + fn block_status(&self, hash: &B::Hash) -> Result { + if self.queue_blocks.contains(hash) { + return Ok(BlockStatus::Queued) + } + self.client.block_status(&BlockId::Hash(*hash)) + } + + /// Is the block corresponding to the given hash known? + fn is_known(&self, hash: &B::Hash) -> bool { + self.block_status(hash).ok().map_or(false, |s| s != BlockStatus::Unknown) + } + + /// Is any peer downloading the given hash? + fn is_already_downloading(&self, hash: &B::Hash) -> bool { + self.peers.iter().any(|(_, p)| p.state == PeerSyncState::DownloadingStale(*hash)) + } +} + +/// Request the ancestry for a block. Sends a request for header and justification for the given +/// block number. Used during ancestry search. +fn ancestry_request(block: NumberFor) -> BlockRequest { + message::generic::BlockRequest { + id: 0, + fields: BlockAttributes::HEADER | BlockAttributes::JUSTIFICATION, + from: message::FromBlock::Number(block), + to: None, + direction: message::Direction::Ascending, + max: Some(1) + } +} + +/// The ancestor search state expresses which algorithm, and its stateful parameters, we are using to +/// try to find an ancestor block +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub 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), +} + +/// This function handles the ancestor search strategy used. The goal is to find a common point +/// that both our chains agree on that is as close to the tip as possible. +/// The way this works is we first have an exponential backoff strategy, where we try to step +/// forward until we find a block hash mismatch. The size of the step doubles each step we take. +/// +/// When we've found a block hash mismatch we then fall back to a binary search between the two +/// last known points to find the common block closest to the tip. +fn handle_ancestor_search_state( + state: &AncestorSearchState, + curr_block_num: NumberFor, + block_hash_match: bool +) -> Option<(AncestorSearchState, NumberFor)> { + let two = >::one() + >::one(); + match state { + AncestorSearchState::ExponentialBackoff(next_distance_to_tip) => { + let next_distance_to_tip = *next_distance_to_tip; + if block_hash_match && next_distance_to_tip == One::one() { + // 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 / two; + let middle = left + (right - left) / two; + Some((AncestorSearchState::BinarySearch(left, right), middle)) + } else { + let next_block_num = curr_block_num.checked_sub(&next_distance_to_tip) + .unwrap_or_else(Zero::zero); + let next_distance_to_tip = next_distance_to_tip * two; + 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) / two; + Some((AncestorSearchState::BinarySearch(left, right), middle)) + } + } +} + +/// Get a new block request for the peer if any. +fn peer_block_request( + id: &PeerId, + peer: &PeerSync, + blocks: &mut BlockCollection, + attrs: &message::BlockAttributes, + max_parallel_downloads: u32, + finalized: NumberFor, + best_num: NumberFor, +) -> Option<(Range>, BlockRequest)> { + if peer.common_number < finalized { + return None; + } + if best_num >= peer.best_number { + // Will be downloaded as alternative fork instead. + return None; + } + if let Some(range) = blocks.needed_blocks( + id.clone(), + MAX_BLOCKS_TO_REQUEST, + peer.best_number, + peer.common_number, + max_parallel_downloads, + MAX_DOWNLOAD_AHEAD, + ) { + let request = message::generic::BlockRequest { + id: 0, + fields: attrs.clone(), + from: message::FromBlock::Number(range.start), + to: None, + direction: message::Direction::Ascending, + max: Some((range.end - range.start).saturated_into::()) + }; + Some((range, request)) + } else { + None + } +} + +/// Get pending fork sync targets for a peer. +fn fork_sync_request( + id: &PeerId, + targets: &mut HashMap>, + best_num: NumberFor, + finalized: NumberFor, + attributes: &message::BlockAttributes, + check_block: impl Fn(&B::Hash) -> BlockStatus, +) -> Option<(B::Hash, BlockRequest)> +{ + targets.retain(|hash, r| { + if r.number <= finalized { + trace!(target: "sync", "Removed expired fork sync request {:?} (#{})", hash, r.number); + return false; + } + if check_block(hash) != BlockStatus::Unknown { + trace!(target: "sync", "Removed obsolete fork sync request {:?} (#{})", hash, r.number); + return false; + } + true + }); + for (hash, r) in targets { + if !r.peers.contains(id) { + continue + } + if r.number <= best_num { + let parent_status = r.parent_hash.as_ref().map_or(BlockStatus::Unknown, check_block); + let mut count = (r.number - finalized).saturated_into::(); // up to the last finalized block + if parent_status != BlockStatus::Unknown { + // request only single block + count = 1; + } + trace!(target: "sync", "Downloading requested fork {:?} from {}, {} blocks", hash, id, count); + return Some((hash.clone(), message::generic::BlockRequest { + id: 0, + fields: attributes.clone(), + from: message::FromBlock::Hash(hash.clone()), + to: None, + direction: message::Direction::Descending, + max: Some(count), + })) + } + } + None +} diff --git a/core/network/src/protocol/sync/blocks.rs b/client/network/src/protocol/sync/blocks.rs similarity index 84% rename from core/network/src/protocol/sync/blocks.rs rename to client/network/src/protocol/sync/blocks.rs index 90264249ea03c..974935f765e6c 100644 --- a/core/network/src/protocol/sync/blocks.rs +++ b/client/network/src/protocol/sync/blocks.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,11 +21,9 @@ use std::collections::{HashMap, BTreeMap}; use std::collections::hash_map::Entry; use log::trace; use libp2p::PeerId; -use sr_primitives::traits::{Block as BlockT, NumberFor, One}; +use sp_runtime::traits::{Block as BlockT, NumberFor, One}; use crate::message; -const MAX_PARALLEL_DOWNLOADS: u32 = 1; - /// Block data with origin. #[derive(Debug, Clone, PartialEq, Eq)] pub struct BlockData { @@ -84,9 +82,7 @@ impl BlockCollection { match self.blocks.get(&start) { Some(&BlockRangeState::Downloading { .. }) => { - trace!(target: "sync", "Ignored block data still marked as being downloaded: {}", start); - debug_assert!(false); - return; + trace!(target: "sync", "Inserting block data still marked as being downloaded: {}", start); }, Some(&BlockRangeState::Complete(ref existing)) if existing.len() >= blocks.len() => { trace!(target: "sync", "Ignored block data already downloaded: {}", start); @@ -100,8 +96,20 @@ impl BlockCollection { } /// Returns a set of block hashes that require a header download. The returned set is marked as being downloaded. - pub fn needed_blocks(&mut self, who: PeerId, count: usize, peer_best: NumberFor, common: NumberFor) - -> Option>> { + pub fn needed_blocks( + &mut self, + who: PeerId, + count: usize, + peer_best: NumberFor, + common: NumberFor, + max_parallel: u32, + max_ahead: u32, + ) -> Option>> + { + if peer_best <= common { + // Bail out early + return None; + } // First block number that we need to download let first_different = common + >::one(); let count = (count as u32).into(); @@ -112,7 +120,7 @@ impl BlockCollection { let next = downloading_iter.next(); break match &(prev, next) { &(Some((start, &BlockRangeState::Downloading { ref len, downloading })), _) - if downloading < MAX_PARALLEL_DOWNLOADS => + if downloading < max_parallel => (*start .. *start + *len, downloading), &(Some((start, r)), Some((next_start, _))) if *start + r.len() < *next_start => (*start + r.len() .. cmp::min(*next_start, *start + r.len() + count), 0), // gap @@ -135,6 +143,12 @@ impl BlockCollection { return None; } range.end = cmp::min(peer_best + One::one(), range.end); + + if self.blocks.iter().next().map_or(false, |(n, _)| range.start > *n + max_ahead.into()) { + trace!(target: "sync", "Too far ahead for peer {} ({})", who, range.start); + return None; + } + self.peer_requests.insert(who, range.start); self.blocks.insert(range.start, BlockRangeState::Downloading { len: range.end - range.start, @@ -185,7 +199,6 @@ impl BlockCollection { true }, _ => { - debug_assert!(false); false } }; @@ -202,8 +215,8 @@ impl BlockCollection { mod test { use super::{BlockCollection, BlockData, BlockRangeState}; use crate::{message, PeerId}; - use sr_primitives::testing::{Block as RawBlock, ExtrinsicWrapper}; - use primitives::H256; + use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper}; + use sp_core::H256; type Block = RawBlock>; @@ -242,18 +255,18 @@ mod test { let peer2 = PeerId::random(); let blocks = generate_blocks(150); - assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0), Some(1 .. 41)); - assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0), Some(41 .. 81)); - assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 0), Some(81 .. 121)); + assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0, 1, 200), Some(1 .. 41)); + assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0, 1, 200), Some(41 .. 81)); + assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 0, 1, 200), Some(81 .. 121)); bc.clear_peer_download(&peer1); bc.insert(41, blocks[41..81].to_vec(), peer1.clone()); assert_eq!(bc.drain(1), vec![]); - assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0), Some(121 .. 151)); + assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0, 1, 200), Some(121 .. 151)); bc.clear_peer_download(&peer0); bc.insert(1, blocks[1..11].to_vec(), peer0.clone()); - assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0), Some(11 .. 41)); + assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0, 1, 200), Some(11 .. 41)); assert_eq!(bc.drain(1), blocks[1..11].iter() .map(|b| BlockData { block: b.clone(), origin: Some(peer0.clone()) }).collect::>()); @@ -267,7 +280,7 @@ mod test { .map(|b| BlockData { block: b.clone(), origin: Some(peer1.clone()) }).collect::>()[..]); bc.clear_peer_download(&peer2); - assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 80), Some(81 .. 121)); + assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 80, 1, 200), Some(81 .. 121)); bc.clear_peer_download(&peer2); bc.insert(81, blocks[81..121].to_vec(), peer2.clone()); bc.clear_peer_download(&peer1); @@ -292,7 +305,8 @@ mod test { bc.blocks.insert(114305, BlockRangeState::Complete(blocks)); let peer0 = PeerId::random(); - assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 000), Some(1 .. 100)); - assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 600), Some(100 + 128 .. 100 + 128 + 128)); + assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 000, 1, 200), Some(1 .. 100)); + assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 600, 1, 200), None); // too far ahead + assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 600, 1, 200000), Some(100 + 128 .. 100 + 128 + 128)); } } diff --git a/core/network/src/protocol/sync/extra_requests.rs b/client/network/src/protocol/sync/extra_requests.rs similarity index 98% rename from core/network/src/protocol/sync/extra_requests.rs rename to client/network/src/protocol/sync/extra_requests.rs index 28ed5fed9f682..a0ea68af5f334 100644 --- a/core/network/src/protocol/sync/extra_requests.rs +++ b/client/network/src/protocol/sync/extra_requests.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use client::error::Error as ClientError; +use sp_blockchain::Error as ClientError; use crate::protocol::sync::{PeerSync, PeerSyncState}; use fork_tree::ForkTree; use libp2p::PeerId; use log::{debug, warn}; -use sr_primitives::traits::{Block as BlockT, NumberFor, Zero}; +use sp_runtime::traits::{Block as BlockT, NumberFor, Zero}; use std::collections::{HashMap, HashSet, VecDeque}; use std::time::{Duration, Instant}; @@ -283,12 +283,12 @@ impl<'a, B: BlockT> Matcher<'a, B> { #[cfg(test)] mod tests { use crate::protocol::sync::PeerSync; - use client::error::Error as ClientError; + use sp_blockchain::Error as ClientError; use quickcheck::{Arbitrary, Gen, QuickCheck, StdThreadGen}; use rand::Rng; use std::collections::{HashMap, HashSet}; use super::*; - use test_client::runtime::{Block, BlockNumber, Hash}; + use sp_test_primitives::{Block, BlockNumber, Hash}; #[test] fn requests_are_processed_in_order() { diff --git a/client/network/src/protocol/util.rs b/client/network/src/protocol/util.rs new file mode 100644 index 0000000000000..9ba9bf6ae89c1 --- /dev/null +++ b/client/network/src/protocol/util.rs @@ -0,0 +1,76 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use 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/client/network/src/service.rs b/client/network/src/service.rs new file mode 100644 index 0000000000000..4e923a51a123e --- /dev/null +++ b/client/network/src/service.rs @@ -0,0 +1,863 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Main entry point of the sc-network crate. +//! +//! There are two main structs in this module: [`NetworkWorker`] and [`NetworkService`]. +//! The [`NetworkWorker`] *is* the network and implements the `Future` trait. It must be polled in +//! order fo the network to advance. +//! The [`NetworkService`] is merely a shared version of the [`NetworkWorker`]. You can obtain an +//! `Arc` by calling [`NetworkWorker::service`]. +//! +//! The methods of the [`NetworkService`] are implemented by sending a message over a channel, +//! which is then processed by [`NetworkWorker::poll`]. + +use std::{collections::{HashMap, HashSet}, fs, marker::PhantomData, io, path::Path}; +use std::sync::{Arc, atomic::{AtomicBool, AtomicUsize, Ordering}}; +use std::pin::Pin; +use std::task::Poll; + +use sp_consensus::import_queue::{ImportQueue, Link}; +use sp_consensus::import_queue::{BlockImportResult, BlockImportError}; +use futures::{prelude::*, channel::mpsc}; +use log::{warn, error, info}; +use libp2p::{PeerId, Multiaddr, kad::record}; +use libp2p::core::{transport::boxed::Boxed, muxing::StreamMuxerBox}; +use libp2p::swarm::NetworkBehaviour; +use parking_lot::Mutex; +use sc_peerset::PeersetHandle; +use sp_runtime::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId}; + +use crate::{behaviour::{Behaviour, BehaviourOut}, config::{parse_str_addr, parse_addr}}; +use crate::{NetworkState, NetworkStateNotConnectedPeer, NetworkStatePeer}; +use crate::{transport, config::NonReservedPeerMode, ReputationChange}; +use crate::config::{Params, TransportConfig}; +use crate::error::Error; +use crate::protocol::{self, Protocol, Context, PeerInfo}; +use crate::protocol::{event::Event, light_dispatch::{AlwaysBadChecker, RequestData}}; +use crate::protocol::specialization::NetworkSpecialization; +use crate::protocol::sync::SyncState; + +/// Minimum Requirements for a Hash within Networking +pub trait ExHashT: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static {} + +impl ExHashT for T where + T: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static +{} + +/// Transaction pool interface +pub trait TransactionPool: Send + Sync { + /// Get transactions from the pool that are ready to be propagated. + fn transactions(&self) -> Vec<(H, B::Extrinsic)>; + /// Get hash of transaction. + fn hash_of(&self, transaction: &B::Extrinsic) -> H; + /// Import a transaction into the pool. + /// + /// Peer reputation is changed by reputation_change if transaction is accepted by the pool. + fn import( + &self, + report_handle: ReportHandle, + who: PeerId, + reputation_change_good: ReputationChange, + reputation_change_bad: ReputationChange, + transaction: B::Extrinsic, + ); + /// Notify the pool about transactions broadcast. + fn on_broadcasted(&self, propagations: HashMap>); +} + +/// A cloneable handle for reporting cost/benefits of peers. +#[derive(Clone)] +pub struct ReportHandle { + inner: PeersetHandle, // wraps it so we don't have to worry about breaking API. +} + +impl From for ReportHandle { + fn from(peerset_handle: PeersetHandle) -> Self { + ReportHandle { inner: peerset_handle } + } +} + +impl ReportHandle { + /// Report a given peer as either beneficial (+) or costly (-) according to the + /// given scalar. + pub fn report_peer(&self, who: PeerId, cost_benefit: ReputationChange) { + self.inner.report_peer(who, cost_benefit); + } +} + +/// Substrate network service. Handles network IO and manages connectivity. +pub struct NetworkService, H: ExHashT> { + /// Number of peers we're connected to. + num_connected: Arc, + /// The local external addresses. + external_addresses: Arc>>, + /// Are we actively catching up with the chain? + is_major_syncing: Arc, + /// Local copy of the `PeerId` of the local node. + local_peer_id: PeerId, + /// Bandwidth logging system. Can be queried to know the average bandwidth consumed. + bandwidth: Arc, + /// Peerset manager (PSM); manages the reputation of nodes and indicates the network which + /// nodes it should be connected to or not. + peerset: PeersetHandle, + /// Channel that sends messages to the actual worker. + to_worker: mpsc::UnboundedSender>, + /// Marker to pin the `H` generic. Serves no purpose except to not break backwards + /// compatibility. + _marker: PhantomData, +} + +impl, H: ExHashT> NetworkWorker { + /// Creates the network service. + /// + /// Returns a `NetworkWorker` that implements `Future` and must be regularly polled in order + /// for the network processing to advance. From it, you can extract a `NetworkService` using + /// `worker.service()`. The `NetworkService` can be shared through the codebase. + pub fn new(params: Params) -> Result, Error> { + let (to_worker, from_worker) = mpsc::unbounded(); + + if let Some(ref path) = params.network_config.net_config_path { + fs::create_dir_all(Path::new(path))?; + } + + // List of multiaddresses that we know in the network. + let mut known_addresses = Vec::new(); + let mut bootnodes = Vec::new(); + let mut reserved_nodes = Vec::new(); + + // Process the bootnodes. + for bootnode in params.network_config.boot_nodes.iter() { + match parse_str_addr(bootnode) { + Ok((peer_id, addr)) => { + bootnodes.push(peer_id.clone()); + known_addresses.push((peer_id, addr)); + }, + Err(_) => warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode), + } + } + + // Check for duplicate bootnodes. + known_addresses.iter() + .try_for_each(|(peer_id, addr)| + if let Some(other) = known_addresses + .iter() + .find(|o| o.1 == *addr && o.0 != *peer_id) + { + Err(Error::DuplicateBootnode { + address: addr.clone(), + first_id: peer_id.clone(), + second_id: other.0.clone(), + }) + } else { + Ok(()) + } + )?; + + // Initialize the reserved peers. + for reserved in params.network_config.reserved_nodes.iter() { + if let Ok((peer_id, addr)) = parse_str_addr(reserved) { + reserved_nodes.push(peer_id.clone()); + known_addresses.push((peer_id, addr)); + } else { + warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved); + } + } + + let peerset_config = sc_peerset::PeersetConfig { + in_peers: params.network_config.in_peers, + out_peers: params.network_config.out_peers, + bootnodes, + reserved_only: params.network_config.non_reserved_mode == NonReservedPeerMode::Deny, + reserved_nodes, + }; + + // Private and public keys configuration. + let local_identity = params.network_config.node_key.clone().into_keypair()?; + let local_public = local_identity.public(); + let local_peer_id = local_public.clone().into_peer_id(); + info!(target: "sub-libp2p", "Local node identity is: {}", local_peer_id.to_base58()); + + let num_connected = Arc::new(AtomicUsize::new(0)); + let is_major_syncing = Arc::new(AtomicBool::new(false)); + let (protocol, peerset_handle) = Protocol::new( + protocol::ProtocolConfig { + roles: params.roles, + max_parallel_downloads: params.network_config.max_parallel_downloads, + }, + params.chain, + params.on_demand.as_ref().map(|od| od.checker().clone()) + .unwrap_or(Arc::new(AlwaysBadChecker)), + params.specialization, + params.transaction_pool, + params.finality_proof_provider, + params.finality_proof_request_builder, + params.protocol_id, + peerset_config, + params.block_announce_validator + )?; + + // Build the swarm. + let (mut swarm, bandwidth) = { + let user_agent = format!( + "{} ({})", + params.network_config.client_version, + params.network_config.node_name + ); + let behaviour = futures::executor::block_on(Behaviour::new( + protocol, + user_agent, + local_public, + known_addresses, + match params.network_config.transport { + TransportConfig::MemoryOnly => false, + TransportConfig::Normal { enable_mdns, .. } => enable_mdns, + }, + match params.network_config.transport { + TransportConfig::MemoryOnly => false, + TransportConfig::Normal { allow_private_ipv4, .. } => allow_private_ipv4, + }, + )); + let (transport, bandwidth) = { + let (config_mem, config_wasm) = match params.network_config.transport { + TransportConfig::MemoryOnly => (true, None), + TransportConfig::Normal { wasm_external_transport, .. } => + (false, wasm_external_transport) + }; + transport::build_transport(local_identity, config_mem, config_wasm) + }; + (Swarm::::new(transport, behaviour, local_peer_id.clone()), bandwidth) + }; + + // Listen on multiaddresses. + for addr in ¶ms.network_config.listen_addresses { + if let Err(err) = Swarm::::listen_on(&mut swarm, addr.clone()) { + warn!(target: "sub-libp2p", "Can't listen on {} because: {:?}", addr, err) + } + } + + // Add external addresses. + for addr in ¶ms.network_config.public_addresses { + Swarm::::add_external_address(&mut swarm, addr.clone()); + } + + let external_addresses = Arc::new(Mutex::new(Vec::new())); + + let service = Arc::new(NetworkService { + bandwidth, + external_addresses: external_addresses.clone(), + num_connected: num_connected.clone(), + is_major_syncing: is_major_syncing.clone(), + peerset: peerset_handle, + local_peer_id, + to_worker: to_worker.clone(), + _marker: PhantomData, + }); + + Ok(NetworkWorker { + external_addresses, + num_connected, + is_major_syncing, + network_service: swarm, + service, + import_queue: params.import_queue, + from_worker, + light_client_rqs: params.on_demand.and_then(|od| od.extract_receiver()), + event_streams: Vec::new(), + }) + } + + /// Returns the downloaded bytes per second averaged over the past few seconds. + pub fn average_download_per_sec(&self) -> u64 { + self.service.bandwidth.average_download_per_sec() + } + + /// Returns the uploaded bytes per second averaged over the past few seconds. + pub fn average_upload_per_sec(&self) -> u64 { + self.service.bandwidth.average_upload_per_sec() + } + + /// Returns the number of peers we're connected to. + pub fn num_connected_peers(&self) -> usize { + self.network_service.user_protocol().num_connected_peers() + } + + /// Returns the number of peers we're connected to and that are being queried. + pub fn num_active_peers(&self) -> usize { + self.network_service.user_protocol().num_active_peers() + } + + /// Current global sync state. + pub fn sync_state(&self) -> SyncState { + self.network_service.user_protocol().sync_state() + } + + /// Target sync block number. + pub fn best_seen_block(&self) -> Option> { + self.network_service.user_protocol().best_seen_block() + } + + /// Number of peers participating in syncing. + pub fn num_sync_peers(&self) -> u32 { + self.network_service.user_protocol().num_sync_peers() + } + + /// Number of blocks in the import queue. + pub fn num_queued_blocks(&self) -> u32 { + self.network_service.user_protocol().num_queued_blocks() + } + + /// Number of active sync requests. + pub fn num_sync_requests(&self) -> usize { + self.network_service.user_protocol().num_sync_requests() + } + + /// Adds an address for a node. + pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) { + self.network_service.add_known_address(peer_id, addr); + } + + /// Return a `NetworkService` that can be shared through the code base and can be used to + /// manipulate the worker. + pub fn service(&self) -> &Arc> { + &self.service + } + + /// You must call this when a new block is imported by the client. + pub fn on_block_imported(&mut self, hash: B::Hash, header: B::Header, data: Vec, is_best: bool) { + self.network_service.user_protocol_mut().on_block_imported(hash, &header, data, is_best); + } + + /// You must call this when a new block is finalized by the client. + pub fn on_block_finalized(&mut self, hash: B::Hash, header: B::Header) { + self.network_service.user_protocol_mut().on_block_finalized(hash, &header); + } + + /// Get network state. + /// + /// **Note**: Use this only for debugging. This API is unstable. There are warnings literaly + /// everywhere about this. Please don't use this function to retrieve actual information. + pub fn network_state(&mut self) -> NetworkState { + let swarm = &mut self.network_service; + let open = swarm.user_protocol().open_peers().cloned().collect::>(); + + let connected_peers = { + let swarm = &mut *swarm; + open.iter().filter_map(move |peer_id| { + let known_addresses = NetworkBehaviour::addresses_of_peer(&mut **swarm, peer_id) + .into_iter().collect(); + + let endpoint = if let Some(e) = swarm.node(peer_id).map(|i| i.endpoint()) { + e.clone().into() + } else { + error!(target: "sub-libp2p", "Found state inconsistency between custom protocol \ + and debug information about {:?}", peer_id); + return None + }; + + Some((peer_id.to_base58(), NetworkStatePeer { + endpoint, + version_string: swarm.node(peer_id) + .and_then(|i| i.client_version().map(|s| s.to_owned())).clone(), + latest_ping_time: swarm.node(peer_id).and_then(|i| i.latest_ping()), + enabled: swarm.user_protocol().is_enabled(&peer_id), + open: swarm.user_protocol().is_open(&peer_id), + known_addresses, + })) + }).collect() + }; + + let not_connected_peers = { + let swarm = &mut *swarm; + let list = swarm.known_peers().filter(|p| open.iter().all(|n| n != *p)) + .cloned().collect::>(); + list.into_iter().map(move |peer_id| { + (peer_id.to_base58(), NetworkStateNotConnectedPeer { + version_string: swarm.node(&peer_id) + .and_then(|i| i.client_version().map(|s| s.to_owned())).clone(), + latest_ping_time: swarm.node(&peer_id).and_then(|i| i.latest_ping()), + known_addresses: NetworkBehaviour::addresses_of_peer(&mut **swarm, &peer_id) + .into_iter().collect(), + }) + }).collect() + }; + + NetworkState { + peer_id: Swarm::::local_peer_id(&swarm).to_base58(), + listened_addresses: Swarm::::listeners(&swarm).cloned().collect(), + external_addresses: Swarm::::external_addresses(&swarm).cloned().collect(), + average_download_per_sec: self.service.bandwidth.average_download_per_sec(), + average_upload_per_sec: self.service.bandwidth.average_upload_per_sec(), + connected_peers, + not_connected_peers, + peerset: swarm.user_protocol_mut().peerset_debug_info(), + } + } + + /// Get currently connected peers. + pub fn peers_debug_info(&mut self) -> Vec<(PeerId, PeerInfo)> { + self.network_service.user_protocol_mut() + .peers_info() + .map(|(id, info)| (id.clone(), info.clone())) + .collect() + } + + /// Removes a `PeerId` from the list of reserved peers. + pub fn remove_reserved_peer(&self, peer: PeerId) { + self.service.remove_reserved_peer(peer); + } + + /// Adds a `PeerId` and its address as reserved. The string should encode the address + /// and peer ID of the remote node. + pub fn add_reserved_peer(&self, peer: String) -> Result<(), String> { + self.service.add_reserved_peer(peer) + } +} + +impl, H: ExHashT> NetworkService { + /// Writes a message on an open notifications channel. Has no effect if the notifications + /// channel with this protocol name is closed. + /// + /// > **Note**: The reason why this is a no-op in the situation where we have no channel is + /// > that we don't guarantee message delivery anyway. Networking issues can cause + /// > connections to drop at any time, and higher-level logic shouldn't differentiate + /// > between the remote voluntarily closing a substream or a network error + /// > preventing the message from being delivered. + /// + /// The protocol must have been registered with `register_notifications_protocol`. + /// + pub fn write_notification(&self, target: PeerId, engine_id: ConsensusEngineId, message: Vec) { + let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::WriteNotification { + target, + engine_id, + message, + }); + } + + /// Returns a stream containing the events that happen on the network. + /// + /// If this method is called multiple times, the events are duplicated. + /// + /// The stream never ends (unless the `NetworkWorker` gets shut down). + pub fn event_stream(&self) -> impl Stream { + // Note: when transitioning to stable futures, remove the `Error` entirely + let (tx, rx) = mpsc::unbounded(); + let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::EventStream(tx)); + rx + } + + /// Registers a new notifications protocol. + /// + /// After that, you can call `write_notifications`. + /// + /// Please call `event_stream` before registering a protocol, otherwise you may miss events + /// about the protocol that you have registered. + /// + /// You are very strongly encouraged to call this method very early on. Any connection open + /// will retain the protocols that were registered then, and not any new one. + pub fn register_notifications_protocol( + &self, + engine_id: ConsensusEngineId, + ) { + let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::RegisterNotifProtocol { + engine_id, + }); + } + + /// You must call this when new transactons are imported by the transaction pool. + /// + /// The latest transactions will be fetched from the `TransactionPool` that was passed at + /// initialization as part of the configuration. + pub fn trigger_repropagate(&self) { + let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::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. This function forces such an announcement. + pub fn announce_block(&self, hash: B::Hash, data: Vec) { + let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::AnnounceBlock(hash, data)); + } + + /// Report a given peer as either beneficial (+) or costly (-) according to the + /// given scalar. + pub fn report_peer(&self, who: PeerId, cost_benefit: ReputationChange) { + self.peerset.report_peer(who, cost_benefit); + } + + /// Disconnect from a node as soon as possible. + /// + /// This triggers the same effects as if the connection had closed itself spontaneously. + pub fn disconnect_peer(&self, who: PeerId) { + let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::DisconnectPeer(who)); + } + + /// Request a justification for the given block from the network. + /// + /// On success, the justification will be passed to the import queue that was part at + /// initialization as part of the configuration. + pub fn request_justification(&self, hash: &B::Hash, number: NumberFor) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::RequestJustification(hash.clone(), number)); + } + + /// Execute a closure with the chain-specific network specialization. + pub fn with_spec(&self, f: F) + where F: FnOnce(&mut S, &mut dyn Context) + Send + 'static + { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::ExecuteWithSpec(Box::new(f))); + } + + /// Are we in the process of downloading the chain? + pub fn is_major_syncing(&self) -> bool { + self.is_major_syncing.load(Ordering::Relaxed) + } + + /// Start getting a value from the DHT. + /// + /// This will generate either a `ValueFound` or a `ValueNotFound` event and pass it as an + /// item on the [`NetworkWorker`] stream. + pub fn get_value(&self, key: &record::Key) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::GetValue(key.clone())); + } + + /// Start putting a value in the DHT. + /// + /// This will generate either a `ValuePut` or a `ValuePutFailed` event and pass it as an + /// item on the [`NetworkWorker`] stream. + pub fn put_value(&self, key: record::Key, value: Vec) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::PutValue(key, value)); + } + + /// Connect to unreserved peers and allow unreserved peers to connect. + pub fn accept_unreserved_peers(&self) { + self.peerset.set_reserved_only(false); + } + + /// Disconnect from unreserved peers and deny new unreserved peers to connect. + pub fn deny_unreserved_peers(&self) { + self.peerset.set_reserved_only(true); + } + + /// Removes a `PeerId` from the list of reserved peers. + pub fn remove_reserved_peer(&self, peer: PeerId) { + self.peerset.remove_reserved_peer(peer); + } + + /// Adds a `PeerId` and its address as reserved. The string should encode the address + /// and peer ID of the remote node. + pub fn add_reserved_peer(&self, peer: String) -> Result<(), String> { + let (peer_id, addr) = parse_str_addr(&peer).map_err(|e| format!("{:?}", e))?; + self.peerset.add_reserved_peer(peer_id.clone()); + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::AddKnownAddress(peer_id, addr)); + Ok(()) + } + + /// Configure an explicit fork sync request. + /// Note that this function should not be used for recent blocks. + /// Sync should be able to download all the recent forks normally. + /// `set_sync_fork_request` should only be used if external code detects that there's + /// a stale fork missing. + /// Passing empty `peers` set effectively removes the sync request. + pub fn set_sync_fork_request(&self, peers: Vec, hash: B::Hash, number: NumberFor) { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::SyncFork(peers, hash, number)); + } + + /// Modify a peerset priority group. + pub fn set_priority_group(&self, group_id: String, peers: HashSet) -> Result<(), String> { + let peers = peers.into_iter().map(|p| { + parse_addr(p).map_err(|e| format!("{:?}", e)) + }).collect::, String>>()?; + + let peer_ids = peers.iter().map(|(peer_id, _addr)| peer_id.clone()).collect(); + self.peerset.set_priority_group(group_id, peer_ids); + + for (peer_id, addr) in peers.into_iter() { + let _ = self + .to_worker + .unbounded_send(ServiceToWorkerMsg::AddKnownAddress(peer_id, addr)); + } + + Ok(()) + } + + /// Returns the number of peers we're connected to. + pub fn num_connected(&self) -> usize { + self.num_connected.load(Ordering::Relaxed) + } +} + +impl, H: ExHashT> sp_consensus::SyncOracle + for NetworkService +{ + fn is_major_syncing(&mut self) -> bool { + NetworkService::is_major_syncing(self) + } + + fn is_offline(&mut self) -> bool { + self.num_connected.load(Ordering::Relaxed) == 0 + } +} + +impl<'a, B: BlockT + 'static, S: NetworkSpecialization, H: ExHashT> sp_consensus::SyncOracle + for &'a NetworkService +{ + fn is_major_syncing(&mut self) -> bool { + NetworkService::is_major_syncing(self) + } + + fn is_offline(&mut self) -> bool { + self.num_connected.load(Ordering::Relaxed) == 0 + } +} + +/// Trait for providing information about the local network state +pub trait NetworkStateInfo { + /// Returns the local external addresses. + fn external_addresses(&self) -> Vec; + + /// Returns the local Peer ID. + fn local_peer_id(&self) -> PeerId; +} + +impl NetworkStateInfo for NetworkService + where + B: sp_runtime::traits::Block, + S: NetworkSpecialization, + H: ExHashT, +{ + /// Returns the local external addresses. + fn external_addresses(&self) -> Vec { + self.external_addresses.lock().clone() + } + + /// Returns the local Peer ID. + fn local_peer_id(&self) -> PeerId { + self.local_peer_id.clone() + } +} + +/// Messages sent from the `NetworkService` to the `NetworkWorker`. +/// +/// Each entry corresponds to a method of `NetworkService`. +enum ServiceToWorkerMsg> { + PropagateExtrinsics, + RequestJustification(B::Hash, NumberFor), + AnnounceBlock(B::Hash, Vec), + ExecuteWithSpec(Box) + Send>), + GetValue(record::Key), + PutValue(record::Key, Vec), + AddKnownAddress(PeerId, Multiaddr), + SyncFork(Vec, B::Hash, NumberFor), + EventStream(mpsc::UnboundedSender), + WriteNotification { + message: Vec, + engine_id: ConsensusEngineId, + target: PeerId, + }, + RegisterNotifProtocol { + engine_id: ConsensusEngineId, + }, + DisconnectPeer(PeerId), +} + +/// Main network worker. Must be polled in order for the network to advance. +/// +/// You are encouraged to poll this in a separate background thread or task. +#[must_use = "The NetworkWorker must be polled in order for the network to work"] +pub struct NetworkWorker, H: ExHashT> { + /// Updated by the `NetworkWorker` and loaded by the `NetworkService`. + external_addresses: Arc>>, + /// Updated by the `NetworkWorker` and loaded by the `NetworkService`. + num_connected: Arc, + /// Updated by the `NetworkWorker` and loaded by the `NetworkService`. + is_major_syncing: Arc, + /// The network service that can be extracted and shared through the codebase. + service: Arc>, + /// The *actual* network. + network_service: Swarm, + /// The import queue that was passed as initialization. + import_queue: Box>, + /// Messages from the `NetworkService` and that must be processed. + from_worker: mpsc::UnboundedReceiver>, + /// Receiver for queries from the light client that must be processed. + light_client_rqs: Option>>, + /// Senders for events that happen on the network. + event_streams: Vec>, +} + +impl, H: ExHashT> Future for NetworkWorker { + type Output = Result<(), io::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context) -> Poll { + let this = &mut *self; + + // Poll the import queue for actions to perform. + this.import_queue.poll_actions(cx, &mut NetworkLink { + protocol: &mut this.network_service, + }); + + // Check for new incoming light client requests. + if let Some(light_client_rqs) = this.light_client_rqs.as_mut() { + while let Poll::Ready(Some(rq)) = light_client_rqs.poll_next_unpin(cx) { + this.network_service.user_protocol_mut().add_light_client_request(rq); + } + } + + loop { + // Process the next message coming from the `NetworkService`. + let msg = match this.from_worker.poll_next_unpin(cx) { + Poll::Ready(Some(msg)) => msg, + Poll::Ready(None) => return Poll::Ready(Ok(())), + Poll::Pending => break, + }; + + match msg { + ServiceToWorkerMsg::ExecuteWithSpec(task) => { + let protocol = this.network_service.user_protocol_mut(); + let (mut context, spec) = protocol.specialization_lock(); + task(spec, &mut context); + }, + ServiceToWorkerMsg::AnnounceBlock(hash, data) => + this.network_service.user_protocol_mut().announce_block(hash, data), + ServiceToWorkerMsg::RequestJustification(hash, number) => + this.network_service.user_protocol_mut().request_justification(&hash, number), + ServiceToWorkerMsg::PropagateExtrinsics => + this.network_service.user_protocol_mut().propagate_extrinsics(), + ServiceToWorkerMsg::GetValue(key) => + this.network_service.get_value(&key), + ServiceToWorkerMsg::PutValue(key, value) => + this.network_service.put_value(key, value), + ServiceToWorkerMsg::AddKnownAddress(peer_id, addr) => + this.network_service.add_known_address(peer_id, addr), + ServiceToWorkerMsg::SyncFork(peer_ids, hash, number) => + this.network_service.user_protocol_mut().set_sync_fork_request(peer_ids, &hash, number), + ServiceToWorkerMsg::EventStream(sender) => + this.event_streams.push(sender), + ServiceToWorkerMsg::WriteNotification { message, engine_id, target } => + this.network_service.user_protocol_mut().write_notification(target, engine_id, message), + ServiceToWorkerMsg::RegisterNotifProtocol { engine_id } => { + let events = this.network_service.user_protocol_mut().register_notifications_protocol(engine_id); + for event in events { + this.event_streams.retain(|sender| sender.unbounded_send(event.clone()).is_ok()); + } + }, + ServiceToWorkerMsg::DisconnectPeer(who) => + this.network_service.user_protocol_mut().disconnect_peer(&who), + } + } + + loop { + // Process the next action coming from the network. + let poll_value = this.network_service.poll_next_unpin(cx); + + match poll_value { + Poll::Pending => break, + Poll::Ready(Some(BehaviourOut::BlockImport(origin, blocks))) => + this.import_queue.import_blocks(origin, blocks), + Poll::Ready(Some(BehaviourOut::JustificationImport(origin, hash, nb, justification))) => + this.import_queue.import_justification(origin, hash, nb, justification), + Poll::Ready(Some(BehaviourOut::FinalityProofImport(origin, hash, nb, proof))) => + this.import_queue.import_finality_proof(origin, hash, nb, proof), + Poll::Ready(Some(BehaviourOut::Event(ev))) => { + this.event_streams.retain(|sender| sender.unbounded_send(ev.clone()).is_ok()); + }, + Poll::Ready(None) => { + error!(target: "sync", "Network events stream has returned None"); + break; + }, + }; + } + + // Update the variables shared with the `NetworkService`. + this.num_connected.store(this.network_service.user_protocol_mut().num_connected_peers(), Ordering::Relaxed); + { + let external_addresses = Swarm::::external_addresses(&this.network_service).cloned().collect(); + *this.external_addresses.lock() = external_addresses; + } + this.is_major_syncing.store(match this.network_service.user_protocol_mut().sync_state() { + SyncState::Idle => false, + SyncState::Downloading => true, + }, Ordering::Relaxed); + + Poll::Pending + } +} + +impl, H: ExHashT> Unpin for NetworkWorker { +} + +/// The libp2p swarm, customized for our needs. +type Swarm = libp2p::swarm::Swarm< + Boxed<(PeerId, StreamMuxerBox), io::Error>, + Behaviour +>; + +// Implementation of `import_queue::Link` trait using the available local variables. +struct NetworkLink<'a, B: BlockT, S: NetworkSpecialization, H: ExHashT> { + protocol: &'a mut Swarm, +} + +impl<'a, B: BlockT, S: NetworkSpecialization, H: ExHashT> Link for NetworkLink<'a, B, S, H> { + fn blocks_processed( + &mut self, + imported: usize, + count: usize, + results: Vec<(Result>, BlockImportError>, B::Hash)> + ) { + self.protocol.user_protocol_mut().blocks_processed(imported, count, results) + } + fn justification_imported(&mut self, who: PeerId, hash: &B::Hash, number: NumberFor, success: bool) { + self.protocol.user_protocol_mut().justification_import_result(hash.clone(), number, success); + if !success { + info!("Invalid justification provided by {} for #{}", who, hash); + self.protocol.user_protocol_mut().disconnect_peer(&who); + self.protocol.user_protocol_mut().report_peer(who, ReputationChange::new_fatal("Invalid justification")); + } + } + fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { + self.protocol.user_protocol_mut().request_justification(hash, number) + } + fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { + self.protocol.user_protocol_mut().request_finality_proof(hash, number) + } + fn finality_proof_imported( + &mut self, + who: PeerId, + request_block: (B::Hash, NumberFor), + finalization_result: Result<(B::Hash, NumberFor), ()>, + ) { + let success = finalization_result.is_ok(); + self.protocol.user_protocol_mut().finality_proof_import_result(request_block, finalization_result); + if !success { + info!("Invalid finality proof provided by {} for #{}", who, request_block.0); + self.protocol.user_protocol_mut().disconnect_peer(&who); + self.protocol.user_protocol_mut().report_peer(who, ReputationChange::new_fatal("Invalid finality proof")); + } + } +} diff --git a/core/network/src/transport.rs b/client/network/src/transport.rs similarity index 83% rename from core/network/src/transport.rs rename to client/network/src/transport.rs index 901ec18581e1d..d632f9b75c0c9 100644 --- a/core/network/src/transport.rs +++ b/client/network/src/transport.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,8 +22,8 @@ use libp2p::{ #[cfg(not(target_os = "unknown"))] use libp2p::{tcp, dns, websocket, noise}; #[cfg(not(target_os = "unknown"))] -use libp2p::core::{upgrade, either::EitherError, either::EitherOutput}; -use libp2p::core::{self, transport::boxed::Boxed, transport::OptionalTransport, muxing::StreamMuxerBox}; +use libp2p::core::{either::EitherError, either::EitherOutput}; +use libp2p::core::{self, upgrade, transport::boxed::Boxed, transport::OptionalTransport, muxing::StreamMuxerBox}; use std::{io, sync::Arc, time::Duration, usize}; pub use self::bandwidth::BandwidthSinks; @@ -71,7 +71,11 @@ pub fn build_transport( let desktop_trans = tcp::TcpConfig::new(); let desktop_trans = websocket::WsConfig::new(desktop_trans.clone()) .or_transport(desktop_trans); - OptionalTransport::some(dns::DnsConfig::new(desktop_trans)) + OptionalTransport::some(if let Ok(dns) = dns::DnsConfig::new(desktop_trans.clone()) { + dns.boxed() + } else { + desktop_trans.map_err(dns::DnsErr::Underlying).boxed() + }) } else { OptionalTransport::none() }); @@ -90,8 +94,8 @@ pub fn build_transport( #[cfg(not(target_os = "unknown"))] let transport = transport.and_then(move |stream, endpoint| { let upgrade = core::upgrade::SelectUpgrade::new(noise_config, secio_config); - core::upgrade::apply(stream, upgrade, endpoint) - .and_then(|out| match out { + core::upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1) + .map(|out| match out? { // We negotiated noise EitherOutput::First((remote_id, out)) => { let remote_key = match remote_id { @@ -101,16 +105,16 @@ pub fn build_transport( Ok((EitherOutput::First(out), remote_key.into_peer_id())) } // We negotiated secio - EitherOutput::Second(out) => - Ok((EitherOutput::Second(out.stream), out.remote_key.into_peer_id())) + EitherOutput::Second((remote_id, out)) => + Ok((EitherOutput::Second(out), remote_id)) }) }); // For WASM, we only support secio for now. #[cfg(target_os = "unknown")] let transport = transport.and_then(move |stream, endpoint| { - core::upgrade::apply(stream, secio_config, endpoint) - .and_then(|out| Ok((out.stream, out.remote_key.into_peer_id()))) + core::upgrade::apply(stream, secio_config, endpoint, upgrade::Version::V1) + .map_ok(|(id, stream)| ((stream, id))) }); // Multiplexing @@ -120,11 +124,11 @@ pub fn build_transport( .map_inbound(move |muxer| (peer_id, muxer)) .map_outbound(move |muxer| (peer_id2, muxer)); - core::upgrade::apply(stream, upgrade, endpoint) - .map(|(id, muxer)| (id, core::muxing::StreamMuxerBox::new(muxer))) + core::upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1) + .map_ok(|(id, muxer)| (id, core::muxing::StreamMuxerBox::new(muxer))) }) - .with_timeout(Duration::from_secs(20)) + .timeout(Duration::from_secs(20)) .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) .boxed(); diff --git a/client/network/src/utils.rs b/client/network/src/utils.rs new file mode 100644 index 0000000000000..f13505d0124db --- /dev/null +++ b/client/network/src/utils.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::time::Duration; +use futures::{FutureExt, Stream, StreamExt, stream::unfold}; +use futures_timer::Delay; + +pub fn interval(duration: Duration) -> impl Stream + Unpin { + unfold((), move |_| { + Delay::new(duration).map(|_| Some(((), ()))) + }).map(drop) +} diff --git a/client/network/test/Cargo.toml b/client/network/test/Cargo.toml new file mode 100644 index 0000000000000..381276ecfa5bd --- /dev/null +++ b/client/network/test/Cargo.toml @@ -0,0 +1,30 @@ +[package] +description = "Integration tests for Substrate network protocol" +name = "sc-network-test" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sc-network = { version = "0.8", path = "../" } +log = "0.4.8" +parking_lot = "0.9.0" +futures = "0.1.29" +futures03 = { package = "futures", version = "0.3.1", features = ["compat"] } +futures-timer = "0.4.0" +rand = "0.7.2" +libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["libp2p-websocket"] } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +sc-client = { version = "2.0.0", path = "../../" } +sc-client-api = { version = "2.0.0", path = "../../api" } +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sc-block-builder = { version = "2.0.0", path = "../../block-builder" } +sp-consensus-babe = { version = "0.8", path = "../../../primitives/consensus/babe" } +env_logger = "0.7.0" +substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } +substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } +tempfile = "3.1.0" +tokio = "0.1.22" diff --git a/client/network/test/src/block_import.rs b/client/network/test/src/block_import.rs new file mode 100644 index 0000000000000..5b2a1266c6776 --- /dev/null +++ b/client/network/test/src/block_import.rs @@ -0,0 +1,89 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Testing block import logic. + +use sp_consensus::ImportedAux; +use sp_consensus::import_queue::{ + import_single_block, BasicQueue, BlockImportError, BlockImportResult, IncomingBlock, +}; +use substrate_test_runtime_client::{self, prelude::*}; +use substrate_test_runtime_client::runtime::{Block, Hash}; +use sp_runtime::generic::BlockId; +use super::*; + +fn prepare_good_block() -> (TestClient, Hash, u64, PeerId, IncomingBlock) { + let mut client = substrate_test_runtime_client::new(); + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + 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(); + let peer_id = PeerId::random(); + (client, hash, number, peer_id.clone(), IncomingBlock { + hash, + header, + body: Some(Vec::new()), + justification, + origin: Some(peer_id.clone()), + allow_missing_state: false, + import_existing: false, + }) +} + +#[test] +fn import_single_good_block_works() { + let (_, _hash, number, peer_id, block) = prepare_good_block(); + + let mut expected_aux = ImportedAux::default(); + expected_aux.is_new_best = true; + + match import_single_block(&mut substrate_test_runtime_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + Ok(BlockImportResult::ImportedUnknown(ref num, ref aux, ref org)) + if *num == number && *aux == expected_aux && *org == Some(peer_id) => {} + r @ _ => panic!("{:?}", r) + } +} + +#[test] +fn import_single_good_known_block_is_ignored() { + let (mut client, _hash, number, _, block) = prepare_good_block(); + match import_single_block(&mut client, BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + Ok(BlockImportResult::ImportedKnown(ref n)) if *n == number => {} + _ => panic!() + } +} + +#[test] +fn import_single_good_block_without_header_fails() { + let (_, _, _, peer_id, mut block) = prepare_good_block(); + block.header = None; + match import_single_block(&mut substrate_test_runtime_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { + Err(BlockImportError::IncompleteHeader(ref org)) if *org == Some(peer_id) => {} + _ => panic!() + } +} + +#[test] +fn async_import_queue_drops() { + // Perform this test multiple times since it exhibits non-deterministic behavior. + for _ in 0..100 { + let verifier = PassThroughVerifier(true); + let queue = BasicQueue::new(verifier, Box::new(substrate_test_runtime_client::new()), None, None); + drop(queue); + } +} diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs new file mode 100644 index 0000000000000..f1b7fa478c6c8 --- /dev/null +++ b/client/network/test/src/lib.rs @@ -0,0 +1,917 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![allow(missing_docs)] + +#[cfg(test)] +mod block_import; +#[cfg(test)] +mod sync; + +use std::{collections::HashMap, pin::Pin, sync::Arc, marker::PhantomData}; + +use libp2p::build_multiaddr; +use log::trace; +use sc_network::FinalityProofProvider; +use sp_blockchain::{ + Result as ClientResult, well_known_cache_keys::{self, Id as CacheKeyId}, Info as BlockchainInfo, +}; +use sc_client_api::{ + BlockchainEvents, BlockImportNotification, + FinalityNotifications, ImportNotifications, + FinalityNotification, + backend::{TransactionFor, AuxStore, Backend, Finalizer}, +}; +use sc_block_builder::BlockBuilder; +use sc_client::LongestChain; +use sc_network::config::Roles; +use sp_consensus::block_validation::DefaultBlockAnnounceValidator; +use sp_consensus::import_queue::{ + BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport, +}; +use sp_consensus::block_import::{BlockImport, ImportResult}; +use sp_consensus::Error as ConsensusError; +use sp_consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, BlockCheckParams, JustificationImport}; +use futures::prelude::*; +use futures03::{Future as _, FutureExt as _, TryFutureExt as _, StreamExt as _, TryStreamExt as _}; +use sc_network::{NetworkWorker, NetworkStateInfo, NetworkService, ReportHandle, config::ProtocolId}; +use sc_network::config::{NetworkConfiguration, TransportConfig, BoxFinalityProofRequestBuilder}; +use libp2p::PeerId; +use parking_lot::Mutex; +use sp_core::H256; +use sc_network::{Context, ProtocolConfig}; +use sp_runtime::generic::{BlockId, OpaqueDigestItemId}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; +use sp_runtime::Justification; +use sc_network::TransactionPool; +use sc_network::specialization::NetworkSpecialization; +use substrate_test_runtime_client::{self, AccountKeyring}; + +pub use substrate_test_runtime_client::runtime::{Block, Extrinsic, Hash, Transfer}; +pub use substrate_test_runtime_client::{TestClient, TestClientBuilder, TestClientBuilderExt}; + +type AuthorityId = sp_consensus_babe::AuthorityId; + +/// A Verifier that accepts all blocks and passes them on with the configured +/// finality to be imported. +#[derive(Clone)] +pub struct PassThroughVerifier(pub bool); + +/// This `Verifier` accepts all data as valid. +impl Verifier for PassThroughVerifier { + fn verify( + &mut self, + origin: BlockOrigin, + header: B::Header, + justification: Option, + body: Option> + ) -> Result<(BlockImportParams, Option)>>), String> { + let maybe_keys = header.digest() + .log(|l| l.try_as_raw(OpaqueDigestItemId::Consensus(b"aura")) + .or_else(|| l.try_as_raw(OpaqueDigestItemId::Consensus(b"babe"))) + ) + .map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]); + + Ok((BlockImportParams { + origin, + header, + body, + storage_changes: None, + finalized: self.0, + justification, + post_digests: vec![], + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }, maybe_keys)) + } +} + +/// The test specialization. +#[derive(Clone)] +pub struct DummySpecialization; + +impl NetworkSpecialization for DummySpecialization { + fn status(&self) -> Vec { + vec![] + } + + fn on_connect( + &mut self, + _ctx: &mut dyn Context, + _peer_id: PeerId, + _status: sc_network::message::Status + ) {} + + fn on_disconnect(&mut self, _ctx: &mut dyn Context, _peer_id: PeerId) {} + + fn on_message( + &mut self, + _ctx: &mut dyn Context, + _peer_id: PeerId, + _message: Vec, + ) {} +} + +pub type PeersFullClient = + sc_client::Client; +pub type PeersLightClient = + sc_client::Client; + +#[derive(Clone)] +pub enum PeersClient { + Full(Arc, Arc), + Light(Arc, Arc), +} + +impl PeersClient { + pub fn as_full(&self) -> Option> { + match *self { + PeersClient::Full(ref client, ref _backend) => Some(client.clone()), + _ => None, + } + } + + pub fn as_block_import(&self) -> BlockImportAdapter { + match *self { + PeersClient::Full(ref client, ref _backend) => + BlockImportAdapter::new_full(client.clone()), + PeersClient::Light(ref client, ref _backend) => + BlockImportAdapter::Light(Arc::new(Mutex::new(client.clone())), PhantomData), + } + } + + pub fn get_aux(&self, key: &[u8]) -> ClientResult>> { + match *self { + PeersClient::Full(ref client, ref _backend) => client.get_aux(key), + PeersClient::Light(ref client, ref _backend) => client.get_aux(key), + } + } + + pub fn info(&self) -> BlockchainInfo { + match *self { + PeersClient::Full(ref client, ref _backend) => client.chain_info(), + PeersClient::Light(ref client, ref _backend) => client.chain_info(), + } + } + + pub fn header(&self, block: &BlockId) -> ClientResult::Header>> { + match *self { + PeersClient::Full(ref client, ref _backend) => client.header(block), + PeersClient::Light(ref client, ref _backend) => client.header(block), + } + } + + pub fn justification(&self, block: &BlockId) -> ClientResult> { + match *self { + PeersClient::Full(ref client, ref _backend) => client.justification(block), + PeersClient::Light(ref client, ref _backend) => client.justification(block), + } + } + + pub fn finality_notification_stream(&self) -> FinalityNotifications { + match *self { + PeersClient::Full(ref client, ref _backend) => client.finality_notification_stream(), + PeersClient::Light(ref client, ref _backend) => client.finality_notification_stream(), + } + } + + pub fn import_notification_stream(&self) -> ImportNotifications{ + match *self { + PeersClient::Full(ref client, ref _backend) => client.import_notification_stream(), + PeersClient::Light(ref client, ref _backend) => client.import_notification_stream(), + } + } + + pub fn finalize_block( + &self, + id: BlockId, + justification: Option, + notify: bool + ) -> ClientResult<()> { + match *self { + PeersClient::Full(ref client, ref _backend) => client.finalize_block(id, justification, notify), + PeersClient::Light(ref client, ref _backend) => client.finalize_block(id, justification, notify), + } + } +} + +pub struct Peer> { + pub data: D, + client: PeersClient, + /// We keep a copy of the verifier so that we can invoke it for locally-generated blocks, + /// instead of going through the import queue. + verifier: VerifierAdapter>, + /// We keep a copy of the block_import so that we can invoke it for locally-generated blocks, + /// instead of going through the import queue. + block_import: BlockImportAdapter<()>, + select_chain: Option>, + backend: Option>, + network: NetworkWorker::Hash>, + imported_blocks_stream: Box, Error = ()> + Send>, + finality_notification_stream: Box, Error = ()> + Send>, +} + +impl> Peer { + /// Get this peer ID. + pub fn id(&self) -> PeerId { + self.network.service().local_peer_id() + } + + /// Returns true if we're major syncing. + pub fn is_major_syncing(&self) -> bool { + self.network.service().is_major_syncing() + } + + // Returns a clone of the local SelectChain, only available on full nodes + pub fn select_chain(&self) -> Option> { + self.select_chain.clone() + } + + /// Returns the number of peers we're connected to. + pub fn num_peers(&self) -> usize { + self.network.num_connected_peers() + } + + /// Returns true if we have no peer. + pub fn is_offline(&self) -> bool { + self.num_peers() == 0 + } + + /// Request a justification for the given block. + pub fn request_justification(&self, hash: &::Hash, number: NumberFor) { + self.network.service().request_justification(hash, number); + } + + /// Announces an important block on the network. + pub fn announce_block(&self, hash: ::Hash, data: Vec) { + self.network.service().announce_block(hash, data); + } + + /// Request explicit fork sync. + pub fn set_sync_fork_request(&self, peers: Vec, hash: ::Hash, number: NumberFor) { + self.network.service().set_sync_fork_request(peers, hash, number); + } + + /// Add blocks to the peer -- edit the block before adding + pub fn generate_blocks(&mut self, count: usize, origin: BlockOrigin, edit_block: F) -> H256 + where F: FnMut(BlockBuilder) -> Block + { + let best_hash = self.client.info().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. + fn generate_blocks_at( + &mut self, + at: BlockId, + count: usize, + origin: BlockOrigin, + mut edit_block: F + ) -> H256 where F: FnMut(BlockBuilder) -> Block { + let full_client = self.client.as_full() + .expect("blocks could only be generated by full clients"); + let mut at = full_client.header(&at).unwrap().unwrap().hash(); + for _ in 0..count { + let builder = full_client.new_block_at( + &BlockId::Hash(at), + Default::default(), + false, + ).unwrap(); + let block = edit_block(builder); + let hash = block.header.hash(); + trace!( + target: "test_network", + "Generating {}, (#{}, parent={})", + hash, + block.header.number, + block.header.parent_hash, + ); + let header = block.header.clone(); + let (import_block, cache) = self.verifier.verify( + origin, + header.clone(), + None, + Some(block.extrinsics) + ).unwrap(); + let cache = if let Some(cache) = cache { + cache.into_iter().collect() + } else { + Default::default() + }; + self.block_import.import_block(import_block, cache).expect("block_import failed"); + self.network.on_block_imported(hash, header, Vec::new(), true); + at = hash; + } + + self.network.service().announce_block(at.clone(), Vec::new()); + at + } + + /// Push blocks to the peer (simplified: with or without a TX) + pub fn push_blocks(&mut self, count: usize, with_tx: bool) -> H256 { + let best_hash = self.client.info().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(&mut self, at: BlockId, count: usize, with_tx: bool) -> H256 { + let mut nonce = 0; + if with_tx { + self.generate_blocks_at(at, count, BlockOrigin::File, |mut builder| { + let transfer = Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Alice.into(), + amount: 1, + nonce, + }; + builder.push(transfer.into_signed_tx()).unwrap(); + nonce = nonce + 1; + builder.build().unwrap().block + }) + } else { + self.generate_blocks_at( + at, + count, + BlockOrigin::File, + |builder| builder.build().unwrap().block, + ) + } + } + + pub fn push_authorities_change_block(&mut self, new_authorities: Vec) -> H256 { + self.generate_blocks(1, BlockOrigin::File, |mut builder| { + builder.push(Extrinsic::AuthoritiesChange(new_authorities.clone())).unwrap(); + builder.build().unwrap().block + }) + } + + /// Get a reference to the client. + pub fn client(&self) -> &PeersClient { + &self.client + } + + /// Get a reference to the network service. + pub fn network_service(&self) -> &Arc::Hash>> { + &self.network.service() + } + + /// Test helper to compare the blockchain state of multiple (networked) + /// clients. + /// Potentially costly, as it creates in-memory copies of both blockchains in order + /// to compare them. If you have easier/softer checks that are sufficient, e.g. + /// by using .info(), you should probably use it instead of this. + pub fn blockchain_canon_equals(&self, other: &Self) -> bool { + if let (Some(mine), Some(others)) = (self.backend.clone(), other.backend.clone()) { + mine.as_in_memory().blockchain() + .canon_equals_to(others.as_in_memory().blockchain()) + } else { + false + } + } + + /// Count the total number of imported blocks. + pub fn blocks_count(&self) -> u64 { + self.backend.as_ref().map( + |backend| backend.blocks_count() + ).unwrap_or(0) + } +} + +pub struct EmptyTransactionPool; + +impl TransactionPool for EmptyTransactionPool { + fn transactions(&self) -> Vec<(Hash, Extrinsic)> { + Vec::new() + } + + fn hash_of(&self, _transaction: &Extrinsic) -> Hash { + Hash::default() + } + + fn import( + &self, + _report_handle: ReportHandle, + _who: PeerId, + _rep_change_good: sc_network::ReputationChange, + _rep_change_bad: sc_network::ReputationChange, + _transaction: Extrinsic + ) {} + + fn on_broadcasted(&self, _: HashMap>) {} +} + +pub trait SpecializationFactory { + fn create() -> Self; +} + +impl SpecializationFactory for DummySpecialization { + fn create() -> DummySpecialization { + DummySpecialization + } +} + +/// Implements `BlockImport` for any `Transaction`. Internally the transaction is +/// "converted", aka the field is set to `None`. +/// +/// This is required as the `TestNetFactory` trait does not distinguish between +/// full and light nodes. +pub enum BlockImportAdapter { + Full( + Arc, + Error = ConsensusError + > + Send>>, + PhantomData, + ), + Light( + Arc, + Error = ConsensusError + > + Send>>, + PhantomData, + ), +} + +impl BlockImportAdapter { + /// Create a new instance of `Self::Full`. + pub fn new_full( + full: impl BlockImport< + Block, + Transaction = TransactionFor, + Error = ConsensusError + > + + 'static + + Send + ) -> Self { + Self::Full(Arc::new(Mutex::new(full)), PhantomData) + } + + /// Create a new instance of `Self::Light`. + pub fn new_light( + light: impl BlockImport< + Block, + Transaction = TransactionFor, + Error = ConsensusError + > + + 'static + + Send + ) -> Self { + Self::Light(Arc::new(Mutex::new(light)), PhantomData) + } +} + +impl Clone for BlockImportAdapter { + fn clone(&self) -> Self { + match self { + Self::Full(full, _) => Self::Full(full.clone(), PhantomData), + Self::Light(light, _) => Self::Light(light.clone(), PhantomData), + } + } +} + +impl BlockImport for BlockImportAdapter { + type Error = ConsensusError; + type Transaction = Transaction; + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + match self { + Self::Full(full, _) => full.lock().check_block(block), + Self::Light(light, _) => light.lock().check_block(block), + } + } + + fn import_block( + &mut self, + block: BlockImportParams, + cache: HashMap>, + ) -> Result { + match self { + Self::Full(full, _) => full.lock().import_block(block.convert_transaction(), cache), + Self::Light(light, _) => light.lock().import_block(block.convert_transaction(), cache), + } + } +} + +/// Implements `Verifier` on an `Arc>`. Used internally. +struct VerifierAdapter(Arc>>); + +impl Clone for VerifierAdapter { + fn clone(&self) -> Self { + VerifierAdapter(self.0.clone()) + } +} + +impl> Verifier for VerifierAdapter { + fn verify( + &mut self, + origin: BlockOrigin, + header: B::Header, + justification: Option, + body: Option> + ) -> Result<(BlockImportParams, Option)>>), String> { + self.0.lock().verify(origin, header, justification, body) + } +} + +pub trait TestNetFactory: Sized { + type Specialization: NetworkSpecialization + SpecializationFactory; + type Verifier: 'static + Verifier; + type PeerData: Default; + + /// These two need to be implemented! + fn from_config(config: &ProtocolConfig) -> Self; + fn make_verifier( + &self, + client: PeersClient, + config: &ProtocolConfig, + peer_data: &Self::PeerData, + ) -> Self::Verifier; + + /// Get reference to peer. + fn peer(&mut self, i: usize) -> &mut Peer; + fn peers(&self) -> &Vec>; + fn mut_peers>)>( + &mut self, + closure: F, + ); + + /// Get custom block import handle for fresh client, along with peer data. + fn make_block_import(&self, client: PeersClient) + -> ( + BlockImportAdapter, + Option>, + Option>, + Option>, + Self::PeerData, + ) + { + (client.as_block_import(), None, None, None, Default::default()) + } + + /// Get finality proof provider (if supported). + fn make_finality_proof_provider( + &self, + _client: PeersClient, + ) -> Option>> { + None + } + + fn default_config() -> ProtocolConfig { + ProtocolConfig::default() + } + + /// Create new test network with this many peers. + fn new(n: usize) -> Self { + trace!(target: "test_network", "Creating test network"); + let config = Self::default_config(); + let mut net = Self::from_config(&config); + + for i in 0..n { + trace!(target: "test_network", "Adding peer {}", i); + net.add_full_peer(&config); + } + net + } + + fn add_full_peer(&mut self, config: &ProtocolConfig) { + self.add_full_peer_with_states(config, None) + } + + /// Add a full peer. + fn add_full_peer_with_states(&mut self, config: &ProtocolConfig, keep_blocks: Option) { + let test_client_builder = match keep_blocks { + Some(keep_blocks) => TestClientBuilder::with_pruning_window(keep_blocks), + None => TestClientBuilder::with_default_backend(), + }; + let backend = test_client_builder.backend(); + let (c, longest_chain) = test_client_builder.build_with_longest_chain(); + let client = Arc::new(c); + + let ( + block_import, + justification_import, + finality_proof_import, + finality_proof_request_builder, + data, + ) = self.make_block_import(PeersClient::Full(client.clone(), backend.clone())); + + let verifier = self.make_verifier( + PeersClient::Full(client.clone(), backend.clone()), + config, + &data, + ); + let verifier = VerifierAdapter(Arc::new(Mutex::new(Box::new(verifier) as Box<_>))); + + let import_queue = Box::new(BasicQueue::new( + verifier.clone(), + Box::new(block_import.clone()), + justification_import, + finality_proof_import, + )); + + let listen_addr = build_multiaddr![Memory(rand::random::())]; + + let network = NetworkWorker::new(sc_network::config::Params { + roles: config.roles, + network_config: NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + transport: TransportConfig::MemoryOnly, + ..NetworkConfiguration::default() + }, + chain: client.clone(), + finality_proof_provider: self.make_finality_proof_provider( + PeersClient::Full(client.clone(), backend.clone()), + ), + finality_proof_request_builder, + on_demand: None, + transaction_pool: Arc::new(EmptyTransactionPool), + protocol_id: ProtocolId::from(&b"test-protocol-name"[..]), + import_queue, + specialization: self::SpecializationFactory::create(), + block_announce_validator: Box::new(DefaultBlockAnnounceValidator::new(client.clone())) + }).unwrap(); + + self.mut_peers(|peers| { + for peer in peers.iter_mut() { + peer.network.add_known_address(network.service().local_peer_id(), listen_addr.clone()); + } + + let imported_blocks_stream = Box::new(client.import_notification_stream() + .map(|v| Ok::<_, ()>(v)).compat().fuse()); + let finality_notification_stream = Box::new(client.finality_notification_stream() + .map(|v| Ok::<_, ()>(v)).compat().fuse()); + + peers.push(Peer { + data, + client: PeersClient::Full(client, backend.clone()), + select_chain: Some(longest_chain), + backend: Some(backend), + imported_blocks_stream, + finality_notification_stream, + block_import, + verifier, + network, + }); + }); + } + + /// Add a light peer. + fn add_light_peer(&mut self, config: &ProtocolConfig) { + let mut config = config.clone(); + config.roles = Roles::LIGHT; + + let (c, backend) = substrate_test_runtime_client::new_light(); + let client = Arc::new(c); + let ( + block_import, + justification_import, + finality_proof_import, + finality_proof_request_builder, + data, + ) = self.make_block_import(PeersClient::Light(client.clone(), backend.clone())); + + let verifier = self.make_verifier( + PeersClient::Light(client.clone(), backend.clone()), + &config, + &data, + ); + let verifier = VerifierAdapter(Arc::new(Mutex::new(Box::new(verifier) as Box<_>))); + + let import_queue = Box::new(BasicQueue::new( + verifier.clone(), + Box::new(block_import.clone()), + justification_import, + finality_proof_import, + )); + + let listen_addr = build_multiaddr![Memory(rand::random::())]; + + let network = NetworkWorker::new(sc_network::config::Params { + roles: config.roles, + network_config: NetworkConfiguration { + listen_addresses: vec![listen_addr.clone()], + transport: TransportConfig::MemoryOnly, + ..NetworkConfiguration::default() + }, + chain: client.clone(), + finality_proof_provider: self.make_finality_proof_provider( + PeersClient::Light(client.clone(), backend.clone()) + ), + finality_proof_request_builder, + on_demand: None, + transaction_pool: Arc::new(EmptyTransactionPool), + protocol_id: ProtocolId::from(&b"test-protocol-name"[..]), + import_queue, + specialization: self::SpecializationFactory::create(), + block_announce_validator: Box::new(DefaultBlockAnnounceValidator::new(client.clone())) + }).unwrap(); + + self.mut_peers(|peers| { + for peer in peers.iter_mut() { + peer.network.add_known_address(network.service().local_peer_id(), listen_addr.clone()); + } + + let imported_blocks_stream = Box::new(client.import_notification_stream() + .map(|v| Ok::<_, ()>(v)).compat().fuse()); + let finality_notification_stream = Box::new(client.finality_notification_stream() + .map(|v| Ok::<_, ()>(v)).compat().fuse()); + + peers.push(Peer { + data, + verifier, + select_chain: None, + backend: None, + block_import, + client: PeersClient::Light(client, backend), + imported_blocks_stream, + finality_notification_stream, + network, + }); + }); + } + + /// Polls the testnet until all nodes are in sync. + /// + /// Must be executed in a task context. + fn poll_until_sync(&mut self) -> Async<()> { + self.poll(); + + // Return `NotReady` if there's a mismatch in the highest block number. + let mut highest = None; + for peer in self.peers().iter() { + if peer.is_major_syncing() || peer.network.num_queued_blocks() != 0 { + return Async::NotReady + } + if peer.network.num_sync_requests() != 0 { + return Async::NotReady + } + match (highest, peer.client.info().best_hash) { + (None, b) => highest = Some(b), + (Some(ref a), ref b) if a == b => {}, + (Some(_), _) => return Async::NotReady, + } + } + Async::Ready(()) + } + + /// Blocks the current thread until we are sync'ed. + /// + /// Calls `poll_until_sync` repeatidely with the runtime passed as parameter. + fn block_until_sync(&mut self, runtime: &mut tokio::runtime::current_thread::Runtime) { + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| Ok(self.poll_until_sync()))).unwrap(); + } + + /// Polls the testnet. Processes all the pending actions and returns `NotReady`. + fn poll(&mut self) { + self.mut_peers(|peers| { + for peer in peers { + trace!(target: "sync", "-- Polling {}", peer.id()); + futures03::future::poll_fn(|cx| Pin::new(&mut peer.network).poll(cx)) + .map(|item| Ok::<_, ()>(item)) + .compat().poll().unwrap(); + trace!(target: "sync", "-- Polling complete {}", peer.id()); + + // We poll `imported_blocks_stream`. + while let Ok(Async::Ready(Some(notification))) = peer.imported_blocks_stream.poll() { + peer.network.on_block_imported( + notification.hash, + notification.header, + Vec::new(), + true, + ); + } + + // We poll `finality_notification_stream`, but we only take the last event. + let mut last = None; + while let Ok(Async::Ready(Some(item))) = peer.finality_notification_stream.poll() { + last = Some(item); + } + if let Some(notification) = last { + peer.network.on_block_finalized(notification.hash, notification.header); + } + } + }); + } +} + +pub struct TestNet { + peers: Vec>, +} + +impl TestNetFactory for TestNet { + type Specialization = DummySpecialization; + type Verifier = PassThroughVerifier; + type PeerData = (); + + /// Create new test network with peers and given config. + fn from_config(_config: &ProtocolConfig) -> Self { + TestNet { + peers: Vec::new(), + } + } + + fn make_verifier(&self, _client: PeersClient, _config: &ProtocolConfig, _peer_data: &()) + -> Self::Verifier + { + PassThroughVerifier(false) + } + + fn peer(&mut self, i: usize) -> &mut Peer<(), Self::Specialization> { + &mut self.peers[i] + } + + fn peers(&self) -> &Vec> { + &self.peers + } + + fn mut_peers>)>(&mut self, closure: F) { + closure(&mut self.peers); + } +} + +pub struct ForceFinalized(PeersClient); + +impl JustificationImport for ForceFinalized { + type Error = ConsensusError; + + fn import_justification( + &mut self, + hash: H256, + _number: NumberFor, + justification: Justification, + ) -> Result<(), Self::Error> { + self.0.finalize_block(BlockId::Hash(hash), Some(justification), true) + .map_err(|_| ConsensusError::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: PeersClient, config: &ProtocolConfig, peer_data: &()) -> Self::Verifier { + self.0.make_verifier(client, config, peer_data) + } + + fn peer(&mut self, i: usize) -> &mut 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 make_block_import(&self, client: PeersClient) + -> ( + BlockImportAdapter, + Option>, + Option>, + Option>, + Self::PeerData, + ) + { + ( + client.as_block_import(), + Some(Box::new(ForceFinalized(client))), + None, + None, + Default::default(), + ) + } +} diff --git a/client/network/test/src/sync.rs b/client/network/test/src/sync.rs new file mode 100644 index 0000000000000..d738eb3d6c3ed --- /dev/null +++ b/client/network/test/src/sync.rs @@ -0,0 +1,662 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sc_network::config::Roles; +use sp_consensus::BlockOrigin; +use futures03::TryFutureExt as _; +use std::time::Duration; +use tokio::runtime::current_thread; +use super::*; + +fn test_ancestor_search_when_common_is(n: usize) { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + 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.block_until_sync(&mut runtime); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); +} + +#[test] +fn sync_peers_works() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(3); + + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + for peer in 0..3 { + if net.peer(peer).num_peers() != 2 { + return Ok(Async::NotReady) + } + } + Ok(Async::Ready(())) + })).unwrap(); +} + +#[test] +fn sync_cycle_from_offline_to_syncing_to_offline() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + 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); + + // Block until all nodes are online and nodes 0 and 1 and major syncing. + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + for peer in 0..3 { + // Online + if net.peer(peer).is_offline() { + return Ok(Async::NotReady) + } + if peer < 2 { + // Major syncing. + if !net.peer(peer).is_major_syncing() { + return Ok(Async::NotReady) + } + } + } + Ok(Async::Ready(())) + })).unwrap(); + + // Block until all nodes are done syncing. + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + for peer in 0..3 { + if net.peer(peer).is_major_syncing() { + return Ok(Async::NotReady) + } + } + Ok(Async::Ready(())) + })).unwrap(); + + // Now drop nodes 1 and 2, and check that node 0 is offline. + net.peers.remove(2); + net.peers.remove(1); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if !net.peer(0).is_offline() { + Ok(Async::NotReady) + } else { + Ok(Async::Ready(())) + } + })).unwrap(); +} + +#[test] +fn syncing_node_not_major_syncing_when_disconnected() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(3); + + // Generate blocks. + net.peer(2).push_blocks(100, false); + + // Check that we're not major syncing when disconnected. + assert!(!net.peer(1).is_major_syncing()); + + // Check that we switch to major syncing. + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if !net.peer(1).is_major_syncing() { + Ok(Async::NotReady) + } else { + Ok(Async::Ready(())) + } + })).unwrap(); + + // Destroy two nodes, and check that we switch to non-major syncing. + net.peers.remove(2); + net.peers.remove(0); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if net.peer(0).is_major_syncing() { + Ok(Async::NotReady) + } else { + Ok(Async::Ready(())) + } + })).unwrap(); +} + +#[test] +fn sync_from_two_peers_works() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(3); + net.peer(1).push_blocks(100, false); + net.peer(2).push_blocks(100, false); + net.block_until_sync(&mut runtime); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); + assert!(!net.peer(0).is_major_syncing()); +} + +#[test] +fn sync_from_two_peers_with_ancestry_search_works() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + 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.block_until_sync(&mut runtime); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); +} + +#[test] +fn ancestry_search_works_when_backoff_is_one() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + 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.block_until_sync(&mut runtime); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); +} + +#[test] +fn ancestry_search_works_when_ancestor_is_genesis() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + 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.block_until_sync(&mut runtime); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); +} + +#[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 _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(2); + net.peer(1).push_blocks(500, false); + net.block_until_sync(&mut runtime); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); +} + +#[test] +fn sync_no_common_longer_chain_fails() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(3); + net.peer(0).push_blocks(20, true); + net.peer(1).push_blocks(20, false); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if net.peer(0).is_major_syncing() { + Ok(Async::NotReady) + } else { + Ok(Async::Ready(())) + } + })).unwrap(); + let peer1 = &net.peers()[1]; + assert!(!net.peers()[0].blockchain_canon_equals(peer1)); +} + +#[test] +fn sync_justifications() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = JustificationTestNet::new(3); + net.peer(0).push_blocks(20, false); + net.block_until_sync(&mut runtime); + + // 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); + + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { + net.poll(); + + for height in (10..21).step_by(5) { + if net.peer(0).client().justification(&BlockId::Number(height)).unwrap() != Some(Vec::new()) { + return Ok(Async::NotReady); + } + if net.peer(1).client().justification(&BlockId::Number(height)).unwrap() != Some(Vec::new()) { + return Ok(Async::NotReady); + } + } + + Ok(Async::Ready(())) + })).unwrap(); +} + +#[test] +fn sync_justifications_across_forks() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + 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.block_until_sync(&mut runtime); + + 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); + + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { + net.poll(); + + if net.peer(0).client().justification(&BlockId::Number(10)).unwrap() == Some(Vec::new()) && + net.peer(1).client().justification(&BlockId::Number(10)).unwrap() == Some(Vec::new()) + { + Ok(Async::Ready(())) + } else { + Ok(Async::NotReady) + } + })).unwrap(); +} + +#[test] +fn sync_after_fork_works() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(3); + net.peer(0).push_blocks(30, false); + net.peer(1).push_blocks(30, false); + net.peer(2).push_blocks(30, false); + + net.peer(0).push_blocks(10, true); + net.peer(1).push_blocks(20, false); + net.peer(2).push_blocks(20, false); + + net.peer(1).push_blocks(10, true); + net.peer(2).push_blocks(1, false); + + // peer 1 has the best chain + net.block_until_sync(&mut runtime); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); + (net.peers()[1].blockchain_canon_equals(peer1)); + (net.peers()[2].blockchain_canon_equals(peer1)); +} + +#[test] +fn syncs_all_forks() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(4); + 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.block_until_sync(&mut runtime); + // Check that all peers have all of the blocks. + assert_eq!(9, net.peer(0).blocks_count()); + assert_eq!(9, net.peer(1).blocks_count()); +} + +#[test] +fn own_blocks_are_announced() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(3); + net.block_until_sync(&mut runtime); // connect'em + net.peer(0).generate_blocks(1, BlockOrigin::Own, |builder| builder.build().unwrap().block); + + net.block_until_sync(&mut runtime); + + assert_eq!(net.peer(0).client.info().best_number, 1); + assert_eq!(net.peer(1).client.info().best_number, 1); + let peer0 = &net.peers()[0]; + assert!(net.peers()[1].blockchain_canon_equals(peer0)); + (net.peers()[2].blockchain_canon_equals(peer0)); +} + +#[test] +fn blocks_are_not_announced_by_light_nodes() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(0); + + // full peer0 is connected to light peer + // light peer1 is connected to full peer2 + let mut light_config = ProtocolConfig::default(); + light_config.roles = Roles::LIGHT; + net.add_full_peer(&ProtocolConfig::default()); + net.add_light_peer(&light_config); + + // Sync between 0 and 1. + net.peer(0).push_blocks(1, false); + assert_eq!(net.peer(0).client.info().best_number, 1); + net.block_until_sync(&mut runtime); + assert_eq!(net.peer(1).client.info().best_number, 1); + + // Add another node and remove node 0. + net.add_full_peer(&ProtocolConfig::default()); + net.peers.remove(0); + + // Poll for a few seconds and make sure 1 and 2 (now 0 and 1) don't sync together. + let mut delay = futures_timer::Delay::new(Duration::from_secs(5)).compat(); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { + net.poll(); + delay.poll().map_err(|_| ()) + })).unwrap(); + assert_eq!(net.peer(1).client.info().best_number, 0); +} + +#[test] +fn can_sync_small_non_best_forks() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(2); + net.peer(0).push_blocks(30, false); + net.peer(1).push_blocks(30, false); + + // small fork + reorg on peer 1. + net.peer(0).push_blocks_at(BlockId::Number(30), 2, true); + let small_hash = net.peer(0).client().info().best_hash; + net.peer(0).push_blocks_at(BlockId::Number(30), 10, false); + assert_eq!(net.peer(0).client().info().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().best_number, 40); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + assert!(net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none()); + + // poll until the two nodes connect, otherwise announcing the block will not work + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if net.peer(0).num_peers() == 0 { + Ok(Async::NotReady) + } else { + Ok(Async::Ready(())) + } + })).unwrap(); + + // synchronization: 0 synced to longer chain and 1 didn't sync to small chain. + + assert_eq!(net.peer(0).client().info().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, Vec::new()); + + // after announcing, peer 1 downloads the block. + + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + if net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none() { + return Ok(Async::NotReady) + } + Ok(Async::Ready(())) + })).unwrap(); + net.block_until_sync(&mut runtime); + + let another_fork = net.peer(0).push_blocks_at(BlockId::Number(35), 2, true); + net.peer(0).announce_block(another_fork, Vec::new()); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if net.peer(1).client().header(&BlockId::Hash(another_fork)).unwrap().is_none() { + return Ok(Async::NotReady) + } + Ok(Async::Ready(())) + })).unwrap(); +} + +#[test] +fn can_not_sync_from_light_peer() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + + // given the network with 1 full nodes (#0) and 1 light node (#1) + let mut net = TestNet::new(1); + net.add_light_peer(&Default::default()); + + // generate some blocks on #0 + net.peer(0).push_blocks(1, false); + + // and let the light client sync from this node + net.block_until_sync(&mut runtime); + + // ensure #0 && #1 have the same best block + let full0_info = net.peer(0).client.info(); + let light_info = net.peer(1).client.info(); + assert_eq!(full0_info.best_number, 1); + assert_eq!(light_info.best_number, 1); + assert_eq!(light_info.best_hash, full0_info.best_hash); + + // add new full client (#2) && remove #0 + net.add_full_peer(&Default::default()); + net.peers.remove(0); + + // ensure that the #2 (now #1) fails to sync block #1 even after 5 seconds + let mut test_finished = futures_timer::Delay::new(Duration::from_secs(5)).compat(); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + test_finished.poll().map_err(|_| ()) + })).unwrap(); +} + +#[test] +fn light_peer_imports_header_from_announce() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + + fn import_with_announce(net: &mut TestNet, runtime: &mut current_thread::Runtime, hash: H256) { + net.peer(0).announce_block(hash, Vec::new()); + + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { + net.poll(); + if net.peer(1).client().header(&BlockId::Hash(hash)).unwrap().is_some() { + Ok(Async::Ready(())) + } else { + Ok(Async::NotReady) + } + })).unwrap(); + } + + // given the network with 1 full nodes (#0) and 1 light node (#1) + let mut net = TestNet::new(1); + net.add_light_peer(&Default::default()); + + // let them connect to each other + net.block_until_sync(&mut runtime); + + // check that NEW block is imported from announce message + let new_hash = net.peer(0).push_blocks(1, false); + import_with_announce(&mut net, &mut runtime, new_hash); + + // check that KNOWN STALE block is imported from announce message + let known_stale_hash = net.peer(0).push_blocks_at(BlockId::Number(0), 1, true); + import_with_announce(&mut net, &mut runtime, known_stale_hash); +} + +#[test] +fn can_sync_explicit_forks() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(2); + net.peer(0).push_blocks(30, false); + net.peer(1).push_blocks(30, false); + + // small fork + reorg on peer 1. + net.peer(0).push_blocks_at(BlockId::Number(30), 2, true); + let small_hash = net.peer(0).client().info().best_hash; + let small_number = net.peer(0).client().info().best_number; + net.peer(0).push_blocks_at(BlockId::Number(30), 10, false); + assert_eq!(net.peer(0).client().info().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().best_number, 40); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + assert!(net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none()); + + // poll until the two nodes connect, otherwise announcing the block will not work + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if net.peer(0).num_peers() == 0 || net.peer(1).num_peers() == 0 { + Ok(Async::NotReady) + } else { + Ok(Async::Ready(())) + } + })).unwrap(); + + // synchronization: 0 synced to longer chain and 1 didn't sync to small chain. + + assert_eq!(net.peer(0).client().info().best_number, 40); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + assert!(!net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + + // request explicit sync + let first_peer_id = net.peer(0).id(); + net.peer(1).set_sync_fork_request(vec![first_peer_id], small_hash, small_number); + + // peer 1 downloads the block. + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + if net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none() { + return Ok(Async::NotReady) + } + Ok(Async::Ready(())) + })).unwrap(); +} + +#[test] +fn syncs_header_only_forks() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(0); + let config = ProtocolConfig::default(); + net.add_full_peer_with_states(&config, None); + net.add_full_peer_with_states(&config, Some(3)); + net.peer(0).push_blocks(2, false); + net.peer(1).push_blocks(2, false); + + net.peer(0).push_blocks(2, true); + let small_hash = net.peer(0).client().info().best_hash; + let small_number = net.peer(0).client().info().best_number; + net.peer(1).push_blocks(4, false); + + net.block_until_sync(&mut runtime); + // Peer 1 will sync the small fork even though common block state is missing + assert_eq!(9, net.peer(0).blocks_count()); + assert_eq!(9, net.peer(1).blocks_count()); + + // Request explicit header-only sync request for the ancient fork. + let first_peer_id = net.peer(0).id(); + net.peer(1).set_sync_fork_request(vec![first_peer_id], small_hash, small_number); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none() { + return Ok(Async::NotReady) + } + Ok(Async::Ready(())) + })).unwrap(); +} + +#[test] +fn does_not_sync_announced_old_best_block() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(3); + + let old_hash = net.peer(0).push_blocks(1, false); + let old_hash_with_parent = net.peer(0).push_blocks(1, false); + net.peer(0).push_blocks(18, true); + net.peer(1).push_blocks(20, true); + + net.peer(0).announce_block(old_hash, Vec::new()); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + // poll once to import announcement + net.poll(); + Ok(Async::Ready(())) + })).unwrap(); + assert!(!net.peer(1).is_major_syncing()); + + net.peer(0).announce_block(old_hash_with_parent, Vec::new()); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + // poll once to import announcement + net.poll(); + Ok(Async::Ready(())) + })).unwrap(); + assert!(!net.peer(1).is_major_syncing()); +} diff --git a/client/offchain/Cargo.toml b/client/offchain/Cargo.toml new file mode 100644 index 0000000000000..8048d10dc34fc --- /dev/null +++ b/client/offchain/Cargo.toml @@ -0,0 +1,42 @@ +[package] +description = "Substrate offchain workers" +name = "sc-offchain" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +bytes = "0.4.12" +sc-client-api = { version = "2.0.0", path = "../api" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } +fnv = "1.0.6" +futures01 = { package = "futures", version = "0.1" } +futures = "0.3.1" +futures-timer = "2.0" +log = "0.4.8" +threadpool = "1.7" +num_cpus = "1.10" +sp-offchain = { version = "2.0.0", path = "../../primitives/offchain" } +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } +parking_lot = "0.9.0" +sp-core = { version = "2.0.0", path = "../../primitives/core" } +rand = "0.7.2" +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sc-network = { version = "0.8", path = "../network" } +sc-keystore = { version = "2.0.0", path = "../keystore" } + +[target.'cfg(not(target_os = "unknown"))'.dependencies] +hyper = "0.12.35" +hyper-rustls = "0.17.1" + +[dev-dependencies] +sc-client-db = { version = "2.0.0", default-features = true, path = "../db/" } +env_logger = "0.7.0" +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } +tokio = "0.1.22" +sc-transaction-pool = { version = "2.0.0", path = "../../client/transaction-pool" } +sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } + +[features] +default = [] diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs new file mode 100644 index 0000000000000..45a82d230c11a --- /dev/null +++ b/client/offchain/src/api.rs @@ -0,0 +1,420 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{ + str::FromStr, + sync::Arc, + convert::TryFrom, + thread::sleep, +}; + +use sp_core::offchain::OffchainStorage; +use futures::Future; +use log::error; +use sc_network::{PeerId, Multiaddr, NetworkStateInfo}; +use codec::{Encode, Decode}; +use sp_core::offchain::{ + Externalities as OffchainExt, HttpRequestId, Timestamp, HttpRequestStatus, HttpError, + OpaqueNetworkState, OpaquePeerId, OpaqueMultiaddr, StorageKind, +}; +pub use sp_offchain::STORAGE_PREFIX; + +#[cfg(not(target_os = "unknown"))] +mod http; + +#[cfg(target_os = "unknown")] +use http_dummy as http; +#[cfg(target_os = "unknown")] +mod http_dummy; + +mod timestamp; + +/// Asynchronous offchain API. +/// +/// NOTE this is done to prevent recursive calls into the runtime (which are not supported currently). +pub(crate) struct Api { + /// Offchain Workers database. + db: Storage, + /// A NetworkState provider. + network_state: Arc, + /// Is this node a potential validator? + is_validator: bool, + /// Everything HTTP-related is handled by a different struct. + http: http::HttpApi, +} + +fn unavailable_yet(name: &str) -> R { + error!( + "The {:?} API is not available for offchain workers yet. Follow \ + https://github.com/paritytech/substrate/issues/1458 for details", name + ); + Default::default() +} + +const LOCAL_DB: &str = "LOCAL (fork-aware) DB"; + +impl OffchainExt for Api { + fn is_validator(&self) -> bool { + self.is_validator + } + + fn network_state(&self) -> Result { + let external_addresses = self.network_state.external_addresses(); + + let state = NetworkState::new( + self.network_state.local_peer_id(), + external_addresses, + ); + Ok(OpaqueNetworkState::from(state)) + } + + fn timestamp(&mut self) -> Timestamp { + timestamp::now() + } + + fn sleep_until(&mut self, deadline: Timestamp) { + sleep(timestamp::timestamp_from_now(deadline)); + } + + fn random_seed(&mut self) -> [u8; 32] { + rand::random() + } + + fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { + match kind { + StorageKind::PERSISTENT => self.db.set(STORAGE_PREFIX, key, value), + StorageKind::LOCAL => unavailable_yet(LOCAL_DB), + } + } + + fn local_storage_compare_and_set( + &mut self, + kind: StorageKind, + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool { + match kind { + StorageKind::PERSISTENT => { + self.db.compare_and_set(STORAGE_PREFIX, key, old_value, new_value) + }, + StorageKind::LOCAL => unavailable_yet(LOCAL_DB), + } + } + + fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { + match kind { + StorageKind::PERSISTENT => self.db.get(STORAGE_PREFIX, key), + StorageKind::LOCAL => unavailable_yet(LOCAL_DB), + } + } + + fn http_request_start( + &mut self, + method: &str, + uri: &str, + _meta: &[u8] + ) -> Result { + self.http.request_start(method, uri) + } + + fn http_request_add_header( + &mut self, + request_id: HttpRequestId, + name: &str, + value: &str + ) -> Result<(), ()> { + self.http.request_add_header(request_id, name, value) + } + + fn http_request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option + ) -> Result<(), HttpError> { + self.http.request_write_body(request_id, chunk, deadline) + } + + fn http_response_wait( + &mut self, + ids: &[HttpRequestId], + deadline: Option + ) -> Vec { + self.http.response_wait(ids, deadline) + } + + fn http_response_headers( + &mut self, + request_id: HttpRequestId + ) -> Vec<(Vec, Vec)> { + self.http.response_headers(request_id) + } + + fn http_response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option + ) -> Result { + self.http.response_read_body(request_id, buffer, deadline) + } +} + +/// Information about the local node's network state. +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct NetworkState { + peer_id: PeerId, + external_addresses: Vec, +} + +impl NetworkState { + fn new(peer_id: PeerId, external_addresses: Vec) -> Self { + NetworkState { + peer_id, + external_addresses, + } + } +} + +impl From for OpaqueNetworkState { + fn from(state: NetworkState) -> OpaqueNetworkState { + let enc = Encode::encode(&state.peer_id.into_bytes()); + let peer_id = OpaquePeerId::new(enc); + + let external_addresses: Vec = state + .external_addresses + .iter() + .map(|multiaddr| { + let e = Encode::encode(&multiaddr.to_string()); + OpaqueMultiaddr::new(e) + }) + .collect(); + + OpaqueNetworkState { + peer_id, + external_addresses, + } + } +} + +impl TryFrom for NetworkState { + type Error = (); + + fn try_from(state: OpaqueNetworkState) -> Result { + let inner_vec = state.peer_id.0; + + let bytes: Vec = Decode::decode(&mut &inner_vec[..]).map_err(|_| ())?; + let peer_id = PeerId::from_bytes(bytes).map_err(|_| ())?; + + let external_addresses: Result, Self::Error> = state.external_addresses + .iter() + .map(|enc_multiaddr| -> Result { + let inner_vec = &enc_multiaddr.0; + let bytes = >::decode(&mut &inner_vec[..]).map_err(|_| ())?; + let multiaddr_str = String::from_utf8(bytes).map_err(|_| ())?; + let multiaddr = Multiaddr::from_str(&multiaddr_str).map_err(|_| ())?; + Ok(multiaddr) + }) + .collect(); + let external_addresses = external_addresses?; + + Ok(NetworkState { + peer_id, + external_addresses, + }) + } +} + +/// Offchain extensions implementation API +/// +/// This is the asynchronous processing part of the API. +pub(crate) struct AsyncApi { + /// Everything HTTP-related is handled by a different struct. + http: Option, +} + +impl AsyncApi { + /// Creates new Offchain extensions API implementation an the asynchronous processing part. + pub fn new( + db: S, + network_state: Arc, + is_validator: bool, + ) -> (Api, AsyncApi) { + let (http_api, http_worker) = http::http(); + + let api = Api { + db, + network_state, + is_validator, + http: http_api, + }; + + let async_api = AsyncApi { + http: Some(http_worker), + }; + + (api, async_api) + } + + /// Run a processing task for the API + pub fn process(mut self) -> impl Future { + let http = self.http.take().expect("Take invoked only once."); + + http + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::{convert::{TryFrom, TryInto}, time::SystemTime}; + use sc_client_db::offchain::LocalStorage; + use sc_network::PeerId; + + struct MockNetworkStateInfo(); + + impl NetworkStateInfo for MockNetworkStateInfo { + fn external_addresses(&self) -> Vec { + Vec::new() + } + + fn local_peer_id(&self) -> PeerId { + PeerId::random() + } + } + + fn offchain_api() -> (Api, AsyncApi) { + let _ = env_logger::try_init(); + let db = LocalStorage::new_test(); + let mock = Arc::new(MockNetworkStateInfo()); + + AsyncApi::new( + db, + mock, + false, + ) + } + + #[test] + fn should_get_timestamp() { + let mut api = offchain_api().0; + + // Get timestamp from std. + let now = SystemTime::now(); + let d: u64 = now.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis().try_into().unwrap(); + + // Get timestamp from offchain api. + let timestamp = api.timestamp(); + + // Compare. + assert!(timestamp.unix_millis() > 0); + assert_eq!(timestamp.unix_millis(), d); + } + + #[test] + fn should_sleep() { + let mut api = offchain_api().0; + + // Arrange. + let now = api.timestamp(); + let delta = sp_core::offchain::Duration::from_millis(100); + let deadline = now.add(delta); + + // Act. + api.sleep_until(deadline); + let new_now = api.timestamp(); + + // Assert. + // The diff could be more than the sleep duration. + assert!(new_now.unix_millis() - 100 >= now.unix_millis()); + } + + #[test] + fn should_set_and_get_local_storage() { + // given + let kind = StorageKind::PERSISTENT; + let mut api = offchain_api().0; + let key = b"test"; + + // when + assert_eq!(api.local_storage_get(kind, key), None); + api.local_storage_set(kind, key, b"value"); + + // then + assert_eq!(api.local_storage_get(kind, key), Some(b"value".to_vec())); + } + + #[test] + fn should_compare_and_set_local_storage() { + // given + let kind = StorageKind::PERSISTENT; + let mut api = offchain_api().0; + let key = b"test"; + api.local_storage_set(kind, key, b"value"); + + // when + assert_eq!(api.local_storage_compare_and_set(kind, key, Some(b"val"), b"xxx"), false); + assert_eq!(api.local_storage_get(kind, key), Some(b"value".to_vec())); + + // when + assert_eq!(api.local_storage_compare_and_set(kind, key, Some(b"value"), b"xxx"), true); + assert_eq!(api.local_storage_get(kind, key), Some(b"xxx".to_vec())); + } + + #[test] + fn should_compare_and_set_local_storage_with_none() { + // given + let kind = StorageKind::PERSISTENT; + let mut api = offchain_api().0; + let key = b"test"; + + // when + let res = api.local_storage_compare_and_set(kind, key, None, b"value"); + + // then + assert_eq!(res, true); + assert_eq!(api.local_storage_get(kind, key), Some(b"value".to_vec())); + } + + #[test] + fn should_convert_network_states() { + // given + let state = NetworkState::new( + PeerId::random(), + vec![ + Multiaddr::try_from("/ip4/127.0.0.1/tcp/1234".to_string()).unwrap(), + Multiaddr::try_from("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21").unwrap(), + ], + ); + + // when + let opaque_state = OpaqueNetworkState::from(state.clone()); + let converted_back_state = NetworkState::try_from(opaque_state).unwrap(); + + // then + assert_eq!(state, converted_back_state); + } + + #[test] + fn should_get_random_seed() { + // given + let mut api = offchain_api().0; + let seed = api.random_seed(); + // then + assert_ne!(seed, [0; 32]); + } +} diff --git a/client/offchain/src/api/http.rs b/client/offchain/src/api/http.rs new file mode 100644 index 0000000000000..84c3ecd69b37f --- /dev/null +++ b/client/offchain/src/api/http.rs @@ -0,0 +1,975 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This module is composed of two structs: [`HttpApi`] and [`HttpWorker`]. Calling the [`http`] +//! function returns a pair of [`HttpApi`] and [`HttpWorker`] that share some state. +//! +//! The [`HttpApi`] is (indirectly) passed to the runtime when calling an offchain worker, while +//! the [`HttpWorker`] must be processed in the background. The [`HttpApi`] mimicks the API of the +//! HTTP-related methods available to offchain workers. +//! +//! The reason for this design is driven by the fact that HTTP requests should continue running +//! (i.e.: the socket should continue being processed) in the background even if the runtime isn't +//! actively calling any function. + +use crate::api::timestamp; +use bytes::Buf as _; +use fnv::FnvHashMap; +use futures::{prelude::*, channel::mpsc, compat::Compat01As03}; +use log::error; +use sp_core::offchain::{HttpRequestId, Timestamp, HttpRequestStatus, HttpError}; +use std::{fmt, io::Read as _, mem, pin::Pin, task::Context, task::Poll}; + +/// Creates a pair of [`HttpApi`] and [`HttpWorker`]. +pub fn http() -> (HttpApi, HttpWorker) { + let (to_worker, from_api) = mpsc::unbounded(); + let (to_api, from_worker) = mpsc::unbounded(); + + let api = HttpApi { + to_worker, + from_worker: from_worker.fuse(), + // We start with a random ID for the first HTTP request, to prevent mischievous people from + // writing runtime code with hardcoded IDs. + next_id: HttpRequestId(rand::random::() % 2000), + requests: FnvHashMap::default(), + }; + + let engine = HttpWorker { + to_api, + from_api, + http_client: hyper::Client::builder().build(hyper_rustls::HttpsConnector::new(1)), + requests: Vec::new(), + }; + + (api, engine) +} + +/// Provides HTTP capabilities. +/// +/// Since this struct is a helper for offchain workers, its API is mimicking the API provided +/// to offchain workers. +pub struct HttpApi { + /// Used to sends messages to the worker. + to_worker: mpsc::UnboundedSender, + /// Used to receive messages from the worker. + /// We use a `Fuse` in order to have an extra protection against panicking. + from_worker: stream::Fuse>, + /// Id to assign to the next HTTP request that is started. + next_id: HttpRequestId, + /// List of HTTP requests in preparation or in progress. + requests: FnvHashMap, +} + +/// One active request within `HttpApi`. +enum HttpApiRequest { + /// The request object is being constructed locally and not started yet. + NotDispatched(hyper::Request, hyper::body::Sender), + /// The request has been dispatched and we're in the process of sending out the body (if the + /// field is `Some`) or waiting for a response (if the field is `None`). + Dispatched(Option), + /// Received a response. + Response(HttpApiRequestRp), + /// A request has been dispatched but the worker notified us of an error. We report this + /// failure to the user as an `IoError` and remove the request from the list as soon as + /// possible. + Fail(hyper::Error), +} + +/// A request within `HttpApi` that has received a response. +struct HttpApiRequestRp { + /// We might still be writing the request's body when the response comes. + /// This field allows to continue writing that body. + sending_body: Option, + /// Status code of the response. + status_code: hyper::StatusCode, + /// Headers of the response. + headers: hyper::HeaderMap, + /// Body of the response, as a channel of `Chunk` objects. + /// While the code is designed to drop the `Receiver` once it ends, we wrap it within a + /// `Fuse` in order to be extra precautious about panics. + /// Elements extracted from the channel are first put into `current_read_chunk`. + /// If the channel produces an error, then that is translated into an `IoError` and the request + /// is removed from the list. + body: stream::Fuse>>, + /// Chunk that has been extracted from the channel and that is currently being read. + /// Reading data from the response should read from this field in priority. + current_read_chunk: Option>, +} + +impl HttpApi { + /// Mimicks the corresponding method in the offchain API. + pub fn request_start( + &mut self, + method: &str, + uri: &str + ) -> Result { + // Start by building the prototype of the request. + // We do this first so that we don't touch anything in `self` if building the prototype + // fails. + let (body_sender, body) = hyper::Body::channel(); + let mut request = hyper::Request::new(body); + *request.method_mut() = hyper::Method::from_bytes(method.as_bytes()).map_err(|_| ())?; + *request.uri_mut() = hyper::Uri::from_shared(From::from(uri)).map_err(|_| ())?; + + let new_id = self.next_id; + debug_assert!(!self.requests.contains_key(&new_id)); + match self.next_id.0.checked_add(1) { + Some(new_id) => self.next_id.0 = new_id, + None => { + error!("Overflow in offchain worker HTTP request ID assignment"); + return Err(()); + } + }; + self.requests.insert(new_id, HttpApiRequest::NotDispatched(request, body_sender)); + + Ok(new_id) + } + + /// Mimicks the corresponding method in the offchain API. + pub fn request_add_header( + &mut self, + request_id: HttpRequestId, + name: &str, + value: &str + ) -> Result<(), ()> { + let request = match self.requests.get_mut(&request_id) { + Some(&mut HttpApiRequest::NotDispatched(ref mut rq, _)) => rq, + _ => return Err(()) + }; + + let name = hyper::header::HeaderName::from_bytes(name.as_bytes()).map_err(|_| ())?; + let value = hyper::header::HeaderValue::from_str(value).map_err(|_| ())?; + // Note that we're always appending headers and never replacing old values. + // We assume here that the user knows what they're doing. + request.headers_mut().append(name, value); + Ok(()) + } + + /// Mimicks the corresponding method in the offchain API. + pub fn request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option + ) -> Result<(), HttpError> { + // Extract the request from the list. + // Don't forget to add it back if necessary when returning. + let mut request = match self.requests.remove(&request_id) { + None => return Err(HttpError::Invalid), + Some(r) => r, + }; + + let mut deadline = timestamp::deadline_to_future(deadline); + // Closure that writes data to a sender, taking the deadline into account. Can return `Ok` + // (if the body has been written), or `DeadlineReached`, or `IoError`. + // If `IoError` is returned, don't forget to remove the request from the list. + let mut poll_sender = move |sender: &mut hyper::body::Sender| -> Result<(), HttpError> { + let mut when_ready = future::maybe_done(Compat01As03::new( + futures01::future::poll_fn(|| sender.poll_ready()) + )); + futures::executor::block_on(future::select(&mut when_ready, &mut deadline)); + match when_ready { + future::MaybeDone::Done(Ok(())) => {} + future::MaybeDone::Done(Err(_)) => return Err(HttpError::IoError), + future::MaybeDone::Future(_) | + future::MaybeDone::Gone => { + debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); + return Err(HttpError::DeadlineReached) + } + }; + + match sender.send_data(hyper::Chunk::from(chunk.to_owned())) { + Ok(()) => Ok(()), + Err(_chunk) => { + error!("HTTP sender refused data despite being ready"); + Err(HttpError::IoError) + }, + } + }; + + loop { + request = match request { + HttpApiRequest::NotDispatched(request, sender) => { + // If the request is not dispatched yet, dispatch it and loop again. + let _ = self.to_worker.unbounded_send(ApiToWorker::Dispatch { + id: request_id, + request + }); + HttpApiRequest::Dispatched(Some(sender)) + } + + HttpApiRequest::Dispatched(Some(mut sender)) => + if !chunk.is_empty() { + match poll_sender(&mut sender) { + Err(HttpError::IoError) => return Err(HttpError::IoError), + other => { + self.requests.insert( + request_id, + HttpApiRequest::Dispatched(Some(sender)) + ); + return other + } + } + } else { + // Writing an empty body is a hint that we should stop writing. Dropping + // the sender. + self.requests.insert(request_id, HttpApiRequest::Dispatched(None)); + return Ok(()) + } + + HttpApiRequest::Response(mut response @ HttpApiRequestRp { sending_body: Some(_), .. }) => + if !chunk.is_empty() { + match poll_sender(response.sending_body.as_mut() + .expect("Can only enter this match branch if Some; qed")) { + Err(HttpError::IoError) => return Err(HttpError::IoError), + other => { + self.requests.insert(request_id, HttpApiRequest::Response(response)); + return other + } + } + + } else { + // Writing an empty body is a hint that we should stop writing. Dropping + // the sender. + self.requests.insert(request_id, HttpApiRequest::Response(HttpApiRequestRp { + sending_body: None, + ..response + })); + return Ok(()) + } + + HttpApiRequest::Fail(_) => + // If the request has already failed, return without putting back the request + // in the list. + return Err(HttpError::IoError), + + v @ HttpApiRequest::Dispatched(None) | + v @ HttpApiRequest::Response(HttpApiRequestRp { sending_body: None, .. }) => { + // We have already finished sending this body. + self.requests.insert(request_id, v); + return Err(HttpError::Invalid) + } + } + } + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_wait( + &mut self, + ids: &[HttpRequestId], + deadline: Option + ) -> Vec { + // First of all, dispatch all the non-dispatched requests and drop all senders so that the + // user can't write anymore data. + for id in ids { + match self.requests.get_mut(id) { + Some(HttpApiRequest::NotDispatched(_, _)) => {} + Some(HttpApiRequest::Dispatched(sending_body)) | + Some(HttpApiRequest::Response(HttpApiRequestRp { sending_body, .. })) => { + let _ = sending_body.take(); + continue + } + _ => continue + }; + + let (request, _sender) = match self.requests.remove(id) { + Some(HttpApiRequest::NotDispatched(rq, s)) => (rq, s), + _ => unreachable!("we checked for NotDispatched above; qed") + }; + + let _ = self.to_worker.unbounded_send(ApiToWorker::Dispatch { + id: *id, + request + }); + + // We also destroy the sender in order to forbid writing more data. + self.requests.insert(*id, HttpApiRequest::Dispatched(None)); + } + + let mut deadline = timestamp::deadline_to_future(deadline); + + loop { + // Within that loop, first try to see if we have all the elements for a response. + // This includes the situation where the deadline is reached. + { + let mut output = Vec::with_capacity(ids.len()); + let mut must_wait_more = false; + for id in ids { + output.push(match self.requests.get_mut(id) { + None => HttpRequestStatus::Invalid, + Some(HttpApiRequest::NotDispatched(_, _)) => + unreachable!("we replaced all the NotDispatched with Dispatched earlier; qed"), + Some(HttpApiRequest::Dispatched(_)) => { + must_wait_more = true; + HttpRequestStatus::DeadlineReached + }, + Some(HttpApiRequest::Fail(_)) => HttpRequestStatus::IoError, + Some(HttpApiRequest::Response(HttpApiRequestRp { status_code, .. })) => + HttpRequestStatus::Finished(status_code.as_u16()), + }); + } + debug_assert_eq!(output.len(), ids.len()); + + // Are we ready to call `return`? + let is_done = if let future::MaybeDone::Done(_) = deadline { + true + } else if !must_wait_more { + true + } else { + false + }; + + if is_done { + // Requests in "fail" mode are purged before returning. + debug_assert_eq!(output.len(), ids.len()); + for n in (0..ids.len()).rev() { + if let HttpRequestStatus::IoError = output[n] { + self.requests.remove(&ids[n]); + } + } + return output + } + } + + // Grab next message from the worker. We call `continue` if deadline is reached so that + // we loop back and `return`. + let next_message = { + let mut next_msg = future::maybe_done(self.from_worker.next()); + futures::executor::block_on(future::select(&mut next_msg, &mut deadline)); + if let future::MaybeDone::Done(msg) = next_msg { + msg + } else { + debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); + continue + } + }; + + // Update internal state based on received message. + match next_message { + Some(WorkerToApi::Response { id, status_code, headers, body }) => + match self.requests.remove(&id) { + Some(HttpApiRequest::Dispatched(sending_body)) => { + self.requests.insert(id, HttpApiRequest::Response(HttpApiRequestRp { + sending_body, + status_code, + headers, + body: body.fuse(), + current_read_chunk: None, + })); + } + None => {} // can happen if we detected an IO error when sending the body + _ => error!("State mismatch between the API and worker"), + } + + Some(WorkerToApi::Fail { id, error }) => + match self.requests.remove(&id) { + Some(HttpApiRequest::Dispatched(_)) => { + self.requests.insert(id, HttpApiRequest::Fail(error)); + } + None => {} // can happen if we detected an IO error when sending the body + _ => error!("State mismatch between the API and worker"), + } + + None => { + error!("Worker has crashed"); + return ids.iter().map(|_| HttpRequestStatus::IoError).collect() + } + } + + } + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_headers( + &mut self, + request_id: HttpRequestId + ) -> Vec<(Vec, Vec)> { + // Do an implicit non-blocking wait on the request. + let _ = self.response_wait(&[request_id], Some(timestamp::now())); + + let headers = match self.requests.get(&request_id) { + Some(HttpApiRequest::Response(HttpApiRequestRp { headers, .. })) => headers, + _ => return Vec::new() + }; + + headers + .iter() + .map(|(name, value)| (name.as_str().as_bytes().to_owned(), value.as_bytes().to_owned())) + .collect() + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option + ) -> Result { + // Do an implicit wait on the request. + let _ = self.response_wait(&[request_id], deadline); + + // Remove the request from the list and handle situations where the request is invalid or + // in the wrong state. + let mut response = match self.requests.remove(&request_id) { + Some(HttpApiRequest::Response(r)) => r, + // Because we called `response_wait` above, we know that the deadline has been reached + // and we still haven't received a response. + Some(rq @ HttpApiRequest::Dispatched(_)) => { + self.requests.insert(request_id, rq); + return Err(HttpError::DeadlineReached) + }, + // The request has failed. + Some(HttpApiRequest::Fail { .. }) => + return Err(HttpError::IoError), + // Request hasn't been dispatched yet; reading the body is invalid. + Some(rq @ HttpApiRequest::NotDispatched(_, _)) => { + self.requests.insert(request_id, rq); + return Err(HttpError::Invalid) + } + None => return Err(HttpError::Invalid) + }; + + // Convert the deadline into a `Future` that resolves when the deadline is reached. + let mut deadline = timestamp::deadline_to_future(deadline); + + loop { + // First read from `current_read_chunk`. + if let Some(mut current_read_chunk) = response.current_read_chunk.take() { + match current_read_chunk.read(buffer) { + Ok(0) => {} + Ok(n) => { + self.requests.insert(request_id, HttpApiRequest::Response(HttpApiRequestRp { + current_read_chunk: Some(current_read_chunk), + .. response + })); + return Ok(n) + }, + Err(err) => { + // This code should never be reached unless there's a logic error somewhere. + error!("Failed to read from current read chunk: {:?}", err); + return Err(HttpError::IoError) + } + } + } + + // If we reach here, that means the `current_read_chunk` is empty and needs to be + // filled with a new chunk from `body`. We block on either the next body or the + // deadline. + let mut next_body = future::maybe_done(response.body.next()); + futures::executor::block_on(future::select(&mut next_body, &mut deadline)); + + if let future::MaybeDone::Done(next_body) = next_body { + match next_body { + Some(Ok(chunk)) => response.current_read_chunk = Some(chunk.reader()), + Some(Err(_)) => return Err(HttpError::IoError), + None => return Ok(0), // eof + } + } + + if let future::MaybeDone::Done(_) = deadline { + self.requests.insert(request_id, HttpApiRequest::Response(response)); + return Err(HttpError::DeadlineReached) + } + } + } +} + +impl fmt::Debug for HttpApi { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.requests.iter()) + .finish() + } +} + +impl fmt::Debug for HttpApiRequest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + HttpApiRequest::NotDispatched(_, _) => + f.debug_tuple("HttpApiRequest::NotDispatched").finish(), + HttpApiRequest::Dispatched(_) => + f.debug_tuple("HttpApiRequest::Dispatched").finish(), + HttpApiRequest::Response(HttpApiRequestRp { status_code, headers, .. }) => + f.debug_tuple("HttpApiRequest::Response").field(status_code).field(headers).finish(), + HttpApiRequest::Fail(err) => + f.debug_tuple("HttpApiRequest::Fail").field(err).finish(), + } + } +} + +/// Message send from the API to the worker. +enum ApiToWorker { + /// Dispatches a new HTTP request. + Dispatch { + /// ID to send back when the response comes back. + id: HttpRequestId, + /// Request to start executing. + request: hyper::Request, + } +} + +/// Message send from the API to the worker. +enum WorkerToApi { + /// A request has succeeded. + Response { + /// The ID that was passed to the worker. + id: HttpRequestId, + /// Status code of the response. + status_code: hyper::StatusCode, + /// Headers of the response. + headers: hyper::HeaderMap, + /// Body of the response, as a channel of `Chunk` objects. + /// We send the body back through a channel instead of returning the hyper `Body` object + /// because we don't want the `HttpApi` to have to drive the reading. + /// Instead, reading an item from the channel will notify the worker task, which will push + /// the next item. + /// Can also be used to send an error, in case an error happend on the HTTP socket. After + /// an error is sent, the channel will close. + body: mpsc::Receiver>, + }, + /// A request has failed because of an error. The request is then no longer valid. + Fail { + /// The ID that was passed to the worker. + id: HttpRequestId, + /// Error that happened. + error: hyper::Error, + }, +} + +/// Must be continuously polled for the [`HttpApi`] to properly work. +pub struct HttpWorker { + /// Used to sends messages to the `HttpApi`. + to_api: mpsc::UnboundedSender, + /// Used to receive messages from the `HttpApi`. + from_api: mpsc::UnboundedReceiver, + /// The engine that runs HTTP requests. + http_client: hyper::Client, hyper::Body>, + /// HTTP requests that are being worked on by the engine. + requests: Vec<(HttpRequestId, HttpWorkerRequest)>, +} + +/// HTTP request being processed by the worker. +enum HttpWorkerRequest { + /// Request has been dispatched and is waiting for a response from the Internet. + Dispatched(Compat01As03), + /// Progressively reading the body of the response and sending it to the channel. + ReadBody { + /// Body to read `Chunk`s from. Only used if the channel is ready to accept data. + body: Compat01As03, + /// Channel to the [`HttpApi`] where we send the chunks to. + tx: mpsc::Sender>, + }, +} + +impl Future for HttpWorker { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + // Reminder: this is continuously run in the background. + + // We use a `me` variable because the compiler isn't smart enough to allow borrowing + // multiple fields at once through a `Deref`. + let me = &mut *self; + + // We remove each element from `requests` one by one and add them back only if necessary. + for n in (0..me.requests.len()).rev() { + let (id, request) = me.requests.swap_remove(n); + match request { + HttpWorkerRequest::Dispatched(mut future) => { + // Check for an HTTP response from the Internet. + let mut response = match Future::poll(Pin::new(&mut future), cx) { + Poll::Pending => { + me.requests.push((id, HttpWorkerRequest::Dispatched(future))); + continue + }, + Poll::Ready(Ok(response)) => response, + Poll::Ready(Err(err)) => { + let _ = me.to_api.unbounded_send(WorkerToApi::Fail { + id, + error: err, + }); + continue; // don't insert the request back + } + }; + + // We received a response! Decompose it into its parts. + let status_code = response.status(); + let headers = mem::replace(response.headers_mut(), hyper::HeaderMap::new()); + let body = Compat01As03::new(response.into_body()); + + let (body_tx, body_rx) = mpsc::channel(3); + let _ = me.to_api.unbounded_send(WorkerToApi::Response { + id, + status_code, + headers, + body: body_rx, + }); + + me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx: body_tx })); + cx.waker().wake_by_ref(); // reschedule in order to poll the new future + continue + } + + HttpWorkerRequest::ReadBody { mut body, mut tx } => { + // Before reading from the HTTP response, check that `tx` is ready to accept + // a new chunk. + match tx.poll_ready(cx) { + Poll::Ready(Ok(())) => {} + Poll::Ready(Err(_)) => continue, // don't insert the request back + Poll::Pending => { + me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); + continue + } + } + + // `tx` is ready. Read a chunk from the socket and send it to the channel. + match Stream::poll_next(Pin::new(&mut body), cx) { + Poll::Ready(Some(Ok(chunk))) => { + let _ = tx.start_send(Ok(chunk)); + me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); + cx.waker().wake_by_ref(); // reschedule in order to continue reading + } + Poll::Ready(Some(Err(err))) => { + let _ = tx.start_send(Err(err)); + // don't insert the request back + }, + Poll::Ready(None) => {} // EOF; don't insert the request back + Poll::Pending => { + me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); + }, + } + } + } + } + + // Check for messages coming from the [`HttpApi`]. + match Stream::poll_next(Pin::new(&mut me.from_api), cx) { + Poll::Pending => {}, + Poll::Ready(None) => return Poll::Ready(()), // stops the worker + Poll::Ready(Some(ApiToWorker::Dispatch { id, request })) => { + let future = Compat01As03::new(me.http_client.request(request)); + debug_assert!(me.requests.iter().all(|(i, _)| *i != id)); + me.requests.push((id, HttpWorkerRequest::Dispatched(future))); + cx.waker().wake_by_ref(); // reschedule the task to poll the request + } + } + + Poll::Pending + } +} + +impl fmt::Debug for HttpWorker { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.requests.iter()) + .finish() + } +} + +impl fmt::Debug for HttpWorkerRequest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + HttpWorkerRequest::Dispatched(_) => + f.debug_tuple("HttpWorkerRequest::Dispatched").finish(), + HttpWorkerRequest::ReadBody { .. } => + f.debug_tuple("HttpWorkerRequest::Response").finish(), + } + } +} + +#[cfg(test)] +mod tests { + use crate::api::timestamp; + use super::http; + use futures::prelude::*; + use futures01::Future as _; + use sp_core::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Duration}; + + // Returns an `HttpApi` whose worker is ran in the background, and a `SocketAddr` to an HTTP + // server that runs in the background as well. + macro_rules! build_api_server { + () => {{ + let (api, worker) = http(); + // Note: we have to use tokio because hyper still uses old futures. + std::thread::spawn(move || { + tokio::run(futures::compat::Compat::new(worker.map(|()| Ok::<(), ()>(())))) + }); + let (addr_tx, addr_rx) = std::sync::mpsc::channel(); + std::thread::spawn(move || { + let server = hyper::Server::bind(&"127.0.0.1:0".parse().unwrap()) + .serve(|| { + hyper::service::service_fn_ok(move |_: hyper::Request| { + hyper::Response::new(hyper::Body::from("Hello World!")) + }) + }); + let _ = addr_tx.send(server.local_addr()); + hyper::rt::run(server.map_err(|e| panic!("{:?}", e))); + }); + (api, addr_rx.recv().unwrap()) + }}; + } + + #[test] + fn basic_localhost() { + let deadline = timestamp::now().add(Duration::from_millis(10_000)); + + // Performs an HTTP query to a background HTTP server. + + let (mut api, addr) = build_api_server!(); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[], Some(deadline)).unwrap(); + + match api.response_wait(&[id], Some(deadline))[0] { + HttpRequestStatus::Finished(200) => {}, + v => panic!("Connecting to localhost failed: {:?}", v) + } + + let headers = api.response_headers(id); + assert!(headers.iter().any(|(h, _)| h.eq_ignore_ascii_case(b"Date"))); + + let mut buf = vec![0; 2048]; + let n = api.response_read_body(id, &mut buf, Some(deadline)).unwrap(); + assert_eq!(&buf[..n], b"Hello World!"); + } + + #[test] + fn request_start_invalid_call() { + let (mut api, addr) = build_api_server!(); + + match api.request_start("\0", &format!("http://{}", addr)) { + Err(()) => {} + Ok(_) => panic!() + }; + + match api.request_start("GET", "http://\0localhost") { + Err(()) => {} + Ok(_) => panic!() + }; + } + + #[test] + fn request_add_header_invalid_call() { + let (mut api, addr) = build_api_server!(); + + match api.request_add_header(HttpRequestId(0xdead), "Foo", "bar") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + match api.request_add_header(id, "\0", "bar") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + match api.request_add_header(id, "Foo", "\0") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_add_header(id, "Foo", "Bar").unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + match api.request_add_header(id, "Foo2", "Bar") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.response_headers(id); + match api.request_add_header(id, "Foo2", "Bar") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.response_read_body(id, &mut [], None).unwrap(); + match api.request_add_header(id, "Foo2", "Bar") { + Err(()) => {} + Ok(_) => panic!() + }; + } + + #[test] + fn request_write_body_invalid_call() { + let (mut api, addr) = build_api_server!(); + + match api.request_write_body(HttpRequestId(0xdead), &[1, 2, 3], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + match api.request_write_body(HttpRequestId(0xdead), &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.request_write_body(id, &[], None).unwrap(); + match api.request_write_body(id, &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.request_write_body(id, &[], None).unwrap(); + match api.request_write_body(id, &[1, 2, 3, 4], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.response_wait(&[id], None); + match api.request_write_body(id, &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.response_wait(&[id], None); + match api.request_write_body(id, &[1, 2, 3, 4], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.response_headers(id); + match api.request_write_body(id, &[1, 2, 3, 4], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.response_headers(id); + match api.request_write_body(id, &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.response_read_body(id, &mut [], None).unwrap(); + match api.request_write_body(id, &[1, 2, 3, 4], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.response_read_body(id, &mut [], None).unwrap(); + match api.request_write_body(id, &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + } + + #[test] + fn response_headers_invalid_call() { + let (mut api, addr) = build_api_server!(); + assert!(api.response_headers(HttpRequestId(0xdead)).is_empty()); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + assert!(api.response_headers(id).is_empty()); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[], None).unwrap(); + while api.response_headers(id).is_empty() { + std::thread::sleep(std::time::Duration::from_millis(100)); + } + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.response_wait(&[id], None); + assert!(!api.response_headers(id).is_empty()); + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + let mut buf = [0; 128]; + while api.response_read_body(id, &mut buf, None).unwrap() != 0 {} + assert!(api.response_headers(id).is_empty()); + } + + #[test] + fn response_header_invalid_call() { + let (mut api, addr) = build_api_server!(); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + assert!(api.response_headers(id).is_empty()); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_add_header(id, "Foo", "Bar").unwrap(); + assert!(api.response_headers(id).is_empty()); + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.request_add_header(id, "Foo", "Bar").unwrap(); + api.request_write_body(id, &[], None).unwrap(); + // Note: this test actually sends out the request, and is supposed to test a situation + // where we haven't received any response yet. This test can theoretically fail if the + // HTTP response comes back faster than the kernel schedules our thread, but that is highly + // unlikely. + assert!(api.response_headers(id).is_empty()); + } + + #[test] + fn response_read_body_invalid_call() { + let (mut api, addr) = build_api_server!(); + let mut buf = [0; 512]; + + match api.response_read_body(HttpRequestId(0xdead), &mut buf, None) { + Err(HttpError::Invalid) => {} + _ => panic!() + } + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + while api.response_read_body(id, &mut buf, None).unwrap() != 0 {} + match api.response_read_body(id, &mut buf, None) { + Err(HttpError::Invalid) => {} + _ => panic!() + } + } + + #[test] + fn fuzzing() { + // Uses the API in random ways to try to trigger panicks. + // Doesn't test some paths, such as waiting for multiple requests. Also doesn't test what + // happens if the server force-closes our socket. + + let (mut api, addr) = build_api_server!(); + + for _ in 0..50 { + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + + for _ in 0..250 { + match rand::random::() % 6 { + 0 => { let _ = api.request_add_header(id, "Foo", "Bar"); } + 1 => { let _ = api.request_write_body(id, &[1, 2, 3, 4], None); } + 2 => { let _ = api.request_write_body(id, &[], None); } + 3 => { let _ = api.response_wait(&[id], None); } + 4 => { let _ = api.response_headers(id); } + 5 => { + let mut buf = [0; 512]; + let _ = api.response_read_body(id, &mut buf, None); + } + 6 ..= 255 => unreachable!() + } + } + } + } +} diff --git a/client/offchain/src/api/http_dummy.rs b/client/offchain/src/api/http_dummy.rs new file mode 100644 index 0000000000000..8725c89899795 --- /dev/null +++ b/client/offchain/src/api/http_dummy.rs @@ -0,0 +1,109 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Contains the same API as the `http` module, except that everything returns an error. + +use sp_core::offchain::{HttpRequestId, Timestamp, HttpRequestStatus, HttpError}; +use std::{future::Future, pin::Pin, task::Context, task::Poll}; + +/// Creates a pair of [`HttpApi`] and [`HttpWorker`]. +pub fn http() -> (HttpApi, HttpWorker) { + (HttpApi, HttpWorker) +} + +/// Dummy implementation of HTTP capabilities. +#[derive(Debug)] +pub struct HttpApi; + +/// Dummy implementation of HTTP capabilities. +#[derive(Debug)] +pub struct HttpWorker; + +impl HttpApi { + /// Mimicks the corresponding method in the offchain API. + pub fn request_start( + &mut self, + _: &str, + _: &str + ) -> Result { + /// Because this always returns an error, none of the other methods should ever be called. + Err(()) + } + + /// Mimicks the corresponding method in the offchain API. + pub fn request_add_header( + &mut self, + _: HttpRequestId, + _: &str, + _: &str + ) -> Result<(), ()> { + unreachable!("Creating a request always fails, thus this function will \ + never be called; qed") + } + + /// Mimicks the corresponding method in the offchain API. + pub fn request_write_body( + &mut self, + _: HttpRequestId, + _: &[u8], + _: Option + ) -> Result<(), HttpError> { + unreachable!("Creating a request always fails, thus this function will \ + never be called; qed") + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_wait( + &mut self, + requests: &[HttpRequestId], + _: Option + ) -> Vec { + if requests.is_empty() { + Vec::new() + } else { + unreachable!("Creating a request always fails, thus the list of requests should \ + always be empty; qed") + } + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_headers( + &mut self, + _: HttpRequestId + ) -> Vec<(Vec, Vec)> { + unreachable!("Creating a request always fails, thus this function will \ + never be called; qed") + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_read_body( + &mut self, + _: HttpRequestId, + _: &mut [u8], + _: Option + ) -> Result { + unreachable!("Creating a request always fails, thus this function will \ + never be called; qed") + } +} + +impl Future for HttpWorker { + type Output = (); + + fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll { + Poll::Ready(()) + } +} diff --git a/core/offchain/src/api/timestamp.rs b/client/offchain/src/api/timestamp.rs similarity index 95% rename from core/offchain/src/api/timestamp.rs rename to client/offchain/src/api/timestamp.rs index 445c7f3878474..e5494fe70d784 100644 --- a/core/offchain/src/api/timestamp.rs +++ b/client/offchain/src/api/timestamp.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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 @@ //! Helper methods dedicated to timestamps. -use primitives::offchain::Timestamp; +use sp_core::offchain::Timestamp; use std::convert::TryInto; use std::time::{SystemTime, Duration}; diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs new file mode 100644 index 0000000000000..e25072d42d603 --- /dev/null +++ b/client/offchain/src/lib.rs @@ -0,0 +1,221 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate offchain workers. +//! +//! The offchain workers is a special function of the runtime that +//! gets executed after block is imported. During execution +//! it's able to asynchronously submit extrinsics that will either +//! be propagated to other nodes added to the next block +//! produced by the node as unsigned transactions. +//! +//! Offchain workers can be used for computation-heavy tasks +//! that are not feasible for execution during regular block processing. +//! It can either be tasks that no consensus is required for, +//! or some form of consensus over the data can be built on-chain +//! for instance via: +//! 1. Challenge period for incorrect computations +//! 2. Majority voting for results +//! 3. etc + +#![warn(missing_docs)] + +use std::{fmt, marker::PhantomData, sync::Arc}; + +use parking_lot::Mutex; +use threadpool::ThreadPool; +use sp_api::{ApiExt, ProvideRuntimeApi}; +use futures::future::Future; +use log::{debug, warn}; +use sc_network::NetworkStateInfo; +use sp_core::{offchain::{self, OffchainStorage}, ExecutionContext}; +use sp_runtime::{generic::BlockId, traits::{self, Header}}; + +mod api; + +pub use sp_offchain::{OffchainWorkerApi, STORAGE_PREFIX}; + +/// An offchain workers manager. +pub struct OffchainWorkers { + client: Arc, + db: Storage, + _block: PhantomData, + thread_pool: Mutex, +} + +impl OffchainWorkers { + /// Creates new `OffchainWorkers`. + pub fn new(client: Arc, db: Storage) -> Self { + Self { + client, + db, + _block: PhantomData, + thread_pool: Mutex::new(ThreadPool::new(num_cpus::get())), + } + } +} + +impl fmt::Debug for OffchainWorkers< + Client, + Storage, + Block, +> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("OffchainWorkers").finish() + } +} + +impl OffchainWorkers< + Client, + Storage, + Block, +> where + Block: traits::Block, + Client: ProvideRuntimeApi + Send + Sync + 'static, + Client::Api: OffchainWorkerApi, + Storage: OffchainStorage + 'static, +{ + /// Start the offchain workers after given block. + #[must_use] + pub fn on_block_imported( + &self, + header: &Block::Header, + network_state: Arc, + is_validator: bool, + ) -> impl Future { + let runtime = self.client.runtime_api(); + let at = BlockId::number(*header.number()); + let has_api_v1 = runtime.has_api_with::, _>( + &at, |v| v == 1 + ); + let has_api_v2 = runtime.has_api::>(&at); + let version = match (has_api_v1, has_api_v2) { + (_, Ok(true)) => 2, + (Ok(true), _) => 1, + _ => 0, + }; + + debug!("Checking offchain workers at {:?}: version:{}", at, version); + if version > 0 { + let (api, runner) = api::AsyncApi::new( + self.db.clone(), + network_state.clone(), + is_validator, + ); + debug!("Spawning offchain workers at {:?}", at); + let header = header.clone(); + let client = self.client.clone(); + self.spawn_worker(move || { + let runtime = client.runtime_api(); + let api = Box::new(api); + debug!("Running offchain workers at {:?}", at); + let context = ExecutionContext::OffchainCall(Some( + (api, offchain::Capabilities::all()) + )); + let run = if version == 2 { + runtime.offchain_worker_with_context(&at, context, &header) + } else { + #[allow(deprecated)] + runtime.offchain_worker_before_version_2_with_context( + &at, context, *header.number() + ) + }; + if let Err(e) = run { + log::error!("Error running offchain workers at {:?}: {:?}", at, e); + } + }); + futures::future::Either::Left(runner.process()) + } else { + futures::future::Either::Right(futures::future::ready(())) + } + } + + /// Spawns a new offchain worker. + /// + /// We spawn offchain workers for each block in a separate thread, + /// since they can run for a significant amount of time + /// in a blocking fashion and we don't want to block the runtime. + /// + /// Note that we should avoid that if we switch to future-based runtime in the future, + /// alternatively: + fn spawn_worker(&self, f: impl FnOnce() -> () + Send + 'static) { + self.thread_pool.lock().execute(f); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::Arc; + use sc_network::{Multiaddr, PeerId}; + use substrate_test_runtime_client::runtime::Block; + use sc_transaction_pool::{BasicPool, FullChainApi}; + use sp_transaction_pool::{TransactionPool, InPoolTransaction}; + use sp_runtime::{generic::Header, traits::Header as _}; + + struct MockNetworkStateInfo(); + + impl NetworkStateInfo for MockNetworkStateInfo { + fn external_addresses(&self) -> Vec { + Vec::new() + } + + fn local_peer_id(&self) -> PeerId { + PeerId::random() + } + } + + struct TestPool(BasicPool, Block>); + + impl sp_transaction_pool::OffchainSubmitTransaction for TestPool { + fn submit_at( + &self, + at: &BlockId, + extrinsic: ::Extrinsic, + ) -> Result<(), ()> { + futures::executor::block_on(self.0.submit_one(&at, extrinsic)) + .map(|_| ()) + .map_err(|_| ()) + } + } + + #[test] + fn should_call_into_runtime_and_produce_extrinsic() { + // given + let _ = env_logger::try_init(); + let client = Arc::new(substrate_test_runtime_client::new()); + let pool = Arc::new(TestPool(BasicPool::new(Default::default(), FullChainApi::new(client.clone())))); + client.execution_extensions() + .register_transaction_pool(Arc::downgrade(&pool.clone()) as _); + let db = sc_client_db::offchain::LocalStorage::new_test(); + let network_state = Arc::new(MockNetworkStateInfo()); + let header = Header::new( + 0u64, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ); + + // when + let offchain = OffchainWorkers::new(client, db); + futures::executor::block_on(offchain.on_block_imported(&header, network_state, false)); + + // then + assert_eq!(pool.0.status().ready, 1); + assert_eq!(pool.0.ready().next().unwrap().is_propagateable(), false); + } +} diff --git a/client/peerset/Cargo.toml b/client/peerset/Cargo.toml new file mode 100644 index 0000000000000..90f44418c72e4 --- /dev/null +++ b/client/peerset/Cargo.toml @@ -0,0 +1,17 @@ +[package] +description = "Connectivity manager based on reputation" +homepage = "http://parity.io" +license = "GPL-3.0" +name = "sc-peerset" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +futures = "0.3.1" +libp2p = { version = "0.14.0-alpha.1", default-features = false } +log = "0.4.8" +serde_json = "1.0.41" + +[dev-dependencies] +rand = "0.7.2" diff --git a/client/peerset/src/lib.rs b/client/peerset/src/lib.rs new file mode 100644 index 0000000000000..c958912727007 --- /dev/null +++ b/client/peerset/src/lib.rs @@ -0,0 +1,688 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Peer Set Manager (PSM). Contains the strategy for choosing which nodes the network should be +//! connected to. + +mod peersstate; + +use std::{collections::{HashSet, HashMap}, collections::VecDeque, time::Instant}; +use futures::{prelude::*, channel::mpsc}; +use libp2p::PeerId; +use log::{debug, error, trace}; +use serde_json::json; +use std::{pin::Pin, task::Context, task::Poll}; + +/// We don't accept nodes whose reputation is under this value. +const BANNED_THRESHOLD: i32 = 82 * (i32::min_value() / 100); +/// Reputation change for a node when we get disconnected from it. +const DISCONNECT_REPUTATION_CHANGE: i32 = -10; +/// Reserved peers group ID +const RESERVED_NODES: &'static str = "reserved"; + +#[derive(Debug)] +enum Action { + AddReservedPeer(PeerId), + RemoveReservedPeer(PeerId), + SetReservedOnly(bool), + ReportPeer(PeerId, ReputationChange), + SetPriorityGroup(String, HashSet), + AddToPriorityGroup(String, PeerId), + RemoveFromPriorityGroup(String, PeerId), +} + +/// Shared handle to the peer set manager (PSM). Distributed around the code. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ReputationChange { + /// Reputation delta. + pub value: i32, + /// Reason for reputation change. + pub reason: &'static str, +} + +impl ReputationChange { + /// New reputation change with given delta and reason. + pub const fn new(value: i32, reason: &'static str) -> ReputationChange { + ReputationChange { value, reason } + } + + /// New reputation change that forces minimum possible reputation. + pub const fn new_fatal(reason: &'static str) -> ReputationChange { + ReputationChange { value: i32::min_value(), reason } + } +} + +/// Shared handle to the peer set manager (PSM). Distributed around the code. +#[derive(Debug, Clone)] +pub struct PeersetHandle { + tx: mpsc::UnboundedSender, +} + +impl PeersetHandle { + /// Adds a new reserved peer. The peerset will make an effort to always remain connected to + /// this peer. + /// + /// Has no effect if the node was already a reserved peer. + /// + /// > **Note**: Keep in mind that the networking has to know an address for this node, + /// > otherwise it will not be able to connect to it. + pub fn add_reserved_peer(&self, peer_id: PeerId) { + let _ = self.tx.unbounded_send(Action::AddReservedPeer(peer_id)); + } + + /// Remove a previously-added reserved peer. + /// + /// Has no effect if the node was not a reserved peer. + pub fn remove_reserved_peer(&self, peer_id: PeerId) { + let _ = self.tx.unbounded_send(Action::RemoveReservedPeer(peer_id)); + } + + /// Sets whether or not the peerset only has connections . + pub fn set_reserved_only(&self, reserved: bool) { + let _ = self.tx.unbounded_send(Action::SetReservedOnly(reserved)); + } + + /// Reports an adjustment to the reputation of the given peer. + pub fn report_peer(&self, peer_id: PeerId, score_diff: ReputationChange) { + let _ = self.tx.unbounded_send(Action::ReportPeer(peer_id, score_diff)); + } + + /// Modify a priority group. + pub fn set_priority_group(&self, group_id: String, peers: HashSet) { + let _ = self.tx.unbounded_send(Action::SetPriorityGroup(group_id, peers)); + } + + /// Add a peer to a priority group. + pub fn add_to_priority_group(&self, group_id: String, peer_id: PeerId) { + let _ = self.tx.unbounded_send(Action::AddToPriorityGroup(group_id, peer_id)); + } + + /// Remove a peer from a priority group. + pub fn remove_from_priority_group(&self, group_id: String, peer_id: PeerId) { + let _ = self.tx.unbounded_send(Action::RemoveFromPriorityGroup(group_id, peer_id)); + } +} + +/// Message that can be sent by the peer set manager (PSM). +#[derive(Debug, PartialEq)] +pub enum Message { + /// Request to open a connection to the given peer. From the point of view of the PSM, we are + /// immediately connected. + Connect(PeerId), + + /// Drop the connection to the given peer, or cancel the connection attempt after a `Connect`. + Drop(PeerId), + + /// Equivalent to `Connect` for the peer corresponding to this incoming index. + Accept(IncomingIndex), + + /// Equivalent to `Drop` for the peer corresponding to this incoming index. + Reject(IncomingIndex), +} + +/// Opaque identifier for an incoming connection. Allocated by the network. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct IncomingIndex(pub u64); + +impl From for IncomingIndex { + fn from(val: u64) -> IncomingIndex { + IncomingIndex(val) + } +} + +/// Configuration to pass when creating the peer set manager. +#[derive(Debug)] +pub struct PeersetConfig { + /// Maximum number of ingoing links to peers. + pub in_peers: u32, + + /// Maximum number of outgoing links to peers. + pub out_peers: u32, + + /// List of bootstrap nodes to initialize the peer with. + /// + /// > **Note**: Keep in mind that the networking has to know an address for these nodes, + /// > otherwise it will not be able to connect to them. + pub bootnodes: Vec, + + /// If true, we only accept reserved nodes. + pub reserved_only: bool, + + /// List of nodes that we should always be connected to. + /// + /// > **Note**: Keep in mind that the networking has to know an address for these nodes, + /// > otherwise it will not be able to connect to them. + pub reserved_nodes: Vec, +} + +/// Side of the peer set manager owned by the network. In other words, the "receiving" side. +/// +/// Implements the `Stream` trait and can be polled for messages. The `Stream` never ends and never +/// errors. +#[derive(Debug)] +pub struct Peerset { + data: peersstate::PeersState, + /// If true, we only accept reserved nodes. + reserved_only: bool, + /// Receiver for messages from the `PeersetHandle` and from `tx`. + rx: mpsc::UnboundedReceiver, + /// Sending side of `rx`. + tx: mpsc::UnboundedSender, + /// Queue of messages to be emitted when the `Peerset` is polled. + message_queue: VecDeque, + /// When the `Peerset` was created. + created: Instant, + /// Last time when we updated the reputations of connected nodes. + latest_time_update: Instant, +} + +impl Peerset { + /// Builds a new peerset from the given configuration. + pub fn from_config(config: PeersetConfig) -> (Peerset, PeersetHandle) { + let (tx, rx) = mpsc::unbounded(); + + let handle = PeersetHandle { + tx: tx.clone(), + }; + + let mut peerset = Peerset { + data: peersstate::PeersState::new(config.in_peers, config.out_peers, config.reserved_only), + tx, + rx, + reserved_only: config.reserved_only, + message_queue: VecDeque::new(), + created: Instant::now(), + latest_time_update: Instant::now(), + }; + + peerset.data.set_priority_group(RESERVED_NODES, config.reserved_nodes.into_iter().collect()); + for peer_id in config.bootnodes { + if let peersstate::Peer::Unknown(entry) = peerset.data.peer(&peer_id) { + entry.discover(); + } else { + debug!(target: "peerset", "Duplicate bootnode in config: {:?}", peer_id); + } + } + + peerset.alloc_slots(); + (peerset, handle) + } + + fn on_add_reserved_peer(&mut self, peer_id: PeerId) { + let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); + reserved.insert(peer_id); + self.data.set_priority_group(RESERVED_NODES, reserved); + self.alloc_slots(); + } + + fn on_remove_reserved_peer(&mut self, peer_id: PeerId) { + let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); + reserved.remove(&peer_id); + self.data.set_priority_group(RESERVED_NODES, reserved); + match self.data.peer(&peer_id) { + peersstate::Peer::Connected(peer) => { + if self.reserved_only { + peer.disconnect(); + self.message_queue.push_back(Message::Drop(peer_id)); + } + } + peersstate::Peer::NotConnected(_) => {}, + peersstate::Peer::Unknown(_) => {}, + } + } + + fn on_set_reserved_only(&mut self, reserved_only: bool) { + self.reserved_only = reserved_only; + self.data.set_priority_only(reserved_only); + + if self.reserved_only { + // Disconnect non-reserved nodes. + let reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); + for peer_id in self.data.connected_peers().cloned().collect::>().into_iter() { + let peer = self.data.peer(&peer_id).into_connected() + .expect("We are enumerating connected peers, therefore the peer is connected; qed"); + if !reserved.contains(&peer_id) { + peer.disconnect(); + self.message_queue.push_back(Message::Drop(peer_id)); + } + } + } else { + self.alloc_slots(); + } + } + + fn on_set_priority_group(&mut self, group_id: &str, peers: HashSet) { + self.data.set_priority_group(group_id, peers); + self.alloc_slots(); + } + + fn on_add_to_priority_group(&mut self, group_id: &str, peer_id: PeerId) { + self.data.add_to_priority_group(group_id, peer_id); + self.alloc_slots(); + } + + fn on_remove_from_priority_group(&mut self, group_id: &str, peer_id: PeerId) { + self.data.remove_from_priority_group(group_id, &peer_id); + self.alloc_slots(); + } + + fn on_report_peer(&mut self, peer_id: PeerId, change: ReputationChange) { + // We want reputations to be up-to-date before adjusting them. + self.update_time(); + + match self.data.peer(&peer_id) { + peersstate::Peer::Connected(mut peer) => { + peer.add_reputation(change.value); + if peer.reputation() < BANNED_THRESHOLD { + debug!(target: "peerset", "Report {}: {:+} to {}. Reason: {}, Disconnecting", + peer_id, change.value, peer.reputation(), change.reason + ); + peer.disconnect(); + self.message_queue.push_back(Message::Drop(peer_id)); + } else { + trace!(target: "peerset", "Report {}: {:+} to {}. Reason: {}", + peer_id, change.value, peer.reputation(), change.reason + ); + } + }, + peersstate::Peer::NotConnected(mut peer) => peer.add_reputation(change.value), + peersstate::Peer::Unknown(peer) => peer.discover().add_reputation(change.value), + } + } + + /// Updates the value of `self.latest_time_update` and performs all the updates that happen + /// over time, such as reputation increases for staying connected. + fn update_time(&mut self) { + // We basically do `(now - self.latest_update).as_secs()`, except that by the way we do it + // we know that we're not going to miss seconds because of rounding to integers. + let secs_diff = { + let now = Instant::now(); + let elapsed_latest = self.latest_time_update - self.created; + let elapsed_now = now - self.created; + self.latest_time_update = now; + elapsed_now.as_secs() - elapsed_latest.as_secs() + }; + + // For each elapsed second, move the node reputation towards zero. + // If we multiply each second the reputation by `k` (where `k` is between 0 and 1), it + // takes `ln(0.5) / ln(k)` seconds to reduce the reputation by half. Use this formula to + // empirically determine a value of `k` that looks correct. + for _ in 0..secs_diff { + for peer_id in self.data.peers().cloned().collect::>() { + // We use `k = 0.98`, so we divide by `50`. With that value, it takes 34.3 seconds + // to reduce the reputation by half. + fn reput_tick(reput: i32) -> i32 { + let mut diff = reput / 50; + if diff == 0 && reput < 0 { + diff = -1; + } else if diff == 0 && reput > 0 { + diff = 1; + } + reput.saturating_sub(diff) + } + match self.data.peer(&peer_id) { + peersstate::Peer::Connected(mut peer) => { + let before = peer.reputation(); + let after = reput_tick(before); + trace!(target: "peerset", "Fleeting {}: {} -> {}", peer_id, before, after); + peer.set_reputation(after) + } + peersstate::Peer::NotConnected(mut peer) => { + let before = peer.reputation(); + let after = reput_tick(before); + trace!(target: "peerset", "Fleeting {}: {} -> {}", peer_id, before, after); + peer.set_reputation(after) + } + peersstate::Peer::Unknown(_) => unreachable!("We iterate over known peers; qed") + }; + } + } + } + + /// Try to fill available out slots with nodes. + fn alloc_slots(&mut self) { + self.update_time(); + + // Try to grab the next node to attempt to connect to. + while let Some(next) = { + if self.reserved_only { + self.data.priority_not_connected_peer_from_group(RESERVED_NODES) + } else { + self.data.priority_not_connected_peer() + } + } { + match next.try_outgoing() { + Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())), + Err(_) => break, // No more slots available. + } + } + + loop { + if self.reserved_only { + break + } + + // Try to grab the next node to attempt to connect to. + let next = match self.data.highest_not_connected_peer() { + Some(p) => p, + None => break, // No known node to add. + }; + + // Don't connect to nodes with an abysmal reputation. + if next.reputation() < BANNED_THRESHOLD { + break; + } + + match next.try_outgoing() { + Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())), + Err(_) => break, // No more slots available. + } + } + } + + /// Indicate that we received an incoming connection. Must be answered either with + /// a corresponding `Accept` or `Reject`, except if we were already connected to this peer. + /// + /// Note that this mechanism is orthogonal to `Connect`/`Drop`. Accepting an incoming + /// connection implicitly means `Connect`, but incoming connections aren't cancelled by + /// `dropped`. + /// + // Implementation note: because of concurrency issues, it is possible that we push a `Connect` + // message to the output channel with a `PeerId`, and that `incoming` gets called with the same + // `PeerId` before that message has been read by the user. In this situation we must not answer. + pub fn incoming(&mut self, peer_id: PeerId, index: IncomingIndex) { + trace!(target: "peerset", "Incoming {:?}", peer_id); + self.update_time(); + + let not_connected = match self.data.peer(&peer_id) { + // If we're already connected, don't answer, as the docs mention. + peersstate::Peer::Connected(_) => return, + peersstate::Peer::NotConnected(entry) => entry, + peersstate::Peer::Unknown(entry) => entry.discover(), + }; + + if not_connected.reputation() < BANNED_THRESHOLD { + self.message_queue.push_back(Message::Reject(index)); + return + } + + match not_connected.try_accept_incoming() { + Ok(_) => self.message_queue.push_back(Message::Accept(index)), + Err(_) => self.message_queue.push_back(Message::Reject(index)), + } + } + + /// Indicate that we dropped an active connection with a peer, or that we failed to connect. + /// + /// Must only be called after the PSM has either generated a `Connect` message with this + /// `PeerId`, or accepted an incoming connection with this `PeerId`. + pub fn dropped(&mut self, peer_id: PeerId) { + trace!(target: "peerset", "Dropping {:?}", peer_id); + + // We want reputations to be up-to-date before adjusting them. + self.update_time(); + + match self.data.peer(&peer_id) { + peersstate::Peer::Connected(mut entry) => { + // Decrease the node's reputation so that we don't try it again and again and again. + entry.add_reputation(DISCONNECT_REPUTATION_CHANGE); + entry.disconnect(); + } + peersstate::Peer::NotConnected(_) | peersstate::Peer::Unknown(_) => + error!(target: "peerset", "Received dropped() for non-connected node"), + } + + self.alloc_slots(); + } + + /// Adds discovered peer ids to the PSM. + /// + /// > **Note**: There is no equivalent "expired" message, meaning that it is the responsibility + /// > of the PSM to remove `PeerId`s that fail to dial too often. + pub fn discovered>(&mut self, peer_ids: I) { + let mut discovered_any = false; + + for peer_id in peer_ids { + if let peersstate::Peer::Unknown(entry) = self.data.peer(&peer_id) { + entry.discover(); + discovered_any = true; + } + } + + if discovered_any { + self.alloc_slots(); + } + } + + /// Reports an adjustment to the reputation of the given peer. + pub fn report_peer(&mut self, peer_id: PeerId, score_diff: ReputationChange) { + // We don't immediately perform the adjustments in order to have state consistency. We + // don't want the reporting here to take priority over messages sent using the + // `PeersetHandle`. + let _ = self.tx.unbounded_send(Action::ReportPeer(peer_id, score_diff)); + } + + /// Produces a JSON object containing the state of the peerset manager, for debugging purposes. + pub fn debug_info(&mut self) -> serde_json::Value { + self.update_time(); + + json!({ + "nodes": self.data.peers().cloned().collect::>().into_iter().map(|peer_id| { + let state = match self.data.peer(&peer_id) { + peersstate::Peer::Connected(entry) => json!({ + "connected": true, + "reputation": entry.reputation() + }), + peersstate::Peer::NotConnected(entry) => json!({ + "connected": false, + "reputation": entry.reputation() + }), + peersstate::Peer::Unknown(_) => + unreachable!("We iterate over the known peers; QED") + }; + + (peer_id.to_base58(), state) + }).collect::>(), + "reserved_only": self.reserved_only, + "message_queue": self.message_queue.len(), + }) + } + + /// Returns priority group by id. + pub fn get_priority_group(&self, group_id: &str) -> Option> { + self.data.get_priority_group(group_id) + } +} + +impl Stream for Peerset { + type Item = Message; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + loop { + if let Some(message) = self.message_queue.pop_front() { + return Poll::Ready(Some(message)); + } + + let action = match Stream::poll_next(Pin::new(&mut self.rx), cx) { + Poll::Pending => return Poll::Pending, + Poll::Ready(Some(event)) => event, + Poll::Ready(None) => return Poll::Pending, + }; + + match action { + Action::AddReservedPeer(peer_id) => + self.on_add_reserved_peer(peer_id), + Action::RemoveReservedPeer(peer_id) => + self.on_remove_reserved_peer(peer_id), + Action::SetReservedOnly(reserved) => + self.on_set_reserved_only(reserved), + Action::ReportPeer(peer_id, score_diff) => + self.on_report_peer(peer_id, score_diff), + Action::SetPriorityGroup(group_id, peers) => + self.on_set_priority_group(&group_id, peers), + Action::AddToPriorityGroup(group_id, peer_id) => + self.on_add_to_priority_group(&group_id, peer_id), + Action::RemoveFromPriorityGroup(group_id, peer_id) => + self.on_remove_from_priority_group(&group_id, peer_id), + } + } + } +} + +#[cfg(test)] +mod tests { + use libp2p::PeerId; + use futures::prelude::*; + use super::{PeersetConfig, Peerset, Message, IncomingIndex, ReputationChange, BANNED_THRESHOLD}; + use std::{pin::Pin, task::Poll, thread, time::Duration}; + + fn assert_messages(mut peerset: Peerset, messages: Vec) -> Peerset { + for expected_message in messages { + let (message, p) = next_message(peerset).expect("expected message"); + assert_eq!(message, expected_message); + peerset = p; + } + assert!(peerset.message_queue.is_empty(), peerset.message_queue); + peerset + } + + fn next_message(mut peerset: Peerset) -> Result<(Message, Peerset), ()> { + let next = futures::executor::block_on_stream(&mut peerset).next(); + let message = next.ok_or_else(|| ())?; + Ok((message, peerset)) + } + + #[test] + fn test_peerset_add_reserved_peer() { + let bootnode = PeerId::random(); + let reserved_peer = PeerId::random(); + let reserved_peer2 = PeerId::random(); + let config = PeersetConfig { + in_peers: 0, + out_peers: 2, + bootnodes: vec![bootnode], + reserved_only: true, + reserved_nodes: Vec::new(), + }; + + let (peerset, handle) = Peerset::from_config(config); + handle.add_reserved_peer(reserved_peer.clone()); + handle.add_reserved_peer(reserved_peer2.clone()); + + assert_messages(peerset, vec![ + Message::Connect(reserved_peer), + Message::Connect(reserved_peer2) + ]); + } + + #[test] + fn test_peerset_incoming() { + let bootnode = PeerId::random(); + let incoming = PeerId::random(); + let incoming2 = PeerId::random(); + let incoming3 = PeerId::random(); + let ii = IncomingIndex(1); + let ii2 = IncomingIndex(2); + let ii3 = IncomingIndex(3); + let ii4 = IncomingIndex(3); + let config = PeersetConfig { + in_peers: 2, + out_peers: 1, + bootnodes: vec![bootnode.clone()], + reserved_only: false, + reserved_nodes: Vec::new(), + }; + + let (mut peerset, _handle) = Peerset::from_config(config); + peerset.incoming(incoming.clone(), ii); + peerset.incoming(incoming.clone(), ii4); + peerset.incoming(incoming2.clone(), ii2); + peerset.incoming(incoming3.clone(), ii3); + + assert_messages(peerset, vec![ + Message::Connect(bootnode.clone()), + Message::Accept(ii), + Message::Accept(ii2), + Message::Reject(ii3), + ]); + } + + #[test] + fn test_peerset_discovered() { + let bootnode = PeerId::random(); + let discovered = PeerId::random(); + let discovered2 = PeerId::random(); + let config = PeersetConfig { + in_peers: 0, + out_peers: 2, + bootnodes: vec![bootnode.clone()], + reserved_only: false, + reserved_nodes: vec![], + }; + + let (mut peerset, _handle) = Peerset::from_config(config); + peerset.discovered(Some(discovered.clone())); + peerset.discovered(Some(discovered.clone())); + peerset.discovered(Some(discovered2)); + + assert_messages(peerset, vec![ + Message::Connect(bootnode), + Message::Connect(discovered), + ]); + } + + #[test] + fn test_peerset_banned() { + let (mut peerset, handle) = Peerset::from_config(PeersetConfig { + in_peers: 25, + out_peers: 25, + bootnodes: vec![], + reserved_only: false, + reserved_nodes: vec![], + }); + + // We ban a node by setting its reputation under the threshold. + let peer_id = PeerId::random(); + handle.report_peer(peer_id.clone(), ReputationChange::new(BANNED_THRESHOLD - 1, "")); + + let fut = futures::future::poll_fn(move |cx| { + // We need one polling for the message to be processed. + assert_eq!(Stream::poll_next(Pin::new(&mut peerset), cx), Poll::Pending); + + // Check that an incoming connection from that node gets refused. + peerset.incoming(peer_id.clone(), IncomingIndex(1)); + if let Poll::Ready(msg) = Stream::poll_next(Pin::new(&mut peerset), cx) { + assert_eq!(msg.unwrap(), Message::Reject(IncomingIndex(1))); + } else { + panic!() + } + + // Wait a bit for the node's reputation to go above the threshold. + thread::sleep(Duration::from_millis(1500)); + + // Try again. This time the node should be accepted. + peerset.incoming(peer_id.clone(), IncomingIndex(2)); + while let Poll::Ready(msg) = Stream::poll_next(Pin::new(&mut peerset), cx) { + assert_eq!(msg.unwrap(), Message::Accept(IncomingIndex(2))); + } + + Poll::Ready(()) + }); + + futures::executor::block_on(fut); + } +} + diff --git a/core/peerset/src/peersstate.rs b/client/peerset/src/peersstate.rs similarity index 99% rename from core/peerset/src/peersstate.rs rename to client/peerset/src/peersstate.rs index 57dfc50d345b0..a27d6e616b23e 100644 --- a/core/peerset/src/peersstate.rs +++ b/client/peerset/src/peersstate.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -249,8 +249,8 @@ impl PeersState { /// Tries to accept the peer as an incoming connection. /// - /// If there are enough slots available, switches the node to "connected" and returns `Ok`. If - /// the slots are full, the node stays "not connected" and we return `Err`. + /// If there are enough slots available, switches the node to "connected" and returns `true`. If + /// the slots are full, the node stays "not connected" and we return `false`. /// /// Note that reserved nodes don't count towards the number of slots. fn try_accept_incoming(&mut self, peer_id: &PeerId) -> bool { diff --git a/core/peerset/tests/fuzz.rs b/client/peerset/tests/fuzz.rs similarity index 95% rename from core/peerset/tests/fuzz.rs rename to client/peerset/tests/fuzz.rs index be29916c34f20..b591d83d8f2af 100644 --- a/core/peerset/tests/fuzz.rs +++ b/client/peerset/tests/fuzz.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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 libp2p::PeerId; use rand::distributions::{Distribution, Uniform, WeightedIndex}; use rand::seq::IteratorRandom; use std::{collections::HashMap, collections::HashSet, iter, pin::Pin, task::Poll}; -use substrate_peerset::{IncomingIndex, Message, PeersetConfig, Peerset}; +use sc_peerset::{IncomingIndex, Message, PeersetConfig, Peerset, ReputationChange}; #[test] fn run() { @@ -97,7 +97,7 @@ fn test_once() { // If we generate 2, adjust a random reputation. 2 => if let Some(id) = known_nodes.iter().choose(&mut rng) { let val = Uniform::new_inclusive(i32::min_value(), i32::max_value()).sample(&mut rng); - peerset_handle.report_peer(id.clone(), val); + peerset_handle.report_peer(id.clone(), ReputationChange::new(val, "")); } // If we generate 3, disconnect from a random node. diff --git a/client/rpc-api/Cargo.toml b/client/rpc-api/Cargo.toml new file mode 100644 index 0000000000000..2c7a2ee071d7f --- /dev/null +++ b/client/rpc-api/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sc-rpc-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0" } +derive_more = "0.99.2" +futures = { version = "0.3.1", features = ["compat"] } +jsonrpc-core = "14.0.3" +jsonrpc-core-client = "14.0.3" +jsonrpc-derive = "14.0.3" +jsonrpc-pubsub = "14.0.3" +log = "0.4.8" +parking_lot = "0.9.0" +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-version = { version = "2.0.0", path = "../../primitives/version" } +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.41" +sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } +sp-rpc = { version = "2.0.0", path = "../../primitives/rpc" } diff --git a/client/rpc-api/src/author/error.rs b/client/rpc-api/src/author/error.rs new file mode 100644 index 0000000000000..8ebd06f8de430 --- /dev/null +++ b/client/rpc-api/src/author/error.rs @@ -0,0 +1,155 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Authoring RPC module errors. + +use crate::errors; +use jsonrpc_core as rpc; + +/// Author RPC Result type. +pub type Result = std::result::Result; + +/// Author RPC future Result type. +pub type FutureResult = Box + Send>; + +/// Author RPC errors. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Client error. + #[display(fmt="Client error: {}", _0)] + #[from(ignore)] + Client(Box), + /// Transaction pool error, + #[display(fmt="Transaction pool error: {}", _0)] + Pool(sp_transaction_pool::error::Error), + /// Verification error + #[display(fmt="Extrinsic verification error: {}", _0)] + #[from(ignore)] + Verification(Box), + /// Incorrect extrinsic format. + #[display(fmt="Invalid extrinsic format: {}", _0)] + BadFormat(codec::Error), + /// Incorrect seed phrase. + #[display(fmt="Invalid seed phrase/SURI")] + BadSeedPhrase, + /// Key type ID has an unknown format. + #[display(fmt="Invalid key type ID format (should be of length four)")] + BadKeyType, + /// Key type ID has some unsupported crypto. + #[display(fmt="The crypto of key type ID is unknown")] + UnsupportedKeyType, + /// Some random issue with the key store. Shouldn't happen. + #[display(fmt="The key store is unavailable")] + KeyStoreUnavailable, +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Client(ref err) => Some(&**err), + Error::Pool(ref err) => Some(err), + Error::Verification(ref err) => Some(&**err), + _ => None, + } + } +} + +/// Base code for all authorship errors. +const BASE_ERROR: i64 = 1000; +/// Extrinsic has an invalid format. +const BAD_FORMAT: i64 = BASE_ERROR + 1; +/// Error during 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; +/// The key type crypto is not known. +const UNSUPPORTED_KEY_TYPE: i64 = POOL_INVALID_TX + 7; + +impl From for rpc::Error { + fn from(e: Error) -> Self { + use sp_transaction_pool::error::{Error as PoolError}; + + match e { + Error::BadFormat(e) => rpc::Error { + code: rpc::ErrorCode::ServerError(BAD_FORMAT), + message: format!("Extrinsic has invalid format: {}", e).into(), + data: None, + }, + Error::Verification(e) => rpc::Error { + code: rpc::ErrorCode::ServerError(VERIFICATION_ERROR), + message: format!("Verification Error: {}", e).into(), + data: Some(format!("{:?}", e).into()), + }, + Error::Pool(PoolError::InvalidTransaction(e)) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), + message: "Invalid Transaction".into(), + data: serde_json::to_value(e).ok(), + }, + Error::Pool(PoolError::UnknownTransaction(e)) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), + message: "Unknown Transaction Validity".into(), + data: serde_json::to_value(e).ok(), + }, + Error::Pool(PoolError::TemporarilyBanned) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_TEMPORARILY_BANNED), + message: "Transaction is temporarily banned".into(), + data: None, + }, + Error::Pool(PoolError::AlreadyImported(hash)) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_ALREADY_IMPORTED), + message: "Transaction Already Imported".into(), + data: Some(format!("{:?}", hash).into()), + }, + Error::Pool(PoolError::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::Pool(PoolError::CycleDetected) => rpc::Error { + code: rpc::ErrorCode::ServerError(POOL_CYCLE_DETECTED), + message: "Cycle Detected".into(), + data: None, + }, + Error::Pool(PoolError::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()), + }, + Error::UnsupportedKeyType => rpc::Error { + code: rpc::ErrorCode::ServerError(UNSUPPORTED_KEY_TYPE), + message: "Unknown key type crypto" .into(), + data: Some( + "The crypto for the given key type is unknown, please add the public key to the \ + request to insert the key successfully.".into() + ), + }, + e => errors::internal(e), + } + } +} diff --git a/client/rpc-api/src/author/hash.rs b/client/rpc-api/src/author/hash.rs new file mode 100644 index 0000000000000..4287af8ede596 --- /dev/null +++ b/client/rpc-api/src/author/hash.rs @@ -0,0 +1,32 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Extrinsic helpers for author RPC module. + +use sp_core::Bytes; +use serde::{Serialize, Deserialize}; + +/// RPC Extrinsic or hash +/// +/// Allows to refer to extrinsic either by its raw representation or its hash. +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum ExtrinsicOrHash { + /// The hash of the extrinsic. + Hash(Hash), + /// Raw extrinsic bytes. + Extrinsic(Bytes), +} diff --git a/client/rpc-api/src/author/mod.rs b/client/rpc-api/src/author/mod.rs new file mode 100644 index 0000000000000..cbdbd38154490 --- /dev/null +++ b/client/rpc-api/src/author/mod.rs @@ -0,0 +1,87 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate block-author/full-node API. + +pub mod error; +pub mod hash; + +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use sp_core::Bytes; +use sp_transaction_pool::TransactionStatus; +use self::error::{FutureResult, Result}; + +pub use self::gen_client::Client as AuthorClient; + +/// Substrate authoring RPC API +#[rpc] +pub trait AuthorApi { + /// RPC metadata + type Metadata; + + /// Submit hex-encoded extrinsic for inclusion in block. + #[rpc(name = "author_submitExtrinsic")] + fn submit_extrinsic(&self, extrinsic: Bytes) -> FutureResult; + + /// Insert a key into the keystore. + #[rpc(name = "author_insertKey")] + fn insert_key(&self, + key_type: String, + suri: String, + public: Bytes, + ) -> Result<()>; + + /// Generate new session keys and returns the corresponding public keys. + #[rpc(name = "author_rotateKeys")] + fn rotate_keys(&self) -> Result; + + /// Returns all pending extrinsics, potentially grouped by sender. + #[rpc(name = "author_pendingExtrinsics")] + fn pending_extrinsics(&self) -> Result>; + + /// Remove given extrinsic from the pool and temporarily ban it to prevent reimporting. + #[rpc(name = "author_removeExtrinsic")] + fn remove_extrinsic(&self, + bytes_or_hash: Vec> + ) -> Result>; + + /// Submit an extrinsic to watch. + /// + /// See [`TransactionStatus`](sp_transaction_pool::TransactionStatus) for details on transaction + /// lifecycle. + #[pubsub( + subscription = "author_extrinsicUpdate", + subscribe, + name = "author_submitAndWatchExtrinsic" + )] + fn watch_extrinsic(&self, + metadata: Self::Metadata, + subscriber: Subscriber>, + bytes: Bytes + ); + + /// Unsubscribe from extrinsic watching. + #[pubsub( + subscription = "author_extrinsicUpdate", + unsubscribe, + name = "author_unwatchExtrinsic" + )] + fn unwatch_extrinsic(&self, + metadata: Option, + id: SubscriptionId + ) -> Result; +} diff --git a/client/rpc-api/src/chain/error.rs b/client/rpc-api/src/chain/error.rs new file mode 100644 index 0000000000000..ffa4d82bdff89 --- /dev/null +++ b/client/rpc-api/src/chain/error.rs @@ -0,0 +1,62 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + + +//! Error helpers for Chain RPC module. + +use crate::errors; +use jsonrpc_core as rpc; + +/// Chain RPC Result type. +pub type Result = std::result::Result; + +/// Chain RPC future Result type. +pub type FutureResult = Box + Send>; + +/// Chain RPC errors. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Client error. + #[display(fmt="Client error: {}", _0)] + Client(Box), + /// Other error type. + Other(String), +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Client(ref err) => Some(&**err), + _ => None, + } + } +} + +/// Base error code for all chain errors. +const BASE_ERROR: i64 = 3000; + +impl From for rpc::Error { + fn from(e: Error) -> Self { + match e { + Error::Other(message) => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 1), + message, + data: None, + }, + e => errors::internal(e), + } + } +} diff --git a/client/rpc-api/src/chain/mod.rs b/client/rpc-api/src/chain/mod.rs new file mode 100644 index 0000000000000..0c270a3f70528 --- /dev/null +++ b/client/rpc-api/src/chain/mod.rs @@ -0,0 +1,100 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate blockchain API. + +pub mod error; + +use jsonrpc_core::Result as RpcResult; +use jsonrpc_core::futures::Future; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use sp_rpc::{number::NumberOrHex, list::ListOrValue}; +use self::error::{FutureResult, Result}; + +pub use self::gen_client::Client as ChainClient; + +/// Substrate blockchain API +#[rpc] +pub trait ChainApi { + /// RPC metadata + type Metadata; + + /// Get header of a relay chain block. + #[rpc(name = "chain_getHeader")] + fn header(&self, hash: Option) -> FutureResult>; + + /// Get header and body of a relay chain block. + #[rpc(name = "chain_getBlock")] + fn block(&self, hash: Option) -> FutureResult>; + + /// Get hash of the n-th block in the canon chain. + /// + /// By default returns latest block hash. + #[rpc(name = "chain_getBlockHash", alias("chain_getHead"))] + fn block_hash( + &self, + hash: Option>>, + ) -> Result>>; + + /// Get hash of the last finalized block in the canon chain. + #[rpc(name = "chain_getFinalizedHead", alias("chain_getFinalisedHead"))] + fn finalized_head(&self) -> Result; + + /// New head subscription + #[pubsub( + subscription = "chain_newHead", + subscribe, + name = "chain_subscribeNewHeads", + alias("subscribe_newHead", "chain_subscribeNewHead") + )] + fn subscribe_new_heads(&self, metadata: Self::Metadata, subscriber: Subscriber
); + + /// Unsubscribe from new head subscription. + #[pubsub( + subscription = "chain_newHead", + unsubscribe, + name = "chain_unsubscribeNewHeads", + alias("unsubscribe_newHead", "chain_unsubscribeNewHead") + )] + fn unsubscribe_new_heads( + &self, + metadata: Option, + id: SubscriptionId, + ) -> RpcResult; + + /// New head subscription + #[pubsub( + subscription = "chain_finalizedHead", + subscribe, + name = "chain_subscribeFinalizedHeads", + alias("chain_subscribeFinalisedHeads") + )] + fn subscribe_finalized_heads(&self, metadata: Self::Metadata, subscriber: Subscriber
); + + /// Unsubscribe from new head subscription. + #[pubsub( + subscription = "chain_finalizedHead", + unsubscribe, + name = "chain_unsubscribeFinalizedHeads", + alias("chain_unsubscribeFinalisedHeads") + )] + fn unsubscribe_finalized_heads( + &self, + metadata: Option, + id: SubscriptionId, + ) -> RpcResult; +} diff --git a/core/rpc/api/src/errors.rs b/client/rpc-api/src/errors.rs similarity index 94% rename from core/rpc/api/src/errors.rs rename to client/rpc-api/src/errors.rs index 984a1cd712762..9db41d0497068 100644 --- a/core/rpc/api/src/errors.rs +++ b/client/rpc-api/src/errors.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/client/rpc-api/src/helpers.rs b/client/rpc-api/src/helpers.rs new file mode 100644 index 0000000000000..912a5664b3c2f --- /dev/null +++ b/client/rpc-api/src/helpers.rs @@ -0,0 +1,31 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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 jsonrpc_core::futures::prelude::*; +use futures::{channel::oneshot, compat::Compat}; + +/// Wraps around `oneshot::Receiver` and adjusts the error type to produce an internal error if the +/// sender gets dropped. +pub struct Receiver(pub Compat>); + +impl Future for Receiver { + type Item = T; + type Error = jsonrpc_core::Error; + + fn poll(&mut self) -> Poll { + self.0.poll().map_err(|_| jsonrpc_core::Error::internal_error()) + } +} diff --git a/client/rpc-api/src/lib.rs b/client/rpc-api/src/lib.rs new file mode 100644 index 0000000000000..c9306f2cddb79 --- /dev/null +++ b/client/rpc-api/src/lib.rs @@ -0,0 +1,34 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate RPC interfaces. +//! +//! A collection of RPC methods and subscriptions supported by all substrate clients. + +#![warn(missing_docs)] + +mod errors; +mod helpers; +mod subscriptions; + +pub use jsonrpc_core::IoHandlerExtension as RpcExtension; +pub use subscriptions::{Subscriptions, TaskExecutor}; +pub use helpers::Receiver; + +pub mod author; +pub mod chain; +pub mod state; +pub mod system; diff --git a/client/rpc-api/src/state/error.rs b/client/rpc-api/src/state/error.rs new file mode 100644 index 0000000000000..4997a728fc4fb --- /dev/null +++ b/client/rpc-api/src/state/error.rs @@ -0,0 +1,69 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! State RPC errors. + +use crate::errors; +use jsonrpc_core as rpc; + +/// State RPC Result type. +pub type Result = std::result::Result; + +/// State RPC future Result type. +pub type FutureResult = Box + Send>; + +/// State RPC errors. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Client error. + #[display(fmt="Client error: {}", _0)] + Client(Box), + /// Provided block range couldn't be resolved to a list of blocks. + #[display(fmt = "Cannot resolve a block range ['{:?}' ... '{:?}]. {}", from, to, details)] + InvalidBlockRange { + /// Beginning of the block range. + from: String, + /// End of the block range. + to: String, + /// Details of the error message. + details: String, + }, +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Client(ref err) => Some(&**err), + _ => None, + } + } +} + +/// Base code for all state errors. +const BASE_ERROR: i64 = 4000; + +impl From for rpc::Error { + fn from(e: Error) -> Self { + match e { + Error::InvalidBlockRange { .. } => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 1), + message: format!("{}", e), + data: None, + }, + e => errors::internal(e), + } + } +} diff --git a/client/rpc-api/src/state/mod.rs b/client/rpc-api/src/state/mod.rs new file mode 100644 index 0000000000000..b22bacbe8706a --- /dev/null +++ b/client/rpc-api/src/state/mod.rs @@ -0,0 +1,151 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate state API. + +pub mod error; + +use jsonrpc_core::Result as RpcResult; +use jsonrpc_core::futures::Future; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use sp_core::Bytes; +use sp_core::storage::{StorageKey, StorageData, StorageChangeSet}; +use sp_version::RuntimeVersion; +use self::error::FutureResult; + +pub use self::gen_client::Client as StateClient; + +/// Substrate state API +#[rpc] +pub trait StateApi { + /// RPC Metadata + type Metadata; + + /// Call a contract at a block's state. + #[rpc(name = "state_call", alias("state_callAt"))] + fn call(&self, name: String, bytes: Bytes, hash: Option) -> FutureResult; + + /// Returns the keys with prefix, leave empty to get all the keys + #[rpc(name = "state_getKeys")] + fn storage_keys(&self, prefix: StorageKey, hash: Option) -> FutureResult>; + + /// Returns a storage entry at a specific block's state. + #[rpc(name = "state_getStorage", alias("state_getStorageAt"))] + fn storage(&self, key: StorageKey, hash: Option) -> FutureResult>; + + /// Returns the hash of a storage entry at a block's state. + #[rpc(name = "state_getStorageHash", alias("state_getStorageHashAt"))] + fn storage_hash(&self, key: StorageKey, hash: Option) -> FutureResult>; + + /// Returns the size of a storage entry at a block's state. + #[rpc(name = "state_getStorageSize", alias("state_getStorageSizeAt"))] + fn storage_size(&self, key: StorageKey, hash: Option) -> FutureResult>; + + /// Returns the keys with prefix from a child storage, leave empty to get all the keys + #[rpc(name = "state_getChildKeys")] + fn child_storage_keys( + &self, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + prefix: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns a child storage entry at a specific block's state. + #[rpc(name = "state_getChildStorage")] + fn child_storage( + &self, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns the hash of a child storage entry at a block's state. + #[rpc(name = "state_getChildStorageHash")] + fn child_storage_hash( + &self, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns the size of a child storage entry at a block's state. + #[rpc(name = "state_getChildStorageSize")] + fn child_storage_size( + &self, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns the runtime metadata as an opaque blob. + #[rpc(name = "state_getMetadata")] + fn metadata(&self, hash: Option) -> FutureResult; + + /// Get the runtime version. + #[rpc(name = "state_getRuntimeVersion", alias("chain_getRuntimeVersion"))] + fn runtime_version(&self, hash: Option) -> FutureResult; + + /// Query historical storage entries (by key) starting from a block given as the second parameter. + /// + /// NOTE This first returned result contains the initial state of storage for all keys. + /// Subsequent values in the vector represent changes to the previous state (diffs). + #[rpc(name = "state_queryStorage")] + fn query_storage( + &self, + keys: Vec, + block: Hash, + hash: Option + ) -> FutureResult>>; + + /// New runtime version subscription + #[pubsub( + subscription = "state_runtimeVersion", + subscribe, + name = "state_subscribeRuntimeVersion", + alias("chain_subscribeRuntimeVersion") + )] + fn subscribe_runtime_version(&self, metadata: Self::Metadata, subscriber: Subscriber); + + /// Unsubscribe from runtime version subscription + #[pubsub( + subscription = "state_runtimeVersion", + unsubscribe, + name = "state_unsubscribeRuntimeVersion", + alias("chain_unsubscribeRuntimeVersion") + )] + fn unsubscribe_runtime_version(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + + /// New storage subscription + #[pubsub(subscription = "state_storage", subscribe, name = "state_subscribeStorage")] + fn subscribe_storage( + &self, metadata: Self::Metadata, subscriber: Subscriber>, keys: Option> + ); + + /// Unsubscribe from storage subscription + #[pubsub(subscription = "state_storage", unsubscribe, name = "state_unsubscribeStorage")] + fn unsubscribe_storage( + &self, metadata: Option, id: SubscriptionId + ) -> RpcResult; +} diff --git a/core/rpc/api/src/subscriptions.rs b/client/rpc-api/src/subscriptions.rs similarity index 98% rename from core/rpc/api/src/subscriptions.rs rename to client/rpc-api/src/subscriptions.rs index d5ca74fa60bc7..808c9d5ba4490 100644 --- a/core/rpc/api/src/subscriptions.rs +++ b/client/rpc-api/src/subscriptions.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/client/rpc-api/src/system/error.rs b/client/rpc-api/src/system/error.rs new file mode 100644 index 0000000000000..fbb4e44bcb635 --- /dev/null +++ b/client/rpc-api/src/system/error.rs @@ -0,0 +1,55 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! System RPC module errors. + +use crate::system::helpers::Health; +use jsonrpc_core as rpc; + +/// System RPC Result type. +pub type Result = std::result::Result; + +/// System RPC errors. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Provided block range couldn't be resolved to a list of blocks. + #[display(fmt = "Node is not fully functional: {}", _0)] + NotHealthy(Health), + /// Peer argument is malformatted. + MalformattedPeerArg(String), +} + +impl std::error::Error for Error {} + +/// Base code for all system errors. +const BASE_ERROR: i64 = 2000; + +impl From for rpc::Error { + fn from(e: Error) -> Self { + match e { + Error::NotHealthy(ref h) => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 1), + message: format!("{}", e), + data: serde_json::to_value(h).ok(), + }, + Error::MalformattedPeerArg(ref e) => rpc::Error { + code :rpc::ErrorCode::ServerError(BASE_ERROR + 2), + message: e.clone(), + data: None, + } + } + } +} diff --git a/client/rpc-api/src/system/helpers.rs b/client/rpc-api/src/system/helpers.rs new file mode 100644 index 0000000000000..572136aeb6c40 --- /dev/null +++ b/client/rpc-api/src/system/helpers.rs @@ -0,0 +1,119 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate system API helpers. + +use std::fmt; +use serde::{Serialize, Deserialize}; +use serde_json::{Value, map::Map}; + +/// Node properties +pub type Properties = Map; + +/// Running node's static details. +#[derive(Clone, Debug)] +pub struct SystemInfo { + /// Implementation name. + pub impl_name: String, + /// Implementation version. + pub impl_version: String, + /// Chain name. + pub chain_name: String, + /// A custom set of properties defined in the chain spec. + pub properties: Properties, +} + +/// Health struct returned by the RPC +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[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, +} + +impl fmt::Display for Health { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{} peers ({})", self.peers, if self.is_syncing { + "syncing" + } else { "idle" }) + } +} + +/// Network Peer information +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PeerInfo { + /// 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, +} + +/// The role the node is running as +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub enum NodeRole { + /// The node is a full node + Full, + /// The node is a light client + LightClient, + /// The node is an authority + Authority, + /// An unknown role with a bit number + UnknownRole(u8) +} + +#[cfg(test)] +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 { + peer_id: "2".into(), + roles: "a".into(), + protocol_version: 2, + best_hash: 5u32, + best_number: 6u32, + }).unwrap(), + r#"{"peerId":"2","roles":"a","protocolVersion":2,"bestHash":5,"bestNumber":6}"#, + ); + } +} diff --git a/client/rpc-api/src/system/mod.rs b/client/rpc-api/src/system/mod.rs new file mode 100644 index 0000000000000..f12a11e0b36dd --- /dev/null +++ b/client/rpc-api/src/system/mod.rs @@ -0,0 +1,87 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate system API. + +pub mod error; +pub mod helpers; + +use crate::helpers::Receiver; +use jsonrpc_derive::rpc; +use futures::{future::BoxFuture, compat::Compat}; + +use self::error::Result as SystemResult; + +pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; +pub use self::gen_client::Client as SystemClient; + +/// Substrate system RPC API +#[rpc] +pub trait SystemApi { + /// Get the node's implementation name. Plain old string. + #[rpc(name = "system_name")] + fn system_name(&self) -> SystemResult; + + /// Get the node implementation's version. Should be a semver string. + #[rpc(name = "system_version")] + fn system_version(&self) -> SystemResult; + + /// Get the chain's type. Given as a string identifier. + #[rpc(name = "system_chain")] + fn system_chain(&self) -> SystemResult; + + /// Get a custom set of properties as a JSON object, defined in the chain spec. + #[rpc(name = "system_properties")] + fn system_properties(&self) -> SystemResult; + + /// Return health status of the node. + /// + /// Node is considered healthy if it is: + /// - connected to some peers (unless running in dev mode) + /// - not performing a major sync + #[rpc(name = "system_health", returns = "Health")] + fn system_health(&self) -> Receiver; + + /// Returns currently connected peers + #[rpc(name = "system_peers", returns = "Vec>")] + fn system_peers(&self) -> Receiver>>; + + /// Returns current state of the network. + /// + /// **Warning**: This API is not stable. + // TODO: make this stable and move structs https://github.com/paritytech/substrate/issues/1890 + #[rpc(name = "system_networkState", returns = "jsonrpc_core::Value")] + fn system_network_state(&self) -> Receiver; + + /// Adds a reserved peer. Returns the empty string or an error. The string + /// parameter should encode a `p2p` multiaddr. + /// + /// `/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV` + /// is an example of a valid, passing multiaddr with PeerId attached. + #[rpc(name = "system_addReservedPeer", returns = "()")] + fn system_add_reserved_peer(&self, peer: String) + -> Compat>>; + + /// Remove a reserved peer. Returns the empty string or an error. The string + /// should encode only the PeerId e.g. `QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV`. + #[rpc(name = "system_removeReservedPeer", returns = "()")] + fn system_remove_reserved_peer(&self, peer_id: String) + -> Compat>>; + + /// Returns the roles the node is running as. + #[rpc(name = "system_nodeRoles", returns = "Vec")] + fn system_node_roles(&self) -> Receiver>; +} diff --git a/client/rpc-servers/Cargo.toml b/client/rpc-servers/Cargo.toml new file mode 100644 index 0000000000000..e540274e25414 --- /dev/null +++ b/client/rpc-servers/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "sc-rpc-server" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +jsonrpc-core = "14.0.3" +pubsub = { package = "jsonrpc-pubsub", version = "14.0.3" } +log = "0.4.8" +serde = "1.0.101" +serde_json = "1.0.41" +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } + +[target.'cfg(not(target_os = "unknown"))'.dependencies] +http = { package = "jsonrpc-http-server", version = "14.0.3" } +ws = { package = "jsonrpc-ws-server", version = "14.0.3" } diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs new file mode 100644 index 0000000000000..97fb10c15e4b5 --- /dev/null +++ b/client/rpc-servers/src/lib.rs @@ -0,0 +1,135 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate RPC servers. + +#![warn(missing_docs)] + +use std::io; +use jsonrpc_core::IoHandlerExtension; +use log::error; +use pubsub::PubSubMetadata; + +/// Maximal payload accepted by RPC servers. +const MAX_PAYLOAD: usize = 15 * 1024 * 1024; + +/// Default maximum number of connections for WS RPC servers. +const WS_MAX_CONNECTIONS: usize = 100; + +/// The RPC IoHandler containing all requested APIs. +pub type RpcHandler = pubsub::PubSubHandler; + +pub use self::inner::*; + +/// Construct rpc `IoHandler` +pub fn rpc_handler( + extension: impl IoHandlerExtension +) -> RpcHandler { + let mut io = pubsub::PubSubHandler::default(); + extension.augment(&mut io); + + // add an endpoint to list all available methods. + let mut methods = io.iter().map(|x| x.0.clone()).collect::>(); + io.add_method("rpc_methods", { + methods.sort(); + let methods = serde_json::to_value(&methods) + .expect("Serialization of Vec is infallible; qed"); + + move |_| Ok(serde_json::json!({ + "version": 1, + "methods": methods.clone(), + })) + }); + io +} + +#[cfg(not(target_os = "unknown"))] +mod inner { + use super::*; + + /// Type alias for http server + pub type HttpServer = http::Server; + /// Type alias for ws server + pub type WsServer = ws::Server; + + /// Start HTTP server listening on given address. + /// + /// **Note**: Only available if `not(target_os = "unknown")`. + pub fn start_http( + addr: &std::net::SocketAddr, + cors: Option<&Vec>, + io: RpcHandler, + ) -> io::Result { + http::ServerBuilder::new(io) + .threads(4) + .health_api(("/health", "system_health")) + .allowed_hosts(hosts_filtering(cors.is_some())) + .rest_api(if cors.is_some() { + http::RestApi::Secure + } else { + http::RestApi::Unsecure + }) + .cors(map_cors::(cors)) + .max_request_body_size(MAX_PAYLOAD) + .start_http(addr) + } + + /// Start WS server listening on given address. + /// + /// **Note**: Only available if `not(target_os = "unknown")`. + pub fn start_ws>> ( + addr: &std::net::SocketAddr, + max_connections: Option, + cors: Option<&Vec>, + io: RpcHandler, + ) -> io::Result { + ws::ServerBuilder::with_meta_extractor(io, |context: &ws::RequestContext| context.sender().into()) + .max_payload(MAX_PAYLOAD) + .max_connections(max_connections.unwrap_or(WS_MAX_CONNECTIONS)) + .allowed_origins(map_cors(cors)) + .allowed_hosts(hosts_filtering(cors.is_some())) + .start(addr) + .map_err(|err| match err { + ws::Error::Io(io) => io, + ws::Error::ConnectionClosed => io::ErrorKind::BrokenPipe.into(), + e => { + error!("{}", e); + io::ErrorKind::Other.into() + } + }) + } + + fn map_cors From<&'a str>>( + cors: Option<&Vec> + ) -> http::DomainsValidation { + cors.map(|x| x.iter().map(AsRef::as_ref).map(Into::into).collect::>()).into() + } + + fn hosts_filtering(enable: bool) -> http::DomainsValidation { + if enable { + // NOTE The listening address is whitelisted by default. + // Setting an empty vector here enables the validation + // and allows only the listening address. + http::DomainsValidation::AllowOnly(vec![]) + } else { + http::DomainsValidation::Disabled + } + } +} + +#[cfg(target_os = "unknown")] +mod inner { +} diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml new file mode 100644 index 0000000000000..f4a42d169a6dc --- /dev/null +++ b/client/rpc/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "sc-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sc-rpc-api = { version = "2.0.0", path = "../rpc-api" } +sc-client-api = { version = "2.0.0", path = "../api" } +sc-client = { version = "2.0.0", path = "../" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +futures = { version = "0.3.1", features = ["compat"] } +jsonrpc-pubsub = "14.0.3" +log = "0.4.8" +sp-core = { version = "2.0.0", path = "../../primitives/core" } +rpc = { package = "jsonrpc-core", version = "14.0.3" } +sp-version = { version = "2.0.0", path = "../../primitives/version" } +serde_json = "1.0.41" +sp-session = { version = "2.0.0", path = "../../primitives/session" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-rpc = { version = "2.0.0", path = "../../primitives/rpc" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } +sc-executor = { version = "2.0.0", path = "../executor" } +sc-keystore = { version = "2.0.0", path = "../keystore" } +sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +hash-db = { version = "0.15.2", default-features = false } +parking_lot = { version = "0.9.0" } + +[dev-dependencies] +assert_matches = "1.3.0" +futures01 = { package = "futures", version = "0.1.29" } +sc-network = { version = "0.8", path = "../network" } +rustc-hex = "2.0.1" +sp-io = { version = "2.0.0", path = "../../primitives/io" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } +tokio = "0.1.22" +sc-transaction-pool = { version = "2.0.0", path = "../transaction-pool" } diff --git a/client/rpc/src/author/mod.rs b/client/rpc/src/author/mod.rs new file mode 100644 index 0000000000000..9891abc47d030 --- /dev/null +++ b/client/rpc/src/author/mod.rs @@ -0,0 +1,209 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate block-author/full-node API. + +#[cfg(test)] +mod tests; + +use std::{sync::Arc, convert::TryInto}; +use log::warn; + +use sc_client::Client; +use sp_blockchain::Error as ClientError; + +use rpc::futures::{ + Sink, Future, + future::result, +}; +use futures::{StreamExt as _, compat::Compat}; +use futures::future::{ready, FutureExt, TryFutureExt}; +use sc_rpc_api::Subscriptions; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use codec::{Encode, Decode}; +use sp_core::{Bytes, traits::BareCryptoStorePtr}; +use sp_api::ProvideRuntimeApi; +use sp_runtime::{generic, traits}; +use sp_transaction_pool::{ + TransactionPool, InPoolTransaction, TransactionStatus, + BlockHash, TxHash, TransactionFor, error::IntoPoolError, +}; +use sp_session::SessionKeys; + +/// Re-export the API for backward compatibility. +pub use sc_rpc_api::author::*; +use self::error::{Error, FutureResult, Result}; + +/// Authoring API +pub struct Author { + /// Substrate client + client: Arc>, + /// Transactions pool + pool: Arc

, + /// Subscriptions manager + subscriptions: Subscriptions, + /// The key store. + keystore: BareCryptoStorePtr, +} + +impl Author { + /// Create new instance of Authoring API. + pub fn new( + client: Arc>, + pool: Arc

, + subscriptions: Subscriptions, + keystore: BareCryptoStorePtr, + ) -> Self { + Author { + client, + pool, + subscriptions, + keystore, + } + } +} + +impl AuthorApi, BlockHash

> + for Author::Block, RA> +where + B: sc_client_api::backend::Backend<

::Block> + Send + Sync + 'static, + E: sc_client::CallExecutor<

::Block> + Send + Sync + 'static, + P: TransactionPool + Sync + Send + 'static, + P::Block: traits::Block, + P::Error: 'static, + RA: Send + Sync + 'static, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + SessionKeys, +{ + type Metadata = crate::metadata::Metadata; + + fn insert_key( + &self, + key_type: String, + suri: String, + public: Bytes, + ) -> Result<()> { + let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?; + let mut keystore = self.keystore.write(); + keystore.insert_unknown(key_type, &suri, &public[..]) + .map_err(|_| Error::KeyStoreUnavailable)?; + Ok(()) + } + + fn rotate_keys(&self) -> Result { + let best_block_hash = self.client.chain_info().best_hash; + self.client.runtime_api().generate_session_keys( + &generic::BlockId::Hash(best_block_hash), + None, + ).map(Into::into).map_err(|e| Error::Client(Box::new(e))) + } + + fn submit_extrinsic(&self, ext: Bytes) -> FutureResult> { + let xt = match Decode::decode(&mut &ext[..]) { + Ok(xt) => xt, + Err(err) => return Box::new(result(Err(err.into()))), + }; + let best_block_hash = self.client.chain_info().best_hash; + Box::new(self.pool + .submit_one(&generic::BlockId::hash(best_block_hash), xt) + .compat() + .map_err(|e| e.into_pool_error() + .map(Into::into) + .unwrap_or_else(|e| error::Error::Verification(Box::new(e)).into())) + ) + } + + fn pending_extrinsics(&self) -> Result> { + Ok(self.pool.ready().map(|tx| tx.data().encode().into()).collect()) + } + + fn remove_extrinsic( + &self, + bytes_or_hash: Vec>>, + ) -> Result>> { + let hashes = bytes_or_hash.into_iter() + .map(|x| match x { + hash::ExtrinsicOrHash::Hash(h) => Ok(h), + hash::ExtrinsicOrHash::Extrinsic(bytes) => { + let xt = Decode::decode(&mut &bytes[..])?; + Ok(self.pool.hash_of(&xt)) + }, + }) + .collect::>>()?; + + Ok( + self.pool + .remove_invalid(&hashes) + .into_iter() + .map(|tx| tx.hash().clone()) + .collect() + ) + } + + fn watch_extrinsic(&self, + _metadata: Self::Metadata, + subscriber: Subscriber, BlockHash

>>, + xt: Bytes, + ) { + let submit = || -> Result<_> { + let best_block_hash = self.client.chain_info().best_hash; + let dxt = TransactionFor::

::decode(&mut &xt[..]) + .map_err(error::Error::from)?; + Ok( + self.pool + .submit_and_watch(&generic::BlockId::hash(best_block_hash), dxt) + .map_err(|e| e.into_pool_error() + .map(error::Error::from) + .unwrap_or_else(|e| error::Error::Verification(Box::new(e)).into()) + ) + ) + }; + + let subscriptions = self.subscriptions.clone(); + let future = ready(submit()) + .and_then(|res| res) + // convert the watcher into a `Stream` + .map(|res| res.map(|stream| stream.map(|v| Ok::<_, ()>(Ok(v))))) + // now handle the import result, + // start a new subscrition + .map(move |result| match result { + Ok(watcher) => { + subscriptions.add(subscriber, move |sink| { + sink + .sink_map_err(|_| unimplemented!()) + .send_all(Compat::new(watcher)) + .map(|_| ()) + }); + }, + Err(err) => { + warn!("Failed to submit extrinsic: {}", err); + // reject the subscriber (ignore errors - we don't care if subscriber is no longer there). + let _ = subscriber.reject(err.into()); + }, + }); + + let res = self.subscriptions.executor() + .execute(Box::new(Compat::new(future.map(|_| Ok(()))))); + if res.is_err() { + warn!("Error spawning subscription RPC task."); + } + } + + fn unwatch_extrinsic(&self, _metadata: Option, id: SubscriptionId) -> Result { + Ok(self.subscriptions.cancel(id)) + } +} diff --git a/client/rpc/src/author/tests.rs b/client/rpc/src/author/tests.rs new file mode 100644 index 0000000000000..9fe51d62f5115 --- /dev/null +++ b/client/rpc/src/author/tests.rs @@ -0,0 +1,239 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use super::*; + +use std::sync::Arc; +use assert_matches::assert_matches; +use codec::Encode; +use sp_core::{ + H256, blake2_256, hexdisplay::HexDisplay, testing::{ED25519, SR25519, KeyStore}, traits::BareCryptoStorePtr, ed25519, + crypto::Pair, +}; +use rpc::futures::Stream as _; +use substrate_test_runtime_client::{ + self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys, RuntimeApi, Block}, + DefaultTestClientBuilderExt, TestClientBuilderExt, Backend, Client, Executor, +}; +use sc_transaction_pool::{BasicPool, FullChainApi}; +use tokio::runtime; + +fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { + let tx = Transfer { + amount: Default::default(), + nonce, + from: sender.into(), + to: Default::default(), + }; + tx.into_signed_tx() +} + +type FullTransactionPool = BasicPool< + FullChainApi, Block>, + Block, +>; + +struct TestSetup { + pub runtime: runtime::Runtime, + pub client: Arc>, + pub keystore: BareCryptoStorePtr, + pub pool: Arc, +} + +impl Default for TestSetup { + fn default() -> Self { + let keystore = KeyStore::new(); + let client = Arc::new(substrate_test_runtime_client::TestClientBuilder::new().set_keystore(keystore.clone()).build()); + let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); + TestSetup { + runtime: runtime::Runtime::new().expect("Failed to create runtime in test setup"), + client, + keystore, + pool, + } + } +} + +impl TestSetup { + fn author(&self) -> Author { + Author { + client: self.client.clone(), + pool: self.pool.clone(), + subscriptions: Subscriptions::new(Arc::new(self.runtime.executor())), + keystore: self.keystore.clone(), + } + } +} + +#[test] +fn submit_transaction_should_not_cause_error() { + let p = TestSetup::default().author(); + let xt = uxt(AccountKeyring::Alice, 1).encode(); + let h: H256 = blake2_256(&xt).into(); + + assert_matches!( + AuthorApi::submit_extrinsic(&p, xt.clone().into()).wait(), + Ok(h2) if h == h2 + ); + assert!( + AuthorApi::submit_extrinsic(&p, xt.into()).wait().is_err() + ); +} + +#[test] +fn submit_rich_transaction_should_not_cause_error() { + let p = TestSetup::default().author(); + let xt = uxt(AccountKeyring::Alice, 0).encode(); + let h: H256 = blake2_256(&xt).into(); + + assert_matches!( + AuthorApi::submit_extrinsic(&p, xt.clone().into()).wait(), + Ok(h2) if h == h2 + ); + assert!( + AuthorApi::submit_extrinsic(&p, xt.into()).wait().is_err() + ); +} + +#[test] +fn should_watch_extrinsic() { + //given + let mut setup = TestSetup::default(); + let p = setup.author(); + + let (subscriber, id_rx, data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); + + // when + p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 0).encode().into()); + + // then + assert_eq!(setup.runtime.block_on(id_rx), Ok(Ok(1.into()))); + // check notifications + let replacement = { + let tx = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }; + tx.into_signed_tx() + }; + AuthorApi::submit_extrinsic(&p, replacement.encode().into()).wait().unwrap(); + let (res, data) = setup.runtime.block_on(data.into_future()).unwrap(); + assert_eq!( + res, + Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":"ready","subscription":1}}"#.into()) + ); + let h = blake2_256(&replacement.encode()); + assert_eq!( + setup.runtime.block_on(data.into_future()).unwrap().0, + Some(format!(r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":1}}}}"#, HexDisplay::from(&h))) + ); +} + +#[test] +fn should_return_watch_validation_error() { + //given + let mut setup = TestSetup::default(); + let p = setup.author(); + + let (subscriber, id_rx, _data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); + + // when + p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 179).encode().into()); + + // then + let res = setup.runtime.block_on(id_rx).unwrap(); + assert!(res.is_err(), "Expected the transaction to be rejected as invalid."); +} + +#[test] +fn should_return_pending_extrinsics() { + let p = TestSetup::default().author(); + + let ex = uxt(AccountKeyring::Alice, 0); + AuthorApi::submit_extrinsic(&p, ex.encode().into()).wait().unwrap(); + assert_matches!( + p.pending_extrinsics(), + Ok(ref expected) if *expected == vec![Bytes(ex.encode())] + ); +} + +#[test] +fn should_remove_extrinsics() { + let setup = TestSetup::default(); + let p = setup.author(); + + let ex1 = uxt(AccountKeyring::Alice, 0); + p.submit_extrinsic(ex1.encode().into()).wait().unwrap(); + let ex2 = uxt(AccountKeyring::Alice, 1); + p.submit_extrinsic(ex2.encode().into()).wait().unwrap(); + let ex3 = uxt(AccountKeyring::Bob, 0); + let hash3 = p.submit_extrinsic(ex3.encode().into()).wait().unwrap(); + assert_eq!(setup.pool.status().ready, 3); + + // now remove all 3 + let removed = p.remove_extrinsic(vec![ + hash::ExtrinsicOrHash::Hash(hash3), + // Removing this one will also remove ex2 + hash::ExtrinsicOrHash::Extrinsic(ex1.encode().into()), + ]).unwrap(); + + assert_eq!(removed.len(), 3); +} + +#[test] +fn should_insert_key() { + let setup = TestSetup::default(); + let p = setup.author(); + + let suri = "//Alice"; + let key_pair = ed25519::Pair::from_string(suri, None).expect("Generates keypair"); + p.insert_key( + String::from_utf8(ED25519.0.to_vec()).expect("Keytype is a valid string"), + suri.to_string(), + key_pair.public().0.to_vec().into(), + ).expect("Insert key"); + + let store_key_pair = setup.keystore.read() + .ed25519_key_pair(ED25519, &key_pair.public()).expect("Key exists in store"); + + assert_eq!(key_pair.public(), store_key_pair.public()); +} + +#[test] +fn should_rotate_keys() { + let setup = TestSetup::default(); + let p = setup.author(); + + let new_public_keys = p.rotate_keys().expect("Rotates the keys"); + + let session_keys = SessionKeys::decode(&mut &new_public_keys[..]) + .expect("SessionKeys decode successfully"); + + let ed25519_key_pair = setup.keystore.read().ed25519_key_pair( + ED25519, + &session_keys.ed25519.clone().into(), + ).expect("ed25519 key exists in store"); + + let sr25519_key_pair = setup.keystore.read().sr25519_key_pair( + SR25519, + &session_keys.sr25519.clone().into(), + ).expect("sr25519 key exists in store"); + + assert_eq!(session_keys.ed25519, ed25519_key_pair.public().into()); + assert_eq!(session_keys.sr25519, sr25519_key_pair.public().into()); +} diff --git a/core/rpc/src/chain/chain_full.rs b/client/rpc/src/chain/chain_full.rs similarity index 83% rename from core/rpc/src/chain/chain_full.rs rename to client/rpc/src/chain/chain_full.rs index ad359a9300cdd..ff732368fe9d2 100644 --- a/core/rpc/src/chain/chain_full.rs +++ b/client/rpc/src/chain/chain_full.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,13 +19,10 @@ use std::sync::Arc; use rpc::futures::future::result; -use api::Subscriptions; -use client::{backend::Backend, CallExecutor, Client}; -use primitives::{H256, Blake2Hasher}; -use sr_primitives::{ - generic::{BlockId, SignedBlock}, - traits::{Block as BlockT}, -}; +use sc_rpc_api::Subscriptions; +use sc_client_api::{CallExecutor, backend::Backend}; +use sc_client::Client; +use sp_runtime::{generic::{BlockId, SignedBlock}, traits::{Block as BlockT}}; use super::{ChainBackend, client_err, error::FutureResult}; @@ -48,9 +45,9 @@ impl FullChain { } impl ChainBackend for FullChain where - Block: BlockT + 'static, - B: Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static, + Block: BlockT + 'static, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static, RA: Send + Sync + 'static, { fn client(&self) -> &Arc> { diff --git a/core/rpc/src/chain/chain_light.rs b/client/rpc/src/chain/chain_light.rs similarity index 84% rename from core/rpc/src/chain/chain_light.rs rename to client/rpc/src/chain/chain_light.rs index d969d6ca93702..3e26bd24bb090 100644 --- a/core/rpc/src/chain/chain_light.rs +++ b/client/rpc/src/chain/chain_light.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,19 +17,14 @@ //! Blockchain API backend for light nodes. use std::sync::Arc; -use futures03::{future::ready, FutureExt, TryFutureExt}; +use futures::{future::ready, FutureExt, TryFutureExt}; use rpc::futures::future::{result, Future, Either}; -use api::Subscriptions; -use client::{ - self, Client, - light::{ - fetcher::{Fetcher, RemoteBodyRequest}, - blockchain::RemoteBlockchain, - }, +use sc_rpc_api::Subscriptions; +use sc_client::{ + Client, light::{fetcher::{Fetcher, RemoteBodyRequest}, blockchain::RemoteBlockchain}, }; -use primitives::{H256, Blake2Hasher}; -use sr_primitives::{ +use sp_runtime::{ generic::{BlockId, SignedBlock}, traits::{Block as BlockT}, }; @@ -67,9 +62,9 @@ impl> LightChain } impl ChainBackend for LightChain where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: client::CallExecutor + Send + Sync + 'static, + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: sc_client::CallExecutor + Send + Sync + 'static, RA: Send + Sync + 'static, F: Fetcher + Send + Sync + 'static, { @@ -85,7 +80,7 @@ impl ChainBackend for LightChain. + +//! Substrate blockchain API. + +mod chain_full; +mod chain_light; + +#[cfg(test)] +mod tests; + +use std::sync::Arc; +use futures::{future, StreamExt, TryStreamExt}; +use log::warn; +use rpc::{ + Result as RpcResult, + futures::{stream, Future, Sink, Stream}, +}; + +use sc_rpc_api::Subscriptions; +use sc_client::{ + self, Client, BlockchainEvents, + light::{fetcher::Fetcher, blockchain::RemoteBlockchain}, +}; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use sp_rpc::{number::NumberOrHex, list::ListOrValue}; +use sp_runtime::{ + generic::{BlockId, SignedBlock}, + traits::{Block as BlockT, Header, NumberFor}, +}; + +use self::error::{Result, Error, FutureResult}; + +pub use sc_rpc_api::chain::*; + +/// Blockchain backend API +trait ChainBackend: Send + Sync + 'static + where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: sc_client::CallExecutor + Send + Sync + 'static, +{ + /// Get client reference. + fn client(&self) -> &Arc>; + + /// Get subscriptions reference. + fn subscriptions(&self) -> &Subscriptions; + + /// Tries to unwrap passed block hash, or uses best block hash otherwise. + fn unwrap_or_best(&self, hash: Option) -> Block::Hash { + match hash.into() { + None => self.client().chain_info().best_hash, + Some(hash) => hash, + } + } + + /// Get header of a relay chain block. + fn header(&self, hash: Option) -> FutureResult>; + + /// Get header and body of a relay chain block. + fn block(&self, hash: Option) -> FutureResult>>; + + /// Get hash of the n-th block in the canon chain. + /// + /// By default returns latest block hash. + fn block_hash( + &self, + number: Option>>, + ) -> Result> { + Ok(match number { + None => Some(self.client().chain_info().best_hash), + Some(num_or_hex) => self.client() + .header(&BlockId::number(num_or_hex.to_number()?)) + .map_err(client_err)? + .map(|h| h.hash()), + }) + } + + /// Get hash of the last finalized block in the canon chain. + fn finalized_head(&self) -> Result { + Ok(self.client().chain_info().finalized_hash) + } + + /// New head subscription + fn subscribe_new_heads( + &self, + _metadata: crate::metadata::Metadata, + subscriber: Subscriber, + ) { + subscribe_headers( + self.client(), + self.subscriptions(), + subscriber, + || self.client().chain_info().best_hash, + || self.client().import_notification_stream() + .filter(|notification| future::ready(notification.is_new_best)) + .map(|notification| Ok::<_, ()>(notification.header)) + .compat(), + ) + } + + /// Unsubscribe from new head subscription. + fn unsubscribe_new_heads( + &self, + _metadata: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions().cancel(id)) + } + + /// New head subscription + fn subscribe_finalized_heads( + &self, + _metadata: crate::metadata::Metadata, + subscriber: Subscriber, + ) { + subscribe_headers( + self.client(), + self.subscriptions(), + subscriber, + || self.client().chain_info().finalized_hash, + || self.client().finality_notification_stream() + .map(|notification| Ok::<_, ()>(notification.header)) + .compat(), + ) + } + + /// Unsubscribe from new head subscription. + fn unsubscribe_finalized_heads( + &self, + _metadata: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions().cancel(id)) + } +} + +/// Create new state API that works on full node. +pub fn new_full( + client: Arc>, + subscriptions: Subscriptions, +) -> Chain + where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: sc_client::CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, +{ + Chain { + backend: Box::new(self::chain_full::FullChain::new(client, subscriptions)), + } +} + +/// Create new state API that works on light node. +pub fn new_light>( + client: Arc>, + subscriptions: Subscriptions, + remote_blockchain: Arc>, + fetcher: Arc, +) -> Chain + where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: sc_client::CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + F: Send + Sync + 'static, +{ + Chain { + backend: Box::new(self::chain_light::LightChain::new( + client, + subscriptions, + remote_blockchain, + fetcher, + )), + } +} + +/// Chain API with subscriptions support. +pub struct Chain { + backend: Box>, +} + +impl ChainApi, Block::Hash, Block::Header, SignedBlock> for Chain where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: sc_client::CallExecutor + Send + Sync + 'static, + RA: Send + Sync + 'static +{ + type Metadata = crate::metadata::Metadata; + + fn header(&self, hash: Option) -> FutureResult> { + self.backend.header(hash) + } + + fn block(&self, hash: Option) -> FutureResult>> + { + self.backend.block(hash) + } + + fn block_hash( + &self, + number: Option>>> + ) -> Result>> { + match number { + None => self.backend.block_hash(None).map(ListOrValue::Value), + Some(ListOrValue::Value(number)) => self.backend.block_hash(Some(number)).map(ListOrValue::Value), + Some(ListOrValue::List(list)) => Ok(ListOrValue::List(list + .into_iter() + .map(|number| self.backend.block_hash(Some(number))) + .collect::>()? + )) + } + } + + fn finalized_head(&self) -> Result { + self.backend.finalized_head() + } + + fn subscribe_new_heads(&self, metadata: Self::Metadata, subscriber: Subscriber) { + self.backend.subscribe_new_heads(metadata, subscriber) + } + + fn unsubscribe_new_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult { + self.backend.unsubscribe_new_heads(metadata, id) + } + + fn subscribe_finalized_heads(&self, metadata: Self::Metadata, subscriber: Subscriber) { + self.backend.subscribe_finalized_heads(metadata, subscriber) + } + + fn unsubscribe_finalized_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult { + self.backend.unsubscribe_finalized_heads(metadata, id) + } +} + +/// Subscribe to new headers. +fn subscribe_headers( + client: &Arc>, + subscriptions: &Subscriptions, + subscriber: Subscriber, + best_block_hash: G, + stream: F, +) where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: sc_client::CallExecutor + Send + Sync + 'static, + F: FnOnce() -> S, + G: FnOnce() -> Block::Hash, + ERR: ::std::fmt::Debug, + S: Stream + Send + 'static, +{ + subscriptions.add(subscriber, |sink| { + // send current head right at the start. + let header = client.header(&BlockId::Hash(best_block_hash())) + .map_err(client_err) + .and_then(|header| { + header.ok_or_else(|| "Best header missing.".to_owned().into()) + }) + .map_err(Into::into); + + // send further subscriptions + let stream = stream() + .map(|res| Ok(res)) + .map_err(|e| warn!("Block notification stream error: {:?}", e)); + + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all( + stream::iter_result(vec![Ok(header)]) + .chain(stream) + ) + // we ignore the resulting Stream (if the first stream is over we are unsubscribed) + .map(|_| ()) + }); +} + +fn client_err(err: sp_blockchain::Error) -> Error { + Error::Client(Box::new(err)) +} diff --git a/client/rpc/src/chain/tests.rs b/client/rpc/src/chain/tests.rs new file mode 100644 index 0000000000000..eb05639018781 --- /dev/null +++ b/client/rpc/src/chain/tests.rs @@ -0,0 +1,249 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use super::*; +use assert_matches::assert_matches; +use substrate_test_runtime_client::{ + prelude::*, + sp_consensus::BlockOrigin, + runtime::{H256, Block, Header}, +}; +use sp_rpc::list::ListOrValue; + +#[test] +fn should_return_header() { + let core = tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + + let client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + + assert_matches!( + api.header(Some(client.genesis_hash()).into()).wait(), + Ok(Some(ref x)) if x == &Header { + parent_hash: H256::from_low_u64_be(0), + number: 0, + state_root: x.state_root.clone(), + extrinsics_root: + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), + digest: Default::default(), + } + ); + + assert_matches!( + api.header(None.into()).wait(), + Ok(Some(ref x)) if x == &Header { + parent_hash: H256::from_low_u64_be(0), + number: 0, + state_root: x.state_root.clone(), + extrinsics_root: + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), + digest: Default::default(), + } + ); + + assert_matches!(api.header(Some(H256::from_low_u64_be(5)).into()).wait(), Ok(None)); +} + +#[test] +fn should_return_a_block() { + let core = tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + let block_hash = block.hash(); + client.import(BlockOrigin::Own, block).unwrap(); + + // Genesis block is not justified + assert_matches!( + api.block(Some(client.genesis_hash()).into()).wait(), + Ok(Some(SignedBlock { justification: None, .. })) + ); + + assert_matches!( + api.block(Some(block_hash).into()).wait(), + Ok(Some(ref x)) if x.block == Block { + header: Header { + parent_hash: client.genesis_hash(), + number: 1, + state_root: x.block.header.state_root.clone(), + extrinsics_root: + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), + digest: Default::default(), + }, + extrinsics: vec![], + } + ); + + assert_matches!( + api.block(None.into()).wait(), + Ok(Some(ref x)) if x.block == Block { + header: Header { + parent_hash: client.genesis_hash(), + number: 1, + state_root: x.block.header.state_root.clone(), + extrinsics_root: + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), + digest: Default::default(), + }, + extrinsics: vec![], + } + ); + + assert_matches!( + api.block(Some(H256::from_low_u64_be(5)).into()).wait(), + Ok(None) + ); +} + +#[test] +fn should_return_block_hash() { + let core = ::tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + + assert_matches!( + api.block_hash(None.into()), + Ok(ListOrValue::Value(Some(ref x))) if x == &client.genesis_hash() + ); + + + assert_matches!( + api.block_hash(Some(ListOrValue::Value(0u64.into())).into()), + Ok(ListOrValue::Value(Some(ref x))) if x == &client.genesis_hash() + ); + + assert_matches!( + api.block_hash(Some(ListOrValue::Value(1u64.into())).into()), + Ok(ListOrValue::Value(None)) + ); + + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block.clone()).unwrap(); + + assert_matches!( + api.block_hash(Some(ListOrValue::Value(0u64.into())).into()), + Ok(ListOrValue::Value(Some(ref x))) if x == &client.genesis_hash() + ); + assert_matches!( + api.block_hash(Some(ListOrValue::Value(1u64.into())).into()), + Ok(ListOrValue::Value(Some(ref x))) if x == &block.hash() + ); + assert_matches!( + api.block_hash(Some(ListOrValue::Value(sp_core::U256::from(1u64).into())).into()), + Ok(ListOrValue::Value(Some(ref x))) if x == &block.hash() + ); + + assert_matches!( + api.block_hash(Some(vec![0u64.into(), 1.into(), 2.into()].into())), + Ok(ListOrValue::List(list)) if list == &[client.genesis_hash().into(), block.hash().into(), None] + ); +} + + +#[test] +fn should_return_finalized_hash() { + let core = ::tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + + assert_matches!( + api.finalized_head(), + Ok(ref x) if x == &client.genesis_hash() + ); + + // import new block + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + // no finalization yet + assert_matches!( + api.finalized_head(), + Ok(ref x) if x == &client.genesis_hash() + ); + + // finalize + client.finalize_block(BlockId::number(1), None).unwrap(); + assert_matches!( + api.finalized_head(), + Ok(ref x) if x == &client.block_hash(1).unwrap().unwrap() + ); +} + +#[test] +fn should_notify_about_latest_block() { + let mut core = ::tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + let (subscriber, id, transport) = Subscriber::new_test("test"); + + { + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + + api.subscribe_new_heads(Default::default(), subscriber); + + // assert id assigned + assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + } + + // assert initial head sent. + let (notification, next) = core.block_on(transport.into_future()).unwrap(); + assert!(notification.is_some()); + // assert notification sent to transport + let (notification, next) = core.block_on(next.into_future()).unwrap(); + assert!(notification.is_some()); + // no more notifications on this channel + assert_eq!(core.block_on(next.into_future()).unwrap().0, None); +} + +#[test] +fn should_notify_about_finalized_block() { + let mut core = ::tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + let (subscriber, id, transport) = Subscriber::new_test("test"); + + { + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + + api.subscribe_finalized_heads(Default::default(), subscriber); + + // assert id assigned + assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + client.finalize_block(BlockId::number(1), None).unwrap(); + } + + // assert initial head sent. + let (notification, next) = core.block_on(transport.into_future()).unwrap(); + assert!(notification.is_some()); + // assert notification sent to transport + let (notification, next) = core.block_on(next.into_future()).unwrap(); + assert!(notification.is_some()); + // no more notifications on this channel + assert_eq!(core.block_on(next.into_future()).unwrap().0, None); +} diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs new file mode 100644 index 0000000000000..3a226a6fb3f9b --- /dev/null +++ b/client/rpc/src/lib.rs @@ -0,0 +1,32 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate RPC implementation. +//! +//! A core implementation of Substrate RPC interfaces. + +#![warn(missing_docs)] + +mod metadata; + +pub use sc_rpc_api::Subscriptions; +pub use self::metadata::Metadata; +pub use rpc::IoHandlerExtension as RpcExtension; + +pub mod author; +pub mod chain; +pub mod state; +pub mod system; diff --git a/client/rpc/src/metadata.rs b/client/rpc/src/metadata.rs new file mode 100644 index 0000000000000..d35653f8e6278 --- /dev/null +++ b/client/rpc/src/metadata.rs @@ -0,0 +1,60 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! RPC Metadata +use std::sync::Arc; + +use jsonrpc_pubsub::{Session, PubSubMetadata}; +use rpc::futures::sync::mpsc; + +/// RPC Metadata. +/// +/// Manages persistent session for transports that support it +/// and may contain some additional info extracted from specific transports +/// (like remote client IP address, request headers, etc) +#[derive(Default, Clone)] +pub struct Metadata { + session: Option>, +} + +impl rpc::Metadata for Metadata {} +impl PubSubMetadata for Metadata { + fn session(&self) -> Option> { + self.session.clone() + } +} + +impl Metadata { + /// Create new `Metadata` with session (Pub/Sub) support. + pub fn new(transport: mpsc::Sender) -> Self { + Metadata { + session: Some(Arc::new(Session::new(transport))), + } + } + + /// Create new `Metadata` for tests. + #[cfg(test)] + pub fn new_test() -> (mpsc::Receiver, Self) { + let (tx, rx) = mpsc::channel(1); + (rx, Self::new(tx)) + } +} + +impl From> for Metadata { + fn from(sender: mpsc::Sender) -> Self { + Self::new(sender) + } +} diff --git a/client/rpc/src/state/mod.rs b/client/rpc/src/state/mod.rs new file mode 100644 index 0000000000000..f8f8fe4223a51 --- /dev/null +++ b/client/rpc/src/state/mod.rs @@ -0,0 +1,354 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate state API. + +mod state_full; +mod state_light; + +#[cfg(test)] +mod tests; + +use std::sync::Arc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use rpc::{Result as RpcResult, futures::Future}; + +use sc_rpc_api::Subscriptions; +use sc_client::{Client, CallExecutor, light::{blockchain::RemoteBlockchain, fetcher::Fetcher}}; +use sp_core::{Bytes, storage::{StorageKey, StorageData, StorageChangeSet}}; +use sp_version::RuntimeVersion; +use sp_runtime::traits::Block as BlockT; + +use sp_api::{Metadata, ProvideRuntimeApi}; + +use self::error::{Error, FutureResult}; + +pub use sc_rpc_api::state::*; + +/// State backend API. +pub trait StateBackend: Send + Sync + 'static + where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: sc_client::CallExecutor + Send + Sync + 'static, + RA: Send + Sync + 'static, +{ + /// Call runtime method at given block. + fn call( + &self, + block: Option, + method: String, + call_data: Bytes, + ) -> FutureResult; + + /// Returns the keys with prefix, leave empty to get all the keys. + fn storage_keys( + &self, + block: Option, + prefix: StorageKey, + ) -> FutureResult>; + + /// Returns a storage entry at a specific block's state. + fn storage( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult>; + + /// Returns the hash of a storage entry at a block's state. + fn storage_hash( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult>; + + /// Returns the size of a storage entry at a block's state. + fn storage_size( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult> { + Box::new(self.storage(block, key) + .map(|x| x.map(|x| x.0.len() as u64))) + } + + /// Returns the keys with prefix from a child storage, leave empty to get all the keys + fn child_storage_keys( + &self, + block: Option, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + prefix: StorageKey, + ) -> FutureResult>; + + /// Returns a child storage entry at a specific block's state. + fn child_storage( + &self, + block: Option, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + ) -> FutureResult>; + + /// Returns the hash of a child storage entry at a block's state. + fn child_storage_hash( + &self, + block: Option, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + ) -> FutureResult>; + + /// Returns the size of a child storage entry at a block's state. + fn child_storage_size( + &self, + block: Option, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + ) -> FutureResult> { + Box::new(self.child_storage(block, child_storage_key, child_info, child_type, key) + .map(|x| x.map(|x| x.0.len() as u64))) + } + + /// Returns the runtime metadata as an opaque blob. + fn metadata(&self, block: Option) -> FutureResult; + + /// Get the runtime version. + fn runtime_version(&self, block: Option) -> FutureResult; + + /// Query historical storage entries (by key) starting from a block given as the second parameter. + /// + /// NOTE This first returned result contains the initial state of storage for all keys. + /// Subsequent values in the vector represent changes to the previous state (diffs). + fn query_storage( + &self, + from: Block::Hash, + to: Option, + keys: Vec, + ) -> FutureResult>>; + + /// New runtime version subscription + fn subscribe_runtime_version( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber, + ); + + /// Unsubscribe from runtime version subscription + fn unsubscribe_runtime_version( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult; + + /// New storage subscription + fn subscribe_storage( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber>, + keys: Option>, + ); + + /// Unsubscribe from storage subscription + fn unsubscribe_storage( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult; +} + +/// Create new state API that works on full node. +pub fn new_full( + client: Arc>, + subscriptions: Subscriptions, +) -> State + where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + Metadata, +{ + State { + backend: Box::new(self::state_full::FullState::new(client, subscriptions)), + } +} + +/// Create new state API that works on light node. +pub fn new_light>( + client: Arc>, + subscriptions: Subscriptions, + remote_blockchain: Arc>, + fetcher: Arc, +) -> State + where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + F: Send + Sync + 'static, +{ + State { + backend: Box::new(self::state_light::LightState::new( + client, + subscriptions, + remote_blockchain, + fetcher, + )), + } +} + +/// State API with subscriptions support. +pub struct State { + backend: Box>, +} + +impl StateApi for State + where + Block: BlockT + 'static, + B: sc_client_api::backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, +{ + type Metadata = crate::metadata::Metadata; + + fn call(&self, method: String, data: Bytes, block: Option) -> FutureResult { + self.backend.call(block, method, data) + } + + fn storage_keys( + &self, + key_prefix: StorageKey, + block: Option, + ) -> FutureResult> { + self.backend.storage_keys(block, key_prefix) + } + + fn storage(&self, key: StorageKey, block: Option) -> FutureResult> { + self.backend.storage(block, key) + } + + fn storage_hash(&self, key: StorageKey, block: Option) -> FutureResult> { + self.backend.storage_hash(block, key) + } + + fn storage_size(&self, key: StorageKey, block: Option) -> FutureResult> { + self.backend.storage_size(block, key) + } + + fn child_storage( + &self, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + block: Option + ) -> FutureResult> { + self.backend.child_storage(block, child_storage_key, child_info, child_type, key) + } + + fn child_storage_keys( + &self, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key_prefix: StorageKey, + block: Option + ) -> FutureResult> { + self.backend.child_storage_keys(block, child_storage_key, child_info, child_type, key_prefix) + } + + fn child_storage_hash( + &self, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + block: Option + ) -> FutureResult> { + self.backend.child_storage_hash(block, child_storage_key, child_info, child_type, key) + } + + fn child_storage_size( + &self, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + block: Option + ) -> FutureResult> { + self.backend.child_storage_size(block, child_storage_key, child_info, child_type, key) + } + + fn metadata(&self, block: Option) -> FutureResult { + self.backend.metadata(block) + } + + fn query_storage( + &self, + keys: Vec, + from: Block::Hash, + to: Option + ) -> FutureResult>> { + self.backend.query_storage(from, to, keys) + } + + fn subscribe_storage( + &self, + meta: Self::Metadata, + subscriber: Subscriber>, + keys: Option> + ) { + self.backend.subscribe_storage(meta, subscriber, keys); + } + + fn unsubscribe_storage(&self, meta: Option, id: SubscriptionId) -> RpcResult { + self.backend.unsubscribe_storage(meta, id) + } + + fn runtime_version(&self, at: Option) -> FutureResult { + self.backend.runtime_version(at) + } + + fn subscribe_runtime_version(&self, meta: Self::Metadata, subscriber: Subscriber) { + self.backend.subscribe_runtime_version(meta, subscriber); + } + + fn unsubscribe_runtime_version( + &self, + meta: Option, + id: SubscriptionId, + ) -> RpcResult { + self.backend.unsubscribe_runtime_version(meta, id) + } +} + +fn client_err(err: sp_blockchain::Error) -> Error { + Error::Client(Box::new(err)) +} + +const CHILD_RESOLUTION_ERROR: &str = "Unexpected child info and type"; + +fn child_resolution_error() -> sp_blockchain::Error { + sp_blockchain::Error::Msg(CHILD_RESOLUTION_ERROR.to_string()) +} diff --git a/client/rpc/src/state/state_full.rs b/client/rpc/src/state/state_full.rs new file mode 100644 index 0000000000000..e42e6b722e49f --- /dev/null +++ b/client/rpc/src/state/state_full.rs @@ -0,0 +1,540 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! State API backend for full nodes. + +use std::collections::{BTreeMap, HashMap}; +use std::sync::Arc; +use std::ops::Range; +use futures::{future, StreamExt as _, TryStreamExt as _}; +use log::warn; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use rpc::{Result as RpcResult, futures::{stream, Future, Sink, Stream, future::result}}; + +use sc_rpc_api::Subscriptions; +use sc_client_api::backend::Backend; +use sp_blockchain::{ + Result as ClientResult, Error as ClientError, HeaderMetadata, CachedHeaderMetadata +}; +use sc_client::{ + Client, CallExecutor, BlockchainEvents, +}; +use sp_core::{ + Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet, ChildInfo}, +}; +use sp_version::RuntimeVersion; +use sp_state_machine::ExecutionStrategy; +use sp_runtime::{ + generic::BlockId, traits::{Block as BlockT, NumberFor, SaturatedConversion}, +}; + +use sp_api::{Metadata, ProvideRuntimeApi}; + +use super::{StateBackend, error::{FutureResult, Error, Result}, client_err, child_resolution_error}; + +/// Ranges to query in state_queryStorage. +struct QueryStorageRange { + /// Hashes of all the blocks in the range. + pub hashes: Vec, + /// Number of the first block in the range. + pub first_number: NumberFor, + /// Blocks subrange ([begin; end) indices within `hashes`) where we should read keys at + /// each state to get changes. + pub unfiltered_range: Range, + /// Blocks subrange ([begin; end) indices within `hashes`) where we could pre-filter + /// blocks-with-changes by using changes tries. + pub filtered_range: Option>, +} + +/// State API backend for full nodes. +pub struct FullState { + client: Arc>, + subscriptions: Subscriptions, +} + +impl FullState + where + Block: BlockT + 'static, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, +{ + /// Create new state API backend for full nodes. + pub fn new(client: Arc>, subscriptions: Subscriptions) -> Self { + Self { client, subscriptions } + } + + /// Returns given block hash or best block hash if None is passed. + fn block_or_best(&self, hash: Option) -> ClientResult { + Ok(hash.unwrap_or_else(|| self.client.chain_info().best_hash)) + } + + /// Splits the `query_storage` block range into 'filtered' and 'unfiltered' subranges. + /// Blocks that contain changes within filtered subrange could be filtered using changes tries. + /// Blocks that contain changes within unfiltered subrange must be filtered manually. + fn split_query_storage_range( + &self, + from: Block::Hash, + to: Option + ) -> Result> { + let to = self.block_or_best(to).map_err(|e| invalid_block::(from, to, e.to_string()))?; + + let invalid_block_err = |e: ClientError| invalid_block::(from, Some(to), e.to_string()); + let from_meta = self.client.header_metadata(from).map_err(invalid_block_err)?; + let to_meta = self.client.header_metadata(to).map_err(invalid_block_err)?; + + if from_meta.number >= to_meta.number { + return Err(invalid_block_range(&from_meta, &to_meta, "from number >= to number".to_owned())) + } + + // check if we can get from `to` to `from` by going through parent_hashes. + let from_number = from_meta.number; + let hashes = { + let mut hashes = vec![to_meta.hash]; + let mut last = to_meta.clone(); + while last.number > from_number { + let header_metadata = self.client + .header_metadata(last.parent) + .map_err(|e| invalid_block_range::(&last, &to_meta, e.to_string()))?; + hashes.push(header_metadata.hash); + last = header_metadata; + } + if last.hash != from_meta.hash { + return Err(invalid_block_range(&from_meta, &to_meta, "from and to are on different forks".to_owned())) + } + hashes.reverse(); + hashes + }; + + // 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_meta.hash)) + .map_err(client_err)?; + let filtered_range_begin = changes_trie_range + .map(|(begin, _)| (begin - from_number).saturated_into::()); + let (unfiltered_range, filtered_range) = split_range(hashes.len(), filtered_range_begin); + + Ok(QueryStorageRange { + hashes, + first_number: from_number, + unfiltered_range, + filtered_range, + }) + } + + /// Iterates through range.unfiltered_range and check each block for changes of keys' values. + fn query_storage_unfiltered( + &self, + range: &QueryStorageRange, + keys: &[StorageKey], + last_values: &mut HashMap>, + changes: &mut Vec>, + ) -> Result<()> { + for block in range.unfiltered_range.start..range.unfiltered_range.end { + let block_hash = range.hashes[block].clone(); + let mut block_changes = StorageChangeSet { block: block_hash.clone(), changes: Vec::new() }; + let id = BlockId::hash(block_hash); + for key in keys { + let (has_changed, data) = { + let curr_data = self.client.storage(&id, key).map_err(client_err)?; + match last_values.get(key) { + Some(prev_data) => (curr_data != *prev_data, curr_data), + None => (true, curr_data), + } + }; + if has_changed { + block_changes.changes.push((key.clone(), data.clone())); + } + last_values.insert(key.clone(), data); + } + if !block_changes.changes.is_empty() { + changes.push(block_changes); + } + } + Ok(()) + } + + /// Iterates through all blocks that are changing keys within range.filtered_range and collects these changes. + fn query_storage_filtered( + &self, + range: &QueryStorageRange, + keys: &[StorageKey], + last_values: &HashMap>, + changes: &mut Vec>, + ) -> Result<()> { + let (begin, end) = match range.filtered_range { + Some(ref filtered_range) => ( + range.first_number + filtered_range.start.saturated_into(), + BlockId::Hash(range.hashes[filtered_range.end - 1].clone()) + ), + None => return Ok(()), + }; + let mut changes_map: BTreeMap, StorageChangeSet> = BTreeMap::new(); + for key in keys { + let mut last_block = None; + let mut last_value = last_values.get(key).cloned().unwrap_or_default(); + let key_changes = self.client.key_changes(begin, end, None, key).map_err(client_err)?; + for (block, _) in key_changes.into_iter().rev() { + if last_block == Some(block) { + continue; + } + + let block_hash = range.hashes[(block - range.first_number).saturated_into::()].clone(); + let id = BlockId::Hash(block_hash); + let value_at_block = self.client.storage(&id, key).map_err(client_err)?; + if last_value == value_at_block { + continue; + } + + changes_map.entry(block) + .or_insert_with(|| StorageChangeSet { block: block_hash, changes: Vec::new() }) + .changes.push((key.clone(), value_at_block.clone())); + last_block = Some(block); + last_value = value_at_block; + } + } + if let Some(additional_capacity) = changes_map.len().checked_sub(changes.len()) { + changes.reserve(additional_capacity); + } + changes.extend(changes_map.into_iter().map(|(_, cs)| cs)); + Ok(()) + } +} + +impl StateBackend for FullState + where + Block: BlockT + 'static, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + Metadata, +{ + fn call( + &self, + block: Option, + method: String, + call_data: Bytes, + ) -> FutureResult { + Box::new(result( + self.block_or_best(block) + .and_then(|block| + self + .client + .executor() + .call( + &BlockId::Hash(block), + &method, + &*call_data, + ExecutionStrategy::NativeElseWasm, + None, + ) + .map(Into::into)) + .map_err(client_err))) + } + + fn storage_keys( + &self, + block: Option, + prefix: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.storage_keys(&BlockId::Hash(block), &prefix)) + .map_err(client_err))) + } + + fn storage( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.storage(&BlockId::Hash(block), &key)) + .map_err(client_err))) + } + + fn storage_hash( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.storage_hash(&BlockId::Hash(block), &key)) + .map_err(client_err))) + } + + fn child_storage_keys( + &self, + block: Option, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + prefix: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.child_storage_keys( + &BlockId::Hash(block), + &child_storage_key, + ChildInfo::resolve_child_info(child_type, &child_info.0[..]) + .ok_or_else(child_resolution_error)?, + &prefix, + )) + .map_err(client_err))) + } + + fn child_storage( + &self, + block: Option, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.child_storage( + &BlockId::Hash(block), + &child_storage_key, + ChildInfo::resolve_child_info(child_type, &child_info.0[..]) + .ok_or_else(child_resolution_error)?, + &key, + )) + .map_err(client_err))) + } + + fn child_storage_hash( + &self, + block: Option, + child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.child_storage_hash( + &BlockId::Hash(block), + &child_storage_key, + ChildInfo::resolve_child_info(child_type, &child_info.0[..]) + .ok_or_else(child_resolution_error)?, + &key, + )) + .map_err(client_err))) + } + + fn metadata(&self, block: Option) -> FutureResult { + Box::new(result( + self.block_or_best(block) + .and_then(|block| + self.client.runtime_api().metadata(&BlockId::Hash(block)).map(Into::into) + ) + .map_err(client_err))) + } + + fn runtime_version(&self, block: Option) -> FutureResult { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.runtime_version_at(&BlockId::Hash(block))) + .map_err(client_err))) + } + + fn query_storage( + &self, + from: Block::Hash, + to: Option, + keys: Vec, + ) -> FutureResult>> { + let call_fn = move || { + let range = self.split_query_storage_range(from, to)?; + let mut changes = Vec::new(); + let mut last_values = HashMap::new(); + self.query_storage_unfiltered(&range, &keys, &mut last_values, &mut changes)?; + self.query_storage_filtered(&range, &keys, &last_values, &mut changes)?; + Ok(changes) + }; + Box::new(result(call_fn())) + } + + fn subscribe_runtime_version( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber, + ) { + let stream = match self.client.storage_changes_notification_stream( + Some(&[StorageKey(well_known_keys::CODE.to_vec())]), + None, + ) { + Ok(stream) => stream, + Err(err) => { + let _ = subscriber.reject(Error::from(client_err(err)).into()); + return; + } + }; + + self.subscriptions.add(subscriber, |sink| { + let version = self.runtime_version(None.into()) + .map_err(Into::into) + .wait(); + + let client = self.client.clone(); + let mut previous_version = version.clone(); + + let stream = stream + .filter_map(move |_| { + let info = client.chain_info(); + let version = client + .runtime_version_at(&BlockId::hash(info.best_hash)) + .map_err(client_err) + .map_err(Into::into); + if previous_version != version { + previous_version = version.clone(); + future::ready(Some(Ok::<_, ()>(version))) + } else { + future::ready(None) + } + }) + .compat(); + + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all( + stream::iter_result(vec![Ok(version)]) + .chain(stream) + ) + // we ignore the resulting Stream (if the first stream is over we are unsubscribed) + .map(|_| ()) + }); + } + + fn unsubscribe_runtime_version( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions.cancel(id)) + } + + fn subscribe_storage( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber>, + keys: Option>, + ) { + let keys = Into::>>::into(keys); + let stream = match self.client.storage_changes_notification_stream( + keys.as_ref().map(|x| &**x), + None + ) { + Ok(stream) => stream, + Err(err) => { + let _ = subscriber.reject(client_err(err).into()); + return; + }, + }; + + // initial values + let initial = stream::iter_result(keys + .map(|keys| { + let block = self.client.chain_info().best_hash; + let changes = keys + .into_iter() + .map(|key| self.storage(Some(block.clone()).into(), key.clone()) + .map(|val| (key.clone(), val)) + .wait() + .unwrap_or_else(|_| (key, None)) + ) + .collect(); + vec![Ok(Ok(StorageChangeSet { block, changes }))] + }).unwrap_or_default()); + + self.subscriptions.add(subscriber, |sink| { + let stream = stream + .map(|(block, changes)| Ok::<_, ()>(Ok(StorageChangeSet { + block, + changes: changes.iter() + .filter_map(|(o_sk, k, v)| if o_sk.is_none() { + Some((k.clone(),v.cloned())) + } else { None }).collect(), + }))) + .compat(); + + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all(initial.chain(stream)) + // we ignore the resulting Stream (if the first stream is over we are unsubscribed) + .map(|_| ()) + }); + } + + fn unsubscribe_storage( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions.cancel(id)) + } +} + +/// Splits passed range into two subranges where: +/// - first range has at least one element in it; +/// - second range (optionally) starts at given `middle` element. +pub(crate) fn split_range(size: usize, middle: Option) -> (Range, Option>) { + // check if we can filter blocks-with-changes from some (sub)range using changes tries + let range2_begin = match middle { + // some of required changes tries are pruned => use available tries + Some(middle) if middle != 0 => Some(middle), + // all required changes tries are available, but we still want values at first block + // => do 'unfiltered' read for the first block and 'filtered' for the rest + Some(_) if size > 1 => Some(1), + // range contains single element => do not use changes tries + Some(_) => None, + // changes tries are not available => do 'unfiltered' read for the whole range + None => None, + }; + let range1 = 0..range2_begin.unwrap_or(size); + let range2 = range2_begin.map(|begin| begin..size); + (range1, range2) +} + +fn invalid_block_range( + from: &CachedHeaderMetadata, + to: &CachedHeaderMetadata, + details: String, +) -> Error { + let to_string = |h: &CachedHeaderMetadata| format!("{} ({:?})", h.number, h.hash); + + Error::InvalidBlockRange { + from: to_string(from), + to: to_string(to), + details, + } +} + +fn invalid_block( + from: B::Hash, + to: Option, + details: String, +) -> Error { + Error::InvalidBlockRange { + from: format!("{:?}", from), + to: format!("{:?}", to), + details, + } +} diff --git a/core/rpc/src/state/state_light.rs b/client/rpc/src/state/state_light.rs similarity index 93% rename from core/rpc/src/state/state_light.rs rename to client/rpc/src/state/state_light.rs index 3d0c7979e3995..abf4631bb82eb 100644 --- a/core/rpc/src/state/state_light.rs +++ b/client/rpc/src/state/state_light.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ use std::{ collections::{HashSet, HashMap, hash_map::Entry}, }; use codec::Decode; -use futures03::{ +use futures::{ future::{ready, Either}, channel::oneshot::{channel, Sender}, FutureExt, TryFutureExt, @@ -38,24 +38,21 @@ use rpc::{ futures::stream::Stream, }; -use api::Subscriptions; -use client::{ - BlockchainEvents, Client, CallExecutor, backend::Backend, - error::Error as ClientError, +use sc_rpc_api::Subscriptions; +use sc_client_api::backend::Backend; +use sp_blockchain::Error as ClientError; +use sc_client::{ + BlockchainEvents, Client, CallExecutor, light::{ blockchain::{future_header, RemoteBlockchain}, fetcher::{Fetcher, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest}, }, }; -use primitives::{ - H256, Blake2Hasher, Bytes, OpaqueMetadata, - storage::{StorageKey, StorageData, StorageChangeSet}, -}; -use runtime_version::RuntimeVersion; -use sr_primitives::{ - generic::BlockId, - traits::Block as BlockT, +use sp_core::{ + Bytes, OpaqueMetadata, storage::{StorageKey, StorageData, StorageChangeSet}, }; +use sp_version::RuntimeVersion; +use sp_runtime::{generic::BlockId, traits::{Block as BlockT, HasherFor}}; use super::{StateBackend, error::{FutureResult, Error}, client_err}; @@ -139,9 +136,9 @@ impl SharedRequests for SimpleSubscriptions where impl + 'static, B, E, RA> LightState where - Block: BlockT, - B: Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static + Clone, + Block: BlockT, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, RA: Send + Sync + 'static, { /// Create new state API backend for light nodes. @@ -167,15 +164,15 @@ impl + 'static, B, E, RA> LightState) -> Block::Hash { - hash.unwrap_or_else(|| self.client.info().chain.best_hash) + hash.unwrap_or_else(|| self.client.chain_info().best_hash) } } impl StateBackend for LightState where - Block: BlockT, - B: Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static + Clone, + Block: BlockT, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, RA: Send + Sync + 'static, F: Fetcher + 'static { @@ -226,7 +223,7 @@ impl StateBackend for LightState::hash(&storage.0)))) ) ) } @@ -235,6 +232,8 @@ impl StateBackend for LightState, _child_storage_key: StorageKey, + _child_info: StorageKey, + _child_type: u32, _prefix: StorageKey, ) -> FutureResult> { Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient)))) @@ -244,6 +243,8 @@ impl StateBackend for LightState, child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, key: StorageKey, ) -> FutureResult> { let block = self.block_or_best(block); @@ -254,6 +255,8 @@ impl StateBackend for LightState StateBackend for LightState, child_storage_key: StorageKey, + child_info: StorageKey, + child_type: u32, key: StorageKey, ) -> FutureResult> { Box::new(self - .child_storage(block, child_storage_key, key) + .child_storage(block, child_storage_key, child_info, child_type, key) .and_then(|maybe_storage| - result(Ok(maybe_storage.map(|storage| Blake2Hasher::hash(&storage.0)))) + result(Ok(maybe_storage.map(|storage| HasherFor::::hash(&storage.0)))) ) ) } @@ -546,7 +551,8 @@ fn runtime_version>( Bytes(Vec::new()), ) .then(|version| ready(version.and_then(|version| - Decode::decode(&mut &version.0[..]).map_err(|_| client_err(ClientError::VersionInvalid)) + Decode::decode(&mut &version.0[..]) + .map_err(|e| client_err(ClientError::VersionInvalid(e.what().into()))) ))) } @@ -592,7 +598,7 @@ fn subscription_stream< issue_request: IssueRequest, compare_values: CompareValues, ) -> impl Stream where - Block: BlockT, + Block: BlockT, Requests: 'static + SharedRequests, FutureBlocksStream: Stream, V: Send + 'static + Clone, @@ -695,13 +701,14 @@ fn ignore_error(future: F) -> impl std::future::Future Ok(Some(result)), Err(()) => Ok(None), - })) + })) } #[cfg(test)] mod tests { use rpc::futures::stream::futures_ordered; - use test_client::runtime::Block; + use substrate_test_runtime_client::runtime::Block; + use sp_core::H256; use super::*; #[test] @@ -752,7 +759,7 @@ mod tests { #[test] fn maybe_share_remote_request_shares_request() { - type UnreachableFuture = futures03::future::Ready>; + type UnreachableFuture = futures::future::Ready>; let shared_requests = SimpleSubscriptions::default(); diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs new file mode 100644 index 0000000000000..5951ee86a93ce --- /dev/null +++ b/client/rpc/src/state/tests.rs @@ -0,0 +1,443 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use super::*; +use super::state_full::split_range; +use self::error::Error; + +use std::sync::Arc; +use assert_matches::assert_matches; +use futures01::stream::Stream; +use sp_core::storage::{well_known_keys, ChildInfo}; +use sp_core::hash::H256; +use sp_io::hashing::blake2_256; +use substrate_test_runtime_client::{ + prelude::*, + sp_consensus::BlockOrigin, + runtime, +}; + +const CHILD_INFO: ChildInfo<'static> = ChildInfo::new_default(b"unique_id"); + +#[test] +fn should_return_storage() { + const KEY: &[u8] = b":mock"; + const VALUE: &[u8] = b"hello world"; + const STORAGE_KEY: &[u8] = b":child_storage:default:child"; + const CHILD_VALUE: &[u8] = b"hello world !"; + + let mut core = tokio::runtime::Runtime::new().unwrap(); + let client = TestClientBuilder::new() + .add_extra_storage(KEY.to_vec(), VALUE.to_vec()) + .add_extra_child_storage(STORAGE_KEY.to_vec(), CHILD_INFO, KEY.to_vec(), CHILD_VALUE.to_vec()) + .build(); + let genesis_hash = client.genesis_hash(); + let client = new_full(Arc::new(client), Subscriptions::new(Arc::new(core.executor()))); + let key = StorageKey(KEY.to_vec()); + let storage_key = StorageKey(STORAGE_KEY.to_vec()); + let (child_info, child_type) = CHILD_INFO.info(); + let child_info = StorageKey(child_info.to_vec()); + + assert_eq!( + client.storage(key.clone(), Some(genesis_hash).into()).wait() + .map(|x| x.map(|x| x.0.len())).unwrap().unwrap() as usize, + VALUE.len(), + ); + assert_matches!( + client.storage_hash(key.clone(), Some(genesis_hash).into()).wait() + .map(|x| x.is_some()), + Ok(true) + ); + assert_eq!( + client.storage_size(key.clone(), None).wait().unwrap().unwrap() as usize, + VALUE.len(), + ); + assert_eq!( + core.block_on( + client.child_storage(storage_key, child_info, child_type, key, Some(genesis_hash).into()) + .map(|x| x.map(|x| x.0.len())) + ).unwrap().unwrap() as usize, + CHILD_VALUE.len(), + ); + +} + +#[test] +fn should_return_child_storage() { + let (child_info, child_type) = CHILD_INFO.info(); + let child_info = StorageKey(child_info.to_vec()); + let core = tokio::runtime::Runtime::new().unwrap(); + let client = Arc::new(substrate_test_runtime_client::TestClientBuilder::new() + .add_child_storage("test", "key", CHILD_INFO, vec![42_u8]) + .build()); + let genesis_hash = client.genesis_hash(); + let client = new_full(client, Subscriptions::new(Arc::new(core.executor()))); + let child_key = StorageKey( + well_known_keys::CHILD_STORAGE_KEY_PREFIX.iter().chain(b"test").cloned().collect() + ); + let key = StorageKey(b"key".to_vec()); + + + assert_matches!( + client.child_storage( + child_key.clone(), + child_info.clone(), + child_type, + key.clone(), + Some(genesis_hash).into(), + ).wait(), + Ok(Some(StorageData(ref d))) if d[0] == 42 && d.len() == 1 + ); + assert_matches!( + client.child_storage_hash( + child_key.clone(), + child_info.clone(), + child_type, + key.clone(), + Some(genesis_hash).into(), + ).wait().map(|x| x.is_some()), + Ok(true) + ); + assert_matches!( + client.child_storage_size( + child_key.clone(), + child_info.clone(), + child_type, + key.clone(), + None, + ).wait(), + Ok(Some(1)) + ); +} + +#[test] +fn should_call_contract() { + let core = tokio::runtime::Runtime::new().unwrap(); + let client = Arc::new(substrate_test_runtime_client::new()); + let genesis_hash = client.genesis_hash(); + let client = new_full(client, Subscriptions::new(Arc::new(core.executor()))); + + assert_matches!( + client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()).wait(), + Err(Error::Client(_)) + ) +} + +#[test] +fn should_notify_about_storage_changes() { + let mut core = tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + let (subscriber, id, transport) = Subscriber::new_test("test"); + + { + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + + api.subscribe_storage(Default::default(), subscriber, None.into()); + + // assert id assigned + assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push_transfer(runtime::Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 42, + nonce: 0, + }).unwrap(); + let block = builder.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + } + + // assert notification sent to transport + let (notification, next) = core.block_on(transport.into_future()).unwrap(); + assert!(notification.is_some()); + // no more notifications on this channel + assert_eq!(core.block_on(next.into_future()).unwrap().0, None); +} + +#[test] +fn should_send_initial_storage_changes_and_notifications() { + let mut core = tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + let (subscriber, id, transport) = Subscriber::new_test("test"); + + { + let mut client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); + + let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())); + + api.subscribe_storage(Default::default(), subscriber, Some(vec![ + StorageKey(alice_balance_key.to_vec()), + ]).into()); + + // assert id assigned + assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push_transfer(runtime::Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 42, + nonce: 0, + }).unwrap(); + let block = builder.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + } + + // assert initial values sent to transport + let (notification, next) = core.block_on(transport.into_future()).unwrap(); + assert!(notification.is_some()); + // assert notification sent to transport + let (notification, next) = core.block_on(next.into_future()).unwrap(); + assert!(notification.is_some()); + // no more notifications on this channel + assert_eq!(core.block_on(next.into_future()).unwrap().0, None); +} + +#[test] +fn should_query_storage() { + fn run_tests(mut client: Arc) { + let core = tokio::runtime::Runtime::new().unwrap(); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + + let mut add_block = |nonce| { + let mut builder = client.new_block(Default::default()).unwrap(); + // fake change: None -> None -> None + builder.push_storage_change(vec![1], None).unwrap(); + // fake change: None -> Some(value) -> Some(value) + builder.push_storage_change(vec![2], Some(vec![2])).unwrap(); + // actual change: None -> Some(value) -> None + builder.push_storage_change(vec![3], if nonce == 0 { Some(vec![3]) } else { None }).unwrap(); + // actual change: None -> Some(value) + builder.push_storage_change(vec![4], if nonce == 0 { None } else { Some(vec![4]) }).unwrap(); + // actual change: Some(value1) -> Some(value2) + builder.push_storage_change(vec![5], Some(vec![nonce as u8])).unwrap(); + let block = builder.build().unwrap().block; + 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 mut expected = vec![ + StorageChangeSet { + block: genesis_hash, + changes: vec![ + (StorageKey(vec![1]), None), + (StorageKey(vec![2]), None), + (StorageKey(vec![3]), None), + (StorageKey(vec![4]), None), + (StorageKey(vec![5]), None), + ], + }, + StorageChangeSet { + block: block1_hash, + changes: vec![ + (StorageKey(vec![2]), Some(StorageData(vec![2]))), + (StorageKey(vec![3]), Some(StorageData(vec![3]))), + (StorageKey(vec![5]), Some(StorageData(vec![0]))), + ], + }, + ]; + + // Query changes only up to block1 + let keys = (1..6).map(|k| StorageKey(vec![k])).collect::>(); + let result = api.query_storage( + keys.clone(), + genesis_hash, + Some(block1_hash).into(), + ); + + assert_eq!(result.wait().unwrap(), expected); + + // Query all changes + let result = api.query_storage( + keys.clone(), + genesis_hash, + None.into(), + ); + + expected.push(StorageChangeSet { + block: block2_hash, + changes: vec![ + (StorageKey(vec![3]), None), + (StorageKey(vec![4]), Some(StorageData(vec![4]))), + (StorageKey(vec![5]), Some(StorageData(vec![1]))), + ], + }); + assert_eq!(result.wait().unwrap(), expected); + + // Query changes up to block2. + let result = api.query_storage( + keys.clone(), + genesis_hash, + Some(block2_hash), + ); + + assert_eq!(result.wait().unwrap(), expected); + + // Inverted range. + let result = api.query_storage( + keys.clone(), + block1_hash, + Some(genesis_hash), + ); + + assert_eq!( + result.wait().map_err(|e| e.to_string()), + Err(Error::InvalidBlockRange { + from: format!("1 ({:?})", block1_hash), + to: format!("0 ({:?})", genesis_hash), + details: "from number >= to number".to_owned(), + }).map_err(|e| e.to_string()) + ); + + let random_hash1 = H256::random(); + let random_hash2 = H256::random(); + + // Invalid second hash. + let result = api.query_storage( + keys.clone(), + genesis_hash, + Some(random_hash1), + ); + + assert_eq!( + result.wait().map_err(|e| e.to_string()), + Err(Error::InvalidBlockRange { + from: format!("{:?}", genesis_hash), + to: format!("{:?}", Some(random_hash1)), + details: format!("UnknownBlock: header not found in db: {}", random_hash1), + }).map_err(|e| e.to_string()) + ); + + // Invalid first hash with Some other hash. + let result = api.query_storage( + keys.clone(), + random_hash1, + Some(genesis_hash), + ); + + assert_eq!( + result.wait().map_err(|e| e.to_string()), + Err(Error::InvalidBlockRange { + from: format!("{:?}", random_hash1), + to: format!("{:?}", Some(genesis_hash)), + details: format!("UnknownBlock: header not found in db: {}", random_hash1), + }).map_err(|e| e.to_string()), + ); + + // Invalid first hash with None. + let result = api.query_storage( + keys.clone(), + random_hash1, + None, + ); + + assert_eq!( + result.wait().map_err(|e| e.to_string()), + Err(Error::InvalidBlockRange { + from: format!("{:?}", random_hash1), + to: format!("{:?}", Some(block2_hash)), // Best block hash. + details: format!("UnknownBlock: header not found in db: {}", random_hash1), + }).map_err(|e| e.to_string()), + ); + + // Both hashes invalid. + let result = api.query_storage( + keys.clone(), + random_hash1, + Some(random_hash2), + ); + + assert_eq!( + result.wait().map_err(|e| e.to_string()), + Err(Error::InvalidBlockRange { + from: format!("{:?}", random_hash1), // First hash not found. + to: format!("{:?}", Some(random_hash2)), + details: format!("UnknownBlock: header not found in db: {}", random_hash1), + }).map_err(|e| e.to_string()), + ); + } + + run_tests(Arc::new(substrate_test_runtime_client::new())); + run_tests(Arc::new(TestClientBuilder::new().set_support_changes_trie(true).build())); +} + +#[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))); +} + + +#[test] +fn should_return_runtime_version() { + let core = tokio::runtime::Runtime::new().unwrap(); + + let client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + + let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ + \"specVersion\":1,\"implVersion\":1,\"apis\":[[\"0xdf6acb689907609b\",2],\ + [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",4],\ + [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\ + [\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]]}"; + + let runtime_version = api.runtime_version(None.into()).wait().unwrap(); + let serialized = serde_json::to_string(&runtime_version).unwrap(); + assert_eq!(serialized, result); + + let deserialized: RuntimeVersion = serde_json::from_str(result).unwrap(); + assert_eq!(deserialized, runtime_version); +} + +#[test] +fn should_notify_on_runtime_version_initially() { + let mut core = tokio::runtime::Runtime::new().unwrap(); + let (subscriber, id, transport) = Subscriber::new_test("test"); + + { + let client = Arc::new(substrate_test_runtime_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + + api.subscribe_runtime_version(Default::default(), subscriber); + + // assert id assigned + assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); + } + + // assert initial version sent. + let (notification, next) = core.block_on(transport.into_future()).unwrap(); + assert!(notification.is_some()); + // no more notifications on this channel + assert_eq!(core.block_on(next.into_future()).unwrap().0, None); +} + +#[test] +fn should_deserialize_storage_key() { + let k = "\"0x7f864e18e3dd8b58386310d2fe0919eef27c6e558564b7f67f22d99d20f587b\""; + let k: StorageKey = serde_json::from_str(k).unwrap(); + + assert_eq!(k.0.len(), 32); +} diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs new file mode 100644 index 0000000000000..3a9ed9f2dcc58 --- /dev/null +++ b/client/rpc/src/system/mod.rs @@ -0,0 +1,139 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate system API. + +#[cfg(test)] +mod tests; + +use futures::{future::BoxFuture, FutureExt, TryFutureExt}; +use futures::{channel::{mpsc, oneshot}, compat::Compat}; +use sc_rpc_api::Receiver; +use sp_runtime::traits::{self, Header as HeaderT}; + +use self::error::Result; + +pub use sc_rpc_api::system::*; +pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; +pub use self::gen_client::Client as SystemClient; + +/// System API implementation +pub struct System { + info: SystemInfo, + send_back: mpsc::UnboundedSender>, +} + +/// Request to be processed. +pub enum Request { + /// Must return the health of the network. + Health(oneshot::Sender), + /// Must return information about the peers we are connected to. + Peers(oneshot::Sender::Number>>>), + /// Must return the state of the network. + NetworkState(oneshot::Sender), + /// Must return any potential parse error. + NetworkAddReservedPeer(String, oneshot::Sender>), + /// Must return any potential parse error. + NetworkRemoveReservedPeer(String, oneshot::Sender>), + /// Must return the node role. + NodeRoles(oneshot::Sender>) +} + +impl System { + /// Creates new `System`. + /// + /// The `send_back` will be used to transmit some of the requests. The user is responsible for + /// reading from that channel and answering the requests. + pub fn new( + info: SystemInfo, + send_back: mpsc::UnboundedSender>, + ) -> Self { + System { + info, + send_back, + } + } +} + +impl SystemApi::Number> for System { + fn system_name(&self) -> Result { + Ok(self.info.impl_name.clone()) + } + + fn system_version(&self) -> Result { + Ok(self.info.impl_version.clone()) + } + + fn system_chain(&self) -> Result { + Ok(self.info.chain_name.clone()) + } + + fn system_properties(&self) -> Result { + Ok(self.info.properties.clone()) + } + + fn system_health(&self) -> Receiver { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::Health(tx)); + Receiver(Compat::new(rx)) + } + + fn system_peers(&self) -> Receiver::Number>>> { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::Peers(tx)); + Receiver(Compat::new(rx)) + } + + fn system_network_state(&self) -> Receiver { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NetworkState(tx)); + Receiver(Compat::new(rx)) + } + + fn system_add_reserved_peer(&self, peer: String) + -> Compat>> + { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NetworkAddReservedPeer(peer, tx)); + async move { + match rx.await { + Ok(Ok(())) => Ok(()), + Ok(Err(e)) => Err(rpc::Error::from(e)), + Err(_) => Err(rpc::Error::internal_error()), + } + }.boxed().compat() + } + + fn system_remove_reserved_peer(&self, peer: String) + -> Compat>> + { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NetworkRemoveReservedPeer(peer, tx)); + async move { + match rx.await { + Ok(Ok(())) => Ok(()), + Ok(Err(e)) => Err(rpc::Error::from(e)), + Err(_) => Err(rpc::Error::internal_error()), + } + }.boxed().compat() + } + + fn system_node_roles(&self) -> Receiver> { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NodeRoles(tx)); + Receiver(Compat::new(rx)) + } +} diff --git a/client/rpc/src/system/tests.rs b/client/rpc/src/system/tests.rs new file mode 100644 index 0000000000000..a280110093b0b --- /dev/null +++ b/client/rpc/src/system/tests.rs @@ -0,0 +1,270 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use super::*; + +use sc_network::{self, PeerId}; +use sc_network::config::Roles; +use substrate_test_runtime_client::runtime::Block; +use assert_matches::assert_matches; +use futures::{prelude::*, channel::mpsc}; +use std::thread; + +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, + } + } +} + +fn api>>(sync: T) -> System { + let status = sync.into().unwrap_or_default(); + let should_have_peers = !status.is_dev; + let (tx, rx) = mpsc::unbounded(); + thread::spawn(move || { + futures::executor::block_on(rx.for_each(move |request| { + match request { + Request::Health(sender) => { + let _ = sender.send(Health { + peers: status.peers, + is_syncing: status.is_syncing, + should_have_peers, + }); + }, + Request::Peers(sender) => { + let mut peers = vec![]; + for _peer in 0..status.peers { + peers.push(PeerInfo { + peer_id: status.peer_id.to_base58(), + roles: format!("{:?}", Roles::FULL), + protocol_version: 1, + best_hash: Default::default(), + best_number: 1, + }); + } + let _ = sender.send(peers); + } + Request::NetworkState(sender) => { + let _ = sender.send(serde_json::to_value(&sc_network::NetworkState { + peer_id: String::new(), + listened_addresses: Default::default(), + external_addresses: Default::default(), + connected_peers: Default::default(), + not_connected_peers: Default::default(), + average_download_per_sec: 0, + average_upload_per_sec: 0, + peerset: serde_json::Value::Null, + }).unwrap()); + }, + Request::NetworkAddReservedPeer(peer, sender) => { + let _ = match sc_network::config::parse_str_addr(&peer) { + Ok(_) => sender.send(Ok(())), + Err(s) => sender.send(Err(error::Error::MalformattedPeerArg(s.to_string()))), + }; + }, + Request::NetworkRemoveReservedPeer(peer, sender) => { + let _ = match peer.parse::() { + Ok(_) => sender.send(Ok(())), + Err(s) => sender.send(Err(error::Error::MalformattedPeerArg(s.to_string()))), + }; + } + Request::NodeRoles(sender) => { + let _ = sender.send(vec![NodeRole::Authority]); + } + }; + + future::ready(()) + })) + }); + System::new(SystemInfo { + impl_name: "testclient".into(), + impl_version: "0.2.0".into(), + chain_name: "testchain".into(), + properties: Default::default(), + }, tx) +} + +fn wait_receiver(rx: Receiver) -> T { + let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap(); + runtime.block_on(rx).unwrap() +} + +#[test] +fn system_name_works() { + assert_eq!( + api(None).system_name().unwrap(), + "testclient".to_owned() + ); +} + +#[test] +fn system_version_works() { + assert_eq!( + api(None).system_version().unwrap(), + "0.2.0".to_owned() + ); +} + +#[test] +fn system_chain_works() { + assert_eq!( + api(None).system_chain().unwrap(), + "testchain".to_owned() + ); +} + +#[test] +fn system_properties_works() { + assert_eq!( + api(None).system_properties().unwrap(), + serde_json::map::Map::new() + ); +} + +#[test] +fn system_health() { + assert_matches!( + wait_receiver(api(None).system_health()), + Health { + peers: 0, + is_syncing: false, + should_have_peers: true, + } + ); + + assert_matches!( + wait_receiver(api(Status { + peer_id: PeerId::random(), + peers: 5, + is_syncing: true, + is_dev: true, + }).system_health()), + Health { + peers: 5, + is_syncing: true, + should_have_peers: false, + } + ); + + assert_eq!( + wait_receiver(api(Status { + peer_id: PeerId::random(), + peers: 5, + is_syncing: false, + is_dev: false, + }).system_health()), + Health { + peers: 5, + is_syncing: false, + should_have_peers: true, + } + ); + + assert_eq!( + wait_receiver(api(Status { + peer_id: PeerId::random(), + peers: 0, + is_syncing: false, + is_dev: true, + }).system_health()), + Health { + peers: 0, + is_syncing: false, + should_have_peers: false, + } + ); +} + +#[test] +fn system_peers() { + let peer_id = PeerId::random(); + assert_eq!( + wait_receiver(api(Status { + peer_id: peer_id.clone(), + peers: 1, + is_syncing: false, + is_dev: true, + }).system_peers()), + vec![PeerInfo { + peer_id: peer_id.to_base58(), + roles: "FULL".into(), + protocol_version: 1, + best_hash: Default::default(), + best_number: 1u64, + }] + ); +} + +#[test] +fn system_network_state() { + let res = wait_receiver(api(None).system_network_state()); + assert_eq!( + serde_json::from_value::(res).unwrap(), + sc_network::NetworkState { + peer_id: String::new(), + listened_addresses: Default::default(), + external_addresses: Default::default(), + connected_peers: Default::default(), + not_connected_peers: Default::default(), + average_download_per_sec: 0, + average_upload_per_sec: 0, + peerset: serde_json::Value::Null, + } + ); +} + +#[test] +fn system_node_roles() { + assert_eq!( + wait_receiver(api(None).system_node_roles()), + vec![NodeRole::Authority] + ); +} + +#[test] +fn system_network_add_reserved() { + let good_peer_id = "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV"; + let bad_peer_id = "/ip4/198.51.100.19/tcp/30333"; + let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap(); + + let good_fut = api(None).system_add_reserved_peer(good_peer_id.into()); + let bad_fut = api(None).system_add_reserved_peer(bad_peer_id.into()); + assert_eq!(runtime.block_on(good_fut), Ok(())); + assert!(runtime.block_on(bad_fut).is_err()); +} + +#[test] +fn system_network_remove_reserved() { + let good_peer_id = "QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV"; + let bad_peer_id = "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV"; + let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap(); + + let good_fut = api(None).system_remove_reserved_peer(good_peer_id.into()); + let bad_fut = api(None).system_remove_reserved_peer(bad_peer_id.into()); + assert_eq!(runtime.block_on(good_fut), Ok(())); + assert!(runtime.block_on(bad_fut).is_err()); +} diff --git a/client/service/Cargo.toml b/client/service/Cargo.toml new file mode 100644 index 0000000000000..ce27b0995c5ef --- /dev/null +++ b/client/service/Cargo.toml @@ -0,0 +1,63 @@ +[package] +name = "sc-service" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[features] +default = ["rocksdb"] +# The RocksDB feature activates the RocksDB database backend. If it is not activated, and you pass +# a path to a database, an error will be produced at runtime. +rocksdb = ["sc-client-db/kvdb-rocksdb"] +wasmtime = [ + "sc-executor/wasmtime", +] + +[dependencies] +derive_more = "0.99.2" +futures = "0.1.29" +futures03 = { package = "futures", version = "0.3.1", features = ["compat"] } +parking_lot = "0.9.0" +lazy_static = "1.4.0" +log = "0.4.8" +slog = { version = "2.5.2", features = ["nested-values"] } +tokio-executor = "0.1.8" +tokio-timer = "0.2.11" +exit-future = "0.2.0" +serde = "1.0.101" +serde_json = "1.0.41" +sysinfo = "0.9.5" +target_info = "0.1.0" +sc-keystore = { version = "2.0.0", path = "../keystore" } +sp-io = { version = "2.0.0", path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-session = { version = "2.0.0", path = "../../primitives/session" } +sp-application-crypto = { version = "2.0.0", path = "../../primitives/application-crypto" } +sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" } +sc-network = { version = "0.8", path = "../network" } +sc-chain-spec = { version = "2.0.0", path = "../chain-spec" } +sc-client-api = { version = "2.0.0", path = "../api" } +sc-client = { version = "2.0.0", path = "../" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } +sc-client-db = { version = "2.0.0", path = "../db" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +sc-executor = { version = "2.0.0", path = "../executor" } +sc-transaction-pool = { version = "2.0.0", path = "../transaction-pool" } +sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } +sc-rpc-server = { version = "2.0.0", path = "../rpc-servers" } +sc-rpc = { version = "2.0.0", path = "../rpc" } +sc-telemetry = { version = "2.0.0", path = "../telemetry" } +sc-offchain = { version = "2.0.0", path = "../offchain" } +parity-multiaddr = { package = "parity-multiaddr", version = "0.5.0" } +grafana-data-source = { version = "2.0.0", path = "../../utils/grafana-data-source" } +sc-tracing = { version = "2.0.0", path = "../tracing" } +tracing = "0.1.10" + +[dev-dependencies] +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } +sp-consensus-babe = { version = "0.8", path = "../../primitives/consensus/babe" } +grandpa = { version = "2.0.0", package = "sc-finality-grandpa", path = "../finality-grandpa" } +grandpa-primitives = { version = "2.0.0", package = "sp-finality-grandpa", path = "../../primitives/finality-grandpa" } +tokio = "0.1" diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs new file mode 100644 index 0000000000000..472043559e5d9 --- /dev/null +++ b/client/service/src/builder.rs @@ -0,0 +1,1176 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::{Service, NetworkStatus, NetworkState, error::Error, DEFAULT_PROTOCOL_ID}; +use crate::{SpawnTaskHandle, start_rpc_servers, build_network_future, TransactionPoolAdapter}; +use crate::status_sinks; +use crate::config::{Configuration, DatabaseConfig, KeystoreConfig}; +use sc_client_api::{ + self, + BlockchainEvents, + backend::RemoteBackend, light::RemoteBlockchain, + execution_extensions::ExtensionsFactory, +}; +use sc_client::Client; +use sc_chain_spec::{RuntimeGenesis, Extension}; +use sp_consensus::import_queue::ImportQueue; +use futures::{prelude::*, sync::mpsc}; +use futures03::{ + compat::Compat, + FutureExt as _, TryFutureExt as _, + StreamExt as _, TryStreamExt as _, + future::{select, Either} +}; +use sc_keystore::{Store as Keystore}; +use log::{info, warn, error}; +use sc_network::{FinalityProofProvider, OnDemand, NetworkService, NetworkStateInfo}; +use sc_network::{config::BoxFinalityProofRequestBuilder, specialization::NetworkSpecialization}; +use parking_lot::{Mutex, RwLock}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{ + Block as BlockT, NumberFor, SaturatedConversion, HasherFor, +}; +use sp_api::ProvideRuntimeApi; +use sc_executor::{NativeExecutor, NativeExecutionDispatch}; +use std::{ + io::{Read, Write, Seek}, + marker::PhantomData, sync::Arc, time::SystemTime +}; +use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; +use sc_telemetry::{telemetry, SUBSTRATE_INFO}; +use sp_transaction_pool::{TransactionPool, TransactionPoolMaintainer}; +use sp_blockchain; +use grafana_data_source::{self, record_metrics}; + +/// Aggregator for the components required to build a service. +/// +/// # Usage +/// +/// Call [`ServiceBuilder::new_full`] or [`ServiceBuilder::new_light`], then call the various +/// `with_` methods to add the required components that you built yourself: +/// +/// - [`with_select_chain`](ServiceBuilder::with_select_chain) +/// - [`with_import_queue`](ServiceBuilder::with_import_queue) +/// - [`with_network_protocol`](ServiceBuilder::with_network_protocol) +/// - [`with_finality_proof_provider`](ServiceBuilder::with_finality_proof_provider) +/// - [`with_transaction_pool`](ServiceBuilder::with_transaction_pool) +/// +/// After this is done, call [`build`](ServiceBuilder::build) to construct the service. +/// +/// The order in which the `with_*` methods are called doesn't matter, as the correct binding of +/// generics is done when you call `build`. +/// +pub struct ServiceBuilder +{ + config: Configuration, + pub (crate) client: Arc, + backend: Arc, + keystore: Arc>, + fetcher: Option, + select_chain: Option, + pub (crate) import_queue: TImpQu, + finality_proof_request_builder: Option, + finality_proof_provider: Option, + network_protocol: TNetP, + transaction_pool: Arc, + rpc_extensions: TRpc, + remote_backend: Option>>, + marker: PhantomData<(TBl, TRtApi)>, +} + +/// Full client type. +pub type TFullClient = Client< + TFullBackend, + TFullCallExecutor, + TBl, + TRtApi, +>; + +/// Full client backend type. +pub type TFullBackend = sc_client_db::Backend; + +/// Full client call executor type. +pub type TFullCallExecutor = sc_client::LocalCallExecutor< + sc_client_db::Backend, + NativeExecutor, +>; + +/// Light client type. +pub type TLightClient = Client< + TLightBackend, + TLightCallExecutor, + TBl, + TRtApi, +>; + +/// Light client backend type. +pub type TLightBackend = sc_client::light::backend::Backend< + sc_client_db::light::LightStorage, + HasherFor, +>; + +/// Light call executor type. +pub type TLightCallExecutor = sc_client::light::call_executor::GenesisCallExecutor< + sc_client::light::backend::Backend< + sc_client_db::light::LightStorage, + HasherFor + >, + sc_client::LocalCallExecutor< + sc_client::light::backend::Backend< + sc_client_db::light::LightStorage, + HasherFor + >, + NativeExecutor + >, +>; + +type TFullParts = ( + TFullClient, + Arc>, + Arc>, +); + +/// Creates a new full client for the given config. +pub fn new_full_client( + config: &Configuration, +) -> Result, Error> where + TBl: BlockT, + TExecDisp: NativeExecutionDispatch, + TGen: sp_runtime::BuildStorage + serde::Serialize + for<'de> serde::Deserialize<'de>, + TCSExt: Extension, +{ + new_full_parts(config).map(|parts| parts.0) +} + +fn new_full_parts( + config: &Configuration, +) -> Result, Error> where + TBl: BlockT, + TExecDisp: NativeExecutionDispatch, + TGen: sp_runtime::BuildStorage + serde::Serialize + for<'de> serde::Deserialize<'de>, + TCSExt: Extension, +{ + let keystore = match &config.keystore { + KeystoreConfig::Path { path, password } => Keystore::open( + path.clone(), + password.clone() + )?, + KeystoreConfig::InMemory => Keystore::new_in_memory(), + KeystoreConfig::None => return Err("No keystore config provided!".into()), + }; + + let executor = NativeExecutor::::new( + config.wasm_method, + config.default_heap_pages, + ); + + let fork_blocks = config.chain_spec + .extensions() + .get::>() + .cloned() + .unwrap_or_default(); + + let bad_blocks = config.chain_spec + .extensions() + .get::>() + .cloned() + .unwrap_or_default(); + + let (client, backend) = { + let db_config = sc_client_db::DatabaseSettings { + state_cache_size: config.state_cache_size, + state_cache_child_ratio: + config.state_cache_child_ratio.map(|v| (v, 100)), + pruning: config.pruning.clone(), + source: match &config.database { + DatabaseConfig::Path { path, cache_size } => + sc_client_db::DatabaseSettingsSrc::Path { + path: path.clone(), + cache_size: cache_size.clone().map(|u| u as usize), + }, + DatabaseConfig::Custom(db) => + sc_client_db::DatabaseSettingsSrc::Custom(db.clone()), + }, + }; + + let extensions = sc_client_api::execution_extensions::ExecutionExtensions::new( + config.execution_strategies.clone(), + Some(keystore.clone()), + ); + + sc_client_db::new_client( + db_config, + executor, + &config.chain_spec, + fork_blocks, + bad_blocks, + extensions, + )? + }; + + Ok((client, backend, keystore)) +} + +impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), ()> +where TGen: RuntimeGenesis, TCSExt: Extension { + /// Start the service builder with a configuration. + pub fn new_full( + config: Configuration + ) -> Result, + Arc>, + (), + (), + BoxFinalityProofRequestBuilder, + Arc>, + (), + (), + (), + TFullBackend, + >, Error> { + let (client, backend, keystore) = new_full_parts(&config)?; + + let client = Arc::new(client); + + Ok(ServiceBuilder { + config, + client, + backend, + keystore, + fetcher: None, + select_chain: None, + import_queue: (), + finality_proof_request_builder: None, + finality_proof_provider: None, + network_protocol: (), + transaction_pool: Arc::new(()), + rpc_extensions: Default::default(), + remote_backend: None, + marker: PhantomData, + }) + } + + /// Start the service builder with a configuration. + pub fn new_light( + config: Configuration + ) -> Result, + Arc>, + (), + (), + BoxFinalityProofRequestBuilder, + Arc>, + (), + (), + (), + TLightBackend, + >, Error> { + let keystore = match &config.keystore { + KeystoreConfig::Path { path, password } => Keystore::open( + path.clone(), + password.clone() + )?, + KeystoreConfig::InMemory => Keystore::new_in_memory(), + KeystoreConfig::None => return Err("No keystore config provided!".into()), + }; + + let executor = NativeExecutor::::new( + config.wasm_method, + config.default_heap_pages, + ); + + let db_storage = { + let db_settings = sc_client_db::DatabaseSettings { + state_cache_size: config.state_cache_size, + state_cache_child_ratio: + config.state_cache_child_ratio.map(|v| (v, 100)), + pruning: config.pruning.clone(), + source: match &config.database { + DatabaseConfig::Path { path, cache_size } => + sc_client_db::DatabaseSettingsSrc::Path { + path: path.clone(), + cache_size: cache_size.clone().map(|u| u as usize), + }, + DatabaseConfig::Custom(db) => + sc_client_db::DatabaseSettingsSrc::Custom(db.clone()), + }, + }; + sc_client_db::light::LightStorage::new(db_settings)? + }; + let light_blockchain = sc_client::light::new_light_blockchain(db_storage); + let fetch_checker = Arc::new( + sc_client::light::new_fetch_checker::<_, TBl, _>( + light_blockchain.clone(), + executor.clone(), + ), + ); + let fetcher = Arc::new(sc_network::OnDemand::new(fetch_checker)); + let backend = sc_client::light::new_light_backend(light_blockchain); + let remote_blockchain = backend.remote_blockchain(); + let client = Arc::new(sc_client::light::new_light( + backend.clone(), + &config.chain_spec, + executor, + )?); + + Ok(ServiceBuilder { + config, + client, + backend, + keystore, + fetcher: Some(fetcher.clone()), + select_chain: None, + import_queue: (), + finality_proof_request_builder: None, + finality_proof_provider: None, + network_protocol: (), + transaction_pool: Arc::new(()), + rpc_extensions: Default::default(), + remote_backend: Some(remote_blockchain), + marker: PhantomData, + }) + } +} + +impl + ServiceBuilder { + + /// Returns a reference to the client that was stored in this builder. + pub fn client(&self) -> &Arc { + &self.client + } + + /// Returns a reference to the backend that was used in this builder. + pub fn backend(&self) -> &Arc { + &self.backend + } + + /// Returns a reference to the select-chain that was stored in this builder. + pub fn select_chain(&self) -> Option<&TSc> { + self.select_chain.as_ref() + } + + /// Defines which head-of-chain strategy to use. + pub fn with_opt_select_chain( + self, + select_chain_builder: impl FnOnce( + &Configuration, &Arc + ) -> Result, Error> + ) -> Result, Error> { + let select_chain = select_chain_builder(&self.config, &self.backend)?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + marker: self.marker, + }) + } + + /// Defines which head-of-chain strategy to use. + pub fn with_select_chain( + self, + builder: impl FnOnce(&Configuration, &Arc) -> Result + ) -> Result, Error> { + self.with_opt_select_chain(|cfg, b| builder(cfg, b).map(Option::Some)) + } + + /// Defines which import queue to use. + pub fn with_import_queue( + self, + builder: impl FnOnce(&Configuration, Arc, Option, Arc) + -> Result + ) -> Result, Error> + where TSc: Clone { + let import_queue = builder( + &self.config, + self.client.clone(), + self.select_chain.clone(), + self.transaction_pool.clone() + )?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + marker: self.marker, + }) + } + + /// Defines which network specialization protocol to use. + pub fn with_network_protocol( + self, + network_protocol_builder: impl FnOnce(&Configuration) -> Result + ) -> Result, Error> { + let network_protocol = network_protocol_builder(&self.config)?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + marker: self.marker, + }) + } + + /// Defines which strategy to use for providing finality proofs. + pub fn with_opt_finality_proof_provider( + self, + builder: impl FnOnce(Arc, Arc) -> Result>>, Error> + ) -> Result>, + TNetP, + TExPool, + TRpc, + Backend, + >, Error> { + let finality_proof_provider = builder(self.client.clone(), self.backend.clone())?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + marker: self.marker, + }) + } + + /// Defines which strategy to use for providing finality proofs. + pub fn with_finality_proof_provider( + self, + build: impl FnOnce(Arc, Arc) -> Result>, Error> + ) -> Result>, + TNetP, + TExPool, + TRpc, + Backend, + >, Error> { + self.with_opt_finality_proof_provider(|client, backend| build(client, backend).map(Option::Some)) + } + + /// Defines which import queue to use. + pub fn with_import_queue_and_opt_fprb( + self, + builder: impl FnOnce( + &Configuration, + Arc, + Arc, + Option, + Option, + Arc, + ) -> Result<(UImpQu, Option), Error> + ) -> Result, Error> + where TSc: Clone, TFchr: Clone { + let (import_queue, fprb) = builder( + &self.config, + self.client.clone(), + self.backend.clone(), + self.fetcher.clone(), + self.select_chain.clone(), + self.transaction_pool.clone() + )?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue, + finality_proof_request_builder: fprb, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + marker: self.marker, + }) + } + + /// Defines which import queue to use. + pub fn with_import_queue_and_fprb( + self, + builder: impl FnOnce( + &Configuration, + Arc, + Arc, + Option, + Option, + Arc, + ) -> Result<(UImpQu, UFprb), Error> + ) -> Result, Error> + where TSc: Clone, TFchr: Clone { + self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx| + builder(cfg, cl, b, f, sc, tx) + .map(|(q, f)| (q, Some(f))) + ) + } + + /// Defines which transaction pool to use. + pub fn with_transaction_pool( + self, + transaction_pool_builder: impl FnOnce( + sc_transaction_pool::txpool::Options, + Arc, + Option, + ) -> Result + ) -> Result, Error> + where TSc: Clone, TFchr: Clone { + let transaction_pool = transaction_pool_builder( + self.config.transaction_pool.clone(), + self.client.clone(), + self.fetcher.clone(), + )?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: Arc::new(transaction_pool), + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + marker: self.marker, + }) + } + + /// Defines the RPC extensions to use. + pub fn with_rpc_extensions( + self, + rpc_ext_builder: impl FnOnce( + Arc, + Arc, + Arc, + Option, + Option>>, + ) -> Result, + ) -> Result, Error> + where TSc: Clone, TFchr: Clone { + let rpc_extensions = rpc_ext_builder( + self.client.clone(), + self.transaction_pool.clone(), + self.backend.clone(), + self.fetcher.clone(), + self.remote_backend.clone(), + )?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions, + remote_backend: self.remote_backend, + marker: self.marker, + }) + } +} + +/// Implemented on `ServiceBuilder`. Allows running block commands, such as import/export/validate +/// components to the builder. +pub trait ServiceBuilderCommand { + /// Block type this API operates on. + type Block: BlockT; + /// Starts the process of importing blocks. + fn import_blocks( + self, + input: impl Read + Seek + Send + 'static, + force: bool, + ) -> Box + Send>; + + /// Performs the blocks export. + fn export_blocks( + self, + output: impl Write + 'static, + from: NumberFor, + to: Option>, + json: bool + ) -> Box>; + + /// Performs a revert of `blocks` blocks. + fn revert_chain( + &self, + blocks: NumberFor + ) -> Result<(), Error>; + + /// Re-validate known block. + fn check_block( + self, + block: BlockId + ) -> Box + Send>; +} + +impl +ServiceBuilder< + TBl, + TRtApi, + TCfg, + TGen, + TCSExt, + Client, + Arc>, + TSc, + TImpQu, + BoxFinalityProofRequestBuilder, + Arc>, + TNetP, + TExPool, + TRpc, + TBackend, +> where + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + sp_api::Metadata + + sc_offchain::OffchainWorkerApi + + sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_session::SessionKeys + + sp_api::ApiErrorExt + + sp_api::ApiExt, + TBl: BlockT, + TRtApi: 'static + Send + Sync, + TCfg: Default, + TGen: RuntimeGenesis, + TCSExt: Extension, + TBackend: 'static + sc_client_api::backend::Backend + Send, + TExec: 'static + sc_client::CallExecutor + Send + Sync + Clone, + TSc: Clone, + TImpQu: 'static + ImportQueue, + TNetP: NetworkSpecialization, + TExPool: 'static + + TransactionPool::Hash> + + TransactionPoolMaintainer::Hash>, + TRpc: sc_rpc::RpcExtension + Clone, +{ + + /// Set an ExecutionExtensionsFactory + pub fn with_execution_extensions_factory(self, execution_extensions_factory: Box) -> Result { + self.client.execution_extensions().set_extensions_factory(execution_extensions_factory); + Ok(self) + } + + /// Builds the service. + pub fn build(self) -> Result, + TSc, + NetworkStatus, + NetworkService::Hash>, + TExPool, + sc_offchain::OffchainWorkers< + Client, + TBackend::OffchainStorage, + TBl + >, + >, Error> { + let ServiceBuilder { + marker: _, + mut config, + client, + fetcher: on_demand, + backend, + keystore, + select_chain, + import_queue, + finality_proof_request_builder, + finality_proof_provider, + network_protocol, + transaction_pool, + rpc_extensions, + remote_backend, + } = self; + + sp_session::generate_initial_session_keys( + client.clone(), + &BlockId::Hash(client.chain_info().best_hash), + config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), + )?; + + let (signal, exit) = exit_future::signal(); + + // List of asynchronous tasks to spawn. We collect them, then spawn them all at once. + let (to_spawn_tx, to_spawn_rx) = + mpsc::unbounded:: + Send>>(); + + // A side-channel for essential tasks to communicate shutdown. + let (essential_failed_tx, essential_failed_rx) = mpsc::unbounded(); + + let import_queue = Box::new(import_queue); + let chain_info = client.chain_info(); + + let version = config.full_version(); + info!("Highest known block at #{}", chain_info.best_number); + telemetry!( + SUBSTRATE_INFO; + "node.start"; + "height" => chain_info.best_number.saturated_into::(), + "best" => ?chain_info.best_hash + ); + + // make transaction pool available for off-chain runtime calls. + client.execution_extensions() + .register_transaction_pool(Arc::downgrade(&transaction_pool) as _); + + let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { + imports_external_transactions: !config.roles.is_light(), + pool: transaction_pool.clone(), + client: client.clone(), + executor: Arc::new(SpawnTaskHandle { sender: to_spawn_tx.clone(), on_exit: exit.clone() }), + }); + + let protocol_id = { + let protocol_id_full = match config.chain_spec.protocol_id() { + Some(pid) => pid, + None => { + warn!("Using default protocol ID {:?} because none is configured in the \ + chain specs", DEFAULT_PROTOCOL_ID + ); + DEFAULT_PROTOCOL_ID + } + }.as_bytes(); + sc_network::config::ProtocolId::from(protocol_id_full) + }; + + let block_announce_validator = + Box::new(sp_consensus::block_validation::DefaultBlockAnnounceValidator::new(client.clone())); + + let network_params = sc_network::config::Params { + roles: config.roles, + network_config: config.network.clone(), + chain: client.clone(), + finality_proof_provider, + finality_proof_request_builder, + on_demand: on_demand.clone(), + transaction_pool: transaction_pool_adapter.clone() as _, + import_queue, + protocol_id, + specialization: network_protocol, + block_announce_validator, + }; + + let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); + let network_mut = sc_network::NetworkWorker::new(network_params)?; + let network = network_mut.service().clone(); + let network_status_sinks = Arc::new(Mutex::new(status_sinks::StatusSinks::new())); + + let offchain_storage = backend.offchain_storage(); + let offchain_workers = match (config.offchain_worker, offchain_storage) { + (true, Some(db)) => { + Some(Arc::new(sc_offchain::OffchainWorkers::new(client.clone(), db))) + }, + (true, None) => { + warn!("Offchain workers disabled, due to lack of offchain storage support in backend."); + None + }, + _ => None, + }; + + { + // block notifications + let txpool = Arc::downgrade(&transaction_pool); + let offchain = offchain_workers.as_ref().map(Arc::downgrade); + let to_spawn_tx_ = to_spawn_tx.clone(); + let network_state_info: Arc = network.clone(); + let is_validator = config.roles.is_authority(); + + let events = client.import_notification_stream() + .map(|v| Ok::<_, ()>(v)).compat() + .for_each(move |notification| { + let txpool = txpool.upgrade(); + + if let Some(txpool) = txpool.as_ref() { + let future = txpool.maintain( + &BlockId::hash(notification.hash), + ¬ification.retracted, + ).map(|_| Ok(())).compat(); + let _ = to_spawn_tx_.unbounded_send(Box::new(future)); + } + + let offchain = offchain.as_ref().and_then(|o| o.upgrade()); + if let Some(offchain) = offchain { + let future = offchain.on_block_imported( + ¬ification.header, + network_state_info.clone(), + is_validator + ).map(|()| Ok(())); + let _ = to_spawn_tx_.unbounded_send(Box::new(Compat::new(future))); + } + + Ok(()) + }) + .select(exit.clone().map(Ok).compat()) + .then(|_| Ok(())); + let _ = to_spawn_tx.unbounded_send(Box::new(events)); + } + + { + // extrinsic notifications + let network = Arc::downgrade(&network); + let transaction_pool_ = transaction_pool.clone(); + let events = transaction_pool.import_notification_stream() + .map(|v| Ok::<_, ()>(v)).compat() + .for_each(move |_| { + if let Some(network) = network.upgrade() { + network.trigger_repropagate(); + } + let status = transaction_pool_.status(); + telemetry!(SUBSTRATE_INFO; "txpool.import"; + "ready" => status.ready, + "future" => status.future + ); + Ok(()) + }) + .select(exit.clone().map(Ok).compat()) + .then(|_| Ok(())); + + let _ = to_spawn_tx.unbounded_send(Box::new(events)); + } + + // Periodically notify the telemetry. + let transaction_pool_ = transaction_pool.clone(); + let client_ = client.clone(); + let mut sys = System::new(); + let self_pid = get_current_pid().ok(); + let (state_tx, state_rx) = mpsc::unbounded::<(NetworkStatus<_>, NetworkState)>(); + network_status_sinks.lock().push(std::time::Duration::from_millis(5000), state_tx); + let tel_task = state_rx.for_each(move |(net_status, _)| { + let info = client_.usage_info(); + let best_number = info.chain.best_number.saturated_into::(); + let best_hash = info.chain.best_hash; + let num_peers = net_status.num_connected_peers; + let txpool_status = transaction_pool_.status(); + let finalized_number: u64 = info.chain.finalized_number.saturated_into::(); + let bandwidth_download = net_status.average_download_per_sec; + let bandwidth_upload = net_status.average_upload_per_sec; + + // get cpu usage and memory usage of this process + let (cpu_usage, memory) = if let Some(self_pid) = self_pid { + if sys.refresh_process(self_pid) { + let proc = sys.get_process(self_pid) + .expect("Above refresh_process succeeds, this should be Some(), qed"); + (proc.cpu_usage(), proc.memory()) + } else { (0.0, 0) } + } else { (0.0, 0) }; + + telemetry!( + SUBSTRATE_INFO; + "system.interval"; + "peers" => num_peers, + "height" => best_number, + "best" => ?best_hash, + "txcount" => txpool_status.ready, + "cpu" => cpu_usage, + "memory" => memory, + "finalized_height" => finalized_number, + "finalized_hash" => ?info.chain.finalized_hash, + "bandwidth_download" => bandwidth_download, + "bandwidth_upload" => bandwidth_upload, + "used_state_cache_size" => info.usage.as_ref().map(|usage| usage.memory.state_cache).unwrap_or(0), + "used_db_cache_size" => info.usage.as_ref().map(|usage| usage.memory.database_cache).unwrap_or(0), + "disk_read_per_sec" => info.usage.as_ref().map(|usage| usage.io.bytes_read).unwrap_or(0), + "disk_write_per_sec" => info.usage.as_ref().map(|usage| usage.io.bytes_written).unwrap_or(0), + ); + let _ = record_metrics!( + "peers" => num_peers, + "height" => best_number, + "txcount" => txpool_status.ready, + "cpu" => cpu_usage, + "memory" => memory, + "finalized_height" => finalized_number, + "bandwidth_download" => bandwidth_download, + "bandwidth_upload" => bandwidth_upload, + "used_state_cache_size" => info.usage.as_ref().map(|usage| usage.memory.state_cache).unwrap_or(0), + "used_db_cache_size" => info.usage.as_ref().map(|usage| usage.memory.database_cache).unwrap_or(0), + "disk_read_per_sec" => info.usage.as_ref().map(|usage| usage.io.bytes_read).unwrap_or(0), + "disk_write_per_sec" => info.usage.as_ref().map(|usage| usage.io.bytes_written).unwrap_or(0), + ); + + Ok(()) + }).select(exit.clone().map(Ok).compat()).then(|_| Ok(())); + let _ = to_spawn_tx.unbounded_send(Box::new(tel_task)); + + // Periodically send the network state to the telemetry. + let (netstat_tx, netstat_rx) = mpsc::unbounded::<(NetworkStatus<_>, NetworkState)>(); + network_status_sinks.lock().push(std::time::Duration::from_secs(30), netstat_tx); + let tel_task_2 = netstat_rx.for_each(move |(_, network_state)| { + telemetry!( + SUBSTRATE_INFO; + "system.network_state"; + "state" => network_state, + ); + Ok(()) + }).select(exit.clone().map(Ok).compat()).then(|_| Ok(())); + let _ = to_spawn_tx.unbounded_send(Box::new(tel_task_2)); + + // RPC + let (system_rpc_tx, system_rpc_rx) = futures03::channel::mpsc::unbounded(); + let gen_handler = || { + use sc_rpc::{chain, state, author, system}; + + let system_info = sc_rpc::system::SystemInfo { + chain_name: config.chain_spec.name().into(), + impl_name: config.impl_name.into(), + impl_version: config.impl_version.into(), + properties: config.chain_spec.properties().clone(), + }; + + let subscriptions = sc_rpc::Subscriptions::new(Arc::new(SpawnTaskHandle { + sender: to_spawn_tx.clone(), + on_exit: exit.clone() + })); + + let (chain, state) = if let (Some(remote_backend), Some(on_demand)) = + (remote_backend.as_ref(), on_demand.as_ref()) { + // Light clients + let chain = sc_rpc::chain::new_light( + client.clone(), + subscriptions.clone(), + remote_backend.clone(), + on_demand.clone() + ); + let state = sc_rpc::state::new_light( + client.clone(), + subscriptions.clone(), + remote_backend.clone(), + on_demand.clone() + ); + (chain, state) + + } else { + // Full nodes + let chain = sc_rpc::chain::new_full(client.clone(), subscriptions.clone()); + let state = sc_rpc::state::new_full(client.clone(), subscriptions.clone()); + (chain, state) + }; + + let author = sc_rpc::author::Author::new( + client.clone(), + transaction_pool.clone(), + subscriptions, + keystore.clone(), + ); + let system = system::System::new(system_info, system_rpc_tx.clone()); + + sc_rpc_server::rpc_handler(( + state::StateApi::to_delegate(state), + chain::ChainApi::to_delegate(chain), + author::AuthorApi::to_delegate(author), + system::SystemApi::to_delegate(system), + rpc_extensions.clone(), + )) + }; + let rpc_handlers = gen_handler(); + let rpc = start_rpc_servers(&config, gen_handler)?; + + + let _ = to_spawn_tx.unbounded_send(Box::new(build_network_future( + config.roles, + network_mut, + client.clone(), + network_status_sinks.clone(), + system_rpc_rx, + has_bootnodes, + ) + .map_err(|_| ()) + .select(exit.clone().map(Ok).compat()) + .then(|_| Ok(())))); + + let telemetry_connection_sinks: Arc>>> = Default::default(); + + // Telemetry + let telemetry = config.telemetry_endpoints.clone().map(|endpoints| { + let is_authority = config.roles.is_authority(); + let network_id = network.local_peer_id().to_base58(); + let name = config.name.clone(); + let impl_name = config.impl_name.to_owned(); + let version = version.clone(); + let chain_name = config.chain_spec.name().to_owned(); + let telemetry_connection_sinks_ = telemetry_connection_sinks.clone(); + let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { + endpoints, + wasm_external_transport: config.telemetry_external_transport.take(), + }); + let startup_time = SystemTime::UNIX_EPOCH.elapsed() + .map(|dur| dur.as_millis()) + .unwrap_or(0); + let future = telemetry.clone() + .map(|ev| Ok::<_, ()>(ev)) + .compat() + .for_each(move |event| { + // Safe-guard in case we add more events in the future. + let sc_telemetry::TelemetryEvent::Connected = event; + + telemetry!(SUBSTRATE_INFO; "system.connected"; + "name" => name.clone(), + "implementation" => impl_name.clone(), + "version" => version.clone(), + "config" => "", + "chain" => chain_name.clone(), + "authority" => is_authority, + "startup_time" => startup_time, + "network_id" => network_id.clone() + ); + + telemetry_connection_sinks_.lock().retain(|sink| { + sink.unbounded_send(()).is_ok() + }); + Ok(()) + }); + let _ = to_spawn_tx.unbounded_send(Box::new(future + .select(exit.clone().map(Ok).compat()) + .then(|_| Ok(())))); + telemetry + }); + + // Grafana data source + if let Some(port) = config.grafana_port { + let future = select( + grafana_data_source::run_server(port).boxed(), + exit.clone() + ).map(|either| match either { + Either::Left((result, _)) => result.map_err(|_| ()), + Either::Right(_) => Ok(()) + }).compat(); + + let _ = to_spawn_tx.unbounded_send(Box::new(future)); + } + + // Instrumentation + if let Some(tracing_targets) = config.tracing_targets.as_ref() { + let subscriber = sc_tracing::ProfilingSubscriber::new( + config.tracing_receiver, tracing_targets + ); + match tracing::subscriber::set_global_default(subscriber) { + Ok(_) => (), + Err(e) => error!(target: "tracing", "Unable to set global default subscriber {}", e), + } + } + + Ok(Service { + client, + network, + network_status_sinks, + select_chain, + transaction_pool, + exit, + signal: Some(signal), + essential_failed_tx, + essential_failed_rx, + to_spawn_tx, + to_spawn_rx, + to_poll: Vec::new(), + rpc_handlers, + _rpc: rpc, + _telemetry: telemetry, + _offchain_workers: offchain_workers, + _telemetry_on_connect_sinks: telemetry_connection_sinks.clone(), + keystore, + marker: PhantomData::, + }) + } +} diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs new file mode 100644 index 0000000000000..0b86fb366f0b6 --- /dev/null +++ b/client/service/src/chain_ops.rs @@ -0,0 +1,311 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Chain utilities. + +use crate::error; +use crate::builder::{ServiceBuilderCommand, ServiceBuilder}; +use crate::error::Error; +use sc_chain_spec::{ChainSpec, RuntimeGenesis, Extension}; +use log::{warn, info}; +use futures::{future, prelude::*}; +use futures03::{ + TryFutureExt as _, +}; +use sp_runtime::traits::{ + Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion +}; +use sp_runtime::generic::{BlockId, SignedBlock}; +use codec::{Decode, Encode, IoReader}; +use sc_client::Client; +use sp_consensus::import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue}; +use sp_consensus::BlockOrigin; + +use std::{ + io::{Read, Write, Seek}, +}; + +use sc_network::message; + +/// Build a chain spec json +pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result where + G: RuntimeGenesis, + E: Extension, +{ + Ok(spec.to_json(raw)?) +} + +impl< + TBl, TRtApi, TCfg, TGen, TCSExt, TBackend, + TExec, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, + TExPool, TRpc, Backend +> ServiceBuilderCommand for ServiceBuilder< + TBl, TRtApi, TCfg, TGen, TCSExt, Client, + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, Backend +> where + TBl: BlockT, + TBackend: 'static + sc_client_api::backend::Backend + Send, + TExec: 'static + sc_client::CallExecutor + Send + Sync + Clone, + TImpQu: 'static + ImportQueue, + TRtApi: 'static + Send + Sync, +{ + type Block = TBl; + + fn import_blocks( + self, + input: impl Read + Seek + Send + 'static, + force: bool, + ) -> Box + Send> { + struct WaitLink { + imported_blocks: u64, + has_error: bool, + } + + impl WaitLink { + fn new() -> WaitLink { + WaitLink { + imported_blocks: 0, + has_error: false, + } + } + } + + impl Link for WaitLink { + fn blocks_processed( + &mut self, + imported: usize, + _count: usize, + results: Vec<(Result>, BlockImportError>, B::Hash)> + ) { + self.imported_blocks += imported as u64; + + for result in results { + if let (Err(err), hash) = result { + warn!("There was an error importing block with hash {:?}: {:?}", hash, err); + self.has_error = true; + break; + } + } + } + } + + let client = self.client; + let mut queue = self.import_queue; + + let mut io_reader_input = IoReader(input); + let mut count = None::; + let mut read_block_count = 0; + let mut link = WaitLink::new(); + + // Importing blocks is implemented as a future, because we want the operation to be + // interruptible. + // + // Every time we read a block from the input or import a bunch of blocks from the import + // queue, the `Future` re-schedules itself and returns `Poll::Pending`. + // This makes it possible either to interleave other operations in-between the block imports, + // or to stop the operation completely. + let import = futures03::future::poll_fn(move |cx| { + // Start by reading the number of blocks if not done so already. + let count = match count { + Some(c) => c, + None => { + let c: u64 = match Decode::decode(&mut io_reader_input) { + Ok(c) => c, + Err(err) => { + let err = format!("Error reading file: {}", err); + return std::task::Poll::Ready(Err(From::from(err))); + }, + }; + info!("Importing {} blocks", c); + count = Some(c); + c + } + }; + + // Read blocks from the input. + if read_block_count < count { + match SignedBlock::::decode(&mut io_reader_input) { + Ok(signed) => { + let (header, extrinsics) = signed.block.deconstruct(); + let hash = header.hash(); + let block = message::BlockData:: { + hash, + justification: signed.justification, + header: Some(header), + body: Some(extrinsics), + receipt: None, + message_queue: None + }; + // import queue handles verification and importing it into the client + queue.import_blocks(BlockOrigin::File, vec![ + IncomingBlock:: { + hash: block.hash, + header: block.header, + body: block.body, + justification: block.justification, + origin: None, + allow_missing_state: false, + import_existing: force, + } + ]); + } + Err(e) => { + warn!("Error reading block data at {}: {}", read_block_count, e); + return std::task::Poll::Ready(Ok(())); + } + } + + read_block_count += 1; + if read_block_count % 1000 == 0 { + info!("#{} blocks were added to the queue", read_block_count); + } + + cx.waker().wake_by_ref(); + return std::task::Poll::Pending; + } + + let blocks_before = link.imported_blocks; + queue.poll_actions(cx, &mut link); + + if link.has_error { + info!( + "Stopping after #{} blocks because of an error", + link.imported_blocks, + ); + return std::task::Poll::Ready(Ok(())); + } + + if link.imported_blocks / 1000 != blocks_before / 1000 { + info!( + "#{} blocks were imported (#{} left)", + link.imported_blocks, + count - link.imported_blocks + ); + } + + if link.imported_blocks >= count { + info!("Imported {} blocks. Best: #{}", read_block_count, client.chain_info().best_number); + return std::task::Poll::Ready(Ok(())); + + } else { + // Polling the import queue will re-schedule the task when ready. + return std::task::Poll::Pending; + } + }); + Box::new(import.compat()) + } + + fn export_blocks( + self, + mut output: impl Write + 'static, + from: NumberFor, + to: Option>, + json: bool + ) -> Box> { + let client = self.client; + let mut block = from; + + let last = match to { + Some(v) if v.is_zero() => One::one(), + Some(v) => v, + None => client.chain_info().best_number, + }; + + let mut wrote_header = false; + + // Exporting blocks is implemented as a future, because we want the operation to be + // interruptible. + // + // Every time we write a block to the output, the `Future` re-schedules itself and returns + // `Poll::Pending`. + // This makes it possible either to interleave other operations in-between the block exports, + // or to stop the operation completely. + let export = futures03::future::poll_fn(move |cx| { + if last < block { + return std::task::Poll::Ready(Err("Invalid block range specified".into())); + } + + if !wrote_header { + info!("Exporting blocks from #{} to #{}", block, last); + if !json { + let last_: u64 = last.saturated_into::(); + let block_: u64 = block.saturated_into::(); + let len: u64 = last_ - block_ + 1; + output.write_all(&len.encode())?; + } + wrote_header = true; + } + + match client.block(&BlockId::number(block))? { + Some(block) => { + if json { + serde_json::to_writer(&mut output, &block) + .map_err(|e| format!("Error writing JSON: {}", e))?; + } else { + output.write_all(&block.encode())?; + } + }, + // Reached end of the chain. + None => return std::task::Poll::Ready(Ok(())), + } + if (block % 10000.into()).is_zero() { + info!("#{}", block); + } + if block == last { + return std::task::Poll::Ready(Ok(())); + } + block += One::one(); + + // Re-schedule the task in order to continue the operation. + cx.waker().wake_by_ref(); + std::task::Poll::Pending + }); + + Box::new(export.compat()) + } + + fn revert_chain( + &self, + blocks: NumberFor + ) -> Result<(), Error> { + let reverted = self.client.revert(blocks)?; + let info = self.client.chain_info(); + + if reverted.is_zero() { + info!("There aren't any non-finalized blocks to revert."); + } else { + info!("Reverted {} blocks. Best: #{} ({})", reverted, info.best_number, info.best_hash); + } + Ok(()) + } + + fn check_block( + self, + block_id: BlockId + ) -> Box + Send> { + match self.client.block(&block_id) { + Ok(Some(block)) => { + let mut buf = Vec::new(); + 1u64.encode_to(&mut buf); + block.encode_to(&mut buf); + let reader = std::io::Cursor::new(buf); + self.import_blocks(reader, true) + } + Ok(None) => Box::new(future::err("Unknown block".into())), + Err(e) => Box::new(future::err(format!("Error reading block: {:?}", e).into())), + } + } +} diff --git a/client/service/src/config.rs b/client/service/src/config.rs new file mode 100644 index 0000000000000..75c626821479d --- /dev/null +++ b/client/service/src/config.rs @@ -0,0 +1,235 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Service configuration. + +pub use sc_client::ExecutionStrategies; +pub use sc_client_db::{kvdb::KeyValueDB, PruningMode}; +pub use sc_network::config::{ExtTransport, NetworkConfiguration, Roles}; +pub use sc_executor::WasmExecutionMethod; + +use std::{path::{PathBuf, Path}, net::SocketAddr, sync::Arc}; +pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions; +use sc_chain_spec::{ChainSpec, RuntimeGenesis, Extension, NoExtension}; +use sp_core::crypto::Protected; +use target_info::Target; +use sc_telemetry::TelemetryEndpoints; + +/// Service configuration. +#[derive(Clone)] +pub struct Configuration { + /// Implementation name + pub impl_name: &'static str, + /// Implementation version + pub impl_version: &'static str, + /// Git commit if any. + pub impl_commit: &'static str, + /// Node roles. + pub roles: Roles, + /// Extrinsic pool configuration. + pub transaction_pool: TransactionPoolOptions, + /// Network configuration. + pub network: NetworkConfiguration, + /// Path to the base configuration directory. + pub config_dir: Option, + /// Configuration for the keystore. + pub keystore: KeystoreConfig, + /// Configuration for the database. + pub database: DatabaseConfig, + /// Size of internal state cache in Bytes + pub state_cache_size: usize, + /// Size in percent of cache size dedicated to child tries + pub state_cache_child_ratio: Option, + /// Pruning settings. + pub pruning: PruningMode, + /// Chain configuration. + pub chain_spec: ChainSpec, + /// Custom configuration. + pub custom: C, + /// Node name. + pub name: String, + /// Wasm execution method. + pub wasm_method: WasmExecutionMethod, + /// Execution strategies. + pub execution_strategies: ExecutionStrategies, + /// RPC over HTTP binding address. `None` if disabled. + pub rpc_http: Option, + /// RPC over Websockets binding address. `None` if disabled. + pub rpc_ws: Option, + /// Maximum number of connections for WebSockets RPC server. `None` if default. + pub rpc_ws_max_connections: Option, + /// CORS settings for HTTP & WS servers. `None` if all origins are allowed. + pub rpc_cors: Option>, + /// Grafana data source http port. `None` if disabled. + pub grafana_port: Option, + /// Telemetry service URL. `None` if disabled. + pub telemetry_endpoints: Option, + /// External WASM transport for the telemetry. If `Some`, when connection to a telemetry + /// endpoint, this transport will be tried in priority before all others. + pub telemetry_external_transport: Option, + /// The default number of 64KB pages to allocate for Wasm execution + pub default_heap_pages: Option, + /// Should offchain workers be executed. + pub offchain_worker: bool, + /// Sentry mode is enabled, the node's role is AUTHORITY but it should not + /// actively participate in consensus (i.e. no keystores should be passed to + /// consensus modules). + pub sentry_mode: bool, + /// Enable authoring even when offline. + pub force_authoring: bool, + /// Disable GRANDPA when running in validator mode + pub disable_grandpa: bool, + /// Development key seed. + /// + /// When running in development mode, the seed will be used to generate authority keys by the keystore. + /// + /// Should only be set when `node` is running development mode. + pub dev_key_seed: Option, + /// Tracing targets + pub tracing_targets: Option, + /// Tracing receiver + pub tracing_receiver: sc_tracing::TracingReceiver, +} + +/// Configuration of the client keystore. +#[derive(Clone)] +pub enum KeystoreConfig { + /// No config supplied. + None, + /// Keystore at a path on-disk. Recommended for native nodes. + Path { + /// The path of the keystore. + path: PathBuf, + /// Node keystore's password. + password: Option> + }, + /// In-memory keystore. Recommended for in-browser nodes. + InMemory +} + +impl KeystoreConfig { + /// Returns the path for the keystore. + pub fn path(&self) -> Option<&Path> { + match self { + Self::Path { path, .. } => Some(&path), + Self::None | Self::InMemory => None, + } + } +} + +/// Configuration of the database of the client. +#[derive(Clone)] +pub enum DatabaseConfig { + /// Database file at a specific path. Recommended for most uses. + Path { + /// Path to the database. + path: PathBuf, + /// Cache Size for internal database in MiB + cache_size: Option, + }, + + /// A custom implementation of an already-open database. + Custom(Arc), +} + +impl Configuration where + C: Default, + G: RuntimeGenesis, + E: Extension, +{ + /// Create a default config for given chain spec and path to configuration dir + pub fn default_with_spec_and_base_path(chain_spec: ChainSpec, config_dir: Option) -> Self { + let mut configuration = Configuration { + impl_name: "parity-substrate", + impl_version: "0.0.0", + impl_commit: "", + chain_spec, + config_dir: config_dir.clone(), + name: Default::default(), + roles: Roles::FULL, + transaction_pool: Default::default(), + network: Default::default(), + keystore: KeystoreConfig::None, + database: DatabaseConfig::Path { + path: Default::default(), + cache_size: Default::default(), + }, + state_cache_size: Default::default(), + state_cache_child_ratio: Default::default(), + custom: Default::default(), + pruning: PruningMode::default(), + wasm_method: WasmExecutionMethod::Interpreted, + execution_strategies: Default::default(), + rpc_http: None, + rpc_ws: None, + rpc_ws_max_connections: None, + rpc_cors: Some(vec![]), + grafana_port: None, + telemetry_endpoints: None, + telemetry_external_transport: None, + default_heap_pages: None, + offchain_worker: Default::default(), + sentry_mode: false, + force_authoring: false, + disable_grandpa: false, + dev_key_seed: None, + tracing_targets: Default::default(), + tracing_receiver: Default::default(), + }; + configuration.network.boot_nodes = configuration.chain_spec.boot_nodes().to_vec(); + + configuration.telemetry_endpoints = configuration.chain_spec.telemetry_endpoints().clone(); + + configuration + } + +} + +impl Configuration { + /// Returns full version string of this configuration. + pub fn full_version(&self) -> String { + full_version_from_strs(self.impl_version, self.impl_commit) + } + + /// Implementation id and version. + pub fn client_id(&self) -> String { + format!("{}/v{}", self.impl_name, self.full_version()) + } + + /// Generate a PathBuf to sub in the chain configuration directory + /// if given + pub fn in_chain_config_dir(&self, sub: &str) -> Option { + self.config_dir.clone().map(|mut path| { + path.push("chains"); + path.push(self.chain_spec.id()); + path.push(sub); + path + }) + } +} + +/// Returns platform info +pub fn platform() -> String { + let env = Target::env(); + let env_dash = if env.is_empty() { "" } else { "-" }; + format!("{}-{}{}{}", Target::arch(), Target::os(), env_dash, env) +} + +/// Returns full version string, using supplied version and commit. +pub fn full_version_from_strs(impl_version: &str, impl_commit: &str) -> String { + let commit_dash = if impl_commit.is_empty() { "" } else { "-" }; + format!("{}{}{}-{}", impl_version, commit_dash, impl_commit, platform()) +} diff --git a/client/service/src/error.rs b/client/service/src/error.rs new file mode 100644 index 0000000000000..6516b1c62c6d6 --- /dev/null +++ b/client/service/src/error.rs @@ -0,0 +1,64 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Errors that can occur during the service operation. + +use sc_network; +use sc_keystore; +use sp_consensus; +use sp_blockchain; + +/// Service Result typedef. +pub type Result = std::result::Result; + +/// Service errors. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Client error. + Client(sp_blockchain::Error), + /// IO error. + Io(std::io::Error), + /// Consensus error. + Consensus(sp_consensus::Error), + /// Network error. + Network(sc_network::error::Error), + /// Keystore error. + Keystore(sc_keystore::Error), + /// Best chain selection strategy is missing. + #[display(fmt="Best chain selection strategy (SelectChain) is not provided.")] + SelectChainRequired, + /// Other error. + Other(String), +} + +impl<'a> From<&'a str> for Error { + fn from(s: &'a str) -> Self { + Error::Other(s.into()) + } +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Client(ref err) => Some(err), + Error::Io(ref err) => Some(err), + Error::Consensus(ref err) => Some(err), + Error::Network(ref err) => Some(err), + Error::Keystore(ref err) => Some(err), + _ => None, + } + } +} diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs new file mode 100644 index 0000000000000..e495f23d16410 --- /dev/null +++ b/client/service/src/lib.rs @@ -0,0 +1,735 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. +//! Manages communication between them. + +#![warn(missing_docs)] + +pub mod config; +#[macro_use] +pub mod chain_ops; +pub mod error; + +mod builder; +mod status_sinks; + +use std::{io, pin::Pin}; +use std::marker::PhantomData; +use std::net::SocketAddr; +use std::collections::HashMap; +use std::time::{Duration, Instant}; +use futures::sync::mpsc; +use parking_lot::Mutex; + +use sc_client::Client; +use exit_future::Signal; +use futures::prelude::*; +use futures03::{ + future::{ready, FutureExt as _, TryFutureExt as _}, + stream::{StreamExt as _, TryStreamExt as _}, +}; +use sc_network::{ + NetworkService, NetworkState, specialization::NetworkSpecialization, + PeerId, ReportHandle, +}; +use log::{log, warn, debug, error, Level}; +use codec::{Encode, Decode}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{NumberFor, Block as BlockT}; + +pub use self::error::Error; +pub use self::builder::{ + new_full_client, + ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend, + TFullCallExecutor, TLightCallExecutor, +}; +pub use config::{Configuration, Roles, PruningMode}; +pub use sc_chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension}; +pub use sp_transaction_pool::{TransactionPool, TransactionPoolMaintainer, InPoolTransaction, error::IntoPoolError}; +pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions; +pub use sc_client::FinalityNotifications; +pub use sc_rpc::Metadata as RpcMetadata; +#[doc(hidden)] +pub use std::{ops::Deref, result::Result, sync::Arc}; +#[doc(hidden)] +pub use sc_network::{FinalityProofProvider, OnDemand, config::BoxFinalityProofRequestBuilder}; +#[doc(hidden)] +pub use futures::future::Executor; + +const DEFAULT_PROTOCOL_ID: &str = "sup"; + +/// Substrate service. +pub struct Service { + client: Arc, + select_chain: Option, + network: Arc, + /// Sinks to propagate network status updates. + /// For each element, every time the `Interval` fires we push an element on the sender. + network_status_sinks: Arc>>, + transaction_pool: Arc, + /// A future that resolves when the service has exited, this is useful to + /// make sure any internally spawned futures stop when the service does. + exit: exit_future::Exit, + /// A signal that makes the exit future above resolve, fired on service drop. + signal: Option, + /// Send a signal when a spawned essential task has concluded. The next time + /// the service future is polled it should complete with an error. + essential_failed_tx: mpsc::UnboundedSender<()>, + /// A receiver for spawned essential-tasks concluding. + essential_failed_rx: mpsc::UnboundedReceiver<()>, + /// Sender for futures that must be spawned as background tasks. + to_spawn_tx: mpsc::UnboundedSender + Send>>, + /// Receiver for futures that must be spawned as background tasks. + to_spawn_rx: mpsc::UnboundedReceiver + Send>>, + /// List of futures to poll from `poll`. + /// If spawning a background task is not possible, we instead push the task into this `Vec`. + /// The elements must then be polled manually. + to_poll: Vec + Send>>, + rpc_handlers: sc_rpc_server::RpcHandler, + _rpc: Box, + _telemetry: Option, + _telemetry_on_connect_sinks: Arc>>>, + _offchain_workers: Option>, + keystore: sc_keystore::KeyStorePtr, + marker: PhantomData, +} + +/// Alias for a an implementation of `futures::future::Executor`. +pub type TaskExecutor = Arc + Send>> + Send + Sync>; + +/// An handle for spawning tasks in the service. +#[derive(Clone)] +pub struct SpawnTaskHandle { + sender: mpsc::UnboundedSender + Send>>, + on_exit: exit_future::Exit, +} + +impl Executor + Send>> for SpawnTaskHandle { + fn execute( + &self, + future: Box + Send>, + ) -> Result<(), futures::future::ExecuteError + Send>>> { + let exit = self.on_exit.clone().map(Ok).compat(); + let future = Box::new(future.select(exit).then(|_| Ok(()))); + if let Err(err) = self.sender.unbounded_send(future) { + let kind = futures::future::ExecuteErrorKind::Shutdown; + Err(futures::future::ExecuteError::new(kind, err.into_inner())) + } else { + Ok(()) + } + } +} + +impl futures03::task::Spawn for SpawnTaskHandle { + fn spawn_obj(&self, future: futures03::task::FutureObj<'static, ()>) + -> Result<(), futures03::task::SpawnError> { + self.execute(Box::new(futures03::compat::Compat::new(future.unit_error()))) + .map_err(|_| futures03::task::SpawnError::shutdown()) + } +} + +/// Abstraction over a Substrate service. +pub trait AbstractService: 'static + Future + + Executor + Send>> + Send { + /// Type of block of this chain. + type Block: BlockT; + /// Backend storage for the client. + type Backend: 'static + sc_client_api::backend::Backend; + /// How to execute calls towards the runtime. + type CallExecutor: 'static + sc_client::CallExecutor + Send + Sync + Clone; + /// API that the runtime provides. + type RuntimeApi: Send + Sync; + /// Chain selection algorithm. + type SelectChain: sp_consensus::SelectChain; + /// Transaction pool. + type TransactionPool: TransactionPool + + TransactionPoolMaintainer; + /// Network specialization. + type NetworkSpecialization: NetworkSpecialization; + + /// Get event stream for telemetry connection established events. + fn telemetry_on_connect_stream(&self) -> futures03::channel::mpsc::UnboundedReceiver<()>; + + /// return a shared instance of Telemetry (if enabled) + fn telemetry(&self) -> Option; + + /// Spawns a task in the background that runs the future passed as parameter. + fn spawn_task(&self, task: impl Future + Send + 'static); + + /// Spawns a task in the background that runs the future passed as + /// parameter. The given task is considered essential, i.e. if it errors we + /// trigger a service exit. + fn spawn_essential_task(&self, task: impl Future + Send + 'static); + + /// Returns a handle for spawning tasks. + fn spawn_task_handle(&self) -> SpawnTaskHandle; + + /// Returns the keystore that stores keys. + fn keystore(&self) -> sc_keystore::KeyStorePtr; + + /// Starts an RPC query. + /// + /// The query is passed as a string and must be a JSON text similar to what an HTTP client + /// would for example send. + /// + /// Returns a `Future` that contains the optional response. + /// + /// If the request subscribes you to events, the `Sender` in the `RpcSession` object is used to + /// send back spontaneous events. + fn rpc_query(&self, mem: &RpcSession, request: &str) -> Box, Error = ()> + Send>; + + /// Get shared client instance. + fn client(&self) -> Arc>; + + /// Get clone of select chain. + fn select_chain(&self) -> Option; + + /// Get shared network instance. + fn network(&self) + -> Arc::Hash>>; + + /// Returns a receiver that periodically receives a status of the network. + fn network_status(&self, interval: Duration) -> mpsc::UnboundedReceiver<(NetworkStatus, NetworkState)>; + + /// Get shared transaction pool instance. + fn transaction_pool(&self) -> Arc; + + /// Get a handle to a future that will resolve on exit. + fn on_exit(&self) -> ::exit_future::Exit; +} + +impl AbstractService for + Service, TSc, NetworkStatus, + NetworkService, TExPool, TOc> +where + TBl: BlockT, + TBackend: 'static + sc_client_api::backend::Backend, + TExec: 'static + sc_client::CallExecutor + Send + Sync + Clone, + TRtApi: 'static + Send + Sync, + TSc: sp_consensus::SelectChain + 'static + Clone + Send, + TExPool: 'static + TransactionPool + + TransactionPoolMaintainer, + TOc: 'static + Send + Sync, + TNetSpec: NetworkSpecialization, +{ + type Block = TBl; + type Backend = TBackend; + type CallExecutor = TExec; + type RuntimeApi = TRtApi; + type SelectChain = TSc; + type TransactionPool = TExPool; + type NetworkSpecialization = TNetSpec; + + fn telemetry_on_connect_stream(&self) -> futures03::channel::mpsc::UnboundedReceiver<()> { + let (sink, stream) = futures03::channel::mpsc::unbounded(); + self._telemetry_on_connect_sinks.lock().push(sink); + stream + } + + fn telemetry(&self) -> Option { + self._telemetry.as_ref().map(|t| t.clone()) + } + + fn keystore(&self) -> sc_keystore::KeyStorePtr { + self.keystore.clone() + } + + fn spawn_task(&self, task: impl Future + Send + 'static) { + let exit = self.on_exit().map(Ok).compat(); + let task = task.select(exit).then(|_| Ok(())); + let _ = self.to_spawn_tx.unbounded_send(Box::new(task)); + } + + fn spawn_essential_task(&self, task: impl Future + Send + 'static) { + let essential_failed = self.essential_failed_tx.clone(); + let essential_task = std::panic::AssertUnwindSafe(task) + .catch_unwind() + .then(move |_| { + error!("Essential task failed. Shutting down service."); + let _ = essential_failed.send(()); + Ok(()) + }); + let exit = self.on_exit().map(Ok::<_, ()>).compat(); + let task = essential_task.select(exit).then(|_| Ok(())); + + let _ = self.to_spawn_tx.unbounded_send(Box::new(task)); + } + + fn spawn_task_handle(&self) -> SpawnTaskHandle { + SpawnTaskHandle { + sender: self.to_spawn_tx.clone(), + on_exit: self.on_exit(), + } + } + + fn rpc_query(&self, mem: &RpcSession, request: &str) -> Box, Error = ()> + Send> { + Box::new(self.rpc_handlers.handle_request(request, mem.metadata.clone())) + } + + fn client(&self) -> Arc> { + self.client.clone() + } + + fn select_chain(&self) -> Option { + self.select_chain.clone() + } + + fn network(&self) + -> Arc::Hash>> + { + self.network.clone() + } + + fn network_status(&self, interval: Duration) -> mpsc::UnboundedReceiver<(NetworkStatus, NetworkState)> { + let (sink, stream) = mpsc::unbounded(); + self.network_status_sinks.lock().push(interval, sink); + stream + } + + fn transaction_pool(&self) -> Arc { + self.transaction_pool.clone() + } + + fn on_exit(&self) -> exit_future::Exit { + self.exit.clone() + } +} + +impl Future for + Service +{ + type Item = (); + type Error = Error; + + fn poll(&mut self) -> Poll { + match self.essential_failed_rx.poll() { + Ok(Async::NotReady) => {}, + Ok(Async::Ready(_)) | Err(_) => { + // Ready(None) should not be possible since we hold a live + // sender. + return Err(Error::Other("Essential task failed.".into())); + } + } + + while let Ok(Async::Ready(Some(task_to_spawn))) = self.to_spawn_rx.poll() { + let executor = tokio_executor::DefaultExecutor::current(); + if let Err(err) = executor.execute(task_to_spawn) { + debug!( + target: "service", + "Failed to spawn background task: {:?}; falling back to manual polling", + err + ); + self.to_poll.push(err.into_future()); + } + } + + // Polling all the `to_poll` futures. + while let Some(pos) = self.to_poll.iter_mut().position(|t| t.poll().map(|t| t.is_ready()).unwrap_or(true)) { + let _ = self.to_poll.remove(pos); + } + + // The service future never ends. + Ok(Async::NotReady) + } +} + +impl Executor + Send>> for + Service +{ + fn execute( + &self, + future: Box + Send> + ) -> Result<(), futures::future::ExecuteError + Send>>> { + if let Err(err) = self.to_spawn_tx.unbounded_send(future) { + let kind = futures::future::ExecuteErrorKind::Shutdown; + Err(futures::future::ExecuteError::new(kind, err.into_inner())) + } else { + Ok(()) + } + } +} + +/// Builds a never-ending future that continuously polls the network. +/// +/// The `status_sink` contain a list of senders to send a periodic network status to. +fn build_network_future< + B: BlockT, + C: sc_client::BlockchainEvents, + S: sc_network::specialization::NetworkSpecialization, + H: sc_network::ExHashT +> ( + roles: Roles, + mut network: sc_network::NetworkWorker, + client: Arc, + status_sinks: Arc, NetworkState)>>>, + rpc_rx: futures03::channel::mpsc::UnboundedReceiver>, + should_have_peers: bool, +) -> impl Future { + // Compatibility shim while we're transitioning to stable Futures. + // See https://github.com/paritytech/substrate/issues/3099 + let mut rpc_rx = futures03::compat::Compat::new(rpc_rx.map(|v| Ok::<_, ()>(v))); + + let mut imported_blocks_stream = client.import_notification_stream().fuse() + .map(|v| Ok::<_, ()>(v)).compat(); + let mut finality_notification_stream = client.finality_notification_stream().fuse() + .map(|v| Ok::<_, ()>(v)).compat(); + + futures::future::poll_fn(move || { + let before_polling = Instant::now(); + + // We poll `imported_blocks_stream`. + while let Ok(Async::Ready(Some(notification))) = imported_blocks_stream.poll() { + network.on_block_imported(notification.hash, notification.header, Vec::new(), notification.is_new_best); + } + + // We poll `finality_notification_stream`, but we only take the last event. + let mut last = None; + while let Ok(Async::Ready(Some(item))) = finality_notification_stream.poll() { + last = Some(item); + } + if let Some(notification) = last { + network.on_block_finalized(notification.hash, notification.header); + } + + // Poll the RPC requests and answer them. + while let Ok(Async::Ready(Some(request))) = rpc_rx.poll() { + match request { + sc_rpc::system::Request::Health(sender) => { + let _ = sender.send(sc_rpc::system::Health { + peers: network.peers_debug_info().len(), + is_syncing: network.service().is_major_syncing(), + should_have_peers, + }); + }, + sc_rpc::system::Request::Peers(sender) => { + let _ = sender.send(network.peers_debug_info().into_iter().map(|(peer_id, p)| + sc_rpc::system::PeerInfo { + peer_id: peer_id.to_base58(), + roles: format!("{:?}", p.roles), + protocol_version: p.protocol_version, + best_hash: p.best_hash, + best_number: p.best_number, + } + ).collect()); + } + sc_rpc::system::Request::NetworkState(sender) => { + if let Some(network_state) = serde_json::to_value(&network.network_state()).ok() { + let _ = sender.send(network_state); + } + } + sc_rpc::system::Request::NetworkAddReservedPeer(peer_addr, sender) => { + let x = network.add_reserved_peer(peer_addr) + .map_err(sc_rpc::system::error::Error::MalformattedPeerArg); + let _ = sender.send(x); + } + sc_rpc::system::Request::NetworkRemoveReservedPeer(peer_id, sender) => { + let _ = match peer_id.parse::() { + Ok(peer_id) => { + network.remove_reserved_peer(peer_id); + sender.send(Ok(())) + } + Err(e) => sender.send(Err(sc_rpc::system::error::Error::MalformattedPeerArg( + e.to_string(), + ))), + }; + } + sc_rpc::system::Request::NodeRoles(sender) => { + use sc_rpc::system::NodeRole; + + let node_roles = (0 .. 8) + .filter(|&bit_number| (roles.bits() >> bit_number) & 1 == 1) + .map(|bit_number| match Roles::from_bits(1 << bit_number) { + Some(Roles::AUTHORITY) => NodeRole::Authority, + Some(Roles::LIGHT) => NodeRole::LightClient, + Some(Roles::FULL) => NodeRole::Full, + _ => NodeRole::UnknownRole(bit_number), + }) + .collect(); + + let _ = sender.send(node_roles); + } + }; + } + + // Interval report for the external API. + status_sinks.lock().poll(|| { + let status = NetworkStatus { + sync_state: network.sync_state(), + best_seen_block: network.best_seen_block(), + num_sync_peers: network.num_sync_peers(), + num_connected_peers: network.num_connected_peers(), + num_active_peers: network.num_active_peers(), + average_download_per_sec: network.average_download_per_sec(), + average_upload_per_sec: network.average_upload_per_sec(), + }; + let state = network.network_state(); + (status, state) + }); + + // Main network polling. + let mut net_poll = futures03::future::poll_fn(|cx| futures03::future::Future::poll(Pin::new(&mut network), cx)) + .compat(); + if let Ok(Async::Ready(())) = net_poll.poll().map_err(|err| { + warn!(target: "service", "Error in network: {:?}", err); + }) { + return Ok(Async::Ready(())); + } + + // Now some diagnostic for performances. + let polling_dur = before_polling.elapsed(); + log!( + target: "service", + if polling_dur >= Duration::from_secs(1) { Level::Warn } else { Level::Trace }, + "Polling the network future took {:?}", + polling_dur + ); + + Ok(Async::NotReady) + }) +} + +/// Overview status of the network. +#[derive(Clone)] +pub struct NetworkStatus { + /// Current global sync state. + pub sync_state: sc_network::SyncState, + /// Target sync block number. + pub best_seen_block: Option>, + /// Number of peers participating in syncing. + pub num_sync_peers: u32, + /// Total number of connected peers + pub num_connected_peers: usize, + /// Total number of active peers. + pub num_active_peers: usize, + /// Downloaded bytes per second averaged over the past few seconds. + pub average_download_per_sec: u64, + /// Uploaded bytes per second averaged over the past few seconds. + pub average_upload_per_sec: u64, +} + +impl Drop for + Service +{ + fn drop(&mut self) { + debug!(target: "service", "Substrate service shutdown"); + if let Some(signal) = self.signal.take() { + let _ = signal.fire(); + } + } +} + +/// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive. +#[cfg(not(target_os = "unknown"))] +fn start_rpc_servers sc_rpc_server::RpcHandler>( + config: &Configuration, + mut gen_handler: H +) -> Result, error::Error> { + fn maybe_start_server(address: Option, mut start: F) -> Result, io::Error> + where F: FnMut(&SocketAddr) -> Result, + { + Ok(match address { + Some(mut address) => Some(start(&address) + .or_else(|e| match e.kind() { + io::ErrorKind::AddrInUse | + io::ErrorKind::PermissionDenied => { + warn!("Unable to bind RPC server to {}. Trying random port.", address); + address.set_port(0); + start(&address) + }, + _ => Err(e), + })?), + None => None, + }) + } + + Ok(Box::new(( + maybe_start_server( + config.rpc_http, + |address| sc_rpc_server::start_http(address, config.rpc_cors.as_ref(), gen_handler()), + )?, + maybe_start_server( + config.rpc_ws, + |address| sc_rpc_server::start_ws( + address, + config.rpc_ws_max_connections, + config.rpc_cors.as_ref(), + gen_handler(), + ), + )?.map(Mutex::new), + ))) +} + +/// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive. +#[cfg(target_os = "unknown")] +fn start_rpc_servers sc_rpc_server::RpcHandler>( + _: &Configuration, + _: H +) -> Result, error::Error> { + Ok(Box::new(())) +} + +/// An RPC session. Used to perform in-memory RPC queries (ie. RPC queries that don't go through +/// the HTTP or WebSockets server). +#[derive(Clone)] +pub struct RpcSession { + metadata: sc_rpc::Metadata, +} + +impl RpcSession { + /// Creates an RPC session. + /// + /// The `sender` is stored inside the `RpcSession` and is used to communicate spontaneous JSON + /// messages. + /// + /// The `RpcSession` must be kept alive in order to receive messages on the sender. + pub fn new(sender: mpsc::Sender) -> RpcSession { + RpcSession { + metadata: sender.into(), + } + } +} + +/// Transaction pool adapter. +pub struct TransactionPoolAdapter { + imports_external_transactions: bool, + pool: Arc

, + client: Arc, + executor: TaskExecutor, +} + +/// Get transactions for propagation. +/// +/// Function extracted to simplify the test and prevent creating `ServiceFactory`. +fn transactions_to_propagate(pool: &Pool) + -> Vec<(H, B::Extrinsic)> +where + Pool: TransactionPool, + B: BlockT, + H: std::hash::Hash + Eq + sp_runtime::traits::Member + sp_runtime::traits::MaybeSerialize, + E: IntoPoolError + From, +{ + pool.ready() + .filter(|t| t.is_propagateable()) + .map(|t| { + let hash = t.hash().clone(); + let ex: B::Extrinsic = t.data().clone(); + (hash, ex) + }) + .collect() +} + +impl sc_network::TransactionPool for + TransactionPoolAdapter +where + C: sc_network::ClientHandle + Send + Sync, + Pool: 'static + TransactionPool, + B: BlockT, + H: std::hash::Hash + Eq + sp_runtime::traits::Member + sp_runtime::traits::MaybeSerialize, + E: 'static + IntoPoolError + From, +{ + fn transactions(&self) -> Vec<(H, ::Extrinsic)> { + transactions_to_propagate(&*self.pool) + } + + fn hash_of(&self, transaction: &B::Extrinsic) -> H { + self.pool.hash_of(transaction) + } + + fn import( + &self, + report_handle: ReportHandle, + who: PeerId, + reputation_change_good: sc_network::ReputationChange, + reputation_change_bad: sc_network::ReputationChange, + transaction: B::Extrinsic + ) { + if !self.imports_external_transactions { + debug!("Transaction rejected"); + return; + } + + let encoded = transaction.encode(); + match Decode::decode(&mut &encoded[..]) { + Ok(uxt) => { + let best_block_id = BlockId::hash(self.client.info().best_hash); + let import_future = self.pool.submit_one(&best_block_id, uxt); + let import_future = import_future + .then(move |import_result| { + match import_result { + Ok(_) => report_handle.report_peer(who, reputation_change_good), + Err(e) => match e.into_pool_error() { + Ok(sp_transaction_pool::error::Error::AlreadyImported(_)) => (), + Ok(e) => { + report_handle.report_peer(who, reputation_change_bad); + debug!("Error adding transaction to the pool: {:?}", e) + } + Err(e) => debug!("Error converting pool error: {:?}", e), + } + } + ready(Ok(())) + }) + .compat(); + + if let Err(e) = self.executor.execute(Box::new(import_future)) { + warn!("Error scheduling extrinsic import: {:?}", e); + } + } + Err(e) => debug!("Error decoding transaction {}", e), + } + } + + fn on_broadcasted(&self, propagations: HashMap>) { + self.pool.on_broadcasted(propagations) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures03::executor::block_on; + use sp_consensus::SelectChain; + use sp_runtime::traits::BlindCheckable; + use substrate_test_runtime_client::{prelude::*, runtime::{Extrinsic, Transfer}}; + use sc_transaction_pool::{BasicPool, FullChainApi}; + + #[test] + fn should_not_propagate_transactions_that_are_marked_as_such() { + // given + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); + let best = longest_chain.best_chain().unwrap(); + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + block_on(pool.submit_one(&BlockId::hash(best.hash()), Extrinsic::IncludeData(vec![1]))).unwrap(); + assert_eq!(pool.status().ready, 2); + + // when + let transactions = transactions_to_propagate(&*pool); + + // then + assert_eq!(transactions.len(), 1); + assert!(transactions[0].1.clone().check().is_ok()); + // this should not panic + let _ = transactions[0].1.transfer(); + } +} diff --git a/core/service/src/status_sinks.rs b/client/service/src/status_sinks.rs similarity index 91% rename from core/service/src/status_sinks.rs rename to client/service/src/status_sinks.rs index 079ecf6353b1f..205a22d70f9f4 100644 --- a/core/service/src/status_sinks.rs +++ b/client/service/src/status_sinks.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -113,14 +113,14 @@ mod tests { use std::time::Duration; #[test] - fn basic_usage() { - let mut status_sinks = StatusSinks::new(); + fn works() { + // We're not testing that the `StatusSink` properly enforces an order in the intervals, as + // this easily causes test failures on busy CPUs. - let (tx1, rx1) = mpsc::unbounded(); - status_sinks.push(Duration::from_millis(200), tx1); + let mut status_sinks = StatusSinks::new(); - let (tx2, rx2) = mpsc::unbounded(); - status_sinks.push(Duration::from_millis(500), tx2); + let (tx, rx) = mpsc::unbounded(); + status_sinks.push(Duration::from_millis(100), tx); let mut runtime = tokio::runtime::Runtime::new().unwrap(); @@ -130,15 +130,15 @@ mod tests { Ok(Async::NotReady) })); - let done = rx1 + let done = rx .into_future() .and_then(|(item, rest)| { assert_eq!(item, Some(6)); rest.into_future() }) - .and_then(|(item, _)| { + .and_then(|(item, rest)| { assert_eq!(item, Some(7)); - rx2.into_future() + rest.into_future() }) .map(|(item, _)| { assert_eq!(item, Some(8)); diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml new file mode 100644 index 0000000000000..2789bfda0fe19 --- /dev/null +++ b/client/service/test/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "sc-service-test" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +tempfile = "3.1.0" +tokio = "0.1.22" +futures = "0.1.29" +log = "0.4.8" +env_logger = "0.7.0" +fdlimit = "0.1.1" +futures03 = { package = "futures", version = "0.3.1", features = ["compat"] } +sc-service = { version = "2.0.0", default-features = false, path = "../../service" } +sc-network = { version = "0.8", path = "../../network" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +sc-client = { version = "2.0.0", path = "../../" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-transaction-pool = { version = "2.0.0", path = "../../../primitives/transaction-pool" } diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs new file mode 100644 index 0000000000000..06a1edd189a29 --- /dev/null +++ b/client/service/test/src/lib.rs @@ -0,0 +1,532 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Service integration test utils. + +use std::iter; +use std::sync::{Arc, Mutex, MutexGuard}; +use std::net::Ipv4Addr; +use std::time::Duration; +use log::info; +use futures::{Future, Stream, Poll}; +use tempfile::TempDir; +use tokio::{runtime::Runtime, prelude::FutureExt}; +use tokio::timer::Interval; +use sc_service::{ + AbstractService, + ChainSpec, + Configuration, + config::{DatabaseConfig, KeystoreConfig}, + Roles, + Error, +}; +use sc_network::{multiaddr, Multiaddr, NetworkStateInfo}; +use sc_network::config::{NetworkConfiguration, TransportConfig, NodeKeyConfig, Secret, NonReservedPeerMode}; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use sp_transaction_pool::TransactionPool; + +/// Maximum duration of single wait call. +const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); + +struct TestNet { + runtime: Runtime, + authority_nodes: Vec<(usize, SyncService, U, Multiaddr)>, + full_nodes: Vec<(usize, SyncService, U, Multiaddr)>, + light_nodes: Vec<(usize, SyncService, Multiaddr)>, + chain_spec: ChainSpec, + base_port: u16, + nodes: usize, +} + +/// Wraps around an `Arc` and implements `Future`. +pub struct SyncService(Arc>); + +impl SyncService { + pub fn get(&self) -> MutexGuard { + self.0.lock().unwrap() + } +} + +impl Clone for SyncService { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl From for SyncService { + fn from(service: T) -> Self { + SyncService(Arc::new(Mutex::new(service))) + } +} + +impl> Future for SyncService { + type Item = (); + type Error = sc_service::Error; + + fn poll(&mut self) -> Poll { + self.0.lock().unwrap().poll() + } +} + +impl TestNet +where F: Send + 'static, L: Send +'static, U: Clone + Send + 'static +{ + pub fn run_until_all_full( + &mut self, + full_predicate: FP, + light_predicate: LP, + ) + where + FP: Send + Fn(usize, &SyncService) -> bool + 'static, + LP: Send + Fn(usize, &SyncService) -> bool + 'static, + { + let full_nodes = self.full_nodes.clone(); + let light_nodes = self.light_nodes.clone(); + let interval = Interval::new_interval(Duration::from_millis(100)) + .map_err(|_| ()) + .for_each(move |_| { + let full_ready = full_nodes.iter().all(|&(ref id, ref service, _, _)| + full_predicate(*id, service) + ); + + if !full_ready { + return Ok(()); + } + + let light_ready = light_nodes.iter().all(|&(ref id, ref service, _)| + light_predicate(*id, service) + ); + + if !light_ready { + Ok(()) + } else { + Err(()) + } + }) + .timeout(MAX_WAIT_TIME); + + match self.runtime.block_on(interval) { + Ok(()) => unreachable!("interval always fails; qed"), + Err(ref err) if err.is_inner() => (), + Err(_) => panic!("Waited for too long"), + } + } +} + +fn node_config ( + index: usize, + spec: &ChainSpec, + role: Roles, + key_seed: Option, + base_port: u16, + root: &TempDir, +) -> Configuration<(), G, E> +{ + let root = root.path().join(format!("node-{}", index)); + + let config_path = Some(String::from(root.join("network").to_str().unwrap())); + let net_config_path = config_path.clone(); + + let network_config = NetworkConfiguration { + config_path, + net_config_path, + listen_addresses: vec! [ + iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) + .chain(iter::once(multiaddr::Protocol::Tcp(base_port + index as u16))) + .collect() + ], + public_addresses: vec![], + boot_nodes: vec![], + node_key: NodeKeyConfig::Ed25519(Secret::New), + in_peers: 50, + out_peers: 450, + reserved_nodes: vec![], + non_reserved_mode: NonReservedPeerMode::Accept, + sentry_nodes: vec![], + client_version: "network/test/0.1".to_owned(), + node_name: "unknown".to_owned(), + transport: TransportConfig::Normal { + enable_mdns: false, + allow_private_ipv4: true, + wasm_external_transport: None, + }, + max_parallel_downloads: NetworkConfiguration::default().max_parallel_downloads, + }; + + Configuration { + impl_name: "network-test-impl", + impl_version: "0.1", + impl_commit: "", + roles: role, + transaction_pool: Default::default(), + network: network_config, + keystore: KeystoreConfig::Path { + path: root.join("key"), + password: None + }, + config_dir: Some(root.clone()), + database: DatabaseConfig::Path { + path: root.join("db"), + cache_size: None + }, + state_cache_size: 16777216, + state_cache_child_ratio: None, + pruning: Default::default(), + chain_spec: (*spec).clone(), + custom: Default::default(), + name: format!("Node {}", index), + wasm_method: sc_service::config::WasmExecutionMethod::Interpreted, + execution_strategies: Default::default(), + rpc_http: None, + rpc_ws: None, + rpc_ws_max_connections: None, + rpc_cors: None, + grafana_port: None, + telemetry_endpoints: None, + telemetry_external_transport: None, + default_heap_pages: None, + offchain_worker: false, + sentry_mode: false, + force_authoring: false, + disable_grandpa: false, + dev_key_seed: key_seed, + tracing_targets: None, + tracing_receiver: Default::default(), + } +} + +impl TestNet where + F: AbstractService, + L: AbstractService, + E: Clone, +{ + fn new( + temp: &TempDir, + spec: ChainSpec, + full: impl Iterator) -> Result<(F, U), Error>>, + light: impl Iterator) -> Result>, + authorities: impl Iterator) -> Result<(F, U), Error> + )>, + base_port: u16 + ) -> TestNet { + let _ = env_logger::try_init(); + fdlimit::raise_fd_limit(); + let runtime = Runtime::new().expect("Error creating tokio runtime"); + let mut net = TestNet { + runtime, + authority_nodes: Default::default(), + full_nodes: Default::default(), + light_nodes: Default::default(), + chain_spec: spec, + base_port, + nodes: 0, + }; + net.insert_nodes(temp, full, light, authorities); + net + } + + fn insert_nodes( + &mut self, + temp: &TempDir, + full: impl Iterator) -> Result<(F, U), Error>>, + light: impl Iterator) -> Result>, + authorities: impl Iterator) -> Result<(F, U), Error>)> + ) { + let executor = self.runtime.executor(); + + for (key, authority) in authorities { + let node_config = node_config( + self.nodes, + &self.chain_spec, + Roles::AUTHORITY, + Some(key), + self.base_port, + &temp, + ); + let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); + let (service, user_data) = authority(node_config).expect("Error creating test node service"); + let service = SyncService::from(service); + + executor.spawn(service.clone().map_err(|_| ())); + let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); + self.authority_nodes.push((self.nodes, service, user_data, addr)); + self.nodes += 1; + } + + for full in full { + let node_config = node_config(self.nodes, &self.chain_spec, Roles::FULL, None, self.base_port, &temp); + let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); + let (service, user_data) = full(node_config).expect("Error creating test node service"); + let service = SyncService::from(service); + + executor.spawn(service.clone().map_err(|_| ())); + let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); + self.full_nodes.push((self.nodes, service, user_data, addr)); + self.nodes += 1; + } + + for light in light { + let node_config = node_config(self.nodes, &self.chain_spec, Roles::LIGHT, None, self.base_port, &temp); + let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); + let service = SyncService::from(light(node_config).expect("Error creating test node service")); + + executor.spawn(service.clone().map_err(|_| ())); + let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); + self.light_nodes.push((self.nodes, service, addr)); + self.nodes += 1; + } + } +} + +fn tempdir_with_prefix(prefix: &str) -> TempDir { + tempfile::Builder::new().prefix(prefix).tempdir().expect("Error creating test dir") +} + +pub fn connectivity( + spec: ChainSpec, + full_builder: Fb, + light_builder: Lb, +) where + E: Clone, + Fb: Fn(Configuration<(), G, E>) -> Result, + F: AbstractService, + Lb: Fn(Configuration<(), G, E>) -> Result, + L: AbstractService, +{ + const NUM_FULL_NODES: usize = 5; + const NUM_LIGHT_NODES: usize = 5; + + let expected_full_connections = NUM_FULL_NODES - 1 + NUM_LIGHT_NODES; + let expected_light_connections = NUM_FULL_NODES; + + { + let temp = tempdir_with_prefix("substrate-connectivity-test"); + let runtime = { + let mut network = TestNet::new( + &temp, + spec.clone(), + (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), + (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), + // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise + // the type of the closure cannot be inferred. + (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), + 30400, + ); + info!("Checking star topology"); + let first_address = network.full_nodes[0].3.clone(); + for (_, service, _, _) in network.full_nodes.iter().skip(1) { + service.get().network().add_reserved_peer(first_address.to_string()) + .expect("Error adding reserved peer"); + } + for (_, service, _) in network.light_nodes.iter() { + service.get().network().add_reserved_peer(first_address.to_string()) + .expect("Error adding reserved peer"); + } + + network.run_until_all_full( + move |_index, service| service.get().network().num_connected() + == expected_full_connections, + move |_index, service| service.get().network().num_connected() + == expected_light_connections, + ); + + network.runtime + }; + + runtime.shutdown_now().wait().expect("Error shutting down runtime"); + + temp.close().expect("Error removing temp dir"); + } + { + let temp = tempdir_with_prefix("substrate-connectivity-test"); + { + let mut network = TestNet::new( + &temp, + spec, + (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), + (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), + // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise + // the type of the closure cannot be inferred. + (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), + 30400, + ); + info!("Checking linked topology"); + let mut address = network.full_nodes[0].3.clone(); + let max_nodes = std::cmp::max(NUM_FULL_NODES, NUM_LIGHT_NODES); + for i in 0..max_nodes { + if i != 0 { + if let Some((_, service, _, node_id)) = network.full_nodes.get(i) { + service.get().network().add_reserved_peer(address.to_string()) + .expect("Error adding reserved peer"); + address = node_id.clone(); + } + } + + if let Some((_, service, node_id)) = network.light_nodes.get(i) { + service.get().network().add_reserved_peer(address.to_string()) + .expect("Error adding reserved peer"); + address = node_id.clone(); + } + } + + network.run_until_all_full( + move |_index, service| service.get().network().num_connected() + == expected_full_connections, + move |_index, service| service.get().network().num_connected() + == expected_light_connections, + ); + } + temp.close().expect("Error removing temp dir"); + } +} + +pub fn sync( + spec: ChainSpec, + full_builder: Fb, + light_builder: Lb, + mut make_block_and_import: B, + mut extrinsic_factory: ExF +) where + Fb: Fn(Configuration<(), G, E>) -> Result<(F, U), Error>, + F: AbstractService, + Lb: Fn(Configuration<(), G, E>) -> Result, + L: AbstractService, + B: FnMut(&F, &mut U), + ExF: FnMut(&F, &U) -> ::Extrinsic, + U: Clone + Send + 'static, + E: Clone, +{ + const NUM_FULL_NODES: usize = 10; + // FIXME: BABE light client support is currently not working. + const NUM_LIGHT_NODES: usize = 10; + const NUM_BLOCKS: usize = 512; + let temp = tempdir_with_prefix("substrate-sync-test"); + let mut network = TestNet::new( + &temp, + spec.clone(), + (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg) }), + (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), + // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise + // the type of the closure cannot be inferred. + (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg) })), + 30500, + ); + info!("Checking block sync"); + let first_address = { + let &mut (_, ref first_service, ref mut first_user_data, _) = &mut network.full_nodes[0]; + for i in 0 .. NUM_BLOCKS { + if i % 128 == 0 { + info!("Generating #{}", i + 1); + } + + make_block_and_import(&first_service.get(), first_user_data); + } + network.full_nodes[0].3.clone() + }; + + info!("Running sync"); + for (_, service, _, _) in network.full_nodes.iter().skip(1) { + service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + } + for (_, service, _) in network.light_nodes.iter() { + service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + } + network.run_until_all_full( + |_index, service| + service.get().client().chain_info().best_number == (NUM_BLOCKS as u32).into(), + |_index, service| + service.get().client().chain_info().best_number == (NUM_BLOCKS as u32).into(), + ); + + info!("Checking extrinsic propagation"); + let first_service = network.full_nodes[0].1.clone(); + let first_user_data = &network.full_nodes[0].2; + let best_block = BlockId::number(first_service.get().client().chain_info().best_number); + let extrinsic = extrinsic_factory(&first_service.get(), first_user_data); + futures03::executor::block_on(first_service.get().transaction_pool().submit_one(&best_block, extrinsic)).unwrap(); + network.run_until_all_full( + |_index, service| service.get().transaction_pool().ready().count() == 1, + |_index, _service| true, + ); +} + +pub fn consensus( + spec: ChainSpec, + full_builder: Fb, + light_builder: Lb, + authorities: impl IntoIterator +) where + Fb: Fn(Configuration<(), G, E>) -> Result, + F: AbstractService, + Lb: Fn(Configuration<(), G, E>) -> Result, + L: AbstractService, + E: Clone, +{ + const NUM_FULL_NODES: usize = 10; + const NUM_LIGHT_NODES: usize = 10; + const NUM_BLOCKS: usize = 10; // 10 * 2 sec block production time = ~20 seconds + let temp = tempdir_with_prefix("substrate-conensus-test"); + let mut network = TestNet::new( + &temp, + spec.clone(), + (0..NUM_FULL_NODES / 2).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), + (0..NUM_LIGHT_NODES / 2).map(|_| { |cfg| light_builder(cfg) }), + authorities.into_iter().map(|key| (key, { |cfg| full_builder(cfg).map(|s| (s, ())) })), + 30600, + ); + + info!("Checking consensus"); + let first_address = network.authority_nodes[0].3.clone(); + for (_, service, _, _) in network.full_nodes.iter() { + service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + } + for (_, service, _) in network.light_nodes.iter() { + service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + } + for (_, service, _, _) in network.authority_nodes.iter().skip(1) { + service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + } + network.run_until_all_full( + |_index, service| + service.get().client().chain_info().finalized_number >= (NUM_BLOCKS as u32 / 2).into(), + |_index, service| + service.get().client().chain_info().best_number >= (NUM_BLOCKS as u32 / 2).into(), + ); + + info!("Adding more peers"); + network.insert_nodes( + &temp, + (0..NUM_FULL_NODES / 2).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), + (0..NUM_LIGHT_NODES / 2).map(|_| { |cfg| light_builder(cfg) }), + // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise + // the type of the closure cannot be inferred. + (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), + ); + for (_, service, _, _) in network.full_nodes.iter() { + service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + } + for (_, service, _) in network.light_nodes.iter() { + service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + } + network.run_until_all_full( + |_index, service| + service.get().client().chain_info().finalized_number >= (NUM_BLOCKS as u32).into(), + |_index, service| + service.get().client().chain_info().best_number >= (NUM_BLOCKS as u32).into(), + ); +} diff --git a/client/src/call_executor.rs b/client/src/call_executor.rs new file mode 100644 index 0000000000000..6a41eba0108c0 --- /dev/null +++ b/client/src/call_executor.rs @@ -0,0 +1,241 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{sync::Arc, panic::UnwindSafe, result, cell::RefCell}; +use codec::{Encode, Decode}; +use sp_runtime::{ + generic::BlockId, traits::{Block as BlockT, HasherFor}, +}; +use sp_state_machine::{ + self, OverlayedChanges, Ext, ExecutionManager, StateMachine, ExecutionStrategy, + backend::Backend as _, StorageProof, +}; +use sc_executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; +use sp_externalities::Extensions; +use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor}; +use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache}; +use sc_client_api::{backend, call_executor::CallExecutor}; + +/// Call executor that executes methods locally, querying all required +/// data from local backend. +pub struct LocalCallExecutor { + backend: Arc, + executor: E, +} + +impl LocalCallExecutor { + /// Creates new instance of local call executor. + pub fn new( + backend: Arc, + executor: E, + ) -> Self { + LocalCallExecutor { + backend, + executor, + } + } +} + +impl Clone for LocalCallExecutor where E: Clone { + fn clone(&self) -> Self { + LocalCallExecutor { + backend: self.backend.clone(), + executor: self.executor.clone(), + } + } +} + +impl CallExecutor for LocalCallExecutor +where + B: backend::Backend, + E: CodeExecutor + RuntimeInfo, + Block: BlockT, +{ + type Error = E::Error; + + type Backend = B; + + fn call( + &self, + id: &BlockId, + method: &str, + call_data: &[u8], + strategy: ExecutionStrategy, + extensions: Option, + ) -> sp_blockchain::Result> { + let mut changes = OverlayedChanges::default(); + let state = self.backend.state_at(*id)?; + let return_data = StateMachine::new( + &state, + self.backend.changes_trie_storage(), + &mut changes, + &self.executor, + method, + call_data, + extensions.unwrap_or_default(), + ).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + strategy.get_manager(), + None, + )?; + { + let _lock = self.backend.get_import_lock().read(); + self.backend.destroy_state(state)?; + } + Ok(return_data.into_encoded()) + } + + fn contextual_call< + 'a, + IB: Fn() -> sp_blockchain::Result<()>, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >( + &self, + initialize_block_fn: IB, + at: &BlockId, + method: &str, + call_data: &[u8], + changes: &RefCell, + storage_transaction_cache: Option<&RefCell< + StorageTransactionCache + >>, + initialize_block: InitializeBlock<'a, Block>, + execution_manager: ExecutionManager, + native_call: Option, + recorder: &Option>, + extensions: Option, + ) -> Result, sp_blockchain::Error> where ExecutionManager: Clone { + match initialize_block { + InitializeBlock::Do(ref init_block) + if init_block.borrow().as_ref().map(|id| id != at).unwrap_or(true) => { + initialize_block_fn()?; + }, + // We don't need to initialize the runtime at a block. + _ => {}, + } + + let mut state = self.backend.state_at(*at)?; + + let mut storage_transaction_cache = storage_transaction_cache.map(|c| c.borrow_mut()); + + let result = match recorder { + Some(recorder) => { + let trie_state = state.as_trie_backend() + .ok_or_else(|| + Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof) + as Box + )?; + + let backend = sp_state_machine::ProvingBackend::new_with_recorder( + trie_state, + recorder.clone(), + ); + + StateMachine::new( + &backend, + self.backend.changes_trie_storage(), + &mut *changes.borrow_mut(), + &self.executor, + method, + call_data, + extensions.unwrap_or_default(), + ) + // TODO: https://github.com/paritytech/substrate/issues/4455 + // .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c)) + .execute_using_consensus_failure_handler(execution_manager, native_call) + } + None => StateMachine::new( + &state, + self.backend.changes_trie_storage(), + &mut *changes.borrow_mut(), + &self.executor, + method, + call_data, + extensions.unwrap_or_default(), + ) + .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c)) + .execute_using_consensus_failure_handler(execution_manager, native_call) + }?; + { + let _lock = self.backend.get_import_lock().read(); + self.backend.destroy_state(state)?; + } + Ok(result) + } + + fn runtime_version(&self, id: &BlockId) -> sp_blockchain::Result { + let mut overlay = OverlayedChanges::default(); + let state = self.backend.state_at(*id)?; + let mut cache = StorageTransactionCache::::default(); + + let mut ext = Ext::new( + &mut overlay, + &mut cache, + &state, + self.backend.changes_trie_storage(), + None, + ); + let version = self.executor.runtime_version(&mut ext); + { + let _lock = self.backend.get_import_lock().read(); + self.backend.destroy_state(state)?; + } + version.map_err(|e| sp_blockchain::Error::VersionInvalid(format!("{:?}", e)).into()) + } + + fn prove_at_trie_state>>( + &self, + trie_state: &sp_state_machine::TrieBackend>, + overlay: &mut OverlayedChanges, + method: &str, + call_data: &[u8] + ) -> Result<(Vec, StorageProof), sp_blockchain::Error> { + sp_state_machine::prove_execution_on_trie_backend( + trie_state, + overlay, + &self.executor, + method, + call_data, + ) + .map_err(Into::into) + } + + fn native_runtime_version(&self) -> Option<&NativeVersion> { + Some(self.executor.native_version()) + } +} + +impl sp_version::GetRuntimeVersion for LocalCallExecutor + where + B: backend::Backend, + E: CodeExecutor + RuntimeInfo, + Block: BlockT, +{ + fn native_version(&self) -> &sp_version::NativeVersion { + self.executor.native_version() + } + + fn runtime_version( + &self, + at: &BlockId, + ) -> Result { + CallExecutor::runtime_version(self, at).map_err(|e| format!("{:?}", e)) + } +} diff --git a/core/client/src/cht.rs b/client/src/cht.rs similarity index 86% rename from core/client/src/cht.rs rename to client/src/cht.rs index 63a5b39c26904..29f19a77504b9 100644 --- a/core/client/src/cht.rs +++ b/client/src/cht.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -25,15 +25,16 @@ use hash_db; use codec::Encode; -use trie; +use sp_trie; -use primitives::{H256, convert_hash}; -use sr_primitives::traits::{Header as HeaderT, SimpleArithmetic, Zero, One}; -use state_machine::backend::InMemory as InMemoryState; -use state_machine::{MemoryDB, TrieBackend, Backend as StateBackend, - prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend}; +use sp_core::{H256, convert_hash}; +use sp_runtime::traits::{Header as HeaderT, SimpleArithmetic, Zero, One}; +use sp_state_machine::{ + MemoryDB, TrieBackend, Backend as StateBackend, StorageProof, InMemoryBackend, + prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend +}; -use crate::error::{Error as ClientError, Result as ClientResult}; +use sp_blockchain::{Error as ClientError, 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. @@ -62,6 +63,19 @@ pub fn is_build_required(cht_size: N, block_num: N) -> Option Some(block_cht_num - two) } +/// Returns Some(max_cht_number) if CHT has ever been built given maximal canonical block number. +pub fn max_cht_number(cht_size: N, max_canonical_block: N) -> Option + where + N: Clone + SimpleArithmetic, +{ + let max_cht_number = block_to_cht_number(cht_size, max_canonical_block)?; + let two = N::one() + N::one(); + if max_cht_number < two { + return None; + } + Some(max_cht_number - two) +} + /// Compute a CHT root from an iterator of block hashes. Fails if shorter than /// SIZE items. The items are assumed to proceed sequentially from `start_number(cht_num)`. /// Discards the trie's nodes. @@ -76,8 +90,8 @@ pub fn compute_root( Hasher::Out: Ord, I: IntoIterator>>, { - use trie::TrieConfiguration; - Ok(trie::trie_types::Layout::::trie_root( + use sp_trie::TrieConfiguration; + Ok(sp_trie::trie_types::Layout::::trie_root( build_pairs::(cht_size, cht_num, hashes)? )) } @@ -88,19 +102,19 @@ pub fn build_proof( cht_num: Header::Number, blocks: BlocksI, hashes: HashesI -) -> ClientResult>> +) -> ClientResult where Header: HeaderT, Hasher: hash_db::Hasher, - Hasher::Out: Ord, + Hasher::Out: Ord + codec::Codec, BlocksI: IntoIterator, HashesI: IntoIterator>>, { let transaction = build_pairs::(cht_size, cht_num, hashes)? .into_iter() - .map(|(k, v)| (None, k, Some(v))) + .map(|(k, v)| (k, Some(v))) .collect::>(); - let mut storage = InMemoryState::::default().update(transaction); + let mut storage = InMemoryBackend::::default().update(vec![(None, transaction)]); let trie_storage = storage.as_trie_backend() .expect("InMemoryState::as_trie_backend always returns Some; qed"); prove_read_on_trie_backend( @@ -114,12 +128,12 @@ pub fn check_proof( local_root: Header::Hash, local_number: Header::Number, remote_hash: Header::Hash, - remote_proof: Vec> + remote_proof: StorageProof, ) -> ClientResult<()> where Header: HeaderT, Hasher: hash_db::Hasher, - Hasher::Out: Ord, + Hasher::Out: Ord + codec::Codec, { do_check_proof::( local_root, @@ -148,7 +162,7 @@ pub fn check_proof_on_proving_backend( where Header: HeaderT, Hasher: hash_db::Hasher, - Hasher::Out: Ord, + Hasher::Out: Ord + codec::Codec, { do_check_proof::( local_root, @@ -317,8 +331,8 @@ pub fn decode_cht_value(value: &[u8]) -> Option { #[cfg(test)] mod tests { - use primitives::{Blake2Hasher}; - use test_client::runtime::Header; + use sp_core::Blake2Hasher; + use substrate_test_runtime_client::runtime::Header; use super::*; #[test] @@ -329,8 +343,24 @@ mod tests { assert_eq!(is_build_required(SIZE, SIZE + 1), None); assert_eq!(is_build_required(SIZE, 2 * SIZE), None); assert_eq!(is_build_required(SIZE, 2 * SIZE + 1), Some(0)); + assert_eq!(is_build_required(SIZE, 2 * SIZE + 2), None); assert_eq!(is_build_required(SIZE, 3 * SIZE), None); assert_eq!(is_build_required(SIZE, 3 * SIZE + 1), Some(1)); + assert_eq!(is_build_required(SIZE, 3 * SIZE + 2), None); + } + + #[test] + fn max_cht_number_works() { + assert_eq!(max_cht_number(SIZE, 0u32.into()), None); + assert_eq!(max_cht_number(SIZE, 1u32.into()), None); + assert_eq!(max_cht_number(SIZE, SIZE), None); + assert_eq!(max_cht_number(SIZE, SIZE + 1), None); + assert_eq!(max_cht_number(SIZE, 2 * SIZE), None); + assert_eq!(max_cht_number(SIZE, 2 * SIZE + 1), Some(0)); + assert_eq!(max_cht_number(SIZE, 2 * SIZE + 2), Some(0)); + assert_eq!(max_cht_number(SIZE, 3 * SIZE), Some(0)); + assert_eq!(max_cht_number(SIZE, 3 * SIZE + 1), Some(1)); + assert_eq!(max_cht_number(SIZE, 3 * SIZE + 2), Some(1)); } #[test] diff --git a/client/src/client.rs b/client/src/client.rs new file mode 100644 index 0000000000000..2babf6f3e900e --- /dev/null +++ b/client/src/client.rs @@ -0,0 +1,3055 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate Client + +use std::{ + marker::PhantomData, collections::{HashSet, BTreeMap, HashMap}, sync::Arc, panic::UnwindSafe, + result, +}; +use log::{info, trace, warn}; +use futures::channel::mpsc; +use parking_lot::{Mutex, RwLock}; +use codec::{Encode, Decode}; +use hash_db::Prefix; +use sp_core::{ + ChangesTrieConfiguration, convert_hash, traits::CodeExecutor, + NativeOrEncoded, storage::{StorageKey, StorageData, well_known_keys, ChildInfo}, +}; +use sc_telemetry::{telemetry, SUBSTRATE_INFO}; +use sp_runtime::{ + Justification, BuildStorage, + generic::{BlockId, SignedBlock, DigestItem}, + traits::{ + Block as BlockT, Header as HeaderT, Zero, NumberFor, HasherFor, SaturatedConversion, One, + DigestFor, + }, +}; +use sp_state_machine::{ + DBValue, Backend as StateBackend, ChangesTrieAnchorBlockId, + prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage, + ChangesTrieConfigurationRange, key_changes, key_changes_proof, StorageProof, + merge_storage_proofs, +}; +use sc_executor::{RuntimeVersion, RuntimeInfo}; +use sp_consensus::{ + Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams, ImportResult, + BlockOrigin, ForkChoiceStrategy, SelectChain, RecordProof, +}; +use sp_blockchain::{self as blockchain, + Backend as ChainBackend, + HeaderBackend as ChainHeaderBackend, ProvideCache, Cache, + well_known_cache_keys::Id as CacheKeyId, + HeaderMetadata, CachedHeaderMetadata, +}; + +use sp_api::{ + CallApiAt, ConstructRuntimeApi, Core as CoreApi, ApiExt, ApiRef, ProvideRuntimeApi, + CallApiAtParams, +}; +use sc_block_builder::BlockBuilderApi; + +pub use sc_client_api::{ + backend::{ + self, BlockImportOperation, PrunableStateChangesTrieStorage, + ClientImportOperation, Finalizer, ImportSummary, NewBlockState, + }, + client::{ + ImportNotifications, FinalityNotification, FinalityNotifications, BlockImportNotification, + ClientInfo, BlockchainEvents, BlockBody, ProvideUncles, BadBlocks, ForkBlocks, + BlockOf, + }, + execution_extensions::{ExecutionExtensions, ExecutionStrategies}, + notifications::{StorageNotifications, StorageEventStream}, + CallExecutor, +}; +use sp_blockchain::Error; + +use crate::{ + call_executor::LocalCallExecutor, + light::{call_executor::prove_execution, fetcher::ChangesProof}, + in_mem, genesis, cht, +}; + +/// Substrate Client +pub struct Client where Block: BlockT { + backend: Arc, + executor: E, + storage_notifications: Mutex>, + import_notification_sinks: Mutex>>>, + finality_notification_sinks: Mutex>>>, + // holds the block hash currently being imported. TODO: replace this with block queue + importing_block: RwLock>, + fork_blocks: ForkBlocks, + bad_blocks: BadBlocks, + execution_extensions: ExecutionExtensions, + _phantom: PhantomData, +} + +// used in importing a block, where additional changes are made after the runtime +// executed. +enum PrePostHeader { + // they are the same: no post-runtime digest items. + Same(H), + // different headers (pre, post). + Different(H, H), +} + +impl PrePostHeader { + // get a reference to the "post-header" -- the header as it should be after all changes are applied. + fn post(&self) -> &H { + match *self { + PrePostHeader::Same(ref h) => h, + PrePostHeader::Different(_, ref h) => h, + } + } + + // convert to the "post-header" -- the header as it should be after all changes are applied. + fn into_post(self) -> H { + match self { + PrePostHeader::Same(h) => h, + PrePostHeader::Different(_, h) => h, + } + } +} + +/// Create an instance of in-memory client. +pub fn new_in_mem( + executor: E, + genesis_storage: S, + keystore: Option, +) -> sp_blockchain::Result, + LocalCallExecutor, E>, + Block, + RA +>> where + E: CodeExecutor + RuntimeInfo, + S: BuildStorage, + Block: BlockT, +{ + new_with_backend(Arc::new(in_mem::Backend::new()), executor, genesis_storage, keystore) +} + +/// Create a client with the explicitly provided backend. +/// This is useful for testing backend implementations. +pub fn new_with_backend( + backend: Arc, + executor: E, + build_genesis_storage: S, + keystore: Option, +) -> sp_blockchain::Result, Block, RA>> + where + E: CodeExecutor + RuntimeInfo, + S: BuildStorage, + Block: BlockT, + B: backend::LocalBackend +{ + let call_executor = LocalCallExecutor::new(backend.clone(), executor); + let extensions = ExecutionExtensions::new(Default::default(), keystore); + Client::new( + backend, + call_executor, + build_genesis_storage, + Default::default(), + Default::default(), + extensions, + ) +} + +impl BlockOf for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Type = Block; +} + +impl Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + /// Creates new Substrate Client with given blockchain and code executor. + pub fn new( + backend: Arc, + executor: E, + build_genesis_storage: S, + fork_blocks: ForkBlocks, + bad_blocks: BadBlocks, + execution_extensions: ExecutionExtensions, + ) -> sp_blockchain::Result { + if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { + let genesis_storage = build_genesis_storage.build_storage()?; + let mut op = backend.begin_operation()?; + backend.begin_state_operation(&mut op, BlockId::Hash(Default::default()))?; + let state_root = op.reset_storage(genesis_storage)?; + let genesis_block = genesis::construct_genesis_block::(state_root.into()); + info!("Initializing Genesis block/state (state: {}, header-hash: {})", + genesis_block.header().state_root(), + genesis_block.header().hash() + ); + op.set_block_data( + genesis_block.deconstruct().0, + Some(vec![]), + None, + NewBlockState::Final + )?; + backend.commit_operation(op)?; + } + + Ok(Client { + backend, + executor, + storage_notifications: Default::default(), + import_notification_sinks: Default::default(), + finality_notification_sinks: Default::default(), + importing_block: Default::default(), + fork_blocks, + bad_blocks, + execution_extensions, + _phantom: Default::default(), + }) + } + + /// Get a reference to the execution extensions. + pub fn execution_extensions(&self) -> &ExecutionExtensions { + &self.execution_extensions + } + + /// Get a reference to the state at a given block. + pub fn state_at(&self, block: &BlockId) -> sp_blockchain::Result { + self.backend.state_at(*block) + } + + /// Given a `BlockId` and a key prefix, return the matching child storage keys in that block. + pub fn storage_keys(&self, id: &BlockId, key_prefix: &StorageKey) -> sp_blockchain::Result> { + let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect(); + Ok(keys) + } + + /// Given a `BlockId` and a key, return the value under the key in that block. + pub fn storage(&self, id: &BlockId, key: &StorageKey) -> sp_blockchain::Result> { + Ok(self.state_at(id)? + .storage(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + .map(StorageData) + ) + } + + /// Given a `BlockId` and a key, return the value under the hash in that block. + pub fn storage_hash(&self, id: &BlockId, key: &StorageKey) + -> sp_blockchain::Result> { + Ok(self.state_at(id)? + .storage_hash(&key.0).map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + ) + } + + /// Given a `BlockId`, a key prefix, and a child storage key, return the matching child storage keys. + pub fn child_storage_keys( + &self, + id: &BlockId, + child_storage_key: &StorageKey, + child_info: ChildInfo, + key_prefix: &StorageKey + ) -> sp_blockchain::Result> { + let keys = self.state_at(id)? + .child_keys(&child_storage_key.0, child_info, &key_prefix.0) + .into_iter() + .map(StorageKey) + .collect(); + Ok(keys) + } + + /// Given a `BlockId`, a key and a child storage key, return the value under the key in that block. + pub fn child_storage( + &self, + id: &BlockId, + storage_key: &StorageKey, + child_info: ChildInfo, + key: &StorageKey + ) -> sp_blockchain::Result> { + Ok(self.state_at(id)? + .child_storage(&storage_key.0, child_info, &key.0) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + .map(StorageData)) + } + + /// Given a `BlockId`, a key and a child storage key, return the hash under the key in that block. + pub fn child_storage_hash( + &self, + id: &BlockId, + storage_key: &StorageKey, + child_info: ChildInfo, + key: &StorageKey + ) -> sp_blockchain::Result> { + Ok(self.state_at(id)? + .child_storage_hash(&storage_key.0, child_info, &key.0) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + ) + } + + /// Get the code at a given block. + pub fn code_at(&self, id: &BlockId) -> sp_blockchain::Result> { + Ok(self.storage(id, &StorageKey(well_known_keys::CODE.to_vec()))? + .expect("None is returned if there's no value stored for the given key;\ + ':code' key is always defined; qed").0) + } + + /// Get the RuntimeVersion at a given block. + pub fn runtime_version_at(&self, id: &BlockId) -> sp_blockchain::Result { + self.executor.runtime_version(id) + } + + /// Get call executor reference. + pub fn executor(&self) -> &E { + &self.executor + } + + /// Reads storage value at a given block + key, returning read proof. + pub fn read_proof(&self, id: &BlockId, keys: I) -> sp_blockchain::Result where + I: IntoIterator, + I::Item: AsRef<[u8]>, + { + self.state_at(id) + .and_then(|state| prove_read(state, keys) + .map_err(Into::into)) + } + + /// Reads child storage value at a given block + storage_key + key, returning + /// read proof. + pub fn read_child_proof( + &self, + id: &BlockId, + storage_key: &[u8], + child_info: ChildInfo, + keys: I, + ) -> sp_blockchain::Result where + I: IntoIterator, + I::Item: AsRef<[u8]>, + { + self.state_at(id) + .and_then(|state| prove_child_read(state, storage_key, child_info, keys) + .map_err(Into::into)) + } + + /// Execute a call to a contract on top of state in a block of given hash + /// AND returning execution proof. + /// + /// No changes are made. + pub fn execution_proof(&self, + id: &BlockId, + method: &str, + call_data: &[u8] + ) -> sp_blockchain::Result<(Vec, StorageProof)> { + let state = self.state_at(id)?; + let header = self.prepare_environment_block(id)?; + prove_execution(state, header, &self.executor, method, call_data) + } + + /// Reads given header and generates CHT-based header proof. + pub fn header_proof(&self, id: &BlockId) -> sp_blockchain::Result<(Block::Header, StorageProof)> { + self.header_proof_with_cht_size(id, cht::size()) + } + + /// Get block hash by number. + pub fn block_hash(&self, + block_number: <::Header as HeaderT>::Number + ) -> sp_blockchain::Result> { + self.backend.blockchain().hash(block_number) + } + + /// Reads given header and generates CHT-based header proof for CHT of given size. + pub fn header_proof_with_cht_size( + &self, + id: &BlockId, + cht_size: NumberFor, + ) -> sp_blockchain::Result<(Block::Header, StorageProof)> { + let proof_error = || sp_blockchain::Error::Backend(format!("Failed to generate header proof for {:?}", id)); + let header = self.backend.blockchain().expect_header(*id)?; + let block_num = *header.number(); + let cht_num = cht::block_to_cht_number(cht_size, block_num).ok_or_else(proof_error)?; + let cht_start = cht::start_number(cht_size, cht_num); + let mut current_num = cht_start; + let cht_range = ::std::iter::from_fn(|| { + let old_current_num = current_num; + current_num = current_num + One::one(); + Some(old_current_num) + }); + let headers = cht_range.map(|num| self.block_hash(num)); + let proof = cht::build_proof::, _, _>( + cht_size, + cht_num, + std::iter::once(block_num), + headers, + )?; + Ok((header, proof)) + } + + /// 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 tries are not supported. + pub fn max_key_changes_range( + &self, + first: NumberFor, + last: BlockId, + ) -> sp_blockchain::Result, BlockId)>> { + let (config, storage) = match self.require_changes_trie().ok() { + Some((config, storage)) => (config, storage), + None => return Ok(None), + }; + let last_num = self.backend.blockchain().expect_block_number_from_id(&last)?; + if first > last_num { + return Err(sp_blockchain::Error::ChangesTrieAccessFailed("Invalid changes trie range".into())); + } + let finalized_number = self.backend.blockchain().info().finalized_number; + let oldest = storage.oldest_changes_trie_block(&config, finalized_number); + let first = ::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. + /// + /// Changes are returned in descending order (i.e. last block comes first). + pub fn key_changes( + &self, + first: NumberFor, + last: BlockId, + storage_key: Option<&StorageKey>, + key: &StorageKey + ) -> sp_blockchain::Result, u32)>> { + let (config, storage) = self.require_changes_trie()?; + let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; + let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; + + // FIXME: remove this in https://github.com/paritytech/substrate/pull/3201 + let config_range = ChangesTrieConfigurationRange { + config: &config, + zero: Zero::zero(), + end: None, + }; + + key_changes::, _>( + config_range, + &*storage, + first, + &ChangesTrieAnchorBlockId { + hash: convert_hash(&last_hash), + number: last_number, + }, + self.backend.blockchain().info().best_number, + storage_key.as_ref().map(|sk| sk.0.as_slice()), + &key.0) + .and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::>()) + .map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err)) + } + + /// Get proof for computation of (block, extrinsic) pairs where key has been changed at given blocks range. + /// `min` is the hash of the first block, which changes trie root is known to the requester - when we're using + /// changes tries from ascendants of this block, we should provide proofs for changes tries roots + /// `max` is the hash of the last block known to the requester - we can't use changes tries from descendants + /// of this block. + /// Works only for runtimes that are supporting changes tries. + pub fn key_changes_proof( + &self, + first: Block::Hash, + last: Block::Hash, + min: Block::Hash, + max: Block::Hash, + storage_key: Option<&StorageKey>, + key: &StorageKey, + ) -> sp_blockchain::Result> { + self.key_changes_proof_with_cht_size( + first, + last, + min, + max, + storage_key, + key, + cht::size(), + ) + } + + /// Does the same work as `key_changes_proof`, but assumes that CHTs are of passed size. + pub fn key_changes_proof_with_cht_size( + &self, + first: Block::Hash, + last: Block::Hash, + min: Block::Hash, + max: Block::Hash, + storage_key: Option<&StorageKey>, + key: &StorageKey, + cht_size: NumberFor, + ) -> sp_blockchain::Result> { + struct AccessedRootsRecorder<'a, Block: BlockT> { + storage: &'a dyn ChangesTrieStorage, NumberFor>, + min: NumberFor, + required_roots_proofs: Mutex, Block::Hash>>, + }; + + impl<'a, Block: BlockT> ChangesTrieRootsStorage, NumberFor> for + AccessedRootsRecorder<'a, Block> + { + fn build_anchor(&self, hash: Block::Hash) + -> Result>, String> + { + self.storage.build_anchor(hash) + } + + fn root( + &self, + anchor: &ChangesTrieAnchorBlockId>, + block: NumberFor, + ) -> Result, String> { + let root = self.storage.root(anchor, block)?; + if block < self.min { + if let Some(ref root) = root { + self.required_roots_proofs.lock().insert( + block, + root.clone() + ); + } + } + Ok(root) + } + } + + impl<'a, Block: BlockT> ChangesTrieStorage, NumberFor> for + AccessedRootsRecorder<'a, Block> + { + fn as_roots_storage(&self) + -> &dyn sp_state_machine::ChangesTrieRootsStorage, NumberFor> + { + self + } + + fn with_cached_changed_keys( + &self, + root: &Block::Hash, + functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool { + self.storage.with_cached_changed_keys(root, functor) + } + + fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result, String> { + self.storage.get(key, prefix) + } + } + + let (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, + required_roots_proofs: Mutex::new(BTreeMap::new()), + }; + + let max_number = std::cmp::min( + self.backend.blockchain().info().best_number, + self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(max))?, + ); + + // FIXME: remove this in https://github.com/paritytech/substrate/pull/3201 + let config_range = ChangesTrieConfigurationRange { + config: &config, + zero: Zero::zero(), + end: None, + }; + + // fetch key changes proof + let first_number = self.backend.blockchain() + .expect_block_number_from_id(&BlockId::Hash(first))?; + let last_number = self.backend.blockchain() + .expect_block_number_from_id(&BlockId::Hash(last))?; + let key_changes_proof = key_changes_proof::, _>( + config_range, + &recording_storage, + first_number, + &ChangesTrieAnchorBlockId { + hash: convert_hash(&last), + number: last_number, + }, + max_number, + storage_key.as_ref().map(|sk| sk.0.as_slice()), + &key.0, + ) + .map_err(|err| sp_blockchain::Error::from(sp_blockchain::Error::ChangesTrieAccessFailed(err)))?; + + // now gather proofs for all changes tries roots that were touched during key_changes_proof + // execution AND are unknown (i.e. replaced with CHT) to the requester + let roots = recording_storage.required_roots_proofs.into_inner(); + let roots_proof = self.changes_trie_roots_proof(cht_size, roots.keys().cloned())?; + + Ok(ChangesProof { + max_block: max_number, + proof: key_changes_proof, + roots: roots.into_iter().map(|(n, h)| (n, convert_hash(&h))).collect(), + roots_proof, + }) + } + + /// Generate CHT-based proof for roots of changes tries at given blocks. + fn changes_trie_roots_proof>>( + &self, + cht_size: NumberFor, + blocks: I + ) -> sp_blockchain::Result { + // most probably we have touched several changes tries that are parts of the single CHT + // => GroupBy changes tries by CHT number and then gather proof for the whole group at once + let mut proofs = Vec::new(); + + cht::for_each_cht_group::(cht_size, blocks, |_, cht_num, cht_blocks| { + let cht_proof = self.changes_trie_roots_proof_at_cht(cht_size, cht_num, cht_blocks)?; + proofs.push(cht_proof); + Ok(()) + }, ())?; + + Ok(merge_storage_proofs(proofs)) + } + + /// Generates CHT-based proof for roots of changes tries at given blocks (that are part of single CHT). + fn changes_trie_roots_proof_at_cht( + &self, + cht_size: NumberFor, + cht_num: NumberFor, + blocks: Vec> + ) -> sp_blockchain::Result { + let cht_start = cht::start_number(cht_size, cht_num); + let mut current_num = cht_start; + let cht_range = ::std::iter::from_fn(|| { + let old_current_num = current_num; + current_num = current_num + One::one(); + Some(old_current_num) + }); + let roots = cht_range + .map(|num| self.header(&BlockId::Number(num)) + .map(|block| + block.and_then(|block| block.digest().log(DigestItem::as_changes_trie_root).cloned())) + ); + let proof = cht::build_proof::, _, _>( + cht_size, + cht_num, + blocks, + roots, + )?; + Ok(proof) + } + + /// Returns changes trie configuration and storage or an error if it is not supported. + fn require_changes_trie(&self) -> sp_blockchain::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(sp_blockchain::Error::ChangesTriesNotSupported.into()), + } + } + + /// Create a new block, built on the head of the chain. + pub fn new_block( + &self, + inherent_digests: DigestFor, + ) -> sp_blockchain::Result> where + E: Clone + Send + Sync, + RA: Send + Sync, + Self: ProvideRuntimeApi, + >::Api: BlockBuilderApi + + ApiExt> + { + let info = self.chain_info(); + sc_block_builder::BlockBuilder::new( + self, + info.best_hash, + info.best_number, + RecordProof::No, + inherent_digests, + &self.backend, + ) + } + + /// Create a new block, built on top of `parent`. + /// + /// When proof recording is enabled, all accessed trie nodes are saved. + /// These recorded trie nodes can be used by a third party to proof the + /// output of this block builder without having access to the full storage. + pub fn new_block_at>( + &self, + parent: &BlockId, + inherent_digests: DigestFor, + record_proof: R, + ) -> sp_blockchain::Result> where + E: Clone + Send + Sync, + RA: Send + Sync, + Self: ProvideRuntimeApi, + >::Api: BlockBuilderApi + + ApiExt> + { + sc_block_builder::BlockBuilder::new( + self, + self.expect_block_hash_from_id(parent)?, + self.expect_block_number_from_id(parent)?, + record_proof.into(), + inherent_digests, + &self.backend + ) + } + + /// 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.backend.get_import_lock().write(); + + let mut op = ClientImportOperation { + op: self.backend.begin_operation()?, + notify_imported: None, + notify_finalized: Vec::new(), + }; + + let r = f(&mut op)?; + + let ClientImportOperation { op, notify_imported, notify_finalized } = op; + self.backend.commit_operation(op)?; + self.notify_finalized(notify_finalized)?; + + if let Some(notify_imported) = notify_imported { + self.notify_imported(notify_imported)?; + } + + Ok(r) + }; + + let result = inner(); + *self.importing_block.write() = None; + + result + } + + /// Apply a checked and validated block to an operation. If a justification is provided + /// then `finalized` *must* be true. + fn apply_block( + &self, + operation: &mut ClientImportOperation, + import_block: BlockImportParams>, + new_cache: HashMap>, + ) -> sp_blockchain::Result where + E: CallExecutor + Send + Sync + Clone, + Self: ProvideRuntimeApi, + >::Api: CoreApi + + ApiExt, + { + let BlockImportParams { + origin, + header, + justification, + post_digests, + body, + storage_changes, + finalized, + auxiliary, + fork_choice, + import_existing, + .. + } = import_block; + + assert!(justification.is_some() && finalized || justification.is_none()); + + let import_headers = if post_digests.is_empty() { + PrePostHeader::Same(header) + } else { + let mut post_header = header.clone(); + for item in post_digests { + post_header.digest_mut().push(item); + } + PrePostHeader::Different(header, post_header) + }; + + let hash = import_headers.post().hash(); + let height = (*import_headers.post().number()).saturated_into::(); + + *self.importing_block.write() = Some(hash); + + let result = self.execute_and_import_block( + operation, + origin, + hash, + import_headers, + justification, + body, + storage_changes, + new_cache, + finalized, + auxiliary, + fork_choice, + import_existing, + ); + + if let Ok(ImportResult::Imported(ref aux)) = result { + if aux.is_new_best { + telemetry!(SUBSTRATE_INFO; "block.import"; + "height" => height, + "best" => ?hash, + "origin" => ?origin + ); + } + } + + result + } + + fn execute_and_import_block( + &self, + operation: &mut ClientImportOperation, + origin: BlockOrigin, + hash: Block::Hash, + import_headers: PrePostHeader, + justification: Option, + body: Option>, + storage_changes: Option, Block>>, + new_cache: HashMap>, + finalized: bool, + aux: Vec<(Vec, Option>)>, + fork_choice: ForkChoiceStrategy, + import_existing: bool, + ) -> sp_blockchain::Result where + E: CallExecutor + Send + Sync + Clone, + Self: ProvideRuntimeApi, + >::Api: CoreApi + + ApiExt, + { + let parent_hash = import_headers.post().parent_hash().clone(); + let status = self.backend.blockchain().status(BlockId::Hash(hash))?; + match (import_existing, status) { + (false, blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), + (false, blockchain::BlockStatus::Unknown) => {}, + (true, blockchain::BlockStatus::InChain) => {}, + (true, blockchain::BlockStatus::Unknown) => + return Err(Error::UnknownBlock(format!("{:?}", hash))), + } + + let info = self.backend.blockchain().info(); + + // the block is lower than our last finalized block so it must revert + // finality, refusing import. + if *import_headers.post().number() <= info.finalized_number { + return Err(sp_blockchain::Error::NotInFinalizedChain); + } + + // this is a fairly arbitrary choice of where to draw the line on making notifications, + // but the general goal is to only make notifications when we are already fully synced + // and get a new chain head. + let make_notifications = match origin { + BlockOrigin::NetworkBroadcast | BlockOrigin::Own | BlockOrigin::ConsensusBroadcast => true, + BlockOrigin::Genesis | BlockOrigin::NetworkInitialSync | BlockOrigin::File => false, + }; + + let storage_changes = match storage_changes { + Some(storage_changes) => { + self.backend.begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?; + + // ensure parent block is finalized to maintain invariant that + // finality is called sequentially. + if finalized { + self.apply_finality_with_block_hash( + operation, + parent_hash, + None, + info.best_hash, + make_notifications, + )?; + } + + operation.op.update_cache(new_cache); + + let (main_sc, child_sc, tx, _, changes_trie_tx) = storage_changes.into_inner(); + + operation.op.update_db_storage(tx)?; + operation.op.update_storage(main_sc.clone(), child_sc.clone())?; + + if let Some(changes_trie_transaction) = changes_trie_tx { + operation.op.update_changes_trie(changes_trie_transaction)?; + } + + Some((main_sc, child_sc)) + }, + None => None, + }; + + let is_new_best = finalized || match fork_choice { + ForkChoiceStrategy::LongestChain => import_headers.post().number() > &info.best_number, + ForkChoiceStrategy::Custom(v) => v, + }; + + let leaf_state = if finalized { + NewBlockState::Final + } else if is_new_best { + NewBlockState::Best + } else { + NewBlockState::Normal + }; + + let retracted = if is_new_best { + let route_from_best = sp_blockchain::tree_route( + self.backend.blockchain(), + info.best_hash, + parent_hash, + )?; + route_from_best.retracted().iter().rev().map(|e| e.hash.clone()).collect() + } else { + Vec::default() + }; + + trace!( + "Imported {}, (#{}), best={}, origin={:?}", + hash, + import_headers.post().number(), + is_new_best, + origin, + ); + + operation.op.set_block_data( + import_headers.post().clone(), + body, + justification, + leaf_state, + )?; + + operation.op.insert_aux(aux)?; + + if make_notifications { + if finalized { + operation.notify_finalized.push(hash); + } + + operation.notify_imported = Some(ImportSummary { + hash, + origin, + header: import_headers.into_post(), + is_new_best, + storage_changes, + retracted, + }) + } + + Ok(ImportResult::imported(is_new_best)) + } + + /// Prepares the storage changes for a block. + /// + /// It checks if the state should be enacted and if the `import_block` maybe already provides + /// the required storage changes. If the state should be enacted and the storage changes are not + /// provided, the block is re-executed to get the storage changes. + fn prepare_block_storage_changes( + &self, + import_block: &mut BlockImportParams>, + ) -> sp_blockchain::Result> + where + Self: ProvideRuntimeApi, + >::Api: CoreApi + + ApiExt, + { + let parent_hash = import_block.header.parent_hash(); + let at = BlockId::Hash(*parent_hash); + let enact_state = match self.block_status(&at)? { + BlockStatus::Unknown => return Ok(Some(ImportResult::UnknownParent)), + BlockStatus::InChainWithState | BlockStatus::Queued => true, + BlockStatus::InChainPruned if import_block.allow_missing_state => false, + BlockStatus::InChainPruned => return Ok(Some(ImportResult::MissingState)), + BlockStatus::KnownBad => return Ok(Some(ImportResult::KnownBad)), + }; + + match (enact_state, &mut import_block.storage_changes, &mut import_block.body) { + // We have storage changes and should enact the state, so we don't need to do anything + // here + (true, Some(_), _) => {}, + // We should enact state, but don't have any storage changes, so we need to execute the + // block. + (true, ref mut storage_changes @ None, Some(ref body)) => { + let runtime_api = self.runtime_api(); + + runtime_api.execute_block( + &at, + Block::new(import_block.header.clone(), body.clone()), + )?; + + let state = self.backend.state_at(at)?; + + let gen_storage_changes = runtime_api.into_storage_changes( + &state, + self.backend.changes_trie_storage(), + *parent_hash, + ); + + { + let _lock = self.backend.get_import_lock().read(); + self.backend.destroy_state(state)?; + } + + // Make sure to consume the error, only after we have destroyed the state. + let gen_storage_changes = gen_storage_changes?; + + if import_block.header.state_root() + != &gen_storage_changes.transaction_storage_root + { + return Err(Error::InvalidStateRoot) + } else { + **storage_changes = Some(gen_storage_changes); + } + }, + // No block body, no storage changes + (true, None, None) => {}, + // We should not enact the state, so we set the storage changes to `None`. + (false, changes, _) => { + changes.take(); + } + }; + + Ok(None) + } + + fn apply_finality_with_block_hash( + &self, + operation: &mut ClientImportOperation, + block: Block::Hash, + justification: Option, + best_block: Block::Hash, + notify: bool, + ) -> sp_blockchain::Result<()> { + // find tree route from last finalized to given block. + let last_finalized = self.backend.blockchain().last_finalized()?; + + if block == last_finalized { + warn!("Possible safety violation: attempted to re-finalize last finalized block {:?} ", last_finalized); + return Ok(()); + } + + let route_from_finalized = sp_blockchain::tree_route(self.backend.blockchain(), last_finalized, block)?; + + if let Some(retracted) = route_from_finalized.retracted().get(0) { + warn!("Safety violation: attempted to revert finalized block {:?} which is not in the \ + same chain as last finalized {:?}", retracted, last_finalized); + + return Err(sp_blockchain::Error::NotInFinalizedChain); + } + + let route_from_best = sp_blockchain::tree_route(self.backend.blockchain(), best_block, block)?; + + // if the block is not a direct ancestor of the current best chain, + // then some other block is the common ancestor. + if route_from_best.common_block().hash != block { + // NOTE: we're setting the finalized block as best block, this might + // be slightly inaccurate since we might have a "better" block + // further along this chain, but since best chain selection logic is + // pluggable we cannot make a better choice here. usages that need + // an accurate "best" block need to go through `SelectChain` + // instead. + operation.op.mark_head(BlockId::Hash(block))?; + } + + let enacted = route_from_finalized.enacted(); + assert!(enacted.len() > 0); + for finalize_new in &enacted[..enacted.len() - 1] { + operation.op.mark_finalized(BlockId::Hash(finalize_new.hash), None)?; + } + + assert_eq!(enacted.last().map(|e| e.hash), Some(block)); + operation.op.mark_finalized(BlockId::Hash(block), justification)?; + + if notify { + // sometimes when syncing, tons of blocks can be finalized at once. + // we'll send notifications spuriously in that case. + const MAX_TO_NOTIFY: usize = 256; + let enacted = route_from_finalized.enacted(); + let start = enacted.len() - ::std::cmp::min(enacted.len(), MAX_TO_NOTIFY); + for finalized in &enacted[start..] { + operation.notify_finalized.push(finalized.hash); + } + } + + Ok(()) + } + + fn notify_finalized( + &self, + notify_finalized: Vec, + ) -> sp_blockchain::Result<()> { + let mut sinks = self.finality_notification_sinks.lock(); + + for finalized_hash in notify_finalized { + let header = self.header(&BlockId::Hash(finalized_hash))? + .expect("header already known to exist in DB because it is indicated in the tree route; qed"); + + telemetry!(SUBSTRATE_INFO; "notify.finalized"; + "height" => format!("{}", header.number()), + "best" => ?finalized_hash, + ); + + let notification = FinalityNotification { + header, + hash: finalized_hash, + }; + + sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); + } + + Ok(()) + } + + fn notify_imported(&self, notify_import: ImportSummary) -> sp_blockchain::Result<()> { + if let Some(storage_changes) = notify_import.storage_changes { + // TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes? + self.storage_notifications.lock() + .trigger( + ¬ify_import.hash, + storage_changes.0.into_iter(), + storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())), + ); + } + + let notification = BlockImportNotification:: { + hash: notify_import.hash, + origin: notify_import.origin, + header: notify_import.header, + is_new_best: notify_import.is_new_best, + retracted: notify_import.retracted, + }; + + self.import_notification_sinks.lock() + .retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); + + Ok(()) + } + + /// Attempts to revert the chain by `n` blocks guaranteeing that no block is + /// reverted past the last finalized block. Returns the number of blocks + /// that were successfully reverted. + pub fn revert(&self, n: NumberFor) -> sp_blockchain::Result> { + Ok(self.backend.revert(n, false)?) + } + + /// Attempts to revert the chain by `n` blocks disregarding finality. This + /// method will revert any finalized blocks as requested and can potentially + /// leave the node in an inconsistent state. Other modules in the system that + /// persist data and that rely on finality (e.g. consensus parts) will be + /// unaffected by the revert. Use this method with caution and making sure + /// that no other data needs to be reverted for consistency aside from the + /// block data. + /// + /// Returns the number of blocks that were successfully reverted. + pub fn unsafe_revert(&self, n: NumberFor) -> sp_blockchain::Result> { + Ok(self.backend.revert(n, true)?) + } + + /// Get usage info about current client. + pub fn usage_info(&self) -> ClientInfo { + ClientInfo { + chain: self.chain_info(), + usage: self.backend.usage_info(), + } + } + + /// Get blockchain info. + pub fn chain_info(&self) -> blockchain::Info { + self.backend.blockchain().info() + } + + /// Get block status. + pub fn block_status(&self, id: &BlockId) -> sp_blockchain::Result { + // this can probably be implemented more efficiently + if let BlockId::Hash(ref h) = id { + if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) { + return Ok(BlockStatus::Queued); + } + } + let hash_and_number = match id.clone() { + BlockId::Hash(hash) => self.backend.blockchain().number(hash)?.map(|n| (hash, n)), + BlockId::Number(n) => self.backend.blockchain().hash(n)?.map(|hash| (hash, n)), + }; + match hash_and_number { + Some((hash, number)) => { + if self.backend.have_state_at(&hash, number) { + Ok(BlockStatus::InChainWithState) + } else { + Ok(BlockStatus::InChainPruned) + } + } + None => Ok(BlockStatus::Unknown), + } + } + + /// Get block header by id. + pub fn header(&self, id: &BlockId) -> sp_blockchain::Result::Header>> { + self.backend.blockchain().header(*id) + } + + /// Get block body by id. + pub fn body(&self, id: &BlockId) -> sp_blockchain::Result::Extrinsic>>> { + self.backend.blockchain().body(*id) + } + + /// Get block justification set by id. + pub fn justification(&self, id: &BlockId) -> sp_blockchain::Result> { + self.backend.blockchain().justification(*id) + } + + /// Get full block by id. + pub fn block(&self, id: &BlockId) + -> sp_blockchain::Result>> + { + Ok(match (self.header(id)?, self.body(id)?, self.justification(id)?) { + (Some(header), Some(extrinsics), justification) => + Some(SignedBlock { block: Block::new(header, extrinsics), justification }), + _ => None, + }) + } + + /// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors. + pub fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) -> sp_blockchain::Result> { + let load_header = |id: Block::Hash| -> sp_blockchain::Result { + match self.backend.blockchain().header(BlockId::Hash(id))? { + Some(hdr) => Ok(hdr), + None => Err(Error::UnknownBlock(format!("{:?}", id))), + } + }; + + let genesis_hash = self.backend.blockchain().info().genesis_hash; + if genesis_hash == target_hash { return Ok(Vec::new()); } + + let mut current_hash = target_hash; + let mut current = load_header(current_hash)?; + let mut ancestor_hash = *current.parent_hash(); + let mut ancestor = load_header(ancestor_hash)?; + let mut uncles = Vec::new(); + + for _generation in 0..max_generation.saturated_into() { + let children = self.backend.blockchain().children(ancestor_hash)?; + uncles.extend(children.into_iter().filter(|h| h != ¤t_hash)); + current_hash = ancestor_hash; + if genesis_hash == current_hash { break; } + current = ancestor; + ancestor_hash = *current.parent_hash(); + ancestor = load_header(ancestor_hash)?; + } + trace!("Collected {} uncles", uncles.len()); + Ok(uncles) + } + + fn changes_trie_config(&self) -> Result, Error> { + Ok(self.backend.state_at(BlockId::Number(self.backend.blockchain().info().best_number))? + .storage(well_known_keys::CHANGES_TRIE_CONFIG) + .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))? + .and_then(|c| Decode::decode(&mut &*c).ok())) + } + + /// Prepare in-memory header that is used in execution environment. + fn prepare_environment_block(&self, parent: &BlockId) -> sp_blockchain::Result { + let parent_header = self.backend.blockchain().expect_header(*parent)?; + Ok(<::Header as HeaderT>::new( + self.backend.blockchain().expect_block_number_from_id(parent)? + One::one(), + Default::default(), + Default::default(), + parent_header.hash(), + Default::default(), + )) + } +} + +impl HeaderMetadata for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = sp_blockchain::Error; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.backend.blockchain().header_metadata(hash) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.backend.blockchain().insert_header_metadata(hash, metadata) + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.backend.blockchain().remove_header_metadata(hash) + } +} + +impl ProvideUncles for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) -> sp_blockchain::Result> { + Ok(Client::uncles(self, target_hash, max_generation)? + .into_iter() + .filter_map(|hash| Client::header(self, &BlockId::Hash(hash)).unwrap_or(None)) + .collect() + ) + } +} + +impl ChainHeaderBackend for Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + RA: Send + Sync, +{ + fn header(&self, id: BlockId) -> sp_blockchain::Result> { + self.backend.blockchain().header(id) + } + + fn info(&self) -> blockchain::Info { + self.backend.blockchain().info() + } + + fn status(&self, id: BlockId) -> sp_blockchain::Result { + self.backend.blockchain().status(id) + } + + fn number(&self, hash: Block::Hash) -> sp_blockchain::Result::Header as HeaderT>::Number>> { + self.backend.blockchain().number(hash) + } + + fn hash(&self, number: NumberFor) -> sp_blockchain::Result> { + self.backend.blockchain().hash(number) + } +} + +impl sp_runtime::traits::BlockIdTo for Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + RA: Send + Sync, +{ + type Error = Error; + + fn to_hash(&self, block_id: &BlockId) -> sp_blockchain::Result> { + self.block_hash_from_id(block_id) + } + + fn to_number(&self, block_id: &BlockId) -> sp_blockchain::Result>> { + self.block_number_from_id(block_id) + } +} + +impl ChainHeaderBackend for &Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + RA: Send + Sync, +{ + fn header(&self, id: BlockId) -> sp_blockchain::Result> { + (**self).backend.blockchain().header(id) + } + + fn info(&self) -> blockchain::Info { + (**self).backend.blockchain().info() + } + + fn status(&self, id: BlockId) -> sp_blockchain::Result { + (**self).status(id) + } + + fn number(&self, hash: Block::Hash) -> sp_blockchain::Result::Header as HeaderT>::Number>> { + (**self).number(hash) + } + + fn hash(&self, number: NumberFor) -> sp_blockchain::Result> { + (**self).hash(number) + } +} + +impl ProvideCache for Client where + B: backend::Backend, + Block: BlockT, +{ + fn cache(&self) -> Option>> { + self.backend.blockchain().cache() + } +} + +impl ProvideRuntimeApi for Client where + B: backend::Backend, + E: CallExecutor + Clone + Send + Sync, + Block: BlockT, + RA: ConstructRuntimeApi, +{ + type Api = >::RuntimeApi; + + fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { + RA::construct_runtime_api(self) + } +} + +impl CallApiAt for Client where + B: backend::Backend, + E: CallExecutor + Clone + Send + Sync, + Block: BlockT, +{ + type Error = Error; + type StateBackend = B::State; + + fn call_api_at< + 'a, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + C: CoreApi, + >( + &self, + params: CallApiAtParams<'a, Block, C, NC, B::State>, + ) -> sp_blockchain::Result> { + let core_api = params.core_api; + let at = params.at; + + let (manager, extensions) = self.execution_extensions.manager_and_extensions( + at, + params.context, + ); + + self.executor.contextual_call::<_, fn(_,_) -> _,_,_>( + || core_api.initialize_block(at, &self.prepare_environment_block(at)?), + at, + params.function, + ¶ms.arguments, + params.overlayed_changes, + Some(params.storage_transaction_cache), + params.initialize_block, + manager, + params.native_call, + params.recorder, + Some(extensions), + ) + } + + fn runtime_version_at(&self, at: &BlockId) -> sp_blockchain::Result { + self.runtime_version_at(at) + } +} + +/// NOTE: only use this implementation when you are sure there are NO consensus-level BlockImport +/// objects. Otherwise, importing blocks directly into the client would be bypassing +/// important verification work. +impl sp_consensus::BlockImport for &Client where + B: backend::Backend, + E: CallExecutor + Clone + Send + Sync, + Block: BlockT, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: CoreApi + + ApiExt, +{ + type Error = ConsensusError; + type Transaction = backend::TransactionFor; + + /// Import a checked and validated block. If a justification is provided in + /// `BlockImportParams` then `finalized` *must* be true. + /// + /// NOTE: only use this implementation when there are NO consensus-level BlockImport + /// objects. Otherwise, importing blocks directly into the client would be bypassing + /// important verification work. + /// + /// If you are not sure that there are no BlockImport objects provided by the consensus + /// algorithm, don't use this function. + fn import_block( + &mut self, + mut import_block: BlockImportParams>, + new_cache: HashMap>, + ) -> Result { + if let Some(res) = self.prepare_block_storage_changes(&mut import_block).map_err(|e| { + warn!("Block prepare storage changes error:\n{:?}", e); + ConsensusError::ClientImport(e.to_string()) + })? { + return Ok(res) + } + + self.lock_import_and_run(|operation| { + self.apply_block(operation, import_block, new_cache) + }).map_err(|e| { + warn!("Block import error:\n{:?}", e); + ConsensusError::ClientImport(e.to_string()).into() + }) + } + + /// Check block preconditions. + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + let BlockCheckParams { hash, number, parent_hash, allow_missing_state, import_existing } = block; + + // Check the block against white and black lists if any are defined + // (i.e. fork blocks and bad blocks respectively) + let fork_block = self.fork_blocks.as_ref() + .and_then(|fs| fs.iter().find(|(n, _)| *n == number)); + + if let Some((_, h)) = fork_block { + if &hash != h { + trace!( + "Rejecting block from known invalid fork. Got {:?}, expected: {:?} at height {}", + hash, + h, + number + ); + return Ok(ImportResult::KnownBad); + } + } + + let bad_block = self.bad_blocks.as_ref() + .filter(|bs| bs.contains(&hash)) + .is_some(); + + if bad_block { + trace!( + "Rejecting known bad block: #{} {:?}", + number, + hash, + ); + return Ok(ImportResult::KnownBad); + } + + // Own status must be checked first. If the block and ancestry is pruned + // this function must return `AlreadyInChain` rather than `MissingState` + match self.block_status(&BlockId::Hash(hash)) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))? + { + BlockStatus::InChainWithState | BlockStatus::Queued if !import_existing => return Ok(ImportResult::AlreadyInChain), + BlockStatus::InChainWithState | BlockStatus::Queued => {}, + BlockStatus::InChainPruned => return Ok(ImportResult::AlreadyInChain), + BlockStatus::Unknown => {}, + BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), + } + + match self.block_status(&BlockId::Hash(parent_hash)) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))? + { + BlockStatus::InChainWithState | BlockStatus::Queued => {}, + BlockStatus::Unknown => return Ok(ImportResult::UnknownParent), + BlockStatus::InChainPruned if allow_missing_state => {}, + BlockStatus::InChainPruned => return Ok(ImportResult::MissingState), + BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), + } + + + Ok(ImportResult::imported(false)) + } +} + +impl sp_consensus::BlockImport for Client where + B: backend::Backend, + E: CallExecutor + Clone + Send + Sync, + Block: BlockT, + Self: ProvideRuntimeApi, + >::Api: CoreApi + + ApiExt, +{ + type Error = ConsensusError; + type Transaction = backend::TransactionFor; + + fn import_block( + &mut self, + import_block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { + (&*self).import_block(import_block, new_cache) + } + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + (&*self).check_block(block) + } +} + +impl Finalizer for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn apply_finality( + &self, + operation: &mut ClientImportOperation, + id: BlockId, + justification: Option, + notify: bool, + ) -> sp_blockchain::Result<()> { + let last_best = self.backend.blockchain().info().best_hash; + let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?; + self.apply_finality_with_block_hash( + operation, + to_finalize_hash, + justification, + last_best, + notify, + ) + } + + fn finalize_block( + &self, + id: BlockId, + justification: Option, + notify: bool, + ) -> sp_blockchain::Result<()> { + self.lock_import_and_run(|operation| { + self.apply_finality(operation, id, justification, notify) + }) + } +} + + +impl Finalizer for &Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn apply_finality( + &self, + operation: &mut ClientImportOperation, + id: BlockId, + justification: Option, + notify: bool, + ) -> sp_blockchain::Result<()> { + (**self).apply_finality(operation, id, justification, notify) + } + + fn finalize_block( + &self, + id: BlockId, + justification: Option, + notify: bool, + ) -> sp_blockchain::Result<()> { + (**self).finalize_block(id, justification, notify) + } +} + +impl BlockchainEvents for Client +where + E: CallExecutor, + Block: BlockT, +{ + /// Get block import event stream. + fn import_notification_stream(&self) -> ImportNotifications { + let (sink, stream) = mpsc::unbounded(); + self.import_notification_sinks.lock().push(sink); + stream + } + + fn finality_notification_stream(&self) -> FinalityNotifications { + let (sink, stream) = mpsc::unbounded(); + self.finality_notification_sinks.lock().push(sink); + stream + } + + /// Get storage changes event stream. + fn storage_changes_notification_stream( + &self, + filter_keys: Option<&[StorageKey]>, + child_filter_keys: Option<&[(StorageKey, Option>)]>, + ) -> sp_blockchain::Result> { + Ok(self.storage_notifications.lock().listen(filter_keys, child_filter_keys)) + } +} + +/// Implement Longest Chain Select implementation +/// where 'longest' is defined as the highest number of blocks +pub struct LongestChain { + backend: Arc, + _phantom: PhantomData +} + +impl Clone for LongestChain { + fn clone(&self) -> Self { + let backend = self.backend.clone(); + LongestChain { + backend, + _phantom: Default::default() + } + } +} + +impl LongestChain +where + B: backend::Backend, + Block: BlockT, +{ + /// Instantiate a new LongestChain for Backend B + pub fn new(backend: Arc) -> Self { + LongestChain { + backend, + _phantom: Default::default() + } + } + + fn best_block_header(&self) -> sp_blockchain::Result<::Header> { + let info = self.backend.blockchain().info(); + let import_lock = self.backend.get_import_lock(); + let best_hash = self.backend.blockchain().best_containing(info.best_hash, None, import_lock)? + .unwrap_or(info.best_hash); + + Ok(self.backend.blockchain().header(BlockId::Hash(best_hash))? + .expect("given block hash was fetched from block in db; qed")) + } + + fn leaves(&self) -> Result::Hash>, sp_blockchain::Error> { + self.backend.blockchain().leaves() + } +} + +impl SelectChain for LongestChain +where + B: backend::Backend, + Block: BlockT, +{ + + fn leaves(&self) -> Result::Hash>, ConsensusError> { + LongestChain::leaves(self) + .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) + } + + fn best_chain(&self) + -> Result<::Header, ConsensusError> + { + LongestChain::best_block_header(&self) + .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) + } + + fn finality_target( + &self, + target_hash: Block::Hash, + maybe_max_number: Option> + ) -> Result, ConsensusError> { + let import_lock = self.backend.get_import_lock(); + self.backend.blockchain().best_containing(target_hash, maybe_max_number, import_lock) + .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) + } +} + +impl BlockBody for Client + where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn block_body( + &self, + id: &BlockId, + ) -> sp_blockchain::Result::Extrinsic>>> { + self.body(id) + } +} + +impl backend::AuxStore for Client + where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, + Self: ProvideRuntimeApi, + >::Api: CoreApi, +{ + /// Insert auxiliary data into key-value store. + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> { + // Import is locked here because we may have other block import + // operations that tries to set aux data. Note that for consensus + // layer, one can always use atomic operations to make sure + // import is only locked once. + self.lock_import_and_run(|operation| { + apply_aux(operation, insert, delete) + }) + } + /// Query auxiliary data from key-value store. + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { + backend::AuxStore::get_aux(&*self.backend, key) + } +} + +impl backend::AuxStore for &Client + where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: CoreApi, +{ + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> { + (**self).insert_aux(insert, delete) + } + + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { + (**self).get_aux(key) + } +} + + +/// Helper function to apply auxiliary data insertion into an operation. +pub fn apply_aux<'a, 'b: 'a, 'c: 'a, B, Block, D, I>( + operation: &mut ClientImportOperation, + insert: I, + delete: D, +) -> sp_blockchain::Result<()> +where + Block: BlockT, + B: backend::Backend, + I: IntoIterator, + D: IntoIterator, +{ + operation.op.insert_aux( + insert.into_iter() + .map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) + .chain(delete.into_iter().map(|k| (k.to_vec(), None))) + ) +} + +impl sp_consensus::block_validation::Chain for Client + where BE: backend::Backend, + E: CallExecutor, + B: BlockT +{ + fn block_status( + &self, + id: &BlockId, + ) -> Result> { + Client::block_status(self, id).map_err(|e| Box::new(e) as Box<_>) + } +} + +#[cfg(test)] +pub(crate) mod tests { + use std::collections::HashMap; + use super::*; + use sp_core::{blake2_256, H256}; + use sp_runtime::DigestItem; + use sp_consensus::{BlockOrigin, SelectChain, BlockImport}; + use substrate_test_runtime_client::{ + prelude::*, + client_ext::ClientExt, + sc_client_db::{Backend, DatabaseSettings, DatabaseSettingsSrc, PruningMode}, + runtime::{self, Block, Transfer, RuntimeApi, TestAPI}, + }; + + /// Returns tuple, consisting of: + /// 1) test client pre-filled with blocks changing balances; + /// 2) roots of changes tries for these blocks + /// 3) test cases in form (begin, end, key, vec![(block, extrinsic)]) that are required to pass + pub fn prepare_client_with_key_changes() -> ( + substrate_test_runtime_client::sc_client::Client, + Vec, + Vec<(u64, u64, Vec, Vec<(u64, u32)>)>, + ) { + // prepare block structure + let blocks_transfers = vec![ + vec![(AccountKeyring::Alice, AccountKeyring::Dave), (AccountKeyring::Bob, AccountKeyring::Dave)], + vec![(AccountKeyring::Charlie, AccountKeyring::Eve)], + vec![], + vec![(AccountKeyring::Alice, AccountKeyring::Dave)], + ]; + + // prepare client ang import blocks + let mut local_roots = Vec::new(); + let mut remote_client = TestClientBuilder::new().set_support_changes_trie(true).build(); + let mut nonces: HashMap<_, u64> = Default::default(); + for (i, block_transfers) in blocks_transfers.into_iter().enumerate() { + let mut builder = remote_client.new_block(Default::default()).unwrap(); + for (from, to) in block_transfers { + builder.push_transfer(Transfer { + from: from.into(), + to: to.into(), + amount: 1, + nonce: *nonces.entry(from).and_modify(|n| { *n = *n + 1 }).or_default(), + }).unwrap(); + } + let block = builder.build().unwrap().block; + remote_client.import(BlockOrigin::Own, block).unwrap(); + + let header = remote_client.header(&BlockId::Number(i as u64 + 1)).unwrap().unwrap(); + let trie_root = header.digest().log(DigestItem::as_changes_trie_root) + .map(|root| H256::from_slice(root.as_ref())) + .unwrap(); + local_roots.push(trie_root); + } + + // prepare test cases + let alice = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())).to_vec(); + let bob = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Bob.into())).to_vec(); + let charlie = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Charlie.into())).to_vec(); + let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let eve = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Eve.into())).to_vec(); + let ferdie = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Ferdie.into())).to_vec(); + let test_cases = vec![ + (1, 4, alice.clone(), vec![(4, 0), (1, 0)]), + (1, 3, alice.clone(), vec![(1, 0)]), + (2, 4, alice.clone(), vec![(4, 0)]), + (2, 3, alice.clone(), vec![]), + + (1, 4, bob.clone(), vec![(1, 1)]), + (1, 1, bob.clone(), vec![(1, 1)]), + (2, 4, bob.clone(), vec![]), + + (1, 4, charlie.clone(), vec![(2, 0)]), + + (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), + (1, 1, dave.clone(), vec![(1, 1), (1, 0)]), + (3, 4, dave.clone(), vec![(4, 0)]), + + (1, 4, eve.clone(), vec![(2, 0)]), + (1, 1, eve.clone(), vec![]), + (3, 4, eve.clone(), vec![]), + + (1, 4, ferdie.clone(), vec![]), + ]; + + (remote_client, local_roots, test_cases) + } + + #[test] + fn client_initializes_from_genesis_ok() { + let client = substrate_test_runtime_client::new(); + + assert_eq!( + client.runtime_api().balance_of( + &BlockId::Number(client.chain_info().best_number), + AccountKeyring::Alice.into() + ).unwrap(), + 1000 + ); + assert_eq!( + client.runtime_api().balance_of( + &BlockId::Number(client.chain_info().best_number), + AccountKeyring::Ferdie.into() + ).unwrap(), + 0 + ); + } + + #[test] + fn block_builder_works_with_no_transactions() { + let mut client = substrate_test_runtime_client::new(); + + let block = client.new_block(Default::default()).unwrap().build().unwrap().block; + + client.import(BlockOrigin::Own, block).unwrap(); + + assert_eq!(client.chain_info().best_number, 1); + } + + #[test] + fn block_builder_works_with_transactions() { + let mut client = substrate_test_runtime_client::new(); + + let mut builder = client.new_block(Default::default()).unwrap(); + + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 42, + nonce: 0, + }).unwrap(); + + let block = builder.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + + assert_eq!(client.chain_info().best_number, 1); + assert_ne!( + client.state_at(&BlockId::Number(1)).unwrap().pairs(), + client.state_at(&BlockId::Number(0)).unwrap().pairs() + ); + assert_eq!( + client.runtime_api().balance_of( + &BlockId::Number(client.chain_info().best_number), + AccountKeyring::Alice.into() + ).unwrap(), + 958 + ); + assert_eq!( + client.runtime_api().balance_of( + &BlockId::Number(client.chain_info().best_number), + AccountKeyring::Ferdie.into() + ).unwrap(), + 42 + ); + } + + #[test] + fn block_builder_does_not_include_invalid() { + let mut client = substrate_test_runtime_client::new(); + + let mut builder = client.new_block(Default::default()).unwrap(); + + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 42, + nonce: 0, + }).unwrap(); + + assert!( + builder.push_transfer(Transfer { + from: AccountKeyring::Eve.into(), + to: AccountKeyring::Alice.into(), + amount: 42, + nonce: 0, + }).is_err() + ); + + let block = builder.build().unwrap().block; + client.import(BlockOrigin::Own, block).unwrap(); + + assert_eq!(client.chain_info().best_number, 1); + assert_ne!( + client.state_at(&BlockId::Number(1)).unwrap().pairs(), + client.state_at(&BlockId::Number(0)).unwrap().pairs() + ); + assert_eq!(client.body(&BlockId::Number(1)).unwrap().unwrap().len(), 1) + } + + #[test] + fn best_containing_with_genesis_block() { + // block tree: + // G + + let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + let genesis_hash = client.chain_info().genesis_hash; + + assert_eq!( + genesis_hash.clone(), + longest_chain_select.finality_target(genesis_hash.clone(), None).unwrap().unwrap() + ); + } + + #[test] + fn best_containing_with_hash_not_found() { + // block tree: + // G + + let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + let uninserted_block = client.new_block(Default::default()).unwrap().build().unwrap().block; + + assert_eq!( + None, + longest_chain_select.finality_target(uninserted_block.hash().clone(), None).unwrap() + ); + } + + #[test] + fn uncles_with_only_ancestors() { + // block tree: + // G -> A1 -> A2 + let mut client = substrate_test_runtime_client::new(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + let v: Vec = Vec::new(); + assert_eq!(v, client.uncles(a2.hash(), 3).unwrap()); + } + + #[test] + fn uncles_with_multiple_forks() { + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + let mut client = substrate_test_runtime_client::new(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + // A3 -> A4 + let a4 = client.new_block_at( + &BlockId::Hash(a3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + + // A4 -> A5 + let a5 = client.new_block_at( + &BlockId::Hash(a4.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + + // A1 -> B2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // B2 -> B3 + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + // B3 -> B4 + let b4 = client.new_block_at( + &BlockId::Hash(b3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + + // // B2 -> C3 + let mut builder = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + + // A1 -> D2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + + let genesis_hash = client.chain_info().genesis_hash; + + let uncles1 = client.uncles(a4.hash(), 10).unwrap(); + assert_eq!(vec![b2.hash(), d2.hash()], uncles1); + + let uncles2 = client.uncles(a4.hash(), 0).unwrap(); + assert_eq!(0, uncles2.len()); + + let uncles3 = client.uncles(a1.hash(), 10).unwrap(); + assert_eq!(0, uncles3.len()); + + let uncles4 = client.uncles(genesis_hash, 10).unwrap(); + assert_eq!(0, uncles4.len()); + + let uncles5 = client.uncles(d2.hash(), 10).unwrap(); + assert_eq!(vec![a2.hash(), b2.hash()], uncles5); + + let uncles6 = client.uncles(b3.hash(), 1).unwrap(); + assert_eq!(vec![c3.hash()], uncles6); + } + + #[test] + fn best_containing_on_longest_chain_with_single_chain_3_blocks() { + // block tree: + // G -> A1 -> A2 + + let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let genesis_hash = client.chain_info().genesis_hash; + + assert_eq!(a2.hash(), longest_chain_select.finality_target(genesis_hash, None).unwrap().unwrap()); + assert_eq!(a2.hash(), longest_chain_select.finality_target(a1.hash(), None).unwrap().unwrap()); + assert_eq!(a2.hash(), longest_chain_select.finality_target(a2.hash(), None).unwrap().unwrap()); + } + + #[test] + fn best_containing_on_longest_chain_with_multiple_forks() { + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + // A3 -> A4 + let a4 = client.new_block_at( + &BlockId::Hash(a3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + + // A4 -> A5 + let a5 = client.new_block_at( + &BlockId::Hash(a4.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + + // A1 -> B2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // B2 -> B3 + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + // B3 -> B4 + let b4 = client.new_block_at( + &BlockId::Hash(b3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + + // // B2 -> C3 + let mut builder = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + + // A1 -> D2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + + assert_eq!(client.chain_info().best_hash, a5.hash()); + + let genesis_hash = client.chain_info().genesis_hash; + let leaves = longest_chain_select.leaves().unwrap(); + + assert!(leaves.contains(&a5.hash())); + assert!(leaves.contains(&b4.hash())); + assert!(leaves.contains(&c3.hash())); + assert!(leaves.contains(&d2.hash())); + assert_eq!(leaves.len(), 4); + + // search without restriction + + assert_eq!(a5.hash(), longest_chain_select.finality_target( + genesis_hash, None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a1.hash(), None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a2.hash(), None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a3.hash(), None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a4.hash(), None).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a5.hash(), None).unwrap().unwrap()); + + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b2.hash(), None).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b3.hash(), None).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b4.hash(), None).unwrap().unwrap()); + + assert_eq!(c3.hash(), longest_chain_select.finality_target( + c3.hash(), None).unwrap().unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), None).unwrap().unwrap()); + + + // search only blocks with number <= 5. equivalent to without restriction for this scenario + + assert_eq!(a5.hash(), longest_chain_select.finality_target( + genesis_hash, Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a1.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a2.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a3.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a4.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(a5.hash(), longest_chain_select.finality_target( + a5.hash(), Some(5)).unwrap().unwrap()); + + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b2.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b3.hash(), Some(5)).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b4.hash(), Some(5)).unwrap().unwrap()); + + assert_eq!(c3.hash(), longest_chain_select.finality_target( + c3.hash(), Some(5)).unwrap().unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), Some(5)).unwrap().unwrap()); + + + // search only blocks with number <= 4 + + assert_eq!(a4.hash(), longest_chain_select.finality_target( + genesis_hash, Some(4)).unwrap().unwrap()); + assert_eq!(a4.hash(), longest_chain_select.finality_target( + a1.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(a4.hash(), longest_chain_select.finality_target( + a2.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(a4.hash(), longest_chain_select.finality_target( + a3.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(a4.hash(), longest_chain_select.finality_target( + a4.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(4)).unwrap()); + + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b2.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b3.hash(), Some(4)).unwrap().unwrap()); + assert_eq!(b4.hash(), longest_chain_select.finality_target( + b4.hash(), Some(4)).unwrap().unwrap()); + + assert_eq!(c3.hash(), longest_chain_select.finality_target( + c3.hash(), Some(4)).unwrap().unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), Some(4)).unwrap().unwrap()); + + + // search only blocks with number <= 3 + + assert_eq!(a3.hash(), longest_chain_select.finality_target( + genesis_hash, Some(3)).unwrap().unwrap()); + assert_eq!(a3.hash(), longest_chain_select.finality_target( + a1.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(a3.hash(), longest_chain_select.finality_target( + a2.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(a3.hash(), longest_chain_select.finality_target( + a3.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a4.hash(), Some(3)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(3)).unwrap()); + + assert_eq!(b3.hash(), longest_chain_select.finality_target( + b2.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(b3.hash(), longest_chain_select.finality_target( + b3.hash(), Some(3)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b4.hash(), Some(3)).unwrap()); + + assert_eq!(c3.hash(), longest_chain_select.finality_target( + c3.hash(), Some(3)).unwrap().unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), Some(3)).unwrap().unwrap()); + + + // search only blocks with number <= 2 + + assert_eq!(a2.hash(), longest_chain_select.finality_target( + genesis_hash, Some(2)).unwrap().unwrap()); + assert_eq!(a2.hash(), longest_chain_select.finality_target( + a1.hash(), Some(2)).unwrap().unwrap()); + assert_eq!(a2.hash(), longest_chain_select.finality_target( + a2.hash(), Some(2)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a3.hash(), Some(2)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a4.hash(), Some(2)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(2)).unwrap()); + + assert_eq!(b2.hash(), longest_chain_select.finality_target( + b2.hash(), Some(2)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b3.hash(), Some(2)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b4.hash(), Some(2)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + c3.hash(), Some(2)).unwrap()); + + assert_eq!(d2.hash(), longest_chain_select.finality_target( + d2.hash(), Some(2)).unwrap().unwrap()); + + + // search only blocks with number <= 1 + + assert_eq!(a1.hash(), longest_chain_select.finality_target( + genesis_hash, Some(1)).unwrap().unwrap()); + assert_eq!(a1.hash(), longest_chain_select.finality_target( + a1.hash(), Some(1)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a2.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a3.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a4.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(1)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + b2.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b3.hash(), Some(1)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b4.hash(), Some(1)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + c3.hash(), Some(1)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + d2.hash(), Some(1)).unwrap()); + + // search only blocks with number <= 0 + + assert_eq!(genesis_hash, longest_chain_select.finality_target( + genesis_hash, Some(0)).unwrap().unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a1.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a2.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a3.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a4.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + a5.hash(), Some(0)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + b2.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b3.hash(), Some(0)).unwrap()); + assert_eq!(None, longest_chain_select.finality_target( + b4.hash(), Some(0)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + c3.hash().clone(), Some(0)).unwrap()); + + assert_eq!(None, longest_chain_select.finality_target( + d2.hash().clone(), Some(0)).unwrap()); + } + + #[test] + fn best_containing_on_longest_chain_with_max_depth_higher_than_best() { + // block tree: + // G -> A1 -> A2 + + let (mut client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let genesis_hash = client.chain_info().genesis_hash; + + assert_eq!(a2.hash(), longest_chain_select.finality_target(genesis_hash, Some(10)).unwrap().unwrap()); + } + + #[test] + fn key_changes_works() { + let (client, _, test_cases) = prepare_client_with_key_changes(); + + for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { + let end = client.block_hash(end).unwrap().unwrap(); + let actual_result = client.key_changes( + begin, + BlockId::Hash(end), + None, + &StorageKey(key), + ).unwrap(); + match actual_result == expected_result { + true => (), + false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}", + index, actual_result, expected_result)), + } + } + } + + #[test] + fn import_with_justification() { + let mut client = substrate_test_runtime_client::new(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let justification = vec![1, 2, 3]; + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import_justified(BlockOrigin::Own, a3.clone(), justification.clone()).unwrap(); + + assert_eq!( + client.chain_info().finalized_hash, + a3.hash(), + ); + + assert_eq!( + client.justification(&BlockId::Hash(a3.hash())).unwrap(), + Some(justification), + ); + + assert_eq!( + client.justification(&BlockId::Hash(a1.hash())).unwrap(), + None, + ); + + assert_eq!( + client.justification(&BlockId::Hash(a2.hash())).unwrap(), + None, + ); + } + + #[test] + fn importing_diverged_finalized_block_should_trigger_reorg() { + let mut client = substrate_test_runtime_client::new(); + + // G -> A1 -> A2 + // \ + // -> B1 + let a1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let mut b1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap(); + // needed to make sure B1 gets a different hash from A1 + b1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + // create but don't import B1 just yet + let b1 = b1.build().unwrap().block; + + // A2 is the current best since it's the longest chain + assert_eq!( + client.chain_info().best_hash, + a2.hash(), + ); + + // importing B1 as finalized should trigger a re-org and set it as new best + let justification = vec![1, 2, 3]; + client.import_justified(BlockOrigin::Own, b1.clone(), justification).unwrap(); + + assert_eq!( + client.chain_info().best_hash, + b1.hash(), + ); + + assert_eq!( + client.chain_info().finalized_hash, + b1.hash(), + ); + } + + #[test] + fn finalizing_diverged_block_should_trigger_reorg() { + + let (mut client, select_chain) = TestClientBuilder::new().build_with_longest_chain(); + + // G -> A1 -> A2 + // \ + // -> B1 -> B2 + let a1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let mut b1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap(); + // needed to make sure B1 gets a different hash from A1 + b1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let b1 = b1.build().unwrap().block; + client.import(BlockOrigin::Own, b1.clone()).unwrap(); + + let b2 = client.new_block_at( + &BlockId::Hash(b1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // A2 is the current best since it's the longest chain + assert_eq!( + client.chain_info().best_hash, + a2.hash(), + ); + + // we finalize block B1 which is on a different branch from current best + // which should trigger a re-org. + ClientExt::finalize_block(&client, BlockId::Hash(b1.hash()), None).unwrap(); + + // B1 should now be the latest finalized + assert_eq!( + client.chain_info().finalized_hash, + b1.hash(), + ); + + // and B1 should be the new best block (`finalize_block` as no way of + // knowing about B2) + assert_eq!( + client.chain_info().best_hash, + b1.hash(), + ); + + // `SelectChain` should report B2 as best block though + assert_eq!( + select_chain.best_chain().unwrap().hash(), + b2.hash(), + ); + + // after we build B3 on top of B2 and import it + // it should be the new best block, + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + assert_eq!( + client.chain_info().best_hash, + b3.hash(), + ); + } + + #[test] + fn get_header_by_block_number_doesnt_panic() { + let client = substrate_test_runtime_client::new(); + + // backend uses u32 for block numbers, make sure we don't panic when + // trying to convert + let id = BlockId::::Number(72340207214430721); + client.header(&id).expect_err("invalid block number overflows u32"); + } + + #[test] + fn state_reverted_on_reorg() { + let _ = env_logger::try_init(); + let mut client = substrate_test_runtime_client::new(); + + let current_balance = |client: &substrate_test_runtime_client::TestClient| + client.runtime_api().balance_of( + &BlockId::number(client.chain_info().best_number), AccountKeyring::Alice.into() + ).unwrap(); + + // G -> A1 -> A2 + // \ + // -> B1 + let mut a1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap(); + a1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), + amount: 10, + nonce: 0, + }).unwrap(); + let a1 = a1.build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + let mut b1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap(); + b1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 50, + nonce: 0, + }).unwrap(); + let b1 = b1.build().unwrap().block; + // Reorg to B1 + client.import_as_best(BlockOrigin::Own, b1.clone()).unwrap(); + + assert_eq!(950, current_balance(&client)); + let mut a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + a2.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Charlie.into(), + amount: 10, + nonce: 1, + }).unwrap(); + let a2 = a2.build().unwrap().block; + // Re-org to A2 + client.import_as_best(BlockOrigin::Own, a2).unwrap(); + assert_eq!(980, current_balance(&client)); + } + + #[test] + fn doesnt_import_blocks_that_revert_finality() { + let _ = env_logger::try_init(); + let tmp = tempfile::tempdir().unwrap(); + + // we need to run with archive pruning to avoid pruning non-canonical + // states + let backend = Arc::new(Backend::new( + DatabaseSettings { + state_cache_size: 1 << 20, + state_cache_child_ratio: None, + pruning: PruningMode::ArchiveAll, + source: DatabaseSettingsSrc::Path { + path: tmp.path().into(), + cache_size: None, + } + }, + u64::max_value(), + ).unwrap()); + + let mut client = TestClientBuilder::with_backend(backend).build(); + + // -> C1 + // / + // G -> A1 -> A2 + // \ + // -> B1 -> B2 -> B3 + + let a1 = client.new_block_at( + &BlockId::Number(0), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + + // needed to make sure B1 gets a different hash from A1 + b1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let b1 = b1.build().unwrap().block; + client.import(BlockOrigin::Own, b1.clone()).unwrap(); + + let b2 = client.new_block_at(&BlockId::Hash(b1.hash()), Default::default(), false) + .unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // we will finalize A2 which should make it impossible to import a new + // B3 at the same height but that doesnt't include it + ClientExt::finalize_block(&client, BlockId::Hash(a2.hash()), None).unwrap(); + + let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default(), false) + .unwrap().build().unwrap().block; + + let import_err = client.import(BlockOrigin::Own, b3).err().unwrap(); + let expected_err = ConsensusError::ClientImport( + sp_blockchain::Error::NotInFinalizedChain.to_string() + ); + + assert_eq!( + import_err.to_string(), + expected_err.to_string(), + ); + + // adding a C1 block which is lower than the last finalized should also + // fail (with a cheaper check that doesn't require checking ancestry). + let mut c1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + + // needed to make sure C1 gets a different hash from A1 and B1 + c1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 2, + nonce: 0, + }).unwrap(); + let c1 = c1.build().unwrap().block; + + let import_err = client.import(BlockOrigin::Own, c1).err().unwrap(); + let expected_err = ConsensusError::ClientImport( + sp_blockchain::Error::NotInFinalizedChain.to_string() + ); + + assert_eq!( + import_err.to_string(), + expected_err.to_string(), + ); + } + + #[test] + fn returns_status_for_pruned_blocks() { + let _ = env_logger::try_init(); + let tmp = tempfile::tempdir().unwrap(); + + // set to prune after 1 block + // states + let backend = Arc::new(Backend::new( + DatabaseSettings { + state_cache_size: 1 << 20, + state_cache_child_ratio: None, + pruning: PruningMode::keep_blocks(1), + source: DatabaseSettingsSrc::Path { + path: tmp.path().into(), + cache_size: None, + } + }, + u64::max_value(), + ).unwrap()); + + let mut client = TestClientBuilder::with_backend(backend).build(); + + let a1 = client.new_block_at(&BlockId::Number(0), Default::default(), false) + .unwrap().build().unwrap().block; + + let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default(), false).unwrap(); + + // b1 is created, but not imported + b1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let b1 = b1.build().unwrap().block; + + let check_block_a1 = BlockCheckParams { + hash: a1.hash().clone(), + number: 0, + parent_hash: a1.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + + assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::imported(false)); + assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::Unknown); + + client.import_as_final(BlockOrigin::Own, a1.clone()).unwrap(); + + assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainWithState); + + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default(), false) + .unwrap().build().unwrap().block; + client.import_as_final(BlockOrigin::Own, a2.clone()).unwrap(); + + let check_block_a2 = BlockCheckParams { + hash: a2.hash().clone(), + number: 1, + parent_hash: a1.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + + assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainPruned); + assert_eq!(client.check_block(check_block_a2.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a2.hash)).unwrap(), BlockStatus::InChainWithState); + + let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default(), false) + .unwrap().build().unwrap().block; + + client.import_as_final(BlockOrigin::Own, a3.clone()).unwrap(); + let check_block_a3 = BlockCheckParams { + hash: a3.hash().clone(), + number: 2, + parent_hash: a2.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + + // a1 and a2 are both pruned at this point + assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainPruned); + assert_eq!(client.check_block(check_block_a2.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a2.hash)).unwrap(), BlockStatus::InChainPruned); + assert_eq!(client.check_block(check_block_a3.clone()).unwrap(), ImportResult::AlreadyInChain); + assert_eq!(client.block_status(&BlockId::hash(check_block_a3.hash)).unwrap(), BlockStatus::InChainWithState); + + let mut check_block_b1 = BlockCheckParams { + hash: b1.hash().clone(), + number: 0, + parent_hash: b1.header().parent_hash().clone(), + allow_missing_state: false, + import_existing: false, + }; + assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::MissingState); + check_block_b1.allow_missing_state = true; + assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::imported(false)); + check_block_b1.parent_hash = H256::random(); + assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::UnknownParent); + } +} diff --git a/client/src/genesis.rs b/client/src/genesis.rs new file mode 100644 index 0000000000000..ab89bdd4d5e13 --- /dev/null +++ b/client/src/genesis.rs @@ -0,0 +1,235 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tool for creating the genesis block. + +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, Zero}; + +/// Create a genesis block, given the initial storage. +pub fn construct_genesis_block< + Block: BlockT +> ( + state_root: Block::Hash +) -> Block { + let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + Vec::new(), + ); + + Block::new( + <::Header as HeaderT>::new( + Zero::zero(), + extrinsics_root, + state_root, + Default::default(), + Default::default() + ), + Default::default() + ) +} + +#[cfg(test)] +mod tests { + use codec::{Encode, Decode, Joiner}; + use sc_executor::native_executor_instance; + use sp_state_machine::{ + StateMachine, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage, + InMemoryBackend, + }; + use substrate_test_runtime_client::{ + runtime::genesismap::{GenesisConfig, insert_genesis_block}, + runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest}, + AccountKeyring, Sr25519Keyring, + }; + use sp_core::Blake2Hasher; + use hex_literal::*; + + native_executor_instance!( + Executor, + substrate_test_runtime_client::runtime::api::dispatch, + substrate_test_runtime_client::runtime::native_version + ); + + fn executor() -> sc_executor::NativeExecutor { + sc_executor::NativeExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None) + } + + fn construct_block( + backend: &InMemoryBackend, + number: BlockNumber, + parent_hash: Hash, + state_root: Hash, + txs: Vec + ) -> (Vec, Hash) { + use sp_trie::{TrieConfiguration, trie_types::Layout}; + + let transactions = txs.into_iter().map(|tx| tx.into_signed_tx()).collect::>(); + + let iter = transactions.iter().map(Encode::encode); + let extrinsics_root = Layout::::ordered_trie_root(iter).into(); + + let mut header = Header { + parent_hash, + number, + state_root, + extrinsics_root, + digest: Digest { logs: vec![], }, + }; + let hash = header.hash(); + let mut overlay = OverlayedChanges::default(); + + StateMachine::new( + backend, + Some(&InMemoryChangesTrieStorage::<_, u64>::new()), + &mut overlay, + &executor(), + "Core_initialize_block", + &header.encode(), + Default::default(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ).unwrap(); + + for tx in transactions.iter() { + StateMachine::new( + backend, + Some(&InMemoryChangesTrieStorage::<_, u64>::new()), + &mut overlay, + &executor(), + "BlockBuilder_apply_extrinsic", + &tx.encode(), + Default::default(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ).unwrap(); + } + + let ret_data = StateMachine::new( + backend, + Some(&InMemoryChangesTrieStorage::<_, u64>::new()), + &mut overlay, + &executor(), + "BlockBuilder_finalize_block", + &[], + Default::default(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ).unwrap(); + header = Header::decode(&mut &ret_data[..]).unwrap(); + + (vec![].and(&Block { header, extrinsics: transactions }), hash) + } + + fn block1(genesis_hash: Hash, backend: &InMemoryBackend) -> (Vec, Hash) { + construct_block( + backend, + 1, + genesis_hash, + hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), + vec![Transfer { + from: AccountKeyring::One.into(), + to: AccountKeyring::Two.into(), + amount: 69, + nonce: 0, + }] + ) + } + + #[test] + fn construct_genesis_should_work_with_native() { + let mut storage = GenesisConfig::new( + false, + vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000, + None, + Default::default(), + ).genesis_map(); + let genesis_hash = insert_genesis_block(&mut storage); + + let backend = InMemoryBackend::from(storage); + let (b1data, _b1hash) = block1(genesis_hash, &backend); + + let mut overlay = OverlayedChanges::default(); + let _ = StateMachine::new( + &backend, + Some(&InMemoryChangesTrieStorage::<_, u64>::new()), + &mut overlay, + &executor(), + "Core_execute_block", + &b1data, + Default::default(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ).unwrap(); + } + + #[test] + fn construct_genesis_should_work_with_wasm() { + let mut storage = GenesisConfig::new(false, + vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000, + None, + Default::default(), + ).genesis_map(); + let genesis_hash = insert_genesis_block(&mut storage); + + let backend = InMemoryBackend::from(storage); + let (b1data, _b1hash) = block1(genesis_hash, &backend); + + let mut overlay = OverlayedChanges::default(); + let _ = StateMachine::new( + &backend, + Some(&InMemoryChangesTrieStorage::<_, u64>::new()), + &mut overlay, + &executor(), + "Core_execute_block", + &b1data, + Default::default(), + ).execute( + ExecutionStrategy::AlwaysWasm, + ).unwrap(); + } + + #[test] + fn construct_genesis_with_bad_transaction_should_panic() { + let mut storage = GenesisConfig::new(false, + vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 68, + None, + Default::default(), + ).genesis_map(); + let genesis_hash = insert_genesis_block(&mut storage); + + let backend = InMemoryBackend::from(storage); + let (b1data, _b1hash) = block1(genesis_hash, &backend); + + let mut overlay = OverlayedChanges::default(); + let r = StateMachine::new( + &backend, + Some(&InMemoryChangesTrieStorage::<_, u64>::new()), + &mut overlay, + &executor(), + "Core_execute_block", + &b1data, + Default::default(), + ).execute( + ExecutionStrategy::NativeElseWasm, + ); + assert!(r.is_err()); + } +} diff --git a/client/src/in_mem.rs b/client/src/in_mem.rs new file mode 100644 index 0000000000000..5d0d14c1cb1d7 --- /dev/null +++ b/client/src/in_mem.rs @@ -0,0 +1,854 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! In memory client backend + +use std::collections::{HashMap, HashSet}; +use std::sync::Arc; +use parking_lot::RwLock; +use sp_core::{ChangesTrieConfiguration, storage::well_known_keys}; +use sp_core::offchain::storage::{ + InMemOffchainStorage as OffchainStorage +}; +use sp_runtime::generic::{BlockId, DigestItem}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor, HasherFor}; +use sp_runtime::{Justification, Storage}; +use sp_state_machine::{ + InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction, + InMemoryBackend, Backend as StateBackend, +}; +use hash_db::Prefix; +use sp_trie::MemoryDB; +use sp_blockchain::{CachedHeaderMetadata, HeaderMetadata}; + +use sc_client_api::{ + backend::{self, NewBlockState, StorageCollection, ChildStorageCollection}, + blockchain::{ + self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId + }, + UsageInfo, +}; +use crate::leaves::LeafSet; + +struct PendingBlock { + block: StoredBlock, + state: NewBlockState, +} + +#[derive(PartialEq, Eq, Clone)] +enum StoredBlock { + Header(B::Header, Option), + Full(B, Option), +} + +impl StoredBlock { + fn new(header: B::Header, body: Option>, just: Option) -> Self { + match body { + Some(body) => StoredBlock::Full(B::new(header, body), just), + None => StoredBlock::Header(header, just), + } + } + + fn header(&self) -> &B::Header { + match *self { + StoredBlock::Header(ref h, _) => h, + StoredBlock::Full(ref b, _) => b.header(), + } + } + + fn justification(&self) -> Option<&Justification> { + match *self { + StoredBlock::Header(_, ref j) | StoredBlock::Full(_, ref j) => j.as_ref() + } + } + + fn extrinsics(&self) -> Option<&[B::Extrinsic]> { + match *self { + StoredBlock::Header(_, _) => None, + StoredBlock::Full(ref b, _) => Some(b.extrinsics()), + } + } + + fn into_inner(self) -> (B::Header, Option>, Option) { + match self { + StoredBlock::Header(header, just) => (header, None, just), + StoredBlock::Full(block, just) => { + let (header, body) = block.deconstruct(); + (header, Some(body), just) + } + } + } +} + +#[derive(Clone)] +struct BlockchainStorage { + blocks: HashMap>, + hashes: HashMap, Block::Hash>, + best_hash: Block::Hash, + best_number: NumberFor, + finalized_hash: Block::Hash, + finalized_number: NumberFor, + genesis_hash: Block::Hash, + header_cht_roots: HashMap, Block::Hash>, + changes_trie_cht_roots: HashMap, Block::Hash>, + leaves: LeafSet>, + aux: HashMap, Vec>, +} + +/// In-memory blockchain. Supports concurrent reads. +pub struct Blockchain { + storage: Arc>>, +} + +impl Clone for Blockchain { + fn clone(&self) -> Self { + let storage = Arc::new(RwLock::new(self.storage.read().clone())); + Blockchain { + storage: storage.clone(), + } + } +} + +impl Blockchain { + /// Get header hash of given block. + pub fn id(&self, id: BlockId) -> Option { + match id { + BlockId::Hash(h) => Some(h), + BlockId::Number(n) => self.storage.read().hashes.get(&n).cloned(), + } + } + + /// Create new in-memory blockchain storage. + pub fn new() -> Blockchain { + let storage = Arc::new(RwLock::new( + BlockchainStorage { + blocks: HashMap::new(), + hashes: HashMap::new(), + best_hash: Default::default(), + best_number: Zero::zero(), + finalized_hash: Default::default(), + finalized_number: Zero::zero(), + genesis_hash: Default::default(), + header_cht_roots: HashMap::new(), + changes_trie_cht_roots: HashMap::new(), + leaves: LeafSet::new(), + aux: HashMap::new(), + })); + Blockchain { + storage: storage.clone(), + } + } + + /// Insert a block header and associated data. + pub fn insert( + &self, + hash: Block::Hash, + header: ::Header, + justification: Option, + body: Option::Extrinsic>>, + new_state: NewBlockState, + ) -> sp_blockchain::Result<()> { + let number = header.number().clone(); + if new_state.is_best() { + self.apply_head(&header)?; + } + + { + 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 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 + } + + /// Compare canonical chain to other canonical chain. + pub fn canon_equals_to(&self, other: &Self) -> bool { + let this = self.storage.read(); + let other = other.storage.read(); + this.hashes == other.hashes + && this.best_hash == other.best_hash + && this.best_number == other.best_number + && this.genesis_hash == other.genesis_hash + } + + /// Insert header CHT root. + pub fn insert_cht_root(&self, block: NumberFor, cht_root: Block::Hash) { + self.storage.write().header_cht_roots.insert(block, cht_root); + } + + /// Set an existing block as head. + pub fn set_head(&self, id: BlockId) -> sp_blockchain::Result<()> { + let header = match self.header(id)? { + Some(h) => h, + None => return Err(sp_blockchain::Error::UnknownBlock(format!("{}", id))), + }; + + self.apply_head(&header) + } + + fn apply_head(&self, header: &::Header) -> sp_blockchain::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 = sp_blockchain::tree_route(self, best_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) -> sp_blockchain::Result<()> { + let hash = match self.header(id)? { + Some(h) => h.hash(), + None => return Err(sp_blockchain::Error::UnknownBlock(format!("{}", id))), + }; + + let mut storage = self.storage.write(); + storage.finalized_hash = hash; + + if justification.is_some() { + let block = storage.blocks.get_mut(&hash) + .expect("hash was fetched from a block in the db; qed"); + + let block_justification = match block { + StoredBlock::Header(_, ref mut j) | StoredBlock::Full(_, ref mut j) => j + }; + + *block_justification = justification; + } + + Ok(()) + } + + fn write_aux(&self, ops: Vec<(Vec, Option>)>) { + let mut storage = self.storage.write(); + for (k, v) in ops { + match v { + Some(v) => storage.aux.insert(k, v), + None => storage.aux.remove(&k), + }; + } + } +} + +impl HeaderBackend for Blockchain { + fn header(&self, id: BlockId) -> sp_blockchain::Result::Header>> { + Ok(self.id(id).and_then(|hash| { + self.storage.read().blocks.get(&hash).map(|b| b.header().clone()) + })) + } + + fn info(&self) -> blockchain::Info { + let storage = self.storage.read(); + blockchain::Info { + best_hash: storage.best_hash, + best_number: storage.best_number, + genesis_hash: storage.genesis_hash, + finalized_hash: storage.finalized_hash, + finalized_number: storage.finalized_number, + } + } + + fn status(&self, id: BlockId) -> sp_blockchain::Result { + match self.id(id).map_or(false, |hash| self.storage.read().blocks.contains_key(&hash)) { + true => Ok(BlockStatus::InChain), + false => Ok(BlockStatus::Unknown), + } + } + + fn number(&self, hash: Block::Hash) -> sp_blockchain::Result>> { + Ok(self.storage.read().blocks.get(&hash).map(|b| *b.header().number())) + } + + fn hash(&self, number: <::Header as HeaderT>::Number) -> sp_blockchain::Result> { + Ok(self.id(BlockId::Number(number))) + } +} + +impl HeaderMetadata for Blockchain { + type Error = sp_blockchain::Error; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header)) + .ok_or(sp_blockchain::Error::UnknownBlock(format!("header not found: {}", hash))) + } + + fn insert_header_metadata(&self, _hash: Block::Hash, _metadata: CachedHeaderMetadata) { + // No need to implement. + } + fn remove_header_metadata(&self, _hash: Block::Hash) { + // No need to implement. + } +} + +impl blockchain::Backend for Blockchain { + fn body(&self, id: BlockId) -> sp_blockchain::Result::Extrinsic>>> { + Ok(self.id(id).and_then(|hash| { + self.storage.read().blocks.get(&hash) + .and_then(|b| b.extrinsics().map(|x| x.to_vec())) + })) + } + + fn justification(&self, id: BlockId) -> sp_blockchain::Result> { + Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| + b.justification().map(|x| x.clone())) + )) + } + + fn last_finalized(&self) -> sp_blockchain::Result { + Ok(self.storage.read().finalized_hash.clone()) + } + + fn cache(&self) -> Option>> { + None + } + + fn leaves(&self) -> sp_blockchain::Result> { + Ok(self.storage.read().leaves.hashes()) + } + + fn children(&self, _parent_hash: Block::Hash) -> sp_blockchain::Result> { + unimplemented!() + } +} + +impl blockchain::ProvideCache for Blockchain { + fn cache(&self) -> Option>> { + None + } +} + +impl backend::AuxStore for Blockchain { + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> { + let mut storage = self.storage.write(); + for (k, v) in insert { + storage.aux.insert(k.to_vec(), v.to_vec()); + } + for k in delete { + storage.aux.remove(*k); + } + Ok(()) + } + + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { + Ok(self.storage.read().aux.get(key).cloned()) + } +} + +impl sc_client_api::light::Storage for Blockchain + where + Block::Hash: From<[u8; 32]>, +{ + fn import_header( + &self, + header: Block::Header, + _cache: HashMap>, + state: NewBlockState, + aux_ops: Vec<(Vec, Option>)>, + ) -> sp_blockchain::Result<()> { + let hash = header.hash(); + self.insert(hash, header, None, None, state)?; + + self.write_aux(aux_ops); + Ok(()) + } + + fn set_head(&self, id: BlockId) -> sp_blockchain::Result<()> { + Blockchain::set_head(self, id) + } + + fn last_finalized(&self) -> sp_blockchain::Result { + Ok(self.storage.read().finalized_hash.clone()) + } + + fn finalize_header(&self, id: BlockId) -> sp_blockchain::Result<()> { + Blockchain::finalize_header(self, id, None) + } + + fn header_cht_root( + &self, + _cht_size: NumberFor, + block: NumberFor, + ) -> sp_blockchain::Result> { + self.storage.read().header_cht_roots.get(&block).cloned() + .ok_or_else(|| sp_blockchain::Error::Backend(format!("Header CHT for block {} not exists", block))) + .map(Some) + } + + fn changes_trie_cht_root( + &self, + _cht_size: NumberFor, + block: NumberFor, + ) -> sp_blockchain::Result> { + self.storage.read().changes_trie_cht_roots.get(&block).cloned() + .ok_or_else(|| sp_blockchain::Error::Backend(format!("Changes trie CHT for block {} not exists", block))) + .map(Some) + } + + fn cache(&self) -> Option>> { + None + } + + fn usage_info(&self) -> Option { + None + } +} + +/// In-memory operation. +pub struct BlockImportOperation { + pending_block: Option>, + pending_cache: HashMap>, + old_state: InMemoryBackend>, + new_state: Option>>, + changes_trie_update: Option>>, + aux: Vec<(Vec, Option>)>, + finalized_blocks: Vec<(BlockId, Option)>, + set_head: Option>, +} + +impl backend::BlockImportOperation for BlockImportOperation where + Block::Hash: Ord, +{ + type State = InMemoryBackend>; + + fn state(&self) -> sp_blockchain::Result> { + Ok(Some(&self.old_state)) + } + + fn set_block_data( + &mut self, + header: ::Header, + body: Option::Extrinsic>>, + justification: Option, + state: NewBlockState, + ) -> sp_blockchain::Result<()> { + assert!(self.pending_block.is_none(), "Only one block per operation is allowed"); + self.pending_block = Some(PendingBlock { + block: StoredBlock::new(header, body, justification), + state, + }); + Ok(()) + } + + fn update_cache(&mut self, cache: HashMap>) { + self.pending_cache = cache; + } + + fn update_db_storage( + &mut self, + update: > as StateBackend>>::Transaction, + ) -> sp_blockchain::Result<()> { + self.new_state = Some(self.old_state.update(update)); + Ok(()) + } + + fn update_changes_trie( + &mut self, + update: ChangesTrieTransaction, NumberFor>, + ) -> sp_blockchain::Result<()> { + self.changes_trie_update = Some(update.0); + Ok(()) + } + + fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result { + check_genesis_storage(&storage)?; + + let child_delta = storage.children.into_iter() + .map(|(storage_key, child_content)| + (storage_key, child_content.data.into_iter().map(|(k, v)| (k, Some(v))), child_content.child_info)); + + let (root, transaction) = self.old_state.full_storage_root( + storage.top.into_iter().map(|(k, v)| (k, Some(v))), + child_delta + ); + + self.new_state = Some(InMemoryBackend::from(transaction)); + Ok(root) + } + + fn insert_aux(&mut self, ops: I) -> sp_blockchain::Result<()> + where I: IntoIterator, Option>)> + { + self.aux.append(&mut ops.into_iter().collect()); + Ok(()) + } + + fn update_storage( + &mut self, + _update: StorageCollection, + _child_update: ChildStorageCollection, + ) -> sp_blockchain::Result<()> { + Ok(()) + } + + fn mark_finalized( + &mut self, + block: BlockId, + justification: Option, + ) -> sp_blockchain::Result<()> { + self.finalized_blocks.push((block, justification)); + Ok(()) + } + + fn mark_head(&mut self, block: BlockId) -> sp_blockchain::Result<()> { + assert!(self.pending_block.is_none(), "Only one set block per operation is allowed"); + self.set_head = Some(block); + Ok(()) + } +} + +/// In-memory backend. Keeps all states and blocks in memory. +/// +/// > **Warning**: Doesn't support all the features necessary for a proper database. Only use this +/// > struct for testing purposes. Do **NOT** use in production. +pub struct Backend where Block::Hash: Ord { + states: RwLock>>>, + changes_trie_storage: ChangesTrieStorage, + blockchain: Blockchain, + import_lock: RwLock<()>, +} + +impl Backend where Block::Hash: Ord { + /// Create a new instance of in-mem backend. + pub fn new() -> Self { + Backend { + states: RwLock::new(HashMap::new()), + changes_trie_storage: ChangesTrieStorage(InMemoryChangesTrieStorage::new()), + blockchain: Blockchain::new(), + import_lock: Default::default(), + } + } +} + +impl backend::AuxStore for Backend where Block::Hash: Ord { + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> sp_blockchain::Result<()> { + self.blockchain.insert_aux(insert, delete) + } + + fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result>> { + self.blockchain.get_aux(key) + } +} + +impl backend::Backend for Backend where Block::Hash: Ord { + type BlockImportOperation = BlockImportOperation; + type Blockchain = Blockchain; + type State = InMemoryBackend>; + type ChangesTrieStorage = ChangesTrieStorage; + type OffchainStorage = OffchainStorage; + + fn begin_operation(&self) -> sp_blockchain::Result { + let old_state = self.state_at(BlockId::Hash(Default::default()))?; + Ok(BlockImportOperation { + pending_block: None, + pending_cache: Default::default(), + old_state, + new_state: None, + changes_trie_update: None, + aux: Default::default(), + finalized_blocks: Default::default(), + set_head: None, + }) + } + + fn begin_state_operation( + &self, + operation: &mut Self::BlockImportOperation, + block: BlockId, + ) -> sp_blockchain::Result<()> { + operation.old_state = self.state_at(block)?; + Ok(()) + } + + fn commit_operation(&self, operation: Self::BlockImportOperation) -> sp_blockchain::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(); + + let hash = header.hash(); + + self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone())); + + let maybe_changes_trie_root = header.digest().log(DigestItem::as_changes_trie_root).cloned(); + if let Some(changes_trie_root) = maybe_changes_trie_root { + if let Some(changes_trie_update) = operation.changes_trie_update { + self.changes_trie_storage.0.insert( + *header.number(), + changes_trie_root, + changes_trie_update + ); + } + } + + self.blockchain.insert(hash, header, justification, body, pending_block.state)?; + } + + 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(()) + } + + fn finalize_block( + &self, + block: BlockId, + justification: Option, + ) -> sp_blockchain::Result<()> { + self.blockchain.finalize_header(block, justification) + } + + fn blockchain(&self) -> &Self::Blockchain { + &self.blockchain + } + + fn usage_info(&self) -> Option { + None + } + + fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage> { + Some(&self.changes_trie_storage) + } + + fn offchain_storage(&self) -> Option { + None + } + + fn state_at(&self, block: BlockId) -> sp_blockchain::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(sp_blockchain::Error::UnknownBlock(format!("{}", block))), + } + } + + fn revert( + &self, + _n: NumberFor, + _revert_finalized: bool, + ) -> sp_blockchain::Result> { + Ok(Zero::zero()) + } + + fn get_import_lock(&self) -> &RwLock<()> { + &self.import_lock + } +} + +impl backend::LocalBackend for Backend where Block::Hash: Ord {} + +impl backend::RemoteBackend for Backend where Block::Hash: 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) + } + + fn remote_blockchain(&self) -> Arc> { + unimplemented!() + } +} + +/// Prunable in-memory changes trie storage. +pub struct ChangesTrieStorage( + InMemoryChangesTrieStorage, NumberFor> +); + +impl backend::PrunableStateChangesTrieStorage for ChangesTrieStorage { + fn oldest_changes_trie_block( + &self, + _config: &ChangesTrieConfiguration, + _best_finalized: NumberFor, + ) -> NumberFor { + Zero::zero() + } +} + +impl sp_state_machine::ChangesTrieRootsStorage, NumberFor> for + ChangesTrieStorage +{ + fn build_anchor( + &self, + _hash: Block::Hash, + ) -> Result>, String> { + Err("Dummy implementation".into()) + } + + fn root( + &self, + _anchor: &ChangesTrieAnchorBlockId>, + _block: NumberFor, + ) -> Result, String> { + Err("Dummy implementation".into()) + } +} + +impl sp_state_machine::ChangesTrieStorage, NumberFor> for + ChangesTrieStorage +{ + fn as_roots_storage(&self) + -> &dyn sp_state_machine::ChangesTrieRootsStorage, NumberFor> + { + self + } + + fn with_cached_changed_keys( + &self, + _root: &Block::Hash, + _functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool { + false + } + + fn get( + &self, + key: &Block::Hash, + prefix: Prefix, + ) -> Result, String> { + self.0.get(key, prefix) + } +} + +/// Check that genesis storage is valid. +pub fn check_genesis_storage(storage: &Storage) -> sp_blockchain::Result<()> { + if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { + return Err(sp_blockchain::Error::GenesisInvalid.into()); + } + + if storage.children.keys().any(|child_key| !well_known_keys::is_child_storage_key(&child_key)) { + return Err(sp_blockchain::Error::GenesisInvalid.into()); + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use sp_core::offchain::{OffchainStorage, storage::InMemOffchainStorage}; + use std::sync::Arc; + + type TestBackend = substrate_test_runtime_client::sc_client::in_mem::Backend; + + #[test] + fn test_leaves_with_complex_block_tree() { + let backend = Arc::new(TestBackend::new()); + + substrate_test_runtime_client::trait_tests::test_leaves_for_backend(backend); + } + + #[test] + fn test_blockchain_query_by_number_gets_canonical() { + let backend = Arc::new(TestBackend::new()); + + substrate_test_runtime_client::trait_tests::test_blockchain_query_by_number_gets_canonical(backend); + } + + #[test] + fn in_memory_offchain_storage() { + + let mut storage = InMemOffchainStorage::default(); + assert_eq!(storage.get(b"A", b"B"), None); + assert_eq!(storage.get(b"B", b"A"), None); + + storage.set(b"A", b"B", b"C"); + assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec())); + assert_eq!(storage.get(b"B", b"A"), None); + + storage.compare_and_set(b"A", b"B", Some(b"X"), b"D"); + assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec())); + storage.compare_and_set(b"A", b"B", Some(b"C"), b"D"); + assert_eq!(storage.get(b"A", b"B"), Some(b"D".to_vec())); + + assert!(!storage.compare_and_set(b"B", b"A", Some(b""), b"Y")); + assert!(storage.compare_and_set(b"B", b"A", None, b"X")); + assert_eq!(storage.get(b"B", b"A"), Some(b"X".to_vec())); + } +} diff --git a/core/client/src/leaves.rs b/client/src/leaves.rs similarity index 84% rename from core/client/src/leaves.rs rename to client/src/leaves.rs index 825c1bf7c0bb5..bb556da83a84a 100644 --- a/core/client/src/leaves.rs +++ b/client/src/leaves.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,9 +19,9 @@ use std::collections::BTreeMap; use std::cmp::Reverse; use kvdb::{KeyValueDB, DBTransaction}; -use sr_primitives::traits::SimpleArithmetic; +use sp_runtime::traits::SimpleArithmetic; use codec::{Encode, Decode}; -use crate::error; +use sp_blockchain::{Error, Result}; #[derive(Debug, Clone, PartialEq, Eq)] struct LeafSetItem { @@ -77,7 +77,7 @@ impl LeafSet where } /// Read the leaf list from the DB, using given prefix for keys. - pub fn read_from_db(db: &dyn KeyValueDB, column: Option, prefix: &[u8]) -> error::Result { + pub fn read_from_db(db: &dyn KeyValueDB, column: u32, prefix: &[u8]) -> Result { let mut storage = BTreeMap::new(); for (key, value) in db.iter_from_prefix(column, prefix) { @@ -85,11 +85,11 @@ impl LeafSet where let raw_hash = &mut &key[prefix.len()..]; let hash = match Decode::decode(raw_hash) { Ok(hash) => hash, - Err(_) => return Err(error::Error::Backend("Error decoding hash".into())), + Err(_) => return Err(Error::Backend("Error decoding hash".into())), }; let number = match Decode::decode(&mut &value[..]) { Ok(number) => number, - Err(_) => return Err(error::Error::Backend("Error decoding number".into())), + Err(_) => return Err(Error::Backend("Error decoding number".into())), }; storage.entry(Reverse(number)).or_insert_with(Vec::new).push(hash); } @@ -158,12 +158,35 @@ impl LeafSet where 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.insert_leaf(Reverse(number.clone() - N::one()), parent_hash); - self.remove_leaf(&Reverse(number), &hash); + /// Revert to the given block height by dropping all leaves in the leaf set + /// with a block number higher than the target. + pub fn revert(&mut self, best_hash: H, best_number: N) { + let items = self.storage.iter() + .flat_map(|(number, hashes)| hashes.iter().map(move |h| (h.clone(), number.clone()))) + .collect::>(); + + for (hash, number) in &items { + if number.0 > best_number { + assert!( + self.remove_leaf(number, hash), + "item comes from an iterator over storage; qed", + ); + + self.pending_removed.push(hash.clone()); + } + } + + let best_number = Reverse(best_number); + let leaves_contains_best = self.storage + .get(&best_number) + .map_or(false, |hashes| hashes.contains(&best_hash)); + + // we need to make sure that the best block exists in the leaf set as + // this is an invariant of regular block import. + if !leaves_contains_best { + self.insert_leaf(best_number.clone(), best_hash.clone()); + self.pending_added.push(LeafSetItem { hash: best_hash, number: best_number }); + } } /// returns an iterator over all hashes in the leaf set @@ -173,7 +196,7 @@ impl LeafSet where } /// Write the leaf list to the database transaction. - pub fn prepare_transaction(&mut self, tx: &mut DBTransaction, column: Option, prefix: &[u8]) { + pub fn prepare_transaction(&mut self, tx: &mut DBTransaction, column: u32, prefix: &[u8]) { let mut buf = prefix.to_vec(); for LeafSetItem { hash, number } in self.pending_added.drain(..) { hash.using_encoded(|s| buf.extend(s)); @@ -277,7 +300,7 @@ mod tests { #[test] fn flush_to_disk() { const PREFIX: &[u8] = b"abcdefg"; - let db = ::kvdb_memorydb::create(0); + let db = ::kvdb_memorydb::create(1); let mut set = LeafSet::new(); set.import(0u32, 0u32, 0u32); @@ -288,10 +311,10 @@ mod tests { let mut tx = DBTransaction::new(); - set.prepare_transaction(&mut tx, None, PREFIX); + set.prepare_transaction(&mut tx, 0, PREFIX); db.write(tx).unwrap(); - let set2 = LeafSet::read_from_db(&db, None, PREFIX).unwrap(); + let set2 = LeafSet::read_from_db(&db, 0, PREFIX).unwrap(); assert_eq!(set, set2); } @@ -311,7 +334,7 @@ mod tests { #[test] fn finalization_consistent_with_disk() { const PREFIX: &[u8] = b"prefix"; - let db = ::kvdb_memorydb::create(0); + let db = ::kvdb_memorydb::create(1); let mut set = LeafSet::new(); set.import(10_1u32, 10u32, 0u32); @@ -322,12 +345,12 @@ mod tests { assert!(set.contains(10, 10_1)); let mut tx = DBTransaction::new(); - set.prepare_transaction(&mut tx, None, PREFIX); + set.prepare_transaction(&mut tx, 0, PREFIX); db.write(tx).unwrap(); let _ = set.finalize_height(11); let mut tx = DBTransaction::new(); - set.prepare_transaction(&mut tx, None, PREFIX); + set.prepare_transaction(&mut tx, 0, PREFIX); db.write(tx).unwrap(); assert!(set.contains(11, 11_1)); @@ -335,7 +358,7 @@ mod tests { assert!(set.contains(12, 12_1)); assert!(!set.contains(10, 10_1)); - let set2 = LeafSet::read_from_db(&db, None, PREFIX).unwrap(); + let set2 = LeafSet::read_from_db(&db, 0, PREFIX).unwrap(); assert_eq!(set, set2); } diff --git a/client/src/lib.rs b/client/src/lib.rs new file mode 100644 index 0000000000000..cfaf08ca7ef6e --- /dev/null +++ b/client/src/lib.rs @@ -0,0 +1,106 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate Client and associated logic. +//! +//! The [`Client`] is one of the most important components of Substrate. It mainly comprises two +//! parts: +//! +//! - A database containing the blocks and chain state, generally referred to as +//! the [`Backend`](backend::Backend). +//! - A runtime environment, generally referred to as the [`Executor`](CallExecutor). +//! +//! # Initialization +//! +//! Creating a [`Client`] is done by calling the `new` method and passing to it a +//! [`Backend`](backend::Backend) and an [`Executor`](CallExecutor). +//! +//! The former is typically provided by the `sc-client-db` crate. +//! +//! The latter typically requires passing one of: +//! +//! - A [`LocalCallExecutor`] running the runtime locally. +//! - A [`RemoteCallExecutor`](light::call_executor::RemoteCallExecutor) that will ask a +//! third-party to perform the executions. +//! - A [`RemoteOrLocalCallExecutor`](light::call_executor::RemoteOrLocalCallExecutor), combination +//! of the two. +//! +//! Additionally, the fourth generic parameter of the `Client` is a marker type representing +//! the ways in which the runtime can interface with the outside. Any code that builds a `Client` +//! is responsible for putting the right marker. +//! +//! ## Example +//! +//! ``` +//! use std::sync::Arc; +//! use sc_client::{Client, in_mem::Backend, LocalCallExecutor}; +//! use sp_core::Blake2Hasher; +//! use sp_runtime::Storage; +//! use sc_executor::{NativeExecutor, WasmExecutionMethod}; +//! +//! // In this example, we're using the `Block` and `RuntimeApi` types from the +//! // `substrate-test-runtime-client` crate. These types are automatically generated when +//! // compiling a runtime. In a typical use-case, these types would have been to be generated +//! // from your runtime. +//! use substrate_test_runtime_client::{LocalExecutor, runtime::Block, runtime::RuntimeApi}; +//! +//! let backend = Arc::new(Backend::::new()); +//! let client = Client::<_, _, _, RuntimeApi>::new( +//! backend.clone(), +//! LocalCallExecutor::new( +//! backend.clone(), +//! NativeExecutor::::new(WasmExecutionMethod::Interpreted, None), +//! ), +//! // This parameter provides the storage for the chain genesis. +//! ::default(), +//! Default::default(), +//! Default::default(), +//! Default::default(), +//! ); +//! ``` +//! + +#![warn(missing_docs)] +#![recursion_limit="128"] + +pub mod cht; +pub mod in_mem; +pub mod genesis; +pub mod light; +pub mod leaves; +mod call_executor; +mod client; + +pub use sc_client_api::{ + blockchain, + blockchain::well_known_cache_keys, + blockchain::Info as ChainInfo, + notifications::{StorageEventStream, StorageChangeSet}, + call_executor::CallExecutor, + utils, +}; +pub use crate::{ + call_executor::LocalCallExecutor, + client::{ + new_with_backend, + new_in_mem, + BlockBody, ImportNotifications, FinalityNotifications, BlockchainEvents, + BlockImportNotification, Client, ClientInfo, ExecutionStrategies, FinalityNotification, + LongestChain, BlockOf, ProvideUncles, BadBlocks, ForkBlocks, apply_aux, + }, + leaves::LeafSet, +}; +pub use sp_state_machine::{ExecutionStrategy, StorageProof}; diff --git a/client/src/light/backend.rs b/client/src/light/backend.rs new file mode 100644 index 0000000000000..65fd94e32395c --- /dev/null +++ b/client/src/light/backend.rs @@ -0,0 +1,545 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Light client 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; +use parking_lot::RwLock; + +use sp_core::storage::{ChildInfo, OwnedChildInfo}; +use sp_core::offchain::storage::InMemOffchainStorage; +use sp_state_machine::{ + Backend as StateBackend, TrieBackend, InMemoryBackend, ChangesTrieTransaction +}; +use sp_runtime::{generic::BlockId, Justification, Storage}; +use sp_runtime::traits::{Block as BlockT, NumberFor, Zero, Header, HasherFor}; +use crate::in_mem::{self, check_genesis_storage}; +use sp_blockchain::{Error as ClientError, Result as ClientResult}; +use sc_client_api::{ + backend::{ + AuxStore, Backend as ClientBackend, BlockImportOperation, RemoteBackend, NewBlockState, + StorageCollection, ChildStorageCollection, + }, + blockchain::{ + HeaderBackend as BlockchainHeaderBackend, well_known_cache_keys, + }, + light::Storage as BlockchainStorage, + UsageInfo, +}; +use crate::light::blockchain::Blockchain; +use hash_db::Hasher; + +const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always succeeds; qed"; + +/// Light client backend. +pub struct Backend { + blockchain: Arc>, + genesis_state: RwLock>>, + import_lock: RwLock<()>, +} + +/// Light block (header and justification) import operation. +pub struct ImportOperation { + header: Option, + cache: HashMap>, + leaf_state: NewBlockState, + aux_ops: Vec<(Vec, Option>)>, + finalized_blocks: Vec>, + set_head: Option>, + storage_update: Option>>, + _phantom: std::marker::PhantomData, +} + +/// Either in-memory genesis state, or locally-unavailable state. +pub enum GenesisOrUnavailableState { + /// Genesis state - storage values are stored in-memory. + Genesis(InMemoryBackend), + /// We know that state exists, but all calls will fail with error, because it + /// isn't locally available. + Unavailable, +} + +impl Backend { + /// Create new light backend. + pub fn new(blockchain: Arc>) -> Self { + Self { + blockchain, + genesis_state: RwLock::new(None), + import_lock: Default::default(), + } + } + + /// Get shared blockchain reference. + pub fn blockchain(&self) -> &Arc> { + &self.blockchain + } +} + +impl AuxStore for Backend { + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> ClientResult<()> { + self.blockchain.storage().insert_aux(insert, delete) + } + + fn get_aux(&self, key: &[u8]) -> ClientResult>> { + self.blockchain.storage().get_aux(key) + } +} + +impl ClientBackend for Backend> + where + Block: BlockT, + S: BlockchainStorage, + Block::Hash: Ord, +{ + type BlockImportOperation = ImportOperation; + type Blockchain = Blockchain; + type State = GenesisOrUnavailableState>; + type ChangesTrieStorage = in_mem::ChangesTrieStorage; + type OffchainStorage = InMemOffchainStorage; + + fn begin_operation(&self) -> ClientResult { + Ok(ImportOperation { + header: None, + cache: Default::default(), + leaf_state: NewBlockState::Normal, + aux_ops: Vec::new(), + finalized_blocks: Vec::new(), + set_head: None, + storage_update: None, + _phantom: Default::default(), + }) + } + + 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.cache, + 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<()> { + self.blockchain.storage().finalize_header(block) + } + + fn blockchain(&self) -> &Blockchain { + &self.blockchain + } + + fn usage_info(&self) -> Option { + self.blockchain.storage().usage_info() + } + + fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage> { + None + } + + fn offchain_storage(&self) -> Option { + None + } + + fn state_at(&self, block: BlockId) -> ClientResult { + 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(GenesisOrUnavailableState::Genesis(genesis_state)); + } + } + + // else return unavailable state. We do not return error here, because error + // would mean that we do not know this state at all. But we know that it exists + Ok(GenesisOrUnavailableState::Unavailable) + } + + fn revert( + &self, + _n: NumberFor, + _revert_finalized: bool, + ) -> ClientResult> { + Err(ClientError::NotAvailableOnLightClient) + } + + fn get_import_lock(&self) -> &RwLock<()> { + &self.import_lock + } +} + +impl RemoteBackend for Backend> +where + Block: BlockT, + S: BlockchainStorage + 'static, + Block::Hash: 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) + } + + fn remote_blockchain(&self) -> Arc> { + self.blockchain.clone() + } +} + +impl BlockImportOperation for ImportOperation + where + Block: BlockT, + S: BlockchainStorage, + Block::Hash: Ord, +{ + type State = GenesisOrUnavailableState>; + + fn state(&self) -> ClientResult> { + // None means 'locally-stateless' backend + Ok(None) + } + + fn set_block_data( + &mut self, + header: Block::Header, + _body: Option>, + _justification: Option, + state: NewBlockState, + ) -> ClientResult<()> { + self.leaf_state = state; + self.header = Some(header); + Ok(()) + } + + fn update_cache(&mut self, cache: HashMap>) { + self.cache = cache; + } + + fn update_db_storage( + &mut self, + _update: >>::Transaction, + ) -> ClientResult<()> { + // we're not storing anything locally => ignore changes + Ok(()) + } + + fn update_changes_trie( + &mut self, + _update: ChangesTrieTransaction, NumberFor>, + ) -> ClientResult<()> { + // we're not storing anything locally => ignore changes + Ok(()) + } + + fn reset_storage(&mut self, input: Storage) -> ClientResult { + check_genesis_storage(&input)?; + + // this is only called when genesis block is imported => shouldn't be performance bottleneck + let mut storage: HashMap, OwnedChildInfo)>, _> = HashMap::new(); + storage.insert(None, input.top); + + // create a list of children keys to re-compute roots for + let child_delta = input.children.iter() + .map(|(storage_key, storage_child)| (storage_key.clone(), None, storage_child.child_info.clone())) + .collect::>(); + + // make sure to persist the child storage + for (child_key, storage_child) in input.children { + storage.insert(Some((child_key, storage_child.child_info)), storage_child.data); + } + + let storage_update = InMemoryBackend::from(storage); + let (storage_root, _) = storage_update.full_storage_root(std::iter::empty(), child_delta); + self.storage_update = Some(storage_update); + + Ok(storage_root) + } + + fn insert_aux(&mut self, ops: I) -> ClientResult<()> + where I: IntoIterator, Option>)> + { + self.aux_ops.append(&mut ops.into_iter().collect()); + Ok(()) + } + + fn update_storage( + &mut self, + _update: StorageCollection, + _child_update: ChildStorageCollection, + ) -> 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(()) + } +} + +impl std::fmt::Debug for GenesisOrUnavailableState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => state.fmt(f), + GenesisOrUnavailableState::Unavailable => write!(f, "Unavailable"), + } + } +} + +impl StateBackend for GenesisOrUnavailableState + where + H::Out: Ord + codec::Codec, +{ + type Error = ClientError; + type Transaction = as StateBackend>::Transaction; + type TrieBackendStorage = as StateBackend>::TrieBackendStorage; + + fn storage(&self, key: &[u8]) -> ClientResult>> { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => + Ok(state.storage(key).expect(IN_MEMORY_EXPECT_PROOF)), + GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), + } + } + + fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> ClientResult>> { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => + Ok(state.child_storage(storage_key, child_info, key).expect(IN_MEMORY_EXPECT_PROOF)), + GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), + } + } + + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => + Ok(state.next_storage_key(key).expect(IN_MEMORY_EXPECT_PROOF)), + GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), + } + } + + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => Ok( + state.next_child_storage_key(storage_key, child_info, key) + .expect(IN_MEMORY_EXPECT_PROOF) + ), + GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), + } + } + + fn for_keys_with_prefix(&self, prefix: &[u8], action: A) { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => state.for_keys_with_prefix(prefix, action), + GenesisOrUnavailableState::Unavailable => (), + } + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], action: A) { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => state.for_key_values_with_prefix(prefix, action), + GenesisOrUnavailableState::Unavailable => (), + } + } + + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + action: A, + ) { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => + state.for_keys_in_child_storage(storage_key, child_info, action), + GenesisOrUnavailableState::Unavailable => (), + } + } + + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + action: A, + ) { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => + state.for_child_keys_with_prefix(storage_key, child_info, prefix, action), + GenesisOrUnavailableState::Unavailable => (), + } + } + + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where + I: IntoIterator, Option>)> + { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => + state.storage_root(delta), + GenesisOrUnavailableState::Unavailable => Default::default(), + } + } + + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (H::Out, bool, Self::Transaction) + where + I: IntoIterator, Option>)> + { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => { + let (root, is_equal, _) = state.child_storage_root(storage_key, child_info, delta); + (root, is_equal, Default::default()) + }, + GenesisOrUnavailableState::Unavailable => + (H::Out::default(), true, Default::default()), + } + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => state.pairs(), + GenesisOrUnavailableState::Unavailable => Vec::new(), + } + } + + fn keys(&self, prefix: &[u8]) -> Vec> { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => state.keys(prefix), + GenesisOrUnavailableState::Unavailable => Vec::new(), + } + } + + fn as_trie_backend(&mut self) -> Option<&TrieBackend> { + match self { + GenesisOrUnavailableState::Genesis(ref mut state) => state.as_trie_backend(), + GenesisOrUnavailableState::Unavailable => None, + } + } +} + +#[cfg(test)] +mod tests { + use sp_core::Blake2Hasher; + use substrate_test_runtime_client::{self, runtime::Block}; + use sc_client_api::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 = substrate_test_runtime_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()).unwrap(); + backend.commit_operation(op).unwrap(); + + match backend.state_at(BlockId::Number(0)).unwrap() { + GenesisOrUnavailableState::Genesis(_) => (), + _ => panic!("unexpected state"), + } + } + + #[test] + fn unavailable_state_is_created_when_genesis_state_is_unavailable() { + let backend: Backend<_, Blake2Hasher> = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); + + match backend.state_at(BlockId::Number(0)).unwrap() { + GenesisOrUnavailableState::Unavailable => (), + _ => panic!("unexpected state"), + } + } + + #[test] + fn light_aux_store_is_updated_via_non_importing_op() { + let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); + let mut op = ClientBackend::::begin_operation(&backend).unwrap(); + BlockImportOperation::::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap(); + ClientBackend::::commit_operation(&backend, op).unwrap(); + + assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2])); + } +} diff --git a/client/src/light/blockchain.rs b/client/src/light/blockchain.rs new file mode 100644 index 0000000000000..756147c941b39 --- /dev/null +++ b/client/src/light/blockchain.rs @@ -0,0 +1,326 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Light client blockchain backend. Only stores headers and justifications of recent +//! blocks. CHT roots are stored for headers of ancient blocks. + +use std::future::Future; +use std::sync::Arc; + +use sp_runtime::{Justification, generic::BlockId}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; + +use sp_blockchain::{ + HeaderMetadata, CachedHeaderMetadata, + Error as ClientError, Result as ClientResult, +}; +pub use sc_client_api::{ + backend::{ + AuxStore, NewBlockState + }, + blockchain::{ + Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache, + HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo, ProvideCache, + well_known_cache_keys, + }, + light::{ + RemoteBlockchain, LocalOrRemote, Storage + } +}; +use crate::cht; +use crate::light::fetcher::{Fetcher, RemoteHeaderRequest}; + +/// Light client blockchain. +pub struct Blockchain { + storage: S, +} + +impl Blockchain { + /// Create new light blockchain backed with given storage. + pub fn new(storage: S) -> Self { + Self { + storage, + } + } + + /// Get storage reference. + pub fn storage(&self) -> &S { + &self.storage + } +} + +impl BlockchainHeaderBackend for Blockchain where Block: BlockT, S: Storage { + fn header(&self, id: BlockId) -> ClientResult> { + match RemoteBlockchain::header(self, id)? { + LocalOrRemote::Local(header) => Ok(Some(header)), + LocalOrRemote::Remote(_) => Err(ClientError::NotAvailableOnLightClient), + LocalOrRemote::Unknown => Ok(None), + } + } + + fn info(&self) -> BlockchainInfo { + self.storage.info() + } + + fn status(&self, id: BlockId) -> ClientResult { + self.storage.status(id) + } + + fn number(&self, hash: Block::Hash) -> ClientResult>> { + self.storage.number(hash) + } + + fn hash(&self, number: <::Header as HeaderT>::Number) -> ClientResult> { + self.storage.hash(number) + } +} + +impl HeaderMetadata for Blockchain where Block: BlockT, S: Storage { + type Error = ClientError; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.storage.header_metadata(hash) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.storage.insert_header_metadata(hash, metadata) + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.storage.remove_header_metadata(hash) + } +} + +impl BlockchainBackend for Blockchain where Block: BlockT, S: Storage { + fn body(&self, _id: BlockId) -> ClientResult>> { + Err(ClientError::NotAvailableOnLightClient) + } + + fn justification(&self, _id: BlockId) -> ClientResult> { + Err(ClientError::NotAvailableOnLightClient) + } + + fn last_finalized(&self) -> ClientResult { + self.storage.last_finalized() + } + + fn cache(&self) -> Option>> { + self.storage.cache() + } + + fn leaves(&self) -> ClientResult> { + Err(ClientError::NotAvailableOnLightClient) + } + + fn children(&self, _parent_hash: Block::Hash) -> ClientResult> { + Err(ClientError::NotAvailableOnLightClient) + } +} + +impl, Block: BlockT> ProvideCache for Blockchain { + fn cache(&self) -> Option>> { + self.storage.cache() + } +} + +impl RemoteBlockchain for Blockchain + where + S: Storage, +{ + fn header(&self, id: BlockId) -> ClientResult, + >> { + // first, try to read header from local storage + if let Some(local_header) = self.storage.header(id)? { + return Ok(LocalOrRemote::Local(local_header)); + } + + // we need to know block number to check if it's a part of CHT + let number = match id { + BlockId::Hash(hash) => match self.storage.number(hash)? { + Some(number) => number, + None => return Ok(LocalOrRemote::Unknown), + }, + BlockId::Number(number) => number, + }; + + // if the header is genesis (never pruned), non-canonical, or from future => return + if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown { + return Ok(LocalOrRemote::Unknown); + } + + Ok(LocalOrRemote::Remote(RemoteHeaderRequest { + cht_root: match self.storage.header_cht_root(cht::size(), number)? { + Some(cht_root) => cht_root, + None => return Ok(LocalOrRemote::Unknown), + }, + block: number, + retry_count: None, + })) + } +} + +/// Returns future that resolves header either locally, or remotely. +pub fn future_header>( + blockchain: &dyn RemoteBlockchain, + fetcher: &F, + id: BlockId, +) -> impl Future, ClientError>> { + use futures::future::{ready, Either, FutureExt}; + + match blockchain.header(id) { + Ok(LocalOrRemote::Remote(request)) => Either::Left( + fetcher + .remote_header(request) + .then(|header| ready(header.map(Some))) + ), + Ok(LocalOrRemote::Unknown) => Either::Right(ready(Ok(None))), + Ok(LocalOrRemote::Local(local_header)) => Either::Right(ready(Ok(Some(local_header)))), + Err(err) => Either::Right(ready(Err(err))), + } +} + +#[cfg(test)] +pub mod tests { + use std::collections::HashMap; + use parking_lot::Mutex; + use substrate_test_runtime_client::runtime::{Hash, Block, Header}; + use sc_client_api::blockchain::Info; + use super::*; + + pub type DummyBlockchain = Blockchain; + + pub struct DummyStorage { + pub changes_tries_cht_roots: HashMap, + pub aux_store: Mutex, Vec>>, + } + + impl DummyStorage { + pub fn new() -> Self { + DummyStorage { + changes_tries_cht_roots: HashMap::new(), + aux_store: Mutex::new(HashMap::new()), + } + } + } + + impl BlockchainHeaderBackend for DummyStorage { + fn header(&self, _id: BlockId) -> ClientResult> { + Err(ClientError::Backend("Test error".into())) + } + + fn info(&self) -> Info { + panic!("Test error") + } + + fn status(&self, _id: BlockId) -> ClientResult { + Err(ClientError::Backend("Test error".into())) + } + + fn number(&self, hash: Hash) -> ClientResult>> { + if hash == Default::default() { + Ok(Some(Default::default())) + } else { + Err(ClientError::Backend("Test error".into())) + } + } + + fn hash(&self, number: u64) -> ClientResult> { + if number == 0 { + Ok(Some(Default::default())) + } else { + Err(ClientError::Backend("Test error".into())) + } + } + } + + impl HeaderMetadata for DummyStorage { + type Error = ClientError; + + fn header_metadata(&self, hash: Hash) -> Result, Self::Error> { + self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header)) + .ok_or(ClientError::UnknownBlock("header not found".to_owned())) + } + fn insert_header_metadata(&self, _hash: Hash, _metadata: CachedHeaderMetadata) {} + fn remove_header_metadata(&self, _hash: Hash) {} + } + + impl AuxStore for DummyStorage { + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, _delete: D) -> ClientResult<()> { + for (k, v) in insert.into_iter() { + self.aux_store.lock().insert(k.to_vec(), v.to_vec()); + } + Ok(()) + } + + fn get_aux(&self, key: &[u8]) -> ClientResult>> { + Ok(self.aux_store.lock().get(key).cloned()) + } + } + + impl Storage for DummyStorage { + fn import_header( + &self, + _header: Header, + _cache: HashMap>, + _state: NewBlockState, + _aux_ops: Vec<(Vec, Option>)>, + ) -> ClientResult<()> { + Ok(()) + } + + fn set_head(&self, _block: BlockId) -> ClientResult<()> { + Err(ClientError::Backend("Test error".into())) + } + + fn finalize_header(&self, _block: BlockId) -> ClientResult<()> { + Err(ClientError::Backend("Test error".into())) + } + + fn last_finalized(&self) -> ClientResult { + Err(ClientError::Backend("Test error".into())) + } + + fn header_cht_root(&self, _cht_size: u64, _block: u64) -> ClientResult> { + Err(ClientError::Backend("Test error".into())) + } + + fn changes_trie_cht_root(&self, cht_size: u64, block: u64) -> ClientResult> { + cht::block_to_cht_number(cht_size, block) + .and_then(|cht_num| self.changes_tries_cht_roots.get(&cht_num)) + .cloned() + .ok_or_else(|| ClientError::Backend( + format!("Test error: CHT for block #{} not found", block) + ).into()) + .map(Some) + } + + fn cache(&self) -> Option>> { + None + } + + fn usage_info(&self) -> Option { + None + } + } +} diff --git a/client/src/light/call_executor.rs b/client/src/light/call_executor.rs new file mode 100644 index 0000000000000..45d9bf303c0cb --- /dev/null +++ b/client/src/light/call_executor.rs @@ -0,0 +1,501 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Methods that light client could use to execute runtime calls. + +use std::{ + sync::Arc, panic::UnwindSafe, result, cell::RefCell, +}; + +use codec::{Encode, Decode}; +use sp_core::{convert_hash, NativeOrEncoded, traits::CodeExecutor}; +use sp_runtime::{ + generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, HasherFor}, +}; +use sp_externalities::Extensions; +use sp_state_machine::{ + self, Backend as StateBackend, OverlayedChanges, ExecutionStrategy, create_proof_check_backend, + execution_proof_check_on_trie_backend, ExecutionManager, StorageProof, + merge_storage_proofs, +}; +use hash_db::Hasher; + +use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache}; + +use sp_blockchain::{Error as ClientError, Result as ClientResult}; + +use sc_client_api::{ + backend::RemoteBackend, + light::RemoteCallRequest, + call_executor::CallExecutor +}; +use sc_executor::{RuntimeVersion, NativeVersion}; + +/// Call executor that is able to execute calls only on genesis state. +/// +/// Trying to execute call on non-genesis state leads to error. +pub struct GenesisCallExecutor { + backend: Arc, + local: L, +} + +impl GenesisCallExecutor { + /// Create new genesis call executor. + pub fn new(backend: Arc, local: L) -> Self { + Self { backend, local } + } +} + +impl Clone for GenesisCallExecutor { + fn clone(&self) -> Self { + GenesisCallExecutor { + backend: self.backend.clone(), + local: self.local.clone(), + } + } +} + +impl CallExecutor for + GenesisCallExecutor + where + Block: BlockT, + B: RemoteBackend, + Local: CallExecutor, +{ + type Error = ClientError; + + type Backend = B; + + fn call( + &self, + id: &BlockId, + method: &str, + call_data: &[u8], + strategy: ExecutionStrategy, + extensions: Option, + ) -> ClientResult> { + match self.backend.is_local_state_available(id) { + true => self.local.call(id, method, call_data, strategy, extensions), + false => Err(ClientError::NotAvailableOnLightClient), + } + } + + fn contextual_call< + 'a, + IB: Fn() -> ClientResult<()>, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >( + &self, + initialize_block_fn: IB, + at: &BlockId, + method: &str, + call_data: &[u8], + changes: &RefCell, + _: Option<&RefCell>>, + initialize_block: InitializeBlock<'a, Block>, + _manager: ExecutionManager, + native_call: Option, + recorder: &Option>, + extensions: 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, + initialize_block_fn, + at, + method, + call_data, + changes, + None, + initialize_block, + ExecutionManager::NativeWhenPossible, + native_call, + recorder, + extensions, + ).map_err(|e| ClientError::Execution(Box::new(e.to_string()))), + false => Err(ClientError::NotAvailableOnLightClient), + } + } + + fn runtime_version(&self, id: &BlockId) -> ClientResult { + match self.backend.is_local_state_available(id) { + true => self.local.runtime_version(id), + false => Err(ClientError::NotAvailableOnLightClient), + } + } + + fn prove_at_trie_state>>( + &self, + _state: &sp_state_machine::TrieBackend>, + _changes: &mut OverlayedChanges, + _method: &str, + _call_data: &[u8], + ) -> ClientResult<(Vec, StorageProof)> { + Err(ClientError::NotAvailableOnLightClient) + } + + 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. +/// Proof includes both environment preparation proof and method execution proof. +pub fn prove_execution( + mut state: S, + header: Block::Header, + executor: &E, + method: &str, + call_data: &[u8], +) -> ClientResult<(Vec, StorageProof)> + where + Block: BlockT, + S: StateBackend>, + E: CallExecutor, +{ + let trie_state = state.as_trie_backend() + .ok_or_else(|| + Box::new(sp_state_machine::ExecutionError::UnableToGenerateProof) as + Box + )?; + + // prepare execution environment + record preparation proof + let mut changes = Default::default(); + let (_, init_proof) = executor.prove_at_trie_state( + trie_state, + &mut changes, + "Core_initialize_block", + &header.encode(), + )?; + + // execute method + record execution proof + let (result, exec_proof) = executor.prove_at_trie_state( + &trie_state, + &mut changes, + method, + call_data, + )?; + let total_proof = merge_storage_proofs(vec![init_proof, exec_proof]); + + Ok((result, total_proof)) +} + +/// Check remote contextual execution proof using given backend. +/// +/// Method is executed using passed header as environment' current block. +/// Proof should include both environment preparation proof and method execution proof. +pub fn check_execution_proof( + executor: &E, + request: &RemoteCallRequest

, + remote_proof: StorageProof, +) -> ClientResult> + where + Header: HeaderT, + E: CodeExecutor, + H: Hasher, + H::Out: Ord + codec::Codec + 'static, +{ + check_execution_proof_with_make_header::( + executor, + request, + remote_proof, + |header|
::new( + *header.number() + One::one(), + Default::default(), + Default::default(), + header.hash(), + Default::default(), + ), + ) +} + +fn check_execution_proof_with_make_header Header>( + executor: &E, + request: &RemoteCallRequest
, + remote_proof: StorageProof, + make_next_header: MakeNextHeader, +) -> ClientResult> + where + Header: HeaderT, + E: CodeExecutor, + H: Hasher, + H::Out: Ord + codec::Codec + 'static, +{ + let local_state_root = request.header.state_root(); + let root: H::Out = convert_hash(&local_state_root); + + // prepare execution environment + check preparation proof + let mut changes = OverlayedChanges::default(); + let trie_backend = create_proof_check_backend(root, remote_proof)?; + let next_header = make_next_header(&request.header); + execution_proof_check_on_trie_backend::( + &trie_backend, + &mut changes, + executor, + "Core_initialize_block", + &next_header.encode(), + )?; + + // execute method + execution_proof_check_on_trie_backend::( + &trie_backend, + &mut changes, + executor, + &request.method, + &request.call_data, + ).map_err(Into::into) +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_consensus::BlockOrigin; + use substrate_test_runtime_client::{ + runtime::{Header, Digest, Block}, TestClient, ClientBlockImportExt, + }; + use sc_executor::{NativeExecutor, WasmExecutionMethod}; + use sp_core::{Blake2Hasher, H256}; + use sc_client_api::backend::{Backend, NewBlockState}; + use crate::in_mem::Backend as InMemBackend; + + struct DummyCallExecutor; + + impl CallExecutor for DummyCallExecutor { + type Error = ClientError; + + type Backend = substrate_test_runtime_client::Backend; + + fn call( + &self, + _id: &BlockId, + _method: &str, + _call_data: &[u8], + _strategy: ExecutionStrategy, + _extensions: Option, + ) -> Result, ClientError> { + Ok(vec![42]) + } + + fn contextual_call< + 'a, + IB: Fn() -> ClientResult<()>, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >( + &self, + _initialize_block_fn: IB, + _at: &BlockId, + _method: &str, + _call_data: &[u8], + _changes: &RefCell, + _storage_transaction_cache: Option<&RefCell< + StorageTransactionCache< + Block, + >::State, + > + >>, + _initialize_block: InitializeBlock<'a, Block>, + _execution_manager: ExecutionManager, + _native_call: Option, + _proof_recorder: &Option>, + _extensions: Option, + ) -> ClientResult> where ExecutionManager: Clone { + unreachable!() + } + + fn runtime_version(&self, _id: &BlockId) -> Result { + unreachable!() + } + + fn prove_at_trie_state>>( + &self, + _trie_state: &sp_state_machine::TrieBackend>, + _overlay: &mut OverlayedChanges, + _method: &str, + _call_data: &[u8] + ) -> Result<(Vec, StorageProof), ClientError> { + unreachable!() + } + + fn native_runtime_version(&self) -> Option<&NativeVersion> { + unreachable!() + } + } + + fn local_executor() -> NativeExecutor { + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + } + + #[test] + fn execution_proof_is_generated_and_checked() { + fn execute(remote_client: &TestClient, at: u64, method: &'static str) -> (Vec, Vec) { + let remote_block_id = BlockId::Number(at); + let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap(); + + // 'fetch' execution proof from remote node + let (remote_result, remote_execution_proof) = remote_client.execution_proof( + &remote_block_id, + method, + &[] + ).unwrap(); + + // check remote execution proof locally + let local_result = check_execution_proof::<_, _, Blake2Hasher>( + &local_executor(), + &RemoteCallRequest { + block: substrate_test_runtime_client::runtime::Hash::default(), + header: remote_header, + method: method.into(), + call_data: vec![], + retry_count: None, + }, + remote_execution_proof, + ).unwrap(); + + (remote_result, local_result) + } + + fn execute_with_proof_failure(remote_client: &TestClient, at: u64, method: &'static str) { + let remote_block_id = BlockId::Number(at); + let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap(); + + // 'fetch' execution proof from remote node + let (_, remote_execution_proof) = remote_client.execution_proof( + &remote_block_id, + method, + &[] + ).unwrap(); + + // check remote execution proof locally + let execution_result = check_execution_proof_with_make_header::<_, _, Blake2Hasher, _>( + &local_executor(), + &RemoteCallRequest { + block: substrate_test_runtime_client::runtime::Hash::default(), + header: remote_header, + method: method.into(), + call_data: vec![], + retry_count: None, + }, + remote_execution_proof, + |header|
::new( + at + 1, + Default::default(), + Default::default(), + header.hash(), + header.digest().clone(), // this makes next header wrong + ), + ); + match execution_result { + Err(sp_blockchain::Error::Execution(_)) => (), + _ => panic!("Unexpected execution result: {:?}", execution_result), + } + } + + // prepare remote client + let mut remote_client = substrate_test_runtime_client::new(); + for i in 1u32..3u32 { + let mut digest = Digest::default(); + digest.push(sp_runtime::generic::DigestItem::Other::(i.to_le_bytes().to_vec())); + remote_client.import_justified( + BlockOrigin::Own, + remote_client.new_block(digest).unwrap().build().unwrap().block, + Default::default(), + ).unwrap(); + } + + // check method that doesn't requires environment + let (remote, local) = execute(&remote_client, 0, "Core_version"); + assert_eq!(remote, local); + + let (remote, local) = execute(&remote_client, 2, "Core_version"); + assert_eq!(remote, local); + + // check method that requires environment + let (_, block) = execute(&remote_client, 0, "BlockBuilder_finalize_block"); + let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); + assert_eq!(local_block.number, 1); + + let (_, block) = execute(&remote_client, 2, "BlockBuilder_finalize_block"); + let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); + assert_eq!(local_block.number, 3); + + // check that proof check doesn't panic even if proof is incorrect AND no panic handler is set + execute_with_proof_failure(&remote_client, 2, "Core_version"); + + // check that proof check doesn't panic even if proof is incorrect AND panic handler is set + sp_panic_handler::set("TEST", "1.2.3"); + execute_with_proof_failure(&remote_client, 2, "Core_version"); + } + + #[test] + fn code_is_executed_at_genesis_only() { + let backend = Arc::new(InMemBackend::::new()); + let def = H256::default(); + let header0 = substrate_test_runtime_client::runtime::Header::new(0, def, def, def, Default::default()); + let hash0 = header0.hash(); + let header1 = substrate_test_runtime_client::runtime::Header::new(1, def, def, hash0, Default::default()); + let hash1 = header1.hash(); + backend.blockchain().insert(hash0, header0, None, None, NewBlockState::Final).unwrap(); + backend.blockchain().insert(hash1, header1, None, None, NewBlockState::Final).unwrap(); + + let genesis_executor = GenesisCallExecutor::new(backend, DummyCallExecutor); + assert_eq!( + genesis_executor.call( + &BlockId::Number(0), + "test_method", + &[], + ExecutionStrategy::NativeElseWasm, + None, + ).unwrap(), + vec![42], + ); + + let call_on_unavailable = genesis_executor.call( + &BlockId::Number(1), + "test_method", + &[], + ExecutionStrategy::NativeElseWasm, + None, + ); + + match call_on_unavailable { + Err(ClientError::NotAvailableOnLightClient) => (), + _ => unreachable!("unexpected result: {:?}", call_on_unavailable), + } + } +} diff --git a/client/src/light/fetcher.rs b/client/src/light/fetcher.rs new file mode 100644 index 0000000000000..d746b3abe5549 --- /dev/null +++ b/client/src/light/fetcher.rs @@ -0,0 +1,794 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Light client data fetcher. Fetches requested data from remote full nodes. + +use std::sync::Arc; +use std::collections::{BTreeMap, HashMap}; +use std::marker::PhantomData; + +use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; +use codec::{Decode, Encode}; +use sp_core::{convert_hash, traits::CodeExecutor}; +use sp_runtime::traits::{ + Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor, + SimpleArithmetic, CheckedConversion, Zero, +}; +use sp_state_machine::{ + ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, + TrieBackend, read_proof_check, key_changes_proof_check, create_proof_check_backend_storage, + read_child_proof_check, +}; +pub use sp_state_machine::StorageProof; +use sp_blockchain::{Error as ClientError, Result as ClientResult}; + +use crate::cht; +pub use sc_client_api::{ + light::{ + RemoteCallRequest, RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest, + RemoteChangesRequest, ChangesProof, RemoteBodyRequest, Fetcher, FetchChecker, + Storage as BlockchainStorage, + }, +}; +use crate::light::blockchain::{Blockchain}; +use crate::light::call_executor::check_execution_proof; + +/// Remote data checker. +pub struct LightDataChecker> { + blockchain: Arc>, + executor: E, + _hasher: PhantomData<(B, H)>, +} + +impl> LightDataChecker { + /// Create new light data checker. + pub fn new(blockchain: Arc>, executor: E) -> Self { + Self { + blockchain, executor, _hasher: PhantomData + } + } + + /// Check remote changes query proof assuming that CHT-s are of given size. + fn check_changes_proof_with_cht_size( + &self, + request: &RemoteChangesRequest, + remote_proof: ChangesProof, + cht_size: NumberFor, + ) -> ClientResult, u32)>> + where + H: Hasher, + H::Out: Ord + codec::Codec, + { + // since we need roots of all changes tries for the range begin..max + // => remote node can't use max block greater that one that we have passed + if remote_proof.max_block > request.max_block.0 || remote_proof.max_block < request.last_block.0 { + return Err(ClientError::ChangesTrieAccessFailed(format!( + "Invalid max_block used by the remote node: {}. Local: {}..{}..{}", + remote_proof.max_block, request.first_block.0, request.last_block.0, request.max_block.0, + )).into()); + } + + // check if remote node has responded with extra changes trie roots proofs + // all changes tries roots must be in range [request.first_block.0; request.tries_roots.0) + let is_extra_first_root = remote_proof.roots.keys().next() + .map(|first_root| *first_root < request.first_block.0 + || *first_root >= request.tries_roots.0) + .unwrap_or(false); + let is_extra_last_root = remote_proof.roots.keys().next_back() + .map(|last_root| *last_root >= request.tries_roots.0) + .unwrap_or(false); + if is_extra_first_root || is_extra_last_root { + return Err(ClientError::ChangesTrieAccessFailed(format!( + "Extra changes tries roots proofs provided by the remote node: [{:?}..{:?}]. Expected in range: [{}; {})", + remote_proof.roots.keys().next(), remote_proof.roots.keys().next_back(), + request.first_block.0, request.tries_roots.0, + )).into()); + } + + // if request has been composed when some required headers were already pruned + // => remote node has sent us CHT-based proof of required changes tries roots + // => check that this proof is correct before proceeding with changes proof + let remote_max_block = remote_proof.max_block; + let remote_roots = remote_proof.roots; + let remote_roots_proof = remote_proof.roots_proof; + let remote_proof = remote_proof.proof; + if !remote_roots.is_empty() { + self.check_changes_tries_proof( + cht_size, + &remote_roots, + remote_roots_proof, + )?; + } + + // FIXME: remove this in https://github.com/paritytech/substrate/pull/3201 + let changes_trie_config_range = ChangesTrieConfigurationRange { + config: &request.changes_trie_config, + zero: Zero::zero(), + end: None, + }; + + // and now check the key changes proof + get the changes + key_changes_proof_check::( + changes_trie_config_range, + &RootsStorage { + roots: (request.tries_roots.0, &request.tries_roots.2), + prev_roots: remote_roots, + }, + remote_proof, + request.first_block.0, + &ChangesTrieAnchorBlockId { + hash: convert_hash(&request.last_block.1), + number: request.last_block.0, + }, + remote_max_block, + request.storage_key.as_ref().map(Vec::as_slice), + &request.key) + .map_err(|err| ClientError::ChangesTrieAccessFailed(err)) + } + + /// Check CHT-based proof for changes tries roots. + fn check_changes_tries_proof( + &self, + cht_size: NumberFor, + remote_roots: &BTreeMap, B::Hash>, + remote_roots_proof: StorageProof, + ) -> ClientResult<()> + where + H: Hasher, + H::Out: Ord + codec::Codec, + { + // all the checks are sharing the same storage + let storage = create_proof_check_backend_storage(remote_roots_proof); + + // remote_roots.keys() are sorted => we can use this to group changes tries roots + // that are belongs to the same CHT + let blocks = remote_roots.keys().cloned(); + cht::for_each_cht_group::(cht_size, blocks, |mut storage, _, cht_blocks| { + // get local changes trie CHT root for given CHT + // it should be there, because it is never pruned AND request has been composed + // when required header has been pruned (=> replaced with CHT) + let first_block = cht_blocks.first().cloned() + .expect("for_each_cht_group never calls callback with empty groups"); + let local_cht_root = self.blockchain.storage().changes_trie_cht_root(cht_size, first_block)? + .ok_or(ClientError::InvalidCHTProof)?; + + // check changes trie root for every block within CHT range + for block in cht_blocks { + // check if the proofs storage contains the root + // normally this happens in when the proving backend is created, but since + // we share the storage for multiple checks, do it here + let mut cht_root = H::Out::default(); + cht_root.as_mut().copy_from_slice(local_cht_root.as_ref()); + if !storage.contains(&cht_root, EMPTY_PREFIX) { + return Err(ClientError::InvalidCHTProof.into()); + } + + // check proof for single changes trie root + let proving_backend = TrieBackend::new(storage, cht_root); + let remote_changes_trie_root = remote_roots[&block]; + cht::check_proof_on_proving_backend::( + local_cht_root, + block, + remote_changes_trie_root, + &proving_backend)?; + + // and return the storage to use in following checks + storage = proving_backend.into_storage(); + } + + Ok(storage) + }, storage) + } +} + +impl FetchChecker for LightDataChecker + where + Block: BlockT, + E: CodeExecutor, + H: Hasher, + H::Out: Ord + codec::Codec + 'static, + S: BlockchainStorage, +{ + fn check_header_proof( + &self, + request: &RemoteHeaderRequest, + remote_header: Option, + remote_proof: StorageProof, + ) -> ClientResult { + let remote_header = remote_header.ok_or_else(|| + ClientError::from(ClientError::InvalidCHTProof))?; + let remote_header_hash = remote_header.hash(); + cht::check_proof::( + request.cht_root, + request.block, + remote_header_hash, + remote_proof, + ).map(|_| remote_header) + } + + fn check_read_proof( + &self, + request: &RemoteReadRequest, + remote_proof: StorageProof, + ) -> ClientResult, Option>>> { + read_proof_check::( + convert_hash(request.header.state_root()), + remote_proof, + request.keys.iter(), + ).map_err(Into::into) + } + + fn check_read_child_proof( + &self, + request: &RemoteReadChildRequest, + remote_proof: StorageProof, + ) -> ClientResult, Option>>> { + read_child_proof_check::( + convert_hash(request.header.state_root()), + remote_proof, + &request.storage_key, + request.keys.iter(), + ).map_err(Into::into) + } + + fn check_execution_proof( + &self, + request: &RemoteCallRequest, + remote_proof: StorageProof, + ) -> ClientResult> { + check_execution_proof::<_, _, H>(&self.executor, request, remote_proof) + } + + fn check_changes_proof( + &self, + request: &RemoteChangesRequest, + remote_proof: ChangesProof + ) -> ClientResult, u32)>> { + self.check_changes_proof_with_cht_size(request, remote_proof, cht::size()) + } + + fn check_body_proof( + &self, + request: &RemoteBodyRequest, + body: Vec + ) -> ClientResult> { + // TODO: #2621 + let extrinsics_root = HashFor::::ordered_trie_root( + body.iter().map(Encode::encode).collect(), + ); + if *request.header.extrinsics_root() == extrinsics_root { + Ok(body) + } else { + Err(format!("RemoteBodyRequest: invalid extrinsics root expected: {} but got {}", + *request.header.extrinsics_root(), + extrinsics_root, + ).into()) + } + + } +} + +/// A view of BTreeMap as a changes trie roots storage. +struct RootsStorage<'a, Number: SimpleArithmetic, Hash: 'a> { + roots: (Number, &'a [Hash]), + prev_roots: BTreeMap, +} + +impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a, Number, Hash> + where + H: Hasher, + Number: ::std::fmt::Display + ::std::hash::Hash + Clone + SimpleArithmetic + Encode + Decode + Send + Sync + 'static, + Hash: 'a + Send + Sync + Clone + AsRef<[u8]>, +{ + fn build_anchor( + &self, + _hash: H::Out, + ) -> Result, String> { + Err("build_anchor is only called when building block".into()) + } + + fn root( + &self, + _anchor: &ChangesTrieAnchorBlockId, + block: Number, + ) -> Result, String> { + // we can't ask for roots from parallel forks here => ignore anchor + let root = if block < self.roots.0 { + self.prev_roots.get(&Number::unique_saturated_from(block)).cloned() + } else { + let index: Option = block.checked_sub(&self.roots.0).and_then(|index| index.checked_into()); + match index { + Some(index) => self.roots.1.get(index as usize).cloned(), + None => None, + } + }; + + Ok(root.map(|root| { + let mut hasher_root: H::Out = Default::default(); + hasher_root.as_mut().copy_from_slice(root.as_ref()); + hasher_root + })) + } +} + +#[cfg(test)] +pub mod tests { + use codec::Decode; + use crate::client::tests::prepare_client_with_key_changes; + use sc_executor::{NativeExecutor, WasmExecutionMethod}; + use sp_blockchain::Error as ClientError; + use sc_client_api::backend::NewBlockState; + use substrate_test_runtime_client::{ + blockchain::HeaderBackend, AccountKeyring, ClientBlockImportExt, + runtime::{self, Hash, Block, Header, Extrinsic} + }; + use sp_consensus::BlockOrigin; + + use crate::in_mem::{Blockchain as InMemoryBlockchain}; + use crate::light::fetcher::{FetchChecker, LightDataChecker, RemoteHeaderRequest}; + use crate::light::blockchain::tests::{DummyStorage, DummyBlockchain}; + use sp_core::{blake2_256, Blake2Hasher, H256}; + use sp_core::storage::{well_known_keys, StorageKey, ChildInfo}; + use sp_runtime::generic::BlockId; + use sp_state_machine::Backend; + use super::*; + + const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1"); + + type TestChecker = LightDataChecker< + NativeExecutor, + Blake2Hasher, + Block, + DummyStorage, + >; + + fn local_executor() -> NativeExecutor { + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + } + + fn prepare_for_read_proof_check() -> (TestChecker, Header, StorageProof, u32) { + // prepare remote client + let remote_client = substrate_test_runtime_client::new(); + let remote_block_id = BlockId::Number(0); + let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); + let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); + remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap() + .storage_root(::std::iter::empty()).0.into(); + + // 'fetch' read proof from remote node + let heap_pages = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::HEAP_PAGES.to_vec())) + .unwrap() + .and_then(|v| Decode::decode(&mut &v.0[..]).ok()).unwrap(); + let remote_read_proof = remote_client.read_proof( + &remote_block_id, + &[well_known_keys::HEAP_PAGES], + ).unwrap(); + + // check remote read proof locally + let local_storage = InMemoryBlockchain::::new(); + local_storage.insert( + remote_block_hash, + remote_block_header.clone(), + None, + None, + NewBlockState::Final, + ).unwrap(); + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor() + ); + (local_checker, remote_block_header, remote_read_proof, heap_pages) + } + + fn prepare_for_read_child_proof_check() -> (TestChecker, Header, StorageProof, Vec) { + use substrate_test_runtime_client::DefaultTestClientBuilderExt; + use substrate_test_runtime_client::TestClientBuilderExt; + // prepare remote client + let remote_client = substrate_test_runtime_client::TestClientBuilder::new() + .add_extra_child_storage( + b":child_storage:default:child1".to_vec(), + CHILD_INFO_1, + b"key1".to_vec(), + b"value1".to_vec(), + ).build(); + let remote_block_id = BlockId::Number(0); + let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); + let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); + remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap() + .storage_root(::std::iter::empty()).0.into(); + + // 'fetch' child read proof from remote node + let child_value = remote_client.child_storage( + &remote_block_id, + &StorageKey(b":child_storage:default:child1".to_vec()), + CHILD_INFO_1, + &StorageKey(b"key1".to_vec()), + ).unwrap().unwrap().0; + assert_eq!(b"value1"[..], child_value[..]); + let remote_read_proof = remote_client.read_child_proof( + &remote_block_id, + b":child_storage:default:child1", + CHILD_INFO_1, + &[b"key1"], + ).unwrap(); + + // check locally + let local_storage = InMemoryBlockchain::::new(); + local_storage.insert( + remote_block_hash, + remote_block_header.clone(), + None, + None, + NewBlockState::Final, + ).unwrap(); + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); + (local_checker, remote_block_header, remote_read_proof, child_value) + } + + fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, StorageProof) { + // prepare remote client + let mut remote_client = substrate_test_runtime_client::new(); + let mut local_headers_hashes = Vec::new(); + for i in 0..4 { + let block = remote_client.new_block(Default::default()).unwrap().build().unwrap().block; + remote_client.import(BlockOrigin::Own, block).unwrap(); + local_headers_hashes.push( + remote_client.block_hash(i + 1) + .map_err(|_| ClientError::Backend("TestError".into())) + ); + } + + // 'fetch' header proof from remote node + let remote_block_id = BlockId::Number(1); + let (remote_block_header, remote_header_proof) = remote_client.header_proof_with_cht_size(&remote_block_id, 4).unwrap(); + + // check remote read proof locally + let local_storage = InMemoryBlockchain::::new(); + let local_cht_root = cht::compute_root::(4, 0, local_headers_hashes).unwrap(); + if insert_cht { + local_storage.insert_cht_root(1, local_cht_root); + } + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); + (local_checker, local_cht_root, remote_block_header, remote_header_proof) + } + + fn header_with_computed_extrinsics_root(extrinsics: Vec) -> Header { + use sp_trie::{TrieConfiguration, trie_types::Layout}; + let iter = extrinsics.iter().map(Encode::encode); + let extrinsics_root = Layout::::ordered_trie_root(iter); + + // only care about `extrinsics_root` + Header::new(0, extrinsics_root, H256::zero(), H256::zero(), Default::default()) + } + + #[test] + fn storage_read_proof_is_generated_and_checked() { + let (local_checker, remote_block_header, remote_read_proof, heap_pages) = prepare_for_read_proof_check(); + assert_eq!((&local_checker as &dyn FetchChecker).check_read_proof(&RemoteReadRequest::
{ + block: remote_block_header.hash(), + header: remote_block_header, + keys: vec![well_known_keys::HEAP_PAGES.to_vec()], + retry_count: None, + }, remote_read_proof).unwrap().remove(well_known_keys::HEAP_PAGES).unwrap().unwrap()[0], heap_pages as u8); + } + + #[test] + fn storage_child_read_proof_is_generated_and_checked() { + let ( + local_checker, + remote_block_header, + remote_read_proof, + result, + ) = prepare_for_read_child_proof_check(); + let child_infos = CHILD_INFO_1.info(); + assert_eq!((&local_checker as &dyn FetchChecker).check_read_child_proof( + &RemoteReadChildRequest::
{ + block: remote_block_header.hash(), + header: remote_block_header, + storage_key: b":child_storage:default:child1".to_vec(), + child_info: child_infos.0.to_vec(), + child_type: child_infos.1, + keys: vec![b"key1".to_vec()], + retry_count: None, + }, + remote_read_proof + ).unwrap().remove(b"key1".as_ref()).unwrap().unwrap(), result); + } + + #[test] + fn header_proof_is_generated_and_checked() { + let (local_checker, local_cht_root, remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); + assert_eq!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ + cht_root: local_cht_root, + block: 1, + retry_count: None, + }, Some(remote_block_header.clone()), remote_header_proof).unwrap(), remote_block_header); + } + + #[test] + fn check_header_proof_fails_if_cht_root_is_invalid() { + let (local_checker, _, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); + remote_block_header.number = 100; + assert!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ + cht_root: Default::default(), + block: 1, + retry_count: None, + }, Some(remote_block_header.clone()), remote_header_proof).is_err()); + } + + #[test] + fn check_header_proof_fails_if_invalid_header_provided() { + let (local_checker, local_cht_root, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); + remote_block_header.number = 100; + assert!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ + cht_root: local_cht_root, + block: 1, + retry_count: None, + }, Some(remote_block_header.clone()), remote_header_proof).is_err()); + } + + #[test] + fn changes_proof_is_generated_and_checked_when_headers_are_not_pruned() { + let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); + let local_checker = &local_checker as &dyn FetchChecker; + let max = remote_client.chain_info().best_number; + let max_hash = remote_client.chain_info().best_hash; + + for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { + let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); + let end_hash = remote_client.block_hash(end).unwrap().unwrap(); + + // 'fetch' changes proof from remote node + let key = StorageKey(key); + let remote_proof = remote_client.key_changes_proof( + begin_hash, end_hash, begin_hash, max_hash, None, &key + ).unwrap(); + + // check proof on local client + let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); + let request = RemoteChangesRequest::
{ + changes_trie_config: runtime::changes_trie_config(), + first_block: (begin, begin_hash), + last_block: (end, end_hash), + max_block: (max, max_hash), + tries_roots: (begin, begin_hash, local_roots_range), + key: key.0, + storage_key: None, + retry_count: None, + }; + let local_result = local_checker.check_changes_proof(&request, ChangesProof { + max_block: remote_proof.max_block, + proof: remote_proof.proof, + roots: remote_proof.roots, + roots_proof: remote_proof.roots_proof, + }).unwrap(); + + // ..and ensure that result is the same as on remote node + match local_result == expected_result { + true => (), + false => panic!(format!("Failed test {}: local = {:?}, expected = {:?}", + index, local_result, expected_result)), + } + } + } + + #[test] + fn changes_proof_is_generated_and_checked_when_headers_are_pruned() { + // we're testing this test case here: + // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), + let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); + let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let dave = StorageKey(dave); + + // 'fetch' changes proof from remote node: + // we're fetching changes for range b1..b4 + // we do not know changes trie roots before b3 (i.e. we only know b3+b4) + // but we have changes trie CHT root for b1...b4 + let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); + let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap(); + let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap(); + let remote_proof = remote_client.key_changes_proof_with_cht_size( + b1, b4, b3, b4, None, &dave, 4 + ).unwrap(); + + // prepare local checker, having a root of changes trie CHT#0 + let local_cht_root = cht::compute_root::(4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); + let mut local_storage = DummyStorage::new(); + local_storage.changes_tries_cht_roots.insert(0, local_cht_root); + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(local_storage)), + local_executor(), + ); + + // check proof on local client + let request = RemoteChangesRequest::
{ + changes_trie_config: runtime::changes_trie_config(), + first_block: (1, b1), + last_block: (4, b4), + max_block: (4, b4), + tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]), + storage_key: None, + key: dave.0, + retry_count: None, + }; + let local_result = local_checker.check_changes_proof_with_cht_size(&request, ChangesProof { + max_block: remote_proof.max_block, + proof: remote_proof.proof, + roots: remote_proof.roots, + roots_proof: remote_proof.roots_proof, + }, 4).unwrap(); + + assert_eq!(local_result, vec![(4, 0), (1, 1), (1, 0)]); + } + + #[test] + fn check_changes_proof_fails_if_proof_is_wrong() { + let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); + let local_checker = &local_checker as &dyn FetchChecker; + let max = remote_client.chain_info().best_number; + let max_hash = remote_client.chain_info().best_hash; + + let (begin, end, key, _) = test_cases[0].clone(); + let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); + let end_hash = remote_client.block_hash(end).unwrap().unwrap(); + + // 'fetch' changes proof from remote node + let key = StorageKey(key); + let remote_proof = remote_client.key_changes_proof( + begin_hash, end_hash, begin_hash, max_hash, None, &key).unwrap(); + + let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); + let request = RemoteChangesRequest::
{ + changes_trie_config: runtime::changes_trie_config(), + first_block: (begin, begin_hash), + last_block: (end, end_hash), + max_block: (max, max_hash), + tries_roots: (begin, begin_hash, local_roots_range.clone()), + storage_key: None, + key: key.0, + retry_count: None, + }; + + // check proof on local client using max from the future + assert!(local_checker.check_changes_proof(&request, ChangesProof { + max_block: remote_proof.max_block + 1, + proof: remote_proof.proof.clone(), + roots: remote_proof.roots.clone(), + roots_proof: remote_proof.roots_proof.clone(), + }).is_err()); + + // check proof on local client using broken proof + assert!(local_checker.check_changes_proof(&request, ChangesProof { + max_block: remote_proof.max_block, + proof: local_roots_range.clone().into_iter().map(|v| v.as_ref().to_vec()).collect(), + roots: remote_proof.roots, + roots_proof: remote_proof.roots_proof, + }).is_err()); + + // extra roots proofs are provided + assert!(local_checker.check_changes_proof(&request, ChangesProof { + max_block: remote_proof.max_block, + proof: remote_proof.proof.clone(), + roots: vec![(begin - 1, Default::default())].into_iter().collect(), + roots_proof: StorageProof::empty(), + }).is_err()); + assert!(local_checker.check_changes_proof(&request, ChangesProof { + max_block: remote_proof.max_block, + proof: remote_proof.proof.clone(), + roots: vec![(end + 1, Default::default())].into_iter().collect(), + roots_proof: StorageProof::empty(), + }).is_err()); + } + + #[test] + fn check_changes_tries_proof_fails_if_proof_is_wrong() { + // we're testing this test case here: + // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), + let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); + let local_cht_root = cht::compute_root::( + 4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); + let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let dave = StorageKey(dave); + + // 'fetch' changes proof from remote node: + // we're fetching changes for range b1..b4 + // we do not know changes trie roots before b3 (i.e. we only know b3+b4) + // but we have changes trie CHT root for b1...b4 + let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); + let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap(); + let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap(); + let remote_proof = remote_client.key_changes_proof_with_cht_size( + b1, b4, b3, b4, None, &dave, 4 + ).unwrap(); + + // fails when changes trie CHT is missing from the local db + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); + assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, + remote_proof.roots_proof.clone()).is_err()); + + // fails when proof is broken + let mut local_storage = DummyStorage::new(); + local_storage.changes_tries_cht_roots.insert(0, local_cht_root); + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(local_storage)), + local_executor(), + ); + let result = local_checker.check_changes_tries_proof( + 4, &remote_proof.roots, StorageProof::empty() + ); + assert!(result.is_err()); + } + + #[test] + fn check_body_proof_faulty() { + let header = header_with_computed_extrinsics_root( + vec![Extrinsic::IncludeData(vec![1, 2, 3, 4])] + ); + let block = Block::new(header.clone(), Vec::new()); + + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); + + let body_request = RemoteBodyRequest { + header: header.clone(), + retry_count: None, + }; + + assert!( + local_checker.check_body_proof(&body_request, block.extrinsics).is_err(), + "vec![1, 2, 3, 4] != vec![]" + ); + } + + #[test] + fn check_body_proof_of_same_data_should_succeed() { + let extrinsics = vec![Extrinsic::IncludeData(vec![1, 2, 3, 4, 5, 6, 7, 8, 255])]; + + let header = header_with_computed_extrinsics_root(extrinsics.clone()); + let block = Block::new(header.clone(), extrinsics); + + let local_checker = TestChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); + + let body_request = RemoteBodyRequest { + header: header.clone(), + retry_count: None, + }; + + assert!(local_checker.check_body_proof(&body_request, block.extrinsics).is_ok()); + } +} diff --git a/client/src/light/mod.rs b/client/src/light/mod.rs new file mode 100644 index 0000000000000..5052b36d7f3e1 --- /dev/null +++ b/client/src/light/mod.rs @@ -0,0 +1,99 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Light client components. + +pub mod backend; +pub mod blockchain; +pub mod call_executor; +pub mod fetcher; + +use std::sync::Arc; + +use sc_executor::RuntimeInfo; +use sp_core::traits::CodeExecutor; +use sp_runtime::BuildStorage; +use sp_runtime::traits::{Block as BlockT, HasherFor}; +use sp_blockchain::Result as ClientResult; + +use crate::call_executor::LocalCallExecutor; +use crate::client::Client; +use sc_client_api::{ + light::Storage as BlockchainStorage, +}; +use crate::light::backend::Backend; +use crate::light::blockchain::Blockchain; +use crate::light::call_executor::GenesisCallExecutor; +use crate::light::fetcher::LightDataChecker; + +/// Create an instance of light client blockchain backend. +pub fn new_light_blockchain>(storage: S) -> Arc> { + Arc::new(Blockchain::new(storage)) +} + +/// Create an instance of light client backend. +pub fn new_light_backend(blockchain: Arc>) -> Arc>> + where + B: BlockT, + S: BlockchainStorage, +{ + Arc::new(Backend::new(blockchain)) +} + +/// Create an instance of light client. +pub fn new_light( + backend: Arc>>, + genesis_storage: GS, + code_executor: E, +) -> ClientResult< + Client< + Backend>, + GenesisCallExecutor< + Backend>, + LocalCallExecutor>, E> + >, + B, + RA + > + > + where + B: BlockT, + S: BlockchainStorage + 'static, + GS: BuildStorage, + E: CodeExecutor + RuntimeInfo, +{ + let local_executor = LocalCallExecutor::new(backend.clone(), code_executor); + let executor = GenesisCallExecutor::new(backend.clone(), local_executor); + Client::new( + backend, + executor, + genesis_storage, + Default::default(), + Default::default(), + Default::default(), + ) +} + +/// Create an instance of fetch data checker. +pub fn new_fetch_checker>( + blockchain: Arc>, + executor: E, +) -> LightDataChecker, B, S> + where + E: CodeExecutor, +{ + LightDataChecker::new(blockchain, executor) +} diff --git a/client/state-db/Cargo.toml b/client/state-db/Cargo.toml new file mode 100644 index 0000000000000..31335d752ea67 --- /dev/null +++ b/client/state-db/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "sc-state-db" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +parking_lot = "0.9.0" +log = "0.4.8" +sp-core = { version = "2.0.0", path = "../../primitives/core" } +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } + +[dev-dependencies] +env_logger = "0.7.0" diff --git a/client/state-db/src/lib.rs b/client/state-db/src/lib.rs new file mode 100644 index 0000000000000..f2722ae308068 --- /dev/null +++ b/client/state-db/src/lib.rs @@ -0,0 +1,610 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! State database maintenance. Handles canonicalization and pruning in the database. The input to +//! this module is a `ChangeSet` which is basically a list of key-value pairs (trie nodes) that +//! were added or deleted during block execution. +//! +//! # Canonicalization. +//! Canonicalization window tracks a tree of blocks identified by header hash. The in-memory +//! overlay allows to get any node that was inserted in any of the blocks within the window. +//! The tree is journaled to the backing database and rebuilt on startup. +//! Canonicalization function selects one root from the top of the tree and discards all other roots and +//! their subtrees. +//! +//! # Pruning. +//! See `RefWindow` for pruning algorithm details. `StateDb` prunes on each canonicalization until pruning +//! constraints are satisfied. + +mod noncanonical; +mod pruning; +#[cfg(test)] mod test; + +use std::fmt; +use parking_lot::RwLock; +use codec::Codec; +use std::collections::{HashMap, hash_map::Entry}; +use noncanonical::NonCanonicalOverlay; +use pruning::RefWindow; +use log::trace; + +const PRUNING_MODE: &[u8] = b"mode"; +const PRUNING_MODE_ARCHIVE: &[u8] = b"archive"; +const PRUNING_MODE_ARCHIVE_CANON: &[u8] = b"archive_canonical"; +const PRUNING_MODE_CONSTRAINED: &[u8] = b"constrained"; + +/// Database value type. +pub type DBValue = Vec; + +/// Basic set of requirements for the Block hash and node key types. +pub trait Hash: Send + Sync + Sized + Eq + PartialEq + Clone + Default + fmt::Debug + Codec + std::hash::Hash + 'static {} +impl Hash for T {} + +/// Backend database trait. Read-only. +pub trait MetaDb { + type Error: fmt::Debug; + + /// Get meta value, such as the journal. + fn get_meta(&self, key: &[u8]) -> Result, Self::Error>; +} + +/// Backend database trait. Read-only. +pub trait NodeDb { + type Key: ?Sized; + type Error: fmt::Debug; + + /// Get state trie node. + fn get(&self, key: &Self::Key) -> Result, Self::Error>; +} + +/// Error type. +pub enum Error { + /// Database backend error. + Db(E), + /// `Codec` decoding error. + Decoding(codec::Error), + /// Trying to canonicalize invalid block. + InvalidBlock, + /// Trying to insert block with invalid number. + InvalidBlockNumber, + /// Trying to insert block with unknown parent. + InvalidParent, + /// Invalid pruning mode specified. Contains expected mode. + InvalidPruningMode(String), +} + +/// Pinning error type. +pub enum PinError { + /// Trying to pin invalid block. + InvalidBlock, +} + +impl From for Error { + fn from(x: codec::Error) -> Self { + Error::Decoding(x) + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::Db(e) => e.fmt(f), + Error::Decoding(e) => write!(f, "Error decoding slicable value: {}", e.what()), + Error::InvalidBlock => write!(f, "Trying to canonicalize invalid block"), + Error::InvalidBlockNumber => write!(f, "Trying to insert block with invalid number"), + Error::InvalidParent => write!(f, "Trying to insert block with unknown parent"), + Error::InvalidPruningMode(e) => write!(f, "Expected pruning mode: {}", e), + } + } +} + +/// A set of state node changes. +#[derive(Default, Debug, Clone)] +pub struct ChangeSet { + /// Inserted nodes. + pub inserted: Vec<(H, DBValue)>, + /// Deleted nodes. + pub deleted: Vec, +} + + +/// A set of changes to the backing database. +#[derive(Default, Debug, Clone)] +pub struct CommitSet { + /// State node changes. + pub data: ChangeSet, + /// Metadata changes. + pub meta: ChangeSet>, +} + +/// Pruning constraints. If none are specified pruning is +#[derive(Default, Debug, Clone, Eq, PartialEq)] +pub struct Constraints { + /// Maximum blocks. Defaults to 0 when unspecified, effectively keeping only non-canonical states. + pub max_blocks: Option, + /// Maximum memory in the pruning overlay. + pub max_mem: Option, +} + +/// Pruning mode. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum PruningMode { + /// Maintain a pruning window. + Constrained(Constraints), + /// No pruning. Canonicalization is a no-op. + ArchiveAll, + /// Canonicalization discards non-canonical nodes. All the canonical nodes are kept in the DB. + ArchiveCanonical, +} + +impl PruningMode { + /// Create a mode that keeps given number of blocks. + pub fn keep_blocks(n: u32) -> PruningMode { + PruningMode::Constrained(Constraints { + max_blocks: Some(n), + max_mem: None, + }) + } + + /// Is this an archive (either ArchiveAll or ArchiveCanonical) pruning mode? + pub fn is_archive(&self) -> bool { + match *self { + PruningMode::ArchiveAll | PruningMode::ArchiveCanonical => true, + PruningMode::Constrained(_) => false + } + } + + /// Is this an archive (either ArchiveAll or ArchiveCanonical) pruning mode? + pub fn id(&self) -> &[u8] { + match self { + PruningMode::ArchiveAll => PRUNING_MODE_ARCHIVE, + PruningMode::ArchiveCanonical => PRUNING_MODE_ARCHIVE_CANON, + PruningMode::Constrained(_) => PRUNING_MODE_CONSTRAINED, + } + } +} + +impl Default for PruningMode { + fn default() -> Self { + PruningMode::keep_blocks(256) + } +} + +fn to_meta_key(suffix: &[u8], data: &S) -> Vec { + let mut buffer = data.encode(); + buffer.extend(suffix); + buffer +} + +struct StateDbSync { + mode: PruningMode, + non_canonical: NonCanonicalOverlay, + pruning: Option>, + pinned: HashMap, +} + +impl StateDbSync { + pub fn new(mode: PruningMode, db: &D) -> Result, Error> { + trace!(target: "state-db", "StateDb settings: {:?}", mode); + + // Check that settings match + Self::check_meta(&mode, db)?; + + let non_canonical: NonCanonicalOverlay = NonCanonicalOverlay::new(db)?; + let pruning: Option> = match mode { + PruningMode::Constrained(Constraints { + max_mem: Some(_), + .. + }) => unimplemented!(), + PruningMode::Constrained(_) => Some(RefWindow::new(db)?), + PruningMode::ArchiveAll | PruningMode::ArchiveCanonical => None, + }; + + Ok(StateDbSync { + mode, + non_canonical, + pruning, + pinned: Default::default(), + }) + } + + fn check_meta(mode: &PruningMode, db: &D) -> Result<(), Error> { + let db_mode = db.get_meta(&to_meta_key(PRUNING_MODE, &())).map_err(Error::Db)?; + trace!(target: "state-db", + "DB pruning mode: {:?}", + db_mode.as_ref().map(|v| std::str::from_utf8(&v)) + ); + match &db_mode { + Some(v) if v.as_slice() == mode.id() => Ok(()), + Some(v) => Err(Error::InvalidPruningMode(String::from_utf8_lossy(v).into())), + None => Ok(()), + } + } + + pub fn insert_block(&mut self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, mut changeset: ChangeSet) -> Result, Error> { + let mut meta = ChangeSet::default(); + if number == 0 { + // Save pruning mode when writing first block. + meta.inserted.push((to_meta_key(PRUNING_MODE, &()), self.mode.id().into())); + } + + match self.mode { + PruningMode::ArchiveAll => { + changeset.deleted.clear(); + // write changes immediately + Ok(CommitSet { + data: changeset, + meta: meta, + }) + }, + PruningMode::Constrained(_) | PruningMode::ArchiveCanonical => { + let commit = self.non_canonical.insert(hash, number, parent_hash, changeset); + commit.map(|mut c| { + c.meta.inserted.extend(meta.inserted); + c + }) + } + } + } + + pub fn canonicalize_block(&mut self, hash: &BlockHash) -> Result, Error> { + let mut commit = CommitSet::default(); + if self.mode == PruningMode::ArchiveAll { + return Ok(commit) + } + match self.non_canonical.canonicalize(&hash, &mut commit) { + Ok(()) => { + if self.mode == PruningMode::ArchiveCanonical { + commit.data.deleted.clear(); + } + } + Err(e) => return Err(e), + }; + if let Some(ref mut pruning) = self.pruning { + pruning.note_canonical(&hash, &mut commit); + } + self.prune(&mut commit); + Ok(commit) + } + + pub fn best_canonical(&self) -> Option { + return self.non_canonical.last_canonicalized_block_number() + } + + 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) { + if let (&mut Some(ref mut pruning), &PruningMode::Constrained(ref constraints)) = (&mut self.pruning, &self.mode) { + loop { + if pruning.window_size() <= constraints.max_blocks.unwrap_or(0) as u64 { + break; + } + + if constraints.max_mem.map_or(false, |m| pruning.mem_used() > m) { + break; + } + + let pinned = &self.pinned; + if pruning.next_hash().map_or(false, |h| pinned.contains_key(&h)) { + break; + } + pruning.prune_one(commit); + } + } + } + + /// Revert all non-canonical blocks with the best block number. + /// Returns a database commit or `None` if not possible. + /// For archive an empty commit set is returned. + pub fn revert_one(&mut self) -> Option> { + match self.mode { + PruningMode::ArchiveAll => { + Some(CommitSet::default()) + }, + PruningMode::ArchiveCanonical | PruningMode::Constrained(_) => { + self.non_canonical.revert_one() + }, + } + } + + pub fn pin(&mut self, hash: &BlockHash) -> Result<(), PinError> { + match self.mode { + PruningMode::ArchiveAll => Ok(()), + PruningMode::ArchiveCanonical | PruningMode::Constrained(_) => { + if self.non_canonical.have_block(hash) || + self.pruning.as_ref().map_or(false, |pruning| pruning.have_block(hash)) + { + let refs = self.pinned.entry(hash.clone()).or_default(); + if *refs == 0 { + trace!(target: "state-db", "Pinned block: {:?}", hash); + self.non_canonical.pin(hash); + } + *refs += 1; + Ok(()) + } else { + Err(PinError::InvalidBlock) + } + } + } + } + + pub fn unpin(&mut self, hash: &BlockHash) { + match self.pinned.entry(hash.clone()) { + Entry::Occupied(mut entry) => { + *entry.get_mut() -= 1; + if *entry.get() == 0 { + trace!(target: "state-db", "Unpinned block: {:?}", hash); + entry.remove(); + self.non_canonical.unpin(hash); + } else { + trace!(target: "state-db", "Releasing reference for {:?}", hash); + } + }, + Entry::Vacant(_) => {}, + } + } + + pub fn get(&self, key: &Key, db: &D) -> Result, Error> + where Key: AsRef + { + if let Some(value) = self.non_canonical.get(key) { + return Ok(Some(value)); + } + db.get(key.as_ref()).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. +/// Can be shared across threads. +pub struct StateDb { + db: RwLock>, +} + +impl StateDb { + /// Creates a new instance. Does not expect any metadata in the database. + pub fn new(mode: PruningMode, db: &D) -> Result, Error> { + Ok(StateDb { + db: RwLock::new(StateDbSync::new(mode, db)?) + }) + } + + /// Add a new non-canonical block. + pub fn insert_block(&self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, changeset: ChangeSet) -> Result, Error> { + self.db.write().insert_block(hash, number, parent_hash, changeset) + } + + /// Finalize a previously inserted block. + pub fn canonicalize_block(&self, hash: &BlockHash) -> Result, Error> { + self.db.write().canonicalize_block(hash) + } + + /// Prevents pruning of specified block and its descendants. + pub fn pin(&self, hash: &BlockHash) -> Result<(), PinError> { + self.db.write().pin(hash) + } + + /// Allows pruning of specified block. + pub fn unpin(&self, hash: &BlockHash) { + self.db.write().unpin(hash) + } + + /// Get a value from non-canonical/pruning overlay or the backing DB. + pub fn get(&self, key: &Key, db: &D) -> Result, Error> + where Key: AsRef + { + self.db.read().get(key, db) + } + + /// Revert all non-canonical blocks with the best block number. + /// Returns a database commit or `None` if not possible. + /// For archive an empty commit set is returned. + pub fn revert_one(&self) -> Option> { + self.db.write().revert_one() + } + + /// Returns last finalized block number. + pub fn best_canonical(&self) -> Option { + return self.db.read().best_canonical() + } + + /// Check if block is pruned away. + 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(); + } +} + +#[cfg(test)] +mod tests { + use std::io; + use sp_core::H256; + 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]); + let state_db = StateDb::new(settings, &db).unwrap(); + + db.commit( + &state_db + .insert_block::( + &H256::from_low_u64_be(1), + 1, + &H256::from_low_u64_be(0), + make_changeset(&[1], &[91]), + ) + .unwrap(), + ); + db.commit( + &state_db + .insert_block::( + &H256::from_low_u64_be(21), + 2, + &H256::from_low_u64_be(1), + make_changeset(&[21], &[921, 1]), + ) + .unwrap(), + ); + db.commit( + &state_db + .insert_block::( + &H256::from_low_u64_be(22), + 2, + &H256::from_low_u64_be(1), + make_changeset(&[22], &[922]), + ) + .unwrap(), + ); + db.commit( + &state_db + .insert_block::( + &H256::from_low_u64_be(3), + 3, + &H256::from_low_u64_be(21), + make_changeset(&[3], &[93]), + ) + .unwrap(), + ); + 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::( + &H256::from_low_u64_be(4), + 4, + &H256::from_low_u64_be(3), + make_changeset(&[4], &[94]), + ) + .unwrap(), + ); + 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, 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] + fn canonical_archive_keeps_canonical() { + let (db, _) = make_test_db(PruningMode::ArchiveCanonical); + assert!(db.data_eq(&make_db(&[1, 21, 3, 91, 921, 922, 93, 94]))); + } + + #[test] + fn prune_window_0() { + let (db, _) = make_test_db(PruningMode::Constrained(Constraints { + max_blocks: Some(0), + max_mem: None, + })); + assert!(db.data_eq(&make_db(&[21, 3, 922, 94]))); + } + + #[test] + fn prune_window_1() { + let (db, sdb) = make_test_db(PruningMode::Constrained(Constraints { + max_blocks: Some(1), + max_mem: None, + })); + 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]))); + } + + #[test] + fn prune_window_2() { + let (db, sdb) = make_test_db(PruningMode::Constrained(Constraints { + max_blocks: Some(2), + max_mem: None, + })); + 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]))); + } + + #[test] + fn detects_incompatible_mode() { + let mut db = make_db(&[]); + let state_db = StateDb::new(PruningMode::ArchiveAll, &db).unwrap(); + db.commit( + &state_db + .insert_block::( + &H256::from_low_u64_be(0), + 0, + &H256::from_low_u64_be(0), + make_changeset(&[], &[]), + ) + .unwrap(), + ); + let new_mode = PruningMode::Constrained(Constraints { max_blocks: Some(2), max_mem: None }); + let state_db: Result, _> = StateDb::new(new_mode, &db); + assert!(state_db.is_err()); + } +} diff --git a/core/state-db/src/noncanonical.rs b/client/state-db/src/noncanonical.rs similarity index 87% rename from core/state-db/src/noncanonical.rs rename to client/state-db/src/noncanonical.rs index 58715715ccdd2..373c1aa0da076 100644 --- a/core/state-db/src/noncanonical.rs +++ b/client/state-db/src/noncanonical.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -37,7 +37,9 @@ pub struct NonCanonicalOverlay { pending_canonicalizations: Vec, pending_insertions: Vec, values: HashMap, //ref counted - pinned: HashMap>, //would be deleted but kept around because block is pinned + //would be deleted but kept around because block is pinned, ref counted. + pinned: HashMap, + pinned_insertions: HashMap>, } #[derive(Encode, Decode)] @@ -68,21 +70,14 @@ fn insert_values(values: &mut HashMap, inserted: } } -fn discard_values( - values: &mut HashMap, - inserted: Vec, - mut into: Option<&mut HashMap>, -) { +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 { - let (key, (_, value)) = e.remove_entry(); - if let Some(ref mut into) = into { - into.insert(key, value); - } + e.remove_entry(); } }, Entry::Vacant(_) => { @@ -97,7 +92,8 @@ fn discard_descendants( mut values: &mut HashMap, index: usize, parents: &mut HashMap, - pinned: &mut HashMap>, + pinned: &HashMap, + pinned_insertions: &mut HashMap>, hash: &BlockHash, ) { let mut discarded = Vec::new(); @@ -105,9 +101,15 @@ fn discard_descendants( *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, pinned.get_mut(hash)); + discarded.push(overlay.hash.clone()); + if pinned.contains_key(&overlay.hash) { + // save to be discarded later. + pinned_insertions.insert(overlay.hash.clone(), overlay.inserted); + } else { + // discard immediatelly. + parents.remove(&overlay.hash); + discard_values(&mut values, overlay.inserted); + } None } else { Some(overlay) @@ -115,7 +117,7 @@ fn discard_descendants( }).collect(); } for hash in discarded { - discard_descendants(levels, values, index + 1, parents, pinned, &hash); + discard_descendants(levels, values, index + 1, parents, pinned, pinned_insertions, &hash); } } @@ -176,6 +178,7 @@ impl NonCanonicalOverlay { pending_canonicalizations: Default::default(), pending_insertions: Default::default(), pinned: Default::default(), + pinned_insertions: Default::default(), values: values, }) } @@ -339,18 +342,23 @@ impl NonCanonicalOverlay { // 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, - &mut self.pinned, + &self.pinned, + &mut self.pinned_insertions, &overlay.hash, ); } - discard_values(&mut self.values, overlay.inserted, self.pinned.get_mut(&overlay.hash)); + if self.pinned.contains_key(&overlay.hash) { + self.pinned_insertions.insert(overlay.hash.clone(), overlay.inserted); + } else { + self.parents.remove(&overlay.hash); + discard_values(&mut self.values, overlay.inserted); + } } } if let Some(hash) = last { @@ -364,11 +372,6 @@ impl NonCanonicalOverlay { if let Some((_, value)) = self.values.get(&key) { return Some(value.clone()); } - for pinned in self.pinned.values() { - if let Some(value) = pinned.get(&key) { - return Some(value.clone()); - } - } None } @@ -385,7 +388,7 @@ 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, None); + discard_values(&mut self.values, overlay.inserted); } commit }) @@ -402,7 +405,7 @@ impl NonCanonicalOverlay { .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, None); + 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(); @@ -424,19 +427,50 @@ impl NonCanonicalOverlay { /// Pin state values in memory pub fn pin(&mut self, hash: &BlockHash) { - self.pinned.insert(hash.clone(), HashMap::default()); + if self.pending_insertions.contains(hash) { + debug_assert!(false, "Trying to pin pending state"); + return; + } + // Also pin all parents + let mut parent = Some(hash); + while let Some(hash) = parent { + let refs = self.pinned.entry(hash.clone()).or_default(); + if *refs == 0 { + trace!(target: "state-db", "Pinned non-canon block: {:?}", hash); + } + *refs += 1; + parent = self.parents.get(hash); + } } /// Discard pinned state pub fn unpin(&mut self, hash: &BlockHash) { - self.pinned.remove(hash); + // Also unpin all parents + let mut parent = Some(hash.clone()); + while let Some(hash) = parent { + parent = self.parents.get(&hash).cloned(); + match self.pinned.entry(hash.clone()) { + Entry::Occupied(mut entry) => { + *entry.get_mut() -= 1; + if *entry.get() == 0 { + entry.remove(); + if let Some(inserted) = self.pinned_insertions.remove(&hash) { + trace!(target: "state-db", "Discarding unpinned non-canon block: {:?}", hash); + discard_values(&mut self.values, inserted); + self.parents.remove(&hash); + } + } + }, + Entry::Vacant(_) => {}, + } + } } } #[cfg(test)] mod tests { use std::io; - use primitives::H256; + use sp_core::H256; use super::{NonCanonicalOverlay, to_journal_key}; use crate::{ChangeSet, CommitSet}; use crate::test::{make_db, make_changeset}; @@ -801,7 +835,7 @@ mod tests { fn keeps_pinned() { let mut db = make_db(&[]); - // - 1 - 1_1 + // - 0 - 1_1 // \ 1_2 let (h_1, c_1) = (H256::random(), make_changeset(&[1], &[])); @@ -810,6 +844,7 @@ mod tests { 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()); + overlay.apply_pending(); overlay.pin(&h_1); @@ -821,4 +856,65 @@ mod tests { overlay.unpin(&h_1); assert!(!contains(&overlay, 1)); } + + #[test] + fn keeps_pinned_ref_count() { + let mut db = make_db(&[]); + + // - 0 - 1_1 + // \ 1_2 + // \ 1_3 + + // 1_1 and 1_2 both make the same change + let (h_1, c_1) = (H256::random(), make_changeset(&[1], &[])); + let (h_2, c_2) = (H256::random(), make_changeset(&[1], &[])); + let (h_3, c_3) = (H256::random(), make_changeset(&[], &[])); + + 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()); + db.commit(&overlay.insert::(&h_3, 1, &H256::default(), c_3).unwrap()); + overlay.apply_pending(); + + overlay.pin(&h_1); + + let mut commit = CommitSet::default(); + overlay.canonicalize::(&h_3, &mut commit).unwrap(); + db.commit(&commit); + overlay.apply_pending(); // 1_2 should be discarded, 1_1 is pinned + + assert!(contains(&overlay, 1)); + overlay.unpin(&h_1); + assert!(!contains(&overlay, 1)); + } + + #[test] + fn pin_keeps_parent() { + let mut db = make_db(&[]); + + // - 0 - 1_1 - 2_1 + // \ 1_2 + + let (h_11, c_11) = (H256::random(), make_changeset(&[1], &[])); + let (h_12, c_12) = (H256::random(), make_changeset(&[], &[])); + let (h_21, c_21) = (H256::random(), make_changeset(&[], &[])); + + let mut overlay = NonCanonicalOverlay::::new(&db).unwrap(); + db.commit(&overlay.insert::(&h_11, 1, &H256::default(), c_11).unwrap()); + db.commit(&overlay.insert::(&h_12, 1, &H256::default(), c_12).unwrap()); + db.commit(&overlay.insert::(&h_21, 2, &h_11, c_21).unwrap()); + overlay.apply_pending(); + + overlay.pin(&h_21); + + let mut commit = CommitSet::default(); + overlay.canonicalize::(&h_12, &mut commit).unwrap(); + db.commit(&commit); + overlay.apply_pending(); // 1_1 and 2_1 should be both pinned + + assert!(contains(&overlay, 1)); + overlay.unpin(&h_21); + assert!(!contains(&overlay, 1)); + assert!(overlay.pinned.is_empty()); + } } diff --git a/core/state-db/src/pruning.rs b/client/state-db/src/pruning.rs similarity index 99% rename from core/state-db/src/pruning.rs rename to client/state-db/src/pruning.rs index 21f472fe69da9..a993df4f111ac 100644 --- a/core/state-db/src/pruning.rs +++ b/client/state-db/src/pruning.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -201,7 +201,7 @@ impl RefWindow { #[cfg(test)] mod tests { use super::RefWindow; - use primitives::H256; + use sp_core::H256; use crate::CommitSet; use crate::test::{make_db, make_commit, TestDb}; diff --git a/client/state-db/src/test.rs b/client/state-db/src/test.rs new file mode 100644 index 0000000000000..accafa9bf831f --- /dev/null +++ b/client/state-db/src/test.rs @@ -0,0 +1,94 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utils + +use std::collections::HashMap; +use sp_core::H256; +use crate::{DBValue, ChangeSet, CommitSet, MetaDb, NodeDb}; + +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct TestDb { + pub data: HashMap, + pub meta: HashMap, DBValue>, +} + +impl MetaDb for TestDb { + type Error = (); + + fn get_meta(&self, key: &[u8]) -> Result, ()> { + Ok(self.meta.get(key).cloned()) + } +} + +impl NodeDb for TestDb { + type Error = (); + type Key = H256; + + fn get(&self, key: &H256) -> Result, ()> { + Ok(self.data.get(key).cloned()) + } +} + +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); + } + self.meta.extend(commit.meta.inserted.iter().cloned()); + for k in commit.meta.deleted.iter() { + self.meta.remove(k); + } + } + + pub fn data_eq(&self, other: &TestDb) -> bool { + self.data == other.data + } +} + +pub fn make_changeset(inserted: &[u64], deleted: &[u64]) -> ChangeSet { + ChangeSet { + inserted: inserted + .iter() + .map(|v| { + (H256::from_low_u64_be(*v), H256::from_low_u64_be(*v).as_bytes().to_vec()) + }) + .collect(), + deleted: deleted.iter().map(|v| H256::from_low_u64_be(*v)).collect(), + } +} + +pub fn make_commit(inserted: &[u64], deleted: &[u64]) -> CommitSet { + CommitSet { + data: make_changeset(inserted, deleted), + meta: ChangeSet::default(), + } +} + +pub fn make_db(inserted: &[u64]) -> TestDb { + TestDb { + data: inserted + .iter() + .map(|v| { + (H256::from_low_u64_be(*v), H256::from_low_u64_be(*v).as_bytes().to_vec()) + }) + .collect(), + meta: Default::default(), + } +} + diff --git a/client/telemetry/Cargo.toml b/client/telemetry/Cargo.toml new file mode 100644 index 0000000000000..c536b7599b59b --- /dev/null +++ b/client/telemetry/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sc-telemetry" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Telemetry utils" +edition = "2018" + +[dependencies] +bytes = "0.5" +parking_lot = "0.9.0" +futures = "0.3.1" +futures-timer = "2.0.0" +libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["libp2p-websocket"] } +log = "0.4.8" +pin-project = "0.4.6" +rand = "0.7.2" +serde = { version = "1.0.101", features = ["derive"] } +slog = { version = "2.5.2", features = ["nested-values"] } +slog-json = { version = "2.3.0", features = ["nested-values"] } +slog-scope = "4.1.2" +take_mut = "0.2.2" +void = "1.0.2" diff --git a/client/telemetry/src/async_record.rs b/client/telemetry/src/async_record.rs new file mode 100644 index 0000000000000..34b7c1435afa1 --- /dev/null +++ b/client/telemetry/src/async_record.rs @@ -0,0 +1,155 @@ +//! # Internal types to ssync drain slog +//! FIXME: REMOVE THIS ONCE THE PR WAS MERGE +//! https://github.com/slog-rs/async/pull/14 + +use slog::{Record, RecordStatic, Level, SingleKV, KV, BorrowedKV}; +use slog::{Serializer, OwnedKVList, Key}; + +use std::fmt; +use take_mut::take; + +struct ToSendSerializer { + kv: Box, +} + +impl ToSendSerializer { + fn new() -> Self { + ToSendSerializer { kv: Box::new(()) } + } + + fn finish(self) -> Box { + self.kv + } +} + +impl Serializer for ToSendSerializer { + fn emit_bool(&mut self, key: Key, val: bool) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_unit(&mut self, key: Key) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, ())))); + Ok(()) + } + fn emit_none(&mut self, key: Key) -> slog::Result { + let val: Option<()> = None; + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_char(&mut self, key: Key, val: char) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_u8(&mut self, key: Key, val: u8) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_i8(&mut self, key: Key, val: i8) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_u16(&mut self, key: Key, val: u16) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_i16(&mut self, key: Key, val: i16) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_u32(&mut self, key: Key, val: u32) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_i32(&mut self, key: Key, val: i32) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_f32(&mut self, key: Key, val: f32) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_u64(&mut self, key: Key, val: u64) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_i64(&mut self, key: Key, val: i64) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_f64(&mut self, key: Key, val: f64) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_usize(&mut self, key: Key, val: usize) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_isize(&mut self, key: Key, val: isize) -> slog::Result { + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_str(&mut self, key: Key, val: &str) -> slog::Result { + let val = val.to_owned(); + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + fn emit_arguments( + &mut self, + key: Key, + val: &fmt::Arguments, + ) -> slog::Result { + let val = fmt::format(*val); + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } + + fn emit_serde(&mut self, key: Key, value: &dyn slog::SerdeValue) -> slog::Result { + let val = value.to_sendable(); + take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val)))); + Ok(()) + } +} + +pub(crate) struct AsyncRecord { + msg: String, + level: Level, + location: Box, + tag: String, + logger_values: OwnedKVList, + kv: Box, +} + +impl AsyncRecord { + /// Serializes a `Record` and an `OwnedKVList`. + pub fn from(record: &Record, logger_values: &OwnedKVList) -> Self { + let mut ser = ToSendSerializer::new(); + record + .kv() + .serialize(record, &mut ser) + .expect("`ToSendSerializer` can't fail"); + + AsyncRecord { + msg: fmt::format(*record.msg()), + level: record.level(), + location: Box::new(*record.location()), + tag: String::from(record.tag()), + logger_values: logger_values.clone(), + kv: ser.finish(), + } + } + + /// Deconstruct this `AsyncRecord` into a record and `OwnedKVList`. + pub fn as_record_values(&self, mut f: impl FnMut(&Record, &OwnedKVList)) { + let rs = RecordStatic { + location: &*self.location, + level: self.level, + tag: &self.tag, + }; + + f(&Record::new( + &rs, + &format_args!("{}", self.msg), + BorrowedKV(&self.kv), + ), &self.logger_values) + } +} diff --git a/client/telemetry/src/lib.rs b/client/telemetry/src/lib.rs new file mode 100644 index 0000000000000..906df545e2377 --- /dev/null +++ b/client/telemetry/src/lib.rs @@ -0,0 +1,301 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Telemetry utilities. +//! +//! Calling `init_telemetry` registers a global `slog` logger using `slog_scope::set_global_logger`. +//! After that, calling `slog_scope::with_logger` will return a logger that sends information to +//! the telemetry endpoints. The `telemetry!` macro is a short-cut for calling +//! `slog_scope::with_logger` followed with `slog_log!`. +//! +//! Note that you are supposed to only ever use `telemetry!` and not `slog_scope::with_logger` at +//! the moment. Substate may eventually be reworked to get proper `slog` support, including sending +//! information to the telemetry. +//! +//! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a +//! background thread/task) in order for the telemetry to properly function. Dropping the object +//! will also deregister the global logger and replace it with a logger that discards messages. +//! The `Stream` generates [`TelemetryEvent`]s. +//! +//! > **Note**: Cloning the [`Telemetry`] and polling from multiple clones has an unspecified behaviour. +//! +//! # Example +//! +//! ```no_run +//! use futures::prelude::*; +//! +//! let telemetry = sc_telemetry::init_telemetry(sc_telemetry::TelemetryConfig { +//! endpoints: sc_telemetry::TelemetryEndpoints::new(vec![ +//! // The `0` is the maximum verbosity level of messages to send to this endpoint. +//! ("wss://example.com".into(), 0) +//! ]), +//! // Can be used to pass an external implementation of WebSockets. +//! wasm_external_transport: None, +//! }); +//! +//! // The `telemetry` object implements `Stream` and must be processed. +//! std::thread::spawn(move || { +//! futures::executor::block_on(telemetry.for_each(|_| future::ready(()))); +//! }); +//! +//! // Sends a message on the telemetry. +//! sc_telemetry::telemetry!(sc_telemetry::SUBSTRATE_INFO; "test"; +//! "foo" => "bar", +//! ) +//! ``` +//! + +use futures::{prelude::*, channel::mpsc}; +use libp2p::{Multiaddr, wasm_ext}; +use log::{error, warn}; +use parking_lot::Mutex; +use serde::{Serialize, Deserialize}; +use std::{pin::Pin, sync::Arc, task::{Context, Poll}, time::{Duration, Instant}}; + +pub use libp2p::wasm_ext::ExtTransport; +pub use slog_scope::with_logger; +pub use slog; + +mod async_record; +mod worker; + +/// Configuration for telemetry. +pub struct TelemetryConfig { + /// Collection of telemetry WebSocket servers with a corresponding verbosity level. + pub endpoints: TelemetryEndpoints, + + /// Optional external implementation of a libp2p transport. Used in WASM contexts where we need + /// some binding between the networking provided by the operating system or environment and + /// libp2p. + /// + /// This parameter exists whatever the target platform is, but it is expected to be set to + /// `Some` only when compiling for WASM. + /// + /// > **Important**: Each individual call to `write` corresponds to one message. There is no + /// > internal buffering going on. In the context of WebSockets, each `write` + /// > must be one individual WebSockets frame. + pub wasm_external_transport: Option, +} + +/// List of telemetry servers we want to talk to. Contains the URL of the server, and the +/// maximum verbosity level. +/// +/// The URL string can be either a URL or a multiaddress. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct TelemetryEndpoints(Vec<(String, u8)>); + +impl TelemetryEndpoints { + pub fn new(endpoints: Vec<(String, u8)>) -> Self { + TelemetryEndpoints(endpoints) + } +} + +/// 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 = "1"; + +/// Telemetry object. Implements `Future` and must be polled regularly. +/// Contains an `Arc` and can be cloned and pass around. Only one clone needs to be polled +/// regularly and should be polled regularly. +/// Dropping all the clones unregisters the telemetry. +#[derive(Clone)] +pub struct Telemetry { + inner: Arc>, + /// Slog guard so that we don't get deregistered. + _guard: Arc, +} + +/// Behind the `Mutex` in `Telemetry`. +/// +/// Note that ideally we wouldn't have to make the `Telemetry` clonable, as that would remove the +/// need for a `Mutex`. However there is currently a weird hack in place in `sc-service` +/// where we extract the telemetry registration so that it continues running during the shutdown +/// process. +struct TelemetryInner { + /// Worker for the telemetry. `None` if it failed to initialize. + worker: Option, + /// Receives log entries for them to be dispatched to the worker. + receiver: mpsc::Receiver, +} + +/// Implements `slog::Drain`. +struct TelemetryDrain { + /// Sends log entries. + sender: std::panic::AssertUnwindSafe>, +} + +/// Initializes the telemetry. See the crate root documentation for more information. +/// +/// Please be careful to not call this function twice in the same program. The `slog` crate +/// doesn't provide any way of knowing whether a global logger has already been registered. +pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { + // Build the list of telemetry endpoints. + let mut endpoints = Vec::new(); + for &(ref url, verbosity) in &config.endpoints.0 { + match url_to_multiaddr(url) { + Ok(addr) => endpoints.push((addr, verbosity)), + Err(err) => warn!(target: "telemetry", "Invalid telemetry URL {}: {}", url, err), + } + } + + let (sender, receiver) = mpsc::channel(16); + let guard = { + let logger = TelemetryDrain { sender: std::panic::AssertUnwindSafe(sender) }; + let root = slog::Logger::root(slog::Drain::fuse(logger), slog::o!()); + slog_scope::set_global_logger(root) + }; + + let worker = match worker::TelemetryWorker::new(endpoints, config.wasm_external_transport) { + Ok(w) => Some(w), + Err(err) => { + error!(target: "telemetry", "Failed to initialize telemetry worker: {:?}", err); + None + } + }; + + Telemetry { + inner: Arc::new(Mutex::new(TelemetryInner { + worker, + receiver, + })), + _guard: Arc::new(guard), + } +} + +/// Event generated when polling the worker. +#[derive(Debug)] +pub enum TelemetryEvent { + /// We have established a connection to one of the telemetry endpoint, either for the first + /// time or after having been disconnected earlier. + Connected, +} + +impl Stream for Telemetry { + type Item = TelemetryEvent; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + let before = Instant::now(); + + // Because the `Telemetry` is clonable, we need to put the actual fields behind a `Mutex`. + // However, the user is only ever supposed to poll from one instance of `Telemetry`, while + // the other instances are used only for RAII purposes. + // We assume that the user is following this advice and therefore that the `Mutex` is only + // ever locked once at a time. + let mut inner = match self.inner.try_lock() { + Some(l) => l, + None => { + warn!( + target: "telemetry", + "The telemetry seems to be polled multiple times simultaneously" + ); + // Returning `Pending` here means that we may never get polled again, but this is + // ok because we're in a situation where something else is actually currently doing + // the polling. + return Poll::Pending; + } + }; + + let mut has_connected = false; + + // The polling pattern is: poll the worker so that it processes its queue, then add one + // message from the receiver (if possible), then poll the worker again, and so on. + loop { + if let Some(worker) = inner.worker.as_mut() { + while let Poll::Ready(event) = worker.poll(cx) { + // Right now we only have one possible event. This line is here in order to not + // forget to handle any possible new event type. + let worker::TelemetryWorkerEvent::Connected = event; + has_connected = true; + } + } + + if let Poll::Ready(Some(log_entry)) = Stream::poll_next(Pin::new(&mut inner.receiver), cx) { + if let Some(worker) = inner.worker.as_mut() { + log_entry.as_record_values(|rec, val| { let _ = worker.log(rec, val); }); + } + } else { + break; + } + } + + if before.elapsed() > Duration::from_millis(200) { + warn!(target: "telemetry", "Polling the telemetry took more than 200ms"); + } + + if has_connected { + Poll::Ready(Some(TelemetryEvent::Connected)) + } else { + Poll::Pending + } + } +} + +impl slog::Drain for TelemetryDrain { + type Ok = (); + type Err = (); + + fn log(&self, record: &slog::Record, values: &slog::OwnedKVList) -> Result { + let before = Instant::now(); + + let serialized = async_record::AsyncRecord::from(record, values); + // Note: interestingly, `try_send` requires a `&mut` because it modifies some internal value, while `clone()` + // is lock-free. + if let Err(err) = self.sender.clone().try_send(serialized) { + warn!(target: "telemetry", "Ignored telemetry message because of error on channel: {:?}", err); + } + + if before.elapsed() > Duration::from_millis(50) { + warn!(target: "telemetry", "Writing a telemetry log took more than 50ms"); + } + + Ok(()) + } +} + +/// Parses a WebSocket URL into a libp2p `Multiaddr`. +fn url_to_multiaddr(url: &str) -> Result { + // First, assume that we have a `Multiaddr`. + let parse_error = match url.parse() { + Ok(ma) => return Ok(ma), + Err(err) => err, + }; + + // If not, try the `ws://path/url` format. + if let Ok(ma) = libp2p::multiaddr::from_url(url) { + return Ok(ma) + } + + // If we have no clue about the format of that string, assume that we were expecting a + // `Multiaddr`. + Err(parse_error) +} + +/// 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 { + ( $a:expr; $b:expr; $( $t:tt )* ) => { + $crate::with_logger(|l| { + $crate::slog::slog_info!(l, #$a, $b; $($t)* ) + }) + } +} diff --git a/client/telemetry/src/worker.rs b/client/telemetry/src/worker.rs new file mode 100644 index 0000000000000..8f43bb612a105 --- /dev/null +++ b/client/telemetry/src/worker.rs @@ -0,0 +1,259 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Contains the object that makes the telemetry work. +//! +//! # Usage +//! +//! - Create a `TelemetryWorker` with `TelemetryWorker::new`. +//! - Send messages to the telemetry with `TelemetryWorker::send_message`. Messages will only be +//! sent to the appropriate targets. Messages may be ignored if the target happens to be +//! temporarily unreachable. +//! - You must appropriately poll the worker with `TelemetryWorker::poll`. Polling will/may produce +//! events indicating what happened since the latest polling. +//! + +use bytes::BytesMut; +use futures::{prelude::*, ready}; +use libp2p::{core::transport::OptionalTransport, Multiaddr, Transport, wasm_ext}; +use log::{trace, warn, error}; +use slog::Drain; +use std::{io, pin::Pin, task::Context, task::Poll, time}; + +mod node; + +/// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP +/// upgrading. +const CONNECT_TIMEOUT: time::Duration = time::Duration::from_secs(20); + +/// Event generated when polling the worker. +#[derive(Debug)] +pub enum TelemetryWorkerEvent { + /// We have established a connection to one of the telemetry endpoint, either for the first + /// time or after having been disconnected earlier. + Connected, +} + +/// Telemetry processing machine. +#[derive(Debug)] +pub struct TelemetryWorker { + /// List of nodes with their maximum verbosity level. + nodes: Vec<(node::Node, u8)>, +} + +trait StreamAndSink: Stream + Sink {} +impl, I> StreamAndSink for T {} + +type WsTrans = libp2p::core::transport::boxed::Boxed< + Pin, + Error = io::Error + > + Send>>, + io::Error +>; + +impl TelemetryWorker { + /// Builds a new `TelemetryWorker`. + /// + /// The endpoints must be a list of targets, plus a verbosity level. When you send a message + /// to the telemetry, only the targets whose verbosity is higher than the verbosity of the + /// message will receive it. + pub fn new( + endpoints: impl IntoIterator, + wasm_external_transport: impl Into> + ) -> Result { + let transport = match wasm_external_transport.into() { + Some(t) => OptionalTransport::some(t), + None => OptionalTransport::none() + }.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _); + + // The main transport is the `wasm_external_transport`, but if we're on desktop we add + // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass + // an external transport on desktop and the fallback is used all the time. + #[cfg(not(target_os = "unknown"))] + let transport = transport.or_transport({ + let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?; + libp2p::websocket::framed::WsConfig::new(inner) + .and_then(|connec, _| { + let connec = connec + .with(|item: BytesMut| { + let item = libp2p::websocket::framed::OutgoingData::Binary(item); + future::ready(Ok::<_, io::Error>(item)) + }) + .try_filter(|item| future::ready(item.is_data())) + .map_ok(|data| BytesMut::from(data.as_ref())); + future::ready(Ok::<_, io::Error>(connec)) + }) + }); + + let transport = transport + .timeout(CONNECT_TIMEOUT) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) + .map(|out, _| { + let out = out + .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) + .sink_map_err(|err| io::Error::new(io::ErrorKind::Other, err)); + Box::pin(out) as Pin> + }) + .boxed(); + + Ok(TelemetryWorker { + nodes: endpoints.into_iter().map(|(addr, verbosity)| { + let node = node::Node::new(transport.clone(), addr); + (node, verbosity) + }).collect() + }) + } + + /// Polls the worker for events that happened. + pub fn poll(&mut self, cx: &mut Context) -> Poll { + for (node, _) in &mut self.nodes { + loop { + match node::Node::poll(Pin::new(node), cx) { + Poll::Ready(node::NodeEvent::Connected) => + return Poll::Ready(TelemetryWorkerEvent::Connected), + Poll::Ready(node::NodeEvent::Disconnected(_)) => continue, + Poll::Pending => break, + } + } + } + + Poll::Pending + } + + /// Equivalent to `slog::Drain::log`, but takes `self` by `&mut` instead, which is more convenient. + /// + /// Keep in mind that you should call `TelemetryWorker::poll` in order to process the messages. + /// You should call this function right after calling `slog::Drain::log`. + pub fn log(&mut self, record: &slog::Record, values: &slog::OwnedKVList) -> Result<(), ()> { + let msg_verbosity = match record.tag().parse::() { + Ok(v) => v, + Err(err) => { + warn!(target: "telemetry", "Failed to parse telemetry tag {:?}: {:?}", + record.tag(), err); + return Err(()) + } + }; + + // None of the nodes want that verbosity, so just return without doing any serialization. + if self.nodes.iter().all(|(_, node_max_verbosity)| msg_verbosity > *node_max_verbosity) { + trace!( + target: "telemetry", + "Skipping log entry because verbosity {:?} is too high for all endpoints", + msg_verbosity + ); + return Ok(()) + } + + // Turn the message into JSON. + let serialized = { + let mut out = Vec::new(); + slog_json::Json::default(&mut out).log(record, values).map_err(|_| ())?; + out + }; + + for (node, node_max_verbosity) in &mut self.nodes { + if msg_verbosity > *node_max_verbosity { + trace!(target: "telemetry", "Skipping {:?} for log entry with verbosity {:?}", + node.addr(), msg_verbosity); + continue; + } + + // `send_message` returns an error if we're not connected, which we silently ignore. + let _ = node.send_message(&serialized.clone()[..]); + } + + Ok(()) + } +} + +/// Wraps around an `AsyncWrite` and implements `Sink`. Guarantees that each item being sent maps +/// to one call of `write`. +/// +/// For some context, we put this object around the `wasm_ext::ExtTransport` in order to make sure +/// that each telemetry message maps to one single call to `write` in the WASM FFI. +#[pin_project::pin_project] +struct StreamSink(#[pin] T, Option); + +impl From for StreamSink { + fn from(inner: T) -> StreamSink { + StreamSink(inner, None) + } +} + +impl Stream for StreamSink { + type Item = Result; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + let this = self.project(); + let mut buf = [0; 128]; + match ready!(AsyncRead::poll_read(this.0, cx, &mut buf)) { + Ok(0) => Poll::Ready(None), + Ok(n) => { + let buf: BytesMut = buf[..n].into(); + Poll::Ready(Some(Ok(buf))) + }, + Err(err) => Poll::Ready(Some(Err(err))), + } + } +} + +impl StreamSink { + fn poll_flush_buffer(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + let this = self.project(); + + if let Some(buffer) = this.1 { + if ready!(this.0.poll_write(cx, &buffer[..]))? != buffer.len() { + error!(target: "telemetry", + "Detected some internal buffering happening in the telemetry"); + let err = io::Error::new(io::ErrorKind::Other, "Internal buffering detected"); + return Poll::Ready(Err(err)); + } + } + + *this.1 = None; + Poll::Ready(Ok(())) + } +} + +impl Sink for StreamSink { + type Error = io::Error; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + ready!(StreamSink::poll_flush_buffer(self, cx))?; + Poll::Ready(Ok(())) + } + + fn start_send(self: Pin<&mut Self>, item: BytesMut) -> Result<(), Self::Error> { + let this = self.project(); + debug_assert!(this.1.is_none()); + *this.1 = Some(item); + Ok(()) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + ready!(self.as_mut().poll_flush_buffer(cx))?; + let this = self.project(); + AsyncWrite::poll_flush(this.0, cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + ready!(self.as_mut().poll_flush_buffer(cx))?; + let this = self.project(); + AsyncWrite::poll_close(this.0, cx) + } +} diff --git a/core/telemetry/src/worker/node.rs b/client/telemetry/src/worker/node.rs similarity index 93% rename from core/telemetry/src/worker/node.rs rename to client/telemetry/src/worker/node.rs index 0f606e4063802..58e9f20bd5f7c 100644 --- a/core/telemetry/src/worker/node.rs +++ b/client/telemetry/src/worker/node.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 @@ //! Contains the `Node` struct, which handles communications with a single telemetry endpoint. use bytes::BytesMut; -use futures::{prelude::*, compat::{Future01CompatExt as _, Compat01As03}}; +use futures::prelude::*; use futures_timer::Delay; use libp2p::Multiaddr; use libp2p::core::transport::Transport; @@ -42,7 +42,7 @@ enum NodeSocket { /// We're connected to the node. This is the normal state. Connected(NodeSocketConnected), /// We are currently dialing the node. - Dialing(Compat01As03), + Dialing(TTrans::Dial), /// A new connection should be started as soon as possible. ReconnectNow, /// Waiting before attempting to dial again. @@ -76,6 +76,9 @@ pub enum NodeEvent { pub enum ConnectionError { /// The connection timed-out. Timeout, + /// Reading from the socket returned and end-of-file, indicating that the socket has been + /// closed. + Closed, /// The sink errored. Sink(TSinkErr), } @@ -106,7 +109,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, /// Sends a WebSocket frame to the node. Returns an error if we are not connected to the node. /// /// After calling this method, you should call `poll` in order for it to be properly processed. - pub fn send_message(&mut self, payload: Vec) -> Result<(), ()> { + pub fn send_message(&mut self, payload: impl Into) -> Result<(), ()> { if let NodeSocket::Connected(NodeSocketConnected { pending, .. }) = &mut self.socket { if pending.len() <= MAX_PENDING { trace!(target: "telemetry", "Adding log entry to queue for {:?}", self.addr); @@ -163,7 +166,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, NodeSocket::ReconnectNow => match self.transport.clone().dial(self.addr.clone()) { Ok(d) => { debug!(target: "telemetry", "Started dialing {}", self.addr); - socket = NodeSocket::Dialing(d.compat()); + socket = NodeSocket::Dialing(d); } Err(err) => { warn!(target: "telemetry", "Error while dialing {}: {:?}", self.addr, err); @@ -212,10 +215,13 @@ where TTrans::Output: Sink ) -> Poll>> { while let Some(item) = self.pending.pop_front() { - if let Poll::Ready(_) = Sink::poll_ready(Pin::new(&mut self.sink), cx) { + if let Poll::Ready(result) = Sink::poll_ready(Pin::new(&mut self.sink), cx) { + if let Err(err) = result { + return Poll::Ready(Err(ConnectionError::Sink(err))) + } + let item_len = item.len(); if let Err(err) = Sink::start_send(Pin::new(&mut self.sink), item) { - self.timeout = None; return Poll::Ready(Err(ConnectionError::Sink(err))) } trace!( @@ -254,11 +260,7 @@ where TTrans::Output: Sink if let Some(timeout) = self.timeout.as_mut() { match Future::poll(Pin::new(timeout), cx) { Poll::Pending => {}, - Poll::Ready(Err(err)) => { - self.timeout = None; - warn!(target: "telemetry", "Connection timeout error for {} {:?}", my_addr, err); - } - Poll::Ready(Ok(_)) => { + Poll::Ready(()) => { self.timeout = None; return Poll::Ready(Err(ConnectionError::Timeout)) } @@ -274,7 +276,10 @@ where TTrans::Output: Sink Poll::Ready(Some(Err(err))) => { return Poll::Ready(Err(ConnectionError::Sink(err))) }, - Poll::Pending | Poll::Ready(None) => {}, + Poll::Ready(None) => { + return Poll::Ready(Err(ConnectionError::Closed)) + }, + Poll::Pending => {}, } Poll::Pending diff --git a/client/tracing/Cargo.toml b/client/tracing/Cargo.toml new file mode 100644 index 0000000000000..2ceee93f6a62a --- /dev/null +++ b/client/tracing/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "sc-tracing" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +erased-serde = "0.3.9" +log = { version = "0.4.8" } +parking_lot = "0.9.0" +serde = "1.0.101" +serde_json = "1.0.41" +slog = { version = "2.5.2", features = ["nested-values"] } +tracing-core = "0.1.7" + +sc-telemetry = { version = "2.0.0", path = "../telemetry" } +grafana-data-source = { version = "2.0.0", path = "../../utils/grafana-data-source" } + +[dev-dependencies] +tracing = "0.1.10" diff --git a/client/tracing/src/lib.rs b/client/tracing/src/lib.rs new file mode 100644 index 0000000000000..cd301041d39af --- /dev/null +++ b/client/tracing/src/lib.rs @@ -0,0 +1,299 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Instrumentation implementation for substrate. +//! +//! This crate is unstable and the API and usage may change. +//! +//! # Usage +//! +//! Monitor performance throughout the codebase via the creation of `Span`s. +//! A span is set in the following way: +//! ``` +//! let span = tracing::span!(tracing::Level::INFO, "my_span_name"); +//! let _guard = span.enter(); +//! ``` +//! To begin timing, a span must be entered. When the span is dropped, the execution time +//! is recorded and details sent to the `Receiver` which defines how to process it. +//! +//! It's possible to record values with each span in the following way: +//! ``` +//! let span = tracing::span!(tracing::Level::INFO, "my_span_name", my_number = 10, a_key = "a value"); +//! let _guard = span.enter(); +//! ``` +//! Currently we provide `Log` (default), `Telemetry` and `Grafana` variants for `Receiver` + +use std::collections::HashMap; +use std::fmt; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::time::{Duration, Instant}; + +use parking_lot::Mutex; +use serde::ser::{Serialize, Serializer, SerializeMap}; +use slog::{SerdeValue, Value}; +use tracing_core::{ + event::Event, + field::{Visit, Field}, + Level, + metadata::Metadata, + span::{Attributes, Id, Record}, + subscriber::Subscriber +}; + +use grafana_data_source::{self, record_metrics}; +use sc_telemetry::{telemetry, SUBSTRATE_INFO}; + +/// Used to configure how to receive the metrics +#[derive(Debug, Clone)] +pub enum TracingReceiver { + /// Output to logger + Log, + /// Output to telemetry + Telemetry, + /// Output to Grafana + Grafana, +} + +impl Default for TracingReceiver { + fn default() -> Self { + Self::Log + } +} + +#[derive(Debug)] +struct SpanDatum { + id: u64, + name: &'static str, + target: &'static str, + level: Level, + line: u32, + start_time: Instant, + overall_time: Duration, + values: Visitor, +} + +#[derive(Clone, Debug)] +struct Visitor(Vec<(String, String)>); + +impl Visit for Visitor { + fn record_i64(&mut self, field: &Field, value: i64) { + self.record_debug(field, &value) + } + + fn record_u64(&mut self, field: &Field, value: u64) { + self.record_debug(field, &value) + } + + fn record_bool(&mut self, field: &Field, value: bool) { + self.record_debug(field, &value) + } + + fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) { + self.0.push((field.name().to_string(), format!("{:?}",value))); + } +} + +impl Serialize for Visitor { + fn serialize(&self, serializer: S) -> Result + where S: Serializer, + { + let mut map = serializer.serialize_map(Some(self.0.len()))?; + for (k, v) in &self.0 { + map.serialize_entry(k, v)?; + } + map.end() + } +} + +impl fmt::Display for Visitor { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let values = self.0.iter().map(|(k,v)| format!("{}={}",k,v)).collect::>().join(", "); + write!(f, "{}", values) + } +} + +impl SerdeValue for Visitor { + fn as_serde(&self) -> &dyn erased_serde::Serialize { + self + } + + fn to_sendable(&self) -> Box { + Box::new(self.clone()) + } +} + +impl Value for Visitor { + fn serialize( + &self, + _record: &slog::Record, + key: slog::Key, + ser: &mut dyn slog::Serializer, + ) -> slog::Result { + ser.emit_serde(key, self) + } +} + +/// Responsible for assigning ids to new spans, which are not re-used. +pub struct ProfilingSubscriber { + next_id: AtomicU64, + targets: Vec<(String, Level)>, + receiver: TracingReceiver, + span_data: Mutex>, +} + +impl ProfilingSubscriber { + /// Takes a `Receiver` and a comma separated list of targets, + /// either with a level: "pallet=trace" + /// or without: "pallet". + pub fn new(receiver: TracingReceiver, targets: &str) -> Self { + let targets: Vec<_> = targets.split(',').map(|s| parse_target(s)).collect(); + ProfilingSubscriber { + next_id: AtomicU64::new(1), + targets, + receiver, + span_data: Mutex::new(HashMap::new()), + } + } +} + +// Default to TRACE if no level given or unable to parse Level +// We do not support a global `Level` currently +fn parse_target(s: &str) -> (String, Level) { + match s.find('=') { + Some(i) => { + let target = s[0..i].to_string(); + if s.len() > i { + let level = s[i + 1..s.len()].parse::().unwrap_or(Level::TRACE); + (target, level) + } else { + (target, Level::TRACE) + } + } + None => (s.to_string(), Level::TRACE) + } +} + +impl Subscriber for ProfilingSubscriber { + fn enabled(&self, metadata: &Metadata<'_>) -> bool { + for t in &self.targets { + if metadata.target().starts_with(t.0.as_str()) && metadata.level() <= &t.1 { + log::debug!("Enabled target: {}, level: {}", metadata.target(), metadata.level()); + return true; + } else { + log::debug!("Disabled target: {}, level: {}", metadata.target(), metadata.level()); + } + } + false + } + + fn new_span(&self, attrs: &Attributes<'_>) -> Id { + let id = self.next_id.fetch_add(1, Ordering::Relaxed); + let mut values = Visitor(Vec::new()); + attrs.record(&mut values); + let span_datum = SpanDatum { + id, + name: attrs.metadata().name(), + target: attrs.metadata().target(), + level: attrs.metadata().level().clone(), + line: attrs.metadata().line().unwrap_or(0), + start_time: Instant::now(), + overall_time: Duration::from_nanos(0), + values, + }; + self.span_data.lock().insert(id, span_datum); + Id::from_u64(id) + } + + fn record(&self, _span: &Id, _values: &Record<'_>) {} + + fn record_follows_from(&self, _span: &Id, _follows: &Id) {} + + fn event(&self, _event: &Event<'_>) {} + + fn enter(&self, span: &Id) { + let mut span_data = self.span_data.lock(); + let start_time = Instant::now(); + if let Some(mut s) = span_data.get_mut(&span.into_u64()) { + s.start_time = start_time; + } else { + log::warn!("Tried to enter span {:?} that has already been closed!", span); + } + } + + fn exit(&self, span: &Id) { + let mut span_data = self.span_data.lock(); + let end_time = Instant::now(); + if let Some(mut s) = span_data.get_mut(&span.into_u64()) { + s.overall_time = end_time - s.start_time + s.overall_time; + } + } + + fn try_close(&self, span: Id) -> bool { + let mut span_data = self.span_data.lock(); + if let Some(data) = span_data.remove(&span.into_u64()) { + self.send_span(data); + }; + true + } +} + +impl ProfilingSubscriber { + fn send_span(&self, span_datum: SpanDatum) { + match self.receiver { + TracingReceiver::Log => print_log(span_datum), + TracingReceiver::Telemetry => send_telemetry(span_datum), + TracingReceiver::Grafana => send_grafana(span_datum), + } + } +} + +fn print_log(span_datum: SpanDatum) { + if span_datum.values.0.is_empty() { + log::info!("TRACING: {} {}: {}, line: {}, time: {}", + span_datum.level, + span_datum.target, + span_datum.name, + span_datum.line, + span_datum.overall_time.as_nanos(), + ); + } else { + log::info!("TRACING: {} {}: {}, line: {}, time: {}, {}", + span_datum.level, + span_datum.target, + span_datum.name, + span_datum.line, + span_datum.overall_time.as_nanos(), + span_datum.values + ); + } +} + +fn send_telemetry(span_datum: SpanDatum) { + telemetry!(SUBSTRATE_INFO; "tracing.profiling"; + "name" => span_datum.name, + "target" => span_datum.target, + "line" => span_datum.line, + "time" => span_datum.overall_time.as_nanos(), + "values" => span_datum.values + ); +} + +fn send_grafana(span_datum: SpanDatum) { + let name = format!("{}::{}", span_datum.target, span_datum.name); + if let Err(e) = record_metrics!(&name => span_datum.overall_time.as_nanos(),) { + log::warn!("Unable to send metrics to grafana: {:?}", e); + } +} diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml new file mode 100644 index 0000000000000..701826307129d --- /dev/null +++ b/client/transaction-pool/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sc-transaction-pool" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0" } +derive_more = "0.99.2" +futures = { version = "0.3.1", features = ["compat"] } +log = "0.4.8" +parking_lot = "0.9.0" +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sc-transaction-graph = { version = "2.0.0", path = "./graph" } +sp-transaction-pool = { version = "2.0.0", path = "../../primitives/transaction-pool" } +sc-client-api = { version = "2.0.0", path = "../api" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } + +[dev-dependencies] +sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" } diff --git a/client/transaction-pool/graph/Cargo.toml b/client/transaction-pool/graph/Cargo.toml new file mode 100644 index 0000000000000..c5897e84fe50d --- /dev/null +++ b/client/transaction-pool/graph/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "sc-transaction-graph" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +derive_more = "0.99.2" +futures = "0.3.1" +log = "0.4.8" +parking_lot = "0.9.0" +serde = { version = "1.0.101", features = ["derive"] } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-transaction-pool = { version = "2.0.0", path = "../../../primitives/transaction-pool" } + +[dev-dependencies] +assert_matches = "1.3.0" +codec = { package = "parity-scale-codec", version = "1.0.0" } +substrate-test-runtime = { version = "2.0.0", path = "../../../test-utils/runtime" } +criterion = "0.3" + +[[bench]] +name = "basics" +harness = false diff --git a/client/transaction-pool/graph/benches/basics.rs b/client/transaction-pool/graph/benches/basics.rs new file mode 100644 index 0000000000000..557a2ca3d1f85 --- /dev/null +++ b/client/transaction-pool/graph/benches/basics.rs @@ -0,0 +1,165 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use criterion::{criterion_group, criterion_main, Criterion}; + +use futures::executor::block_on; +use sc_transaction_graph::*; +use sp_runtime::transaction_validity::{ValidTransaction, InvalidTransaction}; +use codec::Encode; +use substrate_test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; +use sp_runtime::{ + generic::BlockId, + transaction_validity::{TransactionValidity, TransactionTag as Tag}, +}; +use sp_core::blake2_256; + +#[derive(Clone, Debug, Default)] +struct TestApi { + nonce_dependant: bool, +} + +impl TestApi { + fn new_dependant() -> Self { + TestApi { nonce_dependant: true } + } +} + +fn to_tag(nonce: u64, from: AccountId) -> Tag { + let mut data = [0u8; 40]; + data[..8].copy_from_slice(&nonce.to_le_bytes()[..]); + data[8..].copy_from_slice(&from.0[..]); + data.to_vec() +} + +impl ChainApi for TestApi { + type Block = Block; + type Hash = H256; + type Error = sp_transaction_pool::error::Error; + type ValidationFuture = futures::future::Ready>; + + fn validate_transaction( + &self, + at: &BlockId, + uxt: ExtrinsicFor, + ) -> Self::ValidationFuture { + let nonce = uxt.transfer().nonce; + let from = uxt.transfer().from.clone(); + + match self.block_id_to_number(at) { + Ok(Some(num)) if num > 5 => { + return futures::future::ready( + Ok(Err(InvalidTransaction::Stale.into())) + ) + }, + _ => {}, + } + + futures::future::ready( + Ok(Ok(ValidTransaction { + priority: 4, + requires: if nonce > 1 && self.nonce_dependant { + vec![to_tag(nonce-1, from.clone())] + } else { vec![] }, + provides: vec![to_tag(nonce, from)], + longevity: 10, + propagate: true, + })) + ) + } + + fn block_id_to_number( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(*num), + BlockId::Hash(_) => None, + }) + } + + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), + BlockId::Hash(_) => None, + }) + } + + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { + let encoded = uxt.encode(); + (blake2_256(&encoded).into(), encoded.len()) + } +} + +fn uxt(transfer: Transfer) -> Extrinsic { + Extrinsic::Transfer(transfer, Default::default()) +} + +fn bench_configured(pool: Pool, number: u64) { + let mut futures = Vec::new(); + let mut tags = Vec::new(); + + for nonce in 1..=number { + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce, + }); + + tags.push(to_tag(nonce, AccountId::from_h256(H256::from_low_u64_be(1)))); + futures.push(pool.submit_one(&BlockId::Number(1), xt)); + } + + let res = block_on(futures::future::join_all(futures.into_iter())); + assert!(res.iter().all(Result::is_ok)); + + assert_eq!(pool.status().future, 0); + assert_eq!(pool.status().ready, number as usize); + + // Prune all transactions. + let block_num = 6; + block_on(pool.prune_tags( + &BlockId::Number(block_num), + tags, + vec![], + )).expect("Prune failed"); + + // pool is empty + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); +} + +fn benchmark_main(c: &mut Criterion) { + + c.bench_function("sequential 50 tx", |b| { + b.iter(|| { + bench_configured(Pool::new(Default::default(), TestApi::new_dependant()), 50); + }); + }); + + c.bench_function("random 100 tx", |b| { + b.iter(|| { + bench_configured(Pool::new(Default::default(), TestApi::default()), 100); + }); + }); +} + +criterion_group!(benches, benchmark_main); +criterion_main!(benches); diff --git a/core/transaction-pool/graph/src/base_pool.rs b/client/transaction-pool/graph/src/base_pool.rs similarity index 82% rename from core/transaction-pool/graph/src/base_pool.rs rename to client/transaction-pool/graph/src/base_pool.rs index cb37aee07f4b8..1da731b71e6d5 100644 --- a/core/transaction-pool/graph/src/base_pool.rs +++ b/client/transaction-pool/graph/src/base_pool.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -27,15 +27,15 @@ use std::{ use log::{trace, debug, warn}; use serde::Serialize; -use primitives::hexdisplay::HexDisplay; -use sr_primitives::traits::Member; -use sr_primitives::transaction_validity::{ +use sp_core::hexdisplay::HexDisplay; +use sp_runtime::traits::Member; +use sp_runtime::transaction_validity::{ TransactionTag as Tag, TransactionLongevity as Longevity, TransactionPriority as Priority, }; +use sp_transaction_pool::{error, PoolStatus, InPoolTransaction}; -use crate::error; use crate::future::{FutureTransactions, WaitingTransaction}; use crate::ready::ReadyTransactions; @@ -104,13 +104,65 @@ pub struct Transaction { pub propagate: bool, } -impl Transaction { - /// Returns `true` if the transaction should be propagated to other peers. - pub fn is_propagateable(&self) -> bool { +impl AsRef for Transaction { + fn as_ref(&self) -> &Extrinsic { + &self.data + } +} + +impl InPoolTransaction for Transaction { + type Transaction = Extrinsic; + type Hash = Hash; + + fn data(&self) -> &Extrinsic { + &self.data + } + + fn hash(&self) -> &Hash { + &self.hash + } + + fn priority(&self) -> &Priority { + &self.priority + } + + fn longevity(&self) ->&Longevity { + &self.valid_till + } + + fn requires(&self) -> &[Tag] { + &self.requires + } + + fn provides(&self) -> &[Tag] { + &self.provides + } + + fn is_propagateable(&self) -> bool { self.propagate } } +impl Transaction { + /// Explicit transaction clone. + /// + /// Transaction should be cloned only if absolutely necessary && we want + /// every reason to be commented. That's why we `Transaction` is not `Clone`, + /// but there's explicit `duplicate` method. + pub fn duplicate(&self) -> Self { + Transaction { + data: self.data.clone(), + bytes: self.bytes.clone(), + hash: self.hash.clone(), + priority: self.priority.clone(), + valid_till: self.valid_till.clone(), + requires: self.requires.clone(), + provides: self.provides.clone(), + propagate: self.propagate, + } + } +} + impl fmt::Debug for Transaction where Hash: fmt::Debug, Extrinsic: fmt::Debug, @@ -159,6 +211,7 @@ const RECENTLY_PRUNED_TAGS: usize = 2; /// required tags. #[derive(Debug)] pub struct BasePool { + reject_future_transactions: bool, future: FutureTransactions, ready: ReadyTransactions, /// Store recently pruned tags (for last two invocations). @@ -169,18 +222,37 @@ pub struct BasePool { recently_pruned_index: usize, } -impl Default for BasePool { +impl Default for BasePool { fn default() -> Self { + Self::new(false) + } +} + +impl BasePool { + /// Create new pool given reject_future_transactions flag. + pub fn new(reject_future_transactions: bool) -> Self { BasePool { + reject_future_transactions, future: Default::default(), ready: Default::default(), recently_pruned: Default::default(), recently_pruned_index: 0, } } -} -impl BasePool { + /// Temporary enables future transactions, runs closure and then restores + /// `reject_future_transactions` flag back to previous value. + /// + /// The closure accepts the mutable reference to the pool and original value + /// of the `reject_future_transactions` flag. + pub(crate) fn with_futures_enabled(&mut self, closure: impl FnOnce(&mut Self, bool) -> T) -> T { + let previous = self.reject_future_transactions; + self.reject_future_transactions = false; + let return_value = closure(self, previous); + self.reject_future_transactions = previous; + return_value + } + /// Imports transaction to the pool. /// /// The pool consists of two parts: Future and Ready. @@ -202,10 +274,19 @@ impl BasePool BasePool BasePool BasePool BasePool Vec>> { - let mut removed = self.ready.remove_invalid(hashes); + pub fn remove_subtree(&mut self, hashes: &[Hash]) -> Vec>> { + let mut removed = self.ready.remove_subtree(hashes); removed.extend(self.future.remove(hashes)); removed } + /// Removes and returns all transactions from the future queue. + pub fn clear_future(&mut self) -> Vec>> { + self.future.clear() + } + /// Prunes transactions that provide given list of tags. /// /// This will cause all transactions that provide these tags to be removed from the pool, - /// but unlike `remove_invalid`, dependent transactions are not touched. + /// but unlike `remove_subtree`, dependent transactions are not touched. /// Additional transactions from future queue might be promoted to ready if you satisfy tags /// that the pool didn't previously know about. pub fn prune_tags(&mut self, tags: impl IntoIterator) -> PruneStatus { @@ -385,7 +471,7 @@ impl BasePool BasePool Status { - Status { + pub fn status(&self) -> PoolStatus { + PoolStatus { ready: self.ready.len(), ready_bytes: self.ready.bytes(), future: self.future.len(), @@ -423,26 +509,6 @@ impl BasePool bool { - self.ready == 0 && self.future == 0 - } -} - /// Queue limits #[derive(Debug, Clone)] pub struct Limit { @@ -844,7 +910,7 @@ mod tests { assert_eq!(pool.future.len(), 1); // when - pool.remove_invalid(&[6, 1]); + pool.remove_subtree(&[6, 1]); // then assert_eq!(pool.ready().count(), 1); @@ -972,4 +1038,85 @@ requires: [03,02], provides: [04], data: [4]}".to_owned() propagate: false, }.is_propagateable(), false); } + + #[test] + fn should_reject_future_transactions() { + // given + let mut pool = pool(); + + // when + pool.reject_future_transactions = true; + + // then + let err = pool.import(Transaction { + data: vec![5u8], + bytes: 1, + hash: 5, + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + }); + + if let Err(error::Error::RejectedFutureTransaction) = err { + } else { + assert!(false, "Invalid error kind: {:?}", err); + } + } + + #[test] + fn should_clear_future_queue() { + // given + let mut pool = pool(); + + // when + pool.import(Transaction { + data: vec![5u8], + bytes: 1, + hash: 5, + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + }).unwrap(); + + // then + assert_eq!(pool.future.len(), 1); + + // and then when + assert_eq!(pool.clear_future().len(), 1); + + // then + assert_eq!(pool.future.len(), 0); + } + + #[test] + fn should_accept_future_transactions_when_explcitly_asked_to() { + // given + let mut pool = pool(); + pool.reject_future_transactions = true; + + // when + let flag_value = pool.with_futures_enabled(|pool, flag| { + pool.import(Transaction { + data: vec![5u8], + bytes: 1, + hash: 5, + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + }).unwrap(); + + flag + }); + + // then + assert_eq!(flag_value, true); + assert_eq!(pool.reject_future_transactions, true); + assert_eq!(pool.future.len(), 1); + } } diff --git a/client/transaction-pool/graph/src/error.rs b/client/transaction-pool/graph/src/error.rs new file mode 100644 index 0000000000000..6fd7748e369ab --- /dev/null +++ b/client/transaction-pool/graph/src/error.rs @@ -0,0 +1,79 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Transaction pool errors. + +use sp_runtime::transaction_validity::{ + TransactionPriority as Priority, InvalidTransaction, UnknownTransaction, +}; + +/// Transaction pool result. +pub type Result = std::result::Result; + +/// Transaction pool error type. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Transaction is not verifiable yet, but might be in the future. + #[display(fmt="Unknown transaction validity: {:?}", _0)] + UnknownTransaction(UnknownTransaction), + /// Transaction is invalid. + #[display(fmt="Invalid transaction validity: {:?}", _0)] + InvalidTransaction(InvalidTransaction), + /// The transaction validity returned no "provides" tag. + /// + /// Such transactions are not accepted to the pool, since we use those tags + /// to define identity of transactions (occupance of the same "slot"). + #[display(fmt="The transaction does not provide any tags, so the pool can't identify it.")] + NoTagsProvided, + /// The transaction is temporarily banned. + #[display(fmt="Temporarily Banned")] + TemporarilyBanned, + /// The transaction is already in the pool. + #[display(fmt="[{:?}] Already imported", _0)] + AlreadyImported(Box), + /// The transaction cannot be imported cause it's a replacement and has too low priority. + #[display(fmt="Too low priority ({} > {})", old, new)] + TooLowPriority { + /// Transaction already in the pool. + old: Priority, + /// Transaction entering the pool. + new: Priority + }, + /// Deps cycle detected and we couldn't import transaction. + #[display(fmt="Cycle Detected")] + CycleDetected, + /// Transaction was dropped immediately after it got inserted. + #[display(fmt="Transaction couldn't enter the pool because of the limit.")] + ImmediatelyDropped, + /// Invalid block id. + InvalidBlockId(String), +} + +impl std::error::Error for Error {} + +/// Transaction pool error conversion. +pub trait IntoPoolError: ::std::error::Error + Send + Sized { + /// Try to extract original `Error` + /// + /// This implementation is optional and used only to + /// provide more descriptive error messages for end users + /// of RPC API. + fn into_pool_error(self) -> ::std::result::Result { Err(self) } +} + +impl IntoPoolError for Error { + fn into_pool_error(self) -> ::std::result::Result { Ok(self) } +} diff --git a/core/transaction-pool/graph/src/future.rs b/client/transaction-pool/graph/src/future.rs similarity index 95% rename from core/transaction-pool/graph/src/future.rs rename to client/transaction-pool/graph/src/future.rs index c7b13c912df18..d106c65d45ab4 100644 --- a/core/transaction-pool/graph/src/future.rs +++ b/client/transaction-pool/graph/src/future.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,8 +22,8 @@ use std::{ time, }; -use primitives::hexdisplay::HexDisplay; -use sr_primitives::transaction_validity::{ +use sp_core::hexdisplay::HexDisplay; +use sp_runtime::transaction_validity::{ TransactionTag as Tag, }; @@ -227,6 +227,12 @@ impl FutureTransactions { self.waiting.values().map(|waiting| &*waiting.transaction) } + /// Removes and returns all future transactions. + pub fn clear(&mut self) -> Vec>> { + self.wanted_tags.clear(); + self.waiting.drain().map(|(_, tx)| tx.transaction).collect() + } + /// Returns number of transactions in the Future queue. pub fn len(&self) -> usize { self.waiting.len() diff --git a/client/transaction-pool/graph/src/lib.rs b/client/transaction-pool/graph/src/lib.rs new file mode 100644 index 0000000000000..23970ba9b8f8c --- /dev/null +++ b/client/transaction-pool/graph/src/lib.rs @@ -0,0 +1,42 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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 Transaction Pool +//! +//! The pool is based on dependency graph between transactions +//! 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. + +#![warn(missing_docs)] +#![warn(unused_extern_crates)] + +mod future; +mod listener; +mod pool; +mod ready; +mod rotator; +mod validated_pool; + +pub mod base_pool; +pub mod watcher; + +pub use self::base_pool::Transaction; +pub use self::pool::{ + Pool, + Options, ChainApi, EventStream, ExtrinsicFor, + BlockHash, ExHash, NumberFor, TransactionFor, +}; diff --git a/core/transaction-pool/graph/src/listener.rs b/client/transaction-pool/graph/src/listener.rs similarity index 77% rename from core/transaction-pool/graph/src/listener.rs rename to client/transaction-pool/graph/src/listener.rs index 335ff8a0537e9..dab2a6f5aae3f 100644 --- a/core/transaction-pool/graph/src/listener.rs +++ b/client/transaction-pool/graph/src/listener.rs @@ -1,5 +1,5 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,12 +17,13 @@ use std::{ collections::HashMap, + fmt, hash, }; use serde::Serialize; use crate::watcher; -use sr_primitives::traits; -use log::warn; +use sp_runtime::traits; +use log::{debug, trace, warn}; /// Extrinsic pool default listener. pub struct Listener { @@ -37,7 +38,7 @@ impl Default for Listener { } } -impl Listener { +impl Listener { fn fire(&mut self, hash: &H, fun: F) where F: FnOnce(&mut watcher::Sender) { let clean = if let Some(h) = self.watchers.get_mut(hash) { fun(h); @@ -61,11 +62,13 @@ impl Listener { /// Notify the listeners about extrinsic broadcast. pub fn broadcasted(&mut self, hash: &H, peers: Vec) { + trace!(target: "txpool", "[{:?}] Broadcasted", hash); self.fire(hash, |watcher| watcher.broadcast(peers)); } /// New transaction was added to the ready pool or promoted from the future pool. pub fn ready(&mut self, tx: &H, old: Option<&H>) { + trace!(target: "txpool", "[{:?}] Ready (replaced: {:?})", tx, old); self.fire(tx, |watcher| watcher.ready()); if let Some(old) = old { self.fire(old, |watcher| watcher.usurped(tx.clone())); @@ -74,11 +77,13 @@ impl Listener { /// New transaction was added to the future pool. pub fn future(&mut self, tx: &H) { + trace!(target: "txpool", "[{:?}] Future", tx); self.fire(tx, |watcher| watcher.future()); } /// Transaction was dropped from the pool because of the limit. pub fn dropped(&mut self, tx: &H, by: Option<&H>) { + trace!(target: "txpool", "[{:?}] Dropped (replaced by {:?})", tx, by); self.fire(tx, |watcher| match by { Some(t) => watcher.usurped(t.clone()), None => watcher.dropped(), @@ -86,13 +91,18 @@ impl Listener { } /// Transaction was removed as invalid. - pub fn invalid(&mut self, tx: &H) { - warn!(target: "transaction-pool", "Extrinsic invalid: {:?}", tx); + pub fn invalid(&mut self, tx: &H, warn: bool) { + if warn { + warn!(target: "txpool", "Extrinsic invalid: {:?}", tx); + } else { + debug!(target: "txpool", "Extrinsic invalid: {:?}", tx); + } self.fire(tx, |watcher| watcher.invalid()); } /// Transaction was pruned from the pool. pub fn pruned(&mut self, header_hash: H2, tx: &H) { - self.fire(tx, |watcher| watcher.finalized(header_hash)) + debug!(target: "txpool", "[{:?}] Pruned at {:?}", tx, header_hash); + self.fire(tx, |watcher| watcher.in_block(header_hash)) } } diff --git a/client/transaction-pool/graph/src/pool.rs b/client/transaction-pool/graph/src/pool.rs new file mode 100644 index 0000000000000..629bd0a9a93a8 --- /dev/null +++ b/client/transaction-pool/graph/src/pool.rs @@ -0,0 +1,1084 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{ + hash, + collections::HashMap, + sync::Arc, +}; + +use crate::base_pool as base; +use crate::watcher::Watcher; +use serde::Serialize; + +use futures::{ + Future, FutureExt, + channel::mpsc, + future::{Either, ready, join_all}, +}; +use sp_runtime::{ + generic::BlockId, + traits::{self, SaturatedConversion}, + transaction_validity::{TransactionValidity, TransactionTag as Tag, TransactionValidityError}, +}; +use sp_transaction_pool::{error, PoolStatus}; + +use crate::validated_pool::{ValidatedPool, ValidatedTransaction}; + +/// Modification notification event stream type; +pub type EventStream = mpsc::UnboundedReceiver<()>; + +/// Extrinsic hash type for a pool. +pub type ExHash = ::Hash; +/// Block hash type for a pool. +pub type BlockHash = <::Block as traits::Block>::Hash; +/// Extrinsic type for a pool. +pub type ExtrinsicFor = <::Block as traits::Block>::Extrinsic; +/// Block number type for the ChainApi +pub type NumberFor = traits::NumberFor<::Block>; +/// A type of transaction stored in the pool +pub type TransactionFor = Arc, ExtrinsicFor>>; +/// A type of validated transaction stored in the pool. +pub type ValidatedTransactionFor = ValidatedTransaction< + ExHash, + ExtrinsicFor, + ::Error, +>; + +/// Concrete extrinsic validation and query logic. +pub trait ChainApi: Send + Sync { + /// Block type. + type Block: traits::Block; + /// Transaction Hash type + type Hash: hash::Hash + Eq + traits::Member + Serialize; + /// Error type. + type Error: From + error::IntoPoolError; + /// Validate transaction future. + type ValidationFuture: Future> + Send + Unpin; + + /// Verify extrinsic at given block. + fn validate_transaction( + &self, + at: &BlockId, + uxt: ExtrinsicFor, + ) -> Self::ValidationFuture; + + /// Returns a block number given the block id. + fn block_id_to_number(&self, at: &BlockId) -> Result>, Self::Error>; + + /// Returns a block hash given the block id. + fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error>; + + /// Returns hash and encoding length of the extrinsic. + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize); +} + +/// Pool configuration options. +#[derive(Debug, Clone)] +pub struct Options { + /// Ready queue limits. + pub ready: base::Limit, + /// Future queue limits. + pub future: base::Limit, + /// Reject future transactions. + pub reject_future_transactions: bool, +} + +impl Default for Options { + fn default() -> Self { + Options { + ready: base::Limit { + count: 512, + total_bytes: 10 * 1024 * 1024, + }, + future: base::Limit { + count: 128, + total_bytes: 1 * 1024 * 1024, + }, + reject_future_transactions: false, + } + } +} + +/// Extrinsics pool that performs validation. +pub struct Pool { + validated_pool: Arc>, +} + +impl Pool { + /// Create a new transaction pool. + pub fn new(options: Options, api: B) -> Self { + Pool { + validated_pool: Arc::new(ValidatedPool::new(options, api)), + } + } + + /// Imports a bunch of unverified extrinsics to the pool + pub fn submit_at(&self, at: &BlockId, xts: T, force: bool) + -> impl Future, B::Error>>, B::Error>> + where + T: IntoIterator> + { + let validated_pool = self.validated_pool.clone(); + self.verify(at, xts, force) + .map(move |validated_transactions| validated_transactions + .map(|validated_transactions| validated_pool.submit(validated_transactions + .into_iter() + .map(|(_, tx)| tx)))) + } + + /// Imports one unverified extrinsic to the pool + pub fn submit_one( + &self, + at: &BlockId, + xt: ExtrinsicFor, + ) -> impl Future, B::Error>> { + self.submit_at(at, std::iter::once(xt), false) + .map(|import_result| import_result.and_then(|mut import_result| import_result + .pop() + .expect("One extrinsic passed; one result returned; qed") + )) + } + + /// Import a single extrinsic and starts to watch their progress in the pool. + pub fn submit_and_watch( + &self, + at: &BlockId, + xt: ExtrinsicFor, + ) -> impl Future, BlockHash>, B::Error>> { + let block_number = match self.resolve_block_number(at) { + Ok(block_number) => block_number, + Err(err) => return Either::Left(ready(Err(err))) + }; + + let validated_pool = self.validated_pool.clone(); + Either::Right( + self.verify_one(at, block_number, xt, false) + .map(move |validated_transactions| validated_pool.submit_and_watch(validated_transactions.1)) + ) + } + + /// Revalidate all ready transactions. + /// + /// Returns future that performs validation of all ready transactions and + /// then resubmits all transactions back to the pool. + pub fn revalidate_ready( + &self, + at: &BlockId, + max: Option, + ) -> impl Future> { + use std::time::Instant; + log::debug!(target: "txpool", + "Fetching ready transactions (up to: {})", + max.map(|x| format!("{}", x)).unwrap_or_else(|| "all".into()) + ); + let validated_pool = self.validated_pool.clone(); + let ready = self.validated_pool.ready() + .map(|tx| tx.data.clone()) + .take(max.unwrap_or_else(usize::max_value)); + + let now = Instant::now(); + self.verify(at, ready, false) + .map(move |revalidated_transactions| { + log::debug!(target: "txpool", + "Re-verified transactions, took {} ms. Resubmitting.", + now.elapsed().as_millis() + ); + let now = Instant::now(); + let res = revalidated_transactions.map( + |revalidated_transactions| validated_pool.resubmit(revalidated_transactions) + ); + log::debug!(target: "txpool", + "Resubmitted. Took {} ms. Status: {:?}", + now.elapsed().as_millis(), + validated_pool.status() + ); + res + }) + } + + /// Prunes known ready transactions. + /// + /// Used to clear the pool from transactions that were part of recently imported block. + /// The main difference from the `prune` is that we do not revalidate any transactions + /// and ignore unknown passed hashes. + pub fn prune_known(&self, at: &BlockId, hashes: &[ExHash]) -> Result<(), B::Error> { + // Get details of all extrinsics that are already in the pool + let in_pool_tags = self.validated_pool.extrinsics_tags(hashes) + .into_iter().filter_map(|x| x).flat_map(|x| x); + + // Prune all transactions that provide given tags + let prune_status = self.validated_pool.prune_tags(in_pool_tags)?; + let pruned_transactions = hashes.into_iter().cloned() + .chain(prune_status.pruned.iter().map(|tx| tx.hash.clone())); + self.validated_pool.fire_pruned(at, pruned_transactions) + } + + /// 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], + ) -> impl Future> { + log::debug!( + target: "txpool", + "Starting pruning of block {:?} (extrinsics: {})", + at, + extrinsics.len() + ); + // Get details of all extrinsics that are already in the pool + let in_pool_hashes = extrinsics.iter().map(|extrinsic| self.hash_of(extrinsic)).collect::>(); + let in_pool_tags = self.validated_pool.extrinsics_tags(&in_pool_hashes); + + // Zip the ones from the pool with the full list (we get pairs `(Extrinsic, Option>)`) + let all = extrinsics.iter().zip(in_pool_tags.into_iter()); + + // Prepare future that collect tags for all extrinsics + let future_tags = join_all(all + .map(|(extrinsic, in_pool_tags)| + match in_pool_tags { + // reuse the tags for extrinsics that were found in the pool + Some(tags) => Either::Left( + ready(tags) + ), + // if it's not found in the pool query the runtime at parent block + // to get validity info and tags that the extrinsic provides. + None => Either::Right(self.validated_pool.api().validate_transaction(parent, extrinsic.clone()) + .then(|validity| ready(match validity { + Ok(Ok(validity)) => validity.provides, + // silently ignore invalid extrinsics, + // cause they might just be inherent + _ => Vec::new(), + }))), + } + )); + + // Prune transactions by tags + let at = at.clone(); + let self_clone = self.clone(); + future_tags.then(move |tags| self_clone.prune_tags( + &at, + tags.into_iter().flat_map(|tags| tags), + in_pool_hashes, + )) + } + + /// Prunes ready transactions that provide given list of tags. + /// + /// 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. + /// + /// Returns transactions that have been removed from the pool and must be reverified + /// before reinserting to the pool. + /// + /// By removing predecessor transactions as well we might actually end up + /// pruning too much, so all removed transactions are reverified against + /// the runtime (`validate_transaction`) to make sure they are invalid. + /// + /// 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, + ) -> impl Future> { + log::debug!(target: "txpool", "Pruning at {:?}", at); + // Prune all transactions that provide given tags + let prune_status = match self.validated_pool.prune_tags(tags) { + Ok(prune_status) => prune_status, + Err(e) => return Either::Left(ready(Err(e))), + }; + + // Make sure that we don't revalidate extrinsics that were part of the recently + // imported block. This is especially important for UTXO-like chains cause the + // inputs are pruned so such transaction would go to future again. + self.validated_pool.ban(&std::time::Instant::now(), known_imported_hashes.clone().into_iter()); + + // Try to re-validate pruned transactions since some of them might be still valid. + // note that `known_imported_hashes` will be rejected here due to temporary ban. + let pruned_hashes = prune_status.pruned.iter().map(|tx| tx.hash.clone()).collect::>(); + let pruned_transactions = prune_status.pruned.into_iter().map(|tx| tx.data.clone()); + let reverify_future = self.verify(at, pruned_transactions, false); + + log::trace!(target: "txpool", "Prunning at {:?}. Resubmitting transactions.", at); + // And finally - submit reverified transactions back to the pool + let at = at.clone(); + let validated_pool = self.validated_pool.clone(); + Either::Right(reverify_future.then(move |reverified_transactions| + ready(reverified_transactions.and_then(|reverified_transactions| + validated_pool.resubmit_pruned( + &at, + known_imported_hashes, + pruned_hashes, + reverified_transactions.into_iter().map(|(_, xt)| xt).collect(), + )) + ))) + } + + /// Return an event stream of notifications for when transactions are imported to the pool. + /// + /// Consumers of this stream should use the `ready` method to actually get the + /// pending transactions in the right order. + pub fn import_notification_stream(&self) -> EventStream { + self.validated_pool.import_notification_stream() + } + + /// Invoked when extrinsics are broadcasted. + pub fn on_broadcasted(&self, propagated: HashMap, Vec>) { + self.validated_pool.on_broadcasted(propagated) + } + + /// Remove invalid transactions from the pool. + pub fn remove_invalid(&self, hashes: &[ExHash]) -> Vec> { + self.validated_pool.remove_invalid(hashes) + } + + /// Get an iterator for ready transactions ordered by priority + pub fn ready(&self) -> impl Iterator> { + self.validated_pool.ready() + } + + /// Returns pool status. + pub fn status(&self) -> PoolStatus { + self.validated_pool.status() + } + + /// Returns transaction hash + pub fn hash_of(&self, xt: &ExtrinsicFor) -> ExHash { + self.validated_pool.api().hash_and_length(xt).0 + } + + /// Resolves block number by id. + fn resolve_block_number(&self, at: &BlockId) -> Result, B::Error> { + self.validated_pool.api().block_id_to_number(at) + .and_then(|number| number.ok_or_else(|| + error::Error::InvalidBlockId(format!("{:?}", at)).into())) + } + + /// Returns future that validates a bunch of transactions at given block. + fn verify( + &self, + at: &BlockId, + xts: impl IntoIterator>, + force: bool, + ) -> impl Future, ValidatedTransactionFor>, B::Error>> { + // we need a block number to compute tx validity + let block_number = match self.resolve_block_number(at) { + Ok(block_number) => block_number, + Err(err) => return Either::Left(ready(Err(err))), + }; + + // for each xt, prepare a validation future + let validation_futures = xts.into_iter().map(move |xt| + self.verify_one(at, block_number, xt, force) + ); + + // make single validation future that waits all until all extrinsics are validated + Either::Right(join_all(validation_futures).then(|x| ready(Ok(x.into_iter().collect())))) + } + + /// Returns future that validates single transaction at given block. + fn verify_one( + &self, + block_id: &BlockId, + block_number: NumberFor, + xt: ExtrinsicFor, + force: bool, + ) -> impl Future, ValidatedTransactionFor)> { + let (hash, bytes) = self.validated_pool.api().hash_and_length(&xt); + if !force && self.validated_pool.is_banned(&hash) { + return Either::Left(ready(( + hash.clone(), + ValidatedTransaction::Invalid(hash, error::Error::TemporarilyBanned.into()), + ))) + } + + Either::Right(self.validated_pool.api().validate_transaction(block_id, xt.clone()) + .then(move |validation_result| ready((hash.clone(), match validation_result { + Ok(validity) => match validity { + Ok(validity) => if validity.provides.is_empty() { + ValidatedTransaction::Invalid(hash, error::Error::NoTagsProvided.into()) + } else { + ValidatedTransaction::Valid(base::Transaction { + data: xt, + bytes, + hash, + priority: validity.priority, + requires: validity.requires, + provides: validity.provides, + propagate: validity.propagate, + valid_till: block_number + .saturated_into::() + .saturating_add(validity.longevity), + }) + }, + Err(TransactionValidityError::Invalid(e)) => + ValidatedTransaction::Invalid(hash, error::Error::InvalidTransaction(e).into()), + Err(TransactionValidityError::Unknown(e)) => + ValidatedTransaction::Unknown(hash, error::Error::UnknownTransaction(e).into()), + }, + Err(e) => ValidatedTransaction::Invalid(hash, e), + })))) + } +} + +impl Clone for Pool { + fn clone(&self) -> Self { + Self { + validated_pool: self.validated_pool.clone(), + } + } +} + +#[cfg(test)] +mod tests { + use std::{ + collections::{HashMap, HashSet}, + time::Instant, + }; + use parking_lot::Mutex; + use futures::executor::block_on; + use super::*; + use sp_transaction_pool::TransactionStatus; + use sp_runtime::transaction_validity::{ValidTransaction, InvalidTransaction}; + use codec::Encode; + use substrate_test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; + use assert_matches::assert_matches; + use crate::base_pool::Limit; + + const INVALID_NONCE: u64 = 254; + + #[derive(Clone, Debug, Default)] + struct TestApi { + delay: Arc>>>, + invalidate: Arc>>, + clear_requirements: Arc>>, + add_requirements: Arc>>, + } + + impl ChainApi for TestApi { + type Block = Block; + type Hash = u64; + type Error = error::Error; + type ValidationFuture = futures::future::Ready>; + + /// Verify extrinsic at given block. + fn validate_transaction( + &self, + at: &BlockId, + uxt: ExtrinsicFor, + ) -> Self::ValidationFuture { + let hash = self.hash_and_length(&uxt).0; + let block_number = self.block_id_to_number(at).unwrap().unwrap(); + let nonce = uxt.transfer().nonce; + + // This is used to control the test flow. + if nonce > 0 { + let opt = self.delay.lock().take(); + if let Some(delay) = opt { + if delay.recv().is_err() { + println!("Error waiting for delay!"); + } + } + } + + if self.invalidate.lock().contains(&hash) { + return futures::future::ready(Ok(InvalidTransaction::Custom(0).into())); + } + + futures::future::ready(if nonce < block_number { + Ok(InvalidTransaction::Stale.into()) + } else { + let mut transaction = ValidTransaction { + priority: 4, + requires: if nonce > block_number { vec![vec![nonce as u8 - 1]] } else { vec![] }, + provides: if nonce == INVALID_NONCE { vec![] } else { vec![vec![nonce as u8]] }, + longevity: 3, + propagate: true, + }; + + if self.clear_requirements.lock().contains(&hash) { + transaction.requires.clear(); + } + + if self.add_requirements.lock().contains(&hash) { + transaction.requires.push(vec![128]); + } + + Ok(Ok(transaction)) + }) + } + + /// Returns a block number given the block id. + fn block_id_to_number(&self, at: &BlockId) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(*num), + BlockId::Hash(_) => None, + }) + } + + /// Returns a block hash given the block id. + fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), + BlockId::Hash(_) => None, + }) + } + + /// Hash the extrinsic. + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { + let len = uxt.encode().len(); + ( + (H256::from(uxt.transfer().from.clone()).to_low_u64_be() << 5) + uxt.transfer().nonce, + len + ) + } + } + + fn uxt(transfer: Transfer) -> Extrinsic { + Extrinsic::Transfer(transfer, Default::default()) + } + + fn pool() -> Pool { + Pool::new(Default::default(), TestApi::default()) + } + + #[test] + fn should_validate_and_import_transaction() { + // given + let pool = pool(); + + // when + let hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }))).unwrap(); + + // then + assert_eq!(pool.ready().map(|v| v.hash).collect::>(), vec![hash]); + } + + #[test] + fn should_reject_if_temporarily_banned() { + // given + let pool = pool(); + let uxt = 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, + }); + + // when + pool.validated_pool.rotator().ban(&Instant::now(), vec![pool.hash_of(&uxt)]); + let res = block_on(pool.submit_one(&BlockId::Number(0), uxt)); + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + + // then + assert_matches!(res.unwrap_err(), error::Error::TemporarilyBanned); + } + + #[test] + fn should_notify_about_pool_events() { + let stream = { + // given + let pool = pool(); + let stream = pool.import_notification_stream(); + + // when + let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }))).unwrap(); + let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 1, + }))).unwrap(); + // future doesn't count + let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 3, + }))).unwrap(); + + assert_eq!(pool.status().ready, 2); + assert_eq!(pool.status().future, 1); + stream + }; + + // then + let mut it = futures::executor::block_on_stream(stream); + assert_eq!(it.next(), Some(())); + assert_eq!(it.next(), Some(())); + assert_eq!(it.next(), None); + } + + #[test] + fn should_clear_stale_transactions() { + // given + let pool = pool(); + let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }))).unwrap(); + let hash2 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 1, + }))).unwrap(); + let hash3 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 3, + }))).unwrap(); + + // when + pool.validated_pool.clear_stale(&BlockId::Number(5)).unwrap(); + + // then + assert_eq!(pool.ready().count(), 0); + assert_eq!(pool.status().future, 0); + assert_eq!(pool.status().ready, 0); + // make sure they are temporarily banned as well + assert!(pool.validated_pool.rotator().is_banned(&hash1)); + assert!(pool.validated_pool.rotator().is_banned(&hash2)); + assert!(pool.validated_pool.rotator().is_banned(&hash3)); + } + + #[test] + fn should_ban_mined_transactions() { + // given + let pool = pool(); + let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }))).unwrap(); + + // when + block_on(pool.prune_tags(&BlockId::Number(1), vec![vec![0]], vec![hash1.clone()])).unwrap(); + + // then + assert!(pool.validated_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(), + ..Default::default() + }, TestApi::default()); + + let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 1, + }))).unwrap(); + assert_eq!(pool.status().future, 1); + + // when + let hash2 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(2)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 10, + }))).unwrap(); + + // then + assert_eq!(pool.status().future, 1); + assert!(pool.validated_pool.rotator().is_banned(&hash1)); + assert!(!pool.validated_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(), + ..Default::default() + }, TestApi::default()); + + // when + block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 1, + }))).unwrap_err(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + } + + #[test] + fn should_reject_transactions_with_no_provides() { + // given + let pool = pool(); + + // when + let err = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: INVALID_NONCE, + }))).unwrap_err(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + assert_matches!(err, error::Error::NoTagsProvided); + } + + mod listener { + use super::*; + + #[test] + fn should_trigger_ready_and_finalized() { + // given + let pool = pool(); + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }))).unwrap(); + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 0); + + // when + block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![])).unwrap(); + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + + // then + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::InBlock(H256::from_low_u64_be(2).into()))); + assert_eq!(stream.next(), None); + } + + #[test] + fn should_trigger_ready_and_finalized_when_pruning_via_hash() { + // given + let pool = pool(); + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }))).unwrap(); + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 0); + + // when + block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![2u64])).unwrap(); + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + + // then + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::InBlock(H256::from_low_u64_be(2).into()))); + assert_eq!(stream.next(), None); + } + + #[test] + fn should_trigger_future_and_ready_after_promoted() { + // given + let pool = pool(); + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 1, + }))).unwrap(); + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 1); + + // when + block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: 0, + }))).unwrap(); + assert_eq!(pool.status().ready, 2); + + // then + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(TransactionStatus::Future)); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + } + + #[test] + fn should_trigger_invalid_and_ban() { + // given + let pool = pool(); + let uxt = 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 = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt)).unwrap(); + assert_eq!(pool.status().ready, 1); + + // when + pool.validated_pool.remove_invalid(&[*watcher.hash()]); + + + // then + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Invalid)); + assert_eq!(stream.next(), None); + } + + #[test] + fn should_trigger_broadcasted() { + // given + let pool = pool(); + let uxt = 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 = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt)).unwrap(); + assert_eq!(pool.status().ready, 1); + + // when + let mut map = HashMap::new(); + let peers = vec!["a".into(), "b".into(), "c".into()]; + map.insert(*watcher.hash(), peers.clone()); + pool.on_broadcasted(map); + + + // then + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::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(), + ..Default::default() + }, 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 = block_on(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, + }); + block_on(pool.submit_one(&BlockId::Number(1), xt)).unwrap(); + assert_eq!(pool.status().ready, 1); + + // then + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(TransactionStatus::Ready)); + assert_eq!(stream.next(), Some(TransactionStatus::Dropped)); + } + + #[test] + fn should_handle_pruning_in_the_middle_of_import() { + // given + let (ready, is_ready) = std::sync::mpsc::sync_channel(0); + let (tx, rx) = std::sync::mpsc::sync_channel(1); + let mut api = TestApi::default(); + api.delay = Arc::new(Mutex::new(rx.into())); + let pool = Arc::new(Pool::new(Default::default(), api)); + + // when + 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: 1, + }); + + // This transaction should go to future, since we use `nonce: 1` + let pool2 = pool.clone(); + std::thread::spawn(move || { + block_on(pool2.submit_one(&BlockId::Number(0), xt)).unwrap(); + ready.send(()).unwrap(); + }); + + // But now before the previous one is imported we import + // the one that it depends on. + 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: 4, + nonce: 0, + }); + // The tag the above transaction provides (TestApi is using just nonce as u8) + let provides = vec![0_u8]; + block_on(pool.submit_one(&BlockId::Number(0), xt)).unwrap(); + assert_eq!(pool.status().ready, 1); + + // Now block import happens before the second transaction is able to finish verification. + block_on(pool.prune_tags(&BlockId::Number(1), vec![provides], vec![])).unwrap(); + assert_eq!(pool.status().ready, 0); + + + // so when we release the verification of the previous one it will have + // something in `requires`, but should go to ready directly, since the previous transaction was imported + // correctly. + tx.send(()).unwrap(); + + // then + is_ready.recv().unwrap(); // wait for finish + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 0); + } + } + + #[test] + fn should_revalidate_ready_transactions() { + fn transfer(nonce: u64) -> Extrinsic { + 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, + }) + } + + // given + let pool = pool(); + let tx0 = transfer(0); + let hash0 = pool.validated_pool.api().hash_and_length(&tx0).0; + let watcher0 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx0)).unwrap(); + let tx1 = transfer(1); + let hash1 = pool.validated_pool.api().hash_and_length(&tx1).0; + let watcher1 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx1)).unwrap(); + let tx2 = transfer(2); + let hash2 = pool.validated_pool.api().hash_and_length(&tx2).0; + let watcher2 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx2)).unwrap(); + let tx3 = transfer(3); + let hash3 = pool.validated_pool.api().hash_and_length(&tx3).0; + let watcher3 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx3)).unwrap(); + let tx4 = transfer(4); + let hash4 = pool.validated_pool.api().hash_and_length(&tx4).0; + let watcher4 = block_on(pool.submit_and_watch(&BlockId::Number(0), tx4)).unwrap(); + assert_eq!(pool.status().ready, 5); + + // when + pool.validated_pool.api().invalidate.lock().insert(hash3); + pool.validated_pool.api().clear_requirements.lock().insert(hash1); + pool.validated_pool.api().add_requirements.lock().insert(hash0); + block_on(pool.revalidate_ready(&BlockId::Number(0), None)).unwrap(); + + // then + // hash0 now has unsatisfied requirements => it is moved to the future queue + // hash1 is now independent of hash0 => it is in ready queue + // hash2 still depends on hash1 => it is in ready queue + // hash3 is now invalid => it is removed from the pool + // hash4 now depends on invalidated hash3 => it is moved to the future queue + // + // events for hash3 are: Ready, Invalid + // events for hash4 are: Ready, Invalid + assert_eq!(pool.status().ready, 2); + assert_eq!( + futures::executor::block_on_stream(watcher3.into_stream()).collect::>(), + vec![TransactionStatus::Ready, TransactionStatus::Invalid], + ); + + // when + pool.validated_pool.remove_invalid(&[hash0, hash1, hash2, hash4]); + + // then + // events for hash0 are: Ready, Future, Invalid + // events for hash1 are: Ready, Invalid + // events for hash2 are: Ready, Invalid + assert_eq!( + futures::executor::block_on_stream(watcher0.into_stream()).collect::>(), + vec![TransactionStatus::Ready, TransactionStatus::Future, TransactionStatus::Invalid], + ); + assert_eq!( + futures::executor::block_on_stream(watcher1.into_stream()).collect::>(), + vec![TransactionStatus::Ready, TransactionStatus::Invalid], + ); + assert_eq!( + futures::executor::block_on_stream(watcher2.into_stream()).collect::>(), + vec![TransactionStatus::Ready, TransactionStatus::Invalid], + ); + assert_eq!( + futures::executor::block_on_stream(watcher4.into_stream()).collect::>(), + vec![TransactionStatus::Ready, TransactionStatus::Future, TransactionStatus::Invalid], + ); + } +} + diff --git a/core/transaction-pool/graph/src/ready.rs b/client/transaction-pool/graph/src/ready.rs similarity index 76% rename from core/transaction-pool/graph/src/ready.rs rename to client/transaction-pool/graph/src/ready.rs index 85bb4dd783c42..cdb0076e5a948 100644 --- a/core/transaction-pool/graph/src/ready.rs +++ b/client/transaction-pool/graph/src/ready.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,14 +22,14 @@ use std::{ }; use serde::Serialize; -use log::debug; +use log::trace; use parking_lot::RwLock; -use sr_primitives::traits::Member; -use sr_primitives::transaction_validity::{ +use sp_runtime::traits::Member; +use sp_runtime::transaction_validity::{ TransactionTag as Tag, }; +use sp_transaction_pool::error; -use crate::error; use crate::future::WaitingTransaction; use crate::base_pool::Transaction; @@ -56,8 +56,8 @@ impl Clone for TransactionRef { impl Ord for TransactionRef { fn cmp(&self, other: &Self) -> cmp::Ordering { self.transaction.priority.cmp(&other.transaction.priority) - .then(other.transaction.valid_till.cmp(&self.transaction.valid_till)) - .then(other.insertion_id.cmp(&self.insertion_id)) + .then_with(|| other.transaction.valid_till.cmp(&self.transaction.valid_till)) + .then_with(|| other.insertion_id.cmp(&self.insertion_id)) } } @@ -161,7 +161,10 @@ impl ReadyTransactions { &mut self, tx: WaitingTransaction, ) -> error::Result>>> { - assert!(tx.is_ready(), "Only ready transactions can be imported."); + assert!( + tx.is_ready(), + "Only ready transactions can be imported. Missing: {:?}", tx.missing_tags + ); assert!(!self.ready.read().contains_key(&tx.transaction.hash), "Transaction is already imported."); self.insertion_id += 1; @@ -169,10 +172,11 @@ impl ReadyTransactions { let hash = tx.transaction.hash.clone(); let transaction = tx.transaction; - let replaced = self.replace_previous(&transaction)?; + let (replaced, unlocks) = self.replace_previous(&transaction)?; let mut goes_to_best = true; let mut ready = self.ready.write(); + let mut requires_offset = 0; // Add links to transactions that unlock the current one for tag in &transaction.requires { // Check if the transaction that satisfies the tag is still in the queue. @@ -181,10 +185,14 @@ impl ReadyTransactions { tx.unlocks.push(hash.clone()); // this transaction depends on some other, so it doesn't go to best directly. goes_to_best = false; + } else { + requires_offset += 1; } } // update provided_tags + // call to replace_previous guarantees that we will be overwriting + // only entries that have been removed. for tag in &transaction.provides { self.provided_tags.insert(tag.clone(), hash.clone()); } @@ -202,8 +210,8 @@ impl ReadyTransactions { // insert to Ready ready.insert(hash, ReadyTx { transaction, - unlocks: vec![], - requires_offset: 0, + unlocks, + requires_offset, }); Ok(replaced) @@ -230,15 +238,27 @@ impl ReadyTransactions { }).collect() } - /// Removes invalid transactions from the ready pool. + /// Removes a subtree of transactions from the ready pool. /// /// NOTE removing a transaction will also cause a removal of all transactions that depend on that one /// (i.e. the entire subgraph that this transaction is a start of will be removed). /// All removed transactions are returned. - pub fn remove_invalid(&mut self, hashes: &[Hash]) -> Vec>> { - let mut removed = vec![]; - let mut to_remove = hashes.iter().cloned().collect::>(); + pub fn remove_subtree(&mut self, hashes: &[Hash]) -> Vec>> { + let to_remove = hashes.iter().cloned().collect::>(); + self.remove_subtree_with_tag_filter(to_remove, None) + } + /// Removes a subtrees of transactions trees starting from roots given in `to_remove`. + /// + /// We proceed with a particular branch only if there is at least one provided tag + /// that is not part of `provides_tag_filter`. I.e. the filter contains tags + /// that will stay in the pool, so that we can early exit and avoid descending. + fn remove_subtree_with_tag_filter( + &mut self, + mut to_remove: Vec, + provides_tag_filter: Option>, + ) -> Vec>> { + let mut removed = vec![]; let mut ready = self.ready.write(); loop { let hash = match to_remove.pop() { @@ -247,10 +267,21 @@ impl ReadyTransactions { }; if let Some(mut tx) = ready.remove(&hash) { + let invalidated = tx.transaction.transaction.provides + .iter() + .filter(|tag| provides_tag_filter + .as_ref() + .map(|filter| !filter.contains(&**tag)) + .unwrap_or(true) + ); + + let mut removed_some_tags = false; // remove entries from provided_tags - for tag in &tx.transaction.transaction.provides { + for tag in invalidated { + removed_some_tags = true; self.provided_tags.remove(tag); } + // remove from unlocks for tag in &tx.transaction.transaction.requires { if let Some(hash) = self.provided_tags.get(tag) { @@ -263,11 +294,13 @@ impl ReadyTransactions { // remove from best self.best.remove(&tx.transaction); - // remove all transactions that the current one unlocks - to_remove.append(&mut tx.unlocks); + if removed_some_tags { + // remove all transactions that the current one unlocks + to_remove.append(&mut tx.unlocks); + } // add to removed - debug!(target: "txpool", "[{:?}] Removed as invalid: ", hash); + trace!(target: "txpool", "[{:?}] Removed as part of the subtree.", hash); removed.push(tx.transaction.transaction); } } @@ -338,7 +371,20 @@ impl ReadyTransactions { } } - debug!(target: "txpool", "[{:?}] Pruned.", tx.hash); + // we also need to remove all other tags that this transaction provides, + // but since all the hard work is done, we only clear the provided_tag -> hash + // mapping. + let current_tag = &tag; + for tag in &tx.provides { + let removed = self.provided_tags.remove(tag); + assert_eq!( + removed.as_ref(), + if current_tag == tag { None } else { Some(&tx.hash) }, + "The pool contains exactly one transaction providing given tag; the removed transaction + claims to provide that tag, so it has to be mapped to it's hash; qed" + ); + } + removed.push(tx); } } @@ -350,9 +396,15 @@ impl ReadyTransactions { /// we are about to replace is lower than the priority of the replacement transaction. /// We remove/replace old transactions in case they have lower priority. /// - /// In case replacement is successful returns a list of removed transactions. - fn replace_previous(&mut self, tx: &Transaction) -> error::Result>>> { - let mut to_remove = { + /// In case replacement is successful returns a list of removed transactions + /// and a list of hashes that are still in pool and gets unlocked by the new transaction. + fn replace_previous( + &mut self, + tx: &Transaction, + ) -> error::Result< + (Vec>>, Vec) + > { + let (to_remove, unlocks) = { // check if we are replacing a transaction let replace_hashes = tx.provides .iter() @@ -361,7 +413,7 @@ impl ReadyTransactions { // early exit if we are not replacing anything. if replace_hashes.is_empty() { - return Ok(vec![]); + return Ok((vec![], vec![])); } // now check if collective priority is lower than the replacement transaction. @@ -370,7 +422,9 @@ impl ReadyTransactions { replace_hashes .iter() .filter_map(|hash| ready.get(hash)) - .fold(0u64, |total, tx| total.saturating_add(tx.transaction.transaction.priority)) + .fold(0u64, |total, tx| + total.saturating_add(tx.transaction.transaction.priority) + ) }; // bail - the transaction has too low priority to replace the old ones @@ -378,35 +432,31 @@ impl ReadyTransactions { return Err(error::Error::TooLowPriority { old: old_priority, new: tx.priority }) } - replace_hashes.into_iter().cloned().collect::>() - }; - - let new_provides = tx.provides.iter().cloned().collect::>(); - let mut removed = vec![]; - loop { - let hash = match to_remove.pop() { - Some(hash) => hash, - None => return Ok(removed), + // construct a list of unlocked transactions + let unlocks = { + let ready = self.ready.read(); + replace_hashes + .iter() + .filter_map(|hash| ready.get(hash)) + .fold(vec![], |mut list, tx| { + list.extend(tx.unlocks.iter().cloned()); + list + }) }; - let tx = self.ready.write().remove(&hash).expect(HASH_READY); - // check if this transaction provides stuff that is not provided by the new one. - let (mut unlocks, tx) = (tx.unlocks, tx.transaction.transaction); - { - let invalidated = tx.provides - .iter() - .filter(|tag| !new_provides.contains(&**tag)); + ( + replace_hashes.into_iter().cloned().collect::>(), + unlocks + ) + }; - for tag in invalidated { - // remove the tag since it's no longer provided by any transaction - self.provided_tags.remove(tag); - // add more transactions to remove - to_remove.append(&mut unlocks); - } - } + let new_provides = tx.provides.iter().cloned().collect::>(); + let removed = self.remove_subtree_with_tag_filter(to_remove, Some(new_provides)); - removed.push(tx); - } + Ok(( + removed, + unlocks + )) } /// Returns number of transactions in this queue. @@ -420,6 +470,7 @@ impl ReadyTransactions { } } +/// Iterator of ready transactions ordered by priority. pub struct BestIterator { all: Arc>>>, awaiting: HashMap)>, @@ -430,7 +481,7 @@ impl BestIterator { /// Depending on number of satisfied requirements insert given ref /// either to awaiting set or to best set. fn best_or_awaiting(&mut self, satisfied: usize, tx_ref: TransactionRef) { - if satisfied == tx_ref.transaction.requires.len() { + if satisfied >= tx_ref.transaction.requires.len() { // If we have satisfied all deps insert to best self.best.insert(tx_ref); @@ -503,6 +554,14 @@ mod tests { } } + fn import( + ready: &mut ReadyTransactions, + tx: Transaction + ) -> error::Result>>> { + let x = WaitingTransaction::new(tx, ready.provided_tags(), &[]); + ready.import(x) + } + #[test] fn should_replace_transaction_that_provides_the_same_tag() { // given @@ -517,24 +576,56 @@ mod tests { tx3.provides = vec![vec![4]]; // when - let x = WaitingTransaction::new(tx2, &ready.provided_tags(), &[]); - ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx3, &ready.provided_tags(), &[]); - ready.import(x).unwrap(); + import(&mut ready, tx2).unwrap(); + import(&mut ready, tx3).unwrap(); assert_eq!(ready.get().count(), 2); // too low priority - let x = WaitingTransaction::new(tx1.clone(), &ready.provided_tags(), &[]); - ready.import(x).unwrap_err(); + import(&mut ready, tx1.clone()).unwrap_err(); tx1.priority = 10; - let x = WaitingTransaction::new(tx1.clone(), &ready.provided_tags(), &[]); - ready.import(x).unwrap(); + import(&mut ready, tx1).unwrap(); // then assert_eq!(ready.get().count(), 1); } + #[test] + fn should_replace_multiple_transactions_correctly() { + // given + let mut ready = ReadyTransactions::default(); + let mut tx0 = tx(0); + tx0.requires = vec![]; + tx0.provides = vec![vec![0]]; + let mut tx1 = tx(1); + tx1.requires = vec![]; + tx1.provides = vec![vec![1]]; + let mut tx2 = tx(2); + tx2.requires = vec![vec![0], vec![1]]; + tx2.provides = vec![vec![2], vec![3]]; + let mut tx3 = tx(3); + tx3.requires = vec![vec![2]]; + tx3.provides = vec![vec![4]]; + let mut tx4 = tx(4); + tx4.requires = vec![vec![3]]; + tx4.provides = vec![vec![5]]; + // replacement + let mut tx2_2 = tx(5); + tx2_2.requires = vec![vec![0], vec![1]]; + tx2_2.provides = vec![vec![2]]; + tx2_2.priority = 10; + + for tx in vec![tx0, tx1, tx2, tx3, tx4] { + import(&mut ready, tx).unwrap(); + } + assert_eq!(ready.get().count(), 5); + + // when + import(&mut ready, tx2_2).unwrap(); + + // then + assert_eq!(ready.get().count(), 3); + } #[test] fn should_return_best_transactions_in_correct_order() { @@ -563,16 +654,9 @@ mod tests { }; // when - let x = WaitingTransaction::new(tx1, &ready.provided_tags(), &[]); - ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx2, &ready.provided_tags(), &[]); - ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx3, &ready.provided_tags(), &[]); - ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx4, &ready.provided_tags(), &[]); - ready.import(x).unwrap(); - let x = WaitingTransaction::new(tx5, &ready.provided_tags(), &[]); - ready.import(x).unwrap(); + for tx in vec![tx1, tx2, tx3, tx4, tx5] { + import(&mut ready, tx).unwrap(); + } // then assert_eq!(ready.best.len(), 1); diff --git a/core/transaction-pool/graph/src/rotator.rs b/client/transaction-pool/graph/src/rotator.rs similarity index 98% rename from core/transaction-pool/graph/src/rotator.rs rename to client/transaction-pool/graph/src/rotator.rs index 41c1b5842ae84..e1c852f95a418 100644 --- a/core/transaction-pool/graph/src/rotator.rs +++ b/client/transaction-pool/graph/src/rotator.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/client/transaction-pool/graph/src/validated_pool.rs b/client/transaction-pool/graph/src/validated_pool.rs new file mode 100644 index 0000000000000..7af32c88184e6 --- /dev/null +++ b/client/transaction-pool/graph/src/validated_pool.rs @@ -0,0 +1,522 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{ + collections::{HashSet, HashMap}, + fmt, + hash, + sync::Arc, + time, +}; + +use crate::base_pool as base; +use crate::listener::Listener; +use crate::rotator::PoolRotator; +use crate::watcher::Watcher; +use serde::Serialize; +use log::{debug, warn}; + +use futures::channel::mpsc; +use parking_lot::{Mutex, RwLock}; +use sp_runtime::{ + generic::BlockId, + traits::{self, SaturatedConversion}, + transaction_validity::TransactionTag as Tag, +}; +use sp_transaction_pool::{error, PoolStatus}; + +use crate::base_pool::PruneStatus; +use crate::pool::{EventStream, Options, ChainApi, BlockHash, ExHash, ExtrinsicFor, TransactionFor}; + +/// Pre-validated transaction. Validated pool only accepts transactions wrapped in this enum. +#[derive(Debug)] +pub enum ValidatedTransaction { + /// Transaction that has been validated successfully. + Valid(base::Transaction), + /// Transaction that is invalid. + Invalid(Hash, Error), + /// Transaction which validity can't be determined. + /// + /// We're notifying watchers about failure, if 'unknown' transaction is submitted. + Unknown(Hash, Error), +} + +/// A type of validated transaction stored in the pool. +pub type ValidatedTransactionFor = ValidatedTransaction< + ExHash, + ExtrinsicFor, + ::Error, +>; + +/// Pool that deals with validated transactions. +pub(crate) struct ValidatedPool { + api: B, + options: Options, + listener: RwLock, BlockHash>>, + pool: RwLock, + ExtrinsicFor, + >>, + import_notification_sinks: Mutex>>, + rotator: PoolRotator>, +} + +impl ValidatedPool { + /// Create a new transaction pool. + pub fn new(options: Options, api: B) -> Self { + let base_pool = base::BasePool::new(options.reject_future_transactions); + ValidatedPool { + api, + options, + listener: Default::default(), + pool: RwLock::new(base_pool), + import_notification_sinks: Default::default(), + rotator: Default::default(), + } + } + + /// Bans given set of hashes. + pub fn ban(&self, now: &std::time::Instant, hashes: impl IntoIterator>) { + self.rotator.ban(now, hashes) + } + + /// Returns true if transaction with given hash is currently banned from the pool. + pub fn is_banned(&self, hash: &ExHash) -> bool { + self.rotator.is_banned(hash) + } + + /// Imports a bunch of pre-validated transactions to the pool. + pub fn submit(&self, txs: T) -> Vec, B::Error>> where + T: IntoIterator> + { + let results = txs.into_iter() + .map(|validated_tx| self.submit_one(validated_tx)) + .collect::>(); + + // only enforce limits if there is at least one imported transaction + let removed = if results.iter().any(|res| res.is_ok()) { + self.enforce_limits() + } else { + Default::default() + }; + + results.into_iter().map(|res| match res { + Ok(ref hash) if removed.contains(hash) => Err(error::Error::ImmediatelyDropped.into()), + other => other, + }).collect() + } + + /// Submit single pre-validated transaction to the pool. + fn submit_one(&self, tx: ValidatedTransactionFor) -> Result, B::Error> { + match tx { + ValidatedTransaction::Valid(tx) => { + let imported = self.pool.write().import(tx)?; + + if let base::Imported::Ready { .. } = imported { + self.import_notification_sinks.lock().retain(|sink| sink.unbounded_send(()).is_ok()); + } + + let mut listener = self.listener.write(); + fire_events(&mut *listener, &imported); + Ok(imported.hash().clone()) + } + ValidatedTransaction::Invalid(hash, err) => { + self.rotator.ban(&std::time::Instant::now(), std::iter::once(hash)); + Err(err.into()) + }, + ValidatedTransaction::Unknown(hash, err) => { + self.listener.write().invalid(&hash, false); + Err(err.into()) + } + } + } + + fn enforce_limits(&self) -> HashSet> { + let status = self.pool.read().status(); + let ready_limit = &self.options.ready; + let future_limit = &self.options.future; + + debug!(target: "txpool", "Pool Status: {:?}", status); + + if ready_limit.is_exceeded(status.ready, status.ready_bytes) + || future_limit.is_exceeded(status.future, status.future_bytes) { + // clean up the pool + let removed = { + let mut pool = self.pool.write(); + let removed = pool.enforce_limits(ready_limit, future_limit) + .into_iter().map(|x| x.hash.clone()).collect::>(); + // ban all removed transactions + self.rotator.ban(&std::time::Instant::now(), removed.iter().map(|x| x.clone())); + removed + }; + // run notifications + let mut listener = self.listener.write(); + for h in &removed { + listener.dropped(h, None); + } + + removed + } else { + Default::default() + } + } + + /// Import a single extrinsic and starts to watch their progress in the pool. + pub fn submit_and_watch( + &self, + tx: ValidatedTransactionFor, + ) -> Result, BlockHash>, B::Error> { + match tx { + ValidatedTransaction::Valid(tx) => { + let hash = self.api.hash_and_length(&tx.data).0; + let watcher = self.listener.write().create_watcher(hash); + self.submit(std::iter::once(ValidatedTransaction::Valid(tx))) + .pop() + .expect("One extrinsic passed; one result returned; qed") + .map(|_| watcher) + }, + ValidatedTransaction::Invalid(hash, err) => { + self.rotator.ban(&std::time::Instant::now(), std::iter::once(hash)); + Err(err.into()) + }, + ValidatedTransaction::Unknown(_, err) => Err(err.into()), + } + } + + /// Resubmits revalidated transactions back to the pool. + /// + /// Removes and then submits passed transactions and all dependent transactions. + /// Transactions that are missing from the pool are not submitted. + pub fn resubmit(&self, mut updated_transactions: HashMap, ValidatedTransactionFor>) { + #[derive(Debug, Clone, Copy, PartialEq)] + enum Status { Future, Ready, Failed, Dropped }; + + let (mut initial_statuses, final_statuses) = { + let mut pool = self.pool.write(); + + // remove all passed transactions from the ready/future queues + // (this may remove additional transactions as well) + // + // for every transaction that has an entry in the `updated_transactions`, + // we store updated validation result in txs_to_resubmit + // for every transaction that has no entry in the `updated_transactions`, + // we store last validation result (i.e. the pool entry) in txs_to_resubmit + let mut initial_statuses = HashMap::new(); + let mut txs_to_resubmit = Vec::with_capacity(updated_transactions.len()); + while !updated_transactions.is_empty() { + let hash = updated_transactions.keys().next().cloned().expect("transactions is not empty; qed"); + + // note we are not considering tx with hash invalid here - we just want + // to remove it along with dependent transactions and `remove_subtree()` + // does exactly what we need + let removed = pool.remove_subtree(&[hash.clone()]); + for removed_tx in removed { + let removed_hash = removed_tx.hash.clone(); + let updated_transaction = updated_transactions.remove(&removed_hash); + let tx_to_resubmit = if let Some(updated_tx) = updated_transaction { + updated_tx + } else { + // in most cases we'll end up in successful `try_unwrap`, but if not + // we still need to reinsert transaction back to the pool => duplicate call + let transaction = match Arc::try_unwrap(removed_tx) { + Ok(transaction) => transaction, + Err(transaction) => transaction.duplicate(), + }; + ValidatedTransaction::Valid(transaction) + }; + + initial_statuses.insert(removed_hash.clone(), Status::Ready); + txs_to_resubmit.push((removed_hash, tx_to_resubmit)); + } + // make sure to remove the hash even if it's not present in the pool any more. + updated_transactions.remove(&hash); + } + + // if we're rejecting future transactions, then insertion order matters here: + // if tx1 depends on tx2, then if tx1 is inserted before tx2, then it goes + // to the future queue and gets rejected immediately + // => let's temporary stop rejection and clear future queue before return + pool.with_futures_enabled(|pool, reject_future_transactions| { + // now resubmit all removed transactions back to the pool + let mut final_statuses = HashMap::new(); + for (hash, tx_to_resubmit) in txs_to_resubmit { + match tx_to_resubmit { + ValidatedTransaction::Valid(tx) => match pool.import(tx) { + Ok(imported) => match imported { + base::Imported::Ready { promoted, failed, removed, .. } => { + final_statuses.insert(hash, Status::Ready); + for hash in promoted { + final_statuses.insert(hash, Status::Ready); + } + for hash in failed { + final_statuses.insert(hash, Status::Failed); + } + for tx in removed { + final_statuses.insert(tx.hash.clone(), Status::Dropped); + } + }, + base::Imported::Future { .. } => { + final_statuses.insert(hash, Status::Future); + }, + }, + Err(err) => { + // we do not want to fail if single transaction import has failed + // nor we do want to propagate this error, because it could tx unknown to caller + // => let's just notify listeners (and issue debug message) + warn!( + target: "txpool", + "[{:?}] Removing invalid transaction from update: {}", + hash, + err, + ); + final_statuses.insert(hash, Status::Failed); + }, + }, + ValidatedTransaction::Invalid(_, _) | ValidatedTransaction::Unknown(_, _) => { + final_statuses.insert(hash, Status::Failed); + }, + } + } + + // if the pool is configured to reject future transactions, let's clear the future + // queue, updating final statuses as required + if reject_future_transactions { + for future_tx in pool.clear_future() { + final_statuses.insert(future_tx.hash.clone(), Status::Dropped); + } + } + + (initial_statuses, final_statuses) + }) + }; + + // and now let's notify listeners about status changes + let mut listener = self.listener.write(); + for (hash, final_status) in final_statuses { + let initial_status = initial_statuses.remove(&hash); + if initial_status.is_none() || Some(final_status) != initial_status { + match final_status { + Status::Future => listener.future(&hash), + Status::Ready => listener.ready(&hash, None), + Status::Dropped => listener.dropped(&hash, None), + Status::Failed => listener.invalid(&hash, initial_status.is_some()), + } + } + } + } + + /// For each extrinsic, returns tags that it provides (if known), or None (if it is unknown). + pub fn extrinsics_tags(&self, hashes: &[ExHash]) -> Vec>> { + self.pool.read().by_hash(&hashes) + .into_iter() + .map(|existing_in_pool| existing_in_pool + .map(|transaction| transaction.provides.iter().cloned() + .collect())) + .collect() + } + + /// Prunes ready transactions that provide given list of tags. + pub fn prune_tags( + &self, + tags: impl IntoIterator, + ) -> Result, ExtrinsicFor>, B::Error> { + // Perform tag-based pruning in the base pool + let status = self.pool.write().prune_tags(tags); + // Notify event listeners of all transactions + // that were promoted to `Ready` or were dropped. + { + let mut listener = self.listener.write(); + for promoted in &status.promoted { + fire_events(&mut *listener, promoted); + } + for f in &status.failed { + listener.dropped(f, None); + } + } + + Ok(status) + } + + /// Resubmit transactions that have been revalidated after prune_tags call. + pub fn resubmit_pruned( + &self, + at: &BlockId, + known_imported_hashes: impl IntoIterator> + Clone, + pruned_hashes: Vec>, + pruned_xts: Vec>, + ) -> Result<(), B::Error> { + debug_assert_eq!(pruned_hashes.len(), pruned_xts.len()); + + // Resubmit pruned transactions + let results = self.submit(pruned_xts); + + // Collect the hashes of transactions that now became invalid (meaning that they are successfully pruned). + let hashes = results + .into_iter() + .enumerate() + .filter_map(|(idx, r)| match r.map_err(error::IntoPoolError::into_pool_error) { + Err(Ok(error::Error::InvalidTransaction(_))) => Some(pruned_hashes[idx].clone()), + _ => None, + }); + // Fire `pruned` notifications for collected hashes and make sure to include + // `known_imported_hashes` since they were just imported as part of the block. + let hashes = hashes.chain(known_imported_hashes.into_iter()); + self.fire_pruned(at, hashes)?; + + // perform regular cleanup of old transactions in the pool + // and update temporary bans. + self.clear_stale(at)?; + Ok(()) + } + + /// Fire notifications for pruned transactions. + pub fn fire_pruned( + &self, + at: &BlockId, + hashes: impl Iterator>, + ) -> Result<(), B::Error> { + let header_hash = self.api.block_id_to_hash(at)? + .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())?; + let mut listener = self.listener.write(); + for h in hashes { + listener.pruned(header_hash, &h); + } + Ok(()) + } + + /// Removes stale transactions from the pool. + /// + /// Stale transactions are transaction beyond their longevity period. + /// Note this function does not remove transactions that are already included in the chain. + /// See `prune_tags` if you want this. + pub fn clear_stale(&self, at: &BlockId) -> Result<(), B::Error> { + let block_number = self.api.block_id_to_number(at)? + .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())? + .saturated_into::(); + let now = time::Instant::now(); + let to_remove = { + self.ready() + .filter(|tx| self.rotator.ban_if_stale(&now, block_number, &tx)) + .map(|tx| tx.hash.clone()) + .collect::>() + }; + let futures_to_remove: Vec> = { + let p = self.pool.read(); + let mut hashes = Vec::new(); + for tx in p.futures() { + if self.rotator.ban_if_stale(&now, block_number, &tx) { + hashes.push(tx.hash.clone()); + } + } + hashes + }; + // removing old transactions + self.remove_invalid(&to_remove); + self.remove_invalid(&futures_to_remove); + // clear banned transactions timeouts + self.rotator.clear_timeouts(&now); + + Ok(()) + } + + /// Get rotator reference. + #[cfg(test)] + pub fn rotator(&self) -> &PoolRotator> { + &self.rotator + } + + /// Get api reference. + pub fn api(&self) -> &B { + &self.api + } + + /// Return an event stream of transactions imported to the pool. + pub fn import_notification_stream(&self) -> EventStream { + let (sink, stream) = mpsc::unbounded(); + self.import_notification_sinks.lock().push(sink); + stream + } + + /// Invoked when extrinsics are broadcasted. + pub fn on_broadcasted(&self, propagated: HashMap, Vec>) { + let mut listener = self.listener.write(); + for (hash, peers) in propagated.into_iter() { + listener.broadcasted(&hash, peers); + } + } + + /// Remove a subtree of transactions from the pool and mark them invalid. + /// + /// The transactions passed as an argument will be additionally banned + /// to prevent them from entering the pool right away. + /// Note this is not the case for the dependent transactions - those may + /// still be valid so we want to be able to re-import them. + pub fn remove_invalid(&self, hashes: &[ExHash]) -> Vec> { + // early exit in case there is no invalid transactions. + if hashes.is_empty() { + return vec![] + } + + // temporarily ban invalid transactions + debug!(target: "txpool", "Banning invalid transactions: {:?}", hashes); + self.rotator.ban(&time::Instant::now(), hashes.iter().cloned()); + + let invalid = self.pool.write().remove_subtree(hashes); + + let mut listener = self.listener.write(); + for tx in &invalid { + listener.invalid(&tx.hash, true); + } + + invalid + } + + /// Get an iterator for ready transactions ordered by priority + pub fn ready(&self) -> impl Iterator> { + self.pool.read().ready() + } + + /// Returns pool status. + pub fn status(&self) -> PoolStatus { + self.pool.read().status() + } +} + +fn fire_events( + listener: &mut Listener, + imported: &base::Imported, +) where + H: hash::Hash + Eq + traits::Member + Serialize, + H2: Clone + fmt::Debug, +{ + match *imported { + base::Imported::Ready { ref promoted, ref failed, ref removed, ref hash } => { + listener.ready(hash, None); + for f in failed { + listener.invalid(f, true); + } + for r in removed { + listener.dropped(&r.hash, Some(hash)); + } + for p in promoted { + listener.ready(p, None); + } + }, + base::Imported::Future { ref hash } => { + listener.future(hash) + }, + } +} diff --git a/client/transaction-pool/graph/src/watcher.rs b/client/transaction-pool/graph/src/watcher.rs new file mode 100644 index 0000000000000..f9c234f73c3b8 --- /dev/null +++ b/client/transaction-pool/graph/src/watcher.rs @@ -0,0 +1,123 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Extrinsics status updates. + +use futures::{ + Stream, + channel::mpsc, +}; +use sp_transaction_pool::TransactionStatus; + +/// Extrinsic watcher. +/// +/// Represents a stream of status updates for particular extrinsic. +#[derive(Debug)] +pub struct Watcher { + receiver: mpsc::UnboundedReceiver>, + hash: H, +} + +impl Watcher { + /// Returns the transaction hash. + pub fn hash(&self) -> &H { + &self.hash + } + + /// Pipe the notifications to given sink. + /// + /// Make sure to drive the future to completion. + pub fn into_stream(self) -> impl Stream> { + self.receiver + } +} + +/// Sender part of the watcher. Exposed only for testing purposes. +#[derive(Debug)] +pub struct Sender { + receivers: Vec>>, + finalized: bool, +} + +impl Default for Sender { + fn default() -> Self { + Sender { + receivers: Default::default(), + finalized: false, + } + } +} + +impl Sender { + /// Add a new watcher to this sender object. + pub fn new_watcher(&mut self, hash: H) -> Watcher { + let (tx, receiver) = mpsc::unbounded(); + self.receivers.push(tx); + Watcher { + receiver, + hash, + } + } + + /// Transaction became ready. + pub fn ready(&mut self) { + self.send(TransactionStatus::Ready) + } + + /// Transaction was moved to future. + pub fn future(&mut self) { + self.send(TransactionStatus::Future) + } + + /// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid. + pub fn usurped(&mut self, hash: H) { + self.send(TransactionStatus::Usurped(hash)); + self.finalized = true; + } + + /// Extrinsic has been included in block with given hash. + pub fn in_block(&mut self, hash: H2) { + self.send(TransactionStatus::InBlock(hash)); + self.finalized = true; + } + + /// Extrinsic has been marked as invalid by the block builder. + pub fn invalid(&mut self) { + self.send(TransactionStatus::Invalid); + // we mark as finalized as there are no more notifications + self.finalized = true; + } + + /// Transaction has been dropped from the pool because of the limit. + pub fn dropped(&mut self) { + self.send(TransactionStatus::Dropped); + self.finalized = true; + } + + /// The extrinsic has been broadcast to the given peers. + pub fn broadcast(&mut self, peers: Vec) { + self.send(TransactionStatus::Broadcast(peers)) + } + + /// Returns true if the are no more listeners for this extrinsic or it was finalized. + pub fn is_done(&self) -> bool { + self.finalized || self.receivers.is_empty() + } + + fn send(&mut self, status: TransactionStatus) { + self.receivers.retain(|sender| sender.unbounded_send(status.clone()).is_ok()) + } +} diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs new file mode 100644 index 0000000000000..8495b8b65f17b --- /dev/null +++ b/client/transaction-pool/src/api.rs @@ -0,0 +1,200 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Chain api required for the transaction pool. + +use std::{marker::PhantomData, pin::Pin, sync::Arc}; +use codec::{Decode, Encode}; +use futures::{ + channel::oneshot, executor::{ThreadPool, ThreadPoolBuilder}, future::{Future, FutureExt, ready}, +}; + +use sc_client_api::{ + blockchain::HeaderBackend, + light::{Fetcher, RemoteCallRequest} +}; +use sp_core::Hasher; +use sp_runtime::{ + generic::BlockId, traits::{self, Block as BlockT, BlockIdTo, Header as HeaderT, Hash as HashT}, + transaction_validity::TransactionValidity, +}; +use sp_transaction_pool::runtime_api::TaggedTransactionQueue; +use sp_api::ProvideRuntimeApi; + +use crate::error::{self, Error}; + +/// The transaction pool logic for full client. +pub struct FullChainApi { + client: Arc, + pool: ThreadPool, + _marker: PhantomData, +} + +impl FullChainApi where + Block: BlockT, + Client: ProvideRuntimeApi + BlockIdTo, +{ + /// Create new transaction pool logic. + pub fn new(client: Arc) -> Self { + FullChainApi { + client, + pool: ThreadPoolBuilder::new() + .pool_size(2) + .name_prefix("txpool-verifier") + .create() + .expect("Failed to spawn verifier threads, that are critical for node operation."), + _marker: Default::default() + } + } +} + +impl sc_transaction_graph::ChainApi for FullChainApi where + Block: BlockT, + Client: ProvideRuntimeApi + BlockIdTo + 'static + Send + Sync, + Client::Api: TaggedTransactionQueue, + sp_api::ApiErrorFor: Send, +{ + type Block = Block; + type Hash = Block::Hash; + type Error = error::Error; + type ValidationFuture = Pin> + Send>>; + + fn validate_transaction( + &self, + at: &BlockId, + uxt: sc_transaction_graph::ExtrinsicFor, + ) -> Self::ValidationFuture { + let (tx, rx) = oneshot::channel(); + let client = self.client.clone(); + let at = at.clone(); + + self.pool.spawn_ok(async move { + let res = client.runtime_api().validate_transaction(&at, uxt) + .map_err(|e| Error::RuntimeApi(format!("{:?}", e))); + if let Err(e) = tx.send(res) { + log::warn!("Unable to send a validate transaction result: {:?}", e); + } + }); + + Box::pin(async move { + match rx.await { + Ok(r) => r, + Err(_) => Err(Error::RuntimeApi("Validation was canceled".into())), + } + }) + } + + fn block_id_to_number( + &self, + at: &BlockId, + ) -> error::Result>> { + self.client.to_number(at).map_err(|e| Error::BlockIdConversion(format!("{:?}", e))) + } + + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> error::Result>> { + self.client.to_hash(at).map_err(|e| Error::BlockIdConversion(format!("{:?}", e))) + } + + fn hash_and_length(&self, ex: &sc_transaction_graph::ExtrinsicFor) -> (Self::Hash, usize) { + ex.using_encoded(|x| { + (traits::HasherFor::::hash(x), x.len()) + }) + } +} + +/// The transaction pool logic for light client. +pub struct LightChainApi { + client: Arc, + fetcher: Arc, + _phantom: PhantomData, +} + +impl LightChainApi where + Block: BlockT, + Client: HeaderBackend, + F: Fetcher, +{ + /// Create new transaction pool logic. + pub fn new(client: Arc, fetcher: Arc) -> Self { + LightChainApi { + client, + fetcher, + _phantom: Default::default(), + } + } +} + +impl sc_transaction_graph::ChainApi for LightChainApi where + Block: BlockT, + Client: HeaderBackend + 'static, + F: Fetcher + 'static, +{ + type Block = Block; + type Hash = Block::Hash; + type Error = error::Error; + type ValidationFuture = Box> + Send + Unpin>; + + fn validate_transaction( + &self, + at: &BlockId, + uxt: sc_transaction_graph::ExtrinsicFor, + ) -> Self::ValidationFuture { + let header_hash = self.client.expect_block_hash_from_id(at); + let header_and_hash = header_hash + .and_then(|header_hash| self.client.expect_header(BlockId::Hash(header_hash)) + .map(|header| (header_hash, header))); + let (block, header) = match header_and_hash { + Ok((header_hash, header)) => (header_hash, header), + Err(err) => return Box::new(ready(Err(err.into()))), + }; + let remote_validation_request = self.fetcher.remote_call(RemoteCallRequest { + block, + header, + method: "TaggedTransactionQueue_validate_transaction".into(), + call_data: uxt.encode(), + retry_count: None, + }); + let remote_validation_request = remote_validation_request.then(move |result| { + let result: error::Result = result + .map_err(Into::into) + .and_then(|result| Decode::decode(&mut &result[..]) + .map_err(|e| Error::RuntimeApi( + format!("Error decoding tx validation result: {:?}", e) + )) + ); + ready(result) + }); + + Box::new(remote_validation_request) + } + + fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { + Ok(self.client.block_number_from_id(at)?) + } + + fn block_id_to_hash(&self, at: &BlockId) -> error::Result>> { + Ok(self.client.block_hash_from_id(at)?) + } + + fn hash_and_length(&self, ex: &sc_transaction_graph::ExtrinsicFor) -> (Self::Hash, usize) { + ex.using_encoded(|x| { + (<::Hashing as HashT>::hash(x), x.len()) + }) + } +} diff --git a/client/transaction-pool/src/error.rs b/client/transaction-pool/src/error.rs new file mode 100644 index 0000000000000..fa48b387c41d8 --- /dev/null +++ b/client/transaction-pool/src/error.rs @@ -0,0 +1,57 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Transaction pool error. + +use sp_transaction_pool::error::Error as TxPoolError; + +/// Transaction pool result. +pub type Result = std::result::Result; + +/// Transaction pool error type. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Pool error. + Pool(TxPoolError), + /// Blockchain error. + Blockchain(sp_blockchain::Error), + /// Error while converting a `BlockId`. + #[from(ignore)] + BlockIdConversion(String), + /// Error while calling the runtime api. + #[from(ignore)] + RuntimeApi(String), +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Pool(ref err) => Some(err), + Error::Blockchain(ref err) => Some(err), + Error::BlockIdConversion(_) => None, + Error::RuntimeApi(_) => None, + } + } +} + +impl sp_transaction_pool::error::IntoPoolError for Error { + fn into_pool_error(self) -> std::result::Result { + match self { + Error::Pool(e) => Ok(e), + e => Err(e), + } + } +} diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs new file mode 100644 index 0000000000000..4d71307c0abd0 --- /dev/null +++ b/client/transaction-pool/src/lib.rs @@ -0,0 +1,132 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate transaction pool implementation. + +#![warn(missing_docs)] +#![warn(unused_extern_crates)] + +mod api; +mod maintainer; + +pub mod error; +#[cfg(test)] +mod tests; + +pub use sc_transaction_graph as txpool; +pub use crate::api::{FullChainApi, LightChainApi}; +pub use crate::maintainer::{FullBasicPoolMaintainer, LightBasicPoolMaintainer}; + +use std::{collections::HashMap, sync::Arc}; +use futures::{Future, FutureExt}; + +use sp_runtime::{ + generic::BlockId, + traits::Block as BlockT, +}; +use sp_transaction_pool::{ + TransactionPool, PoolStatus, ImportNotificationStream, + TxHash, TransactionFor, TransactionStatusStreamFor, +}; + +/// Basic implementation of transaction pool that can be customized by providing PoolApi. +pub struct BasicPool + where + Block: BlockT, + PoolApi: sc_transaction_graph::ChainApi, +{ + pool: Arc>, +} + +impl BasicPool + where + Block: BlockT, + PoolApi: sc_transaction_graph::ChainApi, +{ + /// Create new basic transaction pool with provided api. + pub fn new(options: sc_transaction_graph::Options, pool_api: PoolApi) -> Self { + BasicPool { + pool: Arc::new(sc_transaction_graph::Pool::new(options, pool_api)), + } + } + + /// Gets shared reference to the underlying pool. + pub fn pool(&self) -> &Arc> { + &self.pool + } +} + +impl TransactionPool for BasicPool + where + Block: BlockT, + PoolApi: 'static + sc_transaction_graph::ChainApi, +{ + type Block = PoolApi::Block; + type Hash = sc_transaction_graph::ExHash; + type InPoolTransaction = sc_transaction_graph::base_pool::Transaction, TransactionFor>; + type Error = error::Error; + + fn submit_at( + &self, + at: &BlockId, + xts: impl IntoIterator> + 'static, + ) -> Box, Self::Error>>, Self::Error>> + Send + Unpin> { + Box::new(self.pool.submit_at(at, xts, false)) + } + + fn submit_one( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box, Self::Error>> + Send + Unpin> { + Box::new(self.pool.submit_one(at, xt)) + } + + fn submit_and_watch( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box>, Self::Error>> + Send + Unpin> { + Box::new( + self.pool.submit_and_watch(at, xt) + .map(|result| result.map(|watcher| Box::new(watcher.into_stream()) as _)) + ) + } + + fn remove_invalid(&self, hashes: &[TxHash]) -> Vec> { + self.pool.remove_invalid(hashes) + } + + fn status(&self) -> PoolStatus { + self.pool.status() + } + + fn ready(&self) -> Box>> { + Box::new(self.pool.ready()) + } + + fn import_notification_stream(&self) -> ImportNotificationStream { + self.pool.import_notification_stream() + } + + fn hash_of(&self, xt: &TransactionFor) -> TxHash { + self.pool.hash_of(xt) + } + + fn on_broadcasted(&self, propagations: HashMap, Vec>) { + self.pool.on_broadcasted(propagations) + } +} diff --git a/client/transaction-pool/src/maintainer.rs b/client/transaction-pool/src/maintainer.rs new file mode 100644 index 0000000000000..97dc7e10a6f11 --- /dev/null +++ b/client/transaction-pool/src/maintainer.rs @@ -0,0 +1,645 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{ + marker::{PhantomData, Unpin}, + sync::Arc, + time::Instant, +}; +use futures::{ + Future, FutureExt, + future::{Either, join, ready}, +}; +use log::{warn, debug, trace}; +use parking_lot::Mutex; + +use sc_client_api::{ + client::BlockBody, + light::{Fetcher, RemoteBodyRequest}, +}; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, Extrinsic, Header, NumberFor, SimpleArithmetic}, +}; +use sp_blockchain::HeaderBackend; +use sp_transaction_pool::{TransactionPoolMaintainer, runtime_api::TaggedTransactionQueue}; +use sp_api::ProvideRuntimeApi; + +use sc_transaction_graph::{self, ChainApi}; + +/// Basic transaction pool maintainer for full clients. +pub struct FullBasicPoolMaintainer { + pool: Arc>, + client: Arc, +} + +impl FullBasicPoolMaintainer { + /// Create new basic full pool maintainer. + pub fn new( + pool: Arc>, + client: Arc, + ) -> Self { + FullBasicPoolMaintainer { pool, client } + } +} + +impl TransactionPoolMaintainer +for + FullBasicPoolMaintainer +where + Block: BlockT, + Client: ProvideRuntimeApi + HeaderBackend + BlockBody + 'static, + Client::Api: TaggedTransactionQueue, + PoolApi: ChainApi + 'static, +{ + type Block = Block; + type Hash = Block::Hash; + + fn maintain( + &self, + id: &BlockId, + retracted: &[Block::Hash], + ) -> Box + Send + Unpin> { + let now = std::time::Instant::now(); + let took = move || format!("Took {} ms", now.elapsed().as_millis()); + + let id = *id; + trace!(target: "txpool", "[{:?}] Starting pool maintainance", id); + // Put transactions from retracted blocks back into the pool. + let client_copy = self.client.clone(); + let retracted_transactions = retracted.to_vec().into_iter() + .filter_map(move |hash| client_copy.block_body(&BlockId::hash(hash)).ok().unwrap_or(None)) + .flat_map(|block| block.into_iter()) + // if signed information is not present, attempt to resubmit anyway. + .filter(|tx| tx.is_signed().unwrap_or(true)); + let resubmit_future = self.pool + .submit_at(&id, retracted_transactions, true) + .then(move |resubmit_result| ready(match resubmit_result { + Ok(_) => trace!(target: "txpool", + "[{:?}] Re-submitting retracted done. {}", id, took() + ), + Err(e) => debug!(target: "txpool", + "[{:?}] Error re-submitting transactions: {:?}", id, e + ), + })); + + // Avoid calling into runtime if there is nothing to prune from the pool anyway. + if self.pool.status().is_empty() { + return Box::new(resubmit_future) + } + + let block = (self.client.header(id), self.client.block_body(&id)); + let prune_future = match block { + (Ok(Some(header)), Ok(Some(extrinsics))) => { + let parent_id = BlockId::hash(*header.parent_hash()); + let prune_future = self.pool + .prune(&id, &parent_id, &extrinsics) + .then(move |prune_result| ready(match prune_result { + Ok(_) => trace!(target: "txpool", + "[{:?}] Pruning done. {}", id, took() + ), + Err(e) => warn!(target: "txpool", + "[{:?}] Error pruning transactions: {:?}", id, e + ), + })); + + Either::Left(resubmit_future.then(|_| prune_future)) + }, + (Ok(_), Ok(_)) => Either::Right(resubmit_future), + err => { + warn!(target: "txpool", "[{:?}] Error reading block: {:?}", id, err); + Either::Right(resubmit_future) + }, + }; + + let revalidate_future = self.pool + .revalidate_ready(&id, Some(16)) + .then(move |result| ready(match result { + Ok(_) => debug!(target: "txpool", + "[{:?}] Revalidation done: {}", id, took() + ), + Err(e) => warn!(target: "txpool", + "[{:?}] Encountered errors while revalidating transactions: {:?}", id, e + ), + })); + + Box::new(prune_future.then(|_| revalidate_future)) + } +} + +/// Basic transaction pool maintainer for light clients. +pub struct LightBasicPoolMaintainer { + pool: Arc>, + client: Arc, + fetcher: Arc, + revalidate_time_period: Option, + revalidate_block_period: Option>, + revalidation_status: Arc>>>, + _phantom: PhantomData, +} + +impl LightBasicPoolMaintainer + where + Block: BlockT, + Client: ProvideRuntimeApi + HeaderBackend + BlockBody + 'static, + Client::Api: TaggedTransactionQueue, + PoolApi: ChainApi + 'static, + F: Fetcher + 'static, +{ + /// Create light pool maintainer with default constants. + /// + /// Default constants are: revalidate every 60 seconds or every 20 blocks + /// (whatever happens first). + pub fn with_defaults( + pool: Arc>, + client: Arc, + fetcher: Arc, + ) -> Self { + Self::new( + pool, + client, + fetcher, + Some(std::time::Duration::from_secs(60)), + Some(20.into()), + ) + } + + /// Create light pool maintainer with passed constants. + pub fn new( + pool: Arc>, + client: Arc, + fetcher: Arc, + revalidate_time_period: Option, + revalidate_block_period: Option>, + ) -> Self { + Self { + pool, + client, + fetcher, + revalidate_time_period, + revalidate_block_period, + revalidation_status: Arc::new(Mutex::new(TxPoolRevalidationStatus::NotScheduled)), + _phantom: Default::default(), + } + } + + /// Returns future that prunes block transactions from the pool. + fn prune( + &self, + id: &BlockId, + header: &Block::Header, + ) -> impl std::future::Future { + // fetch transactions (possible future optimization: proofs of inclusion) that + // have been included into new block and prune these from the pool + let id = id.clone(); + let pool = self.pool.clone(); + self.fetcher.remote_body(RemoteBodyRequest { + header: header.clone(), + retry_count: None, + }) + .then(move |transactions| ready( + transactions + .map_err(|e| format!("{}", e)) + .and_then(|transactions| { + let hashes = transactions + .into_iter() + .map(|tx| pool.hash_of(&tx)) + .collect::>(); + pool.prune_known(&id, &hashes) + .map_err(|e| format!("{}", e)) + }) + )) + .then(|r| { + if let Err(e) = r { + warn!("Error pruning known transactions: {}", e) + } + ready(()) + }) + } + + /// Returns future that performs in-pool transations revalidation, if required. + fn revalidate( + &self, + id: &BlockId, + header: &Block::Header, + ) -> impl std::future::Future { + // to determine whether ready transaction is still valid, we perform periodic revalidaton + // of ready transactions + let is_revalidation_required = self.revalidation_status.lock().is_required( + *header.number(), + self.revalidate_time_period, + self.revalidate_block_period, + ); + match is_revalidation_required { + true => { + let revalidation_status = self.revalidation_status.clone(); + Either::Left(self.pool + .revalidate_ready(id, None) + .map(|r| r.map_err(|e| warn!("Error revalidating known transactions: {}", e))) + .map(move |_| revalidation_status.lock().clear())) + }, + false => Either::Right(ready(())), + } + } +} + +impl TransactionPoolMaintainer +for + LightBasicPoolMaintainer +where + Block: BlockT, + Client: ProvideRuntimeApi + HeaderBackend + BlockBody + 'static, + Client::Api: TaggedTransactionQueue, + PoolApi: ChainApi + 'static, + F: Fetcher + 'static, +{ + type Block = Block; + type Hash = Block::Hash; + + fn maintain( + &self, + id: &BlockId, + _retracted: &[Block::Hash], + ) -> Box + Send + Unpin> { + // Do nothing if transaction pool is empty. + if self.pool.status().is_empty() { + self.revalidation_status.lock().clear(); + return Box::new(ready(())); + } + let header = self.client.header(*id) + .and_then(|h| h.ok_or(sp_blockchain::Error::UnknownBlock(format!("{}", id)))); + let header = match header { + Ok(header) => header, + Err(err) => { + println!("Failed to maintain light tx pool: {:?}", err); + return Box::new(ready(())); + } + }; + + // else prune block transactions from the pool + let prune_future = self.prune(id, &header); + + // and then (optionally) revalidate in-pool transactions + let revalidate_future = self.revalidate(id, &header); + + let maintain_future = join( + prune_future, + revalidate_future, + ).map(|_| ()); + + Box::new(maintain_future) + } +} + +/// The status of transactions revalidation at light tx pool. +#[cfg_attr(test, derive(Debug))] +enum TxPoolRevalidationStatus { + /// The revalidation has never been completed. + NotScheduled, + /// The revalidation is scheduled. + Scheduled(Option, Option), + /// The revalidation is in progress. + InProgress, +} + +impl TxPoolRevalidationStatus { + /// Called when revalidation is completed. + pub fn clear(&mut self) { + *self = TxPoolRevalidationStatus::NotScheduled; + } + + /// Returns true if revalidation is required. + pub fn is_required( + &mut self, + block: N, + revalidate_time_period: Option, + revalidate_block_period: Option, + ) -> bool { + match *self { + TxPoolRevalidationStatus::NotScheduled => { + *self = TxPoolRevalidationStatus::Scheduled( + revalidate_time_period.map(|period| Instant::now() + period), + revalidate_block_period.map(|period| block + period), + ); + false + }, + TxPoolRevalidationStatus::Scheduled(revalidate_at_time, revalidate_at_block) => { + let is_required = revalidate_at_time.map(|at| Instant::now() >= at).unwrap_or(false) + || revalidate_at_block.map(|at| block >= at).unwrap_or(false); + if is_required { + *self = TxPoolRevalidationStatus::InProgress; + } + is_required + }, + TxPoolRevalidationStatus::InProgress => false, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures::executor::block_on; + use codec::Encode; + use substrate_test_runtime_client::{ + prelude::*, Client, runtime::{Block, Transfer}, sp_consensus::{BlockOrigin, SelectChain}, + LongestChain, + }; + use sp_transaction_pool::PoolStatus; + use crate::api::{FullChainApi, LightChainApi}; + + struct TestSetup { + client: Arc>, + longest_chain: LongestChain, + pool: Arc>, + } + + impl TestSetup { + fn new() -> TestSetup, Block>> { + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = Arc::new( + sc_transaction_graph::Pool::new(Default::default(), FullChainApi::new(client.clone())), + ); + TestSetup { + client, + longest_chain, + pool, + } + } + + fn new_light(fetcher: Arc) -> TestSetup, F, Block>> + where F: Fetcher + 'static, + { + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = Arc::new( + sc_transaction_graph::Pool::new( + Default::default(), + LightChainApi::new(client.clone(), fetcher) + ), + ); + TestSetup { + client, + longest_chain, + pool, + } + } + } + + fn setup() -> TestSetup, Block>> { + TestSetup::, Block>>::new() + } + + fn setup_light(fetcher: Arc) -> TestSetup, F, Block>> + where F: Fetcher + 'static, + { + TestSetup::, F, Block>>::new_light(fetcher) + } + + #[test] + fn should_remove_transactions_from_the_full_pool() { + let mut setup = setup(); + + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + let best = setup.longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(setup.pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + + // import the block + let mut builder = setup.client.new_block(Default::default()).unwrap(); + builder.push(transaction.clone()).unwrap(); + let block = builder.build().unwrap().block; + let id = BlockId::hash(block.header().hash()); + setup.client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(setup.pool.status().ready, 1); + block_on(FullBasicPoolMaintainer::new(setup.pool.clone(), setup.client.clone()).maintain(&id, &[])); + + // then + assert_eq!(setup.pool.status().ready, 0); + assert_eq!(setup.pool.status().future, 0); + } + + #[test] + fn should_remove_transactions_from_the_light_pool() { + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + let fetcher_transaction = transaction.clone(); + let fetcher = Arc::new(substrate_test_runtime_client::new_light_fetcher() + .with_remote_body(Some(Box::new(move |_| Ok(vec![fetcher_transaction.clone()])))) + .with_remote_call(Some(Box::new(move |_| { + let validity: sp_runtime::transaction_validity::TransactionValidity = + Ok(sp_runtime::transaction_validity::ValidTransaction { + priority: 0, + requires: Vec::new(), + provides: vec![vec![42]], + longevity: 0, + propagate: true, + }); + Ok(validity.encode()) + })))); + + let setup = setup_light(fetcher.clone()); + let best = setup.longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(setup.pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(setup.pool.status().ready, 1); + block_on(LightBasicPoolMaintainer::with_defaults(setup.pool.clone(), setup.client.clone(), fetcher).maintain( + &BlockId::Number(0), + &[], + )); + + // then + assert_eq!(setup.pool.status().ready, 0); + assert_eq!(setup.pool.status().future, 0); + } + + #[test] + fn should_schedule_transactions_revalidation_at_light_pool() { + // when revalidation is not scheduled, it became scheduled + let mut status = TxPoolRevalidationStatus::NotScheduled; + assert!(!status.is_required(10u32, None, None)); + match status { + TxPoolRevalidationStatus::Scheduled(_, _) => (), + _ => panic!("Unexpected status: {:?}", status), + } + + // revalidation required at time + let mut status = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None); + assert!(status.is_required(10u32, None, None)); + match status { + TxPoolRevalidationStatus::InProgress => (), + _ => panic!("Unexpected status: {:?}", status), + } + + // revalidation required at block + let mut status = TxPoolRevalidationStatus::Scheduled(None, Some(10)); + assert!(status.is_required(10u32, None, None)); + match status { + TxPoolRevalidationStatus::InProgress => (), + _ => panic!("Unexpected status: {:?}", status), + } + } + + #[test] + fn should_revalidate_transactions_at_light_pool() { + use std::sync::atomic; + use sp_runtime::transaction_validity::*; + + let build_fetcher = || { + let validated = Arc::new(atomic::AtomicBool::new(false)); + Arc::new(substrate_test_runtime_client::new_light_fetcher() + .with_remote_body(Some(Box::new(move |_| Ok(vec![])))) + .with_remote_call(Some(Box::new(move |_| { + let is_inserted = validated.swap(true, atomic::Ordering::SeqCst); + let validity: TransactionValidity = if is_inserted { + Err(TransactionValidityError::Invalid( + InvalidTransaction::Custom(0) + )) + } else { + Ok(ValidTransaction { + priority: 0, + requires: Vec::new(), + provides: vec![vec![42]], + longevity: 0, + propagate: true, + }) + }; + Ok(validity.encode()) + })))) + }; + + fn with_fetcher_maintain + 'static>( + fetcher: Arc, + revalidate_time_period: Option, + revalidate_block_period: Option, + prepare_maintainer: impl Fn(&Mutex>), + ) -> PoolStatus { + let setup = setup_light(fetcher.clone()); + let best = setup.longest_chain.best_chain().unwrap(); + + // let's prepare maintainer + let maintainer = LightBasicPoolMaintainer::new( + setup.pool.clone(), + setup.client.clone(), + fetcher, + revalidate_time_period, + revalidate_block_period, + ); + prepare_maintainer(&*maintainer.revalidation_status); + + // store the transaction in the pool + block_on(setup.pool.submit_one( + &BlockId::hash(best.hash()), + Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(), + )).unwrap(); + + // and run maintain procedures + block_on(maintainer.maintain(&BlockId::Number(0), &[])); + + setup.pool.status() + } + + // when revalidation is never required - nothing happens + let fetcher = build_fetcher(); + //let maintainer = DefaultLightTransactionPoolMaintainer::new(client.clone(), fetcher.clone(), None, None); + let status = with_fetcher_maintain(fetcher, None, None, |_revalidation_status| {}); + assert_eq!(status.ready, 1); + + // when revalidation is scheduled by time - it is performed + let fetcher = build_fetcher(); + let status = with_fetcher_maintain(fetcher, None, None, |revalidation_status| + *revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(Some(Instant::now()), None) + ); + assert_eq!(status.ready, 0); + + // when revalidation is scheduled by block number - it is performed + let fetcher = build_fetcher(); + let status = with_fetcher_maintain(fetcher, None, None, |revalidation_status| + *revalidation_status.lock() = TxPoolRevalidationStatus::Scheduled(None, Some(0)) + ); + assert_eq!(status.ready, 0); + } + + #[test] + fn should_add_reverted_transactions_to_the_pool() { + let mut setup = setup(); + + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + let best = setup.longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(setup.pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + + // import the block + let mut builder = setup.client.new_block(Default::default()).unwrap(); + builder.push(transaction.clone()).unwrap(); + let block = builder.build().unwrap().block; + let block1_hash = block.header().hash(); + let id = BlockId::hash(block1_hash.clone()); + setup.client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(setup.pool.status().ready, 1); + block_on(FullBasicPoolMaintainer::new(setup.pool.clone(), setup.client.clone()).maintain(&id, &[])); + + // then + assert_eq!(setup.pool.status().ready, 0); + assert_eq!(setup.pool.status().future, 0); + + // import second block + let builder = setup.client.new_block_at( + &BlockId::hash(best.hash()), + Default::default(), + false, + ).unwrap(); + let block = builder.build().unwrap().block; + let id = BlockId::hash(block.header().hash()); + setup.client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should add the transaction back to the pool. + block_on(FullBasicPoolMaintainer::new(setup.pool.clone(), setup.client.clone()).maintain(&id, &[block1_hash])); + + // then + assert_eq!(setup.pool.status().ready, 1); + assert_eq!(setup.pool.status().future, 0); + } +} diff --git a/client/transaction-pool/src/tests.rs b/client/transaction-pool/src/tests.rs new file mode 100644 index 0000000000000..1199e41cf8740 --- /dev/null +++ b/client/transaction-pool/src/tests.rs @@ -0,0 +1,222 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + + +use super::*; + +use codec::Encode; +use futures::executor::block_on; +use sc_transaction_graph::{self, Pool}; +use substrate_test_runtime_client::{runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}, AccountKeyring::{self, *}}; +use sp_runtime::{ + generic::{self, BlockId}, + traits::{Hash as HashT, BlakeTwo256}, + transaction_validity::{TransactionValidity, ValidTransaction}, +}; + +struct TestApi { + pub modifier: Box, +} + +impl TestApi { + fn default() -> Self { + TestApi { + modifier: Box::new(|_| {}), + } + } +} + +impl sc_transaction_graph::ChainApi for TestApi { + type Block = Block; + type Hash = Hash; + type Error = error::Error; + type ValidationFuture = futures::future::Ready>; + + fn validate_transaction( + &self, + at: &BlockId, + uxt: sc_transaction_graph::ExtrinsicFor, + ) -> Self::ValidationFuture { + let expected = index(at); + let requires = if expected == uxt.transfer().nonce { + vec![] + } else { + vec![vec![uxt.transfer().nonce as u8 - 1]] + }; + let provides = vec![vec![uxt.transfer().nonce as u8]]; + + let mut validity = ValidTransaction { + priority: 1, + requires, + provides, + longevity: 64, + propagate: true, + }; + + (self.modifier)(&mut validity); + + futures::future::ready(Ok( + Ok(validity) + )) + } + + fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { + Ok(Some(number_of(at))) + } + + fn block_id_to_hash(&self, at: &BlockId) -> error::Result>> { + Ok(match at { + generic::BlockId::Hash(x) => Some(x.clone()), + _ => Some(Default::default()), + }) + } + + fn hash_and_length(&self, ex: &sc_transaction_graph::ExtrinsicFor) -> (Self::Hash, usize) { + let encoded = ex.encode(); + (BlakeTwo256::hash(&encoded), encoded.len()) + } + +} + +fn index(at: &BlockId) -> u64 { + 209 + number_of(at) +} + +fn number_of(at: &BlockId) -> u64 { + match at { + generic::BlockId::Number(n) => *n as u64, + _ => 0, + } +} + +fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic { + let transfer = Transfer { + from: who.into(), + to: AccountId::default(), + nonce, + amount: 1, + }; + let signature = transfer.using_encoded(|e| who.sign(e)); + Extrinsic::Transfer(transfer, signature.into()) +} + +fn pool() -> Pool { + Pool::new(Default::default(), TestApi::default()) +} + +#[test] +fn submission_should_work() { + let pool = pool(); + assert_eq!(209, index(&BlockId::number(0))); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); + + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, vec![209]); +} + +#[test] +fn multiple_submission_should_work() { + let pool = pool(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); + + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, vec![209, 210]); +} + +#[test] +fn early_nonce_should_be_culled() { + let pool = pool(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 208))).unwrap(); + + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, Vec::::new()); +} + +#[test] +fn late_nonce_should_be_queued() { + let pool = pool(); + + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, Vec::::new()); + + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, vec![209, 210]); +} + +#[test] +fn prune_tags_should_work() { + let pool = pool(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); + + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, vec![209, 210]); + + block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![])).unwrap(); + + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, vec![210]); +} + +#[test] +fn should_ban_invalid_transactions() { + let pool = pool(); + let uxt = uxt(Alice, 209); + let hash = block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap(); + pool.remove_invalid(&[hash]); + block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap_err(); + + // when + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, Vec::::new()); + + // then + block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap_err(); +} + +#[test] +fn should_correctly_prune_transactions_providing_more_than_one_tag() { + let mut api = TestApi::default(); + api.modifier = Box::new(|v: &mut ValidTransaction| { + v.provides.push(vec![155]); + }); + let pool = Pool::new(Default::default(), api); + let xt = uxt(Alice, 209); + block_on(pool.submit_one(&BlockId::number(0), xt.clone())).expect("1. Imported"); + assert_eq!(pool.status().ready, 1); + + // remove the transaction that just got imported. + block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![])).expect("1. Pruned"); + assert_eq!(pool.status().ready, 0); + // it's re-imported to future + assert_eq!(pool.status().future, 1); + + // so now let's insert another transaction that also provides the 155 + let xt = uxt(Alice, 211); + block_on(pool.submit_one(&BlockId::number(2), xt.clone())).expect("2. Imported"); + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 1); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, vec![211]); + + // prune it and make sure the pool is empty + block_on(pool.prune_tags(&BlockId::number(3), vec![vec![155]], vec![])).expect("2. Pruned"); + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 2); +} diff --git a/core/application-crypto/Cargo.toml b/core/application-crypto/Cargo.toml deleted file mode 100644 index 3a48446696058..0000000000000 --- a/core/application-crypto/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "substrate-application-crypto" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -description = "Provides facilities for generating application specific crypto wrapper types." - -[dependencies] -primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", optional = true, features = ["derive"] } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../sr-io", default-features = false } - -[dev-dependencies] -test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client" } -sr-primitives = { path = "../sr-primitives" } - -[features] -default = [ "std" ] -std = [ "primitives/std", "codec/std", "serde", "rstd/std", "runtime-io/std" ] diff --git a/core/application-crypto/src/ed25519.rs b/core/application-crypto/src/ed25519.rs deleted file mode 100644 index b0113718b5ed0..0000000000000 --- a/core/application-crypto/src/ed25519.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Ed25519 crypto types. - -use crate::{RuntimePublic, KeyTypeId}; - -pub use primitives::ed25519::*; - -mod app { - use primitives::testing::ED25519; - crate::app_crypto!(super, ED25519); -} - -pub use app::Public as AppPublic; -pub use app::Signature as AppSignature; -#[cfg(feature="std")] -pub use app::Pair as AppPair; - -impl RuntimePublic for Public { - type Signature = Signature; - - fn all(key_type: KeyTypeId) -> crate::Vec { - runtime_io::ed25519_public_keys(key_type) - } - - fn generate_pair(key_type: KeyTypeId, seed: Option<&str>) -> Self { - runtime_io::ed25519_generate(key_type, seed) - } - - fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option { - runtime_io::ed25519_sign(key_type, self, msg.as_ref()) - } - - fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { - runtime_io::ed25519_verify(&signature, msg.as_ref(), self) - } -} - -#[cfg(test)] -mod tests { - use sr_primitives::{generic::BlockId, traits::ProvideRuntimeApi}; - use primitives::{testing::{KeyStore, ED25519}, crypto::Pair}; - use test_client::{ - TestClientBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt, - runtime::{TestAPI, app_crypto::ed25519::{AppPair, AppPublic}}, - }; - - #[test] - fn ed25519_works_in_runtime() { - let keystore = KeyStore::new(); - let test_client = TestClientBuilder::new().set_keystore(keystore.clone()).build(); - let (signature, public) = test_client.runtime_api() - .test_ed25519_crypto(&BlockId::Number(0)) - .expect("Tests `ed25519` crypto."); - - let key_pair = keystore.read().ed25519_key_pair(ED25519, &public.as_ref()) - .expect("There should be at a `ed25519` key in the keystore for the given public key."); - - assert!(AppPair::verify(&signature, "ed25519", &AppPublic::from(key_pair.public()))); - } -} diff --git a/core/application-crypto/src/lib.rs b/core/application-crypto/src/lib.rs deleted file mode 100644 index b4ada5425b400..0000000000000 --- a/core/application-crypto/src/lib.rs +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Traits and macros for constructing application specific strongly typed crypto wrappers. - -#![warn(missing_docs)] - -#![cfg_attr(not(feature = "std"), no_std)] - -#[doc(hidden)] -pub use primitives::{self, crypto::{CryptoType, Public, Derive, IsWrappedBy, Wraps}, RuntimeDebug}; -#[doc(hidden)] -#[cfg(feature = "std")] -pub use primitives::crypto::{SecretStringError, DeriveJunction, Ss58Codec, Pair}; -pub use primitives::{crypto::{KeyTypeId, key_types}}; - -#[doc(hidden)] -pub use codec; -#[doc(hidden)] -#[cfg(feature = "std")] -pub use serde; -#[doc(hidden)] -pub use rstd::{ops::Deref, vec::Vec}; - -pub mod ed25519; -pub mod sr25519; -mod traits; - -pub use traits::*; - -/// Declares Public, Pair, Signature types which are functionally equivalent to `$pair`, but are new -/// Application-specific types whose identifier is `$key_type`. -/// -/// ```rust -///# use substrate_application_crypto::{app_crypto, wrap, ed25519, KeyTypeId}; -/// // Declare a new set of crypto types using Ed25519 logic that identifies as `KeyTypeId` -/// // of value `b"fuba"`. -/// app_crypto!(ed25519, KeyTypeId(*b"_uba")); -/// ``` -#[macro_export] -macro_rules! app_crypto { - ($module:ident, $key_type:expr) => { - #[cfg(feature="std")] - $crate::app_crypto!($module::Pair, $module::Public, $module::Signature, $key_type); - #[cfg(not(feature="std"))] - $crate::app_crypto!($module::Public, $module::Signature, $key_type); - }; - ($pair:ty, $public:ty, $sig:ty, $key_type:expr) => { - $crate::app_crypto!($public, $sig, $key_type); - - $crate::wrap!{ - /// A generic `AppPublic` wrapper type over $pair crypto; this has no specific App. - #[derive(Clone)] - pub struct Pair($pair); - } - - impl $crate::CryptoType for Pair { - type Pair = Pair; - } - - #[cfg(feature = "std")] - impl $crate::Pair for Pair { - type Public = Public; - type Seed = <$pair as $crate::Pair>::Seed; - type Signature = Signature; - type DeriveError = <$pair as $crate::Pair>::DeriveError; - fn generate_with_phrase(password: Option<&str>) -> (Self, String, Self::Seed) { - let r = <$pair>::generate_with_phrase(password); - (Self(r.0), r.1, r.2) - } - fn from_phrase(phrase: &str, password: Option<&str>) - -> Result<(Self, Self::Seed), $crate::SecretStringError> - { - <$pair>::from_phrase(phrase, password).map(|r| (Self(r.0), r.1)) - } - fn derive< - Iter: Iterator - >(&self, path: Iter, seed: Option) -> Result<(Self, Option), Self::DeriveError> { - self.0.derive(path, seed).map(|x| (Self(x.0), x.1)) - } - fn from_seed(seed: &Self::Seed) -> Self { Self(<$pair>::from_seed(seed)) } - fn from_seed_slice(seed: &[u8]) -> Result { - <$pair>::from_seed_slice(seed).map(Self) - } - fn sign(&self, msg: &[u8]) -> Self::Signature { - Signature(self.0.sign(msg)) - } - fn verify>( - sig: &Self::Signature, - message: M, - pubkey: &Self::Public, - ) -> bool { - <$pair>::verify(&sig.0, message, pubkey.as_ref()) - } - fn verify_weak, M: AsRef<[u8]>>( - sig: &[u8], - message: M, - pubkey: P, - ) -> bool { - <$pair>::verify_weak(sig, message, pubkey) - } - fn public(&self) -> Self::Public { Public(self.0.public()) } - fn to_raw_vec(&self) -> Vec { self.0.to_raw_vec() } - } - impl $crate::AppKey for Pair { - type UntypedGeneric = $pair; - type Public = Public; - type Pair = Pair; - type Signature = Signature; - const ID: $crate::KeyTypeId = $key_type; - } - impl $crate::AppPair for Pair { - type Generic = $pair; - } - }; - ($public:ty, $sig:ty, $key_type:expr) => { - $crate::wrap!{ - /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. - #[derive( - Clone, Default, Eq, PartialEq, Ord, PartialOrd, - $crate::codec::Encode, - $crate::codec::Decode, - $crate::RuntimeDebug, - )] - #[cfg_attr(feature = "std", derive(Hash))] - pub struct Public($public); - } - - impl $crate::Derive for Public { - #[cfg(feature = "std")] - fn derive>(&self, - path: Iter - ) -> Option { - self.0.derive(path).map(Self) - } - } - - #[cfg(feature = "std")] - impl std::fmt::Display for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use $crate::Ss58Codec; - write!(f, "{}", self.0.to_ss58check()) - } - } - #[cfg(feature = "std")] - impl $crate::serde::Serialize for Public { - fn serialize(&self, serializer: S) -> std::result::Result where - S: $crate::serde::Serializer - { - use $crate::Ss58Codec; - serializer.serialize_str(&self.to_ss58check()) - } - } - #[cfg(feature = "std")] - impl<'de> $crate::serde::Deserialize<'de> for Public { - fn deserialize(deserializer: D) -> std::result::Result where - D: $crate::serde::Deserializer<'de> - { - use $crate::Ss58Codec; - Public::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| $crate::serde::de::Error::custom(format!("{:?}", e))) - } - } - - impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { self.0.as_ref() } - } - - impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { self.0.as_mut() } - } - - impl $crate::CryptoType for Public { - #[cfg(feature="std")] - type Pair = Pair; - } - - impl $crate::Public for Public { - fn from_slice(x: &[u8]) -> Self { Self(<$public>::from_slice(x)) } - } - - impl $crate::AppKey for Public { - type UntypedGeneric = $public; - type Public = Public; - #[cfg(feature="std")] - type Pair = Pair; - type Signature = Signature; - const ID: $crate::KeyTypeId = $key_type; - } - - impl $crate::AppPublic for Public { - type Generic = $public; - } - - impl $crate::RuntimeAppPublic for Public where $public: $crate::RuntimePublic { - const ID: $crate::KeyTypeId = $key_type; - type Signature = Signature; - - fn all() -> $crate::Vec { - <$public as $crate::RuntimePublic>::all($key_type).into_iter().map(Self).collect() - } - - fn generate_pair(seed: Option<&str>) -> Self { - Self(<$public as $crate::RuntimePublic>::generate_pair($key_type, seed)) - } - - fn sign>(&self, msg: &M) -> Option { - <$public as $crate::RuntimePublic>::sign( - self.as_ref(), - $key_type, - msg, - ).map(Signature) - } - - fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { - <$public as $crate::RuntimePublic>::verify(self.as_ref(), msg, &signature.as_ref()) - } - } - - $crate::wrap! { - /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. - #[derive(Clone, Default, Eq, PartialEq, - $crate::codec::Encode, - $crate::codec::Decode, - $crate::RuntimeDebug, - )] - #[cfg_attr(feature = "std", derive(Hash))] - pub struct Signature($sig); - } - - impl $crate::Deref for Signature { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { self.0.as_ref() } - } - - impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { self.0.as_ref() } - } - - impl $crate::CryptoType for Signature { - #[cfg(feature="std")] - type Pair = Pair; - } - - impl $crate::AppKey for Signature { - type UntypedGeneric = $sig; - type Public = Public; - #[cfg(feature="std")] - type Pair = Pair; - type Signature = Signature; - const ID: $crate::KeyTypeId = $key_type; - } - - impl $crate::AppSignature for Signature { - type Generic = $sig; - } - } -} - -/// Implement bidirectional `From` and on-way `AsRef`/`AsMut` for two types, `$inner` and `$outer`. -/// -/// ```rust -/// substrate_application_crypto::wrap! { -/// pub struct Wrapper(u32); -/// } -/// ``` -#[macro_export] -macro_rules! wrap { - ($( #[ $attr:meta ] )* struct $outer:ident($inner:ty);) => { - $( #[ $attr ] )* - struct $outer( $inner ); - $crate::wrap!($inner, $outer); - }; - ($( #[ $attr:meta ] )* pub struct $outer:ident($inner:ty);) => { - $( #[ $attr ] )* - pub struct $outer( $inner ); - $crate::wrap!($inner, $outer); - }; - ($inner:ty, $outer:ty) => { - impl $crate::Wraps for $outer { - type Inner = $inner; - } - impl From<$inner> for $outer { - fn from(inner: $inner) -> Self { - Self(inner) - } - } - impl From<$outer> for $inner { - fn from(outer: $outer) -> Self { - outer.0 - } - } - impl AsRef<$inner> for $outer { - fn as_ref(&self) -> &$inner { - &self.0 - } - } - impl AsMut<$inner> for $outer { - fn as_mut(&mut self) -> &mut $inner { - &mut self.0 - } - } - } -} diff --git a/core/application-crypto/src/sr25519.rs b/core/application-crypto/src/sr25519.rs deleted file mode 100644 index 40f6c6b22ec02..0000000000000 --- a/core/application-crypto/src/sr25519.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Sr25519 crypto types. - -use crate::{RuntimePublic, KeyTypeId}; - -pub use primitives::sr25519::*; - -mod app { - use primitives::testing::SR25519; - crate::app_crypto!(super, SR25519); -} - -pub use app::Public as AppPublic; -pub use app::Signature as AppSignature; -#[cfg(feature="std")] -pub use app::Pair as AppPair; - -impl RuntimePublic for Public { - type Signature = Signature; - - fn all(key_type: KeyTypeId) -> crate::Vec { - runtime_io::sr25519_public_keys(key_type) - } - - fn generate_pair(key_type: KeyTypeId, seed: Option<&str>) -> Self { - runtime_io::sr25519_generate(key_type, seed) - } - - fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option { - runtime_io::sr25519_sign(key_type, self, msg.as_ref()) - } - - fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { - runtime_io::sr25519_verify(&signature, msg.as_ref(), self) - } -} - -#[cfg(test)] -mod tests { - use sr_primitives::{generic::BlockId, traits::ProvideRuntimeApi}; - use primitives::{testing::{KeyStore, SR25519}, crypto::Pair}; - use test_client::{ - TestClientBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt, - runtime::{TestAPI, app_crypto::sr25519::{AppPair, AppPublic}}, - }; - - #[test] - fn sr25519_works_in_runtime() { - let keystore = KeyStore::new(); - let test_client = TestClientBuilder::new().set_keystore(keystore.clone()).build(); - let (signature, public) = test_client.runtime_api() - .test_sr25519_crypto(&BlockId::Number(0)) - .expect("Tests `sr25519` crypto."); - - let key_pair = keystore.read().sr25519_key_pair(SR25519, public.as_ref()) - .expect("There should be at a `sr25519` key in the keystore for the given public key."); - - assert!(AppPair::verify(&signature, "sr25519", &AppPublic::from(key_pair.public()))); - } -} diff --git a/core/application-crypto/src/traits.rs b/core/application-crypto/src/traits.rs deleted file mode 100644 index 66e6cd6579b10..0000000000000 --- a/core/application-crypto/src/traits.rs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#[cfg(feature = "std")] -use primitives::crypto::Pair; - -use codec::Codec; -use primitives::crypto::{KeyTypeId, CryptoType, IsWrappedBy, Public}; -use rstd::fmt::Debug; - -/// An application-specific key. -pub trait AppKey: 'static + Send + Sync + Sized + CryptoType + Clone { - /// The corresponding type as a generic crypto type. - type UntypedGeneric: IsWrappedBy; - - /// The corresponding public key type in this application scheme. - type Public: AppPublic; - - /// The corresponding key pair type in this application scheme. - #[cfg(feature="std")] - type Pair: AppPair; - - /// The corresponding signature type in this application scheme. - type Signature: AppSignature; - - /// An identifier for this application-specific key type. - const ID: KeyTypeId; -} - -/// Type which implements Hash in std, not when no-std (std variant). -#[cfg(feature = "std")] -pub trait MaybeHash: std::hash::Hash {} -#[cfg(feature = "std")] -impl MaybeHash for T {} - -/// Type which implements Hash in std, not when no-std (no-std variant). -#[cfg(not(feature = "std"))] -pub trait MaybeHash {} -#[cfg(not(feature = "std"))] -impl MaybeHash for T {} - -/// A application's public key. -pub trait AppPublic: - AppKey + Public + Ord + PartialOrd + Eq + PartialEq + Debug + MaybeHash + codec::Codec -{ - /// The wrapped type which is just a plain instance of `Public`. - type Generic: - IsWrappedBy + Public + Ord + PartialOrd + Eq + PartialEq + Debug + MaybeHash + codec::Codec; -} - -/// A application's key pair. -#[cfg(feature = "std")] -pub trait AppPair: AppKey + Pair::Public> { - /// The wrapped type which is just a plain instance of `Pair`. - type Generic: IsWrappedBy + Pair::Public as AppPublic>::Generic>; -} - -/// A application's signature. -pub trait AppSignature: AppKey + Eq + PartialEq + Debug + MaybeHash { - /// The wrapped type which is just a plain instance of `Signature`. - type Generic: IsWrappedBy + Eq + PartialEq + Debug + MaybeHash; -} - -/// A runtime interface for a public key. -pub trait RuntimePublic: Sized { - /// The signature that will be generated when signing with the corresponding private key. - type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone; - - /// Returns all public keys for the given key type in the keystore. - fn all(key_type: KeyTypeId) -> crate::Vec; - - /// Generate a public/private pair for the given key type and store it in the keystore. - /// - /// Returns the generated public key. - fn generate_pair(key_type: KeyTypeId, seed: Option<&str>) -> Self; - - /// Sign the given message with the corresponding private key of this public key. - /// - /// The private key will be requested from the keystore using the given key type. - /// - /// Returns the signature or `None` if the private key could not be found or some other error - /// occurred. - fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option; - - /// Verify that the given signature matches the given message using this public key. - fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool; -} - -/// A runtime interface for an application's public key. -pub trait RuntimeAppPublic: Sized { - /// An identifier for this application-specific key type. - const ID: KeyTypeId; - - /// The signature that will be generated when signing with the corresponding private key. - type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone; - - /// Returns all public keys for this application in the keystore. - fn all() -> crate::Vec; - - /// Generate a public/private pair and store it in the keystore. - /// - /// Returns the generated public key. - fn generate_pair(seed: Option<&str>) -> Self; - - /// Sign the given message with the corresponding private key of this public key. - /// - /// The private key will be requested from the keystore. - /// - /// Returns the signature or `None` if the private key could not be found or some other error - /// occurred. - fn sign>(&self, msg: &M) -> Option; - - /// Verify that the given signature matches the given message using this public key. - fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool; -} - diff --git a/core/authority-discovery/Cargo.toml b/core/authority-discovery/Cargo.toml deleted file mode 100644 index 7283e07f89ca7..0000000000000 --- a/core/authority-discovery/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "substrate-authority-discovery" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -build = "build.rs" - -[build-dependencies] -prost-build = "0.5.0" - -[dependencies] -authority-discovery-primitives = { package = "substrate-authority-discovery-primitives", path = "./primitives" } -bytes = "0.4.12" -client = { package = "substrate-client", path = "../../core/client" } -codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" } -derive_more = "0.15.0" -futures = "0.1.29" -libp2p = { version = "0.12.0", default-features = false, features = ["secp256k1", "libp2p-websocket"] } -log = "0.4.8" -network = { package = "substrate-network", path = "../../core/network" } -primitives = { package = "substrate-primitives", path = "../primitives" } -prost = "0.5.0" -serde_json = "1.0.41" -sr-primitives = { path = "../../core/sr-primitives" } -tokio-timer = "0.2.11" - -[dev-dependencies] -parking_lot = "0.9.0" -peerset = { package = "substrate-peerset", path = "../../core/peerset" } -test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } -tokio = "0.1.22" diff --git a/core/authority-discovery/primitives/Cargo.toml b/core/authority-discovery/primitives/Cargo.toml deleted file mode 100644 index 8e9e465a299f6..0000000000000 --- a/core/authority-discovery/primitives/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "substrate-authority-discovery-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Authority discovery primitives" -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" } -client = { package = "substrate-client", path = "../../client", default-features = false } -sr-primitives = { path = "../../sr-primitives", default-features = false } -rstd = { package = "sr-std", path = "../../sr-std", default-features = false } - -[features] -default = ["std"] -std = [ - "rstd/std", - "client/std", - "codec/std", - "sr-primitives/std" -] diff --git a/core/authority-discovery/primitives/src/lib.rs b/core/authority-discovery/primitives/src/lib.rs deleted file mode 100644 index 7c56dc6ca4ca6..0000000000000 --- a/core/authority-discovery/primitives/src/lib.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Runtime Api to help discover authorities. - -#![cfg_attr(not(feature = "std"), no_std)] - -use client::decl_runtime_apis; -use rstd::vec::Vec; -use sr_primitives::RuntimeDebug; - -#[derive(codec::Encode, codec::Decode, Eq, PartialEq, Clone, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Hash))] -pub struct Signature(pub Vec); -#[derive(codec::Encode, codec::Decode, Eq, PartialEq, Clone, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Hash))] -pub struct AuthorityId(pub Vec); - -decl_runtime_apis! { - /// The authority discovery api. - /// - /// This api is used by the `core/authority-discovery` module to retrieve our - /// own authority identifier, to retrieve identifiers of the current authority - /// set, as well as sign and verify Kademlia Dht external address payloads - /// from and to other authorities. - pub trait AuthorityDiscoveryApi { - /// Retrieve authority identifiers of the current authority set. - fn authorities() -> Vec; - - /// Sign the given payload with the private key corresponding to the given authority id. - fn sign(payload: &Vec) -> Option<(Signature, AuthorityId)>; - - /// Verify the given signature for the given payload with the given - /// authority identifier. - fn verify(payload: &Vec, signature: &Signature, authority_id: &AuthorityId) -> bool; - } -} diff --git a/core/authority-discovery/src/error.rs b/core/authority-discovery/src/error.rs deleted file mode 100644 index e8c1ad9705f0c..0000000000000 --- a/core/authority-discovery/src/error.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Authority discovery errors. - -/// AuthorityDiscovery Result. -pub type Result = std::result::Result; - -/// Error type for the authority discovery module. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Failed to verify a dht payload with the given signature. - VerifyingDhtPayload, - /// Failed to hash the authority id to be used as a dht key. - HashingAuthorityId(libp2p::core::multiaddr::multihash::EncodeError), - /// Failed calling into the Substrate runtime. - CallingRuntime(client::error::Error), - /// Failed signing the dht payload via the Substrate runtime. - SigningDhtPayload, - /// From the Dht we only get the hashed authority id. In order to retrieve the actual authority id and to ensure it - /// is actually an authority, we match the hash against the hash of the authority id of all other authorities. This - /// error is the result of the above failing. - MatchingHashedAuthorityIdWithAuthorityId, - /// Failed to set the authority discovery peerset priority group in the peerset module. - SettingPeersetPriorityGroup(String), - /// Failed to encode a dht payload. - Encoding(prost::EncodeError), - /// Failed to decode a dht payload. - Decoding(prost::DecodeError), - /// Failed to parse a libp2p multi address. - ParsingMultiaddress(libp2p::core::multiaddr::Error), - /// Tokio timer error. - PollingTokioTimer(tokio_timer::Error) -} diff --git a/core/authority-discovery/src/lib.rs b/core/authority-discovery/src/lib.rs deleted file mode 100644 index 987169ead90b1..0000000000000 --- a/core/authority-discovery/src/lib.rs +++ /dev/null @@ -1,698 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![warn(missing_docs)] - -//! Substrate authority discovery. -//! -//! This crate enables Substrate authorities to directly connect to other authorities. [`AuthorityDiscovery`] implements -//! the Future trait. By polling [`AuthorityDiscovery`] an authority: -//! -//! -//! 1. **Makes itself discoverable** -//! -//! 1. Retrieves its external addresses. -//! -//! 2. Adds its network peer id to the addresses. -//! -//! 3. Signs the above. -//! -//! 4. Puts the signature and the addresses on the libp2p Kademlia DHT. -//! -//! -//! 2. **Discovers other authorities** -//! -//! 1. Retrieves the current set of authorities. -//! -//! 2. Starts DHT queries for the ids of the authorities. -//! -//! 3. Validates the signatures of the retrieved key value pairs. -//! -//! 4. Adds the retrieved external addresses as priority nodes to the peerset. - -use authority_discovery_primitives::{AuthorityDiscoveryApi, AuthorityId, Signature}; -use client::blockchain::HeaderBackend; -use error::{Error, Result}; -use futures::{prelude::*, sync::mpsc::Receiver}; -use log::{debug, error, log_enabled, warn}; -use network::specialization::NetworkSpecialization; -use network::{DhtEvent, ExHashT}; -use prost::Message; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{Block as BlockT, ProvideRuntimeApi}; -use std::collections::{HashMap, HashSet}; -use std::convert::TryInto; -use std::iter::FromIterator; -use std::marker::PhantomData; -use std::sync::Arc; -use std::time::{Duration, Instant}; - -mod error; -/// Dht payload schemas generated from Protobuf definitions via Prost crate in build.rs. -mod schema { - include!(concat!(env!("OUT_DIR"), "/authority_discovery.rs")); -} - -/// An `AuthorityDiscovery` makes a given authority discoverable and discovers other authorities. -pub struct AuthorityDiscovery -where - Block: BlockT + 'static, - Network: NetworkProvider, - Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, - ::Api: AuthorityDiscoveryApi, -{ - client: Arc, - - network: Arc, - /// Channel we receive Dht events on. - dht_event_rx: Receiver, - - /// Interval to be proactive, publishing own addresses. - publish_interval: tokio_timer::Interval, - /// Interval on which to query for addresses of other authorities. - query_interval: tokio_timer::Interval, - - /// The network peerset interface for priority groups lets us only set an entire group, but we retrieve the - /// addresses of other authorities one by one from the network. To use the peerset interface we need to cache the - /// addresses and always overwrite the entire peerset priority group. To ensure this map doesn't grow indefinitely - /// `purge_old_authorities_from_cache` function is called each time we add a new entry. - address_cache: HashMap>, - - phantom: PhantomData, -} - -impl AuthorityDiscovery -where - Block: BlockT + 'static, - Network: NetworkProvider, - Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, - ::Api: AuthorityDiscoveryApi, -{ - /// Return a new authority discovery. - pub fn new( - client: Arc, - network: Arc, - dht_event_rx: futures::sync::mpsc::Receiver, - ) -> AuthorityDiscovery { - // Kademlia's default time-to-live for Dht records is 36h, republishing records every 24h. Given that a node - // could restart at any point in time, one can not depend on the republishing process, thus publishing own - // external addresses should happen on an interval < 36h. - let publish_interval = - tokio_timer::Interval::new(Instant::now(), Duration::from_secs(12 * 60 * 60)); - - // External addresses of other authorities can change at any given point in time. The interval on which to query - // for external addresses of other authorities is a trade off between efficiency and performance. - let query_interval = - tokio_timer::Interval::new(Instant::now(), Duration::from_secs(10 * 60)); - - let address_cache = HashMap::new(); - - AuthorityDiscovery { - client, - network, - dht_event_rx, - publish_interval, - query_interval, - address_cache, - phantom: PhantomData, - } - } - - fn publish_own_ext_addresses(&mut self) -> Result<()> { - let id = BlockId::hash(self.client.info().best_hash); - - let addresses = self - .network - .external_addresses() - .into_iter() - .map(|a| { - a.with(libp2p::core::multiaddr::Protocol::P2p( - self.network.local_peer_id().into(), - )) - }) - .map(|a| a.to_vec()) - .collect(); - - let mut serialized_addresses = vec![]; - schema::AuthorityAddresses { addresses } - .encode(&mut serialized_addresses) - .map_err(Error::Encoding)?; - - let (signature, authority_id) = self - .client - .runtime_api() - .sign(&id, &serialized_addresses) - .map_err(Error::CallingRuntime)? - .ok_or(Error::SigningDhtPayload)?; - - let mut signed_addresses = vec![]; - schema::SignedAuthorityAddresses { - addresses: serialized_addresses, - signature: signature.0, - } - .encode(&mut signed_addresses) - .map_err(Error::Encoding)?; - - self.network.put_value( - hash_authority_id(authority_id.0.as_ref())?, - signed_addresses, - ); - - Ok(()) - } - - fn request_addresses_of_others(&mut self) -> Result<()> { - let id = BlockId::hash(self.client.info().best_hash); - - let authorities = self - .client - .runtime_api() - .authorities(&id) - .map_err(Error::CallingRuntime)?; - - for authority_id in authorities.iter() { - self.network - .get_value(&hash_authority_id(authority_id.0.as_ref())?); - } - - Ok(()) - } - - fn handle_dht_events(&mut self) -> Result<()> { - while let Ok(Async::Ready(Some(event))) = self.dht_event_rx.poll() { - match event { - DhtEvent::ValueFound(v) => { - if log_enabled!(log::Level::Debug) { - let hashes = v.iter().map(|(hash, _value)| hash.clone()); - debug!(target: "sub-authority-discovery", "Value for hash '{:?}' found on Dht.", hashes); - } - - self.handle_dht_value_found_event(v)?; - } - DhtEvent::ValueNotFound(hash) => { - warn!(target: "sub-authority-discovery", "Value for hash '{:?}' not found on Dht.", hash) - } - DhtEvent::ValuePut(hash) => { - debug!(target: "sub-authority-discovery", "Successfully put hash '{:?}' on Dht.", hash) - } - DhtEvent::ValuePutFailed(hash) => { - warn!(target: "sub-authority-discovery", "Failed to put hash '{:?}' on Dht.", hash) - } - } - } - - Ok(()) - } - - fn handle_dht_value_found_event( - &mut self, - values: Vec<(libp2p::kad::record::Key, Vec)>, - ) -> Result<()> { - debug!(target: "sub-authority-discovery", "Got Dht value from network."); - - let id = BlockId::hash(self.client.info().best_hash); - - // From the Dht we only get the hashed authority id. In order to retrieve the actual authority id and to ensure - // it is actually an authority, we match the hash against the hash of the authority id of all other authorities. - let authorities = self.client.runtime_api().authorities(&id)?; - self.purge_old_authorities_from_cache(&authorities); - - let authorities = authorities - .into_iter() - .map(|a| hash_authority_id(a.0.as_ref()).map(|h| (h, a))) - .collect::>>()?; - - for (key, value) in values.iter() { - // Check if the event origins from an authority in the current authority set. - let authority_id: &AuthorityId = authorities - .get(key) - .ok_or(Error::MatchingHashedAuthorityIdWithAuthorityId)?; - - let schema::SignedAuthorityAddresses { - signature, - addresses, - } = schema::SignedAuthorityAddresses::decode(value).map_err(Error::Decoding)?; - let signature = Signature(signature); - - let is_verified = self - .client - .runtime_api() - .verify(&id, &addresses, &signature, &authority_id.clone()) - .map_err(Error::CallingRuntime)?; - - if !is_verified { - return Err(Error::VerifyingDhtPayload); - } - - let addresses: Vec = schema::AuthorityAddresses::decode(addresses) - .map(|a| a.addresses) - .map_err(Error::Decoding)? - .into_iter() - .map(|a| a.try_into()) - .collect::>() - .map_err(Error::ParsingMultiaddress)?; - - self.address_cache.insert(authority_id.clone(), addresses); - } - - // Let's update the peerset priority group with the all the addresses we have in our cache. - - let addresses = HashSet::from_iter( - self.address_cache - .iter() - .map(|(_peer_id, addresses)| addresses.clone()) - .flatten(), - ); - - debug!(target: "sub-authority-discovery", "Applying priority group {:#?} to peerset.", addresses); - self.network - .set_priority_group("authorities".to_string(), addresses) - .map_err(Error::SettingPeersetPriorityGroup)?; - - Ok(()) - } - - fn purge_old_authorities_from_cache(&mut self, current_authorities: &Vec) { - self.address_cache - .retain(|peer_id, _addresses| current_authorities.contains(peer_id)) - } -} - -impl futures::Future for AuthorityDiscovery -where - Block: BlockT + 'static, - Network: NetworkProvider, - Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, - ::Api: AuthorityDiscoveryApi, -{ - type Item = (); - type Error = (); - - fn poll(&mut self) -> futures::Poll { - let mut inner = || -> Result<()> { - // Process incoming events before triggering new ones. - self.handle_dht_events()?; - - if let Async::Ready(_) = self - .publish_interval - .poll() - .map_err(Error::PollingTokioTimer)? - { - // Make sure to call interval.poll until it returns Async::NotReady once. Otherwise, in case one of the - // function calls within this block do a `return`, we don't call `interval.poll` again and thereby the - // underlying Tokio task is never registered with Tokio's Reactor to be woken up on the next interval - // tick. - while let Async::Ready(_) = self - .publish_interval - .poll() - .map_err(Error::PollingTokioTimer)? - {} - - self.publish_own_ext_addresses()?; - } - - if let Async::Ready(_) = self - .query_interval - .poll() - .map_err(Error::PollingTokioTimer)? - { - // Make sure to call interval.poll until it returns Async::NotReady once. Otherwise, in case one of the - // function calls within this block do a `return`, we don't call `interval.poll` again and thereby the - // underlying Tokio task is never registered with Tokio's Reactor to be woken up on the next interval - // tick. - while let Async::Ready(_) = self - .query_interval - .poll() - .map_err(Error::PollingTokioTimer)? - {} - - self.request_addresses_of_others()?; - } - - Ok(()) - }; - - match inner() { - Ok(()) => {} - Err(e) => error!(target: "sub-authority-discovery", "Poll failure: {:?}", e), - }; - - // Make sure to always return NotReady as this is a long running task with the same lifetime as the node itself. - Ok(futures::Async::NotReady) - } -} - -/// NetworkProvider provides AuthorityDiscovery with all necessary hooks into the underlying Substrate networking. Using -/// this trait abstraction instead of NetworkService directly is necessary to unit test AuthorityDiscovery. -pub trait NetworkProvider { - /// Returns the local external addresses. - fn external_addresses(&self) -> Vec; - - /// Returns the network identity of the node. - fn local_peer_id(&self) -> libp2p::PeerId; - - /// Modify a peerset priority group. - fn set_priority_group( - &self, - group_id: String, - peers: HashSet, - ) -> std::result::Result<(), String>; - - /// Start putting a value in the Dht. - fn put_value(&self, key: libp2p::kad::record::Key, value: Vec); - - /// Start getting a value from the Dht. - fn get_value(&self, key: &libp2p::kad::record::Key); -} - -impl NetworkProvider for network::NetworkService -where - B: BlockT + 'static, - S: NetworkSpecialization, - H: ExHashT, -{ - fn external_addresses(&self) -> Vec { - self.external_addresses() - } - fn local_peer_id(&self) -> libp2p::PeerId { - self.local_peer_id() - } - fn set_priority_group( - &self, - group_id: String, - peers: HashSet, - ) -> std::result::Result<(), String> { - self.set_priority_group(group_id, peers) - } - fn put_value(&self, key: libp2p::kad::record::Key, value: Vec) { - self.put_value(key, value) - } - fn get_value(&self, key: &libp2p::kad::record::Key) { - self.get_value(key) - } -} - -fn hash_authority_id(id: &[u8]) -> Result { - libp2p::multihash::encode(libp2p::multihash::Hash::SHA2256, id) - .map(|k| libp2p::kad::record::Key::new(&k)) - .map_err(Error::HashingAuthorityId) -} - -#[cfg(test)] -mod tests { - use super::*; - use client::runtime_api::{ApiExt, Core, RuntimeVersion}; - use futures::future::poll_fn; - use primitives::{ExecutionContext, NativeOrEncoded}; - use sr_primitives::traits::Zero; - use sr_primitives::traits::{ApiRef, Block as BlockT, NumberFor, ProvideRuntimeApi}; - use std::sync::{Arc, Mutex}; - use test_client::runtime::Block; - use tokio::runtime::current_thread; - - #[derive(Clone)] - struct TestApi {} - - impl ProvideRuntimeApi for TestApi { - type Api = RuntimeApi; - - fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { - RuntimeApi {}.into() - } - } - - /// Blockchain database header backend. Does not perform any validation. - impl HeaderBackend for TestApi { - fn header( - &self, - _id: BlockId, - ) -> std::result::Result, client::error::Error> { - Ok(None) - } - - fn info(&self) -> client::blockchain::Info { - client::blockchain::Info { - best_hash: Default::default(), - best_number: Zero::zero(), - finalized_hash: Default::default(), - finalized_number: Zero::zero(), - genesis_hash: Default::default(), - } - } - - fn status( - &self, - _id: BlockId, - ) -> std::result::Result { - Ok(client::blockchain::BlockStatus::Unknown) - } - - fn number( - &self, - _hash: Block::Hash, - ) -> std::result::Result>, client::error::Error> { - Ok(None) - } - - fn hash( - &self, - _number: NumberFor, - ) -> std::result::Result, client::error::Error> { - Ok(None) - } - } - - struct RuntimeApi {} - - impl Core for RuntimeApi { - fn Core_version_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<()>, - _: Vec, - ) -> std::result::Result, client::error::Error> { - unimplemented!("Not required for testing!") - } - - fn Core_execute_block_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<(Block)>, - _: Vec, - ) -> std::result::Result, client::error::Error> { - unimplemented!("Not required for testing!") - } - - fn Core_initialize_block_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<&::Header>, - _: Vec, - ) -> std::result::Result, client::error::Error> { - unimplemented!("Not required for testing!") - } - } - - impl ApiExt for RuntimeApi { - fn map_api_result std::result::Result, R, E>( - &self, - _: F, - ) -> std::result::Result { - unimplemented!("Not required for testing!") - } - - fn runtime_version_at( - &self, - _: &BlockId, - ) -> std::result::Result { - unimplemented!("Not required for testing!") - } - - fn record_proof(&mut self) { - unimplemented!("Not required for testing!") - } - - fn extract_proof(&mut self) -> Option>> { - unimplemented!("Not required for testing!") - } - } - - impl AuthorityDiscoveryApi for RuntimeApi { - fn AuthorityDiscoveryApi_authorities_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<()>, - _: Vec, - ) -> std::result::Result>, client::error::Error> { - return Ok(NativeOrEncoded::Native(vec![ - AuthorityId("test-authority-id-1".as_bytes().to_vec()), - AuthorityId("test-authority-id-2".as_bytes().to_vec()), - ])); - } - fn AuthorityDiscoveryApi_sign_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<&std::vec::Vec>, - _: Vec, - ) -> std::result::Result< - NativeOrEncoded>, - client::error::Error, - > { - return Ok(NativeOrEncoded::Native(Some(( - Signature("test-signature-1".as_bytes().to_vec()), - AuthorityId("test-authority-id-1".as_bytes().to_vec()), - )))); - } - fn AuthorityDiscoveryApi_verify_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - args: Option<(&Vec, &Signature, &AuthorityId)>, - _: Vec, - ) -> std::result::Result, client::error::Error> { - if *args.unwrap().1 == Signature("test-signature-1".as_bytes().to_vec()) { - return Ok(NativeOrEncoded::Native(true)); - } - return Ok(NativeOrEncoded::Native(false)); - } - } - - #[derive(Default)] - struct TestNetwork { - // Whenever functions on `TestNetwork` are called, the function arguments are added to the vectors below. - pub put_value_call: Arc)>>>, - pub get_value_call: Arc>>, - pub set_priority_group_call: Arc)>>>, - } - - impl NetworkProvider for TestNetwork { - fn external_addresses(&self) -> Vec { - vec![] - } - fn local_peer_id(&self) -> libp2p::PeerId { - libp2p::PeerId::random() - } - fn set_priority_group( - &self, - group_id: String, - peers: HashSet, - ) -> std::result::Result<(), String> { - self.set_priority_group_call - .lock() - .unwrap() - .push((group_id, peers)); - Ok(()) - } - fn put_value(&self, key: libp2p::kad::record::Key, value: Vec) { - self.put_value_call.lock().unwrap().push((key, value)); - } - fn get_value(&self, key: &libp2p::kad::record::Key) { - self.get_value_call.lock().unwrap().push(key.clone()); - } - } - - #[test] - fn publish_own_ext_addresses_puts_record_on_dht() { - let (_dht_event_tx, dht_event_rx) = futures::sync::mpsc::channel(1000); - let test_api = Arc::new(TestApi {}); - let network: Arc = Arc::new(Default::default()); - - let mut authority_discovery = - AuthorityDiscovery::new(test_api, network.clone(), dht_event_rx); - - authority_discovery.publish_own_ext_addresses().unwrap(); - - // Expect authority discovery to put a new record onto the dht. - assert_eq!(network.put_value_call.lock().unwrap().len(), 1); - } - - #[test] - fn request_addresses_of_others_triggers_dht_get_query() { - let (_dht_event_tx, dht_event_rx) = futures::sync::mpsc::channel(1000); - let test_api = Arc::new(TestApi {}); - let network: Arc = Arc::new(Default::default()); - - let mut authority_discovery = - AuthorityDiscovery::new(test_api, network.clone(), dht_event_rx); - - authority_discovery.request_addresses_of_others().unwrap(); - - // Expect authority discovery to request new records from the dht. - assert_eq!(network.get_value_call.lock().unwrap().len(), 2); - } - - #[test] - fn handle_dht_events_with_value_found_should_call_set_priority_group() { - // Create authority discovery. - - let (mut dht_event_tx, dht_event_rx) = futures::sync::mpsc::channel(1000); - let test_api = Arc::new(TestApi {}); - let network: Arc = Arc::new(Default::default()); - - let mut authority_discovery = - AuthorityDiscovery::new(test_api, network.clone(), dht_event_rx); - - // Create sample dht event. - - let authority_id_1 = hash_authority_id("test-authority-id-1".as_bytes()).unwrap(); - let address_1: libp2p::Multiaddr = "/ip6/2001:db8::".parse().unwrap(); - - let mut serialized_addresses = vec![]; - schema::AuthorityAddresses { - addresses: vec![address_1.to_vec()], - } - .encode(&mut serialized_addresses) - .unwrap(); - - let mut signed_addresses = vec![]; - schema::SignedAuthorityAddresses { - addresses: serialized_addresses, - signature: "test-signature-1".as_bytes().to_vec(), - } - .encode(&mut signed_addresses) - .unwrap(); - - let dht_event = network::DhtEvent::ValueFound(vec![(authority_id_1, signed_addresses)]); - dht_event_tx.try_send(dht_event).unwrap(); - - // Make authority discovery handle the event. - - let f = || { - authority_discovery.handle_dht_events().unwrap(); - - // Expect authority discovery to set the priority set. - assert_eq!(network.set_priority_group_call.lock().unwrap().len(), 1); - - assert_eq!( - network.set_priority_group_call.lock().unwrap()[0], - ( - "authorities".to_string(), - HashSet::from_iter(vec![address_1.clone()].into_iter()) - ) - ); - - Ok(Async::Ready(())) - }; - - let mut runtime = current_thread::Runtime::new().unwrap(); - runtime.block_on(poll_fn::<(), (), _>(f)).unwrap(); - } -} diff --git a/core/basic-authorship/Cargo.toml b/core/basic-authorship/Cargo.toml deleted file mode 100644 index 0a98c151d6eaf..0000000000000 --- a/core/basic-authorship/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "substrate-basic-authorship" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -log = "0.4.8" -futures-preview = "0.3.0-alpha.19" -codec = { package = "parity-scale-codec", version = "1.0.0" } -sr-primitives = { path = "../../core/sr-primitives" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -client = { package = "substrate-client", path = "../../core/client" } -consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } -inherents = { package = "substrate-inherents", path = "../inherents" } -substrate-telemetry = { path = "../telemetry" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } - -[dev-dependencies] -test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs deleted file mode 100644 index 7f8b343f6512c..0000000000000 --- a/core/basic-authorship/src/basic_authorship.rs +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! A consensus proposer for "basic" chains which use the primitive inherent-data. - -// FIXME #1021 move this into substrate-consensus-common -// - -use std::{time, sync::Arc}; -use client::{ - error, Client as SubstrateClient, CallExecutor, - block_builder::api::BlockBuilder as BlockBuilderApi, -}; -use codec::Decode; -use consensus_common::{evaluation}; -use inherents::InherentData; -use log::{error, info, debug, trace}; -use primitives::{H256, Blake2Hasher, ExecutionContext}; -use sr_primitives::{ - traits::{ - Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, DigestFor, BlakeTwo256 - }, - generic::BlockId, -}; -use transaction_pool::txpool::{self, Pool as TransactionPool}; -use substrate_telemetry::{telemetry, CONSENSUS_INFO}; - -/// Proposer factory. -pub struct ProposerFactory where A: txpool::ChainApi { - /// The client instance. - pub client: Arc, - /// The transaction pool. - pub transaction_pool: Arc>, -} - -impl consensus_common::Environment for -ProposerFactory, A> -where - A: txpool::ChainApi, - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, - Block: BlockT, - RA: Send + Sync + 'static, - SubstrateClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilderApi, -{ - type Proposer = Proposer, A>; - type Error = error::Error; - - fn init( - &mut self, - parent_header: &::Header, - ) -> Result { - let parent_hash = parent_header.hash(); - - let id = BlockId::hash(parent_hash); - - info!("Starting consensus session on top of parent {:?}", parent_hash); - - let proposer = Proposer { - client: self.client.clone(), - parent_hash, - parent_id: id, - parent_number: *parent_header.number(), - transaction_pool: self.transaction_pool.clone(), - now: Box::new(time::Instant::now), - }; - - Ok(proposer) - } -} - -/// The proposer logic. -pub struct Proposer { - client: Arc, - parent_hash: ::Hash, - parent_id: BlockId, - parent_number: <::Header as HeaderT>::Number, - transaction_pool: Arc>, - now: Box time::Instant>, -} - -impl consensus_common::Proposer for -Proposer, A> -where - A: txpool::ChainApi, - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, - Block: BlockT, - RA: Send + Sync + 'static, - SubstrateClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilderApi, -{ - type Create = futures::future::Ready>; - type Error = error::Error; - - fn propose( - &mut self, - inherent_data: InherentData, - inherent_digests: DigestFor, - max_duration: time::Duration, - ) -> Self::Create { - // leave some time for evaluation and block finalization (33%) - let deadline = (self.now)() + max_duration - max_duration / 3; - futures::future::ready(self.propose_with(inherent_data, inherent_digests, deadline)) - } -} - -impl Proposer, A> where - A: txpool::ChainApi, - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, - Block: BlockT, - RA: Send + Sync + 'static, - SubstrateClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilderApi, -{ - fn propose_with( - &self, - inherent_data: InherentData, - inherent_digests: DigestFor, - deadline: time::Instant, - ) -> Result { - /// 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 utilization. - const MAX_SKIPPED_TRANSACTIONS: usize = 8; - - let mut block_builder = self.client.new_block_at(&self.parent_id, inherent_digests)?; - - // We don't check the API versions any further here since the dispatch compatibility - // check should be enough. - for extrinsic in self.client.runtime_api() - .inherent_extrinsics_with_context( - &self.parent_id, - ExecutionContext::BlockConstruction, - inherent_data - )? - { - block_builder.push(extrinsic)?; - } - - // proceed with transactions - let mut is_first = true; - let mut skipped = 0; - let mut unqueue_invalid = Vec::new(); - let pending_iterator = self.transaction_pool.ready(); - - debug!("Attempting to push transactions from the pool."); - for pending in pending_iterator { - if (self.now)() > deadline { - debug!("Consensus deadline reached when pushing block transactions, proceeding with proposing."); - break; - } - - trace!("[{:?}] Pushing to the block.", pending.hash); - match client::block_builder::BlockBuilder::push(&mut block_builder, pending.data.clone()) { - Ok(()) => { - debug!("[{:?}] Pushed to the block.", pending.hash); - } - Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhausted_resources() => { - if is_first { - debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash); - unqueue_invalid.push(pending.hash.clone()); - } 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) => { - debug!("[{:?}] Invalid transaction: {}", pending.hash, e); - unqueue_invalid.push(pending.hash.clone()); - } - } - - is_first = false; - } - - self.transaction_pool.remove_invalid(&unqueue_invalid); - - let block = block_builder.bake()?; - - info!("Prepared block for proposing at {} [hash: {:?}; parent_hash: {}; extrinsics: [{}]]", - block.header().number(), - ::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" => ?::Hash::from(block.header().hash()), - ); - - if Decode::decode(&mut block.encode().as_slice()).as_ref() != Ok(&block) { - error!("Failed to verify block encoding/decoding"); - } - - if let Err(err) = evaluation::evaluate_initial(&block, &self.parent_hash, self.parent_number) { - error!("Failed to evaluate authored block: {:?}", err); - } - - Ok(block) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use std::cell::RefCell; - use consensus_common::{Environment, Proposer}; - use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; - - fn extrinsic(nonce: u64) -> Extrinsic { - Transfer { - amount: Default::default(), - nonce, - from: AccountKeyring::Alice.into(), - to: Default::default(), - }.into_signed_tx() - } - - #[test] - fn should_cease_building_block_when_deadline_is_reached() { - // given - let client = Arc::new(test_client::new()); - let chain_api = transaction_pool::FullChainApi::new(client.clone()); - let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); - - futures::executor::block_on( - txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)], false) - ).unwrap(); - - let mut proposer_factory = ProposerFactory { - client: client.clone(), - 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 = futures::executor::block_on(proposer.propose(Default::default(), 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/core/basic-authorship/src/lib.rs b/core/basic-authorship/src/lib.rs deleted file mode 100644 index 7961e4fe9e9df..0000000000000 --- a/core/basic-authorship/src/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Basic implementation of block-authoring logic. -//! -//! # Example -//! -//! ``` -//! # use substrate_basic_authorship::ProposerFactory; -//! # use consensus_common::{Environment, Proposer}; -//! # use sr_primitives::generic::BlockId; -//! # use std::{sync::Arc, time::Duration}; -//! # use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; -//! # use transaction_pool::txpool::{self, Pool as TransactionPool}; -//! # let client = Arc::new(test_client::new()); -//! # let chain_api = transaction_pool::FullChainApi::new(client.clone()); -//! # let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); -//! // The first step is to create a `ProposerFactory`. -//! let mut proposer_factory = ProposerFactory { -//! client: client.clone(), -//! transaction_pool: txpool.clone(), -//! }; -//! -//! // From this factory, we create a `Proposer`. -//! let mut proposer = proposer_factory.init( -//! &client.header(&BlockId::number(0)).unwrap().unwrap(), -//! ).unwrap(); -//! -//! // This `Proposer` allows us to create a block proposition. -//! // The proposer will grab transactions from the transaction pool, and put them into the block. -//! let future = proposer.propose( -//! Default::default(), -//! Default::default(), -//! Duration::from_secs(2) -//! ); -//! -//! // We wait until the proposition is performed. -//! let block = futures::executor::block_on(future).unwrap(); -//! println!("Generated block: {:?}", block); -//! ``` -//! - -mod basic_authorship; - -pub use crate::basic_authorship::{ProposerFactory, Proposer}; diff --git a/core/chain-spec/Cargo.toml b/core/chain-spec/Cargo.toml deleted file mode 100644 index 1a3c56affb661..0000000000000 --- a/core/chain-spec/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "substrate-chain-spec" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -chain-spec-derive = { package = "substrate-chain-spec-derive", path = "./derive" } -impl-trait-for-tuples = "0.1.2" -network = { package = "substrate-network", path = "../../core/network" } -primitives = { package = "substrate-primitives", path = "../primitives" } -serde = { version = "1.0.101", features = ["derive"] } -serde_json = "1.0.41" -sr-primitives = { path = "../../core/sr-primitives" } -tel = { package = "substrate-telemetry", path = "../../core/telemetry" } - -[dev-dependencies] diff --git a/core/chain-spec/derive/Cargo.toml b/core/chain-spec/derive/Cargo.toml deleted file mode 100644 index 2e42ca0cf3a70..0000000000000 --- a/core/chain-spec/derive/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "substrate-chain-spec-derive" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -proc-macro-crate = "0.1.4" -proc-macro2 = "1.0.4" -quote = "1.0.2" -syn = "1.0.5" - -[dev-dependencies] diff --git a/core/chain-spec/derive/src/impls.rs b/core/chain-spec/derive/src/impls.rs deleted file mode 100644 index cdc27aef0b9c6..0000000000000 --- a/core/chain-spec/derive/src/impls.rs +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use proc_macro2::{Span, TokenStream}; -use quote::quote; -use syn::{DeriveInput, Ident, Error}; -use proc_macro_crate::crate_name; - -const CRATE_NAME: &str = "substrate-chain-spec"; -const ATTRIBUTE_NAME: &str = "forks"; - -/// Implements `Extension's` `Group` accessor. -/// -/// The struct that derives this implementation will be usable within the `ChainSpec` file. -/// The derive implements a by-type accessor method. -pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { - derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types, fields| { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let forks = fields.named.iter().find_map(|f| { - if f.attrs.iter().any(|attr| attr.path.is_ident(ATTRIBUTE_NAME)) { - let typ = &f.ty; - Some(quote! { #typ }) - } else { - None - } - }).unwrap_or_else(|| quote! { #crate_name::NoExtension }); - - quote! { - impl #impl_generics #crate_name::Extension for #name #ty_generics #where_clause { - type Forks = #forks; - - fn get(&self) -> Option<&T> { - use std::any::{Any, TypeId}; - - match TypeId::of::() { - #( x if x == TypeId::of::<#field_types>() => Any::downcast_ref(&self.#field_names) ),*, - _ => None, - } - } - } - } - }) -} - - -/// Implements required traits and creates `Fork` structs for `ChainSpec` custom parameter group. -pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { - derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types, _fields| { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let fork_name = Ident::new(&format!("{}Fork", name), Span::call_site()); - - let fork_fields = generate_fork_fields(&crate_name, &field_names, &field_types); - let to_fork = generate_base_to_fork(&fork_name, &field_names); - let combine_with = generate_combine_with(&field_names); - let to_base = generate_fork_to_base(name, &field_names); - - quote! { - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] - pub struct #fork_name #ty_generics #where_clause { - #fork_fields - } - - impl #impl_generics #crate_name::Group for #name #ty_generics #where_clause { - type Fork = #fork_name #ty_generics; - - fn to_fork(self) -> Self::Fork { - use #crate_name::Group; - #to_fork - } - } - - impl #impl_generics #crate_name::Fork for #fork_name #ty_generics #where_clause { - type Base = #name #ty_generics; - - fn combine_with(&mut self, other: Self) { - use #crate_name::Fork; - #combine_with - } - - fn to_base(self) -> Option { - use #crate_name::Fork; - #to_base - } - } - } - }) -} - -pub fn derive( - ast: &DeriveInput, - derive: impl Fn( - &Ident, &Ident, &syn::Generics, Vec<&Ident>, Vec<&syn::Type>, &syn::FieldsNamed, - ) -> TokenStream, -) -> proc_macro::TokenStream { - let err = || { - let err = Error::new( - Span::call_site(), - "ChainSpecGroup is only avaible for structs with named fields." - ).to_compile_error(); - quote!( #err ).into() - }; - - let data = match &ast.data { - syn::Data::Struct(ref data) => data, - _ => return err(), - }; - - let fields = match &data.fields { - syn::Fields::Named(ref named) => named, - _ => return err(), - }; - - const PROOF: &str = "CARGO_PKG_NAME always defined when compiling; qed"; - let name = &ast.ident; - let crate_name = match crate_name(CRATE_NAME) { - Ok(chain_spec_name) => chain_spec_name, - Err(e) => if std::env::var("CARGO_PKG_NAME").expect(PROOF) == CRATE_NAME { - // we return the name of the crate here instead of `crate` to support doc tests. - CRATE_NAME.replace("-", "_") - } else { - let err = Error::new(Span::call_site(), &e).to_compile_error(); - return quote!( #err ).into() - }, - }; - let crate_name = Ident::new(&crate_name, Span::call_site()); - let field_names = fields.named.iter().flat_map(|x| x.ident.as_ref()).collect::>(); - let field_types = fields.named.iter().map(|x| &x.ty).collect::>(); - - derive(&crate_name, name, &ast.generics, field_names, field_types, fields).into() -} - -fn generate_fork_fields( - crate_name: &Ident, - names: &[&Ident], - types: &[&syn::Type], -) -> TokenStream { - let crate_name = std::iter::repeat(crate_name); - quote! { - #( pub #names: Option<<#types as #crate_name::Group>::Fork>, )* - } -} - -fn generate_base_to_fork( - fork_name: &Ident, - names: &[&Ident], -) -> TokenStream { - let names2 = names.to_vec(); - - quote!{ - #fork_name { - #( #names: Some(self.#names2.to_fork()), )* - } - } -} - -fn generate_combine_with( - names: &[&Ident], -) -> TokenStream { - let names2 = names.to_vec(); - - quote!{ - #( self.#names.combine_with(other.#names2); )* - } -} - -fn generate_fork_to_base( - fork: &Ident, - names: &[&Ident], -) -> TokenStream { - let names2 = names.to_vec(); - - quote!{ - Some(#fork { - #( #names: self.#names2?.to_base()?, )* - }) - } -} diff --git a/core/chain-spec/derive/src/lib.rs b/core/chain-spec/derive/src/lib.rs deleted file mode 100644 index bcd50c1021785..0000000000000 --- a/core/chain-spec/derive/src/lib.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Macros to derive chain spec extension traits implementation. - -extern crate proc_macro; - -mod impls; - -use proc_macro::TokenStream; - -#[proc_macro_derive(ChainSpecGroup)] -pub fn group_derive(input: TokenStream) -> TokenStream { - match syn::parse(input) { - Ok(ast) => impls::group_derive(&ast), - Err(e) => e.to_compile_error().into(), - } -} - -#[proc_macro_derive(ChainSpecExtension, attributes(forks))] -pub fn extensions_derive(input: TokenStream) -> TokenStream { - match syn::parse(input) { - Ok(ast) => impls::extension_derive(&ast), - Err(e) => e.to_compile_error().into(), - } -} diff --git a/core/chain-spec/src/chain_spec.rs b/core/chain-spec/src/chain_spec.rs deleted file mode 100644 index 0f69654b9e8f6..0000000000000 --- a/core/chain-spec/src/chain_spec.rs +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate chain configurations. - -use std::borrow::Cow; -use std::collections::HashMap; -use std::fs::File; -use std::path::PathBuf; -use std::rc::Rc; -use serde::{Serialize, Deserialize}; -use primitives::storage::{StorageKey, StorageData}; -use sr_primitives::{BuildStorage, StorageOverlay, ChildrenStorageOverlay}; -use serde_json as json; -use crate::RuntimeGenesis; -use network::Multiaddr; -use tel::TelemetryEndpoints; - -enum GenesisSource { - File(PathBuf), - Binary(Cow<'static, [u8]>), - Factory(Rc G>), -} - -impl Clone for GenesisSource { - fn clone(&self) -> Self { - match *self { - GenesisSource::File(ref path) => GenesisSource::File(path.clone()), - GenesisSource::Binary(ref d) => GenesisSource::Binary(d.clone()), - GenesisSource::Factory(ref f) => GenesisSource::Factory(f.clone()), - } - } -} - -impl GenesisSource { - fn resolve(&self) -> Result, String> { - #[derive(Serialize, Deserialize)] - struct GenesisContainer { - genesis: Genesis, - } - - match self { - GenesisSource::File(path) => { - let file = File::open(path) - .map_err(|e| format!("Error opening spec file: {}", e))?; - let genesis: GenesisContainer = json::from_reader(file) - .map_err(|e| format!("Error parsing spec file: {}", e))?; - Ok(genesis.genesis) - }, - GenesisSource::Binary(buf) => { - let genesis: GenesisContainer = json::from_reader(buf.as_ref()) - .map_err(|e| format!("Error parsing embedded file: {}", e))?; - Ok(genesis.genesis) - }, - GenesisSource::Factory(f) => Ok(Genesis::Runtime(f())), - } - } -} - -impl<'a, G: RuntimeGenesis, E> BuildStorage for &'a ChainSpec { - fn build_storage(&self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { - match self.genesis.resolve()? { - Genesis::Runtime(gc) => gc.build_storage(), - Genesis::Raw(map, children_map) => Ok(( - map.into_iter().map(|(k, v)| (k.0, v.0)).collect(), - children_map.into_iter().map(|(sk, map)| ( - sk.0, - map.into_iter().map(|(k, v)| (k.0, v.0)).collect(), - )).collect(), - )), - } - } - - fn assimilate_storage( - &self, - _: &mut (StorageOverlay, ChildrenStorageOverlay) - ) -> Result<(), String> { - Err("`assimilate_storage` not implemented for `ChainSpec`.".into()) - } -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -#[serde(deny_unknown_fields)] -enum Genesis { - Runtime(G), - Raw( - HashMap, - HashMap>, - ), -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -#[serde(rename_all = "camelCase")] -#[serde(deny_unknown_fields)] -struct ChainSpecFile { - pub name: String, - pub id: String, - pub boot_nodes: Vec, - pub telemetry_endpoints: Option, - pub protocol_id: Option, - pub properties: Option, - #[serde(flatten)] - pub extensions: E, - // Never used, left only for backward compatibility. - consensus_engine: (), - #[serde(skip_serializing)] - genesis: serde::de::IgnoredAny, -} - -/// Arbitrary properties defined in chain spec as a JSON object -pub type Properties = json::map::Map; - -/// A type denoting empty extensions. -/// -/// We use `Option` here since `()` is not flattenable by serde. -pub type NoExtension = Option<()>; - -/// A configuration of a chain. Can be used to build a genesis block. -pub struct ChainSpec { - spec: ChainSpecFile, - genesis: GenesisSource, -} - -impl Clone for ChainSpec { - fn clone(&self) -> Self { - ChainSpec { - spec: self.spec.clone(), - genesis: self.genesis.clone(), - } - } -} - -impl ChainSpec { - /// A list of bootnode addresses. - pub fn boot_nodes(&self) -> &[String] { - &self.spec.boot_nodes - } - - /// Spec name. - pub fn name(&self) -> &str { - &self.spec.name - } - - /// Spec id. - pub fn id(&self) -> &str { - &self.spec.id - } - - /// Telemetry endpoints (if any) - pub fn telemetry_endpoints(&self) -> &Option { - &self.spec.telemetry_endpoints - } - - /// Network protocol id. - pub fn protocol_id(&self) -> Option<&str> { - self.spec.protocol_id.as_ref().map(String::as_str) - } - - /// Additional loosly-typed properties of the chain. - /// - /// Returns an empty JSON object if 'properties' not defined in config - pub fn properties(&self) -> Properties { - self.spec.properties.as_ref().unwrap_or(&json::map::Map::new()).clone() - } - - /// Add a bootnode to the list. - pub fn add_boot_node(&mut self, addr: Multiaddr) { - self.spec.boot_nodes.push(addr.to_string()) - } - - /// Returns a reference to defined chain spec extensions. - pub fn extensions(&self) -> &E { - &self.spec.extensions - } - - /// Create hardcoded spec. - pub fn from_genesis G + 'static>( - name: &str, - id: &str, - constructor: F, - boot_nodes: Vec, - telemetry_endpoints: Option, - protocol_id: Option<&str>, - properties: Option, - extensions: E, - ) -> Self { - let spec = ChainSpecFile { - name: name.to_owned(), - id: id.to_owned(), - boot_nodes: boot_nodes, - telemetry_endpoints, - protocol_id: protocol_id.map(str::to_owned), - properties, - extensions, - consensus_engine: (), - genesis: Default::default(), - }; - - ChainSpec { - spec, - genesis: GenesisSource::Factory(Rc::new(constructor)), - } - } -} - -impl ChainSpec { - /// Parse json content into a `ChainSpec` - pub fn from_json_bytes(json: impl Into>) -> Result { - let json = json.into(); - let spec = json::from_slice(json.as_ref()) - .map_err(|e| format!("Error parsing spec file: {}", e))?; - Ok(ChainSpec { - spec, - genesis: GenesisSource::Binary(json), - }) - } - - /// Parse json file into a `ChainSpec` - pub fn from_json_file(path: PathBuf) -> Result { - let file = File::open(&path) - .map_err(|e| format!("Error opening spec file: {}", e))?; - let spec = json::from_reader(file) - .map_err(|e| format!("Error parsing spec file: {}", e))?; - Ok(ChainSpec { - spec, - genesis: GenesisSource::File(path), - }) - } -} - -impl ChainSpec { - /// Dump to json string. - pub fn to_json(self, raw: bool) -> Result { - #[derive(Serialize, Deserialize)] - struct Container { - #[serde(flatten)] - spec: ChainSpecFile, - genesis: Genesis, - - }; - let genesis = match (raw, self.genesis.resolve()?) { - (true, Genesis::Runtime(g)) => { - let storage = g.build_storage()?; - let top = storage.0.into_iter() - .map(|(k, v)| (StorageKey(k), StorageData(v))) - .collect(); - let children = storage.1.into_iter() - .map(|(sk, child)| ( - StorageKey(sk), - child.into_iter() - .map(|(k, v)| (StorageKey(k), StorageData(v))) - .collect(), - )) - .collect(); - - Genesis::Raw(top, children) - }, - (_, genesis) => genesis, - }; - let spec = Container { - spec: self.spec, - genesis, - }; - json::to_string_pretty(&spec) - .map_err(|e| format!("Error generating spec json: {}", e)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[derive(Debug, Serialize, Deserialize)] - struct Genesis(HashMap); - - impl BuildStorage for Genesis { - fn assimilate_storage( - &self, - storage: &mut (StorageOverlay, ChildrenStorageOverlay), - ) -> Result<(), String> { - storage.0.extend( - self.0.iter().map(|(a, b)| (a.clone().into_bytes(), b.clone().into_bytes())) - ); - Ok(()) - } - } - - type TestSpec = ChainSpec; - - #[test] - fn should_deserailize_example_chain_spec() { - let spec1 = TestSpec::from_json_bytes(Cow::Owned( - include_bytes!("../res/chain_spec.json").to_vec() - )).unwrap(); - let spec2 = TestSpec::from_json_file( - PathBuf::from("./res/chain_spec.json") - ).unwrap(); - - assert_eq!(spec1.to_json(false), spec2.to_json(false)); - } - - #[derive(Debug, Serialize, Deserialize)] - #[serde(rename_all = "camelCase")] - struct Extension1 { - my_property: String, - } - - type TestSpec2 = ChainSpec; - - #[test] - fn should_deserialize_chain_spec_with_extensions() { - let spec = TestSpec2::from_json_bytes(Cow::Owned( - include_bytes!("../res/chain_spec2.json").to_vec() - )).unwrap(); - - assert_eq!(spec.extensions().my_property, "Test Extension"); - } -} diff --git a/core/chain-spec/src/lib.rs b/core/chain-spec/src/lib.rs deleted file mode 100644 index 705be998b7967..0000000000000 --- a/core/chain-spec/src/lib.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate chain configurations. -//! -//! This crate contains structs and utilities to declare -//! a runtime-specific configuration file (a.k.a chain spec). -//! -//! Basic chain spec type containing all required parameters is -//! [`ChainSpec`](./struct.ChainSpec.html). It can be extended with -//! additional options that contain configuration specific to your chain. -//! Usually the extension is going to be an amalgamate of types exposed -//! by Substrate core modules. To allow the core modules to retrieve -//! their configuration from your extension you should use `ChainSpecExtension` -//! macro exposed by this crate. -//! -//! ```rust -//! use std::collections::HashMap; -//! use serde::{Serialize, Deserialize}; -//! use substrate_chain_spec::{ChainSpec, ChainSpecExtension}; -//! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] -//! pub struct MyExtension { -//! pub known_blocks: HashMap, -//! } -//! -//! pub type MyChainSpec = ChainSpec; -//! ``` -//! -//! Some parameters may require different values depending on the -//! current blockchain height (a.k.a. forks). You can use `ChainSpecGroup` -//! macro and provided [`Forks`](./struct.Forks.html) structure to put -//! such parameters to your chain spec. -//! This will allow to override a single parameter starting at specific -//! block number. -//! -//! ```rust -//! use serde::{Serialize, Deserialize}; -//! use substrate_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension}; -//! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] -//! pub struct ClientParams { -//! max_block_size: usize, -//! max_extrinsic_size: usize, -//! } -//! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] -//! pub struct PoolParams { -//! max_transaction_size: usize, -//! } -//! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] -//! pub struct Extension { -//! pub client: ClientParams, -//! pub pool: PoolParams, -//! } -//! -//! pub type BlockNumber = u64; -//! -//! /// A chain spec supporting forkable `ClientParams`. -//! pub type MyChainSpec1 = ChainSpec>; -//! -//! /// A chain spec supporting forkable `Extension`. -//! pub type MyChainSpec2 = ChainSpec>; -//! ``` -//! -//! It's also possible to have a set of parameters that is allowed to change -//! with block numbers (i.e. is forkable), and another set that is not subject to changes. -//! This is also possible by declaring an extension that contains `Forks` within it. -//! -//! -//! ```rust -//! use serde::{Serialize, Deserialize}; -//! use substrate_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension}; -//! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] -//! pub struct ClientParams { -//! max_block_size: usize, -//! max_extrinsic_size: usize, -//! } -//! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] -//! pub struct PoolParams { -//! max_transaction_size: usize, -//! } -//! -//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] -//! pub struct Extension { -//! pub client: ClientParams, -//! #[forks] -//! pub pool: Forks, -//! } -//! -//! pub type MyChainSpec = ChainSpec; -//! ``` - - -mod chain_spec; -mod extension; - -pub use chain_spec::{ChainSpec, Properties, NoExtension}; -pub use extension::{Group, Fork, Forks, Extension}; -pub use chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; - -use serde::{Serialize, de::DeserializeOwned}; -use sr_primitives::BuildStorage; - -/// A set of traits for the runtime genesis config. -pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} -impl RuntimeGenesis for T {} diff --git a/core/cli/Cargo.toml b/core/cli/Cargo.toml deleted file mode 100644 index a2723484ad4c1..0000000000000 --- a/core/cli/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "substrate-cli" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Substrate CLI interface." -edition = "2018" - -[dependencies] -clap = "2.33.0" -derive_more = "0.15.0" -env_logger = "0.7.0" -log = "0.4.8" -atty = "0.2.13" -regex = "1.3.1" -time = "0.1.42" -ansi_term = "0.12.1" -lazy_static = "1.4.0" -app_dirs = "1.2.1" -tokio = "0.1.22" -futures = "0.1.29" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19", features = ["compat"] } -fdlimit = "0.1.1" -exit-future = "0.1.4" -serde_json = "1.0.41" -panic-handler = { package = "substrate-panic-handler", path = "../../core/panic-handler" } -client = { package = "substrate-client", path = "../../core/client" } -header-metadata = { package = "substrate-header-metadata", path = "../../core/client/header-metadata" } -network = { package = "substrate-network", path = "../../core/network" } -sr-primitives = { path = "../../core/sr-primitives" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -service = { package = "substrate-service", path = "../../core/service" } -state-machine = { package = "substrate-state-machine", path = "../../core/state-machine" } -substrate-telemetry = { path = "../../core/telemetry" } -keyring = { package = "substrate-keyring", path = "../keyring" } -names = "0.11.0" -structopt = "0.3.3" -rpassword = "4.0.1" - -[dev-dependencies] -tempdir = "0.3.7" diff --git a/core/cli/src/error.rs b/core/cli/src/error.rs deleted file mode 100644 index 600e73d44fe73..0000000000000 --- a/core/cli/src/error.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Initialization errors. - -use client; - -/// Result type alias for the CLI. -pub type Result = std::result::Result; - -/// Error type for the CLI. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Io error - Io(std::io::Error), - /// Cli error - Cli(clap::Error), - /// Service error - Service(service::Error), - /// Client error - Client(client::error::Error), - /// Input error - Input(String), - /// Invalid listen multiaddress - #[display(fmt="Invalid listen multiaddress")] - InvalidListenMultiaddress, - /// Other uncategorized error. - Other(String), -} - -/// Must be implemented explicitly because `derive_more` won't generate this -/// case due to conflicting derive for `Other(String)`. -impl std::convert::From for Error { - fn from(s: String) -> Error { - Error::Input(s) - } -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Io(ref err) => Some(err), - Error::Cli(ref err) => Some(err), - Error::Service(ref err) => Some(err), - Error::Client(ref err) => Some(err), - Error::Input(_) => None, - Error::InvalidListenMultiaddress => None, - Error::Other(_) => None, - } - } -} diff --git a/core/cli/src/informant.rs b/core/cli/src/informant.rs deleted file mode 100644 index f7c23ba47918a..0000000000000 --- a/core/cli/src/informant.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Console informant. Prints sync progress and block events. Runs on the calling thread. - -use client::BlockchainEvents; -use futures::{Future, Stream}; -use futures03::{StreamExt as _, TryStreamExt as _}; -use log::{info, warn}; -use sr_primitives::traits::Header; -use service::AbstractService; -use std::time::Duration; - -mod display; - -/// Creates an informant in the form of a `Future` that must be polled regularly. -pub fn build(service: &impl AbstractService) -> impl Future { - let client = service.client(); - - let mut display = display::InformantDisplay::new(); - - let display_notifications = service - .network_status(Duration::from_millis(5000)) - .for_each(move |(net_status, _)| { - let info = client.info(); - display.display(&info, net_status); - Ok(()) - }); - - let client = service.client(); - let mut last_best = { - let info = client.info(); - Some((info.chain.best_number, info.chain.best_hash)) - }; - - let display_block_import = client.import_notification_stream().map(|v| Ok::<_, ()>(v)).compat().for_each(move |n| { - // detect and log reorganizations. - if let Some((ref last_num, ref last_hash)) = last_best { - if n.header.parent_hash() != last_hash && n.is_new_best { - let maybe_ancestor = header_metadata::lowest_common_ancestor( - &*client, - last_hash.clone(), - n.hash, - ); - - match maybe_ancestor { - Ok(ref ancestor) if ancestor.hash != *last_hash => info!( - "Reorg from #{},{} to #{},{}, common ancestor #{},{}", - last_num, last_hash, - n.header.number(), n.hash, - ancestor.number, ancestor.hash, - ), - Ok(_) => {}, - Err(e) => warn!("Error computing tree route: {}", e), - } - } - } - - if n.is_new_best { - last_best = Some((n.header.number().clone(), n.hash.clone())); - } - - info!(target: "substrate", "Imported #{} ({})", n.header.number(), n.hash); - Ok(()) - }); - - display_notifications.join(display_block_import) - .map(|((), ())| ()) -} diff --git a/core/cli/src/lib.rs b/core/cli/src/lib.rs deleted file mode 100644 index b49f686ae62f7..0000000000000 --- a/core/cli/src/lib.rs +++ /dev/null @@ -1,1046 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate CLI library. - -#![warn(missing_docs)] -#![warn(unused_extern_crates)] - -#[macro_use] -mod traits; -mod params; -mod execution_strategy; -pub mod error; -pub mod informant; - -use client::ExecutionStrategies; -use service::{ - config::Configuration, - ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert, - RuntimeGenesis, ChainSpecExtension, PruningMode, ChainSpec, -}; -use network::{ - self, - multiaddr::Protocol, - config::{ - NetworkConfiguration, TransportConfig, NonReservedPeerMode, NodeKeyConfig, build_multiaddr - }, -}; -use primitives::H256; - -use std::{ - io::{Write, Read, Seek, Cursor, stdin, stdout, ErrorKind}, iter, fs::{self, File}, - net::{Ipv4Addr, SocketAddr}, path::{Path, PathBuf}, str::FromStr, -}; - -use names::{Generator, Name}; -use regex::Regex; -use structopt::{StructOpt, clap::AppSettings}; -#[doc(hidden)] -pub use structopt::clap::App; -use params::{ - RunCmd, PurgeChainCmd, RevertCmd, ImportBlocksCmd, ExportBlocksCmd, BuildSpecCmd, - NetworkConfigurationParams, MergeParameters, TransactionPoolParams, - NodeKeyParams, NodeKeyType, Cors, -}; -pub use params::{NoCustom, CoreParams, SharedParams, ExecutionStrategy as ExecutionStrategyParam}; -pub use traits::{GetLogFilter, AugmentClap}; -use app_dirs::{AppInfo, AppDataType}; -use log::info; -use lazy_static::lazy_static; - -use futures::Future; -use substrate_telemetry::TelemetryEndpoints; - -/// The maximum number of characters for a node name. -const NODE_NAME_MAX_LENGTH: usize = 32; - -/// The file name of the node's Ed25519 secret key inside the chain-specific -/// network config directory, if neither `--node-key` nor `--node-key-file` -/// is specified in combination with `--node-key-type=ed25519`. -const NODE_KEY_ED25519_FILE: &str = "secret_ed25519"; - -/// Executable version. Used to pass version information from the root crate. -#[derive(Clone)] -pub struct VersionInfo { - /// Implementaiton name. - pub name: &'static str, - /// Implementation version. - pub version: &'static str, - /// SCM Commit hash. - pub commit: &'static str, - /// Executable file name. - pub executable_name: &'static str, - /// Executable file description. - pub description: &'static str, - /// Executable file author. - pub author: &'static str, - /// Support URL. - pub support_url: &'static str, -} - -/// Something that can be converted into an exit signal. -pub trait IntoExit { - /// Exit signal type. - type Exit: Future + Send + 'static; - /// Convert into exit signal. - fn into_exit(self) -> Self::Exit; -} - -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 < NODE_NAME_MAX_LENGTH { - break node_name - } - }; - - result -} - -fn load_spec(cli: &SharedParams, factory: F) -> error::Result> where - G: RuntimeGenesis, - E: ChainSpecExtension, - F: FnOnce(&str) -> Result>, String>, -{ - let chain_key = get_chain_key(cli); - let spec = match factory(&chain_key)? { - Some(spec) => spec, - None => ChainSpec::from_json_file(PathBuf::from(chain_key))? - }; - Ok(spec) -} - -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") - ) -} - -/// Check whether a node name is considered as valid -fn is_node_name_valid(_name: &str) -> Result<(), &str> { - let name = _name.to_string(); - if name.chars().count() >= NODE_NAME_MAX_LENGTH { - return Err("Node name too long"); - } - - let invalid_chars = r"[\\.@]"; - let re = Regex::new(invalid_chars).unwrap(); - if re.is_match(&name) { - return Err("Node name should not contain invalid chars such as '.' and '@'"); - } - - let invalid_patterns = r"(https?:\\/+)?(www)+"; - let re = Regex::new(invalid_patterns).unwrap(); - if re.is_match(&name) { - return Err("Node name should not contain urls"); - } - - Ok(()) -} - -/// Parse command line interface arguments and prepares the command for execution. -/// -/// Before returning, this function performs various initializations, such as initializing the -/// panic handler and the logger, or increasing the limit for file descriptors. -/// -/// # Remarks -/// -/// `CC` is a custom subcommand. This needs to be an `enum`! If no custom subcommand is required, -/// `NoCustom` can be used as type here. -/// -/// `RP` are custom parameters for the run command. This needs to be a `struct`! The custom -/// parameters are visible to the user as if they were normal run command parameters. If no custom -/// parameters are required, `NoCustom` can be used as type here. -pub fn parse_and_prepare<'a, CC, RP, I>( - version: &'a VersionInfo, - impl_name: &'static str, - args: I, -) -> ParseAndPrepare<'a, CC, RP> -where - CC: StructOpt + Clone + GetLogFilter, - RP: StructOpt + Clone + AugmentClap, - I: IntoIterator, - ::Item: Into + Clone, -{ - let full_version = service::config::full_version_from_strs( - version.version, - version.commit - ); - - panic_handler::set(version.support_url, &full_version); - - let matches = CoreParams::::clap() - .name(version.executable_name) - .author(version.author) - .about(version.description) - .version(&(full_version + "\n")[..]) - .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) => ParseAndPrepare::Run( - ParseAndPrepareRun { params, impl_name, version } - ), - params::CoreParams::BuildSpec(params) => ParseAndPrepare::BuildSpec( - ParseAndPrepareBuildSpec { params, version } - ), - params::CoreParams::ExportBlocks(params) => ParseAndPrepare::ExportBlocks( - ParseAndPrepareExport { params, version } - ), - params::CoreParams::ImportBlocks(params) => ParseAndPrepare::ImportBlocks( - ParseAndPrepareImport { params, version } - ), - params::CoreParams::PurgeChain(params) => ParseAndPrepare::PurgeChain( - ParseAndPreparePurge { params, version } - ), - params::CoreParams::Revert(params) => ParseAndPrepare::RevertChain( - ParseAndPrepareRevert { params, version } - ), - params::CoreParams::Custom(params) => ParseAndPrepare::CustomCommand(params), - } -} - -/// Output of calling `parse_and_prepare`. -#[must_use] -pub enum ParseAndPrepare<'a, CC, RP> { - /// Command ready to run the main client. - Run(ParseAndPrepareRun<'a, RP>), - /// Command ready to build chain specs. - BuildSpec(ParseAndPrepareBuildSpec<'a>), - /// Command ready to export the chain. - ExportBlocks(ParseAndPrepareExport<'a>), - /// Command ready to import the chain. - ImportBlocks(ParseAndPrepareImport<'a>), - /// Command ready to purge the chain. - PurgeChain(ParseAndPreparePurge<'a>), - /// Command ready to revert the chain. - RevertChain(ParseAndPrepareRevert<'a>), - /// An additional custom command passed to `parse_and_prepare`. - CustomCommand(CC), -} - -/// Command ready to run the main client. -pub struct ParseAndPrepareRun<'a, RP> { - params: MergeParameters, - impl_name: &'static str, - version: &'a VersionInfo, -} - -impl<'a, RP> ParseAndPrepareRun<'a, RP> { - /// Runs the command and runs the main client. - pub fn run( - self, - spec_factory: S, - exit: Exit, - run_service: RS, - ) -> error::Result<()> - where - S: FnOnce(&str) -> Result>, String>, - E: Into, - RP: StructOpt + Clone, - C: Default, - G: RuntimeGenesis, - CE: ChainSpecExtension, - Exit: IntoExit, - RS: FnOnce(Exit, RunCmd, RP, Configuration) -> Result<(), E> - { - let config = create_run_node_config( - self.params.left.clone(), spec_factory, self.impl_name, self.version, - )?; - - run_service(exit, self.params.left, self.params.right, config).map_err(Into::into) - } -} - -/// Command ready to build chain specs. -pub struct ParseAndPrepareBuildSpec<'a> { - params: BuildSpecCmd, - version: &'a VersionInfo, -} - -impl<'a> ParseAndPrepareBuildSpec<'a> { - /// Runs the command and build the chain specs. - pub fn run( - self, - spec_factory: S - ) -> error::Result<()> where - S: FnOnce(&str) -> Result>, String>, - G: RuntimeGenesis, - E: ChainSpecExtension, - { - info!("Building chain spec"); - let raw_output = self.params.raw; - let mut spec = load_spec(&self.params.shared_params, spec_factory)?; - with_default_boot_node(&mut spec, self.params, self.version)?; - let json = service::chain_ops::build_spec(spec, raw_output)?; - - print!("{}", json); - - Ok(()) - } -} - -/// Command ready to export the chain. -pub struct ParseAndPrepareExport<'a> { - params: ExportBlocksCmd, - version: &'a VersionInfo, -} - -impl<'a> ParseAndPrepareExport<'a> { - /// Runs the command and exports from the chain. - pub fn run_with_builder( - self, - builder: F, - spec_factory: S, - exit: Exit, - ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - F: FnOnce(Configuration) -> Result, - B: ServiceBuilderExport, - C: Default, - G: RuntimeGenesis, - E: ChainSpecExtension, - Exit: IntoExit - { - let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; - - info!("DB path: {}", config.database_path.display()); - let from = self.params.from.unwrap_or(1); - let to = self.params.to; - let json = self.params.json; - - let file: Box = match self.params.output { - Some(filename) => Box::new(File::create(filename)?), - None => Box::new(stdout()), - }; - - builder(config)?.export_blocks(exit.into_exit(), file, from.into(), to.map(Into::into), json)?; - Ok(()) - } -} - -/// Command ready to import the chain. -pub struct ParseAndPrepareImport<'a> { - params: ImportBlocksCmd, - version: &'a VersionInfo, -} - -impl<'a> ParseAndPrepareImport<'a> { - /// Runs the command and imports to the chain. - pub fn run_with_builder( - self, - builder: F, - spec_factory: S, - exit: Exit, - ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - F: FnOnce(Configuration) -> Result, - B: ServiceBuilderImport, - C: Default, - G: RuntimeGenesis, - E: ChainSpecExtension, - Exit: IntoExit - { - let mut config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; - config.wasm_method = self.params.wasm_method.into(); - config.execution_strategies = ExecutionStrategies { - importing: self.params.execution.into(), - other: self.params.execution.into(), - ..Default::default() - }; - - let file: Box = match self.params.input { - Some(filename) => Box::new(File::open(filename)?), - None => { - let mut buffer = Vec::new(); - stdin().read_to_end(&mut buffer)?; - Box::new(Cursor::new(buffer)) - }, - }; - - let fut = builder(config)?.import_blocks(exit.into_exit(), file)?; - tokio::run(fut); - Ok(()) - } -} - -/// Command ready to purge the chain. -pub struct ParseAndPreparePurge<'a> { - params: PurgeChainCmd, - version: &'a VersionInfo, -} - -impl<'a> ParseAndPreparePurge<'a> { - /// Runs the command and purges the chain. - pub fn run( - self, - spec_factory: S - ) -> error::Result<()> where - S: FnOnce(&str) -> Result>, String>, - G: RuntimeGenesis, - E: ChainSpecExtension, - { - let config = create_config_with_db_path::<(), _, _, _>( - spec_factory, &self.params.shared_params, self.version - )?; - let db_path = config.database_path; - - if !self.params.yes { - 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(()); - }, - } - } - - match fs::remove_dir_all(&db_path) { - Result::Ok(_) => { - println!("{:?} removed.", &db_path); - Ok(()) - }, - Result::Err(ref err) if err.kind() == ErrorKind::NotFound => { - println!("{:?} did not exist.", &db_path); - Ok(()) - }, - Result::Err(err) => Result::Err(err.into()) - } - } -} - -/// Command ready to revert the chain. -pub struct ParseAndPrepareRevert<'a> { - params: RevertCmd, - version: &'a VersionInfo, -} - -impl<'a> ParseAndPrepareRevert<'a> { - /// Runs the command and reverts the chain. - pub fn run_with_builder( - self, - builder: F, - spec_factory: S - ) -> error::Result<()> where - S: FnOnce(&str) -> Result>, String>, - F: FnOnce(Configuration) -> Result, - B: ServiceBuilderRevert, - C: Default, - G: RuntimeGenesis, - E: ChainSpecExtension, - { - let config = create_config_with_db_path( - spec_factory, &self.params.shared_params, self.version - )?; - let blocks = self.params.num; - builder(config)?.revert_chain(blocks.into())?; - Ok(()) - } -} - -/// Create a `NodeKeyConfig` from the given `NodeKeyParams` in the context -/// of an optional network config storage directory. -fn node_key_config

(params: NodeKeyParams, net_config_dir: &Option

) - -> error::Result -where - P: AsRef -{ - match params.node_key_type { - NodeKeyType::Ed25519 => - params.node_key.as_ref().map(parse_ed25519_secret).unwrap_or_else(|| - Ok(params.node_key_file - .or_else(|| net_config_file(net_config_dir, NODE_KEY_ED25519_FILE)) - .map(network::config::Secret::File) - .unwrap_or(network::config::Secret::New))) - .map(NodeKeyConfig::Ed25519) - } -} - -fn net_config_file

(net_config_dir: &Option

, name: &str) -> Option -where - P: AsRef -{ - net_config_dir.as_ref().map(|d| d.as_ref().join(name)) -} - -/// Create an error caused by an invalid node key argument. -fn invalid_node_key(e: impl std::fmt::Display) -> error::Error { - error::Error::Input(format!("Invalid node key: {}", e)) -} - -/// Parse a Ed25519 secret key from a hex string into a `network::Secret`. -fn parse_ed25519_secret(hex: &String) -> error::Result { - H256::from_str(&hex).map_err(invalid_node_key).and_then(|bytes| - network::config::identity::ed25519::SecretKey::from_bytes(bytes) - .map(network::config::Secret::Input) - .map_err(invalid_node_key)) -} - -/// Fill the given `PoolConfiguration` by looking at the cli parameters. -fn fill_transaction_pool_configuration( - options: &mut Configuration, - 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, - is_dev: bool, -) -> error::Result<()> { - config.boot_nodes.extend(cli.bootnodes.into_iter()); - config.config_path = Some( - network_path(&base_path, chain_spec_id).to_string_lossy().into() - ); - config.net_config_path = config.config_path.clone(); - config.reserved_nodes.extend(cli.reserved_nodes.into_iter()); - - if cli.reserved_only { - config.non_reserved_mode = NonReservedPeerMode::Deny; - } - - for addr in cli.listen_addr.iter() { - let addr = addr.parse().ok().ok_or(error::Error::InvalidListenMultiaddress)?; - 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.node_key = node_key_config(cli.node_key_params, &config.net_config_path)?; - - config.in_peers = cli.in_peers; - config.out_peers = cli.out_peers; - - config.transport = TransportConfig::Normal { - enable_mdns: !is_dev && !cli.no_mdns, - wasm_external_transport: None, - }; - - Ok(()) -} - -fn input_keystore_password() -> Result { - rpassword::read_password_from_tty(Some("Keystore password: ")) - .map_err(|e| format!("{:?}", e)) -} - -/// Fill the password field of the given config instance. -fn fill_config_keystore_password( - config: &mut service::Configuration, - cli: &RunCmd, -) -> Result<(), String> { - config.keystore_password = if cli.password_interactive { - Some(input_keystore_password()?.into()) - } else if let Some(ref file) = cli.password_filename { - Some(fs::read_to_string(file).map_err(|e| format!("{}", e))?.into()) - } else if let Some(ref password) = cli.password { - Some(password.clone().into()) - } else { - None - }; - - Ok(()) -} - -fn create_run_node_config( - cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo, -) -> error::Result> -where - C: Default, - G: RuntimeGenesis, - E: ChainSpecExtension, - S: FnOnce(&str) -> Result>, String>, -{ - let spec = load_spec(&cli.shared_params, spec_factory)?; - let mut config = service::Configuration::default_with_spec(spec.clone()); - - fill_config_keystore_password(&mut config, &cli)?; - - config.impl_name = impl_name; - config.impl_commit = version.commit; - config.impl_version = version.version; - - config.name = match cli.name.or(cli.keyring.account.map(|a| a.to_string())) { - None => generate_node_name(), - Some(name) => name, - }; - match is_node_name_valid(&config.name) { - Ok(_) => (), - Err(msg) => Err( - error::Error::Input( - format!("Invalid node name '{}'. Reason: {}. If unsure, use none.", - config.name, - msg - ) - ) - )? - } - - let base_path = base_path(&cli.shared_params, version); - - config.keystore_path = cli.keystore_path.unwrap_or_else( - || keystore_path(&base_path, config.chain_spec.id()) - ); - - config.database_path = db_path(&base_path, config.chain_spec.id()); - config.database_cache_size = cli.database_cache_size; - config.state_cache_size = cli.state_cache_size; - - let is_dev = cli.shared_params.dev; - - let role = - if cli.light { - service::Roles::LIGHT - } else if cli.validator || is_dev || cli.keyring.account.is_some() { - service::Roles::AUTHORITY - } else { - service::Roles::FULL - }; - - // by default we disable pruning if the node is an authority (i.e. - // `ArchiveAll`), otherwise we keep state for the last 256 blocks. if the - // node is an authority and pruning is enabled explicitly, then we error - // unless `unsafe_pruning` is set. - config.pruning = match cli.pruning { - Some(ref s) if s == "archive" => PruningMode::ArchiveAll, - None if role == service::Roles::AUTHORITY => PruningMode::ArchiveAll, - None => PruningMode::default(), - Some(s) => { - if role == service::Roles::AUTHORITY && !cli.unsafe_pruning { - return Err(error::Error::Input( - "Validators should run with state pruning disabled (i.e. archive). \ - You can ignore this check with `--unsafe-pruning`.".to_string() - )); - } - - PruningMode::keep_blocks(s.parse() - .map_err(|_| error::Error::Input("Invalid pruning mode specified".to_string()))? - ) - }, - }; - - config.wasm_method = cli.wasm_method.into(); - - let exec = cli.execution_strategies; - let exec_all_or = |strat: params::ExecutionStrategy| exec.execution.unwrap_or(strat).into(); - config.execution_strategies = ExecutionStrategies { - syncing: exec_all_or(exec.execution_syncing), - importing: exec_all_or(exec.execution_import_block), - block_construction: exec_all_or(exec.execution_block_construction), - offchain_worker: exec_all_or(exec.execution_offchain_worker), - other: exec_all_or(exec.execution_other), - }; - - config.offchain_worker = match (cli.offchain_worker, role) { - (params::OffchainWorkerEnabled::WhenValidating, service::Roles::AUTHORITY) => true, - (params::OffchainWorkerEnabled::Always, _) => true, - (params::OffchainWorkerEnabled::Never, _) => false, - (params::OffchainWorkerEnabled::WhenValidating, _) => false, - }; - - config.roles = role; - config.disable_grandpa = cli.no_grandpa; - - let client_id = config.client_id(); - fill_network_configuration( - cli.network_config, - &base_path, - spec.id(), - &mut config.network, - client_id, - is_dev, - )?; - - fill_transaction_pool_configuration(&mut config, cli.pool_config)?; - - config.dev_key_seed = cli.keyring.account - .map(|a| format!("//{}", a)).or_else(|| { - if is_dev { - Some("//Alice".into()) - } else { - None - } - }); - - 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), cli.rpc_port)?); - config.rpc_ws = Some(parse_address(&format!("{}:{}", ws_interface, 9944), cli.ws_port)?); - - config.rpc_ws_max_connections = cli.ws_max_connections; - config.rpc_cors = cli.rpc_cors.unwrap_or_else(|| if is_dev { - log::warn!("Running in --dev mode, RPC CORS has been disabled."); - Cors::All - } else { - Cors::List(vec![ - "http://localhost:*".into(), - "http://127.0.0.1:*".into(), - "https://localhost:*".into(), - "https://127.0.0.1:*".into(), - "https://polkadot.js.org".into(), - "https://substrate-ui.parity.io".into(), - ]) - }).into(); - - // Override telemetry - if cli.no_telemetry { - config.telemetry_endpoints = None; - } else if !cli.telemetry_endpoints.is_empty() { - config.telemetry_endpoints = Some(TelemetryEndpoints::new(cli.telemetry_endpoints)); - } - - // Imply forced authoring on --dev - config.force_authoring = cli.shared_params.dev || cli.force_authoring; - - Ok(config) -} - -// -// IANA unassigned port ranges that we could use: -// 6717-6766 Unassigned -// 8504-8553 Unassigned -// 9556-9591 Unassigned -// 9803-9874 Unassigned -// 9926-9949 Unassigned - -fn with_default_boot_node( - spec: &mut ChainSpec, - cli: BuildSpecCmd, - version: &VersionInfo, -) -> error::Result<()> -where - G: RuntimeGenesis, - E: ChainSpecExtension, -{ - if spec.boot_nodes().is_empty() && !cli.disable_default_bootnode { - let base_path = base_path(&cli.shared_params, version); - let storage_path = network_path(&base_path, spec.id()); - let node_key = node_key_config(cli.node_key_params, &Some(storage_path))?; - let keys = node_key.into_keypair()?; - let peer_id = keys.public().into_peer_id(); - let addr = build_multiaddr![ - Ip4([127, 0, 0, 1]), - Tcp(30333u16), - P2p(peer_id) - ]; - spec.add_boot_node(addr) - } - Ok(()) -} - -/// Creates a configuration including the database path. -pub fn create_config_with_db_path( - spec_factory: S, cli: &SharedParams, version: &VersionInfo, -) -> error::Result> -where - C: Default, - G: RuntimeGenesis, - E: ChainSpecExtension, - S: FnOnce(&str) -> Result>, String>, -{ - let spec = load_spec(cli, spec_factory)?; - let base_path = base_path(cli, version); - - let mut config = service::Configuration::default_with_spec(spec.clone()); - config.database_path = db_path(&base_path, spec.id()); - - Ok(config) -} - -/// Internal trait used to cast to a dynamic type that implements Read and Seek. -trait ReadPlusSeek: Read + Seek {} - -impl ReadPlusSeek for T {} - -fn parse_address( - address: &str, - port: Option, -) -> Result { - let mut address: SocketAddr = address.parse().map_err( - |_| format!("Invalid address: {}", address) - )?; - if let Some(port) = port { - address.set_port(port); - } - - Ok(address) -} - -fn keystore_path(base_path: &Path, chain_id: &str) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("chains"); - path.push(chain_id); - path.push("keystore"); - path -} - -fn db_path(base_path: &Path, chain_id: &str) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("chains"); - path.push(chain_id); - path.push("db"); - path -} - -fn network_path(base_path: &Path, chain_id: &str) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("chains"); - path.push(chain_id); - path.push("network"); - path -} - -fn init_logger(pattern: &str) { - use ansi_term::Colour; - - let mut builder = env_logger::Builder::new(); - // Disable info logging by default for some modules: - builder.filter(Some("ws"), log::LevelFilter::Off); - builder.filter(Some("hyper"), log::LevelFilter::Warn); - // Enable info for others. - builder.filter(None, log::LevelFilter::Info); - - if let Ok(lvl) = std::env::var("RUST_LOG") { - builder.parse_filters(&lvl); - } - - builder.parse_filters(pattern); - let isatty = atty::is(atty::Stream::Stderr); - let enable_color = isatty; - - builder.format(move |buf, record| { - let now = time::now(); - let timestamp = - time::strftime("%Y-%m-%d %H:%M:%S", &now) - .expect("Error formatting log timestamp"); - - 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))); - 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 { - output = kill_color(output.as_ref()); - } - - if !isatty && record.level() <= log::Level::Info && atty::is(atty::Stream::Stdout) { - // duplicate INFO/WARN output to console - println!("{}", output); - } - writeln!(buf, "{}", output) - }); - - if builder.try_init().is_err() { - info!("Not registering Substrate logger, as there is already a global logger registered!"); - } -} - -fn kill_color(s: &str) -> String { - lazy_static! { - static ref RE: Regex = Regex::new("\x1b\\[[^m]+m").expect("Error initializing color regex"); - } - RE.replace_all(s, "").to_string() -} - -#[cfg(test)] -mod tests { - use super::*; - use tempdir::TempDir; - use network::config::identity::ed25519; - - #[test] - fn tests_node_name_good() { - assert!(is_node_name_valid("short name").is_ok()); - } - - #[test] - fn tests_node_name_bad() { - assert!(is_node_name_valid("long names are not very cool for the ui").is_err()); - assert!(is_node_name_valid("Dots.not.Ok").is_err()); - assert!(is_node_name_valid("http://visit.me").is_err()); - assert!(is_node_name_valid("https://visit.me").is_err()); - assert!(is_node_name_valid("www.visit.me").is_err()); - assert!(is_node_name_valid("email@domain").is_err()); - } - - #[test] - fn test_node_key_config_input() { - fn secret_input(net_config_dir: Option) -> error::Result<()> { - NodeKeyType::variants().into_iter().try_for_each(|t| { - let node_key_type = NodeKeyType::from_str(t).unwrap(); - let sk = match node_key_type { - NodeKeyType::Ed25519 => ed25519::SecretKey::generate().as_ref().to_vec() - }; - let params = NodeKeyParams { - node_key_type, - node_key: Some(format!("{:x}", H256::from_slice(sk.as_ref()))), - node_key_file: None - }; - node_key_config(params, &net_config_dir).and_then(|c| match c { - NodeKeyConfig::Ed25519(network::config::Secret::Input(ref ski)) - if node_key_type == NodeKeyType::Ed25519 && - &sk[..] == ski.as_ref() => Ok(()), - _ => Err(error::Error::Input("Unexpected node key config".into())) - }) - }) - } - - assert!(secret_input(None).is_ok()); - assert!(secret_input(Some("x".to_string())).is_ok()); - } - - #[test] - fn test_node_key_config_file() { - fn secret_file(net_config_dir: Option) -> error::Result<()> { - NodeKeyType::variants().into_iter().try_for_each(|t| { - let node_key_type = NodeKeyType::from_str(t).unwrap(); - let tmp = TempDir::new("alice")?; - let file = tmp.path().join(format!("{}_mysecret", t)).to_path_buf(); - let params = NodeKeyParams { - node_key_type, - node_key: None, - node_key_file: Some(file.clone()) - }; - node_key_config(params, &net_config_dir).and_then(|c| match c { - NodeKeyConfig::Ed25519(network::config::Secret::File(ref f)) - if node_key_type == NodeKeyType::Ed25519 && f == &file => Ok(()), - _ => Err(error::Error::Input("Unexpected node key config".into())) - }) - }) - } - - assert!(secret_file(None).is_ok()); - assert!(secret_file(Some("x".to_string())).is_ok()); - } - - #[test] - fn test_node_key_config_default() { - fn with_def_params(f: F) -> error::Result<()> - where - F: Fn(NodeKeyParams) -> error::Result<()> - { - NodeKeyType::variants().into_iter().try_for_each(|t| { - let node_key_type = NodeKeyType::from_str(t).unwrap(); - f(NodeKeyParams { - node_key_type, - node_key: None, - node_key_file: None - }) - }) - } - - fn no_config_dir() -> error::Result<()> { - with_def_params(|params| { - let typ = params.node_key_type; - node_key_config::(params, &None) - .and_then(|c| match c { - NodeKeyConfig::Ed25519(network::config::Secret::New) - if typ == NodeKeyType::Ed25519 => Ok(()), - _ => Err(error::Error::Input("Unexpected node key config".into())) - }) - }) - } - - fn some_config_dir(net_config_dir: String) -> error::Result<()> { - with_def_params(|params| { - let dir = PathBuf::from(net_config_dir.clone()); - let typ = params.node_key_type; - node_key_config(params, &Some(net_config_dir.clone())) - .and_then(move |c| match c { - NodeKeyConfig::Ed25519(network::config::Secret::File(ref f)) - if typ == NodeKeyType::Ed25519 && - f == &dir.join(NODE_KEY_ED25519_FILE) => Ok(()), - _ => Err(error::Error::Input("Unexpected node key config".into())) - }) - }) - } - - assert!(no_config_dir().is_ok()); - assert!(some_config_dir("x".to_string()).is_ok()); - } -} diff --git a/core/cli/src/params.rs b/core/cli/src/params.rs deleted file mode 100644 index 4480736066400..0000000000000 --- a/core/cli/src/params.rs +++ /dev/null @@ -1,861 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::traits::{AugmentClap, GetLogFilter}; - -use std::path::PathBuf; -use structopt::{StructOpt, clap::{arg_enum, App, AppSettings, SubCommand, Arg}}; - -pub use crate::execution_strategy::ExecutionStrategy; - -/// Auxiliary 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() - } - } - } -} - -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, - } - } -} - -arg_enum! { - /// How to execute Wasm runtime code - #[allow(missing_docs)] - #[derive(Debug, Clone)] - pub enum WasmExecutionMethod { - // Uses an interpreter. - Interpreted, - } -} - -impl Into for WasmExecutionMethod { - fn into(self) -> service::config::WasmExecutionMethod { - match self { - WasmExecutionMethod::Interpreted => service::config::WasmExecutionMethod::Interpreted, - } - } -} - -arg_enum! { - /// Whether off-chain workers are enabled. - #[allow(missing_docs)] - #[derive(Debug, Clone)] - pub enum OffchainWorkerEnabled { - Always, - Never, - WhenValidating, - } -} - -/// 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, - - /// Sets a custom logging filter. - #[structopt(short = "l", long = "log", value_name = "LOG_PATTERN")] - 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, - - /// Whether to only allow connections to/from reserved nodes. - /// - /// If you are a validator your node might still connect to other validator - /// nodes regardless of whether they are defined as reserved nodes. - #[structopt(long = "reserved-only")] - pub reserved_only: bool, - - /// Listen on this multiaddress. - #[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")] - pub listen_addr: Vec, - - /// Specify p2p protocol TCP port. - /// - /// Only used if --listen-addr is not specified. - #[structopt(long = "port", value_name = "PORT")] - pub port: 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, - - /// Disable mDNS discovery. - /// - /// By default, the network will use mDNS to discover other nodes on the - /// local network. This disables it. Automatically implied when using --dev. - #[structopt(long = "no-mdns")] - pub no_mdns: bool, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub node_key_params: NodeKeyParams -} - -arg_enum! { - #[allow(missing_docs)] - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - pub enum NodeKeyType { - Ed25519 - } -} - -/// Parameters used to create the `NodeKeyConfig`, which determines the keypair -/// used for libp2p networking. -#[derive(Debug, StructOpt, Clone)] -pub struct NodeKeyParams { - /// The secret key to use for libp2p networking. - /// - /// The value is a string that is parsed according to the choice of - /// `--node-key-type` as follows: - /// - /// `ed25519`: - /// The value is parsed as a hex-encoded Ed25519 32 bytes secret key, - /// i.e. 64 hex characters. - /// - /// The value of this option takes precedence over `--node-key-file`. - /// - /// WARNING: Secrets provided as command-line arguments are easily exposed. - /// Use of this option should be limited to development and testing. To use - /// an externally managed secret key, use `--node-key-file` instead. - #[structopt(long = "node-key", value_name = "KEY")] - pub node_key: Option, - - /// The type of secret key to use for libp2p networking. - /// - /// The secret key of the node is obtained as follows: - /// - /// * If the `--node-key` option is given, the value is parsed as a secret key - /// according to the type. See the documentation for `--node-key`. - /// - /// * If the `--node-key-file` option is given, the secret key is read from the - /// specified file. See the documentation for `--node-key-file`. - /// - /// * Otherwise, the secret key is read from a file with a predetermined, - /// type-specific name from the chain-specific network config directory - /// inside the base directory specified by `--base-dir`. If this file does - /// not exist, it is created with a newly generated secret key of the - /// chosen type. - /// - /// The node's secret key determines the corresponding public key and hence the - /// node's peer ID in the context of libp2p. - #[structopt( - long = "node-key-type", - value_name = "TYPE", - possible_values = &NodeKeyType::variants(), - case_insensitive = true, - default_value = "Ed25519" - )] - pub node_key_type: NodeKeyType, - - /// The file from which to read the node's secret key to use for libp2p networking. - /// - /// The contents of the file are parsed according to the choice of `--node-key-type` - /// as follows: - /// - /// `ed25519`: - /// The file must contain an unencoded 32 bytes Ed25519 secret key. - /// - /// If the file does not exist, it is created with a newly generated secret key of - /// the chosen type. - #[structopt(long = "node-key-file", value_name = "FILE")] - pub node_key_file: Option -} - -/// 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, -} - -/// Execution strategies parameters. -#[derive(Debug, StructOpt, Clone)] -pub struct ExecutionStrategies { - /// The means of execution used when calling into the runtime while syncing blocks. - #[structopt( - long = "execution-syncing", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - default_value = "NativeElseWasm" - )] - pub execution_syncing: ExecutionStrategy, - - /// The means of execution used when calling into the runtime while importing blocks. - #[structopt( - long = "execution-import-block", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - default_value = "NativeElseWasm" - )] - pub execution_import_block: ExecutionStrategy, - - /// The means of execution used when calling into the runtime while constructing blocks. - #[structopt( - long = "execution-block-construction", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - default_value = "Wasm" - )] - pub execution_block_construction: ExecutionStrategy, - - /// The means of execution used when calling into the runtime while using an off-chain worker. - #[structopt( - long = "execution-offchain-worker", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - default_value = "Native" - )] - pub execution_offchain_worker: ExecutionStrategy, - - /// The means of execution used when calling into the runtime while not syncing, importing or constructing blocks. - #[structopt( - long = "execution-other", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - default_value = "Native" - )] - pub execution_other: ExecutionStrategy, - - /// The execution strategy that should be used by all execution contexts. - #[structopt( - long = "execution", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - conflicts_with_all = &[ - "execution-other", - "execution-offchain-worker", - "execution-block-construction", - "execution-import-block", - "execution-syncing", - ] - )] - pub execution: Option, -} - -/// The `run` command used to run a node. -#[derive(Debug, StructOpt, Clone)] -pub struct RunCmd { - /// Enable validator mode. - #[structopt(long = "validator")] - pub validator: bool, - - /// Disable GRANDPA voter when running in validator mode, otherwise disables the GRANDPA observer. - #[structopt(long = "no-grandpa")] - pub no_grandpa: bool, - - /// Experimental: Run in light client mode. - #[structopt(long = "light")] - pub light: bool, - - /// Limit the memory the database cache can use. - #[structopt(long = "db-cache", value_name = "MiB")] - pub database_cache_size: Option, - - /// Specify the state cache size. - #[structopt(long = "state-cache-size", value_name = "Bytes", default_value = "67108864")] - pub state_cache_size: usize, - - /// Listen to all RPC interfaces. - /// - /// Default is local. - #[structopt(long = "rpc-external")] - pub rpc_external: bool, - - /// Listen to all Websocket interfaces. - /// - /// Default is local. - #[structopt(long = "ws-external")] - pub ws_external: bool, - - /// Specify HTTP RPC server TCP port. - #[structopt(long = "rpc-port", value_name = "PORT")] - pub rpc_port: Option, - - /// Specify WebSockets RPC server TCP port. - #[structopt(long = "ws-port", value_name = "PORT")] - pub ws_port: Option, - - /// Maximum number of WS RPC server connections. - #[structopt(long = "ws-max-connections", value_name = "COUNT")] - pub ws_max_connections: Option, - - /// Specify browser Origins allowed to access the HTTP & WS RPC servers. - /// - /// A comma-separated list of origins (protocol://domain or special `null` - /// value). Value of `all` will disable origin validation. Default is to - /// allow localhost, https://polkadot.js.org and - /// https://substrate-ui.parity.io origins. When running in --dev mode the - /// default is to allow all origins. - #[structopt(long = "rpc-cors", value_name = "ORIGINS", parse(try_from_str = parse_cors))] - pub rpc_cors: Option, - - /// Specify the state pruning mode, a number of blocks to keep or 'archive'. - /// - /// Default is to keep all block states if the node is running as a - /// validator (i.e. 'archive'), otherwise state is only kept for the last - /// 256 blocks. - #[structopt(long = "pruning", value_name = "PRUNING_MODE")] - pub pruning: Option, - - /// Force start with unsafe pruning settings. - /// - /// When running as a validator it is highly recommended to disable state - /// pruning (i.e. 'archive') which is the default. The node will refuse to - /// start as a validator if pruning is enabled unless this option is set. - #[structopt(long = "unsafe-pruning")] - pub unsafe_pruning: bool, - - /// The human-readable name for this node. - /// - /// The node name will be reported to the telemetry server, if enabled. - #[structopt(long = "name", value_name = "NAME")] - pub name: Option, - - /// Disable connecting to the Substrate telemetry server. - /// - /// Telemetry is on by default on global chains. - #[structopt(long = "no-telemetry")] - pub no_telemetry: bool, - - /// The URL of the telemetry server to connect to. - /// - /// This flag can be passed multiple times as a mean to specify multiple - /// telemetry endpoints. Verbosity levels range from 0-9, with 0 denoting - /// the least verbosity. If no verbosity level is specified the default is - /// 0. - #[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = parse_telemetry_endpoints))] - pub telemetry_endpoints: Vec<(String, u8)>, - - /// Should execute offchain workers on every block. - /// - /// By default it's only enabled for nodes that are authoring new blocks. - #[structopt( - long = "offchain-worker", - value_name = "ENABLED", - possible_values = &OffchainWorkerEnabled::variants(), - case_insensitive = true, - default_value = "WhenValidating" - )] - pub offchain_worker: OffchainWorkerEnabled, - - /// Method for executing Wasm runtime code. - #[structopt( - long = "wasm-execution", - value_name = "METHOD", - possible_values = &WasmExecutionMethod::variants(), - case_insensitive = true, - default_value = "Interpreted" - )] - pub wasm_method: WasmExecutionMethod, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub execution_strategies: ExecutionStrategies, - - #[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, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub keyring: Keyring, - - /// Enable authoring even when offline. - #[structopt(long = "force-authoring")] - pub force_authoring: bool, - - /// Specify custom keystore path. - #[structopt(long = "keystore-path", value_name = "PATH", parse(from_os_str))] - pub keystore_path: Option, - - /// Use interactive shell for entering the password used by the keystore. - #[structopt( - long = "password-interactive", - conflicts_with_all = &[ "password", "password-filename" ] - )] - pub password_interactive: bool, - - /// Password used by the keystore. - #[structopt( - long = "password", - conflicts_with_all = &[ "password-interactive", "password-filename" ] - )] - pub password: Option, - - /// File that contains the password used by the keystore. - #[structopt( - long = "password-filename", - value_name = "PATH", - parse(from_os_str), - conflicts_with_all = &[ "password-interactive", "password" ] - )] - pub password_filename: Option -} - -/// Stores all required Cli values for a keyring test account. -struct KeyringTestAccountCliValues { - help: String, - conflicts_with: Vec, - name: String, - variant: keyring::Sr25519Keyring, -} - -lazy_static::lazy_static! { - /// The Cli values for all test accounts. - static ref TEST_ACCOUNTS_CLI_VALUES: Vec = { - keyring::Sr25519Keyring::iter().map(|a| { - let help = format!( - "Shortcut for `--name {} --validator` with session keys for `{}` added to keystore.", - a, - a, - ); - let conflicts_with = keyring::Sr25519Keyring::iter() - .filter(|b| a != *b) - .map(|b| b.to_string().to_lowercase()) - .chain(std::iter::once("name".to_string())) - .collect::>(); - let name = a.to_string().to_lowercase(); - - KeyringTestAccountCliValues { - help, - conflicts_with, - name, - variant: a, - } - }).collect() - }; -} - -/// Wrapper for exposing the keyring test accounts into the Cli. -#[derive(Debug, Clone)] -pub struct Keyring { - pub account: Option, -} - -impl StructOpt for Keyring { - fn clap<'a, 'b>() -> App<'a, 'b> { - unimplemented!("Should not be called for `TestAccounts`.") - } - - fn from_clap(m: &::structopt::clap::ArgMatches) -> Self { - Keyring { - account: TEST_ACCOUNTS_CLI_VALUES.iter().find(|a| m.is_present(&a.name)).map(|a| a.variant), - } - } -} - -impl AugmentClap for Keyring { - fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { - TEST_ACCOUNTS_CLI_VALUES.iter().fold(app, |app, a| { - let conflicts_with_strs = a.conflicts_with.iter().map(|s| s.as_str()).collect::>(); - - app.arg( - Arg::with_name(&a.name) - .long(&a.name) - .help(&a.help) - .conflicts_with_all(&conflicts_with_strs) - .takes_value(false) - ) - }) - } -} - -impl Keyring { - fn is_subcommand() -> bool { - false - } -} - -/// Default to verbosity level 0, if none is provided. -fn parse_telemetry_endpoints(s: &str) -> Result<(String, u8), Box> { - let pos = s.find(' '); - match pos { - None => { - Ok((s.to_owned(), 0)) - }, - Some(pos_) => { - let verbosity = s[pos_ + 1..].parse()?; - let url = s[..pos_].parse()?; - Ok((url, verbosity)) - } - } -} - -/// CORS setting -/// -/// The type is introduced to overcome `Option>` -/// handling of `structopt`. -#[derive(Clone, Debug)] -pub enum Cors { - /// All hosts allowed - All, - /// Only hosts on the list are allowed. - List(Vec), -} - -impl From for Option> { - fn from(cors: Cors) -> Self { - match cors { - Cors::All => None, - Cors::List(list) => Some(list), - } - } -} - -/// Parse cors origins -fn parse_cors(s: &str) -> Result> { - let mut is_all = false; - let mut origins = Vec::new(); - for part in s.split(',') { - match part { - "all" | "*" => { - is_all = true; - break; - }, - other => origins.push(other.to_owned()), - } - } - - Ok(if is_all { Cors::All } else { Cors::List(origins) }) -} - -impl_augment_clap!(RunCmd); -impl_get_log_filter!(RunCmd); - -/// 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, - - /// Disable adding the default bootnode to the specification. - /// - /// By default the `/ip4/127.0.0.1/tcp/30333/p2p/NODE_PEER_ID` bootnode is added to the - /// specification when no bootnode exists. - #[structopt(long = "disable-default-bootnode")] - pub disable_default_bootnode: bool, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub shared_params: SharedParams, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub node_key_params: NodeKeyParams, -} - -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. - /// - /// Default is 1. - #[structopt(long = "from", value_name = "BLOCK")] - pub from: Option, - - /// Specify last block number. - /// - /// Default is best block. - #[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_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, - - /// Method for executing Wasm runtime code. - #[structopt( - long = "wasm-execution", - value_name = "METHOD", - possible_values = &WasmExecutionMethod::variants(), - case_insensitive = true, - default_value = "Interpreted" - )] - pub wasm_method: WasmExecutionMethod, - - /// The means of execution used when calling into the runtime while importing blocks. - #[structopt( - long = "execution", - value_name = "STRATEGY", - possible_values = &ExecutionStrategy::variants(), - case_insensitive = true, - default_value = "NativeElseWasm" - )] - pub execution: ExecutionStrategy, -} - -impl_get_log_filter!(ImportBlocksCmd); - -/// The `revert` command used revert the chain to a previous state. -#[derive(Debug, StructOpt, Clone)] -pub struct RevertCmd { - /// Number of blocks to revert. - #[structopt(default_value = "256")] - pub num: u32, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub shared_params: SharedParams, -} - -impl_get_log_filter!(RevertCmd); - -/// 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, - - #[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. - ImportBlocks(ImportBlocksCmd), - - /// Revert chain to the previous state. - Revert(RevertCmd), - - /// Remove the whole chain data. - 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, outputting to stdout.") - ) - .subcommand( - ExportBlocksCmd::augment_clap(SubCommand::with_name("export-blocks")) - .about("Export blocks to a file. This file can only be re-imported \ - if it is in binary format (not JSON!)." - ) - ) - .subcommand( - ImportBlocksCmd::augment_clap(SubCommand::with_name("import-blocks")) - .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 deleted file mode 100644 index 0f8d247e49ab1..0000000000000 --- a/core/cli/src/traits.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use structopt::{StructOpt, clap::App}; - -/// Something that can augment a clap 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 deleted file mode 100644 index 5a0afd2d6f72a..0000000000000 --- a/core/client/Cargo.toml +++ /dev/null @@ -1,64 +0,0 @@ -[package] -name = "substrate-client" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -derive_more = { version = "0.15.0", optional = true } -fnv = { version = "1.0.6", optional = true } -log = { version = "0.4.8", optional = true } -parking_lot = { version = "0.9.0", optional = true } -hex-literal = { version = "0.2.1", optional = true } -futures = { version = "0.1.29", optional = true } -futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"], optional = true } -consensus = { package = "substrate-consensus-common", path = "../consensus/common", optional = true } -executor = { package = "substrate-executor", path = "../executor", optional = true } -state-machine = { package = "substrate-state-machine", path = "../state-machine", optional = true } -keyring = { package = "substrate-keyring", path = "../keyring", optional = true } -trie = { package = "substrate-trie", path = "../trie", optional = true } -substrate-telemetry = { path = "../telemetry", optional = true } -hash-db = { version = "0.15.2", default-features = false } -kvdb = { git = "https://github.com/paritytech/parity-common", optional = true, rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } -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" } -header-metadata = { package = "substrate-header-metadata", path = "header-metadata", optional = true } - -[dev-dependencies] -env_logger = "0.7.0" -tempfile = "3.1.0" -test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client" } -kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } -panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } - -[features] -default = ["std"] -std = [ - "rstd/std", - "codec/std", - "primitives/std", - "inherents/std", - "sr-primitives/std", - "runtime-version/std", - "hash-db/std", - "header-metadata", - "consensus", - "parking_lot", - "derive_more", - "fnv", - "log", - "hex-literal", - "futures", - "futures03", - "executor", - "state-machine", - "keyring", - "trie", - "substrate-telemetry", - "kvdb" -] diff --git a/core/client/db/Cargo.toml b/core/client/db/Cargo.toml deleted file mode 100644 index 7d88c39d7fd7e..0000000000000 --- a/core/client/db/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "substrate-client-db" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -parking_lot = "0.9.0" -log = "0.4.8" -kvdb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } -# FIXME replace with release as soon as our rocksdb changes are released upstream https://github.com/paritytech/parity-common/issues/88 -kvdb-rocksdb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d", optional = true } -kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } -linked-hash-map = "0.5.2" -hash-db = "0.15.2" -primitives = { package = "substrate-primitives", path = "../../primitives" } -sr-primitives = { path = "../../sr-primitives" } -client = { package = "substrate-client", path = "../../client" } -state-machine = { package = "substrate-state-machine", path = "../../state-machine" } -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } -executor = { package = "substrate-executor", path = "../../executor" } -state_db = { package = "substrate-state-db", path = "../../state-db" } -trie = { package = "substrate-trie", path = "../../trie" } -consensus_common = { package = "substrate-consensus-common", path = "../../consensus/common" } -header_metadata = { package = "substrate-header-metadata", path = "../header-metadata" } - -[dev-dependencies] -substrate-keyring = { path = "../../keyring" } -test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } -env_logger = "0.7.0" - -[features] -default = [] -test-helpers = [] diff --git a/core/client/db/src/cache/mod.rs b/core/client/db/src/cache/mod.rs deleted file mode 100644 index 9aaea57b0cdb2..0000000000000 --- a/core/client/db/src/cache/mod.rs +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! DB-backed cache of blockchain data. - -use std::{sync::Arc, collections::HashMap}; -use parking_lot::RwLock; - -use kvdb::{KeyValueDB, DBTransaction}; - -use client::blockchain::{well_known_cache_keys::{self, Id as CacheKeyId}, Cache as BlockchainCache}; -use client::error::Result as ClientResult; -use codec::{Encode, Decode}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; -use crate::utils::{self, COLUMN_META, db_err}; - -use self::list_cache::{ListCache, PruningStrategy}; - -mod list_cache; -mod list_entry; -mod list_storage; - -/// Minimal post-finalization age of finalized blocks before they'll pruned. -const PRUNE_DEPTH: u32 = 1024; - -/// The type of entry that is inserted to the cache. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum EntryType { - /// Non-final entry. - NonFinal, - /// Final entry. - Final, - /// Genesis entry (inserted during cache initialization). - Genesis, -} - -/// Block identifier that holds both hash and number. -#[derive(Clone, Debug, Encode, Decode, PartialEq)] -pub struct ComplexBlockId { - hash: Block::Hash, - number: NumberFor, -} - -impl ComplexBlockId { - /// Create new complex block id. - pub fn new(hash: Block::Hash, number: NumberFor) -> Self { - ComplexBlockId { hash, number } - } -} - -impl ::std::cmp::PartialOrd for ComplexBlockId { - fn partial_cmp(&self, other: &ComplexBlockId) -> Option<::std::cmp::Ordering> { - self.number.partial_cmp(&other.number) - } -} - -/// All cache items must implement this trait. -pub trait CacheItemT: Clone + Decode + Encode + PartialEq {} - -impl CacheItemT for T where T: Clone + Decode + Encode + PartialEq {} - -/// Database-backed blockchain data cache. -pub struct DbCache { - cache_at: HashMap, self::list_storage::DbStorage>>, - db: Arc, - key_lookup_column: Option, - header_column: Option, - authorities_column: Option, - genesis_hash: Block::Hash, - best_finalized_block: ComplexBlockId, -} - -impl DbCache { - /// Create new cache. - pub fn new( - db: Arc, - key_lookup_column: Option, - header_column: Option, - authorities_column: Option, - genesis_hash: Block::Hash, - best_finalized_block: ComplexBlockId, - ) -> Self { - Self { - cache_at: HashMap::new(), - db, - key_lookup_column, - header_column, - authorities_column, - genesis_hash, - best_finalized_block, - } - } - - /// Set genesis block hash. - pub fn set_genesis_hash(&mut self, genesis_hash: Block::Hash) { - self.genesis_hash = genesis_hash; - } - - /// Begin cache transaction. - pub fn transaction<'a>(&'a mut self, tx: &'a mut DBTransaction) -> DbCacheTransaction<'a, Block> { - DbCacheTransaction { - cache: self, - tx, - cache_at_op: HashMap::new(), - best_finalized_block: None, - } - } - - /// Run post-commit cache operations. - pub fn commit(&mut self, ops: DbCacheTransactionOps) { - for (name, op) in ops.cache_at_op.into_iter() { - self.get_cache(name).on_transaction_commit(op); - } - if let Some(best_finalized_block) = ops.best_finalized_block { - self.best_finalized_block = best_finalized_block; - } - } - - /// Creates `ListCache` with the given name or returns a reference to the existing. - fn get_cache(&mut self, name: CacheKeyId) -> &mut ListCache, self::list_storage::DbStorage> { - get_cache_helper( - &mut self.cache_at, - name, - &self.db, - self.key_lookup_column, - self.header_column, - self.authorities_column, - &self.best_finalized_block - ) - } -} - -// This helper is needed because otherwise the borrow checker will require to -// clone all parameters outside of the closure. -fn get_cache_helper<'a, Block: BlockT>( - cache_at: &'a mut HashMap, self::list_storage::DbStorage>>, - name: CacheKeyId, - db: &Arc, - key_lookup: Option, - header: Option, - cache: Option, - best_finalized_block: &ComplexBlockId, -) -> &'a mut ListCache, self::list_storage::DbStorage> { - cache_at.entry(name).or_insert_with(|| { - ListCache::new( - self::list_storage::DbStorage::new(name.to_vec(), db.clone(), - self::list_storage::DbColumns { - meta: COLUMN_META, - key_lookup, - header, - cache, - }, - ), - cache_pruning_strategy(name), - best_finalized_block.clone(), - ) - }) -} - -/// Cache operations that are to be committed after database transaction is committed. -pub struct DbCacheTransactionOps { - cache_at_op: HashMap>>, - best_finalized_block: 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, - cache_at_op: HashMap>>, - best_finalized_block: Option>, -} - -impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { - /// Convert transaction into post-commit operations set. - pub fn into_ops(self) -> DbCacheTransactionOps { - DbCacheTransactionOps { - cache_at_op: self.cache_at_op, - best_finalized_block: self.best_finalized_block, - } - } - - /// When new block is inserted into database. - pub fn on_block_insert( - mut self, - parent: ComplexBlockId, - block: ComplexBlockId, - data_at: HashMap>, - entry_type: EntryType, - ) -> ClientResult { - assert!(self.cache_at_op.is_empty()); - - // prepare list of caches that are not update - // (we might still need to do some cache maintenance in this case) - let missed_caches = self.cache.cache_at.keys() - .filter(|cache| !data_at.contains_key(*cache)) - .cloned() - .collect::>(); - - let mut insert_op = |name: CacheKeyId, value: Option>| -> Result<(), client::error::Error> { - let cache = self.cache.get_cache(name); - let op = cache.on_block_insert( - &mut self::list_storage::DbStorageTransaction::new( - cache.storage(), - &mut self.tx, - ), - parent.clone(), - block.clone(), - value, - entry_type, - )?; - if let Some(op) = op { - self.cache_at_op.insert(name, op); - } - Ok(()) - }; - - data_at.into_iter().try_for_each(|(name, data)| insert_op(name, Some(data)))?; - missed_caches.into_iter().try_for_each(|name| insert_op(name, None))?; - - match entry_type { - EntryType::Final | EntryType::Genesis => - self.best_finalized_block = Some(block), - EntryType::NonFinal => (), - } - - Ok(self) - } - - /// When previously inserted block is finalized. - pub fn on_block_finalize( - mut self, - parent: ComplexBlockId, - block: ComplexBlockId - ) -> ClientResult { - assert!(self.cache_at_op.is_empty()); - - for (name, cache_at) in self.cache.cache_at.iter() { - let op = cache_at.on_block_finalize( - &mut self::list_storage::DbStorageTransaction::new( - cache_at.storage(), - &mut self.tx - ), - parent.clone(), - block.clone(), - )?; - - if let Some(op) = op { - self.cache_at_op.insert(name.to_owned(), op); - } - } - - self.best_finalized_block = Some(block); - - Ok(self) - } - - /// When block is reverted. - pub fn on_block_revert( - mut self, - reverted_block: &ComplexBlockId, - ) -> ClientResult { - for (name, cache) in self.cache.cache_at.iter() { - let op = cache.on_block_revert( - &mut self::list_storage::DbStorageTransaction::new( - cache.storage(), - &mut self.tx - ), - reverted_block, - )?; - - assert!(!self.cache_at_op.contains_key(name)); - self.cache_at_op.insert(name.to_owned(), op); - } - - Ok(self) - } -} - -/// Synchronous implementation of database-backed blockchain data cache. -pub struct DbCacheSync(pub RwLock>); - -impl BlockchainCache for DbCacheSync { - fn initialize(&self, key: &CacheKeyId, data: Vec) -> ClientResult<()> { - let mut cache = self.0.write(); - let genesis_hash = cache.genesis_hash; - let cache_contents = vec![(*key, data)].into_iter().collect(); - let db = cache.db.clone(); - let mut dbtx = DBTransaction::new(); - let tx = cache.transaction(&mut dbtx); - let tx = tx.on_block_insert( - ComplexBlockId::new(Default::default(), Zero::zero()), - ComplexBlockId::new(genesis_hash, Zero::zero()), - cache_contents, - EntryType::Genesis, - )?; - let tx_ops = tx.into_ops(); - db.write(dbtx).map_err(db_err)?; - cache.commit(tx_ops); - Ok(()) - } - - fn get_at( - &self, - key: &CacheKeyId, - at: &BlockId, - ) -> Option<((NumberFor, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)> { - let mut cache = self.0.write(); - let storage = cache.get_cache(*key).storage(); - let db = storage.db(); - let columns = storage.columns(); - let at = match *at { - BlockId::Hash(hash) => { - let header = utils::read_header::( - &**db, - columns.key_lookup, - columns.header, - BlockId::Hash(hash.clone())).ok()??; - ComplexBlockId::new(hash, *header.number()) - }, - BlockId::Number(number) => { - let hash = utils::read_header::( - &**db, - columns.key_lookup, - columns.header, - BlockId::Number(number.clone())).ok()??.hash(); - ComplexBlockId::new(hash, number) - }, - }; - - cache.cache_at - .get(key)? - .value_at_block(&at) - .map(|block_and_value| block_and_value.map(|(begin_block, end_block, value)| - ( - (begin_block.number, begin_block.hash), - end_block.map(|end_block| (end_block.number, end_block.hash)), - value, - ))) - .ok()? - } -} - -/// Get pruning strategy for given cache. -fn cache_pruning_strategy>(cache: CacheKeyId) -> PruningStrategy { - // the cache is mostly used to store data from consensus engines - // this kind of data is only required for non-finalized blocks - // => by default we prune finalized cached entries - - match cache { - // we need to keep changes tries configurations forever (or at least until changes tries, - // that were built using this configuration, are pruned) to make it possible to refer - // to old changes tries - well_known_cache_keys::CHANGES_TRIE_CONFIG => PruningStrategy::NeverPrune, - _ => PruningStrategy::ByDepth(PRUNE_DEPTH.into()), - } -} diff --git a/core/client/db/src/lib.rs b/core/client/db/src/lib.rs deleted file mode 100644 index 0f765506a31ef..0000000000000 --- a/core/client/db/src/lib.rs +++ /dev/null @@ -1,2364 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Client backend that uses RocksDB database as storage. -//! -//! # Canonicality vs. Finality -//! -//! Finality indicates that a block will not be reverted, according to the consensus algorithm, -//! while canonicality indicates that the block may be reverted, but we will be unable to do so, -//! having discarded heavy state that will allow a chain reorganization. -//! -//! Finality implies canonicality but not vice-versa. - -#![warn(missing_docs)] - -pub mod light; -pub mod offchain; - -mod cache; -mod storage_cache; -mod utils; - -use std::sync::Arc; -use std::path::PathBuf; -use std::io; -use std::collections::{HashMap, HashSet}; - -use client::backend::NewBlockState; -use client::blockchain::{well_known_cache_keys, HeaderBackend}; -use client::{ForkBlocks, ExecutionStrategies}; -use client::backend::{StorageCollection, ChildStorageCollection}; -use client::error::{Result as ClientResult, Error as ClientError}; -use codec::{Decode, Encode}; -use hash_db::{Hasher, Prefix}; -use kvdb::{KeyValueDB, DBTransaction}; -use trie::{MemoryDB, PrefixedMemoryDB, prefixed_key}; -use parking_lot::{Mutex, RwLock}; -use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash, traits::CodeExecutor}; -use primitives::storage::well_known_keys; -use sr_primitives::{ - generic::{BlockId, DigestItem}, Justification, StorageOverlay, ChildrenStorageOverlay, - BuildStorage, -}; -use sr_primitives::traits::{ - Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion -}; -use executor::RuntimeInfo; -use state_machine::{ - DBValue, ChangesTrieTransaction, ChangesTrieCacheAction, ChangesTrieBuildCache, - backend::Backend as StateBackend, -}; -use crate::utils::{Meta, db_err, meta_keys, read_db, read_meta}; -use client::leaves::{LeafSet, FinalizationDisplaced}; -use client::children; -use state_db::StateDb; -use header_metadata::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache}; -use crate::storage_cache::{CachingState, SharedCache, new_shared_cache}; -use log::{trace, debug, warn}; -pub use state_db::PruningMode; - -#[cfg(feature = "test-helpers")] -use client::in_mem::Backend as InMemoryBackend; - -const CANONICALIZATION_DELAY: u64 = 4096; -const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR: u32 = 32768; - -/// Default value for storage cache child ratio. -const DEFAULT_CHILD_RATIO: (usize, usize) = (1, 10); - -/// DB-backed patricia trie state, transaction type is an overlay of changes to commit. -pub type DbState = state_machine::TrieBackend>, Blake2Hasher>; - -/// A reference tracking state. -/// -/// It makes sure that the hash we are using stays pinned in storage -/// until this structure is dropped. -pub struct RefTrackingState { - state: DbState, - storage: Arc>, - parent_hash: Option, -} - -impl RefTrackingState { - fn new(state: DbState, storage: Arc>, parent_hash: Option) -> RefTrackingState { - RefTrackingState { - state, - parent_hash, - storage, - } - } -} - -impl Drop for RefTrackingState { - fn drop(&mut self) { - if let Some(hash) = &self.parent_hash { - self.storage.state_db.unpin(hash); - } - } -} - -impl std::fmt::Debug for RefTrackingState { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Block {:?}", self.parent_hash) - } -} - -impl StateBackend for RefTrackingState { - type Error = >::Error; - type Transaction = >::Transaction; - type TrieBackendStorage = >::TrieBackendStorage; - - fn storage(&self, key: &[u8]) -> Result>, Self::Error> { - self.state.storage(key) - } - - fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { - self.state.storage_hash(key) - } - - 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 { - self.state.exists_storage(key) - } - - 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_key_values_with_prefix(&self, prefix: &[u8], f: F) { - self.state.for_key_values_with_prefix(prefix, f) - } - - fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { - self.state.for_keys_in_child_storage(storage_key, f) - } - - fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { - self.state.for_child_keys_with_prefix(storage_key, prefix, f) - } - - fn storage_root(&self, delta: I) -> (H256, Self::Transaction) - where - I: IntoIterator, Option>)> - { - self.state.storage_root(delta) - } - - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - { - self.state.child_storage_root(storage_key, delta) - } - - fn pairs(&self) -> Vec<(Vec, Vec)> { - self.state.pairs() - } - - fn keys(&self, prefix: &[u8]) -> Vec> { - self.state.keys(prefix) - } - - fn child_keys(&self, child_key: &[u8], prefix: &[u8]) -> Vec> { - self.state.child_keys(child_key, prefix) - } - - fn as_trie_backend(&mut self) -> Option<&state_machine::TrieBackend> { - self.state.as_trie_backend() - } -} - -/// Database settings. -pub struct DatabaseSettings { - /// Cache size in bytes. If `None` default is used. - pub cache_size: Option, - /// State cache size. - pub state_cache_size: usize, - /// Ratio of cache size dedicated to child tries. - pub state_cache_child_ratio: Option<(usize, usize)>, - /// Path to the database. - pub path: PathBuf, - /// Pruning mode. - pub pruning: PruningMode, -} - -/// Create an instance of db-backed client. -pub fn new_client( - settings: DatabaseSettings, - executor: E, - genesis_storage: S, - fork_blocks: ForkBlocks, - execution_strategies: ExecutionStrategies, - keystore: Option, -) -> Result<( - client::Client< - Backend, - client::LocalCallExecutor, E>, - Block, - RA, - >, - Arc>, - ), - client::error::Error, -> - where - Block: BlockT, - E: CodeExecutor + RuntimeInfo, - S: BuildStorage, -{ - let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); - let executor = client::LocalCallExecutor::new(backend.clone(), executor, keystore); - Ok(( - client::Client::new(backend.clone(), executor, genesis_storage, fork_blocks, execution_strategies)?, - backend, - )) -} - -pub(crate) mod columns { - 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. - pub const KEY_LOOKUP: Option = Some(3); - pub const HEADER: Option = Some(4); - pub const BODY: Option = Some(5); - pub const JUSTIFICATION: Option = Some(6); - pub const CHANGES_TRIE: Option = Some(7); - pub const AUX: Option = Some(8); - /// Offchain workers local storage - pub const OFFCHAIN: Option = Some(9); -} - -struct PendingBlock { - header: Block::Header, - justification: Option, - body: Option>, - leaf_state: NewBlockState, -} - -// wrapper that implements trait required for state_db -struct StateMetaDb<'a>(&'a dyn KeyValueDB); - -impl<'a> state_db::MetaDb for StateMetaDb<'a> { - type Error = io::Error; - - fn get_meta(&self, key: &[u8]) -> Result>, Self::Error> { - self.0.get(columns::STATE_META, key).map(|r| r.map(|v| v.to_vec())) - } -} - -/// Block database -pub struct BlockchainDb { - db: Arc, - meta: Arc, Block::Hash>>>, - leaves: RwLock>>, - header_metadata_cache: HeaderMetadataCache, -} - -impl BlockchainDb { - fn new(db: Arc) -> ClientResult { - let meta = read_meta::(&*db, columns::META, columns::HEADER)?; - let leaves = LeafSet::read_from_db(&*db, columns::META, meta_keys::LEAF_PREFIX)?; - Ok(BlockchainDb { - db, - leaves: RwLock::new(leaves), - meta: Arc::new(RwLock::new(meta)), - header_metadata_cache: HeaderMetadataCache::default(), - }) - } - - fn update_meta( - &self, - hash: Block::Hash, - number: ::Number, - is_best: bool, - is_finalized: bool - ) { - let mut meta = self.meta.write(); - if number.is_zero() { - meta.genesis_hash = hash; - meta.finalized_hash = hash; - } - - if is_best { - meta.best_number = number; - meta.best_hash = hash; - } - - if is_finalized { - meta.finalized_number = number; - meta.finalized_hash = hash; - } - } -} - -impl client::blockchain::HeaderBackend for BlockchainDb { - fn header(&self, id: BlockId) -> ClientResult> { - utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) - } - - fn info(&self) -> client::blockchain::Info { - let meta = self.meta.read(); - client::blockchain::Info { - best_hash: meta.best_hash, - best_number: meta.best_number, - genesis_hash: meta.genesis_hash, - finalized_hash: meta.finalized_hash, - finalized_number: meta.finalized_number, - } - } - - fn status(&self, id: BlockId) -> ClientResult { - let exists = match id { - BlockId::Hash(_) => read_db( - &*self.db, - columns::KEY_LOOKUP, - columns::HEADER, - id - )?.is_some(), - BlockId::Number(n) => n <= self.meta.read().best_number, - }; - match exists { - true => Ok(client::blockchain::BlockStatus::InChain), - false => Ok(client::blockchain::BlockStatus::Unknown), - } - } - - fn number(&self, hash: Block::Hash) -> ClientResult>> { - Ok(self.header_metadata(hash).ok().map(|header_metadata| header_metadata.number)) - } - - fn hash(&self, number: NumberFor) -> ClientResult> { - self.header(BlockId::Number(number)).and_then(|maybe_header| match maybe_header { - Some(header) => Ok(Some(header.hash().clone())), - None => Ok(None), - }) - } -} - -impl client::blockchain::Backend for BlockchainDb { - fn body(&self, id: BlockId) -> ClientResult>> { - match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? { - Some(body) => match Decode::decode(&mut &body[..]) { - Ok(body) => Ok(Some(body)), - Err(err) => return Err(client::error::Error::Backend( - format!("Error decoding body: {}", err) - )), - } - None => Ok(None), - } - } - - fn justification(&self, id: BlockId) -> ClientResult> { - match read_db(&*self.db, columns::KEY_LOOKUP, columns::JUSTIFICATION, id)? { - Some(justification) => match Decode::decode(&mut &justification[..]) { - Ok(justification) => Ok(Some(justification)), - Err(err) => return Err(client::error::Error::Backend( - format!("Error decoding justification: {}", err) - )), - } - None => Ok(None), - } - } - - fn last_finalized(&self) -> ClientResult { - Ok(self.meta.read().finalized_hash.clone()) - } - - fn cache(&self) -> Option>> { - None - } - - fn leaves(&self) -> ClientResult> { - Ok(self.leaves.read().hashes()) - } - - fn children(&self, parent_hash: Block::Hash) -> ClientResult> { - children::read_children(&*self.db, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash) - } -} - -impl client::blockchain::ProvideCache for BlockchainDb { - fn cache(&self) -> Option>> { - None - } -} - -impl HeaderMetadata for BlockchainDb { - type Error = client::error::Error; - - fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { - self.header_metadata_cache.header_metadata(hash).or_else(|_| { - self.header(BlockId::hash(hash))?.map(|header| { - let header_metadata = CachedHeaderMetadata::from(&header); - self.header_metadata_cache.insert_header_metadata( - header_metadata.hash, - header_metadata.clone(), - ); - header_metadata - }).ok_or(ClientError::UnknownBlock(format!("header not found in db: {}", hash))) - }) - } - - fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { - self.header_metadata_cache.insert_header_metadata(hash, metadata) - } - - fn remove_header_metadata(&self, hash: Block::Hash) { - self.header_metadata_cache.remove_header_metadata(hash); - } -} - -/// Database transaction -pub struct BlockImportOperation { - old_state: CachingState, Block>, - db_updates: PrefixedMemoryDB, - storage_updates: StorageCollection, - child_storage_updates: ChildStorageCollection, - changes_trie_updates: MemoryDB, - changes_trie_cache_update: Option>>, - pending_block: Option>, - aux_ops: Vec<(Vec, Option>)>, - finalized_blocks: Vec<(BlockId, Option)>, - set_head: Option>, -} - -impl BlockImportOperation { - fn apply_aux(&mut self, transaction: &mut DBTransaction) { - for (key, maybe_val) in self.aux_ops.drain(..) { - match maybe_val { - Some(val) => transaction.put_vec(columns::AUX, &key, val), - None => transaction.delete(columns::AUX, &key), - } - } - } -} - -impl client::backend::BlockImportOperation - for BlockImportOperation where Block: BlockT, -{ - type State = CachingState, Block>; - - fn state(&self) -> ClientResult> { - Ok(Some(&self.old_state)) - } - - fn set_block_data( - &mut self, - header: Block::Header, - body: Option>, - justification: Option, - leaf_state: NewBlockState, - ) -> ClientResult<()> { - assert!(self.pending_block.is_none(), "Only one block per operation is allowed"); - self.pending_block = Some(PendingBlock { - header, - body, - justification, - leaf_state, - }); - Ok(()) - } - - fn update_cache(&mut self, _cache: HashMap>) { - // Currently cache isn't implemented on full nodes. - } - - fn update_db_storage(&mut self, update: PrefixedMemoryDB) -> ClientResult<()> { - self.db_updates = update; - Ok(()) - } - - fn reset_storage( - &mut self, - top: StorageOverlay, - children: ChildrenStorageOverlay - ) -> ClientResult { - - if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { - return Err(client::error::Error::GenesisInvalid.into()); - } - - for child_key in children.keys() { - if !well_known_keys::is_child_storage_key(&child_key) { - return Err(client::error::Error::GenesisInvalid.into()); - } - } - - let child_delta = children.into_iter() - .map(|(storage_key, child_overlay)| - (storage_key, child_overlay.into_iter().map(|(k, v)| (k, Some(v))))); - - let (root, transaction) = self.old_state.full_storage_root( - top.into_iter().map(|(k, v)| (k, Some(v))), - child_delta - ); - - self.db_updates = transaction; - Ok(root) - } - - fn update_changes_trie( - &mut self, - update: ChangesTrieTransaction>, - ) -> ClientResult<()> { - self.changes_trie_updates = update.0; - self.changes_trie_cache_update = Some(update.1); - Ok(()) - } - - fn insert_aux(&mut self, ops: I) -> ClientResult<()> - where I: IntoIterator, Option>)> - { - self.aux_ops.append(&mut ops.into_iter().collect()); - Ok(()) - } - - fn update_storage( - &mut self, - update: StorageCollection, - child_update: ChildStorageCollection, - ) -> ClientResult<()> { - self.storage_updates = update; - self.child_storage_updates = child_update; - Ok(()) - } - - fn mark_finalized(&mut self, block: BlockId, justification: Option) -> ClientResult<()> { - self.finalized_blocks.push((block, justification)); - Ok(()) - } - - fn mark_head(&mut self, block: BlockId) -> ClientResult<()> { - assert!(self.set_head.is_none(), "Only one set head per operation is allowed"); - self.set_head = Some(block); - Ok(()) - } -} - -struct StorageDb { - pub db: Arc, - pub state_db: StateDb>, -} - -impl state_machine::Storage for StorageDb { - fn get(&self, key: &H256, prefix: Prefix) -> Result, String> { - let key = prefixed_key::(key, prefix); - self.state_db.get(&key, self).map(|r| r.map(|v| DBValue::from_slice(&v))) - .map_err(|e| format!("Database backend error: {:?}", e)) - } -} - -impl state_db::NodeDb for StorageDb { - type Error = io::Error; - type Key = [u8]; - - fn get(&self, key: &[u8]) -> Result>, Self::Error> { - self.db.get(columns::STATE, key).map(|r| r.map(|v| v.to_vec())) - } -} - -struct DbGenesisStorage(pub H256); - -impl DbGenesisStorage { - pub fn new() -> Self { - let mut root = H256::default(); - let mut mdb = MemoryDB::::default(); - state_machine::TrieDBMut::::new(&mut mdb, &mut root); - DbGenesisStorage(root) - } -} - -impl state_machine::Storage for DbGenesisStorage { - fn get(&self, _key: &H256, _prefix: Prefix) -> Result, String> { - Ok(None) - } -} - -/// A database wrapper for changes tries. -pub struct DbChangesTrieStorage { - db: Arc, - meta: Arc, Block::Hash>>>, - min_blocks_to_keep: Option, - cache: RwLock>>, - _phantom: ::std::marker::PhantomData, -} - -impl> DbChangesTrieStorage { - /// Commit new changes trie. - pub fn commit(&self, tx: &mut DBTransaction, mut changes_trie: MemoryDB) { - for (key, (val, _)) in changes_trie.drain() { - tx.put(columns::CHANGES_TRIE, &key[..], &val); - } - } - - /// Commit changes into changes trie build cache. - pub fn commit_cache(&self, cache_update: ChangesTrieCacheAction>) { - self.cache.write().perform(cache_update); - } - - /// Prune obsolete changes tries. - pub fn prune( - &self, - config: &ChangesTrieConfiguration, - tx: &mut DBTransaction, - block_hash: Block::Hash, - block_num: NumberFor, - ) { - // never prune on archive nodes - let min_blocks_to_keep = match self.min_blocks_to_keep { - Some(min_blocks_to_keep) => min_blocks_to_keep, - None => return, - }; - - state_machine::prune_changes_tries( - config, - &*self, - min_blocks_to_keep.into(), - &state_machine::ChangesTrieAnchorBlockId { - hash: convert_hash(&block_hash), - number: block_num, - }, - |node| tx.delete(columns::CHANGES_TRIE, node.as_ref())); - } -} - -impl client::backend::PrunableStateChangesTrieStorage - for DbChangesTrieStorage -where - Block: BlockT, -{ - fn oldest_changes_trie_block( - &self, - config: &ChangesTrieConfiguration, - best_finalized_block: NumberFor, - ) -> NumberFor { - match self.min_blocks_to_keep { - Some(min_blocks_to_keep) => state_machine::oldest_non_pruned_changes_trie( - config, - min_blocks_to_keep.into(), - best_finalized_block, - ), - None => One::one(), - } - } -} - -impl state_machine::ChangesTrieRootsStorage> - for DbChangesTrieStorage -where - Block: BlockT, -{ - fn build_anchor( - &self, - hash: H256, - ) -> Result>, String> { - utils::read_header::(&*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Hash(hash)) - .map_err(|e| e.to_string()) - .and_then(|maybe_header| maybe_header.map(|header| - state_machine::ChangesTrieAnchorBlockId { - hash, - number: *header.number(), - } - ).ok_or_else(|| format!("Unknown header: {}", hash))) - } - - fn root( - &self, - anchor: &state_machine::ChangesTrieAnchorBlockId>, - block: NumberFor, - ) -> Result, String> { - // 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 { - // if block is finalized, we could just read canonical hash - BlockId::Number(block) - } else { - // 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::( - &*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Number(current_num) - ).map_err(|e| e.to_string())?; - if maybe_anchor_header.hash() == current_hash { - // if anchor is canonicalized, then the block is also canonicalized - BlockId::Number(block) - } else { - // else (block is not finalized + anchor is not canonicalized): - // => 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::( - &*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Hash(current_hash) - ).map_err(|e| e.to_string())?; - - current_hash = *current_header.parent_hash(); - current_num = current_num - One::one(); - } - - BlockId::Hash(current_hash) - } - }; - - 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()))) - } -} - -impl state_machine::ChangesTrieStorage> - for DbChangesTrieStorage -where - Block: BlockT, -{ - fn as_roots_storage(&self) -> &dyn state_machine::ChangesTrieRootsStorage> { - self - } - - fn with_cached_changed_keys( - &self, - root: &H256, - functor: &mut dyn FnMut(&HashMap>, HashSet>>), - ) -> bool { - self.cache.read().with_changed_keys(root, functor) - } - - fn get(&self, key: &H256, _prefix: Prefix) -> Result, String> { - self.db.get(columns::CHANGES_TRIE, &key[..]) - .map_err(|err| format!("{}", err)) - } -} - -/// Disk backend. Keeps data in a key-value store. In archive mode, trie nodes are kept from all blocks. -/// Otherwise, trie nodes are kept only from some recent blocks. -pub struct Backend { - storage: Arc>, - offchain_storage: offchain::LocalStorage, - changes_tries_storage: DbChangesTrieStorage, - /// None<*> means that the value hasn't been cached yet. Some(*) means that the value (either None or - /// Some(*)) has been cached and is valid. - changes_trie_config: Mutex>>, - blockchain: BlockchainDb, - canonicalization_delay: u64, - shared_cache: SharedCache, - import_lock: Mutex<()>, -} - -impl> Backend { - /// Create a new instance of database backend. - /// - /// The pruning window is how old a block must be before the state is pruned. - pub fn new(config: DatabaseSettings, canonicalization_delay: u64) -> ClientResult { - Self::new_inner(config, canonicalization_delay) - } - - fn new_inner(config: DatabaseSettings, canonicalization_delay: u64) -> ClientResult { - #[cfg(feature = "kvdb-rocksdb")] - let db = crate::utils::open_database(&config, columns::META, "full")?; - #[cfg(not(feature = "kvdb-rocksdb"))] - let db = { - log::warn!("Running without the RocksDB feature. The database will NOT be saved."); - Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)) - }; - Self::from_kvdb(db as Arc<_>, canonicalization_delay, &config) - } - - /// Create new memory-backed client backend for tests. - #[cfg(any(test, feature = "test-helpers"))] - pub fn new_test(keep_blocks: u32, canonicalization_delay: u64) -> Self { - let db = Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)); - Self::new_test_db(keep_blocks, canonicalization_delay, db as Arc<_>) - } - - /// Creates a client backend with test settings. - #[cfg(any(test, feature = "test-helpers"))] - pub fn new_test_db(keep_blocks: u32, canonicalization_delay: u64, db: Arc) -> Self { - - let db_setting = DatabaseSettings { - cache_size: None, - state_cache_size: 16777216, - state_cache_child_ratio: Some((50, 100)), - path: Default::default(), - pruning: PruningMode::keep_blocks(keep_blocks), - }; - Self::from_kvdb( - db, - canonicalization_delay, - &db_setting, - ).expect("failed to create test-db") - } - - fn from_kvdb( - db: Arc, - canonicalization_delay: u64, - config: &DatabaseSettings - ) -> ClientResult { - let is_archive_pruning = config.pruning.is_archive(); - let blockchain = BlockchainDb::new(db.clone())?; - let meta = blockchain.meta.clone(); - let map_e = |e: state_db::Error| ::client::error::Error::from(format!("State database error: {:?}", e)); - let state_db: StateDb<_, _> = StateDb::new(config.pruning.clone(), &StateMetaDb(&*db)).map_err(map_e)?; - let storage_db = StorageDb { - db: db.clone(), - state_db, - }; - let offchain_storage = offchain::LocalStorage::new(db.clone()); - let changes_tries_storage = DbChangesTrieStorage { - db, - meta, - min_blocks_to_keep: if is_archive_pruning { None } else { Some(MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR) }, - cache: RwLock::new(ChangesTrieBuildCache::new()), - _phantom: Default::default(), - }; - - Ok(Backend { - storage: Arc::new(storage_db), - offchain_storage, - changes_tries_storage, - changes_trie_config: Mutex::new(None), - blockchain, - canonicalization_delay, - shared_cache: new_shared_cache( - config.state_cache_size, - config.state_cache_child_ratio.unwrap_or(DEFAULT_CHILD_RATIO), - ), - import_lock: Default::default(), - }) - } - - /// 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(); - 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 - } - - /// Read (from storage or cache) changes trie config. - /// - /// Currently changes tries configuration is set up once (at genesis) and could not - /// be changed. Thus, we'll actually read value once and then just use cached value. - fn changes_trie_config(&self, block: Block::Hash) -> ClientResult> { - let mut cached_changes_trie_config = self.changes_trie_config.lock(); - match cached_changes_trie_config.clone() { - Some(cached_changes_trie_config) => Ok(cached_changes_trie_config), - None => { - use client::backend::Backend; - let changes_trie_config = self - .state_at(BlockId::Hash(block))? - .storage(well_known_keys::CHANGES_TRIE_CONFIG)? - .and_then(|v| Decode::decode(&mut &*v).ok()); - *cached_changes_trie_config = Some(changes_trie_config.clone()); - Ok(changes_trie_config) - }, - } - } - - /// 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), - ) -> ClientResult<(Vec, Vec)> { - 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 = header_metadata::tree_route( - &self.blockchain, - meta.best_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::Error::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, - ) -> ClientResult<()> { - let last_finalized = last_finalized.unwrap_or_else(|| self.blockchain.meta.read().finalized_hash); - if *header.parent_hash() != last_finalized { - return Err(::client::error::Error::NonSequentialFinalization( - 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>>, - ) -> ClientResult<(Block::Hash, ::Number, bool, bool)> { - // 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 importing a non-finalized block. - fn force_delayed_canonicalize( - &self, - transaction: &mut DBTransaction, - hash: Block::Hash, - number: NumberFor, - ) - -> ClientResult<()> - { - let number_u64 = number.saturated_into::(); - if number_u64 > self.canonicalization_delay { - let new_canonical = number_u64 - self.canonicalization_delay; - - if new_canonical <= self.storage.state_db.best_canonical().unwrap_or(0) { - return Ok(()) - } - - let hash = if new_canonical == number_u64 { - hash - } else { - ::client::blockchain::HeaderBackend::hash(&self.blockchain, new_canonical.saturated_into())? - .expect("existence of block with number `new_canonical` \ - implies existence of blocks with all numbers before it; qed") - }; - - trace!(target: "db", "Canonicalize block #{} ({:?})", new_canonical, 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) - -> ClientResult<()> - { - let mut transaction = DBTransaction::new(); - let mut finalization_displaced_leaves = None; - - operation.apply_aux(&mut transaction); - - let mut meta_updates = Vec::with_capacity(operation.finalized_blocks.len()); - let mut last_finalized_hash = self.blockchain.meta.read().finalized_hash; - - for (block, justification) in operation.finalized_blocks { - let block_hash = self.blockchain.expect_block_hash_from_id(&block)?; - let block_header = self.blockchain.expect_header(BlockId::Hash(block_hash))?; - - meta_updates.push(self.finalize_block_with_transaction( - &mut transaction, - &block_hash, - &block_header, - Some(last_finalized_hash), - justification, - &mut 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, - )?; - - let header_metadata = CachedHeaderMetadata::from(&pending_block.header); - self.blockchain.insert_header_metadata( - header_metadata.hash, - header_metadata, - ); - - transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode()); - if let Some(body) = pending_block.body { - transaction.put(columns::BODY, &lookup_key, &body.encode()); - } - 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.saturated_into::(); - 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); - let cache = operation.old_state.release(); // release state reference so that it can be finalized - - 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, cache)) - } else { - None - }; - - let cache_update = 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(); - - let (enacted, retracted) = self.set_head_with_transaction( - &mut transaction, - hash.clone(), - (number.clone(), hash.clone()) - )?; - meta_updates.push((hash, *number, true, false)); - Some((enacted, retracted)) - } else { - return Err(client::error::Error::UnknownBlock(format!("Cannot set head {:?}", set_head))) - } - } else { - None - }; - - let write_result = self.storage.db.write(transaction).map_err(db_err); - - if let Some(changes_trie_cache_update) = operation.changes_trie_cache_update { - self.changes_tries_storage.commit_cache(changes_trie_cache_update); - } - - if let Some((number, hash, enacted, retracted, displaced_leaf, is_best, mut cache)) = imported { - if let Err(e) = write_result { - let mut leaves = self.blockchain.leaves.write(); - let mut undo = leaves.undo(); - if let Some(displaced_leaf) = displaced_leaf { - undo.undo_import(displaced_leaf); - } - - if let Some(finalization_displaced) = finalization_displaced_leaves { - undo.undo_finalization(finalization_displaced); - } - - return Err(e) - } - - cache.sync_cache( - &enacted, - &retracted, - operation.storage_updates, - operation.child_storage_updates, - Some(hash), - Some(number), - || is_best, - ); - } - - if let Some((enacted, retracted)) = cache_update { - self.shared_cache.lock().sync(&enacted, &retracted); - } - - 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. - fn note_finalized( - &self, - transaction: &mut DBTransaction, - f_header: &Block::Header, - f_hash: Block::Hash, - displaced: &mut Option>> - ) -> ClientResult<()> where - Block: BlockT, - { - let f_num = f_header.number().clone(); - - if self.storage.state_db.best_canonical().map(|c| f_num.saturated_into::() > c).unwrap_or(true) { - let parent_hash = f_header.parent_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) - .map_err(|e: state_db::Error| client::error::Error::from(format!("State database error: {:?}", e)))?; - apply_state_commit(transaction, commit); - - let changes_trie_config = self.changes_trie_config(parent_hash)?; - if let Some(changes_trie_config) = changes_trie_config { - 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(()) - } -} - -fn apply_state_commit(transaction: &mut DBTransaction, commit: state_db::CommitSet>) { - for (key, val) in commit.data.inserted.into_iter() { - transaction.put(columns::STATE, &key[..], &val); - } - for key in commit.data.deleted.into_iter() { - transaction.delete(columns::STATE, &key[..]); - } - for (key, val) in commit.meta.inserted.into_iter() { - transaction.put(columns::STATE_META, &key[..], &val); - } - for key in commit.meta.deleted.into_iter() { - transaction.delete(columns::STATE_META, &key[..]); - } -} - -impl client::backend::AuxStore for Backend where Block: BlockT { - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> ClientResult<()> { - let mut transaction = DBTransaction::new(); - for (k, v) in insert { - transaction.put(columns::AUX, k, v); - } - for k in delete { - transaction.delete(columns::AUX, k); - } - self.storage.db.write(transaction).map_err(db_err)?; - Ok(()) - } - - fn get_aux(&self, key: &[u8]) -> ClientResult>> { - Ok(self.storage.db.get(columns::AUX, key).map(|r| r.map(|v| v.to_vec())).map_err(db_err)?) - } -} - -impl client::backend::Backend for Backend where Block: BlockT { - type BlockImportOperation = BlockImportOperation; - type Blockchain = BlockchainDb; - type State = CachingState, Block>; - type ChangesTrieStorage = DbChangesTrieStorage; - type OffchainStorage = offchain::LocalStorage; - - fn begin_operation(&self) -> ClientResult { - let old_state = self.state_at(BlockId::Hash(Default::default()))?; - Ok(BlockImportOperation { - pending_block: None, - old_state, - db_updates: PrefixedMemoryDB::default(), - storage_updates: Default::default(), - child_storage_updates: Default::default(), - changes_trie_updates: MemoryDB::default(), - changes_trie_cache_update: None, - aux_ops: Vec::new(), - finalized_blocks: Vec::new(), - set_head: None, - }) - } - - fn begin_state_operation( - &self, - operation: &mut Self::BlockImportOperation, - block: BlockId, - ) -> ClientResult<()> { - operation.old_state = self.state_at(block)?; - Ok(()) - } - - fn commit_operation(&self, operation: Self::BlockImportOperation) - -> ClientResult<()> - { - match self.try_commit_operation(operation) { - Ok(_) => { - self.storage.state_db.apply_pending(); - Ok(()) - }, - e @ Err(_) => { - self.storage.state_db.revert_pending(); - e - } - } - } - - fn finalize_block(&self, block: BlockId, justification: Option) - -> ClientResult<()> - { - 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, number, is_best, is_finalized); - Ok(()) - }; - match commit(&mut displaced) { - Ok(()) => self.storage.state_db.apply_pending(), - e @ Err(_) => { - self.storage.state_db.revert_pending(); - if let Some(displaced) = displaced { - self.blockchain.leaves.write().undo().undo_finalization(displaced); - } - return e; - } - } - Ok(()) - } - - fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage> { - Some(&self.changes_tries_storage) - } - - fn offchain_storage(&self) -> Option { - Some(self.offchain_storage.clone()) - } - - fn revert(&self, n: NumberFor) -> ClientResult> { - let mut best = self.blockchain.info().best_number; - let finalized = self.blockchain.info().finalized_number; - let revertible = best - finalized; - let n = if revertible < n { revertible } else { n }; - - for c in 0 .. n.saturated_into::() { - if best.is_zero() { - return Ok(c.saturated_into::>()) - } - let mut transaction = DBTransaction::new(); - match self.storage.state_db.revert_one() { - Some(commit) => { - apply_state_commit(&mut transaction, commit); - let removed = self.blockchain.header(BlockId::Number(best))?.ok_or_else( - || client::error::Error::UnknownBlock( - format!("Error reverting to {}. Block hash not found.", best)))?; - - best -= One::one(); // prev block - let hash = self.blockchain.hash(best)?.ok_or_else( - || client::error::Error::UnknownBlock( - format!("Error reverting to {}. Block hash not found.", best)))?; - let key = utils::number_and_hash_to_lookup_key(best.clone(), &hash)?; - 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(hash, best, true, false); - self.blockchain.leaves.write().revert(removed.hash().clone(), removed.number().clone(), removed.parent_hash().clone()); - } - None => return Ok(c.saturated_into::>()) - } - } - Ok(n) - } - - fn blockchain(&self) -> &BlockchainDb { - &self.blockchain - } - - fn used_state_cache_size(&self) -> Option { - let used = (*&self.shared_cache).lock().used_storage_cache_size(); - Some(used) - } - - fn state_at(&self, block: BlockId) -> ClientResult { - use client::blockchain::HeaderBackend as BcHeaderBackend; - - // special case for genesis initialization - match block { - BlockId::Hash(h) if h == Default::default() => { - let genesis_storage = DbGenesisStorage::new(); - let root = genesis_storage.0.clone(); - let db_state = DbState::new(Arc::new(genesis_storage), root); - let state = RefTrackingState::new(db_state, self.storage.clone(), None); - return Ok(CachingState::new(state, self.shared_cache.clone(), None)); - }, - _ => {} - } - - match self.blockchain.header(block) { - Ok(Some(ref hdr)) => { - let hash = hdr.hash(); - if let Ok(()) = self.storage.state_db.pin(&hash) { - let root = H256::from_slice(hdr.state_root().as_ref()); - let db_state = DbState::new(self.storage.clone(), root); - let state = RefTrackingState::new(db_state, self.storage.clone(), Some(hash.clone())); - Ok(CachingState::new(state, self.shared_cache.clone(), Some(hash))) - } else { - Err(client::error::Error::UnknownBlock(format!("State already discarded for {:?}", block))) - } - }, - Ok(None) => Err(client::error::Error::UnknownBlock(format!("Unknown state for block {:?}", block))), - Err(e) => Err(e), - } - } - - fn have_state_at(&self, hash: &Block::Hash, number: NumberFor) -> bool { - !self.storage.state_db.is_pruned(hash, number.saturated_into::()) - } - - fn destroy_state(&self, state: Self::State) -> ClientResult<()> { - if let Some(hash) = state.cache.parent_hash.clone() { - let is_best = || self.blockchain.meta.read().best_hash == hash; - state.release().sync_cache(&[], &[], vec![], vec![], None, None, is_best); - } - Ok(()) - } - - fn get_import_lock(&self) -> &Mutex<()> { - &self.import_lock - } -} - -impl client::backend::LocalBackend for Backend -where Block: BlockT {} - -/// TODO: remove me in #3201 -pub fn unused_sink(cache_tx: crate::cache::DbCacheTransaction) { - cache_tx.on_block_revert(&crate::cache::ComplexBlockId::new(Default::default(), 0.into())).unwrap(); - unimplemented!() -} - -#[cfg(test)] -mod tests { - use hash_db::{HashDB, EMPTY_PREFIX}; - use super::*; - use crate::columns; - use client::backend::Backend as BTrait; - use client::blockchain::Backend as BLBTrait; - use client::backend::BlockImportOperation as Op; - use sr_primitives::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; - use sr_primitives::traits::{Hash, BlakeTwo256}; - use state_machine::{TrieMut, TrieDBMut, ChangesTrieRootsStorage, ChangesTrieStorage}; - use header_metadata::{lowest_common_ancestor, tree_route}; - - use test_client; - - type Block = RawBlock>; - - fn prepare_changes(changes: Vec<(Vec, Vec)>) -> (H256, MemoryDB) { - let mut changes_root = H256::default(); - let mut changes_trie_update = MemoryDB::::default(); - { - let mut trie = TrieDBMut::::new( - &mut changes_trie_update, - &mut changes_root - ); - for (key, value) in changes { - trie.insert(&key, &value).unwrap(); - } - } - - (changes_root, changes_trie_update) - } - - fn insert_header( - backend: &Backend, - number: u64, - parent_hash: H256, - changes: Vec<(Vec, Vec)>, - extrinsics_root: H256, - ) -> H256 { - use sr_primitives::testing::Digest; - let (changes_root, changes_trie_update) = prepare_changes(changes); - let digest = Digest { - logs: vec![ - DigestItem::ChangesTrieRoot(changes_root), - ], - }; - let header = Header { - number, - parent_hash, - state_root: BlakeTwo256::trie_root(Vec::new()), - digest, - extrinsics_root, - }; - let header_hash = header.hash(); - - let block_id = if number == 0 { - BlockId::Hash(Default::default()) - } else { - BlockId::Number(number - 1) - }; - 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, ChangesTrieCacheAction::Clear)).unwrap(); - backend.commit_operation(op).unwrap(); - - header_hash - } - - #[test] - fn block_hash_inserted_correctly() { - let backing = { - let db = Backend::::new_test(1, 0); - for i in 0..10 { - assert!(db.blockchain().hash(i).unwrap().is_none()); - - { - let id = if i == 0 { - BlockId::Hash(Default::default()) - } else { - BlockId::Number(i - 1) - }; - - 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 { - Default::default() - } else { - db.blockchain.hash(i - 1).unwrap().unwrap() - }, - state_root: Default::default(), - digest: Default::default(), - extrinsics_root: Default::default(), - }; - - op.set_block_data( - header, - Some(vec![]), - None, - NewBlockState::Best, - ).unwrap(); - db.commit_operation(op).unwrap(); - } - - assert!(db.blockchain().hash(i).unwrap().is_some()) - } - db.storage.db.clone() - }; - - let backend = Backend::::new_test_db(1, 0, backing); - assert_eq!(backend.blockchain().info().best_number, 9); - for i in 0..10 { - assert!(backend.blockchain().hash(i).unwrap().is_some()) - } - } - - #[test] - fn set_state_data() { - let db = Backend::::new_test(2, 0); - let hash = { - 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(), - state_root: Default::default(), - digest: Default::default(), - extrinsics_root: Default::default(), - }; - - let storage = vec![ - (vec![1, 3, 5], vec![2, 4, 6]), - (vec![1, 2, 3], vec![9, 9, 9]), - ]; - - header.state_root = op.old_state.storage_root(storage - .iter() - .cloned() - .map(|(x, y)| (x, Some(y))) - ).0.into(); - let hash = header.hash(); - - op.reset_storage(storage.iter().cloned().collect(), Default::default()).unwrap(); - op.set_block_data( - header.clone(), - Some(vec![]), - None, - NewBlockState::Best, - ).unwrap(); - - db.commit_operation(op).unwrap(); - - let state = db.state_at(BlockId::Number(0)).unwrap(); - - assert_eq!(state.storage(&[1, 3, 5]).unwrap(), Some(vec![2, 4, 6])); - assert_eq!(state.storage(&[1, 2, 3]).unwrap(), Some(vec![9, 9, 9])); - assert_eq!(state.storage(&[5, 5, 5]).unwrap(), None); - - hash - }; - - { - 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, - state_root: Default::default(), - digest: Default::default(), - extrinsics_root: Default::default(), - }; - - let storage = vec![ - (vec![1, 3, 5], None), - (vec![5, 5, 5], Some(vec![4, 5, 6])), - ]; - - let (root, overlay) = op.old_state.storage_root(storage.iter().cloned()); - op.update_db_storage(overlay).unwrap(); - header.state_root = root.into(); - - op.set_block_data( - header, - Some(vec![]), - None, - NewBlockState::Best, - ).unwrap(); - - db.commit_operation(op).unwrap(); - - let state = db.state_at(BlockId::Number(1)).unwrap(); - - assert_eq!(state.storage(&[1, 3, 5]).unwrap(), None); - assert_eq!(state.storage(&[1, 2, 3]).unwrap(), Some(vec![9, 9, 9])); - assert_eq!(state.storage(&[5, 5, 5]).unwrap(), Some(vec![4, 5, 6])); - } - } - - #[test] - fn delete_only_when_negative_rc() { - let _ = ::env_logger::try_init(); - let key; - let backend = Backend::::new_test(1, 0); - - let hash = { - 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(), - 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(); - let hash = header.hash(); - - op.reset_storage(storage.iter().cloned().collect(), Default::default()).unwrap(); - - key = op.db_updates.insert(EMPTY_PREFIX, b"hello"); - op.set_block_data( - header, - Some(vec![]), - None, - NewBlockState::Best, - ).unwrap(); - - backend.commit_operation(op).unwrap(); - assert_eq!(backend.storage.db.get( - columns::STATE, - &trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().unwrap(), &b"hello"[..]); - hash - }; - - let hash = { - 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, - 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(); - let hash = header.hash(); - - op.db_updates.insert(EMPTY_PREFIX, b"hello"); - op.db_updates.remove(&key, EMPTY_PREFIX); - op.set_block_data( - header, - Some(vec![]), - None, - NewBlockState::Best, - ).unwrap(); - - backend.commit_operation(op).unwrap(); - assert_eq!(backend.storage.db.get( - columns::STATE, - &trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().unwrap(), &b"hello"[..]); - hash - }; - - 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, - 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(); - let hash = header.hash(); - - op.db_updates.remove(&key, EMPTY_PREFIX); - op.set_block_data( - header, - Some(vec![]), - None, - NewBlockState::Best, - ).unwrap(); - - backend.commit_operation(op).unwrap(); - - - assert!(backend.storage.db.get( - columns::STATE, - &trie::prefixed_key::(&key, EMPTY_PREFIX) - ).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, - &trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().is_none()); - } - - backend.finalize_block(BlockId::Number(1), None).unwrap(); - backend.finalize_block(BlockId::Number(2), None).unwrap(); - backend.finalize_block(BlockId::Number(3), None).unwrap(); - assert!(backend.storage.db.get( - columns::STATE, - &trie::prefixed_key::(&key, EMPTY_PREFIX) - ).unwrap().is_none()); - } - - #[test] - fn changes_trie_storage_works() { - let backend = Backend::::new_test(1000, 100); - backend.changes_tries_storage.meta.write().finalized_number = 1000; - - - 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: 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() { - assert_eq!(backend.changes_trie_storage().unwrap().get(&key, EMPTY_PREFIX), Ok(Some(val))); - } - }; - - let changes0 = vec![(b"key_at_0".to_vec(), b"val_at_0".to_vec())]; - let changes1 = vec![ - (b"key_at_1".to_vec(), b"val_at_1".to_vec()), - (b"another_key_at_1".to_vec(), b"another_val_at_1".to_vec()), - ]; - let changes2 = vec![(b"key_at_2".to_vec(), b"val_at_2".to_vec())]; - - let block0 = insert_header(&backend, 0, Default::default(), changes0.clone(), Default::default()); - let block1 = insert_header(&backend, 1, block0, changes1.clone(), Default::default()); - let _ = insert_header(&backend, 2, block1, changes2.clone(), Default::default()); - - // check that the storage contains tries for all blocks - check_changes(&backend, 0, changes0); - check_changes(&backend, 1, changes1); - check_changes(&backend, 2, changes2); - } - - #[test] - fn changes_trie_storage_works_with_forks() { - let backend = Backend::::new_test(1000, 100); - - let changes0 = vec![(b"k0".to_vec(), b"v0".to_vec())]; - let changes1 = vec![(b"k1".to_vec(), b"v1".to_vec())]; - let changes2 = vec![(b"k2".to_vec(), b"v2".to_vec())]; - let block0 = insert_header(&backend, 0, Default::default(), changes0.clone(), Default::default()); - let block1 = insert_header(&backend, 1, block0, changes1.clone(), Default::default()); - let block2 = insert_header(&backend, 2, block1, changes2.clone(), Default::default()); - - let changes2_1_0 = vec![(b"k3".to_vec(), b"v3".to_vec())]; - let changes2_1_1 = vec![(b"k4".to_vec(), b"v4".to_vec())]; - let block2_1_0 = insert_header(&backend, 3, block2, changes2_1_0.clone(), Default::default()); - let block2_1_1 = insert_header(&backend, 4, block2_1_0, changes2_1_1.clone(), Default::default()); - - let changes2_2_0 = vec![(b"k5".to_vec(), b"v5".to_vec())]; - let changes2_2_1 = vec![(b"k6".to_vec(), b"v6".to_vec())]; - let block2_2_0 = insert_header(&backend, 3, block2, changes2_2_0.clone(), Default::default()); - let block2_2_1 = insert_header(&backend, 4, block2_2_0, changes2_2_1.clone(), Default::default()); - - // finalize block1 - backend.changes_tries_storage.meta.write().finalized_number = 1; - - // branch1: when asking for finalized block hash - let (changes1_root, _) = prepare_changes(changes1); - let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root))); - - // branch2: when asking for finalized block hash - let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root))); - - // branch1: when asking for non-finalized block hash (search by traversal) - let (changes2_1_0_root, _) = prepare_changes(changes2_1_0); - let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_1_0_root))); - - // branch2: when asking for non-finalized block hash (search using canonicalized hint) - let (changes2_2_0_root, _) = prepare_changes(changes2_2_0); - let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); - - // finalize first block of branch2 (block2_2_0) - backend.changes_tries_storage.meta.write().finalized_number = 3; - - // branch2: when asking for finalized block of this branch - assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); - - // branch1: when asking for finalized block of other branch - // => result is incorrect (returned for the block of branch1), but this is expected, - // because the other fork is abandoned (forked before finalized header) - let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 }; - assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root))); - } - - #[test] - fn changes_tries_with_digest_are_pruned_on_finalization() { - let mut backend = Backend::::new_test(1000, 100); - backend.changes_tries_storage.min_blocks_to_keep = Some(8); - let config = ChangesTrieConfiguration { - digest_interval: 2, - digest_levels: 2, - }; - - // insert some blocks - let block0 = insert_header(&backend, 0, Default::default(), vec![(b"key_at_0".to_vec(), b"val_at_0".to_vec())], Default::default()); - let block1 = insert_header(&backend, 1, block0, vec![(b"key_at_1".to_vec(), b"val_at_1".to_vec())], Default::default()); - let block2 = insert_header(&backend, 2, block1, vec![(b"key_at_2".to_vec(), b"val_at_2".to_vec())], Default::default()); - let block3 = insert_header(&backend, 3, block2, vec![(b"key_at_3".to_vec(), b"val_at_3".to_vec())], Default::default()); - let block4 = insert_header(&backend, 4, block3, vec![(b"key_at_4".to_vec(), b"val_at_4".to_vec())], Default::default()); - let block5 = insert_header(&backend, 5, block4, vec![(b"key_at_5".to_vec(), b"val_at_5".to_vec())], Default::default()); - let block6 = insert_header(&backend, 6, block5, vec![(b"key_at_6".to_vec(), b"val_at_6".to_vec())], Default::default()); - let block7 = insert_header(&backend, 7, block6, vec![(b"key_at_7".to_vec(), b"val_at_7".to_vec())], Default::default()); - let block8 = insert_header(&backend, 8, block7, vec![(b"key_at_8".to_vec(), b"val_at_8".to_vec())], Default::default()); - 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 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: 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() - } - let root1 = read_changes_trie_root(&backend, 1); assert_eq!(backend.changes_tries_storage.root(&anchor, 1).unwrap(), Some(root1)); - let root2 = read_changes_trie_root(&backend, 2); assert_eq!(backend.changes_tries_storage.root(&anchor, 2).unwrap(), Some(root2)); - let root3 = read_changes_trie_root(&backend, 3); assert_eq!(backend.changes_tries_storage.root(&anchor, 3).unwrap(), Some(root3)); - let root4 = read_changes_trie_root(&backend, 4); assert_eq!(backend.changes_tries_storage.root(&anchor, 4).unwrap(), Some(root4)); - let root5 = read_changes_trie_root(&backend, 5); assert_eq!(backend.changes_tries_storage.root(&anchor, 5).unwrap(), Some(root5)); - let root6 = read_changes_trie_root(&backend, 6); assert_eq!(backend.changes_tries_storage.root(&anchor, 6).unwrap(), Some(root6)); - let root7 = read_changes_trie_root(&backend, 7); assert_eq!(backend.changes_tries_storage.root(&anchor, 7).unwrap(), Some(root7)); - let root8 = read_changes_trie_root(&backend, 8); assert_eq!(backend.changes_tries_storage.root(&anchor, 8).unwrap(), Some(root8)); - let root9 = read_changes_trie_root(&backend, 9); assert_eq!(backend.changes_tries_storage.root(&anchor, 9).unwrap(), Some(root9)); - let root10 = read_changes_trie_root(&backend, 10); assert_eq!(backend.changes_tries_storage.root(&anchor, 10).unwrap(), Some(root10)); - let root11 = read_changes_trie_root(&backend, 11); assert_eq!(backend.changes_tries_storage.root(&anchor, 11).unwrap(), Some(root11)); - let root12 = read_changes_trie_root(&backend, 12); assert_eq!(backend.changes_tries_storage.root(&anchor, 12).unwrap(), Some(root12)); - - // now simulate finalization of block#12, causing prune of tries at #1..#4 - let mut tx = DBTransaction::new(); - backend.changes_tries_storage.prune(&config, &mut tx, Default::default(), 12); - backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root1, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root2, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root3, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root4, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root5, EMPTY_PREFIX).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root6, EMPTY_PREFIX).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root7, EMPTY_PREFIX).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root8, EMPTY_PREFIX).unwrap().is_some()); - - // now simulate finalization of block#16, causing prune of tries at #5..#8 - let mut tx = DBTransaction::new(); - backend.changes_tries_storage.prune(&config, &mut tx, Default::default(), 16); - backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root5, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root6, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root7, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root8, EMPTY_PREFIX).unwrap().is_none()); - - // now "change" pruning mode to archive && simulate finalization of block#20 - // => no changes tries are pruned, because we never prune in archive mode - backend.changes_tries_storage.min_blocks_to_keep = None; - let mut tx = DBTransaction::new(); - backend.changes_tries_storage.prune(&config, &mut tx, Default::default(), 20); - backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root9, EMPTY_PREFIX).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root10, EMPTY_PREFIX).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root11, EMPTY_PREFIX).unwrap().is_some()); - assert!(backend.changes_tries_storage.get(&root12, EMPTY_PREFIX).unwrap().is_some()); - } - - #[test] - fn changes_tries_without_digest_are_pruned_on_finalization() { - let mut backend = Backend::::new_test(1000, 100); - backend.changes_tries_storage.min_blocks_to_keep = Some(4); - let config = ChangesTrieConfiguration { - digest_interval: 0, - digest_levels: 0, - }; - - // insert some blocks - let block0 = insert_header(&backend, 0, Default::default(), vec![(b"key_at_0".to_vec(), b"val_at_0".to_vec())], Default::default()); - let block1 = insert_header(&backend, 1, block0, vec![(b"key_at_1".to_vec(), b"val_at_1".to_vec())], Default::default()); - let block2 = insert_header(&backend, 2, block1, vec![(b"key_at_2".to_vec(), b"val_at_2".to_vec())], Default::default()); - let block3 = insert_header(&backend, 3, block2, vec![(b"key_at_3".to_vec(), b"val_at_3".to_vec())], Default::default()); - let block4 = insert_header(&backend, 4, block3, vec![(b"key_at_4".to_vec(), b"val_at_4".to_vec())], Default::default()); - let block5 = insert_header(&backend, 5, block4, vec![(b"key_at_5".to_vec(), b"val_at_5".to_vec())], Default::default()); - let block6 = insert_header(&backend, 6, block5, vec![(b"key_at_6".to_vec(), b"val_at_6".to_vec())], Default::default()); - - // check that roots of all tries are in the columns::CHANGES_TRIE - let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block6, number: 6 }; - 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() - } - - let root1 = read_changes_trie_root(&backend, 1); assert_eq!(backend.changes_tries_storage.root(&anchor, 1).unwrap(), Some(root1)); - let root2 = read_changes_trie_root(&backend, 2); assert_eq!(backend.changes_tries_storage.root(&anchor, 2).unwrap(), Some(root2)); - let root3 = read_changes_trie_root(&backend, 3); assert_eq!(backend.changes_tries_storage.root(&anchor, 3).unwrap(), Some(root3)); - let root4 = read_changes_trie_root(&backend, 4); assert_eq!(backend.changes_tries_storage.root(&anchor, 4).unwrap(), Some(root4)); - let root5 = read_changes_trie_root(&backend, 5); assert_eq!(backend.changes_tries_storage.root(&anchor, 5).unwrap(), Some(root5)); - let root6 = read_changes_trie_root(&backend, 6); assert_eq!(backend.changes_tries_storage.root(&anchor, 6).unwrap(), Some(root6)); - - // now simulate finalization of block#5, causing prune of trie at #1 - let mut tx = DBTransaction::new(); - backend.changes_tries_storage.prune(&config, &mut tx, block5, 5); - backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root1, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root2, EMPTY_PREFIX).unwrap().is_some()); - - // now simulate finalization of block#6, causing prune of tries at #2 - let mut tx = DBTransaction::new(); - backend.changes_tries_storage.prune(&config, &mut tx, block6, 6); - backend.storage.db.write(tx).unwrap(); - assert!(backend.changes_tries_storage.get(&root2, EMPTY_PREFIX).unwrap().is_none()); - assert!(backend.changes_tries_storage.get(&root3, EMPTY_PREFIX).unwrap().is_some()); - } - - #[test] - fn tree_route_works() { - let backend = Backend::::new_test(1000, 100); - let blockchain = backend.blockchain(); - let block0 = insert_header(&backend, 0, Default::default(), Vec::new(), Default::default()); - - // fork from genesis: 3 prong. - let a1 = insert_header(&backend, 1, block0, Vec::new(), Default::default()); - let a2 = insert_header(&backend, 2, a1, Vec::new(), Default::default()); - let a3 = insert_header(&backend, 3, a2, Vec::new(), Default::default()); - - // fork from genesis: 2 prong. - let b1 = insert_header(&backend, 1, block0, Vec::new(), H256::from([1; 32])); - let b2 = insert_header(&backend, 2, b1, Vec::new(), Default::default()); - - { - let tree_route = tree_route(blockchain, a3, b2).unwrap(); - - assert_eq!(tree_route.common_block().hash, block0); - assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2, a1]); - assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![b1, b2]); - } - - { - let tree_route = tree_route(blockchain, a1, a3).unwrap(); - - assert_eq!(tree_route.common_block().hash, a1); - assert!(tree_route.retracted().is_empty()); - assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![a2, a3]); - } - - { - let tree_route = tree_route(blockchain, a3, a1).unwrap(); - - assert_eq!(tree_route.common_block().hash, a1); - assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2]); - assert!(tree_route.enacted().is_empty()); - } - - { - let tree_route = tree_route(blockchain, a2, a2).unwrap(); - - assert_eq!(tree_route.common_block().hash, a2); - assert!(tree_route.retracted().is_empty()); - assert!(tree_route.enacted().is_empty()); - } - } - - #[test] - fn tree_route_child() { - let backend = Backend::::new_test(1000, 100); - let blockchain = backend.blockchain(); - - 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 = tree_route(blockchain, block0, 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 lowest_common_ancestor_works() { - let backend = Backend::::new_test(1000, 100); - let blockchain = backend.blockchain(); - let block0 = insert_header(&backend, 0, Default::default(), Vec::new(), Default::default()); - - // fork from genesis: 3 prong. - let a1 = insert_header(&backend, 1, block0, Vec::new(), Default::default()); - let a2 = insert_header(&backend, 2, a1, Vec::new(), Default::default()); - let a3 = insert_header(&backend, 3, a2, Vec::new(), Default::default()); - - // fork from genesis: 2 prong. - let b1 = insert_header(&backend, 1, block0, Vec::new(), H256::from([1; 32])); - let b2 = insert_header(&backend, 2, b1, Vec::new(), Default::default()); - - { - let lca = lowest_common_ancestor(blockchain, a3, b2).unwrap(); - - assert_eq!(lca.hash, block0); - assert_eq!(lca.number, 0); - } - - { - let lca = lowest_common_ancestor(blockchain, a1, a3).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(blockchain, a3, a1).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(blockchain, a2, a3).unwrap(); - - assert_eq!(lca.hash, a2); - assert_eq!(lca.number, 2); - } - - { - let lca = lowest_common_ancestor(blockchain, a2, a1).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(blockchain, a2, a2).unwrap(); - - assert_eq!(lca.hash, a2); - assert_eq!(lca.number, 2); - } - } - - #[test] - fn test_tree_route_regression() { - // NOTE: this is a test for a regression introduced in #3665, the result - // of tree_route would be erroneously computed, since it was taking into - // account the `ancestor` in `CachedHeaderMetadata` for the comparison. - // in this test we simulate the same behavior with the side-effect - // triggering the issue being eviction of a previously fetched record - // from the cache, therefore this test is dependent on the LRU cache - // size for header metadata, which is currently set to 5000 elements. - let backend = Backend::::new_test(10000, 10000); - let blockchain = backend.blockchain(); - - let genesis = insert_header(&backend, 0, Default::default(), Vec::new(), Default::default()); - - let block100 = (1..=100).fold(genesis, |parent, n| { - insert_header(&backend, n, parent, Vec::new(), Default::default()) - }); - - let block7000 = (101..=7000).fold(block100, |parent, n| { - insert_header(&backend, n, parent, Vec::new(), Default::default()) - }); - - // This will cause the ancestor of `block100` to be set to `genesis` as a side-effect. - lowest_common_ancestor(blockchain, genesis, block100).unwrap(); - - // While traversing the tree we will have to do 6900 calls to - // `header_metadata`, which will make sure we will exhaust our cache - // which only takes 5000 elements. In particular, the `CachedHeaderMetadata` struct for - // block #100 will be evicted and will get a new value (with ancestor set to its parent). - let tree_route = tree_route(blockchain, block100, block7000).unwrap(); - - assert!(tree_route.retracted().is_empty()); - } - - #[test] - fn test_leaves_with_complex_block_tree() { - let backend: Arc> = Arc::new(Backend::new_test(20, 20)); - 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); - assert!(backend.get_aux(b"test").unwrap().is_none()); - backend.insert_aux(&[(&b"test"[..], &b"hello"[..])], &[]).unwrap(); - assert_eq!(b"hello", &backend.get_aux(b"test").unwrap().unwrap()[..]); - backend.insert_aux(&[], &[&b"test"[..]]).unwrap(); - assert!(backend.get_aux(b"test").unwrap().is_none()); - } - - #[test] - fn test_finalize_block_with_justification() { - use client::blockchain::{Backend as BlockChainBackend}; - - let backend = Backend::::new_test(10, 10); - - 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(1), justification.clone()).unwrap(); - - assert_eq!( - 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 deleted file mode 100644 index 19fc7fde35f33..0000000000000 --- a/core/client/db/src/light.rs +++ /dev/null @@ -1,1148 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! RocksDB-based light client blockchain storage. - -use std::{sync::Arc, collections::HashMap}; -use std::convert::TryInto; -use parking_lot::RwLock; - -use kvdb::{KeyValueDB, DBTransaction}; - -use client::backend::{AuxStore, NewBlockState}; -use client::blockchain::{ - BlockStatus, Cache as BlockchainCache, - HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo, - well_known_cache_keys, -}; -use client::cht; -use client::error::{Error as ClientError, Result as ClientResult}; -use client::light::blockchain::Storage as LightBlockchainStorage; -use codec::{Decode, Encode}; -use primitives::Blake2Hasher; -use sr_primitives::generic::{DigestItem, BlockId}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor}; -use header_metadata::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache}; -use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType}; -use crate::utils::{self, meta_keys, Meta, db_err, read_db, block_id_to_lookup_key, read_meta}; -use crate::DatabaseSettings; -use log::{trace, warn, debug}; - -pub(crate) mod columns { - 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); - pub const CHT: Option = Some(4); - pub const AUX: Option = Some(5); -} - -/// Prefix for headers CHT. -const HEADER_CHT_PREFIX: u8 = 0; -/// Prefix for changes tries roots CHT. -const CHANGES_TRIE_CHT_PREFIX: u8 = 1; - -/// Light blockchain storage. Stores most recent headers + CHTs for older headers. -/// Locks order: meta, cache. -pub struct LightStorage { - db: Arc, - meta: RwLock, Block::Hash>>, - cache: Arc>, - header_metadata_cache: HeaderMetadataCache, -} - -impl LightStorage - where - Block: BlockT, -{ - /// Create new storage with given settings. - pub fn new(config: DatabaseSettings) -> ClientResult { - Self::new_inner(config) - } - - #[cfg(feature = "kvdb-rocksdb")] - fn new_inner(config: DatabaseSettings) -> ClientResult { - let db = crate::utils::open_database(&config, columns::META, "light")?; - Self::from_kvdb(db as Arc<_>) - } - - #[cfg(not(feature = "kvdb-rocksdb"))] - fn new_inner(_config: DatabaseSettings) -> ClientResult { - log::warn!("Running without the RocksDB feature. The database will NOT be saved."); - let db = Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)); - Self::from_kvdb(db as Arc<_>) - } - - /// Create new memory-backed `LightStorage` for tests. - #[cfg(any(test, feature = "test-helpers"))] - pub fn new_test() -> Self { - use utils::NUM_COLUMNS; - - let db = Arc::new(::kvdb_memorydb::create(NUM_COLUMNS)); - - Self::from_kvdb(db as Arc<_>).expect("failed to create test-db") - } - - fn from_kvdb(db: Arc) -> ClientResult { - let meta = read_meta::(&*db, columns::META, columns::HEADER)?; - let cache = DbCache::new( - db.clone(), - columns::KEY_LOOKUP, - columns::HEADER, - columns::CACHE, - meta.genesis_hash, - ComplexBlockId::new(meta.finalized_hash, meta.finalized_number), - ); - - Ok(LightStorage { - db, - meta: RwLock::new(meta), - cache: Arc::new(DbCacheSync(RwLock::new(cache))), - header_metadata_cache: HeaderMetadataCache::default(), - }) - } - - #[cfg(test)] - pub(crate) fn cache(&self) -> &DbCacheSync { - &self.cache - } - - fn update_meta( - &self, - hash: Block::Hash, - number: NumberFor, - is_best: bool, - is_finalized: bool, - ) { - let mut meta = self.meta.write(); - - if number.is_zero() { - meta.genesis_hash = hash; - meta.finalized_hash = hash; - } - - if is_best { - meta.best_number = number; - meta.best_hash = hash; - } - - if is_finalized { - meta.finalized_number = number; - meta.finalized_hash = hash; - } - } -} - -impl BlockchainHeaderBackend for LightStorage - where - Block: BlockT, -{ - fn header(&self, id: BlockId) -> ClientResult> { - utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) - } - - fn info(&self) -> BlockchainInfo { - let meta = self.meta.read(); - BlockchainInfo { - best_hash: meta.best_hash, - best_number: meta.best_number, - genesis_hash: meta.genesis_hash, - finalized_hash: meta.finalized_hash, - finalized_number: meta.finalized_number, - } - } - - fn status(&self, id: BlockId) -> ClientResult { - let exists = match id { - BlockId::Hash(_) => read_db( - &*self.db, - columns::KEY_LOOKUP, - columns::HEADER, - id - )?.is_some(), - BlockId::Number(n) => n <= self.meta.read().best_number, - }; - match exists { - true => Ok(BlockStatus::InChain), - false => Ok(BlockStatus::Unknown), - } - } - - 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)?; - Ok(Some(number)) - } else { - Ok(None) - } - } - - fn hash(&self, number: NumberFor) -> ClientResult> { - Ok(self.header(BlockId::Number(number))?.map(|header| header.hash().clone())) - } -} - -impl HeaderMetadata for LightStorage { - type Error = ClientError; - - fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { - self.header_metadata_cache.header_metadata(hash).or_else(|_| { - self.header(BlockId::hash(hash))?.map(|header| { - let header_metadata = CachedHeaderMetadata::from(&header); - self.header_metadata_cache.insert_header_metadata( - header_metadata.hash, - header_metadata.clone(), - ); - header_metadata - }).ok_or(ClientError::UnknownBlock(format!("header not found in db: {}", hash))) - }) - } - - fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { - self.header_metadata_cache.insert_header_metadata(hash, metadata) - } - - fn remove_header_metadata(&self, hash: Block::Hash) { - self.header_metadata_cache.remove_header_metadata(hash); - } -} - -impl LightStorage { - // Get block changes trie root, if available. - fn changes_trie_root(&self, block: BlockId) -> ClientResult> { - self.header(block) - .map(|header| header.and_then(|header| - header.digest().log(DigestItem::as_changes_trie_root) - .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), - ) -> ClientResult<()> { - let lookup_key = utils::number_and_hash_to_lookup_key(best_to.0, &best_to.1)?; - - // handle reorg. - let meta = self.meta.read(); - if meta.best_hash != Default::default() { - let tree_route = header_metadata::tree_route(self, meta.best_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, - ) -> ClientResult<()> { - let meta = self.meta.read(); - if &meta.finalized_hash != header.parent_hash() { - return Err(::client::error::Error::NonSequentialFinalization( - format!("Last finalized {:?} not parent of {:?}", - meta.finalized_hash, hash), - ).into()) - } - - 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 - if let Some(new_cht_number) = cht::is_build_required(cht::size(), *header.number()) { - let new_cht_start: NumberFor = cht::start_number(cht::size(), new_cht_number); - - let mut current_num = new_cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - - let new_header_cht_root = cht::compute_root::( - cht::size(), new_cht_number, cht_range.map(|num| self.hash(num)) - )?; - transaction.put( - columns::CHT, - &cht_key(HEADER_CHT_PREFIX, new_cht_start)?, - new_header_cht_root.as_ref() - ); - - // if the header includes changes trie root, let's build a changes tries roots CHT - if header.digest().log(DigestItem::as_changes_trie_root).is_some() { - let mut current_num = new_cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - let new_changes_trie_cht_root = cht::compute_root::( - cht::size(), new_cht_number, cht_range - .map(|num| self.changes_trie_root(BlockId::Number(num))) - )?; - transaction.put( - columns::CHT, - &cht_key(CHANGES_TRIE_CHT_PREFIX, new_cht_start)?, - new_changes_trie_cht_root.as_ref() - ); - } - - // prune headers that are replaced with CHT - let mut prune_block = new_cht_start; - let new_cht_end = cht::end_number(cht::size(), new_cht_number); - trace!(target: "db", "Replacing blocks [{}..{}] with CHT#{}", - new_cht_start, new_cht_end, new_cht_number); - - while prune_block <= new_cht_end { - 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( - transaction, - columns::KEY_LOOKUP, - prune_block, - hash - )?; - transaction.delete(columns::HEADER, &lookup_key); - } - prune_block += One::one(); - } - } - - Ok(()) - } - - /// Read CHT root of given type for the block. - fn read_cht_root( - &self, - cht_type: u8, - cht_size: NumberFor, - block: NumberFor - ) -> ClientResult { - let no_cht_for_block = || ClientError::Backend(format!("CHT for block {} not exists", block)); - - let cht_number = cht::block_to_cht_number(cht_size, block).ok_or_else(no_cht_for_block)?; - let cht_start = cht::start_number(cht_size, cht_number); - self.db.get(columns::CHT, &cht_key(cht_type, cht_start)?).map_err(db_err)? - .ok_or_else(no_cht_for_block) - .and_then(|hash| Block::Hash::decode(&mut &*hash).map_err(|_| no_cht_for_block())) - } -} - -impl AuxStore for LightStorage - where Block: BlockT, -{ - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> ClientResult<()> { - let mut transaction = DBTransaction::new(); - for (k, v) in insert { - transaction.put(columns::AUX, k, v); - } - for k in delete { - transaction.delete(columns::AUX, k); - } - self.db.write(transaction).map_err(db_err) - } - - fn get_aux(&self, key: &[u8]) -> ClientResult>> { - self.db.get(columns::AUX, key).map(|r| r.map(|v| v.to_vec())).map_err(db_err) - } -} - -impl LightBlockchainStorage for LightStorage - where Block: BlockT, -{ - fn import_header( - &self, - header: Block::Header, - cache_at: HashMap>, - leaf_state: NewBlockState, - aux_ops: Vec<(Vec, Option>)>, - ) -> ClientResult<()> { - let mut transaction = DBTransaction::new(); - - let hash = header.hash(); - let number = *header.number(); - let parent_hash = *header.parent_hash(); - - for (key, maybe_val) in aux_ops { - match maybe_val { - Some(val) => transaction.put_vec(columns::AUX, &key, val), - None => transaction.delete(columns::AUX, &key), - } - } - - // blocks are keyed by number + hash. - let lookup_key = utils::number_and_hash_to_lookup_key(number, &hash)?; - - if leaf_state.is_best() { - self.set_head_with_transaction(&mut transaction, parent_hash, (number, hash))?; - } - - utils::insert_hash_to_key_mapping( - &mut transaction, - columns::KEY_LOOKUP, - number, - hash, - )?; - transaction.put(columns::HEADER, &lookup_key, &header.encode()); - - let header_metadata = CachedHeaderMetadata::from(&header); - self.header_metadata_cache.insert_header_metadata( - header.hash().clone(), - header_metadata, - ); - - let is_genesis = number.is_zero(); - if is_genesis { - self.cache.0.write().set_genesis_hash(hash); - 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, - )?; - } - - { - let mut cache = self.cache.0.write(); - let cache_ops = cache.transaction(&mut transaction) - .on_block_insert( - ComplexBlockId::new(*header.parent_hash(), if number.is_zero() { Zero::zero() } else { number - One::one() }), - ComplexBlockId::new(hash, number), - cache_at, - if finalized { CacheEntryType::Final } else { CacheEntryType::NonFinal }, - )? - .into_ops(); - - debug!("Light DB Commit {:?} ({})", hash, number); - self.db.write(transaction).map_err(db_err)?; - cache.commit(cache_ops); - } - - self.update_meta(hash, number, leaf_state.is_best(), finalized); - - 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)?; - self.update_meta(hash, header.number().clone(), true, false); - Ok(()) - } else { - Err(ClientError::UnknownBlock(format!("Cannot set head {:?}", id))) - } - } - - fn header_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> ClientResult { - self.read_cht_root(HEADER_CHT_PREFIX, cht_size, block) - } - - fn changes_trie_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> ClientResult { - self.read_cht_root(CHANGES_TRIE_CHT_PREFIX, cht_size, block) - } - - fn finalize_header(&self, id: BlockId) -> ClientResult<()> { - if let Some(header) = self.header(id)? { - let mut transaction = DBTransaction::new(); - let hash = header.hash(); - let number = *header.number(); - self.note_finalized(&mut transaction, &header, hash.clone())?; - { - let mut cache = self.cache.0.write(); - let cache_ops = cache.transaction(&mut transaction) - .on_block_finalize( - ComplexBlockId::new(*header.parent_hash(), if number.is_zero() { Zero::zero() } else { number - One::one() }), - ComplexBlockId::new(hash, number) - )? - .into_ops(); - - self.db.write(transaction).map_err(db_err)?; - cache.commit(cache_ops); - } - self.update_meta(hash, header.number().clone(), false, true); - - Ok(()) - } else { - Err(ClientError::UnknownBlock(format!("Cannot finalize block {:?}", id))) - } - } - - fn last_finalized(&self) -> ClientResult { - Ok(self.meta.read().finalized_hash.clone()) - } - - fn cache(&self) -> Option>> { - Some(self.cache.clone()) - } -} - -/// Build the key for inserting header-CHT at given block. -fn cht_key>(cht_type: u8, block: N) -> ClientResult<[u8; 5]> { - let mut key = [cht_type; 5]; - key[1..].copy_from_slice(&utils::number_index_key(block)?); - Ok(key) -} - -#[cfg(test)] -pub(crate) mod tests { - use client::cht; - use sr_primitives::generic::DigestItem; - use sr_primitives::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper}; - use header_metadata::{lowest_common_ancestor, tree_route}; - use super::*; - - type Block = RawBlock>; - type AuthorityId = primitives::ed25519::Public; - - pub fn default_header(parent: &Hash, number: u64) -> Header { - Header { - number: number.into(), - parent_hash: *parent, - state_root: Hash::random(), - digest: Default::default(), - extrinsics_root: Default::default(), - } - } - - fn header_with_changes_trie(parent: &Hash, number: u64) -> Header { - let mut header = default_header(parent, number); - header.digest.logs.push(DigestItem::ChangesTrieRoot([(number % 256) as u8; 32].into())); - header - } - - fn header_with_extrinsics_root(parent: &Hash, number: u64, extrinsics_root: Hash) -> Header { - let mut header = default_header(parent, number); - header.extrinsics_root = extrinsics_root; - header - } - - pub fn insert_block Header>( - db: &LightStorage, - cache: HashMap>, - mut header: F, - ) -> Hash { - let header = header(); - let hash = header.hash(); - db.import_header(header, cache, NewBlockState::Best, Vec::new()).unwrap(); - hash - } - - fn insert_final_block Header>( - db: &LightStorage, - cache: HashMap>, - header: F, - ) -> Hash { - let header = header(); - let hash = header.hash(); - db.import_header(header, cache, NewBlockState::Final, Vec::new()).unwrap(); - hash - } - - fn insert_non_best_block Header>( - db: &LightStorage, - cache: HashMap>, - header: F, - ) -> Hash { - let header = header(); - let hash = header.hash(); - db.import_header(header, cache, NewBlockState::Normal, Vec::new()).unwrap(); - hash - } - - #[test] - fn returns_known_header() { - let db = LightStorage::new_test(); - let known_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - let header_by_hash = db.header(BlockId::Hash(known_hash)).unwrap().unwrap(); - let header_by_number = db.header(BlockId::Number(0)).unwrap().unwrap(); - assert_eq!(header_by_hash, header_by_number); - } - - #[test] - fn does_not_return_unknown_header() { - let db = LightStorage::::new_test(); - assert!(db.header(BlockId::Hash(Hash::from_low_u64_be(1))).unwrap().is_none()); - assert!(db.header(BlockId::Number(0)).unwrap().is_none()); - } - - #[test] - fn returns_info() { - let db = LightStorage::new_test(); - let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - let info = db.info(); - assert_eq!(info.best_hash, genesis_hash); - assert_eq!(info.best_number, 0); - assert_eq!(info.genesis_hash, genesis_hash); - let best_hash = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); - let info = db.info(); - assert_eq!(info.best_hash, best_hash); - assert_eq!(info.best_number, 1); - assert_eq!(info.genesis_hash, genesis_hash); - } - - #[test] - fn returns_block_status() { - let db = LightStorage::new_test(); - let genesis_hash = insert_block(&db, HashMap::new(), || 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(Hash::from_low_u64_be(1))).unwrap(), BlockStatus::Unknown); - assert_eq!(db.status(BlockId::Number(1)).unwrap(), BlockStatus::Unknown); - } - - #[test] - fn returns_block_hash() { - let db = LightStorage::new_test(); - let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!(db.hash(0).unwrap(), Some(genesis_hash)); - assert_eq!(db.hash(1).unwrap(), None); - } - - #[test] - fn import_header_works() { - let db = LightStorage::new_test(); - - let genesis_hash = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!(db.db.iter(columns::HEADER).count(), 1); - assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), 2); - - let _ = insert_block(&db, HashMap::new(), || default_header(&genesis_hash, 1)); - assert_eq!(db.db.iter(columns::HEADER).count(), 2); - assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), 4); - } - - #[test] - fn finalized_ancient_headers_are_replaced_with_cht() { - fn insert_headers Header>(header_producer: F) -> LightStorage { - let db = LightStorage::new_test(); - let cht_size: u64 = cht::size(); - let ucht_size: usize = cht_size as _; - - // insert genesis block header (never pruned) - let mut prev_hash = insert_final_block(&db, HashMap::new(), || header_producer(&Default::default(), 0)); - - // insert SIZE blocks && ensure that nothing is pruned - - for number in 0..cht::size() { - prev_hash = insert_block(&db, HashMap::new(), || header_producer(&prev_hash, 1 + number)); - } - assert_eq!(db.db.iter(columns::HEADER).count(), 1 + ucht_size); - assert_eq!(db.db.iter(columns::CHT).count(), 0); - - // insert next SIZE blocks && ensure that nothing is pruned - for number in 0..(cht_size as _) { - prev_hash = insert_block( - &db, - HashMap::new(), - || header_producer(&prev_hash, 1 + cht_size + number), - ); - } - assert_eq!(db.db.iter(columns::HEADER).count(), 1 + ucht_size + ucht_size); - assert_eq!(db.db.iter(columns::CHT).count(), 0); - - // insert block #{2 * cht::size() + 1} && check that new CHT is created + headers of this CHT are pruned - // nothing is yet finalized, so nothing is pruned. - prev_hash = insert_block( - &db, - HashMap::new(), - || header_producer(&prev_hash, 1 + cht_size + cht_size), - ); - assert_eq!(db.db.iter(columns::HEADER).count(), 2 + ucht_size + ucht_size); - assert_eq!(db.db.iter(columns::CHT).count(), 0); - - // now finalize the block. - for i in (0..(ucht_size + ucht_size)).map(|i| i + 1) { - db.finalize_header(BlockId::Number(i as _)).unwrap(); - } - db.finalize_header(BlockId::Hash(prev_hash)).unwrap(); - db - } - - // when headers are created without changes tries roots - let db = insert_headers(default_header); - let cht_size: u64 = cht::size(); - assert_eq!(db.db.iter(columns::HEADER).count(), (1 + cht_size + 1) as usize); - assert_eq!(db.db.iter(columns::KEY_LOOKUP).count(), (2 * (1 + cht_size + 1)) as usize); - assert_eq!(db.db.iter(columns::CHT).count(), 1); - assert!((0..cht_size as _).all(|i| db.header(BlockId::Number(1 + i)).unwrap().is_none())); - assert!(db.header_cht_root(cht_size, cht_size / 2).is_ok()); - assert!(db.header_cht_root(cht_size, cht_size + cht_size / 2).is_err()); - assert!(db.changes_trie_cht_root(cht_size, cht_size / 2).is_err()); - assert!(db.changes_trie_cht_root(cht_size, cht_size + cht_size / 2).is_err()); - - // when headers are created with changes tries roots - let db = insert_headers(header_with_changes_trie); - assert_eq!(db.db.iter(columns::HEADER).count(), (1 + cht_size + 1) as usize); - assert_eq!(db.db.iter(columns::CHT).count(), 2); - assert!((0..cht_size as _).all(|i| db.header(BlockId::Number(1 + i)).unwrap().is_none())); - assert!(db.header_cht_root(cht_size, cht_size / 2).is_ok()); - assert!(db.header_cht_root(cht_size, cht_size + cht_size / 2).is_err()); - assert!(db.changes_trie_cht_root(cht_size, cht_size / 2).is_ok()); - assert!(db.changes_trie_cht_root(cht_size, cht_size + cht_size / 2).is_err()); - } - - #[test] - fn get_cht_fails_for_genesis_block() { - assert!(LightStorage::::new_test().header_cht_root(cht::size(), 0).is_err()); - } - - #[test] - fn get_cht_fails_for_non_existant_cht() { - let cht_size: u64 = cht::size(); - assert!(LightStorage::::new_test().header_cht_root(cht_size, cht_size / 2).is_err()); - } - - #[test] - fn get_cht_works() { - let db = LightStorage::new_test(); - - // insert 1 + SIZE + SIZE + 1 blocks so that CHT#0 is created - let mut prev_hash = insert_final_block(&db, HashMap::new(), || header_with_changes_trie(&Default::default(), 0)); - let cht_size: u64 = cht::size(); - let ucht_size: usize = cht_size as _; - for i in 1..1 + ucht_size + ucht_size + 1 { - prev_hash = insert_block(&db, HashMap::new(), || header_with_changes_trie(&prev_hash, i as u64)); - db.finalize_header(BlockId::Hash(prev_hash)).unwrap(); - } - - let cht_root_1 = db.header_cht_root(cht_size, cht::start_number(cht_size, 0)).unwrap(); - let cht_root_2 = db.header_cht_root(cht_size, cht::start_number(cht_size, 0) + cht_size / 2).unwrap(); - let cht_root_3 = db.header_cht_root(cht_size, cht::end_number(cht_size, 0)).unwrap(); - assert_eq!(cht_root_1, cht_root_2); - assert_eq!(cht_root_2, cht_root_3); - - let cht_root_1 = db.changes_trie_cht_root(cht_size, cht::start_number(cht_size, 0)).unwrap(); - let cht_root_2 = db.changes_trie_cht_root(cht_size, cht::start_number(cht_size, 0) + cht_size / 2).unwrap(); - let cht_root_3 = db.changes_trie_cht_root(cht_size, cht::end_number(cht_size, 0)).unwrap(); - assert_eq!(cht_root_1, cht_root_2); - assert_eq!(cht_root_2, cht_root_3); - } - - #[test] - fn tree_route_works() { - let db = LightStorage::new_test(); - let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - - // fork from genesis: 3 prong. - let a1 = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); - let a2 = insert_block(&db, HashMap::new(), || default_header(&a1, 2)); - let a3 = insert_block(&db, HashMap::new(), || default_header(&a2, 3)); - - // fork from genesis: 2 prong. - let b1 = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block0, 1, Hash::from([1; 32]))); - let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); - - { - let tree_route = tree_route(&db, a3, b2).unwrap(); - - assert_eq!(tree_route.common_block().hash, block0); - assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2, a1]); - assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![b1, b2]); - } - - { - let tree_route = tree_route(&db, a1, a3).unwrap(); - - assert_eq!(tree_route.common_block().hash, a1); - assert!(tree_route.retracted().is_empty()); - assert_eq!(tree_route.enacted().iter().map(|r| r.hash).collect::>(), vec![a2, a3]); - } - - { - let tree_route = tree_route(&db, a3, a1).unwrap(); - - assert_eq!(tree_route.common_block().hash, a1); - assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2]); - assert!(tree_route.enacted().is_empty()); - } - - { - let tree_route = tree_route(&db, a2, a2).unwrap(); - - assert_eq!(tree_route.common_block().hash, a2); - assert!(tree_route.retracted().is_empty()); - assert!(tree_route.enacted().is_empty()); - } - } - - #[test] - fn lowest_common_ancestor_works() { - let db = LightStorage::new_test(); - let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - - // fork from genesis: 3 prong. - let a1 = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); - let a2 = insert_block(&db, HashMap::new(), || default_header(&a1, 2)); - let a3 = insert_block(&db, HashMap::new(), || default_header(&a2, 3)); - - // fork from genesis: 2 prong. - let b1 = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block0, 1, Hash::from([1; 32]))); - let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); - - { - let lca = lowest_common_ancestor(&db, a3, b2).unwrap(); - - assert_eq!(lca.hash, block0); - assert_eq!(lca.number, 0); - } - - { - let lca = lowest_common_ancestor(&db, a1, a3).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(&db, a3, a1).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(&db, a2, a3).unwrap(); - - assert_eq!(lca.hash, a2); - assert_eq!(lca.number, 2); - } - - { - let lca = lowest_common_ancestor(&db, a2, a1).unwrap(); - - assert_eq!(lca.hash, a1); - assert_eq!(lca.number, 1); - } - - { - let lca = lowest_common_ancestor(&db, a2, a2).unwrap(); - - assert_eq!(lca.hash, a2); - assert_eq!(lca.number, 2); - } - } - - #[test] - fn authorities_are_cached() { - let db = LightStorage::new_test(); - - fn run_checks(db: &LightStorage, max: u64, checks: &[(u64, Option>)]) { - for (at, expected) in checks.iter().take_while(|(at, _)| *at <= max) { - let actual = get_authorities(db.cache(), BlockId::Number(*at)); - assert_eq!(*expected, actual); - } - } - - fn same_authorities() -> HashMap> { - HashMap::new() - } - - fn make_authorities(authorities: Vec) -> HashMap> { - let mut map = HashMap::new(); - map.insert(well_known_cache_keys::AUTHORITIES, authorities.encode()); - map - } - - fn get_authorities(cache: &dyn BlockchainCache, at: BlockId) -> Option> { - cache.get_at(&well_known_cache_keys::AUTHORITIES, &at) - .and_then(|(_, _, val)| Decode::decode(&mut &val[..]).ok()) - } - - let auth1 = || AuthorityId::from_raw([1u8; 32]); - let auth2 = || AuthorityId::from_raw([2u8; 32]); - let auth3 = || AuthorityId::from_raw([3u8; 32]); - let auth4 = || AuthorityId::from_raw([4u8; 32]); - let auth5 = || AuthorityId::from_raw([5u8; 32]); - let auth6 = || AuthorityId::from_raw([6u8; 32]); - - let (hash2, hash6) = { - // first few blocks are instantly finalized - // B0(None) -> B1(None) -> B2(1) -> B3(1) -> B4(1, 2) -> B5(1, 2) -> B6(1, 2) - let checks = vec![ - (0, None), - (1, None), - (2, Some(vec![auth1()])), - (3, Some(vec![auth1()])), - (4, Some(vec![auth1(), auth2()])), - (5, Some(vec![auth1(), auth2()])), - (6, Some(vec![auth1(), auth2()])), - ]; - - let hash0 = insert_final_block(&db, same_authorities(), || default_header(&Default::default(), 0)); - run_checks(&db, 0, &checks); - let hash1 = insert_final_block(&db, same_authorities(), || default_header(&hash0, 1)); - run_checks(&db, 1, &checks); - let hash2 = insert_final_block(&db, make_authorities(vec![auth1()]), || default_header(&hash1, 2)); - run_checks(&db, 2, &checks); - let hash3 = insert_final_block(&db, make_authorities(vec![auth1()]), || default_header(&hash2, 3)); - run_checks(&db, 3, &checks); - let hash4 = insert_final_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash3, 4)); - run_checks(&db, 4, &checks); - let hash5 = insert_final_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash4, 5)); - run_checks(&db, 5, &checks); - let hash6 = insert_final_block(&db, same_authorities(), || default_header(&hash5, 6)); - run_checks(&db, 6, &checks); - - (hash2, hash6) - }; - - { - // 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, make_authorities(vec![auth1()]), || default_header(&hash2, 3)); - assert_eq!(None, get_authorities(db.cache(), BlockId::Hash(hash2_1))); - let hash2_2 = insert_non_best_block(&db, make_authorities(vec![auth1(), auth2()]), || default_header(&hash2_1, 4)); - assert_eq!(None, get_authorities(db.cache(), BlockId::Hash(hash2_2))); - } - - let (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) = { - // inserting non-finalized blocks - // B6(None) -> B7(3) -> B8(3) - // \> B6_1(4) -> B6_2(4) - // \> B6_1_1(5) - // \> B6_1_2(6) -> B6_1_3(7) - - let hash7 = insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash6, 7)); - assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), - Some(vec![auth1(), auth2()]), - ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - let hash8 = insert_block(&db, make_authorities(vec![auth3()]), || default_header(&hash7, 8)); - assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), - Some(vec![auth1(), auth2()]), - ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - let hash6_1 = insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6, 7)); - assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), - Some(vec![auth1(), auth2()]), - ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - let hash6_1_1 = insert_non_best_block(&db, make_authorities(vec![auth5()]), || default_header(&hash6_1, 8)); - assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), - Some(vec![auth1(), auth2()]), - ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - let hash6_1_2 = insert_non_best_block(&db, make_authorities(vec![auth6()]), || default_header(&hash6_1, 8)); - assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), - Some(vec![auth1(), auth2()]), - ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); - let hash6_2 = insert_block(&db, make_authorities(vec![auth4()]), || default_header(&hash6_1, 8)); - assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), - Some(vec![auth1(), auth2()]), - ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), Some(vec![auth3()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); - - (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) - }; - - { - // finalize block hash6_1 - db.finalize_header(BlockId::Hash(hash6_1)).unwrap(); - assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), - Some(vec![auth1(), auth2()]), - ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), Some(vec![auth5()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), Some(vec![auth6()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); - // finalize block hash6_2 - db.finalize_header(BlockId::Hash(hash6_2)).unwrap(); - assert_eq!( - get_authorities(db.cache(), BlockId::Hash(hash6)), - Some(vec![auth1(), auth2()]), - ); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash7)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash8)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1)), Some(vec![auth4()])); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_1)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_1_2)), None); - assert_eq!(get_authorities(db.cache(), BlockId::Hash(hash6_2)), Some(vec![auth4()])); - } - } - - #[test] - fn database_is_reopened() { - let db = LightStorage::new_test(); - let hash0 = insert_final_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); - assert_eq!(db.info().best_hash, hash0); - assert_eq!(db.header(BlockId::Hash(hash0)).unwrap().unwrap().hash(), hash0); - - let db = db.db; - let db = LightStorage::from_kvdb(db).unwrap(); - assert_eq!(db.info().best_hash, hash0); - assert_eq!(db.header(BlockId::Hash::(hash0)).unwrap().unwrap().hash(), hash0); - } - - #[test] - fn aux_store_works() { - let db = LightStorage::::new_test(); - - // insert aux1 + aux2 using direct store access - db.insert_aux(&[(&[1][..], &[101][..]), (&[2][..], &[102][..])], ::std::iter::empty()).unwrap(); - - // check aux values - assert_eq!(db.get_aux(&[1]).unwrap(), Some(vec![101])); - assert_eq!(db.get_aux(&[2]).unwrap(), Some(vec![102])); - assert_eq!(db.get_aux(&[3]).unwrap(), None); - - // delete aux1 + insert aux3 using import operation - db.import_header(default_header(&Default::default(), 0), HashMap::new(), NewBlockState::Best, vec![ - (vec![3], Some(vec![103])), - (vec![1], None), - ]).unwrap(); - - // check aux values - assert_eq!(db.get_aux(&[1]).unwrap(), None); - assert_eq!(db.get_aux(&[2]).unwrap(), Some(vec![102])); - assert_eq!(db.get_aux(&[3]).unwrap(), Some(vec![103])); - } - - #[test] - fn cache_can_be_initialized_after_genesis_inserted() { - let (genesis_hash, storage) = { - let db = LightStorage::::new_test(); - - // before cache is initialized => None - assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), None); - - // insert genesis block (no value for cache is provided) - let mut genesis_hash = None; - insert_block(&db, HashMap::new(), || { - let header = default_header(&Default::default(), 0); - genesis_hash = Some(header.hash()); - header - }); - - // after genesis is inserted => None - assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), None); - - // initialize cache - db.cache().initialize(b"test", vec![42]).unwrap(); - - // after genesis is inserted + cache is initialized => Some - assert_eq!( - db.cache().get_at(b"test", &BlockId::Number(0)), - Some(((0, genesis_hash.unwrap()), None, vec![42])), - ); - - (genesis_hash, db.db) - }; - - // restart && check that after restart value is read from the cache - let db = LightStorage::::from_kvdb(storage as Arc<_>).expect("failed to create test-db"); - assert_eq!( - db.cache().get_at(b"test", &BlockId::Number(0)), - Some(((0, genesis_hash.unwrap()), None, vec![42])), - ); - } -} diff --git a/core/client/db/src/offchain.rs b/core/client/db/src/offchain.rs deleted file mode 100644 index 0640fb6c29bd6..0000000000000 --- a/core/client/db/src/offchain.rs +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! RocksDB-based offchain workers local storage. - -use std::{ - collections::HashMap, - sync::Arc, -}; - -use crate::columns; -use kvdb::KeyValueDB; -use parking_lot::Mutex; - -/// Offchain local storage -#[derive(Clone)] -pub struct LocalStorage { - db: Arc, - locks: Arc, Arc>>>>, -} - -impl std::fmt::Debug for LocalStorage { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - fmt.debug_struct("LocalStorage") - .finish() - } -} - -impl LocalStorage { - /// Create new offchain storage for tests (backed by memorydb) - #[cfg(any(test, feature = "test-helpers"))] - pub fn new_test() -> Self { - let db = Arc::new(::kvdb_memorydb::create(crate::utils::NUM_COLUMNS)); - Self::new(db as _) - } - - /// Create offchain local storage with given `KeyValueDB` backend. - pub fn new(db: Arc) -> Self { - Self { - db, - locks: Default::default(), - } - } -} - -impl client::backend::OffchainStorage for LocalStorage { - fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { - let key: Vec = prefix.iter().chain(key).cloned().collect(); - let mut tx = self.db.transaction(); - tx.put(columns::OFFCHAIN, &key, value); - - if let Err(e) = self.db.write(tx) { - log::warn!("Error writing to the offchain DB: {:?}", e); - } - } - - fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { - let key: Vec = prefix.iter().chain(key).cloned().collect(); - self.db.get(columns::OFFCHAIN, &key) - .ok() - .and_then(|x| x) - .map(|v| v.to_vec()) - } - - fn compare_and_set( - &mut self, - prefix: &[u8], - item_key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - let key: Vec = prefix.iter().chain(item_key).cloned().collect(); - let key_lock = { - let mut locks = self.locks.lock(); - locks.entry(key.clone()).or_default().clone() - }; - - let is_set; - { - let _key_guard = key_lock.lock(); - let val = self.db.get(columns::OFFCHAIN, &key) - .ok() - .and_then(|x| x); - is_set = val.as_ref().map(|x| &**x) == old_value; - - if is_set { - self.set(prefix, item_key, new_value) - } - } - - // clean the lock map if we're the only entry - let mut locks = self.locks.lock(); - { - drop(key_lock); - let key_lock = locks.get_mut(&key); - if let Some(_) = key_lock.and_then(Arc::get_mut) { - locks.remove(&key); - } - } - is_set - } -} - -#[cfg(test)] -mod tests { - use super::*; - use client::backend::OffchainStorage; - - #[test] - fn should_compare_and_set_and_clear_the_locks_map() { - let mut storage = LocalStorage::new_test(); - let prefix = b"prefix"; - let key = b"key"; - let value = b"value"; - - storage.set(prefix, key, value); - assert_eq!(storage.get(prefix, key), Some(value.to_vec())); - - assert_eq!(storage.compare_and_set(prefix, key, Some(value), b"asd"), true); - assert_eq!(storage.get(prefix, key), Some(b"asd".to_vec())); - assert!(storage.locks.lock().is_empty(), "Locks map should be empty!"); - } - - #[test] - fn should_compare_and_set_on_empty_field() { - let mut storage = LocalStorage::new_test(); - let prefix = b"prefix"; - let key = b"key"; - - assert_eq!(storage.compare_and_set(prefix, key, None, b"asd"), true); - assert_eq!(storage.get(prefix, key), Some(b"asd".to_vec())); - assert!(storage.locks.lock().is_empty(), "Locks map should be empty!"); - } - -} diff --git a/core/client/db/src/storage_cache.rs b/core/client/db/src/storage_cache.rs deleted file mode 100644 index af8c9e379c4c1..0000000000000 --- a/core/client/db/src/storage_cache.rs +++ /dev/null @@ -1,731 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Global cache state. - -use std::collections::{VecDeque, HashSet, HashMap}; -use std::sync::Arc; -use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; -use linked_hash_map::{LinkedHashMap, Entry}; -use hash_db::Hasher; -use sr_primitives::traits::{Block as BlockT, Header}; -use state_machine::{backend::Backend as StateBackend, TrieBackend}; -use log::trace; -use super::{StorageCollection, ChildStorageCollection}; -use std::hash::Hash as StdHash; -const STATE_CACHE_BLOCKS: usize = 12; - -type StorageKey = Vec; -type ChildStorageKey = (Vec, Vec); -type StorageValue = Vec; - -/// Shared canonical state cache. -pub struct Cache { - /// Storage cache. `None` indicates that key is known to be missing. - lru_storage: LRUMap>, - /// Storage hashes cache. `None` indicates that key is known to be missing. - lru_hashes: LRUMap>, - /// Storage cache for child trie. `None` indicates that key is known to be missing. - lru_child_storage: LRUMap>, - /// Information on the modifications in recently committed blocks; specifically which keys - /// changed in which block. Ordered by block number. - modifications: VecDeque>, -} - -struct LRUMap(LinkedHashMap, usize, usize); - -/// Internal trait similar to `heapsize` but using -/// a simply estimation. -/// -/// This should not be made public, it is implementation -/// detail trait. If it need to become public please -/// consider using `malloc_size_of`. -trait EstimateSize { - /// Return a size estimation of additional size needed - /// to cache this struct (in bytes). - fn estimate_size(&self) -> usize; -} - -impl EstimateSize for Vec { - fn estimate_size(&self) -> usize { - self.capacity() - } -} - -impl EstimateSize for Option> { - fn estimate_size(&self) -> usize { - self.as_ref().map(|v|v.capacity()).unwrap_or(0) - } -} - -struct OptionHOut>(Option); - -impl> EstimateSize for OptionHOut { - fn estimate_size(&self) -> usize { - // capacity would be better - self.0.as_ref().map(|v|v.as_ref().len()).unwrap_or(0) - } -} - -impl EstimateSize for (T, T) { - fn estimate_size(&self) -> usize { - self.0.estimate_size() + self.1.estimate_size() - } -} - -impl LRUMap { - fn remove(&mut self, k: &K) { - let map = &mut self.0; - let storage_used_size = &mut self.1; - if let Some(v) = map.remove(k) { - *storage_used_size -= k.estimate_size(); - *storage_used_size -= v.estimate_size(); - } - } - - fn add(&mut self, k: K, v: V) { - let lmap = &mut self.0; - let storage_used_size = &mut self.1; - let limit = self.2; - let klen = k.estimate_size(); - *storage_used_size += v.estimate_size(); - // TODO assert k v size fit into limit?? to avoid insert remove? - match lmap.entry(k) { - Entry::Occupied(mut entry) => { - // note that in this case we are not running pure lru as - // it would require to remove first - *storage_used_size -= entry.get().estimate_size(); - entry.insert(v); - }, - Entry::Vacant(entry) => { - *storage_used_size += klen; - entry.insert(v); - }, - }; - - while *storage_used_size > limit { - if let Some((k,v)) = lmap.pop_front() { - *storage_used_size -= k.estimate_size(); - *storage_used_size -= v.estimate_size(); - } else { - // can happen fairly often as we get value from multiple lru - // and only remove from a single lru - break; - } - } - } - - fn get(&mut self, k: &Q) -> Option<&mut V> - where K: std::borrow::Borrow, - Q: StdHash + Eq { - self.0.get_refresh(k) - } - - fn used_size(&self) -> usize { - self.1 - } - fn clear(&mut self) { - self.0.clear(); - self.1 = 0; - } - -} - -impl Cache { - /// Returns the used memory size of the storage cache in bytes. - pub fn used_storage_cache_size(&self) -> usize { - self.lru_storage.used_size() - + self.lru_child_storage.used_size() - // ignore small hashes storage and self.lru_hashes.used_size() - } - - /// Synchronize the shared cache with the best block state. - /// This function updates the shared cache by removing entries - /// that are invalidated by chain reorganization. It should be - /// be called when chain reorg happens without importing a new block. - pub fn sync(&mut self, enacted: &[B::Hash], retracted: &[B::Hash]) { - trace!("Syncing shared cache, enacted = {:?}, retracted = {:?}", enacted, retracted); - - // Purge changes from re-enacted and retracted blocks. - // Filter out commiting block if any. - let mut clear = false; - for block in enacted { - clear = clear || { - if let Some(ref mut m) = self.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); - self.lru_storage.remove(a); - } - for a in &m.child_storage { - trace!("Reverting enacted child key {:?}", a); - self.lru_child_storage.remove(a); - } - false - } else { - true - } - }; - } - - for block in retracted { - clear = clear || { - if let Some(ref mut m) = self.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); - self.lru_storage.remove(a); - } - for a in &m.child_storage { - trace!("Retracted child key {:?}", a); - self.lru_child_storage.remove(a); - } - false - } else { - true - } - }; - } - if clear { - // We don't know anything about the block; clear everything - trace!("Wiping cache"); - self.lru_storage.clear(); - self.lru_child_storage.clear(); - self.lru_hashes.clear(); - self.modifications.clear(); - } - } -} - -pub type SharedCache = Arc>>; - -/// Fix lru storage size for hash (small 64ko). -const FIX_LRU_HASH_SIZE: usize = 65_536; - -/// Create a new shared cache instance with given max memory usage. -pub fn new_shared_cache( - shared_cache_size: usize, - child_ratio: (usize, usize), -) -> SharedCache { - let top = child_ratio.1.saturating_sub(child_ratio.0); - Arc::new(Mutex::new(Cache { - lru_storage: LRUMap(LinkedHashMap::new(), 0, - shared_cache_size * top / child_ratio.1), - lru_hashes: LRUMap(LinkedHashMap::new(), 0, FIX_LRU_HASH_SIZE), - lru_child_storage: LRUMap(LinkedHashMap::new(), 0, - shared_cache_size * child_ratio.0 / child_ratio.1), - 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, - /// A set of modified child storage keys. - child_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>, - /// Child storage cache. `None` indicates that key is known to be missing. - child_storage: HashMap>, -} - -/// Cache changes. -pub struct CacheChanges { - /// 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, -} - -/// 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: BlockT> { - /// Backing state. - state: S, - /// Cache data. - pub cache: CacheChanges -} - -impl, B: BlockT> std::fmt::Debug for CachingState { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Block {:?}", self.cache.parent_hash) - } -} - -impl CacheChanges { - /// Propagate local cache into the shared cache and synchronize - /// the shared cache with the best block state. - /// 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: StorageCollection, - child_changes: ChildStorageCollection, - 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; - let enacted: Vec<_> = enacted - .iter() - .filter(|h| commit_hash.as_ref().map_or(true, |p| *h != p)) - .cloned() - .collect(); - cache.sync(&enacted, retracted); - // 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 root entries, {} modified child entries", - local_cache.storage.len(), - local_cache.hashes.len(), - changes.len(), - child_changes.iter().map(|v|v.1.len()).sum::(), - ); - for (k, v) in local_cache.storage.drain() { - cache.lru_storage.add(k, v); - } - for (k, v) in local_cache.child_storage.drain() { - cache.lru_child_storage.add(k, v); - } - for (k, v) in local_cache.hashes.drain() { - cache.lru_hashes.add(k, OptionHOut(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(); - let mut child_modifications = HashSet::new(); - child_changes.into_iter().for_each(|(sk, changes)| - for (k, v) in changes.into_iter() { - let k = (sk.clone(), k); - if is_best { - cache.lru_child_storage.add(k.clone(), v); - } - child_modifications.insert(k); - } - ); - for (k, v) in changes.into_iter() { - if is_best { - cache.lru_hashes.remove(&k); - cache.lru_storage.add(k.clone(), v); - } - modifications.insert(k); - } - - // Save modified storage. These are ordered by the block number. - let block_changes = BlockChanges { - storage: modifications, - child_storage: child_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); - } - } - } - -} - -impl, B: BlockT> 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, - cache: CacheChanges { - shared_cache, - local_cache: RwLock::new(LocalCache { - storage: Default::default(), - hashes: Default::default(), - child_storage: Default::default(), - }), - parent_hash: parent_hash, - }, - } - } - - /// 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: Option<&[u8]>, - child_key: Option<&ChildStorageKey>, - 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 let Some(key) = key { - if m.storage.contains(key) { - trace!("Cache lookup skipped for {:?}: modified in a later block", key); - return false; - } - } - if let Some(child_key) = child_key { - if m.child_storage.contains(child_key) { - trace!("Cache lookup skipped for {:?}: modified in a later block", child_key); - return false; - } - } - } - trace!("Cache lookup skipped for {:?}: parent hash is unknown", key); - false - } - - /// Dispose state and return cache data. - pub fn release(self) -> CacheChanges { - self.cache - } -} - -impl, B: BlockT> 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.cache.local_cache.upgradable_read(); - // Note that local cache makes that lru is not refreshed - if let Some(entry) = local_cache.storage.get(key).cloned() { - trace!("Found in local cache: {:?}", key); - return Ok(entry) - } - let mut cache = self.cache.shared_cache.lock(); - if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) { - if let Some(entry) = cache.lru_storage.get(key).map(|a| a.clone()) { - trace!("Found in shared cache: {:?}", key); - 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.cache.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.cache.shared_cache.lock(); - if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) { - if let Some(entry) = cache.lru_hashes.get(key).map(|a| a.0.clone()) { - trace!("Found hash in shared cache: {:?}", key); - 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> { - let key = (storage_key.to_vec(), key.to_vec()); - let local_cache = self.cache.local_cache.upgradable_read(); - if let Some(entry) = local_cache.child_storage.get(&key).cloned() { - trace!("Found in local cache: {:?}", key); - return Ok(entry) - } - let mut cache = self.cache.shared_cache.lock(); - if Self::is_allowed(None, Some(&key), &self.cache.parent_hash, &cache.modifications) { - if let Some(entry) = cache.lru_child_storage.get(&key).map(|a| a.clone()) { - trace!("Found in shared cache: {:?}", key); - return Ok(entry) - } - } - trace!("Cache miss: {:?}", key); - let value = self.state.child_storage(storage_key, &key.1[..])?; - RwLockUpgradableReadGuard::upgrade(local_cache).child_storage.insert(key, value.clone()); - Ok(value) - } - - 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_key_values_with_prefix(&self, prefix: &[u8], f: F) { - self.state.for_key_values_with_prefix(prefix, f) - } - - fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { - self.state.for_keys_in_child_storage(storage_key, f) - } - - fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { - self.state.for_child_keys_with_prefix(storage_key, prefix, f) - } - - fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) - where - I: IntoIterator, Option>)>, - H::Out: Ord - { - self.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: &[u8]) -> Vec> { - self.state.keys(prefix) - } - - fn child_keys(&self, child_key: &[u8], prefix: &[u8]) -> Vec> { - self.state.child_keys(child_key, prefix) - } - - fn as_trie_backend(&mut self) -> Option<&TrieBackend> { - self.state.as_trie_backend() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sr_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, (0,1)); - - // 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.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![2]))], vec![], Some(h0.clone()), Some(0), || true); - - let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h0.clone())); - s.cache.sync_cache(&[], &[], vec![], vec![], Some(h1a.clone()), Some(1), || true); - - let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h0.clone())); - s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![3]))], vec![], Some(h1b.clone()), Some(1), || false); - - let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h1b.clone())); - s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![4]))], vec![], Some(h2b.clone()), Some(2), || false); - - let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h1a.clone())); - s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![5]))], vec![], Some(h2a.clone()), Some(2), || true); - - let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h2a.clone())); - s.cache.sync_cache(&[], &[], vec![], 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.cache.sync_cache( - &[h1b.clone(), h2b.clone(), h3b.clone()], - &[h1a.clone(), h2a.clone(), h3a.clone()], - vec![], - 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()); - } - - #[test] - fn should_track_used_size_correctly() { - let root_parent = H256::random(); - let shared = new_shared_cache::(109, ((109-36), 109)); - let h0 = H256::random(); - - let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(root_parent.clone())); - - let key = H256::random()[..].to_vec(); - let s_key = H256::random()[..].to_vec(); - s.cache.sync_cache( - &[], - &[], - vec![(key.clone(), Some(vec![1, 2, 3]))], - vec![], - Some(h0.clone()), - Some(0), - || true, - ); - // 32 key, 3 byte size - assert_eq!(shared.lock().used_storage_cache_size(), 35 /* bytes */); - - let key = H256::random()[..].to_vec(); - s.cache.sync_cache( - &[], - &[], - vec![], - vec![(s_key.clone(), vec![(key.clone(), Some(vec![1, 2]))])], - Some(h0.clone()), - Some(0), - || true, - ); - // 35 + (2 * 32) key, 2 byte size - assert_eq!(shared.lock().used_storage_cache_size(), 101 /* bytes */); - } - - #[test] - fn should_remove_lru_items_based_on_tracking_used_size() { - let root_parent = H256::random(); - let shared = new_shared_cache::(36*3, (2,3)); - let h0 = H256::random(); - - let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(root_parent.clone())); - - let key = H256::random()[..].to_vec(); - s.cache.sync_cache( - &[], - &[], - vec![(key.clone(), Some(vec![1, 2, 3, 4]))], - vec![], - Some(h0.clone()), - Some(0), - || true, - ); - // 32 key, 4 byte size - assert_eq!(shared.lock().used_storage_cache_size(), 36 /* bytes */); - - let key = H256::random()[..].to_vec(); - s.cache.sync_cache( - &[], - &[], - vec![(key.clone(), Some(vec![1, 2]))], - vec![], - Some(h0.clone()), - Some(0), - || true, - ); - // 32 key, 2 byte size - assert_eq!(shared.lock().used_storage_cache_size(), 34 /* bytes */); - } -} diff --git a/core/client/db/src/utils.rs b/core/client/db/src/utils.rs deleted file mode 100644 index 70f0ff20588bc..0000000000000 --- a/core/client/db/src/utils.rs +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Db-based backend utility structures and functions, used by both -//! full and light storages. - -#[cfg(feature = "kvdb-rocksdb")] -use std::sync::Arc; -use std::{io, convert::TryInto}; - -use kvdb::{KeyValueDB, DBTransaction}; -#[cfg(feature = "kvdb-rocksdb")] -use kvdb_rocksdb::{Database, DatabaseConfig}; -use log::debug; - -use client; -use codec::Decode; -use trie::DBValue; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ - Block as BlockT, Header as HeaderT, Zero, - UniqueSaturatedFrom, UniqueSaturatedInto, -}; -#[cfg(feature = "kvdb-rocksdb")] -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. -pub const NUM_COLUMNS: u32 = 10; -/// Meta column. The set of keys in the column is shared by full && light storages. -pub const COLUMN_META: Option = Some(0); - -/// Keys of entries in COLUMN_META. -pub mod meta_keys { - /// Type of storage (full or light). - pub const TYPE: &[u8; 4] = b"type"; - /// Best block key. - pub const BEST_BLOCK: &[u8; 4] = b"best"; - /// Last finalized block key. - pub const FINALIZED_BLOCK: &[u8; 5] = b"final"; - /// Meta information prefix for list-based caches. - pub const CACHE_META_PREFIX: &[u8; 5] = b"cache"; - /// Genesis block hash. - 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. -#[derive(Debug)] -pub struct Meta { - /// Hash of the best known block. - pub best_hash: H, - /// Number of the best known block. - pub best_number: N, - /// Hash of the best finalized block. - pub finalized_hash: H, - /// Number of the best finalized block. - pub finalized_number: N, - /// Hash of the genesis block. - pub genesis_hash: H, -} - -/// A block lookup key: used for canonical lookup from block number to hash -pub type NumberIndexKey = [u8; 4]; - -/// Convert block number into short lookup key (LE representation) for -/// blocks that are in the canonical chain. -/// -/// In the current database schema, this kind of key is only used for -/// lookups into an index, NOT for storing header data or others. -pub fn number_index_key>(n: N) -> client::error::Result { - let n = n.try_into().map_err(|_| - client::error::Error::Backend("Block number cannot be converted to u32".into()) - )?; - - Ok([ - (n >> 24) as u8, - ((n >> 16) & 0xff) as u8, - ((n >> 8) & 0xff) as u8, - (n & 0xff) as u8 - ]) -} - -/// Convert number and hash into long lookup key for blocks that are -/// not in the canonical chain. -pub fn number_and_hash_to_lookup_key( - number: N, - hash: H, -) -> client::error::Result> where - N: TryInto, - H: AsRef<[u8]>, -{ - let mut lookup_key = number_index_key(number)?.to_vec(); - lookup_key.extend_from_slice(hash.as_ref()); - Ok(lookup_key) -} - -/// Convert block lookup key into block number. -/// all block lookup keys start with the block number. -pub fn lookup_key_to_number(key: &[u8]) -> client::error::Result where - N: From -{ - if key.len() < 4 { - return Err(client::error::Error::Backend("Invalid block key".into())); - } - Ok((key[0] as u32) << 24 - | (key[1] as u32) << 16 - | (key[2] as u32) << 8 - | (key[3] as u32)).map(Into::into) -} - -/// Delete number to hash mapping in DB transaction. -pub fn remove_number_to_key_mapping>( - transaction: &mut DBTransaction, - key_lookup_col: Option, - number: N, -) -> client::error::Result<()> { - transaction.delete(key_lookup_col, number_index_key(number)?.as_ref()); - Ok(()) -} - -/// Remove key mappings. -pub fn remove_key_mappings, H: AsRef<[u8]>>( - transaction: &mut DBTransaction, - key_lookup_col: Option, - number: N, - hash: H, -) -> client::error::Result<()> { - remove_number_to_key_mapping(transaction, key_lookup_col, number)?; - transaction.delete(key_lookup_col, hash.as_ref()); - Ok(()) -} - -/// Place a number mapping into the database. This maps number to current perceived -/// block hash at that position. -pub fn insert_number_to_key_mapping + Clone, H: AsRef<[u8]>>( - transaction: &mut DBTransaction, - key_lookup_col: Option, - number: N, - hash: H, -) -> client::error::Result<()> { - transaction.put_vec( - key_lookup_col, - number_index_key(number.clone())?.as_ref(), - number_and_hash_to_lookup_key(number, hash)?, - ); - Ok(()) -} - -/// Insert a hash to key mapping in the database. -pub fn insert_hash_to_key_mapping, H: AsRef<[u8]> + Clone>( - transaction: &mut DBTransaction, - key_lookup_col: Option, - number: N, - hash: H, -) -> client::error::Result<()> { - transaction.put_vec( - key_lookup_col, - hash.clone().as_ref(), - number_and_hash_to_lookup_key(number, hash)?, - ); - Ok(()) -} - -/// Convert block id to block lookup key. -/// block lookup key is the DB-key header, block and justification are stored under. -/// looks up lookup key by hash from DB as necessary. -pub fn block_id_to_lookup_key( - db: &dyn KeyValueDB, - key_lookup_col: Option, - id: BlockId -) -> Result>, client::error::Error> where - Block: BlockT, - ::sr_primitives::traits::NumberFor: UniqueSaturatedFrom + UniqueSaturatedInto, -{ - let res = match id { - BlockId::Number(n) => db.get( - key_lookup_col, - number_index_key(n)?.as_ref(), - ), - BlockId::Hash(h) => db.get(key_lookup_col, h.as_ref()), - }; - - res.map(|v| v.map(|v| v.into_vec())).map_err(db_err) -} - -/// Maps database error to client error -pub fn db_err(err: io::Error) -> client::error::Error { - client::error::Error::Backend(format!("{}", err)) -} - -/// Open RocksDB database. -#[cfg(feature = "kvdb-rocksdb")] -pub fn open_database( - config: &DatabaseSettings, - col_meta: Option, - db_type: &str -) -> client::error::Result> { - let mut db_config = DatabaseConfig::with_columns(Some(NUM_COLUMNS)); - db_config.memory_budget = config.cache_size; - let path = config.path.to_str().ok_or_else(|| client::error::Error::Backend("Invalid database path".into()))?; - let db = Database::open(&db_config, &path).map_err(db_err)?; - - // check database type - match db.get(col_meta, meta_keys::TYPE).map_err(db_err)? { - Some(stored_type) => { - if db_type.as_bytes() != &*stored_type { - return Err(client::error::Error::Backend( - format!("Unexpected database type. Expected: {}", db_type)).into()); - } - }, - None => { - let mut transaction = DBTransaction::new(); - transaction.put(col_meta, meta_keys::TYPE, db_type.as_bytes()); - db.write(transaction).map_err(db_err)?; - }, - } - - Ok(Arc::new(db)) -} - -/// Read database column entry for the given block. -pub fn read_db( - db: &dyn KeyValueDB, - col_index: Option, - col: Option, - id: BlockId -) -> client::error::Result> - where - Block: BlockT, -{ - block_id_to_lookup_key(db, col_index, id).and_then(|key| match key { - Some(key) => db.get(col, key.as_ref()).map_err(db_err), - None => Ok(None), - }) -} - -/// Read a header from the database. -pub fn read_header( - db: &dyn KeyValueDB, - col_index: Option, - col: Option, - id: BlockId, -) -> client::error::Result> { - match read_db(db, col_index, col, id)? { - Some(header) => match Block::Header::decode(&mut &header[..]) { - Ok(header) => Ok(Some(header)), - Err(_) => return Err( - client::error::Error::Backend("Error decoding header".into()) - ), - } - None => Ok(None), - } -} - -/// Required header from the database. -pub fn require_header( - db: &dyn KeyValueDB, - col_index: Option, - col: Option, - id: BlockId, -) -> client::error::Result { - read_header(db, col_index, col, id) - .and_then(|header| header.ok_or_else(|| client::error::Error::UnknownBlock(format!("{}", id)))) -} - -/// Read meta from the database. -pub fn read_meta(db: &dyn KeyValueDB, col_meta: Option, col_header: Option) -> Result< - Meta<<::Header as HeaderT>::Number, Block::Hash>, - client::error::Error, -> - where - Block: BlockT, -{ - let genesis_hash: Block::Hash = match db.get(col_meta, meta_keys::GENESIS_HASH).map_err(db_err)? { - Some(h) => match Decode::decode(&mut &h[..]) { - Ok(h) => h, - Err(err) => return Err(client::error::Error::Backend( - format!("Error decoding genesis hash: {}", err) - )), - }, - None => return Ok(Meta { - best_hash: Default::default(), - best_number: Zero::zero(), - finalized_hash: Default::default(), - finalized_number: Zero::zero(), - genesis_hash: Default::default(), - }), - }; - - let load_meta_block = |desc, key| -> Result<_, client::error::Error> { - if let Some(Some(header)) = db.get(col_meta, key).and_then(|id| - match id { - Some(id) => db.get(col_header, &id).map(|h| h.map(|b| Block::Header::decode(&mut &b[..]).ok())), - None => Ok(None), - }).map_err(db_err)? - { - let hash = header.hash(); - debug!("DB Opened blockchain db, fetched {} = {:?} ({})", desc, hash, header.number()); - Ok((hash, *header.number())) - } else { - Ok((genesis_hash.clone(), Zero::zero())) - } - }; - - let (best_hash, best_number) = load_meta_block("best", meta_keys::BEST_BLOCK)?; - let (finalized_hash, finalized_number) = load_meta_block("final", meta_keys::FINALIZED_BLOCK)?; - - Ok(Meta { - best_hash, - best_number, - finalized_hash, - finalized_number, - genesis_hash, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use sr_primitives::testing::{Block as RawBlock, ExtrinsicWrapper}; - type Block = RawBlock>; - - #[test] - fn number_index_key_doesnt_panic() { - let id = BlockId::::Number(72340207214430721); - match id { - BlockId::Number(n) => number_index_key(n).expect_err("number should overflow u32"), - _ => unreachable!(), - }; - } -} diff --git a/core/client/header-metadata/Cargo.toml b/core/client/header-metadata/Cargo.toml deleted file mode 100644 index 43fcebb25bf96..0000000000000 --- a/core/client/header-metadata/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "substrate-header-metadata" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -lru-cache = { version = "0.1.2" } -parking_lot = { version = "0.9.0" } -sr-primitives = { path = "../../sr-primitives" } diff --git a/core/client/header-metadata/src/lib.rs b/core/client/header-metadata/src/lib.rs deleted file mode 100644 index a8c3886020e27..0000000000000 --- a/core/client/header-metadata/src/lib.rs +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Implements tree backend, cached header metadata and algorithms -//! to compute routes efficiently over the tree of headers. - -use sr_primitives::traits::{Block as BlockT, NumberFor, Header}; -use parking_lot::RwLock; -use lru_cache::LruCache; - -/// Set to the expected max difference between `best` and `finalized` blocks at sync. -const LRU_CACHE_SIZE: usize = 5_000; - -/// Get lowest common ancestor between two blocks in the tree. -/// -/// This implementation is efficient because our trees have very few and -/// small branches, and because of our current query pattern: -/// lca(best, final), lca(best + 1, final), lca(best + 2, final), etc. -/// The first call is O(h) but the others are O(1). -pub fn lowest_common_ancestor>( - backend: &T, - id_one: Block::Hash, - id_two: Block::Hash, -) -> Result, T::Error> { - let mut header_one = backend.header_metadata(id_one)?; - let mut header_two = backend.header_metadata(id_two)?; - - let mut orig_header_one = header_one.clone(); - let mut orig_header_two = header_two.clone(); - - // We move through ancestor links as much as possible, since ancestor >= parent. - - while header_one.number > header_two.number { - let ancestor_one = backend.header_metadata(header_one.ancestor)?; - - if ancestor_one.number >= header_two.number { - header_one = ancestor_one; - } else { - break - } - } - - while header_one.number < header_two.number { - let ancestor_two = backend.header_metadata(header_two.ancestor)?; - - if ancestor_two.number >= header_one.number { - header_two = ancestor_two; - } else { - break - } - } - - // Then we move the remaining path using parent links. - - while header_one.hash != header_two.hash { - if header_one.number > header_two.number { - header_one = backend.header_metadata(header_one.parent)?; - } else { - header_two = backend.header_metadata(header_two.parent)?; - } - } - - // Update cached ancestor links. - - if orig_header_one.number > header_one.number { - orig_header_one.ancestor = header_one.hash; - backend.insert_header_metadata(orig_header_one.hash, orig_header_one); - } - - if orig_header_two.number > header_one.number { - orig_header_two.ancestor = header_one.hash; - backend.insert_header_metadata(orig_header_two.hash, orig_header_two); - } - - Ok(HashAndNumber { - hash: header_one.hash, - number: header_one.number, - }) -} - -/// Compute a tree-route between two blocks. See tree-route docs for more details. -pub fn tree_route>( - backend: &T, - from: Block::Hash, - to: Block::Hash, -) -> Result, T::Error> { - let mut from = backend.header_metadata(from)?; - let mut to = backend.header_metadata(to)?; - - let mut from_branch = Vec::new(); - let mut to_branch = Vec::new(); - - while to.number > from.number { - to_branch.push(HashAndNumber { - number: to.number, - hash: to.hash, - }); - - to = backend.header_metadata(to.parent)?; - } - - while from.number > to.number { - from_branch.push(HashAndNumber { - number: from.number, - hash: from.hash, - }); - from = backend.header_metadata(from.parent)?; - } - - // numbers are equal now. walk backwards until the block is the same - - while to.hash != from.hash { - to_branch.push(HashAndNumber { - number: to.number, - hash: to.hash, - }); - to = backend.header_metadata(to.parent)?; - - from_branch.push(HashAndNumber { - number: from.number, - hash: from.hash, - }); - from = backend.header_metadata(from.parent)?; - } - - // add the pivot block. and append the reversed to-branch (note that it's reverse order originals) - let pivot = from_branch.len(); - from_branch.push(HashAndNumber { - number: to.number, - hash: to.hash, - }); - from_branch.extend(to_branch.into_iter().rev()); - - Ok(TreeRoute { - route: from_branch, - pivot, - }) -} - -/// Hash and number of a block. -#[derive(Debug)] -pub struct HashAndNumber { - /// The number of the block. - pub number: NumberFor, - /// The hash of the block. - pub hash: Block::Hash, -} - -/// A tree-route from one block to another in the chain. -/// -/// All blocks prior to the pivot in the deque is the reverse-order unique ancestry -/// of the first block, the block at the pivot index is the common ancestor, -/// and all blocks after the pivot is the ancestry of the second block, in -/// order. -/// -/// The ancestry sets will include the given blocks, and thus the tree-route is -/// never empty. -/// -/// ```text -/// Tree route from R1 to E2. Retracted is [R1, R2, R3], Common is C, enacted [E1, E2] -/// <- R3 <- R2 <- R1 -/// / -/// C -/// \-> E1 -> E2 -/// ``` -/// -/// ```text -/// Tree route from C to E2. Retracted empty. Common is C, enacted [E1, E2] -/// C -> E1 -> E2 -/// ``` -#[derive(Debug)] -pub struct TreeRoute { - route: Vec>, - pivot: usize, -} - -impl TreeRoute { - /// Get a slice of all retracted blocks in reverse order (towards common ancestor) - pub fn retracted(&self) -> &[HashAndNumber] { - &self.route[..self.pivot] - } - - /// Get the common ancestor block. This might be one of the two blocks of the - /// route. - pub fn common_block(&self) -> &HashAndNumber { - self.route.get(self.pivot).expect("tree-routes are computed between blocks; \ - which are included in the route; \ - thus it is never empty; qed") - } - - /// Get a slice of enacted blocks (descendents of the common ancestor) - pub fn enacted(&self) -> &[HashAndNumber] { - &self.route[self.pivot + 1 ..] - } -} - -/// Handles header metadata: hash, number, parent hash, etc. -pub trait HeaderMetadata { - /// Error used in case the header metadata is not found. - type Error; - - fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error>; - fn insert_header_metadata(&self, hash: Block::Hash, header_metadata: CachedHeaderMetadata); - fn remove_header_metadata(&self, hash: Block::Hash); -} - -/// Caches header metadata in an in-memory LRU cache. -pub struct HeaderMetadataCache { - cache: RwLock>>, -} - -impl HeaderMetadataCache { - /// Creates a new LRU header metadata cache with `capacity`. - pub fn new(capacity: usize) -> Self { - HeaderMetadataCache { - cache: RwLock::new(LruCache::new(capacity)), - } - } -} - -impl Default for HeaderMetadataCache { - fn default() -> Self { - HeaderMetadataCache { - cache: RwLock::new(LruCache::new(LRU_CACHE_SIZE)), - } - } -} - -impl HeaderMetadata for HeaderMetadataCache { - type Error = String; - - fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { - self.cache.write().get_mut(&hash).cloned() - .ok_or("header metadata not found in cache".to_owned()) - } - - fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { - self.cache.write().insert(hash, metadata); - } - - fn remove_header_metadata(&self, hash: Block::Hash) { - self.cache.write().remove(&hash); - } -} - -/// Cached header metadata. Used to efficiently traverse the tree. -#[derive(Debug, Clone)] -pub struct CachedHeaderMetadata { - /// Hash of the header. - pub hash: Block::Hash, - /// Block number. - pub number: NumberFor, - /// Hash of parent header. - pub parent: Block::Hash, - /// Hash of an ancestor header. Used to jump through the tree. - ancestor: Block::Hash, -} - -impl From<&Block::Header> for CachedHeaderMetadata { - fn from(header: &Block::Header) -> Self { - CachedHeaderMetadata { - hash: header.hash().clone(), - number: header.number().clone(), - parent: header.parent_hash().clone(), - ancestor: header.parent_hash().clone(), - } - } -} diff --git a/core/client/src/backend.rs b/core/client/src/backend.rs deleted file mode 100644 index 9b6d9ce58fbfe..0000000000000 --- a/core/client/src/backend.rs +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate Client data backend - -use std::sync::Arc; -use std::collections::HashMap; -use crate::error; -use crate::light::blockchain::RemoteBlockchain; -use primitives::ChangesTrieConfiguration; -use sr_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; -use sr_primitives::traits::{Block as BlockT, NumberFor}; -use state_machine::backend::Backend as StateBackend; -use state_machine::{ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieTransaction}; -use crate::blockchain::well_known_cache_keys; -use consensus::BlockOrigin; -use hash_db::Hasher; -use parking_lot::Mutex; - -/// In memory array of storage values. -pub type StorageCollection = Vec<(Vec, Option>)>; - -/// In memory arrays of storage values for multiple child tries. -pub type ChildStorageCollection = Vec<(Vec, StorageCollection)>; - -pub(crate) struct ImportSummary { - pub(crate) hash: Block::Hash, - pub(crate) origin: BlockOrigin, - pub(crate) header: Block::Header, - pub(crate) is_new_best: bool, - pub(crate) storage_changes: Option<(StorageCollection, ChildStorageCollection)>, - pub(crate) retracted: Vec, -} - -/// Import operation wrapper -pub struct ClientImportOperation< - Block: BlockT, - H: Hasher, - B: Backend, -> { - pub(crate) op: B::BlockImportOperation, - pub(crate) notify_imported: Option>, - pub(crate) notify_finalized: Vec, -} - -/// State of a new block. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum NewBlockState { - /// Normal block. - Normal, - /// New best block. - Best, - /// Newly finalized block (implicitly best). - Final, -} - -impl NewBlockState { - /// Whether this block is the new best block. - pub fn is_best(self) -> bool { - match self { - NewBlockState::Best | NewBlockState::Final => true, - 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. -pub trait BlockImportOperation where - Block: BlockT, - H: Hasher, -{ - /// Associated state backend type. - type State: StateBackend; - - /// Returns pending state. Returns None for backends with locally-unavailable state data. - fn state(&self) -> error::Result>; - /// Append block data to the transaction. - fn set_block_data( - &mut self, - header: Block::Header, - body: Option>, - justification: Option, - state: NewBlockState, - ) -> error::Result<()>; - - /// Update cached data. - fn update_cache(&mut self, cache: HashMap>); - /// Inject storage data into the database. - fn update_db_storage(&mut self, update: >::Transaction) -> error::Result<()>; - /// Inject storage data into the database replacing any existing data. - fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> error::Result; - /// Set storage changes. - fn update_storage( - &mut self, - update: StorageCollection, - child_update: ChildStorageCollection, - ) -> error::Result<()>; - /// Inject changes trie data into the database. - fn update_changes_trie(&mut self, update: ChangesTrieTransaction>) -> error::Result<()>; - /// Insert auxiliary keys. Values are `None` if should be deleted. - fn insert_aux(&mut self, ops: I) -> error::Result<()> - where I: IntoIterator, Option>)>; - /// Mark a block as finalized. - fn mark_finalized(&mut self, id: BlockId, justification: Option) -> error::Result<()>; - /// Mark a block as new head. If both block import and set head are specified, set head overrides block import's best block rule. - fn mark_head(&mut self, id: BlockId) -> error::Result<()>; -} - -/// Finalize Facilities -pub trait Finalizer, B: Backend> { - /// Mark all blocks up to given as finalized in operation. If a - /// justification is provided it is stored with the given finalized - /// block (any other finalized blocks are left unjustified). - /// - /// If the block being finalized is on a different fork from the current - /// best block the finalized block is set as best, this might be slightly - /// inaccurate (i.e. outdated). Usages that require determining an accurate - /// best block should use `SelectChain` instead of the client. - fn apply_finality( - &self, - operation: &mut ClientImportOperation, - id: BlockId, - justification: Option, - notify: bool, - ) -> error::Result<()>; - - - /// Finalize a block. This will implicitly finalize all blocks up to it and - /// fire finality notifications. - /// - /// If the block being finalized is on a different fork from the current - /// best block, the finalized block is set as best. This might be slightly - /// inaccurate (i.e. outdated). Usages that require determining an accurate - /// best block should use `SelectChain` instead of the client. - /// - /// Pass a flag to indicate whether finality notifications should be propagated. - /// This is usually tied to some synchronization state, where we don't send notifications - /// while performing major synchronization work. - fn finalize_block( - &self, - id: BlockId, - justification: Option, - notify: bool, - ) -> error::Result<()>; - -} - -/// Provides access to an auxiliary database. -pub trait AuxStore { - /// Insert auxiliary data into key-value store. Deletions occur after insertions. - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> error::Result<()>; - /// Query auxiliary data from key-value store. - fn get_aux(&self, key: &[u8]) -> error::Result>>; -} - -/// Client backend. Manages the data layer. -/// -/// Note on state pruning: while an object from `state_at` is alive, the state -/// should not be pruned. The backend should internally reference-count -/// its state objects. -/// -/// The same applies for live `BlockImportOperation`s: while an import operation building on a parent `P` -/// is alive, the state for `P` should not be pruned. -pub trait Backend: AuxStore + Send + Sync where - Block: BlockT, - H: Hasher, -{ - /// Associated block insertion operation type. - type BlockImportOperation: BlockImportOperation; - /// Associated blockchain backend type. - type Blockchain: crate::blockchain::Backend; - /// Associated state backend type. - type State: StateBackend; - /// Changes trie storage. - type ChangesTrieStorage: PrunableStateChangesTrieStorage; - /// Offchain workers local storage. - type OffchainStorage: OffchainStorage; - - /// Begin a new block insertion transaction with given parent block id. - /// When constructing the genesis, this is called with all-zero hash. - fn begin_operation(&self) -> error::Result; - /// Note an operation to contain state transition. - fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId) -> error::Result<()>; - /// Commit block insertion. - fn commit_operation(&self, transaction: Self::BlockImportOperation) -> error::Result<()>; - /// Finalize block with given Id. This should only be called if the parent of the given - /// block has been finalized. - fn finalize_block(&self, block: BlockId, justification: Option) -> error::Result<()>; - /// Returns reference to blockchain backend. - fn blockchain(&self) -> &Self::Blockchain; - /// Returns the used state cache, if existent. - fn used_state_cache_size(&self) -> Option; - /// Returns reference to changes trie storage. - fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage>; - /// Returns a handle to offchain storage. - fn offchain_storage(&self) -> Option; - /// Returns true if state for given block is available. - fn have_state_at(&self, hash: &Block::Hash, _number: NumberFor) -> bool { - self.state_at(BlockId::Hash(hash.clone())).is_ok() - } - /// Returns state backend with post-state of given block. - fn state_at(&self, block: BlockId) -> error::Result; - /// Destroy state and save any useful data, such as cache. - fn destroy_state(&self, _state: Self::State) -> error::Result<()> { - Ok(()) - } - /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were - /// successfully reverted. - fn revert(&self, n: NumberFor) -> error::Result>; - - /// Insert auxiliary data into key-value store. - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> error::Result<()> - { - AuxStore::insert_aux(self, insert, delete) - } - /// Query auxiliary data from key-value store. - fn get_aux(&self, key: &[u8]) -> error::Result>> { - AuxStore::get_aux(self, key) - } - - /// Gain access to the import lock around this backend. - /// _Note_ Backend isn't expected to acquire the lock by itself ever. Rather - /// the using components should acquire and hold the lock whenever they do - /// something that the import of a block would interfere with, e.g. importing - /// a new block or calculating the best head. - fn get_import_lock(&self) -> &Mutex<()>; -} - -/// Offchain workers local storage. -pub trait OffchainStorage: Clone + Send + Sync { - /// Persist a value in storage under given key and prefix. - fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]); - - /// Retrieve a value from storage under given key and prefix. - fn get(&self, prefix: &[u8], key: &[u8]) -> Option>; - - /// Replace the value in storage if given old_value matches the current one. - /// - /// Returns `true` if the value has been set and false otherwise. - fn compare_and_set( - &mut self, - prefix: &[u8], - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool; -} - -/// 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: NumberFor, - ) -> NumberFor; -} - -/// Mark for all Backend implementations, that are making use of state data, stored locally. -pub trait LocalBackend: Backend -where - Block: BlockT, - H: Hasher, -{} - -/// Mark for all Backend implementations, that are fetching required state data from remote nodes. -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; - /// Returns reference to blockchain backend that either resolves blockchain data - /// locally, or prepares request to fetch that data from remote node. - fn remote_blockchain(&self) -> Arc>; -} diff --git a/core/client/src/block_builder/api.rs b/core/client/src/block_builder/api.rs deleted file mode 100644 index 5bf742a4560d4..0000000000000 --- a/core/client/src/block_builder/api.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! The runtime api for building blocks. - -use sr_primitives::{traits::Block as BlockT, ApplyResult}; -use rstd::vec::Vec; -use sr_api_macros::decl_runtime_apis; -pub use inherents::{InherentData, CheckInherentsResult}; - -decl_runtime_apis! { - /// The `BlockBuilder` api trait that provides required functions for building a block for a runtime. - #[api_version(3)] - pub trait BlockBuilder { - /// Apply the given extrinsics. - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult; - /// Finish the current block. - #[renamed("finalise_block", 3)] - fn finalize_block() -> ::Header; - /// 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) -> CheckInherentsResult; - /// 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 deleted file mode 100644 index 08711469e9a1b..0000000000000 --- a/core/client/src/block_builder/block_builder.rs +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use super::api::BlockBuilder as BlockBuilderApi; -use std::vec::Vec; -use codec::Encode; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ - Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef, DigestFor, -}; -use primitives::{H256, ExecutionContext}; -use crate::blockchain::HeaderBackend; -use crate::runtime_api::{Core, ApiExt}; -use crate::error; - -/// Utility for building new (valid) blocks from a stream of extrinsics. -pub struct BlockBuilder<'a, Block, A: ProvideRuntimeApi> where Block: BlockT { - header: ::Header, - extrinsics: Vec<::Extrinsic>, - api: ApiRef<'a, A::Api>, - block_id: BlockId, -} - -impl<'a, Block, A> BlockBuilder<'a, Block, A> -where - Block: BlockT, - A: ProvideRuntimeApi + HeaderBackend + 'a, - A::Api: BlockBuilderApi, -{ - /// Create a new instance of builder from the given client, building on the - /// latest block. - pub fn new(api: &'a A, inherent_digests: DigestFor) -> error::Result { - Self::at_block(&BlockId::Hash(api.info().best_hash), api, false, inherent_digests) - } - - /// Create a new instance of builder from the given client using a - /// particular block's ID to build upon with optional proof recording enabled. - /// - /// While proof recording is enabled, all accessed trie nodes are saved. - /// These recorded trie nodes can be used by a third party to prove the - /// output of this block builder without having access to the full storage. - pub fn at_block( - block_id: &BlockId, - api: &'a A, - proof_recording: bool, - inherent_digests: DigestFor, - ) -> error::Result { - let number = api.block_number_from_id(block_id)? - .ok_or_else(|| error::Error::UnknownBlock(format!("{}", block_id)))? - + One::one(); - - let parent_hash = api.block_hash_from_id(block_id)? - .ok_or_else(|| error::Error::UnknownBlock(format!("{}", block_id)))?; - let header = <::Header as HeaderT>::new( - number, - Default::default(), - Default::default(), - parent_hash, - inherent_digests, - ); - - let mut api = api.runtime_api(); - - if proof_recording { - api.record_proof(); - } - - api.initialize_block_with_context( - block_id, ExecutionContext::BlockConstruction, &header, - )?; - - Ok(BlockBuilder { - header, - extrinsics: Vec::new(), - api, - block_id: *block_id, - }) - } - - /// 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<()> { - 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(_) => { - extrinsics.push(xt); - Ok(()) - } - Err(e) => { - Err(error::Error::ApplyExtrinsicFailed(e)) - } - } - }) - } - - /// Consume the builder to return a valid `Block` containing all pushed extrinsics. - pub fn bake(mut self) -> error::Result { - self.bake_impl()?; - Ok(::new(self.header, self.extrinsics)) - } - - fn bake_impl(&mut self) -> error::Result<()> { - self.header = self.api.finalize_block_with_context( - &self.block_id, ExecutionContext::BlockConstruction - )?; - - debug_assert_eq!( - self.header.extrinsics_root().clone(), - HashFor::::ordered_trie_root( - self.extrinsics.iter().map(Encode::encode).collect(), - ), - ); - - Ok(()) - } - - /// Consume the builder to return a valid `Block` containing all pushed extrinsics - /// and the generated proof. - /// - /// The proof will be `Some(_)`, if proof recording was enabled while creating - /// the block builder. - pub fn bake_and_extract_proof(mut self) -> error::Result<(Block, Option>>)> { - self.bake_impl()?; - - let proof = self.api.extract_proof(); - Ok((::new(self.header, self.extrinsics), proof)) - } -} diff --git a/core/client/src/block_builder/mod.rs b/core/client/src/block_builder/mod.rs deleted file mode 100644 index 7f617044a42cf..0000000000000 --- a/core/client/src/block_builder/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Utility struct to build a block. - -#[cfg(feature = "std")] -mod block_builder; -#[cfg(feature = "std")] -pub use self::block_builder::*; -pub mod api; diff --git a/core/client/src/blockchain.rs b/core/client/src/blockchain.rs deleted file mode 100644 index 73b7c138d020e..0000000000000 --- a/core/client/src/blockchain.rs +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate blockchain trait - -use std::sync::Arc; - -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use sr_primitives::generic::BlockId; -use sr_primitives::Justification; -use log::warn; -use parking_lot::Mutex; - -use header_metadata::HeaderMetadata; - -use crate::error::{Error, Result}; - -/// Blockchain database header backend. Does not perform any validation. -pub trait HeaderBackend: Send + Sync { - /// Get block header. Returns `None` if block is not found. - fn header(&self, id: BlockId) -> Result>; - /// Get blockchain info. - fn info(&self) -> Info; - /// Get block status. - fn status(&self, id: BlockId) -> Result; - /// Get block number by hash. Returns `None` if the header is not in the chain. - fn number(&self, hash: Block::Hash) -> Result::Header as HeaderT>::Number>>; - /// Get block hash by number. Returns `None` if the header is not in the chain. - fn hash(&self, number: NumberFor) -> Result>; - - /// Convert an arbitrary block ID into a block hash. - fn block_hash_from_id(&self, id: &BlockId) -> Result> { - match *id { - BlockId::Hash(h) => Ok(Some(h)), - BlockId::Number(n) => self.hash(n), - } - } - - /// Convert an arbitrary block ID into a block hash. - fn block_number_from_id(&self, id: &BlockId) -> Result>> { - match *id { - BlockId::Hash(_) => Ok(self.header(*id)?.map(|h| h.number().clone())), - BlockId::Number(n) => Ok(Some(n)), - } - } - - /// Get block header. Returns `UnknownBlock` error if block is not found. - fn expect_header(&self, id: BlockId) -> Result { - self.header(id)?.ok_or_else(|| Error::UnknownBlock(format!("{}", id))) - } - - /// Convert an arbitrary block ID into a block number. Returns `UnknownBlock` error if block is not found. - fn expect_block_number_from_id(&self, id: &BlockId) -> Result> { - self.block_number_from_id(id) - .and_then(|n| n.ok_or_else(|| Error::UnknownBlock(format!("{}", id)))) - } - - /// Convert an arbitrary block ID into a block hash. Returns `UnknownBlock` error if block is not found. - fn expect_block_hash_from_id(&self, id: &BlockId) -> Result { - self.block_hash_from_id(id) - .and_then(|n| n.ok_or_else(|| Error::UnknownBlock(format!("{}", id)))) - } -} - -/// Blockchain database backend. Does not perform any validation. -pub trait Backend: HeaderBackend + HeaderMetadata { - /// Get block body. Returns `None` if block is not found. - fn body(&self, id: BlockId) -> Result::Extrinsic>>>; - /// Get block justification. Returns `None` if justification does not exist. - fn justification(&self, id: BlockId) -> Result>; - /// Get last finalized block hash. - fn last_finalized(&self) -> Result; - /// Returns data cache reference, if it is enabled on this backend. - fn cache(&self) -> Option>>; - - /// Returns hashes of all blocks that are leaves of the block tree. - /// in other words, that have no children, are chain heads. - /// Results must be ordered best (longest, highest) 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>; - - /// Get the most recent block hash of the best (longest) chains - /// that contain block with the given `target_hash`. - /// - /// The search space is always limited to blocks which are in the finalized - /// chain or descendents of it. - /// - /// If `maybe_max_block_number` is `Some(max_block_number)` - /// the search is limited to block `numbers <= max_block_number`. - /// in other words as if there were no blocks greater `max_block_number`. - /// Returns `Ok(None)` if `target_hash` is not found in search space. - /// TODO: document time complexity of this, see [#1444](https://github.com/paritytech/substrate/issues/1444) - fn best_containing( - &self, - target_hash: Block::Hash, - maybe_max_number: Option>, - import_lock: &Mutex<()>, - ) -> Result> { - let target_header = { - match self.header(BlockId::Hash(target_hash))? { - Some(x) => x, - // target not in blockchain - None => { return Ok(None); }, - } - }; - - if let Some(max_number) = maybe_max_number { - // target outside search range - if target_header.number() > &max_number { - return Ok(None); - } - } - - let leaves = { - // ensure no blocks are imported during this code block. - // an import could trigger a reorg which could change the canonical chain. - // we depend on the canonical chain staying the same during this code block. - let _import_guard = import_lock.lock(); - - let info = self.info(); - - // this can be `None` if the best chain is shorter than the target header. - let maybe_canon_hash = self.hash(*target_header.number())?; - - if maybe_canon_hash.as_ref() == Some(&target_hash) { - // if a `max_number` is given we try to fetch the block at the - // given depth, if it doesn't exist or `max_number` is not - // provided, we continue to search from all leaves below. - if let Some(max_number) = maybe_max_number { - if let Some(header) = self.hash(max_number)? { - return Ok(Some(header)); - } - } - } else if info.finalized_number >= *target_header.number() { - // header is on a dead fork. - return Ok(None); - } - - self.leaves()? - }; - - // for each chain. longest chain first. shortest last - for leaf_hash in leaves { - // start at the leaf - let mut current_hash = leaf_hash; - - // if search is not restricted then the leaf is the best - let mut best_hash = leaf_hash; - - // go backwards entering the search space - // waiting until we are <= max_number - if let Some(max_number) = maybe_max_number { - loop { - let current_header = self.header(BlockId::Hash(current_hash.clone()))? - .ok_or_else(|| Error::from(format!("failed to get header for hash {}", current_hash)))?; - - if current_header.number() <= &max_number { - best_hash = current_header.hash(); - break; - } - - current_hash = *current_header.parent_hash(); - } - } - - // go backwards through the chain (via parent links) - loop { - // until we find target - if current_hash == target_hash { - return Ok(Some(best_hash)); - } - - let current_header = self.header(BlockId::Hash(current_hash.clone()))? - .ok_or_else(|| Error::from(format!("failed to get header for hash {}", current_hash)))?; - - // stop search in this chain once we go below the target's block number - if current_header.number() < target_header.number() { - break; - } - - current_hash = *current_header.parent_hash(); - } - } - - // header may be on a dead fork -- the only leaves that are considered are - // those which can still be finalized. - // - // FIXME #1558 only issue this warning when not on a dead fork - warn!( - "Block {:?} exists in chain but not found when following all \ - leaves backwards. Number limit = {:?}", - target_hash, - maybe_max_number, - ); - - Ok(None) - } -} - -/// Provides access to the optional cache. -pub trait ProvideCache { - /// Returns data cache reference, if it is enabled on this backend. - fn cache(&self) -> Option>>; -} - -/// Blockchain optional data cache. -pub trait Cache: Send + Sync { - /// Initialize genesis value for the given cache. - /// - /// The operation should be performed once before anything else is inserted in the cache. - /// Otherwise cache may end up in inconsistent state. - fn initialize(&self, key: &well_known_cache_keys::Id, value_at_genesis: Vec) -> Result<()>; - /// Returns cached value by the given key. - /// - /// Returned tuple is the range where value has been active and the value itself. - fn get_at( - &self, - key: &well_known_cache_keys::Id, - block: &BlockId, - ) -> Option<((NumberFor, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)>; -} - -/// Blockchain info -#[derive(Debug)] -pub struct Info { - /// Best block hash. - pub best_hash: Block::Hash, - /// Best block number. - pub best_number: <::Header as HeaderT>::Number, - /// Genesis block hash. - pub genesis_hash: Block::Hash, - /// The head of the finalized chain. - pub finalized_hash: Block::Hash, - /// Last finalized block number. - pub finalized_number: <::Header as HeaderT>::Number, -} - -/// Block status. -#[derive(Debug, PartialEq, Eq)] -pub enum BlockStatus { - /// Already in the blockchain. - InChain, - /// Not in the queue or the blockchain. - Unknown, -} - -/// A list of all well known keys in the blockchain cache. -pub mod well_known_cache_keys { - /// The type representing cache keys. - pub type Id = consensus::import_queue::CacheKeyId; - - /// A list of authorities. - pub const AUTHORITIES: Id = *b"auth"; - - /// Current Epoch data. - pub const EPOCH: Id = *b"epch"; - - /// Changes trie configuration. - pub const CHANGES_TRIE_CONFIG: Id = *b"chtr"; -} diff --git a/core/client/src/call_executor.rs b/core/client/src/call_executor.rs deleted file mode 100644 index 05a2a8eba1c3e..0000000000000 --- a/core/client/src/call_executor.rs +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::{sync::Arc, cmp::Ord, panic::UnwindSafe, result, cell::RefCell, rc::Rc}; -use codec::{Encode, Decode}; -use sr_primitives::{ - generic::BlockId, traits::Block as BlockT, traits::NumberFor, -}; -use state_machine::{ - self, OverlayedChanges, Ext, ExecutionManager, StateMachine, ExecutionStrategy, - backend::Backend as _, ChangesTrieTransaction, -}; -use executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; -use hash_db::Hasher; -use primitives::{ - offchain::OffchainExt, H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue, - traits::{CodeExecutor, KeystoreExt}, -}; - -use crate::runtime_api::{ProofRecorder, InitializeBlock}; -use crate::backend; -use crate::error; - -/// Method call executor. -pub trait CallExecutor -where - B: BlockT, - H: Hasher, - H::Out: Ord, -{ - /// Externalities error type. - type Error: state_machine::Error; - - /// Execute a call to a contract on top of state in a block of given hash. - /// - /// No changes are made. - fn call( - &self, - id: &BlockId, - method: &str, - call_data: &[u8], - strategy: ExecutionStrategy, - side_effects_handler: Option, - ) -> Result, error::Error>; - - /// Execute a contextual call on top of state in a block of a given hash. - /// - /// No changes are made. - /// Before executing the method, passed header is installed as the current header - /// of the execution context. - fn contextual_call< - 'a, - IB: Fn() -> error::Result<()>, - EM: Fn( - Result, Self::Error>, - Result, Self::Error> - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - >( - &self, - initialize_block_fn: IB, - at: &BlockId, - method: &str, - call_data: &[u8], - changes: &RefCell, - initialize_block: InitializeBlock<'a, B>, - execution_manager: ExecutionManager, - native_call: Option, - side_effects_handler: Option, - proof_recorder: &Option>>>, - enable_keystore: bool, - ) -> error::Result> where ExecutionManager: Clone; - - /// Extract RuntimeVersion of given block - /// - /// No changes are made. - fn runtime_version(&self, id: &BlockId) -> Result; - - /// Execute a call to a contract on top of given state. - /// - /// No changes are made. - fn call_at_state< - S: state_machine::Backend, - F: FnOnce( - Result, Self::Error>, - Result, Self::Error>, - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - >(&self, - state: &S, - overlay: &mut OverlayedChanges, - method: &str, - call_data: &[u8], - manager: ExecutionManager, - native_call: Option, - side_effects_handler: Option, - ) -> Result< - ( - NativeOrEncoded, - (S::Transaction, H::Out), - Option>> - ), - error::Error, - >; - - /// Execute a call to a contract on top of given state, gathering execution proof. - /// - /// No changes are made. - fn prove_at_state>( - &self, - mut state: S, - overlay: &mut OverlayedChanges, - method: &str, - call_data: &[u8] - ) -> Result<(Vec, Vec>), error::Error> { - let trie_state = state.as_trie_backend() - .ok_or_else(|| - Box::new(state_machine::ExecutionError::UnableToGenerateProof) - as Box - )?; - self.prove_at_trie_state(trie_state, overlay, method, call_data) - } - - /// Execute a call to a contract on top of given trie state, gathering execution proof. - /// - /// No changes are made. - fn prove_at_trie_state>( - &self, - trie_state: &state_machine::TrieBackend, - overlay: &mut OverlayedChanges, - method: &str, - call_data: &[u8] - ) -> Result<(Vec, Vec>), error::Error>; - - /// Get runtime version if supported. - fn native_runtime_version(&self) -> Option<&NativeVersion>; -} - -/// Call executor that executes methods locally, querying all required -/// data from local backend. -pub struct LocalCallExecutor { - backend: Arc, - executor: E, - keystore: Option, -} - -impl LocalCallExecutor { - /// Creates new instance of local call executor. - pub fn new( - backend: Arc, - executor: E, - keystore: Option, - ) -> Self { - LocalCallExecutor { - backend, - executor, - keystore, - } - } -} - -impl Clone for LocalCallExecutor where E: Clone { - fn clone(&self) -> Self { - LocalCallExecutor { - backend: self.backend.clone(), - executor: self.executor.clone(), - keystore: self.keystore.clone(), - } - } -} - -impl CallExecutor for LocalCallExecutor -where - B: backend::Backend, - E: CodeExecutor + RuntimeInfo, - Block: BlockT, -{ - type Error = E::Error; - - fn call( - &self, - id: &BlockId, - method: &str, - call_data: &[u8], - strategy: ExecutionStrategy, - side_effects_handler: Option, - ) -> error::Result> { - let mut changes = OverlayedChanges::default(); - let state = self.backend.state_at(*id)?; - let return_data = StateMachine::new( - &state, - self.backend.changes_trie_storage(), - side_effects_handler, - &mut changes, - &self.executor, - method, - call_data, - self.keystore.clone().map(KeystoreExt), - ).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< - 'a, - IB: Fn() -> error::Result<()>, - EM: Fn( - Result, Self::Error>, - Result, Self::Error> - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - >( - &self, - initialize_block_fn: IB, - at: &BlockId, - method: &str, - call_data: &[u8], - changes: &RefCell, - initialize_block: InitializeBlock<'a, Block>, - execution_manager: ExecutionManager, - native_call: Option, - side_effects_handler: Option, - recorder: &Option>>>, - enable_keystore: bool, - ) -> Result, error::Error> where ExecutionManager: Clone { - match initialize_block { - InitializeBlock::Do(ref init_block) - if init_block.borrow().as_ref().map(|id| id != at).unwrap_or(true) => { - initialize_block_fn()?; - }, - // We don't need to initialize the runtime at a block. - _ => {}, - } - - let keystore = if enable_keystore { - self.keystore.clone().map(KeystoreExt) - } else { - None - }; - - let mut state = self.backend.state_at(*at)?; - - let result = match recorder { - Some(recorder) => { - let trie_state = state.as_trie_backend() - .ok_or_else(|| - Box::new(state_machine::ExecutionError::UnableToGenerateProof) - as Box - )?; - - let backend = state_machine::ProvingBackend::new_with_recorder( - trie_state, - recorder.clone() - ); - - StateMachine::new( - &backend, - self.backend.changes_trie_storage(), - side_effects_handler, - &mut *changes.borrow_mut(), - &self.executor, - method, - call_data, - keystore, - ) - .execute_using_consensus_failure_handler( - execution_manager, - false, - native_call, - ) - .map(|(result, _, _)| result) - .map_err(Into::into) - } - None => StateMachine::new( - &state, - self.backend.changes_trie_storage(), - side_effects_handler, - &mut *changes.borrow_mut(), - &self.executor, - method, - call_data, - keystore, - ) - .execute_using_consensus_failure_handler( - execution_manager, - false, - native_call, - ) - .map(|(result, _, _)| result) - }?; - 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)?; - - let mut ext = Ext::new( - &mut overlay, - &state, - self.backend.changes_trie_storage(), - None, - ); - let version = self.executor.runtime_version(&mut ext); - self.backend.destroy_state(state)?; - version.ok_or(error::Error::VersionInvalid.into()) - } - - fn call_at_state< - S: state_machine::Backend, - F: FnOnce( - Result, Self::Error>, - Result, Self::Error>, - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - >(&self, - state: &S, - changes: &mut OverlayedChanges, - method: &str, - call_data: &[u8], - manager: ExecutionManager, - native_call: Option, - side_effects_handler: Option, - ) -> error::Result<( - NativeOrEncoded, - (S::Transaction, ::Out), - Option>>, - )> { - StateMachine::new( - state, - self.backend.changes_trie_storage(), - side_effects_handler, - changes, - &self.executor, - method, - call_data, - self.keystore.clone().map(KeystoreExt), - ).execute_using_consensus_failure_handler( - manager, - true, - native_call, - ) - .map(|(result, storage_tx, changes_tx)| ( - result, - storage_tx.expect("storage_tx is always computed when compute_tx is true; qed"), - changes_tx, - )) - .map_err(Into::into) - } - - fn prove_at_trie_state>( - &self, - trie_state: &state_machine::TrieBackend, - overlay: &mut OverlayedChanges, - method: &str, - call_data: &[u8] - ) -> Result<(Vec, Vec>), error::Error> { - state_machine::prove_execution_on_trie_backend( - trie_state, - overlay, - &self.executor, - method, - call_data, - self.keystore.clone().map(KeystoreExt), - ) - .map_err(Into::into) - } - - fn native_runtime_version(&self) -> Option<&NativeVersion> { - Some(self.executor.native_version()) - } -} diff --git a/core/client/src/children.rs b/core/client/src/children.rs deleted file mode 100644 index 3128f860869ce..0000000000000 --- a/core/client/src/children.rs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Functionality for reading and storing children hashes from db. - -use kvdb::{KeyValueDB, DBTransaction}; -use 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: &dyn 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::Error::Backend("Error reading value from database".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[..]) { - Ok(children) => children, - Err(_) => return Err(error::Error::Backend("Error decoding children".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); - } -} diff --git a/core/client/src/client.rs b/core/client/src/client.rs deleted file mode 100644 index d853d851c546c..0000000000000 --- a/core/client/src/client.rs +++ /dev/null @@ -1,2848 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate Client - -use std::{ - marker::PhantomData, collections::{HashSet, BTreeMap, HashMap}, sync::Arc, - panic::UnwindSafe, result, cell::RefCell, rc::Rc, -}; -use log::{info, trace, warn}; -use futures03::channel::mpsc; -use parking_lot::{Mutex, RwLock}; -use codec::{Encode, Decode}; -use hash_db::{Hasher, Prefix}; -use primitives::{ - Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue, ExecutionContext, - NativeOrEncoded, storage::{StorageKey, StorageData, well_known_keys}, - offchain::{OffchainExt, self}, traits::CodeExecutor, -}; -use substrate_telemetry::{telemetry, SUBSTRATE_INFO}; -use sr_primitives::{ - Justification, BuildStorage, - generic::{BlockId, SignedBlock, DigestItem}, - traits::{ - Block as BlockT, Header as HeaderT, Zero, NumberFor, - ApiRef, ProvideRuntimeApi, SaturatedConversion, One, DigestFor, - }, -}; -use state_machine::{ - DBValue, Backend as StateBackend, ChangesTrieAnchorBlockId, ExecutionStrategy, ExecutionManager, - prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage, - ChangesTrieTransaction, ChangesTrieConfigurationRange, key_changes, key_changes_proof, - OverlayedChanges, BackendTrustLevel, -}; -use executor::{RuntimeVersion, RuntimeInfo}; -use consensus::{ - Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams, - ImportResult, BlockOrigin, ForkChoiceStrategy, - SelectChain, self, -}; -use header_metadata::{HeaderMetadata, CachedHeaderMetadata}; - -use crate::{ - runtime_api::{ - CallRuntimeAt, ConstructRuntimeApi, Core as CoreApi, ProofRecorder, - InitializeBlock, - }, - backend::{ - self, BlockImportOperation, PrunableStateChangesTrieStorage, - ClientImportOperation, Finalizer, ImportSummary, - }, - blockchain::{ - self, Info as ChainInfo, Backend as ChainBackend, - HeaderBackend as ChainHeaderBackend, ProvideCache, Cache, - well_known_cache_keys::Id as CacheKeyId, - }, - call_executor::{CallExecutor, LocalCallExecutor}, - notifications::{StorageNotifications, StorageEventStream}, - light::{call_executor::prove_execution, fetcher::ChangesProof}, - block_builder::{self, api::BlockBuilder as BlockBuilderAPI}, - error::Error, - cht, error, in_mem, genesis -}; - -/// Type that implements `futures::Stream` of block import events. -pub type ImportNotifications = mpsc::UnboundedReceiver>; - -/// A stream of block finality notifications. -pub type FinalityNotifications = mpsc::UnboundedReceiver>; - -type StorageUpdate = < - < - >::BlockImportOperation - as BlockImportOperation - >::State as state_machine::Backend>::Transaction; -type ChangesUpdate = ChangesTrieTransaction>; - -/// Expected hashes of blocks at given heights. -/// -/// This may be used as chain spec extension to filter out known, unwanted forks. -pub type ForkBlocks = Option, ::Hash>>; - -/// Execution strategies settings. -#[derive(Debug, Clone)] -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 for offchain workers. - pub offchain_worker: 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, - offchain_worker: ExecutionStrategy::NativeWhenPossible, - other: ExecutionStrategy::NativeElseWasm, - } - } -} - -/// Substrate Client -pub struct Client where Block: BlockT { - backend: Arc, - executor: E, - storage_notifications: Mutex>, - import_notification_sinks: Mutex>>>, - finality_notification_sinks: Mutex>>>, - // holds the block hash currently being imported. TODO: replace this with block queue - importing_block: RwLock>, - fork_blocks: ForkBlocks, - execution_strategies: ExecutionStrategies, - _phantom: PhantomData, -} - -/// A source of blockchain events. -pub trait BlockchainEvents { - /// Get block import event stream. Not guaranteed to be fired for every - /// imported block. - fn import_notification_stream(&self) -> ImportNotifications; - - /// Get a stream of finality notifications. Not guaranteed to be fired for every - /// finalized block. - fn finality_notification_stream(&self) -> FinalityNotifications; - - /// Get storage changes event stream. - /// - /// Passing `None` as `filter_keys` subscribes to all storage changes. - fn storage_changes_notification_stream( - &self, - filter_keys: Option<&[StorageKey]>, - child_filter_keys: Option<&[(StorageKey, Option>)]>, - ) -> error::Result>; -} - -/// Fetch block body by ID. -pub trait BlockBody { - /// Get block body by ID. Returns `None` if the body is not stored. - fn block_body(&self, - id: &BlockId - ) -> error::Result::Extrinsic>>>; -} - -/// Provide a list of potential uncle headers for a given block. -pub trait ProvideUncles { - /// Gets the uncles of the block with `target_hash` going back `max_generation` ancestors. - fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) - -> error::Result>; -} - -/// Client info -#[derive(Debug)] -pub struct ClientInfo { - /// Best block hash. - pub chain: ChainInfo, - /// State Cache Size currently used by the backend - pub used_state_cache_size: Option, -} - -/// Summary of an imported block -#[derive(Clone, Debug)] -pub struct BlockImportNotification { - /// Imported block header hash. - pub hash: Block::Hash, - /// Imported block origin. - pub origin: BlockOrigin, - /// Imported block header. - pub header: Block::Header, - /// Is this the new best block. - pub is_new_best: bool, - /// List of retracted blocks ordered by block number. - pub retracted: Vec, -} - -/// Summary of a finalized block. -#[derive(Clone, Debug)] -pub struct FinalityNotification { - /// Imported block header hash. - pub hash: Block::Hash, - /// Imported block header. - pub header: Block::Header, -} - -// used in importing a block, where additional changes are made after the runtime -// executed. -enum PrePostHeader { - // they are the same: no post-runtime digest items. - Same(H), - // different headers (pre, post). - Different(H, H), -} - -impl PrePostHeader { - // get a reference to the "pre-header" -- the header as it should be just after the runtime. - fn pre(&self) -> &H { - match *self { - PrePostHeader::Same(ref h) => h, - PrePostHeader::Different(ref h, _) => h, - } - } - - // get a reference to the "post-header" -- the header as it should be after all changes are applied. - fn post(&self) -> &H { - match *self { - PrePostHeader::Same(ref h) => h, - PrePostHeader::Different(_, ref h) => h, - } - } - - // convert to the "post-header" -- the header as it should be after all changes are applied. - fn into_post(self) -> H { - match self { - PrePostHeader::Same(h) => h, - PrePostHeader::Different(_, h) => h, - } - } -} - -/// Create an instance of in-memory client. -pub fn new_in_mem( - executor: E, - genesis_storage: S, - keystore: Option, -) -> error::Result, - LocalCallExecutor, E>, - Block, - RA ->> where - E: CodeExecutor + RuntimeInfo, - S: BuildStorage, - Block: BlockT, -{ - new_with_backend(Arc::new(in_mem::Backend::new()), executor, genesis_storage, keystore) -} - -/// Create a client with the explicitly provided backend. -/// This is useful for testing backend implementations. -pub fn new_with_backend( - backend: Arc, - executor: E, - build_genesis_storage: S, - keystore: Option, -) -> error::Result, Block, RA>> - where - E: CodeExecutor + RuntimeInfo, - S: BuildStorage, - Block: BlockT, - B: backend::LocalBackend -{ - let call_executor = LocalCallExecutor::new(backend.clone(), executor, keystore); - Client::new(backend, call_executor, build_genesis_storage, Default::default(), Default::default()) -} - -/// Figure out the block type for a given type (for now, just a `Client`). -pub trait BlockOf { - /// The type of the block. - type Type: BlockT; -} - -impl BlockOf for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - type Type = Block; -} - -impl Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - /// Creates new Substrate Client with given blockchain and code executor. - pub fn new( - backend: Arc, - executor: E, - build_genesis_storage: S, - fork_blocks: ForkBlocks, - 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()?; - 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!("Initializing Genesis block/state (state: {}, header-hash: {})", - genesis_block.header().state_root(), - genesis_block.header().hash() - ); - op.set_block_data( - genesis_block.deconstruct().0, - Some(vec![]), - None, - crate::backend::NewBlockState::Final - )?; - backend.commit_operation(op)?; - } - - Ok(Client { - backend, - executor, - storage_notifications: Default::default(), - import_notification_sinks: Default::default(), - finality_notification_sinks: Default::default(), - importing_block: Default::default(), - fork_blocks, - 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) - } - - /// Expose backend reference. To be used in tests only - #[doc(hidden)] - #[deprecated(note="Rather than relying on `client` to provide this, access \ - to the backend should be handled at setup only - see #1134. This function \ - will be removed once that is in place.")] - pub fn backend(&self) -> &Arc { - &self.backend - } - - /// Given a `BlockId` and a key prefix, return the matching child storage keys in that block. - pub fn storage_keys(&self, id: &BlockId, key_prefix: &StorageKey) -> error::Result> { - let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect(); - Ok(keys) - } - - /// Given a `BlockId` and a key, return the value under the key in that block. - pub fn storage(&self, id: &BlockId, key: &StorageKey) -> error::Result> { - Ok(self.state_at(id)? - .storage(&key.0).map_err(|e| error::Error::from_state(Box::new(e)))? - .map(StorageData) - ) - } - - /// Given a `BlockId` and a key, return the value under the hash in that block. - pub fn storage_hash(&self, id: &BlockId, key: &StorageKey) - -> error::Result> { - Ok(self.state_at(id)? - .storage_hash(&key.0).map_err(|e| error::Error::from_state(Box::new(e)))? - ) - } - - /// Given a `BlockId`, a key prefix, and a child storage key, return the matching child storage keys. - pub fn child_storage_keys( - &self, - id: &BlockId, - child_storage_key: &StorageKey, - key_prefix: &StorageKey - ) -> error::Result> { - let keys = self.state_at(id)? - .child_keys(&child_storage_key.0, &key_prefix.0) - .into_iter() - .map(StorageKey) - .collect(); - Ok(keys) - } - - /// Given a `BlockId`, a key and a child storage key, return the value under the key in that block. - pub fn child_storage( - &self, - id: &BlockId, - child_storage_key: &StorageKey, - key: &StorageKey - ) -> error::Result> { - Ok(self.state_at(id)? - .child_storage(&child_storage_key.0, &key.0).map_err(|e| error::Error::from_state(Box::new(e)))? - .map(StorageData)) - } - - /// Given a `BlockId`, a key and a child storage key, return the hash under the key in that block. - pub fn child_storage_hash( - &self, - id: &BlockId, - child_storage_key: &StorageKey, - key: &StorageKey - ) -> error::Result> { - Ok(self.state_at(id)? - .child_storage_hash(&child_storage_key.0, &key.0).map_err(|e| error::Error::from_state(Box::new(e)))? - ) - } - - /// Get the code at a given block. - pub fn code_at(&self, id: &BlockId) -> error::Result> { - Ok(self.storage(id, &StorageKey(well_known_keys::CODE.to_vec()))? - .expect("None is returned if there's no value stored for the given key;\ - ':code' key is always defined; qed").0) - } - - /// Get the RuntimeVersion at a given block. - pub fn runtime_version_at(&self, id: &BlockId) -> error::Result { - self.executor.runtime_version(id) - } - - /// Get call executor reference. - pub fn executor(&self) -> &E { - &self.executor - } - - /// Reads storage value at a given block + key, returning read proof. - pub fn read_proof(&self, id: &BlockId, keys: I) -> error::Result>> where - I: IntoIterator, - I::Item: AsRef<[u8]>, - { - self.state_at(id) - .and_then(|state| prove_read(state, keys) - .map_err(Into::into)) - } - - /// Reads child storage value at a given block + storage_key + key, returning - /// read proof. - pub fn read_child_proof( - &self, - id: &BlockId, - storage_key: &[u8], - keys: I, - ) -> error::Result>> where - I: IntoIterator, - I::Item: AsRef<[u8]>, - { - self.state_at(id) - .and_then(|state| prove_child_read(state, storage_key, keys) - .map_err(Into::into)) - } - - /// Execute a call to a contract on top of state in a block of given hash - /// AND returning execution proof. - /// - /// No changes are made. - pub fn execution_proof(&self, - id: &BlockId, - method: &str, - call_data: &[u8] - ) -> error::Result<(Vec, Vec>)> { - let state = self.state_at(id)?; - let header = self.prepare_environment_block(id)?; - prove_execution(state, header, &self.executor, method, call_data) - } - - /// Reads given header and generates CHT-based header proof. - pub fn header_proof(&self, id: &BlockId) -> error::Result<(Block::Header, Vec>)> { - self.header_proof_with_cht_size(id, cht::size()) - } - - /// Get block hash by number. - pub fn block_hash(&self, - block_number: <::Header as HeaderT>::Number - ) -> error::Result> { - self.backend.blockchain().hash(block_number) - } - - /// Reads given header and generates CHT-based header proof for CHT of given size. - pub fn header_proof_with_cht_size( - &self, - id: &BlockId, - cht_size: NumberFor, - ) -> error::Result<(Block::Header, Vec>)> { - let proof_error = || error::Error::Backend(format!("Failed to generate header proof for {:?}", id)); - let header = self.backend.blockchain().expect_header(*id)?; - let block_num = *header.number(); - let cht_num = cht::block_to_cht_number(cht_size, block_num).ok_or_else(proof_error)?; - let cht_start = cht::start_number(cht_size, cht_num); - let mut current_num = cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - let headers = cht_range.map(|num| self.block_hash(num)); - let proof = cht::build_proof::(cht_size, cht_num, ::std::iter::once(block_num), headers)?; - Ok((header, proof)) - } - - /// 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 last_num = self.backend.blockchain().expect_block_number_from_id(&last)?; - if first > last_num { - return Err(error::Error::ChangesTrieAccessFailed("Invalid changes trie range".into())); - } - let finalized_number = self.backend.blockchain().info().finalized_number; - let oldest = storage.oldest_changes_trie_block(&config, finalized_number); - let first = ::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. - /// - /// Changes are returned in descending order (i.e. last block comes first). - pub fn key_changes( - &self, - first: NumberFor, - last: BlockId, - storage_key: Option<&StorageKey>, - key: &StorageKey - ) -> error::Result, u32)>> { - let (config, storage) = self.require_changes_trie()?; - let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; - let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?; - - // FIXME: remove this in https://github.com/paritytech/substrate/pull/3201 - let config_range = ChangesTrieConfigurationRange { - config: &config, - zero: Zero::zero(), - end: None, - }; - - key_changes::( - config_range, - &*storage, - first, - &ChangesTrieAnchorBlockId { - hash: convert_hash(&last_hash), - number: last_number, - }, - self.backend.blockchain().info().best_number, - storage_key.as_ref().map(|sk| sk.0.as_slice()), - &key.0) - .and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::>()) - .map_err(|err| error::Error::ChangesTrieAccessFailed(err)) - } - - /// Get proof for computation of (block, extrinsic) pairs where key has been changed at given blocks range. - /// `min` is the hash of the first block, which changes trie root is known to the requester - when we're using - /// changes tries from ascendants of this block, we should provide proofs for changes tries roots - /// `max` is the hash of the last block known to the requester - we can't use changes tries from descendants - /// of this block. - /// Works only for runtimes that are supporting changes tries. - pub fn key_changes_proof( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&StorageKey>, - key: &StorageKey, - ) -> error::Result> { - self.key_changes_proof_with_cht_size( - first, - last, - min, - max, - storage_key, - key, - cht::size(), - ) - } - - /// Does the same work as `key_changes_proof`, but assumes that CHTs are of passed size. - pub fn key_changes_proof_with_cht_size( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&StorageKey>, - key: &StorageKey, - cht_size: NumberFor, - ) -> error::Result> { - struct AccessedRootsRecorder<'a, Block: BlockT> { - storage: &'a dyn ChangesTrieStorage>, - min: NumberFor, - required_roots_proofs: Mutex, H256>>, - }; - - impl<'a, Block: BlockT> ChangesTrieRootsStorage> for AccessedRootsRecorder<'a, Block> { - fn build_anchor(&self, hash: H256) -> Result>, String> { - self.storage.build_anchor(hash) - } - - fn root( - &self, - anchor: &ChangesTrieAnchorBlockId>, - block: NumberFor, - ) -> Result, String> { - let root = self.storage.root(anchor, block)?; - if block < self.min { - if let Some(ref root) = root { - self.required_roots_proofs.lock().insert( - block, - root.clone() - ); - } - } - Ok(root) - } - } - - impl<'a, Block: BlockT> ChangesTrieStorage> for AccessedRootsRecorder<'a, Block> { - fn as_roots_storage(&self) -> &dyn state_machine::ChangesTrieRootsStorage> { - self - } - - fn with_cached_changed_keys( - &self, - root: &H256, - functor: &mut dyn FnMut(&HashMap>, HashSet>>), - ) -> bool { - self.storage.with_cached_changed_keys(root, functor) - } - - fn get(&self, key: &H256, prefix: Prefix) -> Result, String> { - self.storage.get(key, prefix) - } - } - - 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, - required_roots_proofs: Mutex::new(BTreeMap::new()), - }; - - let max_number = ::std::cmp::min( - self.backend.blockchain().info().best_number, - self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(max))?, - ); - - // FIXME: remove this in https://github.com/paritytech/substrate/pull/3201 - let config_range = ChangesTrieConfigurationRange { - config: &config, - zero: Zero::zero(), - end: None, - }; - - // fetch key changes proof - let first_number = self.backend.blockchain() - .expect_block_number_from_id(&BlockId::Hash(first))?; - let last_number = self.backend.blockchain() - .expect_block_number_from_id(&BlockId::Hash(last))?; - let key_changes_proof = key_changes_proof::( - config_range, - &recording_storage, - first_number, - &ChangesTrieAnchorBlockId { - hash: convert_hash(&last), - number: last_number, - }, - max_number, - storage_key.as_ref().map(|sk| sk.0.as_slice()), - &key.0, - ) - .map_err(|err| error::Error::from(error::Error::ChangesTrieAccessFailed(err)))?; - - // now gather proofs for all changes tries roots that were touched during key_changes_proof - // execution AND are unknown (i.e. replaced with CHT) to the requester - let roots = recording_storage.required_roots_proofs.into_inner(); - let roots_proof = self.changes_trie_roots_proof(cht_size, roots.keys().cloned())?; - - Ok(ChangesProof { - max_block: max_number, - proof: key_changes_proof, - roots: roots.into_iter().map(|(n, h)| (n, convert_hash(&h))).collect(), - roots_proof, - }) - } - - /// Generate CHT-based proof for roots of changes tries at given blocks. - fn changes_trie_roots_proof>>( - &self, - cht_size: NumberFor, - blocks: I - ) -> error::Result>> { - // most probably we have touched several changes tries that are parts of the single CHT - // => GroupBy changes tries by CHT number and then gather proof for the whole group at once - let mut proof = HashSet::new(); - - cht::for_each_cht_group::(cht_size, blocks, |_, cht_num, cht_blocks| { - let cht_proof = self.changes_trie_roots_proof_at_cht(cht_size, cht_num, cht_blocks)?; - proof.extend(cht_proof); - Ok(()) - }, ())?; - - Ok(proof.into_iter().collect()) - } - - /// Generates CHT-based proof for roots of changes tries at given blocks (that are part of single CHT). - fn changes_trie_roots_proof_at_cht( - &self, - cht_size: NumberFor, - cht_num: NumberFor, - blocks: Vec> - ) -> error::Result>> { - let cht_start = cht::start_number(cht_size, cht_num); - let mut current_num = cht_start; - let cht_range = ::std::iter::from_fn(|| { - let old_current_num = current_num; - current_num = current_num + One::one(); - Some(old_current_num) - }); - let roots = cht_range - .map(|num| self.header(&BlockId::Number(num)) - .map(|block| block.and_then(|block| block.digest().log(DigestItem::as_changes_trie_root).cloned()))); - let proof = cht::build_proof::(cht_size, cht_num, blocks, roots)?; - Ok(proof) - } - - /// Returns changes trie 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::Error::ChangesTriesNotSupported.into()), - } - } - - /// Create a new block, built on the head of the chain. - pub fn new_block( - &self, - inherent_digests: DigestFor, - ) -> error::Result> where - E: Clone + Send + Sync, - RA: Send + Sync, - Self: ProvideRuntimeApi, - ::Api: BlockBuilderAPI - { - block_builder::BlockBuilder::new(self, inherent_digests) - } - - /// Create a new block, built on top of `parent`. - pub fn new_block_at( - &self, - parent: &BlockId, - inherent_digests: DigestFor, - ) -> error::Result> where - E: Clone + Send + Sync, - RA: Send + Sync, - Self: ProvideRuntimeApi, - ::Api: BlockBuilderAPI - { - block_builder::BlockBuilder::at_block(parent, &self, false, inherent_digests) - } - - /// Create a new block, built on top of `parent` with proof recording enabled. - /// - /// While proof recording is enabled, all accessed trie nodes are saved. - /// These recorded trie nodes can be used by a third party to proof the - /// output of this block builder without having access to the full storage. - pub fn new_block_at_with_proof_recording( - &self, - parent: &BlockId, - inherent_digests: DigestFor, - ) -> error::Result> where - E: Clone + Send + Sync, - RA: Send + Sync, - Self: ProvideRuntimeApi, - ::Api: BlockBuilderAPI - { - block_builder::BlockBuilder::at_block(parent, &self, true, inherent_digests) - } - - /// 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.backend.get_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 - } - - /// Apply a checked and validated block to an operation. If a justification is provided - /// then `finalized` *must* be true. - fn apply_block( - &self, - operation: &mut ClientImportOperation, - import_block: BlockImportParams, - new_cache: HashMap>, - ) -> error::Result where - E: CallExecutor + Send + Sync + Clone, - { - let BlockImportParams { - 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 = (*import_headers.post().number()).saturated_into::(); - - *self.importing_block.write() = Some(hash); - - let result = self.execute_and_import_block( - operation, - origin, - hash, - import_headers, - justification, - body, - new_cache, - finalized, - auxiliary, - fork_choice, - ); - - if let Ok(ImportResult::Imported(ref aux)) = result { - if aux.is_new_best { - telemetry!(SUBSTRATE_INFO; "block.import"; - "height" => height, - "best" => ?hash, - "origin" => ?origin - ); - } - } - - result - } - - fn execute_and_import_block( - &self, - operation: &mut ClientImportOperation, - origin: BlockOrigin, - hash: Block::Hash, - import_headers: PrePostHeader, - justification: Option, - body: Option>, - new_cache: HashMap>, - finalized: bool, - aux: Vec<(Vec, Option>)>, - fork_choice: ForkChoiceStrategy, - ) -> error::Result where - E: CallExecutor + Send + Sync + Clone, - { - let parent_hash = import_headers.post().parent_hash().clone(); - match self.backend.blockchain().status(BlockId::Hash(hash))? { - blockchain::BlockStatus::InChain => return Ok(ImportResult::AlreadyInChain), - blockchain::BlockStatus::Unknown => {}, - } - - let info = self.backend.blockchain().info(); - - // the block is lower than our last finalized block so it must revert - // finality, refusing import. - if *import_headers.post().number() <= info.finalized_number { - return Err(error::Error::NotInFinalizedChain); - } - - // this is a fairly arbitrary choice of where to draw the line on making notifications, - // but the general goal is to only make notifications when we are already fully synced - // and get a new chain head. - let make_notifications = match origin { - BlockOrigin::NetworkBroadcast | BlockOrigin::Own | BlockOrigin::ConsensusBroadcast => true, - BlockOrigin::Genesis | BlockOrigin::NetworkInitialSync | BlockOrigin::File => false, - }; - - self.backend.begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?; - - // ensure parent block is finalized to maintain invariant that - // finality is called sequentially. - if finalized { - self.apply_finality_with_block_hash(operation, parent_hash, None, info.best_hash, make_notifications)?; - } - - // 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(), - )?; - - let is_new_best = finalized || match fork_choice { - ForkChoiceStrategy::LongestChain => import_headers.post().number() > &info.best_number, - ForkChoiceStrategy::Custom(v) => v, - }; - - let leaf_state = if finalized { - crate::backend::NewBlockState::Final - } else if is_new_best { - crate::backend::NewBlockState::Best - } else { - crate::backend::NewBlockState::Normal - }; - - let retracted = if is_new_best { - let route_from_best = header_metadata::tree_route( - self.backend.blockchain(), - info.best_hash, - parent_hash, - )?; - route_from_best.retracted().iter().rev().map(|e| e.hash.clone()).collect() - } else { - Vec::default() - }; - - trace!("Imported {}, (#{}), best={}, origin={:?}", hash, import_headers.post().number(), is_new_best, origin); - - operation.op.set_block_data( - import_headers.post().clone(), - body, - justification, - leaf_state, - )?; - - operation.op.update_cache(new_cache); - if let Some(storage_update) = storage_update { - operation.op.update_db_storage(storage_update)?; - } - if let Some(storage_changes) = storage_changes.clone() { - operation.op.update_storage(storage_changes.0, storage_changes.1)?; - } - if let Some(Some(changes_update)) = changes_update { - operation.op.update_changes_trie(changes_update)?; - } - - operation.op.insert_aux(aux)?; - - if make_notifications { - if finalized { - operation.notify_finalized.push(hash); - } - - operation.notify_imported = Some(ImportSummary { - hash, - origin, - header: import_headers.into_post(), - is_new_best, - storage_changes, - retracted, - }) - } - - Ok(ImportResult::imported(is_new_best)) - } - - fn block_execution( - &self, - transaction: &B::BlockImportOperation, - import_headers: &PrePostHeader, - origin: BlockOrigin, - hash: Block::Hash, - body: Option>, - ) -> error::Result<( - Option>, - Option>>, - Option<( - Vec<(Vec, Option>)>, - Vec<(Vec, Vec<(Vec, 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(BackendTrustLevel::Trusted), - 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 encoded_block = ::encode_from( - import_headers.pre(), - &body.unwrap_or_default() - ); - - let (_, storage_update, changes_update) = self.executor - .call_at_state::<_, _, NeverNativeValue, fn() -> _>( - transaction_state, - &mut overlay, - "Core_execute_block", - &encoded_block, - match origin { - BlockOrigin::NetworkInitialSync => get_execution_manager( - self.execution_strategies().syncing, - ), - _ => get_execution_manager(self.execution_strategies().importing), - }, - None, - None, - )?; - - overlay.commit_prospective(); - - let (top, children) = overlay.into_committed(); - let children = children.map(|(sk, it)| (sk, it.collect())).collect(); - if import_headers.post().state_root() != &storage_update.1 { - return Err(error::Error::InvalidStateRoot); - } - - Ok((Some(storage_update.0), Some(changes_update), Some((top.collect(), children)))) - }, - None => Ok((None, None, None)) - } - } - - fn apply_finality_with_block_hash( - &self, - operation: &mut ClientImportOperation, - block: Block::Hash, - justification: Option, - best_block: Block::Hash, - notify: bool, - ) -> error::Result<()> { - // find tree route from last finalized to given block. - let last_finalized = self.backend.blockchain().last_finalized()?; - - if block == last_finalized { - warn!("Possible safety violation: attempted to re-finalize last finalized block {:?} ", last_finalized); - return Ok(()); - } - - let route_from_finalized = header_metadata::tree_route(self.backend.blockchain(), last_finalized, block)?; - - if let Some(retracted) = route_from_finalized.retracted().get(0) { - warn!("Safety violation: attempted to revert finalized block {:?} which is not in the \ - same chain as last finalized {:?}", retracted, last_finalized); - - return Err(error::Error::NotInFinalizedChain); - } - - let route_from_best = header_metadata::tree_route(self.backend.blockchain(), best_block, block)?; - - // if the block is not a direct ancestor of the current best chain, - // then some other block is the common ancestor. - if route_from_best.common_block().hash != block { - // NOTE: we're setting the finalized block as best block, this might - // be slightly inaccurate since we might have a "better" block - // further along this chain, but since best chain selection logic is - // pluggable we cannot make a better choice here. usages that need - // an accurate "best" block need to go through `SelectChain` - // instead. - operation.op.mark_head(BlockId::Hash(block))?; - } - - let enacted = route_from_finalized.enacted(); - assert!(enacted.len() > 0); - for finalize_new in &enacted[..enacted.len() - 1] { - operation.op.mark_finalized(BlockId::Hash(finalize_new.hash), None)?; - } - - assert_eq!(enacted.last().map(|e| e.hash), Some(block)); - operation.op.mark_finalized(BlockId::Hash(block), justification)?; - - if notify { - // sometimes when syncing, tons of blocks can be finalized at once. - // we'll send notifications spuriously in that case. - const MAX_TO_NOTIFY: usize = 256; - let enacted = route_from_finalized.enacted(); - let start = enacted.len() - ::std::cmp::min(enacted.len(), MAX_TO_NOTIFY); - for finalized in &enacted[start..] { - operation.notify_finalized.push(finalized.hash); - } - } - - Ok(()) - } - - fn notify_finalized( - &self, - notify_finalized: Vec, - ) -> 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"); - - telemetry!(SUBSTRATE_INFO; "notify.finalized"; - "height" => format!("{}", header.number()), - "best" => ?finalized_hash, - ); - - let notification = FinalityNotification { - header, - hash: finalized_hash, - }; - - sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); - } - - Ok(()) - } - - fn notify_imported(&self, notify_import: ImportSummary) -> error::Result<()> { - if let Some(storage_changes) = notify_import.storage_changes { - // TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes? - self.storage_notifications.lock() - .trigger( - ¬ify_import.hash, - storage_changes.0.into_iter(), - storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())), - ); - } - - let notification = BlockImportNotification:: { - hash: notify_import.hash, - origin: notify_import.origin, - header: notify_import.header, - is_new_best: notify_import.is_new_best, - retracted: notify_import.retracted, - }; - - self.import_notification_sinks.lock() - .retain(|sink| sink.unbounded_send(notification.clone()).is_ok()); - - Ok(()) - } - - /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were - /// successfully reverted. - pub fn revert(&self, n: NumberFor) -> error::Result> { - Ok(self.backend.revert(n)?) - } - - /// Get blockchain info. - pub fn info(&self) -> ClientInfo { - let info = self.backend.blockchain().info(); - ClientInfo { - chain: info, - used_state_cache_size: self.backend.used_state_cache_size(), - } - } - - /// Get block status. - pub fn block_status(&self, id: &BlockId) -> error::Result { - // this can probably be implemented more efficiently - if let BlockId::Hash(ref h) = id { - if self.importing_block.read().as_ref().map_or(false, |importing| h == importing) { - return Ok(BlockStatus::Queued); - } - } - let hash_and_number = match id.clone() { - BlockId::Hash(hash) => self.backend.blockchain().number(hash)?.map(|n| (hash, n)), - BlockId::Number(n) => self.backend.blockchain().hash(n)?.map(|hash| (hash, n)), - }; - match hash_and_number { - Some((hash, number)) => { - if self.backend.have_state_at(&hash, number) { - Ok(BlockStatus::InChainWithState) - } else { - Ok(BlockStatus::InChainPruned) - } - } - None => Ok(BlockStatus::Unknown), - } - } - - /// Get block header by id. - pub fn header(&self, id: &BlockId) -> error::Result::Header>> { - self.backend.blockchain().header(*id) - } - - /// Get block body by id. - pub fn body(&self, id: &BlockId) -> error::Result::Extrinsic>>> { - self.backend.blockchain().body(*id) - } - - /// Get block justification set by id. - pub fn justification(&self, id: &BlockId) -> error::Result> { - self.backend.blockchain().justification(*id) - } - - /// Get full block by id. - pub fn block(&self, id: &BlockId) - -> error::Result>> - { - Ok(match (self.header(id)?, self.body(id)?, self.justification(id)?) { - (Some(header), Some(extrinsics), justification) => - Some(SignedBlock { block: Block::new(header, extrinsics), justification }), - _ => None, - }) - } - - /// 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(Error::UnknownBlock(format!("{:?}", id))), - } - }; - - let genesis_hash = self.backend.blockchain().info().genesis_hash; - if genesis_hash == target_hash { return Ok(Vec::new()); } - - let mut current_hash = target_hash; - let mut current = load_header(current_hash)?; - let mut ancestor_hash = *current.parent_hash(); - let mut ancestor = load_header(ancestor_hash)?; - let mut uncles = Vec::new(); - - for _generation in 0..max_generation.saturated_into() { - let children = self.backend.blockchain().children(ancestor_hash)?; - uncles.extend(children.into_iter().filter(|h| h != ¤t_hash)); - current_hash = ancestor_hash; - if genesis_hash == current_hash { break; } - current = ancestor; - ancestor_hash = *current.parent_hash(); - ancestor = load_header(ancestor_hash)?; - } - trace!("Collected {} uncles", uncles.len()); - Ok(uncles) - } - - fn changes_trie_config(&self) -> Result, Error> { - Ok(self.backend.state_at(BlockId::Number(self.backend.blockchain().info().best_number))? - .storage(well_known_keys::CHANGES_TRIE_CONFIG) - .map_err(|e| error::Error::from_state(Box::new(e)))? - .and_then(|c| Decode::decode(&mut &*c).ok())) - } - - /// Prepare in-memory header that is used in execution environment. - fn prepare_environment_block(&self, parent: &BlockId) -> error::Result { - let parent_header = self.backend.blockchain().expect_header(*parent)?; - Ok(<::Header as HeaderT>::new( - self.backend.blockchain().expect_block_number_from_id(parent)? + One::one(), - Default::default(), - Default::default(), - parent_header.hash(), - Default::default(), - )) - } -} - -impl HeaderMetadata for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - type Error = error::Error; - - fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { - self.backend.blockchain().header_metadata(hash) - } - - fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { - self.backend.blockchain().insert_header_metadata(hash, metadata) - } - - fn remove_header_metadata(&self, hash: Block::Hash) { - self.backend.blockchain().remove_header_metadata(hash) - } -} - -impl ProvideUncles for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - fn uncles(&self, target_hash: Block::Hash, max_generation: NumberFor) -> error::Result> { - Ok(Client::uncles(self, target_hash, max_generation)? - .into_iter() - .filter_map(|hash| Client::header(self, &BlockId::Hash(hash)).unwrap_or(None)) - .collect() - ) - } -} - -impl ChainHeaderBackend for Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, - RA: Send + Sync -{ - fn header(&self, id: BlockId) -> error::Result> { - self.backend.blockchain().header(id) - } - - fn info(&self) -> blockchain::Info { - self.backend.blockchain().info() - } - - fn status(&self, id: BlockId) -> error::Result { - self.backend.blockchain().status(id) - } - - fn number(&self, hash: Block::Hash) -> error::Result::Header as HeaderT>::Number>> { - self.backend.blockchain().number(hash) - } - - fn hash(&self, number: NumberFor) -> error::Result> { - self.backend.blockchain().hash(number) - } -} - -impl ChainHeaderBackend for &Client where - B: backend::Backend, - E: CallExecutor + Send + Sync, - Block: BlockT, - RA: Send + Sync, -{ - fn header(&self, id: BlockId) -> error::Result> { - (**self).backend.blockchain().header(id) - } - - fn info(&self) -> blockchain::Info { - (**self).backend.blockchain().info() - } - - fn status(&self, id: BlockId) -> error::Result { - (**self).status(id) - } - - fn number(&self, hash: Block::Hash) -> error::Result::Header as HeaderT>::Number>> { - (**self).number(hash) - } - - fn hash(&self, number: NumberFor) -> error::Result> { - (**self).hash(number) - } -} - -impl ProvideCache for Client where - B: backend::Backend, - Block: BlockT, -{ - fn cache(&self) -> Option>> { - self.backend.blockchain().cache() - } -} - -impl ProvideRuntimeApi for Client where - B: backend::Backend, - E: CallExecutor + Clone + Send + Sync, - Block: BlockT, - RA: ConstructRuntimeApi -{ - type Api = >::RuntimeApi; - - fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { - RA::construct_runtime_api(self) - } -} - -impl CallRuntimeAt for Client where - B: backend::Backend, - E: CallExecutor + Clone + Send + Sync, - Block: BlockT, -{ - fn call_api_at< - 'a, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - C: CoreApi, - >( - &self, - core_api: &C, - at: &BlockId, - function: &'static str, - args: Vec, - changes: &RefCell, - initialize_block: InitializeBlock<'a, Block>, - native_call: Option, - context: ExecutionContext, - recorder: &Option>>>, - ) -> 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::OffchainCall(Some((_, capabilities))) if capabilities.has_all() => - self.execution_strategies.offchain_worker.get_manager(), - ExecutionContext::OffchainCall(_) => - self.execution_strategies.other.get_manager(), - }; - - let capabilities = context.capabilities(); - let offchain_extensions = if let ExecutionContext::OffchainCall(Some(ext)) = context { - Some(OffchainExt::new(offchain::LimitedExternalities::new(capabilities, ext.0))) - } else { - None - }; - - self.executor.contextual_call::<_, fn(_,_) -> _,_,_>( - || core_api.initialize_block(at, &self.prepare_environment_block(at)?), - at, - function, - &args, - changes, - initialize_block, - manager, - native_call, - offchain_extensions, - recorder, - capabilities.has(offchain::Capability::Keystore), - ) - } - - fn runtime_version_at(&self, at: &BlockId) -> error::Result { - self.runtime_version_at(at) - } -} - -/// NOTE: only use this implementation when you are sure there are NO consensus-level BlockImport -/// objects. Otherwise, importing blocks directly into the client would be bypassing -/// important verification work. -impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client where - B: backend::Backend, - E: CallExecutor + Clone + Send + Sync, - Block: BlockT, -{ - type Error = ConsensusError; - - /// Import a checked and validated block. If a justification is provided in - /// `BlockImportParams` then `finalized` *must* be true. - /// - /// NOTE: only use this implementation when there are NO consensus-level BlockImport - /// objects. Otherwise, importing blocks directly into the client would be bypassing - /// important verification work. - /// - /// If you are not sure that there are no BlockImport objects provided by the consensus - /// algorithm, don't use this function. - fn import_block( - &mut self, - import_block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - self.lock_import_and_run(|operation| { - self.apply_block(operation, import_block, new_cache) - }).map_err(|e| { - warn!("Block import error:\n{:?}", e); - ConsensusError::ClientImport(e.to_string()).into() - }) - } - - /// Check block preconditions. - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - let BlockCheckParams { hash, number, parent_hash } = block; - - if let Some(h) = self.fork_blocks.as_ref().and_then(|x| x.get(&number)) { - if &hash != h { - trace!( - "Rejecting block from known invalid fork. Got {:?}, expected: {:?} at height {}", - hash, - h, - number - ); - return Ok(ImportResult::KnownBad); - } - } - - match self.block_status(&BlockId::Hash(parent_hash)) - .map_err(|e| ConsensusError::ClientImport(e.to_string()))? - { - BlockStatus::InChainWithState | BlockStatus::Queued => {}, - BlockStatus::Unknown | BlockStatus::InChainPruned => return Ok(ImportResult::UnknownParent), - BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), - } - - match self.block_status(&BlockId::Hash(hash)) - .map_err(|e| ConsensusError::ClientImport(e.to_string()))? - { - BlockStatus::InChainWithState | BlockStatus::Queued => return Ok(ImportResult::AlreadyInChain), - BlockStatus::Unknown | BlockStatus::InChainPruned => {}, - BlockStatus::KnownBad => return Ok(ImportResult::KnownBad), - } - - - Ok(ImportResult::imported(false)) - } -} - -impl consensus::BlockImport for Client where - B: backend::Backend, - E: CallExecutor + Clone + Send + Sync, - Block: BlockT, -{ - type Error = ConsensusError; - - fn import_block( - &mut self, - import_block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - (&*self).import_block(import_block, new_cache) - } - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - (&*self).check_block(block) - } -} - -impl Finalizer for Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - fn apply_finality( - &self, - operation: &mut ClientImportOperation, - id: BlockId, - justification: Option, - notify: bool, - ) -> error::Result<()> { - let last_best = self.backend.blockchain().info().best_hash; - let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?; - self.apply_finality_with_block_hash(operation, to_finalize_hash, justification, last_best, notify) - } - - fn finalize_block(&self, id: BlockId, justification: Option, notify: bool) -> error::Result<()> { - self.lock_import_and_run(|operation| { - self.apply_finality(operation, id, justification, notify) - }) - } -} - -impl Finalizer for &Client where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - fn apply_finality( - &self, - operation: &mut ClientImportOperation, - id: BlockId, - justification: Option, - notify: bool, - ) -> error::Result<()> { - (**self).apply_finality(operation, id, justification, notify) - } - - fn finalize_block(&self, id: BlockId, justification: Option, notify: bool) -> error::Result<()> { - (**self).finalize_block(id, justification, notify) - } -} - -impl BlockchainEvents for Client -where - E: CallExecutor, - Block: BlockT, -{ - /// Get block import event stream. - fn import_notification_stream(&self) -> ImportNotifications { - let (sink, stream) = mpsc::unbounded(); - self.import_notification_sinks.lock().push(sink); - stream - } - - fn finality_notification_stream(&self) -> FinalityNotifications { - let (sink, stream) = mpsc::unbounded(); - self.finality_notification_sinks.lock().push(sink); - stream - } - - /// Get storage changes event stream. - fn storage_changes_notification_stream( - &self, - filter_keys: Option<&[StorageKey]>, - child_filter_keys: Option<&[(StorageKey, Option>)]>, - ) -> error::Result> { - Ok(self.storage_notifications.lock().listen(filter_keys, child_filter_keys)) - } -} - -/// Implement Longest Chain Select implementation -/// where 'longest' is defined as the highest number of blocks -pub struct LongestChain { - backend: Arc, - _phantom: PhantomData -} - -impl Clone for LongestChain { - fn clone(&self) -> Self { - let backend = self.backend.clone(); - LongestChain { - backend, - _phantom: Default::default() - } - } -} - -impl LongestChain -where - B: backend::Backend, - Block: BlockT, -{ - /// Instantiate a new LongestChain for Backend B - pub fn new(backend: Arc) -> Self { - LongestChain { - backend, - _phantom: Default::default() - } - } - - fn best_block_header(&self) -> error::Result<::Header> { - let info = self.backend.blockchain().info(); - let import_lock = self.backend.get_import_lock(); - let best_hash = self.backend.blockchain().best_containing(info.best_hash, None, import_lock)? - .unwrap_or(info.best_hash); - - Ok(self.backend.blockchain().header(BlockId::Hash(best_hash))? - .expect("given block hash was fetched from block in db; qed")) - } - - fn leaves(&self) -> Result::Hash>, error::Error> { - self.backend.blockchain().leaves() - } -} - -impl SelectChain for LongestChain -where - B: backend::Backend, - Block: BlockT, -{ - - fn leaves(&self) -> Result::Hash>, ConsensusError> { - LongestChain::leaves(self) - .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) - } - - fn best_chain(&self) - -> Result<::Header, ConsensusError> - { - LongestChain::best_block_header(&self) - .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) - } - - fn finality_target( - &self, - target_hash: Block::Hash, - maybe_max_number: Option> - ) -> Result, ConsensusError> { - let import_lock = self.backend.get_import_lock(); - self.backend.blockchain().best_containing(target_hash, maybe_max_number, import_lock) - .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) - } -} - -impl BlockBody for Client - where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - fn block_body(&self, id: &BlockId) -> error::Result::Extrinsic>>> { - self.body(id) - } -} - -impl backend::AuxStore for Client - where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - /// Insert auxiliary data into key-value store. - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> error::Result<()> { - // Import is locked here because we may have other block import - // operations that tries to set aux data. Note that for consensus - // layer, one can always use atomic operations to make sure - // import is only locked once. - self.lock_import_and_run(|operation| { - apply_aux(operation, insert, delete) - }) - } - /// Query auxiliary data from key-value store. - fn get_aux(&self, key: &[u8]) -> error::Result>> { - crate::backend::AuxStore::get_aux(&*self.backend, key) - } -} - - -impl backend::AuxStore for &Client - where - B: backend::Backend, - E: CallExecutor, - Block: BlockT, -{ - - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> error::Result<()> { - (**self).insert_aux(insert, delete) - } - - fn get_aux(&self, key: &[u8]) -> error::Result>> { - (**self).get_aux(key) - } -} - -/// Helper function to apply auxiliary data insertion into an operation. -pub fn apply_aux<'a, 'b: 'a, 'c: 'a, B, Block, H, D, I>( - operation: &mut ClientImportOperation, - insert: I, - delete: D -) -> error::Result<()> -where - Block: BlockT, - H: Hasher, - B: backend::Backend, - I: IntoIterator, - D: IntoIterator, -{ - operation.op.insert_aux( - insert.into_iter() - .map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) - .chain(delete.into_iter().map(|k| (k.to_vec(), None))) - ) -} - -/// Utility methods for the client. -pub mod utils { - use super::*; - use crate::error; - use primitives::H256; - use std::borrow::Borrow; - - /// Returns a function for checking block ancestry, the returned function will - /// return `true` if the given hash (second parameter) is a descendent of the - /// 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, Block: BlockT, T, H: Borrow + 'a>( - client: &'a T, - current: Option<(H, H)>, - ) -> impl Fn(&H256, &H256) -> Result + 'a - where T: ChainHeaderBackend + HeaderMetadata, - { - move |base, hash| { - if base == hash { return Ok(false); } - - let current = current.as_ref().map(|(c, p)| (c.borrow(), p.borrow())); - - let mut hash = hash; - if let Some((current_hash, current_parent_hash)) = current { - if base == current_hash { return Ok(false); } - if hash == current_hash { - if base == current_parent_hash { - return Ok(true); - } else { - hash = current_parent_hash; - } - } - } - - let ancestor = header_metadata::lowest_common_ancestor(client, *hash, *base)?; - - Ok(ancestor.hash == *base) - } - } -} - -impl consensus::block_validation::Chain for Client - where BE: backend::Backend, - E: CallExecutor, - B: BlockT -{ - fn block_status(&self, id: &BlockId) -> Result> { - Client::block_status(self, id).map_err(|e| Box::new(e) as Box<_>) - } -} - -#[cfg(test)] -pub(crate) mod tests { - use std::collections::HashMap; - use super::*; - use primitives::blake2_256; - use sr_primitives::DigestItem; - use consensus::{BlockOrigin, SelectChain}; - use test_client::{ - prelude::*, - client_db::{Backend, DatabaseSettings, PruningMode}, - runtime::{self, Block, Transfer, RuntimeApi, TestAPI}, - }; - - /// Returns tuple, consisting of: - /// 1) test client pre-filled with blocks changing balances; - /// 2) roots of changes tries for these blocks - /// 3) test cases in form (begin, end, key, vec![(block, extrinsic)]) that are required to pass - pub fn prepare_client_with_key_changes() -> ( - test_client::client::Client, - Vec, - Vec<(u64, u64, Vec, Vec<(u64, u32)>)>, - ) { - // prepare block structure - let blocks_transfers = vec![ - vec![(AccountKeyring::Alice, AccountKeyring::Dave), (AccountKeyring::Bob, AccountKeyring::Dave)], - vec![(AccountKeyring::Charlie, AccountKeyring::Eve)], - vec![], - vec![(AccountKeyring::Alice, AccountKeyring::Dave)], - ]; - - // prepare client ang import blocks - let mut local_roots = Vec::new(); - let remote_client = TestClientBuilder::new().set_support_changes_trie(true).build(); - let mut nonces: HashMap<_, u64> = Default::default(); - for (i, block_transfers) in blocks_transfers.into_iter().enumerate() { - let mut builder = remote_client.new_block(Default::default()).unwrap(); - for (from, to) in block_transfers { - builder.push_transfer(Transfer { - from: from.into(), - to: to.into(), - amount: 1, - nonce: *nonces.entry(from).and_modify(|n| { *n = *n + 1 }).or_default(), - }).unwrap(); - } - remote_client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - - let header = remote_client.header(&BlockId::Number(i as u64 + 1)).unwrap().unwrap(); - let trie_root = header.digest().log(DigestItem::as_changes_trie_root) - .map(|root| H256::from_slice(root.as_ref())) - .unwrap(); - local_roots.push(trie_root); - } - - // prepare test cases - let alice = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())).to_vec(); - let bob = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Bob.into())).to_vec(); - let charlie = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Charlie.into())).to_vec(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let eve = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Eve.into())).to_vec(); - let ferdie = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Ferdie.into())).to_vec(); - let test_cases = vec![ - (1, 4, alice.clone(), vec![(4, 0), (1, 0)]), - (1, 3, alice.clone(), vec![(1, 0)]), - (2, 4, alice.clone(), vec![(4, 0)]), - (2, 3, alice.clone(), vec![]), - - (1, 4, bob.clone(), vec![(1, 1)]), - (1, 1, bob.clone(), vec![(1, 1)]), - (2, 4, bob.clone(), vec![]), - - (1, 4, charlie.clone(), vec![(2, 0)]), - - (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - (1, 1, dave.clone(), vec![(1, 1), (1, 0)]), - (3, 4, dave.clone(), vec![(4, 0)]), - - (1, 4, eve.clone(), vec![(2, 0)]), - (1, 1, eve.clone(), vec![]), - (3, 4, eve.clone(), vec![]), - - (1, 4, ferdie.clone(), vec![]), - ]; - - (remote_client, local_roots, test_cases) - } - - #[test] - fn client_initializes_from_genesis_ok() { - let client = test_client::new(); - - assert_eq!( - client.runtime_api().balance_of( - &BlockId::Number(client.info().chain.best_number), - AccountKeyring::Alice.into() - ).unwrap(), - 1000 - ); - assert_eq!( - client.runtime_api().balance_of( - &BlockId::Number(client.info().chain.best_number), - AccountKeyring::Ferdie.into() - ).unwrap(), - 0 - ); - } - - #[test] - fn block_builder_works_with_no_transactions() { - let client = test_client::new(); - - let builder = client.new_block(Default::default()).unwrap(); - - client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - - assert_eq!(client.info().chain.best_number, 1); - } - - #[test] - fn block_builder_works_with_transactions() { - let client = test_client::new(); - - let mut builder = client.new_block(Default::default()).unwrap(); - - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 42, - nonce: 0, - }).unwrap(); - - client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - - assert_eq!(client.info().chain.best_number, 1); - assert_ne!( - client.state_at(&BlockId::Number(1)).unwrap().pairs(), - client.state_at(&BlockId::Number(0)).unwrap().pairs() - ); - assert_eq!( - client.runtime_api().balance_of( - &BlockId::Number(client.info().chain.best_number), - AccountKeyring::Alice.into() - ).unwrap(), - 958 - ); - assert_eq!( - client.runtime_api().balance_of( - &BlockId::Number(client.info().chain.best_number), - AccountKeyring::Ferdie.into() - ).unwrap(), - 42 - ); - } - - #[test] - fn block_builder_does_not_include_invalid() { - let client = test_client::new(); - - let mut builder = client.new_block(Default::default()).unwrap(); - - builder.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 42, - nonce: 0, - }).unwrap(); - - assert!(builder.push_transfer(Transfer { - from: AccountKeyring::Eve.into(), - to: AccountKeyring::Alice.into(), - amount: 42, - nonce: 0, - }).is_err()); - - client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - - assert_eq!(client.info().chain.best_number, 1); - assert_ne!( - client.state_at(&BlockId::Number(1)).unwrap().pairs(), - client.state_at(&BlockId::Number(0)).unwrap().pairs() - ); - assert_eq!(client.body(&BlockId::Number(1)).unwrap().unwrap().len(), 1) - } - - #[test] - fn best_containing_with_genesis_block() { - // block tree: - // G - - let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - let genesis_hash = client.info().chain.genesis_hash; - - assert_eq!( - genesis_hash.clone(), - longest_chain_select.finality_target(genesis_hash.clone(), None).unwrap().unwrap() - ); - } - - #[test] - fn best_containing_with_hash_not_found() { - // block tree: - // G - - let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - let uninserted_block = client.new_block(Default::default()).unwrap().bake().unwrap(); - - assert_eq!( - None, - longest_chain_select.finality_target(uninserted_block.hash().clone(), None).unwrap() - ); - } - - #[test] - fn uncles_with_only_ancestors() { - // block tree: - // G -> A1 -> A2 - let client = test_client::new(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block(Default::default()).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(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a3.clone()).unwrap(); - - // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a4.clone()).unwrap(); - - // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a5.clone()).unwrap(); - - // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).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()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - - // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b4.clone()).unwrap(); - - // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).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()), Default::default()).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().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_on_longest_chain_with_single_chain_3_blocks() { - // block tree: - // G -> A1 -> A2 - - let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let genesis_hash = client.info().chain.genesis_hash; - - assert_eq!(a2.hash(), longest_chain_select.finality_target(genesis_hash, None).unwrap().unwrap()); - assert_eq!(a2.hash(), longest_chain_select.finality_target(a1.hash(), None).unwrap().unwrap()); - assert_eq!(a2.hash(), longest_chain_select.finality_target(a2.hash(), None).unwrap().unwrap()); - } - - #[test] - fn best_containing_on_longest_chain_with_multiple_forks() { - // block tree: - // G -> A1 -> A2 -> A3 -> A4 -> A5 - // A1 -> B2 -> B3 -> B4 - // B2 -> C3 - // A1 -> D2 - let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a3.clone()).unwrap(); - - // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a4.clone()).unwrap(); - - // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a5.clone()).unwrap(); - - // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).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()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - - // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b4.clone()).unwrap(); - - // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).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()), Default::default()).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(); - - assert_eq!(client.info().chain.best_hash, a5.hash()); - - let genesis_hash = client.info().chain.genesis_hash; - let leaves = longest_chain_select.leaves().unwrap(); - - assert!(leaves.contains(&a5.hash())); - assert!(leaves.contains(&b4.hash())); - assert!(leaves.contains(&c3.hash())); - assert!(leaves.contains(&d2.hash())); - assert_eq!(leaves.len(), 4); - - // search without restriction - - assert_eq!(a5.hash(), longest_chain_select.finality_target( - genesis_hash, None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a1.hash(), None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a2.hash(), None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a3.hash(), None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a4.hash(), None).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a5.hash(), None).unwrap().unwrap()); - - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b2.hash(), None).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b3.hash(), None).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b4.hash(), None).unwrap().unwrap()); - - assert_eq!(c3.hash(), longest_chain_select.finality_target( - c3.hash(), None).unwrap().unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), None).unwrap().unwrap()); - - - // search only blocks with number <= 5. equivalent to without restriction for this scenario - - assert_eq!(a5.hash(), longest_chain_select.finality_target( - genesis_hash, Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a1.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a2.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a3.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a4.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(a5.hash(), longest_chain_select.finality_target( - a5.hash(), Some(5)).unwrap().unwrap()); - - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b2.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b3.hash(), Some(5)).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b4.hash(), Some(5)).unwrap().unwrap()); - - assert_eq!(c3.hash(), longest_chain_select.finality_target( - c3.hash(), Some(5)).unwrap().unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), Some(5)).unwrap().unwrap()); - - - // search only blocks with number <= 4 - - assert_eq!(a4.hash(), longest_chain_select.finality_target( - genesis_hash, Some(4)).unwrap().unwrap()); - assert_eq!(a4.hash(), longest_chain_select.finality_target( - a1.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(a4.hash(), longest_chain_select.finality_target( - a2.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(a4.hash(), longest_chain_select.finality_target( - a3.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(a4.hash(), longest_chain_select.finality_target( - a4.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(4)).unwrap()); - - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b2.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b3.hash(), Some(4)).unwrap().unwrap()); - assert_eq!(b4.hash(), longest_chain_select.finality_target( - b4.hash(), Some(4)).unwrap().unwrap()); - - assert_eq!(c3.hash(), longest_chain_select.finality_target( - c3.hash(), Some(4)).unwrap().unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), Some(4)).unwrap().unwrap()); - - - // search only blocks with number <= 3 - - assert_eq!(a3.hash(), longest_chain_select.finality_target( - genesis_hash, Some(3)).unwrap().unwrap()); - assert_eq!(a3.hash(), longest_chain_select.finality_target( - a1.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(a3.hash(), longest_chain_select.finality_target( - a2.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(a3.hash(), longest_chain_select.finality_target( - a3.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a4.hash(), Some(3)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(3)).unwrap()); - - assert_eq!(b3.hash(), longest_chain_select.finality_target( - b2.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(b3.hash(), longest_chain_select.finality_target( - b3.hash(), Some(3)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b4.hash(), Some(3)).unwrap()); - - assert_eq!(c3.hash(), longest_chain_select.finality_target( - c3.hash(), Some(3)).unwrap().unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), Some(3)).unwrap().unwrap()); - - - // search only blocks with number <= 2 - - assert_eq!(a2.hash(), longest_chain_select.finality_target( - genesis_hash, Some(2)).unwrap().unwrap()); - assert_eq!(a2.hash(), longest_chain_select.finality_target( - a1.hash(), Some(2)).unwrap().unwrap()); - assert_eq!(a2.hash(), longest_chain_select.finality_target( - a2.hash(), Some(2)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a3.hash(), Some(2)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a4.hash(), Some(2)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(2)).unwrap()); - - assert_eq!(b2.hash(), longest_chain_select.finality_target( - b2.hash(), Some(2)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b3.hash(), Some(2)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b4.hash(), Some(2)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - c3.hash(), Some(2)).unwrap()); - - assert_eq!(d2.hash(), longest_chain_select.finality_target( - d2.hash(), Some(2)).unwrap().unwrap()); - - - // search only blocks with number <= 1 - - assert_eq!(a1.hash(), longest_chain_select.finality_target( - genesis_hash, Some(1)).unwrap().unwrap()); - assert_eq!(a1.hash(), longest_chain_select.finality_target( - a1.hash(), Some(1)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a2.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a3.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a4.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(1)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - b2.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b3.hash(), Some(1)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b4.hash(), Some(1)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - c3.hash(), Some(1)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - d2.hash(), Some(1)).unwrap()); - - // search only blocks with number <= 0 - - assert_eq!(genesis_hash, longest_chain_select.finality_target( - genesis_hash, Some(0)).unwrap().unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a1.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a2.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a3.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a4.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - a5.hash(), Some(0)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - b2.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b3.hash(), Some(0)).unwrap()); - assert_eq!(None, longest_chain_select.finality_target( - b4.hash(), Some(0)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - c3.hash().clone(), Some(0)).unwrap()); - - assert_eq!(None, longest_chain_select.finality_target( - d2.hash().clone(), Some(0)).unwrap()); - } - - #[test] - fn best_containing_on_longest_chain_with_max_depth_higher_than_best() { - // block tree: - // G -> A1 -> A2 - - let (client, longest_chain_select) = TestClientBuilder::new().build_with_longest_chain(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let genesis_hash = client.info().chain.genesis_hash; - - assert_eq!(a2.hash(), longest_chain_select.finality_target(genesis_hash, Some(10)).unwrap().unwrap()); - } - - #[test] - fn key_changes_works() { - let (client, _, test_cases) = prepare_client_with_key_changes(); - - for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { - let end = client.block_hash(end).unwrap().unwrap(); - let actual_result = client.key_changes( - begin, - BlockId::Hash(end), - None, - &StorageKey(key), - ).unwrap(); - match actual_result == expected_result { - true => (), - false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}", - index, actual_result, expected_result)), - } - } - } - - #[test] - fn import_with_justification() { - let client = test_client::new(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - // A2 -> A3 - let justification = vec![1, 2, 3]; - let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); - client.import_justified(BlockOrigin::Own, a3.clone(), justification.clone()).unwrap(); - - assert_eq!( - client.info().chain.finalized_hash, - a3.hash(), - ); - - assert_eq!( - client.justification(&BlockId::Hash(a3.hash())).unwrap(), - Some(justification), - ); - - assert_eq!( - client.justification(&BlockId::Hash(a1.hash())).unwrap(), - None, - ); - - assert_eq!( - client.justification(&BlockId::Hash(a2.hash())).unwrap(), - None, - ); - } - - #[test] - fn importing_diverged_finalized_block_should_trigger_reorg() { - - let client = test_client::new(); - - // G -> A1 -> A2 - // \ - // -> B1 - let a1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - // needed to make sure B1 gets a different hash from A1 - b1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 1, - nonce: 0, - }).unwrap(); - // create but don't import B1 just yet - let b1 = b1.bake().unwrap(); - - // A2 is the current best since it's the longest chain - assert_eq!( - client.info().chain.best_hash, - a2.hash(), - ); - - // importing B1 as finalized should trigger a re-org and set it as new best - let justification = vec![1, 2, 3]; - client.import_justified(BlockOrigin::Own, b1.clone(), justification).unwrap(); - - assert_eq!( - client.info().chain.best_hash, - b1.hash(), - ); - - assert_eq!( - client.info().chain.finalized_hash, - b1.hash(), - ); - } - - #[test] - fn finalizing_diverged_block_should_trigger_reorg() { - - let (client, select_chain) = TestClientBuilder::new().build_with_longest_chain(); - - // G -> A1 -> A2 - // \ - // -> B1 -> B2 - let a1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - // needed to make sure B1 gets a different hash from A1 - b1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 1, - nonce: 0, - }).unwrap(); - let b1 = b1.bake().unwrap(); - client.import(BlockOrigin::Own, b1.clone()).unwrap(); - - let b2 = client.new_block_at(&BlockId::Hash(b1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b2.clone()).unwrap(); - - // A2 is the current best since it's the longest chain - assert_eq!( - client.info().chain.best_hash, - a2.hash(), - ); - - // we finalize block B1 which is on a different branch from current best - // which should trigger a re-org. - client.finalize_block(BlockId::Hash(b1.hash()), None).unwrap(); - - // B1 should now be the latest finalized - assert_eq!( - client.info().chain.finalized_hash, - b1.hash(), - ); - - // and B1 should be the new best block (`finalize_block` as no way of - // knowing about B2) - assert_eq!( - client.info().chain.best_hash, - b1.hash(), - ); - - // `SelectChain` should report B2 as best block though - assert_eq!( - select_chain.best_chain().unwrap().hash(), - b2.hash(), - ); - - // after we build B3 on top of B2 and import it - // it should be the new best block, - let b3 = client.new_block_at( - &BlockId::Hash(b2.hash()), - Default::default(), - ).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - - assert_eq!( - client.info().chain.best_hash, - b3.hash(), - ); - } - - #[test] - fn get_header_by_block_number_doesnt_panic() { - let client = test_client::new(); - - // backend uses u32 for block numbers, make sure we don't panic when - // trying to convert - let id = BlockId::::Number(72340207214430721); - client.header(&id).expect_err("invalid block number overflows u32"); - } - - #[test] - fn state_reverted_on_reorg() { - let _ = env_logger::try_init(); - let client = test_client::new(); - - let current_balance = || - client.runtime_api().balance_of( - &BlockId::number(client.info().chain.best_number), AccountKeyring::Alice.into() - ).unwrap(); - - // G -> A1 -> A2 - // \ - // -> B1 - let mut a1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - a1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Bob.into(), - amount: 10, - nonce: 0, - }).unwrap(); - let a1 = a1.bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - b1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 50, - nonce: 0, - }).unwrap(); - let b1 = b1.bake().unwrap(); - // Reorg to B1 - client.import_as_best(BlockOrigin::Own, b1.clone()).unwrap(); - - assert_eq!(950, current_balance()); - let mut a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap(); - a2.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Charlie.into(), - amount: 10, - nonce: 1, - }).unwrap(); - // Re-org to A2 - client.import_as_best(BlockOrigin::Own, a2.bake().unwrap()).unwrap(); - assert_eq!(980, current_balance()); - } - - #[test] - fn doesnt_import_blocks_that_revert_finality() { - let _ = env_logger::try_init(); - let tmp = tempfile::tempdir().unwrap(); - - // we need to run with archive pruning to avoid pruning non-canonical - // states - let backend = Arc::new(Backend::new( - DatabaseSettings { - cache_size: None, - state_cache_size: 1 << 20, - state_cache_child_ratio: None, - path: tmp.path().into(), - pruning: PruningMode::ArchiveAll, - }, - u64::max_value(), - ).unwrap()); - - let client = TestClientBuilder::with_backend(backend).build(); - - // -> C1 - // / - // G -> A1 -> A2 - // \ - // -> B1 -> B2 -> B3 - - let a1 = client.new_block_at(&BlockId::Number(0), Default::default()) - .unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()) - .unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - - // needed to make sure B1 gets a different hash from A1 - b1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 1, - nonce: 0, - }).unwrap(); - let b1 = b1.bake().unwrap(); - client.import(BlockOrigin::Own, b1.clone()).unwrap(); - - let b2 = client.new_block_at(&BlockId::Hash(b1.hash()), Default::default()) - .unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b2.clone()).unwrap(); - - // we will finalize A2 which should make it impossible to import a new - // B3 at the same height but that doesnt't include it - client.finalize_block(BlockId::Hash(a2.hash()), None).unwrap(); - - let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()) - .unwrap().bake().unwrap(); - - let import_err = client.import(BlockOrigin::Own, b3).err().unwrap(); - let expected_err = ConsensusError::ClientImport( - error::Error::NotInFinalizedChain.to_string() - ); - - assert_eq!( - import_err.to_string(), - expected_err.to_string(), - ); - - // adding a C1 block which is lower than the last finalized should also - // fail (with a cheaper check that doesn't require checking ancestry). - let mut c1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - - // needed to make sure C1 gets a different hash from A1 and B1 - c1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 2, - nonce: 0, - }).unwrap(); - let c1 = c1.bake().unwrap(); - - let import_err = client.import(BlockOrigin::Own, c1).err().unwrap(); - let expected_err = ConsensusError::ClientImport( - error::Error::NotInFinalizedChain.to_string() - ); - - assert_eq!( - import_err.to_string(), - expected_err.to_string(), - ); - } -} diff --git a/core/client/src/error.rs b/core/client/src/error.rs deleted file mode 100644 index 922d122b42a8b..0000000000000 --- a/core/client/src/error.rs +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate client possible errors. - -use std::{self, error, result}; -use state_machine; -use sr_primitives::ApplyError; -use consensus; -use derive_more::{Display, From}; - -/// Client Result type alias -pub type Result = result::Result; - -/// Substrate Client error -#[derive(Debug, Display, From)] -pub enum Error { - /// Consensus Error - #[display(fmt = "Consensus: {}", _0)] - Consensus(consensus::Error), - /// Backend error. - #[display(fmt = "Backend error: {}", _0)] - Backend(String), - /// Unknown block. - #[display(fmt = "UnknownBlock: {}", _0)] - UnknownBlock(String), - /// Applying extrinsic error. - #[display(fmt = "Extrinsic error: {:?}", _0)] - ApplyExtrinsicFailed(ApplyError), - /// Execution error. - #[display(fmt = "Execution: {}", _0)] - Execution(Box), - /// Blockchain error. - #[display(fmt = "Blockchain: {}", _0)] - Blockchain(Box), - /// Invalid authorities set received from the runtime. - #[display(fmt = "Current state of blockchain has invalid authorities set")] - InvalidAuthoritiesSet, - /// Could not get runtime version. - #[display(fmt = "On-chain runtime does not specify version")] - VersionInvalid, - /// Genesis config is invalid. - #[display(fmt = "Genesis config provided is invalid")] - GenesisInvalid, - /// Error decoding header justification. - #[display(fmt = "error decoding justification for header")] - JustificationDecode, - /// Justification for header is correctly encoded, but invalid. - #[display(fmt = "bad justification for header: {}", _0)] - BadJustification(String), - /// Not available on light client. - #[display(fmt = "This method is not currently available when running in light client mode")] - NotAvailableOnLightClient, - /// Invalid remote CHT-based proof. - #[display(fmt = "Remote node has responded with invalid header proof")] - InvalidCHTProof, - /// Remote fetch has been cancelled. - #[display(fmt = "Remote data fetch has been cancelled")] - RemoteFetchCancelled, - /// Remote fetch has been failed. - #[display(fmt = "Remote data fetch has been failed")] - RemoteFetchFailed, - /// Error decoding call result. - #[display(fmt = "Error decoding call result of {}: {}", _0, _1)] - CallResultDecode(&'static str, codec::Error), - /// Error converting a parameter between runtime and node. - #[display(fmt = "Error converting `{}` between runtime and node", _0)] - RuntimeParamConversion(String), - /// Changes tries are not supported. - #[display(fmt = "Changes tries are not supported by the runtime")] - ChangesTriesNotSupported, - /// Key changes query has failed. - #[display(fmt = "Failed to check changes proof: {}", _0)] - ChangesTrieAccessFailed(String), - /// Last finalized block not parent of current. - #[display(fmt = "Did not finalize blocks in sequential order.")] - NonSequentialFinalization(String), - /// Safety violation: new best block not descendent of last finalized. - #[display(fmt = "Potential long-range attack: block not in finalized chain.")] - NotInFinalizedChain, - /// Hash that is required for building CHT is missing. - #[display(fmt = "Failed to get hash of block for building CHT")] - MissingHashRequiredForCHT, - /// Invalid calculated state root on block import. - #[display(fmt = "Calculated state root does not match.")] - InvalidStateRoot, - /// A convenience variant for String - #[display(fmt = "{}", _0)] - Msg(String), -} - -impl error::Error for Error { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match self { - Error::Consensus(e) => Some(e), - Error::Blockchain(e) => Some(e), - _ => None, - } - } -} - -impl From for Error { - fn from(s: String) -> Self { - Error::Msg(s) - } -} - -impl<'a> From<&'a str> for Error { - fn from(s: &'a str) -> Self { - Error::Msg(s.into()) - } -} - -impl Error { - /// Chain a blockchain error. - pub fn from_blockchain(e: Box) -> Self { - Error::Blockchain(e) - } - - /// Chain a state error. - pub fn from_state(e: Box) -> Self { - Error::Execution(e) - } -} diff --git a/core/client/src/genesis.rs b/core/client/src/genesis.rs deleted file mode 100644 index 031b2dc0ad7df..0000000000000 --- a/core/client/src/genesis.rs +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tool for creating the genesis block. - -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, Zero}; - -/// Create a genesis block, given the initial storage. -pub fn construct_genesis_block< - Block: BlockT -> ( - state_root: Block::Hash -) -> Block { - let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - Vec::new(), - ); - - Block::new( - <::Header as HeaderT>::new( - Zero::zero(), - extrinsics_root, - state_root, - Default::default(), - Default::default() - ), - Default::default() - ) -} - -#[cfg(test)] -mod tests { - use codec::{Encode, Decode, Joiner}; - use executor::native_executor_instance; - use state_machine::{ - StateMachine, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage, - }; - use state_machine::backend::InMemory; - use test_client::{ - runtime::genesismap::{GenesisConfig, insert_genesis_block}, - runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest}, - AccountKeyring, Sr25519Keyring, - }; - use primitives::{Blake2Hasher, map}; - use hex_literal::*; - - native_executor_instance!( - Executor, - test_client::runtime::api::dispatch, - test_client::runtime::native_version - ); - - fn executor() -> executor::NativeExecutor { - executor::NativeExecutor::new(executor::WasmExecutionMethod::Interpreted, None) - } - - fn construct_block( - backend: &InMemory, - number: BlockNumber, - parent_hash: Hash, - state_root: Hash, - txs: Vec - ) -> (Vec, Hash) { - use trie::{TrieConfiguration, trie_types::Layout}; - - let transactions = txs.into_iter().map(|tx| tx.into_signed_tx()).collect::>(); - - let iter = transactions.iter().map(Encode::encode); - let extrinsics_root = Layout::::ordered_trie_root(iter).into(); - - let mut header = Header { - parent_hash, - number, - state_root, - extrinsics_root, - digest: Digest { logs: vec![], }, - }; - let hash = header.hash(); - let mut overlay = OverlayedChanges::default(); - - StateMachine::new( - backend, - Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - None, - &mut overlay, - &executor(), - "Core_initialize_block", - &header.encode(), - None, - ).execute( - ExecutionStrategy::NativeElseWasm, - ).unwrap(); - - for tx in transactions.iter() { - StateMachine::new( - backend, - Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - None, - &mut overlay, - &executor(), - "BlockBuilder_apply_extrinsic", - &tx.encode(), - None, - ).execute( - ExecutionStrategy::NativeElseWasm, - ).unwrap(); - } - - let (ret_data, _, _) = StateMachine::new( - backend, - Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - None, - &mut overlay, - &executor(), - "BlockBuilder_finalize_block", - &[], - None, - ).execute( - ExecutionStrategy::NativeElseWasm, - ).unwrap(); - header = Header::decode(&mut &ret_data[..]).unwrap(); - - (vec![].and(&Block { header, extrinsics: transactions }), hash) - } - - fn block1(genesis_hash: Hash, backend: &InMemory) -> (Vec, Hash) { - construct_block( - backend, - 1, - genesis_hash, - hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), - vec![Transfer { - from: AccountKeyring::One.into(), - to: AccountKeyring::Two.into(), - amount: 69, - nonce: 0, - }] - ) - } - - #[test] - fn construct_genesis_should_work_with_native() { - let mut storage = GenesisConfig::new(false, - vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], - vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], - 1000, - None, - map![], - map![], - ).genesis_map(); - let genesis_hash = insert_genesis_block(&mut storage); - - let backend = InMemory::from(storage); - let (b1data, _b1hash) = block1(genesis_hash, &backend); - - let mut overlay = OverlayedChanges::default(); - let _ = StateMachine::new( - &backend, - Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - None, - &mut overlay, - &executor(), - "Core_execute_block", - &b1data, - None, - ).execute( - ExecutionStrategy::NativeElseWasm, - ).unwrap(); - } - - #[test] - fn construct_genesis_should_work_with_wasm() { - let mut storage = GenesisConfig::new(false, - vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], - vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], - 1000, - None, - map![], - map![], - ).genesis_map(); - let genesis_hash = insert_genesis_block(&mut storage); - - let backend = InMemory::from(storage); - let (b1data, _b1hash) = block1(genesis_hash, &backend); - - let mut overlay = OverlayedChanges::default(); - let _ = StateMachine::new( - &backend, - Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - None, - &mut overlay, - &executor(), - "Core_execute_block", - &b1data, - None, - ).execute( - ExecutionStrategy::AlwaysWasm, - ).unwrap(); - } - - #[test] - fn construct_genesis_with_bad_transaction_should_panic() { - let mut storage = GenesisConfig::new(false, - vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()], - vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], - 68, - None, - map![], - map![], - ).genesis_map(); - let genesis_hash = insert_genesis_block(&mut storage); - - let backend = InMemory::from(storage); - let (b1data, _b1hash) = block1(genesis_hash, &backend); - - let mut overlay = OverlayedChanges::default(); - let r = StateMachine::new( - &backend, - Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - None, - &mut overlay, - &executor(), - "Core_execute_block", - &b1data, - None, - ).execute( - ExecutionStrategy::NativeElseWasm, - ); - assert!(r.is_err()); - } -} diff --git a/core/client/src/in_mem.rs b/core/client/src/in_mem.rs deleted file mode 100644 index 5c35400d7743c..0000000000000 --- a/core/client/src/in_mem.rs +++ /dev/null @@ -1,893 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! In memory client backend - -use std::collections::{HashMap, HashSet}; -use std::sync::Arc; -use parking_lot::{RwLock, Mutex}; -use primitives::{ChangesTrieConfiguration, storage::well_known_keys}; -use sr_primitives::generic::{BlockId, DigestItem}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor}; -use sr_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay}; -use state_machine::backend::{Backend as StateBackend, InMemory}; -use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction}; -use hash_db::{Hasher, Prefix}; -use trie::MemoryDB; -use header_metadata::{CachedHeaderMetadata, HeaderMetadata}; - -use crate::error; -use crate::backend::{self, NewBlockState, StorageCollection, ChildStorageCollection}; -use crate::light; -use crate::leaves::LeafSet; -use crate::blockchain::{ - self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId -}; - -struct PendingBlock { - block: StoredBlock, - state: NewBlockState, -} - -#[derive(PartialEq, Eq, Clone)] -enum StoredBlock { - Header(B::Header, Option), - Full(B, Option), -} - -impl StoredBlock { - fn new(header: B::Header, body: Option>, just: Option) -> Self { - match body { - Some(body) => StoredBlock::Full(B::new(header, body), just), - None => StoredBlock::Header(header, just), - } - } - - fn header(&self) -> &B::Header { - match *self { - StoredBlock::Header(ref h, _) => h, - StoredBlock::Full(ref b, _) => b.header(), - } - } - - fn justification(&self) -> Option<&Justification> { - match *self { - StoredBlock::Header(_, ref j) | StoredBlock::Full(_, ref j) => j.as_ref() - } - } - - fn extrinsics(&self) -> Option<&[B::Extrinsic]> { - match *self { - StoredBlock::Header(_, _) => None, - StoredBlock::Full(ref b, _) => Some(b.extrinsics()), - } - } - - fn into_inner(self) -> (B::Header, Option>, Option) { - match self { - StoredBlock::Header(header, just) => (header, None, just), - StoredBlock::Full(block, just) => { - let (header, body) = block.deconstruct(); - (header, Some(body), just) - } - } - } -} - -#[derive(Clone)] -struct BlockchainStorage { - blocks: HashMap>, - hashes: HashMap, Block::Hash>, - best_hash: Block::Hash, - best_number: NumberFor, - finalized_hash: Block::Hash, - finalized_number: NumberFor, - genesis_hash: Block::Hash, - header_cht_roots: HashMap, Block::Hash>, - changes_trie_cht_roots: HashMap, Block::Hash>, - leaves: LeafSet>, - aux: HashMap, Vec>, -} - -/// In-memory blockchain. Supports concurrent reads. -pub struct Blockchain { - storage: Arc>>, -} - -impl Clone for Blockchain { - fn clone(&self) -> Self { - let storage = Arc::new(RwLock::new(self.storage.read().clone())); - Blockchain { - storage: storage.clone(), - } - } -} - -impl Blockchain { - /// Get header hash of given block. - pub fn id(&self, id: BlockId) -> Option { - match id { - BlockId::Hash(h) => Some(h), - BlockId::Number(n) => self.storage.read().hashes.get(&n).cloned(), - } - } - - /// Create new in-memory blockchain storage. - pub fn new() -> Blockchain { - let storage = Arc::new(RwLock::new( - BlockchainStorage { - blocks: HashMap::new(), - hashes: HashMap::new(), - best_hash: Default::default(), - best_number: Zero::zero(), - finalized_hash: Default::default(), - finalized_number: Zero::zero(), - genesis_hash: Default::default(), - header_cht_roots: HashMap::new(), - changes_trie_cht_roots: HashMap::new(), - leaves: LeafSet::new(), - aux: HashMap::new(), - })); - Blockchain { - storage: storage.clone(), - } - } - - /// Insert a block header and associated data. - pub fn insert( - &self, - hash: Block::Hash, - header: ::Header, - justification: Option, - body: Option::Extrinsic>>, - new_state: NewBlockState, - ) -> crate::error::Result<()> { - let number = header.number().clone(); - if new_state.is_best() { - self.apply_head(&header)?; - } - - { - 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 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 - } - - /// Compare canonical chain to other canonical chain. - pub fn canon_equals_to(&self, other: &Self) -> bool { - let this = self.storage.read(); - let other = other.storage.read(); - this.hashes == other.hashes - && this.best_hash == other.best_hash - && this.best_number == other.best_number - && this.genesis_hash == other.genesis_hash - } - - /// Insert header CHT root. - pub fn insert_cht_root(&self, block: NumberFor, cht_root: Block::Hash) { - 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::Error::UnknownBlock(format!("{}", id))), - }; - - 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 = header_metadata::tree_route(self, best_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(), - None => return Err(error::Error::UnknownBlock(format!("{}", id))), - }; - - let mut storage = self.storage.write(); - storage.finalized_hash = hash; - - if justification.is_some() { - let block = storage.blocks.get_mut(&hash) - .expect("hash was fetched from a block in the db; qed"); - - let block_justification = match block { - StoredBlock::Header(_, ref mut j) | StoredBlock::Full(_, ref mut j) => j - }; - - *block_justification = justification; - } - - Ok(()) - } - - fn write_aux(&self, ops: Vec<(Vec, Option>)>) { - let mut storage = self.storage.write(); - for (k, v) in ops { - match v { - Some(v) => storage.aux.insert(k, v), - None => storage.aux.remove(&k), - }; - } - } -} - -impl HeaderBackend for Blockchain { - fn header(&self, id: BlockId) -> error::Result::Header>> { - Ok(self.id(id).and_then(|hash| { - self.storage.read().blocks.get(&hash).map(|b| b.header().clone()) - })) - } - - fn info(&self) -> blockchain::Info { - let storage = self.storage.read(); - blockchain::Info { - best_hash: storage.best_hash, - best_number: storage.best_number, - genesis_hash: storage.genesis_hash, - finalized_hash: storage.finalized_hash, - finalized_number: storage.finalized_number, - } - } - - fn status(&self, id: BlockId) -> error::Result { - match self.id(id).map_or(false, |hash| self.storage.read().blocks.contains_key(&hash)) { - true => Ok(BlockStatus::InChain), - false => Ok(BlockStatus::Unknown), - } - } - - fn number(&self, hash: Block::Hash) -> error::Result>> { - Ok(self.storage.read().blocks.get(&hash).map(|b| *b.header().number())) - } - - fn hash(&self, number: <::Header as HeaderT>::Number) -> error::Result> { - Ok(self.id(BlockId::Number(number))) - } -} - -impl HeaderMetadata for Blockchain { - type Error = error::Error; - - fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { - self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header)) - .ok_or(error::Error::UnknownBlock(format!("header not found: {}", hash))) - } - - fn insert_header_metadata(&self, _hash: Block::Hash, _metadata: CachedHeaderMetadata) { - // No need to implement. - } - fn remove_header_metadata(&self, _hash: Block::Hash) { - // No need to implement. - } -} - -impl blockchain::Backend for Blockchain { - fn body(&self, id: BlockId) -> error::Result::Extrinsic>>> { - Ok(self.id(id).and_then(|hash| { - self.storage.read().blocks.get(&hash) - .and_then(|b| b.extrinsics().map(|x| x.to_vec())) - })) - } - - fn justification(&self, id: BlockId) -> error::Result> { - Ok(self.id(id).and_then(|hash| self.storage.read().blocks.get(&hash).and_then(|b| - b.justification().map(|x| x.clone())) - )) - } - - fn last_finalized(&self) -> error::Result { - Ok(self.storage.read().finalized_hash.clone()) - } - - fn cache(&self) -> Option>> { - None - } - - fn leaves(&self) -> error::Result> { - Ok(self.storage.read().leaves.hashes()) - } - - fn children(&self, _parent_hash: Block::Hash) -> error::Result> { - unimplemented!() - } -} - -impl blockchain::ProvideCache for Blockchain { - fn cache(&self) -> Option>> { - None - } -} - -impl backend::AuxStore for Blockchain { - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> error::Result<()> { - let mut storage = self.storage.write(); - for (k, v) in insert { - storage.aux.insert(k.to_vec(), v.to_vec()); - } - for k in delete { - storage.aux.remove(*k); - } - Ok(()) - } - - fn get_aux(&self, key: &[u8]) -> error::Result>> { - Ok(self.storage.read().aux.get(key).cloned()) - } -} - -impl light::blockchain::Storage for Blockchain - where - Block::Hash: From<[u8; 32]>, -{ - fn import_header( - &self, - header: Block::Header, - _cache: HashMap>, - state: NewBlockState, - aux_ops: Vec<(Vec, Option>)>, - ) -> error::Result<()> { - let hash = header.hash(); - self.insert(hash, header, None, None, state)?; - - self.write_aux(aux_ops); - 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()) - } - - fn finalize_header(&self, id: BlockId) -> error::Result<()> { - Blockchain::finalize_header(self, id, None) - } - - fn header_cht_root( - &self, - _cht_size: NumberFor, - block: NumberFor, - ) -> error::Result { - self.storage.read().header_cht_roots.get(&block).cloned() - .ok_or_else(|| error::Error::Backend(format!("Header CHT for block {} not exists", block))) - } - - fn changes_trie_cht_root( - &self, - _cht_size: NumberFor, - block: NumberFor, - ) -> error::Result { - self.storage.read().changes_trie_cht_roots.get(&block).cloned() - .ok_or_else(|| error::Error::Backend(format!("Changes trie CHT for block {} not exists", block))) - } - - fn cache(&self) -> Option>> { - None - } -} - -/// In-memory operation. -pub struct BlockImportOperation { - pending_block: Option>, - pending_cache: HashMap>, - old_state: InMemory, - new_state: Option>, - changes_trie_update: Option>, - aux: Vec<(Vec, Option>)>, - finalized_blocks: Vec<(BlockId, Option)>, - set_head: Option>, -} - -impl backend::BlockImportOperation for BlockImportOperation -where - Block: BlockT, - H: Hasher, - - H::Out: Ord, -{ - type State = InMemory; - - fn state(&self) -> error::Result> { - Ok(Some(&self.old_state)) - } - - fn set_block_data( - &mut self, - header: ::Header, - body: Option::Extrinsic>>, - justification: Option, - state: NewBlockState, - ) -> error::Result<()> { - assert!(self.pending_block.is_none(), "Only one block per operation is allowed"); - self.pending_block = Some(PendingBlock { - block: StoredBlock::new(header, body, justification), - state, - }); - Ok(()) - } - - fn update_cache(&mut self, cache: HashMap>) { - self.pending_cache = cache; - } - - fn update_db_storage(&mut self, update: as StateBackend>::Transaction) -> error::Result<()> { - self.new_state = Some(self.old_state.update(update)); - Ok(()) - } - - fn update_changes_trie(&mut self, update: ChangesTrieTransaction>) -> error::Result<()> { - self.changes_trie_update = Some(update.0); - Ok(()) - } - - fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> error::Result { - check_genesis_storage(&top, &children)?; - - let child_delta = children.into_iter() - .map(|(storage_key, child_overlay)| - (storage_key, child_overlay.into_iter().map(|(k, v)| (k, Some(v))))); - - let (root, transaction) = self.old_state.full_storage_root( - top.into_iter().map(|(k, v)| (k, Some(v))), - child_delta - ); - - self.new_state = Some(InMemory::from(transaction)); - Ok(root) - } - - fn insert_aux(&mut self, ops: I) -> error::Result<()> - where I: IntoIterator, Option>)> - { - self.aux.append(&mut ops.into_iter().collect()); - Ok(()) - } - - fn update_storage( - &mut self, - _update: StorageCollection, - _child_update: ChildStorageCollection, - ) -> 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(()) - } -} - -/// In-memory backend. Keeps all states and blocks in memory. -/// -/// > **Warning**: Doesn't support all the features necessary for a proper database. Only use this -/// > struct for testing purposes. Do **NOT** use in production. -pub struct Backend -where - Block: BlockT, - H: Hasher, - H::Out: Ord, -{ - states: RwLock>>, - changes_trie_storage: ChangesTrieStorage, - blockchain: Blockchain, - import_lock: Mutex<()>, -} - -impl Backend -where - Block: BlockT, - H: Hasher, - H::Out: Ord, -{ - /// Create a new instance of in-mem backend. - pub fn new() -> Backend { - Backend { - states: RwLock::new(HashMap::new()), - changes_trie_storage: ChangesTrieStorage(InMemoryChangesTrieStorage::new()), - blockchain: Blockchain::new(), - import_lock: Default::default(), - } - } -} - -impl backend::AuxStore for Backend -where - Block: BlockT, - H: Hasher, - H::Out: Ord, -{ - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> error::Result<()> { - self.blockchain.insert_aux(insert, delete) - } - - fn get_aux(&self, key: &[u8]) -> error::Result>> { - self.blockchain.get_aux(key) - } -} - -impl backend::Backend for Backend -where - Block: BlockT, - H: Hasher, - H::Out: Ord, -{ - type BlockImportOperation = BlockImportOperation; - type Blockchain = Blockchain; - type State = InMemory; - type ChangesTrieStorage = ChangesTrieStorage; - type OffchainStorage = OffchainStorage; - - fn begin_operation(&self) -> error::Result { - let old_state = self.state_at(BlockId::Hash(Default::default()))?; - Ok(BlockImportOperation { - pending_block: None, - pending_cache: Default::default(), - old_state, - new_state: None, - changes_trie_update: 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(); - - let hash = header.hash(); - - self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone())); - - let maybe_changes_trie_root = header.digest().log(DigestItem::as_changes_trie_root).cloned(); - if let Some(changes_trie_root) = maybe_changes_trie_root { - if let Some(changes_trie_update) = operation.changes_trie_update { - self.changes_trie_storage.0.insert( - *header.number(), - changes_trie_root, - changes_trie_update - ); - } - } - - self.blockchain.insert(hash, header, justification, body, pending_block.state)?; - } - - 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(()) - } - - fn finalize_block(&self, block: BlockId, justification: Option) -> error::Result<()> { - self.blockchain.finalize_header(block, justification) - } - - fn blockchain(&self) -> &Self::Blockchain { - &self.blockchain - } - - fn used_state_cache_size(&self) -> Option { - None - } - - fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage> { - Some(&self.changes_trie_storage) - } - - fn offchain_storage(&self) -> Option { - None - } - - 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::Error::UnknownBlock(format!("{}", block))), - } - } - - fn revert(&self, _n: NumberFor) -> error::Result> { - Ok(Zero::zero()) - } - - fn get_import_lock(&self) -> &Mutex<()> { - &self.import_lock - } -} - -impl backend::LocalBackend for Backend -where - Block: BlockT, - H: Hasher, - H::Out: Ord, -{} - -impl backend::RemoteBackend for Backend -where - Block: BlockT, - H: Hasher, - H::Out: 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) - } - - fn remote_blockchain(&self) -> Arc> { - unimplemented!() - } -} - -/// Prunable in-memory changes trie storage. -pub struct ChangesTrieStorage(InMemoryChangesTrieStorage>); -impl backend::PrunableStateChangesTrieStorage for ChangesTrieStorage { - fn oldest_changes_trie_block( - &self, - _config: &ChangesTrieConfiguration, - _best_finalized: NumberFor, - ) -> NumberFor { - Zero::zero() - } -} - -impl state_machine::ChangesTrieRootsStorage> for ChangesTrieStorage - where - Block: BlockT, - H: Hasher, -{ - fn build_anchor( - &self, - _hash: H::Out, - ) -> Result>, String> { - Err("Dummy implementation".into()) - } - - fn root( - &self, - _anchor: &ChangesTrieAnchorBlockId>, - _block: NumberFor, - ) -> Result, String> { - Err("Dummy implementation".into()) - } -} - -impl state_machine::ChangesTrieStorage> for ChangesTrieStorage - where - Block: BlockT, - H: Hasher, -{ - fn as_roots_storage(&self) -> &dyn state_machine::ChangesTrieRootsStorage> { - self - } - - fn with_cached_changed_keys( - &self, - _root: &H::Out, - _functor: &mut dyn FnMut(&HashMap>, HashSet>>), - ) -> bool { - false - } - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - self.0.get(key, prefix) - } -} - -/// 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::Error::GenesisInvalid.into()); - } - - if children.keys().any(|child_key| !well_known_keys::is_child_storage_key(&child_key)) { - return Err(error::Error::GenesisInvalid.into()); - } - - Ok(()) -} - -/// In-memory storage for offchain workers. -#[derive(Debug, Clone, Default)] -pub struct OffchainStorage { - storage: HashMap, Vec>, -} - -impl backend::OffchainStorage for OffchainStorage { - fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { - let key = prefix.iter().chain(key).cloned().collect(); - self.storage.insert(key, value.to_vec()); - } - - fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { - let key: Vec = prefix.iter().chain(key).cloned().collect(); - self.storage.get(&key).cloned() - } - - fn compare_and_set( - &mut self, - prefix: &[u8], - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - use std::collections::hash_map::Entry; - let key = prefix.iter().chain(key).cloned().collect(); - - match self.storage.entry(key) { - Entry::Vacant(entry) => if old_value.is_none() { - entry.insert(new_value.to_vec()); - true - } else { false }, - Entry::Occupied(ref mut entry) if Some(entry.get().as_slice()) == old_value => { - entry.insert(new_value.to_vec()); - true - }, - _ => false, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::sync::Arc; - use test_client; - use primitives::Blake2Hasher; - - type TestBackend = test_client::client::in_mem::Backend; - - #[test] - fn test_leaves_with_complex_block_tree() { - let backend = Arc::new(TestBackend::new()); - - test_client::trait_tests::test_leaves_for_backend(backend); - } - - #[test] - fn test_blockchain_query_by_number_gets_canonical() { - let backend = Arc::new(TestBackend::new()); - - test_client::trait_tests::test_blockchain_query_by_number_gets_canonical(backend); - } - - #[test] - fn in_memory_offchain_storage() { - use crate::backend::OffchainStorage as _; - - let mut storage = OffchainStorage::default(); - assert_eq!(storage.get(b"A", b"B"), None); - assert_eq!(storage.get(b"B", b"A"), None); - - storage.set(b"A", b"B", b"C"); - assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec())); - assert_eq!(storage.get(b"B", b"A"), None); - - storage.compare_and_set(b"A", b"B", Some(b"X"), b"D"); - assert_eq!(storage.get(b"A", b"B"), Some(b"C".to_vec())); - storage.compare_and_set(b"A", b"B", Some(b"C"), b"D"); - assert_eq!(storage.get(b"A", b"B"), Some(b"D".to_vec())); - - assert!(!storage.compare_and_set(b"B", b"A", Some(b""), b"Y")); - assert!(storage.compare_and_set(b"B", b"A", None, b"X")); - assert_eq!(storage.get(b"B", b"A"), Some(b"X".to_vec())); - } -} diff --git a/core/client/src/lib.rs b/core/client/src/lib.rs deleted file mode 100644 index 5a2cb746f3864..0000000000000 --- a/core/client/src/lib.rs +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate Client and associated logic. -//! -//! The [`Client`] is one of the most important components of Substrate. It mainly comprises two -//! parts: -//! -//! - A database containing the blocks and chain state, generally referred to as -//! the [`Backend`](backend::Backend). -//! - A runtime environment, generally referred to as the [`Executor`](CallExecutor). -//! -//! # Initialization -//! -//! Creating a [`Client`] is done by calling the `new` method and passing to it a -//! [`Backend`](backend::Backend) and an [`Executor`](CallExecutor). -//! -//! The former is typically provided by the `substrate-client-db` crate. -//! -//! The latter typically requires passing one of: -//! -//! - A [`LocalCallExecutor`] running the runtime locally. -//! - A [`RemoteCallExecutor`](light::call_executor::RemoteCallExecutor) that will ask a -//! third-party to perform the executions. -//! - A [`RemoteOrLocalCallExecutor`](light::call_executor::RemoteOrLocalCallExecutor), combination -//! of the two. -//! -//! Additionally, the fourth generic parameter of the `Client` is a marker type representing -//! the ways in which the runtime can interface with the outside. Any code that builds a `Client` -//! is responsible for putting the right marker. -//! -//! ## Example -//! -//! ``` -//! use std::sync::Arc; -//! use substrate_client::{Client, in_mem::Backend, LocalCallExecutor}; -//! use primitives::Blake2Hasher; -//! use sr_primitives::{StorageOverlay, ChildrenStorageOverlay}; -//! use executor::{NativeExecutor, WasmExecutionMethod}; -//! -//! // In this example, we're using the `Block` and `RuntimeApi` types from the -//! // `substrate-test-runtime-client` crate. These types are automatically generated when -//! // compiling a runtime. In a typical use-case, these types would have been to be generated -//! // from your runtime. -//! use test_client::{LocalExecutor, runtime::Block, runtime::RuntimeApi}; -//! -//! let backend = Arc::new(Backend::::new()); -//! let client = Client::<_, _, _, RuntimeApi>::new( -//! backend.clone(), -//! LocalCallExecutor::new( -//! backend.clone(), -//! NativeExecutor::::new(WasmExecutionMethod::Interpreted, None), -//! None, -//! ), -//! // This parameter provides the storage for the chain genesis. -//! <(StorageOverlay, ChildrenStorageOverlay)>::default(), -//! Default::default(), -//! Default::default(), -//! ); -//! ``` -//! - -#![cfg_attr(not(feature = "std"), no_std)] -#![warn(missing_docs)] -#![recursion_limit="128"] - -#[macro_use] -pub mod runtime_api; -#[cfg(feature = "std")] -pub mod error; -#[cfg(feature = "std")] -pub mod blockchain; -#[cfg(feature = "std")] -pub mod backend; -#[cfg(feature = "std")] -pub mod cht; -#[cfg(feature = "std")] -pub mod in_mem; -#[cfg(feature = "std")] -pub mod genesis; -pub mod block_builder; -#[cfg(feature = "std")] -pub mod light; -#[cfg(feature = "std")] -pub mod leaves; -#[cfg(feature = "std")] -pub mod children; -#[cfg(feature = "std")] -mod call_executor; -#[cfg(feature = "std")] -mod client; -#[cfg(feature = "std")] -mod notifications; - - -#[cfg(feature = "std")] -pub use crate::blockchain::Info as ChainInfo; -#[cfg(feature = "std")] -pub use crate::call_executor::{CallExecutor, LocalCallExecutor}; -#[cfg(feature = "std")] -pub use crate::client::{ - new_with_backend, - new_in_mem, - BlockBody, ImportNotifications, FinalityNotifications, BlockchainEvents, - BlockImportNotification, Client, ClientInfo, ExecutionStrategies, FinalityNotification, - LongestChain, BlockOf, ProvideUncles, ForkBlocks, - utils, apply_aux, -}; -#[cfg(feature = "std")] -pub use crate::notifications::{StorageEventStream, StorageChangeSet}; -#[cfg(feature = "std")] -pub use state_machine::ExecutionStrategy; -#[cfg(feature = "std")] -pub use crate::leaves::LeafSet; -#[cfg(feature = "std")] -pub use crate::blockchain::well_known_cache_keys; - -#[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 deleted file mode 100644 index 300d140630d85..0000000000000 --- a/core/client/src/light/backend.rs +++ /dev/null @@ -1,485 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! 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; -use parking_lot::{RwLock, Mutex}; - -use sr_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; -use state_machine::{Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState, ChangesTrieTransaction}; -use sr_primitives::traits::{Block as BlockT, NumberFor, Zero, Header}; -use crate::in_mem::{self, check_genesis_storage}; -use crate::backend::{ - AuxStore, Backend as ClientBackend, BlockImportOperation, RemoteBackend, NewBlockState, - StorageCollection, ChildStorageCollection, -}; -use crate::blockchain::{HeaderBackend as BlockchainHeaderBackend, well_known_cache_keys}; -use crate::error::{Error as ClientError, Result as ClientResult}; -use crate::light::blockchain::{Blockchain, Storage as BlockchainStorage}; -use hash_db::Hasher; -use trie::MemoryDB; - -const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always succeeds; qed"; - -/// Light client backend. -pub struct Backend { - blockchain: Arc>, - genesis_state: RwLock>>, - import_lock: Mutex<()>, -} - -/// Light block (header and justification) import operation. -pub struct ImportOperation { - header: Option, - cache: HashMap>, - leaf_state: NewBlockState, - aux_ops: Vec<(Vec, Option>)>, - finalized_blocks: Vec>, - set_head: Option>, - storage_update: Option>, - _phantom: ::std::marker::PhantomData<(S)>, -} - -/// Either in-memory genesis state, or locally-unavailable state. -pub enum GenesisOrUnavailableState { - /// Genesis state - storage values are stored in-memory. - Genesis(InMemoryState), - /// We know that state exists, but all calls will fail with error, because it - /// isn't locally available. - Unavailable, -} - -impl Backend { - /// Create new light backend. - pub fn new(blockchain: Arc>) -> Self { - Self { - blockchain, - genesis_state: RwLock::new(None), - import_lock: Default::default(), - } - } - - /// Get shared blockchain reference. - pub fn blockchain(&self) -> &Arc> { - &self.blockchain - } -} - -impl AuxStore for Backend { - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, delete: D) -> ClientResult<()> { - self.blockchain.storage().insert_aux(insert, delete) - } - - fn get_aux(&self, key: &[u8]) -> ClientResult>> { - self.blockchain.storage().get_aux(key) - } -} - -impl ClientBackend for Backend where - Block: BlockT, - S: BlockchainStorage, - H: Hasher, - H::Out: Ord, -{ - type BlockImportOperation = ImportOperation; - type Blockchain = Blockchain; - type State = GenesisOrUnavailableState; - type ChangesTrieStorage = in_mem::ChangesTrieStorage; - type OffchainStorage = in_mem::OffchainStorage; - - fn begin_operation(&self) -> ClientResult { - Ok(ImportOperation { - header: None, - cache: Default::default(), - leaf_state: NewBlockState::Normal, - aux_ops: Vec::new(), - finalized_blocks: Vec::new(), - set_head: None, - storage_update: None, - _phantom: Default::default(), - }) - } - - 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.cache, - 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<()> { - self.blockchain.storage().finalize_header(block) - } - - fn blockchain(&self) -> &Blockchain { - &self.blockchain - } - - fn used_state_cache_size(&self) -> Option { - None - } - - fn changes_trie_storage(&self) -> Option<&Self::ChangesTrieStorage> { - None - } - - fn offchain_storage(&self) -> Option { - None - } - - fn state_at(&self, block: BlockId) -> ClientResult { - 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(GenesisOrUnavailableState::Genesis(genesis_state)); - } - } - - // else return unavailable state. We do not return error here, because error - // would mean that we do not know this state at all. But we know that it exists - Ok(GenesisOrUnavailableState::Unavailable) - } - - fn revert(&self, _n: NumberFor) -> ClientResult> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn get_import_lock(&self) -> &Mutex<()> { - &self.import_lock - } -} - -impl RemoteBackend for Backend -where - Block: BlockT, - S: BlockchainStorage + 'static, - H: Hasher, - H::Out: 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) - } - - fn remote_blockchain(&self) -> Arc> { - self.blockchain.clone() - } -} - -impl BlockImportOperation for ImportOperation -where - Block: BlockT, - S: BlockchainStorage, - H: Hasher, - H::Out: Ord, -{ - type State = GenesisOrUnavailableState; - - fn state(&self) -> ClientResult> { - // None means 'locally-stateless' backend - Ok(None) - } - - fn set_block_data( - &mut self, - header: Block::Header, - _body: Option>, - _justification: Option, - state: NewBlockState, - ) -> ClientResult<()> { - self.leaf_state = state; - self.header = Some(header); - Ok(()) - } - - fn update_cache(&mut self, cache: HashMap>) { - self.cache = cache; - } - - fn update_db_storage(&mut self, _update: >::Transaction) -> ClientResult<()> { - // we're not storing anything locally => ignore changes - Ok(()) - } - - fn update_changes_trie(&mut self, _update: ChangesTrieTransaction>) -> ClientResult<()> { - // we're not storing anything locally => ignore changes - Ok(()) - } - - 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); - - // create a list of children keys to re-compute roots for - let child_delta = children.keys() - .cloned() - .map(|storage_key| (storage_key, None)) - .collect::>(); - - // make sure to persist the child storage - 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.full_storage_root(::std::iter::empty(), child_delta); - self.storage_update = Some(storage_update); - - Ok(storage_root) - } - - fn insert_aux(&mut self, ops: I) -> ClientResult<()> - where I: IntoIterator, Option>)> - { - self.aux_ops.append(&mut ops.into_iter().collect()); - Ok(()) - } - - fn update_storage( - &mut self, - _update: StorageCollection, - _child_update: ChildStorageCollection, - ) -> 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(()) - } -} - -impl std::fmt::Debug for GenesisOrUnavailableState { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.fmt(f), - GenesisOrUnavailableState::Unavailable => write!(f, "Unavailable"), - } - } -} - -impl StateBackend for GenesisOrUnavailableState - where - H::Out: Ord, -{ - type Error = ClientError; - type Transaction = (); - type TrieBackendStorage = MemoryDB; - - fn storage(&self, key: &[u8]) -> ClientResult>> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - Ok(state.storage(key).expect(IN_MEMORY_EXPECT_PROOF)), - GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> ClientResult>> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - Ok(state.child_storage(storage_key, key).expect(IN_MEMORY_EXPECT_PROOF)), - GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn for_keys_with_prefix(&self, prefix: &[u8], action: A) { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.for_keys_with_prefix(prefix, action), - GenesisOrUnavailableState::Unavailable => (), - } - } - - fn for_key_values_with_prefix(&self, prefix: &[u8], action: A) { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.for_key_values_with_prefix(prefix, action), - GenesisOrUnavailableState::Unavailable => (), - } - } - - - fn for_keys_in_child_storage(&self, storage_key: &[u8], action: A) { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.for_keys_in_child_storage(storage_key, action), - GenesisOrUnavailableState::Unavailable => (), - } - } - - fn for_child_keys_with_prefix( - &self, - storage_key: &[u8], - prefix: &[u8], - action: A, - ) { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - state.for_child_keys_with_prefix(storage_key, prefix, action), - GenesisOrUnavailableState::Unavailable => (), - } - } - - fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) - where - I: IntoIterator, Option>)> - { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => - (state.storage_root(delta).0, ()), - GenesisOrUnavailableState::Unavailable => (H::Out::default(), ()), - } - } - - fn child_storage_root(&self, key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) - where - I: IntoIterator, Option>)> - { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => { - let (root, is_equal, _) = state.child_storage_root(key, delta); - (root, is_equal, ()) - }, - GenesisOrUnavailableState::Unavailable => (H::Out::default().as_ref().to_vec(), true, ()), - } - } - - fn pairs(&self) -> Vec<(Vec, Vec)> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.pairs(), - GenesisOrUnavailableState::Unavailable => Vec::new(), - } - } - - fn keys(&self, prefix: &[u8]) -> Vec> { - match *self { - GenesisOrUnavailableState::Genesis(ref state) => state.keys(prefix), - GenesisOrUnavailableState::Unavailable => Vec::new(), - } - } - - fn as_trie_backend(&mut self) -> Option<&TrieBackend> { - match self { - GenesisOrUnavailableState::Genesis(ref mut state) => state.as_trie_backend(), - GenesisOrUnavailableState::Unavailable => None, - } - } -} - -#[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() { - GenesisOrUnavailableState::Genesis(_) => (), - _ => panic!("unexpected state"), - } - } - - #[test] - fn unavailable_state_is_created_when_genesis_state_is_unavailable() { - let backend: Backend<_, Blake2Hasher> = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); - - match backend.state_at(BlockId::Number(0)).unwrap() { - GenesisOrUnavailableState::Unavailable => (), - _ => panic!("unexpected state"), - } - } - - #[test] - fn light_aux_store_is_updated_via_non_importing_op() { - let backend = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); - let mut op = ClientBackend::::begin_operation(&backend).unwrap(); - BlockImportOperation::::insert_aux(&mut op, vec![(vec![1], Some(vec![2]))]).unwrap(); - ClientBackend::::commit_operation(&backend, op).unwrap(); - - assert_eq!(AuxStore::get_aux(&backend, &[1]).unwrap(), Some(vec![2])); - } -} diff --git a/core/client/src/light/blockchain.rs b/core/client/src/light/blockchain.rs deleted file mode 100644 index 202f94cd74fed..0000000000000 --- a/core/client/src/light/blockchain.rs +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Light client blockchain backend. Only stores headers and justifications of recent -//! blocks. CHT roots are stored for headers of ancient blocks. - -use std::future::Future; -use std::{sync::Arc, collections::HashMap}; - -use sr_primitives::{Justification, generic::BlockId}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; - -use header_metadata::{HeaderMetadata, CachedHeaderMetadata}; - -use crate::backend::{AuxStore, NewBlockState}; -use crate::blockchain::{ - Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache, - HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo, ProvideCache, - well_known_cache_keys -}; -use crate::cht; -use crate::error::{Error as ClientError, Result as ClientResult}; -use crate::light::fetcher::{Fetcher, RemoteHeaderRequest}; - -/// Light client blockchain storage. -pub trait Storage: AuxStore + BlockchainHeaderBackend + HeaderMetadata { - /// Store new header. Should refuse to revert any finalized blocks. - /// - /// Takes new authorities, the leaf state of the new block, and - /// any auxiliary storage updates to place in the same operation. - fn import_header( - &self, - header: Block::Header, - cache: HashMap>, - 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<()>; - - /// Get last finalized header. - fn last_finalized(&self) -> ClientResult; - - /// Get headers CHT root for given block. Fails if the block is not pruned (not a part of any CHT). - fn header_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> ClientResult; - - /// Get changes trie CHT root for given block. Fails if the block is not pruned (not a part of any CHT). - fn changes_trie_cht_root( - &self, - cht_size: NumberFor, - block: NumberFor, - ) -> ClientResult; - - /// Get storage cache. - fn cache(&self) -> Option>>; -} - -/// Remote header. -#[derive(Debug)] -pub enum LocalOrRemote { - /// When data is available locally, it is returned. - Local(Data), - /// When data is unavailable locally, the request to fetch it from remote node is returned. - Remote(Request), - /// When data is unknown. - Unknown, -} - -/// Futures-based blockchain backend that either resolves blockchain data -/// locally, or fetches required data from remote node. -pub trait RemoteBlockchain: Send + Sync { - /// Get block header. - fn header(&self, id: BlockId) -> ClientResult, - >>; -} - -/// Light client blockchain. -pub struct Blockchain { - storage: S, -} - -impl Blockchain { - /// Create new light blockchain backed with given storage. - pub fn new(storage: S) -> Self { - Self { - storage, - } - } - - /// Get storage reference. - pub fn storage(&self) -> &S { - &self.storage - } -} - -impl BlockchainHeaderBackend for Blockchain where Block: BlockT, S: Storage { - fn header(&self, id: BlockId) -> ClientResult> { - match RemoteBlockchain::header(self, id)? { - LocalOrRemote::Local(header) => Ok(Some(header)), - LocalOrRemote::Remote(_) => Err(ClientError::NotAvailableOnLightClient), - LocalOrRemote::Unknown => Ok(None), - } - } - - fn info(&self) -> BlockchainInfo { - self.storage.info() - } - - fn status(&self, id: BlockId) -> ClientResult { - self.storage.status(id) - } - - fn number(&self, hash: Block::Hash) -> ClientResult>> { - self.storage.number(hash) - } - - fn hash(&self, number: <::Header as HeaderT>::Number) -> ClientResult> { - self.storage.hash(number) - } -} - -impl HeaderMetadata for Blockchain where Block: BlockT, S: Storage { - type Error = ClientError; - - fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { - self.storage.header_metadata(hash) - } - - fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { - self.storage.insert_header_metadata(hash, metadata) - } - - fn remove_header_metadata(&self, hash: Block::Hash) { - self.storage.remove_header_metadata(hash) - } -} - -impl BlockchainBackend for Blockchain where Block: BlockT, S: Storage { - fn body(&self, _id: BlockId) -> ClientResult>> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn justification(&self, _id: BlockId) -> ClientResult> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn last_finalized(&self) -> ClientResult { - self.storage.last_finalized() - } - - fn cache(&self) -> Option>> { - self.storage.cache() - } - - fn leaves(&self) -> ClientResult> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn children(&self, _parent_hash: Block::Hash) -> ClientResult> { - Err(ClientError::NotAvailableOnLightClient) - } -} - -impl, Block: BlockT> ProvideCache for Blockchain { - fn cache(&self) -> Option>> { - self.storage.cache() - } -} - -impl RemoteBlockchain for Blockchain - where - S: Storage, -{ - fn header(&self, id: BlockId) -> ClientResult, - >> { - // first, try to read header from local storage - if let Some(local_header) = self.storage.header(id)? { - return Ok(LocalOrRemote::Local(local_header)); - } - - // we need to know block number to check if it's a part of CHT - let number = match id { - BlockId::Hash(hash) => match self.storage.number(hash)? { - Some(number) => number, - None => return Ok(LocalOrRemote::Unknown), - }, - BlockId::Number(number) => number, - }; - - // if the header is genesis (never pruned), non-canonical, or from future => return - if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown { - return Ok(LocalOrRemote::Unknown); - } - - Ok(LocalOrRemote::Remote(RemoteHeaderRequest { - cht_root: self.storage.header_cht_root(cht::size(), number)?, - block: number, - retry_count: None, - })) - } -} - -/// Returns future that resolves header either locally, or remotely. -pub fn future_header>( - blockchain: &dyn RemoteBlockchain, - fetcher: &F, - id: BlockId, -) -> impl Future, ClientError>> { - use futures03::future::{ready, Either, FutureExt}; - - match blockchain.header(id) { - Ok(LocalOrRemote::Remote(request)) => Either::Left( - fetcher - .remote_header(request) - .then(|header| ready(header.map(Some))) - ), - Ok(LocalOrRemote::Unknown) => Either::Right(ready(Ok(None))), - Ok(LocalOrRemote::Local(local_header)) => Either::Right(ready(Ok(Some(local_header)))), - Err(err) => Either::Right(ready(Err(err))), - } -} - -#[cfg(test)] -pub mod tests { - use std::collections::HashMap; - use parking_lot::Mutex; - use test_client::runtime::{Hash, Block, Header}; - use crate::blockchain::Info; - use super::*; - - pub type DummyBlockchain = Blockchain; - - pub struct DummyStorage { - pub changes_tries_cht_roots: HashMap, - pub aux_store: Mutex, Vec>>, - } - - impl DummyStorage { - pub fn new() -> Self { - DummyStorage { - changes_tries_cht_roots: HashMap::new(), - aux_store: Mutex::new(HashMap::new()), - } - } - } - - impl BlockchainHeaderBackend for DummyStorage { - fn header(&self, _id: BlockId) -> ClientResult> { - Err(ClientError::Backend("Test error".into())) - } - - fn info(&self) -> Info { - panic!("Test error") - } - - fn status(&self, _id: BlockId) -> ClientResult { - Err(ClientError::Backend("Test error".into())) - } - - fn number(&self, hash: Hash) -> ClientResult>> { - if hash == Default::default() { - Ok(Some(Default::default())) - } else { - Err(ClientError::Backend("Test error".into())) - } - } - - fn hash(&self, number: u64) -> ClientResult> { - if number == 0 { - Ok(Some(Default::default())) - } else { - Err(ClientError::Backend("Test error".into())) - } - } - } - - impl HeaderMetadata for DummyStorage { - type Error = ClientError; - - fn header_metadata(&self, hash: Hash) -> Result, Self::Error> { - self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header)) - .ok_or(ClientError::UnknownBlock("header not found".to_owned())) - } - fn insert_header_metadata(&self, _hash: Hash, _metadata: CachedHeaderMetadata) {} - fn remove_header_metadata(&self, _hash: Hash) {} - } - - impl AuxStore for DummyStorage { - fn insert_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >(&self, insert: I, _delete: D) -> ClientResult<()> { - for (k, v) in insert.into_iter() { - self.aux_store.lock().insert(k.to_vec(), v.to_vec()); - } - Ok(()) - } - - fn get_aux(&self, key: &[u8]) -> ClientResult>> { - Ok(self.aux_store.lock().get(key).cloned()) - } - } - - impl Storage for DummyStorage { - fn import_header( - &self, - _header: Header, - _cache: HashMap>, - _state: NewBlockState, - _aux_ops: Vec<(Vec, Option>)>, - ) -> ClientResult<()> { - Ok(()) - } - - fn set_head(&self, _block: BlockId) -> ClientResult<()> { - Err(ClientError::Backend("Test error".into())) - } - - fn finalize_header(&self, _block: BlockId) -> ClientResult<()> { - Err(ClientError::Backend("Test error".into())) - } - - fn last_finalized(&self) -> ClientResult { - Err(ClientError::Backend("Test error".into())) - } - - fn header_cht_root(&self, _cht_size: u64, _block: u64) -> ClientResult { - Err(ClientError::Backend("Test error".into())) - } - - fn changes_trie_cht_root(&self, cht_size: u64, block: u64) -> ClientResult { - cht::block_to_cht_number(cht_size, block) - .and_then(|cht_num| self.changes_tries_cht_roots.get(&cht_num)) - .cloned() - .ok_or_else(|| ClientError::Backend( - format!("Test error: CHT for block #{} not found", block) - ).into()) - } - - fn cache(&self) -> Option>> { - None - } - } -} diff --git a/core/client/src/light/call_executor.rs b/core/client/src/light/call_executor.rs deleted file mode 100644 index 65776bcfe08f3..0000000000000 --- a/core/client/src/light/call_executor.rs +++ /dev/null @@ -1,535 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Methods that light client could use to execute runtime calls. - -use std::{ - collections::HashSet, sync::Arc, panic::UnwindSafe, result, - cell::RefCell, rc::Rc, -}; - -use codec::{Encode, Decode}; -use primitives::{ - offchain::OffchainExt, H256, Blake2Hasher, convert_hash, NativeOrEncoded, - traits::CodeExecutor, -}; -use sr_primitives::{ - generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, NumberFor}, -}; -use state_machine::{ - self, Backend as StateBackend, OverlayedChanges, ExecutionStrategy, create_proof_check_backend, - execution_proof_check_on_trie_backend, ExecutionManager, ChangesTrieTransaction, -}; -use hash_db::Hasher; - -use crate::runtime_api::{ProofRecorder, InitializeBlock}; -use crate::backend::RemoteBackend; -use crate::call_executor::CallExecutor; -use crate::error::{Error as ClientError, Result as ClientResult}; -use crate::light::fetcher::RemoteCallRequest; -use executor::{RuntimeVersion, NativeVersion}; - -/// Call executor that is able to execute calls only on genesis state. -/// -/// Trying to execute call on non-genesis state leads to error. -pub struct GenesisCallExecutor { - backend: Arc, - local: L, -} - -impl GenesisCallExecutor { - /// Create new genesis call executor. - pub fn new(backend: Arc, local: L) -> Self { - Self { backend, local } - } -} - -impl Clone for GenesisCallExecutor { - fn clone(&self) -> Self { - GenesisCallExecutor { - backend: self.backend.clone(), - local: self.local.clone(), - } - } -} - -impl CallExecutor for - GenesisCallExecutor - where - Block: BlockT, - B: RemoteBackend, - Local: CallExecutor, -{ - type Error = ClientError; - - fn call( - &self, - id: &BlockId, - method: &str, - call_data: &[u8], - strategy: ExecutionStrategy, - side_effects_handler: Option, - ) -> ClientResult> { - match self.backend.is_local_state_available(id) { - true => self.local.call(id, method, call_data, strategy, side_effects_handler), - false => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn contextual_call< - 'a, - IB: Fn() -> ClientResult<()>, - EM: Fn( - Result, Self::Error>, - Result, Self::Error> - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - >( - &self, - initialize_block_fn: IB, - at: &BlockId, - method: &str, - call_data: &[u8], - changes: &RefCell, - initialize_block: InitializeBlock<'a, Block>, - _manager: ExecutionManager, - native_call: Option, - side_effects_handler: Option, - recorder: &Option>>>, - enable_keystore: bool, - ) -> 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, - initialize_block_fn, - at, - method, - call_data, - changes, - initialize_block, - ExecutionManager::NativeWhenPossible, - native_call, - side_effects_handler, - recorder, - enable_keystore, - ).map_err(|e| ClientError::Execution(Box::new(e.to_string()))), - false => Err(ClientError::NotAvailableOnLightClient), - } - } - - fn runtime_version(&self, id: &BlockId) -> ClientResult { - match self.backend.is_local_state_available(id) { - true => self.local.runtime_version(id), - false => Err(ClientError::NotAvailableOnLightClient), - } - } - - 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, - _side_effects_handler: Option, - ) -> ClientResult<( - NativeOrEncoded, - (S::Transaction, ::Out), - Option>>, - )> { - Err(ClientError::NotAvailableOnLightClient) - } - - fn prove_at_trie_state>( - &self, - _state: &state_machine::TrieBackend, - _changes: &mut OverlayedChanges, - _method: &str, - _call_data: &[u8] - ) -> ClientResult<(Vec, Vec>)> { - Err(ClientError::NotAvailableOnLightClient) - } - - 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. -/// Proof includes both environment preparation proof and method execution proof. -pub fn prove_execution( - mut state: S, - header: Block::Header, - executor: &E, - method: &str, - call_data: &[u8], -) -> ClientResult<(Vec, Vec>)> - where - Block: BlockT, - S: StateBackend, - E: CallExecutor, -{ - let trie_state = state.as_trie_backend() - .ok_or_else(|| Box::new(state_machine::ExecutionError::UnableToGenerateProof) as Box)?; - - // prepare execution environment + record preparation proof - let mut changes = Default::default(); - let (_, init_proof) = executor.prove_at_trie_state( - trie_state, - &mut changes, - "Core_initialize_block", - &header.encode(), - )?; - - // execute method + record execution proof - let (result, exec_proof) = executor.prove_at_trie_state(&trie_state, &mut changes, method, call_data)?; - let total_proof = init_proof.into_iter() - .chain(exec_proof.into_iter()) - .collect::>() - .into_iter() - .collect(); - - Ok((result, total_proof)) -} - -/// Check remote contextual execution proof using given backend. -/// -/// Method is executed using passed header as environment' current block. -/// Proof should include both environment preparation proof and method execution proof. -pub fn check_execution_proof( - executor: &E, - request: &RemoteCallRequest

, - remote_proof: Vec>, -) -> ClientResult> - where - Header: HeaderT, - E: CodeExecutor, - H: Hasher, -{ - check_execution_proof_with_make_header::( - executor, - request, - remote_proof, - |header|
::new( - *header.number() + One::one(), - Default::default(), - Default::default(), - header.hash(), - Default::default(), - ), - ) -} - -fn check_execution_proof_with_make_header Header>( - executor: &E, - request: &RemoteCallRequest
, - remote_proof: Vec>, - make_next_header: MakeNextHeader, -) -> ClientResult> - where - Header: HeaderT, - E: CodeExecutor, - H: Hasher, -{ - let local_state_root = request.header.state_root(); - let root: H::Out = convert_hash(&local_state_root); - - // prepare execution environment + check preparation proof - let mut changes = OverlayedChanges::default(); - let trie_backend = create_proof_check_backend(root, remote_proof)?; - let next_header = make_next_header(&request.header); - execution_proof_check_on_trie_backend::( - &trie_backend, - &mut changes, - executor, - "Core_initialize_block", - &next_header.encode(), - None, - )?; - - // execute method - execution_proof_check_on_trie_backend::( - &trie_backend, - &mut changes, - executor, - &request.method, - &request.call_data, - None, - ).map_err(Into::into) -} - -#[cfg(test)] -mod tests { - use super::*; - use consensus::BlockOrigin; - use test_client::{self, runtime::{Header, Digest, Block}, ClientExt, TestClient}; - use executor::{NativeExecutor, WasmExecutionMethod}; - use primitives::Blake2Hasher; - use crate::backend::{Backend, NewBlockState}; - use crate::in_mem::Backend as InMemBackend; - - struct DummyCallExecutor; - - impl CallExecutor for DummyCallExecutor { - type Error = ClientError; - - fn call( - &self, - _id: &BlockId, - _method: &str, - _call_data: &[u8], - _strategy: ExecutionStrategy, - _side_effects_handler: Option, - ) -> Result, ClientError> { - Ok(vec![42]) - } - - fn contextual_call< - 'a, - IB: Fn() -> ClientResult<()>, - EM: Fn( - Result, Self::Error>, - Result, Self::Error> - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - >( - &self, - _initialize_block_fn: IB, - _at: &BlockId, - _method: &str, - _call_data: &[u8], - _changes: &RefCell, - _initialize_block: InitializeBlock<'a, Block>, - _execution_manager: ExecutionManager, - _native_call: Option, - _side_effects_handler: Option, - _proof_recorder: &Option>>>, - _enable_keystore: bool, - ) -> ClientResult> where ExecutionManager: Clone { - unreachable!() - } - - fn runtime_version(&self, _id: &BlockId) -> Result { - unreachable!() - } - - fn call_at_state< - S: state_machine::Backend, - F: FnOnce( - Result, Self::Error>, - Result, Self::Error> - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - >(&self, - _state: &S, - _overlay: &mut OverlayedChanges, - _method: &str, - _call_data: &[u8], - _manager: ExecutionManager, - _native_call: Option, - _side_effects_handler: Option, - ) -> Result< - ( - NativeOrEncoded, - (S::Transaction, H256), - Option>>, - ), - ClientError, - > { - unreachable!() - } - - fn prove_at_trie_state>( - &self, - _trie_state: &state_machine::TrieBackend, - _overlay: &mut OverlayedChanges, - _method: &str, - _call_data: &[u8] - ) -> Result<(Vec, Vec>), ClientError> { - unreachable!() - } - - fn native_runtime_version(&self) -> Option<&NativeVersion> { - unreachable!() - } - } - - fn local_executor() -> NativeExecutor { - NativeExecutor::new(WasmExecutionMethod::Interpreted, None) - } - - #[test] - fn execution_proof_is_generated_and_checked() { - fn execute(remote_client: &TestClient, at: u64, method: &'static str) -> (Vec, Vec) { - let remote_block_id = BlockId::Number(at); - let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - - // 'fetch' execution proof from remote node - let (remote_result, remote_execution_proof) = remote_client.execution_proof( - &remote_block_id, - method, - &[] - ).unwrap(); - - // check remote execution proof locally - let local_result = check_execution_proof::<_, _, Blake2Hasher>( - &local_executor(), - &RemoteCallRequest { - block: test_client::runtime::Hash::default(), - header: remote_header, - method: method.into(), - call_data: vec![], - retry_count: None, - }, - remote_execution_proof, - ).unwrap(); - - (remote_result, local_result) - } - - fn execute_with_proof_failure(remote_client: &TestClient, at: u64, method: &'static str) { - let remote_block_id = BlockId::Number(at); - let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - - // 'fetch' execution proof from remote node - let (_, remote_execution_proof) = remote_client.execution_proof( - &remote_block_id, - method, - &[] - ).unwrap(); - - // check remote execution proof locally - let execution_result = check_execution_proof_with_make_header::<_, _, Blake2Hasher, _>( - &local_executor(), - &RemoteCallRequest { - block: test_client::runtime::Hash::default(), - header: remote_header, - method: method.into(), - call_data: vec![], - retry_count: None, - }, - remote_execution_proof, - |header|
::new( - at + 1, - Default::default(), - Default::default(), - header.hash(), - header.digest().clone(), // this makes next header wrong - ), - ); - match execution_result { - Err(crate::error::Error::Execution(_)) => (), - _ => panic!("Unexpected execution result: {:?}", execution_result), - } - } - - // prepare remote client - let remote_client = test_client::new(); - for i in 1u32..3u32 { - let mut digest = Digest::default(); - digest.push(sr_primitives::generic::DigestItem::Other::(i.to_le_bytes().to_vec())); - remote_client.import_justified( - BlockOrigin::Own, - remote_client.new_block(digest).unwrap().bake().unwrap(), - Default::default(), - ).unwrap(); - } - - // check method that doesn't requires environment - let (remote, local) = execute(&remote_client, 0, "Core_version"); - assert_eq!(remote, local); - - let (remote, local) = execute(&remote_client, 2, "Core_version"); - assert_eq!(remote, local); - - // check method that requires environment - let (_, block) = execute(&remote_client, 0, "BlockBuilder_finalize_block"); - let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); - assert_eq!(local_block.number, 1); - - let (_, block) = execute(&remote_client, 2, "BlockBuilder_finalize_block"); - let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); - assert_eq!(local_block.number, 3); - - // check that proof check doesn't panic even if proof is incorrect AND no panic handler is set - execute_with_proof_failure(&remote_client, 2, "Core_version"); - - // check that proof check doesn't panic even if proof is incorrect AND panic handler is set - panic_handler::set("TEST", "1.2.3"); - execute_with_proof_failure(&remote_client, 2, "Core_version"); - } - - #[test] - fn code_is_executed_at_genesis_only() { - let backend = Arc::new(InMemBackend::::new()); - let def = H256::default(); - let header0 = 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 genesis_executor = GenesisCallExecutor::new(backend, DummyCallExecutor); - assert_eq!( - genesis_executor.call( - &BlockId::Number(0), - "test_method", - &[], - ExecutionStrategy::NativeElseWasm, - None, - ).unwrap(), - vec![42], - ); - - let call_on_unavailable = genesis_executor.call( - &BlockId::Number(1), - "test_method", - &[], - ExecutionStrategy::NativeElseWasm, - None, - ); - - match call_on_unavailable { - Err(ClientError::NotAvailableOnLightClient) => (), - _ => unreachable!("unexpected result: {:?}", call_on_unavailable), - } - } -} diff --git a/core/client/src/light/fetcher.rs b/core/client/src/light/fetcher.rs deleted file mode 100644 index dbf6d41c38f16..0000000000000 --- a/core/client/src/light/fetcher.rs +++ /dev/null @@ -1,993 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Light client data fetcher. Fetches requested data from remote full nodes. - -use std::sync::Arc; -use std::collections::{BTreeMap, HashMap}; -use std::marker::PhantomData; -use std::future::Future; - -use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; -use codec::{Decode, Encode}; -use primitives::{ChangesTrieConfiguration, convert_hash, traits::CodeExecutor, H256}; -use sr_primitives::traits::{ - Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor, - SimpleArithmetic, CheckedConversion, Zero, -}; -use state_machine::{ - ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, - TrieBackend, read_proof_check, key_changes_proof_check, create_proof_check_backend_storage, - read_child_proof_check, -}; - -use crate::cht; -use crate::error::{Error as ClientError, 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)] -pub struct RemoteCallRequest { - /// Call at state of given block. - pub block: Header::Hash, - /// Header of block at which call is performed. - pub header: Header, - /// Method to call. - pub method: String, - /// Call data. - pub call_data: Vec, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Remote canonical header request. -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -pub struct RemoteHeaderRequest { - /// The root of CHT this block is included in. - pub cht_root: Header::Hash, - /// Number of the header to query. - pub block: Header::Number, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Remote storage read request. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct RemoteReadRequest { - /// Read at state of given block. - pub block: Header::Hash, - /// Header of block at which read is performed. - pub header: Header, - /// Storage key to read. - pub keys: Vec>, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Remote storage read child request. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct RemoteReadChildRequest { - /// Read at state of given block. - pub block: Header::Hash, - /// Header of block at which read is performed. - pub header: Header, - /// Storage key for child. - pub storage_key: Vec, - /// Child storage key to read. - pub keys: Vec>, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Remote key changes read request. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct RemoteChangesRequest { - /// Changes trie configuration. - pub changes_trie_config: ChangesTrieConfiguration, - /// Query changes from range of blocks, starting (and including) with this hash... - pub first_block: (Header::Number, Header::Hash), - /// ...ending (and including) with this hash. Should come after first_block and - /// be the part of the same fork. - pub last_block: (Header::Number, Header::Hash), - /// Only use digests from blocks up to this hash. Should be last_block OR come - /// after this block and be the part of the same fork. - pub max_block: (Header::Number, Header::Hash), - /// Known changes trie roots for the range of blocks [tries_roots.0..max_block]. - /// Proofs for roots of ascendants of tries_roots.0 are provided by the remote node. - pub tries_roots: (Header::Number, Header::Hash, Vec), - /// Optional Child Storage key to read. - pub storage_key: Option>, - /// Storage key to read. - pub key: Vec, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Key changes read proof. -#[derive(Debug, PartialEq, Eq)] -pub struct ChangesProof { - /// Max block that has been used in changes query. - pub max_block: Header::Number, - /// All touched nodes of all changes tries. - pub proof: Vec>, - /// All changes tries roots that have been touched AND are missing from - /// the requester' node. It is a map of block number => changes trie root. - pub roots: BTreeMap, - /// The proofs for all changes tries roots that have been touched AND are - /// missing from the requester' node. It is a map of CHT number => proof. - pub roots_proof: Vec>, -} - -/// Remote block body request -#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] -pub struct RemoteBodyRequest { - /// Header of the requested block body - pub header: Header, - /// Number of times to retry request. None means that default RETRY_COUNT is used. - pub retry_count: Option, -} - -/// Light client data fetcher. Implementations of this trait must check if remote data -/// is correct (see FetchedDataChecker) and return already checked data. -pub trait Fetcher: Send + Sync { - /// Remote header future. - type RemoteHeaderResult: Future> + Send + 'static; - /// Remote storage read future. - type RemoteReadResult: Future, Option>>, ClientError>> + Send + 'static; - /// Remote call result future. - type RemoteCallResult: Future, ClientError>> + Send + 'static; - /// Remote changes result future. - type RemoteChangesResult: Future, u32)>, ClientError>> + Send + 'static; - /// Remote block body result future. - type RemoteBodyResult: Future, ClientError>> + Send + 'static; - - /// Fetch remote header. - fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult; - /// Fetch remote storage value. - fn remote_read( - &self, - request: RemoteReadRequest - ) -> Self::RemoteReadResult; - /// Fetch remote storage child value. - fn remote_read_child( - &self, - request: RemoteReadChildRequest - ) -> Self::RemoteReadResult; - /// Fetch remote call result. - fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult; - /// Fetch remote changes ((block number, extrinsic index)) where given key has been changed - /// at a given blocks range. - fn remote_changes(&self, request: RemoteChangesRequest) -> Self::RemoteChangesResult; - /// Fetch remote block body - fn remote_body(&self, request: RemoteBodyRequest) -> Self::RemoteBodyResult; -} - -/// Light client remote data checker. -/// -/// Implementations of this trait should not use any prunable blockchain data -/// except that is passed to its methods. -pub trait FetchChecker: Send + Sync { - /// Check remote header proof. - fn check_header_proof( - &self, - request: &RemoteHeaderRequest, - header: Option, - remote_proof: Vec> - ) -> ClientResult; - /// Check remote storage read proof. - fn check_read_proof( - &self, - request: &RemoteReadRequest, - remote_proof: Vec> - ) -> ClientResult, Option>>>; - /// Check remote storage read proof. - fn check_read_child_proof( - &self, - request: &RemoteReadChildRequest, - remote_proof: Vec> - ) -> ClientResult, Option>>>; - /// Check remote method execution proof. - fn check_execution_proof( - &self, - request: &RemoteCallRequest, - remote_proof: Vec> - ) -> ClientResult>; - /// Check remote changes query proof. - fn check_changes_proof( - &self, - request: &RemoteChangesRequest, - proof: ChangesProof - ) -> ClientResult, u32)>>; - /// Check remote body proof. - fn check_body_proof( - &self, - request: &RemoteBodyRequest, - body: Vec - ) -> ClientResult>; -} - -/// Remote data checker. -pub struct LightDataChecker> { - blockchain: Arc>, - executor: E, - _hasher: PhantomData<(B, H)>, -} - -impl> LightDataChecker { - /// Create new light data checker. - pub fn new(blockchain: Arc>, executor: E) -> Self { - Self { - blockchain, executor, _hasher: PhantomData - } - } - - /// Check remote changes query proof assuming that CHT-s are of given size. - fn check_changes_proof_with_cht_size( - &self, - request: &RemoteChangesRequest, - remote_proof: ChangesProof, - cht_size: NumberFor, - ) -> ClientResult, u32)>> - where - H: Hasher, - H::Out: Ord, - { - // since we need roots of all changes tries for the range begin..max - // => remote node can't use max block greater that one that we have passed - if remote_proof.max_block > request.max_block.0 || remote_proof.max_block < request.last_block.0 { - return Err(ClientError::ChangesTrieAccessFailed(format!( - "Invalid max_block used by the remote node: {}. Local: {}..{}..{}", - remote_proof.max_block, request.first_block.0, request.last_block.0, request.max_block.0, - )).into()); - } - - // check if remote node has responded with extra changes trie roots proofs - // all changes tries roots must be in range [request.first_block.0; request.tries_roots.0) - let is_extra_first_root = remote_proof.roots.keys().next() - .map(|first_root| *first_root < request.first_block.0 - || *first_root >= request.tries_roots.0) - .unwrap_or(false); - let is_extra_last_root = remote_proof.roots.keys().next_back() - .map(|last_root| *last_root >= request.tries_roots.0) - .unwrap_or(false); - if is_extra_first_root || is_extra_last_root { - return Err(ClientError::ChangesTrieAccessFailed(format!( - "Extra changes tries roots proofs provided by the remote node: [{:?}..{:?}]. Expected in range: [{}; {})", - remote_proof.roots.keys().next(), remote_proof.roots.keys().next_back(), - request.first_block.0, request.tries_roots.0, - )).into()); - } - - // if request has been composed when some required headers were already pruned - // => remote node has sent us CHT-based proof of required changes tries roots - // => check that this proof is correct before proceeding with changes proof - let remote_max_block = remote_proof.max_block; - let remote_roots = remote_proof.roots; - let remote_roots_proof = remote_proof.roots_proof; - let remote_proof = remote_proof.proof; - if !remote_roots.is_empty() { - self.check_changes_tries_proof( - cht_size, - &remote_roots, - remote_roots_proof, - )?; - } - - // FIXME: remove this in https://github.com/paritytech/substrate/pull/3201 - let changes_trie_config_range = ChangesTrieConfigurationRange { - config: &request.changes_trie_config, - zero: Zero::zero(), - end: None, - }; - - // and now check the key changes proof + get the changes - key_changes_proof_check::( - changes_trie_config_range, - &RootsStorage { - roots: (request.tries_roots.0, &request.tries_roots.2), - prev_roots: remote_roots, - }, - remote_proof, - request.first_block.0, - &ChangesTrieAnchorBlockId { - hash: convert_hash(&request.last_block.1), - number: request.last_block.0, - }, - remote_max_block, - request.storage_key.as_ref().map(Vec::as_slice), - &request.key) - .map_err(|err| ClientError::ChangesTrieAccessFailed(err)) - } - - /// Check CHT-based proof for changes tries roots. - fn check_changes_tries_proof( - &self, - cht_size: NumberFor, - remote_roots: &BTreeMap, B::Hash>, - remote_roots_proof: Vec>, - ) -> ClientResult<()> - where - H: Hasher, - H::Out: Ord, - { - // all the checks are sharing the same storage - let storage = create_proof_check_backend_storage(remote_roots_proof); - - // we remote_roots.keys() are sorted => we can use this to group changes tries roots - // that are belongs to the same CHT - let blocks = remote_roots.keys().cloned(); - cht::for_each_cht_group::(cht_size, blocks, |mut storage, _, cht_blocks| { - // get local changes trie CHT root for given CHT - // it should be there, because it is never pruned AND request has been composed - // when required header has been pruned (=> replaced with CHT) - let first_block = cht_blocks.first().cloned() - .expect("for_each_cht_group never calls callback with empty groups"); - let local_cht_root = self.blockchain.storage().changes_trie_cht_root(cht_size, first_block)?; - - // check changes trie root for every block within CHT range - for block in cht_blocks { - // check if the proofs storage contains the root - // normally this happens in when the proving backend is created, but since - // we share the storage for multiple checks, do it here - let mut cht_root = H::Out::default(); - cht_root.as_mut().copy_from_slice(local_cht_root.as_ref()); - if !storage.contains(&cht_root, EMPTY_PREFIX) { - return Err(ClientError::InvalidCHTProof.into()); - } - - // check proof for single changes trie root - let proving_backend = TrieBackend::new(storage, cht_root); - let remote_changes_trie_root = remote_roots[&block]; - cht::check_proof_on_proving_backend::( - local_cht_root, - block, - remote_changes_trie_root, - &proving_backend)?; - - // and return the storage to use in following checks - storage = proving_backend.into_storage(); - } - - Ok(storage) - }, storage) - } -} - -impl FetchChecker for LightDataChecker - where - Block: BlockT, - E: CodeExecutor, - H: Hasher, - S: BlockchainStorage, -{ - fn check_header_proof( - &self, - request: &RemoteHeaderRequest, - remote_header: Option, - remote_proof: Vec> - ) -> ClientResult { - let remote_header = remote_header.ok_or_else(|| - ClientError::from(ClientError::InvalidCHTProof))?; - let remote_header_hash = remote_header.hash(); - cht::check_proof::( - request.cht_root, - request.block, - remote_header_hash, - remote_proof) - .map(|_| remote_header) - } - - fn check_read_proof( - &self, - request: &RemoteReadRequest, - remote_proof: Vec>, - ) -> ClientResult, Option>>> { - read_proof_check::( - convert_hash(request.header.state_root()), - remote_proof, - request.keys.iter(), - ).map_err(Into::into) - } - - fn check_read_child_proof( - &self, - request: &RemoteReadChildRequest, - remote_proof: Vec> - ) -> ClientResult, Option>>> { - read_child_proof_check::( - convert_hash(request.header.state_root()), - remote_proof, - &request.storage_key, - request.keys.iter(), - ).map_err(Into::into) - } - - fn check_execution_proof( - &self, - request: &RemoteCallRequest, - remote_proof: Vec> - ) -> ClientResult> { - check_execution_proof::<_, _, H>(&self.executor, request, remote_proof) - } - - fn check_changes_proof( - &self, - request: &RemoteChangesRequest, - remote_proof: ChangesProof - ) -> ClientResult, u32)>> { - self.check_changes_proof_with_cht_size(request, remote_proof, cht::size()) - } - - fn check_body_proof( - &self, - request: &RemoteBodyRequest, - body: Vec - ) -> ClientResult> { - // TODO: #2621 - let extrinsics_root = HashFor::::ordered_trie_root( - body.iter().map(Encode::encode).collect(), - ); - if *request.header.extrinsics_root() == extrinsics_root { - Ok(body) - } else { - Err(format!("RemoteBodyRequest: invalid extrinsics root expected: {} but got {}", - *request.header.extrinsics_root(), - extrinsics_root, - ).into()) - } - - } -} - -/// A view of BTreeMap as a changes trie roots storage. -struct RootsStorage<'a, Number: SimpleArithmetic, Hash: 'a> { - roots: (Number, &'a [Hash]), - prev_roots: BTreeMap, -} - -impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a, Number, Hash> - where - H: Hasher, - Number: ::std::fmt::Display + ::std::hash::Hash + Clone + SimpleArithmetic + Encode + Decode + Send + Sync + 'static, - Hash: 'a + Send + Sync + Clone + AsRef<[u8]>, -{ - fn build_anchor( - &self, - _hash: H::Out, - ) -> Result, String> { - Err("build_anchor is only called when building block".into()) - } - - fn root( - &self, - _anchor: &ChangesTrieAnchorBlockId, - block: Number, - ) -> Result, String> { - // we can't ask for roots from parallel forks here => ignore anchor - let root = if block < self.roots.0 { - self.prev_roots.get(&Number::unique_saturated_from(block)).cloned() - } else { - let index: Option = block.checked_sub(&self.roots.0).and_then(|index| index.checked_into()); - match index { - Some(index) => self.roots.1.get(index as usize).cloned(), - None => None, - } - }; - - Ok(root.map(|root| { - let mut hasher_root: H::Out = Default::default(); - hasher_root.as_mut().copy_from_slice(root.as_ref()); - hasher_root - })) - } -} - -#[cfg(test)] -pub mod tests { - use futures03::future::Ready; - use parking_lot::Mutex; - use codec::Decode; - use crate::client::tests::prepare_client_with_key_changes; - use executor::{NativeExecutor, WasmExecutionMethod}; - use crate::error::Error as ClientError; - use test_client::{ - self, ClientExt, blockchain::HeaderBackend, AccountKeyring, - runtime::{self, Hash, Block, Header, Extrinsic} - }; - use consensus::BlockOrigin; - - use crate::in_mem::{Blockchain as InMemoryBlockchain}; - use crate::light::fetcher::{Fetcher, FetchChecker, LightDataChecker, - RemoteCallRequest, RemoteHeaderRequest}; - use crate::light::blockchain::tests::{DummyStorage, DummyBlockchain}; - use primitives::{blake2_256, Blake2Hasher, H256}; - use primitives::storage::{well_known_keys, StorageKey}; - use sr_primitives::generic::BlockId; - use state_machine::Backend; - use super::*; - - pub type OkCallFetcher = Mutex>; - - fn not_implemented_in_tests() -> Ready> - where - E: std::convert::From<&'static str>, - { - futures03::future::ready(Err("Not implemented on test node".into())) - } - - impl Fetcher for OkCallFetcher { - type RemoteHeaderResult = Ready>; - type RemoteReadResult = Ready, Option>>, ClientError>>; - type RemoteCallResult = Ready, ClientError>>; - type RemoteChangesResult = Ready, u32)>, ClientError>>; - type RemoteBodyResult = Ready, ClientError>>; - - fn remote_header(&self, _request: RemoteHeaderRequest
) -> Self::RemoteHeaderResult { - not_implemented_in_tests() - } - - fn remote_read(&self, _request: RemoteReadRequest
) -> Self::RemoteReadResult { - not_implemented_in_tests() - } - - fn remote_read_child(&self, _request: RemoteReadChildRequest
) -> Self::RemoteReadResult { - not_implemented_in_tests() - } - - fn remote_call(&self, _request: RemoteCallRequest
) -> Self::RemoteCallResult { - futures03::future::ready(Ok((*self.lock()).clone())) - } - - fn remote_changes(&self, _request: RemoteChangesRequest
) -> Self::RemoteChangesResult { - not_implemented_in_tests() - } - - fn remote_body(&self, _request: RemoteBodyRequest
) -> Self::RemoteBodyResult { - not_implemented_in_tests() - } - } - - type TestChecker = LightDataChecker< - NativeExecutor, - Blake2Hasher, - Block, - DummyStorage, - >; - - fn local_executor() -> NativeExecutor { - NativeExecutor::new(WasmExecutionMethod::Interpreted, None) - } - - fn prepare_for_read_proof_check() -> (TestChecker, Header, Vec>, u32) { - // prepare remote client - let remote_client = test_client::new(); - let remote_block_id = BlockId::Number(0); - let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); - let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap() - .storage_root(::std::iter::empty()).0.into(); - - // 'fetch' read proof from remote node - let heap_pages = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::HEAP_PAGES.to_vec())) - .unwrap() - .and_then(|v| Decode::decode(&mut &v.0[..]).ok()).unwrap(); - let remote_read_proof = remote_client.read_proof( - &remote_block_id, - &[well_known_keys::HEAP_PAGES], - ).unwrap(); - - // check remote read proof locally - let local_storage = InMemoryBlockchain::::new(); - local_storage.insert( - remote_block_hash, - remote_block_header.clone(), - None, - None, - crate::backend::NewBlockState::Final, - ).unwrap(); - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor() - ); - (local_checker, remote_block_header, remote_read_proof, heap_pages) - } - - fn prepare_for_read_child_proof_check() -> (TestChecker, Header, Vec>, Vec) { - use test_client::DefaultTestClientBuilderExt; - use test_client::TestClientBuilderExt; - // prepare remote client - let remote_client = test_client::TestClientBuilder::new() - .add_extra_child_storage(b":child_storage:default:child1".to_vec(), b"key1".to_vec(), b"value1".to_vec()) - .build(); - let remote_block_id = BlockId::Number(0); - let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); - let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap() - .storage_root(::std::iter::empty()).0.into(); - - // 'fetch' child read proof from remote node - let child_value = remote_client.child_storage( - &remote_block_id, - &StorageKey(b":child_storage:default:child1".to_vec()), - &StorageKey(b"key1".to_vec()), - ).unwrap().unwrap().0; - assert_eq!(b"value1"[..], child_value[..]); - let remote_read_proof = remote_client.read_child_proof( - &remote_block_id, - b":child_storage:default:child1", - &[b"key1"], - ).unwrap(); - - // check locally - let local_storage = InMemoryBlockchain::::new(); - local_storage.insert( - remote_block_hash, - remote_block_header.clone(), - None, - None, - crate::backend::NewBlockState::Final, - ).unwrap(); - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - ); - (local_checker, remote_block_header, remote_read_proof, child_value) - } - - fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, Vec>) { - // prepare remote client - let remote_client = test_client::new(); - let mut local_headers_hashes = Vec::new(); - for i in 0..4 { - let builder = remote_client.new_block(Default::default()).unwrap(); - remote_client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - local_headers_hashes.push(remote_client.block_hash(i + 1) - .map_err(|_| ClientError::Backend("TestError".into()))); - } - - // 'fetch' header proof from remote node - let remote_block_id = BlockId::Number(1); - let (remote_block_header, remote_header_proof) = remote_client.header_proof_with_cht_size(&remote_block_id, 4).unwrap(); - - // check remote read proof locally - let local_storage = InMemoryBlockchain::::new(); - let local_cht_root = cht::compute_root::(4, 0, local_headers_hashes).unwrap(); - if insert_cht { - local_storage.insert_cht_root(1, local_cht_root); - } - let local_checker = LightDataChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - ); - (local_checker, local_cht_root, remote_block_header, remote_header_proof) - } - - fn header_with_computed_extrinsics_root(extrinsics: Vec) -> Header { - use trie::{TrieConfiguration, trie_types::Layout}; - let iter = extrinsics.iter().map(Encode::encode); - let extrinsics_root = Layout::::ordered_trie_root(iter); - - // only care about `extrinsics_root` - Header::new(0, extrinsics_root, H256::zero(), H256::zero(), Default::default()) - } - - #[test] - fn storage_read_proof_is_generated_and_checked() { - let (local_checker, remote_block_header, remote_read_proof, heap_pages) = prepare_for_read_proof_check(); - assert_eq!((&local_checker as &dyn FetchChecker).check_read_proof(&RemoteReadRequest::
{ - block: remote_block_header.hash(), - header: remote_block_header, - keys: vec![well_known_keys::HEAP_PAGES.to_vec()], - retry_count: None, - }, remote_read_proof).unwrap().remove(well_known_keys::HEAP_PAGES).unwrap().unwrap()[0], heap_pages as u8); - } - - #[test] - fn storage_child_read_proof_is_generated_and_checked() { - let ( - local_checker, - remote_block_header, - remote_read_proof, - result, - ) = prepare_for_read_child_proof_check(); - assert_eq!((&local_checker as &dyn FetchChecker).check_read_child_proof( - &RemoteReadChildRequest::
{ - block: remote_block_header.hash(), - header: remote_block_header, - storage_key: b":child_storage:default:child1".to_vec(), - keys: vec![b"key1".to_vec()], - retry_count: None, - }, - remote_read_proof - ).unwrap().remove(b"key1".as_ref()).unwrap().unwrap(), result); - } - - #[test] - fn header_proof_is_generated_and_checked() { - let (local_checker, local_cht_root, remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); - assert_eq!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ - cht_root: local_cht_root, - block: 1, - retry_count: None, - }, Some(remote_block_header.clone()), remote_header_proof).unwrap(), remote_block_header); - } - - #[test] - fn check_header_proof_fails_if_cht_root_is_invalid() { - let (local_checker, _, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); - remote_block_header.number = 100; - assert!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ - cht_root: Default::default(), - block: 1, - retry_count: None, - }, Some(remote_block_header.clone()), remote_header_proof).is_err()); - } - - #[test] - fn check_header_proof_fails_if_invalid_header_provided() { - let (local_checker, local_cht_root, mut remote_block_header, remote_header_proof) = prepare_for_header_proof_check(true); - remote_block_header.number = 100; - assert!((&local_checker as &dyn FetchChecker).check_header_proof(&RemoteHeaderRequest::
{ - cht_root: local_cht_root, - block: 1, - retry_count: None, - }, Some(remote_block_header.clone()), remote_header_proof).is_err()); - } - - #[test] - fn changes_proof_is_generated_and_checked_when_headers_are_not_pruned() { - let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - ); - let local_checker = &local_checker as &dyn FetchChecker; - let max = remote_client.info().chain.best_number; - let max_hash = remote_client.info().chain.best_hash; - - for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { - let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); - let end_hash = remote_client.block_hash(end).unwrap().unwrap(); - - // 'fetch' changes proof from remote node - let key = StorageKey(key); - let remote_proof = remote_client.key_changes_proof( - begin_hash, end_hash, begin_hash, max_hash, None, &key - ).unwrap(); - - // check proof on local client - let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); - let request = RemoteChangesRequest::
{ - changes_trie_config: runtime::changes_trie_config(), - first_block: (begin, begin_hash), - last_block: (end, end_hash), - max_block: (max, max_hash), - tries_roots: (begin, begin_hash, local_roots_range), - key: key.0, - storage_key: None, - retry_count: None, - }; - let local_result = local_checker.check_changes_proof(&request, ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof, - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - }).unwrap(); - - // ..and ensure that result is the same as on remote node - match local_result == expected_result { - true => (), - false => panic!(format!("Failed test {}: local = {:?}, expected = {:?}", - index, local_result, expected_result)), - } - } - } - - #[test] - fn changes_proof_is_generated_and_checked_when_headers_are_pruned() { - // we're testing this test case here: - // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let dave = StorageKey(dave); - - // 'fetch' changes proof from remote node: - // we're fetching changes for range b1..b4 - // we do not know changes trie roots before b3 (i.e. we only know b3+b4) - // but we have changes trie CHT root for b1...b4 - let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); - let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap(); - let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap(); - let remote_proof = remote_client.key_changes_proof_with_cht_size( - b1, b4, b3, b4, None, &dave, 4 - ).unwrap(); - - // prepare local checker, having a root of changes trie CHT#0 - let local_cht_root = cht::compute_root::(4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); - let mut local_storage = DummyStorage::new(); - local_storage.changes_tries_cht_roots.insert(0, local_cht_root); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(local_storage)), - local_executor(), - ); - - // check proof on local client - let request = RemoteChangesRequest::
{ - changes_trie_config: runtime::changes_trie_config(), - first_block: (1, b1), - last_block: (4, b4), - max_block: (4, b4), - tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]), - storage_key: None, - key: dave.0, - retry_count: None, - }; - let local_result = local_checker.check_changes_proof_with_cht_size(&request, ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof, - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - }, 4).unwrap(); - - assert_eq!(local_result, vec![(4, 0), (1, 1), (1, 0)]); - } - - #[test] - fn check_changes_proof_fails_if_proof_is_wrong() { - let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - ); - let local_checker = &local_checker as &dyn FetchChecker; - let max = remote_client.info().chain.best_number; - let max_hash = remote_client.info().chain.best_hash; - - let (begin, end, key, _) = test_cases[0].clone(); - let begin_hash = remote_client.block_hash(begin).unwrap().unwrap(); - let end_hash = remote_client.block_hash(end).unwrap().unwrap(); - - // 'fetch' changes proof from remote node - let key = StorageKey(key); - let remote_proof = remote_client.key_changes_proof( - begin_hash, end_hash, begin_hash, max_hash, None, &key).unwrap(); - - let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); - let request = RemoteChangesRequest::
{ - changes_trie_config: runtime::changes_trie_config(), - first_block: (begin, begin_hash), - last_block: (end, end_hash), - max_block: (max, max_hash), - tries_roots: (begin, begin_hash, local_roots_range.clone()), - storage_key: None, - key: key.0, - retry_count: None, - }; - - // check proof on local client using max from the future - assert!(local_checker.check_changes_proof(&request, ChangesProof { - max_block: remote_proof.max_block + 1, - proof: remote_proof.proof.clone(), - roots: remote_proof.roots.clone(), - roots_proof: remote_proof.roots_proof.clone(), - }).is_err()); - - // check proof on local client using broken proof - assert!(local_checker.check_changes_proof(&request, ChangesProof { - max_block: remote_proof.max_block, - proof: local_roots_range.clone().into_iter().map(|v| v.as_ref().to_vec()).collect(), - roots: remote_proof.roots, - roots_proof: remote_proof.roots_proof, - }).is_err()); - - // extra roots proofs are provided - assert!(local_checker.check_changes_proof(&request, ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof.clone(), - roots: vec![(begin - 1, Default::default())].into_iter().collect(), - roots_proof: vec![], - }).is_err()); - assert!(local_checker.check_changes_proof(&request, ChangesProof { - max_block: remote_proof.max_block, - proof: remote_proof.proof.clone(), - roots: vec![(end + 1, Default::default())].into_iter().collect(), - roots_proof: vec![], - }).is_err()); - } - - #[test] - fn check_changes_tries_proof_fails_if_proof_is_wrong() { - // we're testing this test case here: - // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), - let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let local_cht_root = cht::compute_root::( - 4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); - let dave = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); - let dave = StorageKey(dave); - - // 'fetch' changes proof from remote node: - // we're fetching changes for range b1..b4 - // we do not know changes trie roots before b3 (i.e. we only know b3+b4) - // but we have changes trie CHT root for b1...b4 - let b1 = remote_client.block_hash_from_id(&BlockId::Number(1)).unwrap().unwrap(); - let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap(); - let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap(); - let remote_proof = remote_client.key_changes_proof_with_cht_size( - b1, b4, b3, b4, None, &dave, 4 - ).unwrap(); - - // fails when changes trie CHT is missing from the local db - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - ); - assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, - remote_proof.roots_proof.clone()).is_err()); - - // fails when proof is broken - let mut local_storage = DummyStorage::new(); - local_storage.changes_tries_cht_roots.insert(0, local_cht_root); - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(local_storage)), - local_executor(), - ); - assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, vec![]).is_err()); - } - - #[test] - fn check_body_proof_faulty() { - let header = header_with_computed_extrinsics_root( - vec![Extrinsic::IncludeData(vec![1, 2, 3, 4])] - ); - let block = Block::new(header.clone(), Vec::new()); - - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - ); - - let body_request = RemoteBodyRequest { - header: header.clone(), - retry_count: None, - }; - - assert!( - local_checker.check_body_proof(&body_request, block.extrinsics).is_err(), - "vec![1, 2, 3, 4] != vec![]" - ); - } - - #[test] - fn check_body_proof_of_same_data_should_succeed() { - let extrinsics = vec![Extrinsic::IncludeData(vec![1, 2, 3, 4, 5, 6, 7, 8, 255])]; - - let header = header_with_computed_extrinsics_root(extrinsics.clone()); - let block = Block::new(header.clone(), extrinsics); - - let local_checker = TestChecker::new( - Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor(), - ); - - let body_request = RemoteBodyRequest { - header: header.clone(), - retry_count: None, - }; - - assert!(local_checker.check_body_proof(&body_request, block.extrinsics).is_ok()); - } -} diff --git a/core/client/src/light/mod.rs b/core/client/src/light/mod.rs deleted file mode 100644 index d06a9ae9dd93c..0000000000000 --- a/core/client/src/light/mod.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Light client components. - -pub mod backend; -pub mod blockchain; -pub mod call_executor; -pub mod fetcher; - -use std::sync::Arc; - -use executor::RuntimeInfo; -use primitives::{H256, Blake2Hasher, traits::CodeExecutor}; -use sr_primitives::BuildStorage; -use sr_primitives::traits::Block as BlockT; - -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::GenesisCallExecutor; -use crate::light::fetcher::LightDataChecker; - -/// Create an instance of light client blockchain backend. -pub fn new_light_blockchain>(storage: S) -> Arc> { - Arc::new(Blockchain::new(storage)) -} - -/// Create an instance of light client backend. -pub fn new_light_backend(blockchain: Arc>) -> Arc> - where - B: BlockT, - S: BlockchainStorage, -{ - Arc::new(Backend::new(blockchain)) -} - -/// Create an instance of light client. -pub fn new_light( - backend: Arc>, - genesis_storage: GS, - code_executor: E, -) -> ClientResult, GenesisCallExecutor< - Backend, - LocalCallExecutor, E> ->, B, RA>> - where - B: BlockT, - S: BlockchainStorage + 'static, - GS: BuildStorage, - E: CodeExecutor + RuntimeInfo, -{ - let local_executor = LocalCallExecutor::new(backend.clone(), code_executor, None); - let executor = GenesisCallExecutor::new(backend.clone(), local_executor); - Client::new(backend, executor, genesis_storage, Default::default(), Default::default()) -} - -/// Create an instance of fetch data checker. -pub fn new_fetch_checker>( - blockchain: Arc>, - executor: E, -) -> LightDataChecker - where - E: CodeExecutor, -{ - LightDataChecker::new(blockchain, executor) -} diff --git a/core/client/src/runtime_api.rs b/core/client/src/runtime_api.rs deleted file mode 100644 index 68b49e5910b45..0000000000000 --- a/core/client/src/runtime_api.rs +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! All the functionality required for declaring and implementing runtime apis. - -#[doc(hidden)] -#[cfg(feature = "std")] -pub use state_machine::OverlayedChanges; -#[doc(hidden)] -#[cfg(feature = "std")] -pub use primitives::NativeOrEncoded; -#[doc(hidden)] -#[cfg(not(feature = "std"))] -pub use primitives::to_substrate_wasm_fn_return_value; -#[doc(hidden)] -pub use sr_primitives::{ - traits::{ - Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, - Header as HeaderT, ApiRef, RuntimeApiInfo, Hash as HashT, - }, - generic::BlockId, transaction_validity::TransactionValidity, -}; -#[doc(hidden)] -pub use primitives::{offchain, ExecutionContext}; -#[doc(hidden)] -pub use runtime_version::{ApiId, RuntimeVersion, ApisVec, create_apis_vec}; -#[doc(hidden)] -pub use rstd::{slice, mem}; -#[cfg(feature = "std")] -use rstd::result; -#[doc(hidden)] -pub use codec::{Encode, Decode}; -#[cfg(feature = "std")] -use crate::error; -use sr_api_macros::decl_runtime_apis; -use primitives::OpaqueMetadata; -#[cfg(feature = "std")] -use std::{panic::UnwindSafe, cell::RefCell, rc::Rc}; -#[cfg(feature = "std")] -use primitives::Hasher as HasherT; - -#[cfg(feature = "std")] -/// A type that records all accessed trie nodes and generates a proof out of it. -pub type ProofRecorder = state_machine::ProofRecorder< - <<<::Header as HeaderT>::Hashing as HashT>::Hasher as HasherT>::Out ->; - -/// Something that can be constructed to a runtime api. -#[cfg(feature = "std")] -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>(call: &'a C) -> ApiRef<'a, Self::RuntimeApi>; -} - -/// An extension for the `RuntimeApi`. -#[cfg(feature = "std")] -pub trait ApiExt { - /// The given closure will be called with api instance. Inside the closure any api call is - /// allowed. After doing the api call, the closure is allowed to map the `Result` to a - /// different `Result` type. This can be important, as the internal data structure that keeps - /// track of modifications to the storage, discards changes when the `Result` is an `Err`. - /// On `Ok`, the structure commits the changes to an internal buffer. - fn map_api_result result::Result, R, E>( - &self, - map_call: F - ) -> result::Result where Self: Sized; - - /// Checks if the given api is implemented and versions match. - fn has_api( - &self, - at: &BlockId - ) -> 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; - - /// Start recording all accessed trie nodes for generating proofs. - fn record_proof(&mut self); - - /// Extract the recorded proof. - /// This stops the proof recording. - fn extract_proof(&mut self) -> Option>>; -} - -/// Before calling any runtime api function, the runtime need to be initialized -/// at the requested block. However, some functions like `execute_block` or -/// `initialize_block` itself don't require to have the runtime initialized -/// at the requested block. -/// -/// `call_api_at` is instructed by this enum to do the initialization or to skip -/// it. -#[cfg(feature = "std")] -#[derive(Clone, Copy)] -pub enum InitializeBlock<'a, Block: BlockT> { - /// Skip initializing the runtime for a given block. - /// - /// This is used by functions who do the initialization by themself or don't - /// require it. - Skip, - /// Initialize the runtime for a given block. - /// - /// If the stored `BlockId` is `Some(_)`, the runtime is currently initialized - /// at this block. - Do(&'a RefCell>>), -} - -/// Something that can call into the runtime at a given block. -#[cfg(feature = "std")] -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< - 'a, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - C: Core, - >( - &self, - core_api: &C, - at: &BlockId, - function: &'static str, - args: Vec, - changes: &RefCell, - initialize_block: InitializeBlock<'a, Block>, - native_call: Option, - context: ExecutionContext, - recorder: &Option>>>, - ) -> error::Result>; - - /// Returns the runtime version at the given block. - fn runtime_version_at(&self, at: &BlockId) -> error::Result; -} - -decl_runtime_apis! { - /// The `Core` api trait that is mandatory for each runtime. - #[core_trait] - #[api_version(2)] - pub trait Core { - /// Returns the version of the runtime. - fn version() -> RuntimeVersion; - /// Execute the given block. - #[skip_initialize_block] - fn execute_block(block: Block); - /// Initialize a block with the given header. - #[renamed("initialise_block", 2)] - #[skip_initialize_block] - #[initialize_block] - fn initialize_block(header: &::Header); - } - - /// The `Metadata` api trait that returns metadata for the runtime. - pub trait Metadata { - /// Returns the metadata of a runtime. - fn metadata() -> OpaqueMetadata; - } - - /// The `TaggedTransactionQueue` api trait for interfering with the new transaction queue. - pub trait TaggedTransactionQueue { - /// Validate the given transaction. - fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity; - } -} - diff --git a/core/consensus/aura/Cargo.toml b/core/consensus/aura/Cargo.toml deleted file mode 100644 index a09d51095018e..0000000000000 --- a/core/consensus/aura/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "substrate-consensus-aura" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Aura consensus algorithm for substrate" -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0" } -primitives = { package = "substrate-primitives", path = "../../primitives" } -app-crypto = { package = "substrate-application-crypto", path = "../../application-crypto" } -runtime_support = { package = "srml-support", path = "../../../srml/support" } -runtime_version = { package = "sr-version", path = "../../sr-version" } -runtime_io = { package = "sr-io", path = "../../sr-io" } -slots = { package = "substrate-consensus-slots", path = "../slots" } -aura_primitives = { package = "substrate-consensus-aura-primitives", path = "primitives" } -inherents = { package = "substrate-inherents", path = "../../inherents" } -srml-aura = { path = "../../../srml/aura" } -client = { package = "substrate-client", path = "../../client" } -substrate-telemetry = { path = "../../telemetry" } -keystore = { package = "substrate-keystore", path = "../../keystore" } -consensus_common = { package = "substrate-consensus-common", path = "../common" } -sr-primitives = { path = "../../sr-primitives" } -futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } -futures01 = { package = "futures", version = "0.1" } -futures-timer = "0.4.0" -parking_lot = "0.9.0" -log = "0.4.8" -derive_more = "0.15.0" - -[dev-dependencies] -keyring = { package = "substrate-keyring", path = "../../keyring" } -substrate-executor = { path = "../../executor" } -network = { package = "substrate-network", path = "../../network", features = ["test-helpers"]} -service = { package = "substrate-service", path = "../../service" } -test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } -tokio = "0.1.22" -env_logger = "0.7.0" -tempfile = "3.1.0" diff --git a/core/consensus/aura/primitives/Cargo.toml b/core/consensus/aura/primitives/Cargo.toml deleted file mode 100644 index 7fd3f3d05d9bf..0000000000000 --- a/core/consensus/aura/primitives/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "substrate-consensus-aura-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Primitives for Aura consensus" -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -substrate-client = { path = "../../../client", default-features = false } -app-crypto = { package = "substrate-application-crypto", path = "../../../application-crypto", default-features = false } -rstd = { package = "sr-std", path = "../../../sr-std", default-features = false } -sr-primitives = { path = "../../../sr-primitives", default-features = false } - -[features] -default = ["std"] -std = [ - "rstd/std", - "codec/std", - "sr-primitives/std", - "substrate-client/std", - "app-crypto/std", -] diff --git a/core/consensus/aura/primitives/src/lib.rs b/core/consensus/aura/primitives/src/lib.rs deleted file mode 100644 index e4620fcdbfdd4..0000000000000 --- a/core/consensus/aura/primitives/src/lib.rs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Primitives for Aura. - -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::{Encode, Decode, Codec}; -use substrate_client::decl_runtime_apis; -use rstd::vec::Vec; -use sr_primitives::ConsensusEngineId; - -pub mod sr25519 { - mod app_sr25519 { - use app_crypto::{app_crypto, key_types::AURA, sr25519}; - app_crypto!(sr25519, AURA); - } - - /// An Aura authority keypair using S/R 25519 as its crypto. - #[cfg(feature = "std")] - pub type AuthorityPair = app_sr25519::Pair; - - /// An Aura authority signature using S/R 25519 as its crypto. - pub type AuthoritySignature = app_sr25519::Signature; - - /// An Aura authority identifier using S/R 25519 as its crypto. - pub type AuthorityId = app_sr25519::Public; -} - -pub mod ed25519 { - mod app_ed25519 { - use app_crypto::{app_crypto, key_types::AURA, ed25519}; - app_crypto!(ed25519, AURA); - } - - /// An Aura authority keypair using Ed25519 as its crypto. - #[cfg(feature = "std")] - pub type AuthorityPair = app_ed25519::Pair; - - /// An Aura authority signature using Ed25519 as its crypto. - pub type AuthoritySignature = app_ed25519::Signature; - - /// An Aura authority identifier using Ed25519 as its crypto. - pub type AuthorityId = app_ed25519::Public; -} - -/// The `ConsensusEngineId` of AuRa. -pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a']; - -/// The index of an authority. -pub type AuthorityIndex = u32; - -/// An consensus log item for Aura. -#[derive(Decode, Encode)] -pub enum ConsensusLog { - /// The authorities have changed. - #[codec(index = "1")] - AuthoritiesChange(Vec), - /// Disable the authority with given index. - #[codec(index = "2")] - OnDisabled(AuthorityIndex), -} - -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; - - // Return the current set of authorities. - fn authorities() -> Vec; - } -} diff --git a/core/consensus/aura/src/digest.rs b/core/consensus/aura/src/digest.rs deleted file mode 100644 index 3baa18587bc7c..0000000000000 --- a/core/consensus/aura/src/digest.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Aura (Authority-Round) digests -//! -//! This implements the digests for AuRa, to allow the private -//! `CompatibleDigestItem` trait to appear in public interfaces. - -use primitives::Pair; -use aura_primitives::AURA_ENGINE_ID; -use sr_primitives::generic::{DigestItem, OpaqueDigestItemId}; -use codec::{Encode, Codec}; -use std::fmt::Debug; - -type Signature

=

::Signature; - -/// A digest item which is usable with aura consensus. -pub trait CompatibleDigestItem: Sized { - /// Construct a digest item which contains a signature on the hash. - fn aura_seal(signature: Signature

) -> Self; - - /// If this item is an Aura seal, return the signature. - fn as_aura_seal(&self) -> Option>; - - /// Construct a digest item which contains the slot number - fn aura_pre_digest(slot_num: u64) -> Self; - - /// If this item is an AuRa pre-digest, return the slot number - fn as_aura_pre_digest(&self) -> Option; -} - -impl CompatibleDigestItem

for DigestItem where - P: Pair, - Signature

: Codec, - Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static -{ - fn aura_seal(signature: Signature

) -> Self { - DigestItem::Seal(AURA_ENGINE_ID, signature.encode()) - } - - fn as_aura_seal(&self) -> Option> { - self.try_to(OpaqueDigestItemId::Seal(&AURA_ENGINE_ID)) - } - - fn aura_pre_digest(slot_num: u64) -> Self { - DigestItem::PreRuntime(AURA_ENGINE_ID, slot_num.encode()) - } - - fn as_aura_pre_digest(&self) -> Option { - self.try_to(OpaqueDigestItemId::PreRuntime(&AURA_ENGINE_ID)) - } -} diff --git a/core/consensus/aura/src/lib.rs b/core/consensus/aura/src/lib.rs deleted file mode 100644 index eb2d1dba20f1b..0000000000000 --- a/core/consensus/aura/src/lib.rs +++ /dev/null @@ -1,880 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Aura (Authority-round) consensus in substrate. -//! -//! Aura works by having a list of authorities A who are expected to roughly -//! agree on the current time. Time is divided up into discrete slots of t -//! seconds each. For each slot s, the author of that slot is A[s % |A|]. -//! -//! The author is allowed to issue one block but not more during that slot, -//! and it will be built upon the longest valid chain that has been seen. -//! -//! Blocks from future steps will be either deferred or rejected depending on how -//! far in the future they are. -//! -//! NOTE: Aura itself is designed to be generic over the crypto used. -#![forbid(missing_docs, unsafe_code)] -use std::{sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug, pin::Pin}; - -use codec::{Encode, Decode, Codec}; -use consensus_common::{self, BlockImport, Environment, Proposer, - ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError, - SelectChain, -}; -use consensus_common::import_queue::{ - Verifier, BasicQueue, BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport, -}; -use client::{ - block_builder::api::BlockBuilder as BlockBuilderApi, blockchain::ProvideCache, - runtime_api::ApiExt, error::Result as CResult, backend::AuxStore, BlockOf, - well_known_cache_keys::{self, Id as CacheKeyId}, -}; - -use sr_primitives::{generic::{BlockId, OpaqueDigestItemId}, Justification}; -use sr_primitives::traits::{Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, Zero, Member}; - -use primitives::crypto::Pair; -use inherents::{InherentDataProviders, InherentData, RuntimeString}; - -use futures::prelude::*; -use parking_lot::Mutex; -use log::{debug, info, trace}; - -use srml_aura::{ - InherentType as AuraInherent, AuraInherentData, - timestamp::{TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError} -}; -use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO}; - -use slots::{CheckedHeader, SlotData, SlotWorker, SlotInfo, SlotCompatible}; -use slots::check_equivocation; - -use keystore::KeyStorePtr; - -pub use aura_primitives::*; -pub use consensus_common::SyncOracle; -pub use digest::CompatibleDigestItem; - -mod digest; - -type AuthorityId

=

::Public; - -/// A slot duration. Create with `get_or_compute`. -#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct SlotDuration(slots::SlotDuration); - -impl SlotDuration { - /// Either fetch the slot duration from disk or compute it from the genesis - /// state. - pub fn get_or_compute(client: &C) -> CResult - where - A: Codec, - B: BlockT, - C: AuxStore + ProvideRuntimeApi, - C::Api: AuraApi, - { - slots::SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)).map(Self) - } - - /// Get the slot duration in milliseconds. - pub fn get(&self) -> u64 { - self.0.get() - } -} - -/// Get slot author for given block along with authorities. -fn slot_author(slot_num: u64, authorities: &[AuthorityId

]) -> Option<&AuthorityId

> { - if authorities.is_empty() { return None } - - let idx = slot_num % (authorities.len() as u64); - assert!( - idx <= usize::max_value() as u64, - "It is impossible to have a vector with length beyond the address space; qed", - ); - - let current_author = authorities.get(idx as usize) - .expect("authorities not empty; index constrained to list length;\ - this is a valid index; qed"); - - Some(current_author) -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -struct AuraSlotCompatible; - -impl SlotCompatible for AuraSlotCompatible { - fn extract_timestamp_and_slot( - &self, - data: &InherentData - ) -> Result<(TimestampInherent, AuraInherent, std::time::Duration), consensus_common::Error> { - data.timestamp_inherent_data() - .and_then(|t| data.aura_inherent_data().map(|a| (t, a))) - .map_err(Into::into) - .map_err(consensus_common::Error::InherentData) - .map(|(x, y)| (x, y, Default::default())) - } -} - -/// Start the aura worker. The returned future should be run in a futures executor. -pub fn start_aura( - slot_duration: SlotDuration, - client: Arc, - select_chain: SC, - block_import: I, - env: E, - sync_oracle: SO, - inherent_data_providers: InherentDataProviders, - force_authoring: bool, - keystore: KeyStorePtr, -) -> Result, consensus_common::Error> where - B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache + AuxStore + Send + Sync, - C::Api: AuraApi>, - SC: SelectChain, - E: Environment + Send + Sync + 'static, - E::Proposer: Proposer, - >::Create: Unpin + Send, - P: Pair + Send + Sync, - P::Public: Hash + Member + Encode + Decode, - P::Signature: Hash + Member + Encode + Decode, - H: Header, - I: BlockImport + Send + Sync + 'static, - Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, - SO: SyncOracle + Send + Sync + Clone, -{ - let worker = AuraWorker { - client: client.clone(), - block_import: Arc::new(Mutex::new(block_import)), - env, - keystore, - sync_oracle: sync_oracle.clone(), - force_authoring, - _key_type: PhantomData::

, - }; - register_aura_inherent_data_provider( - &inherent_data_providers, - slot_duration.0.slot_duration() - )?; - Ok(slots::start_slot_worker::<_, _, _, _, _, AuraSlotCompatible>( - slot_duration.0, - select_chain, - worker, - sync_oracle, - inherent_data_providers, - AuraSlotCompatible, - ).map(|()| Ok::<(), ()>(())).compat()) -} - -struct AuraWorker { - client: Arc, - block_import: Arc>, - env: E, - keystore: KeyStorePtr, - sync_oracle: SO, - force_authoring: bool, - _key_type: PhantomData

, -} - -impl slots::SimpleSlotWorker for AuraWorker where - B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache + Sync, - C::Api: AuraApi>, - E: Environment, - E::Proposer: Proposer, - >::Create: Unpin + Send, - H: Header, - I: BlockImport + Send + Sync + 'static, - P: Pair + Send + Sync, - P::Public: Member + Encode + Decode + Hash, - P::Signature: Member + Encode + Decode + Hash + Debug, - SO: SyncOracle + Send + Clone, - Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, -{ - type EpochData = Vec>; - type Claim = P; - type SyncOracle = SO; - type Proposer = E::Proposer; - type BlockImport = I; - - fn logging_target(&self) -> &'static str { - "aura" - } - - fn block_import(&self) -> Arc> { - self.block_import.clone() - } - - fn epoch_data(&self, header: &B::Header, _slot_number: u64) -> Result { - authorities(self.client.as_ref(), &BlockId::Hash(header.hash())) - } - - fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize { - epoch_data.len() - } - - fn claim_slot( - &self, - _header: &B::Header, - slot_number: u64, - epoch_data: &Self::EpochData, - ) -> Option { - let expected_author = slot_author::

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

(&p, app_crypto::key_types::AURA).ok() - }) - } - - fn pre_digest_data(&self, slot_number: u64, _claim: &Self::Claim) -> Vec> { - vec![ - as CompatibleDigestItem

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

>::aura_seal(signature); - - BlockImportParams { - origin: BlockOrigin::Own, - header, - justification: None, - post_digests: vec![signature_digest_item], - body: Some(body), - finalized: false, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - } - }) - } - - fn force_authoring(&self) -> bool { - self.force_authoring - } - - fn sync_oracle(&mut self) -> &mut Self::SyncOracle { - &mut self.sync_oracle - } - - fn proposer(&mut self, block: &B::Header) -> Result { - self.env.init(block).map_err(|e| { - consensus_common::Error::ClientImport(format!("{:?}", e)).into() - }) - } -} - -impl SlotWorker for AuraWorker where - B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache + Sync + Send, - C::Api: AuraApi>, - E: Environment + Send + Sync, - E::Proposer: Proposer, - >::Create: Unpin + Send + 'static, - H: Header, - I: BlockImport + Send + Sync + 'static, - P: Pair + Send + Sync, - P::Public: Member + Encode + Decode + Hash, - P::Signature: Member + Encode + Decode + Hash + Debug, - SO: SyncOracle + Send + Sync + Clone, - Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, -{ - type OnSlot = Pin> + Send>>; - - fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot { - >::on_slot(self, chain_head, slot_info) - } -} - -fn aura_err(error: Error) -> Error { - debug!(target: "aura", "{}", error); - error -} - -#[derive(derive_more::Display)] -enum Error { - #[display(fmt = "Multiple Aura pre-runtime headers")] - MultipleHeaders, - #[display(fmt = "No Aura pre-runtime digest found")] - NoDigestFound, - #[display(fmt = "Header {:?} is unsealed", _0)] - HeaderUnsealed(B::Hash), - #[display(fmt = "Header {:?} has a bad seal", _0)] - HeaderBadSeal(B::Hash), - #[display(fmt = "Slot Author not found")] - SlotAuthorNotFound, - #[display(fmt = "Bad signature on {:?}", _0)] - BadSignature(B::Hash), - #[display(fmt = "Rejecting block too far in future")] - TooFarInFuture, - Client(client::error::Error), - DataProvider(String), - Runtime(RuntimeString) -} - -fn find_pre_digest(header: &B::Header) -> Result> - where DigestItemFor: CompatibleDigestItem

, - P::Signature: Decode, - P::Public: Encode + Decode + PartialEq + Clone, -{ - let mut pre_digest: Option = None; - for log in header.digest().logs() { - trace!(target: "aura", "Checking log {:?}", log); - match (log.as_aura_pre_digest(), pre_digest.is_some()) { - (Some(_), true) => Err(aura_err(Error::MultipleHeaders))?, - (None, _) => trace!(target: "aura", "Ignoring digest not meant for us"), - (s, false) => pre_digest = s, - } - } - pre_digest.ok_or_else(|| aura_err(Error::NoDigestFound)) -} - -/// check a header has been signed by the right key. If the slot is too far in the future, an error will be returned. -/// if it's successful, returns the pre-header and the digest item containing the seal. -/// -/// This digest item will always return `Some` when used with `as_aura_seal`. -// -// FIXME #1018 needs misbehavior types. The `transaction_pool` parameter will be -// used to submit such misbehavior reports. -fn check_header( - client: &C, - slot_now: u64, - mut header: B::Header, - hash: B::Hash, - authorities: &[AuthorityId

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

, - P::Signature: Decode, - C: client::backend::AuxStore, - P::Public: Encode + Decode + PartialEq + Clone, - T: Send + Sync + 'static, -{ - let seal = match header.digest_mut().pop() { - Some(x) => x, - None => return Err(Error::HeaderUnsealed(hash)), - }; - - let sig = seal.as_aura_seal().ok_or_else(|| { - aura_err(Error::HeaderBadSeal(hash)) - })?; - - let slot_num = find_pre_digest::(&header)?; - - if slot_num > slot_now { - header.digest_mut().push(seal); - Ok(CheckedHeader::Deferred(header, slot_num)) - } else { - // check the signature is valid under the expected authority and - // chain state. - let expected_author = match slot_author::

(slot_num, &authorities) { - None => return Err(Error::SlotAuthorNotFound), - Some(author) => author, - }; - - let pre_hash = header.hash(); - - if P::verify(&sig, pre_hash.as_ref(), expected_author) { - if let Some(equivocation_proof) = check_equivocation( - client, - slot_now, - slot_num, - &header, - expected_author, - ).map_err(Error::Client)? { - info!( - "Slot author is equivocating at slot {} with headers {:?} and {:?}", - slot_num, - equivocation_proof.fst_header().hash(), - equivocation_proof.snd_header().hash(), - ); - } - - Ok(CheckedHeader::Checked(header, (slot_num, seal))) - } else { - Err(Error::BadSignature(hash)) - } - } -} - -/// A verifier for Aura blocks. -pub struct AuraVerifier { - client: Arc, - phantom: PhantomData

, - inherent_data_providers: inherents::InherentDataProviders, - transaction_pool: Option>, -} - -impl AuraVerifier - where P: Send + Sync + 'static -{ - fn check_inherents( - &self, - block: B, - block_id: BlockId, - inherent_data: InherentData, - timestamp_now: u64, - ) -> Result<(), Error> - where C: ProvideRuntimeApi, C::Api: BlockBuilderApi - { - const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; - - let inherent_res = self.client.runtime_api().check_inherents( - &block_id, - block, - inherent_data, - ).map_err(Error::Client)?; - - if !inherent_res.ok() { - inherent_res - .into_errors() - .try_for_each(|(i, e)| match TIError::try_from(&i, &e) { - Some(TIError::ValidAtTimestamp(timestamp)) => { - // halt import until timestamp is valid. - // reject when too far ahead. - if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { - return Err(Error::TooFarInFuture); - } - - 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(Error::Runtime(e)), - None => Err(Error::DataProvider( - self.inherent_data_providers.error_to_string(&i, &e) - )), - }) - } else { - Ok(()) - } - } -} - -#[forbid(deprecated)] -impl Verifier for AuraVerifier where - C: ProvideRuntimeApi + Send + Sync + client::backend::AuxStore + ProvideCache + BlockOf, - C::Api: BlockBuilderApi + AuraApi>, - DigestItemFor: CompatibleDigestItem

, - P: Pair + Send + Sync + 'static, - P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + 'static, - P::Signature: Encode + Decode, - T: Send + Sync + 'static, -{ - fn verify( - &mut self, - origin: BlockOrigin, - header: B::Header, - justification: Option, - mut body: Option>, - ) -> Result<(BlockImportParams, Option)>>), String> { - 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 = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash)) - .map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?; - - // we add one to allow for some small drift. - // FIXME #1019 in the future, alter this queue to allow deferring of - // headers - let checked_header = check_header::( - &self.client, - slot_now + 1, - header, - hash, - &authorities[..], - self.transaction_pool.as_ref().map(|x| &**x), - ).map_err(|e| e.to_string())?; - match checked_header { - CheckedHeader::Checked(pre_header, (slot_num, seal)) => { - // if the body is passed through, we need to use the runtime - // to check that the internally-set timestamp in the inherents - // actually matches the slot set in the seal. - if let Some(inner_body) = body.take() { - inherent_data.aura_replace_inherent_data(slot_num); - let block = B::new(pre_header.clone(), inner_body); - - // skip the inherents verification if the runtime API is old. - if self.client - .runtime_api() - .has_api_with::, _>(&BlockId::Hash(parent_hash), |v| v >= 2) - .map_err(|e| format!("{:?}", e))? - { - self.check_inherents( - block.clone(), - BlockId::Hash(parent_hash), - inherent_data, - timestamp_now, - ).map_err(|e| e.to_string())?; - } - - let (_, inner_body) = block.deconstruct(); - body = Some(inner_body); - } - - trace!(target: "aura", "Checked {:?}; importing.", pre_header); - telemetry!(CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header); - - // Look for an authorities-change log. - let maybe_keys = pre_header.digest() - .logs() - .iter() - .filter_map(|l| l.try_to::>>( - OpaqueDigestItemId::Consensus(&AURA_ENGINE_ID) - )) - .find_map(|l| match l { - ConsensusLog::AuthoritiesChange(a) => Some( - vec![(well_known_cache_keys::AUTHORITIES, a.encode())] - ), - _ => None, - }); - - let block_import_params = BlockImportParams { - origin, - header: pre_header, - post_digests: vec![seal], - body, - finalized: false, - justification, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; - - Ok((block_import_params, maybe_keys)) - } - CheckedHeader::Deferred(a, b) => { - 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)) - } - } - } -} - -fn initialize_authorities_cache(client: &C) -> Result<(), ConsensusError> where - A: Codec, - B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache, - C::Api: AuraApi, -{ - // no cache => no initialization - let cache = match client.cache() { - Some(cache) => cache, - None => return Ok(()), - }; - - // check if we already have initialized the cache - let genesis_id = BlockId::Number(Zero::zero()); - let genesis_authorities: Option> = cache - .get_at(&well_known_cache_keys::AUTHORITIES, &genesis_id) - .and_then(|(_, _, v)| Decode::decode(&mut &v[..]).ok()); - if genesis_authorities.is_some() { - return Ok(()); - } - - let map_err = |error| consensus_common::Error::from(consensus_common::Error::ClientImport( - format!( - "Error initializing authorities cache: {}", - error, - ))); - let genesis_authorities = authorities(client, &genesis_id)?; - cache.initialize(&well_known_cache_keys::AUTHORITIES, genesis_authorities.encode()) - .map_err(map_err)?; - - Ok(()) -} - -#[allow(deprecated)] -fn authorities(client: &C, at: &BlockId) -> Result, ConsensusError> where - A: Codec, - B: BlockT, - C: ProvideRuntimeApi + BlockOf + ProvideCache, - C::Api: AuraApi, -{ - client - .cache() - .and_then(|cache| cache - .get_at(&well_known_cache_keys::AUTHORITIES, at) - .and_then(|(_, _, v)| Decode::decode(&mut &v[..]).ok()) - ) - .or_else(|| AuraApi::authorities(&*client.runtime_api(), at).ok()) - .ok_or_else(|| consensus_common::Error::InvalidAuthoritiesSet.into()) -} - -/// The Aura import queue type. -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(Into::into) - .map_err(consensus_common::Error::InherentData) - } else { - Ok(()) - } -} - -/// Start an import queue for the Aura consensus algorithm. -pub fn import_queue( - slot_duration: SlotDuration, - block_import: BoxBlockImport, - justification_import: Option>, - finality_proof_import: Option>, - client: Arc, - inherent_data_providers: InherentDataProviders, - transaction_pool: Option>, -) -> Result, consensus_common::Error> where - B: BlockT, - C: 'static + ProvideRuntimeApi + BlockOf + ProvideCache + Send + Sync + AuxStore, - C::Api: BlockBuilderApi + AuraApi>, - DigestItemFor: CompatibleDigestItem

, - P: Pair + Send + Sync + 'static, - P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode, - P::Signature: Encode + Decode, - T: Send + Sync + 'static, -{ - register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?; - initialize_authorities_cache(&*client)?; - - let verifier = AuraVerifier { - client: client.clone(), - inherent_data_providers, - phantom: PhantomData, - transaction_pool, - }; - Ok(BasicQueue::new( - verifier, - block_import, - justification_import, - finality_proof_import, - )) -} - -#[cfg(test)] -mod tests { - use super::*; - use consensus_common::NoNetwork as DummyOracle; - use network::test::*; - use network::test::{Block as TestBlock, PeersClient, PeersFullClient}; - use sr_primitives::traits::{Block as BlockT, DigestFor}; - use network::config::ProtocolConfig; - use parking_lot::Mutex; - use tokio::runtime::current_thread; - use keyring::sr25519::Keyring; - use client::BlockchainEvents; - use test_client; - use aura_primitives::sr25519::AuthorityPair; - - type Error = client::error::Error; - - type TestClient = client::Client< - test_client::Backend, - test_client::Executor, - TestBlock, - test_client::runtime::RuntimeApi - >; - - struct DummyFactory(Arc); - struct DummyProposer(u64, Arc); - - impl Environment for DummyFactory { - type Proposer = DummyProposer; - type Error = Error; - - fn init(&mut self, parent_header: &::Header) - -> Result - { - Ok(DummyProposer(parent_header.number + 1, self.0.clone())) - } - } - - impl Proposer for DummyProposer { - type Error = Error; - type Create = future::Ready>; - - fn propose( - &mut self, - _: InherentData, - digests: DigestFor, - _: Duration, - ) -> Self::Create { - let r = self.1.new_block(digests).unwrap().bake().map_err(|e| e.into()); - future::ready(r) - } - } - - const SLOT_DURATION: u64 = 1000; - - pub struct AuraTestNet { - peers: Vec>, - } - - impl TestNetFactory for AuraTestNet { - 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(), - } - } - - fn make_verifier(&self, client: PeersClient, _cfg: &ProtocolConfig, _peer_data: &()) - -> Self::Verifier - { - match client { - PeersClient::Full(client, _) => { - 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.get(), SLOT_DURATION); - AuraVerifier { - client, - inherent_data_providers, - transaction_pool: Default::default(), - phantom: Default::default(), - } - }, - PeersClient::Light(_, _) => unreachable!("No (yet) tests for light client + Aura"), - } - } - - fn peer(&mut self, i: usize) -> &mut Peer { - &mut self.peers[i] - } - - fn peers(&self) -> &Vec> { - &self.peers - } - - fn mut_peers>)>(&mut self, closure: F) { - closure(&mut self.peers); - } - } - - #[test] - #[allow(deprecated)] - fn authoring_blocks() { - let _ = env_logger::try_init(); - let net = AuraTestNet::new(3); - - let peers = &[ - (0, Keyring::Alice), - (1, Keyring::Bob), - (2, Keyring::Charlie), - ]; - - let net = Arc::new(Mutex::new(net)); - let mut import_notifications = Vec::new(); - - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut keystore_paths = Vec::new(); - for (peer_id, key) in peers { - let mut net = net.lock(); - let peer = net.peer(*peer_id); - let client = peer.client().as_full().expect("full clients are created").clone(); - let select_chain = peer.select_chain().expect("full client has a select chain"); - let keystore_path = tempfile::tempdir().expect("Creates keystore path"); - let keystore = keystore::Store::open(keystore_path.path(), None).expect("Creates keystore."); - - keystore.write().insert_ephemeral_from_seed::(&key.to_seed()) - .expect("Creates authority key"); - keystore_paths.push(keystore_path); - - let environ = DummyFactory(client.clone()); - import_notifications.push( - client.import_notification_stream() - .take_while(|n| future::ready(!(n.origin != BlockOrigin::Own && n.header.number() < &5))) - .for_each(move |_| future::ready(())) - ); - - 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::<_, _, _, _, _, AuthorityPair, _, _, _>( - slot_duration, - client.clone(), - select_chain, - client, - environ, - DummyOracle, - inherent_data_providers, - false, - keystore, - ).expect("Starts aura"); - - runtime.spawn(aura); - } - - runtime.spawn(futures01::future::poll_fn(move || { - net.lock().poll(); - Ok::<_, ()>(futures01::Async::NotReady::<()>) - })); - - runtime.block_on(future::join_all(import_notifications) - .map(|_| Ok::<(), ()>(())).compat()).unwrap(); - } - - #[test] - fn authorities_call_works() { - let client = test_client::new(); - - assert_eq!(client.info().chain.best_number, 0); - assert_eq!(authorities(&client, &BlockId::Number(0)).unwrap(), vec![ - Keyring::Alice.public().into(), - Keyring::Bob.public().into(), - Keyring::Charlie.public().into() - ]); - } -} diff --git a/core/consensus/babe/Cargo.toml b/core/consensus/babe/Cargo.toml deleted file mode 100644 index 30b7c1f8d6b1c..0000000000000 --- a/core/consensus/babe/Cargo.toml +++ /dev/null @@ -1,52 +0,0 @@ -[package] -name = "substrate-consensus-babe" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "BABE consensus algorithm for substrate" -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } -babe_primitives = { package = "substrate-consensus-babe-primitives", path = "primitives" } -primitives = { package = "substrate-primitives", path = "../../primitives" } -app-crypto = { package = "substrate-application-crypto", path = "../../application-crypto" } -num-bigint = "0.2.3" -num-rational = "0.2.2" -num-traits = "0.2.8" -runtime-support = { package = "srml-support", path = "../../../srml/support" } -runtime-version = { package = "sr-version", path = "../../sr-version" } -runtime-io = { package = "sr-io", path = "../../sr-io" } -inherents = { package = "substrate-inherents", path = "../../inherents" } -substrate-telemetry = { path = "../../telemetry" } -keystore = { package = "substrate-keystore", path = "../../keystore" } -srml-babe = { path = "../../../srml/babe" } -client = { package = "substrate-client", path = "../../client" } -header-metadata = { package = "substrate-header-metadata", path = "../../client/header-metadata" } -consensus-common = { package = "substrate-consensus-common", path = "../common" } -uncles = { package = "substrate-consensus-uncles", path = "../uncles" } -slots = { package = "substrate-consensus-slots", path = "../slots" } -sr-primitives = { path = "../../sr-primitives" } -fork-tree = { path = "../../utils/fork-tree" } -futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } -futures01 = { package = "futures", version = "0.1" } -futures-timer = "0.4.0" -parking_lot = "0.9.0" -log = "0.4.8" -schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated"] } -rand = "0.7.2" -merlin = "1.2.1" -pdqselect = "0.1.0" -derive_more = "0.15.0" - -[dev-dependencies] -keyring = { package = "substrate-keyring", path = "../../keyring" } -substrate-executor = { path = "../../executor" } -network = { package = "substrate-network", path = "../../network", features = ["test-helpers"]} -service = { package = "substrate-service", path = "../../service" } -test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } -tokio = "0.1.22" -env_logger = "0.7.0" -tempfile = "3.1.0" - -[features] -test-helpers = [] diff --git a/core/consensus/babe/primitives/Cargo.toml b/core/consensus/babe/primitives/Cargo.toml deleted file mode 100644 index 79e817d081028..0000000000000 --- a/core/consensus/babe/primitives/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "substrate-consensus-babe-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Primitives for BABE consensus" -edition = "2018" - -[dependencies] -substrate-client = { path = "../../../client", default-features = false } -rstd = { package = "sr-std", path = "../../../sr-std", default-features = false } -sr-primitives = { path = "../../../sr-primitives", default-features = false } -app-crypto = { package = "substrate-application-crypto", path = "../../../application-crypto", default-features = false } -slots = { package = "substrate-consensus-slots", path = "../../slots", optional = true } -schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated"], optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } - -[features] -default = ["std"] -std = [ - "rstd/std", - "sr-primitives/std", - "substrate-client/std", - "codec/std", - "schnorrkel", - "slots", - "app-crypto/std", -] diff --git a/core/consensus/babe/primitives/src/digest.rs b/core/consensus/babe/primitives/src/digest.rs deleted file mode 100644 index 95dd247810782..0000000000000 --- a/core/consensus/babe/primitives/src/digest.rs +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Private implementation details of BABE digests. - -#[cfg(feature = "std")] -use super::{BABE_ENGINE_ID, AuthoritySignature}; -#[cfg(not(feature = "std"))] -use super::{VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH}; -use super::{AuthorityId, AuthorityIndex, SlotNumber, BabeAuthorityWeight}; -#[cfg(feature = "std")] -use sr_primitives::{DigestItem, generic::OpaqueDigestItemId}; -#[cfg(feature = "std")] -use std::fmt::Debug; -use codec::{Decode, Encode}; -#[cfg(feature = "std")] -use codec::{Codec, Input, Error}; -#[cfg(feature = "std")] -use schnorrkel::{ - SignatureError, errors::MultiSignatureStage, - vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH} -}; -use rstd::vec::Vec; - - -/// A BABE pre-runtime digest. This contains all data required to validate a -/// block and for the BABE runtime module. Slots can be assigned to a primary -/// (VRF based) and to a secondary (slot number based). -#[cfg(feature = "std")] -#[derive(Clone, Debug)] -pub enum BabePreDigest { - /// A primary VRF-based slot assignment. - Primary { - /// VRF output - vrf_output: VRFOutput, - /// VRF proof - vrf_proof: VRFProof, - /// Authority index - authority_index: super::AuthorityIndex, - /// Slot number - slot_number: SlotNumber, - }, - /// A secondary deterministic slot assignment. - Secondary { - /// Authority index - authority_index: super::AuthorityIndex, - /// Slot number - slot_number: SlotNumber, - }, -} - -#[cfg(feature = "std")] -impl BabePreDigest { - /// Returns the slot number of the pre digest. - pub fn authority_index(&self) -> AuthorityIndex { - match self { - BabePreDigest::Primary { authority_index, .. } => *authority_index, - BabePreDigest::Secondary { authority_index, .. } => *authority_index, - } - } - - /// Returns the slot number of the pre digest. - pub fn slot_number(&self) -> SlotNumber { - match self { - BabePreDigest::Primary { slot_number, .. } => *slot_number, - BabePreDigest::Secondary { slot_number, .. } => *slot_number, - } - } - - /// Returns the weight _added_ by this digest, not the cumulative weight - /// of the chain. - pub fn added_weight(&self) -> crate::BabeBlockWeight { - match self { - BabePreDigest::Primary { .. } => 1, - BabePreDigest::Secondary { .. } => 0, - } - } -} - -/// The prefix used by BABE for its VRF keys. -pub const BABE_VRF_PREFIX: &[u8] = b"substrate-babe-vrf"; - -/// A raw version of `BabePreDigest`, usable on `no_std`. -#[derive(Copy, Clone, Encode, Decode)] -pub enum RawBabePreDigest { - /// A primary VRF-based slot assignment. - #[codec(index = "1")] - Primary { - /// Authority index - authority_index: AuthorityIndex, - /// Slot number - slot_number: SlotNumber, - /// VRF output - vrf_output: [u8; VRF_OUTPUT_LENGTH], - /// VRF proof - vrf_proof: [u8; VRF_PROOF_LENGTH], - }, - /// A secondary deterministic slot assignment. - #[codec(index = "2")] - Secondary { - /// Authority index - /// - /// This is not strictly-speaking necessary, since the secondary slots - /// are assigned based on slot number and epoch randomness. But including - /// it makes things easier for higher-level users of the chain data to - /// be aware of the author of a secondary-slot block. - authority_index: AuthorityIndex, - /// Slot number - slot_number: SlotNumber, - }, -} - -impl RawBabePreDigest { - /// Returns the slot number of the pre digest. - pub fn slot_number(&self) -> SlotNumber { - match self { - RawBabePreDigest::Primary { slot_number, .. } => *slot_number, - RawBabePreDigest::Secondary { slot_number, .. } => *slot_number, - } - } -} - -#[cfg(feature = "std")] -impl Encode for BabePreDigest { - fn encode(&self) -> Vec { - let raw = match self { - BabePreDigest::Primary { - vrf_output, - vrf_proof, - authority_index, - slot_number, - } => { - RawBabePreDigest::Primary { - vrf_output: *vrf_output.as_bytes(), - vrf_proof: vrf_proof.to_bytes(), - authority_index: *authority_index, - slot_number: *slot_number, - } - }, - BabePreDigest::Secondary { - authority_index, - slot_number, - } => { - RawBabePreDigest::Secondary { - authority_index: *authority_index, - slot_number: *slot_number, - } - }, - }; - - codec::Encode::encode(&raw) - } -} - -#[cfg(feature = "std")] -impl codec::EncodeLike for BabePreDigest {} - -#[cfg(feature = "std")] -impl Decode for BabePreDigest { - fn decode(i: &mut R) -> Result { - let pre_digest = match Decode::decode(i)? { - RawBabePreDigest::Primary { vrf_output, vrf_proof, authority_index, slot_number } => { - // Verify (at compile time) that the sizes in babe_primitives are correct - let _: [u8; super::VRF_OUTPUT_LENGTH] = vrf_output; - let _: [u8; super::VRF_PROOF_LENGTH] = vrf_proof; - - BabePreDigest::Primary { - vrf_proof: VRFProof::from_bytes(&vrf_proof).map_err(convert_error)?, - vrf_output: VRFOutput::from_bytes(&vrf_output).map_err(convert_error)?, - authority_index, - slot_number, - } - }, - RawBabePreDigest::Secondary { authority_index, slot_number } => { - BabePreDigest::Secondary { authority_index, slot_number } - }, - }; - - Ok(pre_digest) - } -} - -/// Information about the next epoch. This is broadcast in the first block -/// of the epoch. -#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] -pub struct NextEpochDescriptor { - /// The authorities. - pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - - /// The value of randomness to use for the slot-assignment. - pub randomness: [u8; VRF_OUTPUT_LENGTH], -} - -/// A digest item which is usable with BABE consensus. -#[cfg(feature = "std")] -pub trait CompatibleDigestItem: Sized { - /// Construct a digest item which contains a BABE pre-digest. - fn babe_pre_digest(seal: BabePreDigest) -> Self; - - /// If this item is an BABE pre-digest, return it. - fn as_babe_pre_digest(&self) -> Option; - - /// Construct a digest item which contains a BABE seal. - fn babe_seal(signature: AuthoritySignature) -> Self; - - /// If this item is a BABE signature, return the signature. - fn as_babe_seal(&self) -> Option; - - /// If this item is a BABE epoch, return it. - fn as_next_epoch_descriptor(&self) -> Option; -} - -#[cfg(feature = "std")] -impl CompatibleDigestItem for DigestItem where - Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static -{ - fn babe_pre_digest(digest: BabePreDigest) -> Self { - DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode()) - } - - fn as_babe_pre_digest(&self) -> Option { - self.try_to(OpaqueDigestItemId::PreRuntime(&BABE_ENGINE_ID)) - } - - fn babe_seal(signature: AuthoritySignature) -> Self { - DigestItem::Seal(BABE_ENGINE_ID, signature.encode()) - } - - fn as_babe_seal(&self) -> Option { - self.try_to(OpaqueDigestItemId::Seal(&BABE_ENGINE_ID)) - } - - fn as_next_epoch_descriptor(&self) -> Option { - self.try_to(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)) - .and_then(|x: super::ConsensusLog| match x { - super::ConsensusLog::NextEpochData(n) => Some(n), - _ => None, - }) - } -} - -#[cfg(feature = "std")] -fn convert_error(e: SignatureError) -> codec::Error { - use SignatureError::*; - use MultiSignatureStage::*; - match e { - EquationFalse => "Signature error: `EquationFalse`".into(), - PointDecompressionError => "Signature error: `PointDecompressionError`".into(), - ScalarFormatError => "Signature error: `ScalarFormatError`".into(), - NotMarkedSchnorrkel => "Signature error: `NotMarkedSchnorrkel`".into(), - BytesLengthError { .. } => "Signature error: `BytesLengthError`".into(), - MuSigAbsent { musig_stage: Commitment } => - "Signature error: `MuSigAbsent` at stage `Commitment`".into(), - MuSigAbsent { musig_stage: Reveal } => - "Signature error: `MuSigAbsent` at stage `Reveal`".into(), - MuSigAbsent { musig_stage: Cosignature } => - "Signature error: `MuSigAbsent` at stage `Commitment`".into(), - MuSigInconsistent { musig_stage: Commitment, duplicate: true } => - "Signature error: `MuSigInconsistent` at stage `Commitment` on duplicate".into(), - MuSigInconsistent { musig_stage: Commitment, duplicate: false } => - "Signature error: `MuSigInconsistent` at stage `Commitment` on not duplicate".into(), - MuSigInconsistent { musig_stage: Reveal, duplicate: true } => - "Signature error: `MuSigInconsistent` at stage `Reveal` on duplicate".into(), - MuSigInconsistent { musig_stage: Reveal, duplicate: false } => - "Signature error: `MuSigInconsistent` at stage `Reveal` on not duplicate".into(), - MuSigInconsistent { musig_stage: Cosignature, duplicate: true } => - "Signature error: `MuSigInconsistent` at stage `Cosignature` on duplicate".into(), - MuSigInconsistent { musig_stage: Cosignature, duplicate: false } => - "Signature error: `MuSigInconsistent` at stage `Cosignature` on not duplicate".into(), - } -} diff --git a/core/consensus/babe/primitives/src/lib.rs b/core/consensus/babe/primitives/src/lib.rs deleted file mode 100644 index c464e797d8d58..0000000000000 --- a/core/consensus/babe/primitives/src/lib.rs +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Primitives for BABE. -#![deny(warnings)] -#![forbid(unsafe_code, missing_docs, unused_variables, unused_imports)] -#![cfg_attr(not(feature = "std"), no_std)] - -mod digest; - -use codec::{Encode, Decode}; -use rstd::vec::Vec; -use sr_primitives::{ConsensusEngineId, RuntimeDebug}; -use substrate_client::decl_runtime_apis; - -#[cfg(feature = "std")] -pub use digest::{BabePreDigest, CompatibleDigestItem}; -pub use digest::{BABE_VRF_PREFIX, RawBabePreDigest, NextEpochDescriptor}; - -mod app { - use app_crypto::{app_crypto, key_types::BABE, sr25519}; - app_crypto!(sr25519, BABE); -} - -/// A Babe authority keypair. Necessarily equivalent to the schnorrkel public key used in -/// the main Babe module. If that ever changes, then this must, too. -#[cfg(feature = "std")] -pub type AuthorityPair = app::Pair; - -/// A Babe authority signature. -pub type AuthoritySignature = app::Signature; - -/// A Babe authority identifier. Necessarily equivalent to the schnorrkel public key used in -/// the main Babe module. If that ever changes, then this must, too. -pub type AuthorityId = app::Public; - -/// The `ConsensusEngineId` of BABE. -pub const BABE_ENGINE_ID: ConsensusEngineId = *b"BABE"; - -/// The length of the VRF output -pub const VRF_OUTPUT_LENGTH: usize = 32; - -/// The length of the VRF proof -pub const VRF_PROOF_LENGTH: usize = 64; - -/// The length of the public key -pub const PUBLIC_KEY_LENGTH: usize = 32; - -/// How many blocks to wait before running the median algorithm for relative time -/// This will not vary from chain to chain as it is not dependent on slot duration -/// or epoch length. -pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by w3f-research. - -/// The index of an authority. -pub type AuthorityIndex = u32; - -/// A slot number. -pub type SlotNumber = u64; - -/// The weight of an authority. -// NOTE: we use a unique name for the weight to avoid conflicts with other -// `Weight` types, since the metadata isn't able to disambiguate. -pub type BabeAuthorityWeight = u64; - -/// The weight of a BABE block. -pub type BabeBlockWeight = u32; - -/// BABE epoch information -#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, RuntimeDebug)] -pub struct Epoch { - /// The epoch index - pub epoch_index: u64, - /// The starting slot of the epoch, - pub start_slot: SlotNumber, - /// The duration of this epoch - pub duration: SlotNumber, - /// The authorities and their weights - pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - /// Randomness for this epoch - pub randomness: [u8; VRF_OUTPUT_LENGTH], -} - -impl Epoch { - /// "increment" the epoch, with given descriptor for the next. - pub fn increment(&self, descriptor: NextEpochDescriptor) -> Epoch { - Epoch { - epoch_index: self.epoch_index + 1, - start_slot: self.start_slot + self.duration, - duration: self.duration, - authorities: descriptor.authorities, - randomness: descriptor.randomness, - } - } - - /// Produce the "end slot" of the epoch. This is NOT inclusive to the epoch, - // i.e. the slots covered by the epoch are `self.start_slot .. self.end_slot()`. - pub fn end_slot(&self) -> SlotNumber { - self.start_slot + self.duration - } -} - -/// An consensus log item for BABE. -#[derive(Decode, Encode, Clone, PartialEq, Eq)] -pub enum ConsensusLog { - /// The epoch has changed. This provides information about the _next_ - /// epoch - information about the _current_ epoch (i.e. the one we've just - /// entered) should already be available earlier in the chain. - #[codec(index = "1")] - NextEpochData(NextEpochDescriptor), - /// Disable the authority with given index. - #[codec(index = "2")] - OnDisabled(AuthorityIndex), -} - -/// Configuration data used by the BABE consensus engine. -#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] -pub struct BabeConfiguration { - /// The slot duration in milliseconds for BABE. Currently, only - /// the value provided by this type at genesis will be used. - /// - /// Dynamic slot duration may be supported in the future. - pub slot_duration: u64, - - /// The duration of epochs in slots. - pub epoch_length: SlotNumber, - - /// A constant value that is used in the threshold calculation formula. - /// Expressed as a rational where the first member of the tuple is the - /// numerator and the second is the denominator. The rational should - /// represent a value between 0 and 1. - /// In the threshold formula calculation, `1 - c` represents the probability - /// of a slot being empty. - pub c: (u64, u64), - - /// The authorities for the genesis epoch. - pub genesis_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - - /// The randomness for the genesis epoch. - pub randomness: [u8; VRF_OUTPUT_LENGTH], - - /// Whether this chain should run with secondary slots, which are assigned - /// in round-robin manner. - pub secondary_slots: bool, -} - -#[cfg(feature = "std")] -impl slots::SlotData for BabeConfiguration { - fn slot_duration(&self) -> u64 { - self.slot_duration - } - - const SLOT_KEY: &'static [u8] = b"babe_configuration"; -} - -decl_runtime_apis! { - /// API necessary for block authorship with BABE. - pub trait BabeApi { - /// Return the configuration for BABE. Currently, - /// only the value provided by this type at genesis will be used. - /// - /// Dynamic configuration may be supported in the future. - fn configuration() -> BabeConfiguration; - } -} diff --git a/core/consensus/babe/src/aux_schema.rs b/core/consensus/babe/src/aux_schema.rs deleted file mode 100644 index 6290d5cf31643..0000000000000 --- a/core/consensus/babe/src/aux_schema.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Schema for BABE epoch changes in the aux-db. - -use log::info; -use codec::{Decode, Encode}; - -use client::backend::AuxStore; -use client::error::{Result as ClientResult, Error as ClientError}; -use sr_primitives::traits::Block as BlockT; -use babe_primitives::BabeBlockWeight; - -use super::{epoch_changes::EpochChangesFor, SharedEpochChanges}; - -const BABE_EPOCH_CHANGES: &[u8] = b"babe_epoch_changes"; - -fn block_weight_key(block_hash: H) -> Vec { - (b"block_weight", block_hash).encode() -} - -fn load_decode(backend: &B, key: &[u8]) -> ClientResult> - where - B: AuxStore, - T: Decode, -{ - let corrupt = |e: codec::Error| { - ClientError::Backend(format!("BABE DB is corrupted. Decode error: {}", e.what())) - }; - match backend.get_aux(key)? { - None => Ok(None), - Some(t) => T::decode(&mut &t[..]).map(Some).map_err(corrupt) - } -} - -/// Load or initialize persistent epoch change data from backend. -pub(crate) fn load_epoch_changes( - backend: &B, -) -> ClientResult> { - let epoch_changes = load_decode::<_, EpochChangesFor>(backend, BABE_EPOCH_CHANGES)? - .map(Into::into) - .unwrap_or_else(|| { - info!(target: "babe", - "Creating empty BABE epoch changes on what appears to be first startup." - ); - SharedEpochChanges::new() - }); - - Ok(epoch_changes) -} - -/// Update the epoch changes on disk after a change. -pub(crate) fn write_epoch_changes( - epoch_changes: &EpochChangesFor, - write_aux: F, -) -> R where - F: FnOnce(&[(&'static [u8], &[u8])]) -> R, -{ - let encoded_epoch_changes = epoch_changes.encode(); - write_aux( - &[(BABE_EPOCH_CHANGES, encoded_epoch_changes.as_slice())], - ) -} - -/// Write the cumulative chain-weight of a block ot aux storage. -pub(crate) fn write_block_weight( - block_hash: H, - block_weight: &BabeBlockWeight, - write_aux: F, -) -> R where - F: FnOnce(&[(Vec, &[u8])]) -> R, -{ - - let key = block_weight_key(block_hash); - block_weight.using_encoded(|s| - write_aux( - &[(key, s)], - ) - ) -} - -/// Load the cumulative chain-weight associated with a block. -pub(crate) fn load_block_weight( - backend: &B, - block_hash: H, -) -> ClientResult> { - load_decode(backend, block_weight_key(block_hash).as_slice()) -} diff --git a/core/consensus/babe/src/lib.rs b/core/consensus/babe/src/lib.rs deleted file mode 100644 index 287b26a300f43..0000000000000 --- a/core/consensus/babe/src/lib.rs +++ /dev/null @@ -1,1196 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # BABE (Blind Assignment for Blockchain Extension) -//! -//! BABE is a slot-based block production mechanism which uses a VRF PRNG to -//! randomly perform the slot allocation. On every slot, all the authorities -//! generate a new random number with the VRF function and if it is lower than a -//! given threshold (which is proportional to their weight/stake) they have a -//! right to produce a block. The proof of the VRF function execution will be -//! used by other peer to validate the legitimacy of the slot claim. -//! -//! The engine is also responsible for collecting entropy on-chain which will be -//! used to seed the given VRF PRNG. An epoch is a contiguous number of slots -//! under which we will be using the same authority set. During an epoch all VRF -//! outputs produced as a result of block production will be collected on an -//! on-chain randomness pool. Epoch changes are announced one epoch in advance, -//! i.e. when ending epoch N, we announce the parameters (randomness, -//! authorities, etc.) for epoch N+2. -//! -//! Since the slot assignment is randomized, it is possible that a slot is -//! assigned to multiple validators in which case we will have a temporary fork, -//! or that a slot is assigned to no validator in which case no block is -//! produced. Which means that block times are not deterministic. -//! -//! The protocol has a parameter `c` [0, 1] for which `1 - c` is the probability -//! of a slot being empty. The choice of this parameter affects the security of -//! the protocol relating to maximum tolerable network delays. -//! -//! In addition to the VRF-based slot assignment described above, which we will -//! call primary slots, the engine also supports a deterministic secondary slot -//! assignment. Primary slots take precedence over secondary slots, when -//! authoring the node starts by trying to claim a primary slot and falls back -//! to a secondary slot claim attempt. The secondary slot assignment is done -//! by picking the authority at index: -//! -//! `blake2_256(epoch_randomness ++ slot_number) % authorities_len`. -//! -//! The fork choice rule is weight-based, where weight equals the number of -//! primary blocks in the chain. We will pick the heaviest chain (more primary -//! blocks) and will go with the longest one in case of a tie. -//! -//! An in-depth description and analysis of the protocol can be found here: -//! - -#![forbid(unsafe_code)] -#![warn(missing_docs)] -pub use babe_primitives::*; -pub use consensus_common::SyncOracle; -use std::{collections::HashMap, sync::Arc, u64, pin::Pin, time::{Instant, Duration}}; -use babe_primitives; -use consensus_common::ImportResult; -use consensus_common::import_queue::{ - BoxJustificationImport, BoxFinalityProofImport, -}; -use sr_primitives::{generic::{BlockId, OpaqueDigestItemId}, Justification, RuntimeString}; -use sr_primitives::traits::{ - Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, - Zero, -}; -use keystore::KeyStorePtr; -use parking_lot::Mutex; -use primitives::{Blake2Hasher, H256, Pair}; -use inherents::{InherentDataProviders, InherentData}; -use substrate_telemetry::{ - telemetry, - CONSENSUS_TRACE, - CONSENSUS_DEBUG, -}; -use consensus_common::{ - self, BlockImport, Environment, Proposer, BlockCheckParams, - ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError, -}; -use srml_babe::{ - BabeInherentData, - timestamp::{TimestampInherentData, InherentType as TimestampInherent} -}; -use consensus_common::SelectChain; -use consensus_common::import_queue::{Verifier, BasicQueue, CacheKeyId}; -use client::{ - block_builder::api::BlockBuilder as BlockBuilderApi, - blockchain::{self, HeaderBackend, ProvideCache}, BlockchainEvents, CallExecutor, Client, - error::Result as ClientResult, error::Error as ClientError, backend::{AuxStore, Backend}, - ProvideUncles, -}; -use slots::{CheckedHeader, check_equivocation}; -use futures::prelude::*; -use log::{warn, debug, info, trace}; -use slots::{SlotWorker, SlotData, SlotInfo, SlotCompatible}; -use epoch_changes::descendent_query; -use header_metadata::HeaderMetadata; -use schnorrkel::SignatureError; - -mod aux_schema; -mod verification; -mod epoch_changes; -mod authorship; -#[cfg(test)] -mod tests; -pub use babe_primitives::{ - AuthorityId, AuthorityPair, AuthoritySignature, Epoch, NextEpochDescriptor, -}; -pub use epoch_changes::{EpochChanges, EpochChangesFor, SharedEpochChanges}; - - -#[derive(derive_more::Display, Debug)] -enum Error { - #[display(fmt = "Multiple BABE pre-runtime digests, rejecting!")] - MultiplePreRuntimeDigests, - #[display(fmt = "No BABE pre-runtime digest found")] - NoPreRuntimeDigest, - #[display(fmt = "Multiple BABE epoch change digests, rejecting!")] - MultipleEpochChangeDigests, - #[display(fmt = "Could not extract timestamp and slot: {:?}", _0)] - Extraction(consensus_common::Error), - #[display(fmt = "Could not fetch epoch at {:?}", _0)] - FetchEpoch(B::Hash), - #[display(fmt = "Header {:?} rejected: too far in the future", _0)] - TooFarInFuture(B::Hash), - #[display(fmt = "Parent ({}) of {} unavailable. Cannot import", _0, _1)] - ParentUnavailable(B::Hash, B::Hash), - #[display(fmt = "Slot number must increase: parent slot: {}, this slot: {}", _0, _1)] - SlotNumberMustIncrease(u64, u64), - #[display(fmt = "Header {:?} has a bad seal", _0)] - HeaderBadSeal(B::Hash), - #[display(fmt = "Header {:?} is unsealed", _0)] - HeaderUnsealed(B::Hash), - #[display(fmt = "Slot author not found")] - SlotAuthorNotFound, - #[display(fmt = "Secondary slot assignments are disabled for the current epoch.")] - SecondarySlotAssignmentsDisabled, - #[display(fmt = "Bad signature on {:?}", _0)] - BadSignature(B::Hash), - #[display(fmt = "Invalid author: Expected secondary author: {:?}, got: {:?}.", _0, _1)] - InvalidAuthor(AuthorityId, AuthorityId), - #[display(fmt = "No secondary author expected.")] - NoSecondaryAuthorExpected, - #[display(fmt = "VRF verification of block by author {:?} failed: threshold {} exceeded", _0, _1)] - VRFVerificationOfBlockFailed(AuthorityId, u128), - #[display(fmt = "VRF verification failed: {:?}", _0)] - VRFVerificationFailed(SignatureError), - #[display(fmt = "Could not fetch parent header: {:?}", _0)] - FetchParentHeader(client::error::Error), - #[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)] - ExpectedEpochChange(B::Hash, u64), - #[display(fmt = "Could not look up epoch: {:?}", _0)] - CouldNotLookUpEpoch(Box>), - #[display(fmt = "Block {} is not valid under any epoch.", _0)] - BlockNotValid(B::Hash), - #[display(fmt = "Unexpected epoch change")] - UnexpectedEpochChange, - #[display(fmt = "Parent block of {} has no associated weight", _0)] - ParentBlockNoAssociatedWeight(B::Hash), - #[display(fmt = "Checking inherents failed: {}", _0)] - CheckInherents(String), - Client(client::error::Error), - Runtime(RuntimeString), - ForkTree(Box>), -} - -impl std::convert::From> for String { - fn from(error: Error) -> String { - error.to_string() - } -} - -fn babe_err(error: Error) -> Error { - debug!(target: "babe", "{}", error); - error -} - -macro_rules! babe_info { - ($($i: expr),+) => { - { - info!(target: "babe", $($i),+); - format!($($i),+) - } - }; -} - -/// A slot duration. Create with `get_or_compute`. -// FIXME: Once Rust has higher-kinded types, the duplication between this -// and `super::babe::Config` can be eliminated. -// https://github.com/paritytech/substrate/issues/2434 -#[derive(Clone)] -pub struct Config(slots::SlotDuration); - -impl Config { - /// Either fetch the slot duration from disk or compute it from the genesis - /// state. - pub fn get_or_compute(client: &C) -> ClientResult where - C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi, - { - trace!(target: "babe", "Getting slot duration"); - match slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) { - Ok(s) => Ok(s), - Err(s) => { - warn!(target: "babe", "Failed to get slot duration"); - Err(s) - } - } - } - - /// Create the genesis epoch (epoch #0). This is defined to start at the slot of - /// the first block, so that has to be provided. - pub fn genesis_epoch(&self, slot_number: SlotNumber) -> Epoch { - Epoch { - epoch_index: 0, - start_slot: slot_number, - duration: self.epoch_length, - authorities: self.genesis_authorities.clone(), - randomness: self.randomness.clone(), - } - } -} - -impl std::ops::Deref for Config { - type Target = BabeConfiguration; - - fn deref(&self) -> &BabeConfiguration { - &*self.0 - } -} - -/// Parameters for BABE. -pub struct BabeParams { - /// The keystore that manages the keys of the node. - pub keystore: KeyStorePtr, - - /// The client to use - pub client: Arc, - - /// The SelectChain Strategy - pub select_chain: SC, - - /// The environment we are producing blocks for. - pub env: E, - - /// The underlying block-import object to supply our produced blocks to. - /// This must be a `BabeBlockImport` or a wrapper of it, otherwise - /// critical consensus logic will be omitted. - pub block_import: I, - - /// A sync oracle - pub sync_oracle: SO, - - /// Providers for inherent data. - pub inherent_data_providers: InherentDataProviders, - - /// Force authoring of blocks even if we are offline - pub force_authoring: bool, - - /// The source of timestamps for relative slots - pub babe_link: BabeLink, -} - -/// Start the babe worker. The returned future should be run in a tokio runtime. -pub fn start_babe(BabeParams { - keystore, - client, - select_chain, - env, - block_import, - sync_oracle, - inherent_data_providers, - force_authoring, - babe_link, -}: BabeParams) -> Result< - impl futures01::Future, - consensus_common::Error, -> where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache + ProvideUncles + BlockchainEvents - + HeaderBackend + HeaderMetadata + Send + Sync + 'static, - C::Api: BabeApi, - SC: SelectChain + 'static, - E: Environment + Send + Sync, - E::Proposer: Proposer, - >::Create: Unpin + Send + 'static, - I: BlockImport + Send + Sync + 'static, - Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, - SO: SyncOracle + Send + Sync + Clone, -{ - let config = babe_link.config; - let worker = BabeWorker { - client: client.clone(), - block_import: Arc::new(Mutex::new(block_import)), - env, - sync_oracle: sync_oracle.clone(), - force_authoring, - keystore, - epoch_changes: babe_link.epoch_changes.clone(), - config: config.clone(), - }; - - register_babe_inherent_data_provider(&inherent_data_providers, config.slot_duration())?; - uncles::register_uncles_inherent_data_provider( - client.clone(), - select_chain.clone(), - &inherent_data_providers, - )?; - - babe_info!("Starting BABE Authorship worker"); - let slot_worker = slots::start_slot_worker( - config.0, - select_chain, - worker, - sync_oracle, - inherent_data_providers, - babe_link.time_source, - ); - - Ok(slot_worker.map(|_| Ok::<(), ()>(())).compat()) -} - -struct BabeWorker { - client: Arc, - block_import: Arc>, - env: E, - sync_oracle: SO, - force_authoring: bool, - keystore: KeyStorePtr, - epoch_changes: SharedEpochChanges, - config: Config, -} - -impl slots::SimpleSlotWorker for BabeWorker where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache + HeaderBackend + HeaderMetadata, - C::Api: BabeApi, - E: Environment, - E::Proposer: Proposer, - >::Create: Unpin + Send + 'static, - I: BlockImport + Send + Sync + 'static, - SO: SyncOracle + Send + Clone, - Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, -{ - type EpochData = Epoch; - type Claim = (BabePreDigest, AuthorityPair); - type SyncOracle = SO; - type Proposer = E::Proposer; - type BlockImport = I; - - fn logging_target(&self) -> &'static str { - "babe" - } - - fn block_import(&self) -> Arc> { - self.block_import.clone() - } - - fn epoch_data(&self, parent: &B::Header, slot_number: u64) -> Result { - self.epoch_changes.lock().epoch_for_child_of( - descendent_query(&*self.client), - &parent.hash(), - parent.number().clone(), - slot_number, - |slot| self.config.genesis_epoch(slot) - ) - .map_err(|e| ConsensusError::ChainLookup(format!("{:?}", e)))? - .map(|e| e.into_inner()) - .ok_or(consensus_common::Error::InvalidAuthoritiesSet) - } - - fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize { - epoch_data.authorities.len() - } - - fn claim_slot( - &self, - _parent_header: &B::Header, - slot_number: SlotNumber, - epoch_data: &Epoch, - ) -> Option { - debug!(target: "babe", "Attempting to claim slot {}", slot_number); - let s = authorship::claim_slot( - slot_number, - epoch_data, - &*self.config, - &self.keystore, - ); - - if let Some(_) = s { - debug!(target: "babe", "Claimed slot {}", slot_number); - } - - s - } - - fn pre_digest_data(&self, _slot_number: u64, claim: &Self::Claim) -> Vec> { - vec![ - as CompatibleDigestItem>::babe_pre_digest(claim.0.clone()), - ] - } - - fn block_import_params(&self) -> Box, - Self::Claim, - ) -> consensus_common::BlockImportParams + Send> { - Box::new(|header, header_hash, body, (_, pair)| { - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let signature = pair.sign(header_hash.as_ref()); - let signature_digest_item = as CompatibleDigestItem>::babe_seal(signature); - - BlockImportParams { - origin: BlockOrigin::Own, - header, - justification: None, - post_digests: vec![signature_digest_item], - body: Some(body), - finalized: false, - auxiliary: Vec::new(), // block-weight is written in block import. - // TODO: block-import handles fork choice and this shouldn't even have the - // option to specify one. - // https://github.com/paritytech/substrate/issues/3623 - fork_choice: ForkChoiceStrategy::LongestChain, - } - }) - } - - fn force_authoring(&self) -> bool { - self.force_authoring - } - - fn sync_oracle(&mut self) -> &mut Self::SyncOracle { - &mut self.sync_oracle - } - - fn proposer(&mut self, block: &B::Header) -> Result { - self.env.init(block).map_err(|e| { - consensus_common::Error::ClientImport(format!("{:?}", e)) - }) - } -} - -impl SlotWorker for BabeWorker where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache + HeaderBackend + HeaderMetadata + Send + Sync, - C::Api: BabeApi, - E: Environment + Send + Sync, - E::Proposer: Proposer, - >::Create: Unpin + Send + 'static, - I: BlockImport + Send + Sync + 'static, - SO: SyncOracle + Send + Sync + Clone, - Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, -{ - type OnSlot = Pin> + Send>>; - - fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot { - >::on_slot(self, chain_head, slot_info) - } -} - -/// Extract the BABE pre digest from the given header. Pre-runtime digests are -/// mandatory, the function will return `Err` if none is found. -fn find_pre_digest(header: &B::Header) -> Result> -{ - // genesis block doesn't contain a pre digest so let's generate a - // dummy one to not break any invariants in the rest of the code - if header.number().is_zero() { - return Ok(BabePreDigest::Secondary { - slot_number: 0, - authority_index: 0, - }); - } - - let mut pre_digest: Option<_> = None; - for log in header.digest().logs() { - trace!(target: "babe", "Checking log {:?}, looking for pre runtime digest", log); - match (log.as_babe_pre_digest(), pre_digest.is_some()) { - (Some(_), true) => return Err(babe_err(Error::MultiplePreRuntimeDigests)), - (None, _) => trace!(target: "babe", "Ignoring digest not meant for us"), - (s, false) => pre_digest = s, - } - } - pre_digest.ok_or_else(|| babe_err(Error::NoPreRuntimeDigest)) -} - -/// Extract the BABE epoch change digest from the given header, if it exists. -fn find_next_epoch_digest(header: &B::Header) - -> Result, Error> - where DigestItemFor: CompatibleDigestItem, -{ - let mut epoch_digest: Option<_> = None; - for log in header.digest().logs() { - trace!(target: "babe", "Checking log {:?}, looking for epoch change digest.", log); - let log = log.try_to::(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)); - match (log, epoch_digest.is_some()) { - (Some(ConsensusLog::NextEpochData(_)), true) => return Err(babe_err(Error::MultipleEpochChangeDigests)), - (Some(ConsensusLog::NextEpochData(epoch)), false) => epoch_digest = Some(epoch), - _ => trace!(target: "babe", "Ignoring digest not meant for us"), - } - } - - Ok(epoch_digest) -} - - -#[derive(Default, Clone)] -struct TimeSource(Arc, Vec<(Instant, u64)>)>>); - -impl SlotCompatible for TimeSource { - fn extract_timestamp_and_slot( - &self, - data: &InherentData, - ) -> Result<(TimestampInherent, u64, std::time::Duration), consensus_common::Error> { - trace!(target: "babe", "extract timestamp"); - data.timestamp_inherent_data() - .and_then(|t| data.babe_inherent_data().map(|a| (t, a))) - .map_err(Into::into) - .map_err(consensus_common::Error::InherentData) - .map(|(x, y)| (x, y, self.0.lock().0.take().unwrap_or_default())) - } -} - -/// State that must be shared between the import queue and the authoring logic. -#[derive(Clone)] -pub struct BabeLink { - time_source: TimeSource, - epoch_changes: SharedEpochChanges, - config: Config, -} -/// A verifier for Babe blocks. -pub struct BabeVerifier { - client: Arc>, - api: Arc, - inherent_data_providers: inherents::InherentDataProviders, - config: Config, - epoch_changes: SharedEpochChanges, - time_source: TimeSource, -} - -impl BabeVerifier { - fn check_inherents( - &self, - block: Block, - block_id: BlockId, - inherent_data: InherentData, - ) -> Result<(), Error> - where PRA: ProvideRuntimeApi, PRA::Api: BlockBuilderApi - { - let inherent_res = self.api.runtime_api().check_inherents( - &block_id, - block, - inherent_data, - ).map_err(Error::Client)?; - - if !inherent_res.ok() { - inherent_res - .into_errors() - .try_for_each(|(i, e)| { - Err(Error::CheckInherents(self.inherent_data_providers.error_to_string(&i, &e))) - }) - } else { - Ok(()) - } - } -} - -#[allow(dead_code)] -fn median_algorithm( - median_required_blocks: u64, - slot_duration: u64, - slot_number: u64, - slot_now: u64, - time_source: &mut (Option, Vec<(Instant, u64)>), -) { - let num_timestamps = time_source.1.len(); - if num_timestamps as u64 >= median_required_blocks && median_required_blocks > 0 { - let mut new_list: Vec<_> = time_source.1.iter().map(|&(t, sl)| { - let offset: u128 = u128::from(slot_duration) - .checked_mul(1_000_000u128) // self.config.slot_duration returns milliseconds - .and_then(|x| { - x.checked_mul(u128::from(slot_number).saturating_sub(u128::from(sl))) - }) - .expect("we cannot have timespans long enough for this to overflow; qed"); - - const NANOS_PER_SEC: u32 = 1_000_000_000; - let nanos = (offset % u128::from(NANOS_PER_SEC)) as u32; - let secs = (offset / u128::from(NANOS_PER_SEC)) as u64; - - t + Duration::new(secs, nanos) - }).collect(); - - // Use a partial sort to move the median timestamp to the middle of the list - pdqselect::select(&mut new_list, num_timestamps / 2); - - let &median = new_list - .get(num_timestamps / 2) - .expect("we have at least one timestamp, so this is a valid index; qed"); - - let now = Instant::now(); - if now >= median { - time_source.0.replace(now - median); - } - - time_source.1.clear(); - } else { - time_source.1.push((Instant::now(), slot_now)) - } -} - -impl Verifier for BabeVerifier where - Block: BlockT, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, - PRA: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache, - PRA::Api: BlockBuilderApi + BabeApi, -{ - fn verify( - &mut self, - origin: BlockOrigin, - header: Block::Header, - justification: Option, - mut body: Option>, - ) -> Result<(BlockImportParams, Option)>>), String> { - trace!( - target: "babe", - "Verifying origin: {:?} header: {:?} justification: {:?} body: {:?}", - origin, - header, - justification, - body, - ); - - debug!(target: "babe", "We have {:?} logs in this header", header.digest().logs().len()); - let mut inherent_data = self - .inherent_data_providers - .create_inherent_data() - .map_err( Error::::Runtime)?; - - let (_, slot_now, _) = self.time_source.extract_timestamp_and_slot(&inherent_data) - .map_err(Error::::Extraction)?; - - let hash = header.hash(); - let parent_hash = *header.parent_hash(); - - let parent_header_metadata = self.client.header_metadata(parent_hash) - .map_err(Error::::FetchParentHeader)?; - - let pre_digest = find_pre_digest::(&header)?; - let epoch = { - let epoch_changes = self.epoch_changes.lock(); - epoch_changes.epoch_for_child_of( - descendent_query(&*self.client), - &parent_hash, - parent_header_metadata.number, - pre_digest.slot_number(), - |slot| self.config.genesis_epoch(slot), - ) - .map_err(|e| Error::::ForkTree(Box::new(e)))? - .ok_or_else(|| Error::::FetchEpoch(parent_hash))? - }; - - // We add one to the current slot to allow for some small drift. - // FIXME #1019 in the future, alter this queue to allow deferring of headers - let v_params = verification::VerificationParams { - header: header.clone(), - pre_digest: Some(pre_digest.clone()), - slot_now: slot_now + 1, - epoch: epoch.as_ref(), - config: &self.config, - }; - - match verification::check_header::(v_params)? { - CheckedHeader::Checked(pre_header, verified_info) => { - let babe_pre_digest = verified_info.pre_digest.as_babe_pre_digest() - .expect("check_header always returns a pre-digest digest item; qed"); - - let slot_number = babe_pre_digest.slot_number(); - - let author = verified_info.author; - - // the header is valid but let's check if there was something else already - // proposed at the same slot by the given author - if let Some(equivocation_proof) = check_equivocation( - &*self.api, - slot_now, - babe_pre_digest.slot_number(), - &header, - &author, - ).map_err(|e| e.to_string())? { - info!( - "Slot author {:?} is equivocating at slot {} with headers {:?} and {:?}", - author, - babe_pre_digest.slot_number(), - equivocation_proof.fst_header().hash(), - equivocation_proof.snd_header().hash(), - ); - } - - // if the body is passed through, we need to use the runtime - // to check that the internally-set timestamp in the inherents - // actually matches the slot set in the seal. - if let Some(inner_body) = body.take() { - inherent_data.babe_replace_inherent_data(slot_number); - let block = Block::new(pre_header.clone(), inner_body); - - self.check_inherents( - block.clone(), - BlockId::Hash(parent_hash), - inherent_data, - )?; - - let (_, inner_body) = block.deconstruct(); - body = Some(inner_body); - } - - trace!(target: "babe", "Checked {:?}; importing.", pre_header); - telemetry!( - CONSENSUS_TRACE; - "babe.checked_and_importing"; - "pre_header" => ?pre_header); - - let block_import_params = BlockImportParams { - origin, - header: pre_header, - post_digests: vec![verified_info.seal], - body, - finalized: false, - justification, - auxiliary: Vec::new(), - // TODO: block-import handles fork choice and this shouldn't even have the - // option to specify one. - // https://github.com/paritytech/substrate/issues/3623 - fork_choice: ForkChoiceStrategy::LongestChain, - }; - - Ok((block_import_params, Default::default())) - } - CheckedHeader::Deferred(a, b) => { - debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); - telemetry!(CONSENSUS_DEBUG; "babe.header_too_far_in_future"; - "hash" => ?hash, "a" => ?a, "b" => ?b - ); - Err(Error::::TooFarInFuture(hash).into()) - } - } - } -} - -/// The BABE import queue type. -pub type BabeImportQueue = BasicQueue; - -/// Register the babe inherent data provider, if not registered already. -fn register_babe_inherent_data_provider( - inherent_data_providers: &InherentDataProviders, - slot_duration: u64, -) -> Result<(), consensus_common::Error> { - debug!(target: "babe", "Registering"); - if !inherent_data_providers.has_provider(&srml_babe::INHERENT_IDENTIFIER) { - inherent_data_providers - .register_provider(srml_babe::InherentDataProvider::new(slot_duration)) - .map_err(Into::into) - .map_err(consensus_common::Error::InherentData) - } else { - Ok(()) - } -} - -/// A block-import handler for BABE. -/// -/// This scans each imported block for epoch change signals. The signals are -/// tracked in a tree (of all forks), and the import logic validates all epoch -/// change transitions, i.e. whether a given epoch change is expected or whether -/// it is missing. -/// -/// The epoch change tree should be pruned as blocks are finalized. -pub struct BabeBlockImport { - inner: I, - client: Arc>, - api: Arc, - epoch_changes: SharedEpochChanges, - config: Config, -} - -impl Clone for BabeBlockImport { - fn clone(&self) -> Self { - BabeBlockImport { - inner: self.inner.clone(), - client: self.client.clone(), - api: self.api.clone(), - epoch_changes: self.epoch_changes.clone(), - config: self.config.clone(), - } - } -} - -impl BabeBlockImport { - fn new( - client: Arc>, - api: Arc, - epoch_changes: SharedEpochChanges, - block_import: I, - config: Config, - ) -> Self { - BabeBlockImport { - client, - api, - inner: block_import, - epoch_changes, - config, - } - } -} - -impl BlockImport for BabeBlockImport where - Block: BlockT, - I: BlockImport + Send + Sync, - I::Error: Into, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, - PRA: ProvideRuntimeApi + ProvideCache, - PRA::Api: BabeApi, -{ - type Error = ConsensusError; - - fn import_block( - &mut self, - mut block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - let hash = block.post_header().hash(); - let number = block.header.number().clone(); - - // early exit if block already in chain, otherwise the check for - // epoch changes will error when trying to re-import an epoch change - match self.client.status(BlockId::Hash(hash)) { - Ok(blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), - Ok(blockchain::BlockStatus::Unknown) => {}, - Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), - } - - let pre_digest = find_pre_digest::(&block.header) - .expect("valid babe headers must contain a predigest; \ - header has been already verified; qed"); - let slot_number = pre_digest.slot_number(); - - let parent_hash = *block.header.parent_hash(); - let parent_header = self.client.header(&BlockId::Hash(parent_hash)) - .map_err(|e| ConsensusError::ChainLookup(e.to_string()))? - .ok_or_else(|| ConsensusError::ChainLookup(babe_err( - Error::::ParentUnavailable(parent_hash, hash) - ).into()))?; - - let parent_slot = find_pre_digest::(&parent_header) - .map(|d| d.slot_number()) - .expect("parent is non-genesis; valid BABE headers contain a pre-digest; \ - header has already been verified; qed"); - - // make sure that slot number is strictly increasing - if slot_number <= parent_slot { - return Err( - ConsensusError::ClientImport(babe_err( - Error::::SlotNumberMustIncrease(parent_slot, slot_number) - ).into()) - ); - } - - let mut epoch_changes = self.epoch_changes.lock(); - - // check if there's any epoch change expected to happen at this slot. - // `epoch` is the epoch to verify the block under, and `first_in_epoch` is true - // if this is the first block in its chain for that epoch. - // - // also provides the total weight of the chain, including the imported block. - let (epoch, first_in_epoch, parent_weight) = { - let parent_weight = if *parent_header.number() == Zero::zero() { - 0 - } else { - aux_schema::load_block_weight(&*self.client, parent_hash) - .map_err(|e| ConsensusError::ClientImport(e.to_string()))? - .ok_or_else(|| ConsensusError::ClientImport( - babe_err(Error::::ParentBlockNoAssociatedWeight(hash)).into() - ))? - }; - - let epoch = epoch_changes.epoch_for_child_of( - descendent_query(&*self.client), - &parent_hash, - *parent_header.number(), - slot_number, - |slot| self.config.genesis_epoch(slot), - ) - .map_err(|e: fork_tree::Error| ConsensusError::ChainLookup( - babe_err(Error::::CouldNotLookUpEpoch(Box::new(e))).into() - ))? - .ok_or_else(|| ConsensusError::ClientImport( - babe_err(Error::::BlockNotValid(hash)).into() - ))?; - - let first_in_epoch = parent_slot < epoch.as_ref().start_slot; - (epoch, first_in_epoch, parent_weight) - }; - - let total_weight = parent_weight + pre_digest.added_weight(); - - // search for this all the time so we can reject unexpected announcements. - let next_epoch_digest = find_next_epoch_digest::(&block.header) - .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; - - match (first_in_epoch, next_epoch_digest.is_some()) { - (true, true) => {}, - (false, false) => {}, - (true, false) => { - return Err( - ConsensusError::ClientImport( - babe_err(Error::::ExpectedEpochChange(hash, slot_number)).into(), - ) - ); - }, - (false, true) => { - return Err(ConsensusError::ClientImport(Error::::UnexpectedEpochChange.into())); - }, - } - - // if there's a pending epoch we'll save the previous epoch changes here - // this way we can revert it if there's any error - let mut old_epoch_changes = None; - - let info = self.client.info().chain; - - if let Some(next_epoch_descriptor) = next_epoch_digest { - let next_epoch = epoch.increment(next_epoch_descriptor); - - old_epoch_changes = Some(epoch_changes.clone()); - - babe_info!("New epoch {} launching at block {} (block slot {} >= start slot {}).", - epoch.as_ref().epoch_index, hash, slot_number, epoch.as_ref().start_slot); - babe_info!("Next epoch starts at slot {}", next_epoch.as_ref().start_slot); - - // prune the tree of epochs not part of the finalized chain or - // that are not live anymore, and then track the given epoch change - // in the tree. - // NOTE: it is important that these operations are done in this - // order, otherwise if pruning after import the `is_descendent_of` - // used by pruning may not know about the block that is being - // imported. - let prune_and_import = || { - prune_finalized( - &self.client, - &mut epoch_changes, - )?; - - epoch_changes.import( - descendent_query(&*self.client), - hash, - number, - *block.header.parent_hash(), - next_epoch, - ).map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))?; - - Ok(()) - }; - - if let Err(e) = prune_and_import() { - debug!(target: "babe", "Failed to launch next epoch: {:?}", e); - *epoch_changes = old_epoch_changes.expect("set `Some` above and not taken; qed"); - return Err(e); - } - - crate::aux_schema::write_epoch_changes::( - &*epoch_changes, - |insert| block.auxiliary.extend( - insert.iter().map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) - ) - ); - } - - aux_schema::write_block_weight( - hash, - &total_weight, - |values| block.auxiliary.extend( - values.iter().map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) - ), - ); - - // The fork choice rule is that we pick the heaviest chain (i.e. - // more primary blocks), if there's a tie we go with the longest - // chain. - block.fork_choice = { - let (last_best, last_best_number) = (info.best_hash, info.best_number); - - let last_best_weight = if &last_best == block.header.parent_hash() { - // the parent=genesis case is already covered for loading parent weight, - // so we don't need to cover again here. - parent_weight - } else { - aux_schema::load_block_weight(&*self.client, last_best) - .map_err(|e| ConsensusError::ChainLookup(format!("{:?}", e)))? - .ok_or_else( - || ConsensusError::ChainLookup(format!("No block weight for parent header.")) - )? - }; - - ForkChoiceStrategy::Custom(if total_weight > last_best_weight { - true - } else if total_weight == last_best_weight { - number > last_best_number - } else { - false - }) - }; - - let import_result = self.inner.import_block(block, new_cache); - - // revert to the original epoch changes in case there's an error - // importing the block - if let Err(_) = import_result { - if let Some(old_epoch_changes) = old_epoch_changes { - *epoch_changes = old_epoch_changes; - } - } - - import_result.map_err(Into::into) - } - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - self.inner.check_block(block).map_err(Into::into) - } -} - -/// Gets the best finalized block and its slot, and prunes the given epoch tree. -fn prune_finalized( - client: &Client, - epoch_changes: &mut EpochChangesFor, -) -> Result<(), ConsensusError> where - Block: BlockT, - E: CallExecutor + Send + Sync, - B: Backend, - RA: Send + Sync, -{ - let info = client.info().chain; - - let finalized_slot = { - let finalized_header = client.header(&BlockId::Hash(info.finalized_hash)) - .map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))? - .expect("best finalized hash was given by client; \ - finalized headers must exist in db; qed"); - - find_pre_digest::(&finalized_header) - .expect("finalized header must be valid; \ - valid blocks have a pre-digest; qed") - .slot_number() - }; - - epoch_changes.prune_finalized( - descendent_query(&*client), - &info.finalized_hash, - info.finalized_number, - finalized_slot, - ).map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))?; - - Ok(()) -} - -/// Produce a BABE block-import object to be used later on in the construction of -/// an import-queue. -/// -/// Also returns a link object used to correctly instantiate the import queue -/// and background worker. -pub fn block_import, I, RA, PRA>( - config: Config, - wrapped_block_import: I, - client: Arc>, - api: Arc, -) -> ClientResult<(BabeBlockImport, BabeLink)> where - B: Backend, - E: CallExecutor + Send + Sync, - RA: Send + Sync, -{ - let epoch_changes = aux_schema::load_epoch_changes(&*client)?; - let link = BabeLink { - epoch_changes: epoch_changes.clone(), - time_source: Default::default(), - config: config.clone(), - }; - - // NOTE: this isn't entirely necessary, but since we didn't use to prune the - // epoch tree it is useful as a migration, so that nodes prune long trees on - // startup rather than waiting until importing the next epoch change block. - prune_finalized( - &client, - &mut epoch_changes.lock(), - )?; - - let import = BabeBlockImport::new( - client, - api, - epoch_changes, - wrapped_block_import, - config, - ); - - Ok((import, link)) -} - -/// Start an import queue for the BABE consensus algorithm. -/// -/// This method returns the import queue, some data that needs to be passed to the block authoring -/// logic (`BabeLink`), and a future that must be run to -/// completion and is responsible for listening to finality notifications and -/// pruning the epoch changes tree. -/// -/// The block import object provided must be the `BabeBlockImport` or a wrapper -/// of it, otherwise crucial import logic will be omitted. -pub fn import_queue, I, RA, PRA>( - babe_link: BabeLink, - block_import: I, - justification_import: Option>, - finality_proof_import: Option>, - client: Arc>, - api: Arc, - inherent_data_providers: InherentDataProviders, -) -> ClientResult> where - B: Backend + 'static, - I: BlockImport + Send + Sync + 'static, - E: CallExecutor + Clone + Send + Sync + 'static, - RA: Send + Sync + 'static, - PRA: ProvideRuntimeApi + ProvideCache + Send + Sync + AuxStore + 'static, - PRA::Api: BlockBuilderApi + BabeApi, -{ - register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?; - - let verifier = BabeVerifier { - client: client.clone(), - api, - inherent_data_providers, - config: babe_link.config, - epoch_changes: babe_link.epoch_changes, - time_source: babe_link.time_source, - }; - - Ok(BasicQueue::new( - verifier, - Box::new(block_import), - justification_import, - finality_proof_import, - )) -} - -/// BABE test helpers. Utility methods for manually authoring blocks. -#[cfg(feature = "test-helpers")] -pub mod test_helpers { - use super::*; - - /// Try to claim the given slot and return a `BabePreDigest` if - /// successful. - pub fn claim_slot( - slot_number: u64, - parent: &B::Header, - client: &C, - keystore: &KeyStorePtr, - link: &BabeLink, - ) -> Option where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache + HeaderBackend + HeaderMetadata, - C::Api: BabeApi, - { - let epoch = link.epoch_changes.lock().epoch_for_child_of( - descendent_query(client), - &parent.hash(), - parent.number().clone(), - slot_number, - |slot| link.config.genesis_epoch(slot), - ).unwrap().unwrap(); - - authorship::claim_slot( - slot_number, - epoch.as_ref(), - &link.config, - keystore, - ).map(|(digest, _)| digest) - } -} diff --git a/core/consensus/babe/src/tests.rs b/core/consensus/babe/src/tests.rs deleted file mode 100644 index 2e236f190b66a..0000000000000 --- a/core/consensus/babe/src/tests.rs +++ /dev/null @@ -1,778 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! BABE testsuite - -// FIXME #2532: need to allow deprecated until refactor is done -// https://github.com/paritytech/substrate/issues/2532 -#![allow(deprecated)] -use super::*; -use authorship::claim_slot; - -use babe_primitives::{AuthorityPair, SlotNumber}; -use client::block_builder::BlockBuilder; -use consensus_common::NoNetwork as DummyOracle; -use consensus_common::import_queue::{ - BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport, -}; -use network::test::*; -use network::test::{Block as TestBlock, PeersClient}; -use network::config::BoxFinalityProofRequestBuilder; -use sr_primitives::{generic::DigestItem, traits::{Block as BlockT, DigestFor}}; -use network::config::ProtocolConfig; -use tokio::runtime::current_thread; -use client::BlockchainEvents; -use test_client; -use log::debug; -use std::{time::Duration, cell::RefCell}; - -type Item = DigestItem; - -type Error = client::error::Error; - -type TestClient = client::Client< - test_client::Backend, - test_client::Executor, - TestBlock, - test_client::runtime::RuntimeApi, ->; - -#[derive(Copy, Clone, PartialEq)] -enum Stage { - PreSeal, - PostSeal, -} - -type Mutator = Arc; - -#[derive(Clone)] -struct DummyFactory { - client: Arc, - epoch_changes: crate::SharedEpochChanges, - config: Config, - mutator: Mutator, -} - -struct DummyProposer { - factory: DummyFactory, - parent_hash: Hash, - parent_number: u64, - parent_slot: SlotNumber, -} - -impl Environment for DummyFactory { - type Proposer = DummyProposer; - type Error = Error; - - fn init(&mut self, parent_header: &::Header) - -> Result - { - - let parent_slot = crate::find_pre_digest::(parent_header) - .expect("parent header has a pre-digest") - .slot_number(); - - Ok(DummyProposer { - factory: self.clone(), - parent_hash: parent_header.hash(), - parent_number: *parent_header.number(), - parent_slot, - }) - } -} - -impl DummyProposer { - fn propose_with(&mut self, pre_digests: DigestFor) - -> future::Ready> - { - use codec::Encode; - let block_builder = self.factory.client.new_block_at( - &BlockId::Hash(self.parent_hash), - pre_digests, - ).unwrap(); - - let mut block = match block_builder.bake().map_err(|e| e.into()) { - Ok(b) => b, - Err(e) => return future::ready(Err(e)), - }; - - let this_slot = crate::find_pre_digest::(block.header()) - .expect("baked block has valid pre-digest") - .slot_number(); - - // figure out if we should add a consensus digest, since the test runtime - // doesn't. - let epoch_changes = self.factory.epoch_changes.lock(); - let epoch = epoch_changes.epoch_for_child_of( - descendent_query(&*self.factory.client), - &self.parent_hash, - self.parent_number, - this_slot, - |slot| self.factory.config.genesis_epoch(slot), - ) - .expect("client has data to find epoch") - .expect("can compute epoch for baked block") - .into_inner(); - - let first_in_epoch = self.parent_slot < epoch.start_slot; - if first_in_epoch { - // push a `Consensus` digest signalling next change. - // we just reuse the same randomness and authorities as the prior - // epoch. this will break when we add light client support, since - // that will re-check the randomness logic off-chain. - let digest_data = ConsensusLog::NextEpochData(NextEpochDescriptor { - authorities: epoch.authorities.clone(), - randomness: epoch.randomness.clone(), - }).encode(); - let digest = DigestItem::Consensus(BABE_ENGINE_ID, digest_data); - block.header.digest_mut().push(digest) - } - - // mutate the block header according to the mutator. - (self.factory.mutator)(&mut block.header, Stage::PreSeal); - - future::ready(Ok(block)) - } -} - -impl Proposer for DummyProposer { - type Error = Error; - type Create = future::Ready>; - - fn propose( - &mut self, - _: InherentData, - pre_digests: DigestFor, - _: Duration, - ) -> Self::Create { - self.propose_with(pre_digests) - } -} - -thread_local! { - static MUTATOR: RefCell = RefCell::new(Arc::new(|_, _|())); -} - -#[derive(Clone)] -struct PanickingBlockImport(B); - -impl> BlockImport for PanickingBlockImport { - type Error = B::Error; - - fn import_block( - &mut self, - block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - Ok(self.0.import_block(block, new_cache).expect("importing block failed")) - } - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - Ok(self.0.check_block(block).expect("checking block failed")) - } -} - -pub struct BabeTestNet { - peers: Vec, DummySpecialization>>, -} - -type TestHeader = ::Header; -type TestExtrinsic = ::Extrinsic; - -pub struct TestVerifier { - inner: BabeVerifier< - test_client::Backend, - test_client::Executor, - TestBlock, - test_client::runtime::RuntimeApi, - PeersFullClient, - >, - mutator: Mutator, -} - -impl Verifier for TestVerifier { - /// Verify the given data and return the BlockImportParams 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( - &mut self, - origin: BlockOrigin, - mut header: TestHeader, - justification: Option, - body: Option>, - ) -> Result<(BlockImportParams, Option)>>), String> { - // apply post-sealing mutations (i.e. stripping seal, if desired). - (self.mutator)(&mut header, Stage::PostSeal); - Ok(self.inner.verify(origin, header, justification, body).expect("verification failed!")) - } -} - -pub struct PeerData { - link: BabeLink, - inherent_data_providers: InherentDataProviders, - block_import: Mutex>>, -} - -impl TestNetFactory for BabeTestNet { - type Specialization = DummySpecialization; - type Verifier = TestVerifier; - type PeerData = Option; - - /// Create new test network with peers and given config. - fn from_config(_config: &ProtocolConfig) -> Self { - debug!(target: "babe", "Creating test network from config"); - BabeTestNet { - peers: Vec::new(), - } - } - - fn make_block_import(&self, client: PeersClient) - -> ( - BoxBlockImport, - Option>, - Option>, - Option>, - Option, - ) - { - let client = client.as_full().expect("only full clients are tested"); - let inherent_data_providers = InherentDataProviders::new(); - - let config = Config::get_or_compute(&*client).expect("config available"); - let (block_import, link) = crate::block_import( - config, - client.clone(), - client.clone(), - client.clone(), - ).expect("can initialize block-import"); - - let block_import = PanickingBlockImport(block_import); - - let data_block_import = Mutex::new(Some(Box::new(block_import.clone()) as BoxBlockImport<_>)); - ( - Box::new(block_import), - None, - None, - None, - Some(PeerData { link, inherent_data_providers, block_import: data_block_import }), - ) - } - - fn make_verifier( - &self, - client: PeersClient, - _cfg: &ProtocolConfig, - maybe_link: &Option, - ) - -> Self::Verifier - { - let client = client.as_full().expect("only full clients are used in test"); - trace!(target: "babe", "Creating a verifier"); - - // ensure block import and verifier are linked correctly. - let data = maybe_link.as_ref().expect("babe link always provided to verifier instantiation"); - - TestVerifier { - inner: BabeVerifier { - client: client.clone(), - api: client, - inherent_data_providers: data.inherent_data_providers.clone(), - config: data.link.config.clone(), - epoch_changes: data.link.epoch_changes.clone(), - time_source: data.link.time_source.clone(), - }, - mutator: MUTATOR.with(|m| m.borrow().clone()), - } - } - - fn peer(&mut self, i: usize) -> &mut Peer { - trace!(target: "babe", "Retreiving a peer"); - &mut self.peers[i] - } - - fn peers(&self) -> &Vec> { - trace!(target: "babe", "Retreiving peers"); - &self.peers - } - - fn mut_peers>)>( - &mut self, - closure: F, - ) { - closure(&mut self.peers); - } -} - -#[test] -#[should_panic] -fn rejects_empty_block() { - env_logger::try_init().unwrap(); - let mut net = BabeTestNet::new(3); - let block_builder = |builder: BlockBuilder<_, _>| { - builder.bake().unwrap() - }; - net.mut_peers(|peer| { - peer[0].generate_blocks(1, BlockOrigin::NetworkInitialSync, block_builder); - }) -} - -fn run_one_test( - mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static, -) { - let _ = env_logger::try_init(); - let mutator = Arc::new(mutator) as Mutator; - - MUTATOR.with(|m| *m.borrow_mut() = mutator.clone()); - let net = BabeTestNet::new(3); - - let peers = &[ - (0, "//Alice"), - (1, "//Bob"), - (2, "//Charlie"), - ]; - - let net = Arc::new(Mutex::new(net)); - let mut import_notifications = Vec::new(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut keystore_paths = Vec::new(); - - for (peer_id, seed) in peers { - let mut net = net.lock(); - let peer = net.peer(*peer_id); - let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); - let select_chain = peer.select_chain().expect("Full client has select_chain"); - - let keystore_path = tempfile::tempdir().expect("Creates keystore path"); - let keystore = keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); - keystore.write().insert_ephemeral_from_seed::(seed).expect("Generates authority key"); - keystore_paths.push(keystore_path); - - let mut got_own = false; - let mut got_other = false; - - let data = peer.data.as_ref().expect("babe link set up during initialization"); - - let environ = DummyFactory { - client: client.clone(), - config: data.link.config.clone(), - epoch_changes: data.link.epoch_changes.clone(), - mutator: mutator.clone(), - }; - - import_notifications.push( - // run each future until we get one of our own blocks with number higher than 5 - // that was produced locally. - client.import_notification_stream() - .take_while(move |n| future::ready(n.header.number() < &5 || { - if n.origin == BlockOrigin::Own { - got_own = true; - } else { - got_other = true; - } - - // continue until we have at least one block of our own - // and one of another peer. - !(got_own && got_other) - })) - .for_each(|_| future::ready(()) ) - ); - - - runtime.spawn(start_babe(BabeParams { - block_import: data.block_import.lock().take().expect("import set up during init"), - select_chain, - client, - env: environ, - sync_oracle: DummyOracle, - inherent_data_providers: data.inherent_data_providers.clone(), - force_authoring: false, - babe_link: data.link.clone(), - keystore, - }).expect("Starts babe")); - } - - runtime.spawn(futures01::future::poll_fn(move || { - net.lock().poll(); - Ok::<_, ()>(futures01::Async::NotReady::<()>) - })); - - runtime.block_on(future::join_all(import_notifications) - .map(|_| Ok::<(), ()>(())).compat()).unwrap(); -} - -#[test] -fn authoring_blocks() { - run_one_test(|_, _| ()) -} - -#[test] -#[should_panic] -fn rejects_missing_inherent_digest() { - run_one_test(|header: &mut TestHeader, stage| { - let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); - header.digest_mut().logs = v.into_iter() - .filter(|v| stage == Stage::PostSeal || v.as_babe_pre_digest().is_none()) - .collect() - }) -} - -#[test] -#[should_panic] -fn rejects_missing_seals() { - run_one_test(|header: &mut TestHeader, stage| { - let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); - header.digest_mut().logs = v.into_iter() - .filter(|v| stage == Stage::PreSeal || v.as_babe_seal().is_none()) - .collect() - }) -} - -#[test] -#[should_panic] -fn rejects_missing_consensus_digests() { - run_one_test(|header: &mut TestHeader, stage| { - let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); - header.digest_mut().logs = v.into_iter() - .filter(|v| stage == Stage::PostSeal || v.as_next_epoch_descriptor().is_none()) - .collect() - }); -} - -#[test] -fn wrong_consensus_engine_id_rejected() { - let _ = env_logger::try_init(); - let sig = AuthorityPair::generate().0.sign(b""); - let bad_seal: Item = DigestItem::Seal([0; 4], sig.to_vec()); - assert!(bad_seal.as_babe_pre_digest().is_none()); - assert!(bad_seal.as_babe_seal().is_none()) -} - -#[test] -fn malformed_pre_digest_rejected() { - let _ = env_logger::try_init(); - let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, [0; 64].to_vec()); - assert!(bad_seal.as_babe_pre_digest().is_none()); -} - -#[test] -fn sig_is_not_pre_digest() { - let _ = env_logger::try_init(); - let sig = AuthorityPair::generate().0.sign(b""); - let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig.to_vec()); - assert!(bad_seal.as_babe_pre_digest().is_none()); - assert!(bad_seal.as_babe_seal().is_some()) -} - -#[test] -fn can_author_block() { - let _ = env_logger::try_init(); - let keystore_path = tempfile::tempdir().expect("Creates keystore path"); - let keystore = keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); - let pair = keystore.write().insert_ephemeral_from_seed::("//Alice") - .expect("Generates authority pair"); - - let mut i = 0; - let epoch = Epoch { - start_slot: 0, - authorities: vec![(pair.public(), 1)], - randomness: [0; 32], - epoch_index: 1, - duration: 100, - }; - - let mut config = crate::BabeConfiguration { - slot_duration: 1000, - epoch_length: 100, - c: (3, 10), - genesis_authorities: Vec::new(), - randomness: [0; 32], - secondary_slots: true, - }; - - // with secondary slots enabled it should never be empty - match claim_slot(i, &epoch, &config, &keystore) { - None => i += 1, - Some(s) => debug!(target: "babe", "Authored block {:?}", s.0), - } - - // otherwise with only vrf-based primary slots we might need to try a couple - // of times. - config.secondary_slots = false; - loop { - match claim_slot(i, &epoch, &config, &keystore) { - None => i += 1, - Some(s) => { - debug!(target: "babe", "Authored block {:?}", s.0); - break; - } - } - } -} - -// Propose and import a new BABE block on top of the given parent. -fn propose_and_import_block( - parent: &TestHeader, - slot_number: Option, - proposer_factory: &mut DummyFactory, - block_import: &mut BoxBlockImport, -) -> H256 { - let mut proposer = proposer_factory.init(parent).unwrap(); - - let slot_number = slot_number.unwrap_or_else(|| { - let parent_pre_digest = find_pre_digest::(parent).unwrap(); - parent_pre_digest.slot_number() + 1 - }); - - let pre_digest = sr_primitives::generic::Digest { - logs: vec![ - Item::babe_pre_digest( - BabePreDigest::Secondary { - authority_index: 0, - slot_number, - }, - ), - ], - }; - - let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap(); - - let seal = { - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let pair = AuthorityPair::from_seed(&[1; 32]); - let pre_hash = block.header.hash(); - let signature = pair.sign(pre_hash.as_ref()); - Item::babe_seal(signature) - }; - - let post_hash = { - block.header.digest_mut().push(seal.clone()); - let h = block.header.hash(); - block.header.digest_mut().pop(); - h - }; - - let import_result = block_import.import_block( - BlockImportParams { - origin: BlockOrigin::Own, - header: block.header, - justification: None, - post_digests: vec![seal], - body: Some(block.extrinsics), - finalized: false, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }, - Default::default(), - ).unwrap(); - - match import_result { - ImportResult::Imported(_) => {}, - _ => panic!("expected block to be imported"), - } - - post_hash -} - -#[test] -fn importing_block_one_sets_genesis_epoch() { - let mut net = BabeTestNet::new(1); - - let peer = net.peer(0); - let data = peer.data.as_ref().expect("babe link set up during initialization"); - let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); - - let mut proposer_factory = DummyFactory { - client: client.clone(), - config: data.link.config.clone(), - epoch_changes: data.link.epoch_changes.clone(), - mutator: Arc::new(|_, _| ()), - }; - - let mut block_import = data.block_import.lock().take().expect("import set up during init"); - - let genesis_header = client.header(&BlockId::Number(0)).unwrap().unwrap(); - - let block_hash = propose_and_import_block( - &genesis_header, - Some(999), - &mut proposer_factory, - &mut block_import, - ); - - let genesis_epoch = data.link.config.genesis_epoch(999); - - let epoch_changes = data.link.epoch_changes.lock(); - let epoch_for_second_block = epoch_changes.epoch_for_child_of( - descendent_query(&*client), - &block_hash, - 1, - 1000, - |slot| data.link.config.genesis_epoch(slot), - ).unwrap().unwrap().into_inner(); - - assert_eq!(epoch_for_second_block, genesis_epoch); -} - -#[test] -fn importing_epoch_change_block_prunes_tree() { - use client::backend::Finalizer; - - let mut net = BabeTestNet::new(1); - - let peer = net.peer(0); - let data = peer.data.as_ref().expect("babe link set up during initialization"); - - let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); - let mut block_import = data.block_import.lock().take().expect("import set up during init"); - let epoch_changes = data.link.epoch_changes.clone(); - - let mut proposer_factory = DummyFactory { - client: client.clone(), - config: data.link.config.clone(), - epoch_changes: data.link.epoch_changes.clone(), - mutator: Arc::new(|_, _| ()), - }; - - // This is just boilerplate code for proposing and importing n valid BABE - // blocks that are built on top of the given parent. The proposer takes care - // of producing epoch change digests according to the epoch duration (which - // is set to 6 slots in the test runtime). - let mut propose_and_import_blocks = |parent_id, n| { - let mut hashes = Vec::new(); - let mut parent_header = client.header(&parent_id).unwrap().unwrap(); - - for _ in 0..n { - let block_hash = propose_and_import_block( - &parent_header, - None, - &mut proposer_factory, - &mut block_import, - ); - hashes.push(block_hash); - parent_header = client.header(&BlockId::Hash(block_hash)).unwrap().unwrap(); - } - - hashes - }; - - // This is the block tree that we're going to use in this test. Each node - // represents an epoch change block, the epoch duration is 6 slots. - // - // *---- F (#7) - // / *------ G (#19) - H (#25) - // / / - // A (#1) - B (#7) - C (#13) - D (#19) - E (#25) - // \ - // *------ I (#25) - - // Create and import the canon chain and keep track of fork blocks (A, C, D) - // from the diagram above. - let canon_hashes = propose_and_import_blocks(BlockId::Number(0), 30); - - // Create the forks - let fork_1 = propose_and_import_blocks(BlockId::Hash(canon_hashes[0]), 10); - let fork_2 = propose_and_import_blocks(BlockId::Hash(canon_hashes[12]), 15); - let fork_3 = propose_and_import_blocks(BlockId::Hash(canon_hashes[18]), 10); - - // We should be tracking a total of 9 epochs in the fork tree - assert_eq!( - epoch_changes.lock().tree().iter().count(), - 9, - ); - - // And only one root - assert_eq!( - epoch_changes.lock().tree().roots().count(), - 1, - ); - - // We finalize block #13 from the canon chain, so on the next epoch - // change the tree should be pruned, to not contain F (#7). - client.finalize_block(BlockId::Hash(canon_hashes[12]), None, false).unwrap(); - propose_and_import_blocks(BlockId::Hash(client.info().chain.best_hash), 7); - - // at this point no hashes from the first fork must exist on the tree - assert!( - !epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_1.contains(h)), - ); - - // but the epoch changes from the other forks must still exist - assert!( - epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_2.contains(h)) - ); - - assert!( - epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_3.contains(h)), - ); - - // finalizing block #25 from the canon chain should prune out the second fork - client.finalize_block(BlockId::Hash(canon_hashes[24]), None, false).unwrap(); - propose_and_import_blocks(BlockId::Hash(client.info().chain.best_hash), 8); - - // at this point no hashes from the second fork must exist on the tree - assert!( - !epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_2.contains(h)), - ); - - // while epoch changes from the last fork should still exist - assert!( - epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_3.contains(h)), - ); -} - -#[test] -#[should_panic] -fn verify_slots_are_strictly_increasing() { - let mut net = BabeTestNet::new(1); - - let peer = net.peer(0); - let data = peer.data.as_ref().expect("babe link set up during initialization"); - - let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); - let mut block_import = data.block_import.lock().take().expect("import set up during init"); - - let mut proposer_factory = DummyFactory { - client: client.clone(), - config: data.link.config.clone(), - epoch_changes: data.link.epoch_changes.clone(), - mutator: Arc::new(|_, _| ()), - }; - - let genesis_header = client.header(&BlockId::Number(0)).unwrap().unwrap(); - - // we should have no issue importing this block - let b1 = propose_and_import_block( - &genesis_header, - Some(999), - &mut proposer_factory, - &mut block_import, - ); - - let b1 = client.header(&BlockId::Hash(b1)).unwrap().unwrap(); - - // we should fail to import this block since the slot number didn't increase. - // we will panic due to the `PanickingBlockImport` defined above. - propose_and_import_block( - &b1, - Some(999), - &mut proposer_factory, - &mut block_import, - ); -} diff --git a/core/consensus/common/Cargo.toml b/core/consensus/common/Cargo.toml deleted file mode 100644 index 73a74c7ced30d..0000000000000 --- a/core/consensus/common/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "substrate-consensus-common" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Common utilities for substrate consensus" -edition = "2018" - -[dependencies] -derive_more = "0.15.0" -libp2p = { version = "0.12.0", default-features = false } -log = "0.4.8" -primitives = { package = "substrate-primitives", path= "../../primitives" } -inherents = { package = "substrate-inherents", path = "../../inherents" } -futures-preview = "0.3.0-alpha.19" -futures-timer = "0.4.0" -rstd = { package = "sr-std", path = "../../sr-std" } -runtime_version = { package = "sr-version", path = "../../sr-version" } -sr-primitives = { path = "../../sr-primitives" } -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } -parking_lot = "0.9.0" - -[dev-dependencies] -test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } - -[features] -default = [] diff --git a/core/consensus/common/src/block_import.rs b/core/consensus/common/src/block_import.rs deleted file mode 100644 index 4342ee38df10a..0000000000000 --- a/core/consensus/common/src/block_import.rs +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Block import helpers. - -use sr_primitives::traits::{Block as BlockT, DigestItemFor, Header as HeaderT, NumberFor}; -use sr_primitives::Justification; -use std::borrow::Cow; -use std::collections::HashMap; -use std::sync::Arc; - -use crate::import_queue::{Verifier, CacheKeyId}; - -/// Block import result. -#[derive(Debug, PartialEq, Eq)] -pub enum ImportResult { - /// Block imported. - Imported(ImportedAux), - /// Already in the blockchain. - AlreadyInChain, - /// Block or parent is known to be bad. - KnownBad, - /// Block parent is not in the chain. - UnknownParent, -} - -/// Auxiliary data associated with an imported block result. -#[derive(Debug, Default, 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, - /// Request a finality proof for the given block. - pub needs_finality_proof: bool, - /// Whether the block that was imported is the new best block. - pub is_new_best: bool, -} - -impl ImportResult { - /// Returns default value for `ImportResult::Imported` with - /// `clear_justification_requests`, `needs_justification`, - /// `bad_justification` and `needs_finality_proof` set to false. - pub fn imported(is_new_best: bool) -> ImportResult { - let mut aux = ImportedAux::default(); - aux.is_new_best = is_new_best; - - ImportResult::Imported(aux) - } -} - -/// Block data origin. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum BlockOrigin { - /// Genesis block built into the client. - Genesis, - /// Block is part of the initial sync with the network. - NetworkInitialSync, - /// Block was broadcasted on the network. - NetworkBroadcast, - /// Block that was received from the network and validated in the consensus process. - ConsensusBroadcast, - /// Block that was collated by this node. - Own, - /// Block was imported from a file. - 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 check validity of a Block. -pub struct BlockCheckParams { - /// Hash of the block that we verify. - pub hash: Block::Hash, - /// Block number of the block that we verify. - pub number: NumberFor, - /// Parent hash of the block that we verify. - pub parent_hash: Block::Hash, -} - -/// Data required to import a Block. -pub struct BlockImportParams { - /// Origin of the Block - pub origin: BlockOrigin, - /// The header, without consensus post-digests applied. This should be in the same - /// state as it comes out of the runtime. - /// - /// Consensus engines which alter the header (by adding post-runtime digests) - /// should strip those off in the initial verification process and pass them - /// via the `post_digests` field. During block authorship, they should - /// not be pushed to the header directly. - /// - /// The reason for this distinction is so the header can be directly - /// re-executed in a runtime that checks digest equivalence -- the - /// post-runtime digests are pushed back on after. - pub header: Block::Header, - /// Justification provided for this block from the outside. - pub justification: Option, - /// Digest items that have been added after the runtime for external - /// work, like a consensus signature. - pub post_digests: Vec>, - /// Block's body - pub body: Option>, - /// Is this block finalized already? - /// `true` implies instant finality. - pub finalized: bool, - /// Auxiliary consensus data produced by the block. - /// 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. This should only be set by a - /// synchronous import, otherwise it may race against other imports. - pub fork_choice: ForkChoiceStrategy, -} - -impl BlockImportParams { - /// Deconstruct the justified header into parts. - pub fn into_inner(self) - -> ( - BlockOrigin, - ::Header, - Option, - Vec>, - Option::Extrinsic>>, - bool, - Vec<(Vec, Option>)>, - ) { - ( - self.origin, - self.header, - self.justification, - self.post_digests, - self.body, - self.finalized, - self.auxiliary, - ) - } - - /// Get a handle to full header (with post-digests applied). - pub fn post_header(&self) -> Cow { - if self.post_digests.is_empty() { - Cow::Borrowed(&self.header) - } else { - Cow::Owned({ - let mut hdr = self.header.clone(); - for digest_item in &self.post_digests { - hdr.digest_mut().push(digest_item.clone()); - } - - hdr - }) - } - } -} - -/// Block import trait. -pub trait BlockImport { - type Error: ::std::error::Error + Send + 'static; - - /// Check block preconditions. - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result; - - /// Import a block. - /// - /// Cached data can be accessed through the blockchain cache. - fn import_block( - &mut self, - block: BlockImportParams, - cache: HashMap>, - ) -> Result; -} - -impl BlockImport for crate::import_queue::BoxBlockImport { - type Error = crate::error::Error; - - /// Check block preconditions. - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - (**self).check_block(block) - } - - /// Import a block. - /// - /// Cached data can be accessed through the blockchain cache. - fn import_block( - &mut self, - block: BlockImportParams, - cache: HashMap>, - ) -> Result { - (**self).import_block(block, cache) - } -} - -impl BlockImport for Arc -where for<'r> &'r T: BlockImport -{ - type Error = E; - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - (&**self).check_block(block) - } - - fn import_block( - &mut self, - block: BlockImportParams, - cache: HashMap>, - ) -> Result { - (&**self).import_block(block, cache) - } -} - -/// Justification import trait -pub trait JustificationImport { - type Error: ::std::error::Error + Send + 'static; - - /// Called by the import queue when it is started. Returns a list of justifications to request - /// from the network. - fn on_start(&mut self) -> Vec<(B::Hash, NumberFor)> { Vec::new() } - - /// Import a Block justification and finalize the given block. - fn import_justification( - &mut self, - hash: B::Hash, - number: NumberFor, - justification: Justification, - ) -> Result<(), Self::Error>; -} - -/// Finality proof import trait. -pub trait FinalityProofImport { - type Error: std::error::Error + Send + 'static; - - /// Called by the import queue when it is started. Returns a list of finality proofs to request - /// from the network. - fn on_start(&mut self) -> Vec<(B::Hash, NumberFor)> { Vec::new() } - - /// Import a Block justification and finalize the given block. Returns finalized block or error. - fn import_finality_proof( - &mut self, - hash: B::Hash, - number: NumberFor, - finality_proof: Vec, - verifier: &mut dyn Verifier, - ) -> Result<(B::Hash, NumberFor), Self::Error>; -} diff --git a/core/consensus/common/src/error.rs b/core/consensus/common/src/error.rs deleted file mode 100644 index cb57bb915eb2d..0000000000000 --- a/core/consensus/common/src/error.rs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Error types in Consensus -use runtime_version::RuntimeVersion; -use primitives::ed25519::{Public, Signature}; -use std::error; - -/// Result type alias. -pub type Result = std::result::Result; - -/// Error type. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Missing state at block with given descriptor. - #[display(fmt="State unavailable at block {}", _0)] - StateUnavailable(String), - /// I/O terminated unexpectedly - #[display(fmt="I/O terminated unexpectedly.")] - IoTerminated, - /// Unable to schedule wakeup. - #[display(fmt="Timer error: {}", _0)] - FaultyTimer(std::io::Error), - /// Error while working with inherent data. - #[display(fmt="InherentData error: {}", _0)] - InherentData(String), - /// Unable to propose a block. - #[display(fmt="Unable to create block proposal.")] - CannotPropose, - /// Error checking signature - #[display(fmt="Message signature {:?} by {:?} is invalid.", _0, _1)] - InvalidSignature(Signature, Public), - /// Invalid authorities set received from the runtime. - #[display(fmt="Current state of blockchain has invalid authorities set")] - InvalidAuthoritiesSet, - /// Account is not an authority. - #[display(fmt="Message sender {:?} is not a valid authority.", _0)] - InvalidAuthority(Public), - /// Authoring interface does not match the runtime. - #[display(fmt="Authoring for current \ - runtime is not supported. Native ({}) cannot author for on-chain ({}).", native, on_chain)] - IncompatibleAuthoringRuntime { native: RuntimeVersion, on_chain: RuntimeVersion }, - /// Authoring interface does not match the runtime. - #[display(fmt="Authoring for current runtime is not supported since it has no version.")] - RuntimeVersionMissing, - /// Authoring interface does not match the runtime. - #[display(fmt="Authoring in current build is not supported since it has no runtime.")] - NativeRuntimeMissing, - /// Justification requirements not met. - #[display(fmt="Invalid justification.")] - InvalidJustification, - /// Some other error. - #[display(fmt="Other error: {}", _0)] - Other(Box), - /// Error from the client while importing - #[display(fmt="Import failed: {}", _0)] - ClientImport(String), - /// Error from the client while importing - #[display(fmt="Chain lookup failed: {}", _0)] - ChainLookup(String), -} - -impl error::Error for Error { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match self { - Error::FaultyTimer(ref err) => Some(err), - Error::Other(ref err) => Some(&**err), - _ => None, - } - } -} diff --git a/core/consensus/common/src/lib.rs b/core/consensus/common/src/lib.rs deleted file mode 100644 index 154ea7bb52f7c..0000000000000 --- a/core/consensus/common/src/lib.rs +++ /dev/null @@ -1,135 +0,0 @@ -// 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 -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate Consensus Common is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate Consensus Common. If not, see . - -//! 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)] - -// our error-chain could potentially blow up otherwise -#![recursion_limit="128"] - -#[macro_use] extern crate log; - -use std::sync::Arc; -use std::time::Duration; - -use sr_primitives::traits::{Block as BlockT, DigestFor}; -use futures::prelude::*; -pub use inherents::InherentData; - -pub mod block_validation; -pub mod offline_tracker; -pub mod error; -pub mod block_import; -mod select_chain; -pub mod import_queue; -pub mod evaluation; - -// block size limit. -const MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024 + 512; - -pub use self::error::Error; -pub use block_import::{ - BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams, ImportResult, - JustificationImport, FinalityProofImport, -}; -pub use select_chain::SelectChain; - -/// Block status. -#[derive(Debug, PartialEq, Eq)] -pub enum BlockStatus { - /// Added to the import queue. - Queued, - /// Already in the blockchain and the state is available. - InChainWithState, - /// In the blockchain, but the state is not available. - InChainPruned, - /// Block or parent is known to be bad. - KnownBad, - /// Not in the queue or the blockchain. - Unknown, -} - -/// Environment producer for a Consensus instance. Creates proposer instance and communication streams. -pub trait Environment { - /// The proposer type this creates. - 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. - fn init(&mut self, parent_header: &B::Header) - -> Result; -} - -/// Logic for a proposer. -/// -/// This will encapsulate creation and evaluation of proposals at a specific -/// block. -/// -/// Proposers are generic over bits of "consensus data" which are engine-specific. -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: Future>; - /// Create a proposal. - fn propose( - &mut self, - inherent_data: InherentData, - inherent_digests: DigestFor, - max_duration: Duration, - ) -> Self::Create; -} - -/// An oracle for when major synchronization work is being undertaken. -/// -/// Generally, consensus authoring work isn't undertaken while well behind -/// the head of the chain. -pub trait SyncOracle { - /// Whether the synchronization service is undergoing major sync. - /// Returns true if so. - fn is_major_syncing(&mut self) -> bool; - /// Whether the synchronization service is offline. - /// Returns true if so. - fn is_offline(&mut self) -> bool; -} - -/// A synchronization oracle for when there is no network. -#[derive(Clone, Copy, Debug)] -pub struct NoNetwork; - -impl SyncOracle for NoNetwork { - fn is_major_syncing(&mut self) -> bool { false } - fn is_offline(&mut self) -> bool { false } -} - -impl SyncOracle for Arc -where T: ?Sized, for<'r> &'r T: SyncOracle -{ - fn is_major_syncing(&mut self) -> bool { - <&T>::is_major_syncing(&mut &**self) - } - fn is_offline(&mut self) -> bool { - <&T>::is_offline(&mut &**self) - } -} diff --git a/core/consensus/pow/Cargo.toml b/core/consensus/pow/Cargo.toml deleted file mode 100644 index 86efcbb95da2b..0000000000000 --- a/core/consensus/pow/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "substrate-consensus-pow" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "PoW consensus algorithm for substrate" -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../primitives" } -sr-primitives = { path = "../../sr-primitives" } -client = { package = "substrate-client", path = "../../client" } -srml-timestamp = { path = "../../../srml/timestamp" } -inherents = { package = "substrate-inherents", path = "../../inherents" } -pow-primitives = { package = "substrate-consensus-pow-primitives", path = "primitives" } -consensus-common = { package = "substrate-consensus-common", path = "../common" } -log = "0.4.8" -futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } -derive_more = "0.15.0" diff --git a/core/consensus/pow/primitives/Cargo.toml b/core/consensus/pow/primitives/Cargo.toml deleted file mode 100644 index 021e4c80a754c..0000000000000 --- a/core/consensus/pow/primitives/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "substrate-consensus-pow-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Primitives for Aura consensus" -edition = "2018" - -[dependencies] -substrate-client = { path = "../../../client", default-features = false } -rstd = { package = "sr-std", path = "../../../sr-std", default-features = false } -sr-primitives = { path = "../../../sr-primitives", default-features = false } -primitives = { package = "substrate-primitives", path = "../../../primitives", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } - -[features] -default = ["std"] -std = [ - "rstd/std", - "substrate-client/std", - "sr-primitives/std", - "primitives/std", - "codec/std", -] diff --git a/core/consensus/pow/primitives/src/lib.rs b/core/consensus/pow/primitives/src/lib.rs deleted file mode 100644 index 2079b1cbe7e88..0000000000000 --- a/core/consensus/pow/primitives/src/lib.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Primitives for Substrate Proof-of-Work (PoW) consensus. - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::vec::Vec; -use sr_primitives::ConsensusEngineId; -use codec::Decode; -use substrate_client::decl_runtime_apis; - -/// The `ConsensusEngineId` of PoW. -pub const POW_ENGINE_ID: ConsensusEngineId = [b'p', b'o', b'w', b'_']; - -/// Type of seal. -pub type Seal = Vec; - -/// Define methods that total difficulty should implement. -pub trait TotalDifficulty { - fn increment(&mut self, other: Self); -} - -impl TotalDifficulty for primitives::U256 { - fn increment(&mut self, other: Self) { - let ret = self.saturating_add(other); - *self = ret; - } -} - -impl TotalDifficulty for u128 { - fn increment(&mut self, other: Self) { - let ret = self.saturating_add(other); - *self = ret; - } -} - -decl_runtime_apis! { - /// API necessary for timestamp-based difficulty adjustment algorithms. - pub trait TimestampApi { - /// Return the timestamp in the current block. - fn timestamp() -> Moment; - } - - /// API for those chains that put their difficulty adjustment algorithm directly - /// onto runtime. Note that while putting difficulty adjustment algorithm to - /// runtime is safe, putting the PoW algorithm on runtime is not. - pub trait DifficultyApi { - /// Return the target difficulty of the next block. - fn difficulty() -> Difficulty; - } -} diff --git a/core/consensus/pow/src/lib.rs b/core/consensus/pow/src/lib.rs deleted file mode 100644 index 040eb01d9c5f0..0000000000000 --- a/core/consensus/pow/src/lib.rs +++ /dev/null @@ -1,539 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Proof of work consensus for Substrate. -//! -//! To use this engine, you can need to have a struct that implements -//! `PowAlgorithm`. After that, pass an instance of the struct, along -//! with other necessary client references to `import_queue` to setup -//! the queue. Use the `start_mine` function for basic CPU mining. -//! -//! The auxiliary storage for PoW engine only stores the total difficulty. -//! For other storage requirements for particular PoW algorithm (such as -//! the actual difficulty for each particular blocks), you can take a client -//! reference in your `PowAlgorithm` implementation, and use a separate prefix -//! for the auxiliary storage. It is also possible to just use the runtime -//! as the storage, but it is not recommended as it won't work well with light -//! clients. - -use std::sync::Arc; -use std::thread; -use std::collections::HashMap; -use client::{ - BlockOf, blockchain::{HeaderBackend, ProvideCache}, - block_builder::api::BlockBuilder as BlockBuilderApi, backend::AuxStore, - well_known_cache_keys::Id as CacheKeyId, -}; -use sr_primitives::{Justification, RuntimeString}; -use sr_primitives::generic::{BlockId, Digest, DigestItem}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi}; -use srml_timestamp::{TimestampInherentData, InherentError as TIError}; -use pow_primitives::{Seal, TotalDifficulty, POW_ENGINE_ID}; -use primitives::H256; -use inherents::{InherentDataProviders, InherentData}; -use consensus_common::{ - BlockImportParams, BlockOrigin, ForkChoiceStrategy, SyncOracle, Environment, Proposer, - SelectChain, Error as ConsensusError -}; -use consensus_common::import_queue::{BoxBlockImport, BasicQueue, Verifier}; -use codec::{Encode, Decode}; -use log::*; - -#[derive(derive_more::Display, Debug)] -pub enum Error { - #[display(fmt = "Header uses the wrong engine {:?}", _0)] - WrongEngine([u8; 4]), - #[display(fmt = "Header {:?} is unsealed", _0)] - HeaderUnsealed(B::Hash), - #[display(fmt = "PoW validation error: invalid seal")] - InvalidSeal, - #[display(fmt = "Rejecting block too far in future")] - TooFarInFuture, - #[display(fmt = "Fetching best header failed using select chain: {:?}", _0)] - BestHeaderSelectChain(ConsensusError), - #[display(fmt = "Fetching best header failed: {:?}", _0)] - BestHeader(client::error::Error), - #[display(fmt = "Best header does not exist")] - NoBestHeader, - #[display(fmt = "Block proposing error: {:?}", _0)] - BlockProposingError(String), - #[display(fmt = "Fetch best hash failed via select chain: {:?}", _0)] - BestHashSelectChain(ConsensusError), - #[display(fmt = "Error with block built on {:?}: {:?}", _0, _1)] - BlockBuiltError(B::Hash, ConsensusError), - #[display(fmt = "Creating inherents failed: {}", _0)] - CreateInherents(RuntimeString), - #[display(fmt = "Checking inherents failed: {}", _0)] - CheckInherents(String), - Client(client::error::Error), - Codec(codec::Error), - Environment(String), - Runtime(RuntimeString) -} - -impl std::convert::From> for String { - fn from(error: Error) -> String { - error.to_string() - } -} - -/// Auxiliary storage prefix for PoW engine. -pub const POW_AUX_PREFIX: [u8; 4] = *b"PoW:"; - -/// Get the auxiliary storage key used by engine to store total difficulty. -fn aux_key(hash: &H256) -> Vec { - POW_AUX_PREFIX.iter().chain(&hash[..]) - .cloned().collect::>() -} - -/// Auxiliary storage data for PoW. -#[derive(Encode, Decode, Clone, Debug, Default)] -pub struct PowAux { - /// Difficulty of the current block. - pub difficulty: Difficulty, - /// Total difficulty up to current block. - pub total_difficulty: Difficulty, -} - -impl PowAux where - Difficulty: Decode + Default, -{ - /// Read the auxiliary from client. - pub fn read(client: &C, hash: &H256) -> Result> { - let key = aux_key(hash); - - match client.get_aux(&key).map_err(Error::Client)? { - Some(bytes) => Self::decode(&mut &bytes[..]) - .map_err(Error::Codec), - None => Ok(Self::default()), - } - } -} - -/// Algorithm used for proof of work. -pub trait PowAlgorithm { - /// Difficulty for the algorithm. - type Difficulty: TotalDifficulty + Default + Encode + Decode + Ord + Clone + Copy; - - /// Get the next block's difficulty. - fn difficulty(&self, parent: &BlockId) -> Result>; - /// Verify proof of work against the given difficulty. - fn verify( - &self, - parent: &BlockId, - pre_hash: &H256, - seal: &Seal, - difficulty: Self::Difficulty, - ) -> Result>; - /// Mine a seal that satisfies the given difficulty. - fn mine( - &self, - parent: &BlockId, - pre_hash: &H256, - difficulty: Self::Difficulty, - round: u32, - ) -> Result, Error>; -} - -/// A verifier for PoW blocks. -pub struct PowVerifier, C, S, Algorithm> { - client: Arc, - algorithm: Algorithm, - inherent_data_providers: inherents::InherentDataProviders, - select_chain: Option, - check_inherents_after: <::Header as HeaderT>::Number, -} - -impl, C, S, Algorithm> PowVerifier { - pub fn new( - client: Arc, - algorithm: Algorithm, - check_inherents_after: <::Header as HeaderT>::Number, - select_chain: Option, - inherent_data_providers: inherents::InherentDataProviders, - ) -> Self { - Self { client, algorithm, inherent_data_providers, select_chain, check_inherents_after } - } - - fn check_header( - &self, - mut header: B::Header, - parent_block_id: BlockId, - ) -> Result<(B::Header, Algorithm::Difficulty, DigestItem), Error> where - Algorithm: PowAlgorithm, - { - let hash = header.hash(); - - let (seal, inner_seal) = match header.digest_mut().pop() { - Some(DigestItem::Seal(id, seal)) => { - if id == POW_ENGINE_ID { - (DigestItem::Seal(id, seal.clone()), seal) - } else { - return Err(Error::WrongEngine(id)) - } - }, - _ => return Err(Error::HeaderUnsealed(hash)), - }; - - let pre_hash = header.hash(); - let difficulty = self.algorithm.difficulty(&parent_block_id)?; - - if !self.algorithm.verify( - &parent_block_id, - &pre_hash, - &inner_seal, - difficulty, - )? { - return Err(Error::InvalidSeal); - } - - Ok((header, difficulty, seal)) - } - - fn check_inherents( - &self, - block: B, - block_id: BlockId, - inherent_data: InherentData, - timestamp_now: u64, - ) -> Result<(), Error> where - C: ProvideRuntimeApi, C::Api: BlockBuilderApi - { - const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; - - if *block.header().number() < self.check_inherents_after { - return Ok(()) - } - - let inherent_res = self.client.runtime_api().check_inherents( - &block_id, - block, - inherent_data, - ).map_err(Error::Client)?; - - if !inherent_res.ok() { - inherent_res - .into_errors() - .try_for_each(|(i, e)| match TIError::try_from(&i, &e) { - Some(TIError::ValidAtTimestamp(timestamp)) => { - if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { - return Err(Error::TooFarInFuture); - } - - Ok(()) - }, - Some(TIError::Other(e)) => Err(Error::Runtime(e)), - None => Err(Error::CheckInherents( - self.inherent_data_providers.error_to_string(&i, &e) - )), - }) - } else { - Ok(()) - } - } -} - -impl, C, S, Algorithm> Verifier for PowVerifier where - C: ProvideRuntimeApi + Send + Sync + HeaderBackend + AuxStore + ProvideCache + BlockOf, - C::Api: BlockBuilderApi, - S: SelectChain, - Algorithm: PowAlgorithm + Send + Sync, -{ - fn verify( - &mut self, - origin: BlockOrigin, - header: B::Header, - justification: Option, - mut body: Option>, - ) -> Result<(BlockImportParams, Option)>>), String> { - let inherent_data = self.inherent_data_providers - .create_inherent_data().map_err(String::from)?; - let timestamp_now = inherent_data.timestamp_inherent_data().map_err(String::from)?; - - let best_hash = match self.select_chain.as_ref() { - Some(select_chain) => select_chain.best_chain() - .map_err(|e| format!("Fetch best chain failed via select chain: {:?}", e))? - .hash(), - None => self.client.info().best_hash, - }; - let hash = header.hash(); - let parent_hash = *header.parent_hash(); - let best_aux = PowAux::read::<_, B>(self.client.as_ref(), &best_hash)?; - let mut aux = PowAux::read::<_, B>(self.client.as_ref(), &parent_hash)?; - - let (checked_header, difficulty, seal) = self.check_header( - header, - BlockId::Hash(parent_hash), - )?; - aux.difficulty = difficulty; - aux.total_difficulty.increment(difficulty); - - if let Some(inner_body) = body.take() { - let block = B::new(checked_header.clone(), inner_body); - - self.check_inherents( - block.clone(), - BlockId::Hash(parent_hash), - inherent_data, - timestamp_now - )?; - - let (_, inner_body) = block.deconstruct(); - body = Some(inner_body); - } - let key = aux_key(&hash); - let import_block = BlockImportParams { - origin, - header: checked_header, - post_digests: vec![seal], - body, - finalized: false, - justification, - auxiliary: vec![(key, Some(aux.encode()))], - fork_choice: ForkChoiceStrategy::Custom(aux.total_difficulty > best_aux.total_difficulty), - }; - - Ok((import_block, None)) - } -} - -/// Register the PoW inherent data provider, if not registered already. -pub fn register_pow_inherent_data_provider( - inherent_data_providers: &InherentDataProviders, -) -> Result<(), consensus_common::Error> { - if !inherent_data_providers.has_provider(&srml_timestamp::INHERENT_IDENTIFIER) { - inherent_data_providers - .register_provider(srml_timestamp::InherentDataProvider) - .map_err(Into::into) - .map_err(consensus_common::Error::InherentData) - } else { - Ok(()) - } -} - -/// The PoW import queue type. -pub type PowImportQueue = BasicQueue; - -/// Import queue for PoW engine. -pub fn import_queue( - block_import: BoxBlockImport, - client: Arc, - algorithm: Algorithm, - check_inherents_after: <::Header as HeaderT>::Number, - select_chain: Option, - inherent_data_providers: InherentDataProviders, -) -> Result, consensus_common::Error> where - B: BlockT, - C: ProvideRuntimeApi + HeaderBackend + BlockOf + ProvideCache + AuxStore, - C: Send + Sync + AuxStore + 'static, - C::Api: BlockBuilderApi, - Algorithm: PowAlgorithm + Send + Sync + 'static, - S: SelectChain + 'static, -{ - register_pow_inherent_data_provider(&inherent_data_providers)?; - - let verifier = PowVerifier::new( - client.clone(), - algorithm, - check_inherents_after, - select_chain, - inherent_data_providers, - ); - - Ok(BasicQueue::new( - verifier, - block_import, - None, - None - )) -} - -/// Start the background mining thread for PoW. Note that because PoW mining -/// is CPU-intensive, it is not possible to use an async future to define this. -/// However, it's not recommended to use background threads in the rest of the -/// codebase. -/// -/// `preruntime` is a parameter that allows a custom additional pre-runtime -/// digest to be inserted for blocks being built. This can encode authorship -/// information, or just be a graffiti. `round` is for number of rounds the -/// CPU miner runs each time. This parameter should be tweaked so that each -/// mining round is within sub-second time. -pub fn start_mine, C, Algorithm, E, SO, S>( - mut block_import: BoxBlockImport, - client: Arc, - algorithm: Algorithm, - mut env: E, - preruntime: Option>, - round: u32, - mut sync_oracle: SO, - build_time: std::time::Duration, - select_chain: Option, - inherent_data_providers: inherents::InherentDataProviders, -) where - C: HeaderBackend + AuxStore + 'static, - Algorithm: PowAlgorithm + Send + Sync + 'static, - E: Environment + Send + Sync + 'static, - E::Error: std::fmt::Debug, - SO: SyncOracle + Send + Sync + 'static, - S: SelectChain + 'static, -{ - if let Err(_) = register_pow_inherent_data_provider(&inherent_data_providers) { - warn!("Registering inherent data provider for timestamp failed"); - } - - thread::spawn(move || { - loop { - match mine_loop( - &mut block_import, - client.as_ref(), - &algorithm, - &mut env, - preruntime.as_ref(), - round, - &mut sync_oracle, - build_time.clone(), - select_chain.as_ref(), - &inherent_data_providers - ) { - Ok(()) => (), - Err(e) => error!( - "Mining block failed with {:?}. Sleep for 1 second before restarting...", - e - ), - } - std::thread::sleep(std::time::Duration::new(1, 0)); - } - }); -} - -fn mine_loop, C, Algorithm, E, SO, S>( - block_import: &mut BoxBlockImport, - client: &C, - algorithm: &Algorithm, - env: &mut E, - preruntime: Option<&Vec>, - round: u32, - sync_oracle: &mut SO, - build_time: std::time::Duration, - select_chain: Option<&S>, - inherent_data_providers: &inherents::InherentDataProviders, -) -> Result<(), Error> where - C: HeaderBackend + AuxStore, - Algorithm: PowAlgorithm, - E: Environment, - E::Error: std::fmt::Debug, - SO: SyncOracle, - S: SelectChain, -{ - 'outer: loop { - if sync_oracle.is_major_syncing() { - debug!(target: "pow", "Skipping proposal due to sync."); - std::thread::sleep(std::time::Duration::new(1, 0)); - continue 'outer - } - - let (best_hash, best_header) = match select_chain { - Some(select_chain) => { - let header = select_chain.best_chain() - .map_err(Error::BestHeaderSelectChain)?; - let hash = header.hash(); - (hash, header) - }, - None => { - let hash = client.info().best_hash; - let header = client.header(BlockId::Hash(hash)) - .map_err(Error::BestHeader)? - .ok_or(Error::NoBestHeader)?; - (hash, header) - }, - }; - let mut aux = PowAux::read(client, &best_hash)?; - let mut proposer = env.init(&best_header) - .map_err(|e| Error::Environment(format!("{:?}", e)))?; - - let inherent_data = inherent_data_providers - .create_inherent_data().map_err(Error::CreateInherents)?; - let mut inherent_digest = Digest::default(); - if let Some(preruntime) = &preruntime { - inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, preruntime.to_vec())); - } - let block = futures::executor::block_on(proposer.propose( - inherent_data, - inherent_digest, - build_time.clone(), - )).map_err(|e| Error::BlockProposingError(format!("{:?}", e)))?; - - let (header, body) = block.deconstruct(); - let (difficulty, seal) = { - let difficulty = algorithm.difficulty( - &BlockId::Hash(best_hash), - )?; - - loop { - let seal = algorithm.mine( - &BlockId::Hash(best_hash), - &header.hash(), - difficulty, - round, - )?; - - if let Some(seal) = seal { - break (difficulty, seal) - } - - if best_hash != client.info().best_hash { - continue 'outer - } - } - }; - - aux.difficulty = difficulty; - aux.total_difficulty.increment(difficulty); - let hash = { - let mut header = header.clone(); - header.digest_mut().push(DigestItem::Seal(POW_ENGINE_ID, seal.clone())); - header.hash() - }; - - let key = aux_key(&hash); - let best_hash = match select_chain { - Some(select_chain) => select_chain.best_chain() - .map_err(Error::BestHashSelectChain)? - .hash(), - None => client.info().best_hash, - }; - let best_aux = PowAux::::read(client, &best_hash)?; - - // if the best block has changed in the meantime drop our proposal - if best_aux.total_difficulty > aux.total_difficulty { - continue 'outer - } - - let import_block = BlockImportParams { - origin: BlockOrigin::Own, - header, - justification: None, - post_digests: vec![DigestItem::Seal(POW_ENGINE_ID, seal)], - body: Some(body), - finalized: false, - auxiliary: vec![(key, Some(aux.encode()))], - fork_choice: ForkChoiceStrategy::Custom(true), - }; - - block_import.import_block(import_block, HashMap::default()) - .map_err(|e| Error::BlockBuiltError(best_hash, e))?; - } -} diff --git a/core/consensus/rhd/Cargo.toml b/core/consensus/rhd/Cargo.toml deleted file mode 100644 index 48d0840b5592d..0000000000000 --- a/core/consensus/rhd/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "substrate-consensus-rhd" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Rhododendron Round-Based consensus-algorithm for substrate" -edition = "2018" - -[dependencies] -derive_more = "0.15.0" -futures = "0.1.29" -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../primitives" } -consensus = { package = "substrate-consensus-common", path = "../common" } -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" } -sr-primitives = { path = "../../sr-primitives" } -runtime_version = { package = "sr-version", path = "../../sr-version" } -runtime_io = { package = "sr-io", path = "../../sr-io" } -tokio = "0.1.22" -parking_lot = "0.9.0" -log = "0.4.8" -rhododendron = { version = "0.7.0", features = ["codec"] } -exit-future = "0.1.4" - -[dev-dependencies] -keyring = { package = "substrate-keyring", path = "../../keyring" } - -[features] -default = ["std"] -std = [ - "primitives/std", - "runtime_support/std", - "sr-primitives/std", - "runtime_version/std", -] diff --git a/core/consensus/rhd/src/error.rs b/core/consensus/rhd/src/error.rs deleted file mode 100644 index 601cf1c963a58..0000000000000 --- a/core/consensus/rhd/src/error.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Error types in the rhododendron Consensus service. -use consensus::error::{Error as CommonError}; -use primitives::AuthorityId; -use client; - -/// A result alias. -pub type Result = std::result::Result; - -/// A RHD error type. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Client error. - Client(client::error::Error), - /// Consensus error. - Common(CommonError), - /// Local account ID not a validator at this block. - #[display(fmt="Local account ID ({:?}) not a validator at this block.", _0)] - NotValidator(AuthorityId), - /// Proposer destroyed before finishing proposing or evaluating - #[display(fmt="Proposer destroyed before finishing proposing or evaluating")] - PrematureDestruction, - /// Failed to register or resolve async timer. - #[display(fmt="Timer failed: {}", _0)] - Timer(tokio::timer::Error), - /// Unable to dispatch agreement future - #[display(fmt="Unable to dispatch agreement future: {:?}", _0)] - Executor(futures::future::ExecuteErrorKind), -} - -impl From<::rhododendron::InputStreamConcluded> for Error { - fn from(_: ::rhododendron::InputStreamConcluded) -> Self { - CommonError::IoTerminated.into() - } -} diff --git a/core/consensus/rhd/src/lib.rs b/core/consensus/rhd/src/lib.rs deleted file mode 100644 index 3bcd1346d47c9..0000000000000 --- a/core/consensus/rhd/src/lib.rs +++ /dev/null @@ -1,1699 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! BFT Agreement based on a rotating proposer in different rounds. -//! -//! Where this crate refers to input stream, should never logically conclude. -//! The logic in this crate assumes that messages flushed to the output stream -//! will eventually reach other nodes and that our own messages are not included -//! in the input stream. -//! -//! Note that it is possible to witness agreement being reached without ever -//! seeing the candidate. Any candidates seen will be checked for validity. -//! -//! Although technically the agreement will always complete (given the eventual -//! delivery of messages), in practice it is possible for this future to -//! conclude without having witnessed the conclusion. -//! In general, this future should be pre-empted by the import of a justification -//! set for this block height. - -#![cfg(feature="rhd")] -// FIXME #1020 doesn't compile -// NOTE: this is the legacy constant used for transaction size. No longer used except -// for the rhd code which is not updated. Placed here for compatibility. -const MAX_TRANSACTIONS_SIZE: u32 = 4 * 1024 * 1024; - -use std::sync::Arc; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::time::{self, Instant, Duration}; - -use codec::{Decode, Encode}; -use consensus::offline_tracker::OfflineTracker; -use consensus::error::{ErrorKind as CommonErrorKind}; -use consensus::{Authorities, BlockImport, Environment, Proposer as BaseProposer}; -use client::{Client as SubstrateClient, CallExecutor}; -use client::runtime_api::{Core, BlockBuilder as BlockBuilderAPI, OldTxQueue, BlockBuilderError}; -use sr_primitives::generic::{BlockId, Era, ImportResult, BlockImportParams, BlockOrigin}; -use sr_primitives::traits::{Block, Header}; -use sr_primitives::traits::{ - Block as BlockT, Hash as HashT, Header as HeaderT, - BlockNumberToHash, SaturatedConversion -}; -use sr_primitives::Justification; -use primitives::{AuthorityId, ed25519, Blake2Hasher, ed25519::LocalizedSignature}; -use srml_system::Trait as SystemT; - -use node_runtime::Runtime; -use transaction_pool::txpool::{self, Pool as TransactionPool}; - -use futures::prelude::*; -use futures::future; -use futures::sync::oneshot; -use tokio::runtime::TaskExecutor; -use tokio::timer::Delay; -use parking_lot::{RwLock, Mutex}; - -pub use rhododendron::{ - self, InputStreamConcluded, AdvanceRoundReason, Message as RhdMessage, - Vote as RhdMessageVote, Communication as RhdCommunication, -}; -pub use self::error::{Error, ErrorKind}; - -// pub mod misbehavior_check; -mod error; -mod service; - -// statuses for an agreement -mod status { - pub const LIVE: usize = 0; - pub const BAD: usize = 1; - pub const GOOD: usize = 2; -} - -pub type Timestamp = u64; - -pub type AccountId = ::primitives::H256; - -/// Localized message type. -pub type LocalizedMessage = rhododendron::LocalizedMessage< - B, - ::Hash, - AuthorityId, - LocalizedSignature ->; - -/// Justification of some hash. -pub struct RhdJustification(rhododendron::Justification); - -/// Justification of a prepare message. -pub struct PrepareJustification(rhododendron::PrepareJustification); - -/// Unchecked justification. -#[derive(Encode, Decode)] -pub struct UncheckedJustification(rhododendron::UncheckedJustification); - -impl UncheckedJustification { - /// Create a new, unchecked justification. - pub fn new(digest: H, signatures: Vec, round_number: u32) -> Self { - UncheckedJustification(rhododendron::UncheckedJustification { - digest, - signatures, - round_number, - }) - } -} - -impl UncheckedJustification { - /// Decode a justification. - pub fn decode_justification(justification: Justification) -> Option { - let inner: rhododendron::UncheckedJustification<_, _> = Decode::decode(&mut &justification[..])?; - - Some(UncheckedJustification(inner)) - } -} - -impl Into for UncheckedJustification { - fn into(self) -> Justification { - self.0.encode() - } -} - -impl From> for UncheckedJustification { - fn from(inner: rhododendron::UncheckedJustification) -> Self { - UncheckedJustification(inner) - } -} - -/// Result of a committed round of BFT -pub type Committed = rhododendron::Committed::Hash, LocalizedSignature>; - -/// Communication between BFT participants. -pub type Communication = rhododendron::Communication::Hash, AuthorityId, LocalizedSignature>; - -/// Misbehavior observed from BFT participants. -pub type Misbehavior = rhododendron::Misbehavior; - -/// Shared offline validator tracker. -pub type SharedOfflineTracker = Arc>; - -/// A proposer for a rhododendron instance. This must implement the base proposer logic. -pub trait LocalProposer: BaseProposer { - /// Import witnessed rhododendron misbehavior. - fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, Misbehavior)>); - - /// Determine the proposer for a given round. This should be a deterministic function - /// with consistent results across all authorities. - fn round_proposer(&self, round_number: u32, authorities: &[AuthorityId]) -> AuthorityId; - - /// Hook called when a BFT round advances without a proposal. - fn on_round_end(&self, _round_number: u32, _proposed: bool) { } -} - - -/// Build new blocks. -pub trait BlockBuilder { - /// Push an extrinsic onto the block. Fails if the extrinsic is invalid. - fn push_extrinsic(&mut self, extrinsic: ::Extrinsic) -> Result<(), Error>; -} - -/// Local client abstraction for the consensus. -pub trait AuthoringApi: - Send - + Sync - + BlockBuilderAPI<::Block, InherentData, Error=::Error> - + Core<::Block, AuthorityId, Error=::Error> - + OldTxQueue<::Block, Error=::Error> -{ - /// The block used for this API type. - type Block: BlockT; - /// The error used by this API type. - type Error: std::error::Error; - - /// Build a block on top of the given, with inherent extrinsics pre-pushed. - fn build_block) -> ()>( - &self, - at: &BlockId, - inherent_data: InherentData, - build_ctx: F, - ) -> Result; -} - -/// A long-lived network which can create BFT message routing processes on demand. -pub trait Network { - /// The block used for this API type. - type Block: BlockT; - /// The input stream of BFT messages. Should never logically conclude. - type Input: Stream,Error=Error>; - /// The output sink of BFT messages. Messages sent here should eventually pass to all - /// current authorities. - type Output: Sink,SinkError=Error>; - - /// Instantiate input and output streams. - fn communication_for( - &self, - validators: &[AuthorityId], - local_id: AuthorityId, - parent_hash: ::Hash, - task_executor: TaskExecutor - ) -> (Self::Input, Self::Output); -} - - -// caches the round number to start at if we end up with BFT consensus on the same -// parent hash more than once (happens if block is bad). -// -// this will force a committed but locally-bad block to be considered analogous to -// a round advancement vote. -#[derive(Debug)] -struct RoundCache { - hash: Option, - start_round: u32, -} - -/// Instance of BFT agreement. -struct BftInstance { - key: Arc, - authorities: Vec, - parent_hash: B::Hash, - round_timeout_multiplier: u64, - cache: Arc>>, - proposer: P, -} - -impl> BftInstance - where - B: Clone + Eq, - B::Hash: ::std::hash::Hash - -{ - fn round_timeout_duration(&self, round: u32) -> Duration { - // 2^(min(6, x/8)) * 10 - // Grows exponentially starting from 10 seconds, capped at 640 seconds. - const ROUND_INCREMENT_STEP: u32 = 8; - - let round = round / ROUND_INCREMENT_STEP; - let round = ::std::cmp::min(6, round); - - let timeout = 1u64.checked_shl(round) - .unwrap_or_else(u64::max_value) - .saturating_mul(self.round_timeout_multiplier); - - Duration::from_secs(timeout) - } - - fn update_round_cache(&self, current_round: u32) { - let mut cache = self.cache.lock(); - if cache.hash.as_ref() == Some(&self.parent_hash) { - cache.start_round = current_round + 1; - } - } -} - -impl> rhododendron::Context for BftInstance - where - B: Clone + Eq, - B::Hash: ::std::hash::Hash, -{ - type Error = P::Error; - type AuthorityId = AuthorityId; - type Digest = B::Hash; - type Signature = LocalizedSignature; - type Candidate = B; - type RoundTimeout = Box>; - type CreateProposal = ::Future; - type EvaluateProposal = ::Future; - - fn local_id(&self) -> AuthorityId { - self.key.public().into() - } - - fn proposal(&self) -> Self::CreateProposal { - self.proposer.propose().into_future() - } - - fn candidate_digest(&self, proposal: &B) -> B::Hash { - proposal.hash() - } - - fn sign_local(&self, message: RhdMessage) -> LocalizedMessage { - sign_message(message, &*self.key, self.parent_hash.clone()) - } - - fn round_proposer(&self, round: u32) -> AuthorityId { - self.proposer.round_proposer(round, &self.authorities[..]) - } - - fn proposal_valid(&self, proposal: &B) -> Self::EvaluateProposal { - self.proposer.evaluate(proposal).into_future() - } - - fn begin_round_timeout(&self, round: u32) -> Self::RoundTimeout { - let timeout = self.round_timeout_duration(round); - let fut = Delay::new(Instant::now() + timeout) - .map_err(|e| Error::from(CommonErrorKind::FaultyTimer(e))) - .map_err(Into::into); - - Box::new(fut) - } - - fn on_advance_round( - &self, - accumulator: &rhododendron::Accumulator, - round: u32, - next_round: u32, - reason: AdvanceRoundReason, - ) { - use std::collections::HashSet; - - let collect_pubkeys = |participants: HashSet<&Self::AuthorityId>| participants.into_iter() - .map(|p| ::ed25519::Public::from_raw(p.0)) - .collect::>(); - - let round_timeout = self.round_timeout_duration(next_round); - debug!(target: "rhd", "Advancing to round {} from {}", next_round, round); - debug!(target: "rhd", "Participating authorities: {:?}", - collect_pubkeys(accumulator.participants())); - debug!(target: "rhd", "Voting authorities: {:?}", - collect_pubkeys(accumulator.voters())); - debug!(target: "rhd", "Round {} should end in at most {} seconds from now", next_round, round_timeout.as_secs()); - - self.update_round_cache(next_round); - - if let AdvanceRoundReason::Timeout = reason { - self.proposer.on_round_end(round, accumulator.proposal().is_some()); - } - } -} - -/// A future that resolves either when canceled (witnessing a block from the network at same height) -/// or when agreement completes. -pub struct BftFuture where - B: Block + Clone + Eq, - B::Hash: ::std::hash::Hash, - P: LocalProposer, - P: BaseProposer, - InStream: Stream, Error=Error>, - OutSink: Sink, SinkError=Error>, -{ - inner: rhododendron::Agreement, InStream, OutSink>, - status: Arc, - cancel: oneshot::Receiver<()>, - import: Arc, -} - -impl Future for BftFuture where - B: Block + Clone + Eq, - B::Hash: ::std::hash::Hash, - P: LocalProposer, - P: BaseProposer, - I: BlockImport, - InStream: Stream, Error=Error>, - OutSink: Sink, SinkError=Error>, -{ - type Item = (); - type Error = (); - - fn poll(&mut self) -> ::futures::Poll<(), ()> { - // service has canceled the future. bail - let cancel = match self.cancel.poll() { - Ok(Async::Ready(())) | Err(_) => true, - Ok(Async::NotReady) => false, - }; - - let committed = match self.inner.poll().map_err(|_| ()) { - Ok(Async::Ready(x)) => x, - Ok(Async::NotReady) => - return Ok(if cancel { Async::Ready(()) } else { Async::NotReady }), - Err(()) => return Err(()), - }; - - // if something was committed, the round leader must have proposed. - self.inner.context().proposer.on_round_end(committed.round_number, true); - - // If we didn't see the proposal (very unlikely), - // we will get the block from the network later. - if let Some(justified_block) = committed.candidate { - let hash = justified_block.hash(); - info!(target: "rhd", "Importing block #{} ({}) directly from BFT consensus", - justified_block.header().number(), hash); - let just: Justification = UncheckedJustification(committed.justification.uncheck()).into(); - let (header, body) = justified_block.deconstruct(); - let import_block = BlockImportParams { - origin: BlockOrigin::ConsensusBroadcast, - header: header, - justification: Some(just), - body: Some(body), - finalized: true, - post_digests: Default::default(), - auxiliary: Default::default() - }; - - let new_status = match self.import.import_block(import_block, None) { - Err(e) => { - warn!(target: "rhd", "Error importing block {:?} in round #{}: {:?}", - hash, committed.round_number, e); - status::BAD - } - Ok(ImportResult::KnownBad) => { - warn!(target: "rhd", "{:?} was bad block agreed on in round #{}", - hash, committed.round_number); - status::BAD - } - _ => status::GOOD - }; - - self.status.store(new_status, Ordering::Release); - - } else { - // assume good unless we received the proposal. - self.status.store(status::GOOD, Ordering::Release); - } - - self.inner.context().update_round_cache(committed.round_number); - - Ok(Async::Ready(())) - } -} - -impl Drop for BftFuture where - B: Block + Clone + Eq, - B::Hash: ::std::hash::Hash, - P: LocalProposer, - P: BaseProposer, - InStream: Stream, Error=Error>, - OutSink: Sink, SinkError=Error>, -{ - fn drop(&mut self) { - let misbehavior = self.inner.drain_misbehavior().collect::>(); - self.inner.context().proposer.import_misbehavior(misbehavior); - } -} - -struct AgreementHandle { - status: Arc, - send_cancel: Option>, -} - -impl AgreementHandle { - fn status(&self) -> usize { - self.status.load(Ordering::Acquire) - } -} - -impl Drop for AgreementHandle { - fn drop(&mut self) { - if let Some(sender) = self.send_cancel.take() { - let _ = sender.send(()); - } - } -} - -/// The BftService kicks off the agreement process on top of any blocks it -/// is notified of. -/// -/// This assumes that it is being run in the context of a tokio runtime. -pub struct BftService { - client: Arc, - live_agreement: Mutex>, - round_cache: Arc>>, - round_timeout_multiplier: u64, - key: Arc, - factory: P, -} - -impl BftService - where - B: Block + Clone + Eq, - P: Environment, - P::Proposer: LocalProposer, - P::Proposer: BaseProposer, - I: BlockImport + Authorities, -{ - /// Create a new service instance. - pub fn new(client: Arc, key: Arc, factory: P) -> BftService { - BftService { - client: client, - live_agreement: Mutex::new(None), - round_cache: Arc::new(Mutex::new(RoundCache { - hash: None, - start_round: 0, - })), - round_timeout_multiplier: 10, - key: key, - factory, - } - } - - /// Get the local Authority ID. - pub fn local_id(&self) -> AuthorityId { - self.key.public().into() - } - - /// Signal that a valid block with the given header has been imported. - /// Provide communication streams that are localized to this block. - /// It's recommended to use the communication primitives provided by this - /// module for signature checking and decoding. See `CheckedStream` and - /// `SigningSink` for more details. - /// - /// Messages received on the stream that don't match the expected format - /// will be dropped. - /// - /// If the local signing key is an authority, this will begin the consensus process to build a - /// block on top of it. If the executor fails to run the future, an error will be returned. - /// Returns `None` if the agreement on the block with given parent is already in progress. - pub fn build_upon(&self, header: &B::Header, input: In, output: Out) - -> Result>::Proposer, - I, - In, - Out, - >>, P::Error> - where - In: Stream, Error=Error>, - Out: Sink, SinkError=Error>, - { - let hash = header.hash(); - - let mut live_agreement = self.live_agreement.lock(); - let can_build = live_agreement.as_ref() - .map_or(true, |x| self.can_build_on_inner(header, x)); - - if !can_build { - return Ok(None) - } - - let authorities = self.client.authorities(&BlockId::Hash(hash.clone())) - .map_err(|e| CommonErrorKind::Other(Box::new(e)).into())?; - - let n = authorities.len(); - let max_faulty = max_faulty_of(n); - trace!(target: "rhd", "Initiating agreement on top of #{}, {:?}", header.number(), hash); - trace!(target: "rhd", "max_faulty_of({})={}", n, max_faulty); - - let local_id = self.local_id(); - - if !authorities.contains(&local_id) { - // cancel current agreement - live_agreement.take(); - Err(CommonErrorKind::InvalidAuthority(local_id).into())?; - } - - let proposer = self.factory.init(header, &authorities, self.key.clone())?; - - let bft_instance = BftInstance { - proposer, - parent_hash: hash.clone(), - cache: self.round_cache.clone(), - round_timeout_multiplier: self.round_timeout_multiplier, - key: self.key.clone(), - authorities: authorities, - }; - - let mut agreement = rhododendron::agree( - bft_instance, - n, - max_faulty, - input, - output, - ); - - // fast forward round number if necessary. - { - let mut cache = self.round_cache.lock(); - trace!(target: "rhd", "Round cache: {:?}", &*cache); - if cache.hash.as_ref() == Some(&hash) { - trace!(target: "rhd", "Fast-forwarding to round {}", cache.start_round); - let start_round = cache.start_round; - cache.start_round += 1; - - drop(cache); - agreement.fast_forward(start_round); - } else { - *cache = RoundCache { - hash: Some(hash.clone()), - start_round: 1, - }; - } - } - - let status = Arc::new(AtomicUsize::new(status::LIVE)); - let (tx, rx) = oneshot::channel(); - - // cancel current agreement. - *live_agreement = Some((header.clone(), AgreementHandle { - send_cancel: Some(tx), - status: status.clone(), - })); - - Ok(Some(BftFuture { - inner: agreement, - status: status, - cancel: rx, - import: self.client.clone(), - })) - } - - /// Cancel current agreement if any. - pub fn cancel_agreement(&self) { - self.live_agreement.lock().take(); - } - - /// Whether we can build using the given header. - pub fn can_build_on(&self, header: &B::Header) -> bool { - self.live_agreement.lock().as_ref() - .map_or(true, |x| self.can_build_on_inner(header, x)) - } - - /// Get a reference to the underlying client. - pub fn client(&self) -> &I { &*self.client } - - fn can_build_on_inner(&self, header: &B::Header, live: &(B::Header, AgreementHandle)) -> bool { - let hash = header.hash(); - let &(ref live_header, ref handle) = live; - match handle.status() { - _ if *header != *live_header && *live_header.parent_hash() != hash => true, // can always follow with next block. - status::BAD => hash == live_header.hash(), // bad block can be re-agreed on. - _ => false, // canceled won't appear since we overwrite the handle before returning. - } - } -} - -/// Stream that decodes rhododendron messages and checks signatures. -/// -/// This stream is localized to a specific parent block-hash, as all messages -/// will be signed in a way that accounts for it. When using this with -/// `BftService::build_upon`, the user should take care to use the same hash as for that. -pub struct CheckedStream { - inner: S, - local_id: AuthorityId, - authorities: Vec, - parent_hash: B::Hash, -} - -impl CheckedStream { - /// Construct a new checked stream. - pub fn new( - inner: S, - local_id: AuthorityId, - authorities: Vec, - parent_hash: B::Hash, - ) -> Self { - CheckedStream { - inner, - local_id, - authorities, - parent_hash, - } - } -} - -impl>> Stream for CheckedStream - where S::Error: From, -{ - type Item = Communication; - type Error = S::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - use rhododendron::LocalizedMessage as RhdLocalized; - loop { - match self.inner.poll()? { - Async::Ready(Some(item)) => { - let comms: Communication = match Decode::decode(&mut &item[..]) { - Some(x) => x, - None => continue, - }; - - match comms { - RhdCommunication::Auxiliary(prepare_just) => { - let checked = check_prepare_justification::( - &self.authorities, - self.parent_hash, - UncheckedJustification(prepare_just.uncheck()), - ); - if let Ok(checked) = checked { - return Ok(Async::Ready( - Some(RhdCommunication::Auxiliary(checked.0)) - )); - } - } - RhdCommunication::Consensus(RhdLocalized::Propose(p)) => { - if p.sender == self.local_id { continue } - - let checked = check_proposal::( - &self.authorities, - &self.parent_hash, - &p, - ); - - if let Ok(()) = checked { - return Ok(Async::Ready( - Some(RhdCommunication::Consensus(RhdLocalized::Propose(p))) - )); - } - } - RhdCommunication::Consensus(RhdLocalized::Vote(v)) => { - if v.sender == self.local_id { continue } - - let checked = check_vote::( - &self.authorities, - &self.parent_hash, - &v, - ); - - if let Ok(()) = checked { - return Ok(Async::Ready( - Some(RhdCommunication::Consensus(RhdLocalized::Vote(v))) - )); - } - } - } - } - Async::Ready(None) => return Ok(Async::Ready(None)), - Async::NotReady => return Ok(Async::NotReady), - } - } - } -} - -/// Given a total number of authorities, yield the maximum faulty that would be allowed. -/// This will always be under 1/3. -pub fn max_faulty_of(n: usize) -> usize { - n.saturating_sub(1) / 3 -} - -/// Given a total number of authorities, yield the minimum required signatures. -/// This will always be over 2/3. -pub fn bft_threshold(n: usize) -> usize { - n - max_faulty_of(n) -} - -// actions in the signature scheme. -#[derive(Encode)] -enum Action { - Prepare(u32, H), - Commit(u32, H), - AdvanceRound(u32), - // signatures of header hash and full candidate are both included. - ProposeHeader(u32, H), - Propose(u32, B), -} - -// encode something in a way which is localized to a specific parent-hash -fn localized_encode(parent_hash: H, value: E) -> Vec { - (parent_hash, value).encode() -} - -fn check_justification_signed_message( - authorities: &[AuthorityId], - message: &[u8], - just: UncheckedJustification) --> Result, UncheckedJustification> { - // additional error information could be useful here. - just.0.check(authorities.len() - max_faulty_of(authorities.len()), |_, _, sig| { - let auth_id = sig.signer.clone().into(); - if !authorities.contains(&auth_id) { return None } - - if ed25519::Pair::verify(&sig.signature, message, &sig.signer) { - Some(sig.signer.0) - } else { - None - } - }).map(RhdJustification).map_err(UncheckedJustification) -} - -/// Check a full justification for a header hash. -/// Provide all valid authorities. -/// -/// On failure, returns the justification back. -pub fn check_justification( - authorities: &[AuthorityId], - parent: B::Hash, - just: UncheckedJustification -) -> Result, UncheckedJustification> { - let vote: Action = Action::Commit(just.0.round_number as u32, just.0.digest.clone()); - let message = localized_encode(parent, vote); - - check_justification_signed_message(authorities, &message[..], just) -} - -/// Check a prepare justification for a header hash. -/// Provide all valid authorities. -/// -/// On failure, returns the justification back. -pub fn check_prepare_justification( - authorities: &[AuthorityId], - parent: B::Hash, - just: UncheckedJustification -) -> Result, UncheckedJustification> { - let vote: Action = Action::Prepare(just.0.round_number as u32, just.0.digest.clone()); - let message = localized_encode(parent, vote); - - check_justification_signed_message(authorities, &message[..], just).map(|e| PrepareJustification(e.0)) -} - -/// Check proposal message signatures and authority. -/// Provide all valid authorities. -pub fn check_proposal( - authorities: &[AuthorityId], - parent_hash: &B::Hash, - propose: &rhododendron::LocalizedProposal) - -> Result<(), Error> -{ - if !authorities.contains(&propose.sender) { - return Err(CommonErrorKind::InvalidAuthority(propose.sender.into()).into()); - } - - let action_header = Action::ProposeHeader(propose.round_number as u32, propose.digest.clone()); - let action_propose = Action::Propose(propose.round_number as u32, propose.proposal.clone()); - check_action::(action_header, parent_hash, &propose.digest_signature)?; - check_action::(action_propose, parent_hash, &propose.full_signature) -} - -/// Check vote message signatures and authority. -/// Provide all valid authorities. -pub fn check_vote( - authorities: &[AuthorityId], - parent_hash: &B::Hash, - vote: &rhododendron::LocalizedVote) - -> Result<(), Error> -{ - if !authorities.contains(&vote.sender) { - return Err(CommonErrorKind::InvalidAuthority(vote.sender.into()).into()); - } - - let action = match vote.vote { - rhododendron::Vote::Prepare(r, ref h) => Action::Prepare(r as u32, h.clone()), - rhododendron::Vote::Commit(r, ref h) => Action::Commit(r as u32, h.clone()), - rhododendron::Vote::AdvanceRound(r) => Action::AdvanceRound(r as u32), - }; - check_action::(action, parent_hash, &vote.signature) -} - -fn check_action( - action: Action, - parent_hash: &B::Hash, - sig: &LocalizedSignature -) -> Result<(), Error> { - let message = localized_encode(*parent_hash, action); - if ed25519::Pair::verify(&sig.signature, &message, &sig.signer) { - Ok(()) - } else { - Err(CommonErrorKind::InvalidSignature(sig.signature.into(), sig.signer.clone().into()).into()) - } -} - -/// Sign a BFT message with the given key. -pub fn sign_message( - message: RhdMessage, - key: &ed25519::Pair, - parent_hash: B::Hash -) -> LocalizedMessage { - let signer = key.public(); - - let sign_action = |action: Action| { - let to_sign = localized_encode(parent_hash.clone(), action); - - LocalizedSignature { - signer: signer.clone(), - signature: key.sign(&to_sign), - } - }; - - match message { - RhdMessage::Propose(r, proposal) => { - let header_hash = proposal.hash(); - let action_header = Action::ProposeHeader(r as u32, header_hash.clone()); - let action_propose = Action::Propose(r as u32, proposal.clone()); - - rhododendron::LocalizedMessage::Propose(rhododendron::LocalizedProposal { - round_number: r, - proposal, - digest: header_hash, - sender: signer.clone().into(), - digest_signature: sign_action(action_header), - full_signature: sign_action(action_propose), - }) - } - RhdMessage::Vote(vote) => rhododendron::LocalizedMessage::Vote({ - let action = match vote { - RhdMessageVote::Prepare(r, h) => Action::Prepare(r as u32, h), - RhdMessageVote::Commit(r, h) => Action::Commit(r as u32, h), - RhdMessageVote::AdvanceRound(r) => Action::AdvanceRound(r as u32), - }; - - rhododendron::LocalizedVote { - vote: vote, - sender: signer.clone().into(), - signature: sign_action(action), - } - }) - } -} - - -impl<'a, B, E, Block> BlockBuilder for client::block_builder::BlockBuilder<'a, B, E, Block, Blake2Hasher> where - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, - Block: BlockT -{ - fn push_extrinsic(&mut self, extrinsic: ::Extrinsic) -> Result<(), Error> { - client::block_builder::BlockBuilder::push(self, extrinsic).map_err(Into::into) - } -} - -impl<'a, B, E, Block> AuthoringApi for SubstrateClient where - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + Clone + 'static, - Block: BlockT, -{ - type Block = Block; - type Error = client::error::Error; - - fn build_block) -> ()>( - &self, - at: &BlockId, - inherent_data: InherentData, - mut build_ctx: F, - ) -> Result { - let runtime_version = self.runtime_version_at(at)?; - - let mut block_builder = self.new_block_at(at)?; - if runtime_version.has_api(*b"blkbuild", 1) { - for inherent in self.inherent_extrinsics(at, &inherent_data)? { - block_builder.push(inherent)?; - } - } - - build_ctx(&mut block_builder); - - block_builder.bake().map_err(Into::into) - } -} - - -/// Proposer factory. -pub struct ProposerFactory where - C: AuthoringApi, - A: txpool::ChainApi, -{ - /// The client instance. - pub client: Arc, - /// The transaction pool. - pub transaction_pool: Arc>, - /// The backing network handle. - pub network: N, - /// handle to remote task executor - pub handle: TaskExecutor, - /// Offline-tracker. - pub offline: SharedOfflineTracker, - /// Force delay in evaluation this long. - pub force_delay: u64, -} - -impl consensus::Environment<::Block> for ProposerFactory where - N: Network::Block>, - C: AuthoringApi + BlockNumberToHash, - A: txpool::ChainApi::Block>, - // <::Block as BlockT>::Hash: - // Into<::Hash> + PartialEq + Into, - Error: From<::Error> -{ - type Proposer = Proposer; - type Error = Error; - - fn init( - &self, - parent_header: &<::Block as BlockT>::Header, - authorities: &[AuthorityId], - sign_with: Arc, - ) -> Result { - use sr_primitives::traits::Hash as HashT; - let parent_hash = parent_header.hash(); - - let id = BlockId::hash(parent_hash); - let random_seed = self.client.random_seed(&id)?; - let random_seed = <<::Block as BlockT>::Header as HeaderT> - ::Hashing::hash(random_seed.as_ref()); - - let validators = self.client.validators(&id)?; - self.offline.write().note_new_block(&validators[..]); - - info!("Starting consensus session on top of parent {:?}", parent_hash); - - let local_id = sign_with.public().0.into(); - let (input, output) = self.network.communication_for( - authorities, - local_id, - parent_hash.clone(), - self.handle.clone(), - ); - let now = Instant::now(); - let proposer = Proposer { - client: self.client.clone(), - start: now, - local_key: sign_with, - parent_hash, - parent_id: id, - parent_number: *parent_header.number(), - random_seed, - transaction_pool: self.transaction_pool.clone(), - offline: self.offline.clone(), - validators, - minimum_timestamp: current_timestamp() + self.force_delay, - network: self.network.clone() - }; - - Ok(proposer) - } -} - -/// The proposer logic. -pub struct Proposer { - client: Arc, - start: Instant, - local_key: Arc, - parent_hash: <::Block as BlockT>::Hash, - parent_id: BlockId<::Block>, - parent_number: <<::Block as BlockT>::Header as HeaderT>::Number, - random_seed: <::Block as BlockT>::Hash, - transaction_pool: Arc>, - offline: SharedOfflineTracker, - validators: Vec, - minimum_timestamp: u64, - network: N, -} - -impl Proposer { - fn primary_index(&self, round_number: u32, len: usize) -> usize { - use primitives::uint::U256; - - let big_len = U256::from(len); - let offset = U256::from_big_endian(self.random_seed.as_ref()) % big_len; - let offset = offset.low_u64() as usize + round_number as usize; - offset % len - } -} - -impl BaseProposer<::Block> for Proposer where - C: AuthoringApi + BlockNumberToHash, - A: txpool::ChainApi::Block>, - <::Block as BlockT>::Hash: - Into<::Hash> + PartialEq + Into, - error::Error: From<::Error> -{ - type Create = Result<::Block, Error>; - type Error = Error; - type Evaluate = Box>; - - fn propose(&self) -> Self::Create { - use sr_primitives::traits::BlakeTwo256; - - const MAX_VOTE_OFFLINE_SECONDS: Duration = Duration::from_secs(60); - - let timestamp = ::std::cmp::max(self.minimum_timestamp, current_timestamp()); - - let elapsed_since_start = self.start.elapsed(); - let offline_indices = if elapsed_since_start > MAX_VOTE_OFFLINE_SECONDS { - Vec::new() - } else { - self.offline.read().reports(&self.validators[..]) - }; - - if !offline_indices.is_empty() { - info!( - "Submitting offline validators {:?} for slash-vote", - offline_indices.iter().map(|&i| self.validators[i as usize]).collect::>(), - ) - } - - let inherent_data = InherentData { - timestamp, - offline_indices, - }; - - let block = self.client.build_block( - &self.parent_id, - inherent_data, - |block_builder| { - let mut unqueue_invalid = Vec::new(); - self.transaction_pool.ready(|pending_iterator| { - let mut pending_size = 0; - for pending in pending_iterator { - let encoded_size = pending.data.encode().len(); - if pending_size + encoded_size >= MAX_TRANSACTIONS_SIZE { break } - - match block_builder.push_extrinsic(pending.data.clone()) { - Ok(()) => { - pending_size += encoded_size; - } - Err(e) => { - trace!(target: "transaction-pool", "Invalid transaction: {}", e); - unqueue_invalid.push(pending.hash.clone()); - } - } - } - }); - - 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(", ") - ); - - let substrate_block = Decode::decode(&mut block.encode().as_slice()) - .expect("blocks are defined to serialize to substrate blocks correctly; qed"); - - assert!(evaluation::evaluate_initial( - &substrate_block, - &self.parent_hash, - self.parent_number, - ).is_ok()); - - Ok(substrate_block) - } - - fn evaluate(&self, unchecked_proposal: &::Block) -> Self::Evaluate { - debug!(target: "rhd", "evaluating block on top of parent ({}, {:?})", self.parent_number, self.parent_hash); - - // do initial serialization and structural integrity checks. - if let Err(e) = evaluation::evaluate_initial( - unchecked_proposal, - &self.parent_hash, - self.parent_number, - ) { - debug!(target: "rhd", "Invalid proposal: {:?}", e); - return Box::new(future::ok(false)); - }; - - let current_timestamp = current_timestamp(); - let inherent = InherentData::new( - current_timestamp, - self.offline.read().reports(&self.validators) - ); - let proposed_timestamp = match self.client.check_inherents( - &self.parent_id, - &unchecked_proposal, - &inherent, - ) { - Ok(Ok(())) => None, - Ok(Err(BlockBuilderError::ValidAtTimestamp(timestamp))) => Some(timestamp), - Ok(Err(e)) => { - debug!(target: "rhd", "Invalid proposal (check_inherents): {:?}", e); - return Box::new(future::ok(false)); - }, - Err(e) => { - debug!(target: "rhd", "Could not call into runtime: {:?}", e); - return Box::new(future::ok(false)); - } - }; - - let vote_delays = { - - // the duration until the given timestamp is current - let proposed_timestamp = ::std::cmp::max(self.minimum_timestamp, proposed_timestamp.unwrap_or(0)); - let timestamp_delay = if proposed_timestamp > current_timestamp { - let delay_s = proposed_timestamp - current_timestamp; - debug!(target: "rhd", "Delaying evaluation of proposal for {} seconds", delay_s); - Some(Instant::now() + Duration::from_secs(delay_s)) - } else { - None - }; - - match timestamp_delay { - Some(duration) => future::Either::A( - Delay::new(duration).map_err(|e| ErrorKind::Timer(e).into()) - ), - None => future::Either::B(future::ok(())), - } - }; - - // evaluate whether the block is actually valid. - // it may be better to delay this until the delays are finished - let evaluated = match self.client.execute_block(&self.parent_id, &unchecked_proposal.clone()) - .map_err(Error::from) { - Ok(()) => Ok(true), - Err(err) => match err.kind() { - error::ErrorKind::Client(client::error::ErrorKind::Execution(_)) => Ok(false), - _ => Err(err) - } - }; - - let future = future::result(evaluated).and_then(move |good| { - let end_result = future::ok(good); - if good { - // delay a "good" vote. - future::Either::A(vote_delays.and_then(|_| end_result)) - } else { - // don't delay a "bad" evaluation. - future::Either::B(end_result) - } - }); - - Box::new(future) as Box<_> - } -} - -impl LocalProposer<::Block> for Proposer where - C: AuthoringApi + BlockNumberToHash, - A: txpool::ChainApi::Block>, - Self: BaseProposer<::Block, Error=Error>, - <::Block as BlockT>::Hash: - Into<::Hash> + PartialEq + Into, - error::Error: From<::Error> -{ - - fn round_proposer(&self, round_number: u32, authorities: &[AuthorityId]) -> AuthorityId { - let offset = self.primary_index(round_number, authorities.len()); - let proposer = authorities[offset as usize].clone(); - trace!(target: "rhd", "proposer for round {} is {}", round_number, proposer); - - proposer - } - - fn import_misbehavior( - &self, - _misbehavior: Vec<(AuthorityId, Misbehavior<<::Block as BlockT>::Hash>)> - ) { - use rhododendron::Misbehavior as GenericMisbehavior; - use sr_primitives::bft::{MisbehaviorKind, MisbehaviorReport}; - use node_runtime::{Call, UncheckedExtrinsic, ConsensusCall}; - - let mut next_index = { - let local_id = self.local_key.public().0; - let cur_index = self.transaction_pool.cull_and_get_pending(&BlockId::hash(self.parent_hash), |pending| pending - .filter(|tx| tx.verified.sender == local_id) - .last() - .map(|tx| Ok(tx.verified.index())) - .unwrap_or_else(|| self.client.account_nonce(&self.parent_id, local_id)) - .map_err(Error::from) - ); - - match cur_index { - Ok(cur_index) => cur_index + 1, - Err(e) => { - warn!(target: "consensus", "Error computing next transaction index: {:?}", e); - return; - } - } - }; - - for (target, misbehavior) in misbehavior { - let report = MisbehaviorReport { - parent_hash: self.parent_hash.into(), - parent_number: self.parent_number.saturated_into::(), - target, - misbehavior: match misbehavior { - GenericMisbehavior::ProposeOutOfTurn(_, _, _) => continue, - GenericMisbehavior::DoublePropose(_, _, _) => continue, - GenericMisbehavior::DoublePrepare(round, (h1, s1), (h2, s2)) - => MisbehaviorKind::BftDoublePrepare(round as u32, (h1.into(), s1.signature), (h2.into(), s2.signature)), - GenericMisbehavior::DoubleCommit(round, (h1, s1), (h2, s2)) - => MisbehaviorKind::BftDoubleCommit(round as u32, (h1.into(), s1.signature), (h2.into(), s2.signature)), - } - }; - let payload = ( - next_index, - Call::Consensus(ConsensusCall::report_misbehavior(report)), - Era::immortal(), - self.client.genesis_hash() - ); - let signature = self.local_key.sign(&payload.encode()).into(); - next_index += 1; - - let local_id = self.local_key.public().0.into(); - let extrinsic = UncheckedExtrinsic { - signature: Some((node_runtime::RawAddress::Id(local_id), signature, payload.0, Era::immortal())), - function: payload.1, - }; - let uxt: <::Block as BlockT>::Extrinsic = Decode::decode( - &mut extrinsic.encode().as_slice()).expect("Encoded extrinsic is valid"); - let hash = BlockId::<::Block>::hash(self.parent_hash); - if let Err(e) = self.transaction_pool.submit_one(&hash, uxt) { - warn!("Error importing misbehavior report: {:?}", e); - } - } - } - - fn on_round_end(&self, round_number: u32, was_proposed: bool) { - let primary_validator = self.validators[ - self.primary_index(round_number, self.validators.len()) - ]; - - // alter the message based on whether we think the empty proposer was forced to skip the round. - // this is determined by checking if our local validator would have been forced to skip the round. - if !was_proposed { - let public = ed25519::Public::from_raw(primary_validator.0); - info!( - "Potential Offline Validator: {} failed to propose during assigned slot: {}", - public, - round_number, - ); - } - - self.offline.write().note_round_end(primary_validator, was_proposed); - } -} - -fn current_timestamp() -> u64 { - 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 std::collections::HashSet; - use std::marker::PhantomData; - - use sr_primitives::testing::{Block as GenericTestBlock, Header as TestHeader}; - use primitives::H256; - use keyring::Ed25519Keyring; - - type TestBlock = GenericTestBlock<()>; - - struct FakeClient { - authorities: Vec, - imported_heights: Mutex> - } - - impl BlockImport for FakeClient { - type Error = Error; - - fn import_block(&self, - block: BlockImportParams, - _new_authorities: Option> - ) -> Result { - assert!(self.imported_heights.lock().insert(block.header.number)); - Ok(ImportResult::Queued) - } - } - - impl Authorities for FakeClient { - type Error = Error; - - fn authorities(&self, _at: &BlockId) -> Result, Self::Error> { - Ok(self.authorities.clone()) - } - } - - // "black hole" output sink. - struct Comms(::std::marker::PhantomData); - - impl Sink for Comms { - type SinkItem = Communication; - type SinkError = E; - - fn start_send(&mut self, _item: Communication) -> ::futures::StartSend, E> { - Ok(::futures::AsyncSink::Ready) - } - - fn poll_complete(&mut self) -> ::futures::Poll<(), E> { - Ok(Async::Ready(())) - } - } - - impl Stream for Comms { - type Item = Communication; - type Error = E; - - fn poll(&mut self) -> ::futures::Poll, Self::Error> { - Ok(::futures::Async::NotReady) - } - } - - struct DummyFactory; - struct DummyProposer(u64); - - impl Environment for DummyFactory { - type Proposer = DummyProposer; - type Error = Error; - - fn init(&mut self, parent_header: &TestHeader, _authorities: &[AuthorityId], _sign_with: Arc) - -> Result - { - Ok(DummyProposer(parent_header.number + 1)) - } - } - - impl BaseProposer for DummyProposer { - type Error = Error; - type Create = Result; - type Evaluate = Result; - - fn propose(&self) -> Result { - - Ok(TestBlock { - header: from_block_number(self.0), - extrinsics: Default::default() - }) - } - - fn evaluate(&self, proposal: &TestBlock) -> Result { - Ok(proposal.header.number == self.0) - } - } - - impl LocalProposer for DummyProposer { - fn import_misbehavior(&self, _misbehavior: Vec<(AuthorityId, Misbehavior)>) {} - - fn round_proposer(&self, round_number: u32, authorities: &[AuthorityId]) -> AuthorityId { - authorities[(round_number as usize) % authorities.len()].clone() - } - } - - fn make_service(client: FakeClient) - -> BftService - { - BftService { - client: Arc::new(client), - live_agreement: Mutex::new(None), - round_cache: Arc::new(Mutex::new(RoundCache { - hash: None, - start_round: 0, - })), - round_timeout_multiplier: 10, - key: Arc::new(Ed25519Keyring::One.into()), - factory: DummyFactory - } - } - - fn sign_vote(vote: rhododendron::Vote, key: &ed25519::Pair, parent_hash: H256) -> LocalizedSignature { - match sign_message::(vote.into(), key, parent_hash) { - rhododendron::LocalizedMessage::Vote(vote) => vote.signature, - _ => panic!("signing vote leads to signed vote"), - } - } - - fn from_block_number(num: u64) -> TestHeader { - TestHeader::new( - num, - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ) - } - - #[test] - fn future_gets_preempted() { - let client = FakeClient { - authorities: vec![ - Ed25519Keyring::One.into(), - Ed25519Keyring::Two.into(), - Ed25519Keyring::Alice.into(), - Ed25519Keyring::Eve.into(), - ], - imported_heights: Mutex::new(HashSet::new()), - }; - - let service = make_service(client); - - let first = from_block_number(2); - let first_hash = first.hash(); - - let mut second = from_block_number(3); - second.parent_hash = first_hash; - let _second_hash = second.hash(); - - let mut first_bft = service.build_upon(&first, Comms(PhantomData), Comms(PhantomData)).unwrap().unwrap(); - assert!(service.live_agreement.lock().as_ref().unwrap().0 == first); - - let _second_bft = service.build_upon(&second, Comms(PhantomData), Comms(PhantomData)).unwrap(); - assert!(service.live_agreement.lock().as_ref().unwrap().0 != first); - assert!(service.live_agreement.lock().as_ref().unwrap().0 == second); - - // first_bft has been cancelled. need to swap out so we can check it. - let (_tx, mut rx) = oneshot::channel(); - ::std::mem::swap(&mut rx, &mut first_bft.cancel); - - assert!(rx.wait().is_ok()); - } - - #[test] - fn max_faulty() { - assert_eq!(max_faulty_of(3), 0); - assert_eq!(max_faulty_of(4), 1); - assert_eq!(max_faulty_of(100), 33); - assert_eq!(max_faulty_of(0), 0); - assert_eq!(max_faulty_of(11), 3); - assert_eq!(max_faulty_of(99), 32); - } - - #[test] - fn justification_check_works() { - let parent_hash = Default::default(); - let hash = [0xff; 32].into(); - - let authorities = vec![ - Ed25519Keyring::One.into(), - Ed25519Keyring::Two.into(), - Ed25519Keyring::Alice.into(), - Ed25519Keyring::Eve.into(), - ]; - - let authorities_keys = vec![ - Ed25519Keyring::One.into(), - Ed25519Keyring::Two.into(), - Ed25519Keyring::Alice.into(), - Ed25519Keyring::Eve.into(), - ]; - - let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { - digest: hash, - round_number: 1, - signatures: authorities_keys.iter().take(3).map(|key| { - sign_vote(rhododendron::Vote::Commit(1, hash).into(), key, parent_hash) - }).collect(), - }); - - assert!(check_justification::(&authorities, parent_hash, unchecked).is_ok()); - - let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { - digest: hash, - round_number: 0, // wrong round number (vs. the signatures) - signatures: authorities_keys.iter().take(3).map(|key| { - sign_vote(rhododendron::Vote::Commit(1, hash).into(), key, parent_hash) - }).collect(), - }); - - assert!(check_justification::(&authorities, parent_hash, unchecked).is_err()); - - // not enough signatures. - let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { - digest: hash, - round_number: 1, - signatures: authorities_keys.iter().take(2).map(|key| { - sign_vote(rhododendron::Vote::Commit(1, hash).into(), key, parent_hash) - }).collect(), - }); - - assert!(check_justification::(&authorities, parent_hash, unchecked).is_err()); - - // wrong hash. - let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { - digest: [0xfe; 32].into(), - round_number: 1, - signatures: authorities_keys.iter().take(3).map(|key| { - sign_vote(rhododendron::Vote::Commit(1, hash).into(), key, parent_hash) - }).collect(), - }); - - assert!(check_justification::(&authorities, parent_hash, unchecked).is_err()); - } - - #[test] - fn propose_check_works() { - let parent_hash = Default::default(); - - let authorities = vec![ - Ed25519Keyring::Alice.into(), - Ed25519Keyring::Eve.into(), - ]; - - let block = TestBlock { - header: from_block_number(1), - extrinsics: Default::default() - }; - - let proposal = sign_message( - rhododendron::Message::Propose(1, block.clone()), - &Ed25519Keyring::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(); - invalid_round.round_number = 0; - assert!(check_proposal(&authorities, &parent_hash, &invalid_round).is_err()); - let mut invalid_digest = proposal.clone(); - invalid_digest.digest = [0xfe; 32].into(); - assert!(check_proposal(&authorities, &parent_hash, &invalid_digest).is_err()); - } else { - assert!(false); - } - - // Not an authority - let proposal = sign_message::( - rhododendron::Message::Propose(1, block), - &Ed25519Keyring::Bob.pair(), - parent_hash, - ); - if let rhododendron::LocalizedMessage::Propose(proposal) = proposal { - assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err()); - } else { - assert!(false); - } - } - - #[test] - fn vote_check_works() { - let parent_hash: H256 = Default::default(); - let hash: H256 = [0xff; 32].into(); - - let authorities = vec![ - Ed25519Keyring::Alice.into(), - Ed25519Keyring::Eve.into(), - ]; - - let vote = sign_message::(rhododendron::Message::Vote(rhododendron::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);; - if let rhododendron::LocalizedMessage::Vote(vote) = vote { - assert!(check_vote::(&authorities, &parent_hash, &vote).is_ok()); - let mut invalid_sender = vote.clone(); - invalid_sender.signature.signer = Keyring::Eve.into(); - assert!(check_vote::(&authorities, &parent_hash, &invalid_sender).is_err()); - } else { - assert!(false); - } - - // Not an authority - let vote = sign_message::(rhododendron::Message::Vote(rhododendron::Vote::Prepare(1, hash)), &Keyring::Bob.pair(), parent_hash);; - if let rhododendron::LocalizedMessage::Vote(vote) = vote { - assert!(check_vote::(&authorities, &parent_hash, &vote).is_err()); - } else { - assert!(false); - } - } - - #[test] - fn drop_bft_future_does_not_deadlock() { - let client = FakeClient { - authorities: vec![ - Ed25519Keyring::One.into(), - Ed25519Keyring::Two.into(), - Ed25519Keyring::Alice.into(), - Ed25519Keyring::Eve.into(), - ], - imported_heights: Mutex::new(HashSet::new()), - }; - - let service = make_service(client); - - let first = from_block_number(2); - let first_hash = first.hash(); - - let mut second = from_block_number(3); - second.parent_hash = first_hash; - - let _ = service.build_upon(&first, Comms(PhantomData), Comms(PhantomData)).unwrap(); - assert!(service.live_agreement.lock().as_ref().unwrap().0 == first); - service.live_agreement.lock().take(); - } - - #[test] - fn bft_can_build_though_skipped() { - let client = FakeClient { - authorities: vec![ - Ed25519Keyring::One.into(), - Ed25519Keyring::Two.into(), - Ed25519Keyring::Alice.into(), - Ed25519Keyring::Eve.into(), - ], - imported_heights: Mutex::new(HashSet::new()), - }; - - let service = make_service(client); - - let first = from_block_number(2); - let first_hash = first.hash(); - - let mut second = from_block_number(3); - second.parent_hash = first_hash; - - let mut third = from_block_number(4); - third.parent_hash = second.hash(); - - let _ = service.build_upon(&first, Comms(PhantomData), Comms(PhantomData)).unwrap(); - assert!(service.live_agreement.lock().as_ref().unwrap().0 == first); - // BFT has not seen second, but will move forward on third - service.build_upon(&third, Comms(PhantomData), Comms(PhantomData)).unwrap(); - assert!(service.live_agreement.lock().as_ref().unwrap().0 == third); - - // but we are not walking backwards - service.build_upon(&second, Comms(PhantomData), Comms(PhantomData)).unwrap(); - assert!(service.live_agreement.lock().as_ref().unwrap().0 == third); - } -} diff --git a/core/consensus/rhd/src/misbehaviour_check.rs b/core/consensus/rhd/src/misbehaviour_check.rs deleted file mode 100644 index bde3976c19b09..0000000000000 --- a/core/consensus/rhd/src/misbehaviour_check.rs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Utility for substrate-based runtimes that want to check misbehavior reports. - -use codec::{Codec, Encode}; -use primitives::{AuthorityId, Signature}; - -use rhododendron::messages::{Action, Message, MisbehaviorKind}; -use runtime_io; - -// check a message signature. returns true if signed by that authority. -fn check_message_sig( - message: Message, - signature: &Signature, - from: &AuthorityId, -) -> bool { - let msg: Vec = message.encode(); - runtime_io::ed25519_verify(&signature.0, &msg, from) -} - -fn prepare(parent: H, round_number: u32, hash: H) -> Message { - Message { - parent, - action: Action::Prepare(round_number, hash), - } -} - -fn commit(parent: H, round_number: u32, hash: H) -> Message { - Message { - parent, - action: Action::Commit(round_number, hash), - } -} - -/// Evaluate misbehavior. -/// -/// Doesn't check that the header hash in question is -/// valid or whether the misbehaving authority was part of -/// the set at that block. -pub fn evaluate_misbehavior( - misbehaved: &AuthorityId, - parent_hash: H, - kind: &MisbehaviorKind, -) -> bool { - match *kind { - MisbehaviorKind::BftDoublePrepare(round, (h_1, ref s_1), (h_2, ref s_2)) => { - s_1 != s_2 && - check_message_sig::(prepare::(parent_hash, round, h_1), s_1, misbehaved) && - check_message_sig::(prepare::(parent_hash, round, h_2), s_2, misbehaved) - } - MisbehaviorKind::BftDoubleCommit(round, (h_1, ref s_1), (h_2, ref s_2)) => { - s_1 != s_2 && - check_message_sig::(commit::(parent_hash, round, h_1), s_1, misbehaved) && - check_message_sig::(commit::(parent_hash, round, h_2), s_2, misbehaved) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use keyring::Ed25519Keyring; - use rhododendron; - - use sr_primitives::testing::{H256, Block as RawBlock}; - - type Block = RawBlock; - - fn sign_prepare(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) { - let msg = ::sign_message::( - rhododendron::Message::Vote(rhododendron::Vote::Prepare(round as _, hash)), - key, - parent_hash - ); - - match msg { - rhododendron::LocalizedMessage::Vote(vote) => (hash, vote.signature.signature), - _ => panic!("signing vote leads to signed vote"), - } - } - - fn sign_commit(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) { - let msg = ::sign_message::( - rhododendron::Message::Vote(rhododendron::Vote::Commit(round as _, hash)), - key, - parent_hash - ); - - match msg { - rhododendron::LocalizedMessage::Vote(vote) => (hash, vote.signature.signature), - _ => panic!("signing vote leads to signed vote"), - } - } - - #[test] - fn evaluates_double_prepare() { - let key = Ed25519Keyring::One.pair(); - let parent_hash = [0xff; 32].into(); - let hash_1 = [0; 32].into(); - let hash_2 = [1; 32].into(); - - assert!(evaluate_misbehavior::( - &key.public().into(), - parent_hash, - &MisbehaviorKind::BftDoublePrepare( - 1, - sign_prepare(&key, 1, hash_1, parent_hash), - sign_prepare(&key, 1, hash_2, parent_hash) - ) - )); - - // same signature twice is not misbehavior. - let signed = sign_prepare(&key, 1, hash_1, parent_hash); - assert!(!evaluate_misbehavior::( - &key.public().into(), - parent_hash, - &MisbehaviorKind::BftDoublePrepare( - 1, - signed, - signed, - ) - )); - - // misbehavior has wrong target. - assert!(!evaluate_misbehavior::( - &Ed25519Keyring::Two.into(), - parent_hash, - &MisbehaviorKind::BftDoublePrepare( - 1, - sign_prepare(&key, 1, hash_1, parent_hash), - sign_prepare(&key, 1, hash_2, parent_hash), - ) - )); - } - - #[test] - fn evaluates_double_commit() { - let key = Ed25519Keyring::One.pair(); - let parent_hash = [0xff; 32].into(); - let hash_1 = [0; 32].into(); - let hash_2 = [1; 32].into(); - - assert!(evaluate_misbehavior::( - &key.public().into(), - parent_hash, - &MisbehaviorKind::BftDoubleCommit( - 1, - sign_commit(&key, 1, hash_1, parent_hash), - sign_commit(&key, 1, hash_2, parent_hash) - ) - )); - - // same signature twice is not misbehavior. - let signed = sign_commit(&key, 1, hash_1, parent_hash); - assert!(!evaluate_misbehavior::( - &key.public().into(), - parent_hash, - &MisbehaviorKind::BftDoubleCommit( - 1, - signed, - signed, - ) - )); - - // misbehavior has wrong target. - assert!(!evaluate_misbehavior::( - &Ed25519Keyring::Two.into(), - parent_hash, - &MisbehaviorKind::BftDoubleCommit( - 1, - sign_commit(&key, 1, hash_1, parent_hash), - sign_commit(&key, 1, hash_2, parent_hash), - ) - )); - } -} diff --git a/core/consensus/rhd/src/service.rs b/core/consensus/rhd/src/service.rs deleted file mode 100644 index 641a97fe06e9b..0000000000000 --- a/core/consensus/rhd/src/service.rs +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Consensus service. - -/// Consensus service. A long running service that manages BFT agreement -/// the network. -use std::thread; -use std::time::{Duration, Instant}; -use std::sync::Arc; - -use client::{BlockchainEvents, BlockBody}; -use futures::prelude::*; -use transaction_pool::txpool::{Pool as TransactionPool, ChainApi as PoolChainApi}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, BlockNumberToHash}; - -use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle; -use tokio::runtime::TaskExecutor as ThreadPoolHandle; -use tokio::runtime::current_thread::Runtime as LocalRuntime; -use tokio::timer::Interval; - -use parking_lot::RwLock; -use consensus::{self, offline_tracker::OfflineTracker}; - -use super::{Network, ProposerFactory, AuthoringApi}; -use {consensus, primitives, ed25519, error, BftService, LocalProposer}; - -const TIMER_DELAY_MS: u64 = 5000; -const TIMER_INTERVAL_MS: u64 = 500; - -// spin up an instance of BFT agreement on the current thread's executor. -// panics if there is no current thread executor. -fn start_bft( - header: ::Header, - bft_service: Arc>, -) where - F: consensus::Environment + 'static, - C: consensus::BlockImport + consensus::Authorities + 'static, - F::Error: ::std::fmt::Debug, - >::Error: ::std::fmt::Display + Into, - >::Proposer : LocalProposer, - >::Error: ::std::fmt::Display, - Block: BlockT, -{ - let mut handle = LocalThreadHandle::current(); - match bft_service.build_upon(&header) { - Ok(Some(bft_work)) => if let Err(e) = handle.spawn_local(Box::new(bft_work)) { - warn!(target: "bft", "Couldn't initialize BFT agreement: {:?}", e); - } - Ok(None) => trace!(target: "bft", "Could not start agreement on top of {}", header.hash()), - Err(e) => warn!(target: "bft", "BFT agreement error: {}", e), - } -} - -/// Consensus service. Starts working when created. -pub struct Service { - thread: Option>, - exit_signal: Option<::exit_future::Signal>, -} - -impl Service { - /// Create and start a new instance. - pub fn new( - client: Arc, - api: Arc, - network: N, - transaction_pool: Arc>, - thread_pool: ThreadPoolHandle, - key: ed25519::Pair, - block_delay: u64, - ) -> Service - where - error::Error: From<::Error>, - A: AuthoringApi + BlockNumberToHash + 'static, - P: PoolChainApi::Block> + 'static, - C: BlockchainEvents<::Block> - + BlockBody<::Block> - + consensus::SelectChain<::Block> - + consensus::BlockImport<::Block> - + consensus::Authorities<::Block> + Send + Sync + 'static, - primitives::H256: From<<::Block as BlockT>::Hash>, - <::Block as BlockT>::Hash: PartialEq + PartialEq, - N: Network::Block> + Send + 'static, - { - - let (signal, exit) = ::exit_future::signal(); - let thread = thread::spawn(move || { - let mut runtime = LocalRuntime::new().expect("Could not create local runtime"); - let key = Arc::new(key); - - let factory = ProposerFactory { - client: api.clone(), - transaction_pool: transaction_pool.clone(), - network, - handle: thread_pool.clone(), - offline: Arc::new(RwLock::new(OfflineTracker::new())), - force_delay: block_delay, - }; - let bft_service = Arc::new(BftService::new(client.clone(), key, factory)); - - let notifications = { - let client = client.clone(); - let bft_service = bft_service.clone(); - - client.import_notification_stream().for_each(move |notification| { - if notification.is_new_best { - start_bft(notification.header, bft_service.clone()); - } - Ok(()) - }) - }; - - let interval = Interval::new( - Instant::now() + Duration::from_millis(TIMER_DELAY_MS), - Duration::from_millis(TIMER_INTERVAL_MS), - ); - - let mut prev_best = match client.best_block_header() { - Ok(header) => header.hash(), - Err(e) => { - warn!("Cant's start consensus service. Error reading best block header: {:?}", e); - return; - } - }; - - let timed = { - let c = client.clone(); - let s = bft_service.clone(); - - interval.map_err(|e| debug!(target: "bft", "Timer error: {:?}", e)).for_each(move |_| { - if let Ok(best_block) = c.best_block_header() { - let hash = best_block.hash(); - - if hash == prev_best { - debug!(target: "bft", "Starting consensus round after a timeout"); - start_bft(best_block, s.clone()); - } - prev_best = hash; - } - Ok(()) - }) - }; - - runtime.spawn(notifications); - runtime.spawn(timed); - - if let Err(e) = runtime.block_on(exit) { - debug!("BFT event loop error {:?}", e); - } - }); - Service { - thread: Some(thread), - exit_signal: Some(signal), - } - } -} - -impl Drop for Service { - fn drop(&mut self) { - if let Some(signal) = self.exit_signal.take() { - signal.fire(); - } - - if let Some(thread) = self.thread.take() { - thread.join().expect("The service thread has panicked"); - } - } -} diff --git a/core/consensus/slots/Cargo.toml b/core/consensus/slots/Cargo.toml deleted file mode 100644 index 4074242502b71..0000000000000 --- a/core/consensus/slots/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "substrate-consensus-slots" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Generic slots-based utilities for consensus" -edition = "2018" -build = "build.rs" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0" } -client = { package = "substrate-client", path = "../../client" } -primitives = { package = "substrate-primitives", path = "../../primitives" } -sr-primitives = { path = "../../sr-primitives" } -substrate-telemetry = { path = "../../telemetry" } -consensus_common = { package = "substrate-consensus-common", path = "../common" } -inherents = { package = "substrate-inherents", path = "../../inherents" } -futures-preview = "0.3.0-alpha.19" -futures-timer = "0.4.0" -parking_lot = "0.9.0" -log = "0.4.8" - -[dev-dependencies] -test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } diff --git a/core/consensus/slots/build.rs b/core/consensus/slots/build.rs deleted file mode 100644 index 36730271c715e..0000000000000 --- a/core/consensus/slots/build.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::env; - -fn main() { - if let Ok(profile) = env::var("PROFILE") { - println!("cargo:rustc-cfg=build_type=\"{}\"", profile); - } -} diff --git a/core/consensus/slots/src/aux_schema.rs b/core/consensus/slots/src/aux_schema.rs deleted file mode 100644 index 186288c174432..0000000000000 --- a/core/consensus/slots/src/aux_schema.rs +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Schema for slots in the aux-db. - -use codec::{Encode, Decode}; -use client::backend::AuxStore; -use client::error::{Result as ClientResult, Error as ClientError}; -use sr_primitives::traits::Header; - -const SLOT_HEADER_MAP_KEY: &[u8] = b"slot_header_map"; -const SLOT_HEADER_START: &[u8] = b"slot_header_start"; - -/// We keep at least this number of slots in database. -pub const MAX_SLOT_CAPACITY: u64 = 1000; -/// We prune slots when they reach this number. -pub const PRUNING_BOUND: u64 = 2 * MAX_SLOT_CAPACITY; - -fn load_decode(backend: &C, key: &[u8]) -> ClientResult> - where - C: AuxStore, - T: Decode, -{ - match backend.get_aux(key)? { - None => Ok(None), - Some(t) => T::decode(&mut &t[..]) - .map_err( - |e| ClientError::Backend(format!("Slots DB is corrupted. Decode error: {}", e.what())), - ) - .map(Some) - } -} - -/// Represents an equivocation proof. -#[derive(Debug, Clone)] -pub struct EquivocationProof { - slot: u64, - fst_header: H, - snd_header: H, -} - -impl EquivocationProof { - /// Get the slot number where the equivocation happened. - pub fn slot(&self) -> u64 { - self.slot - } - - /// Get the first header involved in the equivocation. - pub fn fst_header(&self) -> &H { - &self.fst_header - } - - /// Get the second header involved in the equivocation. - pub fn snd_header(&self) -> &H { - &self.snd_header - } -} - -/// Checks if the header is an equivocation and returns the proof in that case. -/// -/// Note: it detects equivocations only when slot_now - slot <= MAX_SLOT_CAPACITY. -pub fn check_equivocation( - backend: &C, - slot_now: u64, - slot: u64, - header: &H, - signer: &P, -) -> ClientResult>> - where - H: Header, - C: AuxStore, - P: Clone + Encode + Decode + PartialEq, -{ - // We don't check equivocations for old headers out of our capacity. - if slot_now - slot > MAX_SLOT_CAPACITY { - return Ok(None) - } - - // Key for this slot. - let mut curr_slot_key = SLOT_HEADER_MAP_KEY.to_vec(); - slot.using_encoded(|s| curr_slot_key.extend(s)); - - // Get headers of this slot. - let mut headers_with_sig = load_decode::<_, Vec<(H, P)>>(backend, &curr_slot_key[..])? - .unwrap_or_else(Vec::new); - - // Get first slot saved. - let slot_header_start = SLOT_HEADER_START.to_vec(); - let first_saved_slot = load_decode::<_, u64>(backend, &slot_header_start[..])? - .unwrap_or(slot); - - for (prev_header, prev_signer) in headers_with_sig.iter() { - // A proof of equivocation consists of two headers: - // 1) signed by the same voter, - if prev_signer == signer { - // 2) with different hash - if header.hash() != prev_header.hash() { - return Ok(Some(EquivocationProof { - slot, // 3) and mentioning the same slot. - fst_header: prev_header.clone(), - snd_header: header.clone(), - })); - } else { - // We don't need to continue in case of duplicated header, - // since it's already saved and a possible equivocation - // would have been detected before. - return Ok(None) - } - } - } - - let mut keys_to_delete = vec![]; - let mut new_first_saved_slot = first_saved_slot; - - if slot_now - first_saved_slot >= PRUNING_BOUND { - let prefix = SLOT_HEADER_MAP_KEY.to_vec(); - new_first_saved_slot = slot_now.saturating_sub(MAX_SLOT_CAPACITY); - - for s in first_saved_slot..new_first_saved_slot { - let mut p = prefix.clone(); - s.using_encoded(|s| p.extend(s)); - keys_to_delete.push(p); - } - } - - headers_with_sig.push((header.clone(), signer.clone())); - - backend.insert_aux( - &[ - (&curr_slot_key[..], headers_with_sig.encode().as_slice()), - (&slot_header_start[..], new_first_saved_slot.encode().as_slice()), - ], - &keys_to_delete.iter().map(|k| &k[..]).collect::>()[..], - )?; - - Ok(None) -} - -#[cfg(test)] -mod test { - use primitives::{sr25519, Pair}; - use primitives::hash::H256; - use sr_primitives::testing::{Header as HeaderTest, Digest as DigestTest}; - use test_client; - - use super::{MAX_SLOT_CAPACITY, PRUNING_BOUND, check_equivocation}; - - fn create_header(number: u64) -> HeaderTest { - // so that different headers for the same number get different hashes - let parent_hash = H256::random(); - - let header = HeaderTest { - parent_hash, - number, - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: DigestTest { logs: vec![], }, - }; - - header - } - - #[test] - fn check_equivocation_works() { - let client = test_client::new(); - let (pair, _seed) = sr25519::Pair::generate(); - let public = pair.public(); - - let header1 = create_header(1); // @ slot 2 - let header2 = create_header(2); // @ slot 2 - let header3 = create_header(2); // @ slot 4 - let header4 = create_header(3); // @ slot MAX_SLOT_CAPACITY + 4 - let header5 = create_header(4); // @ slot MAX_SLOT_CAPACITY + 4 - let header6 = create_header(3); // @ slot 4 - - // It's ok to sign same headers. - assert!( - check_equivocation( - &client, - 2, - 2, - &header1, - &public, - ).unwrap().is_none(), - ); - - assert!( - check_equivocation( - &client, - 3, - 2, - &header1, - &public, - ).unwrap().is_none(), - ); - - // But not two different headers at the same slot. - assert!( - check_equivocation( - &client, - 4, - 2, - &header2, - &public, - ).unwrap().is_some(), - ); - - // Different slot is ok. - assert!( - check_equivocation( - &client, - 5, - 4, - &header3, - &public, - ).unwrap().is_none(), - ); - - // Here we trigger pruning and save header 4. - assert!( - check_equivocation( - &client, - PRUNING_BOUND + 2, - MAX_SLOT_CAPACITY + 4, - &header4, - &public, - ).unwrap().is_none(), - ); - - // This fails because header 5 is an equivocation of header 4. - assert!( - check_equivocation( - &client, - PRUNING_BOUND + 3, - MAX_SLOT_CAPACITY + 4, - &header5, - &public, - ).unwrap().is_some(), - ); - - // This is ok because we pruned the corresponding header. Shows that we are pruning. - assert!( - check_equivocation( - &client, - PRUNING_BOUND + 4, - 4, - &header6, - &public, - ).unwrap().is_none(), - ); - } -} diff --git a/core/consensus/slots/src/lib.rs b/core/consensus/slots/src/lib.rs deleted file mode 100644 index e33d00d25531f..0000000000000 --- a/core/consensus/slots/src/lib.rs +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Slots functionality for Substrate. -//! -//! Some consensus algorithms have a concept of *slots*, which are intervals in -//! time during which certain events can and/or must occur. This crate -//! provides generic functionality for slots. - -#![deny(warnings)] -#![forbid(unsafe_code, missing_docs)] - -mod slots; -mod aux_schema; - -pub use slots::{SignedDuration, SlotInfo}; -use slots::Slots; -pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND}; - -use codec::{Decode, Encode}; -use consensus_common::{BlockImport, Proposer, SyncOracle, SelectChain}; -use futures::{prelude::*, future::{self, Either}}; -use futures_timer::Delay; -use inherents::{InherentData, InherentDataProviders}; -use log::{debug, error, info, warn}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ApiRef, Block as BlockT, Header, ProvideRuntimeApi}; -use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc}; -use substrate_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; -use parking_lot::Mutex; - -/// A worker that should be invoked at every new slot. -pub trait SlotWorker { - /// The type of the future that will be returned when a new slot is - /// triggered. - type OnSlot: Future>; - - /// Called when a new slot is triggered. - fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot; -} - -/// A skeleton implementation for `SlotWorker` which tries to claim a slot at -/// its beginning and tries to produce a block if successfully claimed, timing -/// out if block production takes too long. -pub trait SimpleSlotWorker { - /// A handle to a `BlockImport`. - type BlockImport: BlockImport + Send + 'static; - - /// A handle to a `SyncOracle`. - type SyncOracle: SyncOracle; - - /// The type of proposer to use to build blocks. - type Proposer: Proposer; - - /// Data associated with a slot claim. - type Claim: Send + 'static; - - /// Epoch data necessary for authoring. - type EpochData; - - /// The logging target to use when logging messages. - fn logging_target(&self) -> &'static str; - - /// A handle to a `BlockImport`. - fn block_import(&self) -> Arc>; - - /// Returns the epoch data necessary for authoring. For time-dependent epochs, - /// use the provided slot number as a canonical source of time. - fn epoch_data(&self, header: &B::Header, slot_number: u64) -> Result; - - /// Returns the number of authorities given the epoch data. - fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize; - - /// Tries to claim the given slot, returning an object with claim data if successful. - fn claim_slot( - &self, - header: &B::Header, - slot_number: u64, - epoch_data: &Self::EpochData, - ) -> Option; - - /// Return the pre digest data to include in a block authored with the given claim. - fn pre_digest_data(&self, slot_number: u64, claim: &Self::Claim) -> Vec>; - - /// Returns a function which produces a `BlockImportParams`. - fn block_import_params(&self) -> Box, - Self::Claim, - ) -> consensus_common::BlockImportParams + Send>; - - /// Whether to force authoring if offline. - fn force_authoring(&self) -> bool; - - /// Returns a handle to a `SyncOracle`. - fn sync_oracle(&mut self) -> &mut Self::SyncOracle; - - /// Returns a `Proposer` to author on top of the given block. - fn proposer(&mut self, block: &B::Header) -> Result; - - /// Implements the `on_slot` functionality from `SlotWorker`. - fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) - -> Pin> + Send>> where - Self: Send + Sync, - >::Create: Unpin + Send + 'static, - { - let (timestamp, slot_number, slot_duration) = - (slot_info.timestamp, slot_info.number, slot_info.duration); - - let epoch_data = match self.epoch_data(&chain_head, slot_number) { - Ok(epoch_data) => epoch_data, - Err(err) => { - warn!("Unable to fetch epoch data at block {:?}: {:?}", chain_head.hash(), err); - - telemetry!( - CONSENSUS_WARN; "slots.unable_fetching_authorities"; - "slot" => ?chain_head.hash(), - "err" => ?err, - ); - - return Box::pin(future::ready(Ok(()))); - } - }; - - let authorities_len = self.authorities_len(&epoch_data); - - if !self.force_authoring() && self.sync_oracle().is_offline() && authorities_len > 1 { - debug!(target: self.logging_target(), "Skipping proposal slot. Waiting for the network."); - telemetry!( - CONSENSUS_DEBUG; - "slots.skipping_proposal_slot"; - "authorities_len" => authorities_len, - ); - - return Box::pin(future::ready(Ok(()))); - } - - let claim = match self.claim_slot(&chain_head, slot_number, &epoch_data) { - None => return Box::pin(future::ready(Ok(()))), - Some(claim) => claim, - }; - - debug!( - target: self.logging_target(), "Starting authorship at slot {}; timestamp = {}", - slot_number, - timestamp, - ); - - telemetry!(CONSENSUS_DEBUG; "slots.starting_authorship"; - "slot_num" => slot_number, - "timestamp" => timestamp, - ); - - let mut proposer = match self.proposer(&chain_head) { - Ok(proposer) => proposer, - Err(err) => { - warn!("Unable to author block in slot {:?}: {:?}", slot_number, err); - - telemetry!(CONSENSUS_WARN; "slots.unable_authoring_block"; - "slot" => slot_number, "err" => ?err - ); - - return Box::pin(future::ready(Ok(()))); - }, - }; - - let remaining_duration = slot_info.remaining_duration(); - let logs = self.pre_digest_data(slot_number, &claim); - - // deadline our production to approx. the end of the slot - let proposal_work = futures::future::select( - proposer.propose( - slot_info.inherent_data, - sr_primitives::generic::Digest { - logs, - }, - remaining_duration, - ).map_err(|e| consensus_common::Error::ClientImport(format!("{:?}", e))), - Delay::new(remaining_duration) - .map_err(consensus_common::Error::FaultyTimer) - ).map(|v| match v { - futures::future::Either::Left((b, _)) => b.map(|b| (b, claim)), - futures::future::Either::Right((Ok(_), _)) => - Err(consensus_common::Error::ClientImport("Timeout in the Slots proposer".into())), - futures::future::Either::Right((Err(err), _)) => Err(err), - }); - - let block_import_params_maker = self.block_import_params(); - let block_import = self.block_import(); - let logging_target = self.logging_target(); - - Box::pin(proposal_work.map_ok(move |(block, claim)| { - // minor hack since we don't have access to the timestamp - // that is actually set by the proposer. - let slot_after_building = SignedDuration::default().slot_now(slot_duration); - if slot_after_building != slot_number { - info!("Discarding proposal for slot {}; block production took too long", slot_number); - // If the node was compiled with debug, tell the user to use release optimizations. - #[cfg(build_type="debug")] - info!("Recompile your node in `--release` mode to mitigate this problem."); - telemetry!(CONSENSUS_INFO; "slots.discarding_proposal_took_too_long"; - "slot" => slot_number, - ); - - return; - } - - let (header, body) = block.deconstruct(); - let header_num = *header.number(); - let header_hash = header.hash(); - let parent_hash = *header.parent_hash(); - - let block_import_params = block_import_params_maker( - header, - &header_hash, - body, - claim, - ); - - info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", - header_num, - block_import_params.post_header().hash(), - header_hash, - ); - - telemetry!(CONSENSUS_INFO; "slots.pre_sealed_block"; - "header_num" => ?header_num, - "hash_now" => ?block_import_params.post_header().hash(), - "hash_previously" => ?header_hash, - ); - - if let Err(err) = block_import.lock().import_block(block_import_params, Default::default()) { - warn!(target: logging_target, - "Error with block built on {:?}: {:?}", - parent_hash, - err, - ); - - telemetry!(CONSENSUS_WARN; "slots.err_with_block_built_on"; - "hash" => ?parent_hash, "err" => ?err, - ); - } - })) - } -} - -/// Slot compatible inherent data. -pub trait SlotCompatible { - /// Extract timestamp and slot from inherent data. - fn extract_timestamp_and_slot( - &self, - inherent: &InherentData, - ) -> Result<(u64, u64, std::time::Duration), consensus_common::Error>; - - /// Get the difference between chain time and local time. Defaults to - /// always returning zero. - fn time_offset() -> SignedDuration { Default::default() } -} - -/// Start a new slot worker. -/// -/// Every time a new slot is triggered, `worker.on_slot` is called and the future it returns is -/// polled until completion, unless we are major syncing. -pub fn start_slot_worker( - slot_duration: SlotDuration, - client: C, - mut worker: W, - mut sync_oracle: SO, - inherent_data_providers: InherentDataProviders, - timestamp_extractor: SC, -) -> impl Future -where - B: BlockT, - C: SelectChain + Clone, - W: SlotWorker, - W::OnSlot: Unpin, - SO: SyncOracle + Send + Clone, - SC: SlotCompatible + Unpin, - T: SlotData + Clone, -{ - let SlotDuration(slot_duration) = slot_duration; - - // rather than use a timer interval, we schedule our waits ourselves - Slots::::new( - slot_duration.slot_duration(), - inherent_data_providers, - timestamp_extractor, - ).inspect_err(|e| debug!(target: "slots", "Faulty timer: {:?}", e)) - .try_for_each(move |slot_info| { - // only propose when we are not syncing. - if sync_oracle.is_major_syncing() { - debug!(target: "slots", "Skipping proposal slot due to sync."); - return Either::Right(future::ready(Ok(()))); - } - - let slot_num = slot_info.number; - let chain_head = match client.best_chain() { - Ok(x) => x, - Err(e) => { - warn!(target: "slots", "Unable to author block in slot {}. \ - no best block header: {:?}", slot_num, e); - return Either::Right(future::ready(Ok(()))); - } - }; - - Either::Left(worker.on_slot(chain_head, slot_info).map_err( - |e| { - warn!(target: "slots", "Encountered consensus error: {:?}", e); - }).or_else(|_| future::ready(Ok(()))) - ) - }).then(|res| { - if let Err(err) = res { - warn!(target: "slots", "Slots stream terminated with an error: {:?}", err); - } - future::ready(()) - }) -} - -/// 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. - /// - /// Includes the digest item that encoded the seal. - Checked(H, S), -} - -/// A type from which a slot duration can be obtained. -pub trait SlotData { - /// Gets the slot duration. - fn slot_duration(&self) -> u64; - - /// The static slot key - const SLOT_KEY: &'static [u8]; -} - -impl SlotData for u64 { - fn slot_duration(&self) -> u64 { - *self - } - - const SLOT_KEY: &'static [u8] = b"aura_slot_duration"; -} - -/// A slot duration. Create with `get_or_compute`. -// The internal member should stay private here to maintain invariants of -// `get_or_compute`. -#[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct SlotDuration(T); - -impl Deref for SlotDuration { - type Target = T; - fn deref(&self) -> &T { - &self.0 - } -} - -impl SlotData for SlotDuration { - /// Get the slot duration in milliseconds. - fn slot_duration(&self) -> u64 - where T: SlotData, - { - self.0.slot_duration() - } - - const SLOT_KEY: &'static [u8] = T::SLOT_KEY; -} - -impl SlotDuration { - /// Either fetch the slot duration from disk or compute it from the - /// genesis state. - /// - /// `slot_key` is marked as `'static`, as it should really be a - /// compile-time constant. - pub fn get_or_compute(client: &C, cb: CB) -> ::client::error::Result where - C: client::backend::AuxStore, - C: ProvideRuntimeApi, - CB: FnOnce(ApiRef, &BlockId) -> ::client::error::Result, - T: SlotData + Encode + Decode + Debug, - { - match client.get_aux(T::SLOT_KEY)? { - Some(v) => ::decode(&mut &v[..]) - .map(SlotDuration) - .map_err(|_| { - client::error::Error::Backend({ - error!(target: "slots", "slot duration kept in invalid format"); - "slot duration kept in invalid format".to_string() - }) - }), - None => { - use sr_primitives::traits::Zero; - let genesis_slot_duration = - cb(client.runtime_api(), &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(&[(T::SLOT_KEY, &s[..])], &[]))?; - - Ok(SlotDuration(genesis_slot_duration)) - } - } - } - - /// Returns slot data value. - pub fn get(&self) -> T { - self.0.clone() - } -} diff --git a/core/consensus/uncles/Cargo.toml b/core/consensus/uncles/Cargo.toml deleted file mode 100644 index 4820324870929..0000000000000 --- a/core/consensus/uncles/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "substrate-consensus-uncles" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Generic uncle inclusion utilities for consensus" -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../../client" } -primitives = { package = "substrate-primitives", path = "../../primitives" } -sr-primitives = { path = "../../sr-primitives" } -srml-authorship = { path = "../../../srml/authorship" } -consensus_common = { package = "substrate-consensus-common", path = "../common" } -inherents = { package = "substrate-inherents", path = "../../inherents" } -log = "0.4.8" diff --git a/core/consensus/uncles/src/lib.rs b/core/consensus/uncles/src/lib.rs deleted file mode 100644 index 5638a23175d56..0000000000000 --- a/core/consensus/uncles/src/lib.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Uncles functionality for Substrate. -//! -#![deny(warnings)] -#![forbid(unsafe_code, missing_docs)] - -use consensus_common::SelectChain; -use inherents::{InherentDataProviders}; -use log::warn; -use client::ProvideUncles; -use sr_primitives::traits::{Block as BlockT, Header}; -use std::sync::Arc; - -/// Maximum uncles generations we may provide to the runtime. -const MAX_UNCLE_GENERATIONS: u32 = 8; - -/// Register uncles inherent data provider, if not registered already. -pub fn register_uncles_inherent_data_provider( - client: Arc, - select_chain: SC, - inherent_data_providers: &InherentDataProviders, -) -> Result<(), consensus_common::Error> where - B: BlockT, - C: ProvideUncles + Send + Sync + 'static, - SC: SelectChain + 'static, -{ - if !inherent_data_providers.has_provider(&srml_authorship::INHERENT_IDENTIFIER) { - inherent_data_providers - .register_provider(srml_authorship::InherentDataProvider::new(move || { - { - let chain_head = match select_chain.best_chain() { - Ok(x) => x, - Err(e) => { - warn!(target: "uncles", "Unable to get chain head: {:?}", e); - return Vec::new(); - } - }; - match client.uncles(chain_head.hash(), MAX_UNCLE_GENERATIONS.into()) { - Ok(uncles) => uncles, - Err(e) => { - warn!(target: "uncles", "Unable to get uncles: {:?}", e); - Vec::new() - } - } - } - })) - .map_err(|err| consensus_common::Error::InherentData(err.into()))?; - } - Ok(()) -} - diff --git a/core/executor/Cargo.toml b/core/executor/Cargo.toml deleted file mode 100644 index cf3ea4ff7a6e7..0000000000000 --- a/core/executor/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "substrate-executor" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -derive_more = "0.15.0" -codec = { package = "parity-scale-codec", version = "1.0.0" } -runtime_io = { package = "sr-io", path = "../sr-io" } -primitives = { package = "substrate-primitives", path = "../primitives" } -trie = { package = "substrate-trie", path = "../trie" } -serializer = { package = "substrate-serializer", path = "../serializer" } -runtime_version = { package = "sr-version", path = "../sr-version" } -panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } -wasmi = "0.5.1" -parity-wasm = "0.40.3" -lazy_static = "1.4.0" -wasm-interface = { package = "substrate-wasm-interface", path = "../wasm-interface" } -externalities = { package = "substrate-externalities", path = "../externalities" } -parking_lot = "0.9.0" -log = "0.4.8" -libsecp256k1 = "0.3.0" -tiny-keccak = "1.5.0" - -[dev-dependencies] -assert_matches = "1.3.0" -wabt = "0.9.2" -hex-literal = "0.2.1" -runtime-test = { package = "substrate-runtime-test", path = "runtime-test" } -substrate-client = { path = "../client" } -substrate-offchain = { path = "../offchain/" } -state_machine = { package = "substrate-state-machine", path = "../state-machine" } - -[features] -default = [] -wasm-extern-trace = [] diff --git a/core/executor/runtime-test/Cargo.toml b/core/executor/runtime-test/Cargo.toml deleted file mode 100644 index 72041218bf9f2..0000000000000 --- a/core/executor/runtime-test/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "substrate-runtime-test" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -build = "build.rs" - -[dependencies] -rstd = { package = "sr-std", path = "../../sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../sr-io", default-features = false } -sandbox = { package = "sr-sandbox", path = "../../sr-sandbox", default-features = false } -primitives = { package = "substrate-primitives", path = "../../primitives", default-features = false } -sr-primitives = { package = "sr-primitives", path = "../../sr-primitives", default-features = false } - -[build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.4", path = "../../utils/wasm-builder-runner" } - -[features] -default = [ "std" ] -std = ["runtime_io/std", "sandbox/std", "rstd/std"] diff --git a/core/executor/runtime-test/build.rs b/core/executor/runtime-test/build.rs deleted file mode 100644 index 68e5205f0c7a8..0000000000000 --- a/core/executor/runtime-test/build.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; - -fn main() { - build_current_project_with_rustflags( - "wasm_binary.rs", - WasmBuilderSource::CratesOrPath { - path: "../../utils/wasm-builder", - version: "1.0.8", - }, - // This instructs LLD to export __heap_base as a global variable, which is used by the - // external memory allocator. - "-Clink-arg=--export=__heap_base", - ); -} diff --git a/core/executor/runtime-test/src/lib.rs b/core/executor/runtime-test/src/lib.rs deleted file mode 100644 index 61eca8dd4e23f..0000000000000 --- a/core/executor/runtime-test/src/lib.rs +++ /dev/null @@ -1,245 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "strict", deny(warnings))] - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -#[cfg(not(feature = "std"))] -use rstd::{vec::Vec, vec}; - -#[cfg(not(feature = "std"))] -use runtime_io::{ - set_storage, storage, clear_prefix, blake2_128, blake2_256, - twox_128, twox_256, ed25519_verify, sr25519_verify, -}; -#[cfg(not(feature = "std"))] -use sr_primitives::{print, traits::{BlakeTwo256, Hash}}; -#[cfg(not(feature = "std"))] -use primitives::{ed25519, sr25519}; - -primitives::wasm_export_functions! { - fn test_data_in(input: Vec) -> Vec { - print("set_storage"); - set_storage(b"input", &input); - - print("storage"); - let foo = storage(b"foo").unwrap(); - - print("set_storage"); - set_storage(b"baz", &foo); - - print("finished!"); - b"all ok!".to_vec() - } - - fn test_clear_prefix(input: Vec) -> Vec { - clear_prefix(&input); - b"all ok!".to_vec() - } - - fn test_empty_return() {} - - fn test_exhaust_heap() -> Vec { Vec::with_capacity(16777216) } - - fn test_panic() { panic!("test panic") } - - fn test_conditional_panic(input: Vec) -> Vec { - if input.len() > 0 { - panic!("test panic") - } - - input - } - - fn test_blake2_256(input: Vec) -> Vec { - blake2_256(&input).to_vec() - } - - fn test_blake2_128(input: Vec) -> Vec { - blake2_128(&input).to_vec() - } - - fn test_twox_256(input: Vec) -> Vec { - twox_256(&input).to_vec() - } - - fn test_twox_128(input: Vec) -> Vec { - twox_128(&input).to_vec() - } - - fn test_ed25519_verify(input: Vec) -> bool { - let mut pubkey = [0; 32]; - let mut sig = [0; 64]; - - pubkey.copy_from_slice(&input[0..32]); - sig.copy_from_slice(&input[32..96]); - - let msg = b"all ok!"; - ed25519_verify(&ed25519::Signature(sig), &msg[..], &ed25519::Public(pubkey)) - } - - fn test_sr25519_verify(input: Vec) -> bool { - let mut pubkey = [0; 32]; - let mut sig = [0; 64]; - - pubkey.copy_from_slice(&input[0..32]); - sig.copy_from_slice(&input[32..96]); - - let msg = b"all ok!"; - sr25519_verify(&sr25519::Signature(sig), &msg[..], &sr25519::Public(pubkey)) - } - - fn test_ordered_trie_root() -> Vec { - BlakeTwo256::ordered_trie_root( - vec![ - b"zero"[..].into(), - b"one"[..].into(), - b"two"[..].into(), - ], - ).as_ref().to_vec() - } - - fn test_sandbox(code: Vec) -> bool { - execute_sandboxed(&code, &[]).is_ok() - } - - fn test_sandbox_args(code: Vec) -> bool { - execute_sandboxed( - &code, - &[ - sandbox::TypedValue::I32(0x12345678), - sandbox::TypedValue::I64(0x1234567887654321), - ], - ).is_ok() - } - - fn test_sandbox_return_val(code: Vec) -> bool { - let ok = match execute_sandboxed( - &code, - &[ - sandbox::TypedValue::I32(0x1336), - ] - ) { - Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(0x1337))) => true, - _ => false, - }; - - ok - } - - fn test_sandbox_instantiate(code: Vec) -> u8 { - let env_builder = sandbox::EnvironmentDefinitionBuilder::new(); - let code = match sandbox::Instance::new(&code, &env_builder, &mut ()) { - Ok(_) => 0, - Err(sandbox::Error::Module) => 1, - Err(sandbox::Error::Execution) => 2, - Err(sandbox::Error::OutOfBounds) => 3, - }; - - code - } - - fn test_offchain_local_storage() -> bool { - let kind = primitives::offchain::StorageKind::PERSISTENT; - assert_eq!(runtime_io::local_storage_get(kind, b"test"), None); - runtime_io::local_storage_set(kind, b"test", b"asd"); - assert_eq!(runtime_io::local_storage_get(kind, b"test"), Some(b"asd".to_vec())); - - let res = runtime_io::local_storage_compare_and_set(kind, b"test", Some(b"asd"), b""); - assert_eq!(runtime_io::local_storage_get(kind, b"test"), Some(b"".to_vec())); - res - } - - fn test_offchain_local_storage_with_none() { - let kind = primitives::offchain::StorageKind::PERSISTENT; - assert_eq!(runtime_io::local_storage_get(kind, b"test"), None); - - let res = runtime_io::local_storage_compare_and_set(kind, b"test", None, b"value"); - assert_eq!(res, true); - assert_eq!(runtime_io::local_storage_get(kind, b"test"), Some(b"value".to_vec())); - } - - fn test_offchain_http() -> bool { - use primitives::offchain::HttpRequestStatus; - let run = || -> Option<()> { - let id = runtime_io::http_request_start("POST", "http://localhost:12345", &[]).ok()?; - runtime_io::http_request_add_header(id, "X-Auth", "test").ok()?; - runtime_io::http_request_write_body(id, &[1, 2, 3, 4], None).ok()?; - runtime_io::http_request_write_body(id, &[], None).ok()?; - let status = runtime_io::http_response_wait(&[id], None); - assert!(status == vec![HttpRequestStatus::Finished(200)], "Expected Finished(200) status."); - let headers = runtime_io::http_response_headers(id); - assert_eq!(headers, vec![(b"X-Auth".to_vec(), b"hello".to_vec())]); - let mut buffer = vec![0; 64]; - let read = runtime_io::http_response_read_body(id, &mut buffer, None).ok()?; - assert_eq!(read, 3); - assert_eq!(&buffer[0..read], &[1, 2, 3]); - let read = runtime_io::http_response_read_body(id, &mut buffer, None).ok()?; - assert_eq!(read, 0); - - Some(()) - }; - - run().is_some() - } - } - -#[cfg(not(feature = "std"))] -fn execute_sandboxed( - code: &[u8], - args: &[sandbox::TypedValue], -) -> Result { - struct State { - counter: u32, - } - - fn env_assert( - _e: &mut State, - args: &[sandbox::TypedValue], - ) -> Result { - if args.len() != 1 { - return Err(sandbox::HostError); - } - let condition = args[0].as_i32().ok_or_else(|| sandbox::HostError)?; - if condition != 0 { - Ok(sandbox::ReturnValue::Unit) - } else { - Err(sandbox::HostError) - } - } - fn env_inc_counter( - e: &mut State, - args: &[sandbox::TypedValue], - ) -> Result { - if args.len() != 1 { - return Err(sandbox::HostError); - } - let inc_by = args[0].as_i32().ok_or_else(|| sandbox::HostError)?; - e.counter += inc_by as u32; - Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(e.counter as i32))) - } - - let mut state = State { counter: 0 }; - - let env_builder = { - let mut env_builder = sandbox::EnvironmentDefinitionBuilder::new(); - env_builder.add_host_func("env", "assert", env_assert); - env_builder.add_host_func("env", "inc_counter", env_inc_counter); - let memory = match sandbox::Memory::new(1, Some(16)) { - Ok(m) => m, - Err(_) => unreachable!(" - Memory::new() can return Err only if parameters are borked; \ - We passing params here explicitly and they're correct; \ - Memory::new() can't return a Error qed" - ), - }; - env_builder.add_memory("env", "memory", memory.clone()); - env_builder - }; - - let mut instance = sandbox::Instance::new(code, &env_builder, &mut state)?; - let result = instance.invoke(b"call", args, &mut state); - - result.map_err(|_| sandbox::HostError) -} diff --git a/core/executor/src/error.rs b/core/executor/src/error.rs deleted file mode 100644 index e1221bea54aef..0000000000000 --- a/core/executor/src/error.rs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Rust executor possible errors. - -use serializer; -use wasmi; - -/// Result type alias. -pub type Result = std::result::Result; - -/// Error type. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Unserializable Data - InvalidData(serializer::Error), - /// Trap occured during execution - Trap(wasmi::Trap), - /// Wasmi loading/instantiating error - Wasmi(wasmi::Error), - /// Error in the API. Parameter is an error message. - ApiError(String), - /// Method is not found - #[display(fmt="Method not found: '{}'", _0)] - MethodNotFound(String), - /// Code is invalid (expected single byte) - #[display(fmt="Invalid Code: {}", _0)] - InvalidCode(String), - /// Could not get runtime version. - #[display(fmt="On-chain runtime does not specify version")] - VersionInvalid, - /// Externalities have failed. - #[display(fmt="Externalities error")] - Externalities, - /// Invalid index. - #[display(fmt="Invalid index provided")] - InvalidIndex, - /// Invalid return type. - #[display(fmt="Invalid type returned (should be u64)")] - InvalidReturn, - /// Runtime failed. - #[display(fmt="Runtime error")] - Runtime, - /// Invalid memory reference. - #[display(fmt="Invalid memory reference")] - InvalidMemoryReference, - /// The runtime must provide a global named `__heap_base` of type i32 for specifying where the - /// allocator is allowed to place its data. - #[display(fmt="The runtime doesn't provide a global named `__heap_base`")] - HeapBaseNotFoundOrInvalid, - /// The runtime WebAssembly module is not allowed to have the `start` function. - #[display(fmt="The runtime has the `start` function")] - RuntimeHasStartFn, - /// Some other error occurred - Other(String), - /// Some error occurred in the allocator - #[display(fmt="Error in allocator: {}", _0)] - Allocator(&'static str), - /// The allocator ran out of space. - #[display(fmt="Allocator ran out of space")] - AllocatorOutOfSpace, - /// Someone tried to allocate more memory than the allowed maximum per allocation. - #[display(fmt="Requested allocation size is too large")] - RequestedAllocationTooLarge, - /// Executing the given function failed with the given error. - #[display(fmt="Function execution failed with: {}", _0)] - FunctionExecution(String), -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::InvalidData(ref err) => Some(err), - Error::Trap(ref err) => Some(err), - Error::Wasmi(ref err) => Some(err), - _ => None, - } - } -} - -impl wasmi::HostError for Error {} - -impl From for Error { - fn from(err: String) -> Error { - Error::Other(err) - } -} - -impl From for Error { - fn from(err: WasmError) -> Error { - Error::Other(err.to_string()) - } -} - -/// Type for errors occurring during Wasm runtime construction. -#[derive(Debug, derive_more::Display)] -pub enum WasmError { - /// Code could not be read from the state. - CodeNotFound, - /// Failure to reinitialize runtime instance from snapshot. - ApplySnapshotFailed, - /// Wasm code failed validation. - InvalidModule, - /// Wasm code could not be deserialized. - CantDeserializeWasm, - /// Instantiation error. - Instantiation(Error), -} diff --git a/core/executor/src/host_interface.rs b/core/executor/src/host_interface.rs deleted file mode 100644 index 7d87d93333fd2..0000000000000 --- a/core/executor/src/host_interface.rs +++ /dev/null @@ -1,1175 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Definition and implementation of the Substrate Wasm host interface. -//! -//! These are the host functions callable from within the Substrate runtime. - -use crate::error::{Error, Result}; - -use codec::Encode; -use std::{convert::TryFrom, str, panic}; -use primitives::{ - blake2_128, blake2_256, twox_64, twox_128, twox_256, ed25519, sr25519, Blake2Hasher, Pair, - crypto::KeyTypeId, offchain, -}; -use trie::{TrieConfiguration, trie_types::Layout}; -use wasm_interface::{FunctionContext, Pointer, PointerType, Result as WResult, WordSize}; - -#[cfg(feature="wasm-extern-trace")] -macro_rules! debug_trace { - ( $( $x:tt )* ) => ( trace!( $( $x )* ) ) -} - -#[cfg(not(feature="wasm-extern-trace"))] -macro_rules! debug_trace { - ( $( $x:tt )* ) => () -} - -pub struct SubstrateExternals; - -enum RecoverResult { - Invalid(u32), - Valid(secp256k1::PublicKey), -} - -fn secp256k1_recover( - context: &mut dyn FunctionContext, - msg_data: Pointer, - sig_data: Pointer, -) -> WResult { - let mut sig = [0u8; 65]; - context.read_memory_into(sig_data, &mut sig[..]) - .map_err(|_| "Invalid attempt to get signature in ext_secp256k1_ecdsa_recover")?; - let rs = match secp256k1::Signature::parse_slice(&sig[0..64]) { - Ok(rs) => rs, - _ => return Ok(RecoverResult::Invalid(1)), - }; - - let recovery_id = if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8; - let v = match secp256k1::RecoveryId::parse(recovery_id) { - Ok(v) => v, - _ => return Ok(RecoverResult::Invalid(2)), - }; - - let mut msg = [0u8; 32]; - context.read_memory_into(msg_data, &mut msg[..]) - .map_err(|_| "Invalid attempt to get message in ext_secp256k1_ecdsa_recover")?; - - Ok(match secp256k1::recover(&secp256k1::Message::parse(&msg), &rs, &v) { - Ok(pubkey) => RecoverResult::Valid(pubkey), - Err(_) => RecoverResult::Invalid(3), - }) -} - -impl_wasm_host_interface! { - impl SubstrateExternals where context { - ext_malloc(size: WordSize) -> Pointer { - let r = context.allocate_memory(size)?; - debug_trace!(target: "sr-io", "malloc {} bytes at {:?}", size, r); - Ok(r) - } - - ext_free(addr: Pointer) { - context.deallocate_memory(addr)?; - debug_trace!(target: "sr-io", "free {:?}", addr); - Ok(()) - } - - ext_sandbox_instantiate( - dispatch_thunk_idx: u32, - wasm_ptr: Pointer, - wasm_len: WordSize, - imports_ptr: Pointer, - imports_len: WordSize, - state: u32, - ) -> u32 { - let wasm = context.read_memory(wasm_ptr, wasm_len) - .map_err(|_| "OOB while ext_sandbox_instantiate: wasm")?; - let raw_env_def = context.read_memory(imports_ptr, imports_len) - .map_err(|_| "OOB while ext_sandbox_instantiate: imports")?; - - context.sandbox().instance_new(dispatch_thunk_idx, &wasm, &raw_env_def, state) - } - - ext_sandbox_instance_teardown(instance_idx: u32) { - context.sandbox().instance_teardown(instance_idx) - } - - ext_sandbox_invoke( - instance_idx: u32, - export_ptr: Pointer, - export_len: WordSize, - args_ptr: Pointer, - args_len: WordSize, - return_val_ptr: Pointer, - return_val_len: WordSize, - state: u32, - ) -> u32 { - let export = context.read_memory(export_ptr, export_len) - .map_err(|_| "OOB while ext_sandbox_invoke: export") - .and_then(|b| - String::from_utf8(b) - .map_err(|_| "Export name should be a valid utf-8 sequence") - )?; - - // Deserialize arguments and convert them into wasmi types. - let serialized_args = context.read_memory(args_ptr, args_len) - .map_err(|_| "OOB while ext_sandbox_invoke: args")?; - - context.sandbox().invoke( - instance_idx, - &export, - &serialized_args, - return_val_ptr, - return_val_len, - state, - ) - } - - ext_sandbox_memory_new(initial: WordSize, maximum: WordSize) -> u32 { - context.sandbox().memory_new(initial, maximum) - } - - ext_sandbox_memory_get( - memory_idx: u32, - offset: WordSize, - buf_ptr: Pointer, - buf_len: WordSize, - ) -> u32 { - context.sandbox().memory_get(memory_idx, offset, buf_ptr, buf_len) - } - - ext_sandbox_memory_set( - memory_idx: u32, - offset: WordSize, - val_ptr: Pointer, - val_len: WordSize, - ) -> u32 { - context.sandbox().memory_set(memory_idx, offset, val_ptr, val_len) - } - - ext_sandbox_memory_teardown(memory_idx: u32) { - context.sandbox().memory_teardown(memory_idx) - } - - ext_print_utf8(utf8_data: Pointer, utf8_len: WordSize) { - if let Ok(utf8) = context.read_memory(utf8_data, utf8_len) { - runtime_io::print_utf8(&utf8); - } - Ok(()) - } - - ext_print_hex(data: Pointer, len: WordSize) { - if let Ok(hex) = context.read_memory(data, len) { - runtime_io::print_hex(&hex); - } - Ok(()) - } - - ext_print_num(number: u64) { - runtime_io::print_num(number); - Ok(()) - } - - ext_log( - level: u32, - target_data: Pointer, - target_len: WordSize, - message_data: Pointer, - message_len: WordSize, - ) { - let target = context.read_memory(target_data, target_len) - .map_err(|_| "Invalid attempt to determine target in ext_log")?; - let message = context.read_memory(message_data, message_len) - .map_err(|_| "Invalid attempt to determine message in ext_log")?; - - runtime_io::log(level.into(), &target, &message); - Ok(()) - } - - ext_set_storage( - key_data: Pointer, - key_len: WordSize, - value_data: Pointer, - value_len: WordSize, - ) { - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to determine key in ext_set_storage")?; - let value = context.read_memory(value_data, value_len) - .map_err(|_| "Invalid attempt to determine value in ext_set_storage")?; - with_external_storage(move || - Ok(runtime_io::set_storage(&key, &value)) - )?; - Ok(()) - } - - ext_set_child_storage( - storage_key_data: Pointer, - storage_key_len: WordSize, - key_data: Pointer, - key_len: WordSize, - value_data: Pointer, - value_len: WordSize, - ) { - let storage_key = context.read_memory(storage_key_data, storage_key_len) - .map_err(|_| "Invalid attempt to determine storage_key in ext_set_child_storage")?; - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to determine key in ext_set_child_storage")?; - let value = context.read_memory(value_data, value_len) - .map_err(|_| "Invalid attempt to determine value in ext_set_child_storage")?; - - with_external_storage(move || - Ok(runtime_io::set_child_storage(&storage_key, &key, &value)) - )?; - Ok(()) - } - - ext_clear_child_storage( - storage_key_data: Pointer, - storage_key_len: WordSize, - key_data: Pointer, - key_len: WordSize, - ) { - let storage_key = context.read_memory(storage_key_data, storage_key_len) - .map_err(|_| "Invalid attempt to determine storage_key in ext_clear_child_storage")?; - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to determine key in ext_clear_child_storage")?; - - with_external_storage(move || - Ok(runtime_io::clear_child_storage(&storage_key, &key)) - )?; - Ok(()) - } - - ext_clear_storage(key_data: Pointer, key_len: WordSize) { - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to determine key in ext_clear_storage")?; - with_external_storage(move || - Ok(runtime_io::clear_storage(&key)) - )?; - Ok(()) - } - - ext_exists_storage(key_data: Pointer, key_len: WordSize) -> u32 { - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to determine key in ext_exists_storage")?; - with_external_storage(move || - Ok(if runtime_io::exists_storage(&key) { 1 } else { 0 }) - ) - } - - ext_exists_child_storage( - storage_key_data: Pointer, - storage_key_len: WordSize, - key_data: Pointer, - key_len: WordSize, - ) -> u32 { - let storage_key = context.read_memory(storage_key_data, storage_key_len) - .map_err(|_| "Invalid attempt to determine storage_key in ext_exists_child_storage")?; - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to determine key in ext_exists_child_storage")?; - - with_external_storage(move || - Ok(if runtime_io::exists_child_storage(&storage_key, &key) { 1 } else { 0 }) - ) - } - - ext_clear_prefix(prefix_data: Pointer, prefix_len: WordSize) { - let prefix = context.read_memory(prefix_data, prefix_len) - .map_err(|_| "Invalid attempt to determine prefix in ext_clear_prefix")?; - with_external_storage(move || - Ok(runtime_io::clear_prefix(&prefix)) - )?; - Ok(()) - } - - ext_clear_child_prefix( - storage_key_data: Pointer, - storage_key_len: WordSize, - prefix_data: Pointer, - prefix_len: WordSize, - ) { - let storage_key = context.read_memory(storage_key_data, storage_key_len) - .map_err(|_| "Invalid attempt to determine storage_key in ext_clear_child_prefix")?; - let prefix = context.read_memory(prefix_data, prefix_len) - .map_err(|_| "Invalid attempt to determine prefix in ext_clear_child_prefix")?; - with_external_storage(move || - Ok(runtime_io::clear_child_prefix(&storage_key, &prefix)) - )?; - - Ok(()) - } - - ext_kill_child_storage(storage_key_data: Pointer, storage_key_len: WordSize) { - let storage_key = context.read_memory(storage_key_data, storage_key_len) - .map_err(|_| "Invalid attempt to determine storage_key in ext_kill_child_storage")?; - with_external_storage(move || - Ok(runtime_io::kill_child_storage(&storage_key)) - )?; - - Ok(()) - } - - ext_get_allocated_storage( - key_data: Pointer, - key_len: WordSize, - written_out: Pointer, - ) -> Pointer { - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to determine key in ext_get_allocated_storage")?; - let maybe_value = with_external_storage(move || - Ok(runtime_io::storage(&key)) - )?; - - if let Some(value) = maybe_value { - let offset = context.allocate_memory(value.len() as u32)?; - context.write_memory(offset, &value) - .map_err(|_| "Invalid attempt to set memory in ext_get_allocated_storage")?; - context.write_primitive(written_out, value.len() as u32) - .map_err(|_| "Invalid attempt to write written_out in ext_get_allocated_storage")?; - Ok(offset) - } else { - context.write_primitive(written_out, u32::max_value()) - .map_err(|_| "Invalid attempt to write failed written_out in ext_get_allocated_storage")?; - Ok(Pointer::null()) - } - } - - ext_get_allocated_child_storage( - storage_key_data: Pointer, - storage_key_len: WordSize, - key_data: Pointer, - key_len: WordSize, - written_out: Pointer, - ) -> Pointer { - let storage_key = context.read_memory(storage_key_data, storage_key_len) - .map_err(|_| "Invalid attempt to determine storage_key in ext_get_allocated_child_storage")?; - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to determine key in ext_get_allocated_child_storage")?; - - let maybe_value = with_external_storage(move || - Ok(runtime_io::child_storage(&storage_key, &key)) - )?; - - if let Some(value) = maybe_value { - let offset = context.allocate_memory(value.len() as u32)?; - context.write_memory(offset, &value) - .map_err(|_| "Invalid attempt to set memory in ext_get_allocated_child_storage")?; - context.write_primitive(written_out, value.len() as u32) - .map_err(|_| "Invalid attempt to write written_out in ext_get_allocated_child_storage")?; - Ok(offset) - } else { - context.write_primitive(written_out, u32::max_value()) - .map_err(|_| "Invalid attempt to write failed written_out in ext_get_allocated_child_storage")?; - Ok(Pointer::null()) - } - } - - ext_get_storage_into( - key_data: Pointer, - key_len: WordSize, - value_data: Pointer, - value_len: WordSize, - value_offset: WordSize, - ) -> WordSize { - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to get key in ext_get_storage_into")?; - let maybe_value = with_external_storage(move || - Ok(runtime_io::storage(&key)) - )?; - - if let Some(value) = maybe_value { - let data = &value[value.len().min(value_offset as usize)..]; - let written = std::cmp::min(value_len as usize, data.len()); - context.write_memory(value_data, &data[..written]) - .map_err(|_| "Invalid attempt to set value in ext_get_storage_into")?; - Ok(value.len() as u32) - } else { - Ok(u32::max_value()) - } - } - - ext_get_child_storage_into( - storage_key_data: Pointer, - storage_key_len: WordSize, - key_data: Pointer, - key_len: WordSize, - value_data: Pointer, - value_len: WordSize, - value_offset: WordSize, - ) -> WordSize { - let storage_key = context.read_memory(storage_key_data, storage_key_len) - .map_err(|_| "Invalid attempt to determine storage_key in ext_get_child_storage_into")?; - let key = context.read_memory(key_data, key_len) - .map_err(|_| "Invalid attempt to get key in ext_get_child_storage_into")?; - - let maybe_value = with_external_storage(move || - Ok(runtime_io::child_storage(&storage_key, &key)) - )?; - - if let Some(value) = maybe_value { - let data = &value[value.len().min(value_offset as usize)..]; - let written = std::cmp::min(value_len as usize, data.len()); - context.write_memory(value_data, &data[..written]) - .map_err(|_| "Invalid attempt to get value in ext_get_child_storage_into")?; - Ok(value.len() as u32) - } else { - Ok(u32::max_value()) - } - } - - ext_storage_root(result: Pointer) { - let r = with_external_storage(move || - Ok(runtime_io::storage_root()) - )?; - context.write_memory(result, r.as_ref()) - .map_err(|_| "Invalid attempt to set memory in ext_storage_root")?; - Ok(()) - } - - ext_child_storage_root( - storage_key_data: Pointer, - storage_key_len: WordSize, - written_out: Pointer, - ) -> Pointer { - let storage_key = context.read_memory(storage_key_data, storage_key_len) - .map_err(|_| "Invalid attempt to determine storage_key in ext_child_storage_root")?; - let value = with_external_storage(move || - Ok(runtime_io::child_storage_root(&storage_key)) - )?; - - let offset = context.allocate_memory(value.len() as u32)?; - context.write_memory(offset, &value) - .map_err(|_| "Invalid attempt to set memory in ext_child_storage_root")?; - context.write_primitive(written_out, value.len() as u32) - .map_err(|_| "Invalid attempt to write written_out in ext_child_storage_root")?; - Ok(offset) - } - - ext_storage_changes_root( - parent_hash_data: Pointer, - _len: WordSize, - result: Pointer, - ) -> u32 { - let mut parent_hash = [0u8; 32]; - context.read_memory_into(parent_hash_data, &mut parent_hash[..]) - .map_err(|_| "Invalid attempt to get parent_hash in ext_storage_changes_root")?; - let r = with_external_storage(move || - Ok(runtime_io::storage_changes_root(parent_hash)) - )?; - - if let Some(r) = r { - context.write_memory(result, &r[..]) - .map_err(|_| "Invalid attempt to set memory in ext_storage_changes_root")?; - Ok(1) - } else { - Ok(0) - } - } - - ext_blake2_256_enumerated_trie_root( - values_data: Pointer, - lens_data: Pointer, - lens_len: WordSize, - result: Pointer, - ) { - let values = (0..lens_len) - .map(|i| context.read_primitive(lens_data.offset(i).ok_or("Pointer overflow")?)) - .collect::, _>>()? - .into_iter() - .scan(0u32, |acc, v| { let o = *acc; *acc += v; Some((o, v)) }) - .map(|(offset, len)| - context.read_memory(values_data.offset(offset).ok_or("Pointer overflow")?, len) - .map_err(|_| - "Invalid attempt to get memory in ext_blake2_256_enumerated_trie_root" - ) - ) - .collect::, _>>()?; - let r = Layout::::ordered_trie_root(values.into_iter()); - context.write_memory(result, &r[..]) - .map_err(|_| "Invalid attempt to set memory in ext_blake2_256_enumerated_trie_root")?; - Ok(()) - } - - ext_chain_id() -> u64 { - Ok(runtime_io::chain_id()) - } - - ext_twox_64(data: Pointer, len: WordSize, out: Pointer) { - let result: [u8; 8] = if len == 0 { - let hashed = twox_64(&[0u8; 0]); - hashed - } else { - let key = context.read_memory(data, len) - .map_err(|_| "Invalid attempt to get key in ext_twox_64")?; - let hashed_key = twox_64(&key); - hashed_key - }; - - context.write_memory(out, &result) - .map_err(|_| "Invalid attempt to set result in ext_twox_64")?; - Ok(()) - } - - ext_twox_128(data: Pointer, len: WordSize, out: Pointer) { - let result: [u8; 16] = if len == 0 { - let hashed = twox_128(&[0u8; 0]); - hashed - } else { - let key = context.read_memory(data, len) - .map_err(|_| "Invalid attempt to get key in ext_twox_128")?; - let hashed_key = twox_128(&key); - hashed_key - }; - - context.write_memory(out, &result) - .map_err(|_| "Invalid attempt to set result in ext_twox_128")?; - Ok(()) - } - - ext_twox_256(data: Pointer, len: WordSize, out: Pointer) { - let result: [u8; 32] = if len == 0 { - twox_256(&[0u8; 0]) - } else { - let mem = context.read_memory(data, len) - .map_err(|_| "Invalid attempt to get data in ext_twox_256")?; - twox_256(&mem) - }; - context.write_memory(out, &result) - .map_err(|_| "Invalid attempt to set result in ext_twox_256")?; - Ok(()) - } - - ext_blake2_128(data: Pointer, len: WordSize, out: Pointer) { - let result: [u8; 16] = if len == 0 { - let hashed = blake2_128(&[0u8; 0]); - hashed - } else { - let key = context.read_memory(data, len) - .map_err(|_| "Invalid attempt to get key in ext_blake2_128")?; - let hashed_key = blake2_128(&key); - hashed_key - }; - - context.write_memory(out, &result) - .map_err(|_| "Invalid attempt to set result in ext_blake2_128")?; - Ok(()) - } - - ext_blake2_256(data: Pointer, len: WordSize, out: Pointer) { - let result: [u8; 32] = if len == 0 { - blake2_256(&[0u8; 0]) - } else { - let mem = context.read_memory(data, len) - .map_err(|_| "Invalid attempt to get data in ext_blake2_256")?; - blake2_256(&mem) - }; - context.write_memory(out, &result) - .map_err(|_| "Invalid attempt to set result in ext_blake2_256")?; - Ok(()) - } - - ext_keccak_256(data: Pointer, len: WordSize, out: Pointer) { - let result: [u8; 32] = if len == 0 { - tiny_keccak::keccak256(&[0u8; 0]) - } else { - let mem = context.read_memory(data, len) - .map_err(|_| "Invalid attempt to get data in ext_keccak_256")?; - tiny_keccak::keccak256(&mem) - }; - context.write_memory(out, &result) - .map_err(|_| "Invalid attempt to set result in ext_keccak_256")?; - Ok(()) - } - - ext_ed25519_public_keys(id_data: Pointer, result_len: Pointer) -> Pointer { - let mut id = [0u8; 4]; - context.read_memory_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_ed25519_public_keys")?; - let key_type = KeyTypeId(id); - - let keys = runtime_io::ed25519_public_keys(key_type).encode(); - - let len = keys.len() as u32; - let offset = context.allocate_memory(len)?; - - context.write_memory(offset, keys.as_ref()) - .map_err(|_| "Invalid attempt to set memory in ext_ed25519_public_keys")?; - context.write_primitive(result_len, len) - .map_err(|_| "Invalid attempt to write result_len in ext_ed25519_public_keys")?; - - Ok(offset) - } - - ext_ed25519_verify( - msg_data: Pointer, - msg_len: WordSize, - sig_data: Pointer, - pubkey_data: Pointer, - ) -> u32 { - let mut sig = [0u8; 64]; - context.read_memory_into(sig_data, &mut sig[..]) - .map_err(|_| "Invalid attempt to get signature in ext_ed25519_verify")?; - let mut pubkey = [0u8; 32]; - context.read_memory_into(pubkey_data, &mut pubkey[..]) - .map_err(|_| "Invalid attempt to get pubkey in ext_ed25519_verify")?; - let msg = context.read_memory(msg_data, msg_len) - .map_err(|_| "Invalid attempt to get message in ext_ed25519_verify")?; - - Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) { - 0 - } else { - 1 - }) - } - - ext_ed25519_generate( - id_data: Pointer, - seed: Pointer, - seed_len: WordSize, - out: Pointer, - ) { - let mut id = [0u8; 4]; - context.read_memory_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_ed25519_generate")?; - let key_type = KeyTypeId(id); - - let seed = if seed_len == 0 { - None - } else { - Some( - context.read_memory(seed, seed_len) - .map_err(|_| "Invalid attempt to get seed in ext_ed25519_generate")? - ) - }; - - let seed = seed.as_ref() - .map(|seed| - std::str::from_utf8(&seed) - .map_err(|_| "Seed not a valid utf8 string in ext_sr25119_generate") - ).transpose()?; - - let pubkey = runtime_io::ed25519_generate(key_type, seed); - - context.write_memory(out, pubkey.as_ref()) - .map_err(|_| "Invalid attempt to set out in ext_ed25519_generate".into()) - } - - ext_ed25519_sign( - id_data: Pointer, - pubkey_data: Pointer, - msg_data: Pointer, - msg_len: WordSize, - out: Pointer, - ) -> u32 { - let mut id = [0u8; 4]; - context.read_memory_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_ed25519_sign")?; - let key_type = KeyTypeId(id); - - let mut pubkey = [0u8; 32]; - context.read_memory_into(pubkey_data, &mut pubkey[..]) - .map_err(|_| "Invalid attempt to get pubkey in ext_ed25519_sign")?; - - let msg = context.read_memory(msg_data, msg_len) - .map_err(|_| "Invalid attempt to get message in ext_ed25519_sign")?; - - let pub_key = ed25519::Public::try_from(pubkey.as_ref()) - .map_err(|_| "Invalid `ed25519` public key")?; - - let signature = runtime_io::ed25519_sign(key_type, &pub_key, &msg); - - match signature { - Some(signature) => { - context.write_memory(out, signature.as_ref()) - .map_err(|_| "Invalid attempt to set out in ext_ed25519_sign")?; - Ok(0) - }, - None => Ok(1), - } - } - - ext_sr25519_public_keys(id_data: Pointer, result_len: Pointer) -> Pointer { - let mut id = [0u8; 4]; - context.read_memory_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_sr25519_public_keys")?; - let key_type = KeyTypeId(id); - - let keys = runtime_io::sr25519_public_keys(key_type).encode(); - - let len = keys.len() as u32; - let offset = context.allocate_memory(len)?; - - context.write_memory(offset, keys.as_ref()) - .map_err(|_| "Invalid attempt to set memory in ext_sr25519_public_keys")?; - context.write_primitive(result_len, len) - .map_err(|_| "Invalid attempt to write result_len in ext_sr25519_public_keys")?; - - Ok(offset) - } - - ext_sr25519_verify( - msg_data: Pointer, - msg_len: WordSize, - sig_data: Pointer, - pubkey_data: Pointer, - ) -> u32 { - let mut sig = [0u8; 64]; - context.read_memory_into(sig_data, &mut sig[..]) - .map_err(|_| "Invalid attempt to get signature in ext_sr25519_verify")?; - let mut pubkey = [0u8; 32]; - context.read_memory_into(pubkey_data, &mut pubkey[..]) - .map_err(|_| "Invalid attempt to get pubkey in ext_sr25519_verify")?; - let msg = context.read_memory(msg_data, msg_len) - .map_err(|_| "Invalid attempt to get message in ext_sr25519_verify")?; - - Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) { - 0 - } else { - 1 - }) - } - - ext_sr25519_generate( - id_data: Pointer, - seed: Pointer, - seed_len: WordSize, - out: Pointer, - ) { - let mut id = [0u8; 4]; - context.read_memory_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_sr25519_generate")?; - let key_type = KeyTypeId(id); - let seed = if seed_len == 0 { - None - } else { - Some( - context.read_memory(seed, seed_len) - .map_err(|_| "Invalid attempt to get seed in ext_sr25519_generate")? - ) - }; - - let seed = seed.as_ref() - .map(|seed| - std::str::from_utf8(&seed) - .map_err(|_| "Seed not a valid utf8 string in ext_sr25119_generate") - ) - .transpose()?; - - let pubkey = runtime_io::sr25519_generate(key_type, seed); - - context.write_memory(out, pubkey.as_ref()) - .map_err(|_| "Invalid attempt to set out in ext_sr25519_generate".into()) - } - - ext_sr25519_sign( - id_data: Pointer, - pubkey_data: Pointer, - msg_data: Pointer, - msg_len: WordSize, - out: Pointer, - ) -> u32 { - let mut id = [0u8; 4]; - context.read_memory_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_sr25519_sign")?; - let key_type = KeyTypeId(id); - - let mut pubkey = [0u8; 32]; - context.read_memory_into(pubkey_data, &mut pubkey[..]) - .map_err(|_| "Invalid attempt to get pubkey in ext_sr25519_sign")?; - - let msg = context.read_memory(msg_data, msg_len) - .map_err(|_| "Invalid attempt to get message in ext_sr25519_sign")?; - - let pub_key = sr25519::Public::try_from(pubkey.as_ref()) - .map_err(|_| "Invalid `sr25519` public key")?; - - let signature = runtime_io::sr25519_sign(key_type, &pub_key, &msg); - - match signature { - Some(signature) => { - context.write_memory(out, signature.as_ref()) - .map_err(|_| "Invalid attempt to set out in ext_sr25519_sign")?; - Ok(0) - }, - None => Ok(1), - } - } - - ext_secp256k1_ecdsa_recover( - msg_data: Pointer, - sig_data: Pointer, - pubkey_data: Pointer, - ) -> u32 { - match secp256k1_recover(context, msg_data, sig_data)? { - RecoverResult::Invalid(c) => Ok(c), - RecoverResult::Valid(pubkey) => { - context.write_memory(pubkey_data, &pubkey.serialize()[1..65]) - .map_err(|_| "Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover")?; - Ok(0) - } - } - } - - ext_secp256k1_ecdsa_recover_compressed( - msg_data: Pointer, - sig_data: Pointer, - pubkey_data: Pointer, - ) -> u32 { - match secp256k1_recover(context, msg_data, sig_data)? { - RecoverResult::Invalid(c) => Ok(c), - RecoverResult::Valid(pubkey) => { - context.write_memory(pubkey_data, &pubkey.serialize_compressed()[..]) - .map_err(|_| "Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover")?; - Ok(0) - } - } - } - - ext_is_validator() -> u32 { - if runtime_io::is_validator() { Ok(1) } else { Ok(0) } - } - - ext_submit_transaction(msg_data: Pointer, len: WordSize) -> u32 { - let extrinsic = context.read_memory(msg_data, len) - .map_err(|_| "OOB while ext_submit_transaction: wasm")?; - - let res = runtime_io::submit_transaction(extrinsic); - - Ok(if res.is_ok() { 0 } else { 1 }) - } - - ext_network_state(written_out: Pointer) -> Pointer { - let res = runtime_io::network_state(); - - let encoded = res.encode(); - let len = encoded.len() as u32; - let offset = context.allocate_memory(len)?; - context.write_memory(offset, &encoded) - .map_err(|_| "Invalid attempt to set memory in ext_network_state")?; - - context.write_primitive(written_out, len) - .map_err(|_| "Invalid attempt to write written_out in ext_network_state")?; - - Ok(offset) - } - - ext_timestamp() -> u64 { - Ok(runtime_io::timestamp().unix_millis()) - } - - ext_sleep_until(deadline: u64) { - runtime_io::sleep_until(offchain::Timestamp::from_unix_millis(deadline)); - Ok(()) - } - - ext_random_seed(seed_data: Pointer) { - // NOTE the runtime as assumptions about seed size. - let seed = runtime_io::random_seed(); - - context.write_memory(seed_data, &seed) - .map_err(|_| "Invalid attempt to set value in ext_random_seed")?; - Ok(()) - } - - ext_local_storage_set( - kind: u32, - key: Pointer, - key_len: WordSize, - value: Pointer, - value_len: WordSize, - ) { - let kind = offchain::StorageKind::try_from(kind) - .map_err(|_| "storage kind OOB while ext_local_storage_set: wasm")?; - let key = context.read_memory(key, key_len) - .map_err(|_| "OOB while ext_local_storage_set: wasm")?; - let value = context.read_memory(value, value_len) - .map_err(|_| "OOB while ext_local_storage_set: wasm")?; - - runtime_io::local_storage_set(kind, &key, &value); - - Ok(()) - } - - ext_local_storage_get( - kind: u32, - key: Pointer, - key_len: WordSize, - value_len: Pointer, - ) -> Pointer { - let kind = offchain::StorageKind::try_from(kind) - .map_err(|_| "storage kind OOB while ext_local_storage_get: wasm")?; - let key = context.read_memory(key, key_len) - .map_err(|_| "OOB while ext_local_storage_get: wasm")?; - - let maybe_value = runtime_io::local_storage_get(kind, &key); - - let (offset, len) = if let Some(value) = maybe_value { - let offset = context.allocate_memory(value.len() as u32)?; - context.write_memory(offset, &value) - .map_err(|_| "Invalid attempt to set memory in ext_local_storage_get")?; - (offset, value.len() as u32) - } else { - (Pointer::null(), u32::max_value()) - }; - - context.write_primitive(value_len, len) - .map_err(|_| "Invalid attempt to write value_len in ext_local_storage_get")?; - - Ok(offset) - } - - ext_local_storage_compare_and_set( - kind: u32, - key: Pointer, - key_len: WordSize, - old_value: Pointer, - old_value_len: WordSize, - new_value: Pointer, - new_value_len: WordSize, - ) -> u32 { - let kind = offchain::StorageKind::try_from(kind) - .map_err(|_| "storage kind OOB while ext_local_storage_compare_and_set: wasm")?; - let key = context.read_memory(key, key_len) - .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; - let new_value = context.read_memory(new_value, new_value_len) - .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; - - let old_value = if old_value_len == u32::max_value() { - None - } else { - Some( - context.read_memory(old_value, old_value_len) - .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")? - ) - }; - - let res = runtime_io::local_storage_compare_and_set( - kind, - &key, - old_value.as_ref().map(|v| v.as_ref()), - &new_value, - ); - - Ok(if res { 0 } else { 1 }) - } - - ext_http_request_start( - method: Pointer, - method_len: WordSize, - url: Pointer, - url_len: WordSize, - meta: Pointer, - meta_len: WordSize, - ) -> u32 { - let method = context.read_memory(method, method_len) - .map_err(|_| "OOB while ext_http_request_start: wasm")?; - let url = context.read_memory(url, url_len) - .map_err(|_| "OOB while ext_http_request_start: wasm")?; - let meta = context.read_memory(meta, meta_len) - .map_err(|_| "OOB while ext_http_request_start: wasm")?; - - let method_str = str::from_utf8(&method) - .map_err(|_| "invalid str while ext_http_request_start: wasm")?; - let url_str = str::from_utf8(&url) - .map_err(|_| "invalid str while ext_http_request_start: wasm")?; - - let id = runtime_io::http_request_start(method_str, url_str, &meta); - - if let Ok(id) = id { - Ok(id.into()) - } else { - Ok(u32::max_value()) - } - } - - ext_http_request_add_header( - request_id: u32, - name: Pointer, - name_len: WordSize, - value: Pointer, - value_len: WordSize, - ) -> u32 { - let name = context.read_memory(name, name_len) - .map_err(|_| "OOB while ext_http_request_add_header: wasm")?; - let value = context.read_memory(value, value_len) - .map_err(|_| "OOB while ext_http_request_add_header: wasm")?; - - let name_str = str::from_utf8(&name) - .map_err(|_| "Invalid str while ext_http_request_add_header: wasm")?; - let value_str = str::from_utf8(&value) - .map_err(|_| "Invalid str while ext_http_request_add_header: wasm")?; - - let res = runtime_io::http_request_add_header( - offchain::HttpRequestId(request_id as u16), - name_str, - value_str, - ); - - Ok(if res.is_ok() { 0 } else { 1 }) - } - - ext_http_request_write_body( - request_id: u32, - chunk: Pointer, - chunk_len: WordSize, - deadline: u64, - ) -> u32 { - let chunk = context.read_memory(chunk, chunk_len) - .map_err(|_| "OOB while ext_http_request_write_body: wasm")?; - - let res = runtime_io::http_request_write_body( - offchain::HttpRequestId(request_id as u16), - &chunk, - deadline_to_timestamp(deadline), - ); - - Ok(match res { - Ok(()) => 0, - Err(e) => e.into(), - }) - } - - ext_http_response_wait( - ids: Pointer, - ids_len: WordSize, - statuses: Pointer, - deadline: u64, - ) { - let ids = (0..ids_len) - .map(|i| - context.read_primitive(ids.offset(i).ok_or("Point overflow")?) - .map(|id: u32| offchain::HttpRequestId(id as u16)) - .map_err(|_| "OOB while ext_http_response_wait: wasm") - ) - .collect::, _>>()?; - - let res = runtime_io::http_response_wait(&ids, deadline_to_timestamp(deadline)) - .into_iter() - .map(|status| u32::from(status)) - .enumerate() - // make sure to take up to `ids_len` to avoid exceeding the mem. - .take(ids_len as usize); - - for (i, status) in res { - context.write_primitive(statuses.offset(i as u32).ok_or("Point overflow")?, status) - .map_err(|_| "Invalid attempt to set memory in ext_http_response_wait")?; - } - - Ok(()) - } - - ext_http_response_headers( - request_id: u32, - written_out: Pointer, - ) -> Pointer { - use codec::Encode; - - let headers = runtime_io::http_response_headers(offchain::HttpRequestId(request_id as u16)); - - let encoded = headers.encode(); - let len = encoded.len() as u32; - let offset = context.allocate_memory(len)?; - - context.write_memory(offset, &encoded) - .map_err(|_| "Invalid attempt to set memory in ext_http_response_headers")?; - context.write_primitive(written_out, len) - .map_err(|_| "Invalid attempt to write written_out in ext_http_response_headers")?; - - Ok(offset) - } - - ext_http_response_read_body( - request_id: u32, - buffer: Pointer, - buffer_len: WordSize, - deadline: u64, - ) -> WordSize { - let mut internal_buffer = Vec::with_capacity(buffer_len as usize); - internal_buffer.resize(buffer_len as usize, 0); - - let res = runtime_io::http_response_read_body( - offchain::HttpRequestId(request_id as u16), - &mut internal_buffer, - deadline_to_timestamp(deadline), - ); - - Ok(match res { - Ok(read) => { - context.write_memory(buffer, &internal_buffer[..read]) - .map_err(|_| "Invalid attempt to set memory in ext_http_response_read_body")?; - - read as u32 - }, - Err(err) => { - u32::max_value() - u32::from(err) + 1 - } - }) - } - } -} - -trait WritePrimitive { - fn write_primitive(&mut self, ptr: Pointer, t: T) -> WResult<()>; -} - -impl WritePrimitive for &mut dyn FunctionContext { - fn write_primitive(&mut self, ptr: Pointer, t: u32) -> WResult<()> { - let r = t.to_le_bytes(); - self.write_memory(ptr.cast(), &r) - } -} - -trait ReadPrimitive { - fn read_primitive(&self, offset: Pointer) -> WResult; -} - -impl ReadPrimitive for &mut dyn FunctionContext { - fn read_primitive(&self, ptr: Pointer) -> WResult { - let mut r = [0u8; 4]; - self.read_memory_into(ptr.cast(), &mut r)?; - Ok(u32::from_le_bytes(r)) - } -} - -/// Execute closure that access external storage. -/// -/// All panics that happen within closure are captured and transformed into -/// runtime error. This requires special panic handler mode to be enabled -/// during the call (see `panic_handler::AbortGuard::never_abort`). -/// If this mode isn't enabled, then all panics within externalities are -/// leading to process abort. -fn with_external_storage(f: F) -> std::result::Result - where - F: panic::UnwindSafe + FnOnce() -> Result -{ - // it is safe beause basic methods of StorageExternalities are guaranteed to touch only - // its internal state + we should discard it on error - panic::catch_unwind(move || f()) - .map_err(|_| Error::Runtime) - .and_then(|result| result) - .map_err(|err| format!("{}", err)) -} - -fn deadline_to_timestamp(deadline: u64) -> Option { - if deadline == 0 { - None - } else { - Some(offchain::Timestamp::from_unix_millis(deadline)) - } -} - diff --git a/core/executor/src/lib.rs b/core/executor/src/lib.rs deleted file mode 100644 index ac98388cd7bbe..0000000000000 --- a/core/executor/src/lib.rs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! A crate that provides means of executing/dispatching calls into the runtime. -//! -//! There are a few responsibilities of this crate at the moment: -//! -//! - It provides an implementation of a common entrypoint for calling into the runtime, both -//! wasm and compiled. -//! - It defines the environment for the wasm execution, namely the host functions that are to be -//! provided into the wasm runtime module. -//! - It also provides the required infrastructure for executing the current wasm runtime (specified -//! by the current value of `:code` in the provided externalities), i.e. interfacing with -//! wasm engine used, instance cache. - -#![warn(missing_docs)] -#![recursion_limit="128"] - -#[macro_use] -mod wasm_utils; -mod wasmi_execution; -#[macro_use] -mod native_executor; -mod sandbox; -mod allocator; -mod host_interface; -mod wasm_runtime; - -pub mod error; -pub use wasmi; -pub use native_executor::{with_native_environment, NativeExecutor, NativeExecutionDispatch}; -pub use runtime_version::{RuntimeVersion, NativeVersion}; -pub use codec::Codec; -#[doc(hidden)] -pub use primitives::traits::Externalities; -#[doc(hidden)] -pub use wasm_interface; -pub use wasm_runtime::WasmExecutionMethod; - -/// Call the given `function` in the given wasm `code`. -/// -/// The signature of `function` needs to follow the default Substrate function signature. -/// -/// - `call_data`: Will be given as input parameters to `function` -/// - `execution_method`: The execution method to use. -/// - `ext`: The externalities that should be set while executing the wasm function. -/// - `heap_pages`: The number of heap pages to allocate. -/// -/// Returns the `Vec` that contains the return value of the function. -pub fn call_in_wasm( - function: &str, - call_data: &[u8], - execution_method: WasmExecutionMethod, - ext: &mut E, - code: &[u8], - heap_pages: u64, -) -> error::Result> { - let mut instance = wasm_runtime::create_wasm_runtime_with_code( - ext, - execution_method, - heap_pages, - code, - )?; - instance.call(ext, function, call_data) -} - -/// Provides runtime information. -pub trait RuntimeInfo { - /// Native runtime information. - fn native_version(&self) -> &NativeVersion; - - /// Extract RuntimeVersion of given :code block - fn runtime_version ( - &self, - ext: &mut E, - ) -> Option; -} - -#[cfg(test)] -mod tests { - use super::*; - use runtime_test::WASM_BINARY; - use runtime_io::TestExternalities; - - #[test] - fn call_in_interpreted_wasm_works() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let res = call_in_wasm( - "test_empty_return", - &[], - WasmExecutionMethod::Interpreted, - &mut ext, - &WASM_BINARY, - 8, - ).unwrap(); - assert_eq!(res, vec![0u8; 0]); - } -} diff --git a/core/executor/src/native_executor.rs b/core/executor/src/native_executor.rs deleted file mode 100644 index 7323703ed9656..0000000000000 --- a/core/executor/src/native_executor.rs +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::{result, cell::RefCell, panic::UnwindSafe}; -use crate::error::{Error, Result}; -use crate::wasm_runtime::{RuntimesCache, WasmExecutionMethod, WasmRuntime}; -use crate::RuntimeInfo; -use runtime_version::{NativeVersion, RuntimeVersion}; -use codec::{Decode, Encode}; -use primitives::{NativeOrEncoded, traits::{CodeExecutor, Externalities}}; -use log::{trace, warn}; - -thread_local! { - static RUNTIMES_CACHE: RefCell = RefCell::new(RuntimesCache::new()); -} - -/// Default num of pages for the heap -const DEFAULT_HEAP_PAGES: u64 = 1024; - -fn safe_call(f: F) -> Result - where F: UnwindSafe + FnOnce() -> U -{ - // Substrate uses custom panic hook that terminates process on panic. Disable termination for the native call. - let _guard = panic_handler::AbortGuard::force_unwind(); - std::panic::catch_unwind(f).map_err(|_| Error::Runtime) -} - -/// Set up the externalities and safe calling environment to execute calls to a native runtime. -/// -/// If the inner closure panics, it will be caught and return an error. -pub fn with_native_environment(ext: &mut dyn Externalities, f: F) -> Result - where F: UnwindSafe + FnOnce() -> U -{ - externalities::set_and_run_with_externalities(ext, move || safe_call(f)) -} - -/// Delegate for dispatching a CodeExecutor call. -/// -/// By dispatching we mean that we execute a runtime function specified by it's name. -pub trait NativeExecutionDispatch: Send + Sync { - /// Dispatch a method in the runtime. - /// - /// If the method with the specified name doesn't exist then `Err` is returned. - fn dispatch(ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result>; - - /// Provide native runtime version. - fn native_version() -> NativeVersion; -} - -/// A generic `CodeExecutor` implementation that uses a delegate to determine wasm code equivalence -/// and dispatch to native code when possible, falling back on `WasmExecutor` when not. -#[derive(Debug)] -pub struct NativeExecutor { - /// Dummy field to avoid the compiler complaining about us not using `D`. - _dummy: ::std::marker::PhantomData, - /// Method used to execute fallback Wasm code. - fallback_method: WasmExecutionMethod, - /// Native runtime version info. - native_version: NativeVersion, - /// The number of 64KB pages to allocate for Wasm execution. - default_heap_pages: u64, -} - -impl NativeExecutor { - /// Create new instance. - /// - /// # Parameters - /// - /// `fallback_method` - Method used to execute fallback Wasm code. - /// - /// `default_heap_pages` - Number of 64KB pages to allocate for Wasm execution. - /// Defaults to `DEFAULT_HEAP_PAGES` if `None` is provided. - pub fn new(fallback_method: WasmExecutionMethod, default_heap_pages: Option) -> Self { - NativeExecutor { - _dummy: Default::default(), - fallback_method, - native_version: D::native_version(), - default_heap_pages: default_heap_pages.unwrap_or(DEFAULT_HEAP_PAGES), - } - } - - fn with_runtime( - &self, - ext: &mut E, - f: impl for <'a> FnOnce(&'a mut dyn WasmRuntime, &'a mut E) -> Result, - ) -> Result where E: Externalities { - RUNTIMES_CACHE.with(|cache| { - let mut cache = cache.borrow_mut(); - let runtime = cache.fetch_runtime(ext, self.fallback_method, self.default_heap_pages)?; - f(runtime, ext) - }) - } -} - -impl Clone for NativeExecutor { - fn clone(&self) -> Self { - NativeExecutor { - _dummy: Default::default(), - fallback_method: self.fallback_method, - native_version: D::native_version(), - default_heap_pages: self.default_heap_pages, - } - } -} - -impl RuntimeInfo for NativeExecutor { - fn native_version(&self) -> &NativeVersion { - &self.native_version - } - - fn runtime_version( - &self, - ext: &mut E, - ) -> Option { - match self.with_runtime(ext, |runtime, _ext| Ok(runtime.version())) { - Ok(version) => version, - Err(e) => { - warn!(target: "executor", "Failed to fetch runtime: {:?}", e); - None - } - } - } -} - -impl CodeExecutor for NativeExecutor { - type Error = Error; - - fn call - < - E: Externalities, - R:Decode + Encode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe - >( - &self, - ext: &mut E, - method: &str, - data: &[u8], - use_native: bool, - native_call: Option, - ) -> (Result>, bool){ - let mut used_native = false; - let result = self.with_runtime(ext, |runtime, ext| { - let onchain_version = runtime.version(); - 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)) - ); - runtime.call(ext, method, data).map(NativeOrEncoded::Encoded) - } - (false, _, _) => runtime.call(ext, method, data).map(NativeOrEncoded::Encoded), - (true, true, Some(call)) => { - trace!( - target: "executor", - "Request for native execution with native call succeeded (native: {}, chain: {}).", - self.native_version.runtime_version, - onchain_version - .as_ref() - .map_or_else(||"".into(), |v| format!("{}", v)) - ); - - used_native = true; - with_native_environment(ext, move || (call)()) - .and_then(|r| r - .map(NativeOrEncoded::Native) - .map_err(|s| Error::ApiError(s.to_string())) - ) - } - _ => { - 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)) - ); - - used_native = true; - D::dispatch(ext, method, data).map(NativeOrEncoded::Encoded) - } - } - }); - (result, used_native) - } -} - -/// Implements a `NativeExecutionDispatch` for provided parameters. -#[macro_export] -macro_rules! native_executor_instance { - ( $pub:vis $name:ident, $dispatcher:path, $version:path $(,)?) => { - /// A unit struct which implements `NativeExecutionDispatch` feeding in the hard-coded runtime. - $pub struct $name; - $crate::native_executor_instance!(IMPL $name, $dispatcher, $version); - }; - (IMPL $name:ident, $dispatcher:path, $version:path) => { - impl $crate::NativeExecutionDispatch for $name { - fn dispatch( - ext: &mut $crate::Externalities, - method: &str, - data: &[u8] - ) -> $crate::error::Result> { - $crate::with_native_environment(ext, move || $dispatcher(method, data))? - .ok_or_else(|| $crate::error::Error::MethodNotFound(method.to_owned())) - } - - fn native_version() -> $crate::NativeVersion { - $version() - } - } - } -} diff --git a/core/executor/src/sandbox.rs b/core/executor/src/sandbox.rs deleted file mode 100644 index e1e9e0db95263..0000000000000 --- a/core/executor/src/sandbox.rs +++ /dev/null @@ -1,875 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![warn(missing_docs)] - -//! This module implements sandboxing support in the runtime. - -use crate::error::{Result, Error}; -use std::{collections::HashMap, rc::Rc}; -use codec::{Decode, Encode}; -use primitives::sandbox as sandbox_primitives; -use wasmi::{ - Externals, ImportResolver, MemoryInstance, MemoryRef, Module, ModuleInstance, - ModuleRef, RuntimeArgs, RuntimeValue, Trap, TrapKind, memory_units::Pages, -}; -use wasm_interface::{Pointer, WordSize}; - -/// Index of a function inside the supervisor. -/// -/// This is a typically an index in the default table of the supervisor, however -/// the exact meaning of this index is depends on the implementation of dispatch function. -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct SupervisorFuncIndex(usize); - -impl From for usize { - fn from(index: SupervisorFuncIndex) -> Self { - index.0 - } -} - -/// Index of a function within guest index space. -/// -/// This index is supposed to be used with as index for `Externals`. -#[derive(Copy, Clone, Debug, PartialEq)] -struct GuestFuncIndex(usize); - -/// This struct holds a mapping from guest index space to supervisor. -struct GuestToSupervisorFunctionMapping { - funcs: Vec, -} - -impl GuestToSupervisorFunctionMapping { - fn new() -> GuestToSupervisorFunctionMapping { - GuestToSupervisorFunctionMapping { funcs: Vec::new() } - } - - fn define(&mut self, supervisor_func: SupervisorFuncIndex) -> GuestFuncIndex { - let idx = self.funcs.len(); - self.funcs.push(supervisor_func); - GuestFuncIndex(idx) - } - - fn func_by_guest_index(&self, guest_func_idx: GuestFuncIndex) -> Option { - self.funcs.get(guest_func_idx.0).cloned() - } -} - -struct Imports { - func_map: HashMap<(Vec, Vec), GuestFuncIndex>, - memories_map: HashMap<(Vec, Vec), MemoryRef>, -} - -impl ImportResolver for Imports { - fn resolve_func( - &self, - module_name: &str, - field_name: &str, - signature: &::wasmi::Signature, - ) -> std::result::Result { - let key = ( - module_name.as_bytes().to_owned(), - field_name.as_bytes().to_owned(), - ); - let idx = *self.func_map.get(&key).ok_or_else(|| { - wasmi::Error::Instantiation(format!( - "Export {}:{} not found", - module_name, field_name - )) - })?; - Ok(wasmi::FuncInstance::alloc_host(signature.clone(), idx.0)) - } - - fn resolve_memory( - &self, - module_name: &str, - field_name: &str, - _memory_type: &::wasmi::MemoryDescriptor, - ) -> std::result::Result { - let key = ( - module_name.as_bytes().to_vec(), - field_name.as_bytes().to_vec(), - ); - let mem = self.memories_map - .get(&key) - .ok_or_else(|| { - wasmi::Error::Instantiation(format!( - "Export {}:{} not found", - module_name, field_name - )) - })? - .clone(); - Ok(mem) - } - - fn resolve_global( - &self, - module_name: &str, - field_name: &str, - _global_type: &::wasmi::GlobalDescriptor, - ) -> std::result::Result { - Err(wasmi::Error::Instantiation(format!( - "Export {}:{} not found", - module_name, field_name - ))) - } - - fn resolve_table( - &self, - module_name: &str, - field_name: &str, - _table_type: &::wasmi::TableDescriptor, - ) -> std::result::Result { - Err(wasmi::Error::Instantiation(format!( - "Export {}:{} not found", - module_name, field_name - ))) - } -} - -/// This trait encapsulates sandboxing capabilities. -/// -/// Note that this functions are only called in the `supervisor` context. -pub trait SandboxCapabilities { - /// Represents a function reference into the supervisor environment. - type SupervisorFuncRef; - - /// Returns a reference to an associated sandbox `Store`. - fn store(&self) -> &Store; - - /// Returns a mutable reference to an associated sandbox `Store`. - fn store_mut(&mut self) -> &mut Store; - - /// 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: WordSize) -> 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: Pointer) -> Result<()>; - - /// Write `data` into the supervisor memory at offset specified by `ptr`. - /// - /// # Errors - /// - /// Returns `Err` if `ptr + data.len()` is out of bounds. - fn write_memory(&mut self, ptr: Pointer, data: &[u8]) -> Result<()>; - - /// Read `len` bytes from the supervisor memory. - /// - /// # Errors - /// - /// Returns `Err` if `ptr + len` is out of bounds. - fn read_memory(&self, ptr: Pointer, len: WordSize) -> Result>; - - /// Invoke a function in the supervisor environment. - /// - /// This first invokes the dispatch_thunk function, passing in the function index of the - /// desired function to call and serialized arguments. The thunk calls the desired function - /// with the deserialized arguments, then serializes the result into memory and returns - /// reference. The pointer to and length of the result in linear memory is encoded into an i64, - /// with the upper 32 bits representing the pointer and the lower 32 bits representing the - /// length. - /// - /// # Errors - /// - /// Returns `Err` if the dispatch_thunk function has an incorrect signature or traps during - /// execution. - fn invoke( - &mut self, - dispatch_thunk: &Self::SupervisorFuncRef, - invoke_args_ptr: Pointer, - invoke_args_len: WordSize, - state: u32, - func_idx: SupervisorFuncIndex, - ) -> Result; -} - -/// Implementation of [`Externals`] that allows execution of guest module with -/// [externals][`Externals`] that might refer functions defined by supervisor. -/// -/// [`Externals`]: ../../wasmi/trait.Externals.html -pub struct GuestExternals<'a, FE: SandboxCapabilities + 'a> { - supervisor_externals: &'a mut FE, - sandbox_instance: &'a SandboxInstance, - state: u32, -} - -fn trap(msg: &'static str) -> Trap { - TrapKind::Host(Box::new(Error::Other(msg.into()))).into() -} - -fn deserialize_result(serialized_result: &[u8]) -> std::result::Result, Trap> { - use self::sandbox_primitives::{HostError, ReturnValue}; - let result_val = std::result::Result::::decode(&mut &serialized_result[..]) - .map_err(|_| trap("Decoding Result failed!"))?; - - match result_val { - Ok(return_value) => Ok(match return_value { - ReturnValue::Unit => None, - ReturnValue::Value(typed_value) => Some(RuntimeValue::from(typed_value)), - }), - Err(HostError) => Err(trap("Supervisor function returned sandbox::HostError")), - } -} - -impl<'a, FE: SandboxCapabilities + 'a> Externals for GuestExternals<'a, FE> { - fn invoke_index( - &mut self, - index: usize, - args: RuntimeArgs, - ) -> std::result::Result, Trap> { - // Make `index` typesafe again. - let index = GuestFuncIndex(index); - - let func_idx = self.sandbox_instance - .guest_to_supervisor_mapping - .func_by_guest_index(index) - .expect( - "`invoke_index` is called with indexes registered via `FuncInstance::alloc_host`; - `FuncInstance::alloc_host` is called with indexes that was obtained from `guest_to_supervisor_mapping`; - `func_by_guest_index` called with `index` can't return `None`; - qed" - ); - - // Serialize arguments into a byte vector. - let invoke_args_data: Vec = args.as_ref() - .iter() - .cloned() - .map(sandbox_primitives::TypedValue::from) - .collect::>() - .encode(); - - let state = self.state; - - // Move serialized arguments inside the memory and invoke dispatch thunk and - // then free allocated memory. - let invoke_args_len = invoke_args_data.len() as WordSize; - let invoke_args_ptr = self.supervisor_externals.allocate(invoke_args_len)?; - self.supervisor_externals.write_memory(invoke_args_ptr, &invoke_args_data)?; - let result = self.supervisor_externals.invoke( - &self.sandbox_instance.dispatch_thunk, - invoke_args_ptr, - invoke_args_len, - state, - func_idx, - )?; - self.supervisor_externals.deallocate(invoke_args_ptr)?; - - // dispatch_thunk returns pointer to serialized arguments. - // Unpack pointer and len of the serialized result data. - let (serialized_result_val_ptr, serialized_result_val_len) = { - // Cast to u64 to use zero-extension. - let v = result as u64; - let ptr = (v as u64 >> 32) as u32; - let len = (v & 0xFFFFFFFF) as u32; - (Pointer::new(ptr), len) - }; - - let serialized_result_val = self.supervisor_externals - .read_memory(serialized_result_val_ptr, serialized_result_val_len)?; - self.supervisor_externals - .deallocate(serialized_result_val_ptr)?; - - deserialize_result(&serialized_result_val) - } -} - -fn with_guest_externals( - supervisor_externals: &mut FE, - sandbox_instance: &SandboxInstance, - state: u32, - f: F, -) -> R -where - FE: SandboxCapabilities, - F: FnOnce(&mut GuestExternals) -> R, -{ - let mut guest_externals = GuestExternals { - supervisor_externals, - sandbox_instance, - state, - }; - f(&mut guest_externals) -} - -/// Sandboxed instance of a wasm module. -/// -/// It's primary purpose is to [`invoke`] exported functions on it. -/// -/// All imports of this instance are specified at the creation time and -/// imports are implemented by the supervisor. -/// -/// Hence, in order to invoke an exported function on a sandboxed module instance, -/// it's required to provide supervisor externals: it will be used to execute -/// code in the supervisor context. -/// -/// This is generic over a supervisor function reference type. -/// -/// [`invoke`]: #method.invoke -pub struct SandboxInstance { - instance: ModuleRef, - dispatch_thunk: FR, - guest_to_supervisor_mapping: GuestToSupervisorFunctionMapping, -} - -impl SandboxInstance { - /// Invoke an exported function by a name. - /// - /// `supervisor_externals` is required to execute the implementations - /// of the syscalls that published to a sandboxed module instance. - /// - /// The `state` parameter can be used to provide custom data for - /// these syscall implementations. - pub fn invoke>( - &self, - export_name: &str, - args: &[RuntimeValue], - supervisor_externals: &mut FE, - state: u32, - ) -> std::result::Result, wasmi::Error> { - with_guest_externals( - supervisor_externals, - self, - state, - |guest_externals| { - self.instance - .invoke_export(export_name, args, guest_externals) - }, - ) - } -} - -/// Error occurred during instantiation of a sandboxed module. -pub enum InstantiationError { - /// Something wrong with the environment definition. It either can't - /// be decoded, have a reference to a non-existent or torn down memory instance. - EnvironmentDefinitionCorrupted, - /// Provided module isn't recognized as a valid webassembly binary. - ModuleDecoding, - /// Module is a well-formed webassembly binary but could not be instantiated. This could - /// happen because, e.g. the module imports entries not provided by the environment. - Instantiation, - /// Module is well-formed, instantiated and linked, but while executing the start function - /// a trap was generated. - StartTrapped, -} - -fn decode_environment_definition( - raw_env_def: &[u8], - memories: &[Option], -) -> std::result::Result<(Imports, GuestToSupervisorFunctionMapping), InstantiationError> { - let env_def = sandbox_primitives::EnvironmentDefinition::decode(&mut &raw_env_def[..]) - .map_err(|_| InstantiationError::EnvironmentDefinitionCorrupted)?; - - let mut func_map = HashMap::new(); - let mut memories_map = HashMap::new(); - let mut guest_to_supervisor_mapping = GuestToSupervisorFunctionMapping::new(); - - for entry in &env_def.entries { - let module = entry.module_name.clone(); - let field = entry.field_name.clone(); - - match entry.entity { - sandbox_primitives::ExternEntity::Function(func_idx) => { - let externals_idx = - guest_to_supervisor_mapping.define(SupervisorFuncIndex(func_idx as usize)); - func_map.insert((module, field), externals_idx); - } - sandbox_primitives::ExternEntity::Memory(memory_idx) => { - let memory_ref = memories - .get(memory_idx as usize) - .cloned() - .ok_or_else(|| InstantiationError::EnvironmentDefinitionCorrupted)? - .ok_or_else(|| InstantiationError::EnvironmentDefinitionCorrupted)?; - memories_map.insert((module, field), memory_ref); - } - } - } - - Ok(( - Imports { - func_map, - memories_map, - }, - guest_to_supervisor_mapping, - )) -} - -/// Instantiate a guest module and return it's index in the store. -/// -/// The guest module's code is specified in `wasm`. Environment that will be available to -/// guest module is specified in `raw_env_def` (serialized version of [`EnvironmentDefinition`]). -/// `dispatch_thunk` is used as function that handle calls from guests. -/// -/// # Errors -/// -/// Returns `Err` if any of the following conditions happens: -/// -/// - `raw_env_def` can't be deserialized as a [`EnvironmentDefinition`]. -/// - Module in `wasm` is invalid or couldn't be instantiated. -/// -/// [`EnvironmentDefinition`]: ../../sandbox/struct.EnvironmentDefinition.html -pub fn instantiate( - supervisor_externals: &mut FE, - dispatch_thunk: FE::SupervisorFuncRef, - wasm: &[u8], - raw_env_def: &[u8], - state: u32, -) -> std::result::Result { - let (imports, guest_to_supervisor_mapping) = - decode_environment_definition(raw_env_def, &supervisor_externals.store().memories)?; - - let module = Module::from_buffer(wasm).map_err(|_| InstantiationError::ModuleDecoding)?; - let instance = ModuleInstance::new(&module, &imports).map_err(|_| InstantiationError::Instantiation)?; - - let sandbox_instance = Rc::new(SandboxInstance { - // In general, it's not a very good idea to use `.not_started_instance()` for anything - // but for extracting memory and tables. But in this particular case, we are extracting - // for the purpose of running `start` function which should be ok. - instance: instance.not_started_instance().clone(), - dispatch_thunk, - guest_to_supervisor_mapping, - }); - - with_guest_externals( - supervisor_externals, - &sandbox_instance, - state, - |guest_externals| { - instance - .run_start(guest_externals) - .map_err(|_| InstantiationError::StartTrapped) - }, - )?; - - // At last, register the instance. - let instance_idx = supervisor_externals - .store_mut() - .register_sandbox_instance(sandbox_instance); - Ok(instance_idx) -} - -/// This struct keeps track of all sandboxed components. -/// -/// This is generic over a supervisor function reference type. -pub struct Store { - // Memories and instances are `Some` untill torndown. - instances: Vec>>>, - memories: Vec>, -} - -impl Store { - /// Create a new empty sandbox store. - pub fn new() -> Self { - Store { - instances: Vec::new(), - memories: Vec::new(), - } - } - - /// Create a new memory instance and return it's index. - /// - /// # Errors - /// - /// Returns `Err` if the memory couldn't be created. - /// Typically happens if `initial` is more than `maximum`. - pub fn new_memory(&mut self, initial: u32, maximum: u32) -> Result { - let maximum = match maximum { - sandbox_primitives::MEM_UNLIMITED => None, - specified_limit => Some(Pages(specified_limit as usize)), - }; - - let mem = - MemoryInstance::alloc( - Pages(initial as usize), - maximum, - )?; - - let mem_idx = self.memories.len(); - self.memories.push(Some(mem)); - Ok(mem_idx as u32) - } - - /// Returns `SandboxInstance` by `instance_idx`. - /// - /// # Errors - /// - /// Returns `Err` If `instance_idx` isn't a valid index of an instance or - /// instance is already torndown. - pub fn instance(&self, instance_idx: u32) -> Result>> { - self.instances - .get(instance_idx as usize) - .cloned() - .ok_or_else(|| "Trying to access a non-existent instance")? - .ok_or_else(|| "Trying to access a torndown instance".into()) - } - - /// Returns reference to a memory instance by `memory_idx`. - /// - /// # Errors - /// - /// Returns `Err` If `memory_idx` isn't a valid index of an memory or - /// if memory has been torn down. - pub fn memory(&self, memory_idx: u32) -> Result { - self.memories - .get(memory_idx as usize) - .cloned() - .ok_or_else(|| "Trying to access a non-existent sandboxed memory")? - .ok_or_else(|| "Trying to access a torndown sandboxed memory".into()) - } - - /// Tear down the memory at the specified index. - /// - /// # Errors - /// - /// Returns `Err` if `memory_idx` isn't a valid index of an memory or - /// if it has been torn down. - pub fn memory_teardown(&mut self, memory_idx: u32) -> Result<()> { - match self.memories.get_mut(memory_idx as usize) { - None => Err("Trying to teardown a non-existent sandboxed memory".into()), - Some(None) => Err("Double teardown of a sandboxed memory".into()), - Some(memory) => { - *memory = None; - Ok(()) - } - } - } - - /// Tear down the instance at the specified index. - /// - /// # Errors - /// - /// Returns `Err` if `instance_idx` isn't a valid index of an instance or - /// if it has been torn down. - pub fn instance_teardown(&mut self, instance_idx: u32) -> Result<()> { - match self.instances.get_mut(instance_idx as usize) { - None => Err("Trying to teardown a non-existent instance".into()), - Some(None) => Err("Double teardown of an instance".into()), - Some(instance) => { - *instance = None; - Ok(()) - } - } - } - - fn register_sandbox_instance(&mut self, sandbox_instance: Rc>) -> u32 { - let instance_idx = self.instances.len(); - self.instances.push(Some(sandbox_instance)); - instance_idx as u32 - } -} - -#[cfg(test)] -mod tests { - use super::*; - use primitives::{Blake2Hasher, traits::Externalities}; - use crate::wasm_runtime::WasmRuntime; - use crate::wasmi_execution; - use state_machine::TestExternalities as CoreTestExternalities; - use wabt; - use runtime_test::WASM_BINARY; - - type TestExternalities = CoreTestExternalities; - - fn call_wasm( - ext: &mut E, - heap_pages: u64, - code: &[u8], - method: &str, - data: &[u8], - ) -> Result> { - let mut instance = wasmi_execution::create_instance(ext, code, heap_pages) - .map_err(|err| err.to_string())?; - instance.call(ext, method, data) - } - - #[test] - fn sandbox_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - (import "env" "inc_counter" (func $inc_counter (param i32) (result i32))) - (func (export "call") - (drop - (call $inc_counter (i32.const 5)) - ) - - (call $inc_counter (i32.const 3)) - ;; current counter value is on the stack - - ;; check whether current == 8 - i32.const 8 - i32.eq - - call $assert - ) - ) - "#).unwrap().encode(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(), - true.encode(), - ); - } - - #[test] - fn sandbox_trap() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - (func (export "call") - i32.const 0 - call $assert - ) - ) - "#).unwrap(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(), - vec![0], - ); - } - - #[test] - fn sandbox_should_trap_when_heap_exhausted() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - (func (export "call") - i32.const 0 - call $assert - ) - ) - "#).unwrap().encode(); - - let res = call_wasm(&mut ext, 8, &test_code[..], "test_exhaust_heap", &code); - assert_eq!(res.is_err(), true); - if let Err(err) = res { - assert_eq!( - format!("{}", err), - format!( - "{}", - wasmi::Error::Trap(Error::FunctionExecution("AllocatorOutOfSpace".into()).into()), - ), - ); - } - } - - #[test] - fn start_called() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - (import "env" "inc_counter" (func $inc_counter (param i32) (result i32))) - - ;; Start function - (start $start) - (func $start - ;; Increment counter by 1 - (drop - (call $inc_counter (i32.const 1)) - ) - ) - - (func (export "call") - ;; Increment counter by 1. The current value is placed on the stack. - (call $inc_counter (i32.const 1)) - - ;; Counter is incremented twice by 1, once there and once in `start` func. - ;; So check the returned value is equal to 2. - i32.const 2 - i32.eq - call $assert - ) - ) - "#).unwrap().encode(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(), - true.encode(), - ); - } - - #[test] - fn invoke_args() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - - (func (export "call") (param $x i32) (param $y i64) - ;; assert that $x = 0x12345678 - (call $assert - (i32.eq - (get_local $x) - (i32.const 0x12345678) - ) - ) - - (call $assert - (i64.eq - (get_local $y) - (i64.const 0x1234567887654321) - ) - ) - ) - ) - "#).unwrap().encode(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox_args", &code).unwrap(), - true.encode(), - ); - } - - #[test] - fn return_val() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (func (export "call") (param $x i32) (result i32) - (i32.add - (get_local $x) - (i32.const 1) - ) - ) - ) - "#).unwrap().encode(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox_return_val", &code).unwrap(), - true.encode(), - ); - } - - #[test] - fn unlinkable_module() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "non-existent" (func)) - - (func (export "call") - ) - ) - "#).unwrap().encode(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(), - 1u8.encode(), - ); - } - - #[test] - fn corrupted_module() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - // Corrupted wasm file - let code = vec![0u8, 0, 0, 0, 1, 0, 0, 0].encode(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(), - 1u8.encode(), - ); - } - - #[test] - fn start_fn_ok() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (func (export "call") - ) - - (func $start - ) - - (start $start) - ) - "#).unwrap().encode(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(), - 0u8.encode(), - ); - } - - #[test] - fn start_fn_traps() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (func (export "call") - ) - - (func $start - unreachable - ) - - (start $start) - ) - "#).unwrap().encode(); - - assert_eq!( - call_wasm(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(), - 2u8.encode(), - ); - } -} diff --git a/core/executor/src/wasm_runtime.rs b/core/executor/src/wasm_runtime.rs deleted file mode 100644 index 8d2291fe04893..0000000000000 --- a/core/executor/src/wasm_runtime.rs +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Traits and accessor functions for calling into the Substrate Wasm runtime. -//! -//! The primary means of accessing the runtimes is through a cache which saves the reusable -//! components of the runtime that are expensive to initialize. - -use crate::error::{Error, WasmError}; -use crate::wasmi_execution; -use log::{trace, warn}; -use codec::Decode; -use primitives::{storage::well_known_keys, traits::Externalities}; -use runtime_version::RuntimeVersion; -use std::{collections::hash_map::{Entry, HashMap}}; - -/// The Substrate Wasm runtime. -pub trait WasmRuntime { - /// Attempt to update the number of heap pages available during execution. - /// - /// Returns false if the update cannot be applied. The function is guaranteed to return true if - /// the heap pages would not change from its current value. - fn update_heap_pages(&mut self, heap_pages: u64) -> bool; - - /// Call a method in the Substrate runtime by name. Returns the encoded result on success. - fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) - -> Result, Error>; - - /// Returns the version of this runtime. - /// - /// Returns `None` if the runtime doesn't provide the information or there was an error - /// while fetching it. - fn version(&self) -> Option; -} - -/// Specification of different methods of executing the runtime Wasm code. -#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] -pub enum WasmExecutionMethod { - /// Uses the Wasmi interpreter. - Interpreted, -} - -/// Cache for the runtimes. -/// -/// When an instance is requested for the first time it is added to this cache. Metadata is kept -/// with the instance so that it can be efficiently reinitialized. -/// -/// When using the Wasmi interpreter execution method, the metadata includes the initial memory and -/// values of mutable globals. Follow-up requests to fetch a runtime return this one instance with -/// the memory reset to the initial memory. So, one runtime instance is reused for every fetch -/// request. -/// -/// For now the cache grows indefinitely, but that should be fine for now since runtimes can only be -/// upgraded rarely and there are no other ways to make the node to execute some other runtime. -pub struct RuntimesCache { - /// A cache of runtime instances along with metadata, ready to be reused. - /// - /// Instances are keyed by the Wasm execution method and the hash of their code. - instances: HashMap<(WasmExecutionMethod, [u8; 32]), Result, WasmError>>, -} - -impl RuntimesCache { - /// Creates a new instance of a runtimes cache. - pub fn new() -> RuntimesCache { - RuntimesCache { - instances: HashMap::new(), - } - } - - /// Fetches an instance of the runtime. - /// - /// On first use we create a new runtime instance, save it to the cache - /// and persist its initial memory. - /// - /// Each subsequent request will return this instance, with its memory restored - /// to the persisted initial memory. Thus, we reuse one single runtime instance - /// for every `fetch_runtime` invocation. - /// - /// # Parameters - /// - /// `ext` - Externalities to use for the runtime. This is used for setting - /// up an initial runtime instance. The parameter is only needed for calling - /// into the Wasm module to find out the `Core_version`. - /// - /// `default_heap_pages` - Number of 64KB pages to allocate for Wasm execution. - /// - /// # Return value - /// - /// If no error occurred a tuple `(wasmi::ModuleRef, Option)` is - /// returned. `RuntimeVersion` is contained if the call to `Core_version` returned - /// a version. - /// - /// In case of failure one of two errors can be returned: - /// - /// `Err::InvalidCode` is returned for runtime code issues. - /// - /// `Error::InvalidMemoryReference` is returned if no memory export with the - /// identifier `memory` can be found in the runtime. - pub fn fetch_runtime( - &mut self, - ext: &mut E, - wasm_method: WasmExecutionMethod, - default_heap_pages: u64, - ) -> Result<&mut (dyn WasmRuntime + 'static), Error> { - let code_hash = ext - .original_storage_hash(well_known_keys::CODE) - .ok_or(Error::InvalidCode("`CODE` not found in storage.".into()))?; - - let heap_pages = ext - .storage(well_known_keys::HEAP_PAGES) - .and_then(|pages| u64::decode(&mut &pages[..]).ok()) - .unwrap_or(default_heap_pages); - - let result = match self.instances.entry((wasm_method, code_hash.into())) { - Entry::Occupied(o) => { - let result = o.into_mut(); - if let Ok(ref mut cached_runtime) = result { - if !cached_runtime.update_heap_pages(heap_pages) { - trace!( - target: "runtimes_cache", - "heap_pages were changed. Reinstantiating the instance" - ); - *result = create_wasm_runtime(ext, wasm_method, heap_pages); - if let Err(ref err) = result { - warn!(target: "runtimes_cache", "cannot create a runtime: {:?}", err); - } - } - } - result - }, - Entry::Vacant(v) => { - trace!(target: "runtimes_cache", "no instance found in cache, creating now."); - let result = create_wasm_runtime(ext, wasm_method, heap_pages); - if let Err(ref err) = result { - warn!(target: "runtimes_cache", "cannot create a runtime: {:?}", err); - } - v.insert(result) - } - }; - - result.as_mut() - .map(|runtime| runtime.as_mut()) - .map_err(|ref e| Error::InvalidCode(format!("{:?}", e))) - } -} - -/// Create a wasm runtime with the given `code`. -pub fn create_wasm_runtime_with_code( - ext: &mut E, - wasm_method: WasmExecutionMethod, - heap_pages: u64, - code: &[u8], -) -> Result, WasmError> { - match wasm_method { - WasmExecutionMethod::Interpreted => - wasmi_execution::create_instance(ext, code, heap_pages) - .map(|runtime| -> Box { Box::new(runtime) }), - } -} - -fn create_wasm_runtime( - ext: &mut E, - wasm_method: WasmExecutionMethod, - heap_pages: u64, -) -> Result, WasmError> { - let code = ext - .original_storage(well_known_keys::CODE) - .ok_or(WasmError::CodeNotFound)?; - create_wasm_runtime_with_code(ext, wasm_method, heap_pages, &code) -} diff --git a/core/executor/src/wasmi_execution.rs b/core/executor/src/wasmi_execution.rs deleted file mode 100644 index 2b832b490641d..0000000000000 --- a/core/executor/src/wasmi_execution.rs +++ /dev/null @@ -1,963 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Implementation of a Wasm runtime using the Wasmi interpreter. - -use std::{str, mem}; -use wasmi::{ - Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, - memory_units::Pages, RuntimeValue::{I32, I64, self}, -}; -use crate::error::{Error, WasmError}; -use codec::{Encode, Decode}; -use primitives::{sandbox as sandbox_primitives, traits::Externalities}; -use crate::host_interface::SubstrateExternals; -use crate::sandbox; -use crate::allocator; -use crate::wasm_runtime::WasmRuntime; -use log::trace; -use parity_wasm::elements::{deserialize_buffer, DataSegment, Instruction, Module as RawModule}; -use runtime_version::RuntimeVersion; -use wasm_interface::{ - FunctionContext, HostFunctions, Pointer, WordSize, Sandbox, MemoryId, Result as WResult, -}; - -struct FunctionExecutor { - sandbox_store: sandbox::Store, - heap: allocator::FreeingBumpHeapAllocator, - memory: MemoryRef, - table: Option, -} - -impl FunctionExecutor { - fn new(m: MemoryRef, heap_base: u32, t: Option) -> Result { - Ok(FunctionExecutor { - sandbox_store: sandbox::Store::new(), - heap: allocator::FreeingBumpHeapAllocator::new(heap_base), - memory: m, - table: t, - }) - } -} - -impl sandbox::SandboxCapabilities for FunctionExecutor { - type SupervisorFuncRef = wasmi::FuncRef; - - fn store(&self) -> &sandbox::Store { - &self.sandbox_store - } - fn store_mut(&mut self) -> &mut sandbox::Store { - &mut self.sandbox_store - } - fn allocate(&mut self, len: WordSize) -> Result, Error> { - let heap = &mut self.heap; - self.memory.with_direct_access_mut(|mem| { - heap.allocate(mem, len) - }) - } - fn deallocate(&mut self, ptr: Pointer) -> Result<(), Error> { - let heap = &mut self.heap; - self.memory.with_direct_access_mut(|mem| { - heap.deallocate(mem, ptr) - }) - } - fn write_memory(&mut self, ptr: Pointer, data: &[u8]) -> Result<(), Error> { - self.memory.set(ptr.into(), data).map_err(Into::into) - } - fn read_memory(&self, ptr: Pointer, len: WordSize) -> Result, Error> { - self.memory.get(ptr.into(), len as usize).map_err(Into::into) - } - - fn invoke( - &mut self, - dispatch_thunk: &Self::SupervisorFuncRef, - invoke_args_ptr: Pointer, - invoke_args_len: WordSize, - state: u32, - func_idx: sandbox::SupervisorFuncIndex, - ) -> Result - { - let result = wasmi::FuncInstance::invoke( - dispatch_thunk, - &[ - RuntimeValue::I32(u32::from(invoke_args_ptr) as i32), - RuntimeValue::I32(invoke_args_len as i32), - RuntimeValue::I32(state as i32), - RuntimeValue::I32(usize::from(func_idx) as i32), - ], - self, - ); - match result { - Ok(Some(RuntimeValue::I64(val))) => Ok(val), - Ok(_) => return Err("Supervisor function returned unexpected result!".into()), - Err(err) => Err(Error::Trap(err)), - } - } -} - -impl FunctionContext for FunctionExecutor { - fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> WResult<()> { - self.memory.get_into(address.into(), dest).map_err(|e| format!("{:?}", e)) - } - - fn write_memory(&mut self, address: Pointer, data: &[u8]) -> WResult<()> { - self.memory.set(address.into(), data).map_err(|e| format!("{:?}", e)) - } - - fn allocate_memory(&mut self, size: WordSize) -> WResult> { - let heap = &mut self.heap; - self.memory.with_direct_access_mut(|mem| { - heap.allocate(mem, size).map_err(|e| format!("{:?}", e)) - }) - } - - fn deallocate_memory(&mut self, ptr: Pointer) -> WResult<()> { - let heap = &mut self.heap; - self.memory.with_direct_access_mut(|mem| { - heap.deallocate(mem, ptr).map_err(|e| format!("{:?}", e)) - }) - } - - fn sandbox(&mut self) -> &mut dyn Sandbox { - self - } -} - -impl Sandbox for FunctionExecutor { - fn memory_get( - &self, - memory_id: MemoryId, - offset: WordSize, - buf_ptr: Pointer, - buf_len: WordSize, - ) -> WResult { - let sandboxed_memory = self.sandbox_store.memory(memory_id).map_err(|e| format!("{:?}", e))?; - - match MemoryInstance::transfer( - &sandboxed_memory, - offset as usize, - &self.memory, - buf_ptr.into(), - buf_len as usize, - ) { - Ok(()) => Ok(sandbox_primitives::ERR_OK), - Err(_) => Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), - } - } - - fn memory_set( - &mut self, - memory_id: MemoryId, - offset: WordSize, - val_ptr: Pointer, - val_len: WordSize, - ) -> WResult { - let sandboxed_memory = self.sandbox_store.memory(memory_id).map_err(|e| format!("{:?}", e))?; - - match MemoryInstance::transfer( - &self.memory, - val_ptr.into(), - &sandboxed_memory, - offset as usize, - val_len as usize, - ) { - Ok(()) => Ok(sandbox_primitives::ERR_OK), - Err(_) => Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), - } - } - - fn memory_teardown(&mut self, memory_id: MemoryId) -> WResult<()> { - self.sandbox_store.memory_teardown(memory_id).map_err(|e| format!("{:?}", e)) - } - - fn memory_new( - &mut self, - initial: u32, - maximum: u32, - ) -> WResult { - self.sandbox_store.new_memory(initial, maximum).map_err(|e| format!("{:?}", e)) - } - - fn invoke( - &mut self, - instance_id: u32, - export_name: &str, - args: &[u8], - return_val: Pointer, - return_val_len: WordSize, - state: u32, - ) -> WResult { - trace!(target: "sr-sandbox", "invoke, instance_idx={}", instance_id); - - // Deserialize arguments and convert them into wasmi types. - let args = Vec::::decode(&mut &args[..]) - .map_err(|_| "Can't decode serialized arguments for the invocation")? - .into_iter() - .map(Into::into) - .collect::>(); - - let instance = self.sandbox_store.instance(instance_id).map_err(|e| format!("{:?}", e))?; - let result = instance.invoke(export_name, &args, self, state); - - match result { - Ok(None) => Ok(sandbox_primitives::ERR_OK), - Ok(Some(val)) => { - // Serialize return value and write it back into the memory. - sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| { - if val.len() > return_val_len as usize { - Err("Return value buffer is too small")?; - } - self.write_memory(return_val, val).map_err(|_| "Return value buffer is OOB")?; - Ok(sandbox_primitives::ERR_OK) - }) - } - Err(_) => Ok(sandbox_primitives::ERR_EXECUTION), - } - } - - fn instance_teardown(&mut self, instance_id: u32) -> WResult<()> { - self.sandbox_store.instance_teardown(instance_id).map_err(|e| format!("{:?}", e)) - } - - fn instance_new( - &mut self, - dispatch_thunk_id: u32, - wasm: &[u8], - raw_env_def: &[u8], - state: u32, - ) -> WResult { - // Extract a dispatch thunk from instance's table by the specified index. - let dispatch_thunk = { - let table = self.table.as_ref() - .ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")?; - table.get(dispatch_thunk_id) - .map_err(|_| "dispatch_thunk_idx is out of the table bounds")? - .ok_or_else(|| "dispatch_thunk_idx points on an empty table entry")? - .clone() - }; - - let instance_idx_or_err_code = - match sandbox::instantiate(self, dispatch_thunk, wasm, raw_env_def, state) { - Ok(instance_idx) => instance_idx, - Err(sandbox::InstantiationError::StartTrapped) => - sandbox_primitives::ERR_EXECUTION, - Err(_) => sandbox_primitives::ERR_MODULE, - }; - - Ok(instance_idx_or_err_code as u32) - } -} - -impl FunctionExecutor { - fn resolver() -> &'static dyn wasmi::ModuleImportResolver { - struct Resolver; - impl wasmi::ModuleImportResolver for Resolver { - fn resolve_func(&self, name: &str, signature: &wasmi::Signature) - -> std::result::Result - { - let signature = wasm_interface::Signature::from(signature); - - if let Some((index, func)) = SubstrateExternals::functions().iter() - .enumerate() - .find(|f| name == f.1.name()) - { - if signature == func.signature() { - Ok(wasmi::FuncInstance::alloc_host(signature.into(), index)) - } else { - Err(wasmi::Error::Instantiation( - format!( - "Invalid signature for function `{}` expected `{:?}`, got `{:?}`", - func.name(), - signature, - func.signature(), - ) - )) - } - } else { - Err(wasmi::Error::Instantiation( - format!("Export {} not found", name), - )) - } - } - } - &Resolver - } -} - -impl wasmi::Externals for FunctionExecutor { - fn invoke_index(&mut self, index: usize, args: wasmi::RuntimeArgs) - -> Result, wasmi::Trap> - { - let mut args = args.as_ref().iter().copied().map(Into::into); - let function = SubstrateExternals::functions().get(index).ok_or_else(|| - Error::from( - format!("Could not find host function with index: {}", index), - ) - )?; - - function.execute(self, &mut args) - .map_err(Error::FunctionExecution) - .map_err(wasmi::Trap::from) - .map(|v| v.map(Into::into)) - } -} - -fn get_mem_instance(module: &ModuleRef) -> Result { - Ok(module - .export_by_name("memory") - .ok_or_else(|| Error::InvalidMemoryReference)? - .as_memory() - .ok_or_else(|| Error::InvalidMemoryReference)? - .clone()) -} - -/// Find the global named `__heap_base` in the given wasm module instance and -/// tries to get its value. -fn get_heap_base(module: &ModuleRef) -> Result { - let heap_base_val = module - .export_by_name("__heap_base") - .ok_or_else(|| Error::HeapBaseNotFoundOrInvalid)? - .as_global() - .ok_or_else(|| Error::HeapBaseNotFoundOrInvalid)? - .get(); - - match heap_base_val { - wasmi::RuntimeValue::I32(v) => Ok(v as u32), - _ => Err(Error::HeapBaseNotFoundOrInvalid), - } -} - -/// Call a given method in the given wasm-module runtime. -fn call_in_wasm_module( - ext: &mut dyn Externalities, - module_instance: &ModuleRef, - method: &str, - data: &[u8], -) -> Result, Error> { - call_in_wasm_module_with_custom_signature( - ext, - module_instance, - method, - |alloc| { - let offset = alloc(data)?; - Ok(vec![I32(offset as i32), I32(data.len() as i32)]) - }, - |res, memory| { - if let Some(I64(r)) = res { - let offset = r as u32; - let length = (r as u64 >> 32) as usize; - memory.get(offset, length).map_err(|_| Error::Runtime).map(Some) - } else { - Ok(None) - } - } - ) -} - -/// Call a given method in the given wasm-module runtime. -fn call_in_wasm_module_with_custom_signature< - F: FnOnce(&mut dyn FnMut(&[u8]) -> Result) -> Result, Error>, - FR: FnOnce(Option, &MemoryRef) -> Result, Error>, - R, ->( - ext: &mut dyn Externalities, - module_instance: &ModuleRef, - method: &str, - create_parameters: F, - filter_result: FR, -) -> Result { - // extract a reference to a linear memory, optional reference to a table - // and then initialize FunctionExecutor. - let memory = get_mem_instance(module_instance)?; - let table: Option = module_instance - .export_by_name("__indirect_function_table") - .and_then(|e| e.as_table().cloned()); - let heap_base = get_heap_base(module_instance)?; - - let mut fec = FunctionExecutor::new( - memory.clone(), - heap_base, - table, - )?; - - let parameters = create_parameters(&mut |data: &[u8]| { - let offset = fec.allocate_memory(data.len() as u32)?; - fec.write_memory(offset, data).map(|_| offset.into()).map_err(Into::into) - })?; - - let result = externalities::set_and_run_with_externalities( - ext, - || module_instance.invoke_export(method, ¶meters, &mut fec), - ); - - match result { - Ok(val) => match filter_result(val, &memory)? { - Some(val) => Ok(val), - None => Err(Error::InvalidReturn), - }, - Err(e) => { - trace!( - target: "wasm-executor", - "Failed to execute code with {} pages", - memory.current_size().0 - ); - Err(e.into()) - }, - } -} - -/// Prepare module instance -fn instantiate_module( - heap_pages: usize, - module: &Module, -) -> Result { - // start module instantiation. Don't run 'start' function yet. - let intermediate_instance = ModuleInstance::new( - module, - &ImportsBuilder::new() - .with_resolver("env", FunctionExecutor::resolver()) - )?; - - // Verify that the module has the heap base global variable. - let _ = get_heap_base(intermediate_instance.not_started_instance())?; - - // Extract a reference to a linear memory. - let memory = get_mem_instance(intermediate_instance.not_started_instance())?; - memory.grow(Pages(heap_pages)).map_err(|_| Error::Runtime)?; - - if intermediate_instance.has_start() { - // Runtime is not allowed to have the `start` function. - Err(Error::RuntimeHasStartFn) - } else { - Ok(intermediate_instance.assert_no_start()) - } -} - -/// A state snapshot of an instance taken just after instantiation. -/// -/// It is used for restoring the state of the module after execution. -#[derive(Clone)] -struct StateSnapshot { - /// The offset and the content of the memory segments that should be used to restore the snapshot - data_segments: Vec<(u32, Vec)>, - /// The list of all global mutable variables of the module in their sequential order. - global_mut_values: Vec, - heap_pages: u64, -} - -impl StateSnapshot { - // Returns `None` if instance is not valid. - fn take( - module_instance: &ModuleRef, - data_segments: Vec, - heap_pages: u64, - ) -> Option { - let prepared_segments = data_segments - .into_iter() - .map(|mut segment| { - // Just replace contents of the segment since the segments will be discarded later - // anyway. - let contents = mem::replace(segment.value_mut(), vec![]); - - let init_expr = match segment.offset() { - Some(offset) => offset.code(), - // Return if the segment is passive - None => return None - }; - - // [op, End] - if init_expr.len() != 2 { - return None; - } - let offset = match init_expr[0] { - Instruction::I32Const(v) => v as u32, - Instruction::GetGlobal(idx) => { - let global_val = module_instance.globals().get(idx as usize)?.get(); - match global_val { - RuntimeValue::I32(v) => v as u32, - _ => return None, - } - } - _ => return None, - }; - - Some((offset, contents)) - }) - .collect::>>()?; - - // Collect all values of mutable globals. - let global_mut_values = module_instance - .globals() - .iter() - .filter(|g| g.is_mutable()) - .map(|g| g.get()) - .collect(); - - Some(Self { - data_segments: prepared_segments, - global_mut_values, - heap_pages, - }) - } - - /// Reset the runtime instance to the initial version by restoring - /// the preserved memory and globals. - /// - /// Returns `Err` if applying the snapshot is failed. - fn apply(&self, instance: &ModuleRef) -> Result<(), WasmError> { - let memory = instance - .export_by_name("memory") - .ok_or(WasmError::ApplySnapshotFailed)? - .as_memory() - .cloned() - .ok_or(WasmError::ApplySnapshotFailed)?; - - // First, erase the memory and copy the data segments into it. - memory - .erase() - .map_err(|_| WasmError::ApplySnapshotFailed)?; - for (offset, contents) in &self.data_segments { - memory - .set(*offset, contents) - .map_err(|_| WasmError::ApplySnapshotFailed)?; - } - - // Second, restore the values of mutable globals. - for (global_ref, global_val) in instance - .globals() - .iter() - .filter(|g| g.is_mutable()) - .zip(self.global_mut_values.iter()) - { - // the instance should be the same as used for preserving and - // we iterate the same way it as we do it for preserving values that means that the - // types should be the same and all the values are mutable. So no error is expected/ - global_ref - .set(*global_val) - .map_err(|_| WasmError::ApplySnapshotFailed)?; - } - Ok(()) - } -} - -/// A runtime along with its version and initial state snapshot. -#[derive(Clone)] -pub struct WasmiRuntime { - /// A wasm module instance. - instance: ModuleRef, - /// Runtime version according to `Core_version`. - /// - /// Can be `None` if the runtime doesn't expose this function. - version: Option, - /// The snapshot of the instance's state taken just after the instantiation. - state_snapshot: StateSnapshot, -} - -impl WasmiRuntime { - /// Perform an operation with the clean version of the runtime wasm instance. - fn with(&self, f: F) -> R - where - F: FnOnce(&ModuleRef) -> R, - { - self.state_snapshot.apply(&self.instance).expect( - "applying the snapshot can only fail if the passed instance is different - from the one that was used for creation of the snapshot; - we use the snapshot that is directly associated with the instance; - thus the snapshot was created using the instance; - qed", - ); - f(&self.instance) - } -} - -impl WasmRuntime for WasmiRuntime { - fn update_heap_pages(&mut self, heap_pages: u64) -> bool { - self.state_snapshot.heap_pages == heap_pages - } - - fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) - -> Result, Error> - { - self.with(|module| { - call_in_wasm_module(ext, module, method, data) - }) - } - - fn version(&self) -> Option { - self.version.clone() - } -} - -pub fn create_instance(ext: &mut E, code: &[u8], heap_pages: u64) - -> Result -{ - let module = Module::from_buffer(&code).map_err(|_| WasmError::InvalidModule)?; - - // Extract the data segments from the wasm code. - // - // A return of this error actually indicates that there is a problem in logic, since - // we just loaded and validated the `module` above. - let data_segments = extract_data_segments(&code)?; - - // Instantiate this module. - let instance = instantiate_module(heap_pages as usize, &module) - .map_err(WasmError::Instantiation)?; - - // Take state snapshot before executing anything. - let state_snapshot = StateSnapshot::take(&instance, data_segments, heap_pages) - .expect( - "`take` returns `Err` if the module is not valid; - we already loaded module above, thus the `Module` is proven to be valid at this point; - qed - ", - ); - - let version = call_in_wasm_module(ext, &instance, "Core_version", &[]) - .ok() - .and_then(|v| RuntimeVersion::decode(&mut v.as_slice()).ok()); - Ok(WasmiRuntime { - instance, - version, - state_snapshot, - }) -} - -/// Extract the data segments from the given wasm code. -/// -/// Returns `Err` if the given wasm code cannot be deserialized. -fn extract_data_segments(wasm_code: &[u8]) -> Result, WasmError> { - let raw_module: RawModule = deserialize_buffer(wasm_code) - .map_err(|_| WasmError::CantDeserializeWasm)?; - - let segments = raw_module - .data_section() - .map(|ds| ds.entries()) - .unwrap_or(&[]) - .to_vec(); - Ok(segments) -} - -#[cfg(test)] -mod tests { - use super::*; - - use state_machine::TestExternalities as CoreTestExternalities; - use hex_literal::hex; - use primitives::{ - Blake2Hasher, blake2_128, blake2_256, ed25519, sr25519, map, Pair, offchain::OffchainExt, - }; - use runtime_test::WASM_BINARY; - use substrate_offchain::testing; - use trie::{TrieConfiguration, trie_types::Layout}; - use codec::{Encode, Decode}; - - type TestExternalities = CoreTestExternalities; - - fn call( - ext: &mut E, - heap_pages: u64, - code: &[u8], - method: &str, - data: &[u8], - ) -> Result, Error> { - let mut instance = create_instance(ext, code, heap_pages) - .map_err(|err| err.to_string())?; - instance.call(ext, method, data) - } - - #[test] - fn returning_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let output = call(&mut ext, 8, &test_code[..], "test_empty_return", &[]).unwrap(); - assert_eq!(output, vec![0u8; 0]); - } - - #[test] - fn panicking_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let output = call(&mut ext, 8, &test_code[..], "test_panic", &[]); - assert!(output.is_err()); - - let output = call(&mut ext, 8, &test_code[..], "test_conditional_panic", &[0]); - assert_eq!(Decode::decode(&mut &output.unwrap()[..]), Ok(Vec::::new())); - - let output = call(&mut ext, 8, &test_code[..], "test_conditional_panic", &vec![2].encode()); - assert!(output.is_err()); - } - - #[test] - fn storage_should_work() { - let mut ext = TestExternalities::default(); - - { - let mut ext = ext.ext(); - ext.set_storage(b"foo".to_vec(), b"bar".to_vec()); - let test_code = WASM_BINARY; - - let output = call( - &mut ext, - 8, - &test_code[..], - "test_data_in", - &b"Hello world".to_vec().encode(), - ).unwrap(); - - assert_eq!(output, b"all ok!".to_vec().encode()); - } - - let expected = TestExternalities::new((map![ - b"input".to_vec() => b"Hello world".to_vec(), - b"foo".to_vec() => b"bar".to_vec(), - b"baz".to_vec() => b"bar".to_vec() - ], map![])); - assert_eq!(ext, expected); - } - - #[test] - fn clear_prefix_should_work() { - let mut ext = TestExternalities::default(); - { - let mut ext = ext.ext(); - ext.set_storage(b"aaa".to_vec(), b"1".to_vec()); - ext.set_storage(b"aab".to_vec(), b"2".to_vec()); - ext.set_storage(b"aba".to_vec(), b"3".to_vec()); - ext.set_storage(b"abb".to_vec(), b"4".to_vec()); - ext.set_storage(b"bbb".to_vec(), b"5".to_vec()); - let test_code = WASM_BINARY; - - // This will clear all entries which prefix is "ab". - let output = call( - &mut ext, - 8, - &test_code[..], - "test_clear_prefix", - &b"ab".to_vec().encode(), - ).unwrap(); - - assert_eq!(output, b"all ok!".to_vec().encode()); - } - - let expected = TestExternalities::new((map![ - b"aaa".to_vec() => b"1".to_vec(), - b"aab".to_vec() => b"2".to_vec(), - b"bbb".to_vec() => b"5".to_vec() - ], map![])); - assert_eq!(expected, ext); - } - - #[test] - fn blake2_256_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_blake2_256", &[0]).unwrap(), - blake2_256(&b""[..]).to_vec().encode(), - ); - assert_eq!( - call( - &mut ext, - 8, - &test_code[..], - "test_blake2_256", - &b"Hello world!".to_vec().encode(), - ).unwrap(), - blake2_256(&b"Hello world!"[..]).to_vec().encode(), - ); - } - - #[test] - fn blake2_128_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_blake2_128", &[0]).unwrap(), - blake2_128(&b""[..]).to_vec().encode(), - ); - assert_eq!( - call( - &mut ext, - 8, - &test_code[..], - "test_blake2_128", - &b"Hello world!".to_vec().encode(), - ).unwrap(), - blake2_128(&b"Hello world!"[..]).to_vec().encode(), - ); - } - - #[test] - fn twox_256_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_twox_256", &[0]).unwrap(), - hex!( - "99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a" - ).to_vec().encode(), - ); - assert_eq!( - call( - &mut ext, - 8, - &test_code[..], - "test_twox_256", - &b"Hello world!".to_vec().encode(), - ).unwrap(), - hex!( - "b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74" - ).to_vec().encode(), - ); - } - - #[test] - fn twox_128_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_twox_128", &[0]).unwrap(), - hex!("99e9d85137db46ef4bbea33613baafd5").to_vec().encode(), - ); - assert_eq!( - call( - &mut ext, - 8, - &test_code[..], - "test_twox_128", - &b"Hello world!".to_vec().encode(), - ).unwrap(), - hex!("b27dfd7f223f177f2a13647b533599af").to_vec().encode(), - ); - } - - #[test] - fn ed25519_verify_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - let key = ed25519::Pair::from_seed(&blake2_256(b"test")); - let sig = key.sign(b"all ok!"); - let mut calldata = vec![]; - calldata.extend_from_slice(key.public().as_ref()); - calldata.extend_from_slice(sig.as_ref()); - - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_ed25519_verify", &calldata.encode()).unwrap(), - true.encode(), - ); - - let other_sig = key.sign(b"all is not ok!"); - let mut calldata = vec![]; - calldata.extend_from_slice(key.public().as_ref()); - calldata.extend_from_slice(other_sig.as_ref()); - - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_ed25519_verify", &calldata.encode()).unwrap(), - false.encode(), - ); - } - - #[test] - fn sr25519_verify_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - let key = sr25519::Pair::from_seed(&blake2_256(b"test")); - let sig = key.sign(b"all ok!"); - let mut calldata = vec![]; - calldata.extend_from_slice(key.public().as_ref()); - calldata.extend_from_slice(sig.as_ref()); - - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_sr25519_verify", &calldata.encode()).unwrap(), - true.encode(), - ); - - let other_sig = key.sign(b"all is not ok!"); - let mut calldata = vec![]; - calldata.extend_from_slice(key.public().as_ref()); - calldata.extend_from_slice(other_sig.as_ref()); - - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_sr25519_verify", &calldata.encode()).unwrap(), - false.encode(), - ); - } - - #[test] - fn ordered_trie_root_should_work() { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let trie_input = vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()]; - let test_code = WASM_BINARY; - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_ordered_trie_root", &[0]).unwrap(), - Layout::::ordered_trie_root(trie_input.iter()).as_bytes().encode(), - ); - } - - #[test] - fn offchain_local_storage_should_work() { - use substrate_client::backend::OffchainStorage; - - let mut ext = TestExternalities::default(); - let (offchain, state) = testing::TestOffchainExt::new(); - ext.register_extension(OffchainExt::new(offchain)); - let test_code = WASM_BINARY; - let mut ext = ext.ext(); - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_offchain_local_storage", &[0]).unwrap(), - true.encode(), - ); - assert_eq!(state.read().persistent_storage.get(b"", b"test"), Some(vec![])); - } - - #[test] - fn offchain_http_should_work() { - let mut ext = TestExternalities::default(); - let (offchain, state) = testing::TestOffchainExt::new(); - ext.register_extension(OffchainExt::new(offchain)); - state.write().expect_request( - 0, - testing::PendingRequest { - method: "POST".into(), - uri: "http://localhost:12345".into(), - body: vec![1, 2, 3, 4], - headers: vec![("X-Auth".to_owned(), "test".to_owned())], - sent: true, - response: Some(vec![1, 2, 3]), - response_headers: vec![("X-Auth".to_owned(), "hello".to_owned())], - ..Default::default() - }, - ); - - let test_code = WASM_BINARY; - let mut ext = ext.ext(); - assert_eq!( - call(&mut ext, 8, &test_code[..], "test_offchain_http", &[0]).unwrap(), - true.encode(), - ); - } -} diff --git a/core/externalities/Cargo.toml b/core/externalities/Cargo.toml deleted file mode 100644 index 97ece5439ac99..0000000000000 --- a/core/externalities/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "substrate-externalities" -version = "2.0.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -primitive-types = { version = "0.5.1", features = ["codec"] } -primitives-storage = { package = "substrate-primitives-storage", path = "../primitives/storage" } -rstd = { package = "sr-std", path = "../sr-std" } -environmental = { version = "1.0.2" } diff --git a/core/externalities/src/lib.rs b/core/externalities/src/lib.rs deleted file mode 100644 index ecd5f7a7a751d..0000000000000 --- a/core/externalities/src/lib.rs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate externalities abstraction -//! -//! The externalities mainly provide access to storage and to registered extensions. Extensions -//! are for example the keystore or the offchain externalities. These externalities are used to -//! access the node from the runtime via the runtime interfaces. -//! -//! This crate exposes the main [`Externalities`] trait. - -use primitive_types::H256; - -use std::any::{Any, TypeId}; - -use primitives_storage::ChildStorageKey; - -pub use scope_limited::{set_and_run_with_externalities, with_externalities}; -pub use extensions::{Extension, Extensions, ExtensionStore}; - -mod extensions; -mod scope_limited; - -/// The Substrate externalities. -/// -/// Provides access to the storage and to other registered extensions. -pub trait Externalities: ExtensionStore { - /// Read runtime storage. - fn storage(&self, key: &[u8]) -> Option>; - - /// Get storage value hash. This may be optimized for large values. - fn storage_hash(&self, key: &[u8]) -> Option; - - /// Get child storage value hash. This may be optimized for large values. - fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option; - - /// Read original runtime storage, ignoring any overlayed changes. - fn original_storage(&self, key: &[u8]) -> Option>; - - /// Read original runtime child storage, ignoring any overlayed changes. - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; - - /// Get original storage value hash, ignoring any overlayed changes. - /// This may be optimized for large values. - fn original_storage_hash(&self, key: &[u8]) -> Option; - - /// Get original child storage value hash, ignoring any overlayed changes. - /// This may be optimized for large values. - fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option; - - /// Read child runtime storage. - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; - - /// Set storage entry `key` of current contract being called (effective immediately). - fn set_storage(&mut self, key: Vec, value: Vec) { - self.place_storage(key, Some(value)); - } - - /// Set child storage entry `key` of current contract being called (effective immediately). - fn set_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Vec) { - self.place_child_storage(storage_key, key, Some(value)) - } - - /// Clear a storage entry (`key`) of current contract being called (effective immediately). - fn clear_storage(&mut self, key: &[u8]) { - self.place_storage(key.to_vec(), None); - } - - /// Clear a child storage entry (`key`) of current contract being called (effective immediately). - fn clear_child_storage(&mut self, storage_key: ChildStorageKey, key: &[u8]) { - self.place_child_storage(storage_key, key.to_vec(), None) - } - - /// Whether a storage entry exists. - fn exists_storage(&self, key: &[u8]) -> bool { - self.storage(key).is_some() - } - - /// Whether a child storage entry exists. - fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { - self.child_storage(storage_key, key).is_some() - } - - /// Clear an entire child storage. - fn kill_child_storage(&mut self, storage_key: ChildStorageKey); - - /// Clear storage entries which keys are start with the given prefix. - fn clear_prefix(&mut self, prefix: &[u8]); - - /// Clear child storage entries which keys are start with the given prefix. - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]); - - /// Set or clear a storage entry (`key`) of current contract being called (effective immediately). - fn place_storage(&mut self, key: Vec, value: Option>); - - /// Set or clear a child storage entry. Return whether the operation succeeds. - fn place_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Option>); - - /// Get the identity of the chain. - fn chain_id(&self) -> u64; - - /// Get the trie root of the current storage map. This will also update all child storage keys - /// in the top-level storage map. - fn storage_root(&mut self) -> H256; - - /// Get the trie root of a child storage map. This will also update the value of the child - /// storage keys in the top-level storage map. - /// If the storage root equals the default hash as defined by the trie, the key in the top-level - /// storage map will be removed. - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec; - - /// Get the change trie root of the current storage overlay at a block with given parent. - fn storage_changes_root(&mut self, parent: H256) -> Result, ()>; -} - -/// Extension for the [`Externalities`] trait. -pub trait ExternalitiesExt { - /// Tries to find a registered extension and returns a mutable reference. - fn extension(&mut self) -> Option<&mut T>; -} - -impl ExternalitiesExt for T { - fn extension(&mut self) -> Option<&mut A> { - self.extension_by_type_id(TypeId::of::()).and_then(Any::downcast_mut) - } -} diff --git a/core/finality-grandpa/Cargo.toml b/core/finality-grandpa/Cargo.toml deleted file mode 100644 index 5148338d0fb75..0000000000000 --- a/core/finality-grandpa/Cargo.toml +++ /dev/null @@ -1,43 +0,0 @@ -[package] -name = "substrate-finality-grandpa" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -fork-tree = { path = "../../core/utils/fork-tree" } -futures01 = { package = "futures", version = "0.1.29" } -futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } -futures-timer = "0.3.0" -log = "0.4.8" -parking_lot = "0.9.0" -tokio-executor = "0.1.8" -rand = "0.7.2" -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } -sr-primitives = { path = "../sr-primitives" } -consensus_common = { package = "substrate-consensus-common", path = "../consensus/common" } -primitives = { package = "substrate-primitives", path = "../primitives" } -substrate-telemetry = { path = "../telemetry" } -keystore = { package = "substrate-keystore", path = "../keystore" } -serde_json = "1.0.41" -client = { package = "substrate-client", path = "../client" } -header-metadata = { package = "substrate-header-metadata", path = "../client/header-metadata" } -inherents = { package = "substrate-inherents", path = "../../core/inherents" } -network = { package = "substrate-network", path = "../network" } -srml-finality-tracker = { path = "../../srml/finality-tracker" } -fg_primitives = { package = "substrate-finality-grandpa-primitives", path = "primitives" } -# TODO: switch to crates.io version -grandpa = { package = "finality-grandpa", git = "https://github.com/paritytech/finality-grandpa", features = ["derive-codec"] } -#grandpa = { package = "finality-grandpa", version = "0.9.0", features = ["derive-codec"] } - -[dev-dependencies] -# TODO: switch to crates.io version -grandpa = { package = "finality-grandpa", git = "https://github.com/paritytech/finality-grandpa", features = ["derive-codec", "test-helpers"] } -#grandpa = { package = "finality-grandpa", version = "0.9.0", features = ["derive-codec", "test-helpers"] } -network = { package = "substrate-network", path = "../network", features = ["test-helpers"] } -keyring = { package = "substrate-keyring", path = "../keyring" } -test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client"} -babe_primitives = { package = "substrate-consensus-babe-primitives", path = "../consensus/babe/primitives" } -env_logger = "0.7.0" -tempfile = "3.1.0" -tokio = "0.1" diff --git a/core/finality-grandpa/primitives/Cargo.toml b/core/finality-grandpa/primitives/Cargo.toml deleted file mode 100644 index 02439d4150d81..0000000000000 --- a/core/finality-grandpa/primitives/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "substrate-finality-grandpa-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../../client", default-features = false } -app-crypto = { package = "substrate-application-crypto", path = "../../application-crypto", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sr-primitives = { path = "../../sr-primitives", default-features = false } -rstd = { package = "sr-std", path = "../../sr-std", default-features = false } -serde = { version = "1.0.101", optional = true, features = ["derive"] } - -[features] -default = ["std"] -std = [ - "client/std", - "codec/std", - "sr-primitives/std", - "rstd/std", - "serde", - "app-crypto/std", -] diff --git a/core/finality-grandpa/primitives/src/lib.rs b/core/finality-grandpa/primitives/src/lib.rs deleted file mode 100644 index 27139bbeeffa8..0000000000000 --- a/core/finality-grandpa/primitives/src/lib.rs +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Primitives for GRANDPA integration, suitable for WASM compilation. - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(not(feature = "std"))] -extern crate alloc; - -#[cfg(feature = "std")] -use serde::Serialize; -use codec::{Encode, Decode, Codec}; -use sr_primitives::{ConsensusEngineId, RuntimeDebug}; -use client::decl_runtime_apis; -use rstd::vec::Vec; - -mod app { - use app_crypto::{app_crypto, key_types::GRANDPA, ed25519}; - app_crypto!(ed25519, GRANDPA); -} - -/// The grandpa crypto scheme defined via the keypair type. -#[cfg(feature = "std")] -pub type AuthorityPair = app::Pair; - -/// Identity of a Grandpa authority. -pub type AuthorityId = app::Public; - -/// Signature for a Grandpa authority. -pub type AuthoritySignature = app::Signature; - -/// The `ConsensusEngineId` of GRANDPA. -pub const GRANDPA_ENGINE_ID: ConsensusEngineId = *b"FRNK"; - -/// The weight of an authority. -pub type AuthorityWeight = u64; - -/// The index of an authority. -pub type AuthorityIndex = u64; - -/// The monotonic identifier of a GRANDPA set of authorities. -pub type SetId = u64; - -/// The round indicator. -pub type RoundNumber = u64; - -/// A scheduled change of authority set. -#[cfg_attr(feature = "std", derive(Serialize))] -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] -pub struct ScheduledChange { - /// The new authorities after the change, along with their respective weights. - pub next_authorities: Vec<(AuthorityId, AuthorityWeight)>, - /// The number of blocks to delay. - pub delay: N, -} - -/// An consensus log item for GRANDPA. -#[cfg_attr(feature = "std", derive(Serialize))] -#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)] -pub enum ConsensusLog { - /// Schedule an authority set change. - /// - /// The earliest digest of this type in a single block will be respected, - /// provided that there is no `ForcedChange` digest. If there is, then the - /// `ForcedChange` will take precedence. - /// - /// No change should be scheduled if one is already and the delay has not - /// passed completely. - /// - /// 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. - #[codec(index = "1")] - ScheduledChange(ScheduledChange), - /// Force an authority set change. - /// - /// Forced changes are applied after a delay of _imported_ blocks, - /// while pending changes are applied after a delay of _finalized_ blocks. - /// - /// The earliest digest of this type in a single block will be respected, - /// with others ignored. - /// - /// No change should be scheduled if one is already and the delay has not - /// passed completely. - /// - /// 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. - #[codec(index = "2")] - ForcedChange(N, ScheduledChange), - /// Note that the authority with given index is disabled until the next change. - #[codec(index = "3")] - OnDisabled(AuthorityIndex), - /// A signal to pause the current authority set after the given delay. - /// After finalizing the block at _delay_ the authorities should stop voting. - #[codec(index = "4")] - Pause(N), - /// A signal to resume the current authority set after the given delay. - /// After authoring the block at _delay_ the authorities should resume voting. - #[codec(index = "5")] - Resume(N), -} - -impl ConsensusLog { - /// Try to cast the log entry as a contained signal. - pub fn try_into_change(self) -> Option> { - match self { - ConsensusLog::ScheduledChange(change) => Some(change), - _ => None, - } - } - - /// Try to cast the log entry as a contained forced signal. - pub fn try_into_forced_change(self) -> Option<(N, ScheduledChange)> { - match self { - ConsensusLog::ForcedChange(median, change) => Some((median, change)), - _ => None, - } - } - - /// Try to cast the log entry as a contained pause signal. - pub fn try_into_pause(self) -> Option { - match self { - ConsensusLog::Pause(delay) => Some(delay), - _ => None, - } - } - - /// Try to cast the log entry as a contained resume signal. - pub fn try_into_resume(self) -> Option { - match self { - ConsensusLog::Resume(delay) => Some(delay), - _ => None, - } - } -} - -/// WASM function call to check for pending changes. -pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change"; -/// WASM function call to get current GRANDPA authorities. -pub const AUTHORITIES_CALL: &str = "grandpa_authorities"; - -decl_runtime_apis! { - /// APIs for integrating the GRANDPA finality gadget into runtimes. - /// This should be implemented on the runtime side. - /// - /// This is primarily used for negotiating authority-set changes for the - /// gadget. GRANDPA uses a signaling model of changing authority sets: - /// changes should be signaled with a delay of N blocks, and then automatically - /// applied in the runtime after those N blocks have passed. - /// - /// The consensus protocol will coordinate the handoff externally. - #[api_version(2)] - pub trait GrandpaApi { - /// 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, AuthorityWeight)>; - } -} diff --git a/core/finality-grandpa/src/aux_schema.rs b/core/finality-grandpa/src/aux_schema.rs deleted file mode 100644 index a2b05a0cd60e1..0000000000000 --- a/core/finality-grandpa/src/aux_schema.rs +++ /dev/null @@ -1,610 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Schema for stuff in the aux-db. - -use std::fmt::Debug; -use std::sync::Arc; -use codec::{Encode, Decode}; -use client::backend::AuxStore; -use client::error::{Result as ClientResult, Error as ClientError}; -use fork_tree::ForkTree; -use grandpa::round::State as RoundState; -use sr_primitives::traits::{Block as BlockT, NumberFor}; -use log::{info, warn}; -use fg_primitives::{AuthorityId, AuthorityWeight, SetId, RoundNumber}; - -use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind}; -use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges}; -use crate::environment::{ - CompletedRound, CompletedRounds, CurrentRounds, HasVoted, SharedVoterSetState, VoterSetState, -}; -use crate::NewAuthoritySet; - -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 = 2; - -/// The voter set state. -#[derive(Debug, Clone, Encode, Decode)] -#[cfg_attr(test, derive(PartialEq))] -pub enum V1VoterSetState { - /// The voter set state, currently paused. - Paused(RoundNumber, RoundState), - /// The voter set state, currently live. - Live(RoundNumber, RoundState), -} - -type V0VoterSetState = (RoundNumber, RoundState); - -#[derive(Debug, Clone, Encode, Decode, PartialEq)] -struct V0PendingChange { - next_authorities: Vec<(AuthorityId, AuthorityWeight)>, - delay: N, - canon_height: N, - canon_hash: H, -} - -#[derive(Debug, Clone, Encode, Decode, PartialEq)] -struct V0AuthoritySet { - current_authorities: Vec<(AuthorityId, AuthorityWeight)>, - set_id: SetId, - 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 - } - } -} - -pub(crate) fn load_decode(backend: &B, key: &[u8]) -> ClientResult> { - match backend.get_aux(key)? { - None => Ok(None), - Some(t) => T::decode(&mut &t[..]) - .map_err( - |e| ClientError::Backend(format!("GRANDPA DB is corrupted: {}", e.what())), - ) - .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: SharedVoterSetState, -} - -fn migrate_from_version0( - backend: &B, - genesis_round: &G, -) -> ClientResult>, - VoterSetState, -)>> where B: AuxStore, - G: Fn() -> RoundState>, -{ - 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 (last_round_number, last_round_state) = match load_decode::<_, V0VoterSetState>>( - backend, - SET_STATE_KEY, - )? { - Some((number, state)) => (number, state), - None => (0, genesis_round()), - }; - - let set_id = new_set.current().0; - - let base = last_round_state.prevote_ghost - .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); - - let mut current_rounds = CurrentRounds::new(); - current_rounds.insert(last_round_number + 1, HasVoted::No); - - let set_state = VoterSetState::Live { - completed_rounds: CompletedRounds::new( - CompletedRound { - number: last_round_number, - state: last_round_state, - votes: Vec::new(), - base, - }, - set_id, - &new_set, - ), - current_rounds, - }; - - backend.insert_aux(&[(SET_STATE_KEY, set_state.encode().as_slice())], &[])?; - - return Ok(Some((new_set, set_state))); - } - - Ok(None) -} - -fn migrate_from_version1( - backend: &B, - genesis_round: &G, -) -> ClientResult>, - VoterSetState, -)>> where B: AuxStore, - G: Fn() -> RoundState>, -{ - CURRENT_VERSION.using_encoded(|s| - backend.insert_aux(&[(VERSION_KEY, s)], &[]) - )?; - - if let Some(set) = load_decode::<_, AuthoritySet>>( - backend, - AUTHORITY_SET_KEY, - )? { - let set_id = set.current().0; - - let completed_rounds = |number, state, base| CompletedRounds::new( - CompletedRound { - number, - state, - votes: Vec::new(), - base, - }, - set_id, - &set, - ); - - let set_state = match load_decode::<_, V1VoterSetState>>( - backend, - SET_STATE_KEY, - )? { - Some(V1VoterSetState::Paused(last_round_number, set_state)) => { - let base = set_state.prevote_ghost - .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); - - VoterSetState::Paused { - completed_rounds: completed_rounds(last_round_number, set_state, base), - } - }, - Some(V1VoterSetState::Live(last_round_number, set_state)) => { - let base = set_state.prevote_ghost - .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); - - let mut current_rounds = CurrentRounds::new(); - current_rounds.insert(last_round_number + 1, HasVoted::No); - - VoterSetState::Live { - completed_rounds: completed_rounds(last_round_number, set_state, base), - current_rounds, - } - }, - None => { - let set_state = genesis_round(); - let base = set_state.prevote_ghost - .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); - - VoterSetState::live( - set_id, - &set, - base, - ) - }, - }; - - backend.insert_aux(&[(SET_STATE_KEY, set_state.encode().as_slice())], &[])?; - - return Ok(Some((set, set_state))); - } - - Ok(None) -} - -/// Load or initialize persistent data from backend. -pub(crate) fn load_persistent( - backend: &B, - genesis_hash: Block::Hash, - genesis_number: NumberFor, - genesis_authorities: G, -) - -> ClientResult> - where - B: AuxStore, - 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 => { - if let Some((new_set, set_state)) = migrate_from_version0::(backend, &make_genesis_round)? { - return Ok(PersistentData { - authority_set: new_set.into(), - consensus_changes: Arc::new(consensus_changes.into()), - set_state: set_state.into(), - }); - } - }, - Some(1) => { - if let Some((new_set, set_state)) = migrate_from_version1::(backend, &make_genesis_round)? { - return Ok(PersistentData { - authority_set: new_set.into(), - consensus_changes: Arc::new(consensus_changes.into()), - set_state: set_state.into(), - }); - } - }, - Some(2) => { - 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 => { - let state = make_genesis_round(); - let base = state.prevote_ghost - .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); - - VoterSetState::live( - set.current().0, - &set, - base, - ) - } - }; - - return Ok(PersistentData { - authority_set: set.into(), - consensus_changes: Arc::new(consensus_changes.into()), - set_state: set_state.into(), - }); - } - } - Some(other) => return Err(ClientError::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_authorities = genesis_authorities()?; - let genesis_set = AuthoritySet::genesis(genesis_authorities.clone()); - let state = make_genesis_round(); - let base = state.prevote_ghost - .expect("state is for completed round; completed rounds must have a prevote ghost; qed."); - - let genesis_state = VoterSetState::live( - 0, - &genesis_set, - base, - ); - - 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.into(), - consensus_changes: Arc::new(consensus_changes.into()), - }) -} - -/// Update the authority set on disk after a change. -/// -/// If there has just been a handoff, pass a `new_set` parameter that describes the -/// handoff. `set` in all cases should reflect the current authority set, with all -/// changes and handoffs applied. -pub(crate) fn update_authority_set( - set: &AuthoritySet>, - new_set: Option<&NewAuthoritySet>>, - write_aux: F -) -> R where - 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 set_state = VoterSetState::::live( - new_set.set_id, - &set, - (new_set.canon_hash, new_set.canon_number), - ); - 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<()> { - 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") -} - -#[cfg(test)] -mod test { - use primitives::H256; - use test_client; - use super::*; - - #[test] - fn load_decode_from_v0_migrates_data_format() { - let client = test_client::new(); - - let authorities = vec![(AuthorityId::default(), 100)]; - let set_id = 3; - let round_number: RoundNumber = 42; - let round_state = RoundState:: { - prevote_ghost: Some((H256::random(), 32)), - finalized: None, - estimate: None, - completable: false, - }; - - { - let authority_set = V0AuthoritySet:: { - current_authorities: authorities.clone(), - pending_changes: Vec::new(), - set_id, - }; - - let voter_set_state = (round_number, round_state.clone()); - - client.insert_aux( - &[ - (AUTHORITY_SET_KEY, authority_set.encode().as_slice()), - (SET_STATE_KEY, voter_set_state.encode().as_slice()), - ], - &[], - ).unwrap(); - } - - assert_eq!( - load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), - None, - ); - - // should perform the migration - load_persistent::( - &client, - H256::random(), - 0, - || unreachable!(), - ).unwrap(); - - assert_eq!( - load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), - Some(2), - ); - - let PersistentData { authority_set, set_state, .. } = load_persistent::( - &client, - H256::random(), - 0, - || unreachable!(), - ).unwrap(); - - assert_eq!( - *authority_set.inner().read(), - AuthoritySet { - current_authorities: authorities.clone(), - pending_standard_changes: ForkTree::new(), - pending_forced_changes: Vec::new(), - set_id, - }, - ); - - let mut current_rounds = CurrentRounds::new(); - current_rounds.insert(round_number + 1, HasVoted::No); - - assert_eq!( - &*set_state.read(), - &VoterSetState::Live { - completed_rounds: CompletedRounds::new( - CompletedRound { - number: round_number, - state: round_state.clone(), - base: round_state.prevote_ghost.unwrap(), - votes: vec![], - }, - set_id, - &*authority_set.inner().read(), - ), - current_rounds, - }, - ); - } - - #[test] - fn load_decode_from_v1_migrates_data_format() { - let client = test_client::new(); - - let authorities = vec![(AuthorityId::default(), 100)]; - let set_id = 3; - let round_number: RoundNumber = 42; - let round_state = RoundState:: { - prevote_ghost: Some((H256::random(), 32)), - finalized: None, - estimate: None, - completable: false, - }; - - { - let authority_set = AuthoritySet:: { - current_authorities: authorities.clone(), - pending_standard_changes: ForkTree::new(), - pending_forced_changes: Vec::new(), - set_id, - }; - - let voter_set_state = V1VoterSetState::Live(round_number, round_state.clone()); - - client.insert_aux( - &[ - (AUTHORITY_SET_KEY, authority_set.encode().as_slice()), - (SET_STATE_KEY, voter_set_state.encode().as_slice()), - (VERSION_KEY, 1u32.encode().as_slice()), - ], - &[], - ).unwrap(); - } - - assert_eq!( - load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), - Some(1), - ); - - // should perform the migration - load_persistent::( - &client, - H256::random(), - 0, - || unreachable!(), - ).unwrap(); - - assert_eq!( - load_decode::<_, u32>(&client, VERSION_KEY).unwrap(), - Some(2), - ); - - let PersistentData { authority_set, set_state, .. } = load_persistent::( - &client, - H256::random(), - 0, - || unreachable!(), - ).unwrap(); - - assert_eq!( - *authority_set.inner().read(), - AuthoritySet { - current_authorities: authorities.clone(), - pending_standard_changes: ForkTree::new(), - pending_forced_changes: Vec::new(), - set_id, - }, - ); - - let mut current_rounds = CurrentRounds::new(); - current_rounds.insert(round_number + 1, HasVoted::No); - - assert_eq!( - &*set_state.read(), - &VoterSetState::Live { - completed_rounds: CompletedRounds::new( - CompletedRound { - number: round_number, - state: round_state.clone(), - base: round_state.prevote_ghost.unwrap(), - votes: vec![], - }, - set_id, - &*authority_set.inner().read(), - ), - current_rounds, - }, - ); - } -} diff --git a/core/finality-grandpa/src/communication/gossip.rs b/core/finality-grandpa/src/communication/gossip.rs deleted file mode 100644 index c15c1594d2186..0000000000000 --- a/core/finality-grandpa/src/communication/gossip.rs +++ /dev/null @@ -1,1897 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Gossip and politeness for polite-grandpa. -//! -//! This module implements the following message types: -//! #### Neighbor Packet -//! -//! The neighbor packet is sent to only our neighbors. It contains this information -//! -//! - Current Round -//! - Current voter set ID -//! - Last finalized hash from commit messages. -//! -//! If a peer is at a given voter set, it is impolite to send messages from -//! an earlier voter set. It is extremely impolite to send messages -//! from a future voter set. "future-set" messages can be dropped and ignored. -//! -//! If a peer is at round r, is impolite to send messages about r-2 or earlier and extremely -//! impolite to send messages about r+1 or later. "future-round" messages can -//! be dropped and ignored. -//! -//! It is impolite to send a neighbor packet which moves backwards in protocol state. -//! -//! This is beneficial if it conveys some progress in the protocol state of the peer. -//! -//! #### Prevote / Precommit -//! -//! These are votes within a round. Noting that we receive these messages -//! from our peers who are not necessarily voters, we have to account the benefit -//! based on what they might have seen. -//! -//! #### Propose -//! -//! This is a broadcast by a known voter of the last-round estimate. -//! -//! #### Commit -//! -//! These are used to announce past agreement of finality. -//! -//! It is impolite to send commits which are earlier than the last commit -//! sent. It is especially impolite to send commits which are invalid, or from -//! a different Set ID than the receiving peer has indicated. -//! -//! Sending a commit is polite when it may finalize something that the receiving peer -//! was not aware of. -//! -//! #### Catch Up -//! -//! These allow a peer to request another peer, which they perceive to be in a -//! later round, to provide all the votes necessary to complete a given round -//! `R`. -//! -//! It is impolite to send a catch up request for a round `R` to a peer whose -//! announced view is behind `R`. It is also impolite to send a catch up request -//! to a peer in a new different Set ID. -//! -//! The logic for issuing and tracking pending catch up requests is implemented -//! in the `GossipValidator`. A catch up request is issued anytime we see a -//! neighbor packet from a peer at a round `CATCH_UP_THRESHOLD` higher than at -//! we are. -//! -//! ## Expiration -//! -//! We keep some amount of recent rounds' messages, but do not accept new ones from rounds -//! older than our current_round - 1. -//! -//! ## Message Validation -//! -//! We only send polite messages to peers, - -use sr_primitives::traits::{NumberFor, Block as BlockT, Zero}; -use network::consensus_gossip::{self as network_gossip, MessageIntent, ValidatorContext}; -use network::{config::Roles, PeerId}; -use codec::{Encode, Decode}; -use fg_primitives::AuthorityId; - -use substrate_telemetry::{telemetry, CONSENSUS_DEBUG}; -use log::{trace, debug}; -use futures::prelude::*; -use futures::channel::mpsc; - -use crate::{environment, CatchUp, CompactCommit, SignedMessage}; -use super::{cost, benefit, Round, SetId}; - -use std::collections::{HashMap, VecDeque}; -use std::pin::Pin; -use std::task::{Context, Poll}; -use std::time::{Duration, Instant}; - -const REBROADCAST_AFTER: Duration = Duration::from_secs(60 * 5); -const CATCH_UP_REQUEST_TIMEOUT: Duration = Duration::from_secs(5); -const CATCH_UP_PROCESS_TIMEOUT: Duration = Duration::from_secs(15); -/// Maximum number of rounds we are behind a peer before issuing a -/// catch up request. -const CATCH_UP_THRESHOLD: u64 = 2; - -type Report = (PeerId, i32); - -/// An outcome of examining a message. -#[derive(Debug, PartialEq, Clone, Copy)] -enum Consider { - /// Accept the message. - Accept, - /// Message is too early. Reject. - RejectPast, - /// Message is from the future. Reject. - RejectFuture, - /// Message cannot be evaluated. Reject. - RejectOutOfScope, -} - -/// A view of protocol state. -#[derive(Debug)] -struct View { - round: Round, // the current round we are at. - set_id: SetId, // the current voter set id. - last_commit: Option, // commit-finalized block height, if any. -} - -impl Default for View { - fn default() -> Self { - View { - round: Round(1), - set_id: SetId(0), - last_commit: None, - } - } -} - -impl View { - /// Update the set ID. implies a reset to round 0. - fn update_set(&mut self, set_id: SetId) { - if set_id != self.set_id { - self.set_id = set_id; - self.round = Round(1); - } - } - - /// Consider a round and set ID combination under a current view. - fn consider_vote(&self, round: Round, set_id: SetId) -> Consider { - // only from current set - if set_id < self.set_id { return Consider::RejectPast } - if set_id > self.set_id { return Consider::RejectFuture } - - // only r-1 ... r+1 - if round.0 > self.round.0.saturating_add(1) { return Consider::RejectFuture } - if round.0 < self.round.0.saturating_sub(1) { return Consider::RejectPast } - - Consider::Accept - } - - /// Consider a set-id global message. Rounds are not taken into account, but are implicitly - /// because we gate on finalization of a further block than a previous commit. - fn consider_global(&self, set_id: SetId, number: N) -> Consider { - // only from current set - if set_id < self.set_id { return Consider::RejectPast } - if set_id > self.set_id { return Consider::RejectFuture } - - // only commits which claim to prove a higher block number than - // the one we're aware of. - match self.last_commit { - None => Consider::Accept, - Some(ref num) => if num < &number { - Consider::Accept - } else { - Consider::RejectPast - } - } - } -} - -const KEEP_RECENT_ROUNDS: usize = 3; - -/// Tracks gossip topics that we are keeping messages for. We keep topics of: -/// -/// - the last `KEEP_RECENT_ROUNDS` complete GRANDPA rounds, -/// -/// - the topic for the current and next round, -/// -/// - and a global topic for commit and catch-up messages. -struct KeepTopics { - current_set: SetId, - rounds: VecDeque<(Round, SetId)>, - reverse_map: HashMap, SetId)> -} - -impl KeepTopics { - fn new() -> Self { - KeepTopics { - current_set: SetId(0), - rounds: VecDeque::with_capacity(KEEP_RECENT_ROUNDS + 2), - reverse_map: HashMap::new(), - } - } - - fn push(&mut self, round: Round, set_id: SetId) { - self.current_set = std::cmp::max(self.current_set, set_id); - - // under normal operation the given round is already tracked (since we - // track one round ahead). if we skip rounds (with a catch up) the given - // round topic might not be tracked yet. - if !self.rounds.contains(&(round, set_id)) { - self.rounds.push_back((round, set_id)); - } - - // we also accept messages for the next round - self.rounds.push_back((Round(round.0.saturating_add(1)), set_id)); - - // the 2 is for the current and next round. - while self.rounds.len() > KEEP_RECENT_ROUNDS + 2 { - let _ = self.rounds.pop_front(); - } - - let mut map = HashMap::with_capacity(KEEP_RECENT_ROUNDS + 3); - map.insert(super::global_topic::(self.current_set.0), (None, self.current_set)); - - for &(round, set) in &self.rounds { - map.insert( - super::round_topic::(round.0, set.0), - (Some(round), set) - ); - } - - self.reverse_map = map; - } - - fn topic_info(&self, topic: &B::Hash) -> Option<(Option, SetId)> { - self.reverse_map.get(topic).cloned() - } -} - -// topics to send to a neighbor based on their view. -fn neighbor_topics(view: &View>) -> Vec { - let s = view.set_id; - let mut topics = vec![ - super::global_topic::(s.0), - super::round_topic::(view.round.0, s.0), - ]; - - if view.round.0 != 0 { - let r = Round(view.round.0 - 1); - topics.push(super::round_topic::(r.0, s.0)) - } - - topics -} - -/// Grandpa gossip message type. -/// This is the root type that gets encoded and sent on the network. -#[derive(Debug, Encode, Decode)] -pub(super) enum GossipMessage { - /// Grandpa message with round and set info. - Vote(VoteMessage), - /// Grandpa commit message with round and set info. - Commit(FullCommitMessage), - /// A neighbor packet. Not repropagated. - Neighbor(VersionedNeighborPacket>), - /// Grandpa catch up request message with round and set info. Not repropagated. - CatchUpRequest(CatchUpRequestMessage), - /// Grandpa catch up message with round and set info. Not repropagated. - CatchUp(FullCatchUpMessage), -} - -impl From>> for GossipMessage { - fn from(neighbor: NeighborPacket>) -> Self { - GossipMessage::Neighbor(VersionedNeighborPacket::V1(neighbor)) - } -} - -/// Network level vote message with topic information. -#[derive(Debug, Encode, Decode)] -pub(super) struct VoteMessage { - /// The round this message is from. - pub(super) round: Round, - /// The voter set ID this message is from. - pub(super) set_id: SetId, - /// The message itself. - pub(super) message: SignedMessage, -} - -/// Network level commit message with topic information. -#[derive(Debug, Encode, Decode)] -pub(super) struct FullCommitMessage { - /// The round this message is from. - pub(super) round: Round, - /// The voter set ID this message is from. - pub(super) set_id: SetId, - /// The compact commit message. - pub(super) message: CompactCommit, -} - -/// V1 neighbor packet. Neighbor packets are sent from nodes to their peers -/// and are not repropagated. These contain information about the node's state. -#[derive(Debug, Encode, Decode, Clone)] -pub(super) struct NeighborPacket { - /// The round the node is currently at. - pub(super) round: Round, - /// The set ID the node is currently at. - pub(super) set_id: SetId, - /// The highest finalizing commit observed. - pub(super) commit_finalized_height: N, -} - -/// A versioned neighbor packet. -#[derive(Debug, Encode, Decode)] -pub(super) enum VersionedNeighborPacket { - #[codec(index = "1")] - V1(NeighborPacket), -} - -impl VersionedNeighborPacket { - fn into_neighbor_packet(self) -> NeighborPacket { - match self { - VersionedNeighborPacket::V1(p) => p, - } - } -} - -/// A catch up request for a given round (or any further round) localized by set id. -#[derive(Clone, Debug, Encode, Decode)] -pub(super) struct CatchUpRequestMessage { - /// The round that we want to catch up to. - pub(super) round: Round, - /// The voter set ID this message is from. - pub(super) set_id: SetId, -} - -/// Network level catch up message with topic information. -#[derive(Debug, Encode, Decode)] -pub(super) struct FullCatchUpMessage { - /// The voter set ID this message is from. - pub(super) set_id: SetId, - /// The compact commit message. - pub(super) message: CatchUp, -} - -/// Misbehavior that peers can perform. -/// -/// `cost` gives a cost that can be used to perform cost/benefit analysis of a -/// peer. -#[derive(Clone, Copy, Debug, PartialEq)] -pub(super) enum Misbehavior { - // invalid neighbor message, considering the last one. - InvalidViewChange, - // could not decode neighbor message. bytes-length of the packet. - UndecodablePacket(i32), - // Bad catch up message (invalid signatures). - BadCatchUpMessage { - signatures_checked: i32, - }, - // Bad commit message - BadCommitMessage { - signatures_checked: i32, - blocks_loaded: i32, - equivocations_caught: i32, - }, - // A message received that's from the future relative to our view. - // always misbehavior. - FutureMessage, - // A message received that cannot be evaluated relative to our view. - // This happens before we have a view and have sent out neighbor packets. - // always misbehavior. - OutOfScopeMessage, -} - -impl Misbehavior { - pub(super) fn cost(&self) -> i32 { - use Misbehavior::*; - - match *self { - InvalidViewChange => cost::INVALID_VIEW_CHANGE, - UndecodablePacket(bytes) => bytes.saturating_mul(cost::PER_UNDECODABLE_BYTE), - BadCatchUpMessage { signatures_checked } => - cost::PER_SIGNATURE_CHECKED.saturating_mul(signatures_checked), - BadCommitMessage { signatures_checked, blocks_loaded, equivocations_caught } => { - let cost = cost::PER_SIGNATURE_CHECKED - .saturating_mul(signatures_checked) - .saturating_add(cost::PER_BLOCK_LOADED.saturating_mul(blocks_loaded)); - - let benefit = equivocations_caught.saturating_mul(benefit::PER_EQUIVOCATION); - - (benefit as i32).saturating_add(cost as i32) - }, - FutureMessage => cost::FUTURE_MESSAGE, - OutOfScopeMessage => cost::OUT_OF_SCOPE_MESSAGE, - } - } -} - -struct PeerInfo { - view: View, - roles: Roles, -} - -impl PeerInfo { - fn new(roles: Roles) -> Self { - PeerInfo { - view: View::default(), - roles, - } - } -} - -/// The peers we're connected do in gossip. -struct Peers { - inner: HashMap>, -} - -impl Default for Peers { - fn default() -> Self { - Peers { inner: HashMap::new() } - } -} - -impl Peers { - fn new_peer(&mut self, who: PeerId, roles: Roles) { - self.inner.insert(who, PeerInfo::new(roles)); - } - - fn peer_disconnected(&mut self, who: &PeerId) { - self.inner.remove(who); - } - - // returns a reference to the new view, if the peer is known. - fn update_peer_state(&mut self, who: &PeerId, update: NeighborPacket) - -> Result>, Misbehavior> - { - let peer = match self.inner.get_mut(who) { - None => return Ok(None), - Some(p) => p, - }; - - let invalid_change = peer.view.set_id > update.set_id - || peer.view.round > update.round && peer.view.set_id == update.set_id - || peer.view.last_commit.as_ref() > Some(&update.commit_finalized_height); - - if invalid_change { - return Err(Misbehavior::InvalidViewChange); - } - - peer.view = View { - round: update.round, - set_id: update.set_id, - last_commit: Some(update.commit_finalized_height), - }; - - trace!(target: "afg", "Peer {} updated view. Now at {:?}, {:?}", - who, peer.view.round, peer.view.set_id); - - Ok(Some(&peer.view)) - } - - fn update_commit_height(&mut self, who: &PeerId, new_height: N) -> Result<(), Misbehavior> { - let peer = match self.inner.get_mut(who) { - None => return Ok(()), - Some(p) => p, - }; - - // this doesn't allow a peer to send us unlimited commits with the - // same height, because there is still a misbehavior condition based on - // sending commits that are <= the best we are aware of. - if peer.view.last_commit.as_ref() > Some(&new_height) { - return Err(Misbehavior::InvalidViewChange); - } - - peer.view.last_commit = Some(new_height); - - Ok(()) - } - - fn peer<'a>(&'a self, who: &PeerId) -> Option<&'a PeerInfo> { - self.inner.get(who) - } -} - -#[derive(Debug, PartialEq)] -pub(super) enum Action { - // repropagate under given topic, to the given peers, applying cost/benefit to originator. - Keep(H, i32), - // discard and process. - ProcessAndDiscard(H, i32), - // discard, applying cost/benefit to originator. - Discard(i32), -} - -/// State of catch up request handling. -#[derive(Debug)] -enum PendingCatchUp { - /// No pending catch up requests. - None, - /// Pending catch up request which has not been answered yet. - Requesting { - who: PeerId, - request: CatchUpRequestMessage, - instant: Instant, - }, - /// Pending catch up request that was answered and is being processed. - Processing { - instant: Instant, - }, -} - -struct Inner { - local_view: Option>>, - peers: Peers>, - live_topics: KeepTopics, - authorities: Vec, - config: crate::Config, - next_rebroadcast: Instant, - pending_catch_up: PendingCatchUp, - catch_up_enabled: bool, -} - -type MaybeMessage = Option<(Vec, NeighborPacket>)>; - -impl Inner { - fn new(config: crate::Config, catch_up_enabled: bool) -> Self { - Inner { - local_view: None, - peers: Peers::default(), - live_topics: KeepTopics::new(), - next_rebroadcast: Instant::now() + REBROADCAST_AFTER, - authorities: Vec::new(), - pending_catch_up: PendingCatchUp::None, - catch_up_enabled, - config, - } - } - - /// Note a round in the current set has started. - fn note_round(&mut self, round: Round) -> MaybeMessage { - { - let local_view = match self.local_view { - None => return None, - Some(ref mut v) => if v.round == round { - return None - } else { - v - }, - }; - - let set_id = local_view.set_id; - - debug!(target: "afg", "Voter {} noting beginning of round {:?} to network.", - self.config.name(), (round,set_id)); - - local_view.round = round; - - self.live_topics.push(round, set_id); - } - self.multicast_neighbor_packet() - } - - /// Note that a voter set with given ID has started. Does nothing if the last - /// call to the function was with the same `set_id`. - fn note_set(&mut self, set_id: SetId, authorities: Vec) -> MaybeMessage { - { - let local_view = match self.local_view { - ref mut x @ None => x.get_or_insert(View { - round: Round(1), - set_id, - last_commit: None, - }), - Some(ref mut v) => if v.set_id == set_id { - return None - } else { - v - }, - }; - - local_view.update_set(set_id); - self.live_topics.push(Round(1), set_id); - self.authorities = authorities; - } - self.multicast_neighbor_packet() - } - - /// Note that we've imported a commit finalizing a given block. - fn note_commit_finalized(&mut self, finalized: NumberFor) -> MaybeMessage { - { - match self.local_view { - None => return None, - Some(ref mut v) => if v.last_commit.as_ref() < Some(&finalized) { - v.last_commit = Some(finalized); - } else { - return None - }, - }; - } - - self.multicast_neighbor_packet() - } - - fn consider_vote(&self, round: Round, set_id: SetId) -> Consider { - self.local_view.as_ref().map(|v| v.consider_vote(round, set_id)) - .unwrap_or(Consider::RejectOutOfScope) - } - - fn consider_global(&self, set_id: SetId, number: NumberFor) -> Consider { - self.local_view.as_ref().map(|v| v.consider_global(set_id, number)) - .unwrap_or(Consider::RejectOutOfScope) - } - - fn cost_past_rejection(&self, _who: &PeerId, _round: Round, _set_id: SetId) -> i32 { - // hardcoded for now. - cost::PAST_REJECTION - } - - fn validate_round_message(&self, who: &PeerId, full: &VoteMessage) - -> Action - { - match self.consider_vote(full.round, full.set_id) { - Consider::RejectFuture => return Action::Discard(Misbehavior::FutureMessage.cost()), - Consider::RejectOutOfScope => return Action::Discard(Misbehavior::OutOfScopeMessage.cost()), - Consider::RejectPast => - return Action::Discard(self.cost_past_rejection(who, full.round, full.set_id)), - Consider::Accept => {}, - } - - // ensure authority is part of the set. - if !self.authorities.contains(&full.message.id) { - telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); - return Action::Discard(cost::UNKNOWN_VOTER); - } - - if let Err(()) = super::check_message_sig::( - &full.message.message, - &full.message.id, - &full.message.signature, - full.round.0, - full.set_id.0, - ) { - debug!(target: "afg", "Bad message signature {}", full.message.id); - telemetry!(CONSENSUS_DEBUG; "afg.bad_msg_signature"; "signature" => ?full.message.id); - return Action::Discard(cost::BAD_SIGNATURE); - } - - let topic = super::round_topic::(full.round.0, full.set_id.0); - Action::Keep(topic, benefit::ROUND_MESSAGE) - } - - fn validate_commit_message(&mut self, who: &PeerId, full: &FullCommitMessage) - -> Action - { - - if let Err(misbehavior) = self.peers.update_commit_height(who, full.message.target_number) { - return Action::Discard(misbehavior.cost()); - } - - match self.consider_global(full.set_id, full.message.target_number) { - Consider::RejectFuture => return Action::Discard(Misbehavior::FutureMessage.cost()), - Consider::RejectPast => - return Action::Discard(self.cost_past_rejection(who, full.round, full.set_id)), - Consider::RejectOutOfScope => return Action::Discard(Misbehavior::OutOfScopeMessage.cost()), - Consider::Accept => {}, - - } - - 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 Action::Discard(cost::MALFORMED_COMMIT); - } - - // always discard commits initially and rebroadcast after doing full - // checking. - let topic = super::global_topic::(full.set_id.0); - Action::ProcessAndDiscard(topic, benefit::BASIC_VALIDATED_COMMIT) - } - - fn validate_catch_up_message(&mut self, who: &PeerId, full: &FullCatchUpMessage) - -> Action - { - match &self.pending_catch_up { - PendingCatchUp::Requesting { who: peer, request, instant } => { - if peer != who { - return Action::Discard(Misbehavior::OutOfScopeMessage.cost()); - } - - if request.set_id != full.set_id { - return Action::Discard(cost::MALFORMED_CATCH_UP); - } - - if request.round.0 > full.message.round_number { - return Action::Discard(cost::MALFORMED_CATCH_UP); - } - - if full.message.prevotes.is_empty() || full.message.precommits.is_empty() { - return Action::Discard(cost::MALFORMED_CATCH_UP); - } - - // move request to pending processing state, we won't push out - // any catch up requests until we import this one (either with a - // success or failure). - self.pending_catch_up = PendingCatchUp::Processing { - instant: instant.clone(), - }; - - // always discard catch up messages, they're point-to-point - let topic = super::global_topic::(full.set_id.0); - Action::ProcessAndDiscard(topic, benefit::BASIC_VALIDATED_CATCH_UP) - }, - _ => Action::Discard(Misbehavior::OutOfScopeMessage.cost()), - } - } - - fn note_catch_up_message_processed(&mut self) { - match &self.pending_catch_up { - PendingCatchUp::Processing { .. } => { - self.pending_catch_up = PendingCatchUp::None; - }, - state => trace!(target: "afg", - "Noted processed catch up message when state was: {:?}", - state, - ), - } - } - - fn handle_catch_up_request( - &mut self, - who: &PeerId, - request: CatchUpRequestMessage, - set_state: &environment::SharedVoterSetState, - ) -> (Option>, Action) { - let local_view = match self.local_view { - None => return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())), - Some(ref view) => view, - }; - - if request.set_id != local_view.set_id { - // NOTE: When we're close to a set change there is potentially a - // race where the peer sent us the request before it observed that - // we had transitioned to a new set. In this case we charge a lower - // cost. - if request.set_id.0.saturating_add(1) == local_view.set_id.0 && - local_view.round.0.saturating_sub(CATCH_UP_THRESHOLD) == 0 - { - return (None, Action::Discard(cost::HONEST_OUT_OF_SCOPE_CATCH_UP)); - } - - return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())); - } - - match self.peers.peer(who) { - None => - return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())), - Some(peer) if peer.view.round >= request.round => - return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())), - _ => {}, - } - - let last_completed_round = set_state.read().last_completed_round(); - if last_completed_round.number < request.round.0 { - return (None, Action::Discard(Misbehavior::OutOfScopeMessage.cost())); - } - - trace!(target: "afg", "Replying to catch-up request for round {} from {} with round {}", - request.round.0, - who, - last_completed_round.number, - ); - - let mut prevotes = Vec::new(); - let mut precommits = Vec::new(); - - // NOTE: the set of votes stored in `LastCompletedRound` is a minimal - // set of votes, i.e. at most one equivocation is stored per voter. The - // code below assumes this invariant is maintained when creating the - // catch up reply since peers won't accept catch-up messages that have - // too many equivocations (we exceed the fault-tolerance bound). - for vote in last_completed_round.votes { - match vote.message { - grandpa::Message::Prevote(prevote) => { - prevotes.push(grandpa::SignedPrevote { - prevote, - signature: vote.signature, - id: vote.id, - }); - }, - grandpa::Message::Precommit(precommit) => { - precommits.push(grandpa::SignedPrecommit { - precommit, - signature: vote.signature, - id: vote.id, - }); - }, - _ => {}, - } - } - - let (base_hash, base_number) = last_completed_round.base; - - let catch_up = CatchUp:: { - round_number: last_completed_round.number, - prevotes, - precommits, - base_hash, - base_number, - }; - - let full_catch_up = GossipMessage::CatchUp::(FullCatchUpMessage { - set_id: request.set_id, - message: catch_up, - }); - - (Some(full_catch_up), Action::Discard(cost::CATCH_UP_REPLY)) - } - - fn try_catch_up(&mut self, who: &PeerId) -> (Option>, Option) { - if !self.catch_up_enabled { - return (None, None); - } - - let mut catch_up = None; - let mut report = None; - - // if the peer is on the same set and ahead of us by a margin bigger - // than `CATCH_UP_THRESHOLD` then we should ask it for a catch up - // message. we only send catch-up requests to authorities, observers - // won't be able to reply since they don't follow the full GRANDPA - // protocol and therefore might not have the vote data available. - if let (Some(peer), Some(local_view)) = (self.peers.peer(who), &self.local_view) { - if peer.roles.is_authority() && - peer.view.set_id == local_view.set_id && - peer.view.round.0.saturating_sub(CATCH_UP_THRESHOLD) > local_view.round.0 - { - // send catch up request if allowed - let round = peer.view.round.0 - 1; // peer.view.round is > 0 - let request = CatchUpRequestMessage { - set_id: peer.view.set_id, - round: Round(round), - }; - - let (catch_up_allowed, catch_up_report) = self.note_catch_up_request(who, &request); - - if catch_up_allowed { - trace!(target: "afg", "Sending catch-up request for round {} to {}", - round, - who, - ); - - catch_up = Some(GossipMessage::::CatchUpRequest(request)); - } - - report = catch_up_report; - } - } - - (catch_up, report) - } - - fn import_neighbor_message(&mut self, who: &PeerId, update: NeighborPacket>) - -> (Vec, Action, Option>, Option) - { - let update_res = self.peers.update_peer_state(who, update); - - let (cost_benefit, topics) = match update_res { - Ok(view) => - (benefit::NEIGHBOR_MESSAGE, view.map(|view| neighbor_topics::(view))), - Err(misbehavior) => - (misbehavior.cost(), None), - }; - - let (catch_up, report) = match update_res { - Ok(_) => self.try_catch_up(who), - _ => (None, None), - }; - - let neighbor_topics = topics.unwrap_or_default(); - - // always discard neighbor messages, it's only valid for one hop. - let action = Action::Discard(cost_benefit); - - (neighbor_topics, action, catch_up, report) - } - - fn multicast_neighbor_packet(&self) -> MaybeMessage { - self.local_view.as_ref().map(|local_view| { - let packet = NeighborPacket { - round: local_view.round, - set_id: local_view.set_id, - commit_finalized_height: local_view.last_commit.unwrap_or(Zero::zero()), - }; - - let peers = self.peers.inner.keys().cloned().collect(); - (peers, packet) - }) - } - - fn note_catch_up_request( - &mut self, - who: &PeerId, - catch_up_request: &CatchUpRequestMessage, - ) -> (bool, Option) { - let report = match &self.pending_catch_up { - PendingCatchUp::Requesting { who: peer, instant, .. } => - if instant.elapsed() <= CATCH_UP_REQUEST_TIMEOUT { - return (false, None); - } else { - // report peer for timeout - Some((peer.clone(), cost::CATCH_UP_REQUEST_TIMEOUT)) - }, - PendingCatchUp::Processing { instant, .. } => - if instant.elapsed() < CATCH_UP_PROCESS_TIMEOUT { - return (false, None); - } else { - None - }, - _ => None, - }; - - self.pending_catch_up = PendingCatchUp::Requesting { - who: who.clone(), - request: catch_up_request.clone(), - instant: Instant::now(), - }; - - (true, report) - } -} - -/// A validator for GRANDPA gossip messages. -pub(super) struct GossipValidator { - inner: parking_lot::RwLock>, - set_state: environment::SharedVoterSetState, - report_sender: mpsc::UnboundedSender, -} - -impl GossipValidator { - /// Create a new gossip-validator. The current set is initialized to 0. If - /// `catch_up_enabled` is set to false then the validator will not issue any - /// catch up requests (useful e.g. when running just the GRANDPA observer). - pub(super) fn new( - config: crate::Config, - set_state: environment::SharedVoterSetState, - catch_up_enabled: bool, - ) -> (GossipValidator, ReportStream) { - let (tx, rx) = mpsc::unbounded(); - let val = GossipValidator { - inner: parking_lot::RwLock::new(Inner::new(config, catch_up_enabled)), - set_state, - report_sender: tx, - }; - - (val, ReportStream { reports: rx }) - } - - /// Note a round in the current set has started. - pub(super) fn note_round(&self, round: Round, send_neighbor: F) - where F: FnOnce(Vec, NeighborPacket>) - { - let maybe_msg = self.inner.write().note_round(round); - if let Some((to, msg)) = maybe_msg { - send_neighbor(to, msg); - } - } - - /// Note that a voter set with given ID has started. Updates the current set to given - /// value and initializes the round to 0. - pub(super) fn note_set(&self, set_id: SetId, authorities: Vec, send_neighbor: F) - where F: FnOnce(Vec, NeighborPacket>) - { - let maybe_msg = self.inner.write().note_set(set_id, authorities); - if let Some((to, msg)) = maybe_msg { - send_neighbor(to, msg); - } - } - - /// Note that we've imported a commit finalizing a given block. - pub(super) fn note_commit_finalized(&self, finalized: NumberFor, send_neighbor: F) - where F: FnOnce(Vec, NeighborPacket>) - { - let maybe_msg = self.inner.write().note_commit_finalized(finalized); - if let Some((to, msg)) = maybe_msg { - send_neighbor(to, msg); - } - } - - /// Note that we've processed a catch up message. - pub(super) fn note_catch_up_message_processed(&self) { - self.inner.write().note_catch_up_message_processed(); - } - - fn report(&self, who: PeerId, cost_benefit: i32) { - let _ = self.report_sender.unbounded_send(PeerReport { who, cost_benefit }); - } - - pub(super) fn do_validate(&self, who: &PeerId, mut data: &[u8]) - -> (Action, Vec, Option>) - { - let mut broadcast_topics = Vec::new(); - let mut peer_reply = None; - - let action = { - match GossipMessage::::decode(&mut data) { - Ok(GossipMessage::Vote(ref message)) - => self.inner.write().validate_round_message(who, message), - Ok(GossipMessage::Commit(ref message)) => self.inner.write().validate_commit_message(who, message), - Ok(GossipMessage::Neighbor(update)) => { - let (topics, action, catch_up, report) = self.inner.write().import_neighbor_message( - who, - update.into_neighbor_packet(), - ); - - if let Some((peer, cost_benefit)) = report { - self.report(peer, cost_benefit); - } - - broadcast_topics = topics; - peer_reply = catch_up; - action - } - Ok(GossipMessage::CatchUp(ref message)) - => self.inner.write().validate_catch_up_message(who, message), - Ok(GossipMessage::CatchUpRequest(request)) => { - let (reply, action) = self.inner.write().handle_catch_up_request( - who, - request, - &self.set_state, - ); - - peer_reply = reply; - action - } - Err(e) => { - debug!(target: "afg", "Error decoding message: {}", e.what()); - telemetry!(CONSENSUS_DEBUG; "afg.err_decoding_msg"; "" => ""); - - let len = std::cmp::min(i32::max_value() as usize, data.len()) as i32; - Action::Discard(Misbehavior::UndecodablePacket(len).cost()) - } - } - }; - - (action, broadcast_topics, peer_reply) - } -} - -impl network_gossip::Validator for GossipValidator { - fn new_peer(&self, context: &mut dyn ValidatorContext, who: &PeerId, roles: Roles) { - let packet = { - let mut inner = self.inner.write(); - inner.peers.new_peer(who.clone(), roles); - - inner.local_view.as_ref().map(|v| { - NeighborPacket { - round: v.round, - set_id: v.set_id, - commit_finalized_height: v.last_commit.unwrap_or(Zero::zero()), - } - }) - }; - - if let Some(packet) = packet { - let packet_data = GossipMessage::::from(packet).encode(); - context.send_message(who, packet_data); - } - } - - fn peer_disconnected(&self, _context: &mut dyn ValidatorContext, who: &PeerId) { - self.inner.write().peers.peer_disconnected(who); - } - - fn validate(&self, context: &mut dyn ValidatorContext, who: &PeerId, data: &[u8]) - -> network_gossip::ValidationResult - { - let (action, broadcast_topics, peer_reply) = self.do_validate(who, data); - - // not with lock held! - if let Some(msg) = peer_reply { - context.send_message(who, msg.encode()); - } - - for topic in broadcast_topics { - context.send_topic(who, topic, false); - } - - match action { - Action::Keep(topic, cb) => { - self.report(who.clone(), cb); - context.broadcast_message(topic, data.to_vec(), false); - network_gossip::ValidationResult::ProcessAndKeep(topic) - } - Action::ProcessAndDiscard(topic, cb) => { - self.report(who.clone(), cb); - network_gossip::ValidationResult::ProcessAndDiscard(topic) - } - Action::Discard(cb) => { - self.report(who.clone(), cb); - network_gossip::ValidationResult::Discard - } - } - } - - fn message_allowed<'a>(&'a self) - -> Box bool + 'a> - { - let (inner, do_rebroadcast) = { - use parking_lot::RwLockWriteGuard; - - let mut inner = self.inner.write(); - let now = Instant::now(); - let do_rebroadcast = if now >= inner.next_rebroadcast { - inner.next_rebroadcast = now + REBROADCAST_AFTER; - true - } else { - false - }; - - // downgrade to read-lock. - (RwLockWriteGuard::downgrade(inner), do_rebroadcast) - }; - - Box::new(move |who, intent, topic, mut data| { - if let MessageIntent::PeriodicRebroadcast = intent { - return do_rebroadcast; - } - - let peer = match inner.peers.peer(who) { - None => return false, - Some(x) => x, - }; - - // if the topic is not something we're keeping at the moment, - // do not send. - let (maybe_round, set_id) = match inner.live_topics.topic_info(&topic) { - None => return false, - Some(x) => x, - }; - - // if the topic is not something the peer accepts, discard. - if let Some(round) = maybe_round { - return peer.view.consider_vote(round, set_id) == Consider::Accept - } - - // global message. - let local_view = match inner.local_view { - Some(ref v) => v, - None => return false, // cannot evaluate until we have a local view. - }; - - let our_best_commit = local_view.last_commit; - let peer_best_commit = peer.view.last_commit; - - match GossipMessage::::decode(&mut data) { - Err(_) => false, - Ok(GossipMessage::Commit(full)) => { - // we only broadcast our best commit and only if it's - // better than last received by peer. - Some(full.message.target_number) == our_best_commit - && Some(full.message.target_number) > peer_best_commit - } - Ok(GossipMessage::Neighbor(_)) => false, - Ok(GossipMessage::CatchUpRequest(_)) => false, - Ok(GossipMessage::CatchUp(_)) => false, - Ok(GossipMessage::Vote(_)) => false, // should not be the case. - } - }) - } - - fn message_expired<'a>(&'a self) -> Box bool + 'a> { - let inner = self.inner.read(); - Box::new(move |topic, mut data| { - // if the topic is not one of the ones that we are keeping at the moment, - // it is expired. - match inner.live_topics.topic_info(&topic) { - None => return true, - Some((Some(_), _)) => return false, // round messages don't require further checking. - Some((None, _)) => {}, - }; - - let local_view = match inner.local_view { - Some(ref v) => v, - None => return true, // no local view means we can't evaluate or hold any topic. - }; - - // global messages -- only keep the best commit. - let best_commit = local_view.last_commit; - - match GossipMessage::::decode(&mut data) { - Err(_) => true, - Ok(GossipMessage::Commit(full)) - => Some(full.message.target_number) != best_commit, - Ok(_) => true, - } - }) - } -} - -struct PeerReport { - who: PeerId, - cost_benefit: i32, -} - -// wrapper around a stream of reports. -#[must_use = "The report stream must be consumed"] -pub(super) struct ReportStream { - reports: mpsc::UnboundedReceiver, -} - -impl ReportStream { - /// Consume the report stream, converting it into a future that - /// handles all reports. - pub(super) fn consume(self, net: N) - -> impl Future + Send + 'static + Unpin - where - B: BlockT, - N: super::Network + Send + 'static, - { - ReportingTask { - reports: self.reports, - net, - _marker: Default::default(), - } - } -} - -/// A future for reporting peers. -#[must_use = "Futures do nothing unless polled"] -struct ReportingTask { - reports: mpsc::UnboundedReceiver, - net: N, - _marker: std::marker::PhantomData, -} - -impl> Future for ReportingTask { - type Output = (); - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> { - loop { - match Stream::poll_next(Pin::new(&mut self.reports), cx) { - Poll::Ready(None) => return Poll::Ready(()), - Poll::Ready(Some(PeerReport { who, cost_benefit })) => - self.net.report(who, cost_benefit), - Poll::Pending => return Poll::Pending, - } - } - } -} - -impl Unpin for ReportingTask { -} - -#[cfg(test)] -mod tests { - use super::*; - use super::environment::SharedVoterSetState; - use network_gossip::Validator as GossipValidatorT; - use network::test::Block; - use primitives::crypto::Public; - - // some random config (not really needed) - fn config() -> crate::Config { - crate::Config { - gossip_duration: Duration::from_millis(10), - justification_period: 256, - keystore: None, - name: None, - } - } - - // dummy voter set state - fn voter_set_state() -> SharedVoterSetState { - use crate::authorities::AuthoritySet; - use crate::environment::VoterSetState; - use primitives::H256; - - let base = (H256::zero(), 0); - let voters = AuthoritySet::genesis(Vec::new()); - let set_state = VoterSetState::live( - 0, - &voters, - base, - ); - - set_state.into() - } - - #[test] - fn view_vote_rules() { - let view = View { round: Round(100), set_id: SetId(1), last_commit: Some(1000u64) }; - - assert_eq!(view.consider_vote(Round(98), SetId(1)), Consider::RejectPast); - assert_eq!(view.consider_vote(Round(1), SetId(0)), Consider::RejectPast); - assert_eq!(view.consider_vote(Round(1000), SetId(0)), Consider::RejectPast); - - assert_eq!(view.consider_vote(Round(99), SetId(1)), Consider::Accept); - assert_eq!(view.consider_vote(Round(100), SetId(1)), Consider::Accept); - assert_eq!(view.consider_vote(Round(101), SetId(1)), Consider::Accept); - - assert_eq!(view.consider_vote(Round(102), SetId(1)), Consider::RejectFuture); - assert_eq!(view.consider_vote(Round(1), SetId(2)), Consider::RejectFuture); - assert_eq!(view.consider_vote(Round(1000), SetId(2)), Consider::RejectFuture); - } - - #[test] - fn view_global_message_rules() { - let view = View { round: Round(100), set_id: SetId(2), last_commit: Some(1000u64) }; - - assert_eq!(view.consider_global(SetId(3), 1), Consider::RejectFuture); - assert_eq!(view.consider_global(SetId(3), 1000), Consider::RejectFuture); - assert_eq!(view.consider_global(SetId(3), 10000), Consider::RejectFuture); - - assert_eq!(view.consider_global(SetId(1), 1), Consider::RejectPast); - assert_eq!(view.consider_global(SetId(1), 1000), Consider::RejectPast); - assert_eq!(view.consider_global(SetId(1), 10000), Consider::RejectPast); - - assert_eq!(view.consider_global(SetId(2), 1), Consider::RejectPast); - assert_eq!(view.consider_global(SetId(2), 1000), Consider::RejectPast); - assert_eq!(view.consider_global(SetId(2), 1001), Consider::Accept); - assert_eq!(view.consider_global(SetId(2), 10000), Consider::Accept); - } - - #[test] - fn unknown_peer_cannot_be_updated() { - let mut peers = Peers::default(); - let id = PeerId::random(); - - let update = NeighborPacket { - round: Round(5), - set_id: SetId(10), - commit_finalized_height: 50, - }; - - let res = peers.update_peer_state(&id, update.clone()); - assert!(res.unwrap().is_none()); - - // connect & disconnect. - peers.new_peer(id.clone(), Roles::AUTHORITY); - peers.peer_disconnected(&id); - - let res = peers.update_peer_state(&id, update.clone()); - assert!(res.unwrap().is_none()); - } - - #[test] - fn update_peer_state() { - let update1 = NeighborPacket { - round: Round(5), - set_id: SetId(10), - commit_finalized_height: 50u32, - }; - - let update2 = NeighborPacket { - round: Round(6), - set_id: SetId(10), - commit_finalized_height: 60, - }; - - let update3 = NeighborPacket { - round: Round(2), - set_id: SetId(11), - commit_finalized_height: 61, - }; - - let update4 = NeighborPacket { - round: Round(3), - set_id: SetId(11), - commit_finalized_height: 80, - }; - - let mut peers = Peers::default(); - let id = PeerId::random(); - - peers.new_peer(id.clone(), Roles::AUTHORITY); - - let mut check_update = move |update: NeighborPacket<_>| { - let view = peers.update_peer_state(&id, update.clone()).unwrap().unwrap(); - assert_eq!(view.round, update.round); - assert_eq!(view.set_id, update.set_id); - assert_eq!(view.last_commit, Some(update.commit_finalized_height)); - }; - - check_update(update1); - check_update(update2); - check_update(update3); - check_update(update4); - } - - #[test] - fn invalid_view_change() { - let mut peers = Peers::default(); - - let id = PeerId::random(); - peers.new_peer(id.clone(), Roles::AUTHORITY); - - peers.update_peer_state(&id, NeighborPacket { - round: Round(10), - set_id: SetId(10), - commit_finalized_height: 10, - }).unwrap().unwrap(); - - let mut check_update = move |update: NeighborPacket<_>| { - let err = peers.update_peer_state(&id, update.clone()).unwrap_err(); - assert_eq!(err, Misbehavior::InvalidViewChange); - }; - - // round moves backwards. - check_update(NeighborPacket { - round: Round(9), - set_id: SetId(10), - commit_finalized_height: 10, - }); - // commit finalized height moves backwards. - check_update(NeighborPacket { - round: Round(10), - set_id: SetId(10), - commit_finalized_height: 9, - }); - // set ID moves backwards. - check_update(NeighborPacket { - round: Round(10), - set_id: SetId(9), - commit_finalized_height: 10, - }); - } - - #[test] - fn messages_not_expired_immediately() { - let (val, _) = GossipValidator::::new( - config(), - voter_set_state(), - true, - ); - - let set_id = 1; - - val.note_set(SetId(set_id), Vec::new(), |_, _| {}); - - for round_num in 1u64..10 { - val.note_round(Round(round_num), |_, _| {}); - } - - { - let mut is_expired = val.message_expired(); - let last_kept_round = 10u64 - KEEP_RECENT_ROUNDS as u64 - 1; - - // messages from old rounds are expired. - for round_num in 1u64..last_kept_round { - let topic = crate::communication::round_topic::(round_num, 1); - assert!(is_expired(topic, &[1, 2, 3])); - } - - // messages from not-too-old rounds are not expired. - for round_num in last_kept_round..10 { - let topic = crate::communication::round_topic::(round_num, 1); - assert!(!is_expired(topic, &[1, 2, 3])); - } - } - } - - #[test] - fn message_from_unknown_authority_discarded() { - assert!(cost::UNKNOWN_VOTER != cost::BAD_SIGNATURE); - - let (val, _) = GossipValidator::::new( - config(), - voter_set_state(), - true, - ); - let set_id = 1; - let auth = AuthorityId::from_slice(&[1u8; 32]); - let peer = PeerId::random(); - - val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); - val.note_round(Round(1), |_, _| {}); - - let inner = val.inner.read(); - let unknown_voter = inner.validate_round_message(&peer, &VoteMessage { - round: Round(1), - set_id: SetId(set_id), - message: SignedMessage:: { - message: grandpa::Message::Prevote(grandpa::Prevote { - target_hash: Default::default(), - target_number: 10, - }), - signature: Default::default(), - id: AuthorityId::from_slice(&[2u8; 32]), - } - }); - - let bad_sig = inner.validate_round_message(&peer, &VoteMessage { - round: Round(1), - set_id: SetId(set_id), - message: SignedMessage:: { - message: grandpa::Message::Prevote(grandpa::Prevote { - target_hash: Default::default(), - target_number: 10, - }), - signature: Default::default(), - id: auth.clone(), - } - }); - - assert_eq!(unknown_voter, Action::Discard(cost::UNKNOWN_VOTER)); - assert_eq!(bad_sig, Action::Discard(cost::BAD_SIGNATURE)); - } - - #[test] - fn unsolicited_catch_up_messages_discarded() { - let (val, _) = GossipValidator::::new( - config(), - voter_set_state(), - true, - ); - - let set_id = 1; - let auth = AuthorityId::from_slice(&[1u8; 32]); - let peer = PeerId::random(); - - val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); - val.note_round(Round(1), |_, _| {}); - - let validate_catch_up = || { - let mut inner = val.inner.write(); - inner.validate_catch_up_message(&peer, &FullCatchUpMessage { - set_id: SetId(set_id), - message: grandpa::CatchUp { - round_number: 10, - prevotes: Default::default(), - precommits: Default::default(), - base_hash: Default::default(), - base_number: Default::default(), - } - }) - }; - - // the catch up is discarded because we have no pending request - assert_eq!(validate_catch_up(), Action::Discard(cost::OUT_OF_SCOPE_MESSAGE)); - - let noted = val.inner.write().note_catch_up_request( - &peer, - &CatchUpRequestMessage { - set_id: SetId(set_id), - round: Round(10), - } - ); - - assert!(noted.0); - - // catch up is allowed because we have requested it, but it's rejected - // because it's malformed (empty prevotes and precommits) - assert_eq!(validate_catch_up(), Action::Discard(cost::MALFORMED_CATCH_UP)); - } - - #[test] - fn unanswerable_catch_up_requests_discarded() { - // create voter set state with round 2 completed - let set_state: SharedVoterSetState = { - let mut completed_rounds = voter_set_state().read().completed_rounds(); - - completed_rounds.push(environment::CompletedRound { - number: 2, - state: grandpa::round::State::genesis(Default::default()), - base: Default::default(), - votes: Default::default(), - }); - - let mut current_rounds = environment::CurrentRounds::new(); - current_rounds.insert(3, environment::HasVoted::No); - - let set_state = environment::VoterSetState::::Live { - completed_rounds, - current_rounds, - }; - - set_state.into() - }; - - let (val, _) = GossipValidator::::new( - config(), - set_state.clone(), - true, - ); - - let set_id = 1; - let auth = AuthorityId::from_slice(&[1u8; 32]); - let peer = PeerId::random(); - - val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); - val.note_round(Round(3), |_, _| {}); - - // add the peer making the request to the validator, - // otherwise it is discarded - let mut inner = val.inner.write(); - inner.peers.new_peer(peer.clone(), Roles::AUTHORITY); - - let res = inner.handle_catch_up_request( - &peer, - CatchUpRequestMessage { - set_id: SetId(set_id), - round: Round(10), - }, - &set_state, - ); - - // we're at round 3, a catch up request for round 10 is out of scope - assert!(res.0.is_none()); - assert_eq!(res.1, Action::Discard(cost::OUT_OF_SCOPE_MESSAGE)); - - let res = inner.handle_catch_up_request( - &peer, - CatchUpRequestMessage { - set_id: SetId(set_id), - round: Round(2), - }, - &set_state, - ); - - // a catch up request for round 2 should be answered successfully - match res.0.unwrap() { - GossipMessage::CatchUp(catch_up) => { - assert_eq!(catch_up.set_id, SetId(set_id)); - assert_eq!(catch_up.message.round_number, 2); - - assert_eq!(res.1, Action::Discard(cost::CATCH_UP_REPLY)); - }, - _ => panic!("expected catch up message"), - }; - } - - #[test] - fn detects_honest_out_of_scope_catch_requests() { - let set_state = voter_set_state(); - let (val, _) = GossipValidator::::new( - config(), - set_state.clone(), - true, - ); - - // the validator starts at set id 2 - val.note_set(SetId(2), Vec::new(), |_, _| {}); - - // add the peer making the request to the validator, - // otherwise it is discarded - let peer = PeerId::random(); - val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); - - let send_request = |set_id, round| { - let mut inner = val.inner.write(); - inner.handle_catch_up_request( - &peer, - CatchUpRequestMessage { - set_id: SetId(set_id), - round: Round(round), - }, - &set_state, - ) - }; - - let assert_res = |res: (Option<_>, Action<_>), honest| { - assert!(res.0.is_none()); - assert_eq!( - res.1, - if honest { - Action::Discard(cost::HONEST_OUT_OF_SCOPE_CATCH_UP) - } else { - Action::Discard(Misbehavior::OutOfScopeMessage.cost()) - }, - ); - }; - - // the validator is at set id 2 and round 0. requests for set id 1 - // should not be answered but they should be considered an honest - // mistake - assert_res( - send_request(1, 1), - true, - ); - - assert_res( - send_request(1, 10), - true, - ); - - // requests for set id 0 should be considered out of scope - assert_res( - send_request(0, 1), - false, - ); - - assert_res( - send_request(0, 10), - false, - ); - - // after the validator progresses further than CATCH_UP_THRESHOLD in set - // id 2, any request for set id 1 should no longer be considered an - // honest mistake. - val.note_round(Round(3), |_, _| {}); - - assert_res( - send_request(1, 1), - false, - ); - - assert_res( - send_request(1, 2), - false, - ); - } - - #[test] - fn issues_catch_up_request_on_neighbor_packet_import() { - let (val, _) = GossipValidator::::new( - config(), - voter_set_state(), - true, - ); - - // the validator starts at set id 1. - val.note_set(SetId(1), Vec::new(), |_, _| {}); - - // add the peer making the request to the validator, - // otherwise it is discarded. - let peer = PeerId::random(); - val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); - - let import_neighbor_message = |set_id, round| { - let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( - &peer, - NeighborPacket { - round: Round(round), - set_id: SetId(set_id), - commit_finalized_height: 42, - }, - ); - - catch_up_request - }; - - // importing a neighbor message from a peer in the same set in a later - // round should lead to a catch up request for the previous round. - match import_neighbor_message(1, 42) { - Some(GossipMessage::CatchUpRequest(request)) => { - assert_eq!(request.set_id, SetId(1)); - assert_eq!(request.round, Round(41)); - }, - _ => panic!("expected catch up message"), - } - - // we note that we're at round 41. - val.note_round(Round(41), |_, _| {}); - - // if we import a neighbor message within CATCH_UP_THRESHOLD then we - // won't request a catch up. - match import_neighbor_message(1, 42) { - None => {}, - _ => panic!("expected no catch up message"), - } - - // or if the peer is on a lower round. - match import_neighbor_message(1, 40) { - None => {}, - _ => panic!("expected no catch up message"), - } - - // we also don't request a catch up if the peer is in a different set. - match import_neighbor_message(2, 42) { - None => {}, - _ => panic!("expected no catch up message"), - } - } - - #[test] - fn doesnt_send_catch_up_requests_when_disabled() { - // we create a gossip validator with catch up requests disabled. - let (val, _) = GossipValidator::::new( - config(), - voter_set_state(), - false, - ); - - // the validator starts at set id 1. - val.note_set(SetId(1), Vec::new(), |_, _| {}); - - // add the peer making the request to the validator, - // otherwise it is discarded. - let peer = PeerId::random(); - val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); - - // importing a neighbor message from a peer in the same set in a later - // round should lead to a catch up request but since they're disabled - // we should get `None`. - let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( - &peer, - NeighborPacket { - round: Round(42), - set_id: SetId(1), - commit_finalized_height: 50, - }, - ); - - match catch_up_request { - None => {}, - _ => panic!("expected no catch up message"), - } - } - - #[test] - fn doesnt_send_catch_up_requests_to_non_authorities() { - let (val, _) = GossipValidator::::new( - config(), - voter_set_state(), - true, - ); - - // the validator starts at set id 1. - val.note_set(SetId(1), Vec::new(), |_, _| {}); - - // add the peers making the requests to the validator, - // otherwise it is discarded. - let peer_authority = PeerId::random(); - let peer_full = PeerId::random(); - - val.inner.write().peers.new_peer(peer_authority.clone(), Roles::AUTHORITY); - val.inner.write().peers.new_peer(peer_full.clone(), Roles::FULL); - - let import_neighbor_message = |peer| { - let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( - &peer, - NeighborPacket { - round: Round(42), - set_id: SetId(1), - commit_finalized_height: 50, - }, - ); - - catch_up_request - }; - - // importing a neighbor message from a peer in the same set in a later - // round should lead to a catch up request but since the node is not an - // authority we should get `None`. - if import_neighbor_message(peer_full).is_some() { - panic!("expected no catch up message"); - } - - // importing the same neighbor message from a peer who is an authority - // should lead to a catch up request. - match import_neighbor_message(peer_authority) { - Some(GossipMessage::CatchUpRequest(request)) => { - assert_eq!(request.set_id, SetId(1)); - assert_eq!(request.round, Round(41)); - }, - _ => panic!("expected catch up message"), - } - } - - #[test] - fn doesnt_expire_next_round_messages() { - // NOTE: this is a regression test - let (val, _) = GossipValidator::::new( - config(), - voter_set_state(), - true, - ); - - // the validator starts at set id 1. - val.note_set(SetId(1), Vec::new(), |_, _| {}); - - // we are at round 10 - val.note_round(Round(9), |_, _| {}); - val.note_round(Round(10), |_, _| {}); - - let mut is_expired = val.message_expired(); - - // we accept messages from rounds 9, 10 and 11 - // therefore neither of those should be considered expired - for round in &[9, 10, 11] { - assert!( - !is_expired( - crate::communication::round_topic::(*round, 1), - &[], - ) - ) - } - } -} diff --git a/core/finality-grandpa/src/communication/mod.rs b/core/finality-grandpa/src/communication/mod.rs deleted file mode 100644 index 9ebd5a6697dee..0000000000000 --- a/core/finality-grandpa/src/communication/mod.rs +++ /dev/null @@ -1,1071 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Communication streams for the polite-grandpa networking protocol. -//! -//! GRANDPA nodes communicate over a gossip network, where messages are not sent to -//! peers until they have reached a given round. -//! -//! Rather than expressing protocol rules, -//! polite-grandpa just carries a notion of impoliteness. Nodes which pass some arbitrary -//! threshold of impoliteness are removed. Messages are either costly, or beneficial. -//! -//! For instance, it is _impolite_ to send the same message more than once. -//! In the future, there will be a fallback for allowing sending the same message -//! under certain conditions that are used to un-stick the protocol. - -use std::{pin::Pin, sync::Arc, task::{Poll, Context}}; - -use futures::{channel::{oneshot, mpsc}, compat::Compat01As03, prelude::*}; -use grandpa::Message::{Prevote, Precommit, PrimaryPropose}; -use grandpa::{voter, voter_set::VoterSet}; -use log::{debug, trace}; -use network::{consensus_gossip as network_gossip, NetworkService}; -use network_gossip::ConsensusMessage; -use codec::{Encode, Decode}; -use primitives::{H256, Pair}; -use sr_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, NumberFor}; -use substrate_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; -use tokio_executor::Executor; - -use crate::{ - CatchUp, Commit, CommunicationIn, CommunicationOutH, - CompactCommit, Error, Message, SignedMessage, -}; -use crate::environment::HasVoted; -use gossip::{ - GossipMessage, FullCatchUpMessage, FullCommitMessage, VoteMessage, GossipValidator -}; -use fg_primitives::{ - AuthorityPair, AuthorityId, AuthoritySignature, SetId as SetIdNumber, RoundNumber, -}; - -pub mod gossip; -mod periodic; - -#[cfg(test)] -mod tests; - -pub use fg_primitives::GRANDPA_ENGINE_ID; - -// cost scalars for reporting peers. -mod cost { - pub(super) const PAST_REJECTION: i32 = -50; - pub(super) const BAD_SIGNATURE: i32 = -100; - pub(super) const MALFORMED_CATCH_UP: i32 = -1000; - pub(super) const MALFORMED_COMMIT: i32 = -1000; - pub(super) const FUTURE_MESSAGE: i32 = -500; - pub(super) const UNKNOWN_VOTER: i32 = -150; - - pub(super) const INVALID_VIEW_CHANGE: i32 = -500; - pub(super) const PER_UNDECODABLE_BYTE: i32 = -5; - pub(super) const PER_SIGNATURE_CHECKED: i32 = -25; - pub(super) const PER_BLOCK_LOADED: i32 = -10; - pub(super) const INVALID_CATCH_UP: i32 = -5000; - pub(super) const INVALID_COMMIT: i32 = -5000; - pub(super) const OUT_OF_SCOPE_MESSAGE: i32 = -500; - pub(super) const CATCH_UP_REQUEST_TIMEOUT: i32 = -200; - - // cost of answering a catch up request - pub(super) const CATCH_UP_REPLY: i32 = -200; - pub(super) const HONEST_OUT_OF_SCOPE_CATCH_UP: i32 = -200; -} - -// benefit scalars for reporting peers. -mod benefit { - pub(super) const NEIGHBOR_MESSAGE: i32 = 100; - pub(super) const ROUND_MESSAGE: i32 = 100; - pub(super) const BASIC_VALIDATED_CATCH_UP: i32 = 200; - pub(super) const BASIC_VALIDATED_COMMIT: i32 = 100; - pub(super) const PER_EQUIVOCATION: i32 = 10; -} - -/// 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 + Send + 'static { - /// A stream of input messages for a topic. - type In: Stream> + Unpin; - - /// Get a stream of messages for a specific gossip topic. - fn messages_for(&self, topic: Block::Hash) -> Self::In; - - /// Register a gossip validator. - fn register_validator(&self, validator: Arc>); - - /// Gossip a message out to all connected peers. - /// - /// Force causes it to be sent to all peers, even if they've seen it already. - /// Only should be used in case of consensus stall. - fn gossip_message(&self, topic: Block::Hash, data: Vec, force: bool); - - /// Register a message with the gossip service, it isn't broadcast right - /// away to any peers, but may be sent to new peers joining or when asked to - /// broadcast the topic. Useful to register previous messages on node - /// startup. - fn register_gossip_message(&self, topic: Block::Hash, data: Vec); - - /// Send a message to a bunch of specific peers, even if they've seen it already. - fn send_message(&self, who: Vec, data: Vec); - - /// Report a peer's cost or benefit after some action. - fn report(&self, who: network::PeerId, cost_benefit: i32); - - /// Inform peers that a block with given hash should be downloaded. - fn announce(&self, block: Block::Hash, associated_data: Vec); - - /// Notifies the sync service to try and sync the given block from the given - /// peers. - /// - /// If the given vector of peers is empty then the underlying implementation - /// should make a best effort to fetch the block from any peers it is - /// connected to (NOTE: this assumption will change in the future #3629). - fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor); -} - -/// Create a unique topic for a round and set-id combo. -pub(crate) fn round_topic(round: RoundNumber, set_id: SetIdNumber) -> B::Hash { - <::Hashing as HashT>::hash(format!("{}-{}", set_id, round).as_bytes()) -} - -/// Create a unique topic for global messages on a set ID. -pub(crate) fn global_topic(set_id: SetIdNumber) -> B::Hash { - <::Hashing as HashT>::hash(format!("{}-GLOBAL", set_id).as_bytes()) -} - -impl Network for Arc> where - B: BlockT, - S: network::specialization::NetworkSpecialization, - H: network::ExHashT, -{ - type In = NetworkStream< - Pin> + Send + 'static>>, - >; - - fn messages_for(&self, topic: B::Hash) -> Self::In { - // Given that one can only communicate with the Substrate network via the `NetworkService` via message-passing, - // and given that methods on the network consensus gossip are not exposed but only reachable by passing a - // closure into `with_gossip` on the `NetworkService` this function needs to make use of the `NetworkStream` - // construction. - // - // We create a oneshot channel and pass the sender within a closure to the network. At some point in the future - // the network passes the message channel back through the oneshot channel. But the consumer of this function - // expects a stream, not a stream within a oneshot. This complexity is abstracted within `NetworkStream`, - // waiting for the oneshot to resolve and from there on acting like a normal message channel. - let (tx, rx) = oneshot::channel(); - self.with_gossip(move |gossip, _| { - let inner_rx: Pin + Send>> = - Box::pin(gossip.messages_for(GRANDPA_ENGINE_ID, topic).map(Result::Ok)); - let _ = tx.send(inner_rx); - }); - NetworkStream::PollingOneshot(rx) - } - - fn register_validator(&self, validator: Arc>) { - self.with_gossip( - move |gossip, context| gossip.register_validator(context, GRANDPA_ENGINE_ID, validator) - ) - } - - fn gossip_message(&self, topic: B::Hash, data: Vec, force: bool) { - let msg = ConsensusMessage { - engine_id: GRANDPA_ENGINE_ID, - data, - }; - - self.with_gossip( - move |gossip, ctx| gossip.multicast(ctx, topic, msg, force) - ) - } - - fn register_gossip_message(&self, topic: B::Hash, data: Vec) { - let msg = ConsensusMessage { - engine_id: GRANDPA_ENGINE_ID, - data, - }; - - self.with_gossip(move |gossip, _| gossip.register_message(topic, msg)) - } - - fn send_message(&self, who: Vec, data: Vec) { - let msg = ConsensusMessage { - engine_id: GRANDPA_ENGINE_ID, - data, - }; - - self.with_gossip(move |gossip, ctx| for who in &who { - gossip.send_message(ctx, who, msg.clone()) - }) - } - - fn report(&self, who: network::PeerId, cost_benefit: i32) { - self.report_peer(who, cost_benefit) - } - - fn announce(&self, block: B::Hash, associated_data: Vec) { - self.announce_block(block, associated_data) - } - - fn set_sync_fork_request(&self, peers: Vec, hash: B::Hash, number: NumberFor) { - NetworkService::set_sync_fork_request(self, peers, hash, number) - } -} - -/// A stream used by NetworkBridge in its implementation of Network. Given a oneshot that eventually returns a channel -/// which eventually returns messages, instead of: -/// -/// 1. polling the oneshot until it returns a message channel -/// -/// 2. polling the message channel for messages -/// -/// `NetworkStream` combines the two steps into one, requiring a consumer to only poll `NetworkStream` to retrieve -/// messages directly. -pub enum NetworkStream { - PollingOneshot(oneshot::Receiver), - PollingTopicNotifications(R), -} - -impl Stream for NetworkStream -where - R: Stream> + Unpin, -{ - type Item = Result; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - match *self { - NetworkStream::PollingOneshot(ref mut oneshot) => { - match Future::poll(Pin::new(oneshot), cx) { - Poll::Ready(Ok(mut stream)) => { - let poll_result = Stream::poll_next(Pin::new(&mut stream), cx); - *self = NetworkStream::PollingTopicNotifications(stream); - poll_result - }, - Poll::Ready(Err(_)) => Poll::Ready(Some(Err(()))), - Poll::Pending => Poll::Pending, - } - }, - NetworkStream::PollingTopicNotifications(ref mut stream) => { - Stream::poll_next(Pin::new(stream), cx) - }, - } - } -} - -impl Unpin for NetworkStream { -} - -/// Bridge between the underlying network service, gossiping consensus messages and Grandpa -pub(crate) struct NetworkBridge> { - service: N, - validator: Arc>, - neighbor_sender: periodic::NeighborPacketSender, - announce_sender: periodic::BlockAnnounceSender, -} - -impl> NetworkBridge { - /// Create a new NetworkBridge to the given NetworkService. Returns the service - /// handle and a future that must be polled to completion to finish startup. - /// On creation it will register previous rounds' votes with the gossip - /// service taken from the VoterSetState. - pub(crate) fn new( - service: N, - config: crate::Config, - set_state: crate::environment::SharedVoterSetState, - on_exit: impl futures01::Future + Clone + Unpin + Send + 'static, - catch_up_enabled: bool, - ) -> ( - Self, - impl Future + Send + 'static, - ) { - - let (validator, report_stream) = GossipValidator::new( - config, - set_state.clone(), - catch_up_enabled, - ); - - let validator = Arc::new(validator); - service.register_validator(validator.clone()); - - { - // register all previous votes with the gossip service so that they're - // available to peers potentially stuck on a previous round. - let completed = set_state.read().completed_rounds(); - let (set_id, voters) = completed.set_info(); - validator.note_set(SetId(set_id), voters.to_vec(), |_, _| {}); - for round in completed.iter() { - let topic = round_topic::(round.number, set_id); - - // we need to note the round with the gossip validator otherwise - // messages will be ignored. - validator.note_round(Round(round.number), |_, _| {}); - - for signed in round.votes.iter() { - let message = gossip::GossipMessage::Vote( - gossip::VoteMessage:: { - message: signed.clone(), - round: Round(round.number), - set_id: SetId(set_id), - } - ); - - service.register_gossip_message( - topic, - message.encode(), - ); - } - - trace!(target: "afg", - "Registered {} messages for topic {:?} (round: {}, set_id: {})", - round.votes.len(), - topic, - round.number, - set_id, - ); - } - } - - let (rebroadcast_job, neighbor_sender) = periodic::neighbor_packet_worker(service.clone()); - let (announce_job, announce_sender) = periodic::block_announce_worker(service.clone()); - let reporting_job = report_stream.consume(service.clone()); - - let bridge = NetworkBridge { service, validator, neighbor_sender, announce_sender }; - - let startup_work = future::lazy(move |_cx| { - // lazily spawn these jobs onto their own tasks. the lazy future has access - // to tokio globals, which aren't available outside. - let mut executor = tokio_executor::DefaultExecutor::current(); - executor.spawn(Box::new(future::select(rebroadcast_job, Compat01As03::new(on_exit.clone())).then(|_| future::ok(())).compat())) - .expect("failed to spawn grandpa rebroadcast job task"); - executor.spawn(Box::new(future::select(announce_job, Compat01As03::new(on_exit.clone())).then(|_| future::ok(())).compat())) - .expect("failed to spawn grandpa block announce job task"); - executor.spawn(Box::new(future::select(reporting_job, Compat01As03::new(on_exit.clone())).then(|_| future::ok(())).compat())) - .expect("failed to spawn grandpa reporting job task"); - }); - - (bridge, startup_work) - } - - /// Note the beginning of a new round to the `GossipValidator`. - pub(crate) fn note_round( - &self, - round: Round, - set_id: SetId, - voters: &VoterSet, - ) { - // is a no-op if currently in that set. - self.validator.note_set( - set_id, - voters.voters().iter().map(|(v, _)| v.clone()).collect(), - |to, neighbor| self.neighbor_sender.send(to, neighbor), - ); - - self.validator.note_round( - round, - |to, neighbor| self.neighbor_sender.send(to, neighbor), - ); - } -} - -impl, N: Network> NetworkBridge { - /// Get a stream of signature-checked round messages from the network as well as a sink for round messages to the - /// network all within the current set. - pub(crate) fn round_communication( - &self, - round: Round, - set_id: SetId, - voters: Arc>, - local_key: Option, - has_voted: HasVoted, - ) -> ( - impl Stream, Error>>, - impl Sink>, Error = Error> + Unpin, - ) { - self.note_round( - round, - set_id, - &*voters, - ); - - let locals = local_key.and_then(|pair| { - let id = pair.public(); - if voters.contains_key(&id) { - Some((pair, id)) - } else { - None - } - }); - - let topic = round_topic::(round.0, set_id.0); - let incoming = self.service.messages_for(topic) - .try_filter_map(|notification| { - let decoded = GossipMessage::::decode(&mut ¬ification.message[..]); - if let Err(ref e) = decoded { - debug!(target: "afg", "Skipping malformed message {:?}: {}", notification, e); - } - future::ok(decoded.ok()) - }) - .map_ok(move |msg| { - match msg { - GossipMessage::Vote(msg) => { - // check signature. - if !voters.contains_key(&msg.message.id) { - debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); - return None; - } - - match &msg.message.message { - PrimaryPropose(propose) => { - telemetry!(CONSENSUS_INFO; "afg.received_propose"; - "voter" => ?format!("{}", msg.message.id), - "target_number" => ?propose.target_number, - "target_hash" => ?propose.target_hash, - ); - }, - 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, - ); - }, - }; - - Some(msg.message) - } - _ => { - debug!(target: "afg", "Skipping unknown message type"); - None - } - } - }) - .try_filter_map(|x| future::ok(x)) - .map_err(|()| Error::Network(format!("Failed to receive message on unbounded stream"))); - - let (tx, out_rx) = mpsc::unbounded(); - let outgoing = OutgoingMessages:: { - round: round.0, - set_id: set_id.0, - network: self.service.clone(), - locals, - sender: tx, - announce_sender: self.announce_sender.clone(), - has_voted, - }; - - let out_rx = out_rx.map(Result::Ok).map_err(move |()| Error::Network( - format!("Failed to receive on unbounded receiver for round {}", round.0) - )); - - // Combine incoming votes from external GRANDPA nodes with outgoing - // votes from our own GRANDPA voter to have a single - // vote-import-pipeline. - let incoming = stream::select(incoming, out_rx); - - (incoming, outgoing) - } - - /// Set up the global communication streams. - pub(crate) fn global_communication( - &self, - set_id: SetId, - voters: Arc>, - is_voter: bool, - ) -> ( - impl Stream, Error>>, - impl Sink, Error = Error> + Unpin, - ) { - self.validator.note_set( - set_id, - voters.voters().iter().map(|(v, _)| v.clone()).collect(), - |to, neighbor| self.neighbor_sender.send(to, neighbor), - ); - - let service = self.service.clone(); - let topic = global_topic::(set_id.0); - let incoming = incoming_global( - service, - topic, - voters, - self.validator.clone(), - self.neighbor_sender.clone(), - ); - - let outgoing = CommitsOut::::new( - self.service.clone(), - set_id.0, - is_voter, - self.validator.clone(), - self.neighbor_sender.clone(), - ); - - let outgoing = outgoing.with(|out| { - let voter::CommunicationOut::Commit(round, commit) = out; - future::ok((round, commit)) - }); - - (incoming, outgoing) - } -} - -impl> NetworkBridge { - /// Notifies the sync service to try and sync the given block from the given - /// peers. - /// - /// If the given vector of peers is empty then the underlying implementation - /// should make a best effort to fetch the block from any peers it is - /// connected to (NOTE: this assumption will change in the future #3629). - pub(crate) fn set_sync_fork_request(&self, peers: Vec, hash: B::Hash, number: NumberFor) { - self.service.set_sync_fork_request(peers, hash, number) - } -} - -fn incoming_global>( - mut service: N, - topic: B::Hash, - voters: Arc>, - gossip_validator: Arc>, - neighbor_sender: periodic::NeighborPacketSender, -) -> impl Stream, Error>> { - let process_commit = move | - msg: FullCommitMessage, - mut notification: network_gossip::TopicNotification, - service: &mut N, - gossip_validator: &Arc>, - voters: &VoterSet, - | { - 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.clone(), - "target_hash" => ?msg.message.target_hash.clone(), - ); - - if let Err(cost) = check_compact_commit::( - &msg.message, - voters, - msg.round, - msg.set_id, - ) { - if let Some(who) = notification.sender { - service.report(who, cost); - } - - return None; - } - - let round = msg.round.0; - let commit = msg.message; - let finalized_number = commit.target_number; - let gossip_validator = gossip_validator.clone(); - let service = service.clone(); - let neighbor_sender = neighbor_sender.clone(); - let cb = move |outcome| match outcome { - voter::CommitProcessingOutcome::Good(_) => { - // if it checks out, gossip it. not accounting for - // any discrepancy between the actual ghost and the claimed - // finalized number. - gossip_validator.note_commit_finalized( - finalized_number, - |to, neighbor| neighbor_sender.send(to, neighbor), - ); - - service.gossip_message(topic, notification.message.clone(), false); - } - voter::CommitProcessingOutcome::Bad(_) => { - // report peer and do not gossip. - if let Some(who) = notification.sender.take() { - service.report(who, cost::INVALID_COMMIT); - } - } - }; - - let cb = voter::Callback::Work(Box::new(cb)); - - Some(voter::CommunicationIn::Commit(round, commit, cb)) - }; - - let process_catch_up = move | - msg: FullCatchUpMessage, - mut notification: network_gossip::TopicNotification, - service: &mut N, - gossip_validator: &Arc>, - voters: &VoterSet, - | { - let gossip_validator = gossip_validator.clone(); - let service = service.clone(); - - if let Err(cost) = check_catch_up::( - &msg.message, - voters, - msg.set_id, - ) { - if let Some(who) = notification.sender { - service.report(who, cost); - } - - return None; - } - - let cb = move |outcome| { - if let voter::CatchUpProcessingOutcome::Bad(_) = outcome { - // report peer - if let Some(who) = notification.sender.take() { - service.report(who, cost::INVALID_CATCH_UP); - } - } - - gossip_validator.note_catch_up_message_processed(); - }; - - let cb = voter::Callback::Work(Box::new(cb)); - - Some(voter::CommunicationIn::CatchUp(msg.message, cb)) - }; - - service.messages_for(topic) - .try_filter_map(|notification| { - // this could be optimized by decoding piecewise. - let decoded = GossipMessage::::decode(&mut ¬ification.message[..]); - if let Err(ref e) = decoded { - trace!(target: "afg", "Skipping malformed commit message {:?}: {}", notification, e); - } - future::ok(decoded.map(move |d| (notification, d)).ok()) - }) - .try_filter_map(move |(notification, msg)| { - future::ok(match msg { - GossipMessage::Commit(msg) => - process_commit(msg, notification, &mut service, &gossip_validator, &*voters), - GossipMessage::CatchUp(msg) => - process_catch_up(msg, notification, &mut service, &gossip_validator, &*voters), - _ => { - debug!(target: "afg", "Skipping unknown message type"); - None - } - }) - }) - .map_err(|()| Error::Network(format!("Failed to receive message on unbounded stream"))) -} - -impl> Clone for NetworkBridge { - fn clone(&self) -> Self { - NetworkBridge { - service: self.service.clone(), - validator: Arc::clone(&self.validator), - neighbor_sender: self.neighbor_sender.clone(), - announce_sender: self.announce_sender.clone(), - } - } -} - -pub(crate) fn localized_payload(round: RoundNumber, set_id: SetIdNumber, message: &E) -> Vec { - (message, round, set_id).encode() -} - -/// Type-safe wrapper around a round number. -#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)] -pub struct Round(pub RoundNumber); - -/// Type-safe wrapper around a set ID. -#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)] -pub struct SetId(pub SetIdNumber); - -// check a message. -pub(crate) fn check_message_sig( - message: &Message, - id: &AuthorityId, - signature: &AuthoritySignature, - round: RoundNumber, - set_id: SetIdNumber, -) -> Result<(), ()> { - let as_public = id.clone(); - let encoded_raw = localized_payload(round, set_id, message); - if AuthorityPair::verify(signature, &encoded_raw, &as_public) { - Ok(()) - } else { - debug!(target: "afg", "Bad signature on message from {:?}", id); - Err(()) - } -} - -/// A sink for outgoing messages to the network. Any messages that are sent will -/// be replaced, as appropriate, according to the given `HasVoted`. -/// NOTE: The votes are stored unsigned, which means that the signatures need to -/// be "stable", i.e. we should end up with the exact same signed message if we -/// use the same raw message and key to sign. This is currently true for -/// `ed25519` and `BLS` signatures (which we might use in the future), care must -/// be taken when switching to different key types. -struct OutgoingMessages> { - round: RoundNumber, - set_id: SetIdNumber, - locals: Option<(AuthorityPair, AuthorityId)>, - sender: mpsc::UnboundedSender>, - announce_sender: periodic::BlockAnnounceSender, - network: N, - has_voted: HasVoted, -} - -impl> Sink> for OutgoingMessages -{ - type Error = Error; - - fn poll_ready(self: Pin<&mut Self>, _: &mut Context) -> Poll> { - Poll::Ready(Ok(())) - } - - fn start_send(self: Pin<&mut Self>, mut msg: Message) -> Result<(), Self::Error> { - // if we've voted on this round previously under the same key, send that vote instead - match &mut msg { - grandpa::Message::PrimaryPropose(ref mut vote) => - if let Some(propose) = self.has_voted.propose() { - *vote = propose.clone(); - }, - grandpa::Message::Prevote(ref mut vote) => - if let Some(prevote) = self.has_voted.prevote() { - *vote = prevote.clone(); - }, - grandpa::Message::Precommit(ref mut vote) => - if let Some(precommit) = self.has_voted.precommit() { - *vote = precommit.clone(); - }, - } - - // when locals exist, sign messages on import - if let Some((ref pair, ref local_id)) = self.locals { - let encoded = localized_payload(self.round, self.set_id, &msg); - let signature = pair.sign(&encoded[..]); - - let target_hash = msg.target().0.clone(); - let signed = SignedMessage:: { - message: msg, - signature, - id: local_id.clone(), - }; - - let message = GossipMessage::Vote(VoteMessage:: { - message: signed.clone(), - round: Round(self.round), - set_id: SetId(self.set_id), - }); - - debug!( - target: "afg", - "Announcing block {} to peers which we voted on in round {} in set {}", - target_hash, - self.round, - self.set_id, - ); - - telemetry!( - CONSENSUS_DEBUG; "afg.announcing_blocks_to_voted_peers"; - "block" => ?target_hash, "round" => ?self.round, "set_id" => ?self.set_id, - ); - - // send the target block hash to the background block announcer - self.announce_sender.send(target_hash, Vec::new()); - - // propagate the message to peers - let topic = round_topic::(self.round, self.set_id); - self.network.gossip_message(topic, message.encode(), false); - - // forward the message to the inner sender. - let _ = self.sender.unbounded_send(signed); - } - - Ok(()) - } - - fn poll_flush(self: Pin<&mut Self>, _: &mut Context) -> Poll> { - Poll::Ready(Ok(())) - } - - fn poll_close(mut self: Pin<&mut Self>, _: &mut Context) -> Poll> { - // ignore errors since we allow this inner sender to be closed already. - self.sender.disconnect(); - Poll::Ready(Ok(())) - } -} - -impl> Unpin for OutgoingMessages { -} - -// checks a compact commit. returns the cost associated with processing it if -// the commit was bad. -fn check_compact_commit( - msg: &CompactCommit, - voters: &VoterSet, - round: Round, - set_id: SetId, -) -> Result<(), i32> { - // 4f + 1 = equivocations from f voters. - let f = voters.total_weight() - voters.threshold(); - let full_threshold = voters.total_weight() + f; - - // check total weight is not out of range. - let mut total_weight = 0; - for (_, ref id) in &msg.auth_data { - if let Some(weight) = voters.info(id).map(|info| info.weight()) { - total_weight += weight; - if total_weight > full_threshold { - return Err(cost::MALFORMED_COMMIT); - } - } else { - debug!(target: "afg", "Skipping commit containing unknown voter {}", id); - return Err(cost::MALFORMED_COMMIT); - } - } - - if total_weight < voters.threshold() { - return Err(cost::MALFORMED_COMMIT); - } - - // check signatures on all contained precommits. - for (i, (precommit, &(ref sig, ref id))) in msg.precommits.iter() - .zip(&msg.auth_data) - .enumerate() - { - use crate::communication::gossip::Misbehavior; - use grandpa::Message as GrandpaMessage; - - if let Err(()) = check_message_sig::( - &GrandpaMessage::Precommit(precommit.clone()), - id, - sig, - round.0, - set_id.0, - ) { - debug!(target: "afg", "Bad commit message signature {}", id); - telemetry!(CONSENSUS_DEBUG; "afg.bad_commit_msg_signature"; "id" => ?id); - let cost = Misbehavior::BadCommitMessage { - signatures_checked: i as i32, - blocks_loaded: 0, - equivocations_caught: 0, - }.cost(); - - return Err(cost); - } - } - - Ok(()) -} - -// checks a catch up. returns the cost associated with processing it if -// the catch up was bad. -fn check_catch_up( - msg: &CatchUp, - voters: &VoterSet, - set_id: SetId, -) -> Result<(), i32> { - // 4f + 1 = equivocations from f voters. - let f = voters.total_weight() - voters.threshold(); - let full_threshold = voters.total_weight() + f; - - // check total weight is not out of range for a set of votes. - fn check_weight<'a>( - voters: &'a VoterSet, - votes: impl Iterator, - full_threshold: u64, - ) -> Result<(), i32> { - let mut total_weight = 0; - - for id in votes { - if let Some(weight) = voters.info(&id).map(|info| info.weight()) { - total_weight += weight; - if total_weight > full_threshold { - return Err(cost::MALFORMED_CATCH_UP); - } - } else { - debug!(target: "afg", "Skipping catch up message containing unknown voter {}", id); - return Err(cost::MALFORMED_CATCH_UP); - } - } - - if total_weight < voters.threshold() { - return Err(cost::MALFORMED_CATCH_UP); - } - - Ok(()) - }; - - check_weight( - voters, - msg.prevotes.iter().map(|vote| &vote.id), - full_threshold, - )?; - - check_weight( - voters, - msg.precommits.iter().map(|vote| &vote.id), - full_threshold, - )?; - - fn check_signatures<'a, B, I>( - messages: I, - round: RoundNumber, - set_id: SetIdNumber, - mut signatures_checked: usize, - ) -> Result where - B: BlockT, - I: Iterator, &'a AuthorityId, &'a AuthoritySignature)>, - { - use crate::communication::gossip::Misbehavior; - - for (msg, id, sig) in messages { - signatures_checked += 1; - - if let Err(()) = check_message_sig::( - &msg, - id, - sig, - round, - set_id, - ) { - debug!(target: "afg", "Bad catch up message signature {}", id); - telemetry!(CONSENSUS_DEBUG; "afg.bad_catch_up_msg_signature"; "id" => ?id); - - let cost = Misbehavior::BadCatchUpMessage { - signatures_checked: signatures_checked as i32, - }.cost(); - - return Err(cost); - } - } - - Ok(signatures_checked) - } - - // check signatures on all contained prevotes. - let signatures_checked = check_signatures::( - msg.prevotes.iter().map(|vote| { - (grandpa::Message::Prevote(vote.prevote.clone()), &vote.id, &vote.signature) - }), - msg.round_number, - set_id.0, - 0, - )?; - - // check signatures on all contained precommits. - let _ = check_signatures::( - msg.precommits.iter().map(|vote| { - (grandpa::Message::Precommit(vote.precommit.clone()), &vote.id, &vote.signature) - }), - msg.round_number, - set_id.0, - signatures_checked, - )?; - - Ok(()) -} - -/// An output sink for commit messages. -struct CommitsOut> { - network: N, - set_id: SetId, - is_voter: bool, - gossip_validator: Arc>, - neighbor_sender: periodic::NeighborPacketSender, -} - -impl> CommitsOut { - /// Create a new commit output stream. - pub(crate) fn new( - network: N, - set_id: SetIdNumber, - is_voter: bool, - gossip_validator: Arc>, - neighbor_sender: periodic::NeighborPacketSender, - ) -> Self { - CommitsOut { - network, - set_id: SetId(set_id), - is_voter, - gossip_validator, - neighbor_sender, - } - } -} - -impl> Sink<(RoundNumber, Commit)> for CommitsOut { - type Error = Error; - - fn poll_ready(self: Pin<&mut Self>, _: &mut Context) -> Poll> { - Poll::Ready(Ok(())) - } - - fn start_send(self: Pin<&mut Self>, input: (RoundNumber, Commit)) -> Result<(), Self::Error> { - if !self.is_voter { - return Ok(()); - } - - let (round, commit) = input; - let round = Round(round); - - telemetry!(CONSENSUS_DEBUG; "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(); - - let compact_commit = CompactCommit:: { - target_hash: commit.target_hash, - target_number: commit.target_number, - precommits, - auth_data - }; - - let message = GossipMessage::Commit(FullCommitMessage:: { - round: round, - set_id: self.set_id, - message: compact_commit, - }); - - let topic = global_topic::(self.set_id.0); - - // the gossip validator needs to be made aware of the best commit-height we know of - // before gossiping - self.gossip_validator.note_commit_finalized( - commit.target_number, - |to, neighbor| self.neighbor_sender.send(to, neighbor), - ); - self.network.gossip_message(topic, message.encode(), false); - - Ok(()) - } - - fn poll_close(self: Pin<&mut Self>, _: &mut Context) -> Poll> { - Poll::Ready(Ok(())) - } - - fn poll_flush(self: Pin<&mut Self>, _: &mut Context) -> Poll> { - Poll::Ready(Ok(())) - } -} - -impl> Unpin for CommitsOut { -} diff --git a/core/finality-grandpa/src/communication/periodic.rs b/core/finality-grandpa/src/communication/periodic.rs deleted file mode 100644 index 90351187ee0d2..0000000000000 --- a/core/finality-grandpa/src/communication/periodic.rs +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Periodic rebroadcast of neighbor packets. - -use std::collections::VecDeque; -use std::{pin::Pin, time::Duration, task::{Context, Poll}}; - -use codec::Encode; -use futures::prelude::*; -use futures::channel::mpsc; -use log::{debug, warn}; -use futures_timer::Delay; - -use network::PeerId; -use sr_primitives::traits::{NumberFor, Block as BlockT}; -use super::{gossip::{NeighborPacket, GossipMessage}, Network}; - -// how often to rebroadcast, if no other -const REBROADCAST_AFTER: Duration = Duration::from_secs(2 * 60); - -/// The number of block hashes that we have previously voted on that we should -/// keep around for announcement. The current value should be enough for 3 -/// rounds assuming we have prevoted and precommited on different blocks. -const LATEST_VOTED_BLOCKS_TO_ANNOUNCE: usize = 6; - -/// A sender used to send neighbor packets to a background job. -#[derive(Clone)] -pub(super) struct NeighborPacketSender( - mpsc::UnboundedSender<(Vec, NeighborPacket>)> -); - -impl NeighborPacketSender { - /// Send a neighbor packet for the background worker to gossip to peers. - pub fn send( - &self, - who: Vec, - neighbor_packet: NeighborPacket>, - ) { - if let Err(err) = self.0.unbounded_send((who, neighbor_packet)) { - debug!(target: "afg", "Failed to send neighbor packet: {:?}", err); - } - } -} - -/// Does the work of sending neighbor packets, asynchronously. -/// -/// It may rebroadcast the last neighbor packet periodically when no -/// progress is made. -pub(super) fn neighbor_packet_worker(net: N) -> ( - impl Future + Unpin + Send + 'static, - NeighborPacketSender, -) where - B: BlockT, - N: Network, -{ - let mut last = None; - let (tx, mut rx) = mpsc::unbounded::<(Vec, NeighborPacket>)>(); - let mut delay = Delay::new(REBROADCAST_AFTER); - - let work = futures::future::poll_fn(move |cx| { - loop { - match Stream::poll_next(Pin::new(&mut rx), cx) { - Poll::Ready(None) => return Poll::Ready(()), - Poll::Ready(Some((to, packet))) => { - // send to peers. - net.send_message(to.clone(), GossipMessage::::from(packet.clone()).encode()); - - // rebroadcasting network. - delay.reset(REBROADCAST_AFTER); - last = Some((to, packet)); - } - Poll::Pending => break, - } - } - - // has to be done in a loop because it needs to be polled after - // re-scheduling. - loop { - match Future::poll(Pin::new(&mut delay), cx) { - Poll::Ready(Err(e)) => { - warn!(target: "afg", "Could not rebroadcast neighbor packets: {:?}", e); - delay.reset(REBROADCAST_AFTER); - } - Poll::Ready(Ok(())) => { - delay.reset(REBROADCAST_AFTER); - - if let Some((ref to, ref packet)) = last { - // send to peers. - net.send_message(to.clone(), GossipMessage::::from(packet.clone()).encode()); - } - } - Poll::Pending => return Poll::Pending, - } - } - }); - - (work, NeighborPacketSender(tx)) -} - -/// A background worker for performing block announcements. -struct BlockAnnouncer { - net: N, - block_rx: mpsc::UnboundedReceiver<(B::Hash, Vec)>, - latest_voted_blocks: VecDeque, - reannounce_after: Duration, - delay: Delay, -} - -/// A background worker for announcing block hashes to peers. The worker keeps -/// track of `LATEST_VOTED_BLOCKS_TO_ANNOUNCE` and periodically announces these -/// blocks to all peers if no new blocks to announce are noted (i.e. presumably -/// GRANDPA progress is stalled). -pub(super) fn block_announce_worker>(net: N) -> ( - impl Future + Unpin, - BlockAnnounceSender, -) { - block_announce_worker_aux(net, REBROADCAST_AFTER) -} - -#[cfg(test)] -pub(super) fn block_announce_worker_with_delay>( - net: N, - reannounce_after: Duration, -) -> ( - impl Future + Unpin, - BlockAnnounceSender, -) { - block_announce_worker_aux(net, reannounce_after) -} - -fn block_announce_worker_aux>( - net: N, - reannounce_after: Duration, -) -> ( - impl Future + Unpin, - BlockAnnounceSender, -) { - let latest_voted_blocks = VecDeque::with_capacity(LATEST_VOTED_BLOCKS_TO_ANNOUNCE); - - let (block_tx, block_rx) = mpsc::unbounded(); - - let announcer = BlockAnnouncer { - net, - block_rx, - latest_voted_blocks, - reannounce_after, - delay: Delay::new(reannounce_after), - }; - - (announcer, BlockAnnounceSender(block_tx)) -} - - -impl BlockAnnouncer { - fn note_block(&mut self, block: B::Hash) -> bool { - if !self.latest_voted_blocks.contains(&block) { - if self.latest_voted_blocks.len() >= LATEST_VOTED_BLOCKS_TO_ANNOUNCE { - self.latest_voted_blocks.pop_front(); - } - - self.latest_voted_blocks.push_back(block); - - true - } else { - false - } - } - - fn reset_delay(&mut self) { - self.delay.reset(self.reannounce_after); - } -} - -impl> Future for BlockAnnouncer { - type Output = (); - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - // note any new blocks to announce and announce them - loop { - match Stream::poll_next(Pin::new(&mut self.block_rx), cx) { - Poll::Ready(None) => return Poll::Ready(()), - Poll::Ready(Some(block)) => { - if self.note_block(block.0) { - self.net.announce(block.0, block.1); - self.reset_delay(); - } - }, - Poll::Pending => break, - } - } - - // check the reannouncement delay timer, has to be done in a loop - // because it needs to be polled after re-scheduling. - loop { - match Future::poll(Pin::new(&mut self.delay), cx) { - Poll::Ready(Err(e)) => { - warn!(target: "afg", "Error in periodic block announcer timer: {:?}", e); - self.reset_delay(); - }, - // after the delay fires announce all blocks that we have - // stored. note that this only happens if we don't receive any - // new blocks above for the duration of `reannounce_after`. - Poll::Ready(Ok(())) => { - self.reset_delay(); - - debug!( - target: "afg", - "Re-announcing latest voted blocks due to lack of progress: {:?}", - self.latest_voted_blocks, - ); - - for block in self.latest_voted_blocks.iter() { - self.net.announce(*block, Vec::new()); - } - }, - Poll::Pending => return Poll::Pending, - } - } - } -} - -impl Unpin for BlockAnnouncer { -} - -/// A sender used to send block hashes to announce to a background job. -#[derive(Clone)] -pub(super) struct BlockAnnounceSender(mpsc::UnboundedSender<(B::Hash, Vec)>); - -impl BlockAnnounceSender { - /// Send a block hash for the background worker to announce. - pub fn send(&self, block: B::Hash, associated_data: Vec) { - if let Err(err) = self.0.unbounded_send((block, associated_data)) { - debug!(target: "afg", "Failed to send block to background announcer: {:?}", err); - } - } -} diff --git a/core/finality-grandpa/src/communication/tests.rs b/core/finality-grandpa/src/communication/tests.rs deleted file mode 100644 index b55a66a32a7b8..0000000000000 --- a/core/finality-grandpa/src/communication/tests.rs +++ /dev/null @@ -1,566 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the communication portion of the GRANDPA crate. - -use futures::{prelude::*, channel::mpsc, ready}; -use network::consensus_gossip as network_gossip; -use network::test::{Block, Hash}; -use network_gossip::Validator; -use std::{collections::HashSet, pin::Pin, sync::Arc, task::Context, task::Poll, time::Duration}; -use parking_lot::Mutex; -use keyring::Ed25519Keyring; -use codec::Encode; -use sr_primitives::traits::NumberFor; - -use crate::environment::SharedVoterSetState; -use super::gossip::{self, GossipValidator}; -use super::{AuthorityId, VoterSet, Round, SetId}; - -enum Event { - MessagesFor(Hash, mpsc::UnboundedSender), - RegisterValidator(Arc>), - GossipMessage(Hash, Vec, bool), - SendMessage(Vec, Vec), - Report(network::PeerId, i32), - Announce(Hash), -} - -#[derive(Clone)] -struct TestNetwork { - sender: mpsc::UnboundedSender, -} - -impl super::Network for TestNetwork { - type In = Pin> + Send>>; - - /// Get a stream of messages for a specific gossip topic. - fn messages_for(&self, topic: Hash) -> Self::In { - let (tx, rx) = mpsc::unbounded(); - let _ = self.sender.unbounded_send(Event::MessagesFor(topic, tx)); - rx.map(Result::Ok).boxed() - } - - /// Register a gossip validator. - fn register_validator(&self, validator: Arc>) { - let _ = self.sender.unbounded_send(Event::RegisterValidator(validator)); - } - - /// Gossip a message out to all connected peers. - /// - /// Force causes it to be sent to all peers, even if they've seen it already. - /// Only should be used in case of consensus stall. - fn gossip_message(&self, topic: Hash, data: Vec, force: bool) { - let _ = self.sender.unbounded_send(Event::GossipMessage(topic, data, force)); - } - - /// Send a message to a bunch of specific peers, even if they've seen it already. - fn send_message(&self, who: Vec, data: Vec) { - let _ = self.sender.unbounded_send(Event::SendMessage(who, data)); - } - - /// Register a message with the gossip service, it isn't broadcast right - /// away to any peers, but may be sent to new peers joining or when asked to - /// broadcast the topic. Useful to register previous messages on node - /// startup. - fn register_gossip_message(&self, _topic: Hash, _data: Vec) { - // NOTE: only required to restore previous state on startup - // not required for tests currently - } - - /// Report a peer's cost or benefit after some action. - fn report(&self, who: network::PeerId, cost_benefit: i32) { - let _ = self.sender.unbounded_send(Event::Report(who, cost_benefit)); - } - - /// Inform peers that a block with given hash should be downloaded. - fn announce(&self, block: Hash, _associated_data: Vec) { - let _ = self.sender.unbounded_send(Event::Announce(block)); - } - - /// Notify the sync service to try syncing the given chain. - fn set_sync_fork_request(&self, _peers: Vec, _hash: Hash, _number: NumberFor) {} -} - -impl network_gossip::ValidatorContext for TestNetwork { - fn broadcast_topic(&mut self, _: Hash, _: bool) { } - - fn broadcast_message(&mut self, _: Hash, _: Vec, _: bool) { } - - fn send_message(&mut self, who: &network::PeerId, data: Vec) { - >::send_message(self, vec![who.clone()], data); - } - - fn send_topic(&mut self, _: &network::PeerId, _: Hash, _: bool) { } -} - -struct Tester { - net_handle: super::NetworkBridge, - gossip_validator: Arc>, - events: mpsc::UnboundedReceiver, -} - -impl Tester { - fn filter_network_events(self, mut pred: F) -> impl Future - where F: FnMut(Event) -> bool - { - let mut s = Some(self); - futures::future::poll_fn(move |cx| loop { - match Stream::poll_next(Pin::new(&mut s.as_mut().unwrap().events), cx) { - Poll::Ready(None) => panic!("concluded early"), - Poll::Ready(Some(item)) => if pred(item) { - return Poll::Ready(s.take().unwrap()) - }, - Poll::Pending => return Poll::Pending, - } - }) - } -} - -// some random config (not really needed) -fn config() -> crate::Config { - crate::Config { - gossip_duration: std::time::Duration::from_millis(10), - justification_period: 256, - keystore: None, - name: None, - } -} - -// dummy voter set state -fn voter_set_state() -> SharedVoterSetState { - use crate::authorities::AuthoritySet; - use crate::environment::VoterSetState; - use grandpa::round::State as RoundState; - use primitives::H256; - - let state = RoundState::genesis((H256::zero(), 0)); - let base = state.prevote_ghost.unwrap(); - let voters = AuthoritySet::genesis(Vec::new()); - let set_state = VoterSetState::live( - 0, - &voters, - base, - ); - - set_state.into() -} - -// needs to run in a tokio runtime. -fn make_test_network() -> ( - impl Future, - TestNetwork, -) { - let (tx, rx) = mpsc::unbounded(); - let net = TestNetwork { sender: tx }; - - #[derive(Clone)] - struct Exit; - - impl futures01::Future for Exit { - type Item = (); - type Error = (); - - fn poll(&mut self) -> futures01::Poll<(), ()> { - Ok(futures01::Async::NotReady) - } - } - - let (bridge, startup_work) = super::NetworkBridge::new( - net.clone(), - config(), - voter_set_state(), - Exit, - true, - ); - - ( - startup_work.map(move |()| Tester { - gossip_validator: bridge.validator.clone(), - net_handle: bridge, - events: rx, - }), - net, - ) -} - -fn make_ids(keys: &[Ed25519Keyring]) -> Vec<(AuthorityId, u64)> { - keys.iter() - .map(|key| key.clone().public().into()) - .map(|id| (id, 1)) - .collect() -} - -struct NoopContext; - -impl network_gossip::ValidatorContext for NoopContext { - fn broadcast_topic(&mut self, _: Hash, _: bool) { } - fn broadcast_message(&mut self, _: Hash, _: Vec, _: bool) { } - fn send_message(&mut self, _: &network::PeerId, _: Vec) { } - fn send_topic(&mut self, _: &network::PeerId, _: Hash, _: bool) { } -} - -#[test] -fn good_commit_leads_to_relay() { - let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let public = make_ids(&private[..]); - let voter_set = Arc::new(public.iter().cloned().collect::>()); - - let round = 1; - let set_id = 1; - - let commit = { - let target_hash: Hash = [1; 32].into(); - let target_number = 500; - - let precommit = grandpa::Precommit { target_hash: target_hash.clone(), target_number }; - let payload = super::localized_payload( - round, set_id, &grandpa::Message::Precommit(precommit.clone()) - ); - - let mut precommits = Vec::new(); - let mut auth_data = Vec::new(); - - for (i, key) in private.iter().enumerate() { - precommits.push(precommit.clone()); - - let signature = fg_primitives::AuthoritySignature::from(key.sign(&payload[..])); - auth_data.push((signature, public[i].0.clone())) - } - - grandpa::CompactCommit { - target_hash, - target_number, - precommits, - auth_data, - } - }; - - let encoded_commit = gossip::GossipMessage::::Commit(gossip::FullCommitMessage { - round: Round(round), - set_id: SetId(set_id), - message: commit, - }).encode(); - - let id = network::PeerId::random(); - let global_topic = super::global_topic::(set_id); - - let test = make_test_network().0 - .map(move |tester| { - // register a peer. - tester.gossip_validator.new_peer(&mut NoopContext, &id, network::config::Roles::FULL); - (tester, id) - }) - .then(move |(tester, id)| { - // start round, dispatch commit, and wait for broadcast. - let (commits_in, _) = tester.net_handle.global_communication(SetId(1), voter_set, false); - - { - let (action, ..) = tester.gossip_validator.do_validate(&id, &encoded_commit[..]); - match action { - gossip::Action::ProcessAndDiscard(t, _) => assert_eq!(t, global_topic), - _ => panic!("wrong expected outcome from initial commit validation"), - } - } - - let commit_to_send = encoded_commit.clone(); - - // asking for global communication will cause the test network - // to send us an event asking us for a stream. use it to - // send a message. - let sender_id = id.clone(); - let send_message = tester.filter_network_events(move |event| match event { - Event::MessagesFor(topic, sender) => { - if topic != global_topic { return false } - let _ = sender.unbounded_send(network_gossip::TopicNotification { - message: commit_to_send.clone(), - sender: Some(sender_id.clone()), - }); - - true - } - _ => false, - }); - - // when the commit comes in, we'll tell the callback it was good. - let handle_commit = commits_in.into_future() - .map(|(item, _)| { - match item.unwrap().unwrap() { - grandpa::voter::CommunicationIn::Commit(_, _, mut callback) => { - callback.run(grandpa::voter::CommitProcessingOutcome::good()); - }, - _ => panic!("commit expected"), - } - }); - - // once the message is sent and commit is "handled" we should have - // a repropagation event coming from the network. - future::join(send_message, handle_commit).then(move |(tester, ())| { - tester.filter_network_events(move |event| match event { - Event::GossipMessage(topic, data, false) => { - if topic == global_topic && data == encoded_commit { - true - } else { - panic!("Trying to gossip something strange") - } - } - _ => false, - }) - }) - .map(|_| ()) - }); - - futures::executor::block_on(test); -} - -#[test] -fn bad_commit_leads_to_report() { - let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let public = make_ids(&private[..]); - let voter_set = Arc::new(public.iter().cloned().collect::>()); - - let round = 1; - let set_id = 1; - - let commit = { - let target_hash: Hash = [1; 32].into(); - let target_number = 500; - - let precommit = grandpa::Precommit { target_hash: target_hash.clone(), target_number }; - let payload = super::localized_payload( - round, set_id, &grandpa::Message::Precommit(precommit.clone()) - ); - - let mut precommits = Vec::new(); - let mut auth_data = Vec::new(); - - for (i, key) in private.iter().enumerate() { - precommits.push(precommit.clone()); - - let signature = fg_primitives::AuthoritySignature::from(key.sign(&payload[..])); - auth_data.push((signature, public[i].0.clone())) - } - - grandpa::CompactCommit { - target_hash, - target_number, - precommits, - auth_data, - } - }; - - let encoded_commit = gossip::GossipMessage::::Commit(gossip::FullCommitMessage { - round: Round(round), - set_id: SetId(set_id), - message: commit, - }).encode(); - - let id = network::PeerId::random(); - let global_topic = super::global_topic::(set_id); - - let test = make_test_network().0 - .map(move |tester| { - // register a peer. - tester.gossip_validator.new_peer(&mut NoopContext, &id, network::config::Roles::FULL); - (tester, id) - }) - .then(move |(tester, id)| { - // start round, dispatch commit, and wait for broadcast. - let (commits_in, _) = tester.net_handle.global_communication(SetId(1), voter_set, false); - - { - let (action, ..) = tester.gossip_validator.do_validate(&id, &encoded_commit[..]); - match action { - gossip::Action::ProcessAndDiscard(t, _) => assert_eq!(t, global_topic), - _ => panic!("wrong expected outcome from initial commit validation"), - } - } - - let commit_to_send = encoded_commit.clone(); - - // asking for global communication will cause the test network - // to send us an event asking us for a stream. use it to - // send a message. - let sender_id = id.clone(); - let send_message = tester.filter_network_events(move |event| match event { - Event::MessagesFor(topic, sender) => { - if topic != global_topic { return false } - let _ = sender.unbounded_send(network_gossip::TopicNotification { - message: commit_to_send.clone(), - sender: Some(sender_id.clone()), - }); - - true - } - _ => false, - }); - - // when the commit comes in, we'll tell the callback it was good. - let handle_commit = commits_in.into_future() - .map(|(item, _)| { - match item.unwrap().unwrap() { - grandpa::voter::CommunicationIn::Commit(_, _, mut callback) => { - callback.run(grandpa::voter::CommitProcessingOutcome::bad()); - }, - _ => panic!("commit expected"), - } - }); - - // once the message is sent and commit is "handled" we should have - // a report event coming from the network. - future::join(send_message, handle_commit).then(move |(tester, ())| { - tester.filter_network_events(move |event| match event { - Event::Report(who, cost_benefit) => { - if who == id && cost_benefit == super::cost::INVALID_COMMIT { - true - } else { - panic!("reported unknown peer or unexpected cost"); - } - } - _ => false, - }) - }) - .map(|_| ()) - }); - - futures::executor::block_on(test); -} - -#[test] -fn peer_with_higher_view_leads_to_catch_up_request() { - let id = network::PeerId::random(); - - let (tester, mut net) = make_test_network(); - let test = tester - .map(move |tester| { - // register a peer with authority role. - tester.gossip_validator.new_peer(&mut NoopContext, &id, network::config::Roles::AUTHORITY); - (tester, id) - }) - .then(move |(tester, id)| { - // send neighbor message at round 10 and height 50 - let result = tester.gossip_validator.validate( - &mut net, - &id, - &gossip::GossipMessage::::from(gossip::NeighborPacket { - set_id: SetId(0), - round: Round(10), - commit_finalized_height: 50, - }).encode(), - ); - - // neighbor packets are always discard - match result { - network_gossip::ValidationResult::Discard => {}, - _ => panic!("wrong expected outcome from neighbor validation"), - } - - // a catch up request should be sent to the peer for round - 1 - tester.filter_network_events(move |event| match event { - Event::SendMessage(peers, message) => { - assert_eq!( - peers, - vec![id.clone()], - ); - - assert_eq!( - message, - gossip::GossipMessage::::CatchUpRequest( - gossip::CatchUpRequestMessage { - set_id: SetId(0), - round: Round(9), - } - ).encode(), - ); - - true - }, - _ => false, - }) - .map(|_| ()) - }); - - futures::executor::block_on(test); -} - -#[test] -fn periodically_reannounce_voted_blocks_on_stall() { - let (tester, net) = make_test_network(); - let (announce_worker, announce_sender) = super::periodic::block_announce_worker_with_delay( - net, - Duration::from_secs(1), - ); - - let hashes = Arc::new(Mutex::new(Vec::new())); - - fn wait_all(tester: Tester, hashes: &[Hash]) -> impl Future { - struct WaitAll { - remaining_hashes: Arc>>, - events_fut: Pin>>, - } - - impl Future for WaitAll { - type Output = Tester; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - let tester = ready!(Future::poll(Pin::new(&mut self.events_fut), cx)); - - if self.remaining_hashes.lock().is_empty() { - return Poll::Ready(tester); - } - - let remaining_hashes = self.remaining_hashes.clone(); - self.events_fut = Box::pin(tester.filter_network_events(move |event| match event { - Event::Announce(h) => - remaining_hashes.lock().remove(&h) || panic!("unexpected announce"), - _ => false, - })); - - Future::poll(self, cx) - } - } - - WaitAll { - remaining_hashes: Arc::new(Mutex::new(hashes.iter().cloned().collect())), - events_fut: Box::pin(future::ready(tester)), - } - } - - let threads_pool = futures::executor::ThreadPool::new().unwrap(); - let test = tester - .map(move |tester| { - threads_pool.spawn_ok(announce_worker); - tester - }) - .then(|tester| { - // announce 12 blocks - for _ in 0..=12 { - let hash = Hash::random(); - hashes.lock().push(hash); - announce_sender.send(hash, Vec::new()); - } - - // we should see an event for each of those announcements - wait_all(tester, &hashes.lock()) - }) - .then(|tester| { - // after a period of inactivity we should see the last - // `LATEST_VOTED_BLOCKS_TO_ANNOUNCE` being rebroadcast - wait_all(tester, &hashes.lock()[7..=12]) - }); - - futures::executor::block_on(test); -} diff --git a/core/finality-grandpa/src/lib.rs b/core/finality-grandpa/src/lib.rs deleted file mode 100644 index 8f3cc74cf513c..0000000000000 --- a/core/finality-grandpa/src/lib.rs +++ /dev/null @@ -1,904 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! 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 -//! -//! First, create a block-import wrapper with the `block_import` function. The -//! GRANDPA worker needs to be linked together with this block import object, so -//! a `LinkHalf` is returned as well. All blocks imported (from network or -//! consensus or otherwise) must pass through this wrapper, otherwise consensus -//! is likely to break in unexpected ways. -//! -//! Next, use the `LinkHalf` and a local configuration to `run_grandpa_voter`. -//! This requires a `Network` implementation. The returned future should be -//! driven to completion and will finalize blocks in the background. -//! -//! # Changing authority sets -//! -//! The rough idea behind changing authority sets in GRANDPA is that at some point, -//! we obtain agreement for some maximum block height that the current set can -//! finalize, and once a block with that height is finalized the next set will -//! pick up finalization from there. -//! -//! Technically speaking, this would be implemented as a voting rule which says, -//! "if there is a signal for a change in N blocks in block B, only vote on -//! chains with length NUM(B) + N if they contain B". This conditional-inclusion -//! 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 (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::*, compat::Compat01As03}; -use log::{debug, info}; -use futures::channel::mpsc; -use client::{ - BlockchainEvents, CallExecutor, Client, backend::Backend, error::Error as ClientError, -}; -use client::blockchain::HeaderBackend; -use codec::Encode; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ - NumberFor, Block as BlockT, DigestFor, ProvideRuntimeApi -}; -use fg_primitives::{GrandpaApi, AuthorityPair}; -use keystore::KeyStorePtr; -use inherents::InherentDataProviders; -use consensus_common::SelectChain; -use primitives::{H256, Blake2Hasher, Pair}; -use substrate_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG}; -use serde_json; - -use srml_finality_tracker; - -use grandpa::Error as GrandpaError; -use grandpa::{voter, BlockNumberOps, voter_set::VoterSet}; - -use std::{fmt, io, pin::Pin, sync::Arc, task::{Context, Poll}, time::Duration}; - -mod authorities; -mod aux_schema; -mod communication; -mod consensus_changes; -mod environment; -mod finality_proof; -mod import; -mod justification; -mod light_import; -mod observer; -mod until_imported; -mod voting_rule; - -pub use communication::Network; -pub use finality_proof::FinalityProofProvider; -pub use justification::GrandpaJustification; -pub use light_import::light_block_import; -pub use observer::run_grandpa_observer; -pub use voting_rule::{ - BeforeBestBlock, ThreeQuartersOfTheUnfinalizedChain, VotingRule, VotingRulesBuilder -}; - -use aux_schema::PersistentData; -use environment::{Environment, VoterSetState}; -use import::GrandpaBlockImport; -use until_imported::UntilGlobalMessageBlocksImported; -use communication::NetworkBridge; -use fg_primitives::{AuthoritySignature, SetId, AuthorityWeight}; - -// Re-export these two because it's just so damn convenient. -pub use fg_primitives::{AuthorityId, ScheduledChange}; - -#[cfg(test)] -mod tests; - -/// A GRANDPA message for a substrate chain. -pub type Message = grandpa::Message<::Hash, NumberFor>; -/// A signed message. -pub type SignedMessage = grandpa::SignedMessage< - ::Hash, - NumberFor, - AuthoritySignature, - AuthorityId, ->; - -/// A primary propose message for this chain's block type. -pub type PrimaryPropose = grandpa::PrimaryPropose<::Hash, NumberFor>; -/// 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. -pub type Precommit = grandpa::Precommit<::Hash, NumberFor>; -/// A catch up message for this chain's block type. -pub type CatchUp = grandpa::CatchUp< - ::Hash, - NumberFor, - AuthoritySignature, - AuthorityId, ->; -/// A commit message for this chain's block type. -pub type Commit = grandpa::Commit< - ::Hash, - NumberFor, - AuthoritySignature, - AuthorityId, ->; -/// A compact commit message for this chain's block type. -pub type CompactCommit = grandpa::CompactCommit< - ::Hash, - NumberFor, - AuthoritySignature, - AuthorityId, ->; -/// A global communication input stream for commits and catch up messages. Not -/// exposed publicly, used internally to simplify types in the communication -/// layer. -type CommunicationIn = grandpa::voter::CommunicationIn< - ::Hash, - NumberFor, - AuthoritySignature, - AuthorityId, ->; - -/// Global communication input stream for commits and catch up messages, with -/// the hash type not being derived from the block, useful for forcing the hash -/// to some type (e.g. `H256`) when the compiler can't do the inference. -type CommunicationInH = grandpa::voter::CommunicationIn< - H, - NumberFor, - AuthoritySignature, - AuthorityId, ->; - -/// Global communication sink for commits with the hash type not being derived -/// from the block, useful for forcing the hash to some type (e.g. `H256`) when -/// the compiler can't do the inference. -type CommunicationOutH = grandpa::voter::CommunicationOut< - H, - NumberFor, - AuthoritySignature, - AuthorityId, ->; - -/// 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: u32, - /// Some local identifier of the voter. - pub name: Option, - /// The keystore that manages the keys of this node. - pub keystore: Option, -} - -impl Config { - fn name(&self) -> &str { - self.name.as_ref().map(|s| s.as_str()).unwrap_or("") - } -} - -/// Errors that can occur while voting in GRANDPA. -#[derive(Debug)] -pub enum Error { - /// An error within grandpa. - Grandpa(GrandpaError), - /// A network error. - Network(String), - /// A blockchain 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(io::Error), -} - -impl From for Error { - fn from(e: GrandpaError) -> Self { - Error::Grandpa(e) - } -} - -impl From for Error { - fn from(e: ClientError) -> Self { - Error::Client(e) - } -} - -/// Something which can determine if a block is known. -pub(crate) trait BlockStatus { - /// Return `Ok(Some(number))` or `Ok(None)` depending on whether the block - /// is definitely known and has been imported. - /// If an unexpected error occurs, return that. - fn block_number(&self, hash: Block::Hash) -> Result>, Error>; -} - -impl, RA> BlockStatus for Arc> where - B: Backend, - E: CallExecutor + Send + Sync, - RA: Send + Sync, - NumberFor: BlockNumberOps, -{ - fn block_number(&self, hash: Block::Hash) -> Result>, Error> { - self.block_number_from_id(&BlockId::Hash(hash)) - .map_err(|e| Error::Blockchain(format!("{:?}", e))) - } -} - -/// Something that one can ask to do a block sync request. -pub(crate) trait BlockSyncRequester { - /// Notifies the sync service to try and sync the given block from the given - /// peers. - /// - /// If the given vector of peers is empty then the underlying implementation - /// should make a best effort to fetch the block from any peers it is - /// connected to (NOTE: this assumption will change in the future #3629). - fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor); -} - -impl BlockSyncRequester for NetworkBridge where - Block: BlockT, - N: communication::Network, -{ - fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor) { - NetworkBridge::set_sync_fork_request(self, peers, hash, number) - } -} - -/// A new authority set along with the canonical block it changed at. -#[derive(Debug)] -pub(crate) struct NewAuthoritySet { - pub(crate) canon_number: N, - pub(crate) canon_hash: H, - pub(crate) set_id: SetId, - pub(crate) authorities: Vec<(AuthorityId, AuthorityWeight)>, -} - -/// Commands issued to the voter. -#[derive(Debug)] -pub(crate) enum VoterCommand { - /// Pause the voter for given reason. - Pause(String), - /// New authorities. - ChangeAuthorities(NewAuthoritySet) -} - -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"), - } - } -} - -/// Signals either an early exit of a voter or an error. -#[derive(Debug)] -pub(crate) enum CommandOrError { - /// An error occurred. - Error(Error), - /// A command to the voter. - VoterCommand(VoterCommand), -} - -impl From for CommandOrError { - fn from(e: Error) -> Self { - CommandOrError::Error(e) - } -} - -impl From for CommandOrError { - fn from(e: ClientError) -> Self { - CommandOrError::Error(Error::Client(e)) - } -} - -impl From for CommandOrError { - fn from(e: grandpa::Error) -> Self { - CommandOrError::Error(Error::from(e)) - } -} - -impl From> for CommandOrError { - fn from(e: VoterCommand) -> Self { - CommandOrError::VoterCommand(e) - } -} - -impl ::std::error::Error for CommandOrError { } - -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), - } - } -} - -pub struct LinkHalf, RA, SC> { - client: Arc>, - select_chain: SC, - persistent_data: PersistentData, - voter_commands_rx: mpsc::UnboundedReceiver>>, -} - -/// Make block importer and link half necessary to tie the background voter -/// to it. -pub fn block_import, RA, PRA, SC>( - client: Arc>, - api: &PRA, - select_chain: SC, -) -> Result<( - GrandpaBlockImport, - LinkHalf - ), ClientError> -where - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, - PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi, - SC: SelectChain, -{ - use sr_primitives::traits::Zero; - - let chain_info = client.info(); - let genesis_hash = chain_info.chain.genesis_hash; - - let persistent_data = aux_schema::load_persistent( - &*client, - 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) - } - )?; - - let (voter_commands_tx, voter_commands_rx) = mpsc::unbounded(); - - Ok(( - GrandpaBlockImport::new( - client.clone(), - select_chain.clone(), - persistent_data.authority_set.clone(), - voter_commands_tx, - persistent_data.consensus_changes.clone(), - ), - LinkHalf { - client, - select_chain, - persistent_data, - voter_commands_rx, - }, - )) -} - -fn global_communication, B, E, N, RA>( - set_id: SetId, - voters: &Arc>, - client: &Arc>, - network: &NetworkBridge, - keystore: &Option, -) -> ( - impl Stream< - Item = Result, CommandOrError>>, - >, - impl Sink< - CommunicationOutH, - Error = CommandOrError>, - > + Unpin, -) where - B: Backend, - E: CallExecutor + Send + Sync, - N: Network, - RA: Send + Sync, - NumberFor: BlockNumberOps, -{ - let is_voter = is_voter(voters, keystore).is_some(); - - // verification stream - let (global_in, global_out) = network.global_communication( - communication::SetId(set_id), - voters.clone(), - is_voter, - ); - - // block commit and catch up messages until relevant blocks are imported. - let global_in = UntilGlobalMessageBlocksImported::new( - client.import_notification_stream(), - network.clone(), - client.clone(), - global_in, - "global", - ); - - let global_in = global_in.map_err(CommandOrError::from); - let global_out = global_out.sink_map_err(CommandOrError::from); - - (global_in, global_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 || { - #[allow(deprecated)] - { - let info = client.info().chain; - telemetry!(CONSENSUS_INFO; "afg.finalized"; - "finalized_number" => ?info.finalized_number, - "finalized_hash" => ?info.finalized_hash, - ); - Ok(info.finalized_number) - } - })) - .map_err(|err| consensus_common::Error::InherentData(err.into())) - } else { - Ok(()) - } -} - -/// Parameters used to run Grandpa. -pub struct GrandpaParams, N, RA, SC, VR, X> { - /// Configuration for the GRANDPA service. - pub config: Config, - /// A link to the block import worker. - pub link: LinkHalf, - /// The Network instance. - pub network: N, - /// The inherent data providers. - pub inherent_data_providers: InherentDataProviders, - /// Handle to a future that will resolve on exit. - pub on_exit: X, - /// If supplied, can be used to hook on telemetry connection established events. - pub telemetry_on_connect: Option>, - /// A voting rule used to potentially restrict target votes. - pub voting_rule: VR, -} - -/// Run a GRANDPA voter as a task. Provide configuration and a link to a -/// block import worker that has already been instantiated with `block_import`. -pub fn run_grandpa_voter, N, RA, SC, VR, X>( - grandpa_params: GrandpaParams, -) -> client::error::Result + Unpin + Send + 'static> where - Block::Hash: Ord, - B: Backend + 'static, - E: CallExecutor + Send + Sync + 'static, - N: Network + Send + Sync + 'static, - N::In: Send + 'static, - SC: SelectChain + 'static, - VR: VotingRule> + Clone + 'static, - NumberFor: BlockNumberOps, - DigestFor: Encode, - RA: Send + Sync + 'static, - X: futures01::Future + Clone + Unpin + Send + 'static, -{ - let GrandpaParams { - config, - link, - network, - inherent_data_providers, - on_exit, - telemetry_on_connect, - voting_rule, - } = grandpa_params; - - let LinkHalf { - client, - select_chain, - persistent_data, - voter_commands_rx, - } = link; - - let (network, network_startup) = NetworkBridge::new( - network, - config.clone(), - persistent_data.set_state.clone(), - on_exit.clone(), - true, - ); - - register_finality_tracker_inherent_data_provider(client.clone(), &inherent_data_providers)?; - - let conf = config.clone(); - let telemetry_task = if let Some(telemetry_on_connect) = telemetry_on_connect { - let authorities = persistent_data.authority_set.clone(); - let events = telemetry_on_connect - .for_each(move |_| { - let curr = authorities.current_authorities(); - let mut auths = curr.voters().into_iter().map(|(p, _)| p); - let maybe_authority_id = authority_id(&mut auths, &conf.keystore) - .unwrap_or(Default::default()); - - telemetry!(CONSENSUS_INFO; "afg.authority_set"; - "authority_id" => maybe_authority_id.to_string(), - "authority_set_id" => ?authorities.set_id(), - "authorities" => { - let authorities: Vec = curr.voters() - .iter().map(|(id, _)| id.to_string()).collect(); - serde_json::to_string(&authorities) - .expect("authorities is always at least an empty vector; elements are always of type string") - } - ); - future::ready(()) - }) - .then(|_| { future::ready(()) }); - future::Either::Left(events) - } else { - future::Either::Right(future::pending()) - }; - - let voter_work = VoterWork::new( - client, - config, - network, - select_chain, - voting_rule, - persistent_data, - voter_commands_rx, - ); - - let voter_work = voter_work - .map(|_| ()); - - let voter_work = network_startup.then(move |()| future::ready(voter_work)); - - // Make sure that `telemetry_task` doesn't accidentally finish and kill grandpa. - let telemetry_task = telemetry_task - .then(|_| future::pending::<()>()); - - Ok(future::select(future::select(voter_work, Compat01As03::new(on_exit)), telemetry_task).then(|_| future::ready(()))) -} - -/// Future that powers the voter. -#[must_use] -struct VoterWork, RA, SC, VR> { - voter: Pin>>> + Send>>, - env: Arc>, - voter_commands_rx: mpsc::UnboundedReceiver>>, -} - -impl VoterWork -where - Block: BlockT, - N: Network + Sync, - N::In: Send + 'static, - NumberFor: BlockNumberOps, - RA: 'static + Send + Sync, - E: CallExecutor + Send + Sync + 'static, - B: Backend + 'static, - SC: SelectChain + 'static, - VR: VotingRule> + Clone + 'static, -{ - fn new( - client: Arc>, - config: Config, - network: NetworkBridge, - select_chain: SC, - voting_rule: VR, - persistent_data: PersistentData, - voter_commands_rx: mpsc::UnboundedReceiver>>, - ) -> Self { - - let voters = persistent_data.authority_set.current_authorities(); - let env = Arc::new(Environment { - client, - select_chain, - voting_rule, - voters: Arc::new(voters), - config, - network, - set_id: persistent_data.authority_set.set_id(), - authority_set: persistent_data.authority_set.clone(), - consensus_changes: persistent_data.consensus_changes.clone(), - voter_set_state: persistent_data.set_state.clone(), - }); - - let mut work = VoterWork { - // `voter` is set to a temporary value and replaced below when - // calling `rebuild_voter`. - voter: Box::pin(future::pending()), - env, - voter_commands_rx, - }; - work.rebuild_voter(); - work - } - - /// Rebuilds the `self.voter` field using the current authority set - /// state. This method should be called when we know that the authority set - /// has changed (e.g. as signalled by a voter command). - fn rebuild_voter(&mut self) { - debug!(target: "afg", "{}: Starting new voter with set ID {}", self.env.config.name(), self.env.set_id); - - let authority_id = is_voter(&self.env.voters, &self.env.config.keystore) - .map(|ap| ap.public()) - .unwrap_or(Default::default()); - - telemetry!(CONSENSUS_DEBUG; "afg.starting_new_voter"; - "name" => ?self.env.config.name(), - "set_id" => ?self.env.set_id, - "authority_id" => authority_id.to_string(), - ); - - let chain_info = self.env.client.info(); - telemetry!(CONSENSUS_INFO; "afg.authority_set"; - "number" => ?chain_info.chain.finalized_number, - "hash" => ?chain_info.chain.finalized_hash, - "authority_id" => authority_id.to_string(), - "authority_set_id" => ?self.env.set_id, - "authorities" => { - let authorities: Vec = self.env.voters.voters() - .iter().map(|(id, _)| id.to_string()).collect(); - serde_json::to_string(&authorities) - .expect("authorities is always at least an empty vector; elements are always of type string") - }, - ); - - match &*self.env.voter_set_state.read() { - VoterSetState::Live { completed_rounds, .. } => { - let last_finalized = ( - chain_info.chain.finalized_hash, - chain_info.chain.finalized_number, - ); - - let global_comms = global_communication( - self.env.set_id, - &self.env.voters, - &self.env.client, - &self.env.network, - &self.env.config.keystore, - ); - - let last_completed_round = completed_rounds.last(); - - let voter = voter::Voter::new( - self.env.clone(), - (*self.env.voters).clone(), - global_comms, - last_completed_round.number, - last_completed_round.state.clone(), - last_finalized, - ); - - self.voter = Box::pin(voter); - }, - VoterSetState::Paused { .. } => - self.voter = Box::pin(future::pending()), - }; - } - - fn handle_voter_command( - &mut self, - command: VoterCommand> - ) -> Result<(), Error> { - match command { - VoterCommand::ChangeAuthorities(new) => { - let voters: Vec = new.authorities.iter().map(move |(a, _)| { - format!("{}", a) - }).collect(); - telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities"; - "number" => ?new.canon_number, - "hash" => ?new.canon_hash, - "voters" => ?voters, - "set_id" => ?new.set_id, - ); - - self.env.update_voter_set_state(|_| { - // start the new authority set using the block where the - // set changed (not where the signal happened!) as the base. - let set_state = VoterSetState::live( - new.set_id, - &*self.env.authority_set.inner().read(), - (new.canon_hash, new.canon_number), - ); - - aux_schema::write_voter_set_state(&*self.env.client, &set_state)?; - Ok(Some(set_state)) - })?; - - self.env = Arc::new(Environment { - voters: Arc::new(new.authorities.into_iter().collect()), - set_id: new.set_id, - voter_set_state: self.env.voter_set_state.clone(), - // Fields below are simply transferred and not updated. - client: self.env.client.clone(), - select_chain: self.env.select_chain.clone(), - config: self.env.config.clone(), - authority_set: self.env.authority_set.clone(), - consensus_changes: self.env.consensus_changes.clone(), - network: self.env.network.clone(), - voting_rule: self.env.voting_rule.clone(), - }); - - self.rebuild_voter(); - Ok(()) - } - VoterCommand::Pause(reason) => { - info!(target: "afg", "Pausing old validator set: {}", reason); - - // not racing because old voter is shut down. - self.env.update_voter_set_state(|voter_set_state| { - let completed_rounds = voter_set_state.completed_rounds(); - let set_state = VoterSetState::Paused { completed_rounds }; - - aux_schema::write_voter_set_state(&*self.env.client, &set_state)?; - Ok(Some(set_state)) - })?; - - self.rebuild_voter(); - Ok(()) - } - } - } -} - -impl Future for VoterWork -where - Block: BlockT, - N: Network + Sync, - N::In: Send + 'static, - NumberFor: BlockNumberOps, - RA: 'static + Send + Sync, - E: CallExecutor + Send + Sync + 'static, - B: Backend + 'static, - SC: SelectChain + 'static, - VR: VotingRule> + Clone + 'static, -{ - type Output = Result<(), Error>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - match Future::poll(Pin::new(&mut self.voter), cx) { - Poll::Pending => {} - Poll::Ready(Ok(())) => { - // voters don't conclude naturally - return Poll::Ready(Err(Error::Safety("GRANDPA voter has concluded.".into()))) - } - Poll::Ready(Err(CommandOrError::Error(e))) => { - // return inner observer error - return Poll::Ready(Err(e)) - } - Poll::Ready(Err(CommandOrError::VoterCommand(command))) => { - // some command issued internally - self.handle_voter_command(command)?; - cx.waker().wake_by_ref(); - } - } - - match Stream::poll_next(Pin::new(&mut self.voter_commands_rx), cx) { - Poll::Pending => {} - Poll::Ready(None) => { - // the `voter_commands_rx` stream should never conclude since it's never closed. - return Poll::Ready(Ok(())) - } - Poll::Ready(Some(command)) => { - // some command issued externally - self.handle_voter_command(command)?; - cx.waker().wake_by_ref(); - } - } - - Poll::Pending - } -} - -#[deprecated(since = "1.1.0", note = "Please switch to run_grandpa_voter.")] -pub fn run_grandpa, N, RA, SC, VR, X>( - grandpa_params: GrandpaParams, -) -> ::client::error::Result + Send + 'static> where - Block::Hash: Ord, - B: Backend + 'static, - E: CallExecutor + Send + Sync + 'static, - N: Network + Send + Sync + 'static, - N::In: Send + 'static, - SC: SelectChain + 'static, - NumberFor: BlockNumberOps, - DigestFor: Encode, - RA: Send + Sync + 'static, - VR: VotingRule> + Clone + 'static, - X: futures01::Future + Clone + Unpin + Send + 'static, -{ - run_grandpa_voter(grandpa_params) -} - -/// When GRANDPA is not initialized we still need to register the finality -/// tracker inherent provider which might be expected by the runtime for block -/// authoring. Additionally, we register a gossip message validator that -/// discards all GRANDPA messages (otherwise, we end up banning nodes that send -/// us a `Neighbor` message, since there is no registered gossip validator for -/// the engine id defined in the message.) -pub fn setup_disabled_grandpa, RA, N>( - client: Arc>, - inherent_data_providers: &InherentDataProviders, - network: N, -) -> Result<(), consensus_common::Error> where - B: Backend + 'static, - E: CallExecutor + Send + Sync + 'static, - RA: Send + Sync + 'static, - N: Network + Send + Sync + 'static, - N::In: Send + 'static, -{ - register_finality_tracker_inherent_data_provider( - client, - inherent_data_providers, - )?; - - network.register_validator(Arc::new(network::consensus_gossip::DiscardAll)); - - Ok(()) -} - -/// Checks if this node is a voter in the given voter set. -/// -/// Returns the key pair of the node that is being used in the current voter set or `None`. -fn is_voter( - voters: &Arc>, - keystore: &Option, -) -> Option { - match keystore { - Some(keystore) => voters.voters().iter() - .find_map(|(p, _)| keystore.read().key_pair::(&p).ok()), - None => None, - } -} - -/// Returns the authority id of this node, if available. -fn authority_id<'a, I>( - authorities: &mut I, - keystore: &Option, -) -> Option where - I: Iterator, -{ - match keystore { - Some(keystore) => { - authorities - .find_map(|p| { - keystore.read().key_pair::(&p) - .ok() - .map(|ap| ap.public()) - }) - } - None => None, - } -} diff --git a/core/finality-grandpa/src/light_import.rs b/core/finality-grandpa/src/light_import.rs deleted file mode 100644 index 30af3a06d3f76..0000000000000 --- a/core/finality-grandpa/src/light_import.rs +++ /dev/null @@ -1,773 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::collections::HashMap; -use std::sync::Arc; -use log::{info, trace, warn}; -use parking_lot::RwLock; - -use client::{ - CallExecutor, Client, - backend::{AuxStore, Backend, Finalizer}, - blockchain::HeaderBackend, - error::Error as ClientError, - well_known_cache_keys, -}; -use codec::{Encode, Decode}; -use consensus_common::{ - import_queue::Verifier, - BlockOrigin, BlockImport, FinalityProofImport, BlockImportParams, ImportResult, ImportedAux, - BlockCheckParams, Error as ConsensusError, -}; -use network::config::{BoxFinalityProofRequestBuilder, FinalityProofRequestBuilder}; -use sr_primitives::Justification; -use sr_primitives::traits::{ - NumberFor, Block as BlockT, Header as HeaderT, ProvideRuntimeApi, DigestFor, -}; -use fg_primitives::{self, GrandpaApi, AuthorityId}; -use sr_primitives::generic::BlockId; -use primitives::{H256, Blake2Hasher}; - -use crate::aux_schema::load_decode; -use crate::consensus_changes::ConsensusChanges; -use crate::environment::canonical_at_height; -use crate::finality_proof::{AuthoritySetForFinalityChecker, ProvableJustification, make_finality_proof_request}; -use crate::justification::GrandpaJustification; - -/// LightAuthoritySet is saved under this key in aux storage. -const LIGHT_AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; -/// ConsensusChanges is saver under this key in aux storage. -const LIGHT_CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; - -/// Create light block importer. -pub fn light_block_import, RA, PRA>( - client: Arc>, - backend: Arc, - authority_set_provider: Arc>, - api: Arc, -) -> Result, ClientError> - where - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, - PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi, -{ - let info = client.info(); - let import_data = load_aux_import_data(info.chain.finalized_hash, &*client, api)?; - Ok(GrandpaLightBlockImport { - client, - backend, - authority_set_provider, - data: Arc::new(RwLock::new(import_data)), - }) -} - -/// A light block-import handler for GRANDPA. -/// -/// It is responsible for: -/// - checking GRANDPA justifications; -/// - fetching finality proofs for blocks that are enacting consensus changes. -pub struct GrandpaLightBlockImport, RA> { - client: Arc>, - backend: Arc, - authority_set_provider: Arc>, - data: Arc>>, -} - -impl, RA> Clone for GrandpaLightBlockImport { - fn clone(&self) -> Self { - GrandpaLightBlockImport { - client: self.client.clone(), - backend: self.backend.clone(), - authority_set_provider: self.authority_set_provider.clone(), - data: self.data.clone(), - } - } -} - -/// Mutable data of light block importer. -struct LightImportData> { - last_finalized: Block::Hash, - authority_set: LightAuthoritySet, - consensus_changes: ConsensusChanges>, -} - -/// Latest authority set tracker. -#[derive(Debug, Encode, Decode)] -struct LightAuthoritySet { - set_id: u64, - authorities: Vec<(AuthorityId, u64)>, -} - -impl, RA> GrandpaLightBlockImport { - /// Create finality proof request builder. - pub fn create_finality_proof_request_builder(&self) -> BoxFinalityProofRequestBuilder { - Box::new(GrandpaFinalityProofRequestBuilder(self.data.clone())) as _ - } -} - -impl, RA> BlockImport - for GrandpaLightBlockImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - DigestFor: Encode, - RA: Send + Sync, -{ - type Error = ConsensusError; - - fn import_block( - &mut self, - block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - do_import_block::<_, _, _, GrandpaJustification>( - &*self.client, &mut *self.data.write(), block, new_cache - ) - } - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - self.client.check_block(block) - } -} - -impl, RA> FinalityProofImport - for GrandpaLightBlockImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - DigestFor: Encode, - RA: Send + Sync, -{ - type Error = ConsensusError; - - fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor)> { - let mut out = Vec::new(); - let chain_info = self.client.info().chain; - - let data = self.data.read(); - for (pending_number, pending_hash) in data.consensus_changes.pending_changes() { - if *pending_number > chain_info.finalized_number && *pending_number <= chain_info.best_number { - out.push((pending_hash.clone(), *pending_number)); - } - } - - out - } - - fn import_finality_proof( - &mut self, - hash: Block::Hash, - number: NumberFor, - finality_proof: Vec, - verifier: &mut dyn Verifier, - ) -> Result<(Block::Hash, NumberFor), Self::Error> { - do_import_finality_proof::<_, _, _, GrandpaJustification>( - &*self.client, - self.backend.clone(), - &*self.authority_set_provider, - &mut *self.data.write(), - hash, - number, - finality_proof, - verifier, - ) - } -} - -impl LightAuthoritySet { - /// Get a genesis set with given authorities. - pub fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self { - LightAuthoritySet { - set_id: fg_primitives::SetId::default(), - authorities: initial, - } - } - - /// Get latest set id. - pub fn set_id(&self) -> u64 { - self.set_id - } - - /// Get latest authorities set. - pub fn authorities(&self) -> Vec<(AuthorityId, u64)> { - self.authorities.clone() - } - - /// Set new authorities set. - pub fn update(&mut self, set_id: u64, authorities: Vec<(AuthorityId, u64)>) { - self.set_id = set_id; - std::mem::replace(&mut self.authorities, authorities); - } -} - -struct GrandpaFinalityProofRequestBuilder>(Arc>>); - -impl> FinalityProofRequestBuilder for GrandpaFinalityProofRequestBuilder { - fn build_request_data(&mut self, _hash: &B::Hash) -> Vec { - let data = self.0.read(); - make_finality_proof_request( - data.last_finalized, - data.authority_set.set_id(), - ) - } -} - -/// Try to import new block. -fn do_import_block, J>( - mut client: C, - data: &mut LightImportData, - mut block: BlockImportParams, - new_cache: HashMap>, -) -> Result - where - C: HeaderBackend - + AuxStore - + Finalizer - + BlockImport - + Clone, - B: Backend + 'static, - NumberFor: grandpa::BlockNumberOps, - DigestFor: Encode, - J: ProvableJustification, -{ - let hash = block.post_header().hash(); - let number = block.header.number().clone(); - - // we don't want to finalize on `inner.import_block` - let justification = block.justification.take(); - let enacts_consensus_change = !new_cache.is_empty(); - let import_result = client.import_block(block, new_cache); - - let mut imported_aux = match import_result { - Ok(ImportResult::Imported(aux)) => aux, - Ok(r) => return Ok(r), - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), - }; - - match justification { - Some(justification) => { - trace!( - target: "finality", - "Imported block {}{}. Importing justification.", - if enacts_consensus_change { " which enacts consensus changes" } else { "" }, - hash, - ); - - do_import_justification::<_, _, _, J>(client, data, hash, number, justification) - }, - None if enacts_consensus_change => { - trace!( - target: "finality", - "Imported block {} which enacts consensus changes. Requesting finality proof.", - hash, - ); - - // remember that we need finality proof for this block - imported_aux.needs_finality_proof = true; - data.consensus_changes.note_change((number, hash)); - Ok(ImportResult::Imported(imported_aux)) - }, - None => Ok(ImportResult::Imported(imported_aux)), - } -} - -/// Try to import finality proof. -fn do_import_finality_proof, J>( - client: C, - backend: Arc, - authority_set_provider: &dyn AuthoritySetForFinalityChecker, - data: &mut LightImportData, - _hash: Block::Hash, - _number: NumberFor, - finality_proof: Vec, - verifier: &mut dyn Verifier, -) -> Result<(Block::Hash, NumberFor), ConsensusError> - where - C: HeaderBackend - + AuxStore - + Finalizer - + BlockImport - + Clone, - B: Backend + 'static, - DigestFor: Encode, - NumberFor: grandpa::BlockNumberOps, - J: ProvableJustification, -{ - let authority_set_id = data.authority_set.set_id(); - let authorities = data.authority_set.authorities(); - let finality_effects = crate::finality_proof::check_finality_proof( - backend.blockchain(), - authority_set_id, - authorities, - authority_set_provider, - finality_proof, - ).map_err(|e| ConsensusError::ClientImport(e.to_string()))?; - - // try to import all new headers - let block_origin = BlockOrigin::NetworkBroadcast; - for header_to_import in finality_effects.headers_to_import { - let (block_to_import, new_authorities) = verifier.verify(block_origin, header_to_import, None, None) - .map_err(|e| ConsensusError::ClientImport(e))?; - assert!(block_to_import.justification.is_none(), "We have passed None as justification to verifier.verify"); - - let mut cache = HashMap::new(); - if let Some(authorities) = new_authorities { - cache.insert(well_known_cache_keys::AUTHORITIES, authorities.encode()); - } - do_import_block::<_, _, _, J>(client.clone(), data, block_to_import, cache)?; - } - - // try to import latest justification - let finalized_block_hash = finality_effects.block; - let finalized_block_number = backend.blockchain() - .expect_block_number_from_id(&BlockId::Hash(finality_effects.block)) - .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; - do_finalize_block( - client, - data, - finalized_block_hash, - finalized_block_number, - finality_effects.justification.encode(), - )?; - - // apply new authorities set - data.authority_set.update( - finality_effects.new_set_id, - finality_effects.new_authorities, - ); - - Ok((finalized_block_hash, finalized_block_number)) -} - -/// Try to import justification. -fn do_import_justification, J>( - client: C, - data: &mut LightImportData, - hash: Block::Hash, - number: NumberFor, - justification: Justification, -) -> Result - where - C: HeaderBackend - + AuxStore - + Finalizer - + Clone, - B: Backend + 'static, - NumberFor: grandpa::BlockNumberOps, - J: ProvableJustification, -{ - // with justification, we have two cases - // - // optimistic: the same GRANDPA authorities set has generated intermediate justification - // => justification is verified using current authorities set + we could proceed further - // - // pessimistic scenario: the GRANDPA authorities set has changed - // => we need to fetch new authorities set (i.e. finality proof) from remote node - - // first, try to behave optimistically - let authority_set_id = data.authority_set.set_id(); - let justification = J::decode_and_verify( - &justification, - authority_set_id, - &data.authority_set.authorities(), - ); - - // BadJustification error means that justification has been successfully decoded, but - // it isn't valid within current authority set - let justification = match justification { - Err(ClientError::BadJustification(_)) => { - trace!( - target: "finality", - "Justification for {} is not valid within current authorities set. Requesting finality proof.", - hash, - ); - - let mut imported_aux = ImportedAux::default(); - imported_aux.needs_finality_proof = true; - return Ok(ImportResult::Imported(imported_aux)); - }, - Err(e) => { - trace!( - target: "finality", - "Justification for {} is not valid. Bailing.", - hash, - ); - - return Err(ConsensusError::ClientImport(e.to_string()).into()); - }, - Ok(justification) => { - trace!( - target: "finality", - "Justification for {} is valid. Finalizing the block.", - hash, - ); - - justification - }, - }; - - // finalize the block - do_finalize_block(client, data, hash, number, justification.encode()) -} - -/// Finalize the block. -fn do_finalize_block>( - client: C, - data: &mut LightImportData, - hash: Block::Hash, - number: NumberFor, - justification: Justification, -) -> Result - where - C: HeaderBackend - + AuxStore - + Finalizer - + Clone, - B: Backend + 'static, - NumberFor: grandpa::BlockNumberOps, -{ - // finalize the block - client.finalize_block(BlockId::Hash(hash), Some(justification), true).map_err(|e| { - warn!(target: "finality", "Error applying finality to block {:?}: {:?}", (hash, number), e); - ConsensusError::ClientImport(e.to_string()) - })?; - - // forget obsoleted consensus changes - let consensus_finalization_res = data.consensus_changes - .finalize((number, hash), |at_height| canonical_at_height(client.clone(), (hash, number), true, at_height)); - match consensus_finalization_res { - Ok((true, _)) => require_insert_aux( - &client, - LIGHT_CONSENSUS_CHANGES_KEY, - &data.consensus_changes, - "consensus changes", - )?, - Ok(_) => (), - Err(error) => return Err(on_post_finalization_error(error, "consensus changes")), - } - - // update last finalized block reference - data.last_finalized = hash; - - // we just finalized this block, so if we were importing it, it is now the new best - Ok(ImportResult::imported(true)) -} - -/// Load light import aux data from the store. -fn load_aux_import_data, PRA>( - last_finalized: Block::Hash, - aux_store: &B, - api: Arc, -) -> Result, ClientError> - where - B: AuxStore, - PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi, -{ - use sr_primitives::traits::Zero; - let authority_set = match load_decode(aux_store, LIGHT_AUTHORITY_SET_KEY)? { - Some(authority_set) => authority_set, - 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 - let genesis_authorities = api.runtime_api().grandpa_authorities(&BlockId::number(Zero::zero()))?; - - let authority_set = LightAuthoritySet::genesis(genesis_authorities); - let encoded = authority_set.encode(); - aux_store.insert_aux(&[(LIGHT_AUTHORITY_SET_KEY, &encoded[..])], &[])?; - - authority_set - }, - }; - - let consensus_changes = match load_decode(aux_store, LIGHT_CONSENSUS_CHANGES_KEY)? { - Some(consensus_changes) => consensus_changes, - None => { - let consensus_changes = ConsensusChanges::>::empty(); - - let encoded = authority_set.encode(); - aux_store.insert_aux(&[(LIGHT_CONSENSUS_CHANGES_KEY, &encoded[..])], &[])?; - - consensus_changes - }, - }; - - Ok(LightImportData { - last_finalized, - authority_set, - consensus_changes, - }) -} - -/// Insert into aux store. If failed, return error && show inconsistency warning. -fn require_insert_aux( - store: &A, - key: &[u8], - value: &T, - value_type: &str, -) -> Result<(), ConsensusError> { - let encoded = value.encode(); - let update_res = store.insert_aux(&[(key, &encoded[..])], &[]); - if let Err(error) = update_res { - return Err(on_post_finalization_error(error, value_type)); - } - - Ok(()) -} - -/// Display inconsistency warning. -fn on_post_finalization_error(error: ClientError, value_type: &str) -> ConsensusError { - warn!(target: "finality", "Failed to write updated {} to disk. Bailing.", value_type); - warn!(target: "finality", "Node is in a potentially inconsistent state."); - ConsensusError::ClientImport(error.to_string()) -} - -#[cfg(test)] -pub mod tests { - use super::*; - use consensus_common::ForkChoiceStrategy; - use primitives::{H256, crypto::Public}; - use test_client::client::in_mem::Blockchain as InMemoryAuxStore; - use test_client::runtime::{Block, Header}; - use crate::tests::TestApi; - use crate::finality_proof::tests::TestJustification; - - pub struct NoJustificationsImport, RA>( - pub GrandpaLightBlockImport - ); - - impl, RA> Clone - for NoJustificationsImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - DigestFor: Encode, - RA: Send + Sync, - { - fn clone(&self) -> Self { - NoJustificationsImport(self.0.clone()) - } - } - - impl, RA> BlockImport - for NoJustificationsImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - DigestFor: Encode, - RA: Send + Sync, - { - type Error = ConsensusError; - - fn import_block( - &mut self, - mut block: BlockImportParams, - new_cache: HashMap>, - ) -> Result { - block.justification.take(); - self.0.import_block(block, new_cache) - } - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - self.0.check_block(block) - } - } - - impl, RA> FinalityProofImport - for NoJustificationsImport where - NumberFor: grandpa::BlockNumberOps, - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - DigestFor: Encode, - RA: Send + Sync, - { - type Error = ConsensusError; - - fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor)> { - self.0.on_start() - } - - fn import_finality_proof( - &mut self, - hash: Block::Hash, - number: NumberFor, - finality_proof: Vec, - verifier: &mut dyn Verifier, - ) -> Result<(Block::Hash, NumberFor), Self::Error> { - self.0.import_finality_proof(hash, number, finality_proof, verifier) - } - } - - /// Creates light block import that ignores justifications that came outside of finality proofs. - pub fn light_block_import_without_justifications, RA, PRA>( - client: Arc>, - backend: Arc, - authority_set_provider: Arc>, - api: Arc, - ) -> Result, ClientError> - where - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, - PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi, - { - light_block_import(client, backend, authority_set_provider, api).map(NoJustificationsImport) - } - - fn import_block( - new_cache: HashMap>, - justification: Option, - ) -> ImportResult { - let (client, _backend) = test_client::new_light(); - let mut import_data = LightImportData { - last_finalized: Default::default(), - authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 1)]), - consensus_changes: ConsensusChanges::empty(), - }; - let block = BlockImportParams { - origin: BlockOrigin::Own, - header: Header { - number: 1, - parent_hash: client.info().chain.best_hash, - state_root: Default::default(), - digest: Default::default(), - extrinsics_root: Default::default(), - }, - justification, - post_digests: Vec::new(), - body: None, - finalized: false, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; - do_import_block::<_, _, _, TestJustification>( - &client, - &mut import_data, - block, - new_cache, - ).unwrap() - } - - #[test] - fn finality_proof_not_required_when_consensus_data_does_not_changes_and_no_justification_provided() { - assert_eq!(import_block(HashMap::new(), None), ImportResult::Imported(ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: false, - is_new_best: true, - })); - } - - #[test] - fn finality_proof_not_required_when_consensus_data_does_not_changes_and_correct_justification_provided() { - let justification = TestJustification(true, Vec::new()).encode(); - assert_eq!(import_block(HashMap::new(), Some(justification)), ImportResult::Imported(ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: false, - is_new_best: true, - })); - } - - #[test] - fn finality_proof_required_when_consensus_data_changes_and_no_justification_provided() { - let mut cache = HashMap::new(); - cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode()); - assert_eq!(import_block(cache, None), ImportResult::Imported(ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: true, - is_new_best: true, - })); - } - - #[test] - fn finality_proof_required_when_consensus_data_changes_and_incorrect_justification_provided() { - let justification = TestJustification(false, Vec::new()).encode(); - let mut cache = HashMap::new(); - cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode()); - assert_eq!( - import_block(cache, Some(justification)), - ImportResult::Imported(ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: true, - is_new_best: false, - }, - )); - } - - - #[test] - fn aux_data_updated_on_start() { - let aux_store = InMemoryAuxStore::::new(); - let api = Arc::new(TestApi::new(vec![(AuthorityId::from_slice(&[1; 32]), 1)])); - - // when aux store is empty initially - assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_none()); - assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_none()); - - // it is updated on importer start - load_aux_import_data(Default::default(), &aux_store, api).unwrap(); - assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_some()); - assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_some()); - } - - #[test] - fn aux_data_loaded_on_restart() { - let aux_store = InMemoryAuxStore::::new(); - let api = Arc::new(TestApi::new(vec![(AuthorityId::from_slice(&[1; 32]), 1)])); - - // when aux store is non-empty initially - let mut consensus_changes = ConsensusChanges::::empty(); - consensus_changes.note_change((42, Default::default())); - aux_store.insert_aux( - &[ - ( - LIGHT_AUTHORITY_SET_KEY, - LightAuthoritySet::genesis( - vec![(AuthorityId::from_slice(&[42; 32]), 2)] - ).encode().as_slice(), - ), - ( - LIGHT_CONSENSUS_CHANGES_KEY, - consensus_changes.encode().as_slice(), - ), - ], - &[], - ).unwrap(); - - // importer uses it on start - let data = load_aux_import_data(Default::default(), &aux_store, api).unwrap(); - assert_eq!(data.authority_set.authorities(), vec![(AuthorityId::from_slice(&[42; 32]), 2)]); - assert_eq!(data.consensus_changes.pending_changes(), &[(42, Default::default())]); - } -} diff --git a/core/finality-grandpa/src/tests.rs b/core/finality-grandpa/src/tests.rs deleted file mode 100644 index a523c3387cc60..0000000000000 --- a/core/finality-grandpa/src/tests.rs +++ /dev/null @@ -1,1700 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests and test helpers for GRANDPA. - -use super::*; -use environment::HasVoted; -use network::test::{Block, DummySpecialization, Hash, TestNetFactory, Peer, PeersClient}; -use network::test::{PassThroughVerifier}; -use network::config::{ProtocolConfig, Roles, BoxFinalityProofRequestBuilder}; -use parking_lot::Mutex; -use futures::{compat::Compat01As03, StreamExt as _, TryStreamExt as _}; -use tokio::runtime::current_thread; -use keyring::Ed25519Keyring; -use client::{ - error::Result, - runtime_api::{Core, RuntimeVersion, ApiExt}, - LongestChain, -}; -use test_client::{self, runtime::BlockNumber}; -use consensus_common::{BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult}; -use consensus_common::import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport}; -use std::collections::{HashMap, HashSet}; -use std::result; -use std::task::{Context, Poll}; -use codec::Decode; -use sr_primitives::traits::{ApiRef, ProvideRuntimeApi, Header as HeaderT}; -use sr_primitives::generic::{BlockId, DigestItem}; -use primitives::{NativeOrEncoded, ExecutionContext, crypto::Public}; -use fg_primitives::{GRANDPA_ENGINE_ID, AuthorityId}; - -use authorities::AuthoritySet; -use finality_proof::{FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker}; -use consensus_changes::ConsensusChanges; - -type PeerData = - Mutex< - Option< - LinkHalf< - test_client::Backend, - test_client::Executor, - Block, - test_client::runtime::RuntimeApi, - LongestChain - > - > - >; -type GrandpaPeer = Peer; - -struct GrandpaTestNet { - peers: Vec, - test_config: TestApi, -} - -impl GrandpaTestNet { - fn new(test_config: TestApi, n_peers: usize) -> Self { - let mut net = GrandpaTestNet { - peers: Vec::with_capacity(n_peers), - test_config, - }; - let config = Self::default_config(); - for _ in 0..n_peers { - net.add_full_peer(&config); - } - net - } -} - -impl TestNetFactory for GrandpaTestNet { - type Specialization = DummySpecialization; - type Verifier = PassThroughVerifier; - type PeerData = PeerData; - - /// Create new test network with peers and given config. - fn from_config(_config: &ProtocolConfig) -> Self { - GrandpaTestNet { - peers: Vec::new(), - test_config: Default::default(), - } - } - - fn default_config() -> ProtocolConfig { - // the authority role ensures gossip hits all nodes here. - ProtocolConfig { - roles: Roles::AUTHORITY, - } - } - - fn make_verifier( - &self, - _client: PeersClient, - _cfg: &ProtocolConfig, - _: &PeerData, - ) -> Self::Verifier { - PassThroughVerifier(false) // use non-instant finality. - } - - fn make_block_import(&self, client: PeersClient) - -> ( - BoxBlockImport, - Option>, - Option>, - Option>, - PeerData, - ) - { - match client { - PeersClient::Full(ref client, ref backend) => { - let (import, link) = block_import( - client.clone(), - &self.test_config, - LongestChain::new(backend.clone()), - ).expect("Could not create block import for fresh peer."); - let justification_import = Box::new(import.clone()); - let block_import = Box::new(import); - (block_import, Some(justification_import), None, None, Mutex::new(Some(link))) - }, - PeersClient::Light(ref client, ref backend) => { - use crate::light_import::tests::light_block_import_without_justifications; - - let authorities_provider = Arc::new(self.test_config.clone()); - // forbid direct finalization using justification that cames with the block - // => light clients will try to fetch finality proofs - let import = light_block_import_without_justifications( - client.clone(), - backend.clone(), - authorities_provider, - Arc::new(self.test_config.clone()) - ).expect("Could not create block import for fresh peer."); - let finality_proof_req_builder = import.0.create_finality_proof_request_builder(); - let proof_import = Box::new(import.clone()); - let block_import = Box::new(import); - (block_import, None, Some(proof_import), Some(finality_proof_req_builder), Mutex::new(None)) - }, - } - } - - fn make_finality_proof_provider( - &self, - client: PeersClient - ) -> Option>> { - match client { - PeersClient::Full(_, ref backend) => { - let authorities_provider = Arc::new(self.test_config.clone()); - Some(Arc::new(FinalityProofProvider::new(backend.clone(), authorities_provider))) - }, - PeersClient::Light(_, _) => None, - } - } - - fn peer(&mut self, i: usize) -> &mut GrandpaPeer { - &mut self.peers[i] - } - - fn peers(&self) -> &Vec { - &self.peers - } - - fn mut_peers)>(&mut self, closure: F) { - closure(&mut self.peers); - } -} - -#[derive(Clone)] -struct Exit; - -impl futures01::Future for Exit { - type Item = (); - type Error = (); - - fn poll(&mut self) -> futures01::Poll<(), ()> { - Ok(futures01::Async::NotReady) - } -} - -#[derive(Default, Clone)] -pub(crate) struct TestApi { - genesis_authorities: Vec<(AuthorityId, u64)>, -} - -impl TestApi { - pub fn new(genesis_authorities: Vec<(AuthorityId, u64)>) -> Self { - TestApi { - genesis_authorities, - } - } -} - -pub(crate) struct RuntimeApi { - inner: TestApi, -} - -impl ProvideRuntimeApi for TestApi { - type Api = RuntimeApi; - - fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { - RuntimeApi { inner: self.clone() }.into() - } -} - -impl Core for RuntimeApi { - fn Core_version_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<()>, - _: Vec, - ) -> Result> { - unimplemented!("Not required for testing!") - } - - fn Core_execute_block_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<(Block)>, - _: Vec, - ) -> Result> { - unimplemented!("Not required for testing!") - } - - fn Core_initialize_block_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<&::Header>, - _: Vec, - ) -> Result> { - unimplemented!("Not required for testing!") - } -} - -impl ApiExt for RuntimeApi { - fn map_api_result result::Result, R, E>( - &self, - _: F - ) -> result::Result { - unimplemented!("Not required for testing!") - } - - fn runtime_version_at(&self, _: &BlockId) -> Result { - unimplemented!("Not required for testing!") - } - - fn record_proof(&mut self) { - unimplemented!("Not required for testing!") - } - - fn extract_proof(&mut self) -> Option>> { - unimplemented!("Not required for testing!") - } -} - -impl GrandpaApi for RuntimeApi { - fn GrandpaApi_grandpa_authorities_runtime_api_impl( - &self, - _: &BlockId, - _: ExecutionContext, - _: Option<()>, - _: Vec, - ) -> Result>> { - Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) - } -} - -impl AuthoritySetForFinalityProver for TestApi { - fn authorities(&self, block: &BlockId) -> Result> { - let runtime_api = RuntimeApi { inner: self.clone() }; - runtime_api.GrandpaApi_grandpa_authorities_runtime_api_impl(block, ExecutionContext::Syncing, None, Vec::new()) - .map(|v| match v { - NativeOrEncoded::Native(value) => value, - _ => unreachable!("only providing native values"), - }) - } - - fn prove_authorities(&self, block: &BlockId) -> Result>> { - self.authorities(block).map(|auth| vec![auth.encode()]) - } -} - -impl AuthoritySetForFinalityChecker for TestApi { - fn check_authorities_proof( - &self, - _hash: ::Hash, - _header: ::Header, - proof: Vec>, - ) -> Result> { - Decode::decode(&mut &proof[0][..]) - .map_err(|_| unreachable!("incorrect value is passed as GRANDPA authorities proof")) - } -} - -const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500); - -fn make_ids(keys: &[Ed25519Keyring]) -> Vec<(AuthorityId, u64)> { - keys.iter().map(|key| key.clone().public().into()).map(|id| (id, 1)).collect() -} - -fn create_keystore(authority: Ed25519Keyring) -> (KeyStorePtr, tempfile::TempDir) { - let keystore_path = tempfile::tempdir().expect("Creates keystore path"); - let keystore = keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); - keystore.write().insert_ephemeral_from_seed::(&authority.to_seed()) - .expect("Creates authority key"); - - (keystore, keystore_path) -} - -// 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( - runtime: &mut current_thread::Runtime, - blocks: u64, - net: Arc>, - peers: &[Ed25519Keyring], - with: F, -) -> u64 where - F: FnOnce(current_thread::Handle) -> Option>>>> -{ - use parking_lot::RwLock; - - let mut wait_for = Vec::new(); - - let highest_finalized = Arc::new(RwLock::new(0)); - - if let Some(f) = (with)(runtime.handle()) { - wait_for.push(f); - }; - - let mut keystore_paths = Vec::new(); - for (peer_id, key) in peers.iter().enumerate() { - let (keystore, keystore_path) = create_keystore(*key); - keystore_paths.push(keystore_path); - - let highest_finalized = highest_finalized.clone(); - let (client, net_service, link) = { - let net = net.lock(); - // temporary needed for some reason - let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed"); - ( - net.peers[peer_id].client().clone(), - net.peers[peer_id].network_service().clone(), - link, - ) - }; - - wait_for.push( - Box::pin( - client.finality_notification_stream() - .take_while(move |n| { - let mut highest_finalized = highest_finalized.write(); - if *n.header.number() > *highest_finalized { - *highest_finalized = *n.header.number(); - } - future::ready(n.header.number() < &blocks) - }) - .collect() - .map(|_| ()) - ) - ); - - fn assert_send(_: &T) { } - - let grandpa_params = GrandpaParams { - config: Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore: Some(keystore), - name: Some(format!("peer#{}", peer_id)), - }, - link: link, - network: net_service, - inherent_data_providers: InherentDataProviders::new(), - on_exit: Exit, - telemetry_on_connect: None, - voting_rule: (), - }; - let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); - - assert_send(&voter); - - runtime.spawn(voter); - } - - // wait for all finalized on each. - let wait_for = ::futures::future::join_all(wait_for) - .map(|_| ()); - - let drive_to_completion = Compat01As03::new(futures01::future::poll_fn(|| { net.lock().poll(); Ok(futures01::Async::NotReady) })); - let _ = futures::executor::block_on(future::select(wait_for, drive_to_completion)).unwrap(); - - let highest_finalized = *highest_finalized.read(); - highest_finalized -} - -fn run_to_completion( - runtime: &mut current_thread::Runtime, - blocks: u64, - net: Arc>, - peers: &[Ed25519Keyring] -) -> u64 { - run_to_completion_with(runtime, blocks, net, peers, |_| None) -} - -fn add_scheduled_change(block: &mut Block, change: ScheduledChange) { - block.header.digest_mut().push(DigestItem::Consensus( - GRANDPA_ENGINE_ID, - fg_primitives::ConsensusLog::ScheduledChange(change).encode(), - )); -} - -fn add_forced_change( - block: &mut Block, - median_last_finalized: BlockNumber, - change: ScheduledChange, -) { - block.header.digest_mut().push(DigestItem::Consensus( - GRANDPA_ENGINE_ID, - fg_primitives::ConsensusLog::ForcedChange(median_last_finalized, change).encode(), - )); -} - -#[test] -fn finalize_3_voters_no_observers() { - let _ = env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let voters = make_ids(peers); - - let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); - net.peer(0).push_blocks(20, false); - net.block_until_sync(&mut runtime); - - for i in 0..3 { - assert_eq!(net.peer(i).client().info().chain.best_number, 20, - "Peer #{} failed to sync", i); - } - - let net = Arc::new(Mutex::new(net)); - run_to_completion(&mut runtime, 20, net.clone(), peers); - - // normally there's no justification for finalized blocks - assert!( - net.lock().peer(0).client().justification(&BlockId::Number(20)).unwrap().is_none(), - "Extra justification for block#1", - ); -} - -#[test] -fn finalize_3_voters_1_full_observer() { - let mut runtime = current_thread::Runtime::new().unwrap(); - - let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let voters = make_ids(peers); - - let mut net = GrandpaTestNet::new(TestApi::new(voters), 4); - net.peer(0).push_blocks(20, false); - net.block_until_sync(&mut runtime); - - let net = Arc::new(Mutex::new(net)); - let mut finality_notifications = Vec::new(); - - let all_peers = peers.iter() - .cloned() - .map(Some) - .chain(std::iter::once(None)); - - let mut keystore_paths = Vec::new(); - - for (peer_id, local_key) in all_peers.enumerate() { - let (client, net_service, link) = { - 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(), - net.peers[peer_id].network_service().clone(), - link, - ) - }; - finality_notifications.push( - client.finality_notification_stream() - .take_while(|n| future::ready(n.header.number() < &20)) - .for_each(move |_| future::ready(())) - ); - - let keystore = if let Some(local_key) = local_key { - let (keystore, keystore_path) = create_keystore(local_key); - keystore_paths.push(keystore_path); - Some(keystore) - } else { - None - }; - - let grandpa_params = GrandpaParams { - config: Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore, - name: Some(format!("peer#{}", peer_id)), - }, - link: link, - network: net_service, - inherent_data_providers: InherentDataProviders::new(), - on_exit: Exit, - telemetry_on_connect: None, - voting_rule: (), - }; - let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); - - runtime.spawn(voter); - } - - // wait for all finalized on each. - let wait_for = futures::future::join_all(finality_notifications) - .map(|_| ()); - - let drive_to_completion = Compat01As03::new(futures01::future::poll_fn(|| { net.lock().poll(); Ok(futures01::Async::NotReady) })); - let _ = futures::executor::block_on(future::select(wait_for, drive_to_completion)).unwrap(); -} - -#[test] -fn transition_3_voters_twice_1_full_observer() { - let _ = env_logger::try_init(); - let peers_a = &[ - Ed25519Keyring::Alice, - Ed25519Keyring::Bob, - Ed25519Keyring::Charlie, - ]; - - let peers_b = &[ - Ed25519Keyring::Dave, - Ed25519Keyring::Eve, - Ed25519Keyring::Ferdie, - ]; - - let peers_c = &[ - Ed25519Keyring::Alice, - Ed25519Keyring::Eve, - Ed25519Keyring::Two, - ]; - - let observer = &[Ed25519Keyring::One]; - - let genesis_voters = make_ids(peers_a); - - let api = TestApi::new(genesis_voters); - let net = Arc::new(Mutex::new(GrandpaTestNet::new(api, 8))); - - let mut runtime = current_thread::Runtime::new().unwrap(); - - net.lock().peer(0).push_blocks(1, false); - net.lock().block_until_sync(&mut runtime); - - for (i, peer) in net.lock().peers().iter().enumerate() { - let full_client = peer.client().as_full().expect("only full clients are used in test"); - assert_eq!(full_client.info().chain.best_number, 1, - "Peer #{} failed to sync", i); - - let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); - - assert_eq!(set.current(), (0, make_ids(peers_a).as_slice())); - assert_eq!(set.pending_changes().count(), 0); - } - - { - let net = net.clone(); - let client = net.lock().peers[0].client().clone(); - let peers_c = peers_c.clone(); - - // wait for blocks to be finalized before generating new ones - let block_production = client.finality_notification_stream() - .take_while(|n| future::ready(n.header.number() < &30)) - .for_each(move |n| { - match n.header.number() { - 1 => { - // first 14 blocks. - net.lock().peer(0).push_blocks(13, false); - }, - 14 => { - // generate transition at block 15, applied at 20. - net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - let mut block = builder.bake().unwrap(); - add_scheduled_change(&mut block, ScheduledChange { - next_authorities: make_ids(peers_b), - delay: 4, - }); - - block - }); - net.lock().peer(0).push_blocks(5, false); - }, - 20 => { - // at block 21 we do another transition, but this time instant. - // add more until we have 30. - net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - let mut block = builder.bake().unwrap(); - add_scheduled_change(&mut block, ScheduledChange { - next_authorities: make_ids(&peers_c), - delay: 0, - }); - - block - }); - net.lock().peer(0).push_blocks(9, false); - }, - _ => {}, - } - - future::ready(()) - }); - - runtime.spawn(block_production); - } - - let mut finality_notifications = Vec::new(); - let all_peers = peers_a.iter() - .chain(peers_b) - .chain(peers_c) - .chain(observer) - .cloned() - .collect::>() // deduplicate - .into_iter() - .enumerate(); - - let mut keystore_paths = Vec::new(); - for (peer_id, local_key) in all_peers { - let (keystore, keystore_path) = create_keystore(local_key); - keystore_paths.push(keystore_path); - - let (client, net_service, link) = { - 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(), - net.peers[peer_id].network_service().clone(), - link, - ) - }; - - finality_notifications.push( - client.finality_notification_stream() - .take_while(|n| future::ready(n.header.number() < &30)) - .for_each(move |_| future::ready(())) - .map(move |()| { - let full_client = client.as_full().expect("only full clients are used in test"); - let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); - - assert_eq!(set.current(), (2, make_ids(peers_c).as_slice())); - assert_eq!(set.pending_changes().count(), 0); - }) - ); - let grandpa_params = GrandpaParams { - config: Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore: Some(keystore), - name: Some(format!("peer#{}", peer_id)), - }, - link: link, - network: net_service, - inherent_data_providers: InherentDataProviders::new(), - on_exit: Exit, - telemetry_on_connect: None, - voting_rule: (), - }; - let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); - - runtime.spawn(voter); - } - - // wait for all finalized on each. - let wait_for = ::futures::future::join_all(finality_notifications) - .map(|_| ()); - - let drive_to_completion = Compat01As03::new(futures01::future::poll_fn(|| { net.lock().poll(); Ok(futures01::Async::NotReady) })); - let _ = futures::executor::block_on(future::select(wait_for, drive_to_completion)).unwrap(); -} - -#[test] -fn justification_is_emitted_when_consensus_data_changes() { - let mut runtime = current_thread::Runtime::new().unwrap(); - let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3); - - // import block#1 WITH consensus data change - let new_authorities = vec![babe_primitives::AuthorityId::from_slice(&[42; 32])]; - net.peer(0).push_authorities_change_block(new_authorities); - net.block_until_sync(&mut runtime); - let net = Arc::new(Mutex::new(net)); - run_to_completion(&mut runtime, 1, net.clone(), peers); - - // ... and check that there's justification for block#1 - assert!(net.lock().peer(0).client().justification(&BlockId::Number(1)).unwrap().is_some(), - "Missing justification for block#1"); -} - -#[test] -fn justification_is_generated_periodically() { - let mut runtime = current_thread::Runtime::new().unwrap(); - let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let voters = make_ids(peers); - - let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); - net.peer(0).push_blocks(32, false); - net.block_until_sync(&mut runtime); - - let net = Arc::new(Mutex::new(net)); - run_to_completion(&mut runtime, 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().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 mut runtime = current_thread::Runtime::new().unwrap(); - let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; - let voters = make_ids(peers_b); - - // 4 peers, 3 of them are authorities and participate in grandpa - let api = TestApi::new(voters); - 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 mut block = builder.bake().unwrap(); - add_scheduled_change(&mut block, 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.block_until_sync(&mut runtime); - - for i in 0..4 { - assert_eq!(net.peer(i).client().info().chain.best_number, 25, - "Peer #{} failed to sync", i); - } - - let net = Arc::new(Mutex::new(net)); - run_to_completion(&mut runtime, 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 - futures::executor::block_on(Compat01As03::new(futures01::future::poll_fn(move || -> std::result::Result<_, ()> { - if net.lock().peer(3).client().justification(&BlockId::Number(21)).unwrap().is_none() { - net.lock().poll(); - Ok(futures01::Async::NotReady) - } else { - Ok(futures01::Async::Ready(())) - } - }))).unwrap() -} - -#[test] -fn finalizes_multiple_pending_changes_in_order() { - let _ = env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - - let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let peers_b = &[Ed25519Keyring::Dave, Ed25519Keyring::Eve, Ed25519Keyring::Ferdie]; - let peers_c = &[Ed25519Keyring::Dave, Ed25519Keyring::Alice, Ed25519Keyring::Bob]; - - let all_peers = &[ - Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie, - Ed25519Keyring::Dave, Ed25519Keyring::Eve, Ed25519Keyring::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 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 mut block = builder.bake().unwrap(); - add_scheduled_change(&mut block, 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 mut block = builder.bake().unwrap(); - add_scheduled_change(&mut block, 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.block_until_sync(&mut runtime); - - // all peers imported both change blocks - for i in 0..6 { - assert_eq!(net.peer(i).client().info().chain.best_number, 30, - "Peer #{} failed to sync", i); - } - - let net = Arc::new(Mutex::new(net)); - run_to_completion(&mut runtime, 30, net.clone(), all_peers); -} - -#[test] -fn force_change_to_new_set() { - let _ = env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - // two of these guys are offline. - let genesis_authorities = &[ - Ed25519Keyring::Alice, - Ed25519Keyring::Bob, - Ed25519Keyring::Charlie, - Ed25519Keyring::One, - Ed25519Keyring::Two, - ]; - let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let api = TestApi::new(make_ids(genesis_authorities)); - - let voters = make_ids(peers_a); - let net = GrandpaTestNet::new(api, 3); - let net = Arc::new(Mutex::new(net)); - - net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - let mut block = builder.bake().unwrap(); - - // add a forced transition at block 12. - add_forced_change(&mut block, 0, ScheduledChange { - next_authorities: voters.clone(), - delay: 10, - }); - - // add a normal transition too to ensure that forced changes take priority. - add_scheduled_change(&mut block, ScheduledChange { - next_authorities: make_ids(genesis_authorities), - delay: 5, - }); - - block - }); - - net.lock().peer(0).push_blocks(25, false); - net.lock().block_until_sync(&mut runtime); - - for (i, peer) in net.lock().peers().iter().enumerate() { - assert_eq!(peer.client().info().chain.best_number, 26, - "Peer #{} failed to sync", i); - - let full_client = peer.client().as_full().expect("only full clients are used in test"); - let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).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(&mut runtime, 25, net, peers_a); -} - -#[test] -fn allows_reimporting_change_blocks() { - let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; - let voters = make_ids(peers_a); - let api = TestApi::new(voters); - let mut net = GrandpaTestNet::new(api.clone(), 3); - - let client = net.peer(0).client().clone(); - let (mut block_import, ..) = net.make_block_import(client.clone()); - - let full_client = client.as_full().unwrap(); - let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - let mut block = builder.bake().unwrap(); - add_scheduled_change(&mut block, ScheduledChange { - next_authorities: make_ids(peers_b), - delay: 0, - }); - - let block = || { - let block = block.clone(); - BlockImportParams { - 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(), HashMap::new()).unwrap(), - ImportResult::Imported(ImportedAux { - needs_justification: true, - clear_justification_requests: false, - bad_justification: false, - needs_finality_proof: false, - is_new_best: true, - }), - ); - - assert_eq!( - block_import.import_block(block(), HashMap::new()).unwrap(), - ImportResult::AlreadyInChain - ); -} - -#[test] -fn test_bad_justification() { - let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let peers_b = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; - let voters = make_ids(peers_a); - let api = TestApi::new(voters); - let mut net = GrandpaTestNet::new(api.clone(), 3); - - let client = net.peer(0).client().clone(); - let (mut block_import, ..) = net.make_block_import(client.clone()); - - let full_client = client.as_full().expect("only full clients are used in test"); - let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - let mut block = builder.bake().unwrap(); - - add_scheduled_change(&mut block, ScheduledChange { - next_authorities: make_ids(peers_b), - delay: 0, - }); - - let block = || { - let block = block.clone(); - BlockImportParams { - 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(), HashMap::new()).unwrap(), - ImportResult::Imported(ImportedAux { - needs_justification: true, - clear_justification_requests: false, - bad_justification: true, - is_new_best: true, - ..Default::default() - }), - ); - - assert_eq!( - block_import.import_block(block(), HashMap::new()).unwrap(), - ImportResult::AlreadyInChain - ); -} - -#[test] -fn voter_persists_its_votes() { - use std::iter::FromIterator; - use std::sync::atomic::{AtomicUsize, Ordering}; - use futures::future; - use futures::channel::mpsc; - - let _ = env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - - // we have two authorities but we'll only be running the voter for alice - // we are going to be listening for the prevotes it casts - let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; - let voters = make_ids(peers); - - // alice has a chain with 20 blocks - let mut net = GrandpaTestNet::new(TestApi::new(voters.clone()), 2); - net.peer(0).push_blocks(20, false); - net.block_until_sync(&mut runtime); - - assert_eq!(net.peer(0).client().info().chain.best_number, 20, - "Peer #{} failed to sync", 0); - - - let peer = net.peer(0); - let client = peer.client().clone(); - let net = Arc::new(Mutex::new(net)); - - // channel between the voter and the main controller. - // sending a message on the `voter_tx` restarts the voter. - let (voter_tx, voter_rx) = mpsc::unbounded::<()>(); - - let mut keystore_paths = Vec::new(); - - // startup a grandpa voter for alice but also listen for messages on a - // channel. whenever a message is received the voter is restarted. when the - // sender is dropped the voter is stopped. - { - let (keystore, keystore_path) = create_keystore(peers[0]); - keystore_paths.push(keystore_path); - - struct ResettableVoter { - voter: Pin> + Send>>, - voter_rx: mpsc::UnboundedReceiver<()>, - net: Arc>, - client: PeersClient, - keystore: KeyStorePtr, - } - - impl Future for ResettableVoter { - type Output = result::Result<(), ()>; - - fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { - match self.voter.poll() { - Ok(futures01::Async::Ready(())) | Err(_) => panic!("error in the voter"), - Poll::Pending => {}, - } - - match self.voter_rx.poll() { - Err(_) | Ok(futures01::Async::Ready(None)) => return Ok(futures01::Async::Ready(())), - Poll::Pending => {} - Ok(futures01::Async::Ready(Some(()))) => { - let (_block_import, _, _, _, link) = - self.net.lock().make_block_import(self.client.clone()); - let link = link.lock().take().unwrap(); - - let grandpa_params = GrandpaParams { - config: Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore: Some(self.keystore.clone()), - name: Some(format!("peer#{}", 0)), - }, - link, - network: self.net.lock().peers[0].network_service().clone(), - inherent_data_providers: InherentDataProviders::new(), - on_exit: Exit, - telemetry_on_connect: None, - voting_rule: VotingRulesBuilder::default().build(), - }; - - let voter = run_grandpa_voter(grandpa_params) - .expect("all in order with client and network") - .map(move |r| { - // we need to keep the block_import alive since it owns the - // sender for the voter commands channel, if that gets dropped - // then the voter will stop - drop(_block_import); - r - }); - - self.voter = Box::pin(voter); - // notify current task in order to poll the voter - cx.waker().wake_by_ref(); - } - }; - - Poll::Pending - } - } - - // we create a "dummy" voter by setting it to `pending` and triggering the `tx`. - // this way, the `ResettableVoter` will reset its `voter` field to a value ASAP. - voter_tx.unbounded_send(()).unwrap(); - runtime.spawn(ResettableVoter { - voter: Box::pin(futures::future::pending()), - voter_rx, - net: net.clone(), - client: client.clone(), - keystore, - }); - } - - let (exit_tx, exit_rx) = futures::channel::oneshot::channel::<()>(); - - // create the communication layer for bob, but don't start any - // voter. instead we'll listen for the prevote that alice casts - // and cast our own manually - { - let (keystore, keystore_path) = create_keystore(peers[1]); - keystore_paths.push(keystore_path); - - let config = Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore: Some(keystore), - name: Some(format!("peer#{}", 1)), - }; - - let set_state = { - let (_, _, _, _, link) = net.lock().make_block_import(client); - let LinkHalf { persistent_data, .. } = link.lock().take().unwrap(); - let PersistentData { set_state, .. } = persistent_data; - set_state - }; - - let (network, routing_work) = communication::NetworkBridge::new( - net.lock().peers[1].network_service().clone(), - config.clone(), - set_state, - Exit, - true, - ); - futures::executor::block_on(routing_work).unwrap(); - - let (round_rx, round_tx) = network.round_communication( - communication::Round(1), - communication::SetId(0), - Arc::new(VoterSet::from_iter(voters)), - Some(peers[1].pair().into()), - HasVoted::No, - ); - - let round_tx = Arc::new(Mutex::new(round_tx)); - let exit_tx = Arc::new(Mutex::new(Some(exit_tx))); - - let net = net.clone(); - let state = AtomicUsize::new(0); - - runtime.spawn(round_rx.try_for_each(move |signed| { - if state.compare_and_swap(0, 1, Ordering::SeqCst) == 0 { - // the first message we receive should be a prevote from alice. - let prevote = match signed.message { - grandpa::Message::Prevote(prevote) => prevote, - _ => panic!("voter should prevote."), - }; - - // its chain has 20 blocks and the voter targets 3/4 of the - // unfinalized chain, so the vote should be for block 15 - assert!(prevote.target_number == 15); - - // we push 20 more blocks to alice's chain - net.lock().peer(0).push_blocks(20, false); - - let net2 = net.clone(); - let net = net.clone(); - let voter_tx = voter_tx.clone(); - let round_tx = round_tx.clone(); - future::Either::Left(futures_timer::Interval::new(Duration::from_millis(200)) - .take_while(move |_| { - Ok(net2.lock().peer(1).client().info().chain.best_number != 40) - }) - .for_each(|_| Ok(())) - .and_then(move |_| { - let block_30_hash = - net.lock().peer(0).client().as_full().unwrap().hash(30).unwrap().unwrap(); - - // we restart alice's voter - voter_tx.unbounded_send(()).unwrap(); - - // and we push our own prevote for block 30 - let prevote = grandpa::Prevote { - target_number: 30, - target_hash: block_30_hash, - }; - - round_tx.lock().start_send(grandpa::Message::Prevote(prevote)).unwrap(); - Ok(()) - }).map_err(|_| panic!())) - - } else if state.compare_and_swap(1, 2, Ordering::SeqCst) == 1 { - // the next message we receive should be our own prevote - let prevote = match signed.message { - grandpa::Message::Prevote(prevote) => prevote, - _ => panic!("We should receive our own prevote."), - }; - - // targeting block 30 - assert!(prevote.target_number == 30); - - // after alice restarts it should send its previous prevote - // therefore we won't ever receive it again since it will be a - // known message on the gossip layer - - future::Either::Right(future::ok(())) - - } else if state.compare_and_swap(2, 3, Ordering::SeqCst) == 2 { - // we then receive a precommit from alice for block 15 - // even though we casted a prevote for block 30 - let precommit = match signed.message { - grandpa::Message::Precommit(precommit) => precommit, - _ => panic!("voter should precommit."), - }; - - assert!(precommit.target_number == 15); - - // signal exit - exit_tx.clone().lock().take().unwrap().send(()).unwrap(); - - future::Either::Right(future::ok(())) - - } else { - panic!() - } - - })); - } - - let drive_to_completion = Compat01As03::new(futures01::future::poll_fn(|| { net.lock().poll(); Ok(futures01::Async::NotReady) })); - let exit = exit_rx.into_future().map(|_| ()); - - futures::executor::block_on(drive_to_completion.select(exit).map(|_| ())).unwrap(); -} - -#[test] -fn finalize_3_voters_1_light_observer() { - let _ = env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let authorities = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let voters = make_ids(authorities); - - let mut net = GrandpaTestNet::new(TestApi::new(voters), 4); - net.peer(0).push_blocks(20, false); - net.block_until_sync(&mut runtime); - - for i in 0..4 { - assert_eq!(net.peer(i).client().info().chain.best_number, 20, - "Peer #{} failed to sync", i); - } - - let net = Arc::new(Mutex::new(net)); - let link = net.lock().peer(3).data.lock().take().expect("link initialized on startup; qed"); - - let finality_notifications = net.lock().peer(3).client().finality_notification_stream() - .take_while(|n| future::ready(n.header.number() < &20)) - .collect(); - - run_to_completion_with(&mut runtime, 20, net.clone(), authorities, |executor| { - executor.spawn( - run_grandpa_observer( - Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore: None, - name: Some("observer".to_string()), - }, - link, - net.lock().peers[3].network_service().clone(), - Exit, - ).unwrap() - ).unwrap(); - - Some(Box::pin(finality_notifications.map(|_| ()))) - }); -} - -#[test] -fn finality_proof_is_fetched_by_light_client_when_consensus_data_changes() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - - let peers = &[Ed25519Keyring::Alice]; - let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 1); - net.add_light_peer(&GrandpaTestNet::default_config()); - - // import block#1 WITH consensus data change. Light client ignores justification - // && instead fetches finality proof for block #1 - net.peer(0).push_authorities_change_block(vec![babe_primitives::AuthorityId::from_slice(&[42; 32])]); - let net = Arc::new(Mutex::new(net)); - run_to_completion(&mut runtime, 1, net.clone(), peers); - net.lock().block_until_sync(&mut runtime); - - // check that the block#1 is finalized on light client - futures::executor::block_on(Compat01As03::new(futures01::future::poll_fn(move || -> result::Result<_, ()> { - if net.lock().peer(1).client().info().chain.finalized_number == 1 { - Ok(futures01::Async::Ready(())) - } else { - net.lock().poll(); - Ok(futures01::Async::NotReady) - } - }))).unwrap() -} - -#[test] -fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_different() { - // for debug: to ensure that without forced change light client will sync finality proof - const FORCE_CHANGE: bool = true; - - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - - // two of these guys are offline. - let genesis_authorities = if FORCE_CHANGE { - vec![ - Ed25519Keyring::Alice, - Ed25519Keyring::Bob, - Ed25519Keyring::Charlie, - Ed25519Keyring::One, - Ed25519Keyring::Two, - ] - } else { - vec![ - Ed25519Keyring::Alice, - Ed25519Keyring::Bob, - Ed25519Keyring::Charlie, - ] - }; - let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let api = TestApi::new(make_ids(&genesis_authorities)); - - let voters = make_ids(peers_a); - let net = GrandpaTestNet::new(api, 3); - let net = Arc::new(Mutex::new(net)); - - // best is #1 - net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - // add a forced transition at block 5. - let mut block = builder.bake().unwrap(); - if FORCE_CHANGE { - add_forced_change(&mut block, 0, ScheduledChange { - next_authorities: voters.clone(), - delay: 3, - }); - } - block - }); - - // ensure block#10 enacts authorities set change => justification is generated - // normally it will reach light client, but because of the forced change, it will not - net.lock().peer(0).push_blocks(8, false); // best is #9 - net.lock().peer(0).push_authorities_change_block( - vec![babe_primitives::AuthorityId::from_slice(&[42; 32])] - ); // #10 - net.lock().peer(0).push_blocks(1, false); // best is #11 - net.lock().block_until_sync(&mut runtime); - - // finalize block #11 on full clients - run_to_completion(&mut runtime, 11, net.clone(), peers_a); - - // request finalization by light client - net.lock().add_light_peer(&GrandpaTestNet::default_config()); - net.lock().block_until_sync(&mut runtime); - - // check block, finalized on light client - assert_eq!( - net.lock().peer(3).client().info().chain.finalized_number, - if FORCE_CHANGE { 0 } else { 10 }, - ); -} - -#[test] -fn voter_catches_up_to_latest_round_when_behind() { - let _ = env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - - let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob]; - let voters = make_ids(peers); - - let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); - net.peer(0).push_blocks(50, false); - net.block_until_sync(&mut runtime); - - let net = Arc::new(Mutex::new(net)); - let mut finality_notifications = Vec::new(); - - let voter = |keystore, peer_id, link, net: Arc>| -> Pin> + Send>> { - let grandpa_params = GrandpaParams { - config: Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore, - name: Some(format!("peer#{}", peer_id)), - }, - link, - network: net.lock().peer(peer_id).network_service().clone(), - inherent_data_providers: InherentDataProviders::new(), - on_exit: Exit, - telemetry_on_connect: None, - voting_rule: (), - }; - - Box::pin(run_grandpa_voter(grandpa_params).expect("all in order with client and network")) - }; - - let mut keystore_paths = Vec::new(); - - // spawn authorities - for (peer_id, key) in peers.iter().enumerate() { - let (client, link) = { - 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(), - link, - ) - }; - - finality_notifications.push( - client.finality_notification_stream() - .take_while(|n| future::ready(n.header.number() < &50)) - .for_each(move |_| Ok(())) - ); - - let (keystore, keystore_path) = create_keystore(*key); - keystore_paths.push(keystore_path); - - let voter = voter(Some(keystore), peer_id, link, net.clone()); - - runtime.spawn(voter); - } - - // wait for them to finalize block 50. since they'll vote on 3/4 of the - // unfinalized chain it will take at least 4 rounds to do it. - let wait_for_finality = ::futures::future::join_all(finality_notifications) - .map(|_| ()); - - // spawn a new voter, it should be behind by at least 4 rounds and should be - // able to catch up to the latest round - let test = { - let net = net.clone(); - let runtime = runtime.handle(); - - wait_for_finality.and_then(move |_| { - let peer_id = 2; - let link = { - let net = net.lock(); - let mut link = net.peers[peer_id].data.lock(); - link.take().expect("link initialized at startup; qed") - }; - - let set_state = link.persistent_data.set_state.clone(); - - let voter = voter(None, peer_id, link, net); - - runtime.spawn(voter).unwrap(); - - let start_time = std::time::Instant::now(); - let timeout = Duration::from_secs(5 * 60); - let wait_for_catch_up = futures::future::poll_fn(move |_| { - // The voter will start at round 1 and since everyone else is - // already at a later round the only way to get to round 4 (or - // later) is by issuing a catch up request. - if set_state.read().last_completed_round().number >= 4 { - Poll::Ready(()) - } else if start_time.elapsed() > timeout { - panic!("Timed out while waiting for catch up to happen") - } else { - Poll::Pending - } - }); - - wait_for_catch_up - }) - }; - - let drive_to_completion = Compat01As03::new(futures01::future::poll_fn(|| { net.lock().poll(); Ok(futures01::Async::NotReady) })); - let _ = futures::executor::block_on(test.select(drive_to_completion)).unwrap(); -} - -#[test] -fn grandpa_environment_respects_voting_rules() { - use grandpa::Chain; - use network::test::TestClient; - - let peers = &[Ed25519Keyring::Alice]; - let voters = make_ids(peers); - - let mut net = GrandpaTestNet::new(TestApi::new(voters), 1); - let peer = net.peer(0); - let network_service = peer.network_service().clone(); - let link = peer.data.lock().take().unwrap(); - - // create a voter environment with a given voting rule - let environment = |voting_rule: Box>| { - let PersistentData { - ref authority_set, - ref consensus_changes, - ref set_state, - .. - } = link.persistent_data; - - let config = Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore: None, - name: None, - }; - - let (network, _) = NetworkBridge::new( - network_service.clone(), - config.clone(), - set_state.clone(), - Exit, - true, - ); - - Environment { - authority_set: authority_set.clone(), - config: config.clone(), - consensus_changes: consensus_changes.clone(), - client: link.client.clone(), - select_chain: link.select_chain.clone(), - set_id: authority_set.set_id(), - voter_set_state: set_state.clone(), - voters: Arc::new(authority_set.current_authorities()), - network, - voting_rule, - } - }; - - // add 20 blocks - peer.push_blocks(20, false); - - // create an environment with no voting rule restrictions - let unrestricted_env = environment(Box::new(())); - - // another with 3/4 unfinalized chain voting rule restriction - let three_quarters_env = environment(Box::new( - voting_rule::ThreeQuartersOfTheUnfinalizedChain - )); - - // and another restricted with the default voting rules: i.e. 3/4 rule and - // always below best block - let default_env = environment(Box::new( - VotingRulesBuilder::default().build() - )); - - // the unrestricted environment should just return the best block - assert_eq!( - unrestricted_env.best_chain_containing( - peer.client().info().chain.finalized_hash - ).unwrap().1, - 20, - ); - - // both the other environments should return block 15, which is 3/4 of the - // way in the unfinalized chain - assert_eq!( - three_quarters_env.best_chain_containing( - peer.client().info().chain.finalized_hash - ).unwrap().1, - 15, - ); - - assert_eq!( - default_env.best_chain_containing( - peer.client().info().chain.finalized_hash - ).unwrap().1, - 15, - ); - - // we finalize block 19 with block 20 being the best block - peer.client().finalize_block(BlockId::Number(19), None, false).unwrap(); - - // the 3/4 environment should propose block 20 for voting - assert_eq!( - three_quarters_env.best_chain_containing( - peer.client().info().chain.finalized_hash - ).unwrap().1, - 20, - ); - - // while the default environment will always still make sure we don't vote - // on the best block - assert_eq!( - default_env.best_chain_containing( - peer.client().info().chain.finalized_hash - ).unwrap().1, - 19, - ); -} - -#[test] -fn imports_justification_for_regular_blocks_on_import() { - // NOTE: this is a regression test since initially we would only import - // justifications for authority change blocks, and would discard any - // existing justification otherwise. - let peers = &[Ed25519Keyring::Alice]; - let voters = make_ids(peers); - let api = TestApi::new(voters); - let mut net = GrandpaTestNet::new(api.clone(), 1); - - let client = net.peer(0).client().clone(); - let (mut block_import, ..) = net.make_block_import(client.clone()); - - let full_client = client.as_full().expect("only full clients are used in test"); - let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - let block = builder.bake().unwrap(); - - let block_hash = block.hash(); - - // create a valid justification, with one precommit targeting the block - let justification = { - let round = 1; - let set_id = 0; - - let precommit = grandpa::Precommit { - target_hash: block_hash, - target_number: *block.header.number(), - }; - - let msg = grandpa::Message::Precommit(precommit.clone()); - let encoded = communication::localized_payload(round, set_id, &msg); - let signature = peers[0].sign(&encoded[..]).into(); - - let precommit = grandpa::SignedPrecommit { - precommit, - signature, - id: peers[0].public().into(), - }; - - let commit = grandpa::Commit { - target_hash: block_hash, - target_number: *block.header.number(), - precommits: vec![precommit], - }; - - GrandpaJustification::from_commit( - &full_client, - round, - commit, - ).unwrap() - }; - - // we import the block with justification attached - let block = BlockImportParams { - origin: BlockOrigin::File, - header: block.header, - justification: Some(justification.encode()), - post_digests: Vec::new(), - body: Some(block.extrinsics), - finalized: false, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; - - assert_eq!( - block_import.import_block(block, HashMap::new()).unwrap(), - ImportResult::Imported(ImportedAux { - needs_justification: false, - clear_justification_requests: false, - bad_justification: false, - is_new_best: true, - ..Default::default() - }), - ); - - // the justification should be imported and available from the client - assert!( - client.justification(&BlockId::Hash(block_hash)).unwrap().is_some(), - ); -} diff --git a/core/inherents/Cargo.toml b/core/inherents/Cargo.toml deleted file mode 100644 index 45e0b9e828ec7..0000000000000 --- a/core/inherents/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "substrate-inherents" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -parking_lot = { version = "0.9.0", optional = true } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sr-primitives = { path = "../sr-primitives", default-features = false } - -[features] -default = [ "std" ] -std = [ - "parking_lot", - "rstd/std", - "codec/std", - "sr-primitives/std", -] diff --git a/core/inherents/src/lib.rs b/core/inherents/src/lib.rs deleted file mode 100644 index f7363b483bfec..0000000000000 --- a/core/inherents/src/lib.rs +++ /dev/null @@ -1,552 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Provides types and traits for creating and checking inherents. -//! -//! Each inherent is added to a produced block. Each runtime decides on which inherents it -//! wants 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)] -#![warn(missing_docs)] - -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 sr_primitives::RuntimeString; - -/// An identifier for an inherent. -pub type InherentIdentifier = [u8; 8]; - -/// Inherent data to include in a block. -#[derive(Clone, Default, Encode, Decode)] -pub struct InherentData { - /// All inherent data encoded with parity-scale-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 and 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[..]) - .map_err(|_| { - "Could not decode requested inherent type!".into() - }) - .map(Some), - None => Ok(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 occurs, all other errors are removed and the implementation needs to -/// abort 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 deleted file mode 100644 index 0147689985fa9..0000000000000 --- a/core/keyring/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "substrate-keyring" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -primitives = { package = "substrate-primitives", path = "../primitives" } -sr-primitives = { path = "../sr-primitives" } -lazy_static = "1.4.0" -strum = "0.15.0" -strum_macros = "0.15.0" diff --git a/core/keyring/src/ed25519.rs b/core/keyring/src/ed25519.rs deleted file mode 100644 index c1a357fc0e427..0000000000000 --- a/core/keyring/src/ed25519.rs +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Support code for the runtime. A set of test accounts. - -use std::{collections::HashMap, ops::Deref}; -use lazy_static::lazy_static; -use primitives::{ed25519::{Pair, Public, Signature}, Pair as PairT, Public as PublicT, H256}; -pub use primitives::ed25519; -use sr_primitives::AccountId32; - -/// Set of test accounts. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum_macros::Display, strum_macros::EnumIter)] -pub enum Keyring { - Alice, - Bob, - Charlie, - Dave, - Eve, - Ferdie, - One, - Two, -} - -impl Keyring { - pub fn from_public(who: &Public) -> Option { - Self::iter().find(|&k| &Public::from(k) == who) - } - - pub fn from_account_id(who: &AccountId32) -> Option { - Self::iter().find(|&k| &k.to_account_id() == who) - } - - pub fn from_raw_public(who: [u8; 32]) -> Option { - Self::from_public(&Public::from_raw(who)) - } - - 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 to_account_id(self) -> AccountId32 { - self.to_raw_public().into() - } - - 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") - } - - /// Returns an iterator over all test accounts. - pub fn iter() -> impl Iterator { - ::iter() - } - - pub fn public(self) -> Public { - self.pair().public() - } - - pub fn to_seed(self) -> String { - format!("//{}", self) - } -} - -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", - } - } -} - -impl From for sr_primitives::MultiSigner { - fn from(x: Keyring) -> Self { - sr_primitives::MultiSigner::Ed25519(x.into()) - } -} - -lazy_static! { - static ref PRIVATE_KEYS: HashMap = { - Keyring::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 AccountId32 { - fn from(k: Keyring) -> Self { - k.to_account_id() - } -} - -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 primitives::{ed25519::Pair, Pair as PairT}; - - #[test] - fn should_work() { - assert!( - Pair::verify( - &Keyring::Alice.sign(b"I am Alice!"), - b"I am Alice!", - &Keyring::Alice.public(), - ) - ); - assert!( - !Pair::verify( - &Keyring::Alice.sign(b"I am Alice!"), - b"I am Bob!", - &Keyring::Alice.public(), - ) - ); - assert!( - !Pair::verify( - &Keyring::Alice.sign(b"I am Alice!"), - b"I am Alice!", - &Keyring::Bob.public(), - ) - ); - } -} diff --git a/core/keyring/src/lib.rs b/core/keyring/src/lib.rs deleted file mode 100644 index e4714ad3c42a9..0000000000000 --- a/core/keyring/src/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Support code for the runtime. A set of test accounts. - -/// Test account crypto for sr25519. -pub mod sr25519; - -/// Test account crypto for ed25519. -pub mod ed25519; - -/// Convenience export: Sr25519's Keyring is exposed as `AccountKeyring`, -/// since it tends to be used for accounts (although it may also be used -/// by authorities). -pub use sr25519::Keyring as AccountKeyring; - -pub use ed25519::Keyring as Ed25519Keyring; -pub use sr25519::Keyring as Sr25519Keyring; - -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 deleted file mode 100644 index b37b2bdf9b22a..0000000000000 --- a/core/keyring/src/sr25519.rs +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Support code for the runtime. A set of test accounts. - -use std::collections::HashMap; -use std::ops::Deref; -use lazy_static::lazy_static; -use primitives::{sr25519::{Pair, Public, Signature}, Pair as PairT, Public as PublicT, H256}; -pub use primitives::sr25519; -use sr_primitives::AccountId32; - -/// Set of test accounts. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum_macros::Display, strum_macros::EnumIter)] -pub enum Keyring { - Alice, - Bob, - Charlie, - Dave, - Eve, - Ferdie, - One, - Two, -} - -impl Keyring { - pub fn from_public(who: &Public) -> Option { - Self::iter().find(|&k| &Public::from(k) == who) - } - - pub fn from_account_id(who: &AccountId32) -> Option { - Self::iter().find(|&k| &k.to_account_id() == who) - } - - pub fn from_raw_public(who: [u8; 32]) -> Option { - Self::from_public(&Public::from_raw(who)) - } - - 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 to_account_id(self) -> AccountId32 { - self.to_raw_public().into() - } - - 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") - } - - /// Returns an iterator over all test accounts. - pub fn iter() -> impl Iterator { - ::iter() - } - - pub fn public(self) -> Public { - self.pair().public() - } - - pub fn to_seed(self) -> String { - format!("//{}", self) - } -} - -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", - } - } -} - -impl From for sr_primitives::MultiSigner { - fn from(x: Keyring) -> Self { - sr_primitives::MultiSigner::Sr25519(x.into()) - } -} - -lazy_static! { - static ref PRIVATE_KEYS: HashMap = { - Keyring::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 AccountId32 { - fn from(k: Keyring) -> Self { - k.to_account_id() - } -} - -impl From for Public { - fn from(k: Keyring) -> Self { - (*PUBLIC_KEYS).get(&k).unwrap().clone() - } -} - -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 primitives::{sr25519::Pair, Pair as PairT}; - - #[test] - fn should_work() { - assert!( - Pair::verify( - &Keyring::Alice.sign(b"I am Alice!"), - b"I am Alice!", - &Keyring::Alice.public(), - ) - ); - assert!( - !Pair::verify( - &Keyring::Alice.sign(b"I am Alice!"), - b"I am Bob!", - &Keyring::Alice.public(), - ) - ); - assert!( - !Pair::verify( - &Keyring::Alice.sign(b"I am Alice!"), - b"I am Alice!", - &Keyring::Bob.public(), - ) - ); - } -} diff --git a/core/keystore/Cargo.toml b/core/keystore/Cargo.toml deleted file mode 100644 index cc491337cf83a..0000000000000 --- a/core/keystore/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "substrate-keystore" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -derive_more = "0.15.0" -primitives = { package = "substrate-primitives", path = "../primitives" } -app-crypto = { package = "substrate-application-crypto", path = "../application-crypto" } -hex = "0.3.2" -rand = "0.7.2" -serde_json = "1.0.41" -subtle = "2.1.1" -parking_lot = "0.9.0" - -[dev-dependencies] -tempdir = "0.3.7" diff --git a/core/keystore/src/lib.rs b/core/keystore/src/lib.rs deleted file mode 100644 index c86e9f8b8850c..0000000000000 --- a/core/keystore/src/lib.rs +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Keystore (and session key management) for ed25519 based chains like Polkadot. - -#![warn(missing_docs)] - -use std::{collections::HashMap, path::PathBuf, fs::{self, File}, io::{self, Write}, sync::Arc}; - -use primitives::{ - crypto::{KeyTypeId, Pair as PairT, Public, IsWrappedBy, Protected}, traits::BareCryptoStore, -}; - -use app_crypto::{AppKey, AppPublic, AppPair, ed25519, sr25519}; - -use parking_lot::RwLock; - -/// Keystore pointer -pub type KeyStorePtr = Arc>; - -/// Keystore error. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// IO error. - Io(io::Error), - /// JSON error. - Json(serde_json::Error), - /// Invalid password. - #[display(fmt="Invalid password")] - InvalidPassword, - /// Invalid BIP39 phrase - #[display(fmt="Invalid recovery phrase (BIP39) data")] - InvalidPhrase, - /// Invalid seed - #[display(fmt="Invalid seed")] - InvalidSeed, - /// Keystore unavailable - #[display(fmt="Keystore unavailable")] - Unavailable, -} - -/// Keystore Result -pub type Result = std::result::Result; - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Io(ref err) => Some(err), - Error::Json(ref err) => Some(err), - _ => None, - } - } -} - -/// Key store. -/// -/// Stores key pairs in a file system store + short lived key pairs in memory. -/// -/// Every pair that is being generated by a `seed`, will be placed in memory. -pub struct Store { - path: PathBuf, - additional: HashMap<(KeyTypeId, Vec), Vec>, - password: Option>, -} - -impl Store { - /// Open the store at the given path. - /// - /// Optionally takes a password that will be used to encrypt/decrypt the keys. - pub fn open>(path: T, password: Option>) -> Result { - let path = path.into(); - fs::create_dir_all(&path)?; - - let instance = Self { path, additional: HashMap::new(), password }; - Ok(Arc::new(RwLock::new(instance))) - } - - /// Get the public/private key pair for the given public key and key type. - fn get_additional_pair( - &self, - public: &Pair::Public, - key_type: KeyTypeId, - ) -> Result> { - let key = (key_type, public.to_raw_vec()); - self.additional - .get(&key) - .map(|bytes| Pair::from_seed_slice(bytes).map_err(|_| Error::InvalidSeed)) - .transpose() - } - - /// Insert the given public/private key pair with the given key type. - /// - /// Does not place it into the file system store. - fn insert_ephemeral_pair(&mut self, pair: &Pair, key_type: KeyTypeId) { - let key = (key_type, pair.public().to_raw_vec()); - self.additional.insert(key, pair.to_raw_vec()); - } - - /// Insert a new key with anonymous crypto. - /// - /// Places it into the file system store. - fn insert_unknown(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<()> { - let mut file = File::create(self.key_file_path(public, key_type)).map_err(Error::Io)?; - serde_json::to_writer(&file, &suri).map_err(Error::Json)?; - file.flush().map_err(Error::Io)?; - Ok(()) - } - - /// Insert a new key. - /// - /// Places it into the file system store. - pub fn insert_by_type(&self, key_type: KeyTypeId, suri: &str) -> Result { - let pair = Pair::from_string( - suri, - self.password.as_ref().map(|p| &***p) - ).map_err(|_| Error::InvalidSeed)?; - self.insert_unknown(key_type, suri, pair.public().as_slice()) - .map_err(|_| Error::Unavailable)?; - Ok(pair) - } - - /// Insert a new key. - /// - /// Places it into the file system store. - pub fn insert(&self, suri: &str) -> Result { - self.insert_by_type::(Pair::ID, suri).map(Into::into) - } - - /// Generate a new key. - /// - /// Places it into the file system store. - pub fn generate_by_type(&self, key_type: KeyTypeId) -> Result { - let (pair, phrase, _) = Pair::generate_with_phrase(self.password.as_ref().map(|p| &***p)); - let mut file = File::create(self.key_file_path(pair.public().as_slice(), key_type))?; - serde_json::to_writer(&file, &phrase)?; - file.flush()?; - Ok(pair) - } - - /// Generate a new key. - /// - /// Places it into the file system store. - pub fn generate(&self) -> Result { - self.generate_by_type::(Pair::ID).map(Into::into) - } - - /// Create a new key from seed. - /// - /// Does not place it into the file system store. - pub fn insert_ephemeral_from_seed_by_type( - &mut self, - seed: &str, - key_type: KeyTypeId, - ) -> Result { - let pair = Pair::from_string(seed, None).map_err(|_| Error::InvalidSeed)?; - self.insert_ephemeral_pair(&pair, key_type); - Ok(pair) - } - - /// Create a new key from seed. - /// - /// Does not place it into the file system store. - pub fn insert_ephemeral_from_seed(&mut self, seed: &str) -> Result { - self.insert_ephemeral_from_seed_by_type::(seed, Pair::ID).map(Into::into) - } - - /// Get a key pair for the given public key and key type. - pub fn key_pair_by_type(&self, - public: &Pair::Public, - key_type: KeyTypeId, - ) -> Result { - if let Some(pair) = self.get_additional_pair(public, key_type)? { - return Ok(pair) - } - - let path = self.key_file_path(public.as_slice(), key_type); - let file = File::open(path)?; - - let phrase: String = serde_json::from_reader(&file)?; - let pair = Pair::from_string( - &phrase, - self.password.as_ref().map(|p| &***p), - ).map_err(|_| Error::InvalidPhrase)?; - - if &pair.public() == public { - Ok(pair) - } else { - Err(Error::InvalidPassword) - } - } - - /// Get a key pair for the given public key. - pub fn key_pair(&self, public: &::Public) -> Result { - self.key_pair_by_type::(IsWrappedBy::from_ref(public), Pair::ID).map(Into::into) - } - - /// Get public keys of all stored keys that match the given key type. - pub fn public_keys_by_type(&self, key_type: KeyTypeId) -> Result> { - let mut public_keys: Vec = self.additional.keys() - .filter_map(|(ty, public)| { - if *ty == key_type { - Some(TPublic::from_slice(public)) - } else { - None - } - }) - .collect(); - - for entry in fs::read_dir(&self.path)? { - let entry = entry?; - let path = entry.path(); - - // skip directories and non-unicode file names (hex is unicode) - if let Some(name) = path.file_name().and_then(|n| n.to_str()) { - match hex::decode(name) { - Ok(ref hex) => { - if &hex[0..4] != &key_type.0 { continue } - let public = TPublic::from_slice(&hex[4..]); - public_keys.push(public); - } - _ => continue, - } - } - } - - Ok(public_keys) - } - - /// Get public keys of all stored keys that match the key type. - /// - /// This will just use the type of the public key (a list of which to be returned) in order - /// to determine the key type. Unless you use a specialised application-type public key, then - /// this only give you keys registered under generic cryptography, and will not return keys - /// registered under the application type. - pub fn public_keys(&self) -> Result> { - self.public_keys_by_type::(Public::ID) - .map(|v| v.into_iter().map(Into::into).collect()) - } - - /// Returns the file path for the given public key and key type. - fn key_file_path(&self, public: &[u8], key_type: KeyTypeId) -> PathBuf { - let mut buf = self.path.clone(); - let key_type = hex::encode(key_type.0); - let key = hex::encode(public); - buf.push(key_type + key.as_str()); - buf - } -} - -impl BareCryptoStore for Store { - fn sr25519_public_keys(&self, key_type: KeyTypeId) -> Vec { - self.public_keys_by_type::(key_type).unwrap_or_default() - } - - fn sr25519_generate_new( - &mut self, - id: KeyTypeId, - seed: Option<&str>, - ) -> std::result::Result { - let pair = match seed { - Some(seed) => self.insert_ephemeral_from_seed_by_type::(seed, id), - None => self.generate_by_type::(id), - }.map_err(|e| e.to_string())?; - - Ok(pair.public()) - } - - fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option { - self.key_pair_by_type::(pub_key, id).ok() - } - - fn ed25519_public_keys(&self, key_type: KeyTypeId) -> Vec { - self.public_keys_by_type::(key_type).unwrap_or_default() - } - - fn ed25519_generate_new( - &mut self, - id: KeyTypeId, - seed: Option<&str>, - ) -> std::result::Result { - let pair = match seed { - Some(seed) => self.insert_ephemeral_from_seed_by_type::(seed, id), - None => self.generate_by_type::(id), - }.map_err(|e| e.to_string())?; - - Ok(pair.public()) - } - - fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option { - self.key_pair_by_type::(pub_key, id).ok() - } - - fn insert_unknown(&mut self, key_type: KeyTypeId, suri: &str, public: &[u8]) - -> std::result::Result<(), ()> - { - Store::insert_unknown(self, key_type, suri, public).map_err(|_| ()) - } - - fn password(&self) -> Option<&str> { - self.password.as_ref().map(|x| x.as_str()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use tempdir::TempDir; - use primitives::{testing::{SR25519}, crypto::{Ss58Codec}}; - - #[test] - fn basic_store() { - let temp_dir = TempDir::new("keystore").unwrap(); - let store = Store::open(temp_dir.path(), None).unwrap(); - - assert!(store.read().public_keys::().unwrap().is_empty()); - - let key: ed25519::AppPair = store.write().generate().unwrap(); - let key2: ed25519::AppPair = store.read().key_pair(&key.public()).unwrap(); - - assert_eq!(key.public(), key2.public()); - - assert_eq!(store.read().public_keys::().unwrap()[0], key.public()); - } - - #[test] - fn test_insert_ephemeral_from_seed() { - let temp_dir = TempDir::new("keystore").unwrap(); - let store = Store::open(temp_dir.path(), None).unwrap(); - - let pair: ed25519::AppPair = store - .write() - .insert_ephemeral_from_seed("0x3d97c819d68f9bafa7d6e79cb991eebcd77d966c5334c0b94d9e1fa7ad0869dc") - .unwrap(); - assert_eq!( - "5DKUrgFqCPV8iAXx9sjy1nyBygQCeiUYRFWurZGhnrn3HJCA", - pair.public().to_ss58check() - ); - - drop(store); - let store = Store::open(temp_dir.path(), None).unwrap(); - // Keys generated from seed should not be persisted! - assert!(store.read().key_pair::(&pair.public()).is_err()); - } - - #[test] - fn password_being_used() { - let password = String::from("password"); - let temp_dir = TempDir::new("keystore").unwrap(); - let store = Store::open(temp_dir.path(), Some(password.clone().into())).unwrap(); - - let pair: ed25519::AppPair = store.write().generate().unwrap(); - assert_eq!( - pair.public(), - store.read().key_pair::(&pair.public()).unwrap().public(), - ); - - // Without the password the key should not be retrievable - let store = Store::open(temp_dir.path(), None).unwrap(); - assert!(store.read().key_pair::(&pair.public()).is_err()); - - let store = Store::open(temp_dir.path(), Some(password.into())).unwrap(); - assert_eq!( - pair.public(), - store.read().key_pair::(&pair.public()).unwrap().public(), - ); - } - - #[test] - fn public_keys_are_returned() { - let temp_dir = TempDir::new("keystore").unwrap(); - let store = Store::open(temp_dir.path(), None).unwrap(); - - let mut public_keys = Vec::new(); - for i in 0..10 { - public_keys.push(store.write().generate::().unwrap().public()); - public_keys.push(store.write().insert_ephemeral_from_seed::( - &format!("0x3d97c819d68f9bafa7d6e79cb991eebcd7{}d966c5334c0b94d9e1fa7ad0869dc", i), - ).unwrap().public()); - } - - // Generate a key of a different type - store.write().generate::().unwrap(); - - public_keys.sort(); - let mut store_pubs = store.read().public_keys::().unwrap(); - store_pubs.sort(); - - assert_eq!(public_keys, store_pubs); - } - - #[test] - fn store_unknown_and_extract_it() { - let temp_dir = TempDir::new("keystore").unwrap(); - let store = Store::open(temp_dir.path(), None).unwrap(); - - let secret_uri = "//Alice"; - let key_pair = sr25519::AppPair::from_string(secret_uri, None).expect("Generates key pair"); - - store.write().insert_unknown( - SR25519, - secret_uri, - key_pair.public().as_ref(), - ).expect("Inserts unknown key"); - - let store_key_pair = store.read().key_pair_by_type::( - &key_pair.public(), - SR25519, - ).expect("Gets key pair from keystore"); - - assert_eq!(key_pair.public(), store_key_pair.public()); - } -} diff --git a/core/network/Cargo.toml b/core/network/Cargo.toml deleted file mode 100644 index 71e7d95bfa56a..0000000000000 --- a/core/network/Cargo.toml +++ /dev/null @@ -1,62 +0,0 @@ -[package] -description = "Substrate network protocol" -name = "substrate-network" -version = "2.0.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -bytes = "0.4.12" -derive_more = "0.15.0" -either = "1.5.3" -log = "0.4.8" -parking_lot = "0.9.0" -bitflags = "1.2.0" -fnv = "1.0.6" -futures = "0.1.29" -futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } -futures-timer = "0.4.0" -linked-hash-map = "0.5.2" -linked_hash_set = "0.1.3" -lru-cache = "0.1.2" -rustc-hex = "2.0.1" -rand = "0.7.2" -libp2p = { version = "0.12.0", default-features = false, features = ["libp2p-websocket"] } -fork-tree = { path = "../../core/utils/fork-tree" } -consensus = { package = "substrate-consensus-common", path = "../../core/consensus/common" } -client = { package = "substrate-client", path = "../../core/client" } -header_metadata = { package = "substrate-header-metadata", path = "../../core/client/header-metadata" } -sr-primitives = { path = "../../core/sr-primitives" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } -peerset = { package = "substrate-peerset", path = "../../core/peerset" } -serde = { version = "1.0.101", features = ["derive"] } -serde_json = "1.0.41" -slog = { version = "2.5.2", features = ["nested-values"] } -slog_derive = "0.1.1" -smallvec = "0.6.10" -tokio-io = "0.1.12" -tokio = { version = "0.1.22", optional = true } -unsigned-varint = { version = "0.2.2", features = ["codec"] } -keyring = { package = "substrate-keyring", path = "../../core/keyring", optional = true } -test_client = { package = "substrate-test-client", path = "../../core/test-client", optional = true } -test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client", optional = true } -erased-serde = "0.3.9" -void = "1.0.2" -zeroize = "0.10.1" -babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../consensus/babe/primitives" } - -[dev-dependencies] -env_logger = "0.7.0" -keyring = { package = "substrate-keyring", path = "../../core/keyring" } -quickcheck = "0.9.0" -rand = "0.7.2" -test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } -test_runtime = { package = "substrate-test-runtime", path = "../../core/test-runtime" } -tempdir = "0.3.7" -tokio = "0.1.22" - -[features] -default = [] -test-helpers = ["keyring", "test-client", "tokio"] diff --git a/core/network/src/behaviour.rs b/core/network/src/behaviour.rs deleted file mode 100644 index 2471cbcaaf26a..0000000000000 --- a/core/network/src/behaviour.rs +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::{ - debug_info, discovery::DiscoveryBehaviour, discovery::DiscoveryOut, DiscoveryNetBehaviour, - protocol::event::DhtEvent -}; -use crate::{ExHashT, specialization::NetworkSpecialization}; -use crate::protocol::{CustomMessageOutcome, Protocol}; -use futures::prelude::*; -use libp2p::NetworkBehaviour; -use libp2p::core::{Multiaddr, PeerId, PublicKey}; -use libp2p::kad::record; -use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess}; -use libp2p::core::{nodes::Substream, muxing::StreamMuxerBox}; -use log::warn; -use sr_primitives::traits::Block as BlockT; -use std::iter; -use void; - -/// General behaviour of the network. Combines all protocols together. -#[derive(NetworkBehaviour)] -#[behaviour(out_event = "BehaviourOut", poll_method = "poll")] -pub struct Behaviour, H: ExHashT> { - /// All the substrate-specific protocols. - substrate: Protocol, - /// Periodically pings and identifies the nodes we are connected to, and store information in a - /// cache. - debug_info: debug_info::DebugInfoBehaviour>, - /// Discovers nodes of the network. - discovery: DiscoveryBehaviour>, - - /// Queue of events to produce for the outside. - #[behaviour(ignore)] - events: Vec>, -} - -/// Event generated by `Behaviour`. -pub enum BehaviourOut { - SubstrateAction(CustomMessageOutcome), - Dht(DhtEvent), -} - -impl, H: ExHashT> Behaviour { - /// Builds a new `Behaviour`. - pub fn new( - substrate: Protocol, - user_agent: String, - local_public_key: PublicKey, - known_addresses: Vec<(PeerId, Multiaddr)>, - enable_mdns: bool, - ) -> Self { - Behaviour { - substrate, - debug_info: debug_info::DebugInfoBehaviour::new(user_agent, local_public_key.clone()), - discovery: DiscoveryBehaviour::new(local_public_key, known_addresses, enable_mdns), - events: Vec::new(), - } - } - - /// Returns the list of nodes that we know exist in the network. - pub fn known_peers(&mut self) -> impl Iterator { - self.discovery.known_peers() - } - - /// Adds a hard-coded address for the given peer, that never expires. - pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) { - self.discovery.add_known_address(peer_id, addr) - } - - /// Borrows `self` and returns a struct giving access to the information about a node. - /// - /// Returns `None` if we don't know anything about this node. Always returns `Some` for nodes - /// we're connected to, meaning that if `None` is returned then we're not connected to that - /// node. - pub fn node(&self, peer_id: &PeerId) -> Option { - self.debug_info.node(peer_id) - } - - /// Returns a shared reference to the user protocol. - pub fn user_protocol(&self) -> &Protocol { - &self.substrate - } - - /// Returns a mutable reference to the user protocol. - pub fn user_protocol_mut(&mut self) -> &mut Protocol { - &mut self.substrate - } - - /// Start querying a record from the DHT. Will later produce either a `ValueFound` or a `ValueNotFound` event. - pub fn get_value(&mut self, key: &record::Key) { - self.discovery.get_value(key); - } - - /// Starts putting a record into DHT. Will later produce either a `ValuePut` or a `ValuePutFailed` event. - pub fn put_value(&mut self, key: record::Key, value: Vec) { - self.discovery.put_value(key, value); - } -} - -impl, H: ExHashT> NetworkBehaviourEventProcess for -Behaviour { - fn inject_event(&mut self, event: void::Void) { - void::unreachable(event) - } -} - -impl, H: ExHashT> NetworkBehaviourEventProcess> for -Behaviour { - fn inject_event(&mut self, event: CustomMessageOutcome) { - self.events.push(BehaviourOut::SubstrateAction(event)); - } -} - -impl, H: ExHashT> NetworkBehaviourEventProcess - for Behaviour { - fn inject_event(&mut self, event: debug_info::DebugInfoEvent) { - let debug_info::DebugInfoEvent::Identified { peer_id, mut info } = event; - 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 {:?} has reported more than 30 addresses; \ - it is identified by {:?} and {:?}", peer_id, info.protocol_version, - info.agent_version - ); - info.listen_addrs.truncate(30); - } - for addr in &info.listen_addrs { - self.discovery.add_self_reported_address(&peer_id, addr.clone()); - } - self.substrate.add_discovered_nodes(iter::once(peer_id.clone())); - } -} - -impl, H: ExHashT> NetworkBehaviourEventProcess - for Behaviour { - fn inject_event(&mut self, out: DiscoveryOut) { - match out { - DiscoveryOut::UnroutablePeer(_peer_id) => { - // Obtaining and reporting listen addresses for unroutable peers back - // to Kademlia is handled by the `Identify` protocol, part of the - // `DebugInfoBehaviour`. See the `NetworkBehaviourEventProcess` - // implementation for `DebugInfoEvent`. - } - DiscoveryOut::Discovered(peer_id) => { - self.substrate.add_discovered_nodes(iter::once(peer_id)); - } - DiscoveryOut::ValueFound(results) => { - self.events.push(BehaviourOut::Dht(DhtEvent::ValueFound(results))); - } - DiscoveryOut::ValueNotFound(key) => { - self.events.push(BehaviourOut::Dht(DhtEvent::ValueNotFound(key))); - } - DiscoveryOut::ValuePut(key) => { - self.events.push(BehaviourOut::Dht(DhtEvent::ValuePut(key))); - } - DiscoveryOut::ValuePutFailed(key) => { - self.events.push(BehaviourOut::Dht(DhtEvent::ValuePutFailed(key))); - } - } - } -} - -impl, H: ExHashT> Behaviour { - fn poll(&mut self) -> Async>> { - if !self.events.is_empty() { - return Async::Ready(NetworkBehaviourAction::GenerateEvent(self.events.remove(0))) - } - - Async::NotReady - } -} diff --git a/core/network/src/chain.rs b/core/network/src/chain.rs deleted file mode 100644 index f68942fd96d38..0000000000000 --- a/core/network/src/chain.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Blockchain access trait - -use client::{self, Client as SubstrateClient, ClientInfo, CallExecutor}; -use client::error::Error; -use client::light::fetcher::ChangesProof; -use consensus::{BlockImport, BlockStatus, Error as ConsensusError}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT}; -use sr_primitives::generic::{BlockId}; -use sr_primitives::Justification; -use primitives::{H256, Blake2Hasher, storage::StorageKey}; - -/// Local client abstraction for the network. -pub trait Client: Send + Sync { - /// Get blockchain info. - fn info(&self) -> ClientInfo; - - /// Get block status. - fn block_status(&self, id: &BlockId) -> Result; - - /// Get block hash by number. - fn block_hash(&self, block_number: ::Number) -> Result, Error>; - - /// Get block header. - fn header(&self, id: &BlockId) -> Result, Error>; - - /// Get block body. - fn body(&self, id: &BlockId) -> Result>, Error>; - - /// Get block justification. - fn justification(&self, id: &BlockId) -> Result, Error>; - - /// Get block header proof. - fn header_proof(&self, block_number: ::Number) -> Result<(Block::Header, Vec>), Error>; - - /// Get storage read execution proof. - fn read_proof(&self, block: &Block::Hash, keys: &[Vec]) -> Result>, Error>; - - /// Get child storage read execution proof. - fn read_child_proof( - &self, - block: &Block::Hash, - storage_key: &[u8], - keys: &[Vec], - ) -> Result>, Error>; - - /// Get method execution proof. - fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, Vec>), Error>; - - /// Get key changes proof. - fn key_changes_proof( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&StorageKey>, - 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; -} - -/// Finality proof provider. -pub trait FinalityProofProvider: Send + Sync { - /// Prove finality of the block. - fn prove_finality(&self, for_block: Block::Hash, request: &[u8]) -> Result>, Error>; -} - -impl FinalityProofProvider for () { - fn prove_finality(&self, _for_block: Block::Hash, _request: &[u8]) -> Result>, Error> { - Ok(None) - } -} - -impl Client for SubstrateClient where - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static, - Self: BlockImport, - Block: BlockT, - RA: Send + Sync -{ - fn info(&self) -> ClientInfo { - (self as &SubstrateClient).info() - } - - fn block_status(&self, id: &BlockId) -> Result { - (self as &SubstrateClient).block_status(id) - } - - fn block_hash(&self, block_number: ::Number) -> Result, Error> { - (self as &SubstrateClient).block_hash(block_number) - } - - fn header(&self, id: &BlockId) -> Result, Error> { - (self as &SubstrateClient).header(id) - } - - fn body(&self, id: &BlockId) -> Result>, Error> { - (self as &SubstrateClient).body(id) - } - - fn justification(&self, id: &BlockId) -> Result, Error> { - (self as &SubstrateClient).justification(id) - } - - fn header_proof(&self, block_number: ::Number) -> Result<(Block::Header, Vec>), Error> { - (self as &SubstrateClient).header_proof(&BlockId::Number(block_number)) - } - - fn read_proof(&self, block: &Block::Hash, keys: &[Vec]) -> Result>, Error> { - (self as &SubstrateClient).read_proof(&BlockId::Hash(block.clone()), keys) - } - - fn read_child_proof( - &self, - block: &Block::Hash, - storage_key: &[u8], - keys: &[Vec], - ) -> Result>, Error> { - (self as &SubstrateClient) - .read_child_proof(&BlockId::Hash(block.clone()), storage_key, keys) - } - - fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, Vec>), Error> { - (self as &SubstrateClient).execution_proof(&BlockId::Hash(block.clone()), method, data) - } - - fn key_changes_proof( - &self, - first: Block::Hash, - last: Block::Hash, - min: Block::Hash, - max: Block::Hash, - storage_key: Option<&StorageKey>, - key: &StorageKey, - ) -> Result, Error> { - (self as &SubstrateClient).key_changes_proof(first, last, min, max, storage_key, key) - } - - fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result { - if base == block { - return Ok(false); - } - - let ancestor = header_metadata::lowest_common_ancestor(self, *block, *base)?; - - Ok(ancestor.hash == *base) - } -} diff --git a/core/network/src/config.rs b/core/network/src/config.rs deleted file mode 100644 index 445d4427bd91c..0000000000000 --- a/core/network/src/config.rs +++ /dev/null @@ -1,521 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Configuration of the networking layer. -//! -//! The [`Params`] struct is the struct that must be passed in order to initialize the networking. -//! See the documentation of [`Params`]. - -pub use crate::protocol::ProtocolConfig; -pub use libp2p::{identity, core::PublicKey, wasm_ext::ExtTransport, build_multiaddr}; - -use crate::chain::{Client, FinalityProofProvider}; -use crate::on_demand_layer::OnDemand; -use crate::service::{ExHashT, TransactionPool}; -use bitflags::bitflags; -use consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; -use sr_primitives::traits::{Block as BlockT}; -use std::sync::Arc; -use libp2p::identity::{Keypair, ed25519}; -use libp2p::wasm_ext; -use libp2p::{PeerId, Multiaddr, multiaddr}; -use std::error::Error; -use std::{io::{self, Write}, iter, fmt, fs, net::Ipv4Addr, path::{Path, PathBuf}}; -use zeroize::Zeroize; - -/// Network initialization parameters. -pub struct Params { - /// Assigned roles for our node (full, light, ...). - pub roles: Roles, - - /// Network layer configuration. - pub network_config: NetworkConfiguration, - - /// Client that contains the blockchain. - pub chain: Arc>, - - /// Finality proof provider. - /// - /// This object, if `Some`, is used when a node on the network requests a proof of finality - /// from us. - pub finality_proof_provider: Option>>, - - /// How to build requests for proofs of finality. - /// - /// This object, if `Some`, is used when we need a proof of finality from another node. - pub finality_proof_request_builder: Option>, - - /// The `OnDemand` object acts as a "receiver" for block data requests from the client. - /// If `Some`, the network worker will process these requests and answer them. - /// Normally used only for light clients. - pub on_demand: Option>>, - - /// Pool of transactions. - /// - /// The network worker will fetch transactions from this object in order to propagate them on - /// the network. - pub transaction_pool: Arc>, - - /// Name of the protocol to use on the wire. Should be different for each chain. - pub protocol_id: ProtocolId, - - /// Import queue to use. - /// - /// The import queue is the component that verifies that blocks received from other nodes are - /// valid. - pub import_queue: Box>, - - /// Customization of the network. Use this to plug additional networking capabilities. - pub specialization: S, - - /// Type to check incoming block announcements. - pub block_announce_validator: Box + Send> -} - -bitflags! { - /// Bitmask of the roles that a node fulfills. - pub struct Roles: u8 { - /// No network. - const NONE = 0b00000000; - /// Full node, does not participate in consensus. - const FULL = 0b00000001; - /// Light client node. - const LIGHT = 0b00000010; - /// Act as an authority - const AUTHORITY = 0b00000100; - } -} - -impl Roles { - /// Does this role represents a client that holds full chain data locally? - pub fn is_full(&self) -> bool { - self.intersects(Roles::FULL | Roles::AUTHORITY) - } - - /// Does this role represents a client that does not participates in the consensus? - pub fn is_authority(&self) -> bool { - *self == Roles::AUTHORITY - } - - /// Does this role represents a client that does not hold full chain data locally? - pub fn is_light(&self) -> bool { - !self.is_full() - } -} - -impl codec::Encode for Roles { - fn encode_to(&self, dest: &mut T) { - dest.push_byte(self.bits()) - } -} - -impl codec::EncodeLike for Roles {} - -impl codec::Decode for Roles { - fn decode(input: &mut I) -> Result { - Self::from_bits(input.read_byte()?).ok_or_else(|| codec::Error::from("Invalid bytes")) - } -} - -/// Finality proof request builder. -pub trait FinalityProofRequestBuilder: Send { - /// Build data blob, associated with the request. - fn build_request_data(&mut self, hash: &B::Hash) -> Vec; -} - -/// Implementation of `FinalityProofRequestBuilder` that builds a dummy empty request. -#[derive(Debug, Default)] -pub struct DummyFinalityProofRequestBuilder; - -impl FinalityProofRequestBuilder for DummyFinalityProofRequestBuilder { - fn build_request_data(&mut self, _: &B::Hash) -> Vec { - Vec::new() - } -} - -/// Shared finality proof request builder struct used by the queue. -pub type BoxFinalityProofRequestBuilder = Box + Send + Sync>; - -/// Name of a protocol, transmitted on the wire. Should be unique for each chain. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ProtocolId(smallvec::SmallVec<[u8; 6]>); - -impl<'a> From<&'a [u8]> for ProtocolId { - fn from(bytes: &'a [u8]) -> ProtocolId { - ProtocolId(bytes.into()) - } -} - -impl ProtocolId { - /// Exposes the `ProtocolId` as bytes. - pub fn as_bytes(&self) -> &[u8] { - self.0.as_ref() - } -} - -/// Parses a string address and splits it into Multiaddress and PeerId, if -/// valid. -/// -/// # Example -/// -/// ``` -/// # use substrate_network::{Multiaddr, PeerId, config::parse_str_addr}; -/// let (peer_id, addr) = parse_str_addr( -/// "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV" -/// ).unwrap(); -/// assert_eq!(peer_id, "QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".parse::().unwrap()); -/// assert_eq!(addr, "/ip4/198.51.100.19/tcp/30333".parse::().unwrap()); -/// ``` -/// -pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> { - let addr: Multiaddr = addr_str.parse()?; - parse_addr(addr) -} - -/// Splits a Multiaddress into a Multiaddress and PeerId. -pub fn parse_addr(mut addr: Multiaddr)-> Result<(PeerId, Multiaddr), ParseErr> { - let who = match addr.pop() { - Some(multiaddr::Protocol::P2p(key)) => PeerId::from_multihash(key) - .map_err(|_| ParseErr::InvalidPeerId)?, - _ => 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(multiaddr::Error), - /// 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 std::error::Error for ParseErr { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - ParseErr::MultiaddrParse(err) => Some(err), - ParseErr::InvalidPeerId => None, - ParseErr::PeerIdMissing => None, - } - } -} - -impl From for ParseErr { - fn from(err: multiaddr::Error) -> ParseErr { - ParseErr::MultiaddrParse(err) - } -} - -/// Network service configuration. -#[derive(Clone)] -pub struct NetworkConfiguration { - /// Directory path to store general network configuration. None means nothing will be saved. - pub config_path: Option, - /// Directory path to store network-specific configuration. None means nothing will be saved. - pub net_config_path: Option, - /// Multiaddresses to listen for incoming connections. - pub listen_addresses: Vec, - /// Multiaddresses to advertise. Detected automatically if empty. - pub public_addresses: Vec, - /// List of initial node addresses - pub boot_nodes: Vec, - /// The node key configuration, which determines the node's network identity keypair. - pub node_key: NodeKeyConfig, - /// Maximum allowed number of incoming connections. - pub in_peers: u32, - /// Number of outgoing connections we're trying to maintain. - pub out_peers: u32, - /// List of reserved node addresses. - pub reserved_nodes: Vec, - /// The non-reserved peer mode. - pub non_reserved_mode: NonReservedPeerMode, - /// 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, - /// Configuration for the transport layer. - pub transport: TransportConfig, -} - -impl Default for NetworkConfiguration { - fn default() -> Self { - NetworkConfiguration { - config_path: None, - net_config_path: None, - listen_addresses: Vec::new(), - public_addresses: Vec::new(), - boot_nodes: Vec::new(), - node_key: NodeKeyConfig::Ed25519(Secret::New), - in_peers: 25, - out_peers: 75, - reserved_nodes: Vec::new(), - non_reserved_mode: NonReservedPeerMode::Accept, - client_version: "unknown".into(), - node_name: "unknown".into(), - transport: TransportConfig::Normal { - enable_mdns: false, - wasm_external_transport: None, - }, - } - } -} - -impl NetworkConfiguration { - /// Create a new instance of default settings. - pub fn new() -> Self { - Self::default() - } - - /// Create new default configuration for localhost-only connection with random port (useful for testing) - pub fn new_local() -> NetworkConfiguration { - let mut config = NetworkConfiguration::new(); - config.listen_addresses = vec![ - iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) - .chain(iter::once(multiaddr::Protocol::Tcp(0))) - .collect() - ]; - config - } - - /// Create new default configuration for localhost-only connection with random port (useful for testing) - pub fn new_memory() -> NetworkConfiguration { - let mut config = NetworkConfiguration::new(); - config.listen_addresses = vec![ - iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) - .chain(iter::once(multiaddr::Protocol::Tcp(0))) - .collect() - ]; - config - } -} - -/// Configuration for the transport layer. -#[derive(Clone)] -pub enum TransportConfig { - /// Normal transport mode. - Normal { - /// If true, the network will use mDNS to discover other libp2p nodes on the local network - /// and connect to them if they support the same chain. - enable_mdns: bool, - - /// Optional external implementation of a libp2p transport. Used in WASM contexts where we - /// need some binding between the networking provided by the operating system or environment - /// and libp2p. - /// - /// This parameter exists whatever the target platform is, but it is expected to be set to - /// `Some` only when compiling for WASM. - wasm_external_transport: Option, - }, - - /// Only allow connections within the same process. - /// Only addresses of the form `/memory/...` will be supported. - MemoryOnly, -} - -/// The policy for connections to non-reserved peers. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum NonReservedPeerMode { - /// Accept them. This is the default. - Accept, - /// Deny them. - Deny, -} - -impl NonReservedPeerMode { - /// Attempt to parse the peer mode from a string. - pub fn parse(s: &str) -> Option { - match s { - "accept" => Some(NonReservedPeerMode::Accept), - "deny" => Some(NonReservedPeerMode::Deny), - _ => None, - } - } -} - -/// The configuration of a node's secret key, describing the type of key -/// and how it is obtained. A node's identity keypair is the result of -/// the evaluation of the node key configuration. -#[derive(Clone)] -pub enum NodeKeyConfig { - /// A Ed25519 secret key configuration. - Ed25519(Secret) -} - -/// The options for obtaining a Ed25519 secret key. -pub type Ed25519Secret = Secret; - -/// The configuration options for obtaining a secret key `K`. -#[derive(Clone)] -pub enum Secret { - /// Use the given secret key `K`. - Input(K), - /// Read the secret key from a file. If the file does not exist, - /// it is created with a newly generated secret key `K`. The format - /// of the file is determined by `K`: - /// - /// * `ed25519::SecretKey`: An unencoded 32 bytes Ed25519 secret key. - File(PathBuf), - /// Always generate a new secret key `K`. - New -} - -impl NodeKeyConfig { - /// Evaluate a `NodeKeyConfig` to obtain an identity `Keypair`: - /// - /// * If the secret is configured as input, the corresponding keypair is returned. - /// - /// * If the secret is configured as a file, it is read from that file, if it exists. - /// Otherwise a new secret is generated and stored. In either case, the - /// keypair obtained from the secret is returned. - /// - /// * If the secret is configured to be new, it is generated and the corresponding - /// keypair is returned. - pub fn into_keypair(self) -> io::Result { - use NodeKeyConfig::*; - match self { - Ed25519(Secret::New) => - Ok(Keypair::generate_ed25519()), - - Ed25519(Secret::Input(k)) => - Ok(Keypair::Ed25519(k.into())), - - Ed25519(Secret::File(f)) => - get_secret(f, - |mut b| ed25519::SecretKey::from_bytes(&mut b), - ed25519::SecretKey::generate, - |b| b.as_ref().to_vec()) - .map(ed25519::Keypair::from) - .map(Keypair::Ed25519), - } - } -} - -/// Load a secret key from a file, if it exists, or generate a -/// new secret key and write it to that file. In either case, -/// the secret key is returned. -fn get_secret(file: P, parse: F, generate: G, serialize: W) -> io::Result -where - P: AsRef, - F: for<'r> FnOnce(&'r mut [u8]) -> Result, - G: FnOnce() -> K, - E: Error + Send + Sync + 'static, - W: Fn(&K) -> Vec, -{ - std::fs::read(&file) - .and_then(|mut sk_bytes| - parse(&mut sk_bytes) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))) - .or_else(|e| { - if e.kind() == io::ErrorKind::NotFound { - file.as_ref().parent().map_or(Ok(()), fs::create_dir_all)?; - let sk = generate(); - let mut sk_vec = serialize(&sk); - write_secret_file(file, &sk_vec)?; - sk_vec.zeroize(); - Ok(sk) - } else { - Err(e) - } - }) -} - -/// Write secret bytes to a file. -fn write_secret_file

(path: P, sk_bytes: &[u8]) -> io::Result<()> -where - P: AsRef -{ - let mut file = open_secret_file(&path)?; - file.write_all(sk_bytes) -} - -/// Opens a file containing a secret key in write mode. -#[cfg(unix)] -fn open_secret_file

(path: P) -> io::Result -where - P: AsRef -{ - use std::os::unix::fs::OpenOptionsExt; - fs::OpenOptions::new() - .write(true) - .create_new(true) - .mode(0o600) - .open(path) -} - -/// Opens a file containing a secret key in write mode. -#[cfg(not(unix))] -fn open_secret_file

(path: P) -> Result -where - P: AsRef -{ - fs::OpenOptions::new() - .write(true) - .create_new(true) - .open(path) -} - -#[cfg(test)] -mod tests { - use super::*; - use tempdir::TempDir; - - fn secret_bytes(kp: &Keypair) -> Vec { - match kp { - Keypair::Ed25519(p) => p.secret().as_ref().iter().cloned().collect(), - Keypair::Secp256k1(p) => p.secret().to_bytes().to_vec(), - _ => panic!("Unexpected keypair.") - } - } - - #[test] - fn test_secret_file() { - let tmp = TempDir::new("x").unwrap(); - std::fs::remove_dir(tmp.path()).unwrap(); // should be recreated - let file = tmp.path().join("x").to_path_buf(); - let kp1 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap(); - let kp2 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap(); - assert!(file.is_file() && secret_bytes(&kp1) == secret_bytes(&kp2)) - } - - #[test] - fn test_secret_input() { - let sk = ed25519::SecretKey::generate(); - let kp1 = NodeKeyConfig::Ed25519(Secret::Input(sk.clone())).into_keypair().unwrap(); - let kp2 = NodeKeyConfig::Ed25519(Secret::Input(sk)).into_keypair().unwrap(); - assert!(secret_bytes(&kp1) == secret_bytes(&kp2)); - } - - #[test] - fn test_secret_new() { - let kp1 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap(); - let kp2 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap(); - assert!(secret_bytes(&kp1) != secret_bytes(&kp2)); - } -} diff --git a/core/network/src/error.rs b/core/network/src/error.rs deleted file mode 100644 index c3f89e43c1710..0000000000000 --- a/core/network/src/error.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate network possible errors. - -use client; - -use libp2p::{PeerId, Multiaddr}; - -use std::fmt; - -/// Result type alias for the network. -pub type Result = std::result::Result; - -/// Error type for the network. -#[derive(derive_more::Display, derive_more::From)] -pub enum Error { - /// Io error - Io(std::io::Error), - /// Client error - Client(client::error::Error), - /// The same bootnode (based on address) is registered with two different peer ids. - #[display( - fmt = "The same bootnode (`{}`) is registered with two different peer ids: `{}` and `{}`", - address, - first_id, - second_id, - )] - DuplicateBootnode { - /// The address of the bootnode. - address: Multiaddr, - /// The first peer id that was found for the bootnode. - first_id: PeerId, - /// The second peer id that was found for the bootnode. - second_id: PeerId, - }, -} - -// Make `Debug` use the `Display` implementation. -impl fmt::Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Io(ref err) => Some(err), - Error::Client(ref err) => Some(err), - Error::DuplicateBootnode { .. } => None, - } - } -} diff --git a/core/network/src/legacy_proto/behaviour.rs b/core/network/src/legacy_proto/behaviour.rs deleted file mode 100644 index 1c83329ba0e10..0000000000000 --- a/core/network/src/legacy_proto/behaviour.rs +++ /dev/null @@ -1,1034 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::{DiscoveryNetBehaviour, config::ProtocolId}; -use crate::legacy_proto::handler::{CustomProtoHandlerProto, CustomProtoHandlerOut, CustomProtoHandlerIn}; -use crate::legacy_proto::upgrade::RegisteredProtocol; -use crate::protocol::message::Message; -use fnv::FnvHashMap; -use futures::prelude::*; -use futures03::{compat::Compat, TryFutureExt as _, StreamExt as _, TryStreamExt as _}; -use libp2p::core::{ConnectedPoint, Multiaddr, PeerId}; -use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use log::{debug, error, trace, warn}; -use rand::distributions::{Distribution as _, Uniform}; -use sr_primitives::traits::Block as BlockT; -use smallvec::SmallVec; -use std::{borrow::Cow, collections::hash_map::Entry, cmp, error, marker::PhantomData, mem, pin::Pin}; -use std::time::{Duration, Instant}; -use tokio_io::{AsyncRead, AsyncWrite}; - -/// Network behaviour that handles opening substreams for custom protocols with other nodes. -/// -/// ## How it works -/// -/// The role of the `LegacyProto` is to synchronize the following components: -/// -/// - The libp2p swarm that opens new connections and reports disconnects. -/// - The connection handler (see `handler.rs`) that handles individual connections. -/// - The peerset manager (PSM) that requests links to nodes to be established or broken. -/// - The external API, that requires knowledge of the links that have been established. -/// -/// Each connection handler can be in four different states: Enabled+Open, Enabled+Closed, -/// Disabled+Open, or Disabled+Closed. The Enabled/Disabled component must be in sync with the -/// peerset manager. For example, if the peerset manager requires a disconnection, we disable the -/// existing handler. The Open/Closed component must be in sync with the external API. -/// -/// However a connection handler only exists if we are actually connected to a node. What this -/// means is that there are six possible states for each node: Disconnected, Dialing (trying to -/// reach it), Enabled+Open, Enabled+Closed, Disabled+open, Disabled+Closed. Most notably, the -/// Dialing state must correspond to a "link established" state in the peerset manager. In other -/// words, the peerset manager doesn't differentiate whether we are dialing a node or connected -/// to it. -/// -/// Additionally, there also exists a "banning" system. If we fail to dial a node, we "ban" it for -/// a few seconds. If the PSM requests a node that is in the "banned" state, then we delay the -/// actual dialing attempt until after the ban expires, but the PSM will still consider the link -/// to be established. -/// Note that this "banning" system is not an actual ban. If a "banned" node tries to connect to -/// us, we accept the connection. The "banning" system is only about delaying dialing attempts. -/// -pub struct LegacyProto { - /// List of protocols to open with peers. Never modified. - protocol: RegisteredProtocol, - - /// Receiver for instructions about who to connect to or disconnect from. - peerset: peerset::Peerset, - - /// List of peers in our state. - peers: FnvHashMap, - - /// List of incoming messages we have sent to the peer set manager and that are waiting for an - /// answer. - incoming: SmallVec<[IncomingPeer; 6]>, - - /// We generate indices to identify incoming connections. This is the next value for the index - /// to use when a connection is incoming. - next_incoming_index: peerset::IncomingIndex, - - /// Events to produce from `poll()`. - events: SmallVec<[NetworkBehaviourAction, LegacyProtoOut>; 4]>, - - /// Marker to pin the generics. - marker: PhantomData, -} - -/// State of a peer we're connected to. -#[derive(Debug)] -enum PeerState { - /// State is poisoned. This is a temporary state for a peer and we should always switch back - /// to it later. If it is found in the wild, that means there was either a panic or a bug in - /// the state machine code. - Poisoned, - - /// The peer misbehaved. If the PSM wants us to connect to this node, we will add an artificial - /// delay to the connection. - Banned { - /// Until when the node is banned. - until: Instant, - }, - - /// The peerset requested that we connect to this peer. We are not connected to this node. - PendingRequest { - /// When to actually start dialing. - timer: Compat, - /// When the `timer` will trigger. - timer_deadline: Instant, - }, - - /// The peerset requested that we connect to this peer. We are currently dialing this peer. - Requested, - - /// We are connected to this peer but the peerset refused it. This peer can still perform - /// Kademlia queries and such, but should get disconnected in a few seconds. - Disabled { - /// How we are connected to this peer. - connected_point: ConnectedPoint, - /// If true, we still have a custom protocol open with it. It will likely get closed in - /// a short amount of time, but we need to keep the information in order to not have a - /// state mismatch. - open: bool, - /// If `Some`, the node is banned until the given `Instant`. - banned_until: Option, - }, - - /// We are connected to this peer but we are not opening any Substrate substream. The handler - /// will be enabled when `timer` fires. This peer can still perform Kademlia queries and such, - /// but should get disconnected in a few seconds. - DisabledPendingEnable { - /// How we are connected to this peer. - connected_point: ConnectedPoint, - /// If true, we still have a custom protocol open with it. It will likely get closed in - /// a short amount of time, but we need to keep the information in order to not have a - /// state mismatch. - open: bool, - /// When to enable this remote. - timer: Compat, - /// When the `timer` will trigger. - timer_deadline: Instant, - }, - - /// We are connected to this peer and the peerset has accepted it. The handler is in the - /// enabled state. - Enabled { - /// How we are connected to this peer. - connected_point: ConnectedPoint, - /// If true, we have a custom protocol open with this peer. - open: bool, - }, - - /// We are connected to this peer, and we sent an incoming message to the peerset. The handler - /// is in initialization mode. We are waiting for the Accept or Reject from the peerset. There - /// is a corresponding entry in `incoming`. - Incoming { - /// How we are connected to this peer. - connected_point: ConnectedPoint, - }, -} - -impl PeerState { - /// True if we have an open channel with that node. - fn is_open(&self) -> bool { - match self { - PeerState::Poisoned => false, - PeerState::Banned { .. } => false, - PeerState::PendingRequest { .. } => false, - PeerState::Requested => false, - PeerState::Disabled { open, .. } => *open, - PeerState::DisabledPendingEnable { open, .. } => *open, - PeerState::Enabled { open, .. } => *open, - PeerState::Incoming { .. } => false, - } - } -} - -/// State of an "incoming" message sent to the peer set manager. -#[derive(Debug)] -struct IncomingPeer { - /// Id of the node that is concerned. - peer_id: PeerId, - /// If true, this "incoming" still corresponds to an actual connection. If false, then the - /// connection corresponding to it has been closed or replaced already. - alive: bool, - /// Id that the we sent to the peerset. - incoming_id: peerset::IncomingIndex, -} - -/// Event that can be emitted by the `LegacyProto`. -#[derive(Debug)] -pub enum LegacyProtoOut { - /// Opened a custom protocol with the remote. - CustomProtocolOpen { - /// 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, - /// Reason why the substream closed, for debugging purposes. - reason: Cow<'static, str>, - }, - - /// Receives a message on a custom protocol substream. - CustomMessage { - /// Id of the peer the message came from. - peer_id: PeerId, - /// Message that has been received. - message: Message, - }, - - /// 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, - /// Copy of the messages that are within the buffer, for further diagnostic. - messages: Vec>, - }, -} - -impl LegacyProto { - /// Creates a `CustomProtos`. - pub fn new( - protocol: impl Into, - versions: &[u8], - peerset: peerset::Peerset, - ) -> Self { - let protocol = RegisteredProtocol::new(protocol, versions); - - LegacyProto { - protocol, - peerset, - peers: FnvHashMap::default(), - incoming: SmallVec::new(), - next_incoming_index: peerset::IncomingIndex(0), - events: SmallVec::new(), - marker: PhantomData, - } - } - - /// Returns the list of all the peers we have an open channel to. - pub fn open_peers<'a>(&'a self) -> impl Iterator + 'a { - self.peers.iter().filter(|(_, state)| state.is_open()).map(|(id, _)| id) - } - - /// Returns true if we have a channel open with this node. - pub fn is_open(&self, peer_id: &PeerId) -> bool { - self.peers.get(peer_id).map(|p| p.is_open()).unwrap_or(false) - } - - /// Disconnects the given peer if we are connected to it. - pub fn disconnect_peer(&mut self, peer_id: &PeerId) { - debug!(target: "sub-libp2p", "External API => Disconnect {:?}", peer_id); - self.disconnect_peer_inner(peer_id, None); - } - - /// Inner implementation of `disconnect_peer`. If `ban` is `Some`, we ban the node for the - /// specific duration. - fn disconnect_peer_inner(&mut self, peer_id: &PeerId, ban: Option) { - let mut entry = if let Entry::Occupied(entry) = self.peers.entry(peer_id.clone()) { - entry - } else { - return - }; - - match mem::replace(entry.get_mut(), PeerState::Poisoned) { - // We're not connected anyway. - st @ PeerState::Disabled { .. } => *entry.into_mut() = st, - st @ PeerState::Requested => *entry.into_mut() = st, - st @ PeerState::PendingRequest { .. } => *entry.into_mut() = st, - st @ PeerState::Banned { .. } => *entry.into_mut() = st, - - // DisabledPendingEnable => Disabled. - PeerState::DisabledPendingEnable { open, connected_point, timer_deadline, .. } => { - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); - self.peerset.dropped(peer_id.clone()); - let banned_until = Some(if let Some(ban) = ban { - cmp::max(timer_deadline, Instant::now() + ban) - } else { - timer_deadline - }); - *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until } - }, - - // Enabled => Disabled. - PeerState::Enabled { open, connected_point } => { - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); - self.peerset.dropped(peer_id.clone()); - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtoHandlerIn::Disable, - }); - let banned_until = ban.map(|dur| Instant::now() + dur); - *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until } - }, - - // Incoming => Disabled. - PeerState::Incoming { connected_point, .. } => { - let inc = if let Some(inc) = self.incoming.iter_mut() - .find(|i| i.peer_id == *entry.key() && i.alive) { - inc - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in \ - incoming for incoming peer"); - return - }; - - inc.alive = false; - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtoHandlerIn::Disable, - }); - let banned_until = ban.map(|dur| Instant::now() + dur); - *entry.into_mut() = PeerState::Disabled { open: false, connected_point, banned_until } - }, - - PeerState::Poisoned => - error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), - } - } - - /// Returns true if we try to open protocols with the given peer. - pub fn is_enabled(&self, peer_id: &PeerId) -> bool { - match self.peers.get(peer_id) { - None => false, - Some(PeerState::Disabled { .. }) => false, - Some(PeerState::DisabledPendingEnable { .. }) => false, - Some(PeerState::Enabled { .. }) => true, - Some(PeerState::Incoming { .. }) => false, - Some(PeerState::Requested) => false, - Some(PeerState::PendingRequest { .. }) => false, - Some(PeerState::Banned { .. }) => false, - Some(PeerState::Poisoned) => false, - } - } - - /// Sends a message to a peer. - /// - /// 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, message: Message) - where B: BlockT { - if !self.is_open(target) { - return; - } - - trace!(target: "sub-libp2p", "External API => Packet for {:?}", target); - trace!(target: "sub-libp2p", "Handler({:?}) <= Packet", target); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: target.clone(), - event: CustomProtoHandlerIn::SendCustomMessage { - message, - } - }); - } - - /// Returns the state of the peerset manager, for debugging purposes. - pub fn peerset_debug_info(&mut self) -> serde_json::Value { - self.peerset.debug_info() - } - - /// Function that is called when the peerset wants us to connect to a node. - fn peerset_report_connect(&mut self, peer_id: PeerId) { - let mut occ_entry = match self.peers.entry(peer_id) { - Entry::Occupied(entry) => entry, - Entry::Vacant(entry) => { - // If there's no entry in `self.peers`, start dialing. - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Starting to connect", entry.key()); - debug!(target: "sub-libp2p", "Libp2p <= Dial {:?}", entry.key()); - self.events.push(NetworkBehaviourAction::DialPeer { peer_id: entry.key().clone() }); - entry.insert(PeerState::Requested); - return; - } - }; - - match mem::replace(occ_entry.get_mut(), PeerState::Poisoned) { - PeerState::Banned { ref until } if *until > Instant::now() => { - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Will start to connect at \ - until {:?}", occ_entry.key(), until); - *occ_entry.into_mut() = PeerState::PendingRequest { - timer: futures_timer::Delay::new_at(until.clone()).compat(), - timer_deadline: until.clone(), - }; - }, - - PeerState::Banned { .. } => { - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Starting to connect", occ_entry.key()); - debug!(target: "sub-libp2p", "Libp2p <= Dial {:?}", occ_entry.key()); - self.events.push(NetworkBehaviourAction::DialPeer { peer_id: occ_entry.key().clone() }); - *occ_entry.into_mut() = PeerState::Requested; - }, - - PeerState::Disabled { open, ref connected_point, banned_until: Some(ref banned) } - if *banned > Instant::now() => { - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Has idle connection through \ - {:?} but node is banned until {:?}", occ_entry.key(), connected_point, banned); - *occ_entry.into_mut() = PeerState::DisabledPendingEnable { - connected_point: connected_point.clone(), - open, - timer: futures_timer::Delay::new_at(banned.clone()).compat(), - timer_deadline: banned.clone(), - }; - }, - - PeerState::Disabled { open, connected_point, banned_until: _ } => { - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling previously-idle \ - connection through {:?}", occ_entry.key(), connected_point); - debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: occ_entry.key().clone(), - event: CustomProtoHandlerIn::Enable, - }); - *occ_entry.into_mut() = PeerState::Enabled { connected_point, open }; - }, - - PeerState::Incoming { connected_point, .. } => { - debug!(target: "sub-libp2p", "PSM => Connect({:?}): Enabling incoming \ - connection through {:?}", occ_entry.key(), connected_point); - if let Some(inc) = self.incoming.iter_mut() - .find(|i| i.peer_id == *occ_entry.key() && i.alive) { - inc.alive = false; - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in \ - incoming for incoming peer") - } - debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", occ_entry.key()); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: occ_entry.key().clone(), - event: CustomProtoHandlerIn::Enable, - }); - *occ_entry.into_mut() = PeerState::Enabled { connected_point, open: false }; - }, - - st @ PeerState::Enabled { .. } => { - warn!(target: "sub-libp2p", "PSM => Connect({:?}): Already connected to this \ - peer", occ_entry.key()); - *occ_entry.into_mut() = st; - }, - st @ PeerState::DisabledPendingEnable { .. } => { - warn!(target: "sub-libp2p", "PSM => Connect({:?}): Already have an idle \ - connection to this peer and waiting to enable it", occ_entry.key()); - *occ_entry.into_mut() = st; - }, - st @ PeerState::Requested { .. } | st @ PeerState::PendingRequest { .. } => { - warn!(target: "sub-libp2p", "PSM => Connect({:?}): Received a previous \ - request for that peer", occ_entry.key()); - *occ_entry.into_mut() = st; - }, - - PeerState::Poisoned => - error!(target: "sub-libp2p", "State of {:?} is poisoned", occ_entry.key()), - } - } - - /// Function that is called when the peerset wants us to disconnect from a node. - fn peerset_report_disconnect(&mut self, peer_id: PeerId) { - let mut entry = match self.peers.entry(peer_id) { - Entry::Occupied(entry) => entry, - Entry::Vacant(entry) => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Node already disabled", entry.key()); - return - } - }; - - match mem::replace(entry.get_mut(), PeerState::Poisoned) { - st @ PeerState::Disabled { .. } | st @ PeerState::Banned { .. } => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Node already disabled", entry.key()); - *entry.into_mut() = st; - }, - - PeerState::DisabledPendingEnable { open, connected_point, timer_deadline, .. } => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Interrupting pending \ - enable", entry.key()); - *entry.into_mut() = PeerState::Disabled { - open, - connected_point, - banned_until: Some(timer_deadline), - }; - }, - - PeerState::Enabled { open, connected_point } => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Disabling connection", entry.key()); - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", entry.key()); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: entry.key().clone(), - event: CustomProtoHandlerIn::Disable, - }); - *entry.into_mut() = PeerState::Disabled { open, connected_point, banned_until: None } - }, - st @ PeerState::Incoming { .. } => { - error!(target: "sub-libp2p", "PSM => Drop({:?}): Was in incoming mode", - entry.key()); - *entry.into_mut() = st; - }, - PeerState::Requested => { - // We don't cancel dialing. Libp2p doesn't expose that on purpose, as other - // sub-systems (such as the discovery mechanism) may require dialing this node as - // well at the same time. - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Was not yet connected", entry.key()); - entry.remove(); - }, - PeerState::PendingRequest { timer_deadline, .. } => { - debug!(target: "sub-libp2p", "PSM => Drop({:?}): Was not yet connected", entry.key()); - *entry.into_mut() = PeerState::Banned { until: timer_deadline } - }, - - PeerState::Poisoned => - error!(target: "sub-libp2p", "State of {:?} is poisoned", entry.key()), - } - } - - /// Function that is called when the peerset wants us to accept an incoming node. - fn peerset_report_accept(&mut self, index: peerset::IncomingIndex) { - let incoming = if let Some(pos) = self.incoming.iter().position(|i| i.incoming_id == index) { - self.incoming.remove(pos) - } else { - error!(target: "sub-libp2p", "PSM => Accept({:?}): Invalid index", index); - return - }; - - if !incoming.alive { - debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Obsolete incoming, - sending back dropped", index, incoming.peer_id); - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", incoming.peer_id); - self.peerset.dropped(incoming.peer_id.clone()); - return - } - - let state = if let Some(state) = self.peers.get_mut(&incoming.peer_id) { - state - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in peers \ - corresponding to an alive incoming"); - return - }; - - let connected_point = if let PeerState::Incoming { connected_point } = state { - connected_point.clone() - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: entry in peers corresponding \ - to an alive incoming is not in incoming state"); - return - }; - - debug!(target: "sub-libp2p", "PSM => Accept({:?}, {:?}): Enabling connection \ - through {:?}", index, incoming.peer_id, connected_point); - debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", incoming.peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: incoming.peer_id, - event: CustomProtoHandlerIn::Enable, - }); - - *state = PeerState::Enabled { open: false, connected_point }; - } - - /// Function that is called when the peerset wants us to reject an incoming node. - fn peerset_report_reject(&mut self, index: peerset::IncomingIndex) { - let incoming = if let Some(pos) = self.incoming.iter().position(|i| i.incoming_id == index) { - self.incoming.remove(pos) - } else { - error!(target: "sub-libp2p", "PSM => Reject({:?}): Invalid index", index); - return - }; - - if !incoming.alive { - error!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Obsolete incoming, \ - ignoring", index, incoming.peer_id); - return - } - - let state = if let Some(state) = self.peers.get_mut(&incoming.peer_id) { - state - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in peers \ - corresponding to an alive incoming"); - return - }; - - let connected_point = if let PeerState::Incoming { connected_point } = state { - connected_point.clone() - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: entry in peers corresponding \ - to an alive incoming is not in incoming state"); - return - }; - - debug!(target: "sub-libp2p", "PSM => Reject({:?}, {:?}): Rejecting connection through \ - {:?}", index, incoming.peer_id, connected_point); - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", incoming.peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: incoming.peer_id, - event: CustomProtoHandlerIn::Disable, - }); - *state = PeerState::Disabled { open: false, connected_point, banned_until: None }; - } -} - -impl DiscoveryNetBehaviour for LegacyProto { - fn add_discovered_nodes(&mut self, peer_ids: impl Iterator) { - self.peerset.discovered(peer_ids.into_iter().map(|peer_id| { - debug!(target: "sub-libp2p", "PSM <= Discovered({:?})", peer_id); - peer_id - })); - } -} - -impl NetworkBehaviour for LegacyProto -where - TSubstream: AsyncRead + AsyncWrite, - B: BlockT, -{ - type ProtocolsHandler = CustomProtoHandlerProto; - type OutEvent = LegacyProtoOut; - - fn new_handler(&mut self) -> Self::ProtocolsHandler { - CustomProtoHandlerProto::new(self.protocol.clone()) - } - - fn addresses_of_peer(&mut self, _: &PeerId) -> Vec { - Vec::new() - } - - fn inject_connected(&mut self, peer_id: PeerId, connected_point: ConnectedPoint) { - match (self.peers.entry(peer_id.clone()).or_insert(PeerState::Poisoned), connected_point) { - (st @ &mut PeerState::Requested, connected_point) | - (st @ &mut PeerState::PendingRequest { .. }, connected_point) => { - debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Connection \ - requested by PSM (through {:?})", peer_id, connected_point - ); - debug!(target: "sub-libp2p", "Handler({:?}) <= Enable", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtoHandlerIn::Enable, - }); - *st = PeerState::Enabled { open: false, connected_point }; - } - - // Note: it may seem weird that "Banned" nodes get treated as if there were absent. - // This is because the word "Banned" means "temporarily prevent outgoing connections to - // this node", and not "banned" in the sense that we would refuse the node altogether. - (st @ &mut PeerState::Poisoned, connected_point @ ConnectedPoint::Listener { .. }) | - (st @ &mut PeerState::Banned { .. }, connected_point @ ConnectedPoint::Listener { .. }) => { - let incoming_id = self.next_incoming_index.clone(); - self.next_incoming_index.0 = match self.next_incoming_index.0.checked_add(1) { - Some(v) => v, - None => { - error!(target: "sub-libp2p", "Overflow in next_incoming_index"); - return - } - }; - debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Incoming connection", - peer_id); - debug!(target: "sub-libp2p", "PSM <= Incoming({:?}, {:?}): Through {:?}", - incoming_id, peer_id, connected_point); - self.peerset.incoming(peer_id.clone(), incoming_id); - self.incoming.push(IncomingPeer { - peer_id: peer_id.clone(), - alive: true, - incoming_id, - }); - *st = PeerState::Incoming { connected_point }; - } - - (st @ &mut PeerState::Poisoned, connected_point) | - (st @ &mut PeerState::Banned { .. }, connected_point) => { - let banned_until = if let PeerState::Banned { until } = st { - Some(*until) - } else { - None - }; - debug!(target: "sub-libp2p", "Libp2p => Connected({:?}): Requested by something \ - else than PSM, disabling", peer_id); - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtoHandlerIn::Disable, - }); - *st = PeerState::Disabled { open: false, connected_point, banned_until }; - } - - st => { - // This is a serious bug either in this state machine or in libp2p. - error!(target: "sub-libp2p", "Received inject_connected for \ - already-connected node; state is {:?}", st - ); - } - } - } - - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { - match self.peers.remove(peer_id) { - None | Some(PeerState::Requested) | Some(PeerState::PendingRequest { .. }) | - Some(PeerState::Banned { .. }) => - // This is a serious bug either in this state machine or in libp2p. - error!(target: "sub-libp2p", "Received inject_disconnected for non-connected \ - node {:?}", peer_id), - - Some(PeerState::Disabled { open, banned_until, .. }) => { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \ - (through {:?})", peer_id, endpoint); - if let Some(until) = banned_until { - self.peers.insert(peer_id.clone(), PeerState::Banned { until }); - } - if open { - debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); - let event = LegacyProtoOut::CustomProtocolClosed { - peer_id: peer_id.clone(), - reason: "Disconnected by libp2p".into(), - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } - } - - Some(PeerState::DisabledPendingEnable { open, timer_deadline, .. }) => { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was disabled \ - (through {:?}) but pending enable", peer_id, endpoint); - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); - self.peerset.dropped(peer_id.clone()); - self.peers.insert(peer_id.clone(), PeerState::Banned { until: timer_deadline }); - if open { - debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); - let event = LegacyProtoOut::CustomProtocolClosed { - peer_id: peer_id.clone(), - reason: "Disconnected by libp2p".into(), - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } - } - - Some(PeerState::Enabled { open, .. }) => { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was enabled \ - (through {:?})", peer_id, endpoint); - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); - self.peerset.dropped(peer_id.clone()); - - let ban_dur = Uniform::new(5, 10).sample(&mut rand::thread_rng()); - self.peers.insert(peer_id.clone(), PeerState::Banned { - until: Instant::now() + Duration::from_secs(ban_dur) - }); - - if open { - debug!(target: "sub-libp2p", "External API <= Closed({:?})", peer_id); - let event = LegacyProtoOut::CustomProtocolClosed { - peer_id: peer_id.clone(), - reason: "Disconnected by libp2p".into(), - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } - } - - // In the incoming state, we don't report "Dropped". Instead we will just ignore the - // corresponding Accept/Reject. - Some(PeerState::Incoming { .. }) => { - if let Some(state) = self.incoming.iter_mut().find(|i| i.peer_id == *peer_id) { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}): Was in incoming \ - mode (id {:?}, through {:?})", peer_id, state.incoming_id, endpoint); - state.alive = false; - } else { - error!(target: "sub-libp2p", "State mismatch in libp2p: no entry in incoming \ - corresponding to an incoming state in peers") - } - } - - Some(PeerState::Poisoned) => - error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), - } - } - - fn inject_addr_reach_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn error::Error) { - trace!(target: "sub-libp2p", "Libp2p => Reach failure for {:?} through {:?}: {:?}", peer_id, addr, error); - } - - fn inject_dial_failure(&mut self, peer_id: &PeerId) { - if let Entry::Occupied(mut entry) = self.peers.entry(peer_id.clone()) { - match mem::replace(entry.get_mut(), PeerState::Poisoned) { - // The node is not in our list. - st @ PeerState::Banned { .. } => { - trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); - *entry.into_mut() = st; - }, - - // "Basic" situation: we failed to reach a node that the peerset requested. - PeerState::Requested | PeerState::PendingRequest { .. } => { - debug!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); - *entry.into_mut() = PeerState::Banned { - until: Instant::now() + Duration::from_secs(5) - }; - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", peer_id); - self.peerset.dropped(peer_id.clone()) - }, - - // We can still get dial failures even if we are already connected to the node, - // as an extra diagnostic for an earlier attempt. - st @ PeerState::Disabled { .. } | st @ PeerState::Enabled { .. } | - st @ PeerState::DisabledPendingEnable { .. } | st @ PeerState::Incoming { .. } => { - debug!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); - *entry.into_mut() = st; - }, - - PeerState::Poisoned => - error!(target: "sub-libp2p", "State of {:?} is poisoned", peer_id), - } - - } else { - // The node is not in our list. - trace!(target: "sub-libp2p", "Libp2p => Dial failure for {:?}", peer_id); - } - } - - fn inject_node_event( - &mut self, - source: PeerId, - event: CustomProtoHandlerOut, - ) { - match event { - CustomProtoHandlerOut::CustomProtocolClosed { reason } => { - debug!(target: "sub-libp2p", "Handler({:?}) => Closed: {}", source, reason); - - let mut entry = if let Entry::Occupied(entry) = self.peers.entry(source.clone()) { - entry - } else { - error!(target: "sub-libp2p", "State mismatch in the custom protos handler"); - return - }; - - debug!(target: "sub-libp2p", "External API <= Closed({:?})", source); - let event = LegacyProtoOut::CustomProtocolClosed { - reason, - peer_id: source.clone(), - }; - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - - match mem::replace(entry.get_mut(), PeerState::Poisoned) { - PeerState::Enabled { open, connected_point } => { - debug_assert!(open); - - debug!(target: "sub-libp2p", "PSM <= Dropped({:?})", source); - self.peerset.dropped(source.clone()); - - debug!(target: "sub-libp2p", "Handler({:?}) <= Disable", source); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: source.clone(), - event: CustomProtoHandlerIn::Disable, - }); - - *entry.into_mut() = PeerState::Disabled { - open: false, - connected_point, - banned_until: None - }; - }, - PeerState::Disabled { open, connected_point, banned_until } => { - debug_assert!(open); - *entry.into_mut() = PeerState::Disabled { open: false, connected_point, banned_until }; - }, - PeerState::DisabledPendingEnable { open, connected_point, timer, timer_deadline } => { - debug_assert!(open); - *entry.into_mut() = PeerState::DisabledPendingEnable { - open: false, - connected_point, - timer, - timer_deadline - }; - }, - _ => error!(target: "sub-libp2p", "State mismatch in the custom protos handler"), - } - } - - CustomProtoHandlerOut::CustomProtocolOpen { version } => { - debug!(target: "sub-libp2p", "Handler({:?}) => Open: version {:?}", source, version); - let endpoint = match self.peers.get_mut(&source) { - Some(PeerState::Enabled { ref mut open, ref connected_point }) | - Some(PeerState::DisabledPendingEnable { ref mut open, ref connected_point, .. }) | - Some(PeerState::Disabled { ref mut open, ref connected_point, .. }) if !*open => { - *open = true; - connected_point.clone() - } - _ => { - error!(target: "sub-libp2p", "State mismatch in the custom protos handler"); - return - } - }; - - debug!(target: "sub-libp2p", "External API <= Open({:?})", source); - let event = LegacyProtoOut::CustomProtocolOpen { - version, - peer_id: source, - endpoint, - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } - - CustomProtoHandlerOut::CustomMessage { message } => { - debug_assert!(self.is_open(&source)); - trace!(target: "sub-libp2p", "Handler({:?}) => Message", source); - trace!(target: "sub-libp2p", "External API <= Message({:?})", source); - let event = LegacyProtoOut::CustomMessage { - peer_id: source, - message, - }; - - self.events.push(NetworkBehaviourAction::GenerateEvent(event)); - } - - CustomProtoHandlerOut::Clogged { messages } => { - debug_assert!(self.is_open(&source)); - trace!(target: "sub-libp2p", "Handler({:?}) => Clogged", source); - trace!(target: "sub-libp2p", "External API <= Clogged({:?})", source); - warn!(target: "sub-libp2p", "Queue of packets to send to {:?} is \ - pretty large", source); - self.events.push(NetworkBehaviourAction::GenerateEvent(LegacyProtoOut::Clogged { - peer_id: source, - messages, - })); - } - - // Don't do anything for non-severe errors except report them. - CustomProtoHandlerOut::ProtocolError { is_severe, ref error } if !is_severe => { - debug!(target: "sub-libp2p", "Handler({:?}) => Benign protocol error: {:?}", - source, error) - } - - CustomProtoHandlerOut::ProtocolError { error, .. } => { - debug!(target: "sub-libp2p", "Handler({:?}) => Severe protocol error: {:?}", - source, error); - // A severe protocol error happens when we detect a "bad" node, such as a node on - // a different chain, or a node that doesn't speak the same protocol(s). We - // decrease the node's reputation, hence lowering the chances we try this node - // again in the short term. - self.peerset.report_peer(source.clone(), i32::min_value()); - self.disconnect_peer_inner(&source, Some(Duration::from_secs(5))); - } - } - } - - fn poll( - &mut self, - _params: &mut impl PollParameters, - ) -> Async< - NetworkBehaviourAction< - CustomProtoHandlerIn, - Self::OutEvent, - >, - > { - // Poll for instructions from the peerset. - // Note that the peerset is a *best effort* crate, and we have to use defensive programming. - loop { - let mut peerset01 = futures03::stream::poll_fn(|cx| - futures03::Stream::poll_next(Pin::new(&mut self.peerset), cx) - ).map(|v| Ok::<_, ()>(v)).compat(); - match peerset01.poll() { - Ok(Async::Ready(Some(peerset::Message::Accept(index)))) => { - self.peerset_report_accept(index); - } - Ok(Async::Ready(Some(peerset::Message::Reject(index)))) => { - self.peerset_report_reject(index); - } - Ok(Async::Ready(Some(peerset::Message::Connect(id)))) => { - self.peerset_report_connect(id); - } - Ok(Async::Ready(Some(peerset::Message::Drop(id)))) => { - self.peerset_report_disconnect(id); - } - Ok(Async::Ready(None)) => { - error!(target: "sub-libp2p", "Peerset receiver stream has returned None"); - break; - } - Ok(Async::NotReady) => break, - Err(err) => { - error!(target: "sub-libp2p", "Peerset receiver stream has errored: {:?}", err); - break - } - } - } - - for (peer_id, peer_state) in self.peers.iter_mut() { - match mem::replace(peer_state, PeerState::Poisoned) { - PeerState::PendingRequest { mut timer, timer_deadline } => { - if let Ok(Async::NotReady) = timer.poll() { - *peer_state = PeerState::PendingRequest { timer, timer_deadline }; - continue; - } - - debug!(target: "sub-libp2p", "Libp2p <= Dial {:?} now that ban has expired", peer_id); - self.events.push(NetworkBehaviourAction::DialPeer { peer_id: peer_id.clone() }); - *peer_state = PeerState::Requested; - } - - PeerState::DisabledPendingEnable { mut timer, connected_point, open, timer_deadline } => { - if let Ok(Async::NotReady) = timer.poll() { - *peer_state = PeerState::DisabledPendingEnable { - timer, - connected_point, - open, - timer_deadline - }; - continue; - } - - debug!(target: "sub-libp2p", "Handler({:?}) <= Enable now that ban has expired", peer_id); - self.events.push(NetworkBehaviourAction::SendEvent { - peer_id: peer_id.clone(), - event: CustomProtoHandlerIn::Enable, - }); - *peer_state = PeerState::Enabled { connected_point, open }; - } - - st @ _ => *peer_state = st, - } - } - - if !self.events.is_empty() { - return Async::Ready(self.events.remove(0)) - } - - Async::NotReady - } -} diff --git a/core/network/src/legacy_proto/mod.rs b/core/network/src/legacy_proto/mod.rs deleted file mode 100644 index bbe795528be9d..0000000000000 --- a/core/network/src/legacy_proto/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -pub use self::behaviour::{LegacyProto, LegacyProtoOut}; - -mod behaviour; -mod handler; -mod upgrade; -mod tests; diff --git a/core/network/src/legacy_proto/tests.rs b/core/network/src/legacy_proto/tests.rs deleted file mode 100644 index 8fd47843df2e5..0000000000000 --- a/core/network/src/legacy_proto/tests.rs +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![cfg(test)] - -use futures::{future, prelude::*, try_ready}; -use libp2p::core::nodes::Substream; -use libp2p::core::{ConnectedPoint, transport::boxed::Boxed, muxing::StreamMuxerBox}; -use libp2p::swarm::{Swarm, ProtocolsHandler, IntoProtocolsHandler}; -use libp2p::swarm::{PollParameters, NetworkBehaviour, NetworkBehaviourAction}; -use libp2p::{PeerId, Multiaddr, Transport}; -use rand::seq::SliceRandom; -use std::{io, time::Duration, time::Instant}; -use test_client::runtime::Block; -use crate::message::generic::Message; -use crate::legacy_proto::{LegacyProto, LegacyProtoOut}; - -/// Builds two nodes that have each other as bootstrap nodes. -/// This is to be used only for testing, and a panic will happen if something goes wrong. -fn build_nodes() --> ( - Swarm, CustomProtoWithAddr>, - Swarm, CustomProtoWithAddr> -) { - let mut out = Vec::with_capacity(2); - - let keypairs: Vec<_> = (0..2).map(|_| libp2p::identity::Keypair::generate_ed25519()).collect(); - let addrs: Vec = (0..2) - .map(|_| format!("/memory/{}", rand::random::()).parse().unwrap()) - .collect(); - - for index in 0 .. 2 { - let transport = libp2p::core::transport::MemoryTransport - .with_upgrade(libp2p::secio::SecioConfig::new(keypairs[index].clone())) - .and_then(move |out, endpoint| { - let peer_id = out.remote_key.into_peer_id(); - libp2p::core::upgrade::apply(out.stream, libp2p::yamux::Config::default(), endpoint) - .map(|muxer| (peer_id, libp2p::core::muxing::StreamMuxerBox::new(muxer))) - }) - .with_timeout(Duration::from_secs(20)) - .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) - .boxed(); - - let (peerset, _) = peerset::Peerset::from_config(peerset::PeersetConfig { - in_peers: 25, - out_peers: 25, - bootnodes: if index == 0 { - keypairs - .iter() - .skip(1) - .map(|keypair| keypair.public().into_peer_id()) - .collect() - } else { - vec![] - }, - reserved_only: false, - reserved_nodes: Vec::new(), - }); - - let behaviour = CustomProtoWithAddr { - inner: LegacyProto::new(&b"test"[..], &[1], peerset), - addrs: addrs - .iter() - .enumerate() - .filter_map(|(n, a)| if n != index { - Some((keypairs[n].public().into_peer_id(), a.clone())) - } else { - None - }) - .collect(), - }; - - let mut swarm = Swarm::new( - transport, - behaviour, - keypairs[index].public().into_peer_id() - ); - Swarm::listen_on(&mut swarm, addrs[index].clone()).unwrap(); - out.push(swarm); - } - - // Final output - let mut out_iter = out.into_iter(); - let first = out_iter.next().unwrap(); - let second = out_iter.next().unwrap(); - (first, second) -} - -/// Wraps around the `CustomBehaviour` network behaviour, and adds hardcoded node addresses to it. -struct CustomProtoWithAddr { - inner: LegacyProto>, - addrs: Vec<(PeerId, Multiaddr)>, -} - -impl std::ops::Deref for CustomProtoWithAddr { - type Target = LegacyProto>; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl std::ops::DerefMut for CustomProtoWithAddr { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} - -impl NetworkBehaviour for CustomProtoWithAddr { - type ProtocolsHandler = - > as NetworkBehaviour>::ProtocolsHandler; - type OutEvent = > as NetworkBehaviour>::OutEvent; - - fn new_handler(&mut self) -> Self::ProtocolsHandler { - self.inner.new_handler() - } - - fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { - let mut list = self.inner.addresses_of_peer(peer_id); - for (p, a) in self.addrs.iter() { - if p == peer_id { - list.push(a.clone()); - } - } - list - } - - fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { - self.inner.inject_connected(peer_id, endpoint) - } - - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { - self.inner.inject_disconnected(peer_id, endpoint) - } - - fn inject_node_event( - &mut self, - peer_id: PeerId, - event: <::Handler as ProtocolsHandler>::OutEvent - ) { - self.inner.inject_node_event(peer_id, event) - } - - fn poll( - &mut self, - params: &mut impl PollParameters - ) -> Async< - NetworkBehaviourAction< - <::Handler as ProtocolsHandler>::InEvent, - Self::OutEvent - > - > { - self.inner.poll(params) - } - - fn inject_replaced(&mut self, peer_id: PeerId, closed_endpoint: ConnectedPoint, new_endpoint: ConnectedPoint) { - self.inner.inject_replaced(peer_id, closed_endpoint, new_endpoint) - } - - fn inject_addr_reach_failure(&mut self, peer_id: Option<&PeerId>, addr: &Multiaddr, error: &dyn std::error::Error) { - self.inner.inject_addr_reach_failure(peer_id, addr, error) - } - - fn inject_dial_failure(&mut self, peer_id: &PeerId) { - self.inner.inject_dial_failure(peer_id) - } - - fn inject_new_listen_addr(&mut self, addr: &Multiaddr) { - self.inner.inject_new_listen_addr(addr) - } - - fn inject_expired_listen_addr(&mut self, addr: &Multiaddr) { - self.inner.inject_expired_listen_addr(addr) - } - - fn inject_new_external_addr(&mut self, addr: &Multiaddr) { - self.inner.inject_new_external_addr(addr) - } -} - -#[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) = build_nodes(); - - let fut1 = future::poll_fn(move || -> io::Result<_> { - loop { - match try_ready!(service1.poll()) { - Some(LegacyProtoOut::CustomProtocolOpen { peer_id, .. }) => { - for n in 0 .. NUM_PACKETS { - service1.send_packet( - &peer_id, - Message::ChainSpecific(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(LegacyProtoOut::CustomProtocolOpen { .. }) => {}, - Some(LegacyProtoOut::CustomMessage { message: Message::ChainSpecific(message), .. }) => { - assert_eq!(message.len(), 1); - packet_counter += 1; - if packet_counter == NUM_PACKETS { - return Ok(Async::Ready(())) - } - } - _ => panic!(), - } - } - }); - - let combined = fut1.select(fut2).map_err(|(err, _)| err); - let _ = tokio::runtime::Runtime::new().unwrap().block_on(combined).unwrap(); -} - -#[test] -fn basic_two_nodes_requests_in_parallel() { - let (mut service1, mut service2) = build_nodes(); - - // Generate random messages with or without a request id. - let mut to_send = { - let mut to_send = Vec::new(); - for _ in 0..200 { // Note: don't make that number too high or the CPU usage will explode. - let msg = (0..10).map(|_| rand::random::()).collect::>(); - to_send.push(Message::ChainSpecific(msg)); - } - to_send - }; - - // 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(LegacyProtoOut::CustomProtocolOpen { peer_id, .. }) => { - for msg in to_send.drain(..) { - service1.send_packet(&peer_id, msg); - } - }, - _ => panic!(), - } - } - }); - - let fut2 = future::poll_fn(move || -> io::Result<_> { - loop { - match try_ready!(service2.poll()) { - Some(LegacyProtoOut::CustomProtocolOpen { .. }) => {}, - Some(LegacyProtoOut::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); - let _ = tokio::runtime::Runtime::new().unwrap().block_on_all(combined).unwrap(); -} - -#[test] -fn reconnect_after_disconnect() { - // We connect two nodes together, then force a disconnect (through the API of the `Service`), - // check that the disconnect worked, and finally check whether they successfully reconnect. - - let (mut service1, mut service2) = build_nodes(); - - // We use the `current_thread` runtime because it doesn't require us to have `'static` futures. - let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap(); - - // For this test, the services can be in the following states. - #[derive(Debug, Copy, Clone, PartialEq, Eq)] - enum ServiceState { NotConnected, FirstConnec, Disconnected, ConnectedAgain } - let mut service1_state = ServiceState::NotConnected; - let mut service2_state = ServiceState::NotConnected; - - // Run the events loops. - runtime.block_on(future::poll_fn(|| -> Result<_, io::Error> { - loop { - let mut service1_not_ready = false; - - match service1.poll().unwrap() { - Async::Ready(Some(LegacyProtoOut::CustomProtocolOpen { .. })) => { - match service1_state { - ServiceState::NotConnected => { - service1_state = ServiceState::FirstConnec; - if service2_state == ServiceState::FirstConnec { - service1.disconnect_peer(Swarm::local_peer_id(&service2)); - } - }, - ServiceState::Disconnected => service1_state = ServiceState::ConnectedAgain, - ServiceState::FirstConnec | ServiceState::ConnectedAgain => panic!(), - } - }, - Async::Ready(Some(LegacyProtoOut::CustomProtocolClosed { .. })) => { - match service1_state { - ServiceState::FirstConnec => service1_state = ServiceState::Disconnected, - ServiceState::ConnectedAgain| ServiceState::NotConnected | - ServiceState::Disconnected => panic!(), - } - }, - Async::NotReady => service1_not_ready = true, - _ => panic!() - } - - match service2.poll().unwrap() { - Async::Ready(Some(LegacyProtoOut::CustomProtocolOpen { .. })) => { - match service2_state { - ServiceState::NotConnected => { - service2_state = ServiceState::FirstConnec; - if service1_state == ServiceState::FirstConnec { - service1.disconnect_peer(Swarm::local_peer_id(&service2)); - } - }, - ServiceState::Disconnected => service2_state = ServiceState::ConnectedAgain, - ServiceState::FirstConnec | ServiceState::ConnectedAgain => panic!(), - } - }, - Async::Ready(Some(LegacyProtoOut::CustomProtocolClosed { .. })) => { - match service2_state { - ServiceState::FirstConnec => service2_state = ServiceState::Disconnected, - ServiceState::ConnectedAgain| ServiceState::NotConnected | - ServiceState::Disconnected => panic!(), - } - }, - Async::NotReady if service1_not_ready => break, - Async::NotReady => {} - _ => panic!() - } - } - - if service1_state == ServiceState::ConnectedAgain && service2_state == ServiceState::ConnectedAgain { - Ok(Async::Ready(())) - } else { - Ok(Async::NotReady) - } - })).unwrap(); - - // Do a second 3-seconds run to make sure we don't get disconnected immediately again. - let mut delay = tokio::timer::Delay::new(Instant::now() + Duration::from_secs(3)); - runtime.block_on(future::poll_fn(|| -> Result<_, io::Error> { - match service1.poll().unwrap() { - Async::NotReady => {}, - _ => panic!() - } - - match service2.poll().unwrap() { - Async::NotReady => {}, - _ => panic!() - } - - if let Async::Ready(()) = delay.poll().unwrap() { - Ok(Async::Ready(())) - } else { - Ok(Async::NotReady) - } - })).unwrap(); -} diff --git a/core/network/src/legacy_proto/upgrade.rs b/core/network/src/legacy_proto/upgrade.rs deleted file mode 100644 index 8831d16f91636..0000000000000 --- a/core/network/src/legacy_proto/upgrade.rs +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::config::ProtocolId; -use crate::protocol::message::Message; -use bytes::Bytes; -use libp2p::core::{Negotiated, Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName}; -use libp2p::tokio_codec::Framed; -use log::debug; -use std::{collections::VecDeque, io, marker::PhantomData, vec::IntoIter as VecIntoIter}; -use futures::{prelude::*, future, stream}; -use codec::{Decode, Encode}; -use sr_primitives::traits::Block as BlockT; -use tokio_io::{AsyncRead, AsyncWrite}; -use unsigned_varint::codec::UviBytes; - -/// 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: impl Into, versions: &[u8]) - -> Self { - let protocol = protocol.into(); - let mut base_name = Bytes::from_static(b"/substrate/"); - base_name.extend_from_slice(protocol.as_bytes()); - 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, - } - } -} - -impl Clone for RegisteredProtocol { - fn clone(&self) -> Self { - RegisteredProtocol { - id: self.id.clone(), - base_name: self.base_name.clone(), - supported_versions: self.supported_versions.clone(), - marker: PhantomData, - } - } -} - -/// Output of a `RegisteredProtocol` upgrade. -pub struct RegisteredProtocolSubstream { - /// 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, UviBytes>>>, - /// 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, - /// Marker to pin the generic. - marker: PhantomData, -} - -impl RegisteredProtocolSubstream { - /// Returns the version of the protocol that was negotiated. - 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 - } - - /// 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: Message) - where B: BlockT { - if self.is_closing { - return - } - - self.send_queue.push_back(data.encode()); - } -} - -/// Event produced by the `RegisteredProtocolSubstream`. -#[derive(Debug, Clone)] -pub enum RegisteredProtocolEvent { - /// Received a message from the remote. - Message(Message), - - /// 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, B: BlockT { - 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| Decode::decode(&mut &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 = as Decode>::decode(&mut &data[..]) - .map_err(|err| { - debug!( - target: "sub-libp2p", - "Couldn't decode packet sent by the remote: {:?}: {}", data, err.what(), - ); - io::ErrorKind::InvalidData - })?; - Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) - } - 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().map(|&version| { - let num = version.to_string(); - - let mut name = self.base_name.clone(); - name.extend_from_slice(num.as_bytes()); - RegisteredProtocolName { - name, - version, - } - }).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, -} - -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: Negotiated, - 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_version: info.version, - clogged_fuse: false, - marker: PhantomData, - }) - } -} - -impl OutboundUpgrade for RegisteredProtocol -where TSubstream: AsyncRead + AsyncWrite, -{ - type Output = >::Output; - type Future = >::Future; - type Error = >::Error; - - fn upgrade_outbound( - self, - socket: Negotiated, - 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_version: info.version, - clogged_fuse: false, - marker: PhantomData, - }) - } -} diff --git a/core/network/src/lib.rs b/core/network/src/lib.rs deleted file mode 100644 index d0977d90c9005..0000000000000 --- a/core/network/src/lib.rs +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![warn(unused_extern_crates)] -#![warn(missing_docs)] - -//! Substrate-specific P2P networking. -//! -//! **Important**: This crate is unstable and the API and usage may change. -//! -//! # Node identities and addresses -//! -//! In a decentralized network, each node possesses a network private key and a network public key. -//! In Substrate, the keys are based on the ed25519 curve. -//! -//! From a node's public key, we can derive its *identity*. In Substrate and libp2p, a node's -//! identity is represented with the [`PeerId`] struct. All network communications between nodes on -//! the network use encryption derived from both sides's keys, which means that **identities cannot -//! be faked**. -//! -//! A node's identity uniquely identifies a machine on the network. If you start two or more -//! clients using the same network key, large interferences will happen. -//! -//! # Substrate's network protocol -//! -//! Substrate's networking protocol is based upon libp2p. It is at the moment not possible and not -//! planned to permit using something else than the libp2p network stack and the rust-libp2p -//! library. However the libp2p framework is very flexible and the rust-libp2p library could be -//! extended to support a wider range of protocols than what is offered by libp2p. -//! -//! ## Discovery mechanisms -//! -//! In order for our node to join a peer-to-peer network, it has to know a list of nodes that are -//! part of said network. This includes nodes identities and their address (how to reach them). -//! Building such a list is called the **discovery** mechanism. There are three mechanisms that -//! Substrate uses: -//! -//! - Bootstrap nodes. These are hard-coded node identities and addresses passed alongside with -//! the network configuration. -//! - mDNS. We perform a UDP broadcast on the local network. Nodes that listen may respond with -//! their identity. More info [here](https://github.com/libp2p/specs/blob/master/discovery/mdns.md). -//! mDNS can be disabled in the network configuration. -//! - Kademlia random walk. Once connected, we perform random Kademlia `FIND_NODE` requests in -//! order for nodes to propagate to us their view of the network. More information about Kademlia -//! can be found [on Wikipedia](https://en.wikipedia.org/wiki/Kademlia). -//! -//! ## Connection establishment -//! -//! When node Alice knows node Bob's identity and address, it can establish a connection with Bob. -//! All connections must always use encryption and multiplexing. While some node addresses (eg. -//! addresses using `/quic`) already imply which encryption and/or multiplexing to use, for others -//! the **multistream-select** protocol is used in order to negotiate an encryption layer and/or a -//! multiplexing layer. -//! -//! The connection establishment mechanism is called the **transport**. -//! -//! As of the writing of this documentation, the following base-layer protocols are supported by -//! Substrate: -//! -//! - TCP/IP for addresses of the form `/ip4/1.2.3.4/tcp/5`. Once the TCP connection is open, an -//! encryption and a multiplexing layer are negotiated on top. -//! - WebSockets for addresses of the form `/ip4/1.2.3.4/tcp/5/ws`. A TCP/IP connection is open and -//! the WebSockets protocol is negotiated on top. Communications then happen inside WebSockets data -//! frames. Encryption and multiplexing are additionally negotiated again inside this channel. -//! - DNS for addresses of the form `/dns4/example.com/tcp/5` or `/dns4/example.com/tcp/5/ws`. A -//! node's address can contain a domain name. -//! -//! The following encryption protocols are supported: -//! -//! - [Secio](https://github.com/libp2p/specs/tree/master/secio). A TLS-1.2-like protocol but -//! without certificates. Support for secio will likely be deprecated in the far future. -//! - [Noise](https://noiseprotocol.org/). Support for noise is very experimental. The details are -//! very blurry and may change at any moment. -//! -//! The following multiplexing protocols are supported: -//! -//! - [Mplex](https://github.com/libp2p/specs/tree/master/mplex). Support for mplex will likely -//! be deprecated in the future. -//! - [Yamux](https://github.com/hashicorp/yamux/blob/master/spec.md). -//! -//! ## Substreams -//! -//! Once a connection has been established and uses multiplexing, substreams can be opened. When -//! a substream is open, the **multistream-select** protocol is used to negotiate which protocol to -//! use on that given substream. In practice, Substrate opens the following substreams: -//! -//! - We periodically open an ephemeral substream in order to ping the remote and check whether the -//! connection is still alive. Failure for the remote to reply leads to a disconnection. This uses -//! the libp2p ping protocol. -//! - We periodically open an ephemeral substream in order to ask information from the remote. This -//! is called [the `identify` protocol](https://github.com/libp2p/specs/tree/master/identify). -//! - We periodically open ephemeral substreams for Kademlia random walk queries. Each Kademlia -//! query is done in a new separate substream. This uses the -//! [standard libp2p Kademlia protocol](https://github.com/libp2p/specs/pull/108). -//! - We optionally keep a substream alive for all Substrate-based communications. The name of the -//! protocol negotiated is based on the *protocol ID* passed as part of the network configuration. -//! This protocol ID should be unique for each chain and prevents nodes from different chains from -//! connecting to each other. More information below. -//! -//! ## The Substrate substream -//! -//! Substrate uses a component named the **peerset manager (PSM)**. Through the discovery -//! mechanism, the PSM is aware of the nodes that are part of the network and decides which nodes -//! we should perform Substrate-based communications with. For these nodes, we open a connection -//! if necessary and open a unique substream for Substrate-based communications. If the PSM decides -//! that we should disconnect a node, then that substream is closed. -//! -//! For more information about the PSM, see the *substrate-peerset* crate. -//! -//! Note that at the moment there is no mechanism in place to solve the issues that arise where the -//! two sides of a connection open the unique substream simultaneously. In order to not run into -//! issues, only the dialer of a connection is allowed to open the unique substream. When the -//! substream is closed, the entire connection is closed as well. This is a bug, and should be -//! fixed by improving the protocol. -//! -//! Within the unique Substrate substream, messages encoded using -//! [*parity-scale-codec*](https://github.com/paritytech/parity-scale-codec) are exchanged. -//! The detail of theses messages is not totally in place, but they can be found in the -//! `message.rs` file. -//! -//! Once the substream is open, the first step is an exchange of a *status* message from both -//! sides, containing information such as the chain root hash, head of chain, and so on. -//! -//! Communications within this substream include: -//! -//! - Syncing. Blocks are announced and requested from other nodes. -//! - Light-client requests. When a light client requires information, a random node we have a -//! substream open with is chosen, and the information is requested from it. -//! - Gossiping. Used for example by grandpa. -//! - Network specialization. The network protocol can be specialized through a template parameter -//! of the network service. This specialization is free to send and receive messages with the -//! remote. This is meant to be used by the chain that is being built on top of Substrate -//! (eg. Polkadot). -//! -//! It is intended that in the future each of these components gets more isolated, so that they -//! are free to open and close their own substreams, and so that syncing and light client requests -//! are able to communicate with nodes outside of the range of the PSM. -//! -//! # Usage -//! -//! Using the `substrate-network` crate is done through the [`NetworkWorker`] struct. Create this -//! struct by passing a [`config::Params`], then poll it as if it was a `Future`. You can extract an -//! `Arc` from the `NetworkWorker`, which can be shared amongst multiple places -//! in order to give orders to the networking. -//! -//! See the [`config`] module for more information about how to configure the networking. -//! -//! After the `NetworkWorker` has been created, the important things to do are: -//! -//! - Calling `NetworkWorker::poll` in order to advance the network. -//! - Calling `on_block_import` whenever a block is added to the client. -//! - Calling `on_block_finalized` whenever a block is finalized. -//! - Calling `trigger_repropagate` when a transaction is added to the pool. -//! -//! More precise usage details are still being worked on and will likely change in the future. -//! - -mod behaviour; -mod chain; -mod legacy_proto; -mod debug_info; -mod discovery; -mod on_demand_layer; -mod protocol; -mod service; -mod transport; - -pub mod config; -pub mod error; - -#[cfg(any(test, feature = "test-helpers"))] -pub mod test; - -pub use chain::{Client as ClientHandle, FinalityProofProvider}; -pub use service::{ - NetworkService, NetworkWorker, TransactionPool, ExHashT, ReportHandle, - NetworkStateInfo, -}; -pub use protocol::{PeerInfo, Context, consensus_gossip, message, specialization}; -pub use protocol::event::{Event, DhtEvent}; -pub use protocol::sync::SyncState; -pub use libp2p::{Multiaddr, PeerId}; -#[doc(inline)] -pub use libp2p::multiaddr; - -pub use message::{generic as generic_message, RequestId, Status as StatusMessage}; -pub use on_demand_layer::{OnDemand, RemoteResponse}; - -// Used by the `construct_simple_protocol!` macro. -#[doc(hidden)] -pub use sr_primitives::traits::Block as BlockT; - -use libp2p::core::ConnectedPoint; -use serde::{Deserialize, Serialize}; -use slog_derive::SerdeValue; -use std::{collections::{HashMap, HashSet}, time::Duration}; - -/// Extension trait for `NetworkBehaviour` that also accepts discovering nodes. -pub trait DiscoveryNetBehaviour { - /// Notify the protocol that we have learned about the existence of nodes. - /// - /// Can (or most likely will) be called multiple times with the same `PeerId`s. - /// - /// Also note that there is no notification for expired nodes. The implementer must add a TTL - /// system, or remove nodes that will fail to reach. - fn add_discovered_nodes(&mut self, nodes: impl Iterator); -} - -/// Returns general information about the networking. -/// -/// Meant for general diagnostic purposes. -/// -/// **Warning**: This API is not stable. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SerdeValue)] -#[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, - /// List of addresses the node knows it can be reached as. - pub external_addresses: HashSet, - /// 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, - /// State of the peerset manager. - pub peerset: serde_json::Value, -} - -/// Part of the `NetworkState` struct. Unstable. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[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, - /// If true, the peer is "open", which means that we have a Substrate-related protocol - /// with this peer. - pub open: bool, - /// List of addresses known for this node. - pub known_addresses: HashSet, -} - -/// Part of the `NetworkState` struct. Unstable. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct NetworkStateNotConnectedPeer { - /// List of addresses known for this node. - pub known_addresses: HashSet, - /// Node information, as provided by the node itself, if we were ever connected to this node. - pub version_string: Option, - /// Latest ping duration with this node, if we were ever connected to this node. - pub latest_ping_time: Option, -} - -/// Part of the `NetworkState` struct. Unstable. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub enum NetworkStatePeerEndpoint { - /// We are dialing the given address. - Dialing(Multiaddr), - /// We are listening. - Listening { - /// Local address of the connection. - local_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 { local_addr, send_back_addr } => - NetworkStatePeerEndpoint::Listening { - local_addr, - send_back_addr - } - } - } -} diff --git a/core/network/src/on_demand_layer.rs b/core/network/src/on_demand_layer.rs deleted file mode 100644 index cdcb99a25f99e..0000000000000 --- a/core/network/src/on_demand_layer.rs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! On-demand requests service. - -use crate::protocol::light_dispatch::RequestData; -use std::collections::HashMap; -use std::sync::Arc; -use futures::{prelude::*, sync::mpsc, sync::oneshot}; -use futures03::compat::{Compat01As03, Future01CompatExt as _}; -use parking_lot::Mutex; -use client::error::Error as ClientError; -use client::light::fetcher::{Fetcher, FetchChecker, RemoteHeaderRequest, - RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, - RemoteReadChildRequest, RemoteBodyRequest}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; - -/// Implements the `Fetcher` trait of the client. Makes it possible for the light client to perform -/// network requests for some state. -/// -/// This implementation stores all the requests in a queue. The network, in parallel, is then -/// responsible for pulling elements out of that queue and fulfilling them. -pub struct OnDemand { - /// Objects that checks whether what has been retrieved is correct. - checker: Arc>, - - /// Queue of requests. Set to `Some` at initialization, then extracted by the network. - /// - /// Note that a better alternative would be to use a MPMC queue here, and add a `poll` method - /// from the `OnDemand`. However there exists no popular implementation of MPMC channels in - /// asynchronous Rust at the moment - requests_queue: Mutex>>>, - - /// Sending side of `requests_queue`. - requests_send: mpsc::UnboundedSender>, -} - -impl OnDemand where - B::Header: HeaderT, -{ - /// Creates new on-demand service. - pub fn new(checker: Arc>) -> Self { - let (requests_send, requests_queue) = mpsc::unbounded(); - let requests_queue = Mutex::new(Some(requests_queue)); - - OnDemand { - checker, - requests_queue, - requests_send, - } - } - - /// Get checker reference. - pub fn checker(&self) -> &Arc> { - &self.checker - } - - /// Extracts the queue of requests. - /// - /// Whenever one of the methods of the `Fetcher` trait is called, an element is pushed on this - /// channel. - /// - /// If this function returns `None`, that means that the receiver has already been extracted in - /// the past, and therefore that something already handles the requests. - pub(crate) fn extract_receiver(&self) -> Option>> { - self.requests_queue.lock().take() - } -} - -impl Fetcher for OnDemand where - B: BlockT, - B::Header: HeaderT, -{ - type RemoteHeaderResult = Compat01As03>; - type RemoteReadResult = Compat01As03, Option>>>>; - type RemoteCallResult = Compat01As03>>; - type RemoteChangesResult = Compat01As03, u32)>>>; - type RemoteBodyResult = Compat01As03>>; - - fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult { - let (sender, receiver) = oneshot::channel(); - let _ = self.requests_send.unbounded_send(RequestData::RemoteHeader(request, sender)); - RemoteResponse { receiver }.compat() - } - - fn remote_read(&self, request: RemoteReadRequest) -> Self::RemoteReadResult { - let (sender, receiver) = oneshot::channel(); - let _ = self.requests_send.unbounded_send(RequestData::RemoteRead(request, sender)); - RemoteResponse { receiver }.compat() - } - - fn remote_read_child( - &self, - request: RemoteReadChildRequest - ) -> Self::RemoteReadResult { - let (sender, receiver) = oneshot::channel(); - let _ = self.requests_send.unbounded_send(RequestData::RemoteReadChild(request, sender)); - RemoteResponse { receiver }.compat() - } - - fn remote_call(&self, request: RemoteCallRequest) -> Self::RemoteCallResult { - let (sender, receiver) = oneshot::channel(); - let _ = self.requests_send.unbounded_send(RequestData::RemoteCall(request, sender)); - RemoteResponse { receiver }.compat() - } - - fn remote_changes(&self, request: RemoteChangesRequest) -> Self::RemoteChangesResult { - let (sender, receiver) = oneshot::channel(); - let _ = self.requests_send.unbounded_send(RequestData::RemoteChanges(request, sender)); - RemoteResponse { receiver }.compat() - } - - fn remote_body(&self, request: RemoteBodyRequest) -> Self::RemoteBodyResult { - let (sender, receiver) = oneshot::channel(); - let _ = self.requests_send.unbounded_send(RequestData::RemoteBody(request, sender)); - RemoteResponse { receiver }.compat() - } -} - -/// Future for an on-demand remote call response. -pub struct RemoteResponse { - receiver: oneshot::Receiver>, -} - -impl Future for RemoteResponse { - type Item = T; - type Error = ClientError; - - fn poll(&mut self) -> Poll { - self.receiver.poll() - .map_err(|_| ClientError::RemoteFetchCancelled.into()) - .and_then(|r| match r { - Async::Ready(Ok(ready)) => Ok(Async::Ready(ready)), - Async::Ready(Err(error)) => Err(error), - Async::NotReady => Ok(Async::NotReady), - }) - } -} diff --git a/core/network/src/protocol.rs b/core/network/src/protocol.rs deleted file mode 100644 index 2e036cf1183f1..0000000000000 --- a/core/network/src/protocol.rs +++ /dev/null @@ -1,1756 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::{DiscoveryNetBehaviour, config::ProtocolId}; -use crate::legacy_proto::{LegacyProto, LegacyProtoOut}; -use futures::prelude::*; -use futures03::{StreamExt as _, TryStreamExt as _}; -use libp2p::{Multiaddr, PeerId}; -use libp2p::core::{ConnectedPoint, nodes::Substream, muxing::StreamMuxerBox}; -use libp2p::swarm::{ProtocolsHandler, IntoProtocolsHandler}; -use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use primitives::storage::StorageKey; -use consensus::{ - BlockOrigin, - block_validation::BlockAnnounceValidator, - import_queue::{BlockImportResult, BlockImportError, IncomingBlock, Origin} -}; -use sr_primitives::{generic::BlockId, ConsensusEngineId, Justification}; -use sr_primitives::traits::{ - Block as BlockT, Header as HeaderT, NumberFor, One, Zero, - CheckedSub, SaturatedConversion -}; -use message::{BlockAnnounce, BlockAttributes, Direction, FromBlock, Message, RequestId}; -use message::generic::{Message as GenericMessage, ConsensusMessage}; -use event::Event; -use consensus_gossip::{ConsensusGossip, MessageRecipient as GossipMessageRecipient}; -use light_dispatch::{LightDispatch, LightDispatchNetwork, RequestData}; -use specialization::NetworkSpecialization; -use sync::{ChainSync, SyncState}; -use crate::service::{TransactionPool, ExHashT}; -use crate::config::{BoxFinalityProofRequestBuilder, Roles}; -use rustc_hex::ToHex; -use std::collections::{BTreeMap, HashMap}; -use std::sync::Arc; -use std::{cmp, num::NonZeroUsize, time}; -use log::{trace, debug, warn, error}; -use crate::chain::{Client, FinalityProofProvider}; -use client::light::fetcher::{FetchChecker, ChangesProof}; -use crate::error; -use util::LruHashSet; - -mod util; -pub mod consensus_gossip; -pub mod message; -pub mod event; -pub mod light_dispatch; -pub mod specialization; -pub mod sync; - -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); - -/// Current protocol version. -pub(crate) const CURRENT_VERSION: u32 = 4; -/// Lowest version we support -pub(crate) const MIN_VERSION: u32 = 3; - -// Maximum allowed entries in `BlockResponse` -const MAX_BLOCK_DATA_RESPONSE: u32 = 128; -/// When light node connects to the full node and the full node is behind light node -/// for at least `LIGHT_MAXIMAL_BLOCKS_DIFFERENCE` blocks, we consider it unuseful -/// and disconnect to free connection slot. -const LIGHT_MAXIMAL_BLOCKS_DIFFERENCE: u64 = 8192; - -/// Reputation change when a peer is "clogged", meaning that it's not fast enough to process our -/// messages. -const CLOGGED_PEER_REPUTATION_CHANGE: i32 = -(1 << 12); -/// Reputation change when a peer doesn't respond in time to our messages. -const TIMEOUT_REPUTATION_CHANGE: i32 = -(1 << 10); -/// Reputation change when a peer sends us a status message while we already received one. -const UNEXPECTED_STATUS_REPUTATION_CHANGE: i32 = -(1 << 20); -/// Reputation change when we are a light client and a peer is behind us. -const PEER_BEHIND_US_LIGHT_REPUTATION_CHANGE: i32 = -(1 << 8); -/// Reputation change when a peer sends us an extrinsic that we didn't know about. -const NEW_EXTRINSIC_REPUTATION_CHANGE: i32 = 1 << 7; -/// We sent an RPC query to the given node, but it failed. -const RPC_FAILED_REPUTATION_CHANGE: i32 = -(1 << 12); - -// Lock must always be taken in order declared here. -pub struct Protocol, H: ExHashT> { - /// Interval at which we call `tick`. - tick_timeout: Box + Send>, - /// Interval at which we call `propagate_extrinsics`. - propagate_timeout: Box + Send>, - config: ProtocolConfig, - /// Handler for light client requests. - light_dispatch: LightDispatch, - genesis_hash: B::Hash, - sync: ChainSync, - specialization: S, - consensus_gossip: ConsensusGossip, - context_data: ContextData, - // Connected peers pending Status message. - handshaking_peers: HashMap, - /// Used to report reputation changes. - peerset_handle: peerset::PeersetHandle, - transaction_pool: Arc>, - /// When asked for a proof of finality, we use this struct to build one. - finality_proof_provider: Option>>, - /// Handles opening the unique substream and sending and receiving raw messages. - behaviour: LegacyProto>, -} - -/// A peer that we are connected to -/// and from whom we have not yet received a Status message. -struct HandshakingPeer { - timestamp: time::Instant, -} - -/// Peer information -#[derive(Debug, Clone)] -struct Peer { - 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: LruHashSet, - /// Holds a set of blocks known to this peer. - known_blocks: LruHashSet, - /// Request counter, - next_request_id: message::RequestId, -} - -/// Info about a peer's known state. -#[derive(Clone, Debug)] -pub struct PeerInfo { - /// Roles - pub roles: Roles, - /// Protocol version - pub protocol_version: u32, - /// Peer best block hash - pub best_hash: B::Hash, - /// Peer best block number - pub best_number: ::Number, -} - -struct LightDispatchIn<'a, B: BlockT> { - behaviour: &'a mut LegacyProto>, - peerset: peerset::PeersetHandle, -} - -impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a, B> { - fn report_peer(&mut self, who: &PeerId, reputation: i32) { - self.peerset.report_peer(who.clone(), reputation) - } - - fn disconnect_peer(&mut self, who: &PeerId) { - self.behaviour.disconnect_peer(who) - } - - fn send_header_request(&mut self, who: &PeerId, id: RequestId, block: <::Header as HeaderT>::Number) { - let message = message::generic::Message::RemoteHeaderRequest(message::RemoteHeaderRequest { - id, - block, - }); - - self.behaviour.send_packet(who, message) - } - - fn send_read_request( - &mut self, - who: &PeerId, - id: RequestId, - block: ::Hash, - keys: Vec>, - ) { - let message = message::generic::Message::RemoteReadRequest(message::RemoteReadRequest { - id, - block, - keys, - }); - - self.behaviour.send_packet(who, message) - } - - fn send_read_child_request( - &mut self, - who: &PeerId, - id: RequestId, - block: ::Hash, - storage_key: Vec, - keys: Vec>, - ) { - let message = message::generic::Message::RemoteReadChildRequest(message::RemoteReadChildRequest { - id, - block, - storage_key, - keys, - }); - - self.behaviour.send_packet(who, message) - } - - fn send_call_request( - &mut self, - who: &PeerId, - id: RequestId, - block: ::Hash, - method: String, - data: Vec - ) { - let message = message::generic::Message::RemoteCallRequest(message::RemoteCallRequest { - id, - block, - method, - data, - }); - - self.behaviour.send_packet(who, message) - } - - fn send_changes_request( - &mut self, - who: &PeerId, - id: RequestId, - first: ::Hash, - last: ::Hash, - min: ::Hash, - max: ::Hash, - storage_key: Option>, - key: Vec, - ) { - let message = message::generic::Message::RemoteChangesRequest(message::RemoteChangesRequest { - id, - first, - last, - min, - max, - storage_key, - key, - }); - - self.behaviour.send_packet(who, message) - } - - fn send_body_request( - &mut self, - who: &PeerId, - id: RequestId, - fields: BlockAttributes, - from: FromBlock<::Hash, <::Header as HeaderT>::Number>, - to: Option<::Hash>, - direction: Direction, - max: Option - ) { - let message = message::generic::Message::BlockRequest(message::BlockRequest:: { - id, - fields, - from, - to, - direction, - max, - }); - - self.behaviour.send_packet(who, message) - } -} - -/// Context for a network-specific handler. -pub trait Context { - /// Adjusts the reputation of the peer. Use this to point out that a peer has been malign or - /// irresponsible or appeared lazy. - fn report_peer(&mut self, who: PeerId, reputation: i32); - - /// Force disconnecting from a peer. Use this when a peer misbehaved. - fn disconnect_peer(&mut self, who: PeerId); - - /// Send a consensus message to a peer. - fn send_consensus(&mut self, who: PeerId, consensus: ConsensusMessage); - - /// Send a chain-specific message to a peer. - fn send_chain_specific(&mut self, who: PeerId, message: Vec); -} - -/// Protocol context. -struct ProtocolContext<'a, B: 'a + BlockT, H: 'a + ExHashT> { - behaviour: &'a mut LegacyProto>, - context_data: &'a mut ContextData, - peerset_handle: &'a peerset::PeersetHandle, -} - -impl<'a, B: BlockT + 'a, H: 'a + ExHashT> ProtocolContext<'a, B, H> { - fn new( - context_data: &'a mut ContextData, - behaviour: &'a mut LegacyProto>, - peerset_handle: &'a peerset::PeersetHandle, - ) -> Self { - ProtocolContext { context_data, peerset_handle, behaviour } - } -} - -impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context for ProtocolContext<'a, B, H> { - fn report_peer(&mut self, who: PeerId, reputation: i32) { - self.peerset_handle.report_peer(who, reputation) - } - - fn disconnect_peer(&mut self, who: PeerId) { - self.behaviour.disconnect_peer(&who) - } - - fn send_consensus(&mut self, who: PeerId, consensus: ConsensusMessage) { - send_message( - self.behaviour, - &mut self.context_data.peers, - who, - GenericMessage::Consensus(consensus) - ) - } - - fn send_chain_specific(&mut self, who: PeerId, message: Vec) { - send_message( - self.behaviour, - &mut self.context_data.peers, - who, - GenericMessage::ChainSpecific(message) - ) - } -} - -/// Data necessary to create a context. -struct ContextData { - // All connected peers - peers: HashMap>, - pub chain: Arc>, -} - -/// Configuration for the Substrate-specific part of the networking layer. -#[derive(Clone)] -pub struct ProtocolConfig { - /// Assigned roles. - pub roles: Roles, -} - -impl Default for ProtocolConfig { - fn default() -> ProtocolConfig { - ProtocolConfig { - roles: Roles::FULL, - } - } -} - -impl, H: ExHashT> Protocol { - /// Create a new instance. - pub fn new( - config: ProtocolConfig, - chain: Arc>, - checker: Arc>, - specialization: S, - transaction_pool: Arc>, - finality_proof_provider: Option>>, - finality_proof_request_builder: Option>, - protocol_id: ProtocolId, - peerset_config: peerset::PeersetConfig, - block_announce_validator: Box + Send> - ) -> error::Result<(Protocol, peerset::PeersetHandle)> { - let info = chain.info(); - let sync = ChainSync::new( - config.roles, - chain.clone(), - &info, - finality_proof_request_builder, - block_announce_validator, - ); - let (peerset, peerset_handle) = peerset::Peerset::from_config(peerset_config); - let versions = &((MIN_VERSION as u8)..=(CURRENT_VERSION as u8)).collect::>(); - let behaviour = LegacyProto::new(protocol_id, versions, peerset); - - let protocol = Protocol { - tick_timeout: Box::new(futures_timer::Interval::new(TICK_TIMEOUT).map(|v| Ok::<_, ()>(v)).compat()), - propagate_timeout: Box::new(futures_timer::Interval::new(PROPAGATE_TIMEOUT).map(|v| Ok::<_, ()>(v)).compat()), - config, - context_data: ContextData { - peers: HashMap::new(), - chain, - }, - light_dispatch: LightDispatch::new(checker), - genesis_hash: info.chain.genesis_hash, - sync, - specialization, - consensus_gossip: ConsensusGossip::new(), - handshaking_peers: HashMap::new(), - transaction_pool, - finality_proof_provider, - peerset_handle: peerset_handle.clone(), - behaviour, - }; - - Ok((protocol, peerset_handle)) - } - - /// Returns the list of all the peers we have an open channel to. - pub fn open_peers(&self) -> impl Iterator { - self.behaviour.open_peers() - } - - /// Returns true if we have a channel open with this node. - pub fn is_open(&self, peer_id: &PeerId) -> bool { - self.behaviour.is_open(peer_id) - } - - /// Disconnects the given peer if we are connected to it. - pub fn disconnect_peer(&mut self, peer_id: &PeerId) { - self.behaviour.disconnect_peer(peer_id) - } - - /// Returns true if we try to open protocols with the given peer. - pub fn is_enabled(&self, peer_id: &PeerId) -> bool { - self.behaviour.is_enabled(peer_id) - } - - /// Returns the state of the peerset manager, for debugging purposes. - pub fn peerset_debug_info(&mut self) -> serde_json::Value { - self.behaviour.peerset_debug_info() - } - - /// Returns the number of peers we're connected to. - pub fn num_connected_peers(&self) -> usize { - self.context_data.peers.values().count() - } - - /// Returns the number of peers we're connected to and that are being queried. - pub fn num_active_peers(&self) -> usize { - self.context_data - .peers - .values() - .filter(|p| p.block_request.is_some()) - .count() - } - - /// Current global sync state. - pub fn sync_state(&self) -> SyncState { - self.sync.status().state - } - - /// Target sync block number. - pub fn best_seen_block(&self) -> Option> { - self.sync.status().best_seen_block - } - - /// Number of peers participating in syncing. - pub fn num_sync_peers(&self) -> u32 { - self.sync.status().num_peers - } - - /// Number of blocks in the import queue. - pub fn num_queued_blocks(&self) -> u32 { - self.sync.status().queued_blocks - } - - /// Starts a new data demand request. - /// - /// The parameter contains a `Sender` where the result, once received, must be sent. - pub(crate) fn add_light_client_request(&mut self, rq: RequestData) { - self.light_dispatch.add_request(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, rq); - } - - fn is_light_response(&self, who: &PeerId, response_id: message::RequestId) -> bool { - self.light_dispatch.is_light_response(&who, response_id) - } - - fn handle_response( - &mut self, - who: PeerId, - response: &message::BlockResponse - ) -> Option> { - if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { - if let Some(_) = peer.obsolete_requests.remove(&response.id) { - trace!(target: "sync", "Ignoring obsolete block response packet from {} ({})", who, response.id); - return None; - } - // Clear the request. If the response is invalid peer will be disconnected anyway. - let request = peer.block_request.take(); - if request.as_ref().map_or(false, |(_, r)| r.id == response.id) { - return request.map(|(_, r)| r) - } - trace!(target: "sync", "Unexpected response packet from {} ({})", who, response.id); - self.peerset_handle.report_peer(who.clone(), i32::min_value()); - self.behaviour.disconnect_peer(&who); - } - None - } - - fn update_peer_info(&mut self, who: &PeerId) { - if let Some(info) = self.sync.peer_info(who) { - if let Some(ref mut peer) = self.context_data.peers.get_mut(who) { - peer.info.best_hash = info.best_hash; - peer.info.best_number = info.best_number; - } - } - } - - /// Returns information about all the peers we are connected to after the handshake message. - pub fn peers_info(&self) -> impl Iterator)> { - self.context_data.peers.iter().map(|(id, peer)| (id, &peer.info)) - } - - pub fn on_event(&mut self, event: Event) { - self.specialization.on_event(event); - } - - pub fn on_custom_message( - &mut self, - who: PeerId, - message: Message, - ) -> CustomMessageOutcome { - match message { - GenericMessage::Status(s) => self.on_status_message(who, s), - GenericMessage::BlockRequest(r) => self.on_block_request(who, r), - GenericMessage::BlockResponse(r) => { - // Note, this is safe because only `ordinary bodies` and `remote bodies` are received in this matter. - if self.is_light_response(&who, r.id) { - self.on_remote_body_response(who, r); - } else { - if let Some(request) = self.handle_response(who.clone(), &r) { - let outcome = self.on_block_response(who.clone(), request, r); - self.update_peer_info(&who); - return outcome - } - } - }, - GenericMessage::BlockAnnounce(announce) => { - let outcome = self.on_block_announce(who.clone(), announce); - self.update_peer_info(&who); - return outcome; - }, - 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::FinalityProofRequest(request) => - self.on_finality_proof_request(who, request), - GenericMessage::FinalityProofResponse(response) => - return self.on_finality_proof_response(who, response), - GenericMessage::RemoteReadChildRequest(request) => - self.on_remote_read_child_request(who, request), - GenericMessage::Consensus(msg) => { - if self.context_data.peers.get(&who).map_or(false, |peer| peer.info.protocol_version > 2) { - self.consensus_gossip.on_incoming( - &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle), - who, - msg, - ); - } - } - GenericMessage::ChainSpecific(msg) => self.specialization.on_message( - &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle), - who, - msg, - ), - } - - CustomMessageOutcome::None - } - - fn send_message(&mut self, who: PeerId, message: Message) { - send_message::( - &mut self.behaviour, - &mut self.context_data.peers, - who, - message, - ); - } - - /// Locks `self` and returns a context plus the `ConsensusGossip` struct. - pub fn consensus_gossip_lock<'a>( - &'a mut self, - ) -> (impl Context + 'a, &'a mut ConsensusGossip) { - let context = ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle); - (context, &mut self.consensus_gossip) - } - - /// Locks `self` and returns a context plus the network specialization. - pub fn specialization_lock<'a>( - &'a mut self, - ) -> (impl Context + 'a, &'a mut S) { - let context = ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle); - (context, &mut self.specialization) - } - - /// Gossip a consensus message to the network. - pub fn gossip_consensus_message( - &mut self, - topic: B::Hash, - engine_id: ConsensusEngineId, - message: Vec, - recipient: GossipMessageRecipient, - ) { - let mut context = ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle); - let message = ConsensusMessage { data: message, engine_id }; - match recipient { - GossipMessageRecipient::BroadcastToAll => - self.consensus_gossip.multicast(&mut context, topic, message, true), - GossipMessageRecipient::BroadcastNew => - self.consensus_gossip.multicast(&mut context, topic, message, false), - GossipMessageRecipient::Peer(who) => - self.send_message(who, GenericMessage::Consensus(message)), - } - } - - /// Called when a new peer is connected - pub fn on_peer_connected(&mut self, who: PeerId) { - trace!(target: "sync", "Connecting {}", who); - self.handshaking_peers.insert(who.clone(), HandshakingPeer { timestamp: time::Instant::now() }); - self.send_status(who); - } - - /// Called by peer when it is disconnecting - pub fn on_peer_disconnected(&mut self, peer: PeerId) { - trace!(target: "sync", "Disconnecting {}", peer); - // lock all the the peer lists so that add/remove peer events are in order - let removed = { - self.handshaking_peers.remove(&peer); - self.context_data.peers.remove(&peer) - }; - if let Some(peer_data) = removed { - let mut context = ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle); - if peer_data.info.protocol_version > 2 { - self.consensus_gossip.peer_disconnected(&mut context, peer.clone()); - } - self.sync.peer_disconnected(peer.clone()); - self.specialization.on_disconnect(&mut context, peer.clone()); - self.light_dispatch.on_disconnect(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, peer); - } - } - - /// 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: PeerId, _msg: Option>) { - self.peerset_handle.report_peer(who.clone(), CLOGGED_PEER_REPUTATION_CHANGE); - - // Print some diagnostics. - if let Some(peer) = self.context_data.peers.get(&who) { - debug!(target: "sync", "Clogged peer {} (protocol_version: {:?}; roles: {:?}; \ - known_extrinsics: {:?}; known_blocks: {:?}; best_hash: {:?}; best_number: {:?})", - who, peer.info.protocol_version, peer.info.roles, peer.known_extrinsics, peer.known_blocks, - 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: PeerId, - request: message::BlockRequest - ) { - trace!(target: "sync", "BlockRequest {} from {}: from {:?} to {:?} max {:?}", - request.id, - peer, - request.from, - request.to, - request.max); - - // sending block requests to the node that is unable to serve it is considered a bad behavior - if !self.config.roles.is_full() { - trace!(target: "sync", "Peer {} is trying to sync from the light node", peer); - self.behaviour.disconnect_peer(&peer); - self.peerset_handle.report_peer(peer, i32::min_value()); - return; - } - - 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; - 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); - 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 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 - }, - receipt: None, - message_queue: None, - justification, - }; - blocks.push(block_data); - match request.direction { - message::Direction::Ascending => id = BlockId::Number(number + One::one()), - message::Direction::Descending => { - if number.is_zero() { - break; - } - id = BlockId::Hash(parent_hash) - } - } - } - let response = message::generic::BlockResponse { - id: request.id, - blocks: blocks, - }; - trace!(target: "sync", "Sending BlockResponse with {} blocks", response.blocks.len()); - self.send_message(peer, GenericMessage::BlockResponse(response)) - } - - /// Adjusts the reputation of a node. - pub fn report_peer(&self, who: PeerId, reputation: i32) { - self.peerset_handle.report_peer(who, reputation) - } - - fn on_block_response( - &mut self, - peer: PeerId, - request: message::BlockRequest, - response: message::BlockResponse, - ) -> CustomMessageOutcome { - 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())), - ) { - (Some(first), Some(last)) if first != last => format!(" ({}..{})", first, last), - (Some(first), Some(_)) => format!(" ({})", first), - _ => Default::default(), - }; - trace!(target: "sync", "BlockResponse {} from {} with {} blocks {}", - response.id, - peer, - response.blocks.len(), - blocks_range - ); - - // TODO [andre]: move this logic to the import queue so that - // justifications are imported asynchronously (#1482) - if request.fields == message::BlockAttributes::JUSTIFICATION { - match self.sync.on_block_justification(peer, response) { - Ok(sync::OnBlockJustification::Nothing) => CustomMessageOutcome::None, - Ok(sync::OnBlockJustification::Import { peer, hash, number, justification }) => - CustomMessageOutcome::JustificationImport(peer, hash, number, justification), - Err(sync::BadPeer(id, repu)) => { - self.behaviour.disconnect_peer(&id); - self.peerset_handle.report_peer(id, repu); - CustomMessageOutcome::None - } - } - } else { - match self.sync.on_block_data(peer, request, response) { - Ok(sync::OnBlockData::Import(origin, blocks)) => - CustomMessageOutcome::BlockImport(origin, blocks), - Ok(sync::OnBlockData::Request(peer, req)) => { - self.send_message(peer, GenericMessage::BlockRequest(req)); - CustomMessageOutcome::None - } - Err(sync::BadPeer(id, repu)) => { - self.behaviour.disconnect_peer(&id); - self.peerset_handle.report_peer(id, repu); - CustomMessageOutcome::None - } - } - } - } - - /// Perform time based maintenance. - /// - /// > **Note**: This method normally doesn't have to be called except for testing purposes. - pub fn tick(&mut self) { - self.consensus_gossip.tick( - &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle) - ); - self.maintain_peers(); - self.light_dispatch.maintain_peers(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }); - } - - fn maintain_peers(&mut self) { - let tick = time::Instant::now(); - let mut aborting = Vec::new(); - { - 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", "Request timeout {}", who); - aborting.push(who.clone()); - } else if peer.obsolete_requests.values().any(|t| (tick - *t).as_secs() > REQUEST_TIMEOUT_SEC) { - trace!(target: "sync", "Obsolete timeout {}", who); - aborting.push(who.clone()); - } - } - 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.clone()); - } - } - - self.specialization.maintain_peers( - &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle) - ); - for p in aborting { - self.behaviour.disconnect_peer(&p); - self.peerset_handle.report_peer(p, TIMEOUT_REPUTATION_CHANGE); - } - } - - /// Called by peer to report status - fn on_status_message(&mut self, who: PeerId, status: message::Status) { - trace!(target: "sync", "New peer {} {:?}", who, status); - let protocol_version = { - if self.context_data.peers.contains_key(&who) { - debug!("Unexpected status packet from {}", who); - self.peerset_handle.report_peer(who, UNEXPECTED_STATUS_REPUTATION_CHANGE); - return; - } - if status.genesis_hash != self.genesis_hash { - trace!( - target: "protocol", - "Peer is on different chain (our genesis: {} theirs: {})", - self.genesis_hash, status.genesis_hash - ); - self.peerset_handle.report_peer(who.clone(), i32::min_value()); - self.behaviour.disconnect_peer(&who); - return; - } - if status.version < MIN_VERSION && CURRENT_VERSION < status.min_supported_version { - trace!(target: "protocol", "Peer {:?} using unsupported protocol version {}", who, status.version); - self.peerset_handle.report_peer(who.clone(), i32::min_value()); - self.behaviour.disconnect_peer(&who); - return; - } - - if self.config.roles.is_light() { - // we're not interested in light peers - if status.roles.is_light() { - debug!(target: "sync", "Peer {} is unable to serve light requests", who); - self.peerset_handle.report_peer(who.clone(), i32::min_value()); - self.behaviour.disconnect_peer(&who); - return; - } - - // we don't interested in peers that are far behind us - let self_best_block = self - .context_data - .chain - .info() - .chain.best_number; - let blocks_difference = self_best_block - .checked_sub(&status.best_number) - .unwrap_or_else(Zero::zero) - .saturated_into::(); - if blocks_difference > LIGHT_MAXIMAL_BLOCKS_DIFFERENCE { - debug!(target: "sync", "Peer {} is far behind us and will unable to serve light requests", who); - self.peerset_handle.report_peer(who.clone(), PEER_BEHIND_US_LIGHT_REPUTATION_CHANGE); - self.behaviour.disconnect_peer(&who); - 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) => { - PeerInfo { - protocol_version: status.version, - roles: status.roles, - best_hash: status.best_hash, - best_number: status.best_number - } - }, - None => { - error!(target: "sync", "Received status from previously unconnected node {}", who); - return; - }, - }; - - let peer = Peer { - info, - block_request: None, - known_extrinsics: LruHashSet::new(cache_limit), - known_blocks: LruHashSet::new(cache_limit), - next_request_id: 0, - obsolete_requests: HashMap::new(), - }; - self.context_data.peers.insert(who.clone(), peer); - - debug!(target: "sync", "Connected {}", who); - status.version - }; - - let info = self.context_data.peers.get(&who).expect("We just inserted above; QED").info.clone(); - self.light_dispatch.on_connect(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, who.clone(), status.roles, status.best_number); - match self.sync.new_peer(who.clone(), info) { - Ok(None) => (), - Ok(Some(req)) => self.send_message(who.clone(), GenericMessage::BlockRequest(req)), - Err(sync::BadPeer(id, repu)) => { - self.behaviour.disconnect_peer(&id); - self.peerset_handle.report_peer(id, repu) - } - } - let mut context = ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle); - if protocol_version > 2 { - self.consensus_gossip.new_peer(&mut context, who.clone(), status.roles); - } - self.specialization.on_connect(&mut context, who, status); - } - - /// Called when peer sends us new extrinsics - fn on_extrinsics( - &mut self, - who: PeerId, - extrinsics: message::Transactions - ) { - // sending extrinsic to light node is considered a bad behavior - if !self.config.roles.is_full() { - trace!(target: "sync", "Peer {} is trying to send extrinsic to the light node", who); - self.behaviour.disconnect_peer(&who); - self.peerset_handle.report_peer(who, i32::min_value()); - return; - } - - // Accept extrinsics only when fully synced - if self.sync.status().state != SyncState::Idle { - trace!(target: "sync", "{} Ignoring extrinsics while syncing", who); - return; - } - trace!(target: "sync", "Received {} extrinsics from {}", extrinsics.len(), who); - if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { - for t in extrinsics { - let hash = self.transaction_pool.hash_of(&t); - peer.known_extrinsics.insert(hash); - - self.transaction_pool.import( - self.peerset_handle.clone().into(), - who.clone(), - NEW_EXTRINSIC_REPUTATION_CHANGE, - t, - ); - } - } - } - - /// Call when we must propagate ready extrinsics to peers. - pub fn propagate_extrinsics( - &mut self, - ) { - debug!(target: "sync", "Propagating extrinsics"); - - // Accept transactions only when fully synced - if self.sync.status().state != SyncState::Idle { - return; - } - - let extrinsics = self.transaction_pool.transactions(); - let mut propagated_to = HashMap::new(); - for (who, peer) in self.context_data.peers.iter_mut() { - // never send extrinsics to the light node - if !peer.info.roles.is_full() { - continue; - } - - let (hashes, to_send): (Vec<_>, Vec<_>) = extrinsics - .iter() - .filter(|&(ref hash, _)| peer.known_extrinsics.insert(hash.clone())) - .cloned() - .unzip(); - - if !to_send.is_empty() { - for hash in hashes { - propagated_to - .entry(hash) - .or_insert_with(Vec::new) - .push(who.to_base58()); - } - trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), who); - self.behaviour.send_packet(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, data: Vec) { - 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; - } - }; - - // don't announce genesis block since it will be ignored - if header.number().is_zero() { - return; - } - - let is_best = self.context_data.chain.info().chain.best_hash == hash; - debug!(target: "sync", "Reannouncing block {:?}", hash); - self.send_announcement(&header, data, is_best, true) - } - - fn send_announcement(&mut self, header: &B::Header, data: Vec, is_best: bool, force: bool) { - let hash = header.hash(); - - for (who, ref mut peer) in self.context_data.peers.iter_mut() { - trace!(target: "sync", "Announcing block {:?} to {}", hash, who); - let inserted = peer.known_blocks.insert(hash); - if inserted || force { - let message = GenericMessage::BlockAnnounce(message::BlockAnnounce { - header: header.clone(), - state: if peer.info.protocol_version >= 4 { - if is_best { - Some(message::BlockState::Best) - } else { - Some(message::BlockState::Normal) - } - } else { - None - }, - data: if peer.info.protocol_version >= 4 { - Some(data.clone()) - } else { - None - }, - }); - - self.behaviour.send_packet(who, message) - } - } - } - - /// Send Status message - fn send_status(&mut self, who: PeerId) { - let info = self.context_data.chain.info(); - let status = message::generic::Status { - version: CURRENT_VERSION, - min_supported_version: MIN_VERSION, - genesis_hash: info.chain.genesis_hash, - roles: self.config.roles.into(), - best_number: info.chain.best_number, - best_hash: info.chain.best_hash, - chain_status: self.specialization.status(), - }; - - self.send_message(who, GenericMessage::Status(status)) - } - - fn on_block_announce(&mut self, who: PeerId, announce: BlockAnnounce) -> CustomMessageOutcome { - let hash = announce.header.hash(); - if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { - peer.known_blocks.insert(hash.clone()); - } - self.light_dispatch.update_best_number(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, who.clone(), *announce.header.number()); - - let is_their_best = match announce.state.unwrap_or(message::BlockState::Best) { - message::BlockState::Best => true, - message::BlockState::Normal => false, - }; - - match self.sync.on_block_announce(who.clone(), hash, &announce, is_their_best) { - sync::OnBlockAnnounce::Nothing => { - // `on_block_announce` returns `OnBlockAnnounce::ImportHeader` - // when we have all data required to import the block - // in the BlockAnnounce message. This is only when: - // 1) we're on light client; - // AND - // 2) parent block is already imported and not pruned. - return CustomMessageOutcome::None - } - sync::OnBlockAnnounce::ImportHeader => () // We proceed with the import. - } - - // to import header from announced block let's construct response to request that normally would have - // been sent over network (but it is not in our case) - let blocks_to_import = self.sync.on_block_data( - who.clone(), - message::generic::BlockRequest { - id: 0, - fields: BlockAttributes::HEADER, - from: message::FromBlock::Hash(hash), - to: None, - direction: message::Direction::Ascending, - max: Some(1), - }, - message::generic::BlockResponse { - id: 0, - blocks: vec![ - message::generic::BlockData { - hash: hash, - header: Some(announce.header), - body: None, - receipt: None, - message_queue: None, - justification: None, - }, - ], - }, - ); - match blocks_to_import { - Ok(sync::OnBlockData::Import(origin, blocks)) => CustomMessageOutcome::BlockImport(origin, blocks), - Ok(sync::OnBlockData::Request(peer, req)) => { - self.send_message(peer, GenericMessage::BlockRequest(req)); - CustomMessageOutcome::None - } - Err(sync::BadPeer(id, repu)) => { - self.behaviour.disconnect_peer(&id); - self.peerset_handle.report_peer(id, repu); - CustomMessageOutcome::None - } - } - } - - /// Call this when a block has been imported in the import queue and we should announce it on - /// the network. - pub fn on_block_imported(&mut self, hash: B::Hash, header: &B::Header, data: Vec, is_best: bool) { - if is_best { - self.sync.update_chain_info(header); - } - self.specialization.on_block_imported( - &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle), - hash.clone(), - header, - ); - - // blocks are not announced by light clients - if self.config.roles.is_light() { - return; - } - - // send out block announcements - self.send_announcement(header, data, is_best, false); - } - - /// Call this when a block has been finalized. The sync layer may have some additional - /// requesting to perform. - pub fn on_block_finalized(&mut self, hash: B::Hash, header: &B::Header) { - self.sync.on_block_finalized(&hash, *header.number()) - } - - fn on_remote_call_request( - &mut self, - who: PeerId, - 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, - ) { - Ok((_, proof)) => proof, - Err(error) => { - trace!(target: "sync", "Remote call request {} from {} ({} at {}) failed with: {}", - request.id, - who, - request.method, - request.block, - error - ); - self.peerset_handle.report_peer(who.clone(), RPC_FAILED_REPUTATION_CHANGE); - Default::default() - } - }; - - self.send_message( - who, - GenericMessage::RemoteCallResponse(message::RemoteCallResponse { - id: request.id, - proof, - }), - ); - } - - /// Request a justification for the given block. - /// - /// Uses `protocol` to queue a new justification request and tries to dispatch all pending - /// requests. - pub fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { - self.sync.request_justification(&hash, number) - } - - /// Request syncing for the given block from given set of peers. - /// Uses `protocol` to queue a new block download request and tries to dispatch all pending - /// requests. - pub fn set_sync_fork_request(&mut self, peers: Vec, hash: &B::Hash, number: NumberFor) { - self.sync.set_sync_fork_request(peers, hash, number) - } - - /// A batch of blocks have been processed, with or without errors. - /// Call this when a batch of blocks have been processed by the importqueue, with or without - /// errors. - pub fn blocks_processed( - &mut self, - imported: usize, - count: usize, - results: Vec<(Result>, BlockImportError>, B::Hash)> - ) { - let peers = self.context_data.peers.clone(); - let results = self.sync.on_blocks_processed( - imported, - count, - results, - |peer_id| peers.get(peer_id).map(|i| i.info.clone()) - ); - for result in results { - match result { - Ok((id, req)) => { - let msg = GenericMessage::BlockRequest(req); - send_message(&mut self.behaviour, &mut self.context_data.peers, id, msg) - } - Err(sync::BadPeer(id, repu)) => { - self.behaviour.disconnect_peer(&id); - self.peerset_handle.report_peer(id, repu) - } - } - } - } - - /// Call this when a justification has been processed by the import queue, with or without - /// errors. - pub fn justification_import_result(&mut self, hash: B::Hash, number: NumberFor, success: bool) { - self.sync.on_justification_import(hash, number, success) - } - - /// Request a finality proof for the given block. - /// - /// Queues a new finality proof request and tries to dispatch all pending requests. - pub fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { - self.sync.request_finality_proof(&hash, number) - } - - pub fn finality_proof_import_result( - &mut self, - request_block: (B::Hash, NumberFor), - finalization_result: Result<(B::Hash, NumberFor), ()>, - ) { - self.sync.on_finality_proof_import(request_block, finalization_result) - } - - fn on_remote_call_response( - &mut self, - who: PeerId, - response: message::RemoteCallResponse - ) { - trace!(target: "sync", "Remote call response {} from {}", response.id, who); - self.light_dispatch.on_remote_call_response(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, who, response); - } - - fn on_remote_read_request( - &mut self, - who: PeerId, - request: message::RemoteReadRequest, - ) { - let keys_str = || match request.keys.len() { - 1 => request.keys[0].to_hex::(), - _ => format!( - "{}..{}", - request.keys[0].to_hex::(), - request.keys[request.keys.len() - 1].to_hex::(), - ), - }; - - trace!(target: "sync", "Remote read request {} from {} ({} at {})", - request.id, who, keys_str(), request.block); - let proof = match self.context_data.chain.read_proof(&request.block, &request.keys) { - Ok(proof) => proof, - Err(error) => { - trace!(target: "sync", "Remote read request {} from {} ({} at {}) failed with: {}", - request.id, - who, - keys_str(), - request.block, - error - ); - Default::default() - } - }; - self.send_message( - who, - GenericMessage::RemoteReadResponse(message::RemoteReadResponse { - id: request.id, - proof, - }), - ); - } - - fn on_remote_read_child_request( - &mut self, - who: PeerId, - request: message::RemoteReadChildRequest, - ) { - let keys_str = || match request.keys.len() { - 1 => request.keys[0].to_hex::(), - _ => format!( - "{}..{}", - request.keys[0].to_hex::(), - request.keys[request.keys.len() - 1].to_hex::(), - ), - }; - - trace!(target: "sync", "Remote read child request {} from {} ({} {} at {})", - request.id, who, request.storage_key.to_hex::(), keys_str(), request.block); - let proof = match self.context_data.chain.read_child_proof( - &request.block, - &request.storage_key, - &request.keys, - ) { - Ok(proof) => proof, - Err(error) => { - trace!(target: "sync", "Remote read child request {} from {} ({} {} at {}) failed with: {}", - request.id, - who, - request.storage_key.to_hex::(), - keys_str(), - request.block, - error - ); - Default::default() - } - }; - self.send_message( - who, - GenericMessage::RemoteReadResponse(message::RemoteReadResponse { - id: request.id, - proof, - }), - ); - } - - fn on_remote_read_response( - &mut self, - who: PeerId, - response: message::RemoteReadResponse - ) { - trace!(target: "sync", "Remote read response {} from {}", response.id, who); - self.light_dispatch.on_remote_read_response(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, who, response); - } - - fn on_remote_header_request( - &mut self, - who: PeerId, - 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) { - Ok((header, proof)) => (Some(header), proof), - Err(error) => { - trace!(target: "sync", "Remote header proof request {} from {} ({}) failed with: {}", - request.id, - who, - request.block, - error - ); - (Default::default(), Default::default()) - } - }; - self.send_message( - who, - GenericMessage::RemoteHeaderResponse(message::RemoteHeaderResponse { - id: request.id, - header, - proof, - }), - ); - } - - fn on_remote_header_response( - &mut self, - who: PeerId, - response: message::RemoteHeaderResponse, - ) { - trace!(target: "sync", "Remote header proof response {} from {}", response.id, who); - self.light_dispatch.on_remote_header_response(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, who, response); - } - - fn on_remote_changes_request( - &mut self, - who: PeerId, - request: message::RemoteChangesRequest, - ) { - trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{})", - request.id, - who, - if let Some(sk) = request.storage_key.as_ref() { - format!("{} : {}", sk.to_hex::(), request.key.to_hex::()) - } else { - request.key.to_hex::() - }, - request.first, - request.last - ); - let storage_key = request.storage_key.map(|sk| StorageKey(sk)); - let key = StorageKey(request.key); - let proof = match self.context_data.chain.key_changes_proof( - request.first, - request.last, - request.min, - request.max, - storage_key.as_ref(), - &key, - ) { - Ok(proof) => proof, - Err(error) => { - trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{}) failed with: {}", - request.id, - who, - if let Some(sk) = storage_key { - format!("{} : {}", sk.0.to_hex::(), key.0.to_hex::()) - } else { - key.0.to_hex::() - }, - request.first, - request.last, - error - ); - ChangesProof:: { - max_block: Zero::zero(), - proof: vec![], - roots: BTreeMap::new(), - roots_proof: vec![], - } - } - }; - 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( - &mut self, - who: PeerId, - response: message::RemoteChangesResponse, B::Hash>, - ) { - trace!(target: "sync", "Remote changes proof response {} from {} (max={})", - response.id, - who, - response.max - ); - self.light_dispatch.on_remote_changes_response(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, who, response); - } - - fn on_finality_proof_request( - &mut self, - who: PeerId, - request: message::FinalityProofRequest, - ) { - trace!(target: "sync", "Finality proof request from {} for {}", who, request.block); - let finality_proof = self.finality_proof_provider.as_ref() - .ok_or_else(|| String::from("Finality provider is not configured")) - .and_then(|provider| - provider.prove_finality(request.block, &request.request).map_err(|e| e.to_string()) - ); - let finality_proof = match finality_proof { - Ok(finality_proof) => finality_proof, - Err(error) => { - trace!(target: "sync", "Finality proof request from {} for {} failed with: {}", - who, - request.block, - error - ); - None - }, - }; - self.send_message( - who, - GenericMessage::FinalityProofResponse(message::FinalityProofResponse { - id: 0, - block: request.block, - proof: finality_proof, - }), - ); - } - - fn on_finality_proof_response( - &mut self, - who: PeerId, - response: message::FinalityProofResponse, - ) -> CustomMessageOutcome { - trace!(target: "sync", "Finality proof response from {} for {}", who, response.block); - match self.sync.on_block_finality_proof(who, response) { - Ok(sync::OnBlockFinalityProof::Nothing) => CustomMessageOutcome::None, - Ok(sync::OnBlockFinalityProof::Import { peer, hash, number, proof }) => - CustomMessageOutcome::FinalityProofImport(peer, hash, number, proof), - Err(sync::BadPeer(id, repu)) => { - self.behaviour.disconnect_peer(&id); - self.peerset_handle.report_peer(id, repu); - CustomMessageOutcome::None - } - } - } - - fn on_remote_body_response( - &mut self, - peer: PeerId, - response: message::BlockResponse - ) { - self.light_dispatch.on_remote_body_response(LightDispatchIn { - behaviour: &mut self.behaviour, - peerset: self.peerset_handle.clone(), - }, peer, response); - } -} - -/// Outcome of an incoming custom message. -#[derive(Debug)] -pub enum CustomMessageOutcome { - BlockImport(BlockOrigin, Vec>), - JustificationImport(Origin, B::Hash, NumberFor, Justification), - FinalityProofImport(Origin, B::Hash, NumberFor, Vec), - None, -} - -fn send_message( - behaviour: &mut LegacyProto>, - peers: &mut HashMap>, - who: PeerId, - 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())); - } - } - behaviour.send_packet(&who, message); -} - -impl, H: ExHashT> NetworkBehaviour for -Protocol { - type ProtocolsHandler = > as NetworkBehaviour>::ProtocolsHandler; - type OutEvent = CustomMessageOutcome; - - fn new_handler(&mut self) -> Self::ProtocolsHandler { - self.behaviour.new_handler() - } - - fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { - self.behaviour.addresses_of_peer(peer_id) - } - - fn inject_connected(&mut self, peer_id: PeerId, endpoint: ConnectedPoint) { - self.behaviour.inject_connected(peer_id, endpoint) - } - - fn inject_disconnected(&mut self, peer_id: &PeerId, endpoint: ConnectedPoint) { - self.behaviour.inject_disconnected(peer_id, endpoint) - } - - fn inject_node_event( - &mut self, - peer_id: PeerId, - event: <::Handler as ProtocolsHandler>::OutEvent, - ) { - self.behaviour.inject_node_event(peer_id, event) - } - - fn poll( - &mut self, - params: &mut impl PollParameters, - ) -> Async< - NetworkBehaviourAction< - <::Handler as ProtocolsHandler>::InEvent, - Self::OutEvent - > - > { - while let Ok(Async::Ready(_)) = self.tick_timeout.poll() { - self.tick(); - } - - while let Ok(Async::Ready(_)) = self.propagate_timeout.poll() { - self.propagate_extrinsics(); - } - - for (id, r) in self.sync.block_requests() { - send_message(&mut self.behaviour, &mut self.context_data.peers, id, GenericMessage::BlockRequest(r)) - } - for (id, r) in self.sync.justification_requests() { - send_message(&mut self.behaviour, &mut self.context_data.peers, id, GenericMessage::BlockRequest(r)) - } - for (id, r) in self.sync.finality_proof_requests() { - send_message(&mut self.behaviour, &mut self.context_data.peers, id, GenericMessage::FinalityProofRequest(r)) - } - - let event = match self.behaviour.poll(params) { - Async::NotReady => return Async::NotReady, - Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => ev, - Async::Ready(NetworkBehaviourAction::DialAddress { address }) => - return Async::Ready(NetworkBehaviourAction::DialAddress { address }), - Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) => - return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }), - Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) => - return Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }), - Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => - return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }), - }; - - let outcome = match event { - LegacyProtoOut::CustomProtocolOpen { peer_id, version, .. } => { - debug_assert!( - version <= CURRENT_VERSION as u8 - && version >= MIN_VERSION as u8 - ); - self.on_peer_connected(peer_id); - CustomMessageOutcome::None - } - LegacyProtoOut::CustomProtocolClosed { peer_id, .. } => { - self.on_peer_disconnected(peer_id); - CustomMessageOutcome::None - }, - LegacyProtoOut::CustomMessage { peer_id, message } => - self.on_custom_message(peer_id, message), - LegacyProtoOut::Clogged { peer_id, messages } => { - debug!(target: "sync", "{} clogging messages:", messages.len()); - for msg in messages.into_iter().take(5) { - debug!(target: "sync", "{:?}", msg); - self.on_clogged_peer(peer_id.clone(), Some(msg)); - } - CustomMessageOutcome::None - } - }; - - if let CustomMessageOutcome::None = outcome { - Async::NotReady - } else { - Async::Ready(NetworkBehaviourAction::GenerateEvent(outcome)) - } - } - - fn inject_replaced(&mut self, peer_id: PeerId, closed_endpoint: ConnectedPoint, new_endpoint: ConnectedPoint) { - self.behaviour.inject_replaced(peer_id, closed_endpoint, new_endpoint) - } - - fn inject_addr_reach_failure( - &mut self, - peer_id: Option<&PeerId>, - addr: &Multiaddr, - error: &dyn std::error::Error - ) { - self.behaviour.inject_addr_reach_failure(peer_id, addr, error) - } - - fn inject_dial_failure(&mut self, peer_id: &PeerId) { - self.behaviour.inject_dial_failure(peer_id) - } - - fn inject_new_listen_addr(&mut self, addr: &Multiaddr) { - self.behaviour.inject_new_listen_addr(addr) - } - - fn inject_expired_listen_addr(&mut self, addr: &Multiaddr) { - self.behaviour.inject_expired_listen_addr(addr) - } - - fn inject_new_external_addr(&mut self, addr: &Multiaddr) { - self.behaviour.inject_new_external_addr(addr) - } -} - -impl, H: ExHashT> DiscoveryNetBehaviour for Protocol { - fn add_discovered_nodes(&mut self, peer_ids: impl Iterator) { - self.behaviour.add_discovered_nodes(peer_ids) - } -} diff --git a/core/network/src/protocol/consensus_gossip.rs b/core/network/src/protocol/consensus_gossip.rs deleted file mode 100644 index f3d4e536a788d..0000000000000 --- a/core/network/src/protocol/consensus_gossip.rs +++ /dev/null @@ -1,758 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Utility for gossip of network messages between nodes. -//! Handles chain-specific and standard BFT messages. -//! -//! Gossip messages are separated by two categories: "topics" and consensus engine ID. -//! The consensus engine ID is sent over the wire with the message, while the topic is not, -//! with the expectation that the topic can be derived implicitly from the content of the -//! message, assuming it is valid. -//! -//! Topics are a single 32-byte tag associated with a message, used to group those messages -//! in an opaque way. Consensus code can invoke `broadcast_topic` to attempt to send all messages -//! under a single topic to all peers who don't have them yet, and `send_topic` to -//! send all messages under a single topic to a specific peer. -//! -//! Each consensus engine ID must have an associated, -//! registered `Validator` for all gossip messages. The primary role of this `Validator` is -//! to process incoming messages from peers, and decide whether to discard them or process -//! them. It also decides whether to re-broadcast the message. -//! -//! The secondary role of the `Validator` is to check if a message is allowed to be sent to a given -//! peer. All messages, before being sent, will be checked against this filter. -//! This enables the validator to use information it's aware of about connected peers to decide -//! whether to send messages to them at any given moment in time - In particular, to wait until -//! peers can accept and process the message before sending it. -//! -//! Lastly, the fact that gossip validators can decide not to rebroadcast messages -//! opens the door for neighbor status packets to be baked into the gossip protocol. -//! These status packets will typically contain light pieces of information -//! used to inform peers of a current view of protocol state. - -use std::collections::{HashMap, HashSet, hash_map::Entry}; -use std::sync::Arc; -use std::iter; -use std::time; -use log::{trace, debug}; -use futures03::channel::mpsc; -use lru_cache::LruCache; -use libp2p::PeerId; -use sr_primitives::traits::{Block as BlockT, Hash, HashFor}; -use sr_primitives::ConsensusEngineId; -pub use crate::message::generic::{Message, ConsensusMessage}; -use crate::protocol::Context; -use crate::config::Roles; - -// FIXME: Add additional spam/DoS attack protection: https://github.com/paritytech/substrate/issues/1115 -const KNOWN_MESSAGES_CACHE_SIZE: usize = 4096; - -const REBROADCAST_INTERVAL: time::Duration = time::Duration::from_secs(30); -/// Reputation change when a peer sends us a gossip message that we didn't know about. -const GOSSIP_SUCCESS_REPUTATION_CHANGE: i32 = 1 << 4; -/// Reputation change when a peer sends us a gossip message that we already knew about. -const DUPLICATE_GOSSIP_REPUTATION_CHANGE: i32 = -(1 << 2); -/// Reputation change when a peer sends us a gossip message for an unknown engine, whatever that -/// means. -const UNKNOWN_GOSSIP_REPUTATION_CHANGE: i32 = -(1 << 6); -/// Reputation change when a peer sends a message from a topic it isn't registered on. -const UNREGISTERED_TOPIC_REPUTATION_CHANGE: i32 = -(1 << 10); - -struct PeerConsensus { - known_messages: HashSet, - roles: Roles, -} - -/// Topic stream message with sender. -#[derive(Debug, Eq, PartialEq)] -pub struct TopicNotification { - /// Message data. - pub message: Vec, - /// Sender if available. - pub sender: Option, -} - -struct MessageEntry { - message_hash: B::Hash, - topic: B::Hash, - message: ConsensusMessage, - sender: Option, -} - -/// Consensus message destination. -pub enum MessageRecipient { - /// Send to all peers. - BroadcastToAll, - /// Send to peers that don't have that message already. - BroadcastNew, - /// Send to specific peer. - Peer(PeerId), -} - -/// The reason for sending out the message. -#[derive(Eq, PartialEq, Copy, Clone)] -pub enum MessageIntent { - /// Requested broadcast - Broadcast, - /// Requested broadcast to all peers. - ForcedBroadcast, - /// Periodic rebroadcast of all messages to all peers. - PeriodicRebroadcast, -} - -/// Message validation result. -pub enum ValidationResult { - /// Message should be stored and propagated under given topic. - ProcessAndKeep(H), - /// Message should be processed, but not propagated. - ProcessAndDiscard(H), - /// Message should be ignored. - Discard, -} - -/// Validation context. Allows reacting to incoming messages by sending out further messages. -pub trait ValidatorContext { - /// Broadcast all messages with given topic to peers that do not have it yet. - fn broadcast_topic(&mut self, topic: B::Hash, force: bool); - /// Broadcast a message to all peers that have not received it previously. - fn broadcast_message(&mut self, topic: B::Hash, message: Vec, force: bool); - /// Send addressed message to a peer. - fn send_message(&mut self, who: &PeerId, message: Vec); - /// Send all messages with given topic to a peer. - fn send_topic(&mut self, who: &PeerId, topic: B::Hash, force: bool); -} - -struct NetworkContext<'g, 'p, B: BlockT> { - gossip: &'g mut ConsensusGossip, - protocol: &'p mut dyn Context, - engine_id: ConsensusEngineId, -} - -impl<'g, 'p, B: BlockT> ValidatorContext for NetworkContext<'g, 'p, B> { - /// Broadcast all messages with given topic to peers that do not have it yet. - fn broadcast_topic(&mut self, topic: B::Hash, force: bool) { - self.gossip.broadcast_topic(self.protocol, topic, force); - } - - /// Broadcast a message to all peers that have not received it previously. - fn broadcast_message(&mut self, topic: B::Hash, message: Vec, force: bool) { - self.gossip.multicast( - self.protocol, - topic, - ConsensusMessage{ data: message, engine_id: self.engine_id.clone() }, - force, - ); - } - - /// Send addressed message to a peer. - fn send_message(&mut self, who: &PeerId, message: Vec) { - self.protocol.send_consensus(who.clone(), ConsensusMessage { - engine_id: self.engine_id, - data: message, - }); - } - - /// Send all messages with given topic to a peer. - fn send_topic(&mut self, who: &PeerId, topic: B::Hash, force: bool) { - self.gossip.send_topic(self.protocol, who, topic, self.engine_id, force); - } -} - -fn propagate<'a, B: BlockT, I>( - protocol: &mut dyn Context, - messages: I, - intent: MessageIntent, - peers: &mut HashMap>, - validators: &HashMap>>, -) - where I: IntoIterator, // (msg_hash, topic, message) -{ - let mut check_fns = HashMap::new(); - let mut message_allowed = move |who: &PeerId, intent: MessageIntent, topic: &B::Hash, message: &ConsensusMessage| { - let engine_id = 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 false, // treat all messages with no validator as not allowed - Some(validator) => vacant.insert(validator.message_allowed()), - } - }; - - (check_fn)(who, intent, topic, &message.data) - }; - - for (message_hash, topic, message) in messages { - for (id, ref mut peer) in peers.iter_mut() { - let intent = match intent { - MessageIntent::Broadcast => - if peer.known_messages.contains(&message_hash) { - continue - } else { - MessageIntent::Broadcast - }, - MessageIntent::PeriodicRebroadcast => - if peer.known_messages.contains(&message_hash) { - MessageIntent::PeriodicRebroadcast - } else { - // peer doesn't know message, so the logic should treat it as an - // initial broadcast. - MessageIntent::Broadcast - }, - other => other, - }; - - if !message_allowed(id, intent, &topic, &message) { - continue - } - peer.known_messages.insert(message_hash.clone()); - trace!(target: "gossip", "Propagating to {}: {:?}", id, message); - protocol.send_consensus(id.clone(), message.clone()); - } - } -} - -/// Validates consensus messages. -pub trait Validator: Send + Sync { - /// New peer is connected. - fn new_peer(&self, _context: &mut dyn ValidatorContext, _who: &PeerId, _roles: Roles) { - } - - /// New connection is dropped. - fn peer_disconnected(&self, _context: &mut dyn ValidatorContext, _who: &PeerId) { - } - - /// Validate consensus message. - fn validate( - &self, - context: &mut dyn ValidatorContext, - sender: &PeerId, - 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| false) - } - - /// Produce a closure for filtering egress messages. - fn message_allowed<'a>(&'a self) -> Box bool + 'a> { - Box::new(move |_who, _intent, _topic, _data| true) - } -} - -/// Consensus network protocol handler. Manages statements and candidate requests. -pub struct ConsensusGossip { - peers: HashMap>, - live_message_sinks: HashMap<(ConsensusEngineId, B::Hash), Vec>>, - messages: Vec>, - known_messages: LruCache, - validators: HashMap>>, - next_broadcast: time::Instant, -} - -impl ConsensusGossip { - /// Create a new instance. - pub fn new() -> Self { - ConsensusGossip { - peers: HashMap::new(), - live_message_sinks: HashMap::new(), - messages: Default::default(), - known_messages: LruCache::new(KNOWN_MESSAGES_CACHE_SIZE), - validators: Default::default(), - next_broadcast: time::Instant::now() + REBROADCAST_INTERVAL, - } - } - - /// Closes all notification streams. - pub fn abort(&mut self) { - self.live_message_sinks.clear(); - } - - /// Register message validator for a message type. - pub fn register_validator( - &mut self, - protocol: &mut dyn Context, - engine_id: ConsensusEngineId, - validator: Arc> - ) { - self.register_validator_internal(engine_id, validator.clone()); - let peers: Vec<_> = self.peers.iter().map(|(id, peer)| (id.clone(), peer.roles)).collect(); - for (id, roles) in peers { - let mut context = NetworkContext { gossip: self, protocol, engine_id: engine_id.clone() }; - validator.new_peer(&mut context, &id, roles); - } - } - - fn register_validator_internal(&mut self, engine_id: ConsensusEngineId, validator: Arc>) { - self.validators.insert(engine_id, validator.clone()); - } - - /// Handle new connected peer. - pub fn new_peer(&mut self, protocol: &mut dyn Context, who: PeerId, roles: Roles) { - // light nodes are not valid targets for consensus gossip messages - if !roles.is_full() { - return; - } - - trace!(target:"gossip", "Registering {:?} {}", roles, who); - self.peers.insert(who.clone(), PeerConsensus { - known_messages: HashSet::new(), - roles, - }); - for (engine_id, v) in self.validators.clone() { - let mut context = NetworkContext { gossip: self, protocol, engine_id: engine_id.clone() }; - v.new_peer(&mut context, &who, roles); - } - } - - fn register_message_hashed( - &mut self, - message_hash: B::Hash, - topic: B::Hash, - message: ConsensusMessage, - sender: Option, - ) { - if self.known_messages.insert(message_hash.clone(), ()).is_none() { - self.messages.push(MessageEntry { - message_hash, - topic, - message, - sender, - }); - } - } - - /// Registers a message without propagating it to any peers. The message - /// becomes available to new peers or when the service is asked to gossip - /// the message's topic. No validation is performed on the message, if the - /// message is already expired it should be dropped on the next garbage - /// collection. - pub fn register_message( - &mut self, - topic: B::Hash, - message: ConsensusMessage, - ) { - let message_hash = HashFor::::hash(&message.data[..]); - self.register_message_hashed(message_hash, topic, message, None); - } - - /// Call when a peer has been disconnected to stop tracking gossip status. - pub fn peer_disconnected(&mut self, protocol: &mut dyn Context, who: PeerId) { - for (engine_id, v) in self.validators.clone() { - let mut context = NetworkContext { gossip: self, protocol, engine_id: engine_id.clone() }; - v.peer_disconnected(&mut context, &who); - } - } - - /// Perform periodic maintenance - pub fn tick(&mut self, protocol: &mut dyn Context) { - self.collect_garbage(); - if time::Instant::now() >= self.next_broadcast { - self.rebroadcast(protocol); - self.next_broadcast = time::Instant::now() + REBROADCAST_INTERVAL; - } - } - - /// Rebroadcast all messages to all peers. - fn rebroadcast(&mut self, protocol: &mut dyn Context) { - let messages = self.messages.iter() - .map(|entry| (&entry.message_hash, &entry.topic, &entry.message)); - propagate(protocol, messages, MessageIntent::PeriodicRebroadcast, &mut self.peers, &self.validators); - } - - /// Broadcast all messages with given topic. - pub fn broadcast_topic(&mut self, protocol: &mut dyn Context, topic: B::Hash, force: bool) { - let messages = self.messages.iter() - .filter_map(|entry| - if entry.topic == topic { Some((&entry.message_hash, &entry.topic, &entry.message)) } else { None } - ); - let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; - propagate(protocol, messages, intent, &mut self.peers, &self.validators); - } - - /// Prune old or no longer relevant consensus messages. Provide a predicate - /// for pruning, which returns `false` when the items with a given topic should be pruned. - pub fn collect_garbage(&mut self) { - self.live_message_sinks.retain(|_, sinks| { - sinks.retain(|sink| !sink.is_closed()); - !sinks.is_empty() - }); - - let known_messages = &mut self.known_messages; - let before = self.messages.len(); - let validators = &self.validators; - - let mut check_fns = HashMap::new(); - let mut message_expired = move |entry: &MessageEntry| { - let engine_id = entry.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| !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| known_messages.contains_key(h)); - } - } - - /// 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_mut() - .filter(|e| e.topic == topic && e.message.engine_id == engine_id) - { - tx.unbounded_send(TopicNotification { - message: entry.message.data.clone(), - sender: entry.sender.clone(), - }) - .expect("receiver known to be live; qed"); - } - - self.live_message_sinks.entry((engine_id, topic)).or_default().push(tx); - - rx - } - - /// Handle an incoming ConsensusMessage for topic by who via protocol. Discard message if topic - /// already known, the message is old, its source peers isn't a registered peer or the connection - /// to them is broken. Return `Some(topic, message)` if it was added to the internal queue, `None` - /// in all other cases. - pub fn on_incoming( - &mut self, - protocol: &mut dyn Context, - who: PeerId, - message: ConsensusMessage, - ) { - let message_hash = HashFor::::hash(&message.data[..]); - - if self.known_messages.contains_key(&message_hash) { - trace!(target:"gossip", "Ignored already known message from {}", who); - protocol.report_peer(who.clone(), DUPLICATE_GOSSIP_REPUTATION_CHANGE); - return; - } - - let engine_id = message.engine_id; - // validate the message - let validation = self.validators.get(&engine_id) - .cloned() - .map(|v| { - let mut context = NetworkContext { gossip: self, protocol, engine_id }; - v.validate(&mut context, &who, &message.data) - }); - - let validation_result = match validation { - Some(ValidationResult::ProcessAndKeep(topic)) => Some((topic, true)), - Some(ValidationResult::ProcessAndDiscard(topic)) => Some((topic, false)), - Some(ValidationResult::Discard) => None, - None => { - trace!(target:"gossip", "Unknown message engine id {:?} from {}", engine_id, who); - protocol.report_peer(who.clone(), UNKNOWN_GOSSIP_REPUTATION_CHANGE); - protocol.disconnect_peer(who); - return; - } - }; - - if let Some((topic, keep)) = validation_result { - protocol.report_peer(who.clone(), GOSSIP_SUCCESS_REPUTATION_CHANGE); - if let Some(ref mut peer) = self.peers.get_mut(&who) { - peer.known_messages.insert(message_hash); - if let Entry::Occupied(mut entry) = self.live_message_sinks.entry((engine_id, topic)) { - debug!(target: "gossip", "Pushing consensus message to sinks for {}.", topic); - entry.get_mut().retain(|sink| { - if let Err(e) = sink.unbounded_send(TopicNotification { - message: message.data.clone(), - sender: Some(who.clone()) - }) { - trace!(target: "gossip", "Error broadcasting message notification: {:?}", e); - } - !sink.is_closed() - }); - if entry.get().is_empty() { - entry.remove_entry(); - } - } - if keep { - self.register_message_hashed(message_hash, topic, message, Some(who.clone())); - } - } else { - trace!(target:"gossip", "Ignored statement from unregistered peer {}", who); - protocol.report_peer(who.clone(), UNREGISTERED_TOPIC_REPUTATION_CHANGE); - } - } else { - trace!(target:"gossip", "Handled valid one hop message from peer {}", who); - } - } - - /// Send all messages with given topic to a peer. - pub fn send_topic( - &mut self, - protocol: &mut dyn Context, - who: &PeerId, - topic: B::Hash, - engine_id: ConsensusEngineId, - force: bool - ) { - let validator = self.validators.get(&engine_id); - let mut message_allowed = match validator { - None => return, // treat all messages with no validator as not allowed - Some(validator) => validator.message_allowed(), - }; - - let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; - - if let Some(ref mut peer) = self.peers.get_mut(who) { - for entry in self.messages.iter().filter(|m| m.topic == topic && m.message.engine_id == engine_id) { - if !force && peer.known_messages.contains(&entry.message_hash) { - continue - } - if !message_allowed(who, intent, &entry.topic, &entry.message.data) { - continue - } - peer.known_messages.insert(entry.message_hash.clone()); - trace!(target: "gossip", "Sending topic message to {}: {:?}", who, entry.message); - protocol.send_consensus(who.clone(), ConsensusMessage { - engine_id: engine_id.clone(), - data: entry.message.data.clone(), - }); - } - } - } - - /// Multicast a message to all peers. - pub fn multicast( - &mut self, - protocol: &mut dyn Context, - topic: B::Hash, - message: ConsensusMessage, - force: bool, - ) { - let message_hash = HashFor::::hash(&message.data); - self.register_message_hashed(message_hash, topic, message.clone(), None); - let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; - propagate(protocol, iter::once((&message_hash, &topic, &message)), intent, &mut self.peers, &self.validators); - } - - /// Send addressed message to a peer. The message is not kept or multicast - /// later on. - pub fn send_message( - &mut self, - protocol: &mut dyn Context, - who: &PeerId, - message: ConsensusMessage, - ) { - let peer = match self.peers.get_mut(who) { - None => return, - Some(peer) => peer, - }; - - let message_hash = HashFor::::hash(&message.data); - - trace!(target: "gossip", "Sending direct to {}: {:?}", who, message); - - peer.known_messages.insert(message_hash); - protocol.send_consensus(who.clone(), message.clone()); - } -} - -/// A gossip message validator that discards all messages. -pub struct DiscardAll; - -impl Validator for DiscardAll { - fn validate( - &self, - _context: &mut dyn ValidatorContext, - _sender: &PeerId, - _data: &[u8], - ) -> ValidationResult { - ValidationResult::Discard - } - - fn message_expired<'a>(&'a self) -> Box bool + 'a> { - Box::new(move |_topic, _data| true) - } - - fn message_allowed<'a>(&'a self) -> Box bool + 'a> { - Box::new(move |_who, _intent, _topic, _data| false) - } -} - -#[cfg(test)] -mod tests { - use sr_primitives::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; - use futures03::executor::block_on_stream; - - use super::*; - - type Block = RawBlock>; - - macro_rules! push_msg { - ($consensus:expr, $topic:expr, $hash: expr, $m:expr) => { - if $consensus.known_messages.insert($hash, ()).is_none() { - $consensus.messages.push(MessageEntry { - message_hash: $hash, - topic: $topic, - message: ConsensusMessage { data: $m, engine_id: [0, 0, 0, 0]}, - sender: None, - }); - } - } - } - - struct AllowAll; - impl Validator for AllowAll { - fn validate( - &self, - _context: &mut dyn ValidatorContext, - _sender: &PeerId, - _data: &[u8], - ) -> ValidationResult { - ValidationResult::ProcessAndKeep(H256::default()) - } - } - - #[test] - fn collects_garbage() { - struct AllowOne; - impl Validator for AllowOne { - fn validate( - &self, - _context: &mut dyn ValidatorContext, - _sender: &PeerId, - data: &[u8], - ) -> ValidationResult { - if data[0] == 1 { - ValidationResult::ProcessAndKeep(H256::default()) - } else { - ValidationResult::Discard - } - } - - fn message_expired<'a>(&'a self) -> Box bool + 'a> { - Box::new(move |_topic, data| data[0] != 1 ) - } - } - - let prev_hash = H256::random(); - let best_hash = H256::random(); - let mut consensus = ConsensusGossip::::new(); - let m1_hash = H256::random(); - let m2_hash = H256::random(); - let m1 = vec![1, 2, 3]; - let m2 = vec![4, 5, 6]; - - push_msg!(consensus, prev_hash, m1_hash, m1); - push_msg!(consensus, best_hash, m2_hash, m2); - consensus.known_messages.insert(m1_hash, ()); - consensus.known_messages.insert(m2_hash, ()); - - let test_engine_id = Default::default(); - consensus.register_validator_internal(test_engine_id, Arc::new(AllowAll)); - consensus.collect_garbage(); - assert_eq!(consensus.messages.len(), 2); - assert_eq!(consensus.known_messages.len(), 2); - - consensus.register_validator_internal(test_engine_id, Arc::new(AllowOne)); - - // m2 is expired - consensus.collect_garbage(); - assert_eq!(consensus.messages.len(), 1); - // known messages are only pruned based on size. - assert_eq!(consensus.known_messages.len(), 2); - assert!(consensus.known_messages.contains_key(&m2_hash)); - } - - #[test] - fn message_stream_include_those_sent_before_asking_for_stream() { - let mut consensus = ConsensusGossip::::new(); - consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); - - let message = ConsensusMessage { data: vec![4, 5, 6], engine_id: [0, 0, 0, 0] }; - let topic = HashFor::::hash(&[1,2,3]); - - consensus.register_message(topic, message.clone()); - let mut stream = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); - - assert_eq!(stream.next(), Some(TopicNotification { message: message.data, sender: None })); - } - - #[test] - fn can_keep_multiple_messages_per_topic() { - let mut consensus = ConsensusGossip::::new(); - - 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, 0] }; - - consensus.register_message(topic, msg_a); - consensus.register_message(topic, msg_b); - - assert_eq!(consensus.messages.len(), 2); - } - - #[test] - fn can_keep_multiple_subscribers_per_topic() { - let mut consensus = ConsensusGossip::::new(); - consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); - - let data = vec![4, 5, 6]; - let message = ConsensusMessage { data: data.clone(), engine_id: [0, 0, 0, 0] }; - let topic = HashFor::::hash(&[1, 2, 3]); - - consensus.register_message(topic, message.clone()); - - let mut stream1 = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); - let mut stream2 = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); - - assert_eq!(stream1.next(), Some(TopicNotification { message: data.clone(), sender: None })); - assert_eq!(stream2.next(), Some(TopicNotification { message: data, sender: None })); - } - - #[test] - fn topics_are_localized_to_engine_id() { - let mut consensus = ConsensusGossip::::new(); - consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); - - let topic = [1; 32].into(); - let msg_a = 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(topic, msg_a); - consensus.register_message(topic, msg_b); - - let mut stream = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); - - assert_eq!(stream.next(), Some(TopicNotification { message: vec![1, 2, 3], sender: None })); - - let _ = consensus.live_message_sinks.remove(&([0, 0, 0, 0], topic)); - assert_eq!(stream.next(), None); - } -} diff --git a/core/network/src/protocol/event.rs b/core/network/src/protocol/event.rs deleted file mode 100644 index c8bee5588c704..0000000000000 --- a/core/network/src/protocol/event.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Network event types. These are are not the part of the protocol, but rather -//! events that happen on the network like DHT get/put results received. - -use libp2p::kad::record::Key; - -/// Events generated by DHT as a response to get_value and put_value requests. -#[derive(Debug, Clone)] -pub enum DhtEvent { - /// The value was found. - ValueFound(Vec<(Key, Vec)>), - - /// The requested record has not been found in the DHT. - ValueNotFound(Key), - - /// The record has been successfully inserted into the DHT. - ValuePut(Key), - - /// An error has occured while putting a record into the DHT. - ValuePutFailed(Key), -} - -/// Type for events generated by networking layer. -#[derive(Debug, Clone)] -pub enum Event { - /// Event generated by a DHT. - Dht(DhtEvent), -} diff --git a/core/network/src/protocol/sync.rs b/core/network/src/protocol/sync.rs deleted file mode 100644 index 4f08c942def1b..0000000000000 --- a/core/network/src/protocol/sync.rs +++ /dev/null @@ -1,1306 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. -// -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Contains the state of the chain synchronization process -//! -//! At any given point in time, a running node tries as much as possible to be at the head of the -//! chain. This module handles the logic of which blocks to request from remotes, and processing -//! responses. It yields blocks to check and potentially move to the database. -//! -//! # Usage -//! -//! The `ChainSync` struct maintains the state of the block requests. Whenever something happens on -//! the network, or whenever a block has been successfully verified, call the appropriate method in -//! order to update it. -//! - -use blocks::BlockCollection; -use client::{ClientInfo, error::Error as ClientError}; -use consensus::{BlockOrigin, BlockStatus, - block_validation::{BlockAnnounceValidator, Validation}, - import_queue::{IncomingBlock, BlockImportResult, BlockImportError} -}; -use crate::{ - config::{Roles, BoxFinalityProofRequestBuilder}, - message::{self, generic::FinalityProofRequest, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse, - FinalityProofResponse}, - protocol -}; -use either::Either; -use extra_requests::ExtraRequests; -use libp2p::PeerId; -use log::{debug, trace, warn, info, error}; -use sr_primitives::{ - Justification, - generic::BlockId, - traits::{Block as BlockT, Header, NumberFor, Zero, One, CheckedSub, SaturatedConversion} -}; -use std::{fmt, ops::Range, collections::{HashMap, HashSet, VecDeque}, sync::Arc}; - -mod blocks; -mod extra_requests; - -/// 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; - -/// We use a heuristic that with a high likelihood, by the time -/// `MAJOR_SYNC_BLOCKS` have been imported we'll be on the same -/// chain as (or at least closer to) the peer so we want to delay -/// the ancestor search to not waste time doing that when we are -/// so far behind. -const MAJOR_SYNC_BLOCKS: u8 = 5; - -/// Number of recently announced blocks to track for each peer. -const ANNOUNCE_HISTORY_SIZE: usize = 64; - -/// Reputation change when a peer sent us a status message that led to a -/// database read error. -const BLOCKCHAIN_STATUS_READ_ERROR_REPUTATION_CHANGE: i32 = -(1 << 16); - -/// Reputation change when a peer failed to answer our legitimate ancestry -/// block search. -const ANCESTRY_BLOCK_ERROR_REPUTATION_CHANGE: i32 = -(1 << 9); - -/// Reputation change when a peer sent us a status message with a different -/// genesis than us. -const GENESIS_MISMATCH_REPUTATION_CHANGE: i32 = i32::min_value() + 1; - -/// Reputation change for peers which send us a block with an incomplete header. -const INCOMPLETE_HEADER_REPUTATION_CHANGE: i32 = -(1 << 20); - -/// Reputation change for peers which send us a block which we fail to verify. -const VERIFICATION_FAIL_REPUTATION_CHANGE: i32 = -(1 << 20); - -/// Reputation change for peers which send us a bad block. -const BAD_BLOCK_REPUTATION_CHANGE: i32 = -(1 << 29); - -/// Reputation change for peers which send us a block with bad justifications. -const BAD_JUSTIFICATION_REPUTATION_CHANGE: i32 = -(1 << 16); - -/// The main data structure which contains all the state for a chains -/// active syncing strategy. -pub struct ChainSync { - /// Chain client. - client: Arc>, - /// The active peers that we are using to sync and their PeerSync status - peers: HashMap>, - /// A `BlockCollection` of blocks that are being downloaded from peers - blocks: BlockCollection, - /// The best block number in our queue of blocks to import - best_queued_number: NumberFor, - /// The best block hash in our queue of blocks to import - best_queued_hash: B::Hash, - /// The role of this node, e.g. light or full - role: Roles, - /// What block attributes we require for this node, usually derived from - /// what role we are, but could be customized - required_block_attributes: message::BlockAttributes, - /// Any extra finality proof requests. - extra_finality_proofs: ExtraRequests, - /// Any extra justification requests. - extra_justifications: ExtraRequests, - /// A set of hashes of blocks that are being downloaded or have been - /// downloaded and are queued for import. - queue_blocks: HashSet, - /// The best block number that we are currently importing. - best_importing_number: NumberFor, - /// Finality proof handler. - request_builder: Option>, - /// Fork sync targets. - fork_targets: HashMap>, - /// A flag that caches idle state with no pending requests. - is_idle: bool, - /// A type to check incoming block announcements. - block_announce_validator: Box + Send> -} - -/// All the data we have about a Peer that we are trying to sync with -#[derive(Debug, Clone)] -pub struct PeerSync { - /// The common number is the block number that is a common point of - /// ancestry for both our chains (as far as we know). - pub common_number: NumberFor, - /// The hash of the best block that we've seen for this peer. - pub best_hash: B::Hash, - /// The number of the best block that we've seen for this peer. - pub best_number: NumberFor, - /// The state of syncing this peer is in for us, generally categories - /// into `Available` or "busy" with something as defined by `PeerSyncState`. - pub state: PeerSyncState, - /// A queue of blocks that this peer has announced to us, should only - /// contain `ANNOUNCE_HISTORY_SIZE` entries. - pub recently_announced: VecDeque -} - -/// The sync status of a peer we are trying to sync with -#[derive(Debug)] -pub struct PeerInfo { - /// Their best block hash. - pub best_hash: B::Hash, - /// Their best block number. - pub best_number: NumberFor -} - -struct ForkTarget { - number: NumberFor, - parent_hash: Option, - peers: HashSet, -} - -/// The state of syncing between a Peer and ourselves. -/// -/// Generally two categories, "busy" or `Available`. If busy, the enum -/// defines what we are busy with. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum PeerSyncState { - /// Available for sync requests. - Available, - /// Searching for ancestors the Peer has in common with us. - AncestorSearch(NumberFor, AncestorSearchState), - /// Actively downloading new blocks, starting from the given Number. - DownloadingNew(NumberFor), - /// Downloading a stale block with given Hash. Stale means that it is a - /// block with a number that is lower than our best number. It might be - /// from a fork and not necessarily already imported. - DownloadingStale(B::Hash), - /// Downloading justification for given block hash. - DownloadingJustification(B::Hash), - /// Downloading finality proof for given block hash. - DownloadingFinalityProof(B::Hash) -} - -impl PeerSyncState { - pub fn is_available(&self) -> bool { - if let PeerSyncState::Available = self { - true - } else { - false - } - } -} - -/// Reported sync state. -#[derive(Clone, Eq, PartialEq, Debug)] -pub enum SyncState { - /// Initial sync is complete, keep-up sync is active. - Idle, - /// Actively catching up with the chain. - Downloading -} - -/// Syncing status and statistics. -#[derive(Clone)] -pub struct Status { - /// Current global sync state. - pub state: SyncState, - /// Target sync block number. - pub best_seen_block: Option>, - /// Number of peers participating in syncing. - pub num_peers: u32, - /// Number of blocks queued for import - pub queued_blocks: u32, -} - -/// A peer did not behave as expected and should be reported. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct BadPeer(pub PeerId, pub i32); - -impl fmt::Display for BadPeer { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "bad peer {}; reputation change: {}", self.0, self.1) - } -} - -impl std::error::Error for BadPeer {} - -/// Result of [`ChainSync::on_block_data`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum OnBlockData { - /// The block should be imported. - Import(BlockOrigin, Vec>), - /// A new block request needs to be made to the given peer. - Request(PeerId, BlockRequest) -} - -/// Result of [`ChainSync::on_block_announce`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum OnBlockAnnounce { - /// The announcement does not require further handling. - Nothing, - /// The announcement header should be imported. - ImportHeader, -} - -/// Result of [`ChainSync::on_block_justification`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum OnBlockJustification { - /// The justification needs no further handling. - Nothing, - /// The justification should be imported. - Import { - peer: PeerId, - hash: B::Hash, - number: NumberFor, - justification: Justification - } -} - -/// Result of [`ChainSync::on_block_finality_proof`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum OnBlockFinalityProof { - /// The proof needs no further handling. - Nothing, - /// The proof should be imported. - Import { - peer: PeerId, - hash: B::Hash, - number: NumberFor, - proof: Vec - } -} - -impl ChainSync { - /// Create a new instance. - pub fn new( - role: Roles, - client: Arc>, - info: &ClientInfo, - request_builder: Option>, - block_announce_validator: Box + Send> - ) -> Self { - let mut required_block_attributes = BlockAttributes::HEADER | BlockAttributes::JUSTIFICATION; - - if role.is_full() { - required_block_attributes |= BlockAttributes::BODY - } - - ChainSync { - client, - peers: HashMap::new(), - blocks: BlockCollection::new(), - best_queued_hash: info.chain.best_hash, - best_queued_number: info.chain.best_number, - extra_finality_proofs: ExtraRequests::new(), - extra_justifications: ExtraRequests::new(), - role, - required_block_attributes, - queue_blocks: Default::default(), - best_importing_number: Zero::zero(), - request_builder, - fork_targets: Default::default(), - is_idle: false, - block_announce_validator, - } - } - - /// Returns the state of the sync of the given peer. - /// - /// Returns `None` if the peer is unknown. - pub fn peer_info(&self, who: &PeerId) -> Option> { - self.peers.get(who).map(|p| PeerInfo { best_hash: p.best_hash, best_number: p.best_number }) - } - - /// Returns the current sync status. - pub fn status(&self) -> Status { - let best_seen = self.peers.values().max_by_key(|p| p.best_number).map(|p| p.best_number); - let sync_state = - if let Some(n) = best_seen { - // A chain is classified as downloading if the provided best block is - // more than `MAJOR_SYNC_BLOCKS` behind the best queued block. - if n > self.best_queued_number && n - self.best_queued_number > MAJOR_SYNC_BLOCKS.into() { - SyncState::Downloading - } else { - SyncState::Idle - } - } else { - SyncState::Idle - }; - - Status { - state: sync_state, - best_seen_block: best_seen, - num_peers: self.peers.len() as u32, - queued_blocks: self.queue_blocks.len() as u32, - } - } - - /// Handle a new connected peer. - /// - /// Call this method whenever we connect to a new peer. - pub fn new_peer(&mut self, who: PeerId, info: protocol::PeerInfo) -> Result>, BadPeer> { - // There is nothing sync can get from the node that has no blockchain data. - if !info.roles.is_full() { - return Ok(None) - } - match self.block_status(&info.best_hash) { - Err(e) => { - debug!(target:"sync", "Error reading blockchain: {:?}", e); - Err(BadPeer(who, BLOCKCHAIN_STATUS_READ_ERROR_REPUTATION_CHANGE)) - } - Ok(BlockStatus::KnownBad) => { - info!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number); - Err(BadPeer(who, i32::min_value())) - } - Ok(BlockStatus::Unknown) => { - if info.best_number.is_zero() { - info!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number); - return Err(BadPeer(who, i32::min_value())) - } - // If there are more than `MAJOR_SYNC_BLOCKS` in the import queue then we have - // enough to do in the import queue that it's not worth kicking off - // an ancestor search, which is what we do in the next match case below. - if self.queue_blocks.len() > MAJOR_SYNC_BLOCKS.into() { - 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() - }); - return Ok(None) - } - - // If we are at genesis, just start downloading. - if self.best_queued_number.is_zero() { - debug!(target:"sync", "New peer with best hash {} ({}).", info.best_hash, info.best_number); - self.peers.insert(who.clone(), PeerSync { - common_number: Zero::zero(), - best_hash: info.best_hash, - best_number: info.best_number, - state: PeerSyncState::Available, - recently_announced: Default::default(), - }); - return Ok(self.select_new_blocks(who).map(|(_, req)| req)) - } - - let common_best = std::cmp::min(self.best_queued_number, 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_number: Zero::zero(), - best_hash: info.best_hash, - best_number: info.best_number, - state: PeerSyncState::AncestorSearch( - common_best, - AncestorSearchState::ExponentialBackoff(One::one()) - ), - recently_announced: Default::default() - }); - self.is_idle = false; - - Ok(Some(ancestry_request::(common_best))) - } - Ok(BlockStatus::Queued) | Ok(BlockStatus::InChainWithState) | Ok(BlockStatus::InChainPruned) => { - debug!(target:"sync", "New peer with known best hash {} ({}).", info.best_hash, info.best_number); - self.peers.insert(who.clone(), PeerSync { - common_number: info.best_number, - best_hash: info.best_hash, - best_number: info.best_number, - state: PeerSyncState::Available, - recently_announced: Default::default(), - }); - self.is_idle = false; - Ok(None) - } - } - } - - /// Signal that `best_header` has been queued for import and update the - /// `ChainSync` state with that information. - pub fn update_chain_info(&mut self, best_header: &B::Header) { - self.on_block_queued(&best_header.hash(), *best_header.number()) - } - - /// Schedule a justification request for the given block. - pub fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { - let client = &self.client; - self.extra_justifications.schedule((*hash, number), |base, block| { - client.is_descendent_of(base, block) - }) - } - - /// Schedule a finality proof request for the given block. - pub fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { - let client = &self.client; - self.extra_finality_proofs.schedule((*hash, number), |base, block| { - client.is_descendent_of(base, block) - }) - } - - /// Request syncing for the given block from given set of peers. - // The implementation is similar to on_block_announce with unknown parent hash. - pub fn set_sync_fork_request(&mut self, mut peers: Vec, hash: &B::Hash, number: NumberFor) { - if peers.is_empty() { - debug!( - target: "sync", - "Explicit sync request for block {:?} with no peers specified. \ - Syncing from all connected peers {:?} instead.", - hash, peers, - ); - - peers = self.peers.iter() - // Only request blocks from peers who are ahead or on a par. - .filter(|(_, peer)| peer.best_number >= number) - .map(|(id, _)| id.clone()) - .collect(); - } else { - debug!(target: "sync", "Explicit sync request for block {:?} with {:?}", hash, peers); - } - - if self.is_known(&hash) { - debug!(target: "sync", "Refusing to sync known hash {:?}", hash); - return; - } - - let block_status = self.client.block_status(&BlockId::Number(number - One::one())) - .unwrap_or(BlockStatus::Unknown); - if block_status == BlockStatus::InChainPruned { - trace!(target: "sync", "Refusing to sync ancient block {:?}", hash); - return; - } - - self.is_idle = false; - for peer_id in &peers { - if let Some(peer) = self.peers.get_mut(peer_id) { - if let PeerSyncState::AncestorSearch(_, _) = peer.state { - continue; - } - - if number > peer.best_number { - peer.best_number = number; - peer.best_hash = hash.clone(); - } - } - } - - self.fork_targets - .entry(hash.clone()) - .or_insert_with(|| ForkTarget { - number, - peers: Default::default(), - parent_hash: None, - }) - .peers.extend(peers); - } - - /// Get an iterator over all scheduled justification requests. - pub fn justification_requests(&mut self) -> impl Iterator)> + '_ { - let peers = &mut self.peers; - let mut matcher = self.extra_justifications.matcher(); - std::iter::from_fn(move || { - if let Some((peer, request)) = matcher.next(&peers) { - peers.get_mut(&peer) - .expect("`Matcher::next` guarantees the `PeerId` comes from the given peers; qed") - .state = PeerSyncState::DownloadingJustification(request.0); - let req = message::generic::BlockRequest { - id: 0, - fields: BlockAttributes::JUSTIFICATION, - from: message::FromBlock::Hash(request.0), - to: None, - direction: message::Direction::Ascending, - max: Some(1) - }; - Some((peer, req)) - } else { - None - } - }) - } - - /// Get an iterator over all scheduled finality proof requests. - pub fn finality_proof_requests(&mut self) -> impl Iterator)> + '_ { - let peers = &mut self.peers; - let request_builder = &mut self.request_builder; - let mut matcher = self.extra_finality_proofs.matcher(); - std::iter::from_fn(move || { - if let Some((peer, request)) = matcher.next(&peers) { - peers.get_mut(&peer) - .expect("`Matcher::next` guarantees the `PeerId` comes from the given peers; qed") - .state = PeerSyncState::DownloadingFinalityProof(request.0); - let req = message::generic::FinalityProofRequest { - id: 0, - block: request.0, - request: request_builder.as_mut() - .map(|builder| builder.build_request_data(&request.0)) - .unwrap_or_default() - }; - Some((peer, req)) - } else { - None - } - }) - } - - /// Get an iterator over all block requests of all peers. - pub fn block_requests(&mut self) -> impl Iterator)> + '_ { - if self.is_idle { - return Either::Left(std::iter::empty()) - } - if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { - trace!(target: "sync", "Too many blocks in the queue."); - return Either::Left(std::iter::empty()) - } - let blocks = &mut self.blocks; - let attrs = &self.required_block_attributes; - let fork_targets = &self.fork_targets; - let mut have_requests = false; - let last_finalized = self.client.info().chain.finalized_number; - let best_queued = self.best_queued_number; - let client = &self.client; - let queue = &self.queue_blocks; - let iter = self.peers.iter_mut().filter_map(move |(id, peer)| { - if !peer.state.is_available() { - trace!(target: "sync", "Peer {} is busy", id); - return None - } - if let Some((hash, req)) = fork_sync_request( - id, - fork_targets, - best_queued, - last_finalized, - attrs, - |hash| if queue.contains(hash) { - BlockStatus::Queued - } else { - client.block_status(&BlockId::Hash(*hash)).unwrap_or(BlockStatus::Unknown) - }, - ) { - trace!(target: "sync", "Downloading fork {:?} from {}", hash, id); - peer.state = PeerSyncState::DownloadingStale(hash); - have_requests = true; - Some((id.clone(), req)) - } else if let Some((range, req)) = peer_block_request(id, peer, blocks, attrs) { - peer.state = PeerSyncState::DownloadingNew(range.start); - trace!(target: "sync", "New block request for {}", id); - have_requests = true; - Some((id.clone(), req)) - } else { - trace!(target: "sync", "No new block request for {}", id); - None - } - }); - if !have_requests { - self.is_idle = true; - } - Either::Right(iter) - } - - /// Handle a response from the remote to a block request that we made. - /// - /// `request` must be the original request that triggered `response`. - /// - /// If this corresponds to a valid block, this outputs the block that - /// must be imported in the import queue. - pub fn on_block_data - (&mut self, who: PeerId, request: BlockRequest, response: BlockResponse) -> Result, BadPeer> - { - let new_blocks: Vec> = - if let Some(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() - } - self.is_idle = false; - match &mut peer.state { - PeerSyncState::DownloadingNew(start_block) => { - self.blocks.clear_peer_download(&who); - self.blocks.insert(*start_block, blocks, who); - peer.state = PeerSyncState::Available; - self.blocks - .drain(self.best_queued_number + One::one()) - .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; - blocks.into_iter().map(|b| { - IncomingBlock { - hash: b.hash, - header: b.header, - body: b.body, - justification: b.justification, - origin: Some(who.clone()), - } - }).collect() - } - PeerSyncState::AncestorSearch(num, state) => { - let block_hash_match = match (blocks.get(0), self.client.block_hash(*num)) { - (Some(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, _) => { - debug!(target: "sync", "Invalid response when searching for ancestor from {}", who); - return Err(BadPeer(who, i32::min_value())) - }, - (_, Err(e)) => { - info!("Error answering legitimate blockchain query: {:?}", e); - return Err(BadPeer(who, ANCESTRY_BLOCK_ERROR_REPUTATION_CHANGE)) - } - }; - if block_hash_match && peer.common_number < *num { - peer.common_number = *num; - } - if !block_hash_match && num.is_zero() { - trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who); - return Err(BadPeer(who, GENESIS_MISMATCH_REPUTATION_CHANGE)) - } - if let Some((next_state, next_num)) = handle_ancestor_search_state(state, *num, block_hash_match) { - peer.state = PeerSyncState::AncestorSearch(next_num, next_state); - return Ok(OnBlockData::Request(who, ancestry_request::(next_num))) - } else { - // Ancestry search is complete. Check if peer is on a stale fork unknown to us and - // add it to sync targets if necessary. - trace!(target: "sync", "Ancestry search complete. Ours={} ({}), Theirs={} ({}), Common={}", - self.best_queued_hash, - self.best_queued_number, - peer.best_hash, - peer.best_number, - peer.common_number - ); - if peer.common_number < peer.best_number && peer.best_number < self.best_queued_number { - trace!(target: "sync", "Added fork target {} for {}" , peer.best_hash, who); - self.fork_targets - .entry(peer.best_hash.clone()) - .or_insert_with(|| ForkTarget { - number: peer.best_number, - parent_hash: None, - peers: Default::default(), - }) - .peers.insert(who); - } - peer.state = PeerSyncState::Available; - Vec::new() - } - } - - | PeerSyncState::Available - | PeerSyncState::DownloadingJustification(..) - | PeerSyncState::DownloadingFinalityProof(..) => Vec::new() - } - } else { - Vec::new() - }; - - 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((h, n)) = new_blocks.last().and_then(|b| b.header.as_ref().map(|h| (&b.hash, *h.number()))) { - trace!(target:"sync", "Accepted {} blocks ({:?}) with origin {:?}", new_blocks.len(), h, origin); - self.on_block_queued(h, n) - } - - let new_best_importing_number = new_blocks.last() - .and_then(|b| b.header.as_ref().map(|h| *h.number())) - .unwrap_or_else(|| Zero::zero()); - - self.queue_blocks.extend(new_blocks.iter().map(|b| b.hash)); - - self.best_importing_number = std::cmp::max(new_best_importing_number, self.best_importing_number); - - Ok(OnBlockData::Import(origin, new_blocks)) - } - - /// Handle a response from the remote to a justification request that we made. - /// - /// `request` must be the original request that triggered `response`. - /// - /// Returns `Some` if this produces a justification that must be imported - /// into the import queue. - pub fn on_block_justification - (&mut self, who: PeerId, response: BlockResponse) -> Result, BadPeer> - { - let peer = - if let Some(peer) = self.peers.get_mut(&who) { - peer - } else { - error!(target: "sync", "Called on_block_justification with a bad peer ID"); - return Ok(OnBlockJustification::Nothing) - }; - - self.is_idle = false; - if let PeerSyncState::DownloadingJustification(hash) = peer.state { - peer.state = PeerSyncState::Available; - - // We only request one justification at a time - if let Some(block) = response.blocks.into_iter().next() { - if hash != block.hash { - info!( - "Invalid block justification provided by {}: requested: {:?} got: {:?}", who, hash, block.hash - ); - return Err(BadPeer(who, i32::min_value())) - } - if let Some((peer, hash, number, j)) = self.extra_justifications.on_response(who, block.justification) { - return Ok(OnBlockJustification::Import { peer, hash, number, justification: j }) - } - } else { - // 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) - } - } - - Ok(OnBlockJustification::Nothing) - } - - /// Handle new finality proof data. - pub fn on_block_finality_proof - (&mut self, who: PeerId, resp: FinalityProofResponse) -> Result, BadPeer> - { - let peer = - if let Some(peer) = self.peers.get_mut(&who) { - peer - } else { - error!(target: "sync", "Called on_block_finality_proof_data with a bad peer ID"); - return Ok(OnBlockFinalityProof::Nothing) - }; - - self.is_idle = false; - if let PeerSyncState::DownloadingFinalityProof(hash) = peer.state { - peer.state = PeerSyncState::Available; - - // We only request one finality proof at a time. - if hash != resp.block { - info!("Invalid block finality proof provided: requested: {:?} got: {:?}", hash, resp.block); - return Err(BadPeer(who, i32::min_value())) - } - - if let Some((peer, hash, number, p)) = self.extra_finality_proofs.on_response(who, resp.proof) { - return Ok(OnBlockFinalityProof::Import { peer, hash, number, proof: p }) - } - } - - Ok(OnBlockFinalityProof::Nothing) - } - - /// A batch of blocks have been processed, with or without errors. - /// - /// Call this when a batch of blocks have been processed by the import - /// queue, with or without errors. - /// - /// `peer_info` is passed in case of a restart. - pub fn on_blocks_processed<'a>( - &'a mut self, - imported: usize, - count: usize, - results: Vec<(Result>, BlockImportError>, B::Hash)>, - mut peer_info: impl FnMut(&PeerId) -> Option> - ) -> impl Iterator), BadPeer>> + 'a { - trace!(target: "sync", "Imported {} of {}", imported, count); - - let mut output = Vec::new(); - - 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; - } - - match result { - Ok(BlockImportResult::ImportedKnown(_number)) => {} - Ok(BlockImportResult::ImportedUnknown(number, aux, who)) => { - if aux.clear_justification_requests { - trace!( - target: "sync", - "Block imported clears all pending justification requests {}: {:?}", - number, - hash - ); - self.extra_justifications.reset() - } - - if aux.needs_justification { - trace!(target: "sync", "Block imported but requires justification {}: {:?}", number, hash); - self.request_justification(&hash, number); - } - - if aux.bad_justification { - if let Some(peer) = who { - info!("Sent block with bad justification to import"); - output.push(Err(BadPeer(peer, BAD_JUSTIFICATION_REPUTATION_CHANGE))); - } - } - - if aux.needs_finality_proof { - trace!(target: "sync", "Block imported but requires finality proof {}: {:?}", number, hash); - self.request_finality_proof(&hash, number); - } - }, - Err(BlockImportError::IncompleteHeader(who)) => { - if let Some(peer) = who { - info!("Peer sent block with incomplete header to import"); - output.push(Err(BadPeer(peer, INCOMPLETE_HEADER_REPUTATION_CHANGE))); - output.extend(self.restart(&mut peer_info)); - } - }, - Err(BlockImportError::VerificationFailed(who, e)) => { - if let Some(peer) = who { - info!("Verification failed from peer: {}", e); - output.push(Err(BadPeer(peer, VERIFICATION_FAIL_REPUTATION_CHANGE))); - output.extend(self.restart(&mut peer_info)); - } - }, - Err(BlockImportError::BadBlock(who)) => { - if let Some(peer) = who { - info!("Bad block"); - output.push(Err(BadPeer(peer, BAD_BLOCK_REPUTATION_CHANGE))); - output.extend(self.restart(&mut peer_info)); - } - }, - Err(BlockImportError::UnknownParent) | - Err(BlockImportError::Cancelled) | - Err(BlockImportError::Other(_)) => { - output.extend(self.restart(&mut peer_info)); - }, - }; - } - - for hash in hashes { - self.queue_blocks.remove(&hash); - } - if has_error { - self.best_importing_number = Zero::zero() - } - - self.is_idle = false; - output.into_iter() - } - - /// Call this when a justification has been processed by the import queue, - /// with or without errors. - pub fn on_justification_import(&mut self, hash: B::Hash, number: NumberFor, success: bool) { - let finalization_result = if success { Ok((hash, number)) } else { Err(()) }; - self.extra_justifications.try_finalize_root((hash, number), finalization_result, true); - self.is_idle = false; - } - - pub fn on_finality_proof_import(&mut self, req: (B::Hash, NumberFor), res: Result<(B::Hash, NumberFor), ()>) { - self.extra_finality_proofs.try_finalize_root(req, res, true); - self.is_idle = false; - } - - /// Notify about finalization of the given block. - pub fn on_block_finalized(&mut self, hash: &B::Hash, number: NumberFor) { - let client = &self.client; - let r = self.extra_finality_proofs.on_block_finalized(hash, number, |base, block| { - client.is_descendent_of(base, block) - }); - - if let Err(err) = r { - warn!(target: "sync", "Error cleaning up pending extra finality proof data requests: {:?}", err) - } - - let client = &self.client; - let r = self.extra_justifications.on_block_finalized(hash, number, |base, block| { - client.is_descendent_of(base, block) - }); - - if let Err(err) = r { - warn!(target: "sync", "Error cleaning up pending extra justification data requests: {:?}", err); - } - } - - /// Called when a block has been queued for import. - /// - /// Updates our internal state for best queued block and then goes - /// through all peers to update our view of their state as well. - fn on_block_queued(&mut self, hash: &B::Hash, number: NumberFor) { - if number > self.best_queued_number { - self.best_queued_number = number; - self.best_queued_hash = *hash; - } - if let Some(_) = self.fork_targets.remove(&hash) { - trace!(target: "sync", "Completed fork sync {:?}", hash); - } - // Update common blocks - for (n, peer) in self.peers.iter_mut() { - if let PeerSyncState::AncestorSearch(_, _) = peer.state { - // Wait for ancestry search to complete first. - continue; - } - let new_common_number = if peer.best_number >= number { - number - } else { - peer.best_number - }; - trace!( - target: "sync", - "Updating peer {} info, ours={}, common={}->{}, their best={}", - n, - number, - peer.common_number, - new_common_number, - peer.best_number, - ); - peer.common_number = new_common_number; - } - self.is_idle = false; - } - - /// Call when a node announces a new block. - /// - /// If `OnBlockAnnounce::ImportHeader` is returned, then the caller MUST try to import passed - /// header (call `on_block_data`). The network request isn't sent - /// in this case. Both hash and header is passed as an optimization - /// to avoid rehashing the header. - pub fn on_block_announce(&mut self, who: PeerId, hash: B::Hash, announce: &BlockAnnounce, is_best: bool) - -> OnBlockAnnounce - { - let header = &announce.header; - let number = *header.number(); - debug!(target: "sync", "Received block announcement with number {:?}", number); - if number.is_zero() { - warn!(target: "sync", "Ignored genesis block (#0) announcement from {}: {}", who, hash); - return OnBlockAnnounce::Nothing - } - let parent_status = self.block_status(header.parent_hash()).ok().unwrap_or(BlockStatus::Unknown); - let known_parent = parent_status != BlockStatus::Unknown; - let ancient_parent = parent_status == BlockStatus::InChainPruned; - - let known = self.is_known(&hash); - let peer = if let Some(peer) = self.peers.get_mut(&who) { - peer - } else { - error!(target: "sync", "Called on_block_announce with a bad peer ID"); - return OnBlockAnnounce::Nothing - }; - while peer.recently_announced.len() >= ANNOUNCE_HISTORY_SIZE { - peer.recently_announced.pop_front(); - } - peer.recently_announced.push_back(hash.clone()); - if is_best && number > peer.best_number { - // update their best block - peer.best_number = number; - peer.best_hash = hash; - } - if let PeerSyncState::AncestorSearch(_, _) = peer.state { - return OnBlockAnnounce::Nothing - } - // If the announced block is the best they have seen, our common number - // is either one further ahead or it's the one they just announced, if we know about it. - if known && is_best { - peer.common_number = number - } else if header.parent_hash() == &self.best_queued_hash || known_parent { - peer.common_number = number - One::one(); - } - self.is_idle = false; - - // known block case - if known || self.is_already_downloading(&hash) { - trace!(target: "sync", "Known block announce from {}: {}", who, hash); - if let Some(target) = self.fork_targets.get_mut(&hash) { - target.peers.insert(who); - } - return OnBlockAnnounce::Nothing - } - - // Let external validator check the block announcement. - let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice()); - match self.block_announce_validator.validate(&header, assoc_data) { - Ok(Validation::Success) => (), - Ok(Validation::Failure) => { - debug!(target: "sync", "Block announcement validation of block {} from {} failed", hash, who); - return OnBlockAnnounce::Nothing - } - Err(e) => { - error!(target: "sync", "Block announcement validation errored: {}", e); - return OnBlockAnnounce::Nothing - } - } - - if ancient_parent { - trace!(target: "sync", "Ignored ancient block announced from {}: {} {:?}", who, hash, header); - return OnBlockAnnounce::Nothing - } - - let requires_additional_data = !self.role.is_light() || !known_parent; - if !requires_additional_data { - trace!(target: "sync", "Importing new header announced from {}: {} {:?}", who, hash, header); - return OnBlockAnnounce::ImportHeader - } - - if number <= self.best_queued_number { - trace!( - target: "sync", - "Added sync target for block announced from {}: {} {:?}", who, hash, header - ); - self.fork_targets - .entry(hash.clone()) - .or_insert_with(|| ForkTarget { - number, - parent_hash: Some(header.parent_hash().clone()), - peers: Default::default(), - }) - .peers.insert(who); - } - - OnBlockAnnounce::Nothing - } - - /// Call when a peer has disconnected. - pub fn peer_disconnected(&mut self, who: PeerId) { - self.blocks.clear_peer_download(&who); - self.peers.remove(&who); - self.extra_justifications.peer_disconnected(&who); - self.extra_finality_proofs.peer_disconnected(&who); - self.is_idle = false; - } - - /// Restart the sync process. - fn restart<'a, F> - (&'a mut self, mut peer_info: F) -> impl Iterator), BadPeer>> + 'a - where F: FnMut(&PeerId) -> Option> + 'a - { - self.queue_blocks.clear(); - self.best_importing_number = Zero::zero(); - self.blocks.clear(); - let info = self.client.info(); - self.best_queued_hash = info.chain.best_hash; - self.best_queued_number = info.chain.best_number; - self.is_idle = false; - debug!(target:"sync", "Restarted with {} ({})", self.best_queued_number, self.best_queued_hash); - let old_peers = std::mem::replace(&mut self.peers, HashMap::new()); - old_peers.into_iter().filter_map(move |(id, _)| { - let info = peer_info(&id)?; - match self.new_peer(id.clone(), info) { - Ok(None) => None, - Ok(Some(x)) => Some(Ok((id, x))), - Err(e) => Some(Err(e)) - } - }) - } - - /// Select a range of new blocks to download from the given peer. - fn select_new_blocks(&mut self, who: PeerId) -> Option<(Range>, BlockRequest)> { - // when there are too many blocks in the queue => do not try to download new blocks - if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { - trace!(target: "sync", "Too many blocks in the queue."); - return None - } - - let peer = self.peers.get_mut(&who)?; - - if !peer.state.is_available() { - trace!(target: "sync", "Peer {} is busy", who); - return None - } - - trace!( - target: "sync", - "Considering new block download from {}, common block is {}, best is {:?}", - who, - peer.common_number, - peer.best_number - ); - - if let Some((range, req)) = peer_block_request(&who, peer, &mut self.blocks, &self.required_block_attributes) { - trace!(target: "sync", "Requesting blocks from {}, ({} to {})", who, range.start, range.end); - peer.state = PeerSyncState::DownloadingNew(range.start); - Some((range, req)) - } else { - trace!(target: "sync", "Nothing to request from {}", who); - None - } - } - - /// What is the status of the block corresponding to the given hash? - fn block_status(&self, hash: &B::Hash) -> Result { - if self.queue_blocks.contains(hash) { - return Ok(BlockStatus::Queued) - } - self.client.block_status(&BlockId::Hash(*hash)) - } - - /// Is the block corresponding to the given hash known? - fn is_known(&self, hash: &B::Hash) -> bool { - self.block_status(hash).ok().map_or(false, |s| s != BlockStatus::Unknown) - } - - /// Is any peer downloading the given hash? - fn is_already_downloading(&self, hash: &B::Hash) -> bool { - self.peers.iter().any(|(_, p)| p.state == PeerSyncState::DownloadingStale(*hash)) - } -} - -/// Request the ancestry for a block. Sends a request for header and justification for the given -/// block number. Used during ancestry search. -fn ancestry_request(block: NumberFor) -> BlockRequest { - message::generic::BlockRequest { - id: 0, - fields: BlockAttributes::HEADER | BlockAttributes::JUSTIFICATION, - from: message::FromBlock::Number(block), - to: None, - direction: message::Direction::Ascending, - max: Some(1) - } -} - -/// The ancestor search state expresses which algorithm, and its stateful parameters, we are using to -/// try to find an ancestor block -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub 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), -} - -/// This function handles the ancestor search strategy used. The goal is to find a common point -/// that both our chains agree on that is as close to the tip as possible. -/// The way this works is we first have an exponential backoff strategy, where we try to step -/// forward until we find a block hash mismatch. The size of the step doubles each step we take. -/// -/// When we've found a block hash mismatch we then fall back to a binary search between the two -/// last known points to find the common block closest to the tip. -fn handle_ancestor_search_state( - state: &AncestorSearchState, - curr_block_num: NumberFor, - block_hash_match: bool -) -> Option<(AncestorSearchState, NumberFor)> { - let two = >::one() + >::one(); - match state { - AncestorSearchState::ExponentialBackoff(next_distance_to_tip) => { - let next_distance_to_tip = *next_distance_to_tip; - if block_hash_match && next_distance_to_tip == One::one() { - // 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 / two; - let middle = left + (right - left) / two; - Some((AncestorSearchState::BinarySearch(left, right), middle)) - } else { - let next_block_num = curr_block_num.checked_sub(&next_distance_to_tip) - .unwrap_or_else(Zero::zero); - let next_distance_to_tip = next_distance_to_tip * two; - 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) / two; - Some((AncestorSearchState::BinarySearch(left, right), middle)) - } - } -} - -/// Get a new block request for the peer if any. -fn peer_block_request( - id: &PeerId, - peer: &PeerSync, - blocks: &mut BlockCollection, - attrs: &message::BlockAttributes, -) -> Option<(Range>, BlockRequest)> { - if let Some(range) = blocks.needed_blocks(id.clone(), MAX_BLOCKS_TO_REQUEST, peer.best_number, peer.common_number) { - let request = message::generic::BlockRequest { - id: 0, - fields: attrs.clone(), - from: message::FromBlock::Number(range.start), - to: None, - direction: message::Direction::Ascending, - max: Some((range.end - range.start).saturated_into::()) - }; - Some((range, request)) - } else { - None - } -} - -/// Get pending fork sync targets for a peer. -fn fork_sync_request( - id: &PeerId, - targets: &HashMap>, - best_num: NumberFor, - finalized: NumberFor, - attributes: &message::BlockAttributes, - check_block: impl Fn(&B::Hash) -> BlockStatus, -) -> Option<(B::Hash, BlockRequest)> -{ - for (hash, r) in targets { - if !r.peers.contains(id) { - continue - } - if r.number <= best_num { - trace!(target: "sync", "Downloading requested fork {:?} from {}", hash, id); - let parent_status = r.parent_hash.as_ref().map_or(BlockStatus::Unknown, check_block); - let mut count = (r.number - finalized).saturated_into::(); // up to the last finalized block - if parent_status != BlockStatus::Unknown { - // request only single block - count = 1; - } - return Some((hash.clone(), message::generic::BlockRequest { - id: 0, - fields: attributes.clone(), - from: message::FromBlock::Hash(hash.clone()), - to: None, - direction: message::Direction::Descending, - max: Some(count), - })) - } - } - None -} diff --git a/core/network/src/protocol/util.rs b/core/network/src/protocol/util.rs deleted file mode 100644 index 5e9e64aae7e9c..0000000000000 --- a/core/network/src/protocol/util.rs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use 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/network/src/service.rs b/core/network/src/service.rs deleted file mode 100644 index 48ad51bde31a6..0000000000000 --- a/core/network/src/service.rs +++ /dev/null @@ -1,808 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Main entry point of the substrate-network crate. -//! -//! There are two main structs in this module: [`NetworkWorker`] and [`NetworkService`]. -//! The [`NetworkWorker`] *is* the network and implements the `Future` trait. It must be polled in -//! order fo the network to advance. -//! The [`NetworkService`] is merely a shared version of the [`NetworkWorker`]. You can obtain an -//! `Arc` by calling [`NetworkWorker::service`]. -//! -//! The methods of the [`NetworkService`] are implemented by sending a message over a channel, -//! which is then processed by [`NetworkWorker::poll`]. - -use std::{collections::{HashMap, HashSet}, fs, marker::PhantomData, io, path::Path}; -use std::sync::{Arc, atomic::{AtomicBool, AtomicUsize, Ordering}}; - -use consensus::import_queue::{ImportQueue, Link}; -use consensus::import_queue::{BlockImportResult, BlockImportError}; -use futures::{prelude::*, sync::mpsc}; -use futures03::TryFutureExt as _; -use log::{warn, error, info}; -use libp2p::{PeerId, Multiaddr, kad::record}; -use libp2p::core::{transport::boxed::Boxed, muxing::StreamMuxerBox}; -use libp2p::swarm::NetworkBehaviour; -use parking_lot::Mutex; -use peerset::PeersetHandle; -use sr_primitives::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId}; - -use crate::{behaviour::{Behaviour, BehaviourOut}, config::{parse_str_addr, parse_addr}}; -use crate::{NetworkState, NetworkStateNotConnectedPeer, NetworkStatePeer}; -use crate::{transport, config::NonReservedPeerMode}; -use crate::config::{Params, TransportConfig}; -use crate::error::Error; -use crate::protocol::{self, Protocol, Context, CustomMessageOutcome, PeerInfo}; -use crate::protocol::consensus_gossip::{ConsensusGossip, MessageRecipient as GossipMessageRecipient}; -use crate::protocol::{event::Event, light_dispatch::{AlwaysBadChecker, RequestData}}; -use crate::protocol::specialization::NetworkSpecialization; -use crate::protocol::sync::SyncState; - -/// Minimum Requirements for a Hash within Networking -pub trait ExHashT: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static {} - -impl ExHashT for T where - T: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static -{} - -/// Transaction pool interface -pub trait TransactionPool: Send + Sync { - /// Get transactions from the pool that are ready to be propagated. - fn transactions(&self) -> Vec<(H, B::Extrinsic)>; - /// Get hash of transaction. - fn hash_of(&self, transaction: &B::Extrinsic) -> H; - /// Import a transaction into the pool. - /// - /// Peer reputation is changed by reputation_change if transaction is accepted by the pool. - fn import( - &self, - report_handle: ReportHandle, - who: PeerId, - reputation_change: i32, - transaction: B::Extrinsic, - ); - /// Notify the pool about transactions broadcast. - fn on_broadcasted(&self, propagations: HashMap>); -} - -/// A cloneable handle for reporting cost/benefits of peers. -#[derive(Clone)] -pub struct ReportHandle { - inner: PeersetHandle, // wraps it so we don't have to worry about breaking API. -} - -impl From for ReportHandle { - fn from(peerset_handle: PeersetHandle) -> Self { - ReportHandle { inner: peerset_handle } - } -} - -impl ReportHandle { - /// Report a given peer as either beneficial (+) or costly (-) according to the - /// given scalar. - pub fn report_peer(&self, who: PeerId, cost_benefit: i32) { - self.inner.report_peer(who, cost_benefit); - } -} - -/// Substrate network service. Handles network IO and manages connectivity. -pub struct NetworkService, H: ExHashT> { - /// Number of peers we're connected to. - num_connected: Arc, - /// The local external addresses. - external_addresses: Arc>>, - /// Are we actively catching up with the chain? - is_major_syncing: Arc, - /// Local copy of the `PeerId` of the local node. - local_peer_id: PeerId, - /// Bandwidth logging system. Can be queried to know the average bandwidth consumed. - bandwidth: Arc, - /// Peerset manager (PSM); manages the reputation of nodes and indicates the network which - /// nodes it should be connected to or not. - peerset: PeersetHandle, - /// Channel that sends messages to the actual worker. - to_worker: mpsc::UnboundedSender>, - /// Marker to pin the `H` generic. Serves no purpose except to not break backwards - /// compatibility. - _marker: PhantomData, -} - -impl, H: ExHashT> NetworkWorker { - /// Creates the network service. - /// - /// Returns a `NetworkWorker` that implements `Future` and must be regularly polled in order - /// for the network processing to advance. From it, you can extract a `NetworkService` using - /// `worker.service()`. The `NetworkService` can be shared through the codebase. - pub fn new(params: Params) -> Result, Error> { - let (to_worker, from_worker) = mpsc::unbounded(); - - if let Some(ref path) = params.network_config.net_config_path { - fs::create_dir_all(Path::new(path))?; - } - - // List of multiaddresses that we know in the network. - let mut known_addresses = Vec::new(); - let mut bootnodes = Vec::new(); - let mut reserved_nodes = Vec::new(); - - // Process the bootnodes. - for bootnode in params.network_config.boot_nodes.iter() { - match parse_str_addr(bootnode) { - Ok((peer_id, addr)) => { - bootnodes.push(peer_id.clone()); - known_addresses.push((peer_id, addr)); - }, - Err(_) => warn!(target: "sub-libp2p", "Not a valid bootnode address: {}", bootnode), - } - } - - // Check for duplicate bootnodes. - known_addresses.iter() - .try_for_each(|(peer_id, addr)| - if let Some(other) = known_addresses - .iter() - .find(|o| o.1 == *addr && o.0 != *peer_id) - { - Err(Error::DuplicateBootnode { - address: addr.clone(), - first_id: peer_id.clone(), - second_id: other.0.clone(), - }) - } else { - Ok(()) - } - )?; - - // Initialize the reserved peers. - for reserved in params.network_config.reserved_nodes.iter() { - if let Ok((peer_id, addr)) = parse_str_addr(reserved) { - reserved_nodes.push(peer_id.clone()); - known_addresses.push((peer_id, addr)); - } else { - warn!(target: "sub-libp2p", "Not a valid reserved node address: {}", reserved); - } - } - - let peerset_config = peerset::PeersetConfig { - in_peers: params.network_config.in_peers, - out_peers: params.network_config.out_peers, - bootnodes, - reserved_only: params.network_config.non_reserved_mode == NonReservedPeerMode::Deny, - reserved_nodes, - }; - - // Private and public keys configuration. - let local_identity = params.network_config.node_key.clone().into_keypair()?; - let local_public = local_identity.public(); - let local_peer_id = local_public.clone().into_peer_id(); - info!(target: "sub-libp2p", "Local node identity is: {}", local_peer_id.to_base58()); - - let num_connected = Arc::new(AtomicUsize::new(0)); - let is_major_syncing = Arc::new(AtomicBool::new(false)); - let (protocol, peerset_handle) = Protocol::new( - protocol::ProtocolConfig { roles: params.roles }, - params.chain, - params.on_demand.as_ref().map(|od| od.checker().clone()) - .unwrap_or(Arc::new(AlwaysBadChecker)), - params.specialization, - params.transaction_pool, - params.finality_proof_provider, - params.finality_proof_request_builder, - params.protocol_id, - peerset_config, - params.block_announce_validator - )?; - - // Build the swarm. - let (mut swarm, bandwidth) = { - let user_agent = format!( - "{} ({})", - params.network_config.client_version, - params.network_config.node_name - ); - let behaviour = Behaviour::new( - protocol, - user_agent, - local_public, - known_addresses, - match params.network_config.transport { - TransportConfig::MemoryOnly => false, - TransportConfig::Normal { enable_mdns, .. } => enable_mdns, - } - ); - let (transport, bandwidth) = { - let (config_mem, config_wasm) = match params.network_config.transport { - TransportConfig::MemoryOnly => (true, None), - TransportConfig::Normal { wasm_external_transport, .. } => - (false, wasm_external_transport) - }; - transport::build_transport(local_identity, config_mem, config_wasm) - }; - (Swarm::::new(transport, behaviour, local_peer_id.clone()), bandwidth) - }; - - // Listen on multiaddresses. - for addr in ¶ms.network_config.listen_addresses { - if let Err(err) = Swarm::::listen_on(&mut swarm, addr.clone()) { - warn!(target: "sub-libp2p", "Can't listen on {} because: {:?}", addr, err) - } - } - - // Add external addresses. - for addr in ¶ms.network_config.public_addresses { - Swarm::::add_external_address(&mut swarm, addr.clone()); - } - - let external_addresses = Arc::new(Mutex::new(Vec::new())); - - let service = Arc::new(NetworkService { - bandwidth, - external_addresses: external_addresses.clone(), - num_connected: num_connected.clone(), - is_major_syncing: is_major_syncing.clone(), - peerset: peerset_handle, - local_peer_id, - to_worker: to_worker.clone(), - _marker: PhantomData, - }); - - Ok(NetworkWorker { - external_addresses, - num_connected, - is_major_syncing, - network_service: swarm, - service, - import_queue: params.import_queue, - from_worker, - light_client_rqs: params.on_demand.and_then(|od| od.extract_receiver()), - }) - } - - /// Returns the downloaded bytes per second averaged over the past few seconds. - pub fn average_download_per_sec(&self) -> u64 { - self.service.bandwidth.average_download_per_sec() - } - - /// Returns the uploaded bytes per second averaged over the past few seconds. - pub fn average_upload_per_sec(&self) -> u64 { - self.service.bandwidth.average_upload_per_sec() - } - - /// Returns the number of peers we're connected to. - pub fn num_connected_peers(&self) -> usize { - self.network_service.user_protocol().num_connected_peers() - } - - /// Returns the number of peers we're connected to and that are being queried. - pub fn num_active_peers(&self) -> usize { - self.network_service.user_protocol().num_active_peers() - } - - /// Current global sync state. - pub fn sync_state(&self) -> SyncState { - self.network_service.user_protocol().sync_state() - } - - /// Target sync block number. - pub fn best_seen_block(&self) -> Option> { - self.network_service.user_protocol().best_seen_block() - } - - /// Number of peers participating in syncing. - pub fn num_sync_peers(&self) -> u32 { - self.network_service.user_protocol().num_sync_peers() - } - - /// Number of blocks in the import queue. - pub fn num_queued_blocks(&self) -> u32 { - self.network_service.user_protocol().num_queued_blocks() - } - - /// Adds an address for a node. - pub fn add_known_address(&mut self, peer_id: PeerId, addr: Multiaddr) { - self.network_service.add_known_address(peer_id, addr); - } - - /// Return a `NetworkService` that can be shared through the code base and can be used to - /// manipulate the worker. - pub fn service(&self) -> &Arc> { - &self.service - } - - /// You must call this when a new block is imported by the client. - pub fn on_block_imported(&mut self, hash: B::Hash, header: B::Header, data: Vec, is_best: bool) { - self.network_service.user_protocol_mut().on_block_imported(hash, &header, data, is_best); - } - - /// You must call this when a new block is finalized by the client. - pub fn on_block_finalized(&mut self, hash: B::Hash, header: B::Header) { - self.network_service.user_protocol_mut().on_block_finalized(hash, &header); - } - - /// Get network state. - /// - /// **Note**: Use this only for debugging. This API is unstable. There are warnings literaly - /// everywhere about this. Please don't use this function to retrieve actual information. - pub fn network_state(&mut self) -> NetworkState { - let swarm = &mut self.network_service; - let open = swarm.user_protocol().open_peers().cloned().collect::>(); - - let connected_peers = { - let swarm = &mut *swarm; - open.iter().filter_map(move |peer_id| { - let known_addresses = NetworkBehaviour::addresses_of_peer(&mut **swarm, peer_id) - .into_iter().collect(); - - let endpoint = if let Some(e) = swarm.node(peer_id).map(|i| i.endpoint()) { - e.clone().into() - } else { - error!(target: "sub-libp2p", "Found state inconsistency between custom protocol \ - and debug information about {:?}", peer_id); - return None - }; - - Some((peer_id.to_base58(), NetworkStatePeer { - endpoint, - version_string: swarm.node(peer_id) - .and_then(|i| i.client_version().map(|s| s.to_owned())).clone(), - latest_ping_time: swarm.node(peer_id).and_then(|i| i.latest_ping()), - enabled: swarm.user_protocol().is_enabled(&peer_id), - open: swarm.user_protocol().is_open(&peer_id), - known_addresses, - })) - }).collect() - }; - - let not_connected_peers = { - let swarm = &mut *swarm; - let list = swarm.known_peers().filter(|p| open.iter().all(|n| n != *p)) - .cloned().collect::>(); - list.into_iter().map(move |peer_id| { - (peer_id.to_base58(), NetworkStateNotConnectedPeer { - version_string: swarm.node(&peer_id) - .and_then(|i| i.client_version().map(|s| s.to_owned())).clone(), - latest_ping_time: swarm.node(&peer_id).and_then(|i| i.latest_ping()), - known_addresses: NetworkBehaviour::addresses_of_peer(&mut **swarm, &peer_id) - .into_iter().collect(), - }) - }).collect() - }; - - NetworkState { - peer_id: Swarm::::local_peer_id(&swarm).to_base58(), - listened_addresses: Swarm::::listeners(&swarm).cloned().collect(), - external_addresses: Swarm::::external_addresses(&swarm).cloned().collect(), - average_download_per_sec: self.service.bandwidth.average_download_per_sec(), - average_upload_per_sec: self.service.bandwidth.average_upload_per_sec(), - connected_peers, - not_connected_peers, - peerset: swarm.user_protocol_mut().peerset_debug_info(), - } - } - - /// Get currently connected peers. - pub fn peers_debug_info(&mut self) -> Vec<(PeerId, PeerInfo)> { - self.network_service.user_protocol_mut() - .peers_info() - .map(|(id, info)| (id.clone(), info.clone())) - .collect() - } -} - -impl, H: ExHashT> NetworkService { - /// Returns the network identity of the node. - pub fn local_peer_id(&self) -> PeerId { - self.local_peer_id.clone() - } - - /// You must call this when new transactons are imported by the transaction pool. - /// - /// The latest transactions will be fetched from the `TransactionPool` that was passed at - /// initialization as part of the configuration. - pub fn trigger_repropagate(&self) { - let _ = self.to_worker.unbounded_send(ServerToWorkerMsg::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. This function forces such an announcement. - pub fn announce_block(&self, hash: B::Hash, data: Vec) { - let _ = self.to_worker.unbounded_send(ServerToWorkerMsg::AnnounceBlock(hash, data)); - } - - /// Send a consensus message through the gossip - pub fn gossip_consensus_message( - &self, - topic: B::Hash, - engine_id: ConsensusEngineId, - message: Vec, - recipient: GossipMessageRecipient, - ) { - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::GossipConsensusMessage( - topic, engine_id, message, recipient, - )); - } - - /// Report a given peer as either beneficial (+) or costly (-) according to the - /// given scalar. - pub fn report_peer(&self, who: PeerId, cost_benefit: i32) { - self.peerset.report_peer(who, cost_benefit); - } - - /// Request a justification for the given block from the network. - /// - /// On success, the justification will be passed to the import queue that was part at - /// initialization as part of the configuration. - pub fn request_justification(&self, hash: &B::Hash, number: NumberFor) { - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::RequestJustification(hash.clone(), number)); - } - - /// Execute a closure with the chain-specific network specialization. - pub fn with_spec(&self, f: F) - where F: FnOnce(&mut S, &mut dyn Context) + Send + 'static - { - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::ExecuteWithSpec(Box::new(f))); - } - - /// Execute a closure with the consensus gossip. - pub fn with_gossip(&self, f: F) - where F: FnOnce(&mut ConsensusGossip, &mut dyn Context) + Send + 'static - { - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::ExecuteWithGossip(Box::new(f))); - } - - /// Are we in the process of downloading the chain? - pub fn is_major_syncing(&self) -> bool { - self.is_major_syncing.load(Ordering::Relaxed) - } - - /// Start getting a value from the DHT. - /// - /// This will generate either a `ValueFound` or a `ValueNotFound` event and pass it to - /// `on_event` on the network specialization. - pub fn get_value(&self, key: &record::Key) { - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::GetValue(key.clone())); - } - - /// Start putting a value in the DHT. - /// - /// This will generate either a `ValuePut` or a `ValuePutFailed` event and pass it to - /// `on_event` on the network specialization. - pub fn put_value(&self, key: record::Key, value: Vec) { - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::PutValue(key, value)); - } - - /// Connect to unreserved peers and allow unreserved peers to connect. - pub fn accept_unreserved_peers(&self) { - self.peerset.set_reserved_only(false); - } - - /// Disconnect from unreserved peers and deny new unreserved peers to connect. - pub fn deny_unreserved_peers(&self) { - self.peerset.set_reserved_only(true); - } - - /// Removes a `PeerId` from the list of reserved peers. - pub fn remove_reserved_peer(&self, peer: PeerId) { - self.peerset.remove_reserved_peer(peer); - } - - /// Adds a `PeerId` and its address as reserved. - pub fn add_reserved_peer(&self, peer: String) -> Result<(), String> { - let (peer_id, addr) = parse_str_addr(&peer).map_err(|e| format!("{:?}", e))?; - self.peerset.add_reserved_peer(peer_id.clone()); - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::AddKnownAddress(peer_id, addr)); - Ok(()) - } - - /// Configure an explicit fork sync request. - /// Note that this function should not be used for recent blocks. - /// Sync should be able to download all the recent forks normally. - /// `set_sync_fork_request` should only be used if external code detects that there's - /// a stale fork missing. - /// Passing empty `peers` set effectively removes the sync request. - pub fn set_sync_fork_request(&self, peers: Vec, hash: B::Hash, number: NumberFor) { - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::SyncFork(peers, hash, number)); - } - - /// Modify a peerset priority group. - pub fn set_priority_group(&self, group_id: String, peers: HashSet) -> Result<(), String> { - let peers = peers.into_iter().map(|p| { - parse_addr(p).map_err(|e| format!("{:?}", e)) - }).collect::, String>>()?; - - let peer_ids = peers.iter().map(|(peer_id, _addr)| peer_id.clone()).collect(); - self.peerset.set_priority_group(group_id, peer_ids); - - for (peer_id, addr) in peers.into_iter() { - let _ = self - .to_worker - .unbounded_send(ServerToWorkerMsg::AddKnownAddress(peer_id, addr)); - } - - Ok(()) - } - - /// Returns the number of peers we're connected to. - pub fn num_connected(&self) -> usize { - self.num_connected.load(Ordering::Relaxed) - } - - /// Returns the local external addresses. - pub fn external_addresses(&self) -> Vec { - self.external_addresses.lock().clone() - } -} - -impl, H: ExHashT> consensus::SyncOracle - for NetworkService -{ - fn is_major_syncing(&mut self) -> bool { - NetworkService::is_major_syncing(self) - } - - fn is_offline(&mut self) -> bool { - self.num_connected.load(Ordering::Relaxed) == 0 - } -} - -impl<'a, B: BlockT + 'static, S: NetworkSpecialization, H: ExHashT> consensus::SyncOracle - for &'a NetworkService -{ - fn is_major_syncing(&mut self) -> bool { - NetworkService::is_major_syncing(self) - } - - fn is_offline(&mut self) -> bool { - self.num_connected.load(Ordering::Relaxed) == 0 - } -} - -/// Trait for providing information about the local network state -pub trait NetworkStateInfo { - /// Returns the local external addresses. - fn external_addresses(&self) -> Vec; - - /// Returns the local Peer ID. - fn peer_id(&self) -> PeerId; -} - -impl NetworkStateInfo for NetworkService - where - B: sr_primitives::traits::Block, - S: NetworkSpecialization, - H: ExHashT, -{ - /// Returns the local external addresses. - fn external_addresses(&self) -> Vec { - self.external_addresses.lock().clone() - } - - /// Returns the local Peer ID. - fn peer_id(&self) -> PeerId { - self.local_peer_id.clone() - } -} - -/// Messages sent from the `NetworkService` to the `NetworkWorker`. -/// -/// Each entry corresponds to a method of `NetworkService`. -enum ServerToWorkerMsg> { - PropagateExtrinsics, - RequestJustification(B::Hash, NumberFor), - AnnounceBlock(B::Hash, Vec), - ExecuteWithSpec(Box) + Send>), - ExecuteWithGossip(Box, &mut dyn Context) + Send>), - GossipConsensusMessage(B::Hash, ConsensusEngineId, Vec, GossipMessageRecipient), - GetValue(record::Key), - PutValue(record::Key, Vec), - AddKnownAddress(PeerId, Multiaddr), - SyncFork(Vec, B::Hash, NumberFor), -} - -/// Main network worker. Must be polled in order for the network to advance. -/// -/// You are encouraged to poll this in a separate background thread or task. -#[must_use = "The NetworkWorker must be polled in order for the network to work"] -pub struct NetworkWorker, H: ExHashT> { - /// Updated by the `NetworkWorker` and loaded by the `NetworkService`. - external_addresses: Arc>>, - /// Updated by the `NetworkWorker` and loaded by the `NetworkService`. - num_connected: Arc, - /// Updated by the `NetworkWorker` and loaded by the `NetworkService`. - is_major_syncing: Arc, - /// The network service that can be extracted and shared through the codebase. - service: Arc>, - /// The *actual* network. - network_service: Swarm, - /// The import queue that was passed as initialization. - import_queue: Box>, - /// Messages from the `NetworkService` and that must be processed. - from_worker: mpsc::UnboundedReceiver>, - /// Receiver for queries from the light client that must be processed. - light_client_rqs: Option>>, -} - -impl, H: ExHashT> Stream for NetworkWorker { - type Item = Event; - type Error = io::Error; - - fn poll(&mut self) -> Poll, Self::Error> { - // Poll the import queue for actions to perform. - let _ = futures03::future::poll_fn(|cx| { - self.import_queue.poll_actions(cx, &mut NetworkLink { - protocol: &mut self.network_service, - }); - std::task::Poll::Pending::> - }).compat().poll(); - - // Check for new incoming light client requests. - if let Some(light_client_rqs) = self.light_client_rqs.as_mut() { - while let Ok(Async::Ready(Some(rq))) = light_client_rqs.poll() { - self.network_service.user_protocol_mut().add_light_client_request(rq); - } - } - - loop { - // Process the next message coming from the `NetworkService`. - let msg = match self.from_worker.poll() { - Ok(Async::Ready(Some(msg))) => msg, - Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(None)), - Ok(Async::NotReady) => break, - }; - - match msg { - ServerToWorkerMsg::ExecuteWithSpec(task) => { - let protocol = self.network_service.user_protocol_mut(); - let (mut context, spec) = protocol.specialization_lock(); - task(spec, &mut context); - }, - ServerToWorkerMsg::ExecuteWithGossip(task) => { - let protocol = self.network_service.user_protocol_mut(); - let (mut context, gossip) = protocol.consensus_gossip_lock(); - task(gossip, &mut context); - } - ServerToWorkerMsg::GossipConsensusMessage(topic, engine_id, message, recipient) => - self.network_service.user_protocol_mut().gossip_consensus_message(topic, engine_id, message, recipient), - ServerToWorkerMsg::AnnounceBlock(hash, data) => - self.network_service.user_protocol_mut().announce_block(hash, data), - ServerToWorkerMsg::RequestJustification(hash, number) => - self.network_service.user_protocol_mut().request_justification(&hash, number), - ServerToWorkerMsg::PropagateExtrinsics => - self.network_service.user_protocol_mut().propagate_extrinsics(), - ServerToWorkerMsg::GetValue(key) => - self.network_service.get_value(&key), - ServerToWorkerMsg::PutValue(key, value) => - self.network_service.put_value(key, value), - ServerToWorkerMsg::AddKnownAddress(peer_id, addr) => - self.network_service.add_known_address(peer_id, addr), - ServerToWorkerMsg::SyncFork(peer_ids, hash, number) => - self.network_service.user_protocol_mut().set_sync_fork_request(peer_ids, &hash, number), - } - } - - loop { - // Process the next action coming from the network. - let poll_value = self.network_service.poll(); - - let outcome = match poll_value { - Ok(Async::NotReady) => break, - Ok(Async::Ready(Some(BehaviourOut::SubstrateAction(outcome)))) => outcome, - Ok(Async::Ready(Some(BehaviourOut::Dht(ev)))) => { - self.network_service.user_protocol_mut() - .on_event(Event::Dht(ev.clone())); - - return Ok(Async::Ready(Some(Event::Dht(ev)))); - }, - Ok(Async::Ready(None)) => CustomMessageOutcome::None, - Err(err) => { - error!(target: "sync", "Error in the network: {:?}", err); - return Err(err) - } - }; - - match outcome { - CustomMessageOutcome::BlockImport(origin, blocks) => - self.import_queue.import_blocks(origin, blocks), - CustomMessageOutcome::JustificationImport(origin, hash, nb, justification) => - self.import_queue.import_justification(origin, hash, nb, justification), - CustomMessageOutcome::FinalityProofImport(origin, hash, nb, proof) => - self.import_queue.import_finality_proof(origin, hash, nb, proof), - CustomMessageOutcome::None => {} - } - } - - // Update the variables shared with the `NetworkService`. - self.num_connected.store(self.network_service.user_protocol_mut().num_connected_peers(), Ordering::Relaxed); - { - let external_addresses = Swarm::::external_addresses(&self.network_service).cloned().collect(); - *self.external_addresses.lock() = external_addresses; - } - self.is_major_syncing.store(match self.network_service.user_protocol_mut().sync_state() { - SyncState::Idle => false, - SyncState::Downloading => true, - }, Ordering::Relaxed); - - Ok(Async::NotReady) - } -} - -/// The libp2p swarm, customized for our needs. -type Swarm = libp2p::swarm::Swarm< - Boxed<(PeerId, StreamMuxerBox), io::Error>, - Behaviour ->; - -// Implementation of `import_queue::Link` trait using the available local variables. -struct NetworkLink<'a, B: BlockT, S: NetworkSpecialization, H: ExHashT> { - protocol: &'a mut Swarm, -} - -impl<'a, B: BlockT, S: NetworkSpecialization, H: ExHashT> Link for NetworkLink<'a, B, S, H> { - fn blocks_processed( - &mut self, - imported: usize, - count: usize, - results: Vec<(Result>, BlockImportError>, B::Hash)> - ) { - self.protocol.user_protocol_mut().blocks_processed(imported, count, results) - } - fn justification_imported(&mut self, who: PeerId, hash: &B::Hash, number: NumberFor, success: bool) { - self.protocol.user_protocol_mut().justification_import_result(hash.clone(), number, success); - if !success { - info!("Invalid justification provided by {} for #{}", who, hash); - self.protocol.user_protocol_mut().disconnect_peer(&who); - self.protocol.user_protocol_mut().report_peer(who, i32::min_value()); - } - } - fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { - self.protocol.user_protocol_mut().request_justification(hash, number) - } - fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor) { - self.protocol.user_protocol_mut().request_finality_proof(hash, number) - } - fn finality_proof_imported( - &mut self, - who: PeerId, - request_block: (B::Hash, NumberFor), - finalization_result: Result<(B::Hash, NumberFor), ()>, - ) { - let success = finalization_result.is_ok(); - self.protocol.user_protocol_mut().finality_proof_import_result(request_block, finalization_result); - if !success { - info!("Invalid finality proof provided by {} for #{}", who, request_block.0); - self.protocol.user_protocol_mut().disconnect_peer(&who); - self.protocol.user_protocol_mut().report_peer(who, i32::min_value()); - } - } -} diff --git a/core/network/src/test/block_import.rs b/core/network/src/test/block_import.rs deleted file mode 100644 index f2830548a501a..0000000000000 --- a/core/network/src/test/block_import.rs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Testing block import logic. - -use consensus::ImportedAux; -use consensus::import_queue::{ - import_single_block, BasicQueue, BlockImportError, BlockImportResult, IncomingBlock, -}; -use test_client::{self, prelude::*}; -use test_client::runtime::{Block, Hash}; -use sr_primitives::generic::BlockId; -use super::*; - -fn prepare_good_block() -> (TestClient, Hash, u64, PeerId, IncomingBlock) { - let client = test_client::new(); - let block = client.new_block(Default::default()).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(); - let peer_id = PeerId::random(); - (client, hash, number, peer_id.clone(), IncomingBlock { - hash, - header, - body: None, - justification, - origin: Some(peer_id.clone()) - }) -} - -#[test] -fn import_single_good_block_works() { - let (_, _hash, number, peer_id, block) = prepare_good_block(); - - let mut expected_aux = ImportedAux::default(); - expected_aux.is_new_best = true; - - match import_single_block(&mut test_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { - Ok(BlockImportResult::ImportedUnknown(ref num, ref aux, ref org)) - if *num == number && *aux == expected_aux && *org == Some(peer_id) => {} - _ => panic!() - } -} - -#[test] -fn import_single_good_known_block_is_ignored() { - let (mut client, _hash, number, _, block) = prepare_good_block(); - match import_single_block(&mut client, BlockOrigin::File, block, &mut PassThroughVerifier(true)) { - Ok(BlockImportResult::ImportedKnown(ref n)) if *n == number => {} - _ => panic!() - } -} - -#[test] -fn import_single_good_block_without_header_fails() { - let (_, _, _, peer_id, mut block) = prepare_good_block(); - block.header = None; - match import_single_block(&mut test_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { - Err(BlockImportError::IncompleteHeader(ref org)) if *org == Some(peer_id) => {} - _ => panic!() - } -} - -#[test] -fn async_import_queue_drops() { - // Perform this test multiple times since it exhibits non-deterministic behavior. - for _ in 0..100 { - let verifier = PassThroughVerifier(true); - let queue = BasicQueue::new(verifier, Box::new(test_client::new()), None, None); - drop(queue); - } -} diff --git a/core/network/src/test/mod.rs b/core/network/src/test/mod.rs deleted file mode 100644 index 92e747280bbbb..0000000000000 --- a/core/network/src/test/mod.rs +++ /dev/null @@ -1,818 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![allow(missing_docs)] - -#[cfg(test)] -mod block_import; -#[cfg(test)] -mod sync; - -use std::collections::HashMap; -use std::sync::Arc; - -use crate::config::build_multiaddr; -use log::trace; -use crate::chain::FinalityProofProvider; -use client::{ - self, ClientInfo, BlockchainEvents, BlockImportNotification, - FinalityNotifications, ImportNotifications, - FinalityNotification, LongestChain, - error::Result as ClientResult, - well_known_cache_keys::{self, Id as CacheKeyId}, -}; -use client::block_builder::BlockBuilder; -use client::backend::{AuxStore, Backend, Finalizer}; -use crate::config::Roles; -use consensus::block_validation::DefaultBlockAnnounceValidator; -use consensus::import_queue::BasicQueue; -use consensus::import_queue::{ - BoxBlockImport, BoxJustificationImport, Verifier, BoxFinalityProofImport, -}; -use consensus::block_import::{BlockImport, ImportResult}; -use consensus::Error as ConsensusError; -use consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, BlockCheckParams, JustificationImport}; -use futures::prelude::*; -use futures03::{StreamExt as _, TryStreamExt as _}; -use crate::{NetworkWorker, NetworkService, ReportHandle, config::ProtocolId}; -use crate::config::{NetworkConfiguration, TransportConfig, BoxFinalityProofRequestBuilder}; -use libp2p::PeerId; -use parking_lot::Mutex; -use primitives::H256; -use crate::protocol::{Context, ProtocolConfig}; -use sr_primitives::generic::{BlockId, OpaqueDigestItemId}; -use sr_primitives::traits::{Block as BlockT, Header, NumberFor}; -use sr_primitives::Justification; -use crate::service::TransactionPool; -use crate::specialization::NetworkSpecialization; -use test_client::{self, AccountKeyring}; - -pub use test_client::runtime::{Block, Extrinsic, Hash, Transfer}; -pub use test_client::{TestClient, TestClientBuilder, TestClientBuilderExt}; - -type AuthorityId = babe_primitives::AuthorityId; - -#[cfg(any(test, feature = "test-helpers"))] -/// A Verifier that accepts all blocks and passes them on with the configured -/// finality to be imported. -#[derive(Clone)] -pub struct PassThroughVerifier(pub bool); - -#[cfg(any(test, feature = "test-helpers"))] -/// This `Verifier` accepts all data as valid. -impl Verifier for PassThroughVerifier { - fn verify( - &mut self, - origin: BlockOrigin, - header: B::Header, - justification: Option, - body: Option> - ) -> Result<(BlockImportParams, Option)>>), String> { - let maybe_keys = header.digest() - .log(|l| l.try_as_raw(OpaqueDigestItemId::Consensus(b"aura")) - .or_else(|| l.try_as_raw(OpaqueDigestItemId::Consensus(b"babe"))) - ) - .map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]); - - Ok((BlockImportParams { - origin, - header, - body, - finalized: self.0, - justification, - post_digests: vec![], - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }, maybe_keys)) - } -} - -/// The test specialization. -#[derive(Clone)] -pub struct DummySpecialization; - -impl NetworkSpecialization for DummySpecialization { - fn status(&self) -> Vec { - vec![] - } - - fn on_connect( - &mut self, - _ctx: &mut dyn Context, - _peer_id: PeerId, - _status: crate::message::Status - ) {} - - fn on_disconnect(&mut self, _ctx: &mut dyn Context, _peer_id: PeerId) {} - - fn on_message( - &mut self, - _ctx: &mut dyn Context, - _peer_id: PeerId, - _message: Vec, - ) {} - - fn on_event( - &mut self, - _event: crate::specialization::Event - ) {} -} - -pub type PeersFullClient = - client::Client; -pub type PeersLightClient = - client::Client; - -#[derive(Clone)] -pub enum PeersClient { - Full(Arc, Arc), - Light(Arc, Arc), -} - -impl PeersClient { - pub fn as_full(&self) -> Option> { - match *self { - PeersClient::Full(ref client, ref _backend) => Some(client.clone()), - _ => None, - } - } - - pub fn as_block_import(&self) -> BoxBlockImport { - match *self { - PeersClient::Full(ref client, ref _backend) => Box::new(client.clone()) as _, - PeersClient::Light(ref client, ref _backend) => Box::new(client.clone()) as _, - } - } - - pub fn get_aux(&self, key: &[u8]) -> ClientResult>> { - match *self { - PeersClient::Full(ref client, ref _backend) => client.get_aux(key), - PeersClient::Light(ref client, ref _backend) => client.get_aux(key), - } - } - - pub fn info(&self) -> ClientInfo { - match *self { - PeersClient::Full(ref client, ref _backend) => client.info(), - PeersClient::Light(ref client, ref _backend) => client.info(), - } - } - - pub fn header(&self, block: &BlockId) -> ClientResult::Header>> { - match *self { - PeersClient::Full(ref client, ref _backend) => client.header(block), - PeersClient::Light(ref client, ref _backend) => client.header(block), - } - } - - pub fn justification(&self, block: &BlockId) -> ClientResult> { - match *self { - PeersClient::Full(ref client, ref _backend) => client.justification(block), - PeersClient::Light(ref client, ref _backend) => client.justification(block), - } - } - - pub fn finality_notification_stream(&self) -> FinalityNotifications { - match *self { - PeersClient::Full(ref client, ref _backend) => client.finality_notification_stream(), - PeersClient::Light(ref client, ref _backend) => client.finality_notification_stream(), - } - } - - pub fn import_notification_stream(&self) -> ImportNotifications{ - match *self { - PeersClient::Full(ref client, ref _backend) => client.import_notification_stream(), - PeersClient::Light(ref client, ref _backend) => client.import_notification_stream(), - } - } - - pub fn finalize_block( - &self, - id: BlockId, - justification: Option, - notify: bool - ) -> ClientResult<()> { - match *self { - PeersClient::Full(ref client, ref _backend) => client.finalize_block(id, justification, notify), - PeersClient::Light(ref client, ref _backend) => client.finalize_block(id, justification, notify), - } - } -} - -pub struct Peer> { - pub data: D, - client: PeersClient, - /// We keep a copy of the verifier so that we can invoke it for locally-generated blocks, - /// instead of going through the import queue. - verifier: VerifierAdapter>, - /// We keep a copy of the block_import so that we can invoke it for locally-generated blocks, - /// instead of going through the import queue. - block_import: Box>, - select_chain: Option>, - backend: Option>, - network: NetworkWorker::Hash>, - imported_blocks_stream: Box, Error = ()> + Send>, - finality_notification_stream: Box, Error = ()> + Send>, -} - -impl> Peer { - /// Get this peer ID. - pub fn id(&self) -> PeerId { - self.network.service().local_peer_id() - } - - /// Returns true if we're major syncing. - pub fn is_major_syncing(&self) -> bool { - self.network.service().is_major_syncing() - } - - // Returns a clone of the local SelectChain, only available on full nodes - pub fn select_chain(&self) -> Option> { - self.select_chain.clone() - } - - /// Returns the number of peers we're connected to. - pub fn num_peers(&self) -> usize { - self.network.num_connected_peers() - } - - /// Returns true if we have no peer. - pub fn is_offline(&self) -> bool { - self.num_peers() == 0 - } - - /// Request a justification for the given block. - pub fn request_justification(&self, hash: &::Hash, number: NumberFor) { - self.network.service().request_justification(hash, number); - } - - /// Announces an important block on the network. - pub fn announce_block(&self, hash: ::Hash, data: Vec) { - self.network.service().announce_block(hash, data); - } - - /// Request explicit fork sync. - pub fn set_sync_fork_request(&self, peers: Vec, hash: ::Hash, number: NumberFor) { - self.network.service().set_sync_fork_request(peers, hash, number); - } - - /// Add blocks to the peer -- edit the block before adding - pub fn generate_blocks(&mut self, count: usize, origin: BlockOrigin, edit_block: F) -> H256 - where F: FnMut(BlockBuilder) -> Block - { - let best_hash = self.client.info().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. - fn generate_blocks_at( - &mut self, - at: BlockId, - count: usize, - origin: BlockOrigin, - mut edit_block: F - ) -> H256 where F: FnMut(BlockBuilder) -> Block { - let full_client = self.client.as_full().expect("blocks could only be generated by full clients"); - let mut at = full_client.header(&at).unwrap().unwrap().hash(); - for _ in 0..count { - let builder = full_client.new_block_at(&BlockId::Hash(at), Default::default() - ).unwrap(); - let block = edit_block(builder); - let hash = block.header.hash(); - trace!( - target: "test_network", - "Generating {}, (#{}, parent={})", - hash, - block.header.number, - block.header.parent_hash - ); - let header = block.header.clone(); - let (import_block, cache) = self.verifier.verify( - origin, - header.clone(), - None, - Some(block.extrinsics) - ).unwrap(); - let cache = if let Some(cache) = cache { - cache.into_iter().collect() - } else { - Default::default() - }; - self.block_import.import_block(import_block, cache).expect("block_import failed"); - self.network.on_block_imported(hash, header, Vec::new(), true); - at = hash; - } - - self.network.service().announce_block(at.clone(), Vec::new()); - at - } - - /// Push blocks to the peer (simplified: with or without a TX) - pub fn push_blocks(&mut self, count: usize, with_tx: bool) -> H256 { - let best_hash = self.client.info().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(&mut self, at: BlockId, count: usize, with_tx: bool) -> H256 { - let mut nonce = 0; - if with_tx { - self.generate_blocks_at(at, count, BlockOrigin::File, |mut builder| { - let transfer = Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Alice.into(), - amount: 1, - nonce, - }; - builder.push(transfer.into_signed_tx()).unwrap(); - nonce = nonce + 1; - builder.bake().unwrap() - }) - } else { - self.generate_blocks_at(at, count, BlockOrigin::File, |builder| builder.bake().unwrap()) - } - } - - pub fn push_authorities_change_block(&mut 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. - pub fn client(&self) -> &PeersClient { - &self.client - } - - /// Get a reference to the network service. - pub fn network_service(&self) -> &Arc::Hash>> { - &self.network.service() - } - - /// Test helper to compare the blockchain state of multiple (networked) - /// clients. - /// Potentially costly, as it creates in-memory copies of both blockchains in order - /// to compare them. If you have easier/softer checks that are sufficient, e.g. - /// by using .info(), you should probably use it instead of this. - pub fn blockchain_canon_equals(&self, other: &Self) -> bool { - if let (Some(mine), Some(others)) = (self.backend.clone(), other.backend.clone()) { - mine.as_in_memory().blockchain() - .canon_equals_to(others.as_in_memory().blockchain()) - } else { - false - } - } - - /// Count the current number of known blocks. Note that: - /// 1. this might be expensive as it creates an in-memory-copy of the chain - /// to count the blocks, thus if you have a different way of testing this - /// (e.g. `info.best_hash`) - use that. - /// 2. This is not always increasing nor accurate, as the - /// orphaned and proven-to-never-finalized blocks may be pruned at any time. - /// Therefore, this number can drop again. - pub fn blocks_count(&self) -> usize { - self.backend.as_ref().map( - |backend| backend.as_in_memory().blockchain().blocks_count() - ).unwrap_or(0) - } -} - -pub struct EmptyTransactionPool; - -impl TransactionPool for EmptyTransactionPool { - fn transactions(&self) -> Vec<(Hash, Extrinsic)> { - Vec::new() - } - - fn hash_of(&self, _transaction: &Extrinsic) -> Hash { - Hash::default() - } - - fn import(&self, _report_handle: ReportHandle, _who: PeerId, _rep_change: i32, _transaction: Extrinsic) {} - - fn on_broadcasted(&self, _: HashMap>) {} -} - -pub trait SpecializationFactory { - fn create() -> Self; -} - -impl SpecializationFactory for DummySpecialization { - fn create() -> DummySpecialization { - DummySpecialization - } -} - -/// Implements `BlockImport` on an `Arc>`. Used internally. Necessary to overcome the way the -/// `TestNet` trait is designed, more specifically `make_block_import` returning a `Box` makes it -/// impossible to clone the underlying object. -struct BlockImportAdapter(Arc>>); - -impl Clone for BlockImportAdapter { - fn clone(&self) -> Self { - BlockImportAdapter(self.0.clone()) - } -} - -impl> BlockImport for BlockImportAdapter { - type Error = T::Error; - - fn check_block( - &mut self, - block: BlockCheckParams, - ) -> Result { - self.0.lock().check_block(block) - } - - fn import_block( - &mut self, - block: BlockImportParams, - cache: HashMap>, - ) -> Result { - self.0.lock().import_block(block, cache) - } -} - -/// Implements `Verifier` on an `Arc>`. Used internally. -struct VerifierAdapter(Arc>>); - -impl Clone for VerifierAdapter { - fn clone(&self) -> Self { - VerifierAdapter(self.0.clone()) - } -} - -impl> Verifier for VerifierAdapter { - fn verify( - &mut self, - origin: BlockOrigin, - header: B::Header, - justification: Option, - body: Option> - ) -> Result<(BlockImportParams, Option)>>), String> { - self.0.lock().verify(origin, header, justification, body) - } -} - -pub trait TestNetFactory: Sized { - type Specialization: NetworkSpecialization + SpecializationFactory; - type Verifier: 'static + Verifier; - type PeerData: Default; - - /// These two need to be implemented! - fn from_config(config: &ProtocolConfig) -> Self; - fn make_verifier( - &self, - client: PeersClient, - config: &ProtocolConfig, - peer_data: &Self::PeerData, - ) -> Self::Verifier; - - /// Get reference to peer. - fn peer(&mut self, i: usize) -> &mut Peer; - fn peers(&self) -> &Vec>; - fn mut_peers>)>(&mut self, closure: F); - - /// Get custom block import handle for fresh client, along with peer data. - fn make_block_import(&self, client: PeersClient) - -> ( - BoxBlockImport, - Option>, - Option>, - Option>, - Self::PeerData, - ) - { - (client.as_block_import(), None, None, None, Default::default()) - } - - /// Get finality proof provider (if supported). - fn make_finality_proof_provider(&self, _client: PeersClient) -> Option>> { - None - } - - fn default_config() -> ProtocolConfig { - ProtocolConfig::default() - } - - /// Create new test network with this many peers. - fn new(n: usize) -> Self { - trace!(target: "test_network", "Creating test network"); - let config = Self::default_config(); - let mut net = Self::from_config(&config); - - for i in 0..n { - trace!(target: "test_network", "Adding peer {}", i); - net.add_full_peer(&config); - } - net - } - - /// Add a full peer. - fn add_full_peer(&mut self, config: &ProtocolConfig) { - let test_client_builder = TestClientBuilder::with_default_backend(); - let backend = test_client_builder.backend(); - let (c, longest_chain) = test_client_builder.build_with_longest_chain(); - let client = Arc::new(c); - - let ( - block_import, - justification_import, - finality_proof_import, - finality_proof_request_builder, - data, - ) = self.make_block_import(PeersClient::Full(client.clone(), backend.clone())); - let block_import = BlockImportAdapter(Arc::new(Mutex::new(block_import))); - - let verifier = self.make_verifier( - PeersClient::Full(client.clone(), backend.clone()), - config, - &data, - ); - let verifier = VerifierAdapter(Arc::new(Mutex::new(Box::new(verifier) as Box<_>))); - - let import_queue = Box::new(BasicQueue::new( - verifier.clone(), - Box::new(block_import.clone()), - justification_import, - finality_proof_import, - )); - - let listen_addr = build_multiaddr![Memory(rand::random::())]; - - let network = NetworkWorker::new(crate::config::Params { - roles: config.roles, - network_config: NetworkConfiguration { - listen_addresses: vec![listen_addr.clone()], - transport: TransportConfig::MemoryOnly, - ..NetworkConfiguration::default() - }, - chain: client.clone(), - finality_proof_provider: self.make_finality_proof_provider(PeersClient::Full(client.clone(), backend.clone())), - finality_proof_request_builder, - on_demand: None, - transaction_pool: Arc::new(EmptyTransactionPool), - protocol_id: ProtocolId::from(&b"test-protocol-name"[..]), - import_queue, - specialization: self::SpecializationFactory::create(), - block_announce_validator: Box::new(DefaultBlockAnnounceValidator::new(client.clone())) - }).unwrap(); - - self.mut_peers(|peers| { - for peer in peers.iter_mut() { - peer.network.add_known_address(network.service().local_peer_id(), listen_addr.clone()); - } - - let imported_blocks_stream = Box::new(client.import_notification_stream() - .map(|v| Ok::<_, ()>(v)).compat().fuse()); - let finality_notification_stream = Box::new(client.finality_notification_stream() - .map(|v| Ok::<_, ()>(v)).compat().fuse()); - - peers.push(Peer { - data, - client: PeersClient::Full(client, backend.clone()), - select_chain: Some(longest_chain), - backend: Some(backend), - imported_blocks_stream, - finality_notification_stream, - block_import: Box::new(block_import), - verifier, - network, - }); - }); - } - - /// Add a light peer. - fn add_light_peer(&mut self, config: &ProtocolConfig) { - let mut config = config.clone(); - config.roles = Roles::LIGHT; - - let (c, backend) = test_client::new_light(); - let client = Arc::new(c); - let ( - block_import, - justification_import, - finality_proof_import, - finality_proof_request_builder, - data, - ) = self.make_block_import(PeersClient::Light(client.clone(), backend.clone())); - let block_import = BlockImportAdapter(Arc::new(Mutex::new(block_import))); - - let verifier = self.make_verifier( - PeersClient::Light(client.clone(), backend.clone()), - &config, - &data, - ); - let verifier = VerifierAdapter(Arc::new(Mutex::new(Box::new(verifier) as Box<_>))); - - let import_queue = Box::new(BasicQueue::new( - verifier.clone(), - Box::new(block_import.clone()), - justification_import, - finality_proof_import, - )); - - let listen_addr = build_multiaddr![Memory(rand::random::())]; - - let network = NetworkWorker::new(crate::config::Params { - roles: config.roles, - network_config: NetworkConfiguration { - listen_addresses: vec![listen_addr.clone()], - transport: TransportConfig::MemoryOnly, - ..NetworkConfiguration::default() - }, - chain: client.clone(), - finality_proof_provider: self.make_finality_proof_provider(PeersClient::Light(client.clone(), backend.clone())), - finality_proof_request_builder, - on_demand: None, - transaction_pool: Arc::new(EmptyTransactionPool), - protocol_id: ProtocolId::from(&b"test-protocol-name"[..]), - import_queue, - specialization: self::SpecializationFactory::create(), - block_announce_validator: Box::new(DefaultBlockAnnounceValidator::new(client.clone())) - }).unwrap(); - - self.mut_peers(|peers| { - for peer in peers.iter_mut() { - peer.network.add_known_address(network.service().local_peer_id(), listen_addr.clone()); - } - - let imported_blocks_stream = Box::new(client.import_notification_stream() - .map(|v| Ok::<_, ()>(v)).compat().fuse()); - let finality_notification_stream = Box::new(client.finality_notification_stream() - .map(|v| Ok::<_, ()>(v)).compat().fuse()); - - peers.push(Peer { - data, - verifier, - select_chain: None, - backend: None, - block_import: Box::new(block_import), - client: PeersClient::Light(client, backend), - imported_blocks_stream, - finality_notification_stream, - network, - }); - }); - } - - /// Polls the testnet until all nodes are in sync. - /// - /// Must be executed in a task context. - fn poll_until_sync(&mut self) -> Async<()> { - self.poll(); - - // Return `NotReady` if there's a mismatch in the highest block number. - let mut highest = None; - for peer in self.peers().iter() { - if peer.is_major_syncing() || peer.network.num_queued_blocks() != 0 { - return Async::NotReady - } - match (highest, peer.client.info().chain.best_number) { - (None, b) => highest = Some(b), - (Some(ref a), ref b) if a == b => {}, - (Some(_), _) => return Async::NotReady, - } - } - Async::Ready(()) - } - - /// Blocks the current thread until we are sync'ed. - /// - /// Calls `poll_until_sync` repeatidely with the runtime passed as parameter. - fn block_until_sync(&mut self, runtime: &mut tokio::runtime::current_thread::Runtime) { - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| Ok(self.poll_until_sync()))).unwrap(); - } - - /// Polls the testnet. Processes all the pending actions and returns `NotReady`. - fn poll(&mut self) { - self.mut_peers(|peers| { - for peer in peers { - trace!(target: "sync", "-- Polling {}", peer.id()); - peer.network.poll().unwrap(); - trace!(target: "sync", "-- Polling complete {}", peer.id()); - - // We poll `imported_blocks_stream`. - while let Ok(Async::Ready(Some(notification))) = peer.imported_blocks_stream.poll() { - peer.network.on_block_imported(notification.hash, notification.header, Vec::new(), true); - } - - // We poll `finality_notification_stream`, but we only take the last event. - let mut last = None; - while let Ok(Async::Ready(Some(item))) = peer.finality_notification_stream.poll() { - last = Some(item); - } - if let Some(notification) = last { - peer.network.on_block_finalized(notification.hash, notification.header); - } - } - }); - } -} - -pub struct TestNet { - peers: Vec>, -} - -impl TestNetFactory for TestNet { - type Specialization = DummySpecialization; - type Verifier = PassThroughVerifier; - type PeerData = (); - - /// Create new test network with peers and given config. - fn from_config(_config: &ProtocolConfig) -> Self { - TestNet { - peers: Vec::new(), - } - } - - fn make_verifier(&self, _client: PeersClient, _config: &ProtocolConfig, _peer_data: &()) - -> Self::Verifier - { - PassThroughVerifier(false) - } - - fn peer(&mut self, i: usize) -> &mut Peer<(), Self::Specialization> { - &mut self.peers[i] - } - - fn peers(&self) -> &Vec> { - &self.peers - } - - fn mut_peers>)>(&mut self, closure: F) { - closure(&mut self.peers); - } -} - -pub struct ForceFinalized(PeersClient); - -impl JustificationImport for ForceFinalized { - type Error = ConsensusError; - - fn import_justification( - &mut self, - hash: H256, - _number: NumberFor, - justification: Justification, - ) -> Result<(), Self::Error> { - self.0.finalize_block(BlockId::Hash(hash), Some(justification), true) - .map_err(|_| ConsensusError::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: PeersClient, config: &ProtocolConfig, peer_data: &()) -> Self::Verifier { - self.0.make_verifier(client, config, peer_data) - } - - fn peer(&mut self, i: usize) -> &mut 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 make_block_import(&self, client: PeersClient) - -> ( - BoxBlockImport, - Option>, - Option>, - Option>, - Self::PeerData, - ) - { - (client.as_block_import(), Some(Box::new(ForceFinalized(client))), None, None, Default::default()) - } -} diff --git a/core/network/src/test/sync.rs b/core/network/src/test/sync.rs deleted file mode 100644 index b1b2b9d407262..0000000000000 --- a/core/network/src/test/sync.rs +++ /dev/null @@ -1,594 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::config::Roles; -use consensus::BlockOrigin; -use futures03::TryFutureExt as _; -use std::time::Duration; -use tokio::runtime::current_thread; -use super::*; - -fn test_ancestor_search_when_common_is(n: usize) { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - 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.block_until_sync(&mut runtime); - let peer1 = &net.peers()[1]; - assert!(net.peers()[0].blockchain_canon_equals(peer1)); -} - -#[test] -fn sync_peers_works() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(3); - - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - for peer in 0..3 { - if net.peer(peer).num_peers() != 2 { - return Ok(Async::NotReady) - } - } - Ok(Async::Ready(())) - })).unwrap(); -} - -#[test] -fn sync_cycle_from_offline_to_syncing_to_offline() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - 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); - - // Block until all nodes are online and nodes 0 and 1 and major syncing. - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - for peer in 0..3 { - // Online - if net.peer(peer).is_offline() { - return Ok(Async::NotReady) - } - if peer < 2 { - // Major syncing. - if !net.peer(peer).is_major_syncing() { - return Ok(Async::NotReady) - } - } - } - Ok(Async::Ready(())) - })).unwrap(); - - // Block until all nodes are done syncing. - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - for peer in 0..3 { - if net.peer(peer).is_major_syncing() { - return Ok(Async::NotReady) - } - } - Ok(Async::Ready(())) - })).unwrap(); - - // Now drop nodes 1 and 2, and check that node 0 is offline. - net.peers.remove(2); - net.peers.remove(1); - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - if !net.peer(0).is_offline() { - Ok(Async::NotReady) - } else { - Ok(Async::Ready(())) - } - })).unwrap(); -} - -#[test] -fn syncing_node_not_major_syncing_when_disconnected() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(3); - - // Generate blocks. - net.peer(2).push_blocks(100, false); - - // Check that we're not major syncing when disconnected. - assert!(!net.peer(1).is_major_syncing()); - - // Check that we switch to major syncing. - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - if !net.peer(1).is_major_syncing() { - Ok(Async::NotReady) - } else { - Ok(Async::Ready(())) - } - })).unwrap(); - - // Destroy two nodes, and check that we switch to non-major syncing. - net.peers.remove(2); - net.peers.remove(0); - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - if net.peer(0).is_major_syncing() { - Ok(Async::NotReady) - } else { - Ok(Async::Ready(())) - } - })).unwrap(); -} - -#[test] -fn sync_from_two_peers_works() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(3); - net.peer(1).push_blocks(100, false); - net.peer(2).push_blocks(100, false); - net.block_until_sync(&mut runtime); - let peer1 = &net.peers()[1]; - assert!(net.peers()[0].blockchain_canon_equals(peer1)); - assert!(!net.peer(0).is_major_syncing()); -} - -#[test] -fn sync_from_two_peers_with_ancestry_search_works() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - 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.block_until_sync(&mut runtime); - let peer1 = &net.peers()[1]; - assert!(net.peers()[0].blockchain_canon_equals(peer1)); -} - -#[test] -fn ancestry_search_works_when_backoff_is_one() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - 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.block_until_sync(&mut runtime); - let peer1 = &net.peers()[1]; - assert!(net.peers()[0].blockchain_canon_equals(peer1)); -} - -#[test] -fn ancestry_search_works_when_ancestor_is_genesis() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - 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.block_until_sync(&mut runtime); - let peer1 = &net.peers()[1]; - assert!(net.peers()[0].blockchain_canon_equals(peer1)); -} - -#[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 _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(2); - net.peer(1).push_blocks(500, false); - net.block_until_sync(&mut runtime); - let peer1 = &net.peers()[1]; - assert!(net.peers()[0].blockchain_canon_equals(peer1)); -} - -#[test] -fn sync_no_common_longer_chain_fails() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(3); - net.peer(0).push_blocks(20, true); - net.peer(1).push_blocks(20, false); - net.block_until_sync(&mut runtime); - let peer1 = &net.peers()[1]; - assert!(!net.peers()[0].blockchain_canon_equals(peer1)); -} - -#[test] -fn sync_justifications() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = JustificationTestNet::new(3); - net.peer(0).push_blocks(20, false); - net.block_until_sync(&mut runtime); - - // 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); - - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { - net.poll(); - - for height in (10..21).step_by(5) { - if net.peer(0).client().justification(&BlockId::Number(height)).unwrap() != Some(Vec::new()) { - return Ok(Async::NotReady); - } - if net.peer(1).client().justification(&BlockId::Number(height)).unwrap() != Some(Vec::new()) { - return Ok(Async::NotReady); - } - } - - Ok(Async::Ready(())) - })).unwrap(); -} - -#[test] -fn sync_justifications_across_forks() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - 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.block_until_sync(&mut runtime); - - 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); - - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { - net.poll(); - - if net.peer(0).client().justification(&BlockId::Number(10)).unwrap() == Some(Vec::new()) && - net.peer(1).client().justification(&BlockId::Number(10)).unwrap() == Some(Vec::new()) - { - Ok(Async::Ready(())) - } else { - Ok(Async::NotReady) - } - })).unwrap(); -} - -#[test] -fn sync_after_fork_works() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(3); - net.peer(0).push_blocks(30, false); - net.peer(1).push_blocks(30, false); - net.peer(2).push_blocks(30, false); - - net.peer(0).push_blocks(10, true); - net.peer(1).push_blocks(20, false); - net.peer(2).push_blocks(20, false); - - net.peer(1).push_blocks(10, true); - net.peer(2).push_blocks(1, false); - - // peer 1 has the best chain - net.block_until_sync(&mut runtime); - let peer1 = &net.peers()[1]; - assert!(net.peers()[0].blockchain_canon_equals(peer1)); - (net.peers()[1].blockchain_canon_equals(peer1)); - (net.peers()[2].blockchain_canon_equals(peer1)); -} - -#[test] -fn syncs_all_forks() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(4); - 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.block_until_sync(&mut runtime); - // Check that all peers have all of the blocks. - assert_eq!(9, net.peer(0).blocks_count()); - assert_eq!(9, net.peer(1).blocks_count()); -} - -#[test] -fn own_blocks_are_announced() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(3); - net.block_until_sync(&mut runtime); // connect'em - net.peer(0).generate_blocks(1, BlockOrigin::Own, |builder| builder.bake().unwrap()); - - net.block_until_sync(&mut runtime); - - assert_eq!(net.peer(0).client.info().chain.best_number, 1); - assert_eq!(net.peer(1).client.info().chain.best_number, 1); - let peer0 = &net.peers()[0]; - assert!(net.peers()[1].blockchain_canon_equals(peer0)); - (net.peers()[2].blockchain_canon_equals(peer0)); -} - -#[test] -fn blocks_are_not_announced_by_light_nodes() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(0); - - // full peer0 is connected to light peer - // light peer1 is connected to full peer2 - let mut light_config = ProtocolConfig::default(); - light_config.roles = Roles::LIGHT; - net.add_full_peer(&ProtocolConfig::default()); - net.add_light_peer(&light_config); - - // Sync between 0 and 1. - net.peer(0).push_blocks(1, false); - assert_eq!(net.peer(0).client.info().chain.best_number, 1); - net.block_until_sync(&mut runtime); - assert_eq!(net.peer(1).client.info().chain.best_number, 1); - - // Add another node and remove node 0. - net.add_full_peer(&ProtocolConfig::default()); - net.peers.remove(0); - - // Poll for a few seconds and make sure 1 and 2 (now 0 and 1) don't sync together. - let mut delay = futures_timer::Delay::new(Duration::from_secs(5)).compat(); - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { - net.poll(); - delay.poll().map_err(|_| ()) - })).unwrap(); - assert_eq!(net.peer(1).client.info().chain.best_number, 0); -} - -#[test] -fn can_sync_small_non_best_forks() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(2); - net.peer(0).push_blocks(30, false); - net.peer(1).push_blocks(30, false); - - // small fork + reorg on peer 1. - net.peer(0).push_blocks_at(BlockId::Number(30), 2, true); - let small_hash = net.peer(0).client().info().chain.best_hash; - net.peer(0).push_blocks_at(BlockId::Number(30), 10, false); - assert_eq!(net.peer(0).client().info().chain.best_number, 40); - - // peer 1 only ever had the long fork. - net.peer(1).push_blocks(10, false); - assert_eq!(net.peer(1).client().info().chain.best_number, 40); - - assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - assert!(net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none()); - - // poll until the two nodes connect, otherwise announcing the block will not work - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - if net.peer(0).num_peers() == 0 { - Ok(Async::NotReady) - } else { - Ok(Async::Ready(())) - } - })).unwrap(); - - // synchronization: 0 synced to longer chain and 1 didn't sync to small chain. - - assert_eq!(net.peer(0).client().info().chain.best_number, 40); - - assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - assert!(!net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - - net.peer(0).announce_block(small_hash, Vec::new()); - - // after announcing, peer 1 downloads the block. - - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - - assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - if net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none() { - return Ok(Async::NotReady) - } - Ok(Async::Ready(())) - })).unwrap(); - net.block_until_sync(&mut runtime); - - let another_fork = net.peer(0).push_blocks_at(BlockId::Number(35), 2, true); - net.peer(0).announce_block(another_fork, Vec::new()); - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - if net.peer(1).client().header(&BlockId::Hash(another_fork)).unwrap().is_none() { - return Ok(Async::NotReady) - } - Ok(Async::Ready(())) - })).unwrap(); -} - -#[test] -fn can_not_sync_from_light_peer() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - - // given the network with 1 full nodes (#0) and 1 light node (#1) - let mut net = TestNet::new(1); - net.add_light_peer(&Default::default()); - - // generate some blocks on #0 - net.peer(0).push_blocks(1, false); - - // and let the light client sync from this node - net.block_until_sync(&mut runtime); - - // ensure #0 && #1 have the same best block - let full0_info = net.peer(0).client.info().chain; - let light_info = net.peer(1).client.info().chain; - assert_eq!(full0_info.best_number, 1); - assert_eq!(light_info.best_number, 1); - assert_eq!(light_info.best_hash, full0_info.best_hash); - - // add new full client (#2) && remove #0 - net.add_full_peer(&Default::default()); - net.peers.remove(0); - - // ensure that the #2 (now #1) fails to sync block #1 even after 5 seconds - let mut test_finished = futures_timer::Delay::new(Duration::from_secs(5)).compat(); - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - test_finished.poll().map_err(|_| ()) - })).unwrap(); -} - -#[test] -fn light_peer_imports_header_from_announce() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - - fn import_with_announce(net: &mut TestNet, runtime: &mut current_thread::Runtime, hash: H256) { - net.peer(0).announce_block(hash, Vec::new()); - - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { - net.poll(); - if net.peer(1).client().header(&BlockId::Hash(hash)).unwrap().is_some() { - Ok(Async::Ready(())) - } else { - Ok(Async::NotReady) - } - })).unwrap(); - } - - // given the network with 1 full nodes (#0) and 1 light node (#1) - let mut net = TestNet::new(1); - net.add_light_peer(&Default::default()); - - // let them connect to each other - net.block_until_sync(&mut runtime); - - // check that NEW block is imported from announce message - let new_hash = net.peer(0).push_blocks(1, false); - import_with_announce(&mut net, &mut runtime, new_hash); - - // check that KNOWN STALE block is imported from announce message - let known_stale_hash = net.peer(0).push_blocks_at(BlockId::Number(0), 1, true); - import_with_announce(&mut net, &mut runtime, known_stale_hash); -} - -#[test] -fn can_sync_explicit_forks() { - let _ = ::env_logger::try_init(); - let mut runtime = current_thread::Runtime::new().unwrap(); - let mut net = TestNet::new(2); - net.peer(0).push_blocks(30, false); - net.peer(1).push_blocks(30, false); - - // small fork + reorg on peer 1. - net.peer(0).push_blocks_at(BlockId::Number(30), 2, true); - let small_hash = net.peer(0).client().info().chain.best_hash; - let small_number = net.peer(0).client().info().chain.best_number; - net.peer(0).push_blocks_at(BlockId::Number(30), 10, false); - assert_eq!(net.peer(0).client().info().chain.best_number, 40); - - // peer 1 only ever had the long fork. - net.peer(1).push_blocks(10, false); - assert_eq!(net.peer(1).client().info().chain.best_number, 40); - - assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - assert!(net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none()); - - // poll until the two nodes connect, otherwise announcing the block will not work - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - if net.peer(0).num_peers() == 0 || net.peer(1).num_peers() == 0 { - Ok(Async::NotReady) - } else { - Ok(Async::Ready(())) - } - })).unwrap(); - - // synchronization: 0 synced to longer chain and 1 didn't sync to small chain. - - assert_eq!(net.peer(0).client().info().chain.best_number, 40); - - assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - assert!(!net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - - // request explicit sync - let first_peer_id = net.peer(0).id(); - net.peer(1).set_sync_fork_request(vec![first_peer_id], small_hash, small_number); - - // peer 1 downloads the block. - runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { - net.poll(); - - assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - if net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none() { - return Ok(Async::NotReady) - } - Ok(Async::Ready(())) - })).unwrap(); -} diff --git a/core/offchain/Cargo.toml b/core/offchain/Cargo.toml deleted file mode 100644 index 678d943c597ce..0000000000000 --- a/core/offchain/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -description = "Substrate offchain workers" -name = "substrate-offchain" -version = "2.0.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -bytes = "0.4.12" -client = { package = "substrate-client", path = "../../core/client" } -fnv = "1.0.6" -futures01 = { package = "futures", version = "0.1" } -futures-preview = "0.3.0-alpha.19" -futures-timer = "0.4.0" -hyper = "0.12.35" -hyper-tls = "0.3.2" -log = "0.4.8" -threadpool = "1.7" -num_cpus = "1.10" -offchain-primitives = { package = "substrate-offchain-primitives", path = "./primitives" } -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } -parking_lot = "0.9.0" -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -rand = "0.7.2" -sr-primitives = { path = "../../core/sr-primitives" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } -network = { package = "substrate-network", path = "../../core/network" } -keystore = { package = "substrate-keystore", path = "../keystore" } - -[dev-dependencies] -env_logger = "0.7.0" -client-db = { package = "substrate-client-db", path = "../../core/client/db/", default-features = true } -test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } -tokio = "0.1.22" - -[features] -default = [] diff --git a/core/offchain/primitives/Cargo.toml b/core/offchain/primitives/Cargo.toml deleted file mode 100644 index c96a579c4446d..0000000000000 --- a/core/offchain/primitives/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -description = "Substrate offchain workers primitives" -name = "substrate-offchain-primitives" -version = "2.0.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../../client", default-features = false } -sr-primitives = { path = "../../sr-primitives", default-features = false } - -[features] -default = ["std"] -std = [ - "client/std", - "sr-primitives/std" -] diff --git a/core/offchain/primitives/src/lib.rs b/core/offchain/primitives/src/lib.rs deleted file mode 100644 index dda08ae43f570..0000000000000 --- a/core/offchain/primitives/src/lib.rs +++ /dev/null @@ -1,32 +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 . - -//! The Offchain Worker runtime api primitives. - -#![cfg_attr(not(feature = "std"), no_std)] -#![warn(missing_docs)] - -use client::decl_runtime_apis; -use sr_primitives::traits::NumberFor; - -decl_runtime_apis! { - /// The offchain worker api. - pub trait OffchainWorkerApi { - /// Starts the off-chain task for given block number. - #[skip_initialize_block] - fn offchain_worker(number: NumberFor); - } -} diff --git a/core/offchain/src/api.rs b/core/offchain/src/api.rs deleted file mode 100644 index d4301d22ed777..0000000000000 --- a/core/offchain/src/api.rs +++ /dev/null @@ -1,477 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::{ - str::FromStr, - sync::Arc, - convert::TryFrom, - thread::sleep, -}; - -use client::backend::OffchainStorage; -use futures::{StreamExt as _, Future, FutureExt as _, future, channel::mpsc}; -use log::{info, debug, warn, error}; -use network::{PeerId, Multiaddr, NetworkStateInfo}; -use codec::{Encode, Decode}; -use primitives::offchain::{ - Externalities as OffchainExt, HttpRequestId, Timestamp, HttpRequestStatus, HttpError, - OpaqueNetworkState, OpaquePeerId, OpaqueMultiaddr, StorageKind, -}; -use sr_primitives::{generic::BlockId, traits::{self, Extrinsic}}; -use transaction_pool::txpool::{Pool, ChainApi}; - -mod http; -mod timestamp; - -/// A message between the offchain extension and the processing thread. -enum ExtMessage { - SubmitExtrinsic(Vec), -} - -/// Asynchronous offchain API. -/// -/// NOTE this is done to prevent recursive calls into the runtime (which are not supported currently). -pub(crate) struct Api { - sender: mpsc::UnboundedSender, - db: Storage, - network_state: Arc, - _at: BlockId, - /// Is this node a potential validator? - is_validator: bool, - /// Everything HTTP-related is handled by a different struct. - http: http::HttpApi, -} - -fn unavailable_yet(name: &str) -> R { - error!( - "The {:?} API is not available for offchain workers yet. Follow \ - https://github.com/paritytech/substrate/issues/1458 for details", name - ); - Default::default() -} - -const LOCAL_DB: &str = "LOCAL (fork-aware) DB"; -const STORAGE_PREFIX: &[u8] = b"storage"; - -impl OffchainExt for Api -where - Storage: OffchainStorage, - Block: traits::Block, -{ - fn is_validator(&self) -> bool { - self.is_validator - } - - fn submit_transaction(&mut self, ext: Vec) -> Result<(), ()> { - self.sender - .unbounded_send(ExtMessage::SubmitExtrinsic(ext)) - .map(|_| ()) - .map_err(|_| ()) - } - - fn network_state(&self) -> Result { - let external_addresses = self.network_state.external_addresses(); - - let state = NetworkState::new( - self.network_state.peer_id(), - external_addresses, - ); - Ok(OpaqueNetworkState::from(state)) - } - - fn timestamp(&mut self) -> Timestamp { - timestamp::now() - } - - fn sleep_until(&mut self, deadline: Timestamp) { - sleep(timestamp::timestamp_from_now(deadline)); - } - - fn random_seed(&mut self) -> [u8; 32] { - rand::random() - } - - fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { - match kind { - StorageKind::PERSISTENT => self.db.set(STORAGE_PREFIX, key, value), - StorageKind::LOCAL => unavailable_yet(LOCAL_DB), - } - } - - fn local_storage_compare_and_set( - &mut self, - kind: StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - match kind { - StorageKind::PERSISTENT => { - self.db.compare_and_set(STORAGE_PREFIX, key, old_value, new_value) - }, - StorageKind::LOCAL => unavailable_yet(LOCAL_DB), - } - } - - fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { - match kind { - StorageKind::PERSISTENT => self.db.get(STORAGE_PREFIX, key), - StorageKind::LOCAL => unavailable_yet(LOCAL_DB), - } - } - - fn http_request_start( - &mut self, - method: &str, - uri: &str, - _meta: &[u8] - ) -> Result { - self.http.request_start(method, uri) - } - - fn http_request_add_header( - &mut self, - request_id: HttpRequestId, - name: &str, - value: &str - ) -> Result<(), ()> { - self.http.request_add_header(request_id, name, value) - } - - fn http_request_write_body( - &mut self, - request_id: HttpRequestId, - chunk: &[u8], - deadline: Option - ) -> Result<(), HttpError> { - self.http.request_write_body(request_id, chunk, deadline) - } - - fn http_response_wait( - &mut self, - ids: &[HttpRequestId], - deadline: Option - ) -> Vec { - self.http.response_wait(ids, deadline) - } - - fn http_response_headers( - &mut self, - request_id: HttpRequestId - ) -> Vec<(Vec, Vec)> { - self.http.response_headers(request_id) - } - - fn http_response_read_body( - &mut self, - request_id: HttpRequestId, - buffer: &mut [u8], - deadline: Option - ) -> Result { - self.http.response_read_body(request_id, buffer, deadline) - } -} - -/// Information about the local node's network state. -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct NetworkState { - peer_id: PeerId, - external_addresses: Vec, -} - -impl NetworkState { - fn new(peer_id: PeerId, external_addresses: Vec) -> Self { - NetworkState { - peer_id, - external_addresses, - } - } -} - -impl From for OpaqueNetworkState { - fn from(state: NetworkState) -> OpaqueNetworkState { - let enc = Encode::encode(&state.peer_id.into_bytes()); - let peer_id = OpaquePeerId::new(enc); - - let external_addresses: Vec = state - .external_addresses - .iter() - .map(|multiaddr| { - let e = Encode::encode(&multiaddr.to_string()); - OpaqueMultiaddr::new(e) - }) - .collect(); - - OpaqueNetworkState { - peer_id, - external_addresses, - } - } -} - -impl TryFrom for NetworkState { - type Error = (); - - fn try_from(state: OpaqueNetworkState) -> Result { - let inner_vec = state.peer_id.0; - - let bytes: Vec = Decode::decode(&mut &inner_vec[..]).map_err(|_| ())?; - let peer_id = PeerId::from_bytes(bytes).map_err(|_| ())?; - - let external_addresses: Result, Self::Error> = state.external_addresses - .iter() - .map(|enc_multiaddr| -> Result { - let inner_vec = &enc_multiaddr.0; - let bytes = >::decode(&mut &inner_vec[..]).map_err(|_| ())?; - let multiaddr_str = String::from_utf8(bytes).map_err(|_| ())?; - let multiaddr = Multiaddr::from_str(&multiaddr_str).map_err(|_| ())?; - Ok(multiaddr) - }) - .collect(); - let external_addresses = external_addresses?; - - Ok(NetworkState { - peer_id, - external_addresses, - }) - } -} - -/// Offchain extensions implementation API -/// -/// This is the asynchronous processing part of the API. -pub(crate) struct AsyncApi { - receiver: Option>, - transaction_pool: Arc>, - at: BlockId, - /// Everything HTTP-related is handled by a different struct. - http: Option, -} - -impl AsyncApi { - /// Creates new Offchain extensions API implementation an the asynchronous processing part. - pub fn new( - transaction_pool: Arc>, - db: S, - at: BlockId, - network_state: Arc, - is_validator: bool, - ) -> (Api, AsyncApi) { - let (sender, rx) = mpsc::unbounded(); - - let (http_api, http_worker) = http::http(); - - let api = Api { - sender, - db, - network_state, - _at: at, - is_validator, - http: http_api, - }; - - let async_api = AsyncApi { - receiver: Some(rx), - transaction_pool, - at, - http: Some(http_worker), - }; - - (api, async_api) - } - - /// Run a processing task for the API - pub fn process(mut self) -> impl Future { - let receiver = self.receiver.take().expect("Take invoked only once."); - let http = self.http.take().expect("Take invoked only once."); - - let extrinsics = receiver.for_each(move |msg| { - match msg { - ExtMessage::SubmitExtrinsic(ext) => self.submit_extrinsic(ext), - } - }); - - future::join(extrinsics, http) - .map(|((), ())| ()) - } - - fn submit_extrinsic(&mut self, ext: Vec) -> impl Future { - let xt = match ::Extrinsic::decode(&mut &*ext) { - Ok(xt) => xt, - Err(e) => { - warn!("Unable to decode extrinsic: {:?}: {}", ext, e.what()); - return future::Either::Left(future::ready(())) - }, - }; - - info!("Submitting transaction to the pool: {:?} (isSigned: {:?})", xt, xt.is_signed()); - future::Either::Right(self.transaction_pool - .submit_one(&self.at, xt.clone()) - .map(|result| match result { - Ok(hash) => { debug!("[{:?}] Offchain transaction added to the pool.", hash); }, - Err(e) => { warn!("Couldn't submit offchain transaction: {:?}", e); }, - })) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::{convert::{TryFrom, TryInto}, time::SystemTime}; - use sr_primitives::traits::Zero; - use client_db::offchain::LocalStorage; - use network::PeerId; - use test_client::runtime::Block; - - struct MockNetworkStateInfo(); - - impl NetworkStateInfo for MockNetworkStateInfo { - fn external_addresses(&self) -> Vec { - Vec::new() - } - - fn peer_id(&self) -> PeerId { - PeerId::random() - } - } - - fn offchain_api() -> (Api, AsyncApi) { - let _ = env_logger::try_init(); - let db = LocalStorage::new_test(); - let client = Arc::new(test_client::new()); - let pool = Arc::new( - Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone())) - ); - - let mock = Arc::new(MockNetworkStateInfo()); - AsyncApi::new( - pool, - db, - BlockId::Number(Zero::zero()), - mock, - false, - ) - } - - #[test] - fn should_get_timestamp() { - let mut api = offchain_api().0; - - // Get timestamp from std. - let now = SystemTime::now(); - let d: u64 = now.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis().try_into().unwrap(); - - // Get timestamp from offchain api. - let timestamp = api.timestamp(); - - // Compare. - assert!(timestamp.unix_millis() > 0); - assert_eq!(timestamp.unix_millis(), d); - } - - #[test] - fn should_sleep() { - let mut api = offchain_api().0; - - // Arrange. - let now = api.timestamp(); - let delta = primitives::offchain::Duration::from_millis(100); - let deadline = now.add(delta); - - // Act. - api.sleep_until(deadline); - let new_now = api.timestamp(); - - // Assert. - // The diff could be more than the sleep duration. - assert!(new_now.unix_millis() - 100 >= now.unix_millis()); - } - - #[test] - fn should_set_and_get_local_storage() { - // given - let kind = StorageKind::PERSISTENT; - let mut api = offchain_api().0; - let key = b"test"; - - // when - assert_eq!(api.local_storage_get(kind, key), None); - api.local_storage_set(kind, key, b"value"); - - // then - assert_eq!(api.local_storage_get(kind, key), Some(b"value".to_vec())); - } - - #[test] - fn should_compare_and_set_local_storage() { - // given - let kind = StorageKind::PERSISTENT; - let mut api = offchain_api().0; - let key = b"test"; - api.local_storage_set(kind, key, b"value"); - - // when - assert_eq!(api.local_storage_compare_and_set(kind, key, Some(b"val"), b"xxx"), false); - assert_eq!(api.local_storage_get(kind, key), Some(b"value".to_vec())); - - // when - assert_eq!(api.local_storage_compare_and_set(kind, key, Some(b"value"), b"xxx"), true); - assert_eq!(api.local_storage_get(kind, key), Some(b"xxx".to_vec())); - } - - #[test] - fn should_compare_and_set_local_storage_with_none() { - // given - let kind = StorageKind::PERSISTENT; - let mut api = offchain_api().0; - let key = b"test"; - - // when - let res = api.local_storage_compare_and_set(kind, key, None, b"value"); - - // then - assert_eq!(res, true); - assert_eq!(api.local_storage_get(kind, key), Some(b"value".to_vec())); - } - - #[test] - fn should_convert_network_states() { - // given - let state = NetworkState::new( - PeerId::random(), - vec![ - Multiaddr::try_from("/ip4/127.0.0.1/tcp/1234".to_string()).unwrap(), - Multiaddr::try_from("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21").unwrap(), - ], - ); - - // when - let opaque_state = OpaqueNetworkState::from(state.clone()); - let converted_back_state = NetworkState::try_from(opaque_state).unwrap(); - - // then - assert_eq!(state, converted_back_state); - } - - #[test] - fn should_get_random_seed() { - // given - let mut api = offchain_api().0; - let seed = api.random_seed(); - // then - assert_ne!(seed, [0; 32]); - } -} diff --git a/core/offchain/src/api/http.rs b/core/offchain/src/api/http.rs deleted file mode 100644 index 6744a42f959c7..0000000000000 --- a/core/offchain/src/api/http.rs +++ /dev/null @@ -1,1004 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! This module is composed of two structs: [`HttpApi`] and [`HttpWorker`]. Calling the [`http`] -//! function returns a pair of [`HttpApi`] and [`HttpWorker`] that share some state. -//! -//! The [`HttpApi`] is (indirectly) passed to the runtime when calling an offchain worker, while -//! the [`HttpWorker`] must be processed in the background. The [`HttpApi`] mimicks the API of the -//! HTTP-related methods available to offchain workers. -//! -//! The reason for this design is driven by the fact that HTTP requests should continue running -//! (i.e.: the socket should continue being processed) in the background even if the runtime isn't -//! actively calling any function. - -use crate::api::timestamp; -use bytes::Buf as _; -use fnv::FnvHashMap; -use futures::{prelude::*, channel::mpsc, compat::Compat01As03}; -use log::{warn, error}; -use primitives::offchain::{HttpRequestId, Timestamp, HttpRequestStatus, HttpError}; -use std::{fmt, io::Read as _, mem, pin::Pin, task::Context, task::Poll}; - -/// Creates a pair of [`HttpApi`] and [`HttpWorker`]. -pub fn http() -> (HttpApi, HttpWorker) { - let (to_worker, from_api) = mpsc::unbounded(); - let (to_api, from_worker) = mpsc::unbounded(); - - let api = HttpApi { - to_worker, - from_worker: from_worker.fuse(), - // We start with a random ID for the first HTTP request, to prevent mischievous people from - // writing runtime code with hardcoded IDs. - next_id: HttpRequestId(rand::random::() % 2000), - requests: FnvHashMap::default(), - }; - - let engine = HttpWorker { - to_api, - from_api, - // TODO: don't unwrap; we should fall back to the HttpConnector if we fail to create the - // Https one; there doesn't seem to be any built-in way to do this - http_client: HyperClient::new(), - requests: Vec::new(), - }; - - (api, engine) -} - -/// Provides HTTP capabilities. -/// -/// Since this struct is a helper for offchain workers, its API is mimicking the API provided -/// to offchain workers. -pub struct HttpApi { - /// Used to sends messages to the worker. - to_worker: mpsc::UnboundedSender, - /// Used to receive messages from the worker. - /// We use a `Fuse` in order to have an extra protection against panicking. - from_worker: stream::Fuse>, - /// Id to assign to the next HTTP request that is started. - next_id: HttpRequestId, - /// List of HTTP requests in preparation or in progress. - requests: FnvHashMap, -} - -/// One active request within `HttpApi`. -enum HttpApiRequest { - /// The request object is being constructed locally and not started yet. - NotDispatched(hyper::Request, hyper::body::Sender), - /// The request has been dispatched and we're in the process of sending out the body (if the - /// field is `Some`) or waiting for a response (if the field is `None`). - Dispatched(Option), - /// Received a response. - Response(HttpApiRequestRp), - /// A request has been dispatched but the worker notified us of an error. We report this - /// failure to the user as an `IoError` and remove the request from the list as soon as - /// possible. - Fail(hyper::Error), -} - -/// A request within `HttpApi` that has received a response. -struct HttpApiRequestRp { - /// We might still be writing the request's body when the response comes. - /// This field allows to continue writing that body. - sending_body: Option, - /// Status code of the response. - status_code: hyper::StatusCode, - /// Headers of the response. - headers: hyper::HeaderMap, - /// Body of the response, as a channel of `Chunk` objects. - /// While the code is designed to drop the `Receiver` once it ends, we wrap it within a - /// `Fuse` in order to be extra precautious about panics. - /// Elements extracted from the channel are first put into `current_read_chunk`. - /// If the channel produces an error, then that is translated into an `IoError` and the request - /// is removed from the list. - body: stream::Fuse>>, - /// Chunk that has been extracted from the channel and that is currently being read. - /// Reading data from the response should read from this field in priority. - current_read_chunk: Option>, -} - -impl HttpApi { - /// Mimicks the corresponding method in the offchain API. - pub fn request_start( - &mut self, - method: &str, - uri: &str - ) -> Result { - // Start by building the prototype of the request. - // We do this first so that we don't touch anything in `self` if building the prototype - // fails. - let (body_sender, body) = hyper::Body::channel(); - let mut request = hyper::Request::new(body); - *request.method_mut() = hyper::Method::from_bytes(method.as_bytes()).map_err(|_| ())?; - *request.uri_mut() = hyper::Uri::from_shared(From::from(uri)).map_err(|_| ())?; - - let new_id = self.next_id; - debug_assert!(!self.requests.contains_key(&new_id)); - match self.next_id.0.checked_add(1) { - Some(new_id) => self.next_id.0 = new_id, - None => { - error!("Overflow in offchain worker HTTP request ID assignment"); - return Err(()); - } - }; - self.requests.insert(new_id, HttpApiRequest::NotDispatched(request, body_sender)); - - Ok(new_id) - } - - /// Mimicks the corresponding method in the offchain API. - pub fn request_add_header( - &mut self, - request_id: HttpRequestId, - name: &str, - value: &str - ) -> Result<(), ()> { - let request = match self.requests.get_mut(&request_id) { - Some(&mut HttpApiRequest::NotDispatched(ref mut rq, _)) => rq, - _ => return Err(()) - }; - - let name = hyper::header::HeaderName::from_bytes(name.as_bytes()).map_err(|_| ())?; - let value = hyper::header::HeaderValue::from_str(value).map_err(|_| ())?; - // Note that we're always appending headers and never replacing old values. - // We assume here that the user knows what they're doing. - request.headers_mut().append(name, value); - Ok(()) - } - - /// Mimicks the corresponding method in the offchain API. - pub fn request_write_body( - &mut self, - request_id: HttpRequestId, - chunk: &[u8], - deadline: Option - ) -> Result<(), HttpError> { - // Extract the request from the list. - // Don't forget to add it back if necessary when returning. - let mut request = match self.requests.remove(&request_id) { - None => return Err(HttpError::Invalid), - Some(r) => r, - }; - - let mut deadline = timestamp::deadline_to_future(deadline); - // Closure that writes data to a sender, taking the deadline into account. Can return `Ok` - // (if the body has been written), or `DeadlineReached`, or `IoError`. - // If `IoError` is returned, don't forget to remove the request from the list. - let mut poll_sender = move |sender: &mut hyper::body::Sender| -> Result<(), HttpError> { - let mut when_ready = future::maybe_done(Compat01As03::new( - futures01::future::poll_fn(|| sender.poll_ready()) - )); - futures::executor::block_on(future::select(&mut when_ready, &mut deadline)); - match when_ready { - future::MaybeDone::Done(Ok(())) => {} - future::MaybeDone::Done(Err(_)) => return Err(HttpError::IoError), - future::MaybeDone::Future(_) | - future::MaybeDone::Gone => { - debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); - return Err(HttpError::DeadlineReached) - } - }; - - match sender.send_data(hyper::Chunk::from(chunk.to_owned())) { - Ok(()) => Ok(()), - Err(_chunk) => { - error!("HTTP sender refused data despite being ready"); - Err(HttpError::IoError) - }, - } - }; - - loop { - request = match request { - HttpApiRequest::NotDispatched(request, sender) => { - // If the request is not dispatched yet, dispatch it and loop again. - let _ = self.to_worker.unbounded_send(ApiToWorker::Dispatch { - id: request_id, - request - }); - HttpApiRequest::Dispatched(Some(sender)) - } - - HttpApiRequest::Dispatched(Some(mut sender)) => - if !chunk.is_empty() { - match poll_sender(&mut sender) { - Err(HttpError::IoError) => return Err(HttpError::IoError), - other => { - self.requests.insert( - request_id, - HttpApiRequest::Dispatched(Some(sender)) - ); - return other - } - } - } else { - // Writing an empty body is a hint that we should stop writing. Dropping - // the sender. - self.requests.insert(request_id, HttpApiRequest::Dispatched(None)); - return Ok(()) - } - - HttpApiRequest::Response(mut response @ HttpApiRequestRp { sending_body: Some(_), .. }) => - if !chunk.is_empty() { - match poll_sender(response.sending_body.as_mut() - .expect("Can only enter this match branch if Some; qed")) { - Err(HttpError::IoError) => return Err(HttpError::IoError), - other => { - self.requests.insert(request_id, HttpApiRequest::Response(response)); - return other - } - } - - } else { - // Writing an empty body is a hint that we should stop writing. Dropping - // the sender. - self.requests.insert(request_id, HttpApiRequest::Response(HttpApiRequestRp { - sending_body: None, - ..response - })); - return Ok(()) - } - - HttpApiRequest::Fail(_) => - // If the request has already failed, return without putting back the request - // in the list. - return Err(HttpError::IoError), - - v @ HttpApiRequest::Dispatched(None) | - v @ HttpApiRequest::Response(HttpApiRequestRp { sending_body: None, .. }) => { - // We have already finished sending this body. - self.requests.insert(request_id, v); - return Err(HttpError::Invalid) - } - } - } - } - - /// Mimicks the corresponding method in the offchain API. - pub fn response_wait( - &mut self, - ids: &[HttpRequestId], - deadline: Option - ) -> Vec { - // First of all, dispatch all the non-dispatched requests and drop all senders so that the - // user can't write anymore data. - for id in ids { - match self.requests.get_mut(id) { - Some(HttpApiRequest::NotDispatched(_, _)) => {} - Some(HttpApiRequest::Dispatched(sending_body)) | - Some(HttpApiRequest::Response(HttpApiRequestRp { sending_body, .. })) => { - let _ = sending_body.take(); - continue - } - _ => continue - }; - - let (request, _sender) = match self.requests.remove(id) { - Some(HttpApiRequest::NotDispatched(rq, s)) => (rq, s), - _ => unreachable!("we checked for NotDispatched above; qed") - }; - - let _ = self.to_worker.unbounded_send(ApiToWorker::Dispatch { - id: *id, - request - }); - - // We also destroy the sender in order to forbid writing more data. - self.requests.insert(*id, HttpApiRequest::Dispatched(None)); - } - - let mut deadline = timestamp::deadline_to_future(deadline); - - loop { - // Within that loop, first try to see if we have all the elements for a response. - // This includes the situation where the deadline is reached. - { - let mut output = Vec::with_capacity(ids.len()); - let mut must_wait_more = false; - for id in ids { - output.push(match self.requests.get_mut(id) { - None => HttpRequestStatus::Invalid, - Some(HttpApiRequest::NotDispatched(_, _)) => - unreachable!("we replaced all the NotDispatched with Dispatched earlier; qed"), - Some(HttpApiRequest::Dispatched(_)) => { - must_wait_more = true; - HttpRequestStatus::DeadlineReached - }, - Some(HttpApiRequest::Fail(_)) => HttpRequestStatus::IoError, - Some(HttpApiRequest::Response(HttpApiRequestRp { status_code, .. })) => - HttpRequestStatus::Finished(status_code.as_u16()), - }); - } - debug_assert_eq!(output.len(), ids.len()); - - // Are we ready to call `return`? - let is_done = if let future::MaybeDone::Done(_) = deadline { - true - } else if !must_wait_more { - true - } else { - false - }; - - if is_done { - // Requests in "fail" mode are purged before returning. - debug_assert_eq!(output.len(), ids.len()); - for n in (0..ids.len()).rev() { - if let HttpRequestStatus::IoError = output[n] { - self.requests.remove(&ids[n]); - } - } - return output - } - } - - // Grab next message from the worker. We call `continue` if deadline is reached so that - // we loop back and `return`. - let next_message = { - let mut next_msg = future::maybe_done(self.from_worker.next()); - futures::executor::block_on(future::select(&mut next_msg, &mut deadline)); - if let future::MaybeDone::Done(msg) = next_msg { - msg - } else { - debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); - continue - } - }; - - // Update internal state based on received message. - match next_message { - Some(WorkerToApi::Response { id, status_code, headers, body }) => - match self.requests.remove(&id) { - Some(HttpApiRequest::Dispatched(sending_body)) => { - self.requests.insert(id, HttpApiRequest::Response(HttpApiRequestRp { - sending_body, - status_code, - headers, - body: body.fuse(), - current_read_chunk: None, - })); - } - None => {} // can happen if we detected an IO error when sending the body - _ => error!("State mismatch between the API and worker"), - } - - Some(WorkerToApi::Fail { id, error }) => - match self.requests.remove(&id) { - Some(HttpApiRequest::Dispatched(_)) => { - self.requests.insert(id, HttpApiRequest::Fail(error)); - } - None => {} // can happen if we detected an IO error when sending the body - _ => error!("State mismatch between the API and worker"), - } - - None => { - error!("Worker has crashed"); - return ids.iter().map(|_| HttpRequestStatus::IoError).collect() - } - } - - } - } - - /// Mimicks the corresponding method in the offchain API. - pub fn response_headers( - &mut self, - request_id: HttpRequestId - ) -> Vec<(Vec, Vec)> { - // Do an implicit non-blocking wait on the request. - let _ = self.response_wait(&[request_id], Some(timestamp::now())); - - let headers = match self.requests.get(&request_id) { - Some(HttpApiRequest::Response(HttpApiRequestRp { headers, .. })) => headers, - _ => return Vec::new() - }; - - headers - .iter() - .map(|(name, value)| (name.as_str().as_bytes().to_owned(), value.as_bytes().to_owned())) - .collect() - } - - /// Mimicks the corresponding method in the offchain API. - pub fn response_read_body( - &mut self, - request_id: HttpRequestId, - buffer: &mut [u8], - deadline: Option - ) -> Result { - // Do an implicit wait on the request. - let _ = self.response_wait(&[request_id], deadline); - - // Remove the request from the list and handle situations where the request is invalid or - // in the wrong state. - let mut response = match self.requests.remove(&request_id) { - Some(HttpApiRequest::Response(r)) => r, - // Because we called `response_wait` above, we know that the deadline has been reached - // and we still haven't received a response. - Some(rq @ HttpApiRequest::Dispatched(_)) => { - self.requests.insert(request_id, rq); - return Err(HttpError::DeadlineReached) - }, - // The request has failed. - Some(HttpApiRequest::Fail { .. }) => - return Err(HttpError::IoError), - // Request hasn't been dispatched yet; reading the body is invalid. - Some(rq @ HttpApiRequest::NotDispatched(_, _)) => { - self.requests.insert(request_id, rq); - return Err(HttpError::Invalid) - } - None => return Err(HttpError::Invalid) - }; - - // Convert the deadline into a `Future` that resolves when the deadline is reached. - let mut deadline = timestamp::deadline_to_future(deadline); - - loop { - // First read from `current_read_chunk`. - if let Some(mut current_read_chunk) = response.current_read_chunk.take() { - match current_read_chunk.read(buffer) { - Ok(0) => {} - Ok(n) => { - self.requests.insert(request_id, HttpApiRequest::Response(HttpApiRequestRp { - current_read_chunk: Some(current_read_chunk), - .. response - })); - return Ok(n) - }, - Err(err) => { - // This code should never be reached unless there's a logic error somewhere. - error!("Failed to read from current read chunk: {:?}", err); - return Err(HttpError::IoError) - } - } - } - - // If we reach here, that means the `current_read_chunk` is empty and needs to be - // filled with a new chunk from `body`. We block on either the next body or the - // deadline. - let mut next_body = future::maybe_done(response.body.next()); - futures::executor::block_on(future::select(&mut next_body, &mut deadline)); - - if let future::MaybeDone::Done(next_body) = next_body { - match next_body { - Some(Ok(chunk)) => response.current_read_chunk = Some(chunk.reader()), - Some(Err(_)) => return Err(HttpError::IoError), - None => return Ok(0), // eof - } - } - - if let future::MaybeDone::Done(_) = deadline { - self.requests.insert(request_id, HttpApiRequest::Response(response)); - return Err(HttpError::DeadlineReached) - } - } - } -} - -impl fmt::Debug for HttpApi { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_list() - .entries(self.requests.iter()) - .finish() - } -} - -impl fmt::Debug for HttpApiRequest { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - HttpApiRequest::NotDispatched(_, _) => - f.debug_tuple("HttpApiRequest::NotDispatched").finish(), - HttpApiRequest::Dispatched(_) => - f.debug_tuple("HttpApiRequest::Dispatched").finish(), - HttpApiRequest::Response(HttpApiRequestRp { status_code, headers, .. }) => - f.debug_tuple("HttpApiRequest::Response").field(status_code).field(headers).finish(), - HttpApiRequest::Fail(err) => - f.debug_tuple("HttpApiRequest::Fail").field(err).finish(), - } - } -} - -/// Message send from the API to the worker. -enum ApiToWorker { - /// Dispatches a new HTTP request. - Dispatch { - /// ID to send back when the response comes back. - id: HttpRequestId, - /// Request to start executing. - request: hyper::Request, - } -} - -/// Message send from the API to the worker. -enum WorkerToApi { - /// A request has succeeded. - Response { - /// The ID that was passed to the worker. - id: HttpRequestId, - /// Status code of the response. - status_code: hyper::StatusCode, - /// Headers of the response. - headers: hyper::HeaderMap, - /// Body of the response, as a channel of `Chunk` objects. - /// We send the body back through a channel instead of returning the hyper `Body` object - /// because we don't want the `HttpApi` to have to drive the reading. - /// Instead, reading an item from the channel will notify the worker task, which will push - /// the next item. - /// Can also be used to send an error, in case an error happend on the HTTP socket. After - /// an error is sent, the channel will close. - body: mpsc::Receiver>, - }, - /// A request has failed because of an error. The request is then no longer valid. - Fail { - /// The ID that was passed to the worker. - id: HttpRequestId, - /// Error that happened. - error: hyper::Error, - }, -} - -/// Wraps around a `hyper::Client` with either TLS enabled or disabled. -enum HyperClient { - /// Everything is ok and HTTPS is available. - Https(hyper::Client, hyper::Body>), - /// We failed to initialize HTTPS and therefore only allow HTTP. - Http(hyper::Client), -} - -impl HyperClient { - /// Creates new hyper client. - /// - /// By default we will try to initialize the `HttpsConnector`, - /// If that's not possible we'll fall back to `HttpConnector`. - pub fn new() -> Self { - match hyper_tls::HttpsConnector::new(1) { - Ok(tls) => HyperClient::Https(hyper::Client::builder().build(tls)), - Err(e) => { - warn!("Unable to initialize TLS client. Falling back to HTTP-only: {:?}", e); - HyperClient::Http(hyper::Client::new()) - }, - } - } -} - -/// Must be continuously polled for the [`HttpApi`] to properly work. -pub struct HttpWorker { - /// Used to sends messages to the `HttpApi`. - to_api: mpsc::UnboundedSender, - /// Used to receive messages from the `HttpApi`. - from_api: mpsc::UnboundedReceiver, - /// The engine that runs HTTP requests. - http_client: HyperClient, - /// HTTP requests that are being worked on by the engine. - requests: Vec<(HttpRequestId, HttpWorkerRequest)>, -} - -/// HTTP request being processed by the worker. -enum HttpWorkerRequest { - /// Request has been dispatched and is waiting for a response from the Internet. - Dispatched(Compat01As03), - /// Progressively reading the body of the response and sending it to the channel. - ReadBody { - /// Body to read `Chunk`s from. Only used if the channel is ready to accept data. - body: Compat01As03, - /// Channel to the [`HttpApi`] where we send the chunks to. - tx: mpsc::Sender>, - }, -} - -impl Future for HttpWorker { - type Output = (); - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { - // Reminder: this is continuously run in the background. - - // We use a `me` variable because the compiler isn't smart enough to allow borrowing - // multiple fields at once through a `Deref`. - let me = &mut *self; - - // We remove each element from `requests` one by one and add them back only if necessary. - for n in (0..me.requests.len()).rev() { - let (id, request) = me.requests.swap_remove(n); - match request { - HttpWorkerRequest::Dispatched(mut future) => { - // Check for an HTTP response from the Internet. - let mut response = match Future::poll(Pin::new(&mut future), cx) { - Poll::Pending => { - me.requests.push((id, HttpWorkerRequest::Dispatched(future))); - continue - }, - Poll::Ready(Ok(response)) => response, - Poll::Ready(Err(err)) => { - let _ = me.to_api.unbounded_send(WorkerToApi::Fail { - id, - error: err, - }); - continue; // don't insert the request back - } - }; - - // We received a response! Decompose it into its parts. - let status_code = response.status(); - let headers = mem::replace(response.headers_mut(), hyper::HeaderMap::new()); - let body = Compat01As03::new(response.into_body()); - - let (body_tx, body_rx) = mpsc::channel(3); - let _ = me.to_api.unbounded_send(WorkerToApi::Response { - id, - status_code, - headers, - body: body_rx, - }); - - me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx: body_tx })); - cx.waker().wake_by_ref(); // reschedule in order to poll the new future - continue - } - - HttpWorkerRequest::ReadBody { mut body, mut tx } => { - // Before reading from the HTTP response, check that `tx` is ready to accept - // a new chunk. - match tx.poll_ready(cx) { - Poll::Ready(Ok(())) => {} - Poll::Ready(Err(_)) => continue, // don't insert the request back - Poll::Pending => { - me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); - continue - } - } - - // `tx` is ready. Read a chunk from the socket and send it to the channel. - match Stream::poll_next(Pin::new(&mut body), cx) { - Poll::Ready(Some(Ok(chunk))) => { - let _ = tx.start_send(Ok(chunk)); - me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); - cx.waker().wake_by_ref(); // reschedule in order to continue reading - } - Poll::Ready(Some(Err(err))) => { - let _ = tx.start_send(Err(err)); - // don't insert the request back - }, - Poll::Ready(None) => {} // EOF; don't insert the request back - Poll::Pending => { - me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); - }, - } - } - } - } - - // Check for messages coming from the [`HttpApi`]. - match Stream::poll_next(Pin::new(&mut me.from_api), cx) { - Poll::Pending => {}, - Poll::Ready(None) => return Poll::Ready(()), // stops the worker - Poll::Ready(Some(ApiToWorker::Dispatch { id, request })) => { - let future = Compat01As03::new(match me.http_client { - HyperClient::Http(ref mut c) => c.request(request), - HyperClient::Https(ref mut c) => c.request(request), - }); - debug_assert!(me.requests.iter().all(|(i, _)| *i != id)); - me.requests.push((id, HttpWorkerRequest::Dispatched(future))); - cx.waker().wake_by_ref(); // reschedule the task to poll the request - } - } - - Poll::Pending - } -} - -impl fmt::Debug for HttpWorker { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_list() - .entries(self.requests.iter()) - .finish() - } -} - -impl fmt::Debug for HttpWorkerRequest { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - HttpWorkerRequest::Dispatched(_) => - f.debug_tuple("HttpWorkerRequest::Dispatched").finish(), - HttpWorkerRequest::ReadBody { .. } => - f.debug_tuple("HttpWorkerRequest::Response").finish(), - } - } -} - -#[cfg(test)] -mod tests { - use crate::api::timestamp; - use super::http; - use futures::prelude::*; - use futures01::Future as _; - use primitives::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Duration}; - - // Returns an `HttpApi` whose worker is ran in the background, and a `SocketAddr` to an HTTP - // server that runs in the background as well. - macro_rules! build_api_server { - () => {{ - let (api, worker) = http(); - // Note: we have to use tokio because hyper still uses old futures. - std::thread::spawn(move || { - tokio::run(futures::compat::Compat::new(worker.map(|()| Ok::<(), ()>(())))) - }); - let (addr_tx, addr_rx) = std::sync::mpsc::channel(); - std::thread::spawn(move || { - let server = hyper::Server::bind(&"127.0.0.1:0".parse().unwrap()) - .serve(|| { - hyper::service::service_fn_ok(move |_: hyper::Request| { - hyper::Response::new(hyper::Body::from("Hello World!")) - }) - }); - let _ = addr_tx.send(server.local_addr()); - hyper::rt::run(server.map_err(|e| panic!("{:?}", e))); - }); - (api, addr_rx.recv().unwrap()) - }}; - } - - #[test] - fn basic_localhost() { - let deadline = timestamp::now().add(Duration::from_millis(10_000)); - - // Performs an HTTP query to a background HTTP server. - - let (mut api, addr) = build_api_server!(); - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.request_write_body(id, &[], Some(deadline)).unwrap(); - - match api.response_wait(&[id], Some(deadline))[0] { - HttpRequestStatus::Finished(200) => {}, - v => panic!("Connecting to localhost failed: {:?}", v) - } - - let headers = api.response_headers(id); - assert!(headers.iter().any(|(h, _)| h.eq_ignore_ascii_case(b"Date"))); - - let mut buf = vec![0; 2048]; - let n = api.response_read_body(id, &mut buf, Some(deadline)).unwrap(); - assert_eq!(&buf[..n], b"Hello World!"); - } - - #[test] - fn request_start_invalid_call() { - let (mut api, addr) = build_api_server!(); - - match api.request_start("\0", &format!("http://{}", addr)) { - Err(()) => {} - Ok(_) => panic!() - }; - - match api.request_start("GET", "http://\0localhost") { - Err(()) => {} - Ok(_) => panic!() - }; - } - - #[test] - fn request_add_header_invalid_call() { - let (mut api, addr) = build_api_server!(); - - match api.request_add_header(HttpRequestId(0xdead), "Foo", "bar") { - Err(()) => {} - Ok(_) => panic!() - }; - - let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); - match api.request_add_header(id, "\0", "bar") { - Err(()) => {} - Ok(_) => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - match api.request_add_header(id, "Foo", "\0") { - Err(()) => {} - Ok(_) => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.request_add_header(id, "Foo", "Bar").unwrap(); - api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); - match api.request_add_header(id, "Foo2", "Bar") { - Err(()) => {} - Ok(_) => panic!() - }; - - let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); - api.response_headers(id); - match api.request_add_header(id, "Foo2", "Bar") { - Err(()) => {} - Ok(_) => panic!() - }; - - let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); - api.response_read_body(id, &mut [], None).unwrap(); - match api.request_add_header(id, "Foo2", "Bar") { - Err(()) => {} - Ok(_) => panic!() - }; - } - - #[test] - fn request_write_body_invalid_call() { - let (mut api, addr) = build_api_server!(); - - match api.request_write_body(HttpRequestId(0xdead), &[1, 2, 3], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - match api.request_write_body(HttpRequestId(0xdead), &[], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); - api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); - api.request_write_body(id, &[], None).unwrap(); - match api.request_write_body(id, &[], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); - api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); - api.request_write_body(id, &[], None).unwrap(); - match api.request_write_body(id, &[1, 2, 3, 4], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); - api.response_wait(&[id], None); - match api.request_write_body(id, &[], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); - api.response_wait(&[id], None); - match api.request_write_body(id, &[1, 2, 3, 4], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.response_headers(id); - match api.request_write_body(id, &[1, 2, 3, 4], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); - api.response_headers(id); - match api.request_write_body(id, &[], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.response_read_body(id, &mut [], None).unwrap(); - match api.request_write_body(id, &[1, 2, 3, 4], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.response_read_body(id, &mut [], None).unwrap(); - match api.request_write_body(id, &[], None) { - Err(HttpError::Invalid) => {} - _ => panic!() - }; - } - - #[test] - fn response_headers_invalid_call() { - let (mut api, addr) = build_api_server!(); - assert!(api.response_headers(HttpRequestId(0xdead)).is_empty()); - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - assert!(api.response_headers(id).is_empty()); - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.request_write_body(id, &[], None).unwrap(); - while api.response_headers(id).is_empty() { - std::thread::sleep(std::time::Duration::from_millis(100)); - } - - let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); - api.response_wait(&[id], None); - assert!(!api.response_headers(id).is_empty()); - - let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); - let mut buf = [0; 128]; - while api.response_read_body(id, &mut buf, None).unwrap() != 0 {} - assert!(api.response_headers(id).is_empty()); - } - - #[test] - fn response_header_invalid_call() { - let (mut api, addr) = build_api_server!(); - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - assert!(api.response_headers(id).is_empty()); - - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - api.request_add_header(id, "Foo", "Bar").unwrap(); - assert!(api.response_headers(id).is_empty()); - - let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); - api.request_add_header(id, "Foo", "Bar").unwrap(); - api.request_write_body(id, &[], None).unwrap(); - // Note: this test actually sends out the request, and is supposed to test a situation - // where we haven't received any response yet. This test can theoretically fail if the - // HTTP response comes back faster than the kernel schedules our thread, but that is highly - // unlikely. - assert!(api.response_headers(id).is_empty()); - } - - #[test] - fn response_read_body_invalid_call() { - let (mut api, addr) = build_api_server!(); - let mut buf = [0; 512]; - - match api.response_read_body(HttpRequestId(0xdead), &mut buf, None) { - Err(HttpError::Invalid) => {} - _ => panic!() - } - - let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); - while api.response_read_body(id, &mut buf, None).unwrap() != 0 {} - match api.response_read_body(id, &mut buf, None) { - Err(HttpError::Invalid) => {} - _ => panic!() - } - } - - #[test] - fn fuzzing() { - // Uses the API in random ways to try to trigger panicks. - // Doesn't test some paths, such as waiting for multiple requests. Also doesn't test what - // happens if the server force-closes our socket. - - let (mut api, addr) = build_api_server!(); - - for _ in 0..50 { - let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); - - for _ in 0..250 { - match rand::random::() % 6 { - 0 => { let _ = api.request_add_header(id, "Foo", "Bar"); } - 1 => { let _ = api.request_write_body(id, &[1, 2, 3, 4], None); } - 2 => { let _ = api.request_write_body(id, &[], None); } - 3 => { let _ = api.response_wait(&[id], None); } - 4 => { let _ = api.response_headers(id); } - 5 => { - let mut buf = [0; 512]; - let _ = api.response_read_body(id, &mut buf, None); - } - 6 ..= 255 => unreachable!() - } - } - } - } -} diff --git a/core/offchain/src/lib.rs b/core/offchain/src/lib.rs deleted file mode 100644 index a335ca53807ab..0000000000000 --- a/core/offchain/src/lib.rs +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate offchain workers. -//! -//! The offchain workers is a special function of the runtime that -//! gets executed after block is imported. During execution -//! it's able to asynchronously submit extrinsics that will either -//! be propagated to other nodes added to the next block -//! produced by the node as unsigned transactions. -//! -//! Offchain workers can be used for computation-heavy tasks -//! that are not feasible for execution during regular block processing. -//! It can either be tasks that no consensus is required for, -//! or some form of consensus over the data can be built on-chain -//! for instance via: -//! 1. Challenge period for incorrect computations -//! 2. Majority voting for results -//! 3. etc - -#![warn(missing_docs)] - -use std::{ - fmt, - marker::PhantomData, - sync::Arc, -}; - -use parking_lot::Mutex; -use threadpool::ThreadPool; -use client::runtime_api::ApiExt; -use futures::future::Future; -use log::{debug, warn}; -use network::NetworkStateInfo; -use primitives::{offchain, ExecutionContext}; -use sr_primitives::{generic::BlockId, traits::{self, ProvideRuntimeApi}}; -use transaction_pool::txpool::{Pool, ChainApi}; - -mod api; - -pub mod testing; - -pub use offchain_primitives::OffchainWorkerApi; - -/// An offchain workers manager. -pub struct OffchainWorkers { - client: Arc, - db: Storage, - _block: PhantomData, - thread_pool: Mutex, -} - -impl OffchainWorkers { - /// Creates new `OffchainWorkers`. - pub fn new(client: Arc, db: Storage) -> Self { - Self { - client, - db, - _block: PhantomData, - thread_pool: Mutex::new(ThreadPool::new(num_cpus::get())), - } - } -} - -impl fmt::Debug for OffchainWorkers< - Client, - Storage, - Block, -> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("OffchainWorkers").finish() - } -} - -impl OffchainWorkers< - Client, - Storage, - Block, -> where - Block: traits::Block, - Client: ProvideRuntimeApi + Send + Sync + 'static, - Client::Api: OffchainWorkerApi, - Storage: client::backend::OffchainStorage + 'static, -{ - /// Start the offchain workers after given block. - #[must_use] - pub fn on_block_imported( - &self, - number: &::Number, - pool: &Arc>, - network_state: Arc, - is_validator: bool, - ) -> impl Future where A: ChainApi + 'static { - let runtime = self.client.runtime_api(); - let at = BlockId::number(*number); - let has_api = runtime.has_api::>(&at); - debug!("Checking offchain workers at {:?}: {:?}", at, has_api); - - if has_api.unwrap_or(false) { - let (api, runner) = api::AsyncApi::new( - pool.clone(), - self.db.clone(), - at.clone(), - network_state.clone(), - is_validator, - ); - debug!("Spawning offchain workers at {:?}", at); - let number = *number; - let client = self.client.clone(); - self.spawn_worker(move || { - let runtime = client.runtime_api(); - let api = Box::new(api); - debug!("Running offchain workers at {:?}", at); - let run = runtime.offchain_worker_with_context( - &at, - ExecutionContext::OffchainCall(Some((api, offchain::Capabilities::all()))), - number, - ); - if let Err(e) = run { - log::error!("Error running offchain workers at {:?}: {:?}", at, e); - } - }); - futures::future::Either::Left(runner.process()) - } else { - futures::future::Either::Right(futures::future::ready(())) - } - } - - /// Spawns a new offchain worker. - /// - /// We spawn offchain workers for each block in a separate thread, - /// since they can run for a significant amount of time - /// in a blocking fashion and we don't want to block the runtime. - /// - /// Note that we should avoid that if we switch to future-based runtime in the future, - /// alternatively: - fn spawn_worker(&self, f: impl FnOnce() -> () + Send + 'static) { - self.thread_pool.lock().execute(f); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use network::{Multiaddr, PeerId}; - - struct MockNetworkStateInfo(); - - impl NetworkStateInfo for MockNetworkStateInfo { - fn external_addresses(&self) -> Vec { - Vec::new() - } - - fn peer_id(&self) -> PeerId { - PeerId::random() - } - } - - #[test] - fn should_call_into_runtime_and_produce_extrinsic() { - // given - let _ = env_logger::try_init(); - let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone()))); - let db = client_db::offchain::LocalStorage::new_test(); - let network_state = Arc::new(MockNetworkStateInfo()); - - // when - let offchain = OffchainWorkers::new(client, db); - futures::executor::block_on(offchain.on_block_imported(&0u64, &pool, network_state, false)); - - // then - assert_eq!(pool.status().ready, 1); - assert_eq!(pool.ready().next().unwrap().is_propagateable(), false); - } -} diff --git a/core/offchain/src/testing.rs b/core/offchain/src/testing.rs deleted file mode 100644 index e1cc7f71a3811..0000000000000 --- a/core/offchain/src/testing.rs +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Offchain Externalities implementation for tests. - -use std::{ - collections::BTreeMap, - sync::Arc, -}; -use client::backend::OffchainStorage; -use parking_lot::RwLock; -use primitives::offchain::{ - self, - HttpError, - HttpRequestId as RequestId, - HttpRequestStatus as RequestStatus, - Timestamp, - StorageKind, - OpaqueNetworkState, -}; - -/// Pending request. -#[derive(Debug, Default, PartialEq, Eq)] -pub struct PendingRequest { - /// HTTP method - pub method: String, - /// URI - pub uri: String, - /// Encoded Metadata - pub meta: Vec, - /// Request headers - pub headers: Vec<(String, String)>, - /// Request body - pub body: Vec, - /// Has the request been sent already. - pub sent: bool, - /// Response body - pub response: Option>, - /// Number of bytes already read from the response body. - pub read: usize, - /// Response headers - pub response_headers: Vec<(String, String)>, -} - -/// Internal state of the externalities. -/// -/// This can be used in tests to respond or assert stuff about interactions. -#[derive(Debug, Default)] -pub struct State { - /// A list of pending requests. - pub requests: BTreeMap, - expected_requests: BTreeMap, - /// Persistent local storage - pub persistent_storage: client::in_mem::OffchainStorage, - /// Local storage - pub local_storage: client::in_mem::OffchainStorage, - /// A vector of transactions submitted from the runtime. - pub transactions: Vec>, -} - -impl State { - /// Asserts that pending request has been submitted and fills it's response. - pub fn fulfill_pending_request( - &mut self, - id: u16, - expected: PendingRequest, - response: impl Into>, - response_headers: impl IntoIterator, - ) { - match self.requests.get_mut(&RequestId(id)) { - None => { - panic!("Missing pending request: {:?}.\n\nAll: {:?}", id, self.requests); - } - Some(req) => { - assert_eq!( - *req, - expected, - ); - req.response = Some(response.into()); - req.response_headers = response_headers.into_iter().collect(); - } - } - } - - fn fulfill_expected(&mut self, id: u16) { - if let Some(mut req) = self.expected_requests.remove(&RequestId(id)) { - let response = req.response.take().expect("Response checked while added."); - let headers = std::mem::replace(&mut req.response_headers, vec![]); - self.fulfill_pending_request(id, req, response, headers); - } - } - - /// Add expected HTTP request. - /// - /// This method can be used to initialize expected HTTP requests and their responses - /// before running the actual code that utilizes them (for instance before calling into runtime). - /// Expected request has to be fulfilled before this struct is dropped, - /// the `response` and `response_headers` fields will be used to return results to the callers. - pub fn expect_request(&mut self, id: u16, expected: PendingRequest) { - if expected.response.is_none() { - panic!("Expected request needs to have a response."); - } - self.expected_requests.insert(RequestId(id), expected); - } -} - -impl Drop for State { - fn drop(&mut self) { - if !self.expected_requests.is_empty() { - panic!("Unfulfilled expected requests: {:?}", self.expected_requests); - } - } -} - -/// Implementation of offchain externalities used for tests. -#[derive(Clone, Default, Debug)] -pub struct TestOffchainExt(pub Arc>); - -impl TestOffchainExt { - /// Create new `TestOffchainExt` and a reference to the internal state. - pub fn new() -> (Self, Arc>) { - let ext = Self::default(); - let state = ext.0.clone(); - (ext, state) - } -} - -impl offchain::Externalities for TestOffchainExt { - fn is_validator(&self) -> bool { - unimplemented!("not needed in tests so far") - } - - fn submit_transaction(&mut self, ex: Vec) -> Result<(), ()> { - let mut state = self.0.write(); - state.transactions.push(ex); - Ok(()) - } - - fn network_state(&self) -> Result { - Ok(OpaqueNetworkState { - peer_id: Default::default(), - external_addresses: vec![], - }) - } - - fn timestamp(&mut self) -> Timestamp { - unimplemented!("not needed in tests so far") - } - - fn sleep_until(&mut self, _deadline: Timestamp) { - unimplemented!("not needed in tests so far") - } - - fn random_seed(&mut self) -> [u8; 32] { - unimplemented!("not needed in tests so far") - } - - fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { - let mut state = self.0.write(); - match kind { - StorageKind::LOCAL => &mut state.local_storage, - StorageKind::PERSISTENT => &mut state.persistent_storage, - }.set(b"", key, value); - } - - fn local_storage_compare_and_set( - &mut self, - kind: StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8] - ) -> bool { - let mut state = self.0.write(); - match kind { - StorageKind::LOCAL => &mut state.local_storage, - StorageKind::PERSISTENT => &mut state.persistent_storage, - }.compare_and_set(b"", key, old_value, new_value) - } - - fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { - let state = self.0.read(); - match kind { - StorageKind::LOCAL => &state.local_storage, - StorageKind::PERSISTENT => &state.persistent_storage, - }.get(b"", key) - } - - fn http_request_start(&mut self, method: &str, uri: &str, meta: &[u8]) -> Result { - let mut state = self.0.write(); - let id = RequestId(state.requests.len() as u16); - state.requests.insert(id.clone(), PendingRequest { - method: method.into(), - uri: uri.into(), - meta: meta.into(), - ..Default::default() - }); - Ok(id) - } - - fn http_request_add_header( - &mut self, - request_id: RequestId, - name: &str, - value: &str, - ) -> Result<(), ()> { - let mut state = self.0.write(); - if let Some(req) = state.requests.get_mut(&request_id) { - req.headers.push((name.into(), value.into())); - Ok(()) - } else { - Err(()) - } - } - - fn http_request_write_body( - &mut self, - request_id: RequestId, - chunk: &[u8], - _deadline: Option - ) -> Result<(), HttpError> { - let mut state = self.0.write(); - - let sent = { - let req = state.requests.get_mut(&request_id).ok_or(HttpError::IoError)?; - req.body.extend(chunk); - if chunk.is_empty() { - req.sent = true; - } - req.sent - }; - - if sent { - state.fulfill_expected(request_id.0); - } - - Ok(()) - } - - fn http_response_wait( - &mut self, - ids: &[RequestId], - _deadline: Option, - ) -> Vec { - let state = self.0.read(); - - ids.iter().map(|id| match state.requests.get(id) { - Some(req) if req.response.is_none() => - panic!("No `response` provided for request with id: {:?}", id), - None => RequestStatus::Invalid, - _ => RequestStatus::Finished(200), - }).collect() - } - - fn http_response_headers(&mut self, request_id: RequestId) -> Vec<(Vec, Vec)> { - let state = self.0.read(); - if let Some(req) = state.requests.get(&request_id) { - req.response_headers - .clone() - .into_iter() - .map(|(k, v)| (k.into_bytes(), v.into_bytes())) - .collect() - } else { - Default::default() - } - } - - fn http_response_read_body( - &mut self, - request_id: RequestId, - buffer: &mut [u8], - _deadline: Option - ) -> Result { - let mut state = self.0.write(); - if let Some(req) = state.requests.get_mut(&request_id) { - let response = req.response - .as_mut() - .expect(&format!("No response provided for request: {:?}", request_id)); - - if req.read >= response.len() { - // Remove the pending request as per spec. - state.requests.remove(&request_id); - Ok(0) - } else { - let read = std::cmp::min(buffer.len(), response[req.read..].len()); - buffer[0..read].copy_from_slice(&response[req.read..read]); - req.read += read; - Ok(read) - } - } else { - Err(HttpError::IoError) - } - } -} diff --git a/core/panic-handler/Cargo.toml b/core/panic-handler/Cargo.toml deleted file mode 100644 index 9724b9291926a..0000000000000 --- a/core/panic-handler/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "substrate-panic-handler" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Substrate panic handler." -edition = "2018" - -[dependencies] -backtrace = "0.3.38" -log = "0.4.8" diff --git a/core/panic-handler/src/lib.rs b/core/panic-handler/src/lib.rs deleted file mode 100644 index 1df05120c119d..0000000000000 --- a/core/panic-handler/src/lib.rs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Custom panic hook with bug report link -//! -//! This crate provides the [`set`] function, which wraps around [`std::panic::set_hook`] and -//! sets up a panic hook that prints a backtrace and invites the user to open an issue to the -//! given URL. -//! -//! By default, the panic handler aborts the process by calling [`std::process::exit`]. This can -//! temporarily be disabled by using an [`AbortGuard`]. - -use backtrace::Backtrace; -use std::io::{self, Write}; -use std::marker::PhantomData; -use std::panic::{self, PanicInfo}; -use std::cell::Cell; -use std::thread; - -thread_local! { - static ON_PANIC: Cell = Cell::new(OnPanic::Abort); -} - -/// Panic action. -#[derive(Debug, Clone, Copy, PartialEq)] -enum OnPanic { - /// Abort when panic occurs. - Abort, - /// Unwind when panic occurs. - Unwind, - /// Always unwind even if someone changes strategy to Abort afterwards. - NeverAbort, -} - -/// Set the panic hook. -/// -/// Calls [`std::panic::set_hook`] to set up the panic hook. -/// -/// The `bug_url` parameter is an invitation for users to visit that URL to submit a bug report -/// in the case where a panic happens. -pub fn set(bug_url: &'static str, version: &str) { - panic::set_hook(Box::new({ - let version = version.to_string(); - move |c| { - panic_hook(c, bug_url, &version) - } - })); -} - -macro_rules! ABOUT_PANIC { - () => (" -This is a bug. Please report it at: - - {} -")} - -/// Set aborting flag. Returns previous value of the flag. -fn set_abort(on_panic: OnPanic) -> OnPanic { - ON_PANIC.with(|val| { - let prev = val.get(); - match prev { - OnPanic::Abort | OnPanic::Unwind => val.set(on_panic), - OnPanic::NeverAbort => (), - } - prev - }) -} - -/// RAII guard for whether panics in the current thread should unwind or abort. -/// -/// Sets a thread-local abort flag on construction and reverts to the previous setting when dropped. -/// Does not implement `Send` on purpose. -/// -/// > **Note**: Because we restore the previous value when dropped, you are encouraged to leave -/// > the `AbortGuard` on the stack and let it destroy itself naturally. -pub struct AbortGuard { - /// Value that was in `ABORT` before we created this guard. - previous_val: OnPanic, - /// Marker so that `AbortGuard` doesn't implement `Send`. - _not_send: PhantomData> -} - -impl AbortGuard { - /// Create a new guard. While the guard is alive, panics that happen in the current thread will - /// unwind the stack (unless another guard is created afterwards). - pub fn force_unwind() -> AbortGuard { - AbortGuard { - previous_val: set_abort(OnPanic::Unwind), - _not_send: PhantomData - } - } - - /// Create a new guard. While the guard is alive, panics that happen in the current thread will - /// abort the process (unless another guard is created afterwards). - pub fn force_abort() -> AbortGuard { - AbortGuard { - previous_val: set_abort(OnPanic::Abort), - _not_send: PhantomData - } - } - - /// Create a new guard. While the guard is alive, panics that happen in the current thread will - /// **never** abort the process (even if `AbortGuard::force_abort()` guard will be created afterwards). - pub fn never_abort() -> AbortGuard { - AbortGuard { - previous_val: set_abort(OnPanic::NeverAbort), - _not_send: PhantomData - } - } -} - -impl Drop for AbortGuard { - fn drop(&mut self) { - set_abort(self.previous_val); - } -} - -/// Function being called when a panic happens. -fn panic_hook(info: &PanicInfo, report_url: &'static str, version: &str) { - let location = info.location(); - let file = location.as_ref().map(|l| l.file()).unwrap_or(""); - let line = location.as_ref().map(|l| l.line()).unwrap_or(0); - - let msg = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => match info.payload().downcast_ref::() { - Some(s) => &s[..], - None => "Box", - } - }; - - let thread = thread::current(); - let name = thread.name().unwrap_or(""); - - let backtrace = Backtrace::new(); - - let mut stderr = io::stderr(); - - let _ = writeln!(stderr, ""); - let _ = writeln!(stderr, "===================="); - let _ = writeln!(stderr, ""); - let _ = writeln!(stderr, "Version: {}", version); - let _ = writeln!(stderr, ""); - let _ = writeln!(stderr, "{:?}", backtrace); - let _ = writeln!(stderr, ""); - let _ = writeln!( - stderr, - "Thread '{}' panicked at '{}', {}:{}", - name, msg, file, line - ); - - let _ = writeln!(stderr, ABOUT_PANIC!(), report_url); - ON_PANIC.with(|val| { - if val.get() == OnPanic::Abort { - ::std::process::exit(1); - } - }) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn does_not_abort() { - set("test", "1.2.3"); - let _guard = AbortGuard::force_unwind(); - ::std::panic::catch_unwind(|| panic!()).ok(); - } - - #[test] - fn does_not_abort_after_never_abort() { - set("test", "1.2.3"); - let _guard = AbortGuard::never_abort(); - let _guard = AbortGuard::force_abort(); - std::panic::catch_unwind(|| panic!()).ok(); - } -} diff --git a/core/peerset/Cargo.toml b/core/peerset/Cargo.toml deleted file mode 100644 index 96b721b41caf0..0000000000000 --- a/core/peerset/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -description = "Connectivity manager based on reputation" -homepage = "http://parity.io" -license = "GPL-3.0" -name = "substrate-peerset" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -futures-preview = "0.3.0-alpha.19" -libp2p = { version = "0.12.0", default-features = false } -linked-hash-map = "0.5.2" -log = "0.4.8" -lru-cache = "0.1.2" -serde_json = "1.0.41" - -[dev-dependencies] -rand = "0.7.2" diff --git a/core/peerset/src/lib.rs b/core/peerset/src/lib.rs deleted file mode 100644 index a243fd00bd2b7..0000000000000 --- a/core/peerset/src/lib.rs +++ /dev/null @@ -1,652 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Peer Set Manager (PSM). Contains the strategy for choosing which nodes the network should be -//! connected to. - -mod peersstate; - -use std::{collections::{HashSet, HashMap}, collections::VecDeque, time::Instant}; -use futures::{prelude::*, channel::mpsc}; -use libp2p::PeerId; -use log::{debug, error, trace}; -use serde_json::json; -use std::{pin::Pin, task::Context, task::Poll}; - -/// We don't accept nodes whose reputation is under this value. -const BANNED_THRESHOLD: i32 = 82 * (i32::min_value() / 100); -/// Reputation change for a node when we get disconnected from it. -const DISCONNECT_REPUTATION_CHANGE: i32 = -10; -/// Reserved peers group ID -const RESERVED_NODES: &'static str = "reserved"; - -#[derive(Debug)] -enum Action { - AddReservedPeer(PeerId), - RemoveReservedPeer(PeerId), - SetReservedOnly(bool), - ReportPeer(PeerId, i32), - SetPriorityGroup(String, HashSet), - AddToPriorityGroup(String, PeerId), - RemoveFromPriorityGroup(String, PeerId), -} - -/// Shared handle to the peer set manager (PSM). Distributed around the code. -#[derive(Debug, Clone)] -pub struct PeersetHandle { - tx: mpsc::UnboundedSender, -} - -impl PeersetHandle { - /// Adds a new reserved peer. The peerset will make an effort to always remain connected to - /// this peer. - /// - /// Has no effect if the node was already a reserved peer. - /// - /// > **Note**: Keep in mind that the networking has to know an address for this node, - /// > otherwise it will not be able to connect to it. - pub fn add_reserved_peer(&self, peer_id: PeerId) { - let _ = self.tx.unbounded_send(Action::AddReservedPeer(peer_id)); - } - - /// Remove a previously-added reserved peer. - /// - /// Has no effect if the node was not a reserved peer. - pub fn remove_reserved_peer(&self, peer_id: PeerId) { - let _ = self.tx.unbounded_send(Action::RemoveReservedPeer(peer_id)); - } - - /// Sets whether or not the peerset only has connections . - pub fn set_reserved_only(&self, reserved: bool) { - let _ = self.tx.unbounded_send(Action::SetReservedOnly(reserved)); - } - - /// Reports an adjustment to the reputation of the given peer. - pub fn report_peer(&self, peer_id: PeerId, score_diff: i32) { - let _ = self.tx.unbounded_send(Action::ReportPeer(peer_id, score_diff)); - } - - /// Modify a priority group. - pub fn set_priority_group(&self, group_id: String, peers: HashSet) { - let _ = self.tx.unbounded_send(Action::SetPriorityGroup(group_id, peers)); - } - - /// Add a peer to a priority group. - pub fn add_to_priority_group(&self, group_id: String, peer_id: PeerId) { - let _ = self.tx.unbounded_send(Action::AddToPriorityGroup(group_id, peer_id)); - } - - /// Remove a peer from a priority group. - pub fn remove_from_priority_group(&self, group_id: String, peer_id: PeerId) { - let _ = self.tx.unbounded_send(Action::RemoveFromPriorityGroup(group_id, peer_id)); - } -} - -/// Message that can be sent by the peer set manager (PSM). -#[derive(Debug, PartialEq)] -pub enum Message { - /// Request to open a connection to the given peer. From the point of view of the PSM, we are - /// immediately connected. - Connect(PeerId), - - /// Drop the connection to the given peer, or cancel the connection attempt after a `Connect`. - Drop(PeerId), - - /// Equivalent to `Connect` for the peer corresponding to this incoming index. - Accept(IncomingIndex), - - /// Equivalent to `Drop` for the peer corresponding to this incoming index. - Reject(IncomingIndex), -} - -/// Opaque identifier for an incoming connection. Allocated by the network. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct IncomingIndex(pub u64); - -impl From for IncomingIndex { - fn from(val: u64) -> IncomingIndex { - IncomingIndex(val) - } -} - -/// Configuration to pass when creating the peer set manager. -#[derive(Debug)] -pub struct PeersetConfig { - /// Maximum number of ingoing links to peers. - pub in_peers: u32, - - /// Maximum number of outgoing links to peers. - pub out_peers: u32, - - /// List of bootstrap nodes to initialize the peer with. - /// - /// > **Note**: Keep in mind that the networking has to know an address for these nodes, - /// > otherwise it will not be able to connect to them. - pub bootnodes: Vec, - - /// If true, we only accept reserved nodes. - pub reserved_only: bool, - - /// List of nodes that we should always be connected to. - /// - /// > **Note**: Keep in mind that the networking has to know an address for these nodes, - /// > otherwise it will not be able to connect to them. - pub reserved_nodes: Vec, -} - -/// Side of the peer set manager owned by the network. In other words, the "receiving" side. -/// -/// Implements the `Stream` trait and can be polled for messages. The `Stream` never ends and never -/// errors. -#[derive(Debug)] -pub struct Peerset { - data: peersstate::PeersState, - /// If true, we only accept reserved nodes. - reserved_only: bool, - /// Receiver for messages from the `PeersetHandle` and from `tx`. - rx: mpsc::UnboundedReceiver, - /// Sending side of `rx`. - tx: mpsc::UnboundedSender, - /// Queue of messages to be emitted when the `Peerset` is polled. - message_queue: VecDeque, - /// When the `Peerset` was created. - created: Instant, - /// Last time when we updated the reputations of connected nodes. - latest_time_update: Instant, -} - -impl Peerset { - /// Builds a new peerset from the given configuration. - pub fn from_config(config: PeersetConfig) -> (Peerset, PeersetHandle) { - let (tx, rx) = mpsc::unbounded(); - - let handle = PeersetHandle { - tx: tx.clone(), - }; - - let mut peerset = Peerset { - data: peersstate::PeersState::new(config.in_peers, config.out_peers, config.reserved_only), - tx, - rx, - reserved_only: config.reserved_only, - message_queue: VecDeque::new(), - created: Instant::now(), - latest_time_update: Instant::now(), - }; - - peerset.data.set_priority_group(RESERVED_NODES, config.reserved_nodes.into_iter().collect()); - for peer_id in config.bootnodes { - if let peersstate::Peer::Unknown(entry) = peerset.data.peer(&peer_id) { - entry.discover(); - } else { - debug!(target: "peerset", "Duplicate bootnode in config: {:?}", peer_id); - } - } - - peerset.alloc_slots(); - (peerset, handle) - } - - fn on_add_reserved_peer(&mut self, peer_id: PeerId) { - let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); - reserved.insert(peer_id); - self.data.set_priority_group(RESERVED_NODES, reserved); - self.alloc_slots(); - } - - fn on_remove_reserved_peer(&mut self, peer_id: PeerId) { - let mut reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); - reserved.remove(&peer_id); - self.data.set_priority_group(RESERVED_NODES, reserved); - match self.data.peer(&peer_id) { - peersstate::Peer::Connected(peer) => { - if self.reserved_only { - peer.disconnect(); - self.message_queue.push_back(Message::Drop(peer_id)); - } - } - peersstate::Peer::NotConnected(_) => {}, - peersstate::Peer::Unknown(_) => {}, - } - } - - fn on_set_reserved_only(&mut self, reserved_only: bool) { - self.reserved_only = reserved_only; - self.data.set_priority_only(reserved_only); - - if self.reserved_only { - // Disconnect non-reserved nodes. - let reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); - for peer_id in self.data.connected_peers().cloned().collect::>().into_iter() { - let peer = self.data.peer(&peer_id).into_connected() - .expect("We are enumerating connected peers, therefore the peer is connected; qed"); - if !reserved.contains(&peer_id) { - peer.disconnect(); - self.message_queue.push_back(Message::Drop(peer_id)); - } - } - } else { - self.alloc_slots(); - } - } - - fn on_set_priority_group(&mut self, group_id: &str, peers: HashSet) { - self.data.set_priority_group(group_id, peers); - self.alloc_slots(); - } - - fn on_add_to_priority_group(&mut self, group_id: &str, peer_id: PeerId) { - self.data.add_to_priority_group(group_id, peer_id); - self.alloc_slots(); - } - - fn on_remove_from_priority_group(&mut self, group_id: &str, peer_id: PeerId) { - self.data.remove_from_priority_group(group_id, &peer_id); - self.alloc_slots(); - } - - fn on_report_peer(&mut self, peer_id: PeerId, score_diff: i32) { - // We want reputations to be up-to-date before adjusting them. - self.update_time(); - - match self.data.peer(&peer_id) { - peersstate::Peer::Connected(mut peer) => { - peer.add_reputation(score_diff); - if peer.reputation() < BANNED_THRESHOLD { - peer.disconnect(); - self.message_queue.push_back(Message::Drop(peer_id)); - } - }, - peersstate::Peer::NotConnected(mut peer) => peer.add_reputation(score_diff), - peersstate::Peer::Unknown(peer) => peer.discover().add_reputation(score_diff), - } - } - - /// Updates the value of `self.latest_time_update` and performs all the updates that happen - /// over time, such as reputation increases for staying connected. - fn update_time(&mut self) { - // We basically do `(now - self.latest_update).as_secs()`, except that by the way we do it - // we know that we're not going to miss seconds because of rounding to integers. - let secs_diff = { - let now = Instant::now(); - let elapsed_latest = self.latest_time_update - self.created; - let elapsed_now = now - self.created; - self.latest_time_update = now; - elapsed_now.as_secs() - elapsed_latest.as_secs() - }; - - // For each elapsed second, move the node reputation towards zero. - // If we multiply each second the reputation by `k` (where `k` is between 0 and 1), it - // takes `ln(0.5) / ln(k)` seconds to reduce the reputation by half. Use this formula to - // empirically determine a value of `k` that looks correct. - for _ in 0..secs_diff { - for peer in self.data.peers().cloned().collect::>() { - // We use `k = 0.98`, so we divide by `50`. With that value, it takes 34.3 seconds - // to reduce the reputation by half. - fn reput_tick(reput: i32) -> i32 { - let mut diff = reput / 50; - if diff == 0 && reput < 0 { - diff = -1; - } else if diff == 0 && reput > 0 { - diff = 1; - } - reput.saturating_sub(diff) - } - match self.data.peer(&peer) { - peersstate::Peer::Connected(mut peer) => - peer.set_reputation(reput_tick(peer.reputation())), - peersstate::Peer::NotConnected(mut peer) => - peer.set_reputation(reput_tick(peer.reputation())), - peersstate::Peer::Unknown(_) => unreachable!("We iterate over known peers; qed") - } - } - } - } - - /// Try to fill available out slots with nodes. - fn alloc_slots(&mut self) { - self.update_time(); - - // Try to grab the next node to attempt to connect to. - while let Some(next) = { - if self.reserved_only { - self.data.priority_not_connected_peer_from_group(RESERVED_NODES) - } else { - self.data.priority_not_connected_peer() - } - } { - match next.try_outgoing() { - Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())), - Err(_) => break, // No more slots available. - } - } - - loop { - if self.reserved_only { - break - } - - // Try to grab the next node to attempt to connect to. - let next = match self.data.highest_not_connected_peer() { - Some(p) => p, - None => break, // No known node to add. - }; - - // Don't connect to nodes with an abysmal reputation. - if next.reputation() < BANNED_THRESHOLD { - break; - } - - match next.try_outgoing() { - Ok(conn) => self.message_queue.push_back(Message::Connect(conn.into_peer_id())), - Err(_) => break, // No more slots available. - } - } - } - - /// Indicate that we received an incoming connection. Must be answered either with - /// a corresponding `Accept` or `Reject`, except if we were already connected to this peer. - /// - /// Note that this mechanism is orthogonal to `Connect`/`Drop`. Accepting an incoming - /// connection implicitly means `Connect`, but incoming connections aren't cancelled by - /// `dropped`. - /// - // Implementation note: because of concurrency issues, it is possible that we push a `Connect` - // message to the output channel with a `PeerId`, and that `incoming` gets called with the same - // `PeerId` before that message has been read by the user. In this situation we must not answer. - pub fn incoming(&mut self, peer_id: PeerId, index: IncomingIndex) { - trace!(target: "peerset", "Incoming {:?}", peer_id); - self.update_time(); - - let not_connected = match self.data.peer(&peer_id) { - // If we're already connected, don't answer, as the docs mention. - peersstate::Peer::Connected(_) => return, - peersstate::Peer::NotConnected(entry) => entry, - peersstate::Peer::Unknown(entry) => entry.discover(), - }; - - if not_connected.reputation() < BANNED_THRESHOLD { - self.message_queue.push_back(Message::Reject(index)); - return - } - - match not_connected.try_accept_incoming() { - Ok(_) => self.message_queue.push_back(Message::Accept(index)), - Err(_) => self.message_queue.push_back(Message::Reject(index)), - } - } - - /// Indicate that we dropped an active connection with a peer, or that we failed to connect. - /// - /// Must only be called after the PSM has either generated a `Connect` message with this - /// `PeerId`, or accepted an incoming connection with this `PeerId`. - pub fn dropped(&mut self, peer_id: PeerId) { - trace!(target: "peerset", "Dropping {:?}", peer_id); - - // We want reputations to be up-to-date before adjusting them. - self.update_time(); - - match self.data.peer(&peer_id) { - peersstate::Peer::Connected(mut entry) => { - // Decrease the node's reputation so that we don't try it again and again and again. - entry.add_reputation(DISCONNECT_REPUTATION_CHANGE); - entry.disconnect(); - } - peersstate::Peer::NotConnected(_) | peersstate::Peer::Unknown(_) => - error!(target: "peerset", "Received dropped() for non-connected node"), - } - - self.alloc_slots(); - } - - /// Adds discovered peer ids to the PSM. - /// - /// > **Note**: There is no equivalent "expired" message, meaning that it is the responsibility - /// > of the PSM to remove `PeerId`s that fail to dial too often. - pub fn discovered>(&mut self, peer_ids: I) { - let mut discovered_any = false; - - for peer_id in peer_ids { - if let peersstate::Peer::Unknown(entry) = self.data.peer(&peer_id) { - entry.discover(); - discovered_any = true; - } - } - - if discovered_any { - self.alloc_slots(); - } - } - - /// Reports an adjustment to the reputation of the given peer. - pub fn report_peer(&mut self, peer_id: PeerId, score_diff: i32) { - // We don't immediately perform the adjustments in order to have state consistency. We - // don't want the reporting here to take priority over messages sent using the - // `PeersetHandle`. - let _ = self.tx.unbounded_send(Action::ReportPeer(peer_id, score_diff)); - } - - /// Produces a JSON object containing the state of the peerset manager, for debugging purposes. - pub fn debug_info(&mut self) -> serde_json::Value { - self.update_time(); - - json!({ - "nodes": self.data.peers().cloned().collect::>().into_iter().map(|peer_id| { - let state = match self.data.peer(&peer_id) { - peersstate::Peer::Connected(entry) => json!({ - "connected": true, - "reputation": entry.reputation() - }), - peersstate::Peer::NotConnected(entry) => json!({ - "connected": false, - "reputation": entry.reputation() - }), - peersstate::Peer::Unknown(_) => - unreachable!("We iterate over the known peers; QED") - }; - - (peer_id.to_base58(), state) - }).collect::>(), - "reserved_only": self.reserved_only, - "message_queue": self.message_queue.len(), - }) - } - - /// Returns priority group by id. - pub fn get_priority_group(&self, group_id: &str) -> Option> { - self.data.get_priority_group(group_id) - } -} - -impl Stream for Peerset { - type Item = Message; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - loop { - if let Some(message) = self.message_queue.pop_front() { - return Poll::Ready(Some(message)); - } - - let action = match Stream::poll_next(Pin::new(&mut self.rx), cx) { - Poll::Pending => return Poll::Pending, - Poll::Ready(Some(event)) => event, - Poll::Ready(None) => return Poll::Pending, - }; - - match action { - Action::AddReservedPeer(peer_id) => - self.on_add_reserved_peer(peer_id), - Action::RemoveReservedPeer(peer_id) => - self.on_remove_reserved_peer(peer_id), - Action::SetReservedOnly(reserved) => - self.on_set_reserved_only(reserved), - Action::ReportPeer(peer_id, score_diff) => - self.on_report_peer(peer_id, score_diff), - Action::SetPriorityGroup(group_id, peers) => - self.on_set_priority_group(&group_id, peers), - Action::AddToPriorityGroup(group_id, peer_id) => - self.on_add_to_priority_group(&group_id, peer_id), - Action::RemoveFromPriorityGroup(group_id, peer_id) => - self.on_remove_from_priority_group(&group_id, peer_id), - } - } - } -} - -#[cfg(test)] -mod tests { - use libp2p::PeerId; - use futures::prelude::*; - use super::{PeersetConfig, Peerset, Message, IncomingIndex, BANNED_THRESHOLD}; - use std::{pin::Pin, task::Poll, thread, time::Duration}; - - fn assert_messages(mut peerset: Peerset, messages: Vec) -> Peerset { - for expected_message in messages { - let (message, p) = next_message(peerset).expect("expected message"); - assert_eq!(message, expected_message); - peerset = p; - } - assert!(peerset.message_queue.is_empty(), peerset.message_queue); - peerset - } - - fn next_message(mut peerset: Peerset) -> Result<(Message, Peerset), ()> { - let next = futures::executor::block_on_stream(&mut peerset).next(); - let message = next.ok_or_else(|| ())?; - Ok((message, peerset)) - } - - #[test] - fn test_peerset_add_reserved_peer() { - let bootnode = PeerId::random(); - let reserved_peer = PeerId::random(); - let reserved_peer2 = PeerId::random(); - let config = PeersetConfig { - in_peers: 0, - out_peers: 2, - bootnodes: vec![bootnode], - reserved_only: true, - reserved_nodes: Vec::new(), - }; - - let (peerset, handle) = Peerset::from_config(config); - handle.add_reserved_peer(reserved_peer.clone()); - handle.add_reserved_peer(reserved_peer2.clone()); - - assert_messages(peerset, vec![ - Message::Connect(reserved_peer), - Message::Connect(reserved_peer2) - ]); - } - - #[test] - fn test_peerset_incoming() { - let bootnode = PeerId::random(); - let incoming = PeerId::random(); - let incoming2 = PeerId::random(); - let incoming3 = PeerId::random(); - let ii = IncomingIndex(1); - let ii2 = IncomingIndex(2); - let ii3 = IncomingIndex(3); - let ii4 = IncomingIndex(3); - let config = PeersetConfig { - in_peers: 2, - out_peers: 1, - bootnodes: vec![bootnode.clone()], - reserved_only: false, - reserved_nodes: Vec::new(), - }; - - let (mut peerset, _handle) = Peerset::from_config(config); - peerset.incoming(incoming.clone(), ii); - peerset.incoming(incoming.clone(), ii4); - peerset.incoming(incoming2.clone(), ii2); - peerset.incoming(incoming3.clone(), ii3); - - assert_messages(peerset, vec![ - Message::Connect(bootnode.clone()), - Message::Accept(ii), - Message::Accept(ii2), - Message::Reject(ii3), - ]); - } - - #[test] - fn test_peerset_discovered() { - let bootnode = PeerId::random(); - let discovered = PeerId::random(); - let discovered2 = PeerId::random(); - let config = PeersetConfig { - in_peers: 0, - out_peers: 2, - bootnodes: vec![bootnode.clone()], - reserved_only: false, - reserved_nodes: vec![], - }; - - let (mut peerset, _handle) = Peerset::from_config(config); - peerset.discovered(Some(discovered.clone())); - peerset.discovered(Some(discovered.clone())); - peerset.discovered(Some(discovered2)); - - assert_messages(peerset, vec![ - Message::Connect(bootnode), - Message::Connect(discovered), - ]); - } - - #[test] - fn test_peerset_banned() { - let (mut peerset, handle) = Peerset::from_config(PeersetConfig { - in_peers: 25, - out_peers: 25, - bootnodes: vec![], - reserved_only: false, - reserved_nodes: vec![], - }); - - // We ban a node by setting its reputation under the threshold. - let peer_id = PeerId::random(); - handle.report_peer(peer_id.clone(), BANNED_THRESHOLD - 1); - - let fut = futures::future::poll_fn(move |cx| { - // We need one polling for the message to be processed. - assert_eq!(Stream::poll_next(Pin::new(&mut peerset), cx), Poll::Pending); - - // Check that an incoming connection from that node gets refused. - peerset.incoming(peer_id.clone(), IncomingIndex(1)); - if let Poll::Ready(msg) = Stream::poll_next(Pin::new(&mut peerset), cx) { - assert_eq!(msg.unwrap(), Message::Reject(IncomingIndex(1))); - } else { - panic!() - } - - // Wait a bit for the node's reputation to go above the threshold. - thread::sleep(Duration::from_millis(1500)); - - // Try again. This time the node should be accepted. - peerset.incoming(peer_id.clone(), IncomingIndex(2)); - while let Poll::Ready(msg) = Stream::poll_next(Pin::new(&mut peerset), cx) { - assert_eq!(msg.unwrap(), Message::Accept(IncomingIndex(2))); - } - - Poll::Ready(()) - }); - - futures::executor::block_on(fut); - } -} - diff --git a/core/phragmen/Cargo.toml b/core/phragmen/Cargo.toml deleted file mode 100644 index e10be1d92d908..0000000000000 --- a/core/phragmen/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "substrate-phragmen" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -sr-primitives = { path = "../sr-primitives", default-features = false } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } - -[dev-dependencies] -runtime-io ={ package = "sr-io", path = "../sr-io" } -support = { package = "srml-support", path = "../../srml/support" } -rand = "0.7.2" - -[features] -default = ["std"] -std = [ - "rstd/std", - "sr-primitives/std", -] diff --git a/core/phragmen/src/lib.rs b/core/phragmen/src/lib.rs deleted file mode 100644 index 7377bac2f802a..0000000000000 --- a/core/phragmen/src/lib.rs +++ /dev/null @@ -1,509 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Rust implementation of the Phragmén election algorithm. This is used in several SRML modules to -//! optimally distribute the weight of a set of voters among an elected set of candidates. In the -//! context of staking this is mapped to validators and nominators. -//! -//! The algorithm has two phases: -//! - Sequential phragmen: performed in [`elect`] function which is first pass of the distribution -//! The results are not optimal but the execution time is less. -//! - Equalize post-processing: tries to further distribute the weight fairly among candidates. -//! Incurs more execution time. -//! -//! The main objective of the assignments done by phragmen is to maximize the minimum backed -//! candidate in the elected set. -//! -//! Reference implementation: https://github.com/w3f/consensus -//! Further details: -//! https://research.web3.foundation/en/latest/polkadot/NPoS/4.%20Sequential%20Phragm%C3%A9n%E2%80%99s%20method/ - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::{prelude::*, collections::btree_map::BTreeMap}; -use sr_primitives::RuntimeDebug; -use sr_primitives::{helpers_128bit::multiply_by_rational, Perbill, Rational128}; -use sr_primitives::traits::{Zero, Convert, Member, SimpleArithmetic, Saturating, Bounded}; - -mod mock; -mod tests; - -/// A type in which performing operations on balances and stakes of candidates and voters are safe. -/// -/// This module's functions expect a `Convert` type to convert all balances to u64. Hence, u128 is -/// a safe type for arithmetic operations over them. -/// -/// Balance types converted to `ExtendedBalance` are referred to as `Votes`. -pub type ExtendedBalance = u128; - -/// The denominator used for loads. Since votes are collected as u64, the smallest ratio that we -/// might collect is `1/approval_stake` where approval stake is the sum of votes. Hence, some number -/// bigger than u64::max_value() is needed. For maximum accuracy we simply use u128; -const DEN: u128 = u128::max_value(); - -/// A candidate entity for phragmen election. -#[derive(Clone, Default, RuntimeDebug)] -pub struct Candidate { - /// Identifier. - pub who: AccountId, - /// Intermediary value used to sort candidates. - pub score: Rational128, - /// Sum of the stake of this candidate based on received votes. - approval_stake: ExtendedBalance, - /// Flag for being elected. - elected: bool, -} - -/// A voter entity. -#[derive(Clone, Default, RuntimeDebug)] -pub struct Voter { - /// Identifier. - who: AccountId, - /// List of candidates proposed by this voter. - edges: Vec>, - /// The stake of this voter. - budget: ExtendedBalance, - /// Incremented each time a candidate that this voter voted for has been elected. - load: Rational128, -} - -/// A candidate being backed by a voter. -#[derive(Clone, Default, RuntimeDebug)] -pub struct Edge { - /// Identifier. - who: AccountId, - /// Load of this vote. - load: Rational128, - /// Index of the candidate stored in the 'candidates' vector. - candidate_index: usize, -} - -/// Means a particular `AccountId` was backed by `Perbill`th of a nominator's stake. -pub type PhragmenAssignment = (AccountId, Perbill); - -/// Means a particular `AccountId` was backed by `ExtendedBalance` of a nominator's stake. -pub type PhragmenStakedAssignment = (AccountId, ExtendedBalance); - -/// Final result of the phragmen election. -#[derive(RuntimeDebug)] -pub struct PhragmenResult { - /// Just winners zipped with their approval stake. Note that the approval stake is merely the - /// sub of their received stake and could be used for very basic sorting and approval voting. - pub winners: Vec<(AccountId, ExtendedBalance)>, - /// Individual assignments. for each tuple, the first elements is a voter and the second - /// is the list of candidates that it supports. - pub assignments: Vec<(AccountId, Vec>)> -} - -/// A structure to demonstrate the phragmen result from the perspective of the candidate, i.e. how -/// much support each candidate is receiving. -/// -/// This complements the [`PhragmenResult`] and is needed to run the equalize post-processing. -/// -/// This, at the current version, resembles the `Exposure` defined in the staking SRML module, yet -/// they do not necessarily have to be the same. -#[derive(Default, RuntimeDebug)] -pub struct Support { - /// The amount of support as the effect of self-vote. - pub own: ExtendedBalance, - /// Total support. - pub total: ExtendedBalance, - /// Support from voters. - pub others: Vec>, -} - -/// A linkage from a candidate and its [`Support`]. -pub type SupportMap = BTreeMap>; - -/// Perform election based on Phragmén algorithm. -/// -/// Returns an `Option` the set of winners and their detailed support ratio from each voter if -/// enough candidates are provided. Returns `None` otherwise. -/// -/// * `candidate_count`: number of candidates to elect. -/// * `minimum_candidate_count`: minimum number of candidates to elect. If less candidates exist, -/// `None` is returned. -/// * `initial_candidates`: candidates list to be elected from. -/// * `initial_voters`: voters list. -/// * `stake_of`: something that can return the stake stake of a particular candidate or voter. -/// * `self_vote`. If true, then each candidate will automatically vote for themselves with the a -/// weight indicated by their stake. Note that when this is `true` candidates are filtered by -/// having at least some backed stake from themselves. -pub fn elect( - candidate_count: usize, - minimum_candidate_count: usize, - initial_candidates: Vec, - initial_voters: Vec<(AccountId, Vec)>, - stake_of: FS, - self_vote: bool, -) -> Option> where - AccountId: Default + Ord + Member, - Balance: Default + Copy + SimpleArithmetic, - for<'r> FS: Fn(&'r AccountId) -> Balance, - C: Convert + Convert, -{ - let to_votes = |b: Balance| >::convert(b) as ExtendedBalance; - - // return structures - let mut elected_candidates: Vec<(AccountId, ExtendedBalance)>; - let mut assigned: Vec<(AccountId, Vec>)>; - - // used to cache and access candidates index. - let mut c_idx_cache = BTreeMap::::new(); - - // voters list. - let num_voters = initial_candidates.len() + initial_voters.len(); - let mut voters: Vec> = Vec::with_capacity(num_voters); - - // collect candidates. self vote or filter might apply - let mut candidates = if self_vote { - // self vote. filter. - initial_candidates.into_iter().map(|who| { - let stake = stake_of(&who); - Candidate { who, approval_stake: to_votes(stake), ..Default::default() } - }) - .filter(|c| !c.approval_stake.is_zero()) - .enumerate() - .map(|(i, c)| { - voters.push(Voter { - who: c.who.clone(), - edges: vec![Edge { who: c.who.clone(), candidate_index: i, ..Default::default() }], - budget: c.approval_stake, - load: Rational128::zero(), - }); - c_idx_cache.insert(c.who.clone(), i); - c - }) - .collect::>>() - } else { - // no self vote. just collect. - initial_candidates.into_iter() - .enumerate() - .map(|(idx, who)| { - c_idx_cache.insert(who.clone(), idx); - Candidate { who, ..Default::default() } - }) - .collect::>>() - }; - - // early return if we don't have enough candidates - if candidates.len() < minimum_candidate_count { return None; } - - // collect voters. use `c_idx_cache` for fast access and aggregate `approval_stake` of - // candidates. - voters.extend(initial_voters.into_iter().map(|(who, votes)| { - let voter_stake = stake_of(&who); - let mut edges: Vec> = Vec::with_capacity(votes.len()); - for v in votes { - if let Some(idx) = c_idx_cache.get(&v) { - // This candidate is valid + already cached. - candidates[*idx].approval_stake = candidates[*idx].approval_stake - .saturating_add(to_votes(voter_stake)); - edges.push(Edge { who: v.clone(), candidate_index: *idx, ..Default::default() }); - } // else {} would be wrong votes. We don't really care about it. - } - Voter { - who, - edges: edges, - budget: to_votes(voter_stake), - load: Rational128::zero(), - } - })); - - - // we have already checked that we have more candidates than minimum_candidate_count. - // run phragmen. - let to_elect = candidate_count.min(candidates.len()); - elected_candidates = Vec::with_capacity(candidate_count); - assigned = Vec::with_capacity(candidate_count); - - // main election loop - for _round in 0..to_elect { - // loop 1: initialize score - for c in &mut candidates { - if !c.elected { - // 1 / approval_stake == (DEN / approval_stake) / DEN. If approval_stake is zero, - // then the ratio should be as large as possible, essentially `infinity`. - if c.approval_stake.is_zero() { - c.score = Rational128::from_unchecked(DEN, 0); - } else { - c.score = Rational128::from(DEN / c.approval_stake, DEN); - } - } - } - - // loop 2: increment score - for n in &voters { - for e in &n.edges { - let c = &mut candidates[e.candidate_index]; - if !c.elected && !c.approval_stake.is_zero() { - let temp_n = multiply_by_rational( - n.load.n(), - n.budget, - c.approval_stake, - ).unwrap_or(Bounded::max_value()); - let temp_d = n.load.d(); - let temp = Rational128::from(temp_n, temp_d); - c.score = c.score.lazy_saturating_add(temp); - } - } - } - - // loop 3: find the best - if let Some(winner) = candidates - .iter_mut() - .filter(|c| !c.elected) - .min_by_key(|c| c.score) - { - // loop 3: update voter and edge load - winner.elected = true; - for n in &mut voters { - for e in &mut n.edges { - if e.who == winner.who { - e.load = winner.score.lazy_saturating_sub(n.load); - n.load = winner.score; - } - } - } - - elected_candidates.push((winner.who.clone(), winner.approval_stake)); - } else { - break - } - } // end of all rounds - - // update backing stake of candidates and voters - for n in &mut voters { - let mut assignment = (n.who.clone(), vec![]); - for e in &mut n.edges { - if let Some(c) = elected_candidates.iter().cloned().find(|(c, _)| *c == e.who) { - if c.0 != n.who { - let per_bill_parts = - { - if n.load == e.load { - // Full support. No need to calculate. - Perbill::accuracy().into() - } else { - if e.load.d() == n.load.d() { - // return e.load / n.load. - let desired_scale: u128 = Perbill::accuracy().into(); - multiply_by_rational( - desired_scale, - e.load.n(), - n.load.n(), - ).unwrap_or(Bounded::max_value()) - } else { - // defensive only. Both edge and nominator loads are built from - // scores, hence MUST have the same denominator. - Zero::zero() - } - } - }; - // safer to .min() inside as well to argue as u32 is safe. - let per_thing = Perbill::from_parts( - per_bill_parts.min(Perbill::accuracy().into()) as u32 - ); - assignment.1.push((e.who.clone(), per_thing)); - } - } - } - - if assignment.1.len() > 0 { - // To ensure an assertion indicating: no stake from the nominator going to waste, - // we add a minimal post-processing to equally assign all of the leftover stake ratios. - let vote_count = assignment.1.len() as u32; - let len = assignment.1.len(); - let sum = assignment.1.iter() - .map(|a| a.1.deconstruct()) - .sum::(); - let accuracy = Perbill::accuracy(); - let diff = accuracy.checked_sub(sum).unwrap_or(0); - let diff_per_vote = (diff / vote_count).min(accuracy); - - if diff_per_vote > 0 { - for i in 0..len { - let current_ratio = assignment.1[i % len].1; - let next_ratio = current_ratio - .saturating_add(Perbill::from_parts(diff_per_vote)); - assignment.1[i % len].1 = next_ratio; - } - } - - // `remainder` is set to be less than maximum votes of a nominator (currently 16). - // safe to cast it to usize. - let remainder = diff - diff_per_vote * vote_count; - for i in 0..remainder as usize { - let current_ratio = assignment.1[i % len].1; - let next_ratio = current_ratio.saturating_add(Perbill::from_parts(1)); - assignment.1[i % len].1 = next_ratio; - } - assigned.push(assignment); - } - } - - Some(PhragmenResult { - winners: elected_candidates, - assignments: assigned, - }) -} - -/// Performs equalize post-processing to the output of the election algorithm. This happens in -/// rounds. The number of rounds and the maximum diff-per-round tolerance can be tuned through input -/// parameters. -/// -/// No value is returned from the function and the `supports` parameter is updated. -/// -/// * `assignments`: exactly the same is the output of phragmen. -/// * `supports`: mutable reference to s `SupportMap`. This parameter is updated. -/// * `tolerance`: maximum difference that can occur before an early quite happens. -/// * `iterations`: maximum number of iterations that will be processed. -/// * `stake_of`: something that can return the stake stake of a particular candidate or voter. -pub fn equalize( - mut assignments: Vec<(AccountId, Vec>)>, - supports: &mut SupportMap, - tolerance: ExtendedBalance, - iterations: usize, - stake_of: FS, -) where - C: Convert + Convert, - for<'r> FS: Fn(&'r AccountId) -> Balance, - AccountId: Ord + Clone, -{ - // prepare the data for equalise - for _i in 0..iterations { - let mut max_diff = 0; - - for (voter, assignment) in assignments.iter_mut() { - let voter_budget = stake_of(&voter); - - let diff = do_equalize::<_, _, C>( - voter, - voter_budget, - assignment, - supports, - tolerance, - ); - if diff > max_diff { max_diff = diff; } - } - - if max_diff < tolerance { - break; - } - } -} - -/// actually perform equalize. same interface is `equalize`. Just called in loops with a check for -/// maximum difference. -fn do_equalize( - voter: &AccountId, - budget_balance: Balance, - elected_edges: &mut Vec>, - support_map: &mut SupportMap, - tolerance: ExtendedBalance -) -> ExtendedBalance where - C: Convert + Convert, - AccountId: Ord + Clone, -{ - let to_votes = |b: Balance| - >::convert(b) as ExtendedBalance; - let budget = to_votes(budget_balance); - - // Nothing to do. This voter had nothing useful. - // Defensive only. Assignment list should always be populated. - if elected_edges.is_empty() { return 0; } - - let stake_used = elected_edges - .iter() - .fold(0 as ExtendedBalance, |s, e| s.saturating_add(e.1)); - - let backed_stakes_iter = elected_edges - .iter() - .filter_map(|e| support_map.get(&e.0)) - .map(|e| e.total); - - let backing_backed_stake = elected_edges - .iter() - .filter(|e| e.1 > 0) - .filter_map(|e| support_map.get(&e.0)) - .map(|e| e.total) - .collect::>(); - - let mut difference; - if backing_backed_stake.len() > 0 { - let max_stake = backing_backed_stake - .iter() - .max() - .expect("vector with positive length will have a max; qed"); - let min_stake = backed_stakes_iter - .min() - .expect("iterator with positive length will have a min; qed"); - - difference = max_stake.saturating_sub(min_stake); - difference = difference.saturating_add(budget.saturating_sub(stake_used)); - if difference < tolerance { - return difference; - } - } else { - difference = budget; - } - - // Undo updates to support - elected_edges.iter_mut().for_each(|e| { - if let Some(support) = support_map.get_mut(&e.0) { - support.total = support.total.saturating_sub(e.1); - support.others.retain(|i_support| i_support.0 != *voter); - } - e.1 = 0; - }); - - elected_edges.sort_unstable_by_key(|e| - if let Some(e) = support_map.get(&e.0) { e.total } else { Zero::zero() } - ); - - let mut cumulative_stake: ExtendedBalance = 0; - let mut last_index = elected_edges.len() - 1; - let mut idx = 0usize; - for e in &mut elected_edges[..] { - if let Some(support) = support_map.get_mut(&e.0) { - let stake = support.total; - let stake_mul = stake.saturating_mul(idx as ExtendedBalance); - let stake_sub = stake_mul.saturating_sub(cumulative_stake); - if stake_sub > budget { - last_index = idx.checked_sub(1).unwrap_or(0); - break; - } - cumulative_stake = cumulative_stake.saturating_add(stake); - } - idx += 1; - } - - let last_stake = elected_edges[last_index].1; - let split_ways = last_index + 1; - let excess = budget - .saturating_add(cumulative_stake) - .saturating_sub(last_stake.saturating_mul(split_ways as ExtendedBalance)); - elected_edges.iter_mut().take(split_ways).for_each(|e| { - if let Some(support) = support_map.get_mut(&e.0) { - e.1 = (excess / split_ways as ExtendedBalance) - .saturating_add(last_stake) - .saturating_sub(support.total); - support.total = support.total.saturating_add(e.1); - support.others.push((voter.clone(), e.1)); - } - }); - - difference -} diff --git a/core/phragmen/src/mock.rs b/core/phragmen/src/mock.rs deleted file mode 100644 index ee4e1eb4bbb32..0000000000000 --- a/core/phragmen/src/mock.rs +++ /dev/null @@ -1,434 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Mock file for phragmen. - -#![cfg(test)] - -use crate::{elect, PhragmenResult, PhragmenAssignment}; -use sr_primitives::{ - assert_eq_error_rate, Perbill, - traits::{Convert, Member, SaturatedConversion} -}; -use rstd::collections::btree_map::BTreeMap; - -pub(crate) struct TestCurrencyToVote; -impl Convert for TestCurrencyToVote { - fn convert(x: Balance) -> u64 { x.saturated_into() } -} -impl Convert for TestCurrencyToVote { - fn convert(x: u128) -> Balance { x } -} - -#[derive(Default, Debug)] -pub(crate) struct _Candidate { - who: A, - score: f64, - approval_stake: f64, - elected: bool, -} - -#[derive(Default, Debug)] -pub(crate) struct _Voter { - who: A, - edges: Vec<_Edge>, - budget: f64, - load: f64, -} - -#[derive(Default, Debug)] -pub(crate) struct _Edge { - who: A, - load: f64, - candidate_index: usize, -} - -#[derive(Default, Debug, PartialEq)] -pub(crate) struct _Support { - pub own: f64, - pub total: f64, - pub others: Vec<_PhragmenAssignment>, -} - -pub(crate) type _PhragmenAssignment = (A, f64); -pub(crate) type _SupportMap = BTreeMap>; - -pub(crate) type Balance = u128; -pub(crate) type AccountId = u64; - -#[derive(Debug, Clone)] -pub(crate) struct _PhragmenResult { - pub winners: Vec<(A, Balance)>, - pub assignments: Vec<(A, Vec<_PhragmenAssignment>)> -} - -pub(crate) fn elect_float( - candidate_count: usize, - minimum_candidate_count: usize, - initial_candidates: Vec, - initial_voters: Vec<(A, Vec)>, - stake_of: FS, - self_vote: bool, -) -> Option<_PhragmenResult> where - A: Default + Ord + Member + Copy, - for<'r> FS: Fn(&'r A) -> Balance, -{ - let mut elected_candidates: Vec<(A, Balance)>; - let mut assigned: Vec<(A, Vec<_PhragmenAssignment>)>; - let mut c_idx_cache = BTreeMap::::new(); - let num_voters = initial_candidates.len() + initial_voters.len(); - let mut voters: Vec<_Voter> = Vec::with_capacity(num_voters); - - let mut candidates = if self_vote { - initial_candidates.into_iter().map(|who| { - let stake = stake_of(&who) as f64; - _Candidate { who, approval_stake: stake, ..Default::default() } - }) - .filter(|c| c.approval_stake != 0f64) - .enumerate() - .map(|(i, c)| { - let who = c.who; - voters.push(_Voter { - who: who.clone(), - edges: vec![ - _Edge { who: who.clone(), candidate_index: i, ..Default::default() } - ], - budget: c.approval_stake, - load: 0f64, - }); - c_idx_cache.insert(c.who.clone(), i); - c - }) - .collect::>>() - } else { - initial_candidates.into_iter() - .enumerate() - .map(|(idx, who)| { - c_idx_cache.insert(who.clone(), idx); - _Candidate { who, ..Default::default() } - }) - .collect::>>() - }; - - if candidates.len() < minimum_candidate_count { - return None; - } - - voters.extend(initial_voters.into_iter().map(|(who, votes)| { - let voter_stake = stake_of(&who) as f64; - let mut edges: Vec<_Edge> = Vec::with_capacity(votes.len()); - for v in votes { - if let Some(idx) = c_idx_cache.get(&v) { - candidates[*idx].approval_stake = candidates[*idx].approval_stake + voter_stake; - edges.push( - _Edge { who: v.clone(), candidate_index: *idx, ..Default::default() } - ); - } - } - _Voter { - who, - edges: edges, - budget: voter_stake, - load: 0f64, - } - })); - - let to_elect = candidate_count.min(candidates.len()); - elected_candidates = Vec::with_capacity(candidate_count); - assigned = Vec::with_capacity(candidate_count); - - for _round in 0..to_elect { - for c in &mut candidates { - if !c.elected { - c.score = 1.0 / c.approval_stake; - } - } - for n in &voters { - for e in &n.edges { - let c = &mut candidates[e.candidate_index]; - if !c.elected && !(c.approval_stake == 0f64) { - c.score += n.budget * n.load / c.approval_stake; - } - } - } - - if let Some(winner) = candidates - .iter_mut() - .filter(|c| !c.elected) - .min_by(|x, y| x.score.partial_cmp(&y.score).unwrap_or(rstd::cmp::Ordering::Equal)) - { - winner.elected = true; - for n in &mut voters { - for e in &mut n.edges { - if e.who == winner.who { - e.load = winner.score - n.load; - n.load = winner.score; - } - } - } - - elected_candidates.push((winner.who.clone(), winner.approval_stake as Balance)); - } else { - break - } - } - - for n in &mut voters { - let mut assignment = (n.who.clone(), vec![]); - for e in &mut n.edges { - if let Some(c) = elected_candidates.iter().cloned().map(|(c, _)| c).find(|c| *c == e.who) { - if c != n.who { - let ratio = e.load / n.load; - assignment.1.push((e.who.clone(), ratio)); - } - } - } - if assignment.1.len() > 0 { - assigned.push(assignment); - } - } - - Some(_PhragmenResult { - winners: elected_candidates, - assignments: assigned, - }) -} - -pub(crate) fn equalize_float( - mut assignments: Vec<(A, Vec<_PhragmenAssignment>)>, - supports: &mut _SupportMap, - tolerance: f64, - iterations: usize, - stake_of: FS, -) where - for<'r> FS: Fn(&'r A) -> Balance, - A: Ord + Clone + std::fmt::Debug, -{ - for _i in 0..iterations { - let mut max_diff = 0.0; - for (voter, assignment) in assignments.iter_mut() { - let voter_budget = stake_of(&voter); - let diff = do_equalize_float( - voter, - voter_budget, - assignment, - supports, - tolerance, - ); - if diff > max_diff { max_diff = diff; } - } - - if max_diff < tolerance { - break; - } - } -} - -pub(crate) fn do_equalize_float( - voter: &A, - budget_balance: Balance, - elected_edges: &mut Vec<_PhragmenAssignment>, - support_map: &mut _SupportMap, - tolerance: f64 -) -> f64 where - A: Ord + Clone, -{ - let budget = budget_balance as f64; - if elected_edges.is_empty() { return 0.0; } - - let stake_used = elected_edges - .iter() - .fold(0.0, |s, e| s + e.1); - - let backed_stakes_iter = elected_edges - .iter() - .filter_map(|e| support_map.get(&e.0)) - .map(|e| e.total); - - let backing_backed_stake = elected_edges - .iter() - .filter(|e| e.1 > 0.0) - .filter_map(|e| support_map.get(&e.0)) - .map(|e| e.total) - .collect::>(); - - let mut difference; - if backing_backed_stake.len() > 0 { - let max_stake = backing_backed_stake - .iter() - .max_by(|x, y| x.partial_cmp(&y).unwrap_or(rstd::cmp::Ordering::Equal)) - .expect("vector with positive length will have a max; qed"); - let min_stake = backed_stakes_iter - .min_by(|x, y| x.partial_cmp(&y).unwrap_or(rstd::cmp::Ordering::Equal)) - .expect("iterator with positive length will have a min; qed"); - - difference = max_stake - min_stake; - difference = difference + budget - stake_used; - if difference < tolerance { - return difference; - } - } else { - difference = budget; - } - - // Undo updates to support - elected_edges.iter_mut().for_each(|e| { - if let Some(support) = support_map.get_mut(&e.0) { - support.total = support.total - e.1; - support.others.retain(|i_support| i_support.0 != *voter); - } - e.1 = 0.0; - }); - - // todo: rewrite. - elected_edges.sort_unstable_by(|x, y| - if let Some(x) = support_map.get(&x.0) { - if let Some(y) = support_map.get(&y.0) { - x.total.partial_cmp(&y.total).unwrap_or(rstd::cmp::Ordering::Equal) - } else { - rstd::cmp::Ordering::Equal - } - } else { - rstd::cmp::Ordering::Equal - } - ); - - let mut cumulative_stake = 0.0; - let mut last_index = elected_edges.len() - 1; - elected_edges.iter_mut().enumerate().for_each(|(idx, e)| { - if let Some(support) = support_map.get_mut(&e.0) { - let stake = support.total; - let stake_mul = stake * (idx as f64); - let stake_sub = stake_mul - cumulative_stake; - if stake_sub > budget { - last_index = idx.checked_sub(1).unwrap_or(0); - return - } - cumulative_stake = cumulative_stake + stake; - } - }); - - let last_stake = elected_edges[last_index].1; - let split_ways = last_index + 1; - let excess = budget + cumulative_stake - last_stake * (split_ways as f64); - elected_edges.iter_mut().take(split_ways).for_each(|e| { - if let Some(support) = support_map.get_mut(&e.0) { - e.1 = excess / (split_ways as f64) + last_stake - support.total; - support.total = support.total + e.1; - support.others.push((voter.clone(), e.1)); - } - }); - - difference -} - - -pub(crate) fn create_stake_of(stakes: &[(AccountId, Balance)]) - -> Box Balance> -{ - let mut storage = BTreeMap::::new(); - stakes.iter().for_each(|s| { storage.insert(s.0, s.1); }); - let stake_of = move |who: &AccountId| -> Balance { storage.get(who).unwrap().to_owned() }; - Box::new(stake_of) -} - - -pub fn check_assignments(assignments: Vec<(AccountId, Vec>)>) { - for (_, a) in assignments { - let sum: u32 = a.iter().map(|(_, p)| p.deconstruct()).sum(); - assert_eq_error_rate!(sum, Perbill::accuracy(), 5); - } -} - -pub(crate) fn run_and_compare( - candidates: Vec, - voters: Vec<(AccountId, Vec)>, - stake_of: Box Balance>, - to_elect: usize, - min_to_elect: usize, - self_vote: bool, -) { - // run fixed point code. - let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( - to_elect, - min_to_elect, - candidates.clone(), - voters.clone(), - &stake_of, - self_vote, - ).unwrap(); - - // run float poc code. - let truth_value = elect_float( - to_elect, - min_to_elect, - candidates, - voters, - &stake_of, - self_vote, - ).unwrap(); - - assert_eq!(winners, truth_value.winners); - - for (nominator, assigned) in assignments.clone() { - if let Some(float_assignments) = truth_value.assignments.iter().find(|x| x.0 == nominator) { - for (candidate, per_thingy) in assigned { - if let Some(float_assignment) = float_assignments.1.iter().find(|x| x.0 == candidate ) { - assert_eq_error_rate!( - Perbill::from_fraction(float_assignment.1).deconstruct(), - per_thingy.deconstruct(), - 1, - ); - } else { - panic!("candidate mismatch. This should never happen.") - } - } - } else { - panic!("nominator mismatch. This should never happen.") - } - } - - check_assignments(assignments); -} - -pub(crate) fn build_support_map( - result: &mut _PhragmenResult, - stake_of: FS, -) -> _SupportMap - where for<'r> FS: Fn(&'r AccountId) -> Balance -{ - let mut supports = <_SupportMap>::new(); - result.winners - .iter() - .map(|(e, _)| (e, stake_of(e) as f64)) - .for_each(|(e, s)| { - let item = _Support { own: s, total: s, ..Default::default() }; - supports.insert(e.clone(), item); - }); - - for (n, assignment) in result.assignments.iter_mut() { - for (c, r) in assignment.iter_mut() { - let nominator_stake = stake_of(n) as f64; - let other_stake = nominator_stake * *r; - if let Some(support) = supports.get_mut(c) { - support.total = support.total + other_stake; - support.others.push((n.clone(), other_stake)); - } - *r = other_stake; - } - } - supports -} diff --git a/core/phragmen/src/tests.rs b/core/phragmen/src/tests.rs deleted file mode 100644 index d3c5b1168cc4e..0000000000000 --- a/core/phragmen/src/tests.rs +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for phragmen. - -#![cfg(test)] - -use crate::mock::*; -use crate::{elect, PhragmenResult}; -use support::assert_eq_uvec; -use sr_primitives::Perbill; - -#[test] -fn float_phragmen_poc_works() { - let candidates = vec![1, 2, 3]; - let voters = vec![ - (10, vec![1, 2]), - (20, vec![1, 3]), - (30, vec![2, 3]), - ]; - let stake_of = create_stake_of(&[(10, 10), (20, 20), (30, 30), (1, 0), (2, 0), (3, 0)]); - let mut phragmen_result = elect_float(2, 2, candidates, voters, &stake_of, false).unwrap(); - let winners = phragmen_result.clone().winners; - let assignments = phragmen_result.clone().assignments; - - assert_eq_uvec!(winners, vec![(2, 40), (3, 50)]); - assert_eq_uvec!( - assignments, - vec![ - (10, vec![(2, 1.0)]), - (20, vec![(3, 1.0)]), - (30, vec![(2, 0.5), (3, 0.5)]), - ] - ); - - let mut support_map = build_support_map(&mut phragmen_result, &stake_of); - - assert_eq!( - support_map.get(&2).unwrap(), - &_Support { own: 0.0, total: 25.0, others: vec![(10u64, 10.0), (30u64, 15.0)]} - ); - assert_eq!( - support_map.get(&3).unwrap(), - &_Support { own: 0.0, total: 35.0, others: vec![(20u64, 20.0), (30u64, 15.0)]} - ); - - equalize_float(phragmen_result.assignments, &mut support_map, 0.0, 2, stake_of); - - assert_eq!( - support_map.get(&2).unwrap(), - &_Support { own: 0.0, total: 30.0, others: vec![(10u64, 10.0), (30u64, 20.0)]} - ); - assert_eq!( - support_map.get(&3).unwrap(), - &_Support { own: 0.0, total: 30.0, others: vec![(20u64, 20.0), (30u64, 10.0)]} - ); -} - -#[test] -fn phragmen_poc_works() { - let candidates = vec![1, 2, 3]; - let voters = vec![ - (10, vec![1, 2]), - (20, vec![1, 3]), - (30, vec![2, 3]), - ]; - - let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( - 2, - 2, - candidates, - voters, - create_stake_of(&[(10, 10), (20, 20), (30, 30)]), - false, - ).unwrap(); - - assert_eq_uvec!(winners, vec![(2, 40), (3, 50)]); - assert_eq_uvec!( - assignments, - vec![ - (10, vec![(2, Perbill::from_percent(100))]), - (20, vec![(3, Perbill::from_percent(100))]), - (30, vec![(2, Perbill::from_percent(100/2)), (3, Perbill::from_percent(100/2))]), - ] - ); -} - -#[test] -fn phragmen_poc_2_works() { - let candidates = vec![10, 20, 30]; - let voters = vec![ - (2, vec![10, 20, 30]), - (4, vec![10, 20, 40]), - ]; - let stake_of = create_stake_of(&[ - (10, 1000), - (20, 1000), - (30, 1000), - (40, 1000), - (2, 500), - (4, 500), - ]); - - run_and_compare(candidates, voters, stake_of, 2, 2, true); -} - -#[test] -fn phragmen_poc_3_works() { - let candidates = vec![10, 20, 30]; - let voters = vec![ - (2, vec![10, 20, 30]), - (4, vec![10, 20, 40]), - ]; - let stake_of = create_stake_of(&[ - (10, 1000), - (20, 1000), - (30, 1000), - (2, 50), - (4, 1000), - ]); - - run_and_compare(candidates, voters, stake_of, 2, 2, true); -} - -#[test] -fn phragmen_accuracy_on_large_scale_only_validators() { - // because of this particular situation we had per_u128 and now rational128. In practice, a - // candidate can have the maximum amount of tokens, and also supported by the maximum. - let candidates = vec![1, 2, 3, 4, 5]; - let stake_of = create_stake_of(&[ - (1, (u64::max_value() - 1).into()), - (2, (u64::max_value() - 4).into()), - (3, (u64::max_value() - 5).into()), - (4, (u64::max_value() - 3).into()), - (5, (u64::max_value() - 2).into()), - ]); - - let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( - 2, - 2, - candidates, - vec![], - stake_of, - true, - ).unwrap(); - - assert_eq_uvec!(winners, vec![(1, 18446744073709551614u128), (5, 18446744073709551613u128)]); - assert_eq!(assignments.len(), 0); - check_assignments(assignments); -} - -#[test] -fn phragmen_accuracy_on_large_scale_validators_and_nominators() { - let candidates = vec![1, 2, 3, 4, 5]; - let voters = vec![ - (13, vec![1, 3, 5]), - (14, vec![2, 4]), - ]; - let stake_of = create_stake_of(&[ - (1, (u64::max_value() - 1).into()), - (2, (u64::max_value() - 4).into()), - (3, (u64::max_value() - 5).into()), - (4, (u64::max_value() - 3).into()), - (5, (u64::max_value() - 2).into()), - (13, (u64::max_value() - 10).into()), - (14, u64::max_value().into()), - ]); - - let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( - 2, - 2, - candidates, - voters, - stake_of, - true, - ).unwrap(); - - assert_eq_uvec!(winners, vec![(2, 36893488147419103226u128), (1, 36893488147419103219u128)]); - assert_eq!( - assignments, - vec![(13, vec![(1, Perbill::one())]), (14, vec![(2, Perbill::one())])] - ); - check_assignments(assignments); -} - -#[test] -fn phragmen_accuracy_on_small_scale_self_vote() { - let candidates = vec![40, 10, 20, 30]; - let voters = vec![]; - let stake_of = create_stake_of(&[ - (40, 0), - (10, 1), - (20, 2), - (30, 1), - ]); - - let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>( - 3, - 3, - candidates, - voters, - stake_of, - true, - ).unwrap(); - - assert_eq_uvec!(winners, vec![(20, 2), (10, 1), (30, 1)]); -} - -#[test] -fn phragmen_accuracy_on_small_scale_no_self_vote() { - let candidates = vec![40, 10, 20, 30]; - let voters = vec![ - (1, vec![10]), - (2, vec![20]), - (3, vec![30]), - (4, vec![40]), - ]; - let stake_of = create_stake_of(&[ - (40, 1000), // don't care - (10, 1000), // don't care - (20, 1000), // don't care - (30, 1000), // don't care - (4, 0), - (1, 1), - (2, 2), - (3, 1), - ]); - - let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>( - 3, - 3, - candidates, - voters, - stake_of, - false, - ).unwrap(); - - assert_eq_uvec!(winners, vec![(20, 2), (10, 1), (30, 1)]); -} - -#[test] -fn phragmen_large_scale_test() { - let candidates = vec![2, 4, 6, 8, 10, 12, 14, 16 ,18, 20, 22, 24]; - let voters = vec![ - (50, vec![2, 4, 6, 8, 10, 12, 14, 16 ,18, 20, 22, 24]), - ]; - let stake_of = create_stake_of(&[ - (2, 1), - (4, 100), - (6, 1000000), - (8, 100000000001000), - (10, 100000000002000), - (12, 100000000003000), - (14, 400000000000000), - (16, 400000000001000), - (18, 18000000000000000), - (20, 20000000000000000), - (22, 500000000000100000), - (24, 500000000000200000), - (50, 990000000000000000), - ]); - - let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( - 2, - 2, - candidates, - voters, - stake_of, - true, - ).unwrap(); - - assert_eq_uvec!(winners, vec![(24, 1490000000000200000u128), (22, 1490000000000100000u128)]); - check_assignments(assignments); -} - -#[test] -fn phragmen_large_scale_test_2() { - let nom_budget: u64 = 1_000_000_000_000_000_000; - let c_budget: u64 = 4_000_000; - - let candidates = vec![2, 4]; - let voters = vec![(50, vec![2, 4])]; - - let stake_of = create_stake_of(&[ - (2, c_budget.into()), - (4, c_budget.into()), - (50, nom_budget.into()), - ]); - - let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( - 2, - 2, - candidates, - voters, - stake_of, - true, - ).unwrap(); - - assert_eq_uvec!(winners, vec![(2, 1000000000004000000u128), (4, 1000000000004000000u128)]); - assert_eq!( - assignments, - vec![(50, vec![(2, Perbill::from_parts(500000001)), (4, Perbill::from_parts(499999999))])], - ); - check_assignments(assignments); -} - -#[test] -fn phragmen_linear_equalize() { - let candidates = vec![11, 21, 31, 41, 51, 61, 71]; - let voters = vec![ - (2, vec![11]), - (4, vec![11, 21]), - (6, vec![21, 31]), - (8, vec![31, 41]), - (110, vec![41, 51]), - (120, vec![51, 61]), - (130, vec![61, 71]), - ]; - let stake_of = create_stake_of(&[ - (11, 1000), - (21, 1000), - (31, 1000), - (41, 1000), - (51, 1000), - (61, 1000), - (71, 1000), - - (2, 2000), - (4, 1000), - (6, 1000), - (8, 1000), - (110, 1000), - (120, 1000), - (130, 1000), - ]); - - run_and_compare(candidates, voters, stake_of, 2, 2, true); -} diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml deleted file mode 100644 index bc8106de3ab35..0000000000000 --- a/core/primitives/Cargo.toml +++ /dev/null @@ -1,92 +0,0 @@ -[package] -name = "substrate-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rustc-hex = { version = "2.0.1", default-features = false } -log = { version = "0.4.8", default-features = false } -serde = { version = "1.0.101", optional = true, features = ["derive"] } -twox-hash = { version = "1.5.0", optional = true } -byteorder = { version = "1.3.2", default-features = false } -primitive-types = { version = "0.5.1", default-features = false, features = ["codec"] } -impl-serde = { version = "0.2.1", optional = true } -wasmi = { version = "0.5.1", optional = true } -hash-db = { version = "0.15.2", default-features = false } -hash256-std-hasher = { version = "0.15.2", default-features = false } -ed25519-dalek = { version = "0.9.1", optional = true } -base58 = { version = "0.1.0", optional = true } -blake2-rfc = { version = "0.2.18", optional = true } -schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated"], optional = true } -rand = { version = "0.7.2", optional = true } -sha2 = { version = "0.8.0", optional = true } -substrate-bip39 = { version = "0.3.1", optional = true } -tiny-bip39 = { version = "0.6.2", optional = true } -hex = { version = "0.3.2", optional = true } -regex = { version = "1.3.1", optional = true } -num-traits = { version = "0.2.8", default-features = false } -zeroize = "0.10.1" -lazy_static = { version = "1.4.0", optional = true } -parking_lot = { version = "0.9.0", optional = true } -libsecp256k1 = { version = "0.3.0", optional = true } -tiny-keccak = { version = "1.5.0", optional = true } -substrate-debug-derive = { version = "2.0.0", path = "./debug-derive" } -externalities = { package = "substrate-externalities", path = "../externalities", optional = true } -primitives-storage = { package = "substrate-primitives-storage", path = "storage", default-features = false } - -[dev-dependencies] -substrate-serializer = { path = "../serializer" } -pretty_assertions = "0.6.1" -hex-literal = "0.2.1" -rand = "0.7.2" -criterion = "0.2.11" - -[[bench]] -name = "benches" -harness = false - -[lib] -bench = false - -[features] -default = ["std"] -std = [ - "log/std", - "wasmi", - "lazy_static", - "parking_lot", - "primitive-types/std", - "primitive-types/serde", - "primitive-types/byteorder", - "primitive-types/rustc-hex", - "primitive-types/libc", - "impl-serde", - "codec/std", - "hash256-std-hasher/std", - "hash-db/std", - "rstd/std", - "serde", - "rustc-hex/std", - "twox-hash", - "blake2-rfc", - "ed25519-dalek", - "hex", - "base58", - "substrate-bip39", - "tiny-bip39", - "serde", - "byteorder/std", - "rand", - "sha2", - "schnorrkel", - "regex", - "num-traits/std", - "libsecp256k1", - "tiny-keccak", - "substrate-debug-derive/std", - "externalities", - "primitives-storage/std", -] diff --git a/core/primitives/benches/benches.rs b/core/primitives/benches/benches.rs deleted file mode 100644 index 5245af44a8131..0000000000000 --- a/core/primitives/benches/benches.rs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2019 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -#[macro_use] -extern crate criterion; - -use substrate_primitives as primitives; -use criterion::{Criterion, black_box, Bencher, Fun}; -use std::time::Duration; -use primitives::crypto::Pair as _; -use primitives::hashing::{twox_128, blake2_128}; - -const MAX_KEY_SIZE: u32 = 32; - -fn get_key(key_size: u32) -> Vec { - use rand::SeedableRng; - use rand::Rng; - - let rnd: [u8; 32] = rand::rngs::StdRng::seed_from_u64(12).gen(); - let mut rnd = rnd.iter().cycle(); - - (0..key_size) - .map(|_| rnd.next().unwrap().clone()) - .collect() -} - -fn bench_blake2_128(b: &mut Bencher, key: &Vec) { - b.iter(|| { - let _a = blake2_128(black_box(key)); - }); -} - -fn bench_twox_128(b: &mut Bencher, key: &Vec) { - b.iter(|| { - let _a = twox_128(black_box(key)); - }); -} - -fn bench_hash_128_fix_size(c: &mut Criterion) { - let key = get_key(MAX_KEY_SIZE); - let blake_fn = Fun::new("blake2_128", bench_blake2_128); - let twox_fn = Fun::new("twox_128", bench_twox_128); - let fns = vec![blake_fn, twox_fn]; - - c.bench_functions("fixed size hashing", fns, key); -} - -fn bench_hash_128_dyn_size(c: &mut Criterion) { - let mut keys = Vec::new(); - for i in (2..MAX_KEY_SIZE).step_by(4) { - keys.push(get_key(i).clone()) - } - - c.bench_function_over_inputs("dyn size hashing - blake2", |b, key| bench_blake2_128(b, &key), keys.clone()); - c.bench_function_over_inputs("dyn size hashing - twox", |b, key| bench_twox_128(b, &key), keys); -} - -fn bench_ed25519(c: &mut Criterion) { - c.bench_function_over_inputs("signing - ed25519", |b, &msg_size| { - let msg = (0..msg_size) - .map(|_| rand::random::()) - .collect::>(); - let key = primitives::ed25519::Pair::generate().0; - b.iter(|| key.sign(&msg)) - }, vec![32, 1024, 1024 * 1024]); - - c.bench_function_over_inputs("verifying - ed25519", |b, &msg_size| { - let msg = (0..msg_size) - .map(|_| rand::random::()) - .collect::>(); - let key = primitives::ed25519::Pair::generate().0; - let sig = key.sign(&msg); - let public = key.public(); - b.iter(|| primitives::ed25519::Pair::verify(&sig, &msg, &public)) - }, vec![32, 1024, 1024 * 1024]); -} - -criterion_group!{ - name = benches; - config = Criterion::default().warm_up_time(Duration::from_millis(500)).without_plots(); - targets = bench_hash_128_fix_size, bench_hash_128_dyn_size, bench_ed25519 -} -criterion_main!(benches); diff --git a/core/primitives/debug-derive/Cargo.toml b/core/primitives/debug-derive/Cargo.toml deleted file mode 100644 index 9c7b7aa1bad49..0000000000000 --- a/core/primitives/debug-derive/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "substrate-debug-derive" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -quote = "1.0.2" -syn = "1.0.5" -proc-macro2 = "1.0" - -[features] -std = [] - -[dev-dependencies] - diff --git a/core/primitives/debug-derive/src/impls.rs b/core/primitives/debug-derive/src/impls.rs deleted file mode 100644 index decceca044c1b..0000000000000 --- a/core/primitives/debug-derive/src/impls.rs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use quote::quote; -use proc_macro2::TokenStream; -use syn::{Data, DeriveInput, parse_quote}; - -pub fn debug_derive(ast: DeriveInput) -> proc_macro::TokenStream { - let name_str = ast.ident.to_string(); - let implementation = implementation::derive(&name_str, &ast.data); - let name = &ast.ident; - let mut generics = ast.generics.clone(); - let (impl_generics, ty_generics, where_clause) = { - let wh = generics.make_where_clause(); - for t in ast.generics.type_params() { - let name = &t.ident; - wh.predicates.push(parse_quote!{ #name : core::fmt::Debug }); - } - generics.split_for_impl() - }; - let gen = quote!{ - impl #impl_generics core::fmt::Debug for #name #ty_generics #where_clause { - fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { - #implementation - } - } - }; - - gen.into() -} - -#[cfg(not(feature = "std"))] -mod implementation { - use super::*; - - /// Derive the inner implementation of `Debug::fmt` function. - /// - /// Non-std environment. We do nothing to prevent bloating the size of runtime. - /// Implement `Printable` if you need to print the details. - pub fn derive(_name_str: &str, _data: &Data) -> TokenStream { - quote! { - fmt.write_str("") - } - } -} - -#[cfg(feature = "std")] -mod implementation { - use super::*; - use proc_macro2::Span; - use syn::{Ident, Index, token::SelfValue}; - - /// Derive the inner implementation of `Debug::fmt` function. - pub fn derive(name_str: &str, data: &Data) -> TokenStream { - match *data { - Data::Struct(ref s) => derive_struct(&name_str, &s.fields), - Data::Union(ref u) => derive_fields(&name_str, Fields::new(u.fields.named.iter(), None)), - Data::Enum(ref e) => derive_enum(&name_str, &e), - } - } - - enum Fields { - Indexed { - indices: Vec, - }, - Unnamed { - vars: Vec, - }, - Named { - names: Vec, - this: Option, - }, - } - - impl Fields { - fn new<'a>(fields: impl Iterator, this: Option) -> Self { - let mut indices = vec![]; - let mut names = vec![]; - - for (i, f) in fields.enumerate() { - if let Some(ident) = f.ident.clone() { - names.push(ident); - } else { - indices.push(Index::from(i)); - } - } - - if names.is_empty() { - Self::Indexed { - indices, - } - } else { - Self::Named { - names, - this, - } - } - } - } - - fn derive_fields<'a>( - name_str: &str, - fields: Fields, - ) -> TokenStream { - match fields { - Fields::Named { names, this } => { - let names_str: Vec<_> = names.iter() - .map(|x| x.to_string()) - .collect(); - - let fields = match this { - None => quote! { #( .field(#names_str, #names) )* }, - Some(this) => quote! { #( .field(#names_str, &#this.#names) )* }, - }; - - quote! { - fmt.debug_struct(#name_str) - #fields - .finish() - } - - }, - Fields::Indexed { indices } => { - quote! { - fmt.debug_tuple(#name_str) - #( .field(&self.#indices) )* - .finish() - } - }, - Fields::Unnamed { vars } => { - quote! { - fmt.debug_tuple(#name_str) - #( .field(#vars) )* - .finish() - } - }, - } - } - - fn derive_enum( - name: &str, - e: &syn::DataEnum, - ) -> TokenStream { - let v = e.variants - .iter() - .map(|v| { - let name = format!("{}::{}", name, v.ident); - let ident = &v.ident; - match v.fields { - syn::Fields::Named(ref f) => { - let names: Vec<_> = f.named.iter().flat_map(|f| f.ident.clone()).collect(); - let fields_impl = derive_fields(&name, Fields::Named { - names: names.clone(), - this: None, - }); - (ident, (quote!{ { #( ref #names ),* } }, fields_impl)) - }, - syn::Fields::Unnamed(ref f) => { - let names = f.unnamed.iter() - .enumerate() - .map(|(id, _)| Ident::new(&format!("a{}", id), Span::call_site())) - .collect::>(); - let fields_impl = derive_fields(&name, Fields::Unnamed { vars: names.clone() }); - (ident, (quote! { ( #( ref #names ),* ) }, fields_impl)) - }, - syn::Fields::Unit => { - let fields_impl = derive_fields(&name, Fields::Indexed { indices: vec![] }); - (ident, (quote! { }, fields_impl)) - }, - } - }); - - type Vecs = (Vec, Vec); - let (variants, others): Vecs<_, _> = v.unzip(); - let (match_fields, variants_impl): Vecs<_, _> = others.into_iter().unzip(); - - quote! { - match self { - #( Self::#variants #match_fields => #variants_impl, )* - _ => Ok(()), - } - } - } - - fn derive_struct( - name_str: &str, - fields: &syn::Fields, - ) -> TokenStream { - match *fields { - syn::Fields::Named(ref f) => derive_fields( - name_str, - Fields::new(f.named.iter(), Some(syn::Token!(self)(Span::call_site()))), - ), - syn::Fields::Unnamed(ref f) => derive_fields( - name_str, - Fields::new(f.unnamed.iter(), None), - ), - syn::Fields::Unit => derive_fields( - name_str, - Fields::Indexed { indices: vec![] }, - ), - } - } -} diff --git a/core/primitives/debug-derive/src/lib.rs b/core/primitives/debug-derive/src/lib.rs deleted file mode 100644 index 5e6cf6098b30e..0000000000000 --- a/core/primitives/debug-derive/src/lib.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Macros to derive runtime debug implementation. -//! -//! This custom derive implements a `core::fmt::Debug` trait, -//! but in case the `std` feature is enabled the implementation -//! will actually print out the structure as regular `derive(Debug)` -//! would do. If `std` is disabled the implementation will be empty. -//! -//! This behaviour is useful to prevent bloating the runtime WASM -//! blob from unneeded code. -//! -//! ```rust -//! #[derive(substrate_debug_derive::RuntimeDebug)] -//! struct MyStruct; -//! -//! assert_eq!(format!("{:?}", MyStruct), "MyStruct"); -//! ``` - -extern crate proc_macro; - -mod impls; - -use proc_macro::TokenStream; - -#[proc_macro_derive(RuntimeDebug)] -pub fn debug_derive(input: TokenStream) -> TokenStream { - impls::debug_derive(syn::parse_macro_input!(input)) -} - diff --git a/core/primitives/debug-derive/tests/tests.rs b/core/primitives/debug-derive/tests/tests.rs deleted file mode 100644 index 63ad6a3e8d497..0000000000000 --- a/core/primitives/debug-derive/tests/tests.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use substrate_debug_derive::RuntimeDebug; - -#[derive(RuntimeDebug)] -struct Unnamed(u64, String); - -#[derive(RuntimeDebug)] -struct Named { - a: u64, - b: String, -} - -#[derive(RuntimeDebug)] -enum EnumLongName { - A, - B(A, String), - VariantLongName { - a: A, - b: String, - }, -} - - -#[test] -fn should_display_proper_debug() { - use self::EnumLongName as Enum; - - assert_eq!( - format!("{:?}", Unnamed(1, "abc".into())), - "Unnamed(1, \"abc\")" - ); - assert_eq!( - format!("{:?}", Named { a: 1, b: "abc".into() }), - "Named { a: 1, b: \"abc\" }" - ); - assert_eq!( - format!("{:?}", Enum::::A), - "EnumLongName::A" - ); - assert_eq!( - format!("{:?}", Enum::B(1, "abc".into())), - "EnumLongName::B(1, \"abc\")" - ); - assert_eq!( - format!("{:?}", Enum::VariantLongName { a: 1, b: "abc".into() }), - "EnumLongName::VariantLongName { a: 1, b: \"abc\" }" - ); -} diff --git a/core/primitives/src/ecdsa.rs b/core/primitives/src/ecdsa.rs deleted file mode 100644 index abff460c91034..0000000000000 --- a/core/primitives/src/ecdsa.rs +++ /dev/null @@ -1,608 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -// tag::description[] -//! Simple ECDSA API. -// end::description[] - -use rstd::cmp::Ordering; -use codec::{Encode, Decode}; - -#[cfg(feature = "std")] -use std::convert::{TryFrom, TryInto}; -#[cfg(feature = "std")] -use substrate_bip39::seed_from_entropy; -#[cfg(feature = "std")] -use bip39::{Mnemonic, Language, MnemonicType}; -#[cfg(feature = "std")] -use crate::{hashing::blake2_256, crypto::{Pair as TraitPair, DeriveJunction, SecretStringError, Ss58Codec}}; -#[cfg(feature = "std")] -use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; -use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}; -#[cfg(feature = "std")] -use secp256k1::{PublicKey, SecretKey}; - -/// A secret seed (which is bytewise essentially equivalent to a SecretKey). -/// -/// We need it as a different type because `Seed` is expected to be AsRef<[u8]>. -#[cfg(feature = "std")] -type Seed = [u8; 32]; - -/// The ECDSA 33-byte compressed public key. -#[derive(Clone, Encode, Decode)] -pub struct Public(pub [u8; 33]); - -impl PartialOrd for Public { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Public { - fn cmp(&self, other: &Self) -> Ordering { - self.0[..].cmp(&other.0[..]) - } -} - -impl PartialEq for Public { - fn eq(&self, other: &Self) -> bool { - &self.0[..] == &other.0[..] - } -} - -impl Eq for Public {} - -impl Default for Public { - fn default() -> Self { - Public([0u8; 33]) - } -} - -/// A key pair. -#[cfg(feature = "std")] -#[derive(Clone)] -pub struct Pair { - public: PublicKey, - secret: SecretKey, -} - -impl AsRef<[u8; 33]> for Public { - fn as_ref(&self) -> &[u8; 33] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl rstd::convert::TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 33 { - let mut inner = [0u8; 33]; - inner.copy_from_slice(data); - Ok(Public(inner)) - } else { - Err(()) - } - } -} - -impl From for [u8; 33] { - fn from(x: Public) -> Self { - x.0 - } -} - -#[cfg(feature = "std")] -impl From for Public { - fn from(x: Pair) -> Self { - x.public() - } -} - -impl UncheckedFrom<[u8; 33]> for Public { - fn unchecked_from(x: [u8; 33]) -> Self { - Public(x) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&&self.0[..]), &s[0..8]) - } -} - -#[cfg(feature = "std")] -impl Serialize for Public { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_str(&self.to_ss58check()) - } -} - -#[cfg(feature = "std")] -impl<'de> Deserialize<'de> for Public { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - Public::from_ss58check(&String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - } -} - -#[cfg(feature = "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([u8; 65]); - -impl rstd::convert::TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 65 { - let mut inner = [0u8; 65]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} - -impl Clone for Signature { - fn clone(&self) -> Self { - let mut r = [0u8; 65]; - r.copy_from_slice(&self.0[..]); - Signature(r) - } -} - -impl Default for Signature { - fn default() -> Self { - Signature([0u8; 65]) - } -} - -impl PartialEq for Signature { - fn eq(&self, b: &Self) -> bool { - self.0[..] == b.0[..] - } -} - -impl Eq for Signature {} - -impl From for [u8; 65] { - fn from(v: Signature) -> [u8; 65] { - v.0 - } -} - -impl AsRef<[u8; 65]> for Signature { - fn as_ref(&self) -> &[u8; 65] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for Signature { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } -} - -#[cfg(feature = "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 65-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_raw(data: [u8; 65]) -> Signature { - Signature(data) - } - - /// Recover the public key from this signature and a message. - #[cfg(feature = "std")] - pub fn recover>(&self, message: M) -> Option { - let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); - let sig: (_, _) = self.try_into().ok()?; - secp256k1::recover(&message, &sig.0, &sig.1).ok() - .map(|recovered| Public(recovered.serialize_compressed())) - } -} - -#[cfg(feature = "std")] -impl From<(secp256k1::Signature, secp256k1::RecoveryId)> for Signature { - fn from(x: (secp256k1::Signature, secp256k1::RecoveryId)) -> Signature { - let mut r = Self::default(); - r.0[0..64].copy_from_slice(&x.0.serialize()[..]); - r.0[64] = x.1.serialize(); - r - } -} - -#[cfg(feature = "std")] -impl<'a> TryFrom<&'a Signature> for (secp256k1::Signature, secp256k1::RecoveryId) { - type Error = (); - fn try_from(x: &'a Signature) -> Result<(secp256k1::Signature, secp256k1::RecoveryId), Self::Error> { - Ok(( - secp256k1::Signature::parse_slice(&x.0[0..64]).expect("hardcoded to 64 bytes; qed"), - secp256k1::RecoveryId::parse(x.0[64]).map_err(|_| ())?, - )) - } -} - -/// An error type for SS58 decoding. -#[cfg(feature = "std")] -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum PublicError { - /// Bad alphabet. - BadBase58, - /// Bad length. - BadLength, - /// Unknown version. - UnknownVersion, - /// Invalid checksum. - InvalidChecksum, -} - -impl Public { - /// A new instance from the given 33-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_raw(data: [u8; 33]) -> Self { - Public(data) - } - - /// Return a slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 33] { - self.as_ref() - } -} - -impl TraitPublic for Public { - /// A new instance from the given slice that should be 33 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 33]; - r.copy_from_slice(data); - Public(r) - } -} - -impl Derive for Public {} - -/// Derive a single hard junction. -#[cfg(feature = "std")] -fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { - ("Secp256k1HDKD", secret_seed, cc).using_encoded(|data| { - let mut res = [0u8; 32]; - res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); - res - }) -} - -/// An error when deriving a key. -#[cfg(feature = "std")] -pub enum DeriveError { - /// A soft key was found in the path (and is unsupported). - SoftKeyInPath, -} - -#[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 and provide the recovery phrase. - /// - /// You can recover the same key later with `from_phrase`. - fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { - let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); - let phrase = mnemonic.phrase(); - let (pair, seed) = Self::from_phrase(phrase, password) - .expect("All phrases generated by Mnemonic are valid; qed"); - ( - pair, - phrase.to_owned(), - seed, - ) - } - - /// Generate key pair from given recovery phrase and password. - fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { - let big_seed = seed_from_entropy( - Mnemonic::from_phrase(phrase, Language::English) - .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(), - password.unwrap_or(""), - ).map_err(|_| SecretStringError::InvalidSeed)?; - let mut seed = Seed::default(); - seed.copy_from_slice(&big_seed[0..32]); - Self::from_seed_slice(&big_seed[0..32]).map(|x| (x, seed)) - } - - /// Make a new key pair from secret seed material. - /// - /// You should never need to use this; generate(), generate_with_phrase - fn from_seed(seed: &Seed) -> Pair { - Self::from_seed_slice(&seed[..]).expect("seed has valid length; qed") - } - - /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it - /// will return `None`. - /// - /// You should never need to use this; generate(), generate_with_phrase - fn from_seed_slice(seed_slice: &[u8]) -> Result { - let secret = SecretKey::parse_slice(seed_slice) - .map_err(|_| SecretStringError::InvalidSeedLength)?; - let public = PublicKey::from_secret_key(&secret); - Ok(Pair{ secret, public }) - } - - /// Derive a child key from a series of given junctions. - fn derive>(&self, - path: Iter, - _seed: Option - ) -> Result<(Pair, Option), DeriveError> { - let mut acc = self.secret.serialize(); - for j in path { - match j { - DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), - DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), - } - } - Ok((Self::from_seed(&acc), Some(acc))) - } - - /// Get the public key. - fn public(&self) -> Public { - Public(self.public.serialize_compressed()) - } - - /// Sign a message. - fn sign(&self, message: &[u8]) -> Signature { - let message = secp256k1::Message::parse(&blake2_256(message)); - secp256k1::sign(&message, &self.secret).into() - } - - /// Verify a signature on a message. Returns true if the signature is good. - fn verify>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { - let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); - let sig: (_, _) = match sig.try_into() { Ok(x) => x, _ => return false }; - match secp256k1::recover(&message, &sig.0, &sig.1) { - Ok(actual) => &pubkey.0[..] == &actual.serialize_compressed()[..], - _ => false, - } - } - - /// Verify a signature on a message. Returns true if the signature is good. - /// - /// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct - /// size. Use it only if you're coming from byte buffers and need the speed. - fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { - let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); - if sig.len() != 65 { return false } - let ri = match secp256k1::RecoveryId::parse(sig[64]) { Ok(x) => x, _ => return false }; - let sig = match secp256k1::Signature::parse_slice(&sig[0..64]) { Ok(x) => x, _ => return false }; - match secp256k1::recover(&message, &sig, &ri) { - Ok(actual) => pubkey.as_ref() == &actual.serialize_compressed()[..], - _ => false, - } - } - - /// Return a vec filled with raw data. - fn to_raw_vec(&self) -> Vec { - self.seed().to_vec() - } -} - -#[cfg(feature = "std")] -impl Pair { - /// Get the seed for this key. - pub fn seed(&self) -> Seed { - self.secret.serialize() - } - - /// Exactly as `from_string` except that if no matches are found then, the the first 32 - /// characters are taken (padded with spaces as necessary) and used as the MiniSecretKey. - pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair { - Self::from_string(s, password_override).unwrap_or_else(|_| { - let mut padded_seed: Seed = [' ' as u8; 32]; - let len = s.len().min(32); - padded_seed[..len].copy_from_slice(&s.as_bytes()[..len]); - Self::from_seed(&padded_seed) - }) - } -} - -impl CryptoType for Public { - #[cfg(feature="std")] - type Pair = Pair; -} - -impl CryptoType for Signature { - #[cfg(feature="std")] - type Pair = Pair; -} - -#[cfg(feature = "std")] -impl CryptoType for Pair { - type Pair = Pair; -} - -#[cfg(test)] -mod test { - use super::*; - use hex_literal::hex; - use crate::crypto::DEV_PHRASE; - - #[test] - fn default_phrase_should_be_used() { - assert_eq!( - Pair::from_string("//Alice///password", None).unwrap().public(), - Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), - ); - } - - #[test] - fn seed_and_derive_should_work() { - let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); - let pair = Pair::from_seed(&seed); - assert_eq!(pair.seed(), seed); - let path = vec![DeriveJunction::Hard([0u8; 32])]; - let derived = pair.derive(path.into_iter(), None).ok().unwrap(); - assert_eq!( - derived.0.seed(), - hex!("b8eefc4937200a8382d00050e050ced2d4ab72cc2ef1b061477afb51564fdd61") - ); - } - - #[test] - fn test_vector_should_work() { - let pair = Pair::from_seed( - &hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") - ); - let public = pair.public(); - assert_eq!(public, Public::from_raw( - hex!("028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd91") - )); - let message = b""; - let signature = hex!("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00"); - let signature = Signature::from_raw(signature); - assert!(&pair.sign(&message[..]) == &signature); - assert!(Pair::verify(&signature, &message[..], &public)); - } - - #[test] - fn test_vector_by_string_should_work() { - let pair = Pair::from_string( - "0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", - None - ).unwrap(); - let public = pair.public(); - assert_eq!(public, Public::from_raw( - hex!("028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd91") - )); - let message = b""; - let signature = hex!("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00"); - let signature = Signature::from_raw(signature); - assert!(&pair.sign(&message[..]) == &signature); - assert!(Pair::verify(&signature, &message[..], &public)); - } - - #[test] - fn generated_pair_should_work() { - let (pair, _) = Pair::generate(); - let public = pair.public(); - let message = b"Something important"; - let signature = pair.sign(&message[..]); - assert!(Pair::verify(&signature, &message[..], &public)); - assert!(!Pair::verify(&signature, b"Something else", &public)); - } - - #[test] - fn seeded_pair_should_work() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); - let public = pair.public(); - assert_eq!(public, Public::from_raw( - hex!("035676109c54b9a16d271abeb4954316a40a32bcce023ac14c8e26e958aa68fba9") - )); - let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); - let signature = pair.sign(&message[..]); - println!("Correct signature: {:?}", signature); - assert!(Pair::verify(&signature, &message[..], &public)); - assert!(!Pair::verify(&signature, "Other message", &public)); - } - - #[test] - fn generate_with_phrase_recovery_possible() { - let (pair1, phrase, _) = Pair::generate_with_phrase(None); - let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); - - assert_eq!(pair1.public(), pair2.public()); - } - - #[test] - fn generate_with_password_phrase_recovery_possible() { - let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); - let (pair2, _) = Pair::from_phrase(&phrase, Some("password")).unwrap(); - - assert_eq!(pair1.public(), pair2.public()); - } - - #[test] - fn password_does_something() { - let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); - let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); - - assert_ne!(pair1.public(), pair2.public()); - } - - #[test] - fn ss58check_roundtrip_works() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); - let public = pair.public(); - let s = public.to_ss58check(); - println!("Correct: {}", s); - let cmp = Public::from_ss58check(&s).unwrap(); - assert_eq!(cmp, public); - } -} diff --git a/core/primitives/src/ed25519.rs b/core/primitives/src/ed25519.rs deleted file mode 100644 index 8c3aa9f89dbdc..0000000000000 --- a/core/primitives/src/ed25519.rs +++ /dev/null @@ -1,620 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -// tag::description[] -//! Simple Ed25519 API. -// end::description[] - - -use crate::{hash::H256, hash::H512}; -use codec::{Encode, Decode}; - -#[cfg(feature = "std")] -use blake2_rfc; -#[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, Ss58Codec}; -#[cfg(feature = "std")] -use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; -use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}}; - -/// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys -/// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we -/// will need it later (such as for HDKD). -#[cfg(feature = "std")] -type Seed = [u8; 32]; - -/// A public key. -#[cfg_attr(feature = "std", derive(Hash))] -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] -pub struct Public(pub [u8; 32]); - -/// A key pair. -#[cfg(feature = "std")] -pub struct Pair(ed25519_dalek::Keypair); - -#[cfg(feature = "std")] -impl Clone for Pair { - fn clone(&self) -> Self { - Pair(ed25519_dalek::Keypair { - public: self.0.public.clone(), - secret: ed25519_dalek::SecretKey::from_bytes(self.0.secret.as_bytes()) - .expect("key is always the correct size; qed") - }) - } -} - -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 rstd::convert::TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 32 { - let mut inner = [0u8; 32]; - inner.copy_from_slice(data); - Ok(Public(inner)) - } else { - Err(()) - } - } -} - -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 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()) - } -} - -impl rstd::fmt::Debug for Public { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "std")] -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))) - } -} - -/// A signature (a 512-bit value). -#[derive(Encode, Decode)] -pub struct Signature(pub [u8; 64]); - -impl rstd::convert::TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 64 { - let mut inner = [0u8; 64]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} - -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[..] - } -} - -impl rstd::fmt::Debug for Signature { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "std")] -impl std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - std::hash::Hash::hash(&self.0[..], state); - } -} - -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. - BadBase58, - /// Bad length. - BadLength, - /// Unknown version. - UnknownVersion, - /// Invalid checksum. - InvalidChecksum, -} - -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 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 slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 32] { - self.as_ref() - } -} - -impl TraitPublic for Public { - /// 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! - fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Public(r) - } -} - -impl Derive for Public {} - -/// 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 - }) -} - -/// An error when deriving a key. -#[cfg(feature = "std")] -pub enum DeriveError { - /// A soft key was found in the path (and is unsupported). - SoftKeyInPath, -} - -#[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 and provide the recovery phrase. - /// - /// You can recover the same key later with `from_phrase`. - fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { - let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); - let phrase = mnemonic.phrase(); - let (pair, seed) = Self::from_phrase(phrase, password) - .expect("All phrases generated by Mnemonic are valid; qed"); - ( - pair, - phrase.to_owned(), - seed, - ) - } - - /// Generate key pair from given recovery phrase and password. - fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { - let big_seed = seed_from_entropy( - Mnemonic::from_phrase(phrase, Language::English) - .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(), - password.unwrap_or(""), - ).map_err(|_| SecretStringError::InvalidSeed)?; - let mut seed = Seed::default(); - seed.copy_from_slice(&big_seed[0..32]); - Self::from_seed_slice(&big_seed[0..32]).map(|x| (x, seed)) - } - - /// Make a new key pair from secret seed material. - /// - /// You should never need to use this; generate(), generate_with_phrasee - fn from_seed(seed: &Seed) -> Pair { - Self::from_seed_slice(&seed[..]).expect("seed has valid length; qed") - } - - /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it - /// will return `None`. - /// - /// You should never need to use this; generate(), generate_with_phrase - fn from_seed_slice(seed_slice: &[u8]) -> Result { - let secret = ed25519_dalek::SecretKey::from_bytes(seed_slice) - .map_err(|_| SecretStringError::InvalidSeedLength)?; - let public = ed25519_dalek::PublicKey::from(secret.expand::()); - Ok(Pair(ed25519_dalek::Keypair { secret, public })) - } - - /// Derive a child key from a series of given junctions. - fn derive>(&self, - path: Iter, - _seed: Option, - ) -> Result<(Pair, Option), DeriveError> { - let mut acc = self.0.secret.to_bytes(); - for j in path { - match j { - DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), - DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), - } - } - Ok((Self::from_seed(&acc), Some(acc))) - } - - /// Get the public key. - fn public(&self) -> Public { - let mut r = [0u8; 32]; - let pk = self.0.public.as_bytes(); - r.copy_from_slice(pk); - Public(r) - } - - /// Sign a message. - fn sign(&self, message: &[u8]) -> Signature { - let r = self.0.sign::(message).to_bytes(); - Signature::from_raw(r) - } - - /// Verify a signature on a message. Returns true if the signature is good. - fn verify>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { - Self::verify_weak(&sig.0[..], message.as_ref(), pubkey) - } - - /// 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 = match ed25519_dalek::PublicKey::from_bytes(pubkey.as_ref()) { - Ok(pk) => pk, - Err(_) => return false, - }; - - let sig = match ed25519_dalek::Signature::from_bytes(sig) { - Ok(s) => s, - Err(_) => return false - }; - - match public_key.verify::(message.as_ref(), &sig) { - Ok(_) => true, - _ => false, - } - } - - /// Return a vec filled with raw data. - fn to_raw_vec(&self) -> Vec { - self.seed().to_vec() - } -} - -#[cfg(feature = "std")] -impl Pair { - /// Get the seed for this key. - pub fn seed(&self) -> &Seed { - self.0.secret.as_bytes() - } - - /// 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) - }) - } -} - -impl CryptoType for Public { - #[cfg(feature="std")] - type Pair = Pair; -} - -impl CryptoType for Signature { - #[cfg(feature="std")] - type Pair = Pair; -} - -#[cfg(feature = "std")] -impl CryptoType for Pair { - type Pair = Pair; -} - -#[cfg(test)] -mod test { - use super::*; - use hex_literal::hex; - use crate::crypto::DEV_PHRASE; - - #[test] - fn default_phrase_should_be_used() { - assert_eq!( - Pair::from_string("//Alice///password", None).unwrap().public(), - Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), - ); - } - - #[test] - fn seed_and_derive_should_work() { - let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); - let pair = Pair::from_seed(&seed); - assert_eq!(pair.seed(), &seed); - let path = vec![DeriveJunction::Hard([0u8; 32])]; - let derived = pair.derive(path.into_iter(), None).ok().unwrap().0; - assert_eq!( - derived.seed(), - &hex!("ede3354e133f9c8e337ddd6ee5415ed4b4ffe5fc7d21e933f4930a3730e5b21c") - ); - } - - #[test] - fn test_vector_should_work() { - let pair = Pair::from_seed( - &hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") - ); - let public = pair.public(); - assert_eq!(public, Public::from_raw( - hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a") - )); - let message = b""; - let signature = hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"); - let signature = Signature::from_raw(signature); - assert!(&pair.sign(&message[..]) == &signature); - assert!(Pair::verify(&signature, &message[..], &public)); - } - - #[test] - fn test_vector_by_string_should_work() { - let pair = Pair::from_string( - "0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", - None - ).unwrap(); - let public = pair.public(); - assert_eq!(public, Public::from_raw( - hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a") - )); - let message = b""; - let signature = hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"); - let signature = Signature::from_raw(signature); - assert!(&pair.sign(&message[..]) == &signature); - assert!(Pair::verify(&signature, &message[..], &public)); - } - - #[test] - fn generated_pair_should_work() { - let (pair, _) = Pair::generate(); - let public = pair.public(); - let message = b"Something important"; - let signature = pair.sign(&message[..]); - assert!(Pair::verify(&signature, &message[..], &public)); - assert!(!Pair::verify(&signature, b"Something else", &public)); - } - - #[test] - fn seeded_pair_should_work() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); - let public = pair.public(); - assert_eq!(public, Public::from_raw( - hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee") - )); - let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); - let signature = pair.sign(&message[..]); - println!("Correct signature: {:?}", signature); - assert!(Pair::verify(&signature, &message[..], &public)); - assert!(!Pair::verify(&signature, "Other message", &public)); - } - - #[test] - fn generate_with_phrase_recovery_possible() { - let (pair1, phrase, _) = Pair::generate_with_phrase(None); - let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); - - assert_eq!(pair1.public(), pair2.public()); - } - - #[test] - fn generate_with_password_phrase_recovery_possible() { - let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); - let (pair2, _) = Pair::from_phrase(&phrase, Some("password")).unwrap(); - - assert_eq!(pair1.public(), pair2.public()); - } - - #[test] - fn password_does_something() { - let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); - let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); - - assert_ne!(pair1.public(), pair2.public()); - } - - #[test] - fn ss58check_roundtrip_works() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); - let public = pair.public(); - let s = public.to_ss58check(); - println!("Correct: {}", s); - let cmp = Public::from_ss58check(&s).unwrap(); - assert_eq!(cmp, public); - } -} diff --git a/core/primitives/src/hash.rs b/core/primitives/src/hash.rs deleted file mode 100644 index c63463e32ae2b..0000000000000 --- a/core/primitives/src/hash.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! A fixed hash type. - -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. -/// Panics if used to convert between different hash types. -pub fn convert_hash, H2: AsRef<[u8]>>(src: &H2) -> H1 { - let mut dest = H1::default(); - assert_eq!(dest.as_mut().len(), src.as_ref().len()); - dest.as_mut().copy_from_slice(src.as_ref()); - dest -} - -#[cfg(test)] -mod tests { - use super::*; - use substrate_serializer as ser; - - #[test] - fn test_h160() { - let tests = vec![ - (Default::default(), "0x0000000000000000000000000000000000000000"), - (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 { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number)); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } - } - - #[test] - fn test_h256() { - let tests = vec![ - (Default::default(), "0x0000000000000000000000000000000000000000000000000000000000000000"), - (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 { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number)); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } - } - - #[test] - fn test_invalid() { - assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"10\"").unwrap_err().is_data()); - } -} diff --git a/core/primitives/src/lib.rs b/core/primitives/src/lib.rs deleted file mode 100644 index 02f28c797c002..0000000000000 --- a/core/primitives/src/lib.rs +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Shareable Substrate types. - -#![warn(missing_docs)] - -#![cfg_attr(not(feature = "std"), no_std)] - -/// Initialize 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 ),* $(,)? ) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ); -} - -use rstd::prelude::*; -use rstd::ops::Deref; -#[cfg(feature = "std")] -use std::borrow::Cow; -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -#[cfg(feature = "std")] -pub use serde;// << for macro -#[doc(hidden)] -pub use codec::{Encode, Decode};// << for macro - -pub use substrate_debug_derive::RuntimeDebug; - -#[cfg(feature = "std")] -pub use impl_serde::serialize as bytes; - -#[cfg(feature = "std")] -pub mod hashing; -#[cfg(feature = "std")] -pub use hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256}; -#[cfg(feature = "std")] -pub mod hexdisplay; -pub mod crypto; - -pub mod u32_trait; - -pub mod ed25519; -pub mod sr25519; -pub mod ecdsa; -pub mod hash; -mod hasher; -pub mod offchain; -pub mod sandbox; -pub mod uint; -mod changes_trie; -#[cfg(feature = "std")] -pub mod traits; -pub mod testing; - -#[cfg(test)] -mod tests; - -pub use self::hash::{H160, H256, H512, convert_hash}; -pub use self::uint::U256; -pub use changes_trie::ChangesTrieConfiguration; -#[cfg(feature = "std")] -pub use crypto::{DeriveJunction, Pair, Public}; - -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; - -pub use primitives_storage as storage; - -#[doc(hidden)] -pub use rstd; - -/// Context for executing a call into the runtime. -pub enum ExecutionContext { - /// Context for general importing (including own blocks). - Importing, - /// Context used when syncing the blockchain. - Syncing, - /// Context used for block construction. - BlockConstruction, - /// Context used for offchain calls. - /// - /// This allows passing offchain extension and customizing available capabilities. - OffchainCall(Option<(Box, offchain::Capabilities)>), -} - -impl ExecutionContext { - /// Returns the capabilities of particular context. - pub fn capabilities(&self) -> offchain::Capabilities { - use ExecutionContext::*; - - match self { - Importing | Syncing | BlockConstruction => - offchain::Capabilities::none(), - // Enable keystore by default for offchain calls. CC @bkchr - OffchainCall(None) => [offchain::Capability::Keystore][..].into(), - OffchainCall(Some((_, capabilities))) => *capabilities, - } - } -} - -/// Hex-serialized shim for `Vec`. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord))] -pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -impl From> for Bytes { - fn from(s: Vec) -> Self { Bytes(s) } -} - -impl From for Bytes { - fn from(s: OpaqueMetadata) -> Self { Bytes(s.0) } -} - -impl Deref for Bytes { - type Target = [u8]; - fn deref(&self) -> &[u8] { &self.0[..] } -} - -/// Stores the encoded `RuntimeMetadata` for the native side as opaque type. -#[derive(Encode, Decode, PartialEq)] -pub struct OpaqueMetadata(Vec); - -impl OpaqueMetadata { - /// Creates a new instance with the given metadata blob. - pub fn new(metadata: Vec) -> Self { - OpaqueMetadata(metadata) - } -} - -impl rstd::ops::Deref for OpaqueMetadata { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &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 rstd::fmt::Debug for NativeOrEncoded { - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - hexdisplay::HexDisplay::from(&self.as_encoded().as_ref()).fmt(f) - } -} - -#[cfg(feature = "std")] -impl NativeOrEncoded { - /// Return the value as the encoded format. - pub fn as_encoded(&self) -> Cow<'_, [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) == codec::Decode::decode(&mut &e[..]).ok().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 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 codec::EncodeLike for NeverNativeValue {} - -#[cfg(feature = "std")] -impl codec::Decode for NeverNativeValue { - fn decode(_: &mut I) -> Result { - Err("`NeverNativeValue` should never be decoded".into()) - } -} - -/// Provide a simple 4 byte identifier for a type. -pub trait TypeId { - /// Simple 4 byte identifier. - const TYPE_ID: [u8; 4]; -} - -/// A log level matching the one from `log` crate. -/// -/// Used internally by `runtime_io::log` method. -#[repr(u32)] -pub enum LogLevel { - /// `Error` log level. - Error = 1, - /// `Warn` log level. - Warn = 2, - /// `Info` log level. - Info = 3, - /// `Debug` log level. - Debug = 4, - /// `Trace` log level. - Trace = 5, -} - -impl From for LogLevel { - fn from(val: u32) -> Self { - match val { - x if x == LogLevel::Warn as u32 => LogLevel::Warn, - x if x == LogLevel::Info as u32 => LogLevel::Info, - x if x == LogLevel::Debug as u32 => LogLevel::Debug, - x if x == LogLevel::Trace as u32 => LogLevel::Trace, - _ => LogLevel::Error, - } - } -} - -impl From for LogLevel { - fn from(l: log::Level) -> Self { - use log::Level::*; - match l { - Error => Self::Error, - Warn => Self::Warn, - Info => Self::Info, - Debug => Self::Debug, - Trace => Self::Trace, - } - } -} - -impl From for log::Level { - fn from(l: LogLevel) -> Self { - use self::LogLevel::*; - match l { - Error => Self::Error, - Warn => Self::Warn, - Info => Self::Info, - Debug => Self::Debug, - Trace => Self::Trace, - } - } -} - -/// Encodes the given value into a buffer and returns the pointer and the length as a single `u64`. -/// -/// When Substrate calls into Wasm it expects a fixed signature for functions exported -/// from the Wasm blob. The return value of this signature is always a `u64`. -/// This `u64` stores the pointer to the encoded return value and the length of this encoded value. -/// The low `32bits` are reserved for the pointer, followed by `32bit` for the length. -#[cfg(not(feature = "std"))] -pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 { - let encoded = value.encode(); - - let ptr = encoded.as_ptr() as u64; - let length = encoded.len() as u64; - let res = ptr | (length << 32); - - // Leak the output vector to avoid it being freed. - // This is fine in a WASM context since the heap - // will be discarded after the call. - rstd::mem::forget(encoded); - - res -} diff --git a/core/primitives/src/offchain.rs b/core/primitives/src/offchain.rs deleted file mode 100644 index 27bd29a00df8d..0000000000000 --- a/core/primitives/src/offchain.rs +++ /dev/null @@ -1,697 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Offchain workers types - -use codec::{Encode, Decode}; -use rstd::{prelude::{Vec, Box}, convert::TryFrom}; -use crate::RuntimeDebug; - -pub use crate::crypto::KeyTypeId; - -/// A type of supported crypto. -#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug)] -#[repr(C)] -pub enum StorageKind { - /// Persistent storage is non-revertible and not fork-aware. It means that any value - /// set by the offchain worker triggered at block `N(hash1)` is persisted even - /// if that block is reverted as non-canonical and is available for the worker - /// that is re-run at block `N(hash2)`. - /// This storage can be used by offchain workers to handle forks - /// and coordinate offchain workers running on different forks. - PERSISTENT = 1, - /// Local storage is revertible and fork-aware. It means that any value - /// set by the offchain worker triggered at block `N(hash1)` is reverted - /// if that block is reverted as non-canonical and is NOT available for the worker - /// that is re-run at block `N(hash2)`. - LOCAL = 2, -} - -impl TryFrom for StorageKind { - type Error = (); - - fn try_from(kind: u32) -> Result { - match kind { - e if e == u32::from(StorageKind::PERSISTENT as u8) => Ok(StorageKind::PERSISTENT), - e if e == u32::from(StorageKind::LOCAL as u8) => Ok(StorageKind::LOCAL), - _ => Err(()), - } - } -} - -impl From for u32 { - fn from(c: StorageKind) -> Self { - c as u8 as u32 - } -} - -/// Opaque type for offchain http requests. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Hash))] -pub struct HttpRequestId(pub u16); - -impl From for u32 { - fn from(c: HttpRequestId) -> Self { - c.0 as u32 - } -} - -/// An error enum returned by some http methods. -#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug)] -#[repr(C)] -pub enum HttpError { - /// The requested action couldn't been completed within a deadline. - DeadlineReached = 1, - /// There was an IO Error while processing the request. - IoError = 2, - /// The ID of the request is invalid in this context. - Invalid = 3, -} - -impl TryFrom for HttpError { - type Error = (); - - fn try_from(error: u32) -> Result { - match error { - e if e == HttpError::DeadlineReached as u8 as u32 => Ok(HttpError::DeadlineReached), - e if e == HttpError::IoError as u8 as u32 => Ok(HttpError::IoError), - e if e == HttpError::Invalid as u8 as u32 => Ok(HttpError::Invalid), - _ => Err(()) - } - } -} - -impl From for u32 { - fn from(c: HttpError) -> Self { - c as u8 as u32 - } -} - -/// Status of the HTTP request -#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug)] -pub enum HttpRequestStatus { - /// Deadline was reached while we waited for this request to finish. - /// - /// Note the deadline is controlled by the calling part, it not necessarily - /// means that the request has timed out. - DeadlineReached, - /// An error has occured during the request, for example a timeout or the - /// remote has closed our socket. - /// - /// The request is now considered destroyed. To retry the request you need - /// to construct it again. - IoError, - /// The passed ID is invalid in this context. - Invalid, - /// The request has finished with given status code. - Finished(u16), -} - -impl From for u32 { - fn from(status: HttpRequestStatus) -> Self { - match status { - HttpRequestStatus::Invalid => 0, - HttpRequestStatus::DeadlineReached => 10, - HttpRequestStatus::IoError => 20, - HttpRequestStatus::Finished(code) => u32::from(code), - } - } -} - -impl TryFrom for HttpRequestStatus { - type Error = (); - - fn try_from(status: u32) -> Result { - match status { - 0 => Ok(HttpRequestStatus::Invalid), - 10 => Ok(HttpRequestStatus::DeadlineReached), - 20 => Ok(HttpRequestStatus::IoError), - 100..=999 => u16::try_from(status).map(HttpRequestStatus::Finished).map_err(|_| ()), - _ => Err(()), - } - } -} - -/// A blob to hold information about the local node's network state -/// without committing to its format. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] -pub struct OpaqueNetworkState { - /// PeerId of the local node. - pub peer_id: OpaquePeerId, - /// List of addresses the node knows it can be reached as. - pub external_addresses: Vec, -} - -/// Simple blob to hold a `PeerId` without committing to its format. -#[derive(Default, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] -pub struct OpaquePeerId(pub Vec); - -impl OpaquePeerId { - /// Create new `OpaquePeerId` - pub fn new(vec: Vec) -> Self { - OpaquePeerId(vec) - } -} - -/// Simple blob to hold a `Multiaddr` without committing to its format. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] -pub struct OpaqueMultiaddr(pub Vec); - -impl OpaqueMultiaddr { - /// Create new `OpaqueMultiaddr` - pub fn new(vec: Vec) -> Self { - OpaqueMultiaddr(vec) - } -} - -/// Opaque timestamp type -#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug)] -pub struct Timestamp(u64); - -/// Duration type -#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug)] -pub struct Duration(u64); - -impl Duration { - /// Create new duration representing given number of milliseconds. - pub fn from_millis(millis: u64) -> Self { - Duration(millis) - } - - /// Returns number of milliseconds this Duration represents. - pub fn millis(&self) -> u64 { - self.0 - } -} - -impl Timestamp { - /// Creates new `Timestamp` given unix timestamp in miliseconds. - pub fn from_unix_millis(millis: u64) -> Self { - Timestamp(millis) - } - - /// Increase the timestamp by given `Duration`. - pub fn add(&self, duration: Duration) -> Timestamp { - Timestamp(self.0.saturating_add(duration.0)) - } - - /// Decrease the timestamp by given `Duration` - pub fn sub(&self, duration: Duration) -> Timestamp { - Timestamp(self.0.saturating_sub(duration.0)) - } - - /// Returns a saturated difference (Duration) between two Timestamps. - pub fn diff(&self, other: &Self) -> Duration { - Duration(self.0.saturating_sub(other.0)) - } - - /// Return number of milliseconds since UNIX epoch. - pub fn unix_millis(&self) -> u64 { - self.0 - } -} - -/// Execution context extra capabilities. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[repr(u8)] -pub enum Capability { - /// Access to transaction pool. - TransactionPool = 1, - /// External http calls. - Http = 2, - /// Keystore access. - Keystore = 4, - /// Randomness source. - Randomness = 8, - /// Access to opaque network state. - NetworkState = 16, - /// Access to offchain worker DB (read only). - OffchainWorkerDbRead = 32, - /// Access to offchain worker DB (writes). - OffchainWorkerDbWrite = 64, -} - -/// A set of capabilities -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Capabilities(u8); - -impl Capabilities { - /// Return an object representing an empty set of capabilities. - pub fn none() -> Self { - Self(0) - } - - /// Return an object representing all capabilities enabled. - pub fn all() -> Self { - Self(u8::max_value()) - } - - /// Return capabilities for rich offchain calls. - /// - /// Those calls should be allowed to sign and submit transactions - /// and access offchain workers database (but read only!). - pub fn rich_offchain_call() -> Self { - [ - Capability::TransactionPool, - Capability::Keystore, - Capability::OffchainWorkerDbRead, - ][..].into() - } - - /// Check if particular capability is enabled. - pub fn has(&self, capability: Capability) -> bool { - self.0 & capability as u8 != 0 - } - - /// Check if this capability object represents all capabilities. - pub fn has_all(&self) -> bool { - self == &Capabilities::all() - } -} - -impl<'a> From<&'a [Capability]> for Capabilities { - fn from(list: &'a [Capability]) -> Self { - Capabilities(list.iter().fold(0_u8, |a, b| a | *b as u8)) - } -} - -/// An extended externalities for offchain workers. -pub trait Externalities { - /// Returns if the local node is a potential validator. - /// - /// Even if this function returns `true`, it does not mean that any keys are configured - /// and that the validator is registered in the chain. - fn is_validator(&self) -> bool; - /// Submit transaction. - /// - /// The transaction will end up in the pool and be propagated to others. - fn submit_transaction(&mut self, extrinsic: Vec) -> Result<(), ()>; - - /// Returns information about the local node's network state. - fn network_state(&self) -> Result; - - /// Returns current UNIX timestamp (in millis) - fn timestamp(&mut self) -> Timestamp; - - /// Pause the execution until `deadline` is reached. - fn sleep_until(&mut self, deadline: Timestamp); - - /// Returns a random seed. - /// - /// This is a trully random non deterministic seed generated by host environment. - /// Obviously fine in the off-chain worker context. - fn random_seed(&mut self) -> [u8; 32]; - - /// Sets a value in the local storage. - /// - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]); - - /// Sets a value in the local storage if it matches current value. - /// - /// Since multiple offchain workers may be running concurrently, to prevent - /// data races use CAS to coordinate between them. - /// - /// Returns `true` if the value has been set, `false` otherwise. - /// - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_compare_and_set( - &mut self, - kind: StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool; - - /// Gets a value from the local storage. - /// - /// If the value does not exist in the storage `None` will be returned. - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option>; - - /// Initiates a http request given HTTP verb and the URL. - /// - /// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters. - /// Returns the id of newly started request. - /// - /// Returns an error if: - /// - No new request identifier could be allocated. - /// - The method or URI contain invalid characters. - /// - fn http_request_start( - &mut self, - method: &str, - uri: &str, - meta: &[u8] - ) -> Result; - - /// Append header to the request. - /// - /// Calling this function multiple times with the same header name continues appending new - /// headers. In other words, headers are never replaced. - /// - /// Returns an error if: - /// - The request identifier is invalid. - /// - You have called `http_request_write_body` on that request. - /// - The name or value contain invalid characters. - /// - /// An error doesn't poison the request, and you can continue as if the call had never been - /// made. - /// - fn http_request_add_header( - &mut self, - request_id: HttpRequestId, - name: &str, - value: &str - ) -> Result<(), ()>; - - /// Write a chunk of request body. - /// - /// Calling this function with a non-empty slice may or may not start the - /// HTTP request. Calling this function with an empty chunks finalizes the - /// request and always starts it. It is no longer valid to write more data - /// afterwards. - /// Passing `None` as deadline blocks forever. - /// - /// Returns an error if: - /// - The request identifier is invalid. - /// - `http_response_wait` has already been called on this request. - /// - The deadline is reached. - /// - An I/O error has happened, for example the remote has closed our - /// request. The request is then considered invalid. - /// - fn http_request_write_body( - &mut self, - request_id: HttpRequestId, - chunk: &[u8], - deadline: Option - ) -> Result<(), HttpError>; - - /// Block and wait for the responses for given requests. - /// - /// Returns a vector of request statuses (the len is the same as ids). - /// Note that if deadline is not provided the method will block indefinitely, - /// otherwise unready responses will produce `DeadlineReached` status. - /// - /// If a response returns an `IoError`, it is then considered destroyed. - /// Its id is then invalid. - /// - /// Passing `None` as deadline blocks forever. - fn http_response_wait( - &mut self, - ids: &[HttpRequestId], - deadline: Option - ) -> Vec; - - /// Read all response headers. - /// - /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. - /// - /// Dispatches the request if it hasn't been done yet. It is no longer - /// valid to modify the headers or write data to the request. - /// - /// Returns an empty list if the identifier is unknown/invalid, hasn't - /// received a response, or has finished. - fn http_response_headers( - &mut self, - request_id: HttpRequestId - ) -> Vec<(Vec, Vec)>; - - /// Read a chunk of body response to given buffer. - /// - /// Dispatches the request if it hasn't been done yet. It is no longer - /// valid to modify the headers or write data to the request. - /// - /// Returns the number of bytes written or an error in case a deadline - /// is reached or server closed the connection. - /// Passing `None` as a deadline blocks forever. - /// - /// If `Ok(0)` or `Err(IoError)` is returned, the request is considered - /// destroyed. Doing another read or getting the response's headers, for - /// example, is then invalid. - /// - /// Returns an error if: - /// - The request identifier is invalid. - /// - The deadline is reached. - /// - An I/O error has happened, for example the remote has closed our - /// request. The request is then considered invalid. - /// - fn http_response_read_body( - &mut self, - request_id: HttpRequestId, - buffer: &mut [u8], - deadline: Option - ) -> Result; - -} -impl Externalities for Box { - fn is_validator(&self) -> bool { - (& **self).is_validator() - } - - fn submit_transaction(&mut self, ex: Vec) -> Result<(), ()> { - (&mut **self).submit_transaction(ex) - } - - fn network_state(&self) -> Result { - (& **self).network_state() - } - - fn timestamp(&mut self) -> Timestamp { - (&mut **self).timestamp() - } - - fn sleep_until(&mut self, deadline: Timestamp) { - (&mut **self).sleep_until(deadline) - } - - fn random_seed(&mut self) -> [u8; 32] { - (&mut **self).random_seed() - } - - fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { - (&mut **self).local_storage_set(kind, key, value) - } - - fn local_storage_compare_and_set( - &mut self, - kind: StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - (&mut **self).local_storage_compare_and_set(kind, key, old_value, new_value) - } - - fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { - (&mut **self).local_storage_get(kind, key) - } - - fn http_request_start(&mut self, method: &str, uri: &str, meta: &[u8]) -> Result { - (&mut **self).http_request_start(method, uri, meta) - } - - fn http_request_add_header(&mut self, request_id: HttpRequestId, name: &str, value: &str) -> Result<(), ()> { - (&mut **self).http_request_add_header(request_id, name, value) - } - - fn http_request_write_body( - &mut self, - request_id: HttpRequestId, - chunk: &[u8], - deadline: Option - ) -> Result<(), HttpError> { - (&mut **self).http_request_write_body(request_id, chunk, deadline) - } - - fn http_response_wait(&mut self, ids: &[HttpRequestId], deadline: Option) -> Vec { - (&mut **self).http_response_wait(ids, deadline) - } - - fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { - (&mut **self).http_response_headers(request_id) - } - - fn http_response_read_body( - &mut self, - request_id: HttpRequestId, - buffer: &mut [u8], - deadline: Option - ) -> Result { - (&mut **self).http_response_read_body(request_id, buffer, deadline) - } -} -/// An `OffchainExternalities` implementation with limited capabilities. -pub struct LimitedExternalities { - capabilities: Capabilities, - externalities: T, -} - -impl LimitedExternalities { - /// Create new externalities limited to given `capabilities`. - pub fn new(capabilities: Capabilities, externalities: T) -> Self { - Self { - capabilities, - externalities, - } - } - - /// Check if given capability is allowed. - /// - /// Panics in case it is not. - fn check(&self, capability: Capability, name: &'static str) { - if !self.capabilities.has(capability) { - panic!("Accessing a forbidden API: {}. No: {:?} capability.", name, capability); - } - } -} - -impl Externalities for LimitedExternalities { - fn is_validator(&self) -> bool { - self.check(Capability::Keystore, "is_validator"); - self.externalities.is_validator() - } - - fn submit_transaction(&mut self, ex: Vec) -> Result<(), ()> { - self.check(Capability::TransactionPool, "submit_transaction"); - self.externalities.submit_transaction(ex) - } - - fn network_state(&self) -> Result { - self.check(Capability::NetworkState, "network_state"); - self.externalities.network_state() - } - - fn timestamp(&mut self) -> Timestamp { - self.check(Capability::Http, "timestamp"); - self.externalities.timestamp() - } - - fn sleep_until(&mut self, deadline: Timestamp) { - self.check(Capability::Http, "sleep_until"); - self.externalities.sleep_until(deadline) - } - - fn random_seed(&mut self) -> [u8; 32] { - self.check(Capability::Randomness, "random_seed"); - self.externalities.random_seed() - } - - fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { - self.check(Capability::OffchainWorkerDbWrite, "local_storage_set"); - self.externalities.local_storage_set(kind, key, value) - } - - fn local_storage_compare_and_set( - &mut self, - kind: StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - self.check(Capability::OffchainWorkerDbWrite, "local_storage_compare_and_set"); - self.externalities.local_storage_compare_and_set(kind, key, old_value, new_value) - } - - fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { - self.check(Capability::OffchainWorkerDbRead, "local_storage_get"); - self.externalities.local_storage_get(kind, key) - } - - fn http_request_start(&mut self, method: &str, uri: &str, meta: &[u8]) -> Result { - self.check(Capability::Http, "http_request_start"); - self.externalities.http_request_start(method, uri, meta) - } - - fn http_request_add_header(&mut self, request_id: HttpRequestId, name: &str, value: &str) -> Result<(), ()> { - self.check(Capability::Http, "http_request_add_header"); - self.externalities.http_request_add_header(request_id, name, value) - } - - fn http_request_write_body( - &mut self, - request_id: HttpRequestId, - chunk: &[u8], - deadline: Option - ) -> Result<(), HttpError> { - self.check(Capability::Http, "http_request_write_body"); - self.externalities.http_request_write_body(request_id, chunk, deadline) - } - - fn http_response_wait(&mut self, ids: &[HttpRequestId], deadline: Option) -> Vec { - self.check(Capability::Http, "http_response_wait"); - self.externalities.http_response_wait(ids, deadline) - } - - fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { - self.check(Capability::Http, "http_response_headers"); - self.externalities.http_response_headers(request_id) - } - - fn http_response_read_body( - &mut self, - request_id: HttpRequestId, - buffer: &mut [u8], - deadline: Option - ) -> Result { - self.check(Capability::Http, "http_response_read_body"); - self.externalities.http_response_read_body(request_id, buffer, deadline) - } -} - -#[cfg(feature = "std")] -externalities::decl_extension! { - /// The offchain extension that will be registered at the Substrate externalities. - pub struct OffchainExt(Box); -} - -#[cfg(feature = "std")] -impl OffchainExt { - /// Create a new instance of `Self`. - pub fn new(offchain: O) -> Self { - Self(Box::new(offchain)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn timestamp_ops() { - let t = Timestamp(5); - assert_eq!(t.add(Duration::from_millis(10)), Timestamp(15)); - assert_eq!(t.sub(Duration::from_millis(10)), Timestamp(0)); - assert_eq!(t.diff(&Timestamp(3)), Duration(2)); - } - - #[test] - fn capabilities() { - let none = Capabilities::none(); - let all = Capabilities::all(); - let some = Capabilities::from(&[Capability::Keystore, Capability::Randomness][..]); - - assert!(!none.has(Capability::Keystore)); - assert!(all.has(Capability::Keystore)); - assert!(some.has(Capability::Keystore)); - assert!(!none.has(Capability::TransactionPool)); - assert!(all.has(Capability::TransactionPool)); - assert!(!some.has(Capability::TransactionPool)); - } -} diff --git a/core/primitives/src/sandbox.rs b/core/primitives/src/sandbox.rs deleted file mode 100644 index dd91ad6a1f5c0..0000000000000 --- a/core/primitives/src/sandbox.rs +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Definition of a sandbox environment. - -use codec::{Encode, Decode}; -use rstd::vec::Vec; - -/// Error error that can be returned from host function. -#[derive(Encode, Decode)] -#[derive(crate::RuntimeDebug)] -pub struct HostError; - -/// Representation of a typed wasm value. -#[derive(Clone, Copy, PartialEq, Encode, Decode)] -#[derive(crate::RuntimeDebug)] -pub enum TypedValue { - /// Value of 32-bit signed or unsigned integer. - #[codec(index = "1")] - I32(i32), - - /// Value of 64-bit signed or unsigned integer. - #[codec(index = "2")] - I64(i64), - - /// Value of 32-bit IEEE 754-2008 floating point number represented as a bit pattern. - #[codec(index = "3")] - F32(i32), - - /// Value of 64-bit IEEE 754-2008 floating point number represented as a bit pattern. - #[codec(index = "4")] - F64(i64), -} - -impl TypedValue { - /// Returns `Some` if this value of type `I32`. - pub fn as_i32(&self) -> Option { - match *self { - TypedValue::I32(v) => Some(v), - _ => None, - } - } -} - -#[cfg(feature = "std")] -impl From<::wasmi::RuntimeValue> for TypedValue { - fn from(val: ::wasmi::RuntimeValue) -> TypedValue { - use ::wasmi::RuntimeValue; - match val { - RuntimeValue::I32(v) => TypedValue::I32(v), - RuntimeValue::I64(v) => TypedValue::I64(v), - RuntimeValue::F32(v) => TypedValue::F32(v.to_bits() as i32), - RuntimeValue::F64(v) => TypedValue::F64(v.to_bits() as i64), - } - } -} - -#[cfg(feature = "std")] -impl From for ::wasmi::RuntimeValue { - fn from(val: TypedValue) -> ::wasmi::RuntimeValue { - use ::wasmi::RuntimeValue; - use ::wasmi::nan_preserving_float::{F32, F64}; - match val { - TypedValue::I32(v) => RuntimeValue::I32(v), - TypedValue::I64(v) => RuntimeValue::I64(v), - TypedValue::F32(v_bits) => RuntimeValue::F32(F32::from_bits(v_bits as u32)), - TypedValue::F64(v_bits) => RuntimeValue::F64(F64::from_bits(v_bits as u64)), - } - } -} - -/// Typed value that can be returned from a function. -/// -/// Basically a `TypedValue` plus `Unit`, for functions which return nothing. -#[derive(Clone, Copy, PartialEq, Encode, Decode)] -#[derive(crate::RuntimeDebug)] -pub enum ReturnValue { - /// For returning nothing. - Unit, - /// For returning some concrete value. - Value(TypedValue), -} - -impl From for ReturnValue { - fn from(v: TypedValue) -> ReturnValue { - ReturnValue::Value(v) - } -} - -impl ReturnValue { - /// Maximum number of bytes `ReturnValue` might occupy when serialized with - /// `Codec`. - /// - /// Breakdown: - /// 1 byte for encoding unit/value variant - /// 1 byte for encoding value type - /// 8 bytes for encoding the biggest value types available in wasm: f64, i64. - pub const ENCODED_MAX_SIZE: usize = 10; -} - -#[test] -fn return_value_encoded_max_size() { - let encoded = ReturnValue::Value(TypedValue::I64(-1)).encode(); - assert_eq!(encoded.len(), ReturnValue::ENCODED_MAX_SIZE); -} - -/// Describes an entity to define or import into the environment. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[derive(crate::RuntimeDebug)] -pub enum ExternEntity { - /// Function that is specified by an index in a default table of - /// a module that creates the sandbox. - #[codec(index = "1")] - Function(u32), - - /// Linear memory that is specified by some identifier returned by sandbox - /// module upon creation new sandboxed memory. - #[codec(index = "2")] - Memory(u32), -} - -/// An entry in a environment definition table. -/// -/// Each entry has a two-level name and description of an entity -/// being defined. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[derive(crate::RuntimeDebug)] -pub struct Entry { - /// Module name of which corresponding entity being defined. - pub module_name: Vec, - /// Field name in which corresponding entity being defined. - pub field_name: Vec, - /// External entity being defined. - pub entity: ExternEntity, -} - -/// Definition of runtime that could be used by sandboxed code. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[derive(crate::RuntimeDebug)] -pub struct EnvironmentDefinition { - /// Vector of all entries in the environment definition. - pub entries: Vec, -} - -/// Constant for specifying no limit when creating a sandboxed -/// memory instance. For FFI purposes. -pub const MEM_UNLIMITED: u32 = -1i32 as u32; - -/// No error happened. -/// -/// For FFI purposes. -pub const ERR_OK: u32 = 0; - -/// Validation or instantiation error occurred when creating new -/// sandboxed module instance. -/// -/// For FFI purposes. -pub const ERR_MODULE: u32 = -1i32 as u32; - -/// Out-of-bounds access attempted with memory or table. -/// -/// For FFI purposes. -pub const ERR_OUT_OF_BOUNDS: u32 = -2i32 as u32; - -/// Execution error occurred (typically trap). -/// -/// For FFI purposes. -pub const ERR_EXECUTION: u32 = -3i32 as u32; - -#[cfg(test)] -mod tests { - use super::*; - use std::fmt; - use codec::Codec; - - fn roundtrip(s: S) { - let encoded = s.encode(); - assert_eq!(S::decode(&mut &encoded[..]).unwrap(), s); - } - - #[test] - fn env_def_roundtrip() { - roundtrip(EnvironmentDefinition { - entries: vec![], - }); - - roundtrip(EnvironmentDefinition { - entries: vec![ - Entry { - module_name: b"kernel"[..].into(), - field_name: b"memory"[..].into(), - entity: ExternEntity::Memory(1337), - }, - ], - }); - - roundtrip(EnvironmentDefinition { - entries: vec![ - Entry { - module_name: b"env"[..].into(), - field_name: b"abort"[..].into(), - entity: ExternEntity::Function(228), - }, - ], - }); - } -} diff --git a/core/primitives/src/sr25519.rs b/core/primitives/src/sr25519.rs deleted file mode 100644 index bb319b8221828..0000000000000 --- a/core/primitives/src/sr25519.rs +++ /dev/null @@ -1,731 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -// 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 schnorrkel::{signing_context, ExpansionMode, 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, Ss58Codec -}; -use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}}; -use crate::hash::{H256, H512}; -use codec::{Encode, Decode}; - -#[cfg(feature = "std")] -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(feature = "std")] -use schnorrkel::keys::{MINI_SECRET_KEY_LENGTH, SECRET_KEY_LENGTH}; - -// signing context -#[cfg(feature = "std")] -const SIGNING_CTX: &[u8] = b"substrate"; - -/// An Schnorrkel/Ristretto x25519 ("sr25519") public key. -#[cfg_attr(feature = "std", derive(Hash))] -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] -pub struct Public(pub [u8; 32]); - -/// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. -#[cfg(feature = "std")] -pub struct Pair(Keypair); - -#[cfg(feature = "std")] -impl Clone for Pair { - fn clone(&self) -> Self { - Pair(schnorrkel::Keypair { - public: self.0.public, - secret: schnorrkel::SecretKey::from_bytes(&self.0.secret.to_bytes()[..]) - .expect("key is always the correct size; qed") - }) - } -} - -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 rstd::convert::TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 32 { - let mut inner = [0u8; 32]; - inner.copy_from_slice(data); - Ok(Public(inner)) - } else { - Err(()) - } - } -} - -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(not(feature = "std"))] -use core as std; - -impl rstd::fmt::Debug for Public { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "std")] -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))) - } -} - -/// 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 rstd::convert::TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 64 { - let mut inner = [0u8; 64]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} - -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()) - } -} - -impl rstd::fmt::Debug for Signature { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -#[cfg(feature = "std")] -impl std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - std::hash::Hash::hash(&self.0[..], state); - } -} - -/// 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, or if you - /// immediately verify the signature. All functions that verify signatures - /// will fail if the `Signature` is not actually a valid signature. - 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()) - } -} - -impl Derive for Public { - /// Derive a child key from a series of given junctions. - /// - /// `None` if there are any hard junctions in there. - #[cfg(feature = "std")] - 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 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 slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 32] { - self.as_ref() - } -} - -impl TraitPublic for Public { - /// 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! - fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Public(r) - } -} - -#[cfg(feature = "std")] -impl From for Pair { - fn from(sec: MiniSecretKey) -> Pair { - Pair(sec.expand_to_keypair(ExpansionMode::Ed25519)) - } -} - -#[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]) -> MiniSecretKey { - secret.hard_derive_mini_secret_key(Some(ChainCode(cc.clone())), b"").0 -} - -/// The raw secret seed, which can be used to recreate the `Pair`. -#[cfg(feature = "std")] -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; - - /// 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 { - Self::from_seed_slice(&seed[..]) - .expect("32 bytes can always build a key; qed") - } - - /// 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 { - match seed.len() { - MINI_SECRET_KEY_LENGTH => { - Ok(Pair( - MiniSecretKey::from_bytes(seed) - .map_err(|_| SecretStringError::InvalidSeed)? - .expand_to_keypair(ExpansionMode::Ed25519) - )) - } - SECRET_KEY_LENGTH => { - Ok(Pair( - SecretKey::from_bytes(seed) - .map_err(|_| SecretStringError::InvalidSeed)? - .to_keypair() - )) - } - _ => Err(SecretStringError::InvalidSeedLength) - } - } - - fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { - let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); - let phrase = mnemonic.phrase(); - let (pair, seed) = Self::from_phrase(phrase, password) - .expect("All phrases generated by Mnemonic are valid; qed"); - ( - pair, - phrase.to_owned(), - seed, - ) - } - - fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { - Mnemonic::from_phrase(phrase, Language::English) - .map_err(|_| SecretStringError::InvalidPhrase) - .map(|m| Self::from_entropy(m.entropy(), password)) - } - - fn derive>(&self, - path: Iter, - seed: Option, - ) -> Result<(Pair, Option), Self::DeriveError> { - let seed = if let Some(s) = seed { - if let Ok(msk) = MiniSecretKey::from_bytes(&s) { - if msk.expand(ExpansionMode::Ed25519) == self.0.secret { - Some(msk) - } else { None } - } else { None } - } else { None }; - let init = self.0.secret.clone(); - let (result, seed) = path.fold((init, seed), |(acc, acc_seed), j| match (j, acc_seed) { - (DeriveJunction::Soft(cc), _) => - (acc.derived_key_simple(ChainCode(cc), &[]).0, None), - (DeriveJunction::Hard(cc), maybe_seed) => { - let seed = derive_hard_junction(&acc, &cc); - (seed.expand(ExpansionMode::Ed25519), maybe_seed.map(|_| seed)) - } - }); - Ok((Self(result.into()), seed.map(|s| MiniSecretKey::to_bytes(&s)))) - } - - 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>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { - Self::verify_weak(&sig.0[..], message, pubkey) - } - - /// 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 { - // Match both schnorrkel 0.1.1 and 0.8.0+ signatures, supporting both wallets - // that have not been upgraded and those that have. To swap to 0.8.0 only, - // create `schnorrkel::Signature` and pass that into `verify_simple` - match PublicKey::from_bytes(pubkey.as_ref()) { - Ok(pk) => pk.verify_simple_preaudit_deprecated( - SIGNING_CTX, message.as_ref(), &sig, - ).is_ok(), - Err(_) => false, - } - } - - /// Return a vec filled with raw data. - fn to_raw_vec(&self) -> Vec { - self.0.secret.to_bytes().to_vec() - } -} - -#[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, Seed) { - 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(ExpansionMode::Ed25519); - (Pair(kp), mini_key.to_bytes()) - } -} - -impl CryptoType for Public { - #[cfg(feature="std")] - type Pair = Pair; -} - -impl CryptoType for Signature { - #[cfg(feature="std")] - type Pair = Pair; -} - -#[cfg(feature = "std")] -impl CryptoType for Pair { - type Pair = Pair; -} - -#[cfg(test)] -mod compatibility_test { - use super::*; - use crate::crypto::{DEV_PHRASE}; - use hex_literal::hex; - - // NOTE: tests to ensure addresses that are created with the `0.1.x` version (pre-audit) are - // still functional. - - #[test] - fn derive_soft_known_pair_should_work() { - let pair = Pair::from_string(&format!("{}/Alice", DEV_PHRASE), None).unwrap(); - // known address of DEV_PHRASE with 1.1 - let known = hex!("d6c71059dbbe9ad2b0ed3f289738b800836eb425544ce694825285b958ca755e"); - assert_eq!(pair.public().to_raw_vec(), known); - } - - #[test] - fn derive_hard_known_pair_should_work() { - let pair = Pair::from_string(&format!("{}//Alice", DEV_PHRASE), None).unwrap(); - // known address of DEV_PHRASE with 1.1 - let known = hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); - assert_eq!(pair.public().to_raw_vec(), known); - } - - #[test] - fn verify_known_message_should_work() { - let public = Public::from_raw(hex!("b4bfa1f7a5166695eb75299fd1c4c03ea212871c342f2c5dfea0902b2c246918")); - // signature generated by the 1.1 version with the same ^^ public key. - let signature = Signature::from_raw(hex!( - "5a9755f069939f45d96aaf125cf5ce7ba1db998686f87f2fb3cbdea922078741a73891ba265f70c31436e18a9acd14d189d73c12317ab6c313285cd938453202" - )); - let message = b"Verifying that I am the owner of 5G9hQLdsKQswNPgB499DeA5PkFBbgkLPJWkkS6FAM6xGQ8xD. Hash: 221455a3\n"; - assert!(Pair::verify(&signature, &message[..], &public)); - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::crypto::{Ss58Codec, DEV_PHRASE, DEV_ADDRESS}; - use hex_literal::hex; - - #[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::from_seed(&hex!( - "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" - )); - let derive_1 = pair.derive(Some(DeriveJunction::soft(1)).into_iter(), None).unwrap().0; - let derive_1b = pair.derive(Some(DeriveJunction::soft(1)).into_iter(), None).unwrap().0; - let derive_2 = pair.derive(Some(DeriveJunction::soft(2)).into_iter(), None).unwrap().0; - assert_eq!(derive_1.public(), derive_1b.public()); - assert_ne!(derive_1.public(), derive_2.public()); - } - - #[test] - fn derive_hard_should_work() { - let pair = Pair::from_seed(&hex!( - "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" - )); - let derive_1 = pair.derive(Some(DeriveJunction::hard(1)).into_iter(), None).unwrap().0; - let derive_1b = pair.derive(Some(DeriveJunction::hard(1)).into_iter(), None).unwrap().0; - let derive_2 = pair.derive(Some(DeriveJunction::hard(2)).into_iter(), None).unwrap().0; - assert_eq!(derive_1.public(), derive_1b.public()); - assert_ne!(derive_1.public(), derive_2.public()); - } - - #[test] - fn derive_soft_public_should_work() { - let pair = Pair::from_seed(&hex!( - "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" - )); - let path = Some(DeriveJunction::soft(1)); - let pair_1 = pair.derive(path.clone().into_iter(), None).unwrap().0; - let public_1 = pair.public().derive(path.into_iter()).unwrap(); - assert_eq!(pair_1.public(), public_1); - } - - #[test] - fn derive_hard_public_should_fail() { - let 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::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 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/testing.rs b/core/primitives/src/testing.rs deleted file mode 100644 index e5d301008e3d4..0000000000000 --- a/core/primitives/src/testing.rs +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Types that should only be used for testing! - -#[cfg(feature = "std")] -use crate::{ed25519, sr25519, crypto::{Public, Pair}}; -use crate::crypto::KeyTypeId; - -/// Key type for generic Ed25519 key. -pub const ED25519: KeyTypeId = KeyTypeId(*b"ed25"); -/// Key type for generic Sr 25519 key. -pub const SR25519: KeyTypeId = KeyTypeId(*b"sr25"); - -/// A keystore implementation usable in tests. -#[cfg(feature = "std")] -#[derive(Default)] -pub struct KeyStore { - /// `KeyTypeId` maps to public keys and public keys map to private keys. - keys: std::collections::HashMap, String>>, -} - -#[cfg(feature = "std")] -impl KeyStore { - /// Creates a new instance of `Self`. - pub fn new() -> crate::traits::BareCryptoStorePtr { - std::sync::Arc::new(parking_lot::RwLock::new(Self::default())) - } -} - -#[cfg(feature = "std")] -impl crate::traits::BareCryptoStore for KeyStore { - fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec { - self.keys.get(&id) - .map(|keys| - keys.values() - .map(|s| sr25519::Pair::from_string(s, None).expect("`sr25519` seed slice is valid")) - .map(|p| p.public()) - .collect() - ) - .unwrap_or_default() - } - - fn sr25519_generate_new( - &mut self, - id: KeyTypeId, - seed: Option<&str>, - ) -> Result { - match seed { - Some(seed) => { - let pair = sr25519::Pair::from_string(seed, None).expect("Generates an `sr25519` pair."); - self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into()); - Ok(pair.public()) - }, - None => { - let (pair, phrase, _) = sr25519::Pair::generate_with_phrase(None); - self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), phrase); - Ok(pair.public()) - } - } - } - - fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option { - self.keys.get(&id) - .and_then(|inner| - inner.get(pub_key.as_slice()) - .map(|s| sr25519::Pair::from_string(s, None).expect("`sr25519` seed slice is valid")) - ) - } - - fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec { - self.keys.get(&id) - .map(|keys| - keys.values() - .map(|s| ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid")) - .map(|p| p.public()) - .collect() - ) - .unwrap_or_default() - } - - fn ed25519_generate_new( - &mut self, - id: KeyTypeId, - seed: Option<&str>, - ) -> Result { - match seed { - Some(seed) => { - let pair = ed25519::Pair::from_string(seed, None).expect("Generates an `ed25519` pair."); - self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into()); - Ok(pair.public()) - }, - None => { - let (pair, phrase, _) = ed25519::Pair::generate_with_phrase(None); - self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), phrase); - Ok(pair.public()) - } - } - } - - fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option { - self.keys.get(&id) - .and_then(|inner| - inner.get(pub_key.as_slice()) - .map(|s| ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid")) - ) - } - - fn insert_unknown(&mut self, id: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> { - self.keys.entry(id).or_default().insert(public.to_owned(), suri.to_string()); - Ok(()) - } - - fn password(&self) -> Option<&str> { - None - } -} - -/// Macro for exporting functions from wasm in with the expected signature for using it with the -/// wasm executor. This is useful for tests where you need to call a function in wasm. -/// -/// The input parameters are expected to be SCALE encoded and will be automatically decoded for you. -/// The output value is also SCALE encoded when returned back to the host. -/// -/// The functions are feature-gated with `#[cfg(not(feature = "std"))]`, so they are only available -/// from within wasm. -/// -/// # Example -/// -/// ``` -/// # use substrate_primitives::wasm_export_functions; -/// -/// wasm_export_functions! { -/// fn test_in_wasm(value: bool, another_value: Vec) -> bool { -/// value && another_value.is_empty() -/// } -/// -/// fn without_return_value() { -/// // do something -/// } -/// } -/// ``` -#[macro_export] -macro_rules! wasm_export_functions { - ( - $( - fn $name:ident ( - $( $arg_name:ident: $arg_ty:ty ),* $(,)? - ) $( -> $ret_ty:ty )? { $( $fn_impl:tt )* } - )* - ) => { - $( - $crate::wasm_export_functions! { - @IMPL - fn $name ( - $( $arg_name: $arg_ty ),* - ) $( -> $ret_ty )? { $( $fn_impl )* } - } - )* - }; - (@IMPL - fn $name:ident ( - $( $arg_name:ident: $arg_ty:ty ),* - ) { $( $fn_impl:tt )* } - ) => { - #[no_mangle] - #[allow(unreachable_code)] - #[cfg(not(feature = "std"))] - pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { - let input: &[u8] = if input_len == 0 { - &[0u8; 0] - } else { - unsafe { - $crate::rstd::slice::from_raw_parts(input_data, input_len) - } - }; - - { - let ($( $arg_name ),*) : ($( $arg_ty ),*) = $crate::Decode::decode( - &mut &input[..], - ).expect("Input data is correctly encoded"); - - $( $fn_impl )* - } - - $crate::to_substrate_wasm_fn_return_value(&()) - } - }; - (@IMPL - fn $name:ident ( - $( $arg_name:ident: $arg_ty:ty ),* - ) $( -> $ret_ty:ty )? { $( $fn_impl:tt )* } - ) => { - #[no_mangle] - #[allow(unreachable_code)] - #[cfg(not(feature = "std"))] - pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { - let input: &[u8] = if input_len == 0 { - &[0u8; 0] - } else { - unsafe { - $crate::rstd::slice::from_raw_parts(input_data, input_len) - } - }; - - let output $( : $ret_ty )? = { - let ($( $arg_name ),*) : ($( $arg_ty ),*) = $crate::Decode::decode( - &mut &input[..], - ).expect("Input data is correctly encoded"); - - $( $fn_impl )* - }; - - $crate::to_substrate_wasm_fn_return_value(&output) - } - }; -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::sr25519; - use crate::testing::{ED25519, SR25519}; - - #[test] - fn store_key_and_extract() { - let store = KeyStore::new(); - - let public = store.write() - .ed25519_generate_new(ED25519, None) - .expect("Genrates key"); - - let store_key_pair = store.read() - .ed25519_key_pair(ED25519, &public) - .expect("Key should exists in store"); - - assert_eq!(public, store_key_pair.public()); - } - - #[test] - fn store_unknown_and_extract_it() { - let store = KeyStore::new(); - - let secret_uri = "//Alice"; - let key_pair = sr25519::Pair::from_string(secret_uri, None).expect("Generates key pair"); - - store.write().insert_unknown( - SR25519, - secret_uri, - key_pair.public().as_ref(), - ).expect("Inserts unknown key"); - - let store_key_pair = store.read().sr25519_key_pair( - SR25519, - &key_pair.public(), - ).expect("Gets key pair from keystore"); - - assert_eq!(key_pair.public(), store_key_pair.public()); - } -} diff --git a/core/primitives/src/tests.rs b/core/primitives/src/tests.rs deleted file mode 100644 index 2dbaed2b0faab..0000000000000 --- a/core/primitives/src/tests.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests. diff --git a/core/primitives/src/traits.rs b/core/primitives/src/traits.rs deleted file mode 100644 index 1ef665032eed4..0000000000000 --- a/core/primitives/src/traits.rs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Shareable Substrate traits. - -use crate::{crypto::KeyTypeId, ed25519, sr25519}; - -use std::{fmt::{Debug, Display}, panic::UnwindSafe}; - -pub use externalities::{Externalities, ExternalitiesExt}; - -/// Something that generates, stores and provides access to keys. -pub trait BareCryptoStore: Send + Sync { - /// Returns all sr25519 public keys for the given key type. - fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec; - /// Generate a new sr25519 key pair for the given key type and an optional seed. - /// - /// If the given seed is `Some(_)`, the key pair will only be stored in memory. - /// - /// Returns the public key of the generated key pair. - fn sr25519_generate_new( - &mut self, - id: KeyTypeId, - seed: Option<&str>, - ) -> Result; - /// Returns the sr25519 key pair for the given key type and public key combination. - fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option; - - /// Returns all ed25519 public keys for the given key type. - fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec; - /// Generate a new ed25519 key pair for the given key type and an optional seed. - /// - /// If the given seed is `Some(_)`, the key pair will only be stored in memory. - /// - /// Returns the public key of the generated key pair. - fn ed25519_generate_new( - &mut self, - id: KeyTypeId, - seed: Option<&str>, - ) -> Result; - - /// Returns the ed25519 key pair for the given key type and public key combination. - fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option; - - /// Insert a new key. This doesn't require any known of the crypto; but a public key must be - /// manually provided. - /// - /// Places it into the file system store. - /// - /// `Err` if there's some sort of weird filesystem error, but should generally be `Ok`. - fn insert_unknown(&mut self, _key_type: KeyTypeId, _suri: &str, _public: &[u8]) -> Result<(), ()>; - - /// Get the password for this store. - fn password(&self) -> Option<&str>; -} - -/// A pointer to the key store. -pub type BareCryptoStorePtr = std::sync::Arc>; - -externalities::decl_extension! { - /// The keystore extension to register/retrieve from the externalities. - pub struct KeystoreExt(BareCryptoStorePtr); -} - -/// Code execution engine. -pub trait CodeExecutor: Sized + Send + Sync { - /// Externalities error type. - type Error: Display + Debug + Send + 'static; - - /// Call a given method in the runtime. Returns a tuple of the result (either the output data - /// or an execution error) together with a `bool`, which is true if native execution was used. - fn call< - E: Externalities, - R: codec::Codec + PartialEq, - NC: FnOnce() -> Result + UnwindSafe, - >( - &self, - ext: &mut E, - method: &str, - data: &[u8], - use_native: bool, - native_call: Option, - ) -> (Result, Self::Error>, bool); -} diff --git a/core/primitives/storage/Cargo.toml b/core/primitives/storage/Cargo.toml deleted file mode 100644 index 7bb2b95623c89..0000000000000 --- a/core/primitives/storage/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "substrate-primitives-storage" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -description = "Storage related primitives" - -[dependencies] -rstd = { package = "sr-std", path = "../../sr-std", default-features = false } -serde = { version = "1.0.101", optional = true, features = ["derive"] } -impl-serde = { version = "0.2.1", optional = true } -substrate-debug-derive = { version = "2.0.0", path = "../debug-derive" } - -[features] -default = [ "std" ] -std = [ "rstd/std", "serde", "impl-serde" ] diff --git a/core/primitives/storage/src/lib.rs b/core/primitives/storage/src/lib.rs deleted file mode 100644 index dcdc223994e26..0000000000000 --- a/core/primitives/storage/src/lib.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Primitive types for storage related stuff. - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -use substrate_debug_derive::RuntimeDebug; - -use rstd::{vec::Vec, borrow::Cow}; - -/// Storage key. -#[derive(PartialEq, Eq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))] -pub struct StorageKey( - #[cfg_attr(feature = "std", serde(with="impl_serde::serialize"))] - pub Vec, -); - -/// Storage data associated to a [`StorageKey`]. -#[derive(PartialEq, Eq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))] -pub struct StorageData( - #[cfg_attr(feature = "std", serde(with="impl_serde::serialize"))] - pub Vec, -); - -/// Storage change set -#[derive(RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, PartialEq, Eq))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -pub struct StorageChangeSet { - /// Block hash - pub block: Hash, - /// A list of changes - pub changes: Vec<(StorageKey, Option)>, -} - -/// List of all well known keys and prefixes in storage. -pub mod well_known_keys { - /// Wasm code of the runtime. - /// - /// Stored as a raw byte vector. Required by substrate. - pub const CODE: &'static [u8] = b":code"; - - /// Number of wasm linear memory pages required for execution of the runtime. - /// - /// The type of this value is encoded `u64`. - pub const HEAP_PAGES: &'static [u8] = b":heappages"; - - /// Current extrinsic index (u32) is stored under this key. - pub const EXTRINSIC_INDEX: &'static [u8] = b":extrinsic_index"; - - /// Changes trie configuration is stored under this key. - pub const CHANGES_TRIE_CONFIG: &'static [u8] = b":changes_trie"; - - /// Prefix of child storage keys. - pub const CHILD_STORAGE_KEY_PREFIX: &'static [u8] = b":child_storage:"; - - /// Whether a key is a child storage key. - /// - /// This is convenience function which basically checks if the given `key` starts - /// with `CHILD_STORAGE_KEY_PREFIX` and doesn't do anything apart from that. - pub fn is_child_storage_key(key: &[u8]) -> bool { - // Other code might depend on this, so be careful changing this. - key.starts_with(CHILD_STORAGE_KEY_PREFIX) - } - - /// Determine whether a child trie key is valid. - /// - /// For now, the only valid child trie keys are those starting with `:child_storage:default:`. - /// - /// `child_trie_root` and `child_delta_trie_root` can panic if invalid value is provided to them. - pub fn is_child_trie_key_valid(storage_key: &[u8]) -> bool { - let has_right_prefix = storage_key.starts_with(b":child_storage:default:"); - if has_right_prefix { - // This is an attempt to catch a change of `is_child_storage_key`, which - // just checks if the key has prefix `:child_storage:` at the moment of writing. - debug_assert!( - is_child_storage_key(&storage_key), - "`is_child_trie_key_valid` is a subset of `is_child_storage_key`", - ); - } - has_right_prefix - } -} - -/// A wrapper around a child storage key. -/// -/// This wrapper ensures that the child storage key is correct and properly used. It is -/// impossible to create an instance of this struct without providing a correct `storage_key`. -pub struct ChildStorageKey<'a> { - storage_key: Cow<'a, [u8]>, -} - -impl<'a> ChildStorageKey<'a> { - /// Create new instance of `Self`. - fn new(storage_key: Cow<'a, [u8]>) -> Option { - if well_known_keys::is_child_trie_key_valid(&storage_key) { - Some(ChildStorageKey { storage_key }) - } else { - None - } - } - - /// Create a new `ChildStorageKey` from a vector. - /// - /// `storage_key` need to start with `:child_storage:default:` - /// See `is_child_trie_key_valid` for more details. - pub fn from_vec(key: Vec) -> Option { - Self::new(Cow::Owned(key)) - } - - /// Create a new `ChildStorageKey` from a slice. - /// - /// `storage_key` need to start with `:child_storage:default:` - /// See `is_child_trie_key_valid` for more details. - pub fn from_slice(key: &'a [u8]) -> Option { - Self::new(Cow::Borrowed(key)) - } - - /// Get access to the byte representation of the storage key. - /// - /// This key is guaranteed to be correct. - pub fn as_ref(&self) -> &[u8] { - &*self.storage_key - } - - /// Destruct this instance into an owned vector that represents the storage key. - /// - /// This key is guaranteed to be correct. - pub fn into_owned(self) -> Vec { - self.storage_key.into_owned() - } -} diff --git a/core/rpc-servers/Cargo.toml b/core/rpc-servers/Cargo.toml deleted file mode 100644 index 80e16bc5ae5be..0000000000000 --- a/core/rpc-servers/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "substrate-rpc-servers" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -jsonrpc-core = "13.2.0" -pubsub = { package = "jsonrpc-pubsub", version = "13.2.0" } -log = "0.4.8" -serde = "1.0.101" -serde_json = "1.0.41" -sr-primitives = { path = "../sr-primitives" } - -[target.'cfg(not(target_os = "unknown"))'.dependencies] -http = { package = "jsonrpc-http-server", version = "13.2.0" } -ws = { package = "jsonrpc-ws-server", version = "13.2.0" } diff --git a/core/rpc-servers/src/lib.rs b/core/rpc-servers/src/lib.rs deleted file mode 100644 index 8d39386f93c4a..0000000000000 --- a/core/rpc-servers/src/lib.rs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate RPC servers. - -#![warn(missing_docs)] - -use std::io; -use jsonrpc_core::IoHandlerExtension; -use log::error; -use pubsub::PubSubMetadata; - -/// Maximal payload accepted by RPC servers. -const MAX_PAYLOAD: usize = 15 * 1024 * 1024; - -/// Default maximum number of connections for WS RPC servers. -const WS_MAX_CONNECTIONS: usize = 100; - -/// The RPC IoHandler containing all requested APIs. -pub type RpcHandler = pubsub::PubSubHandler; - -pub use self::inner::*; - -/// Construct rpc `IoHandler` -pub fn rpc_handler( - extension: impl IoHandlerExtension -) -> RpcHandler { - let mut io = pubsub::PubSubHandler::default(); - extension.augment(&mut io); - - // add an endpoint to list all available methods. - let mut methods = io.iter().map(|x| x.0.clone()).collect::>(); - io.add_method("rpc_methods", { - methods.sort(); - let methods = serde_json::to_value(&methods) - .expect("Serialization of Vec is infallible; qed"); - - move |_| Ok(serde_json::json!({ - "version": 1, - "methods": methods.clone(), - })) - }); - io -} - -#[cfg(not(target_os = "unknown"))] -mod inner { - use super::*; - - /// Type alias for http server - pub type HttpServer = http::Server; - /// Type alias for ws server - pub type WsServer = ws::Server; - - /// Start HTTP server listening on given address. - /// - /// **Note**: Only available if `not(target_os = "unknown")`. - pub fn start_http( - addr: &std::net::SocketAddr, - cors: Option<&Vec>, - io: RpcHandler, - ) -> io::Result { - http::ServerBuilder::new(io) - .threads(4) - .health_api(("/health", "system_health")) - .allowed_hosts(hosts_filtering(cors.is_some())) - .rest_api(if cors.is_some() { - http::RestApi::Secure - } else { - http::RestApi::Unsecure - }) - .cors(map_cors::(cors)) - .max_request_body_size(MAX_PAYLOAD) - .start_http(addr) - } - - /// Start WS server listening on given address. - /// - /// **Note**: Only available if `not(target_os = "unknown")`. - pub fn start_ws>> ( - addr: &std::net::SocketAddr, - max_connections: Option, - cors: Option<&Vec>, - io: RpcHandler, - ) -> io::Result { - ws::ServerBuilder::with_meta_extractor(io, |context: &ws::RequestContext| context.sender().into()) - .max_payload(MAX_PAYLOAD) - .max_connections(max_connections.unwrap_or(WS_MAX_CONNECTIONS)) - .allowed_origins(map_cors(cors)) - .allowed_hosts(hosts_filtering(cors.is_some())) - .start(addr) - .map_err(|err| match err { - ws::Error::Io(io) => io, - ws::Error::ConnectionClosed => io::ErrorKind::BrokenPipe.into(), - e => { - error!("{}", e); - io::ErrorKind::Other.into() - } - }) - } - - fn map_cors From<&'a str>>( - cors: Option<&Vec> - ) -> http::DomainsValidation { - cors.map(|x| x.iter().map(AsRef::as_ref).map(Into::into).collect::>()).into() - } - - fn hosts_filtering(enable: bool) -> http::DomainsValidation { - if enable { - // NOTE The listening address is whitelisted by default. - // Setting an empty vector here enables the validation - // and allows only the listening address. - http::DomainsValidation::AllowOnly(vec![]) - } else { - http::DomainsValidation::Disabled - } - } -} - -#[cfg(target_os = "unknown")] -mod inner { -} diff --git a/core/rpc/Cargo.toml b/core/rpc/Cargo.toml deleted file mode 100644 index 85998feb1b887..0000000000000 --- a/core/rpc/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "substrate-rpc" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -api = { package = "substrate-rpc-api", path = "./api" } -client = { package = "substrate-client", path = "../client" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } -jsonrpc-pubsub = "13.1.0" -log = "0.4.8" -primitives = { package = "substrate-primitives", path = "../primitives" } -rpc = { package = "jsonrpc-core", version = "13.0.0" } -runtime_version = { package = "sr-version", path = "../sr-version" } -serde_json = "1.0.41" -session = { package = "substrate-session", path = "../session" } -sr-primitives = { path = "../sr-primitives" } -rpc-primitives = { package = "substrate-rpc-primitives", path = "primitives" } -state_machine = { package = "substrate-state-machine", path = "../state-machine" } -substrate-executor = { path = "../executor" } -substrate-keystore = { path = "../keystore" } -transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" } -hash-db = { version = "0.15.2", default-features = false } -parking_lot = { version = "0.9.0" } - -[dev-dependencies] -assert_matches = "1.3.0" -futures = "0.1.29" -network = { package = "substrate-network", path = "../network" } -rustc-hex = "2.0.1" -sr-io = { path = "../sr-io" } -test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client" } -tokio = "0.1.22" diff --git a/core/rpc/api/Cargo.toml b/core/rpc/api/Cargo.toml deleted file mode 100644 index bccafc2a85dd7..0000000000000 --- a/core/rpc/api/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "substrate-rpc-api" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0" } -derive_more = "0.15.0" -futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } -jsonrpc-core = "13.2.0" -jsonrpc-core-client = "13.2.0" -jsonrpc-derive = "13.2.0" -jsonrpc-pubsub = "13.2.0" -log = "0.4.8" -parking_lot = "0.9.0" -primitives = { package = "substrate-primitives", path = "../../primitives" } -runtime_version = { package = "sr-version", path = "../../sr-version" } -serde = { version = "1.0.101", features = ["derive"] } -serde_json = "1.0.41" -txpool = { package = "substrate-transaction-graph", path = "../../transaction-pool/graph" } -rpc-primitives = { package = "substrate-rpc-primitives", path = "../../rpc/primitives" } diff --git a/core/rpc/api/src/author/error.rs b/core/rpc/api/src/author/error.rs deleted file mode 100644 index 8e4f8877682b3..0000000000000 --- a/core/rpc/api/src/author/error.rs +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Authoring RPC module errors. - -use crate::errors; -use jsonrpc_core as rpc; - -/// Author RPC Result type. -pub type Result = std::result::Result; - -/// Author RPC future Result type. -pub type FutureResult = Box + Send>; - -/// Author RPC errors. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Client error. - #[display(fmt="Client error: {}", _0)] - Client(Box), - /// Transaction pool error, - #[display(fmt="Transaction pool error: {}", _0)] - Pool(txpool::error::Error), - /// Verification error - #[display(fmt="Extrinsic verification error: {}", _0)] - Verification(Box), - /// Incorrect extrinsic format. - #[display(fmt="Invalid extrinsic format: {}", _0)] - BadFormat(codec::Error), - /// Incorrect seed phrase. - #[display(fmt="Invalid seed phrase/SURI")] - BadSeedPhrase, - /// Key type ID has an unknown format. - #[display(fmt="Invalid key type ID format (should be of length four)")] - BadKeyType, - /// Key type ID has some unsupported crypto. - #[display(fmt="The crypto of key type ID is unknown")] - UnsupportedKeyType, - /// Some random issue with the key store. Shouldn't happen. - #[display(fmt="The key store is unavailable")] - KeyStoreUnavailable, -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Client(ref err) => Some(&**err), - Error::Pool(ref err) => Some(err), - Error::Verification(ref err) => Some(&**err), - _ => None, - } - } -} - -/// Base code for all authorship errors. -const BASE_ERROR: i64 = 1000; -/// Extrinsic has an invalid format. -const BAD_FORMAT: i64 = BASE_ERROR + 1; -/// Error during 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; -/// The key type crypto is not known. -const UNSUPPORTED_KEY_TYPE: i64 = POOL_INVALID_TX + 7; - -impl From for rpc::Error { - fn from(e: Error) -> Self { - use txpool::error::{Error as PoolError}; - - match e { - Error::BadFormat(e) => rpc::Error { - code: rpc::ErrorCode::ServerError(BAD_FORMAT), - message: format!("Extrinsic has invalid format: {}", e).into(), - data: None, - }, - Error::Verification(e) => rpc::Error { - code: rpc::ErrorCode::ServerError(VERIFICATION_ERROR), - message: format!("Verification Error: {}", e).into(), - data: Some(format!("{:?}", e).into()), - }, - Error::Pool(PoolError::InvalidTransaction(e)) => rpc::Error { - code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), - message: "Invalid Transaction".into(), - data: serde_json::to_value(e).ok(), - }, - Error::Pool(PoolError::UnknownTransaction(e)) => rpc::Error { - code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), - message: "Unknown Transaction Validity".into(), - data: serde_json::to_value(e).ok(), - }, - Error::Pool(PoolError::TemporarilyBanned) => rpc::Error { - code: rpc::ErrorCode::ServerError(POOL_TEMPORARILY_BANNED), - message: "Transaction is temporarily banned".into(), - data: None, - }, - Error::Pool(PoolError::AlreadyImported(hash)) => rpc::Error { - code: rpc::ErrorCode::ServerError(POOL_ALREADY_IMPORTED), - message: "Transaction Already Imported".into(), - data: Some(format!("{:?}", hash).into()), - }, - Error::Pool(PoolError::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::Pool(PoolError::CycleDetected) => rpc::Error { - code: rpc::ErrorCode::ServerError(POOL_CYCLE_DETECTED), - message: "Cycle Detected".into(), - data: None, - }, - Error::Pool(PoolError::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()), - }, - Error::UnsupportedKeyType => rpc::Error { - code: rpc::ErrorCode::ServerError(UNSUPPORTED_KEY_TYPE), - message: "Unknown key type crypto" .into(), - data: Some( - "The crypto for the given key type is unknown, please add the public key to the \ - request to insert the key successfully.".into() - ), - }, - e => errors::internal(e), - } - } -} diff --git a/core/rpc/api/src/author/hash.rs b/core/rpc/api/src/author/hash.rs deleted file mode 100644 index a01e26de3c94b..0000000000000 --- a/core/rpc/api/src/author/hash.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Extrinsic helpers for author RPC module. - -use primitives::Bytes; -use serde::{Serialize, Deserialize}; - -/// RPC Extrinsic or hash -/// -/// Allows to refer to extrinsic either by its raw representation or its hash. -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub enum ExtrinsicOrHash { - /// The hash of the extrinsic. - Hash(Hash), - /// Raw extrinsic bytes. - Extrinsic(Bytes), -} diff --git a/core/rpc/api/src/author/mod.rs b/core/rpc/api/src/author/mod.rs deleted file mode 100644 index 4ea96cb3c6122..0000000000000 --- a/core/rpc/api/src/author/mod.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate block-author/full-node API. - -pub mod error; -pub mod hash; - -use jsonrpc_derive::rpc; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use primitives::{ - Bytes -}; -use self::error::{FutureResult, Result}; -use txpool::watcher::Status; - -pub use self::gen_client::Client as AuthorClient; - -/// Substrate authoring RPC API -#[rpc] -pub trait AuthorApi { - /// RPC metadata - type Metadata; - - /// Submit hex-encoded extrinsic for inclusion in block. - #[rpc(name = "author_submitExtrinsic")] - fn submit_extrinsic(&self, extrinsic: Bytes) -> FutureResult; - - /// Insert a key into the keystore. - #[rpc(name = "author_insertKey")] - fn insert_key(&self, - key_type: String, - suri: String, - public: Bytes, - ) -> Result<()>; - - /// Generate new session keys and returns the corresponding public keys. - #[rpc(name = "author_rotateKeys")] - fn rotate_keys(&self) -> Result; - - /// Returns all pending extrinsics, potentially grouped by sender. - #[rpc(name = "author_pendingExtrinsics")] - fn pending_extrinsics(&self) -> Result>; - - /// Remove given extrinsic from the pool and temporarily ban it to prevent reimporting. - #[rpc(name = "author_removeExtrinsic")] - fn remove_extrinsic(&self, - bytes_or_hash: Vec> - ) -> Result>; - - /// Submit an extrinsic to watch. - #[pubsub( - subscription = "author_extrinsicUpdate", - subscribe, - name = "author_submitAndWatchExtrinsic" - )] - fn watch_extrinsic(&self, - metadata: Self::Metadata, - subscriber: Subscriber>, - bytes: Bytes - ); - - /// Unsubscribe from extrinsic watching. - #[pubsub( - subscription = "author_extrinsicUpdate", - unsubscribe, - name = "author_unwatchExtrinsic" - )] - fn unwatch_extrinsic(&self, - metadata: Option, - id: SubscriptionId - ) -> Result; -} diff --git a/core/rpc/api/src/chain/error.rs b/core/rpc/api/src/chain/error.rs deleted file mode 100644 index 454c0887abf82..0000000000000 --- a/core/rpc/api/src/chain/error.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - - -//! Error helpers for Chain RPC module. - -use crate::errors; -use jsonrpc_core as rpc; - -/// Chain RPC Result type. -pub type Result = std::result::Result; - -/// Chain RPC future Result type. -pub type FutureResult = Box + Send>; - -/// Chain RPC errors. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Client error. - #[display(fmt="Client error: {}", _0)] - Client(Box), - /// Other error type. - Other(String), -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Client(ref err) => Some(&**err), - _ => None, - } - } -} - -/// Base error code for all chain errors. -const BASE_ERROR: i64 = 3000; - -impl From for rpc::Error { - fn from(e: Error) -> Self { - match e { - Error::Other(message) => rpc::Error { - code: rpc::ErrorCode::ServerError(BASE_ERROR + 1), - message, - data: None, - }, - e => errors::internal(e), - } - } -} diff --git a/core/rpc/api/src/chain/mod.rs b/core/rpc/api/src/chain/mod.rs deleted file mode 100644 index 73f4388236cc8..0000000000000 --- a/core/rpc/api/src/chain/mod.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate blockchain API. - -pub mod error; - -use jsonrpc_core::Result as RpcResult; -use jsonrpc_core::futures::Future; -use jsonrpc_derive::rpc; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use rpc_primitives::number; -use self::error::{FutureResult, Result}; - -pub use self::gen_client::Client as ChainClient; - -/// Substrate blockchain API -#[rpc] -pub trait ChainApi { - /// RPC metadata - type Metadata; - - /// Get header of a relay chain block. - #[rpc(name = "chain_getHeader")] - fn header(&self, hash: Option) -> FutureResult>; - - /// Get header and body of a relay chain block. - #[rpc(name = "chain_getBlock")] - fn block(&self, hash: Option) -> FutureResult>; - - /// Get hash of the n-th block in the canon chain. - /// - /// By default returns latest block hash. - #[rpc(name = "chain_getBlockHash", alias("chain_getHead"))] - fn block_hash(&self, hash: Option>) -> Result>; - - /// Get hash of the last finalized block in the canon chain. - #[rpc(name = "chain_getFinalizedHead", alias("chain_getFinalisedHead"))] - fn finalized_head(&self) -> Result; - - /// New head subscription - #[pubsub( - subscription = "chain_newHead", - subscribe, - name = "chain_subscribeNewHeads", - alias("subscribe_newHead", "chain_subscribeNewHead") - )] - fn subscribe_new_heads(&self, metadata: Self::Metadata, subscriber: Subscriber

); - - /// Unsubscribe from new head subscription. - #[pubsub( - subscription = "chain_newHead", - unsubscribe, - name = "chain_unsubscribeNewHeads", - alias("unsubscribe_newHead", "chain_unsubscribeNewHead") - )] - fn unsubscribe_new_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult; - - /// New head subscription - #[pubsub( - subscription = "chain_finalizedHead", - subscribe, - name = "chain_subscribeFinalizedHeads", - alias("chain_subscribeFinalisedHeads") - )] - fn subscribe_finalized_heads(&self, metadata: Self::Metadata, subscriber: Subscriber
); - - /// Unsubscribe from new head subscription. - #[pubsub( - subscription = "chain_finalizedHead", - unsubscribe, - name = "chain_unsubscribeFinalizedHeads", - alias("chain_unsubscribeFinalisedHeads") - )] - fn unsubscribe_finalized_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult; -} diff --git a/core/rpc/api/src/helpers.rs b/core/rpc/api/src/helpers.rs deleted file mode 100644 index d500a50a869b4..0000000000000 --- a/core/rpc/api/src/helpers.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use jsonrpc_core::futures::prelude::*; -use futures03::{channel::oneshot, compat::Compat}; - -/// Wraps around `oneshot::Receiver` and adjusts the error type to produce an internal error if the -/// sender gets dropped. -pub struct Receiver(pub Compat>); - -impl Future for Receiver { - type Item = T; - type Error = jsonrpc_core::Error; - - fn poll(&mut self) -> Poll { - self.0.poll().map_err(|_| jsonrpc_core::Error::internal_error()) - } -} diff --git a/core/rpc/api/src/lib.rs b/core/rpc/api/src/lib.rs deleted file mode 100644 index 12db07633dcc4..0000000000000 --- a/core/rpc/api/src/lib.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate RPC interfaces. -//! -//! A collection of RPC methods and subscriptions supported by all substrate clients. - -#![warn(missing_docs)] - -mod errors; -mod helpers; -mod subscriptions; - -pub use jsonrpc_core::IoHandlerExtension as RpcExtension; -pub use subscriptions::{Subscriptions, TaskExecutor}; -pub use helpers::Receiver; - -pub mod author; -pub mod chain; -pub mod state; -pub mod system; diff --git a/core/rpc/api/src/state/error.rs b/core/rpc/api/src/state/error.rs deleted file mode 100644 index 553a06e896f3d..0000000000000 --- a/core/rpc/api/src/state/error.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! State RPC errors. - -use crate::errors; -use jsonrpc_core as rpc; - -/// State RPC Result type. -pub type Result = std::result::Result; - -/// State RPC future Result type. -pub type FutureResult = Box + Send>; - -/// State RPC errors. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Client error. - #[display(fmt="Client error: {}", _0)] - Client(Box), - /// Provided block range couldn't be resolved to a list of blocks. - #[display(fmt = "Cannot resolve a block range ['{:?}' ... '{:?}]. {}", from, to, details)] - InvalidBlockRange { - /// Beginning of the block range. - from: String, - /// End of the block range. - to: String, - /// Details of the error message. - details: String, - }, -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Client(ref err) => Some(&**err), - _ => None, - } - } -} - -/// Base code for all state errors. -const BASE_ERROR: i64 = 4000; - -impl From for rpc::Error { - fn from(e: Error) -> Self { - match e { - Error::InvalidBlockRange { .. } => rpc::Error { - code: rpc::ErrorCode::ServerError(BASE_ERROR + 1), - message: format!("{}", e), - data: None, - }, - e => errors::internal(e), - } - } -} diff --git a/core/rpc/api/src/state/mod.rs b/core/rpc/api/src/state/mod.rs deleted file mode 100644 index 0d06092ca1659..0000000000000 --- a/core/rpc/api/src/state/mod.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate state API. - -pub mod error; - -use jsonrpc_core::Result as RpcResult; -use jsonrpc_core::futures::Future; -use jsonrpc_derive::rpc; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use primitives::Bytes; -use primitives::storage::{StorageKey, StorageData, StorageChangeSet}; -use runtime_version::RuntimeVersion; -use self::error::FutureResult; - -pub use self::gen_client::Client as StateClient; - -/// Substrate state API -#[rpc] -pub trait StateApi { - /// RPC Metadata - type Metadata; - - /// Call a contract at a block's state. - #[rpc(name = "state_call", alias("state_callAt"))] - fn call(&self, name: String, bytes: Bytes, hash: Option) -> FutureResult; - - /// Returns the keys with prefix, leave empty to get all the keys - #[rpc(name = "state_getKeys")] - fn storage_keys(&self, prefix: StorageKey, hash: Option) -> FutureResult>; - - /// Returns a storage entry at a specific block's state. - #[rpc(name = "state_getStorage", alias("state_getStorageAt"))] - fn storage(&self, key: StorageKey, hash: Option) -> FutureResult>; - - /// Returns the hash of a storage entry at a block's state. - #[rpc(name = "state_getStorageHash", alias("state_getStorageHashAt"))] - fn storage_hash(&self, key: StorageKey, hash: Option) -> FutureResult>; - - /// Returns the size of a storage entry at a block's state. - #[rpc(name = "state_getStorageSize", alias("state_getStorageSizeAt"))] - fn storage_size(&self, key: StorageKey, hash: Option) -> FutureResult>; - - /// Returns the keys with prefix from a child storage, leave empty to get all the keys - #[rpc(name = "state_getChildKeys")] - fn child_storage_keys( - &self, - child_storage_key: StorageKey, - prefix: StorageKey, - hash: Option - ) -> FutureResult>; - - /// Returns a child storage entry at a specific block's state. - #[rpc(name = "state_getChildStorage")] - fn child_storage( - &self, - child_storage_key: StorageKey, - key: StorageKey, - hash: Option - ) -> FutureResult>; - - /// Returns the hash of a child storage entry at a block's state. - #[rpc(name = "state_getChildStorageHash")] - fn child_storage_hash( - &self, - child_storage_key: StorageKey, - key: StorageKey, - hash: Option - ) -> FutureResult>; - - /// Returns the size of a child storage entry at a block's state. - #[rpc(name = "state_getChildStorageSize")] - fn child_storage_size( - &self, - child_storage_key: StorageKey, - key: StorageKey, - hash: Option - ) -> FutureResult>; - - /// Returns the runtime metadata as an opaque blob. - #[rpc(name = "state_getMetadata")] - fn metadata(&self, hash: Option) -> FutureResult; - - /// Get the runtime version. - #[rpc(name = "state_getRuntimeVersion", alias("chain_getRuntimeVersion"))] - fn runtime_version(&self, hash: Option) -> FutureResult; - - /// Query historical storage entries (by key) starting from a block given as the second parameter. - /// - /// NOTE This first returned result contains the initial state of storage for all keys. - /// Subsequent values in the vector represent changes to the previous state (diffs). - #[rpc(name = "state_queryStorage")] - fn query_storage( - &self, - keys: Vec, - block: Hash, - hash: Option - ) -> FutureResult>>; - - /// New runtime version subscription - #[pubsub( - subscription = "state_runtimeVersion", - subscribe, - name = "state_subscribeRuntimeVersion", - alias("chain_subscribeRuntimeVersion") - )] - fn subscribe_runtime_version(&self, metadata: Self::Metadata, subscriber: Subscriber); - - /// Unsubscribe from runtime version subscription - #[pubsub( - subscription = "state_runtimeVersion", - unsubscribe, - name = "state_unsubscribeRuntimeVersion", - alias("chain_unsubscribeRuntimeVersion") - )] - fn unsubscribe_runtime_version(&self, metadata: Option, id: SubscriptionId) -> RpcResult; - - /// New storage subscription - #[pubsub(subscription = "state_storage", subscribe, name = "state_subscribeStorage")] - fn subscribe_storage( - &self, metadata: Self::Metadata, subscriber: Subscriber>, keys: Option> - ); - - /// Unsubscribe from storage subscription - #[pubsub(subscription = "state_storage", unsubscribe, name = "state_unsubscribeStorage")] - fn unsubscribe_storage( - &self, metadata: Option, id: SubscriptionId - ) -> RpcResult; -} diff --git a/core/rpc/api/src/system/error.rs b/core/rpc/api/src/system/error.rs deleted file mode 100644 index 32b694e3ac008..0000000000000 --- a/core/rpc/api/src/system/error.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! System RPC module errors. - -use crate::system::helpers::Health; -use jsonrpc_core as rpc; - -/// System RPC Result type. -pub type Result = std::result::Result; - -/// System RPC errors. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Provided block range couldn't be resolved to a list of blocks. - #[display(fmt = "Node is not fully functional: {}", _0)] - NotHealthy(Health), -} - -impl std::error::Error for Error {} - -/// Base code for all system errors. -const BASE_ERROR: i64 = 2000; - -impl From for rpc::Error { - fn from(e: Error) -> Self { - match e { - Error::NotHealthy(ref h) => rpc::Error { - code: rpc::ErrorCode::ServerError(BASE_ERROR + 1), - message: format!("{}", e), - data: serde_json::to_value(h).ok(), - }, - } - } -} diff --git a/core/rpc/api/src/system/helpers.rs b/core/rpc/api/src/system/helpers.rs deleted file mode 100644 index 10319d57b693b..0000000000000 --- a/core/rpc/api/src/system/helpers.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate system API helpers. - -use std::fmt; -use serde::{Serialize, Deserialize}; -use serde_json::{Value, map::Map}; - -/// Node properties -pub type Properties = Map; - -/// Running node's static details. -#[derive(Clone, Debug)] -pub struct SystemInfo { - /// Implementation name. - pub impl_name: String, - /// Implementation version. - pub impl_version: String, - /// Chain name. - pub chain_name: String, - /// A custom set of properties defined in the chain spec. - pub properties: Properties, -} - -/// Health struct returned by the RPC -#[derive(Debug, PartialEq, Serialize, Deserialize)] -#[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, -} - -impl fmt::Display for Health { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{} peers ({})", self.peers, if self.is_syncing { - "syncing" - } else { "idle" }) - } -} - -/// Network Peer information -#[derive(Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PeerInfo { - /// 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, -} - -/// The role the node is running as -#[derive(Debug, PartialEq, Serialize, Deserialize)] -pub enum NodeRole { - /// The node is a full node - Full, - /// The node is a light client - LightClient, - /// The node is an authority - Authority, - /// An unknown role with a bit number - UnknownRole(u8) -} - -#[cfg(test)] -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 { - peer_id: "2".into(), - roles: "a".into(), - protocol_version: 2, - best_hash: 5u32, - best_number: 6u32, - }).unwrap(), - r#"{"peerId":"2","roles":"a","protocolVersion":2,"bestHash":5,"bestNumber":6}"#, - ); - } -} diff --git a/core/rpc/api/src/system/mod.rs b/core/rpc/api/src/system/mod.rs deleted file mode 100644 index f59fd84c7c027..0000000000000 --- a/core/rpc/api/src/system/mod.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate system API. - -pub mod error; -pub mod helpers; - -use crate::helpers::Receiver; -use jsonrpc_derive::rpc; - -use self::error::Result; - -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; -pub use self::gen_client::Client as SystemClient; - -/// Substrate system RPC API -#[rpc] -pub trait SystemApi { - /// Get the node's implementation name. Plain old string. - #[rpc(name = "system_name")] - fn system_name(&self) -> Result; - - /// Get the node implementation's version. Should be a semver string. - #[rpc(name = "system_version")] - fn system_version(&self) -> Result; - - /// Get the chain's type. Given as a string identifier. - #[rpc(name = "system_chain")] - fn system_chain(&self) -> Result; - - /// Get a custom set of properties as a JSON object, defined in the chain spec. - #[rpc(name = "system_properties")] - fn system_properties(&self) -> Result; - - /// Return health status of the node. - /// - /// Node is considered healthy if it is: - /// - connected to some peers (unless running in dev mode) - /// - not performing a major sync - #[rpc(name = "system_health", returns = "Health")] - fn system_health(&self) -> Receiver; - - /// Returns currently connected peers - #[rpc(name = "system_peers", returns = "Vec>")] - fn system_peers(&self) -> Receiver>>; - - /// Returns current state of the network. - /// - /// **Warning**: This API is not stable. - // TODO: make this stable and move structs https://github.com/paritytech/substrate/issues/1890 - #[rpc(name = "system_networkState", returns = "jsonrpc_core::Value")] - fn system_network_state(&self) -> Receiver; - - /// Returns the roles the node is running as. - #[rpc(name = "system_nodeRoles", returns = "Vec")] - fn system_node_roles(&self) -> Receiver>; -} diff --git a/core/rpc/primitives/Cargo.toml b/core/rpc/primitives/Cargo.toml deleted file mode 100644 index 4044428112780..0000000000000 --- a/core/rpc/primitives/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "substrate-rpc-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../primitives" } diff --git a/core/rpc/primitives/src/lib.rs b/core/rpc/primitives/src/lib.rs deleted file mode 100644 index 667b1b1b4b4f9..0000000000000 --- a/core/rpc/primitives/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate RPC primitives and utilities. - -#![warn(missing_docs)] - -pub mod number; diff --git a/core/rpc/src/author/mod.rs b/core/rpc/src/author/mod.rs deleted file mode 100644 index 82122dcf3d21f..0000000000000 --- a/core/rpc/src/author/mod.rs +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate block-author/full-node API. - -#[cfg(test)] -mod tests; - -use std::{sync::Arc, convert::TryInto}; -use futures03::future::{FutureExt, TryFutureExt}; -use log::warn; - -use client::{self, Client}; -use rpc::futures::{ - Sink, Future, - future::result, -}; -use futures03::{StreamExt as _, compat::Compat, future::ready}; -use api::Subscriptions; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use codec::{Encode, Decode}; -use primitives::{Bytes, Blake2Hasher, H256, traits::BareCryptoStorePtr}; -use sr_primitives::{generic, traits::{self, ProvideRuntimeApi}}; -use transaction_pool::{ - txpool::{ - ChainApi as PoolChainApi, - BlockHash, - ExHash, - IntoPoolError, - Pool, - watcher::Status, - }, -}; -use session::SessionKeys; - -/// Re-export the API for backward compatibility. -pub use api::author::*; -use self::error::{Error, FutureResult, Result}; - -/// Authoring API -pub struct Author where P: PoolChainApi + Sync + Send + 'static { - /// Substrate client - client: Arc::Block, RA>>, - /// Transactions pool - pool: Arc>, - /// Subscriptions manager - subscriptions: Subscriptions, - /// The key store. - keystore: BareCryptoStorePtr, -} - -impl Author where P: PoolChainApi + Sync + Send + 'static { - /// Create new instance of Authoring API. - pub fn new( - client: Arc::Block, RA>>, - pool: Arc>, - subscriptions: Subscriptions, - keystore: BareCryptoStorePtr, - ) -> Self { - Author { - client, - pool, - subscriptions, - keystore, - } - } -} - -impl AuthorApi, BlockHash

> for Author where - B: client::backend::Backend<

::Block, Blake2Hasher> + Send + Sync + 'static, - E: client::CallExecutor<

::Block, Blake2Hasher> + Send + Sync + 'static, - P: PoolChainApi + Sync + Send + 'static, - P::Block: traits::Block, - P::Error: 'static, - RA: Send + Sync + 'static, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: SessionKeys, -{ - type Metadata = crate::metadata::Metadata; - - fn insert_key( - &self, - key_type: String, - suri: String, - public: Bytes, - ) -> Result<()> { - let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?; - let mut keystore = self.keystore.write(); - keystore.insert_unknown(key_type, &suri, &public[..]) - .map_err(|_| Error::KeyStoreUnavailable)?; - Ok(()) - } - - fn rotate_keys(&self) -> Result { - let best_block_hash = self.client.info().chain.best_hash; - self.client.runtime_api().generate_session_keys( - &generic::BlockId::Hash(best_block_hash), - None, - ).map(Into::into).map_err(|e| Error::Client(Box::new(e))) - } - - fn submit_extrinsic(&self, ext: Bytes) -> FutureResult> { - let xt = match Decode::decode(&mut &ext[..]) { - Ok(xt) => xt, - Err(err) => return Box::new(result(Err(err.into()))), - }; - let best_block_hash = self.client.info().chain.best_hash; - Box::new(self.pool - .submit_one(&generic::BlockId::hash(best_block_hash), xt) - .compat() - .map_err(|e| e.into_pool_error() - .map(Into::into) - .unwrap_or_else(|e| error::Error::Verification(Box::new(e)).into())) - ) - } - - fn pending_extrinsics(&self) -> Result> { - Ok(self.pool.ready().map(|tx| tx.data.encode().into()).collect()) - } - - fn remove_extrinsic(&self, - bytes_or_hash: Vec>> - ) -> Result>> { - let hashes = bytes_or_hash.into_iter() - .map(|x| match x { - hash::ExtrinsicOrHash::Hash(h) => Ok(h), - hash::ExtrinsicOrHash::Extrinsic(bytes) => { - let xt = Decode::decode(&mut &bytes[..])?; - Ok(self.pool.hash_of(&xt)) - }, - }) - .collect::>>()?; - - Ok( - self.pool.remove_invalid(&hashes) - .into_iter() - .map(|tx| tx.hash.clone()) - .collect() - ) - } - - 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[..]) - .map_err(error::Error::from)?; - Ok( - self.pool - .submit_and_watch(&generic::BlockId::hash(best_block_hash), dxt) - .map_err(|e| e.into_pool_error() - .map(error::Error::from) - .unwrap_or_else(|e| error::Error::Verification(Box::new(e)).into()) - ) - ) - }; - - let subscriptions = self.subscriptions.clone(); - let future = ready(submit()) - .and_then(|res| res) - // convert the watcher into a `Stream` - .map(|res| res.map(|watcher| watcher.into_stream().map(|v| Ok::<_, ()>(Ok(v))))) - // now handle the import result, - // start a new subscrition - .map(move |result| match result { - Ok(watcher) => { - subscriptions.add(subscriber, move |sink| { - sink - .sink_map_err(|_| unimplemented!()) - .send_all(Compat::new(watcher)) - .map(|_| ()) - }); - }, - Err(err) => { - warn!("Failed to submit extrinsic: {}", err); - // reject the subscriber (ignore errors - we don't care if subscriber is no longer there). - let _ = subscriber.reject(err.into()); - }, - }); - - let res = self.subscriptions.executor() - .execute(Box::new(Compat::new(future.map(|_| Ok(()))))); - if res.is_err() { - warn!("Error spawning subscription RPC task."); - } - } - - fn unwatch_extrinsic(&self, _metadata: Option, id: SubscriptionId) -> Result { - Ok(self.subscriptions.cancel(id)) - } -} diff --git a/core/rpc/src/author/tests.rs b/core/rpc/src/author/tests.rs deleted file mode 100644 index 5ae044ff49ede..0000000000000 --- a/core/rpc/src/author/tests.rs +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use super::*; - -use std::sync::Arc; -use assert_matches::assert_matches; -use codec::Encode; -use primitives::{ - H256, blake2_256, hexdisplay::HexDisplay, testing::{ED25519, SR25519, KeyStore}, traits::BareCryptoStorePtr, ed25519, - crypto::Pair, -}; -use rpc::futures::Stream as _; -use test_client::{ - self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys, RuntimeApi, Block}, DefaultTestClientBuilderExt, - TestClientBuilderExt, Backend, Client, Executor -}; -use transaction_pool::{ - txpool::Pool, - FullChainApi, -}; -use tokio::runtime; - -fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { - let tx = Transfer { - amount: Default::default(), - nonce, - from: sender.into(), - to: Default::default(), - }; - tx.into_signed_tx() -} - -struct TestSetup { - pub runtime: runtime::Runtime, - pub client: Arc>, - pub keystore: BareCryptoStorePtr, - pub pool: Arc, Block>>>, -} - -impl Default for TestSetup { - fn default() -> Self { - let keystore = KeyStore::new(); - let client = Arc::new(test_client::TestClientBuilder::new().set_keystore(keystore.clone()).build()); - let pool = Arc::new(Pool::new(Default::default(), FullChainApi::new(client.clone()))); - TestSetup { - runtime: runtime::Runtime::new().expect("Failed to create runtime in test setup"), - client, - keystore, - pool, - } - } -} - -impl TestSetup { - fn author(&self) -> Author, Block>, RuntimeApi> { - Author { - client: self.client.clone(), - pool: self.pool.clone(), - subscriptions: Subscriptions::new(Arc::new(self.runtime.executor())), - keystore: self.keystore.clone(), - } - } -} - -#[test] -fn submit_transaction_should_not_cause_error() { - let p = TestSetup::default().author(); - let xt = uxt(AccountKeyring::Alice, 1).encode(); - let h: H256 = blake2_256(&xt).into(); - - assert_matches!( - AuthorApi::submit_extrinsic(&p, xt.clone().into()).wait(), - Ok(h2) if h == h2 - ); - assert!( - AuthorApi::submit_extrinsic(&p, xt.into()).wait().is_err() - ); -} - -#[test] -fn submit_rich_transaction_should_not_cause_error() { - let p = TestSetup::default().author(); - let xt = uxt(AccountKeyring::Alice, 0).encode(); - let h: H256 = blake2_256(&xt).into(); - - assert_matches!( - AuthorApi::submit_extrinsic(&p, xt.clone().into()).wait(), - Ok(h2) if h == h2 - ); - assert!( - AuthorApi::submit_extrinsic(&p, xt.into()).wait().is_err() - ); -} - -#[test] -fn should_watch_extrinsic() { - //given - let mut setup = TestSetup::default(); - let p = setup.author(); - - let (subscriber, id_rx, data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); - - // when - p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 0).encode().into()); - - // then - assert_eq!(setup.runtime.block_on(id_rx), Ok(Ok(1.into()))); - // check notifications - let replacement = { - let tx = Transfer { - amount: 5, - nonce: 0, - from: AccountKeyring::Alice.into(), - to: Default::default(), - }; - tx.into_signed_tx() - }; - AuthorApi::submit_extrinsic(&p, replacement.encode().into()).wait().unwrap(); - let (res, data) = setup.runtime.block_on(data.into_future()).unwrap(); - assert_eq!( - res, - Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":"ready","subscription":1}}"#.into()) - ); - let h = blake2_256(&replacement.encode()); - assert_eq!( - setup.runtime.block_on(data.into_future()).unwrap().0, - Some(format!(r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":1}}}}"#, HexDisplay::from(&h))) - ); -} - -#[test] -fn should_return_watch_validation_error() { - //given - let mut setup = TestSetup::default(); - let p = setup.author(); - - let (subscriber, id_rx, _data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); - - // when - p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 179).encode().into()); - - // then - let res = setup.runtime.block_on(id_rx).unwrap(); - assert!(res.is_err(), "Expected the transaction to be rejected as invalid."); -} - -#[test] -fn should_return_pending_extrinsics() { - let p = TestSetup::default().author(); - - let ex = uxt(AccountKeyring::Alice, 0); - AuthorApi::submit_extrinsic(&p, ex.encode().into()).wait().unwrap(); - assert_matches!( - p.pending_extrinsics(), - Ok(ref expected) if *expected == vec![Bytes(ex.encode())] - ); -} - -#[test] -fn should_remove_extrinsics() { - let setup = TestSetup::default(); - let p = setup.author(); - - let ex1 = uxt(AccountKeyring::Alice, 0); - p.submit_extrinsic(ex1.encode().into()).wait().unwrap(); - let ex2 = uxt(AccountKeyring::Alice, 1); - p.submit_extrinsic(ex2.encode().into()).wait().unwrap(); - let ex3 = uxt(AccountKeyring::Bob, 0); - let hash3 = p.submit_extrinsic(ex3.encode().into()).wait().unwrap(); - assert_eq!(setup.pool.status().ready, 3); - - // now remove all 3 - let removed = p.remove_extrinsic(vec![ - hash::ExtrinsicOrHash::Hash(hash3), - // Removing this one will also remove ex2 - hash::ExtrinsicOrHash::Extrinsic(ex1.encode().into()), - ]).unwrap(); - - assert_eq!(removed.len(), 3); -} - -#[test] -fn should_insert_key() { - let setup = TestSetup::default(); - let p = setup.author(); - - let suri = "//Alice"; - let key_pair = ed25519::Pair::from_string(suri, None).expect("Generates keypair"); - p.insert_key( - String::from_utf8(ED25519.0.to_vec()).expect("Keytype is a valid string"), - suri.to_string(), - key_pair.public().0.to_vec().into(), - ).expect("Insert key"); - - let store_key_pair = setup.keystore.read() - .ed25519_key_pair(ED25519, &key_pair.public()).expect("Key exists in store"); - - assert_eq!(key_pair.public(), store_key_pair.public()); -} - -#[test] -fn should_rotate_keys() { - let setup = TestSetup::default(); - let p = setup.author(); - - let new_public_keys = p.rotate_keys().expect("Rotates the keys"); - - let session_keys = SessionKeys::decode(&mut &new_public_keys[..]) - .expect("SessionKeys decode successfully"); - - let ed25519_key_pair = setup.keystore.read().ed25519_key_pair( - ED25519, - &session_keys.ed25519.clone().into(), - ).expect("ed25519 key exists in store"); - - let sr25519_key_pair = setup.keystore.read().sr25519_key_pair( - SR25519, - &session_keys.sr25519.clone().into(), - ).expect("sr25519 key exists in store"); - - assert_eq!(session_keys.ed25519, ed25519_key_pair.public().into()); - assert_eq!(session_keys.sr25519, sr25519_key_pair.public().into()); -} diff --git a/core/rpc/src/chain/mod.rs b/core/rpc/src/chain/mod.rs deleted file mode 100644 index 61ecf96711383..0000000000000 --- a/core/rpc/src/chain/mod.rs +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate blockchain API. - -mod chain_full; -mod chain_light; - -#[cfg(test)] -mod tests; - -use std::sync::Arc; -use futures03::{future, StreamExt as _, TryStreamExt as _}; -use log::warn; -use rpc::{ - Result as RpcResult, - futures::{stream, Future, Sink, Stream}, -}; - -use api::Subscriptions; -use client::{ - self, Client, BlockchainEvents, - light::{fetcher::Fetcher, blockchain::RemoteBlockchain}, -}; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use primitives::{H256, Blake2Hasher}; -use rpc_primitives::number; -use sr_primitives::{ - generic::{BlockId, SignedBlock}, - traits::{Block as BlockT, Header, NumberFor}, -}; - -use self::error::{Result, Error, FutureResult}; - -pub use api::chain::*; - -/// Blockchain backend API -trait ChainBackend: Send + Sync + 'static - where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: client::CallExecutor + Send + Sync + 'static, -{ - /// Get client reference. - fn client(&self) -> &Arc>; - - /// Get subscriptions reference. - fn subscriptions(&self) -> &Subscriptions; - - /// Tries to unwrap passed block hash, or uses best block hash otherwise. - fn unwrap_or_best(&self, hash: Option) -> Block::Hash { - match hash.into() { - None => self.client().info().chain.best_hash, - Some(hash) => hash, - } - } - - /// Get header of a relay chain block. - fn header(&self, hash: Option) -> FutureResult>; - - /// Get header and body of a relay chain block. - fn block(&self, hash: Option) -> FutureResult>>; - - /// Get hash of the n-th block in the canon chain. - /// - /// By default returns latest block hash. - fn block_hash( - &self, - number: Option>>, - ) -> Result> { - Ok(match number { - None => Some(self.client().info().chain.best_hash), - Some(num_or_hex) => self.client() - .header(&BlockId::number(num_or_hex.to_number()?)) - .map_err(client_err)? - .map(|h| h.hash()), - }) - } - - /// Get hash of the last finalized block in the canon chain. - fn finalized_head(&self) -> Result { - Ok(self.client().info().chain.finalized_hash) - } - - /// New head subscription - fn subscribe_new_heads( - &self, - _metadata: crate::metadata::Metadata, - subscriber: Subscriber, - ) { - subscribe_headers( - self.client(), - self.subscriptions(), - subscriber, - || self.client().info().chain.best_hash, - || self.client().import_notification_stream() - .filter(|notification| future::ready(notification.is_new_best)) - .map(|notification| Ok::<_, ()>(notification.header)) - .compat(), - ) - } - - /// Unsubscribe from new head subscription. - fn unsubscribe_new_heads( - &self, - _metadata: Option, - id: SubscriptionId, - ) -> RpcResult { - Ok(self.subscriptions().cancel(id)) - } - - /// New head subscription - fn subscribe_finalized_heads( - &self, - _metadata: crate::metadata::Metadata, - subscriber: Subscriber, - ) { - subscribe_headers( - self.client(), - self.subscriptions(), - subscriber, - || self.client().info().chain.finalized_hash, - || self.client().finality_notification_stream() - .map(|notification| Ok::<_, ()>(notification.header)) - .compat(), - ) - } - - /// Unsubscribe from new head subscription. - fn unsubscribe_finalized_heads( - &self, - _metadata: Option, - id: SubscriptionId, - ) -> RpcResult { - Ok(self.subscriptions().cancel(id)) - } -} - -/// Create new state API that works on full node. -pub fn new_full( - client: Arc>, - subscriptions: Subscriptions, -) -> Chain - where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: client::CallExecutor + Send + Sync + 'static + Clone, - RA: Send + Sync + 'static, -{ - Chain { - backend: Box::new(self::chain_full::FullChain::new(client, subscriptions)), - } -} - -/// Create new state API that works on light node. -pub fn new_light>( - client: Arc>, - subscriptions: Subscriptions, - remote_blockchain: Arc>, - fetcher: Arc, -) -> Chain - where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: client::CallExecutor + Send + Sync + 'static + Clone, - RA: Send + Sync + 'static, - F: Send + Sync + 'static, -{ - Chain { - backend: Box::new(self::chain_light::LightChain::new( - client, - subscriptions, - remote_blockchain, - fetcher, - )), - } -} - -/// Chain API with subscriptions support. -pub struct Chain { - backend: Box>, -} - -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 = crate::metadata::Metadata; - - fn header(&self, hash: Option) -> FutureResult> { - self.backend.header(hash) - } - - fn block(&self, hash: Option) -> FutureResult>> - { - self.backend.block(hash) - } - - fn block_hash(&self, number: Option>>) -> Result> { - self.backend.block_hash(number) - } - - fn finalized_head(&self) -> Result { - self.backend.finalized_head() - } - - fn subscribe_new_heads(&self, metadata: Self::Metadata, subscriber: Subscriber) { - self.backend.subscribe_new_heads(metadata, subscriber) - } - - fn unsubscribe_new_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult { - self.backend.unsubscribe_new_heads(metadata, id) - } - - fn subscribe_finalized_heads(&self, metadata: Self::Metadata, subscriber: Subscriber) { - self.backend.subscribe_finalized_heads(metadata, subscriber) - } - - fn unsubscribe_finalized_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult { - self.backend.unsubscribe_finalized_heads(metadata, id) - } -} - -/// Subscribe to new headers. -fn subscribe_headers( - client: &Arc>, - subscriptions: &Subscriptions, - subscriber: Subscriber, - best_block_hash: G, - stream: F, -) where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: client::CallExecutor + Send + Sync + 'static, - F: FnOnce() -> S, - G: FnOnce() -> Block::Hash, - ERR: ::std::fmt::Debug, - S: Stream + Send + 'static, -{ - subscriptions.add(subscriber, |sink| { - // send current head right at the start. - let header = client.header(&BlockId::Hash(best_block_hash())) - .map_err(client_err) - .and_then(|header| { - header.ok_or_else(|| "Best header missing.".to_owned().into()) - }) - .map_err(Into::into); - - // send further subscriptions - let stream = stream() - .map(|res| Ok(res)) - .map_err(|e| warn!("Block notification stream error: {:?}", e)); - - sink - .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) - .send_all( - stream::iter_result(vec![Ok(header)]) - .chain(stream) - ) - // we ignore the resulting Stream (if the first stream is over we are unsubscribed) - .map(|_| ()) - }); -} - -fn client_err(err: client::error::Error) -> Error { - Error::Client(Box::new(err)) -} diff --git a/core/rpc/src/chain/tests.rs b/core/rpc/src/chain/tests.rs deleted file mode 100644 index 8b46befee6520..0000000000000 --- a/core/rpc/src/chain/tests.rs +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use super::*; -use assert_matches::assert_matches; -use test_client::{ - prelude::*, - consensus::BlockOrigin, - runtime::{H256, Block, Header}, -}; - -#[test] -fn should_return_header() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - - assert_matches!( - api.header(Some(client.genesis_hash()).into()).wait(), - Ok(Some(ref x)) if x == &Header { - parent_hash: H256::from_low_u64_be(0), - number: 0, - state_root: x.state_root.clone(), - extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), - digest: Default::default(), - } - ); - - assert_matches!( - api.header(None.into()).wait(), - Ok(Some(ref x)) if x == &Header { - parent_hash: H256::from_low_u64_be(0), - number: 0, - state_root: x.state_root.clone(), - extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), - digest: Default::default(), - } - ); - - assert_matches!( - api.header(Some(H256::from_low_u64_be(5)).into()).wait(), - Ok(None) - ); -} - -#[test] -fn should_return_a_block() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - - let block = client.new_block(Default::default()).unwrap().bake().unwrap(); - let block_hash = block.hash(); - client.import(BlockOrigin::Own, block).unwrap(); - - // Genesis block is not justified - assert_matches!( - api.block(Some(client.genesis_hash()).into()).wait(), - Ok(Some(SignedBlock { justification: None, .. })) - ); - - assert_matches!( - api.block(Some(block_hash).into()).wait(), - Ok(Some(ref x)) if x.block == Block { - header: Header { - parent_hash: client.genesis_hash(), - number: 1, - state_root: x.block.header.state_root.clone(), - extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), - digest: Default::default(), - }, - extrinsics: vec![], - } - ); - - assert_matches!( - api.block(None.into()).wait(), - Ok(Some(ref x)) if x.block == Block { - header: Header { - parent_hash: client.genesis_hash(), - number: 1, - state_root: x.block.header.state_root.clone(), - extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), - digest: Default::default(), - }, - extrinsics: vec![], - } - ); - - assert_matches!( - api.block(Some(H256::from_low_u64_be(5)).into()).wait(), - Ok(None) - ); -} - -#[test] -fn should_return_block_hash() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - - assert_matches!( - api.block_hash(None.into()), - Ok(Some(ref x)) if x == &client.genesis_hash() - ); - - - assert_matches!( - api.block_hash(Some(0u64.into()).into()), - Ok(Some(ref x)) if x == &client.genesis_hash() - ); - - assert_matches!( - api.block_hash(Some(1u64.into()).into()), - Ok(None) - ); - - let block = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, block.clone()).unwrap(); - - assert_matches!( - api.block_hash(Some(0u64.into()).into()), - Ok(Some(ref x)) if x == &client.genesis_hash() - ); - assert_matches!( - api.block_hash(Some(1u64.into()).into()), - Ok(Some(ref x)) if x == &block.hash() - ); - assert_matches!( - api.block_hash(Some(::primitives::U256::from(1u64).into()).into()), - Ok(Some(ref x)) if x == &block.hash() - ); -} - - -#[test] -fn should_return_finalized_hash() { - let core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - - assert_matches!( - api.finalized_head(), - Ok(ref x) if x == &client.genesis_hash() - ); - - // import new block - let builder = client.new_block(Default::default()).unwrap(); - client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - // no finalization yet - assert_matches!( - api.finalized_head(), - Ok(ref x) if x == &client.genesis_hash() - ); - - // finalize - client.finalize_block(BlockId::number(1), None).unwrap(); - assert_matches!( - api.finalized_head(), - Ok(ref x) if x == &client.block_hash(1).unwrap().unwrap() - ); -} - -#[test] -fn should_notify_about_latest_block() { - let mut core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let (subscriber, id, transport) = Subscriber::new_test("test"); - - { - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - - api.subscribe_new_heads(Default::default(), subscriber); - - // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - - let builder = client.new_block(Default::default()).unwrap(); - client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - } - - // assert initial head sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); - assert!(notification.is_some()); - // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); - assert!(notification.is_some()); - // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); -} - -#[test] -fn should_notify_about_finalized_block() { - let mut core = ::tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let (subscriber, id, transport) = Subscriber::new_test("test"); - - { - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - - api.subscribe_finalized_heads(Default::default(), subscriber); - - // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - - let builder = client.new_block(Default::default()).unwrap(); - client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - client.finalize_block(BlockId::number(1), None).unwrap(); - } - - // assert initial head sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); - assert!(notification.is_some()); - // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); - assert!(notification.is_some()); - // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); -} diff --git a/core/rpc/src/helpers.rs b/core/rpc/src/helpers.rs deleted file mode 100644 index e579c743acdad..0000000000000 --- a/core/rpc/src/helpers.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -/// Unwraps the trailing parameter or falls back with the closure result. -pub fn unwrap_or_else(or_else: F, optional: Option) -> Result where - F: FnOnce() -> Result, -{ - match optional.into() { - None => or_else(), - Some(x) => Ok(x), - } -} diff --git a/core/rpc/src/lib.rs b/core/rpc/src/lib.rs deleted file mode 100644 index 9ce9f82fdad2c..0000000000000 --- a/core/rpc/src/lib.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate RPC implementation. -//! -//! A core implementation of Substrate RPC interfaces. - -#![warn(missing_docs)] - -mod helpers; -mod metadata; - -pub use api::Subscriptions; -pub use self::metadata::Metadata; -pub use rpc::IoHandlerExtension as RpcExtension; - -pub mod author; -pub mod chain; -pub mod state; -pub mod system; diff --git a/core/rpc/src/metadata.rs b/core/rpc/src/metadata.rs deleted file mode 100644 index 73bf583765b20..0000000000000 --- a/core/rpc/src/metadata.rs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! RPC Metadata -use std::sync::Arc; - -use jsonrpc_pubsub::{Session, PubSubMetadata}; -use rpc::futures::sync::mpsc; - -/// RPC Metadata. -/// -/// Manages persistent session for transports that support it -/// and may contain some additional info extracted from specific transports -/// (like remote client IP address, request headers, etc) -#[derive(Default, Clone)] -pub struct Metadata { - session: Option>, -} - -impl rpc::Metadata for Metadata {} -impl PubSubMetadata for Metadata { - fn session(&self) -> Option> { - self.session.clone() - } -} - -impl Metadata { - /// Create new `Metadata` with session (Pub/Sub) support. - pub fn new(transport: mpsc::Sender) -> Self { - Metadata { - session: Some(Arc::new(Session::new(transport))), - } - } - - /// Create new `Metadata` for tests. - #[cfg(test)] - pub fn new_test() -> (mpsc::Receiver, Self) { - let (tx, rx) = mpsc::channel(1); - (rx, Self::new(tx)) - } -} - -impl From> for Metadata { - fn from(sender: mpsc::Sender) -> Self { - Self::new(sender) - } -} diff --git a/core/rpc/src/state/mod.rs b/core/rpc/src/state/mod.rs deleted file mode 100644 index b922601b0a5b2..0000000000000 --- a/core/rpc/src/state/mod.rs +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate state API. - -mod state_full; -mod state_light; - -#[cfg(test)] -mod tests; - -use std::sync::Arc; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use rpc::{ - Result as RpcResult, - futures::Future, -}; - -use api::Subscriptions; -use client::{ - Client, CallExecutor, - runtime_api::Metadata, - light::{blockchain::RemoteBlockchain, fetcher::Fetcher}, -}; -use primitives::{ - Blake2Hasher, Bytes, H256, - storage::{StorageKey, StorageData, StorageChangeSet}, -}; -use runtime_version::RuntimeVersion; -use sr_primitives::{ - traits::{Block as BlockT, ProvideRuntimeApi}, -}; - -use self::error::{Error, FutureResult}; - -pub use api::state::*; - -/// State backend API. -pub trait StateBackend: Send + Sync + 'static - where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: client::CallExecutor + Send + Sync + 'static, - RA: Send + Sync + 'static, -{ - /// Call runtime method at given block. - fn call( - &self, - block: Option, - method: String, - call_data: Bytes, - ) -> FutureResult; - - /// Returns the keys with prefix, leave empty to get all the keys. - fn storage_keys( - &self, - block: Option, - prefix: StorageKey, - ) -> FutureResult>; - - /// Returns a storage entry at a specific block's state. - fn storage( - &self, - block: Option, - key: StorageKey, - ) -> FutureResult>; - - /// Returns the hash of a storage entry at a block's state. - fn storage_hash( - &self, - block: Option, - key: StorageKey, - ) -> FutureResult>; - - /// Returns the size of a storage entry at a block's state. - fn storage_size( - &self, - block: Option, - key: StorageKey, - ) -> FutureResult> { - Box::new(self.storage(block, key) - .map(|x| x.map(|x| x.0.len() as u64))) - } - - /// Returns the keys with prefix from a child storage, leave empty to get all the keys - fn child_storage_keys( - &self, - block: Option, - child_storage_key: StorageKey, - prefix: StorageKey, - ) -> FutureResult>; - - /// Returns a child storage entry at a specific block's state. - fn child_storage( - &self, - block: Option, - child_storage_key: StorageKey, - key: StorageKey, - ) -> FutureResult>; - - /// Returns the hash of a child storage entry at a block's state. - fn child_storage_hash( - &self, - block: Option, - child_storage_key: StorageKey, - key: StorageKey, - ) -> FutureResult>; - - /// Returns the size of a child storage entry at a block's state. - fn child_storage_size( - &self, - block: Option, - child_storage_key: StorageKey, - key: StorageKey, - ) -> FutureResult> { - Box::new(self.child_storage(block, child_storage_key, key) - .map(|x| x.map(|x| x.0.len() as u64))) - } - - /// Returns the runtime metadata as an opaque blob. - fn metadata(&self, block: Option) -> FutureResult; - - /// Get the runtime version. - fn runtime_version(&self, block: Option) -> FutureResult; - - /// Query historical storage entries (by key) starting from a block given as the second parameter. - /// - /// NOTE This first returned result contains the initial state of storage for all keys. - /// Subsequent values in the vector represent changes to the previous state (diffs). - fn query_storage( - &self, - from: Block::Hash, - to: Option, - keys: Vec, - ) -> FutureResult>>; - - /// New runtime version subscription - fn subscribe_runtime_version( - &self, - _meta: crate::metadata::Metadata, - subscriber: Subscriber, - ); - - /// Unsubscribe from runtime version subscription - fn unsubscribe_runtime_version( - &self, - _meta: Option, - id: SubscriptionId, - ) -> RpcResult; - - /// New storage subscription - fn subscribe_storage( - &self, - _meta: crate::metadata::Metadata, - subscriber: Subscriber>, - keys: Option>, - ); - - /// Unsubscribe from storage subscription - fn unsubscribe_storage( - &self, - _meta: Option, - id: SubscriptionId, - ) -> RpcResult; -} - -/// Create new state API that works on full node. -pub fn new_full( - client: Arc>, - subscriptions: Subscriptions, -) -> State - where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static + Clone, - RA: Send + Sync + 'static, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: Metadata, -{ - State { - backend: Box::new(self::state_full::FullState::new(client, subscriptions)), - } -} - -/// Create new state API that works on light node. -pub fn new_light>( - client: Arc>, - subscriptions: Subscriptions, - remote_blockchain: Arc>, - fetcher: Arc, -) -> State - where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static + Clone, - RA: Send + Sync + 'static, - F: Send + Sync + 'static, -{ - State { - backend: Box::new(self::state_light::LightState::new( - client, - subscriptions, - remote_blockchain, - fetcher, - )), - } -} - -/// State API with subscriptions support. -pub struct State { - backend: Box>, -} - -impl StateApi for State - where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static + Clone, - RA: Send + Sync + 'static, -{ - type Metadata = crate::metadata::Metadata; - - fn call(&self, method: String, data: Bytes, block: Option) -> FutureResult { - self.backend.call(block, method, data) - } - - fn storage_keys( - &self, - key_prefix: StorageKey, - block: Option, - ) -> FutureResult> { - self.backend.storage_keys(block, key_prefix) - } - - fn storage(&self, key: StorageKey, block: Option) -> FutureResult> { - self.backend.storage(block, key) - } - - fn storage_hash(&self, key: StorageKey, block: Option) -> FutureResult> { - self.backend.storage_hash(block, key) - } - - fn storage_size(&self, key: StorageKey, block: Option) -> FutureResult> { - self.backend.storage_size(block, key) - } - - fn child_storage( - &self, - child_storage_key: StorageKey, - key: StorageKey, - block: Option - ) -> FutureResult> { - self.backend.child_storage(block, child_storage_key, key) - } - - fn child_storage_keys( - &self, - child_storage_key: StorageKey, - key_prefix: StorageKey, - block: Option - ) -> FutureResult> { - self.backend.child_storage_keys(block, child_storage_key, key_prefix) - } - - fn child_storage_hash( - &self, - child_storage_key: StorageKey, - key: StorageKey, - block: Option - ) -> FutureResult> { - self.backend.child_storage_hash(block, child_storage_key, key) - } - - fn child_storage_size( - &self, - child_storage_key: StorageKey, - key: StorageKey, - block: Option - ) -> FutureResult> { - self.backend.child_storage_size(block, child_storage_key, key) - } - - fn metadata(&self, block: Option) -> FutureResult { - self.backend.metadata(block) - } - - fn query_storage( - &self, - keys: Vec, - from: Block::Hash, - to: Option - ) -> FutureResult>> { - self.backend.query_storage(from, to, keys) - } - - fn subscribe_storage( - &self, - meta: Self::Metadata, - subscriber: Subscriber>, - keys: Option> - ) { - self.backend.subscribe_storage(meta, subscriber, keys); - } - - fn unsubscribe_storage(&self, meta: Option, id: SubscriptionId) -> RpcResult { - self.backend.unsubscribe_storage(meta, id) - } - - fn runtime_version(&self, at: Option) -> FutureResult { - self.backend.runtime_version(at) - } - - fn subscribe_runtime_version(&self, meta: Self::Metadata, subscriber: Subscriber) { - self.backend.subscribe_runtime_version(meta, subscriber); - } - - fn unsubscribe_runtime_version( - &self, - meta: Option, - id: SubscriptionId, - ) -> RpcResult { - self.backend.unsubscribe_runtime_version(meta, id) - } -} - -fn client_err(err: client::error::Error) -> Error { - Error::Client(Box::new(err)) -} diff --git a/core/rpc/src/state/state_full.rs b/core/rpc/src/state/state_full.rs deleted file mode 100644 index cd05093c3a8cb..0000000000000 --- a/core/rpc/src/state/state_full.rs +++ /dev/null @@ -1,509 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! State API backend for full nodes. - -use std::collections::{BTreeMap, HashMap}; -use std::sync::Arc; -use std::ops::Range; -use futures03::{future, StreamExt as _, TryStreamExt as _}; -use log::warn; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use rpc::{ - Result as RpcResult, - futures::{stream, Future, Sink, Stream, future::result}, -}; - -use api::Subscriptions; -use client::{ - Client, CallExecutor, BlockchainEvents, runtime_api::Metadata, - backend::Backend, error::Result as ClientResult, -}; -use primitives::{ - H256, Blake2Hasher, Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet}, -}; -use runtime_version::RuntimeVersion; -use state_machine::ExecutionStrategy; -use sr_primitives::{ - generic::BlockId, - traits::{Block as BlockT, Header, NumberFor, ProvideRuntimeApi, SaturatedConversion}, -}; - -use super::{StateBackend, error::{FutureResult, Error, Result}, client_err}; - -/// Ranges to query in state_queryStorage. -struct QueryStorageRange { - /// Hashes of all the blocks in the range. - pub hashes: Vec, - /// Number of the first block in the range. - pub first_number: NumberFor, - /// Blocks subrange ([begin; end) indices within `hashes`) where we should read keys at - /// each state to get changes. - pub unfiltered_range: Range, - /// Blocks subrange ([begin; end) indices within `hashes`) where we could pre-filter - /// blocks-with-changes by using changes tries. - pub filtered_range: Option>, -} - -/// State API backend for full nodes. -pub struct FullState { - client: Arc>, - subscriptions: Subscriptions, -} - -impl FullState - where - Block: BlockT + 'static, - B: Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static + Clone, -{ - /// Create new state API backend for full nodes. - pub fn new(client: Arc>, subscriptions: Subscriptions) -> Self { - Self { client, subscriptions } - } - - /// Returns given block hash or best block hash if None is passed. - fn block_or_best(&self, hash: Option) -> ClientResult { - crate::helpers::unwrap_or_else(|| Ok(self.client.info().chain.best_hash), hash) - } - - /// Splits the `query_storage` block range into 'filtered' and 'unfiltered' subranges. - /// Blocks that contain changes within filtered subrange could be filtered using changes tries. - /// Blocks that contain changes within unfiltered subrange must be filtered manually. - fn split_query_storage_range( - &self, - from: Block::Hash, - to: Option - ) -> Result> { - let to = self.block_or_best(to).map_err(client_err)?; - let from_hdr = self.client.header(&BlockId::hash(from)).map_err(client_err)?; - let to_hdr = self.client.header(&BlockId::hash(to)).map_err(client_err)?; - match (from_hdr, to_hdr) { - (Some(ref from), Some(ref to)) if from.number() <= to.number() => { - // check if we can get from `to` to `from` by going through parent_hashes. - let from_number = *from.number(); - let blocks = { - let mut blocks = vec![to.hash()]; - let mut last = to.clone(); - while *last.number() > from_number { - let hdr = self.client - .header(&BlockId::hash(*last.parent_hash())) - .map_err(client_err)?; - if let Some(hdr) = hdr { - blocks.push(hdr.hash()); - last = hdr; - } else { - return Err(invalid_block_range( - Some(from), - Some(to), - format!("Parent of {} ({}) not found", last.number(), last.hash()), - )) - } - } - if last.hash() != from.hash() { - return Err(invalid_block_range( - Some(from), - Some(to), - format!("Expected to reach `from`, got {} ({})", last.number(), last.hash()), - )) - } - blocks.reverse(); - blocks - }; - // check if we can filter blocks-with-changes from some (sub)range using changes tries - let changes_trie_range = self.client - .max_key_changes_range(from_number, BlockId::Hash(to.hash())) - .map_err(client_err)?; - let filtered_range_begin = changes_trie_range - .map(|(begin, _)| (begin - from_number).saturated_into::()); - let (unfiltered_range, filtered_range) = split_range(blocks.len(), filtered_range_begin); - Ok(QueryStorageRange { - hashes: blocks, - first_number: from_number, - unfiltered_range, - filtered_range, - }) - }, - (from, to) => Err( - invalid_block_range(from.as_ref(), to.as_ref(), "Invalid range or unknown block".into()) - ), - } - } - - /// Iterates through range.unfiltered_range and check each block for changes of keys' values. - fn query_storage_unfiltered( - &self, - range: &QueryStorageRange, - keys: &[StorageKey], - last_values: &mut HashMap>, - changes: &mut Vec>, - ) -> Result<()> { - for block in range.unfiltered_range.start..range.unfiltered_range.end { - let block_hash = range.hashes[block].clone(); - let mut block_changes = StorageChangeSet { block: block_hash.clone(), changes: Vec::new() }; - let id = BlockId::hash(block_hash); - for key in keys { - let (has_changed, data) = { - let curr_data = self.client.storage(&id, key).map_err(client_err)?; - match last_values.get(key) { - Some(prev_data) => (curr_data != *prev_data, curr_data), - None => (true, curr_data), - } - }; - if has_changed { - block_changes.changes.push((key.clone(), data.clone())); - } - last_values.insert(key.clone(), data); - } - if !block_changes.changes.is_empty() { - changes.push(block_changes); - } - } - Ok(()) - } - - /// Iterates through all blocks that are changing keys within range.filtered_range and collects these changes. - fn query_storage_filtered( - &self, - range: &QueryStorageRange, - keys: &[StorageKey], - last_values: &HashMap>, - changes: &mut Vec>, - ) -> Result<()> { - let (begin, end) = match range.filtered_range { - Some(ref filtered_range) => ( - range.first_number + filtered_range.start.saturated_into(), - BlockId::Hash(range.hashes[filtered_range.end - 1].clone()) - ), - None => return Ok(()), - }; - let mut changes_map: BTreeMap, StorageChangeSet> = BTreeMap::new(); - for key in keys { - let mut last_block = None; - let mut last_value = last_values.get(key).cloned().unwrap_or_default(); - let key_changes = self.client.key_changes(begin, end, None, key).map_err(client_err)?; - for (block, _) in key_changes.into_iter().rev() { - if last_block == Some(block) { - continue; - } - - let block_hash = range.hashes[(block - range.first_number).saturated_into::()].clone(); - let id = BlockId::Hash(block_hash); - let value_at_block = self.client.storage(&id, key).map_err(client_err)?; - if last_value == value_at_block { - continue; - } - - changes_map.entry(block) - .or_insert_with(|| StorageChangeSet { block: block_hash, changes: Vec::new() }) - .changes.push((key.clone(), value_at_block.clone())); - last_block = Some(block); - last_value = value_at_block; - } - } - if let Some(additional_capacity) = changes_map.len().checked_sub(changes.len()) { - changes.reserve(additional_capacity); - } - changes.extend(changes_map.into_iter().map(|(_, cs)| cs)); - Ok(()) - } -} - -impl StateBackend for FullState - where - Block: BlockT + 'static, - B: Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static + Clone, - RA: Send + Sync + 'static, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: Metadata, -{ - fn call( - &self, - block: Option, - method: String, - call_data: Bytes, - ) -> FutureResult { - Box::new(result( - self.block_or_best(block) - .and_then(|block| - self - .client - .executor() - .call( - &BlockId::Hash(block), - &method, - &*call_data, - ExecutionStrategy::NativeElseWasm, - None, - ) - .map(Into::into)) - .map_err(client_err))) - } - - fn storage_keys( - &self, - block: Option, - prefix: StorageKey, - ) -> FutureResult> { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.storage_keys(&BlockId::Hash(block), &prefix)) - .map_err(client_err))) - } - - fn storage( - &self, - block: Option, - key: StorageKey, - ) -> FutureResult> { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.storage(&BlockId::Hash(block), &key)) - .map_err(client_err))) - } - - fn storage_hash( - &self, - block: Option, - key: StorageKey, - ) -> FutureResult> { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.storage_hash(&BlockId::Hash(block), &key)) - .map_err(client_err))) - } - - fn child_storage_keys( - &self, - block: Option, - child_storage_key: StorageKey, - prefix: StorageKey, - ) -> FutureResult> { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.child_storage_keys(&BlockId::Hash(block), &child_storage_key, &prefix)) - .map_err(client_err))) - } - - fn child_storage( - &self, - block: Option, - child_storage_key: StorageKey, - key: StorageKey, - ) -> FutureResult> { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.child_storage(&BlockId::Hash(block), &child_storage_key, &key)) - .map_err(client_err))) - } - - fn child_storage_hash( - &self, - block: Option, - child_storage_key: StorageKey, - key: StorageKey, - ) -> FutureResult> { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.child_storage_hash(&BlockId::Hash(block), &child_storage_key, &key)) - .map_err(client_err))) - } - - fn metadata(&self, block: Option) -> FutureResult { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.runtime_api().metadata(&BlockId::Hash(block)).map(Into::into)) - .map_err(client_err))) - } - - fn runtime_version(&self, block: Option) -> FutureResult { - Box::new(result( - self.block_or_best(block) - .and_then(|block| self.client.runtime_version_at(&BlockId::Hash(block))) - .map_err(client_err))) - } - - fn query_storage( - &self, - from: Block::Hash, - to: Option, - keys: Vec, - ) -> FutureResult>> { - let call_fn = move || { - let range = self.split_query_storage_range(from, to)?; - let mut changes = Vec::new(); - let mut last_values = HashMap::new(); - self.query_storage_unfiltered(&range, &keys, &mut last_values, &mut changes)?; - self.query_storage_filtered(&range, &keys, &last_values, &mut changes)?; - Ok(changes) - }; - Box::new(result(call_fn())) - } - - fn subscribe_runtime_version( - &self, - _meta: crate::metadata::Metadata, - subscriber: Subscriber, - ) { - let stream = match self.client.storage_changes_notification_stream( - Some(&[StorageKey(well_known_keys::CODE.to_vec())]), - None, - ) { - Ok(stream) => stream, - Err(err) => { - let _ = subscriber.reject(Error::from(client_err(err)).into()); - return; - } - }; - - self.subscriptions.add(subscriber, |sink| { - let version = self.runtime_version(None.into()) - .map_err(Into::into) - .wait(); - - let client = self.client.clone(); - let mut previous_version = version.clone(); - - let stream = stream - .filter_map(move |_| { - let info = client.info(); - let version = client - .runtime_version_at(&BlockId::hash(info.chain.best_hash)) - .map_err(client_err) - .map_err(Into::into); - if previous_version != version { - previous_version = version.clone(); - future::ready(Some(Ok::<_, ()>(version))) - } else { - future::ready(None) - } - }) - .compat(); - - sink - .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) - .send_all( - stream::iter_result(vec![Ok(version)]) - .chain(stream) - ) - // we ignore the resulting Stream (if the first stream is over we are unsubscribed) - .map(|_| ()) - }); - } - - fn unsubscribe_runtime_version( - &self, - _meta: Option, - id: SubscriptionId, - ) -> RpcResult { - Ok(self.subscriptions.cancel(id)) - } - - fn subscribe_storage( - &self, - _meta: crate::metadata::Metadata, - subscriber: Subscriber>, - keys: Option>, - ) { - let keys = Into::>>::into(keys); - let stream = match self.client.storage_changes_notification_stream( - keys.as_ref().map(|x| &**x), - None - ) { - Ok(stream) => stream, - Err(err) => { - let _ = subscriber.reject(client_err(err).into()); - return; - }, - }; - - // initial values - let initial = stream::iter_result(keys - .map(|keys| { - let block = self.client.info().chain.best_hash; - let changes = keys - .into_iter() - .map(|key| self.storage(Some(block.clone()).into(), key.clone()) - .map(|val| (key.clone(), val)) - .wait() - .unwrap_or_else(|_| (key, None)) - ) - .collect(); - vec![Ok(Ok(StorageChangeSet { block, changes }))] - }).unwrap_or_default()); - - self.subscriptions.add(subscriber, |sink| { - let stream = stream - .map(|(block, changes)| Ok::<_, ()>(Ok(StorageChangeSet { - block, - changes: changes.iter() - .filter_map(|(o_sk, k, v)| if o_sk.is_none() { - Some((k.clone(),v.cloned())) - } else { None }).collect(), - }))) - .compat(); - - sink - .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) - .send_all(initial.chain(stream)) - // we ignore the resulting Stream (if the first stream is over we are unsubscribed) - .map(|_| ()) - }); - } - - fn unsubscribe_storage( - &self, - _meta: Option, - id: SubscriptionId, - ) -> RpcResult { - Ok(self.subscriptions.cancel(id)) - } -} - -/// Splits passed range into two subranges where: -/// - first range has at least one element in it; -/// - second range (optionally) starts at given `middle` element. -pub(crate) fn split_range(size: usize, middle: Option) -> (Range, Option>) { - // check if we can filter blocks-with-changes from some (sub)range using changes tries - let range2_begin = match middle { - // some of required changes tries are pruned => use available tries - Some(middle) if middle != 0 => Some(middle), - // all required changes tries are available, but we still want values at first block - // => do 'unfiltered' read for the first block and 'filtered' for the rest - Some(_) if size > 1 => Some(1), - // range contains single element => do not use changes tries - Some(_) => None, - // changes tries are not available => do 'unfiltered' read for the whole range - None => None, - }; - let range1 = 0..range2_begin.unwrap_or(size); - let range2 = range2_begin.map(|begin| begin..size); - (range1, range2) -} - -fn invalid_block_range(from: Option<&H>, to: Option<&H>, reason: String) -> Error { - let to_string = |x: Option<&H>| match x { - None => "unknown hash".into(), - Some(h) => format!("{} ({})", h.number(), h.hash()), - }; - - Error::InvalidBlockRange { - from: to_string(from), - to: to_string(to), - details: reason, - } -} diff --git a/core/rpc/src/state/tests.rs b/core/rpc/src/state/tests.rs deleted file mode 100644 index 5dfa234337afa..0000000000000 --- a/core/rpc/src/state/tests.rs +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use super::*; -use super::state_full::split_range; -use self::error::Error; - -use std::sync::Arc; -use assert_matches::assert_matches; -use futures::stream::Stream; -use primitives::storage::well_known_keys; -use sr_io::blake2_256; -use test_client::{ - prelude::*, - consensus::BlockOrigin, - runtime, -}; - -#[test] -fn should_return_storage() { - const KEY: &[u8] = b":mock"; - const VALUE: &[u8] = b"hello world"; - const STORAGE_KEY: &[u8] = b":child_storage:default:child"; - const CHILD_VALUE: &[u8] = b"hello world !"; - - let mut core = tokio::runtime::Runtime::new().unwrap(); - let client = TestClientBuilder::new() - .add_extra_storage(KEY.to_vec(), VALUE.to_vec()) - .add_extra_child_storage(STORAGE_KEY.to_vec(), KEY.to_vec(), CHILD_VALUE.to_vec()) - .build(); - let genesis_hash = client.genesis_hash(); - let client = new_full(Arc::new(client), Subscriptions::new(Arc::new(core.executor()))); - let key = StorageKey(KEY.to_vec()); - let storage_key = StorageKey(STORAGE_KEY.to_vec()); - - assert_eq!( - client.storage(key.clone(), Some(genesis_hash).into()).wait() - .map(|x| x.map(|x| x.0.len())).unwrap().unwrap() as usize, - VALUE.len(), - ); - assert_matches!( - client.storage_hash(key.clone(), Some(genesis_hash).into()).wait() - .map(|x| x.is_some()), - Ok(true) - ); - assert_eq!( - client.storage_size(key.clone(), None).wait().unwrap().unwrap() as usize, - VALUE.len(), - ); - assert_eq!( - core.block_on( - client.child_storage(storage_key, key, Some(genesis_hash).into()) - .map(|x| x.map(|x| x.0.len())) - ).unwrap().unwrap() as usize, - CHILD_VALUE.len(), - ); - -} - -#[test] -fn should_return_child_storage() { - let core = tokio::runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::TestClientBuilder::new() - .add_child_storage("test", "key", vec![42_u8]) - .build()); - let genesis_hash = client.genesis_hash(); - let client = new_full(client, Subscriptions::new(Arc::new(core.executor()))); - let child_key = StorageKey(well_known_keys::CHILD_STORAGE_KEY_PREFIX.iter().chain(b"test").cloned().collect()); - let key = StorageKey(b"key".to_vec()); - - - assert_matches!( - client.child_storage(child_key.clone(), key.clone(), Some(genesis_hash).into()).wait(), - Ok(Some(StorageData(ref d))) if d[0] == 42 && d.len() == 1 - ); - assert_matches!( - client.child_storage_hash(child_key.clone(), key.clone(), Some(genesis_hash).into()) - .wait().map(|x| x.is_some()), - Ok(true) - ); - assert_matches!( - client.child_storage_size(child_key.clone(), key.clone(), None).wait(), - Ok(Some(1)) - ); -} - -#[test] -fn should_call_contract() { - let core = tokio::runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); - let genesis_hash = client.genesis_hash(); - let client = new_full(client, Subscriptions::new(Arc::new(core.executor()))); - - assert_matches!( - client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()).wait(), - Err(Error::Client(_)) - ) -} - -#[test] -fn should_notify_about_storage_changes() { - let mut core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let (subscriber, id, transport) = Subscriber::new_test("test"); - - { - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - - api.subscribe_storage(Default::default(), subscriber, None.into()); - - // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - - let mut builder = client.new_block(Default::default()).unwrap(); - builder.push_transfer(runtime::Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 42, - nonce: 0, - }).unwrap(); - client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - } - - // assert notification sent to transport - let (notification, next) = core.block_on(transport.into_future()).unwrap(); - assert!(notification.is_some()); - // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); -} - -#[test] -fn should_send_initial_storage_changes_and_notifications() { - let mut core = tokio::runtime::Runtime::new().unwrap(); - let remote = core.executor(); - let (subscriber, id, transport) = Subscriber::new_test("test"); - - { - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - - let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())); - - api.subscribe_storage(Default::default(), subscriber, Some(vec![ - StorageKey(alice_balance_key.to_vec()), - ]).into()); - - // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - - let mut builder = client.new_block(Default::default()).unwrap(); - builder.push_transfer(runtime::Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Ferdie.into(), - amount: 42, - nonce: 0, - }).unwrap(); - client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - } - - // assert initial values sent to transport - let (notification, next) = core.block_on(transport.into_future()).unwrap(); - assert!(notification.is_some()); - // assert notification sent to transport - let (notification, next) = core.block_on(next.into_future()).unwrap(); - assert!(notification.is_some()); - // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); -} - -#[test] -fn should_query_storage() { - fn run_tests(client: Arc) { - let core = tokio::runtime::Runtime::new().unwrap(); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); - - let add_block = |nonce| { - let mut builder = client.new_block(Default::default()).unwrap(); - // fake change: None -> None -> None - builder.push_storage_change(vec![1], None).unwrap(); - // fake change: None -> Some(value) -> Some(value) - builder.push_storage_change(vec![2], Some(vec![2])).unwrap(); - // actual change: None -> Some(value) -> None - builder.push_storage_change(vec![3], if nonce == 0 { Some(vec![3]) } else { None }).unwrap(); - // actual change: None -> Some(value) - builder.push_storage_change(vec![4], if nonce == 0 { None } else { Some(vec![4]) }).unwrap(); - // actual change: Some(value1) -> Some(value2) - builder.push_storage_change(vec![5], Some(vec![nonce as u8])).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 mut expected = vec![ - StorageChangeSet { - block: genesis_hash, - changes: vec![ - (StorageKey(vec![1]), None), - (StorageKey(vec![2]), None), - (StorageKey(vec![3]), None), - (StorageKey(vec![4]), None), - (StorageKey(vec![5]), None), - ], - }, - StorageChangeSet { - block: block1_hash, - changes: vec![ - (StorageKey(vec![2]), Some(StorageData(vec![2]))), - (StorageKey(vec![3]), Some(StorageData(vec![3]))), - (StorageKey(vec![5]), Some(StorageData(vec![0]))), - ], - }, - ]; - - // Query changes only up to block1 - let keys = (1..6).map(|k| StorageKey(vec![k])).collect::>(); - let result = api.query_storage( - keys.clone(), - genesis_hash, - Some(block1_hash).into(), - ); - - assert_eq!(result.wait().unwrap(), expected); - - // Query all changes - let result = api.query_storage( - keys.clone(), - genesis_hash, - None.into(), - ); - - expected.push(StorageChangeSet { - block: block2_hash, - changes: vec![ - (StorageKey(vec![3]), None), - (StorageKey(vec![4]), Some(StorageData(vec![4]))), - (StorageKey(vec![5]), Some(StorageData(vec![1]))), - ], - }); - assert_eq!(result.wait().unwrap(), expected); - } - - run_tests(Arc::new(test_client::new())); - run_tests(Arc::new(TestClientBuilder::new().set_support_changes_trie(true).build())); -} - -#[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))); -} - - -#[test] -fn should_return_runtime_version() { - let core = tokio::runtime::Runtime::new().unwrap(); - - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); - - let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ - \"specVersion\":1,\"implVersion\":1,\"apis\":[[\"0xdf6acb689907609b\",2],\ - [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",3],\ - [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\ - [\"0xf78b278be53f454c\",1],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]]}"; - - let runtime_version = api.runtime_version(None.into()).wait().unwrap(); - let serialized = serde_json::to_string(&runtime_version).unwrap(); - assert_eq!(serialized, result); - - let deserialized: RuntimeVersion = serde_json::from_str(result).unwrap(); - assert_eq!(deserialized, runtime_version); -} - -#[test] -fn should_notify_on_runtime_version_initially() { - let mut core = tokio::runtime::Runtime::new().unwrap(); - let (subscriber, id, transport) = Subscriber::new_test("test"); - - { - let client = Arc::new(test_client::new()); - let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); - - api.subscribe_runtime_version(Default::default(), subscriber); - - // assert id assigned - assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - } - - // assert initial version sent. - let (notification, next) = core.block_on(transport.into_future()).unwrap(); - assert!(notification.is_some()); - // no more notifications on this channel - assert_eq!(core.block_on(next.into_future()).unwrap().0, None); -} - -#[test] -fn should_deserialize_storage_key() { - let k = "\"0x7f864e18e3dd8b58386310d2fe0919eef27c6e558564b7f67f22d99d20f587b\""; - let k: StorageKey = serde_json::from_str(k).unwrap(); - - assert_eq!(k.0.len(), 32); -} diff --git a/core/rpc/src/system/mod.rs b/core/rpc/src/system/mod.rs deleted file mode 100644 index 8907151d9ac69..0000000000000 --- a/core/rpc/src/system/mod.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate system API. - -#[cfg(test)] -mod tests; - -use futures03::{channel::{mpsc, oneshot}, compat::Compat}; -use api::Receiver; -use sr_primitives::traits::{self, Header as HeaderT}; -use self::error::Result; - -pub use api::system::*; -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; -pub use self::gen_client::Client as SystemClient; - -/// System API implementation -pub struct System { - info: SystemInfo, - send_back: mpsc::UnboundedSender>, -} - -/// Request to be processed. -pub enum Request { - /// Must return the health of the network. - Health(oneshot::Sender), - /// Must return information about the peers we are connected to. - Peers(oneshot::Sender::Number>>>), - /// Must return the state of the network. - NetworkState(oneshot::Sender), - /// Must return the node role. - NodeRoles(oneshot::Sender>) -} - -impl System { - /// Creates new `System`. - /// - /// The `send_back` will be used to transmit some of the requests. The user is responsible for - /// reading from that channel and answering the requests. - pub fn new( - info: SystemInfo, - send_back: mpsc::UnboundedSender> - ) -> Self { - System { - info, - send_back, - } - } -} - -impl SystemApi::Number> for System { - fn system_name(&self) -> Result { - Ok(self.info.impl_name.clone()) - } - - fn system_version(&self) -> Result { - Ok(self.info.impl_version.clone()) - } - - fn system_chain(&self) -> Result { - Ok(self.info.chain_name.clone()) - } - - fn system_properties(&self) -> Result { - Ok(self.info.properties.clone()) - } - - fn system_health(&self) -> Receiver { - let (tx, rx) = oneshot::channel(); - let _ = self.send_back.unbounded_send(Request::Health(tx)); - Receiver(Compat::new(rx)) - } - - fn system_peers(&self) -> Receiver::Number>>> { - let (tx, rx) = oneshot::channel(); - let _ = self.send_back.unbounded_send(Request::Peers(tx)); - Receiver(Compat::new(rx)) - } - - fn system_network_state(&self) -> Receiver { - let (tx, rx) = oneshot::channel(); - let _ = self.send_back.unbounded_send(Request::NetworkState(tx)); - Receiver(Compat::new(rx)) - } - - fn system_node_roles(&self) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let _ = self.send_back.unbounded_send(Request::NodeRoles(tx)); - Receiver(Compat::new(rx)) - } -} diff --git a/core/rpc/src/system/tests.rs b/core/rpc/src/system/tests.rs deleted file mode 100644 index 1c532be372660..0000000000000 --- a/core/rpc/src/system/tests.rs +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use super::*; - -use network::{self, PeerId}; -use network::config::Roles; -use test_client::runtime::Block; -use assert_matches::assert_matches; -use futures03::{prelude::*, channel::mpsc}; -use std::thread; - -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, - } - } -} - -fn api>>(sync: T) -> System { - let status = sync.into().unwrap_or_default(); - let should_have_peers = !status.is_dev; - let (tx, rx) = mpsc::unbounded(); - thread::spawn(move || { - futures03::executor::block_on(rx.for_each(move |request| { - match request { - Request::Health(sender) => { - let _ = sender.send(Health { - peers: status.peers, - is_syncing: status.is_syncing, - should_have_peers, - }); - }, - Request::Peers(sender) => { - let mut peers = vec![]; - for _peer in 0..status.peers { - peers.push(PeerInfo { - peer_id: status.peer_id.to_base58(), - roles: format!("{:?}", Roles::FULL), - protocol_version: 1, - best_hash: Default::default(), - best_number: 1, - }); - } - let _ = sender.send(peers); - } - Request::NetworkState(sender) => { - let _ = sender.send(serde_json::to_value(&network::NetworkState { - peer_id: String::new(), - listened_addresses: Default::default(), - external_addresses: Default::default(), - connected_peers: Default::default(), - not_connected_peers: Default::default(), - average_download_per_sec: 0, - average_upload_per_sec: 0, - peerset: serde_json::Value::Null, - }).unwrap()); - }, - Request::NodeRoles(sender) => { - let _ = sender.send(vec![NodeRole::Authority]); - } - }; - - future::ready(()) - })) - }); - System::new(SystemInfo { - impl_name: "testclient".into(), - impl_version: "0.2.0".into(), - chain_name: "testchain".into(), - properties: Default::default(), - }, tx) -} - -fn wait_receiver(rx: Receiver) -> T { - let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap(); - runtime.block_on(rx).unwrap() -} - -#[test] -fn system_name_works() { - assert_eq!( - api(None).system_name().unwrap(), - "testclient".to_owned() - ); -} - -#[test] -fn system_version_works() { - assert_eq!( - api(None).system_version().unwrap(), - "0.2.0".to_owned() - ); -} - -#[test] -fn system_chain_works() { - assert_eq!( - api(None).system_chain().unwrap(), - "testchain".to_owned() - ); -} - -#[test] -fn system_properties_works() { - assert_eq!( - api(None).system_properties().unwrap(), - serde_json::map::Map::new() - ); -} - -#[test] -fn system_health() { - assert_matches!( - wait_receiver(api(None).system_health()), - Health { - peers: 0, - is_syncing: false, - should_have_peers: true, - } - ); - - assert_matches!( - wait_receiver(api(Status { - peer_id: PeerId::random(), - peers: 5, - is_syncing: true, - is_dev: true, - }).system_health()), - Health { - peers: 5, - is_syncing: true, - should_have_peers: false, - } - ); - - assert_eq!( - wait_receiver(api(Status { - peer_id: PeerId::random(), - peers: 5, - is_syncing: false, - is_dev: false, - }).system_health()), - Health { - peers: 5, - is_syncing: false, - should_have_peers: true, - } - ); - - assert_eq!( - wait_receiver(api(Status { - peer_id: PeerId::random(), - peers: 0, - is_syncing: false, - is_dev: true, - }).system_health()), - Health { - peers: 0, - is_syncing: false, - should_have_peers: false, - } - ); -} - -#[test] -fn system_peers() { - let peer_id = PeerId::random(); - assert_eq!( - wait_receiver(api(Status { - peer_id: peer_id.clone(), - peers: 1, - is_syncing: false, - is_dev: true, - }).system_peers()), - vec![PeerInfo { - peer_id: peer_id.to_base58(), - roles: "FULL".into(), - protocol_version: 1, - best_hash: Default::default(), - best_number: 1u64, - }] - ); -} - -#[test] -fn system_network_state() { - let res = wait_receiver(api(None).system_network_state()); - assert_eq!( - serde_json::from_value::(res).unwrap(), - network::NetworkState { - peer_id: String::new(), - listened_addresses: Default::default(), - external_addresses: Default::default(), - connected_peers: Default::default(), - not_connected_peers: Default::default(), - average_download_per_sec: 0, - average_upload_per_sec: 0, - peerset: serde_json::Value::Null, - } - ); -} - -#[test] -fn system_node_roles() { - assert_eq!( - wait_receiver(api(None).system_node_roles()), - vec![NodeRole::Authority] - ); -} \ No newline at end of file diff --git a/core/serializer/Cargo.toml b/core/serializer/Cargo.toml deleted file mode 100644 index 4e0e706e2fab2..0000000000000 --- a/core/serializer/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "substrate-serializer" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = "1.0.101" -serde_json = "1.0.41" diff --git a/core/serializer/src/lib.rs b/core/serializer/src/lib.rs deleted file mode 100644 index 2586d49f00599..0000000000000 --- a/core/serializer/src/lib.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate customizable serde serializer. -//! -//! The idea is that we can later change the implementation -//! to something more compact, but for now we're using JSON. - -#![warn(missing_docs)] - -pub use serde_json::{from_str, from_slice, from_reader, Result, Error}; - -const PROOF: &str = "Serializers are infallible; qed"; - -/// Serialize the given data structure as a pretty-printed String of JSON. -pub fn to_string_pretty(value: &T) -> String { - serde_json::to_string_pretty(value).expect(PROOF) -} - -/// Serialize the given data structure as a JSON byte vector. -pub fn encode(value: &T) -> Vec { - serde_json::to_vec(value).expect(PROOF) -} - -/// Serialize the given data structure as JSON into the IO stream. -pub fn to_writer(writer: W, value: &T) -> Result<()> { - serde_json::to_writer(writer, value) -} diff --git a/core/service/Cargo.toml b/core/service/Cargo.toml deleted file mode 100644 index 04371087eff2e..0000000000000 --- a/core/service/Cargo.toml +++ /dev/null @@ -1,52 +0,0 @@ -[package] -name = "substrate-service" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -derive_more = "0.15.0" -futures = "0.1.29" -futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } -parking_lot = "0.9.0" -lazy_static = "1.4.0" -log = "0.4.8" -slog = { version = "2.5.2", features = ["nested-values"] } -tokio-executor = "0.1.8" -tokio-timer = "0.2.11" -exit-future = "0.1.4" -serde = "1.0.101" -serde_json = "1.0.41" -sysinfo = "0.9.5" -target_info = "0.1.0" -keystore = { package = "substrate-keystore", path = "../../core/keystore" } -sr-io = { path = "../../core/sr-io" } -sr-primitives = { path = "../../core/sr-primitives" } -primitives = { package = "substrate-primitives", path = "../primitives" } -session = { package = "substrate-session", path = "../session" } -app-crypto = { package = "substrate-application-crypto", path = "../application-crypto" } -consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } -network = { package = "substrate-network", path = "../../core/network" } -chain-spec = { package = "substrate-chain-spec", path = "../chain-spec" } -client = { package = "substrate-client", path = "../../core/client" } -client_db = { package = "substrate-client-db", path = "../../core/client/db", features = ["kvdb-rocksdb"] } -codec = { package = "parity-scale-codec", version = "1.0.0" } -substrate-executor = { path = "../../core/executor" } -substrate-authority-discovery = { path = "../../core/authority-discovery"} -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } -rpc-servers = { package = "substrate-rpc-servers", path = "../../core/rpc-servers" } -rpc = { package = "substrate-rpc", path = "../../core/rpc" } -tel = { package = "substrate-telemetry", path = "../../core/telemetry" } -offchain = { package = "substrate-offchain", path = "../../core/offchain" } -parity-multiaddr = { package = "parity-multiaddr", version = "0.5.0" } -authority-discovery-primitives = { package = "substrate-authority-discovery-primitives", path = "../authority-discovery/primitives", default-features = false } - -[dev-dependencies] -substrate-test-runtime-client = { path = "../test-runtime/client" } -node-executor = { path = "../../node/executor" } -node-primitives = { path = "../../node/primitives" } -node-runtime = { path = "../../node/runtime" } -babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives" } -grandpa = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa" } -grandpa-primitives = { package = "substrate-finality-grandpa-primitives", path = "../../core/finality-grandpa/primitives" } -tokio = "0.1" diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs deleted file mode 100644 index 052d0cca6bd3d..0000000000000 --- a/core/service/src/builder.rs +++ /dev/null @@ -1,1277 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::{Service, NetworkStatus, NetworkState, error::{self, Error}, DEFAULT_PROTOCOL_ID}; -use crate::{SpawnTaskHandle, start_rpc_servers, build_network_future, TransactionPoolAdapter}; -use crate::status_sinks; -use crate::config::Configuration; -use client::{ - BlockchainEvents, Client, runtime_api, - backend::RemoteBackend, light::blockchain::RemoteBlockchain, -}; -use chain_spec::{RuntimeGenesis, Extension}; -use codec::{Decode, Encode, IoReader}; -use consensus_common::import_queue::ImportQueue; -use futures::{prelude::*, sync::mpsc}; -use futures03::{ - compat::Compat, - future::ready, - FutureExt as _, TryFutureExt as _, - StreamExt as _, TryStreamExt as _, -}; -use keystore::{Store as Keystore}; -use log::{info, warn}; -use network::{FinalityProofProvider, OnDemand, NetworkService, NetworkStateInfo, DhtEvent}; -use network::{config::BoxFinalityProofRequestBuilder, specialization::NetworkSpecialization}; -use parking_lot::{Mutex, RwLock}; -use primitives::{Blake2Hasher, H256, Hasher}; -use rpc; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ - Block as BlockT, Extrinsic, ProvideRuntimeApi, NumberFor, One, Zero, Header, SaturatedConversion -}; -use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; -use std::{io::{Read, Write, Seek}, marker::PhantomData, sync::Arc, sync::atomic::AtomicBool}; -use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; -use tel::{telemetry, SUBSTRATE_INFO}; -use transaction_pool::txpool::{self, ChainApi, Pool as TransactionPool}; - -/// Aggregator for the components required to build a service. -/// -/// # Usage -/// -/// Call [`ServiceBuilder::new_full`] or [`ServiceBuilder::new_light`], then call the various -/// `with_` methods to add the required components that you built yourself: -/// -/// - [`with_select_chain`](ServiceBuilder::with_select_chain) -/// - [`with_import_queue`](ServiceBuilder::with_import_queue) -/// - [`with_network_protocol`](ServiceBuilder::with_network_protocol) -/// - [`with_finality_proof_provider`](ServiceBuilder::with_finality_proof_provider) -/// - [`with_transaction_pool`](ServiceBuilder::with_transaction_pool) -/// -/// After this is done, call [`build`](ServiceBuilder::build) to construct the service. -/// -/// The order in which the `with_*` methods are called doesn't matter, as the correct binding of -/// generics is done when you call `build`. -/// -pub struct ServiceBuilder -{ - config: Configuration, - client: Arc, - backend: Arc, - keystore: Arc>, - fetcher: Option, - select_chain: Option, - import_queue: TImpQu, - finality_proof_request_builder: Option, - finality_proof_provider: Option, - network_protocol: TNetP, - transaction_pool: Arc, - rpc_extensions: TRpc, - remote_backend: Option>>, - dht_event_tx: Option>, - marker: PhantomData<(TBl, TRtApi)>, -} - -/// Full client type. -type TFullClient = Client< - TFullBackend, - TFullCallExecutor, - TBl, - TRtApi, ->; - -/// Full client backend type. -type TFullBackend = client_db::Backend; - -/// Full client call executor type. -type TFullCallExecutor = client::LocalCallExecutor< - client_db::Backend, - NativeExecutor, ->; - -/// Light client type. -type TLightClient = Client< - TLightBackend, - TLightCallExecutor, - TBl, - TRtApi, ->; - -/// Light client backend type. -type TLightBackend = client::light::backend::Backend< - client_db::light::LightStorage, - Blake2Hasher, ->; - -/// Light call executor type. -type TLightCallExecutor = client::light::call_executor::GenesisCallExecutor< - client::light::backend::Backend< - client_db::light::LightStorage, - Blake2Hasher - >, - client::LocalCallExecutor< - client::light::backend::Backend< - client_db::light::LightStorage, - Blake2Hasher - >, - NativeExecutor - >, ->; - -impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), ()> -where TGen: RuntimeGenesis, TCSExt: Extension { - /// Start the service builder with a configuration. - pub fn new_full, TRtApi, TExecDisp: NativeExecutionDispatch>( - config: Configuration - ) -> Result, - Arc>, - (), - (), - BoxFinalityProofRequestBuilder, - Arc>, - (), - (), - (), - TFullBackend, - >, Error> { - let keystore = Keystore::open(config.keystore_path.clone(), config.keystore_password.clone())?; - - let db_settings = client_db::DatabaseSettings { - cache_size: None, - state_cache_size: config.state_cache_size, - state_cache_child_ratio: - config.state_cache_child_ratio.map(|v| (v, 100)), - path: config.database_path.clone(), - pruning: config.pruning.clone(), - }; - - let executor = NativeExecutor::::new( - config.wasm_method, - config.default_heap_pages, - ); - - let fork_blocks = config.chain_spec - .extensions() - .get::>() - .cloned() - .unwrap_or_default(); - - let (client, backend) = client_db::new_client( - db_settings, - executor, - &config.chain_spec, - fork_blocks, - config.execution_strategies.clone(), - Some(keystore.clone()), - )?; - - let client = Arc::new(client); - - Ok(ServiceBuilder { - config, - client, - backend, - keystore, - fetcher: None, - select_chain: None, - import_queue: (), - finality_proof_request_builder: None, - finality_proof_provider: None, - network_protocol: (), - transaction_pool: Arc::new(()), - rpc_extensions: Default::default(), - remote_backend: None, - dht_event_tx: None, - marker: PhantomData, - }) - } - - /// Start the service builder with a configuration. - pub fn new_light, TRtApi, TExecDisp: NativeExecutionDispatch + 'static>( - config: Configuration - ) -> Result, - Arc>, - (), - (), - BoxFinalityProofRequestBuilder, - Arc>, - (), - (), - (), - TLightBackend, - >, Error> { - let keystore = Keystore::open(config.keystore_path.clone(), config.keystore_password.clone())?; - - let db_settings = client_db::DatabaseSettings { - cache_size: config.database_cache_size.map(|u| u as usize), - state_cache_size: config.state_cache_size, - state_cache_child_ratio: - config.state_cache_child_ratio.map(|v| (v, 100)), - path: config.database_path.clone(), - pruning: config.pruning.clone(), - }; - - let executor = NativeExecutor::::new( - config.wasm_method, - config.default_heap_pages, - ); - - let db_storage = client_db::light::LightStorage::new(db_settings)?; - let light_blockchain = client::light::new_light_blockchain(db_storage); - let fetch_checker = Arc::new(client::light::new_fetch_checker(light_blockchain.clone(), executor.clone())); - let fetcher = Arc::new(network::OnDemand::new(fetch_checker)); - let backend = client::light::new_light_backend(light_blockchain); - let remote_blockchain = backend.remote_blockchain(); - let client = Arc::new(client::light::new_light( - backend.clone(), - &config.chain_spec, - executor, - )?); - - Ok(ServiceBuilder { - config, - client, - backend, - keystore, - fetcher: Some(fetcher), - select_chain: None, - import_queue: (), - finality_proof_request_builder: None, - finality_proof_provider: None, - network_protocol: (), - transaction_pool: Arc::new(()), - rpc_extensions: Default::default(), - remote_backend: Some(remote_blockchain), - dht_event_tx: None, - marker: PhantomData, - }) - } -} - -impl - ServiceBuilder { - - /// Returns a reference to the client that was stored in this builder. - pub fn client(&self) -> &Arc { - &self.client - } - - /// Returns a reference to the backend that was used in this builder. - pub fn backend(&self) -> &Arc { - &self.backend - } - - /// Returns a reference to the select-chain that was stored in this builder. - pub fn select_chain(&self) -> Option<&TSc> { - self.select_chain.as_ref() - } - - /// Defines which head-of-chain strategy to use. - pub fn with_opt_select_chain( - self, - select_chain_builder: impl FnOnce( - &Configuration, &Arc - ) -> Result, Error> - ) -> Result, Error> { - let select_chain = select_chain_builder(&self.config, &self.backend)?; - - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - select_chain, - import_queue: self.import_queue, - finality_proof_request_builder: self.finality_proof_request_builder, - finality_proof_provider: self.finality_proof_provider, - network_protocol: self.network_protocol, - transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, - remote_backend: self.remote_backend, - dht_event_tx: self.dht_event_tx, - marker: self.marker, - }) - } - - /// Defines which head-of-chain strategy to use. - pub fn with_select_chain( - self, - builder: impl FnOnce(&Configuration, &Arc) -> Result - ) -> Result, Error> { - self.with_opt_select_chain(|cfg, b| builder(cfg, b).map(Option::Some)) - } - - /// Defines which import queue to use. - pub fn with_import_queue( - self, - builder: impl FnOnce(&Configuration, Arc, Option, Arc) - -> Result - ) -> Result, Error> - where TSc: Clone { - let import_queue = builder( - &self.config, - self.client.clone(), - self.select_chain.clone(), - self.transaction_pool.clone() - )?; - - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - select_chain: self.select_chain, - import_queue, - finality_proof_request_builder: self.finality_proof_request_builder, - finality_proof_provider: self.finality_proof_provider, - network_protocol: self.network_protocol, - transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, - remote_backend: self.remote_backend, - dht_event_tx: self.dht_event_tx, - marker: self.marker, - }) - } - - /// Defines which network specialization protocol to use. - pub fn with_network_protocol( - self, - network_protocol_builder: impl FnOnce(&Configuration) -> Result - ) -> Result, Error> { - let network_protocol = network_protocol_builder(&self.config)?; - - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - select_chain: self.select_chain, - import_queue: self.import_queue, - finality_proof_request_builder: self.finality_proof_request_builder, - finality_proof_provider: self.finality_proof_provider, - network_protocol, - transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, - remote_backend: self.remote_backend, - dht_event_tx: self.dht_event_tx, - marker: self.marker, - }) - } - - /// Defines which strategy to use for providing finality proofs. - pub fn with_opt_finality_proof_provider( - self, - builder: impl FnOnce(Arc, Arc) -> Result>>, Error> - ) -> Result>, - TNetP, - TExPool, - TRpc, - Backend, - >, Error> { - let finality_proof_provider = builder(self.client.clone(), self.backend.clone())?; - - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - select_chain: self.select_chain, - import_queue: self.import_queue, - finality_proof_request_builder: self.finality_proof_request_builder, - finality_proof_provider, - network_protocol: self.network_protocol, - transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, - remote_backend: self.remote_backend, - dht_event_tx: self.dht_event_tx, - marker: self.marker, - }) - } - - /// Defines which strategy to use for providing finality proofs. - pub fn with_finality_proof_provider( - self, - build: impl FnOnce(Arc, Arc) -> Result>, Error> - ) -> Result>, - TNetP, - TExPool, - TRpc, - Backend, - >, Error> { - self.with_opt_finality_proof_provider(|client, backend| build(client, backend).map(Option::Some)) - } - - /// Defines which import queue to use. - pub fn with_import_queue_and_opt_fprb( - self, - builder: impl FnOnce( - &Configuration, - Arc, - Arc, - Option, - Option, - Arc, - ) -> Result<(UImpQu, Option), Error> - ) -> Result, Error> - where TSc: Clone, TFchr: Clone { - let (import_queue, fprb) = builder( - &self.config, - self.client.clone(), - self.backend.clone(), - self.fetcher.clone(), - self.select_chain.clone(), - self.transaction_pool.clone() - )?; - - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - select_chain: self.select_chain, - import_queue, - finality_proof_request_builder: fprb, - finality_proof_provider: self.finality_proof_provider, - network_protocol: self.network_protocol, - transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, - remote_backend: self.remote_backend, - dht_event_tx: self.dht_event_tx, - marker: self.marker, - }) - } - - /// Defines which import queue to use. - pub fn with_import_queue_and_fprb( - self, - builder: impl FnOnce( - &Configuration, - Arc, - Arc, - Option, - Option, - Arc, - ) -> Result<(UImpQu, UFprb), Error> - ) -> Result, Error> - where TSc: Clone, TFchr: Clone { - self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx| - builder(cfg, cl, b, f, sc, tx) - .map(|(q, f)| (q, Some(f))) - ) - } - - /// Defines which transaction pool to use. - pub fn with_transaction_pool( - self, - transaction_pool_builder: impl FnOnce(transaction_pool::txpool::Options, Arc) -> Result - ) -> Result, Error> { - let transaction_pool = transaction_pool_builder(self.config.transaction_pool.clone(), self.client.clone())?; - - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - select_chain: self.select_chain, - import_queue: self.import_queue, - finality_proof_request_builder: self.finality_proof_request_builder, - finality_proof_provider: self.finality_proof_provider, - network_protocol: self.network_protocol, - transaction_pool: Arc::new(transaction_pool), - rpc_extensions: self.rpc_extensions, - remote_backend: self.remote_backend, - dht_event_tx: self.dht_event_tx, - marker: self.marker, - }) - } - - /// Defines the RPC extensions to use. - pub fn with_rpc_extensions( - self, - rpc_ext_builder: impl FnOnce(Arc, Arc) -> URpc - ) -> Result, Error> { - let rpc_extensions = rpc_ext_builder(self.client.clone(), self.transaction_pool.clone()); - - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - select_chain: self.select_chain, - import_queue: self.import_queue, - finality_proof_request_builder: self.finality_proof_request_builder, - finality_proof_provider: self.finality_proof_provider, - network_protocol: self.network_protocol, - transaction_pool: self.transaction_pool, - rpc_extensions, - remote_backend: self.remote_backend, - dht_event_tx: self.dht_event_tx, - marker: self.marker, - }) - } - - /// Adds a dht event sender to builder to be used by the network to send dht events to the authority discovery - /// module. - pub fn with_dht_event_tx( - self, - dht_event_tx: mpsc::Sender, - ) -> Result, Error> { - Ok(ServiceBuilder { - config: self.config, - client: self.client, - backend: self.backend, - keystore: self.keystore, - fetcher: self.fetcher, - select_chain: self.select_chain, - import_queue: self.import_queue, - finality_proof_request_builder: self.finality_proof_request_builder, - finality_proof_provider: self.finality_proof_provider, - network_protocol: self.network_protocol, - transaction_pool: self.transaction_pool, - rpc_extensions: self.rpc_extensions, - remote_backend: self.remote_backend, - dht_event_tx: Some(dht_event_tx), - marker: self.marker, - }) - } -} - -/// Implemented on `ServiceBuilder`. Allows importing blocks once you have given all the required -/// components to the builder. -pub trait ServiceBuilderImport { - /// Starts the process of importing blocks. - fn import_blocks( - self, - exit: impl Future + Send + 'static, - input: impl Read + Seek, - ) -> Result + Send>, Error>; -} - -/// Implemented on `ServiceBuilder`. Allows exporting blocks once you have given all the required -/// components to the builder. -pub trait ServiceBuilderExport { - /// Type of block of the builder. - type Block: BlockT; - - /// Performs the blocks export. - fn export_blocks( - &self, - exit: impl Future + Send + 'static, - output: impl Write, - from: NumberFor, - to: Option>, - json: bool - ) -> Result<(), Error>; -} - -/// Implemented on `ServiceBuilder`. Allows reverting the chain once you have given all the -/// required components to the builder. -pub trait ServiceBuilderRevert { - /// Type of block of the builder. - type Block: BlockT; - - /// Performs a revert of `blocks` bocks. - fn revert_chain( - &self, - blocks: NumberFor - ) -> Result<(), Error>; -} - -impl< - TBl, TRtApi, TCfg, TGen, TCSExt, TBackend, - TExec, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, - TExPool, TRpc, Backend -> ServiceBuilderImport for ServiceBuilder< - TBl, TRtApi, TCfg, TGen, TCSExt, Client, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, Backend -> where - TBl: BlockT::Out>, - TBackend: 'static + client::backend::Backend + Send, - TExec: 'static + client::CallExecutor + Send + Sync + Clone, - TImpQu: 'static + ImportQueue, - TRtApi: 'static + Send + Sync, -{ - fn import_blocks( - self, - exit: impl Future + Send + 'static, - input: impl Read + Seek, - ) -> Result + Send>, Error> { - let client = self.client; - let mut queue = self.import_queue; - import_blocks!(TBl, client, queue, exit, input) - .map(|f| Box::new(f) as Box<_>) - } -} - -impl - ServiceBuilderExport for ServiceBuilder, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TBackend> -where - TBl: BlockT::Out>, - TBackend: 'static + client::backend::Backend + Send, - TExec: 'static + client::CallExecutor + Send + Sync + Clone -{ - type Block = TBl; - - fn export_blocks( - &self, - exit: impl Future + Send + 'static, - mut output: impl Write, - from: NumberFor, - to: Option>, - json: bool - ) -> Result<(), Error> { - let client = &self.client; - export_blocks!(client, exit, output, from, to, json) - } -} - -impl - ServiceBuilderRevert for ServiceBuilder, - TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TBackend> -where - TBl: BlockT::Out>, - TBackend: 'static + client::backend::Backend + Send, - TExec: 'static + client::CallExecutor + Send + Sync + Clone -{ - type Block = TBl; - - fn revert_chain( - &self, - blocks: NumberFor - ) -> Result<(), Error> { - let client = &self.client; - revert_chain!(client, blocks) - } -} - -impl -ServiceBuilder< - TBl, - TRtApi, - TCfg, - TGen, - TCSExt, - Client, - Arc>, - TSc, - TImpQu, - BoxFinalityProofRequestBuilder, - Arc>, - TNetP, - TransactionPool, - TRpc, - TBackend, -> where - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: - runtime_api::Metadata + - offchain::OffchainWorkerApi + - runtime_api::TaggedTransactionQueue + - session::SessionKeys, - TBl: BlockT::Out>, - TRtApi: 'static + Send + Sync, - TCfg: Default, - TGen: RuntimeGenesis, - TCSExt: Extension, - TBackend: 'static + client::backend::Backend + Send, - TExec: 'static + client::CallExecutor + Send + Sync + Clone, - TSc: Clone, - TImpQu: 'static + ImportQueue, - TNetP: NetworkSpecialization, - TExPoolApi: 'static + ChainApi::Hash>, - TRpc: rpc::RpcExtension + Clone, -{ - /// Builds the service. - pub fn build(self) -> Result, - TSc, - NetworkStatus, - NetworkService::Hash>, - TransactionPool, - offchain::OffchainWorkers< - Client, - TBackend::OffchainStorage, - TBl - >, - >, Error> { - let ServiceBuilder { - marker: _, - mut config, - client, - fetcher: on_demand, - backend, - keystore, - select_chain, - import_queue, - finality_proof_request_builder, - finality_proof_provider, - network_protocol, - transaction_pool, - rpc_extensions, - remote_backend, - dht_event_tx, - } = self; - - session::generate_initial_session_keys( - client.clone(), - config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default() - )?; - - let (signal, exit) = exit_future::signal(); - - // List of asynchronous tasks to spawn. We collect them, then spawn them all at once. - let (to_spawn_tx, to_spawn_rx) = - mpsc::unbounded:: + Send>>(); - - let import_queue = Box::new(import_queue); - let chain_info = client.info().chain; - - let version = config.full_version(); - info!("Highest known block at #{}", chain_info.best_number); - telemetry!( - SUBSTRATE_INFO; - "node.start"; - "height" => chain_info.best_number.saturated_into::(), - "best" => ?chain_info.best_hash - ); - - let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { - imports_external_transactions: !config.roles.is_light(), - pool: transaction_pool.clone(), - client: client.clone(), - executor: Arc::new(SpawnTaskHandle { sender: to_spawn_tx.clone(), on_exit: exit.clone() }), - }); - - let protocol_id = { - let protocol_id_full = match config.chain_spec.protocol_id() { - Some(pid) => pid, - None => { - warn!("Using default protocol ID {:?} because none is configured in the \ - chain specs", DEFAULT_PROTOCOL_ID - ); - DEFAULT_PROTOCOL_ID - } - }.as_bytes(); - network::config::ProtocolId::from(protocol_id_full) - }; - - let block_announce_validator = - Box::new(consensus_common::block_validation::DefaultBlockAnnounceValidator::new(client.clone())); - - let network_params = network::config::Params { - roles: config.roles, - network_config: config.network.clone(), - chain: client.clone(), - finality_proof_provider, - finality_proof_request_builder, - on_demand: on_demand.clone(), - transaction_pool: transaction_pool_adapter.clone() as _, - import_queue, - protocol_id, - specialization: network_protocol, - block_announce_validator, - }; - - let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); - let network_mut = network::NetworkWorker::new(network_params)?; - let network = network_mut.service().clone(); - let network_status_sinks = Arc::new(Mutex::new(status_sinks::StatusSinks::new())); - - let offchain_storage = backend.offchain_storage(); - let offchain_workers = match (config.offchain_worker, offchain_storage) { - (true, Some(db)) => { - Some(Arc::new(offchain::OffchainWorkers::new(client.clone(), db))) - }, - (true, None) => { - log::warn!("Offchain workers disabled, due to lack of offchain storage support in backend."); - None - }, - _ => None, - }; - - { - // block notifications - let txpool = Arc::downgrade(&transaction_pool); - let wclient = Arc::downgrade(&client); - let offchain = offchain_workers.as_ref().map(Arc::downgrade); - let to_spawn_tx_ = to_spawn_tx.clone(); - let network_state_info: Arc = network.clone(); - let is_validator = config.roles.is_authority(); - - let events = client.import_notification_stream() - .map(|v| Ok::<_, ()>(v)).compat() - .for_each(move |notification| { - let number = *notification.header.number(); - let txpool = txpool.upgrade(); - - if let (Some(txpool), Some(client)) = (txpool.as_ref(), wclient.upgrade()) { - let future = maintain_transaction_pool( - &BlockId::hash(notification.hash), - &client, - &*txpool, - ¬ification.retracted, - ).map_err(|e| warn!("Pool error processing new block: {:?}", e))?; - let _ = to_spawn_tx_.unbounded_send(future); - } - - let offchain = offchain.as_ref().and_then(|o| o.upgrade()); - if let (Some(txpool), Some(offchain)) = (txpool, offchain) { - let future = offchain.on_block_imported(&number, &txpool, network_state_info.clone(), is_validator) - .map(|()| Ok(())); - let _ = to_spawn_tx_.unbounded_send(Box::new(Compat::new(future))); - } - - Ok(()) - }) - .select(exit.clone()) - .then(|_| Ok(())); - let _ = to_spawn_tx.unbounded_send(Box::new(events)); - } - - { - // extrinsic notifications - let network = Arc::downgrade(&network); - let transaction_pool_ = transaction_pool.clone(); - let events = transaction_pool.import_notification_stream() - .map(|v| Ok::<_, ()>(v)).compat() - .for_each(move |_| { - if let Some(network) = network.upgrade() { - network.trigger_repropagate(); - } - let status = transaction_pool_.status(); - telemetry!(SUBSTRATE_INFO; "txpool.import"; - "ready" => status.ready, - "future" => status.future - ); - Ok(()) - }) - .select(exit.clone()) - .then(|_| Ok(())); - - let _ = to_spawn_tx.unbounded_send(Box::new(events)); - } - - // Periodically notify the telemetry. - let transaction_pool_ = transaction_pool.clone(); - let client_ = client.clone(); - let mut sys = System::new(); - let self_pid = get_current_pid().ok(); - let (state_tx, state_rx) = mpsc::unbounded::<(NetworkStatus<_>, NetworkState)>(); - network_status_sinks.lock().push(std::time::Duration::from_millis(5000), state_tx); - let tel_task = state_rx.for_each(move |(net_status, _)| { - let info = client_.info(); - let best_number = info.chain.best_number.saturated_into::(); - let best_hash = info.chain.best_hash; - let num_peers = net_status.num_connected_peers; - let txpool_status = transaction_pool_.status(); - let finalized_number: u64 = info.chain.finalized_number.saturated_into::(); - let bandwidth_download = net_status.average_download_per_sec; - let bandwidth_upload = net_status.average_upload_per_sec; - - let used_state_cache_size = match info.used_state_cache_size { - Some(size) => size, - None => 0, - }; - - // get cpu usage and memory usage of this process - let (cpu_usage, memory) = if let Some(self_pid) = self_pid { - if sys.refresh_process(self_pid) { - let proc = sys.get_process(self_pid) - .expect("Above refresh_process succeeds, this should be Some(), qed"); - (proc.cpu_usage(), proc.memory()) - } else { (0.0, 0) } - } else { (0.0, 0) }; - - telemetry!( - SUBSTRATE_INFO; - "system.interval"; - "peers" => num_peers, - "height" => best_number, - "best" => ?best_hash, - "txcount" => txpool_status.ready, - "cpu" => cpu_usage, - "memory" => memory, - "finalized_height" => finalized_number, - "finalized_hash" => ?info.chain.finalized_hash, - "bandwidth_download" => bandwidth_download, - "bandwidth_upload" => bandwidth_upload, - "used_state_cache_size" => used_state_cache_size, - ); - - Ok(()) - }).select(exit.clone()).then(|_| Ok(())); - let _ = to_spawn_tx.unbounded_send(Box::new(tel_task)); - - // Periodically send the network state to the telemetry. - let (netstat_tx, netstat_rx) = mpsc::unbounded::<(NetworkStatus<_>, NetworkState)>(); - network_status_sinks.lock().push(std::time::Duration::from_secs(30), netstat_tx); - let tel_task_2 = netstat_rx.for_each(move |(_, network_state)| { - telemetry!( - SUBSTRATE_INFO; - "system.network_state"; - "state" => network_state, - ); - Ok(()) - }).select(exit.clone()).then(|_| Ok(())); - let _ = to_spawn_tx.unbounded_send(Box::new(tel_task_2)); - - // RPC - let (system_rpc_tx, system_rpc_rx) = futures03::channel::mpsc::unbounded(); - let gen_handler = || { - use rpc::{chain, state, author, system}; - - let system_info = rpc::system::SystemInfo { - chain_name: config.chain_spec.name().into(), - impl_name: config.impl_name.into(), - impl_version: config.impl_version.into(), - properties: config.chain_spec.properties().clone(), - }; - - let subscriptions = rpc::Subscriptions::new(Arc::new(SpawnTaskHandle { - sender: to_spawn_tx.clone(), - on_exit: exit.clone() - })); - - let (chain, state) = if let (Some(remote_backend), Some(on_demand)) = - (remote_backend.as_ref(), on_demand.as_ref()) { - // Light clients - let chain = rpc::chain::new_light( - client.clone(), - subscriptions.clone(), - remote_backend.clone(), - on_demand.clone() - ); - let state = rpc::state::new_light( - client.clone(), - subscriptions.clone(), - remote_backend.clone(), - on_demand.clone() - ); - (chain, state) - - } else { - // Full nodes - let chain = rpc::chain::new_full(client.clone(), subscriptions.clone()); - let state = rpc::state::new_full(client.clone(), subscriptions.clone()); - (chain, state) - }; - - let author = rpc::author::Author::new( - client.clone(), - transaction_pool.clone(), - subscriptions, - keystore.clone(), - ); - let system = system::System::new(system_info, system_rpc_tx.clone()); - - rpc_servers::rpc_handler(( - state::StateApi::to_delegate(state), - chain::ChainApi::to_delegate(chain), - author::AuthorApi::to_delegate(author), - system::SystemApi::to_delegate(system), - rpc_extensions.clone(), - )) - }; - let rpc_handlers = gen_handler(); - let rpc = start_rpc_servers(&config, gen_handler)?; - - - let _ = to_spawn_tx.unbounded_send(Box::new(build_network_future( - config.roles, - network_mut, - client.clone(), - network_status_sinks.clone(), - system_rpc_rx, - has_bootnodes, - dht_event_tx, - ) - .map_err(|_| ()) - .select(exit.clone()) - .then(|_| Ok(())))); - - let telemetry_connection_sinks: Arc>>> = Default::default(); - - // Telemetry - let telemetry = config.telemetry_endpoints.clone().map(|endpoints| { - let is_authority = config.roles.is_authority(); - let network_id = network.local_peer_id().to_base58(); - let name = config.name.clone(); - let impl_name = config.impl_name.to_owned(); - let version = version.clone(); - let chain_name = config.chain_spec.name().to_owned(); - let telemetry_connection_sinks_ = telemetry_connection_sinks.clone(); - let telemetry = tel::init_telemetry(tel::TelemetryConfig { - endpoints, - wasm_external_transport: config.telemetry_external_transport.take(), - }); - let future = telemetry.clone() - .map(|ev| Ok::<_, ()>(ev)) - .compat() - .for_each(move |event| { - // Safe-guard in case we add more events in the future. - let tel::TelemetryEvent::Connected = event; - - telemetry!(SUBSTRATE_INFO; "system.connected"; - "name" => name.clone(), - "implementation" => impl_name.clone(), - "version" => version.clone(), - "config" => "", - "chain" => chain_name.clone(), - "authority" => is_authority, - "network_id" => network_id.clone() - ); - - telemetry_connection_sinks_.lock().retain(|sink| { - sink.unbounded_send(()).is_ok() - }); - Ok(()) - }); - let _ = to_spawn_tx.unbounded_send(Box::new(future - .select(exit.clone()) - .then(|_| Ok(())))); - telemetry - }); - - Ok(Service { - client, - network, - network_status_sinks, - select_chain, - transaction_pool, - exit, - signal: Some(signal), - essential_failed: Arc::new(AtomicBool::new(false)), - to_spawn_tx, - to_spawn_rx, - to_poll: Vec::new(), - rpc_handlers, - _rpc: rpc, - _telemetry: telemetry, - _offchain_workers: offchain_workers, - _telemetry_on_connect_sinks: telemetry_connection_sinks.clone(), - keystore, - marker: PhantomData::, - }) - } -} - -pub(crate) fn maintain_transaction_pool( - id: &BlockId, - client: &Arc>, - transaction_pool: &TransactionPool, - retracted: &[Block::Hash], -) -> error::Result + Send>> where - Block: BlockT::Out>, - Backend: 'static + client::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, - Executor: 'static + client::CallExecutor, - PoolApi: 'static + txpool::ChainApi, - Api: 'static, -{ - // Put transactions from retracted blocks back into the pool. - let client_copy = client.clone(); - let retracted_transactions = retracted.to_vec().into_iter() - .filter_map(move |hash| client_copy.block(&BlockId::hash(hash)).ok().unwrap_or(None)) - .flat_map(|block| block.block.deconstruct().1.into_iter()) - .filter(|tx| tx.is_signed().unwrap_or(false)); - let resubmit_future = transaction_pool - .submit_at(id, retracted_transactions, true) - .then(|resubmit_result| ready(match resubmit_result { - Ok(_) => Ok(()), - Err(e) => { - warn!("Error re-submitting transactions: {:?}", e); - Ok(()) - } - })) - .compat(); - - // Avoid calling into runtime if there is nothing to prune from the pool anyway. - if transaction_pool.status().is_empty() { - return Ok(Box::new(resubmit_future)) - } - - let block = client.block(id)?; - Ok(match block { - Some(block) => { - let parent_id = BlockId::hash(*block.block.header().parent_hash()); - let prune_future = transaction_pool - .prune(id, &parent_id, block.block.extrinsics()) - .boxed() - .compat() - .map_err(|e| { format!("{:?}", e); }); - - Box::new(resubmit_future.and_then(|_| prune_future)) - }, - None => Box::new(resubmit_future), - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use futures03::executor::block_on; - use consensus_common::{BlockOrigin, SelectChain}; - use substrate_test_runtime_client::{prelude::*, runtime::Transfer}; - - #[test] - fn should_remove_transactions_from_the_pool() { - let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); - let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); - let transaction = Transfer { - amount: 5, - nonce: 0, - from: AccountKeyring::Alice.into(), - to: Default::default(), - }.into_signed_tx(); - let best = longest_chain.best_chain().unwrap(); - - // store the transaction in the pool - block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); - - // import the block - let mut builder = client.new_block(Default::default()).unwrap(); - builder.push(transaction.clone()).unwrap(); - let block = builder.bake().unwrap(); - let id = BlockId::hash(block.header().hash()); - client.import(BlockOrigin::Own, block).unwrap(); - - // fire notification - this should clean up the queue - assert_eq!(pool.status().ready, 1); - maintain_transaction_pool( - &id, - &client, - &pool, - &[] - ).unwrap().wait().unwrap(); - - // then - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - } - - #[test] - fn should_add_reverted_transactions_to_the_pool() { - let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); - let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); - let transaction = Transfer { - amount: 5, - nonce: 0, - from: AccountKeyring::Alice.into(), - to: Default::default(), - }.into_signed_tx(); - let best = longest_chain.best_chain().unwrap(); - - // store the transaction in the pool - block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); - - // import the block - let mut builder = client.new_block(Default::default()).unwrap(); - builder.push(transaction.clone()).unwrap(); - let block = builder.bake().unwrap(); - let block1_hash = block.header().hash(); - let id = BlockId::hash(block1_hash.clone()); - client.import(BlockOrigin::Own, block).unwrap(); - - // fire notification - this should clean up the queue - assert_eq!(pool.status().ready, 1); - maintain_transaction_pool( - &id, - &client, - &pool, - &[] - ).unwrap().wait().unwrap(); - - // then - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - - // import second block - let builder = client.new_block_at(&BlockId::hash(best.hash()), Default::default()).unwrap(); - let block = builder.bake().unwrap(); - let id = BlockId::hash(block.header().hash()); - client.import(BlockOrigin::Own, block).unwrap(); - - // fire notification - this should add the transaction back to the pool. - maintain_transaction_pool( - &id, - &client, - &pool, - &[block1_hash] - ).unwrap().wait().unwrap(); - - // then - assert_eq!(pool.status().ready, 1); - assert_eq!(pool.status().future, 0); - } -} diff --git a/core/service/src/chain_ops.rs b/core/service/src/chain_ops.rs deleted file mode 100644 index e6d7df33c2a1d..0000000000000 --- a/core/service/src/chain_ops.rs +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Chain utilities. - -use crate::error; -use chain_spec::{ChainSpec, RuntimeGenesis, Extension}; - -/// Defines the logic for an operation exporting blocks within a range. -#[macro_export] -/// Export blocks -macro_rules! export_blocks { -($client:ident, $exit:ident, $output:ident, $from:ident, $to:ident, $json:ident) => {{ - let mut block = $from; - - let last = match $to { - Some(v) if v.is_zero() => One::one(), - Some(v) => v, - None => $client.info().chain.best_number, - }; - - if last < block { - return Err("Invalid block range specified".into()); - } - - let (exit_send, exit_recv) = std::sync::mpsc::channel(); - std::thread::spawn(move || { - let _ = $exit.wait(); - let _ = exit_send.send(()); - }); - info!("Exporting blocks from #{} to #{}", block, last); - if !$json { - let last_: u64 = last.saturated_into::(); - let block_: u64 = block.saturated_into::(); - let len: u64 = last_ - block_ + 1; - $output.write_all(&len.encode())?; - } - - loop { - if exit_recv.try_recv().is_ok() { - break; - } - match $client.block(&BlockId::number(block))? { - Some(block) => { - if $json { - serde_json::to_writer(&mut $output, &block) - .map_err(|e| format!("Error writing JSON: {}", e))?; - } else { - $output.write_all(&block.encode())?; - } - }, - None => break, - } - if (block % 10000.into()).is_zero() { - info!("#{}", block); - } - if block == last { - break; - } - block += One::one(); - } - Ok(()) -}} -} - -/// Defines the logic for an operation importing blocks from some known import. -#[macro_export] -/// Import blocks -macro_rules! import_blocks { -($block:ty, $client:ident, $queue:ident, $exit:ident, $input:ident) => {{ - use consensus_common::import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult}; - use consensus_common::BlockOrigin; - use network::message; - use sr_primitives::generic::SignedBlock; - use sr_primitives::traits::Block; - use futures03::TryFutureExt as _; - - struct WaitLink { - imported_blocks: u64, - has_error: bool, - } - - impl WaitLink { - fn new() -> WaitLink { - WaitLink { - imported_blocks: 0, - has_error: false, - } - } - } - - impl Link for WaitLink { - fn blocks_processed( - &mut self, - imported: usize, - _count: usize, - results: Vec<(Result>, BlockImportError>, B::Hash)> - ) { - self.imported_blocks += imported as u64; - - for result in results { - if let (Err(err), hash) = result { - warn!("There was an error importing block with hash {:?}: {:?}", hash, err); - self.has_error = true; - break; - } - } - } - } - - let (exit_send, exit_recv) = std::sync::mpsc::channel(); - std::thread::spawn(move || { - let _ = $exit.wait(); - let _ = exit_send.send(()); - }); - - let mut io_reader_input = IoReader($input); - let count: u64 = Decode::decode(&mut io_reader_input) - .map_err(|e| format!("Error reading file: {}", e))?; - info!("Importing {} blocks", count); - let mut block_count = 0; - for b in 0 .. count { - if exit_recv.try_recv().is_ok() { - break; - } - match SignedBlock::<$block>::decode(&mut io_reader_input) { - Ok(signed) => { - let (header, extrinsics) = signed.block.deconstruct(); - let hash = header.hash(); - let block = message::BlockData::<$block> { - hash, - justification: signed.justification, - header: Some(header), - body: Some(extrinsics), - receipt: None, - message_queue: None - }; - // import queue handles verification and importing it into the client - $queue.import_blocks(BlockOrigin::File, vec![ - IncomingBlock::<$block> { - hash: block.hash, - header: block.header, - body: block.body, - justification: block.justification, - origin: None, - } - ]); - } - Err(e) => { - warn!("Error reading block data at {}: {}", b, e); - break; - } - } - - block_count = b; - if b % 1000 == 0 && b != 0 { - info!("#{} blocks were added to the queue", b); - } - } - - let mut link = WaitLink::new(); - Ok(futures::future::poll_fn(move || { - if exit_recv.try_recv().is_ok() { - return Ok(Async::Ready(())); - } - - let blocks_before = link.imported_blocks; - let _ = futures03::future::poll_fn(|cx| { - $queue.poll_actions(cx, &mut link); - std::task::Poll::Pending::> - }).compat().poll(); - if link.has_error { - info!( - "Stopping after #{} blocks because of an error", - link.imported_blocks, - ); - return Ok(Async::Ready(())); - } - if link.imported_blocks / 1000 != blocks_before / 1000 { - info!( - "#{} blocks were imported (#{} left)", - link.imported_blocks, - count - link.imported_blocks - ); - } - if link.imported_blocks >= count { - info!("Imported {} blocks. Best: #{}", block_count, $client.info().chain.best_number); - Ok(Async::Ready(())) - } else { - Ok(Async::NotReady) - } - })) -}} -} - -/// Revert the chain some number of blocks. -#[macro_export] -macro_rules! revert_chain { -($client:ident, $blocks:ident) => {{ - let reverted = $client.revert($blocks)?; - let info = $client.info().chain; - - if reverted.is_zero() { - info!("There aren't any non-finalized blocks to revert."); - } else { - info!("Reverted {} blocks. Best: #{} ({})", reverted, info.best_number, info.best_hash); - } - Ok(()) -}} -} - -/// Build a chain spec json -pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result where - G: RuntimeGenesis, - E: Extension, -{ - Ok(spec.to_json(raw)?) -} diff --git a/core/service/src/config.rs b/core/service/src/config.rs deleted file mode 100644 index a1ba83753f402..0000000000000 --- a/core/service/src/config.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Service configuration. - -pub use client::ExecutionStrategies; -pub use client_db::PruningMode; -pub use network::config::{ExtTransport, NetworkConfiguration, Roles}; -pub use substrate_executor::WasmExecutionMethod; - -use std::{path::PathBuf, net::SocketAddr}; -use transaction_pool; -use chain_spec::{ChainSpec, RuntimeGenesis, Extension, NoExtension}; -use primitives::crypto::Protected; -use target_info::Target; -use tel::TelemetryEndpoints; - -/// Service configuration. -#[derive(Clone)] -pub struct Configuration { - /// Implementation name - pub impl_name: &'static str, - /// Implementation version - pub impl_version: &'static str, - /// Git commit if any. - pub impl_commit: &'static str, - /// Node roles. - pub roles: Roles, - /// Extrinsic pool configuration. - pub transaction_pool: transaction_pool::txpool::Options, - /// Network configuration. - pub network: NetworkConfiguration, - /// Path to key files. - pub keystore_path: PathBuf, - /// Path to the database. - pub database_path: PathBuf, - /// Cache Size for internal database in MiB - pub database_cache_size: Option, - /// Size of internal state cache in Bytes - pub state_cache_size: usize, - /// Size in percent of cache size dedicated to child tries - pub state_cache_child_ratio: Option, - /// Pruning settings. - pub pruning: PruningMode, - /// Chain configuration. - pub chain_spec: ChainSpec, - /// Custom configuration. - pub custom: C, - /// Node name. - pub name: String, - /// Wasm execution method. - pub wasm_method: WasmExecutionMethod, - /// Execution strategies. - pub execution_strategies: ExecutionStrategies, - /// RPC over HTTP binding address. `None` if disabled. - pub rpc_http: Option, - /// RPC over Websockets binding address. `None` if disabled. - pub rpc_ws: Option, - /// Maximum number of connections for WebSockets RPC server. `None` if default. - pub rpc_ws_max_connections: Option, - /// CORS settings for HTTP & WS servers. `None` if all origins are allowed. - pub rpc_cors: Option>, - /// Telemetry service URL. `None` if disabled. - pub telemetry_endpoints: Option, - /// External WASM transport for the telemetry. If `Some`, when connection to a telemetry - /// endpoint, this transport will be tried in priority before all others. - pub telemetry_external_transport: Option, - /// The default number of 64KB pages to allocate for Wasm execution - pub default_heap_pages: Option, - /// Should offchain workers be executed. - pub offchain_worker: bool, - /// Enable authoring even when offline. - pub force_authoring: bool, - /// Disable GRANDPA when running in validator mode - pub disable_grandpa: bool, - /// Node keystore's password - pub keystore_password: Option>, - /// Development key seed. - /// - /// When running in development mode, the seed will be used to generate authority keys by the keystore. - /// - /// Should only be set when `node` is running development mode. - pub dev_key_seed: Option, -} - -impl Configuration where - C: Default, - G: RuntimeGenesis, - E: Extension, -{ - /// Create default config for given chain spec. - pub fn default_with_spec(chain_spec: ChainSpec) -> Self { - let mut configuration = Configuration { - impl_name: "parity-substrate", - impl_version: "0.0.0", - impl_commit: "", - chain_spec, - name: Default::default(), - roles: Roles::FULL, - transaction_pool: Default::default(), - network: Default::default(), - keystore_path: Default::default(), - database_path: Default::default(), - database_cache_size: Default::default(), - state_cache_size: Default::default(), - state_cache_child_ratio: Default::default(), - custom: Default::default(), - pruning: PruningMode::default(), - wasm_method: WasmExecutionMethod::Interpreted, - execution_strategies: Default::default(), - rpc_http: None, - rpc_ws: None, - rpc_ws_max_connections: None, - rpc_cors: Some(vec![]), - telemetry_endpoints: None, - telemetry_external_transport: None, - default_heap_pages: None, - offchain_worker: Default::default(), - force_authoring: false, - disable_grandpa: false, - keystore_password: None, - dev_key_seed: None, - }; - configuration.network.boot_nodes = configuration.chain_spec.boot_nodes().to_vec(); - - configuration.telemetry_endpoints = configuration.chain_spec.telemetry_endpoints().clone(); - - configuration - } - - /// Returns full version string of this configuration. - pub fn full_version(&self) -> String { - full_version_from_strs(self.impl_version, self.impl_commit) - } - - /// Implementation id and version. - pub fn client_id(&self) -> String { - format!("{}/v{}", self.impl_name, self.full_version()) - } -} - -/// Returns platform info -pub fn platform() -> String { - let env = Target::env(); - let env_dash = if env.is_empty() { "" } else { "-" }; - format!("{}-{}{}{}", Target::arch(), Target::os(), env_dash, env) -} - -/// Returns full version string, using supplied version and commit. -pub fn full_version_from_strs(impl_version: &str, impl_commit: &str) -> String { - let commit_dash = if impl_commit.is_empty() { "" } else { "-" }; - format!("{}{}{}-{}", impl_version, commit_dash, impl_commit, platform()) -} diff --git a/core/service/src/error.rs b/core/service/src/error.rs deleted file mode 100644 index 85a6892b264e1..0000000000000 --- a/core/service/src/error.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Errors that can occur during the service operation. - -use client; -use network; -use keystore; -use consensus_common; - -/// Service Result typedef. -pub type Result = std::result::Result; - -/// Service errors. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Client error. - Client(client::error::Error), - /// IO error. - Io(std::io::Error), - /// Consensus error. - Consensus(consensus_common::Error), - /// Network error. - Network(network::error::Error), - /// Keystore error. - Keystore(keystore::Error), - /// Best chain selection strategy is missing. - #[display(fmt="Best chain selection strategy (SelectChain) is not provided.")] - SelectChainRequired, - /// Other error. - Other(String), -} - -impl<'a> From<&'a str> for Error { - fn from(s: &'a str) -> Self { - Error::Other(s.into()) - } -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Client(ref err) => Some(err), - Error::Io(ref err) => Some(err), - Error::Consensus(ref err) => Some(err), - Error::Network(ref err) => Some(err), - Error::Keystore(ref err) => Some(err), - _ => None, - } - } -} diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs deleted file mode 100644 index 7f01073b2ee3a..0000000000000 --- a/core/service/src/lib.rs +++ /dev/null @@ -1,692 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate service. Starts a thread that spins up the network, client, and extrinsic pool. -//! Manages communication between them. - -#![warn(missing_docs)] - -pub mod config; -#[macro_use] -pub mod chain_ops; -pub mod error; - -mod builder; -mod status_sinks; - -use std::io; -use std::marker::PhantomData; -use std::net::SocketAddr; -use std::collections::HashMap; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::time::{Duration, Instant}; -use futures::sync::mpsc; -use parking_lot::Mutex; - -use client::{runtime_api::BlockT, Client}; -use exit_future::Signal; -use futures::prelude::*; -use futures03::{ - future::{ready, FutureExt as _, TryFutureExt as _}, - stream::{StreamExt as _, TryStreamExt as _}, -}; -use network::{ - NetworkService, NetworkState, specialization::NetworkSpecialization, - Event, DhtEvent, PeerId, ReportHandle, -}; -use log::{log, warn, debug, error, Level}; -use codec::{Encode, Decode}; -use primitives::{Blake2Hasher, H256}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::NumberFor; - -pub use self::error::Error; -pub use self::builder::{ServiceBuilder, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert}; -pub use config::{Configuration, Roles, PruningMode}; -pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension}; -pub use transaction_pool::txpool::{ - self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError -}; -pub use client::FinalityNotifications; -pub use rpc::Metadata as RpcMetadata; -#[doc(hidden)] -pub use std::{ops::Deref, result::Result, sync::Arc}; -#[doc(hidden)] -pub use network::{FinalityProofProvider, OnDemand, config::BoxFinalityProofRequestBuilder}; -#[doc(hidden)] -pub use futures::future::Executor; - -const DEFAULT_PROTOCOL_ID: &str = "sup"; - -/// Substrate service. -pub struct Service { - client: Arc, - select_chain: Option, - network: Arc, - /// Sinks to propagate network status updates. - /// For each element, every time the `Interval` fires we push an element on the sender. - network_status_sinks: Arc>>, - transaction_pool: Arc, - /// A future that resolves when the service has exited, this is useful to - /// make sure any internally spawned futures stop when the service does. - exit: exit_future::Exit, - /// A signal that makes the exit future above resolve, fired on service drop. - signal: Option, - /// Set to `true` when a spawned essential task has failed. The next time - /// the service future is polled it should complete with an error. - essential_failed: Arc, - /// Sender for futures that must be spawned as background tasks. - to_spawn_tx: mpsc::UnboundedSender + Send>>, - /// Receiver for futures that must be spawned as background tasks. - to_spawn_rx: mpsc::UnboundedReceiver + Send>>, - /// List of futures to poll from `poll`. - /// If spawning a background task is not possible, we instead push the task into this `Vec`. - /// The elements must then be polled manually. - to_poll: Vec + Send>>, - rpc_handlers: rpc_servers::RpcHandler, - _rpc: Box, - _telemetry: Option, - _telemetry_on_connect_sinks: Arc>>>, - _offchain_workers: Option>, - keystore: keystore::KeyStorePtr, - marker: PhantomData, -} - -/// Alias for a an implementation of `futures::future::Executor`. -pub type TaskExecutor = Arc + Send>> + Send + Sync>; - -/// An handle for spawning tasks in the service. -#[derive(Clone)] -pub struct SpawnTaskHandle { - sender: mpsc::UnboundedSender + Send>>, - on_exit: exit_future::Exit, -} - -impl Executor + Send>> for SpawnTaskHandle { - fn execute( - &self, - future: Box + Send>, - ) -> Result<(), futures::future::ExecuteError + Send>>> { - let future = Box::new(future.select(self.on_exit.clone()).then(|_| Ok(()))); - if let Err(err) = self.sender.unbounded_send(future) { - let kind = futures::future::ExecuteErrorKind::Shutdown; - Err(futures::future::ExecuteError::new(kind, err.into_inner())) - } else { - Ok(()) - } - } -} - -/// Abstraction over a Substrate service. -pub trait AbstractService: 'static + Future + - Executor + Send>> + Send { - /// Type of block of this chain. - type Block: BlockT; - /// Backend storage for the client. - type Backend: 'static + client::backend::Backend; - /// How to execute calls towards the runtime. - type CallExecutor: 'static + client::CallExecutor + Send + Sync + Clone; - /// API that the runtime provides. - type RuntimeApi: Send + Sync; - /// Chain selection algorithm. - type SelectChain: consensus_common::SelectChain; - /// API of the transaction pool. - type TransactionPoolApi: ChainApi; - /// Network specialization. - type NetworkSpecialization: NetworkSpecialization; - - /// Get event stream for telemetry connection established events. - fn telemetry_on_connect_stream(&self) -> futures03::channel::mpsc::UnboundedReceiver<()>; - - /// return a shared instance of Telemetry (if enabled) - fn telemetry(&self) -> Option; - - /// Spawns a task in the background that runs the future passed as parameter. - fn spawn_task(&self, task: impl Future + Send + 'static); - - /// Spawns a task in the background that runs the future passed as - /// parameter. The given task is considered essential, i.e. if it errors we - /// trigger a service exit. - fn spawn_essential_task(&self, task: impl Future + Send + 'static); - - /// Returns a handle for spawning tasks. - fn spawn_task_handle(&self) -> SpawnTaskHandle; - - /// Returns the keystore that stores keys. - fn keystore(&self) -> keystore::KeyStorePtr; - - /// Starts an RPC query. - /// - /// The query is passed as a string and must be a JSON text similar to what an HTTP client - /// would for example send. - /// - /// Returns a `Future` that contains the optional response. - /// - /// If the request subscribes you to events, the `Sender` in the `RpcSession` object is used to - /// send back spontaneous events. - fn rpc_query(&self, mem: &RpcSession, request: &str) -> Box, Error = ()> + Send>; - - /// Get shared client instance. - fn client(&self) -> Arc>; - - /// Get clone of select chain. - fn select_chain(&self) -> Option; - - /// Get shared network instance. - fn network(&self) -> Arc>; - - /// Returns a receiver that periodically receives a status of the network. - fn network_status(&self, interval: Duration) -> mpsc::UnboundedReceiver<(NetworkStatus, NetworkState)>; - - /// Get shared transaction pool instance. - fn transaction_pool(&self) -> Arc>; - - /// Get a handle to a future that will resolve on exit. - fn on_exit(&self) -> ::exit_future::Exit; -} - -impl AbstractService for - Service, TSc, NetworkStatus, - NetworkService, TransactionPool, TOc> -where - TBl: BlockT, - TBackend: 'static + client::backend::Backend, - TExec: 'static + client::CallExecutor + Send + Sync + Clone, - TRtApi: 'static + Send + Sync, - TSc: consensus_common::SelectChain + 'static + Clone + Send, - TExPoolApi: 'static + ChainApi, - TOc: 'static + Send + Sync, - TNetSpec: NetworkSpecialization, -{ - type Block = TBl; - type Backend = TBackend; - type CallExecutor = TExec; - type RuntimeApi = TRtApi; - type SelectChain = TSc; - type TransactionPoolApi = TExPoolApi; - type NetworkSpecialization = TNetSpec; - - fn telemetry_on_connect_stream(&self) -> futures03::channel::mpsc::UnboundedReceiver<()> { - let (sink, stream) = futures03::channel::mpsc::unbounded(); - self._telemetry_on_connect_sinks.lock().push(sink); - stream - } - - fn telemetry(&self) -> Option { - self._telemetry.as_ref().map(|t| t.clone()) - } - - fn keystore(&self) -> keystore::KeyStorePtr { - self.keystore.clone() - } - - fn spawn_task(&self, task: impl Future + Send + 'static) { - let task = task.select(self.on_exit()).then(|_| Ok(())); - let _ = self.to_spawn_tx.unbounded_send(Box::new(task)); - } - - fn spawn_essential_task(&self, task: impl Future + Send + 'static) { - let essential_failed = self.essential_failed.clone(); - let essential_task = task.map_err(move |_| { - error!("Essential task failed. Shutting down service."); - essential_failed.store(true, Ordering::Relaxed); - }); - let task = essential_task.select(self.on_exit()).then(|_| Ok(())); - - let _ = self.to_spawn_tx.unbounded_send(Box::new(task)); - } - - fn spawn_task_handle(&self) -> SpawnTaskHandle { - SpawnTaskHandle { - sender: self.to_spawn_tx.clone(), - on_exit: self.on_exit(), - } - } - - fn rpc_query(&self, mem: &RpcSession, request: &str) -> Box, Error = ()> + Send> { - Box::new(self.rpc_handlers.handle_request(request, mem.metadata.clone())) - } - - fn client(&self) -> Arc> { - self.client.clone() - } - - fn select_chain(&self) -> Option { - self.select_chain.clone() - } - - fn network(&self) -> Arc> { - self.network.clone() - } - - fn network_status(&self, interval: Duration) -> mpsc::UnboundedReceiver<(NetworkStatus, NetworkState)> { - let (sink, stream) = mpsc::unbounded(); - self.network_status_sinks.lock().push(interval, sink); - stream - } - - fn transaction_pool(&self) -> Arc> { - self.transaction_pool.clone() - } - - fn on_exit(&self) -> exit_future::Exit { - self.exit.clone() - } -} - -impl Future for - Service -{ - type Item = (); - type Error = Error; - - fn poll(&mut self) -> Poll { - if self.essential_failed.load(Ordering::Relaxed) { - return Err(Error::Other("Essential task failed.".into())); - } - - while let Ok(Async::Ready(Some(task_to_spawn))) = self.to_spawn_rx.poll() { - let executor = tokio_executor::DefaultExecutor::current(); - if let Err(err) = executor.execute(task_to_spawn) { - debug!( - target: "service", - "Failed to spawn background task: {:?}; falling back to manual polling", - err - ); - self.to_poll.push(err.into_future()); - } - } - - // Polling all the `to_poll` futures. - while let Some(pos) = self.to_poll.iter_mut().position(|t| t.poll().map(|t| t.is_ready()).unwrap_or(true)) { - let _ = self.to_poll.remove(pos); - } - - // The service future never ends. - Ok(Async::NotReady) - } -} - -impl Executor + Send>> for - Service -{ - fn execute( - &self, - future: Box + Send> - ) -> Result<(), futures::future::ExecuteError + Send>>> { - if let Err(err) = self.to_spawn_tx.unbounded_send(future) { - let kind = futures::future::ExecuteErrorKind::Shutdown; - Err(futures::future::ExecuteError::new(kind, err.into_inner())) - } else { - Ok(()) - } - } -} - -/// Builds a never-ending future that continuously polls the network. -/// -/// The `status_sink` contain a list of senders to send a periodic network status to. -fn build_network_future< - B: BlockT, - C: client::BlockchainEvents, - S: network::specialization::NetworkSpecialization, - H: network::ExHashT -> ( - roles: Roles, - mut network: network::NetworkWorker, - client: Arc, - status_sinks: Arc, NetworkState)>>>, - rpc_rx: futures03::channel::mpsc::UnboundedReceiver>, - should_have_peers: bool, - dht_event_tx: Option>, -) -> impl Future { - // Compatibility shim while we're transitioning to stable Futures. - // See https://github.com/paritytech/substrate/issues/3099 - let mut rpc_rx = futures03::compat::Compat::new(rpc_rx.map(|v| Ok::<_, ()>(v))); - - let mut imported_blocks_stream = client.import_notification_stream().fuse() - .map(|v| Ok::<_, ()>(v)).compat(); - let mut finality_notification_stream = client.finality_notification_stream().fuse() - .map(|v| Ok::<_, ()>(v)).compat(); - - futures::future::poll_fn(move || { - let before_polling = Instant::now(); - - // We poll `imported_blocks_stream`. - while let Ok(Async::Ready(Some(notification))) = imported_blocks_stream.poll() { - network.on_block_imported(notification.hash, notification.header, Vec::new(), notification.is_new_best); - } - - // We poll `finality_notification_stream`, but we only take the last event. - let mut last = None; - while let Ok(Async::Ready(Some(item))) = finality_notification_stream.poll() { - last = Some(item); - } - if let Some(notification) = last { - network.on_block_finalized(notification.hash, notification.header); - } - - // Poll the RPC requests and answer them. - while let Ok(Async::Ready(Some(request))) = rpc_rx.poll() { - match request { - rpc::system::Request::Health(sender) => { - let _ = sender.send(rpc::system::Health { - peers: network.peers_debug_info().len(), - is_syncing: network.service().is_major_syncing(), - should_have_peers, - }); - }, - rpc::system::Request::Peers(sender) => { - let _ = sender.send(network.peers_debug_info().into_iter().map(|(peer_id, p)| - rpc::system::PeerInfo { - peer_id: peer_id.to_base58(), - roles: format!("{:?}", p.roles), - protocol_version: p.protocol_version, - best_hash: p.best_hash, - best_number: p.best_number, - } - ).collect()); - } - rpc::system::Request::NetworkState(sender) => { - if let Some(network_state) = serde_json::to_value(&network.network_state()).ok() { - let _ = sender.send(network_state); - } - } - rpc::system::Request::NodeRoles(sender) => { - use rpc::system::NodeRole; - - let node_roles = (0 .. 8) - .filter(|&bit_number| (roles.bits() >> bit_number) & 1 == 1) - .map(|bit_number| match Roles::from_bits(1 << bit_number) { - Some(Roles::AUTHORITY) => NodeRole::Authority, - Some(Roles::LIGHT) => NodeRole::LightClient, - Some(Roles::FULL) => NodeRole::Full, - _ => NodeRole::UnknownRole(bit_number), - }) - .collect(); - - let _ = sender.send(node_roles); - } - }; - } - - // Interval report for the external API. - status_sinks.lock().poll(|| { - let status = NetworkStatus { - sync_state: network.sync_state(), - best_seen_block: network.best_seen_block(), - num_sync_peers: network.num_sync_peers(), - num_connected_peers: network.num_connected_peers(), - num_active_peers: network.num_active_peers(), - average_download_per_sec: network.average_download_per_sec(), - average_upload_per_sec: network.average_upload_per_sec(), - }; - let state = network.network_state(); - (status, state) - }); - - // Main network polling. - while let Ok(Async::Ready(Some(Event::Dht(event)))) = network.poll().map_err(|err| { - warn!(target: "service", "Error in network: {:?}", err); - }) { - // Given that core/authority-discovery is the only upper stack consumer of Dht events at the moment, all Dht - // events are being passed on to the authority-discovery module. In the future there might be multiple - // consumers of these events. In that case this would need to be refactored to properly dispatch the events, - // e.g. via a subscriber model. - if let Some(Err(e)) = dht_event_tx.as_ref().map(|c| c.clone().try_send(event)) { - if e.is_full() { - warn!(target: "service", "Dht event channel to authority discovery is full, dropping event."); - } else if e.is_disconnected() { - warn!(target: "service", "Dht event channel to authority discovery is disconnected, dropping event."); - } - } - }; - - // Now some diagnostic for performances. - let polling_dur = before_polling.elapsed(); - log!( - target: "service", - if polling_dur >= Duration::from_millis(50) { Level::Debug } else { Level::Trace }, - "Polling the network future took {:?}", - polling_dur - ); - - Ok(Async::NotReady) - }) -} - -/// Overview status of the network. -#[derive(Clone)] -pub struct NetworkStatus { - /// Current global sync state. - pub sync_state: network::SyncState, - /// Target sync block number. - pub best_seen_block: Option>, - /// Number of peers participating in syncing. - pub num_sync_peers: u32, - /// Total number of connected peers - pub num_connected_peers: usize, - /// Total number of active peers. - pub num_active_peers: usize, - /// Downloaded bytes per second averaged over the past few seconds. - pub average_download_per_sec: u64, - /// Uploaded bytes per second averaged over the past few seconds. - pub average_upload_per_sec: u64, -} - -impl Drop for - Service -{ - fn drop(&mut self) { - debug!(target: "service", "Substrate service shutdown"); - if let Some(signal) = self.signal.take() { - signal.fire(); - } - } -} - -/// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive. -#[cfg(not(target_os = "unknown"))] -fn start_rpc_servers rpc_servers::RpcHandler>( - config: &Configuration, - mut gen_handler: H -) -> Result, error::Error> { - fn maybe_start_server(address: Option, mut start: F) -> Result, io::Error> - where F: FnMut(&SocketAddr) -> Result, - { - Ok(match address { - Some(mut address) => Some(start(&address) - .or_else(|e| match e.kind() { - io::ErrorKind::AddrInUse | - io::ErrorKind::PermissionDenied => { - warn!("Unable to bind server to {}. Trying random port.", address); - address.set_port(0); - start(&address) - }, - _ => Err(e), - })?), - None => None, - }) - } - - Ok(Box::new(( - maybe_start_server( - config.rpc_http, - |address| rpc_servers::start_http(address, config.rpc_cors.as_ref(), gen_handler()), - )?, - maybe_start_server( - config.rpc_ws, - |address| rpc_servers::start_ws( - address, - config.rpc_ws_max_connections, - config.rpc_cors.as_ref(), - gen_handler(), - ), - )?.map(Mutex::new), - ))) -} - -/// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive. -#[cfg(target_os = "unknown")] -fn start_rpc_servers components::RpcHandler>( - _: &Configuration, - _: H -) -> Result, error::Error> { - Ok(Box::new(())) -} - -/// An RPC session. Used to perform in-memory RPC queries (ie. RPC queries that don't go through -/// the HTTP or WebSockets server). -pub struct RpcSession { - metadata: rpc::Metadata, -} - -impl RpcSession { - /// Creates an RPC session. - /// - /// The `sender` is stored inside the `RpcSession` and is used to communicate spontaneous JSON - /// messages. - /// - /// The `RpcSession` must be kept alive in order to receive messages on the sender. - pub fn new(sender: mpsc::Sender) -> RpcSession { - RpcSession { - metadata: sender.into(), - } - } -} - -/// Transaction pool adapter. -pub struct TransactionPoolAdapter { - imports_external_transactions: bool, - pool: Arc

, - client: Arc, - executor: TaskExecutor, -} - -/// Get transactions for propagation. -/// -/// Function extracted to simplify the test and prevent creating `ServiceFactory`. -fn transactions_to_propagate(pool: &TransactionPool) - -> Vec<(H, B::Extrinsic)> -where - PoolApi: ChainApi, - B: BlockT, - H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, - E: txpool::error::IntoPoolError + From, -{ - pool.ready() - .filter(|t| t.is_propagateable()) - .map(|t| { - let hash = t.hash.clone(); - let ex: B::Extrinsic = t.data.clone(); - (hash, ex) - }) - .collect() -} - -impl network::TransactionPool for - TransactionPoolAdapter> -where - C: network::ClientHandle + Send + Sync, - PoolApi: 'static + ChainApi, - B: BlockT, - H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, - E: txpool::error::IntoPoolError + From, -{ - fn transactions(&self) -> Vec<(H, ::Extrinsic)> { - transactions_to_propagate(&self.pool) - } - - fn hash_of(&self, transaction: &B::Extrinsic) -> H { - self.pool.hash_of(transaction) - } - - fn import(&self, report_handle: ReportHandle, who: PeerId, reputation_change: i32, transaction: B::Extrinsic) { - if !self.imports_external_transactions { - debug!("Transaction rejected"); - return; - } - - let encoded = transaction.encode(); - match Decode::decode(&mut &encoded[..]) { - Ok(uxt) => { - let best_block_id = BlockId::hash(self.client.info().chain.best_hash); - let import_future = self.pool.submit_one(&best_block_id, uxt); - let import_future = import_future - .then(move |import_result| { - match import_result { - Ok(_) => report_handle.report_peer(who, reputation_change), - Err(e) => match e.into_pool_error() { - Ok(txpool::error::Error::AlreadyImported(_)) => (), - Ok(e) => debug!("Error adding transaction to the pool: {:?}", e), - Err(e) => debug!("Error converting pool error: {:?}", e), - } - } - ready(Ok(())) - }) - .compat(); - - if let Err(e) = self.executor.execute(Box::new(import_future)) { - warn!("Error scheduling extrinsic import: {:?}", e); - } - } - Err(e) => debug!("Error decoding transaction {}", e), - } - } - - fn on_broadcasted(&self, propagations: HashMap>) { - self.pool.on_broadcasted(propagations) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use futures03::executor::block_on; - use consensus_common::SelectChain; - use sr_primitives::traits::BlindCheckable; - use substrate_test_runtime_client::{prelude::*, runtime::{Extrinsic, Transfer}}; - - #[test] - fn should_not_propagate_transactions_that_are_marked_as_such() { - // given - let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); - let client = Arc::new(client); - let pool = Arc::new(TransactionPool::new( - Default::default(), - transaction_pool::FullChainApi::new(client.clone()) - )); - let best = longest_chain.best_chain().unwrap(); - let transaction = Transfer { - amount: 5, - nonce: 0, - from: AccountKeyring::Alice.into(), - to: Default::default(), - }.into_signed_tx(); - block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); - block_on(pool.submit_one(&BlockId::hash(best.hash()), Extrinsic::IncludeData(vec![1]))).unwrap(); - assert_eq!(pool.status().ready, 2); - - // when - let transactions = transactions_to_propagate(&pool); - - // then - assert_eq!(transactions.len(), 1); - assert!(transactions[0].1.clone().check().is_ok()); - // this should not panic - let _ = transactions[0].1.transfer(); - } -} diff --git a/core/service/test/Cargo.toml b/core/service/test/Cargo.toml deleted file mode 100644 index 872d63415f4e8..0000000000000 --- a/core/service/test/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "substrate-service-test" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -tempdir = "0.3.7" -tokio = "0.1.22" -futures = "0.1.29" -log = "0.4.8" -env_logger = "0.7.0" -fdlimit = "0.1.1" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19", features = ["compat"] } -service = { package = "substrate-service", path = "../../../core/service" } -network = { package = "substrate-network", path = "../../../core/network" } -consensus = { package = "substrate-consensus-common", path = "../../../core/consensus/common" } -client = { package = "substrate-client", path = "../../../core/client" } -sr-primitives = { path = "../../../core/sr-primitives" } -primitives = { package = "substrate-primitives", path = "../../../core/primitives" } diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs deleted file mode 100644 index 806996576ff90..0000000000000 --- a/core/service/test/src/lib.rs +++ /dev/null @@ -1,520 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Service integration test utils. - -use std::iter; -use std::sync::{Arc, Mutex, MutexGuard}; -use std::net::Ipv4Addr; -use std::time::Duration; -use log::info; -use futures::{Future, Stream, Poll}; -use tempdir::TempDir; -use tokio::{runtime::Runtime, prelude::FutureExt}; -use tokio::timer::Interval; -use service::{ - AbstractService, - ChainSpec, - Configuration, - Roles, - Error, -}; -use network::{multiaddr, Multiaddr}; -use network::config::{NetworkConfiguration, TransportConfig, NodeKeyConfig, Secret, NonReservedPeerMode}; -use sr_primitives::{generic::BlockId, traits::Block as BlockT}; - -/// Maximum duration of single wait call. -const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); - -struct TestNet { - runtime: Runtime, - authority_nodes: Vec<(usize, SyncService, U, Multiaddr)>, - full_nodes: Vec<(usize, SyncService, U, Multiaddr)>, - light_nodes: Vec<(usize, SyncService, Multiaddr)>, - chain_spec: ChainSpec, - base_port: u16, - nodes: usize, -} - -/// Wraps around an `Arc` and implements `Future`. -pub struct SyncService(Arc>); - -impl SyncService { - pub fn get(&self) -> MutexGuard { - self.0.lock().unwrap() - } -} - -impl Clone for SyncService { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} - -impl From for SyncService { - fn from(service: T) -> Self { - SyncService(Arc::new(Mutex::new(service))) - } -} - -impl> Future for SyncService { - type Item = (); - type Error = service::Error; - - fn poll(&mut self) -> Poll { - self.0.lock().unwrap().poll() - } -} - -impl TestNet -where F: Send + 'static, L: Send +'static, U: Clone + Send + 'static -{ - pub fn run_until_all_full( - &mut self, - full_predicate: FP, - light_predicate: LP, - ) - where - FP: Send + Fn(usize, &SyncService) -> bool + 'static, - LP: Send + Fn(usize, &SyncService) -> bool + 'static, - { - let full_nodes = self.full_nodes.clone(); - let light_nodes = self.light_nodes.clone(); - let interval = Interval::new_interval(Duration::from_millis(100)) - .map_err(|_| ()) - .for_each(move |_| { - let full_ready = full_nodes.iter().all(|&(ref id, ref service, _, _)| - full_predicate(*id, service) - ); - - if !full_ready { - return Ok(()); - } - - let light_ready = light_nodes.iter().all(|&(ref id, ref service, _)| - light_predicate(*id, service) - ); - - if !light_ready { - Ok(()) - } else { - Err(()) - } - }) - .timeout(MAX_WAIT_TIME); - - match self.runtime.block_on(interval) { - Ok(()) => unreachable!("interval always fails; qed"), - Err(ref err) if err.is_inner() => (), - Err(_) => panic!("Waited for too long"), - } - } -} - -fn node_config ( - index: usize, - spec: &ChainSpec, - role: Roles, - key_seed: Option, - base_port: u16, - root: &TempDir, -) -> Configuration<(), G, E> -{ - let root = root.path().join(format!("node-{}", index)); - - let config_path = Some(String::from(root.join("network").to_str().unwrap())); - let net_config_path = config_path.clone(); - - let network_config = NetworkConfiguration { - config_path, - net_config_path, - listen_addresses: vec! [ - iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))) - .chain(iter::once(multiaddr::Protocol::Tcp(base_port + index as u16))) - .collect() - ], - public_addresses: vec![], - boot_nodes: vec![], - node_key: NodeKeyConfig::Ed25519(Secret::New), - in_peers: 50, - out_peers: 450, - reserved_nodes: vec![], - non_reserved_mode: NonReservedPeerMode::Accept, - client_version: "network/test/0.1".to_owned(), - node_name: "unknown".to_owned(), - transport: TransportConfig::Normal { - enable_mdns: false, - wasm_external_transport: None, - }, - }; - - Configuration { - impl_name: "network-test-impl", - impl_version: "0.1", - impl_commit: "", - roles: role, - transaction_pool: Default::default(), - network: network_config, - keystore_path: root.join("key"), - keystore_password: None, - database_path: root.join("db"), - database_cache_size: None, - state_cache_size: 16777216, - state_cache_child_ratio: None, - pruning: Default::default(), - chain_spec: (*spec).clone(), - custom: Default::default(), - name: format!("Node {}", index), - wasm_method: service::config::WasmExecutionMethod::Interpreted, - execution_strategies: Default::default(), - rpc_http: None, - rpc_ws: None, - rpc_ws_max_connections: None, - rpc_cors: None, - telemetry_endpoints: None, - telemetry_external_transport: None, - default_heap_pages: None, - offchain_worker: false, - force_authoring: false, - disable_grandpa: false, - dev_key_seed: key_seed, - } -} - -impl TestNet where - F: AbstractService, - L: AbstractService, - E: Clone, -{ - fn new( - temp: &TempDir, - spec: ChainSpec, - full: impl Iterator) -> Result<(F, U), Error>>, - light: impl Iterator) -> Result>, - authorities: impl Iterator) -> Result<(F, U), Error> - )>, - base_port: u16 - ) -> TestNet { - let _ = env_logger::try_init(); - fdlimit::raise_fd_limit(); - let runtime = Runtime::new().expect("Error creating tokio runtime"); - let mut net = TestNet { - runtime, - authority_nodes: Default::default(), - full_nodes: Default::default(), - light_nodes: Default::default(), - chain_spec: spec, - base_port, - nodes: 0, - }; - net.insert_nodes(temp, full, light, authorities); - net - } - - fn insert_nodes( - &mut self, - temp: &TempDir, - full: impl Iterator) -> Result<(F, U), Error>>, - light: impl Iterator) -> Result>, - authorities: impl Iterator) -> Result<(F, U), Error>)> - ) { - let executor = self.runtime.executor(); - - for (key, authority) in authorities { - let node_config = node_config( - self.nodes, - &self.chain_spec, - Roles::AUTHORITY, - Some(key), - self.base_port, - &temp, - ); - let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); - let (service, user_data) = authority(node_config).expect("Error creating test node service"); - let service = SyncService::from(service); - - executor.spawn(service.clone().map_err(|_| ())); - let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); - self.authority_nodes.push((self.nodes, service, user_data, addr)); - self.nodes += 1; - } - - for full in full { - let node_config = node_config(self.nodes, &self.chain_spec, Roles::FULL, None, self.base_port, &temp); - let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); - let (service, user_data) = full(node_config).expect("Error creating test node service"); - let service = SyncService::from(service); - - executor.spawn(service.clone().map_err(|_| ())); - let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); - self.full_nodes.push((self.nodes, service, user_data, addr)); - self.nodes += 1; - } - - for light in light { - let node_config = node_config(self.nodes, &self.chain_spec, Roles::LIGHT, None, self.base_port, &temp); - let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); - let service = SyncService::from(light(node_config).expect("Error creating test node service")); - - executor.spawn(service.clone().map_err(|_| ())); - let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); - self.light_nodes.push((self.nodes, service, addr)); - self.nodes += 1; - } - } -} - -pub fn connectivity( - spec: ChainSpec, - full_builder: Fb, - light_builder: Lb, - light_node_interconnectivity: bool, // should normally be false, unless the light nodes - // aren't actually light. -) where - E: Clone, - Fb: Fn(Configuration<(), G, E>) -> Result, - F: AbstractService, - Lb: Fn(Configuration<(), G, E>) -> Result, - L: AbstractService, -{ - const NUM_FULL_NODES: usize = 5; - const NUM_LIGHT_NODES: usize = 5; - - let expected_full_connections = NUM_FULL_NODES - 1 + NUM_LIGHT_NODES; - let expected_light_connections = if light_node_interconnectivity { - expected_full_connections - } else { - NUM_FULL_NODES - }; - - { - let temp = TempDir::new("substrate-connectivity-test").expect("Error creating test dir"); - let runtime = { - let mut network = TestNet::new( - &temp, - spec.clone(), - (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), - (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), - // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise - // the type of the closure cannot be inferred. - (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), - 30400, - ); - info!("Checking star topology"); - let first_address = network.full_nodes[0].3.clone(); - for (_, service, _, _) in network.full_nodes.iter().skip(1) { - service.get().network().add_reserved_peer(first_address.to_string()) - .expect("Error adding reserved peer"); - } - for (_, service, _) in network.light_nodes.iter() { - service.get().network().add_reserved_peer(first_address.to_string()) - .expect("Error adding reserved peer"); - } - - network.run_until_all_full( - move |_index, service| service.get().network().num_connected() - == expected_full_connections, - move |_index, service| service.get().network().num_connected() - == expected_light_connections, - ); - - network.runtime - }; - - runtime.shutdown_now().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, - (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), - (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), - // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise - // the type of the closure cannot be inferred. - (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), - 30400, - ); - info!("Checking linked topology"); - let mut address = network.full_nodes[0].3.clone(); - let max_nodes = std::cmp::max(NUM_FULL_NODES, NUM_LIGHT_NODES); - for i in 0..max_nodes { - if i != 0 { - if let Some((_, service, _, node_id)) = network.full_nodes.get(i) { - service.get().network().add_reserved_peer(address.to_string()) - .expect("Error adding reserved peer"); - address = node_id.clone(); - } - } - - if let Some((_, service, node_id)) = network.light_nodes.get(i) { - service.get().network().add_reserved_peer(address.to_string()) - .expect("Error adding reserved peer"); - address = node_id.clone(); - } - } - - network.run_until_all_full( - move |_index, service| service.get().network().num_connected() - == expected_full_connections, - move |_index, service| service.get().network().num_connected() - == expected_light_connections, - ); - } - temp.close().expect("Error removing temp dir"); - } -} - -pub fn sync( - spec: ChainSpec, - full_builder: Fb, - light_builder: Lb, - mut make_block_and_import: B, - mut extrinsic_factory: ExF -) where - Fb: Fn(Configuration<(), G, E>) -> Result<(F, U), Error>, - F: AbstractService, - Lb: Fn(Configuration<(), G, E>) -> Result, - L: AbstractService, - B: FnMut(&F, &mut U), - ExF: FnMut(&F, &U) -> ::Extrinsic, - U: Clone + Send + 'static, - E: Clone, -{ - const NUM_FULL_NODES: usize = 10; - // FIXME: BABE light client support is currently not working. - const NUM_LIGHT_NODES: usize = 10; - const NUM_BLOCKS: usize = 512; - let temp = TempDir::new("substrate-sync-test").expect("Error creating test dir"); - let mut network = TestNet::new( - &temp, - spec.clone(), - (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg) }), - (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), - // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise - // the type of the closure cannot be inferred. - (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg) })), - 30500, - ); - info!("Checking block sync"); - let first_address = { - let &mut (_, ref first_service, ref mut first_user_data, _) = &mut network.full_nodes[0]; - for i in 0 .. NUM_BLOCKS { - if i % 128 == 0 { - info!("Generating #{}", i + 1); - } - - make_block_and_import(&first_service.get(), first_user_data); - } - network.full_nodes[0].3.clone() - }; - - info!("Running sync"); - for (_, service, _, _) in network.full_nodes.iter().skip(1) { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); - } - for (_, service, _) in network.light_nodes.iter() { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); - } - network.run_until_all_full( - |_index, service| - service.get().client().info().chain.best_number == (NUM_BLOCKS as u32).into(), - |_index, service| - service.get().client().info().chain.best_number == (NUM_BLOCKS as u32).into(), - ); - - info!("Checking extrinsic propagation"); - let first_service = network.full_nodes[0].1.clone(); - let first_user_data = &network.full_nodes[0].2; - let best_block = BlockId::number(first_service.get().client().info().chain.best_number); - let extrinsic = extrinsic_factory(&first_service.get(), first_user_data); - futures03::executor::block_on(first_service.get().transaction_pool().submit_one(&best_block, extrinsic)).unwrap(); - network.run_until_all_full( - |_index, service| service.get().transaction_pool().ready().count() == 1, - |_index, _service| true, - ); -} - -pub fn consensus( - spec: ChainSpec, - full_builder: Fb, - light_builder: Lb, - authorities: impl IntoIterator -) where - Fb: Fn(Configuration<(), G, E>) -> Result, - F: AbstractService, - Lb: Fn(Configuration<(), G, E>) -> Result, - L: AbstractService, - E: Clone, -{ - const NUM_FULL_NODES: usize = 10; - const NUM_LIGHT_NODES: usize = 10; - const NUM_BLOCKS: usize = 10; // 10 * 2 sec block production time = ~20 seconds - let temp = TempDir::new("substrate-conensus-test").expect("Error creating test dir"); - let mut network = TestNet::new( - &temp, - spec.clone(), - (0..NUM_FULL_NODES / 2).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), - (0..NUM_LIGHT_NODES / 2).map(|_| { |cfg| light_builder(cfg) }), - authorities.into_iter().map(|key| (key, { |cfg| full_builder(cfg).map(|s| (s, ())) })), - 30600, - ); - - info!("Checking consensus"); - let first_address = network.authority_nodes[0].3.clone(); - for (_, service, _, _) in network.full_nodes.iter() { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); - } - for (_, service, _) in network.light_nodes.iter() { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); - } - for (_, service, _, _) in network.authority_nodes.iter().skip(1) { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); - } - network.run_until_all_full( - |_index, service| - service.get().client().info().chain.finalized_number >= (NUM_BLOCKS as u32 / 2).into(), - |_index, service| - service.get().client().info().chain.best_number >= (NUM_BLOCKS as u32 / 2).into(), - ); - - info!("Adding more peers"); - network.insert_nodes( - &temp, - (0..NUM_FULL_NODES / 2).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), - (0..NUM_LIGHT_NODES / 2).map(|_| { |cfg| light_builder(cfg) }), - // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise - // the type of the closure cannot be inferred. - (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), - ); - for (_, service, _, _) in network.full_nodes.iter() { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); - } - for (_, service, _) in network.light_nodes.iter() { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); - } - network.run_until_all_full( - |_index, service| - service.get().client().info().chain.finalized_number >= (NUM_BLOCKS as u32).into(), - |_index, service| - service.get().client().info().chain.best_number >= (NUM_BLOCKS as u32).into(), - ); -} diff --git a/core/session/Cargo.toml b/core/session/Cargo.toml deleted file mode 100644 index 5d8cb3f0001ba..0000000000000 --- a/core/session/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "substrate-session" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../client", default-features = false } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -sr-primitives = { path = "../sr-primitives", optional = true } -primitives = { package = "substrate-primitives", path = "../primitives", optional = true } - -[features] -default = [ "std" ] -std = [ "client/std", "rstd/std", "sr-primitives", "primitives" ] diff --git a/core/session/src/lib.rs b/core/session/src/lib.rs deleted file mode 100644 index 1b40d2d9ba815..0000000000000 --- a/core/session/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate core types around sessions. - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::vec::Vec; - -#[cfg(feature = "std")] -use sr_primitives::traits::{ProvideRuntimeApi, Block as BlockT}; -#[cfg(feature = "std")] -use primitives::{H256, Blake2Hasher}; - -client::decl_runtime_apis! { - /// Session keys runtime api. - pub trait SessionKeys { - /// Generate a set of session keys with optionally using the given seed. - /// The keys should be stored within the keystore exposed via runtime - /// externalities. - /// - /// The seed needs to be a valid `utf8` string. - /// - /// Returns the concatenated SCALE encoded public keys. - fn generate_session_keys(seed: Option>) -> Vec; - } -} - -/// Generate the initial session keys with the given seeds and store them in -/// the client's keystore. -#[cfg(feature = "std")] -pub fn generate_initial_session_keys( - client: std::sync::Arc>, - seeds: Vec, -) -> Result<(), client::error::Error> -where - B: client::backend::Backend, - E: client::CallExecutor, - Block: BlockT, - client::Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: SessionKeys, -{ - let info = client.info().chain; - let runtime_api = client.runtime_api(); - - for seed in seeds { - runtime_api.generate_session_keys( - &sr_primitives::generic::BlockId::Number(info.best_number), - Some(seed.as_bytes().to_vec()), - )?; - } - - Ok(()) -} diff --git a/core/sr-api-macros/Cargo.toml b/core/sr-api-macros/Cargo.toml deleted file mode 100644 index 022536136b80e..0000000000000 --- a/core/sr-api-macros/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "sr-api-macros" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -quote = "0.6.12" -syn = { version = "0.15.44", features = [ "full", "fold", "extra-traits", "visit" ] } -proc-macro2 = "0.4.27" -blake2-rfc = "0.2.18" -proc-macro-crate = "0.1.4" - -[dev-dependencies] -client = { package = "substrate-client", path = "../client" } -test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client" } -state_machine = { package = "substrate-state-machine", path = "../state-machine" } -sr-primitives = { path = "../sr-primitives" } -sr-version = { path = "../sr-version" } -primitives = { package = "substrate-primitives", path = "../primitives" } -criterion = "0.3.0" -consensus_common = { package = "substrate-consensus-common", path = "../consensus/common" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -trybuild = "1.0.17" -rustversion = "1.0.0" - -[[bench]] -name = "bench" -harness = false - -# We actually don't need the `std` feature in this crate, but the tests require it. -[features] -default = [ "std" ] -std = [] diff --git a/core/sr-api-macros/benches/bench.rs b/core/sr-api-macros/benches/bench.rs deleted file mode 100644 index 9aba38c2d1820..0000000000000 --- a/core/sr-api-macros/benches/bench.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2018 - 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use criterion::{Criterion, criterion_group, criterion_main}; -use test_client::{ - DefaultTestClientBuilderExt, TestClientBuilder, - TestClientBuilderExt, runtime::TestAPI, -}; -use sr_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().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().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().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().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 = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::AlwaysWasm).build(); - let block_id = BlockId::Number(client.info().chain.best_number); - b.iter(|| client.runtime_api().benchmark_indirect_call(&block_id).unwrap()) - }); - - c.bench_function("calling function in wasm", |b| { - let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::AlwaysWasm).build(); - let block_id = BlockId::Number(client.info().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/impl_runtime_apis.rs b/core/sr-api-macros/src/impl_runtime_apis.rs deleted file mode 100644 index 28eb5c60729ed..0000000000000 --- a/core/sr-api-macros/src/impl_runtime_apis.rs +++ /dev/null @@ -1,659 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::utils::{ - unwrap_or_error, generate_crate_access, generate_hidden_includes, - 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, generate_call_api_at_fn_name, prefix_function_with_trait, -}; - -use proc_macro2::{Span, TokenStream}; - -use quote::quote; - -use syn::{ - spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, MethodSig, Path, - ImplItem, parse::{Parse, ParseStream, Result, Error}, PathArguments, GenericArgument, TypePath, - fold::{self, Fold}, parse_quote -}; - -use std::{collections::HashSet, iter}; - -/// Unique identifier used to make the hidden includes unique for this macro. -const HIDDEN_INCLUDES_ID: &str = "IMPL_RUNTIME_APIS"; - -/// The structure used for parsing the runtime api implementations. -struct RuntimeApiImpls { - impls: Vec, -} - -impl Parse for RuntimeApiImpls { - fn parse(input: ParseStream) -> Result { - let mut impls = Vec::new(); - - while !input.is_empty() { - impls.push(ItemImpl::parse(input)?); - } - - Ok(Self { impls }) - } -} - -/// Generates the call to the implementation of the requested function. -/// The generated code includes decoding of the input arguments and encoding of the output. -fn generate_impl_call( - signature: &MethodSig, - runtime: &Type, - input: &Ident, - impl_trait: &Path -) -> Result { - 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 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!( - #( - let #pnames : #ptypes = match #c_iter::runtime_api::Decode::decode(&mut #input) { - Ok(input) => input, - Err(e) => panic!("Bad input data provided to {}: {}", #fn_name_str, e.what()), - }; - )* - - #[allow(deprecated)] - <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*) - ) - ) -} - -/// Extract the trait that is implemented in the given `ItemImpl`. -fn extract_impl_trait<'a>(impl_: &'a ItemImpl) -> Result<&'a Path> { - impl_.trait_.as_ref().map(|v| &v.1).ok_or_else( - || Error::new(impl_.span(), "Only implementation of traits are supported!") - ).and_then(|p| { - if p.segments.len() > 1 { - Ok(p) - } else { - Err( - Error::new( - p.span(), - "The implemented trait has to be referenced with a path, \ - e.g. `impl client::Core for Runtime`." - ) - ) - } - }) -} - -/// Extracts the runtime block identifier. -fn extract_runtime_block_ident(trait_: &Path) -> Result<&TypePath> { - let span = trait_.span(); - let segment = trait_ - .segments - .last() - .ok_or_else( - || Error::new(span, "Empty path not supported") - )?; - let generics = segment.value(); - - match &generics.arguments { - PathArguments::AngleBracketed(ref args) => { - args.args.first().and_then(|v| match v.value() { - GenericArgument::Type(Type::Path(block)) => Some(block), - _ => None - }).ok_or_else(|| Error::new(args.span(), "Missing `Block` generic parameter.")) - }, - PathArguments::None => { - let span = trait_.segments.last().as_ref().unwrap().value().span(); - Err(Error::new(span, "Missing `Block` generic parameter.")) - }, - PathArguments::Parenthesized(_) => { - Err(Error::new(generics.arguments.span(), "Unexpected parentheses in path!")) - } - } -} - -/// Generate all the implementation calls for the given functions. -fn generate_impl_calls( - impls: &[ItemImpl], - input: &Ident -) -> Result> { - let mut impl_calls = Vec::new(); - - for impl_ in impls { - let impl_trait_path = extract_impl_trait(impl_)?; - let impl_trait = extend_with_runtime_decl_path(impl_trait_path.clone()); - let impl_trait_ident = &impl_trait_path - .segments - .last() - .ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))? - .value() - .ident; - - for item in &impl_.items { - if let ImplItem::Method(method) = item { - let impl_call = generate_impl_call( - &method.sig, - &impl_.self_ty, - input, - &impl_trait - )?; - - impl_calls.push( - (impl_trait_ident.clone(), method.sig.ident.clone(), impl_call) - ); - } - } - } - - Ok(impl_calls) -} - -/// Generate the dispatch function that is used in native to call into the runtime. -fn generate_dispatch_function(impls: &[ItemImpl]) -> Result { - let data = Ident::new("data", Span::call_site()); - let c = generate_crate_access(HIDDEN_INCLUDES_ID); - let impl_calls = generate_impl_calls(impls, &data)? - .into_iter() - .map(|(trait_, fn_name, impl_)| { - let name = prefix_function_with_trait(&trait_, &fn_name); - quote!( #name => Some(#c::runtime_api::Encode::encode(&{ #impl_ })), ) - }); - - Ok(quote!( - #[cfg(feature = "std")] - pub fn dispatch(method: &str, mut #data: &[u8]) -> Option> { - match method { - #( #impl_calls )* - _ => None, - } - } - )) -} - -/// Generate the interface functions that are used to call into the runtime in wasm. -fn generate_wasm_interface(impls: &[ItemImpl]) -> Result { - let input = Ident::new("input", Span::call_site()); - let c = generate_crate_access(HIDDEN_INCLUDES_ID); - let impl_calls = generate_impl_calls(impls, &input)? - .into_iter() - .map(|(trait_, fn_name, impl_)| { - let fn_name = Ident::new( - &prefix_function_with_trait(&trait_, &fn_name), - Span::call_site() - ); - - quote!( - #[cfg(not(feature = "std"))] - #[no_mangle] - pub fn #fn_name(input_data: *mut u8, input_len: usize) -> u64 { - let mut #input = if input_len == 0 { - &[0u8; 0] - } else { - unsafe { - #c::runtime_api::slice::from_raw_parts(input_data, input_len) - } - }; - - let output = { #impl_ }; - #c::runtime_api::to_substrate_wasm_fn_return_value(&output) - } - ) - }); - - Ok(quote!( #( #impl_calls )* )) -} - -fn generate_block_and_block_id_ty( - runtime: &Type, - trait_: &'static str, - assoc_type: &'static str, -) -> (TokenStream, TokenStream) { - let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); - let trait_ = Ident::new(trait_, Span::call_site()); - let assoc_type = Ident::new(assoc_type, Span::call_site()); - - let block = quote!( <#runtime as #crate_::runtime_api::#trait_>::#assoc_type ); - let block_id = quote!( #crate_::runtime_api::BlockId<#block> ); - - (block, block_id) -} - -fn generate_node_block_and_block_id_ty(runtime: &Type) -> (TokenStream, TokenStream) { - generate_block_and_block_id_ty(runtime, "GetNodeBlockType", "NodeBlock") -} - -fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result { - let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); - let runtime = &impls.get(0).ok_or_else(|| - Error::new(Span::call_site(), "No api implementation given!") - )?.self_ty; - let (block, block_id) = generate_node_block_and_block_id_ty(runtime); - - Ok(quote!( - pub struct RuntimeApi {} - /// Implements all runtime apis for the client side. - #[cfg(any(feature = "std", test))] - pub struct RuntimeApiImpl + 'static> { - call: &'static C, - commit_on_success: std::cell::RefCell, - initialized_block: std::cell::RefCell>, - changes: std::cell::RefCell<#crate_::runtime_api::OverlayedChanges>, - recorder: Option>>>, - } - - // `RuntimeApi` itself is not threadsafe. However, an instance is only available in a - // `ApiRef` object and `ApiRef` also has an associated lifetime. This lifetimes makes it - // impossible to move `RuntimeApi` into another thread. - #[cfg(any(feature = "std", test))] - unsafe impl> Send for RuntimeApiImpl {} - #[cfg(any(feature = "std", test))] - unsafe impl> Sync for RuntimeApiImpl {} - - #[cfg(any(feature = "std", test))] - impl> #crate_::runtime_api::ApiExt<#block> - for RuntimeApiImpl - { - fn map_api_result std::result::Result, R, E>( - &self, - map_call: F - ) -> ::std::result::Result where Self: Sized { - *self.commit_on_success.borrow_mut() = false; - let res = map_call(self); - *self.commit_on_success.borrow_mut() = true; - - self.commit_on_ok(&res); - - res - } - - fn runtime_version_at( - &self, - at: &#block_id - ) -> #crate_::error::Result<#crate_::runtime_api::RuntimeVersion> { - self.call.runtime_version_at(at) - } - - fn record_proof(&mut self) { - self.recorder = Some(Default::default()); - } - - fn extract_proof(&mut self) -> Option>> { - self.recorder - .take() - .map(|r| { - r.borrow_mut() - .drain() - .into_iter() - .map(|n| n.data.to_vec()) - .collect() - }) - } - } - - #[cfg(any(feature = "std", test))] - 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(), - initialized_block: None.into(), - changes: Default::default(), - recorder: Default::default(), - }.into() - } - } - - #[cfg(any(feature = "std", test))] - impl> RuntimeApiImpl { - fn call_api_at< - R: #crate_::runtime_api::Encode + #crate_::runtime_api::Decode + PartialEq, - F: FnOnce( - &C, - &Self, - &std::cell::RefCell<#crate_::runtime_api::OverlayedChanges>, - &std::cell::RefCell>>, - &Option>>>, - ) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded>, - >( - &self, - call_api_at: F, - ) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded> { - let res = unsafe { - call_api_at( - &self.call, - self, - &self.changes, - &self.initialized_block, - &self.recorder, - ) - }; - - self.commit_on_ok(&res); - res - } - - fn commit_on_ok(&self, res: &::std::result::Result) { - if *self.commit_on_success.borrow() { - if res.is_err() { - self.changes.borrow_mut().discard_prospective(); - } else { - self.changes.borrow_mut().commit_prospective(); - } - } - } - } - )) -} - -/// Extend the given trait path with module that contains the declaration of the trait for the -/// runtime. -fn extend_with_runtime_decl_path(mut trait_: Path) -> Path { - let runtime = { - let trait_name = &trait_ - .segments - .last() - .as_ref() - .expect("Trait path should always contain at least one item; qed") - .value() - .ident; - - generate_runtime_mod_name_for_trait(trait_name) - }; - - let pos = trait_.segments.len() - 1; - trait_.segments.insert(pos, runtime.clone().into()); - trait_ -} - -/// Generates the implementations of the apis for the runtime. -fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result { - let mut impls_prepared = Vec::new(); - - // We put `runtime` before each trait to get the trait that is intended for the runtime and - // we put the `RuntimeBlock` as first argument for the trait generics. - for impl_ in impls.iter() { - let mut impl_ = impl_.clone(); - let trait_ = extract_impl_trait(&impl_)?.clone(); - let trait_ = extend_with_runtime_decl_path(trait_); - - impl_.trait_.as_mut().unwrap().1 = trait_; - impls_prepared.push(impl_); - } - - Ok(quote!( #( #impls_prepared )* )) -} - - -/// 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 -/// with code that calls into the runtime. -struct ApiRuntimeImplToApiRuntimeApiImpl<'a> { - node_block: &'a TokenStream, - runtime_block: &'a TypePath, - node_block_id: &'a TokenStream, - runtime_mod_path: &'a Path, - runtime_type: &'a Type, - trait_generic_arguments: &'a [GenericArgument], - impl_trait: &'a Ident, -} - -impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { - fn fold_type_path(&mut self, input: TypePath) -> TypePath { - let new_ty_path = if input == *self.runtime_block { - let node_block = self.node_block; - parse_quote!( #node_block ) - } else { - input - }; - - fold::fold_type_path(self, new_ty_path) - } - - 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 native_call_generator_ident = - generate_native_call_generator_fn_name(&input.sig.ident); - let call_api_at_call = generate_call_api_at_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(&self.impl_trait, &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>> - ); - - // Generate the new method implementation that calls into the runtime. - parse_quote!( - { - // Get the error to the user (if we have one). - #( #error )* - - self.call_api_at( - |call_runtime_at, core_api, changes, initialized_block, recorder| { - #runtime_mod_path #call_api_at_call( - call_runtime_at, - core_api, - at, - params_encoded, - changes, - initialized_block, - params.map(|p| { - #runtime_mod_path #native_call_generator_ident :: - <#runtime, #node_block #(, #trait_generic_arguments )*> ( - #( #param_tuple_access ),* - ) - }), - context, - recorder, - ) - } - ) - } - ) - }; - - 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 `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 `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) - } -} - -/// Generate the implementations of the runtime apis for the `RuntimeApi` type. -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_path = extract_impl_trait(&impl_)?; - let impl_trait = &impl_trait_path - .segments - .last() - .ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))? - .into_value(); - 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, - runtime_mod_path: &runtime_mod_path, - runtime_type: &*runtime_type, - trait_generic_arguments: &trait_generic_arguments, - impl_trait: &impl_trait.ident, - }; - - result.push(visitor.fold_item_impl(impl_.clone())); - } - Ok(quote!( #( #result )* )) -} - -/// Generates `RUNTIME_API_VERSIONS` that holds all version information about the implemented -/// runtime apis. -fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result { - let mut result = Vec::with_capacity(impls.len()); - let mut processed_traits = HashSet::new(); - - for impl_ in impls { - let mut path = extend_with_runtime_decl_path(extract_impl_trait(&impl_)?.clone()); - // Remove the trait - let trait_ = path - .segments - .pop() - .expect("extract_impl_trait already checks that this is valid; qed") - .into_value() - .ident; - - let span = trait_.span(); - if !processed_traits.insert(trait_) { - return Err( - Error::new( - span, - "Two traits with the same name detected! \ - The trait name is used to generate its ID. \ - Please rename one trait at the declaration!" - ) - ) - } - - let id: Path = parse_quote!( #path ID ); - let version: Path = parse_quote!( #path VERSION ); - - result.push(quote!( (#id, #version) )); - } - - let c = generate_crate_access(HIDDEN_INCLUDES_ID); - - Ok(quote!( - const RUNTIME_API_VERSIONS: #c::runtime_api::ApisVec = - #c::runtime_api::create_apis_vec!([ #( #result ),* ]); - )) -} - -/// The implementation of the `impl_runtime_apis!` macro. -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 api_impls_for_runtime = unwrap_or_error(generate_api_impl_for_runtime(&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 - - #base_runtime_api - - #api_impls_for_runtime - - #api_impls_for_runtime_api - - #runtime_api_versions - - pub mod api { - use super::*; - - #dispatch_impl - - #wasm_interface - } - ).into() -} diff --git a/core/sr-api-macros/src/lib.rs b/core/sr-api-macros/src/lib.rs deleted file mode 100644 index d88fb09d1b11a..0000000000000 --- a/core/sr-api-macros/src/lib.rs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Macros for declaring and implementing runtime apis. - -#![recursion_limit = "512"] -extern crate proc_macro; - -use proc_macro::TokenStream; - -mod impl_runtime_apis; -mod decl_runtime_apis; -mod utils; - -/// Tags given trait implementations as runtime apis. -/// -/// All traits given to this macro, need to be declared with the `decl_runtime_apis!` macro. -/// The implementation of the trait should follow the declaration given to the `decl_runtime_apis!` -/// macro, besides the `Block` type that is required as first generic parameter for each runtime -/// api trait. When implementing a runtime api trait, it is required that the trait is referenced -/// by a path, e.g. `impl my_trait::MyTrait for Runtime`. The macro will use this path to access -/// the declaration of the trait for the runtime side. -/// -/// The macro also generates the api implementations for the client side and provides it through -/// the `RuntimeApi` type. The `RuntimeApi` is hidden behind a `feature` called `std`. -/// -/// To expose version information about all implemented api traits, the constant -/// `RUNTIME_API_VERSIONS` is generated. This constant should be used to instantiate the `apis` -/// field of `RuntimeVersion`. -/// -/// # Example -/// -/// ```rust -/// #[macro_use] -/// extern crate client; -/// extern crate sr_version as version; -/// -/// use version::create_runtime_str; -/// # extern crate test_client; -/// # extern crate sr_primitives; -/// # extern crate primitives; -/// # -/// # use sr_primitives::traits::GetNodeBlockType; -/// # use test_client::runtime::{Block, Header}; -/// # -/// # /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` -/// # /// trait are done by the `construct_runtime!` macro in a real runtime. -/// # pub struct Runtime {} -/// # impl GetNodeBlockType for Runtime { -/// # type NodeBlock = Block; -/// # } -/// # -/// # decl_runtime_apis! { -/// # /// Declare the api trait. -/// # pub trait Balance { -/// # /// Get the balance. -/// # fn get_balance() -> u64; -/// # /// Set the balance. -/// # fn set_balance(val: u64); -/// # } -/// # pub trait BlockBuilder { -/// # fn build_block() -> Block; -/// # } -/// # } -/// -/// /// All runtime api implementations need to be done in one call of the macro! -/// impl_runtime_apis! { -/// # impl client::runtime_api::Core for Runtime { -/// # fn version() -> client::runtime_api::RuntimeVersion { -/// # unimplemented!() -/// # } -/// # fn execute_block(_block: Block) {} -/// # fn initialize_block(_header: &Header) {} -/// # } -/// -/// impl self::Balance for Runtime { -/// fn get_balance() -> u64 { -/// 1 -/// } -/// fn set_balance(_bal: u64) { -/// // Store the balance -/// } -/// } -/// -/// impl self::BlockBuilder for Runtime { -/// fn build_block() -> Block { -/// unimplemented!("Please implement me!") -/// } -/// } -/// } -/// -/// /// Runtime version. This needs to be declared for each runtime. -/// pub const VERSION: version::RuntimeVersion = version::RuntimeVersion { -/// spec_name: create_runtime_str!("node"), -/// impl_name: create_runtime_str!("test-node"), -/// authoring_version: 1, -/// spec_version: 1, -/// impl_version: 0, -/// // Here we are exposing the runtime api versions. -/// apis: RUNTIME_API_VERSIONS, -/// }; -/// -/// # fn main() {} -/// ``` -#[proc_macro] -pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { - impl_runtime_apis::impl_runtime_apis_impl(input) -} - -/// Declares given traits as runtime apis. -/// -/// The macro will create two declarations, one for using on the client side and one for using -/// on the runtime side. The declaration for the runtime side is hidden in its own module. -/// The client side declaration gets two extra parameters per function, -/// `&self` and `at: &BlockId`. The runtime side declaration will match the given trait -/// declaration. Besides one exception, the macro adds an extra generic parameter `Block: BlockT` -/// to the client side and the runtime side. This generic parameter is usable by the user. -/// -/// For implementing these macros you should use the `impl_runtime_apis!` macro. -/// -/// # Example -/// -/// ```rust -/// #[macro_use] -/// extern crate client; -/// -/// decl_runtime_apis! { -/// /// Declare the api trait. -/// pub trait Balance { -/// /// Get the balance. -/// fn get_balance() -> u64; -/// /// Set the balance. -/// fn set_balance(val: u64); -/// } -/// -/// /// You can declare multiple api traits in one macro call. -/// /// In one module you can call the macro at maximum one time. -/// pub trait BlockBuilder { -/// /// The macro adds an explicit `Block: BlockT` generic parameter for you. -/// /// You can use this generic parameter as you would defined it manually. -/// fn build_block() -> Block; -/// } -/// } -/// -/// # fn main() {} -/// ``` -/// -/// # Runtime api trait versioning -/// -/// 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. 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 client; -/// -/// decl_runtime_apis! { -/// /// Declare the api trait. -/// #[api_version(2)] -/// pub trait Balance { -/// /// Get the balance. -/// fn get_balance() -> u64; -/// /// 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: u16); -/// /// In version 2, we added this new function. -/// fn increase_balance(val: u64); -/// } -/// } -/// -/// # fn main() {} -/// ``` -/// -/// To check if a given runtime implements a runtime api trait, the `RuntimeVersion` has the -/// function `has_api()`. Also the `ApiExt` provides a function `has_api(at: &BlockId)` to -/// check if the runtime at the given block id implements the requested runtime api trait. -#[proc_macro] -pub fn decl_runtime_apis(input: TokenStream) -> TokenStream { - decl_runtime_apis::decl_runtime_apis_impl(input) -} diff --git a/core/sr-api-macros/src/utils.rs b/core/sr-api-macros/src/utils.rs deleted file mode 100644 index 21000f431b815..0000000000000 --- a/core/sr-api-macros/src/utils.rs +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use proc_macro2::{TokenStream, Span}; -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 { - res.unwrap_or_else(|e| e.to_compile_error()) -} - -fn generate_hidden_includes_mod_name(unique_id: &'static str) -> Ident { - Ident::new(&format!("sr_api_hidden_includes_{}", unique_id), Span::call_site()) -} - -/// Generates the hidden includes that are required to make the macro independent from its scope. -pub fn generate_hidden_includes(unique_id: &'static str) -> TokenStream { - if env::var("CARGO_PKG_NAME").unwrap() == "substrate-client" { - TokenStream::new() - } else { - let mod_name = generate_hidden_includes_mod_name(unique_id); - 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 `substrate_client` crate. -pub fn generate_crate_access(unique_id: &'static str) -> TokenStream { - if env::var("CARGO_PKG_NAME").unwrap() == "substrate-client" { - quote!( crate ) - } else { - let mod_name = generate_hidden_includes_mod_name(unique_id); - quote!( self::#mod_name::sr_api_client ) - }.into() -} - -/// Generates the name of the module that contains the trait declaration for the runtime. -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(trait_: &Ident, method: &Ident) -> Ident { - Ident::new(&format!("{}_{}_runtime_api_impl", trait_, method), 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 `&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 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()) -} - -/// Generates the name for the call api at function. -pub fn generate_call_api_at_fn_name(fn_name: &Ident) -> Ident { - Ident::new(&format!("{}_call_api_at", fn_name.to_string()), Span::call_site()) -} - -/// Prefix the given function with the trait name. -pub fn prefix_function_with_trait(trait_: &Ident, function: &F) -> String { - format!("{}_{}", trait_.to_string(), function.to_string()) -} diff --git a/core/sr-api-macros/tests/decl_and_impl.rs b/core/sr-api-macros/tests/decl_and_impl.rs deleted file mode 100644 index a539d838221be..0000000000000 --- a/core/sr-api-macros/tests/decl_and_impl.rs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use sr_primitives::traits::{GetNodeBlockType, Block as BlockT}; -use sr_primitives::generic::BlockId; -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` -/// trait are done by the `construct_runtime!` macro in a real runtime. -pub struct Runtime {} -impl GetNodeBlockType for Runtime { - type NodeBlock = Block; -} - -decl_runtime_apis! { - pub trait Api { - fn test(data: u64); - fn something_with_block(block: Block) -> Block; - fn function_with_two_args(data: u64, block: Block); - fn same_name(); - } - - #[api_version(2)] - pub trait ApiWithCustomVersion { - fn same_name(); - #[changed_in(2)] - fn same_name() -> String; - } -} - -impl_runtime_apis! { - impl self::Api for Runtime { - fn test(_: u64) { - unimplemented!() - } - - fn something_with_block(_: Block) -> Block { - unimplemented!() - } - - fn function_with_two_args(_: u64, _: Block) { - unimplemented!() - } - - fn same_name() {} - } - - impl self::ApiWithCustomVersion for Runtime { - fn same_name() {} - } - - impl runtime_api::Core for Runtime { - fn version() -> runtime_api::RuntimeVersion { - unimplemented!() - } - fn execute_block(_: Block) { - unimplemented!() - } - fn initialize_block(_: &::Header) { - unimplemented!() - } - } -} - -type TestClient = client::Client; - -#[test] -fn test_client_side_function_signature() { - 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] -fn check_runtime_api_info() { - assert_eq!(&Api::::ID, &runtime_decl_for_Api::ID); - assert_eq!(Api::::VERSION, runtime_decl_for_Api::VERSION); - assert_eq!(Api::::VERSION, 1); - - assert_eq!( - ApiWithCustomVersion::::VERSION, runtime_decl_for_ApiWithCustomVersion::VERSION - ); - assert_eq!(&ApiWithCustomVersion::::ID, &runtime_decl_for_ApiWithCustomVersion::ID); - assert_eq!(ApiWithCustomVersion::::VERSION, 2); -} - -fn check_runtime_api_versions_contains() { - assert!(RUNTIME_API_VERSIONS.iter().any(|v| v == &(T::ID, T::VERSION))); -} - -#[test] -fn check_runtime_api_versions() { - check_runtime_api_versions_contains::>(); - check_runtime_api_versions_contains::>(); - check_runtime_api_versions_contains::>(); -} diff --git a/core/sr-api-macros/tests/trybuild.rs b/core/sr-api-macros/tests/trybuild.rs deleted file mode 100644 index 9baea83196e9b..0000000000000 --- a/core/sr-api-macros/tests/trybuild.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::env; - -#[rustversion::attr(not(stable), ignore)] -#[test] -fn ui() { - // As trybuild is using `cargo check`, we don't need the real WASM binaries. - env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); - - let t = trybuild::TestCases::new(); - t.compile_fail("tests/ui/*.rs"); -} diff --git a/core/sr-api-macros/tests/ui/adding_at_parameter.rs b/core/sr-api-macros/tests/ui/adding_at_parameter.rs deleted file mode 100644 index d4757e256f024..0000000000000 --- a/core/sr-api-macros/tests/ui/adding_at_parameter.rs +++ /dev/null @@ -1,9 +0,0 @@ -use client::decl_runtime_apis; - -decl_runtime_apis! { - pub trait Api { - fn test(at: u64); - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/adding_at_parameter.stderr b/core/sr-api-macros/tests/ui/adding_at_parameter.stderr deleted file mode 100644 index 1c7e07a418c0a..0000000000000 --- a/core/sr-api-macros/tests/ui/adding_at_parameter.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: `decl_runtime_apis!` adds automatically a parameter `at: &BlockId`. Please rename/remove your parameter. - --> $DIR/adding_at_parameter.rs:5:11 - | -5 | fn test(at: u64); - | ^^ diff --git a/core/sr-api-macros/tests/ui/adding_self_parameter.rs b/core/sr-api-macros/tests/ui/adding_self_parameter.rs deleted file mode 100644 index fb048211adac3..0000000000000 --- a/core/sr-api-macros/tests/ui/adding_self_parameter.rs +++ /dev/null @@ -1,9 +0,0 @@ -use client::decl_runtime_apis; - -decl_runtime_apis! { - pub trait Api { - fn test(&self); - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/adding_self_parameter.stderr b/core/sr-api-macros/tests/ui/adding_self_parameter.stderr deleted file mode 100644 index e7249e9f732f5..0000000000000 --- a/core/sr-api-macros/tests/ui/adding_self_parameter.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: Self values are not supported. - --> $DIR/adding_self_parameter.rs:5:11 - | -5 | fn test(&self); - | ^ diff --git a/core/sr-api-macros/tests/ui/changed_in_unknown_version.rs b/core/sr-api-macros/tests/ui/changed_in_unknown_version.rs deleted file mode 100644 index 127236200517f..0000000000000 --- a/core/sr-api-macros/tests/ui/changed_in_unknown_version.rs +++ /dev/null @@ -1,20 +0,0 @@ -use sr_primitives::traits::GetNodeBlockType; -use test_client::runtime::Block; -use client::decl_runtime_apis; - -/// 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/tests/ui/changed_in_unknown_version.stderr b/core/sr-api-macros/tests/ui/changed_in_unknown_version.stderr deleted file mode 100644 index c62befbab362a..0000000000000 --- a/core/sr-api-macros/tests/ui/changed_in_unknown_version.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: `changed_in` version can not be greater than the `api_version` - --> $DIR/changed_in_unknown_version.rs:15:3 - | -15 | fn test(data: u64); - | ^^ diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.rs b/core/sr-api-macros/tests/ui/declaring_old_block.rs deleted file mode 100644 index 78d35579fae0c..0000000000000 --- a/core/sr-api-macros/tests/ui/declaring_old_block.rs +++ /dev/null @@ -1,10 +0,0 @@ -use sr_primitives::traits::Block as BlockT; -use client::decl_runtime_apis; - -decl_runtime_apis! { - pub trait Api { - fn test(); - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.stderr b/core/sr-api-macros/tests/ui/declaring_old_block.stderr deleted file mode 100644 index 999a50cc96977..0000000000000 --- a/core/sr-api-macros/tests/ui/declaring_old_block.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! - --> $DIR/declaring_old_block.rs:5:16 - | -5 | pub trait Api { - | ^^^^^ - -error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally. - --> $DIR/declaring_old_block.rs:5:23 - | -5 | pub trait Api { - | ^^^^^^ - -warning: unused import: `sr_primitives::traits::Block as BlockT` - --> $DIR/declaring_old_block.rs:1:5 - | -1 | use sr_primitives::traits::Block as BlockT; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.rs b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.rs deleted file mode 100644 index d63eadc1e4b73..0000000000000 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.rs +++ /dev/null @@ -1,10 +0,0 @@ -use sr_primitives::traits::Block as BlockT; -use client::decl_runtime_apis; - -decl_runtime_apis! { - pub trait Api { - fn test(); - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr deleted file mode 100644 index ec033f2e09d23..0000000000000 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally. - --> $DIR/declaring_own_block_with_different_name.rs:5:19 - | -5 | pub trait Api { - | ^^^^^^ - -warning: unused import: `sr_primitives::traits::Block as BlockT` - --> $DIR/declaring_own_block_with_different_name.rs:1:5 - | -1 | use sr_primitives::traits::Block as BlockT; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default diff --git a/core/sr-api-macros/tests/ui/empty_impl_runtime_apis_call.rs b/core/sr-api-macros/tests/ui/empty_impl_runtime_apis_call.rs deleted file mode 100644 index c9c334f6fdcb5..0000000000000 --- a/core/sr-api-macros/tests/ui/empty_impl_runtime_apis_call.rs +++ /dev/null @@ -1,20 +0,0 @@ -use sr_primitives::traits::GetNodeBlockType; -use test_client::runtime::Block; -use client::{decl_runtime_apis, impl_runtime_apis}; - -/// 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 { - fn test(data: u64); - } -} - -impl_runtime_apis! {} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/empty_impl_runtime_apis_call.stderr b/core/sr-api-macros/tests/ui/empty_impl_runtime_apis_call.stderr deleted file mode 100644 index 61527a3480361..0000000000000 --- a/core/sr-api-macros/tests/ui/empty_impl_runtime_apis_call.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: No api implementation given! - --> $DIR/empty_impl_runtime_apis_call.rs:18:1 - | -18 | impl_runtime_apis! {} - | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.rs b/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.rs deleted file mode 100644 index b85431f3ba049..0000000000000 --- a/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.rs +++ /dev/null @@ -1,36 +0,0 @@ -use sr_primitives::traits::{GetNodeBlockType, Block as BlockT}; -use test_client::runtime::Block; -use client::{decl_runtime_apis, impl_runtime_apis, runtime_api}; - -/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` -/// trait are done by the `construct_runtime!` macro in a real runtime. -struct Runtime {} -impl GetNodeBlockType for Runtime { - type NodeBlock = Block; -} - -decl_runtime_apis! { - pub trait Api { - fn test(data: u64); - } -} - -impl_runtime_apis! { - impl self::Api for Runtime { - fn test(data: String) {} - } - - impl runtime_api::Core for Runtime { - fn version() -> runtime_api::RuntimeVersion { - unimplemented!() - } - fn execute_block(_: Block) { - unimplemented!() - } - fn initialize_block(_: &::Header) { - unimplemented!() - } - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.stderr b/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.stderr deleted file mode 100644 index 025ca60c48095..0000000000000 --- a/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.stderr +++ /dev/null @@ -1,51 +0,0 @@ -error[E0053]: method `test` has an incompatible type for trait - --> $DIR/impl_incorrect_method_signature.rs:20:17 - | -14 | fn test(data: u64); - | --- type in trait -... -20 | fn test(data: String) {} - | ^^^^^^ expected u64, found struct `std::string::String` - | - = note: expected type `fn(u64)` - found type `fn(std::string::String)` - -error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for trait - --> $DIR/impl_incorrect_method_signature.rs:18:1 - | -12 | / decl_runtime_apis! { -13 | | pub trait Api { -14 | | fn test(data: u64); -15 | | } -16 | | } - | |_- type in trait -17 | -18 | impl_runtime_apis! { - | ^^^^^^^^^^^^^^^^^^ expected u64, found struct `std::string::String` - | - = note: expected type `fn(&RuntimeApiImpl, &sr_primitives::generic::block::BlockId, substrate_test_runtime::Extrinsic>>, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::error::Error>` - found type `fn(&RuntimeApiImpl, &sr_primitives::generic::block::BlockId, substrate_test_runtime::Extrinsic>>, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::error::Error>` - -error[E0308]: mismatched types - --> $DIR/impl_incorrect_method_signature.rs:18:1 - | -18 | / impl_runtime_apis! { -19 | | impl self::Api for Runtime { -20 | | fn test(data: String) {} -21 | | } -... | -33 | | } -34 | | } - | |_^ expected u64, found struct `std::string::String` - | - = note: expected type `u64` - found type `std::string::String` - -error[E0308]: mismatched types - --> $DIR/impl_incorrect_method_signature.rs:20:11 - | -20 | fn test(data: String) {} - | ^^^^ expected u64, found struct `std::string::String` - | - = note: expected type `u64` - found type `std::string::String` diff --git a/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.rs b/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.rs deleted file mode 100644 index 1664bec577b57..0000000000000 --- a/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.rs +++ /dev/null @@ -1,38 +0,0 @@ -use sr_primitives::traits::GetNodeBlockType; -use test_client::runtime::Block; -use client::{decl_runtime_apis, impl_runtime_apis}; - -/// 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 { - fn test(data: u64); - } -} - -mod second { - use super::*; - - decl_runtime_apis! { - pub trait Api { - fn test2(data: u64); - } - } -} - -impl_runtime_apis! { - impl self::Api for Runtime { - fn test(data: u64) {} - } - - impl second::Api for Runtime { - fn test2(data: u64) {} - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.stderr b/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.stderr deleted file mode 100644 index 4c37b6b716a0a..0000000000000 --- a/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: Two traits with the same name detected! The trait name is used to generate its ID. Please rename one trait at the declaration! - --> $DIR/impl_two_traits_with_same_name.rs:33:15 - | -33 | impl second::Api for Runtime { - | ^^^ - -error[E0277]: the trait bound `RuntimeApiImpl: sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::Core, substrate_test_runtime::Extrinsic>>` is not satisfied - --> $DIR/impl_two_traits_with_same_name.rs:29:7 - | -29 | impl self::Api for Runtime { - | ^^^^^^^^^^^^^^^^ the trait `sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::Core, substrate_test_runtime::Extrinsic>>` is not implemented for `RuntimeApiImpl` - -error[E0277]: the trait bound `RuntimeApiImpl: sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::Core, substrate_test_runtime::Extrinsic>>` is not satisfied - --> $DIR/impl_two_traits_with_same_name.rs:33:7 - | -33 | impl second::Api for Runtime { - | ^^^^^^^^^^^^^^^^^^ the trait `sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::Core, substrate_test_runtime::Extrinsic>>` is not implemented for `RuntimeApiImpl` diff --git a/core/sr-api-macros/tests/ui/invalid_api_version.rs b/core/sr-api-macros/tests/ui/invalid_api_version.rs deleted file mode 100644 index b5afa1d6998ef..0000000000000 --- a/core/sr-api-macros/tests/ui/invalid_api_version.rs +++ /dev/null @@ -1,10 +0,0 @@ -use client::decl_runtime_apis; - -decl_runtime_apis! { - #[api_version] - pub trait Api { - fn test(data: u64); - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/invalid_api_version.stderr b/core/sr-api-macros/tests/ui/invalid_api_version.stderr deleted file mode 100644 index e7d6aa0ed133f..0000000000000 --- a/core/sr-api-macros/tests/ui/invalid_api_version.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error: can't qualify macro invocation with `pub` - --> $DIR/invalid_api_version.rs:3:1 - | -3 | / decl_runtime_apis! { -4 | | #[api_version] -5 | | pub trait Api { -6 | | fn test(data: u64); -7 | | } -8 | | } - | |_^ - | - = help: try adjusting the macro to put `pub` inside the invocation - -error: Unexpected `api_version` attribute. The supported format is `api_version(1)` - --> $DIR/invalid_api_version.rs:3:1 - | -3 | / decl_runtime_apis! { -4 | | #[api_version] -5 | | pub trait Api { -6 | | fn test(data: u64); -7 | | } -8 | | } - | |_^ - -error: Unexpected `api_version` attribute. The supported format is `api_version(1)` - --> $DIR/invalid_api_version.rs:4:4 - | -4 | #[api_version] - | ^^^^^^^^^^^ diff --git a/core/sr-api-macros/tests/ui/invalid_api_version_2.rs b/core/sr-api-macros/tests/ui/invalid_api_version_2.rs deleted file mode 100644 index b8870838009bf..0000000000000 --- a/core/sr-api-macros/tests/ui/invalid_api_version_2.rs +++ /dev/null @@ -1,10 +0,0 @@ -use client::decl_runtime_apis; - -decl_runtime_apis! { - #[api_version("1")] - pub trait Api { - fn test(data: u64); - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/invalid_api_version_2.stderr b/core/sr-api-macros/tests/ui/invalid_api_version_2.stderr deleted file mode 100644 index 3e46efb258052..0000000000000 --- a/core/sr-api-macros/tests/ui/invalid_api_version_2.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error: can't qualify macro invocation with `pub` - --> $DIR/invalid_api_version_2.rs:3:1 - | -3 | / decl_runtime_apis! { -4 | | #[api_version("1")] -5 | | pub trait Api { -6 | | fn test(data: u64); -7 | | } -8 | | } - | |_^ - | - = help: try adjusting the macro to put `pub` inside the invocation - -error: Unexpected `api_version` attribute. The supported format is `api_version(1)` - --> $DIR/invalid_api_version_2.rs:3:1 - | -3 | / decl_runtime_apis! { -4 | | #[api_version("1")] -5 | | pub trait Api { -6 | | fn test(data: u64); -7 | | } -8 | | } - | |_^ - -error: Unexpected `api_version` attribute. The supported format is `api_version(1)` - --> $DIR/invalid_api_version_2.rs:4:4 - | -4 | #[api_version("1")] - | ^^^^^^^^^^^ diff --git a/core/sr-api-macros/tests/ui/invalid_api_version_3.rs b/core/sr-api-macros/tests/ui/invalid_api_version_3.rs deleted file mode 100644 index 6f365b146b222..0000000000000 --- a/core/sr-api-macros/tests/ui/invalid_api_version_3.rs +++ /dev/null @@ -1,10 +0,0 @@ -use client::decl_runtime_apis; - -decl_runtime_apis! { - #[api_version()] - pub trait Api { - fn test(data: u64); - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/invalid_api_version_3.stderr b/core/sr-api-macros/tests/ui/invalid_api_version_3.stderr deleted file mode 100644 index 661221f28e892..0000000000000 --- a/core/sr-api-macros/tests/ui/invalid_api_version_3.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error: can't qualify macro invocation with `pub` - --> $DIR/invalid_api_version_3.rs:3:1 - | -3 | / decl_runtime_apis! { -4 | | #[api_version()] -5 | | pub trait Api { -6 | | fn test(data: u64); -7 | | } -8 | | } - | |_^ - | - = help: try adjusting the macro to put `pub` inside the invocation - -error: Unexpected `api_version` attribute. The supported format is `api_version(1)` - --> $DIR/invalid_api_version_3.rs:3:1 - | -3 | / decl_runtime_apis! { -4 | | #[api_version()] -5 | | pub trait Api { -6 | | fn test(data: u64); -7 | | } -8 | | } - | |_^ - -error: Unexpected `api_version` attribute. The supported format is `api_version(1)` - --> $DIR/invalid_api_version_3.rs:4:4 - | -4 | #[api_version()] - | ^^^^^^^^^^^ diff --git a/core/sr-api-macros/tests/ui/missing_block_generic_parameter.rs b/core/sr-api-macros/tests/ui/missing_block_generic_parameter.rs deleted file mode 100644 index 99755144f7556..0000000000000 --- a/core/sr-api-macros/tests/ui/missing_block_generic_parameter.rs +++ /dev/null @@ -1,26 +0,0 @@ -use sr_primitives::traits::GetNodeBlockType; -use test_client::runtime::Block; -use client::{decl_runtime_apis, impl_runtime_apis}; - -/// 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 { - fn test(data: u64); - } -} - -impl_runtime_apis! { - impl self::Api for Runtime { - fn test(data: u64) { - unimplemented!() - } - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/missing_block_generic_parameter.stderr b/core/sr-api-macros/tests/ui/missing_block_generic_parameter.stderr deleted file mode 100644 index 5c8563a8b89d0..0000000000000 --- a/core/sr-api-macros/tests/ui/missing_block_generic_parameter.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: Missing `Block` generic parameter. - --> $DIR/missing_block_generic_parameter.rs:19:13 - | -19 | impl self::Api for Runtime { - | ^^^ - -error[E0107]: wrong number of type arguments: expected 1, found 0 - --> $DIR/missing_block_generic_parameter.rs:19:7 - | -19 | impl self::Api for Runtime { - | ^^^^^^^^^ expected 1 type argument - -For more information about this error, try `rustc --explain E0107`. diff --git a/core/sr-api-macros/tests/ui/missing_path_for_trait.rs b/core/sr-api-macros/tests/ui/missing_path_for_trait.rs deleted file mode 100644 index f6f6e3dfb3c43..0000000000000 --- a/core/sr-api-macros/tests/ui/missing_path_for_trait.rs +++ /dev/null @@ -1,26 +0,0 @@ -use sr_primitives::traits::GetNodeBlockType; -use test_client::runtime::Block; -use client::{decl_runtime_apis, impl_runtime_apis}; - -/// 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 { - fn test(data: u64); - } -} - -impl_runtime_apis! { - impl Api for Runtime { - fn test(data: u64) { - unimplemented!() - } - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/missing_path_for_trait.stderr b/core/sr-api-macros/tests/ui/missing_path_for_trait.stderr deleted file mode 100644 index 4018712e3f5b3..0000000000000 --- a/core/sr-api-macros/tests/ui/missing_path_for_trait.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: The implemented trait has to be referenced with a path, e.g. `impl client::Core for Runtime`. - --> $DIR/missing_path_for_trait.rs:19:7 - | -19 | impl Api for Runtime { - | ^^^ diff --git a/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.rs b/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.rs deleted file mode 100644 index 20f114c6bb29e..0000000000000 --- a/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.rs +++ /dev/null @@ -1,38 +0,0 @@ -use sr_primitives::traits::{GetNodeBlockType, Block as BlockT}; -use test_client::runtime::Block; -use client::{decl_runtime_apis, impl_runtime_apis, runtime_api}; - -/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` -/// trait are done by the `construct_runtime!` macro in a real runtime. -struct Runtime {} -impl GetNodeBlockType for Runtime { - type NodeBlock = Block; -} - -decl_runtime_apis! { - pub trait Api { - fn test(data: u64); - } -} - -impl_runtime_apis! { - impl self::Api for Runtime { - fn test(data: &u64) { - unimplemented!() - } - } - - impl runtime_api::Core for Runtime { - fn version() -> runtime_api::RuntimeVersion { - unimplemented!() - } - fn execute_block(_: Block) { - unimplemented!() - } - fn initialize_block(_: &::Header) { - unimplemented!() - } - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.stderr deleted file mode 100644 index f3abaddd6ea9d..0000000000000 --- a/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.stderr +++ /dev/null @@ -1,42 +0,0 @@ -error[E0053]: method `test` has an incompatible type for trait - --> $DIR/type_reference_in_impl_runtime_apis_call.rs:20:17 - | -14 | fn test(data: u64); - | --- type in trait -... -20 | fn test(data: &u64) { - | ^^^^ expected u64, found &u64 - | - = note: expected type `fn(u64)` - found type `fn(&u64)` - -error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for trait - --> $DIR/type_reference_in_impl_runtime_apis_call.rs:18:1 - | -12 | / decl_runtime_apis! { -13 | | pub trait Api { -14 | | fn test(data: u64); -15 | | } -16 | | } - | |_- type in trait -17 | -18 | impl_runtime_apis! { - | ^^^^^^^^^^^^^^^^^^ expected u64, found &u64 - | - = note: expected type `fn(&RuntimeApiImpl, &sr_primitives::generic::block::BlockId, substrate_test_runtime::Extrinsic>>, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::error::Error>` - found type `fn(&RuntimeApiImpl, &sr_primitives::generic::block::BlockId, substrate_test_runtime::Extrinsic>>, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::ExecutionContext, std::option::Option<&u64>, std::vec::Vec) -> std::result::Result, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::error::Error>` - -error[E0308]: mismatched types - --> $DIR/type_reference_in_impl_runtime_apis_call.rs:18:1 - | -18 | / impl_runtime_apis! { -19 | | impl self::Api for Runtime { -20 | | fn test(data: &u64) { -21 | | unimplemented!() -... | -35 | | } -36 | | } - | |_^ expected u64, found &u64 - | - = note: expected type `u64` - found type `&u64` diff --git a/core/sr-arithmetic/Cargo.toml b/core/sr-arithmetic/Cargo.toml deleted file mode 100644 index 3962daf493146..0000000000000 --- a/core/sr-arithmetic/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "sr-arithmetic" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -integer-sqrt = "0.1.2" -num-traits = { version = "0.2.8", default-features = false } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -serde = { version = "1.0.101", optional = true, features = ["derive"] } -substrate-debug-derive = { path = "../primitives/debug-derive", default-features = false } - -[dev-dependencies] -primitive-types = "0.6.0" -rand = "0.7.2" - -[features] -bench = [] -default = ["std"] -std = [ - "codec/std", - "num-traits/std", - "rstd/std", - "serde", - "substrate-debug-derive/std", -] diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml deleted file mode 100644 index 482905c435010..0000000000000 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "sr-arithmetic-fuzzer" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -sr-arithmetic = { path = ".." } -honggfuzz = "0.5" -primitive-types = "0.6" -num-bigint = "0.2" -num-traits = "0.2" - -[workspace] - -[[bin]] -name = "biguint" -path = "src/biguint.rs" - -[[bin]] -name = "rational128" -path = "src/rational128.rs" diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs deleted file mode 100644 index bd270a97cac71..0000000000000 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Running -//! Running this fuzzer can be done with `cargo hfuzz run biguint`. `honggfuzz` CLI options can -//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. -//! -//! # Debugging a panic -//! Once a panic is found, it can be debugged with -//! `cargo hfuzz run-debug biguint hfuzz_workspace/biguint/*.fuzz`. -//! -//! # More infomation -//! More information about `honggfuzz` can be found -//! [here](https://docs.rs/honggfuzz/). - -use honggfuzz::fuzz; -use sr_arithmetic::biguint::{BigUint, Single}; -use std::convert::TryFrom; - -fn main() { - loop { - fuzz!(|data: (Vec, Vec, bool)| { - let (mut digits_u, mut digits_v, return_remainder) = data; - - let mut u = BigUint::from_limbs(&digits_u); - let mut v = BigUint::from_limbs(&digits_v); - - u.lstrip(); - v.lstrip(); - - let ue = u128::try_from(u.clone()); - let ve = u128::try_from(v.clone()); - - digits_u.reverse(); - digits_v.reverse(); - - let num_u = num_bigint::BigUint::new(digits_u.clone()); - let num_v = num_bigint::BigUint::new(digits_v.clone()); - - if check_digit_lengths(&u, &v, 4) { - assert_eq!(u.cmp(&v), ue.cmp(&ve)); - assert_eq!(u.eq(&v), ue.eq(&ve)); - } - - if check_digit_lengths(&u, &v, 3) { - let expected = ue.unwrap() + ve.unwrap(); - let t = u.clone().add(&v); - assert_eq!( - u128::try_from(t.clone()).unwrap(), expected, - "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - } - - if check_digit_lengths(&u, &v, 4) { - let expected = ue.unwrap().checked_sub(ve.unwrap()); - let t = u.clone().sub(&v); - if expected.is_none() { - assert!(t.is_err()) - } else { - let t = t.unwrap(); - let expected = expected.unwrap(); - assert_eq!( - u128::try_from(t.clone()).unwrap(), expected, - "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - } - } - - if check_digit_lengths(&u, &v, 2) { - let expected = ue.unwrap() * ve.unwrap(); - let t = u.clone().mul(&v); - assert_eq!( - u128::try_from(t.clone()).unwrap(), expected, - "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - } - - if check_digit_lengths(&u, &v, 4) { - let (ue, ve) = (ue.unwrap(), ve.unwrap()); - if ve == 0 { - return; - } - let (q, r) = (ue / ve, ue % ve); - if let Some((qq, rr)) = u.clone().div(&v, true) { - assert_eq!( - u128::try_from(qq.clone()).unwrap(), q, - "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - assert_eq!( - u128::try_from(rr.clone()).unwrap(), r, - "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, - ); - } else if v.len() == 1 { - let qq = u.clone().div_unit(ve as Single); - assert_eq!( - u128::try_from(qq.clone()).unwrap(), q, - "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - } else if v.msb() != 0 && u.msb() != 0 && u.len() > v.len() { - panic!("div returned none for an unexpected reason"); - } - } - - // Test against num_bigint - - // Equality - - assert_eq!(u.cmp(&v), num_u.cmp(&num_v)); - - // Addition - - let w = u.clone().add(&v); - let num_w = num_u.clone() + &num_v; - - assert_biguints_eq(&w, &num_w); - - // Subtraction - - if let Ok(w) = u.clone().sub(&v) { - let num_w = num_u.clone() - &num_v; - - assert_biguints_eq(&w, &num_w); - } - - // Multiplication - - let w = u.clone().mul(&v); - let num_w = num_u.clone() * &num_v; - - assert_biguints_eq(&w, &num_w); - - // Division - - if v.len() == 1 && v.get(0) != 0 { - let w = u.clone().div_unit(v.get(0)); - let num_w = num_u.clone() / &num_v; - assert_biguints_eq(&w, &num_w); - } else if u.len() > v.len() && v.len() > 0 { - let num_remainder = num_u.clone() % num_v.clone(); - - let (w, remainder) = u.clone().div(&v, return_remainder).unwrap(); - let num_w = num_u.clone() / &num_v; - - assert_biguints_eq(&w, &num_w); - - if return_remainder { - assert_biguints_eq(&remainder, &num_remainder); - } - } - }); - } -} - -fn check_digit_lengths(u: &BigUint, v: &BigUint, max_limbs: usize) -> bool { - 1 <= u.len() && u.len() <= max_limbs && 1 <= v.len() && v.len() <= max_limbs -} - -fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { - let mut a = a.clone(); - a.lstrip(); - - // `num_bigint::BigUint` doesn't expose it's internals, so we need to convert into that to - // compare. - let limbs = (0 .. a.len()).map(|i| a.get(i)).collect(); - let num_a = num_bigint::BigUint::new(limbs); - - assert!(&num_a == b, "\narithmetic: {:?}\nnum-bigint: {:?}", a, b); -} diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs deleted file mode 100644 index b2a00d754527f..0000000000000 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Running -//! Running this fuzzer can be done with `cargo hfuzz run rational128`. `honggfuzz` CLI options can -//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. -//! -//! # Debugging a panic -//! Once a panic is found, it can be debugged with -//! `cargo hfuzz run-debug rational128 hfuzz_workspace/rational128/*.fuzz`. -//! -//! # More infomation -//! More information about `honggfuzz` can be found -//! [here](https://docs.rs/honggfuzz/). - -use honggfuzz::fuzz; -use sr_arithmetic::{helpers_128bit::multiply_by_rational, traits::Zero}; - -fn main() { - loop { - fuzz!(|data: ([u8; 16], [u8; 16], [u8; 16])| { - let (a_bytes, b_bytes, c_bytes) = data; - let (a, b, c) = ( - u128::from_be_bytes(a_bytes), - u128::from_be_bytes(b_bytes), - u128::from_be_bytes(c_bytes), - ); - - println!("++ Equation: {} * {} / {}", a, b, c); - - // The point of this fuzzing is to make sure that `multiply_by_rational` is 100% - // accurate as long as the value fits in a u128. - if let Ok(result) = multiply_by_rational(a, b, c) { - let truth = mul_div(a, b, c); - - if result != truth && result != truth + 1 { - println!("++ Expected {}", truth); - println!("+++++++ Got {}", result); - panic!(); - } - } - }) - } -} - -fn mul_div(a: u128, b: u128, c: u128) -> u128 { - use primitive_types::U256; - if a.is_zero() { - return Zero::zero(); - } - let c = c.max(1); - - // e for extended - let ae: U256 = a.into(); - let be: U256 = b.into(); - let ce: U256 = c.into(); - - let r = ae * be / ce; - if r > u128::max_value().into() { - a - } else { - r.as_u128() - } -} diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs deleted file mode 100644 index c0836e09b301f..0000000000000 --- a/core/sr-arithmetic/src/biguint.rs +++ /dev/null @@ -1,815 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Infinite precision unsigned integer for substrate runtime. - -use num_traits::Zero; -use rstd::{cmp::Ordering, ops, prelude::*, cell::RefCell, convert::TryFrom}; - -// A sensible value for this would be half of the dword size of the host machine. Since the -// runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively -// should yield the most performance. -/// Representation of a single limb. -pub type Single = u32; -/// Representation of two limbs. -pub type Double = u64; -/// Difference in the number of bits of [`Single`] and [`Double`]. -const SHIFT: usize = 32; -/// short form of _Base_. Analogous to the value 10 in base-10 decimal numbers. -const B: Double = Single::max_value() as Double + 1; - -/// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers. -pub fn split(a: Double) -> (Single, Single) { - let al = a as Single; - let ah = (a >> SHIFT) as Single; - (ah, al) -} - -/// Assumed as a given primitive. -/// -/// Multiplication of two singles, which at most yields 1 double. -pub fn mul_single(a: Single, b: Single) -> Double { - let a: Double = a.into(); - let b: Double = b.into(); - a * b -} - -/// Assumed as a given primitive. -/// -/// Addition of two singles, which at most takes a single limb of result and a carry, -/// returned as a tuple respectively. -pub fn add_single(a: Single, b: Single) -> (Single, Single) { - let a: Double = a.into(); - let b: Double = b.into(); - let q = a + b; - let (carry, r) = split(q); - (r, carry) -} - -/// Assumed as a given primitive. -/// -/// Division of double by a single limb. Always returns a double limb of quotient and a single -/// limb of remainder. -fn div_single(a: Double, b: Single) -> (Double, Single) { - let b: Double = b.into(); - let q = a / b; - let r = a % b; - // both conversions are trivially safe. - (q, r as Single) -} - -/// Simple wrapper around an infinitely large integer, represented as limbs of [`Single`]. -#[derive(Clone, Default)] -pub struct BigUint { - /// digits (limbs) of this number (sorted as msb -> lsd). - pub(crate) digits: Vec, -} - -impl BigUint { - /// Create a new instance with `size` limbs. This prevents any number with zero limbs to be - /// created. - /// - /// The behavior of the type is undefined with zero limbs. - pub fn with_capacity(size: usize) -> Self { - Self { digits: vec![0; size.max(1)] } - } - - /// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is - /// used. - pub fn from_limbs(limbs: &[Single]) -> Self { - if !limbs.is_empty() { - Self { digits: limbs.to_vec() } - } else { - Zero::zero() - } - } - - /// Number of limbs. - pub fn len(&self) -> usize { self.digits.len() } - - /// A naive getter for limb at `index`. Note that the order is lsb -> msb. - /// - /// #### Panics - /// - /// This panics if index is out of range. - pub fn get(&self, index: usize) -> Single { - self.digits[self.len() - 1 - index] - } - - /// A naive getter for limb at `index`. Note that the order is lsb -> msb. - pub fn checked_get(&self, index: usize) -> Option { - let i = self.len().checked_sub(1)?; - let j = i.checked_sub(index)?; - self.digits.get(j).cloned() - } - - /// A naive setter for limb at `index`. Note that the order is lsb -> msb. - /// - /// #### Panics - /// - /// This panics if index is out of range. - pub fn set(&mut self, index: usize, value: Single) { - let len = self.digits.len(); - self.digits[len - 1 - index] = value; - } - - /// returns the least significant limb of the number. - /// - /// #### Panics - /// - /// While the constructor of the type prevents this, this can panic if `self` has no digits. - pub fn lsb(&self) -> Single { - self.digits[self.len() - 1] - } - - /// returns the most significant limb of the number. - /// - /// #### Panics - /// - /// While the constructor of the type prevents this, this can panic if `self` has no digits. - pub fn msb(&self) -> Single { - self.digits[0] - } - - /// Strips zeros from the left side (the most significant limbs) of `self`, if any. - pub fn lstrip(&mut self) { - // by definition, a big-int number should never have leading zero limbs. This function - // has the ability to cause this. There is nothing to do if the number already has 1 - // limb only. call it a day and return. - if self.len().is_zero() { return; } - let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(0); - - if index > 0 { - self.digits = self.digits[index..].to_vec() - } - } - - /// Zero-pad `self` from left to reach `size` limbs. Will not make any difference if `self` - /// is already bigger than `size` limbs. - pub fn lpad(&mut self, size: usize) { - let n = self.len(); - if n >= size { return; } - let pad = size - n; - let mut new_digits = (0..pad).map(|_| 0).collect::>(); - new_digits.extend(self.digits.iter()); - self.digits = new_digits; - } - - /// Adds `self` with `other`. self and other do not have to have any particular size. Given - /// that the `n = max{size(self), size(other)}`, it will produce a number with `n + 1` - /// limbs. - /// - /// This function does not strip the output and returns the original allocated `n + 1` - /// limbs. The caller may strip the output if desired. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn add(self, other: &Self) -> Self { - let n = self.len().max(other.len()); - let mut k: Double = 0; - let mut w = Self::with_capacity(n + 1); - - for j in 0..n { - let u = Double::from(self.checked_get(j).unwrap_or(0)); - let v = Double::from(other.checked_get(j).unwrap_or(0)); - let s = u + v + k; - w.set(j, (s % B) as Single); - k = s / B; - } - // k is always 0 or 1. - w.set(n, k as Single); - w - } - - /// Subtracts `other` from `self`. self and other do not have to have any particular size. - /// Given that the `n = max{size(self), size(other)}`, it will produce a number of size `n`. - /// - /// If `other` is bigger than `self`, `Err(B - borrow)` is returned. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn sub(self, other: &Self) -> Result { - let n = self.len().max(other.len()); - let mut k = 0; - let mut w = Self::with_capacity(n); - for j in 0..n { - let s = { - let u = Double::from(self.checked_get(j).unwrap_or(0)); - let v = Double::from(other.checked_get(j).unwrap_or(0)); - let mut needs_borrow = false; - let mut t = 0; - - if let Some(v) = u.checked_sub(v) { - if let Some(v2) = v.checked_sub(k) { - t = v2 % B; - k = 0; - } else { - needs_borrow = true; - } - } else { - needs_borrow = true; - } - if needs_borrow { - t = u + B - v - k; - k = 1; - } - t - }; - // PROOF: t either comes from `v2 % B`, or from `u + B - v - k`. The former is - // trivial. The latter will not overflow this branch will only happen if the sum of - // `u - v - k` part has been negative, hence `u + B - v - k < b`. - w.set(j, s as Single); - } - - if k.is_zero() { - Ok(w) - } else { - Err(w) - } - } - - /// Multiplies n-limb number `self` with m-limb number `other`. - /// - /// The resulting number will always have `n + m` limbs. - /// - /// This function does not strip the output and returns the original allocated `n + m` - /// limbs. The caller may strip the output if desired. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn mul(self, other: &Self) -> Self { - let n = self.len(); - let m = other.len(); - let mut w = Self::with_capacity(m + n); - - for j in 0..n { - if self.get(j) == 0 { - // Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if - // otherwise. - continue; - } - - let mut k = 0; - for i in 0..m { - // PROOF: (B−1) × (B−1) + (B−1) + (B−1) = B^2 −1 < B^2. addition is safe. - let t = - mul_single(self.get(j), other.get(i)) - + Double::from(w.get(i + j)) - + Double::from(k); - w.set(i + j, (t % B) as Single); - // PROOF: (B^2 - 1) / B < B. conversion is safe. - k = (t / B) as Single; - } - w.set(j + m, k); - } - w - } - - /// Divides `self` by a single limb `other`. This can be used in cases where the original - /// division cannot work due to the divisor (`other`) being just one limb. - /// - /// Invariant: `other` cannot be zero. - pub fn div_unit(self, mut other: Single) -> Self { - other = other.max(1); - let n = self.len(); - let mut out = Self::with_capacity(n); - let mut r: Single = 0; - // PROOF: (B-1) * B + (B-1) still fits in double - let with_r = |x: Double, r: Single| { Double::from(r) * B + x }; - for d in (0..n).rev() { - let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ; - out.set(d, q as Single); - r = rr; - } - out - } - - /// Divides an `n + m` limb self by a `n` limb `other`. The result is a `m + 1` limb - /// quotient and a `n` limb remainder, if enabled by passing `true` in `rem` argument, both - /// in the form of an option's `Ok`. - /// - /// - requires `other` to be stripped and have no leading zeros. - /// - requires `self` to be stripped and have no leading zeros. - /// - requires `other` to have at least two limbs. - /// - requires `self` to have a greater length compared to `other`. - /// - /// All arguments are examined without being stripped for the above conditions. If any of - /// the above fails, `None` is returned.` - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn div(self, other: &Self, rem: bool) -> Option<(Self, Self)> { - if other.len() <= 1 - || other.msb() == 0 - || self.msb() == 0 - || self.len() <= other.len() - { - return None - } - let n = other.len(); - let m = self.len() - n; - - let mut q = Self::with_capacity(m + 1); - let mut r = Self::with_capacity(n); - - // PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are - // safe. - let normalizer_bits = other.msb().leading_zeros() as Single; - let normalizer = (2 as Single).pow(normalizer_bits as u32) as Single; - - // step D1. - let mut self_norm = self.mul(&Self::from(normalizer)); - let mut other_norm = other.clone().mul(&Self::from(normalizer)); - - // defensive only; the mul implementation should always create this. - self_norm.lpad(n + m + 1); - other_norm.lstrip(); - - // step D2. - for j in (0..=m).rev() { - // step D3.0 Find an estimate of q[j], named qhat. - let (qhat, rhat) = { - // PROOF: this always fits into `Double`. In the context of Single = u8, and - // Double = u16, think of 255 * 256 + 255 which is just u16::max_value(). - let dividend = - Double::from(self_norm.get(j + n)) - * B - + Double::from(self_norm.get(j + n - 1)); - let divisor = other_norm.get(n - 1); - div_single(dividend, divisor) - }; - - // D3.1 test qhat - // replace qhat and rhat with RefCells. This helps share state with the closure - let qhat = RefCell::new(qhat); - let rhat = RefCell::new(Double::from(rhat)); - - let test = || { - // decrease qhat if it is bigger than the base (B) - let qhat_local = *qhat.borrow(); - let rhat_local = *rhat.borrow(); - let predicate_1 = qhat_local >= B; - let predicate_2 = { - let lhs = qhat_local * Double::from(other_norm.get(n - 2)); - let rhs = B * rhat_local + Double::from(self_norm.get(j + n - 2)); - lhs > rhs - }; - if predicate_1 || predicate_2 { - *qhat.borrow_mut() -= 1; - *rhat.borrow_mut() += Double::from(other_norm.get(n - 1)); - true - } else { - false - } - }; - - test(); - while (*rhat.borrow() as Double) < B { - if !test() { break; } - } - - let qhat = qhat.into_inner(); - // we don't need rhat anymore. just let it go out of scope when it does. - - // step D4 - let lhs = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; - let rhs = other_norm.clone().mul(&Self::from(qhat)); - - let maybe_sub = lhs.sub(&rhs); - let mut negative = false; - let sub = match maybe_sub { - Ok(t) => t, - Err(t) => { negative = true; t } - }; - (j..=j+n).for_each(|d| { self_norm.set(d, sub.get(d - j)); }); - - // step D5 - // PROOF: the `test()` specifically decreases qhat until it is below `B`. conversion - // is safe. - q.set(j, qhat as Single); - - // step D6: add back if negative happened. - if negative { - q.set(j, q.get(j) - 1); - let u = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; - let r = other_norm.clone().add(&u); - (j..=j+n).rev().for_each(|d| { self_norm.set(d, r.get(d - j)); }) - } - } - - // if requested, calculate remainder. - if rem { - // undo the normalization. - if normalizer_bits > 0 { - let s = SHIFT as u32; - let nb = normalizer_bits; - for d in 0..n-1 { - let v = self_norm.get(d) >> nb - | self_norm.get(d + 1).overflowing_shl(s - nb).0; - r.set(d, v); - } - r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits); - } else { - r = self_norm; - } - } - - Some((q, r)) - } -} - -impl rstd::fmt::Debug for BigUint { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { - write!( - f, - "BigUint {{ {:?} ({:?})}}", - self.digits, - u128::try_from(self.clone()).unwrap_or(0), - ) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { - Ok(()) - } - -} - -impl PartialEq for BigUint { - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == Ordering::Equal - } -} - -impl Eq for BigUint {} - -impl Ord for BigUint { - fn cmp(&self, other: &Self) -> Ordering { - let lhs_first = self.digits.iter().position(|&e| e != 0); - let rhs_first = other.digits.iter().position(|&e| e != 0); - - match (lhs_first, rhs_first) { - // edge cases that should not happen. This basically means that one or both were - // zero. - (None, None) => Ordering::Equal, - (Some(_), None) => Ordering::Greater, - (None, Some(_)) => Ordering::Less, - (Some(lhs_idx), Some(rhs_idx)) => { - let lhs = &self.digits[lhs_idx..]; - let rhs = &other.digits[rhs_idx..]; - let len_cmp = lhs.len().cmp(&rhs.len()); - match len_cmp { - Ordering::Equal => lhs.cmp(rhs), - _ => len_cmp, - } - } - } - } -} - -impl PartialOrd for BigUint { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl ops::Add for BigUint { - type Output = Self; - fn add(self, rhs: Self) -> Self::Output { - self.add(&rhs) - } -} - -impl ops::Sub for BigUint { - type Output = Self; - fn sub(self, rhs: Self) -> Self::Output { - self.sub(&rhs).unwrap_or_else(|e| e) - } -} - -impl ops::Mul for BigUint { - type Output = Self; - fn mul(self, rhs: Self) -> Self::Output { - self.mul(&rhs) - } -} - -impl Zero for BigUint { - fn zero() -> Self { - Self { digits: vec![Zero::zero()] } - } - - fn is_zero(&self) -> bool { - self.digits.iter().all(|d| d.is_zero()) - } -} - -macro_rules! impl_try_from_number_for { - ($([$type:ty, $len:expr]),+) => { - $( - impl TryFrom for $type { - type Error = &'static str; - fn try_from(mut value: BigUint) -> Result<$type, Self::Error> { - value.lstrip(); - let error_message = concat!("cannot fit a number into ", stringify!($type)); - if value.len() * SHIFT > $len { - Err(error_message) - } else { - let mut acc: $type = Zero::zero(); - for (i, d) in value.digits.iter().rev().cloned().enumerate() { - let d: $type = d.into(); - acc += d << (SHIFT * i); - } - Ok(acc) - } - } - } - )* - }; -} -// can only be implemented for sizes bigger than two limb. -impl_try_from_number_for!([u128, 128], [u64, 64]); - -macro_rules! impl_from_for_smaller_than_word { - ($($type:ty),+) => { - $(impl From<$type> for BigUint { - fn from(a: $type) -> Self { - Self { digits: vec! [a.into()] } - } - })* - } -} -impl_from_for_smaller_than_word!(u8, u16, Single); - -impl From for BigUint { - fn from(a: Double) -> Self { - let (ah, al) = split(a); - Self { digits: vec![ah, al] } - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - #[cfg(feature = "bench")] - use test::Bencher; - - fn with_limbs(n: usize) -> BigUint { - BigUint { digits: vec![1; n] } - } - - #[test] - fn split_works() { - let a = SHIFT / 2; - let b = SHIFT * 3 / 2; - let num: Double = 1 << a | 1 << b; - // example when `Single = u8` - // assert_eq!(num, 0b_0001_0000_0001_0000) - assert_eq!(split(num), (1 << a, 1 << a)); - } - - #[test] - fn strip_works() { - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1, 0] }); - - let mut a = BigUint::from_limbs(&[0, 0, 1]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1] }); - - let mut a = BigUint::from_limbs(&[0, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); - - let mut a = BigUint::from_limbs(&[0, 0, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); - } - - #[test] - fn lpad_works() { - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(2); - assert_eq!(a.digits, vec![0, 1, 0]); - - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(3); - assert_eq!(a.digits, vec![0, 1, 0]); - - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(4); - assert_eq!(a.digits, vec![0, 0, 1, 0]); - } - - #[test] - fn equality_works() { - assert_eq!( - BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - true, - ); - assert_eq!( - BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - false, - ); - assert_eq!( - BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - true, - ); - } - - #[test] - fn ordering_works() { - assert!(BigUint { digits: vec![0] } < BigUint { digits: vec![1] }); - assert!(BigUint { digits: vec![0] } == BigUint { digits: vec![0] }); - assert!(BigUint { digits: vec![] } == BigUint { digits: vec![0] }); - assert!(BigUint { digits: vec![] } == BigUint { digits: vec![] }); - assert!(BigUint { digits: vec![] } < BigUint { digits: vec![1] }); - - assert!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); - - assert!(BigUint { digits: vec![1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![0, 1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![1, 2, 1, 0] } > BigUint { digits: vec![1, 2, 3] }); - - assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] }); - } - - #[test] - fn can_try_build_numbers_from_types() { - use rstd::convert::TryFrom; - assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1); - assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::max_value() as u64 + 2); - assert_eq!( - u64::try_from(with_limbs(3)).unwrap_err(), - "cannot fit a number into u64", - ); - assert_eq!( - u128::try_from(with_limbs(3)).unwrap(), - u32::max_value() as u128 + u64::max_value() as u128 + 3 - ); - } - - #[test] - fn zero_works() { - assert_eq!(BigUint::zero(), BigUint { digits: vec![0] }); - assert_eq!(BigUint { digits: vec![0, 1, 0] }.is_zero(), false); - assert_eq!(BigUint { digits: vec![0, 0, 0] }.is_zero(), true); - - let a = BigUint::zero(); - let b = BigUint::zero(); - let c = a * b; - assert_eq!(c.digits, vec![0, 0]); - } - - #[test] - fn sub_negative_works() { - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(5 as Single)).unwrap(), - BigUint::from(5 as Single) - ); - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(10 as Single)).unwrap(), - BigUint::from(0 as Single) - ); - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(13 as Single)).unwrap_err(), - BigUint::from((B - 3) as Single), - ); - } - - #[test] - fn mul_always_appends_one_digit() { - let a = BigUint::from(10 as Single); - let b = BigUint::from(4 as Single); - assert_eq!(a.len(), 1); - assert_eq!(b.len(), 1); - - let n = a.mul(&b); - - assert_eq!(n.len(), 2); - assert_eq!(n.digits, vec![0, 40]); - } - - #[test] - fn div_conditions_work() { - let a = BigUint { digits: vec![2] }; - let b = BigUint { digits: vec![1, 2] }; - let c = BigUint { digits: vec![1, 1, 2] }; - let d = BigUint { digits: vec![0, 2] }; - let e = BigUint { digits: vec![0, 1, 1, 2] }; - - assert!(a.clone().div(&b, true).is_none()); - assert!(c.clone().div(&a, true).is_none()); - assert!(c.clone().div(&d, true).is_none()); - assert!(e.clone().div(&a, true).is_none()); - - assert!(c.clone().div(&b, true).is_some()); - } - - #[test] - fn div_unit_works() { - let a = BigUint { digits: vec![100] }; - let b = BigUint { digits: vec![1, 100] }; - - assert_eq!(a.clone().div_unit(1), a); - assert_eq!(a.clone().div_unit(0), a); - assert_eq!(a.clone().div_unit(2), BigUint::from(50 as Single)); - assert_eq!(a.clone().div_unit(7), BigUint::from(14 as Single)); - - assert_eq!(b.clone().div_unit(1), b); - assert_eq!(b.clone().div_unit(0), b); - assert_eq!(b.clone().div_unit(2), BigUint::from(((B + 100) / 2) as Single)); - assert_eq!(b.clone().div_unit(7), BigUint::from(((B + 100) / 7) as Single)); - - } - - #[cfg(feature = "bench")] - fn random_big_uint(size: usize) -> BigUint { - use rand::Rng; - let mut rng = rand::thread_rng(); - let digits = (0..size).map(|_| rng.gen_range(0, Single::max_value())).collect(); - BigUint { digits } - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_addition_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().add(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_addition_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().add(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_subtraction_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().sub(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_subtraction_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().sub(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_multiplication_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().mul(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_multiplication_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().mul(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_division_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().div(&b, true); - }); - } -} diff --git a/core/sr-arithmetic/src/fixed64.rs b/core/sr-arithmetic/src/fixed64.rs deleted file mode 100644 index bd58e36940ae6..0000000000000 --- a/core/sr-arithmetic/src/fixed64.rs +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use rstd::{ - ops, prelude::*, - convert::{TryFrom, TryInto}, -}; -use codec::{Encode, Decode}; -use crate::{ - Perbill, - traits::{ - SaturatedConversion, CheckedSub, CheckedAdd, Bounded, UniqueSaturatedInto, Saturating - } -}; - -/// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036] -/// with fixed point accuracy of one billion. -#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Fixed64(i64); - -/// The accuracy of the `Fixed64` type. -const DIV: i64 = 1_000_000_000; - -impl Fixed64 { - /// creates self from a natural number. - /// - /// Note that this might be lossy. - pub fn from_natural(int: i64) -> Self { - Self(int.saturating_mul(DIV)) - } - - /// Return the accuracy of the type. Given that this function returns the value `X`, it means - /// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`. - pub fn accuracy() -> i64 { - DIV - } - - /// Consume self and return the inner value. - /// - /// This should only be used for testing. - #[cfg(any(feature = "std", test))] - pub fn into_inner(self) -> i64 { self.0 } - - /// Raw constructor. Equal to `parts / 1_000_000_000`. - pub fn from_parts(parts: i64) -> Self { - Self(parts) - } - - /// creates self from a rational number. Equal to `n/d`. - /// - /// Note that this might be lossy. - pub fn from_rational(n: i64, d: u64) -> Self { - Self( - (i128::from(n).saturating_mul(i128::from(DIV)) / i128::from(d).max(1)) - .try_into() - .unwrap_or_else(|_| Bounded::max_value()) - ) - } - - /// Performs a saturated multiply and accumulate by unsigned number. - /// - /// Returns a saturated `int + (self * int)`. - pub fn saturated_multiply_accumulate(self, int: N) -> N - where - N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + - ops::Rem + ops::Div + ops::Mul + - ops::Add, - { - let div = DIV as u64; - let positive = self.0 > 0; - // safe to convert as absolute value. - let parts = self.0.checked_abs().map(|v| v as u64).unwrap_or(i64::max_value() as u64 + 1); - - - // will always fit. - let natural_parts = parts / div; - // might saturate. - let natural_parts: N = natural_parts.saturated_into(); - // fractional parts can always fit into u32. - let perbill_parts = (parts % div) as u32; - - let n = int.clone().saturating_mul(natural_parts); - let p = Perbill::from_parts(perbill_parts) * int.clone(); - - // everything that needs to be either added or subtracted from the original weight. - let excess = n.saturating_add(p); - - if positive { - int.saturating_add(excess) - } else { - int.saturating_sub(excess) - } - } -} - -impl Saturating for Fixed64 { - fn saturating_add(self, rhs: Self) -> Self { - Self(self.0.saturating_add(rhs.0)) - } - fn saturating_mul(self, rhs: Self) -> Self { - Self(self.0.saturating_mul(rhs.0) / DIV) - } - fn saturating_sub(self, rhs: Self) -> Self { - Self(self.0.saturating_sub(rhs.0)) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe addition. -impl ops::Add for Fixed64 { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self(self.0 + rhs.0) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe subtraction. -impl ops::Sub for Fixed64 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) - } -} - -impl CheckedSub for Fixed64 { - fn checked_sub(&self, rhs: &Self) -> Option { - self.0.checked_sub(rhs.0).map(Self) - } -} - -impl CheckedAdd for Fixed64 { - fn checked_add(&self, rhs: &Self) -> Option { - self.0.checked_add(rhs.0).map(Self) - } -} - -impl rstd::fmt::Debug for Fixed64 { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "Fixed64({},{})", self.0 / DIV, (self.0 % DIV) / 1000) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn max() -> Fixed64 { - Fixed64::from_parts(i64::max_value()) - } - - #[test] - fn fixed64_semantics() { - assert_eq!(Fixed64::from_rational(5, 2).0, 5 * 1_000_000_000 / 2); - assert_eq!(Fixed64::from_rational(5, 2), Fixed64::from_rational(10, 4)); - assert_eq!(Fixed64::from_rational(5, 0), Fixed64::from_rational(5, 1)); - - // biggest value that can be created. - assert_ne!(max(), Fixed64::from_natural(9_223_372_036)); - assert_eq!(max(), Fixed64::from_natural(9_223_372_037)); - } - - #[test] - fn fixed_64_growth_decrease_curve() { - let test_set = vec![0u32, 1, 10, 1000, 1_000_000_000]; - - // negative (1/2) - let mut fm = Fixed64::from_rational(-1, 2); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i) as i32, i as i32 - i as i32 / 2); - }); - - // unit (1) multiplier - fm = Fixed64::from_parts(0); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i); - }); - - // i.5 multiplier - fm = Fixed64::from_rational(1, 2); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i * 3 / 2); - }); - - // dual multiplier - fm = Fixed64::from_rational(1, 1); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i * 2); - }); - } - - macro_rules! saturating_mul_acc_test { - ($num_type:tt) => { - assert_eq!( - Fixed64::from_rational(100, 1).saturated_multiply_accumulate(10 as $num_type), - 1010, - ); - assert_eq!( - Fixed64::from_rational(100, 2).saturated_multiply_accumulate(10 as $num_type), - 510, - ); - assert_eq!( - Fixed64::from_rational(100, 3).saturated_multiply_accumulate(0 as $num_type), - 0, - ); - assert_eq!( - Fixed64::from_rational(5, 1).saturated_multiply_accumulate($num_type::max_value()), - $num_type::max_value() - ); - assert_eq!( - max().saturated_multiply_accumulate($num_type::max_value()), - $num_type::max_value() - ); - } - } - - #[test] - fn fixed64_multiply_accumulate_works() { - saturating_mul_acc_test!(u32); - saturating_mul_acc_test!(u64); - saturating_mul_acc_test!(u128); - } -} diff --git a/core/sr-arithmetic/src/lib.rs b/core/sr-arithmetic/src/lib.rs deleted file mode 100644 index 847ca9e797cb0..0000000000000 --- a/core/sr-arithmetic/src/lib.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Minimal fixed point arithmetic primitives and types for runtime. - -#![cfg_attr(not(feature = "std"), no_std)] - -// to allow benchmarking -#![cfg_attr(feature = "bench", feature(test))] -#[cfg(feature = "bench")] extern crate test; - -/// Copied from `sr-primitives` and documented there. -#[cfg(test)] -macro_rules! assert_eq_error_rate { - ($x:expr, $y:expr, $error:expr $(,)?) => { - assert!( - ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), - "{:?} != {:?} (with error rate {:?})", - $x, - $y, - $error, - ); - }; -} - -pub mod biguint; -pub mod helpers_128bit; -pub mod traits; -mod per_things; -mod fixed64; -mod rational128; - -pub use fixed64::Fixed64; -pub use per_things::{Percent, Permill, Perbill, Perquintill}; -pub use rational128::Rational128; diff --git a/core/sr-arithmetic/src/rational128.rs b/core/sr-arithmetic/src/rational128.rs deleted file mode 100644 index 3247321199d61..0000000000000 --- a/core/sr-arithmetic/src/rational128.rs +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use rstd::{cmp::Ordering, prelude::*}; -use crate::helpers_128bit; -use num_traits::Zero; -use substrate_debug_derive::RuntimeDebug; - -/// A wrapper for any rational number with a 128 bit numerator and denominator. -#[derive(Clone, Copy, Default, Eq, RuntimeDebug)] -pub struct Rational128(u128, u128); - -impl Rational128 { - /// Nothing. - pub fn zero() -> Self { - Self(0, 1) - } - - /// If it is zero or not - pub fn is_zero(&self) -> bool { - self.0.is_zero() - } - - /// Build from a raw `n/d`. - pub fn from(n: u128, d: u128) -> Self { - Self(n, d.max(1)) - } - - /// Build from a raw `n/d`. This could lead to / 0 if not properly handled. - pub fn from_unchecked(n: u128, d: u128) -> Self { - Self(n, d) - } - - /// Return the numerator. - pub fn n(&self) -> u128 { - self.0 - } - - /// Return the denominator. - pub fn d(&self) -> u128 { - self.1 - } - - /// Convert `self` to a similar rational number where denominator is the given `den`. - // - /// This only returns if the result is accurate. `Err` is returned if the result cannot be - /// accurately calculated. - pub fn to_den(self, den: u128) -> Result { - if den == self.1 { - Ok(self) - } else { - helpers_128bit::multiply_by_rational(self.0, den, self.1).map(|n| Self(n, den)) - } - } - - /// Get the least common divisor of `self` and `other`. - /// - /// This only returns if the result is accurate. `Err` is returned if the result cannot be - /// accurately calculated. - pub fn lcm(&self, other: &Self) -> Result { - // this should be tested better: two large numbers that are almost the same. - if self.1 == other.1 { return Ok(self.1) } - let g = helpers_128bit::gcd(self.1, other.1); - helpers_128bit::multiply_by_rational(self.1 , other.1, g) - } - - /// A saturating add that assumes `self` and `other` have the same denominator. - pub fn lazy_saturating_add(self, other: Self) -> Self { - if other.is_zero() { - self - } else { - Self(self.0.saturating_add(other.0) ,self.1) - } - } - - /// A saturating subtraction that assumes `self` and `other` have the same denominator. - pub fn lazy_saturating_sub(self, other: Self) -> Self { - if other.is_zero() { - self - } else { - Self(self.0.saturating_sub(other.0) ,self.1) - } - } - - /// Addition. Simply tries to unify the denominators and add the numerators. - /// - /// Overflow might happen during any of the steps. Error is returned in such cases. - pub fn checked_add(self, other: Self) -> Result { - let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; - let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let n = self_scaled.0.checked_add(other_scaled.0) - .ok_or("overflow while adding numerators")?; - Ok(Self(n, self_scaled.1)) - } - - /// Subtraction. Simply tries to unify the denominators and subtract the numerators. - /// - /// Overflow might happen during any of the steps. None is returned in such cases. - pub fn checked_sub(self, other: Self) -> Result { - let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; - let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - - let n = self_scaled.0.checked_sub(other_scaled.0) - .ok_or("overflow while subtracting numerators")?; - Ok(Self(n, self_scaled.1)) - } -} - -impl PartialOrd for Rational128 { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Rational128 { - fn cmp(&self, other: &Self) -> Ordering { - // handle some edge cases. - if self.1 == other.1 { - self.0.cmp(&other.0) - } else if self.1.is_zero() { - Ordering::Greater - } else if other.1.is_zero() { - Ordering::Less - } else { - // Don't even compute gcd. - let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); - let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); - self_n.cmp(&other_n) - } - } -} - -impl PartialEq for Rational128 { - fn eq(&self, other: &Self) -> bool { - // handle some edge cases. - if self.1 == other.1 { - self.0.eq(&other.0) - } else { - let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); - let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); - self_n.eq(&other_n) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use super::helpers_128bit::*; - - const MAX128: u128 = u128::max_value(); - const MAX64: u128 = u64::max_value() as u128; - const MAX64_2: u128 = 2 * u64::max_value() as u128; - - fn r(p: u128, q: u128) -> Rational128 { - Rational128(p, q) - } - - fn mul_div(a: u128, b: u128, c: u128) -> u128 { - use primitive_types::U256; - if a.is_zero() { return Zero::zero(); } - let c = c.max(1); - - // e for extended - let ae: U256 = a.into(); - let be: U256 = b.into(); - let ce: U256 = c.into(); - - let r = ae * be / ce; - if r > u128::max_value().into() { - a - } else { - r.as_u128() - } - } - - #[test] - fn truth_value_function_works() { - assert_eq!( - mul_div(2u128.pow(100), 8, 4), - 2u128.pow(101) - ); - assert_eq!( - mul_div(2u128.pow(100), 4, 8), - 2u128.pow(99) - ); - - // and it returns a if result cannot fit - assert_eq!(mul_div(MAX128 - 10, 2, 1), MAX128 - 10); - } - - #[test] - fn to_denom_works() { - // simple up and down - assert_eq!(r(1, 5).to_den(10), Ok(r(2, 10))); - assert_eq!(r(4, 10).to_den(5), Ok(r(2, 5))); - - // up and down with large numbers - assert_eq!(r(MAX128 - 10, MAX128).to_den(10), Ok(r(10, 10))); - assert_eq!(r(MAX128 / 2, MAX128).to_den(10), Ok(r(5, 10))); - - // large to perbill. This is very well needed for phragmen. - assert_eq!( - r(MAX128 / 2, MAX128).to_den(1000_000_000), - Ok(r(500_000_000, 1000_000_000)) - ); - - // large to large - assert_eq!(r(MAX128 / 2, MAX128).to_den(MAX128/2), Ok(r(MAX128/4, MAX128/2))); - } - - #[test] - fn gdc_works() { - assert_eq!(gcd(10, 5), 5); - assert_eq!(gcd(7, 22), 1); - } - - #[test] - fn lcm_works() { - // simple stuff - assert_eq!(r(3, 10).lcm(&r(4, 15)).unwrap(), 30); - assert_eq!(r(5, 30).lcm(&r(1, 7)).unwrap(), 210); - assert_eq!(r(5, 30).lcm(&r(1, 10)).unwrap(), 30); - - // large numbers - assert_eq!( - r(1_000_000_000, MAX128).lcm(&r(7_000_000_000, MAX128-1)), - Err("result cannot fit in u128"), - ); - assert_eq!( - r(1_000_000_000, MAX64).lcm(&r(7_000_000_000, MAX64-1)), - Ok(340282366920938463408034375210639556610), - ); - assert!(340282366920938463408034375210639556610 < MAX128); - assert!(340282366920938463408034375210639556610 == MAX64 * (MAX64 - 1)); - } - - #[test] - fn add_works() { - // works - assert_eq!(r(3, 10).checked_add(r(1, 10)).unwrap(), r(2, 5)); - assert_eq!(r(3, 10).checked_add(r(3, 7)).unwrap(), r(51, 70)); - - // errors - assert_eq!( - r(1, MAX128).checked_add(r(1, MAX128-1)), - Err("failed to scale to denominator"), - ); - assert_eq!( - r(7, MAX128).checked_add(r(MAX128, MAX128)), - Err("overflow while adding numerators"), - ); - assert_eq!( - r(MAX128, MAX128).checked_add(r(MAX128, MAX128)), - Err("overflow while adding numerators"), - ); - } - - #[test] - fn sub_works() { - // works - assert_eq!(r(3, 10).checked_sub(r(1, 10)).unwrap(), r(1, 5)); - assert_eq!(r(6, 10).checked_sub(r(3, 7)).unwrap(), r(12, 70)); - - // errors - assert_eq!( - r(2, MAX128).checked_sub(r(1, MAX128-1)), - Err("failed to scale to denominator"), - ); - assert_eq!( - r(7, MAX128).checked_sub(r(MAX128, MAX128)), - Err("overflow while subtracting numerators"), - ); - assert_eq!( - r(1, 10).checked_sub(r(2,10)), - Err("overflow while subtracting numerators"), - ); - } - - #[test] - fn ordering_and_eq_works() { - assert!(r(1, 2) > r(1, 3)); - assert!(r(1, 2) > r(2, 6)); - - assert!(r(1, 2) < r(6, 6)); - assert!(r(2, 1) > r(2, 6)); - - assert!(r(5, 10) == r(1, 2)); - assert!(r(1, 2) == r(1, 2)); - - assert!(r(1, 1490000000000200000) > r(1, 1490000000000200001)); - } - - #[test] - fn multiply_by_rational_works() { - assert_eq!(multiply_by_rational(7, 2, 3).unwrap(), 7 * 2 / 3); - assert_eq!(multiply_by_rational(7, 20, 30).unwrap(), 7 * 2 / 3); - assert_eq!(multiply_by_rational(20, 7, 30).unwrap(), 7 * 2 / 3); - - assert_eq!( - // MAX128 % 3 == 0 - multiply_by_rational(MAX128, 2, 3).unwrap(), - MAX128 / 3 * 2, - ); - assert_eq!( - // MAX128 % 7 == 3 - multiply_by_rational(MAX128, 5, 7).unwrap(), - (MAX128 / 7 * 5) + (3 * 5 / 7), - ); - assert_eq!( - // MAX128 % 7 == 3 - multiply_by_rational(MAX128, 11 , 13).unwrap(), - (MAX128 / 13 * 11) + (8 * 11 / 13), - ); - assert_eq!( - // MAX128 % 1000 == 455 - multiply_by_rational(MAX128, 555, 1000).unwrap(), - (MAX128 / 1000 * 555) + (455 * 555 / 1000), - ); - - assert_eq!( - multiply_by_rational(2 * MAX64 - 1, MAX64, MAX64).unwrap(), - 2 * MAX64 - 1, - ); - assert_eq!( - multiply_by_rational(2 * MAX64 - 1, MAX64 - 1, MAX64).unwrap(), - 2 * MAX64 - 3, - ); - - assert_eq!( - multiply_by_rational(MAX64 + 100, MAX64_2, MAX64_2 / 2).unwrap(), - (MAX64 + 100) * 2, - ); - assert_eq!( - multiply_by_rational(MAX64 + 100, MAX64_2 / 100, MAX64_2 / 200).unwrap(), - (MAX64 + 100) * 2, - ); - - assert_eq!( - multiply_by_rational(2u128.pow(66) - 1, 2u128.pow(65) - 1, 2u128.pow(65)).unwrap(), - 73786976294838206461, - ); - assert_eq!( - multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), - 250000000, - ); - } - - #[test] - fn multiply_by_rational_a_b_are_interchangeable() { - assert_eq!( - multiply_by_rational(10, MAX128, MAX128 / 2), - Ok(20), - ); - assert_eq!( - multiply_by_rational(MAX128, 10, MAX128 / 2), - Ok(20), - ); - } - - #[test] - #[ignore] - fn multiply_by_rational_fuzzed_equation() { - assert_eq!( - multiply_by_rational(154742576605164960401588224, 9223376310179529214, 549756068598), - Ok(2596149632101417846585204209223679) - ); - } -} diff --git a/core/sr-arithmetic/src/traits.rs b/core/sr-arithmetic/src/traits.rs deleted file mode 100644 index d02425066ff9d..0000000000000 --- a/core/sr-arithmetic/src/traits.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Primitives for the runtime modules. - -use rstd::{self, convert::{TryFrom, TryInto}}; -use codec::HasCompact; -pub use integer_sqrt::IntegerSquareRoot; -pub use num_traits::{ - Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, - CheckedShl, CheckedShr -}; -use rstd::ops::{ - Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, - RemAssign, Shl, Shr -}; - -/// A meta trait for arithmetic. -/// -/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to -/// be able to represent at least `u32` values without loss, hence the trait implies `From` -/// and smaller ints. All other conversions are fallible. -pub trait SimpleArithmetic: - Zero + One + IntegerSquareRoot + - From + From + From + TryInto + TryInto + TryInto + - TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + - UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + - UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + - Add + AddAssign + - Sub + SubAssign + - Mul + MulAssign + - Div + DivAssign + - Rem + RemAssign + - Shl + Shr + - CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + - Saturating + PartialOrd + Ord + Bounded + - HasCompact + Sized -{} -impl + From + From + TryInto + TryInto + TryInto + - TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + - UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + - UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + - UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + - Add + AddAssign + - Sub + SubAssign + - Mul + MulAssign + - Div + DivAssign + - Rem + RemAssign + - Shl + Shr + - CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + - Saturating + PartialOrd + Ord + Bounded + - HasCompact + Sized -> SimpleArithmetic for T {} - -/// Just like `From` except that if the source value is too big to fit into the destination type -/// then it'll saturate the destination. -pub trait UniqueSaturatedFrom: Sized { - /// Convert from a value of `T` into an equivalent instance of `Self`. - fn unique_saturated_from(t: T) -> Self; -} - -/// Just like `Into` except that if the source value is too big to fit into the destination type -/// then it'll saturate the destination. -pub trait UniqueSaturatedInto: Sized { - /// Consume self to return an equivalent value of `T`. - fn unique_saturated_into(self) -> T; -} - -impl + Bounded + Sized> UniqueSaturatedFrom for S { - fn unique_saturated_from(t: T) -> Self { - S::try_from(t).unwrap_or_else(|_| Bounded::max_value()) - } -} - -impl + Sized> UniqueSaturatedInto for S { - fn unique_saturated_into(self) -> T { - self.try_into().unwrap_or_else(|_| Bounded::max_value()) - } -} - -/// Simple trait to use checked mul and max value to give a saturated mul operation over -/// supported types. -pub trait Saturating { - /// Saturated addition - if the product can't fit in the type then just use max-value. - fn saturating_add(self, o: Self) -> Self; - - /// Saturated subtraction - if the product can't fit in the type then just use max-value. - fn saturating_sub(self, o: Self) -> Self; - - /// Saturated multiply - if the product can't fit in the type then just use max-value. - fn saturating_mul(self, o: Self) -> Self; -} - -impl Saturating for T { - fn saturating_add(self, o: Self) -> Self { - ::saturating_add(self, o) - } - fn saturating_sub(self, o: Self) -> Self { - ::saturating_sub(self, o) - } - fn saturating_mul(self, o: Self) -> Self { - self.checked_mul(&o).unwrap_or_else(Bounded::max_value) - } -} - -/// Convenience type to work around the highly unergonomic syntax needed -/// to invoke the functions of overloaded generic traits, in this case -/// `SaturatedFrom` and `SaturatedInto`. -pub trait SaturatedConversion { - /// Convert from a value of `T` into an equivalent instance of `Self`. - /// - /// This just uses `UniqueSaturatedFrom` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn saturated_from(t: T) -> Self where Self: UniqueSaturatedFrom { - >::unique_saturated_from(t) - } - - /// Consume self to return an equivalent value of `T`. - /// - /// This just uses `UniqueSaturatedInto` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn saturated_into(self) -> T where Self: UniqueSaturatedInto { - >::unique_saturated_into(self) - } -} -impl SaturatedConversion for T {} diff --git a/core/sr-io/Cargo.toml b/core/sr-io/Cargo.toml deleted file mode 100644 index 4d140d289dafe..0000000000000 --- a/core/sr-io/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "sr-io" -version = "2.0.0" -authors = ["Parity Technologies "] -build = "build.rs" -edition = "2018" - -[build-dependencies] -rustc_version = "0.2.3" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -hash-db = { version = "0.15.2", default-features = false } -primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -libsecp256k1 = { version = "0.3.0", optional = true } -tiny-keccak = { version = "1.5.0", optional = true } -substrate-state-machine = { path = "../state-machine", optional = true } -trie = { package = "substrate-trie", path = "../trie", optional = true } -externalities = { package = "substrate-externalities", path = "../externalities", optional = true } -log = { version = "0.4.8", optional = true } - -[features] -default = ["std"] -std = [ - "primitives/std", - "codec/std", - "rstd/std", - "hash-db/std", - "trie", - "substrate-state-machine", - "libsecp256k1", - "tiny-keccak", - "externalities", - "log", -] -nightly = [] -strict = [] - -# These two features are used for `no_std` builds for the environments which already provides -# `#[panic_handler]` and `#[alloc_error_handler]`. -# -# For the regular wasm runtime builds those are not used. -no_panic_handler = [] -no_oom = [] diff --git a/core/sr-io/build.rs b/core/sr-io/build.rs deleted file mode 100644 index 5b5d06b65a253..0000000000000 --- a/core/sr-io/build.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Set a nightly feature - -use rustc_version::{version, version_meta, Channel}; - -fn main() { - // Assert we haven't traveled back in time - assert!(version().unwrap().major >= 1); - - // Set cfg flags depending on release channel - if let Channel::Nightly = version_meta().unwrap().channel { - println!("cargo:rustc-cfg=feature=\"nightly\""); - } -} diff --git a/core/sr-io/src/lib.rs b/core/sr-io/src/lib.rs deleted file mode 100644 index fe5e50b3eda3e..0000000000000 --- a/core/sr-io/src/lib.rs +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! This is part of the Substrate runtime. - -#![warn(missing_docs)] - -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(lang_items))] -#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] -#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] - -#![cfg_attr(feature = "std", doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] -#![cfg_attr(not(feature = "std"), doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] - -use rstd::vec::Vec; - -use primitives::{ - crypto::KeyTypeId, ed25519, sr25519, H256, - offchain::{ - Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, - }, - LogLevel, -}; - -/// Error verifying ECDSA signature -pub enum EcdsaVerifyError { - /// Incorrect value of R or S - BadRS, - /// Incorrect value of V - BadV, - /// Invalid signature - BadSignature, -} - -/// Converts a public trait definition into a private trait and set of public functions -/// that assume the trait is implemented for `()` for ease of calling. -macro_rules! export_api { - ( - $( #[$trait_attr:meta] )* - pub(crate) trait $trait_name:ident { - $( - $( #[$attr:meta] )* - fn $name:ident - ( $( $arg:ident : $arg_ty:ty ),* $(,)? ) - $( -> $ret:ty )? - $( where $( $w_name:path : $w_ty:path ),+ )?; - )* - } - ) => { - $( #[$trait_attr] )* - pub(crate) trait $trait_name { - $( - $( #[$attr] )* - fn $name ( $($arg : $arg_ty ),* ) $( -> $ret )? - $( where $( $w_name : $w_ty ),+ )?; - )* - } - - $( - $( #[$attr] )* - pub fn $name ( $($arg : $arg_ty ),* ) $( -> $ret )? - $( where $( $w_name : $w_ty ),+ )? - { - #[allow(deprecated)] - <()>:: $name ( $( $arg ),* ) - } - )* - } -} - -export_api! { - pub(crate) trait StorageApi { - /// Get `key` from storage and return a `Vec`, empty if there's a problem. - fn storage(key: &[u8]) -> Option>; - - /// Get `key` from child storage and return a `Vec`, empty if there's a problem. - fn child_storage(storage_key: &[u8], key: &[u8]) -> Option>; - - /// Get `key` from storage, placing the value into `value_out` and return the number of - /// bytes that the entry in storage has beyond the offset or `None` if the storage entry - /// doesn't exist at all. - /// If `value_out` length is smaller than the returned length, only `value_out` length bytes - /// are copied into `value_out`. - fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option; - - /// Get `key` from child storage, placing the value into `value_out` and return the number - /// of bytes that the entry in storage has beyond the offset or `None` if the storage entry - /// doesn't exist at all. - /// If `value_out` length is smaller than the returned length, only `value_out` length bytes - /// are copied into `value_out`. - fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option; - - /// Set the storage of some particular key to Some value. - fn set_storage(key: &[u8], value: &[u8]); - - /// Set the child storage of some particular key to Some value. - fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]); - - /// Clear the storage of a key. - fn clear_storage(key: &[u8]); - - /// Clear the storage of a key. - fn clear_child_storage(storage_key: &[u8], key: &[u8]); - - /// Clear an entire child storage. - fn kill_child_storage(storage_key: &[u8]); - - /// Check whether a given `key` exists in storage. - fn exists_storage(key: &[u8]) -> bool; - - /// Check whether a given `key` exists in storage. - fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool; - - /// Clear the storage entries with a key that starts with the given prefix. - fn clear_prefix(prefix: &[u8]); - - /// Clear the child storage entries with a key that starts with the given prefix. - fn clear_child_prefix(storage_key: &[u8], prefix: &[u8]); - - /// "Commit" all existing operations and compute the resultant storage root. - fn storage_root() -> [u8; 32]; - - /// "Commit" all existing operations and compute the resultant child storage root. - fn child_storage_root(storage_key: &[u8]) -> Vec; - - /// "Commit" all existing operations and get the resultant storage change root. - fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]>; - - /// A trie root formed from the iterated items. - fn blake2_256_trie_root(input: Vec<(Vec, Vec)>) -> H256; - - /// A trie root formed from the enumerated items. - fn blake2_256_ordered_trie_root(input: Vec>) -> H256; - } -} - -export_api! { - pub(crate) trait OtherApi { - /// The current relay chain identifier. - fn chain_id() -> u64; - - /// Print a number. - fn print_num(val: u64); - /// Print any valid `utf8` buffer. - fn print_utf8(utf8: &[u8]); - /// Print any `u8` slice as hex. - fn print_hex(data: &[u8]); - - /// Request to print a log message (stderr) on the host. - /// - /// Note that this will be only displayed if the host - /// is enabed to display log messages with given - /// level and target. - /// - /// Instead of using directly, prefer setting up `RuntimeLogger` - /// and using `log` macros. - fn log( - level: LogLevel, - target: &[u8], - message: &[u8] - ); - } -} - -export_api! { - pub(crate) trait CryptoApi { - /// Returns all ed25519 public keys for the given key id from the keystore. - fn ed25519_public_keys(id: KeyTypeId) -> Vec; - /// Generate an ed22519 key for the given key type and store it in the keystore. - /// - /// Returns the raw public key. - fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public; - /// Sign the given `msg` with the ed25519 key that corresponds to the given public key and - /// key type in the keystore. - /// - /// Returns the raw signature. - fn ed25519_sign( - id: KeyTypeId, - pubkey: &ed25519::Public, - msg: &[u8], - ) -> Option; - /// Verify an ed25519 signature. - /// - /// Returns `true` when the verification in successful. - fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool; - - /// Returns all sr25519 public keys for the given key id from the keystore. - fn sr25519_public_keys(id: KeyTypeId) -> Vec; - /// Generate an sr22519 key for the given key type and store it in the keystore. - /// - /// Returns the raw public key. - fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public; - /// Sign the given `msg` with the sr25519 key that corresponds to the given public key and - /// key type in the keystore. - /// - /// Returns the raw signature. - fn sr25519_sign( - id: KeyTypeId, - pubkey: &sr25519::Public, - msg: &[u8], - ) -> Option; - /// Verify an sr25519 signature. - /// - /// Returns `true` when the verification in successful. - fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool; - - /// 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 raw pubkey (doesn't include the 0x04 prefix). - fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError>; - - /// Verify and recover a SECP256k1 ECDSA signature. - /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. - /// - returns `Err` if the signature is bad, otherwise the 33-byte compressed pubkey. - fn secp256k1_ecdsa_recover_compressed(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 33], EcdsaVerifyError>; - } -} - -export_api! { - pub(crate) trait HashingApi { - /// Conduct a 256-bit Keccak hash. - fn keccak_256(data: &[u8]) -> [u8; 32]; - - /// Conduct a 128-bit Blake2 hash. - fn blake2_128(data: &[u8]) -> [u8; 16]; - - /// Conduct a 256-bit Blake2 hash. - fn blake2_256(data: &[u8]) -> [u8; 32]; - - /// Conduct four XX hashes to give a 256-bit result. - fn twox_256(data: &[u8]) -> [u8; 32]; - - /// Conduct two XX hashes to give a 128-bit result. - fn twox_128(data: &[u8]) -> [u8; 16]; - - /// Conduct two XX hashes to give a 64-bit result. - fn twox_64(data: &[u8]) -> [u8; 8]; - } -} - -export_api! { - pub(crate) trait OffchainApi { - /// Returns if the local node is a potential validator. - /// - /// Even if this function returns `true`, it does not mean that any keys are configured - /// and that the validator is registered in the chain. - fn is_validator() -> bool; - - /// Submit transaction to the pool. - /// - /// The transaction will end up in the pool. - fn submit_transaction(data: Vec) -> Result<(), ()>; - - /// Returns information about the local node's network state. - fn network_state() -> Result; - - /// Returns current UNIX timestamp (in millis) - fn timestamp() -> Timestamp; - - /// Pause the execution until `deadline` is reached. - fn sleep_until(deadline: Timestamp); - - /// Returns a random seed. - /// - /// This is a trully random non deterministic seed generated by host environment. - /// Obviously fine in the off-chain worker context. - fn random_seed() -> [u8; 32]; - - /// Sets a value in the local storage. - /// - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_set(kind: StorageKind, key: &[u8], value: &[u8]); - - /// Sets a value in the local storage if it matches current value. - /// - /// Since multiple offchain workers may be running concurrently, to prevent - /// data races use CAS to coordinate between them. - /// - /// Returns `true` if the value has been set, `false` otherwise. - /// - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_compare_and_set( - kind: StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool; - - /// Gets a value from the local storage. - /// - /// If the value does not exist in the storage `None` will be returned. - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_get(kind: StorageKind, key: &[u8]) -> Option>; - - /// Initiates a http request given HTTP verb and the URL. - /// - /// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters. - /// Returns the id of newly started request. - fn http_request_start( - method: &str, - uri: &str, - meta: &[u8], - ) -> Result; - - /// Append header to the request. - fn http_request_add_header( - request_id: HttpRequestId, - name: &str, - value: &str, - ) -> Result<(), ()>; - - /// Write a chunk of request body. - /// - /// Writing an empty chunks finalises the request. - /// Passing `None` as deadline blocks forever. - /// - /// Returns an error in case deadline is reached or the chunk couldn't be written. - fn http_request_write_body( - request_id: HttpRequestId, - chunk: &[u8], - deadline: Option, - ) -> Result<(), HttpError>; - - /// Block and wait for the responses for given requests. - /// - /// Returns a vector of request statuses (the len is the same as ids). - /// Note that if deadline is not provided the method will block indefinitely, - /// otherwise unready responses will produce `DeadlineReached` status. - /// - /// Passing `None` as deadline blocks forever. - fn http_response_wait( - ids: &[HttpRequestId], - deadline: Option, - ) -> Vec; - - /// Read all response headers. - /// - /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. - /// NOTE response headers have to be read before response body. - fn http_response_headers(request_id: HttpRequestId) -> Vec<(Vec, Vec)>; - - /// Read a chunk of body response to given buffer. - /// - /// Returns the number of bytes written or an error in case a deadline - /// is reached or server closed the connection. - /// If `0` is returned it means that the response has been fully consumed - /// and the `request_id` is now invalid. - /// NOTE this implies that response headers must be read before draining the body. - /// Passing `None` as a deadline blocks forever. - fn http_response_read_body( - request_id: HttpRequestId, - buffer: &mut [u8], - deadline: Option, - ) -> Result; - } -} - -/// API trait that should cover all other APIs. -/// -/// Implement this to make sure you implement all APIs. -trait Api: StorageApi + OtherApi + CryptoApi + HashingApi + OffchainApi {} - -mod imp { - use super::*; - - #[cfg(feature = "std")] - include!("../with_std.rs"); - - #[cfg(not(feature = "std"))] - include!("../without_std.rs"); -} - -#[cfg(feature = "std")] -pub use self::imp::{StorageOverlay, ChildrenStorageOverlay, with_storage}; -#[cfg(not(feature = "std"))] -pub use self::imp::ext::*; - -/// Type alias for Externalities implementation used in tests. -#[cfg(feature = "std")] -pub type TestExternalities = self::imp::TestExternalities; diff --git a/core/sr-io/with_std.rs b/core/sr-io/with_std.rs deleted file mode 100644 index fdd32124c129c..0000000000000 --- a/core/sr-io/with_std.rs +++ /dev/null @@ -1,553 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use primitives::{ - blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher, sr25519, Pair, H256, - traits::KeystoreExt, storage::ChildStorageKey, hexdisplay::HexDisplay, Hasher, - offchain::{self, OffchainExt}, -}; -// Switch to this after PoC-3 -// pub use primitives::BlakeHasher; -pub use substrate_state_machine::{BasicExternalities, TestExternalities}; - -use trie::{TrieConfiguration, trie_types::Layout}; - -use std::{collections::HashMap, convert::TryFrom}; - -use externalities::{with_externalities, set_and_run_with_externalities, ExternalitiesExt}; - -/// Additional bounds for `Hasher` trait for with_std. -pub trait HasherBounds {} -impl HasherBounds for T {} - -/// Returns a `ChildStorageKey` if the given `storage_key` slice is a valid storage -/// key or panics otherwise. -/// -/// Panicking here is aligned with what the `without_std` environment would do -/// in the case of an invalid child storage key. -fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { - match ChildStorageKey::from_slice(storage_key) { - Some(storage_key) => storage_key, - None => panic!("child storage key is invalid"), - } -} - -impl StorageApi for () { - fn storage(key: &[u8]) -> Option> { - with_externalities(|ext| ext.storage(key).map(|s| s.to_vec())) - .expect("storage cannot be called outside of an Externalities-provided environment.") - } - - fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { - with_externalities(|ext| ext.storage(key).map(|value| { - let data = &value[value_offset.min(value.len())..]; - let written = std::cmp::min(data.len(), value_out.len()); - value_out[..written].copy_from_slice(&data[..written]); - value.len() - })).expect("read_storage cannot be called outside of an Externalities-provided environment.") - } - - fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.child_storage(storage_key, key).map(|s| s.to_vec()) - }) - .expect("storage cannot be called outside of an Externalities-provided environment.") - } - - fn set_storage(key: &[u8], value: &[u8]) { - with_externalities(|ext| - ext.set_storage(key.to_vec(), value.to_vec()) - ); - } - - fn read_child_storage( - storage_key: &[u8], - key: &[u8], - value_out: &mut [u8], - value_offset: usize, - ) -> Option { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.child_storage(storage_key, key) - .map(|value| { - let data = &value[value_offset.min(value.len())..]; - let written = std::cmp::min(data.len(), value_out.len()); - value_out[..written].copy_from_slice(&data[..written]); - value.len() - }) - }) - .expect("read_child_storage cannot be called outside of an Externalities-provided environment.") - } - - fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.set_child_storage(storage_key, key.to_vec(), value.to_vec()) - }); - } - - fn clear_storage(key: &[u8]) { - with_externalities(|ext| - ext.clear_storage(key) - ); - } - - fn clear_child_storage(storage_key: &[u8], key: &[u8]) { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.clear_child_storage(storage_key, key) - }); - } - - fn kill_child_storage(storage_key: &[u8]) { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.kill_child_storage(storage_key) - }); - } - - fn exists_storage(key: &[u8]) -> bool { - with_externalities(|ext| - ext.exists_storage(key) - ).unwrap_or(false) - } - - fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.exists_child_storage(storage_key, key) - }).unwrap_or(false) - } - - fn clear_prefix(prefix: &[u8]) { - with_externalities(|ext| ext.clear_prefix(prefix)); - } - - fn clear_child_prefix(storage_key: &[u8], prefix: &[u8]) { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.clear_child_prefix(storage_key, prefix) - }); - } - - fn storage_root() -> [u8; 32] { - with_externalities(|ext| - ext.storage_root() - ).unwrap_or(H256::zero()).into() - } - - fn child_storage_root(storage_key: &[u8]) -> Vec { - with_externalities(|ext| { - let storage_key = child_storage_key_or_panic(storage_key); - ext.child_storage_root(storage_key) - }).expect("child_storage_root cannot be called outside of an Externalities-provided environment.") - } - - fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]> { - with_externalities(|ext| - ext.storage_changes_root(parent_hash.into()).map(|h| h.map(|h| h.into())) - ).unwrap_or(Ok(None)).expect("Invalid parent hash passed to storage_changes_root") - } - - fn blake2_256_trie_root(input: Vec<(Vec, Vec)>) -> H256 { - Layout::::trie_root(input) - } - - fn blake2_256_ordered_trie_root(input: Vec>) -> H256 { - Layout::::ordered_trie_root(input) - } -} - -impl OtherApi for () { - fn chain_id() -> u64 { - with_externalities(|ext| - ext.chain_id() - ).unwrap_or(0) - } - - fn print_num(val: u64) { - println!("{}", val); - } - - fn print_utf8(utf8: &[u8]) { - if let Ok(data) = std::str::from_utf8(utf8) { - println!("{}", data) - } - } - - fn print_hex(data: &[u8]) { - println!("{}", HexDisplay::from(&data)); - } - - fn log( - level: LogLevel, - target: &[u8], - message: &[u8], - ) { - let target = std::str::from_utf8(target).unwrap_or("invalid utf8"); - let msg = std::str::from_utf8(message).unwrap_or("invalid utf8"); - - log::log!( - target: target, - log::Level::from(level), - "{}", - msg, - ) - } -} - -impl CryptoApi for () { - fn ed25519_public_keys(id: KeyTypeId) -> Vec { - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .ed25519_public_keys(id) - }).expect("`ed25519_public_keys` cannot be called outside of an Externalities-provided environment.") - } - - fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public { - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .write() - .ed25519_generate_new(id, seed) - .expect("`ed25519_generate` failed") - }).expect("`ed25519_generate` cannot be called outside of an Externalities-provided environment.") - } - - fn ed25519_sign( - id: KeyTypeId, - pubkey: &ed25519::Public, - msg: &[u8], - ) -> Option { - let pub_key = ed25519::Public::try_from(pubkey.as_ref()).ok()?; - - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .ed25519_key_pair(id, &pub_key) - .map(|k| k.sign(msg)) - }).expect("`ed25519_sign` cannot be called outside of an Externalities-provided environment.") - } - - fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool { - ed25519::Pair::verify(sig, msg, pubkey) - } - - fn sr25519_public_keys(id: KeyTypeId) -> Vec { - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .sr25519_public_keys(id) - }).expect("`sr25519_public_keys` cannot be called outside of an Externalities-provided environment.") - } - - fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public { - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .write() - .sr25519_generate_new(id, seed) - .expect("`sr25519_generate` failed") - }).expect("`sr25519_generate` cannot be called outside of an Externalities-provided environment.") - } - - fn sr25519_sign( - id: KeyTypeId, - pubkey: &sr25519::Public, - msg: &[u8], - ) -> Option { - let pub_key = sr25519::Public::try_from(pubkey.as_ref()).ok()?; - - with_externalities(|ext| { - ext.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .sr25519_key_pair(id, &pub_key) - .map(|k| k.sign(msg)) - }).expect("`sr25519_sign` cannot be called outside of an Externalities-provided environment.") - } - - fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool { - sr25519::Pair::verify(sig, msg, pubkey) - } - - 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) - } - - fn secp256k1_ecdsa_recover_compressed(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 33], EcdsaVerifyError> { - let rs = secp256k1::Signature::parse_slice(&sig[0..64]) - .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) - .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) - .map_err(|_| EcdsaVerifyError::BadSignature)?; - Ok(pubkey.serialize_compressed()) - } -} - -impl HashingApi for () { - fn keccak_256(data: &[u8]) -> [u8; 32] { - tiny_keccak::keccak256(data) - } - - fn blake2_128(data: &[u8]) -> [u8; 16] { - blake2_128(data) - } - - fn blake2_256(data: &[u8]) -> [u8; 32] { - blake2_256(data) - } - - fn twox_256(data: &[u8]) -> [u8; 32] { - twox_256(data) - } - - fn twox_128(data: &[u8]) -> [u8; 16] { - twox_128(data) - } - - fn twox_64(data: &[u8]) -> [u8; 8] { - twox_64(data) - } -} - -fn with_offchain(f: impl FnOnce(&mut dyn offchain::Externalities) -> R, msg: &'static str) -> R { - with_externalities(|ext| ext - .extension::() - .map(|ext| f(&mut **ext)) - .expect(msg) - ).expect("offchain-worker functions cannot be called outside of an Externalities-provided environment.") -} - -impl OffchainApi for () { - fn is_validator() -> bool { - with_offchain(|ext| { - ext.is_validator() - }, "is_validator can be called only in the offchain worker context") - } - - fn submit_transaction(data: Vec) -> Result<(), ()> { - with_offchain(|ext| { - ext.submit_transaction(data) - }, "submit_transaction can be called only in the offchain worker context") - } - - fn network_state() -> Result { - with_offchain(|ext| { - ext.network_state() - }, "network_state can be called only in the offchain worker context") - } - - fn timestamp() -> offchain::Timestamp { - with_offchain(|ext| { - ext.timestamp() - }, "timestamp can be called only in the offchain worker context") - } - - fn sleep_until(deadline: offchain::Timestamp) { - with_offchain(|ext| { - ext.sleep_until(deadline) - }, "sleep_until can be called only in the offchain worker context") - } - - fn random_seed() -> [u8; 32] { - with_offchain(|ext| { - ext.random_seed() - }, "random_seed can be called only in the offchain worker context") - } - - fn local_storage_set(kind: offchain::StorageKind, key: &[u8], value: &[u8]) { - with_offchain(|ext| { - ext.local_storage_set(kind, key, value) - }, "local_storage_set can be called only in the offchain worker context") - } - - fn local_storage_compare_and_set( - kind: offchain::StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - with_offchain(|ext| { - ext.local_storage_compare_and_set(kind, key, old_value, new_value) - }, "local_storage_compare_and_set can be called only in the offchain worker context") - } - - fn local_storage_get(kind: offchain::StorageKind, key: &[u8]) -> Option> { - with_offchain(|ext| { - ext.local_storage_get(kind, key) - }, "local_storage_get can be called only in the offchain worker context") - } - - fn http_request_start( - method: &str, - uri: &str, - meta: &[u8], - ) -> Result { - with_offchain(|ext| { - ext.http_request_start(method, uri, meta) - }, "http_request_start can be called only in the offchain worker context") - } - - fn http_request_add_header( - request_id: offchain::HttpRequestId, - name: &str, - value: &str, - ) -> Result<(), ()> { - with_offchain(|ext| { - ext.http_request_add_header(request_id, name, value) - }, "http_request_add_header can be called only in the offchain worker context") - } - - fn http_request_write_body( - request_id: offchain::HttpRequestId, - chunk: &[u8], - deadline: Option, - ) -> Result<(), offchain::HttpError> { - with_offchain(|ext| { - ext.http_request_write_body(request_id, chunk, deadline) - }, "http_request_write_body can be called only in the offchain worker context") - } - - fn http_response_wait( - ids: &[offchain::HttpRequestId], - deadline: Option, - ) -> Vec { - with_offchain(|ext| { - ext.http_response_wait(ids, deadline) - }, "http_response_wait can be called only in the offchain worker context") - } - - fn http_response_headers( - request_id: offchain::HttpRequestId, - ) -> Vec<(Vec, Vec)> { - with_offchain(|ext| { - ext.http_response_headers(request_id) - }, "http_response_headers can be called only in the offchain worker context") - } - - fn http_response_read_body( - request_id: offchain::HttpRequestId, - buffer: &mut [u8], - deadline: Option, - ) -> Result { - with_offchain(|ext| { - ext.http_response_read_body(request_id, buffer, deadline) - }, "http_response_read_body can be called only in the offchain worker context") - } -} - -impl Api for () {} - -/// 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>; - -/// Execute the given closure with global functions available whose functionality routes into -/// externalities that draw from and populate `storage` and `children_storage`. -/// Forwards the value that the closure returns. -pub fn with_storage R>( - storage: &mut (StorageOverlay, ChildrenStorageOverlay), - f: F -) -> R { - let mut alt_storage = Default::default(); - rstd::mem::swap(&mut alt_storage, storage); - - let mut ext = BasicExternalities::new(alt_storage.0, alt_storage.1); - let r = set_and_run_with_externalities(&mut ext, f); - - *storage = ext.into_storages(); - - r -} - -#[cfg(test)] -mod std_tests { - use super::*; - use primitives::map; - - #[test] - fn storage_works() { - let mut t = BasicExternalities::default(); - assert!(set_and_run_with_externalities(&mut t, || { - assert_eq!(storage(b"hello"), None); - set_storage(b"hello", b"world"); - assert_eq!(storage(b"hello"), Some(b"world".to_vec())); - assert_eq!(storage(b"foo"), None); - set_storage(b"foo", &[1, 2, 3][..]); - true - })); - - t = BasicExternalities::new(map![b"foo".to_vec() => b"bar".to_vec()], map![]); - - assert!(!set_and_run_with_externalities(&mut t, || { - assert_eq!(storage(b"hello"), None); - assert_eq!(storage(b"foo"), Some(b"bar".to_vec())); - false - })); - } - - #[test] - fn read_storage_works() { - let mut t = BasicExternalities::new(map![ - b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec() - ], map![]); - - set_and_run_with_externalities(&mut t, || { - let mut v = [0u8; 4]; - assert!(read_storage(b":test", &mut v[..], 0).unwrap() >= 4); - assert_eq!(v, [11u8, 0, 0, 0]); - let mut w = [0u8; 11]; - assert!(read_storage(b":test", &mut w[..], 4).unwrap() >= 11); - assert_eq!(&w, b"Hello world"); - }); - } - - #[test] - fn clear_prefix_works() { - 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(), - b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec() - ], map![]); - - set_and_run_with_externalities(&mut t, || { - clear_prefix(b":abc"); - - assert!(storage(b":a").is_some()); - assert!(storage(b":abdd").is_some()); - assert!(storage(b":abcd").is_none()); - assert!(storage(b":abc").is_none()); - }); - } -} diff --git a/core/sr-io/without_std.rs b/core/sr-io/without_std.rs deleted file mode 100644 index c3f7d62031b93..0000000000000 --- a/core/sr-io/without_std.rs +++ /dev/null @@ -1,1241 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#[doc(hidden)] -pub use rstd; -pub use rstd::{mem, slice}; - -use core::{intrinsics, panic::PanicInfo}; -use rstd::{vec::Vec, cell::Cell, convert::TryInto}; -use primitives::offchain; -use codec::Decode; - -#[cfg(not(feature = "no_panic_handler"))] -#[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { - unsafe { - let message = rstd::alloc::format!("{}", info); - extern_functions_host_impl::ext_print_utf8(message.as_ptr() as *const u8, message.len() as u32); - intrinsics::abort() - } -} - -#[cfg(not(feature = "no_oom"))] -#[alloc_error_handler] -pub extern fn oom(_: core::alloc::Layout) -> ! { - static OOM_MSG: &str = "Runtime memory exhausted. Aborting"; - - unsafe { - extern_functions_host_impl::ext_print_utf8(OOM_MSG.as_ptr(), OOM_MSG.len() as u32); - intrinsics::abort(); - } -} - -/// External (Host) APIs -pub mod ext { - use super::*; - - /// The state of an exchangeable function. - #[derive(Clone, Copy)] - enum ExchangeableFunctionState { - /// Original function is present - Original, - /// The function has been replaced. - 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. - pub(crate) 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); - /// Print data as hex. - fn ext_print_hex(data: *const u8, len: u32); - /// Print a number - fn ext_print_num(value: u64); - /// Print a log line if logging for given level and target is enabled. - fn ext_log( - level: u32, - target_data: *const u8, - target_len: u32, - message_data: *const u8, - message_len: u32, - ); - - /// Set value for key in storage. - fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); - /// Remove key and value from storage. - fn ext_clear_storage(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; - /// Remove storage entries which key starts with given prefix. - fn ext_clear_prefix(prefix_data: *const u8, prefix_len: u32); - /// Remove child storage entries which key starts with given prefix. - fn ext_clear_child_prefix( - storage_key_data: *const u8, - storage_key_len: u32, - prefix_data: *const u8, - prefix_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; - /// 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; - /// Gets the trie root of the storage. - fn ext_storage_root(result: *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, - result: *mut u8, - ) -> u32; - - /// 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; - - /// Calculate a blake2_256 merkle trie root. - fn ext_blake2_256_enumerated_trie_root( - values_data: *const u8, - lens_data: *const u32, - lens_len: u32, - result: *mut u8 - ); - /// BLAKE2_128 hash - fn ext_blake2_128(data: *const u8, len: u32, out: *mut u8); - /// BLAKE2_256 hash - fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8); - /// XX64 hash - fn ext_twox_64(data: *const u8, len: u32, out: *mut u8); - /// XX128 hash - fn ext_twox_128(data: *const u8, len: u32, out: *mut u8); - /// XX256 hash - fn ext_twox_256(data: *const u8, len: u32, out: *mut u8); - /// Keccak256 hash - fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8); - - /// Returns all `ed25519` public keys for the given key type from the keystore. - fn ext_ed25519_public_keys(id: *const u8, result_len: *mut u32) -> *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; - - /// Generate an `ed25519` key pair for the given key type id and store the public key - /// in `out`. - fn ext_ed25519_generate(id: *const u8, seed: *const u8, seed_len: u32, out: *mut u8); - - /// Sign the given `msg` with the `ed25519` key pair that corresponds to then given key - /// type id and public key. The raw signature is stored in `out`. - /// - /// # Returns - /// - /// - `0` on success - /// - nonezero if something failed, e.g. retrieving of the key. - fn ext_ed25519_sign( - id: *const u8, - pubkey: *const u8, - msg: *const u8, - msg_len: u32, - out: *mut u8, - ) -> u32; - - /// Returns all `sr25519` public keys for the given key type from the keystore. - fn ext_sr25519_public_keys(id: *const u8, result_len: *mut u32) -> *mut u8; - - /// 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; - - /// Generate an `sr25519` key pair for the given key type id and store the public - /// key in `out`. - fn ext_sr25519_generate(id: *const u8, seed: *const u8, seed_len: u32, out: *mut u8); - - /// Sign the given `msg` with the `sr25519` key pair that corresponds to then given key - /// type id and public key. The raw signature is stored in `out`. - /// - /// # Returns - /// - /// - `0` on success - /// - nonezero if something failed, e.g. retrieving of the key. - fn ext_sr25519_sign( - id: *const u8, - pubkey: *const u8, - msg: *const u8, - msg_len: u32, - out: *mut u8, - ) -> u32; - - /// Note: ext_secp256k1_ecdsa_recover returns 0 if the signature is correct, nonzero otherwise. - /// - /// pubkey_data must point to 64 bytes. - fn ext_secp256k1_ecdsa_recover( - msg_data: *const u8, - sig_data: *const u8, - pubkey_data: *mut u8, - ) -> u32; - - /// Note: ext_secp256k1_ecdsa_recover_compressed returns 0 if the signature is correct, nonzero otherwise. - /// - /// pubkey_data must point to 33 bytes. - fn ext_secp256k1_ecdsa_recover_compressed( - msg_data: *const u8, - sig_data: *const u8, - pubkey_data: *mut u8, - ) -> u32; - - //================================ - // Offchain-worker Context - //================================ - - /// Returns if the local node is a potential validator. - /// - /// - `1` == `true` - /// - `0` == `false` - fn ext_is_validator() -> u32; - - /// Submit transaction. - /// - /// # Returns - /// - /// - 0 if it was successfuly added to the pool - /// - nonzero otherwise. - fn ext_submit_transaction(data: *const u8, len: u32) -> u32; - - /// Returns information about the local node's network state. - /// - /// # Returns - /// - /// The encoded `Result`. - /// `written_out` contains the length of the message. - /// - /// The ownership of the returned buffer is transferred to the runtime - /// code and the runtime is responsible for freeing it. This is always - /// a properly allocated pointer (which cannot be NULL), hence the - /// runtime code can always rely on it. - fn ext_network_state(written_out: *mut u32) -> *mut u8; - - /// Returns current UNIX timestamp (milliseconds) - fn ext_timestamp() -> u64; - - /// Pause execution until given timestamp (milliseconds; `deadline`) is reached. - /// - /// The deadline is obtained by querying the current timestamp via `ext_timestamp` - /// and then adding some time to it. - fn ext_sleep_until(deadline: u64); - - /// Generate a random seed - /// - /// `data` has to be a pointer to a slice of 32 bytes. - fn ext_random_seed(data: *mut u8); - - /// Write a value to local storage. - fn ext_local_storage_set(kind: u32, key: *const u8, key_len: u32, value: *const u8, value_len: u32); - - /// Write a value to local storage in atomic fashion. - /// - /// # Returns - /// - `0` in case the value has been set - /// - `1` if the `old_value` didn't match - fn ext_local_storage_compare_and_set( - kind: u32, - key: *const u8, - key_len: u32, - old_value: *const u8, - old_value_len: u32, - new_value: *const u8, - new_value_len: u32, - ) -> u32; - - /// Read a value from local storage. - /// - /// - /// # Returns - /// - /// - 0 if the value has not been found, the `value_len` is set to `u32::max_value`. - /// - Otherwise, pointer to the value in memory. `value_len` contains the length of the value. - fn ext_local_storage_get(kind: u32, key: *const u8, key_len: u32, value_len: *mut u32) -> *mut u8; - - /// Initiates a http request. - /// - /// `meta` is parity-scale-codec encoded additional parameters to the request (like redirection policy, - /// timeouts, certificates policy, etc). The format is not yet specified and the field is currently - /// only reserved for future use. - /// - /// # Returns - /// - /// `RequestId(u16)` of initiated request, any value beyond `u16::max_value` - /// signifies an error. - fn ext_http_request_start( - method: *const u8, - method_len: u32, - url: *const u8, - url_len: u32, - meta: *const u8, - meta_len: u32, - ) -> u32; - - /// Add a header to the request. - /// - /// # Returns - /// - /// - `0` if successful (and the request id exists) - /// - nonzero otherwise - fn ext_http_request_add_header( - request_id: u32, - name: *const u8, - name_len: u32, - value: *const u8, - value_len: u32, - ) -> u32; - - /// Write a chunk of request body. - /// - /// Writing an empty chunks finalises the request. - /// Passing `0` as deadline blocks forever. - /// - /// # Returns - /// - /// - `0` if successful, - /// - nonzero otherwise (see HttpError for the codes) - fn ext_http_request_write_body( - request_id: u32, - chunk: *const u8, - chunk_len: u32, - deadline: u64, - ) -> u32; - - /// Block and wait for the responses for given requests. - /// - /// Note that if deadline is 0 the method will block indefinitely, - /// otherwise unready responses will produce `DeadlineReached` status. - /// (see #primitives::offchain::HttpRequestStatus) - /// - /// Make sure that `statuses` have the same length as ids. - fn ext_http_response_wait( - ids: *const u32, - ids_len: u32, - statuses: *mut u32, - deadline: u64, - ); - - /// Read all response headers. - /// - /// Note the headers are only available before response body is fully consumed. - /// - /// # Returns - /// - /// - A pointer to parity-scale-codec encoded vector of pairs `(HeaderKey, HeaderValue)`. - /// - In case invalid `id` is passed it returns a pointer to parity-encoded empty vector. - fn ext_http_response_headers( - id: u32, - written_out: *mut u32, - ) -> *mut u8; - - /// Read a chunk of body response to given buffer. - /// - /// Passing `0` as deadline blocks forever. - /// - /// # Returns - /// - /// The number of bytes written if successful, - /// - if it's `0` it means response has been fully consumed, - /// - if it's greater than `u32::max_value() - 255` it means reading body failed. - /// - /// In case of failure, the error code should be mapped to `HttpError` - /// in a following manner: - /// - `u32::max_value()` HttpError code 1 (DeadlineReached) - /// - `u32::max_value() - 1` HttpError code 2 (IoError) - /// The rest is reserved for potential future errors. - fn ext_http_response_read_body( - id: u32, - buffer: *mut u8, - buffer_len: u32, - deadline: u64, - ) -> u32; - } -} - -pub use self::ext::*; - -impl StorageApi for () { - fn storage(key: &[u8]) -> Option> { - let mut length: u32 = 0; - unsafe { - let ptr = ext_get_allocated_storage.get()(key.as_ptr(), key.len() as u32, &mut length); - from_raw_parts(ptr, length) - } - } - - fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { - let mut length: u32 = 0; - unsafe { - 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 - ); - from_raw_parts(ptr, length) - } - } - - fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { - unsafe { - 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), - } - } - } - - fn read_child_storage(storage_key: &[u8], key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { - unsafe { - 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, - value_offset as u32 - ) { - none if none == u32::max_value() => None, - length => Some(length as usize), - } - } - } - - fn set_storage(key: &[u8], value: &[u8]) { - unsafe { - ext_set_storage.get()( - key.as_ptr(), key.len() as u32, - value.as_ptr(), value.len() as u32 - ); - } - } - - fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { - unsafe { - ext_set_child_storage.get()( - storage_key.as_ptr(), storage_key.len() as u32, - key.as_ptr(), key.len() as u32, - value.as_ptr(), value.len() as u32 - ); - } - } - - fn clear_storage(key: &[u8]) { - unsafe { - ext_clear_storage.get()( - key.as_ptr(), key.len() as u32 - ); - } - } - - fn clear_child_storage(storage_key: &[u8], key: &[u8]) { - unsafe { - ext_clear_child_storage.get()( - storage_key.as_ptr(), storage_key.len() as u32, - key.as_ptr(), key.len() as u32 - ); - } - } - - fn exists_storage(key: &[u8]) -> bool { - unsafe { - ext_exists_storage.get()( - key.as_ptr(), key.len() as u32 - ) != 0 - } - } - - fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { - unsafe { - ext_exists_child_storage.get()( - storage_key.as_ptr(), storage_key.len() as u32, - key.as_ptr(), key.len() as u32 - ) != 0 - } - } - - fn clear_prefix(prefix: &[u8]) { - unsafe { - ext_clear_prefix.get()( - prefix.as_ptr(), - prefix.len() as u32 - ); - } - } - - fn clear_child_prefix(storage_key: &[u8], prefix: &[u8]) { - unsafe { - ext_clear_child_prefix.get()( - storage_key.as_ptr(), storage_key.len() as u32, - prefix.as_ptr(), prefix.len() as u32 - ); - } - } - - fn kill_child_storage(storage_key: &[u8]) { - unsafe { - ext_kill_child_storage.get()( - storage_key.as_ptr(), - storage_key.len() as u32 - ); - } - } - - fn storage_root() -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_storage_root.get()(result.as_mut_ptr()); - } - result - } - - fn child_storage_root(storage_key: &[u8]) -> Vec { - let mut length: u32 = 0; - unsafe { - let ptr = ext_child_storage_root.get()( - storage_key.as_ptr(), - storage_key.len() as u32, - &mut length - ); - from_raw_parts(ptr, length).expect("ext_child_storage_root never returns u32::max_value; qed") - } - } - - fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]> { - let mut result: [u8; 32] = Default::default(); - let is_set = unsafe { - ext_storage_changes_root.get()(parent_hash.as_ptr(), parent_hash.len() as u32, result.as_mut_ptr()) - }; - - if is_set != 0 { - Some(result) - } else { - None - } - } - - - fn blake2_256_trie_root(_input: Vec<(Vec, Vec)>) -> H256 { - unimplemented!() - } - - fn blake2_256_ordered_trie_root(input: Vec>) -> H256 { - let mut values = Vec::with_capacity(input.len()); - let mut lengths = Vec::with_capacity(input.len()); - for v in input { - values.extend_from_slice(&v); - lengths.push((v.len() as u32).to_le()); - } - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_blake2_256_enumerated_trie_root.get()( - values.as_ptr(), - lengths.as_ptr(), - lengths.len() as u32, - result.as_mut_ptr(), - ); - } - result.into() - } -} - -impl OtherApi for () { - fn chain_id() -> u64 { - unsafe { - ext_chain_id.get()() - } - } - - fn print_num(val: u64) { - unsafe { - ext_print_num.get()(val); - } - } - - fn print_utf8(utf8: &[u8]) { - unsafe { - ext_print_utf8.get()(utf8.as_ptr(), utf8.len() as u32); - } - } - - fn print_hex(data: &[u8]) { - unsafe { - ext_print_hex.get()(data.as_ptr(), data.len() as u32); - } - } - - fn log( - level: LogLevel, - target: &[u8], - message: &[u8] - ) { - unsafe { - ext_log.get()( - level as u32, - target.as_ptr(), - target.len() as u32, - message.as_ptr(), - message.len() as u32, - ) - } - } -} - -impl HashingApi for () { - 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 - } - - fn blake2_128(data: &[u8]) -> [u8; 16] { - let mut result: [u8; 16] = Default::default(); - unsafe { - ext_blake2_128.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn blake2_256(data: &[u8]) -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_blake2_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn twox_256(data: &[u8]) -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_twox_256.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn twox_128(data: &[u8]) -> [u8; 16] { - let mut result: [u8; 16] = Default::default(); - unsafe { - ext_twox_128.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - fn twox_64(data: &[u8]) -> [u8; 8] { - let mut result: [u8; 8] = Default::default(); - unsafe { - ext_twox_64.get()(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } -} - -impl CryptoApi for () { - fn ed25519_public_keys(id: KeyTypeId) -> Vec { - let mut res_len = 0u32; - unsafe { - let res_ptr = ext_ed25519_public_keys.get()(id.0.as_ptr(), &mut res_len); - Vec::decode(&mut rstd::slice::from_raw_parts(res_ptr, res_len as usize)).unwrap_or_default() - } - } - - fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public { - let mut res = [0u8; 32]; - let seed = seed.as_ref().map(|s| s.as_bytes()).unwrap_or(&[]); - unsafe { - ext_ed25519_generate.get()(id.0.as_ptr(), seed.as_ptr(), seed.len() as u32, res.as_mut_ptr()) - }; - ed25519::Public(res) - } - - fn ed25519_sign( - id: KeyTypeId, - pubkey: &ed25519::Public, - msg: &[u8], - ) -> Option { - let mut res = [0u8; 64]; - let success = unsafe { - ext_ed25519_sign.get()( - id.0.as_ptr(), - pubkey.0.as_ptr(), - msg.as_ptr(), - msg.len() as u32, - res.as_mut_ptr(), - ) == 0 - }; - - if success { - Some(ed25519::Signature(res)) - } else { - None - } - } - - fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool { - unsafe { - ext_ed25519_verify.get()( - msg.as_ptr(), - msg.len() as u32, - sig.0.as_ptr(), - pubkey.0.as_ptr(), - ) == 0 - } - } - - fn sr25519_public_keys(id: KeyTypeId) -> Vec { - let mut res_len = 0u32; - unsafe { - let res_ptr = ext_sr25519_public_keys.get()(id.0.as_ptr(), &mut res_len); - Vec::decode(&mut rstd::slice::from_raw_parts(res_ptr, res_len as usize)).unwrap_or_default() - } - } - - fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public { - let mut res = [0u8;32]; - let seed = seed.as_ref().map(|s| s.as_bytes()).unwrap_or(&[]); - unsafe { - ext_sr25519_generate.get()(id.0.as_ptr(), seed.as_ptr(), seed.len() as u32, res.as_mut_ptr()) - }; - sr25519::Public(res) - } - - fn sr25519_sign( - id: KeyTypeId, - pubkey: &sr25519::Public, - msg: &[u8], - ) -> Option { - let mut res = [0u8; 64]; - let success = unsafe { - ext_sr25519_sign.get()( - id.0.as_ptr(), - pubkey.0.as_ptr(), - msg.as_ptr(), - msg.len() as u32, - res.as_mut_ptr(), - ) == 0 - }; - - if success { - Some(sr25519::Signature(res)) - } else { - None - } - } - - fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool { - unsafe { - ext_sr25519_verify.get()( - msg.as_ptr(), - msg.len() as u32, - sig.0.as_ptr(), - pubkey.0.as_ptr(), - ) == 0 - } - } - - 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"), - } - } - - fn secp256k1_ecdsa_recover_compressed(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 33], EcdsaVerifyError> { - let mut pubkey = [0u8; 33]; - match unsafe { - ext_secp256k1_ecdsa_recover_compressed.get()(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr()) - } { - 0 => Ok(pubkey), - 1 => Err(EcdsaVerifyError::BadRS), - 2 => Err(EcdsaVerifyError::BadV), - 3 => Err(EcdsaVerifyError::BadSignature), - _ => unreachable!("`ext_secp256k1_ecdsa_recover_compressed` only returns 0, 1, 2 or 3; qed"), - } - } -} - -impl OffchainApi for () { - fn is_validator() -> bool { - unsafe { ext_is_validator.get()() == 1 } - } - - fn submit_transaction(data: Vec) -> Result<(), ()> { - let ret = unsafe { - ext_submit_transaction.get()(data.as_ptr(), data.len() as u32) - }; - - if ret == 0 { - Ok(()) - } else { - Err(()) - } - } - - fn network_state() -> Result { - let mut len = 0_u32; - let raw_result = unsafe { - let ptr = ext_network_state.get()(&mut len); - - from_raw_parts(ptr, len) - }; - - match raw_result { - Some(raw_result) => codec::Decode::decode(&mut &*raw_result).unwrap_or(Err(())), - None => Err(()) - } - } - - fn timestamp() -> offchain::Timestamp { - offchain::Timestamp::from_unix_millis(unsafe { - ext_timestamp.get()() - }) - } - - fn sleep_until(deadline: offchain::Timestamp) { - unsafe { - ext_sleep_until.get()(deadline.unix_millis()) - } - } - - fn random_seed() -> [u8; 32] { - let mut result = [0_u8; 32]; - unsafe { - ext_random_seed.get()(result.as_mut_ptr()) - } - result - } - - fn local_storage_set(kind: offchain::StorageKind, key: &[u8], value: &[u8]) { - unsafe { - ext_local_storage_set.get()( - kind.into(), - key.as_ptr(), - key.len() as u32, - value.as_ptr(), - value.len() as u32, - ) - } - } - - fn local_storage_compare_and_set( - kind: offchain::StorageKind, - key: &[u8], - old_value: Option<&[u8]>, - new_value: &[u8], - ) -> bool { - let (ptr, len) = match old_value { - Some(old_value) => ( - old_value.as_ptr(), - old_value.len() as u32, - ), - None => (0 as *const u8, u32::max_value()), - }; - - unsafe { - ext_local_storage_compare_and_set.get()( - kind.into(), - key.as_ptr(), - key.len() as u32, - ptr, - len, - new_value.as_ptr(), - new_value.len() as u32, - ) == 0 - } - } - - fn local_storage_get(kind: offchain::StorageKind, key: &[u8]) -> Option> { - let mut len = 0u32; - unsafe { - let ptr = ext_local_storage_get.get()( - kind.into(), - key.as_ptr(), - key.len() as u32, - &mut len, - ); - - from_raw_parts(ptr, len) - } - } - - fn http_request_start(method: &str, url: &str, meta: &[u8]) -> Result { - let method = method.as_bytes(); - let url = url.as_bytes(); - - let result = unsafe { - ext_http_request_start.get()( - method.as_ptr(), - method.len() as u32, - url.as_ptr(), - url.len() as u32, - meta.as_ptr(), - meta.len() as u32, - ) - }; - - if result > u16::max_value() as u32 { - Err(()) - } else { - Ok(offchain::HttpRequestId(result as u16)) - } - } - - fn http_request_add_header(request_id: offchain::HttpRequestId, name: &str, value: &str) -> Result<(), ()> { - let name = name.as_bytes(); - let value = value.as_bytes(); - - let result = unsafe { - ext_http_request_add_header.get()( - request_id.into(), - name.as_ptr(), - name.len() as u32, - value.as_ptr(), - value.len() as u32, - ) - }; - - if result == 0 { - Ok(()) - } else { - Err(()) - } - } - - fn http_request_write_body( - request_id: offchain::HttpRequestId, - chunk: &[u8], - deadline: Option - ) -> Result<(), offchain::HttpError> { - let res = unsafe { - ext_http_request_write_body.get()( - request_id.into(), - chunk.as_ptr(), - chunk.len() as u32, - deadline.map_or(0, |x| x.unix_millis()), - ) - }; - - if res == 0 { - Ok(()) - } else { - Err(res.try_into().unwrap_or(offchain::HttpError::IoError)) - } - } - - fn http_response_wait( - ids: &[offchain::HttpRequestId], - deadline: Option - ) -> Vec { - let ids = ids.iter().map(|x| x.0 as u32).collect::>(); - let mut statuses = Vec::new(); - statuses.resize(ids.len(), 0u32); - - unsafe { - ext_http_response_wait.get()( - ids.as_ptr(), - ids.len() as u32, - statuses.as_mut_ptr(), - deadline.map_or(0, |x| x.unix_millis()), - ) - } - - statuses - .into_iter() - .map(|status| status.try_into().unwrap_or(offchain::HttpRequestStatus::Invalid)) - .collect() - } - - fn http_response_headers( - request_id: offchain::HttpRequestId, - ) -> Vec<(Vec, Vec)> { - let mut len = 0u32; - let raw_result = unsafe { - let ptr = ext_http_response_headers.get()( - request_id.into(), - &mut len, - ); - - from_raw_parts(ptr, len).expect("ext_http_response_headers never return u32::max_value; qed") - }; - - codec::Decode::decode(&mut &*raw_result).unwrap_or_default() - } - - fn http_response_read_body( - request_id: offchain::HttpRequestId, - buffer: &mut [u8], - deadline: Option, - ) -> Result { - let res = unsafe { - ext_http_response_read_body.get()( - request_id.into(), - buffer.as_mut_ptr(), - buffer.len() as u32, - deadline.map_or(0, |x| x.unix_millis()), - ) - }; - - if res >= u32::max_value() - 255 { - let code = (u32::max_value() - res) + 1; - code.try_into().map_err(|_| offchain::HttpError::IoError) - } else { - Ok(res as usize) - } - } -} - -unsafe fn from_raw_parts(ptr: *mut u8, len: u32) -> Option> { - if len == u32::max_value() { - None - } else { - // 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, len as usize, len as usize)) - } -} - -impl Api for () {} diff --git a/core/sr-primitives/Cargo.toml b/core/sr-primitives/Cargo.toml deleted file mode 100644 index d3303014260f4..0000000000000 --- a/core/sr-primitives/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "sr-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } -app-crypto = { package = "substrate-application-crypto", path = "../application-crypto", default-features = false } -arithmetic = { package = "sr-arithmetic", path = "../sr-arithmetic", default-features = false } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../sr-io", default-features = false } -log = { version = "0.4.8", optional = true } -paste = "0.1.6" -rand = { version = "0.7.2", optional = true } -impl-trait-for-tuples = "0.1.2" - -[dev-dependencies] -serde_json = "1.0.41" -rand = "0.7.2" -substrate-offchain = { path = "../offchain" } - -[features] -bench = [] -default = ["std"] -std = [ - "app-crypto/std", - "arithmetic/std", - "codec/std", - "log", - "primitives/std", - "rand", - "rstd/std", - "runtime_io/std", - "serde", -] diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs deleted file mode 100644 index 1e030ea1d8769..0000000000000 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Generic implementation of an extrinsic that has passed the verification -//! stage. - -use crate::traits::{ - self, Member, MaybeDisplay, SignedExtension, Dispatchable, ValidateUnsigned, -}; -use crate::weights::{GetDispatchInfo, DispatchInfo}; -use crate::transaction_validity::TransactionValidity; - -/// Definition of something that the external world might want to say; its -/// existence implies that it has been checked and is good, particularly with -/// regards to the signature. -#[derive(PartialEq, Eq, Clone, primitives::RuntimeDebug)] -pub struct CheckedExtrinsic { - /// Who this purports to be from and the number of extrinsics have come before - /// from the same signer, if anyone (note this is not a signature). - pub signed: Option<(AccountId, Extra)>, - - /// The function that should be called. - pub function: Call, -} - -impl traits::Applyable -for - CheckedExtrinsic -where - AccountId: Member + MaybeDisplay, - Call: Member + Dispatchable, - Extra: SignedExtension, - Origin: From>, -{ - type AccountId = AccountId; - type Call = Call; - - fn sender(&self) -> Option<&Self::AccountId> { - self.signed.as_ref().map(|x| &x.0) - } - - fn validate>( - &self, - info: DispatchInfo, - len: usize, - ) -> TransactionValidity { - if let Some((ref id, ref extra)) = self.signed { - Extra::validate(extra, id, &self.function, info, len) - } else { - let valid = Extra::validate_unsigned(&self.function, info, len)?; - Ok(valid.combine_with(U::validate_unsigned(&self.function)?)) - } - } - - fn apply( - self, - info: DispatchInfo, - len: usize, - ) -> crate::ApplyResult { - let (maybe_who, pre) = if let Some((id, extra)) = self.signed { - let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?; - (Some(id), pre) - } else { - let pre = Extra::pre_dispatch_unsigned(&self.function, info, len)?; - (None, pre) - }; - let res = self.function.dispatch(Origin::from(maybe_who)); - Extra::post_dispatch(pre, info, len); - Ok(res.map_err(Into::into)) - } -} - -impl GetDispatchInfo for CheckedExtrinsic -where - Call: GetDispatchInfo, -{ - fn get_dispatch_info(&self) -> DispatchInfo { - self.function.get_dispatch_info() - } -} diff --git a/core/sr-primitives/src/generic/digest.rs b/core/sr-primitives/src/generic/digest.rs deleted file mode 100644 index 83f2c6f1745de..0000000000000 --- a/core/sr-primitives/src/generic/digest.rs +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Generic implementation of a digest. - -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; - -use rstd::prelude::*; - -use crate::ConsensusEngineId; -use crate::codec::{Decode, Encode, Input, Error}; -use primitives::RuntimeDebug; - -/// Generic header digest. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Digest { - /// A list of logs in the digest. - pub logs: Vec>, -} - -impl Default for Digest { - fn default() -> Self { - Digest { logs: Vec::new(), } - } -} - -impl Digest { - /// Get reference to all digest items. - pub fn logs(&self) -> &[DigestItem] { - &self.logs - } - - /// Push new digest item. - pub fn push(&mut self, item: DigestItem) { - self.logs.push(item); - } - - /// Pop a digest item. - pub fn pop(&mut self) -> Option> { - self.logs.pop() - } - - /// Get reference to the first digest item that matches the passed predicate. - pub fn log) -> Option<&T>>(&self, predicate: F) -> Option<&T> { - self.logs().iter() - .filter_map(predicate) - .next() - } - - /// Get a conversion of the first digest item that successfully converts using the function. - pub fn convert_first) -> Option>(&self, predicate: F) -> Option { - self.logs().iter() - .filter_map(predicate) - .next() - } -} - - -/// Digest item that is able to encode/decode 'system' digest items and -/// provide opaque access to other items. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] -pub enum DigestItem { - /// System digest item that contains the root of changes trie at given - /// block. It is created for every block iff runtime supports changes - /// trie creation. - ChangesTrieRoot(Hash), - - /// A pre-runtime digest. - /// - /// These are messages from the consensus engine to the runtime, although - /// the consensus engine can (and should) read them itself to avoid - /// code and state duplication. It is erroneous for a runtime to produce - /// these, but this is not (yet) checked. - PreRuntime(ConsensusEngineId, Vec), - - /// A message from the runtime to the consensus engine. This should *never* - /// be generated by the native code of any consensus engine, but this is not - /// checked (yet). - Consensus(ConsensusEngineId, Vec), - - /// Put a Seal on it. This is only used by native code, and is never seen - /// by runtimes. - Seal(ConsensusEngineId, Vec), - - /// Some other thing. Unsupported and experimental. - Other(Vec), -} - -#[cfg(feature = "std")] -impl serde::Serialize for DigestItem { - fn serialize(&self, seq: S) -> Result where S: serde::Serializer { - self.using_encoded(|bytes| { - primitives::bytes::serialize(bytes, seq) - }) - } -} - -#[cfg(feature = "std")] -impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem { - fn deserialize(de: D) -> Result where - D: serde::Deserializer<'a>, - { - let r = primitives::bytes::deserialize(de)?; - Decode::decode(&mut &r[..]) - .map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e))) - } -} - -/// 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, RuntimeDebug)] -pub enum DigestItemRef<'a, Hash: 'a> { - /// Reference to `DigestItem::ChangesTrieRoot`. - ChangesTrieRoot(&'a Hash), - /// A pre-runtime digest. - /// - /// These are messages from the consensus engine to the runtime, although - /// the consensus engine can (and should) read them itself to avoid - /// code and state duplication. It is erroneous for a runtime to produce - /// these, but this is not (yet) checked. - PreRuntime(&'a ConsensusEngineId, &'a Vec), - /// A message from the runtime to the consensus engine. This should *never* - /// be generated by the native code of any consensus engine, but this is not - /// checked (yet). - Consensus(&'a ConsensusEngineId, &'a Vec), - /// Put a Seal on it. This is only used by native code, and is never seen - /// by runtimes. - Seal(&'a ConsensusEngineId, &'a Vec), - /// Any 'non-system' digest item, opaque to the native code. - Other(&'a Vec), -} - -/// Type of the digest item. Used to gain explicit control over `DigestItem` encoding -/// process. We need an explicit control, because final runtimes are encoding their own -/// digest items using `DigestItemRef` type and we can't auto-derive `Decode` -/// trait for `DigestItemRef`. -#[repr(u32)] -#[derive(Encode, Decode)] -pub enum DigestItemType { - ChangesTrieRoot = 2, - PreRuntime = 6, - Consensus = 4, - Seal = 5, - Other = 0, -} - -/// Type of a digest item that contains raw data; this also names the consensus engine ID where -/// applicable. Used to identify one or more digest items of interest. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub enum OpaqueDigestItemId<'a> { - /// Type corresponding to DigestItem::PreRuntime. - PreRuntime(&'a ConsensusEngineId), - /// Type corresponding to DigestItem::Consensus. - Consensus(&'a ConsensusEngineId), - /// Type corresponding to DigestItem::Seal. - Seal(&'a ConsensusEngineId), - /// Some other (non-prescribed) type. - Other, -} - -impl DigestItem { - /// Returns a 'referencing view' for this digest item. - pub fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash> { - match *self { - DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), - DigestItem::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s), - DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s), - DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s), - DigestItem::Other(ref v) => DigestItemRef::Other(v), - } - } - - /// Returns `Some` if the entry is the `ChangesTrieRoot` entry. - pub fn as_changes_trie_root(&self) -> Option<&Hash> { - self.dref().as_changes_trie_root() - } - - /// Returns `Some` if this entry is the `PreRuntime` entry. - pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> { - self.dref().as_pre_runtime() - } - - /// Returns `Some` if this entry is the `Consensus` entry. - pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &[u8])> { - self.dref().as_consensus() - } - - /// Returns `Some` if this entry is the `Seal` entry. - pub fn as_seal(&self) -> Option<(ConsensusEngineId, &[u8])> { - self.dref().as_seal() - } - - /// Returns Some if `self` is a `DigestItem::Other`. - pub fn as_other(&self) -> Option<&[u8]> { - match *self { - DigestItem::Other(ref v) => Some(&v[..]), - _ => None, - } - } - - /// Returns the opaque data contained in the item if `Some` if this entry has the id given. - pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&[u8]> { - self.dref().try_as_raw(id) - } - - /// Returns the data contained in the item if `Some` if this entry has the id given, decoded - /// to the type provided `T`. - pub fn try_to(&self, id: OpaqueDigestItemId) -> Option { - self.dref().try_to::(id) - } -} - -impl Encode for DigestItem { - fn encode(&self) -> Vec { - self.dref().encode() - } -} - -impl codec::EncodeLike for DigestItem {} - -impl Decode for DigestItem { - #[allow(deprecated)] - fn decode(input: &mut I) -> Result { - let item_type: DigestItemType = Decode::decode(input)?; - match item_type { - DigestItemType::ChangesTrieRoot => Ok(DigestItem::ChangesTrieRoot( - Decode::decode(input)?, - )), - DigestItemType::PreRuntime => { - let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; - Ok(DigestItem::PreRuntime(vals.0, vals.1)) - }, - DigestItemType::Consensus => { - let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; - Ok(DigestItem::Consensus(vals.0, vals.1)) - } - DigestItemType::Seal => { - let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; - Ok(DigestItem::Seal(vals.0, vals.1)) - }, - DigestItemType::Other => Ok(DigestItem::Other( - Decode::decode(input)?, - )), - } - } -} - -impl<'a, Hash> DigestItemRef<'a, Hash> { - /// 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), - _ => None, - } - } - - /// Cast this digest item into `PreRuntime` - pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &'a [u8])> { - match *self { - DigestItemRef::PreRuntime(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), - _ => None, - } - } - - /// Cast this digest item into `Consensus` - pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &'a [u8])> { - match *self { - DigestItemRef::Consensus(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), - _ => None, - } - } - - /// Cast this digest item into `Seal` - pub fn as_seal(&self) -> Option<(ConsensusEngineId, &'a [u8])> { - match *self { - DigestItemRef::Seal(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), - _ => None, - } - } - - /// Cast this digest item into `PreRuntime` - pub fn as_other(&self) -> Option<&'a [u8]> { - match *self { - DigestItemRef::Other(ref data) => Some(data), - _ => None, - } - } - - /// Try to match this digest item to the given opaque item identifier; if it matches, then - /// return the opaque data it contains. - pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&'a [u8]> { - match (id, self) { - (OpaqueDigestItemId::Consensus(w), &DigestItemRef::Consensus(v, s)) | - (OpaqueDigestItemId::Seal(w), &DigestItemRef::Seal(v, s)) | - (OpaqueDigestItemId::PreRuntime(w), &DigestItemRef::PreRuntime(v, s)) - if v == w => Some(&s[..]), - (OpaqueDigestItemId::Other, &DigestItemRef::Other(s)) => Some(&s[..]), - _ => None, - } - } - - /// Try to match this digest item to the given opaque item identifier; if it matches, then - /// try to cast to the given datatype; if that works, return it. - pub fn try_to(&self, id: OpaqueDigestItemId) -> Option { - self.try_as_raw(id).and_then(|mut x| Decode::decode(&mut x).ok()) - } -} - -impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> { - fn encode(&self) -> Vec { - let mut v = Vec::new(); - - match *self { - DigestItemRef::ChangesTrieRoot(changes_trie_root) => { - DigestItemType::ChangesTrieRoot.encode_to(&mut v); - changes_trie_root.encode_to(&mut v); - }, - DigestItemRef::Consensus(val, data) => { - DigestItemType::Consensus.encode_to(&mut v); - (val, data).encode_to(&mut v); - }, - DigestItemRef::Seal(val, sig) => { - DigestItemType::Seal.encode_to(&mut v); - (val, sig).encode_to(&mut v); - }, - DigestItemRef::PreRuntime(val, data) => { - DigestItemType::PreRuntime.encode_to(&mut v); - (val, data).encode_to(&mut v); - }, - DigestItemRef::Other(val) => { - DigestItemType::Other.encode_to(&mut v); - val.encode_to(&mut v); - }, - } - - v - } -} - -impl<'a, Hash: Encode> codec::EncodeLike for DigestItemRef<'a, Hash> {} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn should_serialize_digest() { - let digest = Digest { - logs: vec![ - DigestItem::ChangesTrieRoot(4), - DigestItem::Other(vec![1, 2, 3]), - DigestItem::Seal(*b"test", vec![1, 2, 3]) - ], - }; - - assert_eq!( - ::serde_json::to_string(&digest).unwrap(), - r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"# - ); - } -} diff --git a/core/sr-primitives/src/generic/mod.rs b/core/sr-primitives/src/generic/mod.rs deleted file mode 100644 index 0138a15aee21a..0000000000000 --- a/core/sr-primitives/src/generic/mod.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -// tag::description[] -//! Generic implementations of Extrinsic/Header/Block. -// end::description[] - -mod unchecked_extrinsic; -mod era; -mod checked_extrinsic; -mod header; -mod block; -mod digest; -#[cfg(test)] -mod tests; - -pub use self::unchecked_extrinsic::{UncheckedExtrinsic, SignedPayload}; -pub use self::era::{Era, Phase}; -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, OpaqueDigestItemId -}; - -use crate::codec::Encode; -use rstd::prelude::*; - -fn encode_with_vec_prefix)>(encoder: F) -> Vec { - let size = ::rstd::mem::size_of::(); - let reserve = match size { - 0..=0b00111111 => 1, - 0..=0b00111111_11111111 => 2, - _ => 4, - }; - let mut v = Vec::with_capacity(reserve + size); - v.resize(reserve, 0); - encoder(&mut v); - - // need to prefix with the total length to ensure it's binary compatible with - // Vec. - let mut length: Vec<()> = Vec::new(); - length.resize(v.len() - reserve, ()); - length.using_encoded(|s| { - v.splice(0..reserve, s.iter().cloned()); - }); - - v -} diff --git a/core/sr-primitives/src/generic/tests.rs b/core/sr-primitives/src/generic/tests.rs deleted file mode 100644 index 67e85da374533..0000000000000 --- a/core/sr-primitives/src/generic/tests.rs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the generic implementations of Extrinsic/Header/Block. - -use crate::codec::{Decode, Encode}; -use primitives::H256; -use super::DigestItem; - -#[test] -fn system_digest_item_encoding() { - let item = DigestItem::ChangesTrieRoot::(H256::default()); - let encoded = item.encode(); - assert_eq!(encoded, vec![ - // type = DigestItemType::ChangesTrieRoot - 2, - // trie root - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - ]); - - 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 encoded = item.encode(); - assert_eq!(encoded, vec![ - // type = DigestItemType::Other - 0, - // length of other data - 12, - // authorities - 10, 20, 30, - ]); - - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); - assert_eq!(item, decoded); -} diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs deleted file mode 100644 index 4341e3543add5..0000000000000 --- a/core/sr-primitives/src/lib.rs +++ /dev/null @@ -1,695 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Runtime Modules shared primitive types. - -#![warn(missing_docs)] -#![cfg_attr(not(feature = "std"), no_std)] - -// to allow benchmarking -#![cfg_attr(feature = "bench", feature(test))] -#[cfg(feature = "bench")] extern crate test; - -#[doc(hidden)] -pub use codec; -#[cfg(feature = "std")] -#[doc(hidden)] -pub use serde; -#[doc(hidden)] -pub use rstd; - -#[doc(hidden)] -pub use paste; - -#[doc(hidden)] -pub use app_crypto; - -#[cfg(feature = "std")] -pub use runtime_io::{StorageOverlay, ChildrenStorageOverlay}; - -use rstd::prelude::*; -use rstd::convert::TryFrom; -use primitives::{crypto, ed25519, sr25519, ecdsa, hash::{H256, H512}}; -use codec::{Encode, Decode}; - -#[cfg(feature = "std")] -pub mod testing; - -pub mod curve; -pub mod generic; -pub mod offchain; -pub mod traits; -pub mod transaction_validity; -pub mod weights; - -/// Re-export these since they're only "kind of" generic. -pub use generic::{DigestItem, Digest}; - -/// Re-export this since it's part of the API of this crate. -pub use primitives::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, AccountId32}}; -pub use app_crypto::RuntimeAppPublic; - -/// Re-export `RuntimeDebug`, to avoid dependency clutter. -pub use primitives::RuntimeDebug; - -/// Re-export top-level arithmetic stuff. -pub use arithmetic::{ - Perquintill, Perbill, Permill, Percent, - Rational128, Fixed64 -}; -/// Re-export 128 bit helpers. -pub use arithmetic::helpers_128bit; -/// Re-export big_uint stuff. -pub use arithmetic::biguint; - -/// An abstraction over justification for a block's validity under a consensus algorithm. -/// -/// Essentially a finality proof. The exact formulation will vary between consensus -/// algorithms. In the case where there are multiple valid proofs, inclusion within -/// the block itself would allow swapping justifications to change the block's hash -/// (and thus fork the chain). Sending a `Justification` alongside a block instead -/// bypasses this problem. -pub type Justification = Vec; - -use traits::{Verify, Lazy}; - -/// A module identifier. These are per module and should be stored in a registry somewhere. -#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)] -pub struct ModuleId(pub [u8; 8]); - -impl TypeId for ModuleId { - const TYPE_ID: [u8; 4] = *b"modl"; -} - -/// 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; - -/// Create a const [RuntimeString]. -#[cfg(feature = "std")] -#[macro_export] -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 { - ( $y:expr ) => {{ $y }} -} - -#[cfg(feature = "std")] -pub use serde::{Serialize, Deserialize, de::DeserializeOwned}; -use crate::traits::IdentifyAccount; - -/// Complex storage builder stuff. -#[cfg(feature = "std")] -pub trait BuildStorage: Sized { - /// Build the storage out of this builder. - fn build_storage(&self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { - let mut storage = (Default::default(), Default::default()); - self.assimilate_storage(&mut storage)?; - Ok(storage) - } - /// Assimilate the storage for this module into pre-existing overlays. - fn assimilate_storage( - &self, - storage: &mut (StorageOverlay, ChildrenStorageOverlay), - ) -> Result<(), String>; -} - -/// Something that can build the genesis storage of a module. -#[cfg(feature = "std")] -pub trait BuildModuleGenesisStorage: Sized { - /// Create the module genesis storage into the given `storage` and `child_storage`. - fn build_module_genesis_storage( - &self, - storage: &mut (StorageOverlay, ChildrenStorageOverlay), - ) -> Result<(), String>; -} - -#[cfg(feature = "std")] -impl BuildStorage for (StorageOverlay, ChildrenStorageOverlay) { - fn assimilate_storage( - &self, - storage: &mut (StorageOverlay, ChildrenStorageOverlay), - )-> Result<(), String> { - storage.0.extend(self.0.iter().map(|(k, v)| (k.clone(), v.clone()))); - for (k, other_map) in self.1.iter() { - let k = k.clone(); - if let Some(map) = storage.1.get_mut(&k) { - map.extend(other_map.iter().map(|(k, v)| (k.clone(), v.clone()))); - } else { - storage.1.insert(k, other_map.clone()); - } - } - Ok(()) - } -} - -/// Consensus engine unique ID. -pub type ConsensusEngineId = [u8; 4]; - -/// Signature verify that can work with any known signature types.. -#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug)] -pub enum MultiSignature { - /// An Ed25519 signature. - Ed25519(ed25519::Signature), - /// An Sr25519 signature. - Sr25519(sr25519::Signature), - /// An ECDSA/SECP256k1 signature. - Ecdsa(ecdsa::Signature), -} - -impl From for MultiSignature { - fn from(x: ed25519::Signature) -> Self { - MultiSignature::Ed25519(x) - } -} - -impl From for MultiSignature { - fn from(x: sr25519::Signature) -> Self { - MultiSignature::Sr25519(x) - } -} - -impl From for MultiSignature { - fn from(x: ecdsa::Signature) -> Self { - MultiSignature::Ecdsa(x) - } -} - -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, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub enum MultiSigner { - /// An Ed25519 identity. - Ed25519(ed25519::Public), - /// An Sr25519 identity. - Sr25519(sr25519::Public), - /// An SECP256k1/ECDSA identity (actually, the Blake2 hash of the pub key). - Ecdsa(ecdsa::Public), -} - -impl Default for MultiSigner { - fn default() -> Self { - MultiSigner::Ed25519(Default::default()) - } -} - -/// NOTE: This implementations is required by `SimpleAddressDeterminator`, -/// we convert the hash into some AccountId, it's fine to use any scheme. -impl> crypto::UncheckedFrom for MultiSigner { - fn unchecked_from(x: T) -> Self { - ed25519::Public::unchecked_from(x.into()).into() - } -} - -impl AsRef<[u8]> for MultiSigner { - fn as_ref(&self) -> &[u8] { - match *self { - MultiSigner::Ed25519(ref who) => who.as_ref(), - MultiSigner::Sr25519(ref who) => who.as_ref(), - MultiSigner::Ecdsa(ref who) => who.as_ref(), - } - } -} - -impl traits::IdentifyAccount for MultiSigner { - type AccountId = AccountId32; - fn into_account(self) -> AccountId32 { - match self { - MultiSigner::Ed25519(who) => <[u8; 32]>::from(who).into(), - MultiSigner::Sr25519(who) => <[u8; 32]>::from(who).into(), - MultiSigner::Ecdsa(who) => runtime_io::blake2_256(who.as_ref()).into(), - } - } -} - -impl From for MultiSigner { - fn from(x: ed25519::Public) -> Self { - MultiSigner::Ed25519(x) - } -} - -impl TryFrom for ed25519::Public { - type Error = (); - fn try_from(m: MultiSigner) -> Result { - if let MultiSigner::Ed25519(x) = m { Ok(x) } else { Err(()) } - } -} - -impl From for MultiSigner { - fn from(x: sr25519::Public) -> Self { - MultiSigner::Sr25519(x) - } -} - -impl TryFrom for sr25519::Public { - type Error = (); - fn try_from(m: MultiSigner) -> Result { - if let MultiSigner::Sr25519(x) = m { Ok(x) } else { Err(()) } - } -} - -impl From for MultiSigner { - fn from(x: ecdsa::Public) -> Self { - MultiSigner::Ecdsa(x) - } -} - -impl TryFrom for ecdsa::Public { - type Error = (); - fn try_from(m: MultiSigner) -> Result { - if let MultiSigner::Ecdsa(x) = m { Ok(x) } else { Err(()) } - } -} - -#[cfg(feature = "std")] -impl std::fmt::Display for MultiSigner { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - match *self { - MultiSigner::Ed25519(ref who) => write!(fmt, "ed25519: {}", who), - MultiSigner::Sr25519(ref who) => write!(fmt, "sr25519: {}", who), - MultiSigner::Ecdsa(ref who) => write!(fmt, "ecdsa: {}", who), - } - } -} - -impl Verify for MultiSignature { - type Signer = MultiSigner; - fn verify>(&self, mut msg: L, signer: &AccountId32) -> bool { - use primitives::crypto::Public; - match (self, signer) { - (MultiSignature::Ed25519(ref sig), who) => sig.verify(msg, &ed25519::Public::from_slice(who.as_ref())), - (MultiSignature::Sr25519(ref sig), who) => sig.verify(msg, &sr25519::Public::from_slice(who.as_ref())), - (MultiSignature::Ecdsa(ref sig), who) => { - let m = runtime_io::blake2_256(msg.get()); - match runtime_io::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { - Ok(pubkey) => &runtime_io::blake2_256(pubkey.as_ref()) == >::as_ref(who), - _ => false, - } - } - } - } -} - -/// Signature verify that can work with any known signature types.. -#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct AnySignature(H512); - -impl Verify for AnySignature { - type Signer = sr25519::Public; - fn verify>(&self, mut msg: L, signer: &sr25519::Public) -> bool { - use primitives::crypto::Public; - let msg = msg.get(); - sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref()) - .map(|s| s.verify(msg, signer)) - .unwrap_or(false) - || ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref()) - .map(|s| s.verify(msg, &ed25519::Public::from_slice(signer.as_ref()))) - .unwrap_or(false) - } -} - -impl From for AnySignature { - fn from(s: sr25519::Signature) -> Self { - AnySignature(s.into()) - } -} - -impl From for AnySignature { - fn from(s: ed25519::Signature) -> Self { - AnySignature(s.into()) - } -} - -#[derive(Eq, PartialEq, Clone, Copy, Decode, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize))] -/// Reason why an extrinsic couldn't be applied (i.e. invalid extrinsic). -pub enum ApplyError { - /// General error to do with the permissions of the sender. - NoPermission, - - /// General error to do with the state of the system in general. - BadState, - - /// Any error to do with the transaction validity. - Validity(transaction_validity::TransactionValidityError), -} - -impl ApplyError { - /// Returns if the reason for the error was block resource exhaustion. - pub fn exhausted_resources(&self) -> bool { - match self { - Self::Validity(e) => e.exhausted_resources(), - _ => false, - } - } -} - -impl From for &'static str { - fn from(err: ApplyError) -> &'static str { - match err { - ApplyError::NoPermission => "Transaction does not have required permissions", - ApplyError::BadState => "System state currently prevents this transaction", - ApplyError::Validity(v) => v.into(), - } - } -} - -impl From for ApplyError { - fn from(err: transaction_validity::TransactionValidityError) -> Self { - ApplyError::Validity(err) - } -} - -/// The outcome of applying a transaction. -pub type ApplyOutcome = Result<(), DispatchError>; - -impl From for ApplyOutcome { - fn from(err: DispatchError) -> Self { - Err(err) - } -} - -/// Result from attempt to apply an extrinsic. -pub type ApplyResult = Result; - -#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize))] -/// Reason why a dispatch call failed -pub struct DispatchError { - /// Module index, matching the metadata module index - pub module: Option, - /// Module specific error value - pub error: u8, - /// Optional error message. - #[codec(skip)] - pub message: Option<&'static str>, -} - -impl DispatchError { - /// Create a new instance of `DispatchError`. - pub fn new(module: Option, error: u8, message: Option<&'static str>) -> Self { - Self { - module, - error, - message, - } - } -} - -impl traits::Printable for DispatchError { - fn print(&self) { - "DispatchError".print(); - if let Some(module) = self.module { - module.print(); - } - self.error.print(); - if let Some(msg) = self.message { - msg.print(); - } - } -} - -impl traits::ModuleDispatchError for &'static str { - fn as_u8(&self) -> u8 { - 0 - } - - fn as_str(&self) -> &'static str { - self - } -} - -impl From<&'static str> for DispatchError { - fn from(err: &'static str) -> DispatchError { - DispatchError::new(None, 0, Some(err)) - } -} - -/// Verify a signature on an encoded value in a lazy manner. This can be -/// an optimization if the signature scheme has an "unsigned" escape hash. -pub fn verify_encoded_lazy(sig: &V, item: &T, signer: &::AccountId) -> bool { - // The `Lazy` trait expresses something like `X: FnMut &'a T>`. - // unfortunately this is a lifetime relationship that can't - // be expressed without generic associated types, better unification of HRTBs in type position, - // and some kind of integration into the Fn* traits. - struct LazyEncode { - inner: F, - encoded: Option>, - } - - impl Vec> traits::Lazy<[u8]> for LazyEncode { - fn get(&mut self) -> &[u8] { - self.encoded.get_or_insert_with(&self.inner).as_slice() - } - } - - sig.verify( - LazyEncode { inner: || item.encode(), encoded: None }, - signer, - ) -} - -/// Helper macro for `impl_outer_config` -#[macro_export] -macro_rules! __impl_outer_config_types { - // Generic + Instance - ( - $concrete:ident $config:ident $snake:ident { $instance:ident } < $ignore:ident >; - $( $rest:tt )* - ) => { - #[cfg(any(feature = "std", test))] - pub type $config = $snake::GenesisConfig<$concrete, $snake::$instance>; - $crate::__impl_outer_config_types! { $concrete $( $rest )* } - }; - // Generic - ( - $concrete:ident $config:ident $snake:ident < $ignore:ident >; - $( $rest:tt )* - ) => { - #[cfg(any(feature = "std", test))] - pub type $config = $snake::GenesisConfig<$concrete>; - $crate::__impl_outer_config_types! { $concrete $( $rest )* } - }; - // No Generic and maybe Instance - ( - $concrete:ident $config:ident $snake:ident $( { $instance:ident } )?; - $( $rest:tt )* - ) => { - #[cfg(any(feature = "std", test))] - pub type $config = $snake::GenesisConfig; - $crate::__impl_outer_config_types! { $concrete $( $rest )* } - }; - ($concrete:ident) => () -} - -/// Implement the output "meta" module configuration struct, -/// which is basically: -/// pub struct GenesisConfig { -/// rust_module_one: Option, -/// ... -/// } -#[macro_export] -macro_rules! impl_outer_config { - ( - pub struct $main:ident for $concrete:ident { - $( $config:ident => - $snake:ident $( $instance:ident )? $( <$generic:ident> )*, )* - } - ) => { - $crate::__impl_outer_config_types! { - $concrete $( $config $snake $( { $instance } )? $( <$generic> )*; )* - } - - $crate::paste::item! { - #[cfg(any(feature = "std", test))] - #[derive($crate::serde::Serialize, $crate::serde::Deserialize)] - #[serde(rename_all = "camelCase")] - #[serde(deny_unknown_fields)] - pub struct $main { - $( - pub [< $snake $(_ $instance )? >]: Option<$config>, - )* - } - #[cfg(any(feature = "std", test))] - impl $crate::BuildStorage for $main { - fn assimilate_storage( - &self, - storage: &mut ($crate::StorageOverlay, $crate::ChildrenStorageOverlay), - ) -> std::result::Result<(), String> { - $( - if let Some(ref extra) = self.[< $snake $(_ $instance )? >] { - $crate::impl_outer_config! { - @CALL_FN - $concrete; - $snake; - $( $instance )?; - extra; - storage; - } - } - )* - Ok(()) - } - } - } - }; - (@CALL_FN - $runtime:ident; - $module:ident; - $instance:ident; - $extra:ident; - $storage:ident; - ) => { - $crate::BuildModuleGenesisStorage::<$runtime, $module::$instance>::build_module_genesis_storage( - $extra, - $storage, - )?; - }; - (@CALL_FN - $runtime:ident; - $module:ident; - ; - $extra:ident; - $storage:ident; - ) => { - $crate::BuildModuleGenesisStorage::<$runtime, $module::__InherentHiddenInstance>::build_module_genesis_storage( - $extra, - $storage, - )?; - } -} - -/// Checks that `$x` is equal to `$y` with an error rate of `$error`. -/// -/// # Example -/// -/// ```rust -/// # fn main() { -/// sr_primitives::assert_eq_error_rate!(10, 10, 0); -/// sr_primitives::assert_eq_error_rate!(10, 11, 1); -/// sr_primitives::assert_eq_error_rate!(12, 10, 2); -/// # } -/// ``` -/// -/// ```rust,should_panic -/// # fn main() { -/// sr_primitives::assert_eq_error_rate!(12, 10, 1); -/// # } -/// ``` -#[macro_export] -#[cfg(feature = "std")] -macro_rules! assert_eq_error_rate { - ($x:expr, $y:expr, $error:expr $(,)?) => { - assert!( - ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), - "{:?} != {:?} (with error rate {:?})", - $x, - $y, - $error, - ); - }; -} - -/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized -/// correctly. -#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] -pub struct OpaqueExtrinsic(pub Vec); - -impl rstd::fmt::Debug for OpaqueExtrinsic { - #[cfg(feature = "std")] - fn fmt(&self, fmt: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(fmt, "{}", primitives::hexdisplay::HexDisplay::from(&self.0)) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _fmt: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - - -#[cfg(feature = "std")] -impl ::serde::Serialize for OpaqueExtrinsic { - fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { - codec::Encode::using_encoded(&self.0, |bytes| ::primitives::bytes::serialize(bytes, seq)) - } -} - -#[cfg(feature = "std")] -impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic { - fn deserialize(de: D) -> Result where D: ::serde::Deserializer<'a> { - let r = ::primitives::bytes::deserialize(de)?; - Decode::decode(&mut &r[..]) - .map_err(|e| ::serde::de::Error::custom(format!("Decode error: {}", e))) - } -} - -impl traits::Extrinsic for OpaqueExtrinsic { - type Call = (); - type SignaturePayload = (); -} - -/// Print something that implements `Printable` from the runtime. -pub fn print(print: impl traits::Printable) { - print.print(); -} - -#[cfg(test)] -mod tests { - use crate::DispatchError; - use codec::{Encode, Decode}; - - #[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 dispatch_error_encoding() { - let error = DispatchError { - module: Some(1), - error: 2, - message: Some("error message"), - }; - let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); - assert_eq!(encoded, vec![1, 1, 2]); - assert_eq!( - decoded, - DispatchError { - module: Some(1), - error: 2, - message: None, - }, - ); - } -} diff --git a/core/sr-primitives/src/offchain/http.rs b/core/sr-primitives/src/offchain/http.rs deleted file mode 100644 index 77e514d65342b..0000000000000 --- a/core/sr-primitives/src/offchain/http.rs +++ /dev/null @@ -1,595 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! A high-level helpers for making HTTP requests from Offchain Workers. -//! -//! `sr-io` crate exposes a low level methods to make and control HTTP requests -//! available only for Offchain Workers. Those might be hard to use -//! and usually that level of control is not really necessary. -//! This module aims to provide high-level wrappers for those APIs -//! to simplify making HTTP requests. -//! -//! -//! Example: -//! ```rust,no_run -//! use sr_primitives::offchain::http::Request; -//! -//! // initiate a GET request to localhost:1234 -//! let request: Request = Request::get("http://localhost:1234"); -//! let pending = request -//! .add_header("X-Auth", "hunter2") -//! .send() -//! .unwrap(); -//! -//! // wait for the response indefinitely -//! let mut response = pending.wait().unwrap(); -//! -//! // then check the headers -//! let mut headers = response.headers().into_iter(); -//! assert_eq!(headers.current(), None); -//! -//! // and collect the body -//! let body = response.body(); -//! assert_eq!(body.clone().collect::>(), b"1234".to_vec()); -//! assert_eq!(body.error(), &None); -//! ``` - -use rstd::str; -use rstd::prelude::Vec; -#[cfg(not(feature = "std"))] -use rstd::prelude::vec; -use primitives::RuntimeDebug; -use primitives::offchain::{ - Timestamp, - HttpRequestId as RequestId, - HttpRequestStatus as RequestStatus, - HttpError, -}; - -/// Request method (HTTP verb) -#[derive(Clone, PartialEq, Eq, RuntimeDebug)] -pub enum Method { - /// GET request - Get, - /// POST request - Post, - /// PUT request - Put, - /// PATCH request - Patch, - /// DELETE request - Delete, - /// Custom verb - Other(&'static str), -} - -impl AsRef for Method { - fn as_ref(&self) -> &str { - match *self { - Method::Get => "GET", - Method::Post => "POST", - Method::Put => "PUT", - Method::Patch => "PATCH", - Method::Delete => "DELETE", - Method::Other(m) => m, - } - } -} - -mod header { - use super::*; - - /// A header type. - #[derive(Clone, PartialEq, Eq, RuntimeDebug)] - pub struct Header { - name: Vec, - value: Vec, - } - - impl Header { - /// Creates new header given it's name and value. - pub fn new(name: &str, value: &str) -> Self { - Header { - name: name.as_bytes().to_vec(), - value: value.as_bytes().to_vec(), - } - } - - /// Returns the name of this header. - pub fn name(&self) -> &str { - // Header keys are always produced from `&str` so this is safe. - // we don't store them as `Strings` to avoid bringing `alloc::String` to rstd - // or here. - unsafe { str::from_utf8_unchecked(&self.name) } - } - - /// Returns the value of this header. - pub fn value(&self) -> &str { - // Header values are always produced from `&str` so this is safe. - // we don't store them as `Strings` to avoid bringing `alloc::String` to rstd - // or here. - unsafe { str::from_utf8_unchecked(&self.value) } - } - } -} - -/// An HTTP request builder. -#[derive(Clone, PartialEq, Eq, RuntimeDebug)] -pub struct Request<'a, T = Vec<&'static [u8]>> { - /// Request method - pub method: Method, - /// Request URL - pub url: &'a str, - /// Body of the request - pub body: T, - /// Deadline to finish sending the request - pub deadline: Option, - /// Request list of headers. - headers: Vec, -} - -impl Default for Request<'static, T> { - fn default() -> Self { - Request { - method: Method::Get, - url: "http://localhost", - headers: Vec::new(), - body: Default::default(), - deadline: None, - } - } -} - -impl<'a> Request<'a> { - /// Start a simple GET request - pub fn get(url: &'a str) -> Self { - Self::new(url) - } -} - -impl<'a, T> Request<'a, T> { - /// Create new POST request with given body. - pub fn post(url: &'a str, body: T) -> Self { - let req: Request = Request::default(); - - Request { - url, - body, - method: Method::Post, - headers: req.headers, - deadline: req.deadline, - } - } -} - -impl<'a, T: Default> Request<'a, T> { - /// Create new Request builder with given URL and body. - pub fn new(url: &'a str) -> Self { - Request::default().url(url) - } - - /// Change the method of the request - pub fn method(mut self, method: Method) -> Self { - self.method = method; - self - } - - /// Change the URL of the request. - pub fn url(mut self, url: &'a str) -> Self { - self.url = url; - self - } - - /// Set the body of the request. - pub fn body(mut self, body: T) -> Self { - self.body = body; - self - } - - /// Add a header. - pub fn add_header(mut self, name: &str, value: &str) -> Self { - self.headers.push(header::Header::new(name, value)); - self - } - - /// Set the deadline of the request. - pub fn deadline(mut self, deadline: Timestamp) -> Self { - self.deadline = Some(deadline); - self - } -} - -impl<'a, I: AsRef<[u8]>, T: IntoIterator> Request<'a, T> { - /// Send the request and return a handle. - /// - /// Err is returned in case the deadline is reached - /// or the request timeouts. - pub fn send(self) -> Result { - let meta = &[]; - - // start an http request. - let id = runtime_io::http_request_start(self.method.as_ref(), self.url, meta).map_err(|_| HttpError::IoError)?; - - // add custom headers - for header in &self.headers { - runtime_io::http_request_add_header( - id, - header.name(), - header.value(), - ).map_err(|_| HttpError::IoError)? - } - - // write body - for chunk in self.body { - runtime_io::http_request_write_body(id, chunk.as_ref(), self.deadline)?; - } - - // finalise the request - runtime_io::http_request_write_body(id, &[], self.deadline)?; - - Ok(PendingRequest { - id, - }) - } -} - -/// A request error -#[derive(Clone, PartialEq, Eq, RuntimeDebug)] -pub enum Error { - /// Deadline has been reached. - DeadlineReached, - /// Request had timed out. - IoError, - /// Unknown error has been ecountered. - Unknown, -} - -/// A struct representing an uncompleted http request. -#[derive(PartialEq, Eq, RuntimeDebug)] -pub struct PendingRequest { - /// Request ID - pub id: RequestId, -} - -/// A result of waiting for a pending request. -pub type HttpResult = Result; - -impl PendingRequest { - /// Wait for the request to complete. - /// - /// NOTE this waits for the request indefinitely. - pub fn wait(self) -> HttpResult { - match self.try_wait(None) { - Ok(res) => res, - Err(_) => panic!("Since `None` is passed we will never get a deadline error; qed"), - } - } - - /// Attempts to wait for the request to finish, - /// but will return `Err` in case the deadline is reached. - pub fn try_wait(self, deadline: impl Into>) -> Result { - Self::try_wait_all(vec![self], deadline).pop().expect("One request passed, one status received; qed") - } - - /// Wait for all provided requests. - pub fn wait_all(requests: Vec) -> Vec { - Self::try_wait_all(requests, None) - .into_iter() - .map(|r| match r { - Ok(r) => r, - Err(_) => panic!("Since `None` is passed we will never get a deadline error; qed"), - }) - .collect() - } - - /// Attempt to wait for all provided requests, but up to given deadline. - /// - /// Requests that are complete will resolve to an `Ok` others will return a `DeadlineReached` error. - pub fn try_wait_all( - requests: Vec, - deadline: impl Into> - ) -> Vec> { - let ids = requests.iter().map(|r| r.id).collect::>(); - let statuses = runtime_io::http_response_wait(&ids, deadline.into()); - - statuses - .into_iter() - .zip(requests.into_iter()) - .map(|(status, req)| match status { - RequestStatus::DeadlineReached => Err(req), - RequestStatus::IoError => Ok(Err(Error::IoError)), - RequestStatus::Invalid => Ok(Err(Error::Unknown)), - RequestStatus::Finished(code) => Ok(Ok(Response::new(req.id, code))), - }) - .collect() - } -} - -/// A HTTP response. -#[derive(RuntimeDebug)] -pub struct Response { - /// Request id - pub id: RequestId, - /// Response status code - pub code: u16, - /// A collection of headers. - headers: Option, -} - -impl Response { - fn new(id: RequestId, code: u16) -> Self { - Self { - id, - code, - headers: None, - } - } - - /// Retrieve the headers for this response. - pub fn headers(&mut self) -> &Headers { - if self.headers.is_none() { - self.headers = Some(Headers { raw: runtime_io::http_response_headers(self.id) }); - } - self.headers.as_ref().expect("Headers were just set; qed") - } - - /// Retrieve the body of this response. - pub fn body(&self) -> ResponseBody { - ResponseBody::new(self.id) - } -} - -/// A buffered byte iterator over response body. -/// -/// Note that reading the body may return `None` in following cases: -/// 1. Either the deadline you've set is reached (check via `#error`; -/// In such case you can resume the reader by setting a new deadline) -/// 2. Or because of IOError. In such case the reader is not resumable and will keep -/// returning `None`. -/// 3. The body has been returned. The reader will keep returning `None`. -#[derive(Clone)] -pub struct ResponseBody { - id: RequestId, - error: Option, - buffer: [u8; 4096], - filled_up_to: Option, - position: usize, - deadline: Option, -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for ResponseBody { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - fmt.debug_struct("ResponseBody") - .field("id", &self.id) - .field("error", &self.error) - .field("buffer", &self.buffer.len()) - .field("filled_up_to", &self.filled_up_to) - .field("position", &self.position) - .field("deadline", &self.deadline) - .finish() - } -} - -impl ResponseBody { - fn new(id: RequestId) -> Self { - ResponseBody { - id, - error: None, - buffer: [0_u8; 4096], - filled_up_to: None, - position: 0, - deadline: None, - } - } - - /// Set the deadline for reading the body. - pub fn deadline(&mut self, deadline: impl Into>) { - self.deadline = deadline.into(); - self.error = None; - } - - /// Return an error that caused the iterator to return `None`. - /// - /// If the error is `DeadlineReached` you can resume the iterator by setting - /// a new deadline. - pub fn error(&self) -> &Option { - &self.error - } -} - -impl Iterator for ResponseBody { - type Item = u8; - - fn next(&mut self) -> Option { - if self.error.is_some() { - return None; - } - - if self.filled_up_to.is_none() { - let result = runtime_io::http_response_read_body(self.id, &mut self.buffer, self.deadline); - match result { - Err(e) => { - self.error = Some(e); - return None; - } - Ok(0) => { - return None; - } - Ok(size) => { - self.position = 0; - self.filled_up_to = Some(size); - } - } - } - - if Some(self.position) == self.filled_up_to { - self.filled_up_to = None; - return self.next(); - } - - let result = self.buffer[self.position]; - self.position += 1; - Some(result) - } -} - -/// A collection of Headers in the response. -#[derive(Clone, PartialEq, Eq, RuntimeDebug)] -pub struct Headers { - /// Raw headers - pub raw: Vec<(Vec, Vec)>, -} - -impl Headers { - /// Retrieve a single header from the list of headers. - /// - /// Note this method is linearly looking from all the headers - /// comparing them with the needle byte-by-byte. - /// If you want to consume multiple headers it's better to iterate - /// and collect them on your own. - pub fn find(&self, name: &str) -> Option<&str> { - let raw = name.as_bytes(); - for &(ref key, ref val) in &self.raw { - if &**key == raw { - return str::from_utf8(&val).ok() - } - } - None - } - - /// Convert this headers into an iterator. - pub fn into_iter(&self) -> HeadersIterator { - HeadersIterator { collection: &self.raw, index: None } - } -} - -/// A custom iterator traversing all the headers. -#[derive(Clone, RuntimeDebug)] -pub struct HeadersIterator<'a> { - collection: &'a [(Vec, Vec)], - index: Option, -} - -impl<'a> HeadersIterator<'a> { - /// Move the iterator to the next position. - /// - /// Returns `true` is `current` has been set by this call. - pub fn next(&mut self) -> bool { - let index = self.index.map(|x| x + 1).unwrap_or(0); - self.index = Some(index); - index < self.collection.len() - } - - /// Returns current element (if any). - /// - /// Note that you have to call `next` prior to calling this - pub fn current(&self) -> Option<(&str, &str)> { - self.collection.get(self.index?) - .map(|val| (str::from_utf8(&val.0).unwrap_or(""), str::from_utf8(&val.1).unwrap_or(""))) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use runtime_io::TestExternalities; - use substrate_offchain::testing; - use primitives::offchain::OffchainExt; - - #[test] - fn should_send_a_basic_request_and_get_response() { - let (offchain, state) = testing::TestOffchainExt::new(); - let mut t = TestExternalities::default(); - t.register_extension(OffchainExt::new(offchain)); - - t.execute_with(|| { - let request: Request = Request::get("http://localhost:1234"); - let pending = request - .add_header("X-Auth", "hunter2") - .send() - .unwrap(); - // make sure it's sent correctly - state.write().fulfill_pending_request( - 0, - testing::PendingRequest { - method: "GET".into(), - uri: "http://localhost:1234".into(), - headers: vec![("X-Auth".into(), "hunter2".into())], - sent: true, - ..Default::default() - }, - b"1234".to_vec(), - None, - ); - - // wait - let mut response = pending.wait().unwrap(); - - // then check the response - let mut headers = response.headers().into_iter(); - assert_eq!(headers.current(), None); - assert_eq!(headers.next(), false); - assert_eq!(headers.current(), None); - - let body = response.body(); - assert_eq!(body.clone().collect::>(), b"1234".to_vec()); - assert_eq!(body.error(), &None); - }) - } - - #[test] - fn should_send_a_post_request() { - let (offchain, state) = testing::TestOffchainExt::new(); - let mut t = TestExternalities::default(); - t.register_extension(OffchainExt::new(offchain)); - - t.execute_with(|| { - let pending = Request::default() - .method(Method::Post) - .url("http://localhost:1234") - .body(vec![b"1234"]) - .send() - .unwrap(); - // make sure it's sent correctly - state.write().fulfill_pending_request( - 0, - testing::PendingRequest { - method: "POST".into(), - uri: "http://localhost:1234".into(), - body: b"1234".to_vec(), - sent: true, - ..Default::default() - }, - b"1234".to_vec(), - Some(("Test".to_owned(), "Header".to_owned())), - ); - - // wait - let mut response = pending.wait().unwrap(); - - // then check the response - let mut headers = response.headers().into_iter(); - assert_eq!(headers.current(), None); - assert_eq!(headers.next(), true); - assert_eq!(headers.current(), Some(("Test", "Header"))); - - let body = response.body(); - assert_eq!(body.clone().collect::>(), b"1234".to_vec()); - assert_eq!(body.error(), &None); - }) - } -} diff --git a/core/sr-primitives/src/offchain/mod.rs b/core/sr-primitives/src/offchain/mod.rs deleted file mode 100644 index 6b82f77111999..0000000000000 --- a/core/sr-primitives/src/offchain/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! A collection of higher lever helpers for offchain workers. - -pub mod http; diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs deleted file mode 100644 index b790347118815..0000000000000 --- a/core/sr-primitives/src/testing.rs +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Testing utilities. - -use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer}; -use std::{fmt::Debug, ops::Deref, fmt, cell::RefCell}; -use crate::codec::{Codec, Encode, Decode}; -use crate::traits::{ - self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, ValidateUnsigned, - SignedExtension, Dispatchable, -}; -use crate::{generic, KeyTypeId, ApplyResult}; -use crate::weights::{GetDispatchInfo, DispatchInfo}; -pub use primitives::{H256, sr25519}; -use primitives::{crypto::{CryptoType, Dummy, key_types, Public}, U256}; -use crate::transaction_validity::{TransactionValidity, TransactionValidityError}; - -/// Authority Id -#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug, Hash, Serialize, Deserialize, PartialOrd, Ord)] -pub struct UintAuthorityId(pub u64); - -impl From for UintAuthorityId { - fn from(id: u64) -> Self { - UintAuthorityId(id) - } -} - -impl From for u64 { - fn from(id: UintAuthorityId) -> u64 { - id.0 - } -} - -impl UintAuthorityId { - /// Convert this authority id into a public key. - pub fn to_public_key(&self) -> T { - let bytes: [u8; 32] = U256::from(self.0).into(); - T::from_slice(&bytes) - } -} - -impl CryptoType for UintAuthorityId { - type Pair = Dummy; -} - -impl AsRef<[u8]> for UintAuthorityId { - fn as_ref(&self) -> &[u8] { - // Unsafe, i know, but it's test code and it's just there because it's really convenient to - // keep `UintAuthorityId` as a u64 under the hood. - unsafe { - std::slice::from_raw_parts(&self.0 as *const u64 as *const _, std::mem::size_of::()) - } - } -} - -thread_local! { - /// A list of all UintAuthorityId keys returned to the runtime. - static ALL_KEYS: RefCell> = RefCell::new(vec![]); -} - -impl UintAuthorityId { - /// Set the list of keys returned by the runtime call for all keys of that type. - pub fn set_all_keys>(keys: impl IntoIterator) { - ALL_KEYS.with(|l| *l.borrow_mut() = keys.into_iter().map(Into::into).collect()) - } -} - -impl app_crypto::RuntimeAppPublic for UintAuthorityId { - const ID: KeyTypeId = key_types::DUMMY; - - type Signature = u64; - - fn all() -> Vec { - ALL_KEYS.with(|l| l.borrow().clone()) - } - - fn generate_pair(_: Option<&str>) -> Self { - use rand::RngCore; - UintAuthorityId(rand::thread_rng().next_u64()) - } - - fn sign>(&self, msg: &M) -> Option { - let mut signature = [0u8; 8]; - msg.as_ref().iter() - .chain(std::iter::repeat(&42u8)) - .take(8) - .enumerate() - .for_each(|(i, v)| { signature[i] = *v; }); - - Some(u64::from_le_bytes(signature)) - } - - fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { - let mut msg_signature = [0u8; 8]; - msg.as_ref().iter() - .chain(std::iter::repeat(&42)) - .take(8) - .enumerate() - .for_each(|(i, v)| { msg_signature[i] = *v; }); - - u64::from_le_bytes(msg_signature) == *signature - } -} - -impl OpaqueKeys for UintAuthorityId { - type KeyTypeIds = std::iter::Cloned>; - - fn key_ids() -> Self::KeyTypeIds { - [key_types::DUMMY].iter().cloned() - } - - fn get_raw(&self, _: KeyTypeId) -> &[u8] { - self.as_ref() - } - - fn get(&self, _: KeyTypeId) -> Option { - self.using_encoded(|mut x| T::decode(&mut x)).ok() - } -} - -/// Digest item -pub type DigestItem = generic::DigestItem; - -/// Header Digest -pub type Digest = generic::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, -} - -impl traits::Header for Header { - type Number = u64; - type Hashing = BlakeTwo256; - type Hash = H256; - - fn number(&self) -> &Self::Number { &self.number } - fn set_number(&mut self, num: Self::Number) { self.number = num } - - fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root } - fn set_extrinsics_root(&mut self, root: Self::Hash) { self.extrinsics_root = root } - - fn state_root(&self) -> &Self::Hash { &self.state_root } - fn set_state_root(&mut self, root: Self::Hash) { self.state_root = root } - - fn parent_hash(&self) -> &Self::Hash { &self.parent_hash } - fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash } - - fn digest(&self) -> &Digest { &self.digest } - fn digest_mut(&mut self) -> &mut Digest { &mut self.digest } - - fn new( - number: Self::Number, - extrinsics_root: Self::Hash, - state_root: Self::Hash, - parent_hash: Self::Hash, - digest: Digest, - ) -> Self { - Header { - number, - extrinsics_root, - state_root, - parent_hash, - digest, - } - } -} - -impl<'a> Deserialize<'a> for Header { - fn deserialize>(de: D) -> Result { - let r = >::deserialize(de)?; - Decode::decode(&mut &r[..]) - .map_err(|e| DeError::custom(format!("Invalid value passed into decode: {}", e.what()))) - } -} - -/// An opaque extrinsic wrapper type. -#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] -pub struct ExtrinsicWrapper(Xt); - -impl traits::Extrinsic for ExtrinsicWrapper { - type Call = (); - type SignaturePayload = (); - - fn is_signed(&self) -> Option { - None - } -} - -impl serde::Serialize for ExtrinsicWrapper { - fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { - self.using_encoded(|bytes| seq.serialize_bytes(bytes)) - } -} - -impl From for ExtrinsicWrapper { - fn from(xt: Xt) -> Self { - ExtrinsicWrapper(xt) - } -} - -impl Deref for ExtrinsicWrapper { - type Target = Xt; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// Testing block -#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] -pub struct Block { - /// Block header - pub header: Header, - /// List of extrinsics - pub extrinsics: Vec, -} - -impl traits::Block for Block { - type Extrinsic = Xt; - type Header = Header; - type Hash =

::Hash; - - fn header(&self) -> &Self::Header { - &self.header - } - fn extrinsics(&self) -> &[Self::Extrinsic] { - &self.extrinsics[..] - } - fn deconstruct(self) -> (Self::Header, Vec) { - (self.header, self.extrinsics) - } - fn new(header: Self::Header, extrinsics: Vec) -> Self { - Block { header, extrinsics } - } - fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec { - (header, extrinsics).encode() - } -} - -impl<'a, Xt> Deserialize<'a> for Block where Block: Decode { - fn deserialize>(de: D) -> Result { - let r = >::deserialize(de)?; - Decode::decode(&mut &r[..]) - .map_err(|e| DeError::custom(format!("Invalid value passed into decode: {}", e.what()))) - } -} - -/// Test transaction, tuple of (sender, call, signed_extra) -/// with index only used if sender is some. -/// -/// If sender is some then the transaction is signed otherwise it is unsigned. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -pub struct TestXt(pub Option<(u64, Extra)>, pub Call); - -impl Serialize for TestXt where TestXt: Encode { - fn serialize(&self, seq: S) -> Result where S: Serializer { - self.using_encoded(|bytes| seq.serialize_bytes(bytes)) - } -} - -impl Debug for TestXt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TestXt({:?}, ...)", self.0.as_ref().map(|x| &x.0)) - } -} - -impl Checkable for TestXt { - type Checked = Self; - fn check(self, _: &Context) -> Result { Ok(self) } -} -impl traits::Extrinsic for TestXt { - type Call = Call; - type SignaturePayload = (u64, Extra); - - fn is_signed(&self) -> Option { - Some(self.0.is_some()) - } - - fn new(c: Call, sig: Option) -> Option { - Some(TestXt(sig, c)) - } -} - -impl Applyable for TestXt where - Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Dispatchable, - Extra: SignedExtension, - Origin: From>, -{ - type AccountId = u64; - type Call = Call; - - fn sender(&self) -> Option<&Self::AccountId> { self.0.as_ref().map(|x| &x.0) } - - /// Checks to see if this is a valid *transaction*. It returns information on it if so. - fn validate>( - &self, - _info: DispatchInfo, - _len: usize, - ) -> TransactionValidity { - Ok(Default::default()) - } - - /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, - /// index and sender. - fn apply( - self, - info: DispatchInfo, - len: usize, - ) -> ApplyResult { - let maybe_who = if let Some((who, extra)) = self.0 { - Extra::pre_dispatch(extra, &who, &self.1, info, len)?; - Some(who) - } else { - Extra::pre_dispatch_unsigned(&self.1, info, len)?; - None - }; - - Ok(self.1.dispatch(maybe_who.into()).map_err(Into::into)) - } -} - -impl GetDispatchInfo for TestXt { - fn get_dispatch_info(&self) -> DispatchInfo { - // for testing: weight == size. - DispatchInfo { - weight: self.encode().len() as _, - ..Default::default() - } - } -} diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs deleted file mode 100644 index 4586a84511f73..0000000000000 --- a/core/sr-primitives/src/traits.rs +++ /dev/null @@ -1,1298 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Primitives for the runtime modules. - -use rstd::prelude::*; -use rstd::{self, result, marker::PhantomData, convert::{TryFrom, TryInto}, fmt::Debug}; -use runtime_io; -#[cfg(feature = "std")] -use std::fmt::Display; -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize, de::DeserializeOwned}; -use primitives::{self, Hasher, Blake2Hasher, TypeId}; -use crate::codec::{Codec, Encode, Decode}; -use crate::transaction_validity::{ - ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction, -}; -use crate::generic::{Digest, DigestItem}; -use crate::weights::DispatchInfo; -pub use arithmetic::traits::{ - SimpleArithmetic, UniqueSaturatedInto, UniqueSaturatedFrom, Saturating, SaturatedConversion, - Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, - CheckedShl, CheckedShr, IntegerSquareRoot -}; -use app_crypto::AppKey; -use impl_trait_for_tuples::impl_for_tuples; - -/// 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; -} - -impl<'a> Lazy<[u8]> for &'a [u8] { - fn get(&mut self) -> &[u8] { &**self } -} - -/// Some type that is able to be collapsed into an account ID. It is not possible to recreate the original value from -/// the account ID. -pub trait IdentifyAccount { - /// The account ID that this can be transformed into. - type AccountId; - /// Transform into an account. - fn into_account(self) -> Self::AccountId; -} - -impl IdentifyAccount for primitives::ed25519::Public { - type AccountId = Self; - fn into_account(self) -> Self { self } -} - -impl IdentifyAccount for primitives::sr25519::Public { - type AccountId = Self; - fn into_account(self) -> Self { self } -} - -impl IdentifyAccount for primitives::ecdsa::Public { - type AccountId = Self; - fn into_account(self) -> Self { self } -} - -/// Means of signature verification. -pub trait Verify { - /// Type of the signer. - type Signer: IdentifyAccount; - /// Verify a signature. Return `true` if signature is valid for the value. - fn verify>(&self, msg: L, signer: &::AccountId) -> bool; -} - -impl Verify for primitives::ed25519::Signature { - type Signer = primitives::ed25519::Public; - fn verify>(&self, mut msg: L, signer: &primitives::ed25519::Public) -> bool { - runtime_io::ed25519_verify(self, msg.get(), signer) - } -} - -impl Verify for primitives::sr25519::Signature { - type Signer = primitives::sr25519::Public; - fn verify>(&self, mut msg: L, signer: &primitives::sr25519::Public) -> bool { - runtime_io::sr25519_verify(self, msg.get(), signer) - } -} - -impl Verify for primitives::ecdsa::Signature { - type Signer = primitives::ecdsa::Public; - fn verify>(&self, mut msg: L, signer: &primitives::ecdsa::Public) -> bool { - match runtime_io::secp256k1_ecdsa_recover_compressed(self.as_ref(), &runtime_io::blake2_256(msg.get())) { - Ok(pubkey) => >::as_ref(signer) == &pubkey[..], - _ => false, - } - } -} - -/// Means of signature verification of an application key. -pub trait AppVerify { - /// Type of the signer. - type AccountId; - /// Verify a signature. Return `true` if signature is valid for the value. - fn verify>(&self, msg: L, signer: &Self::AccountId) -> bool; -} - -impl< - S: Verify::Public as app_crypto::AppPublic>::Generic> + From, - T: app_crypto::Wraps + app_crypto::AppKey + app_crypto::AppSignature + - AsRef + AsMut + From, -> AppVerify for T where - ::Signer: IdentifyAccount::Signer>, - <::Public as app_crypto::AppPublic>::Generic: - IdentifyAccount::Public as app_crypto::AppPublic>::Generic>, -{ - type AccountId = ::Public; - fn verify>(&self, msg: L, signer: &::Public) -> bool { - use app_crypto::IsWrappedBy; - let inner: &S = self.as_ref(); - let inner_pubkey = <::Public as app_crypto::AppPublic>::Generic::from_ref(&signer); - Verify::verify(inner, msg, inner_pubkey) - } -} - -/// An error type that indicates that the origin is invalid. -#[derive(Encode, Decode)] -pub struct InvalidOrigin; - -impl From for &'static str { - fn from(_: InvalidOrigin) -> &'static str { - "Invalid origin" - } -} - -/// Some sort of check on the origin is performed by this object. -pub trait EnsureOrigin { - /// A return type. - type Success; - /// Perform the origin check. - fn ensure_origin(o: OuterOrigin) -> result::Result { - Self::try_origin(o).map_err(|_| InvalidOrigin) - } - /// Perform the origin check. - fn try_origin(o: OuterOrigin) -> result::Result; -} - -/// An error that indicates that a lookup failed. -#[derive(Encode, Decode)] -pub struct LookupError; - -impl From for &'static str { - fn from(_: LookupError) -> &'static str { - "Can not lookup" - } -} - -impl From for TransactionValidityError { - fn from(_: LookupError) -> Self { - UnknownTransaction::CannotLookup.into() - } -} - -/// Means of changing one type into another in a manner dependent on the source type. -pub trait Lookup { - /// Type to lookup from. - type Source; - /// Type to lookup into. - type Target; - /// Attempt a lookup. - fn lookup(&self, s: Self::Source) -> 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 + Debug; - /// Type to lookup into. - type Target; - /// Attempt a lookup. - fn lookup(s: Self::Source) -> 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 { Ok(x) } - fn unlookup(x: T) -> T { x } -} - -impl Lookup for IdentityLookup { - type Source = T; - type Target = T; - fn lookup(&self, x: T) -> Result { Ok(x) } -} - -/// 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 } -} - -/// A structure that performs standard conversion using the standard Rust conversion traits. -pub struct ConvertInto; -impl> Convert for ConvertInto { - fn convert(a: A) -> B { a.into() } -} - -/// Convenience type to work around the highly unergonomic syntax needed -/// to invoke the functions of overloaded generic traits, in this case -/// `TryFrom` and `TryInto`. -pub trait CheckedConversion { - /// Convert from a value of `T` into an equivalent instance of `Option`. - /// - /// This just uses `TryFrom` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn checked_from(t: T) -> Option where Self: TryFrom { - >::try_from(t).ok() - } - /// Consume self to return `Some` equivalent value of `Option`. - /// - /// This just uses `TryInto` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn checked_into(self) -> Option where Self: TryInto { - >::try_into(self).ok() - } -} -impl CheckedConversion for T {} - -/// Multiply and divide by a number that isn't necessarily the same type. Basically just the same -/// as `Mul` and `Div` except it can be used for all basic numeric types. -pub trait Scale { - /// The output type of the product of `self` and `Other`. - type Output; - - /// @return the product of `self` and `other`. - fn mul(self, other: Other) -> Self::Output; - - /// @return the integer division of `self` and `other`. - fn div(self, other: Other) -> Self::Output; - - /// @return the modulo remainder of `self` and `other`. - fn rem(self, other: Other) -> Self::Output; -} -macro_rules! impl_scale { - ($self:ty, $other:ty) => { - impl Scale<$other> for $self { - type Output = Self; - fn mul(self, other: $other) -> Self::Output { self * (other as Self) } - fn div(self, other: $other) -> Self::Output { self / (other as Self) } - fn rem(self, other: $other) -> Self::Output { self % (other as Self) } - } - } -} -impl_scale!(u128, u128); -impl_scale!(u128, u64); -impl_scale!(u128, u32); -impl_scale!(u128, u16); -impl_scale!(u128, u8); -impl_scale!(u64, u64); -impl_scale!(u64, u32); -impl_scale!(u64, u16); -impl_scale!(u64, u8); -impl_scale!(u32, u32); -impl_scale!(u32, u16); -impl_scale!(u32, u8); -impl_scale!(u16, u16); -impl_scale!(u16, u8); -impl_scale!(u8, u8); - -/// Trait for things that can be clear (have no bits set). For numeric types, essentially the same -/// as `Zero`. -pub trait Clear { - /// True iff no bits are set. - fn is_clear(&self) -> bool; - - /// Return the value of Self that is clear. - fn clear() -> Self; -} - -impl Clear for T { - fn is_clear(&self) -> bool { *self == Self::clear() } - fn clear() -> Self { Default::default() } -} - -/// A meta trait for all bit ops. -pub trait SimpleBitOps: - Sized + Clear + - rstd::ops::BitOr + - rstd::ops::BitXor + - rstd::ops::BitAnd -{} -impl + - rstd::ops::BitXor + - rstd::ops::BitAnd -> SimpleBitOps for T {} - -/// The block finalization trait. Implementing this lets you express what should happen -/// for your module when the block is ending. -#[impl_for_tuples(30)] -pub trait OnFinalize { - /// The block is being finalized. Implement to have something happen. - fn on_finalize(_n: BlockNumber) {} -} - -/// The block initialization trait. Implementing this lets you express what should happen -/// for your module when the block is beginning (right before the first extrinsic is executed). -#[impl_for_tuples(30)] -pub trait OnInitialize { - /// The block is being initialized. Implement to have something happen. - fn on_initialize(_n: BlockNumber) {} -} - -/// Off-chain computation trait. -/// -/// Implementing this trait on a module allows you to perform long-running tasks -/// that make validators generate extrinsics (either transactions or inherents) -/// with the results of those long-running computations. -/// -/// NOTE: This function runs off-chain, so it can access the block state, -/// but cannot preform any alterations. -#[impl_for_tuples(30)] -pub trait OffchainWorker { - /// This function is being called on every block. - /// - /// Implement this and use special `extern`s to generate transactions or inherents. - /// Any state alterations are lost and are not persisted. - fn generate_extrinsics(_n: BlockNumber) {} -} - -/// Abstraction around hashing -// Stupid bug in the Rust compiler believes derived -// traits must be fulfilled by all type parameters. -pub trait Hash: 'static + MaybeSerializeDeserialize + Debug + Clone + Eq + PartialEq { - /// The hash type produced. - type Output: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash - + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + Encode + Decode; - - /// The associated hash_db Hasher type. - type Hasher: Hasher; - - /// Produce the hash of some byte-slice. - fn hash(s: &[u8]) -> Self::Output; - - /// Produce the hash of some codec-encodable value. - fn hash_of(s: &S) -> Self::Output { - Encode::using_encoded(s, Self::hash) - } - - /// The ordered Patricia tree root of the given `input`. - fn ordered_trie_root(input: Vec>) -> Self::Output; - - /// The Patricia tree root of the given mapping. - fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output; - - /// Acquire the global storage root. - fn storage_root() -> Self::Output; - - /// Acquire the global storage changes root. - fn storage_changes_root(parent_hash: Self::Output) -> Option; -} - -/// Blake2-256 Hash implementation. -#[derive(PartialEq, Eq, Clone, primitives::RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct BlakeTwo256; - -impl Hash for BlakeTwo256 { - type Output = primitives::H256; - type Hasher = Blake2Hasher; - fn hash(s: &[u8]) -> Self::Output { - runtime_io::blake2_256(s).into() - } - - fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { - runtime_io::blake2_256_trie_root(input) - } - - fn ordered_trie_root(input: Vec>) -> Self::Output { - runtime_io::blake2_256_ordered_trie_root(input) - } - - fn storage_root() -> Self::Output { - runtime_io::storage_root().into() - } - - fn storage_changes_root(parent_hash: Self::Output) -> Option { - runtime_io::storage_changes_root(parent_hash.into()).map(Into::into) - } -} - -/// 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); -} - -impl CheckEqual for primitives::H256 { - #[cfg(feature = "std")] - fn check_equal(&self, other: &Self) { - use primitives::hexdisplay::HexDisplay; - if self != other { - println!( - "Hash: given={}, expected={}", - HexDisplay::from(self.as_fixed_bytes()), - HexDisplay::from(other.as_fixed_bytes()), - ); - } - } - - #[cfg(not(feature = "std"))] - fn check_equal(&self, other: &Self) { - if self != other { - "Hash not equal".print(); - self.as_bytes().print(); - other.as_bytes().print(); - } - } -} - -impl CheckEqual for super::generic::DigestItem where H: Encode { - #[cfg(feature = "std")] - fn check_equal(&self, other: &Self) { - if self != other { - println!("DigestItem: given={:?}, expected={:?}", self, other); - } - } - - #[cfg(not(feature = "std"))] - fn check_equal(&self, other: &Self) { - if self != other { - "DigestItem not equal".print(); - (&Encode::encode(self)[..]).print(); - (&Encode::encode(other)[..]).print(); - } - } -} - -macro_rules! impl_maybe_marker { - ( $( $(#[$doc:meta])+ $trait_name:ident: $($trait_bound:path),+ );+ ) => { - $( - $(#[$doc])+ - #[cfg(feature = "std")] - pub trait $trait_name: $($trait_bound +)+ {} - #[cfg(feature = "std")] - impl $trait_name for T {} - - $(#[$doc])+ - #[cfg(not(feature = "std"))] - pub trait $trait_name {} - #[cfg(not(feature = "std"))] - impl $trait_name for T {} - )+ - } -} - -impl_maybe_marker!( - /// A type that implements Display when in std environment. - MaybeDisplay: Display; - - /// A type that implements Hash when in std environment. - MaybeHash: rstd::hash::Hash; - - /// A type that implements Serialize when in std environment. - MaybeSerialize: Serialize; - - /// A type that implements Serialize, DeserializeOwned and Debug when in std environment. - MaybeSerializeDeserialize: DeserializeOwned, Serialize -); - -/// A type that provides a randomness beacon. -pub trait RandomnessBeacon { - /// Returns 32 bytes of random data. The output will change eventually, but - /// is not guaranteed to be different between any two calls. - /// - /// # Security - /// - /// This MUST NOT be used for gambling, as it can be influenced by a - /// malicious validator in the short term. It MAY be used in many - /// cryptographic protocols, however, so long as one remembers that this - /// (like everything else on-chain) is public. For example, it can be - /// used where a number is needed that cannot have been chosen by an - /// adversary, for purposes such as public-coin zero-knowledge proofs. - fn random() -> [u8; 32]; -} - -/// A type that can be used in runtime structures. -pub trait Member: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static {} -impl Member for T {} - -/// Determine if a `MemberId` is a valid member. -pub trait IsMember { - /// Is the given `MemberId` a valid member? - fn is_member(member_id: &MemberId) -> bool; -} - -/// Something which fulfills the abstract idea of a Substrate header. It has types for a `Number`, -/// a `Hash` and a `Hashing`. It provides access to an `extrinsics_root`, `state_root` and -/// `parent_hash`, as well as a `digest` and a block `number`. -/// -/// You can also create a `new` one from those fields. -pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerialize + Debug + 'static { - /// Header number. - type Number: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash - + Copy + MaybeDisplay + SimpleArithmetic + Codec; - /// Header hash type - type Hash: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash - + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; - /// Hashing algorithm - type Hashing: Hash; - - /// Creates new header. - fn new( - number: Self::Number, - extrinsics_root: Self::Hash, - state_root: Self::Hash, - parent_hash: Self::Hash, - digest: Digest, - ) -> Self; - - /// Returns a reference to the header number. - fn number(&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; - /// 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; - /// 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; - /// Sets the parent hash. - fn set_parent_hash(&mut self, hash: Self::Hash); - - /// Returns a reference to the digest. - fn digest(&self) -> &Digest; - /// Get a mutable reference to the digest. - fn digest_mut(&mut self) -> &mut Digest; - - /// Returns the hash of the header. - fn hash(&self) -> Self::Hash { - ::hash_of(self) - } -} - -/// Something which fulfills the abstract idea of a Substrate block. It has types for an -/// `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 + MaybeSerialize + Debug + 'static { - /// Type of extrinsics. - type Extrinsic: Member + Codec + Extrinsic + MaybeSerialize; - /// Header type. - type Header: Header; - /// Block hash type. - type Hash: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash - + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; - - /// Returns a reference to the header. - fn header(&self) -> &Self::Header; - /// 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()) - } - /// Create an encoded block from the given `header` and `extrinsics` without requiring to create an instance. - fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec; -} - -/// Something that acts like an `Extrinsic`. -pub trait Extrinsic: Sized { - /// The function call. - type Call; - - /// The payload we carry for signed extrinsics. - /// - /// Usually it will contain a `Signature` and - /// may include some additional data that are specific to signed - /// extrinsics. - type SignaturePayload; - - /// Is this `Extrinsic` signed? - /// If no information are available about signed/unsigned, `None` should be returned. - fn is_signed(&self) -> Option { None } - - /// Create new instance of the extrinsic. - /// - /// Extrinsics can be split into: - /// 1. Inherents (no signature; created by validators during block production) - /// 2. Unsigned Transactions (no signature; represent "system calls" or other special kinds of calls) - /// 3. Signed Transactions (with signature; a regular transactions with known origin) - fn new(_call: Self::Call, _signed_data: Option) -> Option { None } -} - -/// Extract the hashing type for a block. -pub type HashFor = <::Header as Header>::Hashing; -/// Extract the number type for a block. -pub type NumberFor = <::Header as Header>::Number; -/// Extract the digest type for a block. -pub type DigestFor = Digest<<::Header as Header>::Hash>; -/// Extract the digest item type for a block. -pub type DigestItemFor = DigestItem<<::Header as Header>::Hash>; - -/// 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. -/// Implement for pieces of information that require some additional context `Context` in order to be -/// checked. -pub trait Checkable: Sized { - /// Returned if `check` succeeds. - type Checked; - - /// Check self, given an instance of Context. - fn check(self, c: &Context) -> Result; -} - -/// 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. -/// Implement for pieces of information that don't require additional context in order to be -/// checked. -pub trait BlindCheckable: Sized { - /// Returned if `check` succeeds. - type Checked; - - /// Check self. - fn check(self) -> Result; -} - -// Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`. -impl Checkable for T { - type Checked = ::Checked; - - fn check(self, _c: &Context) -> Result { - BlindCheckable::check(self) - } -} - -/// Result of a module function call; either nothing (functions are only called for "side effects") -/// or an error message. -pub type DispatchResult = result::Result<(), Error>; - -/// A lazy call (module function and argument values) that can be executed via its `dispatch` -/// method. -pub trait Dispatchable { - /// Every function call from 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; - /// The error type returned by this dispatchable. - type Error: Into; - /// Actually dispatch this call and result the result of it. - fn dispatch(self, origin: Self::Origin) -> DispatchResult; -} - -/// Means by which a transaction may be extended. This type embodies both the data and the logic -/// that should be additionally associated with the transaction. It should be plain old data. -pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq { - /// The type which encodes the sender identity. - type AccountId; - - /// The type which encodes the call to be dispatched. - type Call; - - /// Any additional data that will go into the signed payload. This may be created dynamically - /// from the transaction using the `additional_signed` function. - type AdditionalSigned: Encode; - - /// The type that encodes information that can be passed from pre_dispatch to post-dispatch. - type Pre: Default; - - /// Construct any additional data that should be in the signed payload of the transaction. Can - /// also perform any pre-signature-verification checks and return an error if needed. - fn additional_signed(&self) -> Result; - - /// Validate a signed transaction for the transaction queue. - /// - /// This function can be called frequently by the transaction queue, - /// to obtain transaction validity against current state. - /// It should perform all checks that determine a valid transaction, - /// that can pay for it's execution and quickly eliminate ones - /// that are stale or incorrect. - /// - /// Make sure to perform the same checks in `pre_dispatch` function. - fn validate( - &self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: DispatchInfo, - _len: usize, - ) -> TransactionValidity { - Ok(ValidTransaction::default()) - } - - /// Do any pre-flight stuff for a signed transaction. - /// - /// Note this function by default delegates to `validate`, so that - /// all checks performed for the transaction queue are also performed during - /// the dispatch phase (applying the extrinsic). - /// - /// If you ever override this function, you need to make sure to always - /// perform the same validation as in `validate`. - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> Result { - self.validate(who, call, info, len) - .map(|_| Self::Pre::default()) - .map_err(Into::into) - } - - /// Validate an unsigned transaction for the transaction queue. - /// - /// Normally the default implementation is fine since `ValidateUnsigned` - /// is a better way of recognising and validating unsigned transactions. - /// - /// This function can be called frequently by the transaction queue, - /// to obtain transaction validity against current state. - /// It should perform all checks that determine a valid unsigned transaction, - /// and quickly eliminate ones that are stale or incorrect. - /// - /// Make sure to perform the same checks in `pre_dispatch_unsigned` function. - fn validate_unsigned( - _call: &Self::Call, - _info: DispatchInfo, - _len: usize, - ) -> TransactionValidity { - Ok(ValidTransaction::default()) - } - - /// Do any pre-flight stuff for a unsigned transaction. - /// - /// Note this function by default delegates to `validate_unsigned`, so that - /// all checks performed for the transaction queue are also performed during - /// the dispatch phase (applying the extrinsic). - /// - /// If you ever override this function, you need to make sure to always - /// perform the same validation as in `validate_unsigned`. - fn pre_dispatch_unsigned( - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> Result { - Self::validate_unsigned(call, info, len) - .map(|_| Self::Pre::default()) - .map_err(Into::into) - } - - /// Do any post-flight stuff for a transaction. - fn post_dispatch(_pre: Self::Pre, _info: DispatchInfo, _len: usize) { } -} - -/// An error that is returned by a dispatchable function of a module. -pub trait ModuleDispatchError { - /// Convert this error to an `u8`. - /// - /// The `u8` corresponds to the index of the variant in the error enum. - fn as_u8(&self) -> u8; - - /// Convert the error to a `&'static str`. - fn as_str(&self) -> &'static str; -} - -#[impl_for_tuples(1, 12)] -impl SignedExtension for Tuple { - for_tuples!( where #( Tuple: SignedExtension )* ); - type AccountId = AccountId; - type Call = Call; - for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); - for_tuples!( type Pre = ( #( Tuple::Pre ),* ); ); - - fn additional_signed(&self) -> Result { - Ok(for_tuples!( ( #( Tuple.additional_signed()? ),* ) )) - } - - fn validate( - &self, - who: &Self::AccountId, - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> TransactionValidity { - let valid = ValidTransaction::default(); - for_tuples!( #( let valid = valid.combine_with(Tuple.validate(who, call, info, len)?); )* ); - Ok(valid) - } - - fn pre_dispatch(self, who: &Self::AccountId, call: &Self::Call, info: DispatchInfo, len: usize) - -> Result - { - Ok(for_tuples!( ( #( Tuple.pre_dispatch(who, call, info, len)? ),* ) )) - } - - fn validate_unsigned( - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> TransactionValidity { - let valid = ValidTransaction::default(); - for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info, len)?); )* ); - Ok(valid) - } - - fn pre_dispatch_unsigned( - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> Result { - Ok(for_tuples!( ( #( Tuple::pre_dispatch_unsigned(call, info, len)? ),* ) )) - } - - fn post_dispatch( - pre: Self::Pre, - info: DispatchInfo, - len: usize, - ) { - for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info, len); )* ) - } -} - -/// Only for bare bone testing when you don't care about signed extensions at all. -#[cfg(feature = "std")] -impl SignedExtension for () { - type AccountId = u64; - type AdditionalSigned = (); - type Call = (); - type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } -} - -/// 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 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; - - /// Type by which we can dispatch. Restricts the UnsignedValidator type. - type Call; - - /// Returns a reference to the sender if any. - fn sender(&self) -> Option<&Self::AccountId>; - - /// Checks to see if this is a valid *transaction*. It returns information on it if so. - fn validate>( - &self, - info: DispatchInfo, - len: usize, - ) -> TransactionValidity; - - /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, - /// index and sender. - fn apply( - self, - info: DispatchInfo, - len: usize, - ) -> crate::ApplyResult; -} - -/// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. -pub struct ApiRef<'a, T>(T, rstd::marker::PhantomData<&'a ()>); - -impl<'a, T> From for ApiRef<'a, T> { - fn from(api: T) -> Self { - ApiRef(api, Default::default()) - } -} - -impl<'a, T> rstd::ops::Deref for ApiRef<'a, T> { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl<'a, T> rstd::ops::DerefMut for ApiRef<'a, T> { - fn deref_mut(&mut self) -> &mut T { - &mut self.0 - } -} - -/// Something that provides a runtime api. -pub trait ProvideRuntimeApi { - /// The concrete type that provides the api. - type Api; - - /// Returns the runtime api. - /// The returned instance will keep track of modifications to the storage. Any successful - /// call to an api function, will `commit` its changes to an internal buffer. Otherwise, - /// the modifications will be `discarded`. The modifications will not be applied to the - /// storage, even on a `commit`. - fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api>; -} - -/// A marker trait for something that knows the type of the runtime block. -pub trait GetRuntimeBlockType { - /// The `RuntimeBlock` type. - type RuntimeBlock: self::Block; -} - -/// A marker trait for something that knows the type of the node block. -pub trait GetNodeBlockType { - /// The `NodeBlock` type. - type NodeBlock: self::Block; -} - -/// Something that provides information about a runtime api. -pub trait RuntimeApiInfo { - /// The identifier of the runtime api. - const ID: [u8; 8]; - /// The version of the runtime api. - const VERSION: u32; -} - -/// Something that can validate unsigned extrinsics for the transaction pool. -/// -/// Note that any checks done here are only used for determining the validity of -/// the transaction for the transaction pool. -/// During block execution phase one need to perform the same checks anyway, -/// since this function is not being called. -pub trait ValidateUnsigned { - /// The call to validate - type Call; - - /// Return the validity of the call - /// - /// This doesn't execute any side-effects; it merely checks - /// whether the transaction would panic if it were included or not. - /// - /// Changes made to storage should be discarded by caller. - fn validate_unsigned(call: &Self::Call) -> TransactionValidity; -} - -/// Opaque datatype that may be destructured into a series of raw byte slices (which represent -/// individual keys). -pub trait OpaqueKeys: Clone { - /// An iterator over the type IDs of keys that this holds. - type KeyTypeIds: IntoIterator; - - /// Return an iterator over the key-type IDs supported by this set. - fn key_ids() -> Self::KeyTypeIds; - /// Get the raw bytes of key with key-type ID `i`. - fn get_raw(&self, i: super::KeyTypeId) -> &[u8]; - /// Get the decoded key with index `i`. - fn get(&self, i: super::KeyTypeId) -> Option { - T::decode(&mut self.get_raw(i)).ok() - } - /// Verify a proof of ownership for the keys. - fn ownership_proof_is_valid(&self, _proof: &[u8]) -> bool { true } -} - -/// Input that adds infinite number of zero after wrapped input. -struct TrailingZeroInput<'a>(&'a [u8]); - -impl<'a> codec::Input for TrailingZeroInput<'a> { - fn remaining_len(&mut self) -> Result, codec::Error> { - Ok(None) - } - - fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> { - let len_from_inner = into.len().min(self.0.len()); - into[..len_from_inner].copy_from_slice(&self.0[..len_from_inner]); - for i in &mut into[len_from_inner..] { - *i = 0; - } - self.0 = &self.0[len_from_inner..]; - - Ok(()) - } -} - -/// This type can be converted into and possibly from an AccountId (which itself is generic). -pub trait AccountIdConversion: Sized { - /// Convert into an account ID. This is infallible. - fn into_account(&self) -> AccountId { self.into_sub_account(&()) } - - /// Try to convert an account ID into this type. Might not succeed. - fn try_from_account(a: &AccountId) -> Option { - Self::try_from_sub_account::<()>(a).map(|x| x.0) - } - - /// Convert this value amalgamated with the a secondary "sub" value into an account ID. This is - /// infallible. - /// - /// NOTE: The account IDs from this and from `into_account` are *not* guaranteed to be distinct - /// for any given value of `self`, nor are different invocations to this with different types - /// `T`. For example, the following will all encode to the same account ID value: - /// - `self.into_sub_account(0u32)` - /// - `self.into_sub_account(vec![0u8; 0])` - /// - `self.into_account()` - fn into_sub_account(&self, sub: S) -> AccountId; - - /// Try to convert an account ID into this type. Might not succeed. - fn try_from_sub_account(x: &AccountId) -> Option<(Self, S)>; -} - -/// Format is TYPE_ID ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing zeroes to -/// fill AccountId. -impl AccountIdConversion for Id { - fn into_sub_account(&self, sub: S) -> T { - (Id::TYPE_ID, self, sub).using_encoded(|b| - T::decode(&mut TrailingZeroInput(b)) - ).unwrap_or_default() - } - - fn try_from_sub_account(x: &T) -> Option<(Self, S)> { - x.using_encoded(|d| { - if &d[0..4] != Id::TYPE_ID { return None } - let mut cursor = &d[4..]; - let result = Decode::decode(&mut cursor).ok()?; - if cursor.iter().all(|x| *x == 0) { - Some(result) - } else { - None - } - }) - } -} - -/// Calls a given macro a number of times with a set of fixed params and an incrementing numeral. -/// e.g. -/// ```nocompile -/// count!(println ("{}",) foo, bar, baz); -/// // Will result in three `println!`s: "0", "1" and "2". -/// ``` -#[macro_export] -macro_rules! count { - ($f:ident ($($x:tt)*) ) => (); - ($f:ident ($($x:tt)*) $x1:tt) => { $f!($($x)* 0); }; - ($f:ident ($($x:tt)*) $x1:tt, $x2:tt) => { $f!($($x)* 0); $f!($($x)* 1); }; - ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt) => { $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); }; - ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt) => { - $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); - }; - ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt, $x5:tt) => { - $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); $f!($($x)* 4); - }; -} - -/// Implement `OpaqueKeys` for a described struct. -/// Would be much nicer for this to be converted to `derive` code. -/// -/// Every field type must be equivalent implement `as_ref()`, which is expected -/// to hold the standard SCALE-encoded form of that key. This is typically -/// just the bytes of the key. -/// -/// ```rust -/// use sr_primitives::{impl_opaque_keys, KeyTypeId, app_crypto::{sr25519, ed25519}}; -/// use primitives::testing::{SR25519, ED25519}; -/// -/// impl_opaque_keys! { -/// pub struct Keys { -/// #[id(ED25519)] -/// pub ed25519: ed25519::AppPublic, -/// #[id(SR25519)] -/// pub sr25519: sr25519::AppPublic, -/// } -/// } -/// ``` -#[macro_export] -macro_rules! impl_opaque_keys { - ( - pub struct $name:ident { - $( - #[id($key_id:expr)] - pub $field:ident: $type:ty, - )* - } - ) => { - #[derive( - Default, Clone, PartialEq, Eq, - $crate::codec::Encode, - $crate::codec::Decode, - $crate::RuntimeDebug - )] - #[cfg_attr(feature = "std", derive($crate::serde::Serialize, $crate::serde::Deserialize))] - pub struct $name { - $( - pub $field: $type, - )* - } - - impl $name { - /// Generate a set of keys with optionally using the given seed. - /// - /// The generated key pairs are stored in the keystore. - /// - /// Returns the concatenated SCALE encoded public keys. - pub fn generate(seed: Option<&str>) -> $crate::rstd::vec::Vec { - let keys = Self{ - $( - $field: <$type as $crate::app_crypto::RuntimeAppPublic>::generate_pair(seed), - )* - }; - $crate::codec::Encode::encode(&keys) - } - } - - impl $crate::traits::OpaqueKeys for $name { - type KeyTypeIds = $crate::rstd::iter::Cloned< - $crate::rstd::slice::Iter<'static, $crate::KeyTypeId> - >; - - fn key_ids() -> Self::KeyTypeIds { - [ $($key_id),* ].iter().cloned() - } - - fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] { - match i { - $( i if i == $key_id => self.$field.as_ref(), )* - _ => &[], - } - } - } - }; -} - -/// Trait for things which can be printed from the runtime. -pub trait Printable { - /// Print the object. - fn print(&self); -} - -impl Printable for u8 { - fn print(&self) { - (*self as u64).print() - } -} - -impl Printable for u32 { - fn print(&self) { - (*self as u64).print() - } -} - -impl Printable for usize { - fn print(&self) { - (*self as u64).print() - } -} - -impl Printable for u64 { - fn print(&self) { - runtime_io::print_num(*self); - } -} - -impl Printable for &[u8] { - fn print(&self) { - runtime_io::print_hex(self); - } -} - -impl Printable for &str { - fn print(&self) { - runtime_io::print_utf8(self.as_bytes()); - } -} - -#[impl_for_tuples(1, 12)] -impl Printable for Tuple { - fn print(&self) { - for_tuples!( #( Tuple.print(); )* ) - } -} - -#[cfg(test)] -mod tests { - use super::AccountIdConversion; - use crate::codec::{Encode, Decode, Input}; - - mod t { - use primitives::crypto::KeyTypeId; - use app_crypto::{app_crypto, sr25519}; - app_crypto!(sr25519, KeyTypeId(*b"test")); - } - - #[test] - fn app_verify_works() { - use t::*; - use super::AppVerify; - - let s = Signature::default(); - let _ = s.verify(&[0u8; 100][..], &Public::default()); - } - - #[derive(Encode, Decode, Default, PartialEq, Debug)] - struct U32Value(u32); - impl super::TypeId for U32Value { - const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca]; - } - // cafef00d - - #[derive(Encode, Decode, Default, PartialEq, Debug)] - struct U16Value(u16); - impl super::TypeId for U16Value { - const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0]; - } - // f00dcafe - - type AccountId = u64; - - #[test] - fn into_account_should_work() { - let r: AccountId = U32Value::into_account(&U32Value(0xdeadbeef)); - assert_eq!(r, 0x_deadbeef_cafef00d); - } - - #[test] - fn try_from_account_should_work() { - let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64); - assert_eq!(r.unwrap(), U32Value(0xdeadbeef)); - } - - #[test] - fn into_account_with_fill_should_work() { - let r: AccountId = U16Value::into_account(&U16Value(0xc0da)); - assert_eq!(r, 0x_0000_c0da_f00dcafe); - } - - #[test] - fn try_from_account_with_fill_should_work() { - let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64); - assert_eq!(r.unwrap(), U16Value(0xc0da)); - } - - #[test] - fn bad_try_from_account_should_fail() { - let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64); - assert!(r.is_none()); - let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64); - assert!(r.is_none()); - } - - #[test] - fn trailing_zero_should_work() { - let mut t = super::TrailingZeroInput(&[1, 2, 3]); - assert_eq!(t.remaining_len(), Ok(None)); - let mut buffer = [0u8; 2]; - assert_eq!(t.read(&mut buffer), Ok(())); - assert_eq!(t.remaining_len(), Ok(None)); - assert_eq!(buffer, [1, 2]); - assert_eq!(t.read(&mut buffer), Ok(())); - assert_eq!(t.remaining_len(), Ok(None)); - assert_eq!(buffer, [3, 0]); - assert_eq!(t.read(&mut buffer), Ok(())); - assert_eq!(t.remaining_len(), Ok(None)); - assert_eq!(buffer, [0, 0]); - } -} diff --git a/core/sr-primitives/src/weights.rs b/core/sr-primitives/src/weights.rs deleted file mode 100644 index b245f902474ec..0000000000000 --- a/core/sr-primitives/src/weights.rs +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Primitives for transaction weighting. -//! -//! Each dispatch function within `decl_module!` can have an optional `#[weight = $x]` attribute. -//! `$x` can be any type that implements the `ClassifyDispatch` and `WeighData` traits. By -//! default, All transactions are annotated with `#[weight = SimpleDispatchInfo::default()]`. -//! -//! Note that the decl_module macro _cannot_ enforce this and will simply fail if an invalid struct -//! (something that does not implement `Weighable`) is passed in. - -use arithmetic::traits::Bounded; -use crate::RuntimeDebug; - -pub use crate::transaction_validity::TransactionPriority; - -/// Numeric range of a transaction weight. -pub type Weight = u32; - -/// A generalized group of dispatch types. This is only distinguishing normal, user-triggered transactions -/// (`Normal`) and anything beyond which serves a higher purpose to the system (`Operational`). -#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug)] -pub enum DispatchClass { - /// A normal dispatch. - Normal, - /// An operational dispatch. - Operational, -} - -impl Default for DispatchClass { - fn default() -> Self { - DispatchClass::Normal - } -} - -impl From for DispatchClass { - fn from(tx: SimpleDispatchInfo) -> Self { - match tx { - SimpleDispatchInfo::FixedOperational(_) => DispatchClass::Operational, - SimpleDispatchInfo::MaxOperational => DispatchClass::Operational, - SimpleDispatchInfo::FreeOperational => DispatchClass::Operational, - - SimpleDispatchInfo::FixedNormal(_) => DispatchClass::Normal, - SimpleDispatchInfo::MaxNormal => DispatchClass::Normal, - SimpleDispatchInfo::FreeNormal => DispatchClass::Normal, - } - } -} - -/// A bundle of static information collected from the `#[weight = $x]` attributes. -#[cfg_attr(feature = "std", derive(PartialEq, Eq))] -#[derive(Clone, Copy, Default, RuntimeDebug)] -pub struct DispatchInfo { - /// Weight of this transaction. - pub weight: Weight, - /// Class of this transaction. - pub class: DispatchClass, -} - -impl DispatchInfo { - /// Determine if this dispatch should pay the base length-related fee or not. - pub fn pay_length_fee(&self) -> bool { - match self.class { - DispatchClass::Normal => true, - // For now we assume all operational transactions don't pay the length fee. - DispatchClass::Operational => false, - } - } -} - -/// A `Dispatchable` function (aka transaction) that can carry some static information along with it, using the -/// `#[weight]` attribute. -pub trait GetDispatchInfo { - /// Return a `DispatchInfo`, containing relevant information of this dispatch. - /// - /// This is done independently of its encoded size. - fn get_dispatch_info(&self) -> DispatchInfo; -} - -/// Means of weighing some particular kind of data (`T`). -pub trait WeighData { - /// Weigh the data `T` given by `target`. - fn weigh_data(&self, target: T) -> Weight; -} - -/// Means of classifying a dispatchable function. -pub trait ClassifyDispatch { - /// Classify the dispatch function based on input data `target` of type `T`. - fn classify_dispatch(&self, target: T) -> DispatchClass; -} - -/// Default type used with the `#[weight = x]` attribute in a substrate chain. -/// -/// A user may pass in any other type that implements the correct traits. If not, the `Default` -/// implementation of [`SimpleDispatchInfo`] is used. -/// -/// For each generalized group (`Normal` and `Operation`): -/// - A `Fixed` variant means weight fee is charged normally and the weight is the number -/// specified in the inner value of the variant. -/// - A `Free` variant is equal to `::Fixed(0)`. Note that this does not guarantee inclusion. -/// - A `Max` variant is equal to `::Fixed(Weight::max_value())`. -/// -/// Based on the final weight value, based on the above variants: -/// - A _weight-fee_ is deducted. -/// - The block weight is consumed proportionally. -/// -/// As for the generalized groups themselves: -/// - `Normal` variants will be assigned a priority proportional to their weight. They can only -/// consume a portion (1/4) of the maximum block resource limits. -/// - `Operational` variants will be assigned the maximum priority. They can potentially consume -/// the entire block resource limit. -#[derive(Clone, Copy)] -pub enum SimpleDispatchInfo { - /// A normal dispatch with fixed weight. - FixedNormal(Weight), - /// A normal dispatch with the maximum weight. - MaxNormal, - /// A normal dispatch with no weight. - FreeNormal, - /// An operational dispatch with fixed weight. - FixedOperational(Weight), - /// An operational dispatch with the maximum weight. - MaxOperational, - /// An operational dispatch with no weight. - FreeOperational, -} - -impl WeighData for SimpleDispatchInfo { - fn weigh_data(&self, _: T) -> Weight { - match self { - SimpleDispatchInfo::FixedNormal(w) => *w, - SimpleDispatchInfo::MaxNormal => Bounded::max_value(), - SimpleDispatchInfo::FreeNormal => Bounded::min_value(), - - SimpleDispatchInfo::FixedOperational(w) => *w, - SimpleDispatchInfo::MaxOperational => Bounded::max_value(), - SimpleDispatchInfo::FreeOperational => Bounded::min_value(), - } - } -} - -impl ClassifyDispatch for SimpleDispatchInfo { - fn classify_dispatch(&self, _: T) -> DispatchClass { - DispatchClass::from(*self) - } -} - -impl Default for SimpleDispatchInfo { - fn default() -> Self { - // Default weight of all transactions. - SimpleDispatchInfo::FixedNormal(10_000) - } -} diff --git a/core/sr-sandbox/Cargo.toml b/core/sr-sandbox/Cargo.toml deleted file mode 100755 index 87b4e742a0413..0000000000000 --- a/core/sr-sandbox/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "sr-sandbox" -version = "2.0.0" -authors = ["Parity Technologies "] -build = "build.rs" -edition = "2018" - -[build-dependencies] -rustc_version = "0.2.3" - -[dependencies] -wasmi = { version = "0.5.1", optional = true } -primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } - -[dev-dependencies] -wabt = "0.9.2" -assert_matches = "1.3.0" - -[features] -default = ["std"] -std = [ - "wasmi", - "primitives/std", - "rstd/std", - "codec/std", -] -nightly = [] -strict = [] diff --git a/core/sr-sandbox/build.rs b/core/sr-sandbox/build.rs deleted file mode 100755 index 5b5d06b65a253..0000000000000 --- a/core/sr-sandbox/build.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Set a nightly feature - -use rustc_version::{version, version_meta, Channel}; - -fn main() { - // Assert we haven't traveled back in time - assert!(version().unwrap().major >= 1); - - // Set cfg flags depending on release channel - if let Channel::Nightly = version_meta().unwrap().channel { - println!("cargo:rustc-cfg=feature=\"nightly\""); - } -} diff --git a/core/sr-sandbox/src/lib.rs b/core/sr-sandbox/src/lib.rs deleted file mode 100755 index c9f9135661586..0000000000000 --- a/core/sr-sandbox/src/lib.rs +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! This crate provides means to instantiate and execute wasm modules. -//! -//! It works even when the user of this library executes from -//! inside the wasm VM. In this case the same VM is used for execution -//! of both the sandbox owner and the sandboxed module, without compromising security -//! and without the performance penalty of full wasm emulation inside wasm. -//! -//! This is achieved by using bindings to the wasm VM, which are published by the host API. -//! This API is thin and consists of only a handful functions. It contains functions for instantiating -//! modules and executing them, but doesn't contain functions for inspecting the module -//! structure. The user of this library is supposed to read the wasm module. -//! -//! When this crate is used in the `std` environment all these functions are implemented by directly -//! calling the wasm VM. -//! -//! Examples of possible use-cases for this library are not limited to the following: -//! -//! - implementing smart-contract runtimes that use wasm for contract code -//! - executing a wasm substrate runtime inside of a wasm parachain - -#![warn(missing_docs)] -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] - -use rstd::prelude::*; - -pub use primitives::sandbox::{TypedValue, ReturnValue, HostError}; - -mod imp { - #[cfg(feature = "std")] - include!("../with_std.rs"); - - #[cfg(not(feature = "std"))] - include!("../without_std.rs"); -} - -/// Error that can occur while using this crate. -#[derive(primitives::RuntimeDebug)] -pub enum Error { - /// Module is not valid, couldn't be instantiated. - Module, - - /// Access to a memory or table was made with an address or an index which is out of bounds. - /// - /// Note that if wasm module makes an out-of-bounds access then trap will occur. - OutOfBounds, - - /// Failed to invoke the start function or an exported function for some reason. - Execution, -} - -impl From for HostError { - fn from(_e: Error) -> HostError { - HostError - } -} - -/// Function pointer for specifying functions by the -/// supervisor in [`EnvironmentDefinitionBuilder`]. -/// -/// [`EnvironmentDefinitionBuilder`]: struct.EnvironmentDefinitionBuilder.html -pub type HostFuncType = fn(&mut T, &[TypedValue]) -> Result; - -/// Reference to a sandboxed linear memory, that -/// will be used by the guest module. -/// -/// The memory can't be directly accessed by supervisor, but only -/// through designated functions [`get`] and [`set`]. -/// -/// [`get`]: #method.get -/// [`set`]: #method.set -#[derive(Clone)] -pub struct Memory { - inner: imp::Memory, -} - -impl Memory { - /// Construct a new linear memory instance. - /// - /// The memory allocated with initial number of pages specified by `initial`. - /// Minimal possible value for `initial` is 0 and maximum possible is `65536`. - /// (Since maximum addressable memory is 232 = 4GiB = 65536 * 64KiB). - /// - /// It is possible to limit maximum number of pages this memory instance can have by specifying - /// `maximum`. If not specified, this memory instance would be able to allocate up to 4GiB. - /// - /// Allocated memory is always zeroed. - pub fn new(initial: u32, maximum: Option) -> Result { - Ok(Memory { - inner: imp::Memory::new(initial, maximum)?, - }) - } - - /// Read a memory area at the address `ptr` with the size of the provided slice `buf`. - /// - /// Returns `Err` if the range is out-of-bounds. - pub fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error> { - self.inner.get(ptr, buf) - } - - /// Write a memory area at the address `ptr` with contents of the provided slice `buf`. - /// - /// Returns `Err` if the range is out-of-bounds. - pub fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error> { - self.inner.set(ptr, value) - } -} - -/// Struct that can be used for defining an environment for a sandboxed module. -/// -/// The sandboxed module can access only the entities which were defined and passed -/// to the module at the instantiation time. -pub struct EnvironmentDefinitionBuilder { - inner: imp::EnvironmentDefinitionBuilder, -} - -impl EnvironmentDefinitionBuilder { - /// Construct a new `EnvironmentDefinitionBuilder`. - pub fn new() -> EnvironmentDefinitionBuilder { - EnvironmentDefinitionBuilder { - inner: imp::EnvironmentDefinitionBuilder::new(), - } - } - - /// 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 - /// the same function (i.e. with same `module` and `field`) several times. It's up to - /// the user code to check or constrain the types of signatures. - pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) - where - N1: Into>, - N2: Into>, - { - self.inner.add_host_func(module, field, f); - } - - /// Register a memory in this environment definition. - pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) - where - N1: Into>, - N2: Into>, - { - self.inner.add_memory(module, field, mem.inner); - } -} - -/// Sandboxed instance of a wasm module. -/// -/// This instance can be used for invoking exported functions. -pub struct Instance { - inner: imp::Instance, -} - -impl Instance { - /// Instantiate a module with the given [`EnvironmentDefinitionBuilder`]. It will - /// run the `start` function (if it is present in the module) with the given `state`. - /// - /// Returns `Err(Error::Module)` if this module can't be instantiated with the given - /// environment. If execution of `start` function generated a trap, then `Err(Error::Execution)` will - /// be returned. - /// - /// [`EnvironmentDefinitionBuilder`]: struct.EnvironmentDefinitionBuilder.html - pub fn new(code: &[u8], env_def_builder: &EnvironmentDefinitionBuilder, state: &mut T) -> Result, Error> { - Ok(Instance { - inner: imp::Instance::new(code, &env_def_builder.inner, state)?, - }) - } - - /// Invoke an exported function with the given name. - /// - /// # Errors - /// - /// Returns `Err(Error::Execution)` if: - /// - /// - An export function name isn't a proper utf8 byte sequence, - /// - This module doesn't have an exported function with the given name, - /// - If types of the arguments passed to the function doesn't match function signature - /// then trap occurs (as if the exported function was called via call_indirect), - /// - Trap occured at the execution time. - pub fn invoke( - &mut self, - name: &[u8], - args: &[TypedValue], - state: &mut T, - ) -> Result { - self.inner.invoke(name, args, state) - } -} diff --git a/core/sr-sandbox/with_std.rs b/core/sr-sandbox/with_std.rs deleted file mode 100755 index ea7ce818350d0..0000000000000 --- a/core/sr-sandbox/with_std.rs +++ /dev/null @@ -1,481 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use rstd::collections::btree_map::BTreeMap; -use rstd::fmt; - -use wasmi::{ - Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef, ImportResolver, - MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef, - RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, TrapKind -}; -use wasmi::memory_units::Pages; -use super::{Error, TypedValue, ReturnValue, HostFuncType, HostError}; - -#[derive(Clone)] -pub struct Memory { - memref: MemoryRef, -} - -impl Memory { - pub fn new(initial: u32, maximum: Option) -> Result { - Ok(Memory { - memref: MemoryInstance::alloc( - Pages(initial as usize), - maximum.map(|m| Pages(m as usize)), - ).map_err(|_| Error::Module)?, - }) - } - - pub fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error> { - self.memref.get_into(ptr, buf).map_err(|_| Error::OutOfBounds)?; - Ok(()) - } - - pub fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error> { - self.memref.set(ptr, value).map_err(|_| Error::OutOfBounds)?; - Ok(()) - } -} - -struct HostFuncIndex(usize); - -struct DefinedHostFunctions { - funcs: Vec>, -} - -impl Clone for DefinedHostFunctions { - fn clone(&self) -> DefinedHostFunctions { - DefinedHostFunctions { - funcs: self.funcs.clone(), - } - } -} - -impl DefinedHostFunctions { - fn new() -> DefinedHostFunctions { - DefinedHostFunctions { - funcs: Vec::new(), - } - } - - fn define(&mut self, f: HostFuncType) -> HostFuncIndex { - let idx = self.funcs.len(); - self.funcs.push(f); - HostFuncIndex(idx) - } -} - -#[derive(Debug)] -struct DummyHostError; - -impl fmt::Display for DummyHostError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "DummyHostError") - } -} - -impl wasmi::HostError for DummyHostError { -} - -fn from_runtime_value(v: RuntimeValue) -> TypedValue { - match v { - RuntimeValue::I32(v) => TypedValue::I32(v), - RuntimeValue::I64(v) => TypedValue::I64(v), - RuntimeValue::F32(v) => TypedValue::F32(v.to_bits() as i32), - RuntimeValue::F64(v) => TypedValue::F64(v.to_bits() as i64), - } -} - -fn to_runtime_value(v: TypedValue) -> RuntimeValue { - 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), - TypedValue::F32(v_bits) => RuntimeValue::F32(F32::from_bits(v_bits as u32)), - TypedValue::F64(v_bits) => RuntimeValue::F64(F64::from_bits(v_bits as u64)), - } -} - -struct GuestExternals<'a, T: 'a> { - state: &'a mut T, - defined_host_functions: &'a DefinedHostFunctions, -} - -impl<'a, T> Externals for GuestExternals<'a, T> { - fn invoke_index( - &mut self, - index: usize, - args: RuntimeArgs, - ) -> Result, Trap> { - let args = args.as_ref() - .iter() - .cloned() - .map(from_runtime_value) - .collect::>(); - - let result = (self.defined_host_functions.funcs[index])(self.state, &args); - match result { - Ok(value) => Ok(match value { - ReturnValue::Value(v) => Some(to_runtime_value(v)), - ReturnValue::Unit => None, - }), - Err(HostError) => Err(TrapKind::Host(Box::new(DummyHostError)).into()), - } - } -} - -enum ExternVal { - HostFunc(HostFuncIndex), - Memory(Memory), -} - -pub struct EnvironmentDefinitionBuilder { - map: BTreeMap<(Vec, Vec), ExternVal>, - defined_host_functions: DefinedHostFunctions, -} - -impl EnvironmentDefinitionBuilder { - pub fn new() -> EnvironmentDefinitionBuilder { - EnvironmentDefinitionBuilder { - map: BTreeMap::new(), - defined_host_functions: DefinedHostFunctions::new(), - } - } - - pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) - where - N1: Into>, - N2: Into>, - { - let idx = self.defined_host_functions.define(f); - self.map - .insert((module.into(), field.into()), ExternVal::HostFunc(idx)); - } - - pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) - where - N1: Into>, - N2: Into>, - { - self.map - .insert((module.into(), field.into()), ExternVal::Memory(mem)); - } -} - -impl ImportResolver for EnvironmentDefinitionBuilder { - fn resolve_func( - &self, - module_name: &str, - field_name: &str, - signature: &Signature, - ) -> Result { - let key = ( - module_name.as_bytes().to_owned(), - field_name.as_bytes().to_owned(), - ); - let externval = self.map.get(&key).ok_or_else(|| { - wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name)) - })?; - let host_func_idx = match *externval { - ExternVal::HostFunc(ref idx) => idx, - _ => { - return Err(wasmi::Error::Instantiation(format!( - "Export {}:{} is not a host func", - module_name, field_name - ))) - } - }; - Ok(FuncInstance::alloc_host(signature.clone(), host_func_idx.0)) - } - - fn resolve_global( - &self, - _module_name: &str, - _field_name: &str, - _global_type: &GlobalDescriptor, - ) -> Result { - Err(wasmi::Error::Instantiation(format!( - "Importing globals is not supported yet" - ))) - } - - fn resolve_memory( - &self, - module_name: &str, - field_name: &str, - _memory_type: &MemoryDescriptor, - ) -> Result { - let key = ( - module_name.as_bytes().to_owned(), - field_name.as_bytes().to_owned(), - ); - let externval = self.map.get(&key).ok_or_else(|| { - wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name)) - })?; - let memory = match *externval { - ExternVal::Memory(ref m) => m, - _ => { - return Err(wasmi::Error::Instantiation(format!( - "Export {}:{} is not a memory", - module_name, field_name - ))) - } - }; - Ok(memory.memref.clone()) - } - - fn resolve_table( - &self, - _module_name: &str, - _field_name: &str, - _table_type: &TableDescriptor, - ) -> Result { - Err(wasmi::Error::Instantiation(format!( - "Importing tables is not supported yet" - ))) - } -} - -pub struct Instance { - instance: ModuleRef, - defined_host_functions: DefinedHostFunctions, - _marker: ::std::marker::PhantomData, -} - -impl Instance { - pub fn new(code: &[u8], env_def_builder: &EnvironmentDefinitionBuilder, state: &mut T) -> Result, Error> { - let module = Module::from_buffer(code).map_err(|_| Error::Module)?; - let not_started_instance = ModuleInstance::new(&module, env_def_builder) - .map_err(|_| Error::Module)?; - - - let defined_host_functions = env_def_builder.defined_host_functions.clone(); - let instance = { - let mut externals = GuestExternals { - state, - defined_host_functions: &defined_host_functions, - }; - let instance = not_started_instance.run_start(&mut externals).map_err(|_| Error::Execution)?; - instance - }; - - Ok(Instance { - instance, - defined_host_functions, - _marker: ::std::marker::PhantomData::, - }) - } - - pub fn invoke( - &mut self, - name: &[u8], - args: &[TypedValue], - state: &mut T, - ) -> Result { - let args = args.iter().cloned().map(Into::into).collect::>(); - - let name = ::std::str::from_utf8(name).map_err(|_| Error::Execution)?; - let mut externals = GuestExternals { - state, - defined_host_functions: &self.defined_host_functions, - }; - let result = self.instance - .invoke_export(&name, &args, &mut externals); - - match result { - Ok(None) => Ok(ReturnValue::Unit), - Ok(Some(val)) => Ok(ReturnValue::Value(val.into())), - Err(_err) => Err(Error::Execution), - } - } -} - -#[cfg(test)] -mod tests { - use wabt; - use crate::{Error, TypedValue, ReturnValue, HostError, EnvironmentDefinitionBuilder, Instance}; - use assert_matches::assert_matches; - - fn execute_sandboxed(code: &[u8], args: &[TypedValue]) -> Result { - struct State { - counter: u32, - } - - fn env_assert(_e: &mut State, args: &[TypedValue]) -> Result { - if args.len() != 1 { - return Err(HostError); - } - let condition = args[0].as_i32().ok_or_else(|| HostError)?; - if condition != 0 { - Ok(ReturnValue::Unit) - } else { - Err(HostError) - } - } - fn env_inc_counter(e: &mut State, args: &[TypedValue]) -> Result { - if args.len() != 1 { - return Err(HostError); - } - let inc_by = args[0].as_i32().ok_or_else(|| HostError)?; - e.counter += inc_by as u32; - Ok(ReturnValue::Value(TypedValue::I32(e.counter as i32))) - } - /// Function that takes one argument of any type and returns that value. - fn env_polymorphic_id(_e: &mut State, args: &[TypedValue]) -> Result { - if args.len() != 1 { - return Err(HostError); - } - Ok(ReturnValue::Value(args[0])) - } - - let mut state = State { counter: 0 }; - - let mut env_builder = EnvironmentDefinitionBuilder::new(); - env_builder.add_host_func("env", "assert", env_assert); - env_builder.add_host_func("env", "inc_counter", env_inc_counter); - env_builder.add_host_func("env", "polymorphic_id", env_polymorphic_id); - - let mut instance = Instance::new(code, &env_builder, &mut state)?; - let result = instance.invoke(b"call", args, &mut state); - - result.map_err(|_| HostError) - } - - #[test] - fn invoke_args() { - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - - (func (export "call") (param $x i32) (param $y i64) - ;; assert that $x = 0x12345678 - (call $assert - (i32.eq - (get_local $x) - (i32.const 0x12345678) - ) - ) - - (call $assert - (i64.eq - (get_local $y) - (i64.const 0x1234567887654321) - ) - ) - ) - ) - "#).unwrap(); - - let result = execute_sandboxed( - &code, - &[ - TypedValue::I32(0x12345678), - TypedValue::I64(0x1234567887654321), - ] - ); - assert!(result.is_ok()); - } - - #[test] - fn return_value() { - let code = wabt::wat2wasm(r#" - (module - (func (export "call") (param $x i32) (result i32) - (i32.add - (get_local $x) - (i32.const 1) - ) - ) - ) - "#).unwrap(); - - let return_val = execute_sandboxed( - &code, - &[ - TypedValue::I32(0x1336), - ] - ).unwrap(); - assert_eq!(return_val, ReturnValue::Value(TypedValue::I32(0x1337))); - } - - #[test] - fn signatures_dont_matter() { - let code = wabt::wat2wasm(r#" - (module - (import "env" "polymorphic_id" (func $id_i32 (param i32) (result i32))) - (import "env" "polymorphic_id" (func $id_i64 (param i64) (result i64))) - (import "env" "assert" (func $assert (param i32))) - - (func (export "call") - ;; assert that we can actually call the "same" function with different - ;; signatures. - (call $assert - (i32.eq - (call $id_i32 - (i32.const 0x012345678) - ) - (i32.const 0x012345678) - ) - ) - (call $assert - (i64.eq - (call $id_i64 - (i64.const 0x0123456789abcdef) - ) - (i64.const 0x0123456789abcdef) - ) - ) - ) - ) - "#).unwrap(); - - let return_val = execute_sandboxed(&code, &[]).unwrap(); - assert_eq!(return_val, ReturnValue::Unit); - } - - #[test] - fn cant_return_unmatching_type() { - fn env_returns_i32(_e: &mut (), _args: &[TypedValue]) -> Result { - Ok(ReturnValue::Value(TypedValue::I32(42))) - } - - let mut env_builder = EnvironmentDefinitionBuilder::new(); - env_builder.add_host_func("env", "returns_i32", env_returns_i32); - - let code = wabt::wat2wasm(r#" - (module - ;; It's actually returns i32, but imported as if it returned i64 - (import "env" "returns_i32" (func $returns_i32 (result i64))) - - (func (export "call") - (drop - (call $returns_i32) - ) - ) - ) - "#).unwrap(); - - // It succeeds since we are able to import functions with types we want. - let mut instance = Instance::new(&code, &env_builder, &mut ()).unwrap(); - - // But this fails since we imported a function that returns i32 as if it returned i64. - assert_matches!( - instance.invoke(b"call", &[], &mut ()), - Err(Error::Execution) - ); - } -} diff --git a/core/sr-sandbox/without_std.rs b/core/sr-sandbox/without_std.rs deleted file mode 100755 index ee5f7697fe71d..0000000000000 --- a/core/sr-sandbox/without_std.rs +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use rstd::prelude::*; -use rstd::{slice, marker, mem, vec}; -use rstd::rc::Rc; -use codec::{Decode, Encode}; -use primitives::sandbox as sandbox_primitives; -use super::{Error, TypedValue, ReturnValue, HostFuncType}; - -mod ffi { - use rstd::mem; - use super::HostFuncType; - - /// Index into the default table that points to a `HostFuncType`. - pub type HostFuncIndex = usize; - - /// Coerce `HostFuncIndex` to a callable host function pointer. - /// - /// # Safety - /// - /// This function should be only called with a `HostFuncIndex` that was previously registered - /// in the environment definition. Typically this should only - /// be called with an argument received in `dispatch_thunk`. - pub unsafe fn coerce_host_index_to_func(idx: HostFuncIndex) -> HostFuncType { - // We need to ensure that sizes of a callable function pointer and host function index is - // indeed equal. - // We can't use `static_assertions` create because it makes compiler panic, fallback to runtime assert. - // const_assert!(mem::size_of::() == mem::size_of::>(),); - assert!(mem::size_of::() == mem::size_of::>()); - mem::transmute::>(idx) - } - - extern "C" { - pub fn ext_sandbox_instantiate( - dispatch_thunk: extern "C" fn( - serialized_args_ptr: *const u8, - serialized_args_len: usize, - state: usize, - f: HostFuncIndex, - ) -> u64, - wasm_ptr: *const u8, - wasm_len: usize, - imports_ptr: *const u8, - imports_len: usize, - state: usize, - ) -> u32; - pub fn ext_sandbox_invoke( - instance_idx: u32, - export_ptr: *const u8, - export_len: usize, - args_ptr: *const u8, - args_len: usize, - return_val_ptr: *mut u8, - return_val_len: usize, - state: usize, - ) -> u32; - pub fn ext_sandbox_memory_new(initial: u32, maximum: u32) -> u32; - pub fn ext_sandbox_memory_get( - memory_idx: u32, - offset: u32, - buf_ptr: *mut u8, - buf_len: usize, - ) -> u32; - pub fn ext_sandbox_memory_set( - memory_idx: u32, - offset: u32, - val_ptr: *const u8, - val_len: usize, - ) -> u32; - pub fn ext_sandbox_memory_teardown( - memory_idx: u32, - ); - pub fn ext_sandbox_instance_teardown( - instance_idx: u32, - ); - } -} - -struct MemoryHandle { - memory_idx: u32, -} - -impl Drop for MemoryHandle { - fn drop(&mut self) { - unsafe { - ffi::ext_sandbox_memory_teardown(self.memory_idx); - } - } -} - -#[derive(Clone)] -pub struct Memory { - // Handle to memory instance is wrapped to add reference-counting semantics - // to `Memory`. - handle: Rc, -} - -impl Memory { - pub fn new(initial: u32, maximum: Option) -> Result { - let result = unsafe { - let maximum = if let Some(maximum) = maximum { - maximum - } else { - sandbox_primitives::MEM_UNLIMITED - }; - ffi::ext_sandbox_memory_new(initial, maximum) - }; - match result { - sandbox_primitives::ERR_MODULE => Err(Error::Module), - memory_idx => Ok(Memory { - handle: Rc::new(MemoryHandle { memory_idx, }), - }), - } - } - - pub fn get(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> { - let result = unsafe { ffi::ext_sandbox_memory_get(self.handle.memory_idx, offset, buf.as_mut_ptr(), buf.len()) }; - match result { - sandbox_primitives::ERR_OK => Ok(()), - sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds), - _ => unreachable!(), - } - } - - pub fn set(&self, offset: u32, val: &[u8]) -> Result<(), Error> { - let result = unsafe { ffi::ext_sandbox_memory_set(self.handle.memory_idx, offset, val.as_ptr(), val.len()) }; - match result { - sandbox_primitives::ERR_OK => Ok(()), - sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds), - _ => unreachable!(), - } - } -} - -pub struct EnvironmentDefinitionBuilder { - env_def: sandbox_primitives::EnvironmentDefinition, - retained_memories: Vec, - _marker: marker::PhantomData, -} - -impl EnvironmentDefinitionBuilder { - pub fn new() -> EnvironmentDefinitionBuilder { - EnvironmentDefinitionBuilder { - env_def: sandbox_primitives::EnvironmentDefinition { - entries: Vec::new(), - }, - retained_memories: Vec::new(), - _marker: marker::PhantomData::, - } - } - - fn add_entry( - &mut self, - module: N1, - field: N2, - extern_entity: sandbox_primitives::ExternEntity, - ) where - N1: Into>, - N2: Into>, - { - let entry = sandbox_primitives::Entry { - module_name: module.into(), - field_name: field.into(), - entity: extern_entity, - }; - self.env_def.entries.push(entry); - } - - pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) - where - N1: Into>, - N2: Into>, - { - let f = sandbox_primitives::ExternEntity::Function(f as u32); - self.add_entry(module, field, f); - } - - pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) - where - N1: Into>, - N2: Into>, - { - // We need to retain memory to keep it alive while the EnvironmentDefinitionBuilder alive. - self.retained_memories.push(mem.clone()); - - let mem = sandbox_primitives::ExternEntity::Memory(mem.handle.memory_idx as u32); - self.add_entry(module, field, mem); - } -} - -pub struct Instance { - instance_idx: u32, - _retained_memories: Vec, - _marker: marker::PhantomData, -} - -/// The primary responsibility of this thunk is to deserialize arguments and -/// call the original function, specified by the index. -extern "C" fn dispatch_thunk( - serialized_args_ptr: *const u8, - serialized_args_len: usize, - state: usize, - f: ffi::HostFuncIndex, -) -> u64 { - let serialized_args = unsafe { - if serialized_args_len == 0 { - &[] - } else { - slice::from_raw_parts(serialized_args_ptr, serialized_args_len) - } - }; - let args = Vec::::decode(&mut &serialized_args[..]).expect( - "serialized args should be provided by the runtime; - correctly serialized data should be deserializable; - qed", - ); - - unsafe { - // This should be safe since `coerce_host_index_to_func` is called with an argument - // received in an `dispatch_thunk` implementation, so `f` should point - // on a valid host function. - let f = ffi::coerce_host_index_to_func(f); - - // This should be safe since mutable reference to T is passed upon the invocation. - let state = &mut *(state as *mut T); - - // Pass control flow to the designated function. - let result = f(state, &args).encode(); - - // Leak the result vector and return the pointer to return data. - let result_ptr = result.as_ptr() as u64; - let result_len = result.len() as u64; - mem::forget(result); - - (result_ptr << 32) | result_len - } -} - -impl Instance { - pub fn new(code: &[u8], env_def_builder: &EnvironmentDefinitionBuilder, state: &mut T) -> Result, Error> { - let serialized_env_def: Vec = env_def_builder.env_def.encode(); - let result = unsafe { - // It's very important to instantiate thunk with the right type. - let dispatch_thunk = dispatch_thunk::; - - ffi::ext_sandbox_instantiate( - dispatch_thunk, - code.as_ptr(), - code.len(), - serialized_env_def.as_ptr(), - serialized_env_def.len(), - state as *const T as usize, - ) - }; - let instance_idx = match result { - sandbox_primitives::ERR_MODULE => return Err(Error::Module), - sandbox_primitives::ERR_EXECUTION => return Err(Error::Execution), - instance_idx => instance_idx, - }; - // We need to retain memories to keep them alive while the Instance is alive. - let retained_memories = env_def_builder.retained_memories.clone(); - Ok(Instance { - instance_idx, - _retained_memories: retained_memories, - _marker: marker::PhantomData::, - }) - } - - pub fn invoke( - &mut self, - name: &[u8], - args: &[TypedValue], - state: &mut T, - ) -> Result { - let serialized_args = args.to_vec().encode(); - let mut return_val = vec![0u8; sandbox_primitives::ReturnValue::ENCODED_MAX_SIZE]; - - let result = unsafe { - ffi::ext_sandbox_invoke( - self.instance_idx, - name.as_ptr(), - name.len(), - serialized_args.as_ptr(), - serialized_args.len(), - return_val.as_mut_ptr(), - return_val.len(), - state as *const T as usize, - ) - }; - match result { - sandbox_primitives::ERR_OK => { - let return_val = sandbox_primitives::ReturnValue::decode(&mut &return_val[..]) - .map_err(|_| Error::Execution)?; - Ok(return_val) - } - sandbox_primitives::ERR_EXECUTION => Err(Error::Execution), - _ => unreachable!(), - } - } -} - -impl Drop for Instance { - fn drop(&mut self) { - unsafe { - ffi::ext_sandbox_instance_teardown(self.instance_idx); - } - } -} diff --git a/core/sr-staking-primitives/Cargo.toml b/core/sr-staking-primitives/Cargo.toml deleted file mode 100644 index 25e8f4ccf1529..0000000000000 --- a/core/sr-staking-primitives/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "sr-staking-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sr-primitives = { path = "../sr-primitives", default-features = false } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } - -[features] -default = ["std"] -std = [ - "codec/std", - "sr-primitives/std", - "rstd/std", -] diff --git a/core/sr-staking-primitives/src/lib.rs b/core/sr-staking-primitives/src/lib.rs deleted file mode 100644 index 182307cb4712f..0000000000000 --- a/core/sr-staking-primitives/src/lib.rs +++ /dev/null @@ -1,23 +0,0 @@ - -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -#![cfg_attr(not(feature = "std"), no_std)] - -//! A crate which contains primitives that are useful for implementation that uses staking -//! approaches in general. Definitions related to sessions, slashing, etc go here. - -pub mod offence; - -/// Simple index type with which we can count sessions. -pub type SessionIndex = u32; diff --git a/core/sr-std/Cargo.toml b/core/sr-std/Cargo.toml deleted file mode 100644 index 2a8b7d37ca272..0000000000000 --- a/core/sr-std/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "sr-std" -version = "2.0.0" -authors = ["Parity Technologies "] -build = "build.rs" -edition = "2018" - -[build-dependencies] -rustc_version = "0.2.3" - -[features] -default = ["std"] -std = [] -nightly = [] -strict = [] -no_global_allocator = [] diff --git a/core/sr-std/build.rs b/core/sr-std/build.rs deleted file mode 100644 index af9c91db877dd..0000000000000 --- a/core/sr-std/build.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Set a nightly feature - -use rustc_version::{version, version_meta, Channel}; - -fn main() { - // Assert we haven't traveled back in time - assert!(version().unwrap().major >= 1); - - // Set cfg flags depending on release channel - if let Channel::Nightly = version_meta().unwrap().channel { - println!("cargo:rustc-cfg=feature=\"nightly\""); - } -} diff --git a/core/sr-std/src/lib.rs b/core/sr-std/src/lib.rs deleted file mode 100644 index f369d3908ba83..0000000000000 --- a/core/sr-std/src/lib.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Lowest-abstraction level for the Substrate runtime: just exports useful primitives from std -//! or core/alloc to be used with any code that depends on the runtime. - -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] - -#![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.")] - -#[macro_export] -macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) -} - -/// Feature gate some code that should only be run when `std` feature is enabled. -/// -/// # Example -/// -/// ``` -/// use sr_std::if_std; -/// -/// if_std! { -/// // This code is only being compiled and executed when the `std` feature is enabled. -/// println!("Hello native world"); -/// } -/// ``` -#[cfg(feature = "std")] -#[macro_export] -macro_rules! if_std { - ( $( $code:tt )* ) => { - $( $code )* - } -} - -#[cfg(not(feature = "std"))] -#[macro_export] -macro_rules! if_std { - ( $( $code:tt )* ) => {} -} - -#[cfg(feature = "std")] -include!("../with_std.rs"); - -#[cfg(not(feature = "std"))] -include!("../without_std.rs"); - -/// Prelude of common useful imports. -/// -/// This should include only things which are in the normal std prelude. -pub mod prelude { - pub use crate::vec::Vec; - pub use crate::boxed::Box; - pub use crate::cmp::{Eq, PartialEq, Reverse}; - 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 deleted file mode 100644 index 0d5ee04ed51ab..0000000000000 --- a/core/sr-std/with_std.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -pub use std::borrow; -pub use std::boxed; -pub use std::cell; -pub use std::clone; -pub use std::cmp; -pub use std::convert; -pub use std::default; -pub use std::fmt; -pub use std::hash; -pub use std::iter; -pub use std::marker; -pub use std::mem; -pub use std::num; -pub use std::ops; -pub use std::ptr; -pub use std::rc; -pub use std::result; -pub use std::slice; -pub use std::str; -pub use std::vec; - -pub mod collections { - pub use std::collections::btree_map; - pub use std::collections::btree_set; - pub use std::collections::vec_deque; -} diff --git a/core/sr-std/without_std.rs b/core/sr-std/without_std.rs deleted file mode 100755 index 9762c74367198..0000000000000 --- a/core/sr-std/without_std.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#[doc(hidden)] -pub extern crate alloc; - -extern "C" { - fn ext_malloc(size: u32) -> *mut u8; - fn ext_free(ptr: *mut u8); -} - -/// Wasm allocator -pub struct WasmAllocator; - -#[cfg(not(feature = "no_global_allocator"))] -#[global_allocator] -static ALLOCATOR: WasmAllocator = WasmAllocator; - -mod __impl { - use core::alloc::{GlobalAlloc, Layout}; - - use super::WasmAllocator; - - unsafe impl GlobalAlloc for WasmAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - super::ext_malloc(layout.size() as u32) as *mut u8 - } - - unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - super::ext_free(ptr as *mut u8) - } - } -} - -pub use alloc::boxed; -pub use alloc::rc; -pub use alloc::vec; -pub use core::cell; -pub use core::clone; -pub use core::cmp; -pub use core::convert; -pub use core::default; -pub use core::fmt; -pub use core::hash; -pub use core::intrinsics; -pub use core::iter; -pub use core::marker; -pub use core::mem; -pub use core::num; -pub use core::ops; -pub use core::ptr; -pub use core::result; -pub use core::slice; -// Allow intepreting vectors of bytes as strings, but not constructing them. -pub use core::str; -// We are trying to avoid certain things here, such as `core::string` -// (if you need `String` you are probably doing something wrong, since -// runtime doesn't require anything human readable). - -pub mod collections { - pub use alloc::collections::btree_map; - pub use alloc::collections::btree_set; - pub use alloc::collections::vec_deque; -} - -pub mod borrow { - pub use core::borrow::*; - pub use alloc::borrow::*; -} diff --git a/core/sr-version/Cargo.toml b/core/sr-version/Cargo.toml deleted file mode 100644 index fcae97b4d2a7a..0000000000000 --- a/core/sr-version/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "sr-version" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -impl-serde = { version = "0.2.1", optional = true } -serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.5", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -sr-primitives = { path = "../sr-primitives", default-features = false } - -[features] -default = ["std"] -std = [ - "impl-serde", - "serde", - "codec/std", - "rstd/std", - "sr-primitives/std", -] diff --git a/core/sr-version/src/lib.rs b/core/sr-version/src/lib.rs deleted file mode 100644 index 24c54a739a2e0..0000000000000 --- a/core/sr-version/src/lib.rs +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Version module for the Substrate runtime; Provides a function that returns the runtime version. - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -#[cfg(feature = "std")] -use std::fmt; -#[cfg(feature = "std")] -use std::collections::HashSet; -#[cfg(feature = "std")] -use sr_primitives::traits::RuntimeApiInfo; - -use codec::Encode; -#[cfg(feature = "std")] -use codec::Decode; -use sr_primitives::RuntimeString; -pub use sr_primitives::create_runtime_str; - -/// The identity of a particular API interface that the runtime might provide. -pub type ApiId = [u8; 8]; - -/// A vector of pairs of `ApiId` and a `u32` for version. For `"std"` builds, this -/// is a `Cow`. -#[cfg(feature = "std")] -pub type ApisVec = ::std::borrow::Cow<'static, [(ApiId, u32)]>; -/// A vector of pairs of `ApiId` and a `u32` for version. For `"no-std"` builds, this -/// is just a reference. -#[cfg(not(feature = "std"))] -pub type ApisVec = &'static [(ApiId, u32)]; - -/// Create a vector of Api declarations. -#[macro_export] -#[cfg(feature = "std")] -macro_rules! create_apis_vec { - ( $y:expr ) => { ::std::borrow::Cow::Borrowed(& $y) } -} -#[macro_export] -#[cfg(not(feature = "std"))] -macro_rules! create_apis_vec { - ( $y:expr ) => { & $y } -} - -/// Runtime version. -/// This should not be thought of as classic Semver (major/minor/tiny). -/// This triplet have different semantics and mis-interpretation could cause problems. -/// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`, -/// absolutely not `impl_version` since they change the semantics of the runtime. -#[derive(Clone, PartialEq, Eq, Encode, Default, sr_primitives::RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Decode))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -pub struct RuntimeVersion { - /// Identifies the different Substrate runtimes. There'll be at least polkadot and node. - /// A different on-chain spec_name to that of the native runtime would normally result - /// in node not attempting to sync or author blocks. - pub spec_name: RuntimeString, - - /// Name of the implementation of the spec. This is of little consequence for the node - /// and serves only to differentiate code of different implementation teams. For this - /// codebase, it will be parity-polkadot. If there were a non-Rust implementation of the - /// Polkadot runtime (e.g. C++), then it would identify itself with an accordingly different - /// `impl_name`. - pub impl_name: RuntimeString, - - /// `authoring_version` is the version of the authorship interface. An authoring node - /// will not attempt to author blocks unless this is equal to its native runtime. - pub authoring_version: u32, - - /// Version of the runtime specification. A full-node will not attempt to use its native - /// runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, - /// `spec_version` and `authoring_version` are the same between Wasm and native. - pub spec_version: u32, - - /// Version of the implementation of the specification. Nodes are free to ignore this; it - /// serves only as an indication that the code is different; as long as the other two versions - /// are the same then while the actual code may be different, it is nonetheless required to - /// do the same thing. - /// Non-consensus-breaking optimizations are about the only changes that could be made which - /// would result in only the `impl_version` changing. - pub impl_version: u32, - - /// List of supported API "features" along with their versions. - #[cfg_attr( - feature = "std", - serde( - serialize_with = "apis_serialize::serialize", - deserialize_with = "apis_serialize::deserialize", - ) - )] - pub apis: ApisVec, -} - -#[cfg(feature = "std")] -impl fmt::Display for RuntimeVersion { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}-{}:{}({}-{})", - self.spec_name, - self.spec_version, - self.authoring_version, - self.impl_name, - self.impl_version - ) - } -} - -#[cfg(feature = "std")] -impl RuntimeVersion { - /// Check if this version matches other version for calling into runtime. - pub fn can_call_with(&self, other: &RuntimeVersion) -> bool { - self.spec_version == other.spec_version && - self.spec_name == other.spec_name && - self.authoring_version == other.authoring_version - } - - /// Check if this version supports a particular API. - pub fn has_api(&self) -> bool { - self.apis.iter().any(|(s, v)| { - 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")] -#[derive(Debug)] -pub struct NativeVersion { - /// Basic runtime version info. - pub runtime_version: RuntimeVersion, - /// Authoring runtimes that this native runtime supports. - pub can_author_with: HashSet, -} - -#[cfg(feature = "std")] -impl NativeVersion { - /// Check if this version matches other version for authoring blocks. - pub fn can_author_with(&self, other: &RuntimeVersion) -> bool { - self.runtime_version.spec_name == other.spec_name && - (self.runtime_version.authoring_version == other.authoring_version || - 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, de, 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) - } - - #[derive(Deserialize)] - struct ApiIdOwned( - #[serde(deserialize_with="deserialize_bytes")] - super::ApiId, - u32, - ); - - pub fn deserialize<'de, D>(deserializer: D) -> Result where - D: de::Deserializer<'de>, - { - struct Visitor; - impl<'de> de::Visitor<'de> for Visitor { - type Value = ApisVec; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a sequence of api id and version tuples") - } - - fn visit_seq(self, mut visitor: V) -> Result where - V: de::SeqAccess<'de>, - { - let mut apis = Vec::new(); - while let Some(value) = visitor.next_element::()? { - apis.push((value.0, value.1)); - } - Ok(apis.into()) - } - } - deserializer.deserialize_seq(Visitor) - } - - pub fn deserialize_bytes<'de, D>(d: D) -> Result where - D: de::Deserializer<'de> - { - let mut arr = [0; 8]; - bytes::deserialize_check_len(d, bytes::ExpectedLen::Exact(&mut arr[..]))?; - Ok(arr) - } -} diff --git a/core/state-db/Cargo.toml b/core/state-db/Cargo.toml deleted file mode 100644 index d271a0e179d6d..0000000000000 --- a/core/state-db/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "substrate-state-db" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -parking_lot = "0.9.0" -log = "0.4.8" -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } - -[dev-dependencies] -env_logger = "0.7.0" diff --git a/core/state-db/src/lib.rs b/core/state-db/src/lib.rs deleted file mode 100644 index e561d9ce9617c..0000000000000 --- a/core/state-db/src/lib.rs +++ /dev/null @@ -1,610 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! State database maintenance. Handles canonicalization and pruning in the database. The input to -//! this module is a `ChangeSet` which is basically a list of key-value pairs (trie nodes) that -//! were added or deleted during block execution. -//! -//! # Canonicalization. -//! Canonicalization window tracks a tree of blocks identified by header hash. The in-memory -//! overlay allows to get any node that was inserted in any of the blocks within the window. -//! The tree is journaled to the backing database and rebuilt on startup. -//! Canonicalization function selects one root from the top of the tree and discards all other roots and -//! their subtrees. -//! -//! # Pruning. -//! See `RefWindow` for pruning algorithm details. `StateDb` prunes on each canonicalization until pruning -//! constraints are satisfied. - -mod noncanonical; -mod pruning; -#[cfg(test)] mod test; - -use std::fmt; -use parking_lot::RwLock; -use codec::Codec; -use std::collections::{HashMap, hash_map::Entry}; -use noncanonical::NonCanonicalOverlay; -use pruning::RefWindow; -use log::trace; - -const PRUNING_MODE: &[u8] = b"mode"; -const PRUNING_MODE_ARCHIVE: &[u8] = b"archive"; -const PRUNING_MODE_ARCHIVE_CANON: &[u8] = b"archive_canonical"; -const PRUNING_MODE_CONSTRAINED: &[u8] = b"constrained"; - -/// Database value type. -pub type DBValue = Vec; - -/// Basic set of requirements for the Block hash and node key types. -pub trait Hash: Send + Sync + Sized + Eq + PartialEq + Clone + Default + fmt::Debug + Codec + std::hash::Hash + 'static {} -impl Hash for T {} - -/// Backend database trait. Read-only. -pub trait MetaDb { - type Error: fmt::Debug; - - /// Get meta value, such as the journal. - fn get_meta(&self, key: &[u8]) -> Result, Self::Error>; -} - -/// Backend database trait. Read-only. -pub trait NodeDb { - type Key: ?Sized; - type Error: fmt::Debug; - - /// Get state trie node. - fn get(&self, key: &Self::Key) -> Result, Self::Error>; -} - -/// Error type. -pub enum Error { - /// Database backend error. - Db(E), - /// `Codec` decoding error. - Decoding(codec::Error), - /// Trying to canonicalize invalid block. - InvalidBlock, - /// Trying to insert block with invalid number. - InvalidBlockNumber, - /// Trying to insert block with unknown parent. - InvalidParent, - /// Invalid pruning mode specified. Contains expected mode. - InvalidPruningMode(String), -} - -/// Pinning error type. -pub enum PinError { - /// Trying to pin invalid block. - InvalidBlock, -} - -impl From for Error { - fn from(x: codec::Error) -> Self { - Error::Decoding(x) - } -} - -impl fmt::Debug for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::Db(e) => e.fmt(f), - Error::Decoding(e) => write!(f, "Error decoding slicable value: {}", e.what()), - Error::InvalidBlock => write!(f, "Trying to canonicalize invalid block"), - Error::InvalidBlockNumber => write!(f, "Trying to insert block with invalid number"), - Error::InvalidParent => write!(f, "Trying to insert block with unknown parent"), - Error::InvalidPruningMode(e) => write!(f, "Expected pruning mode: {}", e), - } - } -} - -/// A set of state node changes. -#[derive(Default, Debug, Clone)] -pub struct ChangeSet { - /// Inserted nodes. - pub inserted: Vec<(H, DBValue)>, - /// Deleted nodes. - pub deleted: Vec, -} - - -/// A set of changes to the backing database. -#[derive(Default, Debug, Clone)] -pub struct CommitSet { - /// State node changes. - pub data: ChangeSet, - /// Metadata changes. - pub meta: ChangeSet>, -} - -/// Pruning constraints. If none are specified pruning is -#[derive(Default, Debug, Clone, Eq, PartialEq)] -pub struct Constraints { - /// Maximum blocks. Defaults to 0 when unspecified, effectively keeping only non-canonical states. - pub max_blocks: Option, - /// Maximum memory in the pruning overlay. - pub max_mem: Option, -} - -/// Pruning mode. -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum PruningMode { - /// Maintain a pruning window. - Constrained(Constraints), - /// No pruning. Canonicalization is a no-op. - ArchiveAll, - /// Canonicalization discards non-canonical nodes. All the canonical nodes are kept in the DB. - ArchiveCanonical, -} - -impl PruningMode { - /// Create a mode that keeps given number of blocks. - pub fn keep_blocks(n: u32) -> PruningMode { - PruningMode::Constrained(Constraints { - max_blocks: Some(n), - max_mem: None, - }) - } - - /// Is this an archive (either ArchiveAll or ArchiveCanonical) pruning mode? - pub fn is_archive(&self) -> bool { - match *self { - PruningMode::ArchiveAll | PruningMode::ArchiveCanonical => true, - PruningMode::Constrained(_) => false - } - } - - /// Is this an archive (either ArchiveAll or ArchiveCanonical) pruning mode? - pub fn id(&self) -> &[u8] { - match self { - PruningMode::ArchiveAll => PRUNING_MODE_ARCHIVE, - PruningMode::ArchiveCanonical => PRUNING_MODE_ARCHIVE_CANON, - PruningMode::Constrained(_) => PRUNING_MODE_CONSTRAINED, - } - } -} - -impl Default for PruningMode { - fn default() -> Self { - PruningMode::keep_blocks(256) - } -} - -fn to_meta_key(suffix: &[u8], data: &S) -> Vec { - let mut buffer = data.encode(); - buffer.extend(suffix); - buffer -} - -struct StateDbSync { - mode: PruningMode, - non_canonical: NonCanonicalOverlay, - pruning: Option>, - pinned: HashMap, -} - -impl StateDbSync { - pub fn new(mode: PruningMode, db: &D) -> Result, Error> { - trace!(target: "state-db", "StateDb settings: {:?}", mode); - - // Check that settings match - Self::check_meta(&mode, db)?; - - let non_canonical: NonCanonicalOverlay = NonCanonicalOverlay::new(db)?; - let pruning: Option> = match mode { - PruningMode::Constrained(Constraints { - max_mem: Some(_), - .. - }) => unimplemented!(), - PruningMode::Constrained(_) => Some(RefWindow::new(db)?), - PruningMode::ArchiveAll | PruningMode::ArchiveCanonical => None, - }; - - Ok(StateDbSync { - mode, - non_canonical, - pruning, - pinned: Default::default(), - }) - } - - fn check_meta(mode: &PruningMode, db: &D) -> Result<(), Error> { - let db_mode = db.get_meta(&to_meta_key(PRUNING_MODE, &())).map_err(Error::Db)?; - trace!(target: "state-db", - "DB pruning mode: {:?}", - db_mode.as_ref().map(|v| std::str::from_utf8(&v)) - ); - match &db_mode { - Some(v) if v.as_slice() == mode.id() => Ok(()), - Some(v) => Err(Error::InvalidPruningMode(String::from_utf8_lossy(v).into())), - None => Ok(()), - } - } - - pub fn insert_block(&mut self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, mut changeset: ChangeSet) -> Result, Error> { - let mut meta = ChangeSet::default(); - if number == 0 { - // Save pruning mode when writing first block. - meta.inserted.push((to_meta_key(PRUNING_MODE, &()), self.mode.id().into())); - } - - match self.mode { - PruningMode::ArchiveAll => { - changeset.deleted.clear(); - // write changes immediately - Ok(CommitSet { - data: changeset, - meta: meta, - }) - }, - PruningMode::Constrained(_) | PruningMode::ArchiveCanonical => { - let commit = self.non_canonical.insert(hash, number, parent_hash, changeset); - commit.map(|mut c| { - c.meta.inserted.extend(meta.inserted); - c - }) - } - } - } - - pub fn canonicalize_block(&mut self, hash: &BlockHash) -> Result, Error> { - let mut commit = CommitSet::default(); - if self.mode == PruningMode::ArchiveAll { - return Ok(commit) - } - match self.non_canonical.canonicalize(&hash, &mut commit) { - Ok(()) => { - if self.mode == PruningMode::ArchiveCanonical { - commit.data.deleted.clear(); - } - } - Err(e) => return Err(e), - }; - if let Some(ref mut pruning) = self.pruning { - pruning.note_canonical(&hash, &mut commit); - } - self.prune(&mut commit); - Ok(commit) - } - - pub fn best_canonical(&self) -> Option { - return self.non_canonical.last_canonicalized_block_number() - } - - 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) { - if let (&mut Some(ref mut pruning), &PruningMode::Constrained(ref constraints)) = (&mut self.pruning, &self.mode) { - loop { - if pruning.window_size() <= constraints.max_blocks.unwrap_or(0) as u64 { - break; - } - - if constraints.max_mem.map_or(false, |m| pruning.mem_used() > m) { - break; - } - - let pinned = &self.pinned; - if pruning.next_hash().map_or(false, |h| pinned.contains_key(&h)) { - break; - } - pruning.prune_one(commit); - } - } - } - - /// Revert all non-canonical blocks with the best block number. - /// Returns a database commit or `None` if not possible. - /// For archive an empty commit set is returned. - pub fn revert_one(&mut self) -> Option> { - match self.mode { - PruningMode::ArchiveAll => { - Some(CommitSet::default()) - }, - PruningMode::ArchiveCanonical | PruningMode::Constrained(_) => { - self.non_canonical.revert_one() - }, - } - } - - pub fn pin(&mut self, hash: &BlockHash) -> Result<(), PinError> { - match self.mode { - PruningMode::ArchiveAll => Ok(()), - PruningMode::ArchiveCanonical | PruningMode::Constrained(_) => { - if self.non_canonical.have_block(hash) || - self.pruning.as_ref().map_or(false, |pruning| pruning.have_block(hash)) - { - let refs = self.pinned.entry(hash.clone()).or_default(); - if *refs == 0 { - trace!(target: "state-db", "Pinned block: {:?}", hash); - self.non_canonical.pin(hash); - } - *refs += 1; - Ok(()) - } else { - Err(PinError::InvalidBlock) - } - } - } - } - - pub fn unpin(&mut self, hash: &BlockHash) { - match self.pinned.entry(hash.clone()) { - Entry::Occupied(mut entry) => { - *entry.get_mut() -= 1; - if *entry.get() == 0 { - trace!(target: "state-db", "Unpinned block: {:?}", hash); - entry.remove(); - self.non_canonical.unpin(hash); - } else { - trace!(target: "state-db", "Releasing reference for {:?}", hash); - } - }, - Entry::Vacant(_) => {}, - } - } - - pub fn get(&self, key: &Key, db: &D) -> Result, Error> - where Key: AsRef - { - if let Some(value) = self.non_canonical.get(key) { - return Ok(Some(value)); - } - db.get(key.as_ref()).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. -/// Can be shared across threads. -pub struct StateDb { - db: RwLock>, -} - -impl StateDb { - /// Creates a new instance. Does not expect any metadata in the database. - pub fn new(mode: PruningMode, db: &D) -> Result, Error> { - Ok(StateDb { - db: RwLock::new(StateDbSync::new(mode, db)?) - }) - } - - /// Add a new non-canonical block. - pub fn insert_block(&self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, changeset: ChangeSet) -> Result, Error> { - self.db.write().insert_block(hash, number, parent_hash, changeset) - } - - /// Finalize a previously inserted block. - pub fn canonicalize_block(&self, hash: &BlockHash) -> Result, Error> { - self.db.write().canonicalize_block(hash) - } - - /// Prevents pruning of specified block and its descendants. - pub fn pin(&self, hash: &BlockHash) -> Result<(), PinError> { - self.db.write().pin(hash) - } - - /// Allows pruning of specified block. - pub fn unpin(&self, hash: &BlockHash) { - self.db.write().unpin(hash) - } - - /// Get a value from non-canonical/pruning overlay or the backing DB. - pub fn get(&self, key: &Key, db: &D) -> Result, Error> - where Key: AsRef - { - self.db.read().get(key, db) - } - - /// Revert all non-canonical blocks with the best block number. - /// Returns a database commit or `None` if not possible. - /// For archive an empty commit set is returned. - pub fn revert_one(&self) -> Option> { - self.db.write().revert_one() - } - - /// Returns last finalized block number. - pub fn best_canonical(&self) -> Option { - return self.db.read().best_canonical() - } - - /// Check if block is pruned away. - 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(); - } -} - -#[cfg(test)] -mod tests { - use std::io; - use primitives::H256; - 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]); - let state_db = StateDb::new(settings, &db).unwrap(); - - db.commit( - &state_db - .insert_block::( - &H256::from_low_u64_be(1), - 1, - &H256::from_low_u64_be(0), - make_changeset(&[1], &[91]), - ) - .unwrap(), - ); - db.commit( - &state_db - .insert_block::( - &H256::from_low_u64_be(21), - 2, - &H256::from_low_u64_be(1), - make_changeset(&[21], &[921, 1]), - ) - .unwrap(), - ); - db.commit( - &state_db - .insert_block::( - &H256::from_low_u64_be(22), - 2, - &H256::from_low_u64_be(1), - make_changeset(&[22], &[922]), - ) - .unwrap(), - ); - db.commit( - &state_db - .insert_block::( - &H256::from_low_u64_be(3), - 3, - &H256::from_low_u64_be(21), - make_changeset(&[3], &[93]), - ) - .unwrap(), - ); - 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::( - &H256::from_low_u64_be(4), - 4, - &H256::from_low_u64_be(3), - make_changeset(&[4], &[94]), - ) - .unwrap(), - ); - 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, 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] - fn canonical_archive_keeps_canonical() { - let (db, _) = make_test_db(PruningMode::ArchiveCanonical); - assert!(db.data_eq(&make_db(&[1, 21, 3, 91, 921, 922, 93, 94]))); - } - - #[test] - fn prune_window_0() { - let (db, _) = make_test_db(PruningMode::Constrained(Constraints { - max_blocks: Some(0), - max_mem: None, - })); - assert!(db.data_eq(&make_db(&[21, 3, 922, 94]))); - } - - #[test] - fn prune_window_1() { - let (db, sdb) = make_test_db(PruningMode::Constrained(Constraints { - max_blocks: Some(1), - max_mem: None, - })); - 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]))); - } - - #[test] - fn prune_window_2() { - let (db, sdb) = make_test_db(PruningMode::Constrained(Constraints { - max_blocks: Some(2), - max_mem: None, - })); - 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]))); - } - - #[test] - fn detects_incompatible_mode() { - let mut db = make_db(&[]); - let state_db = StateDb::new(PruningMode::ArchiveAll, &db).unwrap(); - db.commit( - &state_db - .insert_block::( - &H256::from_low_u64_be(0), - 0, - &H256::from_low_u64_be(0), - make_changeset(&[], &[]), - ) - .unwrap(), - ); - let new_mode = PruningMode::Constrained(Constraints { max_blocks: Some(2), max_mem: None }); - let state_db: Result, _> = StateDb::new(new_mode, &db); - assert!(state_db.is_err()); - } -} diff --git a/core/state-db/src/test.rs b/core/state-db/src/test.rs deleted file mode 100644 index d90c36990612e..0000000000000 --- a/core/state-db/src/test.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utils - -use std::collections::HashMap; -use primitives::H256; -use crate::{DBValue, ChangeSet, CommitSet, MetaDb, NodeDb}; - -#[derive(Default, Debug, Clone, PartialEq, Eq)] -pub struct TestDb { - pub data: HashMap, - pub meta: HashMap, DBValue>, -} - -impl MetaDb for TestDb { - type Error = (); - - fn get_meta(&self, key: &[u8]) -> Result, ()> { - Ok(self.meta.get(key).cloned()) - } -} - -impl NodeDb for TestDb { - type Error = (); - type Key = H256; - - fn get(&self, key: &H256) -> Result, ()> { - Ok(self.data.get(key).cloned()) - } -} - -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); - } - self.meta.extend(commit.meta.inserted.iter().cloned()); - for k in commit.meta.deleted.iter() { - self.meta.remove(k); - } - } - - pub fn data_eq(&self, other: &TestDb) -> bool { - self.data == other.data - } -} - -pub fn make_changeset(inserted: &[u64], deleted: &[u64]) -> ChangeSet { - ChangeSet { - inserted: inserted - .iter() - .map(|v| { - (H256::from_low_u64_be(*v), H256::from_low_u64_be(*v).as_bytes().to_vec()) - }) - .collect(), - deleted: deleted.iter().map(|v| H256::from_low_u64_be(*v)).collect(), - } -} - -pub fn make_commit(inserted: &[u64], deleted: &[u64]) -> CommitSet { - CommitSet { - data: make_changeset(inserted, deleted), - meta: ChangeSet::default(), - } -} - -pub fn make_db(inserted: &[u64]) -> TestDb { - TestDb { - data: inserted - .iter() - .map(|v| { - (H256::from_low_u64_be(*v), H256::from_low_u64_be(*v).as_bytes().to_vec()) - }) - .collect(), - meta: Default::default(), - } -} - diff --git a/core/state-machine/Cargo.toml b/core/state-machine/Cargo.toml deleted file mode 100644 index 7cd8601a3b636..0000000000000 --- a/core/state-machine/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "substrate-state-machine" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Substrate State Machine" -edition = "2018" - -[dependencies] -log = "0.4.8" -parking_lot = "0.9.0" -hash-db = "0.15.2" -trie-db = "0.15.2" -trie-root = "0.15.2" -trie = { package = "substrate-trie", path = "../trie" } -primitives = { package = "substrate-primitives", path = "../primitives" } -panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -num-traits = "0.2.8" -rand = "0.7.2" -externalities = { package = "substrate-externalities", path = "../externalities" } - -[dev-dependencies] -hex-literal = "0.2.1" - -[features] -default = [] diff --git a/core/state-machine/src/backend.rs b/core/state-machine/src/backend.rs deleted file mode 100644 index e2f398ef7ccae..0000000000000 --- a/core/state-machine/src/backend.rs +++ /dev/null @@ -1,515 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! State machine backends. These manage the code and storage of contracts. - -use std::{error, fmt, cmp::Ord, collections::HashMap, marker::PhantomData}; -use log::warn; -use hash_db::Hasher; -use crate::trie_backend::TrieBackend; -use crate::trie_backend_essence::TrieBackendStorage; -use trie::{ - TrieMut, MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration, - trie_types::{TrieDBMut, Layout}, -}; - -/// A state backend is used to read state data and can have changes committed -/// to it. -/// -/// The clone operation (if implemented) should be cheap. -pub trait Backend: std::fmt::Debug { - /// An error type when fetching data is not possible. - type Error: super::Error; - - /// Storage changes to be applied if committing - type Transaction: Consolidate + Default; - - /// Type of trie backend storage. - type TrieBackendStorage: TrieBackendStorage; - - /// Get keyed storage or None if there is nothing associated. - fn storage(&self, key: &[u8]) -> Result>, Self::Error>; - - /// 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>; - - /// Get child keyed storage value hash or None if there is nothing associated. - fn child_storage_hash(&self, storage_key: &[u8], key: &[u8]) -> Result, Self::Error> { - self.child_storage(storage_key, key).map(|v| v.map(|v| H::hash(&v))) - } - - /// true if a key exists in storage. - fn exists_storage(&self, key: &[u8]) -> Result { - Ok(self.storage(key)?.is_some()) - } - - /// true if a key exists in child storage. - fn exists_child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result { - Ok(self.child_storage(storage_key, key)?.is_some()) - } - - /// Retrieve all entries keys of child storage and call `f` for each of those keys. - fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F); - - /// Retrieve all entries keys which start with the given prefix and - /// call `f` for each of those keys. - fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { - self.for_key_values_with_prefix(prefix, |k, _v| f(k)) - } - - /// Retrieve all entries keys and values of which start with the given prefix and - /// call `f` for each of those keys. - fn for_key_values_with_prefix(&self, prefix: &[u8], f: F); - - - /// Retrieve all child entries keys which start with the given prefix and - /// call `f` for each of those keys. - fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F); - - /// Calculate the storage root, with given delta over what is already stored in - /// the backend, and produce a "transaction" that can be used to commit. - /// Does not include child storage updates. - fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) - where - I: IntoIterator, Option>)>, - H::Out: Ord; - - /// Calculate the child storage root, with given delta over what is already stored in - /// the backend, and produce a "transaction" that can be used to commit. The second argument - /// is true if child storage root equals default storage root. - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - H::Out: Ord; - - /// Get all key/value pairs into a Vec. - fn pairs(&self) -> Vec<(Vec, Vec)>; - - /// Get all keys with given prefix - fn keys(&self, prefix: &[u8]) -> Vec> { - let mut all = Vec::new(); - self.for_keys_with_prefix(prefix, |k| all.push(k.to_vec())); - all - } - - /// Get all keys of child storage with given prefix - fn child_keys(&self, child_storage_key: &[u8], prefix: &[u8]) -> Vec> { - let mut all = Vec::new(); - self.for_child_keys_with_prefix(child_storage_key, prefix, |k| all.push(k.to_vec())); - all - } - - /// Try convert into trie backend. - fn as_trie_backend(&mut self) -> Option<&TrieBackend> { - None - } - - /// Calculate the storage root, with given delta over what is already stored - /// in the backend, and produce a "transaction" that can be used to commit. - /// Does include child storage updates. - fn full_storage_root( - &self, - delta: I1, - child_deltas: I2) - -> (H::Out, Self::Transaction) - where - I1: IntoIterator, Option>)>, - I2i: IntoIterator, Option>)>, - I2: IntoIterator, I2i)>, - ::Out: Ord, - { - let mut txs: Self::Transaction = Default::default(); - let mut child_roots: Vec<_> = Default::default(); - // child first - for (storage_key, child_delta) in child_deltas { - let (child_root, empty, child_txs) = - self.child_storage_root(&storage_key[..], child_delta); - txs.consolidate(child_txs); - if empty { - child_roots.push((storage_key, None)); - } else { - child_roots.push((storage_key, Some(child_root))); - } - } - let (root, parent_txs) = self.storage_root( - delta.into_iter().chain(child_roots.into_iter()) - ); - txs.consolidate(parent_txs); - (root, txs) - } -} - -impl<'a, T: Backend, H: Hasher> Backend for &'a T { - type Error = T::Error; - type Transaction = T::Transaction; - type TrieBackendStorage = T::TrieBackendStorage; - - fn storage(&self, key: &[u8]) -> Result>, Self::Error> { - (*self).storage(key) - } - - fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { - (*self).child_storage(storage_key, key) - } - - fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { - (*self).for_keys_in_child_storage(storage_key, f) - } - - fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { - (*self).for_keys_with_prefix(prefix, f) - } - - fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { - (*self).for_child_keys_with_prefix(storage_key, prefix, f) - } - - fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) - where - I: IntoIterator, Option>)>, - H::Out: Ord, - { - (*self).storage_root(delta) - } - - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - H::Out: Ord, - { - (*self).child_storage_root(storage_key, delta) - } - - fn pairs(&self) -> Vec<(Vec, Vec)> { - (*self).pairs() - } - - fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { - (*self).for_key_values_with_prefix(prefix, f); - } -} - -/// Trait that allows consolidate two transactions together. -pub trait Consolidate { - /// Consolidate two transactions into one. - fn consolidate(&mut self, other: Self); -} - -impl Consolidate for () { - fn consolidate(&mut self, _: Self) { - () - } -} - -impl Consolidate for Vec<(Option>, Vec, Option>)> { - fn consolidate(&mut self, mut other: Self) { - self.append(&mut other); - } -} - -impl> Consolidate for trie::GenericMemoryDB { - fn consolidate(&mut self, other: Self) { - trie::GenericMemoryDB::consolidate(self, other) - } -} - -/// Error impossible. -// FIXME: use `!` type when stabilized. https://github.com/rust-lang/rust/issues/35121 -#[derive(Debug)] -pub enum Void {} - -impl fmt::Display for Void { - fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { - match *self {} - } -} - -impl error::Error for Void { - fn description(&self) -> &str { "unreachable error" } -} - -/// In-memory backend. Fully recomputes tries on each commit but useful for -/// tests. -pub struct InMemory { - inner: HashMap>, HashMap, Vec>>, - trie: Option, H>>, - _hasher: PhantomData, -} - -impl std::fmt::Debug for InMemory { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "InMemory ({} values)", self.inner.len()) - } -} - -impl Default for InMemory { - fn default() -> Self { - InMemory { - inner: Default::default(), - trie: None, - _hasher: PhantomData, - } - } -} - -impl Clone for InMemory { - fn clone(&self) -> Self { - InMemory { - inner: self.inner.clone(), - trie: None, - _hasher: PhantomData, - } - } -} - -impl PartialEq for InMemory { - fn eq(&self, other: &Self) -> bool { - self.inner.eq(&other.inner) - } -} - -impl InMemory { - /// Copy the state, with applied updates - pub fn update(&self, changes: >::Transaction) -> Self { - let mut inner: HashMap<_, _> = self.inner.clone(); - for (storage_key, key, val) in changes { - match val { - Some(v) => { inner.entry(storage_key).or_default().insert(key, v); }, - None => { inner.entry(storage_key).or_default().remove(&key); }, - } - } - - inner.into() - } -} - -impl From>, HashMap, Vec>>> for InMemory { - fn from(inner: HashMap>, HashMap, Vec>>) -> Self { - InMemory { - inner: inner, - trie: None, - _hasher: PhantomData, - } - } -} - -impl From<( - HashMap, Vec>, - HashMap, HashMap, Vec>>, -)> for InMemory { - fn from(inners: ( - HashMap, Vec>, - HashMap, HashMap, Vec>>, - )) -> Self { - let mut inner: HashMap>, HashMap, Vec>> - = inners.1.into_iter().map(|(k, v)| (Some(k), v)).collect(); - inner.insert(None, inners.0); - InMemory { - inner: inner, - trie: None, - _hasher: PhantomData, - } - } -} - -impl From, Vec>> for InMemory { - fn from(inner: HashMap, Vec>) -> Self { - let mut expanded = HashMap::new(); - expanded.insert(None, inner); - InMemory { - inner: expanded, - trie: None, - _hasher: PhantomData, - } - } -} - -impl From>, Vec, Option>)>> for InMemory { - fn from(inner: Vec<(Option>, Vec, Option>)>) -> Self { - let mut expanded: HashMap>, HashMap, Vec>> = HashMap::new(); - for (child_key, key, value) in inner { - if let Some(value) = value { - expanded.entry(child_key).or_default().insert(key, value); - } - } - expanded.into() - } -} - -impl InMemory { - /// child storage key iterator - pub fn child_storage_keys(&self) -> impl Iterator { - self.inner.iter().filter_map(|item| item.0.as_ref().map(|v|&v[..])) - } -} - -impl Backend for InMemory { - type Error = Void; - type Transaction = Vec<(Option>, Vec, Option>)>; - type TrieBackendStorage = MemoryDB; - - fn storage(&self, key: &[u8]) -> Result>, Self::Error> { - Ok(self.inner.get(&None).and_then(|map| map.get(key).map(Clone::clone))) - } - - fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { - Ok(self.inner.get(&Some(storage_key.to_vec())).and_then(|map| map.get(key).map(Clone::clone))) - } - - fn exists_storage(&self, key: &[u8]) -> Result { - Ok(self.inner.get(&None).map(|map| map.get(key).is_some()).unwrap_or(false)) - } - - fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { - self.inner.get(&None).map(|map| map.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f)); - } - - fn for_key_values_with_prefix(&self, prefix: &[u8], mut f: F) { - self.inner.get(&None).map(|map| map.iter().filter(|(key, _val)| key.starts_with(prefix)) - .for_each(|(k, v)| f(k, v))); - } - - fn for_keys_in_child_storage(&self, storage_key: &[u8], mut f: F) { - self.inner.get(&Some(storage_key.to_vec())).map(|map| map.keys().for_each(|k| f(&k))); - } - - fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { - self.inner.get(&Some(storage_key.to_vec())) - .map(|map| map.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f)); - } - - fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) - where - I: IntoIterator, Option>)>, - ::Out: Ord, - { - let existing_pairs = self.inner.get(&None) - .into_iter() - .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), Some(v.clone())))); - - let transaction: Vec<_> = delta.into_iter().collect(); - let root = Layout::::trie_root(existing_pairs.chain(transaction.iter().cloned()) - .collect::>() - .into_iter() - .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) - ); - - let full_transaction = transaction.into_iter().map(|(k, v)| (None, k, v)).collect(); - - (root, full_transaction) - } - - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, - H::Out: Ord - { - let storage_key = storage_key.to_vec(); - - let existing_pairs = self.inner.get(&Some(storage_key.clone())) - .into_iter() - .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), Some(v.clone())))); - - let transaction: Vec<_> = delta.into_iter().collect(); - let root = child_trie_root::, _, _, _>( - &storage_key, - existing_pairs.chain(transaction.iter().cloned()) - .collect::>() - .into_iter() - .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) - ); - - let full_transaction = transaction.into_iter().map(|(k, v)| (Some(storage_key.clone()), k, v)).collect(); - - let is_default = root == default_child_trie_root::>(&storage_key); - - (root, is_default, full_transaction) - } - - fn pairs(&self) -> Vec<(Vec, Vec)> { - self.inner.get(&None) - .into_iter() - .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.clone()))) - .collect() - } - - fn keys(&self, prefix: &[u8]) -> Vec> { - self.inner.get(&None) - .into_iter() - .flat_map(|map| map.keys().filter(|k| k.starts_with(prefix)).cloned()) - .collect() - } - - fn child_keys(&self, storage_key: &[u8], prefix: &[u8]) -> Vec> { - self.inner.get(&Some(storage_key.to_vec())) - .into_iter() - .flat_map(|map| map.keys().filter(|k| k.starts_with(prefix)).cloned()) - .collect() - } - - fn as_trie_backend(&mut self)-> Option<&TrieBackend> { - let mut mdb = MemoryDB::default(); - let mut root = None; - let mut new_child_roots = Vec::new(); - let mut root_map = None; - for (storage_key, map) in &self.inner { - if let Some(storage_key) = storage_key.as_ref() { - let ch = insert_into_memory_db::(&mut mdb, map.clone().into_iter())?; - new_child_roots.push((storage_key.clone(), ch.as_ref().into())); - } else { - root_map = Some(map); - } - } - // root handling - if let Some(map) = root_map.take() { - root = Some(insert_into_memory_db::( - &mut mdb, - map.clone().into_iter().chain(new_child_roots.into_iter()) - )?); - } - let root = match root { - Some(root) => root, - None => insert_into_memory_db::(&mut mdb, ::std::iter::empty())?, - }; - self.trie = Some(TrieBackend::new(mdb, root)); - self.trie.as_ref() - } -} - -/// Insert input pairs into memory db. -pub(crate) fn insert_into_memory_db(mdb: &mut MemoryDB, input: I) -> Option - where - H: Hasher, - I: IntoIterator, Vec)>, -{ - let mut root = ::Out::default(); - { - let mut trie = TrieDBMut::::new(mdb, &mut root); - for (key, value) in input { - if let Err(e) = trie.insert(&key, &value) { - warn!(target: "trie", "Failed to write to trie: {}", e); - return None; - } - } - } - - Some(root) -} diff --git a/core/state-machine/src/basic.rs b/core/state-machine/src/basic.rs deleted file mode 100644 index c2d1a0e3950d0..0000000000000 --- a/core/state-machine/src/basic.rs +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Basic implementation for Externalities. - -use std::{collections::HashMap, any::{TypeId, Any}, iter::FromIterator}; -use crate::backend::{Backend, InMemory}; -use hash_db::Hasher; -use trie::{TrieConfiguration, default_child_trie_root}; -use trie::trie_types::Layout; -use primitives::{ - storage::{well_known_keys::is_child_storage_key, ChildStorageKey}, - traits::Externalities, Blake2Hasher, hash::H256, -}; -use log::warn; - -/// Simple HashMap-based Externalities impl. -#[derive(Debug)] -pub struct BasicExternalities { - top: HashMap, Vec>, - children: HashMap, HashMap, Vec>>, -} - -impl BasicExternalities { - /// Create a new instance of `BasicExternalities` - pub fn new( - top: HashMap, Vec>, - children: HashMap, HashMap, Vec>>, - ) -> Self { - BasicExternalities { - top, - children, - } - } - - /// Insert key/value - pub fn insert(&mut self, k: Vec, v: Vec) -> Option> { - self.top.insert(k, v) - } - - /// Consume self and returns inner storages - pub fn into_storages(self) -> ( - HashMap, Vec>, - HashMap, HashMap, Vec>>, - ) { - (self.top, self.children) - } -} - -impl PartialEq for BasicExternalities { - fn eq(&self, other: &BasicExternalities) -> bool { - self.top.eq(&other.top) && self.children.eq(&other.children) - } -} - -impl FromIterator<(Vec, Vec)> for BasicExternalities { - fn from_iter, Vec)>>(iter: I) -> Self { - let mut t = Self::default(); - t.top.extend(iter); - t - } -} - -impl Default for BasicExternalities { - fn default() -> Self { Self::new(Default::default(), Default::default()) } -} - -impl From, Vec>> for BasicExternalities { - fn from(hashmap: HashMap, Vec>) -> Self { - BasicExternalities { - top: hashmap, - children: Default::default(), - } - } -} - -impl Externalities for BasicExternalities { - fn storage(&self, key: &[u8]) -> Option> { - self.top.get(key).cloned() - } - - fn storage_hash(&self, key: &[u8]) -> Option { - self.storage(key).map(|v| Blake2Hasher::hash(&v)) - } - - fn original_storage(&self, key: &[u8]) -> Option> { - self.storage(key) - } - - fn original_storage_hash(&self, key: &[u8]) -> Option { - self.storage_hash(key) - } - - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { - self.children.get(storage_key.as_ref()).and_then(|child| child.get(key)).cloned() - } - - fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { - self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v)) - } - - fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { - self.child_storage_hash(storage_key, key) - } - - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { - Externalities::child_storage(self, storage_key, key) - } - - fn place_storage(&mut self, key: Vec, maybe_value: Option>) { - if is_child_storage_key(&key) { - warn!(target: "trie", "Refuse to set child storage key via main storage"); - return; - } - - match maybe_value { - Some(value) => { self.top.insert(key, value); } - None => { self.top.remove(&key); } - } - } - - fn place_child_storage( - &mut self, - storage_key: ChildStorageKey, - key: Vec, - value: Option>, - ) { - let child_map = self.children.entry(storage_key.into_owned()).or_default(); - if let Some(value) = value { - child_map.insert(key, value); - } else { - child_map.remove(&key); - } - } - - fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { - self.children.remove(storage_key.as_ref()); - } - - fn clear_prefix(&mut self, prefix: &[u8]) { - if is_child_storage_key(prefix) { - warn!( - target: "trie", - "Refuse to clear prefix that is part of child storage key via main storage" - ); - return; - } - - self.top.retain(|key, _| !key.starts_with(prefix)); - } - - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { - if let Some(child) = self.children.get_mut(storage_key.as_ref()) { - child.retain(|key, _| !key.starts_with(prefix)); - } - } - - fn chain_id(&self) -> u64 { 42 } - - fn storage_root(&mut self) -> H256 { - let mut top = self.top.clone(); - let keys: Vec<_> = self.children.keys().map(|k| k.to_vec()).collect(); - // Single child trie implementation currently allows using the same child - // empty root for all child trie. Using null storage key until multiple - // type of child trie support. - let empty_hash = default_child_trie_root::>(&[]); - for storage_key in keys { - let child_root = self.child_storage_root( - ChildStorageKey::from_slice(storage_key.as_slice()) - .expect("Map only feed by valid keys; qed"), - ); - if &empty_hash[..] == &child_root[..] { - top.remove(&storage_key); - } else { - top.insert(storage_key, child_root); - } - } - - Layout::::trie_root(self.top.clone()) - } - - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { - if let Some(child) = self.children.get(storage_key.as_ref()) { - let delta = child.clone().into_iter().map(|(k, v)| (k, Some(v))); - - InMemory::::default().child_storage_root(storage_key.as_ref(), delta).0 - } else { - default_child_trie_root::>(storage_key.as_ref()) - } - } - - fn storage_changes_root(&mut self, _parent: H256) -> Result, ()> { - Ok(None) - } -} - -impl externalities::ExtensionStore for BasicExternalities { - fn extension_by_type_id(&mut self, _: TypeId) -> Option<&mut dyn Any> { - warn!("Extensions are not supported by `BasicExternalities`."); - None - } -} - -#[cfg(test)] -mod tests { - use super::*; - use primitives::{H256, map}; - use primitives::storage::well_known_keys::CODE; - use hex_literal::hex; - - #[test] - fn commit_should_work() { - let mut ext = BasicExternalities::default(); - 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!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa"); - - assert_eq!(ext.storage_root(), H256::from(ROOT)); - } - - #[test] - fn set_and_retrieve_code() { - let mut ext = BasicExternalities::default(); - - let code = vec![1, 2, 3]; - ext.set_storage(CODE.to_vec(), code.clone()); - - assert_eq!(&ext.storage(CODE).unwrap(), &code); - } - - #[test] - fn children_works() { - let child_storage = b":child_storage:default:test".to_vec(); - - let mut ext = BasicExternalities::new( - Default::default(), - map![ - child_storage.clone() => map![ - b"doe".to_vec() => b"reindeer".to_vec() - ] - ] - ); - - let child = || ChildStorageKey::from_vec(child_storage.clone()).unwrap(); - - assert_eq!(ext.child_storage(child(), b"doe"), Some(b"reindeer".to_vec())); - - ext.set_child_storage(child(), b"dog".to_vec(), b"puppy".to_vec()); - assert_eq!(ext.child_storage(child(), b"dog"), Some(b"puppy".to_vec())); - - ext.clear_child_storage(child(), b"dog"); - assert_eq!(ext.child_storage(child(), b"dog"), None); - - ext.kill_child_storage(child()); - assert_eq!(ext.child_storage(child(), b"doe"), None); - } - - #[test] - fn basic_externalities_is_empty() { - // Make sure no values are set by default in `BasicExternalities`. - let (storage, child_storage) = BasicExternalities::new( - Default::default(), - Default::default(), - ).into_storages(); - assert!(storage.is_empty()); - assert!(child_storage.is_empty()); - } -} diff --git a/core/state-machine/src/changes_trie/build.rs b/core/state-machine/src/changes_trie/build.rs deleted file mode 100644 index 10c38a41e2650..0000000000000 --- a/core/state-machine/src/changes_trie/build.rs +++ /dev/null @@ -1,762 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Structures and functions required to build changes trie for given block. - -use std::collections::{BTreeMap, BTreeSet}; -use std::collections::btree_map::Entry; -use codec::Decode; -use hash_db::Hasher; -use num_traits::One; -use crate::backend::Backend; -use crate::overlayed_changes::OverlayedChanges; -use crate::trie_backend_essence::TrieBackendEssence; -use crate::changes_trie::build_iterator::digest_build_iterator; -use crate::changes_trie::input::{InputKey, InputPair, DigestIndex, ExtrinsicIndex}; -use crate::changes_trie::{AnchorBlockId, ConfigurationRange, Storage, BlockNumber}; -use crate::changes_trie::input::ChildIndex; - -/// Prepare input pairs for building a changes trie of given block. -/// -/// Returns Err if storage error has occurred OR if storage haven't returned -/// required data. -pub(crate) fn prepare_input<'a, B, H, Number>( - backend: &'a B, - storage: &'a dyn Storage, - config: ConfigurationRange<'a, Number>, - changes: &'a OverlayedChanges, - parent: &'a AnchorBlockId, -) -> Result<( - impl Iterator> + 'a, - Vec<(ChildIndex, impl Iterator> + 'a)>, - Vec, - ), String> - where - B: Backend, - H: Hasher + 'a, - Number: BlockNumber, -{ - let number = parent.number.clone() + One::one(); - let (extrinsics_input, children_extrinsics_input) = prepare_extrinsics_input( - backend, - &number, - changes, - )?; - let (digest_input, mut children_digest_input, digest_input_blocks) = prepare_digest_input::( - parent, - config, - number, - storage, - )?; - - let mut children_digest = Vec::with_capacity(children_extrinsics_input.len()); - for (child_index, ext_iter) in children_extrinsics_input.into_iter() { - let dig_iter = children_digest_input.remove(&child_index); - children_digest.push(( - child_index, - Some(ext_iter).into_iter().flatten() - .chain(dig_iter.into_iter().flatten()), - )); - } - for (child_index, dig_iter) in children_digest_input.into_iter() { - children_digest.push(( - child_index, - None.into_iter().flatten() - .chain(Some(dig_iter).into_iter().flatten()), - )); - } - - Ok(( - extrinsics_input.chain(digest_input), - children_digest, - digest_input_blocks, - )) -} -/// Prepare ExtrinsicIndex input pairs. -fn prepare_extrinsics_input<'a, B, H, Number>( - backend: &'a B, - block: &Number, - changes: &'a OverlayedChanges, -) -> Result<( - impl Iterator> + 'a, - BTreeMap, impl Iterator> + 'a>, - ), String> - where - B: Backend, - H: Hasher + 'a, - Number: BlockNumber, -{ - - let mut children_keys = BTreeSet::>::new(); - let mut children_result = BTreeMap::new(); - for (storage_key, _) in changes.prospective.children.iter() - .chain(changes.committed.children.iter()) { - children_keys.insert(storage_key.clone()); - } - for storage_key in children_keys { - let child_index = ChildIndex:: { - block: block.clone(), - storage_key: storage_key.clone(), - }; - - let iter = prepare_extrinsics_input_inner(backend, block, changes, Some(storage_key))?; - children_result.insert(child_index, iter); - } - - let top = prepare_extrinsics_input_inner(backend, block, changes, None)?; - - Ok((top, children_result)) -} - -fn prepare_extrinsics_input_inner<'a, B, H, Number>( - backend: &'a B, - block: &Number, - changes: &'a OverlayedChanges, - storage_key: Option>, -) -> Result> + 'a, String> - where - B: Backend, - H: Hasher, - Number: BlockNumber, -{ - let (committed, prospective) = if let Some(sk) = storage_key.as_ref() { - (changes.committed.children.get(sk), changes.prospective.children.get(sk)) - } else { - (Some(&changes.committed.top), Some(&changes.prospective.top)) - }; - committed.iter().flat_map(|c| c.iter()) - .chain(prospective.iter().flat_map(|c| c.iter())) - .filter(|( _, v)| v.extrinsics.is_some()) - .try_fold(BTreeMap::new(), |mut map: BTreeMap<&[u8], (ExtrinsicIndex, Vec)>, (k, v)| { - match map.entry(k) { - Entry::Vacant(entry) => { - // ignore temporary values (values that have null value at the end of operation - // AND are not in storage at the beginning of operation - if let Some(sk) = storage_key.as_ref() { - if !changes.child_storage(sk, k).map(|v| v.is_some()).unwrap_or_default() { - if !backend.exists_child_storage(sk, k).map_err(|e| format!("{}", e))? { - return Ok(map); - } - } - } else { - if !changes.storage(k).map(|v| v.is_some()).unwrap_or_default() { - if !backend.exists_storage(k).map_err(|e| format!("{}", e))? { - return Ok(map); - } - } - }; - - let extrinsics = v.extrinsics.as_ref() - .expect("filtered by filter() call above; qed") - .iter().cloned().collect(); - entry.insert((ExtrinsicIndex { - block: block.clone(), - key: k.to_vec(), - }, extrinsics)); - }, - Entry::Occupied(mut entry) => { - // we do not need to check for temporary values here, because entry is Occupied - // AND we are checking it before insertion - let extrinsics = &mut entry.get_mut().1; - extrinsics.extend( - v.extrinsics.as_ref() - .expect("filtered by filter() call above; qed") - .iter() - .cloned() - ); - extrinsics.sort_unstable(); - }, - } - - Ok(map) - }) - .map(|pairs| pairs.into_iter().map(|(_, (k, v))| InputPair::ExtrinsicIndex(k, v))) -} - - -/// Prepare DigestIndex input pairs. -fn prepare_digest_input<'a, H, Number>( - parent: &'a AnchorBlockId, - config: ConfigurationRange, - block: Number, - storage: &'a dyn Storage, -) -> Result<( - impl Iterator> + 'a, - BTreeMap, impl Iterator> + 'a>, - Vec, - ), String> - where - H: Hasher, - H::Out: 'a, - Number: BlockNumber, -{ - let build_skewed_digest = config.end.as_ref() == Some(&block); - let block_for_digest = if build_skewed_digest { - config.config.next_max_level_digest_range(config.zero.clone(), block.clone()) - .map(|(_, end)| end) - .unwrap_or_else(|| block.clone()) - } else { - block.clone() - }; - - let digest_input_blocks = digest_build_iterator(config, block_for_digest).collect::>(); - digest_input_blocks.clone().into_iter() - .try_fold( - (BTreeMap::new(), BTreeMap::new()), move |(mut map, mut child_map), digest_build_block| { - let extrinsic_prefix = ExtrinsicIndex::key_neutral_prefix(digest_build_block.clone()); - let digest_prefix = DigestIndex::key_neutral_prefix(digest_build_block.clone()); - let child_prefix = ChildIndex::key_neutral_prefix(digest_build_block.clone()); - let trie_root = storage.root(parent, digest_build_block.clone())?; - let trie_root = trie_root.ok_or_else(|| format!("No changes trie root for block {}", digest_build_block.clone()))?; - - let insert_to_map = |map: &mut BTreeMap<_,_>, key: Vec| { - match map.entry(key.clone()) { - Entry::Vacant(entry) => { - entry.insert((DigestIndex { - block: block.clone(), - key, - }, vec![digest_build_block.clone()])); - }, - Entry::Occupied(mut entry) => { - // DigestIndexValue must be sorted. Here we are relying on the fact that digest_build_iterator() - // returns blocks in ascending order => we only need to check for duplicates - // - // is_dup_block could be true when key has been changed in both digest block - // AND other blocks that it covers - let is_dup_block = entry.get().1.last() == Some(&digest_build_block); - if !is_dup_block { - entry.get_mut().1.push(digest_build_block.clone()); - } - }, - } - }; - - // try to get all updated keys from cache - let populated_from_cache = storage.with_cached_changed_keys( - &trie_root, - &mut |changed_keys| { - for (storage_key, changed_keys) in changed_keys { - let map = match storage_key { - Some(storage_key) => child_map - .entry(ChildIndex:: { - block: block.clone(), - storage_key: storage_key.clone(), - }) - .or_default(), - None => &mut map, - }; - for changed_key in changed_keys.iter().cloned() { - insert_to_map(map, changed_key); - } - } - } - ); - if populated_from_cache { - return Ok((map, child_map)); - } - - let mut children_roots = BTreeMap::, _>::new(); - { - let trie_storage = TrieBackendEssence::<_, H>::new( - crate::changes_trie::TrieBackendStorageAdapter(storage), - trie_root, - ); - - trie_storage.for_key_values_with_prefix(&child_prefix, |key, value| - if let Ok(InputKey::ChildIndex::(trie_key)) = Decode::decode(&mut &key[..]) { - if let Ok(value) = >::decode(&mut &value[..]) { - let mut trie_root = ::Out::default(); - trie_root.as_mut().copy_from_slice(&value[..]); - children_roots.insert(trie_key.storage_key, trie_root); - } - }); - - trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key| - if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = Decode::decode(&mut &key[..]) { - insert_to_map(&mut map, trie_key.key); - }); - - trie_storage.for_keys_with_prefix(&digest_prefix, |key| - if let Ok(InputKey::DigestIndex::(trie_key)) = Decode::decode(&mut &key[..]) { - insert_to_map(&mut map, trie_key.key); - }); - } - - for (storage_key, trie_root) in children_roots.into_iter() { - let child_index = ChildIndex:: { - block: block.clone(), - storage_key, - }; - - let mut map = child_map.entry(child_index).or_default(); - let trie_storage = TrieBackendEssence::<_, H>::new( - crate::changes_trie::TrieBackendStorageAdapter(storage), - trie_root, - ); - trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key| - if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = Decode::decode(&mut &key[..]) { - insert_to_map(&mut map, trie_key.key); - }); - - trie_storage.for_keys_with_prefix(&digest_prefix, |key| - if let Ok(InputKey::DigestIndex::(trie_key)) = Decode::decode(&mut &key[..]) { - insert_to_map(&mut map, trie_key.key); - }); - } - Ok((map, child_map)) - }) - .map(|(pairs, child_pairs)| ( - pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v)), - child_pairs.into_iter().map(|(sk, pairs)| - (sk, pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v)))).collect(), - digest_input_blocks, - )) -} - -#[cfg(test)] -mod test { - use codec::Encode; - use primitives::Blake2Hasher; - use primitives::storage::well_known_keys::{EXTRINSIC_INDEX}; - use crate::backend::InMemory; - use crate::changes_trie::{RootsStorage, Configuration, storage::InMemoryStorage}; - use crate::changes_trie::build_cache::{IncompleteCacheAction, IncompleteCachedBuildData}; - use crate::overlayed_changes::{OverlayedValue, OverlayedChangeSet}; - use super::*; - - fn prepare_for_build(zero: u64) -> ( - InMemory, - InMemoryStorage, - OverlayedChanges, - Configuration, - ) { - let config = Configuration { digest_interval: 4, digest_levels: 2 }; - let backend: InMemory<_> = vec![ - (vec![100], vec![255]), - (vec![101], vec![255]), - (vec![102], vec![255]), - (vec![103], vec![255]), - (vec![104], vec![255]), - (vec![105], vec![255]), - ].into_iter().collect::<::std::collections::HashMap<_, _>>().into(); - let child_trie_key1 = b"1".to_vec(); - let child_trie_key2 = b"2".to_vec(); - let storage = InMemoryStorage::with_inputs(vec![ - (zero + 1, vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![100] }, vec![1, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![101] }, vec![0, 2]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![105] }, vec![0, 2, 4]), - ]), - (zero + 2, vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 2, key: vec![102] }, vec![0]), - ]), - (zero + 3, vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 3, key: vec![100] }, vec![0]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 3, key: vec![105] }, vec![1]), - ]), - (zero + 4, vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![103] }, vec![0, 1]), - - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1, zero + 3]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1, zero + 3]), - ]), - (zero + 5, Vec::new()), - (zero + 6, vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 6, key: vec![105] }, vec![2]), - ]), - (zero + 7, Vec::new()), - (zero + 8, vec![ - InputPair::DigestIndex(DigestIndex { block: zero + 8, key: vec![105] }, vec![zero + 6]), - ]), - (zero + 9, Vec::new()), (zero + 10, Vec::new()), (zero + 11, Vec::new()), (zero + 12, Vec::new()), - (zero + 13, Vec::new()), (zero + 14, Vec::new()), (zero + 15, Vec::new()), - ], vec![(child_trie_key1.clone(), vec![ - (zero + 1, vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![100] }, vec![1, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![101] }, vec![0, 2]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![105] }, vec![0, 2, 4]), - ]), - (zero + 2, vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 2, key: vec![102] }, vec![0]), - ]), - (zero + 4, vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 2, key: vec![102] }, vec![0, 3]), - - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), - ]), - ]), - ]); - let changes = OverlayedChanges { - prospective: OverlayedChangeSet { top: vec![ - (vec![100], OverlayedValue { - value: Some(vec![200]), - extrinsics: Some(vec![0, 2].into_iter().collect()) - }), - (vec![103], OverlayedValue { - value: None, - extrinsics: Some(vec![0, 1].into_iter().collect()) - }), - ].into_iter().collect(), - children: vec![ - (child_trie_key1.clone(), vec![ - (vec![100], OverlayedValue { - value: Some(vec![200]), - extrinsics: Some(vec![0, 2].into_iter().collect()) - }) - ].into_iter().collect()), - (child_trie_key2, vec![ - (vec![100], OverlayedValue { - value: Some(vec![200]), - extrinsics: Some(vec![0, 2].into_iter().collect()) - }) - ].into_iter().collect()), - ].into_iter().collect() - }, - committed: OverlayedChangeSet { top: vec![ - (EXTRINSIC_INDEX.to_vec(), OverlayedValue { - value: Some(3u32.encode()), - extrinsics: None, - }), - (vec![100], OverlayedValue { - value: Some(vec![202]), - extrinsics: Some(vec![3].into_iter().collect()) - }), - (vec![101], OverlayedValue { - value: Some(vec![203]), - extrinsics: Some(vec![1].into_iter().collect()) - }), - ].into_iter().collect(), - children: vec![ - (child_trie_key1, vec![ - (vec![100], OverlayedValue { - value: Some(vec![202]), - extrinsics: Some(vec![3].into_iter().collect()) - }) - ].into_iter().collect()), - ].into_iter().collect(), - }, - changes_trie_config: Some(config.clone()), - }; - - (backend, storage, changes, config) - } - - fn configuration_range<'a>(config: &'a Configuration, zero: u64) -> ConfigurationRange<'a, u64> { - ConfigurationRange { - config, - zero, - end: None, - } - } - - #[test] - fn build_changes_trie_nodes_on_non_digest_block() { - fn test_with_zero(zero: u64) { - let (backend, storage, changes, config) = prepare_for_build(zero); - let parent = AnchorBlockId { hash: Default::default(), number: zero + 4 }; - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range(&config, zero), - &changes, - &parent, - ).unwrap(); - assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![100] }, vec![0, 2, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![103] }, vec![0, 1]), - ]); - assert_eq!(changes_trie_nodes.1.into_iter() - .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ - (ChildIndex { block: zero + 5u64, storage_key: b"1".to_vec() }, - vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5u64, key: vec![100] }, vec![0, 2, 3]), - ]), - (ChildIndex { block: zero + 5, storage_key: b"2".to_vec() }, - vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![100] }, vec![0, 2]), - ]), - ]); - - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn build_changes_trie_nodes_on_digest_block_l1() { - fn test_with_zero(zero: u64) { - let (backend, storage, changes, config) = prepare_for_build(zero); - let parent = AnchorBlockId { hash: Default::default(), number: zero + 3 }; - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range(&config, zero), - &changes, - &parent, - ).unwrap(); - assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![103] }, vec![0, 1]), - - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1, zero + 3]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1, zero + 3]), - ]); - assert_eq!(changes_trie_nodes.1.into_iter() - .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ - (ChildIndex { block: zero + 4u64, storage_key: b"1".to_vec() }, - vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4u64, key: vec![100] }, vec![0, 2, 3]), - - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1]), - ]), - (ChildIndex { block: zero + 4, storage_key: b"2".to_vec() }, - vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2]), - ]), - ]); - - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn build_changes_trie_nodes_on_digest_block_l2() { - fn test_with_zero(zero: u64) { - let (backend, storage, changes, config) = prepare_for_build(zero); - let parent = AnchorBlockId { hash: Default::default(), number: zero + 15 }; - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range(&config, zero), - &changes, - &parent, - ).unwrap(); - assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![100] }, vec![0, 2, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![103] }, vec![0, 1]), - - InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![100] }, vec![zero + 4]), - InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![101] }, vec![zero + 4]), - InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![102] }, vec![zero + 4]), - InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![103] }, vec![zero + 4]), - InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![105] }, vec![zero + 4, zero + 8]), - ]); - assert_eq!(changes_trie_nodes.1.into_iter() - .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ - (ChildIndex { block: zero + 16u64, storage_key: b"1".to_vec() }, - vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16u64, key: vec![100] }, vec![0, 2, 3]), - - InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![102] }, vec![zero + 4]), - ]), - (ChildIndex { block: zero + 16, storage_key: b"2".to_vec() }, - vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![100] }, vec![0, 2]), - ]), - ]); - - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn build_changes_trie_nodes_on_skewed_digest_block() { - fn test_with_zero(zero: u64) { - let (backend, storage, changes, config) = prepare_for_build(zero); - let parent = AnchorBlockId { hash: Default::default(), number: zero + 10 }; - - let mut configuration_range = configuration_range(&config, zero); - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range.clone(), - &changes, - &parent, - ).unwrap(); - assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![100] }, vec![0, 2, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![103] }, vec![0, 1]), - ]); - - configuration_range.end = Some(zero + 11); - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range, - &changes, - &parent, - ).unwrap(); - assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![100] }, vec![0, 2, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![103] }, vec![0, 1]), - - InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![100] }, vec![zero + 4]), - InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![101] }, vec![zero + 4]), - InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![102] }, vec![zero + 4]), - InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![103] }, vec![zero + 4]), - InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![105] }, vec![zero + 4, zero + 8]), - ]); - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn build_changes_trie_nodes_ignores_temporary_storage_values() { - fn test_with_zero(zero: u64) { - let (backend, storage, mut changes, config) = prepare_for_build(zero); - - // 110: missing from backend, set to None in overlay - changes.prospective.top.insert(vec![110], OverlayedValue { - value: None, - extrinsics: Some(vec![1].into_iter().collect()) - }); - - let parent = AnchorBlockId { hash: Default::default(), number: zero + 3 }; - let changes_trie_nodes = prepare_input( - &backend, - &storage, - configuration_range(&config, zero), - &changes, - &parent, - ).unwrap(); - assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![103] }, vec![0, 1]), - - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1, zero + 3]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1, zero + 3]), - ]); - assert_eq!(changes_trie_nodes.1.into_iter() - .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ - (ChildIndex { block: zero + 4u64, storage_key: b"1".to_vec() }, - vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4u64, key: vec![100] }, vec![0, 2, 3]), - - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), - InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1]), - ]), - (ChildIndex { block: zero + 4, storage_key: b"2".to_vec() }, - vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2]), - ]), - ]); - - } - - test_with_zero(0); - test_with_zero(16); - test_with_zero(17); - } - - #[test] - fn cache_is_used_when_changes_trie_is_built() { - let (backend, mut storage, changes, _) = prepare_for_build(0); - let config = changes.changes_trie_config.as_ref().unwrap(); - let parent = AnchorBlockId { hash: Default::default(), number: 15 }; - - // override some actual values from storage with values from the cache - // - // top-level storage: - // (keys 100, 101, 103, 105 are now missing from block#4 => they do not appear - // in l2 digest at block 16) - // - // "1" child storage: - // key 102 is now missing from block#4 => it doesn't appear in l2 digest at block 16 - // (keys 103, 104) are now added to block#4 => they appear in l2 digest at block 16 - // - // "2" child storage: - // (keys 105, 106) are now added to block#4 => they appear in l2 digest at block 16 - let trie_root4 = storage.root(&parent, 4).unwrap().unwrap(); - let cached_data4 = IncompleteCacheAction::CacheBuildData(IncompleteCachedBuildData::new()) - .set_digest_input_blocks(vec![1, 2, 3]) - .insert(None, vec![vec![100], vec![102]].into_iter().collect()) - .insert(Some(b"1".to_vec()), vec![vec![103], vec![104]].into_iter().collect()) - .insert(Some(b"2".to_vec()), vec![vec![105], vec![106]].into_iter().collect()) - .complete(4, &trie_root4); - storage.cache_mut().perform(cached_data4); - - let (root_changes_trie_nodes, child_changes_tries_nodes, _) = prepare_input( - &backend, - &storage, - configuration_range(&config, 0), - &changes, - &parent, - ).unwrap(); - assert_eq!(root_changes_trie_nodes.collect::>>(), vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![100] }, vec![0, 2, 3]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![101] }, vec![1]), - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![103] }, vec![0, 1]), - - InputPair::DigestIndex(DigestIndex { block: 16, key: vec![100] }, vec![4]), - InputPair::DigestIndex(DigestIndex { block: 16, key: vec![102] }, vec![4]), - InputPair::DigestIndex(DigestIndex { block: 16, key: vec![105] }, vec![8]), - ]); - - let child_changes_tries_nodes = child_changes_tries_nodes - .into_iter() - .map(|(k, i)| (k, i.collect::>())) - .collect::>(); - assert_eq!( - child_changes_tries_nodes.get(&ChildIndex { block: 16u64, storage_key: b"1".to_vec() }).unwrap(), - &vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16u64, key: vec![100] }, vec![0, 2, 3]), - - InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![103] }, vec![4]), - InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![104] }, vec![4]), - ], - ); - assert_eq!( - child_changes_tries_nodes.get(&ChildIndex { block: 16u64, storage_key: b"2".to_vec() }).unwrap(), - &vec![ - InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16u64, key: vec![100] }, vec![0, 2]), - - InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![105] }, vec![4]), - InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![106] }, vec![4]), - ], - ); - - } -} diff --git a/core/state-machine/src/changes_trie/mod.rs b/core/state-machine/src/changes_trie/mod.rs deleted file mode 100644 index f771fddf61964..0000000000000 --- a/core/state-machine/src/changes_trie/mod.rs +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Changes trie related structures and functions. -//! -//! Changes trie is a trie built of { storage key => extrinsiscs } pairs -//! at the end of each block. For every changed storage key it contains -//! a pair, mapping key to the set of extrinsics where it has been changed. -//! -//! Optionally, every N blocks, additional level1-digest nodes are appended -//! to the changes trie, containing pairs { storage key => blocks }. For every -//! storage key that has been changed in PREVIOUS N-1 blocks (except for genesis -//! block) it contains a pair, mapping this key to the set of blocks where it -//! has been changed. -//! -//! Optionally, every N^digest_level (where digest_level > 1) blocks, additional -//! digest_level digest is created. It is built out of pairs { storage key => digest -//! block }, containing entries for every storage key that has been changed in -//! the last N*digest_level-1 blocks (except for genesis block), mapping these keys -//! to the set of lower-level digest blocks. -//! -//! Changes trie configuration could change within a time. The range of blocks, where -//! configuration has been active, is given by two blocks: zero and end. Zero block is -//! the block where configuration has been set. But the first changes trie that uses -//! this configuration will be built at the block zero+1. If configuration deactivates -//! at some block, this will be the end block of the configuration. It is also the -//! zero block of the next configuration. -//! -//! If configuration has the end block, it also means that 'skewed digest' has/should -//! been built at that block. If this is the block where max-level digest should have -//! been created, than it is simply max-level digest of this configuration. Otherwise, -//! it is the digest that covers all blocks since last max-level digest block was -//! created. -//! -//! Changes trie only contains the top level storage changes. Sub-level changes -//! are propagated through its storage root on the top level storage. - -mod build; -mod build_cache; -mod build_iterator; -mod changes_iterator; -mod input; -mod prune; -mod storage; -mod surface_iterator; - -pub use self::build_cache::{BuildCache, CachedBuildData, CacheAction}; -pub use self::storage::InMemoryStorage; -pub use self::changes_iterator::{ - key_changes, key_changes_proof, - key_changes_proof_check, key_changes_proof_check_with_db, -}; -pub use self::prune::{prune, oldest_non_pruned_trie}; - -use std::collections::{HashMap, HashSet}; -use std::convert::TryInto; -use hash_db::{Hasher, Prefix}; -use crate::backend::Backend; -use num_traits::{One, Zero}; -use codec::{Decode, Encode}; -use primitives; -use crate::changes_trie::build::prepare_input; -use crate::changes_trie::build_cache::{IncompleteCachedBuildData, IncompleteCacheAction}; -use crate::overlayed_changes::OverlayedChanges; -use trie::{MemoryDB, DBValue, TrieMut}; -use trie::trie_types::TrieDBMut; - -/// Changes that are made outside of extrinsics are marked with this index; -pub const NO_EXTRINSIC_INDEX: u32 = 0xffffffff; - -/// Requirements for block number that can be used with changes tries. -pub trait BlockNumber: - Send + Sync + 'static + - ::std::fmt::Display + - Clone + - From + TryInto + One + Zero + - PartialEq + Ord + - ::std::hash::Hash + - ::std::ops::Add + ::std::ops::Sub + - ::std::ops::Mul + ::std::ops::Div + - ::std::ops::Rem + - ::std::ops::AddAssign + - num_traits::CheckedMul + num_traits::CheckedSub + - Decode + Encode -{} - -impl BlockNumber for T where T: - Send + Sync + 'static + - ::std::fmt::Display + - Clone + - From + TryInto + One + Zero + - PartialEq + Ord + - ::std::hash::Hash + - ::std::ops::Add + ::std::ops::Sub + - ::std::ops::Mul + ::std::ops::Div + - ::std::ops::Rem + - ::std::ops::AddAssign + - num_traits::CheckedMul + num_traits::CheckedSub + - Decode + Encode, -{} - -/// Block identifier that could be used to determine fork of this block. -#[derive(Debug)] -pub struct AnchorBlockId { - /// Hash of this block. - pub hash: Hash, - /// Number of this block. - pub number: Number, -} - -/// Changes trie storage. Provides access to trie roots and trie nodes. -pub trait RootsStorage: Send + Sync { - /// Resolve hash of the block into anchor. - fn build_anchor(&self, hash: H::Out) -> Result, String>; - /// Get changes trie root for the block with given number which is an ancestor (or the block - /// itself) of the anchor_block (i.e. anchor_block.number >= block). - fn root(&self, anchor: &AnchorBlockId, block: Number) -> Result, String>; -} - -/// Changes trie storage. Provides access to trie roots and trie nodes. -pub trait Storage: RootsStorage { - /// Casts from self reference to RootsStorage reference. - fn as_roots_storage(&self) -> &dyn RootsStorage; - /// Execute given functor with cached entry for given trie root. - /// Returns true if the functor has been called (cache entry exists) and false otherwise. - fn with_cached_changed_keys( - &self, - root: &H::Out, - functor: &mut dyn FnMut(&HashMap>, HashSet>>), - ) -> bool; - /// Get a trie node. - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String>; -} - -/// Changes trie storage -> trie backend essence adapter. -pub struct TrieBackendStorageAdapter<'a, H: Hasher, Number: BlockNumber>(pub &'a dyn Storage); - -impl<'a, H: Hasher, N: BlockNumber> crate::TrieBackendStorage for TrieBackendStorageAdapter<'a, H, N> { - type Overlay = trie::MemoryDB; - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - self.0.get(key, prefix) - } -} - -/// Changes trie configuration. -pub type Configuration = primitives::ChangesTrieConfiguration; - -/// Blocks range where configuration has been constant. -#[derive(Clone)] -pub struct ConfigurationRange<'a, N> { - /// Active configuration. - pub config: &'a Configuration, - /// Zero block of this configuration. The configuration is active starting from the next block. - pub zero: N, - /// End block of this configuration. It is the last block where configuration has been active. - pub end: Option, -} - -/// Compute the changes trie root and transaction for given block. -/// Returns Err(()) if unknown `parent_hash` has been passed. -/// Returns Ok(None) if there's no data to perform computation. -/// Panics if background storage returns an error OR if insert to MemoryDB fails. -pub fn build_changes_trie<'a, B: Backend, S: Storage, H: Hasher, Number: BlockNumber>( - backend: &B, - storage: Option<&'a S>, - changes: &OverlayedChanges, - parent_hash: H::Out, -) -> Result, H::Out, CacheAction)>, ()> - where - H::Out: Ord + 'static, -{ - let (storage, config) = match (storage, changes.changes_trie_config.as_ref()) { - (Some(storage), Some(config)) => (storage, config), - _ => return Ok(None), - }; - - // FIXME: remove this in https://github.com/paritytech/substrate/pull/3201 - let config = ConfigurationRange { - config, - zero: Zero::zero(), - end: None, - }; - - // build_anchor error should not be considered fatal - let parent = storage.build_anchor(parent_hash).map_err(|_| ())?; - let block = parent.number.clone() + One::one(); - - // storage errors are considered fatal (similar to situations when runtime fetches values from storage) - let (input_pairs, child_input_pairs, digest_input_blocks) = prepare_input::( - backend, - storage, - config.clone(), - changes, - &parent, - ).expect("changes trie: storage access is not allowed to fail within runtime"); - - // prepare cached data - let mut cache_action = prepare_cached_build_data(config, block.clone()); - let needs_changed_keys = cache_action.collects_changed_keys(); - cache_action = cache_action.set_digest_input_blocks(digest_input_blocks); - - let mut mdb = MemoryDB::default(); - let mut child_roots = Vec::with_capacity(child_input_pairs.len()); - for (child_index, input_pairs) in child_input_pairs { - let mut not_empty = false; - let mut root = Default::default(); - { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); - let mut storage_changed_keys = HashSet::new(); - for input_pair in input_pairs { - if needs_changed_keys { - if let Some(key) = input_pair.key() { - storage_changed_keys.insert(key.to_vec()); - } - } - - let (key, value) = input_pair.into(); - not_empty = true; - trie.insert(&key, &value) - .expect("changes trie: insertion to trie is not allowed to fail within runtime"); - } - - cache_action = cache_action.insert( - Some(child_index.storage_key.clone()), - storage_changed_keys, - ); - } - if not_empty { - child_roots.push(input::InputPair::ChildIndex(child_index, root.as_ref().to_vec())); - } - } - let mut root = Default::default(); - { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); - for (key, value) in child_roots.into_iter().map(Into::into) { - trie.insert(&key, &value) - .expect("changes trie: insertion to trie is not allowed to fail within runtime"); - } - - let mut storage_changed_keys = HashSet::new(); - for input_pair in input_pairs { - if needs_changed_keys { - if let Some(key) = input_pair.key() { - storage_changed_keys.insert(key.to_vec()); - } - } - - let (key, value) = input_pair.into(); - trie.insert(&key, &value) - .expect("changes trie: insertion to trie is not allowed to fail within runtime"); - } - cache_action = cache_action.insert( - None, - storage_changed_keys, - ); - } - - let cache_action = cache_action.complete(block, &root); - Ok(Some((mdb, root, cache_action))) -} - -/// Prepare empty cached build data for given block. -fn prepare_cached_build_data( - config: ConfigurationRange, - block: Number, -) -> IncompleteCacheAction { - // when digests are not enabled in configuration, we do not need to cache anything - // because it'll never be used again for building other tries - // => let's clear the cache - if !config.config.is_digest_build_enabled() { - return IncompleteCacheAction::Clear; - } - - // when this is the last block where current configuration is active - // => let's clear the cache - if config.end.as_ref() == Some(&block) { - return IncompleteCacheAction::Clear; - } - - // we do not need to cache anything when top-level digest trie is created, because - // it'll never be used again for building other tries - // => let's clear the cache - match config.config.digest_level_at_block(config.zero.clone(), block) { - Some((digest_level, _, _)) if digest_level == config.config.digest_levels => IncompleteCacheAction::Clear, - _ => IncompleteCacheAction::CacheBuildData(IncompleteCachedBuildData::new()), - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn cache_is_cleared_when_digests_are_disabled() { - let config = Configuration { digest_interval: 0, digest_levels: 0 }; - let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; - assert_eq!(prepare_cached_build_data(config_range, 8u32), IncompleteCacheAction::Clear); - } - - #[test] - fn build_data_is_cached_when_digests_are_enabled() { - let config = Configuration { digest_interval: 8, digest_levels: 2 }; - let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; - assert!(prepare_cached_build_data(config_range.clone(), 4u32).collects_changed_keys()); - assert!(prepare_cached_build_data(config_range.clone(), 7u32).collects_changed_keys()); - assert!(prepare_cached_build_data(config_range, 8u32).collects_changed_keys()); - } - - #[test] - fn cache_is_cleared_when_digests_are_enabled_and_top_level_digest_is_built() { - let config = Configuration { digest_interval: 8, digest_levels: 2 }; - let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; - assert_eq!(prepare_cached_build_data(config_range, 64u32), IncompleteCacheAction::Clear); - } - - #[test] - fn cache_is_cleared_when_end_block_of_configuration_is_built() { - let config = Configuration { digest_interval: 8, digest_levels: 2 }; - let config_range = ConfigurationRange { zero: 0, end: Some(4u32), config: &config }; - assert_eq!(prepare_cached_build_data(config_range.clone(), 4u32), IncompleteCacheAction::Clear); - } -} diff --git a/core/state-machine/src/changes_trie/storage.rs b/core/state-machine/src/changes_trie/storage.rs deleted file mode 100644 index a82477bdc3933..0000000000000 --- a/core/state-machine/src/changes_trie/storage.rs +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Changes trie storage utilities. - -use std::collections::{BTreeMap, HashSet, HashMap}; -use hash_db::{Hasher, Prefix, EMPTY_PREFIX}; -use trie::DBValue; -use trie::MemoryDB; -use parking_lot::RwLock; -use crate::changes_trie::{BuildCache, RootsStorage, Storage, AnchorBlockId, BlockNumber}; -use crate::trie_backend_essence::TrieBackendStorage; - -#[cfg(test)] -use crate::backend::insert_into_memory_db; -#[cfg(test)] -use crate::changes_trie::input::{InputPair, ChildIndex}; - -/// In-memory implementation of changes trie storage. -pub struct InMemoryStorage { - data: RwLock>, - cache: BuildCache, -} - -/// Adapter for using changes trie storage as a TrieBackendEssence' storage. -pub struct TrieBackendAdapter<'a, H: Hasher, Number: BlockNumber> { - storage: &'a dyn Storage, - _hasher: ::std::marker::PhantomData<(H, Number)>, -} - -struct InMemoryStorageData { - roots: BTreeMap, - mdb: MemoryDB, -} - -impl InMemoryStorage { - /// Creates storage from given in-memory database. - pub fn with_db(mdb: MemoryDB) -> Self { - Self { - data: RwLock::new(InMemoryStorageData { - roots: BTreeMap::new(), - mdb, - }), - cache: BuildCache::new(), - } - } - - /// Creates storage with empty database. - pub fn new() -> Self { - Self::with_db(Default::default()) - } - - /// Creates storage with given proof. - pub fn with_proof(proof: Vec>) -> Self { - use hash_db::HashDB; - - let mut proof_db = MemoryDB::::default(); - for item in proof { - proof_db.insert(EMPTY_PREFIX, &item); - } - Self::with_db(proof_db) - } - - /// Get mutable cache reference. - pub fn cache_mut(&mut self) -> &mut BuildCache { - &mut self.cache - } - - /// Create the storage with given blocks. - pub fn with_blocks(blocks: Vec<(Number, H::Out)>) -> Self { - Self { - data: RwLock::new(InMemoryStorageData { - roots: blocks.into_iter().collect(), - mdb: MemoryDB::default(), - }), - cache: BuildCache::new(), - } - } - - #[cfg(test)] - pub fn with_inputs( - mut top_inputs: Vec<(Number, Vec>)>, - children_inputs: Vec<(Vec, Vec<(Number, Vec>)>)>, - ) -> Self { - let mut mdb = MemoryDB::default(); - let mut roots = BTreeMap::new(); - for (storage_key, child_input) in children_inputs { - for (block, pairs) in child_input { - let root = insert_into_memory_db::(&mut mdb, pairs.into_iter().map(Into::into)); - - if let Some(root) = root { - let ix = if let Some(ix) = top_inputs.iter().position(|v| v.0 == block) { - ix - } else { - top_inputs.push((block.clone(), Default::default())); - top_inputs.len() - 1 - }; - top_inputs[ix].1.push(InputPair::ChildIndex( - ChildIndex { block: block.clone(), storage_key: storage_key.clone() }, - root.as_ref().to_vec(), - )); - } - } - } - - for (block, pairs) in top_inputs { - let root = insert_into_memory_db::(&mut mdb, pairs.into_iter().map(Into::into)); - if let Some(root) = root { - roots.insert(block, root); - } - } - - InMemoryStorage { - data: RwLock::new(InMemoryStorageData { - roots, - mdb, - }), - cache: BuildCache::new(), - } - } - - #[cfg(test)] - pub fn clear_storage(&self) { - self.data.write().mdb = MemoryDB::default(); // use new to be more correct - } - - #[cfg(test)] - pub fn remove_from_storage(&self, keys: &HashSet) { - let mut data = self.data.write(); - for key in keys { - data.mdb.remove_and_purge(key, hash_db::EMPTY_PREFIX); - } - } - - #[cfg(test)] - pub fn into_mdb(self) -> MemoryDB { - self.data.into_inner().mdb - } - - /// Insert changes trie for given block. - pub fn insert(&self, block: Number, changes_trie_root: H::Out, trie: MemoryDB) { - let mut data = self.data.write(); - data.roots.insert(block, changes_trie_root); - data.mdb.consolidate(trie); - } -} - -impl RootsStorage for InMemoryStorage { - fn build_anchor(&self, parent_hash: H::Out) -> Result, String> { - self.data.read().roots.iter() - .find(|(_, v)| **v == parent_hash) - .map(|(k, _)| AnchorBlockId { hash: parent_hash, number: k.clone() }) - .ok_or_else(|| format!("Can't find associated number for block {:?}", parent_hash)) - } - - fn root(&self, _anchor_block: &AnchorBlockId, block: Number) -> Result, String> { - Ok(self.data.read().roots.get(&block).cloned()) - } -} - -impl Storage for InMemoryStorage { - fn as_roots_storage(&self) -> &dyn RootsStorage { - self - } - - fn with_cached_changed_keys( - &self, - root: &H::Out, - functor: &mut dyn FnMut(&HashMap>, HashSet>>), - ) -> bool { - self.cache.with_changed_keys(root, functor) - } - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - MemoryDB::::get(&self.data.read().mdb, key, prefix) - } -} - -impl<'a, H: Hasher, Number: BlockNumber> TrieBackendAdapter<'a, H, Number> { - pub fn new(storage: &'a dyn Storage) -> Self { - Self { storage, _hasher: Default::default() } - } -} - -impl<'a, H, Number> TrieBackendStorage for TrieBackendAdapter<'a, H, Number> - where - Number: BlockNumber, - H: Hasher, -{ - type Overlay = MemoryDB; - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - self.storage.get(key, prefix) - } -} diff --git a/core/state-machine/src/error.rs b/core/state-machine/src/error.rs deleted file mode 100644 index 6e6ce995858ea..0000000000000 --- a/core/state-machine/src/error.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -/// State Machine Errors - -use std::fmt; - -/// State Machine Error bound. -/// -/// This should reflect Wasm error type bound for future compatibility. -pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} - -impl Error for T {} - -/// Externalities Error. -/// -/// Externalities are not really allowed to have errors, since it's assumed that dependent code -/// would not be executed unless externalities were available. This is included for completeness, -/// and as a transition away from the pre-existing framework. -#[derive(Debug, Eq, PartialEq)] -pub enum ExecutionError { - /// Backend error. - Backend(String), - /// The entry `:code` doesn't exist in storage so there's no way we can execute anything. - CodeEntryDoesNotExist, - /// Backend is incompatible with execution proof generation process. - UnableToGenerateProof, - /// Invalid execution proof. - InvalidProof, -} - -impl fmt::Display for ExecutionError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Externalities Error") } -} diff --git a/core/state-machine/src/ext.rs b/core/state-machine/src/ext.rs deleted file mode 100644 index 0e93302a95a54..0000000000000 --- a/core/state-machine/src/ext.rs +++ /dev/null @@ -1,606 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Concrete externalities implementation. - -use crate::{ - backend::Backend, OverlayedChanges, - changes_trie::{ - Storage as ChangesTrieStorage, CacheAction as ChangesTrieCacheAction, build_changes_trie, - }, -}; - -use hash_db::Hasher; -use primitives::{ - storage::{ChildStorageKey, well_known_keys::is_child_storage_key}, - traits::Externalities, hexdisplay::HexDisplay, hash::H256, -}; -use trie::{trie_types::Layout, MemoryDB, default_child_trie_root}; -use externalities::Extensions; - -use std::{error, fmt, any::{Any, TypeId}}; -use log::{warn, trace}; - -const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime"; - -/// Errors that can occur when interacting with the externalities. -#[derive(Debug, Copy, Clone)] -pub enum Error { - /// Failure to load state data from the backend. - #[allow(unused)] - Backend(B), - /// Failure to execute a function. - #[allow(unused)] - Executor(E), -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::Backend(ref e) => write!(f, "Storage backend error: {}", e), - Error::Executor(ref e) => write!(f, "Sub-call execution error: {}", e), - } - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - match *self { - Error::Backend(..) => "backend error", - Error::Executor(..) => "executor error", - } - } -} - -/// Wraps a read-only backend, call executor, and current overlayed changes. -pub struct Ext<'a, H, N, B, T> where H: Hasher, B: 'a + Backend { - /// The overlayed changes to write to. - overlay: &'a mut OverlayedChanges, - /// The storage backend to read from. - backend: &'a B, - /// The storage transaction necessary to commit to the backend. Is cached when - /// `storage_root` is called and the cache is cleared on every subsequent change. - storage_transaction: Option<(B::Transaction, H::Out)>, - /// Changes trie storage to read from. - changes_trie_storage: Option<&'a T>, - /// The changes trie transaction necessary to commit to the changes trie backend. - /// Set to Some when `storage_changes_root` is called. Could be replaced later - /// by calling `storage_changes_root` again => never used as cache. - /// This differs from `storage_transaction` behavior, because the moment when - /// `storage_changes_root` is called matters + we need to remember additional - /// data at this moment (block number). - changes_trie_transaction: Option<(MemoryDB, H::Out, ChangesTrieCacheAction)>, - /// Pseudo-unique id used for tracing. - pub id: u16, - /// Dummy usage of N arg. - _phantom: std::marker::PhantomData, - /// Extensions registered with this instance. - extensions: Option<&'a mut Extensions>, -} - -impl<'a, H, N, B, T> Ext<'a, H, N, B, T> -where - H: Hasher, - B: 'a + Backend, - T: 'a + ChangesTrieStorage, - N: crate::changes_trie::BlockNumber, -{ - - /// Create a new `Ext` from overlayed changes and read-only backend - pub fn new( - overlay: &'a mut OverlayedChanges, - backend: &'a B, - changes_trie_storage: Option<&'a T>, - extensions: Option<&'a mut Extensions>, - ) -> Self { - Ext { - overlay, - backend, - storage_transaction: None, - changes_trie_storage, - changes_trie_transaction: None, - id: rand::random(), - _phantom: Default::default(), - extensions, - } - } - - /// Get the transaction necessary to update the backend. - pub fn transaction(&mut self) -> ( - (B::Transaction, H256), - Option>, - ) { - let _ = self.storage_root(); - - let (storage_transaction, changes_trie_transaction) = ( - self.storage_transaction - .take() - .expect("storage_transaction always set after calling storage root; qed"), - self.changes_trie_transaction - .take() - .map(|(tx, _, cache)| (tx, cache)), - ); - - ( - storage_transaction, - changes_trie_transaction, - ) - } - - /// Invalidates the currently cached storage root and the db transaction. - /// - /// Called when there are changes that likely will invalidate the storage root. - fn mark_dirty(&mut self) { - self.storage_transaction = None; - } -} - -#[cfg(test)] -impl<'a, H, N, B, T> Ext<'a, H, N, B, T> -where - H: Hasher, - B: 'a + Backend, - T: 'a + ChangesTrieStorage, - N: crate::changes_trie::BlockNumber, -{ - pub fn storage_pairs(&self) -> Vec<(Vec, Vec)> { - use std::collections::HashMap; - - self.backend.pairs().iter() - .map(|&(ref k, ref v)| (k.to_vec(), Some(v.to_vec()))) - .chain(self.overlay.committed.top.clone().into_iter().map(|(k, v)| (k, v.value))) - .chain(self.overlay.prospective.top.clone().into_iter().map(|(k, v)| (k, v.value))) - .collect::>() - .into_iter() - .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) - .collect() - } -} - -impl<'a, H, B, T, N> Externalities for Ext<'a, H, N, B, T> -where - H: Hasher, - B: 'a + Backend, - T: 'a + ChangesTrieStorage, - N: crate::changes_trie::BlockNumber, -{ - fn storage(&self, key: &[u8]) -> Option> { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| - self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL)); - trace!(target: "state-trace", "{:04x}: Get {}={:?}", - self.id, - HexDisplay::from(&key), - result.as_ref().map(HexDisplay::from) - ); - result - } - - fn storage_hash(&self, key: &[u8]) -> Option { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = self.overlay - .storage(key) - .map(|x| x.map(|x| H::hash(x))) - .unwrap_or_else(|| - self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL) - ); - trace!(target: "state-trace", "{:04x}: Hash {}={:?}", - self.id, - HexDisplay::from(&key), - result, - ); - result - } - - fn original_storage(&self, key: &[u8]) -> Option> { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL); - trace!(target: "state-trace", "{:04x}: GetOriginal {}={:?}", - self.id, - HexDisplay::from(&key), - result.as_ref().map(HexDisplay::from) - ); - result - } - - fn original_storage_hash(&self, key: &[u8]) -> Option { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL); - trace!(target: "state-trace", "{:04x}: GetOriginalHash {}={:?}", - self.id, - HexDisplay::from(&key), - result, - ); - result - } - - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = self.overlay - .child_storage(storage_key.as_ref(), key) - .map(|x| x.map(|x| x.to_vec())) - .unwrap_or_else(|| - self.backend.child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL) - ); - - trace!(target: "state-trace", "{:04x}: GetChild({}) {}={:?}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&key), - result.as_ref().map(HexDisplay::from) - ); - - result - } - - fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = self.overlay - .child_storage(storage_key.as_ref(), key) - .map(|x| x.map(|x| H::hash(x))) - .unwrap_or_else(|| - self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL) - ); - - trace!(target: "state-trace", "{:04x}: ChildHash({}) {}={:?}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&key), - result, - ); - - result - } - - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = self.backend - .child_storage(storage_key.as_ref(), key) - .expect(EXT_NOT_ALLOWED_TO_FAIL); - - trace!(target: "state-trace", "{:04x}: ChildOriginal({}) {}={:?}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&key), - result.as_ref().map(HexDisplay::from), - ); - result - } - - fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = self.backend - .child_storage_hash(storage_key.as_ref(), key) - .expect(EXT_NOT_ALLOWED_TO_FAIL); - - trace!(target: "state-trace", "{}: ChildHashOriginal({}) {}={:?}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&key), - result, - ); - result - } - - fn exists_storage(&self, key: &[u8]) -> bool { - let _guard = panic_handler::AbortGuard::force_abort(); - let result = match self.overlay.storage(key) { - Some(x) => x.is_some(), - _ => self.backend.exists_storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL), - }; - - trace!(target: "state-trace", "{:04x}: Exists {}={:?}", - self.id, - HexDisplay::from(&key), - result, - ); - result - - } - - fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { - let _guard = panic_handler::AbortGuard::force_abort(); - - let result = match self.overlay.child_storage(storage_key.as_ref(), key) { - Some(x) => x.is_some(), - _ => self.backend - .exists_child_storage(storage_key.as_ref(), key) - .expect(EXT_NOT_ALLOWED_TO_FAIL), - }; - - trace!(target: "state-trace", "{:04x}: ChildExists({}) {}={:?}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&key), - result, - ); - result - } - - fn place_storage(&mut self, key: Vec, value: Option>) { - trace!(target: "state-trace", "{:04x}: Put {}={:?}", - self.id, - HexDisplay::from(&key), - value.as_ref().map(HexDisplay::from) - ); - let _guard = panic_handler::AbortGuard::force_abort(); - if is_child_storage_key(&key) { - warn!(target: "trie", "Refuse to directly set child storage key"); - return; - } - - self.mark_dirty(); - self.overlay.set_storage(key, value); - } - - fn place_child_storage( - &mut self, - storage_key: ChildStorageKey, - key: Vec, - value: Option>, - ) { - trace!(target: "state-trace", "{:04x}: PutChild({}) {}={:?}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&key), - value.as_ref().map(HexDisplay::from) - ); - let _guard = panic_handler::AbortGuard::force_abort(); - - self.mark_dirty(); - self.overlay.set_child_storage(storage_key.into_owned(), key, value); - } - - fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { - trace!(target: "state-trace", "{:04x}: KillChild({})", - self.id, - HexDisplay::from(&storage_key.as_ref()), - ); - let _guard = panic_handler::AbortGuard::force_abort(); - - self.mark_dirty(); - self.overlay.clear_child_storage(storage_key.as_ref()); - self.backend.for_keys_in_child_storage(storage_key.as_ref(), |key| { - self.overlay.set_child_storage(storage_key.as_ref().to_vec(), key.to_vec(), None); - }); - } - - fn clear_prefix(&mut self, prefix: &[u8]) { - trace!(target: "state-trace", "{:04x}: ClearPrefix {}", - self.id, - HexDisplay::from(&prefix), - ); - let _guard = panic_handler::AbortGuard::force_abort(); - if is_child_storage_key(prefix) { - warn!(target: "trie", "Refuse to directly clear prefix that is part of child storage key"); - return; - } - - self.mark_dirty(); - self.overlay.clear_prefix(prefix); - self.backend.for_keys_with_prefix(prefix, |key| { - self.overlay.set_storage(key.to_vec(), None); - }); - } - - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { - trace!(target: "state-trace", "{:04x}: ClearChildPrefix({}) {}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&prefix), - ); - let _guard = panic_handler::AbortGuard::force_abort(); - - self.mark_dirty(); - self.overlay.clear_child_prefix(storage_key.as_ref(), prefix); - self.backend.for_child_keys_with_prefix(storage_key.as_ref(), prefix, |key| { - self.overlay.set_child_storage(storage_key.as_ref().to_vec(), key.to_vec(), None); - }); - } - - fn chain_id(&self) -> u64 { - 42 - } - - fn storage_root(&mut self) -> H256 { - let _guard = panic_handler::AbortGuard::force_abort(); - if let Some((_, ref root)) = self.storage_transaction { - trace!(target: "state-trace", "{:04x}: Root (cached) {}", - self.id, - HexDisplay::from(&root.as_ref()), - ); - return root.clone(); - } - - let child_storage_keys = - self.overlay.prospective.children.keys() - .chain(self.overlay.committed.children.keys()); - let child_delta_iter = child_storage_keys.map(|storage_key| - (storage_key.clone(), self.overlay.committed.children.get(storage_key) - .into_iter() - .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.value.clone()))) - .chain(self.overlay.prospective.children.get(storage_key) - .into_iter() - .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.value.clone())))))); - - - // compute and memoize - let delta = self.overlay.committed.top.iter().map(|(k, v)| (k.clone(), v.value.clone())) - .chain(self.overlay.prospective.top.iter().map(|(k, v)| (k.clone(), v.value.clone()))); - - let (root, transaction) = self.backend.full_storage_root(delta, child_delta_iter); - self.storage_transaction = Some((transaction, root)); - trace!(target: "state-trace", "{:04x}: Root {}", - self.id, - HexDisplay::from(&root.as_ref()), - ); - root - } - - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { - let _guard = panic_handler::AbortGuard::force_abort(); - if self.storage_transaction.is_some() { - let root = self - .storage(storage_key.as_ref()) - .unwrap_or( - default_child_trie_root::>(storage_key.as_ref()) - ); - trace!(target: "state-trace", "{:04x}: ChildRoot({}) (cached) {}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&root.as_ref()), - ); - root - } else { - let storage_key = storage_key.as_ref(); - - let (root, is_empty, _) = { - let delta = self.overlay.committed.children.get(storage_key) - .into_iter() - .flat_map(|map| map.clone().into_iter().map(|(k, v)| (k, v.value))) - .chain(self.overlay.prospective.children.get(storage_key) - .into_iter() - .flat_map(|map| map.clone().into_iter().map(|(k, v)| (k, v.value)))); - - self.backend.child_storage_root(storage_key, delta) - }; - - if is_empty { - self.overlay.set_storage(storage_key.into(), None); - } else { - self.overlay.set_storage(storage_key.into(), Some(root.clone())); - } - - trace!(target: "state-trace", "{:04x}: ChildRoot({}) {}", - self.id, - HexDisplay::from(&storage_key.as_ref()), - HexDisplay::from(&root.as_ref()), - ); - root - - } - } - - fn storage_changes_root(&mut self, parent_hash: H256) -> Result, ()> { - let _guard = panic_handler::AbortGuard::force_abort(); - self.changes_trie_transaction = build_changes_trie::<_, T, H, N>( - self.backend, - self.changes_trie_storage.clone(), - self.overlay, - parent_hash, - )?; - let result = Ok(self.changes_trie_transaction.as_ref().map(|(_, root, _)| root.clone())); - trace!(target: "state-trace", "{:04x}: ChangesRoot({}) {:?}", - self.id, - HexDisplay::from(&parent_hash.as_ref()), - result, - ); - result - } -} - -impl<'a, H, B, T, N> externalities::ExtensionStore for Ext<'a, H, N, B, T> -where - H: Hasher, - B: 'a + Backend, - T: 'a + ChangesTrieStorage, - N: crate::changes_trie::BlockNumber, -{ - fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> { - self.extensions.as_mut().and_then(|exts| exts.get_mut(type_id)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use hex_literal::hex; - use codec::Encode; - use primitives::{Blake2Hasher, storage::well_known_keys::EXTRINSIC_INDEX}; - use crate::{ - changes_trie::{ - Configuration as ChangesTrieConfiguration, - InMemoryStorage as InMemoryChangesTrieStorage, - }, backend::InMemory, overlayed_changes::OverlayedValue, - }; - - type TestBackend = InMemory; - type TestChangesTrieStorage = InMemoryChangesTrieStorage; - type TestExt<'a> = Ext<'a, Blake2Hasher, u64, TestBackend, TestChangesTrieStorage>; - - fn prepare_overlay_with_changes() -> OverlayedChanges { - OverlayedChanges { - prospective: vec![ - (EXTRINSIC_INDEX.to_vec(), OverlayedValue { - value: Some(3u32.encode()), - extrinsics: Some(vec![1].into_iter().collect()) - }), - (vec![1], OverlayedValue { - value: Some(vec![100].into_iter().collect()), - extrinsics: Some(vec![1].into_iter().collect()) - }), - ].into_iter().collect(), - committed: Default::default(), - changes_trie_config: Some(ChangesTrieConfiguration { - digest_interval: 0, - digest_levels: 0, - }), - } - } - - #[test] - fn storage_changes_root_is_none_when_storage_is_not_provided() { - let mut overlay = prepare_overlay_with_changes(); - let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, None, None); - assert_eq!(ext.storage_changes_root(Default::default()).unwrap(), None); - } - - #[test] - fn storage_changes_root_is_none_when_extrinsic_changes_are_none() { - let mut overlay = prepare_overlay_with_changes(); - overlay.changes_trie_config = None; - let storage = TestChangesTrieStorage::with_blocks(vec![(100, Default::default())]); - let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None); - assert_eq!(ext.storage_changes_root(Default::default()).unwrap(), None); - } - - #[test] - fn storage_changes_root_is_some_when_extrinsic_changes_are_non_empty() { - let mut overlay = prepare_overlay_with_changes(); - let storage = TestChangesTrieStorage::with_blocks(vec![(99, Default::default())]); - let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None); - assert_eq!( - ext.storage_changes_root(Default::default()).unwrap(), - Some(hex!("bb0c2ef6e1d36d5490f9766cfcc7dfe2a6ca804504c3bb206053890d6dd02376").into()), - ); - } - - #[test] - fn storage_changes_root_is_some_when_extrinsic_changes_are_empty() { - let mut overlay = prepare_overlay_with_changes(); - overlay.prospective.top.get_mut(&vec![1]).unwrap().value = None; - let storage = TestChangesTrieStorage::with_blocks(vec![(99, Default::default())]); - let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None); - assert_eq!( - ext.storage_changes_root(Default::default()).unwrap(), - Some(hex!("96f5aae4690e7302737b6f9b7f8567d5bbb9eac1c315f80101235a92d9ec27f4").into()), - ); - } -} diff --git a/core/state-machine/src/lib.rs b/core/state-machine/src/lib.rs deleted file mode 100644 index c3092367f0646..0000000000000 --- a/core/state-machine/src/lib.rs +++ /dev/null @@ -1,1128 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate state machine implementation. - -#![warn(missing_docs)] - -use std::{fmt, result, collections::HashMap, panic::UnwindSafe, marker::PhantomData}; -use log::{warn, trace}; -use hash_db::Hasher; -use codec::{Decode, Encode}; -use primitives::{ - storage::well_known_keys, NativeOrEncoded, NeverNativeValue, offchain::OffchainExt, - traits::{KeystoreExt, CodeExecutor}, hexdisplay::HexDisplay, hash::H256, -}; -use overlayed_changes::OverlayedChangeSet; -use externalities::Extensions; - -pub mod backend; -mod changes_trie; -mod error; -mod ext; -mod testing; -mod basic; -mod overlayed_changes; -mod proving_backend; -mod trie_backend; -mod trie_backend_essence; - -pub use trie::{trie_types::{Layout, TrieDBMut}, TrieMut, DBValue, MemoryDB}; -pub use testing::TestExternalities; -pub use basic::BasicExternalities; -pub use ext::Ext; -pub use backend::Backend; -pub use changes_trie::{ - AnchorBlockId as ChangesTrieAnchorBlockId, - Storage as ChangesTrieStorage, - RootsStorage as ChangesTrieRootsStorage, - InMemoryStorage as InMemoryChangesTrieStorage, - BuildCache as ChangesTrieBuildCache, - CacheAction as ChangesTrieCacheAction, - ConfigurationRange as ChangesTrieConfigurationRange, - key_changes, key_changes_proof, key_changes_proof_check, - 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, - Recorder as ProofRecorder, ProvingBackend, -}; -pub use trie_backend_essence::{TrieBackendStorage, Storage}; -pub use trie_backend::TrieBackend; -pub use error::{Error, ExecutionError}; - -type CallResult = Result, E>; - -type DefaultHandler = fn(CallResult, CallResult) -> CallResult; - -/// Type of changes trie transaction. -pub type ChangesTrieTransaction = ( - MemoryDB, - ChangesTrieCacheAction<::Out, N>, -); - -/// Strategy for executing a call into the runtime. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum ExecutionStrategy { - /// Execute with the native equivalent if it is compatible with the given wasm module; otherwise fall back to the wasm. - NativeWhenPossible, - /// Use the given wasm module. - AlwaysWasm, - /// 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, -} - -/// Storage backend trust level. -#[derive(Debug, Clone)] -pub enum BackendTrustLevel { - /// Panics from trusted backends are considered justified, and never caught. - Trusted, - /// Panics from untrusted backend are caught and interpreted as runtime error. - /// Untrusted backend may be missing some parts of the trie, so panics are not considered - /// fatal. - Untrusted, -} - -/// Like `ExecutionStrategy` only it also stores a handler in case of consensus failure. -#[derive(Clone)] -pub enum ExecutionManager { - /// Execute with the native equivalent if it is compatible with the given wasm module; otherwise fall back to the wasm. - NativeWhenPossible, - /// Use the given wasm module. The backend on which code is executed code could be - /// trusted to provide all storage or not (i.e. the light client cannot be trusted to provide - /// for all storage queries since the storage entries it has come from an external node). - AlwaysWasm(BackendTrustLevel), - /// Run with both the wasm and the native variant (if compatible). Call `F` in the case of any discrepency. - Both(F), - /// First native, then if that fails or is not possible, wasm. - NativeElseWasm, -} - -impl<'a, F> From<&'a ExecutionManager> for ExecutionStrategy { - fn from(s: &'a ExecutionManager) -> Self { - match *s { - ExecutionManager::NativeWhenPossible => ExecutionStrategy::NativeWhenPossible, - ExecutionManager::AlwaysWasm(_) => ExecutionStrategy::AlwaysWasm, - ExecutionManager::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(BackendTrustLevel::Trusted), - 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::NativeElseWasm, without having to figure out the type. -pub fn native_else_wasm() -> ExecutionManager> { - ExecutionManager::NativeElseWasm -} - -/// Evaluate to ExecutionManager::AlwaysWasm with trusted backend, without having to figure out the type. -fn always_wasm() -> ExecutionManager> { - ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted) -} - -/// Evaluate ExecutionManager::AlwaysWasm with untrusted backend, without having to figure out the type. -fn always_untrusted_wasm() -> ExecutionManager> { - ExecutionManager::AlwaysWasm(BackendTrustLevel::Untrusted) -} - -/// The substrate state machine. -pub struct StateMachine<'a, B, H, N, T, Exec> where H: Hasher, B: Backend { - backend: &'a B, - exec: &'a Exec, - method: &'a str, - call_data: &'a [u8], - overlay: &'a mut OverlayedChanges, - extensions: Extensions, - changes_trie_storage: Option<&'a T>, - _marker: PhantomData<(H, N)>, -} - -impl<'a, B, H, N, T, Exec> StateMachine<'a, B, H, N, T, Exec> where - H: Hasher, - Exec: CodeExecutor, - B: Backend, - T: ChangesTrieStorage, - N: crate::changes_trie::BlockNumber, -{ - /// Creates new substrate state machine. - pub fn new( - backend: &'a B, - changes_trie_storage: Option<&'a T>, - offchain_ext: Option, - overlay: &'a mut OverlayedChanges, - exec: &'a Exec, - method: &'a str, - call_data: &'a [u8], - keystore: Option, - ) -> Self { - let mut extensions = Extensions::new(); - - if let Some(keystore) = keystore { - extensions.register(keystore); - } - - if let Some(offchain) = offchain_ext { - extensions.register(offchain); - } - - Self { - backend, - exec, - method, - call_data, - extensions, - overlay, - changes_trie_storage, - _marker: PhantomData, - } - } - - /// Execute a call using the given state backend, overlayed changes, and call executor. - /// Produces a state-backend-specific "transaction" which can be used to apply the changes - /// to the backing store, such as the disk. - /// - /// 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, H::Out), Option>), - Box, - > { - // We are not giving a native call and thus we are sure that the result can never be a native - // value. - self.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( - 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, - )) - } - - fn execute_aux( - &mut self, - compute_tx: bool, - use_native: bool, - native_call: Option, - ) -> ( - CallResult, - bool, - Option<(B::Transaction, H::Out)>, - Option>, - ) where - R: Decode + Encode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, - { - let mut ext = Ext::new( - self.overlay, - self.backend, - self.changes_trie_storage.clone(), - Some(&mut self.extensions), - ); - - let id = ext.id; - trace!( - target: "state-trace", "{:04x}: Call {} at {:?}. Input={:?}", - id, - self.method, - self.backend, - HexDisplay::from(&self.call_data), - ); - - let (result, was_native) = self.exec.call( - &mut ext, - self.method, - self.call_data, - use_native, - native_call, - ); - - let (storage_delta, changes_delta) = if compute_tx { - let (storage_delta, changes_delta) = ext.transaction(); - (Some(storage_delta), changes_delta) - } else { - (None, None) - }; - - trace!( - target: "state-trace", "{:04x}: Return. Native={:?}, Result={:?}", - id, - was_native, - result, - ); - - (result, was_native, storage_delta, changes_delta) - } - - fn execute_call_with_both_strategy( - &mut self, - compute_tx: bool, - mut native_call: Option, - orig_prospective: OverlayedChangeSet, - on_consensus_failure: Handler, - ) -> ( - CallResult, - Option<(B::Transaction, H::Out)>, - 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 { - (on_consensus_failure(wasm_result, result), wasm_storage_delta, wasm_changes_delta) - } - } else { - (result, storage_delta, changes_delta) - } - } - - fn execute_call_with_native_else_wasm_strategy( - &mut self, - compute_tx: bool, - mut native_call: Option, - orig_prospective: OverlayedChangeSet, - ) -> ( - CallResult, - Option<(B::Transaction, H::Out)>, - 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) - } - } - - /// 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<(B::Transaction, H::Out)>, - 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 init_overlay = |overlay: &mut OverlayedChanges, final_check: bool, backend: &B| { - 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, &self.backend)?; - - 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(trust_level) => { - let _abort_guard = match trust_level { - BackendTrustLevel::Trusted => None, - BackendTrustLevel::Untrusted => Some(panic_handler::AbortGuard::never_abort()), - }; - let res = self.execute_aux(compute_tx, false, native_call); - (res.0, res.2, res.3) - }, - ExecutionManager::NativeWhenPossible => { - let res = self.execute_aux(compute_tx, true, native_call); - (res.0, res.2, res.3) - }, - }; - result.map(move |out| (out, storage_delta, changes_delta)) - }; - - if result.is_ok() { - init_overlay(self.overlay, true, self.backend)?; - } - - result.map_err(|e| Box::new(e) as _) - } -} - -/// Prove execution using the given state backend, overlayed changes, and call executor. -pub fn prove_execution( - mut backend: B, - overlay: &mut OverlayedChanges, - exec: &Exec, - method: &str, - call_data: &[u8], - keystore: Option, -) -> Result<(Vec, Vec>), Box> -where - B: Backend, - H: Hasher, - Exec: CodeExecutor, -{ - let trie_backend = backend.as_trie_backend() - .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; - prove_execution_on_trie_backend(trie_backend, overlay, exec, method, call_data, keystore) -} - -/// Prove execution using the given trie 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. -/// Execution proof is the set of all 'touched' storage DBValues from the backend. -/// -/// 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 prove_execution_on_trie_backend( - trie_backend: &TrieBackend, - overlay: &mut OverlayedChanges, - exec: &Exec, - method: &str, - call_data: &[u8], - keystore: Option, -) -> Result<(Vec, Vec>), Box> -where - S: trie_backend_essence::TrieBackendStorage, - H: Hasher, - Exec: CodeExecutor, -{ - let proving_backend = proving_backend::ProvingBackend::new(trie_backend); - let mut sm = StateMachine::<_, H, _, InMemoryChangesTrieStorage, Exec>::new( - &proving_backend, None, None, overlay, exec, method, call_data, keystore, - ); - - let (result, _, _) = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( - always_wasm(), - false, - None, - )?; - let proof = sm.backend.extract_proof(); - Ok((result.into_encoded(), proof)) -} - -/// Check execution proof, generated by `prove_execution` call. -pub fn execution_proof_check( - root: H::Out, - proof: Vec>, - overlay: &mut OverlayedChanges, - exec: &Exec, - method: &str, - call_data: &[u8], - keystore: Option, -) -> Result, Box> -where - H: Hasher, - Exec: CodeExecutor, - H::Out: Ord + 'static, -{ - let trie_backend = create_proof_check_backend::(root.into(), proof)?; - execution_proof_check_on_trie_backend(&trie_backend, overlay, exec, method, call_data, keystore) -} - -/// Check execution proof on proving backend, generated by `prove_execution` call. -pub fn execution_proof_check_on_trie_backend( - trie_backend: &TrieBackend, H>, - overlay: &mut OverlayedChanges, - exec: &Exec, - method: &str, - call_data: &[u8], - keystore: Option, -) -> Result, Box> -where - H: Hasher, - Exec: CodeExecutor, -{ - let mut sm = StateMachine::<_, H, _, InMemoryChangesTrieStorage, Exec>::new( - trie_backend, None, None, overlay, exec, method, call_data, keystore, - ); - - sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( - always_untrusted_wasm(), - false, - None, - ).map(|(result, _, _)| result.into_encoded()) -} - -/// Generate storage read proof. -pub fn prove_read( - mut backend: B, - keys: I, -) -> Result>, Box> -where - B: Backend, - H: Hasher, - H::Out: Ord, - I: IntoIterator, - I::Item: AsRef<[u8]>, -{ - let trie_backend = backend.as_trie_backend() - .ok_or_else( - || Box::new(ExecutionError::UnableToGenerateProof) as Box - )?; - prove_read_on_trie_backend(trie_backend, keys) -} - -/// Generate child storage read proof. -pub fn prove_child_read( - mut backend: B, - storage_key: &[u8], - keys: I, -) -> Result>, Box> -where - B: Backend, - H: Hasher, - H::Out: Ord, - I: IntoIterator, - I::Item: AsRef<[u8]>, -{ - let trie_backend = backend.as_trie_backend() - .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; - prove_child_read_on_trie_backend(trie_backend, storage_key, keys) -} - -/// Generate storage read proof on pre-created trie backend. -pub fn prove_read_on_trie_backend( - trie_backend: &TrieBackend, - keys: I, -) -> Result>, Box> -where - S: trie_backend_essence::TrieBackendStorage, - H: Hasher, - H::Out: Ord, - I: IntoIterator, - I::Item: AsRef<[u8]>, -{ - let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend); - for key in keys.into_iter() { - proving_backend - .storage(key.as_ref()) - .map_err(|e| Box::new(e) as Box)?; - } - Ok(proving_backend.extract_proof()) -} - -/// Generate storage read proof on pre-created trie backend. -pub fn prove_child_read_on_trie_backend( - trie_backend: &TrieBackend, - storage_key: &[u8], - keys: I, -) -> Result>, Box> -where - S: trie_backend_essence::TrieBackendStorage, - H: Hasher, - H::Out: Ord, - I: IntoIterator, - I::Item: AsRef<[u8]>, -{ - let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend); - for key in keys.into_iter() { - proving_backend - .child_storage(storage_key, key.as_ref()) - .map_err(|e| Box::new(e) as Box)?; - } - Ok(proving_backend.extract_proof()) -} - -/// Check storage read proof, generated by `prove_read` call. -pub fn read_proof_check( - root: H::Out, - proof: Vec>, - keys: I, -) -> Result, Option>>, Box> -where - H: Hasher, - H::Out: Ord, - I: IntoIterator, - I::Item: AsRef<[u8]>, -{ - let proving_backend = create_proof_check_backend::(root, proof)?; - let mut result = HashMap::new(); - for key in keys.into_iter() { - let value = read_proof_check_on_proving_backend(&proving_backend, key.as_ref())?; - result.insert(key.as_ref().to_vec(), value); - } - Ok(result) -} - -/// Check child storage read proof, generated by `prove_child_read` call. -pub fn read_child_proof_check( - root: H::Out, - proof: Vec>, - storage_key: &[u8], - keys: I, -) -> Result, Option>>, Box> -where - H: Hasher, - H::Out: Ord, - I: IntoIterator, - I::Item: AsRef<[u8]>, -{ - let proving_backend = create_proof_check_backend::(root, proof)?; - let mut result = HashMap::new(); - for key in keys.into_iter() { - let value = read_child_proof_check_on_proving_backend( - &proving_backend, - storage_key, - key.as_ref(), - )?; - result.insert(key.as_ref().to_vec(), value); - } - Ok(result) -} - -/// Check storage read proof on pre-created proving backend. -pub fn read_proof_check_on_proving_backend( - proving_backend: &TrieBackend, H>, - key: &[u8], -) -> Result>, Box> -where - H: Hasher, - H::Out: Ord, -{ - proving_backend.storage(key).map_err(|e| Box::new(e) as Box) -} - -/// Check child storage read proof on pre-created proving backend. -pub fn read_child_proof_check_on_proving_backend( - proving_backend: &TrieBackend, H>, - storage_key: &[u8], - key: &[u8], -) -> Result>, Box> -where - H: Hasher, - H::Out: Ord, -{ - proving_backend.child_storage(storage_key, key).map_err(|e| Box::new(e) as Box) -} - -/// Sets overlayed changes' changes trie configuration. Returns error if configuration -/// differs from previous OR config decode has failed. -fn set_changes_trie_config( - overlay: &mut OverlayedChanges, - config: Option>, - final_check: bool, -) -> Result<(), Box> { - let config = match config { - Some(v) => Some(Decode::decode(&mut &v[..]) - .map_err(|_| Box::new("Failed to decode changes trie configuration".to_owned()) as Box)?), - None => None, - }; - - if final_check && overlay.changes_trie_config.is_some() != config.is_some() { - return Err(Box::new("Changes trie configuration change is not supported".to_owned())); - } - - if let Some(config) = config { - if !overlay.set_changes_trie_config(config) { - return Err(Box::new("Changes trie configuration change is not supported".to_owned())); - } - } - Ok(()) -} - -/// Reads storage value from overlay or from the backend. -fn try_read_overlay_value( - overlay: &OverlayedChanges, - backend: &B, key: &[u8], -) -> Result>, Box> where H: Hasher, B: Backend { - match overlay.storage(key).map(|x| x.map(|x| x.to_vec())) { - Some(value) => Ok(value), - None => backend - .storage(key) - .map_err(|err| Box::new(ExecutionError::Backend(format!("{}", err))) as Box), - } -} - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - use codec::Encode; - use overlayed_changes::OverlayedValue; - use super::*; - use super::backend::InMemory; - use super::ext::Ext; - use super::changes_trie::{ - InMemoryStorage as InMemoryChangesTrieStorage, - Configuration as ChangesTrieConfig, - }; - use primitives::{Blake2Hasher, map, traits::Externalities, storage::ChildStorageKey}; - - struct DummyCodeExecutor { - change_changes_trie_config: bool, - native_available: bool, - native_succeeds: bool, - fallback_succeeds: bool, - } - - impl CodeExecutor for DummyCodeExecutor { - type Error = u8; - - fn call< - E: Externalities, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result, - >( - &self, - ext: &mut E, - _method: &str, - _data: &[u8], - 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() - ) - ); - } - - let using_native = use_native && self.native_available; - match (using_native, self.native_succeeds, self.fallback_succeeds) { - (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), - } - } - } - - #[test] - fn execute_works() { - let backend = trie_backend::tests::test_trie(); - let mut overlayed_changes = Default::default(); - let changes_trie_storage = InMemoryChangesTrieStorage::::new(); - - let mut state_machine = StateMachine::new( - &backend, - Some(&changes_trie_storage), - None, - &mut overlayed_changes, - &DummyCodeExecutor { - change_changes_trie_config: false, - native_available: true, - native_succeeds: true, - fallback_succeeds: true, - }, - "test", - &[], - None, - ); - - assert_eq!( - state_machine.execute(ExecutionStrategy::NativeWhenPossible).unwrap().0, - vec![66], - ); - } - - - #[test] - fn execute_works_with_native_else_wasm() { - let backend = trie_backend::tests::test_trie(); - let mut overlayed_changes = Default::default(); - let changes_trie_storage = InMemoryChangesTrieStorage::::new(); - - let mut state_machine = StateMachine::new( - &backend, - Some(&changes_trie_storage), - None, - &mut overlayed_changes, - &DummyCodeExecutor { - change_changes_trie_config: false, - native_available: true, - native_succeeds: true, - fallback_succeeds: true, - }, - "test", - &[], - None, - ); - - assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap().0, vec![66]); - } - - #[test] - fn dual_execution_strategy_detects_consensus_failure() { - let mut consensus_failed = false; - let backend = trie_backend::tests::test_trie(); - let mut overlayed_changes = Default::default(); - let changes_trie_storage = InMemoryChangesTrieStorage::::new(); - - let mut state_machine = StateMachine::new( - &backend, - Some(&changes_trie_storage), - None, - &mut overlayed_changes, - &DummyCodeExecutor { - change_changes_trie_config: false, - native_available: true, - native_succeeds: true, - fallback_succeeds: false, - }, - "test", - &[], - None, - ); - - assert!( - state_machine.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( - ExecutionManager::Both(|we, _ne| { - consensus_failed = true; - we - }), - true, - None, - ).is_err() - ); - assert!(consensus_failed); - } - - #[test] - fn prove_execution_and_proof_check_works() { - let executor = DummyCodeExecutor { - change_changes_trie_config: false, - native_available: true, - native_succeeds: true, - fallback_succeeds: true, - }; - - // fetch execution proof from 'remote' full node - let remote_backend = trie_backend::tests::test_trie(); - let remote_root = remote_backend.storage_root(std::iter::empty()).0; - let (remote_result, remote_proof) = prove_execution( - remote_backend, - &mut Default::default(), - &executor, - "test", - &[], - None, - ).unwrap(); - - // check proof locally - let local_result = execution_proof_check::( - remote_root, - remote_proof, - &mut Default::default(), - &executor, - "test", - &[], - None, - ).unwrap(); - - // check that both results are correct - assert_eq!(remote_result, vec![66]); - assert_eq!(remote_result, local_result); - } - - #[test] - fn clear_prefix_in_ext_works() { - let initial: HashMap<_, _> = map![ - b"aaa".to_vec() => b"0".to_vec(), - b"abb".to_vec() => b"1".to_vec(), - b"abc".to_vec() => b"2".to_vec(), - b"bbb".to_vec() => b"3".to_vec() - ]; - let mut state = InMemory::::from(initial); - let backend = state.as_trie_backend().unwrap(); - let mut overlay = OverlayedChanges { - committed: map![ - b"aba".to_vec() => OverlayedValue::from(Some(b"1312".to_vec())), - b"bab".to_vec() => OverlayedValue::from(Some(b"228".to_vec())) - ], - prospective: map![ - b"abd".to_vec() => OverlayedValue::from(Some(b"69".to_vec())), - b"bbd".to_vec() => OverlayedValue::from(Some(b"42".to_vec())) - ], - ..Default::default() - }; - - { - let changes_trie_storage = InMemoryChangesTrieStorage::::new(); - let mut ext = Ext::new( - &mut overlay, - backend, - Some(&changes_trie_storage), - None, - ); - ext.clear_prefix(b"ab"); - } - overlay.commit_prospective(); - - assert_eq!( - overlay.committed, - map![ - b"abc".to_vec() => None.into(), - b"abb".to_vec() => None.into(), - b"aba".to_vec() => None.into(), - b"abd".to_vec() => None.into(), - - b"bab".to_vec() => Some(b"228".to_vec()).into(), - b"bbd".to_vec() => Some(b"42".to_vec()).into() - ], - ); - } - - #[test] - fn set_child_storage_works() { - let mut state = InMemory::::default(); - let backend = state.as_trie_backend().unwrap(); - let changes_trie_storage = InMemoryChangesTrieStorage::::new(); - let mut overlay = OverlayedChanges::default(); - let mut ext = Ext::new( - &mut overlay, - backend, - Some(&changes_trie_storage), - None, - ); - - ext.set_child_storage( - ChildStorageKey::from_slice(b":child_storage:default:testchild").unwrap(), - b"abc".to_vec(), - b"def".to_vec() - ); - assert_eq!( - ext.child_storage( - ChildStorageKey::from_slice(b":child_storage:default:testchild").unwrap(), - b"abc" - ), - Some(b"def".to_vec()) - ); - ext.kill_child_storage( - ChildStorageKey::from_slice(b":child_storage:default:testchild").unwrap() - ); - assert_eq!( - ext.child_storage( - ChildStorageKey::from_slice(b":child_storage:default:testchild").unwrap(), - b"abc" - ), - None - ); - } - - #[test] - fn prove_read_and_proof_check_works() { - // fetch read proof from 'remote' full node - let remote_backend = trie_backend::tests::test_trie(); - let remote_root = remote_backend.storage_root(::std::iter::empty()).0; - let remote_proof = prove_read(remote_backend, &[b"value2"]).unwrap(); - // check proof locally - let local_result1 = read_proof_check::( - remote_root, - remote_proof.clone(), - &[b"value2"], - ).unwrap(); - let local_result2 = read_proof_check::( - remote_root, - remote_proof.clone(), - &[&[0xff]], - ).is_ok(); - // check that results are correct - assert_eq!( - local_result1.into_iter().collect::>(), - vec![(b"value2".to_vec(), Some(vec![24]))], - ); - assert_eq!(local_result2, false); - // on child trie - let remote_backend = trie_backend::tests::test_trie(); - let remote_root = remote_backend.storage_root(::std::iter::empty()).0; - let remote_proof = prove_child_read( - remote_backend, - b":child_storage:default:sub1", - &[b"value3"], - ).unwrap(); - let local_result1 = read_child_proof_check::( - remote_root, - remote_proof.clone(), - b":child_storage:default:sub1", - &[b"value3"], - ).unwrap(); - let local_result2 = read_child_proof_check::( - remote_root, - remote_proof.clone(), - b":child_storage:default:sub1", - &[b"value2"], - ).unwrap(); - assert_eq!( - local_result1.into_iter().collect::>(), - vec![(b"value3".to_vec(), Some(vec![142]))], - ); - assert_eq!( - local_result2.into_iter().collect::>(), - vec![(b"value2".to_vec(), None)], - ); - } - - #[test] - fn cannot_change_changes_trie_config() { - let backend = trie_backend::tests::test_trie(); - let mut overlayed_changes = Default::default(); - let changes_trie_storage = InMemoryChangesTrieStorage::::new(); - - let mut state_machine = StateMachine::new( - &backend, - Some(&changes_trie_storage), - None, - &mut overlayed_changes, - &DummyCodeExecutor { - change_changes_trie_config: true, - native_available: false, - native_succeeds: true, - fallback_succeeds: true, - }, - "test", - &[], - None, - ); - - assert!(state_machine.execute(ExecutionStrategy::NativeWhenPossible).is_err()); - } - - #[test] - fn cannot_change_changes_trie_config_with_native_else_wasm() { - let backend = trie_backend::tests::test_trie(); - let mut overlayed_changes = Default::default(); - let changes_trie_storage = InMemoryChangesTrieStorage::::new(); - - let mut state_machine = StateMachine::new( - &backend, - Some(&changes_trie_storage), - None, - &mut overlayed_changes, - &DummyCodeExecutor { - change_changes_trie_config: true, - native_available: false, - native_succeeds: true, - fallback_succeeds: true, - }, - "test", - &[], - None, - ); - - assert!(state_machine.execute(ExecutionStrategy::NativeElseWasm).is_err()); - } -} diff --git a/core/state-machine/src/overlayed_changes.rs b/core/state-machine/src/overlayed_changes.rs deleted file mode 100644 index 53a66dc49ee05..0000000000000 --- a/core/state-machine/src/overlayed_changes.rs +++ /dev/null @@ -1,532 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! The overlayed changes to state. - -#[cfg(test)] -use std::iter::FromIterator; -use std::collections::{HashMap, BTreeSet}; -use 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. -/// -/// A transaction shares all prospective changes within an inner overlay -/// that can be cleared. -#[derive(Debug, Default, Clone)] -pub struct OverlayedChanges { - /// Changes that are not yet committed. - pub(crate) prospective: OverlayedChangeSet, - /// Committed changes. - pub(crate) committed: OverlayedChangeSet, - /// Changes trie configuration. None by default, but could be installed by the - /// runtime if it supports change tries. - pub(crate) changes_trie_config: Option, -} - -/// The storage value, used inside OverlayedChanges. -#[derive(Debug, Default, Clone)] -#[cfg_attr(test, derive(PartialEq))] -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 has announced changes trie support. - pub extrinsics: Option>, -} - -/// Prospective or committed overlayed change set. -#[derive(Debug, Default, Clone)] -#[cfg_attr(test, derive(PartialEq))] -pub struct OverlayedChangeSet { - /// Top level storage changes. - pub top: HashMap, OverlayedValue>, - /// Child storage changes. - pub children: HashMap, HashMap, OverlayedValue>>, -} - -#[cfg(test)] -impl FromIterator<(Vec, OverlayedValue)> for OverlayedChangeSet { - fn from_iter, OverlayedValue)>>(iter: T) -> Self { - Self { - top: iter.into_iter().collect(), - children: Default::default(), - } - } -} - -impl OverlayedChangeSet { - /// Whether the change set is empty. - pub fn is_empty(&self) -> bool { - self.top.is_empty() && self.children.is_empty() - } - - /// Clear the change set. - pub fn clear(&mut self) { - self.top.clear(); - self.children.clear(); - } -} - -impl OverlayedChanges { - /// Whether the overlayed changes are empty. - pub fn is_empty(&self) -> bool { - self.prospective.is_empty() && self.committed.is_empty() - } - - /// Sets the changes trie configuration. - /// - /// Returns false if configuration has been set already and we now trying - /// to install different configuration. This isn't supported now. - pub(crate) fn set_changes_trie_config(&mut self, config: ChangesTrieConfig) -> bool { - if let Some(ref old_config) = self.changes_trie_config { - // we do not support changes trie configuration' change now - if *old_config != config { - return false; - } - } - - self.changes_trie_config = Some(config); - true - } - - /// Returns a double-Option: None if the key is unknown (i.e. and the query should be refered - /// to the backend); Some(None) if the key has been deleted. Some(Some(...)) for a key whose - /// value has been set. - pub fn storage(&self, key: &[u8]) -> Option> { - self.prospective.top.get(key) - .or_else(|| self.committed.top.get(key)) - .map(|x| x.value.as_ref().map(AsRef::as_ref)) - } - - /// Returns a double-Option: None if the key is unknown (i.e. and the query should be refered - /// to the backend); Some(None) if the key has been deleted. Some(Some(...)) for a key whose - /// value has been set. - pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option> { - if let Some(map) = self.prospective.children.get(storage_key) { - if let Some(val) = map.get(key) { - return Some(val.value.as_ref().map(AsRef::as_ref)); - } - } - - if let Some(map) = self.committed.children.get(storage_key) { - if let Some(val) = map.get(key) { - return Some(val.value.as_ref().map(AsRef::as_ref)); - } - } - - None - } - - /// Inserts the given key-value pair into the prospective change set. - /// - /// `None` can be used to delete a value specified by the given key. - pub(crate) fn set_storage(&mut self, key: Vec, val: Option>) { - let extrinsic_index = self.extrinsic_index(); - let entry = self.prospective.top.entry(key).or_default(); - entry.value = val; - - if let Some(extrinsic) = extrinsic_index { - entry.extrinsics.get_or_insert_with(Default::default) - .insert(extrinsic); - } - } - - /// Inserts the given key-value pair into the prospective child change set. - /// - /// `None` can be used to delete a value specified by the given key. - pub(crate) fn set_child_storage(&mut self, storage_key: Vec, key: Vec, val: Option>) { - let extrinsic_index = self.extrinsic_index(); - let map_entry = self.prospective.children.entry(storage_key).or_default(); - let entry = map_entry.entry(key).or_default(); - entry.value = val; - - if let Some(extrinsic) = extrinsic_index { - entry.extrinsics.get_or_insert_with(Default::default) - .insert(extrinsic); - } - } - - /// Clear child storage of given storage key. - /// - /// NOTE that this doesn't take place immediately but written into the prospective - /// change set, and still can be reverted by [`discard_prospective`]. - /// - /// [`discard_prospective`]: #method.discard_prospective - pub(crate) fn clear_child_storage(&mut self, storage_key: &[u8]) { - let extrinsic_index = self.extrinsic_index(); - let map_entry = self.prospective.children.entry(storage_key.to_vec()).or_default(); - - map_entry.values_mut().for_each(|e| { - if let Some(extrinsic) = extrinsic_index { - e.extrinsics.get_or_insert_with(Default::default) - .insert(extrinsic); - } - - e.value = None; - }); - - if let Some(committed_map) = self.committed.children.get(storage_key) { - for (key, value) in committed_map.iter() { - if !map_entry.contains_key(key) { - map_entry.insert(key.clone(), OverlayedValue { - value: None, - extrinsics: extrinsic_index.map(|i| { - let mut e = value.extrinsics.clone() - .unwrap_or_else(|| BTreeSet::default()); - e.insert(i); - e - }), - }); - } - } - } - } - - /// Removes all key-value pairs which keys share the given prefix. - /// - /// NOTE that this doesn't take place immediately but written into the prospective - /// change set, and still can be reverted by [`discard_prospective`]. - /// - /// [`discard_prospective`]: #method.discard_prospective - pub(crate) fn clear_prefix(&mut self, prefix: &[u8]) { - let extrinsic_index = self.extrinsic_index(); - - // Iterate over all prospective and mark all keys that share - // the given prefix as removed (None). - for (key, entry) in self.prospective.top.iter_mut() { - if key.starts_with(prefix) { - entry.value = None; - - if let Some(extrinsic) = extrinsic_index { - entry.extrinsics.get_or_insert_with(Default::default) - .insert(extrinsic); - } - } - } - - // Then do the same with keys from commited changes. - // NOTE that we are making changes in the prospective change set. - for key in self.committed.top.keys() { - if key.starts_with(prefix) { - let entry = self.prospective.top.entry(key.clone()).or_default(); - entry.value = None; - - if let Some(extrinsic) = extrinsic_index { - entry.extrinsics.get_or_insert_with(Default::default) - .insert(extrinsic); - } - } - } - } - - pub(crate) fn clear_child_prefix(&mut self, storage_key: &[u8], prefix: &[u8]) { - let extrinsic_index = self.extrinsic_index(); - let map_entry = self.prospective.children.entry(storage_key.to_vec()).or_default(); - - for (key, entry) in map_entry.iter_mut() { - if key.starts_with(prefix) { - entry.value = None; - - if let Some(extrinsic) = extrinsic_index { - entry.extrinsics.get_or_insert_with(Default::default) - .insert(extrinsic); - } - } - } - - if let Some(child_committed) = self.committed.children.get(storage_key) { - // Then do the same with keys from commited changes. - // NOTE that we are making changes in the prospective change set. - for key in child_committed.keys() { - if key.starts_with(prefix) { - let entry = map_entry.entry(key.clone()).or_default(); - entry.value = None; - - if let Some(extrinsic) = extrinsic_index { - entry.extrinsics.get_or_insert_with(Default::default) - .insert(extrinsic); - } - } - } - } - } - - /// Discard prospective changes to state. - pub fn discard_prospective(&mut self) { - self.prospective.clear(); - } - - /// Commit prospective changes to state. - pub fn commit_prospective(&mut self) { - if self.committed.is_empty() { - ::std::mem::swap(&mut self.prospective, &mut self.committed); - } else { - for (key, val) in self.prospective.top.drain() { - let entry = self.committed.top.entry(key).or_default(); - entry.value = val.value; - - if let Some(prospective_extrinsics) = val.extrinsics { - entry.extrinsics.get_or_insert_with(Default::default) - .extend(prospective_extrinsics); - } - } - for (storage_key, mut map) in self.prospective.children.drain() { - let map_dest = self.committed.children.entry(storage_key).or_default(); - for (key, val) in map.drain() { - let entry = map_dest.entry(key).or_default(); - entry.value = val.value; - - if let Some(prospective_extrinsics) = val.extrinsics { - entry.extrinsics.get_or_insert_with(Default::default) - .extend(prospective_extrinsics); - } - } - } - } - } - - /// Consume `OverlayedChanges` and take committed set. - /// - /// Panics: - /// Will panic if there are any uncommitted prospective changes. - pub fn into_committed(self) -> ( - impl Iterator, Option>)>, - impl Iterator, impl Iterator, Option>)>)>, - ){ - assert!(self.prospective.is_empty()); - (self.committed.top.into_iter().map(|(k, v)| (k, v.value)), - self.committed.children.into_iter() - .map(|(sk, v)| (sk, v.into_iter().map(|(k, v)| (k, v.value))))) - } - - /// Inserts storage entry responsible for current extrinsic index. - #[cfg(test)] - pub(crate) fn set_extrinsic_index(&mut self, extrinsic_index: u32) { - use codec::Encode; - self.prospective.top.insert(EXTRINSIC_INDEX.to_vec(), OverlayedValue { - value: Some(extrinsic_index.encode()), - extrinsics: None, - }); - } - - /// Returns current extrinsic index to use in changes trie construction. - /// None is returned if it is not set or changes trie config is not set. - /// Persistent value (from the backend) can be ignored because runtime must - /// set this index before first and unset after last extrinsic is executied. - /// Changes that are made outside of extrinsics, are marked with - /// `NO_EXTRINSIC_INDEX` index. - fn extrinsic_index(&self) -> Option { - match self.changes_trie_config.is_some() { - true => Some( - self.storage(EXTRINSIC_INDEX) - .and_then(|idx| idx.and_then(|idx| Decode::decode(&mut &*idx).ok())) - .unwrap_or(NO_EXTRINSIC_INDEX)), - false => None, - } - } -} - -#[cfg(test)] -impl From>> for OverlayedValue { - fn from(value: Option>) -> OverlayedValue { - OverlayedValue { value, ..Default::default() } - } -} - -#[cfg(test)] -mod tests { - use hex_literal::hex; - use primitives::{ - Blake2Hasher, H256, traits::Externalities, storage::well_known_keys::EXTRINSIC_INDEX, - }; - use crate::backend::InMemory; - use crate::changes_trie::InMemoryStorage as InMemoryChangesTrieStorage; - use crate::ext::Ext; - use super::*; - - fn strip_extrinsic_index(map: &HashMap, OverlayedValue>) -> HashMap, OverlayedValue> { - let mut clone = map.clone(); - clone.remove(&EXTRINSIC_INDEX.to_vec()); - clone - } - - #[test] - fn overlayed_storage_works() { - let mut overlayed = OverlayedChanges::default(); - - let key = vec![42, 69, 169, 142]; - - assert!(overlayed.storage(&key).is_none()); - - overlayed.set_storage(key.clone(), Some(vec![1, 2, 3])); - assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..])); - - overlayed.commit_prospective(); - assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..])); - - overlayed.set_storage(key.clone(), Some(vec![])); - assert_eq!(overlayed.storage(&key).unwrap(), Some(&[][..])); - - overlayed.set_storage(key.clone(), None); - assert!(overlayed.storage(&key).unwrap().is_none()); - - overlayed.discard_prospective(); - assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..])); - - overlayed.set_storage(key.clone(), None); - overlayed.commit_prospective(); - assert!(overlayed.storage(&key).unwrap().is_none()); - } - - #[test] - fn overlayed_storage_root_works() { - let initial: HashMap<_, _> = vec![ - (b"doe".to_vec(), b"reindeer".to_vec()), - (b"dog".to_vec(), b"puppyXXX".to_vec()), - (b"dogglesworth".to_vec(), b"catXXX".to_vec()), - (b"doug".to_vec(), b"notadog".to_vec()), - ].into_iter().collect(); - let backend = InMemory::::from(initial); - let mut overlay = OverlayedChanges { - committed: vec![ - (b"dog".to_vec(), Some(b"puppy".to_vec()).into()), - (b"dogglesworth".to_vec(), Some(b"catYYY".to_vec()).into()), - (b"doug".to_vec(), Some(vec![]).into()), - ].into_iter().collect(), - prospective: vec![ - (b"dogglesworth".to_vec(), Some(b"cat".to_vec()).into()), - (b"doug".to_vec(), None.into()), - ].into_iter().collect(), - ..Default::default() - }; - - let changes_trie_storage = InMemoryChangesTrieStorage::::new(); - let mut ext = Ext::new( - &mut overlay, - &backend, - Some(&changes_trie_storage), - None, - ); - const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa"); - - assert_eq!(ext.storage_root(), H256::from(ROOT)); - } - - #[test] - fn changes_trie_configuration_is_saved() { - let mut overlay = OverlayedChanges::default(); - assert!(overlay.changes_trie_config.is_none()); - assert_eq!( - overlay.set_changes_trie_config( - ChangesTrieConfig { digest_interval: 4, digest_levels: 1, }, - ), - true, - ); - assert!(overlay.changes_trie_config.is_some()); - } - - #[test] - fn changes_trie_configuration_is_saved_twice() { - let mut overlay = OverlayedChanges::default(); - assert!(overlay.changes_trie_config.is_none()); - assert_eq!(overlay.set_changes_trie_config(ChangesTrieConfig { - digest_interval: 4, digest_levels: 1, - }), true); - overlay.set_extrinsic_index(0); - overlay.set_storage(vec![1], Some(vec![2])); - assert_eq!(overlay.set_changes_trie_config(ChangesTrieConfig { - digest_interval: 4, digest_levels: 1, - }), true); - assert_eq!( - strip_extrinsic_index(&overlay.prospective.top), - vec![ - (vec![1], OverlayedValue { value: Some(vec![2]), extrinsics: Some(vec![0].into_iter().collect()) }), - ].into_iter().collect(), - ); - } - - #[test] - fn panics_when_trying_to_save_different_changes_trie_configuration() { - let mut overlay = OverlayedChanges::default(); - assert_eq!(overlay.set_changes_trie_config(ChangesTrieConfig { - digest_interval: 4, digest_levels: 1, - }), true); - assert_eq!(overlay.set_changes_trie_config(ChangesTrieConfig { - digest_interval: 2, digest_levels: 1, - }), false); - } - - #[test] - fn extrinsic_changes_are_collected() { - let mut overlay = OverlayedChanges::default(); - let _ = overlay.set_changes_trie_config(ChangesTrieConfig { - digest_interval: 4, digest_levels: 1, - }); - - overlay.set_storage(vec![100], Some(vec![101])); - - overlay.set_extrinsic_index(0); - overlay.set_storage(vec![1], Some(vec![2])); - - overlay.set_extrinsic_index(1); - overlay.set_storage(vec![3], Some(vec![4])); - - overlay.set_extrinsic_index(2); - overlay.set_storage(vec![1], Some(vec![6])); - - assert_eq!(strip_extrinsic_index(&overlay.prospective.top), - vec![ - (vec![1], OverlayedValue { value: Some(vec![6]), extrinsics: Some(vec![0, 2].into_iter().collect()) }), - (vec![3], OverlayedValue { value: Some(vec![4]), extrinsics: Some(vec![1].into_iter().collect()) }), - (vec![100], OverlayedValue { value: Some(vec![101]), extrinsics: Some(vec![NO_EXTRINSIC_INDEX].into_iter().collect()) }), - ].into_iter().collect()); - - overlay.commit_prospective(); - - overlay.set_extrinsic_index(3); - overlay.set_storage(vec![3], Some(vec![7])); - - overlay.set_extrinsic_index(4); - overlay.set_storage(vec![1], Some(vec![8])); - - assert_eq!(strip_extrinsic_index(&overlay.committed.top), - vec![ - (vec![1], OverlayedValue { value: Some(vec![6]), extrinsics: Some(vec![0, 2].into_iter().collect()) }), - (vec![3], OverlayedValue { value: Some(vec![4]), extrinsics: Some(vec![1].into_iter().collect()) }), - (vec![100], OverlayedValue { value: Some(vec![101]), extrinsics: Some(vec![NO_EXTRINSIC_INDEX].into_iter().collect()) }), - ].into_iter().collect()); - - assert_eq!(strip_extrinsic_index(&overlay.prospective.top), - vec![ - (vec![1], OverlayedValue { value: Some(vec![8]), extrinsics: Some(vec![4].into_iter().collect()) }), - (vec![3], OverlayedValue { value: Some(vec![7]), extrinsics: Some(vec![3].into_iter().collect()) }), - ].into_iter().collect()); - - overlay.commit_prospective(); - - assert_eq!(strip_extrinsic_index(&overlay.committed.top), - vec![ - (vec![1], OverlayedValue { value: Some(vec![8]), extrinsics: Some(vec![0, 2, 4].into_iter().collect()) }), - (vec![3], OverlayedValue { value: Some(vec![7]), extrinsics: Some(vec![1, 3].into_iter().collect()) }), - (vec![100], OverlayedValue { value: Some(vec![101]), extrinsics: Some(vec![NO_EXTRINSIC_INDEX].into_iter().collect()) }), - ].into_iter().collect()); - - assert_eq!(overlay.prospective, - Default::default()); - } -} diff --git a/core/state-machine/src/proving_backend.rs b/core/state-machine/src/proving_backend.rs deleted file mode 100644 index c6c4ef1ec8c26..0000000000000 --- a/core/state-machine/src/proving_backend.rs +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Proving state machine backend. - -use std::{cell::RefCell, rc::Rc}; -use log::debug; -use hash_db::{Hasher, HashDB, EMPTY_PREFIX}; -use trie::{ - MemoryDB, PrefixedMemoryDB, default_child_trie_root, - read_trie_value_with, read_child_trie_value_with, record_all_keys -}; -pub use trie::Recorder; -pub use trie::trie_types::{Layout, TrieError}; -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. -pub struct ProvingBackendEssence<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { - pub(crate) backend: &'a TrieBackendEssence, - pub(crate) proof_recorder: &'a mut Recorder, -} - -impl<'a, S, H> ProvingBackendEssence<'a, S, H> - where - S: TrieBackendStorage, - H: Hasher, -{ - pub fn storage(&mut self, key: &[u8]) -> Result>, String> { - let mut read_overlay = S::Overlay::default(); - let eph = Ephemeral::new( - self.backend.backend_storage(), - &mut read_overlay, - ); - - let map_e = |e| format!("Trie lookup error: {}", e); - - read_trie_value_with::, _, Ephemeral>( - &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> { - let root = self.storage(storage_key)? - .unwrap_or(default_child_trie_root::>(storage_key)); - - let mut read_overlay = S::Overlay::default(); - let eph = Ephemeral::new( - self.backend.backend_storage(), - &mut read_overlay, - ); - - let map_e = |e| format!("Trie lookup error: {}", e); - - read_child_trie_value_with::, _, _>( - storage_key, - &eph, - &root, - key, - &mut *self.proof_recorder - ).map_err(map_e) - } - - pub fn record_all_keys(&mut self) { - let mut read_overlay = S::Overlay::default(); - let eph = Ephemeral::new( - self.backend.backend_storage(), - &mut read_overlay, - ); - - let mut iter = move || -> Result<(), Box>> { - let root = self.backend.root(); - record_all_keys::, _>(&eph, root, &mut *self.proof_recorder) - }; - - if let Err(e) = iter() { - debug!(target: "trie", "Error while recording all keys: {}", e); - } - } -} - -/// Patricia trie-based backend which also tracks all touched storage trie values. -/// These can be sent to remote node and used as a proof of execution. -pub struct ProvingBackend<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { - backend: &'a TrieBackend, - proof_recorder: Rc>>, -} - -impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> ProvingBackend<'a, S, H> { - /// Create new proving backend. - pub fn new(backend: &'a TrieBackend) -> Self { - ProvingBackend { - backend, - proof_recorder: Rc::new(RefCell::new(Recorder::new())), - } - } - - /// Create new proving backend with the given recorder. - pub fn new_with_recorder( - backend: &'a TrieBackend, - proof_recorder: Rc>>, - ) -> Self { - ProvingBackend { - backend, - proof_recorder, - } - } - - /// Consume the backend, extracting the gathered proof in lexicographical order by value. - pub fn extract_proof(&self) -> Vec> { - self.proof_recorder - .borrow_mut() - .drain() - .into_iter() - .map(|n| n.data.to_vec()) - .collect() - } -} - -impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> std::fmt::Debug for ProvingBackend<'a, S, H> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "ProvingBackend") - } -} - -impl<'a, S, H> Backend for ProvingBackend<'a, S, H> - where - S: 'a + TrieBackendStorage, - H: 'a + Hasher, - H::Out: Ord, -{ - type Error = String; - type Transaction = S::Overlay; - type TrieBackendStorage = PrefixedMemoryDB; - - fn storage(&self, key: &[u8]) -> Result>, Self::Error> { - ProvingBackendEssence { - backend: self.backend.essence(), - proof_recorder: &mut *self.proof_recorder.try_borrow_mut() - .expect("only fails when already borrowed; storage() is non-reentrant; qed"), - }.storage(key) - } - - fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { - ProvingBackendEssence { - backend: self.backend.essence(), - proof_recorder: &mut *self.proof_recorder.try_borrow_mut() - .expect("only fails when already borrowed; child_storage() is non-reentrant; qed"), - }.child_storage(storage_key, key) - } - - fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { - self.backend.for_keys_in_child_storage(storage_key, f) - } - - fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { - self.backend.for_keys_with_prefix(prefix, f) - } - - fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { - self.backend.for_key_values_with_prefix(prefix, f) - } - - fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { - self.backend.for_child_keys_with_prefix(storage_key, prefix, f) - } - - fn pairs(&self) -> Vec<(Vec, Vec)> { - self.backend.pairs() - } - - fn keys(&self, prefix: &[u8]) -> Vec> { - self.backend.keys(prefix) - } - - fn child_keys(&self, child_storage_key: &[u8], prefix: &[u8]) -> Vec> { - self.backend.child_keys(child_storage_key, prefix) - } - - fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) - where I: IntoIterator, Option>)> - { - self.backend.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.backend.child_storage_root(storage_key, delta) - } -} - -/// Create proof check backend. -pub fn create_proof_check_backend( - root: H::Out, - proof: Vec> -) -> Result, H>, Box> -where - H: Hasher, -{ - let db = create_proof_check_backend_storage(proof); - - if db.contains(&root, EMPTY_PREFIX) { - Ok(TrieBackend::new(db, root)) - } else { - Err(Box::new(ExecutionError::InvalidProof)) - } -} - -/// Create in-memory storage of proof check backend. -pub fn create_proof_check_backend_storage( - proof: Vec> -) -> MemoryDB -where - H: Hasher, -{ - let mut db = MemoryDB::default(); - for item in proof { - db.insert(EMPTY_PREFIX, &item); - } - db -} - -#[cfg(test)] -mod tests { - use crate::backend::{InMemory}; - use crate::trie_backend::tests::test_trie; - use super::*; - use primitives::{Blake2Hasher, storage::ChildStorageKey}; - - fn test_proving<'a>( - trie_backend: &'a TrieBackend,Blake2Hasher>, - ) -> ProvingBackend<'a, PrefixedMemoryDB, Blake2Hasher> { - ProvingBackend::new(trie_backend) - } - - #[test] - fn proof_is_empty_until_value_is_read() { - let trie_backend = test_trie(); - assert!(test_proving(&trie_backend).extract_proof().is_empty()); - } - - #[test] - fn proof_is_non_empty_after_value_is_read() { - let trie_backend = test_trie(); - let backend = test_proving(&trie_backend); - assert_eq!(backend.storage(b"key").unwrap(), Some(b"value".to_vec())); - assert!(!backend.extract_proof().is_empty()); - } - - #[test] - fn proof_is_invalid_when_does_not_contains_root() { - use primitives::H256; - assert!(create_proof_check_backend::(H256::from_low_u64_be(1), vec![]).is_err()); - } - - #[test] - fn passes_throgh_backend_calls() { - let trie_backend = test_trie(); - let proving_backend = test_proving(&trie_backend); - assert_eq!(trie_backend.storage(b"key").unwrap(), proving_backend.storage(b"key").unwrap()); - assert_eq!(trie_backend.pairs(), proving_backend.pairs()); - - let (trie_root, mut trie_mdb) = trie_backend.storage_root(::std::iter::empty()); - let (proving_root, mut proving_mdb) = proving_backend.storage_root(::std::iter::empty()); - assert_eq!(trie_root, proving_root); - assert_eq!(trie_mdb.drain(), proving_mdb.drain()); - } - - #[test] - fn proof_recorded_and_checked() { - let contents = (0..64).map(|i| (None, vec![i], Some(vec![i]))).collect::>(); - let in_memory = InMemory::::default(); - let mut in_memory = in_memory.update(contents); - let in_memory_root = in_memory.storage_root(::std::iter::empty()).0; - (0..64).for_each(|i| assert_eq!(in_memory.storage(&[i]).unwrap().unwrap(), vec![i])); - - let trie = in_memory.as_trie_backend().unwrap(); - let trie_root = trie.storage_root(::std::iter::empty()).0; - assert_eq!(in_memory_root, trie_root); - (0..64).for_each(|i| assert_eq!(trie.storage(&[i]).unwrap().unwrap(), vec![i])); - - let proving = ProvingBackend::new(trie); - assert_eq!(proving.storage(&[42]).unwrap().unwrap(), vec![42]); - - let proof = proving.extract_proof(); - - let proof_check = create_proof_check_backend::(in_memory_root.into(), proof).unwrap(); - assert_eq!(proof_check.storage(&[42]).unwrap().unwrap(), vec![42]); - } - - #[test] - fn proof_recorded_and_checked_with_child() { - let subtrie1 = ChildStorageKey::from_slice(b":child_storage:default:sub1").unwrap(); - let subtrie2 = ChildStorageKey::from_slice(b":child_storage:default:sub2").unwrap(); - let own1 = subtrie1.into_owned(); - let own2 = subtrie2.into_owned(); - let contents = (0..64).map(|i| (None, vec![i], Some(vec![i]))) - .chain((28..65).map(|i| (Some(own1.clone()), vec![i], Some(vec![i])))) - .chain((10..15).map(|i| (Some(own2.clone()), vec![i], Some(vec![i])))) - .collect::>(); - let in_memory = InMemory::::default(); - let mut in_memory = in_memory.update(contents); - let in_memory_root = in_memory.full_storage_root::<_, Vec<_>, _>( - ::std::iter::empty(), - in_memory.child_storage_keys().map(|k|(k.to_vec(), Vec::new())) - ).0; - (0..64).for_each(|i| assert_eq!( - in_memory.storage(&[i]).unwrap().unwrap(), - vec![i] - )); - (28..65).for_each(|i| assert_eq!( - in_memory.child_storage(&own1[..], &[i]).unwrap().unwrap(), - vec![i] - )); - (10..15).for_each(|i| assert_eq!( - in_memory.child_storage(&own2[..], &[i]).unwrap().unwrap(), - vec![i] - )); - - let trie = in_memory.as_trie_backend().unwrap(); - let trie_root = trie.storage_root(::std::iter::empty()).0; - assert_eq!(in_memory_root, trie_root); - (0..64).for_each(|i| assert_eq!( - trie.storage(&[i]).unwrap().unwrap(), - vec![i] - )); - - let proving = ProvingBackend::new(trie); - assert_eq!(proving.storage(&[42]).unwrap().unwrap(), vec![42]); - - let proof = proving.extract_proof(); - - let proof_check = create_proof_check_backend::( - in_memory_root.into(), - proof - ).unwrap(); - assert!(proof_check.storage(&[0]).is_err()); - assert_eq!(proof_check.storage(&[42]).unwrap().unwrap(), vec![42]); - // note that it is include in root because proof close - assert_eq!(proof_check.storage(&[41]).unwrap().unwrap(), vec![41]); - assert_eq!(proof_check.storage(&[64]).unwrap(), None); - - let proving = ProvingBackend::new(trie); - assert_eq!(proving.child_storage(&own1[..], &[64]), Ok(Some(vec![64]))); - - let proof = proving.extract_proof(); - let proof_check = create_proof_check_backend::( - in_memory_root.into(), - proof - ).unwrap(); - assert_eq!( - proof_check.child_storage(&own1[..], &[64]).unwrap().unwrap(), - vec![64] - ); - } - -} diff --git a/core/state-machine/src/testing.rs b/core/state-machine/src/testing.rs deleted file mode 100644 index 16ff62020b594..0000000000000 --- a/core/state-machine/src/testing.rs +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test implementation for Externalities. - -use std::{collections::HashMap, any::{Any, TypeId}}; -use hash_db::Hasher; -use crate::{ - backend::{InMemory, Backend}, OverlayedChanges, - changes_trie::{ - InMemoryStorage as ChangesTrieInMemoryStorage, - BlockNumber as ChangesTrieBlockNumber, - }, - ext::Ext, -}; -use primitives::{ - storage::{ - well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES, is_child_storage_key} - }, - hash::H256, Blake2Hasher, -}; -use codec::Encode; -use externalities::{Extensions, Extension}; - -type StorageTuple = (HashMap, Vec>, HashMap, HashMap, Vec>>); - -/// Simple HashMap-based Externalities impl. -pub struct TestExternalities=Blake2Hasher, N: ChangesTrieBlockNumber=u64> { - overlay: OverlayedChanges, - backend: InMemory, - changes_trie_storage: ChangesTrieInMemoryStorage, - extensions: Extensions, -} - -impl, N: ChangesTrieBlockNumber> TestExternalities { - - /// Get externalities implementation. - pub fn ext(&mut self) -> Ext, ChangesTrieInMemoryStorage> { - Ext::new( - &mut self.overlay, - &self.backend, - Some(&self.changes_trie_storage), - Some(&mut self.extensions), - ) - } - - /// Create a new instance of `TestExternalities` with storage. - pub fn new(storage: StorageTuple) -> Self { - Self::new_with_code(&[], storage) - } - - /// Create a new instance of `TestExternalities` with code and storage. - pub fn new_with_code(code: &[u8], mut storage: StorageTuple) -> Self { - let mut overlay = OverlayedChanges::default(); - - assert!(storage.0.keys().all(|key| !is_child_storage_key(key))); - assert!(storage.1.keys().all(|key| is_child_storage_key(key))); - - super::set_changes_trie_config( - &mut overlay, - storage.0.get(&CHANGES_TRIE_CONFIG.to_vec()).cloned(), - false, - ).expect("changes trie configuration is correct in test env; qed"); - - storage.0.insert(HEAP_PAGES.to_vec(), 8u64.encode()); - storage.0.insert(CODE.to_vec(), code.to_vec()); - - let backend: HashMap<_, _> = storage.1.into_iter() - .map(|(keyspace, map)| (Some(keyspace), map)) - .chain(Some((None, storage.0)).into_iter()) - .collect(); - - TestExternalities { - overlay, - changes_trie_storage: ChangesTrieInMemoryStorage::new(), - backend: backend.into(), - extensions: Default::default(), - } - } - - /// Insert key/value into backend - pub fn insert(&mut self, k: Vec, v: Vec) { - self.backend = self.backend.update(vec![(None, k, Some(v))]); - } - - /// Registers the given extension for this instance. - pub fn register_extension(&mut self, ext: E) { - self.extensions.register(ext); - } - - /// Get mutable reference to changes trie storage. - pub fn changes_trie_storage(&mut self) -> &mut ChangesTrieInMemoryStorage { - &mut self.changes_trie_storage - } - - /// Return a new backend with all pending value. - pub fn commit_all(&self) -> InMemory { - let top = self.overlay.committed.top.clone().into_iter() - .chain(self.overlay.prospective.top.clone().into_iter()) - .map(|(k, v)| (None, k, v.value)); - - let children = self.overlay.committed.children.clone().into_iter() - .chain(self.overlay.prospective.children.clone().into_iter()) - .flat_map(|(keyspace, map)| { - map.into_iter() - .map(|(k, v)| (Some(keyspace.clone()), k, v.value)) - .collect::>() - }); - - self.backend.update(top.chain(children).collect()) - } - - /// Execute the given closure while `self` is set as externalities. - /// - /// Returns the result of the given closure. - pub fn execute_with(&mut self, execute: impl FnOnce() -> R) -> R { - let mut ext = self.ext(); - externalities::set_and_run_with_externalities(&mut ext, execute) - } -} - -impl, N: ChangesTrieBlockNumber> std::fmt::Debug for TestExternalities { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "overlay: {:?}\nbackend: {:?}", self.overlay, self.backend.pairs()) - } -} - -impl, N: ChangesTrieBlockNumber> PartialEq for TestExternalities { - /// This doesn't test if they are in the same state, only if they contains the - /// same data at this state - fn eq(&self, other: &TestExternalities) -> bool { - self.commit_all().eq(&other.commit_all()) - } -} - -impl, N: ChangesTrieBlockNumber> Default for TestExternalities { - fn default() -> Self { Self::new(Default::default()) } -} - -impl, N: ChangesTrieBlockNumber> From for TestExternalities { - fn from(storage: StorageTuple) -> Self { - Self::new(storage) - } -} - -impl externalities::ExtensionStore for TestExternalities where - H: Hasher, - N: ChangesTrieBlockNumber, -{ - fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> { - self.extensions.get_mut(type_id) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use primitives::traits::Externalities; - use hex_literal::hex; - - #[test] - fn commit_should_work() { - let mut ext = TestExternalities::::default(); - let mut ext = ext.ext(); - ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); - ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); - ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); - const ROOT: [u8; 32] = hex!("2a340d3dfd52f5992c6b117e9e45f479e6da5afffafeb26ab619cf137a95aeb8"); - assert_eq!(ext.storage_root(), H256::from(ROOT)); - } - - #[test] - fn set_and_retrieve_code() { - let mut ext = TestExternalities::::default(); - let mut ext = ext.ext(); - - 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_essence.rs b/core/state-machine/src/trie_backend_essence.rs deleted file mode 100644 index 5a5431963448c..0000000000000 --- a/core/state-machine/src/trie_backend_essence.rs +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Trie-based state machine backend essence used to read values -//! from storage. - -use std::ops::Deref; -use std::sync::Arc; -use log::{debug, warn}; -use hash_db::{self, Hasher, EMPTY_PREFIX, Prefix}; -use trie::{Trie, MemoryDB, PrefixedMemoryDB, DBValue, - default_child_trie_root, read_trie_value, read_child_trie_value, - for_keys_in_child_trie}; -use trie::trie_types::{TrieDB, TrieError, Layout}; -use crate::backend::Consolidate; - -/// Patricia trie-based storage trait. -pub trait Storage: Send + Sync { - /// Get a trie node. - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String>; -} - -/// Patricia trie-based pairs storage essence. -pub struct TrieBackendEssence, H: Hasher> { - storage: S, - root: H::Out, -} - -impl, H: Hasher> TrieBackendEssence { - /// Create new trie-based backend. - pub fn new(storage: S, root: H::Out) -> Self { - TrieBackendEssence { - storage, - root, - } - } - - /// Get backend storage reference. - pub fn backend_storage(&self) -> &S { - &self.storage - } - - /// Get trie root. - pub fn root(&self) -> &H::Out { - &self.root - } - - /// Consumes self and returns underlying storage. - pub fn into_storage(self) -> S { - self.storage - } - - /// Get the value of storage at given key. - pub fn storage(&self, key: &[u8]) -> Result>, String> { - let mut read_overlay = S::Overlay::default(); - let eph = Ephemeral { - storage: &self.storage, - overlay: &mut read_overlay, - }; - - let map_e = |e| format!("Trie lookup error: {}", e); - - read_trie_value::, _>(&eph, &self.root, key).map_err(map_e) - } - - /// Get the value of child storage at given key. - pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, String> { - let root = self.storage(storage_key)? - .unwrap_or(default_child_trie_root::>(storage_key)); - - let mut read_overlay = S::Overlay::default(); - let eph = Ephemeral { - storage: &self.storage, - overlay: &mut read_overlay, - }; - - let map_e = |e| format!("Trie lookup error: {}", e); - - read_child_trie_value::, _>(storage_key, &eph, &root, key).map_err(map_e) - } - - /// Retrieve all entries keys of child storage and call `f` for each of those keys. - pub fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { - let root = match self.storage(storage_key) { - Ok(v) => v.unwrap_or(default_child_trie_root::>(storage_key)), - Err(e) => { - debug!(target: "trie", "Error while iterating child storage: {}", e); - return; - } - }; - - let mut read_overlay = S::Overlay::default(); - let eph = Ephemeral { - storage: &self.storage, - overlay: &mut read_overlay, - }; - - if let Err(e) = for_keys_in_child_trie::, _, Ephemeral>( - storage_key, - &eph, - &root, - f, - ) { - debug!(target: "trie", "Error while iterating child storage: {}", e); - } - } - - /// Execute given closure for all keys starting with prefix. - pub fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], mut f: F) { - let root_vec = match self.storage(storage_key) { - Ok(v) => v.unwrap_or(default_child_trie_root::>(storage_key)), - Err(e) => { - debug!(target: "trie", "Error while iterating child storage: {}", e); - return; - } - }; - let mut root = H::Out::default(); - root.as_mut().copy_from_slice(&root_vec); - - self.keys_values_with_prefix_inner(&root, prefix, |k, _v| f(k)) - } - - /// Execute given closure for all keys starting with prefix. - pub fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { - self.keys_values_with_prefix_inner(&self.root, prefix, |k, _v| f(k)) - } - - - fn keys_values_with_prefix_inner( - &self, - root: &H::Out, - prefix: &[u8], - mut f: F, - ) { - let mut read_overlay = S::Overlay::default(); - let eph = Ephemeral { - storage: &self.storage, - overlay: &mut read_overlay, - }; - - let mut iter = move || -> Result<(), Box>> { - let trie = TrieDB::::new(&eph, root)?; - let mut iter = trie.iter()?; - - iter.seek(prefix)?; - - for x in iter { - let (key, value) = x?; - - if !key.starts_with(prefix) { - break; - } - - f(&key, &value); - } - - Ok(()) - }; - - if let Err(e) = iter() { - debug!(target: "trie", "Error while iterating by prefix: {}", e); - } - } - - /// Execute given closure for all key and values starting with prefix. - pub fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { - self.keys_values_with_prefix_inner(&self.root, prefix, f) - } - -} - -pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { - storage: &'a S, - overlay: &'a mut S::Overlay, -} - -impl<'a, - S: 'a + TrieBackendStorage, - H: 'a + Hasher -> hash_db::AsPlainDB - for Ephemeral<'a, S, H> -{ - fn as_plain_db<'b>(&'b self) -> &'b (dyn hash_db::PlainDB + 'b) { self } - fn as_plain_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::PlainDB + 'b) { self } -} - -impl<'a, - S: 'a + TrieBackendStorage, - H: 'a + Hasher -> hash_db::AsHashDB - for Ephemeral<'a, S, H> -{ - fn as_hash_db<'b>(&'b self) -> &'b (dyn hash_db::HashDB + 'b) { self } - fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB + 'b) { self } -} - -impl<'a, S: TrieBackendStorage, H: Hasher> Ephemeral<'a, S, H> { - pub fn new(storage: &'a S, overlay: &'a mut S::Overlay) -> Self { - Ephemeral { - storage, - overlay, - } - } -} - -impl<'a, - S: 'a + TrieBackendStorage, - H: Hasher -> hash_db::PlainDB - for Ephemeral<'a, S, H> -{ - fn get(&self, key: &H::Out) -> Option { - if let Some(val) = hash_db::HashDB::get(self.overlay, key, EMPTY_PREFIX) { - Some(val) - } else { - match self.storage.get(&key, EMPTY_PREFIX) { - Ok(x) => x, - Err(e) => { - warn!(target: "trie", "Failed to read from DB: {}", e); - None - }, - } - } - } - - fn contains(&self, key: &H::Out) -> bool { - hash_db::HashDB::get(self, key, EMPTY_PREFIX).is_some() - } - - fn emplace(&mut self, key: H::Out, value: DBValue) { - hash_db::HashDB::emplace(self.overlay, key, EMPTY_PREFIX, value) - } - - fn remove(&mut self, key: &H::Out) { - hash_db::HashDB::remove(self.overlay, key, EMPTY_PREFIX) - } -} - -impl<'a, - S: 'a + TrieBackendStorage, - H: Hasher -> hash_db::PlainDBRef - for Ephemeral<'a, S, H> -{ - 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> -{ - fn get(&self, key: &H::Out, prefix: Prefix) -> Option { - if let Some(val) = hash_db::HashDB::get(self.overlay, key, prefix) { - Some(val) - } else { - match self.storage.get(&key, prefix) { - Ok(x) => x, - Err(e) => { - warn!(target: "trie", "Failed to read from DB: {}", e); - None - }, - } - } - } - - fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { - hash_db::HashDB::get(self, key, prefix).is_some() - } - - fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out { - hash_db::HashDB::insert(self.overlay, prefix, value) - } - - fn emplace(&mut self, key: H::Out, prefix: Prefix, value: DBValue) { - hash_db::HashDB::emplace(self.overlay, key, prefix, value) - } - - fn remove(&mut self, key: &H::Out, prefix: Prefix) { - hash_db::HashDB::remove(self.overlay, key, prefix) - } -} - -impl<'a, - S: 'a + TrieBackendStorage, - H: Hasher -> hash_db::HashDBRef - for Ephemeral<'a, S, H> -{ - fn get(&self, key: &H::Out, prefix: Prefix) -> Option { hash_db::HashDB::get(self, key, prefix) } - fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { hash_db::HashDB::contains(self, key, prefix) } -} - -/// Key-value pairs storage that is used by trie backend essence. -pub trait TrieBackendStorage: Send + Sync { - /// Type of in-memory overlay. - type Overlay: hash_db::HashDB + Default + Consolidate; - /// Get the value stored at key. - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String>; -} - -// This implementation is used by normal storage trie clients. -impl TrieBackendStorage for Arc> { - type Overlay = PrefixedMemoryDB; - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - Storage::::get(self.deref(), key, prefix) - } -} - -// This implementation is used by test storage trie clients. -impl TrieBackendStorage for PrefixedMemoryDB { - type Overlay = PrefixedMemoryDB; - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - Ok(hash_db::HashDB::get(self, key, prefix)) - } -} - -impl TrieBackendStorage for MemoryDB { - type Overlay = MemoryDB; - - fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { - Ok(hash_db::HashDB::get(self, key, prefix)) - } -} diff --git a/core/telemetry/Cargo.toml b/core/telemetry/Cargo.toml deleted file mode 100644 index 90150ad7490df..0000000000000 --- a/core/telemetry/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "substrate-telemetry" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Telemetry utils" -edition = "2018" - -[dependencies] -bytes = "0.4.12" -parking_lot = "0.9.0" -futures01 = { package = "futures", version = "0.1" } -futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } -futures-timer = "0.4.0" -libp2p = { version = "0.12.0", default-features = false, features = ["libp2p-websocket"] } -log = "0.4.8" -rand = "0.7.2" -serde = { version = "1.0.101", features = ["derive"] } -slog = { version = "2.5.2", features = ["nested-values"] } -# TODO: we're using slog-async just to be able to clone records; See https://github.com/slog-rs/slog/issues/221, -# https://github.com/paritytech/substrate/issues/2823 and https://github.com/paritytech/substrate/issues/3260 -slog-async = { git = "https://github.com/paritytech/slog-async", features = ["nested-values"] } -slog-json = { version = "2.3.0", features = ["nested-values"] } -slog-scope = "4.1.2" -tokio-io = "0.1.12" -void = "1.0.2" diff --git a/core/telemetry/src/lib.rs b/core/telemetry/src/lib.rs deleted file mode 100644 index 768fc2df84e6a..0000000000000 --- a/core/telemetry/src/lib.rs +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Telemetry utilities. -//! -//! Calling `init_telemetry` registers a global `slog` logger using `slog_scope::set_global_logger`. -//! After that, calling `slog_scope::with_logger` will return a logger that sends information to -//! the telemetry endpoints. The `telemetry!` macro is a short-cut for calling -//! `slog_scope::with_logger` followed with `slog_log!`. -//! -//! Note that you are supposed to only ever use `telemetry!` and not `slog_scope::with_logger` at -//! the moment. Substate may eventually be reworked to get proper `slog` support, including sending -//! information to the telemetry. -//! -//! The [`Telemetry`] struct implements `Stream` and must be polled regularly (or sent to a -//! background thread/task) in order for the telemetry to properly function. Dropping the object -//! will also deregister the global logger and replace it with a logger that discards messages. -//! The `Stream` generates [`TelemetryEvent`]s. -//! -//! > **Note**: Cloning the [`Telemetry`] and polling from multiple clones has an unspecified behaviour. -//! -//! # Example -//! -//! ```no_run -//! use futures::prelude::*; -//! -//! let telemetry = substrate_telemetry::init_telemetry(substrate_telemetry::TelemetryConfig { -//! endpoints: substrate_telemetry::TelemetryEndpoints::new(vec![ -//! // The `0` is the maximum verbosity level of messages to send to this endpoint. -//! ("wss://example.com".into(), 0) -//! ]), -//! // Can be used to pass an external implementation of WebSockets. -//! wasm_external_transport: None, -//! }); -//! -//! // The `telemetry` object implements `Stream` and must be processed. -//! std::thread::spawn(move || { -//! futures::executor::block_on(telemetry.for_each(|_| future::ready(()))); -//! }); -//! -//! // Sends a message on the telemetry. -//! substrate_telemetry::telemetry!(substrate_telemetry::SUBSTRATE_INFO; "test"; -//! "foo" => "bar", -//! ) -//! ``` -//! - -use futures::{prelude::*, channel::mpsc}; -use libp2p::{Multiaddr, wasm_ext}; -use log::warn; -use parking_lot::Mutex; -use serde::{Serialize, Deserialize}; -use std::{pin::Pin, sync::Arc, task::{Context, Poll}, time::{Duration, Instant}}; - -pub use slog_scope::with_logger; -pub use slog; - -mod worker; - -/// Configuration for telemetry. -pub struct TelemetryConfig { - /// Collection of telemetry WebSocket servers with a corresponding verbosity level. - pub endpoints: TelemetryEndpoints, - - /// Optional external implementation of a libp2p transport. Used in WASM contexts where we need - /// some binding between the networking provided by the operating system or environment and - /// libp2p. - /// - /// This parameter exists whatever the target platform is, but it is expected to be set to - /// `Some` only when compiling for WASM. - /// - /// > **Important**: Each individual call to `write` corresponds to one message. There is no - /// > internal buffering going on. In the context of WebSockets, each `write` - /// > must be one individual WebSockets frame. - pub wasm_external_transport: Option, -} - -/// List of telemetry servers we want to talk to. Contains the URL of the server, and the -/// maximum verbosity level. -/// -/// The URL string can be either a URL or a multiaddress. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub struct TelemetryEndpoints(Vec<(String, u8)>); - -impl TelemetryEndpoints { - pub fn new(endpoints: Vec<(String, u8)>) -> Self { - TelemetryEndpoints(endpoints) - } -} - -/// 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 = "1"; - -/// Telemetry object. Implements `Future` and must be polled regularly. -/// Contains an `Arc` and can be cloned and pass around. Only one clone needs to be polled -/// regularly and should be polled regularly. -/// Dropping all the clones unregisters the telemetry. -#[derive(Clone)] -pub struct Telemetry { - inner: Arc>, - /// Slog guard so that we don't get deregistered. - _guard: Arc, -} - -/// Behind the `Mutex` in `Telemetry`. -/// -/// Note that ideally we wouldn't have to make the `Telemetry` clonable, as that would remove the -/// need for a `Mutex`. However there is currently a weird hack in place in `substrate-service` -/// where we extract the telemetry registration so that it continues running during the shutdown -/// process. -struct TelemetryInner { - /// Worker for the telemetry. - worker: worker::TelemetryWorker, - /// Receives log entries for them to be dispatched to the worker. - receiver: mpsc::Receiver, -} - -/// Implements `slog::Drain`. -struct TelemetryDrain { - /// Sends log entries. - sender: std::panic::AssertUnwindSafe>, -} - -/// Initializes the telemetry. See the crate root documentation for more information. -/// -/// Please be careful to not call this function twice in the same program. The `slog` crate -/// doesn't provide any way of knowing whether a global logger has already been registered. -pub fn init_telemetry(config: TelemetryConfig) -> Telemetry { - // Build the list of telemetry endpoints. - let mut endpoints = Vec::new(); - for &(ref url, verbosity) in &config.endpoints.0 { - match url_to_multiaddr(url) { - Ok(addr) => endpoints.push((addr, verbosity)), - Err(err) => warn!(target: "telemetry", "Invalid telemetry URL {}: {}", url, err), - } - } - - let (sender, receiver) = mpsc::channel(16); - let guard = { - let logger = TelemetryDrain { sender: std::panic::AssertUnwindSafe(sender) }; - let root = slog::Logger::root(slog::Drain::fuse(logger), slog::o!()); - slog_scope::set_global_logger(root) - }; - - Telemetry { - inner: Arc::new(Mutex::new(TelemetryInner { - worker: worker::TelemetryWorker::new(endpoints, config.wasm_external_transport), - receiver, - })), - _guard: Arc::new(guard), - } -} - -/// Event generated when polling the worker. -#[derive(Debug)] -pub enum TelemetryEvent { - /// We have established a connection to one of the telemetry endpoint, either for the first - /// time or after having been disconnected earlier. - Connected, -} - -impl Stream for Telemetry { - type Item = TelemetryEvent; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - let before = Instant::now(); - - // Because the `Telemetry` is clonable, we need to put the actual fields behind a `Mutex`. - // However, the user is only ever supposed to poll from one instance of `Telemetry`, while - // the other instances are used only for RAII purposes. - // We assume that the user is following this advice and therefore that the `Mutex` is only - // ever locked once at a time. - let mut inner = match self.inner.try_lock() { - Some(l) => l, - None => { - warn!( - target: "telemetry", - "The telemetry seems to be polled multiple times simultaneously" - ); - // Returning `Pending` here means that we may never get polled again, but this is - // ok because we're in a situation where something else is actually currently doing - // the polling. - return Poll::Pending; - } - }; - - let mut has_connected = false; - - // The polling pattern is: poll the worker so that it processes its queue, then add one - // message from the receiver (if possible), then poll the worker again, and so on. - loop { - while let Poll::Ready(event) = inner.worker.poll(cx) { - // Right now we only have one possible event. This line is here in order to not - // forget to handle any possible new event type. - let worker::TelemetryWorkerEvent::Connected = event; - has_connected = true; - } - - if let Poll::Ready(Some(log_entry)) = Stream::poll_next(Pin::new(&mut inner.receiver), cx) { - log_entry.as_record_values(|rec, val| { let _ = inner.worker.log(rec, val); }); - } else { - break; - } - } - - if before.elapsed() > Duration::from_millis(200) { - warn!(target: "telemetry", "Polling the telemetry took more than 200ms"); - } - - if has_connected { - Poll::Ready(Some(TelemetryEvent::Connected)) - } else { - Poll::Pending - } - } -} - -impl slog::Drain for TelemetryDrain { - type Ok = (); - type Err = (); - - fn log(&self, record: &slog::Record, values: &slog::OwnedKVList) -> Result { - let before = Instant::now(); - - let serialized = slog_async::AsyncRecord::from(record, values); - // Note: interestingly, `try_send` requires a `&mut` because it modifies some internal value, while `clone()` - // is lock-free. - if let Err(err) = self.sender.clone().try_send(serialized) { - warn!(target: "telemetry", "Ignored telemetry message because of error on channel: {:?}", err); - } - - if before.elapsed() > Duration::from_millis(50) { - warn!(target: "telemetry", "Writing a telemetry log took more than 50ms"); - } - - Ok(()) - } -} - -/// Parses a WebSocket URL into a libp2p `Multiaddr`. -fn url_to_multiaddr(url: &str) -> Result { - // First, assume that we have a `Multiaddr`. - let parse_error = match url.parse() { - Ok(ma) => return Ok(ma), - Err(err) => err, - }; - - // If not, try the `ws://path/url` format. - if let Ok(ma) = libp2p::multiaddr::from_url(url) { - return Ok(ma) - } - - // If we have no clue about the format of that string, assume that we were expecting a - // `Multiaddr`. - Err(parse_error) -} - -/// 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 { - ( $a:expr; $b:expr; $( $t:tt )* ) => { - $crate::with_logger(|l| { - $crate::slog::slog_info!(l, #$a, $b; $($t)* ) - }) - } -} diff --git a/core/telemetry/src/worker.rs b/core/telemetry/src/worker.rs deleted file mode 100644 index 24a1de8ec4a31..0000000000000 --- a/core/telemetry/src/worker.rs +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Contains the object that makes the telemetry work. -//! -//! # Usage -//! -//! - Create a `TelemetryWorker` with `TelemetryWorker::new`. -//! - Send messages to the telemetry with `TelemetryWorker::send_message`. Messages will only be -//! sent to the appropriate targets. Messages may be ignored if the target happens to be -//! temporarily unreachable. -//! - You must appropriately poll the worker with `TelemetryWorker::poll`. Polling will/may produce -//! events indicating what happened since the latest polling. -//! - -use bytes::BytesMut; -use futures::compat::Compat01As03Sink; -use libp2p::{core::transport::OptionalTransport, core::ConnectedPoint, Multiaddr, Transport, wasm_ext}; -use log::{trace, warn, error}; -use slog::Drain; -use std::{io, pin::Pin, task::Context, task::Poll, time}; - -mod node; - -/// Timeout after which a connection attempt is considered failed. Includes the WebSocket HTTP -/// upgrading. -const CONNECT_TIMEOUT: time::Duration = time::Duration::from_secs(20); - -/// Event generated when polling the worker. -#[derive(Debug)] -pub enum TelemetryWorkerEvent { - /// We have established a connection to one of the telemetry endpoint, either for the first - /// time or after having been disconnected earlier. - Connected, -} - -/// Telemetry processing machine. -#[derive(Debug)] -pub struct TelemetryWorker { - /// List of nodes with their maximum verbosity level. - nodes: Vec<(node::Node, u8)>, -} - -/// The pile of libp2p transports. -#[cfg(not(target_os = "unknown"))] -type WsTrans = libp2p::core::transport::timeout::TransportTimeout< - libp2p::core::transport::map::Map< - libp2p::core::transport::OrTransport< - libp2p::core::transport::map::Map< - OptionalTransport, - fn(wasm_ext::Connection, ConnectedPoint) -> StreamSink - >, - libp2p::websocket::framed::WsConfig> - >, - fn(libp2p::core::either::EitherOutput, - libp2p::websocket::framed::BytesConnection>, ConnectedPoint) - -> Compat01As03Sink, - libp2p::websocket::framed::BytesConnection>, BytesMut> - > ->; -#[cfg(target_os = "unknown")] -type WsTrans = libp2p::core::transport::timeout::TransportTimeout< - libp2p::core::transport::map::Map< - libp2p::core::transport::map::Map< - OptionalTransport, - fn(wasm_ext::Connection, ConnectedPoint) -> StreamSink - >, - fn(StreamSink, ConnectedPoint) - -> Compat01As03Sink, BytesMut> - > ->; - -impl TelemetryWorker { - /// Builds a new `TelemetryWorker`. - /// - /// The endpoints must be a list of targets, plus a verbosity level. When you send a message - /// to the telemetry, only the targets whose verbosity is higher than the verbosity of the - /// message will receive it. - pub fn new( - endpoints: impl IntoIterator, - wasm_external_transport: impl Into> - ) -> Self { - let transport = match wasm_external_transport.into() { - Some(t) => OptionalTransport::some(t), - None => OptionalTransport::none() - }.map((|inner, _| StreamSink(inner)) as fn(_, _) -> _); - - // The main transport is the `wasm_external_transport`, but if we're on desktop we add - // support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass - // an external transport on desktop and the fallback is used all the time. - #[cfg(not(target_os = "unknown"))] - let transport = transport.or_transport({ - let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new()); - libp2p::websocket::framed::WsConfig::new(inner) - }); - - let transport = transport - .map((|inner, _| Compat01As03Sink::new(inner)) as fn(_, _) -> _) - .with_timeout(CONNECT_TIMEOUT); - - TelemetryWorker { - nodes: endpoints.into_iter().map(|(addr, verbosity)| { - let node = node::Node::new(transport.clone(), addr); - (node, verbosity) - }).collect() - } - } - - /// Polls the worker for events that happened. - pub fn poll(&mut self, cx: &mut Context) -> Poll { - for (node, _) in &mut self.nodes { - loop { - match node::Node::poll(Pin::new(node), cx) { - Poll::Ready(node::NodeEvent::Connected) => - return Poll::Ready(TelemetryWorkerEvent::Connected), - Poll::Ready(node::NodeEvent::Disconnected(_)) => continue, - Poll::Pending => break, - } - } - } - - Poll::Pending - } - - /// Equivalent to `slog::Drain::log`, but takes `self` by `&mut` instead, which is more convenient. - /// - /// Keep in mind that you should call `TelemetryWorker::poll` in order to process the messages. - /// You should call this function right after calling `slog::Drain::log`. - pub fn log(&mut self, record: &slog::Record, values: &slog::OwnedKVList) -> Result<(), ()> { - let msg_verbosity = match record.tag().parse::() { - Ok(v) => v, - Err(err) => { - warn!(target: "telemetry", "Failed to parse telemetry tag {:?}: {:?}", - record.tag(), err); - return Err(()) - } - }; - - // None of the nodes want that verbosity, so just return without doing any serialization. - if self.nodes.iter().all(|(_, node_max_verbosity)| msg_verbosity > *node_max_verbosity) { - trace!( - target: "telemetry", - "Skipping log entry because verbosity {:?} is too high for all endpoints", - msg_verbosity - ); - return Ok(()) - } - - // Turn the message into JSON. - let serialized = { - let mut out = Vec::new(); - slog_json::Json::default(&mut out).log(record, values).map_err(|_| ())?; - out - }; - - for (node, node_max_verbosity) in &mut self.nodes { - if msg_verbosity > *node_max_verbosity { - trace!(target: "telemetry", "Skipping {:?} for log entry with verbosity {:?}", - node.addr(), msg_verbosity); - continue; - } - - // `send_message` returns an error if we're not connected, which we silently ignore. - let _ = node.send_message(serialized.clone()); - } - - Ok(()) - } -} - -/// Wraps around an `AsyncWrite` and implements `Sink`. Guarantees that each item being sent maps -/// to one call of `write`. -/// -/// For some context, we put this object around the `wasm_ext::ExtTransport` in order to make sure -/// that each telemetry message maps to one single call to `write` in the WASM FFI. -struct StreamSink(T); - -impl futures01::Stream for StreamSink { - type Item = BytesMut; - type Error = io::Error; - - fn poll(&mut self) -> futures01::Poll, Self::Error> { - let mut buf = [0; 128]; - Ok(self.0.poll_read(&mut buf)? - .map(|n| - if n == 0 { - None - } else { - let buf: BytesMut = buf[..n].into(); - Some(buf) - } - )) - } -} - -impl futures01::Sink for StreamSink { - type SinkItem = BytesMut; - type SinkError = io::Error; - - fn start_send(&mut self, item: Self::SinkItem) - -> Result, io::Error> { - match self.0.write(&item[..]) { - Ok(n) if n == item.len() => Ok(futures01::AsyncSink::Ready), - Ok(_) => { - error!(target: "telemetry", - "Detected some internal buffering happening in the telemetry"); - Err(io::Error::new(io::ErrorKind::Other, "Internal buffering detected")) - }, - Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => - Ok(futures01::AsyncSink::NotReady(item)), - Err(err) => Err(err), - } - } - - fn poll_complete(&mut self) -> futures01::Poll<(), io::Error> { - match self.0.flush() { - Ok(()) => Ok(futures01::Async::Ready(())), - Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Ok(futures01::Async::NotReady), - Err(err) => Err(err), - } - } -} diff --git a/core/test-client/Cargo.toml b/core/test-client/Cargo.toml deleted file mode 100644 index de13b34d69753..0000000000000 --- a/core/test-client/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "substrate-test-client" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../client" } -client-db = { package = "substrate-client-db", path = "../client/db", features = ["test-helpers"] } -consensus = { package = "substrate-consensus-common", path = "../consensus/common" } -executor = { package = "substrate-executor", path = "../executor" } -futures-preview = "0.3.0-alpha.19" -hash-db = "0.15.2" -keyring = { package = "substrate-keyring", path = "../keyring" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -primitives = { package = "substrate-primitives", path = "../primitives" } -sr-primitives = { path = "../sr-primitives" } -state_machine = { package = "substrate-state-machine", path = "../state-machine" } diff --git a/core/test-client/src/client_ext.rs b/core/test-client/src/client_ext.rs deleted file mode 100644 index 7d3d7301c55d3..0000000000000 --- a/core/test-client/src/client_ext.rs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Client extension for tests. - -use client::{self, Client, backend::Finalizer}; -use consensus::{ - BlockImportParams, BlockImport, BlockOrigin, Error as ConsensusError, - ForkChoiceStrategy, -}; -use hash_db::Hasher; -use sr_primitives::Justification; -use sr_primitives::traits::{Block as BlockT}; -use sr_primitives::generic::BlockId; -use primitives::Blake2Hasher; -use codec::alloc::collections::hash_map::HashMap; - -/// Extension trait for a test client. -pub trait ClientExt: Sized { - /// Import block to the chain. No finality. - fn import(&self, origin: BlockOrigin, block: Block) - -> Result<(), ConsensusError>; - - /// Import a block and make it our best block if possible. - fn import_as_best(&self, origin: BlockOrigin, block: Block) - -> Result<(), ConsensusError>; - - /// Import block with justification, finalizes block. - fn import_justified( - &self, - origin: BlockOrigin, - block: Block, - justification: Justification - ) -> Result<(), ConsensusError>; - - /// Finalize a block. - fn finalize_block( - &self, - id: BlockId, - justification: Option, - ) -> client::error::Result<()>; - - /// Returns hash of the genesis block. - fn genesis_hash(&self) -> ::Hash; -} - -impl ClientExt for Client - where - B: client::backend::Backend, - E: client::CallExecutor, - for<'r> &'r Self: BlockImport, - Block: BlockT::Out>, -{ - fn import(&self, origin: BlockOrigin, block: Block) - -> Result<(), ConsensusError> - { - let (header, extrinsics) = block.deconstruct(); - let import = BlockImportParams { - origin, - header, - justification: None, - post_digests: vec![], - body: Some(extrinsics), - finalized: false, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; - - BlockImport::import_block(&mut (&*self), import, HashMap::new()).map(|_| ()) - } - - fn import_as_best(&self, origin: BlockOrigin, block: Block) - -> Result<(), ConsensusError> - { - let (header, extrinsics) = block.deconstruct(); - let import = BlockImportParams { - origin, - header, - justification: None, - post_digests: vec![], - body: Some(extrinsics), - finalized: false, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::Custom(true), - }; - - BlockImport::import_block(&mut (&*self), import, HashMap::new()).map(|_| ()) - } - - fn import_justified( - &self, - origin: BlockOrigin, - block: Block, - justification: Justification, - ) -> Result<(), ConsensusError> { - let (header, extrinsics) = block.deconstruct(); - let import = BlockImportParams { - origin, - header, - justification: Some(justification), - post_digests: vec![], - body: Some(extrinsics), - finalized: true, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; - - BlockImport::import_block(&mut (&*self), import, HashMap::new()).map(|_| ()) - } - - fn finalize_block( - &self, - id: BlockId, - justification: Option, - ) -> client::error::Result<()> { - Finalizer::finalize_block(self, id, justification, true) - } - - fn genesis_hash(&self) -> ::Hash { - self.block_hash(0.into()).unwrap().unwrap() - } -} diff --git a/core/test-client/src/lib.rs b/core/test-client/src/lib.rs deleted file mode 100644 index dbe4431456a74..0000000000000 --- a/core/test-client/src/lib.rs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Client testing utilities. - -#![warn(missing_docs)] - -pub mod client_ext; - -pub use client::{ExecutionStrategies, blockchain, backend, self}; -pub use client_db::{Backend, self}; -pub use client_ext::ClientExt; -pub use consensus; -pub use executor::{NativeExecutor, WasmExecutionMethod, self}; -pub use keyring::{ - AccountKeyring, - ed25519::Keyring as Ed25519Keyring, - sr25519::Keyring as Sr25519Keyring, -}; -pub use primitives::{Blake2Hasher, traits::BareCryptoStorePtr}; -pub use sr_primitives::{StorageOverlay, ChildrenStorageOverlay}; -pub use state_machine::ExecutionStrategy; - -use std::sync::Arc; -use std::collections::HashMap; -use hash_db::Hasher; -use primitives::storage::well_known_keys; -use sr_primitives::traits::Block as BlockT; -use client::LocalCallExecutor; - -/// Test client light database backend. -pub type LightBackend = client::light::backend::Backend< - client_db::light::LightStorage, - Blake2Hasher, ->; - -/// A genesis storage initialisation trait. -pub trait GenesisInit: Default { - /// Construct genesis storage. - fn genesis_storage(&self) -> (StorageOverlay, ChildrenStorageOverlay); -} - -impl GenesisInit for () { - fn genesis_storage(&self) -> (StorageOverlay, ChildrenStorageOverlay) { - Default::default() - } -} - -/// A builder for creating a test client instance. -pub struct TestClientBuilder { - execution_strategies: ExecutionStrategies, - genesis_init: G, - child_storage_extension: HashMap, Vec<(Vec, Vec)>>, - backend: Arc, - _executor: std::marker::PhantomData, - keystore: Option, -} - -impl Default for TestClientBuilder< - Executor, - Backend, - G, -> where - Block: BlockT::Out>, -{ - fn default() -> Self { - Self::with_default_backend() - } -} - -impl TestClientBuilder< - Executor, - Backend, - G, -> where - Block: BlockT::Out>, -{ - /// Create new `TestClientBuilder` with default backend. - pub fn with_default_backend() -> Self { - let backend = Arc::new(Backend::new_test(std::u32::MAX, std::u64::MAX)); - Self::with_backend(backend) - } - - /// Give access to the underlying backend of these clients - pub fn backend(&self) -> Arc> { - self.backend.clone() - } -} - -impl TestClientBuilder { - /// Create a new instance of the test client builder. - pub fn with_backend(backend: Arc) -> Self { - TestClientBuilder { - backend, - execution_strategies: ExecutionStrategies::default(), - child_storage_extension: Default::default(), - genesis_init: Default::default(), - _executor: Default::default(), - keystore: None, - } - } - - /// Set the keystore that should be used by the externalities. - pub fn set_keystore(mut self, keystore: BareCryptoStorePtr) -> Self { - self.keystore = Some(keystore); - self - } - - /// Alter the genesis storage parameters. - pub fn genesis_init_mut(&mut self) -> &mut G { - &mut self.genesis_init - } - - /// Extend child storage - pub fn add_child_storage( - mut self, - key: impl AsRef<[u8]>, - child_key: impl AsRef<[u8]>, - value: impl AsRef<[u8]>, - ) -> Self { - let entry = self.child_storage_extension.entry(key.as_ref().to_vec()).or_insert_with(Vec::new); - entry.push((child_key.as_ref().to_vec(), value.as_ref().to_vec())); - self - } - - /// Set the execution strategy that should be used by all contexts. - pub fn set_execution_strategy( - mut self, - execution_strategy: ExecutionStrategy - ) -> Self { - self.execution_strategies = ExecutionStrategies { - syncing: execution_strategy, - importing: execution_strategy, - block_construction: execution_strategy, - offchain_worker: execution_strategy, - other: execution_strategy, - }; - self - } - - /// Build the test client with the given native executor. - pub fn build_with_executor( - self, - executor: Executor, - ) -> ( - client::Client< - Backend, - Executor, - Block, - RuntimeApi, - >, - client::LongestChain, - ) where - Executor: client::CallExecutor, - Backend: client::backend::Backend, - Block: BlockT::Out>, - { - - let storage = { - let mut storage = self.genesis_init.genesis_storage(); - - // Add some child storage keys. - for (key, value) in self.child_storage_extension { - storage.1.insert( - well_known_keys::CHILD_STORAGE_KEY_PREFIX.iter().cloned().chain(key).collect(), - value.into_iter().collect(), - ); - } - - storage - }; - - let client = client::Client::new( - self.backend.clone(), - executor, - storage, - Default::default(), - self.execution_strategies, - ).expect("Creates new client"); - - let longest_chain = client::LongestChain::new(self.backend); - - (client, longest_chain) - } -} - -impl TestClientBuilder< - client::LocalCallExecutor>, - Backend, - G, -> { - /// Build the test client with the given native executor. - pub fn build_with_native_executor( - mut self, - executor: I, - ) -> ( - client::Client< - Backend, - client::LocalCallExecutor>, - Block, - RuntimeApi - >, - client::LongestChain, - ) where - I: Into>>, - E: executor::NativeExecutionDispatch, - Backend: client::backend::Backend, - Block: BlockT::Out>, - { - let executor = executor.into().unwrap_or_else(|| - NativeExecutor::new(WasmExecutionMethod::Interpreted, None) - ); - let executor = LocalCallExecutor::new(self.backend.clone(), executor, self.keystore.take()); - - self.build_with_executor(executor) - } -} diff --git a/core/test-runtime/Cargo.toml b/core/test-runtime/Cargo.toml deleted file mode 100644 index 4e7c3f8bca450..0000000000000 --- a/core/test-runtime/Cargo.toml +++ /dev/null @@ -1,75 +0,0 @@ -[package] -name = "substrate-test-runtime" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -build = "build.rs" - -[dependencies] -log = { version = "0.4.8", optional = true } -serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -keyring = { package = "substrate-keyring", path = "../keyring", optional = true } -substrate-client = { path = "../client", default-features = false } -primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } -app-crypto = { package = "substrate-application-crypto", path = "../application-crypto", default-features = false } -inherents = { package = "substrate-inherents", path = "../inherents", default-features = false } -aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../consensus/aura/primitives", default-features = false } -babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../consensus/babe/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 } -sr-primitives = { path = "../sr-primitives", default-features = false } -session = { package = "substrate-session", path = "../session", 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 } -substrate-trie = { path = "../trie", default-features = false } -trie-db = { version = "0.15.2", default-features = false } -memory-db = { version = "0.15.2", default-features = false } -offchain-primitives = { package = "substrate-offchain-primitives", path = "../offchain/primitives", default-features = false} -executive = { package = "srml-executive", path = "../../srml/executive", default-features = false } -cfg-if = "0.1.10" -srml-babe = { path = "../../srml/babe", default-features = false } -srml-timestamp = { path = "../../srml/timestamp", default-features = false } -srml-system = { path = "../../srml/system", default-features = false } -srml-system-rpc-runtime-api = { path = "../../srml/system/rpc/runtime-api", default-features = false } - -[dev-dependencies] -substrate-executor = { path = "../executor" } -substrate-test-runtime-client = { path = "./client" } -state_machine = { package = "substrate-state-machine", path = "../state-machine" } - -[build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.4", path = "../utils/wasm-builder-runner" } - -[features] -default = [ - "std", -] -std = [ - "log", - "serde", - "substrate-client/std", - "keyring", - "codec/std", - "rstd/std", - "runtime_io/std", - "runtime_support/std", - "primitives/std", - "inherents/std", - "sr-primitives/std", - "runtime_version/std", - "aura-primitives/std", - "babe-primitives/std", - "primitives/std", - "substrate-trie/std", - "trie-db/std", - "memory-db/std", - "offchain-primitives/std", - "executive/std", - "srml-babe/std", - "srml-timestamp/std", - "srml-system/std", - "srml-system-rpc-runtime-api/std", - "app-crypto/std", - "session/std", -] diff --git a/core/test-runtime/build.rs b/core/test-runtime/build.rs deleted file mode 100644 index 200cd6d42c2d7..0000000000000 --- a/core/test-runtime/build.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; - -fn main() { - build_current_project_with_rustflags( - "wasm_binary.rs", - WasmBuilderSource::CratesOrPath { - path: "../utils/wasm-builder", - version: "1.0.8", - }, - // Note that we set the stack-size to 1MB explicitly even though it is set - // to this value by default. This is because some of our tests (`restoration_of_globals`) - // depend on the stack-size. - // - // The --export=__heap_base instructs LLD to export __heap_base as a global variable, which - // is used by the external memory allocator. - "-Clink-arg=-zstack-size=1048576 \ - -Clink-arg=--export=__heap_base", - ); -} diff --git a/core/test-runtime/client/Cargo.toml b/core/test-runtime/client/Cargo.toml deleted file mode 100644 index 6545048759687..0000000000000 --- a/core/test-runtime/client/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "substrate-test-runtime-client" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -generic-test-client = { package = "substrate-test-client", path = "../../test-client" } -primitives = { package = "substrate-primitives", path = "../../primitives" } -runtime = { package = "substrate-test-runtime", path = "../../test-runtime", default-features = false } -sr-primitives = { path = "../../sr-primitives" } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } - -[features] -default = [ - "std", -] -std = [ - "runtime/std", -] diff --git a/core/test-runtime/client/src/block_builder_ext.rs b/core/test-runtime/client/src/block_builder_ext.rs deleted file mode 100644 index c389a946bab86..0000000000000 --- a/core/test-runtime/client/src/block_builder_ext.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Block Builder extensions for tests. - -use runtime; -use sr_primitives::traits::ProvideRuntimeApi; -use generic_test_client::client; -use generic_test_client::client::block_builder::api::BlockBuilder; - -/// Extension trait for test block builder. -pub trait BlockBuilderExt { - /// Add transfer extrinsic to the block. - fn push_transfer(&mut self, transfer: runtime::Transfer) -> Result<(), client::error::Error>; - /// Add storage change extrinsic to the block. - fn push_storage_change(&mut self, key: Vec, value: Option>) -> Result<(), client::error::Error>; -} - -impl<'a, A> BlockBuilderExt for client::block_builder::BlockBuilder<'a, runtime::Block, A> where - A: ProvideRuntimeApi + client::blockchain::HeaderBackend + 'a, - A::Api: BlockBuilder -{ - fn push_transfer(&mut self, transfer: runtime::Transfer) -> Result<(), client::error::Error> { - self.push(transfer.into_signed_tx()) - } - - fn push_storage_change(&mut self, key: Vec, value: Option>) -> Result<(), client::error::Error> { - self.push(runtime::Extrinsic::StorageChange(key, value)) - } -} diff --git a/core/test-runtime/client/src/lib.rs b/core/test-runtime/client/src/lib.rs deleted file mode 100644 index affbae62c22e7..0000000000000 --- a/core/test-runtime/client/src/lib.rs +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Client testing utilities. - -#![warn(missing_docs)] - -pub mod trait_tests; - -mod block_builder_ext; - -use std::sync::Arc; -use std::collections::HashMap; -pub use block_builder_ext::BlockBuilderExt; -pub use generic_test_client::*; -pub use runtime; - -use primitives::sr25519; -use runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT}; - -/// A prelude to import in tests. -pub mod prelude { - // Trait extensions - pub use super::{BlockBuilderExt, DefaultTestClientBuilderExt, TestClientBuilderExt, ClientExt}; - // Client structs - pub use super::{ - TestClient, TestClientBuilder, Backend, LightBackend, - Executor, LightExecutor, LocalExecutor, NativeExecutor, WasmExecutionMethod, - }; - // Keyring - pub use super::{AccountKeyring, Sr25519Keyring}; -} - -mod local_executor { - #![allow(missing_docs)] - use runtime; - use crate::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 - ); -} - -/// Native executor used for tests. -pub use local_executor::LocalExecutor; - -/// Test client database backend. -pub type Backend = generic_test_client::Backend; - -/// Test client executor. -pub type Executor = client::LocalCallExecutor< - Backend, - NativeExecutor, ->; - -/// Test client light database backend. -pub type LightBackend = generic_test_client::LightBackend; - -/// Test client light executor. -pub type LightExecutor = client::light::call_executor::GenesisCallExecutor< - LightBackend, - client::LocalCallExecutor< - client::light::backend::Backend< - client_db::light::LightStorage, - Blake2Hasher, - >, - NativeExecutor - > ->; - -/// Parameters of test-client builder with test-runtime. -#[derive(Default)] -pub struct GenesisParameters { - support_changes_trie: bool, - heap_pages_override: Option, - extra_storage: HashMap, Vec>, - child_extra_storage: HashMap, HashMap, Vec>>, -} - -impl GenesisParameters { - fn genesis_config(&self) -> GenesisConfig { - GenesisConfig::new( - self.support_changes_trie, - vec![ - sr25519::Public::from(Sr25519Keyring::Alice).into(), - sr25519::Public::from(Sr25519Keyring::Bob).into(), - sr25519::Public::from(Sr25519Keyring::Charlie).into(), - ], - vec![ - AccountKeyring::Alice.into(), - AccountKeyring::Bob.into(), - AccountKeyring::Charlie.into(), - ], - 1000, - self.heap_pages_override, - self.extra_storage.clone(), - self.child_extra_storage.clone(), - ) - } -} - -impl generic_test_client::GenesisInit for GenesisParameters { - fn genesis_storage(&self) -> (StorageOverlay, ChildrenStorageOverlay) { - use codec::Encode; - let mut storage = self.genesis_config().genesis_map(); - - let child_roots = storage.1.iter().map(|(sk, child_map)| { - let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - child_map.clone().into_iter().collect() - ); - (sk.clone(), state_root.encode()) - }); - let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - storage.0.clone().into_iter().chain(child_roots).collect() - ); - let block: runtime::Block = client::genesis::construct_genesis_block(state_root); - storage.0.extend(additional_storage_with_genesis(&block)); - - storage - } -} - -/// A `TestClient` with `test-runtime` builder. -pub type TestClientBuilder = generic_test_client::TestClientBuilder; - -/// Test client type with `LocalExecutor` and generic Backend. -pub type Client = client::Client< - B, - client::LocalCallExecutor>, - runtime::Block, - runtime::RuntimeApi, ->; - -/// A test client with default backend. -pub type TestClient = Client; - -/// A `TestClientBuilder` with default backend and executor. -pub trait DefaultTestClientBuilderExt: Sized { - /// Create new `TestClientBuilder` - fn new() -> Self; -} - -impl DefaultTestClientBuilderExt for TestClientBuilder< - Executor, - Backend, -> { - fn new() -> Self { - Self::with_default_backend() - } -} - -/// A `test-runtime` extensions to `TestClientBuilder`. -pub trait TestClientBuilderExt: Sized { - /// Enable or disable support for changes trie in genesis. - fn set_support_changes_trie(self, support_changes_trie: bool) -> Self; - - /// Override the default value for Wasm heap pages. - fn set_heap_pages(self, heap_pages: u64) -> Self; - - /// Add an extra value into the genesis storage. - /// - /// # Panics - /// - /// Panics if the key is empty. - fn add_extra_child_storage>, K: Into>, V: Into>>( - self, - storage_key: SK, - key: K, - value: V, - ) -> Self; - - /// Add an extra child value into the genesis storage. - /// - /// # Panics - /// - /// Panics if the key is empty. - fn add_extra_storage>, V: Into>>(self, key: K, value: V) -> Self; - - /// Build the test client. - fn build(self) -> Client { - self.build_with_longest_chain().0 - } - - /// Build the test client and longest chain selector. - fn build_with_longest_chain(self) -> (Client, client::LongestChain); -} - -impl TestClientBuilderExt for TestClientBuilder< - client::LocalCallExecutor>, - B -> where - B: client::backend::Backend, -{ - fn set_heap_pages(mut self, heap_pages: u64) -> Self { - self.genesis_init_mut().heap_pages_override = Some(heap_pages); - self - } - - fn set_support_changes_trie(mut self, support_changes_trie: bool) -> Self { - self.genesis_init_mut().support_changes_trie = support_changes_trie; - self - } - - fn add_extra_storage>, V: Into>>(mut self, key: K, value: V) -> Self { - let key = key.into(); - assert!(!key.is_empty()); - self.genesis_init_mut().extra_storage.insert(key, value.into()); - self - } - - fn add_extra_child_storage>, K: Into>, V: Into>>( - mut self, - storage_key: SK, - key: K, - value: V, - ) -> Self { - let storage_key = storage_key.into(); - let key = key.into(); - assert!(!storage_key.is_empty()); - assert!(!key.is_empty()); - self.genesis_init_mut().child_extra_storage - .entry(storage_key) - .or_insert_with(Default::default) - .insert(key, value.into()); - self - } - - - fn build_with_longest_chain(self) -> (Client, client::LongestChain) { - self.build_with_native_executor(None) - } -} - -/// Creates new client instance used for tests. -pub fn new() -> Client { - TestClientBuilder::new().build() -} - -/// Creates new light client instance used for tests. -pub fn new_light() -> ( - client::Client, - Arc, -) { - - let storage = client_db::light::LightStorage::new_test(); - let blockchain = Arc::new(client::light::blockchain::Blockchain::new(storage)); - let backend = Arc::new(LightBackend::new(blockchain.clone())); - let executor = NativeExecutor::new(WasmExecutionMethod::Interpreted, None); - let local_call_executor = client::LocalCallExecutor::new(backend.clone(), executor, None); - let call_executor = LightExecutor::new( - backend.clone(), - local_call_executor, - ); - - ( - TestClientBuilder::with_backend(backend.clone()) - .build_with_executor(call_executor) - .0, - backend, - ) -} diff --git a/core/test-runtime/client/src/trait_tests.rs b/core/test-runtime/client/src/trait_tests.rs deleted file mode 100644 index 37fad9c7a1bf1..0000000000000 --- a/core/test-runtime/client/src/trait_tests.rs +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! tests that should hold for all implementations of certain traits. -//! to test implementations without duplication. - -#![allow(missing_docs)] - -use std::sync::Arc; - -use crate::backend; -use crate::block_builder_ext::BlockBuilderExt; -use crate::blockchain::{Backend as BlockChainBackendT, HeaderBackend}; -use crate::{AccountKeyring, ClientExt, TestClientBuilder, TestClientBuilderExt}; -use generic_test_client::consensus::BlockOrigin; -use primitives::Blake2Hasher; -use runtime::{self, Transfer}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::Block as BlockT; - -/// helper to test the `leaves` implementation for various backends -pub fn test_leaves_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 = TestClientBuilder::with_backend(backend.clone()).build(); - let blockchain = backend.blockchain(); - - let genesis_hash = client.info().chain.genesis_hash; - - assert_eq!( - blockchain.leaves().unwrap(), - vec![genesis_hash]); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - assert_eq!( - blockchain.leaves().unwrap(), - vec![a1.hash()]); - - // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - #[allow(deprecated)] - assert_eq!( - blockchain.leaves().unwrap(), - vec![a2.hash()]); - - // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a3.clone()).unwrap(); - assert_eq!( - blockchain.leaves().unwrap(), - vec![a3.hash()]); - - // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a4.clone()).unwrap(); - assert_eq!( - blockchain.leaves().unwrap(), - vec![a4.hash()]); - - // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a5.clone()).unwrap(); - assert_eq!( - blockchain.leaves().unwrap(), - vec![a5.hash()]); - - // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).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(); - assert_eq!( - blockchain.leaves().unwrap(), - vec![a5.hash(), b2.hash()]); - - // B2 -> B3 - let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - assert_eq!( - blockchain.leaves().unwrap(), - vec![a5.hash(), b3.hash()]); - - // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b4.clone()).unwrap(); - assert_eq!( - blockchain.leaves().unwrap(), - vec![a5.hash(), b4.hash()]); - - // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).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(); - assert_eq!( - blockchain.leaves().unwrap(), - vec![a5.hash(), b4.hash(), c3.hash()]); - - // A1 -> D2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).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(); - assert_eq!( - blockchain.leaves().unwrap(), - 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 = TestClientBuilder::with_backend(backend.clone()).build(); - let blockchain = backend.blockchain(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a3.clone()).unwrap(); - - // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a4.clone()).unwrap(); - - // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a5.clone()).unwrap(); - - // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).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()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - - // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b4.clone()).unwrap(); - - // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).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()), Default::default()).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().chain.genesis_hash; - - let children1 = blockchain.children(a4.hash()).unwrap(); - assert_eq!(vec![a5.hash()], children1); - - let children2 = blockchain.children(a1.hash()).unwrap(); - assert_eq!(vec![a2.hash(), b2.hash(), d2.hash()], children2); - - let children3 = blockchain.children(genesis_hash).unwrap(); - assert_eq!(vec![a1.hash()], children3); - - let children4 = 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 - B: backend::LocalBackend, -{ - // block tree: - // G -> A1 -> A2 -> A3 -> A4 -> A5 - // A1 -> B2 -> B3 -> B4 - // B2 -> C3 - // A1 -> D2 - let client = TestClientBuilder::with_backend(backend.clone()).build(); - let blockchain = backend.blockchain(); - - // G -> A1 - let a1 = client.new_block(Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a1.clone()).unwrap(); - - // A1 -> A2 - let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a2.clone()).unwrap(); - - // A2 -> A3 - let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a3.clone()).unwrap(); - - // A3 -> A4 - let a4 = client.new_block_at(&BlockId::Hash(a3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a4.clone()).unwrap(); - - // A4 -> A5 - let a5 = client.new_block_at(&BlockId::Hash(a4.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, a5.clone()).unwrap(); - - // A1 -> B2 - let mut builder = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()).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()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b3.clone()).unwrap(); - - // B3 -> B4 - let b4 = client.new_block_at(&BlockId::Hash(b3.hash()), Default::default()).unwrap().bake().unwrap(); - client.import(BlockOrigin::Own, b4.clone()).unwrap(); - - // // B2 -> C3 - let mut builder = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()).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()), Default::default()).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().chain.genesis_hash; - - assert_eq!(blockchain.header(BlockId::Number(0)).unwrap().unwrap().hash(), genesis_hash); - assert_eq!(blockchain.hash(0).unwrap().unwrap(), genesis_hash); - - assert_eq!(blockchain.header(BlockId::Number(1)).unwrap().unwrap().hash(), a1.hash()); - assert_eq!(blockchain.hash(1).unwrap().unwrap(), a1.hash()); - - assert_eq!(blockchain.header(BlockId::Number(2)).unwrap().unwrap().hash(), a2.hash()); - assert_eq!(blockchain.hash(2).unwrap().unwrap(), a2.hash()); - - assert_eq!(blockchain.header(BlockId::Number(3)).unwrap().unwrap().hash(), a3.hash()); - assert_eq!(blockchain.hash(3).unwrap().unwrap(), a3.hash()); - - assert_eq!(blockchain.header(BlockId::Number(4)).unwrap().unwrap().hash(), a4.hash()); - assert_eq!(blockchain.hash(4).unwrap().unwrap(), a4.hash()); - - assert_eq!(blockchain.header(BlockId::Number(5)).unwrap().unwrap().hash(), a5.hash()); - assert_eq!(blockchain.hash(5).unwrap().unwrap(), a5.hash()); -} diff --git a/core/test-runtime/src/genesismap.rs b/core/test-runtime/src/genesismap.rs deleted file mode 100644 index a3abf235ff1ca..0000000000000 --- a/core/test-runtime/src/genesismap.rs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tool for creating the genesis block. - -use std::collections::HashMap; -use runtime_io::{blake2_256, twox_128}; -use super::{AuthorityId, AccountId, WASM_BINARY}; -use codec::{Encode, KeyedVec, Joiner}; -use primitives::{ChangesTrieConfiguration, map, storage::well_known_keys}; -use sr_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; - -/// Configuration of a general Substrate test genesis block. -pub struct GenesisConfig { - changes_trie_config: Option, - authorities: Vec, - balances: Vec<(AccountId, u64)>, - heap_pages_override: Option, - /// Additional storage key pairs that will be added to the genesis map. - extra_storage: HashMap, Vec>, - child_extra_storage: HashMap, HashMap, Vec>>, -} - -impl GenesisConfig { - pub fn new( - support_changes_trie: bool, - authorities: Vec, - endowed_accounts: Vec, - balance: u64, - heap_pages_override: Option, - extra_storage: HashMap, Vec>, - child_extra_storage: HashMap, HashMap, Vec>>, - ) -> Self { - GenesisConfig { - changes_trie_config: match support_changes_trie { - true => Some(super::changes_trie_config()), - false => None, - }, - authorities: authorities.clone(), - balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(), - heap_pages_override, - extra_storage, - child_extra_storage, - } - } - - pub fn genesis_map(&self) -> ( - HashMap, Vec>, - HashMap, HashMap, Vec>>, - ) { - let wasm_runtime = WASM_BINARY.to_vec(); - let mut map: HashMap, Vec> = self.balances.iter() - .map(|&(ref account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) - .map(|(k, v)| (blake2_256(&k[..])[..].to_vec(), v.to_vec())) - .chain(vec![ - (well_known_keys::CODE.into(), wasm_runtime), - ( - well_known_keys::HEAP_PAGES.into(), - vec![].and(&(self.heap_pages_override.unwrap_or(16 as u64))), - ), - ].into_iter()) - .collect(); - if let Some(ref changes_trie_config) = self.changes_trie_config { - map.insert(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), changes_trie_config.encode()); - } - map.insert(twox_128(&b"sys:auth"[..])[..].to_vec(), self.authorities.encode()); - // Finally, add the extra storage entries. - map.extend(self.extra_storage.clone().into_iter()); - - (map, self.child_extra_storage.clone()) - } -} - -pub fn insert_genesis_block( - storage: &mut ( - HashMap, Vec>, - HashMap, HashMap, Vec>>, - ) -) -> primitives::hash::H256 { - let child_roots = storage.1.iter().map(|(sk, child_map)| { - let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - child_map.clone().into_iter().collect(), - ); - (sk.clone(), state_root.encode()) - }); - let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - storage.0.clone().into_iter().chain(child_roots).collect() - ); - let block: crate::Block = substrate_client::genesis::construct_genesis_block(state_root); - let genesis_hash = block.header.hash(); - storage.0.extend(additional_storage_with_genesis(&block)); - genesis_hash -} - -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 deleted file mode 100644 index 45d86f891c594..0000000000000 --- a/core/test-runtime/src/lib.rs +++ /dev/null @@ -1,1049 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! The Substrate runtime. This can be compiled with #[no_std], ready for Wasm. - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -pub mod genesismap; -pub mod system; - -use rstd::{prelude::*, marker::PhantomData}; -use codec::{Encode, Decode, Input, Error}; - -use primitives::{ - Blake2Hasher, - OpaqueMetadata, - RuntimeDebug, - testing::{ - ED25519, - SR25519, - } -}; -use app_crypto::{ed25519, sr25519, RuntimeAppPublic}; -pub use app_crypto; -use trie_db::{TrieMut, Trie}; -use substrate_trie::PrefixedMemoryDB; -use substrate_trie::trie_types::{TrieDB, TrieDBMut}; - -use substrate_client::{ - runtime_api as client_api, block_builder::api as block_builder_api, decl_runtime_apis, - impl_runtime_apis, -}; -use sr_primitives::{ - ApplyResult, create_runtime_str, Perbill, impl_opaque_keys, - transaction_validity::{ - TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction, - }, - traits::{ - BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, - GetNodeBlockType, GetRuntimeBlockType, Verify, IdentityLookup, - }, -}; -use runtime_version::RuntimeVersion; -pub use primitives::{hash::H256}; -#[cfg(any(feature = "std", test))] -use runtime_version::NativeVersion; -use runtime_support::{impl_outer_origin, parameter_types}; -use inherents::{CheckInherentsResult, InherentData}; -use cfg_if::cfg_if; - -// Ensure Babe and Aura use the same crypto to simplify things a bit. -pub use babe_primitives::AuthorityId; -pub type AuraId = aura_primitives::sr25519::AuthorityId; - -// Inlucde the WASM binary -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -/// Test runtime version. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("test"), - impl_name: create_runtime_str!("parity-test"), - authoring_version: 1, - spec_version: 1, - impl_version: 1, - apis: RUNTIME_API_VERSIONS, -}; - -fn version() -> RuntimeVersion { - VERSION -} - -/// Native version. -#[cfg(any(feature = "std", test))] -pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } -} - -/// Calls in transactions. -#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] -pub struct Transfer { - pub from: AccountId, - pub to: AccountId, - pub amount: u64, - 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, RuntimeDebug)] -pub enum Extrinsic { - AuthoritiesChange(Vec), - Transfer(Transfer, AccountSignature), - IncludeData(Vec), - StorageChange(Vec, Option>), -} - -#[cfg(feature = "std")] -impl serde::Serialize for Extrinsic { - fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { - self.using_encoded(|bytes| seq.serialize_bytes(bytes)) - } -} - -impl BlindCheckable for Extrinsic { - type Checked = Self; - - fn check(self) -> Result { - match self { - Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)), - Extrinsic::Transfer(transfer, signature) => { - if sr_primitives::verify_encoded_lazy(&signature, &transfer, &transfer.from) { - Ok(Extrinsic::Transfer(transfer, signature)) - } else { - Err(InvalidTransaction::BadProof.into()) - } - }, - Extrinsic::IncludeData(_) => Err(InvalidTransaction::BadProof.into()), - Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)), - } - } -} - -impl ExtrinsicT for Extrinsic { - type Call = Extrinsic; - type SignaturePayload = (); - - fn is_signed(&self) -> Option { - if let Extrinsic::IncludeData(_) = *self { - Some(false) - } else { - Some(true) - } - } - - fn new(call: Self::Call, _signature_payload: Option) -> Option { - Some(call) - } -} - -impl Extrinsic { - pub fn transfer(&self) -> &Transfer { - match self { - Extrinsic::Transfer(ref transfer, _) => transfer, - _ => panic!("cannot convert to transfer ref"), - } - } -} - -/// The signature type used by accounts/transactions. -pub type AccountSignature = sr25519::Signature; -/// An identifier for an account on this system. -pub type AccountId = ::Signer; -/// A simple hash type for all our hashing. -pub type Hash = H256; -/// The block number type used in this runtime. -pub type BlockNumber = u64; -/// Index of a transaction. -pub type Index = u64; -/// The item of a block digest. -pub type DigestItem = sr_primitives::generic::DigestItem; -/// The digest of a block. -pub type Digest = sr_primitives::generic::Digest; -/// A test block. -pub type Block = sr_primitives::generic::Block; -/// A test block's header. -pub type Header = sr_primitives::generic::Header; - -/// Run whatever tests we have. -pub fn run_tests(mut input: &[u8]) -> Vec { - use sr_primitives::print; - - print("run_tests..."); - let block = Block::decode(&mut input).unwrap(); - print("deserialized block."); - let stxs = block.extrinsics.iter().map(Encode::encode).collect::>(); - print("reserialized transactions."); - [stxs.len() as u8].encode() -} - -/// Changes trie configuration (optionally) used in tests. -pub fn changes_trie_config() -> primitives::ChangesTrieConfiguration { - primitives::ChangesTrieConfiguration { - digest_interval: 4, - digest_levels: 2, - } -} - -/// A type that can not be decoded. -#[derive(PartialEq)] -pub struct DecodeFails { - _phantom: PhantomData, -} - -impl Encode for DecodeFails { - fn encode(&self) -> Vec { - Vec::new() - } -} - -impl codec::EncodeLike for DecodeFails {} - -impl DecodeFails { - /// Create a new instance. - pub fn new() -> DecodeFails { - DecodeFails { - _phantom: Default::default(), - } - } -} - -impl Decode for DecodeFails { - fn decode(_: &mut I) -> Result { - Err("DecodeFails always fails".into()) - } -} - -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; - /// trie no_std testing - fn use_trie() -> u64; - fn benchmark_indirect_call() -> u64; - fn benchmark_direct_call() -> u64; - fn returns_mutable_static() -> u64; - fn allocates_huge_stack_array(trap: bool) -> Vec; - fn vec_with_capacity(size: u32) -> Vec; - /// Returns the initialized block number. - fn get_block_number() -> u64; - /// Takes and returns the initialized block number. - fn take_block_number() -> Option; - /// Returns if no block was initialized. - #[skip_initialize_block] - fn without_initialize_block() -> bool; - /// Test that `ed25519` crypto works in the runtime. - /// - /// Returns the signature generated for the message `ed25519` and the public key. - fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic); - /// Test that `sr25519` crypto works in the runtime. - /// - /// Returns the signature generated for the message `sr25519`. - fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); - /// Run various tests against storage. - fn test_storage(); - } - } - } else { - 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; - /// trie no_std testing - fn use_trie() -> u64; - fn benchmark_indirect_call() -> u64; - fn benchmark_direct_call() -> u64; - fn returns_mutable_static() -> u64; - fn allocates_huge_stack_array(trap: bool) -> Vec; - fn vec_with_capacity(size: u32) -> Vec; - /// Returns the initialized block number. - fn get_block_number() -> u64; - /// Takes and returns the initialized block number. - fn take_block_number() -> Option; - /// Returns if no block was initialized. - #[skip_initialize_block] - fn without_initialize_block() -> bool; - /// Test that `ed25519` crypto works in the runtime. - /// - /// Returns the signature generated for the message `ed25519` and the public key. - fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic); - /// Test that `sr25519` crypto works in the runtime. - /// - /// Returns the signature generated for the message `sr25519`. - fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); - /// Run various tests against storage. - fn test_storage(); - } - } - } -} - -#[derive(Clone, Eq, PartialEq)] -pub struct Runtime; - -impl GetNodeBlockType for Runtime { - type NodeBlock = Block; -} - -impl GetRuntimeBlockType for Runtime { - type RuntimeBlock = Block; -} - -impl_outer_origin!{ - pub enum Origin for Runtime where system = srml_system {} -} - -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] -pub struct Event; - -impl From for Event { - fn from(_evt: srml_system::Event) -> Self { - unimplemented!("Not required in tests!") - } -} - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const MinimumPeriod: u64 = 5; - pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024; - pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); -} - -impl srml_system::Trait for Runtime { - type Origin = Origin; - type Call = Extrinsic; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} - -impl srml_timestamp::Trait for Runtime { - /// A timestamp: milliseconds since the unix epoch. - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; -} - -parameter_types! { - pub const EpochDuration: u64 = 6; - pub const ExpectedBlockTime: u64 = 10_000; -} - -impl srml_babe::Trait for Runtime { - type EpochDuration = EpochDuration; - type ExpectedBlockTime = ExpectedBlockTime; - // there is no actual runtime in this test-runtime, so testing crates - // are manually adding the digests. normally in this situation you'd use - // srml_babe::SameAuthoritiesForever. - type EpochChangeTrigger = srml_babe::ExternalTrigger; -} - -/// Adds one to the given input and returns the final result. -#[inline(never)] -fn benchmark_add_one(i: u64) -> u64 { - i + 1 -} - -/// 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); - -fn code_using_trie() -> u64 { - let pairs = [ - (b"0103000000000000000464".to_vec(), b"0400000000".to_vec()), - (b"0103000000000000000469".to_vec(), b"0401000000".to_vec()), - ].to_vec(); - - let mut mdb = PrefixedMemoryDB::default(); - let mut root = rstd::default::Default::default(); - let _ = { - let v = &pairs; - let mut t = TrieDBMut::::new(&mut mdb, &mut root); - for i in 0..v.len() { - let key: &[u8]= &v[i].0; - let val: &[u8] = &v[i].1; - if !t.insert(key, val).is_ok() { - return 101; - } - } - t - }; - - if let Ok(trie) = TrieDB::::new(&mdb, &root) { - if let Ok(iter) = trie.iter() { - let mut iter_pairs = Vec::new(); - for pair in iter { - if let Ok((key, value)) = pair { - iter_pairs.push((key, value.to_vec())); - } - } - iter_pairs.len() as u64 - } else { 102 } - } else { 103 } -} - -impl_opaque_keys! { - pub struct SessionKeys { - #[id(ED25519)] - pub ed25519: ed25519::AppPublic, - #[id(SR25519)] - pub sr25519: sr25519::AppPublic, - } -} - -#[cfg(not(feature = "std"))] -/// Mutable static variables should be always observed to have -/// the initialized value at the start of a runtime call. -static mut MUTABLE_STATIC: u64 = 32; - -cfg_if! { - if #[cfg(feature = "std")] { - impl_runtime_apis! { - impl client_api::Core for Runtime { - fn version() -> RuntimeVersion { - version() - } - - fn execute_block(block: Block) { - system::execute_block(block) - } - - fn initialize_block(header: &::Header) { - system::initialize_block(header) - } - } - - impl client_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - unimplemented!() - } - } - - impl client_api::TaggedTransactionQueue for Runtime { - fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { - if let Extrinsic::IncludeData(data) = utx { - return Ok(ValidTransaction { - priority: data.len() as u64, - requires: vec![], - provides: vec![data], - longevity: 1, - propagate: false, - }); - } - - system::validate_transaction(utx) - } - } - - impl block_builder_api::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { - system::execute_transaction(extrinsic) - } - - fn finalize_block() -> ::Header { - system::finalize_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 use_trie() -> u64 { - code_using_trie() - } - - 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)) - } - - fn returns_mutable_static() -> u64 { - unimplemented!("is not expected to be invoked from non-wasm builds"); - } - - fn allocates_huge_stack_array(_trap: bool) -> Vec { - unimplemented!("is not expected to be invoked from non-wasm builds"); - } - - fn vec_with_capacity(_size: u32) -> Vec { - unimplemented!("is not expected to be invoked from non-wasm builds"); - } - - fn get_block_number() -> u64 { - system::get_block_number().expect("Block number is initialized") - } - - fn without_initialize_block() -> bool { - system::get_block_number().is_none() - } - - fn take_block_number() -> Option { - system::take_block_number() - } - - fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { - test_ed25519_crypto() - } - - fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { - test_sr25519_crypto() - } - - fn test_storage() { - test_read_storage(); - test_read_child_storage(); - } - } - - impl aura_primitives::AuraApi for Runtime { - fn slot_duration() -> u64 { 1000 } - fn authorities() -> Vec { - system::authorities().into_iter().map(|a| { - let authority: sr25519::Public = a.into(); - AuraId::from(authority) - }).collect() - } - } - - impl babe_primitives::BabeApi for Runtime { - fn configuration() -> babe_primitives::BabeConfiguration { - babe_primitives::BabeConfiguration { - slot_duration: 1000, - epoch_length: EpochDuration::get(), - c: (3, 10), - genesis_authorities: system::authorities() - .into_iter().map(|x|(x, 1)).collect(), - randomness: >::randomness(), - secondary_slots: true, - } - } - } - - impl offchain_primitives::OffchainWorkerApi for Runtime { - fn offchain_worker(block: u64) { - let ex = Extrinsic::IncludeData(block.encode()); - runtime_io::submit_transaction(ex.encode()).unwrap(); - } - } - - impl session::SessionKeys for Runtime { - fn generate_session_keys(_: Option>) -> Vec { - SessionKeys::generate(None) - } - } - - impl srml_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(_account: AccountId) -> Index { - 0 - } - } - } - } else { - impl_runtime_apis! { - impl client_api::Core for Runtime { - fn version() -> RuntimeVersion { - version() - } - - fn execute_block(block: Block) { - system::execute_block(block) - } - - fn initialize_block(header: &::Header) { - system::initialize_block(header) - } - } - - impl client_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - unimplemented!() - } - } - - impl client_api::TaggedTransactionQueue for Runtime { - fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { - if let Extrinsic::IncludeData(data) = utx { - return Ok(ValidTransaction{ - priority: data.len() as u64, - requires: vec![], - provides: vec![data], - longevity: 1, - propagate: false, - }); - } - - system::validate_transaction(utx) - } - } - - impl block_builder_api::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { - system::execute_transaction(extrinsic) - } - - fn finalize_block() -> ::Header { - system::finalize_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 use_trie() -> u64 { - code_using_trie() - } - - 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)) - } - - fn returns_mutable_static() -> u64 { - unsafe { - MUTABLE_STATIC += 1; - MUTABLE_STATIC - } - } - - fn allocates_huge_stack_array(trap: bool) -> Vec { - // Allocate a stack frame that is approx. 75% of the stack (assuming it is 1MB). - // This will just decrease (stacks in wasm32-u-u grow downwards) the stack - // pointer. This won't trap on the current compilers. - let mut data = [0u8; 1024 * 768]; - - // Then make sure we actually write something to it. - // - // If: - // 1. the stack area is placed at the beginning of the linear memory space, and - // 2. the stack pointer points to out-of-bounds area, and - // 3. a write is performed around the current stack pointer. - // - // then a trap should happen. - // - for (i, v) in data.iter_mut().enumerate() { - *v = i as u8; // deliberate truncation - } - - if trap { - // There is a small chance of this to be pulled up in theory. In practice - // the probability of that is rather low. - panic!() - } - - data.to_vec() - } - - fn vec_with_capacity(size: u32) -> Vec { - Vec::with_capacity(size as usize) - } - - fn get_block_number() -> u64 { - system::get_block_number().expect("Block number is initialized") - } - - fn without_initialize_block() -> bool { - system::get_block_number().is_none() - } - - fn take_block_number() -> Option { - system::take_block_number() - } - - fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { - test_ed25519_crypto() - } - - fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { - test_sr25519_crypto() - } - - fn test_storage() { - test_read_storage(); - test_read_child_storage(); - } - } - - impl aura_primitives::AuraApi for Runtime { - fn slot_duration() -> u64 { 1000 } - fn authorities() -> Vec { - system::authorities().into_iter().map(|a| { - let authority: sr25519::Public = a.into(); - AuraId::from(authority) - }).collect() - } - } - - impl babe_primitives::BabeApi for Runtime { - fn configuration() -> babe_primitives::BabeConfiguration { - babe_primitives::BabeConfiguration { - slot_duration: 1000, - epoch_length: EpochDuration::get(), - c: (3, 10), - genesis_authorities: system::authorities() - .into_iter().map(|x|(x, 1)).collect(), - randomness: >::randomness(), - secondary_slots: true, - } - } - } - - impl offchain_primitives::OffchainWorkerApi for Runtime { - fn offchain_worker(block: u64) { - let ex = Extrinsic::IncludeData(block.encode()); - runtime_io::submit_transaction(ex.encode()).unwrap() - } - } - - impl session::SessionKeys for Runtime { - fn generate_session_keys(_: Option>) -> Vec { - SessionKeys::generate(None) - } - } - - impl srml_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(_account: AccountId) -> Index { - 0 - } - } - } - } -} - -fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { - let public0 = ed25519::AppPublic::generate_pair(None); - let public1 = ed25519::AppPublic::generate_pair(None); - let public2 = ed25519::AppPublic::generate_pair(None); - - let all = ed25519::AppPublic::all(); - assert!(all.contains(&public0)); - assert!(all.contains(&public1)); - assert!(all.contains(&public2)); - - let signature = public0.sign(&"ed25519").expect("Generates a valid `ed25519` signature."); - assert!(public0.verify(&"ed25519", &signature)); - (signature, public0) -} - -fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { - let public0 = sr25519::AppPublic::generate_pair(None); - let public1 = sr25519::AppPublic::generate_pair(None); - let public2 = sr25519::AppPublic::generate_pair(None); - - let all = sr25519::AppPublic::all(); - assert!(all.contains(&public0)); - assert!(all.contains(&public1)); - assert!(all.contains(&public2)); - - let signature = public0.sign(&"sr25519").expect("Generates a valid `sr25519` signature."); - assert!(public0.verify(&"sr25519", &signature)); - (signature, public0) -} - -fn test_read_storage() { - const KEY: &[u8] = b":read_storage"; - runtime_io::set_storage(KEY, b"test"); - - let mut v = [0u8; 4]; - let r = runtime_io::read_storage( - KEY, - &mut v, - 0 - ); - assert_eq!(r, Some(4)); - assert_eq!(&v, b"test"); - - let mut v = [0u8; 4]; - let r = runtime_io::read_storage(KEY, &mut v, 8); - assert_eq!(r, Some(4)); - assert_eq!(&v, &[0, 0, 0, 0]); -} - -fn test_read_child_storage() { - const CHILD_KEY: &[u8] = b":child_storage:default:read_child_storage"; - const KEY: &[u8] = b":read_child_storage"; - runtime_io::set_child_storage(CHILD_KEY, KEY, b"test"); - - let mut v = [0u8; 4]; - let r = runtime_io::read_child_storage( - CHILD_KEY, - KEY, - &mut v, - 0 - ); - assert_eq!(r, Some(4)); - assert_eq!(&v, b"test"); - - let mut v = [0u8; 4]; - let r = runtime_io::read_child_storage(CHILD_KEY, KEY, &mut v, 8); - assert_eq!(r, Some(4)); - assert_eq!(&v, &[0, 0, 0, 0]); -} - -#[cfg(test)] -mod tests { - use substrate_test_runtime_client::{ - prelude::*, - consensus::BlockOrigin, - DefaultTestClientBuilderExt, TestClientBuilder, - runtime::TestAPI, - }; - use sr_primitives::{ - generic::BlockId, - traits::ProvideRuntimeApi, - }; - use primitives::storage::well_known_keys::HEAP_PAGES; - use state_machine::ExecutionStrategy; - use codec::Encode; - - #[test] - fn returns_mutable_static() { - let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::AlwaysWasm).build(); - let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); - - let ret = runtime_api.returns_mutable_static(&block_id).unwrap(); - assert_eq!(ret, 33); - - // We expect that every invocation will need to return the initial - // value plus one. If the value increases more than that then it is - // a sign that the wasm runtime preserves the memory content. - let ret = runtime_api.returns_mutable_static(&block_id).unwrap(); - assert_eq!(ret, 33); - } - - // If we didn't restore the wasm instance properly, on a trap the stack pointer would not be - // returned to its initial value and thus the stack space is going to be leaked. - // - // See https://github.com/paritytech/substrate/issues/2967 for details - #[test] - fn restoration_of_globals() { - // Allocate 32 pages (of 65536 bytes) which gives the runtime 2048KB of heap to operate on - // (plus some additional space unused from the initial pages requested by the wasm runtime - // module). - // - // The fixture performs 2 allocations of 768KB and this theoretically gives 1536KB, however, due - // to our allocator algorithm there are inefficiencies. - const REQUIRED_MEMORY_PAGES: u64 = 32; - - let client = TestClientBuilder::new() - .set_execution_strategy(ExecutionStrategy::AlwaysWasm) - .set_heap_pages(REQUIRED_MEMORY_PAGES) - .build(); - let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); - - // On the first invocation we allocate approx. 768KB (75%) of stack and then trap. - let ret = runtime_api.allocates_huge_stack_array(&block_id, true); - assert!(ret.is_err()); - - // On the second invocation we allocate yet another 768KB (75%) of stack - let ret = runtime_api.allocates_huge_stack_array(&block_id, false); - assert!(ret.is_ok()); - } - - #[test] - fn heap_pages_is_respected() { - // This tests that the on-chain HEAP_PAGES parameter is respected. - - // Create a client devoting only 8 pages of wasm memory. This gives us ~512k of heap memory. - let client = TestClientBuilder::new() - .set_execution_strategy(ExecutionStrategy::AlwaysWasm) - .set_heap_pages(8) - .build(); - let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); - - // Try to allocate 1024k of memory on heap. This is going to fail since it is twice larger - // than the heap. - let ret = runtime_api.vec_with_capacity(&block_id, 1048576); - assert!(ret.is_err()); - - // Create a block that sets the `:heap_pages` to 32 pages of memory which corresponds to - // ~2048k of heap memory. - let new_block_id = { - let mut builder = client.new_block(Default::default()).unwrap(); - builder.push_storage_change(HEAP_PAGES.to_vec(), Some(32u64.encode())).unwrap(); - let block = builder.bake().unwrap(); - let hash = block.header.hash(); - client.import(BlockOrigin::Own, block).unwrap(); - BlockId::Hash(hash) - }; - - // Allocation of 1024k while having ~2048k should succeed. - let ret = runtime_api.vec_with_capacity(&new_block_id, 1048576); - assert!(ret.is_ok()); - } - - #[test] - fn test_storage() { - let client = TestClientBuilder::new() - .set_execution_strategy(ExecutionStrategy::Both) - .build(); - let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); - - runtime_api.test_storage(&block_id).unwrap(); - } -} diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs deleted file mode 100644 index fc4de0ce4b911..0000000000000 --- a/core/test-runtime/src/system.rs +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code -//! and depositing logs. - -use rstd::prelude::*; -use runtime_io::{storage_root, storage_changes_root, blake2_256}; -use runtime_support::storage::{self, StorageValue, StorageMap}; -use runtime_support::storage_items; -use sr_primitives::{ - traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyResult, - transaction_validity::{TransactionValidity, ValidTransaction, InvalidTransaction}, -}; -use codec::{KeyedVec, Encode}; -use crate::{ - AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId -}; -use primitives::storage::well_known_keys; - -const NONCE_OF: &[u8] = b"nonce:"; -const BALANCE_OF: &[u8] = b"balance:"; - -storage_items! { - ExtrinsicData: b"sys:xtd" => required map [ u32 => Vec ]; - // The current block number being processed. Set by `execute_block`. - Number: b"sys:num" => BlockNumber; - ParentHash: b"sys:pha" => required Hash; - NewAuthorities: b"sys:new_auth" => Vec; - StorageDigest: b"sys:digest" => Digest; - Authorities get(authorities): b"sys:auth" => default Vec; -} - -pub fn balance_of_key(who: AccountId) -> Vec { - who.to_keyed_vec(BALANCE_OF) -} - -pub fn balance_of(who: AccountId) -> u64 { - storage::hashed::get_or(&blake2_256, &balance_of_key(who), 0) -} - -pub fn nonce_of(who: AccountId) -> u64 { - storage::hashed::get_or(&blake2_256, &who.to_keyed_vec(NONCE_OF), 0) -} - -pub fn initialize_block(header: &Header) { - // populate environment. - ::put(&header.number); - ::put(&header.parent_hash); - ::put(header.digest()); - storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); - - // try to read something that depends on current header digest - // so that it'll be included in execution proof - if let Some(generic::DigestItem::Other(v)) = header.digest().logs().iter().next() { - let _: Option = storage::unhashed::get(&v); - } -} - -pub fn get_block_number() -> Option { - Number::get() -} - -pub fn take_block_number() -> Option { - Number::take() -} - -#[derive(Copy, Clone)] -enum Mode { - Verify, - Overwrite, -} - -/// Actually execute all transitioning for `block`. -pub fn polish_block(block: &mut Block) { - execute_block_with_state_root_handler(block, Mode::Overwrite); -} - -pub fn execute_block(mut block: Block) { - execute_block_with_state_root_handler(&mut block, Mode::Verify); -} - -fn execute_block_with_state_root_handler( - block: &mut Block, - mode: Mode, -) { - let header = &mut block.header; - - // check transaction trie root represents the transactions. - let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); - let txs_root = BlakeTwo256::ordered_trie_root(txs); - info_expect_equal_hash(&txs_root, &header.extrinsics_root); - if let Mode::Overwrite = mode { - header.extrinsics_root = txs_root; - } else { - assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); - } - - // try to read something that depends on current header digest - // so that it'll be included in execution proof - if let Some(generic::DigestItem::Other(v)) = header.digest().logs().iter().next() { - let _: Option = storage::unhashed::get(&v); - } - - // execute transactions - block.extrinsics.iter().enumerate().for_each(|(i, e)| { - storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - let _ = execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); - storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); - }); - - let o_new_authorities = ::take(); - - if let Mode::Overwrite = mode { - header.state_root = storage_root().into(); - } else { - // check storage root. - let storage_root = storage_root().into(); - info_expect_equal_hash(&storage_root, &header.state_root); - assert!(storage_root == header.state_root, "Storage root must match that calculated."); - } - - // check digest - let digest = &mut header.digest; - if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into()) { - digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); - } - if let Some(new_authorities) = o_new_authorities { - digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode())); - digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode())); - } -} - -/// The block executor. -pub struct BlockExecutor; - -impl executive::ExecuteBlock for BlockExecutor { - fn execute_block(block: Block) { - execute_block(block); - } -} - -/// 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 { - if check_signature(&utx).is_err() { - return InvalidTransaction::BadProof.into(); - } - - let tx = utx.transfer(); - let nonce_key = tx.from.to_keyed_vec(NONCE_OF); - let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); - if tx.nonce < expected_nonce { - return InvalidTransaction::Stale.into(); - } - if tx.nonce > expected_nonce + 64 { - return InvalidTransaction::Future.into(); - } - - let encode = |from: &AccountId, nonce: u64| (from, nonce).encode(); - let requires = if tx.nonce != expected_nonce && tx.nonce > 0 { - vec![encode(&tx.from, tx.nonce - 1)] - } else { - vec![] - }; - - let provides = vec![encode(&tx.from, tx.nonce)]; - - Ok(ValidTransaction { - priority: tx.amount, - requires, - provides, - longevity: 64, - propagate: true, - }) -} - -/// 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 { - let extrinsic_index: u32 = storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap(); - let result = execute_transaction_backend(&utx); - ExtrinsicData::insert(extrinsic_index, utx.encode()); - storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(extrinsic_index + 1)); - result -} - -/// Finalize the block. -pub fn finalize_block() -> Header { - let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap(); - let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect(); - let extrinsics_root = BlakeTwo256::ordered_trie_root(txs).into(); - let number = ::take().expect("Number is set by `initialize_block`"); - let parent_hash = ::take(); - let mut digest = ::take().expect("StorageDigest is set by `initialize_block`"); - - let o_new_authorities = ::take(); - // This MUST come after all changes to storage are done. Otherwise we will fail the - // “Storage root does not match that calculated” assertion. - let storage_root = BlakeTwo256::storage_root(); - let storage_changes_root = BlakeTwo256::storage_changes_root(parent_hash); - - if let Some(storage_changes_root) = storage_changes_root { - digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root)); - } - - if let Some(new_authorities) = o_new_authorities { - digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode())); - digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode())); - } - - Header { - number, - extrinsics_root, - state_root: storage_root, - parent_hash, - digest: digest, - } -} - -#[inline(always)] -fn check_signature(utx: &Extrinsic) -> Result<(), ApplyError> { - use sr_primitives::traits::BlindCheckable; - utx.clone().check().map_err(|_| InvalidTransaction::BadProof.into()).map(|_| ()) -} - -fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { - check_signature(utx)?; - match utx { - Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), - Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), - Extrinsic::IncludeData(_) => Ok(Ok(())), - Extrinsic::StorageChange(key, value) => execute_storage_change(key, value.as_ref().map(|v| &**v)), - } -} - -fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { - // check nonce - let nonce_key = tx.from.to_keyed_vec(NONCE_OF); - let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); - if !(tx.nonce == expected_nonce) { - return Err(InvalidTransaction::Stale.into()); - } - - // increment nonce in storage - storage::hashed::put(&blake2_256, &nonce_key, &(expected_nonce + 1)); - - // check sender balance - let from_balance_key = tx.from.to_keyed_vec(BALANCE_OF); - let from_balance: u64 = storage::hashed::get_or(&blake2_256, &from_balance_key, 0); - - // enact transfer - if !(tx.amount <= from_balance) { - return Err(InvalidTransaction::Payment.into()); - } - let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); - let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); - storage::hashed::put(&blake2_256, &from_balance_key, &(from_balance - tx.amount)); - storage::hashed::put(&blake2_256, &to_balance_key, &(to_balance + tx.amount)); - Ok(Ok(())) -} - -fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult { - NewAuthorities::put(new_authorities.to_vec()); - Ok(Ok(())) -} - -fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyResult { - match value { - Some(value) => storage::unhashed::put_raw(key, value), - None => storage::unhashed::kill(key), - } - Ok(Ok(())) -} - -#[cfg(feature = "std")] -fn info_expect_equal_hash(given: &Hash, expected: &Hash) { - use primitives::hexdisplay::HexDisplay; - if given != expected { - println!( - "Hash: given={}, expected={}", - HexDisplay::from(given.as_fixed_bytes()), - HexDisplay::from(expected.as_fixed_bytes()), - ); - } -} - -#[cfg(not(feature = "std"))] -fn info_expect_equal_hash(given: &Hash, expected: &Hash) { - if given != expected { - sr_primitives::print("Hash not equal"); - sr_primitives::print(given.as_bytes()); - sr_primitives::print(expected.as_bytes()); - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use runtime_io::TestExternalities; - use substrate_test_runtime_client::{AccountKeyring, Sr25519Keyring}; - use crate::{Header, Transfer, WASM_BINARY}; - use primitives::{NeverNativeValue, map, traits::CodeExecutor}; - use substrate_executor::{NativeExecutor, WasmExecutionMethod, native_executor_instance}; - use runtime_io::twox_128; - - // Declare an instance of the native executor dispatch for the test runtime. - native_executor_instance!( - NativeDispatch, - crate::api::dispatch, - crate::native_version - ); - - fn executor() -> NativeExecutor { - NativeExecutor::new(WasmExecutionMethod::Interpreted, None) - } - - fn new_test_ext() -> TestExternalities { - let authorities = vec![ - Sr25519Keyring::Alice.to_raw_public(), - Sr25519Keyring::Bob.to_raw_public(), - Sr25519Keyring::Charlie.to_raw_public() - ]; - TestExternalities::new_with_code( - WASM_BINARY, - ( - map![ - twox_128(b"latest").to_vec() => vec![69u8; 32], - twox_128(b"sys:auth").to_vec() => authorities.encode(), - blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => { - vec![111u8, 0, 0, 0, 0, 0, 0, 0] - } - ], - map![], - ) - ) - } - - fn block_import_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { - let h = Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: Default::default(), - }; - let mut b = Block { - header: h, - extrinsics: vec![], - }; - - new_test_ext().execute_with(|| polish_block(&mut b)); - - block_executor(b, &mut new_test_ext()); - } - - #[test] - fn block_import_works_native() { - block_import_works(|b, ext| ext.execute_with(|| execute_block(b))); - } - - #[test] - fn block_import_works_wasm() { - block_import_works(|b, ext| { - let mut ext = ext.ext(); - executor().call::<_, NeverNativeValue, fn() -> _>( - &mut ext, - "Core_execute_block", - &b.encode(), - false, - None, - ).0.unwrap(); - }) - } - - fn block_import_with_transaction_works(block_executor: F) - where F: Fn(Block, &mut TestExternalities) - { - let mut b1 = Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: Default::default(), - }, - extrinsics: vec![ - Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Bob.into(), - amount: 69, - nonce: 0, - }.into_signed_tx() - ], - }; - - let mut dummy_ext = new_test_ext(); - dummy_ext.execute_with(|| polish_block(&mut b1)); - - let mut b2 = Block { - header: Header { - parent_hash: b1.header.hash(), - number: 2, - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: Default::default(), - }, - extrinsics: vec![ - Transfer { - from: AccountKeyring::Bob.into(), - to: AccountKeyring::Alice.into(), - amount: 27, - nonce: 0, - }.into_signed_tx(), - Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Charlie.into(), - amount: 69, - nonce: 1, - }.into_signed_tx(), - ], - }; - - dummy_ext.execute_with(|| polish_block(&mut b2)); - drop(dummy_ext); - - let mut t = new_test_ext(); - - t.execute_with(|| { - assert_eq!(balance_of(AccountKeyring::Alice.into()), 111); - assert_eq!(balance_of(AccountKeyring::Bob.into()), 0); - }); - - block_executor(b1, &mut t); - - t.execute_with(|| { - assert_eq!(balance_of(AccountKeyring::Alice.into()), 42); - assert_eq!(balance_of(AccountKeyring::Bob.into()), 69); - }); - - block_executor(b2, &mut t); - - t.execute_with(|| { - assert_eq!(balance_of(AccountKeyring::Alice.into()), 0); - assert_eq!(balance_of(AccountKeyring::Bob.into()), 42); - assert_eq!(balance_of(AccountKeyring::Charlie.into()), 69); - }); - } - - #[test] - fn block_import_with_transaction_works_native() { - block_import_with_transaction_works(|b, ext| ext.execute_with(|| execute_block(b))); - } - - #[test] - fn block_import_with_transaction_works_wasm() { - block_import_with_transaction_works(|b, ext| { - let mut ext = ext.ext(); - executor().call::<_, NeverNativeValue, fn() -> _>( - &mut ext, - "Core_execute_block", - &b.encode(), - false, - None, - ).0.unwrap(); - }) - } -} diff --git a/core/transaction-pool/Cargo.toml b/core/transaction-pool/Cargo.toml deleted file mode 100644 index 33ec9e9ece176..0000000000000 --- a/core/transaction-pool/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "substrate-transaction-pool" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -derive_more = "0.15.0" -log = "0.4.8" -futures-preview = "0.3.0-alpha.19" -codec = { package = "parity-scale-codec", version = "1.0.0" } -parking_lot = "0.9.0" -sr-primitives = { path = "../sr-primitives" } -client = { package = "substrate-client", path = "../client" } -primitives = { package = "substrate-primitives", path = "../primitives" } -txpool = { package = "substrate-transaction-graph", path = "./graph" } - -[dev-dependencies] -keyring = { package = "substrate-keyring", path = "../../core/keyring" } -test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } diff --git a/core/transaction-pool/graph/Cargo.toml b/core/transaction-pool/graph/Cargo.toml deleted file mode 100644 index fa0d6f14b6f32..0000000000000 --- a/core/transaction-pool/graph/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "substrate-transaction-graph" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -derive_more = "0.15.0" -futures-preview = "0.3.0-alpha.19" -log = "0.4.8" -parking_lot = "0.9.0" -serde = { version = "1.0.101", features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../primitives" } -sr-primitives = { path = "../../sr-primitives" } - -[dev-dependencies] -assert_matches = "1.3.0" -env_logger = "0.7.0" -codec = { package = "parity-scale-codec", version = "1.0.0" } -test_runtime = { package = "substrate-test-runtime", path = "../../test-runtime" } diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/graph/src/error.rs deleted file mode 100644 index 79006461c6e37..0000000000000 --- a/core/transaction-pool/graph/src/error.rs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Transaction pool errors. - -use sr_primitives::transaction_validity::{ - TransactionPriority as Priority, InvalidTransaction, UnknownTransaction, -}; - -/// Transaction pool result. -pub type Result = std::result::Result; - -/// Transaction pool error type. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Transaction is not verifiable yet, but might be in the future. - #[display(fmt="Unknown transaction validity: {:?}", _0)] - UnknownTransaction(UnknownTransaction), - /// Transaction is invalid. - #[display(fmt="Invalid transaction validity: {:?}", _0)] - InvalidTransaction(InvalidTransaction), - /// The transaction validity returned no "provides" tag. - /// - /// Such transactions are not accepted to the pool, since we use those tags - /// to define identity of transactions (occupance of the same "slot"). - #[display(fmt="The transaction does not provide any tags, so the pool can't identify it.")] - NoTagsProvided, - /// The transaction is temporarily banned. - #[display(fmt="Temporarily Banned")] - TemporarilyBanned, - /// The transaction is already in the pool. - #[display(fmt="[{:?}] Already imported", _0)] - AlreadyImported(Box), - /// The transaction cannot be imported cause it's a replacement and has too low priority. - #[display(fmt="Too low priority ({} > {})", old, new)] - TooLowPriority { - /// Transaction already in the pool. - old: Priority, - /// Transaction entering the pool. - new: Priority - }, - /// Deps cycle etected and we couldn't import transaction. - #[display(fmt="Cycle Detected")] - CycleDetected, - /// Transaction was dropped immediately after it got inserted. - #[display(fmt="Transaction couldn't enter the pool because of the limit.")] - ImmediatelyDropped, - /// Invalid block id. - InvalidBlockId(String), -} - -impl std::error::Error for Error {} - -/// Transaction pool error conversion. -pub trait IntoPoolError: ::std::error::Error + Send + Sized { - /// Try to extract original `Error` - /// - /// This implementation is optional and used only to - /// provide more descriptive error messages for end users - /// of RPC API. - fn into_pool_error(self) -> ::std::result::Result { Err(self) } -} - -impl IntoPoolError for Error { - fn into_pool_error(self) -> ::std::result::Result { Ok(self) } -} diff --git a/core/transaction-pool/graph/src/lib.rs b/core/transaction-pool/graph/src/lib.rs deleted file mode 100644 index 715e60874be95..0000000000000 --- a/core/transaction-pool/graph/src/lib.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Generic Transaction Pool -//! -//! The pool is based on dependency graph between transactions -//! 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. - -#![warn(missing_docs)] -#![warn(unused_extern_crates)] - -mod future; -mod listener; -mod pool; -mod ready; -mod rotator; -mod validated_pool; - -pub mod base_pool; -pub mod error; -pub mod watcher; - -pub use self::error::IntoPoolError; -pub use self::base_pool::{Transaction, Status}; -pub use self::pool::{ - Pool, - Options, ChainApi, EventStream, ExtrinsicFor, - BlockHash, ExHash, NumberFor, TransactionFor, -}; diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs deleted file mode 100644 index 621aeabda8ee9..0000000000000 --- a/core/transaction-pool/graph/src/pool.rs +++ /dev/null @@ -1,911 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::{ - hash, - collections::HashMap, - sync::Arc, -}; - -use crate::base_pool as base; -use crate::error; -use crate::watcher::Watcher; -use serde::Serialize; - -use futures::{ - Future, FutureExt, - channel::mpsc, - future::{Either, ready, join_all}, -}; -use sr_primitives::{ - generic::BlockId, - traits::{self, SaturatedConversion}, - transaction_validity::{TransactionValidity, TransactionTag as Tag, TransactionValidityError}, -}; -use crate::validated_pool::{ValidatedPool, ValidatedTransaction}; - -/// Modification notification event stream type; -pub type EventStream = mpsc::UnboundedReceiver<()>; - -/// Extrinsic hash type for a pool. -pub type ExHash = ::Hash; -/// Block hash type for a pool. -pub type BlockHash = <::Block as traits::Block>::Hash; -/// Extrinsic type for a pool. -pub type ExtrinsicFor = <::Block as traits::Block>::Extrinsic; -/// Block number type for the ChainApi -pub type NumberFor = traits::NumberFor<::Block>; -/// A type of transaction stored in the pool -pub type TransactionFor = Arc, ExtrinsicFor>>; -/// A type of validated transaction stored in the pool. -pub type ValidatedTransactionFor = ValidatedTransaction< - ExHash, - ExtrinsicFor, - ::Error, ->; - -/// Concrete extrinsic validation and query logic. -pub trait ChainApi: Send + Sync { - /// Block type. - type Block: traits::Block; - /// Transaction Hash type - type Hash: hash::Hash + Eq + traits::Member + Serialize; - /// Error type. - type Error: From + error::IntoPoolError; - /// Validate transaction future. - type ValidationFuture: Future> + Send + Unpin; - - /// Verify extrinsic at given block. - fn validate_transaction( - &self, - at: &BlockId, - uxt: ExtrinsicFor, - ) -> Self::ValidationFuture; - - /// Returns a block number given the block id. - fn block_id_to_number(&self, at: &BlockId) -> Result>, Self::Error>; - - /// Returns a block hash given the block id. - fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error>; - - /// Returns hash and encoding length of the extrinsic. - fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize); -} - -/// Pool configuration options. -#[derive(Debug, Clone)] -pub struct Options { - /// Ready queue limits. - pub ready: base::Limit, - /// Future queue limits. - pub future: base::Limit, -} - -impl Default for Options { - fn default() -> Self { - Options { - ready: base::Limit { - count: 512, - total_bytes: 10 * 1024 * 1024, - }, - future: base::Limit { - count: 128, - total_bytes: 1 * 1024 * 1024, - }, - } - } -} - -/// Extrinsics pool that performs validation. -pub struct Pool { - validated_pool: Arc>, -} - -impl Pool { - /// Create a new transaction pool. - pub fn new(options: Options, api: B) -> Self { - Pool { - validated_pool: Arc::new(ValidatedPool::new(options, api)), - } - } - - /// Imports a bunch of unverified extrinsics to the pool - pub fn submit_at(&self, at: &BlockId, xts: T, force: bool) - -> impl Future, B::Error>>, B::Error>> - where - T: IntoIterator> - { - let validated_pool = self.validated_pool.clone(); - self.verify(at, xts, force) - .map(move |validated_transactions| validated_transactions - .map(|validated_transactions| validated_pool.submit(validated_transactions))) - } - - /// Imports one unverified extrinsic to the pool - pub fn submit_one( - &self, - at: &BlockId, - xt: ExtrinsicFor, - ) -> impl Future, B::Error>> { - self.submit_at(at, std::iter::once(xt), false) - .map(|import_result| import_result.and_then(|mut import_result| import_result - .pop() - .expect("One extrinsic passed; one result returned; qed") - )) - } - - /// Import a single extrinsic and starts to watch their progress in the pool. - pub fn submit_and_watch( - &self, - at: &BlockId, - xt: ExtrinsicFor, - ) -> impl Future, BlockHash>, B::Error>> { - let block_number = match self.resolve_block_number(at) { - Ok(block_number) => block_number, - Err(err) => return Either::Left(ready(Err(err))) - }; - - let validated_pool = self.validated_pool.clone(); - Either::Right( - self.verify_one(at, block_number, xt, false) - .map(move |validated_transactions| validated_pool.submit_and_watch(validated_transactions)) - ) - } - - /// Prunes ready transactions. - /// - /// 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], - ) -> impl Future> { - // Get details of all extrinsics that are already in the pool - let (in_pool_hashes, in_pool_tags) = self.validated_pool.extrinsics_tags(extrinsics); - - // Zip the ones from the pool with the full list (we get pairs `(Extrinsic, Option>)`) - let all = extrinsics.iter().zip(in_pool_tags.into_iter()); - - // Prepare future that collect tags for all extrinsics - let future_tags = join_all(all - .map(|(extrinsic, in_pool_tags)| - match in_pool_tags { - // reuse the tags for extrinsics that were found in the pool - Some(tags) => Either::Left( - ready(tags) - ), - // if it's not found in the pool query the runtime at parent block - // to get validity info and tags that the extrinsic provides. - None => Either::Right(self.validated_pool.api().validate_transaction(parent, extrinsic.clone()) - .then(|validity| ready(match validity { - Ok(Ok(validity)) => validity.provides, - // silently ignore invalid extrinsics, - // cause they might just be inherent - _ => Vec::new(), - }))), - } - )); - - // Prune transactions by tags - let at = at.clone(); - let self_clone = self.clone(); - future_tags.then(move |tags| self_clone.prune_tags( - &at, - tags.into_iter().flat_map(|tags| tags), - in_pool_hashes, - )) - } - - /// Prunes ready transactions that provide given list of tags. - /// - /// 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. - /// - /// Returns transactions that have been removed from the pool and must be reverified - /// before reinserting to the pool. - /// - /// By removing predecessor transactions as well we might actually end up - /// pruning too much, so all removed transactions are reverified against - /// the runtime (`validate_transaction`) to make sure they are invalid. - /// - /// 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, - ) -> impl Future> { - // Prune all transactions that provide given tags - let prune_status = match self.validated_pool.prune_tags(tags) { - Ok(prune_status) => prune_status, - Err(e) => return Either::Left(ready(Err(e))), - }; - - // Make sure that we don't revalidate extrinsics that were part of the recently - // imported block. This is especially important for UTXO-like chains cause the - // inputs are pruned so such transaction would go to future again. - self.validated_pool.ban(&std::time::Instant::now(), known_imported_hashes.clone().into_iter()); - - // Try to re-validate pruned transactions since some of them might be still valid. - // note that `known_imported_hashes` will be rejected here due to temporary ban. - let pruned_hashes = prune_status.pruned.iter().map(|tx| tx.hash.clone()).collect::>(); - let pruned_transactions = prune_status.pruned.into_iter().map(|tx| tx.data.clone()); - let reverify_future = self.verify(at, pruned_transactions, false); - - // And finally - submit reverified transactions back to the pool - let at = at.clone(); - let validated_pool = self.validated_pool.clone(); - Either::Right(reverify_future.then(move |reverified_transactions| - ready(reverified_transactions.and_then(|reverified_transactions| - validated_pool.resubmit_pruned( - &at, - known_imported_hashes, - pruned_hashes, - reverified_transactions, - )) - ))) - } - - /// Return an event stream of transactions imported to the pool. - pub fn import_notification_stream(&self) -> EventStream { - self.validated_pool.import_notification_stream() - } - - /// Invoked when extrinsics are broadcasted. - pub fn on_broadcasted(&self, propagated: HashMap, Vec>) { - self.validated_pool.on_broadcasted(propagated) - } - - /// Remove from the pool. - pub fn remove_invalid(&self, hashes: &[ExHash]) -> Vec> { - self.validated_pool.remove_invalid(hashes) - } - - /// Get an iterator for ready transactions ordered by priority - pub fn ready(&self) -> impl Iterator> { - self.validated_pool.ready() - } - - /// Returns pool status. - pub fn status(&self) -> base::Status { - self.validated_pool.status() - } - - /// Returns transaction hash - pub fn hash_of(&self, xt: &ExtrinsicFor) -> ExHash { - self.validated_pool.api().hash_and_length(xt).0 - } - - /// Resolves block number by id. - fn resolve_block_number(&self, at: &BlockId) -> Result, B::Error> { - self.validated_pool.api().block_id_to_number(at) - .and_then(|number| number.ok_or_else(|| - error::Error::InvalidBlockId(format!("{:?}", at)).into())) - } - - /// Returns future that validates a bunch of transactions at given block. - fn verify( - &self, - at: &BlockId, - xts: impl IntoIterator>, - force: bool, - ) -> impl Future>, B::Error>> { - // we need a block number to compute tx validity - let block_number = match self.resolve_block_number(at) { - Ok(block_number) => block_number, - Err(err) => return Either::Left(ready(Err(err))), - }; - - // for each xt, prepare a validation future - let validation_futures = xts.into_iter().map(move |xt| - self.verify_one(at, block_number, xt, force) - ); - - // make single validation future that waits all until all extrinsics are validated - Either::Right(join_all(validation_futures).then(|x| ready(Ok(x)))) - } - - /// Returns future that validates single transaction at given block. - fn verify_one( - &self, - block_id: &BlockId, - block_number: NumberFor, - xt: ExtrinsicFor, - force: bool, - ) -> impl Future> { - let (hash, bytes) = self.validated_pool.api().hash_and_length(&xt); - if !force && self.validated_pool.is_banned(&hash) { - return Either::Left(ready(ValidatedTransaction::Invalid(error::Error::TemporarilyBanned.into()))) - } - - Either::Right(self.validated_pool.api().validate_transaction(block_id, xt.clone()) - .then(move |validation_result| ready(match validation_result { - Ok(validity) => match validity { - Ok(validity) => if validity.provides.is_empty() { - ValidatedTransaction::Invalid(error::Error::NoTagsProvided.into()) - } else { - ValidatedTransaction::Valid(base::Transaction { - data: xt, - bytes, - hash, - priority: validity.priority, - requires: validity.requires, - provides: validity.provides, - propagate: validity.propagate, - valid_till: block_number - .saturated_into::() - .saturating_add(validity.longevity), - }) - }, - Err(TransactionValidityError::Invalid(e)) => - ValidatedTransaction::Invalid(error::Error::InvalidTransaction(e).into()), - Err(TransactionValidityError::Unknown(e)) => - ValidatedTransaction::Unknown(hash, error::Error::UnknownTransaction(e).into()), - }, - Err(e) => ValidatedTransaction::Invalid(e), - }))) - } -} - -impl Clone for Pool { - fn clone(&self) -> Self { - Self { - validated_pool: self.validated_pool.clone(), - } - } -} - -#[cfg(test)] -mod tests { - use std::{ - collections::HashMap, - time::Instant, - }; - use parking_lot::Mutex; - use futures::executor::block_on; - use super::*; - use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransaction}; - use codec::Encode; - use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; - use assert_matches::assert_matches; - use crate::base_pool::Limit; - use crate::watcher; - - const INVALID_NONCE: u64 = 254; - - #[derive(Clone, Debug, Default)] - struct TestApi { - delay: Arc>>>, - } - - impl ChainApi for TestApi { - type Block = Block; - type Hash = u64; - type Error = error::Error; - type ValidationFuture = futures::future::Ready>; - - /// Verify extrinsic at given block. - fn validate_transaction( - &self, - at: &BlockId, - uxt: ExtrinsicFor, - ) -> Self::ValidationFuture { - let block_number = self.block_id_to_number(at).unwrap().unwrap(); - let nonce = uxt.transfer().nonce; - - // This is used to control the test flow. - if nonce > 0 { - let opt = self.delay.lock().take(); - if let Some(delay) = opt { - if delay.recv().is_err() { - println!("Error waiting for delay!"); - } - } - } - - futures::future::ready(if nonce < block_number { - Ok(InvalidTransaction::Stale.into()) - } else { - Ok(Ok(ValidTransaction { - priority: 4, - requires: if nonce > block_number { vec![vec![nonce as u8 - 1]] } else { vec![] }, - provides: if nonce == INVALID_NONCE { vec![] } else { vec![vec![nonce as u8]] }, - longevity: 3, - propagate: true, - })) - }) - } - - /// Returns a block number given the block id. - fn block_id_to_number(&self, at: &BlockId) -> Result>, Self::Error> { - Ok(match at { - BlockId::Number(num) => Some(*num), - BlockId::Hash(_) => None, - }) - } - - /// Returns a block hash given the block id. - fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error> { - Ok(match at { - BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), - BlockId::Hash(_) => None, - }) - } - - /// Hash the extrinsic. - fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { - let len = uxt.encode().len(); - ( - (H256::from(uxt.transfer().from.clone()).to_low_u64_be() << 5) + uxt.transfer().nonce, - len - ) - } - } - - fn uxt(transfer: Transfer) -> Extrinsic { - Extrinsic::Transfer(transfer, Default::default()) - } - - fn pool() -> Pool { - Pool::new(Default::default(), TestApi::default()) - } - - - #[test] - fn should_validate_and_import_transaction() { - // given - let pool = pool(); - - // when - let hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 0, - }))).unwrap(); - - // then - assert_eq!(pool.ready().map(|v| v.hash).collect::>(), vec![hash]); - } - - #[test] - fn should_reject_if_temporarily_banned() { - // given - let pool = pool(); - let uxt = 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, - }); - - // when - pool.validated_pool.rotator().ban(&Instant::now(), vec![pool.hash_of(&uxt)]); - let res = block_on(pool.submit_one(&BlockId::Number(0), uxt)); - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - - // then - assert_matches!(res.unwrap_err(), error::Error::TemporarilyBanned); - } - - #[test] - fn should_notify_about_pool_events() { - let stream = { - // given - let pool = pool(); - let stream = pool.import_notification_stream(); - - // when - let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 0, - }))).unwrap(); - let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 1, - }))).unwrap(); - // future doesn't count - let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 3, - }))).unwrap(); - - assert_eq!(pool.status().ready, 2); - assert_eq!(pool.status().future, 1); - stream - }; - - // then - let mut it = futures::executor::block_on_stream(stream); - assert_eq!(it.next(), Some(())); - assert_eq!(it.next(), Some(())); - assert_eq!(it.next(), None); - } - - #[test] - fn should_clear_stale_transactions() { - // given - let pool = pool(); - let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 0, - }))).unwrap(); - let hash2 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 1, - }))).unwrap(); - let hash3 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 3, - }))).unwrap(); - - // when - pool.validated_pool.clear_stale(&BlockId::Number(5)).unwrap(); - - // then - assert_eq!(pool.ready().count(), 0); - assert_eq!(pool.status().future, 0); - assert_eq!(pool.status().ready, 0); - // make sure they are temporarily banned as well - assert!(pool.validated_pool.rotator().is_banned(&hash1)); - assert!(pool.validated_pool.rotator().is_banned(&hash2)); - assert!(pool.validated_pool.rotator().is_banned(&hash3)); - } - - #[test] - fn should_ban_mined_transactions() { - // given - let pool = pool(); - let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 0, - }))).unwrap(); - - // when - block_on(pool.prune_tags(&BlockId::Number(1), vec![vec![0]], vec![hash1.clone()])).unwrap(); - - // then - assert!(pool.validated_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 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 1, - }))).unwrap(); - assert_eq!(pool.status().future, 1); - - // when - let hash2 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(2)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 10, - }))).unwrap(); - - // then - assert_eq!(pool.status().future, 1); - assert!(pool.validated_pool.rotator().is_banned(&hash1)); - assert!(!pool.validated_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 - block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 1, - }))).unwrap_err(); - - // then - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - } - - #[test] - fn should_reject_transactions_with_no_provides() { - // given - let pool = pool(); - - // when - let err = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: INVALID_NONCE, - }))).unwrap_err(); - - // then - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - assert_matches!(err, error::Error::NoTagsProvided); - } - - mod listener { - use super::*; - - #[test] - fn should_trigger_ready_and_finalized() { - // given - let pool = pool(); - let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 0, - }))).unwrap(); - assert_eq!(pool.status().ready, 1); - assert_eq!(pool.status().future, 0); - - // when - block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![])).unwrap(); - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - - // then - let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Finalized(H256::from_low_u64_be(2).into()))); - assert_eq!(stream.next(), None); - } - - #[test] - fn should_trigger_ready_and_finalized_when_pruning_via_hash() { - // given - let pool = pool(); - let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 0, - }))).unwrap(); - assert_eq!(pool.status().ready, 1); - assert_eq!(pool.status().future, 0); - - // when - block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![2u64])).unwrap(); - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - - // then - let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Finalized(H256::from_low_u64_be(2).into()))); - assert_eq!(stream.next(), None); - } - - #[test] - fn should_trigger_future_and_ready_after_promoted() { - // given - let pool = pool(); - let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 1, - }))).unwrap(); - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 1); - - // when - block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: AccountId::from_h256(H256::from_low_u64_be(1)), - to: AccountId::from_h256(H256::from_low_u64_be(2)), - amount: 5, - nonce: 0, - }))).unwrap(); - assert_eq!(pool.status().ready, 2); - - // then - let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Future)); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - } - - #[test] - fn should_trigger_invalid_and_ban() { - // given - let pool = pool(); - let uxt = 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 = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt)).unwrap(); - assert_eq!(pool.status().ready, 1); - - // when - pool.validated_pool.remove_invalid(&[*watcher.hash()]); - - - // then - let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Invalid)); - assert_eq!(stream.next(), None); - } - - #[test] - fn should_trigger_broadcasted() { - // given - let pool = pool(); - let uxt = 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 = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt)).unwrap(); - assert_eq!(pool.status().ready, 1); - - // when - let mut map = HashMap::new(); - let peers = vec!["a".into(), "b".into(), "c".into()]; - map.insert(*watcher.hash(), peers.clone()); - pool.on_broadcasted(map); - - - // then - let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Broadcast(peers))); - } - - #[test] - 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 = block_on(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, - }); - block_on(pool.submit_one(&BlockId::Number(1), xt)).unwrap(); - assert_eq!(pool.status().ready, 1); - - // then - let mut stream = futures::executor::block_on_stream(watcher.into_stream()); - assert_eq!(stream.next(), Some(watcher::Status::Ready)); - assert_eq!(stream.next(), Some(watcher::Status::Dropped)); - } - - #[test] - fn should_handle_pruning_in_the_middle_of_import() { - let _ = env_logger::try_init(); - // given - let (ready, is_ready) = std::sync::mpsc::sync_channel(0); - let (tx, rx) = std::sync::mpsc::sync_channel(1); - let mut api = TestApi::default(); - api.delay = Arc::new(Mutex::new(rx.into())); - let pool = Arc::new(Pool::new(Default::default(), api)); - - // when - 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: 1, - }); - - // This transaction should go to future, since we use `nonce: 1` - let pool2 = pool.clone(); - std::thread::spawn(move || { - block_on(pool2.submit_one(&BlockId::Number(0), xt)).unwrap(); - ready.send(()).unwrap(); - }); - - // But now before the previous one is imported we import - // the one that it depends on. - 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: 4, - nonce: 0, - }); - // The tag the above transaction provides (TestApi is using just nonce as u8) - let provides = vec![0_u8]; - block_on(pool.submit_one(&BlockId::Number(0), xt)).unwrap(); - assert_eq!(pool.status().ready, 1); - - // Now block import happens before the second transaction is able to finish verification. - block_on(pool.prune_tags(&BlockId::Number(1), vec![provides], vec![])).unwrap(); - assert_eq!(pool.status().ready, 0); - - - // so when we release the verification of the previous one it will have - // something in `requires`, but should go to ready directly, since the previous transaction was imported - // correctly. - tx.send(()).unwrap(); - - // then - is_ready.recv().unwrap(); // wait for finish - assert_eq!(pool.status().ready, 1); - assert_eq!(pool.status().future, 0); - } - } -} diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs deleted file mode 100644 index 9bf1012628645..0000000000000 --- a/core/transaction-pool/graph/src/validated_pool.rs +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::{ - collections::{HashSet, HashMap}, - hash, - time, -}; - -use crate::base_pool as base; -use crate::error; -use crate::listener::Listener; -use crate::rotator::PoolRotator; -use crate::watcher::Watcher; -use serde::Serialize; -use log::debug; - -use futures::channel::mpsc; -use parking_lot::{Mutex, RwLock}; -use sr_primitives::{ - generic::BlockId, - traits::{self, SaturatedConversion}, - transaction_validity::TransactionTag as Tag, -}; - -use crate::base_pool::PruneStatus; -use crate::pool::{EventStream, Options, ChainApi, BlockHash, ExHash, ExtrinsicFor, TransactionFor}; - -/// Pre-validated transaction. Validated pool only accepts transactions wrapped in this enum. -#[derive(Debug)] -pub enum ValidatedTransaction { - /// Transaction that has been validated successfully. - Valid(base::Transaction), - /// Transaction that is invalid. - Invalid(Error), - /// Transaction which validity can't be determined. - /// - /// We're notifying watchers about failure, if 'unknown' transaction is submitted. - Unknown(Hash, Error), -} - -/// A type of validated transaction stored in the pool. -pub type ValidatedTransactionFor = ValidatedTransaction< - ExHash, - ExtrinsicFor, - ::Error, ->; - -/// Pool that deals with validated transactions. -pub(crate) struct ValidatedPool { - api: B, - options: Options, - listener: RwLock, BlockHash>>, - pool: RwLock, - ExtrinsicFor, - >>, - import_notification_sinks: Mutex>>, - rotator: PoolRotator>, -} - -impl ValidatedPool { - /// Create a new transaction pool. - pub fn new(options: Options, api: B) -> Self { - ValidatedPool { - api, - options, - listener: Default::default(), - pool: Default::default(), - import_notification_sinks: Default::default(), - rotator: Default::default(), - } - } - - /// Bans given set of hashes. - pub fn ban(&self, now: &std::time::Instant, hashes: impl IntoIterator>) { - self.rotator.ban(now, hashes) - } - - /// Returns true if transaction with given hash is currently banned from the pool. - pub fn is_banned(&self, hash: &ExHash) -> bool { - self.rotator.is_banned(hash) - } - - /// Imports a bunch of pre-validated transactions to the pool. - pub fn submit(&self, txs: T) -> Vec, B::Error>> where - T: IntoIterator> - { - let results = txs.into_iter() - .map(|validated_tx| self.submit_one(validated_tx)) - .collect::>(); - - let removed = self.enforce_limits(); - - results.into_iter().map(|res| match res { - Ok(ref hash) if removed.contains(hash) => Err(error::Error::ImmediatelyDropped.into()), - other => other, - }).collect() - } - - /// Submit single pre-validated transaction to the pool. - fn submit_one(&self, tx: ValidatedTransactionFor) -> Result, B::Error> { - match tx { - ValidatedTransaction::Valid(tx) => { - let imported = self.pool.write().import(tx)?; - - if let base::Imported::Ready { .. } = imported { - self.import_notification_sinks.lock().retain(|sink| sink.unbounded_send(()).is_ok()); - } - - let mut listener = self.listener.write(); - fire_events(&mut *listener, &imported); - Ok(imported.hash().clone()) - } - ValidatedTransaction::Invalid(err) => Err(err.into()), - ValidatedTransaction::Unknown(hash, err) => { - self.listener.write().invalid(&hash); - Err(err.into()) - } - } - } - - fn enforce_limits(&self) -> HashSet> { - let status = self.pool.read().status(); - let ready_limit = &self.options.ready; - let future_limit = &self.options.future; - - debug!(target: "txpool", "Pool Status: {:?}", status); - - if ready_limit.is_exceeded(status.ready, status.ready_bytes) - || future_limit.is_exceeded(status.future, status.future_bytes) { - // clean up the pool - let removed = { - let mut pool = self.pool.write(); - let removed = pool.enforce_limits(ready_limit, future_limit) - .into_iter().map(|x| x.hash.clone()).collect::>(); - // ban all removed transactions - self.rotator.ban(&std::time::Instant::now(), removed.iter().map(|x| x.clone())); - removed - }; - // run notifications - let mut listener = self.listener.write(); - for h in &removed { - listener.dropped(h, None); - } - - removed - } else { - Default::default() - } - } - - /// Import a single extrinsic and starts to watch their progress in the pool. - pub fn submit_and_watch( - &self, - tx: ValidatedTransactionFor, - ) -> Result, BlockHash>, B::Error> { - match tx { - ValidatedTransaction::Valid(tx) => { - let hash = self.api.hash_and_length(&tx.data).0; - let watcher = self.listener.write().create_watcher(hash); - self.submit(std::iter::once(ValidatedTransaction::Valid(tx))) - .pop() - .expect("One extrinsic passed; one result returned; qed") - .map(|_| watcher) - }, - ValidatedTransaction::Invalid(err) => Err(err.into()), - ValidatedTransaction::Unknown(_, err) => Err(err.into()), - } - } - - /// For each extrinsic, returns tags that it provides (if known), or None (if it is unknown). - pub fn extrinsics_tags(&self, extrinsics: &[ExtrinsicFor]) -> (Vec>, Vec>>) { - let hashes = extrinsics.iter().map(|extrinsic| self.api.hash_and_length(extrinsic).0).collect::>(); - let in_pool = self.pool.read().by_hash(&hashes); - ( - hashes, - in_pool.into_iter() - .map(|existing_in_pool| existing_in_pool - .map(|transaction| transaction.provides.iter().cloned() - .collect())) - .collect(), - ) - } - - /// Prunes ready transactions that provide given list of tags. - pub fn prune_tags( - &self, - tags: impl IntoIterator, - ) -> Result, ExtrinsicFor>, B::Error> { - // Perform tag-based pruning in the base pool - let status = self.pool.write().prune_tags(tags); - // Notify event listeners of all transactions - // that were promoted to `Ready` or were dropped. - { - let mut listener = self.listener.write(); - for promoted in &status.promoted { - fire_events(&mut *listener, promoted); - } - for f in &status.failed { - listener.dropped(f, None); - } - } - - Ok(status) - } - - /// Resubmit transactions that have been revalidated after prune_tags call. - pub fn resubmit_pruned( - &self, - at: &BlockId, - known_imported_hashes: impl IntoIterator> + Clone, - pruned_hashes: Vec>, - pruned_xts: Vec>, - ) -> Result<(), B::Error> { - debug_assert_eq!(pruned_hashes.len(), pruned_xts.len()); - - // Resubmit pruned transactions - let results = self.submit(pruned_xts); - - // Collect the hashes of transactions that now became invalid (meaning that they are successfully pruned). - let hashes = results - .into_iter() - .enumerate() - .filter_map(|(idx, r)| match r.map_err(error::IntoPoolError::into_pool_error) { - Err(Ok(error::Error::InvalidTransaction(_))) => Some(pruned_hashes[idx].clone()), - _ => None, - }); - // Fire `pruned` notifications for collected hashes and make sure to include - // `known_imported_hashes` since they were just imported as part of the block. - let hashes = hashes.chain(known_imported_hashes.into_iter()); - { - let header_hash = self.api.block_id_to_hash(at)? - .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())?; - let mut listener = self.listener.write(); - for h in hashes { - listener.pruned(header_hash, &h); - } - } - // perform regular cleanup of old transactions in the pool - // and update temporary bans. - self.clear_stale(at)?; - Ok(()) - } - - /// Removes stale transactions from the pool. - /// - /// Stale transactions are transaction beyond their longevity period. - /// Note this function does not remove transactions that are already included in the chain. - /// See `prune_tags` if you want this. - pub fn clear_stale(&self, at: &BlockId) -> Result<(), B::Error> { - let block_number = self.api.block_id_to_number(at)? - .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())? - .saturated_into::(); - let now = time::Instant::now(); - let to_remove = { - self.ready() - .filter(|tx| self.rotator.ban_if_stale(&now, block_number, &tx)) - .map(|tx| tx.hash.clone()) - .collect::>() - }; - let futures_to_remove: Vec> = { - let p = self.pool.read(); - let mut hashes = Vec::new(); - for tx in p.futures() { - if self.rotator.ban_if_stale(&now, block_number, &tx) { - hashes.push(tx.hash.clone()); - } - } - hashes - }; - // removing old transactions - self.remove_invalid(&to_remove); - self.remove_invalid(&futures_to_remove); - // clear banned transactions timeouts - self.rotator.clear_timeouts(&now); - - Ok(()) - } - - /// Get rotator reference. - #[cfg(test)] - pub fn rotator(&self) -> &PoolRotator> { - &self.rotator - } - - /// Get api reference. - pub fn api(&self) -> &B { - &self.api - } - - /// Return an event stream of transactions imported to the pool. - pub fn import_notification_stream(&self) -> EventStream { - let (sink, stream) = mpsc::unbounded(); - self.import_notification_sinks.lock().push(sink); - stream - } - - /// Invoked when extrinsics are broadcasted. - pub fn on_broadcasted(&self, propagated: HashMap, Vec>) { - let mut listener = self.listener.write(); - for (hash, peers) in propagated.into_iter() { - listener.broadcasted(&hash, peers); - } - } - - /// Remove from the pool. - pub fn remove_invalid(&self, hashes: &[ExHash]) -> Vec> { - // temporarily ban invalid transactions - debug!(target: "txpool", "Banning invalid transactions: {:?}", hashes); - self.rotator.ban(&time::Instant::now(), hashes.iter().cloned()); - - let invalid = self.pool.write().remove_invalid(hashes); - - let mut listener = self.listener.write(); - for tx in &invalid { - listener.invalid(&tx.hash); - } - - invalid - } - - /// Get an iterator for ready transactions ordered by priority - pub fn ready(&self) -> impl Iterator> { - self.pool.read().ready() - } - - /// Returns pool status. - pub fn status(&self) -> base::Status { - self.pool.read().status() - } -} - -fn fire_events( - listener: &mut Listener, - imported: &base::Imported, -) where - H: hash::Hash + Eq + traits::Member + Serialize, - H2: Clone, -{ - match *imported { - base::Imported::Ready { ref promoted, ref failed, ref removed, ref hash } => { - listener.ready(hash, None); - for f in failed { - listener.invalid(f); - } - for r in removed { - listener.dropped(&r.hash, Some(hash)); - } - for p in promoted { - listener.ready(p, None); - } - }, - base::Imported::Future { ref hash } => { - listener.future(hash) - }, - } -} diff --git a/core/transaction-pool/graph/src/watcher.rs b/core/transaction-pool/graph/src/watcher.rs deleted file mode 100644 index 11d6b9f40742a..0000000000000 --- a/core/transaction-pool/graph/src/watcher.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Extrinsics status updates. - -use futures::{ - Stream, - channel::mpsc, -}; -use serde::{Serialize, Deserialize}; - -/// Possible extrinsic status events -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub enum Status { - /// Extrinsic is part of the future queue. - Future, - /// Extrinsic is part of the ready queue. - Ready, - /// Extrinsic has been finalized in block with given hash. - Finalized(H2), - /// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid. - Usurped(H), - /// The extrinsic has been broadcast to the given peers. - Broadcast(Vec), - /// Extrinsic has been dropped from the pool because of the limit. - Dropped, - /// Extrinsic was detected as invalid. - Invalid, -} - -/// Extrinsic watcher. -/// -/// Represents a stream of status updates for particular extrinsic. -#[derive(Debug)] -pub struct Watcher { - receiver: mpsc::UnboundedReceiver>, - hash: H, -} - -impl Watcher { - /// Returns the transaction hash. - pub fn hash(&self) -> &H { - &self.hash - } - - /// Pipe the notifications to given sink. - /// - /// Make sure to drive the future to completion. - pub fn into_stream(self) -> impl Stream> { - self.receiver - } -} - -/// Sender part of the watcher. Exposed only for testing purposes. -#[derive(Debug)] -pub struct Sender { - receivers: Vec>>, - finalized: bool, -} - -impl Default for Sender { - fn default() -> Self { - Sender { - receivers: Default::default(), - finalized: false, - } - } -} - -impl Sender { - /// Add a new watcher to this sender object. - pub fn new_watcher(&mut self, hash: H) -> Watcher { - let (tx, receiver) = mpsc::unbounded(); - self.receivers.push(tx); - Watcher { - receiver, - hash, - } - } - - /// Transaction became ready. - pub fn ready(&mut self) { - self.send(Status::Ready) - } - - /// Transaction was moved to future. - pub fn future(&mut self) { - self.send(Status::Future) - } - - /// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid. - pub fn usurped(&mut self, hash: H) { - self.send(Status::Usurped(hash)) - } - - /// Extrinsic has been finalized in block with given hash. - pub fn finalized(&mut self, hash: H2) { - self.send(Status::Finalized(hash)); - self.finalized = true; - } - - /// Extrinsic has been marked as invalid by the block builder. - pub fn invalid(&mut self) { - self.send(Status::Invalid); - // we mark as finalized as there are no more notifications - self.finalized = true; - } - - /// Transaction has been dropped from the pool because of the limit. - pub fn dropped(&mut self) { - self.send(Status::Dropped); - } - - /// The extrinsic has been broadcast to the given peers. - pub fn broadcast(&mut self, peers: Vec) { - self.send(Status::Broadcast(peers)) - } - - - /// Returns true if the are no more listeners for this extrinsic or it was finalized. - pub fn is_done(&self) -> bool { - self.finalized || self.receivers.is_empty() - } - - fn send(&mut self, status: Status) { - self.receivers.retain(|sender| sender.unbounded_send(status.clone()).is_ok()) - } -} diff --git a/core/transaction-pool/src/api.rs b/core/transaction-pool/src/api.rs deleted file mode 100644 index 96403bd3f876f..0000000000000 --- a/core/transaction-pool/src/api.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Chain api required for the transaction pool. - -use std::{ - sync::Arc, - marker::PhantomData, -}; -use client::{runtime_api::TaggedTransactionQueue, blockchain::HeaderBackend}; -use codec::Encode; -use txpool; -use primitives::{ - H256, - Blake2Hasher, - Hasher, -}; -use sr_primitives::{ - generic::BlockId, - traits, - transaction_validity::TransactionValidity, -}; - -use crate::error; - -/// The transaction pool logic -pub struct FullChainApi { - client: Arc, - _marker: PhantomData, -} - -impl FullChainApi where - Block: traits::Block, - T: traits::ProvideRuntimeApi + HeaderBackend { - /// Create new transaction pool logic. - pub fn new(client: Arc) -> Self { - FullChainApi { - client, - _marker: Default::default() - } - } -} - -impl txpool::ChainApi for FullChainApi where - Block: traits::Block, - T: traits::ProvideRuntimeApi + HeaderBackend, - T::Api: TaggedTransactionQueue -{ - type Block = Block; - type Hash = H256; - type Error = error::Error; - type ValidationFuture = futures::future::Ready>; - - fn validate_transaction( - &self, - at: &BlockId, - uxt: txpool::ExtrinsicFor, - ) -> Self::ValidationFuture { - futures::future::ready(self.client.runtime_api().validate_transaction(at, uxt).map_err(Into::into)) - } - - fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { - Ok(self.client.block_number_from_id(at)?) - } - - fn block_id_to_hash(&self, at: &BlockId) -> error::Result>> { - Ok(self.client.block_hash_from_id(at)?) - } - - 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 deleted file mode 100644 index f3641aa8ecee3..0000000000000 --- a/core/transaction-pool/src/error.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Transaction pool error. - -use client; -use txpool; - -/// Transaction pool result. -pub type Result = std::result::Result; - -/// Transaction pool error type. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// Client error. - Client(client::error::Error), - /// Pool error. - Pool(txpool::error::Error), -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::Client(ref err) => Some(err), - Error::Pool(ref err) => Some(err), - } - } -} - -impl txpool::IntoPoolError for Error { - fn into_pool_error(self) -> std::result::Result { - match self { - Error::Pool(e) => Ok(e), - e => Err(e), - } - } -} diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs deleted file mode 100644 index 6938166299d85..0000000000000 --- a/core/transaction-pool/src/lib.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate transaction pool. - -#![warn(missing_docs)] -#![warn(unused_extern_crates)] - -mod api; -#[cfg(test)] -mod tests; - -pub mod error; - -pub use api::FullChainApi; -pub use txpool; diff --git a/core/transaction-pool/src/tests.rs b/core/transaction-pool/src/tests.rs deleted file mode 100644 index d1ad27dd260f0..0000000000000 --- a/core/transaction-pool/src/tests.rs +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - - -use super::*; - -use codec::Encode; -use futures::executor::block_on; -use txpool::{self, Pool}; -use test_client::{runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}, AccountKeyring::{self, *}}; -use sr_primitives::{ - generic::{self, BlockId}, - traits::{Hash as HashT, BlakeTwo256}, - transaction_validity::{TransactionValidity, ValidTransaction}, -}; - -struct TestApi; - -impl TestApi { - fn default() -> Self { - TestApi - } -} - -impl txpool::ChainApi for TestApi { - type Block = Block; - type Hash = Hash; - type Error = error::Error; - type ValidationFuture = futures::future::Ready>; - - fn validate_transaction( - &self, - at: &BlockId, - uxt: txpool::ExtrinsicFor, - ) -> Self::ValidationFuture { - let expected = index(at); - let requires = if expected == uxt.transfer().nonce { - vec![] - } else { - vec![vec![uxt.transfer().nonce as u8 - 1]] - }; - let provides = vec![vec![uxt.transfer().nonce as u8]]; - - futures::future::ready(Ok( - Ok(ValidTransaction { - priority: 1, - requires, - provides, - longevity: 64, - propagate: true, - }) - )) - } - - fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { - Ok(Some(number_of(at))) - } - - fn block_id_to_hash(&self, at: &BlockId) -> error::Result>> { - Ok(match at { - generic::BlockId::Hash(x) => Some(x.clone()), - _ => Some(Default::default()), - }) - } - - fn hash_and_length(&self, ex: &txpool::ExtrinsicFor) -> (Self::Hash, usize) { - let encoded = ex.encode(); - (BlakeTwo256::hash(&encoded), encoded.len()) - } - -} - -fn index(at: &BlockId) -> u64 { - 209 + number_of(at) -} - -fn number_of(at: &BlockId) -> u64 { - match at { - generic::BlockId::Number(n) => *n as u64, - _ => 0, - } -} - -fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic { - let transfer = Transfer { - from: who.into(), - to: AccountId::default(), - nonce, - amount: 1, - }; - let signature = transfer.using_encoded(|e| who.sign(e)); - Extrinsic::Transfer(transfer, signature.into()) -} - -fn pool() -> Pool { - Pool::new(Default::default(), TestApi::default()) -} - -#[test] -fn submission_should_work() { - let pool = pool(); - assert_eq!(209, index(&BlockId::number(0))); - block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); - - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); - assert_eq!(pending, vec![209]); -} - -#[test] -fn multiple_submission_should_work() { - let pool = pool(); - block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); - block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); - - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); - assert_eq!(pending, vec![209, 210]); -} - -#[test] -fn early_nonce_should_be_culled() { - let pool = pool(); - block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 208))).unwrap(); - - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); - assert_eq!(pending, Vec::::new()); -} - -#[test] -fn late_nonce_should_be_queued() { - let pool = pool(); - - block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); - assert_eq!(pending, Vec::::new()); - - block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); - assert_eq!(pending, vec![209, 210]); -} - -#[test] -fn prune_tags_should_work() { - let pool = pool(); - block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); - block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); - - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); - assert_eq!(pending, vec![209, 210]); - - block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![])).unwrap(); - - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); - assert_eq!(pending, vec![210]); -} - -#[test] -fn should_ban_invalid_transactions() { - let pool = pool(); - let uxt = uxt(Alice, 209); - let hash = block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap(); - pool.remove_invalid(&[hash]); - block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap_err(); - - // when - let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); - assert_eq!(pending, Vec::::new()); - - // then - block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap_err(); -} diff --git a/core/trie/Cargo.toml b/core/trie/Cargo.toml deleted file mode 100644 index 50498a17ba65d..0000000000000 --- a/core/trie/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "substrate-trie" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Patricia trie stuff using a parity-scale-codec node format" -repository = "https://github.com/paritytech/substrate" -license = "GPL-3.0" -edition = "2018" - -[[bench]] -name = "bench" -harness = false - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -hash-db = { version = "0.15.2", default-features = false } -trie-db = { version = "0.15.2", default-features = false } -trie-root = { version = "0.15.2", default-features = false } -memory-db = { version = "0.15.2", default-features = false } -primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } - -[dev-dependencies] -trie-bench = "0.16.2" -trie-standardmap = "0.15.2" -keccak-hasher = "0.15.2" -criterion = "0.2.11" -hex-literal = "0.2.1" - -[features] -default = ["std"] -std = [ - "rstd/std", - "codec/std", - "hash-db/std", - "memory-db/std", - "trie-db/std", - "trie-root/std", - "primitives/std", -] diff --git a/core/trie/benches/bench.rs b/core/trie/benches/bench.rs deleted file mode 100644 index a8a473222285d..0000000000000 --- a/core/trie/benches/bench.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -use criterion::{Criterion, criterion_group, criterion_main}; -criterion_group!(benches, benchmark); -criterion_main!(benches); - -fn benchmark(c: &mut Criterion) { - trie_bench::standard_benchmark::< - substrate_trie::Layout, - substrate_trie::TrieStream, - >(c, "substrate-blake2"); - trie_bench::standard_benchmark::< - substrate_trie::Layout, - substrate_trie::TrieStream, - >(c, "substrate-keccak"); -} diff --git a/core/trie/src/error.rs b/core/trie/src/error.rs deleted file mode 100644 index c18db37f35ba3..0000000000000 --- a/core/trie/src/error.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015-2017 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[cfg(feature="std")] -use std::fmt; -#[cfg(feature="std")] -use std::error::Error as StdError; - -#[derive(Debug, PartialEq, Eq, Clone)] -/// Error for trie node decoding. -pub enum Error { - /// Bad format. - BadFormat, - /// Decoding error. - Decode(codec::Error) -} - -impl From for Error { - fn from(x: codec::Error) -> Self { - Error::Decode(x) - } -} - -#[cfg(feature="std")] -impl StdError for Error { - fn description(&self) -> &str { - match self { - Error::BadFormat => "Bad format error", - Error::Decode(_) => "Decoding error", - } - } -} - -#[cfg(feature="std")] -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::Decode(e) => write!(f, "Decode error: {}", e.what()), - Error::BadFormat => write!(f, "Bad format"), - } - } -} diff --git a/core/trie/src/lib.rs b/core/trie/src/lib.rs deleted file mode 100644 index eab05bab28af0..0000000000000 --- a/core/trie/src/lib.rs +++ /dev/null @@ -1,619 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -//! Utility functions to interact with Substrate's Base-16 Modified Merkle Patricia tree ("trie"). - -#![cfg_attr(not(feature = "std"), no_std)] - -mod error; -mod node_header; -mod node_codec; -mod trie_stream; - -use rstd::boxed::Box; -use rstd::vec::Vec; -use hash_db::Hasher; -/// Our `NodeCodec`-specific error. -pub use error::Error; -/// The Substrate format implementation of `TrieStream`. -pub use trie_stream::TrieStream; -/// The Substrate format implementation of `NodeCodec`. -pub use node_codec::NodeCodec; -/// Various re-exports from the `trie-db` crate. -pub use trie_db::{ - Trie, TrieMut, DBValue, Recorder, CError, Query, TrieLayout, TrieConfiguration, nibble_ops, -}; -/// Various re-exports from the `memory-db` crate. -pub use memory_db::KeyFunction; -pub use memory_db::prefixed_key; -/// Various re-exports from the `hash-db` crate. -pub use hash_db::{HashDB as HashDBT, EMPTY_PREFIX}; - -#[derive(Default)] -/// substrate trie layout -pub struct Layout(rstd::marker::PhantomData); - -impl TrieLayout for Layout { - const USE_EXTENSION: bool = false; - type Hash = H; - type Codec = NodeCodec; -} - -impl TrieConfiguration for Layout { - fn trie_root(input: I) -> ::Out where - I: IntoIterator, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]>, - { - trie_root::trie_root_no_extension::(input) - } - - fn trie_root_unhashed(input: I) -> Vec where - I: IntoIterator, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]>, - { - trie_root::unhashed_trie_no_extension::(input) - } - - fn encode_index(input: u32) -> Vec { - codec::Encode::encode(&codec::Compact(input)) - } -} - -/// TrieDB error over `TrieConfiguration` trait. -pub type TrieError = trie_db::TrieError, CError>; -/// Reexport from `hash_db`, with genericity set for `Hasher` trait. -pub trait AsHashDB: hash_db::AsHashDB {} -impl> AsHashDB for T {} -/// Reexport from `hash_db`, with genericity set for `Hasher` trait. -pub type HashDB<'a, H> = dyn hash_db::HashDB + 'a; -/// Reexport from `hash_db`, with genericity set for key only. -pub type PlainDB<'a, K> = dyn hash_db::PlainDB + 'a; -/// Reexport from `hash_db`, with genericity set for `Hasher` trait. -/// This uses a `KeyFunction` for prefixing keys internally (avoiding -/// key conflict for non random keys). -pub type PrefixedMemoryDB = memory_db::MemoryDB, trie_db::DBValue>; -/// Reexport from `hash_db`, with genericity set for `Hasher` trait. -/// This uses the `KeyFunction` for prefixing keys internally (avoiding -/// This uses a noops `KeyFunction` (key addressing must be hashed or using -/// an encoding scheme that avoid key conflict). -pub type MemoryDB = memory_db::MemoryDB, trie_db::DBValue>; -/// Reexport from `hash_db`, with genericity set for `Hasher` trait. -pub type GenericMemoryDB = memory_db::MemoryDB; - -/// Persistent trie database read-access interface for the a given hasher. -pub type TrieDB<'a, L> = trie_db::TrieDB<'a, L>; -/// Persistent trie database write-access interface for the a given hasher. -pub type TrieDBMut<'a, L> = trie_db::TrieDBMut<'a, L>; -/// Querying interface, as in `trie_db` but less generic. -pub type Lookup<'a, L, Q> = trie_db::Lookup<'a, L, Q>; -/// Hash type for a trie layout. -pub type TrieHash = <::Hash as Hasher>::Out; - -/// This module is for non generic definition of trie type. -/// Only the `Hasher` trait is generic in this case. -pub mod trie_types { - pub type Layout = super::Layout; - /// Persistent trie database read-access interface for the a given hasher. - pub type TrieDB<'a, H> = super::TrieDB<'a, Layout>; - /// Persistent trie database write-access interface for the a given hasher. - pub type TrieDBMut<'a, H> = super::TrieDBMut<'a, Layout>; - /// Querying interface, as in `trie_db` but less generic. - pub type Lookup<'a, H, Q> = trie_db::Lookup<'a, Layout, Q>; - /// As in `trie_db`, but less generic, error type for the crate. - pub type TrieError = trie_db::TrieError; -} - -/// Determine a trie root given a hash DB and delta values. -pub fn delta_trie_root( - db: &mut DB, - mut root: TrieHash, - delta: I -) -> Result, Box>> where - I: IntoIterator)>, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]>, - DB: hash_db::HashDB, -{ - { - let mut trie = TrieDBMut::::from_existing(&mut *db, &mut root)?; - - for (key, change) in delta { - match change { - Some(val) => trie.insert(key.as_ref(), val.as_ref())?, - None => trie.remove(key.as_ref())?, - }; - } - } - - Ok(root) -} - -/// Read a value from the trie. -pub fn read_trie_value>( - db: &DB, - root: &TrieHash, - 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< - L: TrieConfiguration, - Q: Query, - DB: hash_db::HashDBRef ->( - db: &DB, - root: &TrieHash, - key: &[u8], - query: Q -) -> Result>, Box>> { - Ok(TrieDB::::new(&*db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) -} - -/// Determine the default child trie root. -pub fn default_child_trie_root(_storage_key: &[u8]) -> Vec { - L::trie_root::<_, Vec, Vec>(core::iter::empty()).as_ref().iter().cloned().collect() -} - -/// Determine a child trie root given its ordered contents, closed form. H is the default hasher, -/// but a generic implementation may ignore this type parameter and use other hashers. -pub fn child_trie_root(_storage_key: &[u8], input: I) -> Vec - where - I: IntoIterator, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]>, -{ - L::trie_root(input).as_ref().iter().cloned().collect() -} - -/// 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 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, trie_db::DBValue>, -{ - let mut root = TrieHash::::default(); - // root is fetched from DB, not writable by runtime, so it's always valid. - root.as_mut().copy_from_slice(&root_vec); - - { - 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())?, - }; - } - } - - Ok(root.as_ref().to_vec()) -} - -/// Call `f` for all keys in a child trie. -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, trie_db::DBValue>, -{ - let mut root = TrieHash::::default(); - // root is fetched from DB, not writable by runtime, so it's always valid. - root.as_mut().copy_from_slice(root_slice); - - let trie = TrieDB::::new(&*db, &root)?; - let iter = trie.iter()?; - - for x in iter { - let (key, _) = x?; - f(&key); - } - - Ok(()) -} - -/// Record all keys for a given root. -pub fn record_all_keys( - db: &DB, - root: &TrieHash, - recorder: &mut Recorder> -) -> Result<(), Box>> where - DB: hash_db::HashDBRef -{ - let trie = TrieDB::::new(&*db, root)?; - let iter = trie.iter()?; - - for x in iter { - let (key, _) = x?; - - // there's currently no API like iter_with() - // => use iter to enumerate all keys AND lookup each - // key using get_with - trie.get_with(&key, &mut *recorder)?; - } - - Ok(()) -} - -/// Read a value from the child trie. -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, trie_db::DBValue>, -{ - let mut root = TrieHash::::default(); - // root is fetched from DB, not writable by runtime, so it's always valid. - root.as_mut().copy_from_slice(root_slice); - - 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, DB>( - _storage_key: &[u8], - db: &DB, - root_slice: &[u8], - key: &[u8], - query: Q -) -> Result>, Box>> - where - DB: hash_db::HashDBRef - + hash_db::PlainDBRef, trie_db::DBValue>, -{ - let mut root = TrieHash::::default(); - // root is fetched from DB, not writable by runtime, so it's always valid. - root.as_mut().copy_from_slice(root_slice); - - Ok(TrieDB::::new(&*db, &root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) -} - -/// Constants used into trie simplification codec. -mod trie_constants { - pub const EMPTY_TRIE: u8 = 0; - pub const NIBBLE_SIZE_BOUND: usize = u16::max_value() as usize; - pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6; - pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6; - pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6; -} - -#[cfg(test)] -mod tests { - use super::*; - use codec::{Encode, Compact}; - use primitives::Blake2Hasher; - use hash_db::{HashDB, Hasher}; - use trie_db::{DBValue, TrieMut, Trie, NodeCodec as NodeCodecT}; - use trie_standardmap::{Alphabet, ValueMode, StandardMap}; - use hex_literal::hex; - - type Layout = super::Layout; - - fn hashed_null_node() -> TrieHash { - >::hashed_null_node() - } - - fn check_equivalent(input: &Vec<(&[u8], &[u8])>) { - { - let closed_form = T::trie_root(input.clone()); - let d = T::trie_root_unhashed(input.clone()); - println!("Data: {:#x?}, {:#x?}", d, Blake2Hasher::hash(&d[..])); - let persistent = { - let mut memdb = MemoryDB::default(); - let mut root = Default::default(); - let mut t = TrieDBMut::::new(&mut memdb, &mut root); - for (x, y) in input.iter().rev() { - t.insert(x, y).unwrap(); - } - t.root().clone() - }; - assert_eq!(closed_form, persistent); - } - } - - fn check_iteration(input: &Vec<(&[u8], &[u8])>) { - let mut memdb = MemoryDB::default(); - let mut root = Default::default(); - { - let mut t = TrieDBMut::::new(&mut memdb, &mut root); - for (x, y) in input.clone() { - t.insert(x, y).unwrap(); - } - } - { - let t = TrieDB::::new(&mut memdb, &root).unwrap(); - assert_eq!( - input.iter().map(|(i, j)| (i.to_vec(), j.to_vec())).collect::>(), - t.iter().unwrap() - .map(|x| x.map(|y| (y.0, y.1.to_vec())).unwrap()) - .collect::>() - ); - } - } - - #[test] - fn default_trie_root() { - let mut db = MemoryDB::default(); - let mut root = TrieHash::::default(); - let mut empty = TrieDBMut::::new(&mut db, &mut root); - empty.commit(); - let root1 = empty.root().as_ref().to_vec(); - let root2: Vec = Layout::trie_root::<_, Vec, Vec>( - std::iter::empty(), - ).as_ref().iter().cloned().collect(); - - assert_eq!(root1, root2); - } - - #[test] - fn empty_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![]; - check_equivalent::(&input); - check_iteration::(&input); - } - - #[test] - fn leaf_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0xbb][..])]; - check_equivalent::(&input); - check_iteration::(&input); - } - - #[test] - fn branch_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![ - (&[0xaa][..], &[0x10][..]), - (&[0xba][..], &[0x11][..]), - ]; - check_equivalent::(&input); - check_iteration::(&input); - } - - #[test] - fn extension_and_branch_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![ - (&[0xaa][..], &[0x10][..]), - (&[0xab][..], &[0x11][..]), - ]; - check_equivalent::(&input); - check_iteration::(&input); - } - - #[test] - fn standard_is_equivalent() { - let st = StandardMap { - alphabet: Alphabet::All, - min_key: 32, - journal_key: 0, - value_mode: ValueMode::Random, - count: 1000, - }; - let mut d = st.make(); - d.sort_unstable_by(|&(ref a, _), &(ref b, _)| a.cmp(b)); - let dr = d.iter().map(|v| (&v.0[..], &v.1[..])).collect(); - check_equivalent::(&dr); - check_iteration::(&dr); - } - - #[test] - fn extension_and_branch_with_value_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![ - (&[0xaa][..], &[0xa0][..]), - (&[0xaa, 0xaa][..], &[0xaa][..]), - (&[0xaa, 0xbb][..], &[0xab][..]) - ]; - check_equivalent::(&input); - check_iteration::(&input); - } - - #[test] - fn bigger_extension_and_branch_with_value_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![ - (&[0xaa][..], &[0xa0][..]), - (&[0xaa, 0xaa][..], &[0xaa][..]), - (&[0xaa, 0xbb][..], &[0xab][..]), - (&[0xbb][..], &[0xb0][..]), - (&[0xbb, 0xbb][..], &[0xbb][..]), - (&[0xbb, 0xcc][..], &[0xbc][..]), - ]; - check_equivalent::(&input); - check_iteration::(&input); - } - - #[test] - fn single_long_leaf_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![ - (&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]), - (&[0xba][..], &[0x11][..]), - ]; - check_equivalent::(&input); - check_iteration::(&input); - } - - #[test] - fn two_long_leaves_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![ - (&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]), - (&[0xba][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]) - ]; - check_equivalent::(&input); - check_iteration::(&input); - } - - fn populate_trie<'db, T: TrieConfiguration>( - db: &'db mut dyn HashDB, - root: &'db mut TrieHash, - v: &[(Vec, Vec)] - ) -> TrieDBMut<'db, T> { - let mut t = TrieDBMut::::new(db, root); - for i in 0..v.len() { - let key: &[u8]= &v[i].0; - let val: &[u8] = &v[i].1; - t.insert(key, val).unwrap(); - } - t - } - - fn unpopulate_trie<'db, T: TrieConfiguration>( - t: &mut TrieDBMut<'db, T>, - v: &[(Vec, Vec)], - ) { - for i in v { - let key: &[u8]= &i.0; - t.remove(key).unwrap(); - } - } - - #[test] - fn random_should_work() { - let mut seed = ::Out::zero(); - for test_i in 0..10000 { - if test_i % 50 == 0 { - println!("{:?} of 10000 stress tests done", test_i); - } - let x = StandardMap { - alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()), - min_key: 5, - journal_key: 0, - value_mode: ValueMode::Index, - count: 100, - }.make_with(seed.as_fixed_bytes_mut()); - - let real = Layout::trie_root(x.clone()); - let mut memdb = MemoryDB::default(); - let mut root = Default::default(); - let mut memtrie = populate_trie::(&mut memdb, &mut root, &x); - - memtrie.commit(); - if *memtrie.root() != real { - println!("TRIE MISMATCH"); - println!(""); - println!("{:?} vs {:?}", memtrie.root(), real); - for i in &x { - println!("{:#x?} -> {:#x?}", i.0, i.1); - } - } - assert_eq!(*memtrie.root(), real); - unpopulate_trie::(&mut memtrie, &x); - memtrie.commit(); - let hashed_null_node = hashed_null_node::(); - if *memtrie.root() != hashed_null_node { - println!("- TRIE MISMATCH"); - println!(""); - println!("{:?} vs {:?}", memtrie.root(), hashed_null_node); - for i in &x { - println!("{:#x?} -> {:#x?}", i.0, i.1); - } - } - assert_eq!(*memtrie.root(), hashed_null_node); - } - } - - fn to_compact(n: u8) -> u8 { - Compact(n).encode()[0] - } - - #[test] - fn codec_trie_empty() { - let input: Vec<(&[u8], &[u8])> = vec![]; - let trie = Layout::trie_root_unhashed::<_, _, _>(input); - println!("trie: {:#x?}", trie); - assert_eq!(trie, vec![0x0]); - } - - #[test] - fn codec_trie_single_tuple() { - let input = vec![ - (vec![0xaa], vec![0xbb]) - ]; - let trie = Layout::trie_root_unhashed::<_, _, _>(input); - println!("trie: {:#x?}", trie); - assert_eq!(trie, vec![ - 0x42, // leaf 0x40 (2^6) with (+) key of 2 nibbles (0x02) - 0xaa, // key data - to_compact(1), // length of value in bytes as Compact - 0xbb // value data - ]); - } - - #[test] - fn codec_trie_two_tuples_disjoint_keys() { - let input = vec![(&[0x48, 0x19], &[0xfe]), (&[0x13, 0x14], &[0xff])]; - let trie = Layout::trie_root_unhashed::<_, _, _>(input); - println!("trie: {:#x?}", trie); - let mut ex = Vec::::new(); - ex.push(0x80); // branch, no value (0b_10..) no nibble - ex.push(0x12); // slots 1 & 4 are taken from 0-7 - ex.push(0x00); // no slots from 8-15 - ex.push(to_compact(0x05)); // first slot: LEAF, 5 bytes long. - ex.push(0x43); // leaf 0x40 with 3 nibbles - ex.push(0x03); // first nibble - ex.push(0x14); // second & third nibble - ex.push(to_compact(0x01)); // 1 byte data - ex.push(0xff); // value data - ex.push(to_compact(0x05)); // second slot: LEAF, 5 bytes long. - ex.push(0x43); // leaf with 3 nibbles - ex.push(0x08); // first nibble - ex.push(0x19); // second & third nibble - ex.push(to_compact(0x01)); // 1 byte data - ex.push(0xfe); // value data - - assert_eq!(trie, ex); - } - - #[test] - fn iterator_works() { - let pairs = vec![ - (hex!("0103000000000000000464").to_vec(), hex!("0400000000").to_vec()), - (hex!("0103000000000000000469").to_vec(), hex!("0401000000").to_vec()), - ]; - - let mut mdb = MemoryDB::default(); - let mut root = Default::default(); - let _ = populate_trie::(&mut mdb, &mut root, &pairs); - - let trie = TrieDB::::new(&mdb, &root).unwrap(); - - let iter = trie.iter().unwrap(); - let mut iter_pairs = Vec::new(); - for pair in iter { - let (key, value) = pair.unwrap(); - iter_pairs.push((key, value.to_vec())); - } - - assert_eq!(pairs, iter_pairs); - } -} diff --git a/core/trie/src/node_codec.rs b/core/trie/src/node_codec.rs deleted file mode 100644 index 03cbdfce528f4..0000000000000 --- a/core/trie/src/node_codec.rs +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -//! `NodeCodec` implementation for Substrate's trie format. - -use rstd::marker::PhantomData; -use rstd::vec::Vec; -use rstd::borrow::Borrow; -use codec::{Encode, Decode, Compact}; -use hash_db::Hasher; -use trie_db::{self, NibbleSlice, node::Node, ChildReference, - nibble_ops, Partial, NodeCodec as NodeCodecT}; -use crate::error::Error; -use crate::trie_constants; -use super::{node_header::{NodeHeader, NodeKind}}; - -fn take<'a>(input: &mut &'a[u8], count: usize) -> Option<&'a[u8]> { - if input.len() < count { - return None - } - let r = &(*input)[..count]; - *input = &(*input)[count..]; - Some(r) -} - -/// Concrete implementation of a `NodeCodec` with Parity Codec encoding, generic over the `Hasher` -#[derive(Default, Clone)] -pub struct NodeCodec(PhantomData); - -impl NodeCodecT for NodeCodec { - type Error = Error; - - fn hashed_null_node() -> ::Out { - H::hash(>::empty_node()) - } - - fn decode(data: &[u8]) -> rstd::result::Result { - let input = &mut &*data; - let head = NodeHeader::decode(input)?; - match head { - NodeHeader::Null => Ok(Node::Empty), - NodeHeader::Branch(has_value, nibble_count) => { - let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0; - // check that the padding is valid (if any) - if padding && nibble_ops::pad_left(input[0]) != 0 { - return Err(Error::BadFormat); - } - let nibble_data = take( - input, - (nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) / nibble_ops::NIBBLE_PER_BYTE, - ).ok_or(Error::BadFormat)?; - let nibble_slice = NibbleSlice::new_offset( - nibble_data, - nibble_ops::number_padding(nibble_count), - ); - let bitmap_slice = take(input, BITMAP_LENGTH).ok_or(Error::BadFormat)?; - let bitmap = Bitmap::decode(&bitmap_slice[..])?; - let value = if has_value { - let count = >::decode(input)?.0 as usize; - Some(take(input, count).ok_or(Error::BadFormat)?) - } else { - None - }; - let mut children = [None; 16]; - - for i in 0..nibble_ops::NIBBLE_LENGTH { - if bitmap.value_at(i) { - let count = >::decode(input)?.0 as usize; - children[i] = Some(take(input, count).ok_or(Error::BadFormat)?); - } - } - Ok(Node::NibbledBranch(nibble_slice, children, value)) - } - NodeHeader::Leaf(nibble_count) => { - let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0; - // check that the padding is valid (if any) - if padding && nibble_ops::pad_left(input[0]) != 0 { - return Err(Error::BadFormat); - } - let nibble_data = take( - input, - (nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) / nibble_ops::NIBBLE_PER_BYTE, - ).ok_or(Error::BadFormat)?; - let nibble_slice = NibbleSlice::new_offset( - nibble_data, - nibble_ops::number_padding(nibble_count), - ); - let count = >::decode(input)?.0 as usize; - Ok(Node::Leaf(nibble_slice, take(input, count).ok_or(Error::BadFormat)?)) - } - } - } - - fn try_decode_hash(data: &[u8]) -> Option<::Out> { - if data.len() == H::LENGTH { - let mut r = ::Out::default(); - r.as_mut().copy_from_slice(data); - Some(r) - } else { - None - } - } - - fn is_empty_node(data: &[u8]) -> bool { - data == >::empty_node() - } - - fn empty_node() -> &'static [u8] { - &[trie_constants::EMPTY_TRIE] - } - - fn leaf_node(partial: Partial, value: &[u8]) -> Vec { - let mut output = partial_encode(partial, NodeKind::Leaf); - value.encode_to(&mut output); - output - } - - fn extension_node( - _partial: impl Iterator, - _nbnibble: usize, - _child: ChildReference<::Out>, - ) -> Vec { - unreachable!() - } - - fn branch_node( - _children: impl Iterator::Out>>>>, - _maybe_value: Option<&[u8]>, - ) -> Vec { - unreachable!() - } - - fn branch_node_nibbled( - partial: impl Iterator, - number_nibble: usize, - children: impl Iterator::Out>>>>, - maybe_value: Option<&[u8]>, - ) -> Vec { - let mut output = if maybe_value.is_some() { - partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchWithValue) - } else { - partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchNoValue) - }; - let bitmap_index = output.len(); - let mut bitmap: [u8; BITMAP_LENGTH] = [0; BITMAP_LENGTH]; - (0..BITMAP_LENGTH).for_each(|_|output.push(0)); - if let Some(value) = maybe_value { - value.encode_to(&mut output); - }; - Bitmap::encode(children.map(|maybe_child| match maybe_child.borrow() { - Some(ChildReference::Hash(h)) => { - h.as_ref().encode_to(&mut output); - true - } - &Some(ChildReference::Inline(inline_data, len)) => { - inline_data.as_ref()[..len].encode_to(&mut output); - true - } - None => false, - }), bitmap.as_mut()); - output[bitmap_index..bitmap_index + BITMAP_LENGTH] - .copy_from_slice(&bitmap[..BITMAP_LENGTH]); - output - } - -} - -// utils - -/// Encode and allocate node type header (type and size), and partial value. -/// It uses an iterator over encoded partial bytes as input. -fn partial_from_iterator_encode>( - partial: I, - nibble_count: usize, - node_kind: NodeKind, -) -> Vec { - let nibble_count = rstd::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibble_count); - - let mut output = Vec::with_capacity(3 + (nibble_count / nibble_ops::NIBBLE_PER_BYTE)); - match node_kind { - NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output), - NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output), - NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output), - }; - output.extend(partial); - output -} - -/// Encode and allocate node type header (type and size), and partial value. -/// Same as `partial_from_iterator_encode` but uses non encoded `Partial` as input. -fn partial_encode(partial: Partial, node_kind: NodeKind) -> Vec { - let number_nibble_encoded = (partial.0).0 as usize; - let nibble_count = partial.1.len() * nibble_ops::NIBBLE_PER_BYTE + number_nibble_encoded; - - let nibble_count = rstd::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibble_count); - - let mut output = Vec::with_capacity(3 + partial.1.len()); - match node_kind { - NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output), - NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output), - NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output), - }; - if number_nibble_encoded > 0 { - output.push(nibble_ops::pad_right((partial.0).1)); - } - output.extend_from_slice(&partial.1[..]); - output -} - -const BITMAP_LENGTH: usize = 2; - -/// Radix 16 trie, bitmap encoding implementation, -/// it contains children mapping information for a branch -/// (children presence only), it encodes into -/// a compact bitmap encoding representation. -pub(crate) struct Bitmap(u16); - -impl Bitmap { - pub fn decode(data: &[u8]) -> Result { - Ok(Bitmap(u16::decode(&mut &data[..])?)) - } - - pub fn value_at(&self, i: usize) -> bool { - self.0 & (1u16 << i) != 0 - } - - pub fn encode>(has_children: I , dest: &mut [u8]) { - let mut bitmap: u16 = 0; - let mut cursor: u16 = 1; - for v in has_children { - if v { bitmap |= cursor } - cursor <<= 1; - } - dest[0] = (bitmap % 256) as u8; - dest[1] = (bitmap / 256) as u8; - } -} - diff --git a/core/utils/fork-tree/src/lib.rs b/core/utils/fork-tree/src/lib.rs deleted file mode 100644 index f192ee54785b1..0000000000000 --- a/core/utils/fork-tree/src/lib.rs +++ /dev/null @@ -1,1264 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Utility library for managing tree-like ordered data with logic for pruning -//! the tree while finalizing nodes. - -#![warn(missing_docs)] - -use std::fmt; -use codec::{Decode, Encode}; - -/// Error occured when iterating with the tree. -#[derive(Clone, Debug, PartialEq)] -pub enum Error { - /// Adding duplicate node to tree. - Duplicate, - /// Finalizing descendent of tree node without finalizing ancestor(s). - UnfinalizedAncestor, - /// Imported or finalized node that is an ancestor of previously finalized node. - Revert, - /// Error throw by client when checking for node ancestry. - Client(E), -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let message = match *self { - Error::Duplicate => "Hash already exists in Tree".into(), - Error::UnfinalizedAncestor => "Finalized descendent of Tree node without finalizing its ancestor(s) first".into(), - Error::Revert => "Tried to import or finalize node that is an ancestor of a previously finalized node".into(), - Error::Client(ref err) => format!("Client error: {}", err), - }; - write!(f, "{}", message) - } -} - -impl std::error::Error for Error { - fn cause(&self) -> Option<&dyn std::error::Error> { - None - } -} - -impl From for Error { - fn from(err: E) -> Error { - Error::Client(err) - } -} - -/// Result of finalizing a node (that could be a part of the tree or not). -#[derive(Debug, PartialEq)] -pub enum FinalizationResult { - /// The tree has changed, optionally return the value associated with the finalized node. - Changed(Option), - /// The tree has not changed. - Unchanged, -} - -/// 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 + Clone, - N: Ord + Clone, - V: Clone, -{ - /// Prune the tree, removing all non-canonical nodes. We find the node in the - /// tree that is the deepest ancestor of the given hash and that passes the - /// given predicate. If such a node exists, we re-root the tree to this - /// node. Otherwise the tree remains unchanged. The given function - /// `is_descendent_of` should return `true` if the second hash (target) is a - /// descendent of the first hash (base). - pub fn prune( - &mut self, - hash: &H, - number: &N, - is_descendent_of: &F, - predicate: &P, - ) -> Result<(), Error> - where E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - let new_root = self.find_node_where( - hash, - number, - is_descendent_of, - predicate, - )?; - - if let Some(root) = new_root { - let mut root = root.clone(); - - // we found the deepest ancestor of the finalized block, so we prune - // out any children that don't include the finalized block. - let children = std::mem::replace(&mut root.children, Vec::new()); - root.children = children.into_iter().filter(|node| { - node.number == *number && node.hash == *hash || - node.number < *number && is_descendent_of(&node.hash, hash).unwrap_or(false) - }).take(1).collect(); - - self.roots = vec![root]; - } - - Ok(()) - } -} - -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. - /// - /// Returns `true` if the imported node is a root. - 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)) - } - - /// Find a node in the tree that is the deepest ancestor of the given - /// block hash and which passes the given predicate. The given function - /// `is_descendent_of` should return `true` if the second hash (target) - /// is a descendent of the first hash (base). - pub fn find_node_where( - &self, - hash: &H, - number: &N, - is_descendent_of: &F, - predicate: &P, - ) -> Result>, Error> - where E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - // search for node starting from all roots - for root in self.roots.iter() { - let node = root.find_node_where(hash, number, is_descendent_of, predicate)?; - - // found the node, early exit - if let FindOutcome::Found(node) = node { - return Ok(Some(node)); - } - } - - Ok(None) - } - - /// Finalize a root in the tree and return it, return `None` in case no root - /// with the given hash exists. All other roots are pruned, and the children - /// of the finalized node become the new roots. - pub fn finalize_root(&mut self, hash: &H) -> Option { - self.roots.iter().position(|node| node.hash == *hash) - .map(|position| self.finalize_root_at(position)) - } - - /// Finalize root at given positiion. See `finalize_root` comment for details. - fn finalize_root_at(&mut self, position: usize) -> V { - let node = self.roots.swap_remove(position); - self.roots = node.children; - self.best_finalized_number = Some(node.number); - return node.data; - } - - /// Finalize a node in the tree. This method will make sure that the node - /// being finalized is either an existing root (and return its data), or a - /// node from a competing branch (not in the tree), tree pruning is done - /// accordingly. The given function `is_descendent_of` should return `true` - /// if the second hash (target) is a descendent of the first hash (base). - pub fn finalize( - &mut self, - hash: &H, - number: N, - is_descendent_of: &F, - ) -> Result, Error> - where E: std::error::Error, - F: Fn(&H, &H) -> Result - { - if let Some(ref best_finalized_number) = self.best_finalized_number { - if number <= *best_finalized_number { - return Err(Error::Revert); - } - } - - // check if one of the current roots is being finalized - if let Some(root) = self.finalize_root(hash) { - return Ok(FinalizationResult::Changed(Some(root))); - } - - // make sure we're not finalizing a descendent of any root - for root in self.roots.iter() { - if number > root.number && is_descendent_of(&root.hash, hash)? { - return Err(Error::UnfinalizedAncestor); - } - } - - // we finalized a block earlier than any existing root (or possibly - // another fork not part of the tree). make sure to only keep roots that - // are part of the finalized branch - let mut changed = false; - 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) - } - } - - /// Finalize a node in the tree and all its ancestors. The given function - /// `is_descendent_of` should return `true` if the second hash (target) is - // a descendent of the first hash (base). - pub fn finalize_with_ancestors( - &mut self, - hash: &H, - number: N, - is_descendent_of: &F, - ) -> Result, Error> - where E: std::error::Error, - F: Fn(&H, &H) -> Result - { - if let Some(ref best_finalized_number) = self.best_finalized_number { - if number <= *best_finalized_number { - return Err(Error::Revert); - } - } - - // check if one of the current roots is being finalized - if let Some(root) = self.finalize_root(hash) { - return Ok(FinalizationResult::Changed(Some(root))); - } - - // we need to: - // 1) remove all roots that are not ancestors AND not descendants of finalized block; - // 2) if node is descendant - just leave it; - // 3) if node is ancestor - 'open it' - let mut changed = false; - let mut idx = 0; - while idx != self.roots.len() { - let (is_finalized, is_descendant, is_ancestor) = { - let root = &self.roots[idx]; - let is_finalized = root.hash == *hash; - let is_descendant = !is_finalized - && root.number > number && is_descendent_of(hash, &root.hash).unwrap_or(false); - let is_ancestor = !is_finalized && !is_descendant - && root.number < number && is_descendent_of(&root.hash, hash).unwrap_or(false); - (is_finalized, is_descendant, is_ancestor) - }; - - // if we have met finalized root - open it and return - if is_finalized { - return Ok(FinalizationResult::Changed(Some(self.finalize_root_at(idx)))); - } - - // if node is descendant of finalized block - just leave it as is - if is_descendant { - idx += 1; - continue; - } - - // if node is ancestor of finalized block - remove it and continue with children - if is_ancestor { - let root = self.roots.swap_remove(idx); - self.roots.extend(root.children); - changed = true; - continue; - } - - // if node is neither ancestor, nor descendant of the finalized block - remove it - self.roots.swap_remove(idx); - changed = true; - } - - self.best_finalized_number = Some(number); - - if changed { - Ok(FinalizationResult::Changed(None)) - } else { - Ok(FinalizationResult::Unchanged) - } - } - - /// Checks if any node in the tree is finalized by either finalizing the - /// node itself or a child node that's not in the tree, guaranteeing that - /// the node being finalized isn't a descendent of any of the node's - /// children. Returns `Some(true)` if the node being finalized is a root, - /// `Some(false)` if the node being finalized is not a root, and `None` if - /// no node in the tree is finalized. The given `predicate` is checked on - /// the prospective finalized root and must pass for finalization to occur. - /// The given function `is_descendent_of` should return `true` if the second - /// hash (target) is a descendent of the first hash (base). - pub fn finalizes_any_with_descendent_if( - &self, - hash: &H, - number: N, - is_descendent_of: &F, - predicate: P, - ) -> Result, Error> - where E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - if let Some(ref best_finalized_number) = self.best_finalized_number { - if number <= *best_finalized_number { - return Err(Error::Revert); - } - } - - // check if the given hash is equal or a descendent of any node in the - // tree, if we find a valid node that passes the predicate then we must - // ensure that we're not finalizing past any of its child nodes. - for node in self.node_iter() { - if predicate(&node.data) { - if node.hash == *hash || is_descendent_of(&node.hash, hash)? { - for node in node.children.iter() { - if node.number <= number && is_descendent_of(&node.hash, &hash)? { - return Err(Error::UnfinalizedAncestor); - } - } - - return Ok(Some(self.roots.iter().any(|root| root.hash == node.hash))); - } - } - } - - Ok(None) - } - - /// Finalize a root in the tree by either finalizing the node itself or a - /// 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 predicate(&root.data) { - if root.hash == *hash || is_descendent_of(&root.hash, hash)? { - 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::*; - - /// The outcome of a search within a node. - pub enum FindOutcome { - // this is the node we were looking for. - Found(T), - // not the node we're looking for. contains a flag indicating - // whether the node was a descendent. true implies the predicate failed. - Failure(bool), - // Abort search. - Abort, - } - - #[derive(Clone, Debug, Decode, Encode, PartialEq)] - pub struct Node { - pub hash: H, - 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))) - } - } - - /// Find a node in the tree that is the deepest ancestor of the given - /// block hash which also passes the given predicate, backtracking - /// when the predicate fails. - /// The given function `is_descendent_of` should return `true` if the second hash (target) - /// is a descendent of the first hash (base). - // FIXME: it would be useful if this returned a mutable reference but - // rustc can't deal with lifetimes properly. an option would be to try - // an iterative definition instead. - pub fn find_node_where( - &self, - hash: &H, - number: &N, - is_descendent_of: &F, - predicate: &P, - ) -> Result>, Error> - where E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - // stop searching this branch - if *number < self.number { - return Ok(FindOutcome::Failure(false)); - } - - let mut known_descendent_of = false; - - // continue depth-first search through all children - for node in self.children.iter() { - // found node, early exit - match node.find_node_where(hash, number, is_descendent_of, predicate)? { - FindOutcome::Abort => return Ok(FindOutcome::Abort), - FindOutcome::Found(x) => return Ok(FindOutcome::Found(x)), - FindOutcome::Failure(true) => { - // if the block was a descendent of this child, - // then it cannot be a descendent of any others, - // so we don't search them. - known_descendent_of = true; - break; - }, - FindOutcome::Failure(false) => {}, - } - } - - // node not found in any of the descendents, if the node we're - // searching for is a descendent of this node then we will stop the - // search here, since there aren't any more children and we found - // the correct node so we don't want to backtrack. - let is_descendent_of = known_descendent_of || is_descendent_of(&self.hash, hash)?; - if is_descendent_of { - // if the predicate passes we return the node - if predicate(&self.data) { - return Ok(FindOutcome::Found(self)); - } - } - - // otherwise, tell our ancestor that we failed, and whether - // the block was a descendent. - Ok(FindOutcome::Failure(is_descendent_of)) - } - } -} - -// Workaround for: https://github.com/rust-lang/rust/issues/34537 -use node_implementation::{Node, FindOutcome}; - -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 - // \ - // - L - M - N - // \ - // - O - // \ - // — J - K - // - // (where N is not a part of fork tree) - let is_descendent_of = |base: &&str, block: &&str| -> Result { - let letters = vec!["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]; - match (*base, *block) { - ("A", b) => Ok(letters.into_iter().any(|n| n == b)), - ("B", b) => Ok(b == "C" || b == "D" || b == "E"), - ("C", b) => Ok(b == "D" || b == "E"), - ("D", b) => Ok(b == "E"), - ("E", _) => Ok(false), - ("F", b) => Ok(b == "G" || b == "H" || b == "I" || b == "L" || b == "M" || b == "N" || b == "O"), - ("G", _) => Ok(false), - ("H", b) => Ok(b == "I" || b == "L" || b == "M" || b == "O"), - ("I", _) => Ok(false), - ("J", b) => Ok(b == "K"), - ("K", _) => Ok(false), - ("L", b) => Ok(b == "M" || b == "O" || b == "N"), - ("M", b) => Ok(b == "N"), - ("N", _) => Ok(false), - ("O", _) => Ok(false), - ("0", _) => Ok(true), - _ => Ok(false), - } - }; - - tree.import("A", 1, (), &is_descendent_of).unwrap(); - - tree.import("B", 2, (), &is_descendent_of).unwrap(); - tree.import("C", 3, (), &is_descendent_of).unwrap(); - tree.import("D", 4, (), &is_descendent_of).unwrap(); - tree.import("E", 5, (), &is_descendent_of).unwrap(); - - tree.import("F", 2, (), &is_descendent_of).unwrap(); - tree.import("G", 3, (), &is_descendent_of).unwrap(); - - tree.import("H", 3, (), &is_descendent_of).unwrap(); - tree.import("I", 4, (), &is_descendent_of).unwrap(); - tree.import("L", 4, (), &is_descendent_of).unwrap(); - tree.import("M", 5, (), &is_descendent_of).unwrap(); - tree.import("O", 5, (), &is_descendent_of).unwrap(); - - tree.import("J", 2, (), &is_descendent_of).unwrap(); - tree.import("K", 3, (), &is_descendent_of).unwrap(); - - (tree, is_descendent_of) - } - - #[test] - fn import_doesnt_revert() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - tree.finalize_root(&"A"); - - assert_eq!( - tree.best_finalized_number, - Some(1), - ); - - assert_eq!( - tree.import("A", 1, (), &is_descendent_of), - Err(Error::Revert), - ); - } - - #[test] - fn import_doesnt_add_duplicates() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - assert_eq!( - tree.import("A", 1, (), &is_descendent_of), - Err(Error::Duplicate), - ); - - assert_eq!( - tree.import("I", 4, (), &is_descendent_of), - Err(Error::Duplicate), - ); - - assert_eq!( - tree.import("G", 3, (), &is_descendent_of), - Err(Error::Duplicate), - ); - - assert_eq!( - tree.import("K", 3, (), &is_descendent_of), - Err(Error::Duplicate), - ); - } - - #[test] - fn finalize_root_works() { - let finalize_a = || { - let (mut tree, ..) = test_fork_tree(); - - assert_eq!( - tree.roots().map(|(h, n, _)| (h.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), ("L", 4)], - ); - - // finalizing a node from another fork that isn't part of the tree clears the tree - assert_eq!( - tree.finalize(&"Z", 5, &is_descendent_of), - Ok(FinalizationResult::Changed(None)), - ); - - assert!(tree.roots.is_empty()); - } - - #[test] - fn finalize_with_ancestor_works() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - let original_roots = tree.roots.clone(); - - // finalizing a block prior to any in the node doesn't change the tree - assert_eq!( - tree.finalize_with_ancestors(&"0", 0, &is_descendent_of), - Ok(FinalizationResult::Unchanged), - ); - - assert_eq!(tree.roots, original_roots); - - // finalizing "A" opens up three possible forks - assert_eq!( - tree.finalize_with_ancestors(&"A", 1, &is_descendent_of), - Ok(FinalizationResult::Changed(Some(()))), - ); - - assert_eq!( - tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), - vec![("B", 2), ("F", 2), ("J", 2)], - ); - - // finalizing H: - // 1) removes roots that are not ancestors/descendants of H (B, J) - // 2) opens root that is ancestor of H (F -> G+H) - // 3) finalizes the just opened root H (H -> I + L) - assert_eq!( - tree.finalize_with_ancestors(&"H", 3, &is_descendent_of), - Ok(FinalizationResult::Changed(Some(()))), - ); - - assert_eq!( - tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), - vec![("I", 4), ("L", 4)], - ); - - assert_eq!( - tree.best_finalized_number, - Some(3), - ); - - // finalizing N (which is not a part of the tree): - // 1) removes roots that are not ancestors/descendants of N (I) - // 2) opens root that is ancestor of N (L -> M+O) - // 3) removes roots that are not ancestors/descendants of N (O) - // 4) opens root that is ancestor of N (M -> {}) - assert_eq!( - tree.finalize_with_ancestors(&"N", 6, &is_descendent_of), - Ok(FinalizationResult::Changed(None)), - ); - - assert_eq!( - tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), - vec![], - ); - - assert_eq!( - tree.best_finalized_number, - Some(6), - ); - } - - #[test] - fn finalize_with_descendent_works() { - #[derive(Debug, PartialEq)] - 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(None), - ); - - // finalizing "D" will finalize a block from the tree, but it can't be applied yet - // since it is not a root change - assert_eq!( - tree.finalizes_any_with_descendent_if( - &"D", - 10, - &is_descendent_of, - |c| c.effective == 10, - ), - Ok(Some(false)), - ); - - // finalizing "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(Some(true)), - ); - - assert_eq!( - tree.finalize_with_descendent_if( - &"C", - 5, - &is_descendent_of, - |c| c.effective <= 5, - ), - Ok(FinalizationResult::Changed(Some(Change { effective: 5 }))), - ); - - assert_eq!( - tree.roots().map(|(h, n, _)| (h.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(Some(true)), - ); - - assert_eq!( - tree.finalize_with_descendent_if( - &"G", - 100, - &is_descendent_of, - |c| c.effective <= 100, - ), - Ok(FinalizationResult::Changed(Some(Change { effective: 10 }))), - ); - - // "E" will be pruned out - assert_eq!(tree.roots().count(), 0); - } - - #[test] - fn iter_iterates_in_preorder() { - let (tree, ..) = test_fork_tree(); - assert_eq!( - tree.iter().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), - vec![ - ("A", 1), - ("J", 2), ("K", 3), - ("F", 2), ("H", 3), ("L", 4), ("O", 5), - ("M", 5), - ("I", 4), - ("G", 3), - ("B", 2), ("C", 3), ("D", 4), ("E", 5), - ], - ); - } - - #[test] - fn minimizes_calls_to_is_descendent_of() { - use std::sync::atomic::{AtomicUsize, Ordering}; - - let n_is_descendent_of_calls = AtomicUsize::new(0); - - let is_descendent_of = |_: &&str, _: &&str| -> Result { - n_is_descendent_of_calls.fetch_add(1, Ordering::SeqCst); - Ok(true) - }; - - { - // Deep tree where we want to call `finalizes_any_with_descendent_if`. The - // search for the node should first check the predicate (which is cheaper) and - // only then call `is_descendent_of` - let mut tree = ForkTree::new(); - let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; - - for (i, letter) in letters.iter().enumerate() { - tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(true)).unwrap(); - } - - // "L" is a descendent of "K", but the predicate will only pass for "K", - // therefore only one call to `is_descendent_of` should be made - assert_eq!( - tree.finalizes_any_with_descendent_if( - &"L", - 11, - &is_descendent_of, - |i| *i == 10, - ), - Ok(Some(false)), - ); - - assert_eq!( - n_is_descendent_of_calls.load(Ordering::SeqCst), - 1, - ); - } - - n_is_descendent_of_calls.store(0, Ordering::SeqCst); - - { - // Multiple roots in the tree where we want to call `finalize_with_descendent_if`. - // The search for the root node should first check the predicate (which is cheaper) - // and only then call `is_descendent_of` - let mut tree = ForkTree::new(); - let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; - - for (i, letter) in letters.iter().enumerate() { - tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(false)).unwrap(); - } - - // "L" is a descendent of "K", but the predicate will only pass for "K", - // therefore only one call to `is_descendent_of` should be made - assert_eq!( - tree.finalize_with_descendent_if( - &"L", - 11, - &is_descendent_of, - |i| *i == 10, - ), - Ok(FinalizationResult::Changed(Some(10))), - ); - - assert_eq!( - n_is_descendent_of_calls.load(Ordering::SeqCst), - 1, - ); - } - } - - #[test] - fn find_node_works() { - let (tree, is_descendent_of) = test_fork_tree(); - - let node = tree.find_node_where( - &"D", - &4, - &is_descendent_of, - &|_| true, - ).unwrap().unwrap(); - - assert_eq!(node.hash, "C"); - assert_eq!(node.number, 3); - } - - #[test] - fn prune_works() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - tree.prune( - &"C", - &3, - &is_descendent_of, - &|_| true, - ).unwrap(); - - assert_eq!( - tree.roots.iter().map(|node| node.hash).collect::>(), - vec!["B"], - ); - - assert_eq!( - tree.iter().map(|(hash, _, _)| *hash).collect::>(), - vec!["B", "C", "D", "E"], - ); - - tree.prune( - &"E", - &5, - &is_descendent_of, - &|_| true, - ).unwrap(); - - assert_eq!( - tree.roots.iter().map(|node| node.hash).collect::>(), - vec!["D"], - ); - - assert_eq!( - tree.iter().map(|(hash, _, _)| *hash).collect::>(), - vec!["D", "E"], - ); - } - - #[test] - fn find_node_backtracks_after_finding_highest_descending_node() { - let mut tree = ForkTree::new(); - - // - // A - B - // \ - // — C - // - let is_descendent_of = |base: &&str, block: &&str| -> Result { - match (*base, *block) { - ("A", b) => Ok(b == "B" || b == "C" || b == "D"), - ("B", b) | ("C", b) => Ok(b == "D"), - ("0", _) => Ok(true), - _ => Ok(false), - } - }; - - tree.import("A", 1, 1, &is_descendent_of).unwrap(); - tree.import("B", 2, 2, &is_descendent_of).unwrap(); - tree.import("C", 2, 4, &is_descendent_of).unwrap(); - - // when searching the tree we reach node `C`, but the - // predicate doesn't pass. we should backtrack to `B`, but not to `A`, - // since "B" fulfills the predicate. - let node = tree.find_node_where( - &"D", - &3, - &is_descendent_of, - &|data| *data < 3, - ).unwrap(); - - assert_eq!(node.unwrap().hash, "B"); - } -} diff --git a/core/utils/wasm-builder-runner/src/lib.rs b/core/utils/wasm-builder-runner/src/lib.rs deleted file mode 100644 index 1739c5eff211e..0000000000000 --- a/core/utils/wasm-builder-runner/src/lib.rs +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # WASM builder runner -//! -//! Since cargo contains many bugs when it comes to correct dependency and feature -//! resolution, we need this little tool. See for -//! more information. -//! -//! It will create a project that will call `substrate-wasm-builder` to prevent any dependencies -//! from `substrate-wasm-builder` influencing the main project's dependencies. -//! -//! For more information see - -use std::{env, process::{Command, self}, fs, path::{PathBuf, Path}}; - -/// Environment variable that tells us to skip building the WASM binary. -const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; - -/// Environment variable that tells us to create a dummy WASM binary. -/// -/// This is useful for `cargo check` to speed-up the compilation. -/// -/// # Caution -/// -/// Enabling this option will just provide `&[]` as WASM binary. -const DUMMY_WASM_BINARY_ENV: &str = "BUILD_DUMMY_WASM_BINARY"; - -/// Environment variable that makes sure the WASM build is triggered. -const TRIGGER_WASM_BUILD_ENV: &str = "TRIGGER_WASM_BUILD"; - -/// Replace all backslashes with slashes. -fn replace_back_slashes(path: T) -> String { - path.to_string().replace("\\", "/") -} - -/// The `wasm-builder` dependency source. -pub enum WasmBuilderSource { - /// The relative path to the source code from the current manifest dir. - Path(&'static str), - /// The git repository that contains the source code. - Git { - repo: &'static str, - rev: &'static str, - }, - /// Use the given version released on crates.io. - Crates(&'static str), - /// Use the given version released on crates.io or from the given path. - CratesOrPath { - version: &'static str, - path: &'static str, - } -} - -impl WasmBuilderSource { - /// Convert to a valid cargo source declaration. - /// - /// `absolute_path` - The manifest dir. - fn to_cargo_source(&self, manifest_dir: &Path) -> String { - match self { - WasmBuilderSource::Path(path) => { - replace_back_slashes(format!("path = \"{}\"", manifest_dir.join(path).display())) - } - WasmBuilderSource::Git { repo, rev } => { - format!("git = \"{}\", rev=\"{}\"", repo, rev) - } - WasmBuilderSource::Crates(version) => { - format!("version = \"{}\"", version) - } - WasmBuilderSource::CratesOrPath { version, path } => { - replace_back_slashes( - format!( - "path = \"{}\", version = \"{}\"", - manifest_dir.join(path).display(), - version - ) - ) - } - } - } -} - -/// Build the currently built project as WASM binary and extend `RUSTFLAGS` with the given rustflags. -/// -/// For more information, see [`build_current_project`]. -pub fn build_current_project_with_rustflags( - file_name: &str, - wasm_builder_source: WasmBuilderSource, - default_rustflags: &str, -) { - if check_skip_build() { - // If we skip the build, we still want to make sure to be called when an env variable changes - generate_rerun_if_changed_instructions(); - return; - } - - let manifest_dir = PathBuf::from( - env::var("CARGO_MANIFEST_DIR").expect( - "`CARGO_MANIFEST_DIR` is always set for `build.rs` files; qed" - ) - ); - - let cargo_toml_path = manifest_dir.join("Cargo.toml"); - let out_dir = PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!")); - let file_path = out_dir.join(file_name); - let project_name = env::var("CARGO_PKG_NAME").expect("`CARGO_PKG_NAME` is set by cargo!"); - let project_folder = get_workspace_root().join(project_name); - - if check_provide_dummy_wasm_binary() { - provide_dummy_wasm_binary(&file_path); - } else { - create_project( - &project_folder, - &file_path, - &manifest_dir, - wasm_builder_source, - &cargo_toml_path, - default_rustflags, - ); - run_project(&project_folder); - } - - // As last step we need to generate our `rerun-if-changed` stuff. If a build fails, we don't - // want to spam the output! - generate_rerun_if_changed_instructions(); -} - -/// Build the currently built project as WASM binary. -/// -/// The current project is determined using the `CARGO_MANIFEST_DIR` environment variable. -/// -/// `file_name` - The name of the file being generated in the `OUT_DIR`. The file contains the -/// constant `WASM_BINARY` which contains the build wasm binary. -/// `wasm_builder_path` - Path to the wasm-builder project, relative to `CARGO_MANIFEST_DIR`. -pub fn build_current_project(file_name: &str, wasm_builder_source: WasmBuilderSource) { - build_current_project_with_rustflags(file_name, wasm_builder_source, ""); -} - -/// Returns the root path of the wasm-builder-runner workspace. -/// -/// The wasm-builder-runner workspace contains all wasm-builder-runner's projects. -fn get_workspace_root() -> PathBuf { - let out_dir_env = env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!"); - let mut out_dir = PathBuf::from(&out_dir_env); - - loop { - match out_dir.parent() { - Some(parent) if out_dir.ends_with("build") => return parent.join("wbuild-runner"), - _ => if !out_dir.pop() { - break; - } - } - } - - panic!("Could not find target dir in: {}", out_dir_env) -} - -fn create_project( - project_folder: &Path, - file_path: &Path, - manifest_dir: &Path, - wasm_builder_source: WasmBuilderSource, - cargo_toml_path: &Path, - default_rustflags: &str, -) { - fs::create_dir_all(project_folder.join("src")) - .expect("WASM build runner dir create can not fail; qed"); - - fs::write( - project_folder.join("Cargo.toml"), - format!( - r#" - [package] - name = "wasm-build-runner-impl" - version = "1.0.0" - edition = "2018" - - [dependencies] - substrate-wasm-builder = {{ {wasm_builder_source} }} - - [workspace] - "#, - wasm_builder_source = wasm_builder_source.to_cargo_source(manifest_dir), - ) - ).expect("WASM build runner `Cargo.toml` writing can not fail; qed"); - - fs::write( - project_folder.join("src/main.rs"), - format!( - r#" - use substrate_wasm_builder::build_project_with_default_rustflags; - - fn main() {{ - build_project_with_default_rustflags( - "{file_path}", - "{cargo_toml_path}", - "{default_rustflags}", - ) - }} - "#, - file_path = replace_back_slashes(file_path.display()), - cargo_toml_path = replace_back_slashes(cargo_toml_path.display()), - default_rustflags = default_rustflags, - ) - ).expect("WASM build runner `main.rs` writing can not fail; qed"); -} - -fn run_project(project_folder: &Path) { - let cargo = env::var("CARGO").expect("`CARGO` env variable is always set when executing `build.rs`."); - let mut cmd = Command::new(cargo); - cmd.arg("run").arg(format!("--manifest-path={}", project_folder.join("Cargo.toml").display())); - - if env::var("DEBUG") != Ok(String::from("true")) { - cmd.arg("--release"); - } - - // Unset the `CARGO_TARGET_DIR` to prevent a cargo deadlock (cargo locks a target dir exclusive). - // The runner project is created in `CARGO_TARGET_DIR` and executing it will create a sub target - // directory inside of `CARGO_TARGET_DIR`. - cmd.env_remove("CARGO_TARGET_DIR"); - - if !cmd.status().map(|s| s.success()).unwrap_or(false) { - // Don't spam the output with backtraces when a build failed! - process::exit(1); - } -} - -/// Generate the name of the skip build environment variable for the current crate. -fn generate_crate_skip_build_env_name() -> String { - format!( - "SKIP_{}_WASM_BUILD", - env::var("CARGO_PKG_NAME").expect("Package name is set").to_uppercase().replace('-', "_"), - ) -} - -/// Checks if the build of the WASM binary should be skipped. -fn check_skip_build() -> bool { - env::var(SKIP_BUILD_ENV).is_ok() || env::var(generate_crate_skip_build_env_name()).is_ok() -} - -/// Check if we should provide a dummy WASM binary. -fn check_provide_dummy_wasm_binary() -> bool { - env::var(DUMMY_WASM_BINARY_ENV).is_ok() -} - -/// Provide the dummy WASM binary -fn provide_dummy_wasm_binary(file_path: &Path) { - fs::write( - file_path, - "pub const WASM_BINARY: &[u8] = &[]; pub const WASM_BINARY_BLOATY: &[u8] = &[];", - ).expect("Writing dummy WASM binary should not fail"); -} - -/// Generate the `rerun-if-changed` instructions for cargo to make sure that the WASM binary is -/// rebuilt when needed. -fn generate_rerun_if_changed_instructions() { - // Make sure that the `build.rs` is called again if one of the following env variables changes. - println!("cargo:rerun-if-env-changed={}", SKIP_BUILD_ENV); - println!("cargo:rerun-if-env-changed={}", DUMMY_WASM_BINARY_ENV); - println!("cargo:rerun-if-env-changed={}", TRIGGER_WASM_BUILD_ENV); - println!("cargo:rerun-if-env-changed={}", generate_crate_skip_build_env_name()); -} diff --git a/core/utils/wasm-builder/Cargo.toml b/core/utils/wasm-builder/Cargo.toml deleted file mode 100644 index e9d38f2bd23f6..0000000000000 --- a/core/utils/wasm-builder/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "substrate-wasm-builder" -version = "1.0.8" -authors = ["Parity Technologies "] -description = "Utility for building WASM binaries" -edition = "2018" -readme = "README.md" -repository = "https://github.com/paritytech/substrate" -license = "GPL-3.0" - -[dependencies] -build-helper = "0.1.1" -cargo_metadata = "0.8.2" -tempfile = "3.1.0" -toml = "0.5.3" -walkdir = "2.2.9" -fs2 = "0.4.3" -wasm-gc-api = "0.1.11" diff --git a/core/utils/wasm-builder/README.md b/core/utils/wasm-builder/README.md deleted file mode 100644 index b15d2ebfab2a0..0000000000000 --- a/core/utils/wasm-builder/README.md +++ /dev/null @@ -1,62 +0,0 @@ -## WASM builder is a utility for building a project as a WASM binary - -The WASM builder is a tool that integrates the process of building the WASM binary of your project into the main -`cargo` build process. - -### Project setup - -A project that should be compiled as a WASM binary needs to: - -1. Add a `build.rs` file. -2. Add `substrate-wasm-builder-runner` as dependency into `build-dependencies`. - -The `build.rs` file needs to contain the following code: - -```rust -use wasm_builder_runner::{build_current_project, WasmBuilderSource}; - -fn main() { - build_current_project( - // The name of the file being generated in out-dir. - "wasm_binary.rs", - // How to include wasm-builder, in this case from crates.io. - WasmBuilderSource::Crates("1.0.0"), - ); -} -``` - -As the final step, you need to add the following to your project: - -```rust -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -``` - -This will include the generated WASM binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. -The former is a compact WASM binary and the latter is not compacted. - -### Environment variables - -By using environment variables, you can configure which WASM binaries are built and how: - -- `SKIP_WASM_BUILD` - Skips building any WASM binary. This is useful when only native should be recompiled. -- `BUILD_DUMMY_WASM_BINARY` - Builds dummy WASM binaries. These dummy binaries are empty and useful - for `cargo check` runs. -- `WASM_BUILD_TYPE` - Sets the build type for building WASM binaries. Supported values are `release` or `debug`. - By default the build type is equal to the build type used by the main build. -- `TRIGGER_WASM_BUILD` - Can be set to trigger a WASM build. On subsequent calls the value of the variable - needs to change. As WASM builder instructs `cargo` to watch for file changes - this environment variable should only be required in certain circumstances. -- `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the WASM binary. - -Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. -Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will -be `NODE_RUNTIME`. - -### Prerequisites: - -WASM builder requires the following prerequisities for building the WASM binary: - -- rust nightly + `wasm32-unknown-unknown` toolchain - - -License: GPL-3.0 diff --git a/core/utils/wasm-builder/src/lib.rs b/core/utils/wasm-builder/src/lib.rs deleted file mode 100644 index 93e1700792ab4..0000000000000 --- a/core/utils/wasm-builder/src/lib.rs +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # WASM builder is a utility for building a project as a WASM binary -//! -//! The WASM builder is a tool that integrates the process of building the WASM binary of your project into the main -//! `cargo` build process. -//! -//! ## Project setup -//! -//! A project that should be compiled as a WASM binary needs to: -//! -//! 1. Add a `build.rs` file. -//! 2. Add `substrate-wasm-builder-runner` as dependency into `build-dependencies`. -//! -//! The `build.rs` file needs to contain the following code: -//! -//! ```ignore -//! use wasm_builder_runner::{build_current_project, WasmBuilderSource}; -//! -//! fn main() { -//! build_current_project( -//! // The name of the file being generated in out-dir. -//! "wasm_binary.rs", -//! // How to include wasm-builder, in this case from crates.io. -//! WasmBuilderSource::Crates("1.0.0"), -//! ); -//! } -//! ``` -//! -//! As the final step, you need to add the following to your project: -//! -//! ```ignore -//! include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -//! ``` -//! -//! This will include the generated WASM binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. -//! The former is a compact WASM binary and the latter is not compacted. -//! -//! ## Environment variables -//! -//! By using environment variables, you can configure which WASM binaries are built and how: -//! -//! - `SKIP_WASM_BUILD` - Skips building any WASM binary. This is useful when only native should be recompiled. -//! - `BUILD_DUMMY_WASM_BINARY` - Builds dummy WASM binaries. These dummy binaries are empty and useful -//! for `cargo check` runs. -//! - `WASM_BUILD_TYPE` - Sets the build type for building WASM binaries. Supported values are `release` or `debug`. -//! By default the build type is equal to the build type used by the main build. -//! - `TRIGGER_WASM_BUILD` - Can be set to trigger a WASM build. On subsequent calls the value of the variable -//! needs to change. As WASM builder instructs `cargo` to watch for file changes -//! this environment variable should only be required in certain circumstances. -//! - `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the WASM binary. -//! - `WASM_TARGET_DIRECTORY` - Will copy any build WASM binary to the given directory. The path needs -//! to be absolute. -//! -//! Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. -//! Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will -//! be `NODE_RUNTIME`. -//! -//! ## Prerequisites: -//! -//! WASM builder requires the following prerequisities for building the WASM binary: -//! -//! - rust nightly + `wasm32-unknown-unknown` toolchain -//! - -use std::{env, fs, path::PathBuf, process::{Command, Stdio, self}}; - -mod prerequisites; -mod wasm_project; - -/// Environment variable that tells us to skip building the WASM binary. -const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; - -/// Environment variable to force a certain build type when building the WASM binary. -/// Expects "debug" or "release" as value. -/// -/// By default the WASM binary uses the same build type as the main cargo build. -const WASM_BUILD_TYPE_ENV: &str = "WASM_BUILD_TYPE"; - -/// Environment variable to extend the `RUSTFLAGS` variable given to the WASM build. -const WASM_BUILD_RUSTFLAGS_ENV: &str = "WASM_BUILD_RUSTFLAGS"; - -/// Environment variable to set the target directory to copy the final WASM binary. -/// -/// The directory needs to be an absolute path. -const WASM_TARGET_DIRECTORY: &str = "WASM_TARGET_DIRECTORY"; - -/// Build the currently built project as WASM binary. -/// -/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. -/// -/// `file_name` - The name + path of the file being generated. The file contains the -/// constant `WASM_BINARY`, which contains the built WASM binary. -/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built. -pub fn build_project(file_name: &str, cargo_manifest: &str) { - build_project_with_default_rustflags(file_name, cargo_manifest, ""); -} - -/// Build the currently built project as WASM binary. -/// -/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. -/// -/// `file_name` - The name + path of the file being generated. The file contains the -/// constant `WASM_BINARY`, which contains the built WASM binary. -/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built. -/// `default_rustflags` - Default `RUSTFLAGS` that will always be set for the build. -pub fn build_project_with_default_rustflags( - file_name: &str, - cargo_manifest: &str, - default_rustflags: &str, -) { - if check_skip_build() { - return; - } - - let cargo_manifest = PathBuf::from(cargo_manifest); - - if !cargo_manifest.exists() { - panic!("'{}' does not exist!", cargo_manifest.display()); - } - - if !cargo_manifest.ends_with("Cargo.toml") { - panic!("'{}' no valid path to a `Cargo.toml`!", cargo_manifest.display()); - } - - if let Some(err_msg) = prerequisites::check() { - eprintln!("{}", err_msg); - process::exit(1); - } - - let (wasm_binary, bloaty) = wasm_project::create_and_compile( - &cargo_manifest, - default_rustflags, - ); - - write_file_if_changed( - file_name.into(), - format!( - r#" - pub const WASM_BINARY: &[u8] = include_bytes!("{wasm_binary}"); - pub const WASM_BINARY_BLOATY: &[u8] = include_bytes!("{wasm_binary_bloaty}"); - "#, - wasm_binary = wasm_binary.wasm_binary_path(), - wasm_binary_bloaty = bloaty.wasm_binary_bloaty_path(), - ), - ); -} - -/// Checks if the build of the WASM binary should be skipped. -fn check_skip_build() -> bool { - env::var(SKIP_BUILD_ENV).is_ok() -} - -/// Write to the given `file` if the `content` is different. -fn write_file_if_changed(file: PathBuf, content: String) { - if fs::read_to_string(&file).ok().as_ref() != Some(&content) { - fs::write(&file, content).expect(&format!("Writing `{}` can not fail!", file.display())); - } -} - -/// Get a cargo command that compiles with nightly -fn get_nightly_cargo() -> CargoCommand { - let default_cargo = CargoCommand::new("cargo"); - let mut rustup_run_nightly = CargoCommand::new("rustup"); - rustup_run_nightly.args(&["run", "nightly", "cargo"]); - - if default_cargo.is_nightly() { - default_cargo - } else if rustup_run_nightly.works() { - rustup_run_nightly - } else { - default_cargo - } -} - -/// Builder for cargo commands -#[derive(Debug)] -struct CargoCommand { - program: String, - args: Vec, -} - -impl CargoCommand { - fn new(program: &str) -> Self { - CargoCommand { program: program.into(), args: Vec::new() } - } - - fn arg(&mut self, arg: &str) -> &mut Self { - self.args.push(arg.into()); - self - } - - fn args(&mut self, args: &[&str]) -> &mut Self { - args.into_iter().for_each(|a| { self.arg(a); }); - self - } - - fn command(&self) -> Command { - let mut cmd = Command::new(&self.program); - cmd.args(&self.args); - cmd - } - - fn works(&self) -> bool { - self.command() - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status() - .map(|s| s.success()).unwrap_or(false) - } - - /// Check if the supplied cargo command is a nightly version - fn is_nightly(&self) -> bool { - // `RUSTC_BOOTSTRAP` tells a stable compiler to behave like a nightly. So, when this env - // variable is set, we can assume that whatever rust compiler we have, it is a nightly compiler. - // For "more" information, see: - // https://github.com/rust-lang/rust/blob/fa0f7d0080d8e7e9eb20aa9cbf8013f96c81287f/src/libsyntax/feature_gate/check.rs#L891 - env::var("RUSTC_BOOTSTRAP").is_ok() || - self.command() - .arg("--version") - .output() - .map_err(|_| ()) - .and_then(|o| String::from_utf8(o.stdout).map_err(|_| ())) - .unwrap_or_default() - .contains("-nightly") - } -} diff --git a/core/wasm-interface/Cargo.toml b/core/wasm-interface/Cargo.toml deleted file mode 100644 index b8169031d0bb6..0000000000000 --- a/core/wasm-interface/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "substrate-wasm-interface" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -wasmi = "0.5.1" diff --git a/core/wasm-interface/src/lib.rs b/core/wasm-interface/src/lib.rs deleted file mode 100644 index b3cbde556eea0..0000000000000 --- a/core/wasm-interface/src/lib.rs +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Types and traits for interfacing between the host and the wasm runtime. - -use std::{borrow::Cow, marker::PhantomData, mem, iter::Iterator, result}; - -mod wasmi_impl; - -/// Result type used by traits in this crate. -pub type Result = result::Result; - -/// Value types supported by Substrate on the boundary between host/Wasm. -#[derive(Copy, Clone, PartialEq, Debug, Eq)] -pub enum ValueType { - /// An `i32` value type. - I32, - /// An `i64` value type. - I64, - /// An `f32` value type. - F32, - /// An `f64` value type. - F64, -} - -/// Values supported by Substrate on the boundary between host/Wasm. -#[derive(PartialEq, Debug, Clone, Copy)] -pub enum Value { - /// An `i32` value. - I32(i32), - /// An `i64` value. - I64(i64), - /// An nan-preserving `f32` value. - F32(u32), - /// An nan-preserving `f64` value. - F64(u64), -} - -/// Provides `Sealed` trait to prevent implementing trait `PointerType` outside of this crate. -mod private { - pub trait Sealed {} - - impl Sealed for u8 {} - impl Sealed for u16 {} - impl Sealed for u32 {} - impl Sealed for u64 {} -} - -/// Something that can be wrapped in a wasm `Pointer`. -/// -/// This trait is sealed. -pub trait PointerType: Sized { - /// The size of the type in wasm. - const SIZE: u32 = mem::size_of::() as u32; -} - -impl PointerType for u8 {} -impl PointerType for u16 {} -impl PointerType for u32 {} -impl PointerType for u64 {} - -/// Type to represent a pointer in wasm at the host. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Pointer { - ptr: u32, - _marker: PhantomData, -} - -impl Pointer { - /// Create a new instance of `Self`. - pub fn new(ptr: u32) -> Self { - Self { - ptr, - _marker: Default::default(), - } - } - - /// Calculate the offset from this pointer. - /// - /// `offset` is in units of `T`. So, `3` means `3 * mem::size_of::()` as offset to the pointer. - /// - /// Returns an `Option` to respect that the pointer could probably overflow. - pub fn offset(self, offset: u32) -> Option { - offset.checked_mul(T::SIZE).and_then(|o| self.ptr.checked_add(o)).map(|ptr| { - Self { - ptr, - _marker: Default::default(), - } - }) - } - - /// Create a null pointer. - pub fn null() -> Self { - Self::new(0) - } - - /// Cast this pointer of type `T` to a pointer of type `R`. - pub fn cast(self) -> Pointer { - Pointer::new(self.ptr) - } -} - -impl From> for u32 { - fn from(ptr: Pointer) -> Self { - ptr.ptr - } -} - -impl From> for usize { - fn from(ptr: Pointer) -> Self { - ptr.ptr as _ - } -} - -impl IntoValue for Pointer { - const VALUE_TYPE: ValueType = ValueType::I32; - fn into_value(self) -> Value { Value::I32(self.ptr as _) } -} - -impl TryFromValue for Pointer { - fn try_from_value(val: Value) -> Option { - match val { - Value::I32(val) => Some(Self::new(val as _)), - _ => None, - } - } -} - -/// The word size used in wasm. Normally known as `usize` in Rust. -pub type WordSize = u32; - -/// The Signature of a function -#[derive(Eq, PartialEq, Debug, Clone)] -pub struct Signature { - /// The arguments of a function. - pub args: Cow<'static, [ValueType]>, - /// The optional return value of a function. - pub return_value: Option, -} - -impl Signature { - /// Create a new instance of `Signature`. - pub fn new>>(args: T, return_value: Option) -> Self { - Self { - args: args.into(), - return_value, - } - } - - /// Create a new instance of `Signature` with the given `args` and without any return value. - pub fn new_with_args>>(args: T) -> Self { - Self { - args: args.into(), - return_value: None, - } - } - -} - -/// Something that provides a function implementation on the host for a wasm function. -pub trait Function { - /// Returns the name of this function. - fn name(&self) -> &str; - /// Returns the signature of this function. - fn signature(&self) -> Signature; - /// Execute this function with the given arguments. - fn execute( - &self, - context: &mut dyn FunctionContext, - args: &mut dyn Iterator, - ) -> Result>; -} - -/// Context used by `Function` to interact with the allocator and the memory of the wasm instance. -pub trait FunctionContext { - /// Read memory from `address` into a vector. - fn read_memory(&self, address: Pointer, size: WordSize) -> Result> { - let mut vec = Vec::with_capacity(size as usize); - vec.resize(size as usize, 0); - self.read_memory_into(address, &mut vec)?; - Ok(vec) - } - /// Read memory into the given `dest` buffer from `address`. - fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> Result<()>; - /// Write the given data at `address` into the memory. - fn write_memory(&mut self, address: Pointer, data: &[u8]) -> Result<()>; - /// Allocate a memory instance of `size` bytes. - fn allocate_memory(&mut self, size: WordSize) -> Result>; - /// Deallocate a given memory instance. - fn deallocate_memory(&mut self, ptr: Pointer) -> Result<()>; - /// Provides access to the sandbox. - fn sandbox(&mut self) -> &mut dyn Sandbox; -} - -/// Sandbox memory identifier. -pub type MemoryId = u32; - -/// Something that provides access to the sandbox. -pub trait Sandbox { - /// Get sandbox memory from the `memory_id` instance at `offset` into the given buffer. - fn memory_get( - &self, - memory_id: MemoryId, - offset: WordSize, - buf_ptr: Pointer, - buf_len: WordSize, - ) -> Result; - /// Set sandbox memory from the given value. - fn memory_set( - &mut self, - memory_id: MemoryId, - offset: WordSize, - val_ptr: Pointer, - val_len: WordSize, - ) -> Result; - /// Delete a memory instance. - fn memory_teardown(&mut self, memory_id: MemoryId) -> Result<()>; - /// Create a new memory instance with the given `initial` size and the `maximum` size. - /// The size is given in wasm pages. - fn memory_new(&mut self, initial: u32, maximum: u32) -> Result; - /// Invoke an exported function by a name. - fn invoke( - &mut self, - instance_id: u32, - export_name: &str, - args: &[u8], - return_val: Pointer, - return_val_len: WordSize, - state: u32, - ) -> Result; - /// Delete a sandbox instance. - fn instance_teardown(&mut self, instance_id: u32) -> Result<()>; - /// Create a new sandbox instance. - fn instance_new( - &mut self, - dispatch_thunk_id: u32, - wasm: &[u8], - raw_env_def: &[u8], - state: u32, - ) -> Result; -} - -/// Something that provides implementations for host functions. -pub trait HostFunctions { - /// Returns all host functions. - fn functions() -> &'static [&'static dyn Function]; -} - -/// Something that can be converted into a wasm compatible `Value`. -pub trait IntoValue { - /// The type of the value in wasm. - const VALUE_TYPE: ValueType; - - /// Convert `self` into a wasm `Value`. - fn into_value(self) -> Value; -} - -/// Something that can may be created from a wasm `Value`. -pub trait TryFromValue: Sized { - /// Try to convert the given `Value` into `Self`. - fn try_from_value(val: Value) -> Option; -} - -macro_rules! impl_into_and_from_value { - ( - $( - $type:ty, $( < $gen:ident >, )? $value_variant:ident, - )* - ) => { - $( - impl $( <$gen> )? IntoValue for $type { - const VALUE_TYPE: ValueType = ValueType::$value_variant; - fn into_value(self) -> Value { Value::$value_variant(self as _) } - } - - impl $( <$gen> )? TryFromValue for $type { - fn try_from_value(val: Value) -> Option { - match val { - Value::$value_variant(val) => Some(val as _), - _ => None, - } - } - } - )* - } -} - -impl_into_and_from_value! { - u32, I32, - i32, I32, - u64, I64, - i64, I64, -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn pointer_offset_works() { - let ptr = Pointer::::null(); - - assert_eq!(ptr.offset(10).unwrap(), Pointer::new(40)); - assert_eq!(ptr.offset(32).unwrap(), Pointer::new(128)); - - let ptr = Pointer::::null(); - - assert_eq!(ptr.offset(10).unwrap(), Pointer::new(80)); - assert_eq!(ptr.offset(32).unwrap(), Pointer::new(256)); - } -} diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS new file mode 100644 index 0000000000000..bc4559805b3e0 --- /dev/null +++ b/docs/CODEOWNERS @@ -0,0 +1,72 @@ +# Lists some code owners. +# +# A codeowner just oversees some part of the codebase. If an owned file is changed then the +# corresponding codeowner receives a review request. An approval of the codeowner is +# not required for merging a PR though. +# +# **This is pretty much an experiment at the moment**. Feel free to remove yourself at any time if +# you do not want to receive review requests any longer. +# +# For details about syntax, see: +# https://help.github.com/en/articles/about-code-owners +# But here are some important notes: +# +# - Glob syntax is git-like, e.g. `/core` means the core directory in the root, unlike `core` which +# can be everywhere. +# - Multiple owners are supported. +# - Either handle (e.g, @pepyakin) or email can be used. Keep in mind, that handles might work better because they +# are more recognizable on GitHub, you can use them for mentioning unlike an email. +# - The latest matching rule, if multiple, takes precedence. + +# Wasm execution and the wasm side of Substrate Runtime Interface +/client/executor/ @pepyakin +/primitives/io/ @pepyakin + +# Sandboxing capability of Substrate Runtime +/primitives/sr-sandbox/ @pepyakin +/primitives/core/src/sandbox.rs @pepyakin + +# Transaction pool +/client/transaction-pool/ @tomusdrw +/primitives/transaction-pool/ @tomusdrw + +# Offchain +/client/offchain/ @tomusdrw +/primitives/offchain/ @tomusdrw + +# Everything that has RPC in it +/bin/node/rpc/ @tomusdrw +/bin/node/rpc-client/ @tomusdrw +/client/rpc/ @tomusdrw +/primitives/rpc/ @tomusdrw + +# GRANDPA, BABE, consensus stuff +/frame/babe/ @andresilva @DemiMarie-parity +/frame/grandpa/ @andresilva @DemiMarie-parity +/client/finality-grandpa/ @andresilva @DemiMarie-parity +/client/consensus/babe/ @andresilva @DemiMarie-parity +/client/consensus/slots/ @andresilva @DemiMarie-parity + +# Contracts +/frame/contracts/ @pepyakin @thiolliere +/frame/contracts/src/wasm/runtime.rs @Robbepop + +# Inflation points +/frame/staking/src/inflation.rs @thiolliere + +# NPoS and Governance +/frame/staking/ @kianenigma +/frame/elections/ @kianenigma + +# End to end testing of substrate node +/bin/node/executor/ @kianenigma + +# Transaction weight stuff +/frame/support/src/weights.rs @kianenigma + +# Support crates +/frame/support/ @thiolliere @kianenigma + +# Authority discovery +/client/authority-discovery/ @mxinden +/frame/authority-discovery/ @mxinden diff --git a/CODE_OF_CONDUCT.adoc b/docs/CODE_OF_CONDUCT.adoc similarity index 100% rename from CODE_OF_CONDUCT.adoc rename to docs/CODE_OF_CONDUCT.adoc diff --git a/CONTRIBUTING.adoc b/docs/CONTRIBUTING.adoc similarity index 100% rename from CONTRIBUTING.adoc rename to docs/CONTRIBUTING.adoc diff --git a/PULL_REQUEST_TEMPLATE.md b/docs/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from PULL_REQUEST_TEMPLATE.md rename to docs/PULL_REQUEST_TEMPLATE.md diff --git a/docs/README.adoc b/docs/README.adoc new file mode 100644 index 0000000000000..d8c582296cabb --- /dev/null +++ b/docs/README.adoc @@ -0,0 +1,530 @@ += Substrate +:Author: Substrate developers +:Revision: 0.2.0 +:toc: +:sectnums: + +== Intro in one sentence + +Substrate is a next-generation framework for blockchain innovation. + +== Description + +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 synchronize 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). + +Substrate is designed for use in one of three ways: + +**1. Trivial**: By running the Substrate binary `substrate` and configuring it with a genesis block that includes the current demonstration runtime. In this case, you just build Substrate, configure a JSON file, and launch your own blockchain. This affords you the least amount of customizability, primarily allowing you to change the genesis parameters of the various included runtime modules such as balances, staking, block-period, fees, and governance. + +**2. Modular**: By hacking together pallets built with Substrate FRAME into a new runtime and possibly altering or reconfiguring the Substrate client's block authoring logic. This affords you a very large amount of freedom over your blockchain's logic, letting you change datatypes, add or remove modules, and crucially, add your own modules. Much can be changed without touching the block authoring logic (since it is generic). If this is the case, then the existing Substrate binary can be used for block authoring and syncing. If the block authoring logic needs to be tweaked, then a new, altered block authoring binary must be built as a separate project and used by validators. This is how the Polkadot relay chain is built and should suffice for almost all circumstances in the near to mid-term. + +**3. Generic**: The entire SRML can be ignored and the entire runtime designed and implemented from scratch. If desired, this can be done in a language other than Rust, provided it can target WebAssembly. If the runtime can be made compatible with the existing client's block authoring logic, then you can simply construct a new genesis block from your Wasm blob and launch your chain with the existing Rust-based Substrate client. If not, then you'll need to alter the client's block authoring logic accordingly. This is probably a useless option for most projects right now, but provides complete flexibility allowing for a long-term, far-reaching upgrade path for the Substrate paradigm. + +=== The Basics of Substrate + +Substrate is a blockchain platform with a completely generic state transition function. That said, it does come with both standards and conventions (particularly regarding the Runtime Module Library) regarding underlying data structures. Roughly speaking, these core datatypes correspond to +trait+s in terms of the actual non-negotiable standard and generic +struct+s in terms of the convention. + +``` +Header := Parent + ExtrinsicsRoot + StorageRoot + Digest +Block := Header + Extrinsics + Justifications +``` + +=== Extrinsics + +Extrinsics in Substrate are pieces of information from "the outside world" that are contained in the blocks of the chain. You might think "ahh, that means *transactions*": in fact, no. Extrinsics fall into two broad categories of which only one is *transactions*. The other is known as *inherents*. The difference between these two is that transactions are signed and gossiped on the network and can be deemed useful *per se*. This fits the mold of what you would call transactions in Bitcoin or Ethereum. + +Inherents, meanwhile, are not passed on the network and are not signed. They represent data which describes the environment but which cannot call upon anything to prove it such as a signature. Rather they are assumed to be "true" simply because a sufficiently large number of validators have agreed on them being reasonable. + +To give an example, there is the timestamp inherent, which sets the current timestamp of the block. This is not a fixed part of Substrate, but does come as part of FRAME to be used as desired. No signature could fundamentally prove that a block were authored at a given time in quite the same way that a signature can "prove" the desire to spend some particular funds. Rather, it is the business of each validator to ensure that they believe the timestamp is set to something reasonable before they agree that the block candidate is valid. + +Other examples include the parachain-heads extrinsic in Polkadot and the "note-missed-proposal" extrinsic used in FRAME to determine and punish or deactivate offline validators. + + +=== 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. + +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 a snippet of the Polkadot API implementation as of PoC-3: + +```rust +impl_runtime_apis! { + impl client_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: ::Header) { + Executive::initialize_block(&header) + } + } + // ---snip--- +} +``` + + +=== Inherent Extrinsics + +Substrate FRAME includes functionality for timestamps and slashing. If used, these rely on "trusted" external information being passed in via inherent extrinsics. The Substrate reference block authoring client software will expect to be able to call into the runtime API with collated data (in the case of the reference Substrate authoring client, this is merely the current timestamp and which nodes were offline) in order to return the appropriate extrinsics ready for inclusion. If new inherent extrinsic types and data are to be used in a modified runtime, then it is this function (and its argument type) that would change. + +=== Block-authoring Logic + +In Substrate, there is a major distinction between blockchain *syncing* and block *authoring* ("authoring" is a more general term for what is called "mining" in Bitcoin). The first case might be referred to as a "full node" (or "light node" - Substrate supports both): authoring necessarily requires a synced node and, therefore, all authoring clients must necessarily be able to synchronize. However, the reverse is not true. The primary functionality that authoring nodes have which is not in "sync nodes" is threefold: transaction queue logic, inherent transaction knowledge and BFT consensus logic. BFT consensus logic is provided as a core element of Substrate and can be ignored since it is only exposed in the SDK under the `authorities()` API entry. + +Transaction queue logic in Substrate is designed to be as generic as possible, allowing a runtime to express which transactions are fit for inclusion in a block through the `initialize_block` and `apply_extrinsic` calls. However, more subtle aspects like prioritization and replacement policy must currently be expressed "hard coded" as part of the blockchain's authoring code. That said, Substrate's reference implementation for a transaction queue should be sufficient for an initial chain implementation. + +Inherent extrinsic knowledge is again somewhat generic, and the actual construction of the extrinsics is, by convention, delegated to the "soft code" in the runtime. If ever there needs to be additional extrinsic information in the chain, then both the block authoring logic will need to be altered to provide it into the runtime and the runtime's `inherent_extrinsics` call will need to use this extra information in order to construct any additional extrinsic transactions for inclusion in the block. + +== Roadmap + +=== So far + +- 0.1 "PoC-1": PBFT consensus, Wasm runtime engine, basic runtime modules. +- 0.2 "PoC-2": Libp2p + +=== In progress + +- AfG consensus +- Improved PoS +- Smart contract runtime module + +=== The future + +- Splitting out runtime modules into separate repo +- Introduce substrate executable (the skeleton-key runtime) +- Introduce basic but extensible transaction queue and block-builder and place them in the executable. +- DAO runtime module +- Audit + +== Trying out Substrate Node + +Substrate Node is Substrate's pre-baked blockchain client. You can run a development node locally or configure a new chain and launch your own global testnet. + +=== On Mac and Ubuntu + +To get going as fast as possible, there is a simple script that installs all required dependencies and installs Substrate into your path. Just open a terminal and run: + +[source, shell] +---- +curl https://getsubstrate.io -sSf | bash +---- + +You can start a local Substrate development chain with running `substrate --dev`. + +To create your own global network/cryptocurrency, you'll need to make a new Substrate Node chain specification file ("chainspec"). + +First let's get a template chainspec that you can edit. We'll use the "staging" chain, a sort of default chain that the node comes pre-configured with: + +[source, shell] +---- +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): + +[source, json] +---- + "timestamp": { + "minimumPeriod": 10 + }, +---- + +Now with this new chainspec file, you can build a "raw" chain definition for your new chain: + +[source, shell] +---- +substrate build-spec --chain ~/chainspec.json --raw > ~/mychain.json +---- + +This can be fed into Substrate: + +[source, shell] +---- +substrate --chain ~/mychain.json +---- + +It won't do much until you start producing blocks though, so to do that you'll need to use the `--validator` option together with passing the seed for the account(s) that is configured to be the initial authorities: + +[source, shell] +---- +substrate --chain ~/mychain.json --validator +---- + +You can distribute `mychain.json` so that everyone can synchronize and (depending on your authorities list) validate on your chain. + + +== Building + +=== Hacking on Substrate + +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: + +==== Linux and Mac + +For Unix-based operating systems, you should run the following commands: + +[source, shell] +---- +curl https://sh.rustup.rs -sSf | sh + +rustup update nightly +rustup target add wasm32-unknown-unknown --toolchain nightly +rustup update stable +---- + +You will also need to install the following packages: + + - Linux: +[source, shell] +sudo apt install cmake pkg-config libssl-dev git clang libclang-dev + +- Linux on ARM: +`rust-lld` is required for linking wasm, but is missing on non Tier 1 platforms. +So, use this https://github.com/Plume-org/Plume/blob/master/script/wasm-deps.sh[script] +to build `lld` and create the symlink `/usr/bin/rust-lld` to the build binary. + + - Mac: +[source, shell] +brew install cmake pkg-config openssl git llvm + +To finish installation of Substrate, jump down to <>. + +==== Windows + +If you are trying to set up Substrate on Windows, you should do the following: + +1. First, you will need to download and install "Build Tools for Visual Studio:" + + * You can get it at this link: https://aka.ms/buildtools + * Run the installation file: `vs_buildtools.exe` + * Please ensure the Windows 10 SDK component is included when installing the Visual C++ Build Tools. + * image:https://i.imgur.com/zayVLmu.png[image] + * Restart your computer. + +2. Next, you need to install Rust: + + * Detailed instructions are provided by the https://doc.rust-lang.org/book/ch01-01-installation.html#installing-rustup-on-windows[Rust Book]. + * Download from: https://www.rust-lang.org/tools/install + * Run the installation file: `rustup-init.exe` + > Note that it should not prompt you to install vs_buildtools since you did it in step 1. + * Choose "Default Installation." + * To get started, you need Cargo's bin directory (%USERPROFILE%\.cargo\bin) in your PATH environment variable. Future applications will automatically have the correct environment, but you may need to restart your current shell. + +3. Then, you will need to run some commands in CMD to set up your Wasm Build Environment: + + rustup update nightly + rustup update stable + rustup target add wasm32-unknown-unknown --toolchain nightly + +4. Then, you need to install LLVM: https://releases.llvm.org/download.html + +5. Next, you need to install OpenSSL, which we will do with `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 + +6. After, you need to add OpenSSL to your System Variables. Note that in order for the following commands to work, you need to use Windows Powershell: + + $env:OPENSSL_DIR = 'C:\Tools\vcpkg\installed\x64-windows-static' + $env:OPENSSL_STATIC = 'Yes' + [System.Environment]::SetEnvironmentVariable('OPENSSL_DIR', $env:OPENSSL_DIR, [System.EnvironmentVariableTarget]::User) + [System.Environment]::SetEnvironmentVariable('OPENSSL_STATIC', $env:OPENSSL_STATIC, [System.EnvironmentVariableTarget]::User) + +7. Finally, you need to install `cmake`: https://cmake.org/download/ + +==== Shared Steps + +Then, grab the Substrate source code: + +[source, shell] +---- +git clone https://github.com/paritytech/substrate.git +cd substrate +---- + +Then build the code: + +[source, shell] +---- +cargo build # Builds all native code +---- + +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 pallet-assets`) + +You can start a development chain with: + +[source, shell] +cargo run --release -- --dev + +Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run --release \-- --dev`. + +If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain specification that have been endowed with a testnet DOTs. We'll give each node a name and expose them so they are listed on link:https://telemetry.polkadot.io/#/Local%20Testnet[Telemetry]. You'll need two terminal windows open. + +We'll start Alice's Substrate node first on default TCP port 30333 with her chain database stored locally at `/tmp/alice`. The Bootnode ID of her node is `QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR`, which is generated from the `--node-key` value that we specify below: + +[source, shell] +cargo run --release \-- \ + --base-path /tmp/alice \ + --chain=local \ + --alice \ + --node-key 0000000000000000000000000000000000000000000000000000000000000001 \ + --telemetry-url ws://telemetry.polkadot.io:1024 \ + --validator + +In the second terminal, we'll run the following to start Bob's Substrate node on a different TCP port of 30334, and with his chain database stored locally at `/tmp/bob`. We'll specify a value for the `--bootnodes` option that will connect his node to Alice's Bootnode ID on TCP port 30333: + +[source, shell] +cargo run --release \-- \ + --base-path /tmp/bob \ + --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR \ + --chain=local \ + --bob \ + --port 30334 \ + --telemetry-url ws://telemetry.polkadot.io:1024 \ + --validator + +Additional Substrate CLI usage options are available and may be shown by running `cargo run \-- --help`. + +=== WASM binaries + +The WASM binaries are built during the normal `cargo build` process. To control the WASM binary building, +we support multiple environment variables: + +* `SKIP_WASM_BUILD` - Skips building any WASM binary. This is useful when only native should be recompiled. +* `BUILD_DUMMY_WASM_BINARY` - Builds dummy WASM binaries. These dummy binaries are empty and useful + for `cargo check` runs. +* `WASM_BUILD_TYPE` - Sets the build type for building WASM binaries. Supported values are `release` or `debug`. + By default the build type is equal to the build type used by the main build. +* `TRIGGER_WASM_BUILD` - Can be set to trigger a WASM build. On subsequent calls the value of the variable + needs to change. As WASM builder instructs `cargo` to watch for file changes + this environment variable should only be required in certain circumstances. +* `WASM_TARGET_DIRECTORY` - Will copy any build WASM binary to the given directory. The path needs + to be absolute. +* `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. +* `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. + +Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. +Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will +be `NODE_RUNTIME`. + +[[flaming-fir]] +=== Joining the Flaming Fir Testnet + +Flaming Fir is the new testnet for Substrate master (2.0) to test the latest development features. Please note that master is not compatible with the BBQ Birch, Charred Cherry, Dried Danta or Emberic Elm testnets. Ensure you have the dependencies listed above before compiling. + +Since Flaming Fir is targeting the master branch we make absolutely no guarantees of stability and/or persistence of the network. We might reset the chain at any time if it is necessary to deploy new changes. Currently, the validators are running with a client built from `d013bd900`, if you build from this commit you should be able to successfully sync, later commits may not work as new breaking changes may be introduced in master. + +Latest known working version: `a2a0eb5398d6223e531455b4c155ef053a4a3a2b` + +[source, shell] +---- +git clone https://github.com/paritytech/substrate.git +cd substrate +git checkout -b flaming-fir a2a0eb5398d6223e531455b4c155ef053a4a3a2b +---- + +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/#/Flaming%20Fir + +=== Joining the Emberic Elm Testnet + +Emberic Elm is the testnet for Substrate 1.0. Please note that 1.0 is not compatible with the BBQ Birch, Charred Cherry, Dried Danta or Flaming Fir testnets. +In order to join the Emberic Elm testnet you should build from the `v1.0` branch. Ensure you have the dependencies listed above before compiling. + +[source, shell] +---- +git clone https://github.com/paritytech/substrate.git +cd substrate +git checkout -b v1.0 origin/v1.0 +---- + +You can then follow the same steps for building and running as described above in <>. + +== Key management + +Keys in Substrate are stored in the keystore in the file system. To store keys into this keystore, +you need to use one of the two provided RPC calls. If your keys are encrypted or should be encrypted +by the keystore, you need to provide the key using one of the cli arguments `--password`, +`--password-interactive` or `--password-filename`. + +=== Recommended RPC call + +For most users who want to run a validator node, the `author_rotateKeys` RPC call is sufficient. +The RPC call will generate `N` Session keys for you and return their public keys. `N` is the number +of session keys configured in the runtime. The output of the RPC call can be used as input for the +`session::set_keys` transaction. + +``` +curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_rotateKeys", "id":1 }' localhost:9933 +``` + +=== Advanced RPC call + +If the Session keys need to match a fixed seed, they can be set individually key by key. The RPC call +expects the key seed and the key type. The key types supported by default in Substrate are listed +https://github.com/paritytech/substrate/blob/master/core/primitives/src/crypto.rs#L767[here], but the +user can declare any key type. + +``` +curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_insertKey", "params":["KEY_TYPE", "SEED", "PUBLIC"],"id":1 }' localhost:9933 +``` + +`KEY_TYPE` - needs to be replaced with the 4-character key type identifier. +`SEED` - is the seed of the key. +`PUBLIC` - public key for the given key. + +== Documentation + +=== Viewing documentation for Substrate packages + +You can generate documentation for a Substrate Rust package and have it automatically open in your web browser using https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo[rustdoc with Cargo], +(of the The Rustdoc Book), by running the following command: + +``` +cargo doc --package --open +``` + +Replacing `` with one of the following (i.e. `cargo doc --package substrate --open`): + +* All Substrate Packages +[source, shell] +substrate +* Substrate Core +[source, shell] +substrate, substrate-cli, substrate-client, substrate-client-db, +substrate-consensus-common, substrate-consensus-rhd, +substrate-executor, substrate-finality-grandpa, substrate-keyring, substrate-keystore, substrate-network, +substrate-network-libp2p, substrate-primitives, substrate-rpc, substrate-rpc-servers, +substrate-serializer, substrate-service, substrate-service-test, substrate-state-db, +substrate-state-machine, substrate-telemetry, substrate-test-client, +substrate-test-runtime, substrate-transaction-graph, sp-transaction-pool, +substrate-trie +* Substrate Runtime +[source, shell] +sr-api, sr-io, sr-primitives, sr-sandbox, sr-std, sr-version +* FRAME Core +[source, shell] +frame-metadata, frame-support, frame-system +* FRAME Pallets +[source, shell] +pallet-assets, pallet-balances, pallet-consensus, pallet-contracts, pallet-council, pallet-democracy, pallet-example, +frame-executive, pallet-session, pallet-staking, pallet-timestamp, pallet-treasury +* Node +[source, shell] +node-cli, node-consensus, node-executor, node-network, node-primitives, node-runtime +* Subkey +[source, shell] +subkey + +=== Contributing to documentation for Substrate packages + +https://doc.rust-lang.org/1.9.0/book/documentation.html[Document source code] for Substrate packages by annotating the source code with documentation comments. + +Example (generic): +```markdown +/// Summary +/// +/// Description +/// +/// # Panics +/// +/// # Errors +/// +/// # Safety +/// +/// # Examples +/// +/// Summary of Example 1 +/// +/// ```rust +/// // insert example 1 code here +/// ``` +/// +``` + +* Important notes: +** Documentation comments must use annotations with a triple slash `///` +** Modules are documented using `//!` +``` +//! Summary (of module) +//! +//! Description (of module) +``` +* 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` +** `Examples` section includes examples of using the function or method +* 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 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)]` +* Hide documentation for items with `#[doc(hidden)]` + +=== Contributing to documentation (tests, extended examples, macros) for Substrate packages + +The code block annotations in the `# Example` section may be used as https://doc.rust-lang.org/1.9.0/book/documentation.html#documentation-as-tests[documentation as tests and for extended examples]. + +* 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[Documenting macros]. +** Documentation as tests examples are included when running `cargo test` + +== Contributing + +=== Contributing Guidelines + +include::CONTRIBUTING.adoc[] + +=== Contributor Code of Conduct + +include::CODE_OF_CONDUCT.adoc[] + +== License + +https://github.com/paritytech/substrate/blob/master/LICENSE[LICENSE] diff --git a/SECURITY.md b/docs/SECURITY.md similarity index 100% rename from SECURITY.md rename to docs/SECURITY.md diff --git a/docs/Structure.adoc b/docs/Structure.adoc new file mode 100644 index 0000000000000..cb0e4b28cb001 --- /dev/null +++ b/docs/Structure.adoc @@ -0,0 +1,121 @@ += Structure +:Author: Substrate developers +:Revision: 0.3.0 +:toc: +:sectnums: + + +== Overview + +Substrate is split into multiple levels with increasing opinion and decreasing flexibility: + +* primitives +* client +* FRAME (formerly `srml`) + +Putting all these components together we have: + +* Integration Tests +* Node +* Node template +* Subkey + +=== Runtime + +* _found in_: `/primitives` +* _crates prefix_: `sp-` +* _constraints_: +** must be `[no_std]` +** crates may not (dev-)depend on crates in other subfolders of this repo + +In the lowest level, Substrate defines primitives, interfaces and traits to implement any on-chain Substrate transition system and its interactions with the outside world. This is the lowest level of abstraction and opinion that everything else builds upon. + +=== Client + +* _found in_: `/client` +* _crates prefix_: `substrate-` +* _constraints_: +** crates may not (dev-)depend on any `frame-`-crates + +In the client you can find a set of crates to construct the outer substrate-node, implementing outer runtime interfaces, thus it depends on `runtime`. It provides the outer building blocks like transaction queue, networking layer, database backend, full* and light-client support. + +=== FRAME (formerly `srml`) + +* _found in_: `/frame` +* _crates prefix_: `frame-` and `pallet-` +* _constraints_: +** all crates that go on chain must be `[no_std]` +** must not (dev-)depend on anything in `/client` + +FRAME is a set of modules that implement specific transition functions and features one might want to have in their runtime. + +_Pallets_ are individual modules within _FRAME._ These are containers that host domain-specific logic. They have the `pallet-` prefix. For example, `pallet-staking` contains logic for staking tokens. + +There are a few crates with the `frame-` prefix. These do not contain domain-specific logic. Rather, they are the main FRAME support infrastructure. These are: + +- Executive +- Metadata +- Support +- System +- Utility + +=== Integration Tests + +* _found in_: `/test` +* _crates prefix_: `substrate-test` +* _constraints_: +** only helpers may be published +** purely testing crates must be `publish = false` + +All tests that have to pull (dev)-dependencies out of their subtree and would thus break the dependency rules are considered intergration tests and should be stored in here. Only helper-crates in here shall be published, everything else is expected to be non-publish. + +=== Binaries and template + +* _found in_: `/bin` + +We also provide some binaries pulling from the components creating full applications. + +==== Node + +* _found in_: `/bin/node` + +The default (testing) application pulling together our recommended setup of substrate-client with a wasm-contracts-supporting frame-runtime. The node pulls it all together, constructs the (upgradable) runtime, and wires up the client around it. You can find an example client, which includes a full wasm-contracts chain in `node`. This is also what is being built and run if you do `cargo run`. + +==== Node Template + +* _found in_: `/bin/node-template` + +We also provide a template to get you started building your own node. + +==== Utils + +* _found in_: `/bin/utils` + +- **subkey** + Subkey is a client library to generate keys and sign transactions to send to a substrate node. +- **chain-spec-builder** + The chain spec builder builds a chain specification that includes a Substrate runtime compiled as WASM. To ensure proper functioning of the included runtime compile (or run) the chain spec builder binary in `--release` mode. + +== Internal Dependency Tree + +[ditaa] +.... ++---------------+ +----------------+ +| | | | +| runtime +<------+ frame | +| | | | ++------+-----+--+ +-------------+--+ + ^ ^ ^ + | +----------------+ | + | | | ++------+--------+ | | +| | | | +| client | +--+-------+--------+ +| +<---------+ | ++---------------+ | | + | test /bin/* | + | | + | | + +-------------------+ + +.... diff --git a/docs/Upgrade.md b/docs/Upgrade.md new file mode 100644 index 0000000000000..4908d53f579e4 --- /dev/null +++ b/docs/Upgrade.md @@ -0,0 +1,5 @@ +# Upgrade path for you building on substrate + +## master + - crate rename has been fixed `sp-application-crypto` (was `sc-application-crypto`); `.maintain/rename-crates-for-2.0.sh` has been updated accordingly, you can use it to upgrade to latest naming convention + - crates have been renamed, run `bash .maintain/rename-crates-for-2.0.sh` \ No newline at end of file diff --git a/license_header.txt b/docs/license_header.txt similarity index 92% rename from license_header.txt rename to docs/license_header.txt index 15b778660733f..f9c1daa1ad1c1 100644 --- a/license_header.txt +++ b/docs/license_header.txt @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml new file mode 100644 index 0000000000000..f371f21e1ab7e --- /dev/null +++ b/frame/assets/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "pallet-assets" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +# Needed for various traits. In our case, `OnFinalize`. +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +# Needed for type-safe access to storage DB. +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +# `system` module provides us with all sorts of useful stuff and macros depend on it being around. +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-std = { version = "2.0.0", path = "../../primitives/std" } +sp-io = { version = "2.0.0", path = "../../primitives/io" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs new file mode 100644 index 0000000000000..f77eb663db871 --- /dev/null +++ b/frame/assets/src/lib.rs @@ -0,0 +1,395 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Assets Module +//! +//! A simple, secure module for dealing with fungible assets. +//! +//! ## Overview +//! +//! The Assets module provides functionality for asset management of fungible asset classes +//! with a fixed supply, including: +//! +//! * Asset Issuance +//! * Asset Transfer +//! * Asset Destruction +//! +//! To use it in your runtime, you need to implement the assets [`Trait`](./trait.Trait.html). +//! +//! The supported dispatchable functions are documented in the [`Call`](./enum.Call.html) enum. +//! +//! ### Terminology +//! +//! * **Asset issuance:** The creation of a new asset, whose total supply will belong to the +//! account that issues the asset. +//! * **Asset transfer:** The action of transferring assets from one account to another. +//! * **Asset destruction:** The process of an account removing its entire holding of an asset. +//! * **Fungible asset:** An asset whose units are interchangeable. +//! * **Non-fungible asset:** An asset for which each unit has unique characteristics. +//! +//! ### Goals +//! +//! The assets system in Substrate is designed to make the following possible: +//! +//! * Issue a unique asset to its creator's account. +//! * Move assets between accounts. +//! * Remove an account's balance of an asset when requested by that account's owner and update +//! the asset's total supply. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! * `issue` - Issues the total supply of a new fungible asset to the account of the caller of the function. +//! * `transfer` - Transfers an `amount` of units of fungible asset `id` from the balance of +//! the function caller's account (`origin`) to a `target` account. +//! * `destroy` - Destroys the entire holding of a fungible asset `id` associated with the account +//! that called the function. +//! +//! Please refer to the [`Call`](./enum.Call.html) enum and its associated variants for documentation on each function. +//! +//! ### Public Functions +//! +//! +//! * `balance` - Get the asset `id` balance of `who`. +//! * `total_supply` - Get the total supply of an asset `id`. +//! +//! Please refer to the [`Module`](./struct.Module.html) struct for details on publicly available functions. +//! +//! ## Usage +//! +//! The following example shows how to use the Assets module in your runtime by exposing public functions to: +//! +//! * Issue a new fungible asset for a token distribution event (airdrop). +//! * Query the fungible asset holding balance of an account. +//! * Query the total supply of a fungible asset that has been issued. +//! +//! ### Prerequisites +//! +//! Import the Assets module and types and derive your runtime's configuration traits from the Assets module trait. +//! +//! ### Simple Code Snippet +//! +//! ```rust,ignore +//! use pallet_assets as assets; +//! use frame_support::{decl_module, dispatch, ensure}; +//! use frame_system::{self as system, ensure_signed}; +//! +//! pub trait Trait: assets::Trait { } +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn issue_token_airdrop(origin) -> dispatch::DispatchResult { +//! let sender = ensure_signed(origin).map_err(|e| e.as_str())?; +//! +//! const ACCOUNT_ALICE: u64 = 1; +//! const ACCOUNT_BOB: u64 = 2; +//! const COUNT_AIRDROP_RECIPIENTS: u64 = 2; +//! const TOKENS_FIXED_SUPPLY: u64 = 100; +//! +//! ensure!(!COUNT_AIRDROP_RECIPIENTS.is_zero(), "Divide by zero error."); +//! +//! let asset_id = Self::next_asset_id(); +//! +//! >::mutate(|asset_id| *asset_id += 1); +//! >::insert((asset_id, &ACCOUNT_ALICE), TOKENS_FIXED_SUPPLY / COUNT_AIRDROP_RECIPIENTS); +//! >::insert((asset_id, &ACCOUNT_BOB), TOKENS_FIXED_SUPPLY / COUNT_AIRDROP_RECIPIENTS); +//! >::insert(asset_id, TOKENS_FIXED_SUPPLY); +//! +//! Self::deposit_event(RawEvent::Issued(asset_id, sender, TOKENS_FIXED_SUPPLY)); +//! Ok(()) +//! } +//! } +//! } +//! ``` +//! +//! ## Assumptions +//! +//! Below are assumptions that must be held when using this module. If any of +//! them are violated, the behavior of this module is undefined. +//! +//! * The total count of assets should be less than +//! `Trait::AssetId::max_value()`. +//! +//! ## Related Modules +//! +//! * [`System`](../frame_system/index.html) +//! * [`Support`](../frame_support/index.html) + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::{Parameter, decl_module, decl_event, decl_storage, decl_error, ensure}; +use sp_runtime::traits::{Member, SimpleArithmetic, Zero, StaticLookup}; +use frame_system::{self as system, ensure_signed}; +use sp_runtime::traits::One; + +/// The module configuration trait. +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The units in which we record balances. + type Balance: Member + Parameter + SimpleArithmetic + Default + Copy; + + /// The arithmetic type of asset identifier. + type AssetId: Parameter + SimpleArithmetic + Default + Copy; +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + 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, #[compact] total: T::Balance) { + let origin = ensure_signed(origin)?; + + let id = Self::next_asset_id(); + >::mutate(|id| *id += One::one()); + + >::insert((id, &origin), total); + >::insert(id, total); + + Self::deposit_event(RawEvent::Issued(id, origin, total)); + } + + /// Move some assets from one holder to another. + fn transfer(origin, + #[compact] id: T::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(), Error::::AmountZero); + ensure!(origin_balance >= amount, Error::::BalanceLow); + + Self::deposit_event(RawEvent::Transferred(id, origin, target.clone(), amount)); + >::insert(origin_account, origin_balance - amount); + >::mutate((id, target), |balance| *balance += amount); + } + + /// Destroy any assets of `id` owned by `origin`. + fn destroy(origin, #[compact] id: T::AssetId) { + let origin = ensure_signed(origin)?; + let balance = >::take((id, &origin)); + ensure!(!balance.is_zero(), Error::::BalanceZero); + + >::mutate(id, |total_supply| *total_supply -= balance); + Self::deposit_event(RawEvent::Destroyed(id, origin, balance)); + } + } +} + +decl_event! { + pub enum Event where + ::AccountId, + ::Balance, + ::AssetId, + { + /// Some assets were issued. + Issued(AssetId, AccountId, Balance), + /// Some assets were transferred. + Transferred(AssetId, AccountId, AccountId, Balance), + /// Some assets were destroyed. + Destroyed(AssetId, AccountId, Balance), + } +} + +decl_error! { + pub enum Error for Module { + /// Transfer amount should be non-zero + AmountZero, + /// Account balance must be greater than or equal to the transfer amount + BalanceLow, + /// Balance should be non-zero + BalanceZero, + } +} + +decl_storage! { + trait Store for Module as Assets { + /// The number of units of assets held by any given account. + Balances: map (T::AssetId, T::AccountId) => T::Balance; + /// The next asset identifier up for grabs. + NextAssetId get(fn next_asset_id): T::AssetId; + /// The total unit supply of an asset. + TotalSupply: map T::AssetId => T::Balance; + } +} + +// The main implementation block for the module. +impl Module { + // Public immutables + + /// Get the asset `id` balance of `who`. + pub fn balance(id: T::AssetId, who: T::AccountId) -> T::Balance { + >::get((id, who)) + } + + /// Get the total supply of an asset `id`. + pub fn total_supply(id: T::AssetId) -> T::Balance { + >::get(id) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use frame_support::{impl_outer_origin, assert_ok, assert_noop, parameter_types, weights::Weight}; + use sp_core::H256; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. + use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type Call = (); + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + impl Trait for Test { + type Event = (); + type Balance = u64; + type AssetId = u32; + } + type Assets = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> sp_io::TestExternalities { + frame_system::GenesisConfig::default().build_storage::().unwrap().into() + } + + #[test] + fn issuing_asset_units_to_issuer_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 1), 100); + }); + } + + #[test] + fn querying_total_supply_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 1), 100); + assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); + assert_eq!(Assets::balance(0, 1), 50); + assert_eq!(Assets::balance(0, 2), 50); + assert_ok!(Assets::transfer(Origin::signed(2), 0, 3, 31)); + assert_eq!(Assets::balance(0, 1), 50); + assert_eq!(Assets::balance(0, 2), 19); + assert_eq!(Assets::balance(0, 3), 31); + assert_ok!(Assets::destroy(Origin::signed(3), 0)); + assert_eq!(Assets::total_supply(0), 69); + }); + } + + #[test] + fn transferring_amount_above_available_balance_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 1), 100); + assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); + assert_eq!(Assets::balance(0, 1), 50); + assert_eq!(Assets::balance(0, 2), 50); + }); + } + + #[test] + fn transferring_amount_more_than_available_balance_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 1), 100); + assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); + assert_eq!(Assets::balance(0, 1), 50); + assert_eq!(Assets::balance(0, 2), 50); + assert_ok!(Assets::destroy(Origin::signed(1), 0)); + assert_eq!(Assets::balance(0, 1), 0); + assert_noop!(Assets::transfer(Origin::signed(1), 0, 1, 50), Error::::BalanceLow); + }); + } + + #[test] + fn transferring_less_than_one_unit_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 1), 100); + assert_noop!(Assets::transfer(Origin::signed(1), 0, 2, 0), Error::::AmountZero); + }); + } + + #[test] + fn transferring_more_units_than_total_supply_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 1), 100); + assert_noop!(Assets::transfer(Origin::signed(1), 0, 2, 101), Error::::BalanceLow); + }); + } + + #[test] + fn destroying_asset_balance_with_positive_balance_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 1), 100); + assert_ok!(Assets::destroy(Origin::signed(1), 0)); + }); + } + + #[test] + fn destroying_asset_balance_with_zero_balance_should_not_work() { + new_test_ext().execute_with(|| { + assert_ok!(Assets::issue(Origin::signed(1), 100)); + assert_eq!(Assets::balance(0, 2), 0); + assert_noop!(Assets::destroy(Origin::signed(2), 0), Error::::BalanceZero); + }); + } +} diff --git a/frame/aura/Cargo.toml b/frame/aura/Cargo.toml new file mode 100644 index 0000000000000..26754458321fd --- /dev/null +++ b/frame/aura/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "pallet-aura" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../../primitives/application-crypto" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +serde = { version = "1.0.101", optional = true } +pallet-session = { version = "2.0.0", default-features = false, path = "../session" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io ={ path = "../../primitives/io", default-features = false } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +sp-consensus-aura = { path = "../../primitives/consensus/aura", default-features = false} +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +sp-timestamp = { version = "2.0.0", default-features = false, path = "../../primitives/timestamp" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../timestamp" } + + +[dev-dependencies] +lazy_static = "1.4.0" +parking_lot = "0.9.0" + +[features] +default = ["std"] +std = [ + "sp-application-crypto/std", + "codec/std", + "sp-inherents/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "serde", + "sp-runtime/std", + "frame-support/std", + "sp-consensus-aura/std", + "frame-system/std", + "sp-timestamp/std", + "pallet-timestamp/std", +] diff --git a/frame/aura/src/lib.rs b/frame/aura/src/lib.rs new file mode 100644 index 0000000000000..1a711f314abcd --- /dev/null +++ b/frame/aura/src/lib.rs @@ -0,0 +1,233 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Aura Module +//! +//! - [`aura::Trait`](./trait.Trait.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Overview +//! +//! The Aura module extends Aura consensus by managing offline reporting. +//! +//! ## Interface +//! +//! ### Public Functions +//! +//! - `slot_duration` - Determine the Aura slot-duration based on the Timestamp module configuration. +//! +//! ## Related Modules +//! +//! - [Timestamp](../pallet_timestamp/index.html): The Timestamp module is used in Aura to track +//! consensus rounds (via `slots`). +//! - [Consensus](../frame_consensus/index.html): The Consensus module does not relate directly to Aura, +//! but serves to manage offline reporting by implementing `ProvideInherent` in a similar way. +//! +//! ## References +//! +//! If you're interested in hacking on this module, it is useful to understand the interaction with +//! `substrate/primitives/inherents/src/lib.rs` and, specifically, the required implementation of +//! [`ProvideInherent`](../sp_inherents/trait.ProvideInherent.html) and +//! [`ProvideInherentData`](../sp_inherents/trait.ProvideInherentData.html) to create and check inherents. + +#![cfg_attr(not(feature = "std"), no_std)] + +use pallet_timestamp; + +use sp_std::{result, prelude::*}; +use codec::{Encode, Decode}; +use frame_support::{ + decl_storage, decl_module, Parameter, traits::{Get, FindAuthor}, + ConsensusEngineId, +}; +use sp_runtime::{ + RuntimeAppPublic, + traits::{SaturatedConversion, Saturating, Zero, Member, IsMember}, generic::DigestItem, +}; +use sp_timestamp::OnTimestampSet; +use sp_inherents::{InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; +use sp_consensus_aura::{ + AURA_ENGINE_ID, ConsensusLog, AuthorityIndex, + inherents::{INHERENT_IDENTIFIER, AuraInherentData}, +}; + +mod mock; +mod tests; + +pub trait Trait: pallet_timestamp::Trait { + /// The identifier type for an authority. + type AuthorityId: Member + Parameter + RuntimeAppPublic + Default; +} + +decl_storage! { + trait Store for Module as Aura { + /// The last timestamp. + LastTimestamp get(fn last) build(|_| 0.into()): T::Moment; + + /// The current authorities + pub Authorities get(fn authorities): Vec; + } + add_extra_genesis { + config(authorities): Vec; + build(|config| Module::::initialize_authorities(&config.authorities)) + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { } +} + +impl Module { + fn change_authorities(new: Vec) { + >::put(&new); + + let log: DigestItem = DigestItem::Consensus( + AURA_ENGINE_ID, + ConsensusLog::AuthoritiesChange(new).encode() + ); + >::deposit_log(log.into()); + } + + fn initialize_authorities(authorities: &[T::AuthorityId]) { + if !authorities.is_empty() { + assert!(>::get().is_empty(), "Authorities are already initialized!"); + >::put(authorities); + } + } +} + +impl sp_runtime::BoundToRuntimeAppPublic for Module { + type Public = T::AuthorityId; +} + +impl pallet_session::OneSessionHandler for Module { + type Key = T::AuthorityId; + + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let authorities = validators.map(|(_, k)| k).collect::>(); + Self::initialize_authorities(&authorities); + } + + fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) + where I: Iterator + { + // instant changes + if changed { + let next_authorities = validators.map(|(_, k)| k).collect::>(); + let last_authorities = >::authorities(); + if next_authorities != last_authorities { + Self::change_authorities(next_authorities); + } + } + } + + fn on_disabled(i: usize) { + let log: DigestItem = DigestItem::Consensus( + AURA_ENGINE_ID, + ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), + ); + + >::deposit_log(log.into()); + } +} + +impl FindAuthor for Module { + fn find_author<'a, I>(digests: I) -> Option where + I: 'a + IntoIterator + { + for (id, mut data) in digests.into_iter() { + if id == AURA_ENGINE_ID { + if let Ok(slot_num) = u64::decode(&mut data) { + let author_index = slot_num % Self::authorities().len() as u64; + return Some(author_index as u32) + } + } + } + + None + } +} + +impl IsMember for Module { + fn is_member(authority_id: &T::AuthorityId) -> bool { + Self::authorities() + .iter() + .any(|id| id == authority_id) + } +} + +impl Module { + /// Determine the Aura slot-duration based on the Timestamp module configuration. + pub fn slot_duration() -> T::Moment { + // we double the minimum block-period so each author can always propose within + // the majority of its slot. + ::MinimumPeriod::get().saturating_mul(2.into()) + } + + fn on_timestamp_set(now: T::Moment, slot_duration: T::Moment) { + let last = Self::last(); + ::LastTimestamp::put(now); + + if last.is_zero() { + return; + } + + assert!(!slot_duration.is_zero(), "Aura slot duration cannot be zero."); + + let last_slot = last / slot_duration; + let cur_slot = now / slot_duration; + + assert!(last_slot < cur_slot, "Only one block may be authored per slot."); + + // TODO [#3398] Generate offence report for all authorities that skipped their slots. + } +} + +impl OnTimestampSet for Module { + fn on_timestamp_set(moment: T::Moment) { + Self::on_timestamp_set(moment, Self::slot_duration()) + } +} + +impl ProvideInherent for Module { + type Call = pallet_timestamp::Call; + type Error = MakeFatalError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(_: &InherentData) -> Option { + None + } + + /// Verify the validity of the inherent using the timestamp. + fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> { + let timestamp = match call { + pallet_timestamp::Call::set(ref timestamp) => timestamp.clone(), + _ => return Ok(()), + }; + + let timestamp_based_slot = timestamp / Self::slot_duration(); + + let seal_slot = data.aura_inherent_data()?.saturated_into(); + + if timestamp_based_slot == seal_slot { + Ok(()) + } else { + Err(sp_inherents::Error::from("timestamp set in block doesn't match slot in seal").into()) + } + } +} diff --git a/frame/aura/src/mock.rs b/frame/aura/src/mock.rs new file mode 100644 index 0000000000000..81366cf0842d6 --- /dev/null +++ b/frame/aura/src/mock.rs @@ -0,0 +1,84 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use crate::{Trait, Module, GenesisConfig}; +use sp_consensus_aura::ed25519::AuthorityId; +use sp_runtime::{ + traits::IdentityLookup, Perbill, + testing::{Header, UintAuthorityId}, +}; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use sp_io; +use sp_core::H256; + +impl_outer_origin!{ + pub enum Origin for Test where system = frame_system {} +} + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Test; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const MinimumPeriod: u64 = 1; +} + +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); +} + +impl pallet_timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; +} + +impl Trait for Test { + type AuthorityId = AuthorityId; +} + +pub fn new_test_ext(authorities: Vec) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig::{ + authorities: authorities.into_iter().map(|a| UintAuthorityId(a).to_public_key()).collect(), + }.assimilate_storage(&mut t).unwrap(); + t.into() +} + +pub type Aura = Module; diff --git a/frame/aura/src/tests.rs b/frame/aura/src/tests.rs new file mode 100644 index 0000000000000..a7cb5503c4712 --- /dev/null +++ b/frame/aura/src/tests.rs @@ -0,0 +1,29 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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 crate::mock::{Aura, new_test_ext}; + +#[test] +fn initial_values() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + assert_eq!(Aura::last(), 0u64); + assert_eq!(Aura::authorities().len(), 4); + }); +} diff --git a/frame/authority-discovery/Cargo.toml b/frame/authority-discovery/Cargo.toml new file mode 100644 index 0000000000000..3760d863d70ad --- /dev/null +++ b/frame/authority-discovery/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "pallet-authority-discovery" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-authority-discovery = { version = "2.0.0", default-features = false, path = "../../primitives/authority-discovery" } +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../../primitives/application-crypto" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +serde = { version = "1.0.101", optional = true } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +pallet-session = { version = "2.0.0", features = ["historical" ], path = "../session", default-features = false } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" } + +[features] +default = ["std"] +std = [ + "sp-application-crypto/std", + "sp-authority-discovery/std", + "codec/std", + "sp-core/std", + "sp-io/std", + "sp-std/std", + "serde", + "pallet-session/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs new file mode 100644 index 0000000000000..b3911859f4787 --- /dev/null +++ b/frame/authority-discovery/src/lib.rs @@ -0,0 +1,252 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Authority discovery module. +//! +//! This module is used by the `client/authority-discovery` to retrieve the +//! current set of authorities. + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use frame_support::{decl_module, decl_storage}; +use sp_authority_discovery::AuthorityId; + +/// The module's config trait. +pub trait Trait: frame_system::Trait + pallet_session::Trait {} + +decl_storage! { + trait Store for Module as AuthorityDiscovery { + /// Keys of the current authority set. + Keys get(fn keys): Vec; + } + add_extra_genesis { + config(keys): Vec; + build(|config| Module::::initialize_keys(&config.keys)) + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + } +} + +impl Module { + /// Retrieve authority identifiers of the current authority set. + pub fn authorities() -> Vec { + Keys::get() + } + + fn initialize_keys(keys: &[AuthorityId]) { + if !keys.is_empty() { + assert!(Keys::get().is_empty(), "Keys are already initialized!"); + Keys::put(keys); + } + } +} + +impl sp_runtime::BoundToRuntimeAppPublic for Module { + type Public = AuthorityId; +} + +impl pallet_session::OneSessionHandler for Module { + type Key = AuthorityId; + + fn on_genesis_session<'a, I: 'a>(authorities: I) + where + I: Iterator, + { + let keys = authorities.map(|x| x.1).collect::>(); + Self::initialize_keys(&keys); + } + + fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) + where + I: Iterator, + { + // Remember who the authorities are for the new session. + if changed { + Keys::put(validators.map(|x| x.1).collect::>()); + } + } + + fn on_disabled(_i: usize) { + // ignore + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_authority_discovery::{AuthorityPair}; + use sp_application_crypto::Pair; + use sp_core::{crypto::key_types, H256}; + use sp_io::TestExternalities; + use sp_runtime::{ + testing::{Header, UintAuthorityId}, traits::{ConvertInto, IdentityLookup, OpaqueKeys}, + Perbill, KeyTypeId, + }; + use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; + + type AuthorityDiscovery = Module; + type SessionIndex = u32; + + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + impl Trait for Test {} + + pub struct TestOnSessionEnding; + impl pallet_session::OnSessionEnding for TestOnSessionEnding { + fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { + None + } + } + + parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); + } + + impl pallet_session::Trait for Test { + type OnSessionEnding = TestOnSessionEnding; + type Keys = UintAuthorityId; + type ShouldEndSession = pallet_session::PeriodicSessions; + type SessionHandler = TestSessionHandler; + type Event = (); + type ValidatorId = AuthorityId; + type ValidatorIdOf = ConvertInto; + type SelectInitialValidators = (); + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; + } + + impl pallet_session::historical::Trait for Test { + type FullIdentification = (); + type FullIdentificationOf = (); + } + + pub type BlockNumber = u64; + + parameter_types! { + pub const Period: BlockNumber = 1; + pub const Offset: BlockNumber = 0; + pub const UncleGenerations: u64 = 0; + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = BlockNumber; + type Call = (); + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AuthorityId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + pub struct TestSessionHandler; + impl pallet_session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[key_types::DUMMY]; + + fn on_new_session( + _changed: bool, + _validators: &[(AuthorityId, Ks)], + _queued_validators: &[(AuthorityId, Ks)], + ) { + } + + fn on_disabled(_validator_index: usize) {} + + fn on_genesis_session(_validators: &[(AuthorityId, Ks)]) {} + } + + #[test] + fn authorities_returns_current_authority_set() { + // The whole authority discovery module ignores account ids, but we still need it for + // `pallet_session::OneSessionHandler::on_new_session`, thus its safe to use the same value everywhere. + let account_id = AuthorityPair::from_seed_slice(vec![10; 32].as_ref()).unwrap().public(); + + let first_authorities: Vec = vec![0, 1].into_iter() + .map(|i| AuthorityPair::from_seed_slice(vec![i; 32].as_ref()).unwrap().public()) + .map(AuthorityId::from) + .collect(); + + let second_authorities: Vec = vec![2, 3].into_iter() + .map(|i| AuthorityPair::from_seed_slice(vec![i; 32].as_ref()).unwrap().public()) + .map(AuthorityId::from) + .collect(); + + // Needed for `pallet_session::OneSessionHandler::on_new_session`. + let second_authorities_and_account_ids: Vec<(&AuthorityId, AuthorityId)> = second_authorities.clone() + .into_iter() + .map(|id| (&account_id, id)) + .collect(); + + // Build genesis. + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + GenesisConfig { + keys: vec![], + } + .assimilate_storage::(&mut t) + .unwrap(); + + // Create externalities. + let mut externalities = TestExternalities::new(t); + + externalities.execute_with(|| { + use pallet_session::OneSessionHandler; + + AuthorityDiscovery::on_genesis_session( + first_authorities.iter().map(|id| (id, id.clone())) + ); + assert_eq!(first_authorities, AuthorityDiscovery::authorities()); + + // When `changed` set to false, the authority set should not be updated. + AuthorityDiscovery::on_new_session( + false, + second_authorities_and_account_ids.clone().into_iter(), + vec![].into_iter(), + ); + assert_eq!(first_authorities, AuthorityDiscovery::authorities()); + + // When `changed` set to true, the authority set should be updated. + AuthorityDiscovery::on_new_session( + true, + second_authorities_and_account_ids.into_iter(), + vec![].into_iter(), + ); + assert_eq!(second_authorities, AuthorityDiscovery::authorities()); + }); + } +} diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml new file mode 100644 index 0000000000000..298da65a2b02b --- /dev/null +++ b/frame/authorship/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "pallet-authorship" +version = "2.0.0" +description = "Block and Uncle Author tracking for the SRML" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +sp-authorship = { version = "2.0.0", default-features = false, path = "../../primitives/authorship" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +sp-io ={ path = "../../primitives/io", default-features = false } +impl-trait-for-tuples = "0.1.3" + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-core/std", + "sp-inherents/std", + "sp-runtime/std", + "sp-std/std", + "frame-support/std", + "frame-system/std", + "sp-io/std", + "sp-authorship/std", +] diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs new file mode 100644 index 0000000000000..216f5c729a9c4 --- /dev/null +++ b/frame/authorship/src/lib.rs @@ -0,0 +1,726 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Authorship tracking for SRML runtimes. +//! +//! This tracks the current author of the block and recent uncles. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{result, prelude::*}; +use sp_std::collections::btree_set::BTreeSet; +use frame_support::{decl_module, decl_storage, decl_error, dispatch, ensure}; +use frame_support::traits::{FindAuthor, VerifySeal, Get}; +use codec::{Encode, Decode}; +use frame_system::ensure_none; +use sp_runtime::traits::{Header as HeaderT, One, Zero}; +use frame_support::weights::SimpleDispatchInfo; +use sp_inherents::{InherentIdentifier, ProvideInherent, InherentData}; +use sp_authorship::{INHERENT_IDENTIFIER, UnclesInherentData, InherentError}; + +const MAX_UNCLES: usize = 10; + +pub trait Trait: frame_system::Trait { + /// Find the author of a block. + type FindAuthor: FindAuthor; + /// The number of blocks back we should accept uncles. + /// This means that we will deal with uncle-parents that are + /// `UncleGenerations + 1` before `now`. + type UncleGenerations: Get; + /// A filter for uncles within a block. This is for implementing + /// further constraints on what uncles can be included, other than their ancestry. + /// + /// For PoW, as long as the seals are checked, there is no need to use anything + /// but the `VerifySeal` implementation as the filter. This is because the cost of making many equivocating + /// uncles is high. + /// + /// For PoS, there is no such limitation, so a further constraint must be imposed + /// beyond a seal check in order to prevent an arbitrary number of + /// equivocating uncles from being included. + /// + /// The `OnePerAuthorPerHeight` filter is good for many slot-based PoS + /// engines. + type FilterUncle: FilterUncle; + /// An event handler for authored blocks. + type EventHandler: EventHandler; +} + +/// An event handler for the authorship module. There is a dummy implementation +/// for `()`, which does nothing. +#[impl_trait_for_tuples::impl_for_tuples(30)] +pub trait EventHandler { + /// Note that the given account ID is the author of the current block. + fn note_author(author: Author); + + /// Note that the given account ID authored the given uncle, and how many + /// blocks older than the current block it is (age >= 0, so siblings are allowed) + fn note_uncle(author: Author, age: BlockNumber); +} + +/// Additional filtering on uncles that pass preliminary ancestry checks. +/// +/// This should do work such as checking seals +pub trait FilterUncle { + /// An accumulator of data about uncles included. + /// + /// In practice, this is used to validate uncles against others in the same block. + type Accumulator: Default; + + /// Do additional filtering on a seal-checked uncle block, with the accumulated + /// filter. + fn filter_uncle(header: &Header, acc: &mut Self::Accumulator) + -> Result, &'static str>; +} + +impl FilterUncle for () { + type Accumulator = (); + fn filter_uncle(_: &H, _acc: &mut Self::Accumulator) + -> Result, &'static str> + { + Ok(None) + } +} + +/// A filter on uncles which verifies seals and does no additional checks. +/// This is well-suited to consensus modes such as PoW where the cost of +/// equivocating is high. +pub struct SealVerify(sp_std::marker::PhantomData); + +impl> FilterUncle + for SealVerify +{ + type Accumulator = (); + + fn filter_uncle(header: &Header, _acc: &mut ()) + -> Result, &'static str> + { + T::verify_seal(header) + } +} + +/// A filter on uncles which verifies seals and ensures that there is only +/// one uncle included per author per height. +/// +/// This does O(n log n) work in the number of uncles included. +pub struct OnePerAuthorPerHeight(sp_std::marker::PhantomData<(T, N)>); + +impl FilterUncle + for OnePerAuthorPerHeight +where + Header: HeaderT + PartialEq, + Header::Number: Ord, + Author: Clone + PartialEq + Ord, + T: VerifySeal, +{ + type Accumulator = BTreeSet<(Header::Number, Author)>; + + fn filter_uncle(header: &Header, acc: &mut Self::Accumulator) + -> Result, &'static str> + { + let author = T::verify_seal(header)?; + let number = header.number(); + + if let Some(ref author) = author { + if !acc.insert((number.clone(), author.clone())) { + return Err("more than one uncle per number per author included"); + } + } + + Ok(author) + } +} + +#[derive(Encode, Decode, sp_runtime::RuntimeDebug)] +#[cfg_attr(any(feature = "std", test), derive(PartialEq))] +enum UncleEntryItem { + InclusionHeight(BlockNumber), + Uncle(Hash, Option), +} + +decl_storage! { + trait Store for Module as Authorship { + /// Uncles + Uncles: Vec>; + /// Author of current block. + Author: Option; + /// Whether uncles were already set in this block. + DidSetUncles: bool; + } +} + +decl_error! { + /// Error for the authorship module. + pub enum Error for Module { + /// The uncle parent not in the chain. + InvalidUncleParent, + /// Uncles already set in the block. + UnclesAlreadySet, + /// Too many uncles. + TooManyUncles, + /// The uncle is genesis. + GenesisUncle, + /// The uncle is too high in chain. + TooHighUncle, + /// The uncle is already included. + UncleAlreadyIncluded, + /// The uncle isn't recent enough to be included. + OldUncle, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn on_initialize(now: T::BlockNumber) { + let uncle_generations = T::UncleGenerations::get(); + // prune uncles that are older than the allowed number of generations. + if uncle_generations <= now { + let minimum_height = now - uncle_generations; + Self::prune_old_uncles(minimum_height) + } + + ::DidSetUncles::put(false); + + T::EventHandler::note_author(Self::author()); + } + + fn on_finalize() { + // ensure we never go to trie with these values. + ::Author::kill(); + ::DidSetUncles::kill(); + } + + /// Provide a set of uncles. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn set_uncles(origin, new_uncles: Vec) -> dispatch::DispatchResult { + ensure_none(origin)?; + ensure!(new_uncles.len() <= MAX_UNCLES, Error::::TooManyUncles); + + if ::DidSetUncles::get() { + Err(Error::::UnclesAlreadySet)? + } + ::DidSetUncles::put(true); + + Self::verify_and_import_uncles(new_uncles) + } + } +} + +impl Module { + /// Fetch the author of the block. + /// + /// This is safe to invoke in `on_initialize` implementations, as well + /// as afterwards. + pub fn author() -> T::AccountId { + // Check the memoized storage value. + if let Some(author) = ::Author::get() { + return author; + } + + let digest = >::digest(); + let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); + if let Some(author) = T::FindAuthor::find_author(pre_runtime_digests) { + ::Author::put(&author); + author + } else { + Default::default() + } + } + + fn verify_and_import_uncles(new_uncles: Vec) -> dispatch::DispatchResult { + let now = >::block_number(); + + let mut uncles = ::Uncles::get(); + uncles.push(UncleEntryItem::InclusionHeight(now)); + + let mut acc: >::Accumulator = Default::default(); + + for uncle in new_uncles { + let prev_uncles = uncles.iter().filter_map(|entry| + match entry { + UncleEntryItem::InclusionHeight(_) => None, + UncleEntryItem::Uncle(h, _) => Some(h), + }); + let author = Self::verify_uncle(&uncle, prev_uncles, &mut acc)?; + let hash = uncle.hash(); + + T::EventHandler::note_uncle( + author.clone().unwrap_or_default(), + now - uncle.number().clone(), + ); + uncles.push(UncleEntryItem::Uncle(hash, author)); + } + + ::Uncles::put(&uncles); + Ok(()) + } + + fn verify_uncle<'a, I: IntoIterator>( + uncle: &T::Header, + existing_uncles: I, + accumulator: &mut >::Accumulator, + ) -> Result, dispatch::DispatchError> + { + let now = >::block_number(); + + let (minimum_height, maximum_height) = { + let uncle_generations = T::UncleGenerations::get(); + let min = if now >= uncle_generations { + now - uncle_generations + } else { + Zero::zero() + }; + + (min, now) + }; + + let hash = uncle.hash(); + + if uncle.number() < &One::one() { + return Err(Error::::GenesisUncle.into()); + } + + if uncle.number() > &maximum_height { + return Err(Error::::TooHighUncle.into()); + } + + { + let parent_number = uncle.number().clone() - One::one(); + let parent_hash = >::block_hash(&parent_number); + if &parent_hash != uncle.parent_hash() { + return Err(Error::::InvalidUncleParent.into()); + } + } + + if uncle.number() < &minimum_height { + return Err(Error::::OldUncle.into()); + } + + let duplicate = existing_uncles.into_iter().find(|h| **h == hash).is_some(); + let in_chain = >::block_hash(uncle.number()) == hash; + + if duplicate || in_chain { + return Err(Error::::UncleAlreadyIncluded.into()) + } + + // check uncle validity. + T::FilterUncle::filter_uncle(&uncle, accumulator).map_err(|e| Into::into(e)) + } + + fn prune_old_uncles(minimum_height: T::BlockNumber) { + let mut uncles = ::Uncles::get(); + let prune_entries = uncles.iter().take_while(|item| match item { + UncleEntryItem::Uncle(_, _) => true, + UncleEntryItem::InclusionHeight(height) => height < &minimum_height, + }); + let prune_index = prune_entries.count(); + + let _ = uncles.drain(..prune_index); + ::Uncles::put(uncles); + } +} + +impl ProvideInherent for Module { + type Call = Call; + type Error = InherentError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + let uncles = data.uncles().unwrap_or_default(); + let mut set_uncles = Vec::new(); + + if !uncles.is_empty() { + let prev_uncles = ::Uncles::get(); + let mut existing_hashes: Vec<_> = prev_uncles.into_iter().filter_map(|entry| + match entry { + UncleEntryItem::InclusionHeight(_) => None, + UncleEntryItem::Uncle(h, _) => Some(h), + } + ).collect(); + + let mut acc: >::Accumulator = Default::default(); + + for uncle in uncles { + match Self::verify_uncle(&uncle, &existing_hashes, &mut acc) { + Ok(_) => { + let hash = uncle.hash(); + set_uncles.push(uncle); + existing_hashes.push(hash); + + if set_uncles.len() == MAX_UNCLES { + break + } + } + Err(_) => { + // skip this uncle + } + } + } + } + + if set_uncles.is_empty() { + None + } else { + Some(Call::set_uncles(set_uncles)) + } + } + + fn check_inherent(call: &Self::Call, _data: &InherentData) -> result::Result<(), Self::Error> { + match call { + Call::set_uncles(ref uncles) if uncles.len() > MAX_UNCLES => { + Err(InherentError::Uncles(Error::::TooManyUncles.as_str().into())) + }, + _ => { + Ok(()) + }, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::H256; + use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, testing::Header, generic::DigestItem, Perbill, + }; + use frame_support::{parameter_types, impl_outer_origin, ConsensusEngineId, weights::Weight}; + + impl_outer_origin!{ + pub enum Origin for Test where system = frame_system {} + } + + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + + parameter_types! { + pub const UncleGenerations: u64 = 5; + } + + impl Trait for Test { + type FindAuthor = AuthorGiven; + type UncleGenerations = UncleGenerations; + type FilterUncle = SealVerify; + type EventHandler = (); + } + + type System = frame_system::Module; + type Authorship = Module; + + const TEST_ID: ConsensusEngineId = [1, 2, 3, 4]; + + pub struct AuthorGiven; + + impl FindAuthor for AuthorGiven { + fn find_author<'a, I>(digests: I) -> Option + where I: 'a + IntoIterator + { + for (id, data) in digests { + if id == TEST_ID { + return u64::decode(&mut &data[..]).ok(); + } + } + + None + } + } + + pub struct VerifyBlock; + + impl VerifySeal for VerifyBlock { + fn verify_seal(header: &Header) -> Result, &'static str> { + let pre_runtime_digests = header.digest.logs.iter().filter_map(|d| d.as_pre_runtime()); + let seals = header.digest.logs.iter().filter_map(|d| d.as_seal()); + + let author = match AuthorGiven::find_author(pre_runtime_digests) { + None => return Err("no author"), + Some(author) => author, + }; + + for (id, seal) in seals { + if id == TEST_ID { + match u64::decode(&mut &seal[..]) { + Err(_) => return Err("wrong seal"), + Ok(a) => { + if a != author { + return Err("wrong author in seal"); + } + break + } + } + } + } + + Ok(Some(author)) + } + } + + fn seal_header(mut header: Header, author: u64) -> Header { + { + let digest = header.digest_mut(); + digest.logs.push(DigestItem::PreRuntime(TEST_ID, author.encode())); + digest.logs.push(DigestItem::Seal(TEST_ID, author.encode())); + } + + header + } + + fn create_header(number: u64, parent_hash: H256, state_root: H256) -> Header { + Header::new( + number, + Default::default(), + state_root, + parent_hash, + Default::default(), + ) + } + + fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + t.into() + } + + #[test] + fn prune_old_uncles_works() { + use UncleEntryItem::*; + new_test_ext().execute_with(|| { + let hash = Default::default(); + let author = Default::default(); + let uncles = vec![ + InclusionHeight(1u64), Uncle(hash, Some(author)), Uncle(hash, None), Uncle(hash, None), + InclusionHeight(2u64), Uncle(hash, None), + InclusionHeight(3u64), Uncle(hash, None), + ]; + + ::Uncles::put(uncles); + Authorship::prune_old_uncles(3); + + let uncles = ::Uncles::get(); + assert_eq!(uncles, vec![InclusionHeight(3u64), Uncle(hash, None)]); + }) + } + + #[test] + fn rejects_bad_uncles() { + new_test_ext().execute_with(|| { + let author_a = 69; + + struct CanonChain { + inner: Vec
, + } + + impl CanonChain { + fn best_hash(&self) -> H256 { + self.inner.last().unwrap().hash() + } + + fn canon_hash(&self, index: usize) -> H256 { + self.inner[index].hash() + } + + fn header(&self, index: usize) -> &Header { + &self.inner[index] + } + + fn push(&mut self, header: Header) { + self.inner.push(header) + } + } + + let mut canon_chain = CanonChain { + inner: vec![seal_header(create_header(0, Default::default(), Default::default()), 999)], + }; + + let initialize_block = |number, hash: H256| System::initialize( + &number, + &hash, + &Default::default(), + &Default::default(), + Default::default() + ); + + for number in 1..8 { + initialize_block(number, canon_chain.best_hash()); + let header = seal_header(System::finalize(), author_a); + canon_chain.push(header); + } + + // initialize so system context is set up correctly. + initialize_block(8, canon_chain.best_hash()); + + // 2 of the same uncle at once + { + let uncle_a = seal_header( + create_header(3, canon_chain.canon_hash(2), [1; 32].into()), + author_a, + ); + assert_eq!( + Authorship::verify_and_import_uncles(vec![uncle_a.clone(), uncle_a.clone()]), + Err(Error::::UncleAlreadyIncluded.into()), + ); + } + + // 2 of the same uncle at different times. + { + let uncle_a = seal_header( + create_header(3, canon_chain.canon_hash(2), [1; 32].into()), + author_a, + ); + + assert!(Authorship::verify_and_import_uncles(vec![uncle_a.clone()]).is_ok()); + + assert_eq!( + Authorship::verify_and_import_uncles(vec![uncle_a.clone()]), + Err(Error::::UncleAlreadyIncluded.into()), + ); + } + + // same uncle as ancestor. + { + let uncle_clone = canon_chain.header(5).clone(); + + assert_eq!( + Authorship::verify_and_import_uncles(vec![uncle_clone]), + Err(Error::::UncleAlreadyIncluded.into()), + ); + } + + // uncle without valid seal. + { + let unsealed = create_header(3, canon_chain.canon_hash(2), [2; 32].into()); + assert_eq!( + Authorship::verify_and_import_uncles(vec![unsealed]), + Err("no author".into()), + ); + } + + // old uncles can't get in. + { + assert_eq!(System::block_number(), 8); + + let gen_2 = seal_header( + create_header(2, canon_chain.canon_hash(1), [3; 32].into()), + author_a, + ); + + assert_eq!( + Authorship::verify_and_import_uncles(vec![gen_2]), + Err(Error::::OldUncle.into()), + ); + } + + // siblings are also allowed + { + let other_8 = seal_header( + create_header(8, canon_chain.canon_hash(7), [1; 32].into()), + author_a, + ); + + assert!(Authorship::verify_and_import_uncles(vec![other_8]).is_ok()); + } + }); + } + + #[test] + fn sets_author_lazily() { + new_test_ext().execute_with(|| { + let author = 42; + let mut header = seal_header( + create_header(1, Default::default(), [1; 32].into()), + author, + ); + + header.digest_mut().pop(); // pop the seal off. + System::initialize( + &1, + &Default::default(), + &Default::default(), + header.digest(), + Default::default(), + ); + + assert_eq!(Authorship::author(), author); + }); + } + + #[test] + fn one_uncle_per_author_per_number() { + type Filter = OnePerAuthorPerHeight; + + let author_a = 42; + let author_b = 43; + + let mut acc: >::Accumulator = Default::default(); + let header_a1 = seal_header( + create_header(1, Default::default(), [1; 32].into()), + author_a, + ); + let header_b1 = seal_header( + create_header(1, Default::default(), [1; 32].into()), + author_b, + ); + + let header_a2_1 = seal_header( + create_header(2, Default::default(), [1; 32].into()), + author_a, + ); + let header_a2_2 = seal_header( + create_header(2, Default::default(), [2; 32].into()), + author_a, + ); + + let mut check_filter = move |uncle| { + Filter::filter_uncle(uncle, &mut acc) + }; + + // same height, different author is OK. + assert_eq!(check_filter(&header_a1), Ok(Some(author_a))); + assert_eq!(check_filter(&header_b1), Ok(Some(author_b))); + + // same author, different height. + assert_eq!(check_filter(&header_a2_1), Ok(Some(author_a))); + + // same author, same height (author a, height 2) + assert!(check_filter(&header_a2_2).is_err()); + } +} diff --git a/frame/babe/Cargo.toml b/frame/babe/Cargo.toml new file mode 100644 index 0000000000000..30dbda4e53c29 --- /dev/null +++ b/frame/babe/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "pallet-babe" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +hex-literal = "0.2.1" +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../timestamp" } +sp-timestamp = { version = "2.0.0", default-features = false, path = "../../primitives/timestamp" } +pallet-session = { version = "2.0.0", default-features = false, path = "../session" } +sp-consensus-babe = { version = "0.8", default-features = false, path = "../../primitives/consensus/babe" } +sp-io ={ path = "../../primitives/io", default-features = false } + +[dev-dependencies] +lazy_static = "1.4.0" +parking_lot = "0.9.0" +sp-version = { version = "2.0.0", default-features = false, path = "../../primitives/version" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "frame-support/std", + "sp-runtime/std", + "sp-staking/std", + "frame-system/std", + "pallet-timestamp/std", + "sp-timestamp/std", + "sp-inherents/std", + "sp-consensus-babe/std", + "pallet-session/std", + "sp-io/std", +] diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs new file mode 100644 index 0000000000000..f249ca9e299bf --- /dev/null +++ b/frame/babe/src/lib.rs @@ -0,0 +1,552 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Consensus extension module for BABE consensus. Collects on-chain randomness +//! from VRF outputs and manages epoch transitions. + +#![cfg_attr(not(feature = "std"), no_std)] +#![forbid(unused_must_use, unsafe_code, unused_variables, unused_must_use)] +#![deny(unused_imports)] +pub use pallet_timestamp; + +use sp_std::{result, prelude::*}; +use frame_support::{decl_storage, decl_module, traits::FindAuthor, traits::Get}; +use sp_timestamp::OnTimestampSet; +use sp_runtime::{generic::DigestItem, ConsensusEngineId, Perbill}; +use sp_runtime::traits::{IsMember, SaturatedConversion, Saturating, RandomnessBeacon}; +use sp_staking::{ + SessionIndex, + offence::{Offence, Kind}, +}; + +use codec::{Encode, Decode}; +use sp_inherents::{InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; +use sp_consensus_babe::{ + BABE_ENGINE_ID, ConsensusLog, BabeAuthorityWeight, NextEpochDescriptor, RawBabePreDigest, + SlotNumber, inherents::{INHERENT_IDENTIFIER, BabeInherentData} +}; +pub use sp_consensus_babe::{AuthorityId, VRF_OUTPUT_LENGTH, PUBLIC_KEY_LENGTH}; + +#[cfg(all(feature = "std", test))] +mod tests; + +#[cfg(all(feature = "std", test))] +mod mock; + +pub trait Trait: pallet_timestamp::Trait { + /// The amount of time, in slots, that each epoch should last. + type EpochDuration: Get; + + /// The expected average block time at which BABE should be creating + /// blocks. Since BABE is probabilistic it is not trivial to figure out + /// what the expected average block time should be based on the slot + /// duration and the security parameter `c` (where `1 - c` represents + /// the probability of a slot being empty). + type ExpectedBlockTime: Get; + + /// BABE requires some logic to be triggered on every block to query for whether an epoch + /// has ended and to perform the transition to the next epoch. + /// + /// Typically, the `ExternalTrigger` type should be used. An internal trigger should only be used + /// when no other module is responsible for changing authority set. + type EpochChangeTrigger: EpochChangeTrigger; +} + +/// Trigger an epoch change, if any should take place. +pub trait EpochChangeTrigger { + /// Trigger an epoch change, if any should take place. This should be called + /// during every block, after initialization is done. + fn trigger(now: T::BlockNumber); +} + +/// A type signifying to BABE that an external trigger +/// for epoch changes (e.g. pallet-session) is used. +pub struct ExternalTrigger; + +impl EpochChangeTrigger for ExternalTrigger { + fn trigger(_: T::BlockNumber) { } // nothing - trigger is external. +} + +/// A type signifying to BABE that it should perform epoch changes +/// with an internal trigger, recycling the same authorities forever. +pub struct SameAuthoritiesForever; + +impl EpochChangeTrigger for SameAuthoritiesForever { + fn trigger(now: T::BlockNumber) { + if >::should_epoch_change(now) { + let authorities = >::authorities(); + let next_authorities = authorities.clone(); + + >::enact_epoch_change(authorities, next_authorities); + } + } +} + +/// The length of the BABE randomness +pub const RANDOMNESS_LENGTH: usize = 32; + +const UNDER_CONSTRUCTION_SEGMENT_LENGTH: usize = 256; + +type MaybeVrf = Option<[u8; 32 /* VRF_OUTPUT_LENGTH */]>; + +decl_storage! { + trait Store for Module as Babe { + /// Current epoch index. + pub EpochIndex get(fn epoch_index): u64; + + /// Current epoch authorities. + pub Authorities get(fn authorities): Vec<(AuthorityId, BabeAuthorityWeight)>; + + /// The slot at which the first epoch actually started. This is 0 + /// until the first block of the chain. + pub GenesisSlot get(fn genesis_slot): u64; + + /// Current slot number. + pub CurrentSlot get(fn current_slot): u64; + + /// The epoch randomness for the *current* epoch. + /// + /// # Security + /// + /// This MUST NOT be used for gambling, as it can be influenced by a + /// malicious validator in the short term. It MAY be used in many + /// cryptographic protocols, however, so long as one remembers that this + /// (like everything else on-chain) it is public. For example, it can be + /// used where a number is needed that cannot have been chosen by an + /// adversary, for purposes such as public-coin zero-knowledge proofs. + // NOTE: the following fields don't use the constants to define the + // array size because the metadata API currently doesn't resolve the + // variable to its underlying value. + pub Randomness get(fn randomness): [u8; 32 /* RANDOMNESS_LENGTH */]; + + /// Next epoch randomness. + NextRandomness: [u8; 32 /* RANDOMNESS_LENGTH */]; + + /// Randomness under construction. + /// + /// We make a tradeoff between storage accesses and list length. + /// We store the under-construction randomness in segments of up to + /// `UNDER_CONSTRUCTION_SEGMENT_LENGTH`. + /// + /// Once a segment reaches this length, we begin the next one. + /// We reset all segments and return to `0` at the beginning of every + /// epoch. + SegmentIndex build(|_| 0): u32; + UnderConstruction: map u32 => Vec<[u8; 32 /* VRF_OUTPUT_LENGTH */]>; + + /// Temporary value (cleared at block finalization) which is `Some` + /// if per-block initialization has already been called for current block. + Initialized get(fn initialized): Option; + } + add_extra_genesis { + config(authorities): Vec<(AuthorityId, BabeAuthorityWeight)>; + build(|config| Module::::initialize_authorities(&config.authorities)) + } +} + +decl_module! { + /// The BABE SRML module + pub struct Module for enum Call where origin: T::Origin { + /// The number of **slots** that an epoch takes. We couple sessions to + /// epochs, i.e. we start a new session once the new epoch begins. + const EpochDuration: u64 = T::EpochDuration::get(); + + /// The expected average block time at which BABE should be creating + /// blocks. Since BABE is probabilistic it is not trivial to figure out + /// what the expected average block time should be based on the slot + /// duration and the security parameter `c` (where `1 - c` represents + /// the probability of a slot being empty). + const ExpectedBlockTime: T::Moment = T::ExpectedBlockTime::get(); + + /// Initialization + fn on_initialize(now: T::BlockNumber) { + Self::do_initialize(now); + } + + /// Block finalization + fn on_finalize() { + // at the end of the block, we can safely include the new VRF output + // from this block into the under-construction randomness. If we've determined + // that this block was the first in a new epoch, the changeover logic has + // already occurred at this point, so the under-construction randomness + // will only contain outputs from the right epoch. + if let Some(Some(vrf_output)) = Initialized::take() { + Self::deposit_vrf_output(&vrf_output); + } + } + } +} + +impl RandomnessBeacon for Module { + fn random() -> [u8; VRF_OUTPUT_LENGTH] { + Self::randomness() + } +} + +/// A BABE public key +pub type BabeKey = [u8; PUBLIC_KEY_LENGTH]; + +impl FindAuthor for Module { + fn find_author<'a, I>(digests: I) -> Option where + I: 'a + IntoIterator + { + for (id, mut data) in digests.into_iter() { + if id == BABE_ENGINE_ID { + let pre_digest = RawBabePreDigest::decode(&mut data).ok()?; + return Some(match pre_digest { + RawBabePreDigest::Primary { authority_index, .. } => + authority_index, + RawBabePreDigest::Secondary { authority_index, .. } => + authority_index, + }); + } + } + + return None; + } +} + +impl IsMember for Module { + fn is_member(authority_id: &AuthorityId) -> bool { + >::authorities() + .iter() + .any(|id| &id.0 == authority_id) + } +} + +impl pallet_session::ShouldEndSession for Module { + fn should_end_session(now: T::BlockNumber) -> bool { + // it might be (and it is in current implementation) that session module is calling + // should_end_session() from it's own on_initialize() handler + // => because pallet_session on_initialize() is called earlier than ours, let's ensure + // that we have synced with digest before checking if session should be ended. + Self::do_initialize(now); + + Self::should_epoch_change(now) + } +} + +// TODO [slashing]: @marcio use this, remove the dead_code annotation. +/// A BABE equivocation offence report. +/// +/// When a validator released two or more blocks at the same slot. +#[allow(dead_code)] +struct BabeEquivocationOffence { + /// A babe slot number in which this incident happened. + slot: u64, + /// The session index in which the incident happened. + session_index: SessionIndex, + /// The size of the validator set at the time of the offence. + validator_set_count: u32, + /// The authority that produced the equivocation. + offender: FullIdentification, +} + +impl Offence for BabeEquivocationOffence { + const ID: Kind = *b"babe:equivocatio"; + type TimeSlot = u64; + + fn offenders(&self) -> Vec { + vec![self.offender.clone()] + } + + fn session_index(&self) -> SessionIndex { + self.session_index + } + + fn validator_set_count(&self) -> u32 { + self.validator_set_count + } + + fn time_slot(&self) -> Self::TimeSlot { + self.slot + } + + fn slash_fraction( + offenders_count: u32, + validator_set_count: u32, + ) -> Perbill { + // the formula is min((3k / n)^2, 1) + let x = Perbill::from_rational_approximation(3 * offenders_count, validator_set_count); + // _ ^ 2 + x.square() + } +} + +impl Module { + /// Determine the BABE slot duration based on the Timestamp module configuration. + pub fn slot_duration() -> T::Moment { + // we double the minimum block-period so each author can always propose within + // the majority of their slot. + ::MinimumPeriod::get().saturating_mul(2.into()) + } + + /// Determine whether an epoch change should take place at this block. + /// Assumes that initialization has already taken place. + pub fn should_epoch_change(now: T::BlockNumber) -> bool { + // The epoch has technically ended during the passage of time + // between this block and the last, but we have to "end" the epoch now, + // since there is no earlier possible block we could have done it. + // + // The exception is for block 1: the genesis has slot 0, so we treat + // epoch 0 as having started at the slot of block 1. We want to use + // the same randomness and validator set as signalled in the genesis, + // so we don't rotate the epoch. + now != sp_runtime::traits::One::one() && { + let diff = CurrentSlot::get().saturating_sub(Self::current_epoch_start()); + diff >= T::EpochDuration::get() + } + } + + /// DANGEROUS: Enact an epoch change. Should be done on every block where `should_epoch_change` has returned `true`, + /// and the caller is the only caller of this function. + /// + /// Typically, this is not handled directly by the user, but by higher-level validator-set manager logic like + /// `pallet-session`. + pub fn enact_epoch_change( + authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + next_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + ) { + // PRECONDITION: caller has done initialization and is guaranteed + // by the session module to be called before this. + #[cfg(debug_assertions)] + { + assert!(Self::initialized().is_some()) + } + + // Update epoch index + let epoch_index = EpochIndex::get() + .checked_add(1) + .expect("epoch indices will never reach 2^64 before the death of the universe; qed"); + + EpochIndex::put(epoch_index); + Authorities::put(authorities); + + // Update epoch randomness. + let next_epoch_index = epoch_index + .checked_add(1) + .expect("epoch indices will never reach 2^64 before the death of the universe; qed"); + + // Returns randomness for the current epoch and computes the *next* + // epoch randomness. + let randomness = Self::randomness_change_epoch(next_epoch_index); + Randomness::put(randomness); + + // After we update the current epoch, we signal the *next* epoch change + // so that nodes can track changes. + let next_randomness = NextRandomness::get(); + + let next = NextEpochDescriptor { + authorities: next_authorities, + randomness: next_randomness, + }; + + Self::deposit_consensus(ConsensusLog::NextEpochData(next)) + } + + // finds the start slot of the current epoch. only guaranteed to + // give correct results after `do_initialize` of the first block + // in the chain (as its result is based off of `GenesisSlot`). + fn current_epoch_start() -> SlotNumber { + (EpochIndex::get() * T::EpochDuration::get()) + GenesisSlot::get() + } + + fn deposit_consensus(new: U) { + let log: DigestItem = DigestItem::Consensus(BABE_ENGINE_ID, new.encode()); + >::deposit_log(log.into()) + } + + fn deposit_vrf_output(vrf_output: &[u8; VRF_OUTPUT_LENGTH]) { + let segment_idx = ::get(); + let mut segment = ::get(&segment_idx); + if segment.len() < UNDER_CONSTRUCTION_SEGMENT_LENGTH { + // push onto current segment: not full. + segment.push(*vrf_output); + ::insert(&segment_idx, &segment); + } else { + // move onto the next segment and update the index. + let segment_idx = segment_idx + 1; + ::insert(&segment_idx, &vec![*vrf_output]); + ::put(&segment_idx); + } + } + + fn do_initialize(now: T::BlockNumber) { + // since do_initialize can be called twice (if session module is present) + // => let's ensure that we only modify the storage once per block + let initialized = Self::initialized().is_some(); + if initialized { + return; + } + + let maybe_pre_digest = >::digest() + .logs + .iter() + .filter_map(|s| s.as_pre_runtime()) + .filter_map(|(id, mut data)| if id == BABE_ENGINE_ID { + RawBabePreDigest::decode(&mut data).ok() + } else { + None + }) + .next(); + + let maybe_vrf = maybe_pre_digest.and_then(|digest| { + // on the first non-zero block (i.e. block #1) + // this is where the first epoch (epoch #0) actually starts. + // we need to adjust internal storage accordingly. + if GenesisSlot::get() == 0 { + GenesisSlot::put(digest.slot_number()); + debug_assert_ne!(GenesisSlot::get(), 0); + + // deposit a log because this is the first block in epoch #0 + // we use the same values as genesis because we haven't collected any + // randomness yet. + let next = NextEpochDescriptor { + authorities: Self::authorities(), + randomness: Self::randomness(), + }; + + Self::deposit_consensus(ConsensusLog::NextEpochData(next)) + } + + CurrentSlot::put(digest.slot_number()); + + if let RawBabePreDigest::Primary { vrf_output, .. } = digest { + // place the VRF output into the `Initialized` storage item + // and it'll be put onto the under-construction randomness + // later, once we've decided which epoch this block is in. + Some(vrf_output) + } else { + None + } + }); + + Initialized::put(maybe_vrf); + + // enact epoch change, if necessary. + T::EpochChangeTrigger::trigger::(now) + } + + /// Call this function exactly once when an epoch changes, to update the + /// randomness. Returns the new randomness. + fn randomness_change_epoch(next_epoch_index: u64) -> [u8; RANDOMNESS_LENGTH] { + let this_randomness = NextRandomness::get(); + let segment_idx: u32 = ::mutate(|s| sp_std::mem::replace(s, 0)); + + // overestimate to the segment being full. + let rho_size = segment_idx.saturating_add(1) as usize * UNDER_CONSTRUCTION_SEGMENT_LENGTH; + + let next_randomness = compute_randomness( + this_randomness, + next_epoch_index, + (0..segment_idx).flat_map(|i| ::take(&i)), + Some(rho_size), + ); + NextRandomness::put(&next_randomness); + this_randomness + } + + fn initialize_authorities(authorities: &[(AuthorityId, BabeAuthorityWeight)]) { + if !authorities.is_empty() { + assert!(Authorities::get().is_empty(), "Authorities are already initialized!"); + Authorities::put(authorities); + } + } +} + +impl OnTimestampSet for Module { + fn on_timestamp_set(_moment: T::Moment) { } +} + +impl sp_runtime::BoundToRuntimeAppPublic for Module { + type Public = AuthorityId; +} + +impl pallet_session::OneSessionHandler for Module { + type Key = AuthorityId; + + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); + Self::initialize_authorities(&authorities); + } + + fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, queued_validators: I) + where I: Iterator + { + let authorities = validators.map(|(_account, k)| { + (k, 1) + }).collect::>(); + + let next_authorities = queued_validators.map(|(_account, k)| { + (k, 1) + }).collect::>(); + + Self::enact_epoch_change(authorities, next_authorities) + } + + fn on_disabled(i: usize) { + Self::deposit_consensus(ConsensusLog::OnDisabled(i as u32)) + } +} + +// compute randomness for a new epoch. rho is the concatenation of all +// VRF outputs in the prior epoch. +// +// an optional size hint as to how many VRF outputs there were may be provided. +fn compute_randomness( + last_epoch_randomness: [u8; RANDOMNESS_LENGTH], + epoch_index: u64, + rho: impl Iterator, + rho_size_hint: Option, +) -> [u8; RANDOMNESS_LENGTH] { + let mut s = Vec::with_capacity(40 + rho_size_hint.unwrap_or(0) * VRF_OUTPUT_LENGTH); + s.extend_from_slice(&last_epoch_randomness); + s.extend_from_slice(&epoch_index.to_le_bytes()); + + for vrf_output in rho { + s.extend_from_slice(&vrf_output[..]); + } + + sp_io::hashing::blake2_256(&s) +} + +impl ProvideInherent for Module { + type Call = pallet_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 { + pallet_timestamp::Call::set(ref timestamp) => timestamp.clone(), + _ => return Ok(()), + }; + + let timestamp_based_slot = (timestamp / Self::slot_duration()).saturated_into::(); + let seal_slot = data.babe_inherent_data()?; + + if timestamp_based_slot == seal_slot { + Ok(()) + } else { + Err(sp_inherents::Error::from("timestamp set in block doesn't match slot in seal").into()) + } + } +} diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs new file mode 100644 index 0000000000000..3f0c42a6cb9c6 --- /dev/null +++ b/frame/babe/src/mock.rs @@ -0,0 +1,110 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities +#![allow(dead_code, unused_imports)] + +use super::{Trait, Module, GenesisConfig}; +use sp_consensus_babe::AuthorityId; +use sp_runtime::{ + traits::IdentityLookup, Perbill, testing::{Header, UintAuthorityId}, impl_opaque_keys, +}; +use sp_version::RuntimeVersion; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use sp_io; +use sp_core::{H256, Blake2Hasher}; + +impl_outer_origin!{ + pub enum Origin for Test where system = frame_system {} +} + +type DummyValidatorId = u64; + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Test; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const MinimumPeriod: u64 = 1; + pub const EpochDuration: u64 = 3; + pub const ExpectedBlockTime: u64 = 1; + pub const Version: RuntimeVersion = substrate_test_runtime::VERSION; + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(16); +} + +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Version = Version; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = DummyValidatorId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type ModuleToIndex = (); +} + +impl_opaque_keys! { + pub struct MockSessionKeys { + pub dummy: UintAuthorityId, + } +} + +impl pallet_session::Trait for Test { + type Event = (); + type ValidatorId = ::AccountId; + type ShouldEndSession = Babe; + type SessionHandler = (Babe,Babe,); + type OnSessionEnding = (); + type ValidatorIdOf = (); + type SelectInitialValidators = (); + type Keys = MockSessionKeys; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; +} + +impl pallet_timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = Babe; + type MinimumPeriod = MinimumPeriod; +} + +impl Trait for Test { + type EpochDuration = EpochDuration; + type ExpectedBlockTime = ExpectedBlockTime; + type EpochChangeTrigger = crate::ExternalTrigger; +} + +pub fn new_test_ext(authorities: Vec) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig { + authorities: authorities.into_iter().map(|a| (UintAuthorityId(a).to_public_key(), 1)).collect(), + }.assimilate_storage::(&mut t).unwrap(); + t.into() +} + +pub type System = frame_system::Module; +pub type Babe = Module; diff --git a/frame/babe/src/tests.rs b/frame/babe/src/tests.rs new file mode 100644 index 0000000000000..dbd61238166b0 --- /dev/null +++ b/frame/babe/src/tests.rs @@ -0,0 +1,132 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Consensus extension module tests for BABE consensus. + +use super::*; +use mock::{new_test_ext, Babe, Test}; +use sp_runtime::{traits::OnFinalize, testing::{Digest, DigestItem}}; +use pallet_session::ShouldEndSession; + +const EMPTY_RANDOMNESS: [u8; 32] = [ + 74, 25, 49, 128, 53, 97, 244, 49, + 222, 202, 176, 2, 231, 66, 95, 10, + 133, 49, 213, 228, 86, 161, 164, 127, + 217, 153, 138, 37, 48, 192, 248, 0, +]; + +fn make_pre_digest( + authority_index: sp_consensus_babe::AuthorityIndex, + slot_number: sp_consensus_babe::SlotNumber, + vrf_output: [u8; sp_consensus_babe::VRF_OUTPUT_LENGTH], + vrf_proof: [u8; sp_consensus_babe::VRF_PROOF_LENGTH], +) -> Digest { + let digest_data = sp_consensus_babe::RawBabePreDigest::Primary { + authority_index, + slot_number, + vrf_output, + vrf_proof, + }; + let log = DigestItem::PreRuntime(sp_consensus_babe::BABE_ENGINE_ID, digest_data.encode()); + Digest { logs: vec![log] } +} + +#[test] +fn empty_randomness_is_correct() { + let s = compute_randomness([0; RANDOMNESS_LENGTH], 0, std::iter::empty(), None); + assert_eq!(s, EMPTY_RANDOMNESS); +} + +#[test] +fn initial_values() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + assert_eq!(Babe::authorities().len(), 4) + }) +} + +#[test] +fn check_module() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + assert!(!Babe::should_end_session(0), "Genesis does not change sessions"); + assert!(!Babe::should_end_session(200000), + "BABE does not include the block number in epoch calculations"); + }) +} + +type System = frame_system::Module; + +#[test] +fn first_block_epoch_zero_start() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + let genesis_slot = 100; + let first_vrf = [1; 32]; + let pre_digest = make_pre_digest( + 0, + genesis_slot, + first_vrf, + [0xff; 64], + ); + + assert_eq!(Babe::genesis_slot(), 0); + System::initialize( + &1, + &Default::default(), + &Default::default(), + &pre_digest, + Default::default(), + ); + + // see implementation of the function for details why: we issue an + // epoch-change digest but don't do it via the normal session mechanism. + assert!(!Babe::should_end_session(1)); + assert_eq!(Babe::genesis_slot(), genesis_slot); + assert_eq!(Babe::current_slot(), genesis_slot); + assert_eq!(Babe::epoch_index(), 0); + + Babe::on_finalize(1); + let header = System::finalize(); + + assert_eq!(SegmentIndex::get(), 0); + assert_eq!(UnderConstruction::get(0), vec![first_vrf]); + assert_eq!(Babe::randomness(), [0; 32]); + assert_eq!(NextRandomness::get(), [0; 32]); + + assert_eq!(header.digest.logs.len(), 2); + assert_eq!(pre_digest.logs.len(), 1); + assert_eq!(header.digest.logs[0], pre_digest.logs[0]); + + let authorities = Babe::authorities(); + let consensus_log = sp_consensus_babe::ConsensusLog::NextEpochData( + sp_consensus_babe::NextEpochDescriptor { + authorities, + randomness: Babe::randomness(), + } + ); + let consensus_digest = DigestItem::Consensus(BABE_ENGINE_ID, consensus_log.encode()); + + // first epoch descriptor has same info as last. + assert_eq!(header.digest.logs[1], consensus_digest.clone()) + }) +} + +#[test] +fn authority_index() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + assert_eq!( + Babe::find_author((&[(BABE_ENGINE_ID, &[][..])]).into_iter().cloned()), None, + "Trivially invalid authorities are ignored") + }) +} diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml new file mode 100644 index 0000000000000..e5a3c4f2d7602 --- /dev/null +++ b/frame/balances/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "pallet-balances" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-io = { version = "2.0.0", path = "../../primitives/io" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-transaction-payment = { version = "2.0.0", path = "../transaction-payment" } + +[features] +default = ["std"] +std = [ + "serde", + "safe-mix/std", + "codec/std", + "sp-std/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", +] diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs new file mode 100644 index 0000000000000..1f8e099880b7d --- /dev/null +++ b/frame/balances/src/lib.rs @@ -0,0 +1,1309 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Balances Module +//! +//! The Balances module provides functionality for handling accounts and balances. +//! +//! - [`balances::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Overview +//! +//! The Balances module provides functions for: +//! +//! - Getting and setting free balances. +//! - Retrieving total, reserved and unreserved balances. +//! - Repatriating a reserved balance to a beneficiary account that exists. +//! - Transferring a balance between accounts (when not reserved). +//! - Slashing an account balance. +//! - Account creation and removal. +//! - Managing total issuance. +//! - Setting and managing locks. +//! +//! ### Terminology +//! +//! - **Existential Deposit:** The minimum balance required to create or keep an account open. This prevents +//! "dust accounts" from filling storage. +//! - **Total Issuance:** The total number of units in existence in a system. +//! - **Reaping an account:** The act of removing an account by resetting its nonce. Happens after its balance is set +//! to zero. +//! - **Free Balance:** The portion of a balance that is not reserved. The free balance is the only +//! balance that matters for most operations. When this balance falls below the existential +//! deposit, most functionality of the account is removed. When both it and the reserved balance +//! are deleted, then the account is said to be dead. +//! +//! No account should ever have a free balance that is strictly between 0 and the existential +//! deposit (exclusive). If this ever happens, it indicates either a bug in this module or an +//! erroneous raw mutation of storage. +//! +//! - **Reserved Balance:** Reserved balance still belongs to the account holder, but is suspended. +//! Reserved balance can still be slashed, but only after all the free balance has been slashed. +//! If the reserved balance falls below the existential deposit, it and any related functionality +//! will be deleted. When both it and the free balance are deleted, then the account is said to +//! be dead. +//! +//! No account should ever have a reserved balance that is strictly between 0 and the existential +//! deposit (exclusive). If this ever happens, it indicates either a bug in this module or an +//! erroneous raw mutation of storage. +//! +//! - **Imbalance:** A condition when some funds were credited or debited without equal and opposite accounting +//! (i.e. a difference between total issuance and account balances). Functions that result in an imbalance will +//! return an object of the `Imbalance` trait that can be managed within your runtime logic. (If an imbalance is +//! simply dropped, it should automatically maintain any book-keeping such as total issuance.) +//! - **Lock:** A freeze on a specified amount of an account's free balance until a specified block number. Multiple +//! locks always operate over the same funds, so they "overlay" rather than "stack". +//! - **Vesting:** Similar to a lock, this is another, but independent, liquidity restriction that reduces linearly +//! over time. +//! +//! ### Implementations +//! +//! The Balances module provides implementations for the following traits. If these traits provide the functionality +//! that you need, then you can avoid coupling with the Balances module. +//! +//! - [`Currency`](../frame_support/traits/trait.Currency.html): Functions for dealing with a +//! fungible assets system. +//! - [`ReservableCurrency`](../frame_support/traits/trait.ReservableCurrency.html): +//! Functions for dealing with assets that can be reserved from an account. +//! - [`LockableCurrency`](../frame_support/traits/trait.LockableCurrency.html): Functions for +//! dealing with accounts that allow liquidity restrictions. +//! - [`Imbalance`](../frame_support/traits/trait.Imbalance.html): Functions for handling +//! imbalances between total issuance in the system and account balances. Must be used when a function +//! creates new funds (e.g. a reward) or destroys some funds (e.g. a system fee). +//! - [`IsDeadAccount`](../frame_system/trait.IsDeadAccount.html): Determiner to say whether a +//! given account is unused. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! - `transfer` - Transfer some liquid free balance to another account. +//! - `set_balance` - Set the balances of a given account. The origin of this call must be root. +//! +//! ### Public Functions +//! +//! - `vesting_balance` - Get the amount that is currently being vested and cannot be transferred out of this account. +//! +//! ## Usage +//! +//! The following examples show how to use the Balances module in your custom module. +//! +//! ### Examples from the SRML +//! +//! The Contract module uses the `Currency` trait to handle gas payment, and its types inherit from `Currency`: +//! +//! ``` +//! use frame_support::traits::Currency; +//! # pub trait Trait: frame_system::Trait { +//! # type Currency: Currency; +//! # } +//! +//! pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +//! pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; +//! +//! # fn main() {} +//! ``` +//! +//! The Staking module uses the `LockableCurrency` trait to lock a stash account's funds: +//! +//! ``` +//! use frame_support::traits::{WithdrawReasons, LockableCurrency}; +//! use sp_runtime::traits::Bounded; +//! pub trait Trait: frame_system::Trait { +//! type Currency: LockableCurrency; +//! } +//! # struct StakingLedger { +//! # stash: ::AccountId, +//! # total: <::Currency as frame_support::traits::Currency<::AccountId>>::Balance, +//! # phantom: std::marker::PhantomData, +//! # } +//! # const STAKING_ID: [u8; 8] = *b"staking "; +//! +//! fn update_ledger( +//! controller: &T::AccountId, +//! ledger: &StakingLedger +//! ) { +//! T::Currency::set_lock( +//! STAKING_ID, +//! &ledger.stash, +//! ledger.total, +//! T::BlockNumber::max_value(), +//! WithdrawReasons::all() +//! ); +//! // >::insert(controller, ledger); // Commented out as we don't have access to Staking's storage here. +//! } +//! # fn main() {} +//! ``` +//! +//! ## Genesis config +//! +//! The Balances module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). +//! +//! ## Assumptions +//! +//! * Total issued balanced of all accounts should be less than `Trait::Balance::max_value()`. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use sp_std::{cmp, result, mem, fmt::Debug}; +use codec::{Codec, Encode, Decode}; +use frame_support::{ + StorageValue, Parameter, decl_event, decl_storage, decl_module, decl_error, + traits::{ + UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnReapAccount, OnUnbalanced, TryDrop, + WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, + Imbalance, SignedImbalance, ReservableCurrency, Get, VestingCurrency, + }, + weights::SimpleDispatchInfo, +}; +use sp_runtime::{ + RuntimeDebug, DispatchResult, DispatchError, + traits::{ + Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDeserialize, + Saturating, Bounded, + }, +}; +use frame_system::{self as system, IsDeadAccount, OnNewAccount, ensure_signed, ensure_root}; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +pub use self::imbalances::{PositiveImbalance, NegativeImbalance}; + +pub trait Subtrait: frame_system::Trait { + /// The balance of an account. + type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + + MaybeSerializeDeserialize + Debug + From; + + /// A function that 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 is invoked when the free-balance and the reserved-balance has fallen below + /// the existential deposit and both have been reduced to zero. + /// + /// All resources should be cleaned up all resources associated with the given account. + type OnReapAccount: OnReapAccount; + + /// Handler for when a new account is created. + type OnNewAccount: OnNewAccount; + + /// The minimum amount required to keep an account open. + type ExistentialDeposit: Get; + + /// The fee required to make a transfer. + type TransferFee: Get; + + /// The fee required to create an account. + type CreationFee: Get; +} + +pub trait Trait: frame_system::Trait { + /// The balance of an account. + type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + + MaybeSerializeDeserialize + Debug + From; + + /// A function that 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 is invoked when the free-balance and the reserved-balance has fallen below + /// the existential deposit and both have been reduced to zero. + /// + /// All resources should be cleaned up all resources associated with the given account. + type OnReapAccount: OnReapAccount; + + /// Handler for when a new account is created. + type OnNewAccount: OnNewAccount; + + /// Handler for the unbalanced reduction when taking fees associated with balance + /// transfer (which may also include account creation). + type TransferPayment: OnUnbalanced>; + + /// Handler for the unbalanced reduction when removing a dust account. + type DustRemoval: OnUnbalanced>; + + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The minimum amount required to keep an account open. + type ExistentialDeposit: Get; + + /// The fee required to make a transfer. + type TransferFee: Get; + + /// The fee required to create an account. + type CreationFee: Get; +} + +impl, I: Instance> Subtrait for T { + type Balance = T::Balance; + type OnFreeBalanceZero = T::OnFreeBalanceZero; + type OnReapAccount = T::OnReapAccount; + type OnNewAccount = T::OnNewAccount; + type ExistentialDeposit = T::ExistentialDeposit; + type TransferFee = T::TransferFee; + type CreationFee = T::CreationFee; +} + +decl_event!( + pub enum Event where + ::AccountId, + >::Balance + { + /// A new account was created. + NewAccount(AccountId, Balance), + /// An account was reaped. + ReapedAccount(AccountId, Balance), + /// Transfer succeeded (from, to, value, fees). + Transfer(AccountId, AccountId, Balance, Balance), + /// A balance was set by root (who, free, reserved). + BalanceSet(AccountId, Balance, Balance), + /// Some amount was deposited (e.g. for transaction fees). + Deposit(AccountId, Balance), + } +); + +decl_error! { + pub enum Error for Module, I: Instance> { + /// Vesting balance too high to send value + VestingBalance, + /// Account liquidity restrictions prevent withdrawal + LiquidityRestrictions, + /// Got an overflow after adding + Overflow, + /// Balance too low to send value + InsufficientBalance, + /// Value too low to create account due to existential deposit + ExistentialDeposit, + /// Transfer/payment would kill account + KeepAlive, + /// A vesting schedule already exists for this account + ExistingVestingSchedule, + /// Beneficiary account must pre-exist + DeadAccount, + } +} + +/// Struct to encode the vesting schedule of an individual account. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct VestingSchedule { + /// Locked amount at genesis. + pub locked: Balance, + /// Amount that gets unlocked every block after `starting_block`. + pub per_block: Balance, + /// Starting block for unlocking(vesting). + pub starting_block: BlockNumber, +} + +impl VestingSchedule { + /// Amount locked at block `n`. + pub fn locked_at(&self, n: BlockNumber) -> Balance + where Balance: From + { + // Number of blocks that count toward vesting + // Saturating to 0 when n < starting_block + let vested_block_count = n.saturating_sub(self.starting_block); + // Return amount that is still locked in vesting + if let Some(x) = Balance::from(vested_block_count).checked_mul(&self.per_block) { + self.locked.max(x) - x + } else { + Zero::zero() + } + } +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct BalanceLock { + pub id: LockIdentifier, + pub amount: Balance, + pub until: BlockNumber, + pub reasons: WithdrawReasons, +} + +decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as Balances { + /// The total units issued in the system. + pub TotalIssuance get(fn total_issuance) build(|config: &GenesisConfig| { + config.balances.iter().fold(Zero::zero(), |acc: T::Balance, &(_, n)| acc + n) + }): T::Balance; + + /// Information regarding the vesting of a given account. + pub Vesting get(fn vesting) build(|config: &GenesisConfig| { + // Generate initial vesting configuration + // * who - Account which we are generating vesting configuration for + // * begin - Block when the account will start to vest + // * length - Number of blocks from `begin` until fully vested + // * liquid - Number of units which can be spent before vesting begins + config.vesting.iter().filter_map(|&(ref who, begin, length, liquid)| { + let length = >::from(length); + + config.balances.iter() + .find(|&&(ref w, _)| w == who) + .map(|&(_, balance)| { + // Total genesis `balance` minus `liquid` equals funds locked for vesting + let locked = balance.saturating_sub(liquid); + // Number of units unlocked per block after `begin` + let per_block = locked / length.max(sp_runtime::traits::One::one()); + + (who.clone(), VestingSchedule { + locked: locked, + per_block: per_block, + starting_block: begin + }) + }) + }).collect::>() + }): map T::AccountId => Option>; + + /// The 'free' balance of a given account. + /// + /// This is the only balance that matters in terms of most operations on tokens. It + /// alone is 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`. Further, the `OnFreeBalanceZero` callback + /// is invoked, giving a chance to external modules to clean up data associated with + /// the deleted account. + /// + /// `frame_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(fn 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. + /// + /// 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. + /// + /// When this balance falls below the value of `ExistentialDeposit`, then this 'reserve account' + /// is deleted: specifically, `ReservedBalance`. + /// + /// `frame_system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets + /// collapsed to zero if it ever becomes less than `ExistentialDeposit`.) + pub ReservedBalance get(fn reserved_balance): map T::AccountId => T::Balance; + + /// Any liquidity locks on some account balances. + pub Locks get(fn locks): map T::AccountId => Vec>; + } + add_extra_genesis { + config(balances): Vec<(T::AccountId, T::Balance)>; + config(vesting): Vec<(T::AccountId, T::BlockNumber, T::BlockNumber, T::Balance)>; + // ^^ begin, length, amount liquid at genesis + build(|config: &GenesisConfig| { + for (_, balance) in &config.balances { + assert!( + *balance >= >::ExistentialDeposit::get(), + "the balance of any account should always be more than existential deposit.", + ) + } + }); + } +} + +decl_module! { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + type Error = Error; + + /// The minimum amount required to keep an account open. + const ExistentialDeposit: T::Balance = T::ExistentialDeposit::get(); + + /// The fee required to make a transfer. + const TransferFee: T::Balance = T::TransferFee::get(); + + /// The fee required to create an account. + const CreationFee: T::Balance = T::CreationFee::get(); + + fn deposit_event() = default; + + /// Transfer some liquid free balance to another account. + /// + /// `transfer` will set the `FreeBalance` of the sender and receiver. + /// It will decrease the total issuance of the system by the `TransferFee`. + /// If the sender's account is below the existential deposit as a result + /// of the transfer, the account will be reaped. + /// + /// The dispatch origin for this call must be `Signed` by the transactor. + /// + /// # + /// - Dependent on arguments but not critical, given proper implementations for + /// input config types. See related functions below. + /// - It contains a limited number of reads and writes internally and no complex computation. + /// + /// Related functions: + /// + /// - `ensure_can_withdraw` is always called internally but has a bounded complexity. + /// - Transferring balances to accounts that did not exist before will cause + /// `T::OnNewAccount::on_new_account` to be called. + /// - Removing enough funds from an account will trigger + /// `T::DustRemoval::on_unbalanced` and `T::OnFreeBalanceZero::on_free_balance_zero`. + /// - `transfer_keep_alive` works the same way as `transfer`, but has an additional + /// check that the transfer will not kill the origin account. + /// + /// # + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + pub fn transfer( + origin, + dest: ::Source, + #[compact] value: T::Balance + ) { + let transactor = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + >::transfer(&transactor, &dest, value, ExistenceRequirement::AllowDeath)?; + } + + /// Set the balances of a given account. + /// + /// This will alter `FreeBalance` and `ReservedBalance` in storage. it will + /// also decrease the total issuance of the system (`TotalIssuance`). + /// If the new free or reserved balance is below the existential deposit, + /// it will reset the account nonce (`frame_system::AccountNonce`). + /// + /// The dispatch origin for this call is `root`. + /// + /// # + /// - Independent of the arguments. + /// - Contains a limited number of reads and writes. + /// # + #[weight = SimpleDispatchInfo::FixedOperational(50_000)] + fn set_balance( + origin, + who: ::Source, + #[compact] new_free: T::Balance, + #[compact] new_reserved: T::Balance + ) { + ensure_root(origin)?; + let who = T::Lookup::lookup(who)?; + let existential_deposit = T::ExistentialDeposit::get(); + + let new_free = if new_free < existential_deposit { Zero::zero() } else { new_free }; + let new_reserved = if new_reserved < existential_deposit { Zero::zero() } else { new_reserved }; + + let current_free = >::get(&who); + if new_free > current_free { + mem::drop(PositiveImbalance::::new(new_free - current_free)); + } else if new_free < current_free { + mem::drop(NegativeImbalance::::new(current_free - new_free)); + } + Self::set_free_balance(&who, new_free); + + let current_reserved = >::get(&who); + if new_reserved > current_reserved { + mem::drop(PositiveImbalance::::new(new_reserved - current_reserved)); + } else if new_reserved < current_reserved { + mem::drop(NegativeImbalance::::new(current_reserved - new_reserved)); + } + Self::set_reserved_balance(&who, new_reserved); + + Self::deposit_event(RawEvent::BalanceSet(who, new_free, new_reserved)); + } + + /// Exactly as `transfer`, except the origin must be root and the source account may be + /// specified. + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + pub fn force_transfer( + origin, + source: ::Source, + dest: ::Source, + #[compact] value: T::Balance + ) { + ensure_root(origin)?; + let source = T::Lookup::lookup(source)?; + let dest = T::Lookup::lookup(dest)?; + >::transfer(&source, &dest, value, ExistenceRequirement::AllowDeath)?; + } + + /// Same as the [`transfer`] call, but with a check that the transfer will not kill the + /// origin account. + /// + /// 99% of the time you want [`transfer`] instead. + /// + /// [`transfer`]: struct.Module.html#method.transfer + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + pub fn transfer_keep_alive( + origin, + dest: ::Source, + #[compact] value: T::Balance + ) { + let transactor = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + >::transfer(&transactor, &dest, value, ExistenceRequirement::KeepAlive)?; + } + + } +} + +impl, I: Instance> Module { + // PRIVATE MUTABLES + + /// Set the reserved balance of an account to some new value. Will enforce `ExistentialDeposit` + /// law, annulling the account as needed. + /// + /// Doesn't do any preparatory work for creating a new account, so should only be used when it + /// is known that the account already exists. + /// + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { + if balance < T::ExistentialDeposit::get() { + >::insert(who, balance); + Self::on_reserved_too_low(who); + UpdateBalanceOutcome::AccountKilled + } else { + >::insert(who, balance); + UpdateBalanceOutcome::Updated + } + } + + /// Set the free balance of an account to some new value. Will enforce `ExistentialDeposit` + /// law, annulling the account as needed. + /// + /// Doesn't do any preparatory work for creating a new account, so should only be used when it + /// is known that the account already exists. + /// + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { + // Commented out for now - but consider it instructive. + // assert!(!Self::total_balance(who).is_zero()); + // assert!(Self::free_balance(who) > T::ExistentialDeposit::get()); + if balance < T::ExistentialDeposit::get() { + >::insert(who, balance); + Self::on_free_too_low(who); + UpdateBalanceOutcome::AccountKilled + } else { + >::insert(who, balance); + UpdateBalanceOutcome::Updated + } + } + + /// Register a new account (with existential balance). + /// + /// This just calls appropriate hooks. It doesn't (necessarily) make any state changes. + fn new_account(who: &T::AccountId, balance: T::Balance) { + T::OnNewAccount::on_new_account(&who); + Self::deposit_event(RawEvent::NewAccount(who.clone(), balance.clone())); + } + + /// Unregister an account. + /// + /// This just removes the nonce and leaves an event. + fn reap_account(who: &T::AccountId, dust: T::Balance) { + T::OnReapAccount::on_reap_account(who); + Self::deposit_event(RawEvent::ReapedAccount(who.clone(), dust)); + } + + /// Account's free balance has dropped below existential deposit. Kill its + /// free side and the account completely if its reserved size is already dead. + /// + /// Will maintain total issuance. + fn on_free_too_low(who: &T::AccountId) { + let dust = >::take(who); + >::remove(who); + + T::OnFreeBalanceZero::on_free_balance_zero(who); + + let mut reserved_balance = Self::reserved_balance(who); + + if !dust.is_zero() { + if reserved_balance >= T::ExistentialDeposit::get() { + // any individual account cannot cause overflow in balance. + reserved_balance += dust; + Self::set_reserved_balance(who, reserved_balance); + } else { + // underflow should never happen, but if it does, there's not much we can do. + T::DustRemoval::on_unbalanced(NegativeImbalance::new(dust)); + } + } + + if reserved_balance.is_zero() { + Self::reap_account(who, dust); + } + } + + /// Account's reserved balance has dropped below existential deposit. Kill its + /// reserved side and the account completely if its free size is already dead. + /// + /// Will maintain total issuance. + fn on_reserved_too_low(who: &T::AccountId) { + let dust = >::take(who); + + let mut free_balance = Self::free_balance(who); + + if !dust.is_zero() { + if free_balance >= T::ExistentialDeposit::get() { + // any individual account cannot cause overflow in balance. + free_balance += dust; + Self::set_free_balance(who, free_balance); + } else { + // underflow should never happen, but it if does, there's nothing to be done here. + T::DustRemoval::on_unbalanced(NegativeImbalance::new(dust)); + } + } + + if free_balance.is_zero() { + Self::reap_account(who, dust); + } + } +} + +// wrapping these imbalances in a private module is necessary to ensure absolute privacy +// of the inner member. +mod imbalances { + use super::{ + result, Subtrait, DefaultInstance, Imbalance, Trait, Zero, Instance, Saturating, + StorageValue, TryDrop, + }; + use sp_std::mem; + + /// Opaque, move-only struct with private fields that serves as a token denoting that + /// funds have been created without any equal and opposite accounting. + #[must_use] + pub struct PositiveImbalance, I: Instance=DefaultInstance>(T::Balance); + + impl, I: Instance> PositiveImbalance { + /// Create a new positive imbalance from a balance. + pub fn new(amount: T::Balance) -> Self { + PositiveImbalance(amount) + } + } + + /// Opaque, move-only struct with private fields that serves as a token denoting that + /// funds have been destroyed without any equal and opposite accounting. + #[must_use] + pub struct NegativeImbalance, I: Instance=DefaultInstance>(T::Balance); + + impl, I: Instance> NegativeImbalance { + /// Create a new negative imbalance from a balance. + pub fn new(amount: T::Balance) -> Self { + NegativeImbalance(amount) + } + } + + impl, I: Instance> TryDrop for PositiveImbalance { + fn try_drop(self) -> result::Result<(), Self> { + self.drop_zero() + } + } + + impl, I: Instance> Imbalance for PositiveImbalance { + type Opposite = NegativeImbalance; + + fn zero() -> Self { + Self(Zero::zero()) + } + fn drop_zero(self) -> result::Result<(), Self> { + if self.0.is_zero() { + Ok(()) + } else { + Err(self) + } + } + fn split(self, amount: T::Balance) -> (Self, Self) { + let first = self.0.min(amount); + let second = self.0 - first; + + mem::forget(self); + (Self(first), Self(second)) + } + fn merge(mut self, other: Self) -> Self { + self.0 = self.0.saturating_add(other.0); + mem::forget(other); + + self + } + fn subsume(&mut self, other: Self) { + self.0 = self.0.saturating_add(other.0); + mem::forget(other); + } + fn offset(self, other: Self::Opposite) -> result::Result { + let (a, b) = (self.0, other.0); + mem::forget((self, other)); + + if a >= b { + Ok(Self(a - b)) + } else { + Err(NegativeImbalance::new(b - a)) + } + } + fn peek(&self) -> T::Balance { + self.0.clone() + } + } + + impl, I: Instance> TryDrop for NegativeImbalance { + fn try_drop(self) -> result::Result<(), Self> { + self.drop_zero() + } + } + + impl, I: Instance> Imbalance for NegativeImbalance { + type Opposite = PositiveImbalance; + + fn zero() -> Self { + Self(Zero::zero()) + } + fn drop_zero(self) -> result::Result<(), Self> { + if self.0.is_zero() { + Ok(()) + } else { + Err(self) + } + } + fn split(self, amount: T::Balance) -> (Self, Self) { + let first = self.0.min(amount); + let second = self.0 - first; + + mem::forget(self); + (Self(first), Self(second)) + } + fn merge(mut self, other: Self) -> Self { + self.0 = self.0.saturating_add(other.0); + mem::forget(other); + + self + } + fn subsume(&mut self, other: Self) { + self.0 = self.0.saturating_add(other.0); + mem::forget(other); + } + fn offset(self, other: Self::Opposite) -> result::Result { + let (a, b) = (self.0, other.0); + mem::forget((self, other)); + + if a >= b { + Ok(Self(a - b)) + } else { + Err(PositiveImbalance::new(b - a)) + } + } + fn peek(&self) -> T::Balance { + self.0.clone() + } + } + + impl, I: Instance> Drop for PositiveImbalance { + /// Basic drop handler will just square up the total issuance. + fn drop(&mut self) { + , I>>::mutate( + |v| *v = v.saturating_add(self.0) + ); + } + } + + impl, I: Instance> Drop for NegativeImbalance { + /// Basic drop handler will just square up the total issuance. + fn drop(&mut self) { + , I>>::mutate( + |v| *v = v.saturating_sub(self.0) + ); + } + } +} + +// TODO: #2052 +// Somewhat ugly hack in order to gain access to module's `increase_total_issuance_by` +// using only the Subtrait (which defines only the types that are not dependent +// on Positive/NegativeImbalance). Subtrait must be used otherwise we end up with a +// circular dependency with Trait having some types be dependent on PositiveImbalance +// and PositiveImbalance itself depending back on Trait for its Drop impl (and thus +// its type declaration). +// This works as long as `increase_total_issuance_by` doesn't use the Imbalance +// types (basically for charging fees). +// This should eventually be refactored so that the three type items that do +// depend on the Imbalance type (TransferPayment, DustRemoval) +// are placed in their own SRML module. +struct ElevatedTrait, I: Instance>(T, I); +impl, I: Instance> Clone for ElevatedTrait { + fn clone(&self) -> Self { unimplemented!() } +} +impl, I: Instance> PartialEq for ElevatedTrait { + fn eq(&self, _: &Self) -> bool { unimplemented!() } +} +impl, I: Instance> Eq for ElevatedTrait {} +impl, I: Instance> frame_system::Trait for ElevatedTrait { + type Origin = T::Origin; + type Call = T::Call; + type Index = T::Index; + type BlockNumber = T::BlockNumber; + type Hash = T::Hash; + type Hashing = T::Hashing; + type AccountId = T::AccountId; + type Lookup = T::Lookup; + type Header = T::Header; + type Event = (); + type BlockHashCount = T::BlockHashCount; + type MaximumBlockWeight = T::MaximumBlockWeight; + type MaximumBlockLength = T::MaximumBlockLength; + type AvailableBlockRatio = T::AvailableBlockRatio; + type Version = T::Version; + type ModuleToIndex = T::ModuleToIndex; +} +impl, I: Instance> Trait for ElevatedTrait { + type Balance = T::Balance; + type OnFreeBalanceZero = T::OnFreeBalanceZero; + type OnReapAccount = T::OnReapAccount; + type OnNewAccount = T::OnNewAccount; + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = T::ExistentialDeposit; + type TransferFee = T::TransferFee; + type CreationFee = T::CreationFee; +} + +impl, I: Instance> Currency for Module +where + T::Balance: MaybeSerializeDeserialize + Debug +{ + type Balance = T::Balance; + type PositiveImbalance = PositiveImbalance; + type NegativeImbalance = NegativeImbalance; + + 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 total_issuance() -> Self::Balance { + >::get() + } + + fn minimum_balance() -> Self::Balance { + T::ExistentialDeposit::get() + } + + fn free_balance(who: &T::AccountId) -> Self::Balance { + >::get(who) + } + + fn burn(mut amount: Self::Balance) -> Self::PositiveImbalance { + >::mutate(|issued| { + *issued = issued.checked_sub(&amount).unwrap_or_else(|| { + amount = *issued; + Zero::zero() + }); + }); + PositiveImbalance::new(amount) + } + + fn issue(mut amount: Self::Balance) -> Self::NegativeImbalance { + >::mutate(|issued| + *issued = issued.checked_add(&amount).unwrap_or_else(|| { + amount = Self::Balance::max_value() - *issued; + Self::Balance::max_value() + }) + ); + NegativeImbalance::new(amount) + } + + // # + // Despite iterating over a list of locks, they are limited by the number of + // lock IDs, which means the number of runtime modules that intend to use and create locks. + // # + fn ensure_can_withdraw( + who: &T::AccountId, + _amount: T::Balance, + reasons: WithdrawReasons, + new_balance: T::Balance, + ) -> DispatchResult { + if reasons.intersects(WithdrawReason::Reserve | WithdrawReason::Transfer) + && Self::vesting_balance(who) > new_balance + { + Err(Error::::VestingBalance)? + } + let locks = Self::locks(who); + if locks.is_empty() { + return Ok(()) + } + + let now = >::block_number(); + if locks.into_iter() + .all(|l| + now >= l.until + || new_balance >= l.amount + || !l.reasons.intersects(reasons) + ) + { + Ok(()) + } else { + Err(Error::::LiquidityRestrictions.into()) + } + } + + fn transfer( + transactor: &T::AccountId, + dest: &T::AccountId, + value: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> DispatchResult { + 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 { T::CreationFee::get() } else { T::TransferFee::get() }; + let liability = value.checked_add(&fee).ok_or(Error::::Overflow)?; + let new_from_balance = from_balance.checked_sub(&liability).ok_or(Error::::InsufficientBalance)?; + + if would_create && value < T::ExistentialDeposit::get() { + Err(Error::::ExistentialDeposit)? + } + Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer.into(), new_from_balance)?; + + // NOTE: total stake being stored in the same type means that this could never overflow + // but better to be safe than sorry. + let new_to_balance = to_balance.checked_add(&value).ok_or(Error::::Overflow)?; + + if transactor != dest { + if existence_requirement == ExistenceRequirement::KeepAlive { + if new_from_balance < Self::minimum_balance() { + Err(Error::::KeepAlive)? + } + } + + Self::set_free_balance(transactor, new_from_balance); + if !>::exists(dest) { + Self::new_account(dest, new_to_balance); + } + + // Emit transfer event. + Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); + + // Take action on the set_free_balance call. + // This will emit events that _resulted_ from the transfer. + Self::set_free_balance(dest, new_to_balance); + T::TransferPayment::on_unbalanced(NegativeImbalance::new(fee)); + } + + Ok(()) + } + + fn withdraw( + who: &T::AccountId, + value: Self::Balance, + reasons: WithdrawReasons, + liveness: ExistenceRequirement, + ) -> result::Result { + let old_balance = Self::free_balance(who); + if let Some(new_balance) = old_balance.checked_sub(&value) { + // if we need to keep the account alive... + if liveness == ExistenceRequirement::KeepAlive + // ...and it would be dead afterwards... + && new_balance < T::ExistentialDeposit::get() + // ...yet is was alive before + && old_balance >= T::ExistentialDeposit::get() + { + Err(Error::::KeepAlive)? + } + Self::ensure_can_withdraw(who, value, reasons, new_balance)?; + Self::set_free_balance(who, new_balance); + Ok(NegativeImbalance::new(value)) + } else { + Err(Error::::InsufficientBalance)? + } + } + + fn slash( + who: &T::AccountId, + value: Self::Balance + ) -> (Self::NegativeImbalance, Self::Balance) { + let free_balance = Self::free_balance(who); + let free_slash = cmp::min(free_balance, value); + + Self::set_free_balance(who, free_balance - free_slash); + let remaining_slash = value - free_slash; + // NOTE: `slash()` prefers free balance, but assumes that reserve balance can be drawn + // from in extreme circumstances. `can_slash()` should be used prior to `slash()` to avoid having + // to draw from reserved funds, however we err on the side of punishment if things are inconsistent + // or `can_slash` wasn't used appropriately. + if !remaining_slash.is_zero() { + let reserved_balance = Self::reserved_balance(who); + let reserved_slash = cmp::min(reserved_balance, remaining_slash); + Self::set_reserved_balance(who, reserved_balance - reserved_slash); + (NegativeImbalance::new(free_slash + reserved_slash), remaining_slash - reserved_slash) + } else { + (NegativeImbalance::new(value), Zero::zero()) + } + } + + fn deposit_into_existing( + who: &T::AccountId, + value: Self::Balance + ) -> result::Result { + if Self::total_balance(who).is_zero() { + Err(Error::::DeadAccount)? + } + Self::set_free_balance(who, Self::free_balance(who) + value); + Ok(PositiveImbalance::new(value)) + } + + fn deposit_creating( + who: &T::AccountId, + value: Self::Balance, + ) -> Self::PositiveImbalance { + let (imbalance, _) = Self::make_free_balance_be(who, Self::free_balance(who) + value); + if let SignedImbalance::Positive(p) = imbalance { + p + } else { + // Impossible, but be defensive. + Self::PositiveImbalance::zero() + } + } + + fn make_free_balance_be(who: &T::AccountId, balance: Self::Balance) -> ( + SignedImbalance, + UpdateBalanceOutcome + ) { + let original = Self::free_balance(who); + if balance < T::ExistentialDeposit::get() && original.is_zero() { + // If we're attempting to set an existing account to less than ED, then + // bypass the entire operation. It's a no-op if you follow it through, but + // since this is an instance where we might account for a negative imbalance + // (in the dust cleaner of set_free_balance) before we account for its actual + // equal and opposite cause (returned as an Imbalance), then in the + // instance that there's no other accounts on the system at all, we might + // underflow the issuance and our arithmetic will be off. + return ( + SignedImbalance::Positive(Self::PositiveImbalance::zero()), + UpdateBalanceOutcome::AccountKilled, + ) + } + let imbalance = if original <= balance { + SignedImbalance::Positive(PositiveImbalance::new(balance - original)) + } else { + SignedImbalance::Negative(NegativeImbalance::new(original - balance)) + }; + // 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 + // the term "balance" is used *here* it should be assumed to mean "free balance" + // in the rest of the module. + // Free balance can never be less than ED. If that happens, it gets reduced to zero + // and the account information relevant to this subsystem is deleted (i.e. the + // account is reaped). + let outcome = if balance < T::ExistentialDeposit::get() { + Self::set_free_balance(who, balance); + UpdateBalanceOutcome::AccountKilled + } else { + if !>::exists(who) { + Self::new_account(&who, balance); + } + Self::set_free_balance(who, balance); + UpdateBalanceOutcome::Updated + }; + (imbalance, outcome) + } +} + +impl, I: Instance> ReservableCurrency for Module +where + T::Balance: MaybeSerializeDeserialize + Debug +{ + fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { + Self::free_balance(who) + .checked_sub(&value) + .map_or(false, |new_balance| + Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve.into(), new_balance).is_ok() + ) + } + + fn reserved_balance(who: &T::AccountId) -> Self::Balance { + >::get(who) + } + + fn reserve(who: &T::AccountId, value: Self::Balance) -> result::Result<(), DispatchError> { + let b = Self::free_balance(who); + if b < value { + Err(Error::::InsufficientBalance)? + } + let new_balance = b - value; + Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve.into(), new_balance)?; + Self::set_reserved_balance(who, Self::reserved_balance(who) + value); + Self::set_free_balance(who, new_balance); + Ok(()) + } + + fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance { + let b = Self::reserved_balance(who); + let actual = cmp::min(b, value); + Self::set_free_balance(who, Self::free_balance(who) + actual); + Self::set_reserved_balance(who, b - actual); + value - actual + } + + fn slash_reserved( + who: &T::AccountId, + value: Self::Balance + ) -> (Self::NegativeImbalance, Self::Balance) { + let b = Self::reserved_balance(who); + let slash = cmp::min(b, value); + // underflow should never happen, but it if does, there's nothing to be done here. + Self::set_reserved_balance(who, b - slash); + (NegativeImbalance::new(slash), value - slash) + } + + fn repatriate_reserved( + slashed: &T::AccountId, + beneficiary: &T::AccountId, + value: Self::Balance, + ) -> result::Result { + if Self::total_balance(beneficiary).is_zero() { + Err(Error::::DeadAccount)? + } + let b = Self::reserved_balance(slashed); + let slash = cmp::min(b, value); + Self::set_free_balance(beneficiary, Self::free_balance(beneficiary) + slash); + Self::set_reserved_balance(slashed, b - slash); + Ok(value - slash) + } +} + +impl, I: Instance> LockableCurrency for Module +where + T::Balance: MaybeSerializeDeserialize + Debug +{ + type Moment = T::BlockNumber; + + 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 { + None + }).collect::>(); + if let Some(lock) = new_lock { + locks.push(lock) + } + >::insert(who, locks); + } + + 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); + } + + 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); + } +} + +impl, I: Instance> VestingCurrency for Module +where + T::Balance: MaybeSerializeDeserialize + Debug +{ + type Moment = T::BlockNumber; + + /// Get the amount that is currently being vested and cannot be transferred out of this account. + 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() + } + } + + /// Adds a vesting schedule to a given account. + /// + /// If there already exists a vesting schedule for the given account, an `Err` is returned + /// and nothing is updated. + fn add_vesting_schedule( + who: &T::AccountId, + locked: T::Balance, + per_block: T::Balance, + starting_block: T::BlockNumber + ) -> DispatchResult { + if >::exists(who) { + Err(Error::::ExistingVestingSchedule)? + } + let vesting_schedule = VestingSchedule { + locked, + per_block, + starting_block + }; + >::insert(who, vesting_schedule); + Ok(()) + } + + /// Remove a vesting schedule for a given account. + fn remove_vesting_schedule(who: &T::AccountId) { + >::remove(who); + } +} + +impl, I: Instance> IsDeadAccount for Module +where + T::Balance: MaybeSerializeDeserialize + Debug +{ + fn is_dead_account(who: &T::AccountId) -> bool { + Self::total_balance(who).is_zero() + } +} diff --git a/frame/balances/src/mock.rs b/frame/balances/src/mock.rs new file mode 100644 index 0000000000000..5a3d671e8dbc9 --- /dev/null +++ b/frame/balances/src/mock.rs @@ -0,0 +1,191 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +use sp_runtime::{Perbill, traits::{ConvertInto, IdentityLookup}, testing::Header}; +use sp_core::H256; +use sp_io; +use frame_support::{impl_outer_origin, parameter_types}; +use frame_support::traits::Get; +use frame_support::weights::{Weight, DispatchInfo}; +use std::cell::RefCell; +use crate::{GenesisConfig, Module, Trait}; + +use frame_system as system; +impl_outer_origin!{ + pub enum Origin for Test {} +} + +thread_local! { + pub(crate) static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); + static TRANSFER_FEE: RefCell = RefCell::new(0); + static CREATION_FEE: RefCell = RefCell::new(0); +} + +pub struct ExistentialDeposit; +impl Get for ExistentialDeposit { + fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } +} + +pub struct TransferFee; +impl Get for TransferFee { + fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) } +} + +pub struct CreationFee; +impl Get for CreationFee { + fn get() -> u64 { CREATION_FEE.with(|v| *v.borrow()) } +} + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} +parameter_types! { + pub const TransactionBaseFee: u64 = 0; + pub const TransactionByteFee: u64 = 1; +} +impl pallet_transaction_payment::Trait for Test { + type Currency = Module; + type OnTransactionPayment = (); + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = ConvertInto; + type FeeMultiplierUpdate = (); +} +impl Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type DustRemoval = (); + type TransferPayment = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} + +pub struct ExtBuilder { + existential_deposit: u64, + transfer_fee: u64, + creation_fee: u64, + monied: bool, + vesting: bool, +} +impl Default for ExtBuilder { + fn default() -> Self { + Self { + existential_deposit: 0, + transfer_fee: 0, + creation_fee: 0, + monied: false, + vesting: false, + } + } +} +impl ExtBuilder { + pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { + self.existential_deposit = existential_deposit; + self + } + #[allow(dead_code)] + pub fn transfer_fee(mut self, transfer_fee: u64) -> Self { + self.transfer_fee = transfer_fee; + self + } + pub fn creation_fee(mut self, creation_fee: u64) -> Self { + self.creation_fee = creation_fee; + self + } + pub fn monied(mut self, monied: bool) -> Self { + self.monied = monied; + if self.existential_deposit == 0 { + self.existential_deposit = 1; + } + self + } + pub fn vesting(mut self, vesting: bool) -> Self { + self.vesting = vesting; + self + } + pub fn set_associated_consts(&self) { + EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); + TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee); + CREATION_FEE.with(|v| *v.borrow_mut() = self.creation_fee); + } + pub fn build(self) -> sp_io::TestExternalities { + self.set_associated_consts(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig:: { + balances: if self.monied { + vec![ + (1, 10 * self.existential_deposit), + (2, 20 * self.existential_deposit), + (3, 30 * self.existential_deposit), + (4, 40 * self.existential_deposit), + (12, 10 * self.existential_deposit) + ] + } else { + vec![] + }, + vesting: if self.vesting && self.monied { + vec![ + (1, 0, 10, 5 * self.existential_deposit), + (2, 10, 20, 0), + (12, 10, 20, 5 * self.existential_deposit) + ] + } else { + vec![] + }, + }.assimilate_storage(&mut t).unwrap(); + t.into() + } +} + +pub type System = frame_system::Module; +pub type Balances = Module; + +pub const CALL: &::Call = &(); + +/// create a transaction info struct from weight. Handy to avoid building the whole struct. +pub fn info_from_weight(w: Weight) -> DispatchInfo { + DispatchInfo { weight: w, ..Default::default() } +} diff --git a/frame/balances/src/tests.rs b/frame/balances/src/tests.rs new file mode 100644 index 0000000000000..175e87aea4b4c --- /dev/null +++ b/frame/balances/src/tests.rs @@ -0,0 +1,810 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +use super::*; +use mock::{Balances, ExtBuilder, Test, System, info_from_weight, CALL}; +use sp_runtime::traits::{SignedExtension, BadOrigin}; +use frame_support::{ + assert_noop, assert_ok, assert_err, + traits::{LockableCurrency, LockIdentifier, WithdrawReason, WithdrawReasons, + Currency, ReservableCurrency, ExistenceRequirement::AllowDeath} +}; +use pallet_transaction_payment::ChargeTransactionPayment; +use frame_system::RawOrigin; + +const ID_1: LockIdentifier = *b"1 "; +const ID_2: LockIdentifier = *b"2 "; +const ID_3: LockIdentifier = *b"3 "; + +#[test] +fn basic_locking_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + assert_eq!(Balances::free_balance(&1), 10); + Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all()); + assert_noop!( + >::transfer(&1, &2, 5, AllowDeath), + Error::::LiquidityRestrictions + ); + }); +} + +#[test] +fn partial_locking_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); + }); +} + +#[test] +fn lock_removal_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); + Balances::remove_lock(ID_1, &1); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); + }); +} + +#[test] +fn lock_replacement_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); + }); +} + +#[test] +fn double_locking_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + Balances::set_lock(ID_2, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); + }); +} + +#[test] +fn combination_locking_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, u64::max_value(), 0, WithdrawReasons::none()); + Balances::set_lock(ID_2, &1, 0, u64::max_value(), WithdrawReasons::none()); + Balances::set_lock(ID_3, &1, 0, 0, WithdrawReasons::all()); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); + }); +} + +#[test] +fn lock_value_extension_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); + assert_noop!( + >::transfer(&1, &2, 6, AllowDeath), + Error::::LiquidityRestrictions + ); + Balances::extend_lock(ID_1, &1, 2, u64::max_value(), WithdrawReasons::all()); + assert_noop!( + >::transfer(&1, &2, 6, AllowDeath), + Error::::LiquidityRestrictions + ); + Balances::extend_lock(ID_1, &1, 8, u64::max_value(), WithdrawReasons::all()); + assert_noop!( + >::transfer(&1, &2, 3, AllowDeath), + Error::::LiquidityRestrictions + ); + }); +} + +#[test] +fn lock_reasons_should_work() { + ExtBuilder::default() + .existential_deposit(1) + .monied(true) + .build() + .execute_with(|| { + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into()); + assert_noop!( + >::transfer(&1, &2, 1, AllowDeath), + Error::::LiquidityRestrictions + ); + assert_ok!(>::reserve(&1, 1)); + // NOTE: this causes a fee payment. + assert!( as SignedExtension>::pre_dispatch( + ChargeTransactionPayment::from(1), + &1, + CALL, + info_from_weight(1), + 0, + ).is_ok()); + + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Reserve.into()); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); + assert_noop!( + >::reserve(&1, 1), + Error::::LiquidityRestrictions + ); + assert!( as SignedExtension>::pre_dispatch( + ChargeTransactionPayment::from(1), + &1, + CALL, + info_from_weight(1), + 0, + ).is_ok()); + + Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::TransactionPayment.into()); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); + assert_ok!(>::reserve(&1, 1)); + assert!( as SignedExtension>::pre_dispatch( + ChargeTransactionPayment::from(1), + &1, + CALL, + info_from_weight(1), + 0, + ).is_err()); + }); +} + +#[test] +fn lock_block_number_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); + assert_noop!( + >::transfer(&1, &2, 1, AllowDeath), + Error::::LiquidityRestrictions + ); + + System::set_block_number(2); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); + }); +} + +#[test] +fn lock_block_number_extension_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); + assert_noop!( + >::transfer(&1, &2, 6, AllowDeath), + Error::::LiquidityRestrictions + ); + Balances::extend_lock(ID_1, &1, 10, 1, WithdrawReasons::all()); + assert_noop!( + >::transfer(&1, &2, 6, AllowDeath), + Error::::LiquidityRestrictions + ); + System::set_block_number(2); + Balances::extend_lock(ID_1, &1, 10, 8, WithdrawReasons::all()); + assert_noop!( + >::transfer(&1, &2, 3, AllowDeath), + Error::::LiquidityRestrictions + ); + }); +} + +#[test] +fn lock_reasons_extension_should_work() { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { + Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into()); + assert_noop!( + >::transfer(&1, &2, 6, AllowDeath), + Error::::LiquidityRestrictions + ); + Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReasons::none()); + assert_noop!( + >::transfer(&1, &2, 6, AllowDeath), + Error::::LiquidityRestrictions + ); + Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReason::Reserve.into()); + assert_noop!( + >::transfer(&1, &2, 6, AllowDeath), + Error::::LiquidityRestrictions + ); + }); +} + +#[test] +fn default_indexing_on_new_accounts_should_not_work2() { + ExtBuilder::default() + .existential_deposit(10) + .creation_fee(50) + .monied(true) + .build() + .execute_with(|| { + assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist + // ext_deposit is 10, value is 9, not satisfies for ext_deposit + assert_noop!( + Balances::transfer(Some(1).into(), 5, 9), + Error::::ExistentialDeposit, + ); + assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist + assert_eq!(Balances::free_balance(&1), 100); + }); +} + +#[test] +fn reserved_balance_should_prevent_reclaim_count() { + ExtBuilder::default() + .existential_deposit(256 * 1) + .monied(true) + .build() + .execute_with(|| { + System::inc_account_nonce(&2); + assert_eq!(Balances::is_dead_account(&2), false); + assert_eq!(Balances::is_dead_account(&5), true); + 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 * 20); // reserve still exists. + assert_eq!(Balances::is_dead_account(&2), false); + assert_eq!(System::account_nonce(&2), 1); + + // account 4 tries to take index 1 for account 5. + assert_ok!(Balances::transfer(Some(4).into(), 5, 256 * 1 + 0x69)); + assert_eq!(Balances::total_balance(&5), 256 * 1 + 0x69); + assert_eq!(Balances::is_dead_account(&5), false); + + assert!(Balances::slash(&2, 256 * 19 + 2).1.is_zero()); // account 2 gets slashed + // "reserve" account reduced to 255 (below ED) so account deleted + assert_eq!(Balances::total_balance(&2), 0); + assert_eq!(System::account_nonce(&2), 0); // nonce zero + assert_eq!(Balances::is_dead_account(&2), true); + + // account 4 tries to take index 1 again for account 6. + assert_ok!(Balances::transfer(Some(4).into(), 6, 256 * 1 + 0x69)); + assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); + assert_eq!(Balances::is_dead_account(&6), false); + }); +} + + +#[test] +fn reward_should_work() { + ExtBuilder::default().monied(true).build().execute_with(|| { + assert_eq!(Balances::total_balance(&1), 10); + assert_ok!(Balances::deposit_into_existing(&1, 10).map(drop)); + assert_eq!(Balances::total_balance(&1), 20); + assert_eq!(>::get(), 120); + }); +} + +#[test] +fn dust_account_removal_should_work() { + ExtBuilder::default() + .existential_deposit(100) + .monied(true) + .build() + .execute_with(|| { + System::inc_account_nonce(&2); + assert_eq!(System::account_nonce(&2), 1); + assert_eq!(Balances::total_balance(&2), 2000); + + assert_ok!(Balances::transfer(Some(2).into(), 5, 1901)); // index 1 (account 2) becomes zombie + assert_eq!(Balances::total_balance(&2), 0); + assert_eq!(Balances::total_balance(&5), 1901); + assert_eq!(System::account_nonce(&2), 0); + }); +} + +#[test] +fn dust_account_removal_should_work2() { + ExtBuilder::default() + .existential_deposit(100) + .creation_fee(50) + .monied(true) + .build() + .execute_with(|| { + System::inc_account_nonce(&2); + assert_eq!(System::account_nonce(&2), 1); + assert_eq!(Balances::total_balance(&2), 2000); + // index 1 (account 2) becomes zombie for 256*10 + 50(fee) < 256 * 10 (ext_deposit) + assert_ok!(Balances::transfer(Some(2).into(), 5, 1851)); + assert_eq!(Balances::total_balance(&2), 0); + assert_eq!(Balances::total_balance(&5), 1851); + assert_eq!(System::account_nonce(&2), 0); + }); +} + +#[test] +fn balance_works() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 42); + assert_eq!(Balances::free_balance(&1), 42); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance(&1), 42); + assert_eq!(Balances::free_balance(&2), 0); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::total_balance(&2), 0); + }); +} + +#[test] +fn balance_transfer_works() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(Balances::transfer(Some(1).into(), 2, 69)); + assert_eq!(Balances::total_balance(&1), 42); + assert_eq!(Balances::total_balance(&2), 69); + }); +} + +#[test] +fn force_transfer_works() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_noop!( + Balances::force_transfer(Some(2).into(), 1, 2, 69), + BadOrigin, + ); + assert_ok!(Balances::force_transfer(RawOrigin::Root.into(), 1, 2, 69)); + assert_eq!(Balances::total_balance(&1), 42); + assert_eq!(Balances::total_balance(&2), 69); + }); +} + +#[test] +fn reserving_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + + assert_eq!(Balances::total_balance(&1), 111); + assert_eq!(Balances::free_balance(&1), 111); + assert_eq!(Balances::reserved_balance(&1), 0); + + assert_ok!(Balances::reserve(&1, 69)); + + assert_eq!(Balances::total_balance(&1), 111); + assert_eq!(Balances::free_balance(&1), 42); + assert_eq!(Balances::reserved_balance(&1), 69); + }); +} + +#[test] +fn balance_transfer_when_reserved_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(Balances::reserve(&1, 69)); + assert_noop!( + Balances::transfer(Some(1).into(), 2, 69), + Error::::InsufficientBalance, + ); + }); +} + +#[test] +fn deducting_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(Balances::reserve(&1, 69)); + assert_eq!(Balances::free_balance(&1), 42); + }); +} + +#[test] +fn refunding_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 42); + Balances::set_reserved_balance(&1, 69); + Balances::unreserve(&1, 69); + assert_eq!(Balances::free_balance(&1), 111); + assert_eq!(Balances::reserved_balance(&1), 0); + }); +} + +#[test] +fn slashing_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(Balances::reserve(&1, 69)); + assert!(Balances::slash(&1, 69).1.is_zero()); + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::reserved_balance(&1), 42); + assert_eq!(>::get(), 42); + }); +} + +#[test] +fn slashing_incomplete_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 42); + assert_ok!(Balances::reserve(&1, 21)); + assert_eq!(Balances::slash(&1, 69).1, 27); + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(>::get(), 0); + }); +} + +#[test] +fn unreserving_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(Balances::reserve(&1, 111)); + Balances::unreserve(&1, 42); + assert_eq!(Balances::reserved_balance(&1), 69); + assert_eq!(Balances::free_balance(&1), 42); + }); +} + +#[test] +fn slashing_reserved_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(Balances::reserve(&1, 111)); + assert_eq!(Balances::slash_reserved(&1, 42).1, 0); + assert_eq!(Balances::reserved_balance(&1), 69); + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(>::get(), 69); + }); +} + +#[test] +fn slashing_incomplete_reserved_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(Balances::reserve(&1, 42)); + assert_eq!(Balances::slash_reserved(&1, 69).1, 27); + assert_eq!(Balances::free_balance(&1), 69); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(>::get(), 69); + }); +} + +#[test] +fn transferring_reserved_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 110); + let _ = Balances::deposit_creating(&2, 1); + assert_ok!(Balances::reserve(&1, 110)); + assert_ok!(Balances::repatriate_reserved(&1, &2, 41), 0); + assert_eq!(Balances::reserved_balance(&1), 69); + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::free_balance(&2), 42); + }); +} + +#[test] +fn transferring_reserved_balance_to_nonexistent_should_fail() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_ok!(Balances::reserve(&1, 111)); + assert_noop!(Balances::repatriate_reserved(&1, &2, 42), Error::::DeadAccount); + }); +} + +#[test] +fn transferring_incomplete_reserved_balance_should_work() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 110); + let _ = Balances::deposit_creating(&2, 1); + assert_ok!(Balances::reserve(&1, 41)); + assert_ok!(Balances::repatriate_reserved(&1, &2, 69), 28); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 69); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::free_balance(&2), 42); + }); +} + +#[test] +fn transferring_too_high_value_should_not_panic() { + ExtBuilder::default().build().execute_with(|| { + >::insert(1, u64::max_value()); + >::insert(2, 1); + + assert_err!( + Balances::transfer(Some(1).into(), 2, u64::max_value()), + Error::::Overflow, + ); + + assert_eq!(Balances::free_balance(&1), u64::max_value()); + assert_eq!(Balances::free_balance(&2), 1); + }); +} + +#[test] +fn account_create_on_free_too_low_with_other() { + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 100); + assert_eq!(>::get(), 100); + + // No-op. + let _ = Balances::deposit_creating(&2, 50); + assert_eq!(Balances::free_balance(&2), 0); + assert_eq!(>::get(), 100); + }) +} + + +#[test] +fn account_create_on_free_too_low() { + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + // No-op. + let _ = Balances::deposit_creating(&2, 50); + assert_eq!(Balances::free_balance(&2), 0); + assert_eq!(>::get(), 0); + }) +} + +#[test] +fn account_removal_on_free_too_low() { + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + assert_eq!(>::get(), 0); + + // Setup two accounts with free balance above the existential threshold. + let _ = Balances::deposit_creating(&1, 110); + let _ = Balances::deposit_creating(&2, 110); + + assert_eq!(Balances::free_balance(&1), 110); + assert_eq!(Balances::free_balance(&2), 110); + assert_eq!(>::get(), 220); + + // Transfer funds from account 1 of such amount that after this transfer + // the balance of account 1 will be below the existential threshold. + // This should lead to the removal of all balance of this account. + assert_ok!(Balances::transfer(Some(1).into(), 2, 20)); + + // Verify free balance removal of account 1. + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::free_balance(&2), 130); + + // Verify that TotalIssuance tracks balance removal when free balance is too low. + assert_eq!(>::get(), 130); + }); +} + +#[test] +fn transfer_overflow_isnt_exploitable() { + ExtBuilder::default().creation_fee(50).build().execute_with(|| { + // Craft a value that will overflow if summed with `creation_fee`. + let evil_value = u64::max_value() - 49; + + assert_err!( + Balances::transfer(Some(1).into(), 5, evil_value), + Error::::Overflow, + ); + }); +} + +#[test] +fn check_vesting_status() { + ExtBuilder::default() + .existential_deposit(256) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { + assert_eq!(System::block_number(), 1); + let user1_free_balance = Balances::free_balance(&1); + let user2_free_balance = Balances::free_balance(&2); + let user12_free_balance = Balances::free_balance(&12); + assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance + assert_eq!(user2_free_balance, 256 * 20); // Account 2 has free balance + assert_eq!(user12_free_balance, 256 * 10); // Account 12 has free balance + let user1_vesting_schedule = VestingSchedule { + locked: 256 * 5, + per_block: 128, // Vesting over 10 blocks + starting_block: 0, + }; + let user2_vesting_schedule = VestingSchedule { + locked: 256 * 20, + per_block: 256, // Vesting over 20 blocks + starting_block: 10, + }; + let user12_vesting_schedule = VestingSchedule { + locked: 256 * 5, + per_block: 64, // Vesting over 20 blocks + starting_block: 10, + }; + 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(&12), Some(user12_vesting_schedule)); // Account 12 has a vesting schedule + + // Account 1 has only 128 units vested from their illiquid 256 * 5 units at block 1 + assert_eq!(Balances::vesting_balance(&1), 128 * 9); + // Account 2 has their full balance locked + assert_eq!(Balances::vesting_balance(&2), user2_free_balance); + // Account 12 has only their illiquid funds locked + assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5); + + System::set_block_number(10); + assert_eq!(System::block_number(), 10); + + // Account 1 has fully vested by block 10 + assert_eq!(Balances::vesting_balance(&1), 0); + // Account 2 has started vesting by block 10 + assert_eq!(Balances::vesting_balance(&2), user2_free_balance); + // Account 12 has started vesting by block 10 + assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5); + + 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 + assert_eq!(Balances::vesting_balance(&12), 0); // Account 2 has fully vested by block 30 + + }); +} + +#[test] +fn unvested_balance_should_not_transfer() { + ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { + assert_eq!(System::block_number(), 1); + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 100); // Account 1 has free balance + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Balances::vesting_balance(&1), 45); + assert_noop!( + Balances::transfer(Some(1).into(), 2, 56), + Error::::VestingBalance, + ); // Account 1 cannot send more than vested amount + }); +} + +#[test] +fn vested_balance_should_transfer() { + ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { + assert_eq!(System::block_number(), 1); + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 100); // Account 1 has free balance + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Balances::vesting_balance(&1), 45); + assert_ok!(Balances::transfer(Some(1).into(), 2, 55)); + }); +} + +#[test] +fn extra_balance_should_transfer() { + ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { + assert_eq!(System::block_number(), 1); + assert_ok!(Balances::transfer(Some(3).into(), 1, 100)); + assert_ok!(Balances::transfer(Some(3).into(), 2, 100)); + + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 200); // Account 1 has 100 more free balance than normal + + let user2_free_balance = Balances::free_balance(&2); + assert_eq!(user2_free_balance, 300); // Account 2 has 100 more free balance than normal + + // Account 1 has only 5 units vested at block 1 (plus 150 unvested) + assert_eq!(Balances::vesting_balance(&1), 45); + assert_ok!(Balances::transfer(Some(1).into(), 3, 155)); // Account 1 can send extra units gained + + // Account 2 has no units vested at block 1, but gained 100 + assert_eq!(Balances::vesting_balance(&2), 200); + assert_ok!(Balances::transfer(Some(2).into(), 3, 100)); // Account 2 can send extra units gained + }); +} + +#[test] +fn liquid_funds_should_transfer_with_delayed_vesting() { + ExtBuilder::default() + .existential_deposit(256) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { + assert_eq!(System::block_number(), 1); + let user12_free_balance = Balances::free_balance(&12); + + assert_eq!(user12_free_balance, 2560); // Account 12 has free balance + // Account 12 has liquid funds + assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5); + + // Account 12 has delayed vesting + let user12_vesting_schedule = VestingSchedule { + locked: 256 * 5, + per_block: 64, // Vesting over 20 blocks + starting_block: 10, + }; + assert_eq!(Balances::vesting(&12), Some(user12_vesting_schedule)); + + // Account 12 can still send liquid funds + assert_ok!(Balances::transfer(Some(12).into(), 3, 256 * 5)); + }); +} + +#[test] +fn burn_must_work() { + ExtBuilder::default().monied(true).build().execute_with(|| { + let init_total_issuance = Balances::total_issuance(); + let imbalance = Balances::burn(10); + assert_eq!(Balances::total_issuance(), init_total_issuance - 10); + drop(imbalance); + assert_eq!(Balances::total_issuance(), init_total_issuance); + }); +} + +#[test] +fn transfer_keep_alive_works() { + ExtBuilder::default().existential_deposit(1).build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 100); + assert_err!( + Balances::transfer_keep_alive(Some(1).into(), 2, 100), + Error::::KeepAlive + ); + assert_eq!(Balances::is_dead_account(&1), false); + assert_eq!(Balances::total_balance(&1), 100); + assert_eq!(Balances::total_balance(&2), 0); + }); +} + +#[test] +#[should_panic="the balance of any account should always be more than existential deposit."] +fn cannot_set_genesis_value_below_ed() { + mock::EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = 11); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let _ = GenesisConfig:: { + balances: vec![(1, 10)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); +} + +#[test] +fn dust_moves_between_free_and_reserved() { + ExtBuilder::default() + .existential_deposit(100) + .build() + .execute_with(|| { + // Set balance to free and reserved at the existential deposit + assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 100, 100)); + assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 2, 100, 100)); + // Check balance + assert_eq!(Balances::free_balance(1), 100); + assert_eq!(Balances::reserved_balance(1), 100); + assert_eq!(Balances::free_balance(2), 100); + assert_eq!(Balances::reserved_balance(2), 100); + + // Drop 1 free_balance below ED + assert_ok!(Balances::transfer(Some(1).into(), 2, 1)); + // Check balance, the other 99 should move to reserved_balance + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::reserved_balance(1), 199); + + // Reset accounts + assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 100, 100)); + assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 2, 100, 100)); + + // Drop 2 reserved_balance below ED + Balances::unreserve(&2, 1); + // Check balance, all 100 should move to free_balance + assert_eq!(Balances::free_balance(2), 200); + assert_eq!(Balances::reserved_balance(2), 0); + + // An account with both too little free and reserved is completely killed + assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 99, 99)); + // Check balance is 0 for everything + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::reserved_balance(1), 0); + }); +} diff --git a/frame/collective/Cargo.toml b/frame/collective/Cargo.toml new file mode 100644 index 0000000000000..6bf3c1b9b5c78 --- /dev/null +++ b/frame/collective/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "pallet-collective" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +hex-literal = "0.2.1" +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "safe-mix/std", + "codec/std", + "sp-core/std", + "sp-std/std", + "serde", + "sp-io/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", +] diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs new file mode 100644 index 0000000000000..0d1032cca429c --- /dev/null +++ b/frame/collective/src/lib.rs @@ -0,0 +1,778 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Collective system: Members of a set of account IDs can make their collective feelings known +//! through dispatched calls from one of two specialised origins. +//! +//! The membership can be provided in one of two ways: either directly, using the Root-dispatchable +//! function `set_members`, or indirectly, through implementing the `ChangeMembers` + +#![cfg_attr(not(feature = "std"), no_std)] +#![recursion_limit="128"] + +use sp_std::{prelude::*, result}; +use sp_core::u32_trait::Value as U32; +use sp_runtime::RuntimeDebug; +use sp_runtime::traits::{Hash, EnsureOrigin}; +use frame_support::weights::SimpleDispatchInfo; +use frame_support::{ + dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, + traits::{ChangeMembers, InitializeMembers}, decl_module, decl_event, + decl_storage, decl_error, ensure, +}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +/// Simple index type for proposal counting. +pub type ProposalIndex = u32; + +/// A number of members. +/// +/// This also serves as a number of voting members, and since for motions, each member may +/// vote exactly once, therefore also the number of votes for any given motion. +pub type MemberCount = u32; + +pub trait Trait: frame_system::Trait { + /// The outer origin type. + type Origin: From>; + + /// The outer call dispatch type. + type Proposal: Parameter + Dispatchable>::Origin>; + + /// The outer event type. + type Event: From> + Into<::Event>; +} + +/// Origin for the collective module. +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +pub enum RawOrigin { + /// It has been condoned by a given number of members of the collective from a given total. + Members(MemberCount, MemberCount), + /// It has been condoned by a single member of the collective. + Member(AccountId), + /// Dummy to manage the fact we have instancing. + _Phantom(sp_std::marker::PhantomData), +} + +/// Origin for the collective module. +pub type Origin = RawOrigin<::AccountId, I>; + +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +/// Info for keeping track of a motion being voted on. +pub struct Votes { + /// The proposal's unique index. + index: ProposalIndex, + /// The number of approval votes that are needed to pass the motion. + threshold: MemberCount, + /// The current set of voters that approved it. + ayes: Vec, + /// The current set of voters that rejected it. + nays: Vec, +} + +decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as Collective { + /// The hashes of the active proposals. + pub Proposals get(fn proposals): Vec; + /// Actual proposal for a given hash, if it's current. + pub ProposalOf get(fn proposal_of): map T::Hash => Option<>::Proposal>; + /// Votes on a given proposal, if it is ongoing. + pub Voting get(fn voting): map T::Hash => Option>; + /// Proposals so far. + pub ProposalCount get(fn proposal_count): u32; + /// The current members of the collective. This is stored sorted (just by value). + pub Members get(fn members): Vec; + } + add_extra_genesis { + config(phantom): sp_std::marker::PhantomData; + config(members): Vec; + build(|config| Module::::initialize_members(&config.members)) + } +} + +decl_event! { + pub enum Event where + ::Hash, + ::AccountId, + { + /// A motion (given hash) has been proposed (by given account) with a threshold (given + /// `MemberCount`). + Proposed(AccountId, ProposalIndex, Hash, MemberCount), + /// A motion (given hash) has been voted on by given account, leaving + /// a tally (yes votes and no votes given respectively as `MemberCount`). + Voted(AccountId, Hash, bool, MemberCount, MemberCount), + /// A motion was approved by the required threshold. + Approved(Hash), + /// A motion was not approved by the required threshold. + Disapproved(Hash), + /// A motion was executed; `bool` is true if returned without error. + Executed(Hash, bool), + /// A single member did some action; `bool` is true if returned without error. + MemberExecuted(Hash, bool), + } +} + +decl_error! { + pub enum Error for Module, I: Instance> { + /// Account is not a member + NotMember, + /// Duplicate proposals not allowed + DuplicateProposal, + /// Proposal must exist + ProposalMissing, + /// Mismatched index + WrongIndex, + /// Duplicate vote ignored + DuplicateVote, + /// Members are already initialized! + AlreadyInitialized, + } +} + +// Note: this module is not benchmarked. The weights are obtained based on the similarity of the +// executed logic with other democracy function. Note that councillor operations are assigned to the +// operational class. +decl_module! { + pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { + type Error = Error; + + fn deposit_event() = default; + + /// Set the collective's membership manually to `new_members`. Be nice to the chain and + /// provide it pre-sorted. + /// + /// Requires root origin. + #[weight = SimpleDispatchInfo::FixedOperational(100_000)] + fn set_members(origin, new_members: Vec) { + ensure_root(origin)?; + let mut new_members = new_members; + new_members.sort(); + >::mutate(|m| { + >::set_members_sorted(&new_members[..], m); + *m = new_members; + }); + } + + /// Dispatch a proposal from a member using the `Member` origin. + /// + /// Origin must be a member of the collective. + #[weight = SimpleDispatchInfo::FixedOperational(100_000)] + fn execute(origin, proposal: Box<>::Proposal>) { + let who = ensure_signed(origin)?; + ensure!(Self::is_member(&who), Error::::NotMember); + + let proposal_hash = T::Hashing::hash_of(&proposal); + let ok = proposal.dispatch(RawOrigin::Member(who).into()).is_ok(); + Self::deposit_event(RawEvent::MemberExecuted(proposal_hash, ok)); + } + + /// # + /// - Bounded storage reads and writes. + /// - Argument `threshold` has bearing on weight. + /// # + #[weight = SimpleDispatchInfo::FixedOperational(5_000_000)] + fn propose(origin, #[compact] threshold: MemberCount, proposal: Box<>::Proposal>) { + let who = ensure_signed(origin)?; + ensure!(Self::is_member(&who), Error::::NotMember); + + let proposal_hash = T::Hashing::hash_of(&proposal); + + ensure!(!>::exists(proposal_hash), Error::::DuplicateProposal); + + if threshold < 2 { + let seats = Self::members().len() as MemberCount; + let ok = proposal.dispatch(RawOrigin::Members(1, seats).into()).is_ok(); + Self::deposit_event(RawEvent::Executed(proposal_hash, ok)); + } else { + let index = Self::proposal_count(); + >::mutate(|i| *i += 1); + >::mutate(|proposals| proposals.push(proposal_hash)); + >::insert(proposal_hash, *proposal); + let votes = Votes { index, threshold, ayes: vec![who.clone()], nays: vec![] }; + >::insert(proposal_hash, votes); + + Self::deposit_event(RawEvent::Proposed(who, index, proposal_hash, threshold)); + } + } + + /// # + /// - Bounded storage read and writes. + /// - Will be slightly heavier if the proposal is approved / disapproved after the vote. + /// # + #[weight = SimpleDispatchInfo::FixedOperational(200_000)] + fn vote(origin, proposal: T::Hash, #[compact] index: ProposalIndex, approve: bool) { + let who = ensure_signed(origin)?; + ensure!(Self::is_member(&who), Error::::NotMember); + + let mut voting = Self::voting(&proposal).ok_or(Error::::ProposalMissing)?; + ensure!(voting.index == index, Error::::WrongIndex); + + let position_yes = voting.ayes.iter().position(|a| a == &who); + let position_no = voting.nays.iter().position(|a| a == &who); + + if approve { + if position_yes.is_none() { + voting.ayes.push(who.clone()); + } else { + Err(Error::::DuplicateVote)? + } + if let Some(pos) = position_no { + voting.nays.swap_remove(pos); + } + } else { + if position_no.is_none() { + voting.nays.push(who.clone()); + } else { + Err(Error::::DuplicateVote)? + } + if let Some(pos) = position_yes { + voting.ayes.swap_remove(pos); + } + } + + let yes_votes = voting.ayes.len() as MemberCount; + let no_votes = voting.nays.len() as MemberCount; + Self::deposit_event(RawEvent::Voted(who, proposal, approve, yes_votes, no_votes)); + + let seats = Self::members().len() as MemberCount; + let approved = yes_votes >= voting.threshold; + let disapproved = seats.saturating_sub(no_votes) < voting.threshold; + if approved || disapproved { + if approved { + Self::deposit_event(RawEvent::Approved(proposal)); + + // execute motion, assuming it exists. + if let Some(p) = >::take(&proposal) { + let origin = RawOrigin::Members(voting.threshold, seats).into(); + let ok = p.dispatch(origin).is_ok(); + Self::deposit_event(RawEvent::Executed(proposal, ok)); + } + } else { + // disapproved + >::remove(&proposal); + Self::deposit_event(RawEvent::Disapproved(proposal)); + } + + // remove vote + >::remove(&proposal); + >::mutate(|proposals| proposals.retain(|h| h != &proposal)); + } else { + // update voting + >::insert(&proposal, voting); + } + } + } +} + +impl, I: Instance> Module { + pub fn is_member(who: &T::AccountId) -> bool { + Self::members().contains(who) + } +} + +impl, I: Instance> ChangeMembers for Module { + fn change_members_sorted(_incoming: &[T::AccountId], outgoing: &[T::AccountId], new: &[T::AccountId]) { + // remove accounts from all current voting in motions. + let mut outgoing = outgoing.to_vec(); + outgoing.sort_unstable(); + for h in Self::proposals().into_iter() { + >::mutate(h, |v| + if let Some(mut votes) = v.take() { + votes.ayes = votes.ayes.into_iter() + .filter(|i| outgoing.binary_search(i).is_err()) + .collect(); + votes.nays = votes.nays.into_iter() + .filter(|i| outgoing.binary_search(i).is_err()) + .collect(); + *v = Some(votes); + } + ); + } + >::put(new); + } +} + +impl, I: Instance> InitializeMembers for Module { + fn initialize_members(members: &[T::AccountId]) { + if !members.is_empty() { + assert!(>::get().is_empty(), "Members are already initialized!"); + >::put(members); + } + } +} + +/// Ensure that the origin `o` represents at least `n` members. Returns `Ok` or an `Err` +/// otherwise. +pub fn ensure_members(o: OuterOrigin, n: MemberCount) + -> result::Result +where + OuterOrigin: Into, OuterOrigin>> +{ + match o.into() { + Ok(RawOrigin::Members(x, _)) if x >= n => Ok(n), + _ => Err("bad origin: expected to be a threshold number of members"), + } +} + +pub struct EnsureMember(sp_std::marker::PhantomData<(AccountId, I)>); +impl< + O: Into, O>> + From>, + AccountId, + I, +> EnsureOrigin for EnsureMember { + type Success = AccountId; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + RawOrigin::Member(id) => Ok(id), + r => Err(O::from(r)), + }) + } +} + +pub struct EnsureMembers(sp_std::marker::PhantomData<(N, AccountId, I)>); +impl< + O: Into, O>> + From>, + N: U32, + AccountId, + I, +> EnsureOrigin for EnsureMembers { + type Success = (MemberCount, MemberCount); + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + RawOrigin::Members(n, m) if n >= N::VALUE => Ok((n, m)), + r => Err(O::from(r)), + }) + } +} + +pub struct EnsureProportionMoreThan( + sp_std::marker::PhantomData<(N, D, AccountId, I)> +); +impl< + O: Into, O>> + From>, + N: U32, + D: U32, + AccountId, + I, +> EnsureOrigin for EnsureProportionMoreThan { + type Success = (); + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + RawOrigin::Members(n, m) if n * D::VALUE > N::VALUE * m => Ok(()), + r => Err(O::from(r)), + }) + } +} + +pub struct EnsureProportionAtLeast( + sp_std::marker::PhantomData<(N, D, AccountId, I)> +); +impl< + O: Into, O>> + From>, + N: U32, + D: U32, + AccountId, + I, +> EnsureOrigin for EnsureProportionAtLeast { + type Success = (); + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + RawOrigin::Members(n, m) if n * D::VALUE >= N::VALUE * m => Ok(()), + r => Err(O::from(r)), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::{Hashable, assert_ok, assert_noop, parameter_types, weights::Weight}; + use frame_system::{self as system, EventRecord, Phase}; + use hex_literal::hex; + use sp_core::H256; + use sp_runtime::{ + Perbill, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, + BuildStorage, + }; + use crate as collective; + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + impl Trait for Test { + type Origin = Origin; + type Proposal = Call; + type Event = Event; + } + impl Trait for Test { + type Origin = Origin; + type Proposal = Call; + type Event = Event; + } + + pub type Block = sp_runtime::generic::Block; + pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; + + frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event}, + Collective: collective::::{Module, Call, Event, Origin, Config}, + DefaultCollective: collective::{Module, Call, Event, Origin, Config}, + } + ); + + fn make_ext() -> sp_io::TestExternalities { + GenesisConfig { + collective_Instance1: Some(collective::GenesisConfig { + members: vec![1, 2, 3], + phantom: Default::default(), + }), + collective: None, + }.build_storage().unwrap().into() + } + + #[test] + fn motions_basic_environment_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + assert_eq!(Collective::members(), vec![1, 2, 3]); + assert_eq!(Collective::proposals(), Vec::::new()); + }); + } + + fn make_proposal(value: u64) -> Call { + Call::System(frame_system::Call::remark(value.encode())) + } + + #[test] + fn removal_of_old_voters_votes_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + let hash = BlakeTwo256::hash_of(&proposal); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![] }) + ); + Collective::change_members_sorted(&[4], &[1], &[2, 3, 4]); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![] }) + ); + + let proposal = make_proposal(69); + let hash = BlakeTwo256::hash_of(&proposal); + assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::vote(Origin::signed(3), hash.clone(), 1, false)); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3] }) + ); + Collective::change_members_sorted(&[], &[3], &[2, 4]); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![] }) + ); + }); + } + + #[test] + fn removal_of_old_voters_votes_works_with_set_members() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + let hash = BlakeTwo256::hash_of(&proposal); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![] }) + ); + assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 3, 4])); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![] }) + ); + + let proposal = make_proposal(69); + let hash = BlakeTwo256::hash_of(&proposal); + assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::vote(Origin::signed(3), hash.clone(), 1, false)); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3] }) + ); + assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 4])); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![] }) + ); + }); + } + + #[test] + fn propose_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + let hash = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_eq!(Collective::proposals(), vec![hash]); + assert_eq!(Collective::proposal_of(&hash), Some(proposal)); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 0, threshold: 3, ayes: vec![1], nays: vec![] }) + ); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Proposed( + 1, + 0, + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + 3, + )), + topics: vec![], + } + ]); + }); + } + + #[test] + fn motions_ignoring_non_collective_proposals_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + assert_noop!( + Collective::propose(Origin::signed(42), 3, Box::new(proposal.clone())), + Error::::NotMember + ); + }); + } + + #[test] + fn motions_ignoring_non_collective_votes_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_noop!( + Collective::vote(Origin::signed(42), hash.clone(), 0, true), + Error::::NotMember, + ); + }); + } + + #[test] + fn motions_ignoring_bad_index_collective_vote_works() { + make_ext().execute_with(|| { + System::set_block_number(3); + let proposal = make_proposal(42); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_noop!( + Collective::vote(Origin::signed(2), hash.clone(), 1, true), + Error::::WrongIndex, + ); + }); + } + + #[test] + fn motions_revoting_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 0, threshold: 2, ayes: vec![1], nays: vec![] }) + ); + assert_noop!( + Collective::vote(Origin::signed(1), hash.clone(), 0, true), + Error::::DuplicateVote, + ); + assert_ok!(Collective::vote(Origin::signed(1), hash.clone(), 0, false)); + assert_eq!( + Collective::voting(&hash), + Some(Votes { index: 0, threshold: 2, ayes: vec![], nays: vec![1] }) + ); + assert_noop!( + Collective::vote(Origin::signed(1), hash.clone(), 0, false), + Error::::DuplicateVote, + ); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Proposed( + 1, + 0, + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + 2, + )), + topics: vec![], + }, + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Voted( + 1, + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + false, + 0, + 1, + )), + topics: vec![], + } + ]); + }); + } + + #[test] + fn motions_reproposing_disapproved_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); + assert_eq!(Collective::proposals(), vec![]); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_eq!(Collective::proposals(), vec![hash]); + }); + } + + #[test] + fn motions_disapproval_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1( + RawEvent::Proposed( + 1, + 0, + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + 3, + )), + topics: vec![], + }, + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Voted( + 2, + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + false, + 1, + 1, + )), + topics: vec![], + }, + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Disapproved( + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + )), + topics: vec![], + } + ]); + }); + } + + #[test] + fn motions_approval_works() { + make_ext().execute_with(|| { + System::set_block_number(1); + let proposal = make_proposal(42); + let hash: H256 = proposal.blake2_256().into(); + assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); + assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Proposed( + 1, + 0, + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + 2, + )), + topics: vec![], + }, + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Voted( + 2, + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + true, + 2, + 0, + )), + topics: vec![], + }, + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Approved( + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + )), + topics: vec![], + }, + EventRecord { + phase: Phase::Finalization, + event: Event::collective_Instance1(RawEvent::Executed( + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), + false, + )), + topics: vec![], + } + ]); + }); + } +} diff --git a/srml/contracts/COMPLEXITY.md b/frame/contracts/COMPLEXITY.md similarity index 100% rename from srml/contracts/COMPLEXITY.md rename to frame/contracts/COMPLEXITY.md diff --git a/frame/contracts/Cargo.toml b/frame/contracts/Cargo.toml new file mode 100644 index 0000000000000..c6102d23eabbe --- /dev/null +++ b/frame/contracts/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "pallet-contracts" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +pwasm-utils = { version = "0.12.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +parity-wasm = { version = "0.41.0", default-features = false } +wasmi-validation = { version = "0.3.0", default-features = false } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-sandbox = { version = "2.0.0", default-features = false, path = "../../primitives/sandbox" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +wabt = "0.9.2" +assert_matches = "1.3.0" +hex-literal = "0.2.1" +pallet-balances = { version = "2.0.0", path = "../balances" } +pallet-timestamp = { version = "2.0.0", path = "../timestamp" } +pallet-randomness-collective-flip = { version = "2.0.0", path = "../randomness-collective-flip" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-core/std", + "sp-runtime/std", + "sp-io/std", + "sp-std/std", + "sp-sandbox/std", + "frame-support/std", + "frame-system/std", + "parity-wasm/std", + "pwasm-utils/std", + "wasmi-validation/std", +] diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml new file mode 100644 index 0000000000000..c563d9f727dec --- /dev/null +++ b/frame/contracts/rpc/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "pallet-contracts-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0" } +jsonrpc-core = "14.0.3" +jsonrpc-core-client = "14.0.3" +jsonrpc-derive = "14.0.3" +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-rpc = { version = "2.0.0", path = "../../../primitives/rpc" } +serde = { version = "1.0.101", features = ["derive"] } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +pallet-contracts-rpc-runtime-api = { version = "2.0.0", path = "./runtime-api" } + +[dev-dependencies] +serde_json = "1.0.41" diff --git a/frame/contracts/rpc/runtime-api/Cargo.toml b/frame/contracts/rpc/runtime-api/Cargo.toml new file mode 100644 index 0000000000000..c8e183237cf43 --- /dev/null +++ b/frame/contracts/rpc/runtime-api/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "pallet-contracts-rpc-runtime-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-api = { version = "2.0.0", default-features = false, path = "../../../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../../../primitives/runtime" } + +[features] +default = ["std"] +std = [ + "sp-api/std", + "codec/std", + "sp-std/std", + "sp-runtime/std", +] diff --git a/frame/contracts/rpc/runtime-api/src/lib.rs b/frame/contracts/rpc/runtime-api/src/lib.rs new file mode 100644 index 0000000000000..622cac8572141 --- /dev/null +++ b/frame/contracts/rpc/runtime-api/src/lib.rs @@ -0,0 +1,89 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime API definition required by Contracts RPC extensions. +//! +//! This API should be imported and implemented by the runtime, +//! of a node that wants to use the custom RPC extension +//! adding Contracts access methods. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::vec::Vec; +use codec::{Encode, Decode, Codec}; +use sp_runtime::RuntimeDebug; + +/// A result of execution of a contract. +#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)] +pub enum ContractExecResult { + /// The contract returned successfully. + /// + /// There is a status code and, optionally, some data returned by the contract. + Success { + /// Status code returned by the contract. + status: u8, + /// Output data returned by the contract. + /// + /// Can be empty. + data: Vec, + }, + /// The contract execution either trapped or returned an error. + Error, +} + +/// A result type of the get storage call. +/// +/// See [`ContractsApi::get_storage`] for more info. +pub type GetStorageResult = Result>, GetStorageError>; + +/// The possible errors that can happen querying the storage of a contract. +#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)] +pub enum GetStorageError { + /// The given address doesn't point on a contract. + ContractDoesntExist, + /// The specified contract is a tombstone and thus cannot have any storage. + IsTombstone, +} + +sp_api::decl_runtime_apis! { + /// The API to interact with contracts without using executive. + pub trait ContractsApi where + AccountId: Codec, + Balance: Codec, + { + /// Perform a call from a specified account to a given contract. + /// + /// See the contracts' `call` dispatchable function for more details. + fn call( + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: u64, + input_data: Vec, + ) -> ContractExecResult; + + /// Query a given storage key in a given contract. + /// + /// Returns `Ok(Some(Vec))` if the storage value exists under the given key in the + /// specified account and `Ok(None)` if it doesn't. If the account specified by the address + /// doesn't exist, or doesn't have a contract or if the contract is a tombstone, then `Err` + /// is returned. + fn get_storage( + address: AccountId, + key: [u8; 32], + ) -> GetStorageResult; + } +} diff --git a/frame/contracts/rpc/src/lib.rs b/frame/contracts/rpc/src/lib.rs new file mode 100644 index 0000000000000..4c39bc9516f55 --- /dev/null +++ b/frame/contracts/rpc/src/lib.rs @@ -0,0 +1,251 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Node-specific RPC methods for interaction with contracts. + +use std::sync::Arc; + +use sp_blockchain::HeaderBackend; +use codec::Codec; +use jsonrpc_core::{Error, ErrorCode, Result}; +use jsonrpc_derive::rpc; +use sp_core::{H256, Bytes}; +use sp_rpc::number; +use serde::{Deserialize, Serialize}; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use sp_api::ProvideRuntimeApi; + +pub use self::gen_client::Client as ContractsClient; +pub use pallet_contracts_rpc_runtime_api::{ + self as runtime_api, ContractExecResult, ContractsApi as ContractsRuntimeApi, GetStorageResult, +}; + +const RUNTIME_ERROR: i64 = 1; +const CONTRACT_DOESNT_EXIST: i64 = 2; +const CONTRACT_IS_A_TOMBSTONE: i64 = 3; + +/// A rough estimate of how much gas a decent hardware consumes per second, +/// using native execution. +/// This value is used to set the upper bound for maximal contract calls to +/// prevent blocking the RPC for too long. +/// +/// Based on W3F research spreadsheet: +/// https://docs.google.com/spreadsheets/d/1h0RqncdqiWI4KgxO0z9JIpZEJESXjX_ZCK6LFX6veDo/view +const GAS_PER_SECOND: u64 = 1_000_000_000; + +/// A private newtype for converting `GetStorageError` into an RPC error. +struct GetStorageError(runtime_api::GetStorageError); +impl From for Error { + fn from(e: GetStorageError) -> Error { + use runtime_api::GetStorageError::*; + match e.0 { + ContractDoesntExist => Error { + code: ErrorCode::ServerError(CONTRACT_DOESNT_EXIST), + message: "The specified contract doesn't exist.".into(), + data: None, + }, + IsTombstone => Error { + code: ErrorCode::ServerError(CONTRACT_IS_A_TOMBSTONE), + message: "The contract is a tombstone and doesn't have any storage.".into(), + data: None, + } + } + } +} + +/// A struct that encodes RPC parameters required for a call to a smart-contract. +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct CallRequest { + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: number::NumberOrHex, + input_data: Bytes, +} + +/// An RPC serializable result of contract execution +#[derive(Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "camelCase")] +pub enum RpcContractExecResult { + /// Successful execution + Success { + /// Status code + status: u8, + /// Output data + data: Bytes, + }, + /// Error execution + Error(()), +} + +impl From for RpcContractExecResult { + fn from(r: ContractExecResult) -> Self { + match r { + ContractExecResult::Success { status, data } => { + RpcContractExecResult::Success { status, data: data.into() } + }, + ContractExecResult::Error => { + RpcContractExecResult::Error(()) + }, + } + } +} + +/// Contracts RPC methods. +#[rpc] +pub trait ContractsApi { + /// Executes a call to a contract. + /// + /// This call is performed locally without submitting any transactions. Thus executing this + /// won't change any state. Nonetheless, the calling state-changing contracts is still possible. + /// + /// This method is useful for calling getter-like methods on contracts. + #[rpc(name = "contracts_call")] + fn call( + &self, + call_request: CallRequest, + at: Option, + ) -> Result; + + /// Returns the value under a specified storage `key` in a contract given by `address` param, + /// or `None` if it is not set. + #[rpc(name = "contracts_getStorage")] + fn get_storage( + &self, + address: AccountId, + key: H256, + at: Option, + ) -> Result>; +} + +/// An implementation of contract specific RPC methods. +pub struct Contracts { + client: Arc, + _marker: std::marker::PhantomData, +} + +impl Contracts { + /// Create new `Contracts` with the given reference to the client. + pub fn new(client: Arc) -> Self { + Contracts { + client, + _marker: Default::default(), + } + } +} + +impl ContractsApi<::Hash, AccountId, Balance> + for Contracts +where + Block: BlockT, + C: Send + Sync + 'static + ProvideRuntimeApi + HeaderBackend, + C::Api: ContractsRuntimeApi, + AccountId: Codec, + Balance: Codec, +{ + fn call( + &self, + call_request: CallRequest, + at: Option<::Hash>, + ) -> Result { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| + // If the block hash is not supplied assume the best block. + self.client.info().best_hash)); + + let CallRequest { + origin, + dest, + value, + gas_limit, + input_data, + } = call_request; + let gas_limit = gas_limit.to_number().map_err(|e| Error { + code: ErrorCode::InvalidParams, + message: e, + data: None, + })?; + + let max_gas_limit = 5 * GAS_PER_SECOND; + if gas_limit > max_gas_limit { + return Err(Error { + code: ErrorCode::InvalidParams, + message: format!( + "Requested gas limit is greater than maximum allowed: {} > {}", + gas_limit, + max_gas_limit + ), + data: None, + }); + } + + let exec_result = api + .call(&at, origin, dest, value, gas_limit, input_data.to_vec()) + .map_err(|e| Error { + code: ErrorCode::ServerError(RUNTIME_ERROR), + message: "Runtime trapped while executing a contract.".into(), + data: Some(format!("{:?}", e).into()), + })?; + + Ok(exec_result.into()) + } + + fn get_storage( + &self, + address: AccountId, + key: H256, + at: Option<::Hash>, + ) -> Result> { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| + // If the block hash is not supplied assume the best block. + self.client.info().best_hash)); + + let get_storage_result = api + .get_storage(&at, address, key.into()) + .map_err(|e| + // Handle general API calling errors. + Error { + code: ErrorCode::ServerError(RUNTIME_ERROR), + message: "Runtime trapped while querying storage.".into(), + data: Some(format!("{:?}", e).into()), + })? + .map_err(GetStorageError)? + .map(Bytes); + + Ok(get_storage_result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_serialize_deserialize_properly() { + fn test(expected: &str) { + let res: RpcContractExecResult = serde_json::from_str(expected).unwrap(); + let actual = serde_json::to_string(&res).unwrap(); + assert_eq!(actual, expected); + } + + test(r#"{"success":{"status":5,"data":"0x1234"}}"#); + test(r#"{"error":null}"#); + } +} diff --git a/srml/contracts/src/account_db.rs b/frame/contracts/src/account_db.rs similarity index 90% rename from srml/contracts/src/account_db.rs rename to frame/contracts/src/account_db.rs index 50bd1fd40e97d..3615673f2d9dc 100644 --- a/srml/contracts/src/account_db.rs +++ b/frame/contracts/src/account_db.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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 super::{ TrieIdGenerator, }; use crate::exec::StorageKey; -use rstd::cell::RefCell; -use rstd::collections::btree_map::{BTreeMap, Entry}; -use rstd::prelude::*; -use runtime_io::blake2_256; -use sr_primitives::traits::{Bounded, Zero}; -use support::traits::{Currency, Get, Imbalance, SignedImbalance, UpdateBalanceOutcome}; -use support::{storage::child, StorageMap}; -use system; +use sp_std::cell::RefCell; +use sp_std::collections::btree_map::{BTreeMap, Entry}; +use sp_std::prelude::*; +use sp_io::hashing::blake2_256; +use sp_runtime::traits::{Bounded, Zero}; +use frame_support::traits::{Currency, Get, Imbalance, SignedImbalance, UpdateBalanceOutcome}; +use frame_support::{storage::child, StorageMap}; +use frame_system; // Note: we don't provide Option because we can't create // the trie_id in the overlay, thus we provide an overlay on the fields @@ -100,7 +100,7 @@ impl Default for ChangeEntry { } } -pub type ChangeSet = BTreeMap<::AccountId, ChangeEntry>; +pub type ChangeSet = BTreeMap<::AccountId, ChangeEntry>; pub trait AccountDb { /// Account is used when overlayed otherwise trie_id must be provided. @@ -128,7 +128,7 @@ impl AccountDb for DirectAccountDb { trie_id: Option<&TrieId>, location: &StorageKey ) -> Option> { - trie_id.and_then(|id| child::get_raw(id, &blake2_256(location))) + trie_id.and_then(|id| child::get_raw(id, crate::trie_unique_id(&id[..]), &blake2_256(location))) } fn get_code_hash(&self, account: &T::AccountId) -> Option> { >::get(account).and_then(|i| i.as_alive().map(|i| i.code_hash)) @@ -173,18 +173,18 @@ impl AccountDb for DirectAccountDb { (false, Some(info), _) => info, // Existing contract is being removed. (true, Some(info), None) => { - child::kill_storage(&info.trie_id); + child::kill_storage(&info.trie_id, info.child_trie_unique_id()); >::remove(&address); continue; } // Existing contract is being replaced by a new one. (true, Some(info), Some(code_hash)) => { - child::kill_storage(&info.trie_id); + child::kill_storage(&info.trie_id, info.child_trie_unique_id()); AliveContractInfo:: { code_hash, storage_size: T::StorageSizeOffset::get(), trie_id: ::TrieIdGenerator::trie_id(&address), - deduct_block: >::block_number(), + deduct_block: >::block_number(), rent_allowance: >::max_value(), last_write: None, } @@ -195,7 +195,7 @@ impl AccountDb for DirectAccountDb { code_hash, storage_size: T::StorageSizeOffset::get(), trie_id: ::TrieIdGenerator::trie_id(&address), - deduct_block: >::block_number(), + deduct_block: >::block_number(), rent_allowance: >::max_value(), last_write: None, } @@ -213,18 +213,22 @@ impl AccountDb for DirectAccountDb { } if !changed.storage.is_empty() { - new_info.last_write = Some(>::block_number()); + new_info.last_write = Some(>::block_number()); } for (k, v) in changed.storage.into_iter() { - if let Some(value) = child::get_raw(&new_info.trie_id[..], &blake2_256(&k)) { + if let Some(value) = child::get_raw( + &new_info.trie_id[..], + new_info.child_trie_unique_id(), + &blake2_256(&k), + ) { new_info.storage_size -= value.len() as u32; } if let Some(value) = v { new_info.storage_size += value.len() as u32; - child::put_raw(&new_info.trie_id[..], &blake2_256(&k), &value[..]); + child::put_raw(&new_info.trie_id[..], new_info.child_trie_unique_id(), &blake2_256(&k), &value[..]); } else { - child::kill(&new_info.trie_id[..], &blake2_256(&k)); + child::kill(&new_info.trie_id[..], new_info.child_trie_unique_id(), &blake2_256(&k)); } } diff --git a/srml/contracts/src/exec.rs b/frame/contracts/src/exec.rs similarity index 95% rename from srml/contracts/src/exec.rs rename to frame/contracts/src/exec.rs index af79c6c818131..2c77173135077 100644 --- a/srml/contracts/src/exec.rs +++ b/frame/contracts/src/exec.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,18 +20,22 @@ use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}; use crate::gas::{Gas, GasMeter, Token, approx_gas_for_balance}; use crate::rent; -use rstd::prelude::*; -use sr_primitives::traits::{Bounded, CheckedAdd, CheckedSub, Zero}; -use support::traits::{WithdrawReason, Currency, Time, Randomness}; +use sp_std::prelude::*; +use sp_runtime::traits::{Bounded, CheckedAdd, CheckedSub, Zero}; +use frame_support::{ + storage::unhashed, dispatch::DispatchError, + traits::{WithdrawReason, Currency, Time, Randomness}, +}; -pub type AccountIdOf = ::AccountId; +pub type AccountIdOf = ::AccountId; pub type CallOf = ::Call; pub type MomentOf = <::Time as Time>::Moment; -pub type SeedOf = ::Hash; -pub type BlockNumberOf = ::BlockNumber; +pub type SeedOf = ::Hash; +pub type BlockNumberOf = ::BlockNumber; +pub type StorageKey = [u8; 32]; /// A type that represents a topic of an event. At the moment a hash is used. -pub type TopicOf = ::Hash; +pub type TopicOf = ::Hash; /// A status code return to the source of a contract call or instantiation indicating success or /// failure. A code of 0 indicates success and that changes are applied. All other codes indicate @@ -60,9 +64,9 @@ impl ExecReturnValue { /// VM-specific errors during execution (eg. division by 0, OOB access, failure to satisfy some /// precondition of a system call, etc.) or errors with the orchestration (eg. out-of-gas errors, a /// non-existent destination contract, etc.). -#[cfg_attr(test, derive(sr_primitives::RuntimeDebug))] +#[cfg_attr(test, derive(sp_runtime::RuntimeDebug))] pub struct ExecError { - pub reason: &'static str, + pub reason: DispatchError, /// This is an allocated buffer that may be reused. The buffer must be cleared explicitly /// before reuse. pub buffer: Vec, @@ -79,13 +83,13 @@ macro_rules! try_or_exec_error { ($e:expr, $buffer:expr) => { match $e { Ok(val) => val, - Err(reason) => return Err($crate::exec::ExecError { reason, buffer: $buffer }), + Err(reason) => return Err( + $crate::exec::ExecError { reason: reason.into(), buffer: $buffer } + ), } } } -pub type StorageKey = [u8; 32]; - /// An interface that provides access to the external environment in which the /// smart-contract is executed. /// @@ -176,6 +180,11 @@ pub trait Ext { /// Returns the maximum allowed size of a storage item. fn max_value_size(&self) -> u32; + + /// Returns the value of runtime under the given key. + /// + /// Returns `None` if the value doesn't exist. + fn get_runtime_storage(&self, key: &[u8]) -> Option>; } /// Loader is a companion of the `Vm` trait. It loads an appropriate abstract @@ -232,7 +241,7 @@ impl Token for ExecFeeToken { } #[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq, Clone))] -#[derive(sr_primitives::RuntimeDebug)] +#[derive(sp_runtime::RuntimeDebug)] pub enum DeferredAction { DepositEvent { /// A list of topics this event will be deposited with. @@ -297,7 +306,7 @@ where vm: &vm, loader: &loader, timestamp: T::Time::now(), - block_number: >::block_number(), + block_number: >::block_number(), } } @@ -329,7 +338,7 @@ where ) -> ExecResult { if self.depth == self.config.max_depth as usize { return Err(ExecError { - reason: "reached maximum depth, cannot make a call", + reason: "reached maximum depth, cannot make a call".into(), buffer: input_data, }); } @@ -339,7 +348,7 @@ where .is_out_of_gas() { return Err(ExecError { - reason: "not enough gas to pay base call fee", + reason: "not enough gas to pay base call fee".into(), buffer: input_data, }); } @@ -352,7 +361,7 @@ where // Calls to dead contracts always fail. if let Some(ContractInfo::Tombstone(_)) = contract_info { return Err(ExecError { - reason: "contract has been evicted", + reason: "contract has been evicted".into(), buffer: input_data, }); }; @@ -397,7 +406,7 @@ where .expect("a nested execution context must have a parent; qed"); if parent.is_live(&dest) { return Err(ExecError { - reason: "contract cannot be destroyed during recursive execution", + reason: "contract cannot be destroyed during recursive execution".into(), buffer: output.data, }); } @@ -421,7 +430,7 @@ where ) -> Result<(T::AccountId, ExecReturnValue), ExecError> { if self.depth == self.config.max_depth as usize { return Err(ExecError { - reason: "reached maximum depth, cannot instantiate", + reason: "reached maximum depth, cannot instantiate".into(), buffer: input_data, }); } @@ -431,7 +440,7 @@ where .is_out_of_gas() { return Err(ExecError { - reason: "not enough gas to pay base instantiate fee", + reason: "not enough gas to pay base instantiate fee".into(), buffer: input_data, }); } @@ -481,7 +490,7 @@ where // Error out if insufficient remaining balance. if nested.overlay.get_balance(&dest) < nested.config.existential_deposit { return Err(ExecError { - reason: "insufficient remaining balance", + reason: "insufficient remaining balance".into(), buffer: output.data, }); } @@ -596,7 +605,7 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( dest: &T::AccountId, value: BalanceOf, ctx: &mut ExecutionContext<'a, T, V, L>, -) -> Result<(), &'static str> { +) -> Result<(), DispatchError> { use self::TransferCause::*; use self::TransferFeeKind::*; @@ -630,23 +639,28 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( }; if gas_meter.charge(ctx.config, token).is_out_of_gas() { - return Err("not enough gas to pay transfer fee"); + Err("not enough gas to pay transfer fee")? } // We allow balance to go below the existential deposit here: let from_balance = ctx.overlay.get_balance(transactor); let new_from_balance = match from_balance.checked_sub(&value) { Some(b) => b, - None => return Err("balance too low to send value"), + None => Err("balance too low to send value")?, }; if would_create && value < ctx.config.existential_deposit { - return Err("value too low to create account"); + Err("value too low to create account")? } - T::Currency::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer, new_from_balance)?; + T::Currency::ensure_can_withdraw( + transactor, + value, + WithdrawReason::Transfer.into(), + new_from_balance, + )?; let new_to_balance = match to_balance.checked_add(&value) { Some(b) => b, - None => return Err("destination balance too high to receive value"), + None => Err("destination balance too high to receive value")?, }; if transactor != dest { @@ -786,6 +800,10 @@ where fn max_value_size(&self) -> u32 { self.ctx.config.max_value_size } + + fn get_runtime_storage(&self, key: &[u8]) -> Option> { + unhashed::get_raw(&key) + } } /// These tests exercise the executive layer. @@ -810,6 +828,7 @@ mod tests { }; use std::{cell::RefCell, rc::Rc, collections::HashMap, marker::PhantomData}; use assert_matches::assert_matches; + use sp_runtime::DispatchError; const ALICE: u64 = 1; const BOB: u64 = 2; @@ -860,7 +879,7 @@ mod tests { fn insert(&mut self, f: impl Fn(MockCtx) -> ExecResult + 'a) -> CodeHash { // Generate code hashes as monotonically increasing values. - let code_hash = ::Hash::from_low_u64_be(self.counter); + let code_hash = ::Hash::from_low_u64_be(self.counter); self.counter += 1; self.map.insert(code_hash, MockExecutable::new(f)); @@ -1165,7 +1184,10 @@ mod tests { assert_matches!( result, - Err(ExecError { reason: "balance too low to send value", buffer: _ }) + Err(ExecError { + reason: DispatchError::Other("balance too low to send value"), + buffer: _, + }) ); assert_eq!(ctx.overlay.get_balance(&origin), 0); assert_eq!(ctx.overlay.get_balance(&dest), 0); @@ -1302,7 +1324,10 @@ mod tests { // Verify that we've got proper error and set `reached_bottom`. assert_matches!( r, - Err(ExecError { reason: "reached maximum depth, cannot make a call", buffer: _ }) + Err(ExecError { + reason: DispatchError::Other("reached maximum depth, cannot make a call"), + buffer: _, + }) ); *reached_bottom = true; } else { @@ -1572,7 +1597,7 @@ mod tests { let mut loader = MockLoader::empty(); let dummy_ch = loader.insert( - |_| Err(ExecError { reason: "It's a trap!", buffer: Vec::new() }) + |_| Err(ExecError { reason: "It's a trap!".into(), buffer: Vec::new() }) ); let instantiator_ch = loader.insert({ let dummy_ch = dummy_ch.clone(); @@ -1585,7 +1610,7 @@ mod tests { ctx.gas_meter, vec![] ), - Err(ExecError { reason: "It's a trap!", buffer: _ }) + Err(ExecError { reason: DispatchError::Other("It's a trap!"), buffer: _ }) ); exec_success() diff --git a/srml/contracts/src/gas.rs b/frame/contracts/src/gas.rs similarity index 97% rename from srml/contracts/src/gas.rs rename to frame/contracts/src/gas.rs index 08070916fbf29..e0cc7d4bfb4c7 100644 --- a/srml/contracts/src/gas.rs +++ b/frame/contracts/src/gas.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,12 +15,13 @@ // along with Substrate. If not, see . use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf}; -use rstd::convert::TryFrom; -use sr_primitives::traits::{ +use sp_std::convert::TryFrom; +use sp_runtime::traits::{ CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto, }; -use support::{ +use frame_support::{ traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReason}, StorageValue, + dispatch::DispatchError, }; #[cfg(test)] @@ -201,7 +202,7 @@ impl GasMeter { pub fn buy_gas( transactor: &T::AccountId, gas_limit: Gas, -) -> Result<(GasMeter, NegativeImbalanceOf), &'static str> { +) -> Result<(GasMeter, NegativeImbalanceOf), DispatchError> { // Buy the specified amount of gas. let gas_price = >::gas_price(); let cost = if gas_price.is_zero() { @@ -215,7 +216,7 @@ pub fn buy_gas( let imbalance = T::Currency::withdraw( transactor, cost, - WithdrawReason::Fee, + WithdrawReason::Fee.into(), ExistenceRequirement::KeepAlive )?; diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs new file mode 100644 index 0000000000000..df8da8866020d --- /dev/null +++ b/frame/contracts/src/lib.rs @@ -0,0 +1,1120 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Contract Module +//! +//! The Contract module provides functionality for the runtime to deploy and execute WebAssembly smart-contracts. +//! +//! - [`contract::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! This module extends accounts based on the `Currency` trait to have smart-contract functionality. It can +//! be used with other modules that implement accounts based on `Currency`. These "smart-contract accounts" +//! have the ability to instantiate smart-contracts and make calls to other contract and non-contract accounts. +//! +//! The smart-contract code is stored once in a `code_cache`, and later retrievable via its `code_hash`. +//! This means that multiple smart-contracts can be instantiated from the same `code_cache`, without replicating +//! the code each time. +//! +//! When a smart-contract is called, its associated code is retrieved via the code hash and gets executed. +//! This call can alter the storage entries of the smart-contract account, instantiate new smart-contracts, +//! or call other smart-contracts. +//! +//! Finally, when an account is reaped, its associated code and storage of the smart-contract account +//! will also be deleted. +//! +//! ### Gas +//! +//! Senders must specify a gas limit with every call, as all instructions invoked by the smart-contract require gas. +//! Unused gas is refunded after the call, regardless of the execution outcome. +//! +//! If the gas limit is reached, then all calls and state changes (including balance transfers) are only +//! reverted at the current call's contract level. For example, if contract A calls B and B runs out of gas mid-call, +//! then all of B's calls are reverted. Assuming correct error handling by contract A, A's other calls and state +//! changes still persist. +//! +//! ### Notable Scenarios +//! +//! Contract call failures are not always cascading. When failures occur in a sub-call, they do not "bubble up", +//! and the call will only revert at the specific contract level. For example, if contract A calls contract B, and B +//! fails, A can decide how to handle that failure, either proceeding or reverting A's changes. +//! +//! ## Interface +//! +//! ### Dispatchable functions +//! +//! * `put_code` - Stores the given binary Wasm code into the chain's storage and returns its `code_hash`. +//! * `instantiate` - Deploys a new contract from the given `code_hash`, optionally transferring some balance. +//! This instantiates a new smart contract account and calls its contract deploy handler to +//! initialize the contract. +//! * `call` - Makes a call to an account, optionally transferring some balance. +//! +//! ### Signed Extensions +//! +//! The contracts module defines the following extension: +//! +//! - [`CheckBlockGasLimit`]: Ensures that the transaction does not exceeds the block gas limit. +//! +//! The signed extension needs to be added as signed extra to the transaction type to be used in the +//! runtime. +//! +//! ## Usage +//! +//! The Contract module is a work in progress. The following examples show how this Contract module +//! can be used to instantiate and call contracts. +//! +//! * [`ink`](https://github.com/paritytech/ink) is +//! an [`eDSL`](https://wiki.haskell.org/Embedded_domain_specific_language) that enables writing +//! WebAssembly based smart contracts in the Rust programming language. This is a work in progress. +//! +//! ## Related Modules +//! +//! * [Balances](../pallet_balances/index.html) + +#![cfg_attr(not(feature = "std"), no_std)] + +#[macro_use] +mod gas; + +mod account_db; +mod exec; +mod wasm; +mod rent; + +#[cfg(test)] +mod tests; + +use crate::exec::ExecutionContext; +use crate::account_db::{AccountDb, DirectAccountDb}; +use crate::wasm::{WasmLoader, WasmVm}; + +pub use crate::gas::{Gas, GasMeter}; +pub use crate::exec::{ExecResult, ExecReturnValue, ExecError, StatusCode}; + +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use sp_core::crypto::UncheckedFrom; +use sp_std::{prelude::*, marker::PhantomData, fmt::Debug}; +use codec::{Codec, Encode, Decode}; +use sp_io::hashing::blake2_256; +use sp_runtime::{ + traits::{Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, SignedExtension}, + transaction_validity::{ + ValidTransaction, InvalidTransaction, TransactionValidity, TransactionValidityError, + }, + RuntimeDebug, +}; +use frame_support::dispatch::{DispatchResult, Dispatchable}; +use frame_support::{ + Parameter, decl_module, decl_event, decl_storage, decl_error, storage::child, + parameter_types, IsSubType, + weights::DispatchInfo, +}; +use frame_support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency, Get, Time, Randomness}; +use frame_system::{self as system, ensure_signed, RawOrigin, ensure_root}; +use sp_core::storage::well_known_keys::CHILD_STORAGE_KEY_PREFIX; + +pub type CodeHash = ::Hash; +pub type TrieId = Vec; + +/// 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; +} + +/// A function that returns the fee for dispatching a `Call`. +pub trait ComputeDispatchFee { + fn compute_dispatch_fee(call: &Call) -> Balance; +} + +/// Information for managing an acocunt and its sub trie abstraction. +/// This is the required info to cache for an account +#[derive(Encode, Decode, RuntimeDebug)] +pub enum ContractInfo { + Alive(AliveContractInfo), + Tombstone(TombstoneContractInfo), +} + +impl ContractInfo { + /// If contract is alive then return some alive info + pub fn get_alive(self) -> Option> { + if let ContractInfo::Alive(alive) = self { + Some(alive) + } else { + None + } + } + /// If contract is alive then return some reference to alive info + pub fn as_alive(&self) -> Option<&AliveContractInfo> { + if let ContractInfo::Alive(ref alive) = self { + Some(alive) + } else { + None + } + } + /// If contract is alive then return some mutable reference to alive info + pub fn as_alive_mut(&mut self) -> Option<&mut AliveContractInfo> { + if let ContractInfo::Alive(ref mut alive) = self { + Some(alive) + } else { + None + } + } + + /// If contract is tombstone then return some tombstone info + pub fn get_tombstone(self) -> Option> { + if let ContractInfo::Tombstone(tombstone) = self { + Some(tombstone) + } else { + None + } + } + /// If contract is tombstone then return some reference to tombstone info + pub fn as_tombstone(&self) -> Option<&TombstoneContractInfo> { + if let ContractInfo::Tombstone(ref tombstone) = self { + Some(tombstone) + } else { + None + } + } + /// If contract is tombstone then return some mutable reference to tombstone info + pub fn as_tombstone_mut(&mut self) -> Option<&mut TombstoneContractInfo> { + if let ContractInfo::Tombstone(ref mut tombstone) = self { + Some(tombstone) + } else { + None + } + } +} + +pub type AliveContractInfo = + RawAliveContractInfo, BalanceOf, ::BlockNumber>; + +/// Information for managing an account and its sub trie abstraction. +/// This is the required info to cache for an account. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct RawAliveContractInfo { + /// Unique ID for the subtree encoded as a bytes vector. + pub trie_id: TrieId, + /// The size of stored value in octet. + pub storage_size: u32, + /// The code associated with a given account. + pub code_hash: CodeHash, + /// Pay rent at most up to this value. + pub rent_allowance: Balance, + /// Last block rent has been payed. + pub deduct_block: BlockNumber, + /// Last block child storage has been written. + pub last_write: Option, +} + +impl RawAliveContractInfo { + /// Associated child trie unique id is built from the hash part of the trie id. + pub fn child_trie_unique_id(&self) -> child::ChildInfo { + trie_unique_id(&self.trie_id[..]) + } +} + +/// Associated child trie unique id is built from the hash part of the trie id. +pub(crate) fn trie_unique_id(trie_id: &[u8]) -> child::ChildInfo { + let start = CHILD_STORAGE_KEY_PREFIX.len() + b"default:".len(); + child::ChildInfo::new_default(&trie_id[start ..]) +} + +pub type TombstoneContractInfo = + RawTombstoneContractInfo<::Hash, ::Hashing>; + +#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug)] +pub struct RawTombstoneContractInfo(H, PhantomData); + +impl RawTombstoneContractInfo +where + H: Member + MaybeSerializeDeserialize+ Debug + + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + + sp_std::hash::Hash + Codec, + Hasher: Hash, +{ + fn new(storage_root: &[u8], code_hash: H) -> Self { + let mut buf = Vec::new(); + storage_root.using_encoded(|encoded| buf.extend_from_slice(encoded)); + buf.extend_from_slice(code_hash.as_ref()); + RawTombstoneContractInfo(Hasher::hash(&buf[..]), PhantomData) + } +} + +/// Get a trie id (trie id must be unique and collision resistant depending upon its context). +/// Note that it is different than encode because trie id should be collision resistant +/// (being a proper unique identifier). +pub trait TrieIdGenerator { + /// Get a trie id for an account, using reference to parent account trie id to ensure + /// uniqueness of trie id. + /// + /// The implementation must ensure every new trie id is unique: two consecutive calls with the + /// same parameter needs to return different trie id values. + /// + /// Also, the implementation is responsible for ensuring that `TrieId` starts with + /// `:child_storage:`. + /// TODO: We want to change this, see https://github.com/paritytech/substrate/issues/2325 + fn trie_id(account_id: &AccountId) -> TrieId; +} + +/// Get trie id from `account_id`. +pub struct TrieIdFromParentCounter(PhantomData); + +/// This generator uses inner counter for account id and applies the hash over `AccountId + +/// accountid_counter`. +impl TrieIdGenerator for TrieIdFromParentCounter +where + T::AccountId: AsRef<[u8]> +{ + fn trie_id(account_id: &T::AccountId) -> TrieId { + // Note that skipping a value due to error is not an issue here. + // We only need uniqueness, not sequence. + let new_seed = AccountCounter::mutate(|v| { + *v = v.wrapping_add(1); + *v + }); + + let mut buf = Vec::new(); + buf.extend_from_slice(account_id.as_ref()); + buf.extend_from_slice(&new_seed.to_le_bytes()[..]); + + // TODO: see https://github.com/paritytech/substrate/issues/2325 + CHILD_STORAGE_KEY_PREFIX.iter() + .chain(b"default:") + .chain(T::Hashing::hash(&buf[..]).as_ref().iter()) + .cloned() + .collect() + } +} + +pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +pub type NegativeImbalanceOf = + <::Currency as Currency<::AccountId>>::NegativeImbalance; + +parameter_types! { + /// A reasonable default value for [`Trait::SignedClaimedHandicap`]. + pub const DefaultSignedClaimHandicap: u32 = 2; + /// A reasonable default value for [`Trait::TombstoneDeposit`]. + pub const DefaultTombstoneDeposit: u32 = 16; + /// A reasonable default value for [`Trait::StorageSizeOffset`]. + pub const DefaultStorageSizeOffset: u32 = 8; + /// A reasonable default value for [`Trait::RentByteFee`]. + pub const DefaultRentByteFee: u32 = 4; + /// A reasonable default value for [`Trait::RentDepositOffset`]. + pub const DefaultRentDepositOffset: u32 = 1000; + /// A reasonable default value for [`Trait::SurchargeReward`]. + pub const DefaultSurchargeReward: u32 = 150; + /// A reasonable default value for [`Trait::TransferFee`]. + pub const DefaultTransferFee: u32 = 0; + /// A reasonable default value for [`Trait::InstantiationFee`]. + pub const DefaultInstantiationFee: u32 = 0; + /// A reasonable default value for [`Trait::TransactionBaseFee`]. + pub const DefaultTransactionBaseFee: u32 = 0; + /// A reasonable default value for [`Trait::TransactionByteFee`]. + pub const DefaultTransactionByteFee: u32 = 0; + /// A reasonable default value for [`Trait::ContractFee`]. + pub const DefaultContractFee: u32 = 21; + /// A reasonable default value for [`Trait::CallBaseFee`]. + pub const DefaultCallBaseFee: u32 = 1000; + /// A reasonable default value for [`Trait::InstantiateBaseFee`]. + pub const DefaultInstantiateBaseFee: u32 = 1000; + /// A reasonable default value for [`Trait::MaxDepth`]. + pub const DefaultMaxDepth: u32 = 32; + /// A reasonable default value for [`Trait::MaxValueSize`]. + pub const DefaultMaxValueSize: u32 = 16_384; + /// A reasonable default value for [`Trait::BlockGasLimit`]. + pub const DefaultBlockGasLimit: u32 = 10_000_000; +} + +pub trait Trait: frame_system::Trait { + type Currency: Currency; + type Time: Time; + type Randomness: Randomness; + + /// The outer call dispatch type. + type Call: Parameter + Dispatchable::Origin> + IsSubType, Self>; + + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// A function type to get the contract address given the instantiator. + type DetermineContractAddress: ContractAddressFor, Self::AccountId>; + + /// A function type that computes the fee for dispatching the given `Call`. + /// + /// It is recommended (though not required) for this function to return a fee that would be + /// taken by the Executive module for regular dispatch. + type ComputeDispatchFee: ComputeDispatchFee<::Call, BalanceOf>; + + /// trie id generator + type TrieIdGenerator: TrieIdGenerator; + + /// Handler for the unbalanced reduction when making a gas payment. + type GasPayment: OnUnbalanced>; + + /// Handler for rent payments. + type RentPayment: OnUnbalanced>; + + /// Number of block delay an extrinsic claim surcharge has. + /// + /// When claim surcharge is called by an extrinsic the rent is checked + /// for current_block - delay + type SignedClaimHandicap: Get; + + /// The minimum amount required to generate a tombstone. + type TombstoneDeposit: Get>; + + /// Size of a contract at the time of instantiation. This is a simple way to ensure + /// that empty contracts eventually gets deleted. + type StorageSizeOffset: Get; + + /// Price of a byte of storage per one block interval. Should be greater than 0. + type RentByteFee: Get>; + + /// The amount of funds a contract should deposit in order to offset + /// the cost of one byte. + /// + /// Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day, + /// then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent. + /// But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000, + /// then it would pay 500 BU/day. + type RentDepositOffset: Get>; + + /// Reward that is received by the party whose touch has led + /// to removal of a contract. + type SurchargeReward: Get>; + + /// The fee required to make a transfer. + type TransferFee: Get>; + + /// The fee required to create an account. + type CreationFee: Get>; + + /// The fee to be paid for making a transaction; the base. + type TransactionBaseFee: Get>; + + /// The fee to be paid for making a transaction; the per-byte portion. + type TransactionByteFee: Get>; + + /// The fee required to instantiate a contract instance. + type ContractFee: Get>; + + /// The base fee charged for calling into a contract. + type CallBaseFee: Get; + + /// The base fee charged for instantiating a contract. + type InstantiateBaseFee: Get; + + /// The maximum nesting level of a call/instantiate stack. + type MaxDepth: Get; + + /// The maximum size of a storage value in bytes. + type MaxValueSize: Get; + + /// The maximum amount of gas that could be expended per block. + type BlockGasLimit: Get; +} + +/// Simple contract address determiner. +/// +/// Address calculated from the code (of the constructor), input data to the constructor, +/// and the account id that requested the account creation. +/// +/// Formula: `blake2_256(blake2_256(code) + blake2_256(data) + origin)` +pub struct SimpleAddressDeterminator(PhantomData); +impl ContractAddressFor, T::AccountId> for SimpleAddressDeterminator +where + T::AccountId: UncheckedFrom + AsRef<[u8]> +{ + 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(); + buf.extend_from_slice(code_hash.as_ref()); + buf.extend_from_slice(data_hash.as_ref()); + buf.extend_from_slice(origin.as_ref()); + + UncheckedFrom::unchecked_from(T::Hashing::hash(&buf[..])) + } +} + +/// The default dispatch fee computor computes the fee in the same way that +/// the implementation of `ChargeTransactionPayment` for the Balances module does. Note that this only takes a fixed +/// fee based on size. Unlike the balances module, weight-fee is applied. +pub struct DefaultDispatchFeeComputor(PhantomData); +impl ComputeDispatchFee<::Call, BalanceOf> for DefaultDispatchFeeComputor { + fn compute_dispatch_fee(call: &::Call) -> BalanceOf { + let encoded_len = call.using_encoded(|encoded| encoded.len() as u32); + let base_fee = T::TransactionBaseFee::get(); + let byte_fee = T::TransactionByteFee::get(); + base_fee + byte_fee * encoded_len.into() + } +} + +decl_error! { + /// Error for the contracts module. + pub enum Error for Module { + /// A new schedule must have a greater version than the current one. + InvalidScheduleVersion, + /// An origin must be signed or inherent and auxiliary sender only provided on inherent. + InvalidSurchargeClaim, + /// Cannot restore from nonexisting or tombstone contract. + InvalidSourceContract, + /// Cannot restore to nonexisting or alive contract. + InvalidDestinationContract, + /// Tombstones don't match. + InvalidTombstone, + /// An origin TrieId written in the current block. + InvalidContractOrigin + } +} + +decl_module! { + /// Contracts module. + pub struct Module for enum Call where origin: ::Origin { + type Error = Error; + + /// Number of block delay an extrinsic claim surcharge has. + /// + /// When claim surcharge is called by an extrinsic the rent is checked + /// for current_block - delay + const SignedClaimHandicap: T::BlockNumber = T::SignedClaimHandicap::get(); + + /// The minimum amount required to generate a tombstone. + const TombstoneDeposit: BalanceOf = T::TombstoneDeposit::get(); + + /// Size of a contract at the time of instantiaion. This is a simple way to ensure that + /// empty contracts eventually gets deleted. + const StorageSizeOffset: u32 = T::StorageSizeOffset::get(); + + /// Price of a byte of storage per one block interval. Should be greater than 0. + const RentByteFee: BalanceOf = T::RentByteFee::get(); + + /// The amount of funds a contract should deposit in order to offset + /// the cost of one byte. + /// + /// Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day, + /// then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent. + /// But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000, + /// then it would pay 500 BU/day. + const RentDepositOffset: BalanceOf = T::RentDepositOffset::get(); + + /// Reward that is received by the party whose touch has led + /// to removal of a contract. + const SurchargeReward: BalanceOf = T::SurchargeReward::get(); + + /// The fee required to make a transfer. + const TransferFee: BalanceOf = T::TransferFee::get(); + + /// The fee required to create an account. + const CreationFee: BalanceOf = T::CreationFee::get(); + + /// The fee to be paid for making a transaction; the base. + const TransactionBaseFee: BalanceOf = T::TransactionBaseFee::get(); + + /// The fee to be paid for making a transaction; the per-byte portion. + const TransactionByteFee: BalanceOf = T::TransactionByteFee::get(); + + /// The fee required to instantiate a contract instance. A reasonable default value + /// is 21. + const ContractFee: BalanceOf = T::ContractFee::get(); + + /// The base fee charged for calling into a contract. A reasonable default + /// value is 135. + const CallBaseFee: Gas = T::CallBaseFee::get(); + + /// The base fee charged for instantiating a contract. A reasonable default value + /// is 175. + const InstantiateBaseFee: Gas = T::InstantiateBaseFee::get(); + + /// The maximum nesting level of a call/instantiate stack. A reasonable default + /// value is 100. + const MaxDepth: u32 = T::MaxDepth::get(); + + /// The maximum size of a storage value in bytes. A reasonable default is 16 KiB. + const MaxValueSize: u32 = T::MaxValueSize::get(); + + /// The maximum amount of gas that could be expended per block. A reasonable + /// default value is 10_000_000. + const BlockGasLimit: Gas = T::BlockGasLimit::get(); + + fn deposit_event() = default; + + /// Updates the schedule for metering contracts. + /// + /// The schedule must have a greater version than the stored schedule. + pub fn update_schedule(origin, schedule: Schedule) -> DispatchResult { + ensure_root(origin)?; + if >::current_schedule().version >= schedule.version { + Err(Error::::InvalidScheduleVersion)? + } + + Self::deposit_event(RawEvent::ScheduleUpdated(schedule.version)); + CurrentSchedule::put(schedule); + + Ok(()) + } + + /// Stores the given binary Wasm code into the chain's storage and returns its `codehash`. + /// You can instantiate contracts only with stored code. + pub fn put_code( + origin, + #[compact] gas_limit: Gas, + code: Vec + ) -> DispatchResult { + let origin = ensure_signed(origin)?; + + let (mut gas_meter, imbalance) = gas::buy_gas::(&origin, gas_limit)?; + + let schedule = >::current_schedule(); + 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, imbalance); + + result.map(|_| ()).map_err(Into::into) + } + + /// Makes a call to an account, optionally transferring some balance. + /// + /// * If the account is a smart-contract account, the associated code will be + /// executed and any value will be transferred. + /// * If the account is a regular account, any value will be transferred. + /// * If no account exists and the call value is not less than `existential_deposit`, + /// a regular account will be created and any value will be transferred. + pub fn call( + origin, + dest: ::Source, + #[compact] value: BalanceOf, + #[compact] gas_limit: Gas, + data: Vec + ) -> DispatchResult { + let origin = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + + Self::bare_call(origin, dest, value, gas_limit, data) + .map(|_| ()) + .map_err(|e| e.reason.into()) + } + + /// Instantiates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance. + /// + /// Instantiation is executed as follows: + /// + /// - The destination address is computed based on the sender and hash of the code. + /// - The smart-contract account is created at the computed address. + /// - The `ctor_code` is executed in the context of the newly-created account. Buffer returned + /// after the execution is saved as the `code` of the account. That code will be invoked + /// upon any call received by this account. + /// - The contract is initialized. + pub fn instantiate( + origin, + #[compact] endowment: BalanceOf, + #[compact] gas_limit: Gas, + code_hash: CodeHash, + data: Vec + ) -> DispatchResult { + let origin = ensure_signed(origin)?; + + Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { + ctx.instantiate(endowment, gas_meter, &code_hash, data) + .map(|(_address, output)| output) + }) + .map(|_| ()) + .map_err(|e| e.reason.into()) + } + + /// Allows block producers to claim a small reward for evicting a contract. If a block producer + /// fails to do so, a regular users will be allowed to claim the reward. + /// + /// If contract is not evicted as a result of this call, no actions are taken and + /// the sender is not eligible for the reward. + fn claim_surcharge(origin, dest: T::AccountId, aux_sender: Option) { + let origin = origin.into(); + let (signed, rewarded) = match (origin, aux_sender) { + (Ok(frame_system::RawOrigin::Signed(account)), None) => { + (true, account) + }, + (Ok(frame_system::RawOrigin::None), Some(aux_sender)) => { + (false, aux_sender) + }, + _ => Err(Error::::InvalidSurchargeClaim)?, + }; + + // Add some advantage for block producers (who send unsigned extrinsics) by + // adding a handicap: for signed extrinsics we use a slightly older block number + // for the eviction check. This can be viewed as if we pushed regular users back in past. + let handicap = if signed { + T::SignedClaimHandicap::get() + } else { + Zero::zero() + }; + + // If poking the contract has lead to eviction of the contract, give out the rewards. + if rent::try_evict::(&dest, handicap) == rent::RentOutcome::Evicted { + T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?; + } + } + + fn on_finalize() { + GasSpent::kill(); + } + } +} + +/// The possible errors that can happen querying the storage of a contract. +pub enum GetStorageError { + /// The given address doesn't point on a contract. + ContractDoesntExist, + /// The specified contract is a tombstone and thus cannot have any storage. + IsTombstone, +} + +/// Public APIs provided by the contracts module. +impl Module { + /// Perform a call to a specified contract. + /// + /// This function is similar to `Self::call`, but doesn't perform any address lookups and better + /// suitable for calling directly from Rust. + pub fn bare_call( + origin: T::AccountId, + dest: T::AccountId, + value: BalanceOf, + gas_limit: Gas, + input_data: Vec, + ) -> ExecResult { + Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { + ctx.call(dest, value, gas_meter, input_data) + }) + } + + /// Query storage of a specified contract under a specified key. + pub fn get_storage( + address: T::AccountId, + key: [u8; 32], + ) -> sp_std::result::Result>, GetStorageError> { + let contract_info = >::get(&address) + .ok_or(GetStorageError::ContractDoesntExist)? + .get_alive() + .ok_or(GetStorageError::IsTombstone)?; + + let maybe_value = AccountDb::::get_storage( + &DirectAccountDb, + &address, + Some(&contract_info.trie_id), + &key, + ); + Ok(maybe_value) + } +} + +impl Module { + fn execute_wasm( + origin: T::AccountId, + gas_limit: Gas, + func: impl FnOnce(&mut ExecutionContext, &mut GasMeter) -> ExecResult + ) -> ExecResult { + // Pay for the gas upfront. + // + // NOTE: it is very important to avoid any state changes before + // paying for the gas. + let (mut gas_meter, imbalance) = + try_or_exec_error!( + gas::buy_gas::(&origin, gas_limit), + // We don't have a spare buffer here in the first place, so create a new empty one. + Vec::new() + ); + + let cfg = Config::preload(); + let vm = WasmVm::new(&cfg.schedule); + let loader = WasmLoader::new(&cfg.schedule); + let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); + + let result = func(&mut ctx, &mut gas_meter); + + if result.as_ref().map(|output| output.is_success()).unwrap_or(false) { + // Commit all changes that made it thus far into the persistent storage. + DirectAccountDb.commit(ctx.overlay.into_change_set()); + } + + // Refund cost of the unused gas. + // + // NOTE: This should go after the commit to the storage, since the storage changes + // can alter the balance of the caller. + gas::refund_unused_gas::(&origin, gas_meter, imbalance); + + // Execute deferred actions. + ctx.deferred.into_iter().for_each(|deferred| { + use self::exec::DeferredAction::*; + match deferred { + DepositEvent { + topics, + event, + } => >::deposit_event_indexed( + &*topics, + ::Event::from(event).into(), + ), + DispatchRuntimeCall { + origin: who, + call, + } => { + let result = call.dispatch(RawOrigin::Signed(who.clone()).into()); + Self::deposit_event(RawEvent::Dispatched(who, result.is_ok())); + } + RestoreTo { + donor, + dest, + code_hash, + rent_allowance, + delta, + } => { + let _result = Self::restore_to(donor, dest, code_hash, rent_allowance, delta); + } + } + }); + + result + } + + fn restore_to( + origin: T::AccountId, + dest: T::AccountId, + code_hash: CodeHash, + rent_allowance: BalanceOf, + delta: Vec + ) -> DispatchResult { + let mut origin_contract = >::get(&origin) + .and_then(|c| c.get_alive()) + .ok_or(Error::::InvalidSourceContract)?; + + let current_block = >::block_number(); + + if origin_contract.last_write == Some(current_block) { + Err(Error::::InvalidContractOrigin)? + } + + let dest_tombstone = >::get(&dest) + .and_then(|c| c.get_tombstone()) + .ok_or(Error::::InvalidDestinationContract)?; + + let last_write = if !delta.is_empty() { + Some(current_block) + } else { + origin_contract.last_write + }; + + let key_values_taken = delta.iter() + .filter_map(|key| { + child::get_raw( + &origin_contract.trie_id, + origin_contract.child_trie_unique_id(), + &blake2_256(key), + ).map(|value| { + child::kill( + &origin_contract.trie_id, + origin_contract.child_trie_unique_id(), + &blake2_256(key), + ); + + (key, value) + }) + }) + .collect::>(); + + let tombstone = >::new( + // This operation is cheap enough because last_write (delta not included) + // is not this block as it has been checked earlier. + &child::child_root( + &origin_contract.trie_id, + )[..], + code_hash, + ); + + if tombstone != dest_tombstone { + for (key, value) in key_values_taken { + child::put_raw( + &origin_contract.trie_id, + origin_contract.child_trie_unique_id(), + &blake2_256(key), + &value, + ); + } + + return Err(Error::::InvalidTombstone.into()); + } + + origin_contract.storage_size -= key_values_taken.iter() + .map(|(_, value)| value.len() as u32) + .sum::(); + + >::remove(&origin); + >::insert(&dest, ContractInfo::Alive(RawAliveContractInfo { + trie_id: origin_contract.trie_id, + storage_size: origin_contract.storage_size, + code_hash, + rent_allowance, + deduct_block: current_block, + last_write, + })); + + let origin_free_balance = T::Currency::free_balance(&origin); + T::Currency::make_free_balance_be(&origin, >::zero()); + T::Currency::deposit_creating(&dest, origin_free_balance); + + Ok(()) + } +} + +decl_event! { + pub enum Event + where + Balance = BalanceOf, + ::AccountId, + ::Hash + { + /// Transfer happened `from` to `to` with given `value` as part of a `call` or `instantiate`. + Transfer(AccountId, AccountId, Balance), + + /// Contract deployed by address at the specified address. + Instantiated(AccountId, AccountId), + + /// 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), + + /// An event from contract of account. + Contract(AccountId, Vec), + } +} + +decl_storage! { + trait Store for Module as Contract { + /// Gas spent so far in this block. + GasSpent get(fn gas_spent): Gas; + /// Current cost schedule for contracts. + CurrentSchedule get(fn current_schedule) config(): Schedule = Schedule::default(); + /// A mapping from an original code hash to the original code, untouched by instrumentation. + pub PristineCode: map CodeHash => Option>; + /// A mapping between an original code hash and instrumented wasm code, ready for execution. + pub CodeStorage: map CodeHash => Option; + /// The subtrie counter. + pub AccountCounter: u64 = 0; + /// The code associated with a given account. + pub ContractInfoOf: map T::AccountId => Option>; + /// The price of one unit of gas. + GasPrice get(fn gas_price) config(): BalanceOf = 1.into(); + } +} + +impl OnFreeBalanceZero for Module { + fn on_free_balance_zero(who: &T::AccountId) { + if let Some(ContractInfo::Alive(info)) = >::take(who) { + child::kill_storage(&info.trie_id, info.child_trie_unique_id()); + } + } +} + +/// In-memory cache of configuration values. +/// +/// We assume that these values can't be changed in the +/// course of transaction execution. +pub struct Config { + pub schedule: Schedule, + pub existential_deposit: BalanceOf, + pub max_depth: u32, + pub max_value_size: u32, + pub contract_account_instantiate_fee: BalanceOf, + pub account_create_fee: BalanceOf, + pub transfer_fee: BalanceOf, +} + +impl Config { + fn preload() -> Config { + Config { + schedule: >::current_schedule(), + existential_deposit: T::Currency::minimum_balance(), + max_depth: T::MaxDepth::get(), + max_value_size: T::MaxValueSize::get(), + contract_account_instantiate_fee: T::ContractFee::get(), + account_create_fee: T::CreationFee::get(), + transfer_fee: T::TransferFee::get(), + } + } +} + +/// Definition of the cost schedule and other parameterizations for wasm vm. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] +pub struct Schedule { + /// Version of the schedule. + pub version: u32, + + /// Cost of putting a byte of code into storage. + pub put_code_per_byte_cost: Gas, + + /// Gas cost of a growing memory by single page. + pub grow_mem_cost: Gas, + + /// Gas cost of a regular operation. + pub regular_op_cost: Gas, + + /// Gas cost per one byte returned. + pub return_data_per_byte_cost: Gas, + + /// Gas cost to deposit an event; the per-byte portion. + pub event_data_per_byte_cost: Gas, + + /// Gas cost to deposit an event; the cost per topic. + pub event_per_topic_cost: Gas, + + /// Gas cost to deposit an event; the base. + pub event_base_cost: Gas, + + /// Base gas cost to call into a contract. + pub call_base_cost: Gas, + + /// Base gas cost to instantiate a contract. + pub instantiate_base_cost: Gas, + + /// Gas cost per one byte read from the sandbox memory. + pub sandbox_data_read_cost: Gas, + + /// Gas cost per one byte written to the sandbox memory. + pub sandbox_data_write_cost: Gas, + + /// The maximum number of topics supported by an event. + pub max_event_topics: u32, + + /// Maximum allowed stack height. + /// + /// See https://wiki.parity.io/WebAssembly-StackHeight to find out + /// how the stack frame cost is calculated. + pub max_stack_height: u32, + + /// Maximum number of memory pages allowed for a contract. + pub max_memory_pages: u32, + + /// Maximum allowed size of a declared table. + pub max_table_size: u32, + + /// Whether the `ext_println` function is allowed to be used contracts. + /// MUST only be enabled for `dev` chains, NOT for production chains + pub enable_println: bool, + + /// The maximum length of a subject used for PRNG generation. + pub max_subject_len: u32, +} + +impl Default for Schedule { + fn default() -> Schedule { + Schedule { + version: 0, + put_code_per_byte_cost: 1, + grow_mem_cost: 1, + regular_op_cost: 1, + return_data_per_byte_cost: 1, + event_data_per_byte_cost: 1, + event_per_topic_cost: 1, + event_base_cost: 1, + call_base_cost: 135, + instantiate_base_cost: 175, + sandbox_data_read_cost: 1, + sandbox_data_write_cost: 1, + max_event_topics: 4, + max_stack_height: 64 * 1024, + max_memory_pages: 16, + max_table_size: 16 * 1024, + enable_println: false, + max_subject_len: 32, + } + } +} + +/// `SignedExtension` that checks if a transaction would exhausts the block gas limit. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckBlockGasLimit(PhantomData); + +impl Default for CheckBlockGasLimit { + fn default() -> Self { + Self(PhantomData) + } +} + +impl sp_std::fmt::Debug for CheckBlockGasLimit { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckBlockGasLimit") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for CheckBlockGasLimit { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = (); + type DispatchInfo = DispatchInfo; + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn validate( + &self, + _: &Self::AccountId, + call: &Self::Call, + _: Self::DispatchInfo, + _: usize, + ) -> TransactionValidity { + let call = match call.is_sub_type() { + Some(call) => call, + None => return Ok(ValidTransaction::default()), + }; + + match call { + Call::claim_surcharge(_, _) | Call::update_schedule(_) => + Ok(ValidTransaction::default()), + Call::put_code(gas_limit, _) + | Call::call(_, _, gas_limit, _) + | Call::instantiate(_, gas_limit, _, _) + => { + // Check if the specified amount of gas is available in the current block. + // This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`. + let gas_available = T::BlockGasLimit::get() - >::gas_spent(); + if *gas_limit > gas_available { + // gas limit reached, revert the transaction and retry again in the future + InvalidTransaction::ExhaustsResources.into() + } else { + Ok(ValidTransaction::default()) + } + }, + Call::__PhantomItem(_, _) => unreachable!("Variant is never constructed"), + } + } +} diff --git a/srml/contracts/src/rent.rs b/frame/contracts/src/rent.rs similarity index 90% rename from srml/contracts/src/rent.rs rename to frame/contracts/src/rent.rs index ecc5f610313c0..59c8b02d199cf 100644 --- a/srml/contracts/src/rent.rs +++ b/frame/contracts/src/rent.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,10 +15,11 @@ // along with Substrate. If not, see . use crate::{BalanceOf, ContractInfo, ContractInfoOf, TombstoneContractInfo, Trait, AliveContractInfo}; -use sr_primitives::traits::{Bounded, CheckedDiv, CheckedMul, Saturating, Zero, +use sp_runtime::traits::{Bounded, CheckedDiv, CheckedMul, Saturating, Zero, SaturatedConversion}; -use support::traits::{Currency, ExistenceRequirement, Get, WithdrawReason, OnUnbalanced}; -use support::StorageMap; +use frame_support::traits::{Currency, ExistenceRequirement, Get, WithdrawReason, OnUnbalanced}; +use frame_support::StorageMap; +use frame_support::storage::child; #[derive(PartialEq, Eq, Copy, Clone)] #[must_use] @@ -57,7 +58,7 @@ fn try_evict_or_and_pay_rent( Some(ContractInfo::Alive(contract)) => contract, }; - let current_block_number = >::block_number(); + let current_block_number = >::block_number(); // How much block has passed since the last deduction for the contract. let blocks_passed = { @@ -99,7 +100,7 @@ fn try_evict_or_and_pay_rent( if balance < subsistence_threshold { // The contract cannot afford to leave a tombstone, so remove the contract info altogether. >::remove(account); - runtime_io::kill_child_storage(&contract.trie_id); + child::kill_storage(&contract.trie_id, contract.child_trie_unique_id()); return (RentOutcome::Evicted, None); } @@ -119,7 +120,7 @@ fn try_evict_or_and_pay_rent( let can_withdraw_rent = T::Currency::ensure_can_withdraw( account, dues_limited, - WithdrawReason::Fee, + WithdrawReason::Fee.into(), balance.saturating_sub(dues_limited), ) .is_ok(); @@ -129,7 +130,7 @@ fn try_evict_or_and_pay_rent( let imbalance = T::Currency::withdraw( account, dues_limited, - WithdrawReason::Fee, + WithdrawReason::Fee.into(), ExistenceRequirement::KeepAlive, ) .expect( @@ -146,7 +147,9 @@ fn try_evict_or_and_pay_rent( // threshold, so it leaves a tombstone. // Note: this operation is heavy. - let child_storage_root = runtime_io::child_storage_root(&contract.trie_id); + let child_storage_root = child::child_root( + &contract.trie_id, + ); let tombstone = >::new( &child_storage_root[..], @@ -155,7 +158,7 @@ fn try_evict_or_and_pay_rent( let tombstone_info = ContractInfo::Tombstone(tombstone); >::insert(account, &tombstone_info); - runtime_io::kill_child_storage(&contract.trie_id); + child::kill_storage(&contract.trie_id, contract.child_trie_unique_id()); return (RentOutcome::Evicted, Some(tombstone_info)); } diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs new file mode 100644 index 0000000000000..91679a9216a16 --- /dev/null +++ b/frame/contracts/src/tests.rs @@ -0,0 +1,2464 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// TODO: #1417 Add more integration tests +// also remove the #![allow(unused)] below. + +#![allow(unused)] + +use crate::{ + BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, + Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, Schedule, + TrieIdGenerator, CheckBlockGasLimit, account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}, +}; +use assert_matches::assert_matches; +use hex_literal::*; +use codec::{Decode, Encode, KeyedVec}; +use sp_runtime::{ + Perbill, BuildStorage, transaction_validity::{InvalidTransaction, ValidTransaction}, + traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension}, + testing::{Digest, DigestItem, Header, UintAuthorityId, H256}, +}; +use frame_support::{ + assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, + storage::child, StorageMap, StorageValue, traits::{Currency, Get}, + weights::{DispatchInfo, DispatchClass, Weight}, +}; +use std::{cell::RefCell, sync::atomic::{AtomicUsize, Ordering}}; +use sp_core::storage::well_known_keys; +use frame_system::{self as system, EventRecord, Phase}; + +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 frame_support::impl_outer_event; +} + +use pallet_balances as balances; + +impl_outer_event! { + pub enum MetaEvent for Test { + balances, contract, + } +} +impl_outer_origin! { + pub enum Origin for Test where system = frame_system { } +} +impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + balances::Balances, + contract::Contract, + } +} + +thread_local! { + static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); + static TRANSFER_FEE: RefCell = RefCell::new(0); + static INSTANTIATION_FEE: RefCell = RefCell::new(0); + static BLOCK_GAS_LIMIT: RefCell = RefCell::new(0); +} + +pub struct ExistentialDeposit; +impl Get for ExistentialDeposit { + fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } +} + +pub struct TransferFee; +impl Get for TransferFee { + fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) } +} + +pub struct CreationFee; +impl Get for CreationFee { + fn get() -> u64 { INSTANTIATION_FEE.with(|v| *v.borrow()) } +} + +pub struct BlockGasLimit; +impl Get for BlockGasLimit { + fn get() -> u64 { BLOCK_GAS_LIMIT.with(|v| *v.borrow()) } +} + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = MetaEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); +} +impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = Contract; + type OnReapAccount = System; + type OnNewAccount = (); + type Event = MetaEvent; + type DustRemoval = (); + type TransferPayment = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} +parameter_types! { + pub const MinimumPeriod: u64 = 1; +} +impl pallet_timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; +} +parameter_types! { + pub const SignedClaimHandicap: u64 = 2; + pub const TombstoneDeposit: u64 = 16; + pub const StorageSizeOffset: u32 = 8; + pub const RentByteFee: u64 = 4; + pub const RentDepositOffset: u64 = 10_000; + pub const SurchargeReward: u64 = 150; + pub const TransactionBaseFee: u64 = 2; + pub const TransactionByteFee: u64 = 6; + pub const ContractFee: u64 = 21; + pub const CallBaseFee: u64 = 135; + pub const InstantiateBaseFee: u64 = 175; + pub const MaxDepth: u32 = 100; + pub const MaxValueSize: u32 = 16_384; +} +impl Trait for Test { + type Currency = Balances; + type Time = Timestamp; + type Randomness = Randomness; + type Call = Call; + type DetermineContractAddress = DummyContractAddressFor; + type Event = MetaEvent; + type ComputeDispatchFee = DummyComputeDispatchFee; + type TrieIdGenerator = DummyTrieIdGenerator; + type GasPayment = (); + type RentPayment = (); + type SignedClaimHandicap = SignedClaimHandicap; + type TombstoneDeposit = TombstoneDeposit; + type StorageSizeOffset = StorageSizeOffset; + type RentByteFee = RentByteFee; + type RentDepositOffset = RentDepositOffset; + type SurchargeReward = SurchargeReward; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type ContractFee = ContractFee; + type CallBaseFee = CallBaseFee; + type InstantiateBaseFee = InstantiateBaseFee; + type MaxDepth = MaxDepth; + type MaxValueSize = MaxValueSize; + type BlockGasLimit = BlockGasLimit; +} + +type Balances = pallet_balances::Module; +type Timestamp = pallet_timestamp::Module; +type Contract = Module; +type System = frame_system::Module; +type Randomness = pallet_randomness_collective_flip::Module; + +pub struct DummyContractAddressFor; +impl ContractAddressFor for DummyContractAddressFor { + fn contract_address_for(_code_hash: &H256, _data: &[u8], origin: &u64) -> u64 { + *origin + 1 + } +} + +pub struct DummyTrieIdGenerator; +impl TrieIdGenerator for DummyTrieIdGenerator { + fn trie_id(account_id: &u64) -> TrieId { + use sp_core::storage::well_known_keys; + + let new_seed = super::AccountCounter::mutate(|v| { + *v = v.wrapping_add(1); + *v + }); + + // TODO: see https://github.com/paritytech/substrate/issues/2325 + let mut res = vec![]; + res.extend_from_slice(well_known_keys::CHILD_STORAGE_KEY_PREFIX); + res.extend_from_slice(b"default:"); + res.extend_from_slice(&new_seed.to_le_bytes()); + res.extend_from_slice(&account_id.to_le_bytes()); + res + } +} + +pub struct DummyComputeDispatchFee; +impl ComputeDispatchFee for DummyComputeDispatchFee { + fn compute_dispatch_fee(call: &Call) -> u64 { + 69 + } +} + +const ALICE: u64 = 1; +const BOB: u64 = 2; +const CHARLIE: u64 = 3; +const DJANGO: u64 = 4; + +pub struct ExtBuilder { + existential_deposit: u64, + gas_price: u64, + block_gas_limit: u64, + transfer_fee: u64, + instantiation_fee: u64, +} +impl Default for ExtBuilder { + fn default() -> Self { + Self { + existential_deposit: 0, + gas_price: 2, + block_gas_limit: 100_000_000, + transfer_fee: 0, + instantiation_fee: 0, + } + } +} +impl ExtBuilder { + pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { + self.existential_deposit = existential_deposit; + self + } + pub fn gas_price(mut self, gas_price: u64) -> Self { + self.gas_price = gas_price; + self + } + pub fn block_gas_limit(mut self, block_gas_limit: u64) -> Self { + self.block_gas_limit = block_gas_limit; + self + } + pub fn transfer_fee(mut self, transfer_fee: u64) -> Self { + self.transfer_fee = transfer_fee; + self + } + pub fn instantiation_fee(mut self, instantiation_fee: u64) -> Self { + self.instantiation_fee = instantiation_fee; + self + } + pub fn set_associated_consts(&self) { + EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); + TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee); + INSTANTIATION_FEE.with(|v| *v.borrow_mut() = self.instantiation_fee); + BLOCK_GAS_LIMIT.with(|v| *v.borrow_mut() = self.block_gas_limit); + } + pub fn build(self) -> sp_io::TestExternalities { + self.set_associated_consts(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + GenesisConfig:: { + current_schedule: Schedule { + enable_println: true, + ..Default::default() + }, + gas_price: self.gas_price, + }.assimilate_storage(&mut t).unwrap(); + sp_io::TestExternalities::new(t) + } +} + +/// Generate Wasm binary and code hash from wabt source. +fn compile_module(wabt_module: &str) + -> Result<(Vec, ::Output), wabt::Error> + where T: frame_system::Trait +{ + let wasm = wabt::wat2wasm(wabt_module)?; + let code_hash = T::Hashing::hash(&wasm); + Ok((wasm, code_hash)) +} + +// Perform a simple transfer to a non-existent account supplying way more gas than needed. +// Then we check that the all unused gas is refunded. +#[test] +fn refunds_unused_gas() { + ExtBuilder::default().gas_price(2).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 100_000_000); + + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, Vec::new())); + + // 2 * 135 - gas price multiplied by the call base fee. + assert_eq!(Balances::free_balance(&ALICE), 100_000_000 - (2 * 135)); + }); +} + +#[test] +fn account_removal_removes_storage() { + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let trie_id1 = ::TrieIdGenerator::trie_id(&1); + let trie_id2 = ::TrieIdGenerator::trie_id(&2); + let key1 = &[1; 32]; + let key2 = &[2; 32]; + + // Set up two accounts with free balance above the existential threshold. + { + Balances::deposit_creating(&1, 110); + ContractInfoOf::::insert(1, &ContractInfo::Alive(RawAliveContractInfo { + trie_id: trie_id1.clone(), + storage_size: ::StorageSizeOffset::get(), + deduct_block: System::block_number(), + code_hash: H256::repeat_byte(1), + rent_allowance: 40, + last_write: None, + })); + + let mut overlay = OverlayAccountDb::::new(&DirectAccountDb); + overlay.set_storage(&1, key1.clone(), Some(b"1".to_vec())); + overlay.set_storage(&1, key2.clone(), Some(b"2".to_vec())); + DirectAccountDb.commit(overlay.into_change_set()); + + Balances::deposit_creating(&2, 110); + ContractInfoOf::::insert(2, &ContractInfo::Alive(RawAliveContractInfo { + trie_id: trie_id2.clone(), + storage_size: ::StorageSizeOffset::get(), + deduct_block: System::block_number(), + code_hash: H256::repeat_byte(2), + rent_allowance: 40, + last_write: None, + })); + + let mut overlay = OverlayAccountDb::::new(&DirectAccountDb); + overlay.set_storage(&2, key1.clone(), Some(b"3".to_vec())); + overlay.set_storage(&2, key2.clone(), Some(b"4".to_vec())); + DirectAccountDb.commit(overlay.into_change_set()); + } + + // Transfer funds from account 1 of such amount that after this transfer + // the balance of account 1 will be below the existential threshold. + // + // This should lead to the removal of all storage associated with this account. + assert_ok!(Balances::transfer(Origin::signed(1), 2, 20)); + + // Verify that all entries from account 1 is removed, while + // entries from account 2 is in place. + { + assert!(>::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key1).is_none()); + assert!(>::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key2).is_none()); + + assert_eq!( + >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key1), + Some(b"3".to_vec()) + ); + assert_eq!( + >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key2), + Some(b"4".to_vec()) + ); + } + }); +} + +const CODE_RETURN_FROM_START_FN: &str = r#" +(module + (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (start $start) + (func $start + (call $ext_deposit_event + (i32.const 0) ;; The topics buffer + (i32.const 0) ;; The topics buffer's length + (i32.const 8) ;; The data buffer + (i32.const 4) ;; The data buffer's length + ) + (call $ext_return + (i32.const 8) + (i32.const 4) + ) + (unreachable) + ) + + (func (export "call") + (unreachable) + ) + (func (export "deploy")) + + (data (i32.const 8) "\01\02\03\04") +) +"#; + +#[test] +fn instantiate_and_call_and_deposit_event() { + let (wasm, code_hash) = compile_module::(CODE_RETURN_FROM_START_FN).unwrap(); + + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Check at the end to get hash on error easily + let creation = Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, + code_hash.into(), + vec![], + ); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(pallet_balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + pallet_balances::RawEvent::NewAccount(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Contract(BOB, vec![1, 2, 3, 4])), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + } + ]); + + assert_ok!(creation); + assert!(ContractInfoOf::::exists(BOB)); + }); +} + +const CODE_DISPATCH_CALL: &str = r#" +(module + (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "call") + (call $ext_dispatch_call + (i32.const 8) ;; Pointer to the start of encoded call buffer + (i32.const 11) ;; Length of the buffer + ) + ) + (func (export "deploy")) + + (data (i32.const 8) "\00\00\03\00\00\00\00\00\00\00\C8") +) +"#; + +#[test] +fn dispatch_call() { + // This test can fail due to the encoding changes. In case it becomes too annoying + // let's rewrite so as we use this module controlled call or we serialize it in runtime. + let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); + assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); + + let (wasm, code_hash) = compile_module::(CODE_DISPATCH_CALL).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Let's keep this assert even though it's redundant. If you ever need to update the + // wasm source this test will fail and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(pallet_balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, + code_hash.into(), + vec![], + )); + + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, // newly created account + 0, + 100_000, + vec![], + )); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(pallet_balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + pallet_balances::RawEvent::NewAccount(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + }, + + // Dispatching the call. + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + pallet_balances::RawEvent::NewAccount(CHARLIE, 50) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + pallet_balances::RawEvent::Transfer(BOB, CHARLIE, 50, 0) + ), + topics: vec![], + }, + + // Event emited as a result of dispatch. + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Dispatched(BOB, true)), + topics: vec![], + } + ]); + }); +} + +const CODE_DISPATCH_CALL_THEN_TRAP: &str = r#" +(module + (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "call") + (call $ext_dispatch_call + (i32.const 8) ;; Pointer to the start of encoded call buffer + (i32.const 11) ;; Length of the buffer + ) + (unreachable) ;; trap so that the top level transaction fails + ) + (func (export "deploy")) + + (data (i32.const 8) "\00\00\03\00\00\00\00\00\00\00\C8") +) +"#; + +#[test] +fn dispatch_call_not_dispatched_after_top_level_transaction_failure() { + // This test can fail due to the encoding changes. In case it becomes too annoying + // let's rewrite so as we use this module controlled call or we serialize it in runtime. + let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); + assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); + + let (wasm, code_hash) = compile_module::(CODE_DISPATCH_CALL_THEN_TRAP).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Let's keep this assert even though it's redundant. If you ever need to update the + // wasm source this test will fail and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(pallet_balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, + code_hash.into(), + vec![], + )); + + // Call the newly instantiated contract. The contract is expected to dispatch a call + // and then trap. + assert_err!( + Contract::call( + Origin::signed(ALICE), + BOB, // newly created account + 0, + 100_000, + vec![], + ), + "during execution" + ); + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(pallet_balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + pallet_balances::RawEvent::NewAccount(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + }, + // ABSENCE of events which would be caused by dispatched Balances::transfer call + ]); + }); +} + +const CODE_SET_RENT: &str = r#" +(module + (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) + (import "env" "ext_set_rent_allowance" (func $ext_set_rent_allowance (param i32 i32))) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; insert a value of 4 bytes into storage + (func $call_0 + (call $ext_set_storage + (i32.const 1) + (i32.const 1) + (i32.const 0) + (i32.const 4) + ) + ) + + ;; remove the value inserted by call_1 + (func $call_1 + (call $ext_set_storage + (i32.const 1) + (i32.const 0) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; transfer 50 to ALICE + (func $call_2 + (call $ext_dispatch_call + (i32.const 68) + (i32.const 11) + ) + ) + + ;; do nothing + (func $call_else) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + ;; Dispatch the call according to input size + (func (export "call") + (local $input_size i32) + (set_local $input_size + (call $ext_scratch_size) + ) + (block $IF_ELSE + (block $IF_2 + (block $IF_1 + (block $IF_0 + (br_table $IF_0 $IF_1 $IF_2 $IF_ELSE + (get_local $input_size) + ) + (unreachable) + ) + (call $call_0) + return + ) + (call $call_1) + return + ) + (call $call_2) + return + ) + (call $call_else) + ) + + ;; Set into storage a 4 bytes value + ;; Set call set_rent_allowance with input + (func (export "deploy") + (local $input_size i32) + (set_local $input_size + (call $ext_scratch_size) + ) + (call $ext_set_storage + (i32.const 0) + (i32.const 1) + (i32.const 0) + (i32.const 4) + ) + (call $ext_scratch_read + (i32.const 0) + (i32.const 0) + (get_local $input_size) + ) + (call $ext_set_rent_allowance + (i32.const 0) + (get_local $input_size) + ) + ) + + ;; Encoding of 10 in balance + (data (i32.const 0) "\28") + + ;; Encoding of call transfer 50 to CHARLIE + (data (i32.const 68) "\00\00\03\00\00\00\00\00\00\00\C8") +) +"#; + +/// Input data for each call in set_rent code +mod call { + pub fn set_storage_4_byte() -> Vec { vec![] } + pub fn remove_storage_4_byte() -> Vec { vec![0] } + pub fn transfer() -> Vec { vec![0, 0] } + pub fn null() -> Vec { vec![0, 0, 0] } +} + +/// Test correspondence of set_rent code and its hash. +/// Also test that encoded extrinsic in code correspond to the correct transfer +#[test] +fn test_set_rent_code_and_hash() { + // This test can fail due to the encoding changes. In case it becomes too annoying + // let's rewrite so as we use this module controlled call or we serialize it in runtime. + let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50))); + assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); + + let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // If you ever need to update the wasm source this test will fail + // and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(pallet_balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + }); +} + +#[test] +fn storage_size() { + let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + + // Storage size + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); + + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::set_storage_4_byte())); + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4 + 4); + + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::remove_storage_4_byte())); + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); + }); +} + +fn initialize_block(number: u64) { + System::initialize( + &number, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + Default::default(), + ); +} + +#[test] +fn deduct_blocks() { + let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000); + + // Advance 4 blocks + initialize_block(5); + + // Trigger rent through call + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Check result + let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset + * 4 // rent byte price + * 4; // blocks to rent + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent); + assert_eq!(bob_contract.deduct_block, 5); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent); + + // Advance 7 blocks more + initialize_block(12); + + // Trigger rent through call + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Check result + let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset + * 4 // rent byte price + * 7; // blocks to rent + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); + assert_eq!(bob_contract.deduct_block, 12); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); + + // Second call on same block should have no effect on rent + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); + assert_eq!(bob_contract.deduct_block, 12); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); + }); +} + +#[test] +fn call_contract_removals() { + removals(|| { + // Call on already-removed account might fail, and this is fine. + Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()); + true + }); +} + +#[test] +fn inherent_claim_surcharge_contract_removals() { + removals(|| Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok()); +} + +#[test] +fn signed_claim_surcharge_contract_removals() { + removals(|| Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok()); +} + +#[test] +fn claim_surcharge_malus() { + // Test surcharge malus for inherent + claim_surcharge(4, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(3, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(2, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(1, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), false); + + // Test surcharge malus for signed + claim_surcharge(4, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), true); + claim_surcharge(3, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); + claim_surcharge(2, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); + claim_surcharge(1, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); +} + +/// Claim surcharge with the given trigger_call at the given blocks. +/// if removes is true then assert that the contract is a tombstonedead +fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) { + let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Advance blocks + initialize_block(blocks); + + // Trigger rent through call + assert!(trigger_call()); + + if removes { + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + } else { + assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some()); + } + }); +} + +/// Test for all kind of removals for the given trigger: +/// * if balance is reached and balance > subsistence threshold +/// * if allowance is exceeded +/// * if balance is reached and balance < subsistence threshold +fn removals(trigger_call: impl Fn() -> bool) { + let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + + // Balance reached and superior to subsistence threshold + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/; + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); + assert_eq!(Balances::free_balance(&BOB), 100); + + // Advance blocks + initialize_block(10); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(&BOB), subsistence_threshold); + + // Advance blocks + initialize_block(20); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(&BOB), subsistence_threshold); + }); + + // Allowance exceeded + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 1_000, + 100_000, code_hash.into(), + ::Balance::from(100u32).encode() // rent allowance + )); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100); + assert_eq!(Balances::free_balance(&BOB), 1_000); + + // Advance blocks + initialize_block(10); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + // Balance should be initial balance - initial rent_allowance + assert_eq!(Balances::free_balance(&BOB), 900); + + // Advance blocks + initialize_block(20); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(&BOB), 900); + }); + + // Balance reached and inferior to subsistence threshold + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 50+Balances::minimum_balance(), + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); + assert_eq!(Balances::free_balance(&BOB), 50 + Balances::minimum_balance()); + + // Transfer funds + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::transfer())); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); + assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); + + // Advance blocks + initialize_block(10); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).is_none()); + assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); + + // Advance blocks + initialize_block(20); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).is_none()); + assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); + }); +} + +#[test] +fn call_removed_contract() { + let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + + // Balance reached and superior to subsistence threshold + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Calling contract should succeed. + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Advance blocks + initialize_block(10); + + // Calling contract should remove contract and fail. + assert_err!( + Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), + "contract has been evicted" + ); + + // Subsequent contract calls should also fail. + assert_err!( + Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), + "contract has been evicted" + ); + }) +} + +const CODE_CHECK_DEFAULT_RENT_ALLOWANCE: &str = r#" +(module + (import "env" "ext_rent_allowance" (func $ext_rent_allowance)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call")) + + (func (export "deploy") + ;; fill the scratch buffer with the rent allowance. + (call $ext_rent_allowance) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to >::max_value(). + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 0xFFFFFFFFFFFFFFFF) + ) + ) + ) +) +"#; + +#[test] +fn default_rent_allowance_on_instantiate() { + let (wasm, code_hash) = compile_module::(CODE_CHECK_DEFAULT_RENT_ALLOWANCE).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, + code_hash.into(), + vec![], + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, >::max_value()); + + // Advance blocks + initialize_block(5); + + // Trigger rent through call + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Check contract is still alive + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive(); + assert!(bob_contract.is_some()) + }); +} + +const CODE_RESTORATION: &str = r#" +(module + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) + (import "env" "ext_restore_to" (func $ext_restore_to (param i32 i32 i32 i32 i32 i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "call") + (call $ext_restore_to + ;; Pointer and length of the encoded dest buffer. + (i32.const 256) + (i32.const 8) + ;; Pointer and length of the encoded code hash buffer + (i32.const 264) + (i32.const 32) + ;; Pointer and length of the encoded rent_allowance buffer + (i32.const 296) + (i32.const 8) + ;; Pointer and number of items in the delta buffer. + ;; This buffer specifies multiple keys for removal before restoration. + (i32.const 100) + (i32.const 1) + ) + ) + (func (export "deploy") + ;; Data to restore + (call $ext_set_storage + (i32.const 0) + (i32.const 1) + (i32.const 0) + (i32.const 4) + ) + + ;; ACL + (call $ext_set_storage + (i32.const 100) + (i32.const 1) + (i32.const 0) + (i32.const 4) + ) + ) + + ;; Data to restore + (data (i32.const 0) "\28") + + ;; Buffer that has ACL storage keys. + (data (i32.const 100) "\01") + + ;; Address of bob + (data (i32.const 256) "\02\00\00\00\00\00\00\00") + + ;; Code hash of SET_RENT + (data (i32.const 264) + "\14\eb\65\3c\86\98\d6\b2\3d\8d\3c\4a\54\c6\c4\71" + "\b9\fc\19\36\df\ca\a0\a1\f2\dc\ad\9d\e5\36\0b\25" + ) + + ;; Rent allowance + (data (i32.const 296) "\32\00\00\00\00\00\00\00") +) +"#; + +#[test] +fn restorations_dirty_storage_and_different_storage() { + restoration(true, true); +} + +#[test] +fn restorations_dirty_storage() { + restoration(false, true); +} + +#[test] +fn restoration_different_storage() { + restoration(true, false); +} + +#[test] +fn restoration_success() { + restoration(false, false); +} + +fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: bool) { + let (set_rent_wasm, set_rent_code_hash) = compile_module::(CODE_SET_RENT).unwrap(); + let (restoration_wasm, restoration_code_hash) = + compile_module::(CODE_RESTORATION).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, restoration_wasm)); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, set_rent_wasm)); + + // If you ever need to update the wasm source this test will fail + // and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(pallet_balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(restoration_code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(set_rent_code_hash.into())), + topics: vec![], + }, + ]); + + // Create an account with address `BOB` with code `CODE_SET_RENT`. + // The input parameter sets the rent allowance to 0. + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, + set_rent_code_hash.into(), + ::Balance::from(0u32).encode() + )); + + // Check if `BOB` was created successfully and that the rent allowance is + // set to 0. + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 0); + + if test_different_storage { + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, 0, 100_000, + call::set_storage_4_byte()) + ); + } + + // Advance 4 blocks, to the 5th. + initialize_block(5); + + // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0 + // we expect that it will get removed leaving tombstone. + assert_err!( + Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), + "contract has been evicted" + ); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + + /// Create another account with the address `DJANGO` with `CODE_RESTORATION`. + /// + /// Note that we can't use `ALICE` for creating `DJANGO` so we create yet another + /// account `CHARLIE` and create `DJANGO` with it. + Balances::deposit_creating(&CHARLIE, 1_000_000); + assert_ok!(Contract::instantiate( + Origin::signed(CHARLIE), + 30_000, + 100_000, + restoration_code_hash.into(), + ::Balance::from(0u32).encode() + )); + + // Before performing a call to `DJANGO` save its original trie id. + let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap() + .get_alive().unwrap().trie_id; + + if !test_restore_to_with_dirty_storage { + // Advance 1 block, to the 6th. + initialize_block(6); + } + + // Perform a call to `DJANGO`. This should either perform restoration successfully or + // fail depending on the test parameters. + assert_ok!(Contract::call( + Origin::signed(ALICE), + DJANGO, + 0, + 100_000, + vec![], + )); + + if test_different_storage || test_restore_to_with_dirty_storage { + // Parametrization of the test imply restoration failure. Check that `DJANGO` aka + // restoration contract is still in place and also that `BOB` doesn't exist. + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + let django_contract = ContractInfoOf::::get(DJANGO).unwrap() + .get_alive().unwrap(); + assert_eq!(django_contract.storage_size, 16); + assert_eq!(django_contract.trie_id, django_trie_id); + assert_eq!(django_contract.deduct_block, System::block_number()); + } else { + // Here we expect that the restoration is succeeded. Check that the restoration + // contract `DJANGO` ceased to exist and that `BOB` returned back. + println!("{:?}", ContractInfoOf::::get(BOB)); + let bob_contract = ContractInfoOf::::get(BOB).unwrap() + .get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 50); + assert_eq!(bob_contract.storage_size, 12); + assert_eq!(bob_contract.trie_id, django_trie_id); + assert_eq!(bob_contract.deduct_block, System::block_number()); + assert!(ContractInfoOf::::get(DJANGO).is_none()); + } + }); +} + +const CODE_STORAGE_SIZE: &str = r#" +(module + (import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32))) + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 16 16)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 4) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_read + (i32.const 32) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 4) ;; Count of bytes to copy. + ) + + ;; place a garbage value in storage, the size of which is specified by the call input. + (call $ext_set_storage + (i32.const 0) ;; Pointer to storage key + (i32.const 1) ;; Value is not null + (i32.const 0) ;; Pointer to value + (i32.load (i32.const 32)) ;; Size of value + ) + + (call $assert + (i32.eq + (call $ext_get_storage + (i32.const 0) ;; Pointer to storage key + ) + (i32.const 0) + ) + ) + + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.load (i32.const 32)) + ) + ) + ) + + (func (export "deploy")) + + (data (i32.const 0) "\01") ;; Storage key (32 B) +) +"#; + +#[test] +fn storage_max_value_limit() { + let (wasm, code_hash) = compile_module::(CODE_STORAGE_SIZE).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, + code_hash.into(), + vec![], + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, >::max_value()); + + // Call contract with allowed storage value. + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + Encode::encode(&self::MaxValueSize::get()), + )); + + // Call contract with too large a storage value. + assert_err!( + Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + Encode::encode(&(self::MaxValueSize::get() + 1)), + ), + "during execution" + ); + }); +} + +const CODE_RETURN_WITH_DATA: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_scratch_write" (func $ext_scratch_write (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; Deploy routine is the same as call. + (func (export "deploy") (result i32) + (call $call) + ) + + ;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data. + (func $call (export "call") (result i32) + (local $buf_size i32) + (local $exit_status i32) + + ;; Find out the size of the scratch buffer + (set_local $buf_size (call $ext_scratch_size)) + + ;; Copy scratch buffer into this contract memory. + (call $ext_scratch_read + (i32.const 0) ;; The pointer where to store the scratch buffer contents, + (i32.const 0) ;; Offset from the start of the scratch buffer. + (get_local $buf_size) ;; Count of bytes to copy. + ) + + ;; Copy all but the first 4 bytes of the input data as the output data. + (call $ext_scratch_write + (i32.const 4) ;; Pointer to the data to return. + (i32.sub ;; Count of bytes to copy. + (get_local $buf_size) + (i32.const 4) + ) + ) + + ;; Return the first 4 bytes of the input data as the exit status. + (i32.load (i32.const 0)) + ) +) +"#; + +const CODE_CALLER_CONTRACT: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_balance" (func $ext_balance)) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "ext_println" (func $ext_println (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func $current_balance (param $sp i32) (result i64) + (call $ext_balance) + (call $assert + (i32.eq (call $ext_scratch_size) (i32.const 8)) + ) + (call $ext_scratch_read + (i32.sub (get_local $sp) (i32.const 8)) + (i32.const 0) + (i32.const 8) + ) + (i64.load (i32.sub (get_local $sp) (i32.const 8))) + ) + + (func (export "deploy")) + + (func (export "call") + (local $sp i32) + (local $exit_code i32) + (local $balance i64) + + ;; Input data is the code hash of the contract to be deployed. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 32) + ) + ) + + ;; Copy code hash from scratch buffer into this contract's memory. + (call $ext_scratch_read + (i32.const 24) ;; The pointer where to store the scratch buffer contents, + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 32) ;; Count of bytes to copy. + ) + + ;; Read current balance into local variable. + (set_local $sp (i32.const 1024)) + (set_local $balance + (call $current_balance (get_local $sp)) + ) + + ;; Fail to deploy the contract since it returns a non-zero exit status. + (set_local $exit_code + (call $ext_instantiate + (i32.const 24) ;; Pointer to the code hash. + (i32.const 32) ;; Length of the code hash. + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 9) ;; Pointer to input data buffer address + (i32.const 7) ;; Length of input data buffer + ) + ) + + ;; Check non-zero exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0x11)) + ) + + ;; Check that scratch buffer is empty since contract instantiation failed. + (call $assert + (i32.eq (call $ext_scratch_size) (i32.const 0)) + ) + + ;; Check that balance has not changed. + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Fail to deploy the contract due to insufficient gas. + (set_local $exit_code + (call $ext_instantiate + (i32.const 24) ;; Pointer to the code hash. + (i32.const 32) ;; Length of the code hash. + (i64.const 200) ;; How much gas to devote for the execution. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 8) ;; Pointer to input data buffer address + (i32.const 8) ;; Length of input data buffer + ) + ) + + ;; Check for special trap exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0x0100)) + ) + + ;; Check that scratch buffer is empty since contract instantiation failed. + (call $assert + (i32.eq (call $ext_scratch_size) (i32.const 0)) + ) + + ;; Check that balance has not changed. + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Deploy the contract successfully. + (set_local $exit_code + (call $ext_instantiate + (i32.const 24) ;; Pointer to the code hash. + (i32.const 32) ;; Length of the code hash. + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 8) ;; Pointer to input data buffer address + (i32.const 8) ;; Length of input data buffer + ) + ) + + ;; Check for success exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0x00)) + ) + + ;; Check that scratch buffer contains the address of the new contract. + (call $assert + (i32.eq (call $ext_scratch_size) (i32.const 8)) + ) + + ;; Copy contract address from scratch buffer into this contract's memory. + (call $ext_scratch_read + (i32.const 16) ;; The pointer where to store the scratch buffer contents, + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; Check that balance has been deducted. + (set_local $balance + (i64.sub (get_local $balance) (i64.load (i32.const 0))) + ) + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Call the new contract and expect it to return failing exit code. + (set_local $exit_code + (call $ext_call + (i32.const 16) ;; Pointer to "callee" address. + (i32.const 8) ;; Length of "callee" address. + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 9) ;; Pointer to input data buffer address + (i32.const 7) ;; Length of input data buffer + ) + ) + + ;; Check non-zero exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0x11)) + ) + + ;; Check that scratch buffer contains the expected return data. + (call $assert + (i32.eq (call $ext_scratch_size) (i32.const 3)) + ) + (i32.store + (i32.sub (get_local $sp) (i32.const 4)) + (i32.const 0) + ) + (call $ext_scratch_read + (i32.sub (get_local $sp) (i32.const 4)) + (i32.const 0) + (i32.const 3) + ) + (call $assert + (i32.eq + (i32.load (i32.sub (get_local $sp) (i32.const 4))) + (i32.const 0x00776655) + ) + ) + + ;; Check that balance has not changed. + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Fail to call the contract due to insufficient gas. + (set_local $exit_code + (call $ext_call + (i32.const 16) ;; Pointer to "callee" address. + (i32.const 8) ;; Length of "callee" address. + (i64.const 100) ;; How much gas to devote for the execution. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 8) ;; Pointer to input data buffer address + (i32.const 8) ;; Length of input data buffer + ) + ) + + ;; Check for special trap exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0x0100)) + ) + + ;; Check that scratch buffer is empty since call trapped. + (call $assert + (i32.eq (call $ext_scratch_size) (i32.const 0)) + ) + + ;; Check that balance has not changed. + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + + ;; Call the contract successfully. + (set_local $exit_code + (call $ext_call + (i32.const 16) ;; Pointer to "callee" address. + (i32.const 8) ;; Length of "callee" address. + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 8) ;; Pointer to input data buffer address + (i32.const 8) ;; Length of input data buffer + ) + ) + + ;; Check for success exit status. + (call $assert + (i32.eq (get_local $exit_code) (i32.const 0x00)) + ) + + ;; Check that scratch buffer contains the expected return data. + (call $assert + (i32.eq (call $ext_scratch_size) (i32.const 4)) + ) + (i32.store + (i32.sub (get_local $sp) (i32.const 4)) + (i32.const 0) + ) + (call $ext_scratch_read + (i32.sub (get_local $sp) (i32.const 4)) + (i32.const 0) + (i32.const 4) + ) + (call $assert + (i32.eq + (i32.load (i32.sub (get_local $sp) (i32.const 4))) + (i32.const 0x77665544) + ) + ) + + ;; Check that balance has been deducted. + (set_local $balance + (i64.sub (get_local $balance) (i64.load (i32.const 0))) + ) + (call $assert + (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) + ) + ) + + (data (i32.const 0) "\00\80") ;; The value to transfer on instantiation and calls. + ;; Chosen to be greater than existential deposit. + (data (i32.const 8) "\00\11\22\33\44\55\66\77") ;; The input data to instantiations and calls. +) +"#; + +#[test] +fn deploy_and_call_other_contract() { + let (callee_wasm, callee_code_hash) = compile_module::(CODE_RETURN_WITH_DATA).unwrap(); + let (caller_wasm, caller_code_hash) = compile_module::(CODE_CALLER_CONTRACT).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, caller_wasm)); + + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100_000, + 100_000, + caller_code_hash.into(), + vec![], + )); + + // Call BOB contract, which attempts to instantiate and call the callee contract and + // makes various assertions on the results from those calls. + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 200_000, + callee_code_hash.as_ref().to_vec(), + )); + }); +} + +const CODE_SELF_DESTRUCT: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_address" (func $ext_address)) + (import "env" "ext_balance" (func $ext_balance)) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "deploy")) + + (func (export "call") + ;; If the input data is not empty, then recursively call self with empty input data. + ;; This should trap instead of self-destructing since a contract cannot be removed live in + ;; the execution stack cannot be removed. If the recursive call traps, then trap here as + ;; well. + (if (call $ext_scratch_size) + (then + (call $ext_address) + + ;; Expect address to be 8 bytes. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; Read own address into memory. + (call $ext_scratch_read + (i32.const 16) ;; Pointer to write address to + (i32.const 0) ;; Offset into scrach buffer + (i32.const 8) ;; Length of encoded address + ) + + ;; Recursively call self with empty imput data. + (call $assert + (i32.eq + (call $ext_call + (i32.const 16) ;; Pointer to own address + (i32.const 8) ;; Length of own address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + ) + ) + + ;; Send entire remaining balance to the 0 address. + (call $ext_balance) + + ;; Balance should be encoded as a u64. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; Read balance into memory. + (call $ext_scratch_read + (i32.const 8) ;; Pointer to write balance to + (i32.const 0) ;; Offset into scrach buffer + (i32.const 8) ;; Length of encoded balance + ) + + ;; Self-destruct by sending full balance to the 0 address. + (call $assert + (i32.eq + (call $ext_call + (i32.const 0) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + ) +) +"#; + +#[test] +fn self_destruct_by_draining_balance() { + let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Instantiate the BOB contract. + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100_000, + 100_000, + code_hash.into(), + vec![], + )); + + // Check that the BOB contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB with no input data, forcing it to self-destruct. + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + vec![], + )); + + // Check that BOB is now dead. + assert!(ContractInfoOf::::get(BOB).is_none()); + }); +} + +#[test] +fn cannot_self_destruct_while_live() { + let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Instantiate the BOB contract. + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100_000, + 100_000, + code_hash.into(), + vec![], + )); + + // Check that the BOB contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB with input data, forcing it make a recursive call to itself to + // self-destruct, resulting in a trap. + assert_err!( + Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + vec![0], + ), + "during execution" + ); + + // Check that BOB is still alive. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + }); +} + +const CODE_DESTROY_AND_TRANSFER: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32))) + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "deploy") + ;; Input data is the code hash of the contract to be deployed. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 32) + ) + ) + + ;; Copy code hash from scratch buffer into this contract's memory. + (call $ext_scratch_read + (i32.const 48) ;; The pointer where to store the scratch buffer contents, + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 32) ;; Count of bytes to copy. + ) + + ;; Deploy the contract with the provided code hash. + (call $assert + (i32.eq + (call $ext_instantiate + (i32.const 48) ;; Pointer to the code hash. + (i32.const 32) ;; Length of the code hash. + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + + ;; Read the address of the instantiated contract into memory. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + (call $ext_scratch_read + (i32.const 80) ;; The pointer where to store the scratch buffer contents, + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; Store the return address. + (call $ext_set_storage + (i32.const 16) ;; Pointer to the key + (i32.const 1) ;; Value is not null + (i32.const 80) ;; Pointer to the value + (i32.const 8) ;; Length of the value + ) + ) + + (func (export "call") + ;; Read address of destination contract from storage. + (call $assert + (i32.eq + (call $ext_get_storage + (i32.const 16) ;; Pointer to the key + ) + (i32.const 0) + ) + ) + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + (call $ext_scratch_read + (i32.const 80) ;; The pointer where to store the contract address. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; Calling the destination contract with non-empty input data should fail. + (call $assert + (i32.eq + (call $ext_call + (i32.const 80) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 1) ;; Length of input data buffer + ) + (i32.const 0x0100) + ) + ) + + ;; Call the destination contract regularly, forcing it to self-destruct. + (call $assert + (i32.eq + (call $ext_call + (i32.const 80) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + + ;; Calling the destination address with non-empty input data should now work since the + ;; contract has been removed. Also transfer a balance to the address so we can ensure this + ;; does not keep the contract alive. + (call $assert + (i32.eq + (call $ext_call + (i32.const 80) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 1) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + ) + + (data (i32.const 0) "\00\00\01") ;; Endowment to send when creating contract. + (data (i32.const 8) "") ;; Value to send when calling contract. + (data (i32.const 16) "") ;; The key to store the contract address under. +) +"#; + +// This tests that one contract cannot prevent another from self-destructing by sending it +// additional funds after it has been drained. +#[test] +fn destroy_contract_and_transfer_funds() { + let (callee_wasm, callee_code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); + let (caller_wasm, caller_code_hash) = compile_module::(CODE_DESTROY_AND_TRANSFER).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, caller_wasm)); + + // This deploys the BOB contract, which in turn deploys the CHARLIE contract during + // construction. + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 200_000, + 100_000, + caller_code_hash.into(), + callee_code_hash.as_ref().to_vec(), + )); + + // Check that the CHARLIE contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(CHARLIE), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + CHARLIE.encode(), + )); + + // Check that CHARLIE has moved on to the great beyond (ie. died). + assert!(ContractInfoOf::::get(CHARLIE).is_none()); + }); +} + +const CODE_SELF_DESTRUCTING_CONSTRUCTOR: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_balance" (func $ext_balance)) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "deploy") + ;; Send entire remaining balance to the 0 address. + (call $ext_balance) + + ;; Balance should be encoded as a u64. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; Read balance into memory. + (call $ext_scratch_read + (i32.const 8) ;; Pointer to write balance to + (i32.const 0) ;; Offset into scrach buffer + (i32.const 8) ;; Length of encoded balance + ) + + ;; Self-destruct by sending full balance to the 0 address. + (call $assert + (i32.eq + (call $ext_call + (i32.const 0) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + ) + + (func (export "call")) +) +"#; + +#[test] +fn cannot_self_destruct_in_constructor() { + let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCTING_CONSTRUCTOR).unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Fail to instantiate the BOB contract since its final balance is below existential + // deposit. + assert_err!( + Contract::instantiate( + Origin::signed(ALICE), + 100_000, + 100_000, + code_hash.into(), + vec![], + ), + "insufficient remaining balance" + ); + }); +} + +#[test] +fn check_block_gas_limit_works() { + ExtBuilder::default().block_gas_limit(50).build().execute_with(|| { + let info = DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: true }; + let check = CheckBlockGasLimit::(Default::default()); + let call: Call = crate::Call::put_code(1000, vec![]).into(); + + assert_eq!( + check.validate(&0, &call, info, 0), InvalidTransaction::ExhaustsResources.into(), + ); + + let call: Call = crate::Call::update_schedule(Default::default()).into(); + assert_eq!(check.validate(&0, &call, info, 0), Ok(Default::default())); + }); +} + +const CODE_GET_RUNTIME_STORAGE: &str = r#" +(module + (import "env" "ext_get_runtime_storage" + (func $ext_get_runtime_storage (param i32 i32) (result i32)) + ) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_scratch_write" (func $ext_scratch_write (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "deploy")) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func $call (export "call") + ;; Load runtime storage for the first key and assert that it exists. + (call $assert + (i32.eq + (call $ext_get_runtime_storage + (i32.const 16) + (i32.const 4) + ) + (i32.const 0) + ) + ) + + ;; assert $ext_scratch_size == 4 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 4) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_read + (i32.const 4) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 4) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i32 value of 0x14144020. + (call $assert + (i32.eq + (i32.load + (i32.const 4) + ) + (i32.const 0x14144020) + ) + ) + + ;; Load the second key and assert that it doesn't exist. + (call $assert + (i32.eq + (call $ext_get_runtime_storage + (i32.const 20) + (i32.const 4) + ) + (i32.const 1) + ) + ) + ) + + ;; The first key, 4 bytes long. + (data (i32.const 16) "\01\02\03\04") + ;; The second key, 4 bytes long. + (data (i32.const 20) "\02\03\04\05") +) +"#; + +#[test] +fn get_runtime_storage() { + let (wasm, code_hash) = compile_module::(CODE_GET_RUNTIME_STORAGE).unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + + frame_support::storage::unhashed::put_raw( + &[1, 2, 3, 4], + 0x14144020u32.to_le_bytes().to_vec().as_ref() + ); + + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, + code_hash.into(), + vec![], + )); + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + vec![], + )); + }); +} diff --git a/srml/contracts/src/wasm/code_cache.rs b/frame/contracts/src/wasm/code_cache.rs similarity index 96% rename from srml/contracts/src/wasm/code_cache.rs rename to frame/contracts/src/wasm/code_cache.rs index e6702d29cf5c7..cb942a25892cd 100644 --- a/srml/contracts/src/wasm/code_cache.rs +++ b/frame/contracts/src/wasm/code_cache.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -29,9 +29,9 @@ use crate::gas::{Gas, GasMeter, Token}; use crate::wasm::{prepare, runtime::Env, PrefabWasmModule}; use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait}; -use rstd::prelude::*; -use sr_primitives::traits::{Hash, Bounded}; -use support::StorageMap; +use sp_std::prelude::*; +use sp_runtime::traits::{Hash, Bounded}; +use frame_support::StorageMap; /// Gas metering token that used for charging storing code into the code storage. /// diff --git a/srml/contracts/src/wasm/env_def/macros.rs b/frame/contracts/src/wasm/env_def/macros.rs similarity index 90% rename from srml/contracts/src/wasm/env_def/macros.rs rename to frame/contracts/src/wasm/env_def/macros.rs index af83c366233c6..89a147b2c6f47 100644 --- a/srml/contracts/src/wasm/env_def/macros.rs +++ b/frame/contracts/src/wasm/env_def/macros.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -96,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 } @@ -110,14 +110,14 @@ macro_rules! unmarshall_then_body_then_marshall { unmarshall_then_body!($body, $ctx, $args_iter, $( $names : $params ),*) }); let r = body()?; - return Ok(sandbox::ReturnValue::Value({ use $crate::wasm::env_def::ConvertibleToWasm; r.to_typed_value() })) + return Ok(sp_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::wasm::env_def::macros::constrain_closure::<(), _>(|| { unmarshall_then_body!($body, $ctx, $args_iter, $( $names : $params ),*) }); body()?; - return Ok(sandbox::ReturnValue::Unit) + return Ok(sp_sandbox::ReturnValue::Unit) }) } @@ -126,8 +126,8 @@ 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::wasm::Runtime, - args: &[sandbox::TypedValue], - ) -> Result { + args: &[sp_sandbox::TypedValue], + ) -> Result { #[allow(unused)] let mut args = args.iter(); @@ -195,8 +195,8 @@ macro_rules! define_env { mod tests { use parity_wasm::elements::FunctionType; use parity_wasm::elements::ValueType; - use sr_primitives::traits::Zero; - use sandbox::{self, ReturnValue, TypedValue}; + use sp_runtime::traits::Zero; + use sp_sandbox::{self, ReturnValue, TypedValue}; use crate::wasm::tests::MockExt; use crate::wasm::Runtime; use crate::exec::Ext; @@ -206,15 +206,15 @@ mod tests { fn macro_unmarshall_then_body_then_marshall_value_or_trap() { fn test_value( _ctx: &mut u32, - args: &[sandbox::TypedValue], - ) -> Result { + args: &[sp_sandbox::TypedValue], + ) -> Result { let mut args = args.iter(); unmarshall_then_body_then_marshall!( args, _ctx, (a: u32, b: u32) -> u32 => { if b == 0 { - Err(sandbox::HostError) + Err(sp_sandbox::HostError) } else { Ok(a / b) } @@ -234,8 +234,8 @@ mod tests { fn macro_unmarshall_then_body_then_marshall_unit() { fn test_unit( ctx: &mut u32, - args: &[sandbox::TypedValue], - ) -> Result { + args: &[sp_sandbox::TypedValue], + ) -> Result { let mut args = args.iter(); unmarshall_then_body_then_marshall!( args, @@ -260,11 +260,11 @@ mod tests { if !amount.is_zero() { Ok(()) } else { - Err(sandbox::HostError) + Err(sp_sandbox::HostError) } }); - let _f: fn(&mut Runtime, &[sandbox::TypedValue]) - -> Result = ext_gas::; + let _f: fn(&mut Runtime, &[sp_sandbox::TypedValue]) + -> Result = ext_gas::; } #[test] @@ -312,7 +312,7 @@ mod tests { if !amount.is_zero() { Ok(()) } else { - Err(sandbox::HostError) + Err(sp_sandbox::HostError) } }, ); diff --git a/frame/contracts/src/wasm/env_def/mod.rs b/frame/contracts/src/wasm/env_def/mod.rs new file mode 100644 index 0000000000000..004308da42211 --- /dev/null +++ b/frame/contracts/src/wasm/env_def/mod.rs @@ -0,0 +1,86 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use super::Runtime; +use crate::exec::Ext; + +use sp_sandbox::{self, TypedValue}; +use parity_wasm::elements::{FunctionType, ValueType}; + +#[macro_use] +pub(crate) mod macros; + +pub trait ConvertibleToWasm: Sized { + const VALUE_TYPE: ValueType; + type NativeType; + fn to_typed_value(self) -> TypedValue; + fn from_typed_value(_: TypedValue) -> Option; +} +impl ConvertibleToWasm for i32 { + type NativeType = i32; + const VALUE_TYPE: ValueType = ValueType::I32; + fn to_typed_value(self) -> TypedValue { + TypedValue::I32(self) + } + fn from_typed_value(v: TypedValue) -> Option { + v.as_i32() + } +} +impl ConvertibleToWasm for u32 { + type NativeType = u32; + const VALUE_TYPE: ValueType = ValueType::I32; + fn to_typed_value(self) -> TypedValue { + TypedValue::I32(self as i32) + } + fn from_typed_value(v: TypedValue) -> Option { + match v { + TypedValue::I32(v) => Some(v as u32), + _ => None, + } + } +} +impl ConvertibleToWasm for u64 { + type NativeType = u64; + const VALUE_TYPE: ValueType = ValueType::I64; + fn to_typed_value(self) -> TypedValue { + TypedValue::I64(self as i64) + } + fn from_typed_value(v: TypedValue) -> Option { + match v { + TypedValue::I64(v) => Some(v as u64), + _ => None, + } + } +} + +pub(crate) type HostFunc = + fn( + &mut Runtime, + &[sp_sandbox::TypedValue] + ) -> Result; + +pub(crate) trait FunctionImplProvider { + fn impls)>(f: &mut F); +} + +/// 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/frame/contracts/src/wasm/mod.rs b/frame/contracts/src/wasm/mod.rs new file mode 100644 index 0000000000000..8e02eb482bb8a --- /dev/null +++ b/frame/contracts/src/wasm/mod.rs @@ -0,0 +1,1765 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! 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, ExecResult}; +use crate::gas::GasMeter; + +use sp_std::prelude::*; +use codec::{Encode, Decode}; +use sp_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 str, + prefab_module: PrefabWasmModule, +} + +/// Loader which fetches `WasmExecutable` from the code cache. +pub struct WasmLoader<'a> { + schedule: &'a Schedule, +} + +impl<'a> WasmLoader<'a> { + pub fn new(schedule: &'a Schedule) -> Self { + WasmLoader { schedule } + } +} + +impl<'a, T: Trait> crate::exec::Loader for WasmLoader<'a> { + type Executable = WasmExecutable; + + fn load_init(&self, code_hash: &CodeHash) -> Result { + let prefab_module = load_code::(code_hash, self.schedule)?; + Ok(WasmExecutable { + entrypoint_name: "deploy", + prefab_module, + }) + } + fn load_main(&self, code_hash: &CodeHash) -> Result { + let prefab_module = load_code::(code_hash, self.schedule)?; + Ok(WasmExecutable { + entrypoint_name: "call", + prefab_module, + }) + } +} + +/// Implementation of `Vm` that takes `WasmExecutable` and executes it. +pub struct WasmVm<'a> { + schedule: &'a Schedule, +} + +impl<'a> WasmVm<'a> { + pub fn new(schedule: &'a Schedule) -> Self { + WasmVm { schedule } + } +} + +impl<'a, T: Trait> crate::exec::Vm for WasmVm<'a> { + type Executable = WasmExecutable; + + fn execute>( + &self, + exec: &WasmExecutable, + mut ext: E, + input_data: Vec, + gas_meter: &mut GasMeter, + ) -> ExecResult { + let memory = + sp_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 = sp_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( + &mut ext, + input_data, + &self.schedule, + memory, + gas_meter, + ); + + // Instantiate the instance from the instrumented module code and invoke the contract + // entrypoint. + let result = sp_sandbox::Instance::new(&exec.prefab_module.code, &imports, &mut runtime) + .and_then(|mut instance| instance.invoke(exec.entrypoint_name, &[], &mut runtime)); + to_execution_result(runtime, result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashMap; + use std::cell::RefCell; + use sp_core::H256; + use crate::exec::{Ext, StorageKey, ExecError, ExecReturnValue, STATUS_SUCCESS}; + use crate::gas::{Gas, GasMeter}; + use crate::tests::{Test, Call}; + use crate::wasm::prepare::prepare_contract; + use crate::CodeHash; + use wabt; + use hex_literal::hex; + use assert_matches::assert_matches; + use sp_runtime::DispatchError; + + #[derive(Debug, PartialEq, Eq)] + struct DispatchEntry(Call); + + #[derive(Debug, PartialEq, Eq)] + struct RestoreEntry { + dest: u64, + code_hash: H256, + rent_allowance: u64, + delta: Vec, + } + + #[derive(Debug, PartialEq, Eq)] + struct InstantiateEntry { + 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>, + rent_allowance: u64, + instantiates: Vec, + transfers: Vec, + dispatches: Vec, + restores: Vec, + // (topics, data) + events: Vec<(Vec, Vec)>, + next_account_id: u64, + + /// Runtime storage keys works the following way. + /// + /// - If the test code requests a value and it doesn't exist in this storage map then a + /// panic happens. + /// - If the value does exist it is returned and then removed from the map. So a panic + /// happens if the same value is requested for the second time. + /// + /// This behavior is used to prevent mixing up an access to unexpected location and empty + /// cell. + runtime_storage_keys: RefCell, Option>>>, + } + + impl Ext for MockExt { + type T = Test; + + fn get_storage(&self, key: &StorageKey) -> Option> { + self.storage.get(key).cloned() + } + fn set_storage(&mut self, key: StorageKey, value: Option>) + -> Result<(), &'static str> + { + *self.storage.entry(key).or_insert(Vec::new()) = value.unwrap_or(Vec::new()); + Ok(()) + } + fn instantiate( + &mut self, + code_hash: &CodeHash, + endowment: u64, + gas_meter: &mut GasMeter, + data: Vec, + ) -> Result<(u64, ExecReturnValue), ExecError> { + self.instantiates.push(InstantiateEntry { + 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((address, ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() })) + } + fn call( + &mut self, + to: &u64, + value: u64, + gas_meter: &mut GasMeter, + data: Vec, + ) -> ExecResult { + 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(ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() }) + } + fn note_dispatch_call(&mut self, call: Call) { + self.dispatches.push(DispatchEntry(call)); + } + fn note_restore_to( + &mut self, + dest: u64, + code_hash: H256, + rent_allowance: u64, + delta: Vec, + ) { + self.restores.push(RestoreEntry { + dest, + code_hash, + rent_allowance, + delta, + }); + } + 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 minimum_balance(&self) -> u64 { + 666 + } + + fn random(&self, subject: &[u8]) -> H256 { + H256::from_slice(subject) + } + + fn deposit_event(&mut self, topics: Vec, data: Vec) { + self.events.push((topics, data)) + } + + fn set_rent_allowance(&mut self, rent_allowance: u64) { + self.rent_allowance = rent_allowance; + } + + fn rent_allowance(&self) -> u64 { + self.rent_allowance + } + + fn block_number(&self) -> u64 { 121 } + + fn max_value_size(&self) -> u32 { 16_384 } + + fn get_runtime_storage(&self, key: &[u8]) -> Option> { + let opt_value = self.runtime_storage_keys + .borrow_mut() + .remove(key); + opt_value.unwrap_or_else(|| + panic!( + "{:?} doesn't exist. values that do exist {:?}", + key, + self.runtime_storage_keys + ) + ) + } + } + + impl Ext for &mut MockExt { + type T = ::T; + + fn get_storage(&self, key: &[u8; 32]) -> Option> { + (**self).get_storage(key) + } + fn set_storage(&mut self, key: [u8; 32], value: Option>) + -> Result<(), &'static str> + { + (**self).set_storage(key, value) + } + fn instantiate( + &mut self, + code: &CodeHash, + value: u64, + gas_meter: &mut GasMeter, + input_data: Vec, + ) -> Result<(u64, ExecReturnValue), ExecError> { + (**self).instantiate(code, value, gas_meter, input_data) + } + fn call( + &mut self, + to: &u64, + value: u64, + gas_meter: &mut GasMeter, + input_data: Vec, + ) -> ExecResult { + (**self).call(to, value, gas_meter, input_data) + } + fn note_dispatch_call(&mut self, call: Call) { + (**self).note_dispatch_call(call) + } + fn note_restore_to( + &mut self, + dest: u64, + code_hash: H256, + rent_allowance: u64, + delta: Vec, + ) { + (**self).note_restore_to( + dest, + code_hash, + rent_allowance, + delta, + ) + } + fn caller(&self) -> &u64 { + (**self).caller() + } + fn address(&self) -> &u64 { + (**self).address() + } + fn balance(&self) -> u64 { + (**self).balance() + } + fn value_transferred(&self) -> u64 { + (**self).value_transferred() + } + fn now(&self) -> &u64 { + (**self).now() + } + fn minimum_balance(&self) -> u64 { + (**self).minimum_balance() + } + fn random(&self, subject: &[u8]) -> H256 { + (**self).random(subject) + } + fn deposit_event(&mut self, topics: Vec, data: Vec) { + (**self).deposit_event(topics, data) + } + fn set_rent_allowance(&mut self, rent_allowance: u64) { + (**self).set_rent_allowance(rent_allowance) + } + fn rent_allowance(&self) -> u64 { + (**self).rent_allowance() + } + fn block_number(&self) -> u64 { + (**self).block_number() + } + fn max_value_size(&self) -> u32 { + (**self).max_value_size() + } + fn get_runtime_storage(&self, key: &[u8]) -> Option> { + (**self).get_runtime_storage(key) + } + } + + fn execute( + wat: &str, + input_data: Vec, + ext: E, + gas_meter: &mut GasMeter, + ) -> ExecResult { + 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: "call", + prefab_module, + }; + + let cfg = Default::default(); + let vm = WasmVm::new(&cfg); + + vm.execute(&exec, ext, input_data, gas_meter) + } + + 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(); + let _ = execute( + CODE_TRANSFER, + vec![], + &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: 49971, + }] + ); + } + + const CODE_INSTANTIATE: &str = r#" +(module + ;; ext_instantiate( + ;; 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_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + (func (export "call") + (drop + (call $ext_instantiate + (i32.const 16) ;; Pointer to `code_hash` + (i32.const 32) ;; Length of `code_hash` + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (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 instantiated. + (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_instantiate() { + let mut mock_ext = MockExt::default(); + let _ = execute( + CODE_INSTANTIATE, + vec![], + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ).unwrap(); + + assert_eq!( + &mock_ext.instantiates, + &[InstantiateEntry { + code_hash: [0x11; 32].into(), + endowment: 3, + data: vec![1, 2, 3, 4], + gas_left: 49947, + }] + ); + } + + 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(); + let _ = execute( + &CODE_TRANSFER_LIMITED_GAS, + vec![], + &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_read" (func $ext_scratch_read (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_read + (i32.const 36) ;; The pointer where to store the scratch buffer contents, + ;; 36 = 4 + 32 + (i32.const 0) ;; Offset from the start of the scratch buffer. + (get_local ;; Count of bytes to copy. + $buf_size + ) + ) + + ;; 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], [0x22; 32].to_vec()); + + let output = execute( + CODE_GET_STORAGE, + vec![], + mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ).unwrap(); + + assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: [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_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; 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_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 42. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 42) + ) + ) + ) + + (func (export "deploy")) +) +"#; + + #[test] + fn caller() { + let _ = execute( + CODE_CALLER, + vec![], + MockExt::default(), + &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_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; 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_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 69. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 69) + ) + ) + ) + + (func (export "deploy")) +) +"#; + + #[test] + fn address() { + let _ = execute( + CODE_ADDRESS, + vec![], + MockExt::default(), + &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_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; 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_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 228. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 228) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn balance() { + let mut gas_meter = GasMeter::with_limit(50_000, 1); + let _ = execute( + CODE_BALANCE, + vec![], + MockExt::default(), + &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_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; 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_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 1312. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 1312) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn gas_price() { + let mut gas_meter = GasMeter::with_limit(50_000, 1312); + let _ = execute( + CODE_GAS_PRICE, + vec![], + MockExt::default(), + &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_read" (func $ext_scratch_read (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_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + (call $ext_return + (i32.const 8) + (i32.const 8) + ) + + (unreachable) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn gas_left() { + let mut gas_meter = GasMeter::with_limit(50_000, 1312); + + let output = execute( + CODE_GAS_LEFT, + vec![], + MockExt::default(), + &mut gas_meter, + ).unwrap(); + + let gas_left = Gas::decode(&mut output.data.as_slice()).unwrap(); + assert!(gas_left < 50_000, "gas_left must be less than initial"); + assert!(gas_left > gas_meter.gas_left(), "gas_left must be greater than final"); + } + + const CODE_VALUE_TRANSFERRED: &str = r#" +(module + (import "env" "ext_value_transferred" (func $ext_value_transferred)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "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_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 1337. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 1337) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn value_transferred() { + let mut gas_meter = GasMeter::with_limit(50_000, 1); + let _ = execute( + CODE_VALUE_TRANSFERRED, + vec![], + MockExt::default(), + &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(); + let _ = execute( + CODE_DISPATCH_CALL, + vec![], + &mut mock_ext, + &mut GasMeter::with_limit(50_000, 1), + ).unwrap(); + + assert_eq!( + &mock_ext.dispatches, + &[DispatchEntry( + Call::Balances(pallet_balances::Call::set_balance(42, 1337, 0)), + )] + ); + } + + const CODE_RETURN_FROM_START_FN: &str = r#" +(module + (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "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 output = execute( + CODE_RETURN_FROM_START_FN, + vec![], + MockExt::default(), + &mut GasMeter::with_limit(50_000, 1), + ).unwrap(); + + assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: vec![1, 2, 3, 4] }); + } + + const CODE_TIMESTAMP_NOW: &str = r#" +(module + (import "env" "ext_now" (func $ext_now)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "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_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 1111. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 1111) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn now() { + let mut gas_meter = GasMeter::with_limit(50_000, 1); + let _ = execute( + CODE_TIMESTAMP_NOW, + vec![], + MockExt::default(), + &mut gas_meter, + ).unwrap(); + } + + const CODE_MINIMUM_BALANCE: &str = r#" +(module + (import "env" "ext_minimum_balance" (func $ext_minimum_balance)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + (call $ext_minimum_balance) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 666. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 666) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn minimum_balance() { + let mut gas_meter = GasMeter::with_limit(50_000, 1); + let _ = execute( + CODE_MINIMUM_BALANCE, + vec![], + MockExt::default(), + &mut gas_meter, + ).unwrap(); + } + + const CODE_RANDOM: &str = r#" +(module + (import "env" "ext_random" (func $ext_random (param i32 i32))) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_return" (func $ext_return (param i32 i32))) + (import "env" "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 + (i32.const 40) ;; Pointer in memory to the start of the subject buffer + (i32.const 32) ;; The subject buffer's length + ) + + ;; 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_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 32) ;; Count of bytes to copy. + ) + + ;; return the data from the contract + (call $ext_return + (i32.const 8) + (i32.const 32) + ) + ) + (func (export "deploy")) + + ;; [8,40) is reserved for the result of PRNG. + + ;; the subject used for the PRNG. [40,72) + (data (i32.const 40) + "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F" + "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F" + ) +) +"#; + + #[test] + fn random() { + let mut gas_meter = GasMeter::with_limit(50_000, 1); + + let output = execute( + CODE_RANDOM, + vec![], + MockExt::default(), + &mut gas_meter, + ).unwrap(); + + // The mock ext just returns the same data that was passed as the subject. + assert_eq!( + output, + ExecReturnValue { + status: STATUS_SUCCESS, + data: hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F").to_vec(), + }, + ); + } + + const CODE_DEPOSIT_EVENT: &str = r#" +(module + (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "call") + (call $ext_deposit_event + (i32.const 32) ;; Pointer to the start of topics buffer + (i32.const 33) ;; The length of the topics buffer. + (i32.const 8) ;; Pointer to the start of the data 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") + + ;; Encoded Vec>, the buffer has length of 33 bytes. + (data (i32.const 32) "\04\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33" + "\33\33\33\33\33\33\33\33\33") +) +"#; + + #[test] + fn deposit_event() { + let mut mock_ext = MockExt::default(); + let mut gas_meter = GasMeter::with_limit(50_000, 1); + let _ = execute( + CODE_DEPOSIT_EVENT, + vec![], + &mut mock_ext, + &mut gas_meter + ).unwrap(); + + assert_eq!(mock_ext.events, vec![ + (vec![H256::repeat_byte(0x33)], + vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]) + ]); + + assert_eq!(gas_meter.gas_left(), 49934); + } + + const CODE_DEPOSIT_EVENT_MAX_TOPICS: &str = r#" +(module + (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "call") + (call $ext_deposit_event + (i32.const 32) ;; Pointer to the start of topics buffer + (i32.const 161) ;; The length of the topics buffer. + (i32.const 8) ;; Pointer to the start of the data 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") + + ;; Encoded Vec>, the buffer has length of 161 bytes. + (data (i32.const 32) "\14" +"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" +"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02" +"\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03" +"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04" +"\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05") +) +"#; + + #[test] + fn deposit_event_max_topics() { + // Checks that the runtime traps if there are more than `max_topic_events` topics. + let mut gas_meter = GasMeter::with_limit(50_000, 1); + + assert_matches!( + execute( + CODE_DEPOSIT_EVENT_MAX_TOPICS, + vec![], + MockExt::default(), + &mut gas_meter + ), + Err(ExecError { reason: DispatchError::Other("during execution"), buffer: _ }) + ); + } + + const CODE_DEPOSIT_EVENT_DUPLICATES: &str = r#" +(module + (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "call") + (call $ext_deposit_event + (i32.const 32) ;; Pointer to the start of topics buffer + (i32.const 129) ;; The length of the topics buffer. + (i32.const 8) ;; Pointer to the start of the data 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") + + ;; Encoded Vec>, the buffer has length of 129 bytes. + (data (i32.const 32) "\10" +"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" +"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02" +"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" +"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04") +) +"#; + + #[test] + fn deposit_event_duplicates() { + // Checks that the runtime traps if there are duplicates. + let mut gas_meter = GasMeter::with_limit(50_000, 1); + + assert_matches!( + execute( + CODE_DEPOSIT_EVENT_DUPLICATES, + vec![], + MockExt::default(), + &mut gas_meter + ), + Err(ExecError { reason: DispatchError::Other("during execution"), buffer: _ }) + ); + } + + /// calls `ext_block_number`, loads the current block number from the scratch buffer and + /// compares it with the constant 121. + const CODE_BLOCK_NUMBER: &str = r#" +(module + (import "env" "ext_block_number" (func $ext_block_number)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + ;; This stores the block height in the scratch buffer + (call $ext_block_number) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 121. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 121) + ) + ) + ) + + (func (export "deploy")) +) +"#; + + #[test] + fn block_number() { + let _ = execute( + CODE_BLOCK_NUMBER, + vec![], + MockExt::default(), + &mut GasMeter::with_limit(50_000, 1), + ).unwrap(); + } + + // asserts that the size of the input data is 4. + const CODE_SIMPLE_ASSERT: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "deploy")) + + (func (export "call") + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 4) + ) + ) + ) +) +"#; + + #[test] + fn output_buffer_capacity_preserved_on_success() { + let mut input_data = Vec::with_capacity(1_234); + input_data.extend_from_slice(&[1, 2, 3, 4][..]); + + let output = execute( + CODE_SIMPLE_ASSERT, + input_data, + MockExt::default(), + &mut GasMeter::with_limit(50_000, 1), + ).unwrap(); + + assert_eq!(output.data.len(), 0); + assert_eq!(output.data.capacity(), 1_234); + } + + #[test] + fn output_buffer_capacity_preserved_on_failure() { + let mut input_data = Vec::with_capacity(1_234); + input_data.extend_from_slice(&[1, 2, 3, 4, 5][..]); + + let error = execute( + CODE_SIMPLE_ASSERT, + input_data, + MockExt::default(), + &mut GasMeter::with_limit(50_000, 1), + ).err().unwrap(); + + assert_eq!(error.buffer.capacity(), 1_234); + } + + const CODE_RETURN_WITH_DATA: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_scratch_write" (func $ext_scratch_write (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + ;; Deploy routine is the same as call. + (func (export "deploy") (result i32) + (call $call) + ) + + ;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data. + (func $call (export "call") (result i32) + (local $buf_size i32) + (local $exit_status i32) + + ;; Find out the size of the scratch buffer + (set_local $buf_size (call $ext_scratch_size)) + + ;; Copy scratch buffer into this contract memory. + (call $ext_scratch_read + (i32.const 0) ;; The pointer where to store the scratch buffer contents, + (i32.const 0) ;; Offset from the start of the scratch buffer. + (get_local $buf_size) ;; Count of bytes to copy. + ) + + ;; Copy all but the first 4 bytes of the input data as the output data. + (call $ext_scratch_write + (i32.const 4) ;; Offset from the start of the scratch buffer. + (i32.sub ;; Count of bytes to copy. + (get_local $buf_size) + (i32.const 4) + ) + ) + + ;; Return the first 4 bytes of the input data as the exit status. + (i32.load (i32.const 0)) + ) +) +"#; + + #[test] + fn return_with_success_status() { + let output = execute( + CODE_RETURN_WITH_DATA, + hex!("00112233445566778899").to_vec(), + MockExt::default(), + &mut GasMeter::with_limit(50_000, 1), + ).unwrap(); + + assert_eq!(output, ExecReturnValue { status: 0, data: hex!("445566778899").to_vec() }); + assert!(output.is_success()); + } + + #[test] + fn return_with_failure_status() { + let output = execute( + CODE_RETURN_WITH_DATA, + hex!("112233445566778899").to_vec(), + MockExt::default(), + &mut GasMeter::with_limit(50_000, 1), + ).unwrap(); + + assert_eq!(output, ExecReturnValue { status: 17, data: hex!("5566778899").to_vec() }); + assert!(!output.is_success()); + } + + const CODE_GET_RUNTIME_STORAGE: &str = r#" +(module + (import "env" "ext_get_runtime_storage" + (func $ext_get_runtime_storage (param i32 i32) (result i32)) + ) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_scratch_write" (func $ext_scratch_write (param i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func (export "deploy")) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func $call (export "call") + ;; Load runtime storage for the first key and assert that it exists. + (call $assert + (i32.eq + (call $ext_get_runtime_storage + (i32.const 16) + (i32.const 4) + ) + (i32.const 0) + ) + ) + + ;; assert $ext_scratch_size == 4 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 4) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_read + (i32.const 4) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 4) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i32 value of 0x14144020. + (call $assert + (i32.eq + (i32.load + (i32.const 4) + ) + (i32.const 0x14144020) + ) + ) + + ;; Load the second key and assert that it doesn't exist. + (call $assert + (i32.eq + (call $ext_get_runtime_storage + (i32.const 20) + (i32.const 4) + ) + (i32.const 1) + ) + ) + ) + + ;; The first key, 4 bytes long. + (data (i32.const 16) "\01\02\03\04") + ;; The second key, 4 bytes long. + (data (i32.const 20) "\02\03\04\05") +) +"#; + + #[test] + fn get_runtime_storage() { + let mut gas_meter = GasMeter::with_limit(50_000, 1); + let mock_ext = MockExt::default(); + + // "\01\02\03\04" - Some(0x14144020) + // "\02\03\04\05" - None + *mock_ext.runtime_storage_keys.borrow_mut() = [ + ([1, 2, 3, 4].to_vec(), Some(0x14144020u32.to_le_bytes().to_vec())), + ([2, 3, 4, 5].to_vec().to_vec(), None), + ] + .iter() + .cloned() + .collect(); + let _ = execute( + CODE_GET_RUNTIME_STORAGE, + vec![], + mock_ext, + &mut gas_meter, + ).unwrap(); + } +} diff --git a/srml/contracts/src/wasm/prepare.rs b/frame/contracts/src/wasm/prepare.rs similarity index 99% rename from srml/contracts/src/wasm/prepare.rs rename to frame/contracts/src/wasm/prepare.rs index 41269772a8551..39e1fca79d672 100644 --- a/srml/contracts/src/wasm/prepare.rs +++ b/frame/contracts/src/wasm/prepare.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -25,8 +25,8 @@ use crate::Schedule; use parity_wasm::elements::{self, Internal, External, MemoryType, Type, ValueType}; use pwasm_utils; use pwasm_utils::rules; -use rstd::prelude::*; -use sr_primitives::traits::{SaturatedConversion}; +use sp_std::prelude::*; +use sp_runtime::traits::{SaturatedConversion}; struct ContractModule<'a> { /// A deserialized module. The module is valid (this is Guaranteed by `new` method). diff --git a/frame/contracts/src/wasm/runtime.rs b/frame/contracts/src/wasm/runtime.rs new file mode 100644 index 0000000000000..81b0809f82b02 --- /dev/null +++ b/frame/contracts/src/wasm/runtime.rs @@ -0,0 +1,882 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Environment definition of the wasm smart-contract runtime. + +use crate::{Schedule, Trait, CodeHash, ComputeDispatchFee, BalanceOf}; +use crate::exec::{ + Ext, ExecResult, ExecError, ExecReturnValue, StorageKey, TopicOf, STATUS_SUCCESS, +}; +use crate::gas::{Gas, GasMeter, Token, GasMeterResult, approx_gas_for_balance}; +use sp_sandbox; +use frame_system; +use sp_std::prelude::*; +use sp_std::convert::TryInto; +use sp_std::mem; +use codec::{Decode, Encode}; +use sp_runtime::traits::{Bounded, SaturatedConversion}; + +/// The value returned from ext_call and ext_instantiate contract external functions if the call or +/// instantiation traps. This value is chosen as if the execution does not trap, the return value +/// will always be an 8-bit integer, so 0x0100 is the smallest value that could not be returned. +const TRAP_RETURN_CODE: u32 = 0x0100; + +/// Enumerates all possible *special* trap conditions. +/// +/// In this runtime traps used not only for signaling about errors but also +/// to just terminate quickly in some cases. +enum SpecialTrap { + /// Signals that trap was generated in response to call `ext_return` host function. + Return(Vec), +} + +/// Can only be used for one call. +pub(crate) struct Runtime<'a, E: Ext + 'a> { + ext: &'a mut E, + scratch_buf: Vec, + schedule: &'a Schedule, + memory: sp_sandbox::Memory, + gas_meter: &'a mut GasMeter, + special_trap: Option, +} +impl<'a, E: Ext + 'a> Runtime<'a, E> { + pub(crate) fn new( + ext: &'a mut E, + input_data: Vec, + schedule: &'a Schedule, + memory: sp_sandbox::Memory, + gas_meter: &'a mut GasMeter, + ) -> Self { + Runtime { + ext, + // Put the input data into the scratch buffer immediately. + scratch_buf: input_data, + schedule, + memory, + gas_meter, + special_trap: None, + } + } +} + +pub(crate) fn to_execution_result( + runtime: Runtime, + sandbox_result: Result, +) -> ExecResult { + // Special case. The trap was the result of the execution `return` host function. + if let Some(SpecialTrap::Return(data)) = runtime.special_trap { + return Ok(ExecReturnValue { status: STATUS_SUCCESS, data }); + } + + // Check the exact type of the error. + match sandbox_result { + // No traps were generated. Proceed normally. + Ok(sp_sandbox::ReturnValue::Unit) => { + let mut buffer = runtime.scratch_buf; + buffer.clear(); + Ok(ExecReturnValue { status: STATUS_SUCCESS, data: buffer }) + } + Ok(sp_sandbox::ReturnValue::Value(sp_sandbox::TypedValue::I32(exit_code))) => { + let status = (exit_code & 0xFF).try_into() + .expect("exit_code is masked into the range of a u8; qed"); + Ok(ExecReturnValue { status, data: runtime.scratch_buf }) + } + // This should never happen as the return type of exported functions should have been + // validated by the code preparation process. However, because panics are really + // undesirable in the runtime code, we treat this as a trap for now. Eventually, we might + // want to revisit this. + Ok(_) => Err(ExecError { reason: "return type error".into(), buffer: runtime.scratch_buf }), + // `Error::Module` is returned only if instantiation or linking failed (i.e. + // wasm binary tried to import a function that is not provided by the host). + // This shouldn't happen because validation process ought to reject such binaries. + // + // Because panics are really undesirable in the runtime code, we treat this as + // a trap for now. Eventually, we might want to revisit this. + Err(sp_sandbox::Error::Module) => + Err(ExecError { reason: "validation error".into(), buffer: runtime.scratch_buf }), + // Any other kind of a trap should result in a failure. + Err(sp_sandbox::Error::Execution) | Err(sp_sandbox::Error::OutOfBounds) => + Err(ExecError { reason: "during execution".into(), buffer: runtime.scratch_buf }), + } +} + +#[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), + /// (topic_count, data_bytes): A buffer of the given size is posted as an event indexed with the + /// given number of topics. + DepositEvent(u32, u32), +} + +impl Token for RuntimeToken { + type Metadata = Schedule; + + fn calculate_amount(&self, metadata: &Schedule) -> Gas { + use self::RuntimeToken::*; + let value = match *self { + Explicit(amount) => Some(amount.into()), + ReadMemory(byte_count) => metadata + .sandbox_data_read_cost + .checked_mul(byte_count.into()), + WriteMemory(byte_count) => metadata + .sandbox_data_write_cost + .checked_mul(byte_count.into()), + ReturnData(byte_count) => metadata + .return_data_per_byte_cost + .checked_mul(byte_count.into()), + DepositEvent(topic_count, data_byte_count) => { + let data_cost = metadata + .event_data_per_byte_cost + .checked_mul(data_byte_count.into()); + + let topics_cost = metadata + .event_per_topic_cost + .checked_mul(topic_count.into()); + + data_cost + .and_then(|data_cost| { + topics_cost.and_then(|topics_cost| { + data_cost.checked_add(topics_cost) + }) + }) + .and_then(|data_and_topics_cost| + data_and_topics_cost.checked_add(metadata.event_base_cost) + ) + }, + ComputedDispatchFee(gas) => Some(gas), + }; + + value.unwrap_or_else(|| Bounded::max_value()) + } +} + +/// Charge the gas meter with the specified token. +/// +/// Returns `Err(HostError)` if there is not enough gas. +fn charge_gas>( + gas_meter: &mut GasMeter, + metadata: &Tok::Metadata, + token: Tok, +) -> Result<(), sp_sandbox::HostError> { + match gas_meter.charge(metadata, token) { + GasMeterResult::Proceed => Ok(()), + GasMeterResult::OutOfGas => Err(sp_sandbox::HostError), + } +} + +/// Read designated chunk from the sandbox memory, consuming an appropriate amount of +/// gas. +/// +/// Returns `Err` if one of the following conditions occurs: +/// +/// - calculating the gas cost resulted in overflow. +/// - out of gas +/// - requested buffer is not within the bounds of the sandbox memory. +fn read_sandbox_memory( + ctx: &mut Runtime, + ptr: u32, + len: u32, +) -> Result, sp_sandbox::HostError> { + charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReadMemory(len))?; + + let mut buf = vec![0u8; len as usize]; + ctx.memory.get(ptr, buf.as_mut_slice()).map_err(|_| sp_sandbox::HostError)?; + Ok(buf) +} + +/// Read designated chunk from the sandbox memory into the scratch buffer, consuming an +/// appropriate amount of gas. Resizes the scratch buffer to the specified length on success. +/// +/// Returns `Err` if one of the following conditions occurs: +/// +/// - calculating the gas cost resulted in overflow. +/// - out of gas +/// - requested buffer is not within the bounds of the sandbox memory. +fn read_sandbox_memory_into_scratch( + ctx: &mut Runtime, + ptr: u32, + len: u32, +) -> Result<(), sp_sandbox::HostError> { + charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReadMemory(len))?; + + ctx.scratch_buf.resize(len as usize, 0); + ctx.memory.get(ptr, ctx.scratch_buf.as_mut_slice()).map_err(|_| sp_sandbox::HostError)?; + Ok(()) +} + +/// Read designated chunk from the sandbox memory into the supplied buffer, consuming +/// an appropriate amount of gas. +/// +/// Returns `Err` if one of the following conditions occurs: +/// +/// - calculating the gas cost resulted in overflow. +/// - out of gas +/// - requested buffer is not within the bounds of the sandbox memory. +fn read_sandbox_memory_into_buf( + ctx: &mut Runtime, + ptr: u32, + buf: &mut [u8], +) -> Result<(), sp_sandbox::HostError> { + charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReadMemory(buf.len() as u32))?; + + ctx.memory.get(ptr, buf).map_err(Into::into) +} + +/// Read designated chunk from the sandbox memory, consuming an appropriate amount of +/// gas, and attempt to decode into the specified type. +/// +/// Returns `Err` if one of the following conditions occurs: +/// +/// - calculating the gas cost resulted in overflow. +/// - out of gas +/// - requested buffer is not within the bounds of the sandbox memory. +/// - the buffer contents cannot be decoded as the required type. +fn read_sandbox_memory_as( + ctx: &mut Runtime, + ptr: u32, + len: u32, +) -> Result { + let buf = read_sandbox_memory(ctx, ptr, len)?; + D::decode(&mut &buf[..]).map_err(|_| sp_sandbox::HostError) +} + +/// Write the given buffer to the designated location in the sandbox memory, consuming +/// an appropriate amount of gas. +/// +/// Returns `Err` if one of the following conditions occurs: +/// +/// - calculating the gas cost resulted in overflow. +/// - out of gas +/// - designated area is not within the bounds of the sandbox memory. +fn write_sandbox_memory( + schedule: &Schedule, + gas_meter: &mut GasMeter, + memory: &sp_sandbox::Memory, + ptr: u32, + buf: &[u8], +) -> Result<(), sp_sandbox::HostError> { + charge_gas(gas_meter, schedule, RuntimeToken::WriteMemory(buf.len() as u32))?; + + memory.set(ptr, buf)?; + + Ok(()) +} + +// *********************************************************** +// * AFTER MAKING A CHANGE MAKE SURE TO UPDATE COMPLEXITY.MD * +// *********************************************************** + +// Define a function `fn init_env() -> HostFunctionSet` that returns +// a function set which can be imported by an executed contract. +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) => { + charge_gas(&mut ctx.gas_meter, ctx.schedule, RuntimeToken::Explicit(amount))?; + Ok(()) + }, + + // Change the value at the given key in the storage or remove the entry. + // The value length must not exceed the maximum defined by the Contracts module parameters. + // + // - key_ptr: pointer into the linear + // memory where the location of the requested value is placed. + // - value_non_null: if set to 0, then the entry + // at the given location will be removed. + // - value_ptr: pointer into the linear memory + // where the value to set is placed. If `value_non_null` is set to 0, then this parameter is ignored. + // - value_len: the length of the value. If `value_non_null` is set to 0, then this parameter is ignored. + ext_set_storage(ctx, key_ptr: u32, value_non_null: u32, value_ptr: u32, value_len: u32) => { + if value_non_null != 0 && ctx.ext.max_value_size() < value_len { + return Err(sp_sandbox::HostError); + } + let mut key: StorageKey = [0; 32]; + read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; + let value = + if value_non_null != 0 { + Some(read_sandbox_memory(ctx, value_ptr, value_len)?) + } else { + None + }; + ctx.ext.set_storage(key, value).map_err(|_| sp_sandbox::HostError)?; + + Ok(()) + }, + + // Retrieve the value under the given key from the storage and return 0. + // If there is no entry under the given key then this function will return 1 and + // clear the scratch buffer. + // + // - key_ptr: pointer into the linear memory where the key + // of the requested value is placed. + ext_get_storage(ctx, key_ptr: u32) -> u32 => { + let mut key: StorageKey = [0; 32]; + read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; + if let Some(value) = ctx.ext.get_storage(&key) { + ctx.scratch_buf = value; + Ok(0) + } else { + ctx.scratch_buf.clear(); + Ok(1) + } + }, + + // Make a call to another contract. + // + // If the called contract runs to completion, then this returns the status code the callee + // returns on exit in the bottom 8 bits of the return value. The top 24 bits are 0s. A status + // code of 0 indicates success, and any other code indicates a failure. On failure, any state + // changes made by the called contract are reverted. The scratch buffer is filled with the + // output data returned by the called contract, even in the case of a failure status. + // + // If the contract traps during execution or otherwise fails to complete successfully, then + // this function clears the scratch buffer and returns 0x0100. As with a failure status, any + // state changes made by the called contract are reverted. + // + // - callee_ptr: a pointer to the address of the callee contract. + // Should be decodable as an `T::AccountId`. Traps otherwise. + // - callee_len: length of the address buffer. + // - gas: how much gas to devote to the execution. + // - value_ptr: a pointer to the buffer with value, how much value to send. + // Should be decodable as a `T::Balance`. Traps otherwise. + // - value_len: length of the value buffer. + // - input_data_ptr: a pointer to a buffer to be used as input data to the callee. + // - input_data_len: length of the input data buffer. + ext_call( + ctx, + callee_ptr: u32, + callee_len: u32, + gas: u64, + value_ptr: u32, + value_len: u32, + input_data_ptr: u32, + input_data_len: u32 + ) -> u32 => { + let callee: <::T as frame_system::Trait>::AccountId = + read_sandbox_memory_as(ctx, callee_ptr, callee_len)?; + let value: BalanceOf<::T> = + read_sandbox_memory_as(ctx, value_ptr, value_len)?; + + // Read input data into the scratch buffer, then take ownership of it. + read_sandbox_memory_into_scratch(ctx, input_data_ptr, input_data_len)?; + let input_data = mem::replace(&mut ctx.scratch_buf, Vec::new()); + + let nested_gas_limit = if gas == 0 { + ctx.gas_meter.gas_left() + } else { + gas.saturated_into() + }; + let ext = &mut ctx.ext; + 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, + ) + .map_err(|err| err.buffer) + } + // there is not enough gas to allocate for the nested call. + None => Err(input_data), + } + }); + + match call_outcome { + Ok(output) => { + ctx.scratch_buf = output.data; + Ok(output.status.into()) + }, + Err(buffer) => { + ctx.scratch_buf = buffer; + ctx.scratch_buf.clear(); + Ok(TRAP_RETURN_CODE) + }, + } + }, + + // Instantiate a contract with the specified code hash. + // + // This function creates an account and executes the constructor defined in the code specified + // by the code hash. + // + // If the constructor runs to completion, then this returns the status code that the newly + // instantiated contract returns on exit in the bottom 8 bits of the return value. The top 24 + // bits are 0s. A status code of 0 indicates success, and any other code indicates a failure. + // On failure, any state changes made by the called contract are reverted and the contract is + // not instantiated. On a success status, the scratch buffer is filled with the encoded address + // of the newly instantiated contract. In the case of a failure status, the scratch buffer is + // cleared. + // + // If the contract traps during execution or otherwise fails to complete successfully, then + // this function clears the scratch buffer and returns 0x0100. As with a failure status, any + // state changes made by the called contract are reverted. + + // This function creates an account and executes initializer code. After the execution, + // the returned buffer is saved as the code of the created account. + // + // Returns 0 on the successful contract instantiation and puts the address of the instantiated + // contract into the scratch buffer. Otherwise, returns non-zero value and clears the scratch + // buffer. + // + // - code_hash_ptr: a pointer to the buffer that contains the initializer code. + // - code_hash_len: length of the initializer code buffer. + // - gas: how much gas to devote to the execution of the initializer code. + // - value_ptr: a pointer to the buffer with value, how much value to send. + // Should be decodable as a `T::Balance`. Traps otherwise. + // - value_len: length of the value buffer. + // - input_data_ptr: a pointer to a buffer to be used as input data to the initializer code. + // - input_data_len: length of the input data buffer. + ext_instantiate( + ctx, + code_hash_ptr: u32, + code_hash_len: u32, + gas: u64, + value_ptr: u32, + value_len: u32, + input_data_ptr: u32, + input_data_len: u32 + ) -> u32 => { + let code_hash: CodeHash<::T> = + read_sandbox_memory_as(ctx, code_hash_ptr, code_hash_len)?; + let value: BalanceOf<::T> = + read_sandbox_memory_as(ctx, value_ptr, value_len)?; + + // Read input data into the scratch buffer, then take ownership of it. + read_sandbox_memory_into_scratch(ctx, input_data_ptr, input_data_len)?; + let input_data = mem::replace(&mut ctx.scratch_buf, Vec::new()); + + let nested_gas_limit = if gas == 0 { + ctx.gas_meter.gas_left() + } else { + gas.saturated_into() + }; + let ext = &mut ctx.ext; + let instantiate_outcome = ctx.gas_meter.with_nested(nested_gas_limit, |nested_meter| { + match nested_meter { + Some(nested_meter) => { + ext.instantiate( + &code_hash, + value, + nested_meter, + input_data + ) + .map_err(|err| err.buffer) + } + // there is not enough gas to allocate for the nested call. + None => Err(input_data), + } + }); + match instantiate_outcome { + Ok((address, output)) => { + let is_success = output.is_success(); + ctx.scratch_buf = output.data; + ctx.scratch_buf.clear(); + if is_success { + // Write the address to the scratch buffer. + address.encode_to(&mut ctx.scratch_buf); + } + Ok(output.status.into()) + }, + Err(buffer) => { + ctx.scratch_buf = buffer; + ctx.scratch_buf.clear(); + Ok(TRAP_RETURN_CODE) + }, + } + }, + + // Save a data buffer as a result of the execution, terminate the execution and return a + // successful result to the caller. + // + // This is the only way to return a data buffer to the caller. + ext_return(ctx, data_ptr: u32, data_len: u32) => { + charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReturnData(data_len))?; + + read_sandbox_memory_into_scratch(ctx, data_ptr, data_len)?; + let output_buf = mem::replace(&mut ctx.scratch_buf, Vec::new()); + + ctx.special_trap = Some(SpecialTrap::Return(output_buf)); + + // The trap mechanism is used to immediately terminate the execution. + // This trap should be handled appropriately before returning the result + // to the user of this crate. + Err(sp_sandbox::HostError) + }, + + // Stores the address of the caller into the scratch buffer. + // + // If this is a top-level call (i.e. initiated by an extrinsic) the origin address of the + // extrinsic will be returned. Otherwise, if this call is initiated by another contract then the + // address of the contract will be returned. + ext_caller(ctx) => { + ctx.scratch_buf.clear(); + ctx.ext.caller().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // Stores the address of the current contract into the scratch buffer. + ext_address(ctx) => { + ctx.scratch_buf.clear(); + ctx.ext.address().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // Stores the 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.clear(); + ctx.gas_meter.gas_price().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // Stores the amount of gas left into the scratch buffer. + // + // The data is encoded as Gas. The current contents of the scratch buffer are overwritten. + ext_gas_left(ctx) => { + ctx.scratch_buf.clear(); + ctx.gas_meter.gas_left().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // 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.clear(); + ctx.ext.balance().encode_to(&mut ctx.scratch_buf); + 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.clear(); + ctx.ext.value_transferred().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // Stores the random number for the current block for the given subject into the scratch + // buffer. + // + // The data is encoded as T::Hash. The current contents of the scratch buffer are + // overwritten. + ext_random(ctx, subject_ptr: u32, subject_len: u32) => { + // The length of a subject can't exceed `max_subject_len`. + if subject_len > ctx.schedule.max_subject_len { + return Err(sp_sandbox::HostError); + } + + let subject_buf = read_sandbox_memory(ctx, subject_ptr, subject_len)?; + ctx.scratch_buf.clear(); + ctx.ext.random(&subject_buf).encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // Load the latest block timestamp into the scratch buffer + ext_now(ctx) => { + ctx.scratch_buf.clear(); + ctx.ext.now().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // Stores the minimum balance (a.k.a. existential deposit) into the scratch buffer. + // + // The data is encoded as T::Balance. The current contents of the scratch buffer are + // overwritten. + ext_minimum_balance(ctx) => { + ctx.scratch_buf.clear(); + ctx.ext.minimum_balance().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // Decodes the given buffer as a `T::Call` and adds it to the list + // of to-be-dispatched calls. + // + // All calls made it to the top-level context will be dispatched before + // finishing the execution of the calling extrinsic. + ext_dispatch_call(ctx, call_ptr: u32, call_len: u32) => { + let call: <::T as Trait>::Call = + read_sandbox_memory_as(ctx, call_ptr, call_len)?; + + // Charge gas for dispatching this call. + let fee = { + let balance_fee = <::T as Trait>::ComputeDispatchFee::compute_dispatch_fee(&call); + approx_gas_for_balance(ctx.gas_meter.gas_price(), balance_fee) + }; + charge_gas(&mut ctx.gas_meter, ctx.schedule, RuntimeToken::ComputedDispatchFee(fee))?; + + ctx.ext.note_dispatch_call(call); + + Ok(()) + }, + + // Record a request to restore the caller contract to the specified contract. + // + // At the finalization stage, i.e. when all changes from the extrinsic that invoked this + // contract are commited, this function will compute a tombstone hash from the caller's + // storage and the given code hash and if the hash matches the hash found in the tombstone at + // the specified address - kill the caller contract and restore the destination contract and set + // the specified `rent_allowance`. All caller's funds are transfered to the destination. + // + // This function doesn't perform restoration right away but defers it to the end of the + // transaction. If there is no tombstone in the destination address or if the hashes don't match + // then restoration is cancelled and no changes are made. + // + // `dest_ptr`, `dest_len` - the pointer and the length of a buffer that encodes `T::AccountId` + // with the address of the to be restored contract. + // `code_hash_ptr`, `code_hash_len` - the pointer and the length of a buffer that encodes + // a code hash of the to be restored contract. + // `rent_allowance_ptr`, `rent_allowance_len` - the pointer and the length of a buffer that + // encodes the rent allowance that must be set in the case of successful restoration. + // `delta_ptr` is the pointer to the start of a buffer that has `delta_count` storage keys + // laid out sequentially. + ext_restore_to( + ctx, + dest_ptr: u32, + dest_len: u32, + code_hash_ptr: u32, + code_hash_len: u32, + rent_allowance_ptr: u32, + rent_allowance_len: u32, + delta_ptr: u32, + delta_count: u32 + ) => { + let dest: <::T as frame_system::Trait>::AccountId = + read_sandbox_memory_as(ctx, dest_ptr, dest_len)?; + let code_hash: CodeHash<::T> = + read_sandbox_memory_as(ctx, code_hash_ptr, code_hash_len)?; + let rent_allowance: BalanceOf<::T> = + read_sandbox_memory_as(ctx, rent_allowance_ptr, rent_allowance_len)?; + let delta = { + // We don't use `with_capacity` here to not eagerly allocate the user specified amount + // of memory. + let mut delta = Vec::new(); + let mut key_ptr = delta_ptr; + + for _ in 0..delta_count { + const KEY_SIZE: usize = 32; + + // Read the delta into the provided buffer and collect it into the buffer. + let mut delta_key: StorageKey = [0; KEY_SIZE]; + read_sandbox_memory_into_buf(ctx, key_ptr, &mut delta_key)?; + delta.push(delta_key); + + // Offset key_ptr to the next element. + key_ptr = key_ptr.checked_add(KEY_SIZE as u32).ok_or_else(|| sp_sandbox::HostError)?; + } + + delta + }; + + ctx.ext.note_restore_to( + dest, + code_hash, + rent_allowance, + delta, + ); + + Ok(()) + }, + + // Returns the size of the scratch buffer. + // + // For more details on the scratch buffer see `ext_scratch_read`. + ext_scratch_size(ctx) -> u32 => { + Ok(ctx.scratch_buf.len() as u32) + }, + + // Copy data from the scratch buffer starting from `offset` with length `len` into the contract + // memory. The region at which the data should be put is specified by `dest_ptr`. + // + // In order to get size of the scratch buffer use `ext_scratch_size`. At the start of contract + // execution, the scratch buffer is filled with the input data. Whenever a contract calls + // function that uses the scratch buffer the contents of the scratch buffer are overwritten. + ext_scratch_read(ctx, dest_ptr: u32, offset: u32, len: u32) => { + let offset = offset as usize; + if offset > ctx.scratch_buf.len() { + // Offset can't be larger than scratch buffer length. + return Err(sp_sandbox::HostError); + } + + // This can't panic since `offset <= ctx.scratch_buf.len()`. + let src = &ctx.scratch_buf[offset..]; + if src.len() != len as usize { + return Err(sp_sandbox::HostError); + } + + // Finally, perform the write. + write_sandbox_memory( + ctx.schedule, + ctx.gas_meter, + &ctx.memory, + dest_ptr, + src, + )?; + + Ok(()) + }, + + // Copy data from contract memory starting from `src_ptr` with length `len` into the scratch + // buffer. This overwrites the entire scratch buffer and resizes to `len`. Specifying a `len` + // of zero clears the scratch buffer. + // + // This should be used before exiting a call or instantiation in order to set the return data. + ext_scratch_write(ctx, src_ptr: u32, len: u32) => { + read_sandbox_memory_into_scratch(ctx, src_ptr, len) + }, + + // Deposit a contract event with the data buffer and optional list of topics. There is a limit + // on the maximum number of topics specified by `max_event_topics`. + // + // - topics_ptr - a pointer to the buffer of topics encoded as `Vec`. The value of this + // is ignored if `topics_len` is set to 0. The topics list can't contain duplicates. + // - topics_len - the length of the topics buffer. Pass 0 if you want to pass an empty vector. + // - data_ptr - a pointer to a raw data buffer which will saved along the event. + // - data_len - the length of the data buffer. + ext_deposit_event(ctx, topics_ptr: u32, topics_len: u32, data_ptr: u32, data_len: u32) => { + let mut topics: Vec::::T>> = match topics_len { + 0 => Vec::new(), + _ => read_sandbox_memory_as(ctx, topics_ptr, topics_len)?, + }; + + // If there are more than `max_event_topics`, then trap. + if topics.len() > ctx.schedule.max_event_topics as usize { + return Err(sp_sandbox::HostError); + } + + // Check for duplicate topics. If there are any, then trap. + if has_duplicates(&mut topics) { + return Err(sp_sandbox::HostError); + } + + let event_data = read_sandbox_memory(ctx, data_ptr, data_len)?; + + charge_gas( + ctx.gas_meter, + ctx.schedule, + RuntimeToken::DepositEvent(topics.len() as u32, data_len) + )?; + ctx.ext.deposit_event(topics, event_data); + + Ok(()) + }, + + // Set rent allowance of the contract + // + // - value_ptr: a pointer to the buffer with value, how much to allow for rent + // Should be decodable as a `T::Balance`. Traps otherwise. + // - value_len: length of the value buffer. + ext_set_rent_allowance(ctx, value_ptr: u32, value_len: u32) => { + let value: BalanceOf<::T> = + read_sandbox_memory_as(ctx, value_ptr, value_len)?; + ctx.ext.set_rent_allowance(value); + + Ok(()) + }, + + // Stores the rent allowance into the scratch buffer. + // + // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. + ext_rent_allowance(ctx) => { + ctx.scratch_buf.clear(); + ctx.ext.rent_allowance().encode_to(&mut ctx.scratch_buf); + + Ok(()) + }, + + // Prints utf8 encoded string from the data buffer. + // Only available on `--dev` chains. + // This function may be removed at any time, superseded by a more general contract debugging feature. + ext_println(ctx, str_ptr: u32, str_len: u32) => { + let data = read_sandbox_memory(ctx, str_ptr, str_len)?; + if let Ok(utf8) = core::str::from_utf8(&data) { + sp_runtime::print(utf8); + } + Ok(()) + }, + + // Stores the current block number of the current contract into the scratch buffer. + ext_block_number(ctx) => { + ctx.scratch_buf.clear(); + ctx.ext.block_number().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + + // Retrieve the value under the given key from the **runtime** storage and return 0. + // If there is no entry under the given key then this function will return 1 and + // clear the scratch buffer. + // + // - key_ptr: the pointer into the linear memory where the requested value is placed. + // - key_len: the length of the key in bytes. + ext_get_runtime_storage(ctx, key_ptr: u32, key_len: u32) -> u32 => { + // Steal the scratch buffer so that we hopefully save an allocation for the `key_buf`. + read_sandbox_memory_into_scratch(ctx, key_ptr, key_len)?; + let key_buf = mem::replace(&mut ctx.scratch_buf, Vec::new()); + + match ctx.ext.get_runtime_storage(&key_buf) { + Some(value_buf) => { + // The given value exists. + ctx.scratch_buf = value_buf; + Ok(0) + } + None => { + // Put back the `key_buf` and allow its allocation to be reused. + ctx.scratch_buf = key_buf; + ctx.scratch_buf.clear(); + Ok(1) + } + } + }, +); + +/// Finds duplicates in a given vector. +/// +/// This function has complexity of O(n log n) and no additional memory is required, although +/// the order of items is not preserved. +fn has_duplicates>(items: &mut Vec) -> bool { + // Sort the vector + items.sort_unstable_by(|a, b| { + Ord::cmp(a.as_ref(), b.as_ref()) + }); + // And then find any two consecutive equal elements. + items.windows(2).any(|w| { + match w { + &[ref a, ref b] => a == b, + _ => false, + } + }) +} diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml new file mode 100644 index 0000000000000..8e1aa13fc67f9 --- /dev/null +++ b/frame/democracy/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "pallet-democracy" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +safe-mix = { version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "safe-mix/std", + "codec/std", + "sp-std/std", + "sp-io/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", +] diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs new file mode 100644 index 0000000000000..354e93cc292ee --- /dev/null +++ b/frame/democracy/src/lib.rs @@ -0,0 +1,2452 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Democratic system: Handles administration of general stakeholder voting. +#![recursion_limit="128"] +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use sp_std::{result, convert::TryFrom}; +use sp_runtime::{ + RuntimeDebug, DispatchResult, + traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash, Dispatchable, Saturating}, +}; +use codec::{Ref, Encode, Decode, Input, Output}; +use frame_support::{ + decl_module, decl_storage, decl_event, decl_error, ensure, Parameter, + weights::SimpleDispatchInfo, + traits::{ + Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get, + OnFreeBalanceZero, OnUnbalanced + } +}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +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. +pub type ReferendumIndex = u32; + +/// A value denoting the strength of conviction of a vote. +#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)] +pub enum Conviction { + /// 0.1x votes, unlocked. + None, + /// 1x votes, locked for an enactment period following a successful vote. + Locked1x, + /// 2x votes, locked for 2x enactment periods following a successful vote. + Locked2x, + /// 3x votes, locked for 4x... + Locked3x, + /// 4x votes, locked for 8x... + Locked4x, + /// 5x votes, locked for 16x... + Locked5x, + /// 6x votes, locked for 32x... + Locked6x, +} + +impl Default for Conviction { + fn default() -> Self { + Conviction::None + } +} + +impl From for u8 { + fn from(c: Conviction) -> u8 { + match c { + Conviction::None => 0, + Conviction::Locked1x => 1, + Conviction::Locked2x => 2, + Conviction::Locked3x => 3, + Conviction::Locked4x => 4, + Conviction::Locked5x => 5, + Conviction::Locked6x => 6, + } + } +} + +impl TryFrom for Conviction { + type Error = (); + fn try_from(i: u8) -> result::Result { + Ok(match i { + 0 => Conviction::None, + 1 => Conviction::Locked1x, + 2 => Conviction::Locked2x, + 3 => Conviction::Locked3x, + 4 => Conviction::Locked4x, + 5 => Conviction::Locked5x, + 6 => Conviction::Locked6x, + _ => return Err(()), + }) + } +} + +impl Conviction { + /// The amount of time (in number of periods) that our conviction implies a successful voter's + /// balance should be locked for. + fn lock_periods(self) -> u32 { + match self { + Conviction::None => 0, + Conviction::Locked1x => 1, + Conviction::Locked2x => 2, + Conviction::Locked3x => 4, + Conviction::Locked4x => 8, + Conviction::Locked5x => 16, + Conviction::Locked6x => 32, + } + } + + /// The votes of a voter of the given `balance` with our conviction. + fn votes< + B: From + Zero + Copy + CheckedMul + CheckedDiv + Bounded + >(self, balance: B) -> (B, B) { + match self { + Conviction::None => { + let r = balance.checked_div(&10u8.into()).unwrap_or_else(Zero::zero); + (r, r) + } + x => ( + balance.checked_mul(&u8::from(x).into()).unwrap_or_else(B::max_value), + balance, + ) + } + } +} + +impl Bounded for Conviction { + fn min_value() -> Self { + Conviction::None + } + + fn max_value() -> Self { + Conviction::Locked6x + } +} + +const MAX_RECURSION_LIMIT: u32 = 16; + +/// A number of lock periods, plus a vote, one way or the other. +#[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug)] +pub struct Vote { + pub aye: bool, + pub conviction: Conviction, +} + +impl Encode for Vote { + fn encode_to(&self, output: &mut T) { + output.push_byte(u8::from(self.conviction) | if self.aye { 0b1000_0000 } else { 0 }); + } +} + +impl codec::EncodeLike for Vote {} + +impl Decode for Vote { + fn decode(input: &mut I) -> core::result::Result { + let b = input.read_byte()?; + Ok(Vote { + aye: (b & 0b1000_0000) == 0b1000_0000, + conviction: Conviction::try_from(b & 0b0111_1111) + .map_err(|_| codec::Error::from("Invalid conviction"))?, + }) + } +} + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = +<::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: frame_system::Trait + Sized { + type Proposal: Parameter + Dispatchable; + type Event: From> + Into<::Event>; + + /// Currency type for this module. + type Currency: ReservableCurrency + + LockableCurrency; + + /// The minimum period of locking and the period between a proposal being approved and enacted. + /// + /// It should generally be a little more than the unstake period to ensure that + /// voting stakers have an opportunity to remove themselves from the system in the case where + /// they are on the losing side of a vote. + type EnactmentPeriod: Get; + + /// How often (in blocks) new public referenda are launched. + type LaunchPeriod: Get; + + /// How often (in blocks) to check for new votes. + type VotingPeriod: Get; + + /// The minimum amount to be used as a deposit for a public referendum proposal. + type MinimumDeposit: Get>; + + /// Origin from which the next tabled referendum may be forced. This is a normal + /// "super-majority-required" referendum. + type ExternalOrigin: EnsureOrigin; + + /// Origin from which the next tabled referendum may be forced; this allows for the tabling of + /// a majority-carries referendum. + type ExternalMajorityOrigin: EnsureOrigin; + + /// Origin from which the next tabled referendum may be forced; this allows for the tabling of + /// a negative-turnout-bias (default-carries) referendum. + type ExternalDefaultOrigin: EnsureOrigin; + + /// Origin from which the next referendum proposed by the external majority may be immediately + /// tabled to vote asynchronously in a similar manner to the emergency origin. It remains a + /// majority-carries vote. + type FastTrackOrigin: EnsureOrigin; + + /// Minimum voting period allowed for an fast-track/emergency referendum. + type EmergencyVotingPeriod: Get; + + /// Origin from which any referendum may be cancelled in an emergency. + type CancellationOrigin: EnsureOrigin; + + /// Origin for anyone able to veto proposals. + type VetoOrigin: EnsureOrigin; + + /// Period in blocks where an external proposal may not be re-submitted after being vetoed. + type CooloffPeriod: Get; + + /// The amount of balance that must be deposited per byte of preimage stored. + type PreimageByteDeposit: Get>; + + /// Handler for the unbalanced reduction when slashing a preimage deposit. + type Slash: OnUnbalanced>; +} + +/// Info regarding an ongoing referendum. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct ReferendumInfo { + /// When voting on this referendum will end. + end: BlockNumber, + /// The hash of the proposal being voted on. + proposal_hash: Hash, + /// The thresholding mechanism to determine whether it passed. + threshold: VoteThreshold, + /// The delay (in blocks) to wait after a successful referendum before deploying. + delay: BlockNumber, +} + +impl ReferendumInfo { + /// Create a new instance. + pub fn new( + end: BlockNumber, + proposal_hash: Hash, + threshold: VoteThreshold, + delay: BlockNumber + ) -> Self { + ReferendumInfo { end, proposal_hash, threshold, delay } + } +} + +decl_storage! { + trait Store for Module as Democracy { + /// The number of (public) proposals that have been made so far. + pub PublicPropCount get(fn public_prop_count) build(|_| 0 as PropIndex) : PropIndex; + /// The public proposals. Unsorted. The second item is the proposal's hash. + pub PublicProps get(fn public_props): Vec<(PropIndex, T::Hash, T::AccountId)>; + /// Map of hashes to the proposal preimage, along with who registered it and their deposit. + /// The block number is the block at which it was deposited. + pub Preimages: map T::Hash => Option<(Vec, T::AccountId, BalanceOf, T::BlockNumber)>; + /// Those who have locked a deposit. + pub DepositOf get(fn deposit_of): map PropIndex => Option<(BalanceOf, Vec)>; + + /// The next free referendum index, aka the number of referenda started so far. + pub ReferendumCount get(fn referendum_count) build(|_| 0 as ReferendumIndex): ReferendumIndex; + /// The lowest referendum index representing an unbaked referendum. Equal to + /// `ReferendumCount` if there isn't a unbaked referendum. + pub LowestUnbaked get(fn lowest_unbaked) build(|_| 0 as ReferendumIndex): ReferendumIndex; + /// Information concerning any given referendum. + pub ReferendumInfoOf get(fn referendum_info): + map ReferendumIndex => Option>; + /// Queue of successful referenda to be dispatched. Stored ordered by block number. + pub DispatchQueue get(fn dispatch_queue): Vec<(T::BlockNumber, T::Hash, ReferendumIndex)>; + + /// Get the voters for the current proposal. + pub VotersFor get(fn voters_for): map ReferendumIndex => Vec; + + /// Get the vote in a given referendum of a particular voter. The result is meaningful only + /// if `voters_for` includes the voter when called with the referendum (you'll get the + /// default `Vote` value otherwise). If you don't want to check `voters_for`, then you can + /// also check for simple existence with `VoteOf::exists` first. + pub VoteOf get(fn vote_of): map (ReferendumIndex, T::AccountId) => Vote; + + /// Who is able to vote for whom. Value is the fund-holding account, key is the + /// vote-transaction-sending account. + pub Proxy get(fn proxy): map T::AccountId => Option; + + /// Get the account (and lock periods) to which another account is delegating vote. + pub Delegations get(fn delegations): linked_map T::AccountId => (T::AccountId, Conviction); + + /// True if the last referendum tabled was submitted externally. False if it was a public + /// proposal. + pub LastTabledWasExternal: bool; + + /// The referendum to be tabled whenever it would be valid to table an external proposal. + /// This happens when a referendum needs to be tabled and one of two conditions are met: + /// - `LastTabledWasExternal` is `false`; or + /// - `PublicProps` is empty. + pub NextExternal: Option<(T::Hash, VoteThreshold)>; + + /// A record of who vetoed what. Maps proposal hash to a possible existent block number + /// (until when it may not be resubmitted) and who vetoed it. + pub Blacklist get(fn blacklist): map T::Hash => Option<(T::BlockNumber, Vec)>; + + /// Record of all proposals that have been subject to emergency cancellation. + pub Cancellations: map T::Hash => bool; + } +} + +decl_event! { + pub enum Event where + Balance = BalanceOf, + ::AccountId, + ::Hash, + ::BlockNumber, + { + /// A motion has been proposed by a public account. + Proposed(PropIndex, Balance), + /// A public proposal has been tabled for referendum vote. + Tabled(PropIndex, Balance, Vec), + /// An external proposal has been tabled. + ExternalTabled, + /// A referendum has begun. + Started(ReferendumIndex, VoteThreshold), + /// A proposal has been approved by referendum. + Passed(ReferendumIndex), + /// A proposal has been rejected by referendum. + NotPassed(ReferendumIndex), + /// A referendum has been cancelled. + Cancelled(ReferendumIndex), + /// A proposal has been enacted. + Executed(ReferendumIndex, bool), + /// An account has delegated their vote to another account. + Delegated(AccountId, AccountId), + /// An account has cancelled a previous delegation operation. + Undelegated(AccountId), + /// An external proposal has been vetoed. + Vetoed(AccountId, Hash, BlockNumber), + /// A proposal's preimage was noted, and the deposit taken. + PreimageNoted(Hash, AccountId, Balance), + /// A proposal preimage was removed and used (the deposit was returned). + PreimageUsed(Hash, AccountId, Balance), + /// A proposal could not be executed because its preimage was invalid. + PreimageInvalid(Hash, ReferendumIndex), + /// A proposal could not be executed because its preimage was missing. + PreimageMissing(Hash, ReferendumIndex), + /// A registered preimage was removed and the deposit collected by the reaper (last item). + PreimageReaped(Hash, AccountId, Balance, AccountId), + } +} + +decl_error! { + pub enum Error for Module { + /// Value too low + ValueLow, + /// Proposal does not exist + ProposalMissing, + /// Not a proxy + NotProxy, + /// Unknown index + BadIndex, + /// Cannot cancel the same proposal twice + AlreadyCanceled, + /// Proposal already made + DuplicateProposal, + /// Proposal still blacklisted + ProposalBlacklisted, + /// Next external proposal not simple majority + NotSimpleMajority, + /// Invalid hash + InvalidHash, + /// No external proposal + NoProposal, + /// Identity may not veto a proposal twice + AlreadyVetoed, + /// Already a proxy + AlreadyProxy, + /// Wrong proxy + WrongProxy, + /// Not delegated + NotDelegated, + /// Preimage already noted + DuplicatePreimage, + /// Not imminent + NotImminent, + /// Too early + Early, + /// Imminent + Imminent, + /// Preimage not found + PreimageMissing, + /// Vote given for invalid referendum + ReferendumInvalid, + /// Invalid preimage + PreimageInvalid, + /// No proposals waiting + NoneWaiting, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + /// The minimum period of locking and the period between a proposal being approved and enacted. + /// + /// It should generally be a little more than the unstake period to ensure that + /// voting stakers have an opportunity to remove themselves from the system in the case where + /// they are on the losing side of a vote. + const EnactmentPeriod: T::BlockNumber = T::EnactmentPeriod::get(); + + /// How often (in blocks) new public referenda are launched. + const LaunchPeriod: T::BlockNumber = T::LaunchPeriod::get(); + + /// How often (in blocks) to check for new votes. + const VotingPeriod: T::BlockNumber = T::VotingPeriod::get(); + + /// The minimum amount to be used as a deposit for a public referendum proposal. + const MinimumDeposit: BalanceOf = T::MinimumDeposit::get(); + + /// Minimum voting period allowed for an emergency referendum. + const EmergencyVotingPeriod: T::BlockNumber = T::EmergencyVotingPeriod::get(); + + /// Period in blocks where an external proposal may not be re-submitted after being vetoed. + const CooloffPeriod: T::BlockNumber = T::CooloffPeriod::get(); + + /// The amount of balance that must be deposited per byte of preimage stored. + const PreimageByteDeposit: BalanceOf = T::PreimageByteDeposit::get(); + + fn deposit_event() = default; + + /// Propose a sensitive action to be taken. + /// + /// # + /// - O(1). + /// - Two DB changes, one DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] + fn propose(origin, + proposal_hash: T::Hash, + #[compact] value: BalanceOf + ) { + let who = ensure_signed(origin)?; + ensure!(value >= T::MinimumDeposit::get(), Error::::ValueLow); + T::Currency::reserve(&who, value)?; + + let index = Self::public_prop_count(); + PublicPropCount::put(index + 1); + >::insert(index, (value, &[&who][..])); + + let new_prop = (index, proposal_hash, who); + >::append_or_put(&[Ref::from(&new_prop)][..]); + + Self::deposit_event(RawEvent::Proposed(index, value)); + } + + /// Propose a sensitive action to be taken. + /// + /// # + /// - O(1). + /// - One DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] + fn second(origin, #[compact] proposal: PropIndex) { + let who = ensure_signed(origin)?; + let mut deposit = Self::deposit_of(proposal) + .ok_or(Error::::ProposalMissing)?; + T::Currency::reserve(&who, deposit.0)?; + deposit.1.push(who); + >::insert(proposal, deposit); + } + + /// 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. + /// + /// # + /// - O(1). + /// - One DB change, one DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(200_000)] + fn vote(origin, + #[compact] ref_index: ReferendumIndex, + vote: Vote + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_vote(who, ref_index, vote) + } + + /// Vote in a referendum on behalf of a stash. If `vote.is_aye()`, the vote is to enact + /// the proposal; otherwise it is a vote to keep the status quo. + /// + /// # + /// - O(1). + /// - One DB change, one DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(200_000)] + fn proxy_vote(origin, + #[compact] ref_index: ReferendumIndex, + vote: Vote + ) -> DispatchResult { + let who = Self::proxy(ensure_signed(origin)?).ok_or(Error::::NotProxy)?; + Self::do_vote(who, ref_index, vote) + } + + /// Schedule an emergency cancellation of a referendum. Cannot happen twice to the same + /// referendum. + #[weight = SimpleDispatchInfo::FixedOperational(500_000)] + fn emergency_cancel(origin, ref_index: ReferendumIndex) { + T::CancellationOrigin::ensure_origin(origin)?; + + let info = Self::referendum_info(ref_index).ok_or(Error::::BadIndex)?; + let h = info.proposal_hash; + ensure!(!>::exists(h), Error::::AlreadyCanceled); + + >::insert(h, true); + Self::clear_referendum(ref_index); + } + + /// Schedule a referendum to be tabled once it is legal to schedule an external + /// referendum. + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] + fn external_propose(origin, proposal_hash: T::Hash) { + T::ExternalOrigin::ensure_origin(origin)?; + ensure!(!>::exists(), Error::::DuplicateProposal); + if let Some((until, _)) = >::get(proposal_hash) { + ensure!( + >::block_number() >= until, + Error::::ProposalBlacklisted, + ); + } + >::put((proposal_hash, VoteThreshold::SuperMajorityApprove)); + } + + /// Schedule a majority-carries referendum to be tabled next once it is legal to schedule + /// an external referendum. + /// + /// Unlike `external_propose`, blacklisting has no effect on this and it may replace a + /// pre-scheduled `external_propose` call. + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] + fn external_propose_majority(origin, proposal_hash: T::Hash) { + T::ExternalMajorityOrigin::ensure_origin(origin)?; + >::put((proposal_hash, VoteThreshold::SimpleMajority)); + } + + /// Schedule a negative-turnout-bias referendum to be tabled next once it is legal to + /// schedule an external referendum. + /// + /// Unlike `external_propose`, blacklisting has no effect on this and it may replace a + /// pre-scheduled `external_propose` call. + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] + fn external_propose_default(origin, proposal_hash: T::Hash) { + T::ExternalDefaultOrigin::ensure_origin(origin)?; + >::put((proposal_hash, VoteThreshold::SuperMajorityAgainst)); + } + + /// Schedule the currently externally-proposed majority-carries referendum to be tabled + /// immediately. If there is no externally-proposed referendum currently, or if there is one + /// but it is not a majority-carries referendum then it fails. + /// + /// - `proposal_hash`: The hash of the current external proposal. + /// - `voting_period`: The period that is allowed for voting on this proposal. Increased to + /// `EmergencyVotingPeriod` if too low. + /// - `delay`: The number of block after voting has ended in approval and this should be + /// enacted. This doesn't have a minimum amount. + #[weight = SimpleDispatchInfo::FixedNormal(200_000)] + fn fast_track(origin, + proposal_hash: T::Hash, + voting_period: T::BlockNumber, + delay: T::BlockNumber + ) { + T::FastTrackOrigin::ensure_origin(origin)?; + let (e_proposal_hash, threshold) = >::get().ok_or(Error::::ProposalMissing)?; + ensure!( + threshold != VoteThreshold::SuperMajorityApprove, + Error::::NotSimpleMajority, + ); + ensure!(proposal_hash == e_proposal_hash, Error::::InvalidHash); + + >::kill(); + let now = >::block_number(); + // We don't consider it an error if `vote_period` is too low, like `emergency_propose`. + let period = voting_period.max(T::EmergencyVotingPeriod::get()); + Self::inject_referendum(now + period, proposal_hash, threshold, delay); + } + + /// Veto and blacklist the external proposal hash. + #[weight = SimpleDispatchInfo::FixedNormal(200_000)] + fn veto_external(origin, proposal_hash: T::Hash) { + let who = T::VetoOrigin::ensure_origin(origin)?; + + if let Some((e_proposal_hash, _)) = >::get() { + ensure!(proposal_hash == e_proposal_hash, Error::::ProposalMissing); + } else { + Err(Error::::NoProposal)?; + } + + let mut existing_vetoers = >::get(&proposal_hash) + .map(|pair| pair.1) + .unwrap_or_else(Vec::new); + let insert_position = existing_vetoers.binary_search(&who) + .err().ok_or(Error::::AlreadyVetoed)?; + + existing_vetoers.insert(insert_position, who.clone()); + let until = >::block_number() + T::CooloffPeriod::get(); + >::insert(&proposal_hash, (until, existing_vetoers)); + + Self::deposit_event(RawEvent::Vetoed(who, proposal_hash, until)); + >::kill(); + } + + /// Remove a referendum. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn cancel_referendum(origin, #[compact] ref_index: ReferendumIndex) { + ensure_root(origin)?; + Self::clear_referendum(ref_index); + } + + /// Cancel a proposal queued for enactment. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn cancel_queued(origin, which: ReferendumIndex) { + ensure_root(origin)?; + let mut items = >::get(); + let original_len = items.len(); + items.retain(|i| i.2 != which); + ensure!(items.len() < original_len, Error::::ProposalMissing); + >::put(items); + } + + fn on_initialize(n: T::BlockNumber) { + if let Err(e) = Self::begin_block(n) { + sp_runtime::print(e); + } + } + + /// Specify a proxy. Called by the stash. + /// + /// # + /// - One extra DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + fn set_proxy(origin, proxy: T::AccountId) { + let who = ensure_signed(origin)?; + ensure!(!>::exists(&proxy), Error::::AlreadyProxy); + >::insert(proxy, who) + } + + /// Clear the proxy. Called by the proxy. + /// + /// # + /// - One DB clear. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + fn resign_proxy(origin) { + let who = ensure_signed(origin)?; + >::remove(who); + } + + /// Clear the proxy. Called by the stash. + /// + /// # + /// - One DB clear. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + fn remove_proxy(origin, proxy: T::AccountId) { + let who = ensure_signed(origin)?; + ensure!( + &Self::proxy(&proxy).ok_or(Error::::NotProxy)? == &who, + Error::::WrongProxy, + ); + >::remove(proxy); + } + + /// Delegate vote. + /// + /// # + /// - One extra DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + pub fn delegate(origin, to: T::AccountId, conviction: Conviction) { + let who = ensure_signed(origin)?; + >::insert(&who, (&to, conviction)); + // Currency is locked indefinitely as long as it's delegated. + T::Currency::extend_lock( + DEMOCRACY_ID, + &who, + Bounded::max_value(), + T::BlockNumber::max_value(), + WithdrawReason::Transfer.into() + ); + Self::deposit_event(RawEvent::Delegated(who, to)); + } + + /// Undelegate vote. + /// + /// # + /// - O(1). + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn undelegate(origin) { + let who = ensure_signed(origin)?; + ensure!(>::exists(&who), Error::::NotDelegated); + let (_, conviction) = >::take(&who); + // Indefinite lock is reduced to the maximum voting lock that could be possible. + let now = >::block_number(); + let locked_until = now + T::EnactmentPeriod::get() * conviction.lock_periods().into(); + T::Currency::set_lock( + DEMOCRACY_ID, + &who, + Bounded::max_value(), + locked_until, + WithdrawReason::Transfer.into() + ); + Self::deposit_event(RawEvent::Undelegated(who)); + } + + /// Veto and blacklist the proposal hash. Must be from Root origin. + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn clear_public_proposals(origin) { + ensure_root(origin)?; + + >::kill(); + } + + /// Register the preimage for an upcoming proposal. This doesn't require the proposal to be + /// in the dispatch queue but does require a deposit, returned once enacted. + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + fn note_preimage(origin, encoded_proposal: Vec) { + let who = ensure_signed(origin)?; + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + ensure!(!>::exists(&proposal_hash), Error::::DuplicatePreimage); + + let deposit = >::from(encoded_proposal.len() as u32) + .saturating_mul(T::PreimageByteDeposit::get()); + T::Currency::reserve(&who, deposit)?; + + let now = >::block_number(); + >::insert(proposal_hash, (encoded_proposal, who.clone(), deposit, now)); + + Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, deposit)); + } + + /// Register the preimage for an upcoming proposal. This requires the proposal to be + /// in the dispatch queue. No deposit is needed. + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + fn note_imminent_preimage(origin, encoded_proposal: Vec) { + let who = ensure_signed(origin)?; + let proposal_hash = T::Hashing::hash(&encoded_proposal[..]); + ensure!(!>::exists(&proposal_hash), Error::::DuplicatePreimage); + let queue = >::get(); + ensure!(queue.iter().any(|item| &item.1 == &proposal_hash), Error::::NotImminent); + + let now = >::block_number(); + let free = >::zero(); + >::insert(proposal_hash, (encoded_proposal, who.clone(), free, now)); + + Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, free)); + } + + /// Remove an expired proposal preimage and collect the deposit. + /// + /// This will only work after `VotingPeriod` blocks from the time that the preimage was + /// noted, if it's the same account doing it. If it's a different account, then it'll only + /// work an additional `EnactmentPeriod` later. + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn reap_preimage(origin, proposal_hash: T::Hash) { + let who = ensure_signed(origin)?; + + let (_, old, deposit, then) = >::get(&proposal_hash) + .ok_or(Error::::PreimageMissing)?; + let now = >::block_number(); + let (voting, enactment) = (T::VotingPeriod::get(), T::EnactmentPeriod::get()); + let additional = if who == old { Zero::zero() } else { enactment }; + ensure!(now >= then + voting + additional, Error::::Early); + + let queue = >::get(); + ensure!(!queue.iter().any(|item| &item.1 == &proposal_hash), Error::::Imminent); + + let _ = T::Currency::repatriate_reserved(&old, &who, deposit); + >::remove(&proposal_hash); + Self::deposit_event(RawEvent::PreimageReaped(proposal_hash, old, deposit, who)); + } + } +} + +impl Module { + // exposed immutables. + + /// 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 * (l.len() as u32).into()) + } + + /// Return true if `ref_index` is an on-going referendum. + pub fn is_active_referendum(ref_index: ReferendumIndex) -> bool { + >::exists(ref_index) + } + + /// Get all referenda currently active. + pub fn active_referenda() + -> Vec<(ReferendumIndex, ReferendumInfo)> + { + let next = Self::lowest_unbaked(); + let last = Self::referendum_count(); + (next..last).into_iter() + .filter_map(|i| Self::referendum_info(i).map(|info| (i, info))) + .collect() + } + + /// Get all referenda ready for tally at block `n`. + pub fn maturing_referenda_at( + n: T::BlockNumber + ) -> Vec<(ReferendumIndex, ReferendumInfo)> { + let next = Self::lowest_unbaked(); + let last = Self::referendum_count(); + (next..last).into_iter() + .filter_map(|i| Self::referendum_info(i).map(|info| (i, info))) + .filter(|&(_, ref info)| info.end == n) + .collect() + } + + /// Get the voters for the current proposal. + pub fn tally(ref_index: ReferendumIndex) -> (BalanceOf, BalanceOf, BalanceOf) { + let (approve, against, capital): + (BalanceOf, BalanceOf, BalanceOf) = Self::voters_for(ref_index) + .iter() + .map(|voter| ( + T::Currency::total_balance(voter), Self::vote_of((ref_index, voter.clone())) + )) + .map(|(balance, Vote { aye, conviction })| { + let (votes, turnout) = conviction.votes(balance); + if aye { + (votes, Zero::zero(), turnout) + } else { + (Zero::zero(), votes, turnout) + } + }).fold( + (Zero::zero(), Zero::zero(), Zero::zero()), + |(a, b, c), (d, e, f)| (a + d, b + e, c + f) + ); + let (del_approve, del_against, del_capital) = Self::tally_delegation(ref_index); + (approve + del_approve, against + del_against, capital + del_capital) + } + + /// Get the delegated voters for the current proposal. + /// I think this goes into a worker once https://github.com/paritytech/substrate/issues/1458 is + /// done. + fn tally_delegation(ref_index: ReferendumIndex) -> (BalanceOf, BalanceOf, BalanceOf) { + Self::voters_for(ref_index).iter().fold( + (Zero::zero(), Zero::zero(), Zero::zero()), + |(approve_acc, against_acc, turnout_acc), voter| { + let Vote { aye, conviction } = Self::vote_of((ref_index, voter.clone())); + let (votes, turnout) = Self::delegated_votes( + ref_index, + voter.clone(), + conviction, + MAX_RECURSION_LIMIT + ); + if aye { + (approve_acc + votes, against_acc, turnout_acc + turnout) + } else { + (approve_acc, against_acc + votes, turnout_acc + turnout) + } + } + ) + } + + fn delegated_votes( + ref_index: ReferendumIndex, + to: T::AccountId, + parent_conviction: Conviction, + recursion_limit: u32, + ) -> (BalanceOf, BalanceOf) { + if recursion_limit == 0 { return (Zero::zero(), Zero::zero()); } + >::enumerate() + .filter(|(delegator, (delegate, _))| + *delegate == to && !>::exists(&(ref_index, delegator.clone())) + ).fold( + (Zero::zero(), Zero::zero()), + |(votes_acc, turnout_acc), (delegator, (_delegate, max_conviction))| { + let conviction = Conviction::min(parent_conviction, max_conviction); + let balance = T::Currency::total_balance(&delegator); + let (votes, turnout) = conviction.votes(balance); + let (del_votes, del_turnout) = Self::delegated_votes( + ref_index, + delegator, + conviction, + recursion_limit - 1 + ); + (votes_acc + votes + del_votes, turnout_acc + turnout + del_turnout) + } + ) + } + + // Exposed mutables. + + #[cfg(feature = "std")] + pub fn force_proxy(stash: T::AccountId, proxy: T::AccountId) { + >::insert(proxy, stash) + } + + /// Start a referendum. + pub fn internal_start_referendum( + proposal_hash: T::Hash, + threshold: VoteThreshold, + delay: T::BlockNumber + ) -> ReferendumIndex { + >::inject_referendum( + >::block_number() + T::VotingPeriod::get(), + proposal_hash, + threshold, + delay + ) + } + + /// Remove a referendum. + pub fn internal_cancel_referendum(ref_index: ReferendumIndex) { + Self::deposit_event(RawEvent::Cancelled(ref_index)); + >::clear_referendum(ref_index); + } + + // private. + + /// Actually enact a vote, if legit. + fn do_vote(who: T::AccountId, ref_index: ReferendumIndex, vote: Vote) -> DispatchResult { + ensure!(Self::is_active_referendum(ref_index), Error::::ReferendumInvalid); + if !>::exists((ref_index, &who)) { + >::append_or_insert(ref_index, &[&who][..]); + } + >::insert((ref_index, &who), vote); + Ok(()) + } + + /// Start a referendum + fn inject_referendum( + end: T::BlockNumber, + proposal_hash: T::Hash, + threshold: VoteThreshold, + delay: T::BlockNumber, + ) -> ReferendumIndex { + let ref_index = Self::referendum_count(); + ReferendumCount::put(ref_index + 1); + let item = ReferendumInfo { end, proposal_hash, threshold, delay }; + >::insert(ref_index, item); + Self::deposit_event(RawEvent::Started(ref_index, threshold)); + ref_index + } + + /// Remove all info on a referendum. + fn clear_referendum(ref_index: ReferendumIndex) { + >::remove(ref_index); + + + LowestUnbaked::mutate(|i| if *i == ref_index { + *i += 1; + let end = ReferendumCount::get(); + while !Self::is_active_referendum(*i) && *i < end { + *i += 1; + } + }); + >::remove(ref_index); + for v in Self::voters_for(ref_index) { + >::remove((ref_index, v)); + } + } + + /// Enact a proposal from a referendum. + fn enact_proposal(proposal_hash: T::Hash, index: ReferendumIndex) -> DispatchResult { + if let Some((encoded_proposal, who, amount, _)) = >::take(&proposal_hash) { + if let Ok(proposal) = T::Proposal::decode(&mut &encoded_proposal[..]) { + let _ = T::Currency::unreserve(&who, amount); + Self::deposit_event(RawEvent::PreimageUsed(proposal_hash, who, amount)); + + let ok = proposal.dispatch(frame_system::RawOrigin::Root.into()).is_ok(); + Self::deposit_event(RawEvent::Executed(index, ok)); + + Ok(()) + } else { + T::Slash::on_unbalanced(T::Currency::slash_reserved(&who, amount).0); + Self::deposit_event(RawEvent::PreimageInvalid(proposal_hash, index)); + Err(Error::::PreimageInvalid.into()) + } + } else { + Self::deposit_event(RawEvent::PreimageMissing(proposal_hash, index)); + Err(Error::::PreimageMissing.into()) + } + } + + /// Table the next waiting proposal for a vote. + fn launch_next(now: T::BlockNumber) -> DispatchResult { + if LastTabledWasExternal::take() { + Self::launch_public(now).or_else(|_| Self::launch_external(now)) + } else { + Self::launch_external(now).or_else(|_| Self::launch_public(now)) + }.map_err(|_| Error::::NoneWaiting.into()) + } + + /// Table the waiting external proposal for a vote, if there is one. + fn launch_external(now: T::BlockNumber) -> DispatchResult { + if let Some((proposal, threshold)) = >::take() { + LastTabledWasExternal::put(true); + Self::deposit_event(RawEvent::ExternalTabled); + Self::inject_referendum( + now + T::VotingPeriod::get(), + proposal, + threshold, + T::EnactmentPeriod::get(), + ); + Ok(()) + } else { + Err(Error::::NoneWaiting)? + } + } + + /// Table the waiting public proposal with the highest backing for a vote. + fn launch_public(now: T::BlockNumber) -> DispatchResult { + let mut public_props = Self::public_props(); + if let Some((winner_index, _)) = public_props.iter() + .enumerate() + .max_by_key(|x| Self::locked_for((x.1).0).unwrap_or_else(Zero::zero) + /* ^^ defensive only: All current public proposals have an amount locked*/) + { + let (prop_index, proposal, _) = public_props.swap_remove(winner_index); + >::put(public_props); + + if let Some((deposit, depositors)) = >::take(prop_index) { + // refund depositors + for d in &depositors { + T::Currency::unreserve(d, deposit); + } + Self::deposit_event(RawEvent::Tabled(prop_index, deposit, depositors)); + Self::inject_referendum( + now + T::VotingPeriod::get(), + proposal, + VoteThreshold::SuperMajorityApprove, + T::EnactmentPeriod::get(), + ); + } + Ok(()) + } else { + Err(Error::::NoneWaiting)? + } + + } + + fn bake_referendum( + now: T::BlockNumber, + index: ReferendumIndex, + info: ReferendumInfo + ) -> DispatchResult { + let (approve, against, capital) = Self::tally(index); + let total_issuance = T::Currency::total_issuance(); + let approved = info.threshold.approved(approve, against, capital, total_issuance); + + // Logic defined in https://www.slideshare.net/gavofyork/governance-in-polkadot-poc3 + // Essentially, we extend the lock-period of the coins behind the winning votes to be the + // vote strength times the public delay period from now. + for (a, Vote { conviction, .. }) in Self::voters_for(index).into_iter() + .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.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 + T::EnactmentPeriod::get() * conviction.lock_periods().into(); + // ...extend their bondage until at least then. + T::Currency::extend_lock( + DEMOCRACY_ID, + &a, + Bounded::max_value(), + locked_until, + WithdrawReason::Transfer.into() + ); + } + + Self::clear_referendum(index); + + if approved { + Self::deposit_event(RawEvent::Passed(index)); + if info.delay.is_zero() { + let _ = Self::enact_proposal(info.proposal_hash, index); + } else { + let item = (now + info.delay,info.proposal_hash, index); + >::mutate(|queue| { + let pos = queue.binary_search_by_key(&item.0, |x| x.0).unwrap_or_else(|e| e); + queue.insert(pos, item); + }); + } + } else { + Self::deposit_event(RawEvent::NotPassed(index)); + } + + Ok(()) + } + + /// Current era is ending; we should finish up any proposals. + fn begin_block(now: T::BlockNumber) -> DispatchResult { + // pick out another public referendum if it's time. + if (now % T::LaunchPeriod::get()).is_zero() { + // Errors come from the queue being empty. we don't really care about that, and even if + // we did, there is nothing we can do here. + let _ = Self::launch_next(now); + } + + // tally up votes for any expiring referenda. + for (index, info) in Self::maturing_referenda_at(now).into_iter() { + Self::bake_referendum(now, index, info)?; + } + + let queue = >::get(); + let mut used = 0; + // It's stored in order, so the earliest will always be at the start. + for &(_, proposal_hash, index) in queue.iter().take_while(|x| x.0 == now) { + let _ = Self::enact_proposal(proposal_hash.clone(), index); + used += 1; + } + if used != 0 { + >::put(&queue[used..]); + } + Ok(()) + } +} + +impl OnFreeBalanceZero for Module { + fn on_free_balance_zero(who: &T::AccountId) { + >::remove(who) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::cell::RefCell; + use frame_support::{ + impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, + ord_parameter_types, traits::Contains, weights::Weight, + }; + use sp_core::H256; + use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup, Bounded, BadOrigin}, + testing::Header, Perbill, + }; + use pallet_balances::{BalanceLock, Error as BalancesError}; + use frame_system::EnsureSignedBy; + + const AYE: Vote = Vote{ aye: true, conviction: Conviction::None }; + const NAY: Vote = Vote{ aye: false, conviction: Conviction::None }; + const BIG_AYE: Vote = Vote{ aye: true, conviction: Conviction::Locked1x }; + const BIG_NAY: Vote = Vote{ aye: false, conviction: Conviction::Locked1x }; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + pallet_balances::Balances, + democracy::Democracy, + } + } + + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Clone, Eq, PartialEq, Debug)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + parameter_types! { + pub const LaunchPeriod: u64 = 2; + pub const VotingPeriod: u64 = 2; + pub const EmergencyVotingPeriod: u64 = 1; + pub const MinimumDeposit: u64 = 1; + pub const EnactmentPeriod: u64 = 2; + pub const CooloffPeriod: u64 = 2; + } + ord_parameter_types! { + pub const One: u64 = 1; + pub const Two: u64 = 2; + pub const Three: u64 = 3; + pub const Four: u64 = 4; + pub const Five: u64 = 5; + } + pub struct OneToFive; + impl Contains for OneToFive { + fn sorted_members() -> Vec { + vec![1, 2, 3, 4, 5] + } + } + thread_local! { + static PREIMAGE_BYTE_DEPOSIT: RefCell = RefCell::new(0); + } + pub struct PreimageByteDeposit; + impl Get for PreimageByteDeposit { + fn get() -> u64 { PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow()) } + } + impl super::Trait for Test { + type Proposal = Call; + type Event = (); + type Currency = pallet_balances::Module; + type EnactmentPeriod = EnactmentPeriod; + type LaunchPeriod = LaunchPeriod; + type VotingPeriod = VotingPeriod; + type EmergencyVotingPeriod = EmergencyVotingPeriod; + type MinimumDeposit = MinimumDeposit; + type ExternalOrigin = EnsureSignedBy; + type ExternalMajorityOrigin = EnsureSignedBy; + type ExternalDefaultOrigin = EnsureSignedBy; + type FastTrackOrigin = EnsureSignedBy; + type CancellationOrigin = EnsureSignedBy; + type VetoOrigin = EnsureSignedBy; + type CooloffPeriod = CooloffPeriod; + type PreimageByteDeposit = PreimageByteDeposit; + type Slash = (); + } + + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig::{ + balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + GenesisConfig::default().assimilate_storage(&mut t).unwrap(); + sp_io::TestExternalities::new(t) + } + + type System = frame_system::Module; + type Balances = pallet_balances::Module; + type Democracy = Module; + + #[test] + fn params_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(Democracy::referendum_count(), 0); + assert_eq!(Balances::free_balance(&42), 0); + assert_eq!(Balances::total_issuance(), 210); + }); + } + + fn set_balance_proposal(value: u64) -> Vec { + Call::Balances(pallet_balances::Call::set_balance(42, value, 0)).encode() + } + + fn set_balance_proposal_hash(value: u64) -> H256 { + BlakeTwo256::hash(&set_balance_proposal(value)[..]) + } + + fn set_balance_proposal_hash_and_note(value: u64) -> H256 { + let p = set_balance_proposal(value); + let h = BlakeTwo256::hash(&p[..]); + match Democracy::note_preimage(Origin::signed(6), p) { + Ok(_) => (), + Err(x) if x == Error::::DuplicatePreimage.into() => (), + Err(x) => panic!(x), + } + h + } + + fn propose_set_balance(who: u64, value: u64, delay: u64) -> DispatchResult { + Democracy::propose( + Origin::signed(who), + set_balance_proposal_hash(value), + delay + ) + } + + fn propose_set_balance_and_note(who: u64, value: u64, delay: u64) -> DispatchResult { + Democracy::propose( + Origin::signed(who), + set_balance_proposal_hash_and_note(value), + delay + ) + } + + fn next_block() { + System::set_block_number(System::block_number() + 1); + assert_eq!(Democracy::begin_block(System::block_number()), Ok(())); + } + + fn fast_forward_to(n: u64) { + while System::block_number() < n { + next_block(); + } + } + + #[test] + fn missing_preimage_should_fail() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + next_block(); + next_block(); + + assert_eq!(Balances::free_balance(&42), 0); + }); + } + + #[test] + fn preimage_deposit_should_be_required_and_returned() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + // fee of 100 is too much. + PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 100); + assert_noop!( + Democracy::note_preimage(Origin::signed(6), vec![0; 500]), + BalancesError::::InsufficientBalance, + ); + // fee of 1 is reasonable. + PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + assert_eq!(Balances::reserved_balance(6), 12); + + next_block(); + next_block(); + + assert_eq!(Balances::reserved_balance(6), 0); + assert_eq!(Balances::free_balance(6), 60); + assert_eq!(Balances::free_balance(42), 2); + }); + } + + #[test] + fn preimage_deposit_should_be_reapable_earlier_by_owner() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); + assert_ok!(Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2))); + + assert_eq!(Balances::reserved_balance(6), 12); + + next_block(); + assert_noop!( + Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2)), + Error::::Early + ); + next_block(); + assert_ok!(Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2))); + + assert_eq!(Balances::reserved_balance(6), 0); + assert_eq!(Balances::free_balance(6), 60); + }); + } + + #[test] + fn preimage_deposit_should_be_reapable() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + assert_noop!( + Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2)), + Error::::PreimageMissing + ); + + PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); + assert_ok!(Democracy::note_preimage(Origin::signed(6), set_balance_proposal(2))); + assert_eq!(Balances::reserved_balance(6), 12); + + next_block(); + next_block(); + next_block(); + assert_noop!( + Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2)), + Error::::Early + ); + + next_block(); + assert_ok!(Democracy::reap_preimage(Origin::signed(5), set_balance_proposal_hash(2))); + assert_eq!(Balances::reserved_balance(6), 0); + assert_eq!(Balances::free_balance(6), 48); + assert_eq!(Balances::free_balance(5), 62); + }); + } + + #[test] + fn noting_imminent_preimage_for_free_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1); + + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash(2), + VoteThreshold::SuperMajorityApprove, + 1 + ); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + assert_noop!( + Democracy::note_imminent_preimage(Origin::signed(7), set_balance_proposal(2)), + Error::::NotImminent + ); + + next_block(); + + // Now we're in the dispatch queue it's all good. + assert_ok!(Democracy::note_imminent_preimage(Origin::signed(7), set_balance_proposal(2))); + + next_block(); + + assert_eq!(Balances::free_balance(42), 2); + }); + } + + #[test] + fn reaping_imminent_preimage_should_fail() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let h = set_balance_proposal_hash_and_note(2); + let r = Democracy::inject_referendum(3, h, VoteThreshold::SuperMajorityApprove, 1); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + next_block(); + next_block(); + // now imminent. + assert_noop!(Democracy::reap_preimage(Origin::signed(6), h), Error::::Imminent); + }); + } + + #[test] + fn external_and_public_interleaving_works() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(1), + )); + assert_ok!(propose_set_balance_and_note(6, 2, 2)); + + fast_forward_to(2); + + // both waiting: external goes first. + assert_eq!( + Democracy::referendum_info(0), + Some(ReferendumInfo { + end: 4, + proposal_hash: set_balance_proposal_hash_and_note(1), + threshold: VoteThreshold::SuperMajorityApprove, + delay: 2 + }) + ); + // replenish external + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(3), + )); + + fast_forward_to(4); + + // both waiting: public goes next. + assert_eq!( + Democracy::referendum_info(1), + Some(ReferendumInfo { + end: 6, + proposal_hash: set_balance_proposal_hash_and_note(2), + threshold: VoteThreshold::SuperMajorityApprove, + delay: 2 + }) + ); + // don't replenish public + + fast_forward_to(6); + + // it's external "turn" again, though since public is empty that doesn't really matter + assert_eq!( + Democracy::referendum_info(2), + Some(ReferendumInfo { + end: 8, + proposal_hash: set_balance_proposal_hash_and_note(3), + threshold: VoteThreshold::SuperMajorityApprove, + delay: 2 + }) + ); + // replenish external + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(5), + )); + + fast_forward_to(8); + + // external goes again because there's no public waiting. + assert_eq!( + Democracy::referendum_info(3), + Some(ReferendumInfo { + end: 10, + proposal_hash: set_balance_proposal_hash_and_note(5), + threshold: VoteThreshold::SuperMajorityApprove, + delay: 2 + }) + ); + // replenish both + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(7), + )); + assert_ok!(propose_set_balance_and_note(6, 4, 2)); + + fast_forward_to(10); + + // public goes now since external went last time. + assert_eq!( + Democracy::referendum_info(4), + Some(ReferendumInfo { + end: 12, + proposal_hash: set_balance_proposal_hash_and_note(4), + threshold: VoteThreshold::SuperMajorityApprove, + delay: 2 + }) + ); + // replenish public again + assert_ok!(propose_set_balance_and_note(6, 6, 2)); + // cancel external + let h = set_balance_proposal_hash_and_note(7); + assert_ok!(Democracy::veto_external(Origin::signed(3), h)); + + fast_forward_to(12); + + // public goes again now since there's no external waiting. + assert_eq!( + Democracy::referendum_info(5), + Some(ReferendumInfo { + end: 14, + proposal_hash: set_balance_proposal_hash_and_note(6), + threshold: VoteThreshold::SuperMajorityApprove, + delay: 2 + }) + ); + }); + } + + + #[test] + fn emergency_cancel_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 2 + ); + assert!(Democracy::referendum_info(r).is_some()); + + assert_noop!(Democracy::emergency_cancel(Origin::signed(3), r), BadOrigin); + assert_ok!(Democracy::emergency_cancel(Origin::signed(4), r)); + assert!(Democracy::referendum_info(r).is_none()); + + // some time later... + + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 2 + ); + assert!(Democracy::referendum_info(r).is_some()); + assert_noop!(Democracy::emergency_cancel(Origin::signed(4), r), Error::::AlreadyCanceled); + }); + } + + #[test] + fn veto_external_works() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(2), + )); + assert!(>::exists()); + + let h = set_balance_proposal_hash_and_note(2); + assert_ok!(Democracy::veto_external(Origin::signed(3), h.clone())); + // cancelled. + assert!(!>::exists()); + // fails - same proposal can't be resubmitted. + assert_noop!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash(2), + ), Error::::ProposalBlacklisted); + + fast_forward_to(1); + // fails as we're still in cooloff period. + assert_noop!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash(2), + ), Error::::ProposalBlacklisted); + + fast_forward_to(2); + // works; as we're out of the cooloff period. + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(2), + )); + assert!(>::exists()); + + // 3 can't veto the same thing twice. + assert_noop!( + Democracy::veto_external(Origin::signed(3), h.clone()), + Error::::AlreadyVetoed + ); + + // 4 vetoes. + assert_ok!(Democracy::veto_external(Origin::signed(4), h.clone())); + // cancelled again. + assert!(!>::exists()); + + fast_forward_to(3); + // same proposal fails as we're still in cooloff + assert_noop!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash(2), + ), Error::::ProposalBlacklisted); + // different proposal works fine. + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(3), + )); + }); + } + + #[test] + fn external_referendum_works() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_noop!( + Democracy::external_propose( + Origin::signed(1), + set_balance_proposal_hash(2), + ), + BadOrigin, + ); + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(2), + )); + assert_noop!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash(1), + ), Error::::DuplicateProposal); + fast_forward_to(2); + assert_eq!( + Democracy::referendum_info(0), + Some(ReferendumInfo { + end: 4, + proposal_hash: set_balance_proposal_hash(2), + threshold: VoteThreshold::SuperMajorityApprove, + delay: 2 + }) + ); + }); + } + + #[test] + fn external_majority_referendum_works() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_noop!( + Democracy::external_propose_majority( + Origin::signed(1), + set_balance_proposal_hash(2) + ), + BadOrigin, + ); + assert_ok!(Democracy::external_propose_majority( + Origin::signed(3), + set_balance_proposal_hash_and_note(2) + )); + fast_forward_to(2); + assert_eq!( + Democracy::referendum_info(0), + Some(ReferendumInfo { + end: 4, + proposal_hash: set_balance_proposal_hash(2), + threshold: VoteThreshold::SimpleMajority, + delay: 2, + }) + ); + }); + } + + #[test] + fn external_default_referendum_works() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_noop!( + Democracy::external_propose_default( + Origin::signed(3), + set_balance_proposal_hash(2) + ), + BadOrigin, + ); + assert_ok!(Democracy::external_propose_default( + Origin::signed(1), + set_balance_proposal_hash_and_note(2) + )); + fast_forward_to(2); + assert_eq!( + Democracy::referendum_info(0), + Some(ReferendumInfo { + end: 4, + proposal_hash: set_balance_proposal_hash(2), + threshold: VoteThreshold::SuperMajorityAgainst, + delay: 2, + }) + ); + }); + } + + #[test] + fn fast_track_referendum_works() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + let h = set_balance_proposal_hash_and_note(2); + assert_noop!(Democracy::fast_track(Origin::signed(5), h, 3, 2), Error::::ProposalMissing); + assert_ok!(Democracy::external_propose_majority( + Origin::signed(3), + set_balance_proposal_hash_and_note(2) + )); + assert_noop!(Democracy::fast_track(Origin::signed(1), h, 3, 2), BadOrigin); + assert_ok!(Democracy::fast_track(Origin::signed(5), h, 0, 0)); + assert_eq!( + Democracy::referendum_info(0), + Some(ReferendumInfo { + end: 1, + proposal_hash: set_balance_proposal_hash_and_note(2), + threshold: VoteThreshold::SimpleMajority, + delay: 0, + }) + ); + }); + } + + #[test] + fn fast_track_referendum_fails_when_no_simple_majority() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + let h = set_balance_proposal_hash_and_note(2); + assert_ok!(Democracy::external_propose( + Origin::signed(2), + set_balance_proposal_hash_and_note(2) + )); + assert_noop!( + Democracy::fast_track(Origin::signed(5), h, 3, 2), + Error::::NotSimpleMajority + ); + }); + } + + #[test] + fn locked_for_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + assert_ok!(propose_set_balance_and_note(1, 2, 2)); + assert_ok!(propose_set_balance_and_note(1, 4, 4)); + assert_ok!(propose_set_balance_and_note(1, 3, 3)); + assert_eq!(Democracy::locked_for(0), Some(2)); + assert_eq!(Democracy::locked_for(1), Some(4)); + assert_eq!(Democracy::locked_for(2), Some(3)); + }); + } + + #[test] + fn single_proposal_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_ok!(propose_set_balance_and_note(1, 2, 1)); + assert!(Democracy::referendum_info(0).is_none()); + + // start of 2 => next referendum scheduled. + fast_forward_to(2); + + let r = 0; + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!( + Democracy::referendum_info(0), + Some(ReferendumInfo { + end: 4, + proposal_hash: set_balance_proposal_hash_and_note(2), + threshold: VoteThreshold::SuperMajorityApprove, + delay: 2 + }) + ); + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + assert_eq!(Democracy::tally(r), (1, 0, 1)); + + fast_forward_to(3); + + // referendum still running + assert!(Democracy::referendum_info(0).is_some()); + + // referendum runs during 2 and 3, ends @ start of 4. + fast_forward_to(4); + + assert!(Democracy::referendum_info(0).is_none()); + assert_eq!(Democracy::dispatch_queue(), vec![ + (6, set_balance_proposal_hash_and_note(2), 0) + ]); + + // referendum passes and wait another two blocks for enactment. + fast_forward_to(6); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn cancel_queued_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_ok!(propose_set_balance_and_note(1, 2, 1)); + + // start of 2 => next referendum scheduled. + fast_forward_to(2); + + assert_ok!(Democracy::vote(Origin::signed(1), 0, AYE)); + + fast_forward_to(4); + + assert_eq!(Democracy::dispatch_queue(), vec![ + (6, set_balance_proposal_hash_and_note(2), 0) + ]); + + assert_noop!(Democracy::cancel_queued(Origin::ROOT, 1), Error::::ProposalMissing); + assert_ok!(Democracy::cancel_queued(Origin::ROOT, 0)); + assert_eq!(Democracy::dispatch_queue(), vec![]); + }); + } + + #[test] + fn proxy_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(Democracy::proxy(10), None); + assert_ok!(Democracy::set_proxy(Origin::signed(1), 10)); + assert_eq!(Democracy::proxy(10), Some(1)); + + // Can't set when already set. + assert_noop!(Democracy::set_proxy(Origin::signed(2), 10), Error::::AlreadyProxy); + + // But this works because 11 isn't proxying. + assert_ok!(Democracy::set_proxy(Origin::signed(2), 11)); + assert_eq!(Democracy::proxy(10), Some(1)); + assert_eq!(Democracy::proxy(11), Some(2)); + + // 2 cannot fire 1's proxy: + assert_noop!(Democracy::remove_proxy(Origin::signed(2), 10), Error::::WrongProxy); + + // 1 fires his proxy: + assert_ok!(Democracy::remove_proxy(Origin::signed(1), 10)); + assert_eq!(Democracy::proxy(10), None); + assert_eq!(Democracy::proxy(11), Some(2)); + + // 11 resigns: + assert_ok!(Democracy::resign_proxy(Origin::signed(11))); + assert_eq!(Democracy::proxy(10), None); + assert_eq!(Democracy::proxy(11), None); + }); + } + + #[test] + fn single_proposal_should_work_with_proxy() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_ok!(propose_set_balance_and_note(1, 2, 1)); + + fast_forward_to(2); + let r = 0; + assert_ok!(Democracy::set_proxy(Origin::signed(1), 10)); + assert_ok!(Democracy::proxy_vote(Origin::signed(10), r, AYE)); + + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + assert_eq!(Democracy::tally(r), (1, 0, 1)); + + fast_forward_to(6); + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn single_proposal_should_work_with_delegation() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + + assert_ok!(propose_set_balance_and_note(1, 2, 1)); + + fast_forward_to(2); + + // Delegate vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); + + let r = 0; + 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); + // Delegated vote is counted. + assert_eq!(Democracy::tally(r), (3, 0, 3)); + + fast_forward_to(6); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn single_proposal_should_work_with_cyclic_delegation() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + + assert_ok!(propose_set_balance_and_note(1, 2, 1)); + + fast_forward_to(2); + + // Check behavior with cycle. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); + assert_ok!(Democracy::delegate(Origin::signed(3), 2, Conviction::max_value())); + assert_ok!(Democracy::delegate(Origin::signed(1), 3, Conviction::max_value())); + let r = 0; + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + assert_eq!(Democracy::voters_for(r), vec![1]); + + // Delegated vote is counted. + assert_eq!(Democracy::tally(r), (6, 0, 6)); + + fast_forward_to(6); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + /// If transactor already voted, delegated vote is overwriten. + fn single_proposal_should_work_with_vote_and_delegation() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + + assert_ok!(propose_set_balance_and_note(1, 2, 1)); + + fast_forward_to(2); + + let r = 0; + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + // Vote. + assert_ok!(Democracy::vote(Origin::signed(2), r, AYE)); + // Delegate vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); + assert_eq!(Democracy::voters_for(r), vec![1, 2]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + // Delegated vote is not counted. + assert_eq!(Democracy::tally(r), (3, 0, 3)); + + fast_forward_to(6); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn single_proposal_should_work_with_undelegation() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + + assert_ok!(propose_set_balance_and_note(1, 2, 1)); + + // Delegate and undelegate vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); + assert_ok!(Democracy::undelegate(Origin::signed(2))); + + fast_forward_to(2); + let r = 0; + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + + // Delegated vote is not counted. + assert_eq!(Democracy::tally(r), (1, 0, 1)); + + fast_forward_to(6); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + /// If transactor voted, delegated vote is overwriten. + fn single_proposal_should_work_with_delegation_and_vote() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + + assert_ok!(propose_set_balance_and_note(1, 2, 1)); + + fast_forward_to(2); + let r = 0; + + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + + // Delegate vote. + assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); + + // Vote. + assert_ok!(Democracy::vote(Origin::signed(2), r, AYE)); + + assert_eq!(Democracy::referendum_count(), 1); + assert_eq!(Democracy::voters_for(r), vec![1, 2]); + assert_eq!(Democracy::vote_of((r, 1)), AYE); + + // Delegated vote is not counted. + assert_eq!(Democracy::tally(r), (3, 0, 3)); + + fast_forward_to(6); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn deposit_for_proposals_should_be_taken() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + assert_ok!(propose_set_balance_and_note(1, 2, 5)); + assert_ok!(Democracy::second(Origin::signed(2), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_eq!(Balances::free_balance(&1), 5); + assert_eq!(Balances::free_balance(&2), 15); + assert_eq!(Balances::free_balance(&5), 35); + }); + } + + #[test] + fn deposit_for_proposals_should_be_returned() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + assert_ok!(propose_set_balance_and_note(1, 2, 5)); + assert_ok!(Democracy::second(Origin::signed(2), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + assert_ok!(Democracy::second(Origin::signed(5), 0)); + fast_forward_to(3); + assert_eq!(Balances::free_balance(&1), 10); + assert_eq!(Balances::free_balance(&2), 20); + assert_eq!(Balances::free_balance(&5), 50); + }); + } + + #[test] + fn proposal_with_deposit_below_minimum_should_not_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + assert_noop!(propose_set_balance(1, 2, 0), Error::::ValueLow); + }); + } + + #[test] + fn poor_proposer_should_not_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + assert_noop!(propose_set_balance(1, 2, 11), BalancesError::::InsufficientBalance); + }); + } + + #[test] + fn poor_seconder_should_not_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + assert_ok!(propose_set_balance_and_note(2, 2, 11)); + assert_noop!(Democracy::second(Origin::signed(1), 0), BalancesError::::InsufficientBalance); + }); + } + + #[test] + fn runners_up_should_come_after() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + assert_ok!(propose_set_balance_and_note(1, 2, 2)); + assert_ok!(propose_set_balance_and_note(1, 4, 4)); + assert_ok!(propose_set_balance_and_note(1, 3, 3)); + fast_forward_to(2); + assert_ok!(Democracy::vote(Origin::signed(1), 0, AYE)); + fast_forward_to(4); + assert_ok!(Democracy::vote(Origin::signed(1), 1, AYE)); + fast_forward_to(6); + assert_ok!(Democracy::vote(Origin::signed(1), 2, AYE)); + }); + } + + #[test] + fn ooo_inject_referendums_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r1 = Democracy::inject_referendum( + 3, + set_balance_proposal_hash_and_note(3), + VoteThreshold::SuperMajorityApprove, + 0 + ); + let r2 = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + + assert_ok!(Democracy::vote(Origin::signed(1), r2, AYE)); + assert_eq!(Democracy::voters_for(r2), vec![1]); + assert_eq!(Democracy::vote_of((r2, 1)), AYE); + assert_eq!(Democracy::tally(r2), (1, 0, 1)); + + next_block(); + assert_eq!(Balances::free_balance(&42), 2); + + assert_ok!(Democracy::vote(Origin::signed(1), r1, AYE)); + assert_eq!(Democracy::voters_for(r1), vec![1]); + assert_eq!(Democracy::vote_of((r1, 1)), AYE); + assert_eq!(Democracy::tally(r1), (1, 0, 1)); + + next_block(); + assert_eq!(Balances::free_balance(&42), 3); + }); + } + + #[test] + fn simple_passing_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + 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); + assert_eq!(Democracy::tally(r), (1, 0, 1)); + + next_block(); + next_block(); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn cancel_referendum_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); + assert_ok!(Democracy::cancel_referendum(Origin::ROOT, r.into())); + + next_block(); + next_block(); + + assert_eq!(Balances::free_balance(&42), 0); + }); + } + + #[test] + fn simple_failing_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + 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); + assert_eq!(Democracy::tally(r), (0, 1, 1)); + + next_block(); + next_block(); + + assert_eq!(Balances::free_balance(&42), 0); + }); + } + + #[test] + fn controversial_voting_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + + assert_ok!(Democracy::vote(Origin::signed(1), r, BIG_AYE)); + assert_ok!(Democracy::vote(Origin::signed(2), r, BIG_NAY)); + assert_ok!(Democracy::vote(Origin::signed(3), r, BIG_NAY)); + assert_ok!(Democracy::vote(Origin::signed(4), r, BIG_AYE)); + assert_ok!(Democracy::vote(Origin::signed(5), r, BIG_NAY)); + assert_ok!(Democracy::vote(Origin::signed(6), r, BIG_AYE)); + + assert_eq!(Democracy::tally(r), (110, 100, 210)); + + next_block(); + next_block(); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn delayed_enactment_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 1 + ); + 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), (21, 0, 21)); + + next_block(); + assert_eq!(Balances::free_balance(&42), 0); + + next_block(); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn controversial_low_turnout_voting_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + assert_ok!(Democracy::vote(Origin::signed(5), r, BIG_NAY)); + assert_ok!(Democracy::vote(Origin::signed(6), r, BIG_AYE)); + + assert_eq!(Democracy::tally(r), (60, 50, 110)); + + next_block(); + next_block(); + + assert_eq!(Balances::free_balance(&42), 0); + }); + } + + #[test] + fn passing_low_turnout_voting_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::free_balance(&42), 0); + assert_eq!(Balances::total_issuance(), 210); + + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + assert_ok!(Democracy::vote(Origin::signed(4), r, BIG_AYE)); + assert_ok!(Democracy::vote(Origin::signed(5), r, BIG_NAY)); + assert_ok!(Democracy::vote(Origin::signed(6), r, BIG_AYE)); + + assert_eq!(Democracy::tally(r), (100, 50, 150)); + + next_block(); + next_block(); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn lock_voting_should_work() { + new_test_ext().execute_with(|| { + System::set_block_number(0); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + assert_ok!(Democracy::vote(Origin::signed(1), r, Vote { + aye: false, + conviction: Conviction::Locked5x + })); + assert_ok!(Democracy::vote(Origin::signed(2), r, Vote { + aye: true, + conviction: Conviction::Locked4x + })); + assert_ok!(Democracy::vote(Origin::signed(3), r, Vote { + aye: true, + conviction: Conviction::Locked3x + })); + assert_ok!(Democracy::vote(Origin::signed(4), r, Vote { + aye: true, + conviction: Conviction::Locked2x + })); + assert_ok!(Democracy::vote(Origin::signed(5), r, Vote { + aye: false, + conviction: Conviction::Locked1x + })); + + assert_eq!(Democracy::tally(r), (250, 100, 150)); + + fast_forward_to(2); + + assert_eq!(Balances::locks(1), vec![]); + assert_eq!(Balances::locks(2), vec![BalanceLock { + id: DEMOCRACY_ID, + amount: u64::max_value(), + until: 18, + reasons: WithdrawReason::Transfer.into() + }]); + assert_eq!(Balances::locks(3), vec![BalanceLock { + id: DEMOCRACY_ID, + amount: u64::max_value(), + until: 10, + reasons: WithdrawReason::Transfer.into() + }]); + assert_eq!(Balances::locks(4), vec![BalanceLock { + id: DEMOCRACY_ID, + amount: u64::max_value(), + until: 6, + reasons: WithdrawReason::Transfer.into() + }]); + assert_eq!(Balances::locks(5), vec![]); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } + + #[test] + fn lock_voting_should_work_with_delegation() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + let r = Democracy::inject_referendum( + 2, + set_balance_proposal_hash_and_note(2), + VoteThreshold::SuperMajorityApprove, + 0 + ); + assert_ok!(Democracy::vote(Origin::signed(1), r, Vote { + aye: false, + conviction: Conviction::Locked5x + })); + assert_ok!(Democracy::vote(Origin::signed(2), r, Vote { + aye: true, + conviction: Conviction::Locked4x + })); + assert_ok!(Democracy::vote(Origin::signed(3), r, Vote { + aye: true, + conviction: Conviction::Locked3x + })); + assert_ok!(Democracy::delegate(Origin::signed(4), 2, Conviction::Locked2x)); + assert_ok!(Democracy::vote(Origin::signed(5), r, Vote { + aye: false, + conviction: Conviction::Locked1x + })); + + assert_eq!(Democracy::tally(r), (250, 100, 150)); + + next_block(); + next_block(); + + assert_eq!(Balances::free_balance(&42), 2); + }); + } +} diff --git a/srml/democracy/src/vote_threshold.rs b/frame/democracy/src/vote_threshold.rs similarity index 94% rename from srml/democracy/src/vote_threshold.rs rename to frame/democracy/src/vote_threshold.rs index 61e7e6535941a..46612af09abc5 100644 --- a/srml/democracy/src/vote_threshold.rs +++ b/frame/democracy/src/vote_threshold.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,11 +19,11 @@ #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; use codec::{Encode, Decode}; -use sr_primitives::traits::{Zero, IntegerSquareRoot}; -use rstd::ops::{Add, Mul, Div, Rem}; +use sp_runtime::traits::{Zero, IntegerSquareRoot}; +use sp_std::ops::{Add, Mul, Div, Rem}; /// A means of determining if a vote is past pass threshold. -#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, sr_primitives::RuntimeDebug)] +#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, sp_runtime::RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum VoteThreshold { /// A supermajority of approvals is needed to pass this vote. diff --git a/frame/elections-phragmen/Cargo.toml b/frame/elections-phragmen/Cargo.toml new file mode 100644 index 0000000000000..9d0c3ed61c3b9 --- /dev/null +++ b/frame/elections-phragmen/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "pallet-elections-phragmen" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-phragmen = { version = "2.0.0", default-features = false, path = "../../primitives/phragmen" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } + +[dev-dependencies] +sp-io = { version = "2.0.0", path = "../../primitives/io" } +hex-literal = "0.2.1" +pallet-balances = { version = "2.0.0", path = "../balances" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +substrate-test-utils = { version = "2.0.0", path = "../../test-utils" } +serde = { version = "1.0.101" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "sp-runtime/std", + "sp-phragmen/std", + "frame-system/std", + "sp-std/std", +] diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs new file mode 100644 index 0000000000000..1d9573cbbf320 --- /dev/null +++ b/frame/elections-phragmen/src/lib.rs @@ -0,0 +1,2102 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Phragmen Election Module. +//! +//! An election module based on sequential phragmen. +//! +//! ### Term and Round +//! +//! The election happens in _rounds_: every `N` blocks, all previous members are retired and a new +//! set is elected (which may or may not have an intersection with the previous set). Each round +//! lasts for some number of blocks defined by `TermDuration` storage item. The words _term_ and +//! _round_ can be used interchangeably in this context. +//! +//! `TermDuration` might change during a round. This can shorten or extend the length of the round. +//! The next election round's block number is never stored but rather always checked on the fly. +//! Based on the current block number and `TermDuration`, the condition `BlockNumber % TermDuration +//! == 0` being satisfied will always trigger a new election round. +//! +//! ### Voting +//! +//! Voters can vote for any set of the candidates by providing a list of account ids. Invalid votes +//! (voting for non-candidates) are ignored during election. Yet, a voter _might_ vote for a future +//! candidate. Voters reserve a bond as they vote. Each vote defines a `value`. This amount is +//! locked from the account of the voter and indicates the weight of the vote. Voters can update +//! their votes at any time by calling `vote()` again. This keeps the bond untouched but can +//! optionally change the locked `value`. After a round, votes are kept and might still be valid for +//! further rounds. A voter is responsible for calling `remove_voter` once they are done to have +//! their bond back and remove the lock. +//! +//! Voters also report other voters as being defunct to earn their bond. A voter is defunct once all +//! of the candidates that they have voted for are neither a valid candidate anymore nor a member. +//! Upon reporting, if the target voter is actually defunct, the reporter will be rewarded by the +//! voting bond of the target. The target will lose their bond and get removed. If the target is not +//! defunct, the reporter is slashed and removed. To prevent being reported, voters should manually +//! submit a `remove_voter()` as soon as they are in the defunct state. +//! +//! ### Candidacy and Members +//! +//! Candidates also reserve a bond as they submit candidacy. A candidate cannot take their candidacy +//! back. A candidate can end up in one of the below situations: +//! - **Winner**: A winner is kept as a _member_. They must still have a bond in reserve and they +//! are automatically counted as a candidate for the next election. +//! - **Runner-up**: Runners-up are the best candidates immediately after the winners. The number +//! of runners_up to keep is configurable. Runners-up are used, in order that they are elected, +//! as replacements when a candidate is kicked by `[remove_member]`, or when an active member +//! renounces their candidacy. Runners are automatically counted as a candidate for the next +//! election. +//! - **Loser**: Any of the candidate who are not a winner are left as losers. A loser might be an +//! _outgoing member or runner_, meaning that they are an active member who failed to keep their +//! spot. An outgoing will always lose their bond. +//! +//! ##### Renouncing candidacy. +//! +//! All candidates, elected or not, can renounce their candidacy. A call to [`renounce_candidacy`] +//! will always cause the candidacy bond to be refunded. +//! +//! Note that with the members being the default candidates for the next round and votes persisting +//! in storage, the election system is entirely stable given no further input. This means that if +//! the system has a particular set of candidates `C` and voters `V` that lead to a set of members +//! `M` being elected, as long as `V` and `C` don't remove their candidacy and votes, `M` will keep +//! being re-elected at the end of each round. +//! +//! ### Module Information +//! +//! - [`election_sp_phragmen::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use sp_runtime::{print, DispatchResult, DispatchError, traits::{Zero, StaticLookup, Bounded, Convert}}; +use frame_support::{ + decl_storage, decl_event, ensure, decl_module, decl_error, weights::SimpleDispatchInfo, + traits::{ + Currency, Get, LockableCurrency, LockIdentifier, ReservableCurrency, WithdrawReasons, + ChangeMembers, OnUnbalanced, WithdrawReason, Contains + } +}; +use sp_phragmen::ExtendedBalance; +use frame_system::{self as system, ensure_signed, ensure_root}; + +const MODULE_ID: LockIdentifier = *b"phrelect"; + +/// The maximum votes allowed per voter. +pub const MAXIMUM_VOTE: usize = 16; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = + <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: frame_system::Trait { + /// The overarching event type.c + type Event: From> + Into<::Event>; + + /// The currency that people are electing with. + type Currency: + LockableCurrency + + ReservableCurrency; + + /// What to do when the members change. + type ChangeMembers: ChangeMembers; + + /// Convert a balance into a number used for election calculation. + /// This must fit into a `u64` but is allowed to be sensibly lossy. + type CurrencyToVote: Convert, u64> + Convert>; + + /// How much should be locked up in order to submit one's candidacy. + type CandidacyBond: Get>; + + /// How much should be locked up in order to be able to submit votes. + type VotingBond: Get>; + + /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner-up) + type LoserCandidate: OnUnbalanced>; + + /// Handler for the unbalanced reduction when a reporter has submitted a bad defunct report. + type BadReport: OnUnbalanced>; + + /// Handler for the unbalanced reduction when a member has been kicked. + type KickedMember: OnUnbalanced>; + + /// Number of members to elect. + type DesiredMembers: Get; + + /// Number of runners_up to keep. + type DesiredRunnersUp: Get; + + /// How long each seat is kept. This defines the next block number at which an election + /// round will happen. If set to zero, no elections are ever triggered and the module will + /// be in passive mode. + type TermDuration: Get; +} + +decl_storage! { + trait Store for Module as PhragmenElection { + // ---- State + /// The current elected membership. Sorted based on account id. + pub Members get(fn members): Vec<(T::AccountId, BalanceOf)>; + /// The current runners_up. Sorted based on low to high merit (worse to best runner). + pub RunnersUp get(fn runners_up): Vec<(T::AccountId, BalanceOf)>; + /// The total number of vote rounds that have happened, excluding the upcoming one. + pub ElectionRounds get(fn election_rounds): u32 = Zero::zero(); + + /// Votes of a particular voter, with the round index of the votes. + pub VotesOf get(fn votes_of): linked_map T::AccountId => Vec; + /// Locked stake of a voter. + pub StakeOf get(fn stake_of): map T::AccountId => BalanceOf; + + /// The present candidate list. Sorted based on account-id. A current member or a runner can + /// never enter this vector and is always implicitly assumed to be a candidate. + pub Candidates get(fn candidates): Vec; + } +} + +decl_error! { + /// Error for the elections-phragmen module. + pub enum Error for Module { + /// Cannot vote when no candidates or members exist. + UnableToVote, + /// Must vote for at least one candidate. + NoVotes, + /// Cannot vote more than candidates. + TooManyVotes, + /// Cannot vote more than maximum allowed. + MaximumVotesExceeded, + /// Cannot vote with stake less than minimum balance. + LowBalance, + /// Voter can not pay voting bond. + UnableToPayBond, + /// Must be a voter. + MustBeVoter, + /// Cannot report self. + ReportSelf, + /// Duplicated candidate submission. + DuplicatedCandidate, + /// Member cannot re-submit candidacy. + MemberSubmit, + /// Runner cannot re-submit candidacy. + RunnerSubmit, + /// Candidate does not have enough funds. + InsufficientCandidateFunds, + /// Origin is not a candidate, member or a runner up. + InvalidOrigin, + /// Not a member. + NotMember, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + const CandidacyBond: BalanceOf = T::CandidacyBond::get(); + const VotingBond: BalanceOf = T::VotingBond::get(); + const DesiredMembers: u32 = T::DesiredMembers::get(); + const DesiredRunnersUp: u32 = T::DesiredRunnersUp::get(); + const TermDuration: T::BlockNumber = T::TermDuration::get(); + + /// Vote for a set of candidates for the upcoming round of election. + /// + /// The `votes` should: + /// - not be empty. + /// - be less than the number of candidates. + /// + /// Upon voting, `value` units of `who`'s balance is locked and a bond amount is reserved. + /// It is the responsibility of the caller to not place all of their balance into the lock + /// and keep some for further transactions. + /// + /// # + /// #### State + /// Reads: O(1) + /// Writes: O(V) given `V` votes. V is bounded by 16. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + fn vote(origin, votes: Vec, #[compact] value: BalanceOf) { + let who = ensure_signed(origin)?; + + let candidates_count = >::decode_len().unwrap_or(0) as usize; + let members_count = >::decode_len().unwrap_or(0) as usize; + // addition is valid: candidates and members never overlap. + let allowed_votes = candidates_count + members_count; + + ensure!(!allowed_votes.is_zero(), Error::::UnableToVote); + ensure!(votes.len() <= allowed_votes, Error::::TooManyVotes); + ensure!(votes.len() <= MAXIMUM_VOTE, Error::::MaximumVotesExceeded); + ensure!(!votes.is_empty(), Error::::NoVotes); + + ensure!( + value > T::Currency::minimum_balance(), + Error::::LowBalance, + ); + + if !Self::is_voter(&who) { + // first time voter. Reserve bond. + T::Currency::reserve(&who, T::VotingBond::get()) + .map_err(|_| Error::::UnableToPayBond)?; + } + // Amount to be locked up. + let locked_balance = value.min(T::Currency::total_balance(&who)); + + // lock + T::Currency::set_lock( + MODULE_ID, + &who, + locked_balance, + T::BlockNumber::max_value(), + WithdrawReasons::except(WithdrawReason::TransactionPayment), + ); + >::insert(&who, locked_balance); + >::insert(&who, votes); + } + + /// Remove `origin` as a voter. This removes the lock and returns the bond. + /// + /// # + /// #### State + /// Reads: O(1) + /// Writes: O(1) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn remove_voter(origin) { + let who = ensure_signed(origin)?; + + ensure!(Self::is_voter(&who), Error::::MustBeVoter); + + Self::do_remove_voter(&who, true); + } + + /// Report `target` for being an defunct voter. In case of a valid report, the reporter is + /// rewarded by the bond amount of `target`. Otherwise, the reporter itself is removed and + /// their bond is slashed. + /// + /// A defunct voter is defined to be: + /// - a voter whose current submitted votes are all invalid. i.e. all of them are no + /// longer a candidate nor an active member. + /// + /// # + /// #### State + /// Reads: O(NLogM) given M current candidates and N votes for `target`. + /// Writes: O(1) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + fn report_defunct_voter(origin, target: ::Source) { + let reporter = ensure_signed(origin)?; + let target = T::Lookup::lookup(target)?; + + ensure!(reporter != target, Error::::ReportSelf); + ensure!(Self::is_voter(&reporter), Error::::MustBeVoter); + + // Checking if someone is a candidate and a member here is O(LogN), making the whole + // function O(MLonN) with N candidates in total and M of them being voted by `target`. + // We could easily add another mapping to be able to check if someone is a candidate in + // `O(1)` but that would make the process of removing candidates at the end of each + // round slightly harder. Note that for now we have a bound of number of votes (`N`). + let valid = Self::is_defunct_voter(&target); + if valid { + // reporter will get the voting bond of the target + T::Currency::repatriate_reserved(&target, &reporter, T::VotingBond::get())?; + // remove the target. They are defunct. + Self::do_remove_voter(&target, false); + } else { + // slash the bond of the reporter. + let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0; + T::BadReport::on_unbalanced(imbalance); + // remove the reporter. + Self::do_remove_voter(&reporter, false); + } + Self::deposit_event(RawEvent::VoterReported(target, reporter, valid)); + } + + + /// Submit oneself for candidacy. + /// + /// A candidate will either: + /// - Lose at the end of the term and forfeit their deposit. + /// - Win and become a member. Members will eventually get their stash back. + /// - Become a runner-up. Runners-ups are reserved members in case one gets forcefully + /// removed. + /// + /// # + /// #### State + /// Reads: O(LogN) Given N candidates. + /// Writes: O(1) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn submit_candidacy(origin) { + let who = ensure_signed(origin)?; + + let is_candidate = Self::is_candidate(&who); + ensure!(is_candidate.is_err(), Error::::DuplicatedCandidate); + // assured to be an error, error always contains the index. + let index = is_candidate.unwrap_err(); + + ensure!(!Self::is_member(&who), Error::::MemberSubmit); + ensure!(!Self::is_runner(&who), Error::::RunnerSubmit); + + T::Currency::reserve(&who, T::CandidacyBond::get()) + .map_err(|_| Error::::InsufficientCandidateFunds)?; + + >::mutate(|c| c.insert(index, who)); + } + + /// Renounce one's intention to be a candidate for the next election round. 3 potential + /// outcomes exist: + /// - `origin` is a candidate and not elected in any set. In this case, the bond is + /// unreserved, returned and origin is removed as a candidate. + /// - `origin` is a current runner up. In this case, the bond is unreserved, returned and + /// origin is removed as a runner. + /// - `origin` is a current member. In this case, the bond is unreserved and origin is + /// removed as a member, consequently not being a candidate for the next round anymore. + /// Similar to [`remove_voter`], if replacement runners exists, they are immediately used. + #[weight = SimpleDispatchInfo::FixedOperational(2_000_000)] + fn renounce_candidacy(origin) { + let who = ensure_signed(origin)?; + + // NOTE: this function attempts the 3 conditions (being a candidate, member, runner) and + // fails if none are matched. Unlike other Palette functions and modules where checks + // happen first and then execution happens, this function is written the other way + // around. The main intention is that reading all of the candidates, members and runners + // from storage is expensive. Furthermore, we know (soft proof) that they are always + // mutually exclusive. Hence, we try one, and only then decode more storage. + + if let Ok(_replacement) = Self::remove_and_replace_member(&who) { + T::Currency::unreserve(&who, T::CandidacyBond::get()); + Self::deposit_event(RawEvent::MemberRenounced(who.clone())); + + // safety guard to make sure we do only one arm. Better to read runners later. + return Ok(()); + } + + let mut runners_up_with_stake = Self::runners_up(); + if let Some(index) = runners_up_with_stake.iter() + .position(|(ref r, ref _s)| r == &who) + { + runners_up_with_stake.remove(index); + // unreserve the bond + T::Currency::unreserve(&who, T::CandidacyBond::get()); + // update storage. + >::put(runners_up_with_stake); + // safety guard to make sure we do only one arm. Better to read runners later. + return Ok(()); + } + + let mut candidates = Self::candidates(); + if let Ok(index) = candidates.binary_search(&who) { + candidates.remove(index); + // unreserve the bond + T::Currency::unreserve(&who, T::CandidacyBond::get()); + // update storage. + >::put(candidates); + // safety guard to make sure we do only one arm. Better to read runners later. + return Ok(()); + } + + Err(Error::::InvalidOrigin)? + } + + /// Remove a particular member from the set. This is effective immediately and the bond of + /// the outgoing member is slashed. + /// + /// If a runner-up is available, then the best runner-up will be removed and replaces the + /// outgoing member. Otherwise, a new phragmen round is started. + /// + /// Note that this does not affect the designated block number of the next election. + /// + /// # + /// #### State + /// Reads: O(do_phragmen) + /// Writes: O(do_phragmen) + /// # + #[weight = SimpleDispatchInfo::FixedOperational(2_000_000)] + fn remove_member(origin, who: ::Source) -> DispatchResult { + ensure_root(origin)?; + let who = T::Lookup::lookup(who)?; + + Self::remove_and_replace_member(&who).map(|had_replacement| { + let (imbalance, _) = T::Currency::slash_reserved(&who, T::CandidacyBond::get()); + T::KickedMember::on_unbalanced(imbalance); + Self::deposit_event(RawEvent::MemberKicked(who.clone())); + + if !had_replacement { + Self::do_phragmen(); + } + }) + } + + /// What to do at the end of each block. Checks if an election needs to happen or not. + fn on_initialize(n: T::BlockNumber) { + if let Err(e) = Self::end_block(n) { + print("Guru meditation"); + print(e); + } + } + } +} + +decl_event!( + pub enum Event where + Balance = BalanceOf, + ::AccountId, + { + /// A new term with new members. This indicates that enough candidates existed, not that + /// enough have has been elected. The inner value must be examined for this purpose. + NewTerm(Vec<(AccountId, Balance)>), + /// No (or not enough) candidates existed for this round. + EmptyTerm, + /// A member has been removed. This should always be followed by either `NewTerm` ot + /// `EmptyTerm`. + MemberKicked(AccountId), + /// A member has renounced their candidacy. + MemberRenounced(AccountId), + /// A voter (first element) was reported (byt the second element) with the the report being + /// successful or not (third element). + VoterReported(AccountId, AccountId, bool), + } +); + +impl Module { + /// Attempts to remove a member `who`. If a runner up exists, it is used as the replacement. + /// Otherwise, `Ok(false)` is returned to signal the caller. + /// + /// In both cases, [`Members`], [`ElectionRounds`] and [`RunnersUp`] storage are updated + /// accordingly. Furthermore, the membership change is reported. + /// + /// O(phragmen) in the worse case. + fn remove_and_replace_member(who: &T::AccountId) -> Result { + let mut members_with_stake = Self::members(); + if let Ok(index) = members_with_stake.binary_search_by(|(ref m, ref _s)| m.cmp(who)) { + members_with_stake.remove(index); + + let next_up = >::mutate(|runners_up| runners_up.pop()); + let maybe_replacement = next_up.and_then(|(replacement, stake)| + members_with_stake.binary_search_by(|(ref m, ref _s)| m.cmp(&replacement)) + .err() + .map(|index| { + members_with_stake.insert(index, (replacement.clone(), stake)); + replacement + }) + ); + + >::put(&members_with_stake); + let members = members_with_stake.into_iter().map(|m| m.0).collect::>(); + let result = Ok(maybe_replacement.is_some()); + let old = [who.clone()]; + match maybe_replacement { + Some(new) => T::ChangeMembers::change_members_sorted(&[new], &old, &members), + None => T::ChangeMembers::change_members_sorted(&[], &old, &members), + } + result + } else { + Err(Error::::NotMember)? + } + } + + /// Check if `who` is a candidate. It returns the insert index if the element does not exists as + /// an error. + /// + /// State: O(LogN) given N candidates. + fn is_candidate(who: &T::AccountId) -> Result<(), usize> { + Self::candidates().binary_search(who).map(|_| ()) + } + + /// Check if `who` is a voter. It may or may not be a _current_ one. + /// + /// State: O(1). + fn is_voter(who: &T::AccountId) -> bool { + >::exists(who) + } + + /// Check if `who` is currently an active member. + /// + /// Limited number of members. Binary search. Constant time factor. O(1) + fn is_member(who: &T::AccountId) -> bool { + Self::members().binary_search_by(|(a, _b)| a.cmp(who)).is_ok() + } + + /// Check if `who` is currently an active runner. + /// + /// Limited number of runners-up. Binary search. Constant time factor. O(1) + fn is_runner(who: &T::AccountId) -> bool { + Self::runners_up().iter().position(|(a, _b)| a == who).is_some() + } + + /// Returns number of desired members. + fn desired_members() -> u32 { + T::DesiredMembers::get() + } + + /// Returns number of desired runners up. + fn desired_runners_up() -> u32 { + T::DesiredRunnersUp::get() + } + + /// Returns the term duration + fn term_duration() -> T::BlockNumber { + T::TermDuration::get() + } + + /// Get the members' account ids. + fn members_ids() -> Vec { + Self::members().into_iter().map(|(m, _)| m).collect::>() + } + + /// The the runners' up account ids. + fn runners_up_ids() -> Vec { + Self::runners_up().into_iter().map(|(r, _)| r).collect::>() + } + + /// Check if `who` is a defunct voter. + /// + /// Note that false is returned if `who` is not a voter at all. + /// + /// O(NLogM) with M candidates and `who` having voted for `N` of them. + fn is_defunct_voter(who: &T::AccountId) -> bool { + if Self::is_voter(who) { + Self::votes_of(who) + .iter() + .all(|v| !Self::is_member(v) && !Self::is_runner(v) && !Self::is_candidate(v).is_ok()) + } else { + false + } + } + + /// Remove a certain someone as a voter. + /// + /// This will clean always clean the storage associated with the voter, and remove the balance + /// lock. Optionally, it would also return the reserved voting bond if indicated by `unreserve`. + fn do_remove_voter(who: &T::AccountId, unreserve: bool) { + // remove storage and lock. + >::remove(who); + >::remove(who); + T::Currency::remove_lock(MODULE_ID, who); + + if unreserve { + T::Currency::unreserve(who, T::VotingBond::get()); + } + } + + /// The locked stake of a voter. + fn locked_stake_of(who: &T::AccountId) -> BalanceOf { + Self::stake_of(who) + } + + /// Check there's nothing to do this block. + /// + /// Runs phragmen election and cleans all the previous candidate state. The voter state is NOT + /// cleaned and voters must themselves submit a transaction to retract. + fn end_block(block_number: T::BlockNumber) -> DispatchResult { + if !Self::term_duration().is_zero() { + if (block_number % Self::term_duration()).is_zero() { + Self::do_phragmen(); + } + } + Ok(()) + } + + /// Run the phragmen election with all required side processes and state updates. + /// + /// Calls the appropriate `ChangeMembers` function variant internally. + /// + /// # + /// #### State + /// Reads: O(C + V*E) where C = candidates, V voters and E votes per voter exits. + /// Writes: O(M + R) with M desired members and R runners_up. + /// # + fn do_phragmen() { + let desired_seats = Self::desired_members() as usize; + let desired_runners_up = Self::desired_runners_up() as usize; + let num_to_elect = desired_runners_up + desired_seats; + + let mut candidates = Self::candidates(); + // candidates who explicitly called `submit_candidacy`. Only these folks are at the risk of + // losing their bond. + let exposed_candidates = candidates.clone(); + // current members are always a candidate for the next round as well. + // this is guaranteed to not create any duplicates. + candidates.append(&mut Self::members_ids()); + // previous runners_up are also always candidates for the next round. + candidates.append(&mut Self::runners_up_ids()); + + let voters_and_votes = >::enumerate() + .map(|(v, i)| (v, i)) + .collect::)>>(); + let maybe_phragmen_result = sp_phragmen::elect::<_, _, _, T::CurrencyToVote>( + num_to_elect, + 0, + candidates, + voters_and_votes, + Self::locked_stake_of, + ); + + if let Some(phragmen_result) = maybe_phragmen_result { + let old_members_ids = >::take().into_iter() + .map(|(m, _)| m) + .collect::>(); + let old_runners_up_ids = >::take().into_iter() + .map(|(r, _)| r) + .collect::>(); + + // filter out those who had literally no votes at all. + // AUDIT/NOTE: the need to do this is because all candidates, even those who have no + // vote are still considered by phragmen and when good candidates are scarce, then these + // cheap ones might get elected. We might actually want to remove the filter and allow + // zero-voted candidates to also make it to the membership set. + let new_set_with_approval = phragmen_result.winners; + let new_set = new_set_with_approval + .into_iter() + .filter_map(|(m, a)| if a.is_zero() { None } else { Some(m) } ) + .collect::>(); + + let support_map = sp_phragmen::build_support_map::<_, _, _, T::CurrencyToVote>( + &new_set, + &phragmen_result.assignments, + Self::locked_stake_of, + ); + + let to_balance = |e: ExtendedBalance| + >>::convert(e); + let new_set_with_stake = new_set + .into_iter() + .map(|ref m| { + let support = support_map.get(m) + .expect( + "entire new_set was given to build_support_map; en entry must be \ + created for each item; qed" + ); + (m.clone(), to_balance(support.total)) + }) + .collect::)>>(); + + // split new set into winners and runners up. + let split_point = desired_seats.min(new_set_with_stake.len()); + let mut new_members = (&new_set_with_stake[..split_point]).to_vec(); + + // save the runners up as-is. They are sorted based on desirability. + // sort and save the members. + new_members.sort_by(|i, j| i.0.cmp(&j.0)); + + // new_members_ids is sorted by account id. + let new_members_ids = new_members + .iter() + .map(|(m, _)| m.clone()) + .collect::>(); + + let new_runners_up = &new_set_with_stake[split_point..] + .into_iter() + .cloned() + .rev() + .collect::)>>(); + // new_runners_up remains sorted by desirability. + let new_runners_up_ids = new_runners_up + .iter() + .map(|(r, _)| r.clone()) + .collect::>(); + + // report member changes. We compute diff because we need the outgoing list. + let (incoming, outgoing) = T::ChangeMembers::compute_members_diff( + &new_members_ids, + &old_members_ids, + ); + T::ChangeMembers::change_members_sorted( + &incoming, + &outgoing.clone(), + &new_members_ids, + ); + + // outgoing candidates lose their bond. + let mut to_burn_bond = outgoing.to_vec(); + + // compute the outgoing of runners up as well and append them to the `to_burn_bond` + { + let (_, outgoing) = T::ChangeMembers::compute_members_diff( + &new_runners_up_ids, + &old_runners_up_ids, + ); + to_burn_bond.extend(outgoing); + } + + // Burn loser bond. members list is sorted. O(NLogM) (N candidates, M members) + // runner up list is not sorted. O(K*N) given K runner ups. Overall: O(NLogM + N*K) + // both the member and runner counts are bounded. + exposed_candidates.into_iter().for_each(|c| { + // any candidate who is not a member and not a runner up. + if new_members.binary_search_by_key(&c, |(m, _)| m.clone()).is_err() + && !new_runners_up_ids.contains(&c) + { + let (imbalance, _) = T::Currency::slash_reserved(&c, T::CandidacyBond::get()); + T::LoserCandidate::on_unbalanced(imbalance); + } + }); + + // Burn outgoing bonds + to_burn_bond.into_iter().for_each(|x| { + let (imbalance, _) = T::Currency::slash_reserved(&x, T::CandidacyBond::get()); + T::LoserCandidate::on_unbalanced(imbalance); + }); + + >::put(&new_members); + >::put(new_runners_up); + + Self::deposit_event(RawEvent::NewTerm(new_members.clone().to_vec())); + } else { + Self::deposit_event(RawEvent::EmptyTerm); + } + + // clean candidates. + >::kill(); + + ElectionRounds::mutate(|v| *v += 1); + } +} + +impl Contains for Module { + fn contains(who: &T::AccountId) -> bool { + Self::is_member(who) + } + fn sorted_members() -> Vec { Self::members_ids() } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::cell::RefCell; + use frame_support::{assert_ok, assert_noop, parameter_types, weights::Weight}; + use substrate_test_utils::assert_eq_uvec; + use sp_core::H256; + use sp_runtime::{ + Perbill, testing::Header, BuildStorage, + traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, + }; + use crate as elections; + use frame_system as system; + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + + parameter_types! { + pub const ExistentialDeposit: u64 = 1; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + + impl pallet_balances::Trait for Test { + type Balance = u64; + type OnNewAccount = (); + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type Event = Event; + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + + parameter_types! { + pub const CandidacyBond: u64 = 3; + } + + thread_local! { + static VOTING_BOND: RefCell = RefCell::new(2); + static DESIRED_MEMBERS: RefCell = RefCell::new(2); + static DESIRED_RUNNERS_UP: RefCell = RefCell::new(2); + static TERM_DURATION: RefCell = RefCell::new(5); + } + + pub struct VotingBond; + impl Get for VotingBond { + fn get() -> u64 { VOTING_BOND.with(|v| *v.borrow()) } + } + + pub struct DesiredMembers; + impl Get for DesiredMembers { + fn get() -> u32 { DESIRED_MEMBERS.with(|v| *v.borrow()) } + } + + pub struct DesiredRunnersUp; + impl Get for DesiredRunnersUp { + fn get() -> u32 { DESIRED_RUNNERS_UP.with(|v| *v.borrow()) } + } + + pub struct TermDuration; + impl Get for TermDuration { + fn get() -> u64 { TERM_DURATION.with(|v| *v.borrow()) } + } + + thread_local! { + pub static MEMBERS: RefCell> = RefCell::new(vec![]); + } + + pub struct TestChangeMembers; + impl ChangeMembers for TestChangeMembers { + fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { + // new, incoming, outgoing must be sorted. + let mut new_sorted = new.to_vec(); + new_sorted.sort(); + assert_eq!(new, &new_sorted[..]); + + let mut incoming_sorted = incoming.to_vec(); + incoming_sorted.sort(); + assert_eq!(incoming, &incoming_sorted[..]); + + let mut outgoing_sorted = outgoing.to_vec(); + outgoing_sorted.sort(); + assert_eq!(outgoing, &outgoing_sorted[..]); + + // incoming and outgoing must be disjoint + for x in incoming.iter() { + assert!(outgoing.binary_search(x).is_err()); + } + + let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); + old_plus_incoming.extend_from_slice(incoming); + old_plus_incoming.sort(); + + let mut new_plus_outgoing = new.to_vec(); + new_plus_outgoing.extend_from_slice(outgoing); + new_plus_outgoing.sort(); + + assert_eq!(old_plus_incoming, new_plus_outgoing); + + MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); + } + } + + /// Simple structure that exposes how u64 currency can be represented as... u64. + pub struct CurrencyToVoteHandler; + impl Convert for CurrencyToVoteHandler { + fn convert(x: u64) -> u64 { x } + } + impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { + x as u64 + } + } + + impl Trait for Test { + type Event = Event; + type Currency = Balances; + type CurrencyToVote = CurrencyToVoteHandler; + type ChangeMembers = TestChangeMembers; + type CandidacyBond = CandidacyBond; + type VotingBond = VotingBond; + type TermDuration = TermDuration; + type DesiredMembers = DesiredMembers; + type DesiredRunnersUp = DesiredRunnersUp; + type LoserCandidate = (); + type KickedMember = (); + type BadReport = (); + } + + pub type Block = sp_runtime::generic::Block; + pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; + + frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event}, + Balances: pallet_balances::{Module, Call, Event, Config}, + Elections: elections::{Module, Call, Event}, + } + ); + + pub struct ExtBuilder { + balance_factor: u64, + voter_bond: u64, + term_duration: u64, + desired_runners_up: u32, + } + + impl Default for ExtBuilder { + fn default() -> Self { + Self { + balance_factor: 1, + voter_bond: 2, + desired_runners_up: 0, + term_duration: 5, + } + } + } + + impl ExtBuilder { + pub fn voter_bond(mut self, fee: u64) -> Self { + self.voter_bond = fee; + self + } + pub fn desired_runners_up(mut self, count: u32) -> Self { + self.desired_runners_up = count; + self + } + pub fn term_duration(mut self, duration: u64) -> Self { + self.term_duration = duration; + self + } + pub fn build(self) -> sp_io::TestExternalities { + VOTING_BOND.with(|v| *v.borrow_mut() = self.voter_bond); + TERM_DURATION.with(|v| *v.borrow_mut() = self.term_duration); + DESIRED_RUNNERS_UP.with(|v| *v.borrow_mut() = self.desired_runners_up); + GenesisConfig { + pallet_balances: Some(pallet_balances::GenesisConfig::{ + balances: vec![ + (1, 10 * self.balance_factor), + (2, 20 * self.balance_factor), + (3, 30 * self.balance_factor), + (4, 40 * self.balance_factor), + (5, 50 * self.balance_factor), + (6, 60 * self.balance_factor) + ], + vesting: vec![], + }), + }.build_storage().unwrap().into() + } + } + + fn all_voters() -> Vec { + >::enumerate().map(|(v, _)| v).collect::>() + } + + fn balances(who: &u64) -> (u64, u64) { + (Balances::free_balance(who), Balances::reserved_balance(who)) + } + + fn has_lock(who: &u64) -> u64 { + let lock = Balances::locks(who)[0].clone(); + assert_eq!(lock.id, MODULE_ID); + lock.amount + } + + #[test] + fn params_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::desired_members(), 2); + assert_eq!(Elections::term_duration(), 5); + assert_eq!(Elections::election_rounds(), 0); + + assert_eq!(Elections::members(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + + assert_eq!(Elections::candidates(), vec![]); + assert_eq!(>::decode_len().unwrap(), 0); + assert!(Elections::is_candidate(&1).is_err()); + + assert_eq!(all_voters(), vec![]); + assert_eq!(Elections::votes_of(&1), vec![]); + }); + } + + #[test] + fn term_duration_zero_is_passive() { + ExtBuilder::default() + .term_duration(0) + .build() + .execute_with(|| + { + System::set_block_number(1); + assert_eq!(Elections::term_duration(), 0); + assert_eq!(Elections::desired_members(), 2); + assert_eq!(Elections::election_rounds(), 0); + + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + assert_eq!(Elections::candidates(), vec![]); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + assert_eq!(Elections::candidates(), vec![]); + }); + } + + #[test] + fn simple_candidate_submission_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert!(Elections::is_candidate(&1).is_err()); + assert!(Elections::is_candidate(&2).is_err()); + + assert_eq!(balances(&1), (10, 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_eq!(balances(&1), (7, 3)); + + assert_eq!(Elections::candidates(), vec![1]); + + assert!(Elections::is_candidate(&1).is_ok()); + assert!(Elections::is_candidate(&2).is_err()); + + assert_eq!(balances(&2), (20, 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_eq!(balances(&2), (17, 3)); + + assert_eq!(Elections::candidates(), vec![1, 2]); + + assert!(Elections::is_candidate(&1).is_ok()); + assert!(Elections::is_candidate(&2).is_ok()); + }); + } + + #[test] + fn simple_candidate_submission_with_no_votes_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert!(Elections::is_candidate(&1).is_ok()); + assert!(Elections::is_candidate(&2).is_ok()); + assert_eq!(Elections::candidates(), vec![1, 2]); + + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert!(Elections::is_candidate(&1).is_err()); + assert!(Elections::is_candidate(&2).is_err()); + assert_eq!(Elections::candidates(), vec![]); + + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + }); + } + + #[test] + fn dupe_candidate_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_eq!(Elections::candidates(), vec![1]); + assert_noop!( + Elections::submit_candidacy(Origin::signed(1)), + Error::::DuplicatedCandidate, + ); + }); + } + + #[test] + fn member_candidacy_submission_should_not_work() { + // critically important to make sure that outgoing candidates and losers are not mixed up. + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![5]); + assert_eq!(Elections::runners_up(), vec![]); + assert_eq!(Elections::candidates(), vec![]); + + assert_noop!( + Elections::submit_candidacy(Origin::signed(5)), + Error::::MemberSubmit, + ); + }); + } + + #[test] + fn runner_candidate_submission_should_not_work() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![5, 4], 20)); + assert_ok!(Elections::vote(Origin::signed(1), vec![3], 10)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![3]); + + assert_noop!( + Elections::submit_candidacy(Origin::signed(3)), + Error::::RunnerSubmit, + ); + }); + } + + #[test] + fn poor_candidate_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert_noop!( + Elections::submit_candidacy(Origin::signed(7)), + Error::::InsufficientCandidateFunds, + ); + }); + } + + #[test] + fn simple_voting_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert_eq!(balances(&2), (20, 0)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + + assert_eq!(balances(&2), (18, 2)); + assert_eq!(has_lock(&2), 20); + }); + } + + #[test] + fn can_vote_with_custom_stake() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert_eq!(balances(&2), (20, 0)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 12)); + + assert_eq!(balances(&2), (18, 2)); + assert_eq!(has_lock(&2), 12); + }); + } + + #[test] + fn can_update_votes_and_stake() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(balances(&2), (20, 0)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + + assert_eq!(balances(&2), (18, 2)); + assert_eq!(has_lock(&2), 20); + assert_eq!(Elections::stake_of(2), 20); + + // can update; different stake; different lock and reserve. + assert_ok!(Elections::vote(Origin::signed(2), vec![5, 4], 15)); + assert_eq!(balances(&2), (18, 2)); + assert_eq!(has_lock(&2), 15); + assert_eq!(Elections::stake_of(2), 15); + }); + } + + #[test] + fn cannot_vote_for_no_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + Elections::vote(Origin::signed(2), vec![], 20), + Error::::UnableToVote, + ); + }); + } + + #[test] + fn can_vote_for_old_members_even_when_no_new_candidates() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::candidates(), vec![]); + + assert_ok!(Elections::vote(Origin::signed(3), vec![4, 5], 10)); + }); + } + + #[test] + fn cannot_vote_for_more_than_candidates() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_noop!( + Elections::vote(Origin::signed(2), vec![10, 20, 30], 20), + Error::::TooManyVotes, + ); + }); + } + + #[test] + fn cannot_vote_for_less_than_ed() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_noop!( + Elections::vote(Origin::signed(2), vec![4], 1), + Error::::LowBalance, + ); + }) + } + + #[test] + fn can_vote_for_more_than_total_balance_but_moot() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 30)); + // you can lie but won't get away with it. + assert_eq!(Elections::stake_of(2), 20); + assert_eq!(has_lock(&2), 20); + }); + } + + #[test] + fn remove_voter_should_work() { + ExtBuilder::default().voter_bond(8).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![5], 30)); + + assert_eq_uvec!(all_voters(), vec![2, 3]); + assert_eq!(Elections::stake_of(2), 20); + assert_eq!(Elections::stake_of(3), 30); + assert_eq!(Elections::votes_of(2), vec![5]); + assert_eq!(Elections::votes_of(3), vec![5]); + + assert_ok!(Elections::remove_voter(Origin::signed(2))); + + assert_eq_uvec!(all_voters(), vec![3]); + assert_eq!(Elections::votes_of(2), vec![]); + assert_eq!(Elections::stake_of(2), 0); + + assert_eq!(balances(&2), (20, 0)); + assert_eq!(Balances::locks(&2).len(), 0); + }); + } + + #[test] + fn non_voter_remove_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!(Elections::remove_voter(Origin::signed(3)), Error::::MustBeVoter); + }); + } + + #[test] + fn dupe_remove_should_fail() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + + assert_ok!(Elections::remove_voter(Origin::signed(2))); + assert_eq!(all_voters(), vec![]); + + assert_noop!(Elections::remove_voter(Origin::signed(2)), Error::::MustBeVoter); + }); + } + + #[test] + fn removed_voter_should_not_be_counted() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + assert_ok!(Elections::remove_voter(Origin::signed(4))); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![3, 5]); + }); + } + + #[test] + fn reporter_must_be_voter() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + Elections::report_defunct_voter(Origin::signed(1), 2), + Error::::MustBeVoter, + ); + }); + } + + #[test] + fn can_detect_defunct_voter() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(6))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + assert_ok!(Elections::vote(Origin::signed(6), vec![6], 30)); + // will be soon a defunct voter. + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![6]); + assert_eq!(Elections::candidates(), vec![]); + + // all of them have a member or runner-up that they voted for. + assert_eq!(Elections::is_defunct_voter(&5), false); + assert_eq!(Elections::is_defunct_voter(&4), false); + assert_eq!(Elections::is_defunct_voter(&2), false); + assert_eq!(Elections::is_defunct_voter(&6), false); + + // defunct + assert_eq!(Elections::is_defunct_voter(&3), true); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); + + // has a candidate voted for. + assert_eq!(Elections::is_defunct_voter(&1), false); + + }); + } + + #[test] + fn report_voter_should_work_and_earn_reward() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + // will be soon a defunct voter. + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::candidates(), vec![]); + + assert_eq!(balances(&3), (28, 2)); + assert_eq!(balances(&5), (45, 5)); + + assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 3)); + assert_eq!( + System::events()[1].event, + Event::elections(RawEvent::VoterReported(3, 5, true)) + ); + + assert_eq!(balances(&3), (28, 0)); + assert_eq!(balances(&5), (47, 5)); + }); + } + + #[test] + fn report_voter_should_slash_when_bad_report() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::candidates(), vec![]); + + assert_eq!(balances(&4), (35, 5)); + assert_eq!(balances(&5), (45, 5)); + + assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 4)); + assert_eq!( + System::events()[1].event, + Event::elections(RawEvent::VoterReported(4, 5, false)) + ); + + assert_eq!(balances(&4), (35, 5)); + assert_eq!(balances(&5), (45, 3)); + }); + } + + + #[test] + fn simple_voting_rounds_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 15)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + assert_eq_uvec!(all_voters(), vec![2, 3, 4]); + + assert_eq!(Elections::votes_of(2), vec![5]); + assert_eq!(Elections::votes_of(3), vec![3]); + assert_eq!(Elections::votes_of(4), vec![4]); + + assert_eq!(Elections::candidates(), vec![3, 4, 5]); + assert_eq!(>::decode_len().unwrap(), 3); + + assert_eq!(Elections::election_rounds(), 0); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(3, 30), (5, 20)]); + assert_eq!(Elections::runners_up(), vec![]); + assert_eq_uvec!(all_voters(), vec![2, 3, 4]); + assert_eq!(Elections::candidates(), vec![]); + assert_eq!(>::decode_len().unwrap(), 0); + + assert_eq!(Elections::election_rounds(), 1); + }); + } + + #[test] + fn defunct_voter_will_be_counted() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + + // This guy's vote is pointless for this round. + assert_ok!(Elections::vote(Origin::signed(3), vec![4], 30)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(5, 50)]); + assert_eq!(Elections::election_rounds(), 1); + + // but now it has a valid target. + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + + // candidate 4 is affected by an old vote. + assert_eq!(Elections::members(), vec![(4, 30), (5, 50)]); + assert_eq!(Elections::election_rounds(), 2); + assert_eq_uvec!(all_voters(), vec![3, 5]); + }); + } + + #[test] + fn only_desired_seats_are_chosen() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::election_rounds(), 1); + assert_eq!(Elections::members_ids(), vec![4, 5]); + }); + } + + #[test] + fn phragmen_should_not_self_vote() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::candidates(), vec![]); + assert_eq!(Elections::election_rounds(), 1); + assert_eq!(Elections::members_ids(), vec![]); + }); + } + + #[test] + fn runners_up_should_be_kept() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![2], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + // sorted based on account id. + assert_eq!(Elections::members_ids(), vec![4, 5]); + // sorted based on merit (least -> most) + assert_eq!(Elections::runners_up_ids(), vec![3, 2]); + + // runner ups are still locked. + assert_eq!(balances(&4), (35, 5)); + assert_eq!(balances(&5), (45, 5)); + assert_eq!(balances(&3), (25, 5)); + }); + } + + #[test] + fn runners_up_should_be_next_candidates() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members(), vec![(4, 40), (5, 50)]); + assert_eq!(Elections::runners_up(), vec![(2, 20), (3, 30)]); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 15)); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members(), vec![(3, 30), (4, 40)]); + assert_eq!(Elections::runners_up(), vec![(5, 15), (2, 20)]); + }); + } + + #[test] + fn runners_up_lose_bond_once_outgoing() { + ExtBuilder::default().desired_runners_up(1).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![2]); + assert_eq!(balances(&2), (15, 5)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::runners_up_ids(), vec![3]); + assert_eq!(balances(&2), (15, 2)); + }); + } + + #[test] + fn members_lose_bond_once_outgoing() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(balances(&5), (50, 0)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_eq!(balances(&5), (47, 3)); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_eq!(balances(&5), (45, 5)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![5]); + + assert_ok!(Elections::remove_voter(Origin::signed(5))); + assert_eq!(balances(&5), (47, 3)); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![]); + + assert_eq!(balances(&5), (47, 0)); + }); + } + + #[test] + fn losers_will_lose_the_bond() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + + assert_eq!(balances(&5), (47, 3)); + assert_eq!(balances(&3), (27, 3)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![5]); + + // winner + assert_eq!(balances(&5), (47, 3)); + // loser + assert_eq!(balances(&3), (27, 0)); + }); + } + + #[test] + fn current_members_are_always_next_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::election_rounds(), 1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + assert_ok!(Elections::remove_voter(Origin::signed(4))); + + // 5 will persist as candidates despite not being in the list. + assert_eq!(Elections::candidates(), vec![2, 3]); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + + // 4 removed; 5 and 3 are the new best. + assert_eq!(Elections::members_ids(), vec![3, 5]); + }); + } + + #[test] + fn election_state_is_uninterrupted() { + // what I mean by uninterrupted: + // given no input or stimulants the same members are re-elected. + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + + let check_at_block = |b: u32| { + System::set_block_number(b.into()); + assert_ok!(Elections::end_block(System::block_number())); + // we keep re-electing the same folks. + assert_eq!(Elections::members(), vec![(4, 40), (5, 50)]); + assert_eq!(Elections::runners_up(), vec![(2, 20), (3, 30)]); + // no new candidates but old members and runners-up are always added. + assert_eq!(Elections::candidates(), vec![]); + assert_eq!(Elections::election_rounds(), b / 5); + assert_eq_uvec!(all_voters(), vec![2, 3, 4, 5]); + }; + + // this state will always persist when no further input is given. + check_at_block(5); + check_at_block(10); + check_at_block(15); + check_at_block(20); + }); + } + + #[test] + fn remove_members_triggers_election() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::election_rounds(), 1); + + // a new candidate + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + assert_ok!(Elections::remove_member(Origin::ROOT, 4)); + + assert_eq!(balances(&4), (35, 2)); // slashed + assert_eq!(Elections::election_rounds(), 2); // new election round + assert_eq!(Elections::members_ids(), vec![3, 5]); // new members + }); + } + + #[test] + fn seats_should_be_released_when_no_vote() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + assert_eq!(>::decode_len().unwrap(), 3); + + assert_eq!(Elections::election_rounds(), 0); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![3, 5]); + assert_eq!(Elections::election_rounds(), 1); + + assert_ok!(Elections::remove_voter(Origin::signed(2))); + assert_ok!(Elections::remove_voter(Origin::signed(3))); + assert_ok!(Elections::remove_voter(Origin::signed(4))); + assert_ok!(Elections::remove_voter(Origin::signed(5))); + + // meanwhile, no one cares to become a candidate again. + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::election_rounds(), 2); + }); + } + + #[test] + fn incoming_outgoing_are_reported() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![4, 5]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + // 5 will change their vote and becomes an `outgoing` + assert_ok!(Elections::vote(Origin::signed(5), vec![4], 8)); + // 4 will stay in the set + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + // 3 will become a winner + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + // these two are losers. + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + + // 3, 4 are new members, must still be bonded, nothing slashed. + assert_eq!(Elections::members(), vec![(3, 30), (4, 48)]); + assert_eq!(balances(&3), (25, 5)); + assert_eq!(balances(&4), (35, 5)); + + // 1 is a loser, slashed by 3. + assert_eq!(balances(&1), (5, 2)); + + // 5 is an outgoing loser. will also get slashed. + assert_eq!(balances(&5), (45, 2)); + + assert_eq!( + System::events()[0].event, + Event::elections(RawEvent::NewTerm(vec![(4, 40), (5, 50)])), + ); + }) + } + + #[test] + fn invalid_votes_are_moot() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![10], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq_uvec!(Elections::members_ids(), vec![3, 4]); + assert_eq!(Elections::election_rounds(), 1); + }); + } + + #[test] + fn members_are_sorted_based_on_id_runners_on_merit() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![2], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + // id: low -> high. + assert_eq!(Elections::members(), vec![(4, 50), (5, 40)]); + // merit: low -> high. + assert_eq!(Elections::runners_up(), vec![(3, 20), (2, 30)]); + }); + } + + #[test] + fn candidates_are_sorted() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_eq!(Elections::candidates(), vec![3, 5]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); + + assert_eq!(Elections::candidates(), vec![2, 4, 5]); + }) + } + + #[test] + fn runner_up_replacement_maintains_members_order() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![2], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![2, 4]); + assert_ok!(Elections::remove_member(Origin::ROOT, 2)); + assert_eq!(Elections::members_ids(), vec![4, 5]); + }); + } + + #[test] + fn runner_up_replacement_works_when_out_of_order() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![2], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![2, 4]); + assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); + }); + } + + #[test] + fn can_renounce_candidacy_member_with_runners_bond_is_refunded() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![2, 3]); + + assert_ok!(Elections::renounce_candidacy(Origin::signed(4))); + assert_eq!(balances(&4), (38, 2)); // 2 is voting bond. + + assert_eq!(Elections::members_ids(), vec![3, 5]); + assert_eq!(Elections::runners_up_ids(), vec![2]); + }) + } + + #[test] + fn can_renounce_candidacy_member_without_runners_bond_is_refunded() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![]); + assert_eq!(Elections::candidates(), vec![2, 3]); + + assert_ok!(Elections::renounce_candidacy(Origin::signed(4))); + assert_eq!(balances(&4), (38, 2)); // 2 is voting bond. + + // no replacement + assert_eq!(Elections::members_ids(), vec![5]); + assert_eq!(Elections::runners_up_ids(), vec![]); + // still candidate + assert_eq!(Elections::candidates(), vec![2, 3]); + }) + } + + #[test] + fn can_renounce_candidacy_runner() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![2, 3]); + + assert_ok!(Elections::renounce_candidacy(Origin::signed(3))); + assert_eq!(balances(&3), (28, 2)); // 2 is voting bond. + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::runners_up_ids(), vec![2]); + }) + } + + #[test] + fn can_renounce_candidacy_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_eq!(balances(&5), (47, 3)); + assert_eq!(Elections::candidates(), vec![5]); + + assert_ok!(Elections::renounce_candidacy(Origin::signed(5))); + assert_eq!(balances(&5), (50, 0)); + assert_eq!(Elections::candidates(), vec![]); + }) + } + + #[test] + fn wrong_renounce_candidacy_should_fail() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + Elections::renounce_candidacy(Origin::signed(5)), + Error::::InvalidOrigin, + ); + }) + } + + #[test] + fn behavior_with_dupe_candidate() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + >::put(vec![1, 1, 2, 3, 4]); + + assert_ok!(Elections::vote(Origin::signed(5), vec![1], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![1, 4]); + assert_eq!(Elections::runners_up_ids(), vec![2, 3]); + assert_eq!(Elections::candidates(), vec![]); + }) + } +} diff --git a/frame/elections/Cargo.toml b/frame/elections/Cargo.toml new file mode 100644 index 0000000000000..44d624b986240 --- /dev/null +++ b/frame/elections/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "pallet-elections" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +hex-literal = "0.2.1" +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "safe-mix/std", + "codec/std", + "sp-core/std", + "sp-std/std", + "serde", + "sp-io/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", +] diff --git a/frame/elections/src/lib.rs b/frame/elections/src/lib.rs new file mode 100644 index 0000000000000..e722c4db8050e --- /dev/null +++ b/frame/elections/src/lib.rs @@ -0,0 +1,1216 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Election module for stake-weighted membership selection of a collective. +//! +//! The composition of a set of account IDs works according to one or more approval votes +//! weighted by stake. There is a partial carry-over facility to give greater weight to those +//! whose voting is serially unsuccessful. + +#![cfg_attr(not(feature = "std"), no_std)] +#![recursion_limit="128"] + +use sp_std::prelude::*; +use sp_runtime::{ + RuntimeDebug, DispatchResult, print, + traits::{Zero, One, StaticLookup, Bounded, Saturating}, +}; +use frame_support::{ + decl_storage, decl_event, ensure, decl_module, decl_error, + weights::SimpleDispatchInfo, + traits::{ + Currency, ExistenceRequirement, Get, LockableCurrency, LockIdentifier, + OnUnbalanced, ReservableCurrency, WithdrawReason, WithdrawReasons, ChangeMembers + } +}; +use codec::{Encode, Decode}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +mod mock; +mod tests; + +// no polynomial attacks: +// +// all unbonded public operations should be constant time. +// all other public operations must be linear time in terms of prior public operations and: +// - those "valid" ones that cost nothing be limited to a constant number per single protected +// operation +// - the rest costing the same order as the computational complexity +// all protected operations must complete in at most O(public operations) +// +// we assume "beneficial" transactions will have the same access as attack transactions. +// +// any storage requirements should be bonded by the same order as the volume. + +// public operations: +// - express approvals (you pay in a "voter" bond the first time you do this; O(1); one extra DB +// entry, one DB change) +// - remove active voter (you get your "voter" bond back; O(1); one fewer DB entry, one DB change) +// - remove inactive voter (either you or the target is removed; if the target, you get their +// "voter" bond back; O(1); one fewer DB entry, one DB change) +// - submit candidacy (you pay a "candidate" bond; O(1); one extra DB entry, two DB changes) +// - present winner/runner-up (you may pay a "presentation" bond of O(voters) if the presentation +// is invalid; O(voters) compute; ) protected operations: +// - remove candidacy (remove all votes for a candidate) (one fewer DB entry, two DB changes) + +// to avoid a potentially problematic case of not-enough approvals prior to voting causing a +// back-to-back votes that have no way of ending, then there's a forced grace period between votes. +// to keep the system as stateless as possible (making it a bit easier to reason about), we just +// restrict when votes can begin to blocks that lie on boundaries (`voting_period`). + +// for an approval vote of C members: + +// top K runners-up are maintained between votes. all others are discarded. +// - candidate removed & bond returned when elected. +// - candidate removed & bond burned when discarded. + +// at the point that the vote ends (), all voters' balances are snapshotted. + +// for B blocks following, there's a counting period whereby each of the candidates that believe +// they fall in the top K+C voted can present themselves. they get the total stake +// recorded (based on the snapshot); an ordered list is maintained (the leaderboard). Noone may +// present themselves that, if elected, would result in being included twice in the collective +// (important since existing members will have their approval votes as it may be that they +// don't get removed), nor if existing presenters would mean they're not in the top K+C. + +// following B blocks, the top C candidates are elected and have their bond returned. the top C +// candidates and all other candidates beyond the top C+K are cleared. + +// vote-clearing happens lazily; for an approval to count, the most recent vote at the time of the +// voter's most recent vote must be no later than the most recent vote at the time that the +// candidate in the approval position was registered there. as candidates are removed from the +// register and others join in their place, this prevents an approval meant for an earlier candidate +// being used to elect a new candidate. + +// the candidate list increases as needed, but the contents (though not really the capacity) reduce +// after each vote as all but K entries are cleared. newly registering candidates must use cleared +// entries before they increase the capacity. + +/// The activity status of a voter. +#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, Default, RuntimeDebug)] +pub struct VoterInfo { + /// Last VoteIndex in which this voter assigned (or initialized) approvals. + last_active: VoteIndex, + /// Last VoteIndex in which one of this voter's approvals won. + /// Note that `last_win = N` indicates a last win at index `N-1`, hence `last_win = 0` means no + /// win ever. + last_win: VoteIndex, + /// The amount of stored weight as a result of not winning but changing approvals. + pot: Balance, + /// Current staked amount. A lock equal to this value always exists. + stake: Balance, +} + +/// Used to demonstrate the status of a particular index in the global voter list. +#[derive(PartialEq, Eq, RuntimeDebug)] +pub enum CellStatus { + /// Any out of bound index. Means a push a must happen to the chunk pointed by `NextVoterSet`. + /// Voting fee is applied in case a new chunk is created. + Head, + /// Already occupied by another voter. Voting fee is applied. + Occupied, + /// Empty hole which should be filled. No fee will be applied. + Hole, +} + +const MODULE_ID: LockIdentifier = *b"py/elect"; + +/// Number of voters grouped in one chunk. +pub const VOTER_SET_SIZE: usize = 64; +/// NUmber of approvals grouped in one chunk. +pub const APPROVAL_SET_SIZE: usize = 8; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = + <::Currency as Currency<::AccountId>>::NegativeImbalance; + +/// Index used to access chunks. +type SetIndex = u32; +/// Index used to count voting rounds. +pub type VoteIndex = u32; +/// Underlying data type of the approvals. +type ApprovalFlag = u32; +/// Number of approval flags that can fit into [`ApprovalFlag`] type. +const APPROVAL_FLAG_LEN: usize = 32; + +pub trait Trait: frame_system::Trait { + type Event: From> + Into<::Event>; + + /// The currency that people are electing with. + type Currency: + LockableCurrency + + ReservableCurrency; + + /// Handler for the unbalanced reduction when slashing a validator. + type BadPresentation: OnUnbalanced>; + + /// Handler for the unbalanced reduction when slashing an invalid reaping attempt. + type BadReaper: OnUnbalanced>; + + /// Handler for the unbalanced reduction when submitting a bad `voter_index`. + type BadVoterIndex: OnUnbalanced>; + + /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner up) + type LoserCandidate: OnUnbalanced>; + + /// What to do when the members change. + type ChangeMembers: ChangeMembers; + + /// How much should be locked up in order to submit one's candidacy. A reasonable + /// default value is 9. + type CandidacyBond: Get>; + + /// How much should be locked up in order to be able to submit votes. + type VotingBond: Get>; + + /// The amount of fee paid upon each vote submission, unless if they submit a + /// _hole_ index and replace it. + type VotingFee: Get>; + + /// Minimum about that can be used as the locked value for voting. + type MinimumVotingLock: Get>; + + /// The punishment, per voter, if you provide an invalid presentation. A + /// reasonable default value is 1. + type PresentSlashPerVoter: Get>; + + /// How many runners-up should have their approvals persist until the next + /// vote. A reasonable default value is 2. + type CarryCount: Get; + + /// How many vote indices need to go by after a target voter's last vote before + /// they can be reaped if their approvals are moot. A reasonable default value + /// is 1. + type InactiveGracePeriod: Get; + + /// How often (in blocks) to check for new votes. A reasonable default value + /// is 1000. + type VotingPeriod: Get; + + /// Decay factor of weight when being accumulated. It should typically be set to + /// __at least__ `membership_size -1` to keep the collective secure. + /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight + /// increment step `t`. 0 will result in no weight being added at all (normal + /// approval voting). A reasonable default value is 24. + type DecayRatio: Get; +} + +decl_storage! { + trait Store for Module as Council { + // ---- parameters + + /// How long to give each top candidate to present themselves after the vote ends. + pub PresentationDuration get(fn presentation_duration) config(): T::BlockNumber; + /// How long each position is active for. + pub TermDuration get(fn term_duration) config(): T::BlockNumber; + /// Number of accounts that should constitute the collective. + pub DesiredSeats get(fn desired_seats) config(): u32; + + // ---- permanent state (always relevant, changes only at the finalization of voting) + + /// The current membership. When there's a vote going on, this should still be used for + /// executive matters. The block number (second element in the tuple) is the block that + /// their position is active until (calculated by the sum of the block number when the + /// member was elected and their term duration). + pub Members get(fn members) config(): Vec<(T::AccountId, T::BlockNumber)>; + /// The total number of vote rounds that have happened or are in progress. + pub VoteCount get(fn vote_index): VoteIndex; + + // ---- persistent state (always relevant, changes constantly) + + // A list of votes for each voter. The votes are stored as numeric values and parsed in a + // bit-wise manner. In order to get a human-readable representation (`Vec`), use + // [`all_approvals_of`]. Furthermore, each vector of scalars is chunked with the cap of + // `APPROVAL_SET_SIZE`. + pub ApprovalsOf get(fn approvals_of): map (T::AccountId, SetIndex) => Vec; + /// The vote index and list slot that the candidate `who` was registered or `None` if they + /// are not currently registered. + pub RegisterInfoOf get(fn candidate_reg_info): map T::AccountId => Option<(VoteIndex, u32)>; + /// Basic information about a voter. + pub VoterInfoOf get(fn voter_info): map T::AccountId => Option>>; + /// The present voter list (chunked and capped at [`VOTER_SET_SIZE`]). + pub Voters get(fn voters): map SetIndex => Vec>; + /// the next free set to store a voter in. This will keep growing. + pub NextVoterSet get(fn next_nonfull_voter_set): SetIndex = 0; + /// Current number of Voters. + pub VoterCount get(fn voter_count): SetIndex = 0; + /// The present candidate list. + pub Candidates get(fn candidates): Vec; // has holes + /// Current number of active candidates + pub CandidateCount get(fn candidate_count): u32; + + // ---- temporary state (only relevant during finalization/presentation) + + /// The accounts holding the seats that will become free on the next tally. + pub NextFinalize get(fn next_finalize): Option<(T::BlockNumber, u32, Vec)>; + /// Get the leaderboard if we're in the presentation phase. The first element is the weight + /// of each entry; It may be the direct summed approval stakes, or a weighted version of it. + /// Sorted from low to high. + pub Leaderboard get(fn leaderboard): Option, T::AccountId)> >; + + /// Who is able to vote for whom. Value is the fund-holding account, key is the + /// vote-transaction-sending account. + pub Proxy get(fn proxy): map T::AccountId => Option; + } +} + +decl_error! { + /// Error for the elections module. + pub enum Error for Module { + /// Reporter must be a voter. + NotVoter, + /// Target for inactivity cleanup must be active. + InactiveTarget, + /// Cannot reap during presentation period. + CannotReapPresenting, + /// Cannot reap during grace period. + ReapGrace, + /// Not a proxy. + NotProxy, + /// Invalid reporter index. + InvalidReporterIndex, + /// Invalid target index. + InvalidTargetIndex, + /// Invalid vote index. + InvalidVoteIndex, + /// Cannot retract when presenting. + CannotRetractPresenting, + /// Cannot retract non-voter. + RetractNonVoter, + /// Invalid retraction index. + InvalidRetractionIndex, + /// Duplicate candidate submission. + DuplicatedCandidate, + /// Invalid candidate slot. + InvalidCandidateSlot, + /// Candidate has not enough funds. + InsufficientCandidateFunds, + /// Presenter must have sufficient slashable funds. + InsufficientPresenterFunds, + /// Stake deposited to present winner and be added to leaderboard should be non-zero. + ZeroDeposit, + /// Candidate not worthy of leaderboard. + UnworthyCandidate, + /// Leaderboard must exist while present phase active. + LeaderboardMustExist, + /// Cannot present outside of presentation period. + NotPresentationPeriod, + /// Presented candidate must be current. + InvalidCandidate, + /// Duplicated presentation. + DuplicatedPresentation, + /// Incorrect total. + IncorrectTotal, + /// Invalid voter index. + InvalidVoterIndex, + /// New voter must have sufficient funds to pay the bond. + InsufficientVoterFunds, + /// Locked value must be more than limit. + InsufficientLockedValue, + /// Amount of candidate votes cannot exceed amount of candidates. + TooManyVotes, + /// Amount of candidates to receive approval votes should be non-zero. + ZeroCandidates, + /// No approval changes during presentation period. + ApprovalPresentation, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + /// How much should be locked up in order to submit one's candidacy. A reasonable + /// default value is 9. + const CandidacyBond: BalanceOf = T::CandidacyBond::get(); + + /// How much should be locked up in order to be able to submit votes. + const VotingBond: BalanceOf = T::VotingBond::get(); + + /// The amount of fee paid upon each vote submission, unless if they submit a + /// _hole_ index and replace it. + const VotingFee: BalanceOf = T::VotingFee::get(); + + /// The punishment, per voter, if you provide an invalid presentation. A + /// reasonable default value is 1. + const PresentSlashPerVoter: BalanceOf = T::PresentSlashPerVoter::get(); + + /// How many runners-up should have their approvals persist until the next + /// vote. A reasonable default value is 2. + const CarryCount: u32 = T::CarryCount::get(); + + /// How many vote indices need to go by after a target voter's last vote before + /// they can be reaped if their approvals are moot. A reasonable default value + /// is 1. + const InactiveGracePeriod: VoteIndex = T::InactiveGracePeriod::get(); + + /// How often (in blocks) to check for new votes. A reasonable default value + /// is 1000. + const VotingPeriod: T::BlockNumber = T::VotingPeriod::get(); + + /// Minimum about that can be used as the locked value for voting. + const MinimumVotingLock: BalanceOf = T::MinimumVotingLock::get(); + + /// Decay factor of weight when being accumulated. It should typically be set to + /// __at least__ `membership_size -1` to keep the collective secure. + /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight + /// increment step `t`. 0 will result in no weight being added at all (normal + /// approval voting). A reasonable default value is 24. + const DecayRatio: u32 = T::DecayRatio::get(); + + /// The chunk size of the voter vector. + const VOTER_SET_SIZE: u32 = VOTER_SET_SIZE as u32; + /// The chunk size of the approval vector. + const APPROVAL_SET_SIZE: u32 = APPROVAL_SET_SIZE as u32; + + fn deposit_event() = default; + + /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots + /// are registered. + /// + /// Locks `value` from the balance of `origin` indefinitely. Only [`retract_voter`] or + /// [`reap_inactive_voter`] can unlock the balance. + /// + /// `hint` argument is interpreted differently based on: + /// - if `origin` is setting approvals for the first time: The index will be checked for + /// being a valid _hole_ in the voter list. + /// - if the hint is correctly pointing to a hole, no fee is deducted from `origin`. + /// - Otherwise, the call will succeed but the index is ignored and simply a push to the + /// last chunk with free space happens. If the new push causes a new chunk to be + /// created, a fee indicated by [`VotingFee`] is deducted. + /// - if `origin` is already a voter: the index __must__ be valid and point to the correct + /// position of the `origin` in the current voters list. + /// + /// Note that any trailing `false` votes in `votes` is ignored; In approval voting, not + /// voting for a candidate and voting false, are equal. + /// + /// # + /// - O(1). + /// - Two extra DB entries, one DB change. + /// - Argument `votes` is limited in length to number of candidates. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] + fn set_approvals( + origin, + votes: Vec, + #[compact] index: VoteIndex, + hint: SetIndex, + #[compact] value: BalanceOf + ) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_set_approvals(who, votes, index, hint, value) + } + + /// Set candidate approvals from a proxy. Approval slots stay valid as long as candidates in + /// those slots are registered. + /// + /// # + /// - Same as `set_approvals` with one additional storage read. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] + fn proxy_set_approvals(origin, + votes: Vec, + #[compact] index: VoteIndex, + hint: SetIndex, + #[compact] value: BalanceOf + ) -> DispatchResult { + let who = Self::proxy(ensure_signed(origin)?).ok_or(Error::::NotProxy)?; + Self::do_set_approvals(who, votes, index, hint, value) + } + + /// Remove a voter. For it not to be a bond-consuming no-op, all approved candidate indices + /// must now be either unregistered or registered to a candidate that registered the slot + /// after the voter gave their last approval set. + /// + /// Both indices must be provided as explained in [`voter_at`] function. + /// + /// May be called by anyone. Returns the voter deposit to `signed`. + /// + /// # + /// - O(1). + /// - Two fewer DB entries, one DB change. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] + fn reap_inactive_voter( + origin, + #[compact] reporter_index: u32, + who: ::Source, + #[compact] who_index: u32, + #[compact] assumed_vote_index: VoteIndex + ) { + let reporter = ensure_signed(origin)?; + let who = T::Lookup::lookup(who)?; + + ensure!(!Self::presentation_active(), Error::::CannotReapPresenting); + ensure!(Self::voter_info(&reporter).is_some(), Error::::NotVoter); + + let info = Self::voter_info(&who).ok_or(Error::::InactiveTarget)?; + let last_active = info.last_active; + + ensure!(assumed_vote_index == Self::vote_index(), Error::::InvalidVoteIndex); + ensure!( + assumed_vote_index > last_active + T::InactiveGracePeriod::get(), + Error::::ReapGrace, + ); + + let reporter_index = reporter_index as usize; + let who_index = who_index as usize; + let assumed_reporter = Self::voter_at(reporter_index).ok_or(Error::::InvalidReporterIndex)?; + let assumed_who = Self::voter_at(who_index).ok_or(Error::::InvalidTargetIndex)?; + + ensure!(assumed_reporter == reporter, Error::::InvalidReporterIndex); + ensure!(assumed_who == who, Error::::InvalidTargetIndex); + + // will definitely kill one of reporter or who now. + + let valid = !Self::all_approvals_of(&who).iter() + .zip(Self::candidates().iter()) + .any(|(&appr, addr)| + appr && + *addr != T::AccountId::default() && + // defensive only: all items in candidates list are registered + Self::candidate_reg_info(addr).map_or(false, |x| x.0 <= last_active) + ); + + Self::remove_voter( + if valid { &who } else { &reporter }, + if valid { who_index } else { reporter_index } + ); + + T::Currency::remove_lock( + MODULE_ID, + if valid { &who } else { &reporter } + ); + + if valid { + // This only fails if `reporter` doesn't exist, which it clearly must do since its + // the origin. Still, it's no more harmful to propagate any error at this point. + T::Currency::repatriate_reserved(&who, &reporter, T::VotingBond::get())?; + Self::deposit_event(RawEvent::VoterReaped(who, reporter)); + } else { + let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0; + T::BadReaper::on_unbalanced(imbalance); + Self::deposit_event(RawEvent::BadReaperSlashed(reporter)); + } + } + + /// Remove a voter. All votes are cancelled and the voter deposit is returned. + /// + /// The index must be provided as explained in [`voter_at`] function. + /// + /// Also removes the lock on the balance of the voter. See [`do_set_approvals()`]. + /// + /// # + /// - O(1). + /// - Two fewer DB entries, one DB change. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(1_250_000)] + fn retract_voter(origin, #[compact] index: u32) { + let who = ensure_signed(origin)?; + + ensure!(!Self::presentation_active(), Error::::CannotRetractPresenting); + ensure!(>::exists(&who), Error::::RetractNonVoter); + let index = index as usize; + let voter = Self::voter_at(index).ok_or(Error::::InvalidRetractionIndex)?; + ensure!(voter == who, Error::::InvalidRetractionIndex); + + Self::remove_voter(&who, index); + T::Currency::unreserve(&who, T::VotingBond::get()); + T::Currency::remove_lock(MODULE_ID, &who); + } + + /// Submit oneself for candidacy. + /// + /// Account must have enough transferrable funds in it to pay the bond. + /// + /// NOTE: if `origin` has already assigned approvals via [`set_approvals`], + /// it will NOT have any usable funds to pass candidacy bond and must first retract. + /// Note that setting approvals will lock the entire balance of the voter until + /// retraction or being reported. + /// + /// # + /// - Independent of input. + /// - Three DB changes. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] + fn submit_candidacy(origin, #[compact] slot: u32) { + let who = ensure_signed(origin)?; + + ensure!(!Self::is_a_candidate(&who), Error::::DuplicatedCandidate); + let slot = slot as usize; + let count = Self::candidate_count() as usize; + let candidates = Self::candidates(); + ensure!( + (slot == count && count == candidates.len()) || + (slot < candidates.len() && candidates[slot] == T::AccountId::default()), + Error::::InvalidCandidateSlot, + ); + // NOTE: This must be last as it has side-effects. + T::Currency::reserve(&who, T::CandidacyBond::get()) + .map_err(|_| Error::::InsufficientCandidateFunds)?; + + >::insert(&who, (Self::vote_index(), slot as u32)); + let mut candidates = candidates; + if slot == candidates.len() { + candidates.push(who); + } else { + candidates[slot] = who; + } + >::put(candidates); + CandidateCount::put(count as u32 + 1); + } + + /// Claim that `candidate` is one of the top `carry_count + desired_seats` candidates. Only + /// works iff the presentation period is active. `candidate` should have at least collected + /// some non-zero `total` votes and `origin` must have enough funds to pay for a potential + /// slash. + /// + /// # + /// - O(voters) compute. + /// - One DB change. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(10_000_000)] + fn present_winner( + origin, + candidate: ::Source, + #[compact] total: BalanceOf, + #[compact] index: VoteIndex + ) -> DispatchResult { + let who = ensure_signed(origin)?; + ensure!( + !total.is_zero(), + Error::::ZeroDeposit, + ); + + let candidate = T::Lookup::lookup(candidate)?; + ensure!(index == Self::vote_index(), Error::::InvalidVoteIndex); + let (_, _, expiring) = Self::next_finalize() + .ok_or(Error::::NotPresentationPeriod)?; + let bad_presentation_punishment = + T::PresentSlashPerVoter::get() + * BalanceOf::::from(Self::voter_count() as u32); + ensure!( + T::Currency::can_slash(&who, bad_presentation_punishment), + Error::::InsufficientPresenterFunds, + ); + + let mut leaderboard = Self::leaderboard() + .ok_or(Error::::LeaderboardMustExist)?; + ensure!(total > leaderboard[0].0, Error::::UnworthyCandidate); + + if let Some(p) = Self::members().iter().position(|&(ref c, _)| c == &candidate) { + ensure!( + p < expiring.len(), + Error::::DuplicatedCandidate, + ); + } + + let voters = Self::all_voters(); + let (registered_since, candidate_index): (VoteIndex, u32) = + Self::candidate_reg_info(&candidate).ok_or(Error::::InvalidCandidate)?; + let actual_total = voters.iter() + .filter_map(|maybe_voter| maybe_voter.as_ref()) + .filter_map(|voter| match Self::voter_info(voter) { + Some(b) if b.last_active >= registered_since => { + let last_win = b.last_win; + let now = Self::vote_index(); + let stake = b.stake; + let offset = Self::get_offset(stake, now - last_win); + let weight = stake + offset + b.pot; + if Self::approvals_of_at(voter, candidate_index as usize) { + Some(weight) + } else { None } + }, + _ => None, + }) + .fold(Zero::zero(), |acc, n| acc + n); + let dupe = leaderboard.iter().find(|&&(_, ref c)| c == &candidate).is_some(); + if total == actual_total && !dupe { + // insert into leaderboard + leaderboard[0] = (total, candidate); + leaderboard.sort_by_key(|&(t, _)| t); + >::put(leaderboard); + Ok(()) + } else { + // we can rest assured it will be Ok since we checked `can_slash` earlier; still + // better safe than sorry. + let imbalance = T::Currency::slash(&who, bad_presentation_punishment).0; + T::BadPresentation::on_unbalanced(imbalance); + Err(if dupe { Error::::DuplicatedPresentation } else { Error::::IncorrectTotal })? + } + } + + /// Set the desired member count; if lower than the current count, then seats will not be up + /// election when they expire. If more, then a new vote will be started if one is not + /// already in progress. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn set_desired_seats(origin, #[compact] count: u32) { + ensure_root(origin)?; + DesiredSeats::put(count); + } + + /// Remove a particular member from the set. This is effective immediately. + /// + /// Note: A tally should happen instantly (if not already in a presentation + /// period) to fill the seat if removal means that the desired members are not met. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn remove_member(origin, who: ::Source) { + ensure_root(origin)?; + let who = T::Lookup::lookup(who)?; + let new_set: Vec<(T::AccountId, T::BlockNumber)> = Self::members() + .into_iter() + .filter(|i| i.0 != who) + .collect(); + >::put(&new_set); + let new_set = new_set.into_iter().map(|x| x.0).collect::>(); + T::ChangeMembers::change_members(&[], &[who], new_set); + } + + /// Set the presentation duration. If there is currently a vote being presented for, will + /// invoke `finalize_vote`. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn set_presentation_duration(origin, #[compact] count: T::BlockNumber) { + ensure_root(origin)?; + >::put(count); + } + + /// Set the presentation duration. If there is current a vote being presented for, will + /// invoke `finalize_vote`. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn set_term_duration(origin, #[compact] count: T::BlockNumber) { + ensure_root(origin)?; + >::put(count); + } + + fn on_initialize(n: T::BlockNumber) { + if let Err(e) = Self::end_block(n) { + print("Guru meditation"); + print(e); + } + } + } +} + +decl_event!( + pub enum Event where ::AccountId { + /// reaped voter, reaper + VoterReaped(AccountId, AccountId), + /// slashed reaper + BadReaperSlashed(AccountId), + /// A tally (for approval votes of seat(s)) has started. + TallyStarted(u32), + /// A tally (for approval votes of seat(s)) has ended (with one or more new members). + TallyFinalized(Vec, Vec), + } +); + +impl Module { + // exposed immutables. + + /// True if we're currently in a presentation period. + pub fn presentation_active() -> bool { + >::exists() + } + + /// If `who` a candidate at the moment? + pub fn is_a_candidate(who: &T::AccountId) -> bool { + >::exists(who) + } + + /// Iff the member `who` still has a seat at blocknumber `n` returns `true`. + pub fn will_still_be_member_at(who: &T::AccountId, n: T::BlockNumber) -> bool { + Self::members().iter() + .find(|&&(ref a, _)| a == who) + .map(|&(_, expires)| expires > n) + .unwrap_or(false) + } + + /// Determine the block that a vote can happen on which is no less than `n`. + pub fn next_vote_from(n: T::BlockNumber) -> T::BlockNumber { + let voting_period = T::VotingPeriod::get(); + (n + voting_period - One::one()) / voting_period * voting_period + } + + /// The block number on which the tally for the next election will happen. `None` only if the + /// desired seats of the set is zero. + pub fn next_tally() -> Option { + let desired_seats = Self::desired_seats(); + if desired_seats == 0 { + None + } else { + let c = Self::members(); + let (next_possible, count, coming) = + if let Some((tally_end, comers, leavers)) = Self::next_finalize() { + // if there's a tally in progress, then next tally can begin immediately afterwards + (tally_end, c.len() - leavers.len() + comers as usize, comers) + } else { + (>::block_number(), c.len(), 0) + }; + if count < desired_seats as usize { + Some(next_possible) + } else { + // next tally begins once enough members expire to bring members below desired. + if desired_seats <= coming { + // the entire amount of desired seats is less than those new members - we'll + // have to wait until they expire. + Some(next_possible + Self::term_duration()) + } else { + Some(c[c.len() - (desired_seats - coming) as usize].1) + } + }.map(Self::next_vote_from) + } + } + + // Private + /// Check there's nothing to do this block + fn end_block(block_number: T::BlockNumber) -> DispatchResult { + if (block_number % T::VotingPeriod::get()).is_zero() { + if let Some(number) = Self::next_tally() { + if block_number == number { + Self::start_tally(); + } + } + } + if let Some((number, _, _)) = Self::next_finalize() { + if block_number == number { + Self::finalize_tally()? + } + } + Ok(()) + } + + /// Remove a voter at a specified index from the system. + fn remove_voter(voter: &T::AccountId, index: usize) { + let (set_index, vec_index) = Self::split_index(index, VOTER_SET_SIZE); + let mut set = Self::voters(set_index); + set[vec_index] = None; + >::insert(set_index, set); + VoterCount::mutate(|c| *c = *c - 1); + Self::remove_all_approvals_of(voter); + >::remove(voter); + } + + /// Actually do the voting. + /// + /// The voter index must be provided as explained in [`voter_at`] function. + fn do_set_approvals( + who: T::AccountId, + votes: Vec, + index: VoteIndex, + hint: SetIndex, + value: BalanceOf, + ) -> DispatchResult { + let candidates_len = ::Candidates::decode_len().unwrap_or(0_usize); + + ensure!(!Self::presentation_active(), Error::::ApprovalPresentation); + ensure!(index == Self::vote_index(), Error::::InvalidVoteIndex); + ensure!( + !candidates_len.is_zero(), + Error::::ZeroCandidates, + ); + // Prevent a vote from voters that provide a list of votes that exceeds the candidates + // length since otherwise an attacker may be able to submit a very long list of `votes` that + // far exceeds the amount of candidates and waste more computation than a reasonable voting + // bond would cover. + ensure!( + candidates_len >= votes.len(), + Error::::TooManyVotes, + ); + ensure!(value >= T::MinimumVotingLock::get(), Error::::InsufficientLockedValue); + + // Amount to be locked up. + let mut locked_balance = value.min(T::Currency::total_balance(&who)); + let mut pot_to_set = Zero::zero(); + let hint = hint as usize; + + if let Some(info) = Self::voter_info(&who) { + // already a voter. Index must be valid. No fee. update pot. O(1) + let voter = Self::voter_at(hint).ok_or(Error::::InvalidVoterIndex)?; + ensure!(voter == who, Error::::InvalidVoterIndex); + + // write new accumulated offset. + let last_win = info.last_win; + let now = index; + let offset = Self::get_offset(info.stake, now - last_win); + pot_to_set = info.pot + offset; + } else { + // not yet a voter. Index _could be valid_. Fee might apply. Bond will be reserved O(1). + ensure!( + T::Currency::free_balance(&who) > T::VotingBond::get(), + Error::::InsufficientVoterFunds, + ); + + let (set_index, vec_index) = Self::split_index(hint, VOTER_SET_SIZE); + match Self::cell_status(set_index, vec_index) { + CellStatus::Hole => { + // requested cell was a valid hole. + >::mutate(set_index, |set| set[vec_index] = Some(who.clone())); + }, + CellStatus::Head | CellStatus::Occupied => { + // Either occupied or out-of-range. + let next = Self::next_nonfull_voter_set(); + let set_len = >::decode_len(next).unwrap_or(0_usize); + // Caused a new set to be created. Pay for it. + // This is the last potential error. Writes will begin afterwards. + if set_len == 0 { + let imbalance = T::Currency::withdraw( + &who, + T::VotingFee::get(), + WithdrawReason::Fee.into(), + ExistenceRequirement::KeepAlive, + )?; + T::BadVoterIndex::on_unbalanced(imbalance); + // NOTE: this is safe since the `withdraw()` will check this. + locked_balance -= T::VotingFee::get(); + } + if set_len + 1 == VOTER_SET_SIZE { + NextVoterSet::put(next + 1); + } + >::append_or_insert(next, &[Some(who.clone())][..]) + } + } + + T::Currency::reserve(&who, T::VotingBond::get())?; + VoterCount::mutate(|c| *c = *c + 1); + } + + T::Currency::set_lock( + MODULE_ID, + &who, + locked_balance, + T::BlockNumber::max_value(), + WithdrawReasons::all(), + ); + + >::insert( + &who, + VoterInfo::> { + last_active: index, + last_win: index, + stake: locked_balance, + pot: pot_to_set, + } + ); + Self::set_approvals_chunked(&who, votes); + + Ok(()) + } + + /// Close the voting, record the number of seats that are actually up for grabs. + fn start_tally() { + let members = Self::members(); + let desired_seats = Self::desired_seats() as usize; + let number = >::block_number(); + let expiring = + members.iter().take_while(|i| i.1 <= number).map(|i| i.0.clone()).collect::>(); + let retaining_seats = members.len() - expiring.len(); + if retaining_seats < desired_seats { + let empty_seats = desired_seats - retaining_seats; + >::put( + (number + Self::presentation_duration(), empty_seats as u32, expiring) + ); + + // initialize leaderboard. + let leaderboard_size = empty_seats + T::CarryCount::get() as usize; + >::put(vec![(BalanceOf::::zero(), T::AccountId::default()); leaderboard_size]); + + Self::deposit_event(RawEvent::TallyStarted(empty_seats as u32)); + } + } + + /// Finalize the vote, removing each of the `removals` and inserting `seats` of the most + /// approved candidates in their place. If the total number of members is less than the desired + /// membership a new vote is started. Clears all presented candidates, returning the bond of the + /// elected ones. + fn finalize_tally() -> DispatchResult { + let (_, coming, expiring): (T::BlockNumber, u32, Vec) = + >::take() + .ok_or("finalize can only be called after a tally is started.")?; + let leaderboard: Vec<(BalanceOf, T::AccountId)> = >::take() + .unwrap_or_default(); + let new_expiry = >::block_number() + Self::term_duration(); + + // return bond to winners. + let candidacy_bond = T::CandidacyBond::get(); + let incoming: Vec<_> = leaderboard.iter() + .rev() + .take_while(|&&(b, _)| !b.is_zero()) + .take(coming as usize) + .map(|(_, a)| a) + .cloned() + .inspect(|a| { T::Currency::unreserve(a, candidacy_bond); }) + .collect(); + + // Update last win index for anyone voted for any of the incomings. + incoming.iter().filter_map(|i| Self::candidate_reg_info(i)).for_each(|r| { + let index = r.1 as usize; + Self::all_voters() + .iter() + .filter_map(|mv| mv.as_ref()) + .filter(|v| Self::approvals_of_at(*v, index)) + .for_each(|v| >::mutate(v, |a| { + if let Some(activity) = a { activity.last_win = Self::vote_index() + 1; } + })); + }); + let members = Self::members(); + let outgoing: Vec<_> = members.iter() + .take(expiring.len()) + .map(|a| a.0.clone()).collect(); + + // set the new membership set. + let mut new_set: Vec<_> = members + .into_iter() + .skip(expiring.len()) + .chain(incoming.iter().cloned().map(|a| (a, new_expiry))) + .collect(); + new_set.sort_by_key(|&(_, expiry)| expiry); + >::put(&new_set); + + let new_set = new_set.into_iter().map(|x| x.0).collect::>(); + T::ChangeMembers::change_members(&incoming, &outgoing, new_set); + + // clear all except runners-up from candidate list. + let candidates = Self::candidates(); + let mut new_candidates = vec![T::AccountId::default(); candidates.len()]; // shrink later. + let runners_up = leaderboard.into_iter() + .rev() + .take_while(|&(b, _)| !b.is_zero()) + .skip(coming as usize) + .filter_map(|(_, a)| Self::candidate_reg_info(&a).map(|i| (a, i.1))); + let mut count = 0u32; + for (address, slot) in runners_up { + new_candidates[slot as usize] = address; + count += 1; + } + for (old, new) in candidates.iter().zip(new_candidates.iter()) { + // candidate is not a runner up. + if old != new { + // removed - kill it + >::remove(old); + + // and candidate is not a winner. + if incoming.iter().find(|e| *e == old).is_none() { + // slash the bond. + let (imbalance, _) = T::Currency::slash_reserved(&old, T::CandidacyBond::get()); + T::LoserCandidate::on_unbalanced(imbalance); + } + } + } + // discard any superfluous slots. + if let Some(last_index) = new_candidates + .iter() + .rposition(|c| *c != T::AccountId::default()) { + new_candidates.truncate(last_index + 1); + } + + Self::deposit_event(RawEvent::TallyFinalized(incoming, outgoing)); + + >::put(new_candidates); + CandidateCount::put(count); + VoteCount::put(Self::vote_index() + 1); + Ok(()) + } + + /// Get the set and vector index of a global voter index. + /// + /// Note that this function does not take holes into account. + /// See [`voter_at`]. + fn split_index(index: usize, scale: usize) -> (SetIndex, usize) { + let set_index = (index / scale) as u32; + let vec_index = index % scale; + (set_index, vec_index) + } + + /// Return a concatenated vector over all voter sets. + fn all_voters() -> Vec> { + let mut all = >::get(0); + let mut index = 1; + // NOTE: we could also use `Self::next_nonfull_voter_set()` here but that might change based + // on how we do chunking. This is more generic. + loop { + let next_set = >::get(index); + if next_set.is_empty() { + break; + } else { + index += 1; + all.extend(next_set); + } + } + all + } + + /// Shorthand for fetching a voter at a specific (global) index. + /// + /// NOTE: this function is used for checking indices. Yet, it does not take holes into account. + /// This means that any account submitting an index at any point in time should submit: + /// `VOTER_SET_SIZE * set_index + local_index`, meaning that you are ignoring all holes in the + /// first `set_index` sets. + fn voter_at(index: usize) -> Option { + let (set_index, vec_index) = Self::split_index(index, VOTER_SET_SIZE); + let set = Self::voters(set_index); + if vec_index < set.len() { + set[vec_index].clone() + } else { + None + } + } + + /// A more sophisticated version of `voter_at`. Will be kept separate as most often it is an + /// overdue compared to `voter_at`. Only used when setting approvals. + fn cell_status(set_index: SetIndex, vec_index: usize) -> CellStatus { + let set = Self::voters(set_index); + if vec_index < set.len() { + if let Some(_) = set[vec_index] { + CellStatus::Occupied + } else { + CellStatus::Hole + } + } else { + CellStatus::Head + } + } + + /// Sets the approval of a voter in a chunked manner. + fn set_approvals_chunked(who: &T::AccountId, approvals: Vec) { + let approvals_flag_vec = Self::bool_to_flag(approvals); + approvals_flag_vec + .chunks(APPROVAL_SET_SIZE) + .enumerate() + .for_each(|(index, slice)| >::insert( + (&who, index as SetIndex), slice) + ); + } + + /// shorthand for fetching a specific approval of a voter at a specific (global) index. + /// + /// Using this function to read a vote is preferred as it reads `APPROVAL_SET_SIZE` items of + /// type `ApprovalFlag` from storage at most; not all of them. + /// + /// Note that false is returned in case of no-vote or an explicit `false`. + fn approvals_of_at(who: &T::AccountId, index: usize) -> bool { + let (flag_index, bit) = Self::split_index(index, APPROVAL_FLAG_LEN); + let (set_index, vec_index) = Self::split_index(flag_index as usize, APPROVAL_SET_SIZE); + let set = Self::approvals_of((who.clone(), set_index)); + if vec_index < set.len() { + // This is because bit_at treats numbers in lsb -> msb order. + let reversed_index = set.len() - 1 - vec_index; + Self::bit_at(set[reversed_index], bit) + } else { + false + } + } + + /// Return true of the bit `n` of scalar `x` is set to `1` and false otherwise. + fn bit_at(x: ApprovalFlag, n: usize) -> bool { + if n < APPROVAL_FLAG_LEN { + x & ( 1 << n ) != 0 + } else { + false + } + } + + /// Convert a vec of boolean approval flags to a vec of integers, as denoted by + /// the type `ApprovalFlag`. see `bool_to_flag_should_work` test for examples. + pub fn bool_to_flag(x: Vec) -> Vec { + let mut result: Vec = Vec::with_capacity(x.len() / APPROVAL_FLAG_LEN); + if x.is_empty() { + return result; + } + result.push(0); + let mut index = 0; + let mut counter = 0; + loop { + let shl_index = counter % APPROVAL_FLAG_LEN; + result[index] += (if x[counter] { 1 } else { 0 }) << shl_index; + counter += 1; + if counter > x.len() - 1 { break; } + if counter % APPROVAL_FLAG_LEN == 0 { + result.push(0); + index += 1; + } + } + result + } + + /// Convert a vec of flags (u32) to boolean. + pub fn flag_to_bool(chunk: Vec) -> Vec { + let mut result = Vec::with_capacity(chunk.len()); + if chunk.is_empty() { return vec![] } + chunk.into_iter() + .map(|num| + (0..APPROVAL_FLAG_LEN).map(|bit| Self::bit_at(num, bit)).collect::>() + ) + .for_each(|c| { + let last_approve = match c.iter().rposition(|n| *n) { + Some(index) => index + 1, + None => 0 + }; + result.extend(c.into_iter().take(last_approve)); + }); + result + } + + /// Return a concatenated vector over all approvals of a voter as boolean. + /// The trailing zeros are removed. + fn all_approvals_of(who: &T::AccountId) -> Vec { + let mut all: Vec = vec![]; + let mut index = 0_u32; + loop { + let chunk = Self::approvals_of((who.clone(), index)); + if chunk.is_empty() { break; } + all.extend(Self::flag_to_bool(chunk)); + index += 1; + } + all + } + + /// Remove all approvals associated with one account. + fn remove_all_approvals_of(who: &T::AccountId) { + let mut index = 0; + loop { + let set = Self::approvals_of((who.clone(), index)); + if set.len() > 0 { + >::remove((who.clone(), index)); + index += 1; + } else { + break + } + } + } + + /// Calculates the offset value (stored pot) of a stake, based on the distance + /// to the last win_index, `t`. Regardless of the internal implementation, + /// it should always be used with the following structure: + /// + /// Given Stake of voter `V` being `x` and distance to last_win index `t`, the new weight + /// of `V` is `x + get_offset(x, t)`. + /// + /// In other words, this function returns everything extra that should be added + /// to a voter's stake value to get the correct weight. Indeed, zero is + /// returned if `t` is zero. + fn get_offset(stake: BalanceOf, t: VoteIndex) -> BalanceOf { + let decay_ratio: BalanceOf = T::DecayRatio::get().into(); + if t > 150 { return stake * decay_ratio } + let mut offset = stake; + let mut r = Zero::zero(); + let decay = decay_ratio + One::one(); + for _ in 0..t { + offset = offset.saturating_sub(offset / decay); + r += offset + } + r + } +} diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs new file mode 100644 index 0000000000000..178637e088883 --- /dev/null +++ b/frame/elections/src/mock.rs @@ -0,0 +1,288 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Mock file for election module. + +#![cfg(test)] + +use std::cell::RefCell; +use frame_support::{ + StorageValue, StorageMap, parameter_types, assert_ok, + traits::{Get, ChangeMembers, Currency}, + weights::Weight, +}; +use sp_core::H256; +use sp_runtime::{ + Perbill, BuildStorage, testing::Header, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, +}; +use crate as elections; + + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; +} +impl pallet_balances::Trait for Test { + type Balance = u64; + type OnNewAccount = (); + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type Event = Event; + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} + +parameter_types! { + pub const CandidacyBond: u64 = 3; + pub const CarryCount: u32 = 2; + pub const InactiveGracePeriod: u32 = 1; + pub const VotingPeriod: u64 = 4; + pub const MinimumVotingLock: u64 = 5; +} + +thread_local! { + static VOTER_BOND: RefCell = RefCell::new(0); + static VOTING_FEE: RefCell = RefCell::new(0); + static PRESENT_SLASH_PER_VOTER: RefCell = RefCell::new(0); + static DECAY_RATIO: RefCell = RefCell::new(0); + static MEMBERS: RefCell> = RefCell::new(vec![]); +} + +pub struct VotingBond; +impl Get for VotingBond { + fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) } +} + +pub struct VotingFee; +impl Get for VotingFee { + fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) } +} + +pub struct PresentSlashPerVoter; +impl Get for PresentSlashPerVoter { + fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) } +} + +pub struct DecayRatio; +impl Get for DecayRatio { + fn get() -> u32 { DECAY_RATIO.with(|v| *v.borrow()) } +} + +pub struct TestChangeMembers; +impl ChangeMembers for TestChangeMembers { + fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { + let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); + old_plus_incoming.extend_from_slice(incoming); + old_plus_incoming.sort(); + let mut new_plus_outgoing = new.to_vec(); + new_plus_outgoing.extend_from_slice(outgoing); + new_plus_outgoing.sort(); + assert_eq!(old_plus_incoming, new_plus_outgoing); + + MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); + } +} + +impl elections::Trait for Test { + type Event = Event; + type Currency = Balances; + type BadPresentation = (); + type BadReaper = (); + type BadVoterIndex = (); + type LoserCandidate = (); + type ChangeMembers = TestChangeMembers; + type CandidacyBond = CandidacyBond; + type VotingBond = VotingBond; + type VotingFee = VotingFee; + type MinimumVotingLock = MinimumVotingLock; + type PresentSlashPerVoter = PresentSlashPerVoter; + type CarryCount = CarryCount; + type InactiveGracePeriod = InactiveGracePeriod; + type VotingPeriod = VotingPeriod; + type DecayRatio = DecayRatio; +} + +pub type Block = sp_runtime::generic::Block; +pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; + +use frame_system as system; +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event}, + Balances: pallet_balances::{Module, Call, Event, Config}, + Elections: elections::{Module, Call, Event, Config}, + } +); + +pub struct ExtBuilder { + balance_factor: u64, + decay_ratio: u32, + desired_seats: u32, + voting_fee: u64, + voter_bond: u64, + bad_presentation_punishment: u64, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + balance_factor: 1, + decay_ratio: 24, + desired_seats: 2, + voting_fee: 0, + voter_bond: 0, + bad_presentation_punishment: 1, + } + } +} + +impl ExtBuilder { + pub fn balance_factor(mut self, factor: u64) -> Self { + self.balance_factor = factor; + self + } + pub fn decay_ratio(mut self, ratio: u32) -> Self { + self.decay_ratio = ratio; + self + } + pub fn voting_fee(mut self, fee: u64) -> Self { + self.voting_fee = fee; + self + } + pub fn bad_presentation_punishment(mut self, fee: u64) -> Self { + self.bad_presentation_punishment = fee; + self + } + pub fn voter_bond(mut self, fee: u64) -> Self { + self.voter_bond = fee; + self + } + pub fn desired_seats(mut self, seats: u32) -> Self { + self.desired_seats = seats; + self + } + pub fn build(self) -> sp_io::TestExternalities { + VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond); + VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee); + PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment); + DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio); + GenesisConfig { + pallet_balances: Some(pallet_balances::GenesisConfig::{ + balances: vec![ + (1, 10 * self.balance_factor), + (2, 20 * self.balance_factor), + (3, 30 * self.balance_factor), + (4, 40 * self.balance_factor), + (5, 50 * self.balance_factor), + (6, 60 * self.balance_factor) + ], + vesting: vec![], + }), + elections: Some(elections::GenesisConfig::{ + members: vec![], + desired_seats: self.desired_seats, + presentation_duration: 2, + term_duration: 5, + }), + }.build_storage().unwrap().into() + } +} + +pub(crate) fn voter_ids() -> Vec { + Elections::all_voters().iter().map(|v| v.unwrap_or(0) ).collect::>() +} + +pub(crate) fn vote(i: u64, l: usize) { + let _ = Balances::make_free_balance_be(&i, 20); + assert_ok!( + Elections::set_approvals( + Origin::signed(i), + (0..l).map(|_| true).collect::>(), + 0, + 0, + 20, + ) + ); +} + +pub(crate) fn vote_at(i: u64, l: usize, index: elections::VoteIndex) { + let _ = Balances::make_free_balance_be(&i, 20); + assert_ok!( + Elections::set_approvals( + Origin::signed(i), + (0..l).map(|_| true).collect::>(), + 0, + index, + 20, + ) + ); +} + +pub(crate) fn create_candidate(i: u64, index: u32) { + let _ = Balances::make_free_balance_be(&i, 20); + assert_ok!(Elections::submit_candidacy(Origin::signed(i), index)); +} + +pub(crate) fn balances(who: &u64) -> (u64, u64) { + (Balances::free_balance(who), Balances::reserved_balance(who)) +} + +pub(crate) fn locks(who: &u64) -> Vec { + Balances::locks(who).iter().map(|l| l.amount).collect::>() +} + +pub(crate) fn new_test_ext_with_candidate_holes() -> sp_io::TestExternalities { + let mut t = ExtBuilder::default().build(); + t.execute_with(|| { + >::put(vec![0, 0, 1]); + elections::CandidateCount::put(1); + >::insert(1, (0, 2)); + }); + t +} diff --git a/frame/elections/src/tests.rs b/frame/elections/src/tests.rs new file mode 100644 index 0000000000000..48161bcee49ac --- /dev/null +++ b/frame/elections/src/tests.rs @@ -0,0 +1,1684 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for election module. + +#![cfg(test)] + +use crate::mock::*; +use crate::*; + +use frame_support::{assert_ok, assert_err, assert_noop}; + +#[test] +fn params_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::next_vote_from(1), 4); + assert_eq!(Elections::next_vote_from(4), 4); + assert_eq!(Elections::next_vote_from(5), 8); + assert_eq!(Elections::vote_index(), 0); + assert_eq!(Elections::presentation_duration(), 2); + assert_eq!(Elections::term_duration(), 5); + assert_eq!(Elections::desired_seats(), 2); + + assert_eq!(Elections::members(), vec![]); + assert_eq!(Elections::next_tally(), Some(4)); + assert_eq!(Elections::presentation_active(), false); + assert_eq!(Elections::next_finalize(), None); + + assert_eq!(Elections::candidates(), Vec::::new()); + assert_eq!(Elections::is_a_candidate(&1), false); + assert_eq!(Elections::candidate_reg_info(1), None); + + assert_eq!(Elections::voters(0), Vec::>::new()); + assert_eq!(Elections::voter_info(1), None); + assert_eq!(Elections::all_approvals_of(&1), vec![]); + }); +} + +#[test] +fn chunking_bool_to_flag_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::bool_to_flag(vec![]), vec![]); + assert_eq!(Elections::bool_to_flag(vec![false]), vec![0]); + assert_eq!(Elections::bool_to_flag(vec![true]), vec![1]); + assert_eq!(Elections::bool_to_flag(vec![true, true, true, true]), vec![15]); + assert_eq!(Elections::bool_to_flag(vec![true, true, true, true, true]), vec![15 + 16]); + + let set_1 = vec![ + true, false, false, false, // 0x1 + false, true, true, true, // 0xE + ]; + assert_eq!( + Elections::bool_to_flag(set_1.clone()), + vec![0x00_00_00_E1_u32] + ); + assert_eq!( + Elections::flag_to_bool(vec![0x00_00_00_E1_u32]), + set_1 + ); + + let set_2 = vec![ + false, false, false, true, // 0x8 + false, true, false, true, // 0xA + ]; + assert_eq!( + Elections::bool_to_flag(set_2.clone()), + vec![0x00_00_00_A8_u32] + ); + assert_eq!( + Elections::flag_to_bool(vec![0x00_00_00_A8_u32]), + set_2 + ); + + let mut rhs = (0..100/APPROVAL_FLAG_LEN).map(|_| 0xFFFFFFFF_u32).collect::>(); + // NOTE: this might be need change based on `APPROVAL_FLAG_LEN`. + rhs.extend(vec![0x00_00_00_0F]); + assert_eq!( + Elections::bool_to_flag((0..100).map(|_| true).collect()), + rhs + ) + }) +} + +#[test] +fn chunking_voter_set_growth_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + // create 65. 64 (set0) + 1 (set1) + (1..=63).for_each(|i| vote(i, 0)); + assert_eq!(Elections::next_nonfull_voter_set(), 0); + vote(64, 0); + assert_eq!(Elections::next_nonfull_voter_set(), 1); + vote(65, 0); + + let set1 = Elections::voters(0); + let set2 = Elections::voters(1); + + assert_eq!(set1.len(), 64); + assert_eq!(set2.len(), 1); + + assert_eq!(set1[0], Some(1)); + assert_eq!(set1[10], Some(11)); + assert_eq!(set2[0], Some(65)); + }) +} + +#[test] +fn chunking_voter_set_reclaim_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + (1..=129).for_each(|i| vote(i, 0)); + assert_eq!(Elections::next_nonfull_voter_set(), 2); + + assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); + + assert_ok!(Elections::retract_voter(Origin::signed(66), 65)); + assert_ok!(Elections::retract_voter(Origin::signed(67), 66)); + + // length does not show it but holes do exist. + assert_eq!(Elections::voters(0).len(), 64); + assert_eq!(Elections::voters(1).len(), 64); + assert_eq!(Elections::voters(2).len(), 1); + + assert_eq!(Elections::voters(0)[10], None); + assert_eq!(Elections::voters(1)[1], None); + assert_eq!(Elections::voters(1)[2], None); + // Next set with capacity is 2. + assert_eq!(Elections::next_nonfull_voter_set(), 2); + + // But we can fill a hole. + vote_at(130, 0, 10); + + // Nothing added to set 2. A hole was filled. + assert_eq!(Elections::voters(0).len(), 64); + assert_eq!(Elections::voters(1).len(), 64); + assert_eq!(Elections::voters(2).len(), 1); + + // and the next two (scheduled) to the second set. + assert_eq!(Elections::next_nonfull_voter_set(), 2); + }) +} + +#[test] +fn chunking_approvals_set_growth_should_work() { + ExtBuilder::default().build().execute_with(|| { + // create candidates and voters. + (1..=250).for_each(|i| create_candidate(i, (i-1) as u32)); + (1..=250).for_each(|i| vote(i, i as usize)); + + // all approvals of should return the exact expected vector. + assert_eq!( + Elections::all_approvals_of(&180), + (0..180).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&32), + (0..32).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&8), + (0..8).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&64), + (0..64).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&65), + (0..65).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&63), + (0..63).map(|_| true).collect::>() + ); + + // NOTE: assuming that APPROVAL_SET_SIZE is more or less small-ish. Might fail otherwise. + let full_sets = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; + let left_over = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; + let rem = 180 % APPROVAL_FLAG_LEN; + + // grab and check the last full set, if it exists. + if full_sets > 0 { + assert_eq!( + Elections::approvals_of((180, (full_sets-1) as SetIndex )), + Elections::bool_to_flag( + (0..APPROVAL_SET_SIZE * APPROVAL_FLAG_LEN) + .map(|_| true).collect::>() + ) + ); + } + + // grab and check the last, half-empty, set. + if left_over > 0 { + assert_eq!( + Elections::approvals_of((180, full_sets as SetIndex)), + Elections::bool_to_flag( + (0..left_over * APPROVAL_FLAG_LEN + rem) + .map(|_| true).collect::>() + ) + ); + } + }) +} + +#[test] +fn chunking_cell_status_works() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + (1..=63).for_each(|i| vote(i, 0)); + + assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); + assert_ok!(Elections::retract_voter(Origin::signed(21), 20)); + + assert_eq!(Elections::cell_status(0, 10), CellStatus::Hole); + assert_eq!(Elections::cell_status(0, 0), CellStatus::Occupied); + assert_eq!(Elections::cell_status(0, 20), CellStatus::Hole); + assert_eq!(Elections::cell_status(0, 63), CellStatus::Head); + assert_eq!(Elections::cell_status(1, 0), CellStatus::Head); + assert_eq!(Elections::cell_status(1, 10), CellStatus::Head); + }) +} + +#[test] +fn chunking_voter_index_does_not_take_holes_into_account() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + // create 65. 64 (set0) + 1 (set1) + (1..=65).for_each(|i| vote(i, 0)); + + // account 65 has global index 65. + assert_eq!(Elections::voter_at(64).unwrap(), 65); + + assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); + + // still the same. These holes are in some other set. + assert_eq!(Elections::voter_at(64).unwrap(), 65); + // proof: can submit a new approval with the old index. + assert_noop!( + Elections::set_approvals(Origin::signed(65), vec![], 0, 64 - 2, 10), + Error::::InvalidVoterIndex, + ); + assert_ok!(Elections::set_approvals(Origin::signed(65), vec![], 0, 64, 10)); + }) +} + +#[test] +fn chunking_approval_storage_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); + + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false], 0, 0, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 0, 40)); + + assert_eq!(Elections::all_approvals_of(&2), vec![true]); + // NOTE: these two are stored in mem differently though. + assert_eq!(Elections::all_approvals_of(&3), vec![]); + assert_eq!(Elections::all_approvals_of(&4), vec![]); + + assert_eq!(Elections::approvals_of((3, 0)), vec![0]); + assert_eq!(Elections::approvals_of((4, 0)), vec![]); + }); +} + +#[test] +fn voting_initial_set_approvals_ignores_voter_index() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + // Last argument is essentially irrelevant. You might get or miss a tip. + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 5, 40)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![], 0, 100, 50)); + + // indices are more or less ignored. all is pushed. + assert_eq!(voter_ids(), vec![3, 4, 5]); + }) +} +#[test] +fn voting_bad_approval_index_slashes_voters_and_bond_reduces_stake() { + ExtBuilder::default().voting_fee(5).voter_bond(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + (1..=63).for_each(|i| vote(i, 0)); + assert_eq!(balances(&1), (13, 2)); + assert_eq!(balances(&10), (18, 2)); + assert_eq!(balances(&60), (18, 2)); + + // still no fee + vote(64, 0); + assert_eq!(balances(&64), (18, 2)); + assert_eq!( + Elections::voter_info(&64).unwrap(), + VoterInfo { last_win: 0, last_active: 0, stake: 20, pot:0 } + ); + + assert_eq!(Elections::next_nonfull_voter_set(), 1); + + // now we charge the next voter. + vote(65, 0); + assert_eq!(balances(&65), (13, 2)); + assert_eq!( + Elections::voter_info(&65).unwrap(), + VoterInfo { last_win: 0, last_active: 0, stake: 15, pot:0 } + ); + }); +} + +#[test] +fn voting_subsequent_set_approvals_checks_voter_index() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 5, 40)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![], 0, 100, 50)); + + // invalid index + assert_noop!( + Elections::set_approvals(Origin::signed(4), vec![true], 0, 5, 40), + Error::::InvalidVoterIndex, + ); + // wrong index + assert_noop!( + Elections::set_approvals(Origin::signed(4), vec![true], 0, 0, 40), + Error::::InvalidVoterIndex, + ); + // correct + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1, 40)); + }) +} + +#[test] +fn voting_cannot_lock_less_than_limit() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + assert_noop!( + Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 4), + Error::::InsufficientLockedValue, + ); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 5)); + }); +} + +#[test] +fn voting_locking_more_than_total_balance_is_moot() { + ExtBuilder::default().voter_bond(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + assert_eq!(balances(&3), (30, 0)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 35)); + + assert_eq!(balances(&3), (28, 2)); + assert_eq!( + Elections::voter_info(&3).unwrap(), + VoterInfo { last_win: 0, last_active: 0, stake: 30, pot:0 } + ); + }); +} + +#[test] +fn voting_locking_stake_and_reserving_bond_works() { + ExtBuilder::default().voter_bond(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + + assert_eq!(balances(&2), (20, 0)); + assert_eq!(locks(&2), vec![]); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![], 0, 0, 15)); + assert_eq!(balances(&2), (18, 2)); + assert_eq!(locks(&2), vec![15]); + + // deposit a bit more. + let _ = Balances::make_free_balance_be(&2, 100); + + // change vote + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 70)); + assert_eq!(balances(&2), (100, 2)); + assert_eq!(locks(&2), vec![70]); + + assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); + + assert_eq!(balances(&2), (102, 0)); + assert_eq!(locks(&2), vec![]); + }); +} + +#[test] +fn voting_without_any_candidate_count_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_eq!(Elections::candidates().len(), 0); + + assert_noop!( + Elections::set_approvals(Origin::signed(4), vec![], 0, 0, 40), + Error::::ZeroCandidates, + ); + }); +} + +#[test] +fn voting_setting_an_approval_vote_count_more_than_candidate_count_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_eq!(Elections::candidates().len(), 1); + + assert_noop!( + Elections::set_approvals(Origin::signed(4),vec![true, true], 0, 0, 40), + Error::::TooManyVotes, + ); + }); +} + +#[test] +fn voting_resubmitting_approvals_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 0, 40)); + + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_eq!(Elections::candidates().len(), 3); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true, false, true], 0, 0, 40)); + + assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); + }); +} + +#[test] +fn voting_retracting_voter_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_eq!(Elections::candidates().len(), 1); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 1, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![true], 0, 2, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 3, 40)); + + assert_eq!(voter_ids(), vec![1, 2, 3, 4]); + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&2), vec![true]); + assert_eq!(Elections::all_approvals_of(&3), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + + assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); + + assert_eq!(voter_ids(), vec![0, 2, 3, 4]); + assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&2), vec![true]); + assert_eq!(Elections::all_approvals_of(&3), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + + assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); + + assert_eq!(voter_ids(), vec![0, 0, 3, 4]); + assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&3), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + + assert_ok!(Elections::retract_voter(Origin::signed(3), 2)); + + assert_eq!(voter_ids(), vec![0, 0, 0, 4]); + assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&3), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + }); +} + +#[test] +fn voting_invalid_retraction_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_eq!(voter_ids(), vec![1, 2]); + assert_noop!(Elections::retract_voter(Origin::signed(1), 1), Error::::InvalidRetractionIndex); + }); +} + +#[test] +fn voting_overflow_retraction_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_noop!(Elections::retract_voter(Origin::signed(1), 1), Error::::InvalidRetractionIndex); + }); +} + +#[test] +fn voting_non_voter_retraction_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_noop!(Elections::retract_voter(Origin::signed(2), 0), Error::::RetractNonVoter); + }); +} + +#[test] +fn retracting_inactive_voter_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_ok!(Elections::reap_inactive_voter(Origin::signed(5), + (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), + 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + )); + + assert_eq!(voter_ids(), vec![0, 5]); + assert_eq!(Elections::all_approvals_of(&2).len(), 0); + assert_eq!(Balances::total_balance(&2), 20); + assert_eq!(Balances::total_balance(&5), 50); + }); +} + +#[test] +fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { + ExtBuilder::default().voter_bond(2).build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(11); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + + assert_ok!(Elections::reap_inactive_voter(Origin::signed(5), + (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), + 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + )); + + assert_eq!(voter_ids(), vec![0, 5]); + assert_eq!(Elections::all_approvals_of(&2).len(), 0); + }); +} + +#[test] +fn retracting_inactive_voter_with_bad_reporter_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_noop!(Elections::reap_inactive_voter(Origin::signed(2), + 42, + 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + ), Error::::InvalidReporterIndex); + }); +} + +#[test] +fn retracting_inactive_voter_with_bad_target_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_noop!(Elections::reap_inactive_voter(Origin::signed(2), + (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2, 42, + 2 + ), Error::::InvalidTargetIndex); + }); +} + +#[test] +fn retracting_active_voter_should_slash_reporter() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 2)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false, false, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, false, false], 0, 0, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, true, false], 0, 0, 40)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20 + Elections::get_offset(20, 1), 1)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30 + Elections::get_offset(30, 1), 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::vote_index(), 2); + assert_eq!(::InactiveGracePeriod::get(), 1); + assert_eq!(::VotingPeriod::get(), 4); + assert_eq!(Elections::voter_info(4), Some(VoterInfo { last_win: 1, last_active: 0, stake: 40, pot: 0 })); + + assert_ok!(Elections::reap_inactive_voter(Origin::signed(4), + (voter_ids().iter().position(|&i| i == 4).unwrap() as u32).into(), + 2, + (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + )); + + assert_eq!(voter_ids(), vec![2, 3, 0, 5]); + assert_eq!(Elections::all_approvals_of(&4).len(), 0); + assert_eq!(Balances::total_balance(&4), 40); + }); +} + +#[test] +fn retracting_inactive_voter_by_nonvoter_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_noop!(Elections::reap_inactive_voter(Origin::signed(4), + 0, + 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + ), Error::::NotVoter); + }); +} + +#[test] +fn candidacy_simple_candidate_submission_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_eq!(Elections::candidate_reg_info(1), None); + assert_eq!(Elections::candidate_reg_info(2), None); + assert_eq!(Elections::is_a_candidate(&1), false); + assert_eq!(Elections::is_a_candidate(&2), false); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_eq!(Elections::candidates(), vec![1]); + assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); + assert_eq!(Elections::candidate_reg_info(2), None); + assert_eq!(Elections::is_a_candidate(&1), true); + assert_eq!(Elections::is_a_candidate(&2), false); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_eq!(Elections::candidates(), vec![1, 2]); + assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); + assert_eq!(Elections::candidate_reg_info(2), Some((0, 1))); + assert_eq!(Elections::is_a_candidate(&1), true); + assert_eq!(Elections::is_a_candidate(&2), true); + }); +} + +#[test] +fn candidacy_submission_using_free_slot_should_work() { + let mut t = new_test_ext_with_candidate_holes(); + + t.execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), vec![0, 0, 1]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_eq!(Elections::candidates(), vec![0, 2, 1]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); + assert_eq!(Elections::candidates(), vec![3, 2, 1]); + }); +} + +#[test] +fn candidacy_submission_using_alternative_free_slot_should_work() { + let mut t = new_test_ext_with_candidate_holes(); + + t.execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), vec![0, 0, 1]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_eq!(Elections::candidates(), vec![2, 0, 1]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); + assert_eq!(Elections::candidates(), vec![2, 3, 1]); + }); +} + +#[test] +fn candidacy_submission_not_using_free_slot_should_not_work() { + let mut t = new_test_ext_with_candidate_holes(); + + t.execute_with(|| { + System::set_block_number(1); + assert_noop!( + Elections::submit_candidacy(Origin::signed(4), 3), + Error::::InvalidCandidateSlot + ); + }); +} + +#[test] +fn candidacy_bad_candidate_slot_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_noop!( + Elections::submit_candidacy(Origin::signed(1), 1), + Error::::InvalidCandidateSlot + ); + }); +} + +#[test] +fn candidacy_non_free_candidate_slot_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_eq!(Elections::candidates(), vec![1]); + assert_noop!( + Elections::submit_candidacy(Origin::signed(2), 0), + Error::::InvalidCandidateSlot + ); + }); +} + +#[test] +fn candidacy_dupe_candidate_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_eq!(Elections::candidates(), vec![1]); + assert_noop!( + Elections::submit_candidacy(Origin::signed(1), 1), + Error::::DuplicatedCandidate, + ); + }); +} + +#[test] +fn candidacy_poor_candidate_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_noop!( + Elections::submit_candidacy(Origin::signed(7), 0), + Error::::InsufficientCandidateFunds, + ); + }); +} + +#[test] +fn election_voting_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1, 40)); + + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + assert_eq!(voter_ids(), vec![1, 4]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true, true], 0, 2, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, true], 0, 3, 30)); + + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + assert_eq!(Elections::all_approvals_of(&2), vec![false, true, true]); + assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); + + assert_eq!(voter_ids(), vec![1, 4, 2, 3]); + }); +} + +#[test] +fn election_proxy_voting_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + + >::insert(11, 1); + >::insert(12, 2); + >::insert(13, 3); + >::insert(14, 4); + assert_ok!( + Elections::proxy_set_approvals(Origin::signed(11), vec![true], 0, 0, 10) + ); + assert_ok!( + Elections::proxy_set_approvals(Origin::signed(14), vec![true], 0, 1, 40) + ); + + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + assert_eq!(voter_ids(), vec![1, 4]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + + assert_ok!( + Elections::proxy_set_approvals(Origin::signed(12), vec![false, true], 0, 2, 20) + ); + assert_ok!( + Elections::proxy_set_approvals(Origin::signed(13), vec![false, true], 0, 3, 30) + ); + + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + assert_eq!(Elections::all_approvals_of(&2), vec![false, true]); + assert_eq!(Elections::all_approvals_of(&3), vec![false, true]); + + assert_eq!(voter_ids(), vec![1, 4, 2, 3]); + }); +} + +#[test] +fn election_simple_tally_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_eq!(voter_ids(), vec![2, 5]); + assert_eq!(Elections::all_approvals_of(&2), vec![true]); + assert_eq!(Elections::all_approvals_of(&5), vec![false, true]); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert!(!Elections::presentation_active()); + assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); + + assert!(!Elections::is_a_candidate(&2)); + assert!(!Elections::is_a_candidate(&5)); + assert_eq!(Elections::vote_index(), 1); + assert_eq!( + Elections::voter_info(2), + Some(VoterInfo { last_win: 1, last_active: 0, stake: 20, pot: 0 }) + ); + assert_eq!( + Elections::voter_info(5), + Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 }) + ); + }); +} + +#[test] +fn election_seats_should_be_released() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); + let mut current = System::block_number(); + let free_block; + loop { + current += 1; + System::set_block_number(current); + assert_ok!(Elections::end_block(System::block_number())); + if Elections::members().len() == 0 { + free_block = current; + break; + } + } + // 11 + 2 which is the next voting period. + assert_eq!(free_block, 14); + }); +} + +#[test] +fn election_presentations_with_zero_staked_deposit_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_noop!( + Elections::present_winner(Origin::signed(4), 2, 0, 0), + Error::::ZeroDeposit, + ); + }); +} + +#[test] +fn election_double_presentations_should_be_punished() { + ExtBuilder::default().build().execute_with(|| { + assert!(Balances::can_slash(&4, 10)); + + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + assert_eq!( + Elections::present_winner(Origin::signed(4), 5, 50, 0), + Err(Error::::DuplicatedPresentation.into()), + ); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); + assert_eq!(Balances::total_balance(&4), 38); + }); +} + +#[test] +fn election_presenting_for_double_election_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + // NOTE: This is now mandatory to disable the lock + assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); + assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 1, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_noop!( + Elections::present_winner(Origin::signed(4), 2, 20, 1), + Error::::DuplicatedCandidate, + ); + }); +} + +#[test] +fn election_presenting_loser_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + + assert_eq!(Elections::leaderboard(), Some(vec![ + (30, 3), + (40, 4), + (50, 5), + (60, 1) + ])); + + assert_noop!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Error::::UnworthyCandidate); + }); +} + +#[test] +fn election_presenting_loser_first_should_not_matter() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + + assert_eq!(Elections::leaderboard(), Some(vec![ + (30, 3), + (40, 4), + (50, 5), + (60, 1) + ])); + }); +} + +#[test] +fn election_present_outside_of_presentation_period_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + assert_noop!( + Elections::present_winner(Origin::signed(5), 5, 1, 0), + Error::::NotPresentationPeriod, + ); + }); +} + +#[test] +fn election_present_with_invalid_vote_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_noop!(Elections::present_winner(Origin::signed(4), 2, 20, 1), Error::::InvalidVoteIndex); + }); +} + +#[test] +fn election_present_when_presenter_is_poor_should_not_work() { + let test_present = |p| { + ExtBuilder::default() + .voting_fee(5) + .voter_bond(2) + .bad_presentation_punishment(p) + .build() + .execute_with(|| { + System::set_block_number(4); + let _ = Balances::make_free_balance_be(&1, 15); + assert!(!Elections::presentation_active()); + + // -3 + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_eq!(Balances::free_balance(&1), 12); + // -2 -5 + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 15)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_eq!(Balances::free_balance(&1), 5); + assert_eq!(Balances::reserved_balance(&1), 5); + if p > 5 { + assert_noop!(Elections::present_winner( + Origin::signed(1), 1, 10, 0), + Error::::InsufficientPresenterFunds, + ); + } else { + assert_ok!(Elections::present_winner(Origin::signed(1), 1, 10, 0)); + } + }); + }; + test_present(4); + test_present(6); +} + +#[test] +fn election_invalid_present_tally_should_slash() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + assert_eq!(Balances::total_balance(&4), 40); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_err!(Elections::present_winner(Origin::signed(4), 2, 80, 0), Error::::IncorrectTotal); + + assert_eq!(Balances::total_balance(&4), 38); + }); +} + +#[test] +fn election_runners_up_should_be_kept() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); + + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); + // leaderboard length is the empty seats plus the carry count (i.e. 5 + 2), where those + // to be carried are the lowest and stored in lowest indices + assert_eq!(Elections::leaderboard(), Some(vec![ + (0, 0), + (0, 0), + (0, 0), + (60, 1) + ])); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + assert_eq!(Elections::leaderboard(), Some(vec![ + (30, 3), + (40, 4), + (50, 5), + (60, 1) + ])); + + assert_ok!(Elections::end_block(System::block_number())); + + assert!(!Elections::presentation_active()); + assert_eq!(Elections::members(), vec![(1, 11), (5, 11)]); + + assert!(!Elections::is_a_candidate(&1)); + assert!(!Elections::is_a_candidate(&5)); + assert!(!Elections::is_a_candidate(&2)); + assert!(Elections::is_a_candidate(&3)); + assert!(Elections::is_a_candidate(&4)); + assert_eq!(Elections::vote_index(), 1); + assert_eq!(Elections::voter_info(2), Some(VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0 })); + assert_eq!(Elections::voter_info(3), Some(VoterInfo { last_win: 0, last_active: 0, stake: 30, pot: 0 })); + assert_eq!(Elections::voter_info(4), Some(VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0 })); + assert_eq!(Elections::voter_info(5), Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 })); + assert_eq!(Elections::voter_info(6), Some(VoterInfo { last_win: 1, last_active: 0, stake: 60, pot: 0 })); + assert_eq!(Elections::candidate_reg_info(3), Some((0, 2))); + assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); + }); +} + +#[test] +fn election_second_tally_should_use_runners_up() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![false, false, true, false], 1, 0, 60)); + assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30 + Elections::get_offset(30, 1) + 60, 1)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40 + Elections::get_offset(40, 1), 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert!(!Elections::presentation_active()); + assert_eq!(Elections::members(), vec![(1, 11), (5, 11), (3, 15)]); + + assert!(!Elections::is_a_candidate(&1)); + assert!(!Elections::is_a_candidate(&2)); + assert!(!Elections::is_a_candidate(&3)); + assert!(!Elections::is_a_candidate(&5)); + assert!(Elections::is_a_candidate(&4)); + assert_eq!(Elections::vote_index(), 2); + assert_eq!(Elections::voter_info(2), Some( VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0})); + assert_eq!(Elections::voter_info(3), Some( VoterInfo { last_win: 2, last_active: 0, stake: 30, pot: 0})); + assert_eq!(Elections::voter_info(4), Some( VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0})); + assert_eq!(Elections::voter_info(5), Some( VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0})); + assert_eq!( + Elections::voter_info(6), + Some(VoterInfo { last_win: 2, last_active: 1, stake: 60, pot: 0}) + ); + + assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); + }); +} + +#[test] +fn election_loser_candidates_bond_gets_slashed() { + ExtBuilder::default().desired_seats(1).build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + + assert_eq!(balances(&2), (17, 3)); + + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 0, 0, 50)); + assert_ok!( + Elections::set_approvals(Origin::signed(1), vec![false, true, true, true], 0, 0, 10) + ); + + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(4), 4, 10, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(3), 3, 10, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(2), 2, 10, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 50, 0), Ok(())); + + + // winner + carry + assert_eq!(Elections::leaderboard(), Some(vec![(10, 3), (10, 4), (50, 1)])); + assert_ok!(Elections::end_block(System::block_number())); + assert!(!Elections::presentation_active()); + assert_eq!(Elections::members(), vec![(1, 11)]); + + // account 2 is not a runner up or in leaderboard. + assert_eq!(balances(&2), (17, 0)); + }); +} + +#[test] +fn pot_accumulating_weight_and_decaying_should_work() { + ExtBuilder::default().balance_factor(10).build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); + + assert_ok!( + Elections::set_approvals(Origin::signed(6), vec![true, false, false], 0, 0, 600) + ); + assert_ok!( + Elections::set_approvals(Origin::signed(5), vec![false, true, false], 0, 0, 500) + ); + assert_ok!( + Elections::set_approvals(Origin::signed(1), vec![false, false, true], 0, 0, 100) + ); + + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); + assert_eq!( + Elections::voter_info(6).unwrap(), + VoterInfo { last_win: 1, last_active: 0, stake: 600, pot: 0}, + ); + assert_eq!( + Elections::voter_info(5).unwrap(), + VoterInfo { last_win: 1, last_active: 0, stake: 500, pot: 0}, + ); + assert_eq!( + Elections::voter_info(1).unwrap(), + VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}, + ); + + System::set_block_number(12); + // retract needed to unlock approval funds => submit candidacy again. + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!( + Elections::set_approvals(Origin::signed(6), vec![true, false, false], 1, 0, 600) + ); + assert_ok!( + Elections::set_approvals(Origin::signed(5), vec![false, true, false], 1, 1, 500) + ); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(14); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 1), 1), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 19), (5, 19)]); + assert_eq!( + Elections::voter_info(6).unwrap(), + VoterInfo { last_win: 2, last_active: 1, stake: 600, pot:0 } + ); + assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 2, last_active: 1, stake: 500, pot:0 }); + assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot:0 }); + + System::set_block_number(20); + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 2, 0, 600)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 2, 1, 500)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(22); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 2), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 2), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 2), 2), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96 + 93, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 27), (5, 27)]); + assert_eq!( + Elections::voter_info(6).unwrap(), + VoterInfo { last_win: 3, last_active: 2, stake: 600, pot: 0} + ); + assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 3, last_active: 2, stake: 500, pot: 0}); + assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); + + + System::set_block_number(28); + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 3, 0, 600)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 3, 1, 500)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(30); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 3), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 3), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 3), 3), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96 + 93 + 90, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 35), (5, 35)]); + assert_eq!( + Elections::voter_info(6).unwrap(), + VoterInfo { last_win: 4, last_active: 3, stake: 600, pot: 0} + ); + assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 4, last_active: 3, stake: 500, pot: 0}); + assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); + }) +} + +#[test] +fn pot_winning_resets_accumulated_pot() { + ExtBuilder::default().balance_factor(10).build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 3)); + + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false, false], 0, 0, 600)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, true, false, false], 0, 1, 400)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true, true], 0, 2, 300)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(300, 2), (300, 3), (400, 4), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 11), (4, 11)]); + + System::set_block_number(12); + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(4), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false, false], 1, 0, 600)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, true, false, false], 1, 1, 400)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(14); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300 + Elections::get_offset(300, 1), 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300 + Elections::get_offset(300, 1), 1), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(400, 4), (588, 2), (588, 3), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 19), (3, 19)]); + + System::set_block_number(20); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(22); + // 2 will not get re-elected with 300 + 288, instead just 300. + // because one of 3's candidates (3) won in previous round + // 4 on the other hand will get extra weight since it was unlucky. + assert_eq!(Elections::present_winner(Origin::signed(3), 2, 300, 2), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400 + Elections::get_offset(400, 1), 2), Ok(())); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(4, 27), (2, 27)]); + }) +} + +#[test] +fn pot_resubmitting_approvals_stores_pot() { + ExtBuilder::default() + .voter_bond(0) + .voting_fee(0) + .balance_factor(10) + .build() + .execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); + + assert_ok!( + Elections::set_approvals(Origin::signed(6), vec![true, false, false], 0, 0, 600), + ); + assert_ok!( + Elections::set_approvals(Origin::signed(5), vec![false, true, false], 0, 1, 500), + ); + assert_ok!( + Elections::set_approvals(Origin::signed(1), vec![false, false, true], 0, 2, 100), + ); + + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); + + System::set_block_number(12); + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!( + Elections::set_approvals(Origin::signed(6), vec![true, false, false], 1, 0, 600), + ); + assert_ok!( + Elections::set_approvals(Origin::signed(5), vec![false, true, false], 1, 1, 500), + ); + // give 1 some new high balance + let _ = Balances::make_free_balance_be(&1, 997); + assert_ok!( + Elections::set_approvals(Origin::signed(1), vec![false, false, true], 1, 2, 1000), + ); + assert_eq!(Elections::voter_info(1).unwrap(), + VoterInfo { + stake: 1000, // 997 + 3 which is candidacy bond. + pot: Elections::get_offset(100, 1), + last_active: 1, + last_win: 1, + } + ); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); + + System::set_block_number(14); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); + assert_eq!( + Elections::present_winner(Origin::signed(1), 1, 1000 + 96 /* pot */, 1), + Ok(()), + ); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (500, 5), (600, 6), (1096, 1)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(1, 19), (6, 19)]); + }) +} + +#[test] +fn pot_get_offset_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::get_offset(100, 0), 0); + assert_eq!(Elections::get_offset(100, 1), 96); + assert_eq!(Elections::get_offset(100, 2), 96 + 93); + assert_eq!(Elections::get_offset(100, 3), 96 + 93 + 90); + assert_eq!(Elections::get_offset(100, 4), 96 + 93 + 90 + 87); + // limit + assert_eq!(Elections::get_offset(100, 1000), 100 * 24); + + assert_eq!(Elections::get_offset(50_000_000_000, 0), 0); + assert_eq!(Elections::get_offset(50_000_000_000, 1), 48_000_000_000); + assert_eq!(Elections::get_offset(50_000_000_000, 2), 48_000_000_000 + 46_080_000_000); + assert_eq!(Elections::get_offset(50_000_000_000, 3), 48_000_000_000 + 46_080_000_000 + 44_236_800_000); + assert_eq!( + Elections::get_offset(50_000_000_000, 4), + 48_000_000_000 + 46_080_000_000 + 44_236_800_000 + 42_467_328_000 + ); + // limit + assert_eq!(Elections::get_offset(50_000_000_000, 1000), 50_000_000_000 * 24); + }) +} + +#[test] +fn pot_get_offset_with_zero_decay() { + ExtBuilder::default().decay_ratio(0).build().execute_with(|| { + assert_eq!(Elections::get_offset(100, 0), 0); + assert_eq!(Elections::get_offset(100, 1), 0); + assert_eq!(Elections::get_offset(100, 2), 0); + assert_eq!(Elections::get_offset(100, 3), 0); + // limit + assert_eq!(Elections::get_offset(100, 1000), 0); + }) +} diff --git a/frame/evm/Cargo.toml b/frame/evm/Cargo.toml new file mode 100644 index 0000000000000..933b450ee448a --- /dev/null +++ b/frame/evm/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "pallet-evm" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../timestamp" } +pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +primitive-types = { version = "0.6", default-features = false, features = ["rlp"] } +rlp = { version = "0.4", default-features = false } +evm = { version = "0.14", default-features = false } +sha3 = { version = "0.8", default-features = false } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-core/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "sp-io/std", + "sp-std/std", + "sha3/std", + "rlp/std", + "primitive-types/std", + "evm/std", + "pallet-timestamp/std", +] diff --git a/frame/evm/src/backend.rs b/frame/evm/src/backend.rs new file mode 100644 index 0000000000000..b6c3078a3339a --- /dev/null +++ b/frame/evm/src/backend.rs @@ -0,0 +1,187 @@ +use sp_std::marker::PhantomData; +use sp_std::vec::Vec; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use codec::{Encode, Decode}; +use sp_core::{U256, H256, H160}; +use sp_runtime::traits::UniqueSaturatedInto; +use frame_support::storage::{StorageMap, StorageDoubleMap}; +use sha3::{Keccak256, Digest}; +use evm::Config; +use evm::backend::{Backend as BackendT, ApplyBackend, Apply}; +use crate::{Trait, Accounts, AccountStorages, AccountCodes, Module, Event}; + +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +/// Ethereum account nonce, balance and code. Used by storage. +pub struct Account { + /// Account nonce. + pub nonce: U256, + /// Account balance. + pub balance: U256, +} + +#[derive(Clone, Eq, PartialEq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +/// Ethereum log. Used for `deposit_event`. +pub struct Log { + /// Source address of the log. + pub address: H160, + /// Topics of the log. + pub topics: Vec, + /// Bytearray data of the log. + pub data: Vec, +} + +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +/// External input from the transaction. +pub struct Vicinity { + /// Current transaction gas price. + pub gas_price: U256, + /// Origin of the transaction. + pub origin: H160, +} + +/// Gasometer config used for executor. Currently this is hard-coded to +/// Istanbul hard fork. +pub static GASOMETER_CONFIG: Config = Config::istanbul(); + +/// Substrate backend for EVM. +pub struct Backend<'vicinity, T> { + vicinity: &'vicinity Vicinity, + _marker: PhantomData, +} + +impl<'vicinity, T> Backend<'vicinity, T> { + /// Create a new backend with given vicinity. + pub fn new(vicinity: &'vicinity Vicinity) -> Self { + Self { vicinity, _marker: PhantomData } + } +} + +impl<'vicinity, T: Trait> BackendT for Backend<'vicinity, T> { + fn gas_price(&self) -> U256 { self.vicinity.gas_price } + fn origin(&self) -> H160 { self.vicinity.origin } + + fn block_hash(&self, number: U256) -> H256 { + if number > U256::from(u32::max_value()) { + H256::default() + } else { + let number = T::BlockNumber::from(number.as_u32()); + H256::from_slice(frame_system::Module::::block_hash(number).as_ref()) + } + } + + fn block_number(&self) -> U256 { + let number: u128 = frame_system::Module::::block_number().unique_saturated_into(); + U256::from(number) + } + + fn block_coinbase(&self) -> H160 { + H160::default() + } + + fn block_timestamp(&self) -> U256 { + let now: u128 = pallet_timestamp::Module::::get().unique_saturated_into(); + U256::from(now) + } + + fn block_difficulty(&self) -> U256 { + U256::zero() + } + + fn block_gas_limit(&self) -> U256 { + U256::zero() + } + + fn chain_id(&self) -> U256 { + U256::from(sp_io::misc::chain_id()) + } + + fn exists(&self, _address: H160) -> bool { + true + } + + fn basic(&self, address: H160) -> evm::backend::Basic { + let account = Accounts::get(&address); + + evm::backend::Basic { + balance: account.balance, + nonce: account.nonce, + } + } + + fn code_size(&self, address: H160) -> usize { + AccountCodes::decode_len(&address).unwrap_or(0) + } + + fn code_hash(&self, address: H160) -> H256 { + H256::from_slice(Keccak256::digest(&AccountCodes::get(&address)).as_slice()) + } + + fn code(&self, address: H160) -> Vec { + AccountCodes::get(&address) + } + + fn storage(&self, address: H160, index: H256) -> H256 { + AccountStorages::get(address, index) + } +} + +impl<'vicinity, T: Trait> ApplyBackend for Backend<'vicinity, T> { + fn apply( + &mut self, + values: A, + logs: L, + delete_empty: bool, + ) where + A: IntoIterator>, + I: IntoIterator, + L: IntoIterator, + { + for apply in values { + match apply { + Apply::Modify { + address, basic, code, storage, reset_storage, + } => { + Accounts::mutate(&address, |account| { + account.balance = basic.balance; + account.nonce = basic.nonce; + }); + + if let Some(code) = code { + AccountCodes::insert(address, code); + } + + if reset_storage { + AccountStorages::remove_prefix(address); + } + + for (index, value) in storage { + if value == H256::default() { + AccountStorages::remove(address, index); + } else { + AccountStorages::insert(address, index, value); + } + } + + if delete_empty { + Module::::remove_account_if_empty(&address); + } + }, + Apply::Delete { address } => { + Module::::remove_account(&address) + }, + } + } + + for log in logs { + Module::::deposit_event(Event::Log(Log { + address: log.address, + topics: log.topics, + data: log.data, + })); + } + } +} diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs new file mode 100644 index 0000000000000..8d504127245d0 --- /dev/null +++ b/frame/evm/src/lib.rs @@ -0,0 +1,402 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! EVM execution module for Substrate + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +mod backend; + +pub use crate::backend::{Account, Log, Vicinity, Backend}; + +use sp_std::{vec::Vec, marker::PhantomData}; +use frame_support::{ensure, decl_module, decl_storage, decl_event, decl_error}; +use frame_support::weights::{Weight, WeighData, ClassifyDispatch, DispatchClass, PaysFee}; +use frame_support::traits::{Currency, WithdrawReason, ExistenceRequirement}; +use frame_system::{self as system, ensure_signed}; +use sp_runtime::ModuleId; +use frame_support::weights::SimpleDispatchInfo; +use sp_core::{U256, H256, H160, Hasher}; +use sp_runtime::{ + DispatchResult, traits::{UniqueSaturatedInto, AccountIdConversion, SaturatedConversion}, +}; +use evm::{ExitReason, ExitSucceed, ExitError}; +use evm::executor::StackExecutor; +use evm::backend::ApplyBackend; + +const MODULE_ID: ModuleId = ModuleId(*b"py/ethvm"); + +/// Type alias for currency balance. +pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + +/// Trait that outputs the current transaction gas price. +pub trait FeeCalculator { + /// Return the minimal required gas price. + fn min_gas_price() -> U256; +} + +impl FeeCalculator for () { + fn min_gas_price() -> U256 { U256::zero() } +} + +/// Trait for converting account ids of `balances` module into +/// `H160` for EVM module. +/// +/// Accounts and contracts of this module are stored in its own +/// storage, in an Ethereum-compatible format. In order to communicate +/// with the rest of Substrate module, we require an one-to-one +/// mapping of Substrate account to Ethereum address. +pub trait ConvertAccountId { + /// Given a Substrate address, return the corresponding Ethereum address. + fn convert_account_id(account_id: &A) -> H160; +} + +/// Hash and then truncate the account id, taking the last 160-bit as the Ethereum address. +pub struct HashTruncateConvertAccountId(PhantomData); + +impl Default for HashTruncateConvertAccountId { + fn default() -> Self { + Self(PhantomData) + } +} + +impl> ConvertAccountId for HashTruncateConvertAccountId { + fn convert_account_id(account_id: &A) -> H160 { + let account_id = H::hash(account_id.as_ref()); + let account_id_len = account_id.as_ref().len(); + let mut value = [0u8; 20]; + let value_len = value.len(); + + if value_len > account_id_len { + value[(value_len - account_id_len)..].copy_from_slice(account_id.as_ref()); + } else { + value.copy_from_slice(&account_id.as_ref()[(account_id_len - value_len)..]); + } + + H160::from(value) + } +} + +/// Custom precompiles to be used by EVM engine. +pub trait Precompiles { + /// Try to execute the code address as precompile. If the code address is not + /// a precompile or the precompile is not yet available, return `None`. + /// Otherwise, calculate the amount of gas needed with given `input` and + /// `target_gas`. Return `Some(Ok(status, output, gas_used))` if the execution + /// is successful. Otherwise return `Some(Err(_))`. + fn execute( + address: H160, + input: &[u8], + target_gas: Option + ) -> Option, usize), ExitError>>; +} + +impl Precompiles for () { + fn execute( + _address: H160, + _input: &[u8], + _target_gas: Option + ) -> Option, usize), ExitError>> { + None + } +} + +struct WeightForCallCreate; + +impl WeighData<(&H160, &Vec, &U256, &u32, &U256)> for WeightForCallCreate { + fn weigh_data( + &self, + (_, _, _, gas_provided, gas_price): (&H160, &Vec, &U256, &u32, &U256) + ) -> Weight { + (*gas_price).saturated_into::().saturating_mul(*gas_provided) + } +} + +impl WeighData<(&Vec, &U256, &u32, &U256)> for WeightForCallCreate { + fn weigh_data( + &self, + (_, _, gas_provided, gas_price): (&Vec, &U256, &u32, &U256) + ) -> Weight { + (*gas_price).saturated_into::().saturating_mul(*gas_provided) + } +} + +impl ClassifyDispatch for WeightForCallCreate { + fn classify_dispatch(&self, _: T) -> DispatchClass { + DispatchClass::Normal + } +} + +impl PaysFee for WeightForCallCreate { + fn pays_fee(&self, _: T) -> bool { + true + } +} + +/// EVM module trait +pub trait Trait: frame_system::Trait + pallet_timestamp::Trait { + /// Calculator for current gas price. + type FeeCalculator: FeeCalculator; + /// Convert account ID to H160; + type ConvertAccountId: ConvertAccountId; + /// Currency type for deposit and withdraw. + type Currency: Currency; + /// The overarching event type. + type Event: From + Into<::Event>; + /// Precompiles associated with this EVM engine. + type Precompiles: Precompiles; +} + +decl_storage! { + trait Store for Module as Example { + Accounts get(fn accounts) config(): map H160 => Account; + AccountCodes: map H160 => Vec; + AccountStorages: double_map H160, H256 => H256; + } +} + +decl_event! { + /// EVM events + pub enum Event { + /// Ethereum events from contracts. + Log(Log), + } +} + +decl_error! { + pub enum Error for Module { + /// Not enough balance to perform action + BalanceLow, + /// Calculating total fee overflowed + FeeOverflow, + /// Calculating total payment overflowed + PaymentOverflow, + /// Withdraw fee failed + WithdrawFailed, + /// Gas price is too low. + GasPriceTooLow, + /// Call failed + ExitReasonFailed, + /// Call reverted + ExitReasonRevert, + /// Call returned VM fatal error + ExitReasonFatal, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + /// Despoit balance from currency/balances module into EVM. + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn deposit_balance(origin, value: BalanceOf) { + let sender = ensure_signed(origin)?; + + let imbalance = T::Currency::withdraw( + &sender, + value, + WithdrawReason::Reserve.into(), + ExistenceRequirement::AllowDeath, + )?; + T::Currency::resolve_creating(&Self::account_id(), imbalance); + + let bvalue = U256::from(UniqueSaturatedInto::::unique_saturated_into(value)); + let address = T::ConvertAccountId::convert_account_id(&sender); + Accounts::mutate(&address, |account| { + account.balance += bvalue; + }); + } + + /// Withdraw balance from EVM into currency/balances module. + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn withdraw_balance(origin, value: BalanceOf) { + let sender = ensure_signed(origin)?; + let address = T::ConvertAccountId::convert_account_id(&sender); + let bvalue = U256::from(UniqueSaturatedInto::::unique_saturated_into(value)); + + let mut account = Accounts::get(&address); + account.balance = account.balance.checked_sub(bvalue) + .ok_or(Error::::BalanceLow)?; + + let imbalance = T::Currency::withdraw( + &Self::account_id(), + value, + WithdrawReason::Reserve.into(), + ExistenceRequirement::AllowDeath + )?; + + Accounts::insert(&address, account); + + T::Currency::resolve_creating(&sender, imbalance); + } + + /// Issue an EVM call operation. This is similar to a message call transaction in Ethereum. + #[weight = WeightForCallCreate] + fn call( + origin, + target: H160, + input: Vec, + value: U256, + gas_limit: u32, + gas_price: U256, + ) -> DispatchResult { + let sender = ensure_signed(origin)?; + ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::::GasPriceTooLow); + let source = T::ConvertAccountId::convert_account_id(&sender); + + let vicinity = Vicinity { + gas_price, + origin: source, + }; + + let mut backend = Backend::::new(&vicinity); + let mut executor = StackExecutor::new_with_precompile( + &backend, + gas_limit as usize, + &backend::GASOMETER_CONFIG, + T::Precompiles::execute, + ); + + let total_fee = gas_price.checked_mul(U256::from(gas_limit)) + .ok_or(Error::::FeeOverflow)?; + if Accounts::get(&source).balance < + value.checked_add(total_fee).ok_or(Error::::PaymentOverflow)? + { + Err(Error::::BalanceLow)? + } + executor.withdraw(source, total_fee).map_err(|_| Error::::WithdrawFailed)?; + + let reason = executor.transact_call( + source, + target, + value, + input, + gas_limit as usize, + ); + + let ret = match reason { + ExitReason::Succeed(_) => Ok(()), + ExitReason::Error(_) => Err(Error::::ExitReasonFailed), + ExitReason::Revert(_) => Err(Error::::ExitReasonRevert), + ExitReason::Fatal(_) => Err(Error::::ExitReasonFatal), + }; + let actual_fee = executor.fee(gas_price); + executor.deposit(source, total_fee.saturating_sub(actual_fee)); + + let (values, logs) = executor.deconstruct(); + backend.apply(values, logs, true); + + ret.map_err(Into::into) + } + + /// Issue an EVM create operation. This is similar to a contract creation transaction in + /// Ethereum. + #[weight = WeightForCallCreate] + fn create( + origin, + init: Vec, + value: U256, + gas_limit: u32, + gas_price: U256, + ) -> DispatchResult { + let sender = ensure_signed(origin)?; + ensure!(gas_price >= T::FeeCalculator::min_gas_price(), Error::::GasPriceTooLow); + + let source = T::ConvertAccountId::convert_account_id(&sender); + + let vicinity = Vicinity { + gas_price, + origin: source, + }; + + let mut backend = Backend::::new(&vicinity); + let mut executor = StackExecutor::new_with_precompile( + &backend, + gas_limit as usize, + &backend::GASOMETER_CONFIG, + T::Precompiles::execute, + ); + + let total_fee = gas_price.checked_mul(U256::from(gas_limit)) + .ok_or(Error::::FeeOverflow)?; + if Accounts::get(&source).balance < + value.checked_add(total_fee).ok_or(Error::::PaymentOverflow)? + { + Err(Error::::BalanceLow)? + } + executor.withdraw(source, total_fee).map_err(|_| Error::::WithdrawFailed)?; + + let reason = executor.transact_create( + source, + value, + init, + gas_limit as usize, + ); + + let ret = match reason { + ExitReason::Succeed(_) => Ok(()), + ExitReason::Error(_) => Err(Error::::ExitReasonFailed), + ExitReason::Revert(_) => Err(Error::::ExitReasonRevert), + ExitReason::Fatal(_) => Err(Error::::ExitReasonFatal), + }; + let actual_fee = executor.fee(gas_price); + executor.deposit(source, total_fee.saturating_sub(actual_fee)); + + let (values, logs) = executor.deconstruct(); + backend.apply(values, logs, true); + + ret.map_err(Into::into) + } + } +} + +impl Module { + /// The account ID of the EVM module. + /// + /// This actually does computation. If you need to keep using it, then make sure you cache the + /// value and only call this once. + pub fn account_id() -> T::AccountId { + MODULE_ID.into_account() + } + + /// Check whether an account is empty. + pub fn is_account_empty(address: &H160) -> bool { + let account = Accounts::get(address); + let code_len = AccountCodes::decode_len(address).unwrap_or(0); + + account.nonce == U256::zero() && + account.balance == U256::zero() && + code_len == 0 + } + + /// Remove an account if its empty. + pub fn remove_account_if_empty(address: &H160) { + if Self::is_account_empty(address) { + Self::remove_account(address) + } + } + + /// Remove an account from state. + fn remove_account(address: &H160) { + Accounts::remove(address); + AccountCodes::remove(address); + AccountStorages::remove_prefix(address); + } +} diff --git a/frame/example/Cargo.toml b/frame/example/Cargo.toml new file mode 100644 index 0000000000000..fd80d8b8df179 --- /dev/null +++ b/frame/example/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "pallet-example" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "sp-io/std", + "sp-std/std" +] diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs new file mode 100644 index 0000000000000..80569a1b57374 --- /dev/null +++ b/frame/example/src/lib.rs @@ -0,0 +1,790 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Example Module +//! +//! +//! The Example: A simple example of a runtime module demonstrating +//! concepts, APIs and structures common to most runtime modules. +//! +//! Run `cargo doc --package pallet-example --open` to view this module's documentation. +//! +//! ### Documentation Guidelines: +//! +//! +//! +//! +//! +//! ### Documentation Template:
+//! +//! Copy and paste this template from frame/example/src/lib.rs into file +//! `frame//src/lib.rs` of your own custom module and complete it. +//!

+//! // Add heading with custom module name
+//!
+//! \#  Module
+//!
+//! // Add simple description
+//!
+//! // Include the following links that shows what trait needs to be implemented to use the module
+//! // and the supported dispatchables that are documented in the Call enum.
+//!
+//! - \[`::Trait`](./trait.Trait.html)
+//! - \[`Call`](./enum.Call.html)
+//! - \[`Module`](./struct.Module.html)
+//!
+//! \## Overview
+//!
+//! 
+//! // Short description of module purpose.
+//! // Links to Traits that should be implemented.
+//! // What this module is for.
+//! // What functionality the module provides.
+//! // When to use the module (use case examples).
+//! // How it is used.
+//! // Inputs it uses and the source of each input.
+//! // Outputs it produces.
+//!
+//! 
+//! 
+//!
+//! \## Terminology
+//!
+//! // Add terminology used in the custom module. Include concepts, storage items, or actions that you think
+//! // deserve to be noted to give context to the rest of the documentation or module usage. The author needs to
+//! // use some judgment about what is included. We don't want a list of every storage item nor types - the user
+//! // can go to the code for that. For example, "transfer fee" is obvious and should not be included, but
+//! // "free balance" and "reserved balance" should be noted to give context to the module.
+//! // Please do not link to outside resources. The reference docs should be the ultimate source of truth.
+//!
+//! 
+//!
+//! \## Goals
+//!
+//! // Add goals that the custom module is designed to achieve.
+//!
+//! 
+//!
+//! \### Scenarios
+//!
+//! 
+//!
+//! \#### 
+//!
+//! // Describe requirements prior to interacting with the custom module.
+//! // Describe the process of interacting with the custom module for this scenario and public API functions used.
+//!
+//! \## Interface
+//!
+//! \### Supported Origins
+//!
+//! // What origins are used and supported in this module (root, signed, none)
+//! // i.e. root when \`ensure_root\` used
+//! // i.e. none when \`ensure_none\` used
+//! // i.e. signed when \`ensure_signed\` used
+//!
+//! \`inherent\` 
+//!
+//! 
+//! 
+//!
+//! \### Types
+//!
+//! // Type aliases. Include any associated types and where the user would typically define them.
+//!
+//! \`ExampleType\` 
+//!
+//! 
+//!
+//! // Reference documentation of aspects such as `storageItems` and `dispatchable` functions should only be
+//! // included in the https://docs.rs Rustdocs for Substrate and not repeated in the README file.
+//!
+//! \### Dispatchable Functions
+//!
+//! 
+//!
+//! // A brief description of dispatchable functions and a link to the rustdoc with their actual documentation.
+//!
+//! // MUST have link to Call enum
+//! // MUST have origin information included in function doc
+//! // CAN have more info up to the user
+//!
+//! \### Public Functions
+//!
+//! 
+//!
+//! // A link to the rustdoc and any notes about usage in the module, not for specific functions.
+//! // For example, in the balances module: "Note that when using the publicly exposed functions,
+//! // you (the runtime developer) are responsible for implementing any necessary checks
+//! // (e.g. that the sender is the signer) before calling a function that will affect storage."
+//!
+//! 
+//!
+//! // It is up to the writer of the respective module (with respect to how much information to provide).
+//!
+//! \#### Public Inspection functions - Immutable (getters)
+//!
+//! // Insert a subheading for each getter function signature
+//!
+//! \##### \`example_getter_name()\`
+//!
+//! // What it returns
+//! // Why, when, and how often to call it
+//! // When it could panic or error
+//! // When safety issues to consider
+//!
+//! \#### Public Mutable functions (changing state)
+//!
+//! // Insert a subheading for each setter function signature
+//!
+//! \##### \`example_setter_name(origin, parameter_name: T::ExampleType)\`
+//!
+//! // What state it changes
+//! // Why, when, and how often to call it
+//! // When it could panic or error
+//! // When safety issues to consider
+//! // What parameter values are valid and why
+//!
+//! \### Storage Items
+//!
+//! // Explain any storage items included in this module
+//!
+//! \### Digest Items
+//!
+//! // Explain any digest items included in this module
+//!
+//! \### Inherent Data
+//!
+//! // Explain what inherent data (if any) is defined in the module and any other related types
+//!
+//! \### Events:
+//!
+//! // Insert events for this module if any
+//!
+//! \### Errors:
+//!
+//! // Explain what generates errors
+//!
+//! \## Usage
+//!
+//! // Insert 2-3 examples of usage and code snippets that show how to
+//! // use  module in a custom module.
+//!
+//! \### Prerequisites
+//!
+//! // Show how to include necessary imports for  and derive
+//! // your module configuration trait with the `INSERT_CUSTOM_MODULE_NAME` trait.
+//!
+//! \```rust
+//! use ;
+//!
+//! pub trait Trait: ::Trait { }
+//! \```
+//!
+//! \### Simple Code Snippet
+//!
+//! // Show a simple example (e.g. how to query a public getter function of )
+//!
+//! \### Example from SRML
+//!
+//! // Show a usage example in an actual runtime
+//!
+//! // See:
+//! // - Substrate TCR https://github.com/parity-samples/substrate-tcr
+//! // - Substrate Kitties https://shawntabrizi.github.io/substrate-collectables-workshop/#/
+//!
+//! \## Genesis Config
+//!
+//! 
+//!
+//! \## Dependencies
+//!
+//! // Dependencies on other SRML modules and the genesis config should be mentioned,
+//! // but not the Rust Standard Library.
+//! // Genesis configuration modifications that may be made to incorporate this module
+//! // Interaction with other modules
+//!
+//! 
+//!
+//! \## Related Modules
+//!
+//! // Interaction with other modules in the form of a bullet point list
+//!
+//! \## References
+//!
+//! 
+//!
+//! // Links to reference material, if applicable. For example, Phragmen, W3F research, etc.
+//! // that the implementation is based on.
+//! 

+ +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::marker::PhantomData; +use frame_support::{ + dispatch::DispatchResult, decl_module, decl_storage, decl_event, + weights::{SimpleDispatchInfo, DispatchInfo, DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee}, +}; +use frame_system::{self as system, ensure_signed, ensure_root}; +use codec::{Encode, Decode}; +use sp_runtime::{ + traits::{SignedExtension, Bounded, SaturatedConversion}, + transaction_validity::{ + ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, + }, +}; + +// A custom weight calculator tailored for the dispatch call `set_dummy()`. This actually examines +// the arguments and makes a decision based upon them. +// +// The `WeightData` trait has access to the arguments of the dispatch that it wants to assign a +// weight to. Nonetheless, the trait itself can not make any assumptions about what the generic type +// of the arguments (`T`) is. Based on our needs, we could replace `T` with a more concrete type +// while implementing the trait. The `decl_module!` expects whatever implements `WeighData` to +// replace `T` with a tuple of the dispatch arguments. This is exactly how we will craft the +// implementation below. +// +// The rules of `WeightForSetDummy` are as follows: +// - The final weight of each dispatch is calculated as the argument of the call multiplied by the +// parameter given to the `WeightForSetDummy`'s constructor. +// - assigns a dispatch class `operational` if the argument of the call is more than 1000. +struct WeightForSetDummy(BalanceOf); + +impl WeighData<(&BalanceOf,)> for WeightForSetDummy +{ + fn weigh_data(&self, target: (&BalanceOf,)) -> Weight { + let multiplier = self.0; + (*target.0 * multiplier).saturated_into::() + } +} + +impl ClassifyDispatch<(&BalanceOf,)> for WeightForSetDummy { + fn classify_dispatch(&self, target: (&BalanceOf,)) -> DispatchClass { + if *target.0 > >::from(1000u32) { + DispatchClass::Operational + } else { + DispatchClass::Normal + } + } +} + +impl PaysFee<(&BalanceOf,)> for WeightForSetDummy { + fn pays_fee(&self, _target: (&BalanceOf,)) -> bool { + true + } +} + +/// A type alias for the balance type from this module's point of view. +type BalanceOf = ::Balance; + +/// Our module's configuration trait. All our types and constants go in here. If the +/// module is dependent on specific other modules, then their configuration traits +/// should be added to our implied traits list. +/// +/// `frame_system::Trait` should always be included in our implied traits. +pub trait Trait: pallet_balances::Trait { + /// The overarching event type. + 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(fn 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(fn bar): map T::AccountId => Vec<(T::Balance, u64)>; + // + // For basic value items, you'll get a type which implements + // `frame_support::StorageValue`. For map items, you'll get a type which + // implements `frame_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(fn dummy) config(): Option; + + // A map that has enumerable entries. + Bar get(fn bar) config(): linked_map T::AccountId => T::Balance; + + // this one uses the default, we'll demonstrate the usage of 'mutate' API. + Foo get(fn foo) config(): T::Balance; + } +} + +decl_event!( + /// Events are a 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. + 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. +// +// Anyone can have these functions execute by signing and submitting +// an extrinsic. Ensure that calls into each of these execute in a time, memory and +// using storage space proportional to any costs paid for by the caller or otherwise the +// difficulty of forcing the call to happen. +// +// Generally you'll want to split these into three groups: +// - Public calls that are signed by an external account. +// - Root calls that are allowed to be made only by the governance system. +// - Unsigned calls that can be of two kinds: +// * "Inherent extrinsics" that are opinions generally held by the block +// authors that build child blocks. +// * Unsigned Transactions that are of intrinsic recognisable utility to the +// network, and are validated by the runtime. +// +// Information about where this dispatch initiated from is provided as the first argument +// "origin". As such functions must always look like: +// +// `fn foo(origin, bar: Bar, baz: Baz) -> Result;` +// +// The `Result` is required as part of the syntax (and expands to the conventional dispatch +// result of `Result<(), &'static str>`). +// +// When you come to `impl` them later in the module, you must specify the full type for `origin`: +// +// `fn foo(origin: T::Origin, bar: Bar, baz: Baz) { ... }` +// +// There are three entries in the `frame_system::Origin` enum that correspond +// to the above bullets: `::Signed(AccountId)`, `::Root` and `::None`. You should always match +// against them as the first thing you do in your function. There are three convenience calls +// in system that do the matching for you and return a convenient result: `ensure_signed`, +// `ensure_root` and `ensure_none`. +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 { + /// Deposit one of this module's events by using the default implementation. + /// It is also possible to provide a custom implementation. + /// For non-generic events, the generic parameter just needs to be dropped, so that it + /// looks like: `fn deposit_event() = default;`. + fn deposit_event() = default; + /// 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. + // This just increases the value of `Dummy` by `increase_by`. + // + // Since this is a dispatched function there are two extremely important things to + // remember: + // + // - MUST NOT PANIC: Under no circumstances (save, perhaps, storage getting into an + // irreparably damaged state) must this function panic. + // - NO SIDE-EFFECTS ON ERROR: This function must either complete totally (and return + // `Ok(())` or it must have no side-effects on storage and return `Err('Some reason')`. + // + // The first is relatively easy to audit for - just ensure all panickers are removed from + // logic that executes in production (which you do anyway, right?!). To ensure the second + // is followed, you should do all tests for validity at the top of your function. This + // is stuff like checking the sender (`origin`) or that state is such that the operation + // makes sense. + // + // Once you've determined that it's all good, then enact the operation and change storage. + // If you can't be certain that the operation will succeed without substantial computation + // then you have a classic blockchain attack scenario. The normal way of managing this is + // to attach a bond to the operation. As the first major alteration of storage, reserve + // some value from the sender's account (`Balances` module has a `reserve` function for + // exactly this scenario). This amount should be enough to cover any costs of the + // substantial execution in case it turns out that you can't proceed with the operation. + // + // If it eventually transpires that the operation is fine and, therefore, that the + // expense of the checks should be borne by the network, then you can refund the reserved + // deposit. If, however, the operation turns out to be invalid and the computation is + // wasted, then you can burn it or repatriate elsewhere. + // + // Security bonds ensure that attackers can't game it by ensuring that anyone interacting + // with the system either progresses it or pays for the trouble of faffing around with + // no progress. + // + // If you don't respect these rules, it is likely that your chain will be attackable. + // + // Each transaction can define an optional `#[weight]` attribute to convey a set of static + // information about its dispatch. The `system` and `executive` module then use this + // information to properly execute the transaction, whilst keeping the total load of the + // chain in a moderate rate. + // + // The _right-hand-side_ value of the `#[weight]` attribute can be any type that implements + // a set of traits, namely [`WeighData`] and [`ClassifyDispatch`]. The former conveys the + // weight (a numeric representation of pure execution time and difficulty) of the + // transaction and the latter demonstrates the [`DispatchClass`] of the call. A higher + // weight means a larger transaction (less of which can be placed in a single block). + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn accumulate_dummy(origin, increase_by: T::Balance) -> DispatchResult { + // This is a public call, so we ensure that the origin is some signed account. + let _sender = ensure_signed(origin)?; + + // Read the value of dummy from storage. + // let dummy = Self::dummy(); + // Will also work using the `::get` on the storage item type itself: + // let dummy = >::get(); + + // Calculate the new value. + // let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by); + + // Put the new value into storage. + // >::put(new_dummy); + // Will also work with a reference: + // >::put(&new_dummy); + + // Here's the new one of read and then modify the value. + >::mutate(|dummy| { + let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by); + *dummy = Some(new_dummy); + }); + + // Let's deposit an event to let the outside world know this happened. + Self::deposit_event(RawEvent::Dummy(increase_by)); + + // All good. + Ok(()) + } + + /// A privileged call; in this case it resets our dummy value to something new. + // Implementation of a privileged call. The `origin` parameter is ROOT because + // it's not (directly) from an extrinsic, but rather the system as a whole has decided + // to execute it. Different runtimes have different reasons for allow privileged + // calls to be executed - we don't need to care why. Because it's privileged, we can + // assume it's a one-off operation and substantial processing/storage/memory can be used + // without worrying about gameability or attack scenarios. + // If you do not specify `Result` explicitly as return value, it will be added automatically + // for you and `Ok(())` will be returned. + #[weight = WeightForSetDummy::(>::from(100u32))] + fn set_dummy(origin, #[compact] new_value: T::Balance) { + ensure_root(origin)?; + // Put the new value into storage. + >::put(new_value); + } + + // The signature could also look like: `fn on_initialize()`. + // This function could also very well have a weight annotation, similar to any other. The + // only difference being that if it is not annotated, the default is + // `SimpleDispatchInfo::zero()`, which resolves into no weight. + #[weight = SimpleDispatchInfo::FixedNormal(1000)] + fn on_initialize(_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_finalize()` + #[weight = SimpleDispatchInfo::FixedNormal(2000)] + fn on_finalize(_n: T::BlockNumber) { + // Anything that needs to be done at the end of the block. + // We just kill our dummy storage item. + >::kill(); + } + + // A runtime code run after every block and have access to extended set of APIs. + // + // For instance you can generate extrinsics for the upcoming produced block. + fn offchain_worker(_n: T::BlockNumber) { + // We don't do anything here. + // but we could dispatch extrinsic (transaction/unsigned/inherent) using + // sp_io::submit_extrinsic + } + } +} + +// 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 +// functions that do not write to storage and operation functions that do. +// - Private functions. These are your usual private utilities unavailable to other modules. +impl Module { + // Add public immutables and private mutables. + #[allow(dead_code)] + fn accumulate_foo(origin: T::Origin, increase_by: T::Balance) -> DispatchResult { + let _sender = ensure_signed(origin)?; + + let prev = >::get(); + // Because Foo has 'default', the type of 'foo' in closure is the raw type instead of an Option<> type. + let result = >::mutate(|foo| { + *foo = *foo + increase_by; + *foo + }); + assert!(prev + increase_by == result); + + Ok(()) + } +} + +// Similar to other SRML modules, your module can also define a signed extension and perform some +// checks and [pre/post]processing [before/after] the transaction. A signed extension can be any +// decodable type that implements `SignedExtension`. See the trait definition for the full list of +// bounds. As a convention, you can follow this approach to create an extension for your module: +// - If the extension does not carry any data, then use a tuple struct with just a `marker` +// (needed for the compiler to accept `T: Trait`) will suffice. +// - Otherwise, create a tuple struct which contains the external data. Of course, for the entire +// struct to be decodable, each individual item also needs to be decodable. +// +// Note that a signed extension can also indicate that a particular data must be present in the +// _signing payload_ of a transaction by providing an implementation for the `additional_signed` +// method. This example will not cover this type of extension. See `CheckRuntime` in system module +// for an example. +// +// Using the extension, you can add some hooks to the lifecycle of each transaction. Note that by +// default, an extension is applied to all `Call` functions (i.e. all transactions). the `Call` enum +// variant is given to each function of `SignedExtension`. Hence, you can filter based on module or +// a particular call if needed. +// +// Some extra information, such as encoded length, some static dispatch info like weight and the +// sender of the transaction (if signed) are also provided. +// +// The full list of hooks that can be added to a signed extension can be found +// [here](https://crates.parity.io/sp_runtime/traits/trait.SignedExtension.html). +// +// The signed extensions are aggregated in the runtime file of a substrate chain. All extensions +// should be aggregated in a tuple and passed to the `CheckedExtrinsic` and `UncheckedExtrinsic` +// types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and +// `node-template` for an example of this. + +/// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the +/// priority and prints some log. +/// +/// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No +/// particular reason why, just to demonstrate the power of signed extensions. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct WatchDummy(PhantomData); + +impl sp_std::fmt::Debug for WatchDummy { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "WatchDummy") + } +} + +impl SignedExtension for WatchDummy { + type AccountId = T::AccountId; + // Note that this could also be assigned to the top-level call enum. It is passed into the + // balances module directly and since `Trait: pallet_balances::Trait`, you could also use `T::Call`. + // In that case, you would have had access to all call variants and could match on variants from + // other modules. + type Call = Call; + type AdditionalSigned = (); + type DispatchInfo = DispatchInfo; + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: Self::DispatchInfo, + len: usize, + ) -> TransactionValidity { + // if the transaction is too big, just drop it. + if len > 200 { + return InvalidTransaction::ExhaustsResources.into() + } + + // check for `set_dummy` + match call { + Call::set_dummy(..) => { + sp_runtime::print("set_dummy was received."); + + let mut valid_tx = ValidTransaction::default(); + valid_tx.priority = Bounded::max_value(); + Ok(valid_tx) + } + _ => Ok(Default::default()), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use frame_support::{assert_ok, impl_outer_origin, parameter_types, weights::GetDispatchInfo}; + use sp_core::H256; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. + use sp_runtime::{ + Perbill, testing::Header, + traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup}, + }; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + impl Trait for Test { + type Event = (); + } + type System = frame_system::Module; + type Example = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + pallet_balances::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); + GenesisConfig::{ + dummy: 42, + // we configure the map with (key, value) pairs. + bar: vec![(1, 2), (2, 3)], + foo: 24, + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + #[test] + fn it_works_for_optional_value() { + new_test_ext().execute_with(|| { + // Check that GenesisBuilder works properly. + assert_eq!(Example::dummy(), Some(42)); + + // Check that accumulate works when we have Some value in Dummy already. + assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); + assert_eq!(Example::dummy(), Some(69)); + + // Check that finalizing the block removes Dummy from storage. + >::on_finalize(1); + assert_eq!(Example::dummy(), None); + + // Check that accumulate works when we Dummy has None in it. + >::on_initialize(2); + assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); + assert_eq!(Example::dummy(), Some(42)); + }); + } + + #[test] + fn it_works_for_default_value() { + new_test_ext().execute_with(|| { + assert_eq!(Example::foo(), 24); + assert_ok!(Example::accumulate_foo(Origin::signed(1), 1)); + assert_eq!(Example::foo(), 25); + }); + } + + #[test] + fn signed_ext_watch_dummy_works() { + new_test_ext().execute_with(|| { + let call = >::set_dummy(10); + let info = DispatchInfo::default(); + + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, info, 150) + .unwrap() + .priority, + Bounded::max_value(), + ); + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, info, 250), + InvalidTransaction::ExhaustsResources.into(), + ); + }) + } + + #[test] + fn weights_work() { + // must have a default weight. + let default_call = >::accumulate_dummy(10); + let info = default_call.get_dispatch_info(); + // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` + assert_eq!(info.weight, 10_000); + + // must have a custom weight of `100 * arg = 2000` + let custom_call = >::set_dummy(20); + let info = custom_call.get_dispatch_info(); + assert_eq!(info.weight, 2000); + } +} diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml new file mode 100644 index 0000000000000..b2b30edd1cc58 --- /dev/null +++ b/frame/executive/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "frame-executive" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +serde = { version = "1.0.101", optional = true } +sp-io ={ path = "../../primitives/io", default-features = false } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } + +[dev-dependencies] +hex-literal = "0.2.1" +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-indices = { version = "2.0.0", path = "../indices" } +pallet-balances = { version = "2.0.0", path = "../balances" } +pallet-transaction-payment = { version = "2.0.0", path = "../transaction-payment" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "serde", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs new file mode 100644 index 0000000000000..0507946ef565b --- /dev/null +++ b/frame/executive/src/lib.rs @@ -0,0 +1,759 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Executive Module +//! +//! The Executive module acts as the orchestration layer for the runtime. It dispatches incoming +//! extrinsic calls to the respective modules in the runtime. +//! +//! ## Overview +//! +//! The executive module is not a typical SRML module providing functionality around a specific feature. +//! It is a cross-cutting framework component for the SRML. It works in conjunction with the +//! [SRML System module](../frame_system/index.html) to perform these cross-cutting functions. +//! +//! The Executive module provides functions to: +//! +//! - Check transaction validity. +//! - Initialize a block. +//! - Apply extrinsics. +//! - Execute a block. +//! - Finalize a block. +//! - Start an off-chain worker. +//! +//! ### Implementations +//! +//! The Executive module provides the following implementations: +//! +//! - `ExecuteBlock`: Trait that can be used to execute a block. +//! - `Executive`: Type that can be used to make the SRML available from the runtime. +//! +//! ## Usage +//! +//! The default Substrate node template declares the [`Executive`](./struct.Executive.html) type in its library. +//! +//! ### Example +//! +//! `Executive` type declaration from the node template. +//! +//! ``` +//! # use sp_runtime::generic; +//! # use frame_executive as executive; +//! # pub struct UncheckedExtrinsic {}; +//! # pub struct Header {}; +//! # type Context = frame_system::ChainContext; +//! # pub type Block = generic::Block; +//! # pub type Balances = u64; +//! # pub type AllModules = u64; +//! # pub enum Runtime {}; +//! # use sp_runtime::transaction_validity::{TransactionValidity, UnknownTransaction}; +//! # #[allow(deprecated)] +//! # use sp_runtime::traits::ValidateUnsigned; +//! # #[allow(deprecated)] +//! # impl ValidateUnsigned for Runtime { +//! # type Call = (); +//! # +//! # fn validate_unsigned(_call: &Self::Call) -> TransactionValidity { +//! # UnknownTransaction::NoUnsignedValidator.into() +//! # } +//! # } +//! /// Executive: handles dispatch to the various modules. +//! pub type Executive = executive::Executive; +//! ``` + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{prelude::*, marker::PhantomData}; +use frame_support::weights::{GetDispatchInfo, WeighBlock, DispatchInfo}; +use sp_runtime::{ + generic::Digest, ApplyExtrinsicResult, + traits::{ + self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, + NumberFor, Block as BlockT, OffchainWorker, Dispatchable, Saturating, + }, + transaction_validity::TransactionValidity, +}; +#[allow(deprecated)] +use sp_runtime::traits::ValidateUnsigned; +use codec::{Codec, Encode}; +use frame_system::{extrinsics_root, DigestOf}; + +/// Trait that can be used to execute a block. +pub trait ExecuteBlock { + /// Actually execute all transitions for `block`. + fn execute_block(block: Block); +} + +pub type CheckedOf = >::Checked; +pub type CallOf = as Applyable>::Call; +pub type OriginOf = as Dispatchable>::Origin; + +pub struct Executive( + PhantomData<(System, Block, Context, UnsignedValidator, AllModules)> +); + +#[allow(deprecated)] // Allow ValidateUnsigned, remove the attribute when the trait is removed. +impl< + System: frame_system::Trait, + Block: traits::Block, + Context: Default, + UnsignedValidator, + AllModules: + OnInitialize + + OnFinalize + + OffchainWorker + + WeighBlock, +> ExecuteBlock for Executive +where + Block::Extrinsic: Checkable + Codec, + CheckedOf: + Applyable + + GetDispatchInfo, + CallOf: Dispatchable, + OriginOf: From>, + UnsignedValidator: ValidateUnsigned>, +{ + fn execute_block(block: Block) { + Executive::::execute_block(block); + } +} + +#[allow(deprecated)] // Allow ValidateUnsigned, remove the attribute when the trait is removed. +impl< + System: frame_system::Trait, + Block: traits::Block, + Context: Default, + UnsignedValidator, + AllModules: + OnInitialize + + OnFinalize + + OffchainWorker + + WeighBlock, +> Executive +where + Block::Extrinsic: Checkable + Codec, + CheckedOf: + Applyable + + GetDispatchInfo, + CallOf: Dispatchable, + OriginOf: From>, + UnsignedValidator: ValidateUnsigned>, +{ + /// Start the execution of a particular block. + pub fn initialize_block(header: &System::Header) { + let digests = Self::extract_pre_digest(&header); + Self::initialize_block_impl( + header.number(), + header.parent_hash(), + header.extrinsics_root(), + &digests + ); + } + + fn extract_pre_digest(header: &System::Header) -> DigestOf { + let mut digest = >::default(); + header.digest().logs() + .iter() + .for_each(|d| if d.as_pre_runtime().is_some() { + digest.push(d.clone()) + }); + digest + } + + fn initialize_block_impl( + block_number: &System::BlockNumber, + parent_hash: &System::Hash, + extrinsics_root: &System::Hash, + digest: &Digest, + ) { + >::initialize( + block_number, + parent_hash, + extrinsics_root, + digest, + frame_system::InitKind::Full, + ); + >::on_initialize(*block_number); + >::register_extra_weight_unchecked( + >::on_initialize(*block_number) + ); + >::register_extra_weight_unchecked( + >::on_finalize(*block_number) + ); + } + + fn initial_checks(block: &Block) { + let header = block.header(); + + // Check that `parent_hash` is correct. + let n = header.number().clone(); + assert!( + n > System::BlockNumber::zero() + && >::block_hash(n - System::BlockNumber::one()) == *header.parent_hash(), + "Parent hash should be valid." + ); + + // Check that transaction trie root represents the transactions. + let xts_root = extrinsics_root::(&block.extrinsics()); + header.extrinsics_root().check_equal(&xts_root); + assert!(header.extrinsics_root() == &xts_root, "Transaction trie root must be valid."); + } + + /// Actually execute all transitions for `block`. + pub fn execute_block(block: Block) { + Self::initialize_block(block.header()); + + // any initial checks + Self::initial_checks(&block); + + // execute extrinsics + let (header, extrinsics) = block.deconstruct(); + Self::execute_extrinsics_with_book_keeping(extrinsics, *header.number()); + + // any final checks + Self::final_checks(&header); + } + + /// 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_finalize(block_number); + } + + /// Finalize the block - it is up the caller to ensure that all header fields are valid + /// except state-root. + pub fn finalize_block() -> System::Header { + >::note_finished_extrinsics(); + >::on_finalize(>::block_number()); + + // set up extrinsics + >::derive_extrinsics(); + >::finalize() + } + + /// Apply extrinsic outside of the block execution function. + /// + /// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt + /// hashes. + pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult { + let encoded = uxt.encode(); + let encoded_len = encoded.len(); + Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded)) + } + + /// Apply an extrinsic inside the block execution function. + fn apply_extrinsic_no_note(uxt: Block::Extrinsic) { + let l = uxt.encode().len(); + match Self::apply_extrinsic_with_len(uxt, l, None) { + Ok(Ok(())) => (), + Ok(Err(e)) => sp_runtime::print(e), + Err(e) => { let err: &'static str = e.into(); panic!(err) }, + } + } + + /// Actually apply an extrinsic given its `encoded_len`; this doesn't note its hash. + fn apply_extrinsic_with_len( + uxt: Block::Extrinsic, + encoded_len: usize, + to_note: Option>, + ) -> ApplyExtrinsicResult { + // Verify that the signature is good. + let xt = uxt.check(&Default::default())?; + + // We don't need to make sure to `note_extrinsic` only after we know it's going to be + // executed to prevent it from leaking in storage since at this point, it will either + // execute or panic (and revert storage changes). + if let Some(encoded) = to_note { + >::note_extrinsic(encoded); + } + + // AUDIT: Under no circumstances may this function panic from here onwards. + + // Decode parameters and dispatch + let dispatch_info = xt.get_dispatch_info(); + let r = Applyable::apply::(xt, dispatch_info, encoded_len)?; + + >::note_applied_extrinsic(&r, encoded_len as u32, dispatch_info); + + Ok(r) + } + + fn final_checks(header: &System::Header) { + // remove temporaries + let new_header = >::finalize(); + + // check digest + assert_eq!( + header.digest().logs().len(), + new_header.digest().logs().len(), + "Number of digest items must match that calculated." + ); + let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter()); + for (header_item, computed_item) in items_zip { + header_item.check_equal(&computed_item); + assert!(header_item == computed_item, "Digest item must match that calculated."); + } + + // check storage root. + let storage_root = new_header.state_root(); + header.state_root().check_equal(&storage_root); + assert!(header.state_root() == storage_root, "Storage root must match that calculated."); + } + + /// Check a given signed transaction for validity. This doesn't execute any + /// side-effects; it merely checks whether the transaction would panic if it were included or not. + /// + /// Changes made to storage should be discarded. + pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity { + let encoded_len = uxt.using_encoded(|d| d.len()); + let xt = uxt.check(&Default::default())?; + + let dispatch_info = xt.get_dispatch_info(); + xt.validate::(dispatch_info, encoded_len) + } + + /// Start an offchain worker and generate extrinsics. + pub fn offchain_worker(header: &System::Header) { + // We need to keep events available for offchain workers, + // hence we initialize the block manually. + // OffchainWorker RuntimeApi should skip initialization. + let digests = Self::extract_pre_digest(header); + + >::initialize( + header.number(), + header.parent_hash(), + header.extrinsics_root(), + &digests, + frame_system::InitKind::Inspection, + ); + >::offchain_worker( + // to maintain backward compatibility we call module offchain workers + // with parent block number. + header.number().saturating_sub(1.into()) + ) + } +} + + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::H256; + use sp_runtime::{ + generic::Era, Perbill, DispatchError, testing::{Digest, Header, Block}, + traits::{Bounded, Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}, + transaction_validity::{InvalidTransaction, UnknownTransaction, TransactionValidityError}, + }; + use frame_support::{ + impl_outer_event, impl_outer_origin, parameter_types, impl_outer_dispatch, + weights::Weight, + traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}, + }; + use frame_system::{self as system, Call as SystemCall, ChainContext}; + use pallet_balances::Call as BalancesCall; + use hex_literal::hex; + + mod custom { + use frame_support::weights::SimpleDispatchInfo; + + pub trait Trait: frame_system::Trait {} + + frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin { + #[weight = SimpleDispatchInfo::FixedNormal(100)] + fn some_function(origin) { + // NOTE: does not make any different. + let _ = frame_system::ensure_signed(origin); + } + #[weight = SimpleDispatchInfo::FixedOperational(200)] + fn some_root_operation(origin) { + let _ = frame_system::ensure_root(origin); + } + #[weight = SimpleDispatchInfo::FreeNormal] + fn some_unsigned_message(origin) { + let _ = frame_system::ensure_none(origin); + } + + // module hooks. + // one with block number arg and one without + #[weight = SimpleDispatchInfo::FixedNormal(25)] + fn on_initialize(n: T::BlockNumber) { + println!("on_initialize({})", n); + } + #[weight = SimpleDispatchInfo::FixedNormal(150)] + fn on_finalize() { + println!("on_finalize(?)"); + } + } + } + } + + type System = frame_system::Module; + type Balances = pallet_balances::Module; + type Custom = custom::Module; + + use pallet_balances as balances; + + impl_outer_origin! { + pub enum Origin for Runtime { } + } + + impl_outer_event!{ + pub enum MetaEvent for Runtime { + balances, + } + } + impl_outer_dispatch! { + pub enum Call for Runtime where origin: Origin { + frame_system::System, + pallet_balances::Balances, + } + } + + #[derive(Clone, Eq, PartialEq)] + pub struct Runtime; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type Call = Call; + type BlockNumber = u64; + type Hash = sp_core::H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = MetaEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl pallet_balances::Trait for Runtime { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = MetaEvent; + type DustRemoval = (); + type TransferPayment = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + + parameter_types! { + pub const TransactionBaseFee: u64 = 10; + pub const TransactionByteFee: u64 = 0; + } + impl pallet_transaction_payment::Trait for Runtime { + type Currency = Balances; + type OnTransactionPayment = (); + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = ConvertInto; + type FeeMultiplierUpdate = (); + } + impl custom::Trait for Runtime {} + + #[allow(deprecated)] + impl ValidateUnsigned for Runtime { + type Call = Call; + + fn pre_dispatch(_call: &Self::Call) -> Result<(), TransactionValidityError> { + Ok(()) + } + + fn validate_unsigned(call: &Self::Call) -> TransactionValidity { + match call { + Call::Balances(BalancesCall::set_balance(_, _, _)) => Ok(Default::default()), + _ => UnknownTransaction::NoUnsignedValidator.into(), + } + } + } + + type SignedExtra = ( + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment + ); + type AllModules = (System, Balances, Custom); + type TestXt = sp_runtime::testing::TestXt; + type Executive = super::Executive, ChainContext, Runtime, AllModules>; + + fn extra(nonce: u64, fee: u64) -> SignedExtra { + ( + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(nonce), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(fee) + ) + } + + fn sign_extra(who: u64, nonce: u64, fee: u64) -> Option<(u64, SignedExtra)> { + Some((who, extra(nonce, fee))) + } + + #[test] + fn balance_transfer_dispatch_works() { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(1, 211)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + let xt = sp_runtime::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(2, 69))); + let weight = xt.get_dispatch_info().weight as u64; + let mut t = sp_io::TestExternalities::new(t); + t.execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + let r = Executive::apply_extrinsic(xt); + assert!(r.is_ok()); + assert_eq!(>::total_balance(&1), 142 - 10 - weight); + assert_eq!(>::total_balance(&2), 69); + }); + } + + fn new_test_ext(balance_factor: u64) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(1, 111 * balance_factor)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + #[test] + fn block_import_works() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: hex!("c6b01b27df520ba23adb96e7fc032acb7c586ba1b477c6282de43184111f2091").into(), + extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), + digest: Digest { logs: vec![], }, + }, + extrinsics: vec![], + }); + }); + } + + #[test] + #[should_panic] + fn block_import_of_bad_state_root_fails() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: [0u8; 32].into(), + extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), + digest: Digest { logs: vec![], }, + }, + extrinsics: vec![], + }); + }); + } + + #[test] + #[should_panic] + fn block_import_of_bad_extrinsic_root_fails() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: hex!("49cd58a254ccf6abc4a023d9a22dcfc421e385527a250faec69f8ad0d8ed3e48").into(), + extrinsics_root: [0u8; 32].into(), + digest: Digest { logs: vec![], }, + }, + extrinsics: vec![], + }); + }); + } + + #[test] + fn bad_extrinsic_not_inserted() { + let mut t = new_test_ext(1); + // bad nonce check! + let xt = sp_runtime::testing::TestXt(sign_extra(1, 30, 0), Call::Balances(BalancesCall::transfer(33, 69))); + t.execute_with(|| { + Executive::initialize_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_weight_limit_enforced() { + let mut t = new_test_ext(10000); + // given: TestXt uses the encoded len as fixed Len: + let xt = sp_runtime::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0))); + let encoded = xt.encode(); + let encoded_len = encoded.len() as Weight; + let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get() - 175; + let num_to_exhaust_block = limit / encoded_len; + t.execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + // Initial block weight form the custom module. + assert_eq!(>::all_extrinsics_weight(), 175); + + for nonce in 0..=num_to_exhaust_block { + let xt = sp_runtime::testing::TestXt( + sign_extra(1, nonce.into(), 0), Call::Balances(BalancesCall::transfer(33, 0)), + ); + let res = Executive::apply_extrinsic(xt); + if nonce != num_to_exhaust_block { + assert!(res.is_ok()); + assert_eq!( + >::all_extrinsics_weight(), + encoded_len * (nonce + 1) + 175, + ); + assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); + } else { + assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); + } + } + }); + } + + #[test] + fn block_weight_and_size_is_stored_per_tx() { + let xt = sp_runtime::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0))); + let x1 = sp_runtime::testing::TestXt(sign_extra(1, 1, 0), Call::Balances(BalancesCall::transfer(33, 0))); + let x2 = sp_runtime::testing::TestXt(sign_extra(1, 2, 0), Call::Balances(BalancesCall::transfer(33, 0))); + let len = xt.clone().encode().len() as u32; + let mut t = new_test_ext(1); + t.execute_with(|| { + assert_eq!(>::all_extrinsics_weight(), 0); + assert_eq!(>::all_extrinsics_weight(), 0); + + assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); + + // default weight for `TestXt` == encoded length. + assert_eq!(>::all_extrinsics_weight(), (3 * len) as Weight); + assert_eq!(>::all_extrinsics_len(), 3 * len); + + let _ = >::finalize(); + + assert_eq!(>::all_extrinsics_weight(), 0); + assert_eq!(>::all_extrinsics_weight(), 0); + }); + } + + #[test] + fn validate_unsigned() { + let xt = sp_runtime::testing::TestXt(None, Call::Balances(BalancesCall::set_balance(33, 69, 69))); + let mut t = new_test_ext(1); + + t.execute_with(|| { + assert_eq!(Executive::validate_transaction(xt.clone()), Ok(Default::default())); + assert_eq!(Executive::apply_extrinsic(xt), Ok(Err(DispatchError::BadOrigin))); + }); + } + + #[test] + fn can_pay_for_tx_fee_on_full_lock() { + let id: LockIdentifier = *b"0 "; + let execute_with_lock = |lock: WithdrawReasons| { + let mut t = new_test_ext(1); + t.execute_with(|| { + as LockableCurrency>::set_lock( + id, + &1, + 110, + Bounded::max_value(), + lock, + ); + let xt = sp_runtime::testing::TestXt( + sign_extra(1, 0, 0), + Call::System(SystemCall::remark(vec![1u8])), + ); + let weight = xt.get_dispatch_info().weight as u64; + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + if lock == WithdrawReasons::except(WithdrawReason::TransactionPayment) { + assert!(Executive::apply_extrinsic(xt).unwrap().is_ok()); + // tx fee has been deducted. + assert_eq!(>::total_balance(&1), 111 - 10 - weight); + } else { + assert_eq!( + Executive::apply_extrinsic(xt), + Err(InvalidTransaction::Payment.into()), + ); + assert_eq!(>::total_balance(&1), 111); + } + }); + }; + + execute_with_lock(WithdrawReasons::all()); + execute_with_lock(WithdrawReasons::except(WithdrawReason::TransactionPayment)); + } + + #[test] + fn block_hooks_weight_is_stored() { + new_test_ext(1).execute_with(|| { + + Executive::initialize_block(&Header::new_from_number(1)); + // NOTE: might need updates over time if system and balance introduce new weights. For + // now only accounts for the custom module. + assert_eq!(>::all_extrinsics_weight(), 150 + 25); + }) + } +} diff --git a/frame/finality-tracker/Cargo.toml b/frame/finality-tracker/Cargo.toml new file mode 100644 index 0000000000000..22e1380e65697 --- /dev/null +++ b/frame/finality-tracker/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "pallet-finality-tracker" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-finality-tracker = { version = "2.0.0", default-features = false, path = "../../primitives/finality-tracker" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +impl-trait-for-tuples = "0.1.3" + +[dev-dependencies] +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } + +[features] +default = ["std"] +std = [ + "serde/std", + "codec/std", + "sp-std/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", + "sp-finality-tracker/std", + "sp-inherents/std", +] diff --git a/frame/finality-tracker/src/lib.rs b/frame/finality-tracker/src/lib.rs new file mode 100644 index 0000000000000..c9c9fbb0b5743 --- /dev/null +++ b/frame/finality-tracker/src/lib.rs @@ -0,0 +1,338 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! SRML module that tracks the last finalized block, as perceived by block authors. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_inherents::{InherentIdentifier, ProvideInherent, InherentData, MakeFatalError}; +use sp_runtime::traits::{One, Zero, SaturatedConversion}; +use sp_std::{prelude::*, result, cmp, vec}; +use frame_support::{decl_module, decl_storage, decl_error, ensure}; +use frame_support::traits::Get; +use frame_system::{ensure_none, Trait as SystemTrait}; +use sp_finality_tracker::{INHERENT_IDENTIFIER, FinalizedInherentData}; + +pub const DEFAULT_WINDOW_SIZE: u32 = 101; +pub const DEFAULT_REPORT_LATENCY: u32 = 1000; + +pub trait Trait: SystemTrait { + /// Something which can be notified when the timestamp is set. Set this to `()` + /// if not needed. + type OnFinalizationStalled: OnFinalizationStalled; + /// The number of recent samples to keep from this chain. Default is 101. + type WindowSize: Get; + /// The delay after which point things become suspicious. Default is 1000. + type ReportLatency: Get; +} + +decl_storage! { + trait Store for Module as Timestamp { + /// Recent hints. + RecentHints get(fn recent_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; + /// Ordered recent hints. + OrderedHints get(fn ordered_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; + /// The median. + Median get(fn median) build(|_| T::BlockNumber::zero()): T::BlockNumber; + + /// Final hint to apply in the block. `None` means "same as parent". + Update: Option; + + // when initialized through config this is set in the beginning. + Initialized get(fn initialized) build(|_| false): bool; + } +} + +decl_error! { + pub enum Error for Module { + /// Final hint must be updated only once in the block + AlreadyUpdated, + /// Finalized height above block number + BadHint, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + /// The number of recent samples to keep from this chain. Default is 101. + const WindowSize: T::BlockNumber = T::WindowSize::get(); + + /// The delay after which point things become suspicious. Default is 1000. + const ReportLatency: T::BlockNumber = T::ReportLatency::get(); + + /// 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_none(origin)?; + ensure!(!::Update::exists(), Error::::AlreadyUpdated); + ensure!( + frame_system::Module::::block_number() >= hint, + Error::::BadHint, + ); + ::Update::put(hint); + } + + fn on_finalize() { + 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(), T::WindowSize::get()); + + 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.saturated_into::()); + + 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() as u32; + + ::RecentHints::put(recent); + ::OrderedHints::put(ordered); + ::Median::put(median); + + if T::BlockNumber::from(our_window_size) == window_size { + let now = frame_system::Module::::block_number(); + let latency = T::ReportLatency::get(); + + // 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(), median); + } + } + } +} + +/// Called when finalization stalled at a given number. +#[impl_trait_for_tuples::impl_for_tuples(30)] +pub trait OnFinalizationStalled { + /// The parameter here is how many more blocks to wait before applying + /// changes triggered by finality stalling. + fn on_stalled(further_wait: N, median: N); +} + +impl ProvideInherent for Module { + type Call = Call; + type Error = MakeFatalError<()>; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + if let Ok(final_num) = data.finalized_number() { + // 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)) + }) + } else { + None + } + } + + fn check_inherent(_call: &Self::Call, _data: &InherentData) -> result::Result<(), Self::Error> { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use sp_io::TestExternalities; + use sp_core::H256; + use sp_runtime::{ + testing::Header, Perbill, + traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}, + }; + use frame_support::{assert_ok, impl_outer_origin, parameter_types, weights::Weight}; + use frame_system as system; + use std::cell::RefCell; + + #[derive(Clone, PartialEq, Debug)] + pub struct StallEvent { + at: u64, + further_wait: u64, + } + + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + thread_local! { + static NOTIFICATIONS: RefCell> = Default::default(); + } + + pub struct StallTracker; + impl OnFinalizationStalled for StallTracker { + fn on_stalled(further_wait: u64, _median: u64) { + let now = System::block_number(); + NOTIFICATIONS.with(|v| v.borrow_mut().push(StallEvent { at: now, further_wait })); + } + } + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const WindowSize: u64 = 11; + pub const ReportLatency: u64 = 100; + } + impl Trait for Test { + type OnFinalizationStalled = StallTracker; + type WindowSize = WindowSize; + type ReportLatency = ReportLatency; + } + + type System = system::Module; + type FinalityTracker = Module; + + #[test] + fn median_works() { + let t = system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t).execute_with(|| { + FinalityTracker::update_hint(Some(500)); + assert_eq!(FinalityTracker::median(), 250); + assert!(NOTIFICATIONS.with(|n| n.borrow().is_empty())); + }); + } + + #[test] + fn notifies_when_stalled() { + let t = system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t).execute_with(|| { + let mut parent_hash = System::parent_hash(); + for i in 2..106 { + System::initialize( + &i, + &parent_hash, + &Default::default(), + &Default::default(), + Default::default() + ); + FinalityTracker::on_finalize(i); + let hdr = System::finalize(); + parent_hash = hdr.hash(); + } + + assert_eq!( + NOTIFICATIONS.with(|n| n.borrow().clone()), + vec![StallEvent { at: 105, further_wait: 10 }] + ) + }); + } + + #[test] + fn recent_notifications_prevent_stalling() { + let t = system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t).execute_with(|| { + let mut parent_hash = System::parent_hash(); + for i in 2..106 { + System::initialize( + &i, + &parent_hash, + &Default::default(), + &Default::default(), + Default::default(), + ); + assert_ok!(FinalityTracker::dispatch( + Call::final_hint(i-1), + Origin::NONE, + )); + FinalityTracker::on_finalize(i); + let hdr = System::finalize(); + parent_hash = hdr.hash(); + } + + assert!(NOTIFICATIONS.with(|n| n.borrow().is_empty())); + }); + } +} diff --git a/frame/generic-asset/Cargo.toml b/frame/generic-asset/Cargo.toml new file mode 100644 index 0000000000000..87f4c9d1cf81f --- /dev/null +++ b/frame/generic-asset/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "pallet-generic-asset" +version = "2.0.0" +authors = ["Centrality Developers "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-io ={ version = "2.0.0", path = "../../primitives/io" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } + +[features] +default = ["std"] +std =[ + "serde/std", + "codec/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/generic-asset/src/lib.rs b/frame/generic-asset/src/lib.rs new file mode 100644 index 0000000000000..0a0209b20f175 --- /dev/null +++ b/frame/generic-asset/src/lib.rs @@ -0,0 +1,1362 @@ +// Copyright 2019-2020 +// by Centrality Investments Ltd. +// and Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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 Asset Module +//! +//! The Generic Asset module provides functionality for handling accounts and asset balances. +//! +//! ## Overview +//! +//! The Generic Asset module provides functions for: +//! +//! - Creating a new kind of asset. +//! - Setting permissions of an asset. +//! - Getting and setting free balances. +//! - Retrieving total, reserved and unreserved balances. +//! - Repatriating a reserved balance to a beneficiary account. +//! - Transferring a balance between accounts (when not reserved). +//! - Slashing an account balance. +//! - Managing total issuance. +//! - Setting and managing locks. +//! +//! ### Terminology +//! +//! - **Staking Asset:** The asset for staking, to participate as Validators in the network. +//! - **Spending Asset:** The asset for payment, such as paying transfer fees, gas fees, etc. +//! - **Permissions:** A set of rules for a kind of asset, defining the allowed operations to the asset, and which +//! accounts are allowed to possess it. +//! - **Total Issuance:** The total number of units in existence in a system. +//! - **Free Balance:** The portion of a balance that is not reserved. The free balance is the only balance that matters +//! for most operations. When this balance falls below the existential deposit, most functionality of the account is +//! removed. When both it and the reserved balance are deleted, then the account is said to be dead. +//! - **Reserved Balance:** Reserved balance still belongs to the account holder, but is suspended. Reserved balance +//! can still be slashed, but only after all the free balance has been slashed. If the reserved balance falls below the +//! existential deposit then it and any related functionality will be deleted. When both it and the free balance are +//! deleted, then the account is said to be dead. +//! - **Imbalance:** A condition when some assets were credited or debited without equal and opposite accounting +//! (i.e. a difference between total issuance and account balances). Functions that result in an imbalance will +//! return an object of the `Imbalance` trait that can be managed within your runtime logic. (If an imbalance is +//! simply dropped, it should automatically maintain any book-keeping such as total issuance.) +//! - **Lock:** A freeze on a specified amount of an account's free balance until a specified block number. Multiple +//! locks always operate over the same funds, so they "overlay" rather than "stack". +//! +//! ### Implementations +//! +//! The Generic Asset module provides `AssetCurrency`, which implements the following traits. If these traits provide +//! the functionality that you need, you can avoid coupling with the Generic Asset module. +//! +//! - `Currency`: Functions for dealing with a fungible assets system. +//! - `ReservableCurrency`: Functions for dealing with assets that can be reserved from an account. +//! - `LockableCurrency`: Functions for dealing with accounts that allow liquidity restrictions. +//! - `Imbalance`: Functions for handling imbalances between total issuance in the system and account balances. +//! Must be used when a function creates new assets (e.g. a reward) or destroys some assets (e.g. a system fee). +//! +//! The Generic Asset module provides two types of `AssetCurrency` as follows. +//! +//! - `StakingAssetCurrency`: Currency for staking. +//! - `SpendingAssetCurrency`: Currency for payments such as transfer fee, gas fee. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! - `create`: Create a new kind of asset. +//! - `transfer`: Transfer some liquid free balance to another account. +//! - `update_permission`: Updates permission for a given `asset_id` and an account. The origin of this call +//! must have update permissions. +//! - `mint`: Mint an asset, increases its total issuance. The origin of this call must have mint permissions. +//! - `burn`: Burn an asset, decreases its total issuance. The origin of this call must have burn permissions. +//! - `create_reserved`: Create a new kind of reserved asset. The origin of this call must be root. +//! +//! ### Public Functions +//! +//! - `total_balance`: Get an account's total balance of an asset kind. +//! - `free_balance`: Get an account's free balance of an asset kind. +//! - `reserved_balance`: Get an account's reserved balance of an asset kind. +//! - `create_asset`: Creates an asset. +//! - `make_transfer`: Transfer some liquid free balance from one account to another. +//! This will not emit the `Transferred` event. +//! - `make_transfer_with_event`: Transfer some liquid free balance from one account to another. +//! This will emit the `Transferred` event. +//! - `reserve`: Moves an amount from free balance to reserved balance. +//! - `unreserve`: Move up to an amount from reserved balance to free balance. This function cannot fail. +//! - `slash`: Deduct up to an amount from the combined balance of `who`, preferring to deduct from the +//! free balance. This function cannot fail. +//! - `reward`: Add up to an amount to the free balance of an account. +//! - `slash_reserved`: Deduct up to an amount from reserved balance of an account. This function cannot fail. +//! - `repatriate_reserved`: Move up to an amount from reserved balance of an account to free balance of another +//! account. +//! - `check_permission`: Check permission to perform burn, mint or update. +//! - `ensure_can_withdraw`: Check if the account is able to make a withdrawal of the given amount +//! for the given reason. +//! +//! ### Usage +//! +//! The following examples show how to use the Generic Asset module in your custom module. +//! +//! ### Examples from the PRML +//! +//! The Fees module uses the `Currency` trait to handle fee charge/refund, and its types inherit from `Currency`: +//! +//! ``` +//! use frame_support::{ +//! dispatch, +//! traits::{Currency, ExistenceRequirement, WithdrawReason}, +//! }; +//! # pub trait Trait: frame_system::Trait { +//! # type Currency: Currency; +//! # } +//! type AssetOf = <::Currency as Currency<::AccountId>>::Balance; +//! +//! fn charge_fee(transactor: &T::AccountId, amount: AssetOf) -> dispatch::DispatchResult { +//! // ... +//! T::Currency::withdraw( +//! transactor, +//! amount, +//! WithdrawReason::TransactionPayment.into(), +//! ExistenceRequirement::KeepAlive, +//! )?; +//! // ... +//! Ok(()) +//! } +//! +//! fn refund_fee(transactor: &T::AccountId, amount: AssetOf) -> dispatch::DispatchResult { +//! // ... +//! T::Currency::deposit_into_existing(transactor, amount)?; +//! // ... +//! Ok(()) +//! } +//! +//! # fn main() {} +//! ``` +//! +//! ## Genesis config +//! +//! The Generic Asset module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode, HasCompact, Input, Output, Error as CodecError}; + +use sp_runtime::{RuntimeDebug, DispatchResult, DispatchError}; +use sp_runtime::traits::{ + CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, SimpleArithmetic, + Zero, Bounded, +}; + +use sp_std::prelude::*; +use sp_std::{cmp, result, fmt::Debug}; +use frame_support::{ + decl_event, decl_module, decl_storage, ensure, dispatch, decl_error, + traits::{ + Currency, ExistenceRequirement, Imbalance, LockIdentifier, LockableCurrency, ReservableCurrency, + SignedImbalance, UpdateBalanceOutcome, WithdrawReason, WithdrawReasons, TryDrop, + }, + Parameter, StorageMap, +}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +mod mock; +mod tests; + +pub use self::imbalances::{NegativeImbalance, PositiveImbalance}; + +pub trait Trait: frame_system::Trait { + type Balance: Parameter + + Member + + SimpleArithmetic + + Default + + Copy + + MaybeSerializeDeserialize + + Debug; + type AssetId: Parameter + Member + SimpleArithmetic + Default + Copy; + type Event: From> + Into<::Event>; +} + +pub trait Subtrait: frame_system::Trait { + type Balance: Parameter + + Member + + SimpleArithmetic + + Default + + Copy + + MaybeSerializeDeserialize + + Debug; + type AssetId: Parameter + Member + SimpleArithmetic + Default + Copy; +} + +impl Subtrait for T { + type Balance = T::Balance; + type AssetId = T::AssetId; +} + +/// Asset creation options. +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] +pub struct AssetOptions { + /// Initial issuance of this asset. All deposit to the creater of the asset. + #[codec(compact)] + pub initial_issuance: Balance, + /// Which accounts are allowed to possess this asset. + pub permissions: PermissionLatest, +} + +/// Owner of an asset. +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] +pub enum Owner { + /// No owner. + None, + /// Owned by an AccountId + Address(AccountId), +} + +impl Default for Owner { + fn default() -> Self { + Owner::None + } +} + +/// Asset permissions +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] +pub struct PermissionsV1 { + /// Who have permission to update asset permission + pub update: Owner, + /// Who have permission to mint new asset + pub mint: Owner, + /// Who have permission to burn asset + pub burn: Owner, +} + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] +#[repr(u8)] +enum PermissionVersionNumber { + V1 = 0, +} + +/// Versioned asset permission +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] +pub enum PermissionVersions { + V1(PermissionsV1), +} + +/// Asset permission types +pub enum PermissionType { + /// Permission to burn asset permission + Burn, + /// Permission to mint new asset + Mint, + /// Permission to update asset + Update, +} + +/// Alias to latest asset permissions +pub type PermissionLatest = PermissionsV1; + +impl Default for PermissionVersions { + fn default() -> Self { + PermissionVersions::V1(Default::default()) + } +} + +impl Encode for PermissionVersions { + fn encode_to(&self, dest: &mut T) { + match self { + PermissionVersions::V1(payload) => { + dest.push(&PermissionVersionNumber::V1); + dest.push(payload); + }, + } + } +} + +impl codec::EncodeLike for PermissionVersions {} + +impl Decode for PermissionVersions { + fn decode(input: &mut I) -> core::result::Result { + let version = PermissionVersionNumber::decode(input)?; + Ok( + match version { + PermissionVersionNumber::V1 => PermissionVersions::V1(Decode::decode(input)?) + } + ) + } +} + +impl Default for PermissionsV1 { + fn default() -> Self { + PermissionsV1 { + update: Owner::None, + mint: Owner::None, + burn: Owner::None, + } + } +} + +impl Into> for PermissionVersions { + fn into(self) -> PermissionLatest { + match self { + PermissionVersions::V1(v1) => v1, + } + } +} + +/// Converts the latest permission to other version. +impl Into> for PermissionLatest { + fn into(self) -> PermissionVersions { + PermissionVersions::V1(self) + } +} + +decl_error! { + /// Error for the generic-asset module. + pub enum Error for Module { + /// No new assets id available. + NoIdAvailable, + /// Cannot transfer zero amount. + ZeroAmount, + /// The origin does not have enough permission to update permissions. + NoUpdatePermission, + /// The origin does not have permission to mint an asset. + NoMintPermission, + /// The origin does not have permission to burn an asset. + NoBurnPermission, + /// Total issuance got overflowed after minting. + TotalMintingOverflow, + /// Free balance got overflowed after minting. + FreeMintingOverflow, + /// Total issuance got underflowed after burning. + TotalBurningUnderflow, + /// Free balance got underflowed after burning. + FreeBurningUnderflow, + /// Asset id is already taken. + IdAlreadyTaken, + /// Asset id not available. + IdUnavailable, + /// The balance is too low to send amount. + InsufficientBalance, + /// The account liquidity restrictions prevent withdrawal. + LiquidityRestrictions, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + /// Create a new kind of asset. + fn create(origin, options: AssetOptions) -> dispatch::DispatchResult { + let origin = ensure_signed(origin)?; + let id = Self::next_asset_id(); + + let permissions: PermissionVersions = options.permissions.clone().into(); + + // The last available id serves as the overflow mark and won't be used. + let next_id = id.checked_add(&One::one()).ok_or_else(|| Error::::NoIdAvailable)?; + + >::put(next_id); + >::insert(id, &options.initial_issuance); + >::insert(&id, &origin, &options.initial_issuance); + >::insert(&id, permissions); + + Self::deposit_event(RawEvent::Created(id, origin, options)); + + Ok(()) + } + + /// Transfer some liquid free balance to another account. + pub fn transfer(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, #[compact] amount: T::Balance) { + let origin = ensure_signed(origin)?; + ensure!(!amount.is_zero(), Error::::ZeroAmount); + Self::make_transfer_with_event(&asset_id, &origin, &to, amount)?; + } + + /// Updates permission for a given `asset_id` and an account. + /// + /// The `origin` must have `update` permission. + fn update_permission( + origin, + #[compact] asset_id: T::AssetId, + new_permission: PermissionLatest + ) -> dispatch::DispatchResult { + let origin = ensure_signed(origin)?; + + let permissions: PermissionVersions = new_permission.into(); + + if Self::check_permission(&asset_id, &origin, &PermissionType::Update) { + >::insert(asset_id, &permissions); + + Self::deposit_event(RawEvent::PermissionUpdated(asset_id, permissions.into())); + + Ok(()) + } else { + Err(Error::::NoUpdatePermission)? + } + } + + /// Mints an asset, increases its total issuance. + /// The origin must have `mint` permissions. + fn mint(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, amount: T::Balance) + -> dispatch::DispatchResult + { + let origin = ensure_signed(origin)?; + if Self::check_permission(&asset_id, &origin, &PermissionType::Mint) { + let original_free_balance = Self::free_balance(&asset_id, &to); + let current_total_issuance = >::get(asset_id); + let new_total_issuance = current_total_issuance.checked_add(&amount) + .ok_or(Error::::TotalMintingOverflow)?; + let value = original_free_balance.checked_add(&amount) + .ok_or(Error::::FreeMintingOverflow)?; + + >::insert(asset_id, new_total_issuance); + Self::set_free_balance(&asset_id, &to, value); + + Self::deposit_event(RawEvent::Minted(asset_id, to, amount)); + + Ok(()) + } else { + Err(Error::::NoMintPermission)? + } + } + + /// Burns an asset, decreases its total issuance. + /// + /// The `origin` must have `burn` permissions. + fn burn(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, amount: T::Balance) + -> dispatch::DispatchResult + { + let origin = ensure_signed(origin)?; + + if Self::check_permission(&asset_id, &origin, &PermissionType::Burn) { + let original_free_balance = Self::free_balance(&asset_id, &to); + + let current_total_issuance = >::get(asset_id); + let new_total_issuance = current_total_issuance.checked_sub(&amount) + .ok_or(Error::::TotalBurningUnderflow)?; + let value = original_free_balance.checked_sub(&amount) + .ok_or(Error::::FreeBurningUnderflow)?; + + >::insert(asset_id, new_total_issuance); + + Self::set_free_balance(&asset_id, &to, value); + + Self::deposit_event(RawEvent::Burned(asset_id, to, amount)); + + Ok(()) + } else { + Err(Error::::NoBurnPermission)? + } + } + + /// Can be used to create reserved tokens. + /// Requires Root call. + fn create_reserved( + origin, + asset_id: T::AssetId, + options: AssetOptions + ) -> dispatch::DispatchResult { + ensure_root(origin)?; + Self::create_asset(Some(asset_id), None, options) + } + } +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct BalanceLock { + pub id: LockIdentifier, + pub amount: Balance, + pub until: BlockNumber, + pub reasons: WithdrawReasons, +} + +decl_storage! { + trait Store for Module as GenericAsset { + /// Total issuance of a given asset. + pub TotalIssuance get(fn total_issuance) build(|config: &GenesisConfig| { + let issuance = config.initial_balance * (config.endowed_accounts.len() as u32).into(); + config.assets.iter().map(|id| (id.clone(), issuance)).collect::>() + }): map T::AssetId => T::Balance; + + /// The free balance of a given asset under an account. + pub FreeBalance: double_map T::AssetId, hasher(twox_128) T::AccountId => T::Balance; + + /// The reserved balance of a given asset under an account. + pub ReservedBalance: double_map T::AssetId, hasher(twox_128) T::AccountId => T::Balance; + + /// Next available ID for user-created asset. + pub NextAssetId get(fn next_asset_id) config(): T::AssetId; + + /// Permission options for a given asset. + pub Permissions get(fn get_permission): map T::AssetId => PermissionVersions; + + /// Any liquidity locks on some account balances. + pub Locks get(fn locks): map T::AccountId => Vec>; + + /// The identity of the asset which is the one that is designated for the chain's staking system. + pub StakingAssetId get(fn staking_asset_id) config(): T::AssetId; + + /// The identity of the asset which is the one that is designated for paying the chain's transaction fee. + pub SpendingAssetId get(fn spending_asset_id) config(): T::AssetId; + } + add_extra_genesis { + config(assets): Vec; + config(initial_balance): T::Balance; + config(endowed_accounts): Vec; + + build(|config: &GenesisConfig| { + config.assets.iter().for_each(|asset_id| { + config.endowed_accounts.iter().for_each(|account_id| { + >::insert(asset_id, account_id, &config.initial_balance); + }); + }); + }); + } +} + +decl_event!( + pub enum Event where + ::AccountId, + ::Balance, + ::AssetId, + AssetOptions = AssetOptions<::Balance, ::AccountId> + { + /// Asset created (asset_id, creator, asset_options). + Created(AssetId, AccountId, AssetOptions), + /// Asset transfer succeeded (asset_id, from, to, amount). + Transferred(AssetId, AccountId, AccountId, Balance), + /// Asset permission updated (asset_id, new_permissions). + PermissionUpdated(AssetId, PermissionLatest), + /// New asset minted (asset_id, account, amount). + Minted(AssetId, AccountId, Balance), + /// Asset burned (asset_id, account, amount). + Burned(AssetId, AccountId, Balance), + } +); + +impl Module { + // PUBLIC IMMUTABLES + + /// Get an account's total balance of an asset kind. + pub fn total_balance(asset_id: &T::AssetId, who: &T::AccountId) -> T::Balance { + Self::free_balance(asset_id, who) + Self::reserved_balance(asset_id, who) + } + + /// Get an account's free balance of an asset kind. + pub fn free_balance(asset_id: &T::AssetId, who: &T::AccountId) -> T::Balance { + >::get(asset_id, who) + } + + /// Get an account's reserved balance of an asset kind. + pub fn reserved_balance(asset_id: &T::AssetId, who: &T::AccountId) -> T::Balance { + >::get(asset_id, who) + } + + /// Creates an asset. + /// + /// # Arguments + /// * `asset_id`: An ID of a reserved asset. + /// If not provided, a user-generated asset will be created with the next available ID. + /// * `from_account`: The initiator account of this call + /// * `asset_options`: Asset creation options. + /// + pub fn create_asset( + asset_id: Option, + from_account: Option, + options: AssetOptions, + ) -> dispatch::DispatchResult { + let asset_id = if let Some(asset_id) = asset_id { + ensure!(!>::exists(&asset_id), Error::::IdAlreadyTaken); + ensure!(asset_id < Self::next_asset_id(), Error::::IdUnavailable); + asset_id + } else { + let asset_id = Self::next_asset_id(); + let next_id = asset_id + .checked_add(&One::one()) + .ok_or(Error::::NoIdAvailable)?; + >::put(next_id); + asset_id + }; + + let account_id = from_account.unwrap_or_default(); + let permissions: PermissionVersions = options.permissions.clone().into(); + + >::insert(asset_id, &options.initial_issuance); + >::insert(&asset_id, &account_id, &options.initial_issuance); + >::insert(&asset_id, permissions); + + Self::deposit_event(RawEvent::Created(asset_id, account_id, options)); + + Ok(()) + } + + /// Transfer some liquid free balance from one account to another. + /// This will not emit the `Transferred` event. + pub fn make_transfer( + asset_id: &T::AssetId, + from: &T::AccountId, + to: &T::AccountId, + amount: T::Balance + ) -> dispatch::DispatchResult { + let new_balance = Self::free_balance(asset_id, from) + .checked_sub(&amount) + .ok_or(Error::::InsufficientBalance)?; + Self::ensure_can_withdraw(asset_id, from, amount, WithdrawReason::Transfer.into(), new_balance)?; + + if from != to { + >::mutate(asset_id, from, |balance| *balance -= amount); + >::mutate(asset_id, to, |balance| *balance += amount); + } + + Ok(()) + } + + /// Transfer some liquid free balance from one account to another. + /// This will emit the `Transferred` event. + pub fn make_transfer_with_event( + asset_id: &T::AssetId, + from: &T::AccountId, + to: &T::AccountId, + amount: T::Balance, + ) -> dispatch::DispatchResult { + Self::make_transfer(asset_id, from, to, amount)?; + + if from != to { + Self::deposit_event(RawEvent::Transferred(*asset_id, from.clone(), to.clone(), amount)); + } + + Ok(()) + } + + /// Move `amount` from free balance to reserved balance. + /// + /// If the free balance is lower than `amount`, then no funds will be moved and an `Err` will + /// be returned. This is different behavior than `unreserve`. + pub fn reserve(asset_id: &T::AssetId, who: &T::AccountId, amount: T::Balance) + -> dispatch::DispatchResult + { + // Do we need to consider that this is an atomic transaction? + let original_reserve_balance = Self::reserved_balance(asset_id, who); + let original_free_balance = Self::free_balance(asset_id, who); + if original_free_balance < amount { + Err(Error::::InsufficientBalance)? + } + let new_reserve_balance = original_reserve_balance + amount; + Self::set_reserved_balance(asset_id, who, new_reserve_balance); + let new_free_balance = original_free_balance - amount; + Self::set_free_balance(asset_id, who, new_free_balance); + Ok(()) + } + + /// Moves up to `amount` from reserved balance to free balance. This function cannot fail. + /// + /// As many assets up to `amount` will be moved as possible. If the reserve balance of `who` + /// is less than `amount`, then the remaining amount will be returned. + /// NOTE: This is different behavior than `reserve`. + pub fn unreserve(asset_id: &T::AssetId, who: &T::AccountId, amount: T::Balance) -> T::Balance { + let b = Self::reserved_balance(asset_id, who); + let actual = sp_std::cmp::min(b, amount); + let original_free_balance = Self::free_balance(asset_id, who); + let new_free_balance = original_free_balance + actual; + Self::set_free_balance(asset_id, who, new_free_balance); + Self::set_reserved_balance(asset_id, who, b - actual); + amount - actual + } + + /// Deduct up to `amount` from the combined balance of `who`, preferring to deduct from the + /// free balance. This function cannot fail. + /// + /// As much funds up to `amount` will be deducted as possible. If this is less than `amount` + /// then `Some(remaining)` will be returned. Full completion is given by `None`. + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn slash(asset_id: &T::AssetId, who: &T::AccountId, amount: T::Balance) -> Option { + let free_balance = Self::free_balance(asset_id, who); + let free_slash = sp_std::cmp::min(free_balance, amount); + let new_free_balance = free_balance - free_slash; + Self::set_free_balance(asset_id, who, new_free_balance); + if free_slash < amount { + Self::slash_reserved(asset_id, who, amount - free_slash) + } else { + None + } + } + + /// Deducts up to `amount` from reserved balance of `who`. This function cannot fail. + /// + /// As much funds up to `amount` will be deducted as possible. If the reserve balance of `who` + /// is less than `amount`, then a non-zero second item will be returned. + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn slash_reserved(asset_id: &T::AssetId, who: &T::AccountId, amount: T::Balance) -> Option { + let original_reserve_balance = Self::reserved_balance(asset_id, who); + let slash = sp_std::cmp::min(original_reserve_balance, amount); + let new_reserve_balance = original_reserve_balance - slash; + Self::set_reserved_balance(asset_id, who, new_reserve_balance); + if amount == slash { + None + } else { + Some(amount - slash) + } + } + + /// Move up to `amount` from reserved balance of account `who` to free balance of account + /// `beneficiary`. + /// + /// As much funds up to `amount` will be moved as possible. If this is less than `amount`, then + /// the `remaining` would be returned, else `Zero::zero()`. + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn repatriate_reserved( + asset_id: &T::AssetId, + who: &T::AccountId, + beneficiary: &T::AccountId, + amount: T::Balance, + ) -> T::Balance { + let b = Self::reserved_balance(asset_id, who); + let slash = sp_std::cmp::min(b, amount); + + let original_free_balance = Self::free_balance(asset_id, beneficiary); + let new_free_balance = original_free_balance + slash; + Self::set_free_balance(asset_id, beneficiary, new_free_balance); + + let new_reserve_balance = b - slash; + Self::set_reserved_balance(asset_id, who, new_reserve_balance); + amount - slash + } + + /// Check permission to perform burn, mint or update. + /// + /// # Arguments + /// * `asset_id`: A `T::AssetId` type that contains the `asset_id`, which has the permission embedded. + /// * `who`: A `T::AccountId` type that contains the `account_id` for which to check permissions. + /// * `what`: The permission to check. + /// + pub fn check_permission(asset_id: &T::AssetId, who: &T::AccountId, what: &PermissionType) -> bool { + let permission_versions: PermissionVersions = Self::get_permission(asset_id); + let permission = permission_versions.into(); + + match (what, permission) { + ( + PermissionType::Burn, + PermissionLatest { + burn: Owner::Address(account), + .. + }, + ) => account == *who, + ( + PermissionType::Mint, + PermissionLatest { + mint: Owner::Address(account), + .. + }, + ) => account == *who, + ( + PermissionType::Update, + PermissionLatest { + update: Owner::Address(account), + .. + }, + ) => account == *who, + _ => false, + } + } + + /// Return `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_can_withdraw( + asset_id: &T::AssetId, + who: &T::AccountId, + _amount: T::Balance, + reasons: WithdrawReasons, + new_balance: T::Balance, + ) -> dispatch::DispatchResult { + if asset_id != &Self::staking_asset_id() { + return Ok(()); + } + + 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.intersects(reasons)) + { + Ok(()) + } else { + Err(Error::::LiquidityRestrictions)? + } + } + + // PRIVATE MUTABLES + + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn set_reserved_balance(asset_id: &T::AssetId, who: &T::AccountId, balance: T::Balance) { + >::insert(asset_id, who, &balance); + } + + /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that + /// the caller will do this. + fn set_free_balance(asset_id: &T::AssetId, who: &T::AccountId, balance: T::Balance) { + >::insert(asset_id, who, &balance); + } + + 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 = >::locks(who) + .into_iter() + .filter_map(|l| { + if l.id == id { + new_lock.take() + } else if l.until > now { + Some(l) + } else { + None + } + }) + .collect::>(); + if let Some(lock) = new_lock { + locks.push(lock) + } + >::insert(who, locks); + } + + 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 = >::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); + } + + fn remove_lock(id: LockIdentifier, who: &T::AccountId) { + let now = >::block_number(); + let locks = >::locks(who) + .into_iter() + .filter_map(|l| if l.until > now && l.id != id { Some(l) } else { None }) + .collect::>(); + >::insert(who, locks); + } +} + +pub trait AssetIdProvider { + type AssetId; + fn asset_id() -> Self::AssetId; +} + +// wrapping these imbalanes in a private module is necessary to ensure absolute privacy +// of the inner member. +mod imbalances { + use super::{ + result, AssetIdProvider, Imbalance, Saturating, StorageMap, Subtrait, Zero, TryDrop + }; + use sp_std::mem; + + /// Opaque, move-only struct with private fields that serves as a token denoting that + /// funds have been created without any equal and opposite accounting. + #[must_use] + pub struct PositiveImbalance>( + T::Balance, + sp_std::marker::PhantomData, + ); + impl PositiveImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + pub fn new(amount: T::Balance) -> Self { + PositiveImbalance(amount, Default::default()) + } + } + + /// Opaque, move-only struct with private fields that serves as a token denoting that + /// funds have been destroyed without any equal and opposite accounting. + #[must_use] + pub struct NegativeImbalance>( + T::Balance, + sp_std::marker::PhantomData, + ); + impl NegativeImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + pub fn new(amount: T::Balance) -> Self { + NegativeImbalance(amount, Default::default()) + } + } + + impl TryDrop for PositiveImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + fn try_drop(self) -> result::Result<(), Self> { + self.drop_zero() + } + } + + impl Imbalance for PositiveImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + type Opposite = NegativeImbalance; + + fn zero() -> Self { + Self::new(Zero::zero()) + } + fn drop_zero(self) -> result::Result<(), Self> { + if self.0.is_zero() { + Ok(()) + } else { + Err(self) + } + } + fn split(self, amount: T::Balance) -> (Self, Self) { + let first = self.0.min(amount); + let second = self.0 - first; + + mem::forget(self); + (Self::new(first), Self::new(second)) + } + fn merge(mut self, other: Self) -> Self { + self.0 = self.0.saturating_add(other.0); + mem::forget(other); + + self + } + fn subsume(&mut self, other: Self) { + self.0 = self.0.saturating_add(other.0); + mem::forget(other); + } + fn offset(self, other: Self::Opposite) -> result::Result { + let (a, b) = (self.0, other.0); + mem::forget((self, other)); + + if a >= b { + Ok(Self::new(a - b)) + } else { + Err(NegativeImbalance::new(b - a)) + } + } + fn peek(&self) -> T::Balance { + self.0.clone() + } + } + + impl TryDrop for NegativeImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + fn try_drop(self) -> result::Result<(), Self> { + self.drop_zero() + } + } + + impl Imbalance for NegativeImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + type Opposite = PositiveImbalance; + + fn zero() -> Self { + Self::new(Zero::zero()) + } + fn drop_zero(self) -> result::Result<(), Self> { + if self.0.is_zero() { + Ok(()) + } else { + Err(self) + } + } + fn split(self, amount: T::Balance) -> (Self, Self) { + let first = self.0.min(amount); + let second = self.0 - first; + + mem::forget(self); + (Self::new(first), Self::new(second)) + } + fn merge(mut self, other: Self) -> Self { + self.0 = self.0.saturating_add(other.0); + mem::forget(other); + + self + } + fn subsume(&mut self, other: Self) { + self.0 = self.0.saturating_add(other.0); + mem::forget(other); + } + fn offset(self, other: Self::Opposite) -> result::Result { + let (a, b) = (self.0, other.0); + mem::forget((self, other)); + + if a >= b { + Ok(Self::new(a - b)) + } else { + Err(PositiveImbalance::new(b - a)) + } + } + fn peek(&self) -> T::Balance { + self.0.clone() + } + } + + impl Drop for PositiveImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + /// Basic drop handler will just square up the total issuance. + fn drop(&mut self) { + >>::mutate(&U::asset_id(), |v| *v = v.saturating_add(self.0)); + } + } + + impl Drop for NegativeImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + /// Basic drop handler will just square up the total issuance. + fn drop(&mut self) { + >>::mutate(&U::asset_id(), |v| *v = v.saturating_sub(self.0)); + } + } +} + +// TODO: #2052 +// Somewhat ugly hack in order to gain access to module's `increase_total_issuance_by` +// using only the Subtrait (which defines only the types that are not dependent +// on Positive/NegativeImbalance). Subtrait must be used otherwise we end up with a +// circular dependency with Trait having some types be dependent on PositiveImbalance +// and PositiveImbalance itself depending back on Trait for its Drop impl (and thus +// its type declaration). +// This works as long as `increase_total_issuance_by` doesn't use the Imbalance +// types (basically for charging fees). +// This should eventually be refactored so that the three type items that do +// depend on the Imbalance type (TransactionPayment, TransferPayment, DustRemoval) +// are placed in their own SRML module. +struct ElevatedTrait(T); +impl Clone for ElevatedTrait { + fn clone(&self) -> Self { + unimplemented!() + } +} +impl PartialEq for ElevatedTrait { + fn eq(&self, _: &Self) -> bool { + unimplemented!() + } +} +impl Eq for ElevatedTrait {} +impl frame_system::Trait for ElevatedTrait { + type Origin = T::Origin; + type Call = T::Call; + type Index = T::Index; + type BlockNumber = T::BlockNumber; + type Hash = T::Hash; + type Hashing = T::Hashing; + type AccountId = T::AccountId; + type Lookup = T::Lookup; + type Header = T::Header; + type Event = (); + type MaximumBlockWeight = T::MaximumBlockWeight; + type MaximumBlockLength = T::MaximumBlockLength; + type AvailableBlockRatio = T::AvailableBlockRatio; + type BlockHashCount = T::BlockHashCount; + type Version = T::Version; + type ModuleToIndex = (); +} +impl Trait for ElevatedTrait { + type Balance = T::Balance; + type AssetId = T::AssetId; + type Event = (); +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct AssetCurrency(sp_std::marker::PhantomData, sp_std::marker::PhantomData); + +impl Currency for AssetCurrency +where + T: Trait, + U: AssetIdProvider, +{ + type Balance = T::Balance; + type PositiveImbalance = PositiveImbalance; + type NegativeImbalance = NegativeImbalance; + + fn total_balance(who: &T::AccountId) -> Self::Balance { + Self::free_balance(&who) + Self::reserved_balance(&who) + } + + fn free_balance(who: &T::AccountId) -> Self::Balance { + >::free_balance(&U::asset_id(), &who) + } + + /// Returns the total staking asset issuance + fn total_issuance() -> Self::Balance { + >::total_issuance(U::asset_id()) + } + + fn minimum_balance() -> Self::Balance { + Zero::zero() + } + + fn transfer( + transactor: &T::AccountId, + dest: &T::AccountId, + value: Self::Balance, + _: ExistenceRequirement, // no existential deposit policy for generic asset + ) -> DispatchResult { + >::make_transfer(&U::asset_id(), transactor, dest, value) + } + + fn ensure_can_withdraw( + who: &T::AccountId, + amount: Self::Balance, + reasons: WithdrawReasons, + new_balance: Self::Balance, + ) -> DispatchResult { + >::ensure_can_withdraw(&U::asset_id(), who, amount, reasons, new_balance) + } + + fn withdraw( + who: &T::AccountId, + value: Self::Balance, + reasons: WithdrawReasons, + _: ExistenceRequirement, // no existential deposit policy for generic asset + ) -> result::Result { + let new_balance = Self::free_balance(who) + .checked_sub(&value) + .ok_or(Error::::InsufficientBalance)?; + Self::ensure_can_withdraw(who, value, reasons, new_balance)?; + >::set_free_balance(&U::asset_id(), who, new_balance); + Ok(NegativeImbalance::new(value)) + } + + fn deposit_into_existing( + who: &T::AccountId, + value: Self::Balance, + ) -> result::Result { + // No existential deposit rule and creation fee in GA. `deposit_into_existing` is same with `deposit_creating`. + Ok(Self::deposit_creating(who, value)) + } + + fn deposit_creating(who: &T::AccountId, value: Self::Balance) -> Self::PositiveImbalance { + let (imbalance, _) = Self::make_free_balance_be(who, Self::free_balance(who) + value); + if let SignedImbalance::Positive(p) = imbalance { + p + } else { + // Impossible, but be defensive. + Self::PositiveImbalance::zero() + } + } + + fn make_free_balance_be( + who: &T::AccountId, + balance: Self::Balance, + ) -> ( + SignedImbalance, + UpdateBalanceOutcome, + ) { + let original = >::free_balance(&U::asset_id(), who); + let imbalance = if original <= balance { + SignedImbalance::Positive(PositiveImbalance::new(balance - original)) + } else { + SignedImbalance::Negative(NegativeImbalance::new(original - balance)) + }; + >::set_free_balance(&U::asset_id(), who, balance); + (imbalance, UpdateBalanceOutcome::Updated) + } + + fn can_slash(who: &T::AccountId, value: Self::Balance) -> bool { + >::free_balance(&U::asset_id(), &who) >= value + } + + fn slash(who: &T::AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) { + let remaining = >::slash(&U::asset_id(), who, value); + if let Some(r) = remaining { + (NegativeImbalance::new(value - r), r) + } else { + (NegativeImbalance::new(value), Zero::zero()) + } + } + + fn burn(mut amount: Self::Balance) -> Self::PositiveImbalance { + >::mutate(&U::asset_id(), |issued| + issued.checked_sub(&amount).unwrap_or_else(|| { + amount = *issued; + Zero::zero() + }) + ); + PositiveImbalance::new(amount) + } + + fn issue(mut amount: Self::Balance) -> Self::NegativeImbalance { + >::mutate(&U::asset_id(), |issued| + *issued = issued.checked_add(&amount).unwrap_or_else(|| { + amount = Self::Balance::max_value() - *issued; + Self::Balance::max_value() + }) + ); + NegativeImbalance::new(amount) + } +} + +impl ReservableCurrency for AssetCurrency +where + T: Trait, + U: AssetIdProvider, +{ + fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { + Self::free_balance(who) + .checked_sub(&value) + .map_or(false, |new_balance| + >::ensure_can_withdraw( + &U::asset_id(), who, value, WithdrawReason::Reserve.into(), new_balance + ).is_ok() + ) + } + + fn reserved_balance(who: &T::AccountId) -> Self::Balance { + >::reserved_balance(&U::asset_id(), &who) + } + + fn reserve(who: &T::AccountId, value: Self::Balance) -> DispatchResult { + >::reserve(&U::asset_id(), who, value) + } + + fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance { + >::unreserve(&U::asset_id(), who, value) + } + + fn slash_reserved(who: &T::AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) { + let b = Self::reserved_balance(&who.clone()); + let slash = cmp::min(b, value); + + >::set_reserved_balance(&U::asset_id(), who, b - slash); + (NegativeImbalance::new(slash), value - slash) + } + + fn repatriate_reserved( + slashed: &T::AccountId, + beneficiary: &T::AccountId, + value: Self::Balance, + ) -> result::Result { + Ok(>::repatriate_reserved(&U::asset_id(), slashed, beneficiary, value)) + } +} + +pub struct StakingAssetIdProvider(sp_std::marker::PhantomData); + +impl AssetIdProvider for StakingAssetIdProvider { + type AssetId = T::AssetId; + fn asset_id() -> Self::AssetId { + >::staking_asset_id() + } +} + +pub struct SpendingAssetIdProvider(sp_std::marker::PhantomData); + +impl AssetIdProvider for SpendingAssetIdProvider { + type AssetId = T::AssetId; + fn asset_id() -> Self::AssetId { + >::spending_asset_id() + } +} + +impl LockableCurrency for AssetCurrency> +where + T: Trait, + T::Balance: MaybeSerializeDeserialize + Debug, +{ + type Moment = T::BlockNumber; + + fn set_lock( + id: LockIdentifier, + who: &T::AccountId, + amount: T::Balance, + until: T::BlockNumber, + reasons: WithdrawReasons, + ) { + >::set_lock(id, who, amount, until, reasons) + } + + fn extend_lock( + id: LockIdentifier, + who: &T::AccountId, + amount: T::Balance, + until: T::BlockNumber, + reasons: WithdrawReasons, + ) { + >::extend_lock(id, who, amount, until, reasons) + } + + fn remove_lock(id: LockIdentifier, who: &T::AccountId) { + >::remove_lock(id, who) + } +} + +pub type StakingAssetCurrency = AssetCurrency>; +pub type SpendingAssetCurrency = AssetCurrency>; diff --git a/frame/generic-asset/src/mock.rs b/frame/generic-asset/src/mock.rs new file mode 100644 index 0000000000000..6fdf2d2d884f8 --- /dev/null +++ b/frame/generic-asset/src/mock.rs @@ -0,0 +1,146 @@ +// Copyright 2019-2020 +// by Centrality Investments Ltd. +// and Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Mocks for the module. + +#![cfg(test)] + +use sp_runtime::{ + Perbill, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; +use sp_core::H256; +use frame_support::{parameter_types, impl_outer_event, impl_outer_origin, weights::Weight}; + +use super::*; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +// For testing the module, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of modules we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type BlockHashCount = BlockHashCount; + type Version = (); + type ModuleToIndex = (); +} + +impl Trait for Test { + type Balance = u64; + type AssetId = u32; + type Event = TestEvent; +} + +mod generic_asset { + pub use crate::Event; +} + +use frame_system as system; +impl_outer_event! { + pub enum TestEvent for Test { + generic_asset, + } +} + +pub type GenericAsset = Module; + +pub type System = frame_system::Module; + +pub struct ExtBuilder { + asset_id: u32, + next_asset_id: u32, + accounts: Vec, + initial_balance: u64, +} + +// Returns default values for genesis config +impl Default for ExtBuilder { + fn default() -> Self { + Self { + asset_id: 0, + next_asset_id: 1000, + accounts: vec![0], + initial_balance: 0, + } + } +} + +impl ExtBuilder { + // Sets free balance to genesis config + pub fn free_balance(mut self, free_balance: (u32, u64, u64)) -> Self { + self.asset_id = free_balance.0; + self.accounts = vec![free_balance.1]; + self.initial_balance = free_balance.2; + self + } + + pub fn next_asset_id(mut self, asset_id: u32) -> Self { + self.next_asset_id = asset_id; + self + } + + // builds genesis config + pub fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + GenesisConfig:: { + assets: vec![self.asset_id], + endowed_accounts: self.accounts, + initial_balance: self.initial_balance, + next_asset_id: self.next_asset_id, + staking_asset_id: 16000, + spending_asset_id: 16001, + } + .assimilate_storage(&mut t).unwrap(); + + t.into() + } +} + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext() -> sp_io::TestExternalities { + frame_system::GenesisConfig::default() + .build_storage::() + .unwrap() + .into() +} diff --git a/frame/generic-asset/src/tests.rs b/frame/generic-asset/src/tests.rs new file mode 100644 index 0000000000000..7c12c391bf3e3 --- /dev/null +++ b/frame/generic-asset/src/tests.rs @@ -0,0 +1,1215 @@ +// Copyright 2019-2020 +// by Centrality Investments Ltd. +// and Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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::{new_test_ext, ExtBuilder, GenericAsset, Origin, System, Test, TestEvent}; +use frame_support::{assert_noop, assert_ok}; + +#[test] +fn issuing_asset_units_to_issuer_should_work() { + let balance = 100; + + ExtBuilder::default().free_balance((16000, 1, 100)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + + let expected_balance = balance; + + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: balance, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&16000, &1), expected_balance); + }); +} + +#[test] +fn issuing_with_next_asset_id_overflow_should_not_work() { + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + NextAssetId::::put(u32::max_value()); + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_noop!( + GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 1, + permissions: default_permission + } + ), + Error::::NoIdAvailable + ); + assert_eq!(GenericAsset::next_asset_id(), u32::max_value()); + }); +} + +#[test] +fn querying_total_supply_should_work() { + let asset_id = 1000; + + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); + assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 2, 50)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); + assert_eq!(GenericAsset::free_balance(&asset_id, &2), 50); + assert_ok!(GenericAsset::transfer(Origin::signed(2), asset_id, 3, 31)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); + assert_eq!(GenericAsset::free_balance(&asset_id, &2), 19); + assert_eq!(GenericAsset::free_balance(&asset_id, &3), 31); + assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 1, 1)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); + }); +} + +// Given +// - The next asset id as `asset_id` = 1000. +// - AssetOptions with all permissions. +// - GenesisStore has sufficient free balance. +// +// When +// - Create an asset from `origin` as 1. +// Then +// - free_balance of next asset id = 100. +// +// When +// - After transferring 40 from account 1 to account 2. +// Then +// - Origin account's `free_balance` = 60. +// - account 2's `free_balance` = 40. +#[test] +fn transferring_amount_should_work() { + let asset_id = 1000; + let free_balance = 100; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: free_balance, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), free_balance); + assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 2, 40)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 60); + assert_eq!(GenericAsset::free_balance(&asset_id, &2), 40); + }); +} + +// Given +// - The next asset id as `asset_id` = 1000. +// - AssetOptions with all permissions. +// - GenesisStore has sufficient free balance. +// +// When +// - Create an asset from `origin` as 1. +// Then +// - free_balance of next asset id = 100. +// +// When +// - After transferring 40 from account 1 to account 2. +// Then +// - Origin account's `free_balance` = 60. +// - account 2's `free_balance` = 40. +#[test] +fn transferring_amount_should_fail_when_transferring_more_than_free_balance() { + let asset_id = 1000; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_noop!( + GenericAsset::transfer(Origin::signed(1), asset_id, 2, 2000), + Error::::InsufficientBalance + ); + }); +} + +#[test] +fn transferring_less_than_one_unit_should_not_work() { + let asset_id = 1000; + + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); + assert_noop!( + GenericAsset::transfer(Origin::signed(1), asset_id, 2, 0), + Error::::ZeroAmount + ); + }); +} + +// Given +// - Next asset id as `asset_id` = 1000. +// - Sufficient free balance. +// - initial balance = 100. +// When +// - After performing a self transfer from account 1 to 1. +// Then +// - Should not throw any errors. +// - Free balance after self transfer should equal to the free balance before self transfer. +#[test] +fn self_transfer_should_fail() { + let asset_id = 1000; + let balance = 100; + + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: balance, + permissions: default_permission + } + )); + + let initial_free_balance = GenericAsset::free_balance(&asset_id, &1); + assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 1, 10)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), initial_free_balance); + }); +} + +#[test] +fn transferring_more_units_than_total_supply_should_not_work() { + let asset_id = 1000; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); + assert_noop!( + GenericAsset::transfer(Origin::signed(1), asset_id, 2, 101), + Error::::InsufficientBalance + ); + }); +} + +// Ensures it uses fake money for staking asset id. +#[test] +fn staking_asset_id_should_return_0() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(GenericAsset::staking_asset_id(), 16000); + }); +} + +// Ensures it uses fake money for spending asset id. +#[test] +fn spending_asset_id_should_return_10() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(GenericAsset::spending_asset_id(), 16001); + }); +} + +// Given +// -Â Free balance is 0 and the reserved balance is 0. +// Then +// -Â total_balance should return 0 +#[test] +fn total_balance_should_be_zero() { + new_test_ext().execute_with(|| { + assert_eq!(GenericAsset::total_balance(&0, &0), 0); + }); +} + +// Given +// -Â Free balance is 0 and the reserved balance > 0. +// When +// - After calling total_balance. +// Then +// -Â total_balance should equals to reserved balance. +#[test] +fn total_balance_should_be_equal_to_account_balance() { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::total_balance(&1000, &1), 100); + }); +} + +// Given +// - An account presents with AccountId = 1 +// -Â free_balance > 0. +// - reserved_balance = 50. +// When +// - After calling free_balance. +// Then +// -Â free_balance should return 50. +#[test] +fn free_balance_should_only_return_account_free_balance() { + ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 70); + assert_eq!(GenericAsset::free_balance(&1, &0), 50); + }); +} + +// Given +// - An account presents with AccountId = 1. +// -Â Free balance > 0 and the reserved balance > 0. +// When +// - After calling total_balance. +// Then +// -Â total_balance should equals to account balance + free balance. +#[test] +fn total_balance_should_be_equal_to_sum_of_account_balance_and_free_balance() { + ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 70); + assert_eq!(GenericAsset::total_balance(&1, &0), 120); + }); +} + +// Given +// -Â free_balance > 0. +// - reserved_balance = 70. +// When +// - After calling reserved_balance. +// Then +// - reserved_balance should return 70. +#[test] +fn reserved_balance_should_only_return_account_reserved_balance() { + ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 70); + assert_eq!(GenericAsset::reserved_balance(&1, &0), 70); + }); +} + +// Given +// - A valid account presents. +// - Initial reserved_balance = 0 +// When +// - After calls set_reserved_balance +// Then +// - Should persists the amount as reserved_balance. +// - reserved_balance = amount +#[test] +fn set_reserved_balance_should_add_balance_as_reserved() { + ExtBuilder::default().build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 50); + assert_eq!(GenericAsset::reserved_balance(&1, &0), 50); + }); +} + +// Given +// - A valid account presents. +// - Initial free_balance = 100. +// When +// - After calling set_free_balance. +// Then +// - Should persists the amount as free_balance. +// - New free_balance should replace older free_balance. +#[test] +fn set_free_balance_should_add_amount_as_free_balance() { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { + GenericAsset::set_free_balance(&1, &0, 50); + assert_eq!(GenericAsset::free_balance(&1, &0), 50); + }); +} + +// Given +// - free_balance is greater than the account balance. +// - free_balance = 100 +// - reserved_balance = 0 +// - reserve amount = 70 +// When +// - After calling reserve +// Then +// - Funds should be removed from the account. +// - new free_balance = original free_balance - reserved amount +// - new reserved_balance = original free balance + reserved amount +#[test] +fn reserve_should_moves_amount_from_balance_to_reserved_balance() { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { + assert_ok!(GenericAsset::reserve(&1, &0, 70)); + assert_eq!(GenericAsset::free_balance(&1, &0), 30); + assert_eq!(GenericAsset::reserved_balance(&1, &0), 70); + }); +} + +// Given +// - Free balance is lower than the account balance. +// - free_balance = 100 +// - reserved_balance = 0 +// - reserve amount = 120 +// When +// - After calling reverse function. +// Then +// - Funds should not be removed from the account. +// - Should throw an error. +#[test] +fn reserve_should_not_moves_amount_from_balance_to_reserved_balance() { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { + assert_noop!(GenericAsset::reserve(&1, &0, 120), Error::::InsufficientBalance); + assert_eq!(GenericAsset::free_balance(&1, &0), 100); + assert_eq!(GenericAsset::reserved_balance(&1, &0), 0); + }); +} + +// Given +// - unreserved_amount > reserved_balance. +// - reserved_balance = 100. +// - free_balance = 100. +// - unreserved_amount = 120. +// When +// - After calling unreserve function. +// Then +// - unreserved should return 20. +#[test] +fn unreserve_should_return_substratced_value_from_unreserved_amount_by_actual_acount_balance() { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 100); + assert_eq!(GenericAsset::unreserve(&1, &0, 120), 20); + }); +} + +// Given +// - unreserved_amount < reserved_balance. +// - reserved_balance = 100. +// - free_balance = 100. +// - unreserved_amount = 50. +// When +// - After calling unreserve function. +// Then +// - unreserved should return None. +#[test] +fn unreserve_should_return_none() { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 100); + assert_eq!(GenericAsset::unreserve(&1, &0, 50), 0); + }); +} + +// Given +// - unreserved_amount > reserved_balance. +// - reserved_balance = 100. +// - free_balance = 100. +// - unreserved_amount = 120. +// When +// - After calling unreserve function. +// Then +// - free_balance should be 200. +#[test] +fn unreserve_should_increase_free_balance_by_reserved_balance() { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 100); + GenericAsset::unreserve(&1, &0, 120); + assert_eq!(GenericAsset::free_balance(&1, &0), 200); + }); +} + +// Given +// - unreserved_amount > reserved_balance. +// - reserved_balance = 100. +// - free_balance = 100. +// - unreserved_amount = 120. +// When +// - After calling unreserve function. +// Then +// - reserved_balance should be 0. +#[test] +fn unreserve_should_deduct_reserved_balance_by_reserved_amount() { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { + GenericAsset::set_free_balance(&1, &0, 100); + GenericAsset::unreserve(&1, &0, 120); + assert_eq!(GenericAsset::reserved_balance(&1, &0), 0); + }); +} + +// Given +// - slash amount < free_balance. +// - reserved_balance = 100. +// - free_balance = 100. +// - slash amount = 70. +// When +// - After calling slash function. +// Then +// - slash should return None. +#[test] +fn slash_should_return_slash_reserved_amount() { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 100); + assert_eq!(GenericAsset::slash(&1, &0, 70), None); + }); +} + +// Given +// - slashed_amount > reserved_balance. +// When +// - After calling slashed_reverse function. +// Then +// - Should return slashed_reserved - reserved_balance. +#[test] +fn slash_reserved_should_deducts_up_to_amount_from_reserved_balance() { + ExtBuilder::default().build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 100); + assert_eq!(GenericAsset::slash_reserved(&1, &0, 150), Some(50)); + }); +} + +// Given +// - slashed_amount equals to reserved_amount. +// When +// - After calling slashed_reverse function. +// Then +// - Should return None. +#[test] +fn slash_reserved_should_return_none() { + ExtBuilder::default().build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 100); + assert_eq!(GenericAsset::slash_reserved(&1, &0, 100), None); + }); +} + +// Given +// - reserved_balance = 100. +// - repatriate_reserved_amount > reserved_balance. +// When +// - After calling repatriate_reserved. +// Then +// - Should not return None. +#[test] +fn repatriate_reserved_return_amount_substracted_by_slash_amount() { + ExtBuilder::default().build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 100); + assert_eq!(GenericAsset::repatriate_reserved(&1, &0, &1, 130), 30); + }); +} + +// Given +// - reserved_balance = 100. +// - repatriate_reserved_amount > reserved_balance. +// When +// - After calling repatriate_reserved. +// Then +// - Should return None. +#[test] +fn repatriate_reserved_return_none() { + ExtBuilder::default().build().execute_with(|| { + GenericAsset::set_reserved_balance(&1, &0, 100); + assert_eq!(GenericAsset::repatriate_reserved(&1, &0, &1, 90), 0); + }); +} + +// Given +// - An asset with all permissions +// When +// - After calling `create_reserved` function. +// Then +// - Should create a new reserved asset. +#[test] +fn create_reserved_should_create_a_default_account_with_the_balance_given() { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + let options = AssetOptions { + initial_issuance: 500, + permissions: default_permission, + }; + + let expected_total_issuance = 500; + let created_asset_id = 9; + let created_account_id = 0; + + assert_ok!(GenericAsset::create_reserved(Origin::ROOT, created_asset_id, options)); + + // Tests for side effects. + assert_eq!(>::get(created_asset_id), expected_total_issuance); + assert_eq!( + >::get(&created_asset_id, &created_account_id), + expected_total_issuance + ); + }); +} + +// Given +// - Origin is signed +// - Origin does not have minting permission +// When +// - After calling mint function +// Then +// - Should throw a permission error +#[test] +fn mint_should_throw_permission_error() { + ExtBuilder::default().build().execute_with(|| { + let origin = 1; + let asset_id = 4; + let to_account = 2; + let amount = 100; + + assert_noop!( + GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount), + Error::::NoMintPermission, + ); + }); +} + +// Given +// - Origin is signed. +// - Origin has permissions. +// When +// - After calling mint function +// Then +// - Should increase `to` free_balance. +// - Should not change `origins` free_balance. +#[test] +fn mint_should_increase_asset() { + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let to_account = 2; + let amount = 500; + let initial_issuance = 100; + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + + assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount)); + assert_eq!(GenericAsset::free_balance(&asset_id, &to_account), amount); + + // Origin's free_balance should not change. + assert_eq!(GenericAsset::free_balance(&asset_id, &origin), initial_issuance); + }); +} + +// Given +// - Origin is signed. +// - Origin does not have burning permission. +// When +// - After calling burn function. +// Then +// - Should throw a permission error. +#[test] +fn burn_should_throw_permission_error() { + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 4; + let to_account = 2; + let amount = 10; + + assert_noop!( + GenericAsset::burn(Origin::signed(origin), asset_id, to_account, amount), + Error::::NoBurnPermission, + ); + }); +} + +// Given +// - Origin is signed. +// - Origin has permissions. +// When +// - After calling burn function +// Then +// - Should decrease `to`'s free_balance. +// - Should not change `origin`'s free_balance. +#[test] +fn burn_should_burn_an_asset() { + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let to_account = 2; + let amount = 1000; + let initial_issuance = 100; + let burn_amount = 400; + let expected_amount = 600; + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount)); + + assert_ok!(GenericAsset::burn( + Origin::signed(origin), + asset_id, + to_account, + burn_amount + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &to_account), expected_amount); + }); +} + +// Given +// - `default_permission` with all privileges. +// - All permissions for origin. +// When +// - After executing create function and check_permission function. +// Then +// - The account origin should have burn, mint and update permissions. +#[test] +fn check_permission_should_return_correct_permission() { + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let initial_issuance = 100; + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + }, + )); + + assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); + assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); + assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Update)); + }); +} + +// Given +// - `default_permission` with no privileges. +// - No permissions for origin. +// When +// - After executing create function and check_permission function. +// Then +// - The account origin should not have burn, mint and update permissions. +#[test] +fn check_permission_should_return_false_for_no_permission() { + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let initial_issuance = 100; + + let default_permission = PermissionLatest { + update: Owner::None, + mint: Owner::None, + burn: Owner::None, + }; + + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + + assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); + assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); + assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Update)); + }); +} + +// Given +// - `default_permission` only with update. +// When +// - After executing update_permission function. +// Then +// - The account origin should not have the burn permission. +// - The account origin should have update and mint permissions. +#[test] +fn update_permission_should_change_permission() { + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let initial_issuance = 100; + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::None, + burn: Owner::None, + }; + + let new_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::None, + }; + + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + + assert_ok!(GenericAsset::update_permission( + Origin::signed(origin), + asset_id, + new_permission, + )); + assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); + assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); + }); +} + +// Given +// - `default_permission` without any permissions. +// When +// - After executing update_permission function. +// Then +// - Should throw an error stating "Origin does not have enough permission to update permissions." +#[test] +fn update_permission_should_throw_error_when_lack_of_permissions() { + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let initial_issuance = 100; + + let default_permission = PermissionLatest { + update: Owner::None, + mint: Owner::None, + burn: Owner::None, + }; + + let new_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::None, + }; + + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + }, + )); + + assert_noop!( + GenericAsset::update_permission(Origin::signed(origin), asset_id, new_permission), + Error::::NoUpdatePermission, + ); + }); +} + +// Given +// - `asset_id` provided. +// - `from_account` is present. +// - All permissions for origin. +// When +// - After calling create_asset. +// Then +// - Should create a reserved token with provided id. +// - NextAssetId doesn't change. +// - TotalIssuance must equal to initial issuance. +// - FreeBalance must equal to initial issuance for the given account. +// - Permissions must have burn, mint and updatePermission for the given asset_id. +#[test] +fn create_asset_works_with_given_asset_id_and_from_account() { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { + let origin = 1; + let from_account: Option<::AccountId> = Some(1); + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + let expected_permission = PermissionVersions::V1(default_permission.clone()); + let asset_id = 9; + let initial_issuance = 100; + + assert_ok!(GenericAsset::create_asset( + Some(asset_id), + from_account, + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission.clone() + } + )); + + // Test for side effects. + assert_eq!(>::get(), 10); + assert_eq!(>::get(asset_id), initial_issuance); + assert_eq!(>::get(&asset_id, &origin), initial_issuance); + assert_eq!(>::get(&asset_id), expected_permission); + }); +} + +// Given +// - `asset_id` is an id for user generated assets. +// - Whatever other params. +// Then +// - `create_asset` should not work. +#[test] +fn create_asset_with_non_reserved_asset_id_should_not_work() { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { + let origin = 1; + let from_account: Option<::AccountId> = Some(1); + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + + let asset_id = 11; + let initial_issuance = 100; + + assert_noop!( + GenericAsset::create_asset( + Some(asset_id), + from_account, + AssetOptions { + initial_issuance, + permissions: default_permission.clone() + } + ), + Error::::IdUnavailable, + ); + }); +} + +// Given +// - `asset_id` is for reserved assets, but already taken. +// - Whatever other params. +// Then +// - `create_asset` should not work. +#[test] +fn create_asset_with_a_taken_asset_id_should_not_work() { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { + let origin = 1; + let from_account: Option<::AccountId> = Some(1); + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + + let asset_id = 9; + let initial_issuance = 100; + + assert_ok!(GenericAsset::create_asset( + Some(asset_id), + from_account, + AssetOptions { + initial_issuance, + permissions: default_permission.clone() + } + )); + assert_noop!( + GenericAsset::create_asset( + Some(asset_id), + from_account, + AssetOptions { + initial_issuance, + permissions: default_permission.clone() + } + ), + Error::::IdAlreadyTaken, + ); + }); +} + +// Given +// - `asset_id` provided. +// - `from_account` is None. +// - All permissions for origin. +// When +// - After calling create_asset. +// Then +// - Should create a reserved token. +#[test] +fn create_asset_should_create_a_reserved_asset_when_from_account_is_none() { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { + let origin = 1; + let from_account: Option<::AccountId> = None; + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + + let created_account_id = 0; + let asset_id = 9; + let initial_issuance = 100; + + assert_ok!(GenericAsset::create_asset( + Some(asset_id), + from_account, + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + + // Test for a side effect. + assert_eq!( + >::get(&asset_id, &created_account_id), + initial_issuance + ); + }); +} + +// Given +// - `asset_id` not provided. +// - `from_account` is None. +// - All permissions for origin. +// When +// - After calling create_asset. +// Then +// - Should create a user token. +// - `NextAssetId`'s get should return a new value. +// - Should not create a `reserved_asset`. +#[test] +fn create_asset_should_create_a_user_asset() { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { + let origin = 1; + let from_account: Option<::AccountId> = None; + + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + + let created_account_id = 0; + let reserved_asset_id = 100000; + let initial_issuance = 100; + let created_user_asset_id = 10; + + assert_ok!(GenericAsset::create_asset( + None, + from_account, + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + + // Test for side effects. + assert_eq!(>::get(&reserved_asset_id, &created_account_id), 0); + assert_eq!( + >::get(&created_user_asset_id, &created_account_id), + initial_issuance + ); + assert_eq!(>::get(created_user_asset_id), initial_issuance); + }); +} + +#[test] +fn update_permission_should_raise_event() { + // Arrange + let staking_asset_id = 16000; + let asset_id = 1000; + let origin = 1; + let initial_balance = 1000; + let permissions = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + + ExtBuilder::default() + .next_asset_id(asset_id) + .free_balance((staking_asset_id, origin, initial_balance)) + .build() + .execute_with(|| { + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: 0, + permissions: permissions.clone(), + } + )); + + // Act + assert_ok!(GenericAsset::update_permission( + Origin::signed(origin), + asset_id, + permissions.clone() + )); + + let expected_event = TestEvent::generic_asset( + RawEvent::PermissionUpdated(asset_id, permissions.clone()), + ); + // Assert + assert!(System::events().iter().any(|record| record.event == expected_event)); + }, + ); +} + +#[test] +fn mint_should_raise_event() { + // Arrange + let staking_asset_id = 16000; + let asset_id = 1000; + let origin = 1; + let initial_balance = 1000; + let permissions = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + let to = 2; + let amount = 100; + + ExtBuilder::default() + .next_asset_id(asset_id) + .free_balance((staking_asset_id, origin, initial_balance)) + .build() + .execute_with(|| { + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: 0, + permissions: permissions.clone(), + }, + )); + + // Act + assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to, amount)); + + let expected_event = TestEvent::generic_asset(RawEvent::Minted(asset_id, to, amount)); + + // Assert + assert!(System::events().iter().any(|record| record.event == expected_event)); + }, + ); +} + +#[test] +fn burn_should_raise_event() { + // Arrange + let staking_asset_id = 16000; + let asset_id = 1000; + let origin = 1; + let initial_balance = 1000; + let permissions = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; + let amount = 100; + + ExtBuilder::default() + .next_asset_id(asset_id) + .free_balance((staking_asset_id, origin, initial_balance)) + .build() + .execute_with(|| { + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: amount, + permissions: permissions.clone(), + }, + )); + + // Act + assert_ok!(GenericAsset::burn(Origin::signed(origin), asset_id, origin, amount)); + + let expected_event = TestEvent::generic_asset(RawEvent::Burned(asset_id, origin, amount)); + + // Assert + assert!(System::events().iter().any(|record| record.event == expected_event)); + }, + ); +} diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml new file mode 100644 index 0000000000000..ab5b34c91fd9f --- /dev/null +++ b/frame/grandpa/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "pallet-grandpa" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-finality-grandpa = { version = "2.0.0", default-features = false, path = "../../primitives/finality-grandpa" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0", default-features = false, path = "../session" } +pallet-finality-tracker = { version = "2.0.0", default-features = false, path = "../finality-tracker" } + +[dev-dependencies] +sp-io ={ version = "2.0.0", path = "../../primitives/io" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-core/std", + "sp-finality-grandpa/std", + "sp-std/std", + "frame-support/std", + "sp-runtime/std", + "sp-staking/std", + "frame-system/std", + "pallet-session/std", + "pallet-finality-tracker/std", +] +migrate-authorities = [] diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs new file mode 100644 index 0000000000000..f2ef16dc0eee0 --- /dev/null +++ b/frame/grandpa/src/lib.rs @@ -0,0 +1,525 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! GRANDPA Consensus module for runtime. +//! +//! This manages the GRANDPA authority set ready for the native code. +//! These authorities are only for GRANDPA finality, not for consensus overall. +//! +//! In the future, it will also handle misbehavior reports, and on-chain +//! finality notifications. +//! +//! For full integration with GRANDPA, the `GrandpaApi` should be implemented. +//! The necessary items are re-exported via the `fg_primitives` crate. + +#![cfg_attr(not(feature = "std"), no_std)] + +// re-export since this is necessary for `impl_apis` in runtime. +pub use sp_finality_grandpa as fg_primitives; + +use sp_std::prelude::*; +use codec::{self as codec, Encode, Decode}; +use frame_support::{decl_event, decl_storage, decl_module, decl_error, storage}; +use sp_runtime::{ + DispatchResult, generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, Perbill, +}; +use sp_staking::{ + SessionIndex, + offence::{Offence, Kind}, +}; +use fg_primitives::{ + GRANDPA_AUTHORITIES_KEY, GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog, SetId, RoundNumber, +}; +pub use fg_primitives::{AuthorityId, AuthorityList, AuthorityWeight, VersionedAuthorityList}; +use frame_system::{self as system, ensure_signed, DigestOf}; + +mod mock; +mod tests; + +pub trait Trait: frame_system::Trait { + /// The event type of this module. + type Event: From + Into<::Event>; +} + +/// 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: AuthorityList, +} + +/// A stored pending change. +#[derive(Encode)] +pub struct StoredPendingChange { + /// 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: AuthorityList, + /// 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) -> core::result::Result { + let old = OldStoredPendingChange::decode(value)?; + let forced = >::decode(value).unwrap_or(None); + + Ok(StoredPendingChange { + scheduled_at: old.scheduled_at, + delay: old.delay, + next_authorities: old.next_authorities, + forced, + }) + } +} + +/// Current state of the GRANDPA authority set. State transitions must happen in +/// the same order of states defined below, e.g. `Paused` implies a prior +/// `PendingPause`. +#[derive(Decode, Encode)] +#[cfg_attr(test, derive(Debug, PartialEq))] +pub enum StoredState { + /// The current authority set is live, and GRANDPA is enabled. + Live, + /// There is a pending pause event which will be enacted at the given block + /// height. + PendingPause { + /// Block at which the intention to pause was scheduled. + scheduled_at: N, + /// Number of blocks after which the change will be enacted. + delay: N + }, + /// The current GRANDPA authority set is paused. + Paused, + /// There is a pending resume event which will be enacted at the given block + /// height. + PendingResume { + /// Block at which the intention to resume was scheduled. + scheduled_at: N, + /// Number of blocks after which the change will be enacted. + delay: N, + }, +} + +decl_event! { + pub enum Event { + /// New authority set has been applied. + NewAuthorities(AuthorityList), + /// Current authority set has been paused. + Paused, + /// Current authority set has been resumed. + Resumed, + } +} + +decl_error! { + pub enum Error for Module { + /// Attempt to signal GRANDPA pause when the authority set isn't live + /// (either paused or already pending pause). + PauseFailed, + /// Attempt to signal GRANDPA resume when the authority set isn't paused + /// (either live or already pending resume). + ResumeFailed, + /// Attempt to signal GRANDPA change with one already pending. + ChangePending, + /// Cannot signal forced change so soon after last. + TooSoon, + } +} + +decl_storage! { + trait Store for Module as GrandpaFinality { + /// DEPRECATED + /// + /// This used to store the current authority set, which has been migrated to the well-known + /// GRANDPA_AUTHORITES_KEY unhashed key. + #[cfg(feature = "migrate-authorities")] + pub(crate) Authorities get(fn authorities): AuthorityList; + + /// State of the current authority set. + State get(fn state): StoredState = StoredState::Live; + + /// Pending change: (signaled at, scheduled change). + PendingChange: Option>; + + /// next block number where we can force a change. + NextForced get(fn next_forced): Option; + + /// `true` if we are currently stalled. + Stalled get(fn stalled): Option<(T::BlockNumber, T::BlockNumber)>; + + /// The number of changes (both in terms of keys and underlying economic responsibilities) + /// in the "set" of Grandpa validators from genesis. + CurrentSetId get(fn current_set_id) build(|_| fg_primitives::SetId::default()): SetId; + + /// A mapping from grandpa set ID to the index of the *most recent* session for which its members were responsible. + SetIdSession get(fn session_for_set): map SetId => Option; + } + add_extra_genesis { + config(authorities): AuthorityList; + build(|config| Module::::initialize_authorities(&config.authorities)) + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + /// Report some misbehavior. + fn report_misbehavior(origin, _report: Vec) { + ensure_signed(origin)?; + // FIXME: https://github.com/paritytech/substrate/issues/1112 + } + + fn on_initialize() { + #[cfg(feature = "migrate-authorities")] + Self::migrate_authorities(); + } + + fn on_finalize(block_number: T::BlockNumber) { + // check for scheduled pending authority set changes + if let Some(pending_change) = >::get() { + // emit signal if we're at the block that scheduled the change + if block_number == pending_change.scheduled_at { + if let Some(median) = pending_change.forced { + Self::deposit_log(ConsensusLog::ForcedChange( + median, + ScheduledChange { + delay: pending_change.delay, + next_authorities: pending_change.next_authorities.clone(), + } + )) + } else { + Self::deposit_log(ConsensusLog::ScheduledChange( + ScheduledChange{ + delay: pending_change.delay, + next_authorities: pending_change.next_authorities.clone(), + } + )); + } + } + + // enact the change if we've reached the enacting block + if block_number == pending_change.scheduled_at + pending_change.delay { + Self::set_grandpa_authorities(&pending_change.next_authorities); + Self::deposit_event( + Event::NewAuthorities(pending_change.next_authorities) + ); + >::kill(); + } + } + + // check for scheduled pending state changes + match >::get() { + StoredState::PendingPause { scheduled_at, delay } => { + // signal change to pause + if block_number == scheduled_at { + Self::deposit_log(ConsensusLog::Pause(delay)); + } + + // enact change to paused state + if block_number == scheduled_at + delay { + >::put(StoredState::Paused); + Self::deposit_event(Event::Paused); + } + }, + StoredState::PendingResume { scheduled_at, delay } => { + // signal change to resume + if block_number == scheduled_at { + Self::deposit_log(ConsensusLog::Resume(delay)); + } + + // enact change to live state + if block_number == scheduled_at + delay { + >::put(StoredState::Live); + Self::deposit_event(Event::Resumed); + } + }, + _ => {}, + } + } + } +} + +impl Module { + /// Get the current set of authorities, along with their respective weights. + pub fn grandpa_authorities() -> AuthorityList { + storage::unhashed::get_or_default::(GRANDPA_AUTHORITIES_KEY).into() + } + + /// Set the current set of authorities, along with their respective weights. + fn set_grandpa_authorities(authorities: &AuthorityList) { + storage::unhashed::put( + GRANDPA_AUTHORITIES_KEY, + &VersionedAuthorityList::from(authorities), + ); + } + + /// Schedule GRANDPA to pause starting in the given number of blocks. + /// Cannot be done when already paused. + pub fn schedule_pause(in_blocks: T::BlockNumber) -> DispatchResult { + if let StoredState::Live = >::get() { + let scheduled_at = >::block_number(); + >::put(StoredState::PendingPause { + delay: in_blocks, + scheduled_at, + }); + + Ok(()) + } else { + Err(Error::::PauseFailed)? + } + } + + /// Schedule a resume of GRANDPA after pausing. + pub fn schedule_resume(in_blocks: T::BlockNumber) -> DispatchResult { + if let StoredState::Paused = >::get() { + let scheduled_at = >::block_number(); + >::put(StoredState::PendingResume { + delay: in_blocks, + scheduled_at, + }); + + Ok(()) + } else { + Err(Error::::ResumeFailed)? + } + } + + /// Schedule a change in the authorities. + /// + /// The change will be applied at the end of execution of the block + /// `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 signaled while any change is pending. Returns + /// an error if a change is already pending. + pub fn schedule_change( + next_authorities: AuthorityList, + in_blocks: T::BlockNumber, + forced: Option, + ) -> DispatchResult { + if !>::exists() { + let scheduled_at = >::block_number(); + + if let Some(_) = forced { + if Self::next_forced().map_or(false, |next| next > scheduled_at) { + Err(Error::::TooSoon)? + } + + // only allow the next forced change when twice the window has passed since + // this one. + >::put(scheduled_at + in_blocks * 2.into()); + } + + >::put(StoredPendingChange { + delay: in_blocks, + scheduled_at, + next_authorities, + forced, + }); + + Ok(()) + } else { + Err(Error::::ChangePending)? + } + } + + /// Deposit one of this module's logs. + fn deposit_log(log: ConsensusLog) { + let log: DigestItem = DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()); + >::deposit_log(log.into()); + } + + fn initialize_authorities(authorities: &AuthorityList) { + if !authorities.is_empty() { + assert!( + Self::grandpa_authorities().is_empty(), + "Authorities are already initialized!" + ); + Self::set_grandpa_authorities(authorities); + } + } + + #[cfg(feature = "migrate-authorities")] + fn migrate_authorities() { + if Authorities::exists() { + Self::set_grandpa_authorities(&Authorities::take()); + } + } +} + +impl Module { + /// Attempt to extract a GRANDPA log from a generic digest. + pub fn grandpa_log(digest: &DigestOf) -> Option> { + let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); + digest.convert_first(|l| l.try_to::>(id)) + } + + /// Attempt to extract a pending set-change signal from a digest. + pub fn pending_change(digest: &DigestOf) + -> Option> + { + Self::grandpa_log(digest).and_then(|signal| signal.try_into_change()) + } + + /// Attempt to extract a forced set-change signal from a digest. + pub fn forced_change(digest: &DigestOf) + -> Option<(T::BlockNumber, ScheduledChange)> + { + Self::grandpa_log(digest).and_then(|signal| signal.try_into_forced_change()) + } + + /// Attempt to extract a pause signal from a digest. + pub fn pending_pause(digest: &DigestOf) + -> Option + { + Self::grandpa_log(digest).and_then(|signal| signal.try_into_pause()) + } + + /// Attempt to extract a resume signal from a digest. + pub fn pending_resume(digest: &DigestOf) + -> Option + { + Self::grandpa_log(digest).and_then(|signal| signal.try_into_resume()) + } +} + +impl sp_runtime::BoundToRuntimeAppPublic for Module { + type Public = AuthorityId; +} + +impl pallet_session::OneSessionHandler for Module + where T: pallet_session::Trait +{ + type Key = AuthorityId; + + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); + Self::initialize_authorities(&authorities); + } + + fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) + where I: Iterator + { + // Always issue a change if `session` says that the validators have changed. + // Even if their session keys are the same as before, the underyling economic + // identities have changed. + let current_set_id = if changed { + let next_authorities = validators.map(|(_, k)| (k, 1)).collect::>(); + if let Some((further_wait, median)) = >::take() { + let _ = Self::schedule_change(next_authorities, further_wait, Some(median)); + } else { + let _ = Self::schedule_change(next_authorities, Zero::zero(), None); + } + CurrentSetId::mutate(|s| { *s += 1; *s }) + } else { + // nothing's changed, neither economic conditions nor session keys. update the pointer + // of the current set. + Self::current_set_id() + }; + + // if we didn't issue a change, we update the mapping to note that the current + // set corresponds to the latest equivalent session (i.e. now). + let session_index = >::current_index(); + SetIdSession::insert(current_set_id, &session_index); + } + + fn on_disabled(i: usize) { + Self::deposit_log(ConsensusLog::OnDisabled(i as u64)) + } +} + +impl pallet_finality_tracker::OnFinalizationStalled for Module { + fn on_stalled(further_wait: T::BlockNumber, median: T::BlockNumber) { + // when we record old authority sets, we can use `pallet_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. + >::put((further_wait, median)); + } +} + +/// A round number and set id which point on the time of an offence. +#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Encode, Decode)] +struct GrandpaTimeSlot { + // The order of these matters for `derive(Ord)`. + set_id: SetId, + round: RoundNumber, +} + +// TODO [slashing]: Integrate this. +/// A grandpa equivocation offence report. +#[allow(dead_code)] +struct GrandpaEquivocationOffence { + /// Time slot at which this incident happened. + time_slot: GrandpaTimeSlot, + /// The session index in which the incident happened. + session_index: SessionIndex, + /// The size of the validator set at the time of the offence. + validator_set_count: u32, + /// The authority which produced this equivocation. + offender: FullIdentification, +} + +impl Offence for GrandpaEquivocationOffence { + const ID: Kind = *b"grandpa:equivoca"; + type TimeSlot = GrandpaTimeSlot; + + fn offenders(&self) -> Vec { + vec![self.offender.clone()] + } + + fn session_index(&self) -> SessionIndex { + self.session_index + } + + fn validator_set_count(&self) -> u32 { + self.validator_set_count + } + + fn time_slot(&self) -> Self::TimeSlot { + self.time_slot + } + + fn slash_fraction( + offenders_count: u32, + validator_set_count: u32, + ) -> Perbill { + // the formula is min((3k / n)^2, 1) + let x = Perbill::from_rational_approximation(3 * offenders_count, validator_set_count); + // _ ^ 2 + x.square() + } +} diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs new file mode 100644 index 0000000000000..0015dd1f504aa --- /dev/null +++ b/frame/grandpa/src/mock.rs @@ -0,0 +1,95 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use sp_runtime::{Perbill, DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; +use sp_io; +use frame_support::{impl_outer_origin, impl_outer_event, parameter_types, weights::Weight}; +use sp_core::H256; +use codec::{Encode, Decode}; +use crate::{AuthorityId, AuthorityList, GenesisConfig, Trait, Module, ConsensusLog}; +use sp_finality_grandpa::GRANDPA_ENGINE_ID; + +use frame_system as system; +impl_outer_origin!{ + pub enum Origin for Test where system = frame_system {} +} + +pub fn grandpa_log(log: ConsensusLog) -> DigestItem { + DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()) +} + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug, Decode, Encode)] +pub struct Test; + +impl Trait for Test { + type Event = TestEvent; +} +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +mod grandpa { + pub use crate::Event; +} + +impl_outer_event!{ + pub enum TestEvent for Test { + grandpa, + } +} + +pub fn to_authorities(vec: Vec<(u64, u64)>) -> AuthorityList { + vec.into_iter() + .map(|(id, weight)| (UintAuthorityId(id).to_public_key::(), weight)) + .collect() +} + +pub fn new_test_ext(authorities: Vec<(u64, u64)>) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig { + authorities: to_authorities(authorities), + }.assimilate_storage::(&mut t).unwrap(); + t.into() +} + +pub type System = frame_system::Module; +pub type Grandpa = Module; diff --git a/frame/grandpa/src/tests.rs b/frame/grandpa/src/tests.rs new file mode 100644 index 0000000000000..ff3841b8d4593 --- /dev/null +++ b/frame/grandpa/src/tests.rs @@ -0,0 +1,338 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +#![cfg(test)] + +use sp_runtime::{testing::{H256, Digest}, traits::{Header, OnFinalize}}; +use crate::mock::*; +use frame_system::{EventRecord, Phase}; +use codec::{Decode, Encode}; +use fg_primitives::ScheduledChange; +use super::*; + +fn initialize_block(number: u64, parent_hash: H256) { + System::initialize( + &number, + &parent_hash, + &Default::default(), + &Default::default(), + Default::default(), + ); +} + +#[test] +fn authorities_change_logged() { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { + initialize_block(1, Default::default()); + Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 0, None).unwrap(); + + System::note_finished_extrinsics(); + Grandpa::on_finalize(1); + + let header = System::finalize(); + assert_eq!(header.digest, Digest { + logs: vec![ + grandpa_log(ConsensusLog::ScheduledChange( + ScheduledChange { delay: 0, next_authorities: to_authorities(vec![(4, 1), (5, 1), (6, 1)]) } + )), + ], + }); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Finalization, + event: Event::NewAuthorities(to_authorities(vec![(4, 1), (5, 1), (6, 1)])).into(), + topics: vec![], + }, + ]); + }); +} + +#[test] +fn authorities_change_logged_after_delay() { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { + initialize_block(1, Default::default()); + Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 1, None).unwrap(); + Grandpa::on_finalize(1); + let header = System::finalize(); + assert_eq!(header.digest, Digest { + logs: vec![ + grandpa_log(ConsensusLog::ScheduledChange( + ScheduledChange { delay: 1, next_authorities: to_authorities(vec![(4, 1), (5, 1), (6, 1)]) } + )), + ], + }); + + // no change at this height. + assert_eq!(System::events(), vec![]); + + initialize_block(2, header.hash()); + System::note_finished_extrinsics(); + Grandpa::on_finalize(2); + + let _header = System::finalize(); + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::Finalization, + event: Event::NewAuthorities(to_authorities(vec![(4, 1), (5, 1), (6, 1)])).into(), + topics: vec![], + }, + ]); + }); +} + +#[test] +fn cannot_schedule_change_when_one_pending() { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { + initialize_block(1, Default::default()); + Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 1, None).unwrap(); + assert!(>::exists()); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err()); + + Grandpa::on_finalize(1); + let header = System::finalize(); + + initialize_block(2, header.hash()); + assert!(>::exists()); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err()); + + Grandpa::on_finalize(2); + let header = System::finalize(); + + initialize_block(3, header.hash()); + assert!(!>::exists()); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_ok()); + + Grandpa::on_finalize(3); + let _header = System::finalize(); + }); +} + +#[test] +fn new_decodes_from_old() { + let old = OldStoredPendingChange { + scheduled_at: 5u32, + delay: 100u32, + next_authorities: to_authorities(vec![(1, 5), (2, 10), (3, 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() { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { + initialize_block(1, Default::default()); + Grandpa::schedule_change( + to_authorities(vec![(4, 1), (5, 1), (6, 1)]), + 5, + Some(0), + ).unwrap(); + + assert!(>::exists()); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, Some(0)).is_err()); + + Grandpa::on_finalize(1); + let mut header = System::finalize(); + + for i in 2..7 { + initialize_block(i, header.hash()); + assert!(>::get().unwrap().forced.is_some()); + assert_eq!(Grandpa::next_forced(), Some(11)); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err()); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, Some(0)).is_err()); + + Grandpa::on_finalize(i); + header = System::finalize(); + } + + // change has been applied at the end of block 6. + // add a normal change. + { + initialize_block(7, header.hash()); + assert!(!>::exists()); + assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(4, 1), (5, 1), (6, 1)])); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_ok()); + Grandpa::on_finalize(7); + header = System::finalize(); + } + + // run the normal change. + { + initialize_block(8, header.hash()); + assert!(>::exists()); + assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(4, 1), (5, 1), (6, 1)])); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err()); + Grandpa::on_finalize(8); + header = System::finalize(); + } + + // normal change applied. but we can't apply a new forced change for some + // time. + for i in 9..11 { + initialize_block(i, header.hash()); + assert!(!>::exists()); + assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(5, 1)])); + assert_eq!(Grandpa::next_forced(), Some(11)); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1), (6, 1)]), 5, Some(0)).is_err()); + Grandpa::on_finalize(i); + header = System::finalize(); + } + + { + initialize_block(11, header.hash()); + assert!(!>::exists()); + assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1), (6, 1), (7, 1)]), 5, Some(0)).is_ok()); + assert_eq!(Grandpa::next_forced(), Some(21)); + Grandpa::on_finalize(11); + header = System::finalize(); + } + let _ = header; + }); +} + +#[test] +fn schedule_pause_only_when_live() { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { + // we schedule a pause at block 1 with delay of 1 + initialize_block(1, Default::default()); + Grandpa::schedule_pause(1).unwrap(); + + // we've switched to the pending pause state + assert_eq!( + Grandpa::state(), + StoredState::PendingPause { + scheduled_at: 1u64, + delay: 1, + }, + ); + + Grandpa::on_finalize(1); + let _ = System::finalize(); + + initialize_block(2, Default::default()); + + // signaling a pause now should fail + assert!(Grandpa::schedule_pause(1).is_err()); + + Grandpa::on_finalize(2); + let _ = System::finalize(); + + // after finalizing block 2 the set should have switched to paused state + assert_eq!( + Grandpa::state(), + StoredState::Paused, + ); + }); +} + +#[test] +fn schedule_resume_only_when_paused() { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { + initialize_block(1, Default::default()); + + // the set is currently live, resuming it is an error + assert!(Grandpa::schedule_resume(1).is_err()); + + assert_eq!( + Grandpa::state(), + StoredState::Live, + ); + + // we schedule a pause to be applied instantly + Grandpa::schedule_pause(0).unwrap(); + Grandpa::on_finalize(1); + let _ = System::finalize(); + + assert_eq!( + Grandpa::state(), + StoredState::Paused, + ); + + // we schedule the set to go back live in 2 blocks + initialize_block(2, Default::default()); + Grandpa::schedule_resume(2).unwrap(); + Grandpa::on_finalize(2); + let _ = System::finalize(); + + initialize_block(3, Default::default()); + Grandpa::on_finalize(3); + let _ = System::finalize(); + + initialize_block(4, Default::default()); + Grandpa::on_finalize(4); + let _ = System::finalize(); + + // it should be live at block 4 + assert_eq!( + Grandpa::state(), + StoredState::Live, + ); + }); +} + +#[test] +fn time_slot_have_sane_ord() { + // Ensure that `Ord` implementation is sane. + const FIXTURE: &[GrandpaTimeSlot] = &[ + GrandpaTimeSlot { + set_id: 0, + round: 0, + }, + GrandpaTimeSlot { + set_id: 0, + round: 1, + }, + GrandpaTimeSlot { + set_id: 1, + round: 0, + }, + GrandpaTimeSlot { + set_id: 1, + round: 1, + }, + GrandpaTimeSlot { + set_id: 1, + round: 2, + } + ]; + assert!(FIXTURE.windows(2).all(|f| f[0] < f[1])); +} + +#[test] +#[cfg(feature = "migrate-authorities")] +fn authorities_migration() { + use sp_runtime::traits::OnInitialize; + + with_externalities(&mut new_test_ext(vec![]), || { + let authorities = to_authorities(vec![(1, 1), (2, 1), (3, 1)]); + + Authorities::put(authorities.clone()); + assert!(Grandpa::grandpa_authorities().is_empty()); + + Grandpa::on_initialize(1); + + assert!(!Authorities::exists()); + assert_eq!(Grandpa::grandpa_authorities(), authorities); + }); +} diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml new file mode 100644 index 0000000000000..7962c2a1c62bf --- /dev/null +++ b/frame/identity/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "pallet-identity" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +enumflags2 = { version = "0.6.2" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "sp-io/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs new file mode 100644 index 0000000000000..b23407406b6a4 --- /dev/null +++ b/frame/identity/src/lib.rs @@ -0,0 +1,1210 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Identity Module +//! +//! - [`identity::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! A federated naming system, allowing for multiple registrars to be added from a specified origin. +//! Registrars can set a fee to provide identity-verification service. Anyone can put forth a +//! proposed identity for a fixed deposit and ask for review by any number of registrars (paying +//! each of their fees). Registrar judgements are given as an `enum`, allowing for sophisticated, +//! multi-tier opinions. +//! +//! Some judgements are identified as *sticky*, which means they cannot be removed except by +//! complete removal of the identity, or by the registrar. Judgements are allowed to represent a +//! portion of funds that have been reserved for the registrar. +//! +//! A super-user can remove accounts and in doing so, slash the deposit. +//! +//! All accounts may also have a limited number of sub-accounts which may be specified by the owner; +//! by definition, these have equivalent ownership and each has an individual name. +//! +//! The number of registrars should be limited, and the deposit made sufficiently large, to ensure +//! no state-bloat attack is viable. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! #### For general users +//! * `set_identity` - Set the associated identity of an account; a small deposit is reserved if not +//! already taken. +//! * `set_subs` - Set the sub-accounts of an identity. +//! * `clear_identity` - Remove an account's associated identity; the deposit is returned. +//! * `request_judgement` - Request a judgement from a registrar, paying a fee. +//! * `cancel_request` - Cancel the previous request for a judgement. +//! +//! #### For registrars +//! * `set_fee` - Set the fee required to be paid for a judgement to be given by the registrar. +//! * `set_fields` - Set the fields that a registrar cares about in their judgements. +//! * `provide_judgement` - Provide a judgement to an identity. +//! +//! #### For super-users +//! * `add_registrar` - Add a new registrar to the system. +//! * `kill_identity` - Forcibly remove the associated identity; the deposit is lost. +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use sp_std::{fmt::Debug, ops::Add, iter::once}; +use enumflags2::BitFlags; +use codec::{Encode, Decode}; +use sp_runtime::{DispatchResult, RuntimeDebug}; +use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput}; +use frame_support::{ + decl_module, decl_event, decl_storage, ensure, decl_error, + traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, + weights::SimpleDispatchInfo, +}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The currency trait. + type Currency: ReservableCurrency; + + /// The amount held on deposit for a registered identity. + type BasicDeposit: Get>; + + /// The amount held on deposit per additional field for a registered identity. + type FieldDeposit: Get>; + + /// The amount held on deposit for a registered subaccount. This should account for the fact + /// that one storage item's value will increase by the size of an account ID, and there will be + /// another trie item whose value is the size of an account ID plus 32 bytes. + type SubAccountDeposit: Get>; + + /// The maximum number of sub-accounts allowed per identified account. + type MaximumSubAccounts: Get; + + /// What to do with slashed funds. + type Slashed: OnUnbalanced>; + + /// The origin which may forcibly set or remove a name. Root can always do this. + type ForceOrigin: EnsureOrigin; + + /// The origin which may add or remove registrars. Root can always do this. + type RegistrarOrigin: EnsureOrigin; +} + +/// Either underlying data blob if it is at most 32 bytes, or a hash of it. If the data is greater +/// than 32-bytes then it will be truncated when encoding. +/// +/// Can also be `None`. +#[derive(Clone, Eq, PartialEq, RuntimeDebug)] +pub enum Data { + /// No data here. + None, + /// The data is stored directly. + Raw(Vec), + /// Only the Blake2 hash of the data is stored. The preimage of the hash may be retrieved + /// through some hash-lookup service. + BlakeTwo256([u8; 32]), + /// Only the SHA2-256 hash of the data is stored. The preimage of the hash may be retrieved + /// through some hash-lookup service. + Sha256([u8; 32]), + /// Only the Keccak-256 hash of the data is stored. The preimage of the hash may be retrieved + /// through some hash-lookup service. + Keccak256([u8; 32]), + /// Only the SHA3-256 hash of the data is stored. The preimage of the hash may be retrieved + /// through some hash-lookup service. + ShaThree256([u8; 32]), +} + +impl Decode for Data { + fn decode(input: &mut I) -> sp_std::result::Result { + let b = input.read_byte()?; + Ok(match b { + 0 => Data::None, + n @ 1 ..= 33 => { + let mut r = vec![0u8; n as usize - 1]; + input.read(&mut r[..])?; + Data::Raw(r) + } + 34 => Data::BlakeTwo256(<[u8; 32]>::decode(input)?), + 35 => Data::Sha256(<[u8; 32]>::decode(input)?), + 36 => Data::Keccak256(<[u8; 32]>::decode(input)?), + 37 => Data::ShaThree256(<[u8; 32]>::decode(input)?), + _ => return Err(codec::Error::from("invalid leading byte")), + }) + } +} + +impl Encode for Data { + fn encode(&self) -> Vec { + match self { + Data::None => vec![0u8; 1], + Data::Raw(ref x) => { + let l = x.len().min(32); + let mut r = vec![l as u8 + 1; l + 1]; + &mut r[1..].copy_from_slice(&x[..l as usize]); + r + } + Data::BlakeTwo256(ref h) => once(34u8).chain(h.iter().cloned()).collect(), + Data::Sha256(ref h) => once(35u8).chain(h.iter().cloned()).collect(), + Data::Keccak256(ref h) => once(36u8).chain(h.iter().cloned()).collect(), + Data::ShaThree256(ref h) => once(37u8).chain(h.iter().cloned()).collect(), + } + } +} +impl codec::EncodeLike for Data {} + +impl Default for Data { + fn default() -> Self { + Self::None + } +} + +/// An identifier for a single name registrar/identity verification service. +pub type RegistrarIndex = u32; + +/// An attestation of a registrar over how accurate some `IdentityInfo` is in describing an account. +/// +/// NOTE: Registrars may pay little attention to some fields. Registrars may want to make clear +/// which fields their attestation is relevant for by off-chain means. +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] +pub enum Judgement< + Balance: Encode + Decode + Copy + Clone + Debug + Eq + PartialEq +> { + /// The default value; no opinion is held. + Unknown, + /// No judgement is yet in place, but a deposit is reserved as payment for providing one. + FeePaid(Balance), + /// The data appears to be reasonably acceptable in terms of its accuracy, however no in depth + /// checks (such as in-person meetings or formal KYC) have been conducted. + Reasonable, + /// The target is known directly by the registrar and the registrar can fully attest to the + /// the data's accuracy. + KnownGood, + /// The data was once good but is currently out of date. There is no malicious intent in the + /// inaccuracy. This judgement can be removed through updating the data. + OutOfDate, + /// The data is imprecise or of sufficiently low-quality to be problematic. It is not + /// indicative of malicious intent. This judgement can be removed through updating the data. + LowQuality, + /// The data is erroneous. This may be indicative of malicious intent. This cannot be removed + /// except by the registrar. + Erroneous, +} + +impl< + Balance: Encode + Decode + Copy + Clone + Debug + Eq + PartialEq +> Judgement { + /// Returns `true` if this judgement is indicative of a deposit being currently held. This means + /// it should not be cleared or replaced except by an operation which utilizes the deposit. + fn has_deposit(&self) -> bool { + match self { + Judgement::FeePaid(_) => true, + _ => false, + } + } + + /// Returns `true` if this judgement is one that should not be generally be replaced outside + /// of specialized handlers. Examples include "malicious" judgements and deposit-holding + /// judgements. + fn is_sticky(&self) -> bool { + match self { + Judgement::FeePaid(_) | Judgement::Erroneous => true, + _ => false, + } + } +} + +/// The fields that we use to identify the owner of an account with. Each corresponds to a field +/// in the `IdentityInfo` struct. +#[repr(u64)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, BitFlags, RuntimeDebug)] +pub enum IdentityField { + Display = 0b0000000000000000000000000000000000000000000000000000000000000001, + Legal = 0b0000000000000000000000000000000000000000000000000000000000000010, + Web = 0b0000000000000000000000000000000000000000000000000000000000000100, + Riot = 0b0000000000000000000000000000000000000000000000000000000000001000, + Email = 0b0000000000000000000000000000000000000000000000000000000000010000, + PgpFingerprint = 0b0000000000000000000000000000000000000000000000000000000000100000, + Image = 0b0000000000000000000000000000000000000000000000000000000001000000, + Twitter = 0b0000000000000000000000000000000000000000000000000000000010000000, +} + +/// Wrapper type for `BitFlags` that implements `Codec`. +#[derive(Clone, Copy, PartialEq, Default, RuntimeDebug)] +pub struct IdentityFields(BitFlags); + +impl Eq for IdentityFields {} +impl Encode for IdentityFields { + fn using_encoded R>(&self, f: F) -> R { + self.0.bits().using_encoded(f) + } +} +impl Decode for IdentityFields { + fn decode(input: &mut I) -> sp_std::result::Result { + let field = u64::decode(input)?; + Ok(Self(>::from_bits(field as u64).map_err(|_| "invalid value")?)) + } +} + +/// Information concerning the identity of the controller of an account. +/// +/// NOTE: This should be stored at the end of the storage item to facilitate the addition of extra +/// fields in a backwards compatible way through a specialized `Decode` impl. +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] +#[cfg_attr(test, derive(Default))] +pub struct IdentityInfo { + /// Additional fields of the identity that are not catered for with the struct's explicit + /// fields. + pub additional: Vec<(Data, Data)>, + + /// A reasonable display name for the controller of the account. This should be whatever it is + /// that it is typically known as and should not be confusable with other entities, given + /// reasonable context. + /// + /// Stored as UTF-8. + pub display: Data, + + /// The full legal name in the local jurisdiction of the entity. This might be a bit + /// long-winded. + /// + /// Stored as UTF-8. + pub legal: Data, + + /// A representative website held by the controller of the account. + /// + /// NOTE: `https://` is automatically prepended. + /// + /// Stored as UTF-8. + pub web: Data, + + /// The Riot/Matrix handle held by the controller of the account. + /// + /// Stored as UTF-8. + pub riot: Data, + + /// The email address of the controller of the account. + /// + /// Stored as UTF-8. + pub email: Data, + + /// The PGP/GPG public key of the controller of the account. + pub pgp_fingerprint: Option<[u8; 20]>, + + /// A graphic image representing the controller of the account. Should be a company, + /// organization or project logo or a headshot in the case of a human. + pub image: Data, + + /// The Twitter identity. The leading `@` character may be elided. + pub twitter: Data, +} + +/// Information concerning the identity of the controller of an account. +/// +/// NOTE: This is stored separately primarily to facilitate the addition of extra fields in a +/// backwards compatible way through a specialized `Decode` impl. +#[derive(Clone, Encode, Eq, PartialEq, RuntimeDebug)] +pub struct Registration< + Balance: Encode + Decode + Copy + Clone + Debug + Eq + PartialEq +> { + /// Judgements from the registrars on this identity. Stored ordered by `RegistrarIndex`. There + /// may be only a single judgement from each registrar. + pub judgements: Vec<(RegistrarIndex, Judgement)>, + + /// Amount held on deposit for this information. + pub deposit: Balance, + + /// Information on the identity. + pub info: IdentityInfo, +} + +impl < + Balance: Encode + Decode + Copy + Clone + Debug + Eq + PartialEq + Zero + Add, +> Registration { + fn total_deposit(&self) -> Balance { + self.deposit + self.judgements.iter() + .map(|(_, ref j)| if let Judgement::FeePaid(fee) = j { *fee } else { Zero::zero() }) + .fold(Zero::zero(), |a, i| a + i) + } +} + +impl< + Balance: Encode + Decode + Copy + Clone + Debug + Eq + PartialEq, +> Decode for Registration { + fn decode(input: &mut I) -> sp_std::result::Result { + let (judgements, deposit, info) = Decode::decode(&mut AppendZerosInput::new(input))?; + Ok(Self { judgements, deposit, info }) + } +} + +/// Information concerning a registrar. +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] +pub struct RegistrarInfo< + Balance: Encode + Decode + Clone + Debug + Eq + PartialEq, + AccountId: Encode + Decode + Clone + Debug + Eq + PartialEq +> { + /// The account of the registrar. + pub account: AccountId, + + /// Amount required to be given to the registrar for them to provide judgement. + pub fee: Balance, + + /// Relevant fields for this registrar. Registrar judgements are limited to attestations on + /// these fields. + pub fields: IdentityFields, +} + +decl_storage! { + trait Store for Module as Sudo { + /// Information that is pertinent to identify the entity behind an account. + pub IdentityOf get(fn identity): map T::AccountId => Option>>; + + /// The super-identity of an alternative "sub" identity together with its name, within that + /// context. If the account is not some other account's sub-identity, then just `None`. + pub SuperOf get(fn super_of): map T::AccountId => Option<(T::AccountId, Data)>; + + /// Alternative "sub" identities of this account. + /// + /// The first item is the deposit, the second is a vector of the accounts. + pub SubsOf get(fn subs): map T::AccountId => (BalanceOf, Vec); + + /// The set of registrars. Not expected to get very big as can only be added through a + /// special origin (likely a council motion). + /// + /// The index into this can be cast to `RegistrarIndex` to get a valid value. + pub Registrars get(fn registrars): Vec, T::AccountId>>>; + } +} + +decl_event!( + pub enum Event where AccountId = ::AccountId, Balance = BalanceOf { + /// A name was set or reset (which will remove all judgements). + IdentitySet(AccountId), + /// A name was cleared, and the given balance returned. + IdentityCleared(AccountId, Balance), + /// A name was removed and the given balance slashed. + IdentityKilled(AccountId, Balance), + /// A judgement was asked from a registrar. + JudgementRequested(AccountId, RegistrarIndex), + /// A judgement request was retracted. + JudgementUnrequested(AccountId, RegistrarIndex), + /// A judgement was given by a registrar. + JudgementGiven(AccountId, RegistrarIndex), + /// A registrar was added. + RegistrarAdded(RegistrarIndex), + } +); + +decl_error! { + /// Error for the identity module. + pub enum Error for Module { + /// Too many subs-accounts. + TooManySubAccounts, + /// Account isn't found. + NotFound, + /// Account isn't named. + NotNamed, + /// Empty index. + EmptyIndex, + /// Fee is changed. + FeeChanged, + /// No identity found. + NoIdentity, + /// Sticky judgement. + StickyJudgement, + /// Judgement given. + JudgementGiven, + /// Invalid judgement. + InvalidJudgement, + /// The index is invalid. + InvalidIndex, + /// The target is invalid. + InvalidTarget, + } +} + +decl_module! { + // Simple declaration of the `Module` type. Lets the macro know what it's working on. + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + /// Add a registrar to the system. + /// + /// The dispatch origin for this call must be `RegistrarOrigin` or `Root`. + /// + /// - `account`: the account of the registrar. + /// + /// Emits `RegistrarAdded` if successful. + /// + /// # + /// - `O(R)` where `R` registrar-count (governance-bounded). + /// - One storage mutation (codec `O(R)`). + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn add_registrar(origin, account: T::AccountId) { + T::RegistrarOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + let i = >::mutate(|r| { + r.push(Some(RegistrarInfo { account, fee: Zero::zero(), fields: Default::default() })); + (r.len() - 1) as RegistrarIndex + }); + + Self::deposit_event(RawEvent::RegistrarAdded(i)); + } + + /// Set an account's identity information and reserve the appropriate deposit. + /// + /// If the account already has identity information, the deposit is taken as part payment + /// for the new deposit. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must have a registered + /// identity. + /// + /// - `info`: The identity information. + /// + /// Emits `IdentitySet` if successful. + /// + /// # + /// - `O(X + R)` where `X` additional-field-count (deposit-bounded). + /// - At most two balance operations. + /// - One storage mutation (codec `O(X + R)`). + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn set_identity(origin, info: IdentityInfo) { + let sender = ensure_signed(origin)?; + let fd = >::from(info.additional.len() as u32) * T::FieldDeposit::get(); + + let mut id = match >::get(&sender) { + Some(mut id) => { + // Only keep non-positive judgements. + id.judgements.retain(|j| j.1.is_sticky()); + id.info = info; + id + } + None => Registration { info, judgements: Vec::new(), deposit: Zero::zero() }, + }; + + let old_deposit = id.deposit; + id.deposit = T::BasicDeposit::get() + fd; + if id.deposit > old_deposit { + T::Currency::reserve(&sender, id.deposit - old_deposit)?; + } + if old_deposit > id.deposit { + let _ = T::Currency::unreserve(&sender, old_deposit - id.deposit); + } + + >::insert(&sender, id); + Self::deposit_event(RawEvent::IdentitySet(sender)); + } + + /// Set the sub-accounts of the sender. + /// + /// Payment: Any aggregate balance reserved by previous `set_subs` calls will be returned + /// and an amount `SubAccountDeposit` will be reserved for each item in `subs`. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must have a registered + /// identity. + /// + /// - `subs`: The identity's sub-accounts. + /// + /// # + /// - `O(S)` where `S` subs-count (hard- and deposit-bounded). + /// - At most two balance operations. + /// - At most O(2 * S + 1) storage mutations; codec complexity `O(1 * S + S * 1)`); + /// one storage-exists. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn set_subs(origin, subs: Vec<(T::AccountId, Data)>) { + let sender = ensure_signed(origin)?; + ensure!(>::exists(&sender), Error::::NotFound); + ensure!(subs.len() <= T::MaximumSubAccounts::get() as usize, Error::::TooManySubAccounts); + + let (old_deposit, old_ids) = >::get(&sender); + let new_deposit = T::SubAccountDeposit::get() * >::from(subs.len() as u32); + + if old_deposit < new_deposit { + T::Currency::reserve(&sender, new_deposit - old_deposit)?; + } + // do nothing if they're equal. + if old_deposit > new_deposit { + let _ = T::Currency::unreserve(&sender, old_deposit - new_deposit); + } + + for s in old_ids.iter() { + >::remove(s); + } + let ids = subs.into_iter().map(|(id, name)| { + >::insert(&id, (sender.clone(), name)); + id + }).collect::>(); + + if ids.is_empty() { + >::remove(&sender); + } else { + >::insert(&sender, (new_deposit, ids)); + } + } + + /// Clear an account's identity info and all sub-account and return all deposits. + /// + /// Payment: All reserved balances on the account are returned. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must have a registered + /// identity. + /// + /// Emits `IdentityCleared` if successful. + /// + /// # + /// - `O(R + S + X)`. + /// - One balance-reserve operation. + /// - `S + 2` storage deletions. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn clear_identity(origin) { + let sender = ensure_signed(origin)?; + + let (subs_deposit, sub_ids) = >::take(&sender); + let deposit = >::take(&sender).ok_or(Error::::NotNamed)?.total_deposit() + + subs_deposit; + for sub in sub_ids.iter() { + >::remove(sub); + } + + let _ = T::Currency::unreserve(&sender, deposit.clone()); + + Self::deposit_event(RawEvent::IdentityCleared(sender, deposit)); + } + + /// Request a judgement from a registrar. + /// + /// Payment: At most `max_fee` will be reserved for payment to the registrar if judgement + /// given. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must have a + /// registered identity. + /// + /// - `reg_index`: The index of the registrar whose judgement is requested. + /// - `max_fee`: The maximum fee that may be paid. This should just be auto-populated as: + /// + /// ```nocompile + /// Self::registrars(reg_index).uwnrap().fee + /// ``` + /// + /// Emits `JudgementRequested` if successful. + /// + /// # + /// - `O(R + X)`. + /// - One balance-reserve operation. + /// - Storage: 1 read `O(R)`, 1 mutate `O(X + R)`. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn request_judgement(origin, + #[compact] reg_index: RegistrarIndex, + #[compact] max_fee: BalanceOf, + ) { + let sender = ensure_signed(origin)?; + let registrars = >::get(); + let registrar = registrars.get(reg_index as usize).and_then(Option::as_ref) + .ok_or(Error::::EmptyIndex)?; + ensure!(max_fee >= registrar.fee, Error::::FeeChanged); + let mut id = >::get(&sender).ok_or(Error::::NoIdentity)?; + + let item = (reg_index, Judgement::FeePaid(registrar.fee)); + match id.judgements.binary_search_by_key(®_index, |x| x.0) { + Ok(i) => if id.judgements[i].1.is_sticky() { + Err(Error::::StickyJudgement)? + } else { + id.judgements[i] = item + }, + Err(i) => id.judgements.insert(i, item), + } + + T::Currency::reserve(&sender, registrar.fee)?; + + >::insert(&sender, id); + + Self::deposit_event(RawEvent::JudgementRequested(sender, reg_index)); + } + + /// Cancel a previous request. + /// + /// Payment: A previously reserved deposit is returned on success. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must have a + /// registered identity. + /// + /// - `reg_index`: The index of the registrar whose judgement is no longer requested. + /// + /// Emits `JudgementUnrequested` if successful. + /// + /// # + /// - `O(R + X)`. + /// - One balance-reserve operation. + /// - One storage mutation `O(R + X)`. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn cancel_request(origin, reg_index: RegistrarIndex) { + let sender = ensure_signed(origin)?; + let mut id = >::get(&sender).ok_or(Error::::NoIdentity)?; + + let pos = id.judgements.binary_search_by_key(®_index, |x| x.0) + .map_err(|_| Error::::NotFound)?; + let fee = if let Judgement::FeePaid(fee) = id.judgements.remove(pos).1 { + fee + } else { + Err(Error::::JudgementGiven)? + }; + + let _ = T::Currency::unreserve(&sender, fee); + >::insert(&sender, id); + + Self::deposit_event(RawEvent::JudgementUnrequested(sender, reg_index)); + } + + /// Set the fee required for a judgement to be requested from a registrar. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must be the account + /// of the registrar whose index is `index`. + /// + /// - `index`: the index of the registrar whose fee is to be set. + /// - `fee`: the new fee. + /// + /// # + /// - `O(R)`. + /// - One storage mutation `O(R)`. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn set_fee(origin, + #[compact] index: RegistrarIndex, + #[compact] fee: BalanceOf, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + >::mutate(|rs| + rs.get_mut(index as usize) + .and_then(|x| x.as_mut()) + .and_then(|r| if r.account == who { r.fee = fee; Some(()) } else { None }) + .ok_or_else(|| Error::::InvalidIndex.into()) + ) + } + + /// Change the account associated with a registrar. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must be the account + /// of the registrar whose index is `index`. + /// + /// - `index`: the index of the registrar whose fee is to be set. + /// - `new`: the new account ID. + /// + /// # + /// - `O(R)`. + /// - One storage mutation `O(R)`. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn set_account_id(origin, + #[compact] index: RegistrarIndex, + new: T::AccountId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + >::mutate(|rs| + rs.get_mut(index as usize) + .and_then(|x| x.as_mut()) + .and_then(|r| if r.account == who { r.account = new; Some(()) } else { None }) + .ok_or_else(|| Error::::InvalidIndex.into()) + ) + } + + /// Set the field information for a registrar. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must be the account + /// of the registrar whose index is `index`. + /// + /// - `index`: the index of the registrar whose fee is to be set. + /// - `fields`: the fields that the registrar concerns themselves with. + /// + /// # + /// - `O(R)`. + /// - One storage mutation `O(R)`. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn set_fields(origin, + #[compact] index: RegistrarIndex, + fields: IdentityFields, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + >::mutate(|rs| + rs.get_mut(index as usize) + .and_then(|x| x.as_mut()) + .and_then(|r| if r.account == who { r.fields = fields; Some(()) } else { None }) + .ok_or_else(|| Error::::InvalidIndex.into()) + ) + } + + /// Provide a judgement for an account's identity. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must be the account + /// of the registrar whose index is `reg_index`. + /// + /// - `reg_index`: the index of the registrar whose judgement is being made. + /// - `target`: the account whose identity the judgement is upon. This must be an account + /// with a registered identity. + /// - `judgement`: the judgement of the registrar of index `reg_index` about `target`. + /// + /// Emits `JudgementGiven` if successful. + /// + /// # + /// - `O(R + X)`. + /// - One balance-transfer operation. + /// - Up to one account-lookup operation. + /// - Storage: 1 read `O(R)`, 1 mutate `O(R + X)`. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn provide_judgement(origin, + #[compact] reg_index: RegistrarIndex, + target: ::Source, + judgement: Judgement>, + ) { + let sender = ensure_signed(origin)?; + let target = T::Lookup::lookup(target)?; + ensure!(!judgement.has_deposit(), Error::::InvalidJudgement); + >::get() + .get(reg_index as usize) + .and_then(Option::as_ref) + .and_then(|r| if r.account == sender { Some(r) } else { None }) + .ok_or(Error::::InvalidIndex)?; + let mut id = >::get(&target).ok_or(Error::::InvalidTarget)?; + + let item = (reg_index, judgement); + match id.judgements.binary_search_by_key(®_index, |x| x.0) { + Ok(position) => { + if let Judgement::FeePaid(fee) = id.judgements[position].1 { + let _ = T::Currency::repatriate_reserved(&target, &sender, fee); + } + id.judgements[position] = item + } + Err(position) => id.judgements.insert(position, item), + } + >::insert(&target, id); + Self::deposit_event(RawEvent::JudgementGiven(target, reg_index)); + } + + /// Remove an account's identity and sub-account information and slash the deposits. + /// + /// Payment: Reserved balances from `set_subs` and `set_identity` are slashed and handled by + /// `Slash`. Verification request deposits are not returned; they should be cancelled + /// manually using `cancel_request`. + /// + /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// + /// - `target`: the account whose identity the judgement is upon. This must be an account + /// with a registered identity. + /// + /// Emits `IdentityKilled` if successful. + /// + /// # + /// - `O(R + S + X)`. + /// - One balance-reserve operation. + /// - `S + 2` storage mutations. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn kill_identity(origin, target: ::Source) { + T::ForceOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + // Figure out who we're meant to be clearing. + let target = T::Lookup::lookup(target)?; + // Grab their deposit (and check that they have one). + let (subs_deposit, sub_ids) = >::take(&target); + let deposit = >::take(&target).ok_or(Error::::NotNamed)?.total_deposit() + + subs_deposit; + for sub in sub_ids.iter() { + >::remove(sub); + } + // Slash their deposit from them. + T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit).0); + + Self::deposit_event(RawEvent::IdentityKilled(target, deposit)); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use sp_runtime::traits::BadOrigin; + use frame_support::{ + assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight, + ord_parameter_types + }; + use sp_core::H256; + use frame_system::EnsureSignedBy; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. + use sp_runtime::{ + Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, + }; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + parameter_types! { + pub const BasicDeposit: u64 = 10; + pub const FieldDeposit: u64 = 10; + pub const SubAccountDeposit: u64 = 10; + pub const MaximumSubAccounts: u32 = 2; + } + ord_parameter_types! { + pub const One: u64 = 1; + pub const Two: u64 = 2; + } + impl Trait for Test { + type Event = (); + type Currency = Balances; + type Slashed = (); + type BasicDeposit = BasicDeposit; + type FieldDeposit = FieldDeposit; + type SubAccountDeposit = SubAccountDeposit; + type MaximumSubAccounts = MaximumSubAccounts; + type RegistrarOrigin = EnsureSignedBy; + type ForceOrigin = EnsureSignedBy; + } + type System = frame_system::Module; + type Balances = pallet_balances::Module; + type Identity = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + pallet_balances::GenesisConfig:: { + balances: vec![ + (1, 10), + (2, 10), + (3, 10), + (10, 100), + (20, 100), + (30, 100), + ], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + fn ten() -> IdentityInfo { + IdentityInfo { + display: Data::Raw(b"ten".to_vec()), + legal: Data::Raw(b"The Right Ordinal Ten, Esq.".to_vec()), + .. Default::default() + } + } + + #[test] + fn trailing_zeros_decodes_into_default_data() { + let encoded = Data::Raw(b"Hello".to_vec()).encode(); + assert!(<(Data, Data)>::decode(&mut &encoded[..]).is_err()); + let input = &mut &encoded[..]; + let (a, b) = <(Data, Data)>::decode(&mut AppendZerosInput::new(input)).unwrap(); + assert_eq!(a, Data::Raw(b"Hello".to_vec())); + assert_eq!(b, Data::None); + } + + #[test] + fn adding_registrar_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::add_registrar(Origin::signed(1), 3)); + assert_ok!(Identity::set_fee(Origin::signed(3), 0, 10)); + let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); + assert_ok!(Identity::set_fields(Origin::signed(3), 0, fields)); + assert_eq!(Identity::registrars(), vec![ + Some(RegistrarInfo { account: 3, fee: 10, fields }) + ]); + }); + } + + #[test] + fn registration_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::add_registrar(Origin::signed(1), 3)); + assert_ok!(Identity::set_fee(Origin::signed(3), 0, 10)); + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_eq!(Identity::identity(10).unwrap().info, ten()); + assert_eq!(Balances::free_balance(10), 90); + assert_ok!(Identity::clear_identity(Origin::signed(10))); + assert_eq!(Balances::free_balance(10), 100); + assert_noop!(Identity::clear_identity(Origin::signed(10)), Error::::NotNamed); + }); + } + + #[test] + fn uninvited_judgement_should_work() { + new_test_ext().execute_with(|| { + assert_noop!( + Identity::provide_judgement(Origin::signed(3), 0, 10, Judgement::Reasonable), + Error::::InvalidIndex + ); + + assert_ok!(Identity::add_registrar(Origin::signed(1), 3)); + assert_noop!( + Identity::provide_judgement(Origin::signed(3), 0, 10, Judgement::Reasonable), + Error::::InvalidTarget + ); + + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_noop!( + Identity::provide_judgement(Origin::signed(10), 0, 10, Judgement::Reasonable), + Error::::InvalidIndex + ); + assert_noop!( + Identity::provide_judgement(Origin::signed(3), 0, 10, Judgement::FeePaid(1)), + Error::::InvalidJudgement + ); + + assert_ok!(Identity::provide_judgement(Origin::signed(3), 0, 10, Judgement::Reasonable)); + assert_eq!(Identity::identity(10).unwrap().judgements, vec![(0, Judgement::Reasonable)]); + }); + } + + #[test] + fn clearing_judgement_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::add_registrar(Origin::signed(1), 3)); + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_ok!(Identity::provide_judgement(Origin::signed(3), 0, 10, Judgement::Reasonable)); + assert_ok!(Identity::clear_identity(Origin::signed(10))); + assert_eq!(Identity::identity(10), None); + }); + } + + #[test] + fn killing_slashing_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_noop!(Identity::kill_identity(Origin::signed(1), 10), BadOrigin); + assert_ok!(Identity::kill_identity(Origin::signed(2), 10)); + assert_eq!(Identity::identity(10), None); + assert_eq!(Balances::free_balance(10), 90); + assert_noop!(Identity::kill_identity(Origin::signed(2), 10), Error::::NotNamed); + }); + } + + #[test] + fn setting_subaccounts_should_work() { + new_test_ext().execute_with(|| { + let mut subs = vec![(20, Data::Raw(vec![40; 1]))]; + assert_noop!(Identity::set_subs(Origin::signed(10), subs.clone()), Error::::NotFound); + + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_ok!(Identity::set_subs(Origin::signed(10), subs.clone())); + assert_eq!(Balances::free_balance(10), 80); + assert_eq!(Identity::subs(10), (10, vec![20])); + assert_eq!(Identity::super_of(20), Some((10, Data::Raw(vec![40; 1])))); + + // push another item and re-set it. + subs.push((30, Data::Raw(vec![50; 1]))); + assert_ok!(Identity::set_subs(Origin::signed(10), subs.clone())); + assert_eq!(Balances::free_balance(10), 70); + assert_eq!(Identity::subs(10), (20, vec![20, 30])); + assert_eq!(Identity::super_of(20), Some((10, Data::Raw(vec![40; 1])))); + assert_eq!(Identity::super_of(30), Some((10, Data::Raw(vec![50; 1])))); + + // switch out one of the items and re-set. + subs[0] = (40, Data::Raw(vec![60; 1])); + assert_ok!(Identity::set_subs(Origin::signed(10), subs.clone())); + assert_eq!(Balances::free_balance(10), 70); // no change in the balance + assert_eq!(Identity::subs(10), (20, vec![40, 30])); + assert_eq!(Identity::super_of(20), None); + assert_eq!(Identity::super_of(30), Some((10, Data::Raw(vec![50; 1])))); + assert_eq!(Identity::super_of(40), Some((10, Data::Raw(vec![60; 1])))); + + // clear + assert_ok!(Identity::set_subs(Origin::signed(10), vec![])); + assert_eq!(Balances::free_balance(10), 90); + assert_eq!(Identity::subs(10), (0, vec![])); + assert_eq!(Identity::super_of(30), None); + assert_eq!(Identity::super_of(40), None); + + subs.push((20, Data::Raw(vec![40; 1]))); + assert_noop!(Identity::set_subs(Origin::signed(10), subs.clone()), Error::::TooManySubAccounts); + }); + } + + #[test] + fn clearing_account_should_remove_subaccounts_and_refund() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_ok!(Identity::set_subs(Origin::signed(10), vec![(20, Data::Raw(vec![40; 1]))])); + assert_ok!(Identity::clear_identity(Origin::signed(10))); + assert_eq!(Balances::free_balance(10), 100); + assert!(Identity::super_of(20).is_none()); + }); + } + + #[test] + fn killing_account_should_remove_subaccounts_and_not_refund() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_ok!(Identity::set_subs(Origin::signed(10), vec![(20, Data::Raw(vec![40; 1]))])); + assert_ok!(Identity::kill_identity(Origin::ROOT, 10)); + assert_eq!(Balances::free_balance(10), 80); + assert!(Identity::super_of(20).is_none()); + }); + } + + #[test] + fn cancelling_requested_judgement_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::add_registrar(Origin::signed(1), 3)); + assert_ok!(Identity::set_fee(Origin::signed(3), 0, 10)); + assert_noop!(Identity::cancel_request(Origin::signed(10), 0), Error::::NoIdentity); + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_ok!(Identity::request_judgement(Origin::signed(10), 0, 10)); + assert_ok!(Identity::cancel_request(Origin::signed(10), 0)); + assert_eq!(Balances::free_balance(10), 90); + assert_noop!(Identity::cancel_request(Origin::signed(10), 0), Error::::NotFound); + + assert_ok!(Identity::provide_judgement(Origin::signed(3), 0, 10, Judgement::Reasonable)); + assert_noop!(Identity::cancel_request(Origin::signed(10), 0), Error::::JudgementGiven); + }); + } + + #[test] + fn requesting_judgement_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::add_registrar(Origin::signed(1), 3)); + assert_ok!(Identity::set_fee(Origin::signed(3), 0, 10)); + assert_ok!(Identity::set_identity(Origin::signed(10), ten())); + assert_noop!(Identity::request_judgement(Origin::signed(10), 0, 9), Error::::FeeChanged); + assert_ok!(Identity::request_judgement(Origin::signed(10), 0, 10)); + // 10 for the judgement request, 10 for the identity. + assert_eq!(Balances::free_balance(10), 80); + + // Re-requesting won't work as we already paid. + assert_noop!(Identity::request_judgement(Origin::signed(10), 0, 10), Error::::StickyJudgement); + assert_ok!(Identity::provide_judgement(Origin::signed(3), 0, 10, Judgement::Erroneous)); + // Registrar got their payment now. + assert_eq!(Balances::free_balance(3), 20); + + // Re-requesting still won't work as it's erroneous. + assert_noop!(Identity::request_judgement(Origin::signed(10), 0, 10), Error::::StickyJudgement); + + // Requesting from a second registrar still works. + assert_ok!(Identity::add_registrar(Origin::signed(1), 4)); + assert_ok!(Identity::request_judgement(Origin::signed(10), 1, 10)); + + // Re-requesting after the judgement has been reduced works. + assert_ok!(Identity::provide_judgement(Origin::signed(3), 0, 10, Judgement::OutOfDate)); + assert_ok!(Identity::request_judgement(Origin::signed(10), 0, 10)); + }); + } + + #[test] + fn field_deposit_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::add_registrar(Origin::signed(1), 3)); + assert_ok!(Identity::set_fee(Origin::signed(3), 0, 10)); + assert_ok!(Identity::set_identity(Origin::signed(10), IdentityInfo { + additional: vec![ + (Data::Raw(b"number".to_vec()), Data::Raw(10u32.encode())), + (Data::Raw(b"text".to_vec()), Data::Raw(b"10".to_vec())), + ], .. Default::default() + })); + assert_eq!(Balances::free_balance(10), 70); + }); + } + + #[test] + fn setting_account_id_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Identity::add_registrar(Origin::signed(1), 3)); + // account 4 cannot change the first registrar's identity since it's owned by 3. + assert_noop!(Identity::set_account_id(Origin::signed(4), 0, 3), Error::::InvalidIndex); + // account 3 can, because that's the registrar's current account. + assert_ok!(Identity::set_account_id(Origin::signed(3), 0, 4)); + // account 4 can now, because that's their new ID. + assert_ok!(Identity::set_account_id(Origin::signed(4), 0, 3)); + }); + } +} diff --git a/frame/im-online/Cargo.toml b/frame/im-online/Cargo.toml new file mode 100644 index 0000000000000..5045509c7723a --- /dev/null +++ b/frame/im-online/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "pallet-im-online" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../../primitives/application-crypto" } +pallet-authorship = { version = "2.0.0", default-features = false, path = "../authorship" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +serde = { version = "1.0.101", optional = true } +pallet-session = { version = "2.0.0", default-features = false, path = "../session" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[features] +default = ["std", "pallet-session/historical"] +std = [ + "sp-application-crypto/std", + "pallet-authorship/std", + "codec/std", + "sp-core/std", + "sp-std/std", + "serde", + "pallet-session/std", + "sp-io/std", + "sp-runtime/std", + "sp-staking/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs new file mode 100644 index 0000000000000..065ca7e3bfc16 --- /dev/null +++ b/frame/im-online/src/lib.rs @@ -0,0 +1,680 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # I'm online Module +//! +//! If the local node is a validator (i.e. contains an authority key), this module +//! gossips a heartbeat transaction with each new session. The heartbeat functions +//! as a simple mechanism to signal that the node is online in the current era. +//! +//! Received heartbeats are tracked for one era and reset with each new era. The +//! module exposes two public functions to query if a heartbeat has been received +//! in the current era or session. +//! +//! The heartbeat is a signed transaction, which was signed using the session key +//! and includes the recent best block number of the local validators chain as well +//! as the [NetworkState](../../client/offchain/struct.NetworkState.html). +//! It is submitted as an Unsigned Transaction via off-chain workers. +//! +//! - [`im_online::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Interface +//! +//! ### Public Functions +//! +//! - `is_online` - True if the validator sent a heartbeat in the current session. +//! +//! ## Usage +//! +//! ``` +//! use frame_support::{decl_module, dispatch}; +//! use frame_system::{self as system, ensure_signed}; +//! use pallet_im_online::{self as im_online}; +//! +//! pub trait Trait: im_online::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn is_online(origin, authority_index: u32) -> dispatch::DispatchResult { +//! let _sender = ensure_signed(origin)?; +//! let _is_online = >::is_online(authority_index); +//! Ok(()) +//! } +//! } +//! } +//! # fn main() { } +//! ``` +//! +//! ## Dependencies +//! +//! This module depends on the [Session module](../pallet_session/index.html). + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +mod mock; +mod tests; + +use sp_application_crypto::RuntimeAppPublic; +use codec::{Encode, Decode}; +use sp_core::offchain::{OpaqueNetworkState, StorageKind}; +use sp_std::prelude::*; +use sp_std::convert::TryInto; +use pallet_session::historical::IdentificationTuple; +use sp_runtime::{ + RuntimeDebug, + traits::{Convert, Member, Printable, Saturating}, Perbill, + transaction_validity::{ + TransactionValidity, ValidTransaction, InvalidTransaction, + TransactionPriority, + }, +}; +use sp_staking::{ + SessionIndex, + offence::{ReportOffence, Offence, Kind}, +}; +use frame_support::{ + decl_module, decl_event, decl_storage, print, Parameter, debug, decl_error, + traits::Get, +}; +use frame_system::{self as system, ensure_none}; +use frame_system::offchain::SubmitUnsignedTransaction; + +pub mod sr25519 { + mod app_sr25519 { + use sp_application_crypto::{app_crypto, key_types::IM_ONLINE, sr25519}; + app_crypto!(sr25519, IM_ONLINE); + } + + /// An i'm online keypair using sr25519 as its crypto. + #[cfg(feature = "std")] + pub type AuthorityPair = app_sr25519::Pair; + + /// An i'm online signature using sr25519 as its crypto. + pub type AuthoritySignature = app_sr25519::Signature; + + /// An i'm online identifier using sr25519 as its crypto. + pub type AuthorityId = app_sr25519::Public; +} + +pub mod ed25519 { + mod app_ed25519 { + use sp_application_crypto::{app_crypto, key_types::IM_ONLINE, ed25519}; + app_crypto!(ed25519, IM_ONLINE); + } + + /// An i'm online keypair using ed25519 as its crypto. + #[cfg(feature = "std")] + pub type AuthorityPair = app_ed25519::Pair; + + /// An i'm online signature using ed25519 as its crypto. + pub type AuthoritySignature = app_ed25519::Signature; + + /// An i'm online identifier using ed25519 as its crypto. + pub type AuthorityId = app_ed25519::Public; +} + +/// The local storage database key under which the worker progress status +/// is tracked. +const DB_KEY: &[u8] = b"parity/im-online-worker-status"; + +/// It's important to persist the worker state, since e.g. the +/// server could be restarted while starting the gossip process, but before +/// finishing it. With every execution of the off-chain worker we check +/// if we need to recover and resume gossipping or if there is already +/// another off-chain worker in the process of gossipping. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +struct WorkerStatus { + done: bool, + gossipping_at: BlockNumber, +} + +/// Error which may occur while executing the off-chain code. +#[derive(RuntimeDebug)] +enum OffchainErr { + DecodeWorkerStatus, + FailedSigning, + NetworkState, + SubmitTransaction, +} + +impl Printable for OffchainErr { + fn print(&self) { + match self { + OffchainErr::DecodeWorkerStatus => print("Offchain error: decoding WorkerStatus failed!"), + OffchainErr::FailedSigning => print("Offchain error: signing failed!"), + OffchainErr::NetworkState => print("Offchain error: fetching network state failed!"), + OffchainErr::SubmitTransaction => print("Offchain error: submitting transaction failed!"), + } + } +} + +pub type AuthIndex = u32; + +/// Heartbeat which is sent/received. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct Heartbeat + where BlockNumber: PartialEq + Eq + Decode + Encode, +{ + /// Block number at the time heartbeat is created.. + pub block_number: BlockNumber, + /// A state of local network (peer id and external addresses) + pub network_state: OpaqueNetworkState, + /// Index of the current session. + pub session_index: SessionIndex, + /// An index of the authority on the list of validators. + pub authority_index: AuthIndex, +} + +pub trait Trait: frame_system::Trait + pallet_session::historical::Trait { + /// The identifier type for an authority. + type AuthorityId: Member + Parameter + RuntimeAppPublic + Default + Ord; + + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// A dispatchable call type. + type Call: From>; + + /// A transaction submitter. + type SubmitTransaction: SubmitUnsignedTransaction::Call>; + + /// An expected duration of the session. + /// + /// This parameter is used to determine the longevity of `heartbeat` transaction + /// and a rough time when the heartbeat should be sent. + type SessionDuration: Get; + + /// A type that gives us the ability to submit unresponsiveness offence reports. + type ReportUnresponsiveness: + ReportOffence< + Self::AccountId, + IdentificationTuple, + UnresponsivenessOffence>, + >; +} + +decl_event!( + pub enum Event where + ::AuthorityId, + IdentificationTuple = IdentificationTuple, + { + /// A new heartbeat was received from `AuthorityId` + HeartbeatReceived(AuthorityId), + /// At the end of the session, no offence was committed. + AllGood, + /// At the end of the session, at least once validator was found to be offline. + SomeOffline(Vec), + } +); + +decl_storage! { + trait Store for Module as ImOnline { + /// The block number when we should gossip. + GossipAt get(fn gossip_at): T::BlockNumber; + + /// The current set of keys that may issue a heartbeat. + Keys get(fn keys): Vec; + + /// For each session index, we keep a mapping of `AuthIndex` + /// to `offchain::OpaqueNetworkState`. + ReceivedHeartbeats get(fn received_heartbeats): double_map SessionIndex, AuthIndex + => Option>; + + /// For each session index, we keep a mapping of `T::ValidatorId` to the + /// number of blocks authored by the given authority. + AuthoredBlocks get(fn authored_blocks): double_map SessionIndex, T::ValidatorId => u32; + } + add_extra_genesis { + config(keys): Vec; + build(|config| Module::::initialize_keys(&config.keys)) + } +} + +decl_error! { + /// Error for the im-online module. + pub enum Error for Module { + /// Non existent public key. + InvalidKey, + /// Duplicated heartbeat. + DuplicatedHeartbeat, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + fn heartbeat( + origin, + heartbeat: Heartbeat, + // since signature verification is done in `validate_unsigned` + // we can skip doing it here again. + _signature: ::Signature + ) { + ensure_none(origin)?; + + let current_session = >::current_index(); + let exists = ::exists( + ¤t_session, + &heartbeat.authority_index + ); + let keys = Keys::::get(); + let public = keys.get(heartbeat.authority_index as usize); + if let (false, Some(public)) = (exists, public) { + Self::deposit_event(Event::::HeartbeatReceived(public.clone())); + + let network_state = heartbeat.network_state.encode(); + ::insert( + ¤t_session, + &heartbeat.authority_index, + &network_state + ); + } else if exists { + Err(Error::::DuplicatedHeartbeat)? + } else { + Err(Error::::InvalidKey)? + } + } + + // Runs after every block. + fn offchain_worker(now: T::BlockNumber) { + debug::RuntimeLogger::init(); + + // Only send messages if we are a potential validator. + if sp_io::offchain::is_validator() { + Self::offchain(now); + } + } + } +} + +/// Keep track of number of authored blocks per authority, uncles are counted as +/// well since they're a valid proof of onlineness. +impl pallet_authorship::EventHandler for Module { + fn note_author(author: T::ValidatorId) { + Self::note_authorship(author); + } + + fn note_uncle(author: T::ValidatorId, _age: T::BlockNumber) { + Self::note_authorship(author); + } +} + +impl Module { + /// Returns `true` if a heartbeat has been received for the authority at + /// `authority_index` in the authorities series or if the authority has + /// authored at least one block, during the current session. Otherwise + /// `false`. + pub fn is_online(authority_index: AuthIndex) -> bool { + let current_validators = >::validators(); + + if authority_index >= current_validators.len() as u32 { + return false; + } + + let authority = ¤t_validators[authority_index as usize]; + + Self::is_online_aux(authority_index, authority) + } + + fn is_online_aux(authority_index: AuthIndex, authority: &T::ValidatorId) -> bool { + let current_session = >::current_index(); + + ::exists(¤t_session, &authority_index) || + >::get( + ¤t_session, + authority, + ) != 0 + } + + /// Returns `true` if a heartbeat has been received for the authority at `authority_index` in + /// the authorities series, during the current session. Otherwise `false`. + pub fn received_heartbeat_in_current_session(authority_index: AuthIndex) -> bool { + let current_session = >::current_index(); + ::exists(¤t_session, &authority_index) + } + + /// Note that the given authority has authored a block in the current session. + fn note_authorship(author: T::ValidatorId) { + let current_session = >::current_index(); + + >::mutate( + ¤t_session, + author, + |authored| *authored += 1, + ); + } + + pub(crate) fn offchain(now: T::BlockNumber) { + let next_gossip = >::get(); + let check = Self::check_not_yet_gossipped(now, next_gossip); + let (curr_worker_status, not_yet_gossipped) = match check { + Ok((s, v)) => (s, v), + Err(err) => { + print(err); + return; + }, + }; + if next_gossip < now && not_yet_gossipped { + let value_set = Self::compare_and_set_worker_status(now, false, curr_worker_status); + if !value_set { + // value could not be set in local storage, since the value was + // different from `curr_worker_status`. this indicates that + // another worker was running in parallel. + return; + } + + match Self::do_gossip_at(now) { + Ok(_) => {}, + Err(err) => print(err), + } + } else { + debug::native::debug!( + target: "imonline", + "Skipping gossip at: {:?} >= {:?} || {:?}", + next_gossip, + now, + if not_yet_gossipped { "not gossipped" } else { "gossipped" } + ); + } + } + + fn do_gossip_at(block_number: T::BlockNumber) -> Result<(), OffchainErr> { + // we run only when a local authority key is configured + let authorities = Keys::::get(); + let mut results = Vec::new(); + let mut local_keys = T::AuthorityId::all(); + local_keys.sort(); + + for (authority_index, key) in authorities.into_iter() + .enumerate() + .filter_map(|(index, authority)| { + local_keys.binary_search(&authority) + .ok() + .map(|location| (index as u32, &local_keys[location])) + }) + { + if Self::is_online(authority_index) { + debug::native::info!( + target: "imonline", + "[index: {:?}] Skipping sending heartbeat at block: {:?}. Already online.", + authority_index, + block_number + ); + continue; + } + + let network_state = sp_io::offchain::network_state() + .map_err(|_| OffchainErr::NetworkState)?; + let heartbeat_data = Heartbeat { + block_number, + network_state, + session_index: >::current_index(), + authority_index, + }; + + let signature = key.sign(&heartbeat_data.encode()).ok_or(OffchainErr::FailedSigning)?; + let call = Call::heartbeat(heartbeat_data, signature); + + debug::info!( + target: "imonline", + "[index: {:?}] Reporting im-online at block: {:?}", + authority_index, + block_number + ); + + results.push( + T::SubmitTransaction::submit_unsigned(call) + .map_err(|_| OffchainErr::SubmitTransaction) + ); + } + + // fail only after trying all keys. + results.into_iter().collect::, OffchainErr>>()?; + + // once finished we set the worker status without comparing + // if the existing value changed in the meantime. this is + // because at this point the heartbeat was definitely submitted. + Self::set_worker_status(block_number, true); + + Ok(()) + } + + fn compare_and_set_worker_status( + gossipping_at: T::BlockNumber, + done: bool, + curr_worker_status: Option>, + ) -> bool { + let enc = WorkerStatus { + done, + gossipping_at, + }; + sp_io::offchain::local_storage_compare_and_set( + StorageKind::PERSISTENT, + DB_KEY, + curr_worker_status, + &enc.encode() + ) + } + + fn set_worker_status( + gossipping_at: T::BlockNumber, + done: bool, + ) { + let enc = WorkerStatus { + done, + gossipping_at, + }; + sp_io::offchain::local_storage_set(StorageKind::PERSISTENT, DB_KEY, &enc.encode()); + } + + // Checks if a heartbeat gossip already occurred at this block number. + // Returns a tuple of `(current worker status, bool)`, whereby the bool + // is true if not yet gossipped. + fn check_not_yet_gossipped( + now: T::BlockNumber, + next_gossip: T::BlockNumber, + ) -> Result<(Option>, bool), OffchainErr> { + let last_gossip = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, DB_KEY); + match last_gossip { + Some(last) => { + let worker_status: WorkerStatus = Decode::decode(&mut &last[..]) + .map_err(|_| OffchainErr::DecodeWorkerStatus)?; + + let was_aborted = !worker_status.done && worker_status.gossipping_at < now; + + // another off-chain worker is currently in the process of submitting + let already_submitting = + !worker_status.done && worker_status.gossipping_at == now; + + let not_yet_gossipped = + worker_status.done && worker_status.gossipping_at < next_gossip; + + let ret = (was_aborted && !already_submitting) || not_yet_gossipped; + Ok((Some(last), ret)) + }, + None => Ok((None, true)), + } + } + + fn initialize_keys(keys: &[T::AuthorityId]) { + if !keys.is_empty() { + assert!(Keys::::get().is_empty(), "Keys are already initialized!"); + Keys::::put(keys); + } + } +} + +impl sp_runtime::BoundToRuntimeAppPublic for Module { + type Public = T::AuthorityId; +} + +impl pallet_session::OneSessionHandler for Module { + type Key = T::AuthorityId; + + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let keys = validators.map(|x| x.1).collect::>(); + Self::initialize_keys(&keys); + } + + fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, _queued_validators: I) + where I: Iterator + { + // Tell the offchain worker to start making the next session's heartbeats. + // Since we consider producing blocks as being online, + // the hearbeat is defered a bit to prevent spaming. + let block_number = >::block_number(); + let half_session = T::SessionDuration::get() / 2.into(); + >::put(block_number + half_session); + + // Remember who the authorities are for the new session. + Keys::::put(validators.map(|x| x.1).collect::>()); + } + + fn on_before_session_ending() { + let session_index = >::current_index(); + let keys = Keys::::get(); + let current_validators = >::validators(); + + let offenders = current_validators.into_iter().enumerate() + .filter(|(index, id)| + !Self::is_online_aux(*index as u32, id) + ).filter_map(|(_, id)| + T::FullIdentificationOf::convert(id.clone()).map(|full_id| (id, full_id)) + ).collect::>>(); + + // Remove all received heartbeats and number of authored blocks from the + // current session, they have already been processed and won't be needed + // anymore. + ::remove_prefix(&>::current_index()); + >::remove_prefix(&>::current_index()); + + if offenders.is_empty() { + Self::deposit_event(RawEvent::AllGood); + } else { + Self::deposit_event(RawEvent::SomeOffline(offenders.clone())); + + let validator_set_count = keys.len() as u32; + let offence = UnresponsivenessOffence { session_index, validator_set_count, offenders }; + T::ReportUnresponsiveness::report_offence(vec![], offence); + } + } + + fn on_disabled(_i: usize) { + // ignore + } +} + +#[allow(deprecated)] +impl frame_support::unsigned::ValidateUnsigned for Module { + type Call = Call; + + fn validate_unsigned(call: &Self::Call) -> TransactionValidity { + if let Call::heartbeat(heartbeat, signature) = call { + if >::is_online(heartbeat.authority_index) { + // we already received a heartbeat for this authority + return InvalidTransaction::Stale.into(); + } + + // check if session index from heartbeat is recent + let current_session = >::current_index(); + if heartbeat.session_index != current_session { + return InvalidTransaction::Stale.into(); + } + + // verify that the incoming (unverified) pubkey is actually an authority id + let keys = Keys::::get(); + let authority_id = match keys.get(heartbeat.authority_index as usize) { + Some(id) => id, + None => return InvalidTransaction::BadProof.into(), + }; + + // check signature (this is expensive so we do it last). + let signature_valid = heartbeat.using_encoded(|encoded_heartbeat| { + authority_id.verify(&encoded_heartbeat, &signature) + }); + + if !signature_valid { + return InvalidTransaction::BadProof.into(); + } + + Ok(ValidTransaction { + priority: TransactionPriority::max_value(), + requires: vec![], + provides: vec![(current_session, authority_id).encode()], + longevity: TryInto::::try_into(T::SessionDuration::get() / 2.into()).unwrap_or(64_u64), + propagate: true, + }) + } else { + InvalidTransaction::Call.into() + } + } +} + +/// An offence that is filed if a validator didn't send a heartbeat message. +#[derive(RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Clone, PartialEq, Eq))] +pub struct UnresponsivenessOffence { + /// The current session index in which we report the unresponsive validators. + /// + /// It acts as a time measure for unresponsiveness reports and effectively will always point + /// at the end of the session. + session_index: SessionIndex, + /// The size of the validator set in current session/era. + validator_set_count: u32, + /// Authorities that were unresponsive during the current era. + offenders: Vec, +} + +impl Offence for UnresponsivenessOffence { + const ID: Kind = *b"im-online:offlin"; + type TimeSlot = SessionIndex; + + fn offenders(&self) -> Vec { + self.offenders.clone() + } + + fn session_index(&self) -> SessionIndex { + self.session_index + } + + fn validator_set_count(&self) -> u32 { + self.validator_set_count + } + + fn time_slot(&self) -> Self::TimeSlot { + self.session_index + } + + fn slash_fraction(offenders: u32, validator_set_count: u32) -> Perbill { + // the formula is min((3 * (k - (n / 10 + 1))) / n, 1) * 0.07 + // basically, 10% can be offline with no slash, but after that, it linearly climbs up to 7% + // when 13/30 are offline (around 5% when 1/3 are offline). + if let Some(threshold) = offenders.checked_sub(validator_set_count / 10 + 1) { + let x = Perbill::from_rational_approximation(3 * threshold, validator_set_count); + x.saturating_mul(Perbill::from_percent(7)) + } else { + Perbill::default() + } + } +} diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs new file mode 100644 index 0000000000000..387ff47c09fa5 --- /dev/null +++ b/frame/im-online/src/mock.rs @@ -0,0 +1,179 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use std::cell::RefCell; + +use crate::{Module, Trait}; +use sp_runtime::Perbill; +use sp_staking::{SessionIndex, offence::ReportOffence}; +use sp_runtime::testing::{Header, UintAuthorityId, TestXt}; +use sp_runtime::traits::{IdentityLookup, BlakeTwo256, ConvertInto}; +use sp_core::H256; +use frame_support::{impl_outer_origin, impl_outer_dispatch, parameter_types, weights::Weight}; + +use frame_system as system; +impl_outer_origin!{ + pub enum Origin for Runtime {} +} + +impl_outer_dispatch! { + pub enum Call for Runtime where origin: Origin { + imonline::ImOnline, + } +} + +thread_local! { + pub static VALIDATORS: RefCell>> = RefCell::new(Some(vec![1, 2, 3])); +} + +pub struct TestOnSessionEnding; +impl pallet_session::OnSessionEnding for TestOnSessionEnding { + fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) + -> Option> + { + VALIDATORS.with(|l| l.borrow_mut().take()) + } +} + +impl pallet_session::historical::OnSessionEnding for TestOnSessionEnding { + fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) + -> Option<(Vec, Vec<(u64, u64)>)> + { + VALIDATORS.with(|l| l + .borrow_mut() + .take() + .map(|validators| { + let full_identification = validators.iter().map(|v| (*v, *v)).collect(); + (validators, full_identification) + }) + ) + } +} + +/// An extrinsic type used for tests. +pub type Extrinsic = TestXt; +type SubmitTransaction = frame_system::offchain::TransactionSubmitter<(), Call, Extrinsic>; +type IdentificationTuple = (u64, u64); +type Offence = crate::UnresponsivenessOffence; + +thread_local! { + pub static OFFENCES: RefCell, Offence)>> = RefCell::new(vec![]); +} + +/// A mock offence report handler. +pub struct OffenceHandler; +impl ReportOffence for OffenceHandler { + fn report_offence(reporters: Vec, offence: Offence) { + OFFENCES.with(|l| l.borrow_mut().push((reporters, offence))); + } +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + t.into() +} + + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Runtime; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +parameter_types! { + pub const Period: u64 = 1; + pub const Offset: u64 = 0; +} + +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); +} + +impl pallet_session::Trait for Runtime { + type ShouldEndSession = pallet_session::PeriodicSessions; + type OnSessionEnding = pallet_session::historical::NoteHistoricalRoot; + type SessionHandler = (ImOnline, ); + type ValidatorId = u64; + type ValidatorIdOf = ConvertInto; + type Keys = UintAuthorityId; + type Event = (); + type SelectInitialValidators = (); + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; +} + +impl pallet_session::historical::Trait for Runtime { + type FullIdentification = u64; + type FullIdentificationOf = ConvertInto; +} + +parameter_types! { + pub const UncleGenerations: u32 = 5; +} + +impl pallet_authorship::Trait for Runtime { + type FindAuthor = (); + type UncleGenerations = UncleGenerations; + type FilterUncle = (); + type EventHandler = ImOnline; +} + +impl Trait for Runtime { + type AuthorityId = UintAuthorityId; + type Event = (); + type Call = Call; + type SubmitTransaction = SubmitTransaction; + type ReportUnresponsiveness = OffenceHandler; + type SessionDuration = Period; +} + +/// Im Online module. +pub type ImOnline = Module; +pub type System = frame_system::Module; +pub type Session = pallet_session::Module; + +pub fn advance_session() { + let now = System::block_number(); + System::set_block_number(now + 1); + Session::rotate_session(); + assert_eq!(Session::current_index(), (now / Period::get()) as u32); +} diff --git a/frame/im-online/src/tests.rs b/frame/im-online/src/tests.rs new file mode 100644 index 0000000000000..34eac233ae317 --- /dev/null +++ b/frame/im-online/src/tests.rs @@ -0,0 +1,338 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the im-online module. + +#![cfg(test)] + +use super::*; +use crate::mock::*; +use sp_core::offchain::{ + OpaquePeerId, + OffchainExt, + TransactionPoolExt, + testing::{TestOffchainExt, TestTransactionPoolExt}, +}; +use frame_support::{dispatch, assert_noop}; +use sp_runtime::testing::UintAuthorityId; + +#[test] +fn test_unresponsiveness_slash_fraction() { + // A single case of unresponsiveness is not slashed. + assert_eq!( + UnresponsivenessOffence::<()>::slash_fraction(1, 50), + Perbill::zero(), + ); + + assert_eq!( + UnresponsivenessOffence::<()>::slash_fraction(5, 50), + Perbill::zero(), // 0% + ); + + assert_eq!( + UnresponsivenessOffence::<()>::slash_fraction(7, 50), + Perbill::from_parts(4200000), // 0.42% + ); + + // One third offline should be punished around 5%. + assert_eq!( + UnresponsivenessOffence::<()>::slash_fraction(17, 50), + Perbill::from_parts(46200000), // 4.62% + ); +} + +#[test] +fn should_report_offline_validators() { + new_test_ext().execute_with(|| { + // given + let block = 1; + System::set_block_number(block); + // buffer new validators + Session::rotate_session(); + // enact the change and buffer another one + let validators = vec![1, 2, 3, 4, 5, 6]; + VALIDATORS.with(|l| *l.borrow_mut() = Some(validators.clone())); + Session::rotate_session(); + + // when + // we end current session and start the next one + Session::rotate_session(); + + // then + let offences = OFFENCES.with(|l| l.replace(vec![])); + assert_eq!(offences, vec![ + (vec![], UnresponsivenessOffence { + session_index: 2, + validator_set_count: 3, + offenders: vec![ + (1, 1), + (2, 2), + (3, 3), + ], + }) + ]); + + // should not report when heartbeat is sent + for (idx, v) in validators.into_iter().take(4).enumerate() { + let _ = heartbeat(block, 3, idx as u32, v.into()).unwrap(); + } + Session::rotate_session(); + + // then + let offences = OFFENCES.with(|l| l.replace(vec![])); + assert_eq!(offences, vec![ + (vec![], UnresponsivenessOffence { + session_index: 3, + validator_set_count: 6, + offenders: vec![ + (5, 5), + (6, 6), + ], + }) + ]); + }); +} + +fn heartbeat( + block_number: u64, + session_index: u32, + authority_index: u32, + id: UintAuthorityId, +) -> dispatch::DispatchResult { + #[allow(deprecated)] + use frame_support::unsigned::ValidateUnsigned; + + let heartbeat = Heartbeat { + block_number, + network_state: OpaqueNetworkState { + peer_id: OpaquePeerId(vec![1]), + external_addresses: vec![], + }, + session_index, + authority_index, + }; + let signature = id.sign(&heartbeat.encode()).unwrap(); + + #[allow(deprecated)] // Allow ValidateUnsigned + ImOnline::pre_dispatch(&crate::Call::heartbeat(heartbeat.clone(), signature.clone())) + .map_err(|e| <&'static str>::from(e))?; + ImOnline::heartbeat( + Origin::system(frame_system::RawOrigin::None), + heartbeat, + signature + ) +} + +#[test] +fn should_mark_online_validator_when_heartbeat_is_received() { + new_test_ext().execute_with(|| { + advance_session(); + // given + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); + assert_eq!(Session::validators(), Vec::::new()); + // enact the change and buffer another one + advance_session(); + + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + + assert!(!ImOnline::is_online(0)); + assert!(!ImOnline::is_online(1)); + assert!(!ImOnline::is_online(2)); + + // when + let _ = heartbeat(1, 2, 0, 1.into()).unwrap(); + + // then + assert!(ImOnline::is_online(0)); + assert!(!ImOnline::is_online(1)); + assert!(!ImOnline::is_online(2)); + + // and when + let _ = heartbeat(1, 2, 2, 3.into()).unwrap(); + + // then + assert!(ImOnline::is_online(0)); + assert!(!ImOnline::is_online(1)); + assert!(ImOnline::is_online(2)); + }); +} + +#[test] +fn late_heartbeat_should_fail() { + new_test_ext().execute_with(|| { + advance_session(); + // given + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 4, 4, 5, 6])); + assert_eq!(Session::validators(), Vec::::new()); + // enact the change and buffer another one + advance_session(); + + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + + // when + assert_noop!(heartbeat(1, 3, 0, 1.into()), "Transaction is outdated"); + assert_noop!(heartbeat(1, 1, 0, 1.into()), "Transaction is outdated"); + }); +} + +#[test] +fn should_generate_heartbeats() { + let mut ext = new_test_ext(); + let (offchain, _state) = TestOffchainExt::new(); + let (pool, state) = TestTransactionPoolExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + ext.register_extension(TransactionPoolExt::new(pool)); + + ext.execute_with(|| { + // given + let block = 1; + System::set_block_number(block); + // buffer new validators + Session::rotate_session(); + // enact the change and buffer another one + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); + Session::rotate_session(); + + // when + UintAuthorityId::set_all_keys(vec![0, 1, 2]); + ImOnline::offchain(2); + + // then + let transaction = state.write().transactions.pop().unwrap(); + // All validators have `0` as their session key, so we generate 3 transactions. + assert_eq!(state.read().transactions.len(), 2); + // check stuff about the transaction. + let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); + let heartbeat = match ex.1 { + crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h, + e => panic!("Unexpected call: {:?}", e), + }; + + assert_eq!(heartbeat, Heartbeat { + block_number: 2, + network_state: sp_io::offchain::network_state().unwrap(), + session_index: 2, + authority_index: 2, + }); + }); +} + +#[test] +fn should_cleanup_received_heartbeats_on_session_end() { + new_test_ext().execute_with(|| { + advance_session(); + + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3])); + assert_eq!(Session::validators(), Vec::::new()); + + // enact the change and buffer another one + advance_session(); + + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + + // send an heartbeat from authority id 0 at session 2 + let _ = heartbeat(1, 2, 0, 1.into()).unwrap(); + + // the heartbeat is stored + assert!(!ImOnline::received_heartbeats(&2, &0).is_none()); + + advance_session(); + + // after the session has ended we have already processed the heartbeat + // message, so any messages received on the previous session should have + // been pruned. + assert!(ImOnline::received_heartbeats(&2, &0).is_none()); + }); +} + +#[test] +fn should_mark_online_validator_when_block_is_authored() { + use pallet_authorship::EventHandler; + + new_test_ext().execute_with(|| { + advance_session(); + // given + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); + assert_eq!(Session::validators(), Vec::::new()); + // enact the change and buffer another one + advance_session(); + + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + + for i in 0..3 { + assert!(!ImOnline::is_online(i)); + } + + // when + ImOnline::note_author(1); + ImOnline::note_uncle(2, 0); + + // then + assert!(ImOnline::is_online(0)); + assert!(ImOnline::is_online(1)); + assert!(!ImOnline::is_online(2)); + }); +} + +#[test] +fn should_not_send_a_report_if_already_online() { + use pallet_authorship::EventHandler; + + let mut ext = new_test_ext(); + let (offchain, _state) = TestOffchainExt::new(); + let (pool, pool_state) = TestTransactionPoolExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + ext.register_extension(TransactionPoolExt::new(pool)); + + ext.execute_with(|| { + advance_session(); + // given + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); + assert_eq!(Session::validators(), Vec::::new()); + // enact the change and buffer another one + advance_session(); + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + ImOnline::note_author(2); + ImOnline::note_uncle(3, 0); + + // when + UintAuthorityId::set_all_keys(vec![0]); // all authorities use pallet_session key 0 + ImOnline::offchain(4); + + // then + let transaction = pool_state.write().transactions.pop().unwrap(); + // All validators have `0` as their session key, but we should only produce 1 hearbeat. + assert_eq!(pool_state.read().transactions.len(), 0); + // check stuff about the transaction. + let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); + let heartbeat = match ex.1 { + crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h, + e => panic!("Unexpected call: {:?}", e), + }; + + assert_eq!(heartbeat, Heartbeat { + block_number: 4, + network_state: sp_io::offchain::network_state().unwrap(), + session_index: 2, + authority_index: 0, + }); + }); +} diff --git a/frame/indices/Cargo.toml b/frame/indices/Cargo.toml new file mode 100644 index 0000000000000..d05a7654d1240 --- /dev/null +++ b/frame/indices/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "pallet-indices" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-keyring = { version = "2.0.0", optional = true, path = "../../primitives/keyring" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[features] +default = ["std"] +std = [ + "serde", + "safe-mix/std", + "sp-keyring", + "codec/std", + "sp-core/std", + "sp-std/std", + "sp-io/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", +] diff --git a/srml/indices/src/address.rs b/frame/indices/src/address.rs similarity index 96% rename from srml/indices/src/address.rs rename to frame/indices/src/address.rs index 21ee654cf2e3f..f4487eeb693de 100644 --- a/srml/indices/src/address.rs +++ b/frame/indices/src/address.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,13 +18,13 @@ #[cfg(feature = "std")] use std::fmt; -use rstd::convert::TryInto; +use sp_std::convert::TryInto; use crate::Member; use codec::{Encode, Decode, Input, Output, Error}; /// An indices-aware address, which can be either a direct `AccountId` or /// an index. -#[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] #[cfg_attr(feature = "std", derive(Hash))] pub enum Address where AccountId: Member, diff --git a/frame/indices/src/lib.rs b/frame/indices/src/lib.rs new file mode 100644 index 0000000000000..8d7e37d5dfbe8 --- /dev/null +++ b/frame/indices/src/lib.rs @@ -0,0 +1,235 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! 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 sp_std::{prelude::*, marker::PhantomData, convert::TryInto}; +use codec::{Encode, Codec}; +use frame_support::{Parameter, decl_module, decl_event, decl_storage}; +use sp_runtime::traits::{One, SimpleArithmetic, StaticLookup, Member, LookupError}; +use frame_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: u32 = 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 implementation. +pub struct SimpleResolveHint(PhantomData<(AccountId, AccountIndex)>); +impl> + ResolveHint for SimpleResolveHint +{ + fn resolve_hint(who: &AccountId) -> Option { + Some(AccountIndex::from(who.using_encoded(|e| e[0] as u32 + e[1] as u32 * 256))) + } +} + +/// The module's config trait. +pub trait Trait: frame_system::Trait { + /// Type used for storing an account's index; implies the maximum number of accounts the system + /// can hold. + type AccountIndex: Parameter + Member + Codec + Default + SimpleArithmetic + 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, system = frame_system { + 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(fn next_enum_set) build(|config: &GenesisConfig| { + (config.ids.len() as u32 / ENUM_SET_SIZE).into() + }): T::AccountIndex; + + /// The enumeration sets. + pub EnumSet get(fn enum_set) build(|config: &GenesisConfig| { + (0..((config.ids.len() as u32) + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE) + .map(|i| ( + i.into(), + config.ids[ + (i * ENUM_SET_SIZE) as usize.. + config.ids.len().min(((i + 1) * ENUM_SET_SIZE) as usize) + ].to_owned(), + )) + .collect::>() + }): map T::AccountIndex => Vec; + } + add_extra_genesis { + config(ids): Vec; + } +} + +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).try_into().ok()?; + 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 maybe_usize: Result = (try_index % enum_set_size).try_into(); + if let Ok(i) = maybe_usize { + i < try_set.len() && T::IsDeadAccount::is_dead_account(&try_set[i]) + } else { + false + } + } + + /// 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 { + ENUM_SET_SIZE.into() + } +} + +impl OnNewAccount for Module { + // Implementation of the config type managing the creation of new accounts. + // See Balances module for a concrete example. + // + // # + // - Independent of the arguments. + // - Given the correct value of `Self::next_enum_set`, it always has a limited + // number of reads and writes and no complex computation. + // + // As for storage, calling this function with _non-dead-indices_ will linearly grow the length of + // of `Self::enum_set`. Appropriate economic incentives should exist to make callers of this + // function provide a `who` argument that reclaims a dead account. + // + // At the time of this writing, only the Balances module calls this function upon creation + // of new accounts. + // # + 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); + if let Ok(item_index) = (try_index % enum_set_size).try_into() { + 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 as usize { + break set; + } + set_index += One::one(); + }; + + let index = set_index * enum_set_size + T::AccountIndex::from(set.len() as u32); + + // update set. + set.push(who.clone()); + + // keep NextEnumSet up to date + if set.len() == ENUM_SET_SIZE as usize { + >::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 { + Self::lookup_address(a).ok_or(LookupError) + } + + fn unlookup(a: Self::Target) -> Self::Source { + address::Address::Id(a) + } +} diff --git a/frame/indices/src/mock.rs b/frame/indices/src/mock.rs new file mode 100644 index 0000000000000..b8c9b0a0adfd8 --- /dev/null +++ b/frame/indices/src/mock.rs @@ -0,0 +1,115 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use std::{cell::RefCell, collections::HashSet}; +use sp_runtime::testing::Header; +use sp_runtime::Perbill; +use sp_core::H256; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use crate::{GenesisConfig, Module, Trait, IsDeadAccount, OnNewAccount, ResolveHint}; + +impl_outer_origin!{ + pub enum Origin for Runtime where system = frame_system {} +} + +thread_local! { + static ALIVE: RefCell> = Default::default(); +} + +pub fn make_account(who: u64) { + ALIVE.with(|a| a.borrow_mut().insert(who)); + Indices::on_new_account(&who); +} + +pub fn kill_account(who: u64) { + ALIVE.with(|a| a.borrow_mut().remove(&who)); +} + +pub struct TestIsDeadAccount {} +impl IsDeadAccount for TestIsDeadAccount { + fn is_dead_account(who: &u64) -> bool { + !ALIVE.with(|a| a.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; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = Indices; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +impl Trait for Runtime { + type AccountIndex = u64; + type IsDeadAccount = TestIsDeadAccount; + type ResolveHint = TestResolveHint; + type Event = (); +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + { + ALIVE.with(|a| { + let mut h = a.borrow_mut(); + h.clear(); + for i in 1..5 { h.insert(i); } + }); + } + + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig:: { + ids: vec![1, 2, 3, 4] + }.assimilate_storage(&mut t).unwrap(); + t.into() +} + +pub type Indices = Module; diff --git a/frame/indices/src/tests.rs b/frame/indices/src/tests.rs new file mode 100644 index 0000000000000..95afcef734c54 --- /dev/null +++ b/frame/indices/src/tests.rs @@ -0,0 +1,67 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +#![cfg(test)] + +use super::*; +use crate::mock::{Indices, new_test_ext, make_account, kill_account, TestIsDeadAccount}; + +#[test] +fn indexing_lookup_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(Indices::lookup_index(0), Some(1)); + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(2), Some(3)); + assert_eq!(Indices::lookup_index(3), Some(4)); + assert_eq!(Indices::lookup_index(4), None); + }); +} + +#[test] +fn default_indexing_on_new_accounts_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(Indices::lookup_index(4), None); + make_account(5); + assert_eq!(Indices::lookup_index(4), Some(5)); + }); +} + +#[test] +fn reclaim_indexing_on_new_accounts_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(4), None); + + kill_account(2); // index 1 no longer locked to id 2 + + make_account(1 + 256); // id 257 takes index 1. + assert_eq!(Indices::lookup_index(1), Some(257)); + }); +} + +#[test] +fn alive_account_should_prevent_reclaim() { + new_test_ext().execute_with(|| { + assert!(!TestIsDeadAccount::is_dead_account(&2)); + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(4), None); + + make_account(1 + 256); // id 257 takes index 1. + assert_eq!(Indices::lookup_index(4), Some(257)); + }); +} diff --git a/frame/membership/Cargo.toml b/frame/membership/Cargo.toml new file mode 100644 index 0000000000000..cc45cfb94cb49 --- /dev/null +++ b/frame/membership/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "pallet-membership" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-runtime/std", + "sp-std/std", + "sp-io/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs new file mode 100644 index 0000000000000..3880b6cbb8fd0 --- /dev/null +++ b/frame/membership/src/lib.rs @@ -0,0 +1,411 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Membership Module +//! +//! Allows control of membership of a set of `AccountId`s, useful for managing membership of of a +//! collective. + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use frame_support::{ + decl_module, decl_storage, decl_event, decl_error, + traits::{ChangeMembers, InitializeMembers}, + weights::SimpleDispatchInfo, +}; +use frame_system::{self as system, ensure_root, ensure_signed}; +use sp_runtime::traits::EnsureOrigin; + +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// Required origin for adding a member (though can always be Root). + type AddOrigin: EnsureOrigin; + + /// Required origin for removing a member (though can always be Root). + type RemoveOrigin: EnsureOrigin; + + /// Required origin for adding and removing a member in a single action. + type SwapOrigin: EnsureOrigin; + + /// Required origin for resetting membership. + type ResetOrigin: EnsureOrigin; + + /// The receiver of the signal for when the membership has been initialized. This happens pre- + /// genesis and will usually be the same as `MembershipChanged`. If you need to do something + /// different on initialization, then you can change this accordingly. + type MembershipInitialized: InitializeMembers; + + /// The receiver of the signal for when the membership has changed. + type MembershipChanged: ChangeMembers; +} + +decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as Membership { + /// The current membership, stored as an ordered Vec. + Members get(fn members): Vec; + } + add_extra_genesis { + config(members): Vec; + config(phantom): sp_std::marker::PhantomData; + build(|config: &Self| { + let mut members = config.members.clone(); + members.sort(); + T::MembershipInitialized::initialize_members(&members); + >::put(members); + }) + } +} + +decl_event!( + pub enum Event where + ::AccountId, + >::Event, + { + /// The given member was added; see the transaction for who. + MemberAdded, + /// The given member was removed; see the transaction for who. + MemberRemoved, + /// Two members were swapped; see the transaction for who. + MembersSwapped, + /// The membership was reset; see the transaction for who the new set is. + MembersReset, + /// One of the members' keys changed. + KeyChanged, + /// Phantom member, never used. + Dummy(sp_std::marker::PhantomData<(AccountId, Event)>), + } +); + +decl_error! { + /// Error for the nicks module. + pub enum Error for Module, I: Instance> { + /// Already a member. + AlreadyMember, + /// Not a member. + NotMember, + } +} + +decl_module! { + pub struct Module, I: Instance=DefaultInstance> + for enum Call + where origin: T::Origin + { + fn deposit_event() = default; + + /// Add a member `who` to the set. + /// + /// May only be called from `AddOrigin` or root. + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn add_member(origin, who: T::AccountId) { + T::AddOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + let mut members = >::get(); + let location = members.binary_search(&who).err().ok_or(Error::::AlreadyMember)?; + members.insert(location, who.clone()); + >::put(&members); + + T::MembershipChanged::change_members_sorted(&[who], &[], &members[..]); + + Self::deposit_event(RawEvent::MemberAdded); + } + + /// Remove a member `who` from the set. + /// + /// May only be called from `RemoveOrigin` or root. + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn remove_member(origin, who: T::AccountId) { + T::RemoveOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + let mut members = >::get(); + let location = members.binary_search(&who).ok().ok_or(Error::::NotMember)?; + members.remove(location); + >::put(&members); + + T::MembershipChanged::change_members_sorted(&[], &[who], &members[..]); + + Self::deposit_event(RawEvent::MemberRemoved); + } + + /// Swap out one member `remove` for another `add`. + /// + /// May only be called from `SwapOrigin` or root. + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn swap_member(origin, remove: T::AccountId, add: T::AccountId) { + T::SwapOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + if remove == add { return Ok(()) } + + let mut members = >::get(); + let location = members.binary_search(&remove).ok().ok_or(Error::::NotMember)?; + let _ = members.binary_search(&add).err().ok_or(Error::::AlreadyMember)?; + members[location] = add.clone(); + members.sort(); + >::put(&members); + + T::MembershipChanged::change_members_sorted( + &[add], + &[remove], + &members[..], + ); + + Self::deposit_event(RawEvent::MembersSwapped); + } + + /// Change the membership to a new set, disregarding the existing membership. Be nice and + /// pass `members` pre-sorted. + /// + /// May only be called from `ResetOrigin` or root. + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn reset_members(origin, members: Vec) { + T::ResetOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + let mut members = members; + members.sort(); + >::mutate(|m| { + T::MembershipChanged::set_members_sorted(&members[..], m); + *m = members; + }); + + Self::deposit_event(RawEvent::MembersReset); + } + + /// Swap out the sending member for some other key `new`. + /// + /// May only be called from `Signed` origin of a current member. + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn change_key(origin, new: T::AccountId) { + let remove = ensure_signed(origin)?; + + if remove != new { + let mut members = >::get(); + let location = members.binary_search(&remove).ok().ok_or(Error::::NotMember)?; + let _ = members.binary_search(&new).err().ok_or(Error::::AlreadyMember)?; + members[location] = new.clone(); + members.sort(); + >::put(&members); + + T::MembershipChanged::change_members_sorted( + &[new], + &[remove], + &members[..], + ); + } + + Self::deposit_event(RawEvent::KeyChanged); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use std::cell::RefCell; + use frame_support::{ + assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight, + ord_parameter_types + }; + use sp_core::H256; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. + use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup, BadOrigin}, testing::Header}; + use frame_system::EnsureSignedBy; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + ord_parameter_types! { + pub const One: u64 = 1; + pub const Two: u64 = 2; + pub const Three: u64 = 3; + pub const Four: u64 = 4; + pub const Five: u64 = 5; + } + + thread_local! { + static MEMBERS: RefCell> = RefCell::new(vec![]); + } + + pub struct TestChangeMembers; + impl ChangeMembers for TestChangeMembers { + fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { + let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); + old_plus_incoming.extend_from_slice(incoming); + old_plus_incoming.sort(); + let mut new_plus_outgoing = new.to_vec(); + new_plus_outgoing.extend_from_slice(outgoing); + new_plus_outgoing.sort(); + assert_eq!(old_plus_incoming, new_plus_outgoing); + + MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); + } + } + impl InitializeMembers for TestChangeMembers { + fn initialize_members(members: &[u64]) { + MEMBERS.with(|m| *m.borrow_mut() = members.to_vec()); + } + } + + impl Trait for Test { + type Event = (); + type AddOrigin = EnsureSignedBy; + type RemoveOrigin = EnsureSignedBy; + type SwapOrigin = EnsureSignedBy; + type ResetOrigin = EnsureSignedBy; + type MembershipInitialized = TestChangeMembers; + type MembershipChanged = TestChangeMembers; + } + + type Membership = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + GenesisConfig::{ + members: vec![10, 20, 30], + .. Default::default() + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + #[test] + fn query_membership_works() { + new_test_ext().execute_with(|| { + assert_eq!(Membership::members(), vec![10, 20, 30]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), vec![10, 20, 30]); + }); + } + + #[test] + fn add_member_works() { + new_test_ext().execute_with(|| { + assert_noop!(Membership::add_member(Origin::signed(5), 15), BadOrigin); + assert_noop!(Membership::add_member(Origin::signed(1), 10), Error::::AlreadyMember); + assert_ok!(Membership::add_member(Origin::signed(1), 15)); + assert_eq!(Membership::members(), vec![10, 15, 20, 30]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); + }); + } + + #[test] + fn remove_member_works() { + new_test_ext().execute_with(|| { + assert_noop!(Membership::remove_member(Origin::signed(5), 20), BadOrigin); + assert_noop!(Membership::remove_member(Origin::signed(2), 15), Error::::NotMember); + assert_ok!(Membership::remove_member(Origin::signed(2), 20)); + assert_eq!(Membership::members(), vec![10, 30]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); + }); + } + + #[test] + fn swap_member_works() { + new_test_ext().execute_with(|| { + assert_noop!(Membership::swap_member(Origin::signed(5), 10, 25), BadOrigin); + assert_noop!(Membership::swap_member(Origin::signed(3), 15, 25), Error::::NotMember); + assert_noop!(Membership::swap_member(Origin::signed(3), 10, 30), Error::::AlreadyMember); + assert_ok!(Membership::swap_member(Origin::signed(3), 20, 20)); + assert_eq!(Membership::members(), vec![10, 20, 30]); + assert_ok!(Membership::swap_member(Origin::signed(3), 10, 25)); + assert_eq!(Membership::members(), vec![20, 25, 30]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); + }); + } + + #[test] + fn swap_member_works_that_does_not_change_order() { + new_test_ext().execute_with(|| { + assert_ok!(Membership::swap_member(Origin::signed(3), 10, 5)); + assert_eq!(Membership::members(), vec![5, 20, 30]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); + }); + } + + #[test] + fn change_key_works() { + new_test_ext().execute_with(|| { + assert_noop!(Membership::change_key(Origin::signed(3), 25), Error::::NotMember); + assert_noop!(Membership::change_key(Origin::signed(10), 20), Error::::AlreadyMember); + assert_ok!(Membership::change_key(Origin::signed(10), 40)); + assert_eq!(Membership::members(), vec![20, 30, 40]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); + }); + } + + #[test] + fn change_key_works_that_does_not_change_order() { + new_test_ext().execute_with(|| { + assert_ok!(Membership::change_key(Origin::signed(10), 5)); + assert_eq!(Membership::members(), vec![5, 20, 30]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); + }); + } + + #[test] + fn reset_members_works() { + new_test_ext().execute_with(|| { + assert_noop!(Membership::reset_members(Origin::signed(1), vec![20, 40, 30]), BadOrigin); + assert_ok!(Membership::reset_members(Origin::signed(4), vec![20, 40, 30])); + assert_eq!(Membership::members(), vec![20, 30, 40]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); + }); + } +} diff --git a/frame/metadata/Cargo.toml b/frame/metadata/Cargo.toml new file mode 100644 index 0000000000000..64cf326ff68dc --- /dev/null +++ b/frame/metadata/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "frame-metadata" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-std/std", + "sp-core/std", + "serde", +] diff --git a/frame/metadata/src/lib.rs b/frame/metadata/src/lib.rs new file mode 100644 index 0000000000000..f6e280bed1e79 --- /dev/null +++ b/frame/metadata/src/lib.rs @@ -0,0 +1,407 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Decodable variant of the RuntimeMetadata. +//! +//! This really doesn't belong here, but is necessary for the moment. In the future +//! it should be removed entirely to an external module for shimming on to the +//! codec-encoded metadata. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +use serde::Serialize; +#[cfg(feature = "std")] +use codec::{Decode, Input, Error}; +use codec::{Encode, Output}; +use sp_std::vec::Vec; +use sp_core::RuntimeDebug; + +#[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"))] +type StringBuf = &'static str; + +/// A type that decodes to a different type than it encodes. +/// The user needs to make sure that both types use the same encoding. +/// +/// For example a `&'static [ &'static str ]` can be decoded to a `Vec`. +#[derive(Clone)] +pub enum DecodeDifferent where B: 'static, O: 'static { + Encode(B), + Decoded(O), +} + +impl Encode for DecodeDifferent where B: Encode + 'static, O: Encode + 'static { + fn encode_to(&self, dest: &mut W) { + match self { + DecodeDifferent::Encode(b) => b.encode_to(dest), + DecodeDifferent::Decoded(o) => o.encode_to(dest), + } + } +} + +impl codec::EncodeLike for DecodeDifferent where B: Encode + 'static, O: Encode + 'static {} + +#[cfg(feature = "std")] +impl Decode for DecodeDifferent where B: 'static, O: Decode + 'static { + fn decode(input: &mut I) -> Result { + ::decode(input).map(|val| { + DecodeDifferent::Decoded(val) + }) + } +} + +impl PartialEq for DecodeDifferent +where + B: Encode + Eq + PartialEq + 'static, + O: Encode + Eq + PartialEq + 'static, +{ + fn eq(&self, other: &Self) -> bool { + self.encode() == other.encode() + } +} + +impl Eq for DecodeDifferent + where B: Encode + Eq + PartialEq + 'static, O: Encode + Eq + PartialEq + 'static +{} + +impl sp_std::fmt::Debug for DecodeDifferent + where + B: sp_std::fmt::Debug + Eq + 'static, + O: sp_std::fmt::Debug + Eq + 'static, +{ + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + match self { + DecodeDifferent::Encode(b) => b.fmt(f), + DecodeDifferent::Decoded(o) => o.fmt(f), + } + } +} + +#[cfg(feature = "std")] +impl serde::Serialize for DecodeDifferent + where + B: serde::Serialize + 'static, + O: serde::Serialize + 'static, +{ + fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { + match self { + DecodeDifferent::Encode(b) => b.serialize(serializer), + DecodeDifferent::Decoded(o) => o.serialize(serializer), + } + } +} + +pub type DecodeDifferentArray = DecodeDifferent<&'static [B], Vec>; + +type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; + +/// All the metadata about a function. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct FunctionMetadata { + pub name: DecodeDifferentStr, + pub arguments: DecodeDifferentArray, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// All the metadata about a function argument. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct FunctionArgumentMetadata { + pub name: DecodeDifferentStr, + pub ty: DecodeDifferentStr, +} + +/// Newtype wrapper for support encoding functions (actual the result of the function). +#[derive(Clone, Eq)] +pub struct FnEncode(pub fn() -> E) where E: Encode + 'static; + +impl Encode for FnEncode { + fn encode_to(&self, dest: &mut W) { + self.0().encode_to(dest); + } +} + +impl codec::EncodeLike for FnEncode {} + +impl PartialEq for FnEncode { + fn eq(&self, other: &Self) -> bool { + self.0().eq(&other.0()) + } +} + +impl sp_std::fmt::Debug for FnEncode { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + self.0().fmt(f) + } +} + +#[cfg(feature = "std")] +impl serde::Serialize for FnEncode { + fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { + self.0().serialize(serializer) + } +} + +/// All the metadata about an outer event. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct OuterEventMetadata { + pub name: DecodeDifferentStr, + pub events: DecodeDifferentArray< + (&'static str, FnEncode<&'static [EventMetadata]>), + (StringBuf, Vec) + >, +} + +/// All the metadata about an event. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct EventMetadata { + pub name: DecodeDifferentStr, + pub arguments: DecodeDifferentArray<&'static str, StringBuf>, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// All the metadata about one storage entry. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct StorageEntryMetadata { + pub name: DecodeDifferentStr, + pub modifier: StorageEntryModifier, + pub ty: StorageEntryType, + pub default: ByteGetter, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// All the metadata about one module constant. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct ModuleConstantMetadata { + pub name: DecodeDifferentStr, + pub ty: DecodeDifferentStr, + pub value: ByteGetter, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// All the metadata about a module error. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct ErrorMetadata { + pub name: DecodeDifferentStr, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// All the metadata about errors in a module. +pub trait ModuleErrorMetadata { + fn metadata() -> &'static [ErrorMetadata]; +} + +impl ModuleErrorMetadata for &'static str { + fn metadata() -> &'static [ErrorMetadata] { + &[] + } +} + +/// A technical trait to store lazy initiated vec value as static dyn pointer. +pub trait DefaultByte: Send + Sync { + fn default_byte(&self) -> Vec; +} + +/// 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 codec::EncodeLike for DefaultByteGetter {} + +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) + } +} + +impl sp_std::fmt::Debug for DefaultByteGetter { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + self.0.default_byte().fmt(f) + } +} + +/// Hasher used by storage maps +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub enum StorageHasher { + Blake2_128, + Blake2_256, + Blake2_128Concat, + Twox128, + Twox256, + Twox64Concat, +} + +/// A storage entry type. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub enum StorageEntryType { + Plain(DecodeDifferentStr), + Map { + hasher: StorageHasher, + key: DecodeDifferentStr, + value: DecodeDifferentStr, + is_linked: bool, + }, + DoubleMap { + hasher: StorageHasher, + key1: DecodeDifferentStr, + key2: DecodeDifferentStr, + value: DecodeDifferentStr, + key2_hasher: StorageHasher, + }, +} + +/// A storage entry modifier. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub enum StorageEntryModifier { + Optional, + Default, +} + +/// All metadata of the storage. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct StorageMetadata { + /// The common prefix used by all storage entries. + pub prefix: DecodeDifferent<&'static str, StringBuf>, + pub entries: DecodeDifferent<&'static [StorageEntryMetadata], Vec>, +} + +#[derive(Eq, Encode, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +/// Metadata prefixed by a u32 for reserved usage +pub struct RuntimeMetadataPrefixed(pub u32, pub RuntimeMetadata); + +/// The metadata of a runtime. +/// The version ID encoded/decoded through +/// the enum nature of `RuntimeMetadata`. +#[derive(Eq, Encode, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub enum RuntimeMetadata { + /// Unused; enum filler. + V0(RuntimeMetadataDeprecated), + /// Version 1 for runtime metadata. No longer used. + V1(RuntimeMetadataDeprecated), + /// Version 2 for runtime metadata. No longer used. + V2(RuntimeMetadataDeprecated), + /// Version 3 for runtime metadata. No longer used. + V3(RuntimeMetadataDeprecated), + /// Version 4 for runtime metadata. No longer used. + V4(RuntimeMetadataDeprecated), + /// Version 5 for runtime metadata. No longer used. + V5(RuntimeMetadataDeprecated), + /// Version 6 for runtime metadata. No longer used. + V6(RuntimeMetadataDeprecated), + /// Version 7 for runtime metadata. No longer used. + V7(RuntimeMetadataDeprecated), + /// Version 8 for runtime metadata. No longer used. + V8(RuntimeMetadataDeprecated), + /// Version 9 for runtime metadata. No longer used. + V9(RuntimeMetadataDeprecated), + /// Version 10 for runtime metadata. + V10(RuntimeMetadataV10), +} + +/// Enum that should fail. +#[derive(Eq, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize))] +pub enum RuntimeMetadataDeprecated { } + +impl Encode for RuntimeMetadataDeprecated { + fn encode_to(&self, _dest: &mut W) {} +} + +impl codec::EncodeLike for RuntimeMetadataDeprecated {} + +#[cfg(feature = "std")] +impl Decode for RuntimeMetadataDeprecated { + fn decode(_input: &mut I) -> Result { + Err("Decoding is not supported".into()) + } +} + +/// The metadata of a runtime. +#[derive(Eq, Encode, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct RuntimeMetadataV10 { + pub modules: DecodeDifferentArray, +} + +/// The latest version of the metadata. +pub type RuntimeMetadataLastVersion = RuntimeMetadataV10; + +/// All metadata about an runtime module. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct ModuleMetadata { + pub name: DecodeDifferentStr, + pub storage: Option, StorageMetadata>>, + pub calls: ODFnA, + pub event: ODFnA, + pub constants: DFnA, + pub errors: DFnA, +} + +type ODFnA = Option>; +type DFnA = DecodeDifferent, Vec>; + +impl Into for RuntimeMetadataPrefixed { + fn into(self) -> sp_core::OpaqueMetadata { + sp_core::OpaqueMetadata::new(self.encode()) + } +} + +impl Into for RuntimeMetadataLastVersion { + fn into(self) -> RuntimeMetadataPrefixed { + RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V10(self)) + } +} diff --git a/frame/nicks/Cargo.toml b/frame/nicks/Cargo.toml new file mode 100644 index 0000000000000..0dce684f0df21 --- /dev/null +++ b/frame/nicks/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "pallet-nicks" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "sp-io/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs new file mode 100644 index 0000000000000..de39736a5a042 --- /dev/null +++ b/frame/nicks/src/lib.rs @@ -0,0 +1,408 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Nicks Module +//! +//! - [`nicks::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! Nicks is a trivial module for keeping track of account names on-chain. It makes no effort to +//! create a name hierarchy, be a DNS replacement or provide reverse lookups. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! * `set_name` - Set the associated name of an account; a small deposit is reserved if not already +//! taken. +//! * `clear_name` - Remove an account's associated name; the deposit is returned. +//! * `kill_name` - Forcibly remove the associated name; the deposit is lost. +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use sp_runtime::{ + traits::{StaticLookup, EnsureOrigin, Zero} +}; +use frame_support::{ + decl_module, decl_event, decl_storage, ensure, decl_error, + traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, + weights::SimpleDispatchInfo, +}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The currency trait. + type Currency: ReservableCurrency; + + /// Reservation fee. + type ReservationFee: Get>; + + /// What to do with slashed funds. + type Slashed: OnUnbalanced>; + + /// The origin which may forcibly set or remove a name. Root can always do this. + type ForceOrigin: EnsureOrigin; + + /// The minimum length a name may be. + type MinLength: Get; + + /// The maximum length a name may be. + type MaxLength: Get; +} + +decl_storage! { + trait Store for Module as Sudo { + /// The lookup table for names. + NameOf: map T::AccountId => Option<(Vec, BalanceOf)>; + } +} + +decl_event!( + pub enum Event where AccountId = ::AccountId, Balance = BalanceOf { + /// A name was set. + NameSet(AccountId), + /// A name was forcibly set. + NameForced(AccountId), + /// A name was changed. + NameChanged(AccountId), + /// A name was cleared, and the given balance returned. + NameCleared(AccountId, Balance), + /// A name was removed and the given balance slashed. + NameKilled(AccountId, Balance), + } +); + +decl_error! { + /// Error for the nicks module. + pub enum Error for Module { + /// A name is too short. + TooShort, + /// A name is too long. + TooLong, + /// An account in't named. + Unnamed, + } +} + +decl_module! { + // Simple declaration of the `Module` type. Lets the macro know what it's working on. + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + /// Reservation fee. + const ReservationFee: BalanceOf = T::ReservationFee::get(); + + /// The minimum length a name may be. + const MinLength: u32 = T::MinLength::get() as u32; + + /// The maximum length a name may be. + const MaxLength: u32 = T::MaxLength::get() as u32; + + /// Set an account's name. The name should be a UTF-8-encoded string by convention, though + /// we don't check it. + /// + /// The name may not be more than `T::MaxLength` bytes, nor less than `T::MinLength` bytes. + /// + /// If the account doesn't already have a name, then a fee of `ReservationFee` is reserved + /// in the account. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - At most one balance operation. + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn set_name(origin, name: Vec) { + let sender = ensure_signed(origin)?; + + ensure!(name.len() >= T::MinLength::get(), Error::::TooShort,); + ensure!(name.len() <= T::MaxLength::get(), Error::::TooLong); + + let deposit = if let Some((_, deposit)) = >::get(&sender) { + Self::deposit_event(RawEvent::NameSet(sender.clone())); + deposit + } else { + let deposit = T::ReservationFee::get(); + T::Currency::reserve(&sender, deposit.clone())?; + Self::deposit_event(RawEvent::NameChanged(sender.clone())); + deposit + }; + + >::insert(&sender, (name, deposit)); + } + + /// Clear an account's name and return the deposit. Fails if the account was not named. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - One balance operation. + /// - One storage read/write. + /// - One event. + /// # + fn clear_name(origin) { + let sender = ensure_signed(origin)?; + + let deposit = >::take(&sender).ok_or(Error::::Unnamed)?.1; + + let _ = T::Currency::unreserve(&sender, deposit.clone()); + + Self::deposit_event(RawEvent::NameCleared(sender, deposit)); + } + + /// Remove an account's name and take charge of the deposit. + /// + /// Fails if `who` has not been named. The deposit is dealt with through `T::Slashed` + /// imbalance handler. + /// + /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// + /// # + /// - O(1). + /// - One unbalanced handler (probably a balance transfer) + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn kill_name(origin, target: ::Source) { + T::ForceOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + // Figure out who we're meant to be clearing. + let target = T::Lookup::lookup(target)?; + // Grab their deposit (and check that they have one). + let deposit = >::take(&target).ok_or(Error::::Unnamed)?.1; + // Slash their deposit from them. + T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit.clone()).0); + + Self::deposit_event(RawEvent::NameKilled(target, deposit)); + } + + /// Set a third-party account's name with no deposit. + /// + /// No length checking is done on the name. + /// + /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// + /// # + /// - O(1). + /// - At most one balance operation. + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_name(origin, target: ::Source, name: Vec) { + T::ForceOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + let target = T::Lookup::lookup(target)?; + let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); + >::insert(&target, (name, deposit)); + + Self::deposit_event(RawEvent::NameForced(target)); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use frame_support::{ + assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight, + ord_parameter_types + }; + use sp_core::H256; + use frame_system::EnsureSignedBy; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. + use sp_runtime::{ + Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup, BadOrigin}, + }; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + parameter_types! { + pub const ReservationFee: u64 = 2; + pub const MinLength: usize = 3; + pub const MaxLength: usize = 16; + } + ord_parameter_types! { + pub const One: u64 = 1; + } + impl Trait for Test { + type Event = (); + type Currency = Balances; + type ReservationFee = ReservationFee; + type Slashed = (); + type ForceOrigin = EnsureSignedBy; + type MinLength = MinLength; + type MaxLength = MaxLength; + } + type System = frame_system::Module; + type Balances = pallet_balances::Module; + type Nicks = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + pallet_balances::GenesisConfig:: { + balances: vec![ + (1, 10), + (2, 10), + ], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + #[test] + fn kill_name_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); + assert_eq!(Balances::total_balance(&2), 10); + assert_ok!(Nicks::kill_name(Origin::signed(1), 2)); + assert_eq!(Balances::total_balance(&2), 8); + assert_eq!(>::get(2), None); + }); + } + + #[test] + fn force_name_should_work() { + new_test_ext().execute_with(|| { + assert_noop!( + Nicks::set_name(Origin::signed(2), b"Dr. David Brubeck, III".to_vec()), + Error::::TooLong, + ); + + assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); + assert_eq!(Balances::reserved_balance(&2), 2); + assert_ok!(Nicks::force_name(Origin::signed(1), 2, b"Dr. David Brubeck, III".to_vec())); + assert_eq!(Balances::reserved_balance(&2), 2); + assert_eq!(>::get(2).unwrap(), (b"Dr. David Brubeck, III".to_vec(), 2)); + }); + } + + #[test] + fn normal_operation_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Nicks::set_name(Origin::signed(1), b"Gav".to_vec())); + assert_eq!(Balances::reserved_balance(&1), 2); + assert_eq!(Balances::free_balance(&1), 8); + assert_eq!(>::get(1).unwrap().0, b"Gav".to_vec()); + + assert_ok!(Nicks::set_name(Origin::signed(1), b"Gavin".to_vec())); + assert_eq!(Balances::reserved_balance(&1), 2); + assert_eq!(Balances::free_balance(&1), 8); + assert_eq!(>::get(1).unwrap().0, b"Gavin".to_vec()); + + assert_ok!(Nicks::clear_name(Origin::signed(1))); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 10); + }); + } + + #[test] + fn error_catching_should_work() { + new_test_ext().execute_with(|| { + assert_noop!(Nicks::clear_name(Origin::signed(1)), Error::::Unnamed); + + assert_noop!( + Nicks::set_name(Origin::signed(3), b"Dave".to_vec()), + pallet_balances::Error::::InsufficientBalance + ); + + assert_noop!(Nicks::set_name(Origin::signed(1), b"Ga".to_vec()), Error::::TooShort); + assert_noop!( + Nicks::set_name(Origin::signed(1), b"Gavin James Wood, Esquire".to_vec()), + Error::::TooLong + ); + assert_ok!(Nicks::set_name(Origin::signed(1), b"Dave".to_vec())); + assert_noop!(Nicks::kill_name(Origin::signed(2), 1), BadOrigin); + assert_noop!(Nicks::force_name(Origin::signed(2), 1, b"Whatever".to_vec()), BadOrigin); + }); + } +} diff --git a/frame/offences/Cargo.toml b/frame/offences/Cargo.toml new file mode 100644 index 0000000000000..36d057f4e9fd9 --- /dev/null +++ b/frame/offences/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "pallet-offences" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +serde = { version = "1.0.101", optional = true } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-io = { version = "2.0.0", path = "../../primitives/io" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } + +[features] +default = ["std"] +std = [ + "pallet-balances/std", + "codec/std", + "sp-std/std", + "serde", + "sp-runtime/std", + "sp-staking/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs new file mode 100644 index 0000000000000..310c018d76134 --- /dev/null +++ b/frame/offences/src/lib.rs @@ -0,0 +1,246 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Offences Module +//! +//! Tracks reported offences + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +mod mock; +mod tests; + +use sp_std::vec::Vec; +use frame_support::{ + decl_module, decl_event, decl_storage, Parameter, +}; +use sp_runtime::traits::Hash; +use sp_staking::{ + offence::{Offence, ReportOffence, Kind, OnOffenceHandler, OffenceDetails}, +}; +use codec::{Encode, Decode}; +use frame_system as system; + +/// A binary blob which represents a SCALE codec-encoded `O::TimeSlot`. +type OpaqueTimeSlot = Vec; + +/// A type alias for a report identifier. +type ReportIdOf = ::Hash; + +/// Offences trait +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From + Into<::Event>; + /// Full identification of the validator. + type IdentificationTuple: Parameter + Ord; + /// A handler called for every offence report. + type OnOffenceHandler: OnOffenceHandler; +} + +decl_storage! { + trait Store for Module as Offences { + /// The primary structure that holds all offence records keyed by report identifiers. + Reports get(fn reports): map ReportIdOf => Option>; + + /// A vector of reports of the same kind that happened at the same time slot. + ConcurrentReportsIndex: double_map Kind, OpaqueTimeSlot => Vec>; + + /// Enumerates all reports of a kind along with the time they happened. + /// + /// All reports are sorted by the time of offence. + /// + /// Note that the actual type of this mapping is `Vec`, this is because values of + /// different types are not supported at the moment so we are doing the manual serialization. + ReportsByKindIndex: map Kind => Vec; // (O::TimeSlot, ReportIdOf) + } +} + +decl_event!( + pub enum Event { + /// There is an offence reported of the given `kind` happened at the `session_index` and + /// (kind-specific) time slot. This event is not deposited for duplicate slashes. + Offence(Kind, OpaqueTimeSlot), + } +); + +decl_module! { + /// Offences module, currently just responsible for taking offence reports. + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + } +} +impl> + ReportOffence for Module +where + T::IdentificationTuple: Clone, +{ + fn report_offence(reporters: Vec, offence: O) { + let offenders = offence.offenders(); + let time_slot = offence.time_slot(); + let validator_set_count = offence.validator_set_count(); + + // Go through all offenders in the offence report and find all offenders that was spotted + // in unique reports. + let TriageOutcome { concurrent_offenders } = match Self::triage_offence_report::( + reporters, + &time_slot, + offenders, + ) { + Some(triage) => triage, + // The report contained only duplicates, so there is no need to slash again. + None => return, + }; + + // Deposit the event. + Self::deposit_event(Event::Offence(O::ID, time_slot.encode())); + + let offenders_count = concurrent_offenders.len() as u32; + + // The amount new offenders are slashed + let new_fraction = O::slash_fraction(offenders_count, validator_set_count); + + let slash_perbill: Vec<_> = (0..concurrent_offenders.len()) + .map(|_| new_fraction.clone()).collect(); + + T::OnOffenceHandler::on_offence( + &concurrent_offenders, + &slash_perbill, + offence.session_index(), + ); + } +} + +impl Module { + /// Compute the ID for the given report properties. + /// + /// The report id depends on the offence kind, time slot and the id of offender. + fn report_id>( + time_slot: &O::TimeSlot, + offender: &T::IdentificationTuple, + ) -> ReportIdOf { + (O::ID, time_slot.encode(), offender).using_encoded(T::Hashing::hash) + } + + /// Triages the offence report and returns the set of offenders that was involved in unique + /// reports along with the list of the concurrent offences. + fn triage_offence_report>( + reporters: Vec, + time_slot: &O::TimeSlot, + offenders: Vec, + ) -> Option> { + let mut storage = ReportIndexStorage::::load(time_slot); + + let mut any_new = false; + for offender in offenders { + let report_id = Self::report_id::(time_slot, &offender); + + if !>::exists(&report_id) { + any_new = true; + >::insert( + &report_id, + OffenceDetails { + offender, + reporters: reporters.clone(), + }, + ); + + storage.insert(time_slot, report_id); + } + } + + if any_new { + // Load report details for the all reports happened at the same time. + let concurrent_offenders = storage.concurrent_reports + .iter() + .filter_map(|report_id| >::get(report_id)) + .collect::>(); + + storage.save(); + + Some(TriageOutcome { + concurrent_offenders, + }) + } else { + None + } + } +} + +struct TriageOutcome { + /// Other reports for the same report kinds. + concurrent_offenders: Vec>, +} + +/// An auxilary struct for working with storage of indexes localized for a specific offence +/// kind (specified by the `O` type parameter). +/// +/// This struct is responsible for aggregating storage writes and the underlying storage should not +/// accessed directly meanwhile. +#[must_use = "The changes are not saved without called `save`"] +struct ReportIndexStorage> { + opaque_time_slot: OpaqueTimeSlot, + concurrent_reports: Vec>, + same_kind_reports: Vec<(O::TimeSlot, ReportIdOf)>, +} + +impl> ReportIndexStorage { + /// Preload indexes from the storage for the specific `time_slot` and the kind of the offence. + fn load(time_slot: &O::TimeSlot) -> Self { + let opaque_time_slot = time_slot.encode(); + + let same_kind_reports = ::get(&O::ID); + let same_kind_reports = + Vec::<(O::TimeSlot, ReportIdOf)>::decode(&mut &same_kind_reports[..]) + .unwrap_or_default(); + + let concurrent_reports = >::get(&O::ID, &opaque_time_slot); + + Self { + opaque_time_slot, + concurrent_reports, + same_kind_reports, + } + } + + /// Insert a new report to the index. + fn insert(&mut self, time_slot: &O::TimeSlot, report_id: ReportIdOf) { + // Insert the report id into the list while maintaining the ordering by the time + // slot. + let pos = match self + .same_kind_reports + .binary_search_by_key(&time_slot, |&(ref when, _)| when) + { + Ok(pos) => pos, + Err(pos) => pos, + }; + self.same_kind_reports + .insert(pos, (time_slot.clone(), report_id)); + + // Update the list of concurrent reports. + self.concurrent_reports.push(report_id); + } + + /// Dump the indexes to the storage. + fn save(self) { + ::insert(&O::ID, self.same_kind_reports.encode()); + >::insert( + &O::ID, + &self.opaque_time_slot, + &self.concurrent_reports, + ); + } +} diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs new file mode 100644 index 0000000000000..f344206f5ccdd --- /dev/null +++ b/frame/offences/src/mock.rs @@ -0,0 +1,165 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use std::cell::RefCell; +use crate::{Module, Trait}; +use codec::Encode; +use sp_runtime::Perbill; +use sp_staking::{ + SessionIndex, + offence::{self, Kind, OffenceDetails}, +}; +use sp_runtime::testing::Header; +use sp_runtime::traits::{IdentityLookup, BlakeTwo256}; +use sp_core::H256; +use frame_support::{ + impl_outer_origin, impl_outer_event, parameter_types, StorageMap, StorageDoubleMap, + weights::Weight, +}; +use frame_system as system; + +impl_outer_origin!{ + pub enum Origin for Runtime {} +} + +pub struct OnOffenceHandler; + +thread_local! { + pub static ON_OFFENCE_PERBILL: RefCell> = RefCell::new(Default::default()); +} + +impl offence::OnOffenceHandler for OnOffenceHandler { + fn on_offence( + _offenders: &[OffenceDetails], + slash_fraction: &[Perbill], + _offence_session: SessionIndex, + ) { + ON_OFFENCE_PERBILL.with(|f| { + *f.borrow_mut() = slash_fraction.to_vec(); + }); + } +} + +pub fn with_on_offence_fractions) -> R>(f: F) -> R { + ON_OFFENCE_PERBILL.with(|fractions| { + f(&mut *fractions.borrow_mut()) + }) +} + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Runtime; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +impl Trait for Runtime { + type Event = TestEvent; + type IdentificationTuple = u64; + type OnOffenceHandler = OnOffenceHandler; +} + +mod offences { + pub use crate::Event; +} + +impl_outer_event! { + pub enum TestEvent for Runtime { + offences, + } +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + t.into() +} + +/// Offences module. +pub type Offences = Module; +pub type System = frame_system::Module; + +pub const KIND: [u8; 16] = *b"test_report_1234"; + +/// Returns all offence details for the specific `kind` happened at the specific time slot. +pub fn offence_reports(kind: Kind, time_slot: u128) -> Vec> { + >::get(&kind, &time_slot.encode()) + .into_iter() + .map(|report_id| { + >::get(&report_id) + .expect("dangling report id is found in ConcurrentReportsIndex") + }) + .collect() +} + +#[derive(Clone)] +pub struct Offence { + pub validator_set_count: u32, + pub offenders: Vec, + pub time_slot: u128, +} + +impl offence::Offence for Offence { + const ID: offence::Kind = KIND; + type TimeSlot = u128; + + fn offenders(&self) -> Vec { + self.offenders.clone() + } + + fn validator_set_count(&self) -> u32 { + self.validator_set_count + } + + fn time_slot(&self) -> u128 { + self.time_slot + } + + fn session_index(&self) -> SessionIndex { + 1 + } + + fn slash_fraction( + offenders_count: u32, + validator_set_count: u32, + ) -> Perbill { + Perbill::from_percent(5 + offenders_count * 100 / validator_set_count) + } +} diff --git a/frame/offences/src/tests.rs b/frame/offences/src/tests.rs new file mode 100644 index 0000000000000..703361f77f9a1 --- /dev/null +++ b/frame/offences/src/tests.rs @@ -0,0 +1,214 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the offences module. + +#![cfg(test)] + +use super::*; +use crate::mock::{ + Offences, System, Offence, TestEvent, KIND, new_test_ext, with_on_offence_fractions, + offence_reports, +}; +use sp_runtime::Perbill; +use frame_system::{EventRecord, Phase}; + +#[test] +fn should_report_an_authority_and_trigger_on_offence() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + + // when + Offences::report_offence(vec![], offence); + + // then + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + }); + }); +} + +#[test] +fn should_not_report_the_same_authority_twice_in_the_same_slot() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence.clone()); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + f.clear(); + }); + + // when + // report for the second time + Offences::report_offence(vec![], offence); + + // then + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![]); + }); + }); +} + + +#[test] +fn should_report_in_different_time_slot() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let mut offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence.clone()); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + f.clear(); + }); + + // when + // reportfor the second time + offence.time_slot += 1; + Offences::report_offence(vec![], offence); + + // then + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + }); + }); +} + +#[test] +fn should_deposit_event() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + + // when + Offences::report_offence(vec![], offence); + + // then + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: TestEvent::offences(crate::Event::Offence(KIND, time_slot.encode())), + topics: vec![], + }] + ); + }); +} + +#[test] +fn doesnt_deposit_event_for_dups() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence.clone()); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + f.clear(); + }); + + // when + // report for the second time + Offences::report_offence(vec![], offence); + + // then + // there is only one event. + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: TestEvent::offences(crate::Event::Offence(KIND, time_slot.encode())), + topics: vec![], + }] + ); + }); +} + +#[test] +fn should_properly_count_offences() { + // We report two different authorities for the same issue. Ultimately, the 1st authority + // should have `count` equal 2 and the count of the 2nd one should be equal to 1. + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence1 = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + let offence2 = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![4], + }; + Offences::report_offence(vec![], offence1); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + f.clear(); + }); + + // when + // report for the second time + Offences::report_offence(vec![], offence2); + + // then + // the 1st authority should have count 2 and the 2nd one should be reported only once. + assert_eq!( + offence_reports(KIND, time_slot), + vec![ + OffenceDetails { offender: 5, reporters: vec![] }, + OffenceDetails { offender: 4, reporters: vec![] }, + ] + ); + }); +} diff --git a/frame/randomness-collective-flip/Cargo.toml b/frame/randomness-collective-flip/Cargo.toml new file mode 100644 index 0000000000000..9e25ba4c57082 --- /dev/null +++ b/frame/randomness-collective-flip/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "pallet-randomness-collective-flip" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +safe-mix = { version = "1.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-io = { version = "2.0.0", path = "../../primitives/io" } + +[features] +default = ["std"] +std = [ + "safe-mix/std", + "frame-system/std", + "codec/std", + "frame-support/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs new file mode 100644 index 0000000000000..c7f7bb0db78b8 --- /dev/null +++ b/frame/randomness-collective-flip/src/lib.rs @@ -0,0 +1,287 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Randomness Module +//! +//! The Randomness Collective Flip module provides a [`random`](./struct.Module.html#method.random) +//! function that generates low-influence random values based on the block hashes from the previous +//! `81` blocks. Low-influence randomness can be useful when defending against relatively weak +//! adversaries. +//! +//! ## Public Functions +//! +//! See the [`Module`](./struct.Module.html) struct for details of publicly available functions. +//! +//! ## Usage +//! +//! ### Prerequisites +//! +//! Import the Randomness Collective Flip module and derive your module's configuration trait from +//! the system trait. +//! +//! ### Example - Get random seed for the current block +//! +//! ``` +//! use frame_support::{decl_module, dispatch, traits::Randomness}; +//! +//! pub trait Trait: frame_system::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn random_module_example(origin) -> dispatch::DispatchResult { +//! let _random_seed = >::random_seed(); +//! Ok(()) +//! } +//! } +//! } +//! # fn main() { } +//! ``` + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{prelude::*, convert::TryInto}; +use sp_runtime::traits::Hash; +use frame_support::{decl_module, decl_storage, traits::Randomness}; +use safe_mix::TripletMix; +use codec::Encode; +use frame_system::Trait; + +const RANDOM_MATERIAL_LEN: u32 = 81; + +fn block_number_to_index(block_number: T::BlockNumber) -> usize { + // on_initialize is called on the first block after genesis + let index = (block_number - 1.into()) % RANDOM_MATERIAL_LEN.into(); + index.try_into().ok().expect("Something % 81 is always smaller than usize; qed") +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn on_initialize(block_number: T::BlockNumber) { + let parent_hash = >::parent_hash(); + + >::mutate(|ref mut values| if values.len() < RANDOM_MATERIAL_LEN as usize { + values.push(parent_hash) + } else { + let index = block_number_to_index::(block_number); + values[index] = parent_hash; + }); + } + } +} + +decl_storage! { + trait Store for Module as RandomnessCollectiveFlip { + /// Series of block headers from the last 81 blocks that acts as random seed material. This + /// is arranged as a ring buffer with `block_number % 81` being the index into the `Vec` of + /// the oldest hash. + RandomMaterial get(fn random_material): Vec; + } +} + +impl Randomness for Module { + /// Get a low-influence "random" value. + /// + /// Being a deterministic block chain, real randomness is difficult to come by. This gives you + /// something that approximates it. `subject` is a context identifier and allows you to get a + /// different result to other callers of this function; use it like + /// `random(&b"my context"[..])`. This is initially implemented through a low-influence + /// "triplet mix" convolution of previous block hash values. In the future it will be generated + /// from a secure verifiable random function (VRF). + /// + /// ### Security Notes + /// + /// This randomness uses a low-influence function, drawing upon the block hashes from the + /// previous 81 blocks. Its result for any given subject will be known far in advance by anyone + /// observing the chain. Any block producer has significant influence over their block hashes + /// bounded only by their computational resources. Our low-influence function reduces the actual + /// block producer's influence over the randomness, but increases the influence of small + /// colluding groups of recent block producers. + /// + /// Some BABE blocks have VRF outputs where the block producer has exactly one bit of influence, + /// either they make the block or they do not make the block and thus someone else makes the + /// next block. Yet, this randomness is not fresh in all BABE blocks. + /// + /// If that is an insufficient security guarantee then two things can be used to improve this + /// randomness: + /// + /// - Name, in advance, the block number whose random value will be used; ensure your module + /// retains a buffer of previous random values for its subject and then index into these in + /// order to obviate the ability of your user to look up the parent hash and choose when to + /// transact based upon it. + /// - Require your user to first commit to an additional value by first posting its hash. + /// Require them to reveal the value to determine the final result, hashing it with the + /// output of this random function. This reduces the ability of a cabal of block producers + /// from conspiring against individuals. + /// + /// WARNING: Hashing the result of this function will remove any low-influence properties it has + /// and mean that all bits of the resulting value are entirely manipulatable by the author of + /// the parent block, who can determine the value of `parent_hash`. + fn random(subject: &[u8]) -> T::Hash { + let block_number = >::block_number(); + let index = block_number_to_index::(block_number); + + let hash_series = >::get(); + if !hash_series.is_empty() { + // Always the case after block 1 is initialised. + hash_series.iter() + .cycle() + .skip(index) + .take(RANDOM_MATERIAL_LEN as usize) + .enumerate() + .map(|(i, h)| (i as i8, subject, h).using_encoded(T::Hashing::hash)) + .triplet_mix() + } else { + T::Hash::default() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::H256; + use sp_runtime::{ + Perbill, traits::{BlakeTwo256, OnInitialize, Header as _, IdentityLookup}, testing::Header, + }; + use frame_support::{impl_outer_origin, parameter_types, weights::Weight, traits::Randomness}; + + #[derive(Clone, PartialEq, Eq)] + pub struct Test; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + + type System = frame_system::Module; + type CollectiveFlip = Module; + + fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + t.into() + } + + #[test] + fn test_block_number_to_index() { + for i in 1 .. 1000 { + assert_eq!((i - 1) as usize % 81, block_number_to_index::(i)); + } + } + + fn setup_blocks(blocks: u64) { + let mut parent_hash = System::parent_hash(); + + for i in 1 .. (blocks + 1) { + System::initialize( + &i, + &parent_hash, + &Default::default(), + &Default::default(), + frame_system::InitKind::Full, + ); + CollectiveFlip::on_initialize(i); + + let header = System::finalize(); + parent_hash = header.hash(); + System::set_block_number(*header.number()); + } + } + + #[test] + fn test_random_material_parital() { + new_test_ext().execute_with(|| { + let genesis_hash = System::parent_hash(); + + setup_blocks(38); + + let random_material = CollectiveFlip::random_material(); + + assert_eq!(random_material.len(), 38); + assert_eq!(random_material[0], genesis_hash); + }); + } + + #[test] + fn test_random_material_filled() { + new_test_ext().execute_with(|| { + let genesis_hash = System::parent_hash(); + + setup_blocks(81); + + let random_material = CollectiveFlip::random_material(); + + assert_eq!(random_material.len(), 81); + assert_ne!(random_material[0], random_material[1]); + assert_eq!(random_material[0], genesis_hash); + }); + } + + #[test] + fn test_random_material_filled_twice() { + new_test_ext().execute_with(|| { + let genesis_hash = System::parent_hash(); + + setup_blocks(162); + + let random_material = CollectiveFlip::random_material(); + + assert_eq!(random_material.len(), 81); + assert_ne!(random_material[0], random_material[1]); + assert_ne!(random_material[0], genesis_hash); + }); + } + + #[test] + fn test_random() { + new_test_ext().execute_with(|| { + setup_blocks(162); + + assert_eq!(System::block_number(), 162); + assert_eq!(CollectiveFlip::random_seed(), CollectiveFlip::random_seed()); + assert_ne!(CollectiveFlip::random(b"random_1"), CollectiveFlip::random(b"random_2")); + + let random = CollectiveFlip::random_seed(); + + assert_ne!(random, H256::zero()); + assert!(!CollectiveFlip::random_material().contains(&random)); + }); + } +} diff --git a/frame/scored-pool/Cargo.toml b/frame/scored-pool/Cargo.toml new file mode 100644 index 0000000000000..0b4c2768dfcb5 --- /dev/null +++ b/frame/scored-pool/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "pallet-scored-pool" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +pallet-balances = { version = "2.0.0", path = "../balances" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } + +[features] +default = ["std"] +std = [ + "codec/std", + "serde", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/scored-pool/src/lib.rs b/frame/scored-pool/src/lib.rs new file mode 100644 index 0000000000000..a8fc69971aae0 --- /dev/null +++ b/frame/scored-pool/src/lib.rs @@ -0,0 +1,466 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Scored Pool Module +//! +//! The module maintains a scored membership pool. Each entity in the +//! pool can be attributed a `Score`. From this pool a set `Members` +//! is constructed. This set contains the `MemberCount` highest +//! scoring entities. Unscored entities are never part of `Members`. +//! +//! If an entity wants to be part of the pool a deposit is required. +//! The deposit is returned when the entity withdraws or when it +//! is removed by an entity with the appropriate authority. +//! +//! Every `Period` blocks the set of `Members` is refreshed from the +//! highest scoring members in the pool and, no matter if changes +//! occurred, `T::MembershipChanged::set_members_sorted` is invoked. +//! On first load `T::MembershipInitialized::initialize_members` is +//! invoked with the initial `Members` set. +//! +//! It is possible to withdraw candidacy/resign your membership at any +//! time. If an entity is currently a member, this results in removal +//! from the `Pool` and `Members`; the entity is immediately replaced +//! by the next highest scoring candidate in the pool, if available. +//! +//! - [`scored_pool::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Interface +//! +//! ### Public Functions +//! +//! - `submit_candidacy` - Submit candidacy to become a member. Requires a deposit. +//! - `withdraw_candidacy` - Withdraw candidacy. Deposit is returned. +//! - `score` - Attribute a quantitative score to an entity. +//! - `kick` - Remove an entity from the pool and members. Deposit is returned. +//! - `change_member_count` - Changes the amount of candidates taken into `Members`. +//! +//! ## Usage +//! +//! ``` +//! use frame_support::{decl_module, dispatch}; +//! use frame_system::{self as system, ensure_signed}; +//! use pallet_scored_pool::{self as scored_pool}; +//! +//! pub trait Trait: scored_pool::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn candidate(origin) -> dispatch::DispatchResult { +//! let who = ensure_signed(origin)?; +//! +//! let _ = >::submit_candidacy( +//! T::Origin::from(Some(who.clone()).into()) +//! ); +//! Ok(()) +//! } +//! } +//! } +//! +//! # fn main() { } +//! ``` +//! +//! ## Dependencies +//! +//! This module depends on the [System module](../frame_system/index.html). + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +use codec::FullCodec; +use sp_std::{ + fmt::Debug, + prelude::*, +}; +use frame_support::{ + decl_module, decl_storage, decl_event, ensure, decl_error, + traits::{ChangeMembers, InitializeMembers, Currency, Get, ReservableCurrency}, +}; +use frame_system::{self as system, ensure_root, ensure_signed}; +use sp_runtime::{ + traits::{EnsureOrigin, SimpleArithmetic, MaybeSerializeDeserialize, Zero, StaticLookup}, +}; + +type BalanceOf = <>::Currency as Currency<::AccountId>>::Balance; +type PoolT = Vec<(::AccountId, Option<>::Score>)>; + +/// The enum is supplied when refreshing the members set. +/// Depending on the enum variant the corresponding associated +/// type function will be invoked. +enum ChangeReceiver { + /// Should call `T::MembershipInitialized`. + MembershipInitialized, + /// Should call `T::MembershipChanged`. + MembershipChanged, +} + +pub trait Trait: frame_system::Trait { + /// The currency used for deposits. + type Currency: Currency + ReservableCurrency; + + /// The score attributed to a member or candidate. + type Score: + SimpleArithmetic + Clone + Copy + Default + FullCodec + MaybeSerializeDeserialize + Debug; + + /// The overarching event type. + type Event: From> + Into<::Event>; + + // The deposit which is reserved from candidates if they want to + // start a candidacy. The deposit gets returned when the candidacy is + // withdrawn or when the candidate is kicked. + type CandidateDeposit: Get>; + + /// Every `Period` blocks the `Members` are filled with the highest scoring + /// members in the `Pool`. + type Period: Get; + + /// The receiver of the signal for when the membership has been initialized. + /// This happens pre-genesis and will usually be the same as `MembershipChanged`. + /// If you need to do something different on initialization, then you can change + /// this accordingly. + type MembershipInitialized: InitializeMembers; + + /// The receiver of the signal for when the members have changed. + type MembershipChanged: ChangeMembers; + + /// Allows a configurable origin type to set a score to a candidate in the pool. + type ScoreOrigin: EnsureOrigin; + + /// Required origin for removing a member (though can always be Root). + /// Configurable origin which enables removing an entity. If the entity + /// is part of the `Members` it is immediately replaced by the next + /// highest scoring candidate, if available. + type KickOrigin: EnsureOrigin; +} + +decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as ScoredPool { + /// The current pool of candidates, stored as an ordered Vec + /// (ordered descending by score, `None` last, highest first). + Pool get(fn pool) config(): PoolT; + + /// A Map of the candidates. The information in this Map is redundant + /// to the information in the `Pool`. But the Map enables us to easily + /// check if a candidate is already in the pool, without having to + /// iterate over the entire pool (the `Pool` is not sorted by + /// `T::AccountId`, but by `T::Score` instead). + CandidateExists get(fn candidate_exists): map T::AccountId => bool; + + /// The current membership, stored as an ordered Vec. + Members get(fn members): Vec; + + /// Size of the `Members` set. + MemberCount get(fn member_count) config(): u32; + } + add_extra_genesis { + config(members): Vec; + config(phantom): sp_std::marker::PhantomData; + build(|config| { + let mut pool = config.pool.clone(); + + // reserve balance for each candidate in the pool. + // panicking here is ok, since this just happens one time, pre-genesis. + pool + .iter() + .for_each(|(who, _)| { + T::Currency::reserve(&who, T::CandidateDeposit::get()) + .expect("balance too low to create candidacy"); + >::insert(who, true); + }); + + /// Sorts the `Pool` by score in a descending order. Entities which + /// have a score of `None` are sorted to the beginning of the vec. + pool.sort_by_key(|(_, maybe_score)| + Reverse(maybe_score.unwrap_or_default()) + ); + + >::put(&pool); + >::refresh_members(pool, ChangeReceiver::MembershipInitialized); + }) + } +} + +decl_event!( + pub enum Event where + ::AccountId, + { + /// The given member was removed. See the transaction for who. + MemberRemoved, + /// An entity has issued a candidacy. See the transaction for who. + CandidateAdded, + /// An entity withdrew candidacy. See the transaction for who. + CandidateWithdrew, + /// The candidacy was forcefully removed for an entity. + /// See the transaction for who. + CandidateKicked, + /// A score was attributed to the candidate. + /// See the transaction for who. + CandidateScored, + /// Phantom member, never used. + Dummy(sp_std::marker::PhantomData<(AccountId, I)>), + } +); + +decl_error! { + /// Error for the scored-pool module. + pub enum Error for Module, I: Instance> { + /// Already a member. + AlreadyInPool, + /// Index out of bounds. + InvalidIndex, + /// Index does not match requested account. + WrongAccountIndex, + } +} + +decl_module! { + pub struct Module, I: Instance=DefaultInstance> + for enum Call + where origin: T::Origin + { + type Error = Error; + + fn deposit_event() = default; + + /// Every `Period` blocks the `Members` set is refreshed from the + /// highest scoring members in the pool. + fn on_initialize(n: T::BlockNumber) { + if n % T::Period::get() == Zero::zero() { + let pool = >::get(); + >::refresh_members(pool, ChangeReceiver::MembershipChanged); + } + } + + /// Add `origin` to the pool of candidates. + /// + /// This results in `CandidateDeposit` being reserved from + /// the `origin` account. The deposit is returned once + /// candidacy is withdrawn by the candidate or the entity + /// is kicked by `KickOrigin`. + /// + /// The dispatch origin of this function must be signed. + /// + /// The `index` parameter of this function must be set to + /// the index of the transactor in the `Pool`. + pub fn submit_candidacy(origin) { + let who = ensure_signed(origin)?; + ensure!(!>::exists(&who), Error::::AlreadyInPool); + + let deposit = T::CandidateDeposit::get(); + T::Currency::reserve(&who, deposit)?; + + // can be inserted as last element in pool, since entities with + // `None` are always sorted to the end. + if let Err(e) = >::append(&[(who.clone(), None)]) { + T::Currency::unreserve(&who, deposit); + Err(e)? + } + + >::insert(&who, true); + + Self::deposit_event(RawEvent::CandidateAdded); + } + + /// An entity withdraws candidacy and gets its deposit back. + /// + /// If the entity is part of the `Members`, then the highest member + /// of the `Pool` that is not currently in `Members` is immediately + /// placed in the set instead. + /// + /// The dispatch origin of this function must be signed. + /// + /// The `index` parameter of this function must be set to + /// the index of the transactor in the `Pool`. + pub fn withdraw_candidacy( + origin, + index: u32 + ) { + let who = ensure_signed(origin)?; + + let pool = >::get(); + Self::ensure_index(&pool, &who, index)?; + + Self::remove_member(pool, who, index)?; + Self::deposit_event(RawEvent::CandidateWithdrew); + } + + /// Kick a member `who` from the set. + /// + /// May only be called from `KickOrigin` or root. + /// + /// The `index` parameter of this function must be set to + /// the index of `dest` in the `Pool`. + pub fn kick( + origin, + dest: ::Source, + index: u32 + ) { + T::KickOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + let who = T::Lookup::lookup(dest)?; + + let pool = >::get(); + Self::ensure_index(&pool, &who, index)?; + + Self::remove_member(pool, who, index)?; + Self::deposit_event(RawEvent::CandidateKicked); + } + + /// Score a member `who` with `score`. + /// + /// May only be called from `ScoreOrigin` or root. + /// + /// The `index` parameter of this function must be set to + /// the index of the `dest` in the `Pool`. + pub fn score( + origin, + dest: ::Source, + index: u32, + score: T::Score + ) { + T::ScoreOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + let who = T::Lookup::lookup(dest)?; + + let mut pool = >::get(); + Self::ensure_index(&pool, &who, index)?; + + pool.remove(index as usize); + + // we binary search the pool (which is sorted descending by score). + // if there is already an element with `score`, we insert + // right before that. if not, the search returns a location + // where we can insert while maintaining order. + let item = (who.clone(), Some(score.clone())); + let location = pool + .binary_search_by_key( + &Reverse(score), + |(_, maybe_score)| Reverse(maybe_score.unwrap_or_default()) + ) + .unwrap_or_else(|l| l); + pool.insert(location, item); + + >::put(&pool); + Self::deposit_event(RawEvent::CandidateScored); + } + + /// Dispatchable call to change `MemberCount`. + /// + /// This will only have an effect the next time a refresh happens + /// (this happens each `Period`). + /// + /// May only be called from root. + pub fn change_member_count(origin, count: u32) { + ensure_root(origin)?; + >::put(&count); + } + } +} + +impl, I: Instance> Module { + + /// Fetches the `MemberCount` highest scoring members from + /// `Pool` and puts them into `Members`. + /// + /// The `notify` parameter is used to deduct which associated + /// type function to invoke at the end of the method. + fn refresh_members( + pool: PoolT, + notify: ChangeReceiver + ) { + let count = >::get(); + + let mut new_members: Vec = pool + .into_iter() + .filter(|(_, score)| score.is_some()) + .take(count as usize) + .map(|(account_id, _)| account_id) + .collect(); + new_members.sort(); + + let old_members = >::get(); + >::put(&new_members); + + match notify { + ChangeReceiver::MembershipInitialized => + T::MembershipInitialized::initialize_members(&new_members), + ChangeReceiver::MembershipChanged => + T::MembershipChanged::set_members_sorted( + &new_members[..], + &old_members[..], + ), + } + } + + /// Removes an entity `remove` at `index` from the `Pool`. + /// + /// If the entity is a member it is also removed from `Members` and + /// the deposit is returned. + fn remove_member( + mut pool: PoolT, + remove: T::AccountId, + index: u32 + ) -> Result<(), Error> { + // all callers of this function in this module also check + // the index for validity before calling this function. + // nevertheless we check again here, to assert that there was + // no mistake when invoking this sensible function. + Self::ensure_index(&pool, &remove, index)?; + + pool.remove(index as usize); + >::put(&pool); + + // remove from set, if it was in there + let members = >::get(); + if members.binary_search(&remove).is_ok() { + Self::refresh_members(pool, ChangeReceiver::MembershipChanged); + } + + >::remove(&remove); + + T::Currency::unreserve(&remove, T::CandidateDeposit::get()); + + Self::deposit_event(RawEvent::MemberRemoved); + Ok(()) + } + + /// Checks if `index` is a valid number and if the element found + /// at `index` in `Pool` is equal to `who`. + fn ensure_index( + pool: &PoolT, + who: &T::AccountId, + index: u32 + ) -> Result<(), Error> { + ensure!(index < pool.len() as u32, Error::::InvalidIndex); + + let (index_who, _index_score) = &pool[index as usize]; + ensure!(index_who == who, Error::::WrongAccountIndex); + + Ok(()) + } +} diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs new file mode 100644 index 0000000000000..dd59bbc84fe64 --- /dev/null +++ b/frame/scored-pool/src/mock.rs @@ -0,0 +1,176 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +use super::*; + +use std::cell::RefCell; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight, ord_parameter_types}; +use sp_core::H256; +// The testing primitives are very useful for avoiding having to work with signatures +// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. +use sp_runtime::{ + Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header, +}; +use frame_system::EnsureSignedBy; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +// For testing the module, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of modules we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +parameter_types! { + pub const CandidateDeposit: u64 = 25; + pub const Period: u64 = 4; + + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; +} +ord_parameter_types! { + pub const KickOrigin: u64 = 2; + pub const ScoreOrigin: u64 = 3; +} + +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} + +thread_local! { + pub static MEMBERS: RefCell> = RefCell::new(vec![]); +} + +pub struct TestChangeMembers; +impl ChangeMembers for TestChangeMembers { + fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { + let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); + old_plus_incoming.extend_from_slice(incoming); + old_plus_incoming.sort(); + + let mut new_plus_outgoing = new.to_vec(); + new_plus_outgoing.extend_from_slice(outgoing); + new_plus_outgoing.sort(); + + assert_eq!(old_plus_incoming, new_plus_outgoing); + + MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); + } +} + +impl InitializeMembers for TestChangeMembers { + fn initialize_members(new_members: &[u64]) { + MEMBERS.with(|m| *m.borrow_mut() = new_members.to_vec()); + } +} + +impl Trait for Test { + type Event = (); + type KickOrigin = EnsureSignedBy; + type MembershipInitialized = TestChangeMembers; + type MembershipChanged = TestChangeMembers; + type Currency = Balances; + type CandidateDeposit = CandidateDeposit; + type Period = Period; + type Score = u64; + type ScoreOrigin = EnsureSignedBy; +} + +type System = frame_system::Module; +type Balances = pallet_balances::Module; + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + pallet_balances::GenesisConfig:: { + balances: vec![ + (5, 500_000), + (10, 500_000), + (15, 500_000), + (20, 500_000), + (31, 500_000), + (40, 500_000), + (99, 1), + ], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + GenesisConfig::{ + pool: vec![ + (5, None), + (10, Some(1)), + (20, Some(2)), + (31, Some(2)), + (40, Some(3)), + ], + member_count: 2, + .. Default::default() + }.assimilate_storage(&mut t).unwrap(); + t.into() +} + +/// Fetch an entity from the pool, if existent. +pub fn fetch_from_pool(who: u64) -> Option<(u64, Option)> { + >::pool() + .into_iter() + .find(|item| item.0 == who) +} + +/// Find an entity in the pool. +/// Returns its position in the `Pool` vec, if existent. +pub fn find_in_pool(who: u64) -> Option { + >::pool() + .into_iter() + .position(|item| item.0 == who) +} diff --git a/frame/scored-pool/src/tests.rs b/frame/scored-pool/src/tests.rs new file mode 100644 index 0000000000000..d8c887f4ec683 --- /dev/null +++ b/frame/scored-pool/src/tests.rs @@ -0,0 +1,279 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +use super::*; +use mock::*; + +use frame_support::{assert_ok, assert_noop}; +use sp_runtime::traits::{OnInitialize, BadOrigin}; + +type ScoredPool = Module; +type System = frame_system::Module; +type Balances = pallet_balances::Module; + +#[test] +fn query_membership_works() { + new_test_ext().execute_with(|| { + assert_eq!(ScoredPool::members(), vec![20, 40]); + assert_eq!(Balances::reserved_balance(&31), CandidateDeposit::get()); + assert_eq!(Balances::reserved_balance(&40), CandidateDeposit::get()); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), vec![20, 40]); + }); +} + +#[test] +fn submit_candidacy_must_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + ScoredPool::submit_candidacy(Origin::signed(99)), + pallet_balances::Error::::InsufficientBalance, + ); + assert_noop!( + ScoredPool::submit_candidacy(Origin::signed(40)), + Error::::AlreadyInPool + ); + }); +} + +#[test] +fn submit_candidacy_works() { + new_test_ext().execute_with(|| { + // given + let who = 15; + + // when + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + assert_eq!(fetch_from_pool(15), Some((who, None))); + + // then + assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); + }); +} + +#[test] +fn scoring_works() { + new_test_ext().execute_with(|| { + // given + let who = 15; + let score = 99; + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + + // when + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, score)); + + // then + assert_eq!(fetch_from_pool(who), Some((who, Some(score)))); + assert_eq!(find_in_pool(who), Some(0)); // must be first element, since highest scored + }); +} + +#[test] +fn scoring_same_element_with_same_score_works() { + new_test_ext().execute_with(|| { + // given + let who = 31; + let index = find_in_pool(who).expect("entity must be in pool") as u32; + let score = 2; + + // when + assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, score)); + + // then + assert_eq!(fetch_from_pool(who), Some((who, Some(score)))); + + // must have been inserted right before the `20` element which is + // of the same score as `31`. so sort order is maintained. + assert_eq!(find_in_pool(who), Some(1)); + }); +} + +#[test] +fn kicking_works_only_for_authorized() { + new_test_ext().execute_with(|| { + let who = 40; + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_noop!(ScoredPool::kick(Origin::signed(99), who, index), BadOrigin); + }); +} + +#[test] +fn kicking_works() { + new_test_ext().execute_with(|| { + // given + let who = 40; + assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); + assert_eq!(find_in_pool(who), Some(0)); + + // when + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index)); + + // then + assert_eq!(find_in_pool(who), None); + assert_eq!(ScoredPool::members(), vec![20, 31]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); + assert_eq!(Balances::reserved_balance(&who), 0); // deposit must have been returned + }); +} + +#[test] +fn unscored_entities_must_not_be_used_for_filling_members() { + new_test_ext().execute_with(|| { + // given + // we submit a candidacy, score will be `None` + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(15))); + + // when + // we remove every scored member + ScoredPool::pool() + .into_iter() + .for_each(|(who, score)| { + if let Some(_) = score { + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index)); + } + }); + + // then + // the `None` candidates should not have been filled in + assert_eq!(ScoredPool::members(), vec![]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); + }); +} + +#[test] +fn refreshing_works() { + new_test_ext().execute_with(|| { + // given + let who = 15; + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, 99)); + + // when + ScoredPool::refresh_members(ScoredPool::pool(), ChangeReceiver::MembershipChanged); + + // then + assert_eq!(ScoredPool::members(), vec![15, 40]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); + }); +} + +#[test] +fn refreshing_happens_every_period() { + new_test_ext().execute_with(|| { + // given + System::set_block_number(1); + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(15))); + let index = find_in_pool(15).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), 15, index, 99)); + assert_eq!(ScoredPool::members(), vec![20, 40]); + + // when + System::set_block_number(4); + ScoredPool::on_initialize(4); + + // then + assert_eq!(ScoredPool::members(), vec![15, 40]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); + }); +} + +#[test] +fn withdraw_candidacy_must_only_work_for_members() { + new_test_ext().execute_with(|| { + let who = 77; + let index = 0; + assert_noop!( ScoredPool::withdraw_candidacy(Origin::signed(who), index), Error::::WrongAccountIndex); + }); +} + +#[test] +fn oob_index_should_abort() { + new_test_ext().execute_with(|| { + let who = 40; + let oob_index = ScoredPool::pool().len() as u32; + assert_noop!(ScoredPool::withdraw_candidacy(Origin::signed(who), oob_index), Error::::InvalidIndex); + assert_noop!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, oob_index, 99), Error::::InvalidIndex); + assert_noop!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, oob_index), Error::::InvalidIndex); + }); +} + +#[test] +fn index_mismatches_should_abort() { + new_test_ext().execute_with(|| { + let who = 40; + let index = 3; + assert_noop!(ScoredPool::withdraw_candidacy(Origin::signed(who), index), Error::::WrongAccountIndex); + assert_noop!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, 99), Error::::WrongAccountIndex); + assert_noop!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index), Error::::WrongAccountIndex); + }); +} + +#[test] +fn withdraw_unscored_candidacy_must_work() { + new_test_ext().execute_with(|| { + // given + let who = 5; + + // when + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); + + // then + assert_eq!(fetch_from_pool(5), None); + }); +} + +#[test] +fn withdraw_scored_candidacy_must_work() { + new_test_ext().execute_with(|| { + // given + let who = 40; + assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); + + // when + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); + + // then + assert_eq!(fetch_from_pool(who), None); + assert_eq!(ScoredPool::members(), vec![20, 31]); + assert_eq!(Balances::reserved_balance(&who), 0); + }); +} + +#[test] +fn candidacy_resubmitting_works() { + new_test_ext().execute_with(|| { + // given + let who = 15; + + // when + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + assert_eq!(ScoredPool::candidate_exists(who), true); + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); + assert_eq!(ScoredPool::candidate_exists(who), false); + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + + // then + assert_eq!(ScoredPool::candidate_exists(who), true); + }); +} diff --git a/frame/session/Cargo.toml b/frame/session/Cargo.toml new file mode 100644 index 0000000000000..82047dbd68336 --- /dev/null +++ b/frame/session/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "pallet-session" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../timestamp" } +sp-trie = { optional = true, path = "../../primitives/trie", default-features = false } +sp-io ={ path = "../../primitives/io", default-features = false } +impl-trait-for-tuples = "0.1.3" + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-application-crypto = { version = "2.0.0", path = "../../primitives/application-crypto" } +lazy_static = "1.4.0" + +[features] +default = ["std", "historical"] +historical = ["sp-trie"] +std = [ + "serde", + "safe-mix/std", + "codec/std", + "sp-std/std", + "frame-support/std", + "sp-runtime/std", + "sp-staking/std", + "pallet-timestamp/std", + "sp-trie/std", + "sp-io/std", +] diff --git a/srml/session/src/historical.rs b/frame/session/src/historical.rs similarity index 92% rename from srml/session/src/historical.rs rename to frame/session/src/historical.rs index d3fbc67b950ec..939e6133e8520 100644 --- a/srml/session/src/historical.rs +++ b/frame/session/src/historical.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -25,14 +25,14 @@ //! These roots and proofs of inclusion can be generated at any time during the current session. //! Afterwards, the proofs can be fed to a consensus module when reporting misbehavior. -use rstd::prelude::*; +use sp_std::prelude::*; use codec::{Encode, Decode}; -use sr_primitives::KeyTypeId; -use sr_primitives::traits::{Convert, OpaqueKeys, Hash as HashT}; -use support::{decl_module, decl_storage}; -use support::{Parameter, print}; -use substrate_trie::{MemoryDB, Trie, TrieMut, Recorder, EMPTY_PREFIX}; -use substrate_trie::trie_types::{TrieDBMut, TrieDB}; +use sp_runtime::KeyTypeId; +use sp_runtime::traits::{Convert, OpaqueKeys, Hash as HashT}; +use frame_support::{decl_module, decl_storage}; +use frame_support::{Parameter, print}; +use sp_trie::{MemoryDB, Trie, TrieMut, Recorder, EMPTY_PREFIX}; +use sp_trie::trie_types::{TrieDBMut, TrieDB}; use super::{SessionIndex, Module as SessionModule}; type ValidatorCount = u32; @@ -79,7 +79,7 @@ impl Module { None => return, // nothing to prune. }; - let up_to = rstd::cmp::min(up_to, end); + let up_to = sp_std::cmp::min(up_to, end); if up_to < start { return // out of bounds. harmless. @@ -108,7 +108,7 @@ pub trait OnSessionEnding: crate::OnSessionEndi /// An `OnSessionEnding` implementation that wraps an inner `I` and also /// sets the historical trie root of the ending session. -pub struct NoteHistoricalRoot(rstd::marker::PhantomData<(T, I)>); +pub struct NoteHistoricalRoot(sp_std::marker::PhantomData<(T, I)>); impl crate::OnSessionEnding for NoteHistoricalRoot where I: OnSessionEnding @@ -146,7 +146,7 @@ impl crate::OnSessionEnding for NoteHistoricalRoot< } } -type HasherOf = <::Hashing as HashT>::Hasher; +type HasherOf = <::Hashing as HashT>::Hasher; /// A tuple of the validator's ID and their full identification. pub type IdentificationTuple = (::ValidatorId, ::FullIdentification); @@ -182,11 +182,9 @@ impl ProvingTrie { // map each key to the owner index. for key_id in T::Keys::key_ids() { - let key = keys.get_raw(key_id); + let key = keys.get_raw(*key_id); let res = (key_id, key).using_encoded(|k| - i.using_encoded(|v| - trie.insert(k, v) - ) + i.using_encoded(|v| trie.insert(k, v)) ); let _ = res.map_err(|_| "failed to insert into trie")?; @@ -216,7 +214,7 @@ impl ProvingTrie { } fn from_nodes(root: T::Hash, nodes: &[Vec]) -> Self { - use substrate_trie::HashDBT; + use sp_trie::HashDBT; let mut memory_db = MemoryDB::default(); for node in nodes { @@ -275,7 +273,7 @@ pub struct Proof { trie_nodes: Vec>, } -impl> support::traits::KeyOwnerProofSystem<(KeyTypeId, D)> +impl> frame_support::traits::KeyOwnerProofSystem<(KeyTypeId, D)> for Module { type Proof = Proof; @@ -312,24 +310,24 @@ impl> support::traits::KeyOwnerProofSystem<(KeyTypeId, #[cfg(test)] mod tests { use super::*; - use primitives::crypto::key_types::DUMMY; - use sr_primitives::{traits::OnInitialize, testing::UintAuthorityId}; + use sp_core::crypto::key_types::DUMMY; + use sp_runtime::{traits::OnInitialize, testing::UintAuthorityId}; use crate::mock::{ NEXT_VALIDATORS, force_new_session, set_next_validators, Test, System, Session, }; - use support::traits::KeyOwnerProofSystem; + use frame_support::traits::KeyOwnerProofSystem; type Historical = Module; - fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); crate::GenesisConfig:: { keys: NEXT_VALIDATORS.with(|l| l.borrow().iter().cloned().map(|i| (i, UintAuthorityId(i).into())).collect() ), }.assimilate_storage(&mut t).unwrap(); - runtime_io::TestExternalities::new(t) + sp_io::TestExternalities::new(t) } #[test] diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs new file mode 100644 index 0000000000000..2200221af42fe --- /dev/null +++ b/frame/session/src/lib.rs @@ -0,0 +1,1033 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Session Module +//! +//! The Session module allows validators to manage their session keys, provides a function for changing +//! the session length, and handles session rotation. +//! +//! - [`session::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Overview +//! +//! ### Terminology +//! +//! +//! - **Session:** A session is a period of time that has a constant set of validators. Validators can only join +//! or exit the validator set at a session change. It is measured in block numbers. The block where a session is +//! ended is determined by the `ShouldSessionEnd` trait. When the session is ending, a new validator set +//! can be chosen by `OnSessionEnding` implementations. +//! - **Session key:** A session key is actually several keys kept together that provide the various signing +//! functions required by network authorities/validators in pursuit of their duties. +//! - **Validator ID:** Every account has an associated validator ID. For some simple staking systems, this +//! may just be the same as the account ID. For staking systems using a stash/controller model, +//! the validator ID would be the stash account ID of the controller. +//! - **Session key configuration process:** A session key is set using `set_key` for use in the +//! next session. It is stored in `NextKeyFor`, a mapping between the caller's `ValidatorId` and the session +//! keys provided. `set_key` allows users to set their session key prior to being selected as validator. +//! It is a public call since it uses `ensure_signed`, which checks that the origin is a signed account. +//! As such, the account ID of the origin stored in in `NextKeyFor` may not necessarily be associated with +//! a block author or a validator. The session keys of accounts are removed once their account balance is zero. +//! - **Validator set session key configuration process:** Each session we iterate through the current +//! set of validator account IDs to check if a session key was created for it in the previous session +//! using `set_key`. If it was then we call `set_authority` from the [Consensus module](../frame_consensus/index.html) +//! and pass it a set of session keys (each associated with an account ID) as the session keys for the new +//! validator set. Lastly, if the session key of the current authority does not match any session keys stored under +//! its validator index in the `AuthorityStorageVec` mapping, then we update the mapping with its session +//! key and update the saved list of original authorities if necessary +//! (see https://github.com/paritytech/substrate/issues/1290). Note: Authorities are stored in the Consensus module. +//! They are represented by a validator account ID index from the Session module and allocated with a session +//! key for the length of the session. +//! - **Session length change process:** At the start of the next session we allocate a session index and record the +//! timestamp when the session started. If a `NextSessionLength` was recorded in the previous session, we record +//! it as the new session length. Additionally, if the new session length differs from the length of the +//! next session then we record a `LastLengthChange`. +//! - **Session rotation configuration:** Configure as either a 'normal' (rewardable session where rewards are +//! applied) or 'exceptional' (slashable) session rotation. +//! - **Session rotation process:** The session is changed at the end of the final block of the current session +//! using the `on_finalize` method. It may be called by either an origin or internally from another runtime +//! module at the end of each block. +//! +//! ### Goals +//! +//! The Session module in Substrate is designed to make the following possible: +//! +//! - Set session keys of the validator set for the next session. +//! - Set the length of a session. +//! - Configure and switch between either normal or exceptional session rotations. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! - `set_key` - Set a validator's session key for the next session. +//! - `set_length` - Set a new session length to be applied upon the next session change. +//! - `force_new_session` - Force a new session that should be considered either a normal (rewardable) +//! or exceptional rotation. +//! - `on_finalize` - Called when a block is finalized. Will rotate session if it is the last +//! block of the current session. +//! +//! ### Public Functions +//! +//! - `validator_count` - Get the current number of validators. +//! - `last_length_change` - Get the block number when the session length last changed. +//! - `apply_force_new_session` - Force a new session. Can be called by other runtime modules. +//! - `set_validators` - Set the current set of validators. Can only be called by the Staking module. +//! - `check_rotate_session` - Rotate the session and apply rewards if necessary. Called after the Staking +//! module updates the authorities to the new validator set. +//! - `rotate_session` - Change to the next session. Register the new authority set. Update session keys. +//! Enact session length change if applicable. +//! - `ideal_session_duration` - Get the time of an ideal session. +//! - `blocks_remaining` - Get the number of blocks remaining in the current session, +//! excluding the current block. +//! +//! ## Usage +//! +//! ### Example from the SRML +//! +//! The [Staking module](../pallet_staking/index.html) uses the Session module to get the validator set. +//! +//! ``` +//! use pallet_session as session; +//! # fn not_executed() { +//! +//! let validators = >::validators(); +//! # } +//! # fn main(){} +//! ``` +//! +//! ## Related Modules +//! +//! - [Consensus](../frame_consensus/index.html) +//! - [Staking](../pallet_staking/index.html) +//! - [Timestamp](../pallet_timestamp/index.html) + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{prelude::*, marker::PhantomData, ops::{Sub, Rem}}; +use codec::Decode; +use sp_runtime::{KeyTypeId, Perbill, RuntimeAppPublic, BoundToRuntimeAppPublic}; +use frame_support::weights::SimpleDispatchInfo; +use sp_runtime::traits::{Convert, Zero, Member, OpaqueKeys}; +use sp_staking::SessionIndex; +use frame_support::{dispatch, ConsensusEngineId, decl_module, decl_event, decl_storage, decl_error}; +use frame_support::{ensure, traits::{OnFreeBalanceZero, Get, FindAuthor, ValidatorRegistration}, Parameter}; +use frame_system::{self as system, ensure_signed}; + +#[cfg(test)] +mod mock; + +#[cfg(feature = "historical")] +pub mod historical; + +/// Decides whether the session should be ended. +pub trait ShouldEndSession { + /// Return `true` if the session should be ended. + fn should_end_session(now: BlockNumber) -> bool; +} + +/// Ends the session after a fixed period of blocks. +/// +/// The first session will have length of `Offset`, and +/// the following sessions will have length of `Period`. +/// This may prove nonsensical if `Offset` >= `Period`. +pub struct PeriodicSessions< + Period, + Offset, +>(PhantomData<(Period, Offset)>); + +impl< + BlockNumber: Rem + Sub + Zero + PartialOrd, + Period: Get, + Offset: Get, +> ShouldEndSession for PeriodicSessions { + fn should_end_session(now: BlockNumber) -> bool { + let offset = Offset::get(); + now >= offset && ((now - offset) % Period::get()).is_zero() + } +} + +/// An event handler for when the session is ending. +/// TODO [slashing] consider renaming to OnSessionStarting +pub trait OnSessionEnding { + /// Handle the fact that the session is ending, and optionally provide the new validator set. + /// + /// Even if the validator-set is the same as before, if any underlying economic + /// conditions have changed (i.e. stake-weights), the new validator set must be returned. + /// This is necessary for consensus engines making use of the session module to + /// issue a validator-set change so misbehavior can be provably associated with the new + /// economic conditions as opposed to the old. + /// + /// `ending_index` is the index of the currently ending session. + /// The returned validator set, if any, will not be applied until `will_apply_at`. + /// `will_apply_at` is guaranteed to be at least `ending_index + 1`, since session indices don't + /// repeat, but it could be some time after in case we are staging authority set changes. + fn on_session_ending( + ending_index: SessionIndex, + will_apply_at: SessionIndex + ) -> Option>; +} + +impl OnSessionEnding for () { + fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { None } +} + +/// Handler for session lifecycle events. +pub trait SessionHandler { + /// All the key type ids this session handler can process. + /// + /// The order must be the same as it expects them in + /// [`on_new_session`](Self::on_new_session) and [`on_genesis_session`](Self::on_genesis_session). + const KEY_TYPE_IDS: &'static [KeyTypeId]; + + /// The given validator set will be used for the genesis session. + /// It is guaranteed that the given validator set will also be used + /// for the second session, therefore the first call to `on_new_session` + /// should provide the same validator set. + fn on_genesis_session(validators: &[(ValidatorId, Ks)]); + + /// Session set has changed; act appropriately. Note that this can be called + /// before initialization of your module. + /// + /// `changed` is true whenever any of the session keys or underlying economic + /// identities or weightings behind those keys has changed. + fn on_new_session( + changed: bool, + validators: &[(ValidatorId, Ks)], + queued_validators: &[(ValidatorId, Ks)], + ); + + /// A notification for end of the session. + /// + /// Note it is triggered before any `OnSessionEnding` handlers, + /// so we can still affect the validator set. + fn on_before_session_ending() {} + + /// A validator got disabled. Act accordingly until a new session begins. + fn on_disabled(validator_index: usize); +} + +/// A session handler for specific key type. +pub trait OneSessionHandler: BoundToRuntimeAppPublic { + /// The key type expected. + type Key: Decode + Default + RuntimeAppPublic; + + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator, ValidatorId: 'a; + + /// Session set has changed; act appropriately. Note that this can be called + /// before initialization of your module. + /// + /// `changed` is true when at least one of the session keys + /// or the underlying economic identities/distribution behind one the + /// session keys has changed, false otherwise. + /// + /// The `validators` are the validators of the incoming session, and `queued_validators` + /// will follow. + fn on_new_session<'a, I: 'a>( + changed: bool, + validators: I, + queued_validators: I, + ) where I: Iterator, ValidatorId: 'a; + + + /// A notification for end of the session. + /// + /// Note it is triggered before any `OnSessionEnding` handlers, + /// so we can still affect the validator set. + fn on_before_session_ending() {} + + /// A validator got disabled. Act accordingly until a new session begins. + fn on_disabled(_validator_index: usize); +} + +#[impl_trait_for_tuples::impl_for_tuples(1, 30)] +#[tuple_types_no_default_trait_bound] +impl SessionHandler for Tuple { + for_tuples!( where #( Tuple: OneSessionHandler )* ); + + for_tuples!( + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[ #( ::ID ),* ]; + ); + + fn on_genesis_session(validators: &[(AId, Ks)]) { + for_tuples!( + #( + let our_keys: Box> = Box::new(validators.iter() + .map(|k| (&k.0, k.1.get::(::ID) + .unwrap_or_default()))); + + Tuple::on_genesis_session(our_keys); + )* + ) + } + + fn on_new_session( + changed: bool, + validators: &[(AId, Ks)], + queued_validators: &[(AId, Ks)], + ) { + for_tuples!( + #( + let our_keys: Box> = Box::new(validators.iter() + .map(|k| (&k.0, k.1.get::(::ID) + .unwrap_or_default()))); + let queued_keys: Box> = Box::new(queued_validators.iter() + .map(|k| (&k.0, k.1.get::(::ID) + .unwrap_or_default()))); + Tuple::on_new_session(changed, our_keys, queued_keys); + )* + ) + } + + fn on_before_session_ending() { + for_tuples!( #( Tuple::on_before_session_ending(); )* ) + } + + fn on_disabled(i: usize) { + for_tuples!( #( Tuple::on_disabled(i); )* ) + } +} + +/// `SessionHandler` for tests that use `UintAuthorityId` as `Keys`. +pub struct TestSessionHandler; +impl SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[sp_runtime::key_types::DUMMY]; + + fn on_genesis_session(_: &[(AId, Ks)]) {} + + fn on_new_session(_: bool, _: &[(AId, Ks)], _: &[(AId, Ks)]) {} + + fn on_before_session_ending() {} + + fn on_disabled(_: usize) {} +} + +/// Handler for selecting the genesis validator set. +pub trait SelectInitialValidators { + /// Returns the initial validator set. If `None` is returned + /// all accounts that have session keys set in the genesis block + /// will be validators. + fn select_initial_validators() -> Option>; +} + +/// Implementation of `SelectInitialValidators` that does nothing. +impl SelectInitialValidators for () { + fn select_initial_validators() -> Option> { + None + } +} + +impl ValidatorRegistration for Module { + fn is_registered(id: &T::ValidatorId) -> bool { + Self::load_keys(id).is_some() + } +} + +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From + Into<::Event>; + + /// A stable ID for a validator. + type ValidatorId: Member + Parameter; + + /// A conversion from account ID to validator ID. + type ValidatorIdOf: Convert>; + + /// Indicator for when to end the session. + type ShouldEndSession: ShouldEndSession; + + /// Handler for when a session is about to end. + type OnSessionEnding: OnSessionEnding; + + /// Handler when a session has changed. + type SessionHandler: SessionHandler; + + /// The keys. + type Keys: OpaqueKeys + Member + Parameter + Default; + + /// The fraction of validators set that is safe to be disabled. + /// + /// After the threshold is reached `disabled` method starts to return true, + /// which in combination with `pallet_staking` forces a new era. + type DisabledValidatorsThreshold: Get; + + /// Select initial validators. + type SelectInitialValidators: SelectInitialValidators; +} + +const DEDUP_KEY_PREFIX: &[u8] = b":session:keys"; + +decl_storage! { + trait Store for Module as Session { + /// The current set of validators. + Validators get(fn validators): Vec; + + /// Current index of the session. + CurrentIndex get(fn current_index): SessionIndex; + + /// True if the underlying economic identities or weighting behind the validators + /// has changed in the queued validator set. + QueuedChanged: bool; + + /// The queued keys for the next session. When the next session begins, these keys + /// will be used to determine the validator's session keys. + QueuedKeys get(fn queued_keys): Vec<(T::ValidatorId, T::Keys)>; + + /// Indices of disabled validators. + /// + /// The set is cleared when `on_session_ending` returns a new set of identities. + DisabledValidators get(fn disabled_validators): Vec; + + /// The next session keys for a validator. + /// + /// The first key is always `DEDUP_KEY_PREFIX` to have all the data in the same branch of + /// the trie. Having all data in the same branch should prevent slowing down other queries. + NextKeys: double_map hasher(twox_64_concat) Vec, hasher(blake2_256) T::ValidatorId + => Option; + + /// The owner of a key. The second key is the `KeyTypeId` + the encoded key. + /// + /// The first key is always `DEDUP_KEY_PREFIX` to have all the data in the same branch of + /// the trie. Having all data in the same branch should prevent slowing down other queries. + KeyOwner: double_map hasher(twox_64_concat) Vec, hasher(blake2_256) (KeyTypeId, Vec) + => Option; + } + add_extra_genesis { + config(keys): Vec<(T::ValidatorId, T::Keys)>; + build(|config: &GenesisConfig| { + if T::SessionHandler::KEY_TYPE_IDS.len() != T::Keys::key_ids().len() { + panic!("Number of keys in session handler and session keys does not match"); + } + + T::SessionHandler::KEY_TYPE_IDS.iter().zip(T::Keys::key_ids()).enumerate() + .for_each(|(i, (sk, kk))| { + if sk != kk { + panic!( + "Session handler and session key expect different key type at index: {}", + i, + ); + } + }); + + for (who, keys) in config.keys.iter().cloned() { + assert!( + >::load_keys(&who).is_none(), + "genesis config contained duplicate validator {:?}", who, + ); + + >::do_set_keys(&who, keys) + .expect("genesis config must not contain duplicates; qed"); + } + + let initial_validators = T::SelectInitialValidators::select_initial_validators() + .unwrap_or_else(|| config.keys.iter().map(|(ref v, _)| v.clone()).collect()); + + assert!(!initial_validators.is_empty(), "Empty validator set in genesis block!"); + + let queued_keys: Vec<_> = initial_validators + .iter() + .cloned() + .map(|v| ( + v.clone(), + >::load_keys(&v).unwrap_or_default(), + )) + .collect(); + + // Tell everyone about the genesis session keys + T::SessionHandler::on_genesis_session::(&queued_keys); + + >::put(initial_validators); + >::put(queued_keys); + }); + } +} + +decl_event!( + pub enum Event { + /// New session has happened. Note that the argument is the session index, not the block + /// number as the type might suggest. + NewSession(SessionIndex), + } +); + +decl_error! { + /// Error for the session module. + pub enum Error for Module { + /// Invalid ownership proof. + InvalidProof, + /// No associated validator ID for account. + NoAssociatedValidatorId, + /// Registered duplicate key. + DuplicatedKey, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Used as first key for `NextKeys` and `KeyOwner` to put all the data into the same branch + /// of the trie. + const DEDUP_KEY_PREFIX: &[u8] = DEDUP_KEY_PREFIX; + + type Error = Error; + + fn deposit_event() = default; + + /// Sets the session key(s) of the function caller to `key`. + /// Allows an account to set its session key prior to becoming a validator. + /// This doesn't take effect until the next session. + /// + /// The dispatch origin of this function must be signed. + /// + /// # + /// - O(log n) in number of accounts. + /// - One extra DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(150_000)] + fn set_keys(origin, keys: T::Keys, proof: Vec) -> dispatch::DispatchResult { + let who = ensure_signed(origin)?; + + ensure!(keys.ownership_proof_is_valid(&proof), Error::::InvalidProof); + + let who = T::ValidatorIdOf::convert(who).ok_or(Error::::NoAssociatedValidatorId)?; + + Self::do_set_keys(&who, keys)?; + + Ok(()) + } + + /// Called when a block is initialized. Will rotate session if it is the last + /// block of the current session. + fn on_initialize(n: T::BlockNumber) { + if T::ShouldEndSession::should_end_session(n) { + Self::rotate_session(); + } + } + } +} + +impl Module { + /// Move on to next session. Register new validator set and session keys. Changes + /// to the validator set have a session of delay to take effect. This allows for + /// equivocation punishment after a fork. + pub fn rotate_session() { + let session_index = CurrentIndex::get(); + + let changed = QueuedChanged::get(); + + // Inform the session handlers that a session is going to end. + T::SessionHandler::on_before_session_ending(); + + // Get queued session keys and validators. + let session_keys = >::get(); + let validators = session_keys.iter() + .map(|(validator, _)| validator.clone()) + .collect::>(); + >::put(&validators); + + if changed { + // reset disabled validators + DisabledValidators::take(); + } + + let applied_at = session_index + 2; + + // Get next validator set. + let maybe_next_validators = T::OnSessionEnding::on_session_ending(session_index, applied_at); + let (next_validators, next_identities_changed) + = if let Some(validators) = maybe_next_validators + { + // NOTE: as per the documentation on `OnSessionEnding`, we consider + // the validator set as having changed even if the validators are the + // same as before, as underlying economic conditions may have changed. + (validators, true) + } else { + (>::get(), false) + }; + + // Increment session index. + let session_index = session_index + 1; + CurrentIndex::put(session_index); + + // Queue next session keys. + let (queued_amalgamated, next_changed) = { + // until we are certain there has been a change, iterate the prior + // validators along with the current and check for changes + let mut changed = next_identities_changed; + + let mut now_session_keys = session_keys.iter(); + let mut check_next_changed = |keys: &T::Keys| { + if changed { return } + // since a new validator set always leads to `changed` starting + // as true, we can ensure that `now_session_keys` and `next_validators` + // have the same length. this function is called once per iteration. + if let Some(&(_, ref old_keys)) = now_session_keys.next() { + if old_keys != keys { + changed = true; + return + } + } + }; + let queued_amalgamated = next_validators.into_iter() + .map(|a| { + let k = Self::load_keys(&a).unwrap_or_default(); + check_next_changed(&k); + (a, k) + }) + .collect::>(); + + (queued_amalgamated, changed) + }; + + >::put(queued_amalgamated.clone()); + QueuedChanged::put(next_changed); + + // Record that this happened. + Self::deposit_event(Event::NewSession(session_index)); + + // Tell everyone about the new session keys. + T::SessionHandler::on_new_session::( + changed, + &session_keys, + &queued_amalgamated, + ); + } + + /// Disable the validator of index `i`. + /// + /// Returns `true` if this causes a `DisabledValidatorsThreshold` of validators + /// to be already disabled. + pub fn disable_index(i: usize) -> bool { + let (fire_event, threshold_reached) = DisabledValidators::mutate(|disabled| { + let i = i as u32; + if let Err(index) = disabled.binary_search(&i) { + let count = >::decode_len().unwrap_or(0) as u32; + let threshold = T::DisabledValidatorsThreshold::get() * count; + disabled.insert(index, i); + (true, disabled.len() as u32 > threshold) + } else { + (false, false) + } + }); + + if fire_event { + T::SessionHandler::on_disabled(i); + } + + threshold_reached + } + + /// Disable the validator identified by `c`. (If using with the staking module, + /// this would be their *stash* account.) + /// + /// Returns `Ok(true)` if more than `DisabledValidatorsThreshold` validators in current + /// session is already disabled. + /// If used with the staking module it allows to force a new era in such case. + pub fn disable(c: &T::ValidatorId) -> sp_std::result::Result { + Self::validators().iter().position(|i| i == c).map(Self::disable_index).ok_or(()) + } + + // perform the set_key operation, checking for duplicates. + // does not set `Changed`. + fn do_set_keys(who: &T::ValidatorId, keys: T::Keys) -> dispatch::DispatchResult { + let old_keys = Self::load_keys(&who); + + for id in T::Keys::key_ids() { + let key = keys.get_raw(*id); + + // ensure keys are without duplication. + ensure!( + Self::key_owner(*id, key).map_or(true, |owner| &owner == who), + Error::::DuplicatedKey, + ); + + if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(*id)) { + if key == old { + continue; + } + + Self::clear_key_owner(*id, old); + } + + Self::put_key_owner(*id, key, &who); + } + + Self::put_keys(&who, &keys); + + Ok(()) + } + + fn prune_dead_keys(who: &T::ValidatorId) { + if let Some(old_keys) = Self::take_keys(who) { + for id in T::Keys::key_ids() { + let key_data = old_keys.get_raw(*id); + Self::clear_key_owner(*id, key_data); + } + } + } + + fn load_keys(v: &T::ValidatorId) -> Option { + >::get(DEDUP_KEY_PREFIX, v) + } + + fn take_keys(v: &T::ValidatorId) -> Option { + >::take(DEDUP_KEY_PREFIX, v) + } + + fn put_keys(v: &T::ValidatorId, keys: &T::Keys) { + >::insert(DEDUP_KEY_PREFIX, v, keys); + } + + fn key_owner(id: KeyTypeId, key_data: &[u8]) -> Option { + >::get(DEDUP_KEY_PREFIX, (id, key_data)) + } + + fn put_key_owner(id: KeyTypeId, key_data: &[u8], v: &T::ValidatorId) { + >::insert(DEDUP_KEY_PREFIX, (id, key_data), v) + } + + fn clear_key_owner(id: KeyTypeId, key_data: &[u8]) { + >::remove(DEDUP_KEY_PREFIX, (id, key_data)); + } +} + +impl OnFreeBalanceZero for Module { + fn on_free_balance_zero(who: &T::ValidatorId) { + Self::prune_dead_keys(who); + } +} + +/// Wraps the author-scraping logic for consensus engines that can recover +/// the canonical index of an author. This then transforms it into the +/// registering account-ID of that session key index. +pub struct FindAccountFromAuthorIndex(sp_std::marker::PhantomData<(T, Inner)>); + +impl> FindAuthor + for FindAccountFromAuthorIndex +{ + fn find_author<'a, I>(digests: I) -> Option + where I: 'a + IntoIterator + { + let i = Inner::find_author(digests)?; + + let validators = >::validators(); + validators.get(i as usize).map(|k| k.clone()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::assert_ok; + use sp_core::crypto::key_types::DUMMY; + use sp_runtime::{traits::OnInitialize, testing::UintAuthorityId}; + use mock::{ + NEXT_VALIDATORS, SESSION_CHANGED, TEST_SESSION_CHANGED, authorities, force_new_session, + set_next_validators, set_session_length, session_changed, Test, Origin, System, Session, + reset_before_session_end_called, before_session_end_called, + }; + + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig:: { + keys: NEXT_VALIDATORS.with(|l| + l.borrow().iter().cloned().map(|i| (i, UintAuthorityId(i).into())).collect() + ), + }.assimilate_storage(&mut t).unwrap(); + sp_io::TestExternalities::new(t) + } + + fn initialize_block(block: u64) { + SESSION_CHANGED.with(|l| *l.borrow_mut() = false); + System::set_block_number(block); + Session::on_initialize(block); + } + + #[test] + fn simple_setup_should_work() { + new_test_ext().execute_with(|| { + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert_eq!(Session::validators(), vec![1, 2, 3]); + }); + } + + #[test] + fn put_get_keys() { + new_test_ext().execute_with(|| { + Session::put_keys(&10, &UintAuthorityId(10).into()); + assert_eq!(Session::load_keys(&10), Some(UintAuthorityId(10).into())); + }) + } + + #[test] + fn keys_cleared_on_kill() { + let mut ext = new_test_ext(); + ext.execute_with(|| { + assert_eq!(Session::validators(), vec![1, 2, 3]); + assert_eq!(Session::load_keys(&1), Some(UintAuthorityId(1).into())); + + let id = DUMMY; + assert_eq!(Session::key_owner(id, UintAuthorityId(1).get_raw(id)), Some(1)); + + Session::on_free_balance_zero(&1); + assert_eq!(Session::load_keys(&1), None); + assert_eq!(Session::key_owner(id, UintAuthorityId(1).get_raw(id)), None); + }) + } + + #[test] + fn authorities_should_track_validators() { + reset_before_session_end_called(); + + new_test_ext().execute_with(|| { + set_next_validators(vec![1, 2]); + force_new_session(); + initialize_block(1); + assert_eq!(Session::queued_keys(), vec![ + (1, UintAuthorityId(1).into()), + (2, UintAuthorityId(2).into()), + ]); + assert_eq!(Session::validators(), vec![1, 2, 3]); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + force_new_session(); + initialize_block(2); + assert_eq!(Session::queued_keys(), vec![ + (1, UintAuthorityId(1).into()), + (2, UintAuthorityId(2).into()), + ]); + assert_eq!(Session::validators(), vec![1, 2]); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + set_next_validators(vec![1, 2, 4]); + assert_ok!(Session::set_keys(Origin::signed(4), UintAuthorityId(4).into(), vec![])); + force_new_session(); + initialize_block(3); + assert_eq!(Session::queued_keys(), vec![ + (1, UintAuthorityId(1).into()), + (2, UintAuthorityId(2).into()), + (4, UintAuthorityId(4).into()), + ]); + assert_eq!(Session::validators(), vec![1, 2]); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); + assert!(before_session_end_called()); + + force_new_session(); + initialize_block(4); + assert_eq!(Session::queued_keys(), vec![ + (1, UintAuthorityId(1).into()), + (2, UintAuthorityId(2).into()), + (4, UintAuthorityId(4).into()), + ]); + assert_eq!(Session::validators(), vec![1, 2, 4]); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(4)]); + }); + } + + #[test] + fn should_work_with_early_exit() { + new_test_ext().execute_with(|| { + set_session_length(10); + + initialize_block(1); + assert_eq!(Session::current_index(), 0); + + initialize_block(2); + assert_eq!(Session::current_index(), 0); + + force_new_session(); + initialize_block(3); + assert_eq!(Session::current_index(), 1); + + initialize_block(9); + assert_eq!(Session::current_index(), 1); + + initialize_block(10); + assert_eq!(Session::current_index(), 2); + }); + } + + #[test] + fn session_change_should_work() { + new_test_ext().execute_with(|| { + // Block 1: No change + initialize_block(1); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + + // Block 2: Session rollover, but no change. + initialize_block(2); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + + // Block 3: Set new key for validator 2; no visible change. + initialize_block(3); + assert_ok!(Session::set_keys(Origin::signed(2), UintAuthorityId(5).into(), vec![])); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + + // Block 4: Session rollover; no visible change. + initialize_block(4); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + + // Block 5: No change. + initialize_block(5); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + + // Block 6: Session rollover; authority 2 changes. + initialize_block(6); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(5), UintAuthorityId(3)]); + }); + } + + #[test] + fn duplicates_are_not_allowed() { + new_test_ext().execute_with(|| { + System::set_block_number(1); + Session::on_initialize(1); + assert!(Session::set_keys(Origin::signed(4), UintAuthorityId(1).into(), vec![]).is_err()); + assert!(Session::set_keys(Origin::signed(1), UintAuthorityId(10).into(), vec![]).is_ok()); + + // is fine now that 1 has migrated off. + assert!(Session::set_keys(Origin::signed(4), UintAuthorityId(1).into(), vec![]).is_ok()); + }); + } + + #[test] + fn session_changed_flag_works() { + reset_before_session_end_called(); + + new_test_ext().execute_with(|| { + TEST_SESSION_CHANGED.with(|l| *l.borrow_mut() = true); + + force_new_session(); + initialize_block(1); + assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + force_new_session(); + initialize_block(2); + assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + Session::disable_index(0); + force_new_session(); + initialize_block(3); + assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + force_new_session(); + initialize_block(4); + assert!(session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + force_new_session(); + initialize_block(5); + assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + assert_ok!(Session::set_keys(Origin::signed(2), UintAuthorityId(5).into(), vec![])); + force_new_session(); + initialize_block(6); + assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + // changing the keys of a validator leads to change. + assert_ok!(Session::set_keys(Origin::signed(69), UintAuthorityId(69).into(), vec![])); + force_new_session(); + initialize_block(7); + assert!(session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + // while changing the keys of a non-validator does not. + force_new_session(); + initialize_block(7); + assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + }); + } + + #[test] + fn periodic_session_works() { + struct Period; + struct Offset; + + impl Get for Period { + fn get() -> u64 { 10 } + } + + impl Get for Offset { + fn get() -> u64 { 3 } + } + + + type P = PeriodicSessions; + + for i in 0..3 { + assert!(!P::should_end_session(i)); + } + + assert!(P::should_end_session(3)); + + for i in (1..10).map(|i| 3 + i) { + assert!(!P::should_end_session(i)); + } + + assert!(P::should_end_session(13)); + } + + #[test] + fn session_keys_generate_output_works_as_set_keys_input() { + new_test_ext().execute_with(|| { + let new_keys = mock::MockSessionKeys::generate(None); + assert_ok!( + Session::set_keys( + Origin::signed(2), + ::Keys::decode(&mut &new_keys[..]).expect("Decode keys"), + vec![], + ) + ); + }); + } + + #[test] + fn return_true_if_more_than_third_is_disabled() { + new_test_ext().execute_with(|| { + set_next_validators(vec![1, 2, 3, 4, 5, 6, 7]); + force_new_session(); + initialize_block(1); + // apply the new validator set + force_new_session(); + initialize_block(2); + + assert_eq!(Session::disable_index(0), false); + assert_eq!(Session::disable_index(1), false); + assert_eq!(Session::disable_index(2), true); + assert_eq!(Session::disable_index(3), true); + }); + } +} diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs new file mode 100644 index 0000000000000..7fe9cd01f43bf --- /dev/null +++ b/frame/session/src/mock.rs @@ -0,0 +1,212 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Mock helpers for Session. + +use super::*; +use std::cell::RefCell; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use sp_core::{crypto::key_types::DUMMY, H256}; +use sp_runtime::{ + Perbill, impl_opaque_keys, traits::{BlakeTwo256, IdentityLookup, ConvertInto}, + testing::{Header, UintAuthorityId} +}; +use sp_staking::SessionIndex; + +impl_opaque_keys! { + pub struct MockSessionKeys { + pub dummy: UintAuthorityId, + } +} + +impl From for MockSessionKeys { + fn from(dummy: UintAuthorityId) -> Self { + Self { dummy } + } +} + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +thread_local! { + pub static VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); + pub static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); + pub static AUTHORITIES: RefCell> = + RefCell::new(vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + pub static FORCE_SESSION_END: RefCell = RefCell::new(false); + pub static SESSION_LENGTH: RefCell = RefCell::new(2); + pub static SESSION_CHANGED: RefCell = RefCell::new(false); + pub static TEST_SESSION_CHANGED: RefCell = RefCell::new(false); + pub static DISABLED: RefCell = RefCell::new(false); + // Stores if `on_before_session_end` was called + pub static BEFORE_SESSION_END_CALLED: RefCell = RefCell::new(false); +} + +pub struct TestShouldEndSession; +impl ShouldEndSession for TestShouldEndSession { + fn should_end_session(now: u64) -> bool { + let l = SESSION_LENGTH.with(|l| *l.borrow()); + now % l == 0 || FORCE_SESSION_END.with(|l| { let r = *l.borrow(); *l.borrow_mut() = false; r }) + } +} + +pub struct TestSessionHandler; +impl SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[UintAuthorityId::ID]; + fn on_genesis_session(_validators: &[(u64, T)]) {} + fn on_new_session( + changed: bool, + validators: &[(u64, T)], + _queued_validators: &[(u64, T)], + ) { + SESSION_CHANGED.with(|l| *l.borrow_mut() = changed); + AUTHORITIES.with(|l| + *l.borrow_mut() = validators.iter() + .map(|(_, id)| id.get::(DUMMY).unwrap_or_default()) + .collect() + ); + } + fn on_disabled(_validator_index: usize) { + DISABLED.with(|l| *l.borrow_mut() = true) + } + fn on_before_session_ending() { + BEFORE_SESSION_END_CALLED.with(|b| *b.borrow_mut() = true); + } +} + +pub struct TestOnSessionEnding; +impl OnSessionEnding for TestOnSessionEnding { + fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { + if !TEST_SESSION_CHANGED.with(|l| *l.borrow()) { + VALIDATORS.with(|v| { + let mut v = v.borrow_mut(); + *v = NEXT_VALIDATORS.with(|l| l.borrow().clone()); + Some(v.clone()) + }) + } else if DISABLED.with(|l| std::mem::replace(&mut *l.borrow_mut(), false)) { + // If there was a disabled validator, underlying conditions have changed + // so we return `Some`. + Some(VALIDATORS.with(|v| v.borrow().clone())) + } else { + None + } + } +} + +#[cfg(feature = "historical")] +impl crate::historical::OnSessionEnding for TestOnSessionEnding { + fn on_session_ending(ending_index: SessionIndex, will_apply_at: SessionIndex) + -> Option<(Vec, Vec<(u64, u64)>)> + { + let pair_with_ids = |vals: &[u64]| vals.iter().map(|&v| (v, v)).collect::>(); + >::on_session_ending(ending_index, will_apply_at) + .map(|vals| (pair_with_ids(&vals), vals)) + .map(|(ids, vals)| (vals, ids)) + } +} + +pub fn authorities() -> Vec { + AUTHORITIES.with(|l| l.borrow().to_vec()) +} + +pub fn force_new_session() { + FORCE_SESSION_END.with(|l| *l.borrow_mut() = true ) +} + +pub fn set_session_length(x: u64) { + SESSION_LENGTH.with(|l| *l.borrow_mut() = x ) +} + +pub fn session_changed() -> bool { + SESSION_CHANGED.with(|l| *l.borrow()) +} + +pub fn set_next_validators(next: Vec) { + NEXT_VALIDATORS.with(|v| *v.borrow_mut() = next); +} + +pub fn before_session_end_called() -> bool { + BEFORE_SESSION_END_CALLED.with(|b| *b.borrow()) +} + +pub fn reset_before_session_end_called() { + BEFORE_SESSION_END_CALLED.with(|b| *b.borrow_mut() = false); +} + +#[derive(Clone, Eq, PartialEq)] +pub struct Test; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const MinimumPeriod: u64 = 5; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); +} + +impl pallet_timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; +} + +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); +} + +impl Trait for Test { + type ShouldEndSession = TestShouldEndSession; + #[cfg(feature = "historical")] + type OnSessionEnding = crate::historical::NoteHistoricalRoot; + #[cfg(not(feature = "historical"))] + type OnSessionEnding = TestOnSessionEnding; + type SessionHandler = TestSessionHandler; + type ValidatorId = u64; + type ValidatorIdOf = ConvertInto; + type Keys = MockSessionKeys; + type Event = (); + type SelectInitialValidators = (); + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; +} + +#[cfg(feature = "historical")] +impl crate::historical::Trait for Test { + type FullIdentification = u64; + type FullIdentificationOf = sp_runtime::traits::ConvertInto; +} + +pub type System = frame_system::Module; +pub type Session = Module; diff --git a/frame/society/Cargo.toml b/frame/society/Cargo.toml new file mode 100644 index 0000000000000..94000e898d602 --- /dev/null +++ b/frame/society/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "pallet-society" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-io ={ path = "../../primitives/io", default-features = false } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +rand_chacha = { version = "0.2", default-features = false } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "codec/std", + "serde", + "sp-io/std", + "sp-runtime/std", + "rand_chacha/std", + "sp-std/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs new file mode 100644 index 0000000000000..005746aeb4937 --- /dev/null +++ b/frame/society/src/lib.rs @@ -0,0 +1,1507 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Society Module +//! +//! - [`society::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! The Society module is an economic game which incentivizes users to participate +//! and maintain a membership society. +//! +//! ### User Types +//! +//! At any point, a user in the society can be one of a: +//! * Bidder - A user who has submitted intention of joining the society. +//! * Candidate - A user who will be voted on to join the society. +//! * Suspended Candidate - A user who failed to win a vote. +//! * Member - A user who is a member of the society. +//! * Suspended Member - A member of the society who has accumulated too many strikes +//! or failed their membership challenge. +//! +//! Of the non-suspended members, there is always a: +//! * Head - A member who is exempt from suspension. +//! * Defender - A member whose membership is under question and voted on again. +//! +//! Of the non-suspended members of the society, a random set of them are chosen as +//! "skeptics". The mechanics of skeptics is explained in the +//! [member phase](#member-phase) below. +//! +//! ### Mechanics +//! +//! #### Rewards +//! +//! Members are incentivized to participate in the society through rewards paid +//! by the Society treasury. These payments have a maturity period that the user +//! must wait before they are able to access the funds. +//! +//! #### Punishments +//! +//! Members can be punished by slashing the reward payouts that have not been +//! collected. Additionally, members can accumulate "strikes", and when they +//! reach a max strike limit, they become suspended. +//! +//! #### Skeptics +//! +//! During the voting period, a random set of members are selected as "skeptics". +//! These skeptics are expected to vote on the current candidates. If they do not vote, +//! their skeptic status is treated as a rejection vote, the member is deemed +//! "lazy", and are given a strike per missing vote. +//! +//! #### Membership Challenges +//! +//! Every challenge rotation period, an existing member will be randomly selected +//! to defend their membership into society. Then, other members can vote whether +//! this defender should stay in society. A simple majority wins vote will determine +//! the outcome of the user. Ties are treated as a failure of the challenge, but +//! assuming no one else votes, the defender always get a free vote on their +//! own challenge keeping them in the society. The Head member is exempt from the +//! negative outcome of a membership challenge. +//! +//! #### Society Treasury +//! +//! The membership society is independently funded by a treasury managed by this +//! module. Some subset of this treasury is placed in a Society Pot, which is used +//! to determine the number of accepted bids. +//! +//! #### Rate of Growth +//! +//! The membership society can grow at a rate of 10 accepted candidates per rotation period up +//! to the max membership threshold. Once this threshold is met, candidate selections +//! are stalled until there is space for new members to join. This can be resolved by +//! voting out existing members through the random challenges or by using governance +//! to increase the maximum membership count. +//! +//! ### User Life Cycle +//! +//! A user can go through the following phases: +//! +//! ```ignore +//! +-------> User <----------+ +//! | + | +//! | | | +//! +----------------------------------------------+ +//! | | | | | +//! | | v | | +//! | | Bidder <-----------+ | +//! | | + | | +//! | | | + | +//! | | v Suspended | +//! | | Candidate +----> Candidate | +//! | | + + | +//! | | | | | +//! | + | | | +//! | Suspended +------>| | | +//! | Member | | | +//! | ^ | | | +//! | | v | | +//! | +-------+ Member <----------+ | +//! | | +//! | | +//! +------------------Society---------------------+ +//! ``` +//! +//! #### Initialization +//! +//! The society is initialized with a single member who is automatically chosen as the Head. +//! +//! #### Bid Phase +//! +//! New users must have a bid to join the society. +//! +//! A user can make a bid by reserving a deposit. Alternatively, an already existing member +//! can create a bid on a user's behalf by "vouching" for them. +//! +//! A bid includes reward information that the user would like to receive for joining +//! the society. A vouching bid can additionally request some portion of that reward as a tip +//! to the voucher for vouching for the prospective candidate. +//! +//! Every rotation period, Bids are ordered by reward amount, and the module +//! selects as many bids the Society Pot can support for that period. +//! +//! These selected bids become candidates and move on to the Candidate phase. +//! Bids that were not selected stay in the bidder pool until they are selected or +//! a user chooses to "unbid". +//! +//! #### Candidate Phase +//! +//! Once a bidder becomes a candidate, members vote whether to approve or reject +//! that candidate into society. This voting process also happens during a rotation period. +//! +//! The approval and rejection criteria for candidates are not set on chain, +//! and may change for different societies. +//! +//! At the end of the rotation period, we collect the votes for a candidate +//! and randomly select a vote as the final outcome. +//! +//! ```ignore +//! [ a-accept, r-reject, s-skeptic ] +//! +----------------------------------+ +//! | | +//! | Member |0|1|2|3|4|5|6|7|8|9| | +//! | ----------------------------- | +//! | Vote |a|a|a|r|s|r|a|a|s|a| | +//! | ----------------------------- | +//! | Selected | | | |x| | | | | | | | +//! | | +//! +----------------------------------+ +//! +//! Result: Rejected +//! ``` +//! +//! Each member that voted opposite to this randomly selected vote is punished by +//! slashing their unclaimed payouts and increasing the number of strikes they have. +//! +//! These slashed funds are given to a random user who voted the same as the +//! selected vote as a reward for participating in the vote. +//! +//! If the candidate wins the vote, they receive their bid reward as a future payout. +//! If the bid was placed by a voucher, they will receive their portion of the reward, +//! before the rest is paid to the winning candidate. +//! +//! One winning candidate is selected as the Head of the members. This is randomly +//! chosen, weighted by the number of approvals the winning candidates accumulated. +//! +//! If the candidate loses the vote, they are suspended and it is up to the Suspension +//! Judgement origin to determine if the candidate should go through the bidding process +//! again, should be accepted into the membership society, or rejected and their deposit +//! slashed. +//! +//! #### Member Phase +//! +//! Once a candidate becomes a member, their role is to participate in society. +//! +//! Regular participation involves voting on candidates who want to join the membership +//! society, and by voting in the right way, a member will accumulate future payouts. +//! When a payout matures, members are able to claim those payouts. +//! +//! Members can also vouch for users to join the society, and request a "tip" from +//! the fees the new member would collect by joining the society. This vouching +//! process is useful in situations where a user may not have enough balance to +//! satisfy the bid deposit. A member can only vouch one user at a time. +//! +//! During rotation periods, a random group of members are selected as "skeptics". +//! These skeptics are expected to vote on the current candidates. If they do not vote, +//! their skeptic status is treated as a rejection vote, the member is deemed +//! "lazy", and are given a strike per missing vote. +//! +//! There is a challenge period in parallel to the rotation period. During a challenge period, +//! a random member is selected to defend their membership to the society. Other members +//! make a traditional majority-wins vote to determine if the member should stay in the society. +//! Ties are treated as a failure of the challenge. +//! +//! If a member accumulates too many strikes or fails their membership challenge, +//! they will become suspended. While a member is suspended, they are unable to +//! claim matured payouts. It is up to the Suspension Judgement origin to determine +//! if the member should re-enter society or be removed from society with all their +//! future payouts slashed. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! #### For General Users +//! +//! * `bid` - A user can make a bid to join the membership society by reserving a deposit. +//! * `unbid` - A user can withdraw their bid for entry, the deposit is returned. +//! +//! #### For Members +//! +//! * `vouch` - A member can place a bid on behalf of a user to join the membership society. +//! * `unvouch` - A member can revoke their vouch for a user. +//! * `vote` - A member can vote to approve or reject a candidate's request to join the society. +//! * `defender_vote` - A member can vote to approve or reject a defender's continued membership +//! to the society. +//! * `payout` - A member can claim their first matured payment. +//! +//! #### For Super Users +//! +//! * `found` - The founder origin can initiate this society. Useful for bootstrapping the Society +//! pallet on an already running chain. +//! * `judge_suspended_member` - The suspension judgement origin is able to make +//! judgement on a suspended member. +//! * `judge_suspended_candidate` - The suspension judgement origin is able to +//! make judgement on a suspended candidate. +//! * `set_max_membership` - The ROOT origin can update the maximum member count for the society. +//! The max membership count must be greater than 1. + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +use rand_chacha::{rand_core::{RngCore, SeedableRng}, ChaChaRng}; +use sp_std::prelude::*; +use codec::{Encode, Decode}; +use sp_runtime::{Percent, ModuleId, RuntimeDebug, + traits::{ + StaticLookup, AccountIdConversion, Saturating, Zero, IntegerSquareRoot, + TrailingZeroInput, CheckedSub, EnsureOrigin + } +}; +use frame_support::{decl_error, decl_module, decl_storage, decl_event, ensure, dispatch::DispatchResult}; +use frame_support::weights::SimpleDispatchInfo; +use frame_support::traits::{ + Currency, ReservableCurrency, Randomness, Get, ChangeMembers, + ExistenceRequirement::{KeepAlive, AllowDeath}, +}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +type BalanceOf = <>::Currency as Currency<::AccountId>>::Balance; + +const MODULE_ID: ModuleId = ModuleId(*b"py/socie"); + +/// The module's configuration trait. +pub trait Trait: system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The currency type used for bidding. + type Currency: ReservableCurrency; + + /// Something that provides randomness in the runtime. + type Randomness: Randomness; + + /// The minimum amount of a deposit required for a bid to be made. + type CandidateDeposit: Get>; + + /// The amount of the unpaid reward that gets deducted in the case that either a skeptic + /// doesn't vote or someone votes in the wrong way. + type WrongSideDeduction: Get>; + + /// The number of times a member may vote the wrong way (or not at all, when they are a skeptic) + /// before they become suspended. + type MaxStrikes: Get; + + /// The amount of incentive paid within each period. Doesn't include VoterTip. + type PeriodSpend: Get>; + + /// The receiver of the signal for when the members have changed. + type MembershipChanged: ChangeMembers; + + /// The number of blocks between candidate/membership rotation periods. + type RotationPeriod: Get; + + /// The maximum duration of the payout lock. + type MaxLockDuration: Get; + + /// The origin that is allowed to call `found`. + type FounderOrigin: EnsureOrigin; + + /// The origin that is allowed to make suspension judgements. + type SuspensionJudgementOrigin: EnsureOrigin; + + /// The number of blocks between membership challenges. + type ChallengePeriod: Get; +} + +/// A vote by a member on a candidate application. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] +pub enum Vote { + /// The member has been chosen to be skeptic and has not yet taken any action. + Skeptic, + /// The member has rejected the candidate's application. + Reject, + /// The member approves of the candidate's application. + Approve, +} + +/// A judgement by the suspension judgement origin on a suspended candidate. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] +pub enum Judgement { + /// The suspension judgement origin takes no direct judgment + /// and places the candidate back into the bid pool. + Rebid, + /// The suspension judgement origin has rejected the candidate's application. + Reject, + /// The suspension judgement origin approves of the candidate's application. + Approve, +} + +/// Details of a payout given as a per-block linear "trickle". +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, Default)] +pub struct Payout { + /// Total value of the payout. + value: Balance, + /// Block number at which the payout begins. + begin: BlockNumber, + /// Total number of blocks over which the payout is spread. + duration: BlockNumber, + /// Total value paid out so far. + paid: Balance, +} + +/// Status of a vouching member. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] +pub enum VouchingStatus { + /// Member is currently vouching for a user. + Vouching, + /// Member is banned from vouching for other members. + Banned, +} + +/// Number of strikes that a member has against them. +pub type StrikeCount = u32; + +/// A bid for entry into society. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug,)] +pub struct Bid { + /// The bidder/candidate trying to enter society + who: AccountId, + /// The kind of bid placed for this bidder/candidate. See `BidKind`. + kind: BidKind, + /// The reward that the bidder has requested for successfully joining the society. + value: Balance, +} + +/// A vote by a member on a candidate application. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] +pub enum BidKind { + /// The CandidateDeposit was paid for this bid. + Deposit(Balance), + /// A member vouched for this bid. The account should be reinstated into `Members` once the + /// bid is successful (or if it is rescinded prior to launch). + Vouch(AccountId, Balance), +} + +impl BidKind { + fn check_voucher(&self, v: &AccountId) -> DispatchResult { + if let BidKind::Vouch(ref a, _) = self { + if a == v { + Ok(()) + } else { + Err("incorrect identity")? + } + } else { + Err("not vouched")? + } + } +} + +// This module's storage items. +decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as Society { + /// The current set of candidates; bidders that are attempting to become members. + pub Candidates get(candidates): Vec>>; + + /// The set of suspended candidates. + pub SuspendedCandidates get(suspended_candidate): + map T::AccountId => Option<(BalanceOf, BidKind>)>; + + /// Amount of our account balance that is specifically for the next round's bid(s). + pub Pot get(fn pot) config(): BalanceOf; + + /// The most primary from the most recently approved members. + pub Head get(head) build(|config: &GenesisConfig| config.members.first().cloned()): + Option; + + /// The current set of members, ordered. + pub Members get(fn members) build(|config: &GenesisConfig| { + let mut m = config.members.clone(); + m.sort(); + m + }): Vec; + + /// The set of suspended members. + pub SuspendedMembers get(fn suspended_member): map T::AccountId => Option<()>; + + /// The current bids, stored ordered by the value of the bid. + Bids: Vec>>; + + /// Members currently vouching or banned from vouching again + Vouching get(fn vouching): map T::AccountId => Option; + + /// Pending payouts; ordered by block number, with the amount that should be paid out. + Payouts: map T::AccountId => Vec<(T::BlockNumber, BalanceOf)>; + + /// The ongoing number of losing votes cast by the member. + Strikes: map T::AccountId => StrikeCount; + + /// Double map from Candidate -> Voter -> (Maybe) Vote. + Votes: double_map + hasher(twox_64_concat) T::AccountId, + hasher(twox_64_concat) T::AccountId + => Option; + + /// The defending member currently being challenged. + Defender get(fn defender): Option; + + /// Votes for the defender. + DefenderVotes: map hasher(twox_64_concat) T::AccountId => Option; + + /// The max number of members for the society at one time. + MaxMembers get(fn max_members) config(): u32; + } + add_extra_genesis { + config(members): Vec; + } +} + +// The module's dispatchable functions. +decl_module! { + /// The module declaration. + pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: T::Origin { + type Error = Error; + /// The minimum amount of a deposit required for a bid to be made. + const CandidateDeposit: BalanceOf = T::CandidateDeposit::get(); + + /// The amount of the unpaid reward that gets deducted in the case that either a skeptic + /// doesn't vote or someone votes in the wrong way. + const WrongSideDeduction: BalanceOf = T::WrongSideDeduction::get(); + + /// The number of times a member may vote the wrong way (or not at all, when they are a skeptic) + /// before they become suspended. + const MaxStrikes: u32 = T::MaxStrikes::get(); + + /// The amount of incentive paid within each period. Doesn't include VoterTip. + const PeriodSpend: BalanceOf = T::PeriodSpend::get(); + + /// The number of blocks between candidate/membership rotation periods. + const RotationPeriod: T::BlockNumber = T::RotationPeriod::get(); + + /// The number of blocks between membership challenges. + const ChallengePeriod: T::BlockNumber = T::ChallengePeriod::get(); + + // Used for handling module events. + fn deposit_event() = default; + + /// A user outside of the society can make a bid for entry. + /// + /// Payment: `CandidateDeposit` will be reserved for making a bid. It is returned + /// when the bid becomes a member, or if the bid calls `unbid`. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// Parameters: + /// - `value`: A one time payment the bid would like to receive when joining the society. + /// + /// # + /// Key: B (len of bids), C (len of candidates), M (len of members), X (balance reserve) + /// - Storage Reads: + /// - One storage read to check for suspended candidate. O(1) + /// - One storage read to check for suspended member. O(1) + /// - One storage read to retrieve all current bids. O(B) + /// - One storage read to retrieve all current candidates. O(C) + /// - One storage read to retrieve all members. O(M) + /// - Storage Writes: + /// - One storage mutate to add a new bid to the vector O(B) (TODO: possible optimization w/ read) + /// - Up to one storage removal if bid.len() > MAX_BID_COUNT. O(1) + /// - Notable Computation: + /// - O(B + C + log M) search to check user is not already a part of society. + /// - O(log B) search to insert the new bid sorted. + /// - External Module Operations: + /// - One balance reserve operation. O(X) + /// - Up to one balance unreserve operation if bids.len() > MAX_BID_COUNT. + /// - Events: + /// - One event for new bid. + /// - Up to one event for AutoUnbid if bid.len() > MAX_BID_COUNT. + /// + /// Total Complexity: O(M + B + C + logM + logB + X) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + pub fn bid(origin, value: BalanceOf) -> DispatchResult { + let who = ensure_signed(origin)?; + ensure!(!>::exists(&who), Error::::Suspended); + ensure!(!>::exists(&who), Error::::Suspended); + let bids = >::get(); + ensure!(!Self::is_bid(&bids, &who), Error::::AlreadyBid); + let candidates = >::get(); + ensure!(!Self::is_candidate(&candidates, &who), Error::::AlreadyCandidate); + let members = >::get(); + ensure!(!Self::is_member(&members ,&who), Error::::AlreadyMember); + + let deposit = T::CandidateDeposit::get(); + T::Currency::reserve(&who, deposit)?; + + Self::put_bid(bids, &who, value.clone(), BidKind::Deposit(deposit)); + Self::deposit_event(RawEvent::Bid(who, value)); + Ok(()) + } + + /// A bidder can remove their bid for entry into society. + /// By doing so, they will have their candidate deposit returned or + /// they will unvouch their voucher. + /// + /// Payment: The bid deposit is unreserved if the user made a bid. + /// + /// The dispatch origin for this call must be _Signed_ and a bidder. + /// + /// Parameters: + /// - `pos`: Position in the `Bids` vector of the bid who wants to unbid. + /// + /// # + /// Key: B (len of bids), X (balance unreserve) + /// - One storage read and write to retrieve and update the bids. O(B) + /// - Either one unreserve balance action O(X) or one vouching storage removal. O(1) + /// - One event. + /// + /// Total Complexity: O(B + X) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(20_000)] + pub fn unbid(origin, pos: u32) -> DispatchResult { + let who = ensure_signed(origin)?; + + let pos = pos as usize; + >::mutate(|b| + if pos < b.len() && b[pos].who == who { + // Either unreserve the deposit or free up the vouching member. + // In neither case can we do much if the action isn't completable, but there's + // no reason that either should fail. + match b.remove(pos).kind { + BidKind::Deposit(deposit) => { + let _ = T::Currency::unreserve(&who, deposit); + } + BidKind::Vouch(voucher, _) => { + >::remove(&voucher); + } + } + Self::deposit_event(RawEvent::Unbid(who)); + Ok(()) + } else { + Err(Error::::BadPosition)? + } + ) + } + + /// As a member, vouch for someone to join society by placing a bid on their behalf. + /// + /// There is no deposit required to vouch for a new bid, but a member can only vouch for + /// one bid at a time. If the bid becomes a suspended candidate and ultimately rejected by + /// the suspension judgement origin, the member will be banned from vouching again. + /// + /// As a vouching member, you can claim a tip if the candidate is accepted. This tip will + /// be paid as a portion of the reward the member will receive for joining the society. + /// + /// The dispatch origin for this call must be _Signed_ and a member. + /// + /// Parameters: + /// - `who`: The user who you would like to vouch for. + /// - `value`: The total reward to be paid between you and the candidate if they become + /// a member in the society. + /// - `tip`: Your cut of the total `value` payout when the candidate is inducted into + /// the society. Tips larger than `value` will be saturated upon payout. + /// + /// # + /// Key: B (len of bids), C (len of candidates), M (len of members) + /// - Storage Reads: + /// - One storage read to retrieve all members. O(M) + /// - One storage read to check member is not already vouching. O(1) + /// - One storage read to check for suspended candidate. O(1) + /// - One storage read to check for suspended member. O(1) + /// - One storage read to retrieve all current bids. O(B) + /// - One storage read to retrieve all current candidates. O(C) + /// - Storage Writes: + /// - One storage write to insert vouching status to the member. O(1) + /// - One storage mutate to add a new bid to the vector O(B) (TODO: possible optimization w/ read) + /// - Up to one storage removal if bid.len() > MAX_BID_COUNT. O(1) + /// - Notable Computation: + /// - O(log M) search to check sender is a member. + /// - O(B + C + log M) search to check user is not already a part of society. + /// - O(log B) search to insert the new bid sorted. + /// - External Module Operations: + /// - One balance reserve operation. O(X) + /// - Up to one balance unreserve operation if bids.len() > MAX_BID_COUNT. + /// - Events: + /// - One event for vouch. + /// - Up to one event for AutoUnbid if bid.len() > MAX_BID_COUNT. + /// + /// Total Complexity: O(M + B + C + logM + logB + X) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + pub fn vouch(origin, who: T::AccountId, value: BalanceOf, tip: BalanceOf) -> DispatchResult { + let voucher = ensure_signed(origin)?; + // Check user is not suspended. + ensure!(!>::exists(&who), Error::::Suspended); + ensure!(!>::exists(&who), Error::::Suspended); + // Check user is not a bid or candidate. + let bids = >::get(); + ensure!(!Self::is_bid(&bids, &who), Error::::AlreadyBid); + let candidates = >::get(); + ensure!(!Self::is_candidate(&candidates, &who), Error::::AlreadyCandidate); + // Check user is not already a member. + let members = >::get(); + ensure!(!Self::is_member(&members, &who), Error::::AlreadyMember); + // Check sender can vouch. + ensure!(Self::is_member(&members, &voucher), Error::::NotMember); + ensure!(!>::exists(&voucher), Error::::AlreadyVouching); + + >::insert(&voucher, VouchingStatus::Vouching); + Self::put_bid(bids, &who, value.clone(), BidKind::Vouch(voucher.clone(), tip)); + Self::deposit_event(RawEvent::Vouch(who, value, voucher)); + Ok(()) + } + + /// As a vouching member, unvouch a bid. This only works while vouched user is + /// only a bidder (and not a candidate). + /// + /// The dispatch origin for this call must be _Signed_ and a vouching member. + /// + /// Parameters: + /// - `pos`: Position in the `Bids` vector of the bid who should be unvouched. + /// + /// # + /// Key: B (len of bids) + /// - One storage read O(1) to check the signer is a vouching member. + /// - One storage mutate to retrieve and update the bids. O(B) + /// - One vouching storage removal. O(1) + /// - One event. + /// + /// Total Complexity: O(B) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(20_000)] + pub fn unvouch(origin, pos: u32) -> DispatchResult { + let voucher = ensure_signed(origin)?; + ensure!(Self::vouching(&voucher) == Some(VouchingStatus::Vouching), Error::::NotVouching); + + let pos = pos as usize; + >::mutate(|b| + if pos < b.len() { + b[pos].kind.check_voucher(&voucher)?; + >::remove(&voucher); + let who = b.remove(pos).who; + Self::deposit_event(RawEvent::Unvouch(who)); + Ok(()) + } else { + Err(Error::::BadPosition)? + } + ) + } + + /// As a member, vote on a candidate. + /// + /// The dispatch origin for this call must be _Signed_ and a member. + /// + /// Parameters: + /// - `candidate`: The candidate that the member would like to bid on. + /// - `approve`: A boolean which says if the candidate should be + /// approved (`true`) or rejected (`false`). + /// + /// # + /// Key: C (len of candidates), M (len of members) + /// - One storage read O(M) and O(log M) search to check user is a member. + /// - One account lookup. + /// - One storage read O(C) and O(C) search to check that user is a candidate. + /// - One storage write to add vote to votes. O(1) + /// - One event. + /// + /// Total Complexity: O(M + logM + C) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(30_000)] + pub fn vote(origin, candidate: ::Source, approve: bool) { + let voter = ensure_signed(origin)?; + let candidate = T::Lookup::lookup(candidate)?; + let candidates = >::get(); + ensure!(Self::is_candidate(&candidates, &candidate), Error::::NotCandidate); + let members = >::get(); + ensure!(Self::is_member(&members, &voter), Error::::NotMember); + + let vote = if approve { Vote::Approve } else { Vote::Reject }; + >::insert(&candidate, &voter, vote); + + Self::deposit_event(RawEvent::Vote(candidate, voter, approve)); + } + + /// As a member, vote on the defender. + /// + /// The dispatch origin for this call must be _Signed_ and a member. + /// + /// Parameters: + /// - `approve`: A boolean which says if the candidate should be + /// approved (`true`) or rejected (`false`). + /// + /// # + /// - Key: M (len of members) + /// - One storage read O(M) and O(log M) search to check user is a member. + /// - One storage write to add vote to votes. O(1) + /// - One event. + /// + /// Total Complexity: O(M + logM) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(20_000)] + pub fn defender_vote(origin, approve: bool) { + let voter = ensure_signed(origin)?; + let members = >::get(); + ensure!(Self::is_member(&members, &voter), Error::::NotMember); + + let vote = if approve { Vote::Approve } else { Vote::Reject }; + >::insert(&voter, vote); + + Self::deposit_event(RawEvent::DefenderVote(voter, approve)); + } + + /// Transfer the first matured payout for the sender and remove it from the records. + /// + /// NOTE: This extrinsic needs to be called multiple times to claim multiple matured payouts. + /// + /// Payment: The member will receive a payment equal to their first matured + /// payout to their free balance. + /// + /// The dispatch origin for this call must be _Signed_ and a member with + /// payouts remaining. + /// + /// # + /// Key: M (len of members), P (number of payouts for a particular member) + /// - One storage read O(M) and O(log M) search to check signer is a member. + /// - One storage read O(P) to get all payouts for a member. + /// - One storage read O(1) to get the current block number. + /// - One currency transfer call. O(X) + /// - One storage write or removal to update the member's payouts. O(P) + /// + /// Total Complexity: O(M + logM + P + X) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(30_000)] + pub fn payout(origin) { + let who = ensure_signed(origin)?; + + let members = >::get(); + ensure!(Self::is_member(&members, &who), Error::::NotMember); + + let mut payouts = >::get(&who); + if let Some((when, amount)) = payouts.first() { + if when <= &>::block_number() { + T::Currency::transfer(&Self::payouts(), &who, *amount, KeepAlive)?; + payouts.remove(0); + if payouts.is_empty() { + >::remove(&who); + } else { + >::insert(&who, payouts); + } + return Ok(()) + } + } + Err(Error::::NoPayout)? + } + + /// Found the society. + /// + /// This is done as a discrete action in order to allow for the + /// module to be included into a running chain and can only be done once. + /// + /// The dispatch origin for this call must be from the _FounderOrigin_. + /// + /// Parameters: + /// - `founder` - The first member and head of the newly founded society. + /// + /// # + /// - One storage read to check `Head`. O(1) + /// - One storage write to add the first member to society. O(1) + /// - One storage write to add new Head. O(1) + /// - One event. + /// + /// Total Complexity: O(1) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn found(origin, founder: T::AccountId) { + T::FounderOrigin::ensure_origin(origin)?; + ensure!(!>::exists(), Error::::AlreadyFounded); + // This should never fail in the context of this function... + Self::add_member(&founder)?; + >::put(&founder); + Self::deposit_event(RawEvent::Founded(founder)); + } + /// Allow suspension judgement origin to make judgement on a suspended member. + /// + /// If a suspended member is forgiven, we simply add them back as a member, not affecting + /// any of the existing storage items for that member. + /// + /// If a suspended member is rejected, remove all associated storage items, including + /// their payouts, and remove any vouched bids they currently have. + /// + /// The dispatch origin for this call must be from the _SuspensionJudgementOrigin_. + /// + /// Parameters: + /// - `who` - The suspended member to be judged. + /// - `forgive` - A boolean representing whether the suspension judgement origin + /// forgives (`true`) or rejects (`false`) a suspended member. + /// + /// # + /// Key: B (len of bids), M (len of members) + /// - One storage read to check `who` is a suspended member. O(1) + /// - Up to one storage write O(M) with O(log M) binary search to add a member back to society. + /// - Up to 3 storage removals O(1) to clean up a removed member. + /// - Up to one storage write O(B) with O(B) search to remove vouched bid from bids. + /// - Up to one additional event if unvouch takes place. + /// - One storage removal. O(1) + /// - One event for the judgement. + /// + /// Total Complexity: O(M + logM + B) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(30_000)] + fn judge_suspended_member(origin, who: T::AccountId, forgive: bool) { + T::SuspensionJudgementOrigin::ensure_origin(origin)?; + ensure!(>::exists(&who), Error::::NotSuspended); + + if forgive { + // Try to add member back to society. Can fail with `MaxMembers` limit. + Self::add_member(&who)?; + } else { + // Cancel a suspended member's membership, remove their payouts. + >::remove(&who); + >::remove(&who); + // Remove their vouching status, potentially unbanning them in the future. + if >::take(&who) == Some(VouchingStatus::Vouching) { + // Try to remove their bid if they are vouching. + // If their vouch is already a candidate, do nothing. + >::mutate(|bids| + // Try to find the matching bid + if let Some(pos) = bids.iter().position(|b| b.kind.check_voucher(&who).is_ok()) { + // Remove the bid, and emit an event + let vouched = bids.remove(pos).who; + Self::deposit_event(RawEvent::Unvouch(vouched)); + } + ); + } + } + + >::remove(&who); + Self::deposit_event(RawEvent::SuspendedMemberJudgement(who, forgive)); + } + + /// Allow suspended judgement origin to make judgement on a suspended candidate. + /// + /// If the judgement is `Approve`, we add them to society as a member with the appropriate + /// payment for joining society. + /// + /// If the judgement is `Reject`, we either slash the deposit of the bid, giving it back + /// to the society treasury, or we ban the voucher from vouching again. + /// + /// If the judgement is `Rebid`, we put the candidate back in the bid pool and let them go + /// through the induction process again. + /// + /// The dispatch origin for this call must be from the _SuspensionJudgementOrigin_. + /// + /// Parameters: + /// - `who` - The suspended candidate to be judged. + /// - `judgement` - `Approve`, `Reject`, or `Rebid`. + /// + /// # + /// Key: B (len of bids), M (len of members), X (balance action) + /// - One storage read to check `who` is a suspended candidate. + /// - One storage removal of the suspended candidate. + /// - Approve Logic + /// - One storage read to get the available pot to pay users with. O(1) + /// - One storage write to update the available pot. O(1) + /// - One storage read to get the current block number. O(1) + /// - One storage read to get all members. O(M) + /// - Up to one unreserve currency action. + /// - Up to two new storage writes to payouts. + /// - Up to one storage write with O(log M) binary search to add a member to society. + /// - Reject Logic + /// - Up to one repatriate reserved currency action. O(X) + /// - Up to one storage write to ban the vouching member from vouching again. + /// - Rebid Logic + /// - Storage mutate with O(log B) binary search to place the user back into bids. + /// - Up to one additional event if unvouch takes place. + /// - One storage removal. + /// - One event for the judgement. + /// + /// Total Complexity: O(M + logM + B + X) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn judge_suspended_candidate(origin, who: T::AccountId, judgement: Judgement) { + T::SuspensionJudgementOrigin::ensure_origin(origin)?; + if let Some((value, kind)) = >::get(&who) { + match judgement { + Judgement::Approve => { + // Suspension Judgement origin has approved this candidate + // Make sure we can pay them + let pot = Self::pot(); + ensure!(pot >= value, Error::::InsufficientPot); + // Try to add user as a member! Can fail with `MaxMember` limit. + Self::add_member(&who)?; + // Reduce next pot by payout + >::put(pot - value); + // Add payout for new candidate + let maturity = >::block_number() + + Self::lock_duration(Self::members().len() as u32); + Self::pay_accepted_candidate(&who, value, kind, maturity); + } + Judgement::Reject => { + // Founder has rejected this candidate + match kind { + BidKind::Deposit(deposit) => { + // Slash deposit and move it to the society account + let _ = T::Currency::repatriate_reserved(&who, &Self::account_id(), deposit); + } + BidKind::Vouch(voucher, _) => { + // Ban the voucher from vouching again + >::insert(&voucher, VouchingStatus::Banned); + } + } + } + Judgement::Rebid => { + // Founder has taken no judgement, and candidate is placed back into the pool. + let bids = >::get(); + Self::put_bid(bids, &who, value, kind); + } + } + + // Remove suspended candidate + >::remove(who); + } else { + Err(Error::::NotSuspended)? + } + } + + /// Allows root origin to change the maximum number of members in society. + /// Max membership count must be greater than 1. + /// + /// The dispatch origin for this call must be from _ROOT_. + /// + /// Parameters: + /// - `max` - The maximum number of members for the society. + /// + /// # + /// - One storage write to update the max. O(1) + /// - One event. + /// + /// Total Complexity: O(1) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn set_max_members(origin, max: u32) { + ensure_root(origin)?; + ensure!(max > 1, Error::::MaxMembers); + MaxMembers::::put(max); + Self::deposit_event(RawEvent::NewMaxMembers(max)); + } + + fn on_initialize(n: T::BlockNumber) { + let mut members = vec![]; + + // Run a candidate/membership rotation + if (n % T::RotationPeriod::get()).is_zero() { + members = >::get(); + Self::rotate_period(&mut members); + } + + // Run a challenge rotation + if (n % T::ChallengePeriod::get()).is_zero() { + // Only read members if not already read. + if members.is_empty() { + members = >::get(); + } + Self::rotate_challenge(&mut members); + } + } + } +} + +decl_error! { + /// Errors for this module. + pub enum Error for Module, I: Instance> { + /// An incorrect position was provided. + BadPosition, + /// User is not a member + NotMember, + /// User is already a member + AlreadyMember, + /// User is suspended + Suspended, + /// User is not suspended + NotSuspended, + /// Nothing to payout + NoPayout, + /// Society already founded + AlreadyFounded, + /// Not enough in pot to accept candidate + InsufficientPot, + /// Member is already vouching or banned from vouching again + AlreadyVouching, + /// Member is not vouching + NotVouching, + /// Cannot remove head + Head, + /// User has already made a bid + AlreadyBid, + /// User is already a candidate + AlreadyCandidate, + /// User is not a candidate + NotCandidate, + /// Too many members in the society + MaxMembers, + } +} + +decl_event! { + /// Events for this module. + pub enum Event where + AccountId = ::AccountId, + Balance = BalanceOf + { + /// The society is founded by the given identity. + Founded(AccountId), + /// A membership bid just happened. The given account is the candidate's ID and their offer + /// is the second. + Bid(AccountId, Balance), + /// A membership bid just happened by vouching. The given account is the candidate's ID and + /// their offer is the second. The vouching party is the third. + Vouch(AccountId, Balance, AccountId), + /// A candidate was dropped (due to an excess of bids in the system). + AutoUnbid(AccountId), + /// A candidate was dropped (by their request). + Unbid(AccountId), + /// A candidate was dropped (by request of who vouched for them). + Unvouch(AccountId), + /// A group of candidates have been inducted. The batch's primary is the first value, the + /// batch in full is the second. + Inducted(AccountId, Vec), + /// A suspended member has been judged + SuspendedMemberJudgement(AccountId, bool), + /// A candidate has been suspended + CandidateSuspended(AccountId), + /// A member has been suspended + MemberSuspended(AccountId), + /// A member has been challenged + Challenged(AccountId), + /// A vote has been placed (candidate, voter, vote) + Vote(AccountId, AccountId, bool), + /// A vote has been placed for a defending member (voter, vote) + DefenderVote(AccountId, bool), + /// A new max member count has been set + NewMaxMembers(u32), + } +} + +/// Pick an item at pseudo-random from the slice, given the `rng`. `None` iff the slice is empty. +fn pick_item<'a, R: RngCore, T>(rng: &mut R, items: &'a [T]) -> Option<&'a T> { + if items.is_empty() { + None + } else { + Some(&items[pick_usize(rng, items.len() - 1)]) + } +} + +/// Pick a new PRN, in the range [0, `max`] (inclusive). +fn pick_usize<'a, R: RngCore>(rng: &mut R, max: usize) -> usize { + + (rng.next_u32() % (max as u32 + 1)) as usize +} + +impl, I: Instance> Module { + /// Puts a bid into storage ordered by smallest to largest value. + /// Allows a maximum of 1000 bids in queue, removing largest value people first. + fn put_bid( + mut bids: Vec>>, + who: &T::AccountId, + value: BalanceOf, + bid_kind: BidKind> + ) { + const MAX_BID_COUNT: usize = 1000; + + match bids.binary_search_by(|bid| bid.value.cmp(&value)) { + Ok(pos) | Err(pos) => bids.insert(pos, Bid { + value, + who: who.clone(), + kind: bid_kind, + }), + } + // Keep it reasonably small. + if bids.len() > MAX_BID_COUNT { + let Bid { who: popped, kind, .. } = bids.pop().expect("b.len() > 1000; qed"); + match kind { + BidKind::Deposit(deposit) => { + let _ = T::Currency::unreserve(&popped, deposit); + } + BidKind::Vouch(voucher, _) => { + >::remove(&voucher); + } + } + Self::deposit_event(RawEvent::AutoUnbid(popped)); + } + + >::put(bids); + } + + /// Check a user is a bid. + fn is_bid(bids: &Vec>>, who: &T::AccountId) -> bool { + // Bids are ordered by `value`, so we cannot binary search for a user. + bids.iter().find(|bid| bid.who == *who).is_some() + } + + /// Check a user is a candidate. + fn is_candidate(candidates: &Vec>>, who: &T::AccountId) -> bool { + // Looking up a candidate is the same as looking up a bid + Self::is_bid(candidates, who) + } + + /// Check a user is a member. + fn is_member(members: &Vec, who: &T::AccountId) -> bool { + members.binary_search(who).is_ok() + } + + /// Add a member to the sorted members list. If the user is already a member, do nothing. + /// Can fail when `MaxMember` limit is reached, but has no side-effects. + fn add_member(who: &T::AccountId) -> DispatchResult { + let mut members = >::get(); + ensure!(members.len() < MaxMembers::::get() as usize, Error::::MaxMembers); + match members.binary_search(who) { + // Add the new member + Err(i) => { + members.insert(i, who.clone()); + T::MembershipChanged::change_members_sorted(&[who.clone()], &[], &members); + >::put(members); + Ok(()) + }, + // User is already a member, do nothing. + Ok(_) => Ok(()), + } + } + + /// Remove a member from the members list, except the Head. + /// + /// NOTE: This does not correctly clean up a member from storage. It simply + /// removes them from the Members storage item. + pub fn remove_member(m: &T::AccountId) -> DispatchResult { + ensure!(Self::head() != Some(m.clone()), Error::::Head); + + >::mutate(|members| + match members.binary_search(&m) { + Err(_) => Err(Error::::NotMember)?, + Ok(i) => { + members.remove(i); + T::MembershipChanged::change_members_sorted(&[], &[m.clone()], members); + Ok(()) + } + } + ) + } + + /// End the current period and begin a new one. + fn rotate_period(members: &mut Vec) { + let phrase = b"society_rotation"; + + let mut pot = >::get(); + + // we'll need a random seed here. + let seed = T::Randomness::random(phrase); + // seed needs to be guaranteed to be 32 bytes. + let seed = <[u8; 32]>::decode(&mut TrailingZeroInput::new(seed.as_ref())) + .expect("input is padded with zeroes; qed"); + let mut rng = ChaChaRng::from_seed(seed); + + // we assume there's at least one member or this logic won't work. + if !members.is_empty() { + let candidates = >::take(); + // NOTE: This may cause member length to surpass `MaxMembers`, but results in no consensus + // critical issues or side-effects. This is auto-correcting as members fall out of society. + members.reserve(candidates.len()); + + let maturity = >::block_number() + + Self::lock_duration(members.len() as u32); + + let mut rewardees = Vec::new(); + let mut total_approvals = 0; + let mut total_slash = >::zero(); + let mut total_payouts = >::zero(); + + let accepted = candidates.into_iter().filter_map(|Bid {value, who: candidate, kind }| { + let mut approval_count = 0; + + // Creates a vector of (vote, member) for the given candidate + // and tallies total number of approve votes for that candidate. + let votes = members.iter() + .filter_map(|m| >::take(&candidate, m).map(|v| (v, m))) + .inspect(|&(v, _)| if v == Vote::Approve { approval_count += 1 }) + .collect::>(); + + // Select one of the votes at random. + // Note that `Vote::Skeptical` and `Vote::Reject` both reject the candidate. + let is_accepted = pick_item(&mut rng, &votes).map(|x| x.0) == Some(Vote::Approve); + + let matching_vote = if is_accepted { Vote::Approve } else { Vote::Reject }; + + let bad_vote = |m: &T::AccountId| { + // Voter voted wrong way (or was just a lazy skeptic) then reduce their payout + // and increase their strikes. after MaxStrikes then they go into suspension. + let amount = Self::slash_payout(m, T::WrongSideDeduction::get()); + + let strikes = >::mutate(m, |s| { + *s += 1; + *s + }); + if strikes >= T::MaxStrikes::get() { + Self::suspend_member(m); + } + amount + }; + + // Collect the voters who had a matching vote. + rewardees.extend(votes.into_iter() + .filter_map(|(v, m)| + if v == matching_vote { Some(m) } else { + total_slash += bad_vote(m); + None + } + ).cloned() + ); + + if is_accepted { + total_approvals += approval_count; + total_payouts += value; + members.push(candidate.clone()); + + Self::pay_accepted_candidate(&candidate, value, kind, maturity); + + // We track here the total_approvals so that every candidate has a unique range + // of numbers from 0 to `total_approvals` with length `approval_count` so each + // candidate is proportionally represented when selecting a "primary" below. + Some((candidate, total_approvals)) + } else { + // Suspend Candidate + >::insert(&candidate, (value, kind)); + Self::deposit_event(RawEvent::CandidateSuspended(candidate)); + None + } + }).collect::>(); + + // Reward one of the voters who voted the right way. + if !total_slash.is_zero() { + if let Some(winner) = pick_item(&mut rng, &rewardees) { + // If we can't reward them, not much that can be done. + Self::bump_payout(winner, maturity, total_slash); + } else { + // Move the slashed amount back from payouts account to local treasury. + let _ = T::Currency::transfer(&Self::payouts(), &Self::account_id(), total_slash, AllowDeath); + } + } + + // Fund the total payouts from the local treasury. + if !total_payouts.is_zero() { + // remove payout from pot and shift needed funds to the payout account. + pot = pot.saturating_sub(total_payouts); + + // this should never fail since we ensure we can afford the payouts in a previous + // block, but there's not much we can do to recover if it fails anyway. + let _ = T::Currency::transfer(&Self::account_id(), &Self::payouts(), total_payouts, AllowDeath); + } + + // if at least one candidate was accepted... + if !accepted.is_empty() { + // select one as primary, randomly chosen from the accepted, weighted by approvals. + // Choose a random number between 0 and `total_approvals` + let primary_point = pick_usize(&mut rng, total_approvals - 1); + // Find the user who falls on that point + let primary = accepted.iter().find(|e| e.1 > primary_point) + .expect("e.1 of final item == total_approvals; \ + worst case find will always return that item; qed") + .0.clone(); + + let accounts = accepted.into_iter().map(|x| x.0).collect::>(); + + // Then write everything back out, signal the changed membership and leave an event. + members.sort(); + // NOTE: This may cause member length to surpass `MaxMembers`, but results in no consensus + // critical issues or side-effects. This is auto-correcting as members fall out of society. + >::put(&members[..]); + >::put(&primary); + + T::MembershipChanged::change_members_sorted(&accounts, &[], &members); + Self::deposit_event(RawEvent::Inducted(primary, accounts)); + } + + // Bump the pot by at most PeriodSpend, but less if there's not very much left in our + // account. + let unaccounted = T::Currency::free_balance(&Self::account_id()).saturating_sub(pot); + pot += T::PeriodSpend::get().min(unaccounted / 2u8.into()); + + >::put(&pot); + } + + // Setup the candidates for the new intake + let candidates = Self::take_selected(members.len(), pot); + >::put(&candidates); + + // Select sqrt(n) random members from the society and make them skeptics. + let pick_member = |_| pick_item(&mut rng, &members[..]).expect("exited if members empty; qed"); + for skeptic in (0..members.len().integer_sqrt()).map(pick_member) { + for Bid{ who: c, .. } in candidates.iter() { + >::insert(c, skeptic, Vote::Skeptic); + } + } + } + + /// Attempt to slash the payout of some member. Return the total amount that was deducted. + fn slash_payout(who: &T::AccountId, value: BalanceOf) -> BalanceOf { + let mut rest = value; + let mut payouts = >::get(who); + if !payouts.is_empty() { + let mut dropped = 0; + for (_, amount) in payouts.iter_mut() { + if let Some(new_rest) = rest.checked_sub(&amount) { + // not yet totally slashed after this one; drop it completely. + rest = new_rest; + dropped += 1; + } else { + // whole slash is accounted for. + *amount -= rest; + rest = Zero::zero(); + break; + } + } + >::insert(who, &payouts[dropped..]); + } + value - rest + } + + /// Bump the payout amount of `who`, to be unlocked at the given block number. + fn bump_payout(who: &T::AccountId, when: T::BlockNumber, value: BalanceOf) { + if !value.is_zero(){ + >::mutate(who, |payouts| match payouts.binary_search_by_key(&when, |x| x.0) { + Ok(index) => payouts[index].1 += value, + Err(index) => payouts.insert(index, (when, value)), + }); + } + } + + /// Suspend a user, removing them from the member list. + fn suspend_member(who: &T::AccountId) { + if Self::remove_member(&who).is_ok() { + >::insert(who, ()); + >::remove(who); + Self::deposit_event(RawEvent::MemberSuspended(who.clone())); + } + } + + /// Pay an accepted candidate their bid value. + fn pay_accepted_candidate( + candidate: &T::AccountId, + value: BalanceOf, + kind: BidKind>, + maturity: T::BlockNumber, + ) { + let value = match kind { + BidKind::Deposit(deposit) => { + // In the case that a normal deposit bid is accepted we unreserve + // the deposit. + let _ = T::Currency::unreserve(candidate, deposit); + value + } + BidKind::Vouch(voucher, tip) => { + // Check that the voucher is still vouching, else some other logic may have removed their status. + if >::take(&voucher) == Some(VouchingStatus::Vouching) { + // In the case that a vouched-for bid is accepted we unset the + // vouching status and transfer the tip over to the voucher. + Self::bump_payout(&voucher, maturity, tip.min(value)); + value.saturating_sub(tip) + } else { + value + } + } + }; + + Self::bump_payout(candidate, maturity, value); + } + + /// End the current challenge period and start a new one. + fn rotate_challenge(members: &mut Vec) { + // Assume there are members, else don't run this logic. + if !members.is_empty() { + // End current defender rotation + if let Some(defender) = Self::defender() { + let mut approval_count = 0; + let mut rejection_count = 0; + // Tallies total number of approve and reject votes for the defender. + members.iter() + .filter_map(|m| >::get(m)) + .for_each(|v| { + match v { + Vote::Approve => approval_count += 1, + _ => rejection_count += 1, + } + }); + + if approval_count <= rejection_count { + // User has failed the challenge + Self::suspend_member(&defender); + *members = Self::members(); + } + } + + // Start a new defender rotation + let phrase = b"society_challenge"; + // we'll need a random seed here. + let seed = T::Randomness::random(phrase); + // seed needs to be guaranteed to be 32 bytes. + let seed = <[u8; 32]>::decode(&mut TrailingZeroInput::new(seed.as_ref())) + .expect("input is padded with zeroes; qed"); + let mut rng = ChaChaRng::from_seed(seed); + let chosen = pick_item(&mut rng, &members).expect("exited if members empty; qed"); + + >::put(&chosen); + Self::deposit_event(RawEvent::Challenged(chosen.clone())); + } + } + + /// The account ID of the treasury pot. + /// + /// This actually does computation. If you need to keep using it, then make sure you cache the + /// value and only call this once. + pub fn account_id() -> T::AccountId { + MODULE_ID.into_account() + } + + /// The account ID of the payouts pot. This is where payouts are made from. + /// + /// This actually does computation. If you need to keep using it, then make sure you cache the + /// value and only call this once. + pub fn payouts() -> T::AccountId { + MODULE_ID.into_sub_account(b"payouts") + } + + /// Return the duration of the lock, in blocks, with the given number of members. + /// + /// This is a rather opaque calculation based on the formula here: + /// https://www.desmos.com/calculator/9itkal1tce + fn lock_duration(x: u32) -> T::BlockNumber { + let lock_pc = 100 - 50_000 / (x + 500); + Percent::from_percent(lock_pc as u8) * T::MaxLockDuration::get() + } + + /// Get a selection of bidding accounts such that the total bids is no greater than `Pot` and + /// the number of bids would not surpass `MaxMembers` if all were accepted. + /// + /// May be empty. + pub fn take_selected(members_len: usize, pot: BalanceOf) -> Vec>> + { + let max_members = MaxMembers::::get() as usize; + // No more than 10 will be returned. + let max_selections: usize = 10.min(max_members.saturating_sub(members_len)); + + // Get the number of left-most bidders whose bids add up to less than `pot`. + let mut bids = >::get(); + let taken = bids.iter() + .scan(>::zero(), |total, bid| { + *total = total.saturating_add(bid.value); + Some((*total, bid.who.clone(), bid.kind.clone())) + }) + .take(max_selections) + .take_while(|x| pot >= x.0) + .count(); + + // No need to reset Bids if we're not taking anything. + if taken > 0 { + >::put(&bids[taken..]); + } + bids.truncate(taken); + bids + } +} diff --git a/frame/society/src/mock.rs b/frame/society/src/mock.rs new file mode 100644 index 0000000000000..fc46561fd4fef --- /dev/null +++ b/frame/society/src/mock.rs @@ -0,0 +1,208 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +use super::*; + +use frame_support::{impl_outer_origin, parameter_types, ord_parameter_types}; +use sp_core::H256; +// The testing primitives are very useful for avoiding having to work with signatures +// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. +use sp_runtime::{ + Perbill, traits::{BlakeTwo256, IdentityLookup, OnInitialize, OnFinalize}, testing::Header, +}; +use frame_system::EnsureSignedBy; + +impl_outer_origin! { + pub enum Origin for Test {} +} + +// For testing the module, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of modules we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +parameter_types! { + pub const CandidateDeposit: u64 = 25; + pub const WrongSideDeduction: u64 = 2; + pub const MaxStrikes: u32 = 2; + pub const RotationPeriod: u64 = 4; + pub const PeriodSpend: u64 = 1000; + pub const MaxLockDuration: u64 = 100; + pub const ChallengePeriod: u64 = 8; + pub const MaxMembers: u32 = 100; + + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; +} + +ord_parameter_types! { + pub const FounderSetAccount: u128 = 1; + pub const SuspensionJudgementSetAccount: u128 = 2; +} + +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u128; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + type OnReapAccount = System; +} + +impl Trait for Test { + type Event = (); + type Currency = pallet_balances::Module; + type Randomness = (); + type CandidateDeposit = CandidateDeposit; + type WrongSideDeduction = WrongSideDeduction; + type MaxStrikes = MaxStrikes; + type PeriodSpend = PeriodSpend; + type MembershipChanged = (); + type RotationPeriod = RotationPeriod; + type MaxLockDuration = MaxLockDuration; + type FounderOrigin = EnsureSignedBy; + type SuspensionJudgementOrigin = EnsureSignedBy; + type ChallengePeriod = ChallengePeriod; +} + +pub type Society = Module; +pub type System = frame_system::Module; +pub type Balances = pallet_balances::Module; + +pub struct EnvBuilder { + members: Vec, + balance: u64, + balances: Vec<(u128, u64)>, + pot: u64, + max_members: u32, +} + +impl EnvBuilder { + pub fn new() -> Self { + Self { + members: vec![10], + balance: 10_000, + balances: vec![ + (10, 50), + (20, 50), + (30, 50), + (40, 50), + (50, 50), + (60, 50), + ], + pot: 0, + max_members: 100, + } + } + + pub fn execute R>(mut self, f: F) -> R { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + self.balances.push((Society::account_id(), self.balance.max(self.pot))); + pallet_balances::GenesisConfig:: { + balances: self.balances, + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + GenesisConfig::{ + members: self.members, + pot: self.pot, + max_members: self.max_members, + }.assimilate_storage(&mut t).unwrap(); + let mut ext: sp_io::TestExternalities = t.into(); + ext.execute_with(f) + } + #[allow(dead_code)] + pub fn with_members(mut self, m: Vec) -> Self { + self.members = m; + self + } + #[allow(dead_code)] + pub fn with_balances(mut self, b: Vec<(u128, u64)>) -> Self { + self.balances = b; + self + } + #[allow(dead_code)] + pub fn with_pot(mut self, p: u64) -> Self { + self.pot = p; + self + } + #[allow(dead_code)] + pub fn with_balance(mut self, b: u64) -> Self { + self.balance = b; + self + } + #[allow(dead_code)] + pub fn with_max_members(mut self, n: u32) -> Self { + self.max_members = n; + self + } +} + +/// Run until a particular block. +pub fn run_to_block(n: u64) { + while System::block_number() < n { + if System::block_number() > 1 { + System::on_finalize(System::block_number()); + } + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Society::on_initialize(System::block_number()); + } +} + +/// Creates a bid struct using input parameters. +pub fn create_bid( + value: Balance, + who: AccountId, + kind: BidKind +) -> Bid +{ + Bid { + who, + kind, + value + } +} diff --git a/frame/society/src/tests.rs b/frame/society/src/tests.rs new file mode 100644 index 0000000000000..61bb1fd232cc0 --- /dev/null +++ b/frame/society/src/tests.rs @@ -0,0 +1,744 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +use super::*; +use mock::*; + +use frame_support::{assert_ok, assert_noop}; +use sp_runtime::traits::BadOrigin; + +#[test] +fn founding_works() { + EnvBuilder::new().with_members(vec![]).execute(|| { + // Account 1 is set as the founder origin + // Account 5 cannot start a society + assert_noop!(Society::found(Origin::signed(5), 20), BadOrigin); + // Account 1 can start a society, where 10 is the founding member + assert_ok!(Society::found(Origin::signed(1), 10)); + // Society members only include 10 + assert_eq!(Society::members(), vec![10]); + // 10 is the head of the society + assert_eq!(Society::head(), Some(10)); + // Cannot start another society + assert_noop!(Society::found(Origin::signed(1), 20), Error::::AlreadyFounded); + }); +} + +#[test] +fn basic_new_member_works() { + EnvBuilder::new().execute(|| { + assert_eq!(Balances::free_balance(20), 50); + // Bid causes Candidate Deposit to be reserved. + assert_ok!(Society::bid(Origin::signed(20), 0)); + assert_eq!(Balances::free_balance(20), 25); + assert_eq!(Balances::reserved_balance(20), 25); + // Rotate period every 4 blocks + run_to_block(4); + // 20 is now a candidate + assert_eq!(Society::candidates(), vec![create_bid(0, 20, BidKind::Deposit(25))]); + // 10 (a member) can vote for the candidate + assert_ok!(Society::vote(Origin::signed(10), 20, true)); + // Rotate period every 4 blocks + run_to_block(8); + // 20 is now a member of the society + assert_eq!(Society::members(), vec![10, 20]); + // Reserved balance is returned + assert_eq!(Balances::free_balance(20), 50); + assert_eq!(Balances::reserved_balance(20), 0); + }); +} + +#[test] +fn bidding_works() { + EnvBuilder::new().execute(|| { + // Users make bids of various amounts + assert_ok!(Society::bid(Origin::signed(60), 1900)); + assert_ok!(Society::bid(Origin::signed(50), 500)); + assert_ok!(Society::bid(Origin::signed(40), 400)); + assert_ok!(Society::bid(Origin::signed(30), 300)); + // Rotate period + run_to_block(4); + // Pot is 1000 after "PeriodSpend" + assert_eq!(Society::pot(), 1000); + assert_eq!(Balances::free_balance(Society::account_id()), 10_000); + // Choose smallest bidding users whose total is less than pot + assert_eq!(Society::candidates(), vec![ + create_bid(300, 30, BidKind::Deposit(25)), + create_bid(400, 40, BidKind::Deposit(25)), + ]); + // A member votes for these candidates to join the society + assert_ok!(Society::vote(Origin::signed(10), 30, true)); + assert_ok!(Society::vote(Origin::signed(10), 40, true)); + run_to_block(8); + // Candidates become members after a period rotation + assert_eq!(Society::members(), vec![10, 30, 40]); + // Pot is increased by 1000, but pays out 700 to the members + assert_eq!(Balances::free_balance(Society::account_id()), 9_300); + assert_eq!(Society::pot(), 1_300); + // Left over from the original bids is 50 who satisfies the condition of bid less than pot. + assert_eq!(Society::candidates(), vec![ create_bid(500, 50, BidKind::Deposit(25)) ]); + // 40, now a member, can vote for 50 + assert_ok!(Society::vote(Origin::signed(40), 50, true)); + run_to_block(12); + // 50 is now a member + assert_eq!(Society::members(), vec![10, 30, 40, 50]); + // Pot is increased by 1000, and 500 is paid out. Total payout so far is 1200. + assert_eq!(Society::pot(), 1_800); + assert_eq!(Balances::free_balance(Society::account_id()), 8_800); + // No more candidates satisfy the requirements + assert_eq!(Society::candidates(), vec![]); + assert_ok!(Society::defender_vote(Origin::signed(10), true)); // Keep defender around + // Next period + run_to_block(16); + // Same members + assert_eq!(Society::members(), vec![10, 30, 40, 50]); + // Pot is increased by 1000 again + assert_eq!(Society::pot(), 2_800); + // No payouts + assert_eq!(Balances::free_balance(Society::account_id()), 8_800); + // Candidate 60 now qualifies based on the increased pot size. + assert_eq!(Society::candidates(), vec![ create_bid(1900, 60, BidKind::Deposit(25)) ]); + // Candidate 60 is voted in. + assert_ok!(Society::vote(Origin::signed(50), 60, true)); + run_to_block(20); + // 60 joins as a member + assert_eq!(Society::members(), vec![10, 30, 40, 50, 60]); + // Pay them + assert_eq!(Society::pot(), 1_900); + assert_eq!(Balances::free_balance(Society::account_id()), 6_900); + }); +} + +#[test] +fn unbidding_works() { + EnvBuilder::new().execute(|| { + // 20 and 30 make bids + assert_ok!(Society::bid(Origin::signed(20), 1000)); + assert_ok!(Society::bid(Origin::signed(30), 0)); + // Balances are reserved + assert_eq!(Balances::free_balance(30), 25); + assert_eq!(Balances::reserved_balance(30), 25); + // Must know right position to unbid + cannot unbid someone else + assert_noop!(Society::unbid(Origin::signed(30), 1), Error::::BadPosition); + // Can unbid themselves with the right position + assert_ok!(Society::unbid(Origin::signed(30), 0)); + // Balance is returned + assert_eq!(Balances::free_balance(30), 50); + assert_eq!(Balances::reserved_balance(30), 0); + // 20 wins candidacy + run_to_block(4); + assert_eq!(Society::candidates(), vec![ create_bid(1000, 20, BidKind::Deposit(25)) ]); + }); +} + +#[test] +fn payout_works() { + EnvBuilder::new().execute(|| { + // Original balance of 50 + assert_eq!(Balances::free_balance(20), 50); + assert_ok!(Society::bid(Origin::signed(20), 1000)); + run_to_block(4); + assert_ok!(Society::vote(Origin::signed(10), 20, true)); + run_to_block(8); + // payout not ready + assert_noop!(Society::payout(Origin::signed(20)), Error::::NoPayout); + run_to_block(9); + // payout should be here + assert_ok!(Society::payout(Origin::signed(20))); + assert_eq!(Balances::free_balance(20), 1050); + }); +} + +#[test] +fn basic_new_member_skeptic_works() { + EnvBuilder::new().execute(|| { + assert_eq!(Strikes::::get(10), 0); + assert_ok!(Society::bid(Origin::signed(20), 0)); + run_to_block(4); + assert_eq!(Society::candidates(), vec![create_bid(0, 20, BidKind::Deposit(25))]); + run_to_block(8); + assert_eq!(Society::members(), vec![10]); + assert_eq!(Strikes::::get(10), 1); + }); +} + +#[test] +fn basic_new_member_reject_works() { + EnvBuilder::new().execute(|| { + // Starting Balance + assert_eq!(Balances::free_balance(20), 50); + // 20 makes a bid + assert_ok!(Society::bid(Origin::signed(20), 0)); + assert_eq!(Balances::free_balance(20), 25); + assert_eq!(Balances::reserved_balance(20), 25); + // Rotation Period + run_to_block(4); + assert_eq!(Society::candidates(), vec![create_bid(0, 20, BidKind::Deposit(25))]); + // We say no + assert_ok!(Society::vote(Origin::signed(10), 20, false)); + run_to_block(8); + // User is not added as member + assert_eq!(Society::members(), vec![10]); + // User is suspended + assert_eq!(Society::candidates(), vec![]); + assert_eq!(Society::suspended_candidate(20).is_some(), true); + }); +} + +#[test] +fn slash_payout_works() { + EnvBuilder::new().execute(|| { + assert_eq!(Balances::free_balance(20), 50); + assert_ok!(Society::bid(Origin::signed(20), 1000)); + run_to_block(4); + assert_ok!(Society::vote(Origin::signed(10), 20, true)); + run_to_block(8); + // payout in queue + assert_eq!(Payouts::::get(20), vec![(9, 1000)]); + assert_noop!(Society::payout(Origin::signed(20)), Error::::NoPayout); + // slash payout + assert_eq!(Society::slash_payout(&20, 500), 500); + assert_eq!(Payouts::::get(20), vec![(9, 500)]); + run_to_block(9); + // payout should be here, but 500 less + assert_ok!(Society::payout(Origin::signed(20))); + assert_eq!(Balances::free_balance(20), 550); + }); +} + +#[test] +fn slash_payout_multi_works() { + EnvBuilder::new().execute(|| { + assert_eq!(Balances::free_balance(20), 50); + // create a few payouts + Society::bump_payout(&20, 5, 100); + Society::bump_payout(&20, 10, 100); + Society::bump_payout(&20, 15, 100); + Society::bump_payout(&20, 20, 100); + // payouts in queue + assert_eq!(Payouts::::get(20), vec![(5, 100), (10, 100), (15, 100), (20, 100)]); + // slash payout + assert_eq!(Society::slash_payout(&20, 250), 250); + assert_eq!(Payouts::::get(20), vec![(15, 50), (20, 100)]); + // slash again + assert_eq!(Society::slash_payout(&20, 50), 50); + assert_eq!(Payouts::::get(20), vec![(20, 100)]); + }); +} + +#[test] +fn suspended_member_lifecycle_works() { + EnvBuilder::new().execute(|| { + // Add 20 to members, who is not the head and can be suspended/removed. + assert_ok!(Society::add_member(&20)); + assert_eq!(>::get(), vec![10, 20]); + assert_eq!(Strikes::::get(20), 0); + assert_eq!(>::get(20), None); + + // Let's suspend account 20 by giving them 2 strikes by not voting + assert_ok!(Society::bid(Origin::signed(30), 0)); + run_to_block(8); + assert_eq!(Strikes::::get(20), 1); + assert_ok!(Society::bid(Origin::signed(40), 0)); + run_to_block(16); + + // Strike 2 is accumulated, and 20 is suspended :( + assert_eq!(>::get(20), Some(())); + assert_eq!(>::get(), vec![10]); + + // Suspended members cannot get payout + Society::bump_payout(&20, 10, 100); + assert_noop!(Society::payout(Origin::signed(20)), Error::::NotMember); + + // Normal people cannot make judgement + assert_noop!(Society::judge_suspended_member(Origin::signed(20), 20, true), BadOrigin); + + // Suspension judgment origin can judge thee + // Suspension judgement origin forgives the suspended member + assert_ok!(Society::judge_suspended_member(Origin::signed(2), 20, true)); + assert_eq!(>::get(20), None); + assert_eq!(>::get(), vec![10, 20]); + + // Let's suspend them again, directly + Society::suspend_member(&20); + assert_eq!(>::get(20), Some(())); + // Suspension judgement origin does not forgive the suspended member + assert_ok!(Society::judge_suspended_member(Origin::signed(2), 20, false)); + // Cleaned up + assert_eq!(>::get(20), None); + assert_eq!(>::get(), vec![10]); + assert_eq!(>::get(20), vec![]); + }); +} + +#[test] +fn suspended_candidate_rejected_works() { + EnvBuilder::new().execute(|| { + // Starting Balance + assert_eq!(Balances::free_balance(20), 50); + assert_eq!(Balances::free_balance(Society::account_id()), 10000); + // 20 makes a bid + assert_ok!(Society::bid(Origin::signed(20), 0)); + assert_eq!(Balances::free_balance(20), 25); + assert_eq!(Balances::reserved_balance(20), 25); + // Rotation Period + run_to_block(4); + assert_eq!(Society::candidates(), vec![create_bid(0, 20, BidKind::Deposit(25))]); + // We say no + assert_ok!(Society::vote(Origin::signed(10), 20, false)); + run_to_block(8); + // User is not added as member + assert_eq!(Society::members(), vec![10]); + // User is suspended + assert_eq!(Society::candidates(), vec![]); + assert_eq!(Society::suspended_candidate(20).is_some(), true); + + // Normal user cannot make judgement on suspended candidate + assert_noop!(Society::judge_suspended_candidate(Origin::signed(20), 20, Judgement::Approve), BadOrigin); + + // Suspension judgement origin makes no direct judgement + assert_ok!(Society::judge_suspended_candidate(Origin::signed(2), 20, Judgement::Rebid)); + // They are placed back in bid pool, repeat suspension process + // Rotation Period + run_to_block(12); + assert_eq!(Society::candidates(), vec![create_bid(0, 20, BidKind::Deposit(25))]); + // We say no + assert_ok!(Society::vote(Origin::signed(10), 20, false)); + run_to_block(16); + // User is not added as member + assert_eq!(Society::members(), vec![10]); + // User is suspended + assert_eq!(Society::candidates(), vec![]); + assert_eq!(Society::suspended_candidate(20).is_some(), true); + + // Suspension judgement origin rejects the candidate + assert_ok!(Society::judge_suspended_candidate(Origin::signed(2), 20, Judgement::Reject)); + // User is slashed + assert_eq!(Balances::free_balance(20), 25); + assert_eq!(Balances::reserved_balance(20), 0); + // Funds are deposited to society account + assert_eq!(Balances::free_balance(Society::account_id()), 10025); + // Cleaned up + assert_eq!(Society::candidates(), vec![]); + assert_eq!(>::get(20), None); + }); +} + +#[test] +fn vouch_works() { + EnvBuilder::new().execute(|| { + // 10 is the only member + assert_eq!(Society::members(), vec![10]); + // A non-member cannot vouch + assert_noop!(Society::vouch(Origin::signed(1), 20, 1000, 100), Error::::NotMember); + // A member can though + assert_ok!(Society::vouch(Origin::signed(10), 20, 1000, 100)); + assert_eq!(>::get(10), Some(VouchingStatus::Vouching)); + // A member cannot vouch twice at the same time + assert_noop!(Society::vouch(Origin::signed(10), 30, 100, 0), Error::::AlreadyVouching); + // Vouching creates the right kind of bid + assert_eq!(>::get(), vec![create_bid(1000, 20, BidKind::Vouch(10, 100))]); + // Vouched user can become candidate + run_to_block(4); + assert_eq!(Society::candidates(), vec![create_bid(1000, 20, BidKind::Vouch(10, 100))]); + // Vote yes + assert_ok!(Society::vote(Origin::signed(10), 20, true)); + // Vouched user can win + run_to_block(8); + assert_eq!(Society::members(), vec![10, 20]); + // Voucher wins a portion of the payment + assert_eq!(>::get(10), vec![(9, 100)]); + // Vouched user wins the rest + assert_eq!(>::get(20), vec![(9, 900)]); + // 10 is no longer vouching + assert_eq!(>::get(10), None); + }); +} + +#[test] +fn voucher_cannot_win_more_than_bid() { + EnvBuilder::new().execute(|| { + // 10 is the only member + assert_eq!(Society::members(), vec![10]); + // 10 vouches, but asks for more than the bid + assert_ok!(Society::vouch(Origin::signed(10), 20, 100, 1000)); + // Vouching creates the right kind of bid + assert_eq!(>::get(), vec![create_bid(100, 20, BidKind::Vouch(10, 1000))]); + // Vouched user can become candidate + run_to_block(4); + assert_eq!(Society::candidates(), vec![create_bid(100, 20, BidKind::Vouch(10, 1000))]); + // Vote yes + assert_ok!(Society::vote(Origin::signed(10), 20, true)); + // Vouched user can win + run_to_block(8); + assert_eq!(Society::members(), vec![10, 20]); + // Voucher wins as much as the bid + assert_eq!(>::get(10), vec![(9, 100)]); + // Vouched user gets nothing + assert_eq!(>::get(20), vec![]); + }); +} + +#[test] +fn unvouch_works() { + EnvBuilder::new().execute(|| { + // 10 is the only member + assert_eq!(Society::members(), vec![10]); + // 10 vouches for 20 + assert_ok!(Society::vouch(Origin::signed(10), 20, 100, 0)); + // 20 has a bid + assert_eq!(>::get(), vec![create_bid(100, 20, BidKind::Vouch(10, 0))]); + // 10 is vouched + assert_eq!(>::get(10), Some(VouchingStatus::Vouching)); + // To unvouch, you must know the right bid position + assert_noop!(Society::unvouch(Origin::signed(10), 2), Error::::BadPosition); + // 10 can unvouch with the right position + assert_ok!(Society::unvouch(Origin::signed(10), 0)); + // 20 no longer has a bid + assert_eq!(>::get(), vec![]); + // 10 is no longer vouching + assert_eq!(>::get(10), None); + + // Cannot unvouch after they become candidate + assert_ok!(Society::vouch(Origin::signed(10), 20, 100, 0)); + run_to_block(4); + assert_eq!(Society::candidates(), vec![create_bid(100, 20, BidKind::Vouch(10, 0))]); + assert_noop!(Society::unvouch(Origin::signed(10), 0), Error::::BadPosition); + // 10 is still vouching until candidate is approved or rejected + assert_eq!(>::get(10), Some(VouchingStatus::Vouching)); + run_to_block(8); + // In this case candidate is denied and suspended + assert!(Society::suspended_candidate(&20).is_some()); + assert_eq!(Society::members(), vec![10]); + // User is stuck vouching until judgement origin resolves suspended candidate + assert_eq!(>::get(10), Some(VouchingStatus::Vouching)); + // Judge denies candidate + assert_ok!(Society::judge_suspended_candidate(Origin::signed(2), 20, Judgement::Reject)); + // 10 is banned from vouching + assert_eq!(>::get(10), Some(VouchingStatus::Banned)); + assert_eq!(Society::members(), vec![10]); + + // 10 cannot vouch again + assert_noop!(Society::vouch(Origin::signed(10), 30, 100, 0), Error::::AlreadyVouching); + // 10 cannot unvouch either, so they are banned forever. + assert_noop!(Society::unvouch(Origin::signed(10), 0), Error::::NotVouching); + }); +} + +#[test] +fn unbid_vouch_works() { + EnvBuilder::new().execute(|| { + // 10 is the only member + assert_eq!(Society::members(), vec![10]); + // 10 vouches for 20 + assert_ok!(Society::vouch(Origin::signed(10), 20, 100, 0)); + // 20 has a bid + assert_eq!(>::get(), vec![create_bid(100, 20, BidKind::Vouch(10, 0))]); + // 10 is vouched + assert_eq!(>::get(10), Some(VouchingStatus::Vouching)); + // 20 doesn't want to be a member and can unbid themselves. + assert_ok!(Society::unbid(Origin::signed(20), 0)); + // Everything is cleaned up + assert_eq!(>::get(10), None); + assert_eq!(>::get(), vec![]); + }); +} + +#[test] +fn head_cannot_be_removed() { + EnvBuilder::new().execute(|| { + // 10 is the only member and head + assert_eq!(Society::members(), vec![10]); + assert_eq!(Society::head(), Some(10)); + // 10 can still accumulate strikes + assert_ok!(Society::bid(Origin::signed(20), 0)); + run_to_block(8); + assert_eq!(Strikes::::get(10), 1); + assert_ok!(Society::bid(Origin::signed(30), 0)); + run_to_block(16); + assert_eq!(Strikes::::get(10), 2); + // Awkwardly they can obtain more than MAX_STRIKES... + assert_ok!(Society::bid(Origin::signed(40), 0)); + run_to_block(24); + assert_eq!(Strikes::::get(10), 3); + + // Replace the head + assert_ok!(Society::bid(Origin::signed(50), 0)); + run_to_block(28); + assert_ok!(Society::vote(Origin::signed(10), 50, true)); + assert_ok!(Society::defender_vote(Origin::signed(10), true)); // Keep defender around + run_to_block(32); + assert_eq!(Society::members(), vec![10, 50]); + assert_eq!(Society::head(), Some(50)); + + // 10 can now be suspended for strikes + assert_ok!(Society::bid(Origin::signed(60), 0)); + run_to_block(36); + // The candidate is rejected, so voting approve will give a strike + assert_ok!(Society::vote(Origin::signed(10), 60, true)); + run_to_block(40); + assert_eq!(Strikes::::get(10), 0); + assert_eq!(>::get(10), Some(())); + assert_eq!(Society::members(), vec![50]); + }); +} + +#[test] +fn challenges_work() { + EnvBuilder::new().execute(|| { + // Add some members + assert_ok!(Society::add_member(&20)); + assert_ok!(Society::add_member(&30)); + assert_ok!(Society::add_member(&40)); + // Check starting point + assert_eq!(Society::members(), vec![10, 20, 30, 40]); + assert_eq!(Society::defender(), None); + // 20 will be challenged during the challenge rotation + run_to_block(8); + assert_eq!(Society::defender(), Some(20)); + // They can always free vote for themselves + assert_ok!(Society::defender_vote(Origin::signed(20), true)); + // If no one else votes, nothing happens + run_to_block(16); + assert_eq!(Society::members(), vec![10, 20, 30, 40]); + // New challenge period + assert_eq!(Society::defender(), Some(20)); + // Non-member cannot challenge + assert_noop!(Society::defender_vote(Origin::signed(1), true), Error::::NotMember); + // 3 people say accept, 1 reject + assert_ok!(Society::defender_vote(Origin::signed(10), true)); + assert_ok!(Society::defender_vote(Origin::signed(20), true)); + assert_ok!(Society::defender_vote(Origin::signed(30), true)); + assert_ok!(Society::defender_vote(Origin::signed(40), false)); + run_to_block(24); + // 20 survives + assert_eq!(Society::members(), vec![10, 20, 30, 40]); + // One more time + assert_eq!(Society::defender(), Some(20)); + // 2 people say accept, 2 reject + assert_ok!(Society::defender_vote(Origin::signed(10), true)); + assert_ok!(Society::defender_vote(Origin::signed(20), true)); + assert_ok!(Society::defender_vote(Origin::signed(30), false)); + assert_ok!(Society::defender_vote(Origin::signed(40), false)); + run_to_block(32); + // 20 is suspended + assert_eq!(Society::members(), vec![10, 30, 40]); + assert_eq!(Society::suspended_member(20), Some(())); + // New defender is chosen + assert_eq!(Society::defender(), Some(40)); + }); +} + +#[test] +fn bad_vote_slash_works() { + EnvBuilder::new().execute(|| { + // Add some members + assert_ok!(Society::add_member(&20)); + assert_ok!(Society::add_member(&30)); + assert_ok!(Society::add_member(&40)); + // Create some payouts + Society::bump_payout(&10, 5, 100); + Society::bump_payout(&20, 5, 100); + Society::bump_payout(&30, 5, 100); + Society::bump_payout(&40, 5, 100); + // Check starting point + assert_eq!(Society::members(), vec![10, 20, 30, 40]); + assert_eq!(>::get(10), vec![(5, 100)]); + assert_eq!(>::get(20), vec![(5, 100)]); + assert_eq!(>::get(30), vec![(5, 100)]); + assert_eq!(>::get(40), vec![(5, 100)]); + // Create a new bid + assert_ok!(Society::bid(Origin::signed(50), 1000)); + run_to_block(4); + assert_ok!(Society::vote(Origin::signed(10), 50, false)); + assert_ok!(Society::vote(Origin::signed(20), 50, true)); + assert_ok!(Society::vote(Origin::signed(30), 50, false)); + assert_ok!(Society::vote(Origin::signed(40), 50, false)); + run_to_block(8); + // Wrong voter gained a strike + assert_eq!(>::get(10), 0); + assert_eq!(>::get(20), 1); + assert_eq!(>::get(30), 0); + assert_eq!(>::get(40), 0); + // Their payout is slashed, a random person is rewarded + assert_eq!(>::get(10), vec![(5, 100), (9,2)]); + assert_eq!(>::get(20), vec![(5, 98)]); + assert_eq!(>::get(30), vec![(5, 100)]); + assert_eq!(>::get(40), vec![(5, 100)]); + }); +} + +#[test] +fn user_cannot_bid_twice() { + EnvBuilder::new().execute(|| { + // Cannot bid twice + assert_ok!(Society::bid(Origin::signed(20), 100)); + assert_noop!(Society::bid(Origin::signed(20), 100), Error::::AlreadyBid); + // Cannot bid when vouched + assert_ok!(Society::vouch(Origin::signed(10), 30, 100, 100)); + assert_noop!(Society::bid(Origin::signed(30), 100), Error::::AlreadyBid); + // Cannot vouch when already bid + assert_ok!(Society::add_member(&50)); + assert_noop!(Society::vouch(Origin::signed(50), 20, 100, 100), Error::::AlreadyBid); + }); +} + +#[test] +fn vouching_handles_removed_member_with_bid() { + EnvBuilder::new().execute(|| { + // Add a member + assert_ok!(Society::add_member(&20)); + // Have that member vouch for a user + assert_ok!(Society::vouch(Origin::signed(20), 30, 1000, 100)); + // That user is now a bid and the member is vouching + assert_eq!(>::get(), vec![create_bid(1000, 30, BidKind::Vouch(20, 100))]); + assert_eq!(>::get(20), Some(VouchingStatus::Vouching)); + // Suspend that member + Society::suspend_member(&20); + assert_eq!(>::get(20), Some(())); + // Nothing changes yet + assert_eq!(>::get(), vec![create_bid(1000, 30, BidKind::Vouch(20, 100))]); + assert_eq!(>::get(20), Some(VouchingStatus::Vouching)); + // Remove member + assert_ok!(Society::judge_suspended_member(Origin::signed(2), 20, false)); + // Bid is removed, vouching status is removed + assert_eq!(>::get(), vec![]); + assert_eq!(>::get(20), None); + }); +} + +#[test] +fn vouching_handles_removed_member_with_candidate() { + EnvBuilder::new().execute(|| { + // Add a member + assert_ok!(Society::add_member(&20)); + // Have that member vouch for a user + assert_ok!(Society::vouch(Origin::signed(20), 30, 1000, 100)); + // That user is now a bid and the member is vouching + assert_eq!(>::get(), vec![create_bid(1000, 30, BidKind::Vouch(20, 100))]); + assert_eq!(>::get(20), Some(VouchingStatus::Vouching)); + // Make that bid a candidate + run_to_block(4); + assert_eq!(Society::candidates(), vec![create_bid(1000, 30, BidKind::Vouch(20, 100))]); + // Suspend that member + Society::suspend_member(&20); + assert_eq!(>::get(20), Some(())); + // Nothing changes yet + assert_eq!(Society::candidates(), vec![create_bid(1000, 30, BidKind::Vouch(20, 100))]); + assert_eq!(>::get(20), Some(VouchingStatus::Vouching)); + // Remove member + assert_ok!(Society::judge_suspended_member(Origin::signed(2), 20, false)); + // Vouching status is removed, but candidate is still in the queue + assert_eq!(>::get(20), None); + assert_eq!(Society::candidates(), vec![create_bid(1000, 30, BidKind::Vouch(20, 100))]); + // Candidate wins + assert_ok!(Society::vote(Origin::signed(10), 30, true)); + run_to_block(8); + assert_eq!(Society::members(), vec![10, 30]); + // Payout does not go to removed member + assert_eq!(>::get(20), vec![]); + assert_eq!(>::get(30), vec![(9, 1000)]); + }); +} + +#[test] +fn votes_are_working() { + EnvBuilder::new().execute(|| { + // Users make bids of various amounts + assert_ok!(Society::bid(Origin::signed(50), 500)); + assert_ok!(Society::bid(Origin::signed(40), 400)); + assert_ok!(Society::bid(Origin::signed(30), 300)); + // Rotate period + run_to_block(4); + // A member votes for these candidates to join the society + assert_ok!(Society::vote(Origin::signed(10), 30, true)); + assert_ok!(Society::vote(Origin::signed(10), 40, true)); + // You cannot vote for a non-candidate + assert_noop!(Society::vote(Origin::signed(10), 50, true), Error::::NotCandidate); + // Votes are stored + assert_eq!(>::get(30, 10), Some(Vote::Approve)); + assert_eq!(>::get(40, 10), Some(Vote::Approve)); + assert_eq!(>::get(50, 10), None); + run_to_block(8); + // Candidates become members after a period rotation + assert_eq!(Society::members(), vec![10, 30, 40]); + // Votes are cleaned up + assert_eq!(>::get(30, 10), None); + assert_eq!(>::get(40, 10), None); + }); +} + +#[test] +fn max_limits_work() { + EnvBuilder::new().with_pot(100000).execute(|| { + // Max bids is 1000, when extra bids come in, it pops the larger ones off the stack. + // Try to put 1010 users into the bid pool + for i in (100..1110).rev() { + // Give them some funds + let _ = Balances::make_free_balance_be(&(i as u128), 1000); + assert_ok!(Society::bid(Origin::signed(i as u128), i)); + } + let bids = >::get(); + // Length is 1000 + assert_eq!(bids.len(), 1000); + // First bid is smallest number (100) + assert_eq!(bids[0], create_bid(100, 100, BidKind::Deposit(25))); + // Last bid is smallest number + 99 (1099) + assert_eq!(bids[999], create_bid(1099, 1099, BidKind::Deposit(25))); + // Rotate period + run_to_block(4); + // Max of 10 candidates + assert_eq!(Society::candidates().len(), 10); + // Fill up membership, max 100, we will do just 95 + for i in 2000..2095 { + assert_ok!(Society::add_member(&(i as u128))); + } + // Remember there was 1 original member, so 96 total + assert_eq!(Society::members().len(), 96); + // Rotate period + run_to_block(8); + // Only of 4 candidates possible now + assert_eq!(Society::candidates().len(), 4); + // Fill up members with suspended candidates from the first rotation + for i in 100..104 { + assert_ok!(Society::judge_suspended_candidate(Origin::signed(2), i, Judgement::Approve)); + } + assert_eq!(Society::members().len(), 100); + // Can't add any more members + assert_noop!(Society::add_member(&98), Error::::MaxMembers); + // However, a fringe scenario allows for in-progress candidates to increase the membership + // pool, but it has no real after-effects. + for i in Society::members().iter() { + assert_ok!(Society::vote(Origin::signed(*i), 110, true)); + assert_ok!(Society::vote(Origin::signed(*i), 111, true)); + assert_ok!(Society::vote(Origin::signed(*i), 112, true)); + } + // Rotate period + run_to_block(12); + // Members length is over 100, no problem... + assert_eq!(Society::members().len(), 103); + // No candidates because full + assert_eq!(Society::candidates().len(), 0); + // Increase member limit + assert_ok!(Society::set_max_members(Origin::ROOT, 200)); + // Rotate period + run_to_block(16); + // Candidates are back! + assert_eq!(Society::candidates().len(), 10); + }); +} diff --git a/frame/staking/Cargo.toml b/frame/staking/Cargo.toml new file mode 100644 index 0000000000000..e3e6fcbe7badf --- /dev/null +++ b/frame/staking/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "pallet-staking" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-keyring = { version = "2.0.0", optional = true, path = "../../primitives/keyring" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-phragmen = { version = "2.0.0", default-features = false, path = "../../primitives/phragmen" } +sp-io ={ path = "../../primitives/io", default-features = false } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +pallet-session = { version = "2.0.0", features = ["historical"], path = "../session", default-features = false } +pallet-authorship = { version = "2.0.0", default-features = false, path = "../authorship" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } +pallet-timestamp = { version = "2.0.0", path = "../timestamp" } +pallet-staking-reward-curve = { version = "2.0.0", path = "../staking/reward-curve" } +substrate-test-utils = { version = "2.0.0", path = "../../test-utils" } + +[features] +migrate = [] +default = ["std"] +std = [ + "serde", + "safe-mix/std", + "sp-keyring", + "codec/std", + "sp-std/std", + "sp-phragmen/std", + "sp-io/std", + "frame-support/std", + "sp-runtime/std", + "sp-staking/std", + "pallet-session/std", + "frame-system/std", + "pallet-authorship/std", +] diff --git a/frame/staking/reward-curve/Cargo.toml b/frame/staking/reward-curve/Cargo.toml new file mode 100644 index 0000000000000..0353476a955d1 --- /dev/null +++ b/frame/staking/reward-curve/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "pallet-staking-reward-curve" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "1.0.7", features = ["full", "visit"] } +quote = "1.0" +proc-macro2 = "1.0.6" +proc-macro-crate = "0.1.4" + +[dev-dependencies] +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } diff --git a/frame/staking/reward-curve/src/lib.rs b/frame/staking/reward-curve/src/lib.rs new file mode 100644 index 0000000000000..89a1980d19fd9 --- /dev/null +++ b/frame/staking/reward-curve/src/lib.rs @@ -0,0 +1,425 @@ +extern crate proc_macro; + +mod log; + +use log::log2; +use proc_macro::TokenStream; +use proc_macro2::{TokenStream as TokenStream2, Span}; +use proc_macro_crate::crate_name; +use quote::{quote, ToTokens}; +use std::convert::TryInto; +use syn::parse::{Parse, ParseStream}; + +/// Accepts a number of expressions to create a instance of PiecewiseLinear which represents the +/// NPoS curve (as detailed +/// [here](http://research.web3.foundation/en/latest/polkadot/Token%20Economics/#inflation-model)) +/// for those parameters. Parameters are: +/// - `min_inflation`: the minimal amount to be rewarded between validators, expressed as a fraction +/// of total issuance. Known as `I_0` in the literature. +/// Expressed in millionth, must be between 0 and 1_000_000. +/// +/// - `max_inflation`: the maximum amount to be rewarded between validators, expressed as a fraction +/// of total issuance. This is attained only when `ideal_stake` is achieved. +/// Expressed in millionth, must be between min_inflation and 1_000_000. +/// +/// - `ideal_stake`: the fraction of total issued tokens that should be actively staked behind +/// validators. Known as `x_ideal` in the literature. +/// Expressed in millionth, must be between 0_100_000 and 0_900_000. +/// +/// - `falloff`: Known as `decay_rate` in the literature. A co-efficient dictating the strength of +/// the global incentivisation to get the `ideal_stake`. A higher number results in less typical +/// inflation at the cost of greater volatility for validators. +/// Expressed in millionth, must be between 0 and 1_000_000. +/// +/// - `max_piece_count`: The maximum number of pieces in the curve. A greater number uses more +/// resources but results in higher accuracy. +/// Must be between 2 and 1_000. +/// +/// - `test_precision`: The maximum error allowed in the generated test. +/// Expressed in millionth, must be between 0 and 1_000_000. +/// +/// # Example +/// +/// ``` +/// # fn main() {} +/// use sp_runtime::curve::PiecewiseLinear; +/// +/// pallet_staking_reward_curve::build! { +/// const I_NPOS: PiecewiseLinear<'static> = curve!( +/// min_inflation: 0_025_000, +/// max_inflation: 0_100_000, +/// ideal_stake: 0_500_000, +/// falloff: 0_050_000, +/// max_piece_count: 40, +/// test_precision: 0_005_000, +/// ); +/// } +/// ``` +#[proc_macro] +pub fn build(input: TokenStream) -> TokenStream { + let input = syn::parse_macro_input!(input as INposInput); + + let points = compute_points(&input); + + let declaration = generate_piecewise_linear(points); + let test_module = generate_test_module(&input); + + let imports = match crate_name("sp-runtime") { + Ok(sp_runtime) => { + let ident = syn::Ident::new(&sp_runtime, Span::call_site()); + quote!( extern crate #ident as _sp_runtime; ) + }, + Err(e) => syn::Error::new(Span::call_site(), &e).to_compile_error(), + }; + + let const_name = input.ident; + let const_type = input.typ; + + quote!( + const #const_name: #const_type = { + #imports + #declaration + }; + #test_module + ).into() +} + +const MILLION: u32 = 1_000_000; + +mod keyword { + syn::custom_keyword!(curve); + syn::custom_keyword!(min_inflation); + syn::custom_keyword!(max_inflation); + syn::custom_keyword!(ideal_stake); + syn::custom_keyword!(falloff); + syn::custom_keyword!(max_piece_count); + syn::custom_keyword!(test_precision); +} + +struct INposInput { + ident: syn::Ident, + typ: syn::Type, + min_inflation: u32, + ideal_stake: u32, + max_inflation: u32, + falloff: u32, + max_piece_count: u32, + test_precision: u32, +} + +struct Bounds { + min: u32, + min_strict: bool, + max: u32, + max_strict: bool, +} + +impl Bounds { + fn check(&self, value: u32) -> bool { + let wrong = (self.min_strict && value <= self.min) + || (!self.min_strict && value < self.min) + || (self.max_strict && value >= self.max) + || (!self.max_strict && value > self.max); + + !wrong + } +} + +impl core::fmt::Display for Bounds { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!( + f, + "{}{:07}; {:07}{}", + if self.min_strict { "]" } else { "[" }, + self.min, + self.max, + if self.max_strict { "[" } else { "]" }, + ) + } +} + +fn parse_field(input: ParseStream, bounds: Bounds) + -> syn::Result +{ + ::parse(&input)?; + ::parse(&input)?; + let value_lit = syn::LitInt::parse(&input)?; + let value: u32 = value_lit.base10_parse()?; + if !bounds.check(value) { + return Err(syn::Error::new(value_lit.span(), format!( + "Invalid {}: {}, must be in {}", Token::default().to_token_stream(), value, bounds, + ))); + } + + Ok(value) +} + +impl Parse for INposInput { + fn parse(input: ParseStream) -> syn::Result { + let args_input; + + ::parse(&input)?; + let ident = ::parse(&input)?; + ::parse(&input)?; + let typ = ::parse(&input)?; + ::parse(&input)?; + ::parse(&input)?; + ::parse(&input)?; + syn::parenthesized!(args_input in input); + ::parse(&input)?; + + if !input.is_empty() { + return Err(input.error("expected end of input stream, no token expected")); + } + + let min_inflation = parse_field::(&args_input, Bounds { + min: 0, + min_strict: true, + max: 1_000_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let max_inflation = parse_field::(&args_input, Bounds { + min: min_inflation, + min_strict: true, + max: 1_000_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let ideal_stake = parse_field::(&args_input, Bounds { + min: 0_100_000, + min_strict: false, + max: 0_900_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let falloff = parse_field::(&args_input, Bounds { + min: 0_010_000, + min_strict: false, + max: 1_000_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let max_piece_count = parse_field::(&args_input, Bounds { + min: 2, + min_strict: false, + max: 1_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let test_precision = parse_field::(&args_input, Bounds { + min: 0, + min_strict: false, + max: 1_000_000, + max_strict: false, + })?; + >::parse(&args_input)?; + + if !args_input.is_empty() { + return Err(args_input.error("expected end of input stream, no token expected")); + } + + Ok(Self { + ident, + typ, + min_inflation, + ideal_stake, + max_inflation, + falloff, + max_piece_count, + test_precision, + }) + } +} + +struct INPoS { + i_0: u32, + i_ideal_times_x_ideal: u32, + i_ideal: u32, + x_ideal: u32, + d: u32, +} + +impl INPoS { + fn from_input(input: &INposInput) -> Self { + INPoS { + i_0: input.min_inflation, + i_ideal: (input.max_inflation as u64 * MILLION as u64 / input.ideal_stake as u64) + .try_into().unwrap(), + i_ideal_times_x_ideal: input.max_inflation, + x_ideal: input.ideal_stake, + d: input.falloff, + } + } + + fn compute_opposite_after_x_ideal(&self, y: u32) -> u32 { + if y == self.i_0 { + return u32::max_value(); + } + let log = log2(self.i_ideal_times_x_ideal - self.i_0, y - self.i_0); + + let term: u32 = ((self.d as u64 * log as u64) / 1_000_000).try_into().unwrap(); + + self.x_ideal + term + } +} + +fn compute_points(input: &INposInput) -> Vec<(u32, u32)> { + let inpos = INPoS::from_input(input); + + let mut points = vec![]; + points.push((0, inpos.i_0)); + points.push((inpos.x_ideal, inpos.i_ideal_times_x_ideal)); + + // For each point p: (next_p.0 - p.0) < segment_lenght && (next_p.1 - p.1) < segment_lenght. + // This ensures that the total number of segment doesn't overflow max_piece_count. + let max_length = (input.max_inflation - input.min_inflation + 1_000_000 - inpos.x_ideal) + / (input.max_piece_count - 1); + + let mut delta_y = max_length; + let mut y = input.max_inflation; + + // The algorithm divide the curve in segment with vertical len and horizontal len less + // than `max_length`. This is not very accurate in case of very consequent steep. + while delta_y != 0 { + let next_y = y - delta_y; + + if next_y <= input.min_inflation { + delta_y = delta_y.saturating_sub(1); + continue + } + + let next_x = inpos.compute_opposite_after_x_ideal(next_y); + + if (next_x - points.last().unwrap().0) > max_length { + delta_y = delta_y.saturating_sub(1); + continue + } + + if next_x >= 1_000_000 { + let prev = points.last().unwrap(); + // Compute the y corresponding to x=1_000_000 using the this point and the previous one. + + let delta_y: u32 = ( + (next_x - 1_000_000) as u64 + * (prev.1 - next_y) as u64 + / (next_x - prev.0) as u64 + ).try_into().unwrap(); + + let y = next_y + delta_y; + + points.push((1_000_000, y)); + return points; + } + points.push((next_x, next_y)); + y = next_y; + } + + points.push((1_000_000, inpos.i_0)); + + points +} + +fn generate_piecewise_linear(points: Vec<(u32, u32)>) -> TokenStream2 { + let mut points_tokens = quote!(); + + let max = points.iter() + .map(|&(_, x)| x) + .max() + .unwrap_or(0) + .checked_mul(1_000) + // clip at 1.0 for sanity only since it'll panic later if too high. + .unwrap_or(1_000_000_000); + + for (x, y) in points { + let error = || panic!(format!( + "Generated reward curve approximation doesn't fit into [0, 1] -> [0, 1] \ + because of point: + x = {:07} per million + y = {:07} per million", + x, y + )); + + let x_perbill = x.checked_mul(1_000).unwrap_or_else(error); + let y_perbill = y.checked_mul(1_000).unwrap_or_else(error); + + points_tokens.extend(quote!( + ( + _sp_runtime::Perbill::from_parts(#x_perbill), + _sp_runtime::Perbill::from_parts(#y_perbill), + ), + )); + } + + quote!( + _sp_runtime::curve::PiecewiseLinear::<'static> { + points: & [ #points_tokens ], + maximum: _sp_runtime::Perbill::from_parts(#max), + } + ) +} + +fn generate_test_module(input: &INposInput) -> TokenStream2 { + let inpos = INPoS::from_input(input); + + let ident = &input.ident; + let precision = input.test_precision; + let i_0 = inpos.i_0 as f64/ MILLION as f64; + let i_ideal_times_x_ideal = inpos.i_ideal_times_x_ideal as f64 / MILLION as f64; + let i_ideal = inpos.i_ideal as f64 / MILLION as f64; + let x_ideal = inpos.x_ideal as f64 / MILLION as f64; + let d = inpos.d as f64 / MILLION as f64; + let max_piece_count = input.max_piece_count; + + quote!( + #[cfg(test)] + mod __pallet_staking_reward_curve_test_module { + fn i_npos(x: f64) -> f64 { + if x <= #x_ideal { + #i_0 + x * (#i_ideal - #i_0 / #x_ideal) + } else { + #i_0 + (#i_ideal_times_x_ideal - #i_0) * 2_f64.powf((#x_ideal - x) / #d) + } + } + + const MILLION: u32 = 1_000_000; + + #[test] + fn reward_curve_precision() { + for &base in [MILLION, u32::max_value()].into_iter() { + let number_of_check = 100_000.min(base); + for check_index in 0..=number_of_check { + let i = (check_index as u64 * base as u64 / number_of_check as u64) as u32; + let x = i as f64 / base as f64; + let float_res = (i_npos(x) * base as f64).round() as u32; + let int_res = super::#ident.calculate_for_fraction_times_denominator(i, base); + let err = ( + (float_res.max(int_res) - float_res.min(int_res)) as u64 + * MILLION as u64 + / float_res as u64 + ) as u32; + if err > #precision { + panic!(format!("\n\ + Generated reward curve approximation differ from real one:\n\t\ + for i = {} and base = {}, f(i/base) * base = {},\n\t\ + but approximation = {},\n\t\ + err = {:07} millionth,\n\t\ + try increase the number of segment: {} or the test_error: {}.\n", + i, base, float_res, int_res, err, #max_piece_count, #precision + )); + } + } + } + } + + #[test] + fn reward_curve_piece_count() { + assert!( + super::#ident.points.len() as u32 - 1 <= #max_piece_count, + "Generated reward curve approximation is invalid: \ + has more points than specified, please fill an issue." + ); + } + } + ).into() +} diff --git a/srml/staking/reward-curve/src/log.rs b/frame/staking/reward-curve/src/log.rs similarity index 100% rename from srml/staking/reward-curve/src/log.rs rename to frame/staking/reward-curve/src/log.rs diff --git a/frame/staking/reward-curve/tests/test.rs b/frame/staking/reward-curve/tests/test.rs new file mode 100644 index 0000000000000..89f8653fe18d9 --- /dev/null +++ b/frame/staking/reward-curve/tests/test.rs @@ -0,0 +1,44 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test crate for pallet-staking-reward-curve. Allows to test for procedural macro. +//! See tests directory. + +mod test_small_falloff { + pallet_staking_reward_curve::build! { + const REWARD_CURVE: sp_runtime::curve::PiecewiseLinear<'static> = curve!( + min_inflation: 0_020_000, + max_inflation: 0_200_000, + ideal_stake: 0_600_000, + falloff: 0_010_000, + max_piece_count: 200, + test_precision: 0_005_000, + ); + } +} + +mod test_big_falloff { + pallet_staking_reward_curve::build! { + const REWARD_CURVE: sp_runtime::curve::PiecewiseLinear<'static> = curve!( + min_inflation: 0_100_000, + max_inflation: 0_400_000, + ideal_stake: 0_400_000, + falloff: 1_000_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); + } +} diff --git a/srml/staking/src/inflation.rs b/frame/staking/src/inflation.rs similarity index 75% rename from srml/staking/src/inflation.rs rename to frame/staking/src/inflation.rs index 89326b92c0fd1..9f11fa9845987 100644 --- a/srml/staking/src/inflation.rs +++ b/frame/staking/src/inflation.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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 @@ //! The staking rate in NPoS is the total amount of tokens staked by nominators and validators, //! divided by the total token supply. -use sr_primitives::{Perbill, traits::SimpleArithmetic, curve::PiecewiseLinear}; +use sp_runtime::{Perbill, traits::SimpleArithmetic, curve::PiecewiseLinear}; /// The total payout to all validators (and their nominators) per era. /// @@ -32,20 +32,24 @@ pub fn compute_total_payout( npos_token_staked: N, total_tokens: N, era_duration: u64 -) -> N where N: SimpleArithmetic + Clone -{ +) -> (N, N) where N: SimpleArithmetic + Clone { // Milliseconds per year for the Julian year (365.25 days). const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100; - Perbill::from_rational_approximation(era_duration as u64, MILLISECONDS_PER_YEAR) - * yearly_inflation.calculate_for_fraction_times_denominator(npos_token_staked, total_tokens) + let portion = Perbill::from_rational_approximation(era_duration as u64, MILLISECONDS_PER_YEAR); + let payout = portion * yearly_inflation.calculate_for_fraction_times_denominator( + npos_token_staked, + total_tokens.clone(), + ); + let maximum = portion * (yearly_inflation.maximum * total_tokens); + (payout, maximum) } #[cfg(test)] mod test { - use sr_primitives::curve::PiecewiseLinear; + use sp_runtime::curve::PiecewiseLinear; - srml_staking_reward_curve::build! { + pallet_staking_reward_curve::build! { const I_NPOS: PiecewiseLinear<'static> = curve!( min_inflation: 0_025_000, max_inflation: 0_100_000, @@ -59,26 +63,31 @@ mod test { #[test] fn npos_curve_is_sensible() { const YEAR: u64 = 365 * 24 * 60 * 60 * 1000; + + // check maximum inflation. + // not 10_000 due to rounding error. + assert_eq!(super::compute_total_payout(&I_NPOS, 0, 100_000u64, YEAR).1, 9_993); + //super::I_NPOS.calculate_for_fraction_times_denominator(25, 100) - assert_eq!(super::compute_total_payout(&I_NPOS, 0, 100_000u64, YEAR), 2_498); - assert_eq!(super::compute_total_payout(&I_NPOS, 5_000, 100_000u64, YEAR), 3_248); - assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, YEAR), 6_246); - assert_eq!(super::compute_total_payout(&I_NPOS, 40_000, 100_000u64, YEAR), 8_494); - assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, YEAR), 9_993); - assert_eq!(super::compute_total_payout(&I_NPOS, 60_000, 100_000u64, YEAR), 4_379); - assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, YEAR), 2_733); - assert_eq!(super::compute_total_payout(&I_NPOS, 95_000, 100_000u64, YEAR), 2_513); - assert_eq!(super::compute_total_payout(&I_NPOS, 100_000, 100_000u64, YEAR), 2_505); + assert_eq!(super::compute_total_payout(&I_NPOS, 0, 100_000u64, YEAR).0, 2_498); + assert_eq!(super::compute_total_payout(&I_NPOS, 5_000, 100_000u64, YEAR).0, 3_248); + assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, YEAR).0, 6_246); + assert_eq!(super::compute_total_payout(&I_NPOS, 40_000, 100_000u64, YEAR).0, 8_494); + assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, YEAR).0, 9_993); + assert_eq!(super::compute_total_payout(&I_NPOS, 60_000, 100_000u64, YEAR).0, 4_379); + assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, YEAR).0, 2_733); + assert_eq!(super::compute_total_payout(&I_NPOS, 95_000, 100_000u64, YEAR).0, 2_513); + assert_eq!(super::compute_total_payout(&I_NPOS, 100_000, 100_000u64, YEAR).0, 2_505); const DAY: u64 = 24 * 60 * 60 * 1000; - assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, DAY), 17); - assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, DAY), 27); - assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, DAY), 7); + assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, DAY).0, 17); + assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, DAY).0, 27); + assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, DAY).0, 7); const SIX_HOURS: u64 = 6 * 60 * 60 * 1000; - assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, SIX_HOURS), 4); - assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, SIX_HOURS), 7); - assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, SIX_HOURS), 2); + assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, SIX_HOURS).0, 4); + assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, SIX_HOURS).0, 7); + assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, SIX_HOURS).0, 2); const HOUR: u64 = 60 * 60 * 1000; assert_eq!( @@ -87,7 +96,7 @@ mod test { 2_500_000_000_000_000_000_000_000_000u128, 5_000_000_000_000_000_000_000_000_000u128, HOUR - ), + ).0, 57_038_500_000_000_000_000_000 ); } diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs new file mode 100644 index 0000000000000..f2f3fdfb70dee --- /dev/null +++ b/frame/staking/src/lib.rs @@ -0,0 +1,1815 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Staking Module +//! +//! The Staking module is used to manage funds at stake by network maintainers. +//! +//! - [`staking::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Overview +//! +//! The Staking module is the means by which a set of network maintainers (known as _authorities_ +//! in some contexts and _validators_ in others) are chosen based upon those who voluntarily place +//! funds under deposit. Under deposit, those funds are rewarded under normal operation but are +//! held at pain of _slash_ (expropriation) should the staked maintainer be found not to be +//! discharging its duties properly. +//! +//! ### Terminology +//! +//! +//! - Staking: The process of locking up funds for some time, placing them at risk of slashing +//! (loss) in order to become a rewarded maintainer of the network. +//! - Validating: The process of running a node to actively maintain the network, either by +//! producing blocks or guaranteeing finality of the chain. +//! - Nominating: The process of placing staked funds behind one or more validators in order to +//! share in any reward, and punishment, they take. +//! - Stash account: The account holding an owner's funds used for staking. +//! - Controller account: The account that controls an owner's funds for staking. +//! - Era: A (whole) number of sessions, which is the period that the validator set (and each +//! validator's active nominator set) is recalculated and where rewards are paid out. +//! - Slash: The punishment of a staker by reducing its funds. +//! +//! ### Goals +//! +//! +//! The staking system in Substrate NPoS is designed to make the following possible: +//! +//! - Stake funds that are controlled by a cold wallet. +//! - Withdraw some, or deposit more, funds without interrupting the role of an entity. +//! - Switch between roles (nominator, validator, idle) with minimal overhead. +//! +//! ### Scenarios +//! +//! #### Staking +//! +//! Almost any interaction with the Staking module requires a process of _**bonding**_ (also known +//! as being a _staker_). To become *bonded*, a fund-holding account known as the _stash account_, +//! which holds some or all of the funds that become frozen in place as part of the staking process, +//! is paired with an active **controller** account, which issues instructions on how they shall be +//! used. +//! +//! An account pair can become bonded using the [`bond`](./enum.Call.html#variant.bond) call. +//! +//! Stash accounts can change their associated controller using the +//! [`set_controller`](./enum.Call.html#variant.set_controller) call. +//! +//! There are three possible roles that any staked account pair can be in: `Validator`, `Nominator` +//! and `Idle` (defined in [`StakerStatus`](./enum.StakerStatus.html)). There are three +//! corresponding instructions to change between roles, namely: +//! [`validate`](./enum.Call.html#variant.validate), [`nominate`](./enum.Call.html#variant.nominate), +//! and [`chill`](./enum.Call.html#variant.chill). +//! +//! #### Validating +//! +//! A **validator** takes the role of either validating blocks or ensuring their finality, +//! maintaining the veracity of the network. A validator should avoid both any sort of malicious +//! misbehavior and going offline. Bonded accounts that state interest in being a validator do NOT +//! get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they +//! _might_ get elected at the _next era_ as a validator. The result of the election is determined +//! by nominators and their votes. +//! +//! An account can become a validator candidate via the +//! [`validate`](./enum.Call.html#variant.validate) call. +//! +//! #### Nomination +//! +//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on +//! a set of validators to be elected. Once interest in nomination is stated by an account, it +//! takes effect at the next election round. The funds in the nominator's stash account indicate the +//! _weight_ of its vote. Both the rewards and any punishment that a validator earns are shared +//! between the validator and its nominators. This rule incentivizes the nominators to NOT vote for +//! the misbehaving/offline validators as much as possible, simply because the nominators will also +//! lose funds if they vote poorly. +//! +//! An account can become a nominator via the [`nominate`](enum.Call.html#variant.nominate) call. +//! +//! #### Rewards and Slash +//! +//! The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace +//! valid behavior_ while _punishing any misbehavior or lack of availability_. +//! +//! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is +//! determined, a value is deducted from the balance of the validator and all the nominators who +//! voted for this validator (values are deducted from the _stash_ account of the slashed entity). +//! +//! Slashing logic is further described in the documentation of the `slashing` module. +//! +//! Similar to slashing, rewards are also shared among a validator and its associated nominators. +//! Yet, the reward funds are not always transferred to the stash account and can be configured. +//! See [Reward Calculation](#reward-calculation) for more details. +//! +//! #### Chilling +//! +//! Finally, any of the roles above can choose to step back temporarily and just chill for a while. +//! This means that if they are a nominator, they will not be considered as voters anymore and if +//! they are validators, they will no longer be a candidate for the next election. +//! +//! An account can step back via the [`chill`](enum.Call.html#variant.chill) call. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! The dispatchable functions of the Staking module enable the steps needed for entities to accept +//! and change their role, alongside some helper functions to get/set the metadata of the module. +//! +//! ### Public Functions +//! +//! The Staking module contains many public storage items and (im)mutable functions. +//! +//! ## Usage +//! +//! ### Example: Rewarding a validator by id. +//! +//! ``` +//! use frame_support::{decl_module, dispatch}; +//! use frame_system::{self as system, ensure_signed}; +//! use pallet_staking::{self as staking}; +//! +//! pub trait Trait: staking::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! /// Reward a validator. +//! pub fn reward_myself(origin) -> dispatch::DispatchResult { +//! let reported = ensure_signed(origin)?; +//! >::reward_by_ids(vec![(reported, 10)]); +//! Ok(()) +//! } +//! } +//! } +//! # fn main() { } +//! ``` +//! +//! ## Implementation Details +//! +//! ### Slot Stake +//! +//! The term [`SlotStake`](./struct.Module.html#method.slot_stake) will be used throughout this +//! section. It refers to a value calculated at the end of each era, containing the _minimum value +//! at stake among all validators._ Note that a validator's value at stake might be a combination +//! of the validator's own stake and the votes it received. See [`Exposure`](./struct.Exposure.html) +//! for more details. +//! +//! ### Reward Calculation +//! +//! Validators and nominators are rewarded at the end of each era. The total reward of an era is +//! calculated using the era duration and the staking rate (the total amount of tokens staked by +//! nominators and validators, divided by the total token supply). It aims to incentivise toward a +//! defined staking rate. The full specification can be found +//! [here](https://research.web3.foundation/en/latest/polkadot/Token%20Economics.html#inflation-model). +//! +//! Total reward is split among validators and their nominators depending on the number of points +//! they received during the era. Points are added to a validator using +//! [`reward_by_ids`](./enum.Call.html#variant.reward_by_ids) or +//! [`reward_by_indices`](./enum.Call.html#variant.reward_by_indices). +//! +//! [`Module`](./struct.Module.html) implements +//! [`pallet_authorship::EventHandler`](../pallet_authorship/trait.EventHandler.html) to add reward points +//! to block producer and block producer of referenced uncles. +//! +//! The validator and its nominator split their reward as following: +//! +//! The validator can declare an amount, named +//! [`commission`](./struct.ValidatorPrefs.html#structfield.commission), that does not +//! get shared with the nominators at each reward payout through its +//! [`ValidatorPrefs`](./struct.ValidatorPrefs.html). This value gets deducted from the total reward +//! that is paid to the validator and its nominators. The remaining portion is split among the +//! validator and all of the nominators that nominated the validator, proportional to the value +//! staked behind this validator (_i.e._ dividing the +//! [`own`](./struct.Exposure.html#structfield.own) or +//! [`others`](./struct.Exposure.html#structfield.others) by +//! [`total`](./struct.Exposure.html#structfield.total) in [`Exposure`](./struct.Exposure.html)). +//! +//! All entities who receive a reward have the option to choose their reward destination +//! through the [`Payee`](./struct.Payee.html) storage item (see +//! [`set_payee`](enum.Call.html#variant.set_payee)), to be one of the following: +//! +//! - Controller account, (obviously) not increasing the staked value. +//! - Stash account, not increasing the staked value. +//! - Stash account, also increasing the staked value. +//! +//! ### Additional Fund Management Operations +//! +//! Any funds already placed into stash can be the target of the following operations: +//! +//! The controller account can free a portion (or all) of the funds using the +//! [`unbond`](enum.Call.html#variant.unbond) call. Note that the funds are not immediately +//! accessible. Instead, a duration denoted by [`BondingDuration`](./struct.BondingDuration.html) +//! (in number of eras) must pass until the funds can actually be removed. Once the +//! `BondingDuration` is over, the [`withdraw_unbonded`](./enum.Call.html#variant.withdraw_unbonded) +//! call can be used to actually withdraw the funds. +//! +//! Note that there is a limitation to the number of fund-chunks that can be scheduled to be +//! unlocked in the future via [`unbond`](enum.Call.html#variant.unbond). In case this maximum +//! (`MAX_UNLOCKING_CHUNKS`) is reached, the bonded account _must_ first wait until a successful +//! call to `withdraw_unbonded` to remove some of the chunks. +//! +//! ### Election Algorithm +//! +//! The current election algorithm is implemented based on Phragmén. +//! The reference implementation can be found +//! [here](https://github.com/w3f/consensus/tree/master/NPoS). +//! +//! The election algorithm, aside from electing the validators with the most stake value and votes, +//! tries to divide the nominator votes among candidates in an equal manner. To further assure this, +//! an optional post-processing can be applied that iteratively normalizes the nominator staked +//! values until the total difference among votes of a particular nominator are less than a +//! threshold. +//! +//! ## GenesisConfig +//! +//! The Staking module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). +//! +//! ## Related Modules +//! +//! - [Balances](../pallet_balances/index.html): Used to manage values at stake. +//! - [Session](../pallet_session/index.html): Used to manage sessions. Also, a list of new validators +//! is stored in the Session module's `Validators` at the end of each era. + +#![recursion_limit="128"] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; +mod migration; +mod slashing; + +pub mod inflation; + +use sp_std::{prelude::*, result}; +use codec::{HasCompact, Encode, Decode}; +use frame_support::{ + decl_module, decl_event, decl_storage, ensure, decl_error, + weights::SimpleDispatchInfo, + traits::{ + Currency, OnFreeBalanceZero, LockIdentifier, LockableCurrency, + WithdrawReasons, OnUnbalanced, Imbalance, Get, Time + } +}; +use pallet_session::{historical::OnSessionEnding, SelectInitialValidators}; +use sp_runtime::{ + Perbill, + RuntimeDebug, + curve::PiecewiseLinear, + traits::{ + Convert, Zero, One, StaticLookup, CheckedSub, Saturating, Bounded, SaturatedConversion, + SimpleArithmetic, EnsureOrigin, + } +}; +use sp_staking::{ + SessionIndex, + offence::{OnOffenceHandler, OffenceDetails, Offence, ReportOffence}, +}; +#[cfg(feature = "std")] +use sp_runtime::{Serialize, Deserialize}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +use sp_phragmen::{ExtendedBalance, PhragmenStakedAssignment}; + +const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4; +const MAX_NOMINATIONS: usize = 16; +const MAX_UNLOCKING_CHUNKS: usize = 32; +const STAKING_ID: LockIdentifier = *b"staking "; + +/// Counter for the number of eras that have passed. +pub type EraIndex = u32; + +/// Counter for the number of "reward" points earned by a given validator. +pub type Points = u32; + +/// Reward points of an era. Used to split era total payout between validators. +#[derive(Encode, Decode, Default)] +pub struct EraPoints { + /// Total number of points. Equals the sum of reward points for each validator. + total: Points, + /// The reward points earned by a given validator. The index of this vec corresponds to the + /// index into the current validator set. + individual: Vec, +} + +impl EraPoints { + /// Add the reward to the validator at the given index. Index must be valid + /// (i.e. `index < current_elected.len()`). + fn add_points_to_index(&mut self, index: u32, points: u32) { + if let Some(new_total) = self.total.checked_add(points) { + self.total = new_total; + self.individual.resize((index as usize + 1).max(self.individual.len()), 0); + self.individual[index as usize] += points; // Addition is less than total + } + } +} + +/// Indicates the initial status of the staker. +#[derive(RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum StakerStatus { + /// Chilling. + Idle, + /// Declared desire in validating or already participating in it. + Validator, + /// Nominating for a group of other stakers. + Nominator(Vec), +} + +/// A destination account for payment. +#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug)] +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 regarding validation. +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +pub struct ValidatorPrefs { + /// Reward that validator takes up-front; only the rest is split between themselves and + /// nominators. + #[codec(compact)] + pub commission: Perbill, +} + +impl Default for ValidatorPrefs { + fn default() -> Self { + ValidatorPrefs { + commission: Default::default(), + } + } +} + +/// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked. +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +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: EraIndex, +} + +/// The ledger of a (bonded) stash. +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +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 + SimpleArithmetic, +> 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: EraIndex) -> 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 } + } + + /// Re-bond funds that were scheduled for unlocking. + fn rebond(mut self, value: Balance) -> Self { + let mut unlocking_balance: Balance = Zero::zero(); + + while let Some(last) = self.unlocking.last_mut() { + if unlocking_balance + last.value <= value { + unlocking_balance += last.value; + self.active += last.value; + self.unlocking.pop(); + } else { + let diff = value - unlocking_balance; + + unlocking_balance += diff; + self.active += diff; + last.value -= diff; + } + + if unlocking_balance >= value { + break + } + } + + self + } +} + +impl StakingLedger where + Balance: SimpleArithmetic + Saturating + Copy, +{ + /// Slash the validator for a given amount of balance. This can grow the value + /// of the slash in the case that the validator has less than `minimum_balance` + /// active funds. Returns the amount of funds actually slashed. + /// + /// Slashes from `active` funds first, and then `unlocking`, starting with the + /// chunks that are closest to unlocking. + fn slash( + &mut self, + mut value: Balance, + minimum_balance: Balance, + ) -> Balance { + let pre_total = self.total; + let total = &mut self.total; + let active = &mut self.active; + + let slash_out_of = | + total_remaining: &mut Balance, + target: &mut Balance, + value: &mut Balance, + | { + let mut slash_from_target = (*value).min(*target); + + if !slash_from_target.is_zero() { + *target -= slash_from_target; + + // don't leave a dust balance in the staking system. + if *target <= minimum_balance { + slash_from_target += *target; + *value += sp_std::mem::replace(target, Zero::zero()); + } + + *total_remaining = total_remaining.saturating_sub(slash_from_target); + *value -= slash_from_target; + } + }; + + slash_out_of(total, active, &mut value); + + let i = self.unlocking.iter_mut() + .map(|chunk| { + slash_out_of(total, &mut chunk.value, &mut value); + chunk.value + }) + .take_while(|value| value.is_zero()) // take all fully-consumed chunks out. + .count(); + + // kill all drained chunks. + let _ = self.unlocking.drain(..i); + + pre_total.saturating_sub(*total) + } +} + +/// A record of the nominations made by a specific account. +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +pub struct Nominations { + /// The targets of nomination. + pub targets: Vec, + /// The era the nominations were submitted. + pub submitted_in: EraIndex, + /// Whether the nominations have been suppressed. + pub suppressed: bool, +} + +/// The amount of exposure (to slashing) than an individual nominator has. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug)] +pub struct IndividualExposure { + /// The stash account of the nominator in question. + 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, RuntimeDebug)] +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>, +} + +/// A pending slash record. The value of the slash has been computed but not applied yet, +/// rather deferred for several eras. +#[derive(Encode, Decode, Default, RuntimeDebug)] +pub struct UnappliedSlash { + /// The stash ID of the offending validator. + validator: AccountId, + /// The validator's own slash. + own: Balance, + /// All other slashed stakers and amounts. + others: Vec<(AccountId, Balance)>, + /// Reporters of the offence; bounty payout recipients. + reporters: Vec, + /// The amount of payout. + payout: Balance, +} + +pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; +type PositiveImbalanceOf = + <::Currency as Currency<::AccountId>>::PositiveImbalance; +type NegativeImbalanceOf = + <::Currency as Currency<::AccountId>>::NegativeImbalance; +type MomentOf = <::Time as Time>::Moment; + +/// Means for interacting with a specialized version of the `session` trait. +/// +/// This is needed because `Staking` sets the `ValidatorIdOf` of the `pallet_session::Trait` +pub trait SessionInterface: frame_system::Trait { + /// Disable a given validator by stash ID. + /// + /// Returns `true` if new era should be forced at the end of this session. + /// This allows preventing a situation where there is too many validators + /// disabled and block production stalls. + fn disable_validator(validator: &AccountId) -> Result; + /// Get the validators from session. + fn validators() -> Vec; + /// Prune historical session tries up to but not including the given index. + fn prune_historical_up_to(up_to: SessionIndex); +} + +impl SessionInterface<::AccountId> for T where + T: pallet_session::Trait::AccountId>, + T: pallet_session::historical::Trait< + FullIdentification = Exposure<::AccountId, BalanceOf>, + FullIdentificationOf = ExposureOf, + >, + T::SessionHandler: pallet_session::SessionHandler<::AccountId>, + T::OnSessionEnding: pallet_session::OnSessionEnding<::AccountId>, + T::SelectInitialValidators: pallet_session::SelectInitialValidators<::AccountId>, + T::ValidatorIdOf: Convert<::AccountId, Option<::AccountId>> +{ + fn disable_validator(validator: &::AccountId) -> Result { + >::disable(validator) + } + + fn validators() -> Vec<::AccountId> { + >::validators() + } + + fn prune_historical_up_to(up_to: SessionIndex) { + >::prune_up_to(up_to); + } +} + +pub trait Trait: frame_system::Trait { + /// The staking balance. + type Currency: LockableCurrency; + + /// Time used for computing era duration. + type Time: Time; + + /// Convert a balance into a number used for election calculation. + /// This must fit into a `u64` but is allowed to be sensibly lossy. + /// TODO: #1377 + /// The backward convert should be removed as the new Phragmen API returns ratio. + /// The post-processing needs it but will be moved to off-chain. TODO: #2908 + type CurrencyToVote: Convert, u64> + Convert>; + + /// Tokens have been minted and are unused for validator-reward. + type RewardRemainder: OnUnbalanced>; + + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// Handler for the unbalanced reduction when slashing a staker. + type Slash: OnUnbalanced>; + + /// Handler for the unbalanced increment when rewarding a staker. + type Reward: OnUnbalanced>; + + /// Number of sessions per era. + type SessionsPerEra: Get; + + /// Number of eras that staked funds must remain bonded for. + type BondingDuration: Get; + + /// Number of eras that slashes are deferred by, after computation. This + /// should be less than the bonding duration. Set to 0 if slashes should be + /// applied immediately, without opportunity for intervention. + type SlashDeferDuration: Get; + + /// The origin which can cancel a deferred slash. Root can always do this. + type SlashCancelOrigin: EnsureOrigin; + + /// Interface for interacting with a session module. + type SessionInterface: self::SessionInterface; + + /// The NPoS reward curve to use. + type RewardCurve: Get<&'static PiecewiseLinear<'static>>; +} + +/// Mode of era-forcing. +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum Forcing { + /// Not forcing anything - just let whatever happen. + NotForcing, + /// Force a new era, then reset to `NotForcing` as soon as it is done. + ForceNew, + /// Avoid a new era indefinitely. + ForceNone, + /// Force a new era at the end of all sessions indefinitely. + ForceAlways, +} + +impl Default for Forcing { + fn default() -> Self { Forcing::NotForcing } +} + +decl_storage! { + trait Store for Module as Staking { + + /// The ideal number of staking participants. + pub ValidatorCount get(fn validator_count) config(): u32; + /// Minimum number of staking participants before emergency conditions are imposed. + pub MinimumValidatorCount get(fn minimum_validator_count) config(): + u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT; + + /// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're + /// easy to initialize and the performance hit is minimal (we expect no more than four + /// invulnerables) and restricted to testnets. + pub Invulnerables get(fn invulnerables) config(): Vec; + + /// Map from all locked "stash" accounts to the controller account. + pub Bonded get(fn bonded): map T::AccountId => Option; + /// Map from all (unlocked) "controller" accounts to the info regarding the staking. + pub Ledger get(fn ledger): + map T::AccountId => Option>>; + + /// Where the reward payment should be made. Keyed by stash. + pub Payee get(fn payee): map T::AccountId => RewardDestination; + + /// The map from (wannabe) validator stash key to the preferences of that validator. + pub Validators get(fn validators): linked_map T::AccountId => ValidatorPrefs; + + /// The map from nominator stash key to the set of stash keys of all validators to nominate. + /// + /// NOTE: is private so that we can ensure upgraded before all typical accesses. + /// Direct storage APIs can still bypass this protection. + Nominators get(fn nominators): linked_map T::AccountId => Option>; + + /// Nominators for a particular account that is in action right now. You can't iterate + /// through validators here, but you can find them in the Session module. + /// + /// This is keyed by the stash account. + pub Stakers get(fn stakers): map T::AccountId => Exposure>; + + /// The currently elected validator set keyed by stash account ID. + pub CurrentElected get(fn current_elected): Vec; + + /// The current era index. + pub CurrentEra get(fn current_era) config(): EraIndex; + + /// The start of the current era. + pub CurrentEraStart get(fn current_era_start): MomentOf; + + /// The session index at which the current era started. + pub CurrentEraStartSessionIndex get(fn current_era_start_session_index): SessionIndex; + + /// Rewards for the current era. Using indices of current elected set. + CurrentEraPointsEarned get(fn current_era_reward): EraPoints; + + /// The amount of balance actively at stake for each validator slot, currently. + /// + /// This is used to derive rewards and punishments. + pub SlotStake get(fn slot_stake) build(|config: &GenesisConfig| { + config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() + }): BalanceOf; + + /// True if the next session change will be a new era regardless of index. + pub ForceEra get(fn force_era) config(): Forcing; + + /// The percentage of the slash that is distributed to reporters. + /// + /// The rest of the slashed value is handled by the `Slash`. + pub SlashRewardFraction get(fn slash_reward_fraction) config(): Perbill; + + /// The amount of currency given to reporters of a slash event which was + /// canceled by extraordinary circumstances (e.g. governance). + pub CanceledSlashPayout get(fn canceled_payout) config(): BalanceOf; + + /// All unapplied slashes that are queued for later. + pub UnappliedSlashes: map EraIndex => Vec>>; + + /// A mapping from still-bonded eras to the first session index of that era. + BondedEras: Vec<(EraIndex, SessionIndex)>; + + /// All slashing events on validators, mapped by era to the highest slash proportion + /// and slash value of the era. + ValidatorSlashInEra: + double_map EraIndex, hasher(twox_128) T::AccountId => Option<(Perbill, BalanceOf)>; + + /// All slashing events on nominators, mapped by era to the highest slash value of the era. + NominatorSlashInEra: + double_map EraIndex, hasher(twox_128) T::AccountId => Option>; + + /// Slashing spans for stash accounts. + SlashingSpans: map T::AccountId => Option; + + /// Records information about the maximum slash of a stash within a slashing span, + /// as well as how much reward has been paid out. + SpanSlash: + map (T::AccountId, slashing::SpanIndex) => slashing::SpanRecord>; + + /// The earliest era for which we have a pending, unapplied slash. + EarliestUnappliedSlash: Option; + + /// The version of storage for upgrade. + StorageVersion: u32; + } + add_extra_genesis { + config(stakers): + Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; + build(|config: &GenesisConfig| { + for &(ref stash, ref controller, balance, ref status) in &config.stakers { + assert!( + T::Currency::free_balance(&stash) >= balance, + "Stash does not have enough balance to bond." + ); + let _ = >::bond( + T::Origin::from(Some(stash.clone()).into()), + T::Lookup::unlookup(controller.clone()), + balance, + RewardDestination::Staked, + ); + let _ = match status { + StakerStatus::Validator => { + >::validate( + T::Origin::from(Some(controller.clone()).into()), + Default::default(), + ) + }, + StakerStatus::Nominator(votes) => { + >::nominate( + T::Origin::from(Some(controller.clone()).into()), + votes.iter().map(|l| T::Lookup::unlookup(l.clone())).collect(), + ) + }, _ => Ok(()) + }; + } + + StorageVersion::put(migration::CURRENT_VERSION); + }); + } +} + +decl_event!( + pub enum Event where Balance = BalanceOf, ::AccountId { + /// All validators have been rewarded by the first balance; the second is the remainder + /// from the maximum amount of reward. + Reward(Balance, Balance), + /// One validator (and its nominators) has been slashed by the given amount. + Slash(AccountId, Balance), + /// An old slashing report from a prior era was discarded because it could + /// not be processed. + OldSlashingReportDiscarded(SessionIndex), + } +); + +decl_error! { + /// Error for the staking module. + pub enum Error for Module { + /// Not a controller account. + NotController, + /// Not a stash account. + NotStash, + /// Stash is already bonded. + AlreadyBonded, + /// Controller is already paired. + AlreadyPaired, + /// Targets cannot be empty. + EmptyTargets, + /// Duplicate index. + DuplicateIndex, + /// Slash record index out of bounds. + InvalidSlashIndex, + /// Can not bond with value less than minimum balance. + InsufficientValue, + /// Can not schedule more unlock chunks. + NoMoreChunks, + /// Can not rebond without unlocking chunks. + NoUnlockChunk, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Number of sessions per era. + const SessionsPerEra: SessionIndex = T::SessionsPerEra::get(); + + /// Number of eras that staked funds must remain bonded for. + const BondingDuration: EraIndex = T::BondingDuration::get(); + + type Error = Error; + + fn deposit_event() = default; + + fn on_initialize() { + Self::ensure_storage_upgraded(); + } + + fn on_finalize() { + // Set the start of the first era. + if !>::exists() { + >::put(T::Time::now()); + } + } + + /// Take the origin account as a stash and lock up `value` of its balance. `controller` will + /// be the account that controls it. + /// + /// `value` must be more than the `minimum_balance` specified by `T::Currency`. + /// + /// The dispatch origin for this call must be _Signed_ by the stash account. + /// + /// # + /// - Independent of the arguments. Moderate complexity. + /// - O(1). + /// - Three extra DB entries. + /// + /// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned unless + /// the `origin` falls below _existential deposit_ and gets removed as dust. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn bond(origin, + controller: ::Source, + #[compact] value: BalanceOf, + payee: RewardDestination + ) { + let stash = ensure_signed(origin)?; + + if >::exists(&stash) { + Err(Error::::AlreadyBonded)? + } + + let controller = T::Lookup::lookup(controller)?; + + if >::exists(&controller) { + Err(Error::::AlreadyPaired)? + } + + // reject a bond which is considered to be _dust_. + if value < T::Currency::minimum_balance() { + Err(Error::::InsufficientValue)? + } + + // You're auto-bonded forever, here. We might improve this by only bonding when + // you actually validate/nominate and remove once you unbond __everything__. + >::insert(&stash, &controller); + >::insert(&stash, payee); + + let stash_balance = T::Currency::free_balance(&stash); + let value = value.min(stash_balance); + let item = StakingLedger { stash, total: value, active: value, unlocking: vec![] }; + Self::update_ledger(&controller, &item); + } + + /// Add some extra amount that have appeared in the stash `free_balance` into the balance up + /// for staking. + /// + /// Use this if there are additional funds in your stash account that you wish to bond. + /// Unlike [`bond`] or [`unbond`] this function does not impose any limitation on the amount + /// that can be added. + /// + /// The dispatch origin for this call must be _Signed_ by the stash, not the controller. + /// + /// # + /// - Independent of the arguments. Insignificant complexity. + /// - O(1). + /// - One DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn bond_extra(origin, #[compact] max_additional: BalanceOf) { + let stash = ensure_signed(origin)?; + + let controller = Self::bonded(&stash).ok_or(Error::::NotStash)?; + let mut ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + + let stash_balance = T::Currency::free_balance(&stash); + + if let Some(extra) = stash_balance.checked_sub(&ledger.total) { + let extra = extra.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::minimum_balance(), then it is increased to the full amount. + /// + /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move + /// the funds out of management ready for transfer. + /// + /// No more than a limited number of unlocking chunks (see `MAX_UNLOCKING_CHUNKS`) + /// can co-exists at the same time. In that case, [`Call::withdraw_unbonded`] need + /// to be called first to remove some of the chunks (if possible). + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// + /// See also [`Call::withdraw_unbonded`]. + /// + /// # + /// - Independent of the arguments. Limited but potentially exploitable complexity. + /// - Contains a limited number of reads. + /// - Each call (requires the remainder of the bonded balance to be above `minimum_balance`) + /// will cause a new entry to be inserted into a vector (`Ledger.unlocking`) kept in storage. + /// The only way to clean the aforementioned storage item is also user-controlled via `withdraw_unbonded`. + /// - One DB entry. + /// + #[weight = SimpleDispatchInfo::FixedNormal(400_000)] + fn unbond(origin, #[compact] value: BalanceOf) { + let controller = ensure_signed(origin)?; + let mut ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + ensure!( + ledger.unlocking.len() < MAX_UNLOCKING_CHUNKS, + Error::::NoMoreChunks, + ); + + 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. + if ledger.active < T::Currency::minimum_balance() { + value += ledger.active; + ledger.active = Zero::zero(); + } + + let era = Self::current_era() + T::BondingDuration::get(); + 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. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// + /// See also [`Call::unbond`]. + /// + /// # + /// - Could be dependent on the `origin` argument and how much `unlocking` chunks exist. + /// It implies `consolidate_unlocked` which loops over `Ledger.unlocking`, which is + /// indirectly user-controlled. See [`unbond`] for more detail. + /// - Contains a limited number of reads, yet the size of which could be large based on `ledger`. + /// - Writes are limited to the `origin` account key. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(400_000)] + fn withdraw_unbonded(origin) { + let controller = ensure_signed(origin)?; + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + let ledger = ledger.consolidate_unlocked(Self::current_era()); + + if ledger.unlocking.is_empty() && ledger.active.is_zero() { + // This account must have called `unbond()` with some value that caused the active + // portion to fall below existential deposit + will have no more unlocking chunks + // left. We can now safely remove this. + let stash = ledger.stash; + // remove the lock. + T::Currency::remove_lock(STAKING_ID, &stash); + // remove all staking-related information. + Self::kill_stash(&stash); + } else { + // This was the consequence of a partial unbond. just update the ledger and move on. + 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. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// + /// # + /// - Independent of the arguments. Insignificant complexity. + /// - Contains a limited number of reads. + /// - Writes are limited to the `origin` account key. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(750_000)] + fn validate(origin, prefs: ValidatorPrefs) { + Self::ensure_storage_upgraded(); + + let controller = ensure_signed(origin)?; + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + let stash = &ledger.stash; + >::remove(stash); + >::insert(stash, prefs); + } + + /// Declare the desire to nominate `targets` for the origin controller. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// + /// # + /// - The transaction's complexity is proportional to the size of `targets`, + /// which is capped at `MAX_NOMINATIONS`. + /// - Both the reads and writes follow a similar pattern. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(750_000)] + fn nominate(origin, targets: Vec<::Source>) { + Self::ensure_storage_upgraded(); + + let controller = ensure_signed(origin)?; + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + let stash = &ledger.stash; + ensure!(!targets.is_empty(), Error::::EmptyTargets); + let targets = targets.into_iter() + .take(MAX_NOMINATIONS) + .map(|t| T::Lookup::lookup(t)) + .collect::, _>>()?; + + let nominations = Nominations { + targets, + submitted_in: Self::current_era(), + suppressed: false, + }; + + >::remove(stash); + >::insert(stash, &nominations); + } + + /// Declare no desire to either validate or nominate. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// + /// # + /// - Independent of the arguments. Insignificant complexity. + /// - Contains one read. + /// - Writes are limited to the `origin` account key. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn chill(origin) { + let controller = ensure_signed(origin)?; + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + Self::chill_stash(&ledger.stash); + } + + /// (Re-)set the payment target for a controller. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. + /// + /// # + /// - Independent of the arguments. Insignificant complexity. + /// - Contains a limited number of reads. + /// - Writes are limited to the `origin` account key. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn set_payee(origin, payee: RewardDestination) { + let controller = ensure_signed(origin)?; + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + let stash = &ledger.stash; + >::insert(stash, payee); + } + + /// (Re-)set the controller of a stash. + /// + /// Effects will be felt at the beginning of the next era. + /// + /// The dispatch origin for this call must be _Signed_ by the stash, not the controller. + /// + /// # + /// - Independent of the arguments. Insignificant complexity. + /// - Contains a limited number of reads. + /// - Writes are limited to the `origin` account key. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(750_000)] + fn set_controller(origin, controller: ::Source) { + let stash = ensure_signed(origin)?; + let old_controller = Self::bonded(&stash).ok_or(Error::::NotStash)?; + let controller = T::Lookup::lookup(controller)?; + if >::exists(&controller) { + Err(Error::::AlreadyPaired)? + } + if controller != old_controller { + >::insert(&stash, &controller); + if let Some(l) = >::take(&old_controller) { + >::insert(&controller, l); + } + } + } + + /// The ideal number of validators. + #[weight = SimpleDispatchInfo::FreeOperational] + fn set_validator_count(origin, #[compact] new: u32) { + ensure_root(origin)?; + ValidatorCount::put(new); + } + + // ----- Root calls. + + /// Force there to be no new eras indefinitely. + /// + /// # + /// - No arguments. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_no_eras(origin) { + ensure_root(origin)?; + ForceEra::put(Forcing::ForceNone); + } + + /// Force there to be a new era at the end of the next session. After this, it will be + /// reset to normal (non-forced) behaviour. + /// + /// # + /// - No arguments. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_new_era(origin) { + ensure_root(origin)?; + ForceEra::put(Forcing::ForceNew); + } + + /// Set the validators who cannot be slashed (if any). + #[weight = SimpleDispatchInfo::FreeOperational] + fn set_invulnerables(origin, validators: Vec) { + ensure_root(origin)?; + >::put(validators); + } + + /// Force a current staker to become completely unstaked, immediately. + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_unstake(origin, stash: T::AccountId) { + ensure_root(origin)?; + + // remove the lock. + T::Currency::remove_lock(STAKING_ID, &stash); + // remove all staking-related information. + Self::kill_stash(&stash); + } + + /// Force there to be a new era at the end of sessions indefinitely. + /// + /// # + /// - One storage write + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_new_era_always(origin) { + ensure_root(origin)?; + ForceEra::put(Forcing::ForceAlways); + } + + /// Cancel enactment of a deferred slash. Can be called by either the root origin or + /// the `T::SlashCancelOrigin`. + /// passing the era and indices of the slashes for that era to kill. + /// + /// # + /// - One storage write. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn cancel_deferred_slash(origin, era: EraIndex, slash_indices: Vec) { + T::SlashCancelOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root)?; + + let mut slash_indices = slash_indices; + slash_indices.sort_unstable(); + let mut unapplied = ::UnappliedSlashes::get(&era); + + for (removed, index) in slash_indices.into_iter().enumerate() { + let index = index as usize; + + // if `index` is not duplicate, `removed` must be <= index. + ensure!(removed <= index, Error::::DuplicateIndex); + + // all prior removals were from before this index, since the + // list is sorted. + let index = index - removed; + ensure!(index < unapplied.len(), Error::::InvalidSlashIndex); + + unapplied.remove(index); + } + + ::UnappliedSlashes::insert(&era, &unapplied); + } + + /// Rebond a portion of the stash scheduled to be unlocked. + /// + /// # + /// - Time complexity: O(1). Bounded by `MAX_UNLOCKING_CHUNKS`. + /// - Storage changes: Can't increase storage, only decrease it. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn rebond(origin, #[compact] value: BalanceOf) { + let controller = ensure_signed(origin)?; + let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + ensure!( + ledger.unlocking.len() > 0, + Error::::NoUnlockChunk, + ); + + let ledger = ledger.rebond(value); + + Self::update_ledger(&controller, &ledger); + } + } +} + +impl Module { + // PUBLIC IMMUTABLES + + /// The total balance that can be slashed from a stash account as of right now. + pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { + Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default() + } + + // MUTABLES (DANGEROUS) + + /// Update the ledger for a controller. This will also update the stash lock. The lock will + /// will lock the entire funds except paying for further transactions. + fn update_ledger( + controller: &T::AccountId, + ledger: &StakingLedger> + ) { + T::Currency::set_lock( + STAKING_ID, + &ledger.stash, + ledger.total, + T::BlockNumber::max_value(), + WithdrawReasons::all(), + ); + >::insert(controller, ledger); + } + + /// Chill a stash account. + fn chill_stash(stash: &T::AccountId) { + >::remove(stash); + >::remove(stash); + } + + /// Ensures storage is upgraded to most recent necessary state. + fn ensure_storage_upgraded() { + migration::perform_migrations::(); + } + + /// 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(stash: &T::AccountId, amount: BalanceOf) -> Option> { + let dest = Self::payee(stash); + match dest { + RewardDestination::Controller => Self::bonded(stash) + .and_then(|controller| + T::Currency::deposit_into_existing(&controller, amount).ok() + ), + RewardDestination::Stash => + T::Currency::deposit_into_existing(stash, amount).ok(), + RewardDestination::Staked => Self::bonded(stash) + .and_then(|c| Self::ledger(&c).map(|l| (c, l))) + .and_then(|(controller, mut l)| { + l.active += amount; + l.total += amount; + let r = T::Currency::deposit_into_existing(stash, amount).ok(); + Self::update_ledger(&controller, &l); + r + }), + } + } + + /// Reward a given validator by a specific amount. Add the reward to the validator's, and its + /// nominators' balance, pro-rata based on their exposure, after having removed the validator's + /// pre-payout cut. + fn reward_validator(stash: &T::AccountId, reward: BalanceOf) -> PositiveImbalanceOf { + let off_the_table = Self::validators(stash).commission * reward; + let reward = reward.saturating_sub(off_the_table); + let mut imbalance = >::zero(); + let validator_cut = if reward.is_zero() { + Zero::zero() + } else { + let exposure = Self::stakers(stash); + let total = exposure.total.max(One::one()); + + for i in &exposure.others { + let per_u64 = Perbill::from_rational_approximation(i.value, total); + imbalance.maybe_subsume(Self::make_payout(&i.who, per_u64 * reward)); + } + + let per_u64 = Perbill::from_rational_approximation(exposure.own, total); + per_u64 * reward + }; + + imbalance.maybe_subsume(Self::make_payout(stash, validator_cut + off_the_table)); + + imbalance + } + + /// Session has just ended. Provide the validator set for the next session if it's an era-end, along + /// with the exposure of the prior validator set. + fn new_session(session_index: SessionIndex) + -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> + { + let era_length = session_index.checked_sub(Self::current_era_start_session_index()).unwrap_or(0); + match ForceEra::get() { + Forcing::ForceNew => ForceEra::kill(), + Forcing::ForceAlways => (), + Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (), + _ => return None, + } + let validators = T::SessionInterface::validators(); + let prior = validators.into_iter() + .map(|v| { let e = Self::stakers(&v); (v, e) }) + .collect(); + + Self::new_era(session_index).map(move |new| (new, prior)) + } + + /// The era has changed - enact new staking set. + /// + /// 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(start_session_index: SessionIndex) -> Option> { + // Payout + let points = CurrentEraPointsEarned::take(); + let now = T::Time::now(); + let previous_era_start = >::mutate(|v| { + sp_std::mem::replace(v, now) + }); + let era_duration = now - previous_era_start; + if !era_duration.is_zero() { + let validators = Self::current_elected(); + + let validator_len: BalanceOf = (validators.len() as u32).into(); + let total_rewarded_stake = Self::slot_stake() * validator_len; + + let (total_payout, max_payout) = inflation::compute_total_payout( + &T::RewardCurve::get(), + total_rewarded_stake.clone(), + T::Currency::total_issuance(), + // Duration of era; more than u64::MAX is rewarded as u64::MAX. + era_duration.saturated_into::(), + ); + + let mut total_imbalance = >::zero(); + + for (v, p) in validators.iter().zip(points.individual.into_iter()) { + if p != 0 { + let reward = Perbill::from_rational_approximation(p, points.total) * total_payout; + total_imbalance.subsume(Self::reward_validator(v, reward)); + } + } + + // assert!(total_imbalance.peek() == total_payout) + let total_payout = total_imbalance.peek(); + + let rest = max_payout.saturating_sub(total_payout); + Self::deposit_event(RawEvent::Reward(total_payout, rest)); + + T::Reward::on_unbalanced(total_imbalance); + T::RewardRemainder::on_unbalanced(T::Currency::issue(rest)); + } + + // Increment current era. + let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); + + CurrentEraStartSessionIndex::mutate(|v| { + *v = start_session_index; + }); + let bonding_duration = T::BondingDuration::get(); + + BondedEras::mutate(|bonded| { + bonded.push((current_era, start_session_index)); + + if current_era > bonding_duration { + let first_kept = current_era - bonding_duration; + + // prune out everything that's from before the first-kept index. + let n_to_prune = bonded.iter() + .take_while(|&&(era_idx, _)| era_idx < first_kept) + .count(); + + // kill slashing metadata. + for (pruned_era, _) in bonded.drain(..n_to_prune) { + slashing::clear_era_metadata::(pruned_era); + } + + if let Some(&(_, first_session)) = bonded.first() { + T::SessionInterface::prune_historical_up_to(first_session); + } + } + }); + + // Reassign all Stakers. + let (_slot_stake, maybe_new_validators) = Self::select_validators(); + Self::apply_unapplied_slashes(current_era); + + maybe_new_validators + } + + /// Apply previously-unapplied slashes on the beginning of a new era, after a delay. + fn apply_unapplied_slashes(current_era: EraIndex) { + let slash_defer_duration = T::SlashDeferDuration::get(); + ::EarliestUnappliedSlash::mutate(|earliest| if let Some(ref mut earliest) = earliest { + let keep_from = current_era.saturating_sub(slash_defer_duration); + for era in (*earliest)..keep_from { + let era_slashes = ::UnappliedSlashes::take(&era); + for slash in era_slashes { + slashing::apply_slash::(slash); + } + } + + *earliest = (*earliest).max(keep_from) + }) + } + + /// Select a new validator set from the assembled stakers and their role preferences. + /// + /// Returns the new `SlotStake` value and a set of newly selected _stash_ IDs. + /// + /// Assumes storage is coherent with the declaration. + fn select_validators() -> (BalanceOf, Option>) { + let mut all_nominators: Vec<(T::AccountId, Vec)> = Vec::new(); + let all_validator_candidates_iter = >::enumerate(); + let all_validators = all_validator_candidates_iter.map(|(who, _pref)| { + let self_vote = (who.clone(), vec![who.clone()]); + all_nominators.push(self_vote); + who + }).collect::>(); + + let nominator_votes = >::enumerate().map(|(nominator, nominations)| { + let Nominations { submitted_in, mut targets, suppressed: _ } = nominations; + + // Filter out nomination targets which were nominated before the most recent + // slashing span. + targets.retain(|stash| { + ::SlashingSpans::get(&stash).map_or( + true, + |spans| submitted_in >= spans.last_start(), + ) + }); + + (nominator, targets) + }); + all_nominators.extend(nominator_votes); + + let maybe_phragmen_result = sp_phragmen::elect::<_, _, _, T::CurrencyToVote>( + Self::validator_count() as usize, + Self::minimum_validator_count().max(1) as usize, + all_validators, + all_nominators, + Self::slashable_balance_of, + ); + + if let Some(phragmen_result) = maybe_phragmen_result { + let elected_stashes = phragmen_result.winners.iter() + .map(|(s, _)| s.clone()) + .collect::>(); + let assignments = phragmen_result.assignments; + + let to_votes = |b: BalanceOf| + , u64>>::convert(b) as ExtendedBalance; + let to_balance = |e: ExtendedBalance| + >>::convert(e); + + let mut supports = sp_phragmen::build_support_map::<_, _, _, T::CurrencyToVote>( + &elected_stashes, + &assignments, + Self::slashable_balance_of, + ); + + // Clear Stakers. + for v in Self::current_elected().iter() { + >::remove(v); + } + + // Populate Stakers and figure out the minimum stake behind a slot. + let mut slot_stake = BalanceOf::::max_value(); + for (c, s) in supports.into_iter() { + // build `struct exposure` from `support` + let exposure = Exposure { + own: to_balance(s.own), + // This might reasonably saturate and we cannot do much about it. The sum of + // someone's stake might exceed the balance type if they have the maximum amount + // of balance and receive some support. This is super unlikely to happen, yet + // we simulate it in some tests. + total: to_balance(s.total), + others: s.others + .into_iter() + .map(|(who, value)| IndividualExposure { who, value: to_balance(value) }) + .collect::>>(), + }; + if exposure.total < slot_stake { + slot_stake = exposure.total; + } + >::insert(&c, exposure.clone()); + } + + // Update slot stake. + >::put(&slot_stake); + + // Set the new validator set in sessions. + >::put(&elected_stashes); + + // In order to keep the property required by `n_session_ending` + // that we must return the new validator set even if it's the same as the old, + // as long as any underlying economic conditions have changed, we don't attempt + // to do any optimization where we compare against the prior set. + (slot_stake, Some(elected_stashes)) + } else { + // There were not enough candidates for even our minimal level of functionality. + // This is bad. + // We should probably disable all functionality except for block production + // and let the chain keep producing blocks until we can decide on a sufficiently + // substantial set. + // TODO: #2494 + (Self::slot_stake(), None) + } + } + + /// Remove all associated data of a stash account from the staking system. + /// + /// Assumes storage is upgraded before calling. + /// + /// This is called : + /// - Immediately when an account's balance falls below existential deposit. + /// - after a `withdraw_unbond()` call that frees all of a stash's bonded balance. + fn kill_stash(stash: &T::AccountId) { + if let Some(controller) = >::take(stash) { + >::remove(&controller); + } + >::remove(stash); + >::remove(stash); + >::remove(stash); + + slashing::clear_stash_metadata::(stash); + } + + /// Add reward points to validators using their stash account ID. + /// + /// Validators are keyed by stash account ID and must be in the current elected set. + /// + /// For each element in the iterator the given number of points in u32 is added to the + /// validator, thus duplicates are handled. + /// + /// At the end of the era each the total payout will be distributed among validator + /// relatively to their points. + /// + /// COMPLEXITY: Complexity is `number_of_validator_to_reward x current_elected_len`. + /// If you need to reward lots of validator consider using `reward_by_indices`. + pub fn reward_by_ids(validators_points: impl IntoIterator) { + CurrentEraPointsEarned::mutate(|rewards| { + let current_elected = >::current_elected(); + for (validator, points) in validators_points.into_iter() { + if let Some(index) = current_elected.iter() + .position(|elected| *elected == validator) + { + rewards.add_points_to_index(index as u32, points); + } + } + }); + } + + /// Add reward points to validators using their validator index. + /// + /// For each element in the iterator the given number of points in u32 is added to the + /// validator, thus duplicates are handled. + pub fn reward_by_indices(validators_points: impl IntoIterator) { + // TODO: This can be optimised once #3302 is implemented. + let current_elected_len = >::current_elected().len() as u32; + + CurrentEraPointsEarned::mutate(|rewards| { + for (validator_index, points) in validators_points.into_iter() { + if validator_index < current_elected_len { + rewards.add_points_to_index(validator_index, points); + } + } + }); + } + + /// Ensures that at the end of the current session there will be a new era. + fn ensure_new_era() { + match ForceEra::get() { + Forcing::ForceAlways | Forcing::ForceNew => (), + _ => ForceEra::put(Forcing::ForceNew), + } + } +} + +impl pallet_session::OnSessionEnding for Module { + fn on_session_ending(_ending: SessionIndex, start_session: SessionIndex) -> Option> { + Self::ensure_storage_upgraded(); + Self::new_session(start_session - 1).map(|(new, _old)| new) + } +} + +impl OnSessionEnding>> for Module { + fn on_session_ending(_ending: SessionIndex, start_session: SessionIndex) + -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> + { + Self::ensure_storage_upgraded(); + Self::new_session(start_session - 1) + } +} + +impl OnFreeBalanceZero for Module { + fn on_free_balance_zero(stash: &T::AccountId) { + Self::ensure_storage_upgraded(); + Self::kill_stash(stash); + } +} + +/// Add reward points to block authors: +/// * 20 points to the block producer for producing a (non-uncle) block in the relay chain, +/// * 2 points to the block producer for each reference to a previously unreferenced uncle, and +/// * 1 point to the producer of each referenced uncle block. +impl pallet_authorship::EventHandler for Module { + fn note_author(author: T::AccountId) { + Self::reward_by_ids(vec![(author, 20)]); + } + fn note_uncle(author: T::AccountId, _age: T::BlockNumber) { + Self::reward_by_ids(vec![ + (>::author(), 2), + (author, 1) + ]) + } +} + +/// A `Convert` implementation that finds the stash of the given controller account, +/// if any. +pub struct StashOf(sp_std::marker::PhantomData); + +impl Convert> for StashOf { + fn convert(controller: T::AccountId) -> Option { + >::ledger(&controller).map(|l| l.stash) + } +} + +/// A typed conversion from stash account ID to the current exposure of nominators +/// on that account. +pub struct ExposureOf(sp_std::marker::PhantomData); + +impl Convert>>> + for ExposureOf +{ + fn convert(validator: T::AccountId) -> Option>> { + Some(>::stakers(&validator)) + } +} + +impl SelectInitialValidators for Module { + fn select_initial_validators() -> Option> { + >::select_validators().1 + } +} + +/// This is intended to be used with `FilterHistoricalOffences`. +impl OnOffenceHandler> for Module where + T: pallet_session::Trait::AccountId>, + T: pallet_session::historical::Trait< + FullIdentification = Exposure<::AccountId, BalanceOf>, + FullIdentificationOf = ExposureOf, + >, + T::SessionHandler: pallet_session::SessionHandler<::AccountId>, + T::OnSessionEnding: pallet_session::OnSessionEnding<::AccountId>, + T::SelectInitialValidators: pallet_session::SelectInitialValidators<::AccountId>, + T::ValidatorIdOf: Convert<::AccountId, Option<::AccountId>> +{ + fn on_offence( + offenders: &[OffenceDetails>], + slash_fraction: &[Perbill], + slash_session: SessionIndex, + ) { + >::ensure_storage_upgraded(); + + let reward_proportion = SlashRewardFraction::get(); + + let era_now = Self::current_era(); + let window_start = era_now.saturating_sub(T::BondingDuration::get()); + let current_era_start_session = CurrentEraStartSessionIndex::get(); + + // fast path for current-era report - most likely. + let slash_era = if slash_session >= current_era_start_session { + era_now + } else { + let eras = BondedEras::get(); + + // reverse because it's more likely to find reports from recent eras. + match eras.iter().rev().filter(|&&(_, ref sesh)| sesh <= &slash_session).next() { + None => return, // before bonding period. defensive - should be filtered out. + Some(&(ref slash_era, _)) => *slash_era, + } + }; + + ::EarliestUnappliedSlash::mutate(|earliest| { + if earliest.is_none() { + *earliest = Some(era_now) + } + }); + + let slash_defer_duration = T::SlashDeferDuration::get(); + + for (details, slash_fraction) in offenders.iter().zip(slash_fraction) { + let stash = &details.offender.0; + let exposure = &details.offender.1; + + // Skip if the validator is invulnerable. + if Self::invulnerables().contains(stash) { + continue + } + + let unapplied = slashing::compute_slash::(slashing::SlashParams { + stash, + slash: *slash_fraction, + exposure, + slash_era, + window_start, + now: era_now, + reward_proportion, + }); + + if let Some(mut unapplied) = unapplied { + unapplied.reporters = details.reporters.clone(); + if slash_defer_duration == 0 { + // apply right away. + slashing::apply_slash::(unapplied); + } else { + // defer to end of some `slash_defer_duration` from now. + ::UnappliedSlashes::mutate( + era_now, + move |for_later| for_later.push(unapplied), + ); + } + } + } + } +} + +/// Filter historical offences out and only allow those from the bonding period. +pub struct FilterHistoricalOffences { + _inner: sp_std::marker::PhantomData<(T, R)>, +} + +impl ReportOffence + for FilterHistoricalOffences, R> where + T: Trait, + R: ReportOffence, + O: Offence, +{ + fn report_offence(reporters: Vec, offence: O) { + >::ensure_storage_upgraded(); + + // disallow any slashing from before the current bonding period. + let offence_session = offence.session_index(); + let bonded_eras = BondedEras::get(); + + if bonded_eras.first().filter(|(_, start)| offence_session >= *start).is_some() { + R::report_offence(reporters, offence) + } else { + >::deposit_event( + RawEvent::OldSlashingReportDiscarded(offence_session) + ) + } + } +} diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs new file mode 100644 index 0000000000000..bb020b0fc0e5f --- /dev/null +++ b/frame/staking/src/migration.rs @@ -0,0 +1,88 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Storage migrations for srml-staking. + +/// Indicator of a version of a storage layout. +pub type VersionNumber = u32; + +// the current expected version of the storage +pub const CURRENT_VERSION: VersionNumber = 1; + +#[cfg(any(test, feature = "migrate"))] +mod inner { + use crate::{Store, Module, Trait}; + use frame_support::{StorageLinkedMap, StorageValue}; + use sp_std::vec::Vec; + use super::{CURRENT_VERSION, VersionNumber}; + + // the minimum supported version of the migration logic. + const MIN_SUPPORTED_VERSION: VersionNumber = 0; + + // migrate storage from v0 to v1. + // + // this upgrades the `Nominators` linked_map value type from `Vec` to + // `Option>` + pub fn to_v1(version: &mut VersionNumber) { + if *version != 0 { return } + *version += 1; + + let now = >::current_era(); + let res = as Store>::Nominators::translate::, _, _>( + |key| key, + |targets| crate::Nominations { + targets, + submitted_in: now, + suppressed: false, + }, + ); + + if let Err(e) = res { + frame_support::print("Encountered error in migration of Staking::Nominators map."); + if e.is_none() { + frame_support::print("Staking::Nominators map reinitialized"); + } + } + + frame_support::print("Finished migrating Staking storage to v1."); + } + + pub(super) fn perform_migrations() { + as Store>::StorageVersion::mutate(|version| { + if *version < MIN_SUPPORTED_VERSION { + frame_support::print("Cannot migrate staking storage because version is less than\ + minimum."); + frame_support::print(*version); + return + } + + if *version == CURRENT_VERSION { return } + + to_v1::(version); + }); + } +} + +#[cfg(not(any(test, feature = "migrate")))] +mod inner { + pub(super) fn perform_migrations() { } +} + +/// Perform all necessary storage migrations to get storage into the expected stsate for current +/// logic. No-op if fully upgraded. +pub(crate) fn perform_migrations() { + inner::perform_migrations::(); +} diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs new file mode 100644 index 0000000000000..3c238b56ed317 --- /dev/null +++ b/frame/staking/src/mock.rs @@ -0,0 +1,513 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +use std::{collections::HashSet, cell::RefCell}; +use sp_runtime::{Perbill, KeyTypeId}; +use sp_runtime::curve::PiecewiseLinear; +use sp_runtime::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize, SaturatedConversion}; +use sp_runtime::testing::{Header, UintAuthorityId}; +use sp_staking::{SessionIndex, offence::{OffenceDetails, OnOffenceHandler}}; +use sp_core::{H256, crypto::key_types}; +use sp_io; +use frame_support::{ + assert_ok, impl_outer_origin, parameter_types, StorageLinkedMap, StorageValue, + traits::{Currency, Get, FindAuthor}, + weights::Weight, +}; +use crate::{ + EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination, + Nominators, inflation +}; + +/// The AccountId alias in this test module. +pub type AccountId = u64; +pub type BlockNumber = u64; +pub type Balance = u64; + +/// Simple structure that exposes how u64 currency can be represented as... u64. +pub struct CurrencyToVoteHandler; +impl Convert for CurrencyToVoteHandler { + fn convert(x: u64) -> u64 { x } +} +impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { x.saturated_into() } +} + +thread_local! { + static SESSION: RefCell<(Vec, HashSet)> = RefCell::new(Default::default()); + static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); + static SLASH_DEFER_DURATION: RefCell = RefCell::new(0); +} + +pub struct TestSessionHandler; +impl pallet_session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[key_types::DUMMY]; + + fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} + + fn on_new_session( + _changed: bool, + validators: &[(AccountId, Ks)], + _queued_validators: &[(AccountId, Ks)], + ) { + SESSION.with(|x| + *x.borrow_mut() = (validators.iter().map(|x| x.0.clone()).collect(), HashSet::new()) + ); + } + + fn on_disabled(validator_index: usize) { + SESSION.with(|d| { + let mut d = d.borrow_mut(); + let value = d.0[validator_index]; + d.1.insert(value); + }) + } +} + +pub fn is_disabled(controller: AccountId) -> bool { + let stash = Staking::ledger(&controller).unwrap().stash; + SESSION.with(|d| d.borrow().1.contains(&stash)) +} + +pub struct ExistentialDeposit; +impl Get for ExistentialDeposit { + fn get() -> u64 { + EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) + } +} + +pub struct SlashDeferDuration; +impl Get for SlashDeferDuration { + fn get() -> EraIndex { + SLASH_DEFER_DURATION.with(|v| *v.borrow()) + } +} + +impl_outer_origin!{ + pub enum Origin for Test where system = frame_system {} +} + +/// Author of block is always 11 +pub struct Author11; +impl FindAuthor for Author11 { + fn find_author<'a, I>(_digests: I) -> Option + where I: 'a + IntoIterator + { + Some(11) + } +} + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = BlockNumber; + type Call = (); + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); +} +parameter_types! { + pub const TransferFee: Balance = 0; + pub const CreationFee: Balance = 0; +} +impl pallet_balances::Trait for Test { + type Balance = Balance; + type OnFreeBalanceZero = Staking; + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} +parameter_types! { + pub const Period: BlockNumber = 1; + pub const Offset: BlockNumber = 0; + pub const UncleGenerations: u64 = 0; + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(25); +} +impl pallet_session::Trait for Test { + type OnSessionEnding = pallet_session::historical::NoteHistoricalRoot; + type Keys = UintAuthorityId; + type ShouldEndSession = pallet_session::PeriodicSessions; + type SessionHandler = TestSessionHandler; + type Event = (); + type ValidatorId = AccountId; + type ValidatorIdOf = crate::StashOf; + type SelectInitialValidators = Staking; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; +} + +impl pallet_session::historical::Trait for Test { + type FullIdentification = crate::Exposure; + type FullIdentificationOf = crate::ExposureOf; +} +impl pallet_authorship::Trait for Test { + type FindAuthor = Author11; + type UncleGenerations = UncleGenerations; + type FilterUncle = (); + type EventHandler = Module; +} +parameter_types! { + pub const MinimumPeriod: u64 = 5; +} +impl pallet_timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; +} +pallet_staking_reward_curve::build! { + const I_NPOS: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000, + max_inflation: 0_100_000, + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} +parameter_types! { + pub const SessionsPerEra: SessionIndex = 3; + pub const BondingDuration: EraIndex = 3; + pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS; +} +impl Trait for Test { + type Currency = pallet_balances::Module; + type Time = pallet_timestamp::Module; + type CurrencyToVote = CurrencyToVoteHandler; + type RewardRemainder = (); + type Event = (); + type Slash = (); + type Reward = (); + type SessionsPerEra = SessionsPerEra; + type SlashDeferDuration = SlashDeferDuration; + type SlashCancelOrigin = frame_system::EnsureRoot; + type BondingDuration = BondingDuration; + type SessionInterface = Self; + type RewardCurve = RewardCurve; +} + +pub struct ExtBuilder { + existential_deposit: u64, + validator_pool: bool, + nominate: bool, + validator_count: u32, + minimum_validator_count: u32, + slash_defer_duration: EraIndex, + fair: bool, + num_validators: Option, + invulnerables: Vec, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + existential_deposit: 0, + validator_pool: false, + nominate: true, + validator_count: 2, + minimum_validator_count: 0, + slash_defer_duration: 0, + fair: true, + num_validators: None, + invulnerables: vec![], + } + } +} + +impl ExtBuilder { + pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { + self.existential_deposit = existential_deposit; + self + } + pub fn validator_pool(mut self, validator_pool: bool) -> Self { + self.validator_pool = validator_pool; + self + } + pub fn nominate(mut self, nominate: bool) -> Self { + 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 slash_defer_duration(mut self, eras: EraIndex) -> Self { + self.slash_defer_duration = eras; + self + } + pub fn fair(mut self, is_fair: bool) -> Self { + self.fair = is_fair; + self + } + pub fn num_validators(mut self, num_validators: u32) -> Self { + self.num_validators = Some(num_validators); + self + } + pub fn invulnerables(mut self, invulnerables: Vec) -> Self { + self.invulnerables = invulnerables; + self + } + pub fn set_associated_consts(&self) { + EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); + SLASH_DEFER_DURATION.with(|v| *v.borrow_mut() = self.slash_defer_duration); + } + pub fn build(self) -> sp_io::TestExternalities { + self.set_associated_consts(); + let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let balance_factor = if self.existential_deposit > 0 { + 256 + } else { + 1 + }; + + let num_validators = self.num_validators.unwrap_or(self.validator_count); + let validators = (0..num_validators) + .map(|x| ((x + 1) * 10 + 1) as u64) + .collect::>(); + + let _ = pallet_balances::GenesisConfig::{ + balances: 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), + (30, balance_factor), + (31, balance_factor * 2000), + (40, balance_factor), + (41, balance_factor * 2000), + (100, 2000 * balance_factor), + (101, 2000 * balance_factor), + // This allow us to have a total_payout different from 0. + (999, 1_000_000_000_000), + ], + vesting: vec![], + }.assimilate_storage(&mut storage); + + let stake_21 = if self.fair { 1000 } else { 2000 }; + let stake_31 = if self.validator_pool { balance_factor * 1000 } else { 1 }; + let status_41 = if self.validator_pool { + StakerStatus::::Validator + } else { + StakerStatus::::Idle + }; + let nominated = if self.nominate { vec![11, 21] } else { vec![] }; + let _ = GenesisConfig::{ + current_era: 0, + stakers: vec![ + // (stash, controller, staked_amount, status) + (11, 10, balance_factor * 1000, StakerStatus::::Validator), + (21, 20, stake_21, StakerStatus::::Validator), + (31, 30, stake_31, StakerStatus::::Validator), + (41, 40, balance_factor * 1000, status_41), + // nominator + (101, 100, balance_factor * 500, StakerStatus::::Nominator(nominated)) + ], + validator_count: self.validator_count, + minimum_validator_count: self.minimum_validator_count, + invulnerables: self.invulnerables, + slash_reward_fraction: Perbill::from_percent(10), + ..Default::default() + }.assimilate_storage(&mut storage); + + let _ = pallet_session::GenesisConfig:: { + keys: validators.iter().map(|x| (*x, UintAuthorityId(*x))).collect(), + }.assimilate_storage(&mut storage); + + let mut ext = sp_io::TestExternalities::from(storage); + ext.execute_with(|| { + let validators = Session::validators(); + SESSION.with(|x| + *x.borrow_mut() = (validators.clone(), HashSet::new()) + ); + }); + ext + } +} + +pub type System = frame_system::Module; +pub type Balances = pallet_balances::Module; +pub type Session = pallet_session::Module; +pub type Timestamp = pallet_timestamp::Module; +pub type Staking = Module; + +pub fn check_exposure_all() { + Staking::current_elected().into_iter().for_each(|acc| check_exposure(acc)); +} + +pub fn check_nominator_all() { + >::enumerate().for_each(|(acc, _)| check_nominator_exposure(acc)); +} + +/// Check for each selected validator: expo.total = Sum(expo.other) + expo.own +pub fn check_exposure(stash: u64) { + assert_is_stash(stash); + let expo = Staking::stakers(&stash); + assert_eq!( + expo.total as u128, expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), + "wrong total exposure for {:?}: {:?}", stash, expo, + ); +} + +/// Check that for each nominator: slashable_balance > sum(used_balance) +/// Note: we might not consume all of a nominator's balance, but we MUST NOT over spend it. +pub fn check_nominator_exposure(stash: u64) { + assert_is_stash(stash); + let mut sum = 0; + Staking::current_elected() + .iter() + .map(|v| Staking::stakers(v)) + .for_each(|e| e.others.iter() + .filter(|i| i.who == stash) + .for_each(|i| sum += i.value)); + let nominator_stake = Staking::slashable_balance_of(&stash); + // a nominator cannot over-spend. + assert!( + nominator_stake >= sum, + "failed: Nominator({}) stake({}) >= sum divided({})", stash, nominator_stake, sum, + ); +} + +pub fn assert_is_stash(acc: u64) { + assert!(Staking::bonded(&acc).is_some(), "Not a stash."); +} + +pub fn assert_ledger_consistent(stash: u64) { + assert_is_stash(stash); + let ledger = Staking::ledger(stash - 1).unwrap(); + + let real_total: Balance = ledger.unlocking.iter().fold(ledger.active, |a, c| a + c.value); + assert_eq!(real_total, ledger.total); +} + +pub fn bond_validator(acc: u64, val: u64) { + // a = controller + // a + 1 = stash + let _ = Balances::make_free_balance_be(&(acc + 1), val); + assert_ok!(Staking::bond(Origin::signed(acc + 1), acc, val, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(acc), ValidatorPrefs::default())); +} + +pub fn bond_nominator(acc: u64, val: u64, target: Vec) { + // a = controller + // a + 1 = stash + let _ = Balances::make_free_balance_be(&(acc + 1), val); + assert_ok!(Staking::bond(Origin::signed(acc + 1), acc, val, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(acc), target)); +} + +pub fn advance_session() { + let current_index = Session::current_index(); + start_session(current_index + 1); +} + +pub fn start_session(session_index: SessionIndex) { + // Compensate for session delay + let session_index = session_index + 1; + for i in Session::current_index()..session_index { + System::set_block_number((i + 1).into()); + Timestamp::set_timestamp(System::block_number() * 1000); + Session::on_initialize(System::block_number()); + } + + assert_eq!(Session::current_index(), session_index); +} + +pub fn start_era(era_index: EraIndex) { + start_session((era_index * 3).into()); + assert_eq!(Staking::current_era(), era_index); +} + +pub fn current_total_payout_for_duration(duration: u64) -> u64 { + inflation::compute_total_payout( + ::RewardCurve::get(), + >::slot_stake() * 2, + Balances::total_issuance(), + duration, + ).0 +} + +pub fn reward_all_elected() { + let rewards = >::current_elected().iter() + .map(|v| (*v, 1)) + .collect::>(); + + >::reward_by_ids(rewards) +} + +pub fn validator_controllers() -> Vec { + Session::validators().into_iter().map(|s| Staking::bonded(&s).expect("no controller for validator")).collect() +} + +pub fn on_offence_in_era( + offenders: &[OffenceDetails>], + slash_fraction: &[Perbill], + era: EraIndex, +) { + let bonded_eras = crate::BondedEras::get(); + for &(bonded_era, start_session) in bonded_eras.iter() { + if bonded_era == era { + Staking::on_offence(offenders, slash_fraction, start_session); + return + } else if bonded_era > era { + break + } + } + + if Staking::current_era() == era { + Staking::on_offence(offenders, slash_fraction, Staking::current_era_start_session_index()); + } else { + panic!("cannot slash in era {}", era); + } +} + +pub fn on_offence_now( + offenders: &[OffenceDetails>], + slash_fraction: &[Perbill], +) { + let now = Staking::current_era(); + on_offence_in_era(offenders, slash_fraction, now) +} diff --git a/frame/staking/src/slashing.rs b/frame/staking/src/slashing.rs new file mode 100644 index 0000000000000..6d591603fdbcc --- /dev/null +++ b/frame/staking/src/slashing.rs @@ -0,0 +1,824 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A slashing implementation for NPoS systems. +//! +//! For the purposes of the economic model, it is easiest to think of each validator +//! of a nominator which nominates only its own identity. +//! +//! The act of nomination signals intent to unify economic identity with the validator - to take part in the +//! rewards of a job well done, and to take part in the punishment of a job done badly. +//! +//! There are 3 main difficulties to account for with slashing in NPoS: +//! - A nominator can nominate multiple validators and be slashed via any of them. +//! - Until slashed, stake is reused from era to era. Nominating with N coins for E eras in a row +//! does not mean you have N*E coins to be slashed - you've only ever had N. +//! - Slashable offences can be found after the fact and out of order. +//! +//! The algorithm implemented in this module tries to balance these 3 difficulties. +//! +//! First, we only slash participants for the _maximum_ slash they receive in some time period, +//! rather than the sum. This ensures a protection from overslashing. +//! +//! Second, we do not want the time period (or "span") that the maximum is computed +//! over to last indefinitely. That would allow participants to begin acting with +//! impunity after some point, fearing no further repercussions. For that reason, we +//! automatically "chill" validators and withdraw a nominator's nomination after a slashing event, +//! requiring them to re-enlist voluntarily (acknowledging the slash) and begin a new +//! slashing span. +//! +//! Typically, you will have a single slashing event per slashing span. Only in the case +//! where a validator releases many misbehaviors at once, or goes "back in time" to misbehave in +//! eras that have already passed, would you encounter situations where a slashing span +//! has multiple misbehaviors. However, accounting for such cases is necessary +//! to deter a class of "rage-quit" attacks. +//! +//! Based on research at https://research.web3.foundation/en/latest/polkadot/slashing/npos/ + +use super::{ + EraIndex, Trait, Module, Store, BalanceOf, Exposure, Perbill, SessionInterface, + NegativeImbalanceOf, UnappliedSlash, +}; +use sp_runtime::traits::{Zero, Saturating}; +use frame_support::{ + StorageMap, StorageDoubleMap, + traits::{Currency, OnUnbalanced, Imbalance}, +}; +use sp_std::vec::Vec; +use codec::{Encode, Decode}; + +/// The proportion of the slashing reward to be paid out on the first slashing detection. +/// This is f_1 in the paper. +const REWARD_F1: Perbill = Perbill::from_percent(50); + +/// The index of a slashing span - unique to each stash. +pub(crate) type SpanIndex = u32; + +// A range of start..end eras for a slashing span. +#[derive(Encode, Decode)] +#[cfg_attr(test, derive(Debug, PartialEq))] +pub(crate) struct SlashingSpan { + pub(crate) index: SpanIndex, + pub(crate) start: EraIndex, + pub(crate) length: Option, // the ongoing slashing span has indeterminate length. +} + +impl SlashingSpan { + fn contains_era(&self, era: EraIndex) -> bool { + self.start <= era && self.length.map_or(true, |l| self.start + l > era) + } +} + +/// An encoding of all of a nominator's slashing spans. +#[derive(Encode, Decode)] +pub struct SlashingSpans { + // the index of the current slashing span of the nominator. different for + // every stash, resets when the account hits free balance 0. + span_index: SpanIndex, + // the start era of the most recent (ongoing) slashing span. + last_start: EraIndex, + // all prior slashing spans start indices, in reverse order (most recent first) + // encoded as offsets relative to the slashing span after it. + prior: Vec, +} + +impl SlashingSpans { + // creates a new record of slashing spans for a stash, starting at the beginning + // of the bonding period, relative to now. + fn new(window_start: EraIndex) -> Self { + SlashingSpans { + span_index: 0, + last_start: window_start, + prior: Vec::new(), + } + } + + // update the slashing spans to reflect the start of a new span at the era after `now` + // returns `true` if a new span was started, `false` otherwise. `false` indicates + // that internal state is unchanged. + fn end_span(&mut self, now: EraIndex) -> bool { + let next_start = now + 1; + if next_start <= self.last_start { return false } + + let last_length = next_start - self.last_start; + self.prior.insert(0, last_length); + self.last_start = next_start; + self.span_index += 1; + true + } + + // an iterator over all slashing spans in _reverse_ order - most recent first. + pub(crate) fn iter(&'_ self) -> impl Iterator + '_ { + let mut last_start = self.last_start; + let mut index = self.span_index; + let last = SlashingSpan { index, start: last_start, length: None }; + let prior = self.prior.iter().cloned().map(move |length| { + let start = last_start - length; + last_start = start; + index -= 1; + + SlashingSpan { index, start, length: Some(length) } + }); + + sp_std::iter::once(last).chain(prior) + } + + /// Yields the era index where the last (current) slashing span started. + pub(crate) fn last_start(&self) -> EraIndex { + self.last_start + } + + // prune the slashing spans against a window, whose start era index is given. + // + // If this returns `Some`, then it includes a range start..end of all the span + // indices which were pruned. + fn prune(&mut self, window_start: EraIndex) -> Option<(SpanIndex, SpanIndex)> { + let old_idx = self.iter() + .skip(1) // skip ongoing span. + .position(|span| span.length.map_or(false, |len| span.start + len <= window_start)); + + let earliest_span_index = self.span_index - self.prior.len() as SpanIndex; + let pruned = match old_idx { + Some(o) => { + self.prior.truncate(o); + let new_earliest = self.span_index - self.prior.len() as SpanIndex; + Some((earliest_span_index, new_earliest)) + } + None => None, + }; + + // readjust the ongoing span, if it started before the beginning of the window. + self.last_start = sp_std::cmp::max(self.last_start, window_start); + pruned + } +} + +/// A slashing-span record for a particular stash. +#[derive(Encode, Decode, Default)] +pub(crate) struct SpanRecord { + slashed: Balance, + paid_out: Balance, +} + +impl SpanRecord { + /// The value of stash balance slashed in this span. + #[cfg(test)] + pub(crate) fn amount_slashed(&self) -> &Balance { + &self.slashed + } +} + +/// Parameters for performing a slash. +#[derive(Clone)] +pub(crate) struct SlashParams<'a, T: 'a + Trait> { + /// The stash account being slashed. + pub(crate) stash: &'a T::AccountId, + /// The proportion of the slash. + pub(crate) slash: Perbill, + /// The exposure of the stash and all nominators. + pub(crate) exposure: &'a Exposure>, + /// The era where the offence occurred. + pub(crate) slash_era: EraIndex, + /// The first era in the current bonding period. + pub(crate) window_start: EraIndex, + /// The current era. + pub(crate) now: EraIndex, + /// The maximum percentage of a slash that ever gets paid out. + /// This is f_inf in the paper. + pub(crate) reward_proportion: Perbill, +} + +/// Computes a slash of a validator and nominators. It returns an unapplied +/// record to be applied at some later point. Slashing metadata is updated in storage, +/// since unapplied records are only rarely intended to be dropped. +/// +/// The pending slash record returned does not have initialized reporters. Those have +/// to be set at a higher level, if any. +pub(crate) fn compute_slash(params: SlashParams) + -> Option>> +{ + let SlashParams { + stash, + slash, + exposure, + slash_era, + window_start, + now, + reward_proportion, + } = params.clone(); + + let mut reward_payout = Zero::zero(); + let mut val_slashed = Zero::zero(); + + // is the slash amount here a maximum for the era? + let own_slash = slash * exposure.own; + if slash * exposure.total == Zero::zero() { + // kick out the validator even if they won't be slashed, + // as long as the misbehavior is from their most recent slashing span. + kick_out_if_recent::(params); + return None; + } + + let (prior_slash_p, _era_slash) = as Store>::ValidatorSlashInEra::get( + &slash_era, + stash, + ).unwrap_or((Perbill::zero(), Zero::zero())); + + // compare slash proportions rather than slash values to avoid issues due to rounding + // error. + if slash.deconstruct() > prior_slash_p.deconstruct() { + as Store>::ValidatorSlashInEra::insert( + &slash_era, + stash, + &(slash, own_slash), + ); + } else { + // we slash based on the max in era - this new event is not the max, + // so neither the validator or any nominators will need an update. + // + // this does lead to a divergence of our system from the paper, which + // pays out some reward even if the latest report is not max-in-era. + // we opt to avoid the nominator lookups and edits and leave more rewards + // for more drastic misbehavior. + return None; + } + + // apply slash to validator. + { + let mut spans = fetch_spans::( + stash, + window_start, + &mut reward_payout, + &mut val_slashed, + reward_proportion, + ); + + let target_span = spans.compare_and_update_span_slash( + slash_era, + own_slash, + ); + + if target_span == Some(spans.span_index()) { + // misbehavior occurred within the current slashing span - take appropriate + // actions. + + // chill the validator - it misbehaved in the current span and should + // not continue in the next election. also end the slashing span. + spans.end_span(now); + >::chill_stash(stash); + + // make sure to disable validator till the end of this session + if T::SessionInterface::disable_validator(stash).unwrap_or(false) { + // force a new era, to select a new validator set + >::ensure_new_era() + } + } + } + + let mut nominators_slashed = Vec::new(); + reward_payout += slash_nominators::(params, prior_slash_p, &mut nominators_slashed); + + Some(UnappliedSlash { + validator: stash.clone(), + own: val_slashed, + others: nominators_slashed, + reporters: Vec::new(), + payout: reward_payout, + }) +} + +// doesn't apply any slash, but kicks out the validator if the misbehavior is from +// the most recent slashing span. +fn kick_out_if_recent( + params: SlashParams, +) { + // these are not updated by era-span or end-span. + let mut reward_payout = Zero::zero(); + let mut val_slashed = Zero::zero(); + let mut spans = fetch_spans::( + params.stash, + params.window_start, + &mut reward_payout, + &mut val_slashed, + params.reward_proportion, + ); + + if spans.era_span(params.slash_era).map(|s| s.index) == Some(spans.span_index()) { + spans.end_span(params.now); + >::chill_stash(params.stash); + + // make sure to disable validator till the end of this session + if T::SessionInterface::disable_validator(params.stash).unwrap_or(false) { + // force a new era, to select a new validator set + >::ensure_new_era() + } + } +} + +/// Slash nominators. Accepts general parameters and the prior slash percentage of the validator. +/// +/// Returns the amount of reward to pay out. +fn slash_nominators( + params: SlashParams, + prior_slash_p: Perbill, + nominators_slashed: &mut Vec<(T::AccountId, BalanceOf)>, +) -> BalanceOf { + let SlashParams { + stash: _, + slash, + exposure, + slash_era, + window_start, + now, + reward_proportion, + } = params; + + let mut reward_payout = Zero::zero(); + + nominators_slashed.reserve(exposure.others.len()); + for nominator in &exposure.others { + let stash = &nominator.who; + let mut nom_slashed = Zero::zero(); + + // the era slash of a nominator always grows, if the validator + // had a new max slash for the era. + let era_slash = { + let own_slash_prior = prior_slash_p * nominator.value; + let own_slash_by_validator = slash * nominator.value; + let own_slash_difference = own_slash_by_validator.saturating_sub(own_slash_prior); + + let mut era_slash = as Store>::NominatorSlashInEra::get( + &slash_era, + stash, + ).unwrap_or(Zero::zero()); + + era_slash += own_slash_difference; + + as Store>::NominatorSlashInEra::insert( + &slash_era, + stash, + &era_slash, + ); + + era_slash + }; + + // compare the era slash against other eras in the same span. + { + let mut spans = fetch_spans::( + stash, + window_start, + &mut reward_payout, + &mut nom_slashed, + reward_proportion, + ); + + let target_span = spans.compare_and_update_span_slash( + slash_era, + era_slash, + ); + + if target_span == Some(spans.span_index()) { + // End the span, but don't chill the nominator. its nomination + // on this validator will be ignored in the future. + spans.end_span(now); + } + } + + nominators_slashed.push((stash.clone(), nom_slashed)); + } + + reward_payout +} + +// helper struct for managing a set of spans we are currently inspecting. +// writes alterations to disk on drop, but only if a slash has been carried out. +// +// NOTE: alterations to slashing metadata should not be done after this is dropped. +// dropping this struct applies any necessary slashes, which can lead to free balance +// being 0, and the account being garbage-collected -- a dead account should get no new +// metadata. +struct InspectingSpans<'a, T: Trait + 'a> { + dirty: bool, + window_start: EraIndex, + stash: &'a T::AccountId, + spans: SlashingSpans, + paid_out: &'a mut BalanceOf, + slash_of: &'a mut BalanceOf, + reward_proportion: Perbill, + _marker: sp_std::marker::PhantomData, +} + +// fetches the slashing spans record for a stash account, initializing it if necessary. +fn fetch_spans<'a, T: Trait + 'a>( + stash: &'a T::AccountId, + window_start: EraIndex, + paid_out: &'a mut BalanceOf, + slash_of: &'a mut BalanceOf, + reward_proportion: Perbill, +) -> InspectingSpans<'a, T> { + let spans = as Store>::SlashingSpans::get(stash).unwrap_or_else(|| { + let spans = SlashingSpans::new(window_start); + as Store>::SlashingSpans::insert(stash, &spans); + spans + }); + + InspectingSpans { + dirty: false, + window_start, + stash, + spans, + slash_of, + paid_out, + reward_proportion, + _marker: sp_std::marker::PhantomData, + } +} + +impl<'a, T: 'a + Trait> InspectingSpans<'a, T> { + fn span_index(&self) -> SpanIndex { + self.spans.span_index + } + + fn end_span(&mut self, now: EraIndex) { + self.dirty = self.spans.end_span(now) || self.dirty; + } + + fn add_slash(&mut self, amount: BalanceOf) { + *self.slash_of += amount; + } + + // find the span index of the given era, if covered. + fn era_span(&self, era: EraIndex) -> Option { + self.spans.iter().find(|span| span.contains_era(era)) + } + + // compares the slash in an era to the overall current span slash. + // if it's higher, applies the difference of the slashes and then updates the span on disk. + // + // returns the span index of the era where the slash occurred, if any. + fn compare_and_update_span_slash( + &mut self, + slash_era: EraIndex, + slash: BalanceOf, + ) -> Option { + let target_span = self.era_span(slash_era)?; + let span_slash_key = (self.stash.clone(), target_span.index); + let mut span_record = as Store>::SpanSlash::get(&span_slash_key); + let mut changed = false; + + let reward = if span_record.slashed < slash { + // new maximum span slash. apply the difference. + let difference = slash - span_record.slashed; + span_record.slashed = slash; + + // compute reward. + let reward = REWARD_F1 + * (self.reward_proportion * slash).saturating_sub(span_record.paid_out); + + self.add_slash(difference); + changed = true; + + reward + } else if span_record.slashed == slash { + // compute reward. no slash difference to apply. + REWARD_F1 * (self.reward_proportion * slash).saturating_sub(span_record.paid_out) + } else { + Zero::zero() + }; + + if !reward.is_zero() { + changed = true; + span_record.paid_out += reward; + *self.paid_out += reward; + } + + if changed { + self.dirty = true; + as Store>::SpanSlash::insert(&span_slash_key, &span_record); + } + + Some(target_span.index) + } +} + +impl<'a, T: 'a + Trait> Drop for InspectingSpans<'a, T> { + fn drop(&mut self) { + // only update on disk if we slashed this account. + if !self.dirty { return } + + if let Some((start, end)) = self.spans.prune(self.window_start) { + for span_index in start..end { + as Store>::SpanSlash::remove(&(self.stash.clone(), span_index)); + } + } + + as Store>::SlashingSpans::insert(self.stash, &self.spans); + } +} + +/// Clear slashing metadata for an obsolete era. +pub(crate) fn clear_era_metadata(obsolete_era: EraIndex) { + as Store>::ValidatorSlashInEra::remove_prefix(&obsolete_era); + as Store>::NominatorSlashInEra::remove_prefix(&obsolete_era); +} + +/// Clear slashing metadata for a dead account. +pub(crate) fn clear_stash_metadata(stash: &T::AccountId) { + let spans = match as Store>::SlashingSpans::take(stash) { + None => return, + Some(s) => s, + }; + + // kill slashing-span metadata for account. + // + // this can only happen while the account is staked _if_ they are completely slashed. + // in that case, they may re-bond, but it would count again as span 0. Further ancient + // slashes would slash into this new bond, since metadata has now been cleared. + for span in spans.iter() { + as Store>::SpanSlash::remove(&(stash.clone(), span.index)); + } +} + +// apply the slash to a stash account, deducting any missing funds from the reward +// payout, saturating at 0. this is mildly unfair but also an edge-case that +// can only occur when overlapping locked funds have been slashed. +fn do_slash( + stash: &T::AccountId, + value: BalanceOf, + reward_payout: &mut BalanceOf, + slashed_imbalance: &mut NegativeImbalanceOf, +) { + let controller = match >::bonded(stash) { + None => return, // defensive: should always exist. + Some(c) => c, + }; + + let mut ledger = match >::ledger(&controller) { + Some(ledger) => ledger, + None => return, // nothing to do. + }; + + let value = ledger.slash(value, T::Currency::minimum_balance()); + + if !value.is_zero() { + let (imbalance, missing) = T::Currency::slash(stash, value); + slashed_imbalance.subsume(imbalance); + + if !missing.is_zero() { + // deduct overslash from the reward payout + *reward_payout = reward_payout.saturating_sub(missing); + } + + >::update_ledger(&controller, &ledger); + + // trigger the event + >::deposit_event( + super::RawEvent::Slash(stash.clone(), value) + ); + } +} + +/// Apply a previously-unapplied slash. +pub(crate) fn apply_slash(unapplied_slash: UnappliedSlash>) { + let mut slashed_imbalance = NegativeImbalanceOf::::zero(); + let mut reward_payout = unapplied_slash.payout; + + do_slash::( + &unapplied_slash.validator, + unapplied_slash.own, + &mut reward_payout, + &mut slashed_imbalance, + ); + + for &(ref nominator, nominator_slash) in &unapplied_slash.others { + do_slash::( + &nominator, + nominator_slash, + &mut reward_payout, + &mut slashed_imbalance, + ); + } + + pay_reporters::(reward_payout, slashed_imbalance, &unapplied_slash.reporters); +} + + +/// Apply a reward payout to some reporters, paying the rewards out of the slashed imbalance. +fn pay_reporters( + reward_payout: BalanceOf, + slashed_imbalance: NegativeImbalanceOf, + reporters: &[T::AccountId], +) { + if reward_payout.is_zero() || reporters.is_empty() { + // nobody to pay out to or nothing to pay; + // just treat the whole value as slashed. + T::Slash::on_unbalanced(slashed_imbalance); + return + } + + // take rewards out of the slashed imbalance. + let reward_payout = reward_payout.min(slashed_imbalance.peek()); + let (mut reward_payout, mut value_slashed) = slashed_imbalance.split(reward_payout); + + let per_reporter = reward_payout.peek() / (reporters.len() as u32).into(); + for reporter in reporters { + let (reporter_reward, rest) = reward_payout.split(per_reporter); + reward_payout = rest; + + // this cancels out the reporter reward imbalance internally, leading + // to no change in total issuance. + T::Currency::resolve_creating(reporter, reporter_reward); + } + + // the rest goes to the on-slash imbalance handler (e.g. treasury) + value_slashed.subsume(reward_payout); // remainder of reward division remains. + T::Slash::on_unbalanced(value_slashed); +} + +// TODO: function for undoing a slash. +// + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn span_contains_era() { + // unbounded end + let span = SlashingSpan { index: 0, start: 1000, length: None }; + assert!(!span.contains_era(0)); + assert!(!span.contains_era(999)); + + assert!(span.contains_era(1000)); + assert!(span.contains_era(1001)); + assert!(span.contains_era(10000)); + + // bounded end - non-inclusive range. + let span = SlashingSpan { index: 0, start: 1000, length: Some(10) }; + assert!(!span.contains_era(0)); + assert!(!span.contains_era(999)); + + assert!(span.contains_era(1000)); + assert!(span.contains_era(1001)); + assert!(span.contains_era(1009)); + assert!(!span.contains_era(1010)); + assert!(!span.contains_era(1011)); + } + + #[test] + fn single_slashing_span() { + let spans = SlashingSpans { + span_index: 0, + last_start: 1000, + prior: Vec::new(), + }; + + assert_eq!( + spans.iter().collect::>(), + vec![SlashingSpan { index: 0, start: 1000, length: None }], + ); + } + + #[test] + fn many_prior_spans() { + let spans = SlashingSpans { + span_index: 10, + last_start: 1000, + prior: vec![10, 9, 8, 10], + }; + + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 10, start: 1000, length: None }, + SlashingSpan { index: 9, start: 990, length: Some(10) }, + SlashingSpan { index: 8, start: 981, length: Some(9) }, + SlashingSpan { index: 7, start: 973, length: Some(8) }, + SlashingSpan { index: 6, start: 963, length: Some(10) }, + ], + ) + } + + #[test] + fn pruning_spans() { + let mut spans = SlashingSpans { + span_index: 10, + last_start: 1000, + prior: vec![10, 9, 8, 10], + }; + + assert_eq!(spans.prune(981), Some((6, 8))); + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 10, start: 1000, length: None }, + SlashingSpan { index: 9, start: 990, length: Some(10) }, + SlashingSpan { index: 8, start: 981, length: Some(9) }, + ], + ); + + assert_eq!(spans.prune(982), None); + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 10, start: 1000, length: None }, + SlashingSpan { index: 9, start: 990, length: Some(10) }, + SlashingSpan { index: 8, start: 981, length: Some(9) }, + ], + ); + + assert_eq!(spans.prune(989), None); + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 10, start: 1000, length: None }, + SlashingSpan { index: 9, start: 990, length: Some(10) }, + SlashingSpan { index: 8, start: 981, length: Some(9) }, + ], + ); + + assert_eq!(spans.prune(1000), Some((8, 10))); + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 10, start: 1000, length: None }, + ], + ); + + assert_eq!(spans.prune(2000), None); + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 10, start: 2000, length: None }, + ], + ); + + // now all in one shot. + let mut spans = SlashingSpans { + span_index: 10, + last_start: 1000, + prior: vec![10, 9, 8, 10], + }; + assert_eq!(spans.prune(2000), Some((6, 10))); + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 10, start: 2000, length: None }, + ], + ); + } + + #[test] + fn ending_span() { + let mut spans = SlashingSpans { + span_index: 1, + last_start: 10, + prior: Vec::new(), + }; + + assert!(spans.end_span(10)); + + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 2, start: 11, length: None }, + SlashingSpan { index: 1, start: 10, length: Some(1) }, + ], + ); + + assert!(spans.end_span(15)); + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 3, start: 16, length: None }, + SlashingSpan { index: 2, start: 11, length: Some(5) }, + SlashingSpan { index: 1, start: 10, length: Some(1) }, + ], + ); + + // does nothing if not a valid end. + assert!(!spans.end_span(15)); + assert_eq!( + spans.iter().collect::>(), + vec![ + SlashingSpan { index: 3, start: 16, length: None }, + SlashingSpan { index: 2, start: 11, length: Some(5) }, + SlashingSpan { index: 1, start: 10, length: Some(1) }, + ], + ); + } +} diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs new file mode 100644 index 0000000000000..555edac979d87 --- /dev/null +++ b/frame/staking/src/tests.rs @@ -0,0 +1,2835 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +use super::*; +use mock::*; +use sp_runtime::{assert_eq_error_rate, traits::{OnInitialize, BadOrigin}}; +use sp_staking::offence::OffenceDetails; +use frame_support::{ + assert_ok, assert_noop, + traits::{Currency, ReservableCurrency}, + dispatch::DispatchError, +}; +use substrate_test_utils::assert_eq_uvec; + +#[test] +fn force_unstake_works() { + // Verifies initial conditions of mock + ExtBuilder::default().build().execute_with(|| { + // Account 11 is stashed and locked, and account 10 is the controller + assert_eq!(Staking::bonded(&11), Some(10)); + // Cant transfer + assert_noop!( + Balances::transfer(Origin::signed(11), 1, 10), + DispatchError::Module { + index: 0, + error: 1, + message: Some("LiquidityRestrictions"), + } + ); + // Force unstake requires root. + assert_noop!(Staking::force_unstake(Origin::signed(11), 11), BadOrigin); + // We now force them to unstake + assert_ok!(Staking::force_unstake(Origin::ROOT, 11)); + // No longer bonded. + assert_eq!(Staking::bonded(&11), None); + // Transfer works. + assert_ok!(Balances::transfer(Origin::signed(11), 1, 10)); + }); +} + +#[test] +fn basic_setup_works() { + // Verifies initial conditions of mock + ExtBuilder::default().build().execute_with(|| { + // Account 11 is stashed and locked, and account 10 is the controller + assert_eq!(Staking::bonded(&11), Some(10)); + // Account 21 is stashed and locked, and account 20 is the controller + assert_eq!(Staking::bonded(&21), Some(20)); + // Account 1 is not a stashed + assert_eq!(Staking::bonded(&1), None); + + // Account 10 controls the stash from account 11, which is 100 * balance_factor units + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] }) + ); + // Account 20 controls the stash from account 21, which is 200 * balance_factor units + assert_eq!( + Staking::ledger(&20), + Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![] }) + ); + // Account 1 does not control any stash + assert_eq!(Staking::ledger(&1), None); + + // ValidatorPrefs are default + assert_eq!(>::enumerate().collect::>(), vec![ + (31, ValidatorPrefs::default()), + (21, ValidatorPrefs::default()), + (11, ValidatorPrefs::default()) + ]); + + assert_eq!( + Staking::ledger(100), + Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![] }) + ); + assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); + + if cfg!(feature = "equalize") { + assert_eq!( + Staking::stakers(11), + Exposure { total: 1250, own: 1000, others: vec![ IndividualExposure { who: 101, value: 250 }] } + ); + assert_eq!( + Staking::stakers(21), + Exposure { total: 1250, own: 1000, others: vec![ IndividualExposure { who: 101, value: 250 }] } + ); + // initial slot_stake + assert_eq!(Staking::slot_stake(), 1250); + } else { + assert_eq!( + Staking::stakers(11), + Exposure { total: 1125, own: 1000, others: vec![ IndividualExposure { who: 101, value: 125 }] } + ); + assert_eq!( + Staking::stakers(21), + Exposure { total: 1375, own: 1000, others: vec![ IndividualExposure { who: 101, value: 375 }] } + ); + // initial slot_stake + assert_eq!(Staking::slot_stake(), 1125); + } + + + // The number of validators required. + assert_eq!(Staking::validator_count(), 2); + + // Initial Era and session + assert_eq!(Staking::current_era(), 0); + + // Account 10 has `balance_factor` free balance + assert_eq!(Balances::free_balance(&10), 1); + assert_eq!(Balances::free_balance(&10), 1); + + // New era is not being forced + assert_eq!(Staking::force_era(), Forcing::NotForcing); + + // All exposures must be correct. + check_exposure_all(); + check_nominator_all(); + }); +} + +#[test] +fn change_controller_works() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Staking::bonded(&11), Some(10)); + + assert!(>::enumerate().map(|(c, _)| c).collect::>().contains(&11)); + // 10 can control 11 who is initially a validator. + assert_ok!(Staking::chill(Origin::signed(10))); + assert!(!>::enumerate().map(|(c, _)| c).collect::>().contains(&11)); + + assert_ok!(Staking::set_controller(Origin::signed(11), 5)); + + start_era(1); + + assert_noop!( + Staking::validate(Origin::signed(10), ValidatorPrefs::default()), + Error::::NotController, + ); + assert_ok!(Staking::validate(Origin::signed(5), ValidatorPrefs::default())); + }) +} + +#[test] +fn rewards_should_work() { + // should check that: + // * rewards get recorded per session + // * rewards get paid per Era + // * Check that nominators are also rewarded + ExtBuilder::default().nominate(false).build().execute_with(|| { + // Init some balances + let _ = Balances::make_free_balance_be(&2, 500); + + let delay = 1000; + let init_balance_2 = Balances::total_balance(&2); + let init_balance_10 = Balances::total_balance(&10); + let init_balance_11 = Balances::total_balance(&11); + + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + + // Initial config should be correct + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + + // Add a dummy nominator. + // + // Equal division indicates that the reward will be equally divided among validator and + // nominator. + >::insert(&11, Exposure { + own: 500, + total: 1000, + others: vec![IndividualExposure {who: 2, value: 500 }] + }); + + >::insert(&2, RewardDestination::Stash); + assert_eq!(Staking::payee(2), RewardDestination::Stash); + assert_eq!(Staking::payee(11), RewardDestination::Controller); + + let mut block = 3; // Block 3 => Session 1 => Era 0 + System::set_block_number(block); + Timestamp::set_timestamp(block * 5000); // on time. + Session::on_initialize(System::block_number()); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 1); + >::reward_by_ids(vec![(11, 50)]); + >::reward_by_ids(vec![(11, 50)]); + // This is the second validator of the current elected set. + >::reward_by_ids(vec![(21, 50)]); + // This must be no-op as it is not an elected validator. + >::reward_by_ids(vec![(1001, 10_000)]); + + // Compute total payout now for whole duration as other parameter won't change + let total_payout = current_total_payout_for_duration(9 * 5 * 1000); + assert!(total_payout > 10); // Test is meaningful if reward something + + // No reward yet + assert_eq!(Balances::total_balance(&2), init_balance_2); + assert_eq!(Balances::total_balance(&10), init_balance_10); + assert_eq!(Balances::total_balance(&11), init_balance_11); + + block = 6; // Block 6 => Session 2 => Era 0 + System::set_block_number(block); + Timestamp::set_timestamp(block * 5000 + delay); // a little late. + Session::on_initialize(System::block_number()); + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 2); + + block = 9; // Block 9 => Session 3 => Era 1 + System::set_block_number(block); + Timestamp::set_timestamp(block * 5000); // back to being on time. no delays + Session::on_initialize(System::block_number()); + assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::current_index(), 3); + + // 11 validator has 2/3 of the total rewards and half half for it and its nominator + assert_eq_error_rate!(Balances::total_balance(&2), init_balance_2 + total_payout / 3, 1); + assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + total_payout / 3, 1); + assert_eq!(Balances::total_balance(&11), init_balance_11); + }); +} + +#[test] +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. + ExtBuilder::default().nominate(false).build().execute_with(|| { + let init_balance_10 = Balances::total_balance(&10); + + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + + // Compute now as other parameter won't change + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 10); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 1)]); + + start_session(0); + start_session(1); + start_session(2); + start_session(3); + + assert_eq!(Staking::current_era(), 1); + assert_eq!(Balances::total_balance(&10), init_balance_10 + total_payout_0); + + start_session(4); + + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 10); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 101)]); + + // new era is triggered here. + start_session(5); + + // pay time + assert_eq!(Balances::total_balance(&10), init_balance_10 + total_payout_0 + total_payout_1); + }); +} + +#[test] +fn staking_should_work() { + // 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. + ExtBuilder::default() + .nominate(false) + .fair(false) // to give 20 more staked value + .build() + .execute_with(|| { + Timestamp::set_timestamp(1); // Initialize time. + + // remember + compare this along with the test. + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + // put some money in account that we'll use. + for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); } + + // --- Block 1: + start_session(1); + // add a new candidate for being a validator. account 3 controlled by 4. + assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); + + // No effects will be seen so far. + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + // --- Block 2: + start_session(2); + + // No effects will be seen so far. Era has not been yet triggered. + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + + // --- Block 3: the validators will now be queued. + start_session(3); + assert_eq!(Staking::current_era(), 1); + + // --- Block 4: the validators will now be changed. + start_session(4); + + assert_eq_uvec!(validator_controllers(), vec![20, 4]); + // --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3 + // 4 will chill + Staking::chill(Origin::signed(4)).unwrap(); + + // --- Block 5: nothing. 4 is still there. + start_session(5); + assert_eq_uvec!(validator_controllers(), vec![20, 4]); + + // --- Block 6: 4 will not be a validator. + start_session(7); + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + // Note: the stashed value of 4 is still lock + assert_eq!( + Staking::ledger(&4), + Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![] }) + ); + // e.g. it cannot spend more than 500 that it has free from the total 2000 + assert_noop!( + Balances::reserve(&3, 501), + DispatchError::Module { + index: 0, + error: 1, + message: Some("LiquidityRestrictions"), + } + ); + assert_ok!(Balances::reserve(&3, 409)); + }); +} + +#[test] +fn less_than_needed_candidates_works() { + ExtBuilder::default() + .minimum_validator_count(1) + .validator_count(4) + .nominate(false) + .num_validators(3) + .build() + .execute_with(|| { + assert_eq!(Staking::validator_count(), 4); + assert_eq!(Staking::minimum_validator_count(), 1); + assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); + + start_era(1); + + // Previous set is selected. NO election algorithm is even executed. + assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); + + // But the exposure is updated in a simple way. No external votes exists. + // This is purely self-vote. + assert_eq!(Staking::stakers(10).others.len(), 0); + assert_eq!(Staking::stakers(20).others.len(), 0); + assert_eq!(Staking::stakers(30).others.len(), 0); + check_exposure_all(); + check_nominator_all(); + }); +} + +#[test] +fn no_candidate_emergency_condition() { + ExtBuilder::default() + .minimum_validator_count(10) + .validator_count(15) + .num_validators(4) + .validator_pool(true) + .nominate(false) + .build() + .execute_with(|| { + // initial validators + assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); + + // set the minimum validator count. + ::MinimumValidatorCount::put(10); + ::ValidatorCount::put(15); + assert_eq!(Staking::validator_count(), 15); + + let _ = Staking::chill(Origin::signed(10)); + + // trigger era + System::set_block_number(1); + Session::on_initialize(System::block_number()); + + // Previous ones are elected. chill is invalidates. TODO: #2494 + assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); + assert_eq!(Staking::current_elected().len(), 0); + }); +} + +#[test] +fn nominating_and_rewards_should_work() { + // PHRAGMEN OUTPUT: running this test with the reference impl gives: + // + // Sequential Phragmén gives + // 10 is elected with stake 2200.0 and score 0.0003333333333333333 + // 20 is elected with stake 1800.0 and score 0.0005555555555555556 + + // 10 has load 0.0003333333333333333 and supported + // 10 with stake 1000.0 + // 20 has load 0.0005555555555555556 and supported + // 20 with stake 1000.0 + // 30 has load 0 and supported + // 30 with stake 0 + // 40 has load 0 and supported + // 40 with stake 0 + // 2 has load 0.0005555555555555556 and supported + // 10 with stake 600.0 20 with stake 400.0 30 with stake 0.0 + // 4 has load 0.0005555555555555556 and supported + // 10 with stake 600.0 20 with stake 400.0 40 with stake 0.0 + + // Sequential Phragmén with post processing gives + // 10 is elected with stake 2000.0 and score 0.0003333333333333333 + // 20 is elected with stake 2000.0 and score 0.0005555555555555556 + + // 10 has load 0.0003333333333333333 and supported + // 10 with stake 1000.0 + // 20 has load 0.0005555555555555556 and supported + // 20 with stake 1000.0 + // 30 has load 0 and supported + // 30 with stake 0 + // 40 has load 0 and supported + // 40 with stake 0 + // 2 has load 0.0005555555555555556 and supported + // 10 with stake 400.0 20 with stake 600.0 30 with stake 0 + // 4 has load 0.0005555555555555556 and supported + // 10 with stake 600.0 20 with stake 400.0 40 with stake 0.0 + ExtBuilder::default() + .nominate(false) + .validator_pool(true) + .build() + .execute_with(|| { + // initial validators -- everyone is actually even. + assert_eq_uvec!(validator_controllers(), vec![40, 30]); + + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(20), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(30), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(40), RewardDestination::Controller)); + + // give the man some money + let initial_balance = 1000; + for i in [1, 2, 3, 4, 5, 10, 11, 20, 21].iter() { + let _ = Balances::make_free_balance_be(i, initial_balance); + } + + // bond two account pairs and state interest in nomination. + // 2 will nominate for 10, 20, 30 + assert_ok!(Staking::bond(Origin::signed(1), 2, 1000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21, 31])); + // 4 will nominate for 10, 20, 40 + assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41])); + + // the total reward for era 0 + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(41, 1)]); + >::reward_by_ids(vec![(31, 1)]); + >::reward_by_ids(vec![(21, 10)]); // must be no-op + >::reward_by_ids(vec![(11, 10)]); // must be no-op + + start_era(1); + + // 10 and 20 have more votes, they will be chosen by phragmen. + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + // OLD validators must have already received some rewards. + assert_eq!(Balances::total_balance(&40), 1 + total_payout_0 / 2); + assert_eq!(Balances::total_balance(&30), 1 + total_payout_0 / 2); + + // ------ check the staked value of all parties. + + if cfg!(feature = "equalize") { + // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(11).own, 1000); + assert_eq_error_rate!(Staking::stakers(11).total, 1000 + 1000, 2); + // 2 and 4 supported 10, each with stake 600, according to phragmen. + assert_eq!( + Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), + vec![600, 400] + ); + assert_eq!( + Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), + vec![3, 1] + ); + // total expo of 20, with 500 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(21).own, 1000); + assert_eq_error_rate!(Staking::stakers(21).total, 1000 + 1000, 2); + // 2 and 4 supported 20, each with stake 250, according to phragmen. + assert_eq!( + Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), + vec![400, 600] + ); + assert_eq!( + Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), + vec![3, 1] + ); + } else { + // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(11).own, 1000); + assert_eq!(Staking::stakers(11).total, 1000 + 800); + // 2 and 4 supported 10, each with stake 600, according to phragmen. + assert_eq!( + Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), + vec![400, 400] + ); + assert_eq!( + Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), + vec![3, 1] + ); + // total expo of 20, with 500 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(21).own, 1000); + assert_eq_error_rate!(Staking::stakers(21).total, 1000 + 1200, 2); + // 2 and 4 supported 20, each with stake 250, according to phragmen. + assert_eq!( + Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), + vec![600, 600] + ); + assert_eq!( + Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), + vec![3, 1] + ); + } + + // They are not chosen anymore + assert_eq!(Staking::stakers(31).total, 0); + assert_eq!(Staking::stakers(41).total, 0); + + // the total reward for era 1 + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(41, 10)]); // must be no-op + >::reward_by_ids(vec![(31, 10)]); // must be no-op + >::reward_by_ids(vec![(21, 2)]); + >::reward_by_ids(vec![(11, 1)]); + + start_era(2); + + // nothing else will happen, era ends and rewards are paid again, + // it is expected that nominators will also be paid. See below + + let payout_for_10 = total_payout_1 / 3; + let payout_for_20 = 2 * total_payout_1 / 3; + if cfg!(feature = "equalize") { + // Nominator 2: has [400 / 2000 ~ 1 / 5 from 10] + [600 / 2000 ~ 3 / 10 from 20]'s reward. + assert_eq_error_rate!( + Balances::total_balance(&2), + initial_balance + payout_for_10 / 5 + payout_for_20 * 3 / 10, + 2, + ); + // Nominator 4: has [400 / 2000 ~ 1 / 5 from 20] + [600 / 2000 ~ 3 / 10 from 10]'s reward. + assert_eq_error_rate!( + Balances::total_balance(&4), + initial_balance + payout_for_20 / 5 + payout_for_10 * 3 / 10, + 2, + ); + + // Validator 10: got 1000 / 2000 external stake. + assert_eq_error_rate!( + Balances::total_balance(&10), + initial_balance + payout_for_10 / 2, + 1, + ); + // Validator 20: got 1000 / 2000 external stake. + assert_eq_error_rate!( + Balances::total_balance(&20), + initial_balance + payout_for_20 / 2, + 1, + ); + } else { + // Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 + assert_eq_error_rate!( + Balances::total_balance(&2), + initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), + 1, + ); + // Nominator 4: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 + assert_eq_error_rate!( + Balances::total_balance(&4), + initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), + 1, + ); + + // Validator 10: got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9 + assert_eq_error_rate!( + Balances::total_balance(&10), + initial_balance + 5 * payout_for_10 / 9, + 1, + ); + // Validator 20: got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = 5/11 + assert_eq_error_rate!( + Balances::total_balance(&20), + initial_balance + 5 * payout_for_20 / 11, + 1, + ); + } + + check_exposure_all(); + check_nominator_all(); + }); +} + +#[test] +fn nominators_also_get_slashed() { + // A nominator should be slashed if the validator they nominated is slashed + // Here is the breakdown of roles: + // 10 - is the controller of 11 + // 11 - is the stash. + // 2 - is the nominator of 20, 10 + ExtBuilder::default().nominate(false).build().execute_with(|| { + assert_eq!(Staking::validator_count(), 2); + + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + + // give the man some money. + let initial_balance = 1000; + for i in [1, 2, 3, 10].iter() { + let _ = Balances::make_free_balance_be(i, initial_balance); + } + + // 2 will nominate for 10, 20 + let nominator_stake = 500; + assert_ok!(Staking::bond(Origin::signed(1), 2, nominator_stake, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 10])); + + let total_payout = current_total_payout_for_duration(3000); + assert!(total_payout > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 1)]); + + // new era, pay rewards, + start_era(1); + + // Nominator stash didn't collect any. + assert_eq!(Balances::total_balance(&2), initial_balance); + + // 10 goes offline + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(5)], + ); + let expo = Staking::stakers(11); + let slash_value = 50; + let total_slash = expo.total.min(slash_value); + let validator_slash = expo.own.min(total_slash); + let nominator_slash = nominator_stake.min(total_slash - validator_slash); + + // initial + first era reward + slash + assert_eq!(Balances::total_balance(&11), initial_balance - validator_slash); + assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); + check_exposure_all(); + check_nominator_all(); + // Because slashing happened. + assert!(is_disabled(10)); + }); +} + +#[test] +fn double_staking_should_fail() { + // should test (in the same order): + // * an account already bonded as stash cannot be be stashed again. + // * an account already bonded as stash cannot nominate. + // * an account already bonded as controller can nominate. + ExtBuilder::default().build().execute_with(|| { + let arbitrary_value = 5; + // 2 = controller, 1 stashed => ok + assert_ok!( + Staking::bond(Origin::signed(1), 2, arbitrary_value, + RewardDestination::default()) + ); + // 4 = not used so far, 1 stashed => not allowed. + assert_noop!( + Staking::bond(Origin::signed(1), 4, arbitrary_value, + RewardDestination::default()), Error::::AlreadyBonded, + ); + // 1 = stashed => attempting to nominate should fail. + assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), Error::::NotController); + // 2 = controller => nominating should work. + assert_ok!(Staking::nominate(Origin::signed(2), vec![1])); + }); +} + +#[test] +fn double_controlling_should_fail() { + // should test (in the same order): + // * an account already bonded as controller CANNOT be reused as the controller of another account. + ExtBuilder::default().build().execute_with(|| { + let arbitrary_value = 5; + // 2 = controller, 1 stashed => ok + assert_ok!(Staking::bond( + Origin::signed(1), + 2, + arbitrary_value, + RewardDestination::default(), + )); + // 2 = controller, 3 stashed (Note that 2 is reused.) => no-op + assert_noop!( + Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default()), + Error::::AlreadyPaired, + ); + }); +} + +#[test] +fn session_and_eras_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Staking::current_era(), 0); + + // Block 1: No change. + start_session(0); + assert_eq!(Session::current_index(), 1); + assert_eq!(Staking::current_era(), 0); + + // Block 2: Simple era change. + start_session(2); + assert_eq!(Session::current_index(), 3); + assert_eq!(Staking::current_era(), 1); + + // Block 3: Schedule an era length change; no visible changes. + start_session(3); + assert_eq!(Session::current_index(), 4); + assert_eq!(Staking::current_era(), 1); + + // Block 4: Era change kicks in. + start_session(5); + assert_eq!(Session::current_index(), 6); + assert_eq!(Staking::current_era(), 2); + + // Block 5: No change. + start_session(6); + assert_eq!(Session::current_index(), 7); + assert_eq!(Staking::current_era(), 2); + + // Block 6: No change. + start_session(7); + assert_eq!(Session::current_index(), 8); + assert_eq!(Staking::current_era(), 2); + + // Block 7: Era increment. + start_session(8); + assert_eq!(Session::current_index(), 9); + assert_eq!(Staking::current_era(), 3); + }); +} + +#[test] +fn forcing_new_era_works() { + ExtBuilder::default().build().execute_with(|| { + // normal flow of session. + assert_eq!(Staking::current_era(), 0); + start_session(0); + assert_eq!(Staking::current_era(), 0); + start_session(1); + assert_eq!(Staking::current_era(), 0); + start_session(2); + assert_eq!(Staking::current_era(), 1); + + // no era change. + ForceEra::put(Forcing::ForceNone); + start_session(3); + assert_eq!(Staking::current_era(), 1); + start_session(4); + assert_eq!(Staking::current_era(), 1); + start_session(5); + assert_eq!(Staking::current_era(), 1); + start_session(6); + assert_eq!(Staking::current_era(), 1); + + // back to normal. + // this immediately starts a new session. + ForceEra::put(Forcing::NotForcing); + start_session(7); + assert_eq!(Staking::current_era(), 2); + start_session(8); + assert_eq!(Staking::current_era(), 2); + + // forceful change + ForceEra::put(Forcing::ForceAlways); + start_session(9); + assert_eq!(Staking::current_era(), 3); + start_session(10); + assert_eq!(Staking::current_era(), 4); + start_session(11); + assert_eq!(Staking::current_era(), 5); + + // just one forceful change + ForceEra::put(Forcing::ForceNew); + start_session(12); + assert_eq!(Staking::current_era(), 6); + + assert_eq!(ForceEra::get(), Forcing::NotForcing); + start_session(13); + assert_eq!(Staking::current_era(), 6); + + }); +} + +#[test] +fn cannot_transfer_staked_balance() { + // Tests that a stash account cannot transfer funds + ExtBuilder::default().nominate(false).build().execute_with(|| { + // Confirm account 11 is stashed + assert_eq!(Staking::bonded(&11), Some(10)); + // Confirm account 11 has some free balance + assert_eq!(Balances::free_balance(&11), 1000); + // Confirm account 11 (via controller 10) is totally staked + assert_eq!(Staking::stakers(&11).total, 1000); + // Confirm account 11 cannot transfer as a result + assert_noop!( + Balances::transfer(Origin::signed(11), 20, 1), + DispatchError::Module { + index: 0, + error: 1, + message: Some("LiquidityRestrictions"), + } + ); + + // Give account 11 extra free balance + let _ = Balances::make_free_balance_be(&11, 10000); + // Confirm that account 11 can now transfer some balance + assert_ok!(Balances::transfer(Origin::signed(11), 20, 1)); + }); +} + +#[test] +fn cannot_transfer_staked_balance_2() { + // Tests that a stash account cannot transfer funds + // Same test as above but with 20, and more accurate. + // 21 has 2000 free balance but 1000 at stake + ExtBuilder::default().nominate(false).fair(true).build().execute_with(|| { + // Confirm account 21 is stashed + assert_eq!(Staking::bonded(&21), Some(20)); + // Confirm account 21 has some free balance + assert_eq!(Balances::free_balance(&21), 2000); + // Confirm account 21 (via controller 20) is totally staked + assert_eq!(Staking::stakers(&21).total, 1000); + // Confirm account 21 can transfer at most 1000 + assert_noop!( + Balances::transfer(Origin::signed(21), 20, 1001), + DispatchError::Module { + index: 0, + error: 1, + message: Some("LiquidityRestrictions"), + } + ); + assert_ok!(Balances::transfer(Origin::signed(21), 20, 1000)); + }); +} + +#[test] +fn cannot_reserve_staked_balance() { + // Checks that a bonded account cannot reserve balance from free balance + ExtBuilder::default().build().execute_with(|| { + // 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(&11).own, 1000); + // Confirm account 11 cannot transfer as a result + assert_noop!( + Balances::reserve(&11, 1), + DispatchError::Module { + index: 0, + error: 1, + message: Some("LiquidityRestrictions"), + } + ); + + // Give account 11 extra free balance + let _ = Balances::make_free_balance_be(&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 + ExtBuilder::default().nominate(false).build().execute_with(|| { + // Check that account 11 is a validator + assert!(Staking::current_elected().contains(&11)); + // Check the balance of the validator account + assert_eq!(Balances::free_balance(&10), 1); + // Check the balance of the stash account + assert_eq!(Balances::free_balance(&11), 1000); + // Check how much is at stake + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: vec![], + })); + + // Compute total payout now for whole duration as other parameter won't change + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 1)]); + + start_era(1); + + // Check that RewardDestination is Staked (default) + assert_eq!(Staking::payee(&11), RewardDestination::Staked); + // Check that reward went to the stash account of validator + assert_eq!(Balances::free_balance(&11), 1000 + total_payout_0); + // Check that amount at stake increased accordingly + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, + total: 1000 + total_payout_0, + active: 1000 + total_payout_0, + unlocking: vec![], + })); + + //Change RewardDestination to Stash + >::insert(&11, RewardDestination::Stash); + + // Compute total payout now for whole duration as other parameter won't change + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 1)]); + + start_era(2); + + // Check that RewardDestination is Stash + assert_eq!(Staking::payee(&11), RewardDestination::Stash); + // Check that reward went to the stash account + assert_eq!(Balances::free_balance(&11), 1000 + total_payout_0 + total_payout_1); + // Record this value + let recorded_stash_balance = 1000 + total_payout_0 + total_payout_1; + // Check that amount at stake is NOT increased + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, + total: 1000 + total_payout_0, + active: 1000 + total_payout_0, + unlocking: vec![], + })); + + // Change RewardDestination to Controller + >::insert(&11, RewardDestination::Controller); + + // Check controller balance + assert_eq!(Balances::free_balance(&10), 1); + + // Compute total payout now for whole duration as other parameter won't change + let total_payout_2 = current_total_payout_for_duration(3000); + assert!(total_payout_2 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 1)]); + + start_era(3); + + // Check that RewardDestination is Controller + assert_eq!(Staking::payee(&11), RewardDestination::Controller); + // Check that reward went to the controller account + assert_eq!(Balances::free_balance(&10), 1 + total_payout_2); + // Check that amount at stake is NOT increased + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, + total: 1000 + total_payout_0, + active: 1000 + total_payout_0, + unlocking: vec![], + })); + // Check that amount in staked account is NOT increased. + assert_eq!(Balances::free_balance(&11), recorded_stash_balance); + }); +} + +#[test] +fn validator_payment_prefs_work() { + // Test that validator preferences are correctly honored + // Note: unstake threshold is being directly tested in slashing tests. + // This test will focus on validator payment. + ExtBuilder::default().build().execute_with(|| { + // Initial config + let stash_initial_balance = Balances::total_balance(&11); + + // check the balance of a validator accounts. + assert_eq!(Balances::total_balance(&10), 1); + // check the balance of a validator's stash accounts. + assert_eq!(Balances::total_balance(&11), stash_initial_balance); + // and the nominator (to-be) + let _ = Balances::make_free_balance_be(&2, 500); + + // add a dummy nominator. + >::insert(&11, 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::Stash); + >::insert(&11, ValidatorPrefs { + commission: Perbill::from_percent(50), + }); + + // Compute total payout now for whole duration as other parameter won't change + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 1)]); + + start_era(1); + + // whats left to be shared is the sum of 3 rounds minus the validator's cut. + let shared_cut = total_payout_0 / 2; + // Validator's payee is Staked account, 11, reward will be paid here. + assert_eq!(Balances::total_balance(&11), stash_initial_balance + shared_cut / 2 + shared_cut); + // Controller account will not get any reward. + assert_eq!(Balances::total_balance(&10), 1); + // Rest of the reward will be shared and paid to the nominator in stake. + assert_eq!(Balances::total_balance(&2), 500 + shared_cut / 2); + + check_exposure_all(); + check_nominator_all(); + }); + +} + +#[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`. + ExtBuilder::default().build().execute_with(|| { + // Check that account 10 is a validator + assert!(>::exists(11)); + // 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 + let _ = Balances::make_free_balance_be(&11, 1000000); + + // Call the bond_extra function from controller, add only 100 + assert_ok!(Staking::bond_extra(Origin::signed(11), 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(11), 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. + ExtBuilder::default().nominate(false).build().execute_with(|| { + // Set payee to controller. avoids confusion + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + + // Give account 11 some large free balance greater than total + let _ = Balances::make_free_balance_be(&11, 1000000); + + // Initial config should be correct + assert_eq!(Staking::current_era(), 0); + assert_eq!(Session::current_index(), 0); + + // 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. + start_era(1); + + // Initial state of 10 + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: vec![], + })); + assert_eq!(Staking::stakers(&11), Exposure { total: 1000, own: 1000, others: vec![] }); + + // deposit the extra 100 units + Staking::bond_extra(Origin::signed(11), 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(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + + // trigger next era. + Timestamp::set_timestamp(10); + start_era(2); + assert_eq!(Staking::current_era(), 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(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + + // Unbond almost all of the funds in stash. + Staking::unbond(Origin::signed(10), 1000).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] }) + ); + + // Attempting to free the balances now will fail. 2 eras need to pass. + Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] })); + + // trigger next era. + start_era(3); + + // nothing yet + Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); + assert_eq!(Staking::ledger(&10), Some(StakingLedger { + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] })); + + // trigger next era. + start_era(5); + + 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 too_many_unbond_calls_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + // locked at era 0 until 3 + for _ in 0..MAX_UNLOCKING_CHUNKS-1 { + assert_ok!(Staking::unbond(Origin::signed(10), 1)); + } + + start_era(1); + + // locked at era 1 until 4 + assert_ok!(Staking::unbond(Origin::signed(10), 1)); + // can't do more. + assert_noop!(Staking::unbond(Origin::signed(10), 1), Error::::NoMoreChunks); + + start_era(3); + + assert_noop!(Staking::unbond(Origin::signed(10), 1), Error::::NoMoreChunks); + // free up. + assert_ok!(Staking::withdraw_unbonded(Origin::signed(10))); + + // Can add again. + assert_ok!(Staking::unbond(Origin::signed(10), 1)); + assert_eq!(Staking::ledger(&10).unwrap().unlocking.len(), 2); + }) +} + +#[test] +fn rebond_works() { + // * Should test + // * Given an account being bonded [and chosen as a validator](not mandatory) + // * it can unbond a portion of its funds from the stash account. + // * it can re-bond a portion of the funds scheduled to unlock. + ExtBuilder::default() + .nominate(false) + .build() + .execute_with(|| { + // Set payee to controller. avoids confusion + assert_ok!(Staking::set_payee( + Origin::signed(10), + RewardDestination::Controller + )); + + // Give account 11 some large free balance greater than total + let _ = Balances::make_free_balance_be(&11, 1000000); + + // confirm that 10 is a normal validator and gets paid at the end of the era. + start_era(1); + + // Initial state of 10 + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: vec![], + }) + ); + + start_era(2); + assert_eq!(Staking::current_era(), 2); + + // Try to rebond some funds. We get an error since no fund is unbonded. + assert_noop!( + Staking::rebond(Origin::signed(10), 500), + Error::::NoUnlockChunk, + ); + + // Unbond almost all of the funds in stash. + Staking::unbond(Origin::signed(10), 900).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 100, + unlocking: vec![UnlockChunk { + value: 900, + era: 2 + 3 + },] + }) + ); + + // Re-bond all the funds unbonded. + Staking::rebond(Origin::signed(10), 900).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: vec![], + }) + ); + + // Unbond almost all of the funds in stash. + Staking::unbond(Origin::signed(10), 900).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 100, + unlocking: vec![UnlockChunk { value: 900, era: 5 }], + }) + ); + + // Re-bond part of the funds unbonded. + Staking::rebond(Origin::signed(10), 500).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 600, + unlocking: vec![UnlockChunk { value: 400, era: 5 }], + }) + ); + + // Re-bond the remainder of the funds unbonded. + Staking::rebond(Origin::signed(10), 500).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: vec![] + }) + ); + + // Unbond parts of the funds in stash. + Staking::unbond(Origin::signed(10), 300).unwrap(); + Staking::unbond(Origin::signed(10), 300).unwrap(); + Staking::unbond(Origin::signed(10), 300).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 100, + unlocking: vec![ + UnlockChunk { value: 300, era: 5 }, + UnlockChunk { value: 300, era: 5 }, + UnlockChunk { value: 300, era: 5 }, + ] + }) + ); + + // Re-bond part of the funds unbonded. + Staking::rebond(Origin::signed(10), 500).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 600, + unlocking: vec![ + UnlockChunk { value: 300, era: 5 }, + UnlockChunk { value: 100, era: 5 }, + ] + }) + ); + }) +} + +#[test] +fn rebond_is_fifo() { + // Rebond should proceed by reversing the most recent bond operations. + ExtBuilder::default() + .nominate(false) + .build() + .execute_with(|| { + // Set payee to controller. avoids confusion + assert_ok!(Staking::set_payee( + Origin::signed(10), + RewardDestination::Controller + )); + + // Give account 11 some large free balance greater than total + let _ = Balances::make_free_balance_be(&11, 1000000); + + // confirm that 10 is a normal validator and gets paid at the end of the era. + start_era(1); + + // Initial state of 10 + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 1000, + unlocking: vec![], + }) + ); + + start_era(2); + + // Unbond some of the funds in stash. + Staking::unbond(Origin::signed(10), 400).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 600, + unlocking: vec![ + UnlockChunk { value: 400, era: 2 + 3 }, + ] + }) + ); + + start_era(3); + + // Unbond more of the funds in stash. + Staking::unbond(Origin::signed(10), 300).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 300, + unlocking: vec![ + UnlockChunk { value: 400, era: 2 + 3 }, + UnlockChunk { value: 300, era: 3 + 3 }, + ] + }) + ); + + start_era(4); + + // Unbond yet more of the funds in stash. + Staking::unbond(Origin::signed(10), 200).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 100, + unlocking: vec![ + UnlockChunk { value: 400, era: 2 + 3 }, + UnlockChunk { value: 300, era: 3 + 3 }, + UnlockChunk { value: 200, era: 4 + 3 }, + ] + }) + ); + + // Re-bond half of the unbonding funds. + Staking::rebond(Origin::signed(10), 400).unwrap(); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { + stash: 11, + total: 1000, + active: 500, + unlocking: vec![ + UnlockChunk { value: 400, era: 2 + 3 }, + UnlockChunk { value: 100, era: 3 + 3 }, + ] + }) + ); + }) +} + +#[test] +fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment() { + // Test that slot_stake is determined by the least staked validator + // Test that slot_stake is the maximum punishment that can happen to a validator + ExtBuilder::default().nominate(false).fair(false).build().execute_with(|| { + // Confirm validator count is 2 + assert_eq!(Staking::validator_count(), 2); + // Confirm account 10 and 20 are validators + assert!(>::exists(&11) && >::exists(&21)); + + assert_eq!(Staking::stakers(&11).total, 1000); + assert_eq!(Staking::stakers(&21).total, 2000); + + // Give the man some money. + let _ = Balances::make_free_balance_be(&10, 1000); + let _ = Balances::make_free_balance_be(&20, 1000); + + // We confirm initialized slot_stake is this value + assert_eq!(Staking::slot_stake(), Staking::stakers(&11).total); + + // Now lets lower account 20 stake + >::insert(&21, Exposure { total: 69, own: 69, others: vec![] }); + assert_eq!(Staking::stakers(&21).total, 69); + >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![] }); + + // Compute total payout now for whole duration as other parameter won't change + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 1)]); + >::reward_by_ids(vec![(21, 1)]); + + // New era --> rewards are paid --> stakes are changed + start_era(1); + + // -- new balances + reward + assert_eq!(Staking::stakers(&11).total, 1000 + total_payout_0 / 2); + assert_eq!(Staking::stakers(&21).total, 69 + total_payout_0 / 2); + + let _11_balance = Balances::free_balance(&11); + assert_eq!(_11_balance, 1000 + total_payout_0 / 2); + + // -- slot stake should also be updated. + assert_eq!(Staking::slot_stake(), 69 + total_payout_0 / 2); + + check_exposure_all(); + check_nominator_all(); + }); +} + +#[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 + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + // Check the balance of the validator account + assert_eq!(Balances::free_balance(&10), 256); + // Check the balance of the stash account + 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 + // 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(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + + // Reduce free_balance of controller to 0 + let _ = Balances::slash(&10, u64::max_value()); + + // 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(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + + // Reduce free_balance of stash to 0 + let _ = Balances::slash(&11, u64::max_value()); + // Check total balance of stash + assert_eq!(Balances::total_balance(&11), 0); + + // Check storage items do not exist + assert!(!>::exists(&10)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + 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 + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + // Make 10 a nominator + assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); + // Check that account 10 is a nominator + assert!(>::exists(11)); + // 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); + + // 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(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + + // Reduce free_balance of controller to 0 + let _ = Balances::slash(&10, u64::max_value()); + // 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(&11)); + assert!(>::exists(&11)); + assert!(>::exists(&11)); + + // Reduce free_balance of stash to 0 + let _ = Balances::slash(&11, u64::max_value()); + // Check total balance of stash + assert_eq!(Balances::total_balance(&11), 0); + + // Check storage items do not exist + assert!(!>::exists(&10)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + assert!(!>::exists(&11)); + }); +} + + +#[test] +fn switching_roles() { + // Test that it should be possible to switch between roles (nominator, validator, idle) with minimal overhead. + ExtBuilder::default().nominate(false).build().execute_with(|| { + Timestamp::set_timestamp(1); // Initialize time. + + // Reset reward destination + for i in &[10, 20] { assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); } + + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + // put some money in account that we'll use. + for i in 1..7 { let _ = Balances::deposit_creating(&i, 5000); } + + // add 2 nominators + assert_ok!(Staking::bond(Origin::signed(1), 2, 2000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 5])); + + assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![21, 1])); + + // add a new validator candidate + assert_ok!(Staking::bond(Origin::signed(5), 6, 1000, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(6), ValidatorPrefs::default())); + + // new block + start_session(1); + + // no change + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + // new block + start_session(2); + + // no change + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + // new block --> ne era --> new validators + start_session(3); + + // with current nominators 10 and 5 have the most stake + assert_eq_uvec!(validator_controllers(), vec![6, 10]); + + // 2 decides to be a validator. Consequences: + assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + // new stakes: + // 10: 1000 self vote + // 20: 1000 self vote + 250 vote + // 6 : 1000 self vote + // 2 : 2000 self vote + 250 vote. + // Winners: 20 and 2 + + start_session(4); + assert_eq_uvec!(validator_controllers(), vec![6, 10]); + + start_session(5); + assert_eq_uvec!(validator_controllers(), vec![6, 10]); + + // ne era + start_session(6); + assert_eq_uvec!(validator_controllers(), vec![2, 20]); + + check_exposure_all(); + check_nominator_all(); + }); +} + +#[test] +fn wrong_vote_is_null() { + ExtBuilder::default().nominate(false).validator_pool(true).build().execute_with(|| { + assert_eq_uvec!(validator_controllers(), vec![40, 30]); + + // put some money in account that we'll use. + for i in 1..3 { let _ = Balances::deposit_creating(&i, 5000); } + + // add 1 nominators + assert_ok!(Staking::bond(Origin::signed(1), 2, 2000, RewardDestination::default())); + assert_ok!(Staking::nominate(Origin::signed(2), vec![ + 11, 21, // good votes + 1, 2, 15, 1000, 25 // crap votes. No effect. + ])); + + // new block + start_era(1); + + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + }); +} + +#[test] +fn bond_with_no_staked_value() { + // Behavior when someone bonds with no staked value. + // Particularly when she votes and the candidate is elected. + ExtBuilder::default() + .validator_count(3) + .existential_deposit(5) + .nominate(false) + .minimum_validator_count(1) + .build() + .execute_with(|| { + // Can't bond with 1 + assert_noop!( + Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller), + Error::::InsufficientValue, + ); + // bonded with absolute minimum value possible. + assert_ok!(Staking::bond(Origin::signed(1), 2, 5, RewardDestination::Controller)); + assert_eq!(Balances::locks(&1)[0].amount, 5); + + // unbonding even 1 will cause all to be unbonded. + assert_ok!(Staking::unbond(Origin::signed(2), 1)); + assert_eq!( + Staking::ledger(2), + Some(StakingLedger { + stash: 1, + active: 0, + total: 5, + unlocking: vec![UnlockChunk {value: 5, era: 3}] + }) + ); + + start_era(1); + start_era(2); + + // not yet removed. + assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); + assert!(Staking::ledger(2).is_some()); + assert_eq!(Balances::locks(&1)[0].amount, 5); + + start_era(3); + + // poof. Account 1 is removed from the staking system. + assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); + assert!(Staking::ledger(2).is_none()); + assert_eq!(Balances::locks(&1).len(), 0); + }); +} + +#[test] +fn bond_with_little_staked_value_bounded_by_slot_stake() { + // Behavior when someone bonds with little staked value. + // Particularly when she votes and the candidate is elected. + ExtBuilder::default() + .validator_count(3) + .nominate(false) + .minimum_validator_count(1) + .build() + .execute_with(|| { + // setup + assert_ok!(Staking::chill(Origin::signed(30))); + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + let init_balance_2 = Balances::free_balance(&2); + let init_balance_10 = Balances::free_balance(&10); + + // Stingy validator. + assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something + reward_all_elected(); + start_era(1); + + // 2 is elected. + // and fucks up the slot stake. + assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); + assert_eq!(Staking::slot_stake(), 1); + + // Old ones are rewarded. + assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3); + // no rewards paid to 2. This was initial election. + assert_eq!(Balances::free_balance(&2), init_balance_2); + + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 100); // Test is meaningfull if reward something + reward_all_elected(); + start_era(2); + + assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); + assert_eq!(Staking::slot_stake(), 1); + + assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_1 / 3); + assert_eq!( + Balances::free_balance(&10), + init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3, + ); + check_exposure_all(); + check_nominator_all(); + }); +} + +#[cfg(feature = "equalize")] +#[test] +fn phragmen_linear_worse_case_equalize() { + ExtBuilder::default() + .nominate(false) + .validator_pool(true) + .fair(true) + .build() + .execute_with(|| { + bond_validator(50, 1000); + bond_validator(60, 1000); + bond_validator(70, 1000); + + bond_nominator(2, 2000, vec![11]); + bond_nominator(4, 1000, vec![11, 21]); + bond_nominator(6, 1000, vec![21, 31]); + bond_nominator(8, 1000, vec![31, 41]); + bond_nominator(110, 1000, vec![41, 51]); + bond_nominator(120, 1000, vec![51, 61]); + bond_nominator(130, 1000, vec![61, 71]); + + for i in &[10, 20, 30, 40, 50, 60, 70] { + assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); + } + + assert_eq_uvec!(validator_controllers(), vec![40, 30]); + assert_ok!(Staking::set_validator_count(Origin::ROOT, 7)); + + start_era(1); + + assert_eq_uvec!(validator_controllers(), vec![10, 60, 40, 20, 50, 30, 70]); + + assert_eq_error_rate!(Staking::stakers(11).total, 3000, 2); + assert_eq_error_rate!(Staking::stakers(21).total, 2255, 2); + assert_eq_error_rate!(Staking::stakers(31).total, 2255, 2); + assert_eq_error_rate!(Staking::stakers(41).total, 1925, 2); + assert_eq_error_rate!(Staking::stakers(51).total, 1870, 2); + assert_eq_error_rate!(Staking::stakers(61).total, 1890, 2); + assert_eq_error_rate!(Staking::stakers(71).total, 1800, 2); + + check_exposure_all(); + check_nominator_all(); + }) +} + +#[test] +fn new_era_elects_correct_number_of_validators() { + ExtBuilder::default() + .nominate(true) + .validator_pool(true) + .fair(true) + .validator_count(1) + .build() + .execute_with(|| { + assert_eq!(Staking::validator_count(), 1); + assert_eq!(validator_controllers().len(), 1); + + System::set_block_number(1); + Session::on_initialize(System::block_number()); + + assert_eq!(validator_controllers().len(), 1); + check_exposure_all(); + check_nominator_all(); + }) +} + +#[test] +fn phragmen_should_not_overflow_validators() { + ExtBuilder::default().nominate(false).build().execute_with(|| { + let _ = Staking::chill(Origin::signed(10)); + let _ = Staking::chill(Origin::signed(20)); + + bond_validator(2, u64::max_value()); + bond_validator(4, u64::max_value()); + + bond_nominator(6, u64::max_value() / 2, vec![3, 5]); + bond_nominator(8, u64::max_value() / 2, vec![3, 5]); + + start_era(1); + + assert_eq_uvec!(validator_controllers(), vec![4, 2]); + + // This test will fail this. Will saturate. + // check_exposure_all(); + assert_eq!(Staking::stakers(3).total, u64::max_value()); + assert_eq!(Staking::stakers(5).total, u64::max_value()); + }) +} + +#[test] +fn phragmen_should_not_overflow_nominators() { + ExtBuilder::default().nominate(false).build().execute_with(|| { + let _ = Staking::chill(Origin::signed(10)); + let _ = Staking::chill(Origin::signed(20)); + + bond_validator(2, u64::max_value() / 2); + bond_validator(4, u64::max_value() / 2); + + bond_nominator(6, u64::max_value(), vec![3, 5]); + bond_nominator(8, u64::max_value(), vec![3, 5]); + + start_era(1); + + assert_eq_uvec!(validator_controllers(), vec![4, 2]); + + // Saturate. + assert_eq!(Staking::stakers(3).total, u64::max_value()); + assert_eq!(Staking::stakers(5).total, u64::max_value()); + }) +} + +#[test] +fn phragmen_should_not_overflow_ultimate() { + ExtBuilder::default().nominate(false).build().execute_with(|| { + bond_validator(2, u64::max_value()); + bond_validator(4, u64::max_value()); + + bond_nominator(6, u64::max_value(), vec![3, 5]); + bond_nominator(8, u64::max_value(), vec![3, 5]); + + start_era(1); + + assert_eq_uvec!(validator_controllers(), vec![4, 2]); + + // Saturate. + assert_eq!(Staking::stakers(3).total, u64::max_value()); + assert_eq!(Staking::stakers(5).total, u64::max_value()); + }) +} + +#[test] +fn reward_validator_slashing_validator_doesnt_overflow() { + ExtBuilder::default().build().execute_with(|| { + let stake = u32::max_value() as u64 * 2; + let reward_slash = u32::max_value() as u64 * 2; + + // Assert multiplication overflows in balance arithmetic. + assert!(stake.checked_mul(reward_slash).is_none()); + + // Set staker + let _ = Balances::make_free_balance_be(&11, stake); + >::insert(&11, Exposure { total: stake, own: stake, others: vec![] }); + + // Check reward + let _ = Staking::reward_validator(&11, reward_slash); + assert_eq!(Balances::total_balance(&11), stake * 2); + + // Set staker + let _ = Balances::make_free_balance_be(&11, stake); + let _ = Balances::make_free_balance_be(&2, stake); + + // only slashes out of bonded stake are applied. without this line, + // it is 0. + Staking::bond(Origin::signed(2), 20000, stake - 1, RewardDestination::default()).unwrap(); + >::insert(&11, Exposure { total: stake, own: 1, others: vec![ + IndividualExposure { who: 2, value: stake - 1 } + ]}); + + + // Check slashing + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(100)], + ); + + assert_eq!(Balances::total_balance(&11), stake - 1); + assert_eq!(Balances::total_balance(&2), 1); + }) +} + +#[test] +fn reward_from_authorship_event_handler_works() { + ExtBuilder::default().build().execute_with(|| { + use pallet_authorship::EventHandler; + + assert_eq!(>::author(), 11); + + >::note_author(11); + >::note_uncle(21, 1); + // An uncle author that is not currently elected doesn't get rewards, + // but the block producer does get reward for referencing it. + >::note_uncle(31, 1); + // Rewarding the same two times works. + >::note_uncle(11, 1); + + // Not mandatory but must be coherent with rewards + assert_eq!(>::get(), vec![21, 11]); + + // 21 is rewarded as an uncle producer + // 11 is rewarded as a block producer and uncle referencer and uncle producer + assert_eq!(CurrentEraPointsEarned::get().individual, vec![1, 20 + 2 * 3 + 1]); + assert_eq!(CurrentEraPointsEarned::get().total, 28); + }) +} + +#[test] +fn add_reward_points_fns_works() { + ExtBuilder::default().build().execute_with(|| { + let validators = >::current_elected(); + // Not mandatory but must be coherent with rewards + assert_eq!(validators, vec![21, 11]); + + >::reward_by_indices(vec![ + (0, 1), + (1, 1), + (2, 1), + (1, 1), + ]); + + >::reward_by_ids(vec![ + (21, 1), + (11, 1), + (31, 1), + (11, 1), + ]); + + assert_eq!(CurrentEraPointsEarned::get().individual, vec![2, 4]); + assert_eq!(CurrentEraPointsEarned::get().total, 6); + }) +} + +#[test] +fn unbonded_balance_is_not_slashable() { + ExtBuilder::default().build().execute_with(|| { + // total amount staked is slashable. + assert_eq!(Staking::slashable_balance_of(&11), 1000); + + assert_ok!(Staking::unbond(Origin::signed(10), 800)); + + // only the active portion. + assert_eq!(Staking::slashable_balance_of(&11), 200); + }) +} + +#[test] +fn era_is_always_same_length() { + // This ensures that the sessions is always of the same length if there is no forcing no + // session changes. + ExtBuilder::default().build().execute_with(|| { + start_era(1); + assert_eq!(Staking::current_era_start_session_index(), SessionsPerEra::get()); + + start_era(2); + assert_eq!(Staking::current_era_start_session_index(), SessionsPerEra::get() * 2); + + let session = Session::current_index(); + ForceEra::put(Forcing::ForceNew); + advance_session(); + assert_eq!(Staking::current_era(), 3); + assert_eq!(Staking::current_era_start_session_index(), session + 1); + + start_era(4); + assert_eq!(Staking::current_era_start_session_index(), session + SessionsPerEra::get() + 1); + }); +} + +#[test] +fn offence_forces_new_era() { + ExtBuilder::default().build().execute_with(|| { + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(5)], + ); + + assert_eq!(Staking::force_era(), Forcing::ForceNew); + }); +} + +#[test] +fn offence_ensures_new_era_without_clobbering() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Staking::force_new_era_always(Origin::ROOT)); + + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(5)], + ); + + assert_eq!(Staking::force_era(), Forcing::ForceAlways); + }); +} + +#[test] +fn offence_deselects_validator_when_slash_is_zero() { + ExtBuilder::default().build().execute_with(|| { + assert!(>::exists(11)); + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(0)], + ); + assert_eq!(Staking::force_era(), Forcing::ForceNew); + assert!(!>::exists(11)); + }); +} + +#[test] +fn slashing_performed_according_exposure() { + // This test checks that slashing is performed according the exposure (or more precisely, + // historical exposure), not the current balance. + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Staking::stakers(&11).own, 1000); + + // Handle an offence with a historical exposure. + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Exposure { + total: 500, + own: 500, + others: vec![], + }, + ), + reporters: vec![], + }], + &[Perbill::from_percent(50)], + ); + + // The stash account should be slashed for 250 (50% of 500). + assert_eq!(Balances::free_balance(&11), 1000 - 250); + }); +} + +#[test] +fn slash_in_old_span_does_not_deselect() { + ExtBuilder::default().build().execute_with(|| { + start_era(1); + + assert!(>::exists(11)); + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(0)], + ); + assert_eq!(Staking::force_era(), Forcing::ForceNew); + assert!(!>::exists(11)); + + start_era(2); + + Staking::validate(Origin::signed(10), Default::default()).unwrap(); + assert_eq!(Staking::force_era(), Forcing::NotForcing); + assert!(>::exists(11)); + + start_era(3); + + // this staker is in a new slashing span now, having re-registered after + // their prior slash. + + on_offence_in_era( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(0)], + 1, + ); + + // not for zero-slash. + assert_eq!(Staking::force_era(), Forcing::NotForcing); + assert!(>::exists(11)); + + on_offence_in_era( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(100)], + 1, + ); + + // or non-zero. + assert_eq!(Staking::force_era(), Forcing::NotForcing); + assert!(>::exists(11)); + assert_ledger_consistent(11); + }); +} + +#[test] +fn reporters_receive_their_slice() { + // This test verifies that the reporters of the offence receive their slice from the slashed + // amount. + ExtBuilder::default().build().execute_with(|| { + // The reporters' reward is calculated from the total exposure. + #[cfg(feature = "equalize")] + let initial_balance = 1250; + #[cfg(not(feature = "equalize"))] + let initial_balance = 1125; + + assert_eq!(Staking::stakers(&11).total, initial_balance); + + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![1, 2], + }], + &[Perbill::from_percent(50)], + ); + + // F1 * (reward_proportion * slash - 0) + // 50% * (10% * initial_balance / 2) + let reward = (initial_balance / 20) / 2; + let reward_each = reward / 2; // split into two pieces. + assert_eq!(Balances::free_balance(&1), 10 + reward_each); + assert_eq!(Balances::free_balance(&2), 20 + reward_each); + assert_ledger_consistent(11); + }); +} + +#[test] +fn subsequent_reports_in_same_span_pay_out_less() { + // This test verifies that the reporters of the offence receive their slice from the slashed + // amount. + ExtBuilder::default().build().execute_with(|| { + // The reporters' reward is calculated from the total exposure. + #[cfg(feature = "equalize")] + let initial_balance = 1250; + #[cfg(not(feature = "equalize"))] + let initial_balance = 1125; + + assert_eq!(Staking::stakers(&11).total, initial_balance); + + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![1], + }], + &[Perbill::from_percent(20)], + ); + + // F1 * (reward_proportion * slash - 0) + // 50% * (10% * initial_balance * 20%) + let reward = (initial_balance / 5) / 20; + assert_eq!(Balances::free_balance(&1), 10 + reward); + + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![1], + }], + &[Perbill::from_percent(50)], + ); + + let prior_payout = reward; + + // F1 * (reward_proportion * slash - prior_payout) + // 50% * (10% * (initial_balance / 2) - prior_payout) + let reward = ((initial_balance / 20) - prior_payout) / 2; + assert_eq!(Balances::free_balance(&1), 10 + prior_payout + reward); + assert_ledger_consistent(11); + }); +} + +#[test] +fn invulnerables_are_not_slashed() { + // For invulnerable validators no slashing is performed. + ExtBuilder::default().invulnerables(vec![11]).build().execute_with(|| { + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&21), 2000); + + let exposure = Staking::stakers(&21); + let initial_balance = Staking::slashable_balance_of(&21); + + let nominator_balances: Vec<_> = exposure.others + .iter().map(|o| Balances::free_balance(&o.who)).collect(); + + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + OffenceDetails { + offender: (21, Staking::stakers(&21)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(50), Perbill::from_percent(20)], + ); + + // The validator 11 hasn't been slashed, but 21 has been. + assert_eq!(Balances::free_balance(&11), 1000); + // 2000 - (0.2 * initial_balance) + assert_eq!(Balances::free_balance(&21), 2000 - (2 * initial_balance / 10)); + + // ensure that nominators were slashed as well. + for (initial_balance, other) in nominator_balances.into_iter().zip(exposure.others) { + assert_eq!( + Balances::free_balance(&other.who), + initial_balance - (2 * other.value / 10), + ); + } + assert_ledger_consistent(11); + assert_ledger_consistent(21); + }); +} + +#[test] +fn dont_slash_if_fraction_is_zero() { + // Don't slash if the fraction is zero. + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Balances::free_balance(&11), 1000); + + on_offence_now( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(0)], + ); + + // The validator hasn't been slashed. The new era is not forced. + assert_eq!(Balances::free_balance(&11), 1000); + assert_ledger_consistent(11); + }); +} + +#[test] +fn only_slash_for_max_in_era() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Balances::free_balance(&11), 1000); + + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(50)], + ); + + // The validator has been slashed and has been force-chilled. + assert_eq!(Balances::free_balance(&11), 500); + assert_eq!(Staking::force_era(), Forcing::ForceNew); + + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(25)], + ); + + // The validator has not been slashed additionally. + assert_eq!(Balances::free_balance(&11), 500); + + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(60)], + ); + + // The validator got slashed 10% more. + assert_eq!(Balances::free_balance(&11), 400); + assert_ledger_consistent(11); + }) +} + +#[test] +fn garbage_collection_after_slashing() { + ExtBuilder::default().existential_deposit(1).build().execute_with(|| { + assert_eq!(Balances::free_balance(&11), 256_000); + + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); + + assert_eq!(Balances::free_balance(&11), 256_000 - 25_600); + assert!(::SlashingSpans::get(&11).is_some()); + assert_eq!(::SpanSlash::get(&(11, 0)).amount_slashed(), &25_600); + + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(100)], + ); + + // validator and nominator slash in era are garbage-collected by era change, + // so we don't test those here. + + assert_eq!(Balances::free_balance(&11), 0); + assert!(::SlashingSpans::get(&11).is_none()); + assert_eq!(::SpanSlash::get(&(11, 0)).amount_slashed(), &0); + }) +} + +#[test] +fn garbage_collection_on_window_pruning() { + ExtBuilder::default().build().execute_with(|| { + start_era(1); + + assert_eq!(Balances::free_balance(&11), 1000); + + let exposure = Staking::stakers(&11); + assert_eq!(Balances::free_balance(&101), 2000); + let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; + + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); + + let now = Staking::current_era(); + + assert_eq!(Balances::free_balance(&11), 900); + assert_eq!(Balances::free_balance(&101), 2000 - (nominated_value / 10)); + + assert!(::ValidatorSlashInEra::get(&now, &11).is_some()); + assert!(::NominatorSlashInEra::get(&now, &101).is_some()); + + // + 1 because we have to exit the bonding window. + for era in (0..(BondingDuration::get() + 1)).map(|offset| offset + now + 1) { + assert!(::ValidatorSlashInEra::get(&now, &11).is_some()); + assert!(::NominatorSlashInEra::get(&now, &101).is_some()); + + start_era(era); + } + + assert!(::ValidatorSlashInEra::get(&now, &11).is_none()); + assert!(::NominatorSlashInEra::get(&now, &101).is_none()); + }) +} + +#[test] +fn slashing_nominators_by_span_max() { + ExtBuilder::default().build().execute_with(|| { + start_era(1); + start_era(2); + start_era(3); + + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&21), 2000); + assert_eq!(Balances::free_balance(&101), 2000); + assert_eq!(Staking::slashable_balance_of(&21), 1000); + + + let exposure_11 = Staking::stakers(&11); + let exposure_21 = Staking::stakers(&21); + assert_eq!(Balances::free_balance(&101), 2000); + let nominated_value_11 = exposure_11.others.iter().find(|o| o.who == 101).unwrap().value; + let nominated_value_21 = exposure_21.others.iter().find(|o| o.who == 101).unwrap().value; + + on_offence_in_era( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + 2, + ); + + assert_eq!(Balances::free_balance(&11), 900); + + let slash_1_amount = Perbill::from_percent(10) * nominated_value_11; + assert_eq!(Balances::free_balance(&101), 2000 - slash_1_amount); + + let expected_spans = vec![ + slashing::SlashingSpan { index: 1, start: 4, length: None }, + slashing::SlashingSpan { index: 0, start: 0, length: Some(4) }, + ]; + + let get_span = |account| ::SlashingSpans::get(&account).unwrap(); + + assert_eq!( + get_span(11).iter().collect::>(), + expected_spans, + ); + + assert_eq!( + get_span(101).iter().collect::>(), + expected_spans, + ); + + // second slash: higher era, higher value, same span. + on_offence_in_era( + &[ + OffenceDetails { + offender: (21, Staking::stakers(&21)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(30)], + 3, + ); + + // 11 was not further slashed, but 21 and 101 were. + assert_eq!(Balances::free_balance(&11), 900); + assert_eq!(Balances::free_balance(&21), 1700); + + let slash_2_amount = Perbill::from_percent(30) * nominated_value_21; + assert!(slash_2_amount > slash_1_amount); + + // only the maximum slash in a single span is taken. + assert_eq!(Balances::free_balance(&101), 2000 - slash_2_amount); + + // third slash: in same era and on same validator as first, higher + // in-era value, but lower slash value than slash 2. + on_offence_in_era( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(20)], + 2, + ); + + // 11 was further slashed, but 21 and 101 were not. + assert_eq!(Balances::free_balance(&11), 800); + assert_eq!(Balances::free_balance(&21), 1700); + + let slash_3_amount = Perbill::from_percent(20) * nominated_value_21; + assert!(slash_3_amount < slash_2_amount); + assert!(slash_3_amount > slash_1_amount); + + // only the maximum slash in a single span is taken. + assert_eq!(Balances::free_balance(&101), 2000 - slash_2_amount); + }); +} + +#[test] +fn slashes_are_summed_across_spans() { + ExtBuilder::default().build().execute_with(|| { + start_era(1); + start_era(2); + start_era(3); + + assert_eq!(Balances::free_balance(&21), 2000); + assert_eq!(Staking::slashable_balance_of(&21), 1000); + + let get_span = |account| ::SlashingSpans::get(&account).unwrap(); + + on_offence_now( + &[ + OffenceDetails { + offender: (21, Staking::stakers(&21)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); + + let expected_spans = vec![ + slashing::SlashingSpan { index: 1, start: 4, length: None }, + slashing::SlashingSpan { index: 0, start: 0, length: Some(4) }, + ]; + + assert_eq!(get_span(21).iter().collect::>(), expected_spans); + assert_eq!(Balances::free_balance(&21), 1900); + + // 21 has been force-chilled. re-signal intent to validate. + Staking::validate(Origin::signed(20), Default::default()).unwrap(); + + start_era(4); + + assert_eq!(Staking::slashable_balance_of(&21), 900); + + on_offence_now( + &[ + OffenceDetails { + offender: (21, Staking::stakers(&21)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); + + let expected_spans = vec![ + slashing::SlashingSpan { index: 2, start: 5, length: None }, + slashing::SlashingSpan { index: 1, start: 4, length: Some(1) }, + slashing::SlashingSpan { index: 0, start: 0, length: Some(4) }, + ]; + + assert_eq!(get_span(21).iter().collect::>(), expected_spans); + assert_eq!(Balances::free_balance(&21), 1810); + }); +} + +#[test] +fn deferred_slashes_are_deferred() { + ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| { + start_era(1); + + assert_eq!(Balances::free_balance(&11), 1000); + + let exposure = Staking::stakers(&11); + assert_eq!(Balances::free_balance(&101), 2000); + let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; + + on_offence_now( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); + + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&101), 2000); + + start_era(2); + + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&101), 2000); + + start_era(3); + + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&101), 2000); + + // at the start of era 4, slashes from era 1 are processed, + // after being deferred for at least 2 full eras. + start_era(4); + + assert_eq!(Balances::free_balance(&11), 900); + assert_eq!(Balances::free_balance(&101), 2000 - (nominated_value / 10)); + }) +} + +#[test] +fn remove_deferred() { + ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| { + start_era(1); + + assert_eq!(Balances::free_balance(&11), 1000); + + let exposure = Staking::stakers(&11); + assert_eq!(Balances::free_balance(&101), 2000); + let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; + + on_offence_now( + &[ + OffenceDetails { + offender: (11, exposure.clone()), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); + + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&101), 2000); + + start_era(2); + + on_offence_in_era( + &[ + OffenceDetails { + offender: (11, exposure.clone()), + reporters: vec![], + }, + ], + &[Perbill::from_percent(15)], + 1, + ); + + Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0]).unwrap(); + + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&101), 2000); + + start_era(3); + + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&101), 2000); + + // at the start of era 4, slashes from era 1 are processed, + // after being deferred for at least 2 full eras. + start_era(4); + + // the first slash for 10% was cancelled, so no effect. + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&101), 2000); + + start_era(5); + + let slash_10 = Perbill::from_percent(10); + let slash_15 = Perbill::from_percent(15); + let initial_slash = slash_10 * nominated_value; + + let total_slash = slash_15 * nominated_value; + let actual_slash = total_slash - initial_slash; + + // 5% slash (15 - 10) processed now. + assert_eq!(Balances::free_balance(&11), 950); + assert_eq!(Balances::free_balance(&101), 2000 - actual_slash); + }) +} + +#[test] +fn remove_multi_deferred() { + ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| { + start_era(1); + + assert_eq!(Balances::free_balance(&11), 1000); + + let exposure = Staking::stakers(&11); + assert_eq!(Balances::free_balance(&101), 2000); + + on_offence_now( + &[ + OffenceDetails { + offender: (11, exposure.clone()), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); + + on_offence_now( + &[ + OffenceDetails { + offender: (21, Staking::stakers(&21)), + reporters: vec![], + } + ], + &[Perbill::from_percent(10)], + ); + + on_offence_now( + &[ + OffenceDetails { + offender: (11, exposure.clone()), + reporters: vec![], + }, + ], + &[Perbill::from_percent(25)], + ); + + assert_eq!(::UnappliedSlashes::get(&1).len(), 3); + Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0, 2]).unwrap(); + + let slashes = ::UnappliedSlashes::get(&1); + assert_eq!(slashes.len(), 1); + assert_eq!(slashes[0].validator, 21); + }) +} + +#[test] +fn version_initialized() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(::StorageVersion::get(), crate::migration::CURRENT_VERSION); + }); +} + +#[test] +fn slash_kicks_validators_not_nominators() { + ExtBuilder::default().build().execute_with(|| { + start_era(1); + + assert_eq!(Balances::free_balance(&11), 1000); + + let exposure = Staking::stakers(&11); + assert_eq!(Balances::free_balance(&101), 2000); + let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; + + on_offence_now( + &[ + OffenceDetails { + offender: (11, exposure.clone()), + reporters: vec![], + }, + ], + &[Perbill::from_percent(10)], + ); + + assert_eq!(Balances::free_balance(&11), 900); + assert_eq!(Balances::free_balance(&101), 2000 - (nominated_value / 10)); + + // This is the best way to check that the validator was chilled; `get` will + // return default value. + for (stash, _) in ::Validators::enumerate() { + assert!(stash != 11); + } + + let nominations = ::Nominators::get(&101).unwrap(); + + // and make sure that the vote will be ignored even if the validator + // re-registers. + let last_slash = ::SlashingSpans::get(&11).unwrap().last_start(); + assert!(nominations.submitted_in < last_slash); + }); +} diff --git a/frame/sudo/Cargo.toml b/frame/sudo/Cargo.toml new file mode 100644 index 0000000000000..c97d04f9c7ce1 --- /dev/null +++ b/frame/sudo/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "pallet-sudo" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "sp-io/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/sudo/src/lib.rs b/frame/sudo/src/lib.rs new file mode 100644 index 0000000000000..e49596b4bdb9b --- /dev/null +++ b/frame/sudo/src/lib.rs @@ -0,0 +1,217 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Sudo Module +//! +//! - [`sudo::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! The Sudo module allows for a single account (called the "sudo key") +//! to execute dispatchable functions that require a `Root` call +//! or designate a new account to replace them as the sudo key. +//! Only one account can be the sudo key at a time. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! Only the sudo key can call the dispatchable functions from the Sudo module. +//! +//! * `sudo` - Make a `Root` call to a dispatchable function. +//! * `set_key` - Assign a new account to be the sudo key. +//! +//! ## Usage +//! +//! ### Executing Privileged Functions +//! +//! The Sudo module itself is not intended to be used within other modules. +//! Instead, you can build "privileged functions" (i.e. functions that require `Root` origin) in other modules. +//! You can execute these privileged functions by calling `sudo` with the sudo key account. +//! Privileged functions cannot be directly executed via an extrinsic. +//! +//! Learn more about privileged functions and `Root` origin in the [`Origin`] type documentation. +//! +//! ### Simple Code Snippet +//! +//! This is an example of a module that exposes a privileged function: +//! +//! ``` +//! use frame_support::{decl_module, dispatch}; +//! use frame_system::{self as system, ensure_root}; +//! +//! pub trait Trait: frame_system::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn privileged_function(origin) -> dispatch::DispatchResult { +//! ensure_root(origin)?; +//! +//! // do something... +//! +//! Ok(()) +//! } +//! } +//! } +//! # fn main() {} +//! ``` +//! +//! ## Genesis Config +//! +//! The Sudo module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). +//! You need to set an initial superuser account as the sudo `key`. +//! +//! ## Related Modules +//! +//! * [Consensus](../frame_consensus/index.html) +//! * [Democracy](../pallet_democracy/index.html) +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html +//! [`Origin`]: https://docs.substrate.dev/docs/substrate-types + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use sp_runtime::{traits::{StaticLookup, Dispatchable}, DispatchError}; + +use frame_support::{ + Parameter, decl_module, decl_event, decl_storage, decl_error, ensure, + weights::SimpleDispatchInfo, +}; +use frame_system::{self as system, ensure_signed}; + +pub trait Trait: frame_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 it's working on. + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn deposit_event() = default; + + /// Authenticates the sudo key and dispatches a function call with `Root` origin. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB write (event). + /// - Unknown weight of derivative `proposal` execution. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn sudo(origin, proposal: Box) { + // This is a public call, so we ensure that the origin is some signed account. + let sender = ensure_signed(origin)?; + ensure!(sender == Self::key(), Error::::RequireSudo); + + let res = match proposal.dispatch(frame_system::RawOrigin::Root.into()) { + Ok(_) => true, + Err(e) => { + let e: DispatchError = e.into(); + sp_runtime::print(e); + false + } + }; + + Self::deposit_event(RawEvent::Sudid(res)); + } + + /// Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo key. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB change. + /// # + 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(), Error::::RequireSudo); + let new = T::Lookup::lookup(new)?; + + Self::deposit_event(RawEvent::KeyChanged(Self::key())); + >::put(new); + } + + /// Authenticates the sudo key and dispatches a function call with `Signed` origin from + /// a given account. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB write (event). + /// - Unknown weight of derivative `proposal` execution. + /// # + #[weight = SimpleDispatchInfo::FixedOperational(0)] + fn sudo_as(origin, who: ::Source, proposal: Box) { + // This is a public call, so we ensure that the origin is some signed account. + let sender = ensure_signed(origin)?; + ensure!(sender == Self::key(), Error::::RequireSudo); + + let who = T::Lookup::lookup(who)?; + + let res = match proposal.dispatch(frame_system::RawOrigin::Signed(who).into()) { + Ok(_) => true, + Err(e) => { + let e: DispatchError = e.into(); + sp_runtime::print(e); + false + } + }; + + Self::deposit_event(RawEvent::SudoAsDone(res)); + } + } +} + +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), + /// A sudo just took place. + SudoAsDone(bool), + } +); + +decl_storage! { + trait Store for Module as Sudo { + /// The `AccountId` of the sudo key. + Key get(fn key) config(): T::AccountId; + } +} + +decl_error! { + /// Error for the Sudo module + pub enum Error for Module { + /// Sender must be the Sudo account + RequireSudo, + } +} diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml new file mode 100644 index 0000000000000..1695375d36832 --- /dev/null +++ b/frame/support/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "frame-support" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4" +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } +frame-metadata = { version = "2.0.0", default-features = false, path = "../metadata" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io ={ path = "../../primitives/io", default-features = false } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-arithmetic = { version = "2.0.0", default-features = false, path = "../../primitives/arithmetic" } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +frame-support-procedural = { version = "2.0.0", path = "./procedural" } +paste = "0.1.6" +once_cell = { version = "0.2.4", default-features = false, optional = true } +sp-state-machine = { version = "2.0.0", optional = true, path = "../../primitives/state-machine" } +bitmask = { version = "0.5.0", default-features = false } +impl-trait-for-tuples = "0.1.3" +tracing = { version = "0.1.10", optional = true } + +[dev-dependencies] +pretty_assertions = "0.6.1" +frame-system = { version = "2.0.0", path = "../system" } + +[features] +default = ["std"] +std = [ + "tracing", + "once_cell", + "bitmask/std", + "serde", + "sp-io/std", + "codec/std", + "sp-std/std", + "sp-runtime/std", + "sp-arithmetic/std", + "frame-metadata/std", + "sp-inherents/std", + "sp-state-machine", +] +nightly = [] +strict = [] diff --git a/frame/support/procedural/Cargo.toml b/frame/support/procedural/Cargo.toml new file mode 100644 index 0000000000000..321002e08bdd7 --- /dev/null +++ b/frame/support/procedural/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "frame-support-procedural" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +frame-support-procedural-tools = { version = "2.0.0", path = "./tools" } +proc-macro2 = "1.0.6" +quote = "1.0.2" +syn = { version = "1.0.7", features = ["full"] } diff --git a/frame/support/procedural/src/construct_runtime/mod.rs b/frame/support/procedural/src/construct_runtime/mod.rs new file mode 100644 index 0000000000000..7e66610641dfa --- /dev/null +++ b/frame/support/procedural/src/construct_runtime/mod.rs @@ -0,0 +1,383 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +mod parse; + +use frame_support_procedural_tools::syn_ext as ext; +use frame_support_procedural_tools::{generate_crate_access, generate_hidden_includes}; +use parse::{ModuleDeclaration, RuntimeDefinition, WhereSection}; +use proc_macro::TokenStream; +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use syn::{Ident, Result}; + +/// The fixed name of the system module. +const SYSTEM_MODULE_NAME: &str = "System"; + +pub fn construct_runtime(input: TokenStream) -> TokenStream { + let definition = syn::parse_macro_input!(input as RuntimeDefinition); + construct_runtime_parsed(definition) + .unwrap_or_else(|e| e.to_compile_error()) + .into() +} + +fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result { + let RuntimeDefinition { + name, + where_section: WhereSection { + block, + node_block, + unchecked_extrinsic, + .. + }, + modules: + ext::Braces { + content: ext::Punctuated { inner: modules, .. }, + token: modules_token, + }, + .. + } = definition; + + // Assert we have system module declared + let system_module = match find_system_module(modules.iter()) { + Some(sm) => sm, + None => { + return Err(syn::Error::new( + modules_token.span, + "`System` module declaration is missing. \ + Please add this line: `System: system::{Module, Call, Storage, Config, Event},`", + )) + } + }; + let hidden_crate_name = "construct_runtime"; + let scrate = generate_crate_access(&hidden_crate_name, "frame-support"); + let scrate_decl = generate_hidden_includes(&hidden_crate_name, "frame-support"); + + let all_but_system_modules = modules.iter().filter(|module| module.name != SYSTEM_MODULE_NAME); + + let outer_event = decl_outer_event_or_origin( + &name, + all_but_system_modules.clone(), + &system_module, + &scrate, + DeclOuterKind::Event, + )?; + let outer_origin = decl_outer_event_or_origin( + &name, + all_but_system_modules.clone(), + &system_module, + &scrate, + DeclOuterKind::Origin, + )?; + let all_modules = decl_all_modules(&name, modules.iter()); + let module_to_index = decl_module_to_index(modules.iter(), modules.len(), &scrate); + + let dispatch = decl_outer_dispatch(&name, modules.iter(), &scrate); + let metadata = decl_runtime_metadata(&name, modules.iter(), &scrate); + let outer_config = decl_outer_config(&name, modules.iter(), &scrate); + let inherent = decl_outer_inherent(&block, &unchecked_extrinsic, modules.iter(), &scrate); + let validate_unsigned = decl_validate_unsigned(&name, modules.iter(), &scrate); + + Ok(quote!( + #scrate_decl + + #[derive(Clone, Copy, PartialEq, Eq)] + #[cfg_attr(feature = "std", derive(Debug))] + pub struct #name; + impl #scrate::sp_runtime::traits::GetNodeBlockType for #name { + type NodeBlock = #node_block; + } + impl #scrate::sp_runtime::traits::GetRuntimeBlockType for #name { + type RuntimeBlock = #block; + } + + #outer_event + + #outer_origin + + #all_modules + + #module_to_index + + #dispatch + + #metadata + + #outer_config + + #inherent + + #validate_unsigned + ) + .into()) +} + +fn decl_validate_unsigned<'a>( + runtime: &'a Ident, + module_declarations: impl Iterator, + scrate: &'a TokenStream2, +) -> TokenStream2 { + let modules_tokens = module_declarations + .filter(|module_declaration| module_declaration.exists_part("ValidateUnsigned")) + .map(|module_declaration| &module_declaration.name); + quote!( + #scrate::impl_outer_validate_unsigned!( + impl ValidateUnsigned for #runtime { + #( #modules_tokens )* + } + ); + ) +} + +fn decl_outer_inherent<'a>( + block: &'a syn::TypePath, + unchecked_extrinsic: &'a syn::TypePath, + module_declarations: impl Iterator, + scrate: &'a TokenStream2, +) -> TokenStream2 { + let modules_tokens = module_declarations.filter_map(|module_declaration| { + let maybe_config_part = module_declaration.find_part("Inherent"); + maybe_config_part.map(|config_part| { + let arg = config_part + .args + .as_ref() + .and_then(|parens| parens.content.inner.iter().next()) + .unwrap_or(&module_declaration.name); + let name = &module_declaration.name; + quote!(#name : #arg,) + }) + }); + quote!( + #scrate::impl_outer_inherent!( + impl Inherents where Block = #block, UncheckedExtrinsic = #unchecked_extrinsic { + #(#modules_tokens)* + } + ); + ) +} + +fn decl_outer_config<'a>( + runtime: &'a Ident, + module_declarations: impl Iterator, + scrate: &'a TokenStream2, +) -> TokenStream2 { + let modules_tokens = module_declarations + .filter_map(|module_declaration| { + module_declaration.find_part("Config").map(|part| { + let transformed_generics: Vec<_> = part + .generics + .params + .iter() + .map(|param| quote!(<#param>)) + .collect(); + (module_declaration, transformed_generics) + }) + }) + .map(|(module_declaration, generics)| { + let module = &module_declaration.module; + let name = Ident::new( + &format!("{}Config", module_declaration.name), + module_declaration.name.span(), + ); + let instance = module_declaration.instance.as_ref().into_iter(); + quote!( + #name => + #module #(#instance)* #(#generics)*, + ) + }); + quote!( + #scrate::sp_runtime::impl_outer_config! { + pub struct GenesisConfig for #runtime { + #(#modules_tokens)* + } + } + ) +} + +fn decl_runtime_metadata<'a>( + runtime: &'a Ident, + module_declarations: impl Iterator, + scrate: &'a TokenStream2, +) -> TokenStream2 { + let modules_tokens = module_declarations + .filter_map(|module_declaration| { + module_declaration.find_part("Module").map(|_| { + let filtered_names: Vec<_> = module_declaration + .module_parts() + .into_iter() + .filter(|part| part.name != "Module") + .map(|part| part.name.clone()) + .collect(); + (module_declaration, filtered_names) + }) + }) + .map(|(module_declaration, filtered_names)| { + let module = &module_declaration.module; + let name = &module_declaration.name; + let instance = module_declaration + .instance + .as_ref() + .map(|name| quote!(<#name>)) + .into_iter(); + quote!(#module::Module #(#instance)* as #name with #(#filtered_names)* ,) + }); + quote!( + #scrate::impl_runtime_metadata!{ + for #runtime with modules + #(#modules_tokens)* + } + ) +} + +fn decl_outer_dispatch<'a>( + runtime: &'a Ident, + module_declarations: impl Iterator, + scrate: &'a TokenStream2, +) -> TokenStream2 { + let modules_tokens = module_declarations + .filter(|module_declaration| module_declaration.exists_part("Call")) + .map(|module_declaration| { + let module = &module_declaration.module; + let name = &module_declaration.name; + quote!(#module::#name) + }); + quote!( + #scrate::impl_outer_dispatch! { + pub enum Call for #runtime where origin: Origin { + #(#modules_tokens,)* + } + } + ) +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +enum DeclOuterKind { + Event, + Origin, +} + +fn decl_outer_event_or_origin<'a>( + runtime_name: &'a Ident, + module_declarations: impl Iterator, + system_name: &'a Ident, + scrate: &'a TokenStream2, + kind: DeclOuterKind, +) -> syn::Result { + let mut modules_tokens = TokenStream2::new(); + let kind_str = format!("{:?}", kind); + for module_declaration in module_declarations { + match module_declaration.find_part(&kind_str) { + Some(module_entry) => { + let module = &module_declaration.module; + let instance = module_declaration.instance.as_ref(); + let generics = &module_entry.generics; + if instance.is_some() && generics.params.len() == 0 { + let msg = format!( + "Instantiable module with no generic `{}` cannot \ + be constructed: module `{}` must have generic `{}`", + kind_str, module_declaration.name, kind_str + ); + return Err(syn::Error::new(module_declaration.name.span(), msg)); + } + let tokens = quote!(#module #instance #generics ,); + modules_tokens.extend(tokens); + } + None => {} + } + } + let macro_call = match kind { + DeclOuterKind::Event => quote!(#scrate::impl_outer_event!), + DeclOuterKind::Origin => quote!(#scrate::impl_outer_origin!), + }; + let enum_name = Ident::new(kind_str.as_str(), Span::call_site()); + Ok(quote!( + #macro_call { + pub enum #enum_name for #runtime_name where system = #system_name { + #modules_tokens + } + } + )) +} + +fn decl_all_modules<'a>( + runtime: &'a Ident, + module_declarations: impl Iterator, +) -> TokenStream2 { + let mut types = TokenStream2::new(); + let mut names = Vec::new(); + for module_declaration in module_declarations { + let type_name = &module_declaration.name; + let module = &module_declaration.module; + let mut generics = vec![quote!(#runtime)]; + generics.extend( + module_declaration + .instance + .iter() + .map(|name| quote!(#module::#name)), + ); + let type_decl = quote!( + pub type #type_name = #module::Module <#(#generics),*>; + ); + types.extend(type_decl); + names.push(&module_declaration.name); + } + // Make nested tuple structure like (((Babe, Consensus), Grandpa), ...) + // But ignore the system module. + let all_modules = names.iter() + .filter(|n| **n != SYSTEM_MODULE_NAME) + .fold(TokenStream2::default(), |combined, name| quote!((#name, #combined))); + + quote!( + #types + type AllModules = ( #all_modules ); + ) +} + +fn decl_module_to_index<'a>( + module_declarations: impl Iterator, + num_modules: usize, + scrate: &TokenStream2, +) -> TokenStream2 { + let names = module_declarations.map(|d| &d.name); + let indices = 0..num_modules; + + quote!( + /// Provides an implementation of `ModuleToIndex` to map a module + /// to its index in the runtime. + pub struct ModuleToIndex; + + impl #scrate::traits::ModuleToIndex for ModuleToIndex { + fn module_to_index() -> Option { + let type_id = #scrate::sp_std::any::TypeId::of::(); + #( + if type_id == #scrate::sp_std::any::TypeId::of::<#names>() { + return Some(#indices) + } + )* + + None + } + } + ) +} + +fn find_system_module<'a>( + mut module_declarations: impl Iterator, +) -> Option<&'a Ident> { + module_declarations + .find(|decl| decl.name == SYSTEM_MODULE_NAME) + .map(|decl| &decl.module) +} diff --git a/frame/support/procedural/src/construct_runtime/parse.rs b/frame/support/procedural/src/construct_runtime/parse.rs new file mode 100644 index 0000000000000..0559c45bbcdd7 --- /dev/null +++ b/frame/support/procedural/src/construct_runtime/parse.rs @@ -0,0 +1,417 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use frame_support_procedural_tools::syn_ext as ext; +use proc_macro2::Span; +use std::collections::HashSet; +use syn::{ + parse::{Parse, ParseStream}, + spanned::Spanned, + token, Error, Ident, Result, Token, +}; + +mod keyword { + syn::custom_keyword!(Block); + syn::custom_keyword!(NodeBlock); + syn::custom_keyword!(UncheckedExtrinsic); +} + +#[derive(Debug)] +pub struct RuntimeDefinition { + pub visibility_token: Token![pub], + pub enum_token: Token![enum], + pub name: Ident, + pub where_section: WhereSection, + pub modules: ext::Braces>, +} + +impl Parse for RuntimeDefinition { + fn parse(input: ParseStream) -> Result { + Ok(Self { + visibility_token: input.parse()?, + enum_token: input.parse()?, + name: input.parse()?, + where_section: input.parse()?, + modules: input.parse()?, + }) + } +} + +#[derive(Debug)] +pub struct WhereSection { + pub block: syn::TypePath, + pub node_block: syn::TypePath, + pub unchecked_extrinsic: syn::TypePath, +} + +impl Parse for WhereSection { + fn parse(input: ParseStream) -> Result { + input.parse::()?; + let mut definitions = Vec::new(); + while !input.peek(token::Brace) { + let definition: WhereDefinition = input.parse()?; + definitions.push(definition); + if !input.peek(Token![,]) { + if !input.peek(token::Brace) { + return Err(input.error("Expected `,` or `{`")); + } + break; + } + input.parse::()?; + } + let block = remove_kind(input, WhereKind::Block, &mut definitions)?.value; + let node_block = remove_kind(input, WhereKind::NodeBlock, &mut definitions)?.value; + let unchecked_extrinsic = + remove_kind(input, WhereKind::UncheckedExtrinsic, &mut definitions)?.value; + if let Some(WhereDefinition { + ref kind_span, + ref kind, + .. + }) = definitions.first() + { + let msg = format!( + "`{:?}` was declared above. Please use exactly one delcataion for `{:?}`.", + kind, kind + ); + return Err(Error::new(*kind_span, msg)); + } + Ok(Self { + block, + node_block, + unchecked_extrinsic, + }) + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub enum WhereKind { + Block, + NodeBlock, + UncheckedExtrinsic, +} + +#[derive(Debug)] +pub struct WhereDefinition { + pub kind_span: Span, + pub kind: WhereKind, + pub value: syn::TypePath, +} + +impl Parse for WhereDefinition { + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + let (kind_span, kind) = if lookahead.peek(keyword::Block) { + (input.parse::()?.span(), WhereKind::Block) + } else if lookahead.peek(keyword::NodeBlock) { + ( + input.parse::()?.span(), + WhereKind::NodeBlock, + ) + } else if lookahead.peek(keyword::UncheckedExtrinsic) { + ( + input.parse::()?.span(), + WhereKind::UncheckedExtrinsic, + ) + } else { + return Err(lookahead.error()); + }; + + Ok(Self { + kind_span, + kind, + value: { + let _: Token![=] = input.parse()?; + input.parse()? + }, + }) + } +} + +#[derive(Debug)] +pub struct ModuleDeclaration { + pub name: Ident, + pub module: Ident, + pub instance: Option, + pub details: Option>>, +} + +impl Parse for ModuleDeclaration { + fn parse(input: ParseStream) -> Result { + let name = input.parse()?; + let _: Token![:] = input.parse()?; + let module = input.parse()?; + let instance = if input.peek(Token![::]) && input.peek3(Token![<]) { + let _: Token![::] = input.parse()?; + let _: Token![<] = input.parse()?; + let res = Some(input.parse()?); + let _: Token![>] = input.parse()?; + res + } else { + None + }; + let details = if input.peek(Token![::]) { + let _: Token![::] = input.parse()?; + Some(input.parse()?) + } else { + None + }; + let parsed = Self { + name, + module, + instance, + details, + }; + if let Some(ref details) = parsed.details { + let parts = &details.content.inner; + let mut resolved = HashSet::new(); + let has_default = parts.into_iter().any(|m| m.is_default()); + for entry in parts { + match entry { + ModuleEntry::Part(part) => { + if has_default && part.is_included_in_default() { + let msg = format!( + "`{}` is already included in `default`. Either remove `default` or remove `{}`", + part.name, + part.name + ); + return Err(Error::new(part.name.span(), msg)); + } + + if !resolved.insert(part.name.clone()) { + let msg = format!( + "`{}` was already declared before. Please remove the duplicate declaration", + part.name + ); + return Err(Error::new(part.name.span(), msg)); + } + } + _ => {} + } + } + } + Ok(parsed) + } +} + +impl ModuleDeclaration { + /// Get resolved module parts, i.e. after expanding `default` keyword + /// or empty declaration + pub fn module_parts(&self) -> Vec { + if let Some(ref details) = self.details { + details + .content + .inner + .iter() + .flat_map(|entry| match entry { + ModuleEntry::Default(ref token) => Self::default_modules(token.span()), + ModuleEntry::Part(ref part) => vec![part.clone()], + }) + .collect() + } else { + Self::default_modules(self.module.span()) + } + } + + pub fn find_part(&self, name: &str) -> Option { + self.module_parts() + .into_iter() + .find(|part| part.name == name) + } + + pub fn exists_part(&self, name: &str) -> bool { + self.find_part(name).is_some() + } + + fn default_modules(span: Span) -> Vec { + let mut res: Vec<_> = ["Module", "Call", "Storage"] + .iter() + .map(|name| ModulePart::with_name(name, span)) + .collect(); + res.extend( + ["Event", "Config"] + .iter() + .map(|name| ModulePart::with_generics(name, span)), + ); + res + } +} + +#[derive(Debug)] +pub enum ModuleEntry { + Default(Token![default]), + Part(ModulePart), +} + +impl Parse for ModuleEntry { + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![default]) { + Ok(ModuleEntry::Default(input.parse()?)) + } else if lookahead.peek(Ident) { + Ok(ModuleEntry::Part(input.parse()?)) + } else { + Err(lookahead.error()) + } + } +} + +impl ModuleEntry { + pub fn is_default(&self) -> bool { + match self { + ModuleEntry::Default(_) => true, + _ => false, + } + } +} + +#[derive(Debug, Clone)] +pub struct ModulePart { + pub name: Ident, + pub generics: syn::Generics, + pub args: Option>>, +} + +impl Parse for ModulePart { + fn parse(input: ParseStream) -> Result { + let name: Ident = input.parse()?; + + if !ModulePart::all_allowed().iter().any(|n| name == n) { + return Err(syn::Error::new( + name.span(), + format!( + "Only the following modules are allowed: {}", + ModulePart::format_names(ModulePart::all_allowed()), + ), + )) + } + + let generics: syn::Generics = input.parse()?; + if !generics.params.is_empty() && !Self::is_allowed_generic(&name) { + let valid_generics = ModulePart::format_names(ModulePart::allowed_generics()); + let msg = format!( + "`{}` is not allowed to have generics. \ + Only the following modules are allowed to have generics: {}.", + name, valid_generics + ); + return Err(syn::Error::new(name.span(), msg)); + } + let args = if input.peek(token::Paren) { + if !Self::is_allowed_arg(&name) { + let syn::group::Parens { token: parens, .. } = syn::group::parse_parens(input)?; + let valid_names = ModulePart::format_names(ModulePart::allowed_args()); + let msg = format!( + "`{}` is not allowed to have arguments in parens. \ + Only the following modules are allowed to have arguments in parens: {}.", + name, valid_names + ); + return Err(syn::Error::new(parens.span, msg)); + } + Some(input.parse()?) + } else { + None + }; + + Ok(Self { + name, + generics, + args, + }) + } +} + +impl ModulePart { + pub fn is_allowed_generic(ident: &Ident) -> bool { + Self::allowed_generics().into_iter().any(|n| ident == n) + } + + pub fn is_allowed_arg(ident: &Ident) -> bool { + Self::allowed_args().into_iter().any(|n| ident == n) + } + + pub fn allowed_generics() -> &'static [&'static str] { + &["Event", "Origin", "Config"] + } + + pub fn allowed_args() -> &'static [&'static str] { + &["Inherent"] + } + + /// Returns all allowed names for module parts. + pub fn all_allowed() -> &'static [&'static str] { + &["Module", "Call", "Storage", "Event", "Config", "Origin", "Inherent", "ValidateUnsigned"] + } + + pub fn format_names(names: &[&'static str]) -> String { + let res: Vec<_> = names.into_iter().map(|s| format!("`{}`", s)).collect(); + res.join(", ") + } + + pub fn is_included_in_default(&self) -> bool { + ["Module", "Call", "Storage", "Event", "Config"] + .iter() + .any(|name| self.name == name) + } + + /// Plain module name like `Event` or `Call`, etc. + pub fn with_name(name: &str, span: Span) -> Self { + let name = Ident::new(name, span); + Self { + name, + generics: syn::Generics { + lt_token: None, + gt_token: None, + where_clause: None, + ..Default::default() + }, + args: None, + } + } + + /// Module name with generic like `Event` or `Call`, etc. + pub fn with_generics(name: &str, span: Span) -> Self { + let name = Ident::new(name, span); + let typ = Ident::new("T", span); + let generic_param = syn::GenericParam::Type(typ.into()); + let generic_params = vec![generic_param].into_iter().collect(); + let generics = syn::Generics { + lt_token: Some(syn::token::Lt { spans: [span] }), + params: generic_params, + gt_token: Some(syn::token::Gt { spans: [span] }), + where_clause: None, + }; + Self { + name, + generics, + args: None, + } + } +} + +fn remove_kind( + input: ParseStream, + kind: WhereKind, + definitions: &mut Vec, +) -> Result { + if let Some(pos) = definitions.iter().position(|d| d.kind == kind) { + Ok(definitions.remove(pos)) + } else { + let msg = format!( + "Missing associated type for `{:?}`. Add `{:?}` = ... to where section.", + kind, kind + ); + Err(input.error(msg)) + } +} diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs new file mode 100644 index 0000000000000..7c27bc2a04dcb --- /dev/null +++ b/frame/support/procedural/src/lib.rs @@ -0,0 +1,314 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Proc macro of Support code for the runtime. +// end::description[] + +#![recursion_limit="512"] + +extern crate proc_macro; + +mod storage; +mod construct_runtime; + +use proc_macro::TokenStream; + +/// Declares strongly-typed wrappers around codec-compatible types in storage. +/// +/// ## Example +/// +/// ```nocompile +/// decl_storage! { +/// trait Store for Module as Example { +/// Foo get(fn foo) config(): u32=12; +/// Bar: map u32 => u32; +/// pub Zed build(|config| vec![(0, 0)]): linked_map u32 => u32; +/// } +/// } +/// ``` +/// +/// Declaration is set with the header `(pub) trait Store for Module as Example`, +/// with `Store` a (pub) trait generated associating each storage item to the `Module` and +/// `as Example` setting the prefix used for storage items of this module. `Example` must be unique: +/// another module with the same name and the same inner storage item name will conflict. +/// `Example` is called the module prefix. +/// +/// note: For instantiable modules the module prefix is prepended with instance +/// prefix. Instance prefix is "" for default instance and "Instance$n" for instance number $n. +/// Thus, instance 3 of module Example has a module prefix of `Instance3Example` +/// +/// Basic storage consists of a name and a type; supported types are: +/// +/// * Value: `Foo: type`: Implements the +/// [`StorageValue`](../frame_support/storage/trait.StorageValue.html) trait using the +/// [`StorageValue generator`](../frame_support/storage/generator/trait.StorageValue.html). +/// +/// The generator is implemented with: +/// * `module_prefix`: module_prefix +/// * `storage_prefix`: storage_name +/// +/// Thus the storage value is finally stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) +/// ``` +/// +/// * Map: `Foo: map hasher($hash) type => type`: Implements the +/// [`StorageMap`](../frame_support/storage/trait.StorageMap.html) trait using the +/// [`StorageMap generator`](../frame_support/storage/generator/trait.StorageMap.html). +/// And [`StoragePrefixedMap`](../frame_support/storage/trait.StoragePrefixedMap.html). +/// +/// `$hash` representing a choice of hashing algorithms available in the +/// [`Hashable`](../frame_support/trait.Hashable.html) trait. +/// +/// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher +/// with care, see generator documentation. +/// +/// The generator is implemented with: +/// * `module_prefix`: $module_prefix +/// * `storage_prefix`: storage_name +/// * `Hasher`: $hash +/// +/// Thus the keys are stored at: +/// ```nocompile +/// twox128(module_prefix) ++ twox128(storage_prefix) ++ hasher(encode(key)) +/// ``` +/// +/// * Linked map: `Foo: linked_map hasher($hash) type => type`: Implements the +/// [`StorageLinkedMap`](../frame_support/storage/trait.StorageLinkedMap.html) trait using the +/// [`StorageLinkedMap generator`](../frame_support/storage/generator/trait.StorageLinkedMap.html). +/// And [`StoragePrefixedMap`](../frame_support/storage/trait.StoragePrefixedMap.html). +/// +/// `$hash` representing a choice of hashing algorithms available in the +/// [`Hashable`](../frame_support/trait.Hashable.html) trait. +/// +/// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher +/// with care, see generator documentation. +/// +/// All key formatting logic can be accessed in a type-agnostic format via the +/// [`KeyFormat`](../srml_support/storage/generator/trait.KeyFormat.html) trait, which +/// is implemented for the storage linked map type as well. +/// +/// The generator key format is implemented with: +/// * `module_prefix`: $module_prefix +/// * `storage_prefix`: storage_name +/// * `head_prefix`: `"HeadOf" ++ storage_name` +/// * `Hasher`: $hash +/// +/// Thus the keys are stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key)) +/// ``` +/// and head is stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(head_prefix) +/// ``` +/// +/// * Double map: `Foo: double_map hasher($hash1) u32, hasher($hash2) u32 => u32`: Implements the +/// [`StorageDoubleMap`](../frame_support/storage/trait.StorageDoubleMap.html) trait using the +/// [`StorageDoubleMap generator`](../frame_support/storage/generator/trait.StorageDoubleMap.html). +/// And [`StoragePrefixedMap`](../frame_support/storage/trait.StoragePrefixedMap.html). +/// +/// `$hash1` and `$hash2` representing choices of hashing algorithms available in the +/// [`Hashable`](../frame_support/trait.Hashable.html) trait. They must be choosen with care, see +/// generator documentation. +/// +/// `hasher($hash1)` and `hasher($hash2) are optional and default to `blake2_256`. +/// One should use another hasher with care, see generator documentation. +/// +/// If the first key is untrusted, a cryptographic `hasher` such as `blake2_256` must be used. +/// Otherwise, other values of all storage items can be compromised. +/// +/// If the second key is untrusted, a cryptographic `hasher` such as `blake2_256` must be used. +/// Otherwise, other items in storage with the same first key can be compromised. +/// +/// The generator is implemented with: +/// * `module_prefix`: $module_prefix +/// * `storage_prefix`: storage_name +/// * `Hasher1`: $hash1 +/// * `Hasher2`: $hash2 +/// +/// Thus keys are stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++ Hasher2(encode(key2)) +/// ``` +/// +/// Supported hashers (ordered from least to best security): +/// +/// * `twox_64_concat` - TwoX with 64bit + key concatenated. +/// * `twox_128` - TwoX with 128bit. +/// * `twox_256` - TwoX with with 256bit. +/// * `blake2_128_concat` - Blake2 with 128bit + key concatenated. +/// * `blake2_128` - Blake2 with 128bit. +/// * `blake2_256` - Blake2 with 256bit. +/// +/// Basic storage can be extended as such: +/// +/// `#vis #name get(fn #getter) config(#field_name) build(#closure): #type = #default;` +/// +/// * `#vis`: Set the visibility of the structure. `pub` or nothing. +/// * `#name`: Name of the storage item, used as a prefix in storage. +/// * [optional] `get(fn #getter)`: Implements the function #getter to `Module`. +/// * [optional] `config(#field_name)`: `field_name` is optional if get is set. +/// Will include the item in `GenesisConfig`. +/// * [optional] `build(#closure)`: Closure called with storage overlays. +/// * `#type`: Storage type. +/// * [optional] `#default`: Value returned when none. +/// +/// Storage items are accessible in multiple ways: +/// +/// * The structure: `Foo` or `Foo::` depending if the value type is generic or not. +/// * The `Store` trait structure: ` as Store>::Foo` +/// * The getter on the module that calls get on the structure: `Module::::foo()` +/// +/// ## GenesisConfig +/// +/// An optional `GenesisConfig` struct for storage initialization can be defined, either +/// when at least one storage field requires default initialization +/// (both `get` and `config` or `build`), or specifically as in: +/// +/// ```nocompile +/// decl_storage! { +/// trait Store for Module as Example { +/// +/// // Your storage items +/// } +/// add_extra_genesis { +/// config(genesis_field): GenesisFieldType; +/// config(genesis_field2): GenesisFieldType; +/// ... +/// build(|_: &Self| { +/// // Modification of storage +/// }) +/// } +/// } +/// ``` +/// +/// This struct can be exposed as `ExampleConfig` by the `construct_runtime!` macro like follows: +/// +/// ```nocompile +/// construct_runtime!( +/// pub enum Runtume with ... { +/// ..., +/// Example: example::{Module, Storage, ..., Config}, +/// ..., +/// } +/// ); +/// ``` +/// +/// ### Module with Instances +/// +/// The `decl_storage!` macro supports building modules with instances with the following syntax +/// (`DefaultInstance` type is optional): +/// +/// ```nocompile +/// trait Store for Module, I: Instance=DefaultInstance> as Example {} +/// ``` +/// +/// Accessing the structure no requires the instance as generic parameter: +/// * `Foo::` if the value type is not generic +/// * `Foo::` if the value type is generic +/// +/// ## Where clause +/// +/// This macro supports a where clause which will be replicated to all generated types. +/// +/// ```nocompile +/// trait Store for Module as Example where T::AccountId: std::fmt::Display {} +/// ``` +/// +/// ## Limitations +/// +/// # Instancing and generic `GenesisConfig` +/// +/// If your module supports instancing and you see an error like `parameter `I` is never used` for +/// your `decl_storage!`, you are hitting a limitation of the current implementation. You probably +/// try to use an associated type of a non-instantiable trait. To solve this, add the following to +/// your macro call: +/// +/// ```nocompile +/// add_extra_genesis { +/// config(phantom): std::marker::PhantomData, +/// } +/// ... +/// +/// This adds a field to your `GenesisConfig` with the name `phantom` that you can initialize with +/// `Default::default()`. +/// +#[proc_macro] +pub fn decl_storage(input: TokenStream) -> TokenStream { + storage::decl_storage_impl(input) +} + +/// Construct a runtime, with the given name and the given modules. +/// +/// The parameters here are specific types for `Block`, `NodeBlock`, and `UncheckedExtrinsic` +/// and the modules that are used by the runtime. +/// `Block` is the block type that is used in the runtime and `NodeBlock` is the block type +/// that is used in the node. For instance they can differ in the extrinsics type. +/// +/// # Example: +/// +/// ```nocompile +/// construct_runtime!( +/// pub enum Runtime where +/// Block = Block, +/// NodeBlock = runtime::Block, +/// UncheckedExtrinsic = UncheckedExtrinsic +/// { +/// System: system, +/// Test: test::{default}, +/// 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 identifier `System` is the name of the module and the lower case identifier `system` is the +/// name of the Rust module/crate for this Substrate module. +/// +/// The module `Test: test::{default}` will expand to +/// `Test: test::{Module, Call, Storage, Event, Config}`. +/// +/// The module `Test2: test_with_long_module::{Module}` will expand to +/// `Test2: test_with_long_module::{Module}`. +/// +/// We provide support for the following types in a module: +/// +/// - `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) +/// - `Inherent ( $(CALL),* )` - If the module provides/can check inherents. The optional parameter +/// is for modules that use a `Call` from a different module as +/// inherent. +/// - `ValidateUnsigned` - If the module validates unsigned extrinsics. +/// +/// # Note +/// +/// The population of the genesis storage depends on the order of modules. So, if one of your +/// modules depends on another module, the module that is depended upon needs to come before +/// the module depending on it. +#[proc_macro] +pub fn construct_runtime(input: TokenStream) -> TokenStream { + construct_runtime::construct_runtime(input) +} diff --git a/frame/support/procedural/src/storage/genesis_config/builder_def.rs b/frame/support/procedural/src/storage/genesis_config/builder_def.rs new file mode 100644 index 0000000000000..59e436880728f --- /dev/null +++ b/frame/support/procedural/src/storage/genesis_config/builder_def.rs @@ -0,0 +1,135 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Builder logic definition used to build genesis storage. + +use frame_support_procedural_tools::syn_ext as ext; +use proc_macro2::TokenStream; +use syn::spanned::Spanned; +use quote::{quote, quote_spanned}; +use super::super::{DeclStorageDefExt, StorageLineTypeDef}; + +/// Definition of builder blocks, each block insert some value in the storage. +/// They must be called inside externalities, and with `self` being the genesis config. +pub struct BuilderDef { + /// Contains: + /// * build block for storage with build attribute. + /// * build block for storage with config attribute and no build attribute. + /// * build block for extra genesis build expression. + pub blocks: Vec, + /// The build blocks requires generic traits. + pub is_generic: bool, +} + +impl BuilderDef { + pub fn from_def(scrate: &TokenStream, def: &DeclStorageDefExt) -> Self { + let mut blocks = Vec::new(); + let mut is_generic = false; + + for line in def.storage_lines.iter() { + let storage_struct = &line.storage_struct; + let storage_trait = &line.storage_trait; + let value_type = &line.value_type; + + // Defines the data variable to use for insert at genesis either from build or config. + let mut data = None; + + if let Some(builder) = &line.build { + is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic); + is_generic |= line.is_generic; + + data = Some(match &line.storage_type { + StorageLineTypeDef::Simple(_) if line.is_option => + quote_spanned!(builder.span() => + let data = (#builder)(self); + let data = Option::as_ref(&data); + ), + _ => quote_spanned!(builder.span() => let data = &(#builder)(self); ), + }); + } else if let Some(config) = &line.config { + is_generic |= line.is_generic; + + data = Some(match &line.storage_type { + StorageLineTypeDef::Simple(_) if line.is_option => + quote!( let data = Some(&self.#config); ), + _ => quote!( let data = &self.#config; ), + }); + }; + + if let Some(data) = data { + blocks.push(match &line.storage_type { + StorageLineTypeDef::Simple(_) if line.is_option => { + quote!{{ + #data + let v: Option<&#value_type>= data; + if let Some(v) = v { + <#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v); + } + }} + }, + StorageLineTypeDef::Simple(_) if !line.is_option => { + quote!{{ + #data + let v: &#value_type = data; + <#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v); + }} + }, + StorageLineTypeDef::Simple(_) => unreachable!(), + StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => { + let key = &map.key; + quote!{{ + #data + let data: &#scrate::sp_std::vec::Vec<(#key, #value_type)> = data; + data.iter().for_each(|(k, v)| { + <#storage_struct as #scrate::#storage_trait>::insert::< + &#key, &#value_type + >(k, v); + }); + }} + }, + StorageLineTypeDef::DoubleMap(map) => { + let key1 = &map.key1; + let key2 = &map.key2; + quote!{{ + #data + let data: &#scrate::sp_std::vec::Vec<(#key1, #key2, #value_type)> = data; + data.iter().for_each(|(k1, k2, v)| { + <#storage_struct as #scrate::#storage_trait>::insert::< + &#key1, &#key2, &#value_type + >(k1, k2, v); + }); + }} + }, + }); + } + } + + if let Some(builder) = def.extra_genesis_build.as_ref() { + is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic); + + blocks.push(quote_spanned! { builder.span() => + let extra_genesis_builder: fn(&Self) = #builder; + extra_genesis_builder(self); + }); + } + + + Self { + blocks, + is_generic, + } + } +} diff --git a/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs b/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs similarity index 82% rename from srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs rename to frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs index f9d2f8abe8055..100907b2926d1 100644 --- a/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs +++ b/frame/support/procedural/src/storage/genesis_config/genesis_config_def.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,16 +16,16 @@ //! Genesis config defintion. -use srml_support_procedural_tools::syn_ext as ext; +use frame_support_procedural_tools::syn_ext as ext; use proc_macro2::TokenStream; -use syn::parse_quote; +use syn::{spanned::Spanned, parse_quote}; use quote::quote; use super::super::{DeclStorageDefExt, StorageLineTypeDef}; pub struct GenesisConfigFieldDef { - pub doc: Vec, pub name: syn::Ident, pub typ: syn::Type, + pub attrs: Vec, pub default: TokenStream, } @@ -43,8 +43,8 @@ pub struct GenesisConfigDef { } impl GenesisConfigDef { - pub fn from_def(def: &DeclStorageDefExt) -> Self { - let fields = Self::get_genesis_config_field_defs(def); + pub fn from_def(def: &DeclStorageDefExt) -> syn::Result { + let fields = Self::get_genesis_config_field_defs(def)?; let is_generic = fields.iter() .any(|field| ext::type_contains_ident(&field.typ, &def.module_runtime_generic)); @@ -71,17 +71,19 @@ impl GenesisConfigDef { (quote!(), quote!(), quote!(), None) }; - Self { + Ok(Self { is_generic, fields, genesis_struct_decl, genesis_struct, genesis_impl, genesis_where_clause, - } + }) } - fn get_genesis_config_field_defs(def: &DeclStorageDefExt) -> Vec { + fn get_genesis_config_field_defs(def: &DeclStorageDefExt) + -> syn::Result> + { let mut config_field_defs = Vec::new(); for (config_field, line) in def.storage_lines.iter() @@ -114,31 +116,39 @@ impl GenesisConfigDef { .unwrap_or_else(|| quote!( Default::default() )); config_field_defs.push(GenesisConfigFieldDef { - doc: line.doc_attrs.clone(), name: config_field, typ, + attrs: line.doc_attrs.clone(), default, }); } for line in &def.extra_genesis_config_lines { - let doc = line.attrs.iter() - .filter_map(|a| a.parse_meta().ok()) - .filter(|m| m.name() == "doc") - .collect(); + let attrs = line.attrs.iter() + .map(|attr| { + let meta = attr.parse_meta()?; + if meta.path().is_ident("cfg") { + return Err(syn::Error::new( + meta.span(), + "extra genesis config items do not support `cfg` attribute" + )); + } + Ok(meta) + }) + .collect::>()?; let default = line.default.as_ref().map(|e| quote!( #e )) .unwrap_or_else(|| quote!( Default::default() )); config_field_defs.push(GenesisConfigFieldDef { - doc, name: line.name.clone(), typ: line.typ.clone(), + attrs, default, }); } - config_field_defs + Ok(config_field_defs) } } diff --git a/frame/support/procedural/src/storage/genesis_config/mod.rs b/frame/support/procedural/src/storage/genesis_config/mod.rs new file mode 100644 index 0000000000000..09afcb9a60d78 --- /dev/null +++ b/frame/support/procedural/src/storage/genesis_config/mod.rs @@ -0,0 +1,197 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Declaration of genesis config structure and implementation of build storage trait and +//! functions. + +use proc_macro2::{TokenStream, Span}; +use quote::quote; +use super::{DeclStorageDefExt, instance_trait::DEFAULT_INSTANTIABLE_TRAIT_NAME}; +use genesis_config_def::GenesisConfigDef; +use builder_def::BuilderDef; + +mod genesis_config_def; +mod builder_def; + +const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance"; + +fn decl_genesis_config_and_impl_default( + scrate: &TokenStream, + genesis_config: &GenesisConfigDef, +) -> TokenStream { + let config_fields = genesis_config.fields.iter().map(|field| { + let (name, typ, attrs) = (&field.name, &field.typ, &field.attrs); + quote!( #( #[ #attrs] )* pub #name: #typ, ) + }); + + let config_field_defaults = genesis_config.fields.iter().map(|field| { + let (name, default) = (&field.name, &field.default); + quote!( #name: #default, ) + }); + + let serde_bug_bound = if !genesis_config.fields.is_empty() { + let mut b_ser = String::new(); + let mut b_dser = String::new(); + + for typ in genesis_config.fields.iter().map(|c| &c.typ) { + let typ = quote!( #typ ); + b_ser.push_str(&format!("{} : {}::serde::Serialize, ", typ, scrate)); + b_dser.push_str(&format!("{} : {}::serde::de::DeserializeOwned, ", typ, scrate)); + } + + quote! { + #[serde(bound(serialize = #b_ser))] + #[serde(bound(deserialize = #b_dser))] + } + } else { + quote!() + }; + + let genesis_struct_decl = &genesis_config.genesis_struct_decl; + let genesis_struct = &genesis_config.genesis_struct; + let genesis_impl = &genesis_config.genesis_impl; + let genesis_where_clause = &genesis_config.genesis_where_clause; + + quote!( + #[derive(#scrate::Serialize, #scrate::Deserialize)] + #[cfg(feature = "std")] + #[serde(rename_all = "camelCase")] + #[serde(deny_unknown_fields)] + #serde_bug_bound + pub struct GenesisConfig#genesis_struct_decl #genesis_where_clause { + #( #config_fields )* + } + + #[cfg(feature = "std")] + impl#genesis_impl Default for GenesisConfig#genesis_struct #genesis_where_clause { + fn default() -> Self { + GenesisConfig { + #( #config_field_defaults )* + } + } + } + ) +} + +fn impl_build_storage( + scrate: &TokenStream, + def: &DeclStorageDefExt, + genesis_config: &GenesisConfigDef, + builders: &BuilderDef, +) -> TokenStream { + let runtime_generic = &def.module_runtime_generic; + let runtime_trait = &def.module_runtime_trait; + let optional_instance = &def.optional_instance; + let optional_instance_bound = &def.optional_instance_bound; + let where_clause = &def.where_clause; + + let inherent_instance = def.optional_instance.clone().unwrap_or_else(|| { + let name = syn::Ident::new(DEFAULT_INSTANCE_NAME, Span::call_site()); + quote!( #name ) + }); + let inherent_instance_bound = def.optional_instance_bound.clone().unwrap_or_else(|| { + let bound = syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site()); + quote!( #inherent_instance: #bound ) + }); + + let build_storage_impl = quote!( + <#runtime_generic: #runtime_trait, #inherent_instance_bound> + ); + + let genesis_struct = &genesis_config.genesis_struct; + let genesis_impl = &genesis_config.genesis_impl; + let genesis_where_clause = &genesis_config.genesis_where_clause; + + let ( + fn_generic, + fn_traitinstance, + fn_where_clause + ) = if !genesis_config.is_generic && builders.is_generic { + ( + quote!( <#runtime_generic: #runtime_trait, #optional_instance_bound> ), + quote!( #runtime_generic, #optional_instance ), + Some(&def.where_clause), + ) + } else { + (quote!(), quote!(), None) + }; + + let builder_blocks = &builders.blocks; + + let build_storage_impl_trait = quote!( + #scrate::sp_runtime::BuildModuleGenesisStorage<#runtime_generic, #inherent_instance> + ); + + quote!{ + #[cfg(feature = "std")] + impl#genesis_impl GenesisConfig#genesis_struct #genesis_where_clause { + pub fn build_storage #fn_generic (&self) -> std::result::Result< + #scrate::sp_runtime::Storage, + String + > #fn_where_clause { + let mut storage = Default::default(); + self.assimilate_storage::<#fn_traitinstance>(&mut storage)?; + Ok(storage) + } + + /// Assimilate the storage for this module into pre-existing overlays. + pub fn assimilate_storage #fn_generic ( + &self, + storage: &mut #scrate::sp_runtime::Storage, + ) -> std::result::Result<(), String> #fn_where_clause { + #scrate::BasicExternalities::execute_with_storage(storage, || { + #( #builder_blocks )* + Ok(()) + }) + } + } + + #[cfg(feature = "std")] + impl#build_storage_impl #build_storage_impl_trait for GenesisConfig#genesis_struct + #where_clause + { + fn build_module_genesis_storage( + &self, + storage: &mut #scrate::sp_runtime::Storage, + ) -> std::result::Result<(), String> { + self.assimilate_storage::<#fn_traitinstance> (storage) + } + } + } +} + +pub fn genesis_config_and_build_storage( + scrate: &TokenStream, + def: &DeclStorageDefExt, +) -> TokenStream { + let builders = BuilderDef::from_def(scrate, def); + if !builders.blocks.is_empty() { + let genesis_config = match GenesisConfigDef::from_def(def) { + Ok(genesis_config) => genesis_config, + Err(err) => return err.to_compile_error(), + }; + let decl_genesis_config_and_impl_default = + decl_genesis_config_and_impl_default(scrate, &genesis_config); + let impl_build_storage = impl_build_storage(scrate, def, &genesis_config, &builders); + + quote!{ + #decl_genesis_config_and_impl_default + #impl_build_storage + } + } else { + quote!() + } +} diff --git a/srml/support/procedural/src/storage/getters.rs b/frame/support/procedural/src/storage/getters.rs similarity index 97% rename from srml/support/procedural/src/storage/getters.rs rename to frame/support/procedural/src/storage/getters.rs index f30e489eb58bc..34d182d7f4d7b 100644 --- a/srml/support/procedural/src/storage/getters.rs +++ b/frame/support/procedural/src/storage/getters.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/frame/support/procedural/src/storage/instance_trait.rs b/frame/support/procedural/src/storage/instance_trait.rs new file mode 100644 index 0000000000000..b2f0ad9c06c03 --- /dev/null +++ b/frame/support/procedural/src/storage/instance_trait.rs @@ -0,0 +1,137 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of the trait instance and the instance structures implementing it. +//! (For not instantiable traits there is still the inherent instance implemented). + +use proc_macro2::{TokenStream, Span}; +use quote::quote; +use super::DeclStorageDefExt; + +const NUMBER_OF_INSTANCE: usize = 16; +pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; +pub(crate) const DEFAULT_INSTANTIABLE_TRAIT_NAME: &str = "__GeneratedInstantiable"; + +// Used to generate an instance implementation. +struct InstanceDef { + prefix: String, + instance_struct: syn::Ident, + doc: TokenStream, +} + +pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { + let mut impls = TokenStream::new(); + + impls.extend(create_instance_trait(def)); + + // Implementation of instances. + if let Some(module_instance) = &def.module_instance { + let instance_defs = (0..NUMBER_OF_INSTANCE) + .map(|i| { + let name = format!("Instance{}", i); + InstanceDef { + instance_struct: syn::Ident::new(&name, proc_macro2::Span::call_site()), + prefix: name, + doc: quote!(#[doc=r"Module instance"]), + } + }) + .chain( + module_instance.instance_default.as_ref().map(|ident| InstanceDef { + prefix: String::new(), + instance_struct: ident.clone(), + doc: quote!(#[doc=r"Default module instance"]), + }) + ); + + for instance_def in instance_defs { + impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def)); + } + } + + // The name of the inherently available instance. + let inherent_instance = syn::Ident::new(INHERENT_INSTANCE_NAME, Span::call_site()); + + // Implementation of inherent instance. + if let Some(default_instance) = def.module_instance.as_ref() + .and_then(|i| i.instance_default.as_ref()) + { + impls.extend(quote! { + #[doc(hidden)] + pub type #inherent_instance = #default_instance; + }); + } else { + let instance_def = InstanceDef { + prefix: String::new(), + instance_struct: inherent_instance, + doc: quote!(#[doc(hidden)]), + }; + impls.extend(create_and_impl_instance_struct(scrate, &instance_def, def)); + } + + impls +} + +fn create_instance_trait( + def: &DeclStorageDefExt, +) -> TokenStream { + let instance_trait = def.module_instance.as_ref().map(|i| i.instance_trait.clone()) + .unwrap_or_else(|| syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); + + let optional_hide = if def.module_instance.is_some() { + quote!() + } else { + quote!(#[doc(hidden)]) + }; + + quote! { + /// Tag a type as an instance of a module. + /// + /// Defines storage prefixes, they must be unique. + #optional_hide + pub trait #instance_trait: 'static { + /// The prefix used by any storage entry of an instance. + const PREFIX: &'static str; + } + } +} + +fn create_and_impl_instance_struct( + scrate: &TokenStream, + instance_def: &InstanceDef, + def: &DeclStorageDefExt, +) -> TokenStream { + let instance_trait = def.module_instance.as_ref().map(|i| i.instance_trait.clone()) + .unwrap_or_else(|| syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); + + let instance_struct = &instance_def.instance_struct; + let prefix = format!("{}{}", instance_def.prefix, def.crate_name.to_string()); + let doc = &instance_def.doc; + + quote! { + // Those trait are derived because of wrong bounds for generics + #[derive( + Clone, Eq, PartialEq, + #scrate::codec::Encode, + #scrate::codec::Decode, + #scrate::RuntimeDebug, + )] + #doc + pub struct #instance_struct; + impl #instance_trait for #instance_struct { + const PREFIX: &'static str = #prefix; + } + } +} diff --git a/frame/support/procedural/src/storage/metadata.rs b/frame/support/procedural/src/storage/metadata.rs new file mode 100644 index 0000000000000..f8dfb10d2edb2 --- /dev/null +++ b/frame/support/procedural/src/storage/metadata.rs @@ -0,0 +1,230 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of `storage_metadata` on module structure, used by construct_runtime. + +use frame_support_procedural_tools::clean_type_string; +use proc_macro2::TokenStream; +use quote::quote; +use super::{DeclStorageDefExt, StorageLineDefExt, StorageLineTypeDef}; + +fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) -> TokenStream { + let value_type = &line.value_type; + let value_type = clean_type_string("e!( #value_type ).to_string()); + match &line.storage_type { + StorageLineTypeDef::Simple(_) => { + quote!{ + #scrate::metadata::StorageEntryType::Plain( + #scrate::metadata::DecodeDifferent::Encode(#value_type), + ) + } + }, + StorageLineTypeDef::Map(map) => { + let hasher = map.hasher.into_metadata(); + let key = &map.key; + let key = clean_type_string("e!(#key).to_string()); + quote!{ + #scrate::metadata::StorageEntryType::Map { + hasher: #scrate::metadata::#hasher, + key: #scrate::metadata::DecodeDifferent::Encode(#key), + value: #scrate::metadata::DecodeDifferent::Encode(#value_type), + is_linked: false, + } + } + }, + StorageLineTypeDef::LinkedMap(map) => { + let hasher = map.hasher.into_metadata(); + let key = &map.key; + let key = clean_type_string("e!(#key).to_string()); + quote!{ + #scrate::metadata::StorageEntryType::Map { + hasher: #scrate::metadata::#hasher, + key: #scrate::metadata::DecodeDifferent::Encode(#key), + value: #scrate::metadata::DecodeDifferent::Encode(#value_type), + is_linked: true, + } + } + }, + StorageLineTypeDef::DoubleMap(map) => { + let hasher1 = map.hasher1.into_metadata(); + let hasher2 = map.hasher2.into_metadata(); + let key1 = &map.key1; + let key1 = clean_type_string("e!(#key1).to_string()); + let key2 = &map.key2; + let key2 = clean_type_string("e!(#key2).to_string()); + quote!{ + #scrate::metadata::StorageEntryType::DoubleMap { + hasher: #scrate::metadata::#hasher1, + key1: #scrate::metadata::DecodeDifferent::Encode(#key1), + key2: #scrate::metadata::DecodeDifferent::Encode(#key2), + value: #scrate::metadata::DecodeDifferent::Encode(#value_type), + key2_hasher: #scrate::metadata::#hasher2, + } + } + }, + } +} + +fn default_byte_getter( + scrate: &TokenStream, + line: &StorageLineDefExt, + def: &DeclStorageDefExt, +) -> (TokenStream, TokenStream) { + let default = line.default_value.as_ref().map(|d| quote!( #d )) + .unwrap_or_else(|| quote!( Default::default() )); + + let str_name = line.name.to_string(); + let struct_name = syn::Ident::new(&("__GetByteStruct".to_string() + &str_name), line.name.span()); + let cache_name = syn::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), line.name.span()); + + let runtime_generic = &def.module_runtime_generic; + let runtime_trait = &def.module_runtime_trait; + let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default; + let optional_instance_bound = &def.optional_instance_bound; + let optional_instance = &def.optional_instance; + let optional_comma_instance = optional_instance.as_ref().map(|i| quote!(, #i)); + let where_clause = &def.where_clause; + + let query_type = &line.query_type; + + let struct_def = quote! { + #[doc(hidden)] + pub struct #struct_name< + #runtime_generic, #optional_instance_bound_optional_default + >(pub #scrate::sp_std::marker::PhantomData<(#runtime_generic #optional_comma_instance)>); + + #[cfg(feature = "std")] + #[allow(non_upper_case_globals)] + static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::sp_std::vec::Vec> = + #scrate::once_cell::sync::OnceCell::new(); + + #[cfg(feature = "std")] + impl<#runtime_generic: #runtime_trait, #optional_instance_bound> + #scrate::metadata::DefaultByte + for #struct_name<#runtime_generic, #optional_instance> + #where_clause + { + fn default_byte(&self) -> #scrate::sp_std::vec::Vec { + use #scrate::codec::Encode; + #cache_name.get_or_init(|| { + let def_val: #query_type = #default; + <#query_type as Encode>::encode(&def_val) + }).clone() + } + } + + unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Send + for #struct_name<#runtime_generic, #optional_instance> #where_clause {} + + unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Sync + for #struct_name<#runtime_generic, #optional_instance> #where_clause {} + + #[cfg(not(feature = "std"))] + impl<#runtime_generic: #runtime_trait, #optional_instance_bound> + #scrate::metadata::DefaultByte + for #struct_name<#runtime_generic, #optional_instance> + #where_clause + { + fn default_byte(&self) -> #scrate::sp_std::vec::Vec { + use #scrate::codec::Encode; + let def_val: #query_type = #default; + <#query_type as Encode>::encode(&def_val) + } + } + }; + let struct_instance = quote!( + #struct_name::<#runtime_generic, #optional_instance>(#scrate::sp_std::marker::PhantomData) + ); + + (struct_def, struct_instance) +} + +pub fn impl_metadata(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { + let mut entries = TokenStream::new(); + let mut default_byte_getter_struct_defs = TokenStream::new(); + + for line in def.storage_lines.iter() { + let str_name = line.name.to_string(); + + let modifier = if line.is_option { + quote!(#scrate::metadata::StorageEntryModifier::Optional) + } else { + quote!(#scrate::metadata::StorageEntryModifier::Default) + }; + + let ty = storage_line_metadata_type(scrate, line); + + let ( + default_byte_getter_struct_def, + default_byte_getter_struct_instance, + ) = default_byte_getter(scrate, line, def); + + let mut docs = TokenStream::new(); + for attr in line.attrs.iter().filter_map(|v| v.parse_meta().ok()) { + if let syn::Meta::NameValue(meta) = attr { + if meta.path.is_ident("doc") { + let lit = meta.lit; + docs.extend(quote!(#lit,)); + } + } + } + + let entry = quote! { + #scrate::metadata::StorageEntryMetadata { + name: #scrate::metadata::DecodeDifferent::Encode(#str_name), + modifier: #modifier, + ty: #ty, + default: #scrate::metadata::DecodeDifferent::Encode( + #scrate::metadata::DefaultByteGetter(&#default_byte_getter_struct_instance) + ), + documentation: #scrate::metadata::DecodeDifferent::Encode(&[ #docs ]), + }, + }; + + default_byte_getter_struct_defs.extend(default_byte_getter_struct_def); + entries.extend(entry); + } + + let prefix = if let Some(instance) = &def.module_instance { + let instance_generic = &instance.instance_generic; + quote!(#instance_generic::PREFIX) + } else { + let prefix = def.crate_name.to_string(); + quote!(#prefix) + }; + + let store_metadata = quote!( + #scrate::metadata::StorageMetadata { + prefix: #scrate::metadata::DecodeDifferent::Encode(#prefix), + entries: #scrate::metadata::DecodeDifferent::Encode(&[ #entries ][..]), + } + ); + + let module_struct = &def.module_struct; + let module_impl = &def.module_impl; + let where_clause = &def.where_clause; + + quote!( + #default_byte_getter_struct_defs + + impl#module_impl #module_struct #where_clause { + #[doc(hidden)] + pub fn storage_metadata() -> #scrate::metadata::StorageMetadata { + #store_metadata + } + } + ) +} diff --git a/frame/support/procedural/src/storage/mod.rs b/frame/support/procedural/src/storage/mod.rs new file mode 100644 index 0000000000000..453cb9c4678ca --- /dev/null +++ b/frame/support/procedural/src/storage/mod.rs @@ -0,0 +1,436 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! `decl_storage` input definition and expansion. + +mod storage_struct; +mod parse; +mod store_trait; +mod getters; +mod metadata; +mod instance_trait; +mod genesis_config; + +use quote::quote; +use frame_support_procedural_tools::{ + generate_crate_access, generate_hidden_includes, syn_ext as ext +}; + +/// All informations contained in input of decl_storage +pub struct DeclStorageDef { + /// Name of the module used to import hidden imports. + hidden_crate: Option, + /// Visibility of store trait. + visibility: syn::Visibility, + /// Name of store trait: usually `Store`. + store_trait: syn::Ident, + /// Module name used by construct_runtime: usually `Module`. + module_name: syn::Ident, + /// Usually `T`. + module_runtime_generic: syn::Ident, + /// Usually `Trait` + module_runtime_trait: syn::Path, + /// For instantiable module: usually `I: Instance=DefaultInstance`. + module_instance: Option, + /// Where claused used to constrain T and I even more. + where_clause: Option, + /// The extra build function used to build storage at genesis. + extra_genesis_build: Option, + /// The extra genesis config fields. + extra_genesis_config_lines: Vec, + /// Definition of storages. + storage_lines: Vec, + /// Name of the crate, used for storage prefixes. + crate_name: syn::Ident, +} + +impl syn::parse::Parse for DeclStorageDef { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + parse::parse(input) + } +} + +/// Extended version of `DeclStorageDef` with useful precomputed value. +pub struct DeclStorageDefExt { + /// Name of the module used to import hidden imports. + hidden_crate: Option, + /// Visibility of store trait. + visibility: syn::Visibility, + /// Name of store trait: usually `Store`. + store_trait: syn::Ident, + /// Module name used by construct_runtime: usually `Module`. + #[allow(unused)] + module_name: syn::Ident, + /// Usually `T`. + module_runtime_generic: syn::Ident, + /// Usually `Trait`. + module_runtime_trait: syn::Path, + /// For instantiable module: usually `I: Instance=DefaultInstance`. + module_instance: Option, + /// Where claused used to constrain T and I even more. + where_clause: Option, + /// The extra build function used to build storage at genesis. + extra_genesis_build: Option, + /// The extra genesis config fields. + extra_genesis_config_lines: Vec, + /// Definition of storages. + storage_lines: Vec, + /// Name of the crate, used for storage prefixes. + crate_name: syn::Ident, + /// Full struct expansion: `Module`. + module_struct: proc_macro2::TokenStream, + /// Impl block for module: ``. + module_impl: proc_macro2::TokenStream, + /// For instantiable: `I`. + optional_instance: Option, + /// For instantiable: `I: Instance`. + optional_instance_bound: Option, + /// For instantiable: `I: Instance = DefaultInstance`. + optional_instance_bound_optional_default: Option, +} + +impl From for DeclStorageDefExt { + fn from(mut def: DeclStorageDef) -> Self { + let storage_lines = def.storage_lines.drain(..).collect::>(); + let storage_lines = storage_lines.into_iter() + .map(|line| StorageLineDefExt::from_def(line, &def)) + .collect(); + + let ( + optional_instance, + optional_instance_bound, + optional_instance_bound_optional_default, + ) = if let Some(instance) = def.module_instance.as_ref() { + let instance_generic = &instance.instance_generic; + let instance_trait= &instance.instance_trait; + let optional_equal_instance_default = instance.instance_default.as_ref() + .map(|d| quote!( = #d )); + ( + Some(quote!(#instance_generic)), + Some(quote!(#instance_generic: #instance_trait)), + Some(quote!(#instance_generic: #instance_trait #optional_equal_instance_default)), + ) + } else { + (None, None, None) + }; + + let module_runtime_generic = &def.module_runtime_generic; + let module_runtime_trait = &def.module_runtime_trait; + let module_name = &def.module_name; + + let module_struct = quote!( + #module_name<#module_runtime_generic, #optional_instance> + ); + + let module_impl = quote!( + <#module_runtime_generic: #module_runtime_trait + 'static, #optional_instance_bound> + ); + + Self { + hidden_crate: def.hidden_crate, + visibility: def.visibility, + store_trait: def.store_trait, + module_name: def.module_name, + module_runtime_generic: def.module_runtime_generic, + module_runtime_trait: def.module_runtime_trait, + module_instance: def.module_instance, + where_clause: def.where_clause, + extra_genesis_build: def.extra_genesis_build, + extra_genesis_config_lines: def.extra_genesis_config_lines, + crate_name: def.crate_name, + storage_lines, + module_struct, + module_impl, + optional_instance, + optional_instance_bound, + optional_instance_bound_optional_default, + } + } +} + +/// Usually `I: Instance=DefaultInstance`. +pub struct ModuleInstanceDef { + /// Usually: `I`. + instance_generic: syn::Ident, + /// Usually: `Instance`. + instance_trait: syn::Ident, + /// Usually: `DefaultInstance`. + instance_default: Option, +} + +pub struct StorageLineDef { + attrs: Vec, + /// Visibility of the storage struct. + visibility: syn::Visibility, + name: syn::Ident, + /// The name of getter function to be implemented on Module struct. + getter: Option, + /// The name of the field to be used in genesis config if any. + config: Option, + /// The build function of the storage if any. + build: Option, + /// Default value of genesis config field and also for storage when no value available. + default_value: Option, + storage_type: StorageLineTypeDef, +} + +pub struct StorageLineDefExt { + #[allow(unused)] + attrs: Vec, + /// Visibility of the storage struct. + visibility: syn::Visibility, + name: syn::Ident, + /// The name of getter function to be implemented on Module struct. + getter: Option, + /// The name of the field to be used in genesis config if any. + config: Option, + /// The build function of the storage if any. + build: Option, + /// Default value of genesis config field and also for storage when no value available. + default_value: Option, + storage_type: StorageLineTypeDef, + doc_attrs: Vec, + /// Either the type stored in storage or wrapped in an Option. + query_type: syn::Type, + /// The type stored in storage. + value_type: syn::Type, + /// Full struct, for example: `StorageName`. + storage_struct: proc_macro2::TokenStream, + /// If storage is generic over runtime then `T`. + optional_storage_runtime_comma: Option, + /// If storage is generic over runtime then `T: Trait`. + optional_storage_runtime_bound_comma: Option, + /// The where clause to use to constrain generics if storage is generic over runtime. + optional_storage_where_clause: Option, + /// Full trait, for example: `storage::StorageMap`. + storage_trait: proc_macro2::TokenStream, + /// Full trait, for example: `storage::generator::StorageMap`. + storage_generator_trait: proc_macro2::TokenStream, + /// Weither the storage is generic. + is_generic: bool, + /// Weither the storage value is an option. + is_option: bool, +} + +impl StorageLineDefExt { + fn from_def(storage_def: StorageLineDef, def: &DeclStorageDef) -> Self { + let is_generic = match &storage_def.storage_type { + StorageLineTypeDef::Simple(value) => { + ext::type_contains_ident(&value, &def.module_runtime_generic) + }, + StorageLineTypeDef::Map(map) => { + ext::type_contains_ident(&map.key, &def.module_runtime_generic) + || ext::type_contains_ident(&map.value, &def.module_runtime_generic) + } + StorageLineTypeDef::LinkedMap(map) => { + ext::type_contains_ident(&map.key, &def.module_runtime_generic) + || ext::type_contains_ident(&map.value, &def.module_runtime_generic) + } + StorageLineTypeDef::DoubleMap(map) => { + ext::type_contains_ident(&map.key1, &def.module_runtime_generic) + || ext::type_contains_ident(&map.key2, &def.module_runtime_generic) + || ext::type_contains_ident(&map.value, &def.module_runtime_generic) + } + }; + + let query_type = match &storage_def.storage_type { + StorageLineTypeDef::Simple(value) => value.clone(), + StorageLineTypeDef::Map(map) => map.value.clone(), + StorageLineTypeDef::LinkedMap(map) => map.value.clone(), + StorageLineTypeDef::DoubleMap(map) => map.value.clone(), + }; + let is_option = ext::extract_type_option(&query_type).is_some(); + let value_type = ext::extract_type_option(&query_type).unwrap_or(query_type.clone()); + + let module_runtime_generic = &def.module_runtime_generic; + let module_runtime_trait = &def.module_runtime_trait; + let optional_storage_runtime_comma = if is_generic { + Some(quote!( #module_runtime_generic, )) + } else { + None + }; + let optional_storage_runtime_bound_comma = if is_generic { + Some(quote!( #module_runtime_generic: #module_runtime_trait, )) + } else { + None + }; + + let storage_name = &storage_def.name; + let optional_instance_generic = def.module_instance.as_ref().map(|i| { + let instance_generic = &i.instance_generic; + quote!( #instance_generic ) + }); + let storage_struct = quote!( + #storage_name<#optional_storage_runtime_comma #optional_instance_generic> + ); + + let optional_storage_where_clause = if is_generic { + def.where_clause.as_ref().map(|w| quote!( #w )) + } else { + None + }; + + let storage_trait_trunkated = match &storage_def.storage_type { + StorageLineTypeDef::Simple(_) => { + quote!( StorageValue<#value_type> ) + }, + StorageLineTypeDef::Map(map) => { + let key = &map.key; + quote!( StorageMap<#key, #value_type> ) + }, + StorageLineTypeDef::LinkedMap(map) => { + let key = &map.key; + quote!( StorageLinkedMap<#key, #value_type> ) + }, + StorageLineTypeDef::DoubleMap(map) => { + let key1 = &map.key1; + let key2 = &map.key2; + quote!( StorageDoubleMap<#key1, #key2, #value_type> ) + }, + }; + + let storage_trait = quote!( storage::#storage_trait_trunkated ); + let storage_generator_trait = quote!( storage::generator::#storage_trait_trunkated ); + + let doc_attrs = storage_def.attrs.iter() + .filter_map(|a| a.parse_meta().ok()) + .filter(|m| m.path().is_ident("doc")) + .collect(); + + Self { + attrs: storage_def.attrs, + visibility: storage_def.visibility, + name: storage_def.name, + getter: storage_def.getter, + config: storage_def.config, + build: storage_def.build, + default_value: storage_def.default_value, + storage_type: storage_def.storage_type, + doc_attrs, + query_type, + value_type, + storage_struct, + optional_storage_runtime_comma, + optional_storage_runtime_bound_comma, + optional_storage_where_clause, + storage_trait, + storage_generator_trait, + is_generic, + is_option, + } + } +} + +pub enum StorageLineTypeDef { + Map(MapDef), + LinkedMap(MapDef), + DoubleMap(DoubleMapDef), + Simple(syn::Type), +} + +pub struct MapDef { + pub hasher: HasherKind, + pub key: syn::Type, + /// This is the query value not the inner value used in storage trait implementation. + pub value: syn::Type, +} + +pub struct DoubleMapDef { + pub hasher1: HasherKind, + pub hasher2: HasherKind, + pub key1: syn::Type, + pub key2: syn::Type, + /// This is the query value not the inner value used in storage trait implementation. + pub value: syn::Type, +} + +pub struct ExtraGenesisLineDef { + attrs: Vec, + name: syn::Ident, + typ: syn::Type, + default: Option, +} + +#[derive(Debug, Clone)] +pub enum HasherKind { + Blake2_256, + Blake2_128, + Blake2_128Concat, + Twox256, + Twox128, + Twox64Concat, +} + +impl HasherKind { + fn to_storage_hasher_struct(&self) -> proc_macro2::TokenStream { + match self { + HasherKind::Blake2_256 => quote!( Blake2_256 ), + HasherKind::Blake2_128 => quote!( Blake2_128 ), + HasherKind::Blake2_128Concat => quote!( Blake2_128Concat ), + HasherKind::Twox256 => quote!( Twox256 ), + HasherKind::Twox128 => quote!( Twox128 ), + HasherKind::Twox64Concat => quote!( Twox64Concat ), + } + } + + fn into_metadata(&self) -> proc_macro2::TokenStream { + match self { + HasherKind::Blake2_256 => quote!( StorageHasher::Blake2_256 ), + HasherKind::Blake2_128 => quote!( StorageHasher::Blake2_128 ), + HasherKind::Blake2_128Concat => quote!( StorageHasher::Blake2_128Concat ), + HasherKind::Twox256 => quote!( StorageHasher::Twox256 ), + HasherKind::Twox128 => quote!( StorageHasher::Twox128 ), + HasherKind::Twox64Concat => quote!( StorageHasher::Twox64Concat ), + } + } +} + +/// Full implementation of decl_storage. +pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let def = syn::parse_macro_input!(input as DeclStorageDef); + let def_ext = DeclStorageDefExt::from(def); + + let hidden_crate_name = def_ext.hidden_crate.as_ref().map(|i| i.to_string()) + .unwrap_or_else(|| "decl_storage".to_string()); + + let scrate = generate_crate_access(&hidden_crate_name, "frame-support"); + let scrate_decl = generate_hidden_includes(&hidden_crate_name, "frame-support"); + + let store_trait = store_trait::decl_and_impl(&def_ext); + let getters = getters::impl_getters(&scrate, &def_ext); + let metadata = metadata::impl_metadata(&scrate, &def_ext); + let instance_trait = instance_trait::decl_and_impl(&scrate, &def_ext); + let genesis_config = genesis_config::genesis_config_and_build_storage(&scrate, &def_ext); + let storage_struct = storage_struct::decl_and_impl(&scrate, &def_ext); + + quote!( + use #scrate::{ + StorageValue as _, + StorageMap as _, + StorageLinkedMap as _, + StorageDoubleMap as _, + StoragePrefixedMap as _, + }; + + #scrate_decl + #store_trait + #getters + #metadata + #instance_trait + #genesis_config + #storage_struct + ).into() +} diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs new file mode 100644 index 0000000000000..5d91fbcc0e912 --- /dev/null +++ b/frame/support/procedural/src/storage/parse.rs @@ -0,0 +1,408 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Parsing of decl_storage input. + +use frame_support_procedural_tools::{ToTokens, Parse, syn_ext as ext}; +use syn::{Ident, Token, spanned::Spanned}; + +mod keyword { + syn::custom_keyword!(hiddencrate); + syn::custom_keyword!(add_extra_genesis); + syn::custom_keyword!(extra_genesis_skip_phantom_data_field); + syn::custom_keyword!(config); + syn::custom_keyword!(build); + syn::custom_keyword!(get); + syn::custom_keyword!(map); + syn::custom_keyword!(linked_map); + syn::custom_keyword!(double_map); + syn::custom_keyword!(blake2_256); + syn::custom_keyword!(blake2_128); + syn::custom_keyword!(blake2_128_concat); + syn::custom_keyword!(twox_256); + syn::custom_keyword!(twox_128); + syn::custom_keyword!(twox_64_concat); + syn::custom_keyword!(hasher); +} + +/// Parsing usage only +#[derive(Parse, ToTokens, Debug)] +struct StorageDefinition { + pub hidden_crate: ext::Opt, + pub visibility: syn::Visibility, + pub trait_token: Token![trait], + pub ident: Ident, + pub for_token: Token![for], + pub module_ident: Ident, + pub mod_lt_token: Token![<], + pub mod_param_generic: syn::Ident, + pub mod_param_bound_token: Option, + pub mod_param_bound: syn::Path, + pub mod_instance_param_token: Option, + pub mod_instance: Option, + pub mod_instantiable_token: Option, + pub mod_instantiable: Option, + pub mod_default_instance_token: Option, + pub mod_default_instance: Option, + pub mod_gt_token: Token![>], + pub as_token: Token![as], + pub crate_ident: Ident, + pub where_clause: Option, + pub content: ext::Braces>, + pub extra_genesis: ext::Opt, +} + +#[derive(Parse, ToTokens, Debug)] +struct SpecificHiddenCrate { + pub keyword: keyword::hiddencrate, + pub ident: ext::Parens, +} + +#[derive(Parse, ToTokens, Debug)] +struct AddExtraGenesis { + pub extragenesis_keyword: keyword::add_extra_genesis, + pub content: ext::Braces, +} + +#[derive(Parse, ToTokens, Debug)] +struct AddExtraGenesisContent { + pub lines: ext::Punctuated, +} + +#[derive(Parse, ToTokens, Debug)] +enum AddExtraGenesisLineEnum { + AddExtraGenesisLine(AddExtraGenesisLine), + AddExtraGenesisBuild(DeclStorageBuild), +} + +#[derive(Parse, ToTokens, Debug)] +struct AddExtraGenesisLine { + pub attrs: ext::OuterAttributes, + pub config_keyword: keyword::config, + pub extra_field: ext::Parens, + pub coldot_token: Token![:], + pub extra_type: syn::Type, + pub default_value: ext::Opt, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageLine { + // attrs (main use case is doc) + pub attrs: ext::OuterAttributes, + // visibility (no need to make optional + pub visibility: syn::Visibility, + // name + pub name: Ident, + pub getter: ext::Opt, + pub config: ext::Opt, + pub build: ext::Opt, + pub coldot_token: Token![:], + pub storage_type: DeclStorageType, + pub default_value: ext::Opt, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageGetterBody { + fn_keyword: Option, + ident: Ident, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageGetter { + pub getter_keyword: keyword::get, + pub getfn: ext::Parens, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageConfig { + pub config_keyword: keyword::config, + pub expr: ext::Parens>, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageBuild { + pub build_keyword: keyword::build, + pub expr: ext::Parens, +} + +#[derive(Parse, ToTokens, Debug)] +enum DeclStorageType { + Map(DeclStorageMap), + LinkedMap(DeclStorageLinkedMap), + DoubleMap(DeclStorageDoubleMap), + Simple(syn::Type), +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageMap { + pub map_keyword: keyword::map, + pub hasher: ext::Opt, + pub key: syn::Type, + pub ass_keyword: Token![=>], + pub value: syn::Type, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageLinkedMap { + pub map_keyword: keyword::linked_map, + pub hasher: ext::Opt, + pub key: syn::Type, + pub ass_keyword: Token![=>], + pub value: syn::Type, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageDoubleMap { + pub map_keyword: keyword::double_map, + pub hasher1: ext::Opt, + pub key1: syn::Type, + pub comma_keyword: Token![,], + pub hasher2: ext::Opt, + pub key2: syn::Type, + pub ass_keyword: Token![=>], + pub value: syn::Type, +} + +#[derive(Parse, ToTokens, Debug)] +enum Hasher { + Blake2_256(keyword::blake2_256), + Blake2_128(keyword::blake2_128), + Blake2_128Concat(keyword::blake2_128_concat), + Twox256(keyword::twox_256), + Twox128(keyword::twox_128), + Twox64Concat(keyword::twox_64_concat), +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageDefault { + pub equal_token: Token![=], + pub expr: syn::Expr, +} + +#[derive(Parse, ToTokens, Debug)] +struct SetHasher { + pub hasher_keyword: keyword::hasher, + pub inner: ext::Parens, +} + +impl From for super::HasherKind { + fn from(set_hasher: SetHasher) -> Self { + set_hasher.inner.content.into() + } +} + +impl From for super::HasherKind { + fn from(hasher: Hasher) -> Self { + match hasher { + Hasher::Blake2_256(_) => super::HasherKind::Blake2_256, + Hasher::Blake2_128(_) => super::HasherKind::Blake2_128, + Hasher::Blake2_128Concat(_) => super::HasherKind::Blake2_128Concat, + Hasher::Twox256(_) => super::HasherKind::Twox256, + Hasher::Twox128(_) => super::HasherKind::Twox128, + Hasher::Twox64Concat(_) => super::HasherKind::Twox64Concat, + } + } +} + +fn get_module_instance( + instance: Option, + instantiable: Option, + default_instance: Option, +) -> syn::Result> { + let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance"; + + match (instance, instantiable, default_instance) { + (Some(instance), Some(instantiable), default_instance) => { + Ok(Some(super::ModuleInstanceDef { + instance_generic: instance, + instance_trait: instantiable, + instance_default: default_instance, + })) + }, + (None, None, None) => Ok(None), + (Some(instance), None, _) => Err( + syn::Error::new( + instance.span(), + format!( + "Expect instantiable trait bound for instance: {}. {}", + instance, + right_syntax, + ) + ) + ), + (None, Some(instantiable), _) => Err( + syn::Error::new( + instantiable.span(), + format!( + "Expect instance generic for bound instantiable: {}. {}", + instantiable, + right_syntax, + ) + ) + ), + (None, _, Some(default_instance)) => Err( + syn::Error::new( + default_instance.span(), + format!( + "Expect instance generic for default instance: {}. {}", + default_instance, + right_syntax, + ) + ) + ), + } +} + +pub fn parse(input: syn::parse::ParseStream) -> syn::Result { + use syn::parse::Parse; + + let def = StorageDefinition::parse(input)?; + + let module_instance = get_module_instance( + def.mod_instance, + def.mod_instantiable, + def.mod_default_instance, + )?; + + let mut extra_genesis_config_lines = vec![]; + let mut extra_genesis_build = None; + + for line in def.extra_genesis.inner.into_iter() + .flat_map(|o| o.content.content.lines.inner.into_iter()) + { + match line { + AddExtraGenesisLineEnum::AddExtraGenesisLine(def) => { + extra_genesis_config_lines.push(super::ExtraGenesisLineDef{ + attrs: def.attrs.inner, + name: def.extra_field.content, + typ: def.extra_type, + default: def.default_value.inner.map(|o| o.expr), + }); + } + AddExtraGenesisLineEnum::AddExtraGenesisBuild(def) => { + if extra_genesis_build.is_some() { + return Err(syn::Error::new( + def.span(), + "Only one build expression allowed for extra genesis" + )) + } + + extra_genesis_build = Some(def.expr.content); + } + } + } + + let storage_lines = parse_storage_line_defs(def.content.content.inner.into_iter())?; + + Ok(super::DeclStorageDef { + hidden_crate: def.hidden_crate.inner.map(|i| i.ident.content), + visibility: def.visibility, + module_name: def.module_ident, + store_trait: def.ident, + module_runtime_generic: def.mod_param_generic, + module_runtime_trait: def.mod_param_bound, + where_clause: def.where_clause, + crate_name: def.crate_ident, + module_instance, + extra_genesis_build, + extra_genesis_config_lines, + storage_lines, + }) +} + +/// Parse the `DeclStorageLine` into `StorageLineDef`. +fn parse_storage_line_defs( + defs: impl Iterator, +) -> syn::Result> { + let mut storage_lines = Vec::::new(); + + for line in defs { + let getter = line.getter.inner.map(|o| o.getfn.content.ident); + let config = if let Some(config) = line.config.inner { + if let Some(ident) = config.expr.content { + Some(ident) + } else if let Some(ref ident) = getter { + Some(ident.clone()) + } else { + return Err(syn::Error::new( + config.span(), + "Invalid storage definition, couldn't find config identifier: storage must \ + either have a get identifier `get(fn ident)` or a defined config identifier \ + `config(ident)`", + )) + } + } else { + None + }; + + if let Some(ref config) = config { + storage_lines.iter().filter_map(|sl| sl.config.as_ref()).try_for_each(|other_config| { + if other_config == config { + Err(syn::Error::new( + config.span(), + "`config()`/`get()` with the same name already defined.", + )) + } else { + Ok(()) + } + })?; + } + + let storage_type = match line.storage_type { + DeclStorageType::Map(map) => super::StorageLineTypeDef::Map( + super::MapDef { + hasher: map.hasher.inner.map(Into::into) + .unwrap_or(super::HasherKind::Blake2_256), + key: map.key, + value: map.value, + } + ), + DeclStorageType::LinkedMap(map) => super::StorageLineTypeDef::LinkedMap( + super::MapDef { + hasher: map.hasher.inner.map(Into::into) + .unwrap_or(super::HasherKind::Blake2_256), + key: map.key, + value: map.value, + } + ), + DeclStorageType::DoubleMap(map) => super::StorageLineTypeDef::DoubleMap( + super::DoubleMapDef { + hasher1: map.hasher1.inner.map(Into::into) + .unwrap_or(super::HasherKind::Blake2_256), + hasher2: map.hasher2.inner.map(Into::into) + .unwrap_or(super::HasherKind::Blake2_256), + key1: map.key1, + key2: map.key2, + value: map.value, + } + ), + DeclStorageType::Simple(expr) => super::StorageLineTypeDef::Simple(expr), + }; + + storage_lines.push(super::StorageLineDef { + attrs: line.attrs.inner, + visibility: line.visibility, + name: line.name, + getter, + config, + build: line.build.inner.map(|o| o.expr.content), + default_value: line.default_value.inner.map(|o| o.expr), + storage_type, + }) + } + + Ok(storage_lines) +} diff --git a/frame/support/procedural/src/storage/storage_struct.rs b/frame/support/procedural/src/storage/storage_struct.rs new file mode 100644 index 0000000000000..e44863b1579d5 --- /dev/null +++ b/frame/support/procedural/src/storage/storage_struct.rs @@ -0,0 +1,266 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of storage structures and implementation of storage traits on them. + +use proc_macro2::{TokenStream, Ident, Span}; +use quote::quote; +use super::{ + DeclStorageDefExt, StorageLineTypeDef, + instance_trait::INHERENT_INSTANCE_NAME, +}; + +fn from_optional_value_to_query(is_option: bool, default: &Option) -> TokenStream { + let default = default.as_ref().map(|d| quote!( #d )) + .unwrap_or_else(|| quote!( Default::default() )); + + if !is_option { + // raw type case + quote!( v.unwrap_or_else(|| #default ) ) + } else { + // Option<> type case + quote!( v.or_else(|| #default ) ) + } +} + +fn from_query_to_optional_value(is_option: bool) -> TokenStream { + if !is_option { + // raw type case + quote!( Some(v) ) + } else { + // Option<> type case + quote!( v ) + } +} + +pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { + let mut impls = TokenStream::new(); + + for line in &def.storage_lines { + + // Propagate doc attributes. + let attrs = &line.doc_attrs; + + let visibility = &line.visibility; + let optional_storage_runtime_comma = &line.optional_storage_runtime_comma; + let optional_storage_runtime_bound_comma = &line.optional_storage_runtime_bound_comma; + let optional_storage_where_clause = &line.optional_storage_where_clause; + let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default; + let optional_instance_bound = &def.optional_instance_bound; + let optional_instance = &def.optional_instance; + let name = &line.name; + + let struct_decl = quote!( + #( #[ #attrs ] )* + #visibility struct #name< + #optional_storage_runtime_bound_comma #optional_instance_bound_optional_default + >( + #scrate::sp_std::marker::PhantomData< + (#optional_storage_runtime_comma #optional_instance) + > + ) #optional_storage_where_clause; + ); + + let from_query_to_optional_value = from_query_to_optional_value(line.is_option); + let from_optional_value_to_query = + from_optional_value_to_query(line.is_option, &line.default_value); + + // Contains accessor to instance, used to get prefixes + let instance_or_inherent = if let Some(instance) = def.module_instance.as_ref() { + instance.instance_generic.clone() + } else { + Ident::new(INHERENT_INSTANCE_NAME, Span::call_site()) + }; + + let storage_name_str = syn::LitStr::new(&line.name.to_string(), line.name.span()); + + let storage_generator_trait = &line.storage_generator_trait; + let storage_struct = &line.storage_struct; + let impl_trait = quote!( #optional_storage_runtime_bound_comma #optional_instance_bound ); + let value_type = &line.value_type; + let query_type = &line.query_type; + + let struct_impl = match &line.storage_type { + StorageLineTypeDef::Simple(_) => { + quote!( + impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct + #optional_storage_where_clause + { + type Query = #query_type; + + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() + } + + fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { + #from_optional_value_to_query + } + + fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { + #from_query_to_optional_value + } + } + ) + }, + StorageLineTypeDef::Map(map) => { + let hasher = map.hasher.to_storage_hasher_struct(); + quote!( + impl<#impl_trait> #scrate::storage::StoragePrefixedMap<#value_type> + for #storage_struct #optional_storage_where_clause + { + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() + } + } + + impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct + #optional_storage_where_clause + { + type Query = #query_type; + type Hasher = #scrate::#hasher; + + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() + } + + fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { + #from_optional_value_to_query + } + + fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { + #from_query_to_optional_value + } + } + ) + }, + StorageLineTypeDef::LinkedMap(map) => { + let hasher = map.hasher.to_storage_hasher_struct(); + + let head_prefix_str = syn::LitStr::new( + &format!("HeadOf{}", line.name.to_string()), + line.name.span(), + ); + + quote!( + impl<#impl_trait> #scrate::storage::StoragePrefixedMap<#value_type> + for #storage_struct #optional_storage_where_clause + { + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() + } + } + + impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct + #optional_storage_where_clause + { + type Query = #query_type; + type KeyFormat = Self; + + fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { + #from_optional_value_to_query + } + + fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { + #from_query_to_optional_value + } + } + + impl<#impl_trait> #scrate::storage::generator::LinkedMapKeyFormat for #storage_struct { + type Hasher = #scrate::#hasher; + + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() + } + + fn head_prefix() -> &'static [u8] { + #head_prefix_str.as_bytes() + } + } + ) + }, + StorageLineTypeDef::DoubleMap(map) => { + let hasher1 = map.hasher1.to_storage_hasher_struct(); + let hasher2 = map.hasher2.to_storage_hasher_struct(); + quote!( + impl<#impl_trait> #scrate::storage::StoragePrefixedMap<#value_type> + for #storage_struct #optional_storage_where_clause + { + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() + } + } + + impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct + #optional_storage_where_clause + { + type Query = #query_type; + + type Hasher1 = #scrate::#hasher1; + + type Hasher2 = #scrate::#hasher2; + + fn module_prefix() -> &'static [u8] { + #instance_or_inherent::PREFIX.as_bytes() + } + + fn storage_prefix() -> &'static [u8] { + #storage_name_str.as_bytes() + } + + fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { + #from_optional_value_to_query + } + + fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { + #from_query_to_optional_value + } + } + ) + } + }; + + impls.extend(quote!( + #struct_decl + #struct_impl + )) + } + + impls +} diff --git a/srml/support/procedural/src/storage/store_trait.rs b/frame/support/procedural/src/storage/store_trait.rs similarity index 96% rename from srml/support/procedural/src/storage/store_trait.rs rename to frame/support/procedural/src/storage/store_trait.rs index 4c9d96b6bb27a..96281e408e958 100644 --- a/srml/support/procedural/src/storage/store_trait.rs +++ b/frame/support/procedural/src/storage/store_trait.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/frame/support/procedural/tools/Cargo.toml b/frame/support/procedural/tools/Cargo.toml new file mode 100644 index 0000000000000..a9b8f6d4bfafd --- /dev/null +++ b/frame/support/procedural/tools/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "frame-support-procedural-tools" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +frame-support-procedural-tools-derive = { version = "2.0.0", path = "./derive" } +proc-macro2 = "1.0.6" +quote = "1.0.2" +syn = { version = "1.0.7", features = ["full", "visit"] } +proc-macro-crate = "0.1.4" diff --git a/frame/support/procedural/tools/derive/Cargo.toml b/frame/support/procedural/tools/derive/Cargo.toml new file mode 100644 index 0000000000000..49aea10807f1b --- /dev/null +++ b/frame/support/procedural/tools/derive/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "frame-support-procedural-tools-derive" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0.6" +quote = { version = "1.0.2", features = ["proc-macro"] } +syn = { version = "1.0.7", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/frame/support/procedural/tools/derive/src/lib.rs b/frame/support/procedural/tools/derive/src/lib.rs new file mode 100644 index 0000000000000..e130ffbfa0e0c --- /dev/null +++ b/frame/support/procedural/tools/derive/src/lib.rs @@ -0,0 +1,243 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Use to derive parsing for parsing struct. +// end::description[] + +#![recursion_limit = "128"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use proc_macro2::Span; +use syn::parse_macro_input; +use quote::quote; + +pub(crate) fn fields_idents( + fields: impl Iterator, +) -> impl Iterator { + fields.enumerate().map(|(ix, field)| { + field.ident.clone().map(|i| quote!{#i}).unwrap_or_else(|| { + let f_ix: syn::Ident = syn::Ident::new(&format!("f_{}", ix), Span::call_site()); + quote!( #f_ix ) + }) + }) +} + +pub(crate) fn fields_access( + fields: impl Iterator, +) -> impl Iterator { + fields.enumerate().map(|(ix, field)| { + field.ident.clone().map(|i| quote!( #i )).unwrap_or_else(|| { + let f_ix: syn::Index = syn::Index { + index: ix as u32, + span: Span::call_site(), + }; + quote!( #f_ix ) + }) + }) +} + +/// 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 successful 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, + .. + } = input; + let field_names = { + let name = fields_idents(fields.iter().map(Clone::clone)); + quote!{ + #( + #name, + )* + } + }; + let field = fields_idents(fields.iter().map(Clone::clone)); + let tokens = quote! { + impl #generics syn::parse::Parse for #ident #generics { + fn parse(input: syn::parse::ParseStream) -> syn::parse::Result { + #( + let #field = input.parse()?; + )* + Ok(Self { + #field_names + }) + } + } + }; + tokens.into() +} + +fn derive_parse_enum(input: syn::ItemEnum) -> TokenStream { + let syn::ItemEnum { + ident, + generics, + variants, + .. + } = input; + let variants = variants.iter().map(|v| { + let variant_ident = v.ident.clone(); + let fields_build = if v.fields.iter().count() > 0 { + let fields_id = fields_idents(v.fields.iter().map(Clone::clone)); + quote!( (#(#fields_id), *) ) + } else { + quote!() + }; + + let fields_procs = fields_idents(v.fields.iter().map(Clone::clone)) + .map(|fident| { + quote!{ + let mut #fident = match fork.parse() { + Ok(r) => r, + Err(_e) => break, + }; + } + }); + let fields_procs_again = fields_idents(v.fields.iter().map(Clone::clone)) + .map(|fident| { + quote!{ + #fident = input.parse().expect("was parsed just before"); + } + }); + + // double parse to update input cursor position + // next syn crate version should be checked for a way + // to copy position/state from a fork + quote!{ + let mut fork = input.fork(); + loop { + #(#fields_procs)* + #(#fields_procs_again)* + return Ok(#ident::#variant_ident#fields_build); + } + } + }); + + let tokens = quote! { + impl #generics syn::parse::Parse for #ident #generics { + fn parse(input: syn::parse::ParseStream) -> syn::parse::Result { + #( + #variants + )* + // no early return from any variants + Err( + syn::parse::Error::new( + proc_macro2::Span::call_site(), + "derived enum no matching variants" + ) + ) + } + } + + }; + tokens.into() +} + +/// 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, + .. + } = input; + let variants = variants.iter().map(|v| { + let v_ident = v.ident.clone(); + let fields_build = if v.fields.iter().count() > 0 { + let fields_id = fields_idents(v.fields.iter().map(Clone::clone)); + quote!( (#(#fields_id), *) ) + } else { + quote!() + }; + let field = fields_idents(v.fields.iter().map(Clone::clone)); + quote! { + #ident::#v_ident#fields_build => { + #( + #field.to_tokens(tokens); + )* + }, + } + }); + let tokens = quote! { + impl #generics quote::ToTokens for #ident #generics { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + match self { + #( + #variants + )* + } + } + } + }; + + tokens.into() +} diff --git a/frame/support/procedural/tools/src/lib.rs b/frame/support/procedural/tools/src/lib.rs new file mode 100644 index 0000000000000..102fee0e18ed0 --- /dev/null +++ b/frame/support/procedural/tools/src/lib.rs @@ -0,0 +1,91 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Proc macro helpers for procedural macros +// end::description[] + +// reexport proc macros +pub use frame_support_procedural_tools_derive::*; + +use proc_macro_crate::crate_name; +use syn::parse::Error; +use quote::quote; + +pub mod syn_ext; + +// FIXME #1569, remove the following functions, which are copied from sp-api-macros +use proc_macro2::{TokenStream, Span}; +use syn::Ident; + +fn generate_hidden_includes_mod_name(unique_id: &str) -> Ident { + Ident::new(&format!("sp_api_hidden_includes_{}", unique_id), Span::call_site()) +} + +/// Generates the access to the `frame-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::quote!( frame_support ) + } else { + let mod_name = generate_hidden_includes_mod_name(unique_id); + 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) -> TokenStream { + if std::env::var("CARGO_PKG_NAME").unwrap() == def_crate { + TokenStream::new() + } else { + let mod_name = generate_hidden_includes_mod_name(unique_id); + + 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 ) + } + } + + } +} + +// fn to remove white spaces around string types +// (basically whitespaces around 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/frame/support/procedural/tools/src/syn_ext.rs similarity index 87% rename from srml/support/procedural/tools/src/syn_ext.rs rename to frame/support/procedural/tools/src/syn_ext.rs index 1658a6b4aea25..d0a5066b8017a 100644 --- a/srml/support/procedural/tools/src/syn_ext.rs +++ b/frame/support/procedural/tools/src/syn_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 syn::{visit::{Visit, self}, parse::{Parse, ParseStream, Result}, Ident}; use proc_macro2::{TokenStream, TokenTree}; -use quote::{ToTokens, quote}; +use quote::ToTokens; use std::iter::once; -use srml_support_procedural_tools_derive::{ToTokens, Parse}; +use frame_support_procedural_tools_derive::{ToTokens, Parse}; /// stop parsing here getting remaining token as content /// Warn duplicate stream (part of) @@ -59,6 +59,11 @@ macro_rules! groups_impl { } } + impl Clone for $name

{ + fn clone(&self) -> Self { + Self { token: self.token.clone(), content: self.content.clone() } + } + } } } @@ -72,11 +77,11 @@ pub struct PunctuatedInner { pub variant: V, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct NoTrailing; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Trailing; pub type Punctuated = PunctuatedInner; @@ -107,6 +112,12 @@ impl ToTokens for PunctuatedInner { } } +impl Clone for PunctuatedInner { + fn clone(&self) -> Self { + Self { inner: self.inner.clone(), variant: self.variant.clone() } + } +} + /// Note that syn Meta is almost fine for use case (lacks only `ToToken`) #[derive(Debug, Clone)] pub struct Meta { @@ -124,13 +135,7 @@ impl Parse for Meta { impl ToTokens for Meta { fn to_tokens(&self, tokens: &mut TokenStream) { match self.inner { - syn::Meta::Word(ref ident) => { - let ident = ident.clone(); - let toks = quote!{ - #[#ident] - }; - tokens.extend(toks); - }, + syn::Meta::Path(ref path) => path.to_tokens(tokens), syn::Meta::List(ref l) => l.to_tokens(tokens), syn::Meta::NameValue(ref n) => n.to_tokens(tokens), } @@ -184,13 +189,21 @@ impl ToTokens for Opt

{ } } +impl Clone for Opt

, +} + +impl TransactionPayment { + /// Create new `TransactionPayment` with the given reference to the client. + pub fn new(client: Arc) -> Self { + TransactionPayment { client, _marker: Default::default() } + } +} + +/// Error type of this RPC api. +pub enum Error { + /// The transaction was not decodable. + DecodeError, + /// The call to runtime failed. + RuntimeError, +} + +impl From for i64 { + fn from(e: Error) -> i64 { + match e { + Error::RuntimeError => 1, + Error::DecodeError => 2, + } + } +} + +impl TransactionPaymentApi<::Hash, Balance> + for TransactionPayment +where + Block: BlockT, + C: Send + Sync + 'static + ProvideRuntimeApi + HeaderBackend, + C::Api: TransactionPaymentRuntimeApi, + Balance: Codec + UniqueSaturatedInto, + Extrinsic: Codec + Send + Sync + 'static, +{ + fn query_info( + &self, + encoded_xt: Bytes, + at: Option<::Hash> + ) -> Result { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| + // If the block hash is not supplied assume the best block. + self.client.info().best_hash + )); + + let encoded_len = encoded_xt.len() as u32; + + let uxt: Extrinsic = Decode::decode(&mut &*encoded_xt).map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::DecodeError.into()), + message: "Unable to query dispatch info.".into(), + data: Some(format!("{:?}", e).into()), + })?; + api.query_info(&at, uxt, encoded_len).map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), + message: "Unable to query dispatch info.".into(), + data: Some(format!("{:?}", e).into()), + }).map(CappedDispatchInfo::new) + } +} diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs new file mode 100644 index 0000000000000..bae3096f3cdd1 --- /dev/null +++ b/frame/transaction-payment/src/lib.rs @@ -0,0 +1,653 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Transaction Payment Module +//! +//! This module provides the basic logic needed to pay the absolute minimum amount needed for a +//! transaction to be included. This includes: +//! - _weight fee_: A fee proportional to amount of weight a transaction consumes. +//! - _length fee_: A fee proportional to the encoded length of the transaction. +//! - _tip_: An optional tip. Tip increases the priority of the transaction, giving it a higher +//! chance to be included by the transaction queue. +//! +//! Additionally, this module allows one to configure: +//! - The mapping between one unit of weight to one unit of fee via [`WeightToFee`]. +//! - A means of updating the fee for the next block, via defining a multiplier, based on the +//! final state of the chain at the end of the previous block. This can be configured via +//! [`FeeMultiplierUpdate`] + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use codec::{Encode, Decode}; +use frame_support::{ + decl_storage, decl_module, + traits::{Currency, Get, OnUnbalanced, ExistenceRequirement, WithdrawReason}, + weights::{Weight, DispatchInfo, GetDispatchInfo}, +}; +use sp_runtime::{ + Fixed64, + transaction_validity::{ + TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError, + TransactionValidity, + }, + traits::{Zero, Saturating, SignedExtension, SaturatedConversion, Convert}, +}; +use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; + +type Multiplier = Fixed64; +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = + <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: frame_system::Trait { + /// The currency type in which fees will be paid. + type Currency: Currency + Send + Sync; + + /// Handler for the unbalanced reduction when taking transaction fees. + type OnTransactionPayment: OnUnbalanced>; + + /// The fee to be paid for making a transaction; the base. + type TransactionBaseFee: Get>; + + /// The fee to be paid for making a transaction; the per-byte portion. + type TransactionByteFee: Get>; + + /// Convert a weight value into a deductible fee based on the currency type. + type WeightToFee: Convert>; + + /// Update the multiplier of the next block, based on the previous block's weight. + type FeeMultiplierUpdate: Convert; +} + +decl_storage! { + trait Store for Module as Balances { + NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::from_parts(0); + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// The fee to be paid for making a transaction; the base. + const TransactionBaseFee: BalanceOf = T::TransactionBaseFee::get(); + + /// The fee to be paid for making a transaction; the per-byte portion. + const TransactionByteFee: BalanceOf = T::TransactionByteFee::get(); + + fn on_finalize() { + NextFeeMultiplier::mutate(|fm| { + *fm = T::FeeMultiplierUpdate::convert(*fm) + }); + } + } +} + +impl Module { + /// Query the data that we know about the fee of a given `call`. + /// + /// As this module is not and cannot be aware of the internals of a signed extension, it only + /// interprets them as some encoded value and takes their length into account. + /// + /// All dispatchables must be annotated with weight and will have some fee info. This function + /// always returns. + // NOTE: we can actually make it understand `ChargeTransactionPayment`, but would be some hassle + // for sure. We have to make it aware of the index of `ChargeTransactionPayment` in `Extra`. + // Alternatively, we could actually execute the tx's per-dispatch and record the balance of the + // sender before and after the pipeline.. but this is way too much hassle for a very very little + // potential gain in the future. + pub fn query_info( + unchecked_extrinsic: Extrinsic, + len: u32, + ) -> RuntimeDispatchInfo> + where + T: Send + Sync, + BalanceOf: Send + Sync, + { + let dispatch_info = ::get_dispatch_info(&unchecked_extrinsic); + + let partial_fee = >::compute_fee(len, dispatch_info, 0u32.into()); + let DispatchInfo { weight, class, .. } = dispatch_info; + + RuntimeDispatchInfo { weight, class, partial_fee } + } +} + +/// Require the transactor pay for themselves and maybe include a tip to gain additional priority +/// in the queue. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct ChargeTransactionPayment(#[codec(compact)] BalanceOf); + +impl ChargeTransactionPayment { + /// utility constructor. Used only in client/factory code. + pub fn from(fee: BalanceOf) -> Self { + Self(fee) + } + + /// Compute the final fee value for a particular transaction. + /// + /// The final fee is composed of: + /// - _base_fee_: This is the minimum amount a user pays for a transaction. + /// - _len_fee_: This is the amount paid merely to pay for size of the transaction. + /// - _weight_fee_: This amount is computed based on the weight of the transaction. Unlike + /// size-fee, this is not input dependent and reflects the _complexity_ of the execution + /// and the time it consumes. + /// - _targeted_fee_adjustment_: This is a multiplier that can tune the final fee based on + /// the congestion of the network. + /// - (optional) _tip_: if included in the transaction, it will be added on top. Only signed + /// transactions can have a tip. + /// + /// final_fee = base_fee + targeted_fee_adjustment(len_fee + weight_fee) + tip; + fn compute_fee( + len: u32, + info: ::DispatchInfo, + tip: BalanceOf, + ) -> BalanceOf + where + BalanceOf: Sync + Send, + { + if info.pays_fee { + let len = >::from(len); + let per_byte = T::TransactionByteFee::get(); + let len_fee = per_byte.saturating_mul(len); + + let weight_fee = { + // cap the weight to the maximum defined in runtime, otherwise it will be the `Bounded` + // maximum of its data type, which is not desired. + let capped_weight = info.weight.min(::MaximumBlockWeight::get()); + T::WeightToFee::convert(capped_weight) + }; + + // the adjustable part of the fee + let adjustable_fee = len_fee.saturating_add(weight_fee); + let targeted_fee_adjustment = NextFeeMultiplier::get(); + // adjusted_fee = adjustable_fee + (adjustable_fee * targeted_fee_adjustment) + let adjusted_fee = targeted_fee_adjustment.saturated_multiply_accumulate(adjustable_fee); + + let base_fee = T::TransactionBaseFee::get(); + let final_fee = base_fee.saturating_add(adjusted_fee).saturating_add(tip); + + final_fee + } else { + tip + } + } +} + +impl sp_std::fmt::Debug for ChargeTransactionPayment { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "ChargeTransactionPayment<{:?}>", self.0) + } + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for ChargeTransactionPayment + where BalanceOf: Send + Sync +{ + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = (); + type DispatchInfo = DispatchInfo; + type Pre = (); + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn validate( + &self, + who: &Self::AccountId, + _call: &Self::Call, + info: Self::DispatchInfo, + len: usize, + ) -> TransactionValidity { + // pay any fees. + let tip = self.0; + let fee = Self::compute_fee(len as u32, info, tip); + let imbalance = match T::Currency::withdraw( + who, + fee, + if tip.is_zero() { + WithdrawReason::TransactionPayment.into() + } else { + WithdrawReason::TransactionPayment | WithdrawReason::Tip + }, + ExistenceRequirement::KeepAlive, + ) { + Ok(imbalance) => imbalance, + Err(_) => return InvalidTransaction::Payment.into(), + }; + T::OnTransactionPayment::on_unbalanced(imbalance); + + let mut r = ValidTransaction::default(); + // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which + // will be a bit more than setting the priority to tip. For now, this is enough. + r.priority = fee.saturated_into::(); + Ok(r) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::Encode; + use frame_support::{ + parameter_types, impl_outer_origin, impl_outer_dispatch, + weights::{DispatchClass, DispatchInfo, GetDispatchInfo, Weight}, + }; + use sp_core::H256; + use sp_runtime::{ + Perbill, + testing::{Header, TestXt}, + traits::{BlakeTwo256, IdentityLookup, Extrinsic}, + }; + use pallet_balances::Call as BalancesCall; + use sp_std::cell::RefCell; + use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; + + const CALL: &::Call = &Call::Balances(BalancesCall::transfer(2, 69)); + + impl_outer_dispatch! { + pub enum Call for Runtime where origin: Origin { + pallet_balances::Balances, + frame_system::System, + } + } + + #[derive(Clone, PartialEq, Eq, Debug)] + pub struct Runtime; + + use frame_system as system; + impl_outer_origin!{ + pub enum Origin for Runtime {} + } + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + + parameter_types! { + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + pub const ExistentialDeposit: u64 = 0; + } + + impl pallet_balances::Trait for Runtime { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + + thread_local! { + static TRANSACTION_BASE_FEE: RefCell = RefCell::new(0); + static TRANSACTION_BYTE_FEE: RefCell = RefCell::new(1); + static WEIGHT_TO_FEE: RefCell = RefCell::new(1); + } + + pub struct TransactionBaseFee; + impl Get for TransactionBaseFee { + fn get() -> u64 { TRANSACTION_BASE_FEE.with(|v| *v.borrow()) } + } + + pub struct TransactionByteFee; + impl Get for TransactionByteFee { + fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) } + } + + pub struct WeightToFee(u64); + impl Convert for WeightToFee { + fn convert(t: Weight) -> u64 { + WEIGHT_TO_FEE.with(|v| *v.borrow() * (t as u64)) + } + } + + impl Trait for Runtime { + type Currency = pallet_balances::Module; + type OnTransactionPayment = (); + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = WeightToFee; + type FeeMultiplierUpdate = (); + } + + type Balances = pallet_balances::Module; + type System = frame_system::Module; + type TransactionPayment = Module; + + pub struct ExtBuilder { + balance_factor: u64, + base_fee: u64, + byte_fee: u64, + weight_to_fee: u64 + } + + impl Default for ExtBuilder { + fn default() -> Self { + Self { + balance_factor: 1, + base_fee: 0, + byte_fee: 1, + weight_to_fee: 1, + } + } + } + + impl ExtBuilder { + pub fn fees(mut self, base: u64, byte: u64, weight: u64) -> Self { + self.base_fee = base; + self.byte_fee = byte; + self.weight_to_fee = weight; + self + } + pub fn balance_factor(mut self, factor: u64) -> Self { + self.balance_factor = factor; + self + } + fn set_constants(&self) { + TRANSACTION_BASE_FEE.with(|v| *v.borrow_mut() = self.base_fee); + TRANSACTION_BYTE_FEE.with(|v| *v.borrow_mut() = self.byte_fee); + WEIGHT_TO_FEE.with(|v| *v.borrow_mut() = self.weight_to_fee); + } + pub fn build(self) -> sp_io::TestExternalities { + self.set_constants(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![ + (1, 10 * self.balance_factor), + (2, 20 * self.balance_factor), + (3, 30 * self.balance_factor), + (4, 40 * self.balance_factor), + (5, 50 * self.balance_factor), + (6, 60 * self.balance_factor) + ], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + } + + /// create a transaction info struct from weight. Handy to avoid building the whole struct. + pub fn info_from_weight(w: Weight) -> DispatchInfo { + DispatchInfo { weight: w, pays_fee: true, ..Default::default() } + } + + #[test] + fn signed_extension_transaction_payment_work() { + ExtBuilder::default() + .balance_factor(10) // 100 + .fees(5, 1, 1) // 5 fixed, 1 per byte, 1 per weight + .build() + .execute_with(|| + { + let len = 10; + assert!( + ChargeTransactionPayment::::from(0) + .pre_dispatch(&1, CALL, info_from_weight(5), len) + .is_ok() + ); + assert_eq!(Balances::free_balance(&1), 100 - 5 - 5 - 10); + + assert!( + ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, info_from_weight(3), len) + .is_ok() + ); + assert_eq!(Balances::free_balance(&2), 200 - 5 - 10 - 3 - 5); + }); + } + + #[test] + fn signed_extension_transaction_payment_is_bounded() { + ExtBuilder::default() + .balance_factor(1000) + .fees(0, 0, 1) + .build() + .execute_with(|| + { + // maximum weight possible + assert!( + ChargeTransactionPayment::::from(0) + .pre_dispatch(&1, CALL, info_from_weight(Weight::max_value()), 10) + .is_ok() + ); + // fee will be proportional to what is the actual maximum weight in the runtime. + assert_eq!( + Balances::free_balance(&1), + (10000 - ::MaximumBlockWeight::get()) as u64 + ); + }); + } + + #[test] + fn signed_extension_allows_free_transactions() { + ExtBuilder::default() + .fees(100, 1, 1) + .balance_factor(0) + .build() + .execute_with(|| + { + // 1 ain't have a penny. + assert_eq!(Balances::free_balance(&1), 0); + + let len = 100; + + // like a FreeOperational + let operational_transaction = DispatchInfo { + weight: 0, + class: DispatchClass::Operational, + pays_fee: false, + }; + assert!( + ChargeTransactionPayment::::from(0) + .validate(&1, CALL, operational_transaction , len) + .is_ok() + ); + + // like a FreeNormal + let free_transaction = DispatchInfo { + weight: 0, + class: DispatchClass::Normal, + pays_fee: true, + }; + assert!( + ChargeTransactionPayment::::from(0) + .validate(&1, CALL, free_transaction , len) + .is_err() + ); + }); + } + + #[test] + fn signed_ext_length_fee_is_also_updated_per_congestion() { + ExtBuilder::default() + .fees(5, 1, 1) + .balance_factor(10) + .build() + .execute_with(|| + { + // all fees should be x1.5 + NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); + let len = 10; + + assert!( + ChargeTransactionPayment::::from(10) // tipped + .pre_dispatch(&1, CALL, info_from_weight(3), len) + .is_ok() + ); + assert_eq!(Balances::free_balance(&1), 100 - 10 - 5 - (10 + 3) * 3 / 2); + }) + } + + #[test] + fn query_info_works() { + let call = Call::Balances(BalancesCall::transfer(2, 69)); + let origin = 111111; + let extra = (); + let xt = TestXt::new(call, Some((origin, extra))).unwrap(); + let info = xt.get_dispatch_info(); + let ext = xt.encode(); + let len = ext.len() as u32; + ExtBuilder::default() + .fees(5, 1, 2) + .build() + .execute_with(|| + { + // all fees should be x1.5 + NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); + + assert_eq!( + TransactionPayment::query_info(xt, len), + RuntimeDispatchInfo { + weight: info.weight, + class: info.class, + partial_fee: + 5 /* base */ + + ( + len as u64 /* len * 1 */ + + info.weight.min(MaximumBlockWeight::get()) as u64 * 2 /* weight * weight_to_fee */ + ) * 3 / 2 + }, + ); + + }); + } + + #[test] + fn compute_fee_works_without_multiplier() { + ExtBuilder::default() + .fees(100, 10, 1) + .balance_factor(0) + .build() + .execute_with(|| + { + // Next fee multiplier is zero + assert_eq!(NextFeeMultiplier::get(), Fixed64::from_natural(0)); + + // Tip only, no fees works + let dispatch_info = DispatchInfo { + weight: 0, + class: DispatchClass::Operational, + pays_fee: false, + }; + assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 10), 10); + // No tip, only base fee works + let dispatch_info = DispatchInfo { + weight: 0, + class: DispatchClass::Operational, + pays_fee: true, + }; + assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 0), 100); + // Tip + base fee works + assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 69), 169); + // Len (byte fee) + base fee works + assert_eq!(ChargeTransactionPayment::::compute_fee(42, dispatch_info, 0), 520); + // Weight fee + base fee works + let dispatch_info = DispatchInfo { + weight: 1000, + class: DispatchClass::Operational, + pays_fee: true, + }; + assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 0), 1100); + }); + } + + #[test] + fn compute_fee_works_with_multiplier() { + ExtBuilder::default() + .fees(100, 10, 1) + .balance_factor(0) + .build() + .execute_with(|| + { + // Add a next fee multiplier + NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); // = 1/2 = .5 + // Base fee is unaffected by multiplier + let dispatch_info = DispatchInfo { + weight: 0, + class: DispatchClass::Operational, + pays_fee: true, + }; + assert_eq!(ChargeTransactionPayment::::compute_fee(0, dispatch_info, 0), 100); + + // Everything works together :) + let dispatch_info = DispatchInfo { + weight: 123, + class: DispatchClass::Operational, + pays_fee: true, + }; + // 123 weight, 456 length, 100 base + // adjustable fee = (123 * 1) + (456 * 10) = 4683 + // adjusted fee = (4683 * .5) + 4683 = 7024.5 -> 7024 + // final fee = 100 + 7024 + 789 tip = 7913 + assert_eq!(ChargeTransactionPayment::::compute_fee(456, dispatch_info, 789), 7913); + }); + } + + #[test] + fn compute_fee_does_not_overflow() { + ExtBuilder::default() + .fees(100, 10, 1) + .balance_factor(0) + .build() + .execute_with(|| + { + // Overflow is handled + let dispatch_info = DispatchInfo { + weight: ::max_value(), + class: DispatchClass::Operational, + pays_fee: true, + }; + assert_eq!( + ChargeTransactionPayment::::compute_fee( + ::max_value(), + dispatch_info, + ::max_value() + ), + ::max_value() + ); + }); + } +} diff --git a/frame/treasury/Cargo.toml b/frame/treasury/Cargo.toml new file mode 100644 index 0000000000000..9fd76ddd9cefa --- /dev/null +++ b/frame/treasury/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "pallet-treasury" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" } + +[dev-dependencies] +sp-io ={ version = "2.0.0", path = "../../primitives/io" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", +] diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs new file mode 100644 index 0000000000000..1800d0ad04392 --- /dev/null +++ b/frame/treasury/src/lib.rs @@ -0,0 +1,1174 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Treasury Module +//! +//! The Treasury module provides a "pot" of funds that can be managed by stakeholders in the +//! system and a structure for making spending proposals from this pot. +//! +//! - [`treasury::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! The Treasury Module itself provides the pot to store funds, and a means for stakeholders to +//! propose, approve, and deny expenditures. The chain will need to provide a method (e.g. +//! inflation, fees) for collecting funds. +//! +//! By way of example, the Council could vote to fund the Treasury with a portion of the block +//! reward and use the funds to pay developers. +//! +//! ### Tipping +//! +//! A separate subsystem exists to allow for an agile "tipping" process, whereby a reward may be +//! given without first having a pre-determined stakeholder group come to consensus on how much +//! should be paid. +//! +//! A group of `Tippers` is determined through the config `Trait`. After half of these have declared +//! some amount that they believe a particular reported reason deserves, then a countfown period is +//! entered where any remaining members can declare their tip amounts also. After the close of the +//! countdown period, the median of all declared tips is paid to the reported beneficiary, along +//! with any finders fee, in case of a public (and bonded) original report. +//! +//! ### Terminology +//! +//! - **Proposal:** A suggestion to allocate funds from the pot to a beneficiary. +//! - **Beneficiary:** An account who will receive the funds from a proposal iff +//! the proposal is approved. +//! - **Deposit:** Funds that a proposer must lock when making a proposal. The +//! deposit will be returned or slashed if the proposal is approved or rejected +//! respectively. +//! - **Pot:** Unspent funds accumulated by the treasury module. +//! +//! Tipping protocol: +//! - **Tipping:** The process of gathering declarations of amounts to tip and taking the median +//! amount to be transferred from the treasury to a beneficiary account. +//! - **Tip Reason:** The reason for a tip; generally a URL which embodies or explains why a +//! particular individual (identified by an account ID) is worthy of a recognition by the +//! treasury. +//! - **Finder:** The original public reporter of some reason for tipping. +//! - **Finders Fee:** Some proportion of the tip amount that is paid to the reporter of the tip, +//! rather than the main beneficiary. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! General spending/proposal protocol: +//! - `propose_spend` - Make a spending proposal and stake the required deposit. +//! - `set_pot` - Set the spendable balance of funds. +//! - `configure` - Configure the module's proposal requirements. +//! - `reject_proposal` - Reject a proposal, slashing the deposit. +//! - `approve_proposal` - Accept the proposal, returning the deposit. +//! +//! Tipping protocol: +//! - `report_awesome` - Report something worthy of a tip and register for a finders fee. +//! - `retract_tip` - Retract a previous (finders fee registered) report. +//! - `tip_new` - Report an item worthy of a tip and declare a specific amount to tip. +//! - `tip` - Declare or redeclare an amount to tip for a particular reason. +//! - `close_tip` - Close and pay out a tip. +//! +//! ## GenesisConfig +//! +//! The Treasury module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use sp_std::prelude::*; +use frame_support::{decl_module, decl_storage, decl_event, ensure, print, decl_error, Parameter}; +use frame_support::traits::{ + Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, ExistenceRequirement::AllowDeath, + ReservableCurrency, WithdrawReason +}; +use sp_runtime::{Permill, ModuleId, Percent, RuntimeDebug, traits::{ + Zero, EnsureOrigin, StaticLookup, AccountIdConversion, Saturating, Hash, BadOrigin +}}; +use frame_support::{weights::SimpleDispatchInfo, traits::Contains}; +use codec::{Encode, Decode}; +use frame_system::{self as system, ensure_signed}; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type PositiveImbalanceOf = <::Currency as Currency<::AccountId>>::PositiveImbalance; +type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; + +/// The treasury's module id, used for deriving its sovereign account ID. +const MODULE_ID: ModuleId = ModuleId(*b"py/trsry"); + +pub trait Trait: frame_system::Trait { + /// The staking balance. + type Currency: Currency + ReservableCurrency; + + /// Origin from which approvals must come. + type ApproveOrigin: EnsureOrigin; + + /// Origin from which rejections must come. + type RejectOrigin: EnsureOrigin; + + /// Origin from which tippers must come. + type Tippers: Contains; + + /// The period for which a tip remains open after is has achieved threshold tippers. + type TipCountdown: Get; + + /// The percent of the final tip which goes to the original reporter of the tip. + type TipFindersFee: Get; + + /// The amount held on deposit for placing a tip report. + type TipReportDepositBase: Get>; + + /// The amount held on deposit per byte within the tip report reason. + type TipReportDepositPerByte: Get>; + + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// Handler for the unbalanced decrease when slashing for a rejected proposal. + type ProposalRejection: OnUnbalanced>; + + /// Fraction of a proposal's value that should be bonded in order to place the proposal. + /// An accepted proposal gets these back. A rejected proposal does not. + type ProposalBond: Get; + + /// Minimum amount of funds that should be placed in a deposit for making a proposal. + type ProposalBondMinimum: Get>; + + /// Period between successive spends. + type SpendPeriod: Get; + + /// Percentage of spare funds (if any) that are burnt per spend period. + type Burn: Get; +} + +/// An index of a proposal. Just a `u32`. +pub type ProposalIndex = u32; + +/// A spending proposal. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct Proposal { + /// The account proposing it. + proposer: AccountId, + /// The (total) amount that should be paid if the proposal is accepted. + value: Balance, + /// The account to whom the payment should be made if the proposal is accepted. + beneficiary: AccountId, + /// The amount held on deposit (reserved) for making this proposal. + bond: Balance, +} + +/// An open tipping "motion". Retains all details of a tip including information on the finder +/// and the members who have voted. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] +pub struct OpenTip< + AccountId: Parameter, + Balance: Parameter, + BlockNumber: Parameter, + Hash: Parameter, +> { + /// The hash of the reason for the tip. The reason should be a human-readable UTF-8 encoded string. A URL would be + /// sensible. + reason: Hash, + /// The account to be tipped. + who: AccountId, + /// The account who began this tip and the amount held on deposit. + finder: Option<(AccountId, Balance)>, + /// The block number at which this tip will close if `Some`. If `None`, then no closing is + /// scheduled. + closes: Option, + /// The members who have voted for this tip. Sorted by AccountId. + tips: Vec<(AccountId, Balance)>, +} + +decl_storage! { + trait Store for Module as Treasury { + /// Number of proposals that have been made. + ProposalCount get(fn proposal_count): ProposalIndex; + + /// Proposals that have been made. + Proposals get(fn proposals): map ProposalIndex => Option>>; + + /// Proposal indices that have been approved but not yet awarded. + Approvals get(fn approvals): Vec; + + /// Tips that are not yet completed. Keyed by the hash of `(reason, who)` from the value. + /// This has the insecure enumerable hash function since the key itself is already + /// guaranteed to be a secure hash. + pub Tips get(fn tips): map hasher(twox_64_concat) T::Hash + => Option, T::BlockNumber, T::Hash>>; + + /// Simple preimage lookup from the reason's hash to the original data. Again, has an + /// insecure enumerable hash since the key is guaranteed to be the result of a secure hash. + pub Reasons get(fn reasons): map hasher(twox_64_concat) T::Hash => Option>; + } + add_extra_genesis { + build(|_config| { + // Create Treasury account + let _ = T::Currency::make_free_balance_be( + &>::account_id(), + T::Currency::minimum_balance(), + ); + }); + } +} + +decl_event!( + pub enum Event + where + Balance = BalanceOf, + ::AccountId, + ::Hash, + { + /// New proposal. + Proposed(ProposalIndex), + /// We have ended a spend period and will now allocate funds. + Spending(Balance), + /// Some funds have been allocated. + Awarded(ProposalIndex, Balance, AccountId), + /// A proposal was rejected; funds were slashed. + Rejected(ProposalIndex, Balance), + /// Some of our funds have been burnt. + Burnt(Balance), + /// Spending has finished; this is the amount that rolls over until next spend. + Rollover(Balance), + /// Some funds have been deposited. + Deposit(Balance), + /// A new tip suggestion has been opened. + NewTip(Hash), + /// A tip suggestion has reached threshold and is closing. + TipClosing(Hash), + /// A tip suggestion has been closed. + TipClosed(Hash, AccountId, Balance), + /// A tip suggestion has been retracted. + TipRetracted(Hash), + } +); + +decl_error! { + /// Error for the treasury module. + pub enum Error for Module { + /// Proposer's balance is too low. + InsufficientProposersBalance, + /// No proposal at that index. + InvalidProposalIndex, + /// The reason given is just too big. + ReasonTooBig, + /// The tip was already found/started. + AlreadyKnown, + /// The tip hash is unknown. + UnknownTip, + /// The account attempting to retract the tip is not the finder of the tip. + NotFinder, + /// The tip cannot be claimed/closed because there are not enough tippers yet. + StillOpen, + /// The tip cannot be claimed/closed because it's still in the countdown period. + Premature, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Fraction of a proposal's value that should be bonded in order to place the proposal. + /// An accepted proposal gets these back. A rejected proposal does not. + const ProposalBond: Permill = T::ProposalBond::get(); + + /// Minimum amount of funds that should be placed in a deposit for making a proposal. + const ProposalBondMinimum: BalanceOf = T::ProposalBondMinimum::get(); + + /// Period between successive spends. + const SpendPeriod: T::BlockNumber = T::SpendPeriod::get(); + + /// Percentage of spare funds (if any) that are burnt per spend period. + const Burn: Permill = T::Burn::get(); + + /// The period for which a tip remains open after is has achieved threshold tippers. + const TipCountdown: T::BlockNumber = T::TipCountdown::get(); + + /// The amount of the final tip which goes to the original reporter of the tip. + const TipFindersFee: Percent = T::TipFindersFee::get(); + + /// The amount held on deposit for placing a tip report. + const TipReportDepositBase: BalanceOf = T::TipReportDepositBase::get(); + + /// The amount held on deposit per byte within the tip report reason. + const TipReportDepositPerByte: BalanceOf = T::TipReportDepositPerByte::get(); + + type Error = Error; + + 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. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB change, one extra DB entry. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn propose_spend( + origin, + #[compact] value: BalanceOf, + beneficiary: ::Source + ) { + let proposer = ensure_signed(origin)?; + let beneficiary = T::Lookup::lookup(beneficiary)?; + + let bond = Self::calculate_bond(value); + T::Currency::reserve(&proposer, bond) + .map_err(|_| Error::::InsufficientProposersBalance)?; + + let c = Self::proposal_count(); + ProposalCount::put(c + 1); + >::insert(c, Proposal { proposer, value, beneficiary, bond }); + + Self::deposit_event(RawEvent::Proposed(c)); + } + + /// Reject a proposed spend. The original deposit will be slashed. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB clear. + /// # + #[weight = SimpleDispatchInfo::FixedOperational(100_000)] + fn reject_proposal(origin, #[compact] proposal_id: ProposalIndex) { + T::RejectOrigin::ensure_origin(origin)?; + let proposal = >::take(&proposal_id).ok_or(Error::::InvalidProposalIndex)?; + + let value = proposal.bond; + let imbalance = T::Currency::slash_reserved(&proposal.proposer, value).0; + T::ProposalRejection::on_unbalanced(imbalance); + + Self::deposit_event(Event::::Rejected(proposal_id, value)); + } + + /// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary + /// and the original deposit will be returned. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB change. + /// # + #[weight = SimpleDispatchInfo::FixedOperational(100_000)] + fn approve_proposal(origin, #[compact] proposal_id: ProposalIndex) { + T::ApproveOrigin::ensure_origin(origin)?; + + ensure!(>::exists(proposal_id), Error::::InvalidProposalIndex); + + Approvals::mutate(|v| v.push(proposal_id)); + } + + /// Report something `reason` that deserves a tip and claim any eventual the finder's fee. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// Payment: `TipReportDepositBase` will be reserved from the origin account, as well as + /// `TipReportDepositPerByte` for each byte in `reason`. + /// + /// - `reason`: The reason for, or the thing that deserves, the tip; generally this will be + /// a UTF-8-encoded URL. + /// - `who`: The account which should be credited for the tip. + /// + /// Emits `NewTip` if successful. + /// + /// # + /// - `O(R)` where `R` length of `reason`. + /// - One balance operation. + /// - One storage mutation (codec `O(R)`). + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + fn report_awesome(origin, reason: Vec, who: T::AccountId) { + let finder = ensure_signed(origin)?; + + const MAX_SENSIBLE_REASON_LENGTH: usize = 16384; + ensure!(reason.len() <= MAX_SENSIBLE_REASON_LENGTH, Error::::ReasonTooBig); + + let reason_hash = T::Hashing::hash(&reason[..]); + ensure!(!Reasons::::exists(&reason_hash), Error::::AlreadyKnown); + let hash = T::Hashing::hash_of(&(&reason_hash, &who)); + ensure!(!Tips::::exists(&hash), Error::::AlreadyKnown); + + let deposit = T::TipReportDepositBase::get() + + T::TipReportDepositPerByte::get() * (reason.len() as u32).into(); + T::Currency::reserve(&finder, deposit)?; + + Reasons::::insert(&reason_hash, &reason); + let finder = Some((finder, deposit)); + let tip = OpenTip { reason: reason_hash, who, finder, closes: None, tips: vec![] }; + Tips::::insert(&hash, tip); + Self::deposit_event(RawEvent::NewTip(hash)); + } + + /// Retract a prior tip-report from `report_awesome`, and cancel the process of tipping. + /// + /// If successful, the original deposit will be unreserved. + /// + /// The dispatch origin for this call must be _Signed_ and the tip identified by `hash` + /// must have been reported by the signing account through `report_awesome` (and not + /// through `tip_new`). + /// + /// - `hash`: The identity of the open tip for which a tip value is declared. This is formed + /// as the hash of the tuple of the original tip `reason` and the beneficiary account ID. + /// + /// Emits `TipRetracted` if successful. + /// + /// # + /// - `O(T)` + /// - One balance operation. + /// - Two storage removals (one read, codec `O(T)`). + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn retract_tip(origin, hash: T::Hash) { + let who = ensure_signed(origin)?; + let tip = Tips::::get(&hash).ok_or(Error::::UnknownTip)?; + let (finder, deposit) = tip.finder.ok_or(Error::::NotFinder)?; + ensure!(finder == who, Error::::NotFinder); + + Reasons::::remove(&tip.reason); + Tips::::remove(&hash); + let _ = T::Currency::unreserve(&who, deposit); + Self::deposit_event(RawEvent::TipRetracted(hash)); + } + + /// Give a tip for something new; no finder's fee will be taken. + /// + /// The dispatch origin for this call must be _Signed_ and the signing account must be a + /// member of the `Tippers` set. + /// + /// - `reason`: The reason for, or the thing that deserves, the tip; generally this will be + /// a UTF-8-encoded URL. + /// - `who`: The account which should be credited for the tip. + /// - `tip_value`: The amount of tip that the sender would like to give. The median tip + /// value of active tippers will be given to the `who`. + /// + /// Emits `NewTip` if successful. + /// + /// # + /// - `O(R + T)` where `R` length of `reason`, `T` is the number of tippers. `T` is + /// naturally capped as a membership set, `R` is limited through transaction-size. + /// - Two storage insertions (codecs `O(R)`, `O(T)`), one read `O(1)`. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(150_000)] + fn tip_new(origin, reason: Vec, who: T::AccountId, tip_value: BalanceOf) { + let tipper = ensure_signed(origin)?; + ensure!(T::Tippers::contains(&tipper), BadOrigin); + let reason_hash = T::Hashing::hash(&reason[..]); + ensure!(!Reasons::::exists(&reason_hash), Error::::AlreadyKnown); + let hash = T::Hashing::hash_of(&(&reason_hash, &who)); + + Reasons::::insert(&reason_hash, &reason); + Self::deposit_event(RawEvent::NewTip(hash.clone())); + let tips = vec![(tipper, tip_value)]; + let tip = OpenTip { reason: reason_hash, who, finder: None, closes: None, tips }; + Tips::::insert(&hash, tip); + } + + /// Declare a tip value for an already-open tip. + /// + /// The dispatch origin for this call must be _Signed_ and the signing account must be a + /// member of the `Tippers` set. + /// + /// - `hash`: The identity of the open tip for which a tip value is declared. This is formed + /// as the hash of the tuple of the hash of the original tip `reason` and the beneficiary + /// account ID. + /// - `tip_value`: The amount of tip that the sender would like to give. The median tip + /// value of active tippers will be given to the `who`. + /// + /// Emits `TipClosing` if the threshold of tippers has been reached and the countdown period + /// has started. + /// + /// # + /// - `O(T)` + /// - One storage mutation (codec `O(T)`), one storage read `O(1)`. + /// - Up to one event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn tip(origin, hash: T::Hash, tip_value: BalanceOf) { + let tipper = ensure_signed(origin)?; + ensure!(T::Tippers::contains(&tipper), BadOrigin); + + let mut tip = Tips::::get(hash).ok_or(Error::::UnknownTip)?; + if Self::insert_tip_and_check_closing(&mut tip, tipper, tip_value) { + Self::deposit_event(RawEvent::TipClosing(hash.clone())); + } + Tips::::insert(&hash, tip); + } + + /// Close and payout a tip. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// The tip identified by `hash` must have finished its countdown period. + /// + /// - `hash`: The identity of the open tip for which a tip value is declared. This is formed + /// as the hash of the tuple of the original tip `reason` and the beneficiary account ID. + /// + /// # + /// - `O(T)` + /// - One storage retrieval (codec `O(T)`) and two removals. + /// - Up to three balance operations. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn close_tip(origin, hash: T::Hash) { + ensure_signed(origin)?; + + let tip = Tips::::get(hash).ok_or(Error::::UnknownTip)?; + let n = tip.closes.as_ref().ok_or(Error::::StillOpen)?; + ensure!(system::Module::::block_number() >= *n, Error::::Premature); + // closed. + Reasons::::remove(&tip.reason); + Tips::::remove(hash); + Self::payout_tip(tip); + } + + fn on_finalize(n: T::BlockNumber) { + // Check to see if we should spend some funds! + if (n % T::SpendPeriod::get()).is_zero() { + Self::spend_funds(); + } + } + } +} + +impl Module { + // Add public immutables and private mutables. + + /// The account ID of the treasury pot. + /// + /// This actually does computation. If you need to keep using it, then make sure you cache the + /// value and only call this once. + pub fn account_id() -> T::AccountId { + MODULE_ID.into_account() + } + + /// The needed bond for a proposal whose spend is `value`. + fn calculate_bond(value: BalanceOf) -> BalanceOf { + T::ProposalBondMinimum::get().max(T::ProposalBond::get() * value) + } + + /// Given a mutable reference to an `OpenTip`, insert the tip into it and check whether it + /// closes, if so, then deposit the relevant event and set closing accordingly. + /// + /// `O(T)` and one storage access. + fn insert_tip_and_check_closing( + tip: &mut OpenTip, T::BlockNumber, T::Hash>, + tipper: T::AccountId, + tip_value: BalanceOf, + ) -> bool { + match tip.tips.binary_search_by_key(&&tipper, |x| &x.0) { + Ok(pos) => tip.tips[pos] = (tipper, tip_value), + Err(pos) => tip.tips.insert(pos, (tipper, tip_value)), + } + Self::retain_active_tips(&mut tip.tips); + let threshold = (T::Tippers::count() + 1) / 2; + if tip.tips.len() >= threshold && tip.closes.is_none() { + tip.closes = Some(system::Module::::block_number() + T::TipCountdown::get()); + true + } else { + false + } + } + + /// Remove any non-members of `Tippers` from a `tips` vectr. `O(T)`. + fn retain_active_tips(tips: &mut Vec<(T::AccountId, BalanceOf)>) { + let members = T::Tippers::sorted_members(); + let mut members_iter = members.iter(); + let mut member = members_iter.next(); + tips.retain(|(ref a, _)| loop { + match member { + None => break false, + Some(m) if m > a => break false, + Some(m) => { + member = members_iter.next(); + if m < a { + continue + } else { + break true; + } + } + } + }); + } + + /// Execute the payout of a tip. + /// + /// Up to three balance operations. + /// Plus `O(T)` (`T` is Tippers length). + fn payout_tip(tip: OpenTip, T::BlockNumber, T::Hash>) { + let mut tips = tip.tips; + Self::retain_active_tips(&mut tips); + tips.sort_by_key(|i| i.1); + let treasury = Self::account_id(); + let max_payout = T::Currency::free_balance(&treasury); + let mut payout = tips[tips.len() / 2].1.min(max_payout); + if let Some((finder, deposit)) = tip.finder { + let _ = T::Currency::unreserve(&finder, deposit); + if finder != tip.who { + // pay out the finder's fee. + let finders_fee = T::TipFindersFee::get() * payout; + payout -= finders_fee; + // this should go through given we checked it's at most the free balance, but still + // we only make a best-effort. + let _ = T::Currency::transfer(&treasury, &finder, finders_fee, AllowDeath); + } + } + // same as above: best-effort only. + let _ = T::Currency::transfer(&treasury, &tip.who, payout, AllowDeath); + } + + // Spend some money! + fn spend_funds() { + let mut budget_remaining = Self::pot(); + Self::deposit_event(RawEvent::Spending(budget_remaining)); + + let mut missed_any = false; + let mut imbalance = >::zero(); + Approvals::mutate(|v| { + v.retain(|&index| { + // Should always be true, but shouldn't panic if false or we're screwed. + if let Some(p) = Self::proposals(index) { + if p.value <= budget_remaining { + budget_remaining -= p.value; + >::remove(index); + + // return their deposit. + let _ = T::Currency::unreserve(&p.proposer, p.bond); + + // provide the allocation. + imbalance.subsume(T::Currency::deposit_creating(&p.beneficiary, p.value)); + + Self::deposit_event(RawEvent::Awarded(index, p.value, p.beneficiary)); + false + } else { + missed_any = true; + true + } + } else { + false + } + }); + }); + + if !missed_any { + // burn some proportion of the remaining budget if we run a surplus. + let burn = (T::Burn::get() * budget_remaining).min(budget_remaining); + budget_remaining -= burn; + imbalance.subsume(T::Currency::burn(burn)); + Self::deposit_event(RawEvent::Burnt(burn)) + } + + // Must never be an error, but better to be safe. + // proof: budget_remaining is account free balance minus ED; + // Thus we can't spend more than account free balance minus ED; + // Thus account is kept alive; qed; + if let Err(problem) = T::Currency::settle( + &Self::account_id(), + imbalance, + WithdrawReason::Transfer.into(), + ExistenceRequirement::KeepAlive + ) { + print("Inconsistent state - couldn't settle imbalance for funds spent by treasury"); + // Nothing else to do here. + drop(problem); + } + + Self::deposit_event(RawEvent::Rollover(budget_remaining)); + } + + /// Return the amount of money in the pot. + // The existential deposit is not part of the pot so treasury account never gets deleted. + fn pot() -> BalanceOf { + T::Currency::free_balance(&Self::account_id()) + // Must never be less than 0 but better be safe. + .saturating_sub(T::Currency::minimum_balance()) + } +} + +impl OnUnbalanced> for Module { + fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { + let numeric_amount = amount.peek(); + + // Must resolve into existing but better to be safe. + let _ = T::Currency::resolve_creating(&Self::account_id(), amount); + + Self::deposit_event(RawEvent::Deposit(numeric_amount)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use frame_support::{assert_noop, assert_ok, impl_outer_origin, parameter_types, weights::Weight}; + use frame_support::traits::Contains; + use sp_core::H256; + use sp_runtime::{ + traits::{BlakeTwo256, OnFinalize, IdentityLookup, BadOrigin}, testing::Header, Perbill + }; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 1; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl pallet_balances::Trait for Test { + type Balance = u64; + type OnNewAccount = (); + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + pub struct TenToFourteen; + impl Contains for TenToFourteen { + fn contains(n: &u64) -> bool { + *n >= 10 && *n <= 14 + } + fn sorted_members() -> Vec { + vec![10, 11, 12, 13, 14] + } + } + parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: u64 = 1; + pub const SpendPeriod: u64 = 2; + pub const Burn: Permill = Permill::from_percent(50); + pub const TipCountdown: u64 = 1; + pub const TipFindersFee: Percent = Percent::from_percent(20); + pub const TipReportDepositBase: u64 = 1; + pub const TipReportDepositPerByte: u64 = 1; + } + impl Trait for Test { + type Currency = pallet_balances::Module; + type ApproveOrigin = frame_system::EnsureRoot; + type RejectOrigin = frame_system::EnsureRoot; + type Tippers = TenToFourteen; + type TipCountdown = TipCountdown; + type TipFindersFee = TipFindersFee; + type TipReportDepositBase = TipReportDepositBase; + type TipReportDepositPerByte = TipReportDepositPerByte; + type Event = (); + type ProposalRejection = (); + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type SpendPeriod = SpendPeriod; + type Burn = Burn; + } + type System = frame_system::Module; + type Balances = pallet_balances::Module; + type Treasury = Module; + + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig::{ + // Total issuance will be 200 with treasury account initialized at ED. + balances: vec![(0, 100), (1, 98), (2, 1)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + GenesisConfig::default().assimilate_storage::(&mut t).unwrap(); + t.into() + } + + #[test] + fn genesis_config_works() { + new_test_ext().execute_with(|| { + assert_eq!(Treasury::pot(), 0); + assert_eq!(Treasury::proposal_count(), 0); + }); + } + + fn tip_hash() -> H256 { + BlakeTwo256::hash_of(&(BlakeTwo256::hash(b"awesome.dot"), 3u64)) + } + + #[test] + fn tip_new_cannot_be_used_twice() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_ok!(Treasury::tip_new(Origin::signed(10), b"awesome.dot".to_vec(), 3, 10)); + assert_noop!( + Treasury::tip_new(Origin::signed(11), b"awesome.dot".to_vec(), 3, 10), + Error::::AlreadyKnown + ); + }); + } + + #[test] + fn report_awesome_and_tip_works() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_ok!(Treasury::report_awesome(Origin::signed(0), b"awesome.dot".to_vec(), 3)); + assert_eq!(Balances::reserved_balance(&0), 12); + assert_eq!(Balances::free_balance(&0), 88); + + // other reports don't count. + assert_noop!( + Treasury::report_awesome(Origin::signed(1), b"awesome.dot".to_vec(), 3), + Error::::AlreadyKnown + ); + + let h = tip_hash(); + assert_ok!(Treasury::tip(Origin::signed(10), h.clone(), 10)); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10)); + assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10)); + assert_noop!(Treasury::tip(Origin::signed(9), h.clone(), 10), BadOrigin); + System::set_block_number(2); + assert_ok!(Treasury::close_tip(Origin::signed(100), h.into())); + assert_eq!(Balances::reserved_balance(&0), 0); + assert_eq!(Balances::free_balance(&0), 102); + assert_eq!(Balances::free_balance(&3), 8); + }); + } + + #[test] + fn report_awesome_from_beneficiary_and_tip_works() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_ok!(Treasury::report_awesome(Origin::signed(0), b"awesome.dot".to_vec(), 0)); + assert_eq!(Balances::reserved_balance(&0), 12); + assert_eq!(Balances::free_balance(&0), 88); + let h = BlakeTwo256::hash_of(&(BlakeTwo256::hash(b"awesome.dot"), 0u64)); + assert_ok!(Treasury::tip(Origin::signed(10), h.clone(), 10)); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10)); + assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10)); + System::set_block_number(2); + assert_ok!(Treasury::close_tip(Origin::signed(100), h.into())); + assert_eq!(Balances::reserved_balance(&0), 0); + assert_eq!(Balances::free_balance(&0), 110); + }); + } + + #[test] + fn close_tip_works() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Treasury::pot(), 100); + + assert_ok!(Treasury::tip_new(Origin::signed(10), b"awesome.dot".to_vec(), 3, 10)); + let h = tip_hash(); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10)); + assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::::StillOpen); + + assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10)); + assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::::Premature); + + System::set_block_number(2); + assert_noop!(Treasury::close_tip(Origin::NONE, h.into()), BadOrigin); + assert_ok!(Treasury::close_tip(Origin::signed(0), h.into())); + assert_eq!(Balances::free_balance(&3), 10); + + assert_noop!(Treasury::close_tip(Origin::signed(100), h.into()), Error::::UnknownTip); + }); + } + + #[test] + fn retract_tip_works() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_ok!(Treasury::report_awesome(Origin::signed(0), b"awesome.dot".to_vec(), 3)); + let h = tip_hash(); + assert_ok!(Treasury::tip(Origin::signed(10), h.clone(), 10)); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10)); + assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10)); + assert_noop!(Treasury::retract_tip(Origin::signed(10), h.clone()), Error::::NotFinder); + assert_ok!(Treasury::retract_tip(Origin::signed(0), h.clone())); + System::set_block_number(2); + assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::::UnknownTip); + }); + } + + #[test] + fn tip_median_calculation_works() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_ok!(Treasury::tip_new(Origin::signed(10), b"awesome.dot".to_vec(), 3, 0)); + let h = tip_hash(); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10)); + assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 1000000)); + System::set_block_number(2); + assert_ok!(Treasury::close_tip(Origin::signed(0), h.into())); + assert_eq!(Balances::free_balance(&3), 10); + }); + } + + #[test] + fn tip_changing_works() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_ok!(Treasury::tip_new(Origin::signed(10), b"awesome.dot".to_vec(), 3, 10000)); + let h = tip_hash(); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10000)); + assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10000)); + assert_ok!(Treasury::tip(Origin::signed(13), h.clone(), 0)); + assert_ok!(Treasury::tip(Origin::signed(14), h.clone(), 0)); + assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 1000)); + assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 100)); + assert_ok!(Treasury::tip(Origin::signed(10), h.clone(), 10)); + System::set_block_number(2); + assert_ok!(Treasury::close_tip(Origin::signed(0), h.into())); + assert_eq!(Balances::free_balance(&3), 10); + }); + } + + #[test] + fn minting_works() { + new_test_ext().execute_with(|| { + // Check that accumulate works when we have Some value in Dummy already. + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Treasury::pot(), 100); + }); + } + + #[test] + fn spend_proposal_takes_min_deposit() { + new_test_ext().execute_with(|| { + assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); + assert_eq!(Balances::free_balance(&0), 99); + assert_eq!(Balances::reserved_balance(&0), 1); + }); + } + + #[test] + fn spend_proposal_takes_proportional_deposit() { + new_test_ext().execute_with(|| { + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_eq!(Balances::free_balance(&0), 95); + assert_eq!(Balances::reserved_balance(&0), 5); + }); + } + + #[test] + fn spend_proposal_fails_when_proposer_poor() { + new_test_ext().execute_with(|| { + assert_noop!( + Treasury::propose_spend(Origin::signed(2), 100, 3), + Error::::InsufficientProposersBalance, + ); + }); + } + + #[test] + fn accepted_spend_proposal_ignored_outside_spend_period() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + + >::on_finalize(1); + assert_eq!(Balances::free_balance(&3), 0); + assert_eq!(Treasury::pot(), 100); + }); + } + + #[test] + fn unused_pot_should_diminish() { + new_test_ext().execute_with(|| { + let init_total_issuance = Balances::total_issuance(); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::total_issuance(), init_total_issuance + 100); + + >::on_finalize(2); + assert_eq!(Treasury::pot(), 50); + assert_eq!(Balances::total_issuance(), init_total_issuance + 50); + }); + } + + #[test] + fn rejected_spend_proposal_ignored_on_spend_period() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); + + >::on_finalize(2); + assert_eq!(Balances::free_balance(&3), 0); + assert_eq!(Treasury::pot(), 50); + }); + } + + #[test] + fn reject_already_rejected_spend_proposal_fails() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); + assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + }); + } + + #[test] + fn reject_non_existant_spend_proposal_fails() { + new_test_ext().execute_with(|| { + assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + }); + } + + #[test] + fn accept_non_existant_spend_proposal_fails() { + new_test_ext().execute_with(|| { + assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + }); + } + + #[test] + fn accept_already_rejected_spend_proposal_fails() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); + assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + }); + } + + #[test] + fn accepted_spend_proposal_enacted_on_spend_period() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Treasury::pot(), 100); + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + + >::on_finalize(2); + assert_eq!(Balances::free_balance(&3), 100); + assert_eq!(Treasury::pot(), 0); + }); + } + + #[test] + fn pot_underflow_should_not_diminish() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Treasury::pot(), 100); + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + + >::on_finalize(2); + assert_eq!(Treasury::pot(), 100); // Pot hasn't changed + + let _ = Balances::deposit_into_existing(&Treasury::account_id(), 100).unwrap(); + >::on_finalize(4); + assert_eq!(Balances::free_balance(&3), 150); // Fund has been spent + assert_eq!(Treasury::pot(), 25); // Pot has finally changed + }); + } + + // Treasury account doesn't get deleted if amount approved to spend is all its free balance. + // i.e. pot should not include existential deposit needed for account survival. + #[test] + fn treasury_account_doesnt_get_deleted() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Treasury::pot(), 100); + let treasury_balance = Balances::free_balance(&Treasury::account_id()); + + assert_ok!(Treasury::propose_spend(Origin::signed(0), treasury_balance, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + + >::on_finalize(2); + assert_eq!(Treasury::pot(), 100); // Pot hasn't changed + + assert_ok!(Treasury::propose_spend(Origin::signed(0), Treasury::pot(), 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); + + >::on_finalize(4); + assert_eq!(Treasury::pot(), 0); // Pot is emptied + assert_eq!(Balances::free_balance(&Treasury::account_id()), 1); // but the account is still there + }); + } + + // In case treasury account is not existing then it works fine. + // This is usefull for chain that will just update runtime. + #[test] + fn inexisting_account_works() { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig::{ + balances: vec![(0, 100), (1, 99), (2, 1)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + // Treasury genesis config is not build thus treasury account does not exist + let mut t: sp_io::TestExternalities = t.into(); + + t.execute_with(|| { + assert_eq!(Balances::free_balance(&Treasury::account_id()), 0); // Account does not exist + assert_eq!(Treasury::pot(), 0); // Pot is empty + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 99, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); + >::on_finalize(2); + assert_eq!(Treasury::pot(), 0); // Pot hasn't changed + assert_eq!(Balances::free_balance(&3), 0); // Balance of `3` hasn't changed + + Balances::make_free_balance_be(&Treasury::account_id(), 100); + assert_eq!(Treasury::pot(), 99); // Pot now contains funds + assert_eq!(Balances::free_balance(&Treasury::account_id()), 100); // Account does exist + + >::on_finalize(4); + + assert_eq!(Treasury::pot(), 0); // Pot has changed + assert_eq!(Balances::free_balance(&3), 99); // Balance of `3` has changed + }); + } +} diff --git a/frame/utility/Cargo.toml b/frame/utility/Cargo.toml new file mode 100644 index 0000000000000..afd7ae3d374c7 --- /dev/null +++ b/frame/utility/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "pallet-utility" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "sp-io/std", + "sp-std/std" +] diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs new file mode 100644 index 0000000000000..9ab2975e29550 --- /dev/null +++ b/frame/utility/src/lib.rs @@ -0,0 +1,1069 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Utility Module +//! A module with helpers for dispatch management. +//! +//! - [`utility::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! This module contains three basic pieces of functionality, two of which are stateless: +//! - Batch dispatch: A stateless operation, allowing any origin to execute multiple calls in a +//! single dispatch. This can be useful to amalgamate proposals, combining `set_code` with +//! corresponding `set_storage`s, for efficient multiple payouts with just a single signature +//! verify, or in combination with one of the other two dispatch functionality. +//! - Pseudonymal dispatch: A stateless operation, allowing a signed origin to execute a call from +//! an alternative signed origin. Each account has 2**16 possible "pseudonyms" (alternative +//! account IDs) and these can be stacked. This can be useful as a key management tool, where you +//! need multiple distinct accounts (e.g. as controllers for many staking accounts), but where +//! it's perfectly fine to have each of them controlled by the same underlying keypair. +//! - Multisig dispatch (stateful): A potentially stateful operation, allowing multiple signed +//! origins (accounts) to coordinate and dispatch a call from a well-known origin, derivable +//! deterministically from the set of account IDs and the threshold number of accounts from the +//! set that must approve it. In the case that the threshold is just one then this is a stateless +//! operation. This is useful for multisig wallets where cryptographic threshold signatures are +//! not available or desired. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! #### For batch dispatch +//! * `batch` - Dispatch multiple calls from the sender's origin. +//! +//! #### For pseudonymal dispatch +//! * `as_sub` - Dispatch a call from a secondary ("sub") signed origin. +//! +//! #### For multisig dispatch +//! * `as_multi` - Approve and if possible dispatch a call from a composite origin formed from a +//! number of signed origins. +//! * `approve_as_multi` - Approve a call from a composite origin. +//! * `cancel_as_multi` - Cancel a call from a composite origin. +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use codec::{Encode, Decode}; +use sp_core::TypeId; +use sp_io::hashing::blake2_256; +use frame_support::{decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, RuntimeDebug}; +use frame_support::{traits::{Get, ReservableCurrency, Currency}, weights::{ + GetDispatchInfo, ClassifyDispatch, WeighData, Weight, DispatchClass, PaysFee +}}; +use frame_system::{self as system, ensure_signed}; +use sp_runtime::{DispatchError, DispatchResult, traits::Dispatchable}; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + +/// Configuration trait. +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The overarching call type. + type Call: Parameter + Dispatchable + GetDispatchInfo; + + /// The currency mechanism. + type Currency: ReservableCurrency; + + /// The base amount of currency needed to reserve for creating a multisig execution. + /// + /// This is held for an additional storage item whose value size is + /// `4 + sizeof((BlockNumber, Balance, AccountId))` bytes. + type MultisigDepositBase: Get>; + + /// The amount of currency needed per unit threshold when creating a multisig execution. + /// + /// This is held for adding 32 bytes more into a pre-existing storage value. + type MultisigDepositFactor: Get>; + + /// The maximum amount of signatories allowed in the multisig. + type MaxSignatories: Get; +} + +/// A global extrinsic index, formed as the extrinsic index within a block, together with that +/// block's height. This allows a transaction in which a multisig operation of a particular +/// composite was created to be uniquely identified. +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)] +pub struct Timepoint { + /// The hieght of the chain at the point in time. + height: BlockNumber, + /// The index of the extrinsic at the point in time. + index: u32, +} + +/// An open multisig operation. +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default, RuntimeDebug)] +pub struct Multisig { + /// The extrinsic when the multisig operation was opened. + when: Timepoint, + /// The amount held in reserve of the `depositor`, to be returned once the operation ends. + deposit: Balance, + /// The account who opened it (i.e. the first to approve it). + depositor: AccountId, + /// The approvals achieved so far, including the depositor. Always sorted. + approvals: Vec, +} + +decl_storage! { + trait Store for Module as Utility { + /// The set of open multisig operations. + pub Multisigs: double_map + hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) [u8; 32] + => Option, T::AccountId>>; + } +} + +decl_error! { + pub enum Error for Module { + /// Threshold is too low (zero). + ZeroThreshold, + /// Call is already approved by this signatory. + AlreadyApproved, + /// Call doesn't need any (more) approvals. + NoApprovalsNeeded, + /// There are too few signatories in the list. + TooFewSignatories, + /// There are too many signatories in the list. + TooManySignatories, + /// The signatories were provided out of order; they should be ordered. + SignatoriesOutOfOrder, + /// The sender was contained in the other signatories; it shouldn't be. + SenderInSignatories, + /// Multisig operation not found when attempting to cancel. + NotFound, + /// Only the account that originally created the multisig is able to cancel it. + NotOwner, + /// No timepoint was given, yet the multisig operation is already underway. + NoTimepoint, + /// A different timepoint was given to the multisig operation that is underway. + WrongTimepoint, + /// A timepoint was given, yet no multisig operation is underway. + UnexpectedTimepoint, + } +} + +decl_event! { + /// Events type. + pub enum Event where + AccountId = ::AccountId, + BlockNumber = ::BlockNumber + { + /// Batch of dispatches did not complete fully. Index of first failing dispatch given, as + /// well as the error. + BatchInterrupted(u32, DispatchError), + /// Batch of dispatches completed fully with no error. + BatchCompleted, + /// A new multisig operation has begun. First param is the account that is approving, + /// second is the multisig account. + NewMultisig(AccountId, AccountId), + /// A multisig operation has been approved by someone. First param is the account that is + /// approving, third is the multisig account. + MultisigApproval(AccountId, Timepoint, AccountId), + /// A multisig operation has been executed. First param is the account that is + /// approving, third is the multisig account. + MultisigExecuted(AccountId, Timepoint, AccountId, DispatchResult), + /// A multisig operation has been cancelled. First param is the account that is + /// cancelling, third is the multisig account. + MultisigCancelled(AccountId, Timepoint, AccountId), + } +} + +/// Simple index-based pass through for the weight functions. +struct Passthrough(sp_std::marker::PhantomData); + +impl Passthrough { + fn new() -> Self { Self(Default::default()) } +} +impl WeighData<(&u16, &Box)> for Passthrough { + fn weigh_data(&self, (_, call): (&u16, &Box)) -> Weight { + call.get_dispatch_info().weight + 10_000 + } +} +impl ClassifyDispatch<(&u16, &Box)> for Passthrough { + fn classify_dispatch(&self, (_, call): (&u16, &Box)) -> DispatchClass { + call.get_dispatch_info().class + } +} +impl PaysFee<(&u16, &Box)> for Passthrough { + fn pays_fee(&self, (_, call): (&u16, &Box)) -> bool { + call.get_dispatch_info().pays_fee + } +} + +/// Sumation pass-through for the weight function of the batch call. +/// +/// This just adds all of the weights together of all of the calls. +struct BatchPassthrough(sp_std::marker::PhantomData); + +impl BatchPassthrough { + fn new() -> Self { Self(Default::default()) } +} +impl WeighData<(&Vec,)> for BatchPassthrough { + fn weigh_data(&self, (calls,): (&Vec,)) -> Weight { + calls.iter() + .map(|call| call.get_dispatch_info().weight) + .fold(10_000, |a, n| a + n) + } +} +impl ClassifyDispatch<(&Vec,)> for BatchPassthrough { + fn classify_dispatch(&self, (calls,): (&Vec,)) -> DispatchClass { + let all_operational = calls.iter() + .map(|call| call.get_dispatch_info().class) + .all(|class| class == DispatchClass::Operational); + if all_operational { + DispatchClass::Operational + } else { + DispatchClass::Normal + } + } +} +impl PaysFee<(&Vec,)> for BatchPassthrough { + fn pays_fee(&self, (calls,): (&Vec,)) -> bool { + calls.iter() + .any(|call| call.get_dispatch_info().pays_fee) + } +} + +/// Simple index-based pass through for the weight functions. +struct MultiPassthrough( + sp_std::marker::PhantomData<(Call, AccountId, Timepoint)> +); + +impl MultiPassthrough { + fn new() -> Self { Self(Default::default()) } +} +impl WeighData<(&u16, &Vec, &Timepoint, &Box)> +for MultiPassthrough +{ + fn weigh_data(&self, (_, sigs, _, call): (&u16, &Vec, &Timepoint, &Box)) -> Weight { + call.get_dispatch_info().weight + 10_000 * (sigs.len() as u32 + 1) + } +} +impl ClassifyDispatch<(&u16, &Vec, &Timepoint, &Box)> +for MultiPassthrough +{ + fn classify_dispatch(&self, (_, _, _, call): (&u16, &Vec, &Timepoint, &Box)) + -> DispatchClass + { + call.get_dispatch_info().class + } +} +impl PaysFee<(&u16, &Vec, &Timepoint, &Box)> +for MultiPassthrough +{ + fn pays_fee(&self, _: (&u16, &Vec, &Timepoint, &Box)) -> bool { + true + } +} + +/// Simple index-based pass through for the weight functions. +struct SigsLen( + sp_std::marker::PhantomData<(AccountId, Timepoint)> +); + +impl SigsLen { + fn new() -> Self { Self(Default::default()) } +} +impl WeighData<(&u16, &Vec, &Timepoint, &[u8; 32])> +for SigsLen +{ + fn weigh_data(&self, (_, sigs, _, _): (&u16, &Vec, &Timepoint, &[u8; 32])) -> Weight { + 10_000 * (sigs.len() as u32 + 1) + } +} +impl ClassifyDispatch<(&u16, &Vec, &Timepoint, &[u8; 32])> +for SigsLen +{ + fn classify_dispatch(&self, _: (&u16, &Vec, &Timepoint, &[u8; 32])) + -> DispatchClass + { + DispatchClass::Normal + } +} +impl PaysFee<(&u16, &Vec, &Timepoint, &[u8; 32])> +for SigsLen +{ + fn pays_fee(&self, _: (&u16, &Vec, &Timepoint, &[u8; 32])) -> bool { + true + } +} + +/// A module identifier. These are per module and should be stored in a registry somewhere. +#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)] +struct IndexedUtilityModuleId(u16); + +impl TypeId for IndexedUtilityModuleId { + const TYPE_ID: [u8; 4] = *b"suba"; +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Deposit one of this module's events by using the default implementation. + fn deposit_event() = default; + + /// Send a batch of dispatch calls. + /// + /// This will execute until the first one fails and then stop. + /// + /// May be called from any origin. + /// + /// - `calls`: The calls to be dispatched from the same origin. + /// + /// # + /// - The sum of the weights of the `calls`. + /// - One event. + /// # + /// + /// This will return `Ok` in all circumstances. To determine the success of the batch, an + /// event is deposited. If a call failed and the batch was interrupted, then the + /// `BatchInterrupted` event is deposited, along with the number of successful calls made + /// and the error of the failed call. If all were successful, then the `BatchCompleted` + /// event is deposited. + #[weight = ::Call>>::new()] + fn batch(origin, calls: Vec<::Call>) { + for (index, call) in calls.into_iter().enumerate() { + let result = call.dispatch(origin.clone()); + if let Err(e) = result { + Self::deposit_event(Event::::BatchInterrupted(index as u32, e)); + return Ok(()); + } + } + Self::deposit_event(Event::::BatchCompleted); + } + + /// Send a call through an indexed pseudonym of the sender. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - The weight of the `call`. + /// # + #[weight = ::Call>>::new()] + fn as_sub(origin, index: u16, call: Box<::Call>) -> DispatchResult { + let who = ensure_signed(origin)?; + let pseudonym = Self::sub_account_id(who, index); + call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into()) + } + + /// Register approval for a dispatch to be made from a deterministic composite account if + /// approved by a total of `threshold - 1` of `other_signatories`. + /// + /// If there are enough, then dispatch the call. + /// + /// Payment: `MultisigDepositBase` will be reserved if this is the first approval, plus + /// `threshold` times `MultisigDepositFactor`. It is returned once this dispatch happens or + /// is cancelled. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `threshold`: The total number of approvals for this dispatch before it is executed. + /// - `other_signatories`: The accounts (other than the sender) who can approve this + /// dispatch. May not be empty. + /// - `maybe_timepoint`: If this is the first approval, then this must be `None`. If it is + /// not the first approval, then it must be `Some`, with the timepoint (block number and + /// transaction index) of the first approval transaction. + /// - `call`: The call to be executed. + /// + /// NOTE: Unless this is the final approval, you will generally want to use + /// `approve_as_multi` instead, since it only requires a hash of the call. + /// + /// Result is equivalent to the dispatched result if `threshold` is exactly `1`. Otherwise + /// on success, result is `Ok` and the result from the interior call, if it was executed, + /// may be found in the deposited `MultisigExecuted` event. + /// + /// # + /// - `O(S + Z + Call)`. + /// - Up to one balance-reserve or unreserve operation. + /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of + /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. + /// - One call encode & hash, both of complexity `O(Z)` where `Z` is tx-len. + /// - One encode & hash, both of complexity `O(S)`. + /// - Up to one binary search and insert (`O(logS + S)`). + /// - I/O: 1 read `O(S)`, up to 1 mutate `O(S)`. Up to one remove. + /// - One event. + /// - The weight of the `call`. + /// - Storage: inserts one item, value size bounded by `MaxSignatories`, with a + /// deposit taken for its lifetime of + /// `MultisigDepositBase + threshold * MultisigDepositFactor`. + /// # + #[weight = ::Call, T::AccountId, Option>>>::new()] + fn as_multi(origin, + threshold: u16, + other_signatories: Vec, + maybe_timepoint: Option>, + call: Box<::Call>, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + ensure!(threshold >= 1, Error::::ZeroThreshold); + let max_sigs = T::MaxSignatories::get() as usize; + ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); + ensure!(other_signatories.len() < max_sigs, Error::::TooManySignatories); + let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; + + let id = Self::multi_account_id(&signatories, threshold); + let call_hash = call.using_encoded(blake2_256); + + if let Some(mut m) = >::get(&id, call_hash) { + let timepoint = maybe_timepoint.ok_or(Error::::NoTimepoint)?; + ensure!(m.when == timepoint, Error::::WrongTimepoint); + if let Err(pos) = m.approvals.binary_search(&who) { + // we know threshold is greater than zero from the above ensure. + if (m.approvals.len() as u16) < threshold - 1 { + m.approvals.insert(pos, who.clone()); + >::insert(&id, call_hash, m); + Self::deposit_event(RawEvent::MultisigApproval(who, timepoint, id)); + return Ok(()) + } + } else { + if (m.approvals.len() as u16) < threshold { + Err(Error::::AlreadyApproved)? + } + } + + let result = call.dispatch(frame_system::RawOrigin::Signed(id.clone()).into()); + let _ = T::Currency::unreserve(&m.depositor, m.deposit); + >::remove(&id, call_hash); + Self::deposit_event(RawEvent::MultisigExecuted(who, timepoint, id, result)); + } else { + ensure!(maybe_timepoint.is_none(), Error::::UnexpectedTimepoint); + if threshold > 1 { + let deposit = T::MultisigDepositBase::get() + + T::MultisigDepositFactor::get() * threshold.into(); + T::Currency::reserve(&who, deposit)?; + >::insert(&id, call_hash, Multisig { + when: Self::timepoint(), + deposit, + depositor: who.clone(), + approvals: vec![who.clone()], + }); + Self::deposit_event(RawEvent::NewMultisig(who, id)); + } else { + return call.dispatch(frame_system::RawOrigin::Signed(id).into()) + } + } + Ok(()) + } + + /// Register approval for a dispatch to be made from a deterministic composite account if + /// approved by a total of `threshold - 1` of `other_signatories`. + /// + /// Payment: `MultisigDepositBase` will be reserved if this is the first approval, plus + /// `threshold` times `MultisigDepositFactor`. It is returned once this dispatch happens or + /// is cancelled. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `threshold`: The total number of approvals for this dispatch before it is executed. + /// - `other_signatories`: The accounts (other than the sender) who can approve this + /// dispatch. May not be empty. + /// - `maybe_timepoint`: If this is the first approval, then this must be `None`. If it is + /// not the first approval, then it must be `Some`, with the timepoint (block number and + /// transaction index) of the first approval transaction. + /// - `call_hash`: The hash of the call to be executed. + /// + /// NOTE: If this is the final approval, you will want to use `as_multi` instead. + /// + /// # + /// - `O(S)`. + /// - Up to one balance-reserve or unreserve operation. + /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of + /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. + /// - One encode & hash, both of complexity `O(S)`. + /// - Up to one binary search and insert (`O(logS + S)`). + /// - I/O: 1 read `O(S)`, up to 1 mutate `O(S)`. Up to one remove. + /// - One event. + /// - Storage: inserts one item, value size bounded by `MaxSignatories`, with a + /// deposit taken for its lifetime of + /// `MultisigDepositBase + threshold * MultisigDepositFactor`. + /// # + #[weight = >>>::new()] + fn approve_as_multi(origin, + threshold: u16, + other_signatories: Vec, + maybe_timepoint: Option>, + call_hash: [u8; 32], + ) -> DispatchResult { + let who = ensure_signed(origin)?; + ensure!(threshold >= 1, Error::::ZeroThreshold); + let max_sigs = T::MaxSignatories::get() as usize; + ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); + ensure!(other_signatories.len() < max_sigs, Error::::TooManySignatories); + let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; + + let id = Self::multi_account_id(&signatories, threshold); + + if let Some(mut m) = >::get(&id, call_hash) { + let timepoint = maybe_timepoint.ok_or(Error::::NoTimepoint)?; + ensure!(m.when == timepoint, Error::::WrongTimepoint); + ensure!(m.approvals.len() < threshold as usize, Error::::NoApprovalsNeeded); + if let Err(pos) = m.approvals.binary_search(&who) { + m.approvals.insert(pos, who.clone()); + >::insert(&id, call_hash, m); + Self::deposit_event(RawEvent::MultisigApproval(who, timepoint, id)); + } else { + Err(Error::::AlreadyApproved)? + } + } else { + if threshold > 1 { + ensure!(maybe_timepoint.is_none(), Error::::UnexpectedTimepoint); + let deposit = T::MultisigDepositBase::get() + + T::MultisigDepositFactor::get() * threshold.into(); + T::Currency::reserve(&who, deposit)?; + >::insert(&id, call_hash, Multisig { + when: Self::timepoint(), + deposit, + depositor: who.clone(), + approvals: vec![who.clone()], + }); + Self::deposit_event(RawEvent::NewMultisig(who, id)); + } else { + Err(Error::::NoApprovalsNeeded)? + } + } + Ok(()) + } + + /// Cancel a pre-existing, on-going multisig transaction. Any deposit reserved previously + /// for this operation will be unreserved on success. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `threshold`: The total number of approvals for this dispatch before it is executed. + /// - `other_signatories`: The accounts (other than the sender) who can approve this + /// dispatch. May not be empty. + /// - `timepoint`: The timepoint (block number and transaction index) of the first approval + /// transaction for this dispatch. + /// - `call_hash`: The hash of the call to be executed. + /// + /// # + /// - `O(S)`. + /// - Up to one balance-reserve or unreserve operation. + /// - One passthrough operation, one insert, both `O(S)` where `S` is the number of + /// signatories. `S` is capped by `MaxSignatories`, with weight being proportional. + /// - One encode & hash, both of complexity `O(S)`. + /// - One event. + /// - I/O: 1 read `O(S)`, one remove. + /// - Storage: removes one item. + /// # + #[weight = >>::new()] + fn cancel_as_multi(origin, + threshold: u16, + other_signatories: Vec, + timepoint: Timepoint, + call_hash: [u8; 32], + ) -> DispatchResult { + let who = ensure_signed(origin)?; + ensure!(threshold >= 1, Error::::ZeroThreshold); + let max_sigs = T::MaxSignatories::get() as usize; + ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); + ensure!(other_signatories.len() < max_sigs, Error::::TooManySignatories); + let signatories = Self::ensure_sorted_and_insert(other_signatories, who.clone())?; + + let id = Self::multi_account_id(&signatories, threshold); + + let m = >::get(&id, call_hash) + .ok_or(Error::::NotFound)?; + ensure!(m.when == timepoint, Error::::WrongTimepoint); + ensure!(m.depositor == who, Error::::NotOwner); + + let _ = T::Currency::unreserve(&m.depositor, m.deposit); + >::remove(&id, call_hash); + + Self::deposit_event(RawEvent::MultisigCancelled(who, timepoint, id)); + Ok(()) + } + } +} + +impl Module { + /// Derive a sub-account ID from the owner account and the sub-account index. + pub fn sub_account_id(who: T::AccountId, index: u16) -> T::AccountId { + let entropy = (b"modlpy/utilisuba", who, index).using_encoded(blake2_256); + T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() + } + + /// Derive a multi-account ID from the sorted list of accounts and the threshold that are + /// required. + /// + /// NOTE: `who` must be sorted. If it is not, then you'll get the wrong answer. + pub fn multi_account_id(who: &[T::AccountId], threshold: u16) -> T::AccountId { + let entropy = (b"modlpy/utilisuba", who, threshold).using_encoded(blake2_256); + T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() + } + + /// The current `Timepoint`. + pub fn timepoint() -> Timepoint { + Timepoint { + height: >::block_number(), + index: >::extrinsic_count(), + } + } + + /// Check that signatories is sorted and doesn't contain sender, then insert sender. + fn ensure_sorted_and_insert(other_signatories: Vec, who: T::AccountId) + -> Result, DispatchError> + { + let mut signatories = other_signatories; + let mut maybe_last = None; + let mut index = 0; + for item in signatories.iter() { + if let Some(last) = maybe_last { + ensure!(last < item, Error::::SignatoriesOutOfOrder); + } + if item <= &who { + ensure!(item != &who, Error::::SenderInSignatories); + index += 1; + } + maybe_last = Some(item); + } + signatories.insert(index, who); + Ok(signatories) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use frame_support::{ + assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch, + weights::Weight, impl_outer_event + }; + use sp_core::H256; + use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + use crate as utility; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + impl_outer_event! { + pub enum TestEvent for Test { + pallet_balances, + utility, + } + } + impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + pallet_balances::Balances, + utility::Utility, + } + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = Call; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = TestEvent; + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + parameter_types! { + pub const MultisigDepositBase: u64 = 1; + pub const MultisigDepositFactor: u64 = 1; + pub const MaxSignatories: u16 = 3; + } + impl Trait for Test { + type Event = TestEvent; + type Call = Call; + type Currency = Balances; + type MultisigDepositBase = MultisigDepositBase; + type MultisigDepositFactor = MultisigDepositFactor; + type MaxSignatories = MaxSignatories; + } + type System = frame_system::Module; + type Balances = pallet_balances::Module; + type Utility = Module; + + use pallet_balances::Call as BalancesCall; + use pallet_balances::Error as BalancesError; + + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(1, 10), (2, 10), (3, 10), (4, 10), (5, 10)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + fn last_event() -> TestEvent { + system::Module::::events().pop().map(|e| e.event).expect("Event expected") + } + + fn expect_event>(e: E) { + assert_eq!(last_event(), e.into()); + } + + fn now() -> Timepoint { + Utility::timepoint() + } + + #[test] + fn multisig_deposit_is_taken_and_returned() { + new_test_ext().execute_with(|| { + let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call.clone())); + assert_eq!(Balances::free_balance(1), 2); + assert_eq!(Balances::reserved_balance(1), 3); + + assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), call)); + assert_eq!(Balances::free_balance(1), 5); + assert_eq!(Balances::reserved_balance(1), 0); + }); + } + + #[test] + fn cancel_multisig_returns_deposit() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + let hash = call.using_encoded(blake2_256); + assert_ok!(Utility::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone())); + assert_ok!(Utility::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone())); + assert_eq!(Balances::free_balance(1), 6); + assert_eq!(Balances::reserved_balance(1), 4); + assert_ok!( + Utility::cancel_as_multi(Origin::signed(1), 3, vec![2, 3], now(), hash.clone()), + ); + assert_eq!(Balances::free_balance(1), 10); + assert_eq!(Balances::reserved_balance(1), 0); + }); + } + + #[test] + fn timepoint_checking_works() { + new_test_ext().execute_with(|| { + let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + let hash = call.using_encoded(blake2_256); + + assert_noop!( + Utility::approve_as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), hash.clone()), + Error::::UnexpectedTimepoint, + ); + + assert_ok!(Utility::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash)); + + assert_noop!( + Utility::as_multi(Origin::signed(2), 2, vec![1, 3], None, call.clone()), + Error::::NoTimepoint, + ); + let later = Timepoint { index: 1, .. now() }; + assert_noop!( + Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(later), call.clone()), + Error::::WrongTimepoint, + ); + }); + } + + #[test] + fn multisig_2_of_3_works() { + new_test_ext().execute_with(|| { + let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + let hash = call.using_encoded(blake2_256); + assert_ok!(Utility::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash)); + assert_eq!(Balances::free_balance(6), 0); + + assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), call)); + assert_eq!(Balances::free_balance(6), 15); + }); + } + + #[test] + fn multisig_3_of_3_works() { + new_test_ext().execute_with(|| { + let multi = Utility::multi_account_id(&[1, 2, 3][..], 3); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + let hash = call.using_encoded(blake2_256); + assert_ok!(Utility::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone())); + assert_ok!(Utility::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone())); + assert_eq!(Balances::free_balance(6), 0); + + assert_ok!(Utility::as_multi(Origin::signed(3), 3, vec![1, 2], Some(now()), call)); + assert_eq!(Balances::free_balance(6), 15); + }); + } + + #[test] + fn cancel_multisig_works() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + let hash = call.using_encoded(blake2_256); + assert_ok!(Utility::approve_as_multi(Origin::signed(1), 3, vec![2, 3], None, hash.clone())); + assert_ok!(Utility::approve_as_multi(Origin::signed(2), 3, vec![1, 3], Some(now()), hash.clone())); + assert_noop!( + Utility::cancel_as_multi(Origin::signed(2), 3, vec![1, 3], now(), hash.clone()), + Error::::NotOwner, + ); + assert_ok!( + Utility::cancel_as_multi(Origin::signed(1), 3, vec![2, 3], now(), hash.clone()), + ); + }); + } + + #[test] + fn multisig_2_of_3_as_multi_works() { + new_test_ext().execute_with(|| { + let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call.clone())); + assert_eq!(Balances::free_balance(6), 0); + + assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), call)); + assert_eq!(Balances::free_balance(6), 15); + }); + } + + #[test] + fn multisig_2_of_3_as_multi_with_many_calls_works() { + new_test_ext().execute_with(|| { + let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call1 = Box::new(Call::Balances(BalancesCall::transfer(6, 10))); + let call2 = Box::new(Call::Balances(BalancesCall::transfer(7, 5))); + + assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call1.clone())); + assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], None, call2.clone())); + assert_ok!(Utility::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), call2)); + assert_ok!(Utility::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), call1)); + + assert_eq!(Balances::free_balance(6), 10); + assert_eq!(Balances::free_balance(7), 5); + }); + } + + #[test] + fn multisig_2_of_3_cannot_reissue_same_call() { + new_test_ext().execute_with(|| { + let multi = Utility::multi_account_id(&[1, 2, 3][..], 2); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 10))); + assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call.clone())); + assert_ok!(Utility::as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), call.clone())); + assert_eq!(Balances::free_balance(multi), 5); + + assert_ok!(Utility::as_multi(Origin::signed(1), 2, vec![2, 3], None, call.clone())); + assert_ok!(Utility::as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), call)); + + let err = DispatchError::from(BalancesError::::InsufficientBalance).stripped(); + expect_event(RawEvent::MultisigExecuted(3, now(), multi, Err(err))); + }); + } + + #[test] + fn zero_threshold_fails() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + assert_noop!( + Utility::as_multi(Origin::signed(1), 0, vec![2], None, call), + Error::::ZeroThreshold, + ); + }); + } + + #[test] + fn too_many_signatories_fails() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + assert_noop!( + Utility::as_multi(Origin::signed(1), 2, vec![2, 3, 4], None, call.clone()), + Error::::TooManySignatories, + ); + }); + } + + #[test] + fn duplicate_approvals_are_ignored() { + new_test_ext().execute_with(|| { + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + let hash = call.using_encoded(blake2_256); + assert_ok!(Utility::approve_as_multi(Origin::signed(1), 2, vec![2, 3], None, hash.clone())); + assert_noop!( + Utility::approve_as_multi(Origin::signed(1), 2, vec![2, 3], Some(now()), hash.clone()), + Error::::AlreadyApproved, + ); + assert_ok!(Utility::approve_as_multi(Origin::signed(2), 2, vec![1, 3], Some(now()), hash.clone())); + assert_noop!( + Utility::approve_as_multi(Origin::signed(3), 2, vec![1, 2], Some(now()), hash.clone()), + Error::::NoApprovalsNeeded, + ); + }); + } + + #[test] + fn multisig_1_of_3_works() { + new_test_ext().execute_with(|| { + let multi = Utility::multi_account_id(&[1, 2, 3][..], 1); + assert_ok!(Balances::transfer(Origin::signed(1), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(2), multi, 5)); + assert_ok!(Balances::transfer(Origin::signed(3), multi, 5)); + + let call = Box::new(Call::Balances(BalancesCall::transfer(6, 15))); + let hash = call.using_encoded(blake2_256); + assert_noop!( + Utility::approve_as_multi(Origin::signed(1), 1, vec![2, 3], None, hash.clone()), + Error::::NoApprovalsNeeded, + ); + assert_noop!( + Utility::as_multi(Origin::signed(4), 1, vec![2, 3], None, call.clone()), + BalancesError::::InsufficientBalance, + ); + assert_ok!(Utility::as_multi(Origin::signed(1), 1, vec![2, 3], None, call)); + + assert_eq!(Balances::free_balance(6), 15); + }); + } + + #[test] + fn as_sub_works() { + new_test_ext().execute_with(|| { + let sub_1_0 = Utility::sub_account_id(1, 0); + assert_ok!(Balances::transfer(Origin::signed(1), sub_1_0, 5)); + assert_noop!(Utility::as_sub( + Origin::signed(1), + 1, + Box::new(Call::Balances(BalancesCall::transfer(6, 3))), + ), BalancesError::::InsufficientBalance); + assert_ok!(Utility::as_sub( + Origin::signed(1), + 0, + Box::new(Call::Balances(BalancesCall::transfer(2, 3))), + )); + assert_eq!(Balances::free_balance(sub_1_0), 2); + assert_eq!(Balances::free_balance(2), 13); + }); + } + + #[test] + fn batch_with_root_works() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::free_balance(1), 10); + assert_eq!(Balances::free_balance(2), 10); + assert_ok!(Utility::batch(Origin::ROOT, vec![ + Call::Balances(BalancesCall::force_transfer(1, 2, 5)), + Call::Balances(BalancesCall::force_transfer(1, 2, 5)) + ])); + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::free_balance(2), 20); + }); + } + + #[test] + fn batch_with_signed_works() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::free_balance(1), 10); + assert_eq!(Balances::free_balance(2), 10); + assert_ok!( + Utility::batch(Origin::signed(1), vec![ + Call::Balances(BalancesCall::transfer(2, 5)), + Call::Balances(BalancesCall::transfer(2, 5)) + ]), + ); + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::free_balance(2), 20); + }); + } + + #[test] + fn batch_early_exit_works() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::free_balance(1), 10); + assert_eq!(Balances::free_balance(2), 10); + assert_ok!( + Utility::batch(Origin::signed(1), vec![ + Call::Balances(BalancesCall::transfer(2, 5)), + Call::Balances(BalancesCall::transfer(2, 10)), + Call::Balances(BalancesCall::transfer(2, 5)), + ]), + ); + assert_eq!(Balances::free_balance(1), 5); + assert_eq!(Balances::free_balance(2), 15); + }); + } +} diff --git a/node-template/Cargo.toml b/node-template/Cargo.toml deleted file mode 100644 index f0538e1518b57..0000000000000 --- a/node-template/Cargo.toml +++ /dev/null @@ -1,41 +0,0 @@ -[package] -name = "node-template" -version = "2.0.0" -authors = ["Anonymous"] -build = "build.rs" -edition = "2018" - -[[bin]] -name = "node-template" -path = "src/main.rs" - -[dependencies] -derive_more = "0.15.0" -futures = "0.1.29" -futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } -ctrlc = { version = "3.1.3", features = ["termination"] } -log = "0.4.8" -tokio = "0.1.22" -exit-future = "0.1.4" -parking_lot = "0.9.0" -codec = { package = "parity-scale-codec", version = "1.0.0" } -trie-root = "0.15.2" -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" } -aura = { package = "substrate-consensus-aura", path = "../core/consensus/aura" } -aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../core/consensus/aura/primitives" } -grandpa = { package = "substrate-finality-grandpa", path = "../core/finality-grandpa" } -grandpa-primitives = { package = "substrate-finality-grandpa-primitives", path = "../core/finality-grandpa/primitives" } -substrate-client = { path = "../core/client" } -basic-authorship = { package = "substrate-basic-authorship", path = "../core/basic-authorship" } -runtime = { package = "node-template-runtime", path = "runtime" } -sr-primitives = { path = "../core/sr-primitives" } - -[build-dependencies] -vergen = "3.0.4" diff --git a/node-template/build.rs b/node-template/build.rs deleted file mode 100644 index bab46f579d068..0000000000000 --- a/node-template/build.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::{env, path::PathBuf}; - -use vergen::{ConstantsFlags, generate_cargo_keys}; - -const ERROR_MSG: &str = "Failed to generate metadata files"; - -fn main() { - generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG); - - let mut manifest_dir = PathBuf::from( - env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo.") - ); - - while manifest_dir.parent().is_some() { - if manifest_dir.join(".git/HEAD").exists() { - println!("cargo:rerun-if-changed={}", manifest_dir.join(".git/HEAD").display()); - return - } - - manifest_dir.pop(); - } - - println!("cargo:warning=Could not find `.git/HEAD` from manifest dir!"); -} diff --git a/node-template/runtime/Cargo.toml b/node-template/runtime/Cargo.toml deleted file mode 100644 index ff2e3eb2b1676..0000000000000 --- a/node-template/runtime/Cargo.toml +++ /dev/null @@ -1,61 +0,0 @@ -[package] -name = "node-template-runtime" -version = "2.0.0" -authors = ["Anonymous"] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true, features = ["derive"] } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default_features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default_features = false } -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 } -substrate-session = { path = "../../core/session", default-features = false } -balances = { package = "srml-balances", path = "../../srml/balances", default_features = false } -aura = { package = "srml-aura", path = "../../srml/aura", default_features = false } -aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default_features = false } -grandpa = { package = "srml-grandpa", path = "../../srml/grandpa", default_features = false } -executive = { package = "srml-executive", path = "../../srml/executive", default_features = false } -indices = { package = "srml-indices", path = "../../srml/indices", default_features = false } -randomness-collective-flip = { package = "srml-randomness-collective-flip", path = "../../srml/randomness-collective-flip", default_features = false } -system = { package = "srml-system", path = "../../srml/system", default_features = false } -timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default_features = false } -sudo = { package = "srml-sudo", path = "../../srml/sudo", default_features = false } -transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment", default_features = false } -sr-primitives = { path = "../../core/sr-primitives", default_features = false } -client = { package = "substrate-client", path = "../../core/client", default_features = false } -offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false } - -[build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.4" } - -[features] -default = ["std"] -std = [ - "codec/std", - "client/std", - "rstd/std", - "runtime-io/std", - "support/std", - "balances/std", - "aura/std", - "aura-primitives/std", - "grandpa/std", - "executive/std", - "indices/std", - "primitives/std", - "sr-primitives/std", - "randomness-collective-flip/std", - "system/std", - "timestamp/std", - "sudo/std", - "transaction-payment/std", - "version/std", - "serde", - "safe-mix/std", - "offchain-primitives/std", - "substrate-session/std", -] diff --git a/node-template/runtime/build.rs b/node-template/runtime/build.rs deleted file mode 100644 index c5e798c6efa90..0000000000000 --- a/node-template/runtime/build.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; - -fn main() { - build_current_project_with_rustflags( - "wasm_binary.rs", - WasmBuilderSource::Crates("1.0.8"), - // This instructs LLD to export __heap_base as a global variable, which is used by the - // external memory allocator. - "-Clink-arg=--export=__heap_base", - ); -} diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs deleted file mode 100644 index b803e184174b2..0000000000000 --- a/node-template/runtime/src/lib.rs +++ /dev/null @@ -1,364 +0,0 @@ -//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm. - -#![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit="256"] - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -use rstd::prelude::*; -use primitives::{OpaqueMetadata, crypto::key_types}; -use sr_primitives::{ - ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str, - impl_opaque_keys, MultiSignature -}; -use sr_primitives::traits::{ - NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify, ConvertInto, IdentifyAccount -}; -use sr_primitives::weights::Weight; -use client::{ - block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api}, - runtime_api as client_api, impl_runtime_apis -}; -use aura_primitives::sr25519::AuthorityId as AuraId; -use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight}; -use grandpa::fg_primitives; -use version::RuntimeVersion; -#[cfg(feature = "std")] -use version::NativeVersion; - -// A few exports that help ease life for downstream crates. -#[cfg(any(feature = "std", test))] -pub use sr_primitives::BuildStorage; -pub use timestamp::Call as TimestampCall; -pub use balances::Call as BalancesCall; -pub use sr_primitives::{Permill, Perbill}; -pub use support::{StorageValue, construct_runtime, parameter_types, traits::Randomness}; - -/// An index to a block. -pub type BlockNumber = u32; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -/// The type for looking up accounts. We don't expect more than 4 billion of them, but you -/// never know... -pub type AccountIndex = u32; - -/// Balance of an account. -pub type Balance = u128; - -/// Index of a transaction in the chain. -pub type Index = u32; - -/// A hash of some data used by the chain. -pub type Hash = primitives::H256; - -/// Digest item type. -pub type DigestItem = generic::DigestItem; - -/// 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::*; - - pub use sr_primitives::OpaqueExtrinsic as UncheckedExtrinsic; - - /// 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; - - impl_opaque_keys! { - pub struct SessionKeys { - #[id(key_types::AURA)] - pub aura: AuraId, - #[id(key_types::GRANDPA)] - pub grandpa: GrandpaId, - } - } -} - -/// This runtime version. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("node-template"), - impl_name: create_runtime_str!("node-template"), - authoring_version: 1, - spec_version: 1, - impl_version: 1, - apis: RUNTIME_API_VERSIONS, -}; - -pub const MILLISECS_PER_BLOCK: u64 = 6000; - -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -// These time units are defined in number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; - -/// The version infromation used to identify this runtime when compiled natively. -#[cfg(feature = "std")] -pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } -} - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 1_000_000; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); - pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; - pub const Version: RuntimeVersion = VERSION; -} - -impl system::Trait for Runtime { - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type Call = Call; - /// 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 = Index; - /// The index type for blocks. - type BlockNumber = BlockNumber; - /// The type for hashing blocks and tries. - type Hash = Hash; - /// The hashing algorithm used. - type Hashing = BlakeTwo256; - /// The header type. - type Header = generic::Header; - /// The ubiquitous event type. - type Event = Event; - /// The ubiquitous origin type. - type Origin = Origin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Maximum weight of each block. - type MaximumBlockWeight = MaximumBlockWeight; - /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. - type MaximumBlockLength = MaximumBlockLength; - /// Portion of the block weight that is available to all normal transactions. - type AvailableBlockRatio = AvailableBlockRatio; - /// Version of the runtime. - type Version = Version; -} - -impl aura::Trait for Runtime { - type AuthorityId = AuraId; -} - -impl grandpa::Trait for Runtime { - type Event = Event; -} - -impl indices::Trait for Runtime { - /// The type for recording indexing into the account enumeration. If this ever overflows, there - /// will be problems! - type AccountIndex = AccountIndex; - /// 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 ubiquitous event type. - type Event = Event; -} - -parameter_types! { - pub const MinimumPeriod: u64 = SLOT_DURATION / 2; -} - -impl timestamp::Trait for Runtime { - /// A timestamp: milliseconds since the unix epoch. - type Moment = u64; - type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; -} - -parameter_types! { - pub const ExistentialDeposit: u128 = 500; - pub const TransferFee: u128 = 0; - pub const CreationFee: u128 = 0; -} - -impl balances::Trait for Runtime { - /// The type for recording an account's balance. - type Balance = Balance; - /// 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 ubiquitous event type. - type Event = Event; - type DustRemoval = (); - type TransferPayment = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} - -parameter_types! { - pub const TransactionBaseFee: Balance = 0; - pub const TransactionByteFee: Balance = 1; -} - -impl transaction_payment::Trait for Runtime { - type Currency = balances::Module; - type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; - type FeeMultiplierUpdate = (); -} - -impl sudo::Trait for Runtime { - 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 where - Block = Block, - NodeBlock = opaque::Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Module, Call, Storage, Config, Event}, - Timestamp: timestamp::{Module, Call, Storage, Inherent}, - Aura: aura::{Module, Config, Inherent(Timestamp)}, - Grandpa: grandpa::{Module, Call, Storage, Config, Event}, - Indices: indices::{default, Config}, - Balances: balances::{default, Error}, - TransactionPayment: transaction_payment::{Module, Storage}, - Sudo: sudo, - // Used for the module template in `./template.rs` - TemplateModule: template::{Module, Call, Storage, Event}, - RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage}, - } -); - -/// The address format for describing accounts. -pub type Address = ::Source; -/// Block header type as expected by this runtime. -pub type Header = generic::Header; -/// Block type as expected by this runtime. -pub type Block = generic::Block; -/// A Block signed with a Justification -pub type SignedBlock = generic::SignedBlock; -/// BlockId type as expected by this runtime. -pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( - system::CheckVersion, - system::CheckGenesis, - system::CheckEra, - system::CheckNonce, - system::CheckWeight, - transaction_payment::ChargeTransactionPayment -); -/// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; -/// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; -/// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive, Runtime, AllModules>; - -impl_runtime_apis! { - impl client_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block) - } - - fn initialize_block(header: &::Header) { - Executive::initialize_block(header) - } - } - - impl client_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 finalize_block() -> ::Header { - Executive::finalize_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 { - RandomnessCollectiveFlip::random_seed() - } - } - - impl client_api::TaggedTransactionQueue for Runtime { - fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { - Executive::validate_transaction(tx) - } - } - - impl offchain_primitives::OffchainWorkerApi for Runtime { - fn offchain_worker(number: NumberFor) { - Executive::offchain_worker(number) - } - } - - impl aura_primitives::AuraApi for Runtime { - fn slot_duration() -> u64 { - Aura::slot_duration() - } - - fn authorities() -> Vec { - Aura::authorities() - } - } - - impl substrate_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string")); - opaque::SessionKeys::generate(seed) - } - } - - impl fg_primitives::GrandpaApi for Runtime { - fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> { - Grandpa::grandpa_authorities() - } - } -} diff --git a/node-template/src/chain_spec.rs b/node-template/src/chain_spec.rs deleted file mode 100644 index 8d43e67304c79..0000000000000 --- a/node-template/src/chain_spec.rs +++ /dev/null @@ -1,143 +0,0 @@ -use primitives::{Pair, Public, sr25519}; -use runtime::{ - AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, - SudoConfig, IndicesConfig, SystemConfig, WASM_BINARY, Signature -}; -use aura_primitives::sr25519::{AuthorityId as AuraId}; -use grandpa_primitives::{AuthorityId as GrandpaId}; -use substrate_service; -use sr_primitives::traits::{Verify, IdentifyAccount}; - -// Note this is the URL for the telemetry server -//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; - -/// Specialized `ChainSpec`. This is a specialization 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, -} - -/// Helper function to generate a crypto pair from seed -pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) - .expect("static values are valid; qed") - .public() -} - -type AccountPublic = ::Signer; - -/// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId where - AccountPublic: From<::Public> -{ - AccountPublic::from(get_from_seed::(seed)).into_account() -} - -/// Helper function to generate an authority key for Aura -pub fn get_authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { - ( - get_from_seed::(s), - get_from_seed::(s), - ) -} - -impl Alternative { - /// Get an actual chain config from one of the alternatives. - pub(crate) fn load(self) -> Result { - Ok(match self { - Alternative::Development => ChainSpec::from_genesis( - "Development", - "dev", - || testnet_genesis(vec![ - get_authority_keys_from_seed("Alice"), - ], - get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - ], - true), - vec![], - None, - None, - None, - None - ), - Alternative::LocalTestnet => ChainSpec::from_genesis( - "Local Testnet", - "local_testnet", - || testnet_genesis(vec![ - get_authority_keys_from_seed("Alice"), - get_authority_keys_from_seed("Bob"), - ], - get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - ], - true), - vec![], - None, - None, - None, - None - ), - }) - } - - pub(crate) fn from(s: &str) -> Option { - match s { - "dev" => Some(Alternative::Development), - "" | "local" => Some(Alternative::LocalTestnet), - _ => None, - } - } -} - -fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, - root_key: AccountId, - endowed_accounts: Vec, - _enable_println: bool) -> GenesisConfig { - GenesisConfig { - system: Some(SystemConfig { - code: WASM_BINARY.to_vec(), - changes_trie_config: Default::default(), - }), - indices: Some(IndicesConfig { - ids: endowed_accounts.clone(), - }), - balances: Some(BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), - vesting: vec![], - }), - sudo: Some(SudoConfig { - key: root_key, - }), - aura: Some(AuraConfig { - authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), - }), - grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), - }), - } -} diff --git a/node-template/src/cli.rs b/node-template/src/cli.rs deleted file mode 100644 index 15c1a0486fb3f..0000000000000 --- a/node-template/src/cli.rs +++ /dev/null @@ -1,114 +0,0 @@ -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_prepare, ParseAndPrepare, NoCustom}; -use substrate_service::{AbstractService, Roles as ServiceRoles, Configuration}; -use aura_primitives::sr25519::{AuthorityPair as AuraPair}; -use crate::chain_spec; -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, -{ - type Config = Configuration<(), T>; - match parse_and_prepare::(&version, "substrate-node", args) { - ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, - |exit, _cli_args, _custom_args, config: 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))?; - match config.roles { - ServiceRoles::LIGHT => run_until_exit( - runtime, - service::new_light(config)?, - exit - ), - _ => run_until_exit( - runtime, - service::new_full(config)?, - exit - ), - } - }), - ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec), - ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| - Ok(new_full_start!(config).0), load_spec, exit), - ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| - Ok(new_full_start!(config).0), load_spec, exit), - ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>| - Ok(new_full_start!(config).0), load_spec), - ParseAndPrepare::CustomCommand(_) => Ok(()) - }?; - - Ok(()) -} - -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: AbstractService, - E: IntoExit, -{ - let (exit_send, exit) = exit_future::signal(); - - let informant = informant::build(&service); - runtime.executor().spawn(exit.until(informant).map(|_| ())); - - // we eagerly drop the service so that the internal exit future is fired, - // but we need to keep holding a reference to the global telemetry guard - let _telemetry = service.telemetry(); - - let service_res = { - let exit = e.into_exit().map_err(|_| error::Error::Other("Exit future failed.".into())); - let service = service.map_err(|err| error::Error::Service(err)); - let select = service.select(exit).map(|_| ()).map_err(|(err, _)| err); - runtime.block_on(select) - }; - - exit_send.fire(); - - // TODO [andre]: timeout this future #1318 - let _ = runtime.shutdown_on_idle().wait(); - - service_res -} - -// 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 || { - let exit_send = exit_send_cell.try_borrow_mut().expect("signal handler not reentrant; qed").take(); - if let Some(exit_send) = exit_send { - exit_send.send(()).expect("Error sending exit notification"); - } - }).expect("Error setting Ctrl-C handler"); - - exit.map_err(drop) - } -} diff --git a/node-template/src/main.rs b/node-template/src/main.rs deleted file mode 100644 index 1f286a2237548..0000000000000 --- a/node-template/src/main.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! Substrate Node Template CLI library. - -#![warn(missing_docs)] -#![warn(unused_extern_crates)] - -mod chain_spec; -#[macro_use] -mod service; -mod cli; - -pub use substrate_cli::{VersionInfo, IntoExit, error}; - -fn main() -> Result<(), cli::error::Error> { - let version = VersionInfo { - name: "Substrate Node", - commit: env!("VERGEN_SHA_SHORT"), - version: env!("CARGO_PKG_VERSION"), - executable_name: "node-template", - author: "Anonymous", - description: "Template Node", - support_url: "support.anonymous.an", - }; - - cli::run(std::env::args(), cli::Exit, version) -} diff --git a/node-template/src/service.rs b/node-template/src/service.rs deleted file mode 100644 index 53a52ac0aca25..0000000000000 --- a/node-template/src/service.rs +++ /dev/null @@ -1,211 +0,0 @@ -//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. - -use std::sync::Arc; -use std::time::Duration; -use substrate_client::LongestChain; -use futures03::prelude::*; -use runtime::{self, GenesisConfig, opaque::Block, RuntimeApi}; -use substrate_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder}; -use transaction_pool::{self, txpool::{Pool as TransactionPool}}; -use inherents::InherentDataProviders; -use network::{construct_simple_protocol}; -use substrate_executor::native_executor_instance; -pub use substrate_executor::NativeExecutor; -use aura_primitives::sr25519::{AuthorityPair as AuraPair}; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; - -// Our native executor instance. -native_executor_instance!( - pub Executor, - runtime::api::dispatch, - runtime::native_version, -); - -construct_simple_protocol! { - /// Demo protocol attachment for substrate. - pub struct NodeProtocol where Block = Block { } -} - -/// Starts a `ServiceBuilder` for a full service. -/// -/// Use this macro if you don't actually need the full service, but just the builder in order to -/// be able to perform chain operations. -macro_rules! new_full_start { - ($config:expr) => {{ - let mut import_setup = None; - let inherent_data_providers = inherents::InherentDataProviders::new(); - - let builder = substrate_service::ServiceBuilder::new_full::< - runtime::opaque::Block, runtime::RuntimeApi, crate::service::Executor - >($config)? - .with_select_chain(|_config, backend| { - Ok(substrate_client::LongestChain::new(backend.clone())) - })? - .with_transaction_pool(|config, client| - Ok(transaction_pool::txpool::Pool::new(config, transaction_pool::FullChainApi::new(client))) - )? - .with_import_queue(|_config, client, mut select_chain, transaction_pool| { - let select_chain = select_chain.take() - .ok_or_else(|| substrate_service::Error::SelectChainRequired)?; - - let (grandpa_block_import, grandpa_link) = - grandpa::block_import::<_, _, _, runtime::RuntimeApi, _, _>( - client.clone(), &*client, select_chain - )?; - - let import_queue = aura::import_queue::<_, _, AuraPair, _>( - aura::SlotDuration::get_or_compute(&*client)?, - Box::new(grandpa_block_import.clone()), - Some(Box::new(grandpa_block_import.clone())), - None, - client, - inherent_data_providers.clone(), - Some(transaction_pool), - )?; - - import_setup = Some((grandpa_block_import, grandpa_link)); - - Ok(import_queue) - })?; - - (builder, import_setup, inherent_data_providers) - }} -} - -/// Builds a new service for a full client. -pub fn new_full(config: Configuration) - -> Result -{ - let is_authority = config.roles.is_authority(); - let force_authoring = config.force_authoring; - let name = config.name.clone(); - let disable_grandpa = config.disable_grandpa; - - let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); - - let (block_import, grandpa_link) = - import_setup.take() - .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); - - let service = builder.with_network_protocol(|_| Ok(NodeProtocol::new()))? - .with_finality_proof_provider(|client, backend| - Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) - )? - .build()?; - - if is_authority { - let proposer = basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; - - let client = service.client(); - let select_chain = service.select_chain() - .ok_or(ServiceError::SelectChainRequired)?; - - let aura = aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( - aura::SlotDuration::get_or_compute(&*client)?, - client, - select_chain, - block_import, - proposer, - service.network(), - inherent_data_providers.clone(), - force_authoring, - service.keystore(), - )?; - - // the AURA authoring task is considered essential, i.e. if it - // fails we take down the service with it. - service.spawn_essential_task(aura); - } - - let grandpa_config = grandpa::Config { - // FIXME #1578 make this available through chainspec - gossip_duration: Duration::from_millis(333), - justification_period: 512, - name: Some(name), - keystore: Some(service.keystore()), - }; - - match (is_authority, disable_grandpa) { - (false, false) => { - // start the lightweight GRANDPA observer - service.spawn_task(grandpa::run_grandpa_observer( - grandpa_config, - grandpa_link, - service.network(), - service.on_exit(), - )?.map(|()| Ok::<(), ()>(())).compat()); - }, - (true, false) => { - // start the full GRANDPA voter - let voter_config = grandpa::GrandpaParams { - config: grandpa_config, - link: grandpa_link, - network: service.network(), - inherent_data_providers: inherent_data_providers.clone(), - on_exit: service.on_exit(), - telemetry_on_connect: Some(service.telemetry_on_connect_stream()), - voting_rule: grandpa::VotingRulesBuilder::default().build(), - }; - - // the GRANDPA voter task is considered infallible, i.e. - // if it fails we take down the service with it. - service.spawn_essential_task(grandpa::run_grandpa_voter(voter_config)? - .map(|()| Ok::<(), ()>(())).compat()); - }, - (_, true) => { - grandpa::setup_disabled_grandpa( - service.client(), - &inherent_data_providers, - service.network(), - )?; - }, - } - - Ok(service) -} - -/// Builds a new service for a light client. -pub fn new_light(config: Configuration) - -> Result -{ - let inherent_data_providers = InherentDataProviders::new(); - - ServiceBuilder::new_light::(config)? - .with_select_chain(|_config, backend| { - Ok(LongestChain::new(backend.clone())) - })? - .with_transaction_pool(|config, client| - Ok(TransactionPool::new(config, transaction_pool::FullChainApi::new(client))) - )? - .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { - let fetch_checker = fetcher - .map(|fetcher| fetcher.checker().clone()) - .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; - let grandpa_block_import = grandpa::light_block_import::<_, _, _, RuntimeApi, _>( - client.clone(), backend, Arc::new(fetch_checker), client.clone() - )?; - let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = - finality_proof_import.create_finality_proof_request_builder(); - - let import_queue = aura::import_queue::<_, _, AuraPair, ()>( - aura::SlotDuration::get_or_compute(&*client)?, - Box::new(grandpa_block_import), - None, - Some(Box::new(finality_proof_import)), - client, - inherent_data_providers.clone(), - None, - )?; - - Ok((import_queue, finality_proof_request_builder)) - })? - .with_network_protocol(|_| Ok(NodeProtocol::new()))? - .with_finality_proof_provider(|client, backend| - Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) - )? - .build() -} diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml deleted file mode 100644 index 67ff844f78a11..0000000000000 --- a/node/cli/Cargo.toml +++ /dev/null @@ -1,67 +0,0 @@ -[package] -name = "node-cli" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Substrate node implementation in Rust." -build = "build.rs" -edition = "2018" - -[dependencies] -log = "0.4.8" -tokio = "0.1.22" -futures = "0.1.29" -futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } -exit-future = "0.1.4" -jsonrpc-core = "13.2.0" -cli = { package = "substrate-cli", path = "../../core/cli" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -sr-io = { path = "../../core/sr-io" } -client = { package = "substrate-client", path = "../../core/client" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -inherents = { package = "substrate-inherents", path = "../../core/inherents" } -node-runtime = { path = "../runtime" } -node-rpc = { path = "../rpc" } -node-primitives = { path = "../primitives" } -hex-literal = "0.2.1" -substrate-rpc = { package = "substrate-rpc", path = "../../core/rpc" } -substrate-basic-authorship = { path = "../../core/basic-authorship" } -substrate-service = { path = "../../core/service" } -chain-spec = { package = "substrate-chain-spec", path = "../../core/chain-spec" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } -network = { package = "substrate-network", path = "../../core/network" } -babe = { package = "substrate-consensus-babe", path = "../../core/consensus/babe" } -babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives" } -grandpa = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa" } -grandpa_primitives = { package = "substrate-finality-grandpa-primitives", path = "../../core/finality-grandpa/primitives" } -sr-primitives = { path = "../../core/sr-primitives" } -node-executor = { path = "../executor" } -substrate-telemetry = { package = "substrate-telemetry", path = "../../core/telemetry" } -structopt = "0.3.3" -transaction-factory = { path = "../../test-utils/transaction-factory" } -keyring = { package = "substrate-keyring", path = "../../core/keyring" } -indices = { package = "srml-indices", path = "../../srml/indices" } -timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default-features = false } -rand = "0.7.2" -finality_tracker = { package = "srml-finality-tracker", path = "../../srml/finality-tracker", default-features = false } -contracts = { package = "srml-contracts", path = "../../srml/contracts" } -system = { package = "srml-system", path = "../../srml/system" } -balances = { package = "srml-balances", path = "../../srml/balances" } -transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment" } -support = { package = "srml-support", path = "../../srml/support", default-features = false } -im_online = { package = "srml-im-online", path = "../../srml/im-online", default-features = false } -sr-authority-discovery = { package = "srml-authority-discovery", path = "../../srml/authority-discovery", default-features = false } -authority-discovery = { package = "substrate-authority-discovery", path = "../../core/authority-discovery"} -serde = { version = "1.0.101", features = [ "derive" ] } -client_db = { package = "substrate-client-db", path = "../../core/client/db", features = ["kvdb-rocksdb"] } -offchain = { package = "substrate-offchain", path = "../../core/offchain" } - -[dev-dependencies] -keystore = { package = "substrate-keystore", path = "../../core/keystore" } -babe = { package = "substrate-consensus-babe", path = "../../core/consensus/babe", features = ["test-helpers"] } -consensus-common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } -service-test = { package = "substrate-service-test", path = "../../core/service/test" } -tempfile = "3.1.0" - -[build-dependencies] -cli = { package = "substrate-cli", path = "../../core/cli" } -structopt = "0.3.3" diff --git a/node/cli/build.rs b/node/cli/build.rs deleted file mode 100644 index e7a7b271f1503..0000000000000 --- a/node/cli/build.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use cli::{NoCustom, CoreParams}; - -use std::{fs, env, path::Path}; - -use structopt::{StructOpt, clap::Shell}; - -fn main() { - build_shell_completion(); -} - -/// 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() { - 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(); - - CoreParams::::clap().gen_completions("substrate-node", *shell, &path); -} diff --git a/node/cli/res/flaming-fir.json b/node/cli/res/flaming-fir.json deleted file mode 100644 index 5cd11eb97fa00..0000000000000 --- a/node/cli/res/flaming-fir.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "name": "Flaming Fir", - "id": "flaming-fir", - "properties": { - "tokenDecimals": 15, - "tokenSymbol": "FIR" - }, - "bootNodes": [ - "/ip4/35.246.224.91/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", - "/ip4/35.246.224.91/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", - "/ip4/35.246.210.11/tcp/30333/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", - "/ip4/35.246.210.11/tcp/30334/ws/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", - "/ip4/35.198.110.45/tcp/30333/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", - "/ip4/35.198.110.45/tcp/30334/ws/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", - "/ip4/35.198.114.154/tcp/30333/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6", - "/ip4/35.198.114.154/tcp/30334/ws/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6" - ], - "telemetryEndpoints": [ - ["wss://telemetry.polkadot.io/submit/", 0] - ], - "protocolId": "fir", - "consensusEngine": null, - "genesis": { - "raw": [ - { - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579730a299be621974fd19374a88f1dddd8442b21db25d2c923907dda6af815b657fe": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0xd368b9d9bb1cc910c9a2b8e5d0f5f2fc": "0xf6ffc06ff28623000000000000000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579731143fa96e07eb73af3db3a1b057d18899f864e6fc5d2f905f9296ca641565564": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797397dddc7aba561f16ac00da4bae75ab812aa7b81418bebdab74425f0d6aa31cee": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0xbde3e43a2a348359d103d64bc95928146bdd9ae3490e26da38d2e4d19c137507": "0x0000a0dec5adc9353600000000000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797340944475c781bbdc9726766a78b1964888e039600b1c865c62586ab8f98c171e": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0xf186665804ca50670311307912458ce448d82cb96e7e4fe71df38c283a8720f4": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d120f0000c16ff286230f0000c16ff2862300", - "0x50a63a871aced22e88ee6466fe5aa5d9": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", - "0xaf837bb0dec545e1b97d62ed037898d1": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0xe026dd082e3158e72eb7c985fc8bac4f": "0x80700000", - "0xb49a6659ec27619e87dd18e11b6838c0": "0x00", - "0x7c79972b34b7e51bdd5f168ba3accd35fbec396be75dfad19dd1121327f1a1ad": "0x000168655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde7800", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797399a2fc4b1339e668345bac7e1aadd1a834b90939a4ea40b64f30433a1d475817": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0xbc3717660105a864bd63dcd430de64128d58bd0917fa8dd75aee827cf086e19c": "0x0000c16ff28623000000000000000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579732c1312343dce08149336968907c27cc602536aaf7a2b105d6fa07058a3803d31": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x72143961950b9317e15506626c4524c4": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0x9651d20f401bfac47731a01d6eba33b4": "0x00000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973dc4036f96ca26a30da6d8637ca1431896c1069bf172c419e98dc08109e7b23b5": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0xf14d23a9d4492a1efc9194e257b3c3d9": "0x00000000", - "0x90e2849b965314409e8bc00011f3004f": "0x04000000", - "0x52b963fbdb3d6e1b03808fc20071f07f": "0x004e0c00", - "0x87e6cbd186029472cea8c1748f99126b": "0x00000000", - "0x717a2ee9c64ad3424e10e4461ec08296": "0x0000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000008700000000000000af0000000000000001000000000000000100000000000000040000000000010010000000004000000020000000", - "0xeecb67c20ca6cc8ba4d4434687f61309": "0x103919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef01000000000000005633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce44001000000000000007932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f01000000000000009becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993320100000000000000", - "0x154ebcb2c318b2e1c23e43e65aea27cd1348c4c5157502d7669a31c7635019cc": "0x9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526", - "0x633daafcb669e97549c1b9d65660881016f969040bc16171709159437c31294a": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0xfacbe054606f2488121046f9c5539d98": "0x00", - "0x0c41b62474c49057a4476d0b96853c6d44e9c86c5fa130b0da3831c5eef546a0": "0x00", - "0xc1bc13c775b3406279618b05c28523cb": "0x00", - "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b657973711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0x7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e", - "0x75f6361fd25fec35714be80f2d9870af8c92e73cb6d299ba4774f5b0ad842275": "0x00", - "0x579ab55d37b1220812be3c3df29d4858": "0x00000000", - "0x4e62513de81454ce76df887573f7f98b101eb4585b1485a222b7db599f4e93e2": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff0f", - "0xa902f1f0ef97177b8df9f9fd413768e7": "0x00000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973be035f25cd43adc80f1dcf505f5ffd158d1592ab3719f354a256a4c3b7571934": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0x1ba14d232d3c301a93e35f55e3d7aef2d98dbb9cc0ce48f457b81b421e0f704d": "0x0000c16ff28623000000000000000000", - "0x2dce29f1a768624dc5343063cb77f77d": "0x07000000", - "0xa978690c6b811e943721dbb6cb9b6246": "0x0000000000000000", - "0x8b4621d5f16433d6024b5a31547c59ee24e749e051dbb4bc7e64502f2a4f62fb": "0x66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f", - "0x8cb577756012d928f17362e0741f9f2c": "0x01000000", - "0xc63b8a0db7e72fd87c88d8dcf4777b883f86728613c57148c4e5cdceb05b7a1a": "0x0001f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630168655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0x637414312dac3b280120bf15b4f66cee": "0x00000000", - "0xbf18c0c65fb39f32ee7c8016685c0a6056f8f924192efb2655be9a692d0b03b6": "0x00", - "0x3a636f6465": "0x0061736d01000000019f022660037f7f7f017f60027f7f017f60027f7f0060017f0060057f7f7f7f7f0060037f7f7f0060047f7f7f7f0060017f017e60057f7f7f7f7f017f60067f7f7f7f7f7f0060047f7f7f7f017f60017e0060067f7f7f7f7f7f017f60087f7f7f7f7f7f7f7f017f6000017f60077f7f7f7f7f7f7f017f60017f017f60027f7f017e60000060037e7f7f017f60047f7f7e7e0060077f7f7e7e7f7f7f0060087f7f7f7f7f7e7e7f0060057f7f7f7e7e0060077f7f7f7e7e7f7f0060037f7e7e0060057f7f7e7e7f0060077f7e7e7f7f7f7f0060067f7f7e7e7f7f0060077f7f7f7f7f7e7e0060047f7f7f7f017e6000017e60077f7f7f7e7e7e7f0060067f7f7f7e7e7f0060037f7e7f0060047f7e7e7f0060057f7e7e7e7e0060067f7e7e7e7e7f0002af082803656e760e6578745f626c616b65325f323536000503656e761f6578745f6765745f616c6c6f63617465645f6368696c645f73746f72616765000803656e76176578745f636c6561725f6368696c645f73746f72616765000603656e76146578745f6765745f73746f726167655f696e746f000803656e76166578745f6b696c6c5f6368696c645f73746f72616765000203656e76156578745f7365745f6368696c645f73746f72616765000903656e76196578745f6765745f616c6c6f63617465645f73746f72616765000003656e760f6578745f7365745f73746f72616765000603656e760c6578745f74776f785f313238000503656e76116578745f636c6561725f73746f72616765000203656e76126578745f737232353531395f766572696679000a03656e760e6578745f7072696e745f75746638000203656e760d6578745f7072696e745f6e756d000b03656e76166578745f6368696c645f73746f726167655f726f6f74000003656e76106578745f636c6561725f707265666978000203656e76166578745f73616e64626f785f6d656d6f72795f6e6577000103656e761b6578745f73616e64626f785f6d656d6f72795f74656172646f776e000303656e76176578745f73616e64626f785f696e7374616e7469617465000c03656e76126578745f73616e64626f785f696e766f6b65000d03656e761d6578745f73616e64626f785f696e7374616e63655f74656172646f776e000303656e76106578745f73746f726167655f726f6f74000303656e76186578745f73746f726167655f6368616e6765735f726f6f74000003656e76126578745f656432353531395f766572696679000a03656e76166578745f73616e64626f785f6d656d6f72795f676574000a03656e76166578745f73616e64626f785f6d656d6f72795f736574000a03656e760d6578745f7072696e745f686578000203656e76106578745f69735f76616c696461746f72000e03656e76156578745f6c6f63616c5f73746f726167655f676574000a03656e76216578745f6c6f63616c5f73746f726167655f636f6d706172655f616e645f736574000f03656e76116578745f6e6574776f726b5f7374617465001003656e76106578745f737232353531395f7369676e000803656e76166578745f7375626d69745f7472616e73616374696f6e000103656e76156578745f6c6f63616c5f73746f726167655f736574000403656e76146578745f656432353531395f67656e6572617465000603656e76146578745f737232353531395f67656e6572617465000603656e76236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74000603656e760a6578745f6d616c6c6f63001003656e76086578745f66726565000303656e76176578745f737232353531395f7075626c69635f6b657973000103656e760b6578745f74776f785f3634000503fd04fb0410100303000010101112030205001202060001010201021303070c0a0200060101011001010101010201060305030001010001010800010001010101010102030203030202020202020203020202020202020202020202020202020502020202050304050205010205020202140303020e02020303030202020201020102020405020202020202020202030202150101160509021706030505180602030202020205050505000314141212030212120501030303030303030303030303030303020202020202020502020202051202020303120e050502020502141406060505050502020205171919120503020302031a02020202021b020303030203140303051c1905050202020502050201010303020202020503020203020202060605030302020302020202020202021d0206030302020303030205020503030302020202020312020206020202030202050205060202051206090606060606060606060606060606060606060606060606061e02020203030203021f1203020302020505020203030302020203030202030303050510120202020202120202030202031010020202040302060202020303030203030202010a020202020202030b03030202030202020202020202020220030321060202020102010602030505020202030302021111021111050202111111021111110511031111111111111111030303030202020202020202030214020204020303020202020302020202020a0101010101010102010101010102010105020102050503050202010101050501010205050405220202020505040202050303030302020204020201050102060501050606050501040405050505060303010101000000002323242424250407017001de01de0105030100120619037f01418080c0000b7f004188b1c6000b7f004188b1c6000b078d0518066d656d6f72790200195f5f696e6469726563745f66756e6374696f6e5f7461626c6501000a5f5f646174615f656e6403010b5f5f686561705f62617365030209686173685f7465737400300c436f72655f76657273696f6e008c0412436f72655f657865637574655f626c6f636b008d0415436f72655f696e697469616c697a655f626c6f636b008f04114d657461646174615f6d657461646174610090041c426c6f636b4275696c6465725f6170706c795f65787472696e7369630094041b426c6f636b4275696c6465725f66696e616c697a655f626c6f636b00950420426c6f636b4275696c6465725f696e686572656e745f65787472696e736963730096041c426c6f636b4275696c6465725f636865636b5f696e686572656e747300980418426c6f636b4275696c6465725f72616e646f6d5f736565640099042b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e009a04214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b6572009c041e4772616e6470614170695f6772616e6470615f617574686f726974696573009e0415426162654170695f636f6e66696775726174696f6e009f0421417574686f72697479446973636f766572794170695f617574686f72697469657300a0041a417574686f72697479446973636f766572794170695f7369676e00a1041c417574686f72697479446973636f766572794170695f76657269667900a2041d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e636500a30411436f6e7472616374734170695f63616c6c00a4042153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b65797300a50409a403010041010bdd013d4c5147e50448495ea201a401fd02ff0280038103820383038403850386038703880389038a038b038c038d038e038f0390039103920393039403950396039703d801ca04d0048605d2048205e604d804e204d4044f8c05d10497059405393a3b8901644155565758595a5b6160636566678a018b018d018e01900192014e4d9d03be04b301be01a701bf01a801b601c001bb01f20262ad03ac03d901b103a203a403d503d403d6039c039b03c403da01a202a002db01a402a904a804dc01b204dc02db02dd01dd02ba04b904de01bf04b603b503df01b703c802c702e001cb02d903d803e101b602b702d802d702e201e302e202e301e402e703e603e401ea0389048804e501a702a602e601b201e701a302cd02ef03f003c902b402b502b902b802ca02bb04d202d102d002cf02ce02cc02f303d902ac04de02e802e702e502f602f402f702f302f502a303a603a503b003af03ae03d703e903e803f403f203f103ee03ed03ec03eb038a04af04ae04ad04ab04aa04b304bd04bc04c304c204c104c004cc04ce04cb04c904c704c804cf04e104d5049505980596050ac3c540fb040600200010290b0600200010240b06002000102b0b0600200010250b0a00200020012002102d0b2801017f0240200210242203450d002003200020022001200120024b1b109a051a200010250b20030b06002000102f0b1c01017f0240200010242201450d002001410020001099051a0b20010bfa0202017f037e230041206b220224002001ad42adfed5e4d485fda8d8007e42c3007c210302400240024002400240200141084b0d00200141014b0d0120010d02420021040c030b0240200141104b0d00200241106a2000290000200385420042adfed5e4d485fda8d8004200109f05200241186a29030020022903107c200120006a41786a2900008521040c040b200120006a41786a2900002105200321040340200029000020048542adfed5e4d485fda8d8007e42178942adfed5e4d485fda8d8007e2003852103200041086a2100200442cf829ebbefefde82147c2104200141786a220141084b0d000b200320058521040c030b0240200141034b0d00200120006a417e6a33000042108620003300008420038521040c030b200120006a417c6a35000042208620003500008420038521040c020b200031000021040b200420038521040b20022004420042adfed5e4d485fda8d8004200109f05200241086a290300210420022903002103200241206a2400200420037c0b0a00418080c0001032000b5b02017f037e230041306b220124002000290208210220002902102103200029020021042001420437031020014201370204200120043703182001200141186a36020020012003370328200120023703202001200141206a103e000b870301067f230041306b2202240020012802002103024002402001280204220441037422050d00410021060c010b200341046a2107410021060340200728020020066a2106200741086a2107200541786a22050d000b0b024002400240024002400240200141146a2802000d00200621070c010b024020040d0041ac80c000410041001034000b024002402006410f4b0d002003280204450d010b200620066a220720064f0d010b4101210541002107200241086a21060c010b2007417f4c0d01200241086a2106024020070d0041012105410021070c010b200710282205450d020b200241003602102002200736020c200220053602082002200241086a360214200241186a41106a200141106a290200370300200241186a41086a200141086a29020037030020022001290200370318200241146a41bc80c000200241186a10350d0220002006290200370200200041086a200641086a280200360200200241306a24000f0b1036000b200741011037000b41d480c0004133200241186a418881c0001038000b6c01017f230041306b2203240020032002360204200320013602002003411c6a41023602002003412c6a41013602002003420237020c200341e883c000360208200341013602242003200341206a360218200320033602282003200341046a360220200341086a2000103e000bbd0801087f230041c0006b22032400200341246a2001360200200341346a200241146a2802002204360200200341033a00382003412c6a2002280210220520044103746a36020020034280808080800437030820032000360220410021062003410036021820034100360210200320053602302003200536022802400240024002400240200228020822070d0020022802002108200228020422092004200420094b1b220a450d0141012104200020082802002008280204200128020c1100000d04200841086a210241012106034002402005280200200341086a200541046a280200110100450d00410121040c060b2006200a4f0d02200241046a210020022802002101200541086a2105200241086a210241012104200641016a2106200328022020012000280200200328022428020c110000450d000c050b0b20022802002108200228020422092002410c6a2802002205200520094b1b220a450d0041012104200020082802002008280204200128020c1100000d03200741106a2105200841086a21024101210603402003200541786a28020036020c2003200541106a2d00003a003820032005417c6a28020036020841002101410021040240024002400240200541086a2802000e0400010203000b2005410c6a2802002100410121040c020b02402005410c6a2802002207200328023422044f0d0041002104200328023020074103746a22072802044102470d0220072802002802002100410121040c020b41a089c000200720041034000b4100210420032802282207200328022c460d002003200741086a3602284100210420072802044102470d0020072802002802002100410121040b2003200036021420032004360210024002400240024002400240024020052802000e0404010006040b20032802282200200328022c470d010c050b200541046a2802002200200328023422044f0d01200328023020004103746a22002802044102470d04200028020028020021040c030b2003200041086a36022820002802044102470d03200028020028020021040c020b41a089c000200020041034000b200541046a28020021040b410121010b2003200436021c2003200136021802400240200541706a2802004101460d0020032802282204200328022c460d042003200441086a3602280c010b200541746a2802002204200328023422004f0d04200328023020044103746a21040b02402004280200200341086a200441046a280200110100450d00410121040c050b2006200a4f0d01200241046a210020022802002101200541246a2105200241086a210241012104200641016a2106200328022020012000280200200328022428020c110000450d000c040b0b0240200920064d0d00410121042003280220200820064103746a22052802002005280204200328022428020c1100000d030b410021040c020b41f087c0001032000b41b089c000200420001034000b200341c0006a240020040b05001031000b0e0041a6f4c500412210e70400000b810101017f230041c0006b220424002004200136020c2004200036020820042003360214200420023602102004412c6a41023602002004413c6a41033602002004420237021c200441b8c2c200360218200441043602342004200441306a3602282004200441106a3602382004200441086a360230200441186a4188afc000103e000bb10101037f0240024002400240200028020022002802042203200028020822046b2002490d00200028020021030c010b200420026a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102821030c010b200028020020032004102c21030b2003450d012000200436020420002003360200200028020821040b2000200420026a360208200320046a20012002109a051a41000f0b200441011037000b1031000ba70401047f230041106b220224002000280200210002400240024002400240024002402001418001490d002002410036020c2001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c040b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c030b0240200028020822032000280204470d00200341016a22042003490d06200341017422052004200520044b1b22044100480d060240024020030d002004102821030c010b200028020020032004102c21030b2003450d022000200436020420002003360200200028020821030b200028020020036a20013a00002000200028020841016a3602080c030b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b200441011037000b0240024020002802042204200028020822036b2001490d00200028020021040c010b200320016a22052003490d03200441017422032005200320054b1b22034100480d030240024020040d002003102821040c010b200028020020042003102c21040b2004450d022000200336020420002004360200200028020821030b2000200320016a360208200420036a2002410c6a2001109a051a0b200241106a240041000f0b200341011037000b1031000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41bc80c000200241086a10352101200241206a240020010b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c2002418486c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a419486c000103e000b0d00200035020041012001103f0b4702017f017e230041206b2202240020012902002103200241146a20012902083702002002200337020c20022000360208200241f883c0003602042002410136020020021040000bd40203027f017e037f230041306b22032400412721040240024020004290ce005a0d00200021050c010b412721040340200341096a20046a2206417c6a200020004290ce0080220542f0b17f7e7ca7220741ffff037141e4006e220841017441ba84c0006a2f00003b00002006417e6a2008419c7f6c20076a41ffff037141017441ba84c0006a2f00003b00002004417c6a2104200042ffc1d72f5621062005210020060d000b0b02402005a7220641e3004c0d00200341096a2004417e6a22046a2005a7220741ffff037141e4006e2206419c7f6c20076a41ffff037141017441ba84c0006a2f00003b00000b024002402006410a480d00200341096a2004417e6a22046a200641017441ba84c0006a2f00003b00000c010b200341096a2004417f6a22046a200641306a3a00000b2002200141b8aec6004100200341096a20046a412720046b10422104200341306a240020040b6601017f230041c0006b220124002001200036020c200141346a410136020020014201370224200141b0aec6003602202001410536023c2001200141386a36023020012001410c6a360238200141106a200141206a10332001280210200128021810e70400000b0d0042c8dfc497e99ce988eb000be00501057f024002402001450d00412b418080c4002000280200220641017122011b2107200120056a21080c010b200541016a210820002802002106412d21070b0240024020064104710d00410021020c010b4100210902402003450d002003210a200221010340200920012d000041c00171418001466a2109200141016a2101200a417f6a220a0d000b0b200820036a20096b21080b410121010240024020002802084101460d00200020072002200310430d012000280218200420052000411c6a28020028020c1100000f0b02402000410c6a280200220920084b0d00200020072002200310430d012000280218200420052000411c6a28020028020c1100000f0b0240024020064108710d00200920086b210941002101024002400240410120002d0030220a200a4103461b0e0402000100020b20092101410021090c010b20094101762101200941016a41017621090b200141016a210103402001417f6a2201450d0220002802182000280204200028021c280210110100450d000b41010f0b41012101200041013a003020004130360204200020072002200310430d01200920086b210941002101024002400240410120002d0030220a200a4103461b0e0402000100020b20092101410021090c010b20094101762101200941016a41017621090b200141016a2101024003402001417f6a2201450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210a41012101200028021820042005200028021c28020c1100000d01200941016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110100450d000c020b0b2000280204210a41012101200020072002200310430d00200028021820042005200028021c28020c1100000d00200941016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110100450d000b0b20010b5401017f024002402001418080c400460d0041012104200028021820012000411c6a2802002802101101000d010b024020020d0041000f0b2000280218200220032000411c6a28020028020c11000021040b20040b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c200241cc86c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41dc86c000103e000b8307010c7f200028021021030240024002400240200028020822044101460d0020030d012000280218200120022000411c6a28020028020c11000021030c030b2003450d010b0240024020020d00410021020c010b200120026a2105200041146a28020041016a21064100210720012103200121080340200341016a210902400240024020032c0000220a417f4a0d000240024020092005470d004100210b200521030c010b20032d0001413f71210b200341026a220921030b200a411f71210c0240200a41ff0171220a41df014b0d00200b200c41067472210a0c020b0240024020032005470d004100210d2005210e0c010b20032d0000413f71210d200341016a2209210e0b200d200b41067472210b0240200a41f0014f0d00200b200c410c7472210a0c020b02400240200e2005470d004100210a200921030c010b200e41016a2103200e2d0000413f71210a0b200b410674200c411274418080f0007172200a72220a418080c400470d020c040b200a41ff0171210a0b200921030b02402006417f6a2206450d00200720086b20036a21072003210820052003470d010c020b0b200a418080c400460d00024002402007450d0020072002460d0041002103200720024f0d01200120076a2c00004140480d010b200121030b2007200220031b21022003200120031b21010b20040d002000280218200120022000411c6a28020028020c1100000f0b4100210902402002450d002002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b0240200220096b200028020c2206490d002000280218200120022000411c6a28020028020c1100000f0b410021074100210902402002450d00410021092002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b200920026b20066a210a024002400240410020002d0030220320034103461b0e0402000100020b200a21074100210a0c010b200a4101762107200a41016a410176210a0b200741016a2103024003402003417f6a2203450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210941012103200028021820012002200028021c28020c1100000d00200a41016a2103200028021c210a20002802182100034002402003417f6a22030d0041000f0b20002009200a280210110100450d000b41010f0b20030bcd0801067f230041f0006b220424002004200336020c20042002360208410121052001210602402001418102490d00410020016b2107418002210803400240200820014f0d00200020086a2c000041bf7f4c0d0041002105200821060c020b2008417f6a21064100210520084101460d01200720086a21092006210820094101470d000b0b200420063602142004200036021020044100410520051b36021c200441b8aec600419287c00020051b3602180240024002400240200220014b22080d00200320014b0d00200220034b0d01024002402002450d0020012002460d00200120024d0d01200020026a2c00004140480d010b200321020b200420023602202002450d0220022001460d02200141016a210903400240200220014f0d00200020026a2c000041404e0d040b2002417f6a210820024101460d0420092002462106200821022006450d000c040b0b20042002200320081b360228200441306a41146a4103360200200441c8006a41146a4104360200200441d4006a4104360200200442033702342004419887c0003602302004410136024c2004200441c8006a3602402004200441186a3602582004200441106a3602502004200441286a360248200441306a41b087c000103e000b200441e4006a4104360200200441c8006a41146a4104360200200441d4006a4101360200200441306a41146a410436020020044204370234200441c087c0003602302004410136024c2004200441c8006a3602402004200441186a3602602004200441106a36025820042004410c6a3602502004200441086a360248200441306a41e087c000103e000b200221080b024020082001460d00410121060240024002400240200020086a22092c00002202417f4a0d0041002105200020016a220621010240200941016a2006460d00200941026a210120092d0001413f7121050b2002411f712109200241ff017141df014b0d01200520094106747221010c020b2004200241ff0171360224200441286a21020c020b4100210020062107024020012006460d00200141016a210720012d0000413f7121000b200020054106747221010240200241ff017141f0014f0d0020012009410c747221010c010b41002102024020072006460d0020072d0000413f7121020b20014106742009411274418080f00071722002722201418080c400460d020b2004200136022441012106200441286a21022001418001490d00410221062001418010490d0041034104200141808004491b21060b200420083602282004200620086a36022c200441306a41146a4105360200200441ec006a4104360200200441e4006a4104360200200441c8006a41146a4106360200200441d4006a4107360200200442053702342004418888c000360230200420023602582004410136024c2004200441c8006a3602402004200441186a3602682004200441106a3602602004200441246a3602502004200441206a360248200441306a41b088c000103e000b41f087c0001032000b100020012000280200200028020410450b6c01037f230041206b22022400024020002001104b0d002001411c6a280200210320012802182104200242043703182002420137020c2002419889c00036020820042003200241086a10350d00200041046a2001104b2101200241206a240020010f0b200241206a240041010bd90a02077f017e410121020240200128021841272001411c6a2802002802101101000d0041022103024002400240024002402000280200220241776a2200411e4d0d00200241dc00470d010c020b41f40021040240024020000e1f05010202000202020202020202020202020202020202020202030202020203050b41f20021040c040b41ee0021040c030b02400240024002400240024002402002104a0d00024002400240024002400240200241808004490d00200241808008490d0120024190fc476a4190fc0b490d0a200241e28b746a41e28d2c490d0a2002419fa8746a419f18490d0a200241dee2746a410e490d0a200241feffff0071419ef00a460d0a200241a9b2756a4129490d0a200241cb91756a410a4d0d0a410121030c0e0b20024180fe0371410876210541d095c000210041002106200241ff017121040340200041026a2107200620002d000122036a2108024020002d000022002005460d00200020054b0d092008210620072100200741a296c000470d010c090b20082006490d02200841a5024b0d03200641a296c0006a2100024003402003450d012003417f6a210320002d00002106200041016a210020062004470d000c0c0b0b2008210620072100200741a296c000470d000c080b0b20024180fe0371410876210541819bc000210041002106200241ff017121040340200041026a2107200620002d000122036a2108024020002d000022002005460d00200020054b0d072008210620072100200741c79bc000470d010c070b20082006490d03200841a6014b0d04200641c79bc0006a2100024003402003450d012003417f6a210320002d00002106200041016a210020062004470d000c0b0b0b2008210620072100200741c79bc000470d000c060b0b200620081044000b200841a502103c000b200620081044000b200841a601103c000b200241017267410276410773ad4280808080d0008421090c040b200241ffff0371210441ed9cc00021034101210002400340200341016a21080240024020032d0000220641187441187522074100480d00200821030c010b20084185a0c000460d02200741ff007141087420032d0001722106200341026a21030b200420066b22044100480d032000410173210020034185a0c000470d000c030b0b41f087c0001032000b200241ffff0371210441c798c0002103410121000340200341016a21080240024020032d0000220641187441187522074100480d00200821030c010b200841819bc000460d05200741ff007141087420032d0001722106200341026a21030b200420066b22044100480d0120004101732100200341819bc000470d000b0b4101210320004101710d030b200241017267410276410773ad4280808080d0008421090b410321030c020b41f087c0001032000b0b200221040b03402003210641dc0021004101210241012103024002400240024020060e0401020300010b024002400240024002402009422088a741ff01710e06050403020100050b200942ffffffff8f60834280808080c000842109410321030c060b200942ffffffff8f608342808080803084210941f5002100410321030c050b200942ffffffff8f608342808080802084210941fb002100410321030c040b20042009a72206410274411c7176410f712203413072200341d7006a2003410a491b210002402006450d002009427f7c42ffffffff0f83200942808080807083842109410321030c040b200942ffffffff8f6083428080808010842109410321030c030b200942ffffffff8f6083210941fd002100410321030c020b20012802184127200128021c2802101101000f0b41002103200421000b20012802182000200128021c280210110100450d000b0b20020b950201017f024002402000418010490d00024002400240024002400240200041808004490d002000410c7641706a2201418002490d0141a8a0c00020014180021034000b200041067641606a220141df074b0d01200141f08bc0006a2d0000220141c9004b0d0220014103744180a1c0006a21010c060b200141d093c0006a2d00004106742000410676413f7172220141ff034b0d02200141d0a5c0006a2d0000220141394b0d03200141037441d0a9c0006a21010c050b4188a0c000200141e0071034000b4198a0c000200141ca001034000b41b8a0c00020014180041034000b41c8a0c0002001413a1034000b200041037641f8ffffff017141d889c0006a21010b200129030042012000413f71ad86834200520baf0201037f23004180016b2202240002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001103f21000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000b0d00200035020041012001103f0b1c00200128021841a1aec000410b2001411c6a28020028020c1100000b1c00200128021841acaec000410e2001411c6a28020028020c1100000b6901037f230041206b220224002001411c6a280200210320012802182104200241086a41106a2000280200220141106a290200370300200241086a41086a200141086a2902003703002002200129020037030820042003200241086a10352101200241206a240020010b5e01017f230041306b220224002002200136020c20022000360208200241246a410136020020024201370214200241b0aec6003602102002410436022c2002200241286a3602202002200241086a360228200241106a41f8aec000103e000b140020002802002001200028020428020c1101000bc30501077f410021040240024020024103712205450d00410420056b2205450d00200220032005200520034b1b22046a210641002105200141ff017121072004210820022109024003400240200620096b41034b0d0041002107200141ff0171210603402008450d04200920076a210a2008417f6a2108200741016a2107200a2d0000220a2006470d000b2005200a200141ff01714641016a4101716a20076a417f6a21050c020b200520092d0000220a2007476a2105200a2007460d012005200941016a2d0000220a2007476a2105200a2007460d012005200941026a2d0000220a2007476a2105200a2007460d012005200941036a2d0000220a2007476a21052008417c6a2108200941046a2109200a2007470d000b0b410121090c010b200141ff017121070240024020034108490d002004200341786a220a4b0d00200741818284086c210502400340200220046a220941046a2802002005732208417f73200841fffdfb776a7120092802002005732209417f73200941fffdfb776a7172418081828478710d01200441086a2204200a4d0d000b0b200420034b0d010b200220046a2109200220036a2102200320046b2108410021050240024003400240200220096b41034b0d0041002107200141ff0171210203402008450d04200920076a210a2008417f6a2108200741016a2107200a2d0000220a2002470d000b200a200141ff01714641016a41017120056a20076a417f6a21050c020b200520092d0000220a2007476a2105200a2007460d012005200941016a2d0000220a2007476a2105200a2007460d012005200941026a2d0000220a2007476a2105200a2007460d012005200941036a2d0000220a2007476a21052008417c6a2108200941046a2109200a2007470d000b0b41012109200520046a21050c020b41002109200520076a20046a21050c010b200420031044000b20002005360204200020093602000b2601017f200028020022012802002001280204200028020428020020002802082802001046000b850804057f017e017f017e02400240024002402002450d00410020016b410020014103711b2103200241796a4100200241074b1b210441002105034002400240200120056a2d000022064118744118752207417f4a0d0042808080801021080240200641e681c0006a2d0000417e6a220941024d0d0042808080808020210a0c070b0240024002400240024020090e03000102000b200541016a22062002490d024200210a0c090b4200210a200541016a220920024f0d08200120096a2d0000210902400240200641a07e6a2206410d4b0d000240024020060e0e0002020202020202020202020201000b200941e0017141a001460d0242808080808020210a0c0c0b02402009411874411875417f4c0d0042808080808020210a0c0c0b200941ff017141a001490d0142808080808020210a0c0b0b02402007411f6a41ff0171410b4b0d0002402009411874411875417f4c0d0042808080808020210a0c0c0b200941ff017141c001490d0142808080808020210a0c0b0b0240200941ff017141bf014d0d0042808080808020210a0c0b0b0240200741fe017141ee01460d0042808080808020210a0c0b0b2009411874411875417f4c0d0042808080808020210a0c0a0b42002108200541026a220620024f0d09200120066a2d000041c00171418001460d020c070b4200210a200541016a220920024f0d07200120096a2d0000210902400240200641907e6a220641044b0d000240024020060e050002020201000b200941f0006a41ff01714130490d0242808080808020210a0c0b0b02402009411874411875417f4c0d0042808080808020210a0c0b0b200941ff0171419001490d0142808080808020210a0c0a0b0240200941ff017141bf014d0d0042808080808020210a0c0a0b02402007410f6a41ff017141024d0d0042808080808020210a0c0a0b2009411874411875417f4c0d0042808080808020210a0c090b200541026a220620024f0d07200120066a2d000041c00171418001470d0642002108200541036a220620024f0d08200120066a2d000041c00171418001460d01428080808080e000210a42808080801021080c080b42808080808020210a4280808080102108200120066a2d000041c00171418001470d070b200641016a21050c010b0240200320056b4103710d000240200520044f0d000340200120056a220641046a280200200628020072418081828478710d01200541086a22052004490d000b0b200520024f0d010340200120056a2c00004100480d022002200541016a2205470d000c040b0b200541016a21050b20052002490d000b0b20002001360204200041086a2002360200200041003602000f0b428080808080c000210a42808080801021080c010b420021080b2000200a2008842005ad84370204200041013602000b02000ba20401077f230041306b220324000240024020020d00410021040c010b200341286a210502400240024002400340024020002802082d0000450d00200028020041e4afc0004104200028020428020c1100000d050b2003410a3602282003428a808080103703202003200236021c200341003602182003200236021420032001360210200341086a410a200120021052024002400240024020032802084101470d00200328020c210403402003200420032802186a41016a2204360218024002402004200328022422064f0d00200328021421070c010b200328021422072004490d00200641054f0d072003280210200420066b22086a22092005460d04200920052006109c05450d040b200328021c22092004490d0220072009490d0220032006200341106a6a41176a2d0000200328021020046a200920046b10522003280204210420032802004101460d000b0b2003200328021c3602180b200028020841003a0000200221040c010b200028020841013a0000200841016a21040b2000280204210920002802002106024020044520022004467222070d00200220044d0d03200120046a2c000041bf7f4c0d030b200620012004200928020c1100000d04024020070d00200220044d0d04200120046a2c000041bf7f4c0d040b200120046a2101200220046b22020d000b410021040c040b20064104103c000b20012002410020041046000b20012002200420021046000b410121040b200341306a240020040bf90101017f230041106b220224002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b20002002410c6a200110562101200241106a240020010b6001017f230041206b2202240020022000360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41ccafc000200241086a10352101200241206a240020010b0d0020002802002001200210560b800201017f230041106b22022400200028020021002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b20002002410c6a200110562101200241106a240020010b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41ccafc000200241086a10352101200241206a240020010bdb0302047f057e230041d0006b2205240041012106024020002d00040d0020002d000521070240200028020022082d00004104710d0041012106200828021841caafc00041e8afc000200741ff017122071b4102410320071b2008411c6a28020028020c1100000d014101210620002802002208280218200120022008411c6a28020028020c1100000d01410121062000280200220828021841b9a8c40041022008411c6a28020028020c1100000d0120032000280200200428020c11010021060c010b0240200741ff01710d0041012106200828021841ebafc00041032008411c6a28020028020c1100000d01200028020021080b41012106200541013a00172005200541176a360210200829020821092008290210210a200541346a41b0afc000360200200520082902183703082008290220210b2008290228210c200520082d00303a00482008290200210d2005200c3703402005200b3703382005200a370328200520093703202005200d3703182005200541086a360230200541086a2001200210560d00200541086a41b9a8c400410210560d002003200541186a200428020c1101000d00200528023041c8afc0004102200528023428020c11000021060b200041013a0005200020063a0004200541d0006a240020000bf30202047f057e230041d0006b2203240041012104024020002d00080d00200028020421050240200028020022062d00004104710d0041012104200628021841caafc00041f1afc00020051b4102410120051b2006411c6a28020028020c1100000d0120012000280200200228020c11010021040c010b024020050d0041012104200628021841f2afc00041022006411c6a28020028020c1100000d01200028020021060b41012104200341013a00172003200341176a3602102006290208210720062902102108200341346a41b0afc00036020020032006290218370308200629022021092006290228210a200320062d00303a00482006290200210b2003200a3703402003200937033820032008370328200320073703202003200b3703182003200341086a3602302001200341186a200228020c1101000d00200328023041c8afc0004102200328023428020c11000021040b200020043a00082000200028020441016a360204200341d0006a240020000b6401027f230041206b220224002001411c6a280200210320012802182101200241086a41106a200041106a290200370300200241086a41086a200041086a2902003703002002200029020037030820012003200241086a10352100200241206a240020000bb50f020d7f017e230041206b220324004101210402400240200228021841222002411c6a2802002802101101000d000240024020010d00410021050c010b200020016a21062000210741002105410021080240034020072109200741016a210a02400240024020072c0000220b417f4a0d0002400240200a2006470d004100210c200621070c010b20072d0001413f71210c200741026a220a21070b200b411f7121040240200b41ff0171220b41df014b0d00200c200441067472210b0c020b0240024020072006470d004100210d2006210e0c010b20072d0000413f71210d200741016a220a210e0b200d200c41067472210c0240200b41f0014f0d00200c2004410c7472210b0c020b02400240200e2006470d004100210b200a21070c010b200e41016a2107200e2d0000413f71210b0b200c4106742004411274418080f0007172200b72220b418080c400470d020c040b200b41ff0171210b0b200a21070b4102210a024002400240024002400240200b41776a220c411e4d0d00200b41dc00470d010c020b41f400210e02400240200c0e1f05010202000202020202020202020202020202020202020202030202020203050b41f200210e0c040b41ee00210e0c030b02400240200b104a0d00024002400240024002400240024002400240200b41808004490d00200b41808008490d01200b4190fc476a4190fc0b490d09200b41e28b746a41e28d2c490d09200b419fa8746a419f18490d09200b41dee2746a410e490d09200b41feffff0071419ef00a460d09200b41a9b2756a4129490d09200b41cb91756a410a4d0d090c0e0b200b4180fe0371410876210f41d095c000210c410021040340200c41026a210d2004200c2d0001220a6a210e0240200c2d0000220c200f460d00200c200f4b0d08200e2104200d210c200d41a296c000470d010c080b200e2004490d02200e41a5024b0d03200441a296c0006a210c02400340200a450d01200a417f6a210a200c2d00002104200c41016a210c2004200b41ff0171470d000c0b0b0b200e2104200d210c200d41a296c000470d000c070b0b200b4180fe0371410876210f41819bc000210c410021040340200c41026a210d2004200c2d0001220a6a210e0240200c2d0000220c200f460d00200c200f4b0d06200e2104200d210c200d41c79bc000470d010c060b200e2004490d03200e41a6014b0d04200441c79bc0006a210c02400340200a450d01200a417f6a210a200c2d00002104200c41016a210c2004200b41ff0171470d000c0a0b0b200e2104200d210c200d41c79bc000470d000c050b0b2004200e1044000b200e41a502103c000b2004200e1044000b200e41a601103c000b200b41ffff0371210e41ed9cc000210a4101210c02400340200a41016a210d02400240200a2d00002204411874411875220f4100480d00200d210a0c010b200d4185a0c000460d02200f41ff0071410874200a2d0001722104200a41026a210a0b200e20046b220e4100480d03200c410173210c200a4185a0c000470d000c030b0b41f087c0001032000b200b41ffff0371210e41c798c000210a4101210c0340200a41016a210d02400240200a2d00002204411874411875220f4100480d00200d210a0c010b200d41819bc000460d04200f41ff0071410874200a2d0001722104200a41026a210a0b200e20046b220e4100480d01200c410173210c200a41819bc000470d000b0b200c4101710d050b200b41017267410276410773ad4280808080d0008421104103210a0c020b41f087c0001032000b0b200b210e0b2003200136020420032000360200200320053602082003200836020c0240024020082005490d0002402005450d0020052001460d00200520014f0d01200020056a2c000041bf7f4c0d010b02402008450d0020082001460d00200820014f0d01200020086a2c000041bf7f4c0d010b2002280218200020056a200820056b200228021c28020c110000450d01410121040c060b20032003410c6a3602182003200341086a36021420032003360210200341106a1053000b0340200a210c4101210441dc0021054101210a024002400240024002400240200c0e0402010500020b02400240024002402010422088a741ff01710e06050302010006050b201042ffffffff8f60834280808080308421104103210a41f50021050c070b201042ffffffff8f60834280808080208421104103210a41fb0021050c060b200e2010a7220c410274411c7176410f71220a413072200a41d7006a200a410a491b21050240200c450d002010427f7c42ffffffff0f832010428080808070838421100c050b201042ffffffff8f60834280808080108421100c040b201042ffffffff8f608321104103210a41fd0021050c040b4100210a200e21050c030b4101210a0240200b418001490d004102210a200b418010490d0041034104200b41808004491b210a0b200a20086a21050c040b201042ffffffff8f60834280808080c0008421100b4103210a0b20022802182005200228021c2802101101000d050c000b0b200820096b20076a210820062007470d000b0b2005450d0020052001460d00200520014f0d02200020056a2c000041bf7f4c0d020b410121042002280218200020056a200120056b200228021c28020c1100000d0020022802184122200228021c28021011010021040b200341206a240020040f0b20002001200520011046000bc00201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d0020002d0000210420034120710d012004ad42ff018341012001103f21000c020b20002d00002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000b0b0020002802002001104b0b800201027f230041106b2202240020012802184198b0c00041092001411c6a28020028020c1100002103200241003a0005200220033a0004200220013602002002200036020c200241a1b0c000410b2002410c6a41f8afc000105c21012002200041046a36020c200141acb0c00041092002410c6a41b8b0c000105c1a20022d00042101024020022d0005450d00200141ff0171210041012101024020000d0020022802002201411c6a28020028020c210020012802182103024020012d00004104710d00200341eeafc0004102200011000021010c010b200341f0afc0004101200011000021010b200220013a00040b200241106a2400200141ff01714100470bb50201027f230041106b2202240002400240200028020022002d00004101460d00200128021841e0e2c50041042001411c6a28020028020c11000021010c010b2002200128021841e4e2c50041042001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200041016a36020c20022002410c6a4188b0c000105d1a20022d00082101024020022802042203450d00200141ff0171210041012101024020000d00024020034101470d0020022d000941ff0171450d00200228020022002d00004104710d0041012101200028021841f4afc00041012000411c6a28020028020c1100000d010b2002280200220128021841c8a4c60041012001411c6a28020028020c11000021010b200220013a00080b200141ff017141004721010b200241106a240020010b1c00200128021841b8aec60041052001411c6a28020028020c1100000b040041000b02000b02000b9e10020a7f017e23004180016b2202240002400240024020012802042203200128020022046b41e100490d000240024003402001200441206a3602002001280208220341186a280200210520032802102106200241e0006a41186a22034200370300200241e0006a41106a22074200370300200241e0006a41086a220842003703002002420037036020044120200241e0006a1000200241106a41186a22092003290300370300200241106a41106a220a2007290300370300200241106a41086a220b2008290300370300200220022903603703102002410036026020062005200241106a4120200241e0006a10012106024020022802602205417f460d0020022005360258200220053602542002200636025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c050b20012001280200220441206a3602002001280208220541186a2802002106200528021021052003420037030020074200370300200842003703002002420037036020044120200241e0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903603703102002410036026020052006200241106a4120200241e0006a10012106024020022802602205417f470d0020012001280200220441206a3602002001280208220541186a2802002106200528021021052003420037030020074200370300200842003703002002420037036020044120200241e0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903603703102002410036026020052006200241106a4120200241e0006a1001210620022802602205417f470d0320012001280200220441206a3602002001280208220541186a2802002106200528021021052003420037030020074200370300200842003703002002420037036020044120200241e0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903603703102002410036026020052006200241106a4120200241e0006a1001210720022802602203417f470d0220012802042203200128020022046b41e0004b0d010c040b0b20022005360258200220053602542002200636025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c030b20022003360258200220033602542002200736025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c020b20022005360258200220053602542002200636025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c010b024020042003460d0003402001200441206a3602002001280208220341186a280200210720032802102103200241e0006a41186a22084200370300200241e0006a41106a22094200370300200241e0006a41086a220a42003703002002420037036020044120200241e0006a1000200241106a41186a2008290300370300200241106a41106a2009290300370300200241106a41086a200a290300370300200220022903603703102002410036026020032007200241106a4120200241e0006a10012107024020022802602203417f460d0020022003360258200220033602542002200736025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c030b200128020022042001280204470d000b0b200041003602000c010b200241e0006a41086a2002220141086a280200220336020020022001290200220c370360200020043602002000200c3702042000410c6a20033602000b20024180016a24000b950201057f230041e0026b22012400024020002802082202200028020c460d00200141b0016a4101722103200141d8016a210403402000200241b0016a36020820022d00002105200141b0016a200241016a41af01109a051a20054103460d01200141016a200141b0016a41af01109a051a200120053a00b0012003200141016a41af01109a051a02400240200541014b0d000240024020050e020001000b024020012802b801450d0020012802b401102a0b20012d00c0014105490d0220012802e801450d0220012802e401102a0c020b2004106a0c010b200128029802450d00200128029402102a0b20002802082202200028020c470d000b0b02402000280204450d002000280200102a0b200141e0026a24000baa0b01057f02402000280200220141124b0d00024002400240024002400240024002400240024002400240024020010e13000d0d010d0d020304050607080d090d0a0b0c000b0240200041086a280200220141054b0d0002400240024020010e06101000100102100b200041106a280200450d0f2000410c6a280200102a0f0b200041106a280200450d0e2000410c6a280200102a0f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141186a2101200241686a22020d000b0b200041106a280200450d0d200028020c102a0f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b200041106a280200450d0c200028020c102a0f0b02402000410c6a2802002201450d0020002802042203200141f0006c6a2104034002402003410c6a2802002202450d0020032802042101200241246c210203400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012002415c6a22020d000b0b200341f0006a21010240200341086a280200450d002003280204102a0b2001210320012004470d000b0b200041086a280200450d0b2000280204102a0f0b0240200041086a2d00002201410c4b0d0020014106470d0b200041106a280200450d0b2000410c6a280200102a0f0b200041106a280200450d0a2000410c6a280200102a0f0b200041086a280200450d092000280204102a0f0b200041086a2d0000417f6a220141074b0d08024002400240024020010e08000c0c0c0c010203000b2000410c6a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b20002d0004417f6a220141024b0d0702400240024020010e03000102000b2000410c6a280200450d09200041086a280200102a0f0b200041086a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b20002d0004417f6a220141024b0d0602400240024020010e03000102000b2000410c6a280200450d08200041086a280200102a0f0b200041086a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b200041086a280200417f6a220141014b0d050240024020010e020001000b200041106a280200450d062000410c6a280200102a0f0b200041106a280200450d052000410c6a280200102a0f0b20002d00044104490d042000410c6a280200450d04200041086a280200102a0c040b200041086a280200450d032000280204102a0f0b200041086a2d0000417e6a220141024b0d0202400240024020010e03000102000b200041106a280200450d042000410c6a280200102a0f0b200041346a280200450d03200041306a280200102a0f0b200041306a280200450d022000412c6a280200102a0f0b02402000280204220141024b0d00024020010e03030003030b200041086a2201280200106a2001280200102a0f0b2000412c6a2201280200106a2001280200102a0f0b02402000410c6a280200450d00200041086a280200102a0b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102a0f0b0b960301097f230041106b2202240002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002006450d0020042d0001210720012003417e6a22063602042001200441026a3602002006450d0020042d0002210820012003417d6a22063602042001200441036a3602002006450d0020042d0003210620012003417c6a3602042001200441046a360200200241086a2001106c20022802080d022001280204200228020c2204490d022004417f4c0d0302400240024020040d004101210341010d010c050b2004102e2203450d0120012802042004490d03200320012802002004109a0521092001280204220a2004490d062001200a20046b3602042001200128020020046a3602002009450d040b20002004360208200020033602042000410c6a2004360200200020074108742005722008411074722006411874723602000c060b200441011037000b200041003602040c040b2003102a0b200041003602040c020b1036000b2004200a1044000b200241106a24000bcf0201067f0240024020012802042202450d00200128020022032d0000210420012002417f6a2205360204410121062001200341016a3602000240200441037122074103460d0002400240024020070e03000102000b20044102762107410021060c040b41012106024020050d000c040b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d03200141fcff03714102762107410021060c030b20054103490d01200341036a2d0000210620032f0001210720012002417c6a3602042001200341046a3602002007200641107472410874200472220141027621072001418080044921060c020b0240200441034d0d000c020b20054104490d012003280001210720012002417b6a3602042001200341056a36020020074180808080044921060c010b410121060b20002007360204200020063602000baf04010a7f230041d0006b2202240020022001106c0240024002400240024020022802000d00200128020422034160712204417f4c0d022002280204210502400240200341057622060d00410121070c010b200410282207450d040b02402005450d00410021080340200241003a00482008220941016a21082001280204417f6a21034100210402400240024003402003417f460d01200241286a20046a2001280200220a2d00003a0000200120033602042001200a41016a3602002002200441016a220a3a00482003417f6a2103200a2104200a4120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a220a200241286a41106a290300370300200241086a41086a220b200241286a41086a2903003703002002200229032837030820062009470d020240200941017422032008200320084b1b220641ffffff3f712006470d002006410574220341004e0d020b1031000b0240200441ff0171450d00200241003a00480b200041003602002006450d052007102a0c050b0240024020090d002003102821070c010b200720094105742003102c21070b2007450d070b200720094105746a22032002290308370000200341186a2004290300370000200341106a200a290300370000200341086a200b29030037000020082005470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241d0006a24000f0b1036000b200441011037000b200341011037000b9203010a7f200041086a220228020021034100210420024100360200024002402003450d004100210541002106410021044100210702400340024002402004450d00200741057421080340200720034f0d062001200028020022096b2008460d02200920086a220a20014120109c05450d020240200620076a220b20034f0d00200920056a20086a2209200a290000370000200941186a200a41186a290000370000200941106a200a41106a290000370000200941086a200a41086a290000370000200841206a2108200741016a22072003490d010c050b0b41c4b2c000200b20031034000b200028020020074105746a21080340200720034f0d0520012008460d01200820014120109c05450d01200841206a2108200741016a22072003490d000b410021040c030b200541606a21052006417f6a2106200441016a2104200741016a22072003490d000b0b2004450d00200320074d0d00200028020020074105746a220820044105746b2008200320076b410574109b051a0b2002200320046b3602000f0b41e8b1c000200720031034000bfe0203017f017e0b7f024002400240024020012802082202ad42187e2203422088a70d002003a72204417f4c0d00200128020021050240024020040d00410421060c010b200410282206450d020b0240024020020d00410021070c010b2005200241186c6a210841002107200621010340200541086a2802002204417f4c0d02200528020021090240024020040d004101210a4100210b0c010b2004210b20041028220a450d050b200a20092004109a05210a200541146a2802002209417f4c0d022005410c6a280200210c0240024020090d004100210d4101210e0c010b2009210d20091028220e450d060b200e200c2009109a05210c200141146a2009360200200141106a200d3602002001410c6a200c360200200141086a2004360200200141046a200b3602002001200a360200200141186a2101200741016a2107200541186a22052008470d000b0b2000200736020820002002360204200020063602000f0b1036000b200441041037000b200441011037000b200941011037000bc90a03027f017e1c7f230041f0006b22022400024002400240024002400240024020012802082203ad42f0007e2204422088a70d002004a72205417f4c0d00200128020021060240024020050d00410421070c010b200510282207450d020b0240024020030d00410021080c010b2006200341f0006c6a2109410021082007210a0340200241c0006a41086a220b200641186a290000370300200241c0006a41106a220c200641206a290000370300200241c0006a41186a220d200641286a290000370300200241206a41086a220e200641386a29000037030020062900102104200241206a41106a220f200641c0006a290000370300200241206a41186a2210200641c8006a290000370300200241186a2211200641e8006a290000370300200241106a2212200641e0006a290000370300200241086a2213200641d8006a290000370300200220043703402002200629003037032020022006290050370300200628020c2214ad42247e2204422088a70d022004a72201417f4c0d0220062802002115200628020421160240024020010d00410421170c010b200110282217450d050b0240024020140d00410021180c010b201441246c211941002105410021180340024002400240024002400240201620056a22012d00000e050001020304000b2002200141146a2900003703602002200141196a290000370065200141056a2f0000200141076a2d000041107472211a200141106a280000211b2001410c6a280000211c200141086a280000211d200141016a280000211e4100211f0c040b200141106a280200221b417f4c0d08200141086a2802002120200141016a280000211e4101211f0240201b0d004100211c4101211d41012020201b109a051a0c040b201b211c201b1028221d450d0b201d2020201b109a051a0c030b200141106a280200221b417f4c0d07200141086a280200211f200141016a280000211e02400240201b0d004100211c4101211d0c010b201b211c201b1028221d450d0c0b201d201f201b109a051a4102211f0c020b200141106a280200221b417f4c0d06200141086a280200211f200141016a280000211e02400240201b0d004100211c4101211d0c010b201b211c201b1028221d450d0c0b201d201f201b109a051a4103211f0c010b2001410c6a280200221c417f4c0d05200141046a280200210102400240201c0d004101211a4100211d0c010b201c211d201c1028221a450d0c0b201a2001201c109a052201411874211e2001410876211a4104211f0b201720056a2201201f3a0000200141076a201a4110763a0000200141056a201a3b0000200141106a201b3600002001410c6a201c360000200141086a201d360000200141016a201e360000200141146a20022903603702002001411c6a200241e0006a41086a290300370200201841016a21182019200541246a2205470d000b0b200a2017360204200a410c6a2018360200200a41086a2014360200200a2002290340370210200a41186a200b290300370200200a2015360200200a2002290320370230200a41206a200c290300370200200a41286a200d290300370200200a41386a200e290300370200200a41c0006a200f290300370200200a41c8006a2010290300370200200a41e8006a2011290300370200200a41e0006a2012290300370200200a41d8006a2013290300370200200a2002290300370250200841016a2108200a41f0006a210a200641f0006a22062009470d000b0b200020083602082000200336020420002007360200200241f0006a24000f0b1036000b200541041037000b200141041037000b201b41011037000b201b41011037000b201b41011037000b201c41011037000b890203017f017e077f02400240024020012802082202ad420c7e2203422088a70d002003a72204417f4c0d00200128020021050240024020040d00410421060c010b200410282206450d020b0240024020020d00410021070c010b20052002410c6c6a210841002107200621040340200541086a2802002201417f4c0d02200528020021090240024020010d004101210a0c010b20011028220a450d050b200a20092001109a052109200441086a2001360200200441046a2001360200200420093602002004410c6a2104200741016a21072005410c6a22052008470d000b0b2000200736020820002002360204200020063602000f0b1036000b200441041037000b200141011037000bd70201037f024020002802082201450d002000280200220020014188016c6a2102200041f8006a2100034002400240200041887f6a22012d00002203410e4b0d00024002400240024020030e0f050505050500050501050205030505050b200041907f6a2d00004101470d042000419c7f6a280200450d04200041987f6a280200102a0c040b2000418c7f6a2d00004103470d030240200041947f6a280200450d00200041907f6a280200102a0b200041a07f6a280200450d032000419c7f6a280200102a0c030b2000418c7f6a2802000d02200041947f6a280200450d02200041907f6a280200102a0c020b200041907f6a2d00004105490d01200041b87f6a280200450d01200041b47f6a280200102a0c010b200041907f6a280200450d002000418c7f6a280200102a0b0240200141fc006a280200450d002000280200102a0b20004188016a210020014188016a2002470d000b0b0baf04010a7f230041d0006b2202240020022001106c0240024002400240024020022802000d00200128020422034160712204417f4c0d022002280204210502400240200341057622060d00410121070c010b200410282207450d040b02402005450d00410021080340200241003a00482008220941016a21082001280204417f6a21034100210402400240024003402003417f460d01200241286a20046a2001280200220a2d00003a0000200120033602042001200a41016a3602002002200441016a220a3a00482003417f6a2103200a2104200a4120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a220a200241286a41106a290300370300200241086a41086a220b200241286a41086a2903003703002002200229032837030820062009470d020240200941017422032008200320084b1b220641ffffff3f712006470d002006410574220341004e0d020b1031000b0240200441ff0171450d00200241003a00480b200041003602002006450d052007102a0c050b0240024020090d002003102821070c010b200720094105742003102c21070b2007450d070b200720094105746a22032002290308370000200341186a2004290300370000200341106a200a290300370000200341086a200b29030037000020082005470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241d0006a24000f0b1036000b200441011037000b200341011037000b8a06030a7f037e017f23004190016b2202240020022001106c0240024002400240024020022802000d00200128020441216e220341216c2204417f4c0d01200228020421050240024020040d00410121060c010b200410282206450d030b02402005450d0041002107034020012802042208450d05200128020022092d0000210420012008417f6a220a3602042001200941016a360200200441014b0d054100210b0240024020040e020100010b41002104200241003a0088012008417e6a210803400240200a2004470d00200441ff0171450d08200241003a0088010c080b200241e8006a20046a200920046a220b41016a2d00003a0000200120083602042001200b41026a3602002002200441016a220b3a0088012008417f6a2108200b2104200b4120470d000b200241c8006a41186a200241e8006a41186a290300370300200241c8006a41106a200241e8006a41106a290300370300200241c8006a41086a200241e8006a41086a290300370300200220022903683703484101210b0b200741016a2108200241286a41186a200241c8006a41186a290300220c370300200241286a41106a200241c8006a41106a290300220d370300200241286a41086a200241c8006a41086a290300220e370300200241086a41086a2209200e370300200241086a41106a220a200d370300200241086a41186a220f200c37030020022002290348220c3703282002200c370308024020032007470d000240200741017422042008200420084b1b2203ad42217e220c422088a70d00200ca722044100480d000240024020070d002004102821060c010b2006200741216c2004102c21060b20060d01200441011037000b1031000b2006200741216c6a2204200b3a000020042002290308370001200441096a2009290300370000200441116a200a290300370000200441196a200f2903003700002008210720082005470d000b0b2000200336020420002006360200200041086a20053602000c040b200041003602000c030b1036000b200441011037000b200041003602002003450d002006102a0b20024190016a24000bc902010a7f230041106b22022400200241086a2001106c0240024020022802080d00024020012802042203417f4c0d00200228020c210402400240024020030d00410121050c010b200310282205450d010b02402004450d004100210641002107034002400240024020012802042208450d00200741016a21092001280200220a2d0000210b20012008417f6a3602042001200a41016a36020020072003460d010c020b200041003602002003450d072005102a0c070b024020062009200620094b1b22034100480d000240024020070d002003102821050c010b200520072003102c21050b20050d01200341011037000b1031000b200520076a200b3a0000200641026a21062009210720042009470d000b0b2000200336020420002005360200200041086a20043602000c030b200341011037000b1036000b200041003602000b200241106a24000b990a02137f017e230041e0006b22022400200241086a2001106c0240024020022802080d000240200128020441246e220341246c2204417f4c0d00200228020c210502400240024020040d00410421060c010b200410282206450d010b02400240024020050d00410021040c010b2002412d6a2107200241cb006a220841056a21094100210a4100210b0340024002402001280204220c450d002001280200220d2d000021042001200c417f6a220e3602042001200d41016a360200200441064b0d00024002400240024002400240024020040e0700070107030402000b20022001106c20022802000d0620012802042002280204220c490d06200c417f4c0d0c024002400240200c0d004101210441010d010c090b200c102e2204450d012001280204200c490d0620042001280200200c109a05210f2001280204220d200c490d072001200d200c6b36020420012001280200200c6a360200200f450d080b200241206a41086a200241386a41086a290200370300200220022902383703202004410876210f4104210d200c210e201041ffffff0771200441187472221021110c080b200c41011037000b41002104200241003a0058200c417e6a210c03400240200e2004470d00200441ff0171450d07200241003a00580c070b200241386a20046a200d20046a220f41016a2d00003a00002001200c3602042001200f41026a3602002002200441016a220f3a0058200c417f6a210c200f2104200f4120470d000b2002200829000037032020022009290000370025200228004721122002280043210e200228003f210c2002280238211120022f013c210420022d003e210f200741026a200241356a41026a2d00003a0000200720022f00353b00002004200f41107472210f4100210d0c060b200241386a2001106b200228023c220c450d04200228024421122002280240210e200228023821114101210d0c050b200241386a2001106b200228023c220c450d03200228024421122002280240210e200228023821114102210d0c040b200241386a2001106b200228023c220c450d02200228024421122002280240210e200228023821114103210d0c030b2004102a0c010b200c200d1044000b200041003602000240200b450d002006210403400240024020042d0000220141034b0d0002400240024020010e0404000102040b2004410c6a280200450d03200441086a280200102a0c030b2004410c6a280200450d02200441086a280200102a0c020b2004410c6a280200450d01200441086a280200102a0c010b200441086a280200450d00200441046a280200102a0b200441246a2104200a415c6a220a0d000b0b2003450d072006102a0c070b200241106a41086a2213200241206a41086a290300370300200220022903203703100240200b2003470d0002400240200341016a22042003490d00200341017422142004201420044b1b2204ad42247e2215422088a70d002015a7221441004e0d010b1031000b0240024020030d002014102821060c010b2006200341246c2014102c21060b2006450d03200421030b2006200b41246c6a220420123600102004200e36000c2004200c3600082004200f3b0005200420113600012004200d3a0000200441076a200f4110763a0000200420022903103700142004411c6a2013290300370000200a41246a210a200b41016a2204210b20042005470d000b0b2000200336020420002006360200200041086a20043602000c040b201441041037000b200441041037000b1036000b200041003602000b200241e0006a24000bb906020c7f047e230041b0016b2202240020022001106c02400240024002400240024020022802000d00200128020441286e220341286c2204417f4c0d02200228020421050240024020040d00410821060c010b200410282206450d040b02402005450d00410021070340200241003a00a8012007220841016a210720012802042109417f210a4100210402400240024002400240034020092004460d0120024188016a20046a2001280200220b2d00003a000020012009200a6a3602042001200b41016a3602002002200441016a220c3a00a801200a417f6a210a200c2104200c4120470d000b200241e8006a41186a220420024188016a41186a290300370300200241e8006a41106a220a20024188016a41106a290300370300200241e8006a41086a220d20024188016a41086a29030037030020022002290388013703682009200c6b220c41074d0d01200b290001210e2001200b41096a3602002001200c41786a360204200241286a41086a200d290300220f370300200241286a41106a200a2903002210370300200241286a41186a20042903002211370300200241086a41086a220a200f370300200241086a41106a220c2010370300200241086a41186a2209201137030020022002290368220f3703282002200f37030820032008470d04200841017422042007200420074b1b2203ad42287e220f422088a70d0c200fa722044100480d0c20080d022004102821060c030b200441ff0171450d00200241003a00a8010b200241286a41186a200241c8006a41186a290300370300200241286a41106a200241c8006a41106a290300370300200241286a41086a200241c8006a41086a29030037030020022002290348370328200041003602002003450d062006102a0c060b2006200841286c2004102c21060b2006450d070b2006200841286c6a22042002290308370300200a290300210f200c2903002110200929030021112004200e370320200441186a2011370300200441106a2010370300200441086a200f37030020072005470d000b0b2000200336020420002006360200200041086a20053602000c010b200041003602000b200241b0016a24000f0b1036000b200441081037000b200441081037000b1031000bf80404097f027e027f017e230041d0006b2202240020022001106c024002400240024002400240024020022802000d00200128020441306e220341306c2204417f4c0d01200228020421050240024020040d00410821060c010b200410282206450d030b02402005450d00410021070340200128020422084110490d07200741016a21092001280200220a41086a290000210b200a290000210c2001200a41106a3602002001200841706a220d36020441002104200241003a00482008416f6a210803400240200d2004470d00200441ff0171450d09200241003a00480c090b200241286a20046a200a20046a220e41106a2d00003a0000200120083602042001200e41116a3602002002200441016a220e3a00482008417f6a2108200e2104200e4120470d000b200241086a41186a2208200241286a41186a290300370300200241086a41106a220e200241286a41106a290300370300200241086a41086a220a200241286a41086a29030037030020022002290328370308024020032007470d00200741017422042009200420094b1b2203ad42307e220f422088a70d07200fa722044100480d070240024020070d002004102821060c010b2006200741306c2004102c21060b2006450d060b2006200741306c6a2204200b3703082004200c37030020042002290308370310200441186a200a290300370300200441206a200e290300370300200441286a20082903003703002009210720092005470d000b0b2000200336020420002006360200200041086a20053602000c060b200041003602000c050b1036000b200441081037000b200441081037000b1031000b200041003602002003450d002006102a0b200241d0006a24000ba40303087f017e017f230041d0046b22022400200241086a2001106c02400240024002400240024020022802080d00200128020441a0026e220341a0026c2204417f4c0d02200228020c21050240024020040d00410821060c010b200410282206450d040b024002402005450d004100210741002104410021080340200241b0026a2001107a2002290398034203510d02200841016a2109200241106a200241b0026a41a002109a051a024020082003470d0020072009200720094b1b2203ad42a0027e220a422088a70d09200aa7220b4100480d090240024020080d00200b102821060c010b20062004200b102c21060b2006450d080b200620046a200241106a41a002109a051a200741026a2107200441a0026a21042009210820052009470d000b0b2000200336020420002006360200200041086a20053602000c020b2000410036020002402008450d0020064198016a210903402009106a200941a0026a2109200441e07d6a22040d000b0b2003450d012006102a0c010b200041003602000b200241d0046a24000f0b1036000b200441081037000b200b41081037000b1031000bae0c04047f017e097f067e23004180066b22022400200241286a2001106c02400240024002400240024020022802280d000240200228022c2203450d0003402003417f6a22030d000b0b20012802042203450d01200128020022042d0000210520012003417f6a3602042001200441016a36020002400240200541ff00714103470d0020054118744118754100480d01420221060c060b200042033703680c060b20024198046a200110a50120022d0098044102460d02200241f0036a41206a20024198046a41206a280200360200200241f0036a41186a20024198046a41186a290300370300200241f0036a41106a20024198046a41106a290300370300200241f0036a41086a20024198046a41086a29030037030020022002290398043703f00341002103200241003a00c00220012802042107417f2105024002400240034020072003460d0120024180026a20036a200128020022082d00003a00002001200720056a3602042001200841016a3602002002200341016a22043a00c0022005417f6a210520042103200441c000470d000b200241c0056a41386a220320024180026a41386a290300370300200241c0056a41306a220920024180026a41306a290300370300200241c0056a41286a220a20024180026a41286a290300370300200241c0056a41206a220b20024180026a41206a290300370300200241c0056a41186a220c20024180026a41186a290300370300200241c0056a41106a220d20024180026a41106a290300370300200241c0056a41086a220e20024180026a41086a29030037030020022002290380023703c005200441ff017141c000490d0520024180056a41386a220f200329030037030020024180056a41306a2009290300220637030020024180056a41286a200a290300221037030020024180056a41206a200b290300221137030020024180056a41186a200c290300221237030020024180056a41106a200d290300221337030020024180056a41086a200e2903002214370300200220022903c005221537038005200241c0046a41306a2006370300200241c0046a41286a2010370300200241c0046a41206a2011370300200241c0046a41186a2012370300200241c0046a41106a2013370300200241c0046a41086a2014370300200241c0046a41386a200f290300370300200220153703c00420072004460d05200831000121112001200720056a3602042001200841026a360200201150450d01420021060c020b200341ff0171450d04200241003a00c0020c040b2007417f6a2004460d03200831000221122001200841036a3602002001200720046b417e6a36020442022011420f838622104204540d034201210620124208862011844204882010420c882211420120114201561b7e221120105a0d030b200241206a2001106c20022802200d0220022802242105200241086a2001109f012002290308a70d02200241086a41106a290300211320022903102112200241e8026a41206a200241f0036a41206a280200360200200241e8026a41186a200241f0036a41186a290300370300200241e8026a41106a200241f0036a41106a290300370300200241e8026a41086a200241f0036a41086a29030037030020024194036a200241c0046a41086a2903003702002002419c036a200241c0046a41106a290300370200200241a4036a200241c0046a41186a290300370200200241ac036a200241c0046a41206a290300370200200241b4036a200241e8046a290300370200200241bc036a200241f0046a290300370200200241c4036a200241f8046a290300370200200220022903f0033703e802200220022903c00437028c0320024180026a200241e8026a41e800109a051a0c030b200042033703680c040b200042033703680c030b420221060b20024198016a20024180026a41e800109a051a024020064202520d00200042033703680c020b200241306a20024198016a41e800109a051a0b200241e8026a2001108101024020022802e8024113460d002000200241306a41e800109a0522034188016a201337030020034180016a201237030020034190016a2005360200200341f8006a2011370300200320103703702003200637036820034198016a200241e8026a418801109a051a0c010b200042033703680b20024180066a24000bfb1002147f037e230041c0026b22022400200241086a2001106c0240024020022802080d000240200128020441c4006e220341c4006c2204417f4c0d00200228020c210502400240024020040d00410421060c010b200410282206450d010b024002402005450d0020024198026a410772210741002108034002400240024002400240024020012802042209450d002001280200220a2d0000210420012009417f6a220b3602042001200a41016a360200200441014b0d000240024020040e020001000b200b41034d0d01200a280001210c20012009417b6a3602042001200a41056a360200200241d4016a41026a200241d8016a41026a2d00003a0000200241b8016a41086a200241f8016a41086a290200370300200241b8016a41106a200241f8016a41106a290200370300200241b8016a41186a200241f8016a41186a2d00003a000020024198016a41086a20024198026a41086a29010037030020024198016a41106a20024198026a41106a29010037030020024198016a41186a20024198026a41186a290100370300200220022f00d8013b01d401200220022902f8013703b801200220022901980237039801200220022f01f4013b0196014100210d0c030b4100210e200241003a00b8022009417e6a210d03400240200b200e2204470d000240200441ff0171450d00200241003a00b8020b4102210d0c040b20024198026a20046a200a20046a220e41016a2d00003a00002001200d3602042001200e41026a3602002002200441016a220e3a00b802200d417f6a210d200e4120470d000b200241f4016a41026a220f20022d009a023a0000200241d8016a41086a2210200741086a290000370300200241d8016a41106a2211200741106a290000370300200241d8016a41186a2212200741186a2d00003a0000200220022f0198023b01f401200220072900003703d801200b200e460d01200228009b022113200a200e6a220a41016a2d0000210b2001200d3602042001200a41026a360200200b41014b0d014100211402400240200b0e020100010b4100210d200241003a00b802200e20096b41026a210b200920046b417c6a210403400240200b200d6a0d00200d41ff0171450d04200241003a00b8020c040b20024198026a200d6a200a200d6a220e41026a2d00003a0000200120043602042001200e41036a3602002002200d41016a220e3a00b8022004417f6a2104200e210d200e4120470d000b200241f8016a41186a20024198026a41186a290300370300200241f8016a41106a20024198026a41106a290300370300200241f8016a41086a20024198026a41086a29030037030020022002290398023703f801410121140b20024198016a41186a200241f8016a41186a29030037030020024198016a41106a200241f8016a41106a29030037030020024198016a41086a200241f8016a41086a290300370300200241d4016a41026a200f2d00003a0000200241b8016a41086a2010290300370300200241b8016a41106a2011290300370300200241b8016a41186a20122d00003a0000200220022903f80137039801200220022f01f4013b01d401200220022903d8013703b8014101210d201421152013210c0c020b20024192016a41026a200241d4016a41026a2d00003a0000200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a200241b8016a41106a290300370300200241f8006a41186a200241b8016a41186a2d00003a0000200241d8006a41086a20024198016a41086a290300370300200241d8006a41106a20024198016a41106a290300370300200241d8006a41186a20024198016a41186a290300370300200220022f01d4013b019201200220022903b8013703782002200229039801370358200220022f0196013b01560c020b4102210d0b20024192016a41026a2204200241d4016a41026a2d00003a0000200241f8006a41086a220a200241b8016a41086a290300370300200241f8006a41106a220b200241b8016a41106a290300370300200241f8006a41186a2209200241b8016a41186a2d00003a0000200241d8006a41086a220f20024198016a41086a290300370300200241d8006a41106a221020024198016a41106a290300370300200241d8006a41186a221120024198016a41186a290300370300200220022f01d4013b019201200220022903b8013703782002200229039801370358200220022f0196013b0156200d4102460d00200841016a210e200241d2006a41026a221220042d00003a0000200241386a41086a2213200a290300370300200241386a41106a220a200b290300370300200241386a41186a220b20092d00003a0000200241186a41086a2209200f290300370300200241186a41106a220f2010290300370300200241186a41186a22102011290300370300200220022f0192013b01522002200229037837033820022002290358370318200220022f01563b011620032008470d02024020084101742204200e2004200e4b1b2203ad42c4007e2216422088a70d002016a7220441004e0d020b1031000b200041003602002003450d082006102a0c080b0240024020080d002004102821060c010b2006200841c4006c2004102c21060b2006450d030b2006200841c4006c6a2204200d3a00002004200c360004200441036a20122d00003a0000200420022f01523b0001200b2d0000210d200a29030021162013290300211720022903382118200420153a002120042018370008200441106a2017370000200441186a2016370000200441206a200d3a00002004413a6a2010290300370000200441326a200f2903003700002004412a6a200929030037000020042002290318370022200420022f01163b0042200e2108200e2005470d000b0b2000200336020420002006360200200041086a20053602000c040b200441041037000b200441041037000b1036000b200041003602000b200241c0026a24000baf04010a7f230041d0006b2202240020022001106c0240024002400240024020022802000d00200128020422034160712204417f4c0d022002280204210502400240200341057622060d00410121070c010b200410282207450d040b02402005450d00410021080340200241003a00482008220941016a21082001280204417f6a21034100210402400240024003402003417f460d01200241286a20046a2001280200220a2d00003a0000200120033602042001200a41016a3602002002200441016a220a3a00482003417f6a2103200a2104200a4120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a220a200241286a41106a290300370300200241086a41086a220b200241286a41086a2903003703002002200229032837030820062009470d020240200941017422032008200320084b1b220641ffffff3f712006470d002006410574220341004e0d020b1031000b0240200441ff0171450d00200241003a00480b200041003602002006450d052007102a0c050b0240024020090d002003102821070c010b200720094105742003102c21070b2007450d070b200720094105746a22032002290308370000200341186a2004290300370000200341106a200a290300370000200341086a200b29030037000020082005470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241d0006a24000f0b1036000b200441011037000b200341011037000bb005020c7f037e230041f0006b2202240020022001106c0240024002400240024020022802000d00200128020441246e220341246c2204417f4c0d02200228020421050240024020040d00410421060c010b200410282206450d040b02402005450d00410021070340200241003a00682007220841016a210720012802042109417f210a410021040240024002400240034020092004460d01200241c8006a20046a2001280200220b2d00003a000020012009200a6a3602042001200b41016a3602002002200441016a220c3a0068200a417f6a210a200c2104200c4120470d000b200241286a41186a2204200241c8006a41186a290300370300200241286a41106a220a200241c8006a41106a290300370300200241286a41086a220d200241c8006a41086a290300370300200220022903483703282009200c6b220c4104490d01200b28000121092001200b41056a3602002001200c417c6a360204200241086a41086a220c200d290300370300200241086a41106a220b200a290300370300200241086a41186a220a20042903003703002002200229032837030820032008470d030240200841017422042007200420074b1b2203ad42247e220e422088a70d00200ea7220441004e0d030b1031000b200441ff0171450d00200241003a00680b200041003602002003450d052006102a0c050b0240024020080d002004102821060c010b2006200841246c2004102c21060b2006450d070b2006200841246c6a22042002290308370200200c290300210e200b290300210f200a290300211020042009360220200441186a2010370200200441106a200f370200200441086a200e37020020072005470d000b0b2000200336020420002006360200200041086a20053602000c010b200041003602000b200241f0006a24000f0b1036000b200441041037000b200441041037000be60403087f017e017f230041f0016b22022400200241086a2001106c02400240024002400240024020022802080d00200128020441f0006e220341f0006c2204417f4c0d02200228020c21050240024020040d00410421060c010b200410282206450d040b024002402005450d00410021074100210841002109034020024180016a2001107f200228028401450d02200941016a2104200241106a20024180016a41f000109a051a024020092003470d0020072004200720044b1b2203ad42f0007e220a422088a70d09200aa7220b4100480d090240024020090d00200b102821060c010b20062008200b102c21060b2006450d080b200620086a200241106a41f000109a051a200741026a2107200841f0006a21082004210920052004470d000b0b2000200336020420002006360200200041086a20053602000c020b2000410036020002402009450d00200620086a210120062107034002402007410c6a2802002209450d0020072802042104200941246c210903400240024020042d0000220841034b0d0002400240024020080e0404000102040b2004410c6a280200450d03200441086a280200102a0c030b2004410c6a280200450d02200441086a280200102a0c020b2004410c6a280200450d01200441086a280200102a0c010b200441086a280200450d00200441046a280200102a0b200441246a21042009415c6a22090d000b0b200741f0006a21040240200741086a280200450d002007280204102a0b2004210720012004470d000b0b2003450d012006102a0c010b200041003602000b200241f0016a24000f0b1036000b200441041037000b200b41041037000b1031000b9f0a03077f037e057f230041d0026b2202240041002103200241003a00c8022001280204417f6a210402400240024003402004417f460d01200241a8026a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00c8022004417f6a21042005210320054120470d000b200241e8006a41086a200241a8026a41086a290300370300200241e8006a41106a200241a8026a41106a290300370300200241e8006a41186a200241a8026a41186a290300370300200220022903a80237036820022001106c2002280200450d01200041003602040c020b0240200341ff0171450d00200241003a00c8020b200041003602040c010b2002280204210641002104200241003a00c80220012802042107417f21030240034020072004460d01200241a8026a20046a200128020022082d00003a00002001200720036a3602042001200841016a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241a8016a41086a200241a8026a41086a2903002209370300200241a8016a41106a200241a8026a41106a290300220a370300200241a8016a41186a200241a8026a41186a290300220b37030020024188016a41086a200937030020024188016a41106a200a37030020024188016a41186a200b370300200220022903a80222093703a801200220093703880141002104200241003a00c802200720056b210c200720036a210303400240200c2004470d000240200441ff0171450d00200241003a00c8020b200041003602040c030b200241a8026a20046a200820046a220541016a2d00003a0000200120033602042001200541026a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241e8016a41086a200241a8026a41086a2903002209370300200241e8016a41106a200241a8026a41106a290300220a370300200241e8016a41186a200241a8026a41186a290300220b370300200241c8016a41086a22042009370300200241c8016a41106a2203200a370300200241c8016a41186a2205200b370300200220022903a80222093703e801200220093703c801200241a8026a20011076024020022802a8022201450d00200241c8006a41086a2208200241e8006a41086a290300370300200241c8006a41106a2207200241e8006a41106a290300370300200241c8006a41186a220c200241e8006a41186a290300370300200241286a41086a220d20024188016a41086a290300370300200241286a41106a220e20024188016a41106a290300370300200241286a41186a220f20024188016a41186a29030037030020022002290368370348200220022903880137032820022902ac022109200241086a41186a22102005290300370300200241086a41106a22052003290300370300200241086a41086a22032004290300370300200220022903c801370308200020093702082000200136020420002006360200200041106a2002290348370200200041186a2008290300370200200041206a2007290300370200200041286a200c290300370200200041306a2002290328370200200041386a200d290300370200200041c0006a200e290300370200200041c8006a200f290300370200200041e8006a2010290300370200200041e0006a2005290300370200200041d8006a2003290300370200200041d0006a20022903083702000c020b200041003602040c010b0240200441ff0171450d00200241003a00c8020b200041003602040b200241d0026a24000b9505020c7f017e230041b0056b22022400200241086a2001106c0240024002400240024020022802080d0020012802044190016e22034190016c2204417f4c0d02200228020c21050240024020040d00410821060c010b200410282206450d040b02402005450d00200241a0036a410472210741002108410021044100210903400240024002402001280204220a450d002001280200220b2d0000210c2001200a417f6a3602042001200b41016a360200200c41014b0d004113210a024002400240200c0e020100010b200241a8046a200110810120022802a8044113460d02200241a0036a200241a8046a418801109a051a2001280204220c4104490d012001280200220a280000210d2001200c417c6a3602042001200a41046a36020020022802a003210a2002419c026a2007418401109a051a200a4113460d0220024198016a2002419c026a418401109a051a200a4114460d020b200941016a210c200241146a20024198016a418401109a051a20092003470d0302402008200c2008200c4b1b2203ad4290017e220e422088a70d00200ea7220b41004e0d030b1031000b200241a0036a106a0b2000410036020002402009450d00200621010340024020012802004113460d002001106a0b20014190016a2101200441f07e6a22040d000b0b2003450d052006102a0c050b0240024020090d00200b102821060c010b20062004200b102c21060b2006450d070b200620046a2209200a360200200941046a200241146a418401109a051a20094188016a200d360200200841026a210820044190016a2104200c21092005200c470d000b0b2000200336020420002006360200200041086a20053602000c010b200041003602000b200241b0056a24000f0b1036000b200441081037000b200b41081037000bf3910107087f017e067f087e087f017e017f230041f0096b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200200541144b0d16200141046a210720050e150102030405060708090a0b0c0d0e0f101112131415010b200041133602000c4c0b02402006450d0020042d0001210620012003417e6a22083602042001200441026a360200200641054b0d004101210902400240024002400240024020060e06510001020304510b20022001106c20022802000d05200128020420022802042204490d052004417f4c0d1e02400240024020040d00410121050c010b2004102e2205450d0120072802002004490d06200520012802002004109a051a200128020422032004490d212001200320046b3602042001200128020020046a3602000b2005450d062004ad220a422086200a84210a410221090c510b200441011037000b20084108490d042004290002210a2001200341766a36020420012004410a6a360200410321090c4f0b200241086a2001106c20022802080d032001280204200228020c2204490d032004417f4c0d1c02400240024020040d00410121050c010b2004102e2205450d0120072802002004490d04200520012802002004109a051a200128020422032004490d202001200320046b3602042001200128020020046a3602000b2005450d042004ad220a422086200a84210a410421090c4f0b200441011037000b200241206a2001106c20022802200d02200728020041186e220b41186c2204417f4c0d1b2002280224210c0240024020040d00410421050c010b200410282205450d1f0b0240200c450d004100210d41002106410021080340200241186a2001106c02400240024020022802180d002001280204200228021c2204490d002004417f4c0d2002400240024020040d004101210e0c010b2004102e220e450d3920072802002004490d01200e20012802002004109a051a200128020422032004490d262001200320046b3602042001200128020020046a3602000b200241106a2001106c024020022802100d00200128020420022802142203490d002003417f4c0d22024002400240024020030d004101210f0c010b2003102e220f450d0120072802002003490d02200f20012802002003109a051a200128020422092003490d2a2001200920036b3602042001200128020020036a3602000b200841016a21092008200b470d06200d2009200d20094b1b220bad42187e220a422088a70d55200aa7221041004e0d050c550b200341011037000b200f102a0b2004450d010b200e102a0b02402008450d002005210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141186a2101200641686a22060d000b0b200b0d050c060b0240024020080d002010102821050c010b200520062010102c21050b2005450d240b200520066a2208200e360200200841146a2003ad220a3e02002008410c6a200a422086200fad84370200200841046a2004ad220a422086200a84370200200d41026a210d200641186a210620092108200c2009470d000b0b2005450d02200cad422086200bad84210a410521090c4d0b200241306a2001106c20022802300d012007280200410c6e220e410c6c2204417f4c0d1a2002280234210f0240024020040d00410421050c010b200410282205450d220b024002400240200f450d004100210841002103410021090340200241286a2001106c20022802280d032001280204200228022c2204490d032004417f4c0d1e0240024020040d004101210d0c010b2004102e220d450d3720072802002004490d03200d20012802002004109a051a200128020422062004490d272001200620046b3602042001200128020020046a3602000b200941016a210602402009200e470d0020082006200820064b1b220ead420c7e220a422088a70d50200aa7220b4100480d500240024020090d00200b102821050c010b20052003200b102c21050b2005450d280b200520036a2209200d360200200941086a2004360200200941046a2004360200200841026a21082003410c6a210320062109200f2006470d000b0b2005450d03200fad422086200ead84210a410621090c4e0b200d102a0b02402009450d002005210103400240200141046a280200450d002001280200102a0b2001410c6a2101200341746a22030d000b0b200e450d010b2005102a0b200041133602000c4b0b02402006450d0020012003417e6a3602042001200441026a3602000b200041133602000c4a0b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241386a2001109e012002290338a70d002002290340210a20004102360200200041086a200a370300200041106a200241e8086a41f800109a051a0c4a0b200041133602000c490b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e0076a2001107e20022802e00722010d130b200041133602000c480b02402006450d0020012003417e6a3602042001200441026a3602000b200041133602000c470b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541024b0d00024002400240024020050e03000102000b200241e8086a200110a50120022d00e8084102460d0320024184096a290200210a200241fc086a2902002111200241e8086a41106a2802002107200241f4086a2802002104200241f0086a280200210320022802ec08210520022802e8082106200241c8006a2001109f0120022802480d03200241c8006a41106a290300211241012101200229035021130c020b200241e8086a200110a50120022d00e8084102460d02200241e0076a41086a20024180096a290300370300200241e0076a41106a20024188096a2802003602002002200241e8086a41106a2903003703e007200241f4086a2802002104200241e8086a41086a280200210320022802ec08210520022802e8082106200241f8006a2001109f012002290378a70d02200241f8006a41106a29030021122002290380012113200241e0006a2001109f012002290360a70d02200241e0006a41106a290300211420022903682115200241a8056a41106a200241e0076a41106a280200360200200241a8056a41086a200241e0076a41086a290300370300200220022903e00722163703a805200241b4056a290200210a20022902ac0521112016a7210741022101420021160c010b200241e8086a200110a50120022d00e8084102460d0120024184096a290200210a200241fc086a2902002111200241e8086a41106a22092802002107200241f4086a2802002104200241e8086a41086a2208280200210320022802ec08210520022802e8082106200241e8086a200110a50120022d00e8084102460d01200241e0076a41206a220d200241e8086a41206a280200360200200241e0076a41186a220e200241e8086a41186a290300370300200241e0076a41106a2009290300370300200241e0076a41086a2008290300370300200220022903e8083703e00720024190016a2001109f01200229039001a70d0120024190016a41106a29030021172002290398012118200241e8076a2903002112200241f0076a2903002115200e2903002114200d350200211620022903e0072113410321010b20004105360200200041e0006a2017370200200041d8006a2018370200200041c8006a2014370200200041c0006a2015370200200041386a2012370200200041306a2013370200200041286a200a370200200041206a2011370200200041d0006a20163702002000411c6a2007360200200041186a2004360200200041146a2003360200200041106a20053602002000410c6a2006360200200041086a2001360200200041e8006a200229038806370300200041f0006a20024188066a41086a290300370300200041f8006a20024188066a41106a29030037030020004180016a20024188066a41186a2903003703000c470b200041133602000c460b2006450d4120042d0001210520012003417e6a22193602042001200441026a3602002005410c4b0d41410421104100211a4100211b02400240024002400240024002400240024002400240024020050e0d0001024e030405060708090a0b000b200241e0076a200110a50120022d00e0074102460d4c200241ec076a290200211120024180086a280200210b200241ff076a2d00002108200241fe076a2d0000210d200241fd076a2d0000210c200241f9076a2800002104200241f5076a280000210f200241f4076a2d0000210e20022902e407210a20022802e0072106200241a8016a2001109f0120022903a801a70d4c20072802002203450d4c200241b8016a290300211320022903b0012112200128020022052d0000210920012003417f6a360204410121102001200541016a36020020094103492201450d4c200441807e71410020011b211b2004410020011b211a0c4d0b200241c0016a2001109f0120022903c001a70d4b200241d0016a290300211120022903c801210a410221104100211b0c4c0b200241d8016a2001109f0120022903d801a70d4a200241e8016a290300211120022903e001210a410321104100210c4100211a4100211b0c4b0b200241f0016a2001109f0120022903f001a70d4920024180026a290300211120022903f801210a410521104100211b0c4a0b20024188026a2001106c2002280288020d48200728020041246e221c41246c2204417f4c0d19200228028c02211d0240024020040d00410421060c010b200410282206450d240b0240201d450d0041232105200241f0076a211e41002107410021040340200241e0076a200110a501024020022d00e00722094102470d00201c450d4b2006102a0c4b0b200441016a2103201e290300210a20022903e807211120022d008308210820022d008208210d20022d008108210e20022800fd07210f20022800f907210b20022d00f807210c20022802e407211020022d00e307211b20022d00e207211920022d00e107211f02402004201c470d0020072003200720034b1b221cad42247e2212422088a70d4d2012a722204100480d4d0240024020040d002020102821060c010b20062005415d6a2020102c21060b2006450d270b200620056a220420083a0000200441656a2208200a370008200820113700002004417f6a200d3a00002004417e6a200e3a00002004417a6a200f360000200441766a200b360000200441756a200c3a0000200441616a2010360000200441606a201b3a00002004415f6a20193a00002004415e6a201f3a00002004415d6a20093a0000200741026a2107200541246a210520032104201d2003470d000b0b2006450d48201dad422086201cad84210a42002111410621104100211b0c490b410721104100211b0c480b2019450d4620042d0002210920012003417d6a3602042001200441036a360200200941034f0d46410821104100211b0c470b200241e0076a200110a50120022d00e0074102460d45200241f9076a280000221a41807e71211b200241ec076a290200211120024180086a280200210b200241ff076a2d00002108200241fe076a2d0000210d200241fd076a2d0000210c200241f5076a280000210f200241f4076a2d0000210e20022902e407210a20022802e0072106410921100c460b20024190026a2001106c2002280290020d442002280294022106410a21104100211b0c450b410b21104100211b0c440b410c21104100211b0c430b200241e0076a2001106d20022802e0072206450d4120022902e407210a42002111410d21104100211b0c420b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e8086a200110e80120022d00e8084101460d00200241e0076a200241e8086a41017241e000109a051a20024198026a2001106c2002280298020d002001280204200228029c022204490d002004417f4c0d12024002400240024020040d004101210341010d010c040b2004102e2203450d0120072802002004490d02200320012802002004109a052105200128020422062004490d212001200620046b3602042001200128020020046a3602002005450d030b20024188066a200241e0076a41e000109a051a200241a8056a20024188066a41e000109a051a2000410c6a2004360200200041086a20043602002000200336020420004107360200200041106a200241a8056a41e000109a051a20004180016a20024188076a41106a290300370300200041f8006a20024188076a41086a290300370300200041f0006a2002290388073703000c470b200441011037000b2003102a0b200041133602000c440b2006450d3e20042d0001210520012003417e6a221d3602042001200441026a360200200541104b0d3e410e211a4100211c024002400240024002400240024002400240024002400240024002400240024020050e11000102030405060708090a0b0c4d0d0e0f000b200241e0076a200110810120022802e0074113460d4d200241e8086a200241e0076a418801109a051a41880110282206450d382006200241e8086a418801109a052104200241a0026a2001109f01024020022903a002a7450d002004106a2004102a0c4e0b200241b0026a290300210a2004411876211c20022903a8022211422088a7211f2011a7211b4101211a0c4c0b200241b8026a2001106c20022802b8020d4c20022802bc022206411876211c4102211a0c4a0b200241c0026a2001106c20022802c0020d4b20072802002204450d4b20022802c4022106200128020022052d0000210320012004417f6a3602042001200541016a360200200341ff0071220d41064b0d4b2006411876211c200341077621084103211a0c480b200241c8026a2001106c20022802c8020d4a20072802002204450d4a20022802cc022106200128020022052d0000210320012004417f6a3602042001200541016a360200200341ff0071220d41064b0d4a2006411876211c200341077621084104211a0c470b201d4104490d492004280002210620012003417a6a3602042001200441066a3602002006411876211c4105211a0c470b200241e0076a200110810120022802e0074113460d48200241e8086a200241e0076a418801109a051a41880110282206450d342006200241e8086a418801109a05411876211c4106211a0c460b200241e0076a200110810120022802e0074113460d47200241e8086a200241e0076a418801109a051a41880110282206450d342006200241e8086a418801109a05411876211c4107211a0c450b200241e0076a200110810120022802e0074113460d46200241e8086a200241e0076a418801109a051a41880110282206450d342006200241e8086a418801109a05411876211c4108211a0c440b41002105200241003a0088092003417e6a2109417d21060340024020092005470d00200541ff0171450d47200241003a0088090c470b200241e8086a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a0088092006417f6a21062007210520074120470d000b200241b0056a2205200241f1086a290000370300200241a8056a41106a200241f9086a290000370300200241bf056a220620024180096a290000370000200220022900e908220a3703a805200320076b2203417e6a4104490d4520022d00ac05210920022f01aa05210d200241b5056a330000211120023500b105211220052d0000211b20022f01ae05211a200241bd056a3100002113200241bb056a330000211620023500b705211820022d00e80821082006280000210f20022d00ad05211c20022d00a905211020022800c305210b20022d00be05210e200420076a220441026a280000210c20012003417a6a22053602042001200441066a220736020020054104490d45200d2009411074722106200aa7210d200728000021192001200341766a36020420012004410a6a36020020182016201342108684422086844208862012201142208684221142ffffffffffff3f83221242288884210a2012421886201a201b41107472ad42ffffff078384a7211b2011420888a7211f4109211a0c440b41002105200241003a0088092003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d46200241003a0088090c460b200241e8086a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0088092003417f6a21032006210520064120470d000b200241b0056a200241f1086a290000370300200241bf056a220120024180096a290000370000200241a8056a41106a200241f9086a290000370300200220022900e90822113703a80520022f01aa0520022d00ac0541107472210620022901ae052212422088a7211f20022d00e80821082001280000210f200241b6056a290100210a20022d00ad05211c20022d00a905211020022800c305210b20022d00be05210e2011a7210d2012a7211b410a211a0c430b200241d0026a2001106c20022802d0020d4320022802d4022206411876211c410b211a0c410b200241e8026a2001106c20022802e8020d4220022802ec022106200241e0026a2001106c20022802e0020d4220022802e402211b200241d8026a2001106c20022802d8020d4220022802dc02211f2006411876211c410c211a0c410b41002105200241003a0088092003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d43200241003a0088090c430b200241e8086a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0088092003417f6a21032006210520064120470d000b200241b0056a200241f1086a290000370300200241bf056a220120024180096a290000370000200241a8056a41106a200241f9086a290000370300200220022900e90822113703a80520022f01aa0520022d00ac0541107472210620022901ae052212422088a7211f20022d00e80821082001280000210f200241b6056a290100210a20022d00ad05211c20022d00a905211020022800c305210b20022d00be05210e2011a7210d2012a7211b410d211a0c400b41002105200241003a0088092003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d42200241003a0088090c420b200241e8086a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0088092003417f6a21032006210520064120470d000b200241b0056a2201200241f1086a290000370300200241a8056a41106a200241f9086a290000370300200241bf056a220420024180096a290000370000200220022900e90822123703a80520023500b705200241bb056a330000200241bd056a310000421086844220868442088620023500b105200241b5056a33000042208684221142288884210a201142188620023301ae0520013100004210868484a7211b20022f01aa0520022d00ac054110747221062011420888a7211f20022d00e80821082004280000210f20022d00ad05211c20022d00a905211020022800c305210b20022d00be05210e2012a7210d410f211a0c3f0b41002105200241003a0088092003417e6a21092003417d6a21060340024020092005470d00200541ff0171450d41200241003a0088090c410b200241e8086a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a0088092006417f6a21062007210520074120470d000b200241b0056a200241f1086a290000370300200241b8056a200241f9086a290000370300200241bf056a220520024180096a290000370000200220022900e908220a3703a805200241d8076a41046a20022d00ac053a0000200241e8066a41046a200241b5056a2f00003b01002002200a3e02d807200220022800b1053602e8062003417e6a2007460d3f20022d00e808210820022800ad05211c2005290000211120022900b705210a200420076a220441026a2d00002109200120063602042001200441036a360200200941064b0d3f20024190076a200241e8066a41046a2f01003b0100200220022802d807220d3602d007200220022802e80636028c072002201c360288072002200a37019207200a423888201142088684a7210e4110211a20022f01d207200241d8076a41046a2d00004110747221062011422088a7210b2002290089072212422088a7211f20024191076a290000210a20022d00d10721102011a7210f2012a7211b0c3e0b4111211a0c3d0b200241e0076a200110e90120022d00e0074105470d0d200041133602000c420b200241e0076a200110e90120022d00e0074105470d0d200041133602000c410b2006450d3720042d0001210520012003417e6a3602042001200441026a360200200541094b0d37024002400240024002400240024002400240024020050e0a00010203040506070809000b200241e0076a2001107520022802e0072204450d40200241e8076a280200210520022802e4072103200241f0026a2001106c024020022802f002450d0020030d400c410b0240200728020022094104490d0020022802f402210620012802002208280000210720012009417c6a220d3602042001200841046a360200200d4110490d002008410c6a29000021122008290004211320012009416c6a3602042001200841146a360200410121010c3f0b20030d3f0c400b200241e0076a2001107520022802e0072204450d3f200241e8076a280200210520022802e4072103200241f8026a2001106c024020022802f802450d002003450d400c3f0b0240200728020022094104490d0020022802fc02210620012802002208280000210720012009417c6a220d3602042001200841046a360200200d4110490d002008410c6a29000021122008290004211320012009416c6a3602042001200841146a360200410221010c3e0b20030d3e0c3f0b20024190036a2001106c2002280290030d3e2002280294032104200241e0076a200110a50120022d00e0074102460d3e20024188066a41086a200241f8076a29030037030020024188066a41106a20024180086a2802003602002002200241e0076a41106a29030037038806200241ec076a2802002107200241e0076a41086a280200210620022802e407210520022802e007210320024188036a2001106c2002280288030d3e200228028c03210920024180036a2001106c2002280280030d3e20024198066a280200210820024190066a29030021122002290388062113200228028403ad210a42002111410321010c3c0b20024198036a2001106c2002280298030d3d41042101200228029c0321040c3b0b200241a0036a2001106c20022802a0030d3c4105210120022802a40321040c3a0b200241e0076a200110a50120022d00e0074102460d3b20024188066a41086a200241f8076a29030037030020024188066a41106a20024180086a2802003602002002200241e0076a41106a29030037038806200241e0076a41086a290300211620022903e0072118200241b0036a2001109f0120022903b003a70d3b200241b0036a41106a290300211120022903b803210a200241a8036a2001106c20022802a8030d3b20022802ac032108200241a8056a41106a20024188066a41106a280200360200200241a8056a41086a20024188066a41086a290300370300200220022903880622173703a8052018422088a721032016422088a72106200241b4056a290200211220022902ac0521132017a721072018a721042016a72105410621010c390b200241c8036a2001106c20022802c8030d3a4107210120022802cc0321040c380b200241e0076a200110a50120022d00e0074102460d39200241fc076a2902002112200241f4076a2902002113200241f0076a2802002107200241ec076a280200210641082101200241e0076a41086a280200210520022802e407210320022802e00721040c370b200241d0036a2001106c20022802d0030d384109210120022802d40321040c360b200241d8036a2001106c20022802d8030d37410a210120022802dc0321040c350b2006450d3320042d0001210520012003417e6a3602042001200441026a360200200541034b0d33024002400240024020050e0400010203000b41002105200241003a0080082003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d38200241003a0080080c380b200241e0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0080082003417f6a21032006210520064120470d000b200241a8056a41106a200241f1076a290000370300200241b0056a200241e0076a41096a290000220a370300200241bf056a2201200241e0076a41186a290000370000200241e8066a41096a200a370000200241e8066a41106a200241b7056a290000370000200220022d00e007220d3a00e806200220022900e1073700e9062001280000210f20022800c305210b20022800ef06220c411876211020022800eb062201411876210820022d00ff06211b20022900f706211220022800f306211a20022d00ea06211920022d00e906211f4101211c0c350b41002105200241003a0080082003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d37200241003a0080080c370b200241e0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0080082003417f6a21032006210520064120470d000b200241b0056a200241e9076a290000370300200241bf056a2204200241e0076a41186a290000370000200241a8056a41106a200241f1076a290000370300200220022900e107220a3703a80520022f01aa0520022d00ac0541107472210120022901ae052211a7220c41187621102011422088a7211a20022d00e007210d2004280000210f200241b6056a290100211220022d00ad05210820022d00a905211920022800c305210b20022d00be05211b200aa7211f4102211c0c340b41002105200241003a008008410220036b21092003417d6a210603400240200920056a0d00200541ff0171450d36200241003a0080080c360b200241e0076a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a0080082006417f6a21062007210520074120470d000b200241b0056a200241e9076a290000370300200241b8056a200241f1076a290000370300200241bf056a2205200241f8076a290000370000200220022900e107220a3703a805200241d8076a41046a20022d00ac053a0000200241e8066a41046a200241b5056a2f00003b01002002200a3e02d807200220022800b1053602e80620022d00e007210d20022800ad0521082005290000211320022900b705211241002105200241003a008008200420076a2109200720036b41026a210303400240200320056a0d00200541ff0171450d36200241003a0080080c360b200241e0076a20056a200920056a220441026a2d00003a0000200120063602042001200441036a3602002002200541016a22043a0080082006417f6a21062004210520044120470d000b200241bf056a2201200241f8076a290000370000200241a8056a41106a200241f1076a290000370300200241a8056a41086a2203200241e9076a290000370300200220022900e10722163703a80520022d00e007210420012800002109200241bb056a3300002111200241bd056a3100002118200241b5056a330000210a2003310000211720022801aa05210620022d00a905210520022800c305210e20022d00be05210720023500b705211520023500b105211420023301ae052121200241d0076a41046a2201200241d8076a41046a2d00003a0000200220022802d8073602d007200220083602880720024188076a41086a200241e8066a41046a2f01003b0100200220022802e80636028c0720022012370192072002419a076a20133701002014200a422086842214421886202120174210868484210a201520112018421086844220868442088620144228888421112012423888201342088684a7211b2008410876210c20022f01d20720012d00004110747221012013422088a7210b2002290091072112200228008d07211a20022d008c07211020022d00d107211920022d00d007211f2016a721032013a7210f4103211c0c330b200241e0076a2001106d20022802e0072201450d3320022802e407220c411876211020014118762108200241e8076a280200211a4104211c0c320b024002402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e0036a2001106c20022802e003450d010b200041133602000c3f0b20022802e40321012000410d36020020002001360204200041086a200241e8086a418001109a051a0c3e0b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e8036a2001106c20022802e8030d00200128020420022802ec032204490d002004417f4c0d0b024002400240024020040d00410121030c010b2004102e2203450d0120072802002004490d02200320012802002004109a051a200128020422052004490d1b2001200520046b3602042001200128020020046a3602000b2003450d02200020033602042000410e360200200041086a2004ad220a422086200a84370200200041106a200241e8086a41f800109a051a0c400b200441011037000b2003102a0b200041133602000c3d0b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541024b0d0002400240024020050e03000102000b200241f0036a2001109f0120022903f003a70d0220024180046a290300210a20022903f8032111200241e0076a200110a50120022d00e0074102460d02200241fc076a2902002112200241f4076a2902002113200241f0076a2802002101200241ec076a2802002104200241e8076a280200210320022802e407210520022802e0072106410121070c310b20024188046a2001106c2002280288040d0141022107200228028c0421060c300b20024190046a2001106c2002280290040d004103210720022802940421060c2f0b200041133602000c3c0b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541044b0d0002400240024002400240024002400240024020050e050001020607000b200241e8086a200110ea0120022d00d8094102460d08200241e8076a20024198096a290300370300200241f0076a200241a0096a29030037030020022002290390093703e0072002418c096a280200210b20024184096a2802002104200241fd086a2800002108200241f9086a280000210d200228028809211b20022d008309210520022d008209210620022d008109210f20022d00f808210e20022903f008210a20022903e8082111200241d8096a2903002113200241b8096a2903002116200241c5096a2800002101200241c1096a280000210320022903d009211820022903b009211720022802cc09210720022d00cb09210c20022d00ca09211f20022d00c909211c20022d00c009211d20022903a8092112410121220c020b200241a0046a2001109e0120022903a004a70d0720022903a804210a20024198046a2001106c2002280298040d072001280204200228029c042204490d072004417f4c0d1002400240024020040d00410121090c010b2004102e2209450d0120072802002004490d08200920012802002004109a051a200128020422032004490d202001200320046b3602042001200128020020046a3602000b2009450d082004ad22114220862011842111200241e0076a41106a200241e8086a41106a290300370300200241e0076a41086a200241e8086a41086a290300370300200220022903e8083703e007410221220c350b200441011037000b200241e8086a200110a50120022d00e8084102460d06200241f4086a290200210a20024188096a280200210420024187096a2d0000210520024186096a2d0000210620024185096a2d0000210f20024181096a2800002108200241fd086a280000210d200241fc086a2d0000210e20022902ec08211120022802e8082109200241c8046a2001109f0120022903c804a70d06200241d8046a290300211320022903d0042116200241b8046a2001109e0120022903b804a70d0620022903c0042112200241b0046a2001106c20022802b0040d06200128020420022802b404220b490d06200b417f4c0d0f02400240200b0d004101211b41010d010c080b200b102e221b450d022007280200200b490d03201b2001280200200b109a05210320012802042207200b490d1f20012007200b6b36020420012001280200200b6a3602002003450d070b200241f0076a2013370300200220163703e8072002200b3602e007410321220b0c320b200b41011037000b201b102a0c030b200241f8046a2001109f0120022903f804a70d0220024188056a290300210a2002290380052111200241e8046a2001109e0120022903e804a70d0220022903f004211241002103200241003a0088092007280200417f6a21040240024002400240024003402004417f460d01200241e8086a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a0088092004417f6a21042005210320054120470d000b20024190076a200241e8086a410e6a290100221337030020024198076a200241e8086a41166a2204290100370300200241a0076a20024186096a2f01003b0100200241e8066a410e6a2013370100200241e8066a41166a20042f01003b0100200220022d00e80822103a00e806200220022800e9083600e906200220022d00ed083a00ed06200220022901ee0822133701ee062002201337038807200228019e072108200228019a07210d200241e0046a2001106c20022802e0040d07200128020420022802e404220b490d07200b417f4c0d10200b0d01410121040c020b200341ff0171450d06200241003a0088090c060b200b102e2204450d012007280200200b490d0220042001280200200b109a051a20012802042203200b490d1e20012003200b6b36020420012001280200200b6a3602000b2004450d04200220113703e007200220123703f0072002200a3703e807200241f7066a290000210a20022900ef06211120022d00ff06210e20022800eb06210920022d00ea06211a20022d00e906211941042122200b211b0c310b200b41011037000b2004102a0c020b41002105200241003a0088092003417e6a21092003417d6a21060340024020092005470d00200541ff0171450d03200241003a0088090c030b200241e8086a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a0088092006417f6a21062007210520074120470d000b2003417e6a2007460d01200241f7086a290000210a20022900ef08211120022d00e808211020022d00e908211920022d00ea08211a20022800eb08210920022d00ff08210e200228028009210d2002280284092108200420076a220c41026a2d0000211f200120063602042001200c41036a360200201f41014b0d014100210f02400240201f0e020100010b41002104200241003a008809200720036b41036a2106200320076b417c6a210303400240200620046a0d00200441ff0171450d04200241003a0088090c040b200241e8086a20046a200c20046a220541036a2d00003a0000200120033602042001200541046a3602002002200441016a22053a0088092003417f6a21032005210420054120470d000b200241b0056a200241f1086a290000370300200241b8056a200241f9086a290000370300200241bf056a220120024180096a290000370000200220022900e90822123703a805200241d8076a41046a20022d00ac053a0000200241e8066a41046a2203200241b5056a2f00003b0100200220123e02d807200220022800b1053602e80620022d00e808210620022800ad05211b2001290000211320022900b705211220022802e806210b20022800d907210420022d00d8072105200220032f01003b0188074101210f0b200241ea076a2013370100200241f6076a200241ce076a2f01003b0100200220022f0188073b01e007200220123701e207200220022801ca073601f207410521220c2e0b2009102a0b200041133602000c3b0b2006450d2a20042d0001210520012003417e6a3602042001200441026a360200200541024b0d2a0240024002400240024020050e03000102000b200241e0076a200110810120022802e0074113470d020c2e0b200241e8086a200110a5014102210120022d00e8084102460d2d200241a8056a41106a20024188096a280200360200200241a8056a41086a20024180096a2903003703002002200241e8086a41106a29030022123703a80520022903e8082213422088a72103200241e8086a41086a2903002216422088a72105200241b4056a290200210a20022902ac0521112013a721042012a721062016a721070c020b200241e8086a200110a50120022d00e8084102460d2c20024184096a290200210a200241fc086a2902002111200241f8086a2802002106200241f4086a2802002105200241f0086a280200210720022802ec08210320022802e8082104200241e0076a200110810120022802e0074113460d2c200241e8086a200241e0076a418801109a051a41880110282209450d1b2009200241e8086a418801109a051a410321010c010b200241e8086a200241e0076a418801109a051a41880110282204450d192004200241e8086a418801109a051a410121010b2000200136020420004111360200200041246a200a3702002000411c6a20113702002000412c6a2009360200200041186a2006360200200041146a2005360200200041106a20073602002000410c6a2003360200200041086a2004360200200041306a20024188066a41d800109a051a0c3a0b2006450d2820042d0001210520012003417e6a22063602042001200441026a36020020050d2820064104490d282004280002210b20012003417a6a3602042001200441066a360200200241a0056a2001106c20022802a0050d28200128020420022802a4052205490d282005417f4c0d060240024020050d004101210c41010d010c2a0b2005102e220c450d2520072802002005490d28200c20012802002005109a052104200128020422032005490d1a2001200320056b3602042001200128020020056a3602002004450d290b20024198056a2001106c2002280298050d262007280200410c6e220f410c6c2204417f4c0d06200228029c0521100240024020040d004104210e0c010b20041028220e450d1b0b0240024002400240024002402010450d00410021084100210341002109034020024190056a2001106c2002280290050d0320012802042002280294052204490d032004417f4c0d0d0240024020040d004101210d0c010b2004102e220d450d2b20072802002004490d03200d20012802002004109a051a200128020422062004490d232001200620046b3602042001200128020020046a3602000b200941016a210602402009200f470d0020082006200820064b1b220fad420c7e220a422088a70d3f200aa7221b4100480d3f0240024020090d00201b1028210e0c010b200e2003201b102c210e0b200e450d240b200e20036a2209200d360200200941046a2004ad220a422086200a84370200200841026a21082003410c6a21032006210920102006470d000b0b200e450d2b200c450d2d200728020022034104490d0220012802002207280000210820012003417c6a22043602042001200741046a36020020044104490d032007280004210d2001200341786a22093602042001200741086a36020041002104200241003a00a809200341776a2103034020092004460d05200241e8086a20046a200720046a220641086a2d00003a0000200120033602042001200641096a3602002002200441016a22063a00a8092003417f6a210320062104200641c000470d000b200241e0076a41386a2201200241e8086a41386a290300370300200241e0076a41306a2204200241e8086a41306a290300370300200241e0076a41286a2203200241e8086a41286a290300370300200241e0076a41206a2207200241e8086a41206a290300370300200241e0076a41186a2209200241e8086a41186a290300370300200241e0076a41106a221b200241e8086a41106a290300370300200241e0076a41086a221a200241e8086a41086a290300370300200220022903e8083703e007200641ff017141c000490d2a20024188066a41386a2206200129030037030020024188066a41306a2004290300220a37030020024188066a41286a2003290300221137030020024188066a41206a2007290300221237030020024188066a41186a2009290300221337030020024188066a41106a201b290300221637030020024188066a41086a201a2903002218370300200220022903e007221737038806200241a8056a41306a200a370300200241a8056a41286a2011370300200241a8056a41206a2012370300200241a8056a41186a2013370300200241a8056a41106a2016370300200241a8056a41086a2018370300200241a8056a41386a2006290300370300200220173703a805200c450d2d20024188076a41386a2201200241a8056a41386a29030037030020024188076a41306a2204200241a8056a41306a29030037030020024188076a41286a2203200241a8056a41286a29030037030020024188076a41206a2206200241a8056a41206a29030037030020024188076a41186a2207200241a8056a41186a29030037030020024188076a41106a2209200241a8056a41106a29030037030020024188076a41086a221b200241a8056a41086a290300370300200220022903a80537038807200041246a200d360200200041206a20083602002000411c6a2010360200200041186a200f360200200041146a200e360200200041106a20053602002000410c6a2005360200200041086a200c3602002000200b36020420004112360200200041286a200229038807370200200041306a201b290300370200200041386a2009290300370200200041c0006a2007290300370200200041c8006a2006290300370200200041d0006a2003290300370200200041d8006a2004290300370200200041e0006a200129030037020020004180016a200241e8066a41186a290300370300200041f8006a200241e8066a41106a290300370300200041f0006a200241e8066a41086a290300370300200041e8006a20022903e8063703000c3e0b200d102a0b02402009450d00200e210103400240200141046a280200450d002001280200102a0b2001410c6a2101200341746a22030d000b0b200f450d29200e102a0c290b02402005450d00200c102a0b02402010450d002010410c6c2104200e210103400240200141046a280200450d002001280200102a0b2001410c6a2101200441746a22040d000b0b200f450d2a200e102a0c2a0b02402005450d00200c102a0b02402010450d002010410c6c2104200e210103400240200141046a280200450d002001280200102a0b2001410c6a2101200441746a22040d000b0b200f450d29200e102a0c290b200441ff0171450d25200241003a00a8090c250b02402006450d0020012003417e6a3602042001200441026a3602000b200041133602000c380b02402006450d0020012003417e6a3602042001200441026a3602000b200041133602000c370b200041133602000c360b200041086a20022902e4073702002000200136020420004103360200200041106a200241e8086a41f800109a051a0c350b20024188066a41206a200241e0076a41206a290300220a37030020024188066a41186a200241e0076a41186a290300221137030020024188066a41106a200241e0076a41106a290300221237030020024188066a41086a200241e0076a41086a2903002213370300200220022903e00722163703880620004109360200200020163702042000410c6a2013370200200041146a20123702002000411c6a2011370200200041246a200a3702002000412c6a200241e8086a41dc00109a051a0c340b20024188066a41206a200241e0076a41206a290300220a37030020024188066a41186a200241e0076a41186a290300221137030020024188066a41106a200241e0076a41106a290300221237030020024188066a41086a200241e0076a41086a2903002213370300200220022903e0072216370388062000410a360200200020163702042000410c6a2013370200200041146a20123702002000411c6a2011370200200041246a200a3702002000412c6a200241e8086a41dc00109a051a0c330b1036000b200420031044000b200420031044000b200441041037000b200420031044000b200320091044000b201041041037000b200441041037000b200420061044000b200b41041037000b200441041037000b202041041037000b200420061044000b200420051044000b200420031044000b200b20071044000b200b20031044000b41880141081037000b41880141081037000b200520031044000b200441041037000b200420061044000b201b41041037000b200441011037000b200441011037000b41880141081037000b41880141081037000b41880141081037000b41880141081037000b200441011037000b200541011037000b02402005450d00200c102a0b02402010450d002010410c6c2104200e210103400240200141046a280200450d002001280200102a0b2001410c6a2101200441746a22040d000b0b200f450d02200e102a0c020b2005450d010b200c102a0b200041133602000c100b200041133602000c0f0b20024188066a41106a221e200241e0076a41106a29030037030020024188066a41086a2220200241e0076a41086a290300370300200220022903e00737038806200041346a200b360200200041306a201b3602002000412c6a2004360200200020053a002b200020063a002a2000200f3a0029200041256a2008360000200041216a200d360000200041206a200e3a0000200041186a200a370200200041106a20113700002000410c6a20093600002000201a3a000b200020193a000a200020103a0009200041086a20223a000020004110360200200041d0006a2012370200200041e9006a2003360000200041ed006a2001360000200041f4006a2007360200200041f8006a201837020020004180016a20133702002000200c3a00732000201f3a00722000201c3a0071200041e8006a201d3a0000200041d8006a2017370200200041e0006a2016370200200041386a200229038806370200200041c0006a2020290300370200200041c8006a201e2903003702000c0e0b2000410f360200200041386a200a370200200041306a2011370200200041286a2012370200200041206a20133702002000411c6a2001360200200041186a2004360200200041146a2003360200200041106a20053602002000410c6a2006360200200041086a2007360200200041c0006a200241e8086a41c800109a051a0c0d0b2000200e3600412000200936003d200020053a0027200020033a0026200020043a0025200020193a00072000201f3a00062000200d3a00052000201c3a00042000410c360200200041346a20113700002000412c6a200a3700002000413c6a20073a0000200041286a2006360000200041216a200b3600002000411d6a200f3600002000411c6a201b3a0000200041146a2012370000200041106a201a3600002000410c6a2010411874200c41ffffff077172360000200041086a2008411874200141ffffff07717236000020004180016a200241a0096a290300370300200041f8006a20024198096a290300370300200041f0006a200241e8086a41286a290300370300200041e8006a20024188096a290300370300200041e0006a200241e8086a41186a290300370300200041d8006a200241e8086a41106a290300370300200041d0006a200241e8086a41086a290300370300200041c8006a20022903e8083703000c0c0b200041133602000c0b0b2000410b360200200041c0006a2011370200200041386a200a370200200041286a2012370200200041206a2013370200200041346a2009360200200041306a20083602002000411c6a2007360200200041186a2006360200200041146a2005360200200041106a20033602002000410c6a2004360200200041086a2001360200200041c8006a20022903e808370300200041d0006a200241e8086a41086a290300370300200041d8006a200241e8086a41106a290300370300200041e0006a200241e8086a41186a290300370300200041e8006a200241e8086a41206a290300370300200041f0006a200241e8086a41286a290300370300200041f8006a200241e8086a41306a29030037030020004180016a200241e8086a41386a2903003703000c0a0b2004102a0b200041133602000c080b4100211f4200210a0c010b4100211f4200210a0b200020093a0029200020103a000b2000200d3a000a200020083a000920004108360200200041186a200a370200200041346a4100360200200041306a20193602002000412c6a200c360200200041256a200b360000200041216a200f360000200041206a200e3a0000200041086a201a3a00002000410c6a201c411874200641ffffff077172360200200041106a201fad422086201bad84370200200041386a20024188066a41d000109a051a0c050b200041133602000c040b200041133602000c030b200020083a002b2000200d3a002a2000200c3a0029200020093a000920004106360200200041386a2013370200200041306a2012370200200041186a2011370200200041106a200a3702002000412c6a200b360200200041216a200f360000200041206a200e3a00002000410c6a2006360200200041086a20103a0000200041256a201b201a41ff017172360000200041c0006a200241e8086a41c800109a051a0c020b1031000b20004100360200200041106a200a3702002000410c6a2005360200200041086a2009360200200041186a200241e8086a41f000109a051a0b200241f0096a24000bf602010b7f230041106b22022400200241086a2001106c0240024002400240024020022802080d0020012802042203417c712204417f4c0d02200228020c210502400240200341027622060d00410421070c010b200410282207450d040b02402005450d0041002108410021094100210403400240024002402001280204220a4104490d00200441016a21032001280200220b280000210c2001200a417c6a3602042001200b41046a36020020042006470d02024020082003200820034b1b220641ffffffff03712006470d002006410274220a41004e0d020b1031000b200041003602002006450d052007102a0c050b0240024020040d00200a102821070c010b20072009200a102c21070b2007450d070b200720096a200c360200200841026a2108200941046a21092003210420052003470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241106a24000f0b1036000b200441041037000b200a41041037000bbf0701107f230041f0006b22032400200341206a2001200228020c22041102000240024020032802200d002000410036020820004201370200200120022802001103002002280204450d012001102a0c010b200341c8006a41106a200341206a41106a290300370300200341c8006a41086a200341206a41086a290300370300200341c8006a41186a200341206a41186a290300370300200341c8006a41206a200341206a41206a280200360200200341086a200341d4006a290200370300200341106a200341dc006a290200370300200341186a200341e4006a290200370300200320032903203703482003200329024c370300200341c8006a2001200228021022051102000240417f2003280248220641016a220720072006491b220641ffffff3f712006470d0020064105742207417f4c0d004101210841012109024002402007450d00200710282209450d010b20092003290300370000200941186a200341186a220a290300370000200941106a200341106a220b290300370000200941086a200341086a220c290300370000200341206a200120041102000240024020032802200d002006210d0c010b200341c8006a41047221074120210e410121080340200341c8006a41206a200341206a41206a280200360200200341c8006a41186a220f200341206a41186a290300370300200341c8006a41106a2210200341206a41106a290300370300200341c8006a41086a2211200341206a41086a29030037030020032003290320370348200c200741086a290000370300200b200741106a290000370300200a200741186a29000037030020032007290000370300200f200a2903003703002010200b2903003703002011200c290300370300200320032903003703480240024020082006460d002006210d0c010b200341206a2001200511020002402006417f2003280220220d41016a22122012200d491b6a220d2006490d0020064101742212200d2012200d4b1b220d41ffffff3f71200d470d00200d41057422124100480d000240024020060d002012102821090c010b200920064105742012102c21090b20090d01201241011037000b1031000b2009200e6a22062003290348370000200641186a200f290300370000200641106a2010290300370000200641086a2011290300370000200341206a20012004110200200e41206a210e200841016a2108200d210620032802200d000b0b2001200228020011030002402002280204450d002001102a0b200020083602082000200d360204200020093602000c020b200741011037000b1036000b200341f0006a24000bad08040c7f017e057f037e23004180016b22022400024002400240200141086a220328020022042001410c6a2802002205460d002001280210220628020021072006280208220841014b210903402003200441206a220a360200200241e0006a41186a200441186a290000370300200241e0006a41106a200441106a290000370300200241e0006a41086a200441086a29000037030020022004290000370360410021040240024020090d0020080e020401040b2008210b0340200b410176220c20046a220d20042007200d4105746a200241e0006a4120109c054101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a4120109c050d02200a2104200a2005470d000b0b20004100360208200042013702002001280204450d012001280200102a0c010b200241c0006a41086a2204200241e0006a41086a290300370300200241c0006a41106a220b200241e0006a41106a290300370300200241c0006a41186a220c200241e0006a41186a29030037030020022002290360220e3703002002200e370340024041201028220f450d00200f2002290340370000200f41186a200c290300370000200f41106a200b290300370000200f41086a2004290300370000200128020421102001280200211102400240200a2005470d0041012112410121130c010b41012112410121130340200628020821032006280200210702400340200241e0006a41186a2208200a41186a290000370300200241e0006a41106a2209200a41106a290000370300200241e0006a41086a2201200a41086a2900003703002002200a290000370360200a41206a210a4100210402400240200341014b0d0020030e020301030b2003210b0340200b410176220c20046a220d20042007200d4105746a200241e0006a4120109c054101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a4120109c050d01200a2005470d000c030b0b200241c0006a41086a2001290300220e370300200241c0006a41106a20092903002214370300200241c0006a41186a20082903002215370300200220022903602216370340200241186a220b2015370300200241106a220c2014370300200241086a220d200e37030020022016370300024020132012470d000240201241016a22042012490d00201241017422072004200720044b1b221341ffffff3f712013470d00201341057422044100480d000240024020120d0020041028210f0c010b200f20124105742004102c210f0b200f0d01200441011037000b1031000b200f20124105746a22042002290300370000200441186a200b290300370000200441106a200c290300370000200441086a200d290300370000201241016a2112200a2005470d000b0b02402010450d002011102a0b20002012360208200020133602042000200f3602000c010b412041011037000b20024180016a24000bce0401057f23004180016b2202240002400240024020012802042203200128020022046b41e100490d0003402001200441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b20012001280200220441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b20012001280200220441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b20012001280200220441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b20012802042203200128020022046b41e0004b0d000b0b024020042003460d0003402001200441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b200128020022042001280204470d000b0b200041003602400c010b20002001290300370300200041386a200141386a290300370300200041306a200141306a290300370300200041286a200141286a290300370300200041206a200141206a290300370300200041186a200141186a290300370300200041106a200141106a290300370300200041086a200141086a290300370300200241086a2203200141cc006a290200370300200241106a2205200141d4006a290200370300200241186a2206200141dc006a2802003602002002200141c4006a2902003703002000200436024020002002290300370244200041cc006a2003290300370200200041d4006a2005290300370200200041dc006a20062802003602000b20024180016a24000bf00c030c7f017e067f230041a0026b22022400024002400240411010282203450d002003410029008ab740370000200341086a4100290092b7403700002002429080808080023702e401200220033602e0012002200241e0016a3602a0012001200241a0016a10c80120022802e001210320022802e8012101200241f8006a41186a22044200370300200241f8006a41106a22054200370300200241f8006a41086a220642003703002002420037037820032001200241f8006a1000200241d8006a41186a2004290300370300200241d8006a41106a2005290300370300200241d8006a41086a200629030037030020022002290378370358024020022802e401450d0020022802e001102a0b200241003602e001200241d8006a4120200241e0016a1006210420022802e0012205417f460d012004450d012002200536029c01200220043602980141002103200241003a0038024002400340024020052003470d002002410036029c01200341ff0171450d02200241003a00380c020b200241186a20036a200420036a22012d00003a00002002200141016a360298012002200341016a22013a00382001210320014120470d000b200241f8006a41086a2206200241186a41086a2207290300370300200241f8006a41106a2208200241186a41106a2209290300370300200241f8006a41186a220a200241186a41186a220b290300370300200220022903183703782002200520016b36029c01200241186a20024198016a10d40120022802382203450d00200241e0016a41186a220c200a290300370300200241e0016a41106a220a2008290300370300200241e0016a41086a220d2006290300370300200241e0016a41286a22062007290300370300200241e0016a41306a22072009290300370300200241e0016a41386a2208200b290300370300200220022903783703e00120022002290318370380022002413c6a2802002101200241186a41286a2209290300210e200241a0016a41086a200d290300370300200241a0016a41106a200a290300370300200241a0016a41186a200c290300370300200241a0016a41206a220a200229038002370300200241a0016a41286a220b2006290300370300200241a0016a41306a220c2007290300370300200241a0016a41386a220d2008290300370300200220022903e0013703a001200241186a20024198016a106d20022802180d012001450d002003102a0b41c4d1c3004133200241a0016a419cd9c3001038000b200241f8006a41086a220f200241186a41086a2210280200360200200241e0016a41086a2211200241a0016a41086a290300370300200241e0016a41106a2212200241a0016a41106a290300370300200241e0016a41186a2213200241a0016a41186a290300370300200241e0016a41206a2214200a2903003703002006200b2903003703002007200c2903003703002008200d29030037030020022002290318370378200220022903a0013703e00120102011290300370300200241186a41106a2012290300370300200241186a41186a2013290300370300200241186a41206a201429030037030020092006290300370300200241186a41306a2007290300370300200241186a41386a2008290300370300200241086a41086a200f280200360200200220022903e001370318200220022903783703082005450d022004102a0c020b411041011037000b410021030b200241e0016a41086a2204200241186a41086a290300370300200241e0016a41106a2205200241186a41106a290300370300200241e0016a41186a2206200241186a41186a290300370300200241e0016a41206a2207200241186a41206a290300370300200241e0016a41286a2208200241186a41286a290300370300200241e0016a41306a2209200241186a41306a290300370300200241e0016a41386a220a200241186a41386a290300370300200220022903183703e001200241a0016a41086a220b200241086a41086a280200360200200220022903083703a00102402003450d00200020022903e00137030020002001360244200041c8006a200e370200200041386a200a290300370300200041306a2009290300370300200041286a2008290300370300200041206a2007290300370300200041186a2006290300370300200041106a2005290300370300200041086a2004290300370300200041d8006a200b280200360200200041d0006a20022903a0013702000b20002003360240200241a0026a24000bb00705077f037e097f017e017f23004180016b22022400024002400240200141086a220328020022042001410c6a2802002205460d0020012802102106200241f4006a2107034020032004220841206a2204360200200841086a2903002109200841106a290300210a2008290300210b200241e0006a41186a200841186a290300370300200241e0006a41106a200a370300200241e0006a41086a20093703002002200b3703600240200aa720062802004d0d002001280214220c2007460d002007290000200c290000520d030b20052004470d000b0b20004100360208200042083702002001280204450d012001280200102a0c010b200241086a2204200241e0006a41086a290300370300200241106a2203200241e0006a41106a290300370300200241186a2207200241e0006a41186a29030037030020022002290360220a3703202002200a3703000240024002400240024041201028220d450d00200d2002290300370300200d41186a2007290300370300200d41106a2003290300370300200d41086a20042903003703002001280204210e2001280200210f200541606a2008460d03200841206a2110200541606a2111200241f4006a21014101211241012113200d21140340200c2001460d042010210802400340200241e0006a41186a2204200841186a290300370300200241e0006a41106a2203200841106a290300220a370300200241e0006a41086a2207200841086a290300370300200220082903003703600240200aa720062802004d0d002001290000200c290000520d020b2005200841206a2208470d000c070b0b200241206a41086a2007290300220a370300200241206a41106a20032903002209370300200241206a41186a2004290300220b3703002002200229036022153703202004200b370300200320093703002007200a37030020022015370360024020132012470d00201241016a22132012490d04201241017422102013201020134b1b221341ffffff3f712013470d04201341057422104100480d040240024020120d002010102821140c010b201420124105742010102c21140b2014450d030b200841206a2110201420124105746a22162002290360370300201641186a2004290300370300201641106a2003290300370300201641086a2007290300370300201241016a211220112008470d000c050b0b412041081037000b201041081037000b1031000b4101211241012113200d21140b0240200e450d00200f102a0b2000201236020820002013360204200020143602000b20024180016a24000bed0704067f017e0a7f027e230041f0006b22032400200341206a2001200228020c22041102000240024020032802200d002000410036020820004208370200200120022802001103002002280204450d012001102a0c010b200341c8006a41106a200341206a41106a290300370300200341c8006a41086a200341206a41086a290300370300200341c8006a41186a200341206a41186a290300370300200341c8006a41206a200341206a41206a280200360200200341086a200341d4006a290200370300200341106a200341dc006a290200370300200341186a200341e4006a290200370300200320032903203703482003200329024c370300200341c8006a2001200228021022051102000240024002400240417f2003280248220641016a220720072006491b2208ad42287e2209422088a70d002009a72206417f4c0d000240024020060d004108210a4108210b0c010b20061028220a450d02200a210b0b200a2003290300370300200a41186a200341186a220c290300370300200a41106a200341106a220d290300370300200a41086a200341086a290300370300200b4201370320200341206a200120041102000240024020032802200d004101210e0c010b200341c8006a410472210641c800210f4101210e0340200341c8006a41206a200341206a41206a280200360200200341c8006a41186a2210200341206a41186a290300370300200341c8006a41106a2211200341206a41106a290300370300200341c8006a41086a2212200341206a41086a29030037030020032003290320370348200341086a2207200641086a290200370300200d200641106a290200370300200c200641186a290200370300200320062902003703002010200c2903003703002011200d29030037030020122007290300370300200320032903003703480240200e2008470d00200341206a200120051102002008417f2003280220220741016a221320132007491b6a22072008490d06200841017422132007201320074b1b2213ad42287e2209422088a70d062009a722074100480d060240024020080d0020071028210a0c010b200a200841286c2007102c210a0b200a450d05200a210b201321080b200b200f6a221341606a2207200329034837030020122903002109201129030021142010290300211520134201370300200741186a2015370300200741106a2014370300200741086a2009370300200341206a20012004110200200f41286a210f200e41016a210e20032802200d000b0b2001200228020011030002402002280204450d002001102a0b2000200e360208200020083602042000200b3602000c040b1036000b200641081037000b200741081037000b1031000b200341f0006a24000b02000bef0101057f230041c0006b220524000240024020030d00200041003602000c010b2003280208210620032802002103200541206a41186a22074200370300200541206a41106a22084200370300200541206a41086a220942003703002005420037032020044120200541206a1000200541186a2007290300370300200541106a2008290300370300200541086a200929030037030020052005290320370300200541003602202003200620054120200541206a10012104024020052802202203417f460d002000200336020420002004360200200041086a20033602000c010b200041003602000b200541c0006a24000baf0201027f23004190016b2203240020032002108c010240024020032d000022024102470d00200041003a00000c010b200341e0006a200341286a290300370300200341e8006a200341306a290300370300200341d8006a41186a200341386a290300370300200341d8006a41206a200341c0006a290300370300200341d8006a41286a200341c8006a290300370300200341d8006a41306a200341d0006a2802003602002003200341206a29030037035802402002450d00200041003a00000c010b2003411c6a2802002102200341186a28020021042000200329026c370001200041013a0000200041196a20034184016a290200370000200041116a200341fc006a290200370000200041096a200341d8006a411c6a2902003700002002450d002004102a0b20034190016a24000bd60201057f230041d0016b220224000240411710282203450d00200341002900f1d8433700002003410f6a4100290080d943370000200341086a41002900f9d84337000020024297808080f00237027c200220033602782001200241f8006a108f01200228028001210320022802782101200241186a22044200370300200241106a22054200370300200241086a22064200370300200242003703002001200320021000200241d8006a41186a2004290300370300200241d8006a41106a2005290300370300200241d8006a41086a2006290300370300200220022903003703580240200228027c450d002002280278102a0b2002200241d8006a10960220022d00002103200241f8006a200241017241d700109a051a0240024020034102470d00200041023a00000c010b200020033a0000200041016a200241f8006a41d700109a051a0b200241d0016a24000f0b411741011037000b870102017f037e230041e0006b22032400200341086a2002108c010240024020032d000822024102470d00420021040c010b2002410173ad2104200341186a2903002105200341106a290300210620020d00200341246a280200450d00200341206a280200102a0b2000200637030820002004370300200041106a2005370300200341e0006a24000b940201057f230041d0006b220224000240411710282203450d00200341002900f1d8433700002003410f6a4100290080d943370000200341086a41002900f9d84337000020024297808080f002370224200220033602202001200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002412041014100410010032103200241d0006a24002003417f470f0b411741011037000b952801057f02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141046a2202280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00003a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0220012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00013a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0320012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00023a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0420012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00033a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0520012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00043a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0620012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00053a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0720012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00063a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0820012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00073a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0920012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00083a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0a20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00093a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0b20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000a3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0c20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000b3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000c3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000d3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000e3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1020012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000f3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00103a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1220012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00113a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1320012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00123a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1420012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00133a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1520012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00143a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1620012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00153a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1720012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00163a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1820012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00173a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1920012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00183a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1a20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00193a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1b20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001a3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1c20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001b3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001c3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001d3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001e3a000002400240200228020020032802002202460d00200128020021040c010b200241016a22042002490d21200241017422052004200520044b1b22054100480d210240024020020d002005102821040c010b200128020020022005102c21040b2004450d2020012004360200200141046a2005360200200141086a28020021020b2003200241016a360200200420026a20002d001f3a00000f0b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200541011037000b1031000b3802017f017e230041106b2203240020032002109101200329030021042000200341086a29030037030820002004370300200341106a24000bf40202057f027e230041d0006b2202240002400240411410282203450d00200341002900cfe140370000200341106a41002800dfe140360000200341086a41002900d7e14037000020024294808080c002370224200220033602202001200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002410036023020024120200241306a100621030240024020022802302201417f470d0042002107420021080c010b20014110490d02200341086a2900002108200329000021072003102a0b2000200737030020002008370308200241d0006a24000f0b411441011037000b41c4d1c3004133200241306a419cd9c3001038000bbc200b067f017e0d7f067e047f037e017f027e0d7f027e067f230041c0046b22022400200241186a42003703002002420037031020024200370308200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b200241106a21072002413c6a20042f0106360200200241206a41186a4100360200200241346a2004360200200220033602402002410036023020024200370328200220013602242002410036022020024188016a200241206a109301024002400240024020022903a80122084202510d00200241bc016a210920024188016a412c6a210a20024188016a410472210b200241e5016a210c20024188016a41086a2103200241e8026a412c6a210d200241e8026a41106a210e200241b8016a210f200241d0016a21100340200241e8006a41186a220620024188016a41186a2201290300370300200241e8006a41106a221120024188016a41106a2204290300370300200241e8006a41086a22122003290300370300200241c8006a41086a2213200c41086a290000370300200241c8006a41106a2214200c41106a290000370300200241c8006a41186a2215200c41186a29000037030020022002290388013703682002200c290000370348200f29030021162010290300211720022903b001211820022903c801211920022903c001211a20022903d801211b20022802e001211c20022d00e401211d20022d008502210520024188026a41186a200629030037030020024188026a41106a201129030037030020024188026a41086a20122903003703002002200229036837038802200241a8026a41186a22122015290300370300200241a8026a41106a221e2014290300370300200241a8026a41086a221f2013290300370300200220022903483703a8020240024002402005ad42ff0183200820085022061b4201520d0020024188016a20024188026a4200201820061b4200201620061b10940120042903002120200229039001211820022d00a00121062002290388012121200241086a41106a221129030021082002290310211602400240024002400240024020022903084201510d0020214200510d022016201856200820205620082020511b0d04202020087d2018201654ad7d2121201820167d21220c010b20214200510d02427f200820207c201620187c22182016542213ad7c22162013201620085420162008511b22131b2121427f201820131b21220b420121080c030b427f200820207c201620187c22182016542213ad7c22162013201620085420162008511b22131b2121427f201820131b2122420021080c020b202020087d2018201654ad7d200820207d2016201854ad7d20182016562020200856202020085122131b22141b2121201820167d201620187d20141b21222018201658202020085820131bad21080c010b200820207d2016201854ad7d2121201620187d2122420021080b201120213703002002202237031020022008370308200641ff01710d010b024002400240201d41ff0171222341014622060d00200541ff01710d00201c201aa772450d010b20024188016a20024188026a108c010240024020022d0088012211417f6a221341014b0d00024020130e020002000b20110d0420022802a401450d0420022802a001102a0c040b200241c8026a41086a200941086a290200370300200241c8026a41106a200941106a290200370300200241c8026a41186a200941186a290200370300200220092902003703c80220042903002124200229039001212520022802dc01212620022802b801212720022802b401212820022802b001212920022802ac01212a20022802a801212b20022802a401212c20022802a001212d0c020b4102212820110d0120022802a401450d0120022802a001102a0c010b201ba7210402400240201b422088a722050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b2002201c3602a801200241003602a001200241003602980120024200370390012002200136028c0120024100360288012002200436029c01200220042f01063602a40120024188016a1095010c020b4102212e02400240024002400240024002400240024020284102460d00202b417f4c0d0102400240202b0d004100212f410121300c010b202b212f202b10282230450d030b2030202d202b109a051a2001200241c8026a41186a2903003703002004200241c8026a41106a2903003703002003200241c8026a41086a290300370300200220022903c802370388012028410146212e202b2131202a2132202521332024213420292135202721360b200241b8036a41186a22372001290300370300200241b8036a41106a22382004290300370300200241b8036a41086a22392003290300370300200241a0046a41086a221d201f290300370300200241a0046a41106a2214201e290300370300200241a0046a41186a2215201229030037030020022002290388013703b803200220022903a8023703a004200541ff0171450d030c020b1036000b202b41011037000b202e4102460d0120302031100420060d0320024188026a109601202f450d022030102a0c020b202e4102460d00200d20022903b803370200200d41086a2039290300370200200d41106a2038290300370200200d41186a2037290300370200200220333703e80220022036360290032002202e36028c032002203536028803200220323602840320022031360280032002202f3602fc02200220303602f802200220343703f0022035213a2033212020342121203221110c030b2006450d004108211120024188016a20024188026a109701109801213a200e41086a20024188016a41086a280200360200200e200229038801370200200d20022903a004370100200d41086a200241a0046a41086a290300370100200d41106a2014290300370100200d41186a2015290300370100427f21202002427f3703f0022002427f3703e80220024108360284034100212e2002410036028c032002203a36028803427f21210c020b20284102460d020240202c0d004100212c0c030b202d102a0c020b4108211120024188016a20024188026a109701109801213a200e41086a20024188016a41086a280200360200200e200229038801370200200d20022903a004370100200d41086a200241a0046a41086a290300370100200d41106a2014290300370100200d41186a2015290300370100427f21202002427f3703f0022002427f3703e80220024108360284034100212e2002410036028c032002203a360288030240202f450d002030102a427f21200b427f21210b0240201a4201520d00200220193703e802200220173703f00220192120201721210b02402023450d00200d20022903a802370000200d41186a2012290300370000200d41106a201e290300370000200d41086a201f2903003700000b0240201c450d0010980121054101212e2002410136028c0320022005360290030b201ba7210502400240201b422088a722120d00200521060c010b2012211320052106034020062802ec0321062013417f6a22130d000b0340200520052f01064102746a41ec036a28020021052012417f6a22120d000b0b20052f010621122002201c3602d803200220123602d403200241003602d003200220053602cc03200241003602c803200242003703c003200220063602bc03200241003602b80320024188016a200241b8036a10990102402002280288014101470d00200228028003211320022802f802211c0340200241e0036a41186a200b41186a2902002208370300200241e0036a41106a200b41106a290200221b370300200241e0036a41086a200b41086a29020022163703002002200b29020022183703e00320022802ac01210520022802b001211e20022802b401210620024180046a41186a200837030020024180046a41106a201b37030020024180046a41086a20163703002002201837038004200142003703002004420037030020034200370300200242003703880120024180046a412020024188016a10002015200129030037030020142004290300370300201d200329030037030020022002290388013703a0042002410036028801201c2013200241a0046a412020024188016a1001211f02402002280288012212417f460d00201120126b21112012450d00201f102a0b0240024020050d00200142003703002004420037030020034200370300200242003703880120024180046a412020024188016a10002015200129030037030020142004290300370300201d200329030037030020022002290388013703a004201c2013200241a0046a412010020c010b200142003703002004420037030020034200370300200242003703880120024180046a412020024188016a10002015200129030037030020142004290300370300201d200329030037030020022002290388013703a004201c2013200241a0046a4120200520061005201120066a2111201e450d002005102a0b20024188016a200241b8036a1099012002280288014101460d000b20022011360284030b200241b8036a1095012037200241c8026a41186a2903003703002038200241c8026a41106a2903003703002039200241c8026a41086a290300370300200220022903c8023703b8030240024020284102460d00200a20022903b803370200200a41086a2039290300370200200a41106a2038290300370200200a41186a20372903003702002002202537038801200220273602b001200220283602ac01200220293602a8012002202a3602a4012002202c36029c012002202d36029801200220263602d40120022024370390012002202b3602a001410121040240202b200228028003470d0002400240202d20022802f8022201460d00202d2001202b109c050d02202a2011470d020c010b202a2011470d010b200a200d4120109c050d0020252020852024202185844200520d002029203a470d0002402028202e470d004100210420284101470d012027200228029003460d010b410121040b0240202c450d00202d102a0b20044102460d002004450d010b2003200241e8026a41d000109a051a200241003a00880120024188026a20024188016a109a010c020b20022802fc02450d0120022802f802102a0c010b201ba7210402400240201b422088a722050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b2002201c3602a801200241003602a001200241003602980120024200370390012002200136028c0120024100360288012002200436029c01200220042f01063602a40120024188016a1095010b20024188016a200241206a10930120022903a80122084202520d000b20022903082108200241206a109b012008500d010c020b200241206a109b010b02402002290310200241186a29030084500d0041f4b5c0001032000b20022903084200520d00200220073602880120024188016a109c010c010b200220073602880120024188016a109d010b200241c0046a24000bf90503087f017e017f23004180026b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2203200128020422052f01064f0d01200241186a2206200520034105746a220741206a290000370300200241106a2208200741186a290000370300200241086a2209200741106a2900003703002002200741086a290000370300200241206a2005200341e0006c6a41e8026a41e000109a051a2001200341016a36020c200120043602082001200536020420024180016a41186a200629030037030020024180016a41106a200829030037030020024180016a41086a2009290300370300200220022903003703800120024180016a41206a200241206a41e000109a051a200020024180016a418001109a051a0c020b200042023703200c010b2001280200210702400240200528020022030d002004ad210a410021030c010b200741016a210720053301044220862004ad84210a0b2005102a200aa7210402400240200a422088a7220620032f01064f0d00200321050c010b034002400240200328020022050d002004ad210a410021050c010b200741016a210720033301044220862004ad84210a0b2003102a200aa7210420052103200a422088a7220620052f01064f0d000b0b200241186a2208200520064105746a220341206a290000370300200241106a2209200341186a290000370300200241086a220b200341106a2900003703002002200341086a290000370300200241206a2005200641e0006c6a41e8026a41e000109a051a200641027420056a418c0b6a280200210302402007417f6a2205450d00034020032802880b21032005417f6a22050d000b0b2001410036020c20012004360208200120033602042001410036020020024180016a41186a200829030037030020024180016a41106a200929030037030020024180016a41086a200b290300370300200220022903003703800120024180016a41206a200241206a41e000109a051a200020024180016a418001109a051a0b20024180026a24000ba90703067f027e017f230041a0016b220424000240024002400240411410282205450d00200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b0240200242ffffe883b1de1656200342005220035022051b0d00200a200b844200520d0020004200370300200041013a0018200041106a4200370300200041086a42003703000c040b4101210602402002428080e983b1de1654410020051b0d00411410282205450d0341002106200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370224200420053602202001200441206a108f012004280228210520042802202107200441306a41186a22084200370300200441306a41106a22094200370300200441306a41086a220c42003703002004420037033020072005200441306a1000200441186a2008290300370300200441106a2009290300370300200441086a200c2903003703002004200429033037030002402004280224450d002004280220102a0b200441204101410041001003417f470d002001109302200441e8006a2003370300200441e0006a200237030041002106200441306a41086a41003a0000200441396a2001290000370000200441c1006a200141086a290000370000200441c9006a200141106a290000370000200441d1006a200141186a290000370000200441023a003041014100200441306a10cc010b200120022003108f02200041106a200b20037d200a200254ad7d2003200b7d2002200a54ad7d200a200256200b200356200b2003511b22051b3703002000200a20027d2002200a7d20051b370308200020063a001820002005ad3703000c030b411441011037000b41c4d1c3004133200441306a419cd9c3001038000b411441011037000b200441a0016a24000bb00101037f230041306b2201240020012000109901024020012802004101470d000340024020012802242202450d002001280228450d002002102a0b2001200010990120012802004101460d000b0b02402000280204220241f8b9c000460d00200228020021032002102a2003450d00200328020021002003102a2000450d00024020002802002202450d0003402000102a2002210020022802002203210220030d000b0b2000102a0b200141306a24000b870201057f230041d0006b220124000240411710282202450d00200241002900f1d8433700002002410f6a4100290080d943370000200241086a41002900f9d84337000020014297808080f002370224200120023602202000200141206a108f012001280228210220012802202100200141306a41186a22034200370300200141306a41106a22044200370300200141306a41086a220542003703002001420037033020002002200141306a1000200141186a2003290300370300200141106a2004290300370300200141086a20052903003703002001200129033037030002402001280224450d002001280220102a0b200141201009200141d0006a24000f0b411741011037000ba60603037f017e017f230041c0006b22022400200241206a41086a220342003703002002420037032041d8fec5004117200241206a1008200241086a2003290300370300200220022903203703002002410036022020024110200241206a1006210302400240024002400240024020022802202204417f470d00420121050c010b024020030d00420121050c010b20044108490d01200329000021052003102a200542017c21050b200241206a41086a220342003703002002420037032041d8fec5004117200241206a1008200241086a2003290300370300200220022903203703002002200537032020024110200241206a41081007412010282203450d0120032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003412041c000102c2201450d0220012005370020200241206a41186a22034200370300200241206a41106a22044200370300200241206a41086a220642003703002002420037032020014128200241206a1000200241186a2003290300370300200241106a2004290300370300200241086a200629030037030020022002290320370300413710282203450d03200342bac6a1cbc68dd9aff300370000200342f4dec98bf6ac999de400370008200341e5cc85ab073600102003413a3a0016200341ece8013b001420032002290300370017200320022f01083b001f2003200228010a360021200320022f010e3b0025200320022d00103a0027200320022d00113a0028200320022d00123a0029200320022d00133a002a200320022d00143a002b200320022d00153a002c200320022d00163a002d200320022d00173a002e200320022d00183a002f200320022d00193a0030200320022d001a3a0031200320022d001b3a0032200320022d001c3a0033200320022d001d3a0034200320022d001e3a0035200320022d001f3a0036200041ed93c40041c593c4006b410f6a36020820004137360204200020033602002001102a200241c0006a24000f0b41c4d1c3004133200241206a419cd9c3001038000b412041011037000b41c00041011037000b413741011037000ba70101047f230041206b22002400200041106a41086a220142003703002000420037031041d9efc200410d200041106a1008200041086a200129030037030020002000290310370300410021022000410036021020004110200041106a100621010240024020002802102203417f460d002001450d0020034104490d01200128000021022001102a0b200041206a240020020f0b41c4d1c3004133200041106a419cd9c3001038000bdd0605057f047e017f017e047f23004190016b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2203200128020422052f01064f0d01200241e0006a41186a200520034105746a220641206a2900002207370300200241e0006a41106a200641186a2900002208370300200241e0006a41086a200641106a29000022093703002002200641086a290000220a370360200241306a41086a20052003410c6c6a220641f0026a280200220b360200200641e8026a290200210c2001200341016a36020c20012004360208200120053602042002200c3703302000200a3702042000410c6a2009370200200041146a20083702002000411c6a2007370200200041246a200c3702002000412c6a200b360200200041013602000c020b200041003602000c010b2001280200210602400240200528020022030d002004ad210c410021030c010b200641016a210620053301044220862004ad84210c0b2005102a200ca7210402400240200c422088a7220b20032f01064f0d00200321050c010b034002400240200328020022050d002004ad210c410021050c010b200641016a210620033301044220862004ad84210c0b2003102a200ca7210420052103200c422088a7220b20052f01064f0d000b0b200241306a41186a220d2005200b4105746a220341206a290000370300200241306a41106a220e200341186a290000370300200241306a41086a220f200341106a2900003703002002200341086a290000370330200241d0006a41086a22102005200b410c6c6a220341f0026a2802003602002002200341e8026a290200370350200b41027420056a41f0036a280200210302402006417f6a2205450d00034020032802ec0321032005417f6a22050d000b0b2001410036020c200120043602082001200336020420014100360200200241e0006a41186a200d290300220c370300200241e0006a41106a200e2903002207370300200241e0006a41086a200f290300220837030020024188016a201028020022033602002000200229033022093702042000410c6a2008370200200041146a20073702002000411c6a200c370200200041246a2002290350220c3702002000412c6a2003360200200220093703602002200c37038001200041013602000b20024190016a24000ba70201057f230041d0006b220224000240411710282203450d00200341002900f1d8433700002003410f6a4100290080d943370000200341086a41002900f9d84337000020024297808080f002370224200220033602202000200241206a108f012002280228210320022802202100200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020002003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002200110e203024020012d00000d002001411c6a280200450d00200141186a280200102a0b200241d0006a24000f0b411741011037000bca0201067f230041b0016b22012400200141086a2000109301024020012903284202510d000340200128026021022001280258210302400240200128025c22040d00200321050c010b2004210620032105034020052802ec0321052006417f6a22060d000b0340200320032f01064102746a41ec036a28020021032004417f6a22040d000b0b200120023602a801200141003602a001200141003602980120014200370390012001200536028c0120014100360288012001200336029c01200120032f01063602a40120014188016a109501200141086a200010930120012903284202520d000b0b02402000280204220341f8b9c000460d00200328020021042003102a2004450d00200428020021052004102a2005450d00024020052802002203450d0003402005102a2003210520032802002204210320040d000b0b2005102a0b200141b0016a24000bcf0204017f017e027f037e230041206b2201240042002102200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a1006210302400240024020012802102204417f470d00420021050c010b20044110490d01200341086a2900002105200329000021022003102a0b2000280200220341086a290300210620032903002107200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a2003290300370300200120012903103703002001427f200520067c200220077c22062002542203ad7c22022003200220055420022005511b22031b3703182001427f200620031b37031020014110200141106a41101007200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000bd00204017f017e027f037e230041206b2201240042002102200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a1006210302400240024020012802102204417f470d00420021050c010b20044110490d01200341086a2900002105200329000021022003102a0b2000280200220341086a290300210620032903002107200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a20032903003703002001200129031037030020014200200520067d2002200754ad7d2206200220077d2207200256200620055620062005511b22031b37031820014200200720031b37031020014110200141106a41101007200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000bb50404057f017e017f017e0240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a3602000240200441037122064103460d00024002400240024020060e03000102000b2004410276ad21070c020b41012106024020050d000c050b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d04200141fcff0371410276ad21070c010b410121060240200541034f0d000c040b200341036a2d0000210520032f0001210820012002417c6a3602042001200341046a3602002008200541107472410874200472220141808004490d032001410276ad21070b410021060c020b02402004410276220841044b0d000240024020080e050002020201000b20054104490d022003350001210720012002417b6a3602042001200341056a36020020074280808080045421060c030b20054108490d01200329000121072001200241776a3602042001200341096a3602002007428080808080808080015421060c020b200841046a220541084b0d002002417e6a2102200341026a2103410021044200210741012106034002402002417f470d000c030b2003417f6a310000210920012002360204200120033602002002417f6a2102200341016a210320092004410374413871ad862007842107200441016a220441ff01712005490d000b2007427f412820084103746b413871ad885821060c010b410121060b2000200737030820002006ad3703000bde0506067f017e017f017e017f017e230041206b220224000240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200024002400240200541037122074103460d0002400240024020070e03000102000b2005410276ad21080c040b410121072006450d0220042d0001210620012003417e6a3602042001200441026a3602002006410874200572220141ffff0371418002490d02200141fcff0371410276ad21080c030b4101210720064103490d01200441036a2d0000210620042f0001210920012003417c6a3602042001200441046a3602002009200641107472410874200572220141808004490d012001410276ad21080c020b024020054102762209410c4b0d0002400240024020090e0d00030303010303030303030302000b20064104490d052004350001210820012003417b6a3602042001200441056a36020020084280808080045421074200210a0c060b20064108490d04200429000121082001200341776a3602042001200441096a3602002008428080808080808080015421074200210a0c050b20064110490d03200441096a290000210a2004290001210820012003416f6a3602042001200441116a360200200a428080808080808080015421070c040b200941046a220641104b0d022003417e6a2103200441026a21044100210541012107200241186a210b420021084200210a03402003417f460d01200241106a2004417f6a3100004200200541037441f80071109d0520012003360204200120043602002003417f6a2103200441016a2104200b290300200a84210a20022903102008842108200541016a220541ff01712006490d000b2002427f427f41e80020094103746b41f80071109e052008200229030058200a200241086a290300220c58200a200c511b21070c030b0c020b4200210a410021070c010b410121070b20002008370308200041106a200a37030020002007ad370300200241206a24000b9e0701037f02400240024002400240024020002802002202413f4b0d0002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d06200041017422042003200420034b1b22044100480d060240024020000d002004102821030c010b200128020020002004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20024102743a00000f0b200241808001490d032002418080808004490d020c010b200441011037000b0240024002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102821030c010b200128020020022004102c21030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280200210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d05200241017422002004200020044b1b22004100480d050240024020020d002000102821020c010b200128020020022000102c21020b2002450d0220012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b200441011037000b200041011037000b024002400240200141046a2802002203200141086a28020022006b4104490d00200128020021030c010b200041046a22042000490d03200341017422002004200020044b1b22004100480d030240024020030d002000102821030c010b200128020020032000102c21030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20024102744102723600000f0b200041011037000b024002400240200141046a2802002203200141086a28020022006b4102490d00200128020021030c010b200041026a22042000490d02200341017422002004200020044b1b22004100480d020240024020030d002000102821030c010b200128020020032000102c21030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20024102744101723b00000f0b200041011037000b1031000bac0903017f017e057f230041e0006b220224000240024002400240024002400240024002400240024020002903002203423f560d0002400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d0b200041017422052004200520044b1b22054100480d0b0240024020000d002005102821040c010b200128020020002005102c21040b2004450d0220012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a2003a74102743a00000c080b200342808001540d062003428080808004540d054108200379a741037622056b4104490d0402400240200141046a280200200141086a2802002204460d00200128020021060c010b200441016a22072004490d0a200441017422062007200620074b1b22074100480d0a0240024020040d002007102821060c010b200128020020042007102c21060b2006450d0220012006360200200141046a2007360200200141086a28020021040b200141086a2207200441016a360200200620046a411320054102746b3a0000200220002903002203370308200541786a2104200141046a2106034002400240200628020020072802002200460d00200128020021050c010b200041016a22052000490d0b200041017422082005200820054b1b22084100480d0b0240024020000d002008102821050c010b200128020020002008102c21050b2005450d042001200536020020062008360200200728020021000b2007200041016a360200200520006a2003a73a000020034208882103200441016a22002004492105200021042005450d000b20022003370308200350450d030c070b200541011037000b200741011037000b200841011037000b200241286a41146a4108360200200241346a4109360200200241106a41146a41033602002002200241086a360240200241f8b9c00036024420024203370214200241c8afc6003602102002410936022c200242043703582002420137024c20024180bac0003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a4188bac000103e000b41dcb9c0001032000b024002400240200141046a2802002204200141086a28020022006b4104490d00200128020021040c010b200041046a22052000490d05200441017422002005200020054b1b22004100480d050240024020040d002000102821040c010b200128020020042000102c21040b2004450d0120012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a2003a74102744102723600000c020b200041011037000b02400240200141046a2802002204200141086a28020022006b4102490d00200128020021040c010b200041026a22052000490d03200441017422002005200020054b1b22004100480d030240024020040d002000102821040c010b200128020020042000102c21040b2004450d0220012004360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200420006a2003a74102744101723b00000b200241e0006a24000f0b200041011037000b1031000bbf0202027f017e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d01200441012001103f21000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20034180011044000b20034180011044000b800a03017f027e057f230041e0006b2202240002400240024002400240024002400240024002400240200028020022002903002203423f56200041086a290300220442005220045022051b0d0002400240200141046a280200200141086a2802002200460d00200128020021050c010b200041016a22052000490d0b200041017422062005200620054b1b22064100480d0b0240024020000d002006102821050c010b200128020020002006102c21050b2005450d0220012005360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200520006a2003a74102743a00000c080b20034280800154410020051b0d06200342808080800454410020051b0d05411020047920037942c0007c20044200521ba741037622066b4104490d0402400240200141046a280200200141086a2802002205460d00200128020021070c010b200541016a22082005490d0a200541017422072008200720084b1b22084100480d0a0240024020050d002008102821070c010b200128020020052008102c21070b2007450d0220012007360200200141046a2008360200200141086a28020021050b200141086a2208200541016a360200200720056a413320064102746b3a0000200029030021032002200041086a290300220437030820022003370300200641706a2105200141046a2107034002400240200728020020082802002200460d00200128020021060c010b200041016a22062000490d0b200041017422092006200920064b1b22094100480d0b0240024020000d002009102821060c010b200128020020002009102c21060b2006450d042001200636020020072009360200200828020021000b2008200041016a360200200620006a2003a73a00002003420888200442388684210320044208882104200541016a22002005492106200021052006450d000b2002200337030020022004370308200320048450450d030c070b200641011037000b200841011037000b200941011037000b200241286a41146a4108360200200241346a410a360200200241106a41146a410336020020022002360240200241a8bbc00036024420024203370214200241c8afc6003602102002410a36022c200242043703582002420137024c20024180bac0003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a41b8bbc000103e000b418cbbc0001032000b024002400240200141046a2802002205200141086a28020022006b4104490d00200128020021050c010b200041046a22062000490d05200541017422002006200020064b1b22004100480d050240024020050d002000102821050c010b200128020020052000102c21050b2005450d0120012005360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200520006a2003a74102744102723600000c020b200041011037000b02400240200141046a2802002205200141086a28020022006b4102490d00200128020021050c010b200041026a22062000490d03200541017422002006200020064b1b22004100480d030240024020050d002000102821050c010b200128020020052000102c21050b2005450d0220012005360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200520006a2003a74102744101723b00000b200241e0006a24000f0b200041011037000b1031000b810605027f027e017f027e027f230041a0016b220224002000280200210002400240024002400240024002400240200128020022034110710d00200041086a29030021042000290300210520034120710d0220054290ce005441002004501b450d012005a72103412721000c060b200041086a2903002105200029030021044180012100024003402000450d01200241206a20006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a210020044204882005423c8684220420054204882205844200520d000b0b20004181014f0d0220014101419087c0004102200241206a20006a41800120006b104221000c060b41272100200241186a21060340200241106a200520044290ce00420010a0052002200229031022072006290300220842f0b17f427f109f05200241206a20006a2203417c6a200520022903007ca7220941ffff037141e4006e220a41017441ba84c0006a2f00003b00002003417e6a200a419c7f6c20096a41ffff037141017441ba84c0006a2f00003b0000200542ffc1d72f56210320044200522109200450210a2000417c6a2100200721052008210420032009200a1b0d000c040b0b4180012100024003402000450d01200241206a20006a417f6a2005a7410f712203413072200341376a2003410a491b3a00002000417f6a210020054204882004423c8684220520044204882204844200520d000b0b20004181014f0d0120014101419087c0004102200241206a20006a41800120006b104221000c040b20004180011044000b20004180011044000b2007a721030b02400240200341e3004a0d00200321090c010b200241206a2000417e6a22006a2003200341ffff037141e4006e2209419c7f6c6a41ffff037141017441ba84c0006a2f00003b00000b024002402009410a480d00200241206a2000417e6a22006a200941017441ba84c0006a2f00003b00000c010b200241206a2000417f6a22006a200941306a3a00000b2001410141b8aec6004100200241206a20006a412720006b104221000b200241a0016a240020000bf40601067f230041f0006b21020240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a2206360204410121072001200441016a360200200541f001490d0a200541847e6a220541034b0d0420050e0401020803010b200041023a00000f0b20064102490d0320042f0001210520012003417d6a3602042001200441036a360200200541ef014b0d04200041023a00000f0b20064104490d042004280001210520012003417b6a3602042001200441056a36020041012107200541ffff034b0d07200041023a00000f0b41002105200241003a00682003417f6a21062003417e6a210302400340024020062005470d000240200541ff0171450d00200241003a00680b410121010c020b200241c8006a20056a200420056a220741016a2d00003a0000200120033602042001200741026a3602002002200541016a22073a00682003417f6a21032007210520074120470d000b200241c6006a20022d004a3a0000200241306a200241d7006a290000370300200241386a200241df006a290000370300200241c0006a200241e7006a2d00003a0000200220022f01483b01442002200229004f370328200228004b2105410021010b200241246a41026a2203200241c4006a41026a2d00003a0000200241086a41086a2207200241286a41086a290300370300200241086a41106a2204200241286a41106a290300370300200241086a41186a2206200241286a41186a2d00003a0000200220022f01443b0124200220022903283703082001450d05200041023a00000f0b200041023a00000f0b200041023a00000f0b410121070c030b200041023a00000f0b0240200641044f0d00200041023a00000f0b200041023a000020012003417b6a3602042001200441056a3602000f0b200241286a41026a20032d00003a0000200241c8006a41086a2007290300370300200241c8006a41106a2004290300370300200241c8006a41186a20062d00003a0000200220022f01243b012820022002290308370348410021070b200020073a0000200020022f01283b0001200041046a2005360200200041086a2002290348370200200041036a2002412a6a2d00003a0000200041106a200241c8006a41086a290300370200200041186a200241c8006a41106a290300370200200041206a200241c8006a41186a2802003602000bb30801037f0240024002400240024002400240024020002d00004101460d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d08200241017422042003200420034b1b22044100480d080240024020020d002004102821030c010b200128020020022004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41ff013a0000200041016a2001108f010f0b0240024002400240200041046a280200220241ffff034b0d00200241ef014b0d03200141046a280200200141086a2802002200460d01200128020021030c020b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0a200041017422042003200420034b1b22044100480d0a0240024020000d002004102821030c010b200128020020002004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fd013a000002400240200141046a2802002203200428020022006b4104490d00200128020021030c010b200041046a22042000490d0a200341017422002004200020044b1b22004100480d0a0240024020030d002000102821030c010b200128020020032000102c21030b2003450d0620012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20023600000f0b200041016a22032000490d08200041017422042003200420034b1b22044100480d080240024020000d002004102821030c010b200128020020002004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20023a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d07200041017422042003200420034b1b22044100480d070240024020000d002004102821030c010b200128020020002004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fc013a000002400240200141046a2802002203200428020022006b4102490d00200128020021030c010b200041026a22042000490d07200341017422002004200020044b1b22004100480d070240024020030d002000102821030c010b200128020020032000102c21030b2003450d0620012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20023b00000f0b200441011037000b200441011037000b200041011037000b200441011037000b200441011037000b200041011037000b1031000bd80402097f017e230041106b22052400024002400240200128020041016a220641004c0d0020012006360200200141046a2106200141086a28020021070240024003402006280200220841086a210920082f0106220a41057421064100210b0240024003402006450d01200220094120109c05220c450d02200641606a2106200b41016a210b200941206a2109200c417f4a0d000b200b417f6a210a0b2007450d022007417f6a21072008200a4102746a41880b6a21060c010b0b2008200b41e0006c6a22094198036a2106200941e8026a210d2009419c036a2802002107024003402006280200220841086a210920082f0106220a41057421064100210b0240024003402006450d01200420094120109c05220c450d02200641606a2106200b41016a210b200941206a2109200c417f4a0d000b200b417f6a210a0b024020070d004100210c0c030b2007417f6a21072008200a4102746a41ec036a21060c010b0b4101210c0240200841e8026a200b410c6c6a2206280200220b0d00410021060c010b20062802082209417f4c0d040240024020090d0020054200370300410121060c010b200910282206450d0620054100360204200520093602000b200520093602042006200b2009109a051a2005290300210e0b02400240200d2d005d450d0020064100200c1b21060c010b200c450d010b2000200e370204200020063602000c010b20002001280210200220032004200141146a28020028020c1104000b20012001280200417f6a360200200541106a24000f0b41b8b8c0004118200541086a41e0b8c0001038000b1036000b200941011037000bfc0202097f037e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d01200220084120109c05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a22054190036a290300210c20054188036a290300210d20054180036a290300210e0240200541c5036a2d00000d00200ea721054201210e2005450d010c020b200e4202520d010b200320012802102002200141146a280200280214110500200341106a290300210c200128020021042003290308210d2003290300210e0b20012004417f6a360200200041106a200c3703002000200d3703082000200e370300200341206a24000f0b41b8b8c0004118200341186a41e0b8c0001038000bd70501037f024002400240024002400240024020002d00004101460d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d07200241017422042003200420034b1b22044100480d070240024020020d002004102821030c010b200128020020022004102c21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41003a00000c010b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d06200241017422042003200420034b1b22044100480d060240024020020d002004102821030c010b200128020020022004102c21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41013a0000200041016a2001108f010b024020002d00214101460d0002400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d06200041017422032002200320024b1b22034100480d060240024020000d002003102821020c010b200128020020002003102c21020b2002450d0420012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41003a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102821030c010b200128020020022004102c21030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41013a0000200041226a2001108f010f0b200441011037000b200441011037000b200341011037000b200441011037000b1031000bbf0501047f200141046a2802002102200141086a28020021030240024002400240024002400240200028020022040d000240024020022003460d00200128020021020c010b200341016a22022003490d07200341017422042002200420024b1b22044100480d070240024020030d002004102821020c010b200128020020032004102c21020b2002450d0320012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a41003a00000c010b0240024020022003460d00200128020021020c010b200341016a22022003490d06200341017422052002200520024b1b22054100480d060240024020030d002005102821020c010b200128020020032005102c21020b2002450d0320012002360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200220036a41013a000020042001108f010b200141046a2802002102200141086a28020021030240200028020422040d000240024020022003460d00200128020021000c010b200341016a22002003490d06200341017422022000200220004b1b22024100480d060240024020030d002002102821000c010b200128020020032002102c21000b2000450d0420012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b0240024020022003460d00200128020021000c010b200341016a22002003490d05200341017422022000200220004b1b22024100480d050240024020030d002002102821000c010b200128020020032002102c21000b2000450d0420012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41013a000020042001108f010f0b200441011037000b200541011037000b200241011037000b200241011037000b1031000b860a05037f047e057f027e047f230022022103200241c0016b41607122022400200141186a220429000021052004200229039801370000200129001021062001200229039001370010200129000821072001200229038801370008200241003a00800120012900002108200120022903800137000020022005370378200220063703702002200737036820022008370360200141206a2d0000210420024180016a41176a2209200537000020024180016a41106a220a200229007137030020024180016a41086a220b2002290069370300200220022900613703800102402008a741ff01714101460d0020004200370300200324000f0b200241186a41176a2009290000370000200241186a41106a200a290300370300200241186a41086a200b2903003703002002200229038001370318200220043a0037200241386a200241186a10ac012002410036028001200241386a412020024180016a1006210c02400240200228028001220d417f460d002002200d36025c2002200c3602582002200241d8006a109f012002290300a70d01200228025c2204450d01200241106a290300210e2002290308210f20022004417f6a220a36025c20022002280258221041016a220b36025820102d0000220441014b0d01410021110240024020040e020100010b4100210403400240200a2004470d002002410036025c0c040b2002201020046a41026a360258200441016a2209210420094120470d000b2002200a20096b220a36025c41012111201020096a41016a210b0b200a450d012002200a417f6a220a36025c2002200b41016a360258200b2d0000220941014b0d01410021040240024020090e020100010b41002104200241003a00a00103400240200a2004470d002002410036025c200441ff0171450d04200241003a00a0010c040b20024180016a20046a200b20046a220941016a2d00003a00002002200941026a3602582002200441016a22093a00a0012009210420094120470d000b200241e0006a41086a20024180016a41086a290300370300200241e0006a41106a20024180016a41106a290300370300200241e0006a41186a20024180016a41186a29030037030020022002290380013703602002200a20096b36025c410121040b20024180016a41186a2209200241e0006a41186a220a29030037030020024180016a41106a220b200241e0006a41106a221029030037030020024180016a41086a2212200241e0006a41086a2213290300370300200220022903603703800120114102460d01200a20092903003703002010200b2903003703002013201229030037030020022002290380013703600240200d450d00200c102a0b20024180016a41186a200241e0006a41186a2209290300220537030020024180016a41106a200241e0006a41106a220a290300220837030020024180016a41086a200241e0006a41086a220b29030022063703002002200229036022073703800120092005370300200a2008370300200b200637030020022007370360200120043a000020012007370001200141096a2006370000200141116a2008370000200141196a2005370000200041306a200e370300200041286a200f3703002000420137030020002002290318370008200041106a200241186a41086a290300370000200041186a200241186a41106a290300370000200041206a200241186a41186a290300370000200324000f0b41c9b4c00041dd001050000b41c4d1c3004133200241b8016a419cd9c3001038000bfc0101057f230041306b220224000240411210282203450d00200341002900c1ae44370000200341106a41002f00d1ae443b0000200341086a41002900c9ae4437000020024292808080a0023702042002200336020020012002108f012002280208210320022802002101200241106a41186a22044200370300200241106a41106a22054200370300200241106a41086a220642003703002002420037031020012003200241106a1000200041186a2004290300370000200041106a2005290300370000200041086a20062903003700002000200229031037000002402002280204450d002002280200102a0b200241306a24000f0b411241011037000b910a03037f047e0c7f230022022103200241c0016b41607122022400200141186a220429000021052004200229039801370000200129001021062001200229039001370010200129000821072001200229038801370008200241003a00800120012900002108200120022903800137000020022005370378200220063703702002200737036820022008370360200141206a2d0000210420024180016a41176a2209200537000020024180016a41106a220a200229007137030020024180016a41086a220b2002290069370300200220022900613703800102402008a741ff01714101460d0020004100360220200324000f0b200241086a41176a2009290000370000200241086a41106a200a290300370300200241086a41086a200b2903003703002002200229038001370308200220043a0027200241286a200241086a10ae012002410036028001200241286a412020024180016a1006210c024002400240200228028001220d417f460d002002200d36024c2002200c360248200241d0006a200241c8006a106d2002280250220e450d022002280254210f200228024c2204450d01200241d8006a280200211020022004417f6a220a36024c20022002280248221141016a220b36024820112d0000220441014b0d01410021120240024020040e020100010b4100210403400240200a2004470d002002410036024c0c040b2002201120046a41026a360248200441016a2209210420094120470d000b2002200a20096b220a36024c41012112201120096a41016a210b0b200a450d012002200a417f6a220a36024c2002200b41016a360248200b2d0000220941014b0d01410021040240024020090e020100010b41002104200241003a00a00103400240200a2004470d002002410036024c200441ff0171450d04200241003a00a0010c040b20024180016a20046a200b20046a220941016a2d00003a00002002200941026a3602482002200441016a22093a00a0012009210420094120470d000b200241e0006a41086a20024180016a41086a290300370300200241e0006a41106a20024180016a41106a290300370300200241e0006a41186a20024180016a41186a29030037030020022002290380013703602002200a20096b36024c410121040b20024180016a41186a2209200241e0006a41186a220a29030037030020024180016a41106a220b200241e0006a41106a221129030037030020024180016a41086a2213200241e0006a41086a2214290300370300200220022903603703800120124102460d02200a20092903003703002011200b2903003703002014201329030037030020022002290380013703600240200d450d00200c102a0b20024180016a41186a200241e0006a41186a2209290300220537030020024180016a41106a200241e0006a41106a220a290300220837030020024180016a41086a200241e0006a41086a220b29030022063703002002200229036022073703800120092005370300200a2008370300200b200637030020022007370360200120043a000020012007370001200141096a2006370000200141116a2008370000200141196a2005370000200041286a20103602002000200f3602242000200e36022020002002290308370000200041086a200241086a41086a290300370000200041106a200241086a41106a290300370000200041186a200241086a41186a290300370000200324000f0b41c9b4c00041dd001050000b200f450d00200e102a0b41c4d1c3004133200241d0006a419cd9c3001038000bfc0101057f230041306b220224000240411210282203450d0020034100290095ae44370000200341106a41002f00a5ae443b0000200341086a410029009dae4437000020024292808080a0023702042002200336020020012002108f012002280208210320022802002101200241106a41186a22044200370300200241106a41106a22054200370300200241106a41086a220642003703002002420037031020012003200241106a1000200041186a2004290300370000200041106a2005290300370000200041086a20062903003700002000200229031037000002402002280204450d002002280200102a0b200241306a24000f0b411241011037000bfe0703037f047e0a7f23002202210320024180036b41607122022400200141186a220429000021052004200229039802370000200129001021062001200229039002370010200129000821072001200229038802370008200241003a0080022001290000210820012002290380023700002002200537039801200220063703900120022007370388012002200837038001200141206a2d0000210420024180026a41176a2209200537000020024180026a41106a220a20022900910137030020024180026a41086a220b20022900890137030020022002290081013703800202402008a741ff01714101460d00200041073a0040200324000f0b200241186a41176a2009290000370000200241186a41106a200a290300370300200241186a41086a200b2903003703002002200229038002370318200220043a0037200241e0006a200241186a10b0012002410036028002200241e0006a412020024180026a1006210c0240200228028002220d417f460d002002200d36023c2002200c36023820024180026a200241386a10b101024020022d00a1024102460d00200241d8016a41206a220420024180026a41206a2d00003a0000200241d8016a41186a220920024180026a41186a220e290300370300200241d8016a41106a220a20024180026a41106a220f290300370300200241d8016a41086a220b20024180026a41086a221029030037030020022002290380023703d80120024180016a200241a2026a41c100109a051a0240200d450d00200c102a0b200241386a41206a220d20042d00003a0000200241386a41186a220c2009290300370300200241386a41106a2211200a290300370300200241386a41086a2212200b290300370300200220022903d80137033820024180026a20024180016a41c100109a051a2004200d2d00003a00002009200c290300370300200a2011290300370300200b2012290300370300200220022903383703d80120024180016a20024180026a41c100109a051a200141206a20024180016a41c0006a2d00003a0000200141186a20024180016a41386a290000370000200141106a20024180016a41306a290000370000200141086a20024180016a41286a290000370000200120022900a001370000200e200241186a41186a290300370300200f200241186a41106a2903003703002010200241186a41086a290300370300200220022903183703800220024180026a41286a200b29030037030020024180026a41306a200a29030037030020024180026a41386a200929030037030020024180026a41c0006a20042d00003a0000200220022903d8013703a002200020024180026a41c100109a051a200324000f0b41c4d1c300413320024180016a419cd9c3001038000b41c9b4c00041dd001050000bfc0101057f230041306b220224000240411510282203450d00200341002900d088453700002003410d6a41002900dd8845370000200341086a41002900d8884537000020024295808080d0023702042002200336020020012002108f012002280208210320022802002101200241106a41186a22044200370300200241106a41106a22054200370300200241106a41086a220642003703002002420037031020012003200241106a1000200041186a2004290300370000200041106a2005290300370000200041086a20062903003700002000200229031037000002402002280204450d002002280200102a0b200241306a24000f0b411541011037000bd30b03097f017e017f23004190026b2202240041002103200241003a00880220012802042204417d6a2105417f21060240024002400240024002400240034020042003460d01200241e8016a20036a200128020022072d00003a00002001200420066a3602042001200741016a3602002002200341016a22083a0088022005417f6a21052006417f6a21062008210320084120470d000b200241c8016a41186a200241e8016a41186a290300370300200241c8016a41106a200241e8016a41106a290300370300200241c8016a41086a200241e8016a41086a290300370300200220022903e8013703c80120042008460d0120072d000121092001200420066a3602042001200741026a360200200941074f0d01200241086a41186a200241c8016a41186a290300370300200241086a41106a200241c8016a41106a290300370300200241086a41086a200241c8016a41086a290300370300200220022903c8013703082004417f6a2008460d0520072d000221032001200741036a220a3602002001200420086b2206417e6a2208360204200341014b0d0520030e020302030b200341ff0171450d00200241003a0088020b200041023a00210c040b41002103200241003a0088022006417e6a2104417d21080340024020042003470d00200341ff0171450d04200241003a0088020c040b200241e8016a20036a200720036a220641036a2d00003a00002001200520036b3602042001200641046a3602002002200341016a22063a0088022008417f6a21082006210320064120470d000b200241a8016a41086a200241e8016a41086a290300220b37030020024188016a41186a200241e8016a41186a29030037030020024188016a41106a200241e8016a41106a29030037030020024188016a41086a200b370300200220022903e801220b3703a8012002200b370388014101210c200520066b41016a2108200720066a41036a210a0c010b4100210c0b200241e8006a41186a20024188016a41186a290300370300200241e8006a41106a20024188016a41106a290300370300200241e8006a41086a20024188016a41086a29030037030020022002290388013703682008450d00200a2d0000210320012008417f6a3602042001200a41016a360200200341014b0d00410021060240024020030e020100010b41002103200241003a0088022008417f6a21042008417e6a21060340024020042003470d00200341ff0171450d03200241003a0088020c030b200241e8016a20036a200a20036a220841016a2d00003a0000200120063602042001200841026a3602002002200341016a22083a0088022006417f6a21062008210320084120470d000b200241a8016a41086a200241e8016a41086a290300220b37030020024188016a41186a200241e8016a41186a29030037030020024188016a41106a200241e8016a41106a29030037030020024188016a41086a200b370300200220022903e801220b3703a8012002200b37038801410121060b200241286a41186a220320024188016a41186a290300370300200241286a41106a220120024188016a41106a290300370300200241286a41086a220820024188016a41086a290300370300200241c8006a41086a2204200241e8006a41086a290300370300200241c8006a41106a2205200241e8006a41106a290300370300200241c8006a41186a2207200241e8006a41186a290300370300200220022903880137032820022002290368370348200041186a200241086a41186a290300370000200041106a200241086a41106a290300370000200041086a200241086a41086a290300370000200020022903083700002000200c3a0021200020093a0020200041c2006a20063a0000200020022903483700222000412a6a2004290300370000200041326a20052903003700002000413a6a2007290300370000200041c3006a2002290328370000200041cb006a2008290300370000200041d3006a2001290300370000200041db006a20032903003700000c010b200041023a00210b20024190026a24000b340020004197dbc00036020420004100360200200041146a4103360200200041106a41bcbcc000360200200041086a42083702000b5201027f230041106b2202240002404104102822030d00410441011037000b20024204370204200220033602004100200210b401200041086a200228020836020020002002290300370200200241106a24000b920701037f0240024002400240024002402000413f4b0d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d06200241017422042003200420034b1b22044100480d060240024020020d002004102821030c010b200128020020022004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20004102743a00000f0b200041808001490d032000418080808004490d020c010b200441011037000b0240024002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102821030c010b200128020020022004102c21030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a000002400240200141046a2802002203200428020022026b4104490d00200128020021030c010b200241046a22042002490d05200341017422022004200220044b1b22024100480d050240024020030d002002102821030c010b200128020020032002102c21030b2003450d0220012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20003600000f0b200441011037000b200241011037000b024002400240200141046a2802002203200141086a28020022026b4104490d00200128020021030c010b200241046a22042002490d03200341017422022004200220044b1b22024100480d030240024020030d002002102821030c010b200128020020032002102c21030b2003450d0120012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20004102744102723600000f0b200241011037000b024002400240200141046a2802002203200141086a28020022026b4102490d00200128020021030c010b200241026a22042002490d02200341017422022004200220044b1b22024100480d020240024020030d002002102821030c010b200128020020032002102c21030b2003450d0120012003360200200141046a2002360200200141086a28020021020b200141086a200241026a360200200320026a20004102744101723b00000f0b200241011037000b1031000bd82504027f027e087f037e230041b00d6b220724000240024002402001280230200128024022082802b801460d002004420020042903082209200841c0006a2903007d220a200a20095622081b3703082008450d0120004188c5c00036020420004101360200200041086a412a3602002000410c6a2006290200370200200041146a200641086a2802003602000c020b200041f3c3c00036020420004101360200200041086a41293602002000410c6a2006290200370200200041146a200641086a2802003602000c010b200741186a41186a200141e8006a290000370300200741186a41106a200141e0006a290000370300200741186a41086a200141d8006a290000370300200720012900503703182006280208210b20062802002108200741b0026a41186a220c4200370300200741b0026a41106a220d4200370300200741b0026a41086a220e4200370300200742003703b0022008200b200741b0026a1000200741d00a6a41186a200c290300370300200741d00a6a41106a200d290300370300200741d00a6a41086a200e290300370300200720072903b0023703d00a0240024002400240024002400240024002400240412010282208450d0020082005290000370000200841186a200541186a290000370000200841106a200541106a290000370000200841086a200541086a2900003700002008412041c000102c2208450d01200820072903d00a370020200841386a200741d00a6a41186a290300370000200841306a200741d00a6a41106a290300370000200841286a200741d00a6a41086a290300370000200841c000418001102c2208450d0220082007290318370040200841d8006a200741186a41186a290300370000200841d0006a200741186a41106a290300370000200841c8006a200741186a41086a290300370000200741b0026a41186a220c4200370300200741b0026a41106a220d4200370300200741b0026a41086a220e4200370300200742003703b002200841e000200741b0026a1000200741386a41186a220f200c290300370300200741386a41106a220c200d290300370300200741386a41086a220d200e290300370300200720072903b0023703382008102a20062902002109200741d8006a41d8006a200d290300370300200741d8006a41e0006a200c290300370300200741c0016a200f29030037030020074194016a410036020020074184016a419cc4c000360200200741f8006a4200370300200741f4006a221041f8b9c00036020020072001360260200741d8006a41286a200141186a2211360200200720072903383703a8012007420837028c012007410036027020074100360264200720012802483602a00120072001290340370398012007200128023041016a360288012001290300210a2007200128024c3602a4012007200a370358200741c8016a41186a200541186a290000370300200741c8016a41106a200541106a290000370300200741c8016a41086a200541086a29000037030020074101360270200720052900003703c8012011200741386a10b601210620072007280270417f6a2208360270024020060d0020080d042007417f36027020074190026a41186a200741386a41186a29030037030020074190026a41106a200741386a41106a29030037030020074190026a41086a200741386a41086a2903003703002007200729033837039002024002402007280274220e41f8b9c000460d002007280278210f0c010b4100210f200741d00a6a410041e0021099051a200741b0026a410041a0081099051a41880b1028220e450d06200e41003b0106200e4100360200200e41086a200741d00a6a41e002109a051a200e41e8026a200741b0026a41a008109a051a200741003602782007200e3602740b024002400340200e41086a2108200e2f0106221241057421064100210c0240024003402006450d0120074190026a20084120109c05220d450d02200641606a2106200c41016a210c200841206a2108200d417f4a0d000b200c417f6a21120b200f450d02200f417f6a210f200e20124102746a41880b6a280200210e0c010b0b200e200c41e0006c6a41e8026a21060c010b200741f0016a41186a20074190026a41186a290300220a370300200741f0016a41106a20074190026a41106a2903002213370300200741f0016a41086a20074190026a41086a2903002214370300200720072903900222153703f001200741ec0a6a2014370200200741d00a6a41246a2013370200200741fc0a6a200a3702002007200741d8006a41246a3602e00a200720123602dc0a200720103602d80a2007200e3602d40a200741003602d00a200720153702e40a200741e4026a4200370200200741003a00ec02200742003703b002200741003a008d03200741f8b9c0003602e002200742003703c802200741d00a6a200741b0026a10b70121060b200741e0016a290300210a20064201370318200641013a003c200641286a427f370300200641206a427f3703002006413d6a20072903c801370000200641d5006a200a370000200641cd006a200741d8016a290300370000200641c5006a200741d0016a2903003700002007200728027041016a360270200741106a20044101200741186a200741386a20022003200741d8006a10b8012007280210220e0d06200741b0026a200520072802a00128020010b901024020072802b0024101470d002009422088a72106200741b8026a280200210520072802b402210e2009a721010c0b0b20074190026a41186a200741b0026a410472220641186a2802002208360200200741d00a6a41106a200641086a290200370300200741d00a6a41186a200641106a290200370300200741f00a6a2008360200200741063602d40a200741b38dc6003602d00a200720062902003703d80a200728029c0121062007200741d8006a3602c8022007290358210a20072802a4012108200741d8026a200741186a41086a290300370300200741e0026a200741186a41106a290300370300200741e8026a200741186a41186a290300370300200720033703b802200720023703b002200720083602cc022007200a3703c002200720072903183703d0022007200b3602f801200720093703f00120074190026a2006200741d00a6a200741b0026a200741f0016a200410ba012007419c026a290200210220074190026a41086a2802002112200728029402210f02402007280290024101470d002002422088a72106200741a4026a280200210b2002a7210120122105200f210e0c0a0b200728027041016a220b41004c0d072007200b360270200728027821040240024003402010280200220541086a210820052f0106220e41057421064100210c0240024003402006450d01200741386a20084120109c05220d450d02200641606a2106200c41016a210c200841206a2108200d417f4a0d000b200c417f6a210e0b2004450d022004417f6a21042005200e4102746a41880b6a21100c010b0b2005200c41e0006c6a220641c5036a310000200641e8026a290300220320035022081ba7450d004200200641f8026a29030020081b21034200200641f0026a29030020081b21090c010b2007200728028001200741386a20072802840128021c110500200741086a2903002103200729030021092007280270210b0b2007200b417f6a3602702009200728029801220629037854200320064180016a29030022095420032009511b450d082002a7210b41c0c4c000210e411e2105200f2101201221060c090b2009422088a721062009a7210141dec4c000210e412a21050c090b412041011037000b41c00041011037000b41800141011037000b41a8b8c0004110200741b0026a41d0b8c0001038000b41880b41081037000b200728021421052009422088a721062009a721010c030b41b8b8c0004118200741b0026a41e0b8c0001038000b20074190026a41086a2208200741186a41086a29030037030020074190026a41106a220c200741186a41106a29030037030020074190026a41186a220d200741186a41186a290300370300200741f0016a41086a2205200741386a41086a290300370300200741f0016a41106a2204200741386a41106a290300370300200741f0016a41186a220e200741386a41186a2903003703002007200729031837039002200720072903383703f00102400240024002402007280294012206200728029001470d00200641016a220b2006490d0320064101742210200b2010200b4b1b2210ad42b0017e2203422088a70d032003a7220b4100480d030240024020060d00200b102821060c010b200728028c01200641b0016c200b102c21060b2006450d0120072010360290012007200636028c0120072802940121060b200728028c01200641b0016c6a220641003a0000200620072f00ed013b0001200641013a00102006410036000c200642013700042006200729039002370011200620072903f001370031200641036a200741ef016a2d00003a0000200641196a2008290300370000200641216a200c290300370000200641296a200d290300370000200641396a2005290300370000200641c1006a2004290300370000200641c9006a200e290300370000200641e0006a200741d7016a290000370000200641d9006a200741c8016a41086a290000370000200620072900c801370051200641e8006a200741b0026a41c800109a051a200720072802940141016a2208360294010240200741d00a6a41186a280200450d00200741e40a6a280200102a20072802940121080b200728029001210e200728028c012105200728027c210b2007280278210d2007280274210602402007280264220c450d00200741e8006a280200450d00200c102a0b0240024020024280808080f01f8350450d002007200b3602b8022007200d3602b402200720063602b0022011200741b0026a10bb012007200e3602b402200720053602b00220072005200841b0016c22086a22043602bc0202400240200141386a280200220c2001413c6a28020022066b200841b0016d220d490d002001280234210c0c010b2006200d6a220e2006490d05200c4101742206200e2006200e4b1b2206ad42b0017e2203422088a70d052003a7220e4100480d0502400240200c0d00200e1028210c0c010b2001280234200c41b0016c200e102c210c0b200c450d042001200c360234200141386a20063602002001413c6a28020021060b200c200641b0016c6a20052008109a051a2001413c6a22062006280200200d6a360200200720043602b802200741b0026a10690c010b02402008450d00200841b0016c210441002108034002400240200520086a220c2d0000220141014b0d000240024020010e020001000b0240200c41086a280200450d00200c41046a280200102a0b200c41106a2d00004105490d02200c41386a280200450d02200c41346a280200102a0c020b200c41286a106a0c010b200c41e8006a280200450d00200c41e4006a280200102a0b2004200841b0016a2208470d000b0b0240200e450d002005102a0b02400240200d0d00200621080c010b200d210c20062108034020082802880b2108200c417f6a220c0d000b0340200620062f01064102746a41880b6a2802002106200d417f6a220d0d000b0b200741cc026a20062f0106360200200741c8026a4100360200200741c4026a20063602002007200b3602d002200741003602c002200742003703b802200720083602b402200741003602b002200741b0026a109b010b20002007290338370004200041003602002000412c6a2002370200200041286a2012360200200041246a200f3602002000411c6a200741d0006a290300370000200041146a200741c8006a2903003700002000410c6a200741c0006a2903003700000c050b200b41081037000b200e41081037000b1031000b200741e80a6a280200450d00200741e40a6a280200102a0b024020072802642208450d00200741e8006a280200450d002008102a0b2006ad2102200728027c21042007280274210602400240200728027822080d002006210c0c010b2008210d2006210c0340200c2802880b210c200d417f6a220d0d000b0340200620062f01064102746a41880b6a28020021062008417f6a22080d000b0b200242208621022001ad2103200741cc026a20062f010636020041002108200741c8026a4100360200200741c4026a2006360200200720043602d002200741003602c002200742003703b8022007200c3602b402200741003602b002200741b0026a109b0102402007280294012206450d00200728028c01210d200641b0016c2101034002400240200d20086a22062d0000220c41014b0d0002400240200c0e020001000b0240200641086a280200450d00200641046a280200102a0b200641106a2d00004105490d02200641386a280200450d02200641346a280200102a0c020b200641286a106a0c010b200641e8006a280200450d00200641e4006a280200102a0b2001200841b0016a2208470d000b0b200220038421020240200728029001450d00200728028c01102a0b2000200e36020420004101360200200041146a200b3602002000410c6a2002370200200041086a20053602000b200741b00d6a24000bb80201097f230041106b220224000240200028020041016a220341004c0d0020002003360200200041046a2104200041086a280200210502400240024003402004280200220641086a210720062f010622084105742104410021090240024003402004450d01200120074120109c05220a450d02200441606a2104200941016a2109200741206a2107200a417f4a0d000b2009417f6a21080b2005450d022005417f6a2105200620084102746a41880b6a21040c010b0b2006200941e0006c6a220441a4036a2d000022074101410220074101461b200441c5036a2d00001b22044102470d010b20002802102001200041146a2802002802181101002104200028020021030c010b200441014621040b20002003417f6a360200200241106a240020040f0b41b8b8c0004118200241086a41e0b8c0001038000b8f1901187f230041d0116b2202240020002802102203200328020041016a360200200028020c21042000280208210520002802042103200241206a41186a22062000412c6a290000370300200241206a41106a2207200041246a290000370300200241206a41086a22082000411c6a29000037030020022000290014370320200241a0026a200141e000109a051a024002400240024020032f01062201410b490d00200241b0036a410041e0021099051a20024198066a410041a0081099051a0240024041880b10282209450d00200941003b010620094100360200200941086a200241b0036a41e002109a052101200941e8026a20024198066a41a008109a052106200220032f00c8013b01ac032002200341ca016a2d00003a00ae03200220032900db01370398032002200341e0016a29000037009d03200341cb016a280000210a200341cf016a280000210b200341d3016a280000210c200341d7016a280000210d20024198066a200341a8076a41e000109a051a2001200341e8016a20032f010641796a2200410574109a052101200620034188086a200041e0006c109a052106200341063b0106200920003b0106200220022f01ac033b019403200220022d00ae033a0096032002200229039803370380032002200229009d0337008503200241b0036a20024198066a41e000109a051a0240024020044107490d00200441057420016a41c07e6a2001200441796a22074105746a2201200041ffff037120076b410574109b051a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200441e0006c20066a220041c07b6a200041e07a6a220e200941066a22002f010020076b41e0006c109b051a200e200241a0026a41e000109a051a0c010b200341086a20044105746a220141206a2001200341066a22002f010020046b410574109b051a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200341e8026a200441e0006c6a220e41e0006a200e20002f010020046b41e0006c109b051a200e200241a0026a41e000109a051a0b20024188026a41026a220420022d0096033a0000200020002f010041016a3b0100200220022f0194033b01880220022002290380033703800120022002290085033700850120024190016a200241b0036a41e000109a051a2002411c6a41026a220f20042d00003a0000200220022f0188023b011c2002200229038001370308200220022900850137000d200241206a20024190016a41e000109a051a20032802002206450d0320032f0104211020024198066a410272211103402002419c026a41026a2212200f2d00003a0000200220022f011c3b019c0220022002290308370388022002200229000d37008d02200241a0026a200241206a41e000109a051a201041ffff0371210702400240024020062f01062203410b490d002011410041b20b1099051a41b80b10282201450d0520014100360200200141046a20024198066a41b40b109a051a200220062f00c8013b01ac032002200641ca016a2d00003a00ae03200220062900db01370398032002200641e0016a29000037009d03200641cb016a2800002113200641cf016a2800002114200641d3016a2800002115200641d7016a280000211620024198066a200641a8076a41e000109a051a200141086a200641e8016a20062f0106220041796a2203410574109a052117200141e8026a20064188086a200341e0006c109a052118200141880b6a200641a40b6a2000417a6a2208410274109a052119200641063b0106200120033b010602402008450d00410021032019210003402000280200220420033b010420042001360200200041046a21002008200341016a2203470d000b0b200241b0036a20024198066a41e000109a051a200220022d00ae0322033a009603200220022f01ac0322003b0194032002200229009d033700850320022002290398033703800320024194066a41026a220820033a0000200220003b01940620022002290380033703800120022002290085033700850120024198066a200241b0036a41e000109a051a201041ffff037122004107490d0120172007417a6a22044105746a2017200741796a22034105746a220020012f010620036b410574109b051a200041186a200229008d023700002000200d36000f2000200c36000b2000200b3600072000200a360003200041026a20122d00003a0000200020022f019c023b00002000200229038802370013200741e0006c20186a220041c07b6a200041e07a6a220020012f010620036b41e0006c109b051a2000200241a0026a41e000109a051a200120012f010641016a22003b01062007410274220a20196a416c6a201920044102746a2210200041ffff0371220720046b410274109b051a2010200936020020072004490d022001200a6a41f00a6a2100034020002802002204200341016a22033b010420042001360200200041046a210020032007490d000c030b0b200641086a2200200741016a22044105746a200020074105746a2200200320076b2201410574109b051a2000200d36000f2000200c36000b2000200b3600072000200a360003200041026a2002419c026a41026a2d00003a0000200020022f019c023b00002000200229038802370013200041186a200229008d023700002006200741e0006c6a220041c8036a200041e8026a2200200141e0006c109b051a2000200241a0026a41e000109a051a2006200341016a22033b01062007410274200641880b6a22006a41086a200020044102746a2200200341ffff037120046b410274109b051a20002009360200201041ffff037120062f010622034f0d07200920043b010420092006360200200420034f0d072003417f6a210120062004417f6a22034102746a41900b6a2100034020002802002204200341026a3b010420042006360200200041046a21002001200341016a2203470d000c080b0b200641086a2203200741016a22044105746a200320074105746a220320062f0106221020076b2219410574109b051a2003200d36000f2003200c36000b2003200b3600072003200a360003200341026a20122d00003a0000200320022f019c023b00002003200229038802370013200341186a200229008d02370000200641e8026a200741e0006c6a220341e0006a2003201941e0006c109b051a2003200241a0026a41e000109a051a2006201041016a22033b010620074102742219200641880b6a22106a41086a201020044102746a2210200341ffff037120046b410274109b051a20102009360200200020062f010622044f0d00200620196a418c0b6a2103034020032802002200200741016a22073b010420002006360200200341046a210320042007470d000b0b20024184026a41026a220320082d00003a0000200220022f0194063b01840220022002290380013703f00120022002290085013700f50120024190016a20024198066a41e000109a051a200f20032d00003a0000200220022f0184023b011c200220022903f001370308200220022900f50137000d200241206a20024190016a41e000109a051a0240200628020022030d002013210a2016210d2015210c2014210b200121090c050b20062f010421102013210a2016210d2015210c2014210b20032106200121090c000b0b41880b41081037000b41b80b41081037000b200320044105746a220041286a200041086a2210200120046b410574109b051a200041206a2006290300370000200041186a2007290300370000200041106a2008290300370000201020022903203700002003200441e0006c6a220041c8036a200041e8026a220e20032f010620046b41e0006c109b051a200e200241a0026a41e000109a051a200320032f010641016a3b01060c010b20024198066a410272410041b20b1099051a41b80b10282203450d0120034100360200200341046a20024198066a41b40b109a051a2003200528020022003602880b200520033602002005200528020441016a360204200041003b010420002003360200200320032f010622044105746a220041086a20022f011c3b00002000410a6a2002411c6a41026a2d00003a0000200041176a200d360000200041136a200c3600002000410f6a200b3600002000410b6a200a3600002000411b6a2002290308370000200041206a200229000d3700002003200441e0006c6a41e8026a200241206a41e000109a051a200341880b6a200441016a22004102746a2009360200200320003b0106200920003b0104200920033602000b200241d0116a2400200e0f0b41b80b41081037000b9f19020a7f087e230041800c6b220824000240024002400240024002400240024002400240200728021841016a220941004c0d0020072009360218200741206a280200210a2007411c6a220b210c024002400340200c280200220d41086a210e200d2f0106220f410574210c41002110024002400340200c450d012004200e4120109c052211450d02200c41606a210c201041016a2110200e41206a210e2011417f4a0d000b2010417f6a210f0b200a450d02200a417f6a210a200d200f4102746a41880b6a210c0c010b0b200d201041e0006c6a220c41c5036a310000200c41e8026a2903002212201250220e1ba7450d004200200c41f8026a290300200e1b21134200200c41f0026a290300200e1b21140c010b200841286a200741286a28020020042007412c6a28020028021c110500200841306a290300211320072802182109200829032821140b20072009417f6a360218200141186a29030021122007280240210c20012903102115024002400240024041004101410220142013842216501b20021b0e03010200010b200c41a8016a210c0c020b200c4188016a210c0c010b200c4198016a210c0b20152012844200510d01200841186a200c290300200c41086a2903002015201210a00520014200200129030822122008290318427f200841186a41086a290300501b7d22152015201256220c1b3703080240200c450d0041b2c5c000210c4122210e0c0a0b200728021841016a220141004c0d02200720013602182007280220210a200b210c024002400340200c280200220d41086a210e200d2f0106220f410574210c41002110024002400340200c450d012003200e4120109c052211450d02200c41606a210c201041016a2110200e41206a210e2011417f4a0d000b2010417f6a210f0b200a450d02200a417f6a210a200d200f4102746a41880b6a210c0c010b0b200d201041e0006c6a220c41c5036a310000200c41e8026a2903002212201250220e1ba7450d004200200c41f8026a290300200e1b21124200200c41f0026a290300200e1b21150c010b200841086a200741286a28020020032007412c6a28020028021c110500200841106a290300211220072802182101200829030821150b20072001417f6a3602180240201520057d2217201556201220067d2015200554ad7d221520125620152012511b4101470d00419893c100210c411d210e0c0a0b024020164200520d002007280240220c290378200556200c4180016a290300221220065620122006511b450d0041e293c100210c411f210e0c0a0b2008200341022017201510bc0102402008280200220c450d002008280204210e0c0a0b0240201420057c2216201454220c201320067c200cad7c221220135420122013511b450d0041b593c100210c412d210e0c0a0b4100210c024020032004470d000c0a0b0240200320044120109c050d000c0a0b20072802180d032007417f360218200841e0006a41186a200341186a290000370300200841e0006a41106a200341106a290000370300200841e0006a41086a200341086a2900003703002008200329000037036002400240200728021c221141f8b9c000460d002007280220210a0c010b4100210a200841a0096a410041e0021099051a20084180016a410041a0081099051a41880b10282211450d05201141003b010620114100360200201141086a200841a0096a41e002109a051a201141e8026a20084180016a41a008109a051a200741003602202007201136021c0b02400240034020112f0106220f410574210d4100210c4100210e02400340200d200c460d01200841e0006a2011200c6a41086a4120109c052210450d03200c41206a210c200e41016a210e2010417f4a0d000b200e417f6a210f0b0240200a450d00200a417f6a210a2011200f4102746a41880b6a28020021110c010b0b200841c0006a41186a200841e0006a41186a2903002213370300200841c0006a41106a200841e0006a41106a2903002214370300200841c0006a41086a200841e0006a41086a2903002218370300200820082903602219370340200841bc096a2018370200200841a0096a41246a2014370200200841cc096a20133702002008200741246a22013602b0092008200f3602ac092008200b3602a809200820113602a409200841003602a009200820193702b409200841b4016a4200370200200841bc016a41003a0000200841f8b9c0003602b00120084200370398012008420037038001200841003a00dd01200841a0096a20084180016a10b701210c0c010b20084198016a420037030020084194016a41f8b9c000360200200841003602a00120084100360290012008420037038801200841f8b9c000360284012008410036028001200741246a21012011200e41e0006c6a41e8026a210c20084180016a1095010b200c41106a2015370300200c2017370308200c420137030020072007280218220c41016a220e360218200e200c4f0d052007417f360218200841e0006a41186a200441186a290000370300200841e0006a41106a200441106a290000370300200841e0006a41086a200441086a2900003703002008200429000037036002400240200728021c221141f8b9c000460d002007280220210a0c010b4100210a200841a0096a410041e0021099051a20084180016a410041a0081099051a41880b10282211450d07201141003b010620114100360200201141086a200841a0096a41e002109a051a201141e8026a20084180016a41a008109a051a200741003602202007201136021c0b02400240034020112f0106220f410574210d4100210c4100210e02400340200d200c460d01200841e0006a2011200c6a41086a4120109c052210450d03200c41206a210c200e41016a210e2010417f4a0d000b200e417f6a210f0b0240200a450d00200a417f6a210a2011200f4102746a41880b6a28020021110c010b0b200841c0006a41186a200841e0006a41186a2903002215370300200841c0006a41106a200841e0006a41106a2903002213370300200841c0006a41086a200841e0006a41086a2903002214370300200820082903602217370340200841bc096a2014370200200841c4096a2013370200200841cc096a2015370200200820013602b0092008200f3602ac092008200b3602a809200820113602a409200841003602a009200820173702b409200841b4016a4200370200200841bc016a41003a0000200841f8b9c0003602b00120084200370398012008420037038001200841003a00dd01200841a0096a20084180016a10b701210c0c010b20084198016a420037030020084194016a41f8b9c000360200200841003602a00120084100360290012008420037038801200841f8b9c0003602840120084100360280012011200e41e0006c6a41e8026a210c20084180016a1095010b200c41106a2012370300200c2016370308200c42013703002007200728021841016a360218200841a0096a41086a2210200341086a290000370300200841a0096a41106a2211200341106a290000370300200841a0096a41186a220d200341186a290000370300200841e0006a41086a220a200441086a290000370300200841e0006a41106a220f200441106a290000370300200841e0006a41186a2201200441186a290000370300200820032900003703a0092008200429000037036002402007413c6a280200220e200741386a280200470d00200e41016a220c200e490d09200e4101742204200c2004200c4b1b2203ad42b0017e2212422088a70d092012a722044100480d0902400240200e0d0020041028210c0c010b2007280234200e41b0016c2004102c210c0b200c450d082007200c360234200741386a2003360200200728023c210e0b4100210c2007280234200e41b0016c6a220e41003a0000200e20082f003d3b0001200e4200370008200e4101360004200e20082903a009370011200e2008290360370031200e41036a2008413f6a2d00003a0000200e41106a41003a0000200e41196a2010290300370000200e41216a2011290300370000200e41296a200d290300370000200e41396a200a290300370000200e41c1006a200f290300370000200e41c9006a2001290300370000200e2005370358200e41e0006a2006370300200e41d4006a200841c0006a41036a280000360000200e2008280040360051200e41e8006a20084180016a41c800109a051a2007200728023c41016a36023c0c090b41b8b8c000411820084180016a41e0b8c0001038000b419cb7c0001032000b41b8b8c000411820084180016a41e0b8c0001038000b41a8b8c000411020084180016a41d0b8c0001038000b41880b41081037000b41a8b8c000411020084180016a41d0b8c0001038000b41880b41081037000b200441081037000b1031000b2000200e3602042000200c360200200841800c6a24000bb011030b7f017e047f230041b0016b220324000240024002400240024002400240024002400240411410282204450d00200441002900ddd843370000200441106a41002800edd843360000200441086a41002900e5d84337000020034294808080c00237023c200320043602382003200341386a36028001200120034180016a10c801200328023821042003280240210520034180016a41186a2206420037030020034180016a41106a2207420037030020034180016a41086a2208420037030020034200370380012004200520034180016a1000200341d8006a41186a2006290300370300200341d8006a41106a2007290300370300200341d8006a41086a200829030037030020032003290380013703580240200328023c450d002003280238102a0b2003410036028001200341d8006a412020034180016a100621062003280280012209417f460d032006450d0320032009360284012003200636028001200341286a20034180016a106c20032802280d02200328022c2105200341206a20034180016a106c20032802200d0220032802242108200341186a20034180016a106c20032802180d022003280284012204450d02200328021c210a20032004417f6a360284012003200328028001220441016a3602800120042d0000220441014b0d024100210b0240024020040e020100010b4101210b0b200341106a20034180016a106c20032802100d02200328028401220c20032802142204490d022004417f4c0d050240024020040d00410121070c010b2004102e2207450d022007200328028001220d2004109a051a2003200c20046b360284012003200d20046a360280010b2007450d02200341a0016a41026a220c200341386a41026a220d2d00003a0000200320032f00383b01a00102402009450d002006102a0b200d200c2d000022063a0000200341346a41026a20063a0000200320032f01a00122063b0138200320063b0134410021060c040b411441011037000b200441011037000b41c4d1c3004133200341386a419cd9c3001038000b4101210641d2bfc2002105411121084102210b0b200341306a41026a2209200341346a41026a220c2d00003a0000200320032f01343b013002402006450d002000200536020420004101360200200041086a20083602000c050b200c20092d00003a0000200320032f01303b013402400240200228025820054b0d002004210620042102200721090c010b411510282205450d02200541002900c8d8433700002005410d6a41002900d5d843370000200541086a41002900d0d84337000020034295808080d00237023c200320053602382003200341386a36028001200120034180016a10c801200328023821052003280240210620034180016a41186a2208420037030020034180016a41106a2209420037030020034180016a41086a220b420037030020034200370380012005200620034180016a1000200341d8006a41186a2008290300370300200341d8006a41106a2009290300370300200341d8006a41086a200b29030037030020032003290380013703580240200328023c450d002003280238102a0b2003410036028001200341d8006a412020034180016a100621060240024002402003280280012208417f460d002006450d0020032008360284012003200636028001200341086a20034180016a106c02400240024020032802080d002003280284012209200328020c2205490d002005417f4c0d070240024020050d004101210c0c010b2005102e220c450d02200c200328028001220b2005109a051a2003200920056b360284012003200b20056a360280010b200c0d020b41c4d1c3004133200341386a419cd9c3001038000b200541011037000b2005ad220e422086200e84210e02402008450d002006102a0b20034180016a200c200e422088a7200210f802200ea7210d20034180016a41086a280200210820032802840121052003280280014101470d022000200536020420004101360200200041086a2008360200200d450d01200c102a0c010b200041e3bfc20036020420004101360200200041086a411a3602000b2004450d062007102a0c060b200341d8006a41026a220f2003419f016a2d00003a0000200320032f009d013b01582003419c016a2d0000210b20034198016a280200210620034194016a280200210220034190016a28020021092003418c016a280200210a02402004450d002007102a0b200341346a41026a200f2d00003a0000200320032f01583b01342006417f4c0d010240024020060d0041002107410121040c010b20062107200610282204450d040b200420092006109a05210f200341386a41146a2006360200200341386a41106a20073602002003200a3602402003200836023c200320053602382003200f3602442003200b41ff01714101463a0050411410282204450d04200441002900ddd843370000200441106a41002800edd843360000200441086a41002900e5d84337000020034294808080c0023702a401200320043602a0012003200341a0016a36028001200120034180016a10c80120032802a001210420032802a801210120034180016a41186a2210420037030020034180016a41106a2211420037030020034180016a41086a2212420037030020034200370380012004200120034180016a1000200341d8006a41186a2010290300370300200341d8006a41106a2011290300370300200341d8006a41086a20122903003703002003200329038001370358024020032802a401450d0020032802a001102a0b20034120360284012003200341d8006a36028001200341386a20034180016a10f90202402007450d00200f102a0b200d450d00200c102a0b20002005360204200020032f01343b001d200041003602002000411c6a200b3a0000200041186a2006360200200041146a2002360200200041106a20093602002000410c6a200a360200200041086a20083602002000411f6a200341366a2d00003a00000c040b1036000b411541011037000b200641011037000b411441011037000b200341b0016a24000b821d02097f017e230041e0006b22062400024002402002410c6a280200200241106a280200100f2207417f460d00410c102822080d01410c41041037000b10fc02000b200820073602082008428180808010370200200641186a420037030020064280808080c0003703102006420437030802400240024002400240024002400240024002400240024002400240024002402008280200220741016a220941014d0d00200820093602002007417e460d002008200741026a3602000240200628021c22072006280218470d00200741016a22092007490d0b2007410174220a2009200a20094b1b220941ffffffff03712009470d0b2009410274220b4100480d0b0240024020070d00200b1028210a0c010b20062802142007410274200b102c210a0b200a450d02200620093602182006200a3602140b200628021420074102746a20083602002006200628021c41016a36021c2008280208210b410310282209450d02200941026a41002d00fae2453a0000200941002f00f8e2453b000041061028220a450d03200a41046a41002f00cf8f443b0000200a41002800cb8f44360000024020062802102207200628020c470d00200741016a220c2007490d0b2007410174220d200c200d200c4b1b220c41ffffff3f71200c470d0b200c410574220e4100480d0b0240024020070d00200e1028210d0c010b20062802082007410574200e102c210d0b200d450d052006200c36020c2006200d3602080b200628020820074105746a220741013602182007200a36020c2007428380808030370204200720093602002007411c6a200b360200200741106a4286808080e0003702002006200628021041016a36021020082008280200417f6a2207360200024020070d002008280208101020082008280204417f6a220736020420070d002008102a0b200641086a41f8e2c500410341effec5004103410b10fe02200641086a41f8e2c500410341f2fec500410f410c10fe02200641086a41f8e2c50041034181ffc500410f410d10fe02200641086a41f8e2c50041034190ffc5004108410e10fe02200641086a41f8e2c50041034198ffc500410f410f10fe02200641086a41f8e2c500410341a7ffc500410a411010fe02200641086a41f8e2c500410341b1ffc500410a411110fe02200641086a41f8e2c500410341bbffc500410b411210fe02200641086a41f8e2c500410341c6ffc500410d411310fe02200641086a41f8e2c500410341d3ffc500410c411410fe02200641086a41f8e2c500410341dfffc500410b411510fe02200641086a41f8e2c500410341eaffc5004115411610fe02200641086a41f8e2c500410341ffffc500410a411710fe02200641086a41f8e2c5004103418980c6004107411810fe02200641086a41f8e2c5004103419080c6004113411910fe02200641086a41f8e2c500410341a380c6004111411a10fe02200641086a41f8e2c500410341b480c600410e411b10fe02200641086a41f8e2c500410341c280c6004110411c10fe02200641086a41f8e2c500410341d280c6004110411d10fe02200641086a41f8e2c500410341e280c6004111411e10fe02200641086a41f8e2c500410341f380c6004111411f10fe02200641086a41f8e2c5004103418481c6004116412010fe02200641086a41f8e2c5004103419a81c6004112412110fe02200641086a41f8e2c500410341ac81c600410b412210fe02200641086a41f8e2c500410341b781c6004110412310fe02200641206a410c6a200441086a280200360200200620033602204100210d2006410036023c20062005360238200620083602342006200429020037022420062001280200360230200241146a280200210b2002411c6a280200210c200628020821072006280210210820064100360258200642013703502008200641d0006a10b40102402008450d00200720084105746a2105034020072802002104200741086a2802002208200641d0006a10b401024002402006280254220a200628025822096b2008490d002006280250210a0c010b200920086a22012009490d0d200a41017422032001200320014b1b22014100480d0d02400240200a0d0020011028210a0c010b2006280250200a2001102c210a0b200a450d08200620013602542006200a3602500b2006200920086a360258200a20096a20042008109a051a2007410c6a2802002103200741146a280200220a200641d0006a10b4010240024020062802542209200628025822046b200a490d00200628025021080c010b2004200a6a22082004490d0d200941017422012008200120084b1b22014100480d0d0240024020090d002001102821080c010b200628025020092001102c21080b2008450d092006200136025420062008360250200121090b20062004200a6a2201360258200820046a2003200a109a051a02400240200741186a2802004101460d000240024020092001460d002009210a0c010b200941016a220a2009490d0f20094101742204200a2004200a4b1b220a4100480d0f0240024020090d00200a102821080c010b20082009200a102c21080b2008450d0c2006200a360254200620083602500b2006200141016a2209360258200820016a41013a000020062007411c6a2802002204360248200641c8006a21010c010b0240024020092001460d002009210a0c010b200941016a220a2009490d0e20094101742204200a2004200a4b1b220a4100480d0e0240024020090d00200a102821080c010b20082009200a102c21080b2008450d0c2006200a360254200620083602500b2006200141016a2209360258200820016a41023a000020062007411c6a2802002204360248200641c8006a21010b0240200a20096b41034b0d00200941046a22042009490d0d200a41017422032004200320044b1b22044100480d0d02400240200a0d002004102821080c010b2008200a2004102c21080b2008450d0c2006200436025420062008360250200128020021040b2006200941046a360258200820096a2004360000200741206a22072005470d000b0b2006280254210302404124200b200c2006280250220e2006280258200641206a1011220b41036a220841024b0d000240024020080e03000201000b4102210d0b41012104024020030d000c110b200e102a0c100b200628021c220541ffffffff03712005470d0b20054102742207417f4c0d0b200628021421080240024020070d004104210c0c010b20071028220c450d0d0b0240024020050d004100210a0c010b200541027421044100210a200c210703402008280200220928020041016a220141014d0d022009200136020020072009360200200a41016a210a200741046a2107200841046a21082004417c6a22040d000b0b02402003450d00200e102a0b200228020421092002280200210420064100360258200642013703504100200641d0006a10b401200628025821012006280254210220062802502107410a102e2208450d0d0240024002400240200b20042009200720012008410a200641206a101241036a220941034b0d004101210420090e0402000001020b41a8c7c2001032000b2006410936024c410121042006200841016a36024820082d0000220941014b0d01410421010240024020090e020100010b200641d0006a200641c8006a109803200628025022014104460d02200628025421030b410021040b2008102a2002450d0f2007102a0c0f0b2008102a024020020d000c0f0b2007102a0c0e0b00000b200b41041037000b410341011037000b410641011037000b200e41041037000b200141011037000b200141011037000b200a41011037000b200a41011037000b200441011037000b1031000b1036000b200741041037000b410a41011037000b200b10130240200a450d00200a4102742107200c21080340200828020022092009280200417f6a3602000240200828020022092802000d0020092802081010200828020022092009280204417f6a360204200828020022092802040d002009102a0b200841046a21082007417c6a22070d000b0b4102210d2005450d00200c102a0b200641206a41086a28020021072006280234210820062802242109024002400240024002400240024002400240200628023c220a0d002006412c6a290200210f20040d04200141044b0d0320010e050203030301020b2000200a36020420004100360200200041106a41003a0000200041086a200641c0006a29030037020002402007450d002009102a0b20082008280200417f6a220736020020070d072008280208101020082008280204417f6a22073602042007450d060c070b2000200936020441002109200041106a41003a00002000410c6a4100360200200041086a20073602000c040b20002009360204200041106a20033a00002000410c6a200f3e0200200041086a2007360200410021090c030b200041aa9cc400360204200041146a200f3e0200200041106a20073602002000410c6a2009360200200041086a41113602000c010b0240200d450d00200041cb9cc400360204200041146a200f3e0200200041106a20073602002000410c6a2009360200200041086a41103602000c010b200041bb9cc400360204200041146a200f3e0200200041106a20073602002000410c6a2009360200200041086a41103602000b410121090b2000200936020020082008280200417f6a220736020020070d012008280208101020082008280204417f6a220736020420070d010b2008102a0b024020062802102207450d00200628020821082007410574210703400240200841046a280200450d002008280200102a0b0240200841106a280200450d002008410c6a280200102a0b200841206a2108200741606a22070d000b0b0240200628020c450d002006280208102a0b0240200628021c2207450d0020062802142108200741027421070340200828020022092009280200417f6a3602000240200828020022092802000d0020092802081010200828020022092009280204417f6a360204200828020022092802040d002009102a0b200841046a21082007417c6a22070d000b0b02402006280218450d002006280214102a0b200641e0006a24000b8a1409057f017e0c7f047e037f017e037f047e097f230041f00c6b22022400024020002802000d002000417f360200200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b2002411c6a20042f0106360200200241186a4100360200200241146a20043602002002200336022020024100360210200242003703082002200136020420024100360200200241f0016a2002109301024020022903900222074202510d002000410c6a2108200041046a2109200241900a6a41146a210a200241900a6a41206a210b200241f0016a4104722103200241f0016a413d6a210c200241cd026a210d200241b8026a210e200241f0016a41306a210f200241f0016a41286a21100340200241c8006a41086a2204200241f0016a41086a2211290300370300200241c8006a41106a2201200241f0016a41106a2212290300370300200241c8006a41186a2205200241f0016a41186a2213290300370300200220022903f001370348200e2903002114200f290300211520022903b0022116200229039802211720022f01ee02211820022d00ed02211920022d00cc02211a20022903a802211b20022802c002211c20022802c402211d20022802c802211e200241286a41186a200d41186a290000221f370300200241286a41106a200d41106a2900002220370300200241286a41086a200d41086a29000022213703002002200d2900002222370328200241e8006a41186a2223201f370300200241e8006a41106a22242020370300200241e8006a41086a222520213703002002202237036820024188016a41186a2226200529030037030020024188016a41106a2227200129030037030020024188016a41086a222820042903003703002002200229034837038801024002400240024002402009280200222941f8b9c000460d002000280208212a0c010b200241900a6a410041e0021099051a200241f0016a410041a0081099051a41880b10282229450d014100212a202941003b010620294100360200202941086a200241900a6a41e002109a051a202941e8026a200241f0016a41a008109a051a20004100360208200020293602040b0340202941086a210120292f0106222b410574210441002105024003402004450d0120024188016a20014120109c052206450d04200441606a2104200541016a2105200141206a21012006417f4a0d000b2005417f6a212b0b0240202a450d00202a417f6a212a2029202b4102746a41880b6a28020021290c010b0b200241c0016a41186a2026290300221f370300200241c0016a41106a20272903002220370300200241c0016a41086a20282903002221370300200220022903880122223703c001200a2022370200200a41086a2021370200200a41106a2020370200200a41186a201f370200200220083602a00a2002202b36029c0a200220093602980a200220293602940a200241003602900a20102014370300201220153703002002201637039002200220173703f8012002201a3a00ac022002201e3602a8022002201d3602a4022002201c3602a0022002201b37038802200220073703f001200c2002290368370000200c41086a2025290300370000200c41106a2024290300370000200c41186a2023290300370000200220183b01ce02200220193a00cd02200241900a6a200241f0016a10b7011a0c020b41880b41081037000b202941e8026a200541e0006c6a2129024020194101710d0020292029290300200720075022041b37030020292029290308201720041b370308202941106a22012001290300201520041b370300200241900a6a41186a22062023290300370300200241900a6a41106a222a2024290300370300200241900a6a41086a222b2025290300370300200220022903683703900a20292d003c21012013202941d5006a22052900003703002012202941cd006a22192900003703002011202941c5006a222329000037030020022029413d6a22242900003703f0012028200241900a6a200241f0016a201a41ff0171410146221a1b220441086a2900003703002027200441106a2900003703002026200441186a2900003703002002200429000037038801202941012001201a1b3a003c2024200229038801370000202320282903003700002019202729030037000020052026290300370000202920162029290320201ba722041b370320202941286a22012014200129030020041b3703002029201b202929031820041b37031802400240201d0d00201c21040c010b201d2101201c2104034020042802ec0321042001417f6a22010d000b0340201c201c2f01064102746a41ec036a280200211c201d417f6a221d0d000b0b201c2f010621012002201e3602a801200220013602a401200241003602a0012002201c36029c01200241003602980120024200370390012002200436028c012002410036028801200241f0016a20024188016a109901024020022802f0014101470d00202941306a211c0340200241900a6a41286a200341286a280200360200200b200341206a2902003703002006200341186a2204290200370300202a200341106a2201290200370300202b200341086a2205290200370300200220032902003703900a200241c0016a41186a2004290000370300200241c0016a41106a2001290000370300200241c0016a41086a2005290000370300200220032900003703c001200241e0016a41086a200b41086a2802003602002002200b2902003703e001200241b0016a201c200241c0016a200241e0016a10bd01024020022802b001450d0020022802b4012204450d0020022802b801450d002004102a0b200241f0016a20024188016a10990120022802f0014101460d000b0b20024188016a1095010c010b202941386a212b202941306a212a202928023821262029280230210402400240202941346a28020022050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b200220263602900220024100360288022002410036028002200242003703f801200220013602f401200241003602f0012002200436028402200220042f010636028c02200241f0016a109501202941286a201437030020292016370320202941106a2015370300202920173703082029201b37031820292007370300202a201d360204202a201c360200202b201e3602002029201a3a003c2029413d6a2002290368370000202941c5006a2025290300370000202941cd006a2024290300370000202941d5006a2023290300370000202920183b015e202920193a005d0b200241f0016a200210930120022903900222074202520d000b0b2002109b012000200028020041016a360200200241f00c6a24000f0b41a8b8c0004110200241f0016a41d0b8c0001038000bf00203027f017e037f230041306b22052400024002400240200241ff0171417e6a220641024b0d000240024020060e03000201000b200520011099022005290300200358200541086a290300220720045820072004511b0d010c020b200541106a20011099022005290310200356200541186a290300220720045620072004511b0d010b200541206a2001109a020240200528022822010d0002402005280224450d002005280220102a0b410021010c020b200141057421061098012108200528022421092005280220220a2101024002400240034002402008200141106a2802004f0d002001290300200358200141086a290300220720045820072004511b0d002001411c6a2d000020027141ff0171200241ff0171460d020b200141206a2101200641606a22060d000b4100210120090d010c020b4184dfc00021012009450d010b200a102a0b413121060c010b41dedec0002101412621060b2000200636020420002001360200200541306a24000bc31e03087f037e127f23004180076b22042400200441e0006a41186a200241186a290000370300200441e0006a41106a200241106a290000370300200441e0006a41086a200241086a290000370300200420022900003703600240024002400240024002400240024002402001280200220541f8b9c000460d00200128020421060c010b41002106200441e8026a410041e0021099051a200441c0016a41004184011099051a41ec0310282205450d01200541003b010620054100360200200541086a200441e8026a41e002109a051a200541e8026a200441c0016a418401109a051a20014100360204200120053602000b02400340200541086a2107200541066a210820052f0106220941057421024100210a0240024003402002450d01200441e0006a20074120109c05220b450d02200241606a2102200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200520094102746a41ec036a28020021050c010b0b200441e8026a41086a22022005200a410c6c6a220741f0026a220a2802003602002004200741e8026a22072902003703e80220072003290200370200200a200341086a280200360200200441c0016a41086a20022802002202360200200420042903e802220c3703c0012000410c6a20023602002000200c370204200041013602000c060b200441086a41186a220b200441e0006a41186a2202290300370300200441086a41106a200441e0006a41106a2207290300220c370300200441086a41086a200441e0006a41086a220a290300220d37030020042004290360220e3703082001200128020841016a3602082007200c370300200a200d3703002002200b2903003703002004200e370360200441d8026a41086a2206200341086a280200360200200420032902003703d802024020082f01002203410b490d00200441e8026a410041e0021099051a200441c0016a41004184011099051a41ec031028220f450d02200f41003b0106200f4100360200200f41086a200441e8026a41e002109a052107200f41e8026a200441c0016a418401109a05210a200441e8026a41086a220b200541b8036a280200360200200420052900db013703a8012004200541e0016a2900003700ad01200420052902b0033703e802200420052f00c8013b01bc012004200541ca016a2d00003a00be01200541cb016a2800002110200541cf016a2800002111200541d3016a2800002112200541d7016a28000021132007200541e8016a20052f010641796a2202410574109a052107200a200541bc036a2002410c6c109a05210a200541063b0106200f20023b0106200420042f01bc013b01a401200420042d00be013a00a601200420042903a8013703c001200420042900ad013700c501200441286a41086a200b280200360200200420042903e8023703280240024020094107490d00200941057420076a41c07e6a2007200941796a220b4105746a2207200241ffff0371200b6b410574109b051a200741186a200441e0006a41186a290300370000200741106a200441e0006a41106a290300370000200741086a200441e0006a41086a290300370000200720042903603700002009410c6c200a6a220241b87f6a200241ac7f6a2202200f41066a22082f0100200b6b410c6c109b051a200241086a200441d8026a41086a280200360200200220042903d8023702000c010b200541086a20094105746a220241206a200220082f010020096b410574109b051a200241186a200441e0006a41186a290300370000200241106a200441e0006a41106a290300370000200241086a200441e0006a41086a29030037000020022004290360370000200541e8026a2009410c6c6a2202410c6a200220082f010020096b410c6c109b051a200241086a200441d8026a41086a280200360200200220042903d8023702000b200820082f010041016a3b010020044198016a41026a220220042d00a6013a0000200441c8026a41086a2214200441286a41086a280200360200200420042f01a4013b019801200420042903c001370350200420042900c501370055200420042903283703c8022004413c6a41026a221520022d00003a0000200420042f0198013b013c2004200429005537002d20042004290350370328200441c0006a41086a22162014280200360200200420042903c80237034020052802002206450d0420052f01042103200441e8026a4102722117034020044194016a41026a221820152d00003a0000200420042f013c3b019401200420042903283703602004200429002d37006520044198016a41086a221920162802003602002004200429034037039801200341ffff0371210502400240024020062f01062202410b490d00201741004196041099051a419c041028220b450d07200b4100360200200b41046a200441e8026a419804109a051a200420062f00c8013b01bc012004200641ca016a2d00003a00be012004200641db016a2900003703a8012004200641e0016a2900003700ad01200641cb016a280000211a200641cf016a280000211b200641d3016a280000211c200641d7016a280000211d200441e8026a41086a221e200641b8036a2802003602002004200641b0036a2902003703e802200b41086a200641e8016a20062f0106220741796a2202410574109a05211f200b41e8026a200641bc036a2002410c6c109a052120200b41ec036a20064188046a2007417a6a2209410274109a052108200641063b0106200b20023b010602402009450d00410021022008210703402007280200220a20023b0104200a200b360200200741046a21072009200241016a2202470d000b0b200441d8026a41086a2202201e280200360200200420042d00be0122073a00a601200420042f01bc01220a3b01a401200420042903a8013703c001200420042900ad013700c501200420042903e8023703d802200441c4026a41026a220920073a00002004200a3b01c402200420042903c0013703e802200420042900c5013700ed0220142002280200360200200420042903d8023703c802200341ffff037122074107490d01201f2005417a6a220a4105746a201f200541796a22024105746a2207200b2f010620026b410574109b051a200741186a20042900653700002007201336000f2007201236000b2007201136000720072010360003200741026a20182d00003a0000200720042f0194013b0000200720042903603700132005410c6c20206a220741b87f6a200741ac7f6a2207200b2f0106220320026b410c6c109b051a200741086a20192802003602002007200429039801370200200b200341016a22073b01062005410274221020086a416c6a2008200a4102746a2203200741ffff03712205200a6b410274109b051a2003200f3602002005200a490d02200b20106a41d4036a210703402007280200220a200241016a22023b0104200a200b360200200741046a210720022005490d000c030b0b200641086a2207200541016a220a4105746a200720054105746a2207200220056b410574109b051a200741186a20042900653700002007201336000f2007201236000b2007201136000720072010360003200741026a20044194016a41026a2d00003a0000200720042f0194013b00002007200429036037001320062005410c6c6a220241f4026a200241e8026a220720062f0106220b20056b410c6c109b051a200241f0026a20044198016a41086a28020036020020072004290398013702002006200b41016a22023b01062005410274200641ec036a22076a41086a2007200a4102746a2207200241ffff0371220b200a6b410274109b051a2007200f360200200341ffff0371200b4f0d082006200a417f6a22024102746a41f0036a210703402007280200220a200241016a22023b0104200a2006360200200741046a21072002200b490d000c090b0b200641086a2202200541016a22034105746a200220054105746a220220062f010620056b410574109b051a200241186a20042900653700002002201336000f2002201236000b2002201136000720022010360003200241026a20182d00003a0000200220042f0194013b000020022004290360370013200641e8026a2005410c6c6a2202410c6a200220062f0106220a20056b410c6c109b051a200241086a201928020036020020022004290398013702002006200a41016a22023b010620054102742210200641ec036a220a6a41086a200a20034102746a2208200241ffff0371220a20036b410274109b051a2008200f3602002007200a4f0d00200620106a41f0036a2102034020022802002207200541016a22053b010420072006360200200241046a2102200a2005470d000b0b20044190016a41026a220220092d00003a000020044180016a41086a22072014280200360200200420042f01c402220a3b019001200420042903e802370350200420042900ed02370055200420042903c80237038001201520022d00003a00002004200a3b013c2004200429005537002d200420042903503703282016200728020036020020042004290380013703400240200628020022020d00201a2110201d2113201c2112201b2111200b210f0c060b20062f01042103201a2110201d2113201c2112201b211120022106200b210f0c000b0b200520094105746a220b41286a200b41086a2201200320096b410574109b051a200b41206a2002290300370000200b41186a2007290300370000200b41106a200a2903003700002001200429036037000020052009410c6c6a220241f4026a200241e8026a220720052f010620096b410c6c109b051a200241f0026a2006280200360200200720042903d802370200200520052f010641016a3b01060c040b41ec0341041037000b41ec0341041037000b419c0441041037000b200441e8026a41027241004196041099051a419c0410282202450d0220024100360200200241046a200441e8026a419804109a051a2002200128020022073602ec03200120023602002001200128020441016a360204200741003b010420072002360200200220022f0106220a4105746a220741086a20042f013c3b00002007410a6a2004413c6a41026a2d00003a0000200741176a2013360000200741136a20123600002007410f6a20113600002007410b6a20103600002007411b6a2004290328370000200741206a200429002d3700002002200a410c6c6a220741f0026a200441c0006a41086a280200360200200741e8026a2004290340370200200241ec036a200a41016a22074102746a200f360200200220073b0106200f20073b0104200f20023602000b200041003602000b20044180076a24000f0b419c0441041037000bc50101057f230041306b220124002000410c6a28020021022000280204210302400240200041086a28020022040d00200321000c010b2004210520032100034020002802880b21002005417f6a22050d000b0340200320032f01064102746a41880b6a28020021032004417f6a22040d000b0b200141246a20032f0106360200200141206a41003602002001411c6a20033602002001200236022820014100360218200142003703102001200036020c20014100360208200141086a109b01200141306a24000bcb0401097f230041c0006b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a280200210602400240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d01200220084120109c05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a220841e8026a210502400240200841c5036a2d00000d00200341206a41086a220a200541c5006a290000370300200341206a41106a220b200541cd006a290000370300200341206a41186a2207200541d5006a29000037030020032005413d6a2900003703204102210820052d003c4101470d01200341186a2007290300370300200341106a200b290300370300200341086a200a29030037030020032003290320370300410121080c010b200341086a200541c5006a290000370300200341106a200541cd006a290000370300200341186a200541d5006a29000037030020032005413d6a29000037030020052d003c21080b200841ff01714102470d010b200020012802102002200141146a280200280210110500200128020021040c010b200020083a000020002003290300370001200041096a200341086a290300370000200041116a200341106a290300370000200041196a200341186a2903003700000b20012004417f6a360200200341c0006a24000f0b41b8b8c0004118200341206a41e0b8c0001038000be80202097f027e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d01200220084120109c05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a220541c5036a310000200541e8026a290300220c200c5022081ba7450d004200200541f8026a29030020081b210c4200200541f0026a29030020081b210d0c010b200341086a20012802102002200141146a28020028021c110500200341106a290300210c200128020021042003290308210d0b20012004417f6a3602002000200c3703082000200d370300200341206a24000f0b41b8b8c0004118200341186a41e0b8c0001038000ba62a020c7f037e230022072108200741800f6b41607122072400200720043703382007200337033020072005360244024002400240024002402001280230200128024022092802b801460d002005420020052903082203200941386a2903007d2204200420035622091b37030820090d0120074180046a20024100410110c201200741a4046a280200210a200741a0046a280200210b20072d008804220541037122094103460d0220090e03030203030b200041d4c5c00036020420004101360200200041086a41293602002000410c6a2006290200370200200041146a200641086a2802003602000c030b200041fdc5c00036020420004101360200200041086a41233602002000410c6a2006290200370200200041146a200641086a280200360200200824000f0b200041a0c6c00036020420004101360200200041086a41193602002000410c6a2006290200370200200041146a200641086a28020036020020050d01200a450d01200b102a200824000f0b200741a8046a2802002109200741c8006a41186a220c200141e8006a290000370300200741c8006a41106a220d200141e0006a290000370300200741c8006a41086a220e200141d8006a290000370300200720012900503703484100210f4100211002400240024002400240024002400240024002400240024002400240024020050d002009417f4c0d010240024020090d002007420037038004410121100c010b200910282210450d03200741003602840420072009360280040b20072009360284042010200b2009109a051a2007290380042103200a450d00200b102a0b200741a4016a410036020020074194016a419cc4c000360200200741e8006a41206a420037030020074184016a41f8b9c000360200200741e8006a41106a2003370300200741e8006a41d8006a200241086a290000370300200741e8006a41e0006a200241106a290000370300200741e8006a41e8006a200241186a29000037030020072001360270200741e8006a41286a200141186a22113602002007420837029c01200741003602800120072010360274200720022900003703b801200720012802483602b001200720012903403703a8012007200128023041016a36029801200129030021032007200128024c3602b40120072003370368200741d8016a41206a200e290300370300200741d8016a41286a200d29030037030020074188026a200c290300370300200741ec016a200641086a280200360200200720023602e001200720072903483703f001200720062902003702e4012007200741c4006a3602dc012007200741306a3602d8010240024020072903302203200741306a41086a290300220484500d00200741286a20072802444100200741f0016a200220032004200741e8006a10b801200728022822060d01200728028001210f20072802e00121020b200f41016a220d41004c0d03200741d8016a41186a210e200741e4016a210f2007200d36028001200741e8006a41206a280200210a20074184016a2212210602400240024003402006280200220b41086a2105200b2f0106220c4105742106410021090240024003402006450d01200220054120109c052210450d02200641606a2106200941016a2109200541206a21052010417f4a0d000b2009417f6a210c0b200a450d02200a417f6a210a200b200c4102746a41880b6a21060c010b0b200b200941e0006c6a220541e8026a210602400240200541c5036a2d00000d0020074180046a41086a2209200641c5006a29000037030020074180046a41106a2210200641cd006a29000037030020074180046a41186a220b200641d5006a29000037030020072006413d6a290000370380044102210520062d003c4101470d01200741a00c6a41186a200b290300370300200741a00c6a41106a2010290300370300200741a00c6a41086a200929030037030020072007290380043703a00c410121050c010b200741a80c6a200641c5006a290000370300200741b00c6a200641cd006a290000370300200741b80c6a200641d5006a29000037030020072006413d6a2900003703a00c20062d003c21050b200541ff01714102470d010b20074190026a2007280290012002200728029401280210110500200728028001210d20072d00900221050c010b20074199026a200741a80c6a290300370000200741a1026a200741b00c6a290300370000200741a9026a200741b80c6a290300370000200720053a009002200720072903a00c370091020b2007200d417f6a360280014101210a0240200541ff01714101470d00200741b8026a41186a200741a9026a290000370300200741b8026a41106a200741a1026a290000370300200741b8026a41086a20074199026a29000037030020072007290091023703b80220074180046a200741b8026a20072802b00128020010b90102402007280280044101470d0020072902e4012203422088a7210520074180046a41086a28020021092007280284042106200741ec016a28020021102003a721020c100b200741a00c6a41186a220520074180046a410472220641186a2802002209360200200741d8026a41106a200641086a290200370300200741d8026a41186a200641106a290200370300200741f8026a2009360200200741043602dc02200741af8dc6003602d802200720062902003703e00220072802ac0121062005200e41186a2900002203370300200741a00c6a41106a200e41106a2900002204370300200741a00c6a41086a2205200e41086a2900002213370300200741a8046a2013370300200741b0046a2004370300200741b8046a20033703002007200e29000022033703a00c200720033703a00420072802d801220941086a29030021032007200741e8006a36029804200929030021042007290368211320072802b4012109200720033703880420072004370380042007200936029c0420072013370390042005200f41086a2802003602002007200f2902003703a00c200741e0036a2006200741d8026a20074180046a200741a00c6a20072802dc0128020010ba01200741ec036a2902002103200741e0036a41086a280200210c20072802e403210a024020072802e0034101470d002003422088a72105200741f4036a28020021102003a72102200c2109200a21060c0f0b20072802800141016a220f41004c0d0520072802e00121022007200f36028001200728028801210d201221060240024003402006280200220b41086a2105200b2f0106220e4105742106410021090240024003402006450d01200220054120109c052210450d02200641606a2106200941016a2109200541206a21052010417f4a0d000b2009417f6a210e0b200d450d02200d417f6a210d200b200e4102746a41880b6a21060c010b0b200b200941e0006c6a220641c5036a310000200641e8026a290300220420045022051ba7450d004200200641f8026a29030020051b21044200200641f0026a29030020051b21130c010b200741186a200728029001200220072802940128021c110500200741206a290300210420072903182113200728028001210f0b2007200f417f6a221036028001201320072802a801220629037854200420064180016a29030022135420042013511b0d060c070b4100210c420021030240200741e8016a280200450d0020072802e401102a0b420021040c070b200728022c210920072902e4012203422088a721052003a72102200741ec016a28020021100c0d0b1036000b200941011037000b41b8b8c000411820074180046a41e0b8c0001038000b41b8b8c000411820074180046a41e0b8c0001038000b20072802702206450d020240024020072802e0012205200641d0006a2209460d00200920054120109c05450d00034020062802082206450d022005200641d0006a2209460d01200920054120109c050d000b0b2003a7211041b9c6c000210641372109200c2105200a21020c080b20100d032007417f36028001200741003a00bc03200742003702b403200741013a009d03200741f8b9c0003602b003200741e0036a41186a200541186a290000370300200741e0036a41106a200541106a290000370300200741e0036a41086a200541086a290000370300200720052900003703e00302400240200728028401221041f8b9c000460d00200728028801210b0c010b200741a00c6a410041e0021099051a20074180046a410041a0081099051a41880b10282210450d054100210b201041003b010620104100360200201041086a200741a00c6a41e002109a051a201041e8026a20074180046a41a008109a051a200741003602880120072010360284010b02400240034020102f0106220d4105742102410021064100210502400240034020022006460d01200741e0036a201020066a41086a4120109c052209450d02200641206a2106200541016a21052009417f4a0d000b2005417f6a210d0b200b450d02200b417f6a210b2010200d4102746a41880b6a28020021100c010b0b2010200541e0006c6a22064190036a20072903a80337030020064188036a20072903a003370300200641c0036a200729039803370000200641b8036a200729039003370000200641b0036a200729038803370000200641a8036a20072903800337000020064180036a4200370300200641e8026a2205290300211320054200370300200641a0036a22052802002102200520072903b80337030020064198036a22062903002104200620072903b0033703002004a721062004422088a721050c010b200741c0036a41186a200741e0036a41186a2903002204370300200741c0036a41106a200741e0036a41106a2903002213370300200741c0036a41086a200741e0036a41086a2903002214370300200720072903e00322153703c003200741bc0c6a2014370200200741a00c6a41246a2013370200200741cc0c6a20043702002007200741e8006a41246a3602b00c2007200d3602ac0c200720123602a80c200720103602a40c200741003602a00c200720153702b40c20074180046a41186a42003703002007420037038004200741b8046a20072903b803370300200741b0046a20072903b003370300200741a8046a20072903a803370300200741a0046a20072903a003370300200741d8046a200729039803370300200741d0046a200729039003370300200741c8046a200729038803370300200741c0046a200729038003370300200741a00c6a20074180046a10b7011a420221130b024020134202510d000240024020050d00200621090c010b2005211020062109034020092802ec0321092010417f6a22100d000b0340200620062f01064102746a41ec036a28020021062005417f6a22050d000b0b2007419c046a20062f010636020020074198046a410036020020074194046a2006360200200720023602a004200741003602900420074200370388042007200936028404200741003602800420074180046a1095010b200720072802800141016a360280010b0240200741f0026a280200450d00200741ec026a280200102a0b200342ffffffff0f83210420034280808080708321030b20072802a401210520072802a001210d200728029c01210b200728028c01210e20072802880121102007280284012106024020072802742209450d00200741f8006a280200450d002009102a0b200420038421040240024020034280808080f01f8350450d002007200e3602880420072010360284042007200636028004201120074180046a10bb012007200d360284042007200b360280042007200b200541b0016c22056a220236028c0402400240200141386a28020022092001413c6a28020022066b200541b0016d2210490d00200128023421090c010b200620106a220d2006490d0720094101742206200d2006200d4b1b2206ad42b0017e2203422088a70d072003a7220d4100480d070240024020090d00200d102821090c010b2001280234200941b0016c200d102c21090b2009450d0620012009360234200141386a20063602002001413c6a28020021060b2009200641b0016c6a200b2005109a051a2001413c6a2206200628020020106a360200200720023602880420074180046a10692000410c6a2004370200200041086a200c3602002000200a3602040c010b2000200a3602042000410c6a2004370200200041086a200c36020002402005450d00200541b0016c210141002105034002400240200b20056a22092d0000220241014b0d000240024020020e020001000b0240200941086a280200450d00200941046a280200102a0b200941106a2d00004105490d02200941386a280200450d02200941346a280200102a0c020b200941286a106a0c010b200941e8006a280200450d00200941e4006a280200102a0b2001200541b0016a2205470d000b0b0240200d450d00200b102a0b0240024020100d00200621050c010b2010210920062105034020052802880b21052009417f6a22090d000b0340200620062f01064102746a41880b6a28020021062010417f6a22100d000b0b2007419c046a20062f010636020020074198046a410036020020074194046a20063602002007200e3602a004200741003602900420074200370388042007200536028404200741003602800420074180046a109b010b20004100360200200824000f0b41f0c6c00041321050000b41a8b8c000411020074180046a41d0b8c0001038000b41880b41081037000b200d41081037000b1031000b200741f0026a280200450d00200741ec026a280200102a0b2000200636020420004101360200200041146a2010360200200041086a20093602002000410c6a2005ad4220862002ad84370200024020072802742206450d00200741f8006a280200450d002006102a0b200741e8006a411c6a2802002106200728028c0121000240024020072802880122050d00200621090c010b2005211020062109034020092802880b21092010417f6a22100d000b0340200620062f01064102746a41880b6a28020021062005417f6a22050d000b0b20074180046a411c6a20062f01063602004100210520074198046a410036020020074194046a2006360200200720003602a004200741003602900420074200370388042007200936028404200741003602800420074180046a109b01024020072802a4012206450d00200728029c012110200641b0016c2100034002400240201020056a22062d0000220941014b0d000240024020090e020001000b0240200641086a280200450d00200641046a280200102a0b200641106a2d00004105490d02200641386a280200450d02200641346a280200102a0c020b200641286a106a0c010b200641e8006a280200450d00200641e4006a280200102a0b2000200541b0016a2205470d000b0b20072802a001450d00200728029c01102a200824000f0b200824000b871304057f027e0a7f077e230041f0026b22042400200441d0006a2001108c010240024020042d00502205417f6a41ff017141024f0d00200041003a0000200041086a200441d0006a41d800109a051a0c010b200441a8016a41086a2206200441d0006a413c6a290200370300200441a8016a41106a2207200441d0006a41c4006a290200370300200441a8016a41186a2208200441d0006a41cc006a2902003703002004200441d0006a41346a2902003703a801200441d0006a41106a2903002109200441d0006a41086a290300210a200441d0006a41306a280200210b200441d0006a412c6a280200210c200441d0006a41246a280200210d200441d0006a41206a280200210e200441ec006a280200210f200441d0006a41186a2802002110200441d0006a41d4006a2802002111200441d0006a41286a28020021120240024002400240024002400240024002400240024041004100109801221320026b2202200220134b1b220220126b2214201420024b1b2214450d00200441c0006a2001109101200441306a20042903402215200441c0006a41086a2903002216428080a8ec85afd1b101420010a0054200200dad2217200429033022187d221920192017564200200441306a41086a2903002017201854ad7c7d22174200522017501b22021b22184200201720021b221784500d042015428080d287e2bc2d5441002016501b0d01200441186a2014ad420020182017109f05200441086a2004290318200441186a41086a290300428080e983b1de164200109f05200441286a20014108420020152015428080aef89dc3527c2217200a200a201756200920162017201554ad7c427f7c22175620092017511b22021b22182004290308221920182019542017200920021b2218200441086a41086a29030022175420182017511b22021b221a7d221b201b20155620162018201720021b22187d2015201a54ad7d221520165620152016511b22141b4200201520141b10bc010240024020042802280d000240024020020d002003450d010b20044188026a2001201a201841081098022004280288024101460d08200420044198026a2903003703f001200420044188026a41086a2903003703e8012004200441e8016a3602880220044188026a109d010b20020d0020030d01200041003a0008200041023a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903a801370000200041c4006a200441b0016a290300370000200041cc006a200441a8016a41106a290300370000200041d4006a200441a8016a41186a290300370000200041dc006a2011360000200541037122004103460d0520000e030d05050d0b20044100360288022010200e20044188026a100d21142004280288022213417f460d07200441e8016a41186a200441a8016a41186a290300370300200441e8016a41106a200441a8016a41106a290300370300200441e8016a41086a200441a8016a41086a290300370300200420042903a8013703e801200441003602e802200442013703e00220142013200441e0026a10b2020240024020042802e402220320042802e802220d6b4120490d00200d41206a211220042802e00221020c010b200d41206a2212200d490d0a200341017422022012200220124b1b220b4100480d0a0240024020030d00200b102821020c010b20042802e0022003200b102c21020b2002450d092004200b3602e402200420023602e002200b21030b200420123602e8022002200d6a220d20042903e801370000200d41086a200441e8016a41086a290300370000200d41106a200441e8016a41106a290300370000200d41186a200441e8016a41186a29030037000020044188026a41186a220d420037030020044188026a41106a220b420037030020044188026a41086a220c420037030020044200370388022002201220044188026a1000200441c8016a41186a2212200d290300370300200441c8016a41106a220d200b290300370300200441c8016a41086a220b200c29030037030020042004290388023703c80102402003450d002002102a0b200441a1026a201229030037000020044199026a200d29030037000020044191026a200b290300370000200420042903c80137008902200441013a008802200120044188026a10b3022010200e1004200041013a0000200041086a20044188026a41d800109a051a2013450d032014102a0c030b200441b8026a200b360200200441b4026a200c360200200441b0026a2013360200200441ac026a200d360200200441a8026a200e360200200441a4026a200f36020020044188026a41186a2010360200200441bc026a20042903a801370200200441c4026a200441a8016a41086a290300370200200441cc026a200441a8016a41106a290300370200200441d4026a200441a8016a41186a29030037020020044188026a41106a200920177d200a201954ad7d370300200441003a0088022004200a20197d37039002200120044188026a10b302200041023a0000200041086a20044188026a41d800109a051a0c090b200041003a0008200041003a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903a801370000200041c4006a2006290300370000200041cc006a2007290300370000200041d4006a2008290300370000200041dc006a20113600000c080b20011096012010200e1004200041023a0008200041013a00000b200f450d062010102a0c060b200f450d070c060b200041003a0008200041003a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903a801370000200041c4006a200441b0016a290300370000200041cc006a200441a8016a41106a290300370000200041d4006a200441a8016a41186a290300370000200041dc006a20113600000c040b2004200429028c023703e80141f896c10041fe00200441e8016a41f897c1001038000b41eef3c50041381050000b200b41011037000b1031000b0240200541037122004103460d0020000e03020000020b200f450d010b2010102a0b200441f0026a24000be20d03047f017e027f230041106b2202240020024100360208200242013703000240024002400240024002400240024002400240024002400240024002402001280200220341044b0d000240024002400240024020030e050001020304000b410110282203450d05200242818080801037020420022003360200200341013a0000200128020421042001410c6a2802002203200210b40102402003450d002004200341286c6a2105034020042002108f01200441206a29030021060240024020022802042207200228020822036b4108490d00200228020021070c010b200341086a22082003490d15200741017422032008200320084b1b22034100480d150240024020070d002003102821070c010b200228020020072003102c21070b2007450d092002200336020420022007360200200228020821030b2002200341086a360208200720036a20063700002005200441286a2204470d000b0b200141106a28020021070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d13200441017422032008200320084b1b22034100480d130240024020040d002003102821040c010b200228020020042003102c21040b2004450d082002200336020420022004360200200228020821030b2002200341046a360208200420036a20073600000c040b410110282203450d07200242818080801037020420022003360200200341023a0000200128020421070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d12200441017422052008200520084b1b22084100480d120240024020040d002008102821040c010b200228020020042008102c21040b2004450d0920022008360204200220043602000b2002200341046a360208200420036a200736000020012802082104200141106a2802002203200210b40102402003450d002004200341286c6a2105034020042002108f01200441206a29030021060240024020022802042207200228020822036b4108490d00200228020021070c010b200341086a22082003490d14200741017422032008200320084b1b22034100480d140240024020070d002003102821070c010b200228020020072003102c21070b2007450d0c2002200336020420022007360200200228020821030b2002200341086a360208200720036a20063700002005200441286a2204470d000b0b200141146a28020021070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d12200441017422032008200320084b1b22034100480d120240024020040d002003102821040c010b200228020020042003102c21040b2004450d0b2002200336020420022004360200200228020821030b2002200341046a360208200420036a20073600000c030b410110282203450d0a200242818080801037020420022003360200200341033a0000200141086a29030021060240024020022802042207200228020822036b4108490d00200341086a2104200228020021070c010b200341086a22042003490d11200741017422082004200820044b1b22084100480d110240024020070d002008102821070c010b200228020020072008102c21070b2007450d0c20022008360204200220073602000b20022004360208200720036a20063700000c020b410110282203450d0b200242818080801037020420022003360200200341043a0000200128020421070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d10200441017422012008200120084b1b22084100480d100240024020040d002008102821040c010b200228020020042008102c21040b2004450d0d20022008360204200220043602000b2002200341046a360208200420036a20073600000c010b410110282203450d0c200242818080801037020420022003360200200341053a0000200128020421080240024020022802042207200228020822036b4104490d00200341046a2104200228020021070c010b200341046a22042003490d0f200741017422012004200120044b1b22014100480d0f0240024020070d002001102821070c010b200228020020072001102c21070b2007450d0e20022001360204200220073602000b20022004360208200720036a20083600000b20002002290300370200200041086a200241086a280200360200200241106a24000f0b410141011037000b200341011037000b200341011037000b410141011037000b200841011037000b200341011037000b200341011037000b410141011037000b200841011037000b410141011037000b200841011037000b410141011037000b200141011037000b1031000bfb0101077f230041106b220124002001410036020820014201370300200110c40120012802042102200128020021030240024002400240200041046a2802002204200041086a28020022056b20012802082206490d00200028020021040c010b200520066a22072005490d02200441017422052007200520074b1b22054100480d020240024020040d002005102821040c010b200028020020042005102c21040b2004450d0120002004360200200041046a2005360200200041086a28020021050b200041086a200520066a360200200420056a20032006109a051a02402002450d002003102a0b200141106a24000f0b200541011037000b1031000ba5900108027f017e0b7f037e2f7f027e057f0e7e23004190106b220224000240024002400240024002400240024002400240024002400240200141106a2802002203ad42d0007e2204422088a70d002004a72205417f4c0d00200128020821060240024002400240024002400240024020050d00410821070c010b200510282207450d010b0240024020030d00410021080c010b2006200341d0006c6a2109410021082007210a0340200241c8046a41186a220b200641186a290300370300200241c8046a41106a220c200641106a290300370300200241c8046a41086a220d200641086a290300370300200220062903003703c8042006280248220ead42307e2204422088a70d082004a7220f417f4c0d08200641386a2903002104200641286a290300211020062903302111200629032021122006280240210502400240200f0d00410821130c010b200f10282213450d040b200641d0006a210602400240200e0d00410021140c010b2005200e41306c6a2115410021142013210f0340200f2005290300370300200f200541086a290300370308200f41106a200541106a290300370300200f41186a200541186a290300370300200f41206a200541206a290300370300200f41286a200541286a290300370300200f41306a210f201441016a2114200541306a22052015470d000b0b200a2012370320200a20022903c804370300200a41386a2004370300200a41306a2011370300200a41286a2010370300200a41c8006a2014360200200a41c4006a200e360200200a41c0006a2013360200200a41186a200b290300370300200a41106a200c290300370300200a41086a200d290300370300200841016a2108200a41d0006a210a20062009470d000b0b200028020821162000280204211720002802002118200128020421192001280200210b41041028221a450d02201a200b36000020024284808080c0003702bc072002201a3602b807411b10282205450d03200541176a41002800f39646360000200541106a41002900ec9646370000200541086a41002900e49646370000200541002900dc96463700002002429b808080b00337028c08200220053602880841a2c7c00020024188086a10c601200228029008210f2002280288082105200241c8046a41186a22144200370300200241c8046a41106a22154200370300200241c8046a41086a22064200370300200242003703c8042005200f200241c8046a1000200241b00f6a41186a2014290300370300200241b00f6a41106a2015290300370300200241b00f6a41086a2006290300370300200220022903c8043703b00f0240200228028c08450d002005102a0b2002410036028808200241b00f6a412020024188086a100621142002280288082215417f460d042014450d042002201536028c082002201436028808200241d0026a20024188086a106c02400240024020022802d0020d00200228028c08220620022802d402220f490d00200f417f4c0d0902400240200f0d00410121050c010b200f102e2205450d022005200228028808220a200f109a051a20022006200f6b36028c082002200a200f6a360288080b20050d020b41c4d1c3004133200241f8056a419cd9c3001038000b200f41011037000b200fad220442208620048421042015450d052014102a0c050b200541081037000b200f41081037000b410441011037000b411b41011037000b410021050b20022005410120051b22133602b00f20022004420020051b22104220883e02b40f200241c8026a200241b00f6a106c20022802cc02210e41002106024020022802c8020d0020022802b40f220541246e220a41246c220f417f4c0d0102400240024002400240200f0d00410421060c010b200f10282206450d010b200e450d034100210c034020054104490d03200c41016a210d20022005417c6a22143602b40f200220022802b00f221541046a3602b00f2015280000210941002105200241003a00a8080340024020142005470d00200241003602b40f200541ff0171450d05200241003a00a8080c050b20024188086a20056a201520056a220f41046a2d00003a00002002200f41056a3602b00f2002200541016a220f3a00a808200f2105200f4120470d000b200241c8046a41086a221520024188086a41086a290300370300200241c8046a41106a220020024188086a41106a290300370300200241c8046a41186a221b20024188086a41186a29030037030020022002290388083703c80420022014200f6b22053602b40f0240200a200c470d00200c410174220f200d200f200d4b1b220aad42247e2204422088a70d122004a7220f4100480d1202400240200c0d00200f102821060c010b2006200c41246c200f102c21060b2006450d030b2006200c41246c6a220f2009360200200f20022903c804370204200f410c6a2015290300370200200f41146a2000290300370200200f411c6a201b290300370200200d210c200d200e470d000c040b0b200f41041037000b200f41041037000b0240200a0d00410021060c010b2006102a410021060b200241b00f6a200241b8076a10c70120022802b80f210f20022802b00f210520024100360288082005200f20024188086a1006210f024002402002280288082214417f460d00200f450d00200220143602dc062002200f3602d80620024188086a200241d8066a106d0240200228028808221c450d00200229028c0821042014450d02200f102a0c020b41c4d1c3004133200241f8056a419cd9c3001038000b420021044101211c0b024020022802b40f450d002005102a0b2004422088211102402010a7450d002013102a0b200e410020061b211d200a410020061b211e2006410420061b210c2011a7211f2004a72120200242003702dc02200241f8b9c0003602d8022007200841d0006c6a21210240024020080d00200721130c010b200241b8036a41306a212220024188086a410c6a212320164101742205201641ffffff3f712224200520244b1b222541ffffff3f71202547212620254105742127202420164721282016410574222941606a41057641016a212a20024188086a41306a212b20024188086a41206a212c20024188086a410272212d20024198056a41046a212e20024188086a41c0006a212f200241b00f6a41106a2130200241b8076a4104722131200241b8036a41c4006a21322018201820296a4621332007211302400240034020024188086a41386a22062013220541386a290300370300202b200541306a29030037030020024188086a41286a220a200541286a290300370300202c200541206a29030037030020024188086a41186a2234200541186a29030037030020024188086a41106a2235200541106a29030037030020024188086a41086a2236200541086a290300370300200241b00f6a41086a221b200541cc006a28020036020020022005290300370388082002200541c4006a2902003703b00f200541d0006a2113200541c0006a2802002205450d03200241f8026a41386a220f2006290300370300200241f8026a41306a2214202b290300370300200241f8026a41286a2215200a290300370300200241f8026a41206a220e202c290300370300200241f8026a41186a220d2034290300370300200241f8026a41106a22092035290300370300200241f8026a41086a22002036290300370300200241e8026a41086a2237201b28020036020020022002290388083703f802200220022903b00f3703e802200241b8036a41386a2238200f29030037030020222014290300370300200241b8036a41286a22392015290300370300200241b8036a41206a2215200e290300370300200241b8036a41186a223a200d290300370300200241b8036a41106a223b2009290300370300200241b8036a41086a223c2000290300370300200220022903f8023703b803200220053602f803203220022903e802370200203241086a20372802003602000240024002400240024002400240410410282214450d002014200b360000202341002900a2c740370000202341086a41002900aac74037000020024284808080c00037028c0820022014360288082002200241b8036a3602a408410810282205450d01200242083702b40f200220053602b00f2023200241b00f6a10c6014104200241b00f6a10b4010240024020022802b40f220f20022802b80f22056b4104490d0020022802b00f210f0c010b200541046a220e2005490d18200f4101742205200e2005200e4b1b22054100480d1802400240200f0d0020051028210f0c010b20022802b00f200f2005102c210f0b200f450d03200220053602b40f2002200f3602b00f20022802b80f21050b2002200541046a3602b80f200f20056a2014280000360000200241b8036a200241b00f6a108f01200220153602b807200241b8076a200241b00f6a10a301200220223602b807200241b8076a200241b00f6a10a30120022802f8032105200228028004220f200241b00f6a10b4010240200f450d00200f41306c210f0340200541106a200241b00f6a108f01200220053602b807200541306a2105200241b8076a200241b00f6a10a301200f41506a220f0d000b0b20022802b40f210f20022802b80f211520022802b00f2105200241c8046a41186a220d4200370300200241c8046a41106a22094200370300200241c8046a41086a22004200370300200242003703c80420052015200241c8046a100020024188046a41186a223d200d29030037030020024188046a41106a223e200929030037030020024188046a41086a223f2000290300370300200220022903c804370388040240200f450d002005102a0b2014102a411010282205450d032005410029008ab7402204370000200541086a4100290092b740221037000020024290808080800237028c082002200536028808200220024188086a3602b80720024188046a200241b8076a10c8012002280288082105200228029008210f200d42003703002009420037030020004200370300200242003703c8042005200f200241c8046a1000200241b00f6a41186a2240200d29030037030020302009290300370300201b2000290300370300200220022903c8043703b00f0240200228028c08450d00200228028808102a0b200241b00f6a41204101410041001003417f460d050c040b410441011037000b410841011037000b200541011037000b411041011037000b20022802fc03450d0120022802f803102a0c010b200241a8046a41186a2241203a290300370300200241a8046a41106a223a203b290300370300200241a8046a41086a223b203c290300370300200220022903b8033703a804200228028004220ead42307e2211422088a70d052011a7220f417f4c0d05203829030021112039290300211220022903e803214220022903d803214320022802f8032105024002400240024002400240024002400240024002400240200f0d00410821370c010b200f10282237450d010b02400240200e0d00410021140c010b2005200e41306c6a2115410021142037210f0340200f2005290300370300200f200541086a290300370308200f41106a200541106a290300370300200f41186a200541186a290300370300200f41206a200541206a290300370300200f41286a200541286a290300370300200f41306a210f201441016a2114200541306a22052015470d000b0b200241b00f6a41386a2011370300200241b00f6a41286a2012370300204020412903003703002030203a290300370300201b203b290300370300200220423703e00f200220433703d00f200220022903a8043703b00f200220143602f80f2002200e3602f40f200220373602f00f0240024020022802d802220541f8b9c000460d0020022802dc02210f0c010b20024188086a410041f0061099051a41f80610282205450d024100210f200541003b010620054100360200200541086a20024188086a41f006109a051a200241003602dc02200220053602d8020b2002200536028c082002200f360288082002200241d8026a36029008200241b8076a20024188086a200241b00f6a10c901024020022802b8074101470d00202f20312902003702002036203041086a2903003703002035203041106a2903003703002034203041186a290300370300202c203041206a290300370300200a203041286a290300370300202b203041306a2903003703002006203041386a290300370300202f41086a203141086a290200370200200220302903003703880820022802bc0f2115202e41086a220f201b280200360200202e20022903b00f370200200241c8046a20024188086a41d000109a051a200241a8056a200241c8046a41d000109a051a200220022802e00241016a3602e00220022802f005214120022802f405211420022802ec052105200241d8066a41086a22442000290300370300200241d8066a41106a220e2009290300370300200241d8066a41186a2237200d290300370300200241d8066a41206a2239200241c8046a41206a290300370300200241d8066a41286a223a200241c8046a41286a290300370300200241d8066a41306a223b200241c8046a41306a290300370300200241d8066a41386a223c200241c8046a41386a290300370300200241c8066a41086a2245200f280200360200200220022903c8043703d8062002202e2902003703c80620052f01062238410b490d0520024188086a410041f0061099051a41f80610282238450d03203841003b010620384100360200203841086a20024188086a41f006109a05210f20024188086a4108200541086a2246200541f8b9c0004622471b224841e0036a41d000109a051a200f204841b0046a20052f010641796a224841d0006c109a05210f200541063b0106203820483b0106200241b00f6a20024188086a41d000109a051a0240024020144107490d00201441d0006c4108200f203841f8b9c0004622061b6a220f41a07c6a200f41d07b6a220f4100204841ffff037120061b20146b41d0006c41b0046a109b051a200f201536020c200f41086a2045280200360200200f20022903c806370300200f20022903d806370310200f41186a2044290300370300200f41206a200e290300370300200f41286a2037290300370300200f41306a2039290300370300200f41386a203a290300370300200f41c0006a203b290300370300200f41c8006a203c290300370300203820382f010641016a3b01060c010b4108210f200241a8076a41086a200241c8066a41086a28020036020020024188086a41086a200241d8066a41086a2903003703002035200e29030037030020342037290300370300202c2039290300370300200a203a290300370300202b203b2903003703002006203c290300370300200220022903c8063703a807200220022903d80637038808024002402047450d004100210e0c010b20052f0106210e2046210f0b200f201441d0006c6a220f41d0006a200f200e20146b41d0006c109b051a200f201536020c200f41086a200241a8076a41086a280200360200200f20022903a807370300200f200229038808370310200f41186a2036290300370300200f41206a2035290300370300200f41286a2034290300370300200f41306a202c290300370300200f41386a200a290300370300200f41c0006a202b290300370300200f41c8006a2006290300370300200520052f010641016a3b01060b200241b8076a200241b00f6a41d000109a051a200241f8056a200241b8076a41d000109a051a2005280200220e450d0620052f010421370340200241d8066a200241f8056a41d000109a051a203741ffff0371210602400240024002400240200e2f01062205410b490d00202d410041a2071099051a41a80710282215450d0a20154100360200201541046a20024188086a41a407109a051a20024188086a4108200e41086a223b200e41f8b9c00046223c1b220541e0036a41d000109a051a201541086a223a200541b0046a200e2f0106220541796a220f41d0006c109a051a201541f8066a200e4194076a2005417a6a220a410274109a052139200e41063b01062015200f3b01060240200a450d00410021052039210f0340200f280200221420053b010420142015360200200f41046a210f200a200541016a2205470d000b0b200241b00f6a20024188086a41d000109a051a200241b8076a200241b00f6a41d000109a051a203741ffff037122054107490d0320024188086a200241d8066a41d000109a051a200641796a210541f8b9c0002114201541f8b9c000470d014108213a4100210a0c020b4108200e41086a200e41f8b9c0004622141b200641d0006c6a220f41d0006a200f4100200520141b20066b41d0006c109b051a200f200241d8066a41d000109a051a200e200e2f010641016a220f3b01062006410274200e41f8066a22146a41086a2014200641016a22054102746a2214200f41ffff0371220f20056b410274109b051a201420383602002006200f4f0d0c203820053b01042038200e3602002005200f4f0d0c200f417f6a2115200e2005417f6a22054102746a4180076a210f0340200f2802002214200541026a3b01042014200e360200200f41046a210f2015200541016a2205470d000c0d0b0b20152f0106210a201521140b203a2006417a6a220f41d0006c6a203a200541d0006c6a2237200a20056b41d0006c109b051a203720024188086a41d000109a051a201520152f010641016a220a3b01062006410274223720396a416c6a2039200f4102746a2206200a41ffff0371200f6b410274109b051a20062038360200200f20142f010622064b0d01201520376a41e0066a210f0340200f2802002214200541016a22053b010420142015360200200f41046a210f20052006490d000c020b0b200e41f8066a210f20024188086a200241d8066a41d000109a051a02400240203c450d004108213b4100210a0c010b200e2f0106210a0b203b200641d0006c6a221441d0006a2014200a20066b41d0006c109b051a201420024188086a41d000109a051a200e200e2f010641016a22143b010620064102742237200f6a41086a200f200641016a220a4102746a220f201441ffff0371200a6b410274109b051a200f20383602002005200e2f010622144f0d00200e20376a41fc066a210503402005280200220f200641016a22063b0104200f200e360200200541046a210520142006470d000b0b200241f8056a200241b8076a41d000109a051a0240200e28020022050d00201521380c080b200e2f010421372005210e201521380c000b0b20024198056a41086a203141086a2902003703002002203129020037039805200e450d062037102a0c060b200f41081037000b41f80641081037000b41f80641081037000b41a80741081037000b4108200541086a200541f8b9c0004622061b201441d0006c6a220f41d0006a200f4100203820061b20146b41d0006c109b051a200f201536020c200f41086a2045280200360200200f20022903c806370300200f20022903d806370310200f41186a2044290300370300200f41206a200e290300370300200f41286a2037290300370300200f41306a2039290300370300200f41386a203a290300370300200f41c0006a203b290300370300200f41c8006a203c290300370300200520052f010641016a3b01060c010b202d410041a2071099051a41a80710282205450d0120054100360200200541046a20024188086a41a407109a051a20052041280200220f3602f806204120053602002041204128020441016a360204200f41003b0104200f20053602004108200541086a200541f8b9c000461b20052f0106220f41d0006c6a200241f8056a41d000109a051a200541f8066a200f41016a220f4102746a2038360200200520052f010641016a3b01062038200f3b0104203820053602000b200241b00f6a200241b8036a41d000109a051a20280d082029417f4c0d080240024020290d00410121150c010b202910282215450d020b024020162024490d00201621060c030b20262027410048720d140240024020160d002027102821150c010b201520292027102c21150b2025210620150d02202741011037000b41a80741081037000b202941011037000b024002402033450d00410021050c010b20292114201521052018210f03402005200f290000370000200541186a200f41186a290000370000200541106a200f41106a290000370000200541086a200f41086a290000370000200541206a2105200f41206a210f201441606a22140d000b202a21050b20024188086a200241b00f6a41d000109a051a200220053602e008200220063602dc08200220153602d808024002400240411010282205450d0020052004370000200541086a20103700002002429080808080023702bc07200220053602b8072002200241b8076a3602d80620024188046a200241d8066a10c80120022802b807210520022802c007210f200d42003703002009420037030020004200370300200242003703c8042005200f200241c8046a10002040200d29030037030020302009290300370300201b2000290300370300200220022903c8043703b00f024020022802bc07450d0020022802b807102a0b200241003602c007200242013703b80720024188086a200241b8076a108f012002202c3602d806200241d8066a200241b8076a10a3012002202b3602d806200241d8066a200241b8076a10a30120022802c808210520022802d008220f200241b8076a10b4010240200f450d00200f41306c210f0340200541106a200241b8076a108f01200220053602d806200541306a2105200241d8066a200241b8076a10a301200f41506a220f0d000b0b20022802d808210520022802e008220f200241b8076a10b4010240200f450d00200f410574210f03402005200241b8076a108f01200541206a2105200f41606a220f0d000b0b20022802bc072105200241b00f6a412020022802b807220f20022802c007100702402005450d00200f102a0b024020022802cc08450d0020022802c808102a0b024020022802dc08450d0020022802d808102a0b200241b8076a41186a2206203d290300370300200241b8076a41106a220a203e290300370300200241b8076a41086a220e203f29030037030020022002290388043703b807410021050240201d41014b0d000240201d0e020003000b203420062903003703002035200a2903003703002036200e290300370300200220022903b80737038808410021050c030b201d210f03402005200f410176221420056a2215200c201541246c6a280200200b4b1b2105200f20146b220f41014b0d000c020b0b411041011037000b0240200c200541246c6a280200220f200b460d002005200f200b496a21050b203420062903003703002035200a2903003703002036200e290300370300200220022903b80737038808201d20054f0d0041f8b0c0001032000b0240201d201e470d00201d41016a220f201d490d12201d4101742214200f2014200f4b1b221ead42247e2204422088a70d122004a7220f4100480d1202400240201d0d00200f1028210c0c010b200c201d41246c200f102c210c0b200c450d030b200c200541246c6a220f41246a200f201d20056b41246c109b051a200f200b360200200f411c6a2034290300370200200f41146a2035290300370200200f410c6a2036290300370200200f200229038808370204204020062903003703002030200a290300370300201b200e290300370300200220022903b8073703b00f0240201f2020470d00201f41016a2205201f490d12201f410174220f2005200f20054b1b222041ffffff3f712020470d12202041057422054100480d1202400240201f0d0020051028211c0c010b201c201f4105742005102c211c0b201c450d040b201d41016a211d201c201f4105746a220520022903b00f370000200541186a2040290300370000200541106a2030290300370000200541086a201b290300370000201f41016a211f0b20132021470d000b202121130c020b200f41041037000b200541011037000b024020132021460d002007200841d0006c6a21140340201341c0006a280200220f450d01201341d0006a21050240201341c4006a280200450d00200f102a0b2005211320142005470d000b0b02402003450d002007102a0b0240024002400240024002400240024002400240024020022802e0020d0020022802d80220022802dc02410010ca01201a102a02402020450d00201c102a0b0240201e450d00200c102a0b2017450d012018102a0c010b2002201c3602d8062002201c201f4105746a3602dc06200241b00f6a200241d8066a10850102400240200241f00f6a2802000d004108210841002109410021230c010b20024188086a200241b00f6a41e000109a051a41e00010282208450d03200820024188086a41e000109a051a200220022903d8063703b807200241b00f6a200241b8076a1085010240200241f00f6a2802000d0041012109410121230c010b4102210f41e00021054101210941012123034020024188086a200241b00f6a41e000109a051a024020092023470d00200941016a22142009490d19200f2014200f20144b1b2223ad42e0007e2204422088a70d192004a722144100480d190240024020090d002014102821080c010b200820052014102c21080b2008450d060b200820056a20024188086a41e000109a051a200f41026a210f200541e0006a2105200941016a2109200241b00f6a200241b8076a10850120022802f00f0d000b0b200241a8086a201d360200200241a4086a201e36020020024198086a201fad4220862020ad843703002002201c3602940820024284808080c00037028c082002201a360288082002200c3602a008200241003602b80f200242013703b00f201d200241b00f6a10b4010240201d450d00200c201d41246c6a210a200c210f0340200f28020021150240024020022802b40f221420022802b80f22056b4104490d0020022802b00f21140c010b200541046a22062005490d19201441017422052006200520064b1b22054100480d190240024020140d002005102821140c010b20022802b00f20142005102c21140b2014450d07200220053602b40f200220143602b00f20022802b80f21050b2002200541046a3602b80f201420056a20153600002002200241b00f6a3602b807200f41046a200241b8076a10c801200f41246a220f200a470d000b0b20022802b80f211420022802b40f211520022802b00f210f411b10282205450d05200541176a41002800f39646360000200541106a41002900ec9646370000200541086a41002900e49646370000200541002900dc96463700002002429b808080b0033702bc07200220053602b80741a2c7c000200241b8076a10c60120022802c007210620022802b8072105200241c8046a41186a220a4200370300200241c8046a41106a220e4200370300200241c8046a41086a22134200370300200242003703c80420052006200241c8046a1000200241b00f6a41186a200a290300370300200241b00f6a41106a200e290300370300200241b00f6a41086a2013290300370300200220022903c8043703b00f024020022802bc07450d002005102a0b200241203602bc072002200241b00f6a3602b807200f2014200241b8076a10cb0102402015450d00200f102a0b200241b8076a20024188086a10c70120022802c007211520022802b8072114200241003602b80f200242013703b00f201f200241b00f6a10b4010240201f450d00201f410574210f201c210503402002200241b00f6a3602d8062005200241d8066a10c801200541206a2105200f41606a220f0d000b0b20022802b40f21052014201520022802b00f220f20022802b80f100702402005450d00200f102a0b024020022802bc07450d002014102a0b201a102a02402020450d00201c102a0b0240201e450d00200c102a0b20022802d802210520022902dc02210402402017450d002018102a0b20050d010b20012802082114024020012802102205450d00200541d0006c210f201441c0006a210503400240200541046a280200450d002005280200102a0b200541d0006a2105200f41b07f6a220f0d000b0b2001410c6a280200450d142014102a0c140b200220043702bc03200220053602b803410410282205450d042005200b36000020024190086a4284808080c00037030020024198086a41002900a2c740370300200241a0086a41002900aac7403703002002200536028c082002410f3a0088084101410020024188086a10cc012019418094ebdc036e22054101200541014b1b220520194b0d052019200941036c417d6a220f200f20194b1b20056ead428094ebdc037e201920056ead221080a741146e2215211420092004422088a76b220f0d060c070b41e00041081037000b201441081037000b200541011037000b411b41011037000b410441011037000b41acaac3001032000b2002418094ebdc0336028c082002418094ebdc03201941002009200f6b2214201420094b1b41036c417d6a2214201420194b1b20056ead428094ebdc037e201080a741146e22056bad4100201520056b2205200520154b1bad7e428094ebdc0380a722053602880820024188086a2005418094ebdc034b4102746a28020021140b200941e0006c220541e0006e2129410021130240024020050d0041042138410021290c010b2029410274220610282238450d020b0240200820056a2008460d000240200f0d00200941e0006c210f4100211320382105034020052014360200201341016a2113200541046a2105200f41a07f6a220f0d000c020b0b2008200941e0006c6a2106200941057441606a210a203821052008210f0340200220022802b8033602b40f200220022802bc033602b00f2002200241b8036a3602b80f20024188086a200241b00f6a200f10c9012005201420152002280288084101461b360200200541046a21052006200f41e0006a220f470d000b200a41057641016a21130b20024188086a41086a220542003703002002420037038808419e9dc600411b20024188086a1008200241b00f6a41086a200529030037030020022002290388083703b00f4100211b2002410036028808200241b00f6a411020024188086a100621050240200228028808220f417f460d002005450d00200f4104490d032005280000211b2005102a0b20024188086a41086a22054200370300200242003703880841bb9cc600411220024188086a1008200241b00f6a41086a200529030037030020022002290388083703b00f4100213b2002410036028808200241b00f6a411020024188086a100621050240200228028808220f417f460d002005450d00200f4104490d042005280000213b2005102a0b411710282205450d042005410f6a41002900d3fe44370000200541086a41002900ccfe44370000200541002900c4fe4437000020054117412e102c2205450d052005203b36001742002149200241f8056a41186a220f4200370300200241f8056a41106a22144200370300200241f8056a41086a22154200370300200242003703f8052005411b200241f8056a1000200241a8056a41186a200f290300370300200241a8056a41106a2014290300370300200241a8056a41086a2015290300370300200220022903f8053703a8052005102a2002410036028808200241a8056a412020024188086a100621002002280288082230417f460d092000450d09200220303602fc02200220003602f802200241c0026a200241f8026a106c20022802c0020d0820022802fc0222154140712205417f4c0d0020022802c402210d024002402015410676220e0d004108211d0c010b20051028221d450d070b0240200d450d004100210a0340200241003a00a808200a220641016a210a41002105024002400240034020152005460d0120024188086a20056a20022802f80222142d00003a00002002201441016a3602f8022002200541016a220f3a00a808200f2105200f4120470d000b200241f8056a41186a220520024188086a41186a290300370300200241f8056a41106a220b20024188086a41106a290300370300200241f8056a41086a220c20024188086a41086a29030037030020022002290388083703f8052015200f6b220f4110490d012002201441116a3602f802200f41706a410f4b0d02200f41706a210f0c010b0240200541ff0171450d00200241003a00a8080b4100210f0b200241b8076a41086a200241b00f6a41086a290300370300200220022903b00f3703b8072002200f3602fc02200e450d0b201d102a0c0b0b201441096a290000210420142900012110200241b8076a41086a2215200c290300370300200241b8076a41106a220c200b290300370300200241b8076a41186a220b20052903003703002002201441216a3602f802200220022903f80522113703b00f200220113703b807201441196a290000211120142900112112200241d8066a41186a2214200b290300370300200241d8066a41106a220b200c290300370300200241d8066a41086a220c2015290300370300200220022903b8073703d8060240200e2006470d0020064101742205200a2005200a4b1b220e41ffffff1f71200e470d0f200e41067422054100480d0f0240024020060d0020051028211d0c010b201d20064106742005102c211d0b201d450d0a0b200f41606a2115201d20064106746a220520123703102005200437030820052010370300200541186a2011370300200520022903d806370320200541286a200c290300370300200541306a200b290300370300200541386a2014290300370300200a200d470d000b2002200f41606a3602fc020b201d450d08200dad422086200ead84214902402030450d002000102a0b2049422088a7210f2049a7210e0c0a0b1036000b200641041037000b41c4d1c3004133200241f8056a419cd9c3001038000b41c4d1c3004133200241f8056a419cd9c3001038000b411741011037000b412e41011037000b200541081037000b200541081037000b41c4d1c3004133200241f8056a419cd9c3001038000b4108211d4100210f4100210e0b0240024020132009200920134b1b221f0d004200214a4200214b0c010b200241b00f6a4105722122200241b8076a41036a213920024188086a410572213220024188086a41086a2113201bad214c20024191086a2135200241e8016a41186a213a2008210b4200214a4200214b41002130034020134200370300200242003703880841c8ffc400411520024188086a1008200241b00f6a41086a2236201329030037030020022002290388083703b00f2002410036028808200241b00f6a411020024188086a100621140240024002400240024002400240024002400240024002400240024002400240024002400240200228028808220f417f460d002002200f3602bc07200220143602b80720024188086a200241b8076a106d2002280288082205450d02200229028c082104200f450d012014102a0c010b42002104410121050b20052004422088a72008203041e0006c6a220f10cd01211402402004a7450d002005102a0b20140d10200241b0026a200f41206a22342903002204203441086a222c290300428094ebdc03420010a005200241a0026a20022903b0022210200241b0026a41086a29030022114280ec94a37c427f109f0520024190026a20102011203820304102746a35020022124200109f0520022903900222102012200420022903a0027c7e428094ebdc038042ffffffff0f837c220420024190026a41086a2903002004201054ad7c2210844200510d1020134200370300200242003703880841c785c200411220024188086a100820024198056a41086a220c2013290300370300200220022903880837039805200241003602880820024198056a411020024188086a10062105024002402002280288082214417f460d002005450d00200220143602b40f200220053602b00f20024188086a200241b00f6a106d2002280288082237450d03200229028c0821122014450d012005102a0c010b41012137420021120b20372012422088a74105746a21064100211420372105024003400240200620056b41e0004b0d004102212b20052006460d080340200b2005460d0320142005200f4120109c0522154100476a21142015450d032006200541206a2205470d000c090b0b2005200f460d0120142005200f4120109c0522154100476a21142015450d01200541206a2215200f460d0120142015200f4120109c0522154100476a21142015450d01200541c0006a2215200f460d0120142015200f4120109c0522154100476a21142015450d01200541e0006a2215200f460d0120142015200f4120109c0522154100476a211420054180016a210520150d000b0b20134200370300200242003703880841bd99c600411a20024188086a1008200c2013290300370300200220022903880837039805200241003602880820024198056a411020024188086a100621052002280288082206417f460d032005450d03200220063602b40f200220053602b00f20024188086a200241b00f6a1082012002280288082215450d02200229028c0821112006450d042005102a0c040b41c4d1c3004133200241f8056a419cd9c3001038000b41c4d1c3004133200241f8056a419cd9c3001038000b41c4d1c3004133200241f8056a419cd9c3001038000b410021150b2015410420151b21004100210502400240024002402011420020151b22114220882242a7220e41014b0d00200e0e020201020b200e2115034020052015410176220620056a220a20142000200a4102746a280200491b2105201520066b221541014b0d000b0b4100212b02402014200020054102746a2802002215470d00410021400c020b2005201420154b6a21050b20134200370300200242003703880841c785c200411220024188086a1008200c2013290300370300200220022903880837039805200241003602880820024198056a411020024188086a1006210602400240200228028808220a417f470d00410021150c010b024020060d00410021150c010b2002200a36028c08200220063602880820024188026a20024188086a106c024002402002280288020d00200228028c0221150c010b410021150b200a450d002006102a0b20152015418094ebdc036e22064180ec94a37c6c6aad4280fd87d1007e428094ebdc038021432005200e4b0d020240200e2011a7470d00200e41016a2215200e490d11200e410174220a20152015200a491b221541ffffffff03712015470d112015410274220a4100480d1102400240200e0d00200a102821000c010b2000200e410274200a102c21000b2000450d042015ad21110b200020054102746a221541046a2015200e20056b410274109b051a2015201436020041012140201142ffffffff0f83200e41016a2205ad2242422086842111200520064180fd87d1006c2043a76a4b212b0b20134200370300200242003703880841bd99c600411a20024188086a1008200c20132903003703002002200229038808370398050240024020000d0020024198056a411010090c010b200241003602900820024201370388082042a7221520024188086a10b4010240024020150d00200228029008210c200228028c08210e20022802880821150c010b410020022802900822056b2106200020154102746a211b200228028c08210e2000210a0340200a280200210d02400240200e20066a4104490d0020022802880821150c010b200541046a22152005490d13200e410174220c2015200c20154b1b220c4100480d1302400240200e0d00200c102821150c010b200228028808200e200c102c21150b2015450d072002200c36028c082002201536028808200c210e0b2002200541046a220c36029008201520056a200d3600002006417c6a2106200c2105201b200a41046a220a470d000b0b2011a7210520024198056a41102015200c10070240200e450d002015102a0b2005450d002000102a0b2040450d00200241023602b00f20022014ad3703b80f20024188086a200241b00f6a10c301203941086a221520132802003600002039200229038808370000203220022900b807370000203241076a200241b8076a41076a2206290000370000200241c6a4b9da0436008908200241023a00880820024188086a10ce012002201436028c082002410136028808200241003602b80f200242013703b00f410110282205450d04200220053602b00f200520022802b80f22146a41023a0000200241013602b40f2002201441016a22053602b80f200228028c08210a02400240410020146b4104490d0020022802b00f21140c010b200541046a22142005490d10410141017422052014200520144b1b22054100480d100240024041010d002005102821140c010b20022802b00f41012005102c21140b2014450d06200220053602b40f200220143602b00f20022802b80f21050b2002200541046a3602b80f201420056a200a360000200241d8066a41086a20022802b80f2205360200200220022903b00f22113703d8062015200536000020392011370000202220022900b807370000202241076a2006290000370000200241c28289aa043600b10f200241023a00b00f200241b00f6a10ce012002280288080d00200228029008450d00200228028c08102a0b02402012a7450d002037102a0b0240202b4102460d00202b410171450d00201342003703002002420037038808418e9dc600411020024188086a10082036201329030037030020022002290388083703b00f410110282205450d06200541013a0000200241b00f6a41102005410110072005102a0b202c2903002212201020342903002243200454201220105420122010511b22051b214d2043200420051b214e024002402049422088224fa722060d0042002110420021040c010b20064106742114201d41206a21054200211042002104034002400240200b2005460d002005200f4120109c050d010b427f2004200541706a221541086a2903007c201020152903007c22112010542215ad7c22102015201020045420102004511b22151b2104427f201120151b21100b200541c0006a2105201441406a22140d000b0b200241e8016a200f204e4200200f290330221120107d22422042201156200f41386a290300224220047d2011201054ad7d220420425620042042511b22051b22102010204e564200200420051b2204204d562004204d511b22051b2210204d200420051b220410cf01200241e8016a41086a290300215020022903e80121510240204e201020022903f80122527d22537d2254204d2004203a2903007d2010205254ad7d22557d204e205354ad7d225284500d00204320117d2210201220427d2043201154ad7d220484500d00200f2802482214450d00200f2802402205201441306c6a2115200241c8016a20542052428094ebdc03420010a005200241d8016a20102004428094ebdc03420010a005200241b8016a20022903c8012252200241c8016a41086a29030022564280ec94a37c427f109f05200241d8016a41086a2903002211420020022903d801224242015620114200522011501b22141b21122042420120141b2142205420022903b8017c21540340200241a8016a2010200529030022112011201056200541086a290300221120045620112004511b22141b2004201120141b2042201210a00520022903a8012243428080808010544100200241a8016a41086a290300501b450d0820024198016a201020042042201210a005200229039801221142808080801054410020024198016a41086a290300501b450d092011a7450d0a200241e8006a20522056204342ffffffff0f83428094ebdc037e201142ffffffff0f838042ffffffff0f8322114200109f05200241f8006a200541106a20022903682243201120547e428094ebdc038042ffffffff0f837c2211200241e8006a41086a2903002011204354ad7c10cf01427f2050200241f8006a41086a2903007c205120022903787c22432051542214ad7c22112014201120505420112050511b22141b2150427f204320141b2151200541306a22052015470d000b0b200241a8056a41186a2215200f41186a220a290300370300200241a8056a41106a220e200f41106a220c290300370300200241a8056a41086a220d200f41086a22002903003703002002200f2903003703a8050240024020062049a7460d00200621140c010b200641016a22052006490d0f204fa72214410174221b20052005201b491b220541ffffff1f712005470d0f2005410674221b4100480d0f0240024020060d00201b1028211d0c010b201d2014410674201b102c211d0b201d450d0a2005ad21490b200241d8006a20512050428094ebdc03420010a005200241c8006a20022903582204200241d8006a41086a29030022104280ec94a37c427f109f05200241386a20042010204c4200109f05201d20144106746a220520533703102005204d3703082005204e370300200541186a2055370300200520022903a805370320200541286a200d290300370300200541306a200e290300370300200541386a2015290300370300200241013a009008200241033a008808200a2900002104200c290000211020002900002111200f290000211220024188086a41386a204d37030020352012370000203541086a2011370000203541106a2010370000203541186a20043700002002204e3703b8084101410020024188086a10cc01204942ffffffff0f83201441016aad4220868421490240024020022903382210205120022903487c204c7e428094ebdc038042ffffffff0f837c2204200241386a41086a2903002004201054ad7c221084500d00200f41d8006a28020022050d010b427f204b20507c204a20517c2210204a542205ad7c220420052004204b542004204b511b22051b214b427f201020051b214a0c0b0b200241286a200420512051200456205020105620502010511b22141b22542010205020141b224d2005ad420010a00520054105742114200f2802502105200241286a41086a29030021522002290328215620542112204d21420340200241186a2005205620122012205656204220525620422052511b220f1b220420522042200f1b221010d00120024188086a41106a2010200241186a41086a29030022437d20042002290318221154ad7d204320107d2011200454ad7d201120045820432010582043201051220f1b22151b3703002002200420117d201120047d20151b37039008200220112004562043201056200f1b220fad37038808204220107d21102012200454ad211102400240200f0d00200220133602b00f200241b00f6a109d010c010b200220133602b00f200241b00f6a109c010b201020117d2142201220047d2112200541206a2105201441606a22140d000b427f427f204b20427c204a20127c2210204a542205ad7c220420052004204b542004204b511b22051b22042050204d7d2051205454ad7d7c427f201020051b2210205120547d7c22112010542205ad7c22102005201020045420102004511b22051b214b427f201120051b214a0c0a0b41f8b0c0001032000b200a41041037000b200c41011037000b410141011037000b200541011037000b410141011037000b10d101000b10d201000b41acaac3001032000b201b41081037000b200b41e0006a210b203041016a2230201f490d000b2049422088a7210f2049a7210e0b024002400240024002400240411710282205450d002005410f6a41002900d3fe44370000200541086a41002900ccfe44370000200541002900c4fe4437000020054117412e102c2205450d012005203b360017200241f8056a41186a22144200370300200241f8056a41106a22154200370300200241f8056a41086a22064200370300200242003703f8052005411b200241f8056a1000200241a8056a41186a2014290300370300200241a8056a41106a2015290300370300200241a8056a41086a2006290300370300200220022903f8053703a8052005102a20024100360290082002420137038808200f20024188086a10b401200f450d02200f410674210a201d21050340200541206a20024188086a108f01200541086a29030021042005290300211002400240200228028c08221420022802900822156b4110490d00200228028808210f0c010b201541106a220f2015490d0920144101742215200f2015200f4b1b22064100480d090240024020140d0020061028210f0c010b20022802880820142006102c210f0b200f450d052002200636028c082002200f360288082002280290082115200621140b200f20156a22062004370008200620103700002002201541106a221536029008200541186a2903002104200541106a290300211002400240201420156b410f4d0d00201421060c010b201541106a22062015490d09201441017422152006201520064b1b22064100480d090240024020140d0020061028210f0c010b200f20142006102c210f0b200f450d062002200636028c082002200f3602880820022802900821150b200541c0006a2105200f20156a22142004370008201420103700002002201541106a221436029008200a41406a220a0d000c060b0b411741011037000b412e41011037000b2002280290082114200228028c082106200228028808210f0c020b200641011037000b200641011037000b200241a8056a4120200f2014100702402006450d00200f102a0b0240200e450d00201d102a0b20024188086a10d301200241086a20024188086a204a204b10d001200241c00f6a204b200241086a41086a29030022107d204a2002290308220454ad7d2010204b7d2004204a54ad7d2004204a582010204b582010204b5122051b220f1b3703002002204a20047d2004204a7d200f1b3703b80f20022004204a562010204b5620051b2205ad3703b00f200241b00f6a41086a210f0240024020050d002002200f3602b807200241b8076a109d010c010b2002200f3602b807200241b8076a109c010b02402029450d002038102a0b02402009450d00200941e0006c210f200841d4006a210503400240200541706a280200450d002005416c6a280200102a0b02402005280200450d002005417c6a280200102a0b200541e0006a2105200f41a07f6a220f0d000b0b02402023450d002008102a0b20022802b80320022802bc0320022802c00310ca0120012802082114024020012802102205450d00200541d0006c210f201441c0006a210503400240200541046a280200450d002005280200102a0b200541d0006a2105200f41b07f6a220f0d000b0b2001410c6a280200450d002014102a0b20024190106a24000f0b1031000b8c1501037f0240024002400240024002400240024002400240024002400240024002400240024002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00003a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00013a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00023a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00033a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00043a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00053a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00063a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0820012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00073a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0920012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00083a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0a20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00093a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000a3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0c20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000b3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0d20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000c3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0e20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000d3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0f20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000e3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d1020012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20002d000f3a00000f0b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b1031000bba0601087f230041d0006b220224000240024002400240024002400240411f10282203450d00200341176a41002900c9c740370000200341106a41002900c2c740370000200341086a41002900bac740370000200341002900b2c7403700002002429f808080f0033702242002200336022041a2c7c000200241206a10c6012002280228210420022802202103200241306a41186a22054200370300200241306a41106a22064200370300200241306a41086a220742003703002002420037033020032004200241306a1000200241186a2005290300370300200241106a2006290300370300200241086a20072903003703002002200229033037030002402002280224450d002003102a0b412010282203450d0120032002290300370000200341186a200241186a290300370000200341106a200241106a290300370000200341086a200241086a2903003700002001280208220441046a2205417f4c0d02200128020021070240024020050d00410121010c010b200510282201450d040b2002410036023820022005360234200220013602302004200241306a10b4010240024020022802342206200228023822016b2004490d00200228023021050c010b200120046a22052001490d06200641017422082005200820054b1b22084100480d060240024020060d002008102821050c010b200228023020062008102c21050b2005450d052002200836023420022005360230200821060b200520016a20072004109a051a200241306a41186a22074200370300200241306a41106a22084200370300200241306a41086a22094200370300200242003703302005200120046a200241306a1000200241186a2007290300370300200241106a2008290300370300200241086a20092903003703002002200229033037030002402006450d002005102a0b2003412041c000102c2203450d0620032002290300370020200341386a200241186a290300370000200341306a200241106a290300370000200341286a200241086a290300370000200042c0808080800837020420002003360200200241d0006a24000f0b411f41011037000b412041011037000b1036000b200541011037000b200841011037000b1031000b41c00041011037000bba0501037f02400240024002400240024002400240410110282202450d00200220002d00003a0000200241014102102c2202450d01200220002d00013a0001200241024104102c2202450d02200220002d00023a0002200220002d00033a0003200241044108102c2202450d03200220002d00043a0004200220002d00053a0005200220002d00063a0006200220002d00073a0007200241084110102c2202450d04200220002d00083a0008200220002d00093a0009200220002d000a3a000a200220002d000b3a000b200220002d000c3a000c200220002d000d3a000d200220002d000e3a000e200220002d000f3a000f200241104120102c2202450d05200220002d00103a0010200220002d00113a0011200220002d00123a0012200220002d00133a0013200220002d00143a0014200220002d00153a0015200220002d00163a0016200220002d00173a0017200220002d00183a0018200220002d00193a0019200220002d001a3a001a200220002d001b3a001b200220002d001c3a001c200220002d001d3a001d200220002d001e3a001e200220002d001f3a001f024002402001280200220041046a2802002203200041086a28020022016b4120490d00200028020021030c010b200141206a22042001490d08200341017422012004200120044b1b22014100480d080240024020030d002001102821030c010b200028020020032001102c21030b2003450d0720002003360200200041046a2001360200200041086a28020021010b200041086a200141206a360200200320016a220041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a290000370000200020022900003700002002102a0f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b200141011037000b1031000b9705060a7f047e037f027e047f027e200128020821032001280204210420012802002105200241386a2106200241286a2107034002400240200441f8b9c000462208450d00410021094108210a4108210b0c010b20042f01062109200441086a220a210b0b200b200941d0006c6a210c2006290300210d2007290300210e2002290330210f2002290320211020022802482111200228024021124100210b0240024002400340200b21090240200a200c470d0002402008450d00410021090c030b20042f010621090c020b024002402002200a4120109c05220b450d00417f4101200b4100481b21130c010b417f2010200a290320221485200e200a41286a290300221585844200522010201454200e201554200e2015511b1b22130d00417f200f200a41306a290300221485200d200a41386a29030022158584420052200f201454200d201554200d2015511b1b22130d00200a41c8006a28020022162011201120164b1b2117200a280240210b417f21182012211903400240201841016a22182017490d00417f201120164720112016491b21130c020b0240201941106a200b41106a4120109c052213450d00417f410120134100481b21130c020b2019290300221a200b290300221b54201941086a2903002215200b41086a29030022145420152014511b0d03200b41306a210b201941306a211941012113201a201b85201520148584500d000b0b200941016a210b200a41d0006a210a0240201341016a0e03020001020b0b4100210a0c010b20050d014101210a410021050b200020053602042000200a360200200041106a20093602002000410c6a2003360200200041086a20043602000f0b2001200336020820012005417f6a22053602002001200420094102746a41f8066a28020022043602040c000b0bee0303047f017e017f02402001450d00034020002802f80621002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d004108200041086a200041f8b9c000461b200141d0006c6a22042802442105200441c0006a2802002106200141016a21010c010b02400240200028020022010d002003ad210741002104410021010c010b20003301044220862003ad842107410121040b2000102a2007a72103024002402007422088a7220820012f01064f0d00200121000c010b034002400240200128020022000d002003ad2107410021000c010b200441016a210420013301044220862003ad8421070b2001102a2007a72103200021012007422088a7220820002f01064f0d000b0b4108200041086a200041f8b9c000461b200841d0006c6a22012802442105200141c0006a2802002106200841027420006a41fc066a280200210002402004417f6a2201450d00034020002802f80621002001417f6a22010d000b0b410021010b2006450d012002417f6a210202402005450d002006102a0b20020d000b0b0240200041f8b9c000460d00200028020021012000102a2001450d00200128020021002001102a2000450d00024020002802002201450d0003402000102a2001210020012802002203210120030d000b0b2000102a0b0b9d0201057f230041106b220324000240024002400240200141046a2204417f4c0d000240024020040d00410121050c010b200410282205450d020b2003410036020820032004360204200320053602002001200310b4010240024020032802042206200328020822056b2001490d00200328020021040c010b200520016a22042005490d04200641017422072004200720044b1b22074100480d040240024020060d002007102821040c010b200328020020062007102c21040b2004450d032003200736020420032004360200200721060b200420056a20002001109a051a200228020020022802042004200520016a100702402006450d002004102a0b200341106a24000f0b1036000b200441011037000b200741011037000b1031000bcd1f03087f047e017f230041a0036b2203240020034100360288014188e8c200411020034188016a10062104024002402003280288012205417f460d002004450d00024020054104490d00200428000021062004102a410021070c020b41c4d1c300413320034188016a419cd9c3001038000b410121070b0240024002400240024002400240024002400240024020010d004101210841002105410021090c010b200141057422044100480d07200410282208450d012001410574220941606a410576210a2008210420002105034020034188016a41186a200541186a290000220b37030020034188016a41106a200541106a290000220c37030020034188016a41086a200541086a290000220d37030020032005290000220e37038801200441186a200b370000200441106a200c370000200441086a200d3700002004200e370000200441206a2104200541206a2105200941606a22090d000b200a41016a2109200121050b200341f4006a2006360200200320073602702003200241f000109a0522044180016a2009360200200441fc006a20053602002004200836027820044190026a41086a22054200370300200442003703900241eea0c600411120044190026a1008200441b0026a41086a200529030037030020042004290390023703b0022004410036028801200441b0026a411020044188016a10062105024002400240024002400240024002402004280288012203417f470d00410021080c010b024020050d00410021080c010b20034104490d01200528000021082005102a0b0240200841016a22032008490d0020044190026a41086a22054200370300200442003703900241eea0c600411120044190026a1008200441b0026a41086a2209200529030037030020042004290390023703b0022004200336028801200441b0026a411020044188016a4104100720044188016a2004418801109a051a20054200370300200442003703900241d4f2c200410d20044190026a10082009200529030037030020042004290390023703b0022004410036029002200441b0026a411020044190026a10062103024002402004280290022205417f460d002005210920030d010b2004410036028003200442083703f80220044100360298022004420137039002410020044190026a10b401200428029802210520042802940221092004280290022103200441f8026a10720b200420053602c802200420093602c402200420033602c002024002402005450d0020044190026a20032005410110d6022004280290024101470d0120042802c402450d0c20042802c002102a0c0c0b4101200441c0026a10b40120044188016a200441c0026a10aa030c090b200428029402210202402004419c026a280200220520044198026a2802002203460d0020042802c802200520036b6a22094188016a2207417f4c0d100240024020070d00410121060c010b200710282206450d040b200420073602d402200420063602d002200420093602d8022004200441d0026a36029002200220044190026a200510d70120092005490d0420042802d80222022009490d0520042802c80222022003490d0620042802d002210720042802c00221062004200920056b22093602dc022004200220036b22023602940320092002470d07200720056a200620036a2009109a051a20044188016a200441d0026a10aa0320042802d802210320042802d402210920042802d002210520042802c402450d0a20042802c002102a0c0a0b2004200441c0026a36029002200220044190026a200310d70120044188016a200441c0026a10aa030c080b200410ab030c0b0b41c4d1c300413320044188016a419cd9c3001038000b200741011037000b200520091044000b20092002103c000b200320021044000b200441f8026a41146a410836020020044184036a4125360200200441e0026a41146a4103360200200442033702e402200441c8afc6003602e002200441253602fc022004200441dc026a36029803200420044194036a36029c03200442043703a00220044201370294022004419cb0c600360290022004200441f8026a3602f002200420044190026a3602880320042004419c036a36028003200420044198036a3602f802200441e0026a41d8b0c600103e000b200441011037000b20042802c802210320042802c402210920042802c00221050b20050d010b20044188016a10ab030c010b200441b0026a411020052003100702402009450d002005102a0b20044188016a10ab0320044190026a41086a22054200370300200442003703900241d9efc200410d20044190026a1008200441b0026a41086a200529030037030020042004290390023703b0024100210f2004410036028801200441b0026a411020044188016a1006210502402004280288012203417f460d002005450d0020034104490d032005280000210f2005102a0b2001450d002001410574210a02400340200420083602d4022004200f3602d0020240024002400240024002400240024002400240024002400240024002400240411210282205450d00200541106a41002f00f1f2423b0000200541086a41002900e9f242370000200541002900e1f24237000020044188016a41186a2203420037030020044188016a41106a2209420037030020044188016a41086a2201420037030020044200370388012005411220044188016a100020044190026a41186a2202200329030037030020044190026a41106a2207200929030037030020044190026a41086a220620012903003703002004200429038801370390022005102a412010282205450d012005200429039002370000200541186a2002290300370000200541106a2007290300370000200541086a200629030037000020044188016a200010e0022005412041c000102c2205450d022005200429008801370020200541386a2003290000370000200541306a2009290000370000200541286a20012900003700002004410036028801200541c00020044188016a10062109024002402004280288012201417f460d00200121030c010b20044100360290012004420137038801410020044188016a10b4012004280290012103200428028c01210120042802880121090b200420033602b802200420013602b402200420093602b002024002400240024002402003450d0020044188016a20092003410110d6022004280288014101460d04200428028c01210220042802940122032004280290012209460d0320042802b802200320096b6a220141086a2207417f4c0d1a20070d01410121060c020b4101200441b0026a10b40120042802d00221010240024020042802b402220920042802b80222036b4104490d0020042802b00221090c010b200341046a22022003490d18200941017422032002200320024b1b22034100480d180240024020090d002003102821090c010b20042802b00220092003102c21090b2009450d08200420033602b402200420093602b00220042802b80221030b2004200341046a3602b802200920036a200136000020042802d40221010240024020042802b402220920042802b80222036b4104490d0020042802b00221090c010b200341046a22022003490d18200941017422032002200320024b1b22034100480d180240024020090d002003102821090c010b20042802b00220092003102c21090b2009450d09200420033602b402200420093602b00220042802b80221030b2004200341046a3602b802200920036a20013600000c120b200710282206450d080b200420073602e402200420063602e002200420013602e8022004200441e0026a36028801200220044188016a200310d70120012003490d0820042802e80222022001490d0920042802b80222022009490d0a20042802e002210720042802b00221062004200120036b2201360294032004200220096b22023602980320012002470d0b200720036a200620096a2001109a051a20042802d00221010240024020042802e402220920042802e80222036b4104490d0020042802e00221090c010b200341046a22022003490d16200941017422032002200320024b1b22034100480d160240024020090d002003102821090c010b20042802e00220092003102c21090b2009450d0d200420033602e402200420093602e00220042802e80221030b2004200341046a3602e802200920036a200136000020042802d40221010240024020042802e402220920042802e80222036b4104490d0020042802e00221090c010b200341046a22022003490d16200941017422032002200320024b1b22034100480d160240024020090d002003102821090c010b20042802e00220092003102c21090b2009450d0e200420033602e402200420093602e00220042802e80221030b2004200341046a3602e802200920036a200136000020042802e802210920042802e402210120042802e002210320042802b402450d1120042802b002102a0c110b2004200441b0026a36028801200220044188016a200910d70120042802d00221010240024020042802b402220920042802b80222036b4104490d0020042802b00221090c010b200341046a22022003490d15200941017422032002200320024b1b22034100480d150240024020090d002003102821090c010b20042802b00220092003102c21090b2009450d0e200420033602b402200420093602b00220042802b80221030b2004200341046a3602b802200920036a200136000020042802d40221010240024020042802b402220920042802b80222036b4104490d0020042802b00221090c010b200341046a22022003490d15200941017422032002200320024b1b22034100480d150240024020090d002003102821090c010b20042802b00220092003102c21090b2009450d0f200420033602b402200420093602b00220042802b80221030b2004200341046a3602b802200920036a20013600000c0f0b20042802b402450d1120042802b002102a0c110b411241011037000b412041011037000b41c00041011037000b200341011037000b200341011037000b200741011037000b200320011044000b20012002103c000b200920021044000b200441f8026a41146a410836020020044184036a412536020020044190026a41146a41033602002004420337029402200441c8afc60036029002200441253602fc02200420044194036a36029c03200420044198036a3602c00220044204370398012004420137028c012004419cb0c600360288012004200441f8026a3602a002200420044188016a360288032004200441c0026a3602800320042004419c036a3602f80220044190026a41d8b0c600103e000b200341011037000b200341011037000b200341011037000b200341011037000b20042802b802210920042802b402210120042802b00221030b2003450d01200541c00020032009100702402001450d002003102a0b200041206a21002005102a200a41606a220a0d000c020b0b2005102a0b200441a0036a24000f0b1031000b41c4d1c300413320044188016a419cd9c3001038000b1036000bcd0101047f200020014105746a210320002104024003400240200320046b41e0004b0d00024020042003460d00200020014105746a210503404101210620022004460d04200420024120109c05450d042005200441206a2204470d000b0b41000f0b4101210620042002460d01200420024120109c05450d01200441206a22052002460d01200520024120109c05450d01200441c0006a22052002460d01200520024120109c05450d01200441e0006a22052002460d0120044180016a2104200520024120109c050d000b0b20060bba0604017f017e047f027e230041c0006b2201240042002102200141186a41086a220342003703002001420037031841b1f0c200410d200141186a1008200141086a200329030037030020012001290318370300410021032001410036021820014110200141186a100621040240024002400240024020012802182205417f460d002001200536021420012004360210200141186a200141106a107620012802182206450d02200129021c210202402005450d002004102a0b2002422088a721032002a721050c010b41042106410021050b200141186a41206a200041206a280200360200200141186a41186a200041186a290200370300200141186a41106a200041106a290200370300200141186a41086a200041086a29020037030020012000290200370318024020032005470d00024020032002a7470d00200341016a22002003490d04200341017422052000200520004b1bad220742247e2208422088a70d042008a722004100480d040240024020030d002000102821060c010b2006200341246c2000102c21060b2006450d0320024280808080708320078421020b2002422088a721030b2006200341246c22056a22002001290318370200200041206a200141186a41206a280200360200200041186a200141186a41186a290300370200200041106a200141186a41106a290300370200200041086a200141186a41086a2200290300370200200042003703002001420037031841b1f0c200410d200141186a1008200141086a2000290300370300200120012903183703002001411036021c200120013602182006200341016a2200200141186a10e102024020002003490d00200541246a21002006210303400240024020032d0000220541034b0d0002400240024020050e0404000102040b2003410c6a280200450d03200341086a280200102a0c030b2003410c6a280200450d02200341086a280200102a0c020b2003410c6a280200450d01200341086a280200102a0c010b200341086a280200450d00200341046a280200102a0b200341246a21032000415c6a22000d000b0b02402002a7450d002006102a0b200141c0006a24000f0b41c4d1c3004133200141186a419cd9c3001038000b200041041037000b1031000b8c0702067f067e230041d0006b220424000240024002400240411410282205450d00200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b2001200a2002200a200a200256200b200356200b2003511b22051b220c7d200b2003200b20051b220d7d200a200c54ad7d108f02024002402002200c7d220b2003200d7d2002200c54ad7d220e8450450d004200210a4200210e0c010b411810282205450d03200541002900e3e140370000200541106a41002900f3e140370000200541086a41002900ebe140370000200442988080808003370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d0042002102420021030c010b20064110490d05200541086a2900002103200529000021022005102a0b20012002200b20022002200b562003200e562003200e511b22051b220a7d2003200e200320051b220f7d2002200a54ad7d109002200e200f7d200b200a54ad7d210e200f200d7c200a200c7c2202200a54ad7c2103200b200a7d210a0b2000200a37031020002002370300200041186a200e37030020002003370308200441d0006a24000f0b411441011037000b41c4d1c3004133200441306a419cd9c3001038000b411841011037000b41c4d1c3004133200441306a419cd9c3001038000be20302067f027e230041d0006b2204240002400240411410282205450d00200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b200441306a2001200a20027c2202200b20037c2002200a54ad7c109401200441106a200441306a41106a290300220a370300200420042903382202370308200420042903302203370300024020034200510d002004200441086a360230200441306a109d01420021024200210a0b200020023703002000200a370308200441d0006a24000f0b411441011037000b41c4d1c3004133200441306a419cd9c3001038000b0a0041a8acc3001032000b0a0041b8abc3001032000bbf0301077f230041d0006b22012400024002400240024002400240410110282202450d00200241ed003a0000200241014102102c2202450d01200241ef003a0001200241024104102c2202450d02200241e4d8013b0002200241044108102c2202450d03200241f0f2bda107360004200241084110102c2203450d04200341f2e6c9cb07360008200141003a0048410c210220032104410021050340200141003a0008200141086a200420024100472206109a051a024020020d00200141003a00080b20022006490d06200141286a20056a20012d00083a00002001200541016a22073a0048200220066b2102200420066a21042007210520074120470d000b200141086a41186a2202200141286a41186a290300370300200141086a41106a2206200141286a41106a290300370300200141086a41086a2204200141286a41086a290300370300200120012903283703082003102a200041186a2002290300370000200041106a2006290300370000200041086a200429030037000020002001290308370000200141d0006a24000f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b200620021044000b940705017f047e087f057e017f23004180026b22022400200241c0006a2001109f01024002402002290340a7450d00200041003602200c010b200241c0006a41106a290300210320022903482104200241286a2001109f0102402002290328a7450d00200041003602200c010b200241286a41106a290300210520022903302106200241206a2001106c0240024002400240024020022802200d00200128020441306e220741306c2208417f4c0d02200228022421090240024020080d004108210a0c010b20081028220a450d040b02402009450d004100210b0340200241003a00f801200b220c41016a210b2001280204417f6a21084100210d024002400240024003402008417f460d01200241d8016a200d6a2001280200220e2d00003a0000200120083602042001200e41016a3602002002200d41016a220e3a00f8012008417f6a2108200e210d200e4120470d000b200241b8016a41186a2208200241d8016a41186a290300370300200241b8016a41106a220d200241d8016a41106a290300370300200241b8016a41086a220e200241d8016a41086a290300370300200220022903d8013703b801200241086a2001109f012002290308a70d01200241086a41106a290300210f20022903102110200241f8006a41086a200e2903002211370300200241f8006a41106a200d2903002212370300200241f8006a41186a20082903002213370300200241d8006a41086a220d2011370300200241d8006a41106a220e2012370300200241d8006a41186a22142013370300200220022903b8012211370378200220113703582007200c470d030240200c4101742208200b2008200b4b1b2207ad42307e2211422088a70d002011a7220841004e0d030b1031000b200d41ff0171450d00200241003a00f8010b200241f8006a41086a20024198016a41086a2903003703002007450d04200a102a0c040b02400240200c0d0020081028210a0c010b200a200c41306c2008102c210a0b200a450d070b200a200c41306c6a2208200f3703082008201037030020082002290358370310200841186a200d290300370300200841206a200e290300370300200841286a2014290300370300200b2009470d000b0b200a0d010b200041003602200c040b20002004370300200020073602242000200a3602202000200637031020002003370308200041286a2009360200200041186a20053703000c030b1036000b200841081037000b200841081037000b20024180026a24000b0a0041f0b8c0001032000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccd1c5003602002000410436021c200041c4d1c5003602182000200041186a360210200041ccb9c000103e000b8d0301027f230041e0006b22032400200341003a0005024002402000413f4b0d0041012104200341013a0005200320004102743a00000c010b02400240200041808001490d0020004180808080044f0d0141042104200341043a0005200320004102744102723602000c020b41022104200341023a0005200320004102744101723b01000c010b41052104200341053a0005200341033a0000200320003600010b024002402001280200220028020822012002490d0020002802002100200320023602082003200436020c20042002470d01200020032002109a051a200341e0006a24000f0b20022001103c000b200341286a41146a4108360200200341346a4125360200200341106a41146a410336020020034203370214200341c8afc6003602102003412536022c2003200341086a36024020032003410c6a360244200342043703582003420137024c2003419cb0c6003602482003200341286a3602202003200341c8006a3602382003200341c4006a3602302003200341c0006a360228200341106a41d8b0c600103e000bb60201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001103f21000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000b130020004102360204200041cc9dc6003602000b130020004101360204200041b8a8c3003602000b130020004103360204200041a8dcc0003602000b130020004103360204200041bcaac4003602000b130020004101360204200041d899c6003602000b13002000410b3602042000418082c5003602000b13002000410636020420004198e8c2003602000b130020004104360204200041d09ec1003602000b130020004105360204200041f8aec3003602000b130020004103360204200041ec91c6003602000b130020004105360204200041ac81c2003602000b130020004106360204200041f8d1c3003602000b130020004103360204200041a896c4003602000b13002000410136020420004190e0c0003602000b130020004101360204200041f896c6003602000b8b0701077f23004190026b2202240041002103200241003a002820012802042104417f210502400240034020042003460d01200241086a20036a200128020022062d00003a00002001200420056a3602042001200641016a3602002002200341016a22073a00282005417f6a21052007210320074120470d000b200241e8006a41086a200241086a41086a290300370300200241e8006a41106a200241086a41106a290300370300200241e8006a41186a200241086a41186a2903003703002002200229030837036841002103200241003a0028200420076b2108200420056a21050340024020082003470d000240200341ff0171450d00200241003a00280b200041013a00000c030b200241086a20036a200620036a220741016a2d00003a0000200120053602042001200741026a3602002002200341016a22073a00282005417f6a21052007210320074120470d000b20024188016a41086a200241086a41086a29030037030020024188016a41106a200241086a41106a29030037030020024188016a41186a200241086a41186a290300370300200220022903083703880141002103200241003a008802200620076a2106034002402005417f470d000240200341ff0171450d00200241003a0088020b200041013a00000c030b200241e8016a20036a200620036a220741016a2d00003a0000200120053602042001200741026a3602002002200341016a22073a0088022005417f6a21052007210320074120470d000b200241a8016a41086a2201200241e8016a41086a290300370300200241a8016a41106a2203200241e8016a41106a290300370300200241a8016a41186a2205200241e8016a41186a290300370300200241086a41086a200241e8006a41086a290300370300200241086a41106a200241e8006a41106a290300370300200241086a41186a200241e8006a41186a290300370300200220022903e8013703a80120022002290368370308200241c0006a20024188016a41186a290300370300200241386a20024188016a41106a290300370300200241306a20024188016a41086a2903003703002002200229038801370328200241e0006a2005290300370300200241d8006a2003290300370300200241d0006a2001290300370300200220022903a801370348200041016a200241086a41e000109a051a200041003a00000c010b0240200341ff0171450d00200241003a00280b200041013a00000b20024190026a24000bf90802067f047e230041d0026b220224000240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541034b0d0620050e0401020304010b200041053a00000c090b200241206a2001106d20022802200d03200041053a00000c080b200241c0006a20011081010240024020022802404113460d00200241c8016a200241c0006a418801109a051a418801102822050d0141880141081037000b200041053a00000c080b2005200241c8016a418801109a052105200041023a0000200020022f00103b0001200041036a200241106a41026a2d00003a0000200041046a2005360200200041086a2002290220370200200041106a200241206a41086a290200370200200041186a200241206a41106a290200370200200041206a200241206a41186a2902003702000c070b20022001106c20022802000d0520022802042105200241c0006a200110810120022802404113460d05200241c8016a200241c0006a418801109a051a41880110282201450d032001200241c8016a418801109a052101200041033a0000200020022f00103b0001200041036a200241126a2d00003a0000200041086a2001360200200041046a20053602002000410c6a2002290220370200200041146a200241206a41086a2902003702002000411c6a200241306a290200370200200041246a200241386a2802003602000c060b41002105200241003a00e8012003417f6a21062003417e6a21030340024020062005470d00200541ff0171450d05200241003a00e8010c050b200241c8016a20056a200420056a220741016a2d00003a0000200120033602042001200741026a3602002002200541016a22073a00e8012003417f6a21032007210520074120470d000b200241c0006a41186a200241c8016a41186a290300370300200241c0006a41106a200241c8016a41106a290300370300200241c0006a41086a200241c8016a41086a290300370300200220022903c801370340200241086a2001106c20022802080d0320012802042205450d03200228020c2103200128020022072d0000210420012005417f6a3602042001200741016a360200200241206a41086a200241c0006a41086a2903002208370300200241206a41106a200241c0006a41106a2903002209370300200241206a41186a200241c0006a41186a290300220a37030020022002290340220b370320200041043a00002000200b370001200041096a2008370000200041116a2009370000200041196a200a370000200041246a2003360200200041216a20043a00000c050b200241cb006a200241206a41086a28020036000020022002290320370043200041013a000020002002290040370001200041086a200241c7006a290000370000200041106a20022902c801370200200041186a200241c8016a41086a290200370200200041206a200241c8016a41106a2902003702000c040b200041053a00000c030b41880141081037000b200041053a00000c010b200041053a00000b200241d0026a24000bd50603057f0b7e057f230041106b21020240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a36020020064108490d00200429000421072001200341746a220636020420012004410c6a36020020064108490d00200429000c210820012003416c6a22063602042001200441146a36020020064108490d00200429001421092001200341646a220636020420012004411c6a36020020064108490d00200429001c210a20012003415c6a22063602042001200441246a36020020064108490d002004290024210b2001200341546a220636020420012004412c6a36020020064108490d00200429002c210c20012003414c6a22063602042001200441346a36020020064108490d002004290034210d2001200341446a220636020420012004413c6a36020020064108490d00200429003c210e2001200341bc7f6a22063602042001200441c4006a36020020064108490d002004290044210f2001200341b47f6a22063602042001200441cc006a36020020064108490d00200429004c21102001200341ac7f6a22063602042001200441d4006a36020020064108490d00200429005421112001200341a47f6a22063602042001200441dc006a36020020064104490d00200428005c21122001200341a07f6a22063602042001200441e0006a36020020064104490d002004280060211320012003419c7f6a22063602042001200441e4006a36020020064104490d00200428006421142001200341987f6a22063602042001200441e8006a36020020064104490d00200428006821152001200341947f6a22063602042001200441ec006a22043602002006450d0020042d000021162001200341937f6a22063602042001200441016a36020020064104490d00200020163a00702000201536026820002014360264200020133602602000201236025c2000200536025820002011370350200020103703482000200f3703402000200e3703382000200d3703302000200c3703282000200b3703202000200a3703182000200937031020002008370308200020073703002004280001210620012003418f7f6a3602042001200441056a3602002000200636026c200041f4006a2002410c6a280000360000200020022800093600710f0b200041023a00700bfb910205057f017e067f017e017f230041206b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000280200220341144b0d00024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e15000102030405060708090a0b0c0d0e0f1011121314000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d62200341017422052004200520044b1b22054100480d620240024020030d002005102821040c010b200128020020032005102c21040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000280208417f6a220341054b0d1502400240024002400240024020030e06000102030405000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d67200341017422042000200420004b1b22044100480d670240024020030d002004102821000c010b200128020020032004102c21000b2000450d1d20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c1a0b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d66200341017422052004200520044b1b22054100480d660240024020030d002005102821040c010b200128020020032005102c21040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200028020c2106200041146a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d66200441017422002005200020054b1b22004100480d660240024020040d002000102821040c010b200128020020042000102c21040b2004450d1e20012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c190b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d65200341017422052004200520044b1b22054100480d650240024020030d002005102821040c010b200128020020032005102c21040b2004450d1e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000290310210702400240200141046a2802002200200528020022036b4108490d00200128020021000c010b200341086a22042003490d65200041017422032004200320044b1b22034100480d650240024020000d002003102821000c010b200128020020002003102c21000b2000450d1f20012000360200200141046a2003360200200141086a28020021030b200141086a200341086a360200200020036a20073700000c180b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d64200341017422052004200520044b1b22054100480d640240024020030d002005102821040c010b200128020020032005102c21040b2004450d1f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c2106200041146a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d64200441017422002005200020054b1b22004100480d640240024020040d002000102821040c010b200128020020042000102c21040b2004450d2020012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c170b200141086a2802002103200241043a0018024002402003200141046a280200460d00200128020021050c010b200341016a22042003490d63200341017422052004200520044b1b22044100480d630240024020030d002004102821050c010b200128020020032004102c21050b2005450d2020012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41043a0000200028020c2103200041146a2802002200200110b4012000450d162003200041186c6a2108200141046a2106034020032802002109200341086a2802002200200110b401024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d64200a4101742205200b2005200b4b1b22054100480d6402400240200a0d0020051028210a0c010b2001280200200a2005102c210a0b200a450d222001200a36020020062005360200200428020021050b2004200520006a360200200a20056a20092000109a051a2003410c6a2802002109200341146a2802002200200110b401024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d64200a4101742205200b2005200b4b1b22054100480d6402400240200a0d0020051028210a0c010b2001280200200a2005102c210a0b200a450d232001200a36020020062005360200200428020021050b2004200520006a360200200a20056a20092000109a051a200341186a22032008470d000c170b0b200241053a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d62200341017422052004200520044b1b22054100480d620240024020030d002005102821040c010b200128020020032005102c21040b2004450d2220012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41053a0000200028020c2104200041146a2802002203200110b4012003450d1520042003410c6c6a2108200141046a210903402004280200210a200441086a2802002203200110b4010240024020092802002205200628020022006b2003490d00200128020021050c010b200020036a220b2000490d6320054101742200200b2000200b4b1b22004100480d630240024020050d002000102821050c010b200128020020052000102c21050b2005450d242001200536020020092000360200200628020021000b2006200020036a360200200520006a200a2003109a051a2004410c6a22042008470d000c160b0b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d61200341017422042000200420004b1b22044100480d610240024020030d002004102821000c010b200128020020032004102c21000b2000450d2320012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000c130b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d2320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d2420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a200110a1010c130b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5f200341017422052004200520044b1b22054100480d5f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5f200341017422052004200520044b1b22054100480d5f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2520012004360200200141046a2005360200200141086a28020021030b200141086a220a200341016a360200200420036a41003a00002000280204210c2000410c6a2802002203200110b4012003450d12200c200341f0006c6a210d200141046a210b034020022001360208200c41106a200241086a10c801200c200110a00120022001360208200c41306a200241086a10c80120022001360208200c41d0006a200241086a10c801200c2802042104200c28020c2203200110b40102402003450d00200341246c21090340200241086a200410ec012002280208210602400240200b2802002205200a28020022036b20022802102200490d00200128020021050c010b200320006a22082003490d62200541017422032008200320084b1b22034100480d620240024020050d002003102821050c010b200128020020052003102c21050b2005450d2920012005360200200b2003360200200a28020021030b200a200320006a360200200520036a20062000109a051a0240200228020c450d002006102a0b200441246a21042009415c6a22090d000b0b200c41f0006a220c200d470d000c130b0b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d5e200341017422042000200420004b1b22044100480d5e0240024020030d002004102821000c010b200128020020032004102c21000b2000450d2620012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41043a00000c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5d200341017422052004200520044b1b22054100480d5d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000280208417f6a220341024b0d10024002400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d60200341017422052004200520044b1b22044100480d600240024020030d002004102821050c010b200128020020032004102c21050b2005450d2a20012005360200200141046a2004360200200141086a28020021030b200041306a2104200141086a200341016a360200200520036a41003a00002000410c6a200110a601200241146a21030c020b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d5f200341017422052004200520044b1b22044100480d5f0240024020030d002004102821050c010b200128020020032004102c21050b2005450d2a20012005360200200141046a2004360200200141086a28020021030b200041c0006a2104200141086a200341016a360200200520036a41013a00002000410c6a200110a6012002200041306a360218200241186a200110a3012002411c6a21030c010b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d5e200341017422052004200520044b1b22044100480d5e0240024020030d002004102821050c010b200128020020032004102c21050b2005450d2a20012005360200200141046a2004360200200141086a28020021030b200041d8006a2104200141086a200341016a360200200520036a41023a00002000410c6a200110a601200041306a200110a601200241086a21030b200320043602002003200110a3010c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a000020002d0008417f6a2203410c4b0d0f024002400240024002400240024002400240024002400240024020030e0d000102030405060708090a0b0c000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d68200341017422052004200520044b1b22054100480d680240024020030d002005102821040c010b200128020020032005102c21040b2004450d3620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000410c6a200110a6012002200041306a360208200241086a200110a30120002d0009220341024b0d1b02400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d6a200341017422042000200420004b1b22044100480d6a0240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c1d0b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d69200341017422042000200420004b1b22044100480d690240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000c1c0b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d68200341017422042000200420004b1b22044100480d680240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41023a00000c1b0b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d67200341017422052004200520044b1b22054100480d670240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002002200041106a360208200241086a200110a3010c1a0b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d66200341017422052004200520044b1b22054100480d660240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200041106a360208200241086a200110a3010c190b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d65200341017422042000200420004b1b22044100480d650240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41033a00000c180b200141086a2802002103200241043a0018024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d64200341017422052004200520044b1b22054100480d640240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002002200041106a360208200241086a200110a3010c170b200241053a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d63200341017422052004200520044b1b22054100480d630240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200028020c2103200041146a2802002200200110b4012000450d16200041246c210003402003200110a601200341246a21032000415c6a22000d000c170b0b200241063a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d62200341017422042000200420004b1b22044100480d620240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41063a00000c150b200241073a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d61200341017422052004200520044b1b22054100480d610240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a000020002d0009220341024b0d1402400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d63200341017422042000200420004b1b22044100480d630240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c160b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d62200341017422042000200420004b1b22044100480d620240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000c150b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d61200341017422042000200420004b1b22044100480d610240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41023a00000c140b200141046a2802002104200241083a0018024002402004200141086a2802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a00002000410c6a200110a6010c130b200241093a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5f200341017422052004200520044b1b22054100480d5f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a200110a0010c120b2002410a3a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d5e200341017422042000200420004b1b22044100480d5e0240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a410a3a00000c110b2002410b3a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d5d200341017422042000200420004b1b22044100480d5d0240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a410b3a00000c100b2002410c3a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a0000200028020c2103200041146a2802002200200110b4012000450d0f20004105742100034020032001108f01200341206a2103200041606a22000d000c100b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41073a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d3d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041106a2001108f01200041306a2001108f01200041d0006a2001108f01200028020421062000410c6a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d5b200441017422002005200020054b1b22004100480d5b0240024020040d002000102821040c010b200128020020042000102c21040b2004450d3e20012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c0e0b02400240200141046a2206280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d5a2003410174220a2005200a20054b1b220a4100480d5a0240024020030d00200a102821050c010b20012802002003200a102c21050b2005450d3e20012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41083a0000200041086a22052d0000417f6a220341104b0d0d0240024002400240024002400240024002400240024002400240024002400240024020030e11000102030405060708090a0b0c0d0e0f10000b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d6a200341017422052004200520044b1b22054100480d6a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d4f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020c200110eb012002200041106a360208200241086a200110a3010c1d0b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d69200341017422052004200520044b1b22054100480d690240024020030d002005102821040c010b200128020020032005102c21040b2004450d4f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110a0010c1c0b02400240200628020020042802002203460d00200128020021060c010b200341016a22062003490d682003410174220a2006200a20064b1b220a4100480d680240024020030d00200a102821060c010b20012802002003200a102c21060b2006450d4f20012006360200200141046a200a360200200141086a28020021030b200141086a220a200341016a360200200620036a41023a00002000410c6a200110a00120052d00012106200541026a2d0000210502400240200141046a280200200a2802002203460d00200128020021000c010b200341016a22002003490d682003410174220a2000200a20004b1b220a4100480d680240024020030d00200a102821000c010b20012802002003200a102c21000b2000450d5020012000360200200141046a200a360200200141086a28020021030b2004200341016a360200200020036a20064100474107742005723a00000c1b0b02400240200628020020042802002203460d00200128020021060c010b200341016a22062003490d672003410174220a2006200a20064b1b220a4100480d670240024020030d00200a102821060c010b20012802002003200a102c21060b2006450d5020012006360200200141046a200a360200200141086a28020021030b200141086a220a200341016a360200200620036a41033a00002000410c6a200110a00120052d00012106200541026a2d0000210502400240200141046a280200200a2802002203460d00200128020021000c010b200341016a22002003490d672003410174220a2000200a20004b1b220a4100480d670240024020030d00200a102821000c010b20012802002003200a102c21000b2000450d5120012000360200200141046a200a360200200141086a28020021030b2004200341016a360200200020036a20064100474107742005723a00000c1a0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d662003410174220a2005200a20054b1b220a4100480d660240024020030d00200a102821050c010b20012802002003200a102c21050b2005450d5120012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41043a0000200028020c21050240024020062802002200200428020022036b4104490d00200128020021000c010b200341046a22062003490d66200041017422032006200320064b1b22034100480d660240024020000d002003102821000c010b200128020020002003102c21000b2000450d5220012000360200200141046a2003360200200141086a28020021030b2004200341046a360200200020036a20053600000c190b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d65200341017422052004200520044b1b22054100480d650240024020030d002005102821040c010b200128020020032005102c21040b2004450d5220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200028020c200110eb010c180b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d64200341017422052004200520044b1b22054100480d640240024020030d002005102821040c010b200128020020032005102c21040b2004450d5220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a0000200028020c200110eb010c170b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d63200341017422052004200520044b1b22054100480d630240024020030d002005102821040c010b200128020020032005102c21040b2004450d5220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200028020c200110eb010c160b02400240200628020020042802002203460d002001280200210a0c010b200341016a220a2003490d6220034101742209200a2009200a4b1b22094100480d620240024020030d0020091028210a0c010b200128020020032009102c210a0b200a450d522001200a360200200141046a2009360200200141086a28020021030b200141086a2209200341016a360200200a20036a41083a000020022001360208200541016a200241086a10c801200028022c210a02400240200141046a2802002205200928020022036b4104490d00200128020021050c010b200341046a22092003490d62200541017422032009200320094b1b22034100480d620240024020050d002003102821050c010b200128020020052003102c21050b2005450d5320012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200a360000200028023021050240024020062802002200200428020022036b4104490d00200128020021000c010b200341046a22062003490d62200041017422032006200320064b1b22034100480d620240024020000d002003102821000c010b200128020020002003102c21000b2000450d5420012000360200200141046a2003360200200141086a28020021030b2004200341046a360200200020036a20053600000c150b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d61200341017422042000200420004b1b22044100480d610240024020030d002004102821000c010b200128020020032004102c21000b2000450d5420012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41093a000020022001360208200541016a200241086a10c8010c140b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d5420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a00002000410c6a200110a0010c130b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5f200341017422052004200520044b1b22054100480d5f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d5420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a00002000410c6a200110a001200041106a200110a001200041146a200110a0010c120b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5e200341017422042000200420004b1b22044100480d5e0240024020030d002004102821000c010b200128020020032004102c21000b2000450d5420012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a410c3a0000200541016a2001108f010c110b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5d200341017422052000200520004b1b22054100480d5d0240024020030d002005102821000c010b200128020020032005102c21000b2000450d5420012000360200200141046a2005360200200141086a28020021030b2004200341016a360200200020036a410d3a00000c100b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5c200341017422042000200420004b1b22044100480d5c0240024020030d002004102821000c010b200128020020032004102c21000b2000450d5420012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a410e3a0000200541016a2001108f010c0f0b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5b2003410174220a2000200a20004b1b220a4100480d5b0240024020030d00200a102821000c010b20012802002003200a102c21000b2000450d5420012000360200200141046a200a360200200141086a28020021030b200141086a200341016a360200200020036a410f3a0000200541016a2001108f0120052d0021220341064b0d0e0240024002400240024002400240024020030e0700010203040506000b410021000c060b410121000c050b410221000c040b410321000c030b410421000c020b410521000c010b410621000b200220003a001802400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5b200341017422062005200620054b1b22064100480d5b0240024020030d002006102821050c010b200128020020032006102c21050b2005450d5520012005360200200141046a2006360200200141086a28020021030b2004200341016a360200200520036a20003a00000c0e0b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5a200341017422052000200520004b1b22054100480d5a0240024020030d002005102821000c010b200128020020032005102c21000b2000450d5520012000360200200141046a2005360200200141086a28020021030b2004200341016a360200200020036a41103a00000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d59200341017422052004200520044b1b22054100480d590240024020030d002005102821040c010b200128020020032005102c21040b2004450d5520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a0000200041046a200110ed010c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d58200341017422052004200520044b1b22054100480d580240024020030d002005102821040c010b200128020020032005102c21040b2004450d5520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a0000200041046a200110ed010c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d57200341017422052004200520044b1b22054100480d570240024020030d002005102821040c010b200128020020032005102c21040b2004450d5520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a00002000280208417f6a220341094b0d0a024002400240024002400240024002400240024020030e0a00010203040506070809000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d5f20012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41003a0000200028020c2104200041146a280200220a200110b4010240200a450d00200141046a2109034002400240200928020020062802002203460d00200128020021050c010b200341016a22052003490dad012003410174220b2005200b20054b1b220b4100480dad010240024020030d00200b102821050c010b20012802002003200b102c21050b2005450d63200120053602002009200b360200200628020021030b2006200341016a360200200520036a20042d00003a0000200441016a2104200a417f6a220a0d000b0b200041186a200110a001200028021c210502400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22062003490dab01200441017422032006200320064b1b22034100480dab010240024020040d002003102821040c010b200128020020042003102c21040b2004450d6220012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041286a29030021072000290320210e02400240200141046a2802002200200628020022036b4110490d00200128020021000c010b200341106a22042003490dab01200041017422032004200320044b1b22034100480dab010240024020000d002003102821000c010b200128020020002003102c21000b2000450d6320012000360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200020036a220320073700082003200e3700000c130b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490daa01200341017422052004200520044b1b22054100480daa010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6320012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41013a0000200028020c2104200041146a280200220a200110b4010240200a450d00200141046a2109034002400240200928020020062802002203460d00200128020021050c010b200341016a22052003490dac012003410174220b2005200b20054b1b220b4100480dac010240024020030d00200b102821050c010b20012802002003200b102c21050b2005450d66200120053602002009200b360200200628020021030b2006200341016a360200200520036a20042d00003a0000200441016a2104200a417f6a220a0d000b0b200041186a200110a001200028021c210502400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22062003490daa01200441017422032006200320064b1b22034100480daa010240024020040d002003102821040c010b200128020020042003102c21040b2004450d6520012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041286a29030021072000290320210e02400240200141046a2802002200200628020022036b4110490d00200128020021000c010b200341106a22042003490daa01200041017422032004200320044b1b22034100480daa010240024020000d002003102821000c010b200128020020002003102c21000b2000450d6620012000360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200020036a220320073700082003200e3700000c120b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da901200341017422052004200520044b1b22054100480da9010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a200110a001200041106a200110a601200041346a200110a001200041386a200110a0010c110b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da801200341017422052004200520044b1b22054100480da8010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002000410c6a200110a0010c100b200141086a2802002103200241043a0018024002402003200141046a280200460d00200128020021040c010b200341016a22042003490da701200341017422052004200520044b1b22054100480da7010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a200110a0010c0f0b200241053a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da601200341017422052004200520044b1b22054100480da6010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000410c6a200110a6012002200041386a360208200241086a200110a301200041306a200110a0010c0e0b200241063a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da501200341017422052004200520044b1b22054100480da5010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a00002000410c6a200110a0010c0d0b200241073a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da401200341017422052004200520044b1b22054100480da4010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a00002000410c6a200110a6010c0c0b200141046a2802002104200241083a0018024002402004200141086a2802002203460d00200128020021040c010b200341016a22042003490da301200341017422052004200520044b1b22054100480da3010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a00002000410c6a200110a0010c0b0b200241093a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da201200341017422052004200520044b1b22054100480da2010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a200110a0010c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da101200341017422052004200520044b1b22054100480da1010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a0000200041046a22042d0000417f6a220341034b0d09024002400240024020030e0400010203000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490da401200341017422052000200520004b1b22054100480da4010240024020030d002005102821000c010b200128020020032005102c21000b2000450d6a20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a41003a0000200441016a2001108f010c0c0b200141086a2802002103200141046a2802002100200241013a00180240024020002003460d00200128020021000c010b200341016a22002003490da301200341017422052000200520004b1b22054100480da3010240024020030d002005102821000c010b200128020020032005102c21000b2000450d6a20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a41013a0000200441016a2001108f010c0b0b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490da201200341017422052000200520004b1b22054100480da2010240024020030d002005102821000c010b200128020020032005102c21000b2000450d6a20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a41023a0000200441016a2001108f01200441216a2001108f010c0a0b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da101200341017422052004200520044b1b22054100480da1010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002802082103200041106a2802002200200110b4012000450d0920004105742100034020032001108f01200341206a2103200041606a22000d000c0a0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da001200341017422052004200520044b1b22054100480da0010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410d3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490da001200341017422052004200520044b1b22054100480da0010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041046a200110a0010c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9f01200341017422052004200520044b1b22054100480d9f010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410e3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d9f01200341017422052004200520044b1b22054100480d9f010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020421062000410c6a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d9f01200441017422002005200020054b1b22004100480d9f010240024020040d002000102821040c010b200128020020042000102c21040b2004450d6d20012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9e01200341017422052004200520044b1b22054100480d9e010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410f3a00002000280208417f6a220341024b0d0602400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da001200341017422052004200520044b1b22054100480da0010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002002200041306a360208200241086a200110a3012000410c6a200110a6010c080b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9f01200341017422052004200520044b1b22054100480d9f010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110a0010c070b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9e01200341017422052004200520044b1b22054100480d9e010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a200110a0010c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9d01200341017422052004200520044b1b22054100480d9d010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41103a0000200041086a22042d0000417f6a220341044b0d050240024002400240024020030e050001020304000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da101200341017422052004200520044b1b22054100480da1010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041106a200110ee010c090b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da001200341017422052004200520044b1b22054100480da0010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a200110a101200028020c2106200041146a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490da001200441017422002005200020054b1b22004100480da0010240024020040d002000102821040c010b200128020020042000102c21040b2004450d7620012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c080b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9f01200341017422052004200520044b1b22054100480d9f010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000410c6a200110a6012002200041c0006a360208200241086a200110a301200041d0006a200110a10120002802302106200041386a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d9f01200441017422002005200020054b1b22004100480d9f010240024020040d002000102821040c010b200128020020042000102c21040b2004450d7720012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c070b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22052003490d9e01200341017422062005200620054b1b22064100480d9e010240024020030d002006102821050c010b200128020020032006102c21050b2005450d7720012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a41033a00002002200041386a360208200241086a200110a301200041c8006a200110a10120022001360208200441016a200241086a10c801200028022c2105200041346a2802002203200110b40102400240200141046a2802002204200628020022006b2003490d00200128020021040c010b200020036a22062000490d9e01200441017422002006200020064b1b22004100480d9e010240024020040d002000102821040c010b200128020020042000102c21040b2004450d7820012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20052003109a051a0c060b200141086a2802002103200241043a0018024002402003200141046a280200460d00200128020021000c010b200341016a22002003490d9d01200341017422052000200520004b1b22054100480d9d010240024020030d002005102821000c010b200128020020032005102c21000b2000450d7820012000360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200020036a41043a0000200441016a2001108f01024020042d00214101460d00200241003a001802400240200141046a28020020052802002203460d00200128020021000c010b200341016a22002003490d9e01200341017422042000200420004b1b22044100480d9e010240024020030d002004102821000c010b200128020020032004102c21000b2000450d7a20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c060b200241013a001802400240200141046a28020020052802002203460d00200128020021000c010b200341016a22002003490d9d01200341017422052000200520004b1b22054100480d9d010240024020030d002005102821000c010b200128020020032005102c21000b2000450d7a20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a41013a0000200441226a2001108f010c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9c01200341017422052004200520044b1b22054100480d9c010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41113a00002000280204417f6a220341024b0d0402400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9e01200341017422052004200520044b1b22054100480d9e010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000280208200110eb010c060b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9d01200341017422052004200520044b1b22054100480d9d010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041086a200110a6010c050b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9c01200341017422052004200520044b1b22054100480d9c010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041086a200110a601200028022c200110eb010c040b02400240200141046a220a280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d9b01200441017422062005200620054b1b22064100480d9b010240024020040d002006102821050c010b200128020020042006102c21050b2005450d7d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a41123a000002400240200a28020020032802002204460d00200128020021050c010b200441016a22052004490d9b01200441017422062005200620054b1b22064100480d9b010240024020040d002006102821050c010b200128020020042006102c21050b2005450d7e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a41003a00002000280204210602400240200a2802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d9b01200541017422042009200420094b1b22044100480d9b010240024020050d002004102821050c010b200128020020052004102c21050b2005450d7f20012005360200200141046a2004360200200141086a28020021040b200141086a2209200441046a360200200520046a2006360000200041086a280200210b200041106a2802002204200110b40102400240200141046a2802002206200928020022056b2004490d00200128020021060c010b200520046a22092005490d9b01200641017422052009200520094b1b22054100480d9b010240024020060d002005102821060c010b200128020020062005102c21060b2006450d800120012006360200200141046a2005360200200141086a28020021050b200141086a2208200520046a360200200620056a200b2004109a051a200041146a28020021062000411c6a2802002204200110b40102402004450d0020062004410c6c6a210f200141046a210c03402006280200210b200641086a2802002204200110b40102400240200c2802002209200828020022056b2004490d00200128020021090c010b200520046a220d2005490d9d0120094101742205200d2005200d4b1b22054100480d9d010240024020090d002005102821090c010b200128020020092005102c21090b2009450d830120012009360200200c2005360200200828020021050b2003200520046a360200200920056a200b2004109a051a2006410c6a2206200f470d000b0b200041206a280200210602400240200a2802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d9b01200541017422042009200420094b1b22044100480d9b010240024020050d002004102821050c010b200128020020052004102c21050b2005450d820120012005360200200141046a2004360200200141086a28020021040b2003200441046a360200200520046a2006360000200041246a280200210602400240200a2802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d9b01200541017422042009200420094b1b22044100480d9b010240024020050d002004102821050c010b200128020020052004102c21050b2005450d830120012005360200200141046a2004360200200141086a28020021040b2003200441046a360200200520046a200636000002400240200a28020020032802002204460d00200128020021050c010b200441016a22052004490d9b01200441017422062005200620054b1b22064100480d9b010240024020040d002006102821050c010b200128020020042006102c21050b2005450d840120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a200041286a22042d00003a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d850120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00013a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d860120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d002a3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d870120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00033a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d880120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d002c3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d890120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00053a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8a0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d002e3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8b0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00073a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8c0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00303a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8d0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00093a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8e0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00323a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8f0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d000b3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d900120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00343a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d910120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d000d3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d920120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00363a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d930120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d000f3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d940120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00383a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d950120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00113a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d960120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d003a3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d970120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00133a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d980120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d003c3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d990120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00153a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9a0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d003e3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9c0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00173a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9d0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00403a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9e0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00193a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9f0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00423a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da00120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d001b3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da10120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00443a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da20120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d001d3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da30120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00463a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da40120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d001f3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da50120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00483a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da60120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00213a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da70120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d004a3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da80120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00233a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da90120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d004c3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450daa0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00253a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dab0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d004e3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dac0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00273a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dad0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00503a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dae0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00293a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450daf0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00523a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db00120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d002b3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db10120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00543a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db20120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d002d3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db30120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00563a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db40120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d002f3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db50120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00583a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db60120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00313a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db70120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d005a3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db80120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00333a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db90120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d005c3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dba0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00353a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbb0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d005e3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbc0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00373a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbd0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00603a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbe0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00393a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbf0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00623a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dc00120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d003b3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dc10120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00643a000002400240200a28020020032802002200460d00200128020021050c010b200041016a22052000490dc701200041017422062005200620054b1b22064100480dc7010240024020000d002006102821050c010b200128020020002006102c21050b2005450dc20120012005360200200141046a2006360200200141086a28020021000b2003200041016a360200200520006a20042d003d3a000002400240200a28020020032802002200460d00200128020021050c010b200041016a22052000490dc701200041017422062005200620054b1b22064100480dc7010240024020000d002006102821050c010b200128020020002006102c21050b2005450dc30120012005360200200141046a2006360200200141086a28020021000b2003200041016a360200200520006a20042d003e3a000002400240200a28020020032802002200460d00200128020021050c010b200041016a22052000490dc701200041017422062005200620054b1b22064100480dc7010240024020000d002006102821050c010b200128020020002006102c21050b2005450dc40120012005360200200141046a2006360200200141086a28020021000b2003200041016a360200200520006a20042d003f3a00000c030b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490dc601200341017422042000200420004b1b22044100480dc6010240024020030d002004102821000c010b200128020020032004102c21000b2000450dc40120012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41133a00000c010b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490dc501200341017422042000200420004b1b22044100480dc5010240024020030d002004102821000c010b200128020020032004102c21000b2000450dc40120012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41143a00000b200110c4010b200241206a24000f0b200541011037000b200441011037000b200541011037000b200041011037000b200541011037000b200341011037000b200541011037000b200041011037000b200441011037000b200541011037000b200541011037000b200541011037000b200041011037000b200441011037000b200541011037000b200541011037000b200541011037000b200541011037000b200341011037000b200441011037000b200541011037000b200441011037000b200441011037000b200441011037000b200541011037000b200541011037000b200441011037000b200441011037000b200441011037000b200541011037000b200541011037000b200441011037000b200541011037000b200541011037000b200441011037000b200541011037000b200441011037000b200441011037000b200441011037000b200541011037000b200541011037000b200441011037000b200441011037000b200541011037000b200541011037000b200541011037000b200041011037000b200a41011037000b200541011037000b200541011037000b200a41011037000b200a41011037000b200a41011037000b200a41011037000b200a41011037000b200341011037000b200541011037000b200541011037000b200541011037000b200941011037000b200341011037000b200341011037000b200441011037000b200541011037000b200541011037000b200441011037000b200541011037000b200441011037000b200a41011037000b200641011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b1031000b200b41011037000b200341011037000b200341011037000b200541011037000b200b41011037000b200341011037000b200341011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200041011037000b200641011037000b200041011037000b200541011037000b200441011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200641011037000b200641011037000b200441011037000b200541011037000b200541011037000b200441011037000b200441011037000b200641011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b1031000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200641011037000b200641011037000b200641011037000b200441011037000b200441011037000b1031000bb31601067f230041106b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e050003010204000b2002410036020820024201370300410110282203450d05200242818080801037020420022003360200200341023a00002002200236020c200141016a2002410c6a10c8010c040b2002410036020820024201370300410110282203450d05200242818080801037020420022003360200200341043a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102821040c010b200228020020032005102c21040b2004450d0720022005360204200220043602000b2002200341016a360208200420036a20012d00013a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102821040c010b200228020020032005102c21040b2004450d0820022005360204200220043602000b2002200341016a360208200420036a20012d00023a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102821040c010b200228020020032005102c21040b2004450d0920022005360204200220043602000b2002200341016a360208200420036a20012d00033a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102821040c010b200228020020032005102c21040b2004450d0a20022005360204200220043602000b2002200341016a360208200420036a20012d00043a000020012802082105200141106a2802002201200210b4010240024020022802042204200228020822036b2001490d00200228020021040c010b200320016a22062003490d1a200441017422072006200720064b1b22064100480d1a0240024020040d002006102821040c010b200228020020042006102c21040b2004450d0b20022006360204200220043602000b2002200320016a360208200420036a20052001109a051a0c030b2002410036020820024201370300410110282203450d0a200242818080801037020420022003360200200341053a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102821040c010b200228020020032005102c21040b2004450d0c20022005360204200220043602000b2002200341016a360208200420036a20012d00013a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102821040c010b200228020020032005102c21040b2004450d0d20022005360204200220043602000b2002200341016a360208200420036a20012d00023a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102821040c010b200228020020032005102c21040b2004450d0e20022005360204200220043602000b2002200341016a360208200420036a20012d00033a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102821040c010b200228020020032005102c21040b2004450d0f20022005360204200220043602000b2002200341016a360208200420036a20012d00043a000020012802082105200141106a2802002201200210b4010240024020022802042204200228020822036b2001490d00200228020021040c010b200320016a22062003490d19200441017422072006200720064b1b22064100480d190240024020040d002006102821040c010b200228020020042006102c21040b2004450d1020022006360204200220043602000b2002200320016a360208200420036a20052001109a051a0c020b2002410036020820024201370300410110282203450d0f200242818080801037020420022003360200200341063a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102821040c010b200228020020032005102c21040b2004450d1120022005360204200220043602000b2002200341016a360208200420036a20012d00013a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102821040c010b200228020020032005102c21040b2004450d1220022005360204200220043602000b2002200341016a360208200420036a20012d00023a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102821040c010b200228020020032005102c21040b2004450d1320022005360204200220043602000b2002200341016a360208200420036a20012d00033a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102821040c010b200228020020032005102c21040b2004450d1420022005360204200220043602000b2002200341016a360208200420036a20012d00043a000020012802082105200141106a2802002201200210b4010240024020022802042204200228020822036b2001490d00200228020021040c010b200320016a22062003490d18200441017422072006200720064b1b22064100480d180240024020040d002006102821040c010b200228020020042006102c21040b2004450d1520022006360204200220043602000b2002200320016a360208200420036a20052001109a051a0c010b2002410036020820024201370300410110282203450d14200242818080801037020420022003360200200341003a0000200141046a28020021052001410c6a2802002201200210b4010240024020022802042204200228020822036b2001490d00200228020021040c010b200320016a22062003490d17200441017422072006200720064b1b22064100480d170240024020040d002006102821040c010b200228020020042006102c21040b2004450d1620022006360204200220043602000b2002200320016a360208200420036a20052001109a051a0b200020022201290200370200200041086a200141086a280200360200200241106a24000f0b410141011037000b410141011037000b200541011037000b200541011037000b200541011037000b200541011037000b200641011037000b410141011037000b200541011037000b200541011037000b200541011037000b200541011037000b200641011037000b410141011037000b200541011037000b200541011037000b200541011037000b200541011037000b200641011037000b410141011037000b200641011037000b1031000b800801047f230041106b22022400024002400240024002400240024020002d0000417f6a220341034b0d00024002400240024020030e0400010203000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020421032000410c6a2802002200200110b4012000450d0320004105742100034020032001108f01200341206a2103200041606a22000d000c040b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102821040c010b200128020020032005102c21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000280204200110eb010c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102821040c010b200128020020032005102c21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041046a200110a0012000280208200110eb010c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102821040c010b200128020020032005102c21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a00002002200136020c200041016a2002410c6a10c801200041246a200110a00102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102821040c010b200128020020032005102c21040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00213a00000b200241106a24000f0b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b1031000bf71802047f017e20002802582102024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141046a2802002203200141086a28020022046b4104490d00200128020021030c010b200441046a22052004490d13200341017422042005200420054b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200320046a20023600002000290300210602400240200141046a2802002203200528020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290308210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0320012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290310210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0420012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290318210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290320210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0620012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290328210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0720012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290330210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0820012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290338210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0920012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290340210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0a20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290348210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0b20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290350210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0c20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a2006370000200028025c210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0d20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280260210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0e20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280264210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0f20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280268210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d1020012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a200536000002400240200141046a28020020022802002204460d00200128020021030c010b200441016a22032004490d13200441017422022003200220034b1b22024100480d130240024020040d002002102821030c010b200128020020042002102c21030b2003450d1120012003360200200141046a2002360200200141086a28020021040b200141086a2202200441016a360200200320046a20002d00703a0000200028026c210302400240200141046a2802002204200228020022006b4104490d00200128020021040c010b200041046a22022000490d13200441017422002002200020024b1b22004100480d130240024020040d002000102821040c010b200128020020042000102c21040b2004450d1220012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a20033600000f0b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200241011037000b200041011037000b1031000bb90201057f230041106b2203240020034100360208200342013703002001200310b4010240024002402001450d00200141b0016c2104034020004188016a28020021050240024020032802042206200328020822016b4104490d00200328020021060c010b200141046a22072001490d04200641017422012007200120074b1b22014100480d040240024020060d002001102821060c010b200328020020062001102c21060b2006450d032003200136020420032006360200200328020821010b2003200141046a360208200620016a20053600002000200310eb012000418c016a2003108f01200041b0016a2100200441d07e6a22040d000b0b2003280204210020022802002002280204200328020022012003280208100702402000450d002001102a0b200341106a24000f0b200141011037000b1031000bee1405177f017e017f027e047f230041206b220224000240024020014115490d0002402001410176220341ffffff3f712003470d0020034105742204417f4c0d0041012105024002402004450d00200410282205450d010b200041606a2106200041a07f6a210741002108410021094104210a4100210b2001210c034002400240200c220d417f6a220e0d004101210f4100210c0c010b0240024002400240024002402000200e4105746a200d410574221020006a41406a4120109c054100480d004102200d6b210e200720106a21044101210f03400240200e200f6a4101470d004100210c200d210f0c080b200f41016a210f200441206a20044120109c052111200441606a21042011417f4a0d000b200d200f6b210e0c010b200720106a2104024003400240200e4101470d004100210e0c020b200e417f6a210e200441206a20044120109c052111200441606a210420114100480d000b0b200d200e490d01200d20014b0d03200d200e6b220f4101762212450d00200620106a21042000200e4105746a21110340200241186a2210201141186a2213290000370300200241106a2214201141106a2215290000370300200241086a2216201141086a221729000037030020022011290000370300200441086a22182900002119200441106a221a290000211b200441186a220c290000211c201120042900003700002013201c3700002015201b37000020172019370000200c2010290300370000201a20142903003700002018201629030037000020042002290300370000200441606a2104201141206a21112012417f6a22120d000b0b0240200e0d00200e210c0c050b0240200f41094d0d00200e210c0c050b200d20014b0d01200d200e6b21122000200e4105746a21100340200d200e417f6a220c490d040240200d200c6b220f4102490d002000200e4105746a22042000200c4105746a220e4120109c05417f4a0d00200e2900002119200e2004290000370000200241186a2216200e41186a2211290000370300200241106a2217200e41106a2213290000370300200241086a2218200e41086a22142900003703002014200441086a2900003700002013200441106a2900003700002011200441186a29000037000020022019370300410121150240200f4103490d00200e41c0006a20024120109c05417f4a0d00410221112010210402400340200441186a200441386a290000370000200441106a200441306a290000370000200441086a200441286a2900003700002004200441206a221329000037000020122011460d01200441c0006a21142011211520132104201141016a2111201420024120109c05417f4a0d020c000b0b201121150b200e20154105746a22042002290300370000200441186a2016290300370000200441106a2017290300370000200441086a20182903003700000b200c450d05201041606a2110201241016a2112200c210e200f410a4f0d050c000b0b200e200d1044000b200d200e417f6a220c490d010b200d2001103c000b200c200d1044000b024002400240200b2009470d0002400240200941016a22042009490d00200941017422112004201120044b1b220441ffffffff01712004470d002004410374221141004e0d010b1031000b0240024020090d0020111028210a0c010b200a20094103742011102c210a0b200a450d01200421092008210b0b200a200b4103746a2204200f3602042004200c360200200841016a220b2108200b4102490d01024003400240024002400240200a200b417f6a22084103746a2204280200450d00200b410374200a6a220f41746a280200220e200428020422114d0d000240200b41024b0d00200b21084102210b0c080b200a200b417d6a22164103746a28020422042011200e6a4d0d010240200b41034b0d00200b21084103210b0c080b200f41646a2802002004200e6a4d0d01200b21080c070b200b4103490d0120042802042111200a200b417d6a22164103746a28020421040b20042011490d010b200b417e6a21160b024002400240024002400240200b201641016a221d4b221e450d00200b20164b221f450d01200a20164103746a2217280204222020172802006a2204200a201d4103746a2218280200221a490d02200420014b0d032000201a4105746a22142018280204221541057422116a210f2004410574210e2004201a6b220d20156b220420154f0d042005200f20044105742211109a05221320116a21120240024020154101480d00200441014e0d010b200f2104201321110c060b2006200e6a210e200f21040340200e200441606a220f201241606a220d200d200f4120109c0541004822101b2211290000370000200e41186a201141186a290000370000200e41106a201141106a290000370000200e41086a201141086a2900003700002012200d20101b211202402014200f200420101b2204490d00201321110c070b200e41606a210e2013211120132012490d000c060b0b41b8dbc000201d200b1034000b41b8dbc0002016200b1034000b201a20041044000b20042001103c000b200520142011109a05221320116a21120240024020154101480d00200d20154a0d010b20142104201321110c010b2000200e6a2110201321112014210403402004200f2011200f20114120109c05410048220d1b220e290000370000200441186a200e41186a290000370000200441106a200e41106a290000370000200441086a200e41086a2900003700002011201141206a200d1b2111200441206a2104200f41206a200f200d1b220f20104f0d01201220114b0d000b0b20042011201220116b416071109a051a0240201f450d002017201a360200201741046a202020156a360200201e450d022018201841086a200b201d417f736a410374109b051a2008210b200841014d0d040c010b0b41c8dbc0002016200b1034000b41b0b1c0001032000b201141041037000b200c0d000b02402009450d00200a102a0b2003450d032005102a0c030b200441011037000b1036000b20014102490d002001417f6a2111200141057420006a41206a2110410121120340024002400240024020112204417f6a221120014b0d00200120116b220e4102490d03200020044105746a2204200020114105746a220d4120109c05417f4a0d03200d2900002119200d2004290000370000200241186a2214200d41186a220f290000370300200241106a220b200d41106a2213290000370300200241086a2215200d41086a220a290000370300200a200441086a2900003700002013200441106a290000370000200f200441186a2900003700002002201937030041012104200e4103490d02200d41c0006a20024120109c05417f4a0d0241002113201021040340200441406a220e200441606a220f290000370000200e41186a200f41186a290000370000200e41106a200f41106a290000370000200e41086a200f41086a29000037000020122013220e460d02200e417f6a2113200420024120109c05210f200441206a2104200f417f4a0d020c000b0b201120011044000b4102200e6b21040b200d20044105746a22042002290300370000200441186a2014290300370000200441106a200b290300370000200441086a20152903003700000b201041606a21102012417f6a211220110d000b0b200241206a24000ba3950103057f027e027f230041106b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00000e10000102030405060708090a0b0c0d0e0f000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200141046a28020021042005280200210302402000410c6a2d000022054102470d000240024020042003460d00200128020021000c010b200341016a22002003490d5d200341017422042000200420004b1b22044100480d5d0240024020030d002004102821000c010b200128020020032004102c21000b2000450d1320012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c100b0240024020042003460d00200128020021040c010b200341016a22042003490d5c200341017422062004200620044b1b22064100480d5c0240024020030d002006102821040c010b200128020020032006102c21040b2004450d1320012004360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200420036a41013a00000240024020054101460d0002400240200141046a28020020062802002203460d00200128020021040c010b200341016a22042003490d5e200341017422052004200520044b1b22054100480d5e0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00000c010b02400240200141046a28020020062802002203460d00200128020021040c010b200341016a22042003490d5d200341017422052004200520044b1b22054100480d5d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5d200341017422052004200520044b1b22054100480d5d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d000d3a00000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d000e3a00000c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041086a2001108f012000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d5b200341017422002005200020054b1b22004100480d5b0240024020030d002000102821030c010b200128020020032000102c21030b2003450d1920012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5a200341017422052004200520044b1b22054100480d5a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a000020002d0008220341024b0d0d02400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041096a2001108f01200041386a29030021072000290330210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5c200341017422002004200020044b1b22004100480d5c0240024020030d002000102821030c010b200128020020032000102c21030b2003450d1d20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041096a2001108f010c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5a200341017422052004200520044b1b22054100480d5a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200041096a2001108f01200041296a2001108f01200041d8006a29030021072000290350210802400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d5a200441017422032005200320054b1b22034100480d5a0240024020040d002003102821040c010b200128020020042003102c21040b2004450d1e20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a2203200737000820032008370000200041e8006a29030021072000290360210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5a200341017422002004200020044b1b22004100480d5a0240024020030d002000102821030c010b200128020020032000102c21030b2003450d1f20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d59200341017422052004200520044b1b22054100480d590240024020030d002005102821040c010b200128020020032005102c21040b2004450d1f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002d0008220341024b0d0c02400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041186a29030021072000290310210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5b200341017422002004200020044b1b22004100480d5b0240024020030d002000102821030c010b200128020020032000102c21030b2003450d2320012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5a200341017422052004200520044b1b22054100480d5a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041096a2001108f01200041386a29030021072000290330210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5a200341017422002004200020044b1b22004100480d5a0240024020030d002000102821030c010b200128020020032000102c21030b2003450d2420012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d59200341017422052004200520044b1b22054100480d590240024020030d002005102821040c010b200128020020032005102c21040b2004450d2420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d59200341017422002005200020054b1b22004100480d590240024020030d002000102821030c010b200128020020032000102c21030b2003450d2520012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d58200341017422052004200520044b1b22054100480d580240024020030d002005102821040c010b200128020020032005102c21040b2004450d2520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d58200341017422052004200520044b1b22054100480d580240024020030d002005102821040c010b200128020020032005102c21040b2004450d2620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d58200341017422002005200020054b1b22004100480d580240024020030d002000102821030c010b200128020020032000102c21030b2003450d2720012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0b0b02400240200141046a2206280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d57200341017422092005200920054b1b22094100480d570240024020030d002009102821050c010b200128020020032009102c21050b2005450d2720012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41053a000020002d00082203410a4b0d0a0240024002400240024002400240024002400240024020030e0b000102030405060708090a000b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d61200341017422092005200920054b1b22094100480d610240024020030d002009102821050c010b200128020020032009102c21050b2005450d3220012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41003a0000200028020c21090240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d6120054101742203200a2003200a4b1b22034100480d610240024020050d002003102821050c010b200128020020052003102c21050b2005450d3320012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2009360000200041186a2903002107200029031021080240024020062802002203200428020022006b4110490d00200128020021030c010b200041106a22052000490d61200341017422002005200020054b1b22004100480d610240024020030d002000102821030c010b200128020020032000102c21030b2003450d3420012003360200200141046a2000360200200141086a28020021000b2004200041106a360200200320006a22012007370008200120083700000c140b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d60200341017422092005200920054b1b22094100480d600240024020030d002009102821050c010b200128020020032009102c21050b2005450d3420012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41013a0000200028020c21090240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d6020054101742203200a2003200a4b1b22034100480d600240024020050d002003102821050c010b200128020020052003102c21050b2005450d3520012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2009360000200041286a2903002107200029032021080240024020062802002205200428020022036b4110490d00200128020021040c010b200341106a22042003490d60200541017422032004200320044b1b22034100480d600240024020050d002003102821040c010b200128020020052003102c21040b2004450d3620012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a220320073700082003200837000020002802102103200041186a2802002200200110b4012000450d1320004105742100034020032001108f01200341206a2103200041606a22000d000c140b0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5f200041017422052003200520034b1b22054100480d5f0240024020000d002005102821030c010b200128020020002005102c21030b2003450d3620012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c120b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5e200341017422092005200920054b1b22094100480d5e0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3620012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41033a0000200028020c21090240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d5e20054101742203200a2003200a4b1b22034100480d5e0240024020050d002003102821050c010b200128020020052003102c21050b2005450d3720012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200936000020002d0009220041024b0d1102400240024020000e03000102000b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d60200041017422052003200520034b1b22054100480d600240024020000d002005102821030c010b200128020020002005102c21030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41003a00000c130b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5f200041017422052003200520034b1b22054100480d5f0240024020000d002005102821030c010b200128020020002005102c21030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41013a00000c120b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5e200041017422052003200520034b1b22054100480d5e0240024020000d002005102821030c010b200128020020002005102c21030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c110b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5d200341017422092005200920054b1b22094100480d5d0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3a20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41043a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d5d200341017422002006200020064b1b22004100480d5d0240024020030d002000102821030c010b200128020020032000102c21030b2003450d3b20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c100b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5c200341017422092005200920054b1b22094100480d5c0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3b20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41053a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d5c200341017422002006200020064b1b22004100480d5c0240024020030d002000102821030c010b200128020020032000102c21030b2003450d3c20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0f0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5b200341017422092005200920054b1b22094100480d5b0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3c20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41063a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d5b200341017422002006200020064b1b22004100480d5b0240024020030d002000102821030c010b200128020020032000102c21030b2003450d3d20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0e0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5a200341017422092005200920054b1b22094100480d5a0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3d20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41073a0000200028020c21090240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d5a20054101742203200a2003200a4b1b22034100480d5a0240024020050d002003102821050c010b200128020020052003102c21050b2005450d3e20012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200936000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5a200341017422062005200620054b1b22064100480d5a0240024020030d002006102821050c010b200128020020032006102c21050b2005450d3f20012005360200200141046a2006360200200141086a28020021030b2004200341016a360200200520036a20002d00093a00000c0d0b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d59200341017422052004200520044b1b22054100480d590240024020030d002005102821040c010b200128020020032005102c21040b2004450d3f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a0000200041096a2001108f01200041296a2001108f010c0c0b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d58200341017422052004200520044b1b22054100480d580240024020030d002005102821040c010b200128020020032005102c21040b2004450d3f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a0000200041096a2001108f010c0b0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d57200341017422062005200620054b1b22064100480d570240024020030d002006102821050c010b200128020020032006102c21050b2005450d3f20012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a410a3a0000200041096a2001108f0120022001360208200041296a200241086a10c801200028024c210502400240200141046a2802002203200628020022006b4104490d00200128020021030c010b200041046a22062000490d57200341017422002006200020064b1b22004100480d570240024020030d002000102821030c010b200128020020032000102c21030b2003450d4020012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d56200341017422052004200520044b1b22054100480d560240024020030d002005102821040c010b200128020020032005102c21040b2004450d4020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a0000200041046a200110f2010c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d55200341017422052004200520044b1b22054100480d550240024020030d002005102821040c010b200128020020032005102c21040b2004450d4020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200041046a200110f2010c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d54200341017422052004200520044b1b22054100480d540240024020030d002005102821040c010b200128020020032005102c21040b2004450d4020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a0000024002400240024020002d00040e0400010203000b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d57200341017422052004200520044b1b22054100480d570240024020030d002005102821040c010b200128020020032005102c21040b2004450d4420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041056a2001108f01200041256a2001108f010c0a0b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d56200341017422052004200520044b1b22054100480d560240024020030d002005102821040c010b200128020020032005102c21040b2004450d4420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041056a2001108f010c090b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d55200341017422052004200520044b1b22054100480d550240024020030d002005102821040c010b200128020020032005102c21040b2004450d4420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000280208210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d55200341017422002005200020054b1b22004100480d550240024020030d002000102821030c010b200128020020032000102c21030b2003450d4520012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c080b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d54200341017422052004200520044b1b22054100480d540240024020030d002005102821040c010b200128020020032005102c21040b2004450d4520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002802082103200041106a2802002204200110b40102402004450d0020044105742104034020032001108f01200341206a2103200441606a22040d000b0b200028021421032000411c6a2802002200200110b4012000450d0720004105742100034020032001108f01200341206a2103200041606a22000d000c080b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d53200341017422052004200520044b1b22054100480d530240024020030d002005102821040c010b200128020020032005102c21040b2004450d4520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a000020002d0001220041044b0d060240024002400240024020000e050001020304000b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d57200041017422042003200420034b1b22044100480d570240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000c0a0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d56200041017422042003200420034b1b22044100480d560240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c090b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d55200041017422042003200420034b1b22044100480d550240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a00000c080b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d54200041017422042003200420034b1b22044100480d540240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41033a00000c070b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d53200041017422042003200420034b1b22044100480d530240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41043a00000c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d52200341017422052004200520044b1b22054100480d520240024020030d002005102821040c010b200128020020032005102c21040b2004450d4a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a00002000280204220341024b0d0502400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d54200341017422052004200520044b1b22054100480d540240024020030d002005102821040c010b200128020020032005102c21040b2004450d4d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000020002802082103200041106a2802002200200110b4012000450d072003200041286c6a210a200141046a2106034020032001108f01200341206a29030021070240024020062802002204200528020022006b4108490d00200128020021040c010b200041086a22092000490d55200441017422002009200020094b1b22004100480d550240024020040d002000102821040c010b200128020020042000102c21040b2004450d4f2001200436020020062000360200200528020021000b2005200041086a360200200420006a2007370000200a200341286a2203470d000c080b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d53200041017422042003200420034b1b22044100480d530240024020000d002004102821030c010b200128020020002004102c21030b2003450d4e20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c060b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d52200041017422042003200420034b1b22044100480d520240024020000d002004102821030c010b200128020020002004102c21030b2003450d4e20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a00000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d51200341017422052004200520044b1b22054100480d510240024020030d002005102821040c010b200128020020032005102c21040b2004450d4e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a000020002d0008220341044b0d040240024002400240024020030e050001020304000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d55200341017422052004200520044b1b22054100480d550240024020030d002005102821040c010b200128020020032005102c21040b2004450d5320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d55200341017422002005200020054b1b22004100480d550240024020030d002000102821030c010b200128020020032000102c21030b2003450d5420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d74200341017422052004200520044b1b22054100480d740240024020030d002005102821040c010b200128020020032005102c21040b2004450d5520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a29030021072000290310210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d74200341017422002004200020044b1b22004100480d740240024020030d002000102821030c010b200128020020032000102c21030b2003450d5620012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d73200341017422052004200520044b1b22054100480d730240024020030d002005102821040c010b200128020020032005102c21040b2004450d5620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200028022c210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d73200441017422032005200320054b1b22034100480d730240024020040d002003102821040c010b200128020020042003102c21040b2004450d5720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2006360000200041386a29030021072000290330210802400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d73200441017422032005200320054b1b22034100480d730240024020040d002003102821040c010b200128020020042003102c21040b2004450d5820012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2203200737000820032008370000200041096a2001108f010c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d72200341017422052004200520044b1b22054100480d720240024020030d002005102821040c010b200128020020032005102c21040b2004450d5820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041186a29030021072000290310210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d72200341017422002004200020044b1b22004100480d720240024020030d002000102821030c010b200128020020032000102c21030b2003450d5920012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d5920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041186a29030021072000290310210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d71200341017422002004200020044b1b22004100480d710240024020030d002000102821030c010b200128020020032000102c21030b2003450d5a20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d70200341017422052004200520044b1b22054100480d700240024020030d002005102821040c010b200128020020032005102c21040b2004450d5a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a000020002d0008220341054b0d0302400240024002400240024020030e06000102030405000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d75200341017422052004200520044b1b22054100480d750240024020030d002005102821040c010b200128020020032005102c21040b2004450d6020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041096a2001108f01200041296a2001108f01200041d8006a29030021072000290350210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d75200341017422002004200020044b1b22004100480d750240024020030d002000102821030c010b200128020020032000102c21030b2003450d6120012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d74200341017422052004200520044b1b22054100480d740240024020030d002005102821040c010b200128020020032005102c21040b2004450d6120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041096a2001108f01200041296a2001108f010c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d73200341017422052004200520044b1b22054100480d730240024020030d002005102821040c010b200128020020032005102c21040b2004450d6120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200136020c200041096a2002410c6a10c8010c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d72200341017422052004200520044b1b22054100480d720240024020030d002005102821040c010b200128020020032005102c21040b2004450d6120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d72200341017422002005200020054b1b22004100480d720240024020030d002000102821030c010b200128020020032000102c21030b2003450d6220012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d6220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041096a2001108f0102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d6320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00293a00000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d70200341017422052004200520044b1b22054100480d700240024020030d002005102821040c010b200128020020032005102c21040b2004450d6320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a0000200041096a2001108f01200028022c2106200041346a2802002200200110b40102400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d70200441017422032005200320054b1b22034100480d700240024020040d002003102821040c010b200128020020042003102c21040b2004450d6420012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a20062000109a051a0c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6f200341017422052004200520044b1b22054100480d6f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410d3a000020002d0001220341024b0d0202400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d6720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d6820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00023a00000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d70200341017422052004200520044b1b22054100480d700240024020030d002005102821040c010b200128020020032005102c21040b2004450d6820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041026a2001108f010c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6f200341017422052004200520044b1b22054100480d6f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d6f200341017422052004200520044b1b22054100480d6f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00023a00000c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6e200341017422052004200520044b1b22054100480d6e0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410e3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d6e200341017422052004200520044b1b22054100480d6e0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041016a2001108f010c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6d200341017422052004200520044b1b22054100480d6d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410f3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d6d200341017422052004200520044b1b22054100480d6d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041106a200110c601200028020421062000410c6a2802002200200110b40102400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d6d200441017422032005200320054b1b22034100480d6d0240024020040d002003102821040c010b200128020020042003102c21040b2004450d6c20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a20062000109a051a0b200241106a24000f0b200541011037000b200441011037000b200641011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200341011037000b200041011037000b200541011037000b200541011037000b200041011037000b200541011037000b200041011037000b200541011037000b200041011037000b200541011037000b200541011037000b200041011037000b200941011037000b200941011037000b200341011037000b200041011037000b200941011037000b200341011037000b200341011037000b200541011037000b200941011037000b200341011037000b200541011037000b200541011037000b200541011037000b200941011037000b200041011037000b200941011037000b200041011037000b200941011037000b200041011037000b200941011037000b200341011037000b200641011037000b200541011037000b200541011037000b200641011037000b200041011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200541011037000b200541011037000b200041011037000b200441011037000b200441011037000b200541011037000b200541011037000b200041011037000b1031000b200541011037000b200041011037000b200541011037000b200341011037000b200341011037000b200541011037000b200041011037000b200541011037000b200041011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200541011037000b200341011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200341011037000b1031000bfd1201057f230041106b2202240002400240024002400240024002400240024002400240024002400240024020002d0000220341054b0d0002400240024002400240024020030e06000102030405000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102821040c010b200128020020032005102c21040b2004450d0720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041016a2001108f012000280244210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d14200441017422032005200320054b1b22034100480d140240024020040d002003102821040c010b200128020020042003102c21040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a20063600002002200136020c200041216a2002410c6a10c8012000280248210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d14200341017422002005200020054b1b22004100480d140240024020030d002000102821030c010b200128020020032000102c21030b2003450d0920012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102821040c010b200128020020032005102c21040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041016a2001108f012002200136020c200041216a2002410c6a10c80102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102821040c010b200128020020032005102c21040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20002d00413a00002000280244210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d13200441017422032005200320054b1b22034100480d130240024020040d002003102821040c010b200128020020042003102c21040b2004450d0b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a20063600002000280248210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d13200341017422002005200020054b1b22004100480d130240024020030d002000102821030c010b200128020020032000102c21030b2003450d0c20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102821040c010b200128020020032005102c21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200136020c200041016a2002410c6a10c8010c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102821040c010b200128020020032005102c21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002002200136020c200041016a2002410c6a10c8010c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102821040c010b200128020020032005102c21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a00002002200136020c200041016a2002410c6a10c80102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102821040c010b200128020020032005102c21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00213a00000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a00002002200136020c200041016a2002410c6a10c80102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00213a00000b200241106a24000f0b200541011037000b200341011037000b200041011037000b200541011037000b200541011037000b200341011037000b200041011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b1031000bf40501027f4190ce0021024100210302400240024002400240024002400240024002400240024002400240024020012802000e15000e08080e01020304050607090e0e0a0e0c0e0e0e000b417f2102200141086a280200417f6a220141054b0d0a41012103024020010e060e0b0d000d0d0e0b41c09a0c21020c0d0b200141086a280200417f6a220141024b0d0941c0843d210241002103024020010e030d000d0d0b4101210341d0860321020c0c0b200141086a2d0000417f6a2201410c4b0d0841a0c21e21024100210302400240024020010e0d0e0e000001010e0e01020808080e0b4180b5182102410021030c0d0b41b0e32d2102410021030c0c0b4101210341f0930921020c0b0b41f093092102410021030c0a0b200141086a2d0000417f6a220141104b0d0641c096b102210241002103024002400240024020010e110d0d0101000d0d0d0101070702020203030d0b4101210341a0c21e21020c0c0b41c09a0c2102410021030c0b0b41a08d062102410021030c0a0b41a0c21e2102410021030c090b20012d0004417f6a220141034b0d054101210341a08d0621020240024020010e040a0a00010a0b41c096b10221020c090b41c09a0c21020c080b20012d0004417f6a220141034b0d044101210341a08d0621020240024020010e0409090001090b41c096b10221020c080b41c09a0c21020c070b200141086a280200417f6a220141094b0d0341a0cb98012102410021030240024020010e0a08080800080102020202080b41d0a5cc002102410021030c070b4180ade2042102410021030c060b410121030c040b41d086034190ce0020012d0004411d7441808080807e6a411d75417f4a1b2102410021030c040b200141086a280200417f6a220141024b0d0041a0c21e210241002103024020010e03040000040b4101210341a08d0621020c030b4190ce002102410021030c020b02402001280204417f6a220141024b0d00410121034100210220010e03020002020b410021030b4190ce0021020b200020033a0004200020023602000be6fe0109017f017e067f017e047f017e0a7f037e177f230041d0076b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e15000102031e1c1b1a191817160f0e0d0c0b0a090807000b200141106a29030021042001410c6a280200210520022d0001210620022d000021020240024002400240024002400240200141086a28020022070e0700060102030405000b200341d4066a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a4188a6c300103e000b2004a7210702400240200241ff01710d00200641ff01714101460d010b2007450d2d2005102a0c2d0b2007450d2a2005102a0c2a0b200220067241ff01710d2a410810282202450d09200220043700004198a6c300410a2002410810072002102a0c290b2004a721070240200220067241ff0171450d002007450d2a2005102a0c2a0b41a2a6c300410520052004422088a710072007450d282005102a0c280b2004422088a721082004a721090240200220067241ff0171450d0002402008450d00200841186c21062005210203400240200241046a280200450d002002280200102a0b0240200241106a280200450d002002410c6a280200102a0b200241186a2102200641686a22060d000b0b410121064100210a4105210820090d260c270b0240200841186c2202450d00200520026a21062005210203402002280200200241086a2802002002410c6a280200200241146a2802001007200241186a22022006470d000b0b02402008450d00200841186c21062005210203400240200241046a280200450d002002280200102a0b0240200241106a280200450d002002410c6a280200102a0b200241186a2102200641686a22060d000b0b410121064100210a4107210820090d250c260b2004422088a721082004a721090240200220067241ff0171450d0002402008450d002008410c6c21062005210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b410021064101210a410521082009450d260c250b02402008410c6c2202450d00200520026a21062005210203402002280200200241086a28020010092002410c6a22022006470d000b0b02402008450d002008410c6c21062005210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b410021064101210a4107210820090d240c250b200220067241ff01710d260c250b10f501000b024020022d00000d0020022d000141ff01714102470d00200141086a290300210420034180056a41086a22024200370300200342003703800541d8a1c600411320034180056a1008200341b8026a41086a2206200229030037030020032003290380053703b8020240200341b8026a41104101410041001003417f470d0020024200370300200342003703800541feb3c300410d20034180056a10082006200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a100621020240024020032802c0062206417f460d002002450d0020064108490d012002290000210b2002102a200b500d004200210b20034180056a41086a22024200370300200342003703800541feb3c300410d20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a10062102024020032802c0062206417f460d002002450d0020064108490d072002290000210b2002102a0b200b42dc0b7c2004560d050b20034180056a41086a22024200370300200342003703800541feb3c300410d20034180056a1008200341b8026a41086a2206200229030037030020032003290380053703b802200320043703c006200341b8026a4110200341c0066a4108100741012105200341013a00c00620024200370300200342003703800541d8a1c600411320034180056a10082006200229030037030020032003290380053703b802200341b8026a4110200341c0066a41011007200041023a0008410121060c2b0b41c4d1c3004133200341c8076a419cd9c3001038000b41c8adc3001032000b20004181043b01082000410f360204200041ea9fc6003602002000410a6a41003a00000c1a0b2001410c6a2802002105200141086a280200210c2001280204210d41ea9fc600210e410f210f20022d00000d1e20022d000141ff01714102470d1e20034180056a41086a22024200370300200342003703800541c8fbc500411720034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a10062102024002400240024020032802c0062206417f460d002002450d002006450d0120022d000021062002102a20064102460d002006410171450d0041a4cdc200210e411c210f0c220b200341013a00c00620034180056a41086a22024200370300200342003703800541c8fbc500411720034180056a1008200341b8026a41086a2206200229030037030020032003290380053703b802200341b8026a4110200341c0066a4101100710980121082002420037030020034200370380054193cdc200411120034180056a10082006200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a1006210202400240024020032802c0062206417f460d002002450d0020032006360294012003200236029001200341c0066a20034190016a107b20032802c0062207450d0520032902c406210402402006450d002002102a0b200320073602980302402004422088220ba722022004a7470d00200341c0066a21060c020b200341c0066a21060c020b4104210720034104360298034200210441002102200341c0066a21060b024020022004a7470d00200241016a220a2002490d1120024101742209200a2009200a4b1bad220b42c4007e2210422088a70d112010a7220a4100480d110240024020020d00200a102821070c010b2007200241c4006c200a102c21070b2007450d032003200736029803200442808080807083200b8421040b2004422088220ba721020b2007200241c4006c6a22022008360204200241003a000020022006290200370208200241106a200641086a290200370200200241186a200641106a290200370200200241206a200641186a290200370200200241286a200641206a290200370200200241306a200641286a290200370200200241386a200641306a290200370200200241c0006a200641386a280200360200200b422086200442ffffffff0f83844280808080107c2104200d200541f0006c6a2108024020050d00200d21070c200b200341e0056a417f6a210a20034193046a2111200341d7046a21122003419b056a2113200341c0066a41106a2114200341c0066a41086a211520034180056a41186a2116200d2107024003402007280204210220072802002106200341c0066a200741086a41e800109a051a200741f0006a21072002450d2120034190016a200341c0066a41e800109a051a200320023602c406200320063602c006201520034190016a41e800109a051a20032802980321171098012102200341e0056a200341c0066a10f60102400240024020032802c00622060d0041d6cdc200210e4110210f0c010b0240200620024d0d00411a210f41e6cdc200210e0c010b20034198046a2006417f6a10f701024020034198046a20144120109c05450d004119210f4180cec200210e0c010b024020032802c006221841002002417b6a2206200620024b1b4f0d004126210f4199cec200210e0c010b20172004422088220ba7220941c4006c22196a21052017210202400240201941cd01490d00201721020340024020022d00004101470d00200241016a2106200a2002460d032006200341e0056a4120109c05450d030b0240200241c4006a2d00004101470d00200241c5006a210620132002460d032006200341e0056a4120109c05450d030b024020024188016a2d00004101470d0020024189016a210620122002460d032006200341e0056a4120109c05450d030b0240200241cc016a2d00004101470d00200241cd016a210620112002460d032006200341e0056a4120109c05450d030b200520024190026a22026b41cc014b0d000b0b024020022005460d000340024020022d00004101470d00200241016a2106200a2002460d032006200341e0056a4120109c05450d030b2005200241c4006a2202470d000b0b410021060b20034198046a201810f70120034198046a200341e0056a4120109c052102200341b8036a41086a221a20034180056a41086a2205290200370300200341b8036a41106a20034180056a41106a221829020037030020032003290280053703b80341c0cdc200210e4116210f20060d2220020d010c220b200341b8036a41086a20034180056a41086a290200370300200341b8036a41106a20034180056a41106a29020037030020032003290280053703b8030c210b200341b8026a410e6a2206200341b8036a410e6a290100370100200341b8026a41086a220e201a290300370300200320032903b8033703b80220034198046a200341c0066a10f6012016420037030020184200370300200542003703002003420037038005024041c80010282202450d0020034198026a10f8012002410236022020024101360244200241186a20034198026a41186a290300370200200241106a20034198026a41106a290300370200200241086a20034198026a41086a290300370200200220032903980237020020022003290380053700242002412c6a2005290300370000200241346a20182903003700002002413c6a2016290300370000200320023602e00520034282808080203702e405200341e0056a10f901200341f8016a41086a220520034198046a41086a290300370300200341f8016a41106a221820034198046a41106a290300370300200341f8016a41186a220f20034198046a41186a290300370300200341e0056a41086a221a200e290300370300200341e0056a410e6a220e200629010037010020032003290398043703f801200320032903b8023703e0050240024020092004a7460d00200421100c010b200941016a22022009490d13200ba74101742206200220022006491bad221042c4007e220b422088a70d13200ba722064100480d130240024020090d002006102821020c010b201720192006102c21020b2002450d0320032002360298032004422088220ba721090b200328029803200941c4006c6a220241013a0000200f29030021042018290300211b2005290300211c20032903f801211d20024116360028200241c0cdc200360024200241003a00212002413a6a200e290100370000200241346a201a290300370000200220032903e00537002c2002201d370001200241096a201c370000200241116a201b370000200241196a2004370000201042ffffffff0f832104200b422086210b024020032802cc062206450d0020032802c4062102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200b2004842104024020032802c806450d0020032802c406102a0b20044280808080107c210420072008470d010c230b0b41c80041041037000b200641041037000b41c4d1c3004133200341c8076a419cd9c3001038000b200a41041037000b41c4d1c3004133200341c8076a419cd9c3001038000b4190aec3001032000b41c4d1c3004133200341c8076a419cd9c3001038000b410841011037000b10d601000b10fa01000b200141246a280200211a200141206a280200210f2001411c6a280200210a200141186a2802002118200141146a2802002109200141106a28020021132001410c6a280200210e200141086a280200211920022d0001210620022d000021022001280204210820034190016a41386a200141e0006a29000037030020034190016a41306a200141d8006a29000037030020034190016a41286a200141d0006a29000037030020034190016a41206a200141c8006a29000037030020034190016a41186a200141c0006a29000037030020034190016a41106a200141386a29000037030020034190016a41086a200141306a2900003703002003200141286a2900003703900141ea9fc6002105410f21070240024020020d00200641ff01714102470d00024010fb01200f460d0041fb91c1002105411c21070c010b200341c0066a200f201a10fc0120032802c006220220032802c80641014100410010032106024020032802c406450d002002102a0b20034180056a41086a22024200370300200342003703800541c2e1c000410d20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a1006210202400240024002400240024002400240024002400240024020032802c0062205417f460d002002450d002003200536029c042003200236029804200341c0066a20034198046a107c20032802c006220c450d0220032902c40621042005450d012002102a0c010b420021044101210c0b02402006417f460d0041b392c1002105411521070c030b200c201a4105746a4100201a2004422088a7491b22120d0141c892c1002105411821070c020b41c4d1c3004133200341c8076a419cd9c3001038000b200341003602c806200342013703c00602400240024002400240410410282202450d0020034284808080c0003702c406200320023602c006200220083600002013200341c0066a10b4010240024020032802c406220620032802c80622026b2013490d0020032802c00621060c010b200220136a22052002490d16200641017422072005200720054b1b22054100480d160240024020060d002005102821060c010b20032802c00620062005102c21060b2006450d02200320053602c406200320063602c0060b2003200220136a3602c806200620026a20192013109a051a200a200341c0066a10b4012009200a410c6c6a2116200a450d0220092106034020062802002117200641086a2802002202200341c0066a10b4010240024020032802c406220720032802c80622056b2002490d0020032802c00621080c010b200520026a22082005490d172007410174220d2008200d20084b1b220d4100480d170240024020070d00200d102821080c010b20032802c0062007200d102c21080b2008450d052003200d3602c406200320083602c006200d21070b2003200520026a220d3602c806200820056a20172002109a051a2006410c6a22062016470d000c050b0b410441011037000b200541011037000b20032802c406210720032802c806210d0c010b200d41011037000b024002402007200d6b4104490d0020032802c00621020c010b200d41046a2202200d490d11200741017422062002200620024b1b22064100480d110240024020070d002006102821020c010b20032802c00620072006102c21020b2002450d03200320063602c406200320023602c006200621070b2003200d41046a22063602c8062002200d6a200f36000002400240200720066b41034d0d00200721050c010b200641046a22052006490d11200741017422082005200820054b1b22054100480d110240024020070d002005102821020c010b200220072005102c21020b2002450d04200320053602c406200320023602c0060b200220066a201a3600002002200d41086a20034190016a2012100a210602402005450d002002102a0b2006450d01419792c1002105411c21070b2004a7450d07200c102a0c070b201241086a290000210b201241106a29000021102012290000211b20034198026a41186a201241186a290000221c37030020034198026a41106a201037030020034198026a41086a200b3703002003201b37039802200341c9066a200b370000200341d1066a2010370000200341d9066a201c3700002003410e3a00c0062003201b3700c10641014100200341c0066a10cc01200341003602c806200342013703c0062013200341c0066a10b4010240024020032802c406220620032802c80622026b2013490d0020032802c00621060c010b200220136a22052002490d0f200641017422072005200720054b1b22054100480d0f0240024020060d002005102821060c010b20032802c00620062005102c21060b2006450d03200320053602c406200320063602c0060b2003200220136a3602c806200620026a20192013109a051a200a200341c0066a10b401200a450d0320092106034020062802002117200641086a2802002202200341c0066a10b4010240024020032802c406220820032802c80622056b2002490d0020032802c00621070c010b200520026a22072005490d102008410174220d2007200d20074b1b220d4100480d100240024020080d00200d102821070c010b20032802c0062008200d102c21070b2007450d062003200d3602c406200320073602c006200d21080b2003200520026a220d3602c806200720056a20172002109a051a2006410c6a22062016470d000c060b0b200641011037000b200541011037000b200541011037000b20032802c806210d20032802c406210820032802c00621070c010b200d41011037000b200341c0066a200f201a10fc0120032802c0062102200320032802c80636029c0420032002360298042007200d20034198046a10cb01024020032802c406450d002002102a0b02402008450d002007102a0b02402004a7450d00200c102a0b0240200e450d002019102a0b0240200a450d00200a410c6c21062009210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b02402018450d002009102a0b200041023a0008410021160c010b0240200e450d002019102a0b0240200a450d00200a410c6c21062009210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b02402018450d002009102a0b20004181243b01082000200736020420002005360200410021162000410a6a41003a00000b410121054101210641012107410121084101210a41012109410121174101210d410121184101210e4101210f410121190c2b0b2002411a6a2901002104200241196a2d00002119200241186a2d00002116200241166a2f0100211a200241156a2d00002113200241146a2d0000210c200241126a2f01002112200241116a2d00002111200241106a2d000021092002410e6a2f010021172002410d6a2d0000210d2002410c6a2d000021182002410a6a2f0100210e200241096a2d0000210f200241086a2d00002106200241066a2f01002105200241056a2d00002107200241046a2d00002115200241026a2f01002114200141216a290000210b200141206a2d0000211e2001411d6a2f0000211f2001411c6a2d00002120200141196a2f00002121200141186a2d00002122200141156a2f00002123200141146a2d00002124200141116a2f00002125200141106a2d000021262001410c6a2802002127200141086a280200210a20022d0001210820022d0000210220012d001f212820012d001b212920012d0017212a20012d0013212b024002400240024002400240024002400240024020012802040e0400010203000b200341c0066a41146a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a41b49dc400103e000b410420054108742006411874722007724104200841ff017141014622061b200241ff017122021b21050240024020020d0020060d010b410f210641ea9fc600210202400240024002400240024020050e070001020304050a000b200e410874200f7220184118747221022017410874200d7220094118747221060c090b410e210641dc9fc60021020c080b410c210641d09fc60021020c070b4109210641c79fc60021020c060b4113210641b49fc60021020c050b4111210641a39fc60021020c040b200320043703b004200320193a00af04200320163a00ae042003201a3b01ac04200320133a00ab042003200c3a00aa04200320123b01a804200320113a00a704200320093a00a604200320173b01a4042003200d3a00a304200320183a00a2042003200e3b01a0042003200f3a009f042003200536009b04200320153a009a04200320143b01980420034180056a41086a22024200370300200342003703800541e69dc400410820034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341c0066a200341b8026a411010fd010240024020032d00c0064101460d00200341a8016a420037030020034190016a41106a420037030020034190016a41086a420037030020034200370390010c010b200320032f00c1063b019001200320032d00c3063a009201200320032802c406360093012003200341c0066a41086a2d00003a0097012003200341d9066a2900003703a8012003200341c9066a290000370398012003200341d1066a2900003703a0010b024020034198046a20034190016a4120109c05450d0041c49dc4002102412221060c040b200341c0066a200a418801109a051a200341003b019001200341e0056a200341c0066a20034190016a10f40141012102024020032d00e80522064102460d00200341e9056a310000210b20033100ea05210420032802e405210720032802e005210541f19ec600410d100b02402006450d00200b100c0b2004100c410021022005450d0020052007100b0b200320023a00c2062003410d3b01c00641014100200341c0066a10cc01200a102a0c060b410420054108742006411874722007724104200841ff017141014622061b200241ff017122021b21050240024020020d0020060d010b410f210641ea9fc600210202400240024002400240024020050e070001020304050a000b200e410874200f7220184118747221022017410874200d7220094118747221060c090b410e210641dc9fc60021020c080b410c210641d09fc60021020c070b4109210641c79fc60021020c060b4113210641b49fc60021020c050b4111210641a39fc60021020c040b200320043703b004200320193a00af04200320163a00ae042003201a3b01ac04200320133a00ab042003200c3a00aa04200320123b01a804200320113a00a704200320093a00a604200320173b01a4042003200d3a00a304200320183a00a2042003200e3b01a0042003200f3a009f042003200536009b04200320153a009a04200320143b01980420034180056a41086a22024200370300200342003703800541e69dc400410820034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341c0066a200341b8026a411010fd010240024020032d00c0064101460d00200341a8016a420037030020034190016a41106a420037030020034190016a41086a420037030020034200370390010c010b200320032f00c1063b019001200320032d00c3063a009201200320032802c406360093012003200341c0066a41086a2d00003a0097012003200341d9066a2900003703a8012003200341c9066a290000370398012003200341d1066a2900003703a0010b024020034198046a20034190016a4120109c05450d0041ee9dc4002102413121060c050b0240200a41ff01714101460d00200a4118762105200a41087621070c020b200341c0066a202741067610fe0120032802c00621060240024020032802c8062027413f7122024b0d00410021020c010b200620024105746a2202290018210b20022d0017211e20022d0016212820022f0014211f20022d0013212020022d0012212920022f0010212120022d000f212220022d000e212a20022f000c212320022d000b212420022d000a212b20022f0008212520022d000721262002280003212720022d0002210520022f00002107410121020b024020032802c406450d002006102a0b20020d0141dc9fc6002102410e21060c040b2001412c6a280200212c410420054108742007722006411874724104200841ff017141014622061b200241ff017122021b210502400240024020020d0020060d010b410f210641ea9fc600210202400240024002400240024020050e0700010203040507000b200e410874200f7220184118747221022017410874200d7220094118747221060c060b410e210641dc9fc60021020c050b410c210641d09fc60021020c040b4109210641c79fc60021020c030b4113210641b49fc60021020c020b4111210641a39fc60021020c010b200320043703b004200320193a00af04200320163a00ae042003201a3b01ac04200320133a00ab042003200c3a00aa04200320123b01a804200320113a00a704200320093a00a604200320173b01a4042003200d3a00a304200320183a00a2042003200e3b01a0042003200f3a009f042003200536009b04200320153a009a04200320143b01980420034180056a41086a22024200370300200342003703800541e69dc400410820034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341c0066a200341b8026a411010fd010240024020032d00c0064101460d00200341a8016a420037030020034190016a41106a420037030020034190016a41086a420037030020034200370390010c010b200320032f00c1063b019001200320032d00c3063a009201200320032802c406360093012003200341c0066a41086a2d00003a0097012003200341d9066a2900003703a8012003200341c9066a290000370398012003200341d1066a2900003703a0010b024020034198046a20034190016a4120109c05450d0041c49dc4002102412221060c010b4101210602400240200a41ff01714101460d00200a4118762105200a41087621020c010b200341c0066a202741067610fe0120032802c00621070240024020032802c8062027413f7122024b0d00410021080c010b200720024105746a2202290018210b20022d0017211e20022d0016212820022f0014211f20022d0013212020022d0012212920022f0010212120022d000f212220022d000e212a20022f000c212320022d000b212420022d000a212b20022f0008212520022d000721262002280003212720022d0002210520022f00002102410121080b024020032802c406450d002007102a0b20080d0041dc9fc6002102410e21060c010b200341c0066a202c418801109a051a200341aa016a200b370100200341a9016a201e3a0000200341a8016a20283a0000200341a6016a201f3b0100200341a5016a20203a0000200341a4016a20293a0000200341a2016a20213b0100200341a1016a20223a0000200341a0016a202a3a00002003419e016a20233b010020034190016a410d6a20243a00002003419c016a202b3a00002003419a016a20253b010020034190016a41096a20263a00002003202736009501200320053a009401200320023b01920120034180023b019001200341e0056a200341c0066a20034190016a10f401024020032d00e80522024102460d00200341e0056a41096a310000210b20033100ea05210420032802e405210720032802e005210541f19ec600410d100b02402002450d00200b100c0b2004100c410021062005450d0020052007100b0b200320063a00c2062003418d043b01c00641014100200341c0066a10cc01202c102a0c050b202c106a202c102a0c020b20034180056a41086a22064200370300200342003703800541e69dc400410820034180056a1008200341b8026a41086a2208200629030037030020032003290380053703b802200341c0066a200341b8026a411010fd01200341c0066a41086a2d0000210a200341c9066a22092f00002117200341cb066a2d0000210d200341cc066a22182d0000210e200341cd066a220f2f00002119200341cf066a2d00002116200341c0066a41106a221a2d00002113200341d1066a220c2f00002112200341d3066a2d00002111200341d4066a22152d00002114200341d5066a222c2f0000212d200341d7066a2d0000212e200341d8066a222f2d0000213020032f00c106213120032d00c306213220032802c4062133200341da066a200341d9066a2234290000420020032d00c00641014622021b37010020342030410020021b3a0000202f202e410020021b3a0000200341d6066a202d410020021b3b0100202c2014410020021b3a000020152011410020021b3a0000200341d2066a2012410020021b3b0100200c2013410020021b3a0000201a2016410020021b3a0000200341ce066a2019410020021b3b0100200f200e410020021b3a00002018200d410020021b3a0000200341ca066a2017410020021b3b01002009200a410020021b3a000020032033410020021b3600c50620032032410020021b3a00c40620032031410020021b3b01c2062003418d023b01c00641014100200341c0066a10cc012003200b3703d8062003201e3a00d706200320283a00d6062003201f3b01d406200320203a00d306200320293a00d206200320213b01d006200320223a00cf062003202a3a00ce06200320233b01cc06200320243a00cb062003202b3a00ca06200320253b01c806200320263a00c706200320273600c306200320053a00c206200320073b01c00620064200370300200342003703800541e69dc400410820034180056a10082008200629030037030020032003290380053703b80220034110360294012003200341b8026a36029001200341c0066a20034190016a10ff010c030b200a106a200a102a0b2002450d010b20004181223b01082000200636020420002002360200410021192000410a6a41003a00000c010b200041023a0008410021190b410121054101210641012107410121084101210a41012109410121174101210d410121184101210e4101210f0c290b200341c0066a200141086a418001109a051a20034190016a41206a200241206a29020037030020034190016a41186a200241186a29020037030020034190016a41106a200241106a29020037030020034190016a41086a200241086a290200370300200320022902003703900120034188016a200341c0066a20034190016a1080020240024020032802880122020d00200041023a00084100210f0c010b200328028c01210620004181203b0108200020023602004100210f2000410a6a41003a0000200020063602040b410121054101210641012107410121084101210a41012109410121174101210d410121184101210e410121190c280b200341b8036a41086a22092001411c6a290200370300200341b8036a41106a2217200141246a290200370300200341b8036a41186a220d2001412c6a2802003602002003200141146a2902003703b803200241086a28020021062001410c6a280200210a410e2105200241046a280200210820022d000021070240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141086a2802000e0400010203000b200341c0066a41146a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a41e4c4c200103e000b200641107621182006410876210e200141386a290300210b200141306a29030021042002411a6a2901002110200241196a2d00002113200241186a2d0000210c200241166a2f01002112200241156a2d00002111200241146a2d00002115200241126a2f01002114200241116a2d00002127200241106a2d0000210f2002410e6a2f010021192002410d6a2d000021162002410c6a2d0000211a200241026a2f0100211e200141106a280200210520022d0001210220034198046a41186a200d28020036020020034198046a41106a201729030037030020034198046a41086a2009290300370300200320032903b80337039804410420084108762006411874724104200241014622091b200741ff017122021b21060240024020020d0020090d010b410f210541ea9fc600210202400240024002400240024020060e0700010203040516000b200e41ff0171201841087472201a4118747221022019410874201672200f4118747221050c150b410e210541dc9fc60021020c140b410c210541d09fc60021020c130b4109210541c79fc60021020c120b4113210541b49fc60021020c110b4111210541a39fc60021020c100b200320103703a801200320133a00a7012003200c3a00a601200320123b01a401200320113a00a301200320153a00a201200320143b01a001200320273a009f012003200f3a009e01200320193b019c01200320163a009b012003201a3a009a01200320183b0198012003200e3a0097012003200636009301200320083a0092012003201e3b019001200341c0066a41186a220220034198046a41186a280200360200200341c0066a41106a220720034198046a41106a290300370300200341c0066a41086a220820034198046a41086a29030037030020032003290398043703c0060240200a41ff01714101460d00200a4108762106200341e0056a41186a20022d00003a0000200341e0056a41106a2007290300370300200341e0056a41086a2008290300370300200320032903c0063703e0050c0f0b20034198026a200541067610fe0120032802980221070240024020032802a0022005413f7122024b0d00410021020c010b200341e8056a200720024105746a2202410f6a290000370300200341e0056a41106a200241176a290000370300200341f8056a2002411f6a2d00003a0000200320022900073703e00520022f0000200241026a2d000041107472210620022800032105410121020b0240200328029c02450d002007102a0b20020d0e200341b8026a41086a20034180056a41086a290000370300200341b8026a41106a20034180056a41106a29000037030041dc9fc6002102410e21050c0f0b41a6f5c5002102200741ff01714101470d0f20064102490d0f200841ff01710d0f411210282202450d01200241106a41002f008086423b0000200241086a41002900f88542370000200241002900f08542370000200241124124102c2202450d022002200a36001220034198026a41186a2206420037030020034198026a41106a2205420037030020034198026a41086a2207420037030020034200370398022002411620034198026a1000200341f8016a41186a2006290300370300200341f8016a41106a2005290300370300200341f8016a41086a200729030037030020032003290398023703f8012002102a200341003602c006200341f8016a4120200341c0066a1006210220032802c0062206417f460d092002450d09200320063602bc02200320023602b802200341c0066a200341b8026a10810220032903c0064201510d0320032802c806210520034198046a200341cc066a41dc00109a051a02402006450d002002102a0b200341c0066a20034198046a41dc00109a051a200341f8016a41201009410121020c0a0b41a6f5c5002102200741ff01714101470d0e20064104490d0e200841ff01710d0e411210282202450d03200241106a41002f008086423b0000200241086a41002900f88542370000200241002900f08542370000200241124124102c2202450d042002200a36001220034198026a41186a2206420037030020034198026a41106a2205420037030020034198026a41086a2207420037030020034200370398022002411620034198026a1000200341f8016a41186a2006290300370300200341f8016a41106a2005290300370300200341f8016a41086a200729030037030020032003290398023703f8012002102a200341f8016a41204101410041001003417f460d0a20034180056a41086a2202420037030020034200370380054181a2c600411220034180056a1008200341b8026a41086a200229030037030020032003290380053703b80241002102200341003602c006200341b8026a4110200341c0066a100621060240024020032802c0062205417f470d000c010b024020060d000c010b20032005360294012003200636029001200341c0066a20034190016a10820120032802c0062202450d0620032902c40621042005450d002006102a0b2002410420021b210d02402004420020021b2204422088220ba722022004a7470d00200241016a22062002490d19200ba722074101742205200620062005491b220641ffffffff03712006470d19200641027422054100480d190240024020020d0020051028210d0c010b200d20074102742005102c210d0b200d450d072004422088220ba721022006ad21040b200d20024102746a200a36020020034180056a41086a2202420037030020034200370380054181a2c600411220034180056a1008200341b8026a41086a200229030037030020032003290380053703b8020240200d0d00200341b8026a411010090c100b200341003602c806200342013703c006200ba741016a2206200341c0066a10b4010240024020060d0020032802c806210a20032802c406210820032802c00621060c010b410020032802c80622026b2105200d20064102746a211720032802c4062108200d210703402007280200210902400240200820056a4104490d0020032802c00621060c010b200241046a22062002490d1b2008410174220a2006200a20064b1b220a4100480d1b0240024020080d00200a102821060c010b20032802c0062008200a102c21060b2006450d0a2003200a3602c406200320063602c006200a21080b2003200241046a220a3602c806200620026a20093600002005417c6a2105200a21022017200741046a2207470d000b0b2004a72102200341b8026a41102006200a100702402008450d002006102a0b2002450d0f200d102a0c0f0b411241011037000b412441011037000b41c4d1c3004133200341c8076a419cd9c3001038000b411241011037000b412441011037000b41c4d1c3004133200341c8076a419cd9c3001038000b200541041037000b200a41011037000b410021020b200341e0056a200341c0066a41dc00109a051a200341c0066a200341e0056a41dc00109a051a20020d010b418ec5c2002102411921050c030b20034180056a200341c0066a41dc00109a051a200320053602900120034190016a41047220034180056a41dc00109a051a200341f8006a200341b0016a20032903a001200341a8016a29030010820220032903782104200320034180016a2903003703c806200320043703c0062003200341c0066a3602980420034198046a109d010c030b200341e0006a2004200b42c0843d420010a005200341d0006a20032903602210200341e0006a41086a290300221b42c0fb42427f109f05200341c0006a2010201b42d086034200109f0520034198036a41086a200341e0056a41086a29030037030020034198036a41106a200341e0056a41106a29030037030020034198036a41186a200341e0056a41186a2d00003a0000200320032903e00522103703b8022003201037039803200341f0006a20034190016a2003290340221b200420032903507c42148042ffffffff0f837c2210428080e983b1de162010428080e983b1de1656200341c0006a41086a2903002010201b54ad7c22104200522010501b22021b221b2010420020021b221010830202402003280270450d0041f4c4c2002102411a21050c010b20034180056a41086a22024200370300200342003703800541eba1c600411620034180056a1008200341b8026a41086a200229030037030020032003290380053703b80241002107200341003602c006200341b8026a4110200341c0066a10062102024020032802c0062208417f460d002002450d0020084104490d04200228000021072002102a0b20034180056a41086a22024200370300200342003703800541eba1c600411620034180056a1008200341b8026a41086a200229030037030020032003290380053703b8022003200741016a3602c006200341b8026a4110200341c0066a41041007200341f8066a20034190016a41186a290300370300200341f0066a20034190016a41106a290300370300200341e8066a20034190016a41086a29030037030020034183076a200536000020034187076a2003290398033700002003418f076a20034198036a41086a29030037000020034197076a20034198036a41106a2903003700002003419f076a20034198036a41186a2d00003a0000200320063b01800720034182076a20064110763a00002003200b3703c806200320043703c00620032003290390013703e006200341c0066a41186a20103703002003201b3703d006411210282202450d04200241106a41002f008086423b0000200241086a41002900f88542370000200241002900f08542370000200241124124102c2202450d052002200736001220034198026a41186a2206420037030020034198026a41106a2205420037030020034198026a41086a2208420037030020034200370398022002411620034198026a1000200341f8016a41186a2006290300370300200341f8016a41106a2005290300370300200341f8016a41086a200829030037030020032003290398023703f8012002102a200341003602e805200342013703e005200341e0066a200341e0056a108f01200341c0066a41086a290300210420032903c006210b0240024020032802e405220620032802e80522026b4110490d0020032802e00521060c010b200241106a22052002490d0c200641017422022005200220054b1b22024100480d0c0240024020060d002002102821060c010b20032802e00520062002102c21060b2006450d07200320023602e405200320063602e00520032802e80521020b200620026a220620043700082006200b3700002003200241106a3602e80520034180076a200341e0056a108f01200341d8066a290300210420032903d006210b0240024020032802e405220520032802e80522066b4110490d0020032802e00521020c010b200641106a22022006490d0c200541017422062002200620024b1b22084100480d0c0240024020050d002008102821020c010b20032802e00520052008102c21020b2002450d08200320083602e405200320023602e00520032802e8052106200821050b200220066a220820043700082008200b370000200341f8016a41202002200641106a100702402005450d002002102a0b200341cc066a200736020041002102200341c8066a41003a00002003410b3a00c00641014100200341c0066a10cc010b2002450d010b200041811e3b010820002005360204200020023602002000410a6a41003a00000c160b200041023a00080c150b41c4d1c3004133200341c8076a419cd9c3001038000b411241011037000b412441011037000b200241011037000b200841011037000b200141086a28020021062001280204210502400240024020022d00000d0020022d000141ff01714101460d010b02402006450d002005102a0b200041811c3b010820004113360204200041b49fc6003602004100210e2000410a6a41003a00000c010b02402006450d002005102a0b200041023a00084100210e0b410121054101210641012107410121084101210a41012109410121174101210d410121180c250b02400240024020022d00000d0020022d000141ff01714102470d002001280204210220034180056a41086a220642003703002003420037038005418194c100411020034180056a1008200341b8026a41086a200629030037030020032003290380053703b802200341b8026a41104101410041001003417f470d011098012002490d0220034180056a41086a220642003703002003420037038005418194c100411020034180056a1008200341b8026a41086a200629030037030020032003290380053703b802200320023602c006200341b8026a4110200341c0066a41041007200041023a00080c110b200041811a3b01082000410f360204200041ea9fc6003602002000410a6a41003a00000c100b41a894c1001032000b41bc95c1001032000b200341b8036a41026a2205200141076a2d00003a000020034190016a41086a22072001411c6a29020037030020034190016a41106a220a200141246a29020037030020034190016a41186a2001412c6a290200370300200341b0016a200141346a290200370300200341b8016a2001413c6a290200370300200341c0016a200141c4006a2d00003a0000200320012f00053b01b8032003200141146a29020037039001200141086a28020021082001410c6a2802002109200141106a280200210620022f0001200241036a2d000041107472210d2002410c6a2802002118200241086a280200210e200241046a280200210f20022d0000210202400240024002400240024002400240024002400240024020012d000422170e050001020304000b200341c0066a41146a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a41e8cfc300103e000b200341af046a2007290300370000200341b7046a200a2d00003a0000200320032f01b8033b019804200320063600a3042003200936009f042003200836009b0420032003290390013700a704200320052d00003a009a04024002402002417f6a220641024b0d00024020060e03000102000b200e41017420184d0d00200f41ff0171450d010b2002200d7241ff0171450d0041a3d0c3002105410a2118410021060c0e0b20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a1006210202400240024002400240024002400240024020032802c0062206417f460d002002450d00200320063602e405200320023602e005200341c0066a200341e0056a106d20032802c006220a450d0c20032902c406210420032802c406211802402006450d002002102a0b2003200a3602e0052004a7210e410021022004422088a7220d41014b0d02200d0e020103010b4101210a200341013602e005410021184100210e0b200341f8016a41186a20034198046a41186a290300370300200341f8016a41106a20034198046a41106a290300370300200341f8016a41086a20034198046a41086a29030037030020032003290398043703f8014100210d200341f8016a2106410021050c020b200d210603402006410176220520026a22072002200a20074105746a20034198046a4120109c054101481b2102200620056b220641014b0d000b0b0240200a20024105746a20034198046a4120109c0522060d004193d0c3002105200e450d05200a102a0c050b200341f8016a41186a20034198046a41186a290300370300200341f8016a41106a20034198046a41106a290300370300200341f8016a41086a20034198046a41086a29030037030020032003290398043703f8012006411f7620026a2205200d4b0d01200341f8016a21060b200d200e460d012018210e0c020b41f8b0c0001032000b02402018200d460d002018210e0c010b201841016a22022018490d0c201841017422072002200720024b1b220e41ffffff3f71200e470d0c200e41057422024100480d0c0240024020180d0020021028210a0c010b200a20184105742002102c210a0b200a450d062003200a3602e0050b200a20054105746a220241206a2002200d20056b410574109b051a200241186a200641186a290000370000200241106a200641106a290000370000200241086a200641086a2900003700002002200629000037000020034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b80220032802e0052102200341003602c806200342013703c006200d41016a2207200341c0066a10b40102402007200d490d00200d41057441206a210603402002200341c0066a108f01200241206a2102200641606a22060d000b0b20032802c4062102200341b8026a411020032802c006220620032802c806100702402002450d002006102a0b200341c0066a41186a20034198046a41186a290300370300200341c0066a41106a20034198046a41106a290300370300200341c0066a41086a20034198046a41086a29030037030020032003290398043703c006410021054101410020032802e00522022007108402200341093b01c00641014100200341c0066a10cc01200e450d002002102a0b41102118410021060c0d0b200341af046a2007290300370000200341b7046a200a2d00003a0000200320032f01b8033b019804200320063600a3042003200936009f042003200836009b0420032003290390013700a704200320052d00003a009a04024002402002417f6a220641024b0d00024020060e03000102000b200e41017420184d0d00200f41ff0171450d010b2002200d7241ff0171450d0041a3d0c3002105410a2118410021060c0d0b20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a100621020240024020032802c0062206417f460d002002450d00200320063602e405200320023602e005200341c0066a200341e0056a106d20032802c006220a450d0620032902c40621042006450d012002102a0c010b420021044101210a0b41002102024002400240024002402004422088a7220d41014b0d00200d0e020201020b200d210603402006410176220520026a22072002200a20074105746a20034198046a4120109c054101481b2102200620056b220641014b0d000b0b200a20024105746a20034198046a4120109c05450d010b41add0c3002105410c21182004a7450d01200a102a410021060c0e0b2002200d4f0d06200a20024105746a2206200641206a2002417f73200d6a410574109b051a20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c806200342013703c006200d417f6a2205200341c0066a10b40102402005450d00200d41057441606a2106200a210203402002200341c0066a108f01200241206a2102200641606a22060d000b0b20032802c4062102200341b8026a411020032802c006220620032802c806100702402002450d002006102a0b200341c0066a41186a20034198046a41186a290300370300200341c0066a41106a20034198046a41106a290300370300200341c0066a41086a20034198046a41086a29030037030020032003290398043703c006200341c0066a4101200a200510840220034189023b01c0064100210541014100200341c0066a10cc0102402004a7450d00200a102a0b0b410021060c0c0b200341f7056a2007290300370000200341ff056a200a2d00003a0000200320032f01b8033b01e005200320063600eb05200320093600e705200320083600e30520032003290390013700ef05200320052d00003a00e20520034198046a41186a200341b9016a29000037030020034198046a41106a200341b1016a29000037030020034198046a41086a200341a9016a290000370300200320032900a10137039804024002402002417f6a220641024b0d00024020060e03000102000b200e41017420184d0d00200f41ff0171450d010b2002200d7241ff0171450d0041a3d0c3002105410a2118410021060c0c0b02400240200341e0056a20034198046a4120109c050d00410021050c010b20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a100621020240024020032802c0062206417f460d002002450d0020032006360284052003200236028005200341c0066a20034180056a106d20032802c006220d450d0820032902c40621042006450d012002102a0c010b4101210d420021040b41add0c3002105410c211841002102024002402004422088a7220e41014b0d00200e0e020c010c0b200e210603402006410176220720026a220a2002200d200a4105746a200341e0056a4120109c054101481b2102200620076b220641014b0d000b0b200d20024105746a2206200341e0056a4120109c050d0a20034198026a41186a220520034198046a41186a29030037030020034198026a41106a220720034198046a41106a29030037030020034198026a41086a220a20034198046a41086a2903003703002003200329039804370398022002200e4f0d072006200329039802370000200641186a2005290300370000200641106a2007290300370000200641086a200a290300370000410021020240200e4101460d0041002102200e210603402006410176220520026a22072002200d20074105746a20034198046a4120109c054101481b2102200620056b220641014b0d000b0b0240200d20024105746a20034198046a4120109c050d004193d0c3002105411021180c0b0b200d200e10f00120034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c806200342013703c006200e200341c0066a10b4010240200e450d00200e4105742106200d210203402002200341c0066a108f01200241206a2102200641606a22060d000b0b20032802c4062102200341b8026a411020032802c006220620032802c806100702402002450d002006102a0b200341c0066a41186a200341e0056a41186a290300370300200341c0066a41106a200341e0056a41106a290300370300200341c0066a41086a200341e0056a41086a290300370300200320032903e0053703c006200341c0066a4101200d200e10840220034189043b01c0064100210541014100200341c0066a10cc012004a7450d00200d102a0b0c0a0b024002402002417f6a220541024b0d00024020050e03000102000b200e41017420184d0d00200f41ff0171450d010b2002200d7241ff0171450d0002402009450d002008102a0b41a3d0c3002105410a21180c0c0b2008200610f00120034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a100621050240024020032802c0062207417f460d002005450d002003200736029c042003200536029804200341c0066a20034198046a106d20032802c0062202450d0820032902c40621042007450d012005102a0c010b42002104410121020b2008200620022004422088a710850202402004a7450d002002102a0b20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c806200342013703c0062006200341c0066a10b40102402006450d00200641057421062008210203402002200341c0066a108f01200241206a2102200641606a22060d000b0b20032802c4062102200341b8026a411020032802c006220620032802c806100702402002450d002006102a0b02402009450d002008102a0b20034189063b01c006410021054101210641014100200341c0066a10cc010c0a0b41c4d1c3004133200341c8076a419cd9c3001038000b200241011037000b41c4d1c3004133200341c8076a419cd9c3001038000b41b0b1c0001032000b41c4d1c3004133200341c8076a419cd9c3001038000b41bcd0c3002002200e1034000b41c4d1c3004133200341c8076a419cd9c3001038000b1031000b2004a7450d00200d102a410021060c010b410021060b0240024002402017417f6a220241034b0d00024020020e0403030300030b200620094572450d010c020b20174104490d012009450d010b2008102a0b20050d00200041023a0008410021180c010b20004181183b01082000201836020420002005360200410021182000410a6a41003a00000b410121054101210641012107410121084101210a41012109410121174101210d0c1c0b200341c0066a41386a200141c0006a290300370300200341c0066a41306a200141386a290300370300200341c0066a41286a200141306a290300370300200341c0066a41206a200141286a290300370300200341c0066a41186a200141206a290300370300200341c0066a41106a200141186a290300370300200341c0066a41086a200141106a2903003703002003200141086a2903003703c00620034190016a41206a200241206a29020037030020034190016a41186a200241186a29020037030020034190016a41106a200241106a29020037030020034190016a41086a200241086a2902003703002003200229020037039001200341386a200341c0066a20034190016a10860202400240200328023822020d00200041023a00084100210d0c010b200328023c210620004181163b0108200020023602004100210d2000410a6a41003a0000200020063602040b410121054101210641012107410121084101210a41012109410121170c1a0b20034190016a41206a200141246a29020037030020034190016a41186a2001411c6a29020037030020034190016a41106a200141146a29020037030020034190016a41086a2001410c6a2902003703002003200129020437039001200341c0066a41206a200241206a290200370300200341c0066a41186a200241186a290200370300200341c0066a41106a200241106a290200370300200341c0066a41086a200241086a290200370300200320022902003703c006200341306a20034190016a200341c0066a10870202400240200328023022020d00200041023a0008410021170c010b2003280234210620004181143b010820002002360200410021172000410a6a41003a0000200020063602040b410121054101210641012107410121084101210a410121090c180b20034190016a41206a200141246a29020037030020034190016a41186a2001411c6a29020037030020034190016a41106a200141146a29020037030020034190016a41086a2001410c6a2902003703002003200129020437039001200341c0066a41206a200241206a290200370300200341c0066a41186a200241186a290200370300200341c0066a41106a200241106a290200370300200341c0066a41086a200241086a290200370300200320022902003703c006200341286a20034190016a200341c0066a10880202400240200328022822020d00200041023a0008410021090c010b200328022c210620004181123b010820002002360200410021092000410a6a41003a0000200020063602040b410121054101210641012107410121084101210a0c160b200341c0066a41286a200141306a290300370300200341c0066a41206a200141286a290300370300200341c0066a41186a200141206a290300370300200341c0066a41106a200141186a290300370300200341c0066a41086a200141106a2903003703002003200141086a2903003703c00620034190016a41206a200241206a29020037030020034190016a41186a200241186a29020037030020034190016a41106a200241106a29020037030020034190016a41086a200241086a2902003703002003200229020037039001200341206a200341c0066a20034190016a10890202400240200328022022020d00200041023a00084100210a0c010b2003280224210620004181103b0108200020023602004100210a2000410a6a41003a0000200020063602040b410121054101210641012107410121080c140b200141086a28020021162001280204211a200341c0066a2001410c6a41e400109a051a2002411a6a2901002104200241196a2d00002118200241186a2d0000210e200241166a2f0100210f200241156a2d00002119200241146a2d00002113200241126a2f0100210c200241116a2d00002112200241106a2d000021072002410e6a2f010021082002410d6a2d0000210a2002410c6a2d000021092002410a6a2f01002117200241096a2d0000210d200241046a2d00002111200241026a2f01002115200241056a280000210520022d0000210620022d00012102200341b8026a200341c0066a41046a41e000109a051a410420054104200241014622021b20061b21050240024002400240024020060d0020020d010b410f210641ea9fc600210202400240024002400240024020050e0700010203040507000b2017410874200d7220094118747221022008410874200a7220074118747221060c060b410e210641dc9fc60021020c050b410c210641d09fc60021020c040b4109210641c79fc60021020c030b4113210641b49fc60021020c020b4111210641a39fc60021020c010b2003200437039805200320183a0097052003200e3a0096052003200f3b019405200320193a009305200320133a0092052003200c3b019005200320123a008f05200320073a008e05200320083b018c052003200a3a008b05200320093a008a05200320173b0188052003200d3a0087052003200536008305200320113a008205200320153b018005024002400240024002400240410e10282202450d002002410029008aaf44370000200241066a4100290090af443700002003428e808080e00137029401200320023602900120034180056a20034190016a108f012003280298012102200328029001210620034198026a41186a2205420037030020034198026a41106a2207420037030020034198026a41086a2208420037030020034200370398022006200220034198026a1000200341f8016a41186a2005290300370300200341f8016a41106a2007290300370300200341f8016a41086a200829030037030020032003290398023703f8010240200328029401450d00200328029001102a0b2003410036029001200341f8016a412020034190016a100621022003280290012206417f460d022002450d022003200636029c02200320023602980220034190016a20034198026a108a0220032802b0012217450d0120034198046a41086a2205200341c0016a29030037030020034198046a41106a2207200341c8016a29030037030020034198046a41186a2208200341d0016a29030037030020034198046a41206a220a200341d8016a2802003602002003200341b8016a2903003703980420032802b401210902402006450d002002102a0b200341e0056a41086a20052903002204370300200341e0056a41106a2007290300220b370300200341e0056a41186a20082903002210370300200341e0056a41206a200a28020022023602002003200329039804221b3703e00520034190016a41106a200b37030020034190016a41086a200437030020034190016a41186a201037030020034190016a41206a2002360200200341f8016a41086a2003419c016a290200370300200341f8016a41106a200341a4016a290200370300200341f8016a41186a200341ac016a2902003703002003201b3703900120032003290294013703f80102402009450d002017102a0b20034198036a41086a200341f8016a41086a29030037030020034198036a41106a200341f8016a41106a29030037030020034198036a41186a200341f8016a41186a290300370300200320032903f80137039803200341b8036a200341b8026a41e000109a051a20034198026a20034198036a108b0220032802a0022106200328029802210220034100360290012002200620034190016a100621062003280290012205417f460d042006450d042003200536028405200320063602800520034190016a20034180056a10e80120032d0090014101460d03200341e0056a20034190016a41017241e000109a051a02402005450d002006102a0b20034180056a200341e0056a41e000109a051a20034190016a20034180056a41e000109a051a200341013a00980420034198046a41017220034190016a41e000109a051a0c050b410e41011037000b41c4d1c3004133200341c8076a419cd9c3001038000b41a5c4c2002102412721060c030b41c4d1c3004133200341c8076a419cd9c3001038000b20034190016a20034180056a41e000109a051a200341003a0098040b0240200328029c02450d002002102a0b200341b9046a2112200341d9046a2111200341b8036a41206a2113200341f8036a210c20034198046a410172211520034190016a41017221054104210741e7e485f30621060240024003400240024002400240200641e9dabdf30646220f0d000240200641e7e485f306470d00200341b8036a210a0c020b200641e2c289ab06470d022013210a0c010b200c210a0b41202102410021084120102822090d01412041011037000b41012108410021024101210a410121090b2009200a2002109a052109200320023602a402200320023602a0022003200936029c022003200636029802200341f8016a20034198026a108c0220034190016a20032802f801221720032802800210fd0120034180056a41086a220d200541086a29000037030020034180056a41106a2218200541106a29000037030020034180056a41186a220e200541186a29000037030020032005290000370380050240024020032d0090014101470d00200341e0056a41186a2219200e290300370300200341e0056a41106a220e2018290300370300200341e0056a41086a2218200d29030037030020032003290380053703e005024020032802fc01450d002017102a0b024020080d002009102a0b20034190016a41186a201929030037030020034190016a41106a200e29030037030020034190016a41086a2018290300370300200320032903e0053703900120034190016a20034198036a4120109c05450d0141ccc4c2002102411821060c050b024020032802fc01450d002017102a0b20080d002009102a0b0240024020032d0098044101470d00024002400240200641e2c289ab06460d00200f0d010240200641e7e485f306460d0041002109410121170c030b41202109201521170c020b41202109201221170c010b41202109201121170b024020022009470d00200a2017460d02200a20172002109c05450d020b0240024020090d004100210d410121180c010b2009210d200910282218450d040b201820172009109a0521172003200936029c012003200d3602980120032017360294012003200636029001200341e0056a20034190016a108c0220032802e005220920032802e8051009024020032802e405450d002009102a0b200d450d002017102a0b41012109024020080d00200210282209450d040b2009200a2002109a05210a2003200236029c0120032002360298012003200a360294012003200636029001200341e0056a20034190016a108c0220032802e0052102200320032802e80536028405200320023602800520034198036a20034180056a10ff01024020032802e405450d002002102a0b20080d00200a102a0b02402007410c460d00200741f8c8c0006a2800002106200741046a21070c010b0b200341e0056a20034198036a108b0220032802e805210620032802e005210220034100360298012003420137039001200341b8036a20034190016a108f01201320034190016a108f01200c20034190016a108f012003280294012105200220062003280290012207200328029801100702402005450d002007102a0b024020032802e405450d002002102a0b2016450d03201a102a0c030b200941011037000b200241011037000b02402016450d00201a102a0b2002450d00200041810e3b01082000200636020420002002360200410021082000410a6a41003a00000c010b200041023a0008410021080b4101210541012106410121070c120b200341c0066a41306a200141386a290300370300200341c0066a41286a200141306a290300370300200341c0066a41206a200141286a290300370300200341c0066a41186a200141206a290300370300200341c0066a41106a200141186a290300370300200341c0066a41086a200141106a2903003703002003200141086a2903003703c00620034190016a41206a200241206a29020037030020034190016a41186a200241186a29020037030020034190016a41106a200241106a29020037030020034190016a41086a200241086a2902003703002003200229020037039001200341186a200341c0066a20034190016a108d0202400240200328021822020d00200041023a0008410021070c010b200328021c2106200041810c3b010820002002360200410021072000410a6a41003a0000200020063602040b41012105410121060c100b200141256a2900002110200141246a2d0000211a200141216a2f00002113200141206a2d0000210c2001411d6a2f000021122001411c6a2d00002111200141196a2f00002109200141186a2d00002117200141156a2f0000210d200141146a2d00002118200141106a28020021052001410d6a2f0000210e2001410c6a2d00002127200141086a2802002107200141306a2903002104200141386a290300210b20012d0023211520012d001f211420012d001b210f20012d0017211920012d000f211620034198046a41106a200141d0006a2d00003a000020034198046a41086a221e200141c8006a2903003703002003200141c0006a290300370398044111210620022d0001210820022d0000210a02400240024002400240024002400240024002400240024002400240024020070e0400010203000b200341c0066a41146a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a41e092c100103e000b200241106a2d0000211e2002410e6a2f0100211f2002410d6a2d000021202002410c6a2d000021212002410a6a2f01002122200241096a2d000021234104200241056a2800004104200841ff017141014622081b200a41ff017122061b21070240024020060d0020080d010b410f210641ea9fc600210202400240024002400240024020070e0700010203040511000b20224108742023722021411874722102201f410874202072201e4118747221060c100b410e210641dc9fc60021020c0f0b410c210641d09fc60021020c0e0b4109210641c79fc60021020c0d0b4113210641b49fc60021020c0c0b4111210641a39fc60021020c0b0b200241196a2d00002106200241186a2d00002108200241166a2f0100210a200241156a2d00002124200241146a2d00002125200241126a2f01002126200241116a2d00002128200241046a2d00002129200241026a2f0100212a20032002411a6a2901003703a801200320063a00a701200320083a00a6012003200a3b01a401200320243a00a301200320253a00a201200320263b01a001200320283a009f012003201e3a009e012003201f3b019c01200320203a009b01200320213a009a01200320223b019801200320233a0097012003200736009301200320293a0092012003202a3b01900102400240202741ff01714101470d00200341e0056a200541067610fe0120032802e00521060240024020032802e8052005413f7122024b0d00410021020c010b200620024105746a2202290018211020022d0017211a20022d0016211520022f0014211320022d0013210c20022d0012211420022f0010211220022d000f211120022d000e210f20022f000c210920022d000b211720022d000a211920022f0008210d20022d000721182002280003210520022d0002211620022f0000210e410121020b024020032802e405450d002006102a0b20020d00410121020c010b410021020b20032010370390022003201a3a008f02200320153a008e02200320133b018c022003200c3a008b02200320143a008a02200320123b018802200320113a0087022003200f3a008602200320093b018402200320173a008302200320193a0082022003200d3b018002200320183a00ff01200320053600fb01200320163a00fa012003200e3b01f80120020d09200341c0066a41186a200341f8016a41186a290300370300200341c0066a41106a200341f8016a41106a290300370300200341c0066a41086a200341f8016a41086a290300370300200320032903f8013703c006200341086a20034190016a200341c0066a2004200b108e0220032802082202450d0b200328020c21060c0a0b41a39fc60021022008200a7241ff01710d0b201e290300211b200329039804211c0240202741ff01714101470d0020034190016a200541067610fe012003280290012106024002402003280298012005413f7122024b0d00410021020c010b200620024105746a2202290018211020022d0017211a20022d0016211520022f0014211320022d0013210c20022d0012211420022f0010211220022d000f211120022d000e210f20022f000c210920022d000b211720022d000a211920022f0008210d20022d000721182002280003210520022d0002211620022f0000210e410121020b0240200328029401450d002006102a0b2002450d080b200320103703d8062003201a3a00d706200320153a00d606200320133b01d4062003200c3a00d306200320143a00d206200320123b01d006200320113a00cf062003200f3a00ce06200320093b01cc06200320173a00cb06200320193a00ca062003200d3b01c806200320183a00c706200320053600c306200320163a00c2062003200e3b01c006411410282202450d01200241002900cfe140370000200241106a41002800dfe140360000200241086a41002900d7e14037000020034294808080c002370294012003200236029001200341c0066a20034190016a108f012003280298012102200328029001210620034198026a41186a2205420037030020034198026a41106a2207420037030020034198026a41086a2208420037030020034200370398022006200220034198026a1000200341f8016a41186a2005290300370300200341f8016a41106a2007290300370300200341f8016a41086a200829030037030020032003290398023703f8010240200328029401450d00200328029001102a0b2003410036029001200341f8016a412020034190016a100621022003280290012206417f460d052002450d0520064110490d02200241086a29000021102002290000211d2002102a0c060b41a39fc60021022008200a7241ff01710d0a200141e0006a290300211c200141d8006a290300211d20032900a104211b20032d00a004210720032d009f04210820032f009d04210a20032d009c04211e20032d009b04211f20032f009904212020032d00980421210240202741ff01714101470d00200341c0066a200541067610fe0120032802c00621060240024020032802c8062005413f7122024b0d00410021020c010b200620024105746a2202290018211020022d0017211a20022d0016211520022f0014211320022d0013210c20022d0012211420022f0010211220022d000f211120022d000e210f20022f000c210920022d000b211720022d000a211920022f0008210d20022d000721182002280003210520022d0002211620022f0000210e410121020b024020032802c406450d002006102a0b2002450d070b2004422088a72106200320103703a8012003201a3a00a701200320153a00a601200320133b01a4012003200c3a00a301200320143a00a201200320123b01a001200320113a009f012003200f3a009e01200320093b019c01200320173a009b01200320193a009a012003200d3b019801200320183a0097012003200536009301200320163a0092012003200e3b01900102402004a741ff01714101460d00200ba72118200b423888a7210f200b422888a72109200b422088a72117200b421888a72119200b420888a7210d2004421888a721162004420888a7210e0c030b200341e0056a2004422688a710fe0120032802e00521050240024020032802e8052006413f7122024b0d00410021022013210a200c211e2014211f201221202011212120152108201a21072010211b0c010b200520024105746a2202290018211b20022d0017210720022d0016210820022f0014210a20022d0013211e20022d0012211f20022f0010212020022d000f212120022d000e210f20022f000c210920022d000b211720022d000a211920022f0008210d20022d000721182002280003210620022d0002211620022f0000210e410121020b024020032802e405450d002005102a0b20020d02410121020c030b411441011037000b41c4d1c3004133200341c8076a419cd9c3001038000b410021020b2003201b37039002200320073a008f02200320083a008e022003200a3b018c022003201e3a008b022003201f3a008a02200320203b018802200320213a0087022003200f3a008602200320093b018402200320173a008302200320193a0082022003200d3b018002200320183a00ff01200320063600fb01200320163a00fa012003200e3b01f80120020d03200341c0066a41186a200341f8016a41186a290300370300200341c0066a41106a200341f8016a41106a290300370300200341c0066a41086a200341f8016a41086a290300370300200320032903f8013703c006200341106a20034190016a200341c0066a201d201c108e0220032802102202450d05200328021421060c040b4200211d420021100b02400240201d20045422062010200b542010200b5122021b0d00201d2004562010200b5620021b450d012003201d20047d3703900120032010200b7d2006ad7d37039801200320034190016a3602e005200341e0056a109d010c010b20032004201d7d370390012003200b20107d2004201d54ad7d37039801200320034190016a3602e005200341e0056a109c010b200341c0066a2004200b108f020240024002400240411810282202450d00200241002900e3e140370000200241106a41002900f3e140370000200241086a41002900ebe140370000200342988080808003370294012003200236029001200341c0066a20034190016a108f012003280298012102200328029001210620034198026a41186a2205420037030020034198026a41106a2207420037030020034198026a41086a2208420037030020034200370398022006200220034198026a1000200341f8016a41186a2005290300370300200341f8016a41106a2007290300370300200341f8016a41086a200829030037030020032003290398023703f8010240200328029401450d00200328029001102a0b2003410036029001200341f8016a412020034190016a100621022003280290012206417f460d022002450d0220064110490d01200241086a29000021042002290000210b2002102a0c030b411841011037000b41c4d1c3004133200341c8076a419cd9c3001038000b4200210b420021040b02400240200b201c5422062004201b542004201b5122021b0d00200b201c562004201b5620021b450d012003200b201c7d3703900120032004201b7d2006ad7d37039801200320034190016a3602e005200341e0056a109d010c010b2003201c200b7d370390012003201b20047d201c200b54ad7d37039801200320034190016a3602e005200341e0056a109c010b200341c0066a201c201b1090020c030b41dc9fc6002102410e21060c030b41dc9fc6002102410e21060b20020d010b200041023a00080c010b200041810a3b010820002006360204200020023602002000410a6a41003a00000b41012105410121060c0d0b109102000b024020032802cc062206450d0020032802c4062102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b024020032802c806450d0020032802c406102a0b024020072008460d0003402007280204220a450d01200741086a280200210902402007410c6a2802002202450d00200241246c2106200a210203400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200741f0006a210702402009450d00200a102a0b20072008470d000b0b0240200c450d00200d102a0b2004a7450d032017102a0c030b20072008460d0003402007280204220a450d01200741086a280200210902402007410c6a2802002202450d00200241246c2106200a210203400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200741f0006a210702402009450d00200a102a0b20072008470d000b0b0240200c450d00200d102a0b20034180056a41086a2202420037030020034200370380054193cdc200411120034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341c0066a20032802980322022004422088a7109202200341b8026a411020032802c006220620032802c8061007024020032802c406450d002006102a0b02402004a7450d002002102a0b200041023a000841002106410121050c090b02402005450d00200d200541f0006c6a2108200d2107034002402007410c6a2802002206450d0020072802042102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200741f0006a21020240200741086a280200450d002007280204102a0b2002210720022008470d000b0b200c450d00200d102a0b20004181063b01082000200f3602042000200e360200410021062000410a6a41003a0000410121050c070b2005102a0b0240024002402007417f6a220241054b0d00024002400240024020020e06060006010203060b41000d052004a70d040c050b41000d042004a70d030c040b200a450d0302402004422088a72202450d00200241186c21062005210203400240200241046a280200450d002002280200102a0b0240200241106a280200450d002002410c6a280200102a0b200241186a2102200641686a22060d000b0b2004a70d020c030b2006450d0202402004422088a72202450d002002410c6c21062005210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b2004a70d010c020b02402004422088a72202450d002002410c6c21062005210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b2004a7450d010b2005102a0b410f210241ea9fc6002105410621072008417c6a0e0402010300020b200041023a0008410121060c030b4111210241a39fc6002105410521070c010b4113210241b49fc6002105410421070b41012106200041013b010820002002360204200020053602002000410a6a20073a00000b410021050b410121070b410121080b4101210a0b410121090b410121170b4101210d0b410121180b4101210e0b4101210f410121190b410121160b02402001280200220241124b0d00024002400240024002400240024002400240024002400240024020020e13000d0d010d0d020304050607080d090d0a0b0c000b2005450d0c0240200141086a280200220241054b0d0002400240024020020e06101000100102100b200141106a280200450d0f2001410c6a280200102a0c0f0b200141106a280200450d0e2001410c6a280200102a0c0e0b0240200141146a2802002206450d002001410c6a2802002102200641186c210603400240200241046a280200450d002002280200102a0b0240200241106a280200450d002002410c6a280200102a0b200241186a2102200641686a22060d000b0b200141106a280200450d0d200128020c102a0c0d0b0240200141146a2802002206450d002001410c6a28020021022006410c6c210603400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b200141106a280200450d0c200128020c102a0c0c0b2006450d0b02402001410c6a2802002202450d0020012802042200200241f0006c6a2107034002402000410c6a2802002206450d0020002802042102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200041f0006a21020240200041086a280200450d002000280204102a0b2002210020022007470d000b0b200141086a280200450d0b2001280204102a0c0b0b2007450d0a0240200141086a2d00002202410c4b0d0020024106470d0b200141106a280200450d0b2001410c6a280200102a0c0b0b200141106a280200450d0a2001410c6a280200102a0c0a0b2008450d09200141086a280200450d092001280204102a0c090b200a450d08200141086a2d0000417f6a220241074b0d08024002400240024020020e08000c0c0c0c010203000b2001410c6a2202280200106a2002280200102a0c0b0b2001410c6a2202280200106a2002280200102a0c0a0b2001410c6a2202280200106a2002280200102a0c090b2001410c6a2202280200106a2002280200102a0c080b2009450d0720012d0004417f6a220241024b0d0702400240024020020e03000102000b2001410c6a280200450d09200141086a280200102a0c090b200141086a2202280200106a2002280200102a0c080b2001410c6a2202280200106a2002280200102a0c070b2017450d0620012d0004417f6a220241024b0d0602400240024020020e03000102000b2001410c6a280200450d08200141086a280200102a0c080b200141086a2202280200106a2002280200102a0c070b2001410c6a2202280200106a2002280200102a0c060b200d450d05200141086a280200417f6a220241014b0d050240024020020e020001000b200141106a280200450d062001410c6a280200102a0c060b200141106a280200450d052001410c6a280200102a0c050b2018450d0420012d00044104490d042001410c6a280200450d04200141086a280200102a0c040b200e450d03200141086a280200450d032001280204102a0c030b200f450d02200141086a2d0000417e6a220241024b0d0202400240024020020e03000102000b200141106a280200450d042001410c6a280200102a0c040b200141346a280200450d03200141306a280200102a0c030b200141306a280200450d022001412c6a280200102a0c020b2019450d0102402001280204220241024b0d00024020020e03030003030b200141086a2202280200106a2002280200102a0c020b2001412c6a2202280200106a2002280200102a0c010b2016450d0002402001410c6a280200450d00200141086a280200102a0b02402001411c6a2802002206450d00200141146a28020021022006410c6c210603400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b200141186a280200450d002001280214102a0b200341d0076a24000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccd1c5003602002000410436021c200041c4d1c5003602182000200041186a360210200041a8c6c200103e000bfa0301077f230041306b22022400200241003602082002420137030020022002360210200141106a200241106a10c8012001200210a00120022002360210200141306a200241106a10c80120022002360210200141d0006a200241106a10c801200128020421032001410c6a2802002201200210b4010240024002402001450d00200141246c21040340200241106a200310ec01200228021021050240024020022802042206200228020822016b20022802182207490d00200228020021060c010b200120076a22082001490d04200641017422012008200120084b1b22014100480d040240024020060d002001102821060c010b200228020020062001102c21060b2006450d032002200136020420022006360200200228020821010b2002200120076a360208200620016a20052007109a051a02402002280214450d002005102a0b200341246a21032004415c6a22040d000b0b200228020421072002280208210320022802002101200241106a41186a22064200370300200241106a41106a22054200370300200241106a41086a220442003703002002420037031020012003200241106a1000200041186a2006290300370000200041106a2005290300370000200041086a20042903003700002000200229031037000002402007450d002001102a0b200241306a24000f0b200141011037000b1031000ba80301047f230041f0006b2202240002400240411010282203450d00200341086a41002900c6f042370000200341002900bef042370000200341104120102c2203450d0120032001360010200241086a41186a22014200370300200241086a41106a22044200370300200241086a41086a220542003703002002420037030820034114200241086a1000200241306a41186a2001290300370300200241306a41106a2004290300370300200241306a41086a2005290300370300200220022903083703302003102a200241086a200241306a412010a703200241d0006a41086a200241116a290000370300200241d0006a41106a2203200241196a290000370300200241d0006a41186a2201200241216a290000370300200220022900093703500240024020022d00084101460d0020004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b20002002290350370000200041186a2001290300370000200041106a2003290300370000200041086a200241d0006a41086a2903003700000b200241f0006a24000f0b411041011037000b412041011037000bd50c04077f017e027f017e230041b0016b22012400200141306a41086a220242003703002001420037033041afc5c2004111200141306a1008200141086a200229030037030020012001290330370300200141c0006a2001411010fd0120012d00402103200141106a41186a2204200141d9006a290000370300200141106a41106a2205200141c0006a41116a290000370300200141106a41086a2206200141c9006a290000370300200120012900413703100240024020034101470d0020002001290310370000200041186a2004290300370000200041106a2005290300370000200041086a20062903003700000c010b200141c0006a41086a220342003703002001420037034041b1f0c200410d200141c0006a1008200220032903003703002001200129034037033020014100360240200141306a4110200141c0006a1006210202400240024020012802402203417f460d002002450d002001200336021420012002360210200141c0006a200141106a107620012802402207450d02200129024421082003450d012002102a0c010b41042107420021080b20072008422088a7220941246c6a2104200721020240024002400240034002400240200420026b41ed00490d0003400240200222032d00004101470d00200341246a210a200341106a2105200341086a2106200341016a21020c030b0240200341246a2d00004101470d00200341c8006a210a200341346a21052003412c6a2106200341256a21020c030b0240200341c8006a2d00004101470d00200341ec006a210a200341d8006a2105200341d0006a2106200341c9006a21020c030b0240200341ec006a2d00004101470d0020034190016a210a200341fc006a2105200341f4006a2106200341ed006a21020c030b200420034190016a22026b41ec004b0d000b20034190016a21020b20022004460d020240034020022d00004101460d012004200241246a2202460d040c000b0b200241246a210a200241106a2105200241086a2106200241016a21020b200228000021022006280200210320012005280200360214200120033602100240200241c28289aa04460d00200a21020c010b0b200141c0006a200141106a10ba0220012d004022024102460d00200141a4016a28020021062001280244210a4200210b200141306a41086a220342003703002001420037033041c785c2004112200141306a1008200141c0006a41086a20032903003703002001200129033037034020014100360210200141c0006a4110200141106a100621050240024020012802102203417f460d002001200336023420012005360230200141106a200141306a106d20012802102204450d052001290214210b2003450d012005102a0c010b410121040b410021030240200a200620024101711b2202200b422088a74f0d00200420024105746a2202450d00200141106a41186a200241186a290000370300200141106a41106a200241106a290000370300200141106a41086a200241086a29000037030020012002290000370310410121030b0240200ba7450d002004102a0b20030d010b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b200141c0006a41186a2202200141106a41186a290300370300200141c0006a41106a2203200141106a41106a290300370300200141c0006a41086a2204200141106a41086a29030037030020012001290310370340200141306a41086a220542003703002001420037033041afc5c2004111200141306a1008200141086a2005290300370300200120012903303703002001411036023420012001360230200141c0006a200141306a10ff01200041186a2002290300370000200041106a2003290300370000200041086a2004290300370000200020012903403700000b02402009450d00200941246c21032007210203400240024020022d0000220441034b0d0002400240024020040e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022003415c6a22030d000b0b2008a7450d022007102a0c020b41c4d1c30041332001419cd9c3001038000b41c4d1c30041332001419cd9c3001038000b200141b0016a24000b860c07057f017e047f027e037f027e047f230041c0006b22012400200141106a41086a220242003703002001420037031041f09cc600411e200141106a1008200141086a2203200229030037030020012001290310370300200141106a200110de03200128021021042001280214210520012903182106200028020821072000280204210820002802002109200242003703002001420037031041a5afc4004116200141106a100820032002290300370300200120012903103703002001410036021020014110200141106a100621000240024002400240024002400240024020012802102202417f460d002000450d002001200236023420012000360230200141106a200141306a106d2001280210220a450d022001290214210b2002450d012000102a0c010b4101210a4200210b0b2006420020051b210c2004410020051b21042005410420051b210d02402007450d002009200741246c6a210e200a200b422088a74105746a21032009210203402002280220210f200241086a2900002106200241106a290000211020022900002111200141106a41186a200241186a290000370300200141106a41106a2010370300200141106a41086a200637030020012011370310200241246a2102200a2105410021000240024003400240200320056b41e0004b0d0020052003460d030340200141106a2005460d0320002005200141106a4120109c0522074100476a21002007450d032003200541206a2205470d000c040b0b200141106a2005460d0120002005200141106a4120109c0522074100476a21002007450d01200541206a2207200141106a460d0120002007200141106a4120109c0522074100476a21002007450d01200541c0006a2207200141106a460d0120002007200141106a4120109c0522074100476a21002007450d01200541e0006a2207200141106a460d0120054180016a210520002007200141106a4120109c0522074100476a210020070d000b0b2004200f6a22072004490d000240200041016a2204200c422088a722054d0d000240200ca7221220056b20042005200420054b1b221320056b22044f0d00200520046a22142005490d0a201241017422152014201520144b1b221441ffffffff03712014470d0a201441027422154100480d0a0240024020120d0020151028210d0c010b200d20124102742015102c210d0b200d450d062014ad210c0b200d20054102746a21120240024020044102490d002012410020132005417f736a22044102741099051a200d200520136a20056b4102746a417c6a2112200420056a21050c010b2004450d010b20124100360200200541016a21050b200520004d0d05200d20004102746a22002000280200200f6a360200200c42ffffffff0f832005ad42208684210c200721040b2002200e470d000b0b02402008450d002009102a0b0240200ba7450d00200a102a0b200141106a41086a220542003703002001420037031041f09cc600411e200141106a1008200141086a20052903003703002001200129031037030002400240200d0d002001411010090c010b2001410036021820014201370310410410282205450d042005200436000020014284808080c00037021420012005360210200c422088a72205200141106a10b4010240024020050d002001280218210420012802142103200128021021000c010b2005410274210f4100200128021822056b210220012802142103200d210703402007280200210a02400240200320026a4104490d00200128021021000c010b200541046a22002005490d09200341017422042000200420004b1b22044100480d090240024020030d002004102821000c010b200128021020032004102c21000b2000450d082001200436021420012000360210200421030b200741046a21072001200541046a2204360218200020056a200a3600002002417c6a210220042105200f417c6a220f0d000b0b200ca721052001411020002004100702402003450d002000102a0b2005450d00200d102a0b200141c0006a24000f0b41c4d1c3004133200141386a419cd9c3001038000b201541041037000b41ac9bc600200020051034000b410441011037000b200441011037000b1031000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccd1c5003602002000410436021c200041c4d1c5003602182000200041186a3602102000419896c400103e000ba70101047f230041206b22002400200041106a41086a2201420037030020004200370310419499c6004114200041106a1008200041086a200129030037030020002000290310370300410021022000410036021020004110200041106a100621010240024020002802102203417f460d002001450d0020034104490d01200128000021022001102a0b200041206a240020020f0b41c4d1c3004133200041106a419cd9c3001038000b9d0401067f230041d0006b220324000240024002400240411b10282204450d00200441176a41002800d89646360000200441106a41002900d19646370000200441086a41002900c99646370000200441002900c196463700002004411b4136102c2204450d012004200136001b200341306a41186a22014200370300200341306a41106a22054200370300200341306a41086a22064200370300200342003703302004411f200341306a1000200341086a41186a22072001290300370300200341086a41106a2005290300370300200341086a41086a2006290300370300200320032903303703082004102a412010282204450d0220042003290308370000200441186a2007290300370000200441106a200341086a41106a2205290300370000200441086a200341086a41086a22062903003700002003200236022c20014200370300200341306a41106a22024200370300200341306a41086a22084200370300200342003703302003412c6a4104200341306a1000200720012903003703002005200229030037030020062008290300370300200320032903303703082004412041c000102c2204450d0320042003290308370020200441386a200341206a290300370000200441306a2005290300370000200441286a2006290300370000200042c0808080800837020420002004360200200341d0006a24000f0b411b41011037000b413641011037000b412041011037000b41c00041011037000bcb0201047f230041d0006b220324002003410036022820012002200341286a1006210402400240024020032802282205417f460d0020040d010b200041003a00000c010b41002101200341003a00480340024020052001470d000240200141ff0171450d00200341003a00480b41c4d1c3004133200341286a419cd9c3001038000b200341286a20016a200420016a2d00003a00002003200141016a22023a00482002210120024120470d000b200341086a41186a2201200341286a41186a290300370300200341086a41106a2202200341286a41106a290300370300200341086a41086a2206200341286a41086a2903003703002003200329032837030802402005450d002004102a0b20002003290308370001200041013a0000200041196a2001290300370000200041116a2002290300370000200041096a20062903003700000b200341d0006a24000bec0202047f017e230041d0006b22022400024002400240410f10282203450d00200341076a4100290092b4433700002003410029008bb4433700002003410f411e102c2203450d012003200136000f200241286a41186a22014200370300200241286a41106a22044200370300200241286a41086a220542003703002002420037032820034113200241286a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903283703002003102a2002410036022820024120200241286a100621010240024020022802282203417f460d002002200336022420022001360220200241286a200241206a106d20022802282204450d04200229022c210602402003450d002001102a0b20002006370204200020043602000c010b20004100360208200042013702000b200241d0006a24000f0b410f41011037000b411e41011037000b41c4d1c3004133200241c8006a419cd9c3001038000bdf0301017f024002400240024002400240410110282202450d00200220002d00003a0000200241014102102c2202450d01200220002d00013a0001200241024104102c2202450d02200220002d00023a0002200220002d00033a0003200241044108102c2202450d03200220002d00043a0004200220002d00053a0005200220002d00063a0006200220002d00073a0007200241084110102c2202450d04200220002d00083a0008200220002d00093a0009200220002d000a3a000a200220002d000b3a000b200220002d000c3a000c200220002d000d3a000d200220002d000e3a000e200220002d000f3a000f200241104120102c2202450d05200220002d00103a0010200220002d00113a0011200220002d00123a0012200220002d00133a0013200220002d00143a0014200220002d00153a0015200220002d00163a0016200220002d00173a0017200220002d00183a0018200220002d00193a0019200220002d001a3a001a200220002d001b3a001b200220002d001c3a001c200220002d001d3a001d200220002d001e3a001e200220002d001f3a001f200128020020012802042002412010072002102a0f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000bf54606077f027e0f7f047e117f017e230041800a6b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341cc026a4101360200200342013702bc02200341ccd1c5003602b802200341043602b406200341c4d1c5003602b0062003200341b0066a3602c802200341b8026a41e893c400103e000b200141e0006a2802002104200341b0066a200141086a41d800109a051a20034198056a200141fc006a28020036020020034190056a200141f4006a29020037030020034180056a41086a200141ec006a2902003703002003200141e4006a29020037038005024020022d000120022d000072450d0041a39fc600210541112104410121060c120b200341b8026a10f70302402003280290032004490d0041f893c400210541352104410121060c120b200341b8026a41086a41033a00002003410c3a00b802200341b8026a410c6a20043602004100210541014100200341b8026a10cc01200341b8026a200341b0066a41d800109a051a2003419c036a20034180056a41086a290300370200200341a4036a20034180056a41106a290300370200200341ac036a20034180056a41186a2802003602002003200436029003200320032903800537029403200341c0086a41086a22024200370300200342003703c00841c0fec5004118200341c0086a100820034180046a41086a2002290300370300200320032903c00837038004200341003602c808200342013703c008200341b8026a200341c0086a10ee0120032802c408210220034180046a411020032802c008220420032802c80810072002450d0f2004102a0c0f0b2001410c6a2802002107200141086a280200210841042104200141046a2802002109200141106a290300210a2002411a6a290100210b200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d00002118200241046a2d00002119200241026a2f0100211a0240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f01002105200241086a2d00002102410021060c010b4101210641002102410021050b200541ffff0371410874200241187472200441ff017172210202402006450d0041ea9fc6002105410f210402400240024002400240024020020e0700010203040513000b20174108742018722016411874722105201441087420157220134118747221040c120b41dc9fc6002105410e21040c110b41d09fc6002105410c21040c100b41c79fc6002105410921040c0f0b41b49fc6002105411321040c0e0b41a39fc6002105411121040c0d0b2003200b370398042003200c3a0097042003200d3a0096042003200e3b0194042003200f3a009304200320103a009204200320113b019004200320123a008f04200320133a008e04200320143b018c04200320153a008b04200320163a008a04200320173b018804200320183a0087042003200236008304200320193a0082042003201a3b018004200341e8006a10f603024002402003290368220b200341e8006a41086a290300221b8450450d004200211c4200211d0c010b200341c8006a201b4200200a4200109f05200341d8006a200b4200200a4200109f05200341386a42004200200b4200109f0502402003290350200329034084420052200341e0006a290300221c200329034820032903387c7c221d201c5472450d0041a6b5c0002105412721040c0e0b2003290358211c0b200341b8026a20034180046a201c201d4108109802024020032802b8024101470d0020032802c002210420032802bc0221050c0d0b200341c8026a290300211c20032903c002211d200341b8026a10f703200341286a20032903b80242002007ad4200109f050240200a427f200329032820032903304200521b7d221e200a562205450d0041fdbfc2002102412c21040c0b0b200341b0066a20092007200341b8026a10f802024020032802b0064101470d00200341b8066a280200210420032802b40621020c0b0b200341c8096a41186a2206200341b0066a410472220241186a280200360200200341c8096a41106a2216200241106a290200370300200341c8096a41086a2217200241086a290200370300200320022902003703c80920034180056a41186a2213420037030020034180056a41106a2214420037030020034180056a41086a2215420037030020034200370380052009200720034180056a1000200341da016a221820032d0082053a000020034198026a41086a220c20034180056a41136a290000370300200341a5026a220d2013290000370000200320032f0180053b01d8012003200329008b053703980220032800830521022003280087052104200341e0076a41186a2006280200360200200341e0076a41106a2016290300370300200341e0076a41086a2017290300370300200320032903c8093703e007200320043600b706200320023600b306200320182d00003a00b206200320032f01d8013b01b006200341b0066a41136a200c290300370000200341b0066a41186a200d29000037000020032003290398023700bb06411410282206450d03200641002900ddd843370000200641106a41002800edd843360000200641086a41002900e5d84337000020034294808080c0023702fc01200320063602f8012003200341f8016a36028005200341b0066a20034180056a10c80120032802f8012106200328028002211620134200370300201442003703002015420037030020034200370380052006201620034180056a1000200341c0086a41186a2013290300370300200341c0086a41106a2014290300370300200341c0086a41086a201529030037030020032003290380053703c008024020032802fc01450d0020032802f801102a0b200341203602b4062003200341c0086a3602b006200341e0076a200341b0066a10f9020240200341f0076a280200450d0020032802ec07102a0b200341c3066a20034198026a41086a290300370000200341b0066a41186a20034198026a410d6a2900003700002003200341da016a2d00003a00b206200320032f01d8013b01b006200320043600b706200320023600b30620032003290398023700bb06411510282206450d04200641002900c8d8433700002006410d6a41002900d5d843370000200641086a41002900d0d84337000020034295808080d0023702e407200320063602e0072003200341e0076a36028005200341b0066a20034180056a10c80120032802e007210620032802e807211320034180056a41186a2214420037030020034180056a41106a2215420037030020034180056a41086a2216420037030020034200370380052006201320034180056a1000200341c0086a41186a2014290300370300200341c0086a41106a2015290300370300200341c0086a41086a201629030037030020032003290380053703c008024020032802e407450d0020032802e007102a0b200341203602b4062003200341c0086a3602b00620092007200341b0066a10cb0102402008450d002009102a0b200341f8016a41026a200341d8016a41026a2d000022063a000020034180056a41086a221320034198026a41086a29030037030020034180056a410d6a220820034198026a410d6a290000370000200320032f01d80122093b01f801200320032903980237038005200341b0066a41086a41023a0000200341b9066a20093b0000200341bb066a20063a0000200341c0066a20043602002003410c3a00b006200341b0066a410c6a2002360200200341c4066a200329038005370200200341cc066a2013290300370200200341d1066a20082900003700004100211341014100200341b0066a10cc010c0b0b200141c0006a290300210b200141386a290300211d2002411a6a290100211c200241196a2d0000211f200241186a2d00002120200241166a2f01002121200241156a2d00002122200241146a2d00002123200241126a2f01002124200241116a2d00002125200241106a2d000021262002410e6a2f010021272002410d6a2d000021282002410c6a2d000021292002410a6a2f0100212a200241096a2d0000212b41042104200241046a2d0000212c200241026a2f0100212d200141306a280200212e2001412c6a2802002108200141286a28020021092001411d6a290000210a2001411c6a2d000021142001411b6a2d00002115200141196a2f00002116200141186a2d00002117200141176a2d00002118200141156a2f0000210c200141146a2d0000210d200141136a2d0000210e200141116a2f0000210f200141106a2d000021102001410f6a2d000021112001410d6a2f000021122001410c6a2d00002119200141086a2802002105200141076a2d0000211a200141056a2f00002107200141046a2d0000212f200141c8006a290300211b0240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f01002106200241086a2d00002102410021130c010b4101211341002102410021060b200641ffff0371410874200241187472200441ff01717221060240024002402013450d0041ea9fc6002105410f21040240024002400240024020060e0700060102030410000b202a410874202b722029411874722105202741087420287220264118747221040c0f0b41d09fc6002105410c21040c0e0b41c79fc6002105410921040c0d0b41b49fc6002105411321040c0c0b41a39fc6002105411121040c0b0b202f41ff01714101470d01200341b8026a200541067610fe0120032802b80221040240024020032802c0022005413f7122024b0d00410021020c010b200420024105746a2202290018210a20022d0017211420022d0016211520022f0014211620022d0013211720022d0012211820022f0010210c20022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d000721192002280003210520022d0002211a20022f00002107410121020b024020032802bc02450d002004102a0b20020d010b41dc9fc6002105410e21040c090b2003201c3703c8062003201f3a00c706200320203a00c606200320213b01c406200320223a00c306200320233a00c206200320243b01c006200320253a00bf06200320263a00be06200320273b01bc06200320283a00bb06200320293a00ba062003202a3b01b8062003202b3a00b706200320063600b3062003202c3a00b2062003202d3b01b0062003200a3703d002200320143a00cf02200320153a00ce02200320163b01cc02200320173a00cb02200320183a00ca022003200c3b01c8022003200d3a00c7022003200e3a00c6022003200f3b01c402200320103a00c302200320113a00c202200320123b01c002200320193a00bf02200320053600bb022003201a3a00ba02200320073b01b8022003202e3602c808200320083602c408200320093602c00820034180056a200341b0066a200341b8026a201d200b201b200341c0086a10f5030240024002402003280280054101460d00024020034188056a280200450d00200328028405102a0b41002113410121060c010b4101210620032802840522050d01410021130b41012108410021050c110b20034188056a2802002104024020034190056a280200450d002003418c056a280200102a0b41002113410121080c100b200141386a290300211c200141306a290300211b200141c0006a290300210a200341d8016a41186a200141196a290000370300200341d8016a41106a200141116a290000370300200341d8016a41086a200141096a290000370300200320012900013703d8012002411a6a290100210b200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021092002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d0000211841042104200241046a2d00002119200241026a2f0100211a2001412c6a2802002107200141286a2802002106200141246a28020021080240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f01002105200241086a2d00002102410021130c010b4101211341002105410021020b200541ffff0371410874200441ff017172200241187472210202402013450d00410f210441ea9fc6002105024002400240024002400240024020020e0700010203040506000b20174108742018722016411874722105201441087420157220094118747221040c050b410e210441dc9fc60021050c040b410c210441d09fc60021050c030b4109210441c79fc60021050c020b4113210441b49fc60021050c010b4111210441a39fc60021050b2006450d072008102a0c070b2003200b370390022003200c3a008f022003200d3a008e022003200e3b018c022003200f3a008b02200320103a008a02200320113b018802200320123a008702200320093a008602200320143b018402200320153a008302200320163a008202200320173b018002200320183a00ff01200320023600fb01200320193a00fa012003201a3b01f801200341c8016a10f603024002400240024020032903c801220b200341c8016a41086a29030022308450450d004200211e4200211d0c010b200341a8016a20304200200a4200109f05200341b8016a200b4200200a4200109f0520034198016a42004200200b4200109f05024020032903b00120032903a00184420052200341c0016a290300221e20032903a8012003290398017c7c221d201e5472450d004127210441a6b5c00021050c020b20032903b801211e0b200341b8026a200341f8016a201e201d410810980220032802b8024101470d0120032802c002210420032802bc0221050b2006450d072008102a0c070b200341b8026a41106a290300211e20032903c002211d20034198026a41186a20303703002003200b3703a8022003200a3703a0022003200a37039802200341b8026a10f703200341b8036a4200370300200341e8036a4200370300200341d8036a4200370300200341c8036a42003703002003428080e983b1de163703b00320034280a094a58d1d3703e00320034280a094a58d1d3703d00320034280a094a58d1d3703c003200342808880808080103703f0032003200341b8026a3602f8032003200341b8026a3602fc03200341b0066a41186a2204200341f8016a41186a290300370300200341b0066a41106a2202200341f8016a41106a290300370300200341b0066a41086a2205200341f8016a41086a290300370300200320032903f8013703b00610a003210a1098012113200341b8046a420037030020034180046a412c6a41d0b5c00036020020034180046a41286a4101360200200341a0046a42003703002003419c046a41f8b9c000360200200341d8046a2005290300370300200341e0046a2002290300370300200341e8046a200429030037030020034200370388042003428080808080013703b004410021122003410036029804200320032903b0063703d0042003200341fc036a3602c8042003200341f8036a3602c4042003200341b8026a3602c004200320133602cc042003200a37038004200320073602880520032006360284052003200836028005200341b0066a20034180046a201b201c20034198026a200341d8016a20034180056a10b50120032802b0064101470d0420022802002207410876212f200341bc066a2802002126200341b0066a41086a280200210420032802b406211a41012112410121190c050b200141216a2d0000210620034180056a41186a200141196a29000037030020034180056a41106a200141116a29000037030020034180056a41086a200141096a290000370300200320012900013703800541ad94c400210541e900210420022d00000d0c200228000121130240200641ff01714101460d00201341ff01714101470d0d20134118762104201341087621052002411a6a290100210a200241196a2d00002106200241186a2d00002113200241166a2f01002108200241156a2d00002109200241146a2d00002114200241126a2f01002115200241116a2d00002116200241106a2d000021172002410e6a2f010021182002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241056a2800002102410221100c030b201341ff01714102470d0c2001413a6a290000210a200141396a2d00002106200141386a2d00002113200141366a2f00002108200141356a2d00002109200141346a2d00002114200141326a2f00002115200141316a2d00002116200141306a2d000021172001412e6a2f000021182001412d6a2d0000210c2001412c6a2d0000210d2001412a6a2f0000210e200141296a2d0000210f200141256a2800002102200141246a2d00002104200141226a2f00002105410021100c020b411441011037000b411541011037000b2003200a3703c806200320063a00c706200320133a00c606200320083b01c406200320093a00c306200320143a00c206200320153b01c006200320163a00bf06200320173a00be06200320183b01bc062003200c3a00bb062003200d3a00ba062003200e3b01b8062003200f3a00b706200320023600b306200320043a00b206200320053b01b006200341b8026a20034180056a2010410010c20120032d00b8022102024020032d00c0020d00200341dc026a280200450d00200341d8026a280200102a0b0240200241ff01714101470d00200341b8026a200341b0066a42808086bdbacdd21a420010a502024020032802b8024101470d0020032802c002210420032802bc022105410121060c0c0b200320032903c0023703c0082003200341c8026a2903003703c8082003200341c0086a3602800420034180046a109c010b410021050c080b200341e0066a2802002207410876212f200341b0066a412c6a2802002126200341b0066a41286a2802002104200341d4066a280200211a41012119200741ff01710d00200341b0066a41086a200341a0046a29030037030020034180056a41086a200341bc066a28020036020020032003290398043703b006200320032902b40637038005200341f8096a20034180056a1092014100210741002112410021190b200341f8006a20032903a802200341b0026a29030020032903a002220a4200109f05200329039802200a7d10e50320034188016a200341f8016a2003290378200341f8006a41086a29030010d001200341c0066a201e20034188016a41086a290300220b7d201d200329038801220a54ad7d200b201e7d200a201d54ad7d200a201d58200b201e58200b201e5122021b22051b221c3703002003201d200a7d200a201d7d20051b221b3703b8062003200a201d56200b201e5620021b2202ad220a3703b00641012105024020020d002003201b370380052003201c37038805200320034180056a3602c008200341c0086a109d014100210520032903b006210a0b200341b0066a41086a210202400240200a4200520d002005450d01200320023602800520034180056a109d010c010b200320023602800520034180056a109c010b20032802bc04210520032802b8042106200320032802b40422023602f804200320063602f404200320023602f00420032002200541b0016c6a22163602fc0402402005450d00200341c0086a410172210e200341e7076a210f200341e0076a4102722113200341b0066a41106a2110200341d8066a210d20034194076a2118200341f1066a2108200341d1066a2109200341b0066a4101722117200341a8076a2111034020022d0000210520034180056a200241016a41af01109a051a0240024020054103460d00200320053a00b006201720034180056a41af01109a052106024002400240024020050e03000102000b20032802b806211520032802bc06210620032802b4062105200f201041d800109a051a2003410c3a00c008200e200341e0076a41df00109a051a20052006200341c0086a10cc01410121064100211402402015450d002005102a0b410021150c020b20032f00b106210520032d00b306211420032802b406211520032d00b806210c20032900b906210a20032900c106210b20032900c906211d200341c0086a200d418801109a051a20132006290000370000201341086a200641086a290000370000201341106a200641106a290000370000201341186a200641186a29000037000020034180023b01e007200341c8096a200341c0086a200341e0076a10f401200320032d00d0094102463a00e9082003201d3700e1082003200b3700d9082003200a3700d1082003200c3a00d008200320153602cc08200320143a00cb08200320053b00c908200341043a00c8082003410c3a00c008410021064101211441014100200341c0086a10cc01410021150c010b2011290300210a20032903a007210b200341c8096a41186a200641186a290000370300200341c8096a41106a200641106a290000370300200341c8096a41086a200641086a290000370300200320062900003703c809200341e0076a41186a200941186a290000370300200341e0076a41106a200941106a290000370300200341e0076a41086a200941086a290000370300200320092900003703e007200341c0086a41186a200841186a290000370300200341c0086a41106a200841106a290000370300200341c0086a41086a200841086a290000370300200320082900003703c008200341e8096a41086a201841086a280200360200200320182902003703e809200341c8096a200341e0076a200341c0086a200b200a200341e8096a10f8034101211441012106410121150b024020032d00b006220541014b0d000240024020050e020001000b2014450d03024020032802b806450d0020032802b406102a0b20032d00c0064105490d0320032802e806450d0320032802e406102a0c030b2006450d02200d106a0c020b201520032802980745720d01200328029407102a0c010b2003200241b0016a3602f8040c020b200241b0016a22022016470d000b200320163602f8040b200341f0046a10690240200328028c042202450d0020034190046a280200450d002002102a0b02402019450d0020034180046a411c6a280200210220032802a40421080240024020032802a00422060d00200221050c010b2006211320022105034020052802880b21052013417f6a22130d000b0340200220022f01064102746a41880b6a28020021022006417f6a22060d000b0b200341b0066a411c6a20022f0106360200200341c8066a4100360200200341c4066a2002360200200320083602d006200341003602c006200342003703b806200320053602b406200341003602b006200341b0066a109b010b024020120d0041002105024020040d00410021040c020b201a102a0c010b0240201a0d00410021050c010b0240202f410874200741ff017172450d002026102a0b201a21050b4100210841012106410121130c080b41002113410121062008450d032009102a410121080c070b410121132008450d002009102a0b200341086a200b201b4200201e20051b221e4200109f05200a201e7d10e503200341186a20034180046a2003290308200341086a41086a29030010d001200341c0066a201c200341186a41086a290300220b7d201d2003290318220a54ad7d200b201c7d200a201d54ad7d200a201d58200b201c58200b201c5122051b22061b221b3703002003201d200a7d200a201d7d20061b221e3703b8062003200a201d56200b201c5620051b2205ad220a3703b00641012106024020050d002003201e3703c0082003201b3703c8082003200341c0086a3602e007200341e0076a109d014100210620032903b006210a0b200341b0066a41086a210502400240200a4200520d002006450d01200320053602c008200341c0086a109d010c010b200320053602c008200341c0086a109c010b41002106410021052013450d04200221050c040b41012113410021062008450d002009102a0b410121080c030b0b410121060b41012113410121080b024020012d0000417e6a220241024b0d00024002400240024020020e03000102000b2006450d03200141086a280200450d03200141046a280200102a0c030b20130d010c020b2008450d01200141286a280200450d01200141246a280200102a0c010b2001412c6a280200450d00200141286a280200102a0b2000200436020420002005360200200341800a6a24000be90604057f027e067f027e23004190016b2202240041002103200241003a008801200128020421040240024003402004450d01200241e8006a20036a200128020022052d00003a000020012004417f6a22043602042001200541016a3602002002200341016a22063a0088012006210320064120470d000b200241086a41086a200241e8006a41086a290300370300200241086a41106a200241e8006a41106a290300370300200241086a41186a200241e8006a41186a29030037030020022002290368370308024020044110490d00200541096a2900002107200529000121082001200441706a22093602042001200541116a36020041002103200241003a008801416f210a0340024020092003470d000240200341ff0171450d00200241003a0088010b200042013703000c040b200241e8006a20036a200520036a220641116a2d00003a00002001200420036b416f6a3602042001200641126a3602002002200341016a22063a008801200a417f6a210a2006210320064120470d000b200241286a41086a220b200241e8006a41086a2203290300370300200241286a41106a220c200241e8006a41106a220a290300370300200241286a41186a220d200241e8006a41186a2209290300370300200220022903683703280240200420066b220441706a4110490d002003200241086a41086a290300370300200a200241086a41106a2903003703002009200241086a41186a290300370300200241c8006a41086a220e200b290300370300200241c8006a41106a220b200c290300370300200241c8006a41186a220c200d290300370300200520066a220641116a290000210f200641196a29000021102001200441606a3602042001200641216a3602002002200229030837036820022002290328370348200041206a2010370300200041186a200f370300200041106a200737030020002008370308200041286a2002290368370300200041306a2003290300370300200041386a200a290300370300200041c0006a2009290300370300200041c8006a2002290348370300200041d0006a200e290300370300200041d8006a200b290300370300200041e0006a200c290300370300200042003703000c030b200042013703000c020b200042013703000c010b0240200341ff0171450d00200241003a0088010b200042013703000b20024190016a24000ba80302067f027e230041d0006b2204240002400240411810282205450d00200541002900e3e140370000200541106a41002900f3e140370000200541086a41002900ebe140370000200442988080808003370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b2001200a2002200a200a200256200b200356200b2003511b22051b22027d200b2003200b20051b22037d200a200254ad7d1090022000200337030820002002370300200441d0006a24000f0b411841011037000b41c4d1c3004133200441306a419cd9c3001038000be40602067f047e230041e0006b22042400024002400240024002400240411410282205450d00200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370234200420053602302001200441306a108f012004280238210520042802302106200441c0006a41186a22074200370300200441c0006a41106a22084200370300200441c0006a41086a220942003703002004420037034020062005200441c0006a1000200441106a41186a2007290300370300200441106a41106a2008290300370300200441106a41086a20092903003703002004200429034037031002402004280234450d002004280230102a0b20044100360240200441106a4120200441c0006a100621050240024020042802402206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b0240200a2002542205200b200354200b2003511b450d00418991c1002105411521010c060b200441086a20014104200a20027d220a200b20037d2005ad7d220b10bc01200428020822050d04411810282205450d02200541002900e3e140370000200541106a41002900f3e140370000200541086a41002900ebe140370000200442988080808003370234200420053602302001200441306a108f012004280238210520042802302106200441c0006a41186a22074200370300200441c0006a41106a22084200370300200441c0006a41086a220942003703002004420037034020062005200441c0006a1000200441106a41186a2007290300370300200441106a41106a2008290300370300200441106a41086a20092903003703002004200429034037031002402004280234450d002004280230102a0b20044100360240200441106a4120200441c0006a100621050240024020042802402206417f470d004200210c4200210d0c010b20064110490d04200541086a290000210d2005290000210c2005102a0b2001200c20027c2202200d20037c2002200c54ad7c1090022001200a200b108f02410021050c050b411441011037000b41c4d1c3004133200441c0006a419cd9c3001038000b411841011037000b41c4d1c3004133200441c0006a419cd9c3001038000b200428020c21010b2000200136020420002005360200200441e0006a24000bd9140a057f017e067f037e037f017e017f027e077f057e23002204210520044180026b4160712204240002400240200141ffffff3f712001470d0020014105742206417f4c0d0002400240024020060d00410121070c010b200610282207450d010b410021084100210602402001450d002001410574210820072106034020062000290000370000200641186a200041186a290000370000200641106a200041106a290000370000200641086a200041086a290000370000200641206a2106200041206a2100200841606a22080d000b200141057441606a41057641016a2106200121080b20042006360218200420083602142004200736021020072006410041202006676b10c40242002109200441b0016a41086a22004200370300200442003703b00141cf96c300411d200441b0016a1008200441e0016a41086a2000290300370300200420042903b0013703e001200441003602b001200441e0016a4110200441b0016a1006210602400240024020042802b0012200417f460d0020042000360294012004200636029001200441b0016a20044190016a106d20042802b001220a450d0220042902b40121092000450d012006102a0c010b4101210a0b2009422088a72200450d032000410574210b200441e0016a410c6a210c200441e0016a411472210d200441e0016a410872210e200441c0006a410c72210f200a210002400340200041086a2900002110200041106a290000211120002900002112200441206a41186a2213200041186a290000370300200441206a41106a22142011370300200441206a41086a22152010370300200420123703200240024002400240411a10282206450d00200641002900ec96432216370000200641186a41002f0084974322173b0000200641106a41002900fc96432218370000200641086a41002900f4964322193700002004429a808080a0033702b401200420063602b0012004200441b0016a3602e001200441206a200441e0016a10c80120042802b001210720042802b801211a200441e0016a41186a22014200370300200441e0016a41106a22064200370300200441e0016a41086a22084200370300200442003703e0012007201a200441e0016a100020044190016a41186a221b200129030037030020044190016a41106a221c200629030037030020044190016a41086a221a2008290300370300200420042903e00137039001024020042802b401450d0020042802b001102a0b200441003602e00120044190016a4120200441e0016a1006211d20042802e0012207417f460d02200420073602642004201d360260200441e0016a200441e0006a10b30320042802e801221e450d01200441b0016a41086a221f200c41086a290200370300200441b0016a41106a2220200c41106a2802003602002004200c2902003703b00120042903e001211002402007450d00201d102a0b200f20042903b00122113702002006202028020022073602002008201f2903002212370300200f41086a2012370200200f41106a2007360200200420113703e001200420103703400c030b411a41011037000b41c4d1c3004133200441d0016a419cd9c3001038000b2006200441b0016a41106a2802003602002008200441b0016a41086a290300370300200420042903b0013703e0014100211e0b2004201e360248200441003602e80120042903582112200420042903f801222137035820042903502122200420042903f001222337035020042903402124200420042903e001221137034020042903482110200420042903e80122253703482025a72107024002402010a7221d0d002025211020232122202121120c010b200420243703e001200420103703e801200420223703f001200420123703f8012004201d2022a74105746a3602bc012004201d3602b80120042010422088a73602b4012004201d3602b0012004200441106a3602c00120044190016a200441b0016a108401200e41086a201a280200360200200e20042903900137020020042022422088a7221d2012422088a74105746a3602bc012004201d3602b80120042012a73602b4012004201d3602b0012004200441106a3602c00120044190016a200441b0016a108401200d41086a201a280200360200200d20042903900137020020042903e801211020042903e001211120042903f801211220042903f001212202402007450d002021a7211d02402025422088a7450d002007102a0b201d450d002023422088a7102a0b200420113703402004201037034820042022370350200420123703582010a721070b2004201137036020042010370368200420223703702004201237037802400240024020070d00200441b0016a41186a2013290300370300200441b0016a41106a2014290300370300200441b0016a41086a2015290300370300200420042903203703b001411a10282207450d0220072016370000200741186a20173b0000200741106a2018370000200741086a20193700002004429a808080a0033702d401200420073602d0012004200441d0016a3602e001200441b0016a200441e0016a10c80120042802d001210720042802d801211d200142003703002006420037030020084200370300200442003703e0012007201d200441e0016a1000201b2001290300370300201c2006290300370300201a2008290300370300200420042903e00137039001024020042802d401450d0020042802d001102a0b20044190016a412010090c010b200441b0016a41186a2013290300370300200441b0016a41106a2014290300370300200441b0016a41086a2015290300370300200420042903203703b001411a10282207450d0320072016370000200741186a20173b0000200741106a2018370000200741086a20193700002004429a808080a0033702d401200420073602d0012004200441d0016a3602e001200441b0016a200441e0016a10c80120042802d001210720042802d801211d200142003703002006420037030020084200370300200442003703e0012007201d200441e0016a1000201b2001290300370300201c2006290300370300201a2008290300370300200420042903e00137039001024020042802d401450d0020042802d001102a0b200441203602e401200420044190016a3602e001200441e0006a200441e0016a10b4030b02402010a72206450d002012a7210802402010422088a7450d002006102a0b2008450d002022422088a7102a0b200041206a2100200b41606a220b0d010c060b0b411a41011037000b411a41011037000b41c4d1c3004133200441d0016a419cd9c3001038000b200641011037000b1036000b02402009a7450d00200a102a0b200441003602e801200442013703e0012003200441e0016a10b40102402003450d002003410574210003402002200441e0016a108f01200241206a2102200041606a22000d000b0b20042802e401210620042802e801210820042802e0012100200441b0016a41086a22014200370300200442003703b0014196f0c200411b200441b0016a1008200441e0016a41086a2001290300370300200420042903b0013703e001200441e0016a411020002008100702402006450d002000102a0b02402004280214450d002004280210102a0b200524000bb80901177f230041206b220424002002410020031b21052000410020011b2106200241206a200220031b2107200041206a200020011b2108200020014105746a2109200220034105746a210a4100210b4100210c4101210d4100210e4100210f41012110024002400340200b4101742111200b4105742112024002400240024002400340024020050d0020072113200d2114200c2115200b21160c040b2005210220072103200d2114200c2115200b2116201221172011211802400340024002402006450d0020022006460d06200220064120109c052213450d062013417f4c0d01200321072014210d2015210c2016210b200221050c080b200441186a2203200541186a290000370300200441106a2216200541106a290000370300200441086a2206200541086a290000370300200420052900003703000240200b200c470d00200b41016a2202200b490d0c200b41017422172002201720024b1b220c41ffffff3f71200c470d0c200c41057422024100480d0c02400240200b0d0020021028210d0c010b200d200b4105742002102c210d0b200d450d030b200d200b4105746a22022004290300370000200241186a2003290300370000200241106a2016290300370000200241086a200629030037000041002106410020072007200a4622021b2105201141026a2111201241206a2112200b41016a210b2007200741206a20021b21070c030b200441186a2213200241186a290000370300200441106a2219200241106a290000370300200441086a221a200241086a29000037030020042002290000370300024020162015470d00201641016a22022016490d0b20182002201820024b1b221541ffffff3f712015470d0b201541057422024100480d0b0240024020160d002002102821140c010b201420172002102c21140b2014450d040b201420176a22022004290300370000200241186a2013290300370000200241106a2019290300370000200241086a201a290300370000410020032003200a4622131b2102201841026a2118201741206a2117201641016a21162003200341206a20131b221321032002450d050c000b0b0b200241011037000b200241011037000b2014210d2015210c2016210b2003200341206a2003200a4622021b210741002008200820094622161b21064100200320021b21052008200841206a20161b21080c030b410021052006450d01201321072014210d2015210c2016210b0b200441186a2203200641186a290000370300200441106a2216200641106a290000370300200441086a2217200641086a290000370300200420062900003703000240200e200f470d00200e41016a2202200e490d04200e41017422062002200620024b1b220f41ffffff3f71200f470d04200f41057422024100480d0402400240200e0d002002102821100c010b2010200e4105742002102c21100b2010450d030b2010200e4105746a22022004290300370000200241186a2003290300370000200241106a2016290300370000200241086a201729030037000041002008200820094622021b2106200e41016a210e2008200841206a20021b21080c010b0b201420162000200110840202402015450d002014102a0b0240200f450d002010102a0b200441206a24000f0b200241011037000b1031000ba8ca0106017f027e057f017e217f0b7e230041e0046b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e0b000102030405060c0d0e0f000b20034184036a4101360200200342013702f402200341ccd1c5003602f002200341043602b404200341c4d1c5003602b0042003200341b0046a36028003200341f0026a41a0f8c100103e000b200141206a2903002104200141186a29030021052001410c6a2802002106200141086a2802002107200141146a2802002108200141106a28020021092001280204210a2002411a6a290100210b200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d0000211841042119200241046a2d0000211a200241026a2f0100211b0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d410021024100211c0b2003200b370380012003200c3a007f2003200d3a007e2003200e3b017c2003200f3a007b200320103a007a200320113b0178200320123a0077200320133a0076200320143b0174200320153a0073200320163a0072200320173b0170200320183a006f2003201a3a006a2003201b3b01682003201c41ffff0371410874200241187472201941ff017172221c36006b201d450d0e410f210241ea9fc60021190240024002400240024002400240201c0e0700010203040506000b200328006f2119200328007321020c050b410e210241dc9fc60021190c040b410c210241d09fc60021190c030b4109210241c79fc60021190c020b4113210241b49fc60021190c010b4111210241a39fc60021190b4100210c4101211d2007450d43200a102a0c430b200141206a2903002104200141186a29030021052001410c6a2802002106200141086a280200211b200141146a2802002108200141106a28020021092001280204210a2002411a6a290100210b200241196a2d0000210c200241186a2d00002107200241166a2f0100210d200241156a2d0000210e200241146a2d0000210f200241126a2f01002110200241116a2d00002111200241106a2d000021122002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002116200241096a2d0000211741042119200241046a2d00002118200241026a2f0100211a0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d410021024100211c0b2003200b3703e8022003200c3a00e702200320073a00e6022003200d3b01e4022003200e3a00e3022003200f3a00e202200320103b01e002200320113a00df02200320123a00de02200320133b01dc02200320143a00db02200320153a00da02200320163b01d802200320173a00d702200320183a00d2022003201a3b01d0022003201c41ffff0371410874200241187472201941ff017172221c3600d3020240201d450d00410f210241ea9fc6002119024002400240024002400240201c0e0700010203040548000b20032800d702211920032800db0221020c470b410e210241dc9fc60021190c460b410c210241d09fc60021190c450b4109210241c79fc60021190c440b4113210241b49fc60021190c430b4111210241a39fc60021190c420b20034188046a41186a200341d0026a41186a29030037030020034188046a41106a200341d0026a41106a29030037030020034188046a41086a200341d0026a41086a290300370300200320032903d00237038804410d10282202450d0e200241002900b0f841370000200241056a41002900b5f8413700002003428d808080d0013702f402200320023602f00220034188046a200341f0026a108f0120032802f802210220032802f0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341e8006a41186a201c290300370300200341e8006a41106a201d290300370300200341e8006a41086a200c290300370300200320032903b004370368024020032802f402450d0020032802f002102a0b200341003602f002200341e8006a4120200341f0026a1006211c20032802f002221d417f460d3f201c450d3f41002102200341003a009003024002400340201d2002460d01200341f0026a20026a201c20026a2d00003a00002003200241016a22193a0090032019210220194120470d000b200341b0046a41186a2202200341f0026a41186a290300370300200341b0046a41106a200341f0026a41106a290300370300200341b0046a41086a200341f0026a41086a290300370300200320032903f0023703b004201941ff0171411f4d0d01200341e0036a41086a2219200341c3046a290000370300200341e0036a410d6a220c2002290000370000200341e8016a41026a220720032d00b2043a0000200341a8026a41086a2019290300370300200341a8026a410d6a220d200c290000370000200320032f01b0043b01e801200320032900bb043703a80220032800b304211920032800b70421020240201d450d00201c102a0b200341b0046a41026a20072d00003a0000200341f0026a41086a200341a8026a41086a290300370300200341f0026a410d6a200d290000370000200320032f01e8013b01b004200320032903a8023703f0024101211c0c420b200241ff0171450d00200341003a0090030b41c4d1c3004133200341d8046a419cd9c3001038000b200141216a290000210b200141206a2d000021072001411d6a2f0000210d2001411c6a2d0000210e200141196a2f0000210f200141186a2d00002110200141156a2f00002111200141146a2d00002112200141116a2f00002113200141106a2d000021142001410c6a280200211c200141086a2d0000211e200141306a280200211f2001412c6a280200212020012d001f211520012d001b211620012d0017211720012d0013211820012d000b211a20012f0009211b200128020421212002411a6a2901002104200241196a2d00002122200241186a2d00002123200241166a2f01002124200241156a2d00002125200241146a2d00002126200241126a2f01002127200241116a2d00002128200241106a2d0000210a2002410e6a2f010021062002410d6a2d000021082002410c6a2d000021092002410a6a2f01002129200241096a2d0000212a41042119200241046a2d0000212b200241026a2f0100212c0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211d200241086a2d000021024100210c0c010b4101210c410021024100211d0b201d41ffff0371410874200241187472201941ff017172211d0240200c450d00410f210241ea9fc60021190240201d0e0700050607083e3f000b2029410874202a7220094118747221192006410874200872200a4118747221020c3e0b200320043703a002200320223a009f02200320233a009e02200320243b019c02200320253a009b02200320263a009a02200320273b019802200320283a0097022003200a3a009602200320063b019402200320083a009302200320093a009202200320293b0190022003202a3a008f022003201d36008b022003202b3a008a022003202c3b0188020240201e41ff01714101470d00200341f0026a201c41067610fe0120032802f00221190240024020032802f802201c413f7122024b0d00410021020c010b201920024105746a2202290018210b20022d0017210720022d0016211520022f0014210d20022d0013210e20022d0012211620022f0010210f20022d000f211020022d000e211720022f000c211120022d000b211220022d000a211820022f0008211320022d000721142002280003211c20022d0002211a20022f0000211b410121020b024020032802f402450d002019102a0b2002450d3c0b2003200b3703c002200320073a00bf02200320153a00be022003200d3b01bc022003200e3a00bb02200320163a00ba022003200f3b01b802200320103a00b702200320173a00b602200320113b01b402200320123a00b302200320183a00b202200320133b01b002200320143a00af022003201c3600ab022003201a3a00aa022003201b3b01a802200341b0046a41086a22024200370300200342003703b00441b8a2c1004114200341b0046a1008200341e8006a41086a2002290300370300200320032903b0043703680240200341e8006a41104101410041001003417f460d0041bdf8c1002119412621020c3e0b411310282202450d0e200241002900c2a3413700002002410f6a41002800d1a341360000200241086a41002900caa34137000020034293808080b0023702f402200320023602f00220034188026a200341f0026a108f0120032802f802210220032802f0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341d0026a41186a201c290300370300200341d0026a41106a201d290300370300200341d0026a41086a200c290300370300200320032903b0043703d002024020032802f402450d0020032802f002102a0b200341003602f002200341d0026a4120200341f0026a1006210220032802f0022219417f460d102002450d10200320193602b404200320023602b004200341f0026a200341b0046a10c20220032903f0024201510d0f02402019450d002002102a0b411310282202450d11200241002900c2a3413700002002410f6a41002800d1a341360000200241086a41002900caa34137000020034293808080b0023702f402200320023602f002200341a8026a200341f0026a108f0120032802f802210220032802f0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341d0026a41186a201c290300370300200341d0026a41106a201d290300370300200341d0026a41086a200c290300370300200320032903b0043703d002024020032802f402450d0020032802f002102a0b200341003602f002200341d0026a4120200341f0026a1006210220032802f0022219417f460d132002450d13200320193602b404200320023602b004200341f0026a200341b0046a10c20220032903f0024201510d1220034198036a280200211002402019450d002002102a0b200341b0046a41086a22024200370300200342003703b004418891c6004111200341b0046a1008200341e8006a41086a2002290300370300200320032903b00437036841002119200341003602f002200341e8006a4110200341f0026a10062102024020032802f002221c417f460d002002450d00201c4104490d15200228000021192002102a0b02402019201f460d0041e3f8c1002119411621020c3e0b0240201041016a201f490d0041f9f8c1002119411f21020c3e0b410e10282202450d15200241066a41002900b2a441370000200241002900aca4413700002002410e411c102c2202450d162002202141067636000e200341b0046a41186a22194200370300200341b0046a41106a221c4200370300200341b0046a41086a221d4200370300200342003703b00420024112200341b0046a1000200341d0026a41186a2019290300370300200341d0026a41106a201c290300370300200341d0026a41086a201d290300370300200320032903b0043703d0022002102a200341003602f002200341d0026a4120200341f0026a1006210220032802f0022219417f460d342002450d34200320193602b404200320023602b004200341f0026a200341b0046a107420032802f002220c450d172021413f71211c20032902f402210b02402019450d002002102a0b4100211d201c200b422088a74f0d32200c201c41216c6a22192d00004101470d32200341a6016a201941036a2d00003a000020034188016a41086a201941146a29000037030020034195016a201941196a290000370000200320192f00013b01a40120032019410c6a29000037038801201941086a2800002102201941046a28000021194101211d0c330b2001280204211b2002411a6a290100210b200241196a2d0000210c200241186a2d00002107200241166a2f0100210d200241156a2d0000210e200241146a2d0000210f200241126a2f01002110200241116a2d00002111200241106a2d000021122002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002116200241096a2d0000211741042119200241046a2d00002118200241026a2f0100211a0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d410021024100211c0b2003200b3703e8022003200c3a00e702200320073a00e6022003200d3b01e4022003200e3a00e3022003200f3a00e202200320103b01e002200320113a00df02200320123a00de02200320133b01dc02200320143a00db02200320153a00da02200320163b01d802200320173a00d702200320183a00d2022003201a3b01d0022003201c41ffff0371410874200241187472201941ff017172221c3600d3020240201d450d00410f210241ea9fc60021190240201c0e0700040506073d3e000b20032800d702211920032800db0221020c3d0b20034188046a41186a200341d0026a41186a29030037030020034188046a41106a200341d0026a41106a29030037030020034188046a41086a200341d0026a41086a290300370300200320032903d00237038804200341b0046a41086a22024200370300200342003703b00441b8a2c1004114200341b0046a1008200341e8006a41086a2002290300370300200320032903b0043703680240200341e8006a41104101410041001003417f460d0041d9fac1002119411e21020c3d0b411310282202450d17200241002900c2a3413700002002410f6a41002800d1a341360000200241086a41002900caa34137000020034293808080b0023702f402200320023602f00220034188046a200341f0026a108f0120032802f802211920032802f002211c41182102200341b0046a41186a221d4200370300200341b0046a41106a220c4200370300200341b0046a41086a22074200370300200342003703b004201c2019200341b0046a1000200341d0026a41186a201d290300370300200341d0026a41106a200c290300370300200341d0026a41086a2007290300370300200320032903b0043703d002024020032802f402450d0020032802f002102a0b0240200341d0026a41204101410041001003417f470d0041f7fac10021190c3d0b410e10282202450d18200241066a41002900b2a441370000200241002900aca4413700002002410e411c102c2219450d192019201b41067636000e41182102200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420194112200341b0046a1000200341e8006a41186a201c290300370300200341e8006a41106a201d290300370300200341e8006a41086a200c290300370300200320032903b0043703682019102a200341003602b004200341e8006a4120200341b0046a1006211c20032802b0042219417f460d1b200320193602e4032003201c3602e003200341b0046a200341e0036a107420032802b004221d450d1a201b413f71210220032902b404210b02402019450d00201c102a0b4100211c2002200b422088a74f0d2e201d200241216c6a22192d00004101470d2e20034186026a201941036a2d00003a0000200341e8016a41086a201941146a290000370300200341f5016a201941196a290000370000200320192f00013b01840220032019410c6a2900003703e801201941086a2800002102201941046a28000021194101211c0c2f0b2001280204210c2002411a6a290100210b200241196a2d00002112200241186a2d00002113200241166a2f01002114200241156a2d00002115200241146a2d00002116200241126a2f01002117200241116a2d00002118200241106a2d000021072002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d0000211141042119200241046a2d0000211a200241026a2f0100211b0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d4100211c410021020b201c41ffff0371410874201941ff017172200241187472211c0240201d450d00410f210241ea9fc60021190240201c0e0700030405063c3d000b2010410874201172200f411874722119200d410874200e7220074118747221020c3c0b2003200b3703a004200320123a009f04200320133a009e04200320143b019c04200320153a009b04200320163a009a04200320173b019804200320183a009704200320073a0096042003200d3b0194042003200e3a0093042003200f3a009204200320103b019004200320113a008f042003201c36008b042003201a3a008a042003201b3b018804411610282202450d1b20024100290093a2413700002002410e6a41002900a1a241370000200241086a410029009ba24137000020034296808080e0023702f402200320023602f00220034188046a200341f0026a108f0120032802f802210220032802f0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a22074200370300200342003703b00420192002200341b0046a1000200341e8006a41186a201c290300370300200341e8006a41106a201d290300370300200341e8006a41086a2007290300370300200320032903b004370368024020032802f402450d0020032802f002102a0b4101211d0240200341e8006a41204101410041001003417f460d00418ffbc1002119411e21024101210c0c400b200341b0046a41086a22024200370300200342003703b00441bf91c6004116200341b0046a1008200341e8006a41086a2002290300370300200320032903b0043703684100211c200341003602f002200341e8006a4110200341f0026a10062102024020032802f0022219417f460d002002450d0020194104490d1d2002280000211c2002102a0b200341b0046a41086a22024200370300200342003703b00441b0a3c1004112200341b0046a1008200341e8006a41086a2002290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a100621020240024020032802f0022219417f460d002002450d00200320193602b404200320023602b004200341f0026a200341b0046a106d20032802f0022207450d1f20032902f402210b02402019450d002002102a0b200b422088a7210d0c010b4100210d4200210b410121070b0240024002400240201c200c470d00200d200c460d010b41adfbc100211941162102200d200c4d0d01200c200b422088a7220d4f0d2120034188036a420037030020034180036a4200370300200341f8026a4200370300200342003703f0022007200c4105746a220d200341f0026a460d00200d200341f0026a4120109c050d010b200341306a20034188046a4280809aa6eaafe30142001083022003280230450d0141c3fbc1002119411e21020b0240200ba7450d002007102a0b4101210c0c400b200341b0046a41086a22024200370300200342003703b004418891c6004111200341b0046a1008200341e8006a41086a2002290300370300200320032903b00437036841002119200341003602f002200341e8006a4110200341f0026a10062102024020032802f002221d417f460d002002450d00201d4104490d20200228000021192002102a0b411610282202450d2020024100290093a2413700002002410e6a41002900a1a241370000200241086a410029009ba24137000020034296808080e0023702f402200320023602f00220034188046a200341f0026a108f0120032802f802210220032802f002211d200341b0046a41186a220d4200370300200341b0046a41106a220e4200370300200341b0046a41086a220f4200370300200342003703b004201d2002200341b0046a1000200341e8006a41186a200d290300370300200341e8006a41106a200e290300370300200341e8006a41086a200f290300370300200320032903b004370368024020032802f402450d0020032802f002102a0b410810282202450d212002200c36000420022019360000200341e8006a41202002410810072002102a200ba7211d02400240200c200b422088a72202460d00200341d0026a41186a220d20034188046a41186a290300370300200341d0026a41106a220e20034188046a41106a290300370300200341d0026a41086a20034188046a41086a29030037030020032003290388043703d002200c20024f0d242007200c4105746a221920032903d002370000201941186a200d290300370000201941106a200e290300370000201941086a200341d0026a41086a2903003700000c010b200341d0026a41186a221920034188046a41186a290300370300200341d0026a41106a220d20034188046a41106a290300370300200341d0026a41086a20034188046a41086a29030037030020032003290388043703d0020240200c201d470d00200c41016a2202200c490d38200c410174221d2002201d20024b1b221d41ffffff3f71201d470d38201d41057422024100480d3802400240200c0d002002102821070c010b2007200c4105742002102c21070b2007450d25200b422088a7210c0b2007200c4105746a220220032903d002370000200241186a2019290300370000200241106a200d290300370000200241086a200341d0026a41086a290300370000200c41016a21020b200341b0046a41086a22194200370300200342003703b00441b0a3c1004112200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200341003602f802200342013703f0022002200341f0026a10b40102402002450d00200241057421192007210203402002200341f0026a108f01200241206a2102201941606a22190d000b0b20032802f4022102200341e8006a411020032802f002221920032802f802100702402002450d002019102a0b0240201d450d002007102a0b200341b0046a41086a22024200370300200342003703b00441bf91c6004116200341b0046a1008200341e8006a41086a2002290300370300200320032903b0043703684101211d2003201c41016a3602f002200341e8006a4110200341f0026a41041007410021194101210c0c3f0b200141386a2903002104200141306a29030021052001411d6a290000210b2001411c6a2d00002112200141196a2f00002113200141186a2d00002114200141156a2f00002115200141146a2d00002116200141116a2f00002117200141106a2d000021182001410d6a2f0000211a2001410c6a2d0000211b200141086a280200210c200141286a280200211f20012d001b210a20012d0017210620012d0013210820012d000f210920012d0007212920012f0005212a20012d0004212c2002411a6a290100212d200241196a2d0000211e200241186a2d00002122200241166a2f01002123200241156a2d00002124200241146a2d00002125200241126a2f01002126200241116a2d00002127200241106a2d000021072002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d0000211141042119200241046a2d00002128200241026a2f0100212b0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d4100211c410021020b201c41ffff0371410874201941ff017172200241187472211c201d450d04410f210241ea9fc60021190240201c0e0700010203043a3b000b2010410874201172200f411874722119200d410874200e7220074118747221020c3a0b410e210241dc9fc60021190c390b410c210241d09fc60021190c380b4109210241c79fc60021190c370b4113210241b49fc60021190c360b2003202d3703f8032003201e3a00f703200320223a00f603200320233b01f403200320243a00f303200320253a00f203200320263b01f003200320273a00ef03200320073a00ee032003200d3b01ec032003200e3a00eb032003200f3a00ea03200320103b01e803200320113a00e7032003201c3600e303200320283a00e2032003202b3b01e0030240200520048450450d00419ffcc100211941d00021020c360b02400240202c41ff01714101470d00200341f0026a200c41067610fe0120032802f00221190240024020032802f802200c413f7122024b0d00410021020c010b201920024105746a2202290018210b20022d0017211220022d0016210a20022f0014211320022d0013211420022d0012210620022f0010211520022d000f211620022d000e210820022f000c211720022d000b211820022d000a210920022f0008211a20022d0007211b2002280003210c20022d0002212920022f0000212a410121020b024020032802f402450d002019102a0b20020d00410121020c010b410021020b2003200b3701e802200320123a00e7022003200a3a00e602200320133b01e402200320143a00e302200320063a00e202200320153b01e002200320163a00df02200320083a00de02200320173b01dc02200320183a00db02200320093a00da022003201a3b01d8022003201b3a00d7022003200c3600d302200320293a00d2022003202a3b01d00220020d3320034188046a41186a200341d0026a41186a29010037030020034188046a41106a200341d0026a41106a29010037030020034188046a41086a200341d0026a41086a290100370300200320032901d00237038804200341b0046a41086a22024200370300200342003703b004418891c6004111200341b0046a1008200341e8006a41086a2002290300370300200320032903b00437036841002119200341003602f002200341e8006a4110200341f0026a10062102024020032802f002221c417f460d002002450d00201c4104490d1f200228000021192002102a0b02402019201f460d00418efcc1002119411121020c360b200341b0046a41086a22024200370300200342003703b00441b8a2c1004114200341b0046a1008200341e8006a41086a22192002290300370300200320032903b004370368200341f0026a200341e8006a10be02024020032802f802220d0d0041e1fbc1002119412d21020c360b20032902fc02212e20024200370300200342003703b00441ad91c6004112200341b0046a100820192002290300370300200320032903b00437036841002119200341003602f002200341e8006a4110200341f0026a10062102024020032802f002221c417f460d002002450d00201c4104490d20200228000021192002102a0b200341d8006a2019ad42004280a094a58d1d4200109f05200341d8006a41086a290300210b411410282202450d202003290358212f200241002900cfe140370000200241106a41002800dfe140360000200241086a41002900d7e14037000020034294808080c0023702d402200320023602d002200341e0036a200341d0026a108f0120032802d802210220032802d0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341f0026a41186a201c290300370300200341f0026a41106a201d290300370300200341f0026a41086a200c290300370300200320032903b0043703f002024020032802d402450d0020032802d002102a0b200341003602b004200341f0026a4120200341b0046a1006210220032802b0042219417f460d252002450d2520194110490d21200241086a290000212d200229000021302002102a0c260b4101211d20022d000120022d0000720d2320012802042102200341b0046a41086a22194200370300200342003703b00441f490c6004114200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200320023602f002200341e8006a4110200341f0026a41041007410021194101210c0c380b024020022d000120022d000072450d0041a39fc6002119411121020c340b200141086a2802002119024020012d00044101460d00200141106a2d0000211c200141146a2d0000211d200141186a2d0000210c2001411c6a2d0000210720012f0005210220012d0007210d20012d000c210e20012f000d210f20012d000f211020012f0011211120012d0013211220012f0015211320012d0017211420012f0019211520012d001b2116200129001d210b0c210b200341f0026a201941067610fe0120032802f00221170240024020032802f8022019413f7122024b0d00410021180c010b201720024105746a2202290018210b20022d0017210720022d0016211620022f0014211520022d0013210c20022d0012211420022f0010211320022d000f211d20022d000e211220022f000c211120022d000b211c20022d000a211020022f0008210f20022d0007210e2002280003211920022d0002210d20022f00002102410121180b024020032802f402450d002017102a0b20180d20410121170c210b4101211d20022d000120022d0000720d2120012802042102200341b0046a41086a22194200370300200342003703b00441f0a2c100411c200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200320023602f002200341e8006a4110200341f0026a41041007410021194101210c0c360b4101211d20022d000120022d0000720d2020012802042102200341b0046a41086a22194200370300200342003703b00441dca2c1004114200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200320023602f002200341e8006a4110200341f0026a41041007410021194101210c0c350b200341d0026a41186a200341e8006a41186a290300220b370300200341d0026a41106a200341e8006a41106a290300222d370300200341d0026a41086a200341e8006a41086a290300222e37030020032003290368222f3703d002200341f0026a41186a200b370300200341f0026a41106a202d370300200341f0026a41086a202e3703002003202f3703f002200320063602b804200320073602b4042003200a3602b0042003200341f0026a200341b0046a200920082005200410d40220032802042102200328020021194100210c4101211d0c340b410d41011037000b411341011037000b41c4d1c3004133200341d8046a419cd9c3001038000b41c4f9c1002119411821020c2c0b411341011037000b41c4d1c3004133200341d8046a419cd9c3001038000b4198f9c1002119412c21020c290b41c4d1c3004133200341d8046a419cd9c3001038000b410e41011037000b411c41011037000b41c4d1c3004133200341d8046a419cd9c3001038000b411341011037000b410e41011037000b411c41011037000b41c4d1c3004133200341d8046a419cd9c3001038000b4101211c41a8fac10021190c140b411641011037000b41c4d1c3004133200341d8046a419cd9c3001038000b41c4d1c3004133200341d8046a419cd9c3001038000b41cca2c100200c200d1034000b41c4d1c3004133200341d8046a419cd9c3001038000b411641011037000b410841011037000b41a0a3c100200c20021034000b200241011037000b41c4d1c3004133200341d8046a419cd9c3001038000b41c4d1c3004133200341d8046a419cd9c3001038000b411441011037000b41c4d1c3004133200341d8046a419cd9c3001038000b410021170b2003200b37018001200320073a007f200320163a007e200320153b017c2003200c3a007b200320143a007a200320133b01782003201d3a0077200320123a0076200320113b01742003201c3a0073200320103a00722003200f3b01702003200e3a006f2003201936006b2003200d3a006a200320023b016820170d0f200341d0026a41186a200341e8006a41186a290100370300200341d0026a41106a200341e8006a41106a290100370300200341d0026a41086a200341e8006a41086a2202290100370300200320032901683703d002200341b0046a41086a22194200370300200342003703b00441a9a2c100410f200341b0046a100820022019290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a10062102024002400240024002400240024020032802f0022219417f460d002002450d00200320193602b404200320023602b004200341f0026a200341b0046a107d20032802f002221c450d0220032902f402210b2019450d012002102a0c010b4200210b4104211c0b200ba72111024002400240200b422088a72207450d00201c200741246c221d6a210c410021190340200341f0026a41206a201c20196a220241206a280200360200200341f0026a41186a200241186a290200370300200341f0026a41106a200241106a290200370300200341f0026a41086a200241086a290200370300200320022902003703f002200341f0026a200341d0026a4120109c050d02201d201941246a2219470d000b0b4104210f4100210d024020110d00410021100c020b201c102a410021100c010b20034188046a41086a200341f0026a41086a290300220b370300200341e0036a41086a221d200b370300200341e0036a41106a220d200341f0026a41106a290300370300200341e0036a41186a220e200341f0026a41186a290300370300200341e0036a41206a2210200341f0026a41206a280200360200200320032903f002220b370388042003200b3703e00341241028220f450d02200f20032903e003370200200f41206a2010280200360200200f41186a200e290300370200200f41106a200d290300370200200f41086a201d29030037020002400240200741246c415c6a2019470d004101210d410121100c010b200241246a2113200c415c6a21144101210d4101211003402013210202400340200341f0026a41206a2219200241206a280200360200200341f0026a41186a221d200241186a290200370300200341f0026a41106a2207200241106a290200370300200341f0026a41086a220e200241086a290200370300200320022902003703f002200341f0026a200341d0026a4120109c050d01200c200241246a2202470d000c030b0b200341b0046a41206a2019280200221236020020034188046a41086a200e290300220b37030020034188046a41106a2007290300220437030020034188046a41186a201d290300220537030020034188046a41206a2012360200200320032903f002222d3703880420192012360200201d200537030020072004370300200e200b3703002003202d3703f00202402010200d470d00200d41016a2210200d490d15200d41017422122010201220104b1b2210ad42247e220b422088a70d15200ba722124100480d1502400240200d0d0020121028210f0c010b200f200d41246c2012102c210f0b200f450d060b200241246a2113200f200d41246c6a221220032903f002370200201241206a2019280200360200201241186a201d290300370200201241106a2007290300370200201241086a200e290300370200200d41016a210d20142002470d000b0b2011450d00201c102a0b200341b0046a41086a22024200370300200342003703b00441a9a2c100410f200341b0046a1008200341e8006a41086a2002290300370300200320032903b004370368200341003602f802200342013703f002200d200341f0026a10b4010240200d450d00200f200d41246c6a2107200f211903402019200341f0026a108f01201941206a280200211d0240024020032802f402221c20032802f80222026b4104490d0020032802f002211c0c010b200241046a220c2002490d14201c4101742202200c2002200c4b1b22024100480d1402400240201c0d0020021028211c0c010b20032802f002201c2002102c211c0b201c450d06200320023602f4022003201c3602f00220032802f80221020b2003200241046a3602f802201c20026a201d3600002007201941246a2219470d000b0b20032802f4022102200341e8006a411020032802f002221920032802f802100702402002450d002019102a0b200d41246c220241246d210c4100211c0240024020020d00410121074100210c0c010b200c41ffffff3f71200c470d12200c41057422024100480d12200210282207450d050b0240200d450d00200d41246c211d4100211c20072102200f21190340201941086a290000210b201941106a290000210420192900002105200241186a201941186a290000370000200241106a2004370000200241086a200b37000020022005370000201c41016a211c200241206a2102201941246a2119201d415c6a221d0d000b0b02402010450d00200f102a0b200341f0026a41186a200341d0026a41186a290300370300200341f0026a41106a200341d0026a41106a290300370300200341f0026a41086a200341d0026a41086a290300370300200320032903d0023703f002410021192007201c41004120201c676b10c4024101211d200341f0026a41012007201c10c5020240200c450d002007102a0b4101210c0c1a0b41c4d1c3004133200341d8046a419cd9c3001038000b412441041037000b201241041037000b200241011037000b200241011037000b41a39fc6002119411121024101210c0c140b420021304200212d0b024002402030202f54202d200b54202d200b511b450d0041a0fdc1002119412e21020c010b200341b0046a41086a22024200370300200342003703b004418ca3c1004113200341b0046a1008200341e8006a41086a2002290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a1006210202400240024002400240024002400240024020032802f0022219417f460d002002450d00200320193602b404200320023602b004200341f0026a200341b0046a107820032802f0022210450d0320032902f402212d02402019450d002002102a0b202d422088a72217450d05202da7211441f1fdc1002119412321022010290300200554201041086a290300223020045420302004511b450d07200341b0046a41086a22194200370300200342003703b00441a9a2c100410f200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a1006211920032802f002221c417f460d012019450d012003201c3602b404200320193602b004200341f0026a200341b0046a107d20032802f0022207450d0420032902f4022130201c450d022019102a0c020b41effcc1002119413121020c080b42002130410421070b20072030422088a7220e41246c6a210c200721194100211c024003400240200c20196b41ec004b0d00200c2019460d062007200e41246c6a210c034020034188046a2019460d03201c201920034188046a4120109c05221d4100476a211c201d450d03200c201941246a2219470d000c070b0b201920034188046a460d01201c201920034188046a4120109c05221d4100476a211c201d450d01201941246a221d20034188046a460d01201c201d20034188046a4120109c05221d4100476a211c201d450d01201941c8006a221d20034188046a460d01201c201d20034188046a4120109c05221d4100476a211c201d450d01201941ec006a221d20034188046a460d0120194190016a2119201c201d20034188046a4120109c05221d4100476a211c201d0d000b0b201c202e422088a7490d034194fec1002119413621022030a7450d042007102a0c040b41c4d1c3004133200341d8046a419cd9c3001038000b41c4d1c3004133200341d8046a419cd9c3001038000b41cca2c100410041001034000b02402030a7450d002007102a0b200341a8026a10c002200341f0026a20034188046a10bf0220032802f0024101460d01024020032802ac02450d0020032802a802102a0b41cefdc10021190b2014450d012010102a0c010b20032802a80221260240024002400240024002400240024002400240024020032802b00222020d0042002131420021320c010b20032802f4022111200241216c211c202641016a2102200341f8026a2802002219410876211241012019411f7174211520194105764107712213417f7321164200213142002132034002402002417f6a2d00004101470d00411310282219450d06201941002900c2a3413700002019410f6a41002800d1a341360000201941086a41002900caa34137000020034293808080b0023702f402200320193602f0022002200341f0026a108f0120032802f802211d20032802f002210c200341b0046a41186a22074200370300200341b0046a41106a220e4200370300200341b0046a41086a22194200370300200342003703b004200c201d200341b0046a1000200341e8006a41186a2007290300370300200341e8006a41106a200e290300370300200341e8006a41086a22072019290300370300200320032903b004370368024020032802f402450d0020032802f002102a0b200341003602f002200341e8006a4120200341f0026a1006210c20032802f002221d417f460d002003201d3602b4042003200c3602b004200341f0026a200341b0046a10c20220032903f0024201510d05200341f0026a41206a2903002133200341f0026a41106a220f2903002134200329038803213520032903f8022136200328029803210e0240201d450d00200c102a0b200e2011490d0020194200370300200342003703b004418891c6004111200341b0046a100820072019290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a10062119024020032802f002221d417f460d00201d41034d0d052019102a0b200341f0026a41186a200241186a290000370300200f200241106a290000370300200341f0026a41086a200241086a290000370300200320022900003703f0022003201236029003200341b0046a200341f0026a10c10242002130420021370240201320032802b80422194f0d00201920166a221d20194f0d04203320347c203520367c2230203554ad7c420020032802b004201d4102746a28020020157122191b21372030420020191b21300b024020032802b404450d0020032802b004102a0b203720327c203020317c2231203054ad7c21320b200241216a2102201c415f6a221c0d000b0b2010201741306c6a210920102102024002400240024003400240200920026b4190014b0d00024020022009460d0003404101211c200241106a220220034188046a460d04200220034188046a4120109c05450d04200241206a22022009470d000b0b4100211c203120058520322004858450450d02200341d0026a41186a220220034188046a41186a290300370300200341d0026a41106a221920034188046a41106a290300370300200341d0026a41086a221c20034188046a41086a29030037030020032003290388043703d0022010200437030820102005370300201020032903d002370310201041186a201c290300370300201041206a2019290300370300201041286a200229030037030020174115490d0a202d422188220b42307e2204422088a70d182004a72202417f4c0d1820020d03410821254108210f0c040b4101211c200241106a221920034188046a460d01201920034188046a4120109c05450d01200241c0006a221920034188046a460d01201920034188046a4120109c05450d01200241f0006a221920034188046a460d01201920034188046a4120109c05450d01200241a0016a221920034188046a460d01200241c0016a2102201920034188046a4120109c050d000b0b200341386a200341e0036a202f200b10cf012003290338210b2003200341c0006a2903003703f8022003200b3703f00241cafec10041e0fec100201c1b21194116410f201c1b21022003200341f0026a3602b004200341b0046a109d014101211c0c090b200210282225450d012025210f0b200ba7211f201041506a2128201041306a212c201041f07e6a212b410421154100212741002106410021122017210a0340200a21074100210a4101210c02402007417f6a221c450d000240024002400240024002402010201c41306c6a2202290300200741306c221120106a41a07f6a2219290300220454200241086a2903002205201941086a290300220b542005200b511b0d002007417e6a210e202b20116a21024100210a4100211903400240200e2019470d002007210c0c080b20042002290300222d5a211c200b200241086a290300220551211d200b20055a210c200241506a2102201941016a2119202d21042005210b201c200c201d1b0d000b201941016a210c2019417f7320076a211c0c010b202b20116a2102024003400240201c4101470d004100211c0c020b20042002290300222d542119200b200241086a290300220551211d200b200554210c200241506a2102201c417f6a211c202d21042005210b2019200c201d1b0d000b0b2007201c490d01200720174b0d032007201c6b220c410176221d450d00202820116a21022010201c41306c6a21190340200341f0026a41286a220e201941286a2211290300370300200341f0026a41206a2213201941206a2216290300370300200341f0026a41186a2218201941186a221a290300370300200341f0026a41106a221b201941106a220a290300370300200341f0026a41086a2208201941086a2229290300370300200320192903003703f002200241086a222a290300210b200241106a221e2903002104200241186a22222903002105200241206a2223290300212d200241286a2224290300212f201920022903003703002011202f3703002016202d370300201a2005370300200a20043703002029200b3703002024200e2903003703002023201329030037030020222018290300370300201e201b290300370300202a2008290300370300200220032903f002370300201941306a2119200241506a2102201d417f6a221d0d000b0b0240201c0d00201c210a0c050b0240200c41094d0d00201c210a0c050b200720174b0d012007201c6b211d202c201c41306c6a210e03402007201c417f6a220a490d0402402007200a6b220c4102490d002010201c41306c6a22022903002010200a41306c6a221c29030022055a200241086a22192903002204201c41086a2211290300220b5a2004200b511b0d00200341b0046a41186a2216201c41286a2213290300370300200341b0046a41106a2218201c41206a221a290300370300200341b0046a41086a221b201c41186a22082903003703002003201c2903103703b004201c200229030037030020112019290300370300201c41106a200241106a2903003703002008200241186a290300370300201a200241206a2903003703002013200241286a290300370300410121190240200c4103490d00201c29036020055a201c41e8006a2903002204200b5a2004200b511b0d0041022111200e211303402013220241506a22192002290300370300201941286a200241286a290300370300201941206a200241206a290300370300201941186a200241186a290300370300201941106a200241106a290300370300201941086a200241086a290300370300201d20112219460d01201941016a2111200241306a221329030020055a200241386a2903002204200b5a2004200b511b450d000b0b200220053703002002200b370308201c201941306c6a220241286a2016290300370300200241206a2018290300370300200241186a201b290300370300200220032903b0043703100b200a450d05200e41506a210e201d41016a211d200a211c200c410a4f0d050c000b0b201c20071044000b2007201c417f6a220a490d010b20072017103c000b200a20071044000b02400240024020122027470d00202741016a22022027490d18202741017422192002201920024b1b220241ffffffff01712002470d18200241037422194100480d180240024020270d002019102821150c010b201520274103742019102c21150b2015450d0120022127200621120b201520124103746a2202200c3602042002200a360200200641016a2212210620124102490d0102400340024002400240024020152012417f6a22064103746a2202280200450d00201241037420156a221d41746a280200221c200228020422194d0d000240201241024b0d0020122106410221120c080b20152012417d6a22164103746a28020422022019201c6a4d0d010240201241034b0d0020122106410321120c080b201d41646a2802002002201c6a4d0d01201221060c070b20124103490d012002280204211920152012417d6a22164103746a28020421020b20022019490d010b2012417e6a21160b0240024002400240024002402012201641016a22084b2229450d00201220164b222a450d01201520164103746a2218280204221e20182802006a2202201520084103746a221a280200221b490d02200220174b0d032010201b41306c6a2211201a280204221341306c22196a211d200241306c211c2002201b6b220720136b220220134f0d042025201d200241306c2219109a051a200f20196a210c0240024020134101480d00200241014e0d010b201d2102200f21190c060b2028201c6a211c201d21020340201c200241506a221d200c41506a22072007290300201d29030054200741086a290300220b201d41086a290300220454200b2004511b220e1b2219290300370300201c41086a201941086a290300370300201c41106a201941106a290300370300201c41186a201941186a290300370300201c41206a201941206a290300370300201c41286a201941286a290300370300200c2007200e1b210c02402011201d2002200e1b2202490d00200f21190c070b201c41506a211c200f2119200f200c490d000c060b0b41b8dbc000200820121034000b41b8dbc000201620121034000b201b20021044000b20022017103c000b202520112019109a051a200f20196a210c0240024020134101480d00200720134a0d010b20112102200f21190c010b2010201c6a210e200f21192011210203402002201d2019201d290300201929030054201d41086a290300220b201941086a290300220454200b2004511b22071b221c290300370300200241086a201c41086a290300370300200241106a201c41106a290300370300200241186a201c41186a290300370300200241206a201c41206a290300370300200241286a201c41286a2903003703002019201941306a20071b2119200241306a2102201d41306a201d20071b221d200e4f0d01200c20194b0d000b0b20022019200c20196b221c201c4130706b109a051a0240202a450d002018201b360200201841046a201e20136a3602002029450d02201a201a41086a20122008417f736a410374109b051a20062112200641014d0d040c010b0b41c8dbc000201620121034000b41b0b1c0001032000b201941041037000b200a0d000b02402027450d002015102a0b201f450d062025102a0c060b200241081037000b41cca2c100201d20191034000b41c4d1c3004133200341d8046a419cd9c3001038000b41c4d1c3004133200341d8046a419cd9c3001038000b411341011037000b20174102490d002017417f6a211c2010201741306c6a21074101211d03400240024002400240201c2202417f6a221c20174b0d002017201c6b22194102490d032010200241306c6a22022903002010201c41306c6a220c29030022055a200241086a220e2903002204200c41086a220f290300220b5a2004200b511b0d03200341b0046a41186a2211200c41286a2212290300370300200341b0046a41106a2213200c41206a2215290300370300200341b0046a41086a2216200c41186a22182903003703002003200c2903103703b004200c2002290300370300200f200e290300370300200c41106a200241106a2903003703002018200241186a2903003703002015200241206a2903003703002012200241286a2903003703004101210e20194103490d02200c29036020055a200c41e8006a2903002204200b5a2004200b511b0d024100210e2007211903402019220241506a22192002290300370300201941286a200241286a290300370300201941206a200241206a290300370300201941186a200241186a290300370300201941106a200241106a290300370300201941086a200241086a290300370300201d200e220f460d02200f417f6a210e200241306a221929030020055a200241386a2903002204200b5a2004200b511b0d020c000b0b201c20171044000b4102200f6b210e0b200220053703002002200b370308200c200e41306c6a220241286a2011290300370300200241206a2013290300370300200241186a2016290300370300200220032903b0043703100b200741506a2107201d417f6a211d201c0d000b0b200341b0046a41086a22024200370300200342003703b004418ca3c1004113200341b0046a1008200341e8006a41086a2002290300370300200320032903b004370368200341003602f802200342013703f0022017200341f0026a10b401201021020340200241086a290300210b200229030021040240024020032802f402221c20032802f80222196b4110490d0020032802f002211c0c010b201941106a221d2019490d0f201c4101742219201d2019201d4b1b22194100480d0f02400240201c0d0020191028211c0c010b20032802f002201c2019102c211c0b201c450d03200320193602f4022003201c3602f00220032802f80221190b201c20196a221c200b370008201c20043700002003201941106a3602f802200241106a200341f0026a108f01200241306a22022009470d000b20032802f4022102200341e8006a411020032802f002221920032802f802100702402002450d002019102a0b02402014450d002010102a0b4100211c410021190b024020032802ac02450d002026102a0b0240201c0d00202ea7450d120c020b02402014450d002010102a0b202ea7450d110c010b201941011037000b200d102a0c0f0b202ea7450d0e200d102a0c0e0b0b024002400240200ba7450d00201d102a201c0d010c020b201c450d010b200341e4016a41026a20034184026a41026a2d00003a0000200341c8016a41086a200341e8016a41086a290300370300200341c8016a410d6a200341e8016a410d6a290000370000200320032f0184023b01e401200320032903e8013703c8014100211c0c010b4101211c4118210241a8fac10021190b200341c4016a41026a221d200341e4016a41026a2d00003a0000200341a8016a41086a220c200341c8016a41086a290300370300200341a8016a41106a200341c8016a41106a290300370300200320032f01e4013b01c401200320032903c8013703a801201c0d0b20034183036a200c29030037000020034188036a200341b5016a290000370000200320032f01c4013b01f002200320023600f702200320193600f302200320032903a8013700fb022003201d2d00003a00f2020240200341f0026a20034188046a4120109c050d0020034188046a201b10d50220034188046a428080e983b1de16420010aa02200342f0f2bda9c6add9b1f4003703d00220031098013602a802200341b0046a20034188046a109a0220032802b404211920032802b004210220032802b804211c200341c4046a200341d0026a36020020032002201c4105746a3602bc04200320023602b804200320193602b404200320023602b0042003200341a8026a3602c004200341e0036a200341b0046a108701200341b0046a41086a200341e0036a41086a280200360200200320032903e0033703b00420034188046a200341b0046a109c02410021190c0c0b41c0fac1002119411921020c0b0b0b0240200ba7450d00200c102a201d450d010c020b201d0d010b4101211c4116210241dcf9c10021190c010b200341b0046a41026a200341a4016a41026a2d00003a0000200341f0026a41086a20034188016a41086a290300370300200341f0026a410d6a20034188016a410d6a290000370000200320032f01a4013b01b00420032003290388013703f0024100211c0b200341e8006a41026a221d200341b0046a41026a2d00003a000020034188046a41086a220c200341f0026a41086a29030037030020034188046a41106a200341f0026a41106a290300370300200320032f01b0043b0168200320032903f00237038804201c0d06200341f3036a200c290300370000200341f8036a20034195046a290000370000200320032f01683b01e003200320023600e703200320193600e30320032003290388043700eb032003201d2d00003a00e20302400240024002400240024002400240410e10282202450d00200241066a41002900b2a441370000200241002900aca4413700002002410e411c102c2202450d012002202041067636000e200341b0046a41186a22194200370300200341b0046a41106a221c4200370300200341b0046a41086a221d4200370300200342003703b00420024112200341b0046a1000200341e8006a41186a2019290300370300200341e8006a41106a201c290300370300200341e8006a41086a201d290300370300200320032903b0043703682002102a200341003602f002200341e8006a4120200341f0026a1006210220032802f0022219417f460d052002450d05200320193602b404200320023602b004200341f0026a200341b0046a107420032802f002220c450d022020413f71211c20032902f402210b02402019450d002002102a0b4100211d201c200b422088a74f0d03200c201c41216c6a22192d00004101470d0320034186026a201941036a2d00003a0000200341e8016a41086a201941146a290000370300200341f5016a201941196a290000370000200320192f00013b01840220032019410c6a2900003703e801201941086a2800002102201941046a28000021194101211d0c040b410e41011037000b411c41011037000b41c4d1c3004133200341d8046a419cd9c3001038000b0b0240200ba7450d00200c102a201d450d010c020b201d0d010b4101211c4114210241f2f9c10021190c010b200341e4016a41026a20034184026a41026a2d00003a0000200341c8016a41086a200341e8016a41086a290300370300200341c8016a410d6a200341e8016a410d6a290000370000200320032f0184023b01e401200320032903e8013703c8014100211c0b200341c4016a41026a221d200341e4016a41026a2d00003a0000200341a8016a41086a220c200341c8016a41086a290300370300200341a8016a41106a200341c8016a41106a290300370300200320032f01e4013b01c401200320032903c8013703a801201c0d062003419b046a200c290300370000200341a0046a200341b5016a290000370000200320032f01c4013b0188042003200236008f042003201936008b04200320032903a801370093042003201d2d00003a008a040240200341e0036a20034188026a4120109c05450d004186fac1002119411221020c070b024020034188046a200341a8026a4120109c05450d004198fac1002119411021020c070b200341f0026a41186a2217200341a8026a41186a2218290300370300200341f0026a41106a221a200341a8026a41106a221b290300370300200341f0026a41086a220a200341a8026a41086a2206290300370300200320032903a8023703f002410021022003410036029003200341b0046a200341f0026a10c1020240024020032802b804220d0d0041012112410021130c010b410021114100211341012112410021150340200d417f4c0d0220032802b404211620032802b00421140240024002400240200d1028220e450d0002400240200d41027422020d00410021070c010b201420026a210f410021072014210c0340200c2802002119412010282202450d0320022019411f763a001f200220194101713a000020022019411e764101713a001e20022019411d764101713a001d20022019411c764101713a001c20022019411b764101713a001b20022019411a764101713a001a200220194119764101713a0019200220194118764101713a0018200220194117764101713a0017200220194116764101713a0016200220194115764101713a0015200220194114764101713a0014200220194113764101713a0013200220194112764101713a0012200220194111764101713a0011200220194110764101713a001020022019410f764101713a000f20022019410e764101713a000e20022019410d764101713a000d20022019410c764101713a000c20022019410b764101713a000b20022019410a764101713a000a200220194109764101713a0009200220194108764101713a00082002201941ff017122194107763a0007200220194106764101713a0006200220194105764101713a0005200220194104764101713a0004200220194103764101713a0003200220194102764101713a0002200220194101764101713a0001200c41046a210c4100211902400240024002400340201941206a221c41034d0d010240200220196a221c411f6a2d0000450d002019411f6a211d0c040b0240201c411e6a2d0000450d002019411e6a211d0c040b0240201c411d6a2d00000d002019417c6a2119201c411c6a2d00000d030c010b0b2019411d6a211d0c020b0340201c450d032002201c6a2119201c417f6a221d211c2019417f6a2d0000450d000c020b0b201941206a211d0b201d41016a221c201d490d000240200d20076b201c4120201c4120491b22194f0d00200720196a22192007490d0b200d410174221d2019201d20194b1b22194100480d0b02400240200d0d0020191028210e0c010b200e200d2019102c210e0b200e450d062019210d0b200e20076a211d410021190240034020194120460d01201d20196a200220196a2d00004101713a0000201c201941016a2219470d000b0b200720196a21070b2002102a200c200f470d000b0b02402016450d002014102a0b0240201320116b2007490d00201120076a21020c040b201120076a22022011490d07201341017422192002201920024b1b22194100480d070240024020130d002019102821120c010b201220132019102c21120b02402012450d00201921130c040b201941011037000b200d41011037000b412041011037000b201941011037000b201220116a200e2007109a051a0240200d450d00200e102a0b20172018290300370300201a201b290300370300200a2006290300370300200320032903a8023703f0022003201541016a221536029003200341b0046a200341f0026a10c1022002211120032802b804220d0d000b0b024020032802b404450d0020032802b004102a0b200341b0046a41086a22194200370300200342003703b00441b0a3c1004112200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a1006211902400240024020032802f002221c417f460d002019450d002003201c3602b404200320193602b004200341f0026a200341b0046a106d20032802f002220e450d0220032902f402210b201c450d012019102a0c010b4101210e4200210b0b200b422088a741ffffff3f7122192002200220194b1b221c450d034100211920034188036a211d20034180036a210c200341f8026a2107200e210203400240201220196a2d0000450d00201d4200370300200c420037030020074200370300200342003703f002200341f0026a2002460d002002200341f0026a4120109c05450d00200341f0026a200210bf024101210d20032802f0024101470d0020032802f40220104d0d060b200241206a2102201941016a2219201c4f0d040c000b0b41c4d1c3004133200341d8046a419cd9c3001038000b1036000b1031000b4100210d0b0240200ba7450d00200e102a0b02402013450d002012102a0b20034188026a200341a8026a200d1b221920212020200d1b10d502200342f0f2bda9c6add9b1f4003703c80220031098013602d002200341f0026a2019109a0220032802f402211c20032802f002210220032802f802211d20034184036a200341c8026a36020020032002201d4105746a3602fc02200320023602f8022003201c3602f402200320023602f0022003200341d0026a36028003200341b0046a200341f0026a108701200341f0026a41086a200341b0046a41086a280200360200200320032903b0043703f0022019200341f0026a109c020240024002400240024002400240200d450d00200341106a20034188026a428080e983b1de1642001082022003290310210b2003200341106a41086a2903003703f8022003200b3703f0022003200341f0026a3602b004200341b0046a109d01200341013a00f402200341083a00f002200341f0026a4105722102200341f0026a211c0c010b200341206a20034188026a109d022003290320200341206a41086a29030084500d02411810282202450d03200241002900e3e140370000200241106a41002900f3e140370000200241086a41002900ebe1403700002003429880808080033702d402200320023602d002200341a8026a200341d0026a108f0120032802d802210220032802d0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341f0026a41186a201c290300370300200341f0026a41106a201d290300370300200341f0026a41086a200c290300370300200320032903b0043703f002024020032802d402450d0020032802d002102a0b200341003602b004200341f0026a4120200341b0046a1006210202400240024020032802b0042219417f470d004200210b420021050c010b20194110490d06200241086a29000021052002290000210b2002102a428080e983b1de1621044200212d200b428080e983b1de165441002005501b450d010b200b21042005212d0b411410282202450d05200241002900cfe140370000200241106a41002800dfe140360000200241086a41002900d7e14037000020034294808080c0023702d402200320023602d00220034188026a200341d0026a108f0120032802d802210220032802d0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341f0026a41186a201c290300370300200341f0026a41106a201d290300370300200341f0026a41086a200c290300370300200320032903b0043703f002024020032802d402450d0020032802d002102a0b200341003602b004200341f0026a4120200341b0046a100621020240024020032802b0042219417f470d004200212e4200212f0c010b20194110490d02200241086a290000212f2002290000212e2002102a0b20034188026a202e20047c2230202f202d7c2030202e54ad7c108f02200341a8026a200b20047d2005202d7d200b200454ad7d10900220034185036a200341b8026a2903003700002003418d036a200341c0026a290300370000200341083a00f002200341fd026a200341a8026a41086a290300370000200341003a00f402200320032903a8023700f50220034195036a2102200341f0026a211c0b2002200329038802370000200241186a20034188026a41186a290300370000200241106a20034188026a41106a290300370000200241086a20034188026a41086a290300370000410021194101211d41014100201c10cc014101210c0c0b0b41c4d1c3004133200341d8046a419cd9c3001038000b41b5dfc0002119412221020c050b411841011037000b41c4d1c3004133200341d8046a419cd9c3001038000b411441011037000b41dc9fc6002119410e21020c010b4111210241a39fc60021190b4101211d4101210c0c030b4100211c0b20034184026a41026a221d200341b0046a41026a2d00003a0000200341e8016a41086a220c200341f0026a41086a290300370300200341e8016a410d6a2207200341f0026a410d6a290000370000200320032f01b0043b018402200320032903f0023703e80102400240201c0d004101211c410b210241d8d2c50021190c010b200341e4016a41026a201d2d00003a0000200341c8016a41086a200c290300370300200341c8016a410d6a2007290000370000200320032f0184023b01e401200320032903e8013703c8014100211c0b200341c4016a41026a200341e4016a41026a2d00003a0000200341a8016a41086a200341c8016a41086a290300370300200341a8016a41106a200341c8016a41106a290300370300200320032f01e4013b01c401200320032903c8013703a801201c0d00200341a4016a41026a200341c4016a41026a2d0000221c3a000020034188016a41086a221d200341a8016a41086a29030037030020034188016a410d6a220c200341a8016a410d6a290000370000200320032f01c40122073b01a401200320032903a8013703880120034183036a201d29030037000020034188036a200c2900003700002003201c3a00f202200320073b01f002200320023600f702200320193600f30220032003290388013700fb02200320063602b8042003201b3602b4042003200a3602b004200341086a200341f0026a200341b0046a200920082005200410d402200328020c2102200328020821194101210c4100211d0c010b4101210c4100211d201b450d00200a102a0b02402001280200417f6a221c41014b0d0002400240201c0e020100010b201d450d01200141086a280200450d012001280204102a0c010b200c450d00200141086a280200450d002001280204102a0b2000200236020420002019360200200341e0046a24000bb55304087f017e097f027e23004190056b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d000022040e050001020304000b2003418c046a4101360200200342013702fc03200341ccd1c5003602f803200341043602f402200341c4d1c5003602f0022003200341f0026a36028804200341f8036a41a8a6c300103e000b200141086a2802002105200141046a2802002106024020022d000020022d000172450d0041a39fc600210741112108410021094101210a02402005450d002006102a0b410121060c230b20062001410c6a280200220210f0014200210b200341f8036a41086a22074200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2007290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621090240024020032802f8032208417f460d00200320083602ec01200320093602e801200341f8036a200341e8016a106d20032802f8032207450d0520032902fc03210b2008450d012009102a0c010b410121070b200620022007200b422088a71085020240200ba7450d002007102a0b200341f8036a41086a22074200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2007290300370300200320032903f8033703f0022003410036028004200342013703f8032002200341f8036a10b40102402002450d00200241057421072006210203402002200341f8036a108f01200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b4101210a2005450d212006102a0c210b200141046a280200210941b49fc60021074113210820022d00000d1e2002280001220a41ff01714101470d1e2003200a4118763a00622003200a4108763b01602003200241216a2d00003a007f2003200241196a2900003700772003200241116a29000037006f2003200241096a2900003700672003200241056a2800003600634200210b200341f8036a41086a22024200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621080240024020032802f8032207417f460d00200320073602ec01200320083602e801200341f8036a200341e8016a106d20032802f8032202450d0520032902fc03210b2007450d012008102a0c010b410121020b2002200b422088a7200341e0006a10cd0121070240200ba7450d002002102a0b024020070d0041b8a6c3002107411521080c1f0b4100210a2003410036028004200342013703f8032009200341f8036a10eb0120032802fc032107200328028004210820032802f8032102200341f0026a41186a22064200370300200341f0026a41106a22054200370300200341f0026a41086a220c4200370300200342003703f00220022008200341f0026a1000200341e8016a41186a22082006290300370300200341e8016a41106a220d2005290300370300200341e8016a41086a2205200c290300370300200320032903f0023703e80102402007450d002002102a0b200341f8036a2009418801109a051a200341f0026a410d6a200341e0006a41086a290300370000200341f0026a41156a200341e0006a41106a290300370000200341f0026a411d6a200341e0006a41186a29030037000041012106200341013a00f402200320032903603700f502200341023a00f002200341c0006a200341f8036a200341f0026a10f40120032d00482102200341f8036a410d6a2005290300370000200341f8036a41156a200d290300370000200341f8036a411d6a20082903003700002003419d046a20024102463a0000200341053a00fc03200341073a00f803200320032903e8013700fd0341014100200341f8036a10cc012009102a0c170b200141086a280200210941b49fc60021074113210820022d00000d1c2002280001220a41ff01714101470d1c200141046a28020021062003200a4118763a00422003200a4108763b01402003200241216a2d00003a005f2003200241196a2900003700572003200241116a29000037004f2003200241096a2900003700472003200241056a280000360043200341f8036a41086a22024200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621070240024020032802f8032208417f460d002007450d00200320083602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032202450d0520032902fc03210b2008450d012007102a0c010b4200210b410121020b2002200b422088a7200341c0006a10cd0121070240200ba7450d002002102a0b024020070d0041b8a6c3002107411521080c1d0b2003410036028004200342013703f8032009200341f8036a10eb0120032802fc032107200328028004210820032802f8032102200341f0026a41186a220a4200370300200341f0026a41106a22054200370300200341f0026a41086a220c4200370300200342003703f00220022008200341f0026a1000200341e0006a41186a2208200a290300370300200341e0006a41106a220a2005290300370300200341e0006a41086a2205200c290300370300200320032903f00237036002402007450d002002102a0b200341f8036a41186a2008290300370300200341f8036a41106a200a290300370300200341f8036a41086a2005290300370300200320032903603703f803411e10282202450d04200241002900f6a743370000200241166a410029008ca843370000200241106a4100290086a843370000200241086a41002900fea7433700002003429e808080e0033702ec01200320023602e8012003200341e8016a3602f002200341f8036a200341f0026a10c80120032802e801210220032802f0012107200341f0026a41186a22084200370300200341f0026a41106a220a4200370300200341f0026a41086a22054200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a200a290300370300200341206a41086a2005290300370300200320032903f002370320024020032802ec01450d0020032802e801102a0b200341206a41204101410041001003417f470d05200341f8036a41086a22024200370300200342003703f803024020064102490d004194a8c3004121200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f0024100210a200341003602f803200341f0026a4110200341f8036a10062102024020032802f8032207417f460d002002450d0020074104490d082002280000210a2002102a0b200341f8036a41086a22024200370300200342003703f8034194a8c3004121200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621020240024020032802f8032207417f460d002002450d00024020074104490d00200228000021072002102a200741016a21070c020b41c4d1c300413320034188056a419cd9c3001038000b410121070b200341f8036a41086a22024200370300200342003703f8034194a8c3004121200341f8036a1008200341f0026a41086a22082002290300370300200320032903f8033703f002200320073602f803200341f0026a4110200341f8036a4104100720024200370300200342003703f80341cf96c300411d200341f8036a100820082002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210220032802f8032207417f460d092002450d09200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f8032208450d0820032902fc03210b02402007450d002002102a0b200320083602e8012003200b3702ec01200341206a41186a200341e0006a41186a290300370300200341206a41106a200341e0006a41106a290300370300200341206a41086a200341e0006a41086a29030037030020032003290360370320200341e8016a2107200b422088a72202200ba72208470d150c140b4196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f00241002102200341003602f803200341f0026a4110200341f8036a10062108024020032802f8032207417f460d00200320073602ec01200320083602e801200341f8036a200341e8016a106d20032802f803220a450d0a20032902fc03210b02402007450d002008102a0b200b422088a72102200ba7450d00200a102a0b200341f8036a2009418801109a051a200341fc026a2002360200200341f0026a41086a4101360200200341003a00f402200341023a00f002200341e8016a200341f8036a200341f0026a10f40120032d00f001210220034185046a200341e0006a41086a2903003700002003418d046a200341f0006a29030037000020034195046a200341f8006a2903003700002003419d046a20024102463a0000200341043a00fc03200341073a00f803200320032903603700fd03200341f8036a21020c150b200141216a2d0000210a200141246a2802002109200341186a200141196a290000370300200341106a200141116a290000370300200341086a200141096a290000370300200320012900013703000240024020022d00000d002002280001220741ff01714101460d010b41b49fc60021070c110b200320074118763a0042200320074108763b01402003200241216a2d00003a005f2003200241196a2900003700572003200241116a29000037004f2003200241096a2900003700472003200241056a280000360043200341f8036a41086a22024200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621070240024020032802f8032208417f460d002007450d00200320083602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032202450d0b20032902fc03210b2008450d012007102a0c010b4200210b410121020b2002200b422088a7200341c0006a10cd0121070240200ba7450d002002102a0b024020070d0041bea7c3002107411221080c120b411a10282202450d0a200241002900ec9643370000200241186a41002f008497433b0000200241106a41002900fc9643370000200241086a41002900f496433700002003429a808080a0033702fc03200320023602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321022003280280042107200341f0026a41186a22084200370300200341f0026a41106a22064200370300200341f0026a41086a22054200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a2006290300370300200341206a41086a2005290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341003602f803200341206a4120200341f8036a1006210220032802f8032207417f460d0f2002450d0f200320073602f402200320023602f002200341f8036a200341f0026a10b3032003280280042205450d0b20034194046a280200210e20034190046a280200210f2003418c046a280200210c41102108200341f8036a41106a2802002110200328028404211120032802fc03211220032802f803210602402007450d002002102a0b41d0a7c300210720062009470d0e200520104105746a21062005210241002108024003400240200620026b41e0004b0d0020022006470d02410021130c100b200341c0006a2002460d0e20082002200341c0006a4120109c0522074100476a21082007450d0e200241206a2207200341c0006a460d0e20082007200341c0006a4120109c0522074100476a21082007450d0e200241c0006a2207200341c0006a460d0e20082007200341c0006a4120109c0522074100476a21082007450d0e200241e0006a2207200341c0006a460d0e20024180016a210220082007200341c0006a4120109c0522074100476a210820070d000c0e0b0b200520104105746a21060340200341c0006a2002460d0d20082002200341c0006a4120109c0522074100476a21082007450d0d410021132006200241206a2202470d000c0e0b0b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b411e41011037000b41cda6c3002107411f21080c160b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b41002102200341003602f001200342013703e801200341206a41186a200341e0006a41186a290300370300200341206a41106a200341e0006a41106a290300370300200341206a41086a200341e0006a41086a29030037030020032003290360370320200341e8016a21070c0a0b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b411a41011037000b41c4d1c300413320034188056a419cd9c3001038000b410121130b200c200e4105746a210d200c21024100210702400240024003400240200d20026b41e0004b0d002002200d470d02410021060c040b200341c0006a2002460d0220072002200341c0006a4120109c0522064100476a21072006450d02200241206a2206200341c0006a460d0220072006200341c0006a4120109c0522064100476a21072006450d02200241c0006a2206200341c0006a460d0220072006200341c0006a4120109c0522064100476a21072006450d02200241e0006a2206200341c0006a460d0220024180016a210220072006200341c0006a4120109c0522064100476a210720060d000c020b0b0340200341c0006a2002460d0120072002200341c0006a4120109c0522064100476a21072006450d0141002106200d200241206a2202470d000c020b0b410121060b024002400240024002400240024002400240200a41ff01710d002006450d010c080b20130d07200341f8036a41186a220d200341c0006a41186a290300370300200341f8036a41106a2213200341c0006a41106a290300370300200341f8036a41086a2214200341c0006a41086a290300370300200320032903403703f803024020102011460d0020112108201021110c020b201141016a22022011490d10201141017422082002200820024b1b220841ffffff3f712008470d10200841057422024100480d100240024020110d002002102821050c010b200520114105742002102c21050b20050d01200241011037000b200341f8036a41186a2206200341c0006a41186a290300370300200341f8036a41106a220d200341c0006a41106a290300370300200341f8036a41086a2214200341c0006a41086a290300370300200320032903403703f80302400240200e200f460d00200f2107200e210f0c010b200f41016a2202200f490d10200f41017422072002200720024b1b220741ffffff3f712007470d10200741057422024100480d1002400240200f0d0020021028210c0c010b200c200f4105742002102c210c0b200c0d00200241011037000b200c200f4105746a220220032903f803370000200241186a2006290300370000200241106a200d290300370000200241086a2014290300370000200e41016a210e024002402013450d00201020084d0d0120052010417f6a22104105746a2202290000210b2002290008211520022900102116200520084105746a220841186a200241186a29000037000020082016370010200820153700082008200b3700000b2007210f201121080c020b41c4f2c200200820101034000b200520114105746a220220032903f803370000200241186a200d290300370000200241106a2013290300370000200241086a2014290300370000201041016a21102006450d00200e20074d0d01200c200e417f6a220e4105746a2202290000210b2002290008211520022900102116200c20074105746a220741186a200241186a29000037000020072016370010200720153700082007200b3700000b2003419d046a200329030037000020034185046a200341c0006a41086a2903003700002003418d046a200341c0006a41106a29030037000020034195046a200341c0006a41186a290300370000200341a5046a200341086a290300370000200341ad046a200341106a290300370000200341b5046a200341186a290300370000200341013a00fc03200341073a00f803200320032903403700fd03200341c4046a200e360200200341c0046a2010360200200341bd046a200a3a000041014100200341f8036a10cc01200341f8036a41086a22024200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210220032802f8032207417f460d022002450d02200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f803220a450d0120032902fc03210b02402007450d002002102a0b200b422088a72102200ba7450d03200a102a0c030b41c4f2c2002007200e1034000b41c4d1c300413320034188056a419cd9c3001038000b410021020b024002400240024002400240024002400240201020124f22070d0041002002200e6b220a200a20024b1b2012490d0020034194046a200e360200200341f8036a41186a200f360200200341f8036a41106a201036020020034184046a20083602002003200c36028c042003200536028004200320123602fc03200320093602f803411a10282202450d01200241002900ec9643370000200241186a41002f008497433b0000200241106a41002900fc9643370000200241086a41002900f496433700002003429a808080a0033702ec01200320023602e8012003200341e8016a3602f0022003200341f0026a10c80120032802e801210220032802f0012107200341f0026a41186a22094200370300200341f0026a41106a220a4200370300200341f0026a41086a22064200370300200342003703f00220022007200341f0026a1000200341206a41186a2009290300370300200341206a41106a200a290300370300200341206a41086a2006290300370300200320032903f002370320024020032802ec01450d0020032802e801102a0b200341203602f4022003200341206a3602f002200341f8036a200341f0026a10b40302402008450d002005102a0b200f0d050c060b024020070d0020034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a290300370000200341033a00fc03200341073a00f803200320032903003700fd0341014100200341f8036a10cc010c040b20034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a290300370000200341023a00fc03200341073a00f803200320032903003700fd0341014100200341f8036a10cc01411e10282207450d01200741002900f6a743370000200741166a410029008ca843370000200741106a4100290086a843370000200741086a41002900fea7433700002003429e808080e0033702fc03200320073602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321072003280280042109200341f0026a41186a220a4200370300200341f0026a41106a22064200370300200341f0026a41086a220d4200370300200342003703f00220072009200341f0026a1000200341206a41186a200a290300370300200341206a41106a2006290300370300200341206a41086a200d290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341003602f803200341206a4120200341f8036a100621090240024020032802f803220a417f470d00411321070c010b024020090d00411321070c010b2003200a360284052003200936028005200341f8036a20034180056a10810120032802f80322074113460d03200341f0026a200341f8036a410472418401109a051a0240200a450d002009102a0b200341206a412010090b200341e8016a200341f0026a418401109a051a200341f8036a200341e8016a418401109a051a20074113460d03200341e0006a200341f8036a418401109a051a200320073602f803200341f8036a410472200341e0006a418401109a051a200341fc026a2002360200200341f0026a41086a2012360200200341003a00f402200341023a00f002200341e8016a200341f8036a200341f0026a10f40120032d00f001210220034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a2903003700002003419d046a20024102463a0000200341043a00fc03200341073a00f803200320032903003700fd0341014100200341f8036a10cc010c030b411a41011037000b411e41011037000b41c4d1c300413320034188056a419cd9c3001038000b411a10282202450d02200241002900ec9643370000200241186a41002f008497433b0000200241106a41002900fc9643370000200241086a41002900f496433700002003429a808080a0033702fc03200320023602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321072003280280042109200341f0026a41186a220a4200370300200341f0026a41106a22064200370300200341f0026a41086a22024200370300200342003703f00220072009200341f0026a1000200341206a41186a200a290300370300200341206a41106a2006290300370300200341206a41086a2002290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341206a41201009200341f8036a41086a22074200370300200342003703f80341cf96c300411d200341f8036a100820022007290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621070240024020032802f8032202417f460d00200320023602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032209450d0520032902fc03210b02402002450d002007102a0b2003200b3702ec01200320093602e8010c010b200341003602f001200342013703e8010b200341e8016a2003106e20032802f001210220032802ec01210a20032802e8012109200341f8036a41086a22074200370300200342003703f80341cf96c300411d200341f8036a1008200341f0026a41086a2007290300370300200320032903f8033703f0020240024020090d00200341f0026a411010090c010b2003410036028004200342013703f8032002200341f8036a10b40102402002450d00200241057421072009210203402003200341f8036a3602602002200341e0006a10c801200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b200a450d002009102a0b02402008450d002005102a0b200f450d010b200c102a0b410021074101210a41012106410121090c140b411a41011037000b41c4d1c300413320034188056a419cd9c3001038000b41e0a7c3002107411621080b02402011450d002005102a0b200f450d02200c102a0c020b41aba7c30021070b411321080b4101210a410121060c0b0b200741046a28020022082002470d00200241016a22082002490d03200241017422052008200520084b1b220841ffffff3f712008470d03200841057422054100480d030240024020020d002005102821020c010b200728020020024105742005102c21020b2002450d0420072002360200200741046a200836020020032802f00121020b200728020022052002410574220d6a22072003290320370000200741186a200341206a41186a290300370000200741106a200341206a41106a290300370000200741086a200341206a41086a2903003700002003200241016a22073602f001200341f8036a41086a220c4200370300200342003703f80341cf96c300411d200341f8036a1008200341f0026a41086a200c290300370300200320032903f8033703f0022003410036028004200342013703f8032007200341f8036a10b401024020072002490d00200d41206a21072005210203402003200341f8036a3602202002200341206a10c801200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b02402008450d002005102a0b200341f8036a2009418801109a051a200341e8016a41186a200341e0006a41186a290300370300200341e8016a41106a200341e0006a41106a290300370300200341e8016a41086a200341e0006a41086a290300370300200320032903603703e801411e10282202450d04200241002900f6a743370000200241166a410029008ca843370000200241106a4100290086a843370000200241086a41002900fea7433700002003429e808080e00337020420032002360200200320033602f002200341e8016a200341f0026a10c8012003280200210220032802082107200341f0026a41186a22084200370300200341f0026a41106a22054200370300200341f0026a41086a220c4200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a2005290300370300200341206a41086a200c290300370300200320032903f00237032002402003280204450d002003280200102a0b200341003602f802200342013703f002200341f8036a200341f0026a10eb0120032802f4022102200341206a412020032802f002220720032802f802100702402002450d002007102a0b200341f8036a106a412010282202450d0520022003290340370000200241186a200341c0006a41186a290300370000200241106a200341c0006a41106a290300370000200241086a200341c0006a41086a29030037000020034184026a4100360200200341f4016a428180808010370200200342013702fc01200320023602f001200320063602ec012003200a3602e801200341f8036a41186a200341e0006a41186a290300370300200341f8036a41106a200341e0006a41106a290300370300200341f8036a41086a200341e0006a41086a290300370300200320032903603703f803411a10282207450d06200741002900ec9643370000200741186a41002f008497433b0000200741106a41002900fc9643370000200741086a41002900f496433700002003429a808080a00337020420032007360200200320033602f002200341f8036a200341f0026a10c8012003280200210720032802082108200341f0026a41186a22054200370300200341f0026a41106a220c4200370300200341f0026a41086a220d4200370300200342003703f00220072008200341f0026a1000200341206a41186a2005290300370300200341206a41106a200c290300370300200341206a41086a200d290300370300200320032903f00237032002402003280204450d002003280200102a0b200341203602fc032003200341206a3602f803200341e8016a200341f8036a10b4032002102a20034185046a200341c0006a41086a2903003700002003418d046a200341c0006a41106a29030037000020034195046a200341c0006a41186a2903003700002003419d046a2003290360370000200341a5046a200341e0006a41086a290300370000200341ad046a200341e0006a41106a290300370000200341b5046a200341e0006a41186a290300370000200341c4046a2006360200200341c0046a200a360200200341003a00fc03200341073a00f803200320032903403700fd03200341f8036a21020b410021064101210a41014100200210cc012009102a0b41012109410021070c090b1031000b200541011037000b411e41011037000b412041011037000b411a41011037000b2009106a2009102a410021064101210a0c010b2009106a2009102a410121064100210a0b410121090c010b4100210941012106410021070b02402004410771417f6a220241024b0d0002400240024020020e03000102000b2009450d02200141086a280200450d02200141046a280200102a0c020b200a450d01200141046a2802002202106a2002102a0c010b2006450d00200141086a2802002202106a2002102a0b200020083602042000200736020020034190056a24000bf35c040b7f017e127f027e23004190056b220324000240024002400240024002400240024002400240024002400240024002400240024020012d000022040e0500010a0302000b2003418c046a4101360200200342013702fc03200341ccd1c5003602f803200341043602f402200341c4d1c5003602f0022003200341f0026a36028804200341f8036a41a8a6c300103e000b200141086a2802002105200141046a2802002106024020022d000020022d000172450d0041a39fc600210741112108410021094101210a02402005450d002006102a0b4101210b0c0f0b20062001410c6a280200220c10f001200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210202400240024020032802f8032207417f460d002002450d00200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f803220d450d0220032902fc03210e2007450d012002102a0c010b4101210d4200210e0b20064100200c1b2109200d41206a200d200e422088a722021b210f200641206a2006200c1b2110200d410020021b21112006200c4105746a2112200d20024105746a2113410021144100211541012116410021174100211841012119024003402014410174211a2014410574211b024002400240024002400340024020110d00200f211c2016211d2015211e201421080c040b20112102200f21072016211d2015211e20142108201b210a201a210b02400340024002402009450d0020022009460d06200220094120109c05221c450d06201c417f4c0d012007210f201d2116201e211520082114200221110c080b200341f8036a41186a2207201141186a290000370300200341f8036a41106a2208201141106a290000370300200341f8036a41086a2209201141086a290000370300200320112900003703f803024020142015470d00201441016a22022014490d0f2014410174220a2002200a20024b1b221541ffffff3f712015470d0f201541057422024100480d0f0240024020140d002002102821160c010b201620144105742002102c21160b2016450d030b201620144105746a220220032903f803370000200241186a2007290300370000200241106a2008290300370000200241086a2009290300370000410021094100200f200f20134622021b2111201a41026a211a201b41206a211b201441016a2114200f200f41206a20021b210f0c030b200341f8036a41186a221c200241186a290000370300200341f8036a41106a221f200241106a290000370300200341f8036a41086a2220200241086a290000370300200320022900003703f80302402008201e470d00200841016a22022008490d0e200b2002200b20024b1b221e41ffffff3f71201e470d0e201e41057422024100480d0e0240024020080d0020021028211d0c010b201d200a2002102c211d0b201d450d040b201d200a6a220220032903f803370000200241186a201c290300370000200241106a201f290300370000200241086a2020290300370000410020072007201346221c1b2102200b41026a210b200a41206a210a200841016a21082007200741206a201c1b221c21072002450d050c000b0b0b200241011037000b200241011037000b201d2116201e2115200821142007200741206a200720134622021b210f41002010201020124622081b21094100200720021b21112010201041206a20081b21100c030b410021112009450d01201c210f201d2116201e2115200821140b200341206a41186a2207200941186a290000370300200341206a41106a2208200941106a290000370300200341206a41086a220a200941086a29000037030020032009290000370320024020172018470d00201741016a22022017490d07201741017422092002200920024b1b221841ffffff3f712018470d07201841057422024100480d070240024020170d002002102821190c010b201920174105742002102c21190b2019450d030b201920174105746a22022003290320370000200241186a2007290300370000200241106a2008290300370000200241086a200a29030037000041002010201020124622021b2109201741016a21172010201041206a20021b21100c010b0b201d20082006200c10c5020240201e450d00201d102a0b02402018450d002019102a0b0240200ea7450d00200d102a0b200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f0022003410036028004200342013703f803200c200341f8036a10b4010240200c450d00200c41057421072006210203402002200341f8036a108f01200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b4101210a2005450d0f2006102a0c0f0b200241011037000b41c4d1c300413320034188056a419cd9c3001038000b200141216a2d0000210a200141246a2802002109200341186a200141196a290000370300200341106a200141116a290000370300200341086a200141096a29000037030020032001290001370300024002400240024020022d00000d002002280001220741ff01714101460d010b41b49fc60021070c010b200320074118763a0042200320074108763b01402003200241216a2d00003a005f2003200241196a2900003700572003200241116a29000037004f2003200241096a2900003700472003200241056a280000360043200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210702400240024002400240024002400240024020032802f8032208417f460d002007450d00200320083602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032202450d0220032902fc03210e2008450d012007102a0c010b4200210e410121020b2002200e422088a7200341c0006a10cd0121070240200ea7450d002002102a0b024020070d0041bea7c3002107411221080c090b411a10282202450d01200241002900b59643370000200241186a41002f00cd96433b0000200241106a41002900c59643370000200241086a41002900bd96433700002003429a808080a0033702fc03200320023602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321022003280280042107200341f0026a41186a22084200370300200341f0026a41106a220b4200370300200341f0026a41086a221e4200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a200b290300370300200341206a41086a201e290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341003602f803200341206a4120200341f8036a1006210220032802f8032207417f460d062002450d06200320073602f402200320023602f002200341f8036a200341f0026a10b303200328028004221e450d0220034194046a280200211420034190046a28020021202003418c046a280200211d41102108200341f8036a41106a280200211f200328028404211320032802fc03211020032802f803210b02402007450d002002102a0b41d0a7c3002107200b2009470d05201e201f4105746a210b201e210241002108024003400240200b20026b41e0004b0d002002200b470d02410021110c070b200341c0006a2002460d0520082002200341c0006a4120109c0522074100476a21082007450d05200241206a2207200341c0006a460d0520082007200341c0006a4120109c0522074100476a21082007450d05200241c0006a2207200341c0006a460d0520082007200341c0006a4120109c0522074100476a21082007450d05200241e0006a2207200341c0006a460d0520024180016a210220082007200341c0006a4120109c0522074100476a210820070d000c050b0b201e201f4105746a210b0340200341c0006a2002460d0420082002200341c0006a4120109c0522074100476a21082007450d0441002111200b200241206a2202470d000c050b0b41c4d1c300413320034188056a419cd9c3001038000b411a41011037000b41c4d1c300413320034188056a419cd9c3001038000b410121110b201d20144105746a211c201d21024100210702400240024003400240201c20026b41e0004b0d002002201c470d024100210b0c040b200341c0006a2002460d0220072002200341c0006a4120109c05220b4100476a2107200b450d02200241206a220b200341c0006a460d022007200b200341c0006a4120109c05220b4100476a2107200b450d02200241c0006a220b200341c0006a460d022007200b200341c0006a4120109c05220b4100476a2107200b450d02200241e0006a220b200341c0006a460d0220024180016a21022007200b200341c0006a4120109c05220b4100476a2107200b0d000c020b0b0340200341c0006a2002460d0120072002200341c0006a4120109c05220b4100476a2107200b450d014100210b201c200241206a2202470d000c020b0b4101210b0b024002400240024002400240024002400240200a41ff01710d00200b450d010c080b20110d07200341f8036a41186a221c200341c0006a41186a290300370300200341f8036a41106a2211200341c0006a41106a290300370300200341f8036a41086a220f200341c0006a41086a290300370300200320032903403703f8030240201f2013460d0020132108201f21130c020b201341016a22022013490d0d201341017422082002200820024b1b220841ffffff3f712008470d0d200841057422024100480d0d0240024020130d0020021028211e0c010b201e20134105742002102c211e0b201e0d01200241011037000b200341f8036a41186a220b200341c0006a41186a290300370300200341f8036a41106a221c200341c0006a41106a290300370300200341f8036a41086a220f200341c0006a41086a290300370300200320032903403703f8030240024020142020460d0020202107201421200c010b202041016a22022020490d0d202041017422072002200720024b1b220741ffffff3f712007470d0d200741057422024100480d0d0240024020200d0020021028211d0c010b201d20204105742002102c211d0b201d0d00200241011037000b201d20204105746a220220032903f803370000200241186a200b290300370000200241106a201c290300370000200241086a200f290300370000201441016a2114024002402011450d00201f20084d0d01201e201f417f6a221f4105746a2202290000210e2002290008212120022900102122201e20084105746a220841186a200241186a29000037000020082022370010200820213700082008200e3700000b20072120201321080c020b41c4f2c2002008201f1034000b201e20134105746a220220032903f803370000200241186a201c290300370000200241106a2011290300370000200241086a200f290300370000201f41016a211f200b450d00201420074d0d01201d2014417f6a22144105746a2202290000210e2002290008212120022900102122201d20074105746a220741186a200241186a29000037000020072022370010200720213700082007200e3700000b2003419d046a200329030037000020034185046a200341c0006a41086a2903003700002003418d046a200341c0006a41106a29030037000020034195046a200341c0006a41186a290300370000200341a5046a200341086a290300370000200341ad046a200341106a290300370000200341b5046a200341186a290300370000200341013a00fc03200341063a00f803200320032903403700fd03200341c4046a2014360200200341c0046a201f360200200341bd046a200a3a000041014100200341f8036a10cc01200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210220032802f8032207417f460d022002450d02200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f803220a450d0120032902fc03210e02402007450d002002102a0b200e422088a72102200ea7450d03200a102a0c030b41c4f2c200200720141034000b41c4d1c300413320034188056a419cd9c3001038000b410021020b024002400240024002400240024002400240201f20104f22070d004100200220146b220a200a20024b1b2010490d0020034194046a2014360200200341f8036a41186a2020360200200341f8036a41106a201f36020020034184046a20083602002003201d36028c042003201e36028004200320103602fc03200320093602f803411a10282202450d01200241002900b59643370000200241186a41002f00cd96433b0000200241106a41002900c59643370000200241086a41002900bd96433700002003429a808080a0033702ec01200320023602e8012003200341e8016a3602f0022003200341f0026a10c80120032802e801210220032802f0012107200341f0026a41186a22094200370300200341f0026a41106a220a4200370300200341f0026a41086a220b4200370300200342003703f00220022007200341f0026a1000200341206a41186a2009290300370300200341206a41106a200a290300370300200341206a41086a200b290300370300200320032903f002370320024020032802ec01450d0020032802e801102a0b200341203602f4022003200341206a3602f002200341f8036a200341f0026a10b40302402008450d00201e102a0b20200d050c060b024020070d0020034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a290300370000200341033a00fc03200341063a00f803200320032903003700fd0341014100200341f8036a10cc010c040b20034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a290300370000200341023a00fc03200341063a00f803200320032903003700fd0341014100200341f8036a10cc01411e10282207450d01200741002900eca643370000200741166a4100290082a743370000200741106a41002900fca643370000200741086a41002900f4a6433700002003429e808080e0033702fc03200320073602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321072003280280042109200341f0026a41186a220a4200370300200341f0026a41106a220b4200370300200341f0026a41086a221c4200370300200342003703f00220072009200341f0026a1000200341206a41186a200a290300370300200341206a41106a200b290300370300200341206a41086a201c290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341003602f803200341206a4120200341f8036a100621090240024020032802f803220a417f470d00411321070c010b024020090d00411321070c010b2003200a360284052003200936028005200341f8036a20034180056a10810120032802f80322074113460d03200341f0026a200341f8036a410472418401109a051a0240200a450d002009102a0b200341206a412010090b200341e8016a200341f0026a418401109a051a200341f8036a200341e8016a418401109a051a20074113460d03200341e0006a200341f8036a418401109a051a200320073602f803200341f8036a410472200341e0006a418401109a051a200341fc026a2002360200200341f0026a41086a2010360200200341003a00f402200341013a00f002200341e8016a200341f8036a200341f0026a10f40120032d00f001210220034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a2903003700002003419d046a20024102463a0000200341043a00fc03200341063a00f803200320032903003700fd0341014100200341f8036a10cc010c030b411a41011037000b411e41011037000b41c4d1c300413320034188056a419cd9c3001038000b411a10282202450d02200241002900b59643370000200241186a41002f00cd96433b0000200241106a41002900c59643370000200241086a41002900bd96433700002003429a808080a0033702fc03200320023602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321072003280280042109200341f0026a41186a220a4200370300200341f0026a41106a220b4200370300200341f0026a41086a22024200370300200342003703f00220072009200341f0026a1000200341206a41186a200a290300370300200341206a41106a200b290300370300200341206a41086a2002290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341206a41201009200341f8036a41086a22074200370300200342003703f803419896c300411d200341f8036a100820022007290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621070240024020032802f8032202417f460d00200320023602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032209450d0520032902fc03210e02402002450d002007102a0b2003200e3702ec01200320093602e8010c010b200341003602f001200342013703e8010b200341e8016a2003106e20032802f001210220032802ec01210a20032802e8012109200341f8036a41086a22074200370300200342003703f803419896c300411d200341f8036a1008200341f0026a41086a2007290300370300200320032903f8033703f0020240024020090d00200341f0026a411010090c010b2003410036028004200342013703f8032002200341f8036a10b40102402002450d00200241057421072009210203402003200341f8036a3602602002200341e0006a10c801200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b200a450d002009102a0b02402008450d00201e102a0b2020450d010b201d102a0b410021074101210a4101210b410121090c140b411a41011037000b41c4d1c300413320034188056a419cd9c3001038000b41e0a7c3002107411621080b02402013450d00201e102a0b2020450d02201d102a0c020b41aba7c30021070b411321080b4101210a4101210b0c0b0b200141086a280200210941b49fc60021074113210820022d00000d052002280001220a41ff01714101470d05200141046a280200210b2003200a4118763a00422003200a4108763b01402003200241216a2d00003a005f2003200241196a2900003700572003200241116a29000037004f2003200241096a2900003700472003200241056a280000360043200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210702400240024002400240024002400240024002400240024020032802f8032208417f460d002007450d00200320083602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032202450d0220032902fc03210e2008450d012007102a0c010b4200210e410121020b2002200e422088a7200341c0006a10cd0121070240200ea7450d002002102a0b024020070d0041b8a6c3002107411521080c100b2003410036028004200342013703f8032009200341f8036a10eb0120032802fc032107200328028004210820032802f8032102200341f0026a41186a220a4200370300200341f0026a41106a221e4200370300200341f0026a41086a221d4200370300200342003703f00220022008200341f0026a1000200341e0006a41186a2208200a290300370300200341e0006a41106a220a201e290300370300200341e0006a41086a221e201d290300370300200320032903f00237036002402007450d002002102a0b200341f8036a41186a2008290300370300200341f8036a41106a200a290300370300200341f8036a41086a201e290300370300200320032903603703f803411e10282202450d01200241002900eca643370000200241166a4100290082a743370000200241106a41002900fca643370000200241086a41002900f4a6433700002003429e808080e0033702ec01200320023602e8012003200341e8016a3602f002200341f8036a200341f0026a10c80120032802e801210220032802f0012107200341f0026a41186a22084200370300200341f0026a41106a220a4200370300200341f0026a41086a221e4200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a200a290300370300200341206a41086a201e290300370300200320032903f002370320024020032802ec01450d0020032802e801102a0b200341206a41204101410041001003417f470d02200341f8036a41086a22024200370300200342003703f8030240200b4102490d00418aa7c3004121200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f0024100210a200341003602f803200341f0026a4110200341f8036a10062102024020032802f8032207417f460d002002450d0020074104490d052002280000210a2002102a0b200341f8036a41086a22024200370300200342003703f803418aa7c3004121200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621020240024020032802f8032207417f460d002002450d00024020074104490d00200228000021072002102a200741016a21070c020b41c4d1c300413320034188056a419cd9c3001038000b410121070b200341f8036a41086a22024200370300200342003703f803418aa7c3004121200341f8036a1008200341f0026a41086a22082002290300370300200320032903f8033703f002200320073602f803200341f0026a4110200341f8036a4104100720024200370300200342003703f803419896c300411d200341f8036a100820082002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210220032802f8032207417f460d062002450d06200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f8032208450d0520032902fc03210e02402007450d002002102a0b200320083602e8012003200e3702ec01200341206a41186a200341e0006a41186a290300370300200341206a41106a200341e0006a41106a290300370300200341206a41086a200341e0006a41086a29030037030020032003290360370320200341e8016a2107200e422088a72202200ea72208470d090c080b41fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f00241002102200341003602f803200341f0026a4110200341f8036a10062108024020032802f8032207417f460d00200320073602ec01200320083602e801200341f8036a200341e8016a106d20032802f803220a450d0720032902fc03210e02402007450d002008102a0b200e422088a72102200ea7450d00200a102a0b200341f8036a2009418801109a051a200341fc026a2002360200200341f0026a41086a4101360200200341003a00f402200341013a00f002200341e8016a200341f8036a200341f0026a10f40120032d00f001210220034185046a200341e0006a41086a2903003700002003418d046a200341f0006a29030037000020034195046a200341f8006a2903003700002003419d046a20024102463a0000200341043a00fc03200341063a00f803200320032903603700fd03200341f8036a21020c090b41c4d1c300413320034188056a419cd9c3001038000b411e41011037000b41cda6c3002107411f21080c0c0b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b41002102200341003602f001200342013703e801200341206a41186a200341e0006a41186a290300370300200341206a41106a200341e0006a41106a290300370300200341206a41086a200341e0006a41086a29030037030020032003290360370320200341e8016a21070c010b41c4d1c300413320034188056a419cd9c3001038000b200741046a28020022082002470d00200241016a22082002490d022002410174221e2008201e20084b1b220841ffffff3f712008470d022008410574221e4100480d020240024020020d00201e102821020c010b20072802002002410574201e102c21020b2002450d0320072002360200200741046a200836020020032802f00121020b2007280200221e2002410574221c6a22072003290320370000200741186a200341206a41186a290300370000200741106a200341206a41106a290300370000200741086a200341206a41086a2903003700002003200241016a22073602f001200341f8036a41086a221d4200370300200342003703f803419896c300411d200341f8036a1008200341f0026a41086a201d290300370300200320032903f8033703f0022003410036028004200342013703f8032007200341f8036a10b401024020072002490d00201c41206a2107201e210203402003200341f8036a3602202002200341206a10c801200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b02402008450d00201e102a0b200341f8036a2009418801109a051a200341e8016a41186a200341e0006a41186a290300370300200341e8016a41106a200341e0006a41106a290300370300200341e8016a41086a200341e0006a41086a290300370300200320032903603703e801411e10282202450d03200241002900eca643370000200241166a4100290082a743370000200241106a41002900fca643370000200241086a41002900f4a6433700002003429e808080e00337020420032002360200200320033602f002200341e8016a200341f0026a10c8012003280200210220032802082107200341f0026a41186a22084200370300200341f0026a41106a221e4200370300200341f0026a41086a221d4200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a201e290300370300200341206a41086a201d290300370300200320032903f00237032002402003280204450d002003280200102a0b200341003602f802200342013703f002200341f8036a200341f0026a10eb0120032802f4022102200341206a412020032802f002220720032802f802100702402002450d002007102a0b200341f8036a106a412010282202450d0420022003290340370000200241186a200341c0006a41186a290300370000200241106a200341c0006a41106a290300370000200241086a200341c0006a41086a29030037000020034184026a4100360200200341f4016a428180808010370200200342013702fc01200320023602f0012003200b3602ec012003200a3602e801200341f8036a41186a200341e0006a41186a290300370300200341f8036a41106a200341e0006a41106a290300370300200341f8036a41086a200341e0006a41086a290300370300200320032903603703f803411a10282207450d05200741002900b59643370000200741186a41002f00cd96433b0000200741106a41002900c59643370000200741086a41002900bd96433700002003429a808080a00337020420032007360200200320033602f002200341f8036a200341f0026a10c8012003280200210720032802082108200341f0026a41186a221e4200370300200341f0026a41106a221d4200370300200341f0026a41086a221c4200370300200342003703f00220072008200341f0026a1000200341206a41186a201e290300370300200341206a41106a201d290300370300200341206a41086a201c290300370300200320032903f00237032002402003280204450d002003280200102a0b200341203602fc032003200341206a3602f803200341e8016a200341f8036a10b4032002102a20034185046a200341c0006a41086a2903003700002003418d046a200341c0006a41106a29030037000020034195046a200341c0006a41186a2903003700002003419d046a2003290360370000200341a5046a200341e0006a41086a290300370000200341ad046a200341e0006a41106a290300370000200341b5046a200341e0006a41186a290300370000200341c4046a200b360200200341c0046a200a360200200341003a00fc03200341063a00f803200320032903403700fd03200341f8036a21020b4100210b4101210a41014100200210cc012009102a0c070b1031000b201e41011037000b411e41011037000b412041011037000b411a41011037000b2009106a2009102a4100210b4101210a0c040b200141046a280200210941b49fc60021074113210820022d00000d022002280001220a41ff01714101470d022003200a4118763a00622003200a4108763b01602003200241216a2d00003a007f2003200241196a2900003700772003200241116a29000037006f2003200241096a2900003700672003200241056a2800003600634200210e200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621080240024020032802f8032207417f460d00200320073602ec01200320083602e801200341f8036a200341e8016a106d20032802f8032202450d0320032902fc03210e2007450d012008102a0c010b410121020b2002200e422088a7200341e0006a10cd0121070240200ea7450d002002102a0b024020070d0041b8a6c3002107411521080c030b4100210a2003410036028004200342013703f8032009200341f8036a10eb0120032802fc032107200328028004210820032802f8032102200341f0026a41186a220b4200370300200341f0026a41106a221e4200370300200341f0026a41086a221d4200370300200342003703f00220022008200341f0026a1000200341e8016a41186a2208200b290300370300200341e8016a41106a221c201e290300370300200341e8016a41086a221e201d290300370300200320032903f0023703e80102402007450d002002102a0b200341f8036a2009418801109a051a200341f0026a410d6a200341e0006a41086a290300370000200341f0026a41156a200341e0006a41106a290300370000200341f0026a411d6a200341e0006a41186a2903003700004101210b200341013a00f402200320032903603700f502200341013a00f002200341c0006a200341f8036a200341f0026a10f40120032d00482102200341f8036a410d6a201e290300370000200341f8036a41156a201c290300370000200341f8036a411d6a20082903003700002003419d046a20024102463a0000200341053a00fc03200341063a00f803200320032903e8013700fd0341014100200341f8036a10cc012009102a0b41012109410021070c040b41c4d1c300413320034188056a419cd9c3001038000b2009106a2009102a4101210b4100210a0b410121090c010b410021094101210b410021070b02402004410771417f6a220241024b0d0002400240024020020e03000102000b2009450d02200141086a280200450d02200141046a280200102a0c020b200a450d01200141046a2802002202106a2002102a0c010b200b450d00200141086a2802002202106a2002102a0b200020083602042000200736020020034190056a24000bfad30106017f027e017f017e157f017e230041b0086b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e12000102030405060708090a0b0c0d0e0f1013000b200341ac066a41013602002003420137029c06200341ccd1c5003602980620034104360254200341c4d1c5003602502003200341d0006a3602a80620034198066a41d4d1c500103e000b200141106a2903002104200141086a2903002105200141046a28020021062002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241046a2d00002115200241026a2f0100211602400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002118200241056a2d0000211920022d0001211a200320073703980641002102201a41ff01714101460d010b410121024104211941002117410021180b20032007370348200320083a0047200320093a00462003200a3b01442003200b3a00432003200c3a00422003200d3b01402003200e3a003f2003200f3a003e200320103b013c200320113a003b200320123a003a200320133b0138200320143a0037200320153a0032200320163b01302003201841ffff0371410874201741187472201941ff017172220a36003302402002450d00410f210841ea9fc6002109024002400240024002400240200a0e0700010203040565000b20032800372109200328003b21080c640b410e210841dc9fc60021090c630b410c210841d09fc60021090c620b4109210841c79fc60021090c610b4113210841b49fc60021090c600b4111210841a39fc60021090c5f0b200341b8036a41186a200341306a41186a290300370300200341b8036a41106a200341306a41106a290300370300200341b8036a41086a200341306a41086a290300370300200320032903303703b8030240200542808084fea6dee1115441002004501b450d0041e4d1c5002109410d21080c5f0b2003200341b8036a2005200410830202402003280200450d0041f1d1c5002109411a21080c5f0b20034188086a41086a220242003703002003420037038808419090c600411920034188086a1008200341e8076a41086a200229030037030020032003290388083703e807410021082003410036029806200341e8076a411020034198066a1006210202402003280298062209417f460d002002450d0020094104490d18200228000021082002102a0b20034188086a41086a220942003703002003420037038808419090c600411920034188086a1008200341e8076a41086a220a200929030037030020032003290388083703e8072003200841016a36029806200341e8076a411020034198066a41041007412010282202450d18200220032903b803370000200341ac066a428180808010370200200241186a200341b8036a41186a2217290300370000200241106a200341b8036a41106a2218290300370000200241086a200341b8036a41086a22192903003700002003200537039806200320023602a806200320043703a006200820034198066a10c404200341a0026a200610cf03200341d0006a200341a0026a418801109a051a200341e4016a2019290300370200200341ec016a2018290300370200200341f4016a2017290300370200200320083602d801200320032903b8033702dc0120094200370300200342003703880841ac89c500411520034188086a1008200a200929030037030020032003290388083703e8072003410036029806200341e8076a411020034198066a10062109024002402003280298062202417f460d002002210a20090d010b200341003602a0062003420137039806410020034198066a10b40120032802a0062102200328029c06210a20032802980621090b200320023602d0072003200a3602cc07200320093602c807024002402002450d0020034198066a20092002410110d6022003280298064101470d0120032802cc07450d5d20032802c807102a0c5d0b4101200341c8076a10b40120032802d801210a0240024020032802cc07220920032802d00722026b4104490d0020032802c80721090c010b200241046a22172002490d4b200941017422022017200220174b1b22024100480d4b0240024020090d002002102821090c010b20032802c80720092002102c21090b2009450d1b200320023602cc07200320093602c80720032802d00721020b2003200241046a3602d007200920026a200a360000200341d0006a200341c8076a10eb01200341dc016a200341c8076a108f010c5a0b200328029c0621170240200341a4066a2802002202200341a0066a2802002209460d0020032802d007200220096b6a220a41b0016a2218417f4c0d1b0240024020180d00410121190c010b201810282219450d1d0b2003201836028c0820032019360288082003200a36029008200320034188086a36029806201720034198066a200210d701200a2002490d1d2003280290082217200a490d1e20032802d00722172009490d1f200328028808211820032802c80721192003200a20026b220a3602302003201720096b221736028002200a2017470d20201820026a201920096a200a109a051a20032802d801210a02400240200328028c08220920032802900822026b4104490d0020032802880821090c010b200241046a22172002490d4b200941017422022017200220174b1b22024100480d4b0240024020090d002002102821090c010b20032802880820092002102c21090b2009450d222003200236028c08200320093602880820032802900821020b2003200241046a36029008200920026a200a360000200341d0006a20034188086a10eb01200341dc016a20034188086a108f012003280290082109200328028c08210a200328028808210220032802cc07450d5b20032802c807102a0c5b0b2003200341c8076a36029806201720034198066a200910d70120032802d801210a0240024020032802cc07220920032802d00722026b4104490d0020032802c80721090c010b200241046a22172002490d4a200941017422022017200220174b1b22024100480d4a0240024020090d002002102821090c010b20032802c80720092002102c21090b2009450d22200320023602cc07200320093602c80720032802d00721020b2003200241046a3602d007200920026a200a360000200341d0006a200341c8076a10eb01200341dc016a200341c8076a108f010c590b200141046a28020021162002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d0001211a200320073703980641002102201a41ff01714101460d010b410121024104211841002117410021060b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201741187472201841ff017172220a3600830202402002450d00410f210841ea9fc6002109200a0e070f1213141555560f0b200341d0006a41186a20034180026a41186a290300370300200341d0006a41106a20034180026a41106a290300370300200341d0006a41086a20034180026a41086a290300370300200320032903800237035020034198066a201610b804024020032802a80622170d00418bd2c5002109412421084101210a0c570b200341b4066a280200210920034198066a41186a280200210820032802ac062102200341086a200341d0006a200329029c062207422086200335029806842204200341a4066a350200422086200742208884220710830220032802080d53200341306a41186a200341d0006a41186a290300370300200341306a41106a220a200341d0006a41106a290300370300200341306a41086a2218200341d0006a41086a29030037030020032003290350370330024020082002460d0020022106200821020c520b200241016a22062002490d48200241017422192006201920064b1b220641ffffff3f712006470d48200641057422194100480d480240024020020d002019102821170c010b201720024105742019102c21170b20170d51201941011037000b200141026a2d00002116200141046a280200211a20012d0001211b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d0001211c200320073703980641002102201c41ff01714101460d010b410121024104211841002117410021060b20032007370348200320083a0047200320093a00462003200a3b0144200320193a00432003200b3a00422003200c3b01402003200d3a003f2003200e3a003e2003200f3b013c200320103a003b200320113a003a200320123b0138200320133a0037200320143a0032200320153b01302003200641ffff0371410874201741187472201841ff017172220a36003302402002450d00410f210841ea9fc60021090240200a0e0700121314155556000b20032800372109200328003b21084101210a0c560b20034180026a41186a200341306a41186a290300220737030020034180026a41106a200341306a41106a290300220437030020034180026a41086a200341306a41086a290300220537030020032003290330221d3703800220034198066a41186a200737030020034198066a41106a200437030020034198066a41086a20053703002003201d3703980620034198066a201a201b41ff0171410047201610c50421090c4f0b200141026a2d00002116200141046a280200211a20012d0001211b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d0001211c200320073703980641002102201c41ff01714101460d010b410121024104211841002117410021060b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201741187472201841ff017172220a3600830202402002450d00410f210841ea9fc6002109200a0e070d1011121353540d0b200341d0006a41186a20034180026a41186a290300370300200341d0006a41106a20034180026a41106a290300370300200341d0006a41086a20034180026a41086a2903003703002003200329038002370350410f10282202450d1f200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f00137029c062003200236029806200341d0006a20034198066a108f0120032802a00621022003280298062108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a0023703300240200328029c06450d00200328029806102a0b20034198066a200341306a412010fd01200341e8046a41026a220a20032d009b063a0000200341e8076a41086a200341ac066a290200370300200341e8076a410d6a2217200341b1066a290000370000200320032f0099063b01e8042003200341a4066a2902003703e807410121020240024020032d0098064101460d00410b210841d8d2c50021090c010b20034198066a41086a2802002108200328029c062109200341c0046a41026a200a2d00003a000020034188056a41086a200341e8076a41086a29030037030020034188056a410d6a2017290000370000200320032f01e8043b01c004200320032903e80737038805410021020b200341106a41026a200341c0046a41026a2d00003a000020034188086a41086a220a20034188056a41086a29030037030020034188086a41106a20034188056a41106a290300370300200320032f01c0043b011020032003290388053703880820020d53200341d0056a41026a200341106a41026a2d000022023a0000200341b8036a41086a2217200a290300370300200341b8036a410d6a220a20034188086a410d6a290000370000200320032f011022063b01d00520032003290388083703b803200341ab066a2017290300370000200341b0066a200a290000370000200320023a009a06200320063b0198062003200836009f062003200936009b06200320032903b8033700a30620034198066a201a201b41ff0171410047201610c50421090c4e0b41a6f5c5002109410e210820022d0000417f6a221941024b0d52200141046a280200210b4101210a4101210641012118410121170240024020190e03005d01000b200241046a2d00000d534101210a410121064101211841012117200241086a28020041036c2002410c6a280200410174490d5c0b20034198066a200b10ca03024020032802980622024113470d0041f3d4c5002109410d21084101210a0c540b200341a0026a20034198066a410472419401109a051a20032002360250200341d0006a410472200341a0026a419401109a051a200341003602a0062003420137039806200341d0006a20034198066a10eb01200328029c06210820032802a00621092003280298062102200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220022009200341a0026a1000200341b8036a41186a2209200a290300370300200341b8036a41106a220a2017290300370300200341b8036a41086a22172006290300370300200320032903a0023703b80302402008450d002002102a0b20034198066a41186a200929030037030020034198066a41106a200a29030037030020034198066a41086a2017290300370300200320032903b80337039806411710282202450d1f200241002900e3d2453700002002410f6a41002900f2d245370000200241086a41002900ebd24537000020034297808080f0023702d405200320023602d0052003200341d0056a3602a00220034198066a200341a0026a10c80120032802d005210220032802d8052108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220022008200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a002370330024020032802d405450d0020032802d005102a0b4101210a200341306a41204101410041001003417f460d4c200341d0006a106a4180d5c5002109412521080c530b200141046a280200210a41a6f5c5002109410e210820022d0000417f6a221741024b0d4a0240024020170e03004c01000b200241086a2802004101742002410c6a280200490d4b200241046a28020041ff01710d4b0b20034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e8070240200341e8076a41104101410041001003417f460d004194d3c5002109411521080c4b0b200341003602a0062003420137039806200a20034198066a10eb01200328029c06210820032802a00621092003280298062102200341a0026a41186a22174200370300200341a0026a41106a22064200370300200341a0026a41086a22184200370300200342003703a00220022009200341a0026a1000200341d0006a41186a22092017290300370300200341d0006a41106a2006290300370300200341d0006a41086a2018290300370300200320032903a00237035002402008450d002002102a0b20034198066a41186a200929030037030020034198066a41106a200341d0006a41106a29030037030020034198066a41086a200341d0006a41086a2903003703002003200329035037039806411310282202450d1f200241002900a9d3453700002002410f6a41002800b8d345360000200241086a41002900b1d34537000020034293808080b0023702d405200320023602d0052003200341d0056a3602a00220034198066a200341a0026a10c80120032802d005210220032802d8052108200341a0026a41186a22094200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220022008200341a0026a1000200341306a41186a2009290300370300200341306a41106a2017290300370300200341306a41086a2006290300370300200320032903a002370330024020032802d405450d0020032802d005102a0b200341b8036a200341306a10e103024020032802bc032202450d0020032802b803210820032802c0032109109801211702402009450d002002102a0b201720084f0d0041fad2c5002109411a21080c4b0b20034198066a200a418801109b051a200341003a00a00720034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341003602a802200342013703a00220034198066a200341a0026a10eb01024020032d00a007220241024b0d00024002400240024020020e03000102000b410021080c020b410121080c010b410221080b200320083a00a8080240024020032802a40220032802a8022202460d0020032802a00221090c010b200241016a22082002490d46200241017422092008200920084b1b22084100480d460240024020020d002008102821090c010b20032802a00220022008102c21090b2009450d22200320083602a402200320093602a00220032d00a808210820032802a80221020b2003200241016a3602a802200920026a20083a00000b20032802a4022102200341e8076a411020032802a002220820032802a802100702402002450d002008102a0b20034198066a106a200a102a4100210a410121060c480b200141046a28020021080240024020022d0000417f6a220941024b0d00024020090e03000102000b200241046a2d00000d00200241086a2802004102742002410c6a28020041036c4f0d010b2008106a2008102a41a6f5c5002109410e2108410021064101210a410121180c530b20034198066a2008418801109a051a200341023a00a00720034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341003602582003420137035020034198066a200341d0006a10eb01024020032d00a007220241024b0d00024002400240024020020e03000102000b410021090c020b410121090c010b410221090b200320093a00a80802400240200328025420032802582202460d002003280250210a0c010b200241016a22092002490d452002410174220a2009200a20094b1b22094100480d450240024020020d0020091028210a0c010b200328025020022009102c210a0b200a450d22200320093602542003200a36025020032d00a8082109200328025821020b2003200241016a360258200a20026a20093a00000b20032802542102200341e8076a4110200328025022092003280258100702402002450d002009102a0b20034198066a106a2008102a410021064101210a0c470b200141046a28020021080240024020022d0000417f6a220941024b0d00024020090e03000102000b200241086a2802002002410c6a280200490d00200241046a28020041ff0171450d010b2008106a2008102a41a6f5c5002109410e2108410021184101210a410121060c520b20034198066a2008418801109a051a200341013a00a00720034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341003602582003420137035020034198066a200341d0006a10eb01024020032d00a007220241024b0d00024002400240024020020e03000102000b410021090c020b410121090c010b410221090b200320093a00a80802400240200328025420032802582202460d002003280250210a0c010b200241016a22092002490d442002410174220a2009200a20094b1b22094100480d440240024020020d0020091028210a0c010b200328025020022009102c210a0b200a450d22200320093602542003200a36025020032d00a8082109200328025821020b2003200241016a360258200a20026a20093a00000b20032802542102200341e8076a4110200328025022092003280258100702402002450d002009102a0b20034198066a106a2008102a410021184101210a410121060c470b200141286a2802002118200141246a2802002106200341e8056a200141196a290000370300200341e0056a200141116a290000370300200341d0056a41086a200141096a290000370300200320012900013703d0054101210a41a6f5c5002109410e210820022d0000417e6a221741014b0d4f0240024020170e020001000b200241046a2d00000d50200241086a28020041036c2002410c6a280200410174490d500b20034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e80720034198066a200341e8076a10df032003280298062102200341a0026a20034198066a410472418401109a051a200320032800a107360288082003200341a4076a28000036008b08024020024113470d0041f2d3c5002109411021080c500b200341a0076a2d00002108200341b8036a200341a0026a418401109a051a20032002360250200341d0006a410472200341b8036a418401109a051a200841ff01710d4341c8d3c5002109412a21080c440b200341a0056a200141196a29000037030020034188056a41106a200141116a29000037030020034188056a41086a200141096a2900003703002003200129000137038805200241216a2f0000200241236a2d00004110747221082002411d6a2f00002002411f6a2d00004110747221092002410d6a2f00002002410f6a2d000041107472210a200241096a2f00002002410b6a2d0000411074722117200241056a2f0000200241076a2d0000411074722106200241206a2d0000210b200241106a2d0000210c2002410c6a2d0000210d200241086a2d0000210e0240024020022d00004102460d00410121180c010b200241246a2802002119200241116a2900002107200241046a2d0000210f2003200241196a2800003602a0062003200737039806410121180240200f4101460d000c010b2007421888a7210f2007a7210241002118200329029c0621070b200320083b019c022003419e026a20084110763a0000200320093b0198022003419a026a20094110763a0000200320023b018c02410e210820034180026a410e6a20024110763a00002003200a3b0188022003418a026a200a4110763a0000200320193a009f022003200b3a009b0220032007370390022003200f3a008f022003200c3a008b022003200d3a0087022003200e3a008302200320173b018402200320174110763a008602200320063b018002200320064110763a00820202402018450d0041a6f5c50021094101210a0c4f0b200341d0056a41186a20034180026a41186a290300370300200341d0056a41106a20034180026a41106a290300370300200341d0056a41086a20034180026a41086a29030037030020032003290380023703d00520034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e80720034198066a200341e8076a10df032003280298062102200341a0026a20034198066a4104722208418401109a051a2003200341a4076a28000036008b08200320032800a10736028808024020024113460d00200341d0006a200341a0026a418401109a051a20032002360298062008200341d0006a418401109a051a200341003602a802200342013703a00220034198066a200341a0026a10eb0120032802a402210820032802a802210920032802a0022102200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220022009200341a0026a1000200341b8036a41186a200a290300370300200341b8036a41106a2017290300370300200341b8036a41086a2006290300370300200320032903a0023703b80302402008450d002002102a0b20034188056a200341b8036a4120109c05210220034198066a106a02402002450d00411021084182d4c50021094101210a0c500b411310282202450d20200241002900a9d3453700002002410f6a41002800b8d345360000200241086a41002900b1d34537000020034293808080b002370254200320023602502003200341d0006a3602a00220034188056a200341a0026a10c8012003280250210220032802582108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220022008200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a00237033002402003280254450d002003280250102a0b20034198066a200341306a10e103200328029c0622170d374101211741002118410021190c380b411421084192d4c50021094101210a0c4e0b4101210a20022d000120022d0000720d34200141046a28020010ce03410021090c490b4101210a20022d000120022d0000720d332001410c6a2802002119200141086a2802002108200141046a2802002109411710282202450d1e2002410f6a41002900918945370000200241086a410029008a894537000020024100290082894537000020024117412e102c2202450d1f2002200936001742002107200341a0026a41186a22174200370300200341a0026a41106a22064200370300200341a0026a41086a22184200370300200342003703a0022002411b200341a0026a1000200341306a41186a2017290300370300200341306a41106a2006290300370300200341306a41086a2018290300370300200320032903a0023703302002102a2003410036029806200341306a412020034198066a10062102024002402003280298062206417f470d00410821170c010b024020020d00410821170c010b200320063602542003200236025020034198066a200341d0006a1080012003280298062217450d21200329029c0621072006450d002002102a0b2007422088a721020240024002400240201720084190016c6a2206450d00200820024f0d0020062802004113460d01201720084190016c6a22084188016a2802002019470d012006106a20064113360200200841046a200341a0026a418401109a051a2008418c016a2003418b086a28000036000020084189016a200328008808360000411710282208450d252008410f6a41002900918945370000200841086a410029008a894537000020084100290082894537000020084117412e102c2208450d2620082009360017200341a0026a41186a22094200370300200341a0026a41106a22064200370300200341a0026a41086a22184200370300200342003703a0022008411b200341a0026a1000200341306a41186a2009290300370300200341306a41106a2006290300370300200341306a41086a2018290300370300200320032903a0023703302008102a20034198066a2017200210ac02200341306a4120200328029806220820032802a00610070240200328029c06450d002008102a0b20024190016c2108201721020340024020022802004113460d002002106a0b20024190016a2102200841f07e6a22080d000b410021092007a70d030c4c0b2002450d010b20024190016c2108201721020340024020022802004113460d002002106a0b20024190016a2102200841f07e6a22080d000b0b41a5d5c5002109411221082007a7450d4d2017102a0c4d0b2017102a0c480b200341b8036a41186a200141196a290000370300200341b8036a41106a200141116a290000370300200341b8036a41086a200141096a290000370300200320012900013703b8032002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d00012116200320073703980641002102201641ff01714101460d010b410121024100210641042118410021170b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201841ff017172201741187472220a3600830202402002450d00410f210841ea9fc6002109200a0e07040708090a4a4b040b200341c0046a41186a20034180026a41186a290300370300200341c0046a41106a20034180026a41106a290300370300200341c0046a41086a20034180026a41086a29030037030020032003290380023703c004410f10282202450d22200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f00137029c062003200236029806200341b8036a20034198066a108f0120032802a00621022003280298062108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a0023703300240200328029c06450d00200328029806102a0b0240200341306a41204101410041001003417f460d0041ccd4c5002109410f21084101210a0c4c0b200341d0006a41186a200341c0046a41186a290300370300200341d0006a41106a200341c0046a41106a290300370300200341d0006a41086a200341c0046a41086a290300370300200320032903c00437035020034198066a41186a200341b8036a41186a29030037030020034198066a41106a200341b8036a41106a29030037030020034198066a41086a200341b8036a41086a290300370300200320032903b80337039806410f10282202450d2341002109200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f0013702d405200320023602d00520034198066a200341d0056a108f0120032802d805210220032802d0052108200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220082002200341a0026a1000200341306a41186a200a290300370300200341306a41106a2017290300370300200341306a41086a2006290300370300200320032903a002370330024020032802d405450d0020032802d005102a0b2003412036029c062003200341306a36029806200341d0006a20034198066a10ff014101210a0c4b0b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d00012116200320073703980641002102201641ff01714101460d010b410121024100210641042118410021170b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201841ff017172201741187472220a3600830202402002450d00410f210841ea9fc6002109200a0e070306070809494a030b200341c0046a41186a20034180026a41186a2903002207370300200341c0046a41106a20034180026a41106a2903002204370300200341c0046a41086a20034180026a41086a29030022053703002003200329038002221d3703c00420034198066a41186a200737030020034198066a41106a200437030020034198066a41086a20053703002003201d37039806410f10282202450d2341002109200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f0013702542003200236025020034198066a200341d0006a108f012003280258210220032802502108200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220082002200341a0026a1000200341306a41186a200a290300370300200341306a41106a2017290300370300200341306a41086a2006290300370300200320032903a00237033002402003280254450d002003280250102a0b200341306a412010094101210a0c460b200341d0056a41186a200141196a290000370300200341d0056a41106a200141116a290000370300200341d0056a41086a200141096a290000370300200320012900013703d0052002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d00012116200320073703980641002102201641ff01714101460d010b410121024100210641042118410021170b200320073703d804200320083a00d704200320093a00d6042003200a3b01d404200320193a00d3042003200b3a00d2042003200c3b01d0042003200d3a00cf042003200e3a00ce042003200f3b01cc04200320103a00cb04200320113a00ca04200320123b01c804200320133a00c704200320143a00c204200320153b01c0042003200641ffff0371410874201841ff017172201741187472220a3600c30402402002450d00410f210841ea9fc60021090240200a0e070006070809494a000b20032800c704210920032800cb0421084101210a0c4a0b200341b8036a41186a200341c0046a41186a290300370300200341b8036a41106a200341c0046a41106a290300370300200341b8036a41086a200341c0046a41086a290300370300200320032903c0043703b803410f10282202450d23200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f0013702cc07200320023602c807200341d0056a200341c8076a108f0120032802d007210220032802c8072108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a002370330024020032802cc07450d0020032802c807102a0b20034198066a200341306a412010fd0120034180026a41086a200341a1066a29000037030020034190026a200341a9066a29000037030020034180026a41186a200341b1066a290000370300200320032900990637038002410121020240024020032d0098064101460d00410b210841d8d2c50021090c010b200341e8046a41026a20032d00820222023a0000200341e8076a41086a220a20034193026a290000370300200341e8076a410d6a221720034198026a290000370000200341c0046a41026a20023a0000200320032f01800222023b01e8042003200329008b0222073703e807200320023b01c0042003280083022109200328008702210820034188056a410d6a201729000037000020034188056a41086a200a2903003703002003200737038805410021020b200341106a41026a220a200341c0046a41026a2d00003a000020034188086a41086a221720034188056a41086a29030037030020034188086a41106a20034188056a41106a290300370300200320032f01c0043b011020032003290388053703880820020d48200341e3006a2017290300370000200341d0006a41186a20034195086a290000370000200320032f01103b01502003200836005720032009360053200320032903880837005b2003200a2d00003a00520240200341d0006a200341b8036a4120109c05450d0041dbd4c5002109410b21084101210a0c4a0b20034198066a41186a200341d0056a41186a29030037030020034198066a41106a200341d0056a41106a29030037030020034198066a41086a200341d0056a41086a290300370300200320032903d00537039806410f10282202450d2441002109200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f0013702542003200236025020034198066a200341d0006a108f012003280258210220032802502108200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220082002200341a0026a100020034180026a41186a200a29030037030020034180026a41106a201729030037030020034180026a41086a2006290300370300200320032903a0023703800202402003280254450d002003280250102a0b20034180026a412010094101210a0c490b200141216a2d00002116200341106a41186a200141196a290000370300200341106a41106a200141116a290000370300200341106a41086a200141096a290000370300200320012900013703102002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d0001211a200320073703980641002102201a41ff01714101460d010b410121024100210641042118410021170b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201841ff017172201741187472220a360083022002450d01410f210841ea9fc6002109200a0e0700030405064647000b2003280087022109200328008b0221084101210a0c470b200341c0046a41186a20034180026a41186a2903002207370300200341c0046a41106a20034180026a41106a2903002204370300200341c0046a41086a20034180026a41086a29030022053703002003200329038002221d3703c004200341e8046a41186a2007370300200341e8046a41106a2004370300200341e8046a41086a20053703002003201d3703e80420034188056a41186a200341106a41186a29030037030020034188056a41106a200341106a41106a29030037030020034188056a41086a200341106a41086a2903003703002003200329031037038805200320163a00a805411510282202450d22200241002900d088453700002002410d6a41002900dd8845370000200241086a41002900d8884537000020034295808080d00237029c062003200236029806200341e8046a20034198066a108f0120032802a00621022003280298062108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a0023703300240200328029c06450d00200328029806102a0b2003410036029806200341306a412020034198066a1006210202400240200328029806220a417f460d002002450d002003200a3602bc03200320023602b80320034198066a200341b8036a10b10120032d00b90622084102460d25200341d0006a41186a2217200341d2066a290100370300200341d0006a41106a2206200341ca066a290100370300200341d0006a41086a2218200341c2066a290100370300200341a0026a41086a2219200341e3066a290000370300200341a0026a41106a220b200341eb066a290000370300200341a0026a41186a220c200341f3066a290000370300200320032901ba063703502003200341db066a2900003703a002200341da066a2d000021090240200a450d002002102a0b200341b8036a41186a2017290300370300200341b8036a41106a2006290300370300200341b8036a41086a201829030037030020034188086a41086a201929030037030020034188086a41106a200b29030037030020034188086a41186a200c290300370300200320032903503703b803200320032903a002370388080c010b200341a0026a41186a22024200370300200341a0026a41106a22084200370300200341a0026a41086a22094200370300200342003703a00241e588c500411d200341a0026a100020034198066a41186a220a200229030037030020034198066a41106a2217200829030037030020034198066a41086a22062009290300370300200320032903a00237039806200341d0056a20034198066a412010fd010240024020032d00d0050d00200242003703002008420037030020094200370300200342003703a00241e588c500411d200341a0026a1000200a20022903003703002017200829030037030020062009290300370300200320032903a0023703980620034120360254200320034198066a360250200341e8046a200341d0006a10ff01410021090c010b200341c8076a41186a200341e9056a290000370300200341c8076a41106a200341e1056a290000370300200341c8076a41086a200341d9056a290000370300200320032900d1053703c807200341e8076a200341c8076a10b0012003410036029806200341e8076a412020034198066a100621022003280298062208417f460d272002450d27200320083602542003200236025020034198066a200341d0006a10b10120032d00b906220a4102460d2620034188086a41186a220920034198066a41186a29030037030020034188086a41106a221720034198066a41106a29030037030020034188086a41086a220620034198066a41086a29030037030020032003290398063703880820032d00b8062118200341a0026a200341ba066a221941c100109a051a02402008450d002002102a0b200341d0006a41186a22022009290300370300200341d0006a41106a22082017290300370300200341d0006a41086a220920062903003703002003200329038808370350200341b8036a200341a0026a41c100109a051a200341a0026a41186a22172002290300370300200341a0026a41106a22062008290300370300200341a0026a41086a220b2009290300370300200320032903503703a0022003200a3a00980620034198066a410172200341b8036a41c100109a051a20022017290300370300200820062903003703002009200b290300370300200341f8006a2019410020032d00b9064101461b360200200320032903a002370350200320183a00702003200341e8046a360274200341003602c003200342013703b803200341d0006a200341b8036a108f01024020032d0070220241064b0d000240024002400240024002400240024020020e0700010203040506000b410021080c060b410121080c050b410221080c040b410321080c030b410421080c020b410521080c010b410621080b200320083a00a8080240024020032802bc0320032802c0032202460d0020032802b80321090c010b200241016a22082002490d3c200241017422092008200920084b1b22084100480d3c0240024020020d002008102821090c010b20032802b80320022008102c21090b2009450d2a200320083602bc03200320093602b80320032d00a808210820032802c00321020b2003200241016a3602c003200920026a20083a00000b200341f4006a200341b8036a10aa0120032802bc032102200341e8076a412020032802b803220820032802c003100702402002450d002008102a0b200341a0026a41186a22024200370300200341a0026a41106a22084200370300200341a0026a41086a22094200370300200342003703a00241e588c500411d200341a0026a100020034198066a41186a200229030037030020034198066a41106a200829030037030020034198066a41086a2009290300370300200320032903a0023703980620034120360254200320034198066a360250200341e8046a200341d0006a10ff0120034188086a41086a200341c8076a41086a29030037030020034188086a41106a200341c8076a41106a29030037030020034188086a41186a200341c8076a41186a290300370300200320032903c80737038808410121090b410021080b200341a5066a200341b8036a41086a290300370000200341ad066a200341b8036a41106a290300370000200341b5066a200341b8036a41186a290300370000200341bd066a20093a0000200341be066a200329038808370100200341c6066a20034188086a41086a290300370100200341ce066a20034188086a41106a290300370100200341d6066a20034188086a41186a290300370100200320083a009c06200320032903b80337009d06200320034188056a36029806200341003602582003420137035020034188056a200341d0006a108f01024020032d00a805220241064b0d000240024002400240024002400240024020020e0700010203040506000b410021080c060b410121080c050b410221080c040b410321080c030b410421080c020b410521080c010b410621080b200320083a00a80802400240200328025420032802582202460d00200328025021090c010b200241016a22082002490d3a200241017422092008200920084b1b22084100480d3a0240024020020d002008102821090c010b200328025020022008102c21090b2009450d29200320083602542003200936025020032d00a8082108200328025821020b2003200241016a360258200920026a20083a00000b20034198066a410472200341d0006a10a90120032802542102200341306a4120200328025022082003280258100702402002450d002008102a0b200342e4cab5fbb6ccdcb0e3003703e004200341e0046a200341c0046a417f10a80220034198066a41086a41083a0000200341a1066a20032903c004370000200341a9066a200341c0046a41086a290300370000200341b1066a200341c0046a41106a290300370000200341b9066a200341c0046a41186a290300370000200341c1066a2003290310370000200341c9066a200341106a41086a290300370000200341d1066a200341106a41106a290300370000200341d9066a200341106a41186a290300370000200341053a009806410021094101210a4101410020034198066a10cc010c420b2002411a6a2901002107200241196a2d00002117200241186a2d00002106200241166a2f01002118200241156a2d00002110200241146a2d00002111200241126a2f01002112200241116a2d00002113200241106a2d000021192002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320173a009b06200320063a009a06200320183b0198060c010b200241086a2d00002108200241066a2f01002109200241056a2d0000210a20022d00012116200320073703980641002102201641ff01714101460d010b41012102410021094104210a410021080b200941ffff0371410874200a41ff017172200841187472210a2002450d04410f210841ea9fc60021090240200a0e0700010203044445000b200e410874200f72200d411874722109200b410874200c7220194118747221084101210a0c450b410e210841dc9fc60021094101210a0c440b410c210841d09fc60021094101210a0c430b4109210841c79fc60021094101210a0c420b4113210841b49fc60021094101210a0c410b2003200737038005200320173a00ff04200320063a00fe04200320183b01fc04200320103a00fb04200320113a00fa04200320123b01f804200320133a00f704200320193a00f6042003200b3b01f4042003200c3a00f3042003200d3a00f2042003200e3b01f0042003200f3a00ef042003200a3600eb04200320143a00ea04200320153b01e804411510282202450d22200241002900d08845370000410d21082002410d6a41002900dd8845370000200241086a41002900d8884537000020034295808080d00237025420032002360250200341e8046a200341d0006a108f012003280258210220032802502109200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220092002200341a0026a100020034198066a41186a200a29030037030020034198066a41106a201729030037030020034198066a41086a2006290300370300200320032903a0023703980602402003280254450d002003280250102a0b024020034198066a41204101410041001003417f470d0041e6d4c50021094101210a0c410b411510282202450d23200241002900d088453700002002410d6a41002900dd8845370000200241086a41002900d8884537000020034295808080d00237029c062003200236029806200341e8046a20034198066a108f0120032802a00621022003280298062108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341c0046a41186a2009290300370300200341c0046a41106a200a290300370300200341c0046a41086a2017290300370300200320032903a0023703c0040240200328029c06450d00200328029806102a0b2003410036029806200341c0046a412020034198066a100621022003280298062209417f460d252002450d25200320093602542003200236025020034198066a200341d0006a10b10120032d00b90622084102460d2420034188086a41186a20034198066a41186a29030037030020034188086a41106a20034198066a41106a29030037030020034188086a41086a20034198066a41086a29030037030020032003290398063703880820032d00b8062117200341a0026a200341ba066a41c100109a051a02402009450d002002102a0b200341c0046a412010090c260b41c4d1c3004133200341a8086a419cd9c3001038000b412041011037000b200241011037000b1036000b201841011037000b2002200a1044000b200a2017103c000b200920171044000b200341d0056a41146a4108360200200341dc056a412536020020034188056a41146a41033602002003420337028c05200341c8afc60036028805200341253602d4052003200341306a3602c004200320034180026a3602e804200342043703a8062003420137029c062003419cb0c600360298062003200341d0056a36029805200320034198066a3602e0052003200341e8046a3602d8052003200341c0046a3602d00520034188056a41d8b0c600103e000b200241011037000b200241011037000b410f41011037000b411741011037000b411341011037000b200841011037000b200941011037000b200941011037000b411341011037000b411741011037000b412e41011037000b41c4d1c3004133200341a8086a419cd9c3001038000b411741011037000b412e41011037000b410f41011037000b410f41011037000b410f41011037000b410f41011037000b410f41011037000b411541011037000b41c4d1c3004133200341a8086a419cd9c3001038000b41c4d1c3004133200341a8086a419cd9c3001038000b41b7b3c0004192011050000b200841011037000b200841011037000b411541011037000b411541011037000b41c4d1c3004133200341a8086a419cd9c3001038000b410221080b200341c8076a41186a220220034188086a41186a290300370300200341c8076a41106a220920034188086a41106a290300370300200341c8076a41086a220a20034188086a41086a29030037030020032003290388083703c80720034188056a200341a0026a41c100109a051a200341306a41086a2206200a290300370300200341306a41106a220a2009290300370300200341306a41186a22092002290300370300200320032903c807370330200341d0056a20034188056a41c100109a051a41072102024020084102460d0020034180026a41186a200929030037030020034180026a41106a200a29030037030020034180026a41086a20062903003703002003200329033037038002200320083a0050200341d0006a410172200341d0056a41c100109a05210a200341f2006a21094100210202400240024002400240024002400240024020032d00714101470d0020034198066a200910b001200341a0026a41186a20034198066a41186a22082900002207370300200341a0026a41106a20034198066a41106a22062900002204370300200341a0026a41086a20034198066a41086a221829000022053703002003200329009806221d3703a0022008200737030020062004370300201820053703002003201d37039806412010282202450d012002200329039806370000200241186a2008290300370000200241106a2006290300370000200241086a201829030037000020032d005021080b0240200841ff01714101460d0020032d00714101460d03200341a0026a41186a22084200370300200341a0026a41106a22094200370300200341a0026a41086a220a4200370300200342003703a00241e588c500411d200341a0026a100020034198066a41186a200829030037030020034198066a41106a200929030037030020034198066a41086a200a290300370300200320032903a0023703980620034198066a412010090c070b20034198066a200a10b001200341a0026a41186a20034198066a41186a2903002207370300200341a0026a41106a20034198066a41106a2903002204370300200341a0026a41086a20034198066a41086a29030022053703002003200329039806221d3703a002200341e8076a41186a22092007370300200341e8076a41106a220a2004370300200341e8076a41086a220620053703002003201d3703e807412010282208450d01200820032903e807370000200841186a2009290300370000200841106a200a290300370000200841086a200629030037000020034100360298062008412020034198066a1006210a2003280298062206417f460d04200a450d042003200636028c082003200a3602880820034198066a20034188086a10b10120032d00b90622194102460d03200341f1006a2109200341a0026a41206a220b20034198066a41206a22182d00003a0000200341a0026a41186a220c20034198066a41186a220d290300370300200341a0026a41106a220e20034198066a41106a220f290300370300200341a0026a41086a221020034198066a41086a221129030037030020032003290398063703a002200341b8036a200341ba066a221241c100109a051a02402006450d00200a102a0b201220032900b8033701002018200b2d00003a0000200d200c290300370300200f200e29030037030020112010290300370300200341c2066a200341b8036a41086a290000370100200341ca066a200341b8036a41106a290000370100200341d2066a200341b8036a41186a290000370100200320032903a00237039806200320193a00b906200341fa066a200941206a2d00003a0000200341f2066a200941186a290000370100200341ea066a200941106a290000370100200341e2066a200941086a290000370100200341da066a2009290000370100200341003602a802200342013703a00220034198066a200341a0026a108f01024020182d0000220941064b0d000240024002400240024002400240024020090e0700010203040506000b4100210a0c060b4101210a0c050b4102210a0c040b4103210a0c030b4104210a0c020b4105210a0c010b4106210a0b2003200a3a00a8080240024020032802a40220032802a8022209460d0020032802a00221060c010b200941016a220a2009490d1620094101742206200a2006200a4b1b220a4100480d160240024020090d00200a102821060c010b20032802a0022009200a102c21060b2006450d072003200a3602a402200320063602a00220032d00a808210a20032802a80221090b2003200941016a3602a802200620096a200a3a00000b200341b9066a200341a0026a10a90120032802a40221092008412020032802a002220a20032802a802100702402009450d00200a102a0b2008102a4101210a0c070b412041011037000b412041011037000b200341a0026a41186a22084200370300200341a0026a41106a220a4200370300200341a0026a41086a22064200370300200342003703a00241e588c500411d200341a0026a100020034198066a41186a200829030037030020034198066a41106a200a29030037030020034198066a41086a2006290300370300200320032903a00237039806200341203602a402200320034198066a3602a0022009200341a0026a10ff010c030b41c4d1c3004133200341a8086a419cd9c3001038000b41e2bbc00041d8001050000b200a41011037000b410021084100210a0b024002400240024002400240024020020d00410021090c010b20034100360298062002412020034198066a100621092003280298062206417f460d022009450d02200320063602bc03200320093602b80320034198066a200341b8036a10b10120032d00b9064102460d0120034188086a41186a221820034198066a41186a221929030037030020034188086a41106a220b20034198066a41106a220c29030037030020034188086a41086a220d20034198066a41086a220e29030037030020032003290398063703880820032d00b806210f200341a0026a200341ba066a221041c100109a051a02402006450d002009102a0b20192018290300370300200c200b290300370300200e200d2903003703002003200329038808370398062003200f3a00b8062010200341a0026a41c100109a051a200341c1066a200341d0006a41086a290300370000200341c9066a200341d0006a41106a290300370000200341d1066a200341d0006a41186a29030037000020034198066a41c1006a200341d0006a41206a2d00003a0000200320032903503700b906200341003602a802200342013703a00220034198066a200341a0026a108f01024020032d00b806220941064b0d000240024002400240024002400240024020090e0700010203040506000b410021060c060b410121060c050b410221060c040b410321060c030b410421060c020b410521060c010b410621060b200320063a00a8080240024020032802a40220032802a8022209460d0020032802a00221180c010b200941016a22062009490d14200941017422182006201820064b1b22064100480d140240024020090d002006102821180c010b20032802a00220092006102c21180b2018450d05200320063602a402200320183602a00220032d00a808210620032802a80221090b2003200941016a3602a802201820096a20063a00000b200341b9066a200341a0026a10a90120032802a40221092002412020032802a002220620032802a802100702402009450d002006102a0b2002102a410121090b200a20084572450d030c040b41c4d1c3004133200341a8086a419cd9c3001038000b41e2bbc00041d8001050000b200641011037000b2008102a0b02402002452009720d002002102a0b201721020b1098012108200342e4cab5fbb6ccdcb0e30037035041002109200341d0006a200341e8046a427f427f200841002002200241ff01714107461b41187441187541027441f48fc6006a2802004180de346c6a410210a90220034198066a41086a41093a000020034198066a41096a20032903e804370000200341a9066a200341e8046a41086a290300370000200341b1066a200341e8046a41106a290300370000200341b9066a200341e8046a41186a290300370000200341053a0098064101410020034198066a10cc014101210a0c190b41a39fc6002109411121080c180b20032802a006211820032903a0062207a7211941002102024002402007422088a7220641014b0d0020060e020201020b2006210803402008410176220920026a220a20022017200a4105746a200341d0056a4120109c054101481b2102200820096b220841014b0d000b0b201720024105746a200341d0056a4120109c052208450d0a0c010b20034198066a41186a200341d0056a41186a29030037030020034198066a41106a200341d0056a41106a29030037030020034198066a41086a200341d0056a41086a290300370300200320032903d005370398064100210620034198066a2108410021090c010b20034198066a41186a200341d0056a41186a29030037030020034198066a41106a200341d0056a41106a29030037030020034198066a41086a200341d0056a41086a290300370300200320032903d005370398062008411f7620026a220920064b0d0120034198066a21080b20062019460d012018210a0c020b41f8b0c0001032000b024020182006460d002018210a0c010b201841016a22022018490d042018410174220a2002200a20024b1b220a41ffffff3f71200a470d04200a41057422024100480d040240024020180d002002102821170c010b201720184105742002102c21170b2017450d010b201720094105746a220241206a2002200620096b410574109b051a200241186a200841186a290000370000200241106a200841106a290000370000200241086a200841086a290000370000200220082900003700001098012108411310282202450d01200241002900a9d3453700002002410f6a41002800b8d345360000200241086a41002900b1d34537000020034293808080b00237029c062003200236029806200320034198066a36025020034188056a200341d0006a10c801200328029806210220032802a0062109200341a0026a41186a22184200370300200341a0026a41106a22194200370300200341a0026a41086a220b4200370300200342003703a00220022009200341a0026a1000200341306a41186a2018290300370300200341306a41106a2019290300370300200341306a41086a200b290300370300200320032903a0023703300240200328029c06450d00200328029806102a0b410410282202450d0220034284808080c00037029c0620032002360298062002200841809c316a2209360000200641016a220220034198066a10b40102402002450d00200641057441206a2108201721020340200220034198066a108f01200241206a2102200841606a22080d000b0b200328029c062102200341306a4120200328029806220820032802a006100702402002450d002008102a0b0240200a450d002017102a0b20034198066a41086a410a3a0000200341a1066a20032903d005370000200341c1066a200329038805370000200341a9066a200341d0056a41086a290300370000200341b1066a200341d0056a41106a290300370000200341b9066a200341d0056a41186a290300370000200341c9066a20034188056a41086a290300370000200341d1066a20034188056a41106a290300370000200341d9066a20034188056a41186a290300370000200341053a009806200341e4066a2009360200410021094101410020034198066a10cc0120034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341e8076a411010094101210a0c110b200241011037000b411341011037000b410441011037000b1031000b41a6d4c5002109412621082019450d0b2017102a4101210a0c0c0b200341003602a0062003420137039806200341d0006a20034198066a10eb01200328029c06210920032802a00621172003280298062102200341a0026a41186a22194200370300200341a0026a41106a220b4200370300200341a0026a41086a220c4200370300200342003703a00220022017200341a0026a100020034198066a41186a201929030037030020034198066a41106a200b29030037030020034198066a41086a200c290300370300200320032903a0023703980602402009450d002002102a0b0240200341d0056a20034198066a4120109c05450d0041bcd3c5002109410c21080c010b20034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341e8076a41101009109801210220034198066a200341d0006a418801109a051a200341a0026a200220064180a30520064180a3054b1b6a20034198066a2008201810b704024020032802a0024101470d0020032802a4022209450d00200341a0026a41086a28020021080c0c0b410021090c0b0b200341d0006a106a0c0a0b410121180b41012117410021090c100b200a106a200a102a410121064100210a410121180c080b200341013a00880520034198066a41186a200341b8036a41186a29030037030020034198066a41106a200341b8036a41106a29030037030020034198066a41086a200341b8036a41086a290300370300200320032903b803370398060240411710282202450d0041002109200241002900e3d2453700002002410f6a41002900f2d245370000200241086a41002900ebd24537000020034297808080f0023702d405200320023602d0052003200341d0056a3602a00220034198066a200341a0026a10c80120032802d005210220032802d8052108200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220022008200341a0026a1000200341306a41186a200a290300370300200341306a41106a2017290300370300200341306a41086a2006290300370300200320032903a002370330024020032802d405450d0020032802d005102a0b4101210a200341306a412020034188056a41011007200b10ce03200341d0006a106a0c030b411741011037000b412221084101210a0c050b201720024105746a22022003290330370000200241186a200341306a41186a290300370000200241106a200a290300370000200241086a20182903003700004101210a20034198066a41186a200841016a360200200341ac066a2006360200200320073703a0062003200437039806200320093602b406200320173602a806201620034198066a10c404410021090b4101210641012118410121170c0b0b41afd2c5002109411a21082002450d012017102a4101210a0c020b4111210841a39fc60021090b4101210a0b41012106410121180b410121170c060b20032802d007210920032802cc07210a20032802c80721020b2002450d00200341e8076a4110200220091007200a450d012002102a0c010b41b00110282202450d01200320032802d8013602a00720034198066a200341d0006a10cf0320034198066a41a4016a200341d0006a41a4016a29020037020020034198066a419c016a200341d0006a419c016a29020037020020034198066a4194016a200341d0006a4194016a290200370200200320032902dc013702a407200220034198066a41b001109a05210220034188086a41086a22094200370300200342003703880841ac89c500411520034188086a1008200341e8076a41086a200929030037030020032003290388083703e8072003411036029c062003200341e8076a360298062002410120034198066a10ef012002106a2002102a0b200341d0006a106a200341b0066a2004370300200341a8066a2005370300200341a4066a200836020041002117200341a0066a41003a0000200341053a0098064101210a4101410020034198066a10cc012006106a2006102a4101210641012118410021090c020b41b00141081037000b2006106a2006102a410021174101210a41012106410121180b0240024020012d0000417f6a2202410f4b0d00024002400240024020020e1000040404040102030404040405040505000b2017450d04200141046a2202280200106a2002280200102a0c040b200a450d03200141046a2202280200106a2002280200102a0c030b2006450d02200141046a2202280200106a2002280200102a0c020b2018450d01200141046a2202280200106a2002280200102a0c010b200241074b0d00024002400240024020020e080004040404010203000b200141046a2202280200106a2002280200102a0c030b200141046a2202280200106a2002280200102a0c020b200141046a2202280200106a2002280200102a0c010b200141046a2202280200106a2002280200102a0b2000200836020420002009360200200341b0086a24000b8b0708047f047e057f027e017f017e017f017e230041a0016b2202240041002103200241003a0098012001280204417f6a210402400240024003402004417f460d01200241f8006a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a0098012004417f6a21042005210320054120470d000b200241d8006a41186a200241f8006a41186a290300370300200241d8006a41106a200241f8006a41106a290300370300200241d8006a41086a200241f8006a41086a29030037030020022002290378370358200241c0006a2001109f012002290340a7450d01200041003602200c020b0240200341ff0171450d00200241003a0098010b200041003602200c010b200241c0006a41106a290300210620022903482107200241286a2001109f0102402002290328a7450d00200041003602200c010b200241286a41106a290300210820022903302109200241206a2001106c02400240024002400240024020022802200d00200128020441186e220a41186c2204417f4c0d022002280224210b0240024020040d004108210c0c010b20041028220c450d040b0240200b450d00200241086a41106a210d4100210e41002105410021030340200241086a2001109f01024002402002290308a70d00200d290300210f2002290310211020022001106c2002280200450d010b200a450d03200c102a0c030b200341016a21042002280204211102402003200a470d00200e2004200e20044b1b220aad42187e2212422088a70d082012a722134100480d080240024020030d0020131028210c0c010b200c20052013102c210c0b200c450d070b200c20056a2203200f37030820032010370300200341106a2011360200200e41026a210e200541186a210520042103200b2004470d000b0b200c0d010b200041003602200c050b200241f8006a41186a200241d8006a41186a290300220f370300200241f8006a41106a200241d8006a41106a2903002210370300200241f8006a41086a200241d8006a41086a2903002212370300200220022903582214370378200041186a2008370300200020093703102000200637030820002007370300200041286a200b3602002000200a3602242000200c3602202000412c6a2014370200200041346a20123702002000413c6a2010370200200041c4006a200f3702000c040b1036000b200441081037000b201341081037000b1031000b200241a0016a24000bde0401067f230041306b2202240002400240024002400240411010282203450d00200341086a4100290097a5423700002003410029008fa54237000020024290808080800237021420022003360210410d200241106a10b40102400240024020022802142204200228021822056b410d490d002005410d6a2106200228021021030c010b2005410d6a22062005490d01200441017422032006200320064b1b22074100480d010240024020040d002007102821030c010b200228021020042007102c21030b2003450d032002200736021420022003360210200721040b20022006360218200320056a22054100290082a542370000200541056a4100290087a54237000020022003200610df0202402004450d002003102a0b20022802082203417f4c0d03200228020021050240024020030d0041012106410021040c010b20032104200310282206450d050b200620052003109a05210702402002280204450d002005102a0b200241106a200110e0020240200420036b4120490d00200341206a21050c060b200341206a22052003490d00200441017422062005200620054b1b22014100480d000240024020040d002001102821060c010b200720042001102c21060b02402006450d00200121040c060b200141011037000b1031000b411041011037000b200741011037000b1036000b200341011037000b200620036a22032002290010370000200341186a200241106a41186a290000370000200341106a200241106a41106a290000370000200341086a200241106a41086a290000370000200020053602082000200436020420002006360200200241306a24000bd00a010b7f230041c0006b2202240002400240024002400240024002400240024002400240411010282203450d00200341086a41002900b1c042370000200341002900a9c04237000020024290808080800237022420022003360220410d200241206a10b40102400240024020022802242204200228022822056b410d490d002005410d6a2106200228022021030c010b2005410d6a22062005490d01200441017422032006200320064b1b22074100480d010240024020040d002007102821030c010b200228022020042007102c21030b2003450d032002200736022420022003360220200721040b20022006360228200320056a22054100290082a542370000200541056a4100290087a54237000020022003200610df0202402004450d002003102a0b20022802082206417f4c0d03200228020021030240024020060d0041012107410021080c010b20062108200610282207450d050b200720032006109a05210902402002280204450d002003102a0b2001410c6a28020041046a2204417f4c0d03024002402004450d00200410282203450d0720024100360228200220043602240c010b200241003602282002200436022420024101360220410110282203450d07200241013602240b2002200336022020024101360228200320012d00003a00000240200228022422044101470d0041000d014102410241024102491b22044100480d01200341012004102c2203450d0820022004360224200220033602200b20024102360228200320012d00013a00010240024020044102460d00200421050c010b200441016a22052004490d012004410174220a2005200a20054b1b22054100480d010240024020040d002005102821030c010b200320042005102c21030b2003450d0920022005360224200220033602200b20024103360228200341026a20012d00023a0000024020054103470d00200541016a22042005490d012005410174220a2004200a20044b1b22044100480d010240024020050d002004102821030c010b200320052004102c21030b2003450d0a20022004360224200220033602200b20024104360228200341036a20012d00033a00002001280204210a200128020c2201200241206a10b4010240024020022802242205200228022822046b2001490d00200228022021030c010b200420016a22032004490d012005410174220b2003200b20034b1b220b4100480d010240024020050d00200b102821030c010b20022802202005200b102c21030b2003450d0b2002200b36022420022003360220200b21050b200320046a200a2001109a051a200241206a41186a220a4200370300200241206a41106a220b4200370300200241206a41086a220c4200370300200242003703202003200420016a200241206a1000200241186a200a290300370300200241106a200b290300370300200241086a200c2903003703002002200229032037030002402005450d002003102a0b0240200820066b4120490d00200641206a21010c0c0b200641206a22012006490d00200841017422032001200320014b1b22034100480d000240024020080d002003102821070c010b200920082003102c21070b02402007450d00200321080c0c0b200341011037000b1031000b411041011037000b200741011037000b1036000b200641011037000b200441011037000b410141011037000b200441011037000b200541011037000b200441011037000b200b41011037000b200720066a22032002290300370000200341186a200241186a290300370000200341106a200241106a290300370000200341086a200241086a290300370000200020013602082000200836020420002007360200200241c0006a24000be6e80106017f037e137f017e117f057e230041c0056b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0e000102030405060708090f101112000b20034184056a4101360200200342013702f404200341ccd1c5003602f004200341043602b401200341c4d1c5003602b0012003200341b0016a36028005200341f0046a41bc80c500103e000b200141306a2903002104200141286a29030021052001411d6a29000021062001411c6a2d000021072001411b6a2d00002108200141196a2f00002109200141186a2d0000210a200141176a2d0000210b200141156a2f0000210c200141146a2d0000210d200141136a2d0000210e200141116a2f0000210f200141106a2d000021102001410f6a2d000021112001410d6a2f000021122001410c6a2d00002113200141086a2802002114200141076a2d00002115200141056a2f0000211641042117200141046a2d0000211820012d000121192002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d00002127200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e07000a0b0c0d5253000b20264108742027722025411874722102202341087420247220224118747221170c520b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d11200241002900fcae44370000200241066a4100290082af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b4101212b0240200341d0006a41204101410041001003417f460d00419681c500210241142117410121220c530b0240201841ff01714101470d00200341f0046a201441067610fe0120032802f00421170240024020032802f8042014413f7122024b0d00410021020c010b201720024105746a2202290018210620022d0017210720022d0016210820022f0014210920022d0013210a20022d0012210b20022f0010210c20022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d000721132002280003211420022d0002211520022f00002116410121020b024020032802f404450d002017102a0b20020d0041dc9fc6002102410e2117410121220c530b200320063703c801200320073a00c701200320083a00c601200320093b01c4012003200a3a00c3012003200b3a00c2012003200c3b01c0012003200d3a00bf012003200e3a00be012003200f3b01bc01200320103a00bb01200320113a00ba01200320123b01b801200320133a00b701200320143600b301200320153a00b201200320163b01b001410e10282202450d122002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341b0016a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a2222420037030020034188046a41086a2223420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a2022290300370300200341d0006a41086a20232903003703002003200329038804370350024020032802f404450d0020032802f004102a0b0240200341d0006a41204101410041001003417f460d0041cc80c500210241192117410121220c530b02402005428080e983b1de165441002004501b450d0041e580c500210241312117410121220c530b200341f0046a41186a200341b0016a41186a290300370300200341f0046a41106a200341b0016a41106a290300370300200341f0046a41086a200341b0016a41086a290300370300200320032903b0013703f004410e10282202450d13200241002900fcae44370000200241066a4100290082af443700002003428e808080e0013702d404200320023602d004200341a0036a200341d0046a108f0120032802d804210220032802d004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802d404450d0020032802d004102a0b200341203602d4042003200341d0006a3602d004200341f0046a200341d0046a10ff01410d10282202450d1420024100290098af44370000200241056a410029009daf443700002003428d808080d0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b024002400240024002400240201941037122024103460d0020020e03010203010b200341d0006a41204101410010070c040b410021170c020b410121170c010b410221170b200320173a00f004410110282202450d16200220173a0000200341d0006a41202002410110072002102a0b2003200341a0036a109101200341086a290300211a200329030021064100210220034198056a41003602002003419e056a20032d00a2033a00002003419f056a20032800a303360000200341a3056a20032d00a7033a0000200341b4056a20032903b803370200200341a4056a20032903a803370200200341ac056a20032903b00337020020034188056a201a20042006200554201a200454201a2004511b22171b221a370300200320032f01a0033b019c0520034208370390052003201a3703f80420032006200520171b221a3703f0042003201a37038005200341b0016a200341f0046a10b50420034194056a280200450d4f200328029005102a0c4f0b200141106a2903002106200141086a29030021042002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e0700090a0b0c5152000b20264108742027722025411874722102202341087420247220224118747221170c510b2003201a3703e8042003201b3a00e7042003201c3a00e6042003201d3b01e4042003201e3a00e3042003201f3a00e204200320203b01e004200320213a00df04200320223a00de04200320233b01dc04200320243a00db04200320253a00da04200320263b01d804200320273a00d7042003202a3600d304200320283a00d204200320293b01d004200341f0046a200341d0046a10b1044101212a0240024020032d00f0044101460d00410b211741aa81c50021020c010b2003418a046a20032d00f3043a0000200341b0016a41086a20034184056a290200370300200341bd016a20034189056a290000370000200320032f00f1043b0188042003200341fc046a2902003703b001200341f0046a41086a28020021174100212a20032802f40421020b20034180036a41026a222b20034188046a41026a2d00003a0000200341a8046a41086a2222200341b0016a41086a290300370300200341a8046a41106a200341b0016a41106a290300370300200320032f0188043b018003200320032903b0013703a804202a0d50200341b3036a2022290300370000200341a0036a41186a200341b5046a290000370000200320032f0180033b01a003200320173600a703200320023600a303200320032903a8043700ab032003202b2d00003a00a203410e10282202450d152002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006211720032802f0042202417f460d2e200320023602ac04200320173602a804200341f0046a200341a8046a108a02200328029005222a450d16200341f0046a41186a290300212c200341f0046a410c6a350200211a200341bc056a280200212b200341f0046a41c4006a2902002105200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412f6a28000021262003419c056a2f01002127200329038005212d20032902f404212e20032d00b305211b20032d00b205211c20032d00af05211d20032d00ae05211e20032d00ab05211f20032d00aa05212020032d00a705212120032d00a605212820032d00a305212920032d009e052114200329029405212f20032802f004210702402002450d002017102a0b200341b0016a41186a202c370300200341b0016a410c6a201a3e0200200341b0016a41c4006a2005370200200341f3016a201b3a0000200341f2016a201c3a0000200341b0016a41c0006a20223b0100200341ef016a201d3a0000200341ee016a201e3a0000200341b0016a413c6a20233b0100200341eb016a201f3a0000200341ea016a20203a0000200341b0016a41386a20243b0100200341e7016a20213a0000200341e6016a20283a0000200341b0016a41346a20253b0100200341e3016a20293a0000200341b0016a412f6a2026360000200341de016a20143a0000200341d4016a202f3702002003202d3703c0012003202e3702b4012003202b3602fc01200320273b01dc012003202a3602d001200320073602b001200341106a200341d0046a10910102402003290310221a20032903b001222e7d222f201a56200341106a41086a2903002205200341b0016a41086a29030022307d201a202e54ad7d221a200556201a2005511b0d0020032004202f202f200456201a200656201a2006511b22021b2204202d7c22053703c001200341c8016a2006201a20021b221a202c7c2005200454ad7c37030020032004202e7c22063703b0012003201a20307c2006200454ad7c3703b801200341a0036a200341b0016a10b5040b20032802d401450d4d20032802d001102a0c4d0b200141106a2903002106200141086a29030021042002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e070008090a0b5051000b20264108742027722025411874722102202341087420247220224118747221170c500b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d162002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006210220032802f0042217417f460d2d2002450d2d200320173602d404200320023602d004200341f0046a200341d0046a108a02200328029005222a450d17200341f0046a41186a290300211a200341f0046a410c6a350200212d200341bc056a280200212b200341f0046a41c4006a290200212e200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412f6a28000021262003419c056a2f01002127200329038005212c20032902f404212f20032d00b305211b20032d00b205211c20032d00af05211d20032d00ae05211e20032d00ab05211f20032d00aa05212020032d00a705212120032d00a605212820032d00a305212920032d009e052114200329029405210520032802f004210702402017450d002002102a0b200341b0016a41186a201a370300200341b0016a410c6a202d3e0200200341b0016a41c4006a202e370200200341f3016a201b3a0000200341f2016a201c3a0000200341b0016a41c0006a20223b0100200341ef016a201d3a0000200341ee016a201e3a0000200341b0016a413c6a20233b0100200341eb016a201f3a0000200341ea016a20203a0000200341b0016a41386a20243b0100200341e7016a20213a0000200341e6016a20283a0000200341b0016a41346a20253b0100200341e3016a20293a0000200341b0016a412f6a2026360000200341de016a20143a0000200341d4016a20053702002003202c3703c0012003202f3702b4012003202b3602fc01200320273b01dc012003202a3602d001200320073602b0012005a7212b02400240024002402005422088a7411f4b0d00202c2004202c200454201a200654201a2006511b22021b2204201a200620021b220684500d03200341c8016a4200201a20067d202c200454ad7d2205202c20047d222d428080e983b1de165441002005501b22171b37030020034200202d20171b3703c001200341f0046a41086a22024200370300200342003703f00441bb9cc6004112200341f0046a1008200341d0046a41086a2002290300370300200320032903f0043703d004200341003602f004200341d0046a4110200341f0046a1006210220032802f004222a417f470d0141a005212a0c020b41c581c500210241232117202b450d52202a102a0c520b024020020d0041a005212a0c010b202a4104490d1a2002280000212a2002102a202a41a0056a212a0b024020032802d801220220032802d401470d00200241016a222b2002490d4720024101742222202b2022202b4b1b2222ad42187e2205422088a70d472005a7222b4100480d470240024020020d00202b102821020c010b20032802d001200241186c202b102c21020b2002450d1b200320223602d401200320023602d00120032802d80121020b20032802d001200241186c6a2202201a200620171b3703082002202c200420171b3703002002202a360210200320032802d80141016a3602d801200341a0036a200341b0016a10b50420032802d401212b0b202b450d4c20032802d001102a410021020c4d0b2002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e07000708090a4f50000b20264108742027722025411874722102202341087420247220224118747221170c4f0b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d192002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006210220032802f0042217417f460d2c2002450d2c200320173602b401200320023602b001200341f0046a200341b0016a108a022003280290052224450d1a20034188056a290300212c200341fc046a350200211a200341b4056a290200212e200341b0056a2f01002126200341ac056a2f01002127200341a8056a2f0100211b200341a4056a2f0100211c2003419c056a2f0100211d200329038005212d20032902f404210620032d00b305211e20032d00b205211f20032d00af05212020032d00ae05212120032d00ab05212820032d00aa05212920032d00a705211420032d00a605210720032d00a3052108200328009f05210920032d009e05210a200329029405210420032802f004212a02402017450d002002102a0b200341f0046a41086a22024200370300200342003703f00441bb9cc6004112200341f0046a1008200341d0046a41086a2002290300370300200320032903f0043703d0044100212b200341003602f004200341d0046a4110200341f0046a10062102024020032802f0042217417f460d002002450d0020174104490d1d2002280000212b2002102a0b201a422086200642208884211a2006422086202aad8421062004a7210b0240024002402004422088a7222541186c2202450d00202420026a2122200241686a2117202421020340200241086a290300210520022903002104202b200241106a280200222a490d024200201a20057d2006200454ad7d2205200620047d22042006562005201a562005201a511b222a1b211a42002004202a1b2106201741686a2117200241186a22022022470d000b0b410821234100212a0240200b0d00410021250c020b2024102a410021250c010b411810282223450d1e202320043703002023202a360210202320053703080240024020170d004101212a410121250c010b200241186a210c202541186c20246a41686a210e4101212a410121250340200c210202400340200241086a290300210520022903002104202b200241106a2802002217490d014200201a20057d2006200454ad7d2205200620047d22042006562005201a562005201a511b22171b211a4200200420171b2106200241186a22022022470d000c030b0b02402025202a470d00202a41016a2225202a490d48202a410174220c2025200c20254b1b2225ad42187e222f422088a70d48202fa7220c4100480d4802400240202a0d00200c102821230c010b2023202a41186c200c102c21230b2023450d220b200241186a210c2023202a41186c6a220d2005370308200d2004370300200d2017360210202a41016a212a200e2002470d000b0b200b450d002024102a0b200341b4056a202e370200200341b3056a201e3a0000200341b2056a201f3a0000200341b0056a20263b0100200341af056a20203a0000200341ae056a20213a0000200341ac056a20273b0100200341ab056a20283a0000200341aa056a20293a0000200341a8056a201b3b0100200341a7056a20143a0000200341a6056a20073a0000200341a4056a201c3b0100200341a3056a20083a00002003419f056a20093600002003419e056a200a3a000020034198056a202a36020020034194056a20253602002003202d3703800520034188056a202c370300200320063703f0042003201d3b019c0520032023360290052003201a3703f8040240202d202c844200520d00202a450d1c0b200341a0036a200341f0046a10b5040c4a0b200141106a2903002106200141086a29030021042002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e0700060708094e4f000b20264108742027722025411874722102202341087420247220224118747221170c4e0b2003201a370398012003201b3a0097012003201c3a0096012003201d3b0194012003201e3a0093012003201f3a009201200320203b019001200320213a008f01200320223a008e01200320233b018c01200320243a008b01200320253a008a01200320263b018801200320273a0087012003202a36008301200320283a008201200320293b018001410e10282202450d1e2002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f00420034180016a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006210220032802f0042217417f460d2b2002450d2b200320173602a403200320023602a003200341f0046a200341a0036a108a02200328029005222a450d1f200341f0046a41186a290300211a200341f0046a410c6a3502002105200341bc056a280200212b200341f0046a41c4006a290200212c200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412c6a2f01002126200329038005212d20032902f404212e20032d00b305212720032d00b205211b20032d00af05211c20032d00ae05211d20032d00ab05211e20032d00aa05211f20032d00a705212020032d00a605212120032d00a3052128200328009f05212920032d009e052114200329029405212f20032802f004210702402017450d002002102a0b200341b0016a41186a201a370300200341b0016a410c6a20053e0200200341b0016a41c4006a202c370200200341f3016a20273a0000200341f2016a201b3a0000200341b0016a41c0006a20223b0100200341ef016a201c3a0000200341ee016a201d3a0000200341b0016a413c6a20233b0100200341eb016a201e3a0000200341ea016a201f3a0000200341b0016a41386a20243b0100200341e7016a20203a0000200341e6016a20213a0000200341b0016a41346a20253b0100200341e3016a20283a0000200341df016a2029360000200341de016a20143a0000200341d4016a202f3702002003202d3703c0012003202e3702b4012003202b3602fc01200320263b01dc012003202a3602d001200320073602b001200341b0016a412c6a222310a7042003200637037820032004370370411210282202450d20200241002900c1ae44370000200241106a41002f00d1ae443b0000200241086a41002900c9ae4437000020034292808080a0023702f404200320023602f0042023200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a100621250240024020032802f0042226417f460d002025450d00200320263602ec03200320253602e803200341386a200341e8036a109f0120032802380d4a20032802ec032202450d4a20032002417f6a222a3602ec03200320032802e803222241016a222b3602e80320222d0000220241014b0d4a410021240240024020020e020100010b41002102200341003a00900503400240202a2002470d00200341003602ec03200241ff0171450d4d200341003a0090050c4d0b200341f0046a20026a202220026a221741016a2d00003a00002003201741026a3602e8032003200241016a22173a0090052017210220174120470d000b200341a0036a41086a200341f0046a41086a290300370300200341a0036a41106a200341f0046a41106a290300370300200341a0036a41186a200341f0046a41186a290300370300200320032903f0043703a0032003202a20176b222a3602ec0341012124202220176a41016a212b0b20034188046a41186a200341a0036a41186a29030037030020034188046a41106a200341a0036a41106a29030037030020034188046a41086a200341a0036a41086a290300370300200320032903a00337038804202a450d4a2003202a417f6a222a3602ec032003202b41016a3602e803202b2d0000221741014b0d4a410021020240024020170e020100010b41002102200341003a00900503400240202a2002470d00200341003602ec03200241ff0171450d4d200341003a0090050c4d0b200341f0046a20026a202b20026a221741016a2d00003a00002003201741026a3602e8032003200241016a22173a0090052017210220174120470d000b200341a0036a41086a200341f0046a41086a290300370300200341a0036a41106a200341f0046a41106a290300370300200341a0036a41186a200341f0046a41186a290300370300200320032903f0043703a0032003202a20176b3602ec03410121020b200341c0026a41186a2222200341a0036a41186a2217290300370300200341c0026a41106a2223200341a0036a41106a222a290300370300200341c0026a41086a2227200341a0036a41086a222b290300370300200341e0026a41086a221b20034188046a41086a290300370300200341e0026a41106a221c20034188046a41106a290300370300200341e0026a41186a221d20034188046a41186a290300370300200320032903a0033703c00220032003290388043703e002200341a0026a41186a221e201d290300370300200341a0026a41106a221d201c290300370300200341a0026a41086a221c201b290300370300200320032903e0023703a00220034180026a41186a221b202229030037030020034180026a41106a2222202329030037030020034180026a41086a22232027290300370300200320032903c00237038002200341f0046a41186a2227201e290300370300200341f0046a41106a221e201d290300370300200341f0046a41086a221d201c290300370300200320032903a0023703f0042017201b290300370300202a2022290300370300202b202329030037030020032003290380023703a00320244102460d4a200341d0046a41186a2027290300370300200341d0046a41106a201e290300370300200341d0046a41086a201d290300370300200341a8046a41086a202b290300370300200341a8046a41106a202a290300370300200341a8046a41186a2017290300370300200320032903f0043703d004200320032903a0033703a80402402026450d002025102a0b200341a0036a41186a200341d0046a41186a290300370300200341a0036a41106a200341d0046a41106a290300370300200341a0036a41086a200341d0046a41086a29030037030020034188046a41086a200341a8046a41086a29030037030020034188046a41106a200341a8046a41106a29030037030020034188046a41186a200341a8046a41186a290300370300200320032903d0043703a003200320032903a804370388040c010b200341e8036a41186a22024200370300200341e8036a41106a22174200370300200341e8036a41086a222a4200370300200342003703e80341d3aec400411a200341e8036a1000200341f0046a41186a222b2002290300370300200341f0046a41106a22222017290300370300200341f0046a41086a2224202a290300370300200320032903e8033703f004200341a0036a200341f0046a412010fd01024020032d00a0030d002002420037030020174200370300202a4200370300200342003703e80341d3aec400411a200341e8036a1000202b2002290300370300202220172903003703002024202a290300370300200320032903e8033703f004200341203602d4042003200341f0046a3602d0042023200341d0046a10ff0141002102410021240c010b200341c8036a41186a200341b9036a290000370300200341c8036a41106a200341b1036a290000370300200341c8036a41086a200341a9036a290000370300200320032900a1033703c80320034180036a200341c8036a10ac01200341003602f00420034180036a4120200341f0046a1006212420032802f0042226417f460d222024450d22200320263602a401200320243602a001200341206a200341a0016a109f012003290320a70d4820032802a4012202450d48200341306a290300211a2003290328210620032002417f6a222a3602a401200320032802a001222241016a222b3602a00120222d0000220241014b0d48410021250240024020020e020100010b41002102200341003a00900503400240202a2002470d00200341003602a401200241ff0171450d4b200341003a0090050c4b0b200341f0046a20026a202220026a221741016a2d00003a00002003201741026a3602a0012003200241016a22173a0090052017210220174120470d000b20034188046a41086a200341f0046a41086a2903002204370300200341d0046a41186a200341f0046a41186a290300370300200341d0046a41106a200341f0046a41106a290300370300200341d0046a41086a20043703002003202a20176b222a3602a401200320032903f004220437038804200320043703d00441012125202220176a41016a212b0b200341e8036a41186a200341d0046a41186a290300370300200341e8036a41106a200341d0046a41106a290300370300200341e8036a41086a200341d0046a41086a290300370300200320032903d0043703e80341002122200341003a00f004202a450d482003202a417f6a222a3602a4012003202b41016a3602a001202b2d0000220241014b0d480240024020020e020100010b41002102200341003a00900503400240202a2002470d00200341003602a401200241ff0171450d4b200341003a0090050c4b0b200341f0046a20026a202b20026a221741016a2d00003a00002003201741026a3602a0012003200241016a22173a0090052017210220174120470d000b200341a8046a41086a200341f0046a41086a2903002204370300200341d0046a41186a200341f0046a41186a290300370300200341d0046a41106a200341f0046a41106a290300370300200341d0046a41086a20043703002003202a20176b3602a401200320032903f00422043703a804200320043703d004410121220b200341c0026a41186a222b200341d0046a41186a2202290300370300200341c0026a41106a2227200341d0046a41106a2217290300370300200341c0026a41086a221b200341d0046a41086a222a290300370300200341e0026a41086a221c200341e8036a41086a290300370300200341e0026a41106a221d200341e8036a41106a290300370300200341e0026a41186a221e200341e8036a41186a290300370300200320032903d0043703c002200320032903e8033703e002200341a0026a41186a221f201e290300370300200341a0026a41106a221e201d290300370300200341a0026a41086a221d201c290300370300200320032903e0023703a00220034180026a41186a221c202b29030037030020034180026a41106a222b202729030037030020034180026a41086a2227201b290300370300200320032903c00237038002200341f0046a41186a221b201f290300370300200341f0046a41106a221f201e290300370300200341f0046a41086a221e201d290300370300200320032903a0023703f0042002201c2903003703002017202b290300370300202a202729030037030020032003290380023703d00420254102460d48200341a8046a41186a201b290300370300200341a8046a41106a201f290300370300200341a8046a41086a201e29030037030020034188046a41086a202a29030037030020034188046a41106a201729030037030020034188046a41186a2002290300370300200320032903f0043703a804200320032903d0043703880402402026450d002024102a0b200341d0046a41186a2224200341a8046a41186a290300370300200341d0046a41106a222b200341a8046a41106a290300370300200341d0046a41086a2226200341a8046a41086a290300370300200341e8036a41086a220220034188046a41086a2227290300370300200341e8036a41106a221720034188046a41106a221b290300370300200341e8036a41186a222a20034188046a41186a221c290300370300200320032903a8043703d00420032003290388043703e803200320253a00f004200341f9046a202629030037000020034181056a202b29030037000020034189056a2024290300370000200320032903d0043700f104200320223a00910520034192056a222520032903e8033701002003419a056a2002290300370100200341a2056a2017290300370100200341aa056a202a29030037010041002124200341e4046a2025410020221b3602002003201a3703d804200320063703d004200320233602e004200341003602b004200342013703a8042003200341d0046a3602880420034188046a200341a8046a10a301202b200341a8046a10aa0120032802ac04212b20034180036a412020032802a804222220032802b00410070240202b450d002022102a0b202a42003703002017420037030020024200370300200342003703e80341d3aec400411a200341e8036a1000200341f0046a41186a202a290300370300200341f0046a41106a2017290300370300200341f0046a41086a2002290300370300200320032903e8033703f004200341203602d4042003200341f0046a3602d0042023200341d0046a10ff012027200341c8036a41086a290300370300201b200341c8036a41106a290300370300201c200341c8036a41186a290300370300200320032903c80337038804410121020b200341fd046a200341a0036a41086a29030037000020034185056a200341a0036a41106a2903003700002003418d056a200341a0036a41186a29030037000020034195056a20023a000020034196056a2003290388043701002003419e056a20034188046a41086a290300370100200341a6056a20034188046a41106a290300370100200341ae056a20034188046a41186a290300370100200320243a00f404200320032903a0033700f5042003200341f0006a3602f004200341003602d804200342013703d0042003200341f0006a3602a804200341a8046a200341d0046a10a301200341f0046a410472200341d0046a10a90120032802d4042102200341d0006a412020032802d004221720032802d804100702402002450d002017102a0b20032802d401450d4a20032802d001102a410021020c4b0b2001410c6a2802002108200141086a280200211b41042117200141046a280200211c2002411a6a290100211a200241196a2d0000211d200241186a2d0000211e200241166a2f0100211f200241156a2d00002120200241146a2d00002121200241126a2f01002128200241116a2d00002129200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d00002127200241046a2d00002114200241026a2f010021070240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b4100212a410021020b202a41ffff0371410874201741ff017172200241187472212a0240202b450d00410f211741ea9fc6002102024002400240024002400240202a0e070001020304054c000b20264108742027722025411874722102202341087420247220224118747221170c4b0b410e211741dc9fc60021020c4a0b410c211741d09fc60021020c490b4109211741c79fc60021020c480b4113211741b49fc60021020c470b4111211741a39fc60021020c460b2003201a370398012003201d3a0097012003201e3a0096012003201f3b019401200320203a009301200320213a009201200320283b019001200320293a008f01200320223a008e01200320233b018c01200320243a008b01200320253a008a01200320263b018801200320273a0087012003202a36008301200320143a008201200320073b018001410e10282202450d212002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f00420034180016a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a10062102024020032802f0042217417f460d002002450d00200320173602a403200320023602a003200341f0046a200341a0036a108a02200328029005222a450d23200341f0046a41186a2903002106200341f0046a410c6a3502002104200341bc056a280200212b200341f0046a41c4006a2902002105200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412c6a2f01002126200329038005212c20032902f404212d20032d00b305212720032d00b205211d20032d00af05211e20032d00ae05211f20032d00ab05212020032d00aa05212120032d00a705212820032d00a605212920032d00a3052114200328009f05210720032d009e052109200329029405211a20032802f004210a02402017450d002002102a0b200341b0016a41186a2006370300200341b0016a410c6a20043e0200200341b0016a41c4006a2005370200200341f3016a20273a0000200341f2016a201d3a0000200341b0016a41c0006a20223b0100200341ef016a201e3a0000200341ee016a201f3a0000200341b0016a413c6a20233b0100200341eb016a20203a0000200341ea016a20213a0000200341b0016a41386a20243b0100200341e7016a20283a0000200341e6016a20293a0000200341b0016a41346a20253b0100200341e3016a20143a0000200341df016a2007360000200341de016a20093a0000200341b0016a41246a201a3702002003202c3703c0012003202d3702b4012003202b3602fc01200320263b01dc012003202a3602d0012003200a3602b0012008450d44200341003a00a804200341103602e0042003201c200841246c6a3602dc042003201c3602d8042003201b3602d4042003201c3602d0042003200341a8046a3602e404200341f0046a200341d0046a1085040240024020032d00f0044101460d0020032802dc04212a20032802d8042102024003400240202a2002470d002002212b0c020b20022d00002117200241246a222b210220174102470d000b0b2003202b3602d8044100212441012123024020032802d4040d00410021020c020b20032802d004102a410021020c010b412010282223450d25202320032900f104370000202341186a20034189056a290000370000202341106a20034181056a290000370000202341086a200341f9046a290000370000200341a0036a41106a200341d0046a41106a290300370300200341a0036a41086a200341d0046a41086a290300370300200320032903d0043703a003200341f0046a200341a0036a1085040240024020032d00f0040d0041012102410121240c010b200341f0046a4101722117410221224120212b4101210241012124034020034188046a41186a2225201741186a29000037030020034188046a41106a2226201741106a29000037030020034188046a41086a2227201741086a2900003703002003201729000037038804024020022024470d00200241016a222a2002490d472022202a2022202a4b1b222441ffffff3f712024470d472024410574222a4100480d470240024020020d00202a102821230c010b2023202b202a102c21230b20230d00202a41011037000b2023202b6a222a200329038804370000202a41186a2025290300370000202a41106a2026290300370000202a41086a2027290300370000202241026a2122202b41206a212b200241016a2102200341f0046a200341a0036a10850420032d00f0040d000b0b20032802ac03212b20032802a8032117024003400240202b2017470d00201721220c020b20172d0000212a201741246a22222117202a4102470d000b0b200320223602a80320032802a403450d0020032802a003102a0b024020032d00a804450d002024450d432023102a0c430b2023450d42200341b0016a412c6a222a10a604200320023602a801200320243602a401200320233602a001411210282202450d2520024100290095ae44370000200241106a41002f00a5ae443b0000200241086a410029009dae4437000020034292808080a0023702f404200320023602f004202a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222b420037030020034188046a41106a2222420037030020034188046a41086a2223420037030020034200370388042017200220034188046a1000200341d0006a41186a202b290300370300200341d0006a41106a2022290300370300200341d0006a41086a20232903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006212b024020032802f0042222417f460d00202b450d00200320223602ec032003202b3602e803200341d0046a200341e8036a106d20032802d0042224450d3f20032802d404212a20032802ec032202450d3e20032002417f6a22233602ec03200320032802e803222541016a22263602e80320252d0000221741014b0d3e410021020240024020170e020100010b41002102200341003a0090050340024020232002470d00200341003602ec03200241ff0171450d41200341003a0090050c410b200341f0046a20026a202520026a221741016a2d00003a00002003201741026a3602e8032003200241016a22173a0090052017210220174120470d000b200341a0036a41086a200341f0046a41086a290300370300200341a0036a41106a200341f0046a41106a290300370300200341a0036a41186a200341f0046a41186a290300370300200320032903f0043703a0032003202320176b22233602ec0341012102202520176a41016a21260b20034188046a41186a200341a0036a41186a29030037030020034188046a41106a200341a0036a41106a29030037030020034188046a41086a200341a0036a41086a290300370300200320032903a003370388042023450d3e20032023417f6a22253602ec032003202641016a3602e80320262d0000222341014b0d3e410021170240024020230e020100010b41002117200341003a0090050340024020252017470d00200341003602ec03201741ff0171450d41200341003a0090050c410b200341f0046a20176a202620176a222341016a2d00003a00002003202341026a3602e8032003201741016a22233a0090052023211720234120470d000b200341a0036a41086a200341f0046a41086a290300370300200341a0036a41106a200341f0046a41106a290300370300200341a0036a41186a200341f0046a41186a290300370300200320032903f0043703a0032003202520236b3602ec03410121170b200341c0026a41186a2223200341a0036a41186a2225290300370300200341c0026a41106a2226200341a0036a41106a2227290300370300200341c0026a41086a221b200341a0036a41086a221c290300370300200341e0026a41086a221d20034188046a41086a290300370300200341e0026a41106a221e20034188046a41106a290300370300200341e0026a41186a221f20034188046a41186a290300370300200320032903a0033703c00220032003290388043703e002200341a0026a41186a2220201f290300370300200341a0026a41106a221f201e290300370300200341a0026a41086a221e201d290300370300200320032903e0023703a00220034180026a41186a221d202329030037030020034180026a41106a2223202629030037030020034180026a41086a2226201b290300370300200320032903c00237038002200341f0046a41186a2020290300370300200341f0046a41106a201f290300370300200341f0046a41086a201e290300370300200320032903a0023703f0042025201d29030037030020272023290300370300201c202629030037030020032003290380023703a0030c400b200341e8036a41186a22024200370300200341e8036a41106a22174200370300200341e8036a41086a222b4200370300200342003703e80341a7aec400411a200341e8036a1000200341f0046a41186a22222002290300370300200341f0046a41106a22232017290300370300200341f0046a41086a2224202b290300370300200320032903e8033703f004200341a0036a200341f0046a412010fd01024020032d00a0030d002002420037030020174200370300202b4200370300200342003703e80341a7aec400411a200341e8036a100020222002290300370300202320172903003703002024202b290300370300200320032903e8033703f004200341203602d4042003200341f0046a3602d004202a200341d0046a10ff01410021170c3c0b200341c8036a41186a200341b9036a290000370300200341c8036a41106a200341b1036a290000370300200341c8036a41086a200341a9036a290000370300200320032900a1033703c80320034180036a200341c8036a10ae01200341003602f00420034180036a4120200341f0046a1006212320032802f0042226417f460d262023450d26200320263602cc04200320233602c804200341f0006a200341c8046a106d20032802702224450d392003280274212220032802cc042202450d38200341f8006a280200212b20032002417f6a22273602cc04200320032802c804221b41016a221c3602c804201b2d0000220241014b0d38410021250240024020020e020100010b41002102200341003a0090050340024020272002470d00200341003602cc04200241ff0171450d3b200341003a0090050c3b0b200341f0046a20026a201b20026a221741016a2d00003a00002003201741026a3602c8042003200241016a22173a0090052017210220174120470d000b20034188046a41086a200341f0046a41086a290300221a370300200341d0046a41186a200341f0046a41186a290300370300200341d0046a41106a200341f0046a41106a290300370300200341d0046a41086a201a3703002003202720176b22273602cc04200320032903f004221a370388042003201a3703d00441012125201b20176a41016a211c0b200341e8036a41186a200341d0046a41186a290300370300200341e8036a41106a200341d0046a41106a290300370300200341e8036a41086a200341d0046a41086a290300370300200320032903d0043703e80341002117200341003a00f0042027450d3820032027417f6a22273602cc042003201c41016a3602c804201c2d0000220241014b0d380240024020020e020100010b41002102200341003a0090050340024020272002470d00200341003602cc04200241ff0171450d3b200341003a0090050c3b0b200341f0046a20026a201c20026a221741016a2d00003a00002003201741026a3602c8042003200241016a22173a0090052017210220174120470d000b200341a8046a41086a200341f0046a41086a290300221a370300200341d0046a41186a200341f0046a41186a290300370300200341d0046a41106a200341f0046a41106a290300370300200341d0046a41086a201a3703002003202720176b3602cc04200320032903f004221a3703a8042003201a3703d004410121170b200341c0026a41186a2202200341d0046a41186a2227290300370300200341c0026a41106a221b200341d0046a41106a221c290300370300200341c0026a41086a221d200341d0046a41086a221e290300370300200341e0026a41086a221f200341e8036a41086a290300370300200341e0026a41106a2220200341e8036a41106a290300370300200341e0026a41186a2221200341e8036a41186a290300370300200320032903d0043703c002200320032903e8033703e002200341a0026a41186a22282021290300370300200341a0026a41106a22212020290300370300200341a0026a41086a2220201f290300370300200320032903e0023703a00220034180026a41186a221f200229030037030020034180026a41106a2202201b29030037030020034180026a41086a221b201d290300370300200320032903c00237038002200341f0046a41186a2028290300370300200341f0046a41106a2021290300370300200341f0046a41086a2020290300370300200320032903a0023703f0042027201f290300370300201c2002290300370300201e201b29030037030020032003290380023703d0040c3a0b4110211741b581c50021020c450b2002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b4100212a410021020b202a41ffff0371410874201741ff017172200241187472212a0240202b450d00410f211741ea9fc60021020240202a0e0700040506074c4d000b20264108742027722025411874722102202341087420247220224118747221170c4c0b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d252002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006211720032802f0042202417f460d29200320023602d404200320173602d004200341f0046a200341d0046a108a02200328029005222a450d26200341f0046a41186a290300211a200341f0046a410c6a3502002106200341bc056a280200212b200341f0046a41c4006a2902002104200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412c6a2f01002126200329038005210520032902f404212c20032d00b305212720032d00b205211b20032d00af05211c20032d00ae05211d20032d00ab05211e20032d00aa05211f20032d00a705212020032d00a605212120032d00a3052128200328009f05212920032d009e052114200329029405212d20032802f004210702402002450d002017102a0b200341b0016a41186a201a370300200341b0016a410c6a20063e0200200341b0016a41c4006a2004370200200341f3016a20273a0000200341f2016a201b3a0000200341b0016a41c0006a20223b0100200341ef016a201c3a0000200341ee016a201d3a0000200341b0016a413c6a20233b0100200341eb016a201e3a0000200341ea016a201f3a0000200341b0016a41386a20243b0100200341e7016a20203a0000200341e6016a20213a0000200341b0016a41346a20253b0100200341e3016a20283a0000200341df016a2029360000200341de016a20143a0000200341d4016a2202202d370200200320053703c0012003202c3702b4012003202b3602fc01200320263b01dc012003202a3602d001200320073602b001200341b0016a412c6a221710a604201710a7042002280200450d4820032802d001102a410021020c490b20012d000121142002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b4100212a410021020b202a41ffff0371410874201741ff017172200241187472212a0240202b450d00410f211741ea9fc60021020240202a0e0700030405064b4c000b20264108742027722025411874722102202341087420247220224118747221170c4b0b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d262002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006210220032802f0042217417f460d282002450d28200320173602d404200320023602d004200341f0046a200341d0046a108a02200328029005222a450d27200341f0046a41186a290300211a200341f0046a410c6a3502002106200341bc056a280200212b200341f0046a41c4006a2902002104200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412c6a2f01002126200329038005210520032902f404212c20032d00b305212720032d00b205211b20032d00af05211c20032d00ae05211d20032d00ab05211e20032d00aa05211f20032d00a705212020032d00a605212120032d00a3052128200328009f05212920032d009e052107200329029405212d20032802f004210802402017450d002002102a0b200341b0016a41186a201a370300200341b0016a410c6a20063e0200200341b0016a41c4006a2004370200200341f3016a20273a0000200341f2016a201b3a0000200341b0016a41c0006a20223b0100200341ef016a201c3a0000200341ee016a201d3a0000200341b0016a413c6a20233b0100200341eb016a201e3a0000200341ea016a201f3a0000200341b0016a41386a20243b0100200341e7016a20203a0000200341e6016a20213a0000200341b0016a41346a20253b0100200341e3016a20283a0000200341df016a2029360000200341de016a20073a0000200341d4016a202d370200200320053703c0012003202c3702b4012003202b3602fc01200320263b01dc012003202a3602d001200320083602b001410d10282202450d2920024100290098af44370000200241056a410029009daf443700002003428d808080d0013702f404200320023602f004200341b0016a412c6a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b024002400240024002400240201441037122024103460d0020020e03010203010b200341d0006a41204101410010070c040b410021170c020b410121170c010b410221170b200320173a00f004410110282202450d2b200220173a0000200341d0006a41202002410110072002102a0b20032802d401450d4720032802d001102a410021020c480b2001411d6a29000021062001411c6a2d000021072001411b6a2d00002108200141196a2f00002109200141186a2d0000210a200141176a2d0000210b200141156a2f0000210c200141146a2d0000210d200141136a2d0000210e200141116a2f0000210f200141106a2d000021102001410f6a2d000021112001410d6a2f000021122001410c6a2d00002113200141086a280200211b200141076a2d00002115200141056a2f0000211641042117200141046a2d000021182002411a6a290100211a200241196a2d0000211c200241186a2d0000211d200241166a2f0100211e200241156a2d0000211f200241146a2d00002120200241126a2f01002121200241116a2d00002128200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d00002127200241046a2d00002129200241026a2f010021140240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b4100212a410021020b202a41ffff0371410874201741ff017172200241187472212a202b450d04410f211741ea9fc60021020240202a0e070001020304494a000b20264108742027722025411874722102202341087420247220224118747221170c490b410e211741dc9fc60021020c480b410c211741d09fc60021020c470b4109211741c79fc60021020c460b4113211741b49fc60021020c450b2003201a3703e0032003201c3a00df032003201d3a00de032003201e3b01dc032003201f3a00db03200320203a00da03200320213b01d803200320283a00d703200320223a00d603200320233b01d403200320243a00d303200320253a00d203200320263b01d003200320273a00cf032003202a3600cb03200320293a00ca03200320143b01c803200341f0046a200341c8036a10b1044101212a0240024020032d00f0044101460d00410b211741aa81c50021020c010b2003418a046a20032d00f3043a0000200341b0016a41086a20034184056a290200370300200341bd016a20034189056a290000370000200320032f00f1043b0188042003200341fc046a2902003703b001200341f0046a41086a28020021174100212a20032802f40421020b20034180036a41026a222b20034188046a41026a2d00003a0000200341a8046a41086a2222200341b0016a41086a290300370300200341a8046a41106a200341b0016a41106a290300370300200320032f0188043b018003200320032903b0013703a804202a0d44200341fb036a202229030037000020034180046a200341b5046a290000370000200320032f0180033b01e803200320173600ef03200320023600eb03200320032903a8043700f3032003202b2d00003a00ea030240201841ff01714101470d00200341f0046a201b41067610fe0120032802f00421170240024020032802f804201b413f7122024b0d00410021020c010b201720024105746a2202290018210620022d0017210720022d0016210820022f0014210920022d0013210a20022d0012210b20022f0010210c20022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d000721132002280003211b20022d0002211520022f00002116410121020b024020032802f404450d002017102a0b20020d0041dc9fc6002102410e21170c450b200320063703c004200320073a00bf04200320083a00be04200320093b01bc042003200a3a00bb042003200b3a00ba042003200c3b01b8042003200d3a00b7042003200e3a00b6042003200f3b01b404200320103a00b304200320113a00b204200320123b01b004200320133a00af042003201b3600ab04200320153a00aa04200320163b01a804410e10282202450d252002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a8046a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b0240200341d0006a41204101410041001003417f460d0041cc80c5002102411921170c450b200341a8046a200341e8036a4120109c05450d41410e10282202450d26200241002900fcae44370000200241066a4100290082af443700002003428e808080e0013702f404200320023602f004200341c8036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341203602f4042003200341d0006a3602f004200341a8046a200341f0046a10ff01410e10282202450d272002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341e8036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006212a0240024020032802f0042217417f470d00410021020c010b2003201736028c042003202a36028804200341f0046a20034188046a108a022003280290052202450d29200341b0016a41186a200341f0046a41186a290300370300200341b0016a41106a200341f0046a41106a290300370300200341b0016a41086a200341f0046a41086a290300370300200320032903f0043703b0012003419c056a2f010021222003419f056a2800002124200341a4056a2f01002126200341a8056a2f0100211c200341ac056a2f0100211f200341b0056a2f01002128200341b4056a290200212d200341bc056a2802002107200329029405212c20032d009e05212320032d00a305212520032d00a605212720032d00a705211b20032d00aa05211d20032d00ab05211e20032d00ae05212020032d00af05212120032d00b205212920032d00b305211402402017450d00202a102a0b200341d0006a412010090b200341a0036a41186a200341b0016a41186a290300221a370300200341a0036a41106a200341b0016a41106a2903002206370300200341a0036a41086a200341b0016a41086a2903002204370300200320032903b00122053703a003200341f0046a41186a2217201a370300200341f0046a41106a222a2006370300200341f0046a41086a222b2004370300200320053703f0042002450d41200341d0046a41186a2017290300221a370300200341d0046a41106a202a2903002206370300200341d0046a41086a202b2903002204370300200320032903f00422053703d0042017201a370300202a2006370300202b2004370300200341b4056a202d370200200341b3056a20143a0000200341b2056a20293a0000200341b0056a20283b0100200341af056a20213a0000200341ae056a20203a0000200341ac056a201f3b0100200341ab056a201e3a0000200341aa056a201d3a0000200341a8056a201c3b0100200341a7056a201b3a0000200341a6056a20273a0000200341a4056a20263b0100200341a3056a20253a00002003419f056a20243600002003419e056a20233a000020034194056a202c370200200320053703f004200320073602bc05200320223b019c052003200236029005410e10282202450d292002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702b401200320023602b001200341a8046a200341b0016a108f0120032802b801210220032802b001211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802b401450d0020032802b001102a0b200341203602b4012003200341d0006a3602b001200341f0046a200341b0016a10b604200328029405450d41200328029005102a410021020c420b4101212b024020022d000120022d000072450d0041a39fc600210241112117410121220c450b200141046a2802002102200341f0046a41086a22174200370300200342003703f00441889cc6004116200341f0046a1008200341d0046a41086a2017290300370300200320032903f0043703d004200320023602f004200341d0046a4110200341f0046a410410070c2c0b20022d000120022d0000720d2c200341f0046a41086a22024200370300200342003703f004418e9dc6004110200341f0046a1008200341d0046a41086a2002290300370300200320032903f0043703d004200341023a00f0044101212b410110282202450d28200241023a0000200341d0046a41102002410110072002102a0c2b0b20022d000120022d0000720d2b200341f0046a41086a22024200370300200342003703f004418e9dc6004110200341f0046a1008200341d0046a41086a2002290300370300200320032903f0043703d0044101212b200341013a00f004410110282202450d28200241013a0000200341d0046a41102002410110072002102a0c2a0b200141086a280200212a200141046a2802002123024020022d000120022d000072450d0041a39fc600210241112117410021224101212b202a450d422023102a0c420b2001410c6a2802002102200341f0046a41086a22174200370300200342003703f00441c8ffc4004115200341f0046a1008200341d0046a41086a2017290300370300200320032903f0043703d004200341003602f804200342013703f0042002200341f0046a10b40102402002450d00200241057421172023210203402002200341f0046a108f01200241206a2102201741606a22170d000b0b20032802f4042102200341d0046a411020032802f004221720032802f804100702402002450d002017102a0b4101212b202a450d282023102a0c280b410e41011037000b410e41011037000b410e41011037000b410d41011037000b410141011037000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b41c4d1c3004133200341e0026a419cd9c3001038000b202b41081037000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b200341c8016a200341b4056a290200370300200341c0016a200341ac056a290200370300200341b0016a41086a200341a4056a2902003703002003200329029c053703b001200342f3e885db96cddbb3203703e803200310980136028804200341d0046a200341b0016a109a0220032802d404211720032802d004210220032802d804212a200341e4046a200341e8036a36020020032002202a4105746a3602dc04200320023602d804200320173602d404200320023602d004200320034188046a3602e004200341a8046a200341d0046a108701200341d0046a41086a200341a8046a41086a280200360200200320032903a8043703d004200341b0016a200341d0046a109c02200341b0016a1095020c2e0b41c4d1c3004133200341e0026a419cd9c3001038000b411841081037000b200c41081037000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b411241011037000b41b7b3c0004192011050000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b412041011037000b411241011037000b41b7b3c0004192011050000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b41b581c5002102411021170c210b410d41011037000b410141011037000b410e41011037000b410e41011037000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b410e41011037000b410141011037000b410141011037000b41002122410021020c180b41002102410121220c170b41a39fc6002102411121170c150b2022450d002024102a0b410221250b20254102460d01200341a8046a41186a221c200341f0046a41186a290300370300200341a8046a41106a221d200341f0046a41106a290300370300200341a8046a41086a221e200341f0046a41086a29030037030020034188046a41086a221f200341d0046a41086a222729030037030020034188046a41106a2220200341d0046a41106a220229030037030020034188046a41186a2221200341d0046a41186a221b290300370300200320032903f0043703a804200320032903d0043703880402402026450d002023102a0b201b201c2903003703002002201d2903003703002027201e290300370300200341e8036a41086a2223201f290300370300200341e8036a41106a22262020290300370300200341e8036a41186a221c2021290300370300200320032903a8043703d00420032003290388043703e803200320253a00f004200341f9046a202729030037000020034181056a200229030037000020034189056a201b290300370000200320032903d0043700f104200320173a00910520034192056a222520032903e8033701002003419a056a2023290300370100200341a2056a2026290300370100200341aa056a201c290300370100200220254100201741ff01714101461b3602002003202a3602dc042003202b3602d804200320223602d404200320243602d004200341003602b004200342013703a804202b200341a8046a10b401200341dc046a21230240202b450d00202b41057421172024210203402002200341a8046a108f01200241206a2102201741606a22170d000b0b2023200341a8046a10aa0120032802ac04210220034180036a412020032802a804221720032802b004100702402002450d002017102a0b02402022450d002024102a0b200341e8036a41186a22024200370300200341e8036a41106a22174200370300200341e8036a41086a222b4200370300200342003703e80341a7aec400411a200341e8036a1000200341f0046a41186a2002290300370300200341f0046a41106a2017290300370300200341f0046a41086a202b290300370300200320032903e8033703f004200341203602d4042003200341f0046a3602d004202a200341d0046a10ff0120034188046a41086a200341c8036a41086a29030037030020034188046a41106a200341c8036a41106a29030037030020034188046a41186a200341c8036a41186a290300370300200320032903c80337038804410121170b410021020c040b41c4d1c3004133200341e0026a419cd9c3001038000b202a450d002024102a0b410221020b20024102460d01200341d0046a41186a2223200341f0046a41186a290300370300200341d0046a41106a2225200341f0046a41106a290300370300200341d0046a41086a2226200341f0046a41086a290300370300200341a8046a41086a2227200341a0036a41086a221b290300370300200341a8046a41106a221c200341a0036a41106a221d290300370300200341a8046a41186a221e200341a0036a41186a221f290300370300200320032903f0043703d004200320032903a0033703a80402402022450d00202b102a0b201f2023290300370300201d2025290300370300201b202629030037030020034188046a41086a202729030037030020034188046a41106a201c29030037030020034188046a41186a201e290300370300200320032903d0043703a003200320032903a80437038804202a450d002024102a0b200341fd046a200341a0036a41086a29030037000020034185056a200341a0036a41106a2903003700002003418d056a200341a0036a41186a29030037000020034195056a20173a000020034196056a2003290388043701002003419e056a20034188046a41086a290300370100200341a6056a20034188046a41106a290300370100200341ae056a20034188046a41186a290300370100200320023a00f404200320032903a0033700f5042003200341a0016a3602f004200341003602d804200342013703d00420032802a001210220032802a8012217200341d0046a10b401200341f0046a410472212a02402017450d002017410574211703402002200341d0046a108f01200241206a2102201741606a22170d000b0b202a200341d0046a10a90120032802d4042102200341d0006a412020032802d004221720032802d804100702402002450d002017102a0b024020032802a401450d0020032802a001102a0b024020032802d401450d0020032802d001102a0b4100212b41012122410021020c0d0b41c4d1c3004133200341e0026a419cd9c3001038000b41dc9fc6002102410e21174100212b20032802d401212a0c020b1031000b201aa7212a41e881c5002102411721174101212b0b0240202a450d0020032802d001102a0b202b0d00410121224100212b0c080b410121224100212b201b450d07201c102a0c070b41c4d1c3004133200341e0026a419cd9c3001038000b41c4d1c3004133200341e0026a419cd9c3001038000b200328029405450d00200328029005102a410021020c010b410021020b4101212b410121220c020b4111211741a39fc60021020b4101212b410121220b0240024020012d0000222a410d4b0d004101202a7441be3f710d010240202a4106460d00202a410d470d012022450d02200141086a280200450d02200141046a280200102a0c020b202b450d01200141086a280200450d01200141046a280200102a0c010b200141086a280200450d00200141046a280200102a0b2000201736020420002002360200200341c0056a24000b990d02067f077e230041b0016b22052400024002400240024002400240411410282206450d00200641002900cfe140370000200641106a41002800dfe140360000200641086a41002900d7e14037000020054294808080c002370234200520063602302001200541306a108f012005280238210620052802302107200541c0006a41186a22084200370300200541c0006a41106a22094200370300200541c0006a41086a220a42003703002005420037034020072006200541c0006a1000200541106a41186a2008290300370300200541106a41106a2009290300370300200541106a41086a200a2903003703002005200529034037031002402005280234450d002005280230102a0b20054100360240200541106a4120200541c0006a100621060240024020052802402207417f470d004200210b4200210c0c010b20074110490d02200641086a290000210c2006290000210b2006102a0b411410282206450d02200641002900cfe140370000200641106a41002800dfe140360000200641086a41002900d7e14037000020054294808080c002370234200520063602302002200541306a108f012005280238210620052802302107200541c0006a41186a22084200370300200541c0006a41106a22094200370300200541c0006a41086a220a42003703002005420037034020072006200541c0006a1000200541106a41186a2008290300370300200541106a41106a2009290300370300200541106a41086a200a2903003703002005200529034037031002402005280234450d002005280230102a0b20054100360240200541106a4120200541c0006a100621060240024020052802402207417f470d004200210d4200210e0c010b20074110490d04200641086a290000210e2006290000210d2006102a0b024020034280a094a58d1d7c220f200354220620042006ad7c2210200454200f20035a1b450d0041f092c1002106412821010c060b0240200b200f7d2211200b56200c20107d200b200f54ad7d220f200c56200f200c511b4101470d00419893c1002106411d21010c060b0240200342ffffe883b1de165620044200522004501b0d00200d200e8450450d0041e293c1002106411f21010c060b200541086a200141022011200f10bc01024020052802082206450d00200528020c21010c060b0240200d20037c220c200d542206200e20047c2006ad7c220b200e54200b200e511b450d0041b593c1002106412d21010c060b41002106024020012002470d000c060b0240200120024120109c050d000c060b20012011200f108f02411410282206450d04200641002900cfe140370000200641106a41002800dfe140360000200641086a41002900d7e14037000020054294808080c002370234200520063602302002200541306a108f012005280238210620052802302107200541c0006a41186a22084200370300200541c0006a41106a22094200370300200541c0006a41086a220a42003703002005420037034020072006200541c0006a1000200541106a41186a2008290300370300200541106a41106a2009290300370300200541106a41086a200a2903003703002005200529034037031002402005280234450d002005280230102a0b0240200541106a41204101410041001003417f470d002002109302200541f8006a200b370300200541f0006a200c370300200541c0006a41086a41003a0000200541c9006a2002290000370000200541d1006a200241086a290000370000200541d9006a200241106a290000370000200541e1006a200241186a290000370000200541023a004041014100200541c0006a10cc010b2002200c200b108f022005420037034820054280a094a58d1d3703402005200541c0006a360210200541106a109d01200541a8016a4200370300200541a0016a4280a094a58d1d37030020054198016a200437030020054190016a2003370300200541c0006a41086a41023a0000200541c9006a2001290000370000200541d1006a200141086a290000370000200541d9006a200141106a290000370000200541e1006a200141186a290000370000200541e9006a2002290000370000200541f1006a200241086a290000370000200541f9006a200241106a29000037000020054181016a200241186a290000370000200541023a00404100210641014100200541c0006a10cc010c050b411441011037000b41c4d1c3004133200541c0006a419cd9c3001038000b411441011037000b41c4d1c3004133200541c0006a419cd9c3001038000b411441011037000b2000200136020420002006360200200541b0016a24000b881201097f230041f0026b22032400024002400240024002400240024002400240411410282204450d00200441002900cfe140370000200441106a41002800dfe140360000200441086a41002900d7e14037000020034294808080c002370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b200320013703202003200237032820034180026a4120200341206a41101007200142ffffe883b1de165620024200522002501b0d06411410282204450d01200441002900cfe140370000200441106a41002800dfe140360000200441086a41002900d7e14037000020034294808080c002370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b200341086a20034180026a109402200341086a41106a29030021022003290310210120032802082109410e10282204450d02200441002900fbe140370000200441066a4100290081e2403700002003428e808080e001370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b20034180026a4120100902402001200284500d002009450d0020032001370320200320023703282003200341206a3602800220034180026a109d010b2000109502411710282204450d03200441002900f1d8433700002004410f6a4100290080d943370000200441086a41002900f9d84337000020034297808080f002370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b200341206a20034180026a109602024020032d002022044102460d0020034180026a412010090b2003413c6a2802002106200341386a2802002105024020040d002005200341c0006a28020010042006450d060c050b20044103710d0520060d040c050b411441011037000b411441011037000b410e41011037000b411741011037000b2005102a0b200341f0016a2000108b0220032802f001210420032802f8012105410021062003410036022020042005200341206a10062108024002400240024020032802202207417f460d00200320073602e402200320083602e002200341206a200341e0026a10e80120032d00204101460d0120034180026a200341206a41017241e000109a051a02402007450d002008102a0b200341206a20034180026a41e000109a051a200420051009410121060b20034190016a200341206a41e000109a051a200341206a20034190016a41e000109a051a2006450d0120034180026a200341206a41e000109a051a024020032802f401450d002004102a0b200341206a20034180026a41e000109a051a200341c0006a210a200341e0006a210b4104210641e7e485f30621040340200b210702400240200441e9dabdf306460d000240200441e7e485f306470d00200341206a21070c010b200a2107200441e2c289ab06460d00410121084100210541012107410121090c010b41202105410021084120102822090d00412041011037000b200920072005109a0521072003200536029c01200320053602980120032007360294012003200436029001200341f0016a20034190016a108c0220032802f001220420032802f8011009024020032802f401450d002004102a0b024020080d002007102a0b2006410c460d03200641f8c8c0006a2800002104200641046a21060c000b0b41c4d1c3004133200341e8026a419cd9c3001038000b20032802f401450d002004102a0b411810282204450d01200441002900e3e140370000200441106a41002900f3e140370000200441086a41002900ebe140370000200342988080808003370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b2003410036022020034180026a4120200341206a10062104024020032802202205417f460d0020054110490d03200441086a2900002102200429000021012004102a200120028450450d010b2000109702200341206a41086a41013a0000200341296a2000290000370000200341316a200041086a290000370000200341396a200041106a290000370000200341c1006a200041186a290000370000200341023a002041014100200341206a10cc010b200341f0026a24000f0b411841011037000b41c4d1c3004133200341e8026a419cd9c3001038000bd40801067f230041c0016b220324000240024002400240411810282204450d00200441002900e3e140370000200441106a41002900f3e140370000200441086a41002900ebe140370000200342988080808003370244200320043602402000200341c0006a108f012003280248210420032802402105200341d0006a41186a22064200370300200341d0006a41106a22074200370300200341d0006a41086a220842003703002003420037035020052004200341d0006a1000200341206a41186a2006290300370300200341206a41106a2007290300370300200341206a41086a20082903003703002003200329035037032002402003280244450d002003280240102a0b2003200137035020032002370358200341206a4120200341d0006a411010070240200142ffffe883b1de165620024200522002501b0d00411810282204450d02200441002900e3e140370000200441106a41002900f3e140370000200441086a41002900ebe140370000200342988080808003370244200320043602402000200341c0006a108f012003280248210420032802402105200341d0006a41186a22064200370300200341d0006a41106a22074200370300200341d0006a41086a220842003703002003420037035020052004200341d0006a1000200341206a41186a2006290300370300200341206a41106a2007290300370300200341206a41086a20082903003703002003200329035037032002402003280244450d002003280240102a0b200341086a200341206a109402024020032903102202200341086a41106a290300220184500d002003280208450d0020032002370350200320013703582003200341d0006a360220200341206a109d010b411410282204450d03200441002900cfe140370000200441106a41002800dfe140360000200441086a41002900d7e14037000020034294808080c002370244200320043602402000200341c0006a108f012003280248210420032802402105200341d0006a41186a22064200370300200341d0006a41106a22074200370300200341d0006a41086a220842003703002003420037035020052004200341d0006a1000200341206a41186a2006290300370300200341206a41106a2007290300370300200341206a41086a20082903003703002003200329035037032002402003280244450d002003280240102a0b20034100360250200341206a4120200341d0006a10062104024020032802502205417f460d0020054110490d05200441086a2900002102200429000021012004102a200120028450450d010b2000109702200341d0006a41086a41013a0000200341d9006a2000290000370000200341e1006a200041086a290000370000200341e9006a200041106a290000370000200341f1006a200041186a290000370000200341023a005041014100200341d0006a10cc010b200341c0016a24000f0b411841011037000b411841011037000b411441011037000b41c4d1c3004133200341d0006a419cd9c3001038000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccd1c5003602002000410436021c200041c4d1c5003602182000200041186a360210200041e8b5c300103e000bb30701057f230041106b2203240020034100360208200342013703002002200310b40102400240024002400240024002402002450d00200241c4006c210403400240024020012d00004101460d0002400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d0a200241017422062005200620054b1b22064100480d0a0240024020020d002006102821050c010b200328020020022006102c21050b2005450d052003200636020420032005360200200328020821020b2003200241016a360208200520026a41003a0000200141046a28020021060240024020032802042205200328020822026b4104490d00200328020021050c010b200241046a22072002490d0a200541017422022007200220074b1b22024100480d0a0240024020050d002002102821050c010b200328020020052002102c21050b2005450d062003200236020420032005360200200328020821020b2003200241046a360208200520026a20063600000c010b02400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d09200241017422062005200620054b1b22064100480d090240024020020d002006102821050c010b200328020020022006102c21050b2005450d062003200636020420032005360200200328020821020b2003200241016a360208200520026a41013a00002003200336020c200141016a2003410c6a10c8010240200141216a2d00004101460d0002400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d0a200241017422062005200620054b1b22064100480d0a0240024020020d002006102821050c010b200328020020022006102c21050b2005450d082003200636020420032005360200200328020821020b2003200241016a360208200520026a41003a00000c010b02400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d09200241017422062005200620054b1b22064100480d090240024020020d002006102821050c010b200328020020022006102c21050b2005450d082003200636020420032005360200200328020821020b2003200241016a360208200520026a41013a0000200141226a2003108f010b200141c4006a2101200441bc7f6a22040d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b200641011037000b200241011037000b200641011037000b200641011037000b200641011037000b1031000bcc0b03057f037e047f230041a0016b22012400200141306a41086a220242003703002001420037033041f5b8c3004113200141306a1008200141206a41086a2002290300370300200120012903303703204100210220014100360230200141206a4110200141306a100621030240024002400240024002400240024002400240024020012802302204417f460d002003450d0020044104490d01200328000021022003102a0b410110282203450d01200320002d00003a0000200341014102102c2203450d02200320002d00013a0001200341024104102c2203450d03200320002d00023a0002200320002d00033a0003200341044108102c2203450d04200320002d00043a0004200320002d00053a0005200320002d00063a0006200320002d00073a0007200341084110102c2203450d05200320002d00083a0008200320002d00093a0009200320002d000a3a000a200320002d000b3a000b200320002d000c3a000c200320002d000d3a000d200320002d000e3a000e200320002d000f3a000f200341104120102c2203450d06200320002d00103a0010200320002d00113a0011200320002d00123a0012200320002d00133a0013200320002d00143a0014200320002d00153a0015200320002d00163a0016200320002d00173a0017200320002d00183a0018200320002d00193a0019200320002d001a3a001a200320002d001b3a001b200320002d001c3a001c200320002d001d3a001d200320002d001e3a001e200320002d001f3a001f20032d0000210420032d000121052003102a200141206a2004200541087472410676220510fe0102402004413f71220320012802284f0d002001200128022020034105746a2203109d022001290300200141086a290300844200520d00200041086a2900002106200041106a2900002107200041186a290000210820032000290000370000200341186a2008370000200341106a2007370000200341086a2006370000200141306a41086a200141206a41086a280200360200200120012903203703302005200141306a10c5030c0a0b02402001280224450d002001280220102a0b200141306a200210fe010240200128023841c000490d000340200241016a210202402001280234450d002001280230102a0b200141306a200210fe012001280238413f4b0d000b0b200141106a41086a200141306a41086a2205280200220336020020012001290330370310200141306a41186a2209200041186a290000370300200141306a41106a220a200041106a2900003703002005200041086a29000037030020012000290000370330024020032001280214470d00200341016a22042003490d092003410174220b2004200b20044b1b220441ffffff3f712004470d092004410574220c4100480d090240024020030d00200c1028210b0c010b20012802102003410574200c102c210b0b200b450d08200120043602142001200b3602100b200320024106746a210b200128021020034105746a22042001290330370000200441086a2005290300370000200441106a200a290300370000200441186a20092903003700002001200341016a22033602180240200341c000470d00200141306a41086a220342003703002001420037033041f5b8c3004113200141306a1008200141206a41086a2003290300370300200120012903303703202001200241016a360230200141206a4110200141306a410410070b200141306a41086a2203200141106a41086a280200360200200120012903103703302002200141306a10c50320032000290000370300200141306a41106a200041086a290000370300200141306a41186a200041106a290000370300200141d0006a200041186a2900003703002001200b360234200141013a003041014100200141306a10cc010c090b41c4d1c3004133200141306a419cd9c3001038000b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b200c41011037000b1031000b200141a0016a24000b980102037f037e230041106b220224002002410036020420014120200241046a1006210302400240024020022802042204417f470d00420021050c010b20044110490d01200341086a2900002106200329000021072003102a200141201009420121050b2000200537030020002007370308200041106a2006370300200241106a24000f0b41c4d1c3004133200241086a419cd9c3001038000ba00803067f047e027f230041b0016b22012400024002400240410e10282202450d00200241002900fcae44370000200241066a4100290082af443700002001428e808080e00137026c200120023602682000200141e8006a108f01200128027021022001280268210320014188016a41186a2204420037030020014188016a41106a2205420037030020014188016a41086a2206420037030020014200370388012003200220014188016a1000200141286a41186a2004290300370300200141286a41106a2005290300370300200141286a41086a200629030037030020012001290388013703280240200128026c450d002001280268102a0b20014188016a200141286a412010fd01024020012d00880141014722020d00200141286a412010090b200141c8006a41186a2203200141a1016a2900002207370300200141c8006a41106a220420014199016a2900002208370300200141c8006a41086a220520014191016a29000022093703002001200129008901220a370348200141e8006a41186a22062007370300200141e8006a41106a220b2008370300200141e8006a41086a220c20093703002001200a370368024020020d00200141086a41186a20062903002207370300200141086a41106a200b2903002208370300200141086a41086a200c290300220937030020012001290368220a3703082003200737030020042008370300200520093703002001200a370348410e10282202450d022002410029008aaf44370000200241066a4100290090af443700002001428e808080e00137022c20012002360228200141c8006a200141286a108f01200128023021022001280228210320014188016a41186a2204420037030020014188016a41106a2205420037030020014188016a41086a2206420037030020014200370388012003200220014188016a1000200141e8006a41186a2004290300370300200141e8006a41106a2005290300370300200141e8006a41086a200629030037030020012001290388013703680240200128022c450d002001280228102a0b200141e8006a412010090b410d10282202450d0220024100290098af44370000200241056a410029009daf443700002001428d808080d00137024c200120023602482000200141c8006a108f01200128025021022001280248210320014188016a41186a2204420037030020014188016a41106a2205420037030020014188016a41086a2206420037030020014200370388012003200220014188016a1000200141e8006a41186a2004290300370300200141e8006a41106a2005290300370300200141e8006a41086a200629030037030020012001290388013703680240200128024c450d002001280248102a0b200141e8006a41201009200010a604200010a704200141b0016a24000f0b410e41011037000b410e41011037000b410d41011037000bd00a050a7f027e037f027e017f230041e0006b220224002002410036023820014120200241386a1006210302400240024002400240024002400240024020022802382204417f460d0020030d010b200041023a00000c010b2002200436021c200220033602182004450d0520032d0000210120022004417f6a36021c2002200341016a360218200141014b0d0502400240024020010e020001000b200241086a200241186a106c20022802080d07200228021c200228020c2205490d072005417f4c0d030240024020050d0041012106200228021c21070c010b2005102e2206450d092006200228021822012005109a051a200228021c22042005490d052002200420056b220736021c2002200120056a3602180b20074104490d0520022802182208280000210920022007417c6a220a36021c2002200841046a36021841002101200241003a0058417b210b03400240200a2001470d000240200141ff0171450d00200241003a00580b20050d080c090b200241386a20016a200820016a220441046a2d00003a000020022007200b6a36021c2002200441056a3602182002200141016a22043a0058200b417f6a210b2004210120044120470d000b200220022802383602302002200228003b3600330240024002400240200720046b220b417c6a4110490d00200241c7006a290000210c200229003f210d20022d0057210a2002280053210e200228004f210f2002200820046a220141146a22083602182002200b416c6a221036021c20104104490d002001410c6a2900002111200141046a2900002112200828000021082002200b41686a36021c2002200141186a2210360218200741686a2004460d0320102d000021102002200b41676a221336021c2002200141196a360218201041014b0d034100210420100e020201020b20050d090c0a0b20134104490d01200141196a28000021072002200b41636a36021c20022001411d6a360218410121040b2002200228003336002b20022002280230360228200220022802283602382002200228002b36003b200220022800203602102002200241236a280000360013410021012005210b0c020b2005450d070c060b41002101200241003a00582004417f6a21072004417e6a21040340024020072001470d00200141ff0171450d08200241003a00580c080b200241386a20016a200320016a220b41016a2d00003a00002002200b41026a3602182002200141016a220b3a00582002200436021c2004417f6a2104200b2101200b4120470d000b2002200228003b360033200220022802383602302002200228003336002b20022002280230360228200220022802283602102002200228002b360013200241c7006a2900002111200229003f2112200228004f21062002280053210b20022d005721052002200241236a28000036003b20022002280020360238410121010b2002200228021036023020022002280013360033200220022802383602282002200228003b36002b2003102a200041106a2011370300200041086a2012370300200041c3006a200c3700002000413b6a200d370000200020013a0000200041306a20073602002000412c6a2004360200200041286a2008360200200041246a2009360200200041206a20053602002000411c6a200b360200200041186a2006360200200041d3006a200a3a0000200041cf006a200e360000200041cb006a200f36000020002002280230360001200041046a2002280033360000200041346a2002280228360200200041376a200228002b3600000b200241e0006a24000f0b1036000b200520041044000b2005450d010b2006102a0b41c4d1c3004133200241206a419cd9c3001038000b200541011037000b870201057f230041d0006b220124000240411310282202450d00200241002900cef0423700002002410f6a41002800ddf042360000200241086a41002900d6f04237000020014293808080b002370224200120023602202000200141206a108f012001280228210220012802202100200141306a41186a22034200370300200141306a41106a22044200370300200141306a41086a220542003703002001420037033020002002200141306a1000200141186a2003290300370300200141106a2004290300370300200141086a20052903003703002001200129033037030002402001280224450d002001280220102a0b200141201009200141d0006a24000f0b411341011037000bd10402067f037e230041e0006b22052400024002400240411410282206450d00200641002900cfe140370000200641106a41002800dfe140360000200641086a41002900d7e14037000020054294808080c002370234200520063602302001200541306a108f012005280238210620052802302107200541c0006a41186a22084200370300200541c0006a41106a22094200370300200541c0006a41086a220a42003703002005420037034020072006200541c0006a1000200541106a41186a2008290300370300200541106a41106a2009290300370300200541106a41086a200a2903003703002005200529034037031002402005280234450d002005280230102a0b20054100360240200541106a4120200541c0006a100621060240024020052802402207417f470d004200210b4200210c0c010b20074110490d02200641086a290000210c2006290000210b2006102a0b410121060240200b20027d220d200b56200c20037d200b200254ad7d220b200c56200b200c511b4101470d00200041d7dfc000360204200041086a411d3602000c030b024002400240200d428080e983b1de16544100200b501b0d00200541086a20012004200d200b10bc0120052802082206450d02200528020c210120002006360204200041086a20013602000c010b200041f4dfc000360204200041086a411a3602000b410121060c030b2001200d200b108f02200041106a2003370300200041086a2002370300410021060c020b411441011037000b41c4d1c3004133200541c0006a419cd9c3001038000b20002006360200200541e0006a24000bdb0702067f087e23004180016b22022400024002400240411010282203450d0020034100290089e240370000200341086a4100290091e240370000200242908080808002370254200220033602502001200241d0006a108f012002280258210320022802502104200241e0006a41186a22054200370300200241e0006a41106a22064200370300200241e0006a41086a220742003703002002420037036020042003200241e0006a1000200241306a41186a2005290300370300200241306a41106a2006290300370300200241306a41086a20072903003703002002200229036037033002402002280254450d002002280250102a0b20024100360260200241306a4120200241e0006a1006210302400240024020022802602204417f460d002003450d00024020044110490d0020044170714110460d002004417c714120470d020b41c4d1c3004133200241e0006a419cd9c3001038000b42002108420021090c010b200341086a290000210a2003290000210b200341186a290000210c20032900102108200328002021042003102a411410282203450d02200341002900cfe140370000200341106a41002800dfe140360000200341086a41002900d7e14037000020024294808080c002370254200220033602502001200241d0006a108f012002280258210320022802502101200241e0006a41186a22054200370300200241e0006a41106a22064200370300200241e0006a41086a220742003703002002420037036020012003200241e0006a1000200241306a41186a2005290300370300200241306a41106a2006290300370300200241306a41086a20072903003703002002200229036037033002402002280254450d002002280250102a0b20024100360260200241306a4120200241e0006a100621030240024020022802602201417f470d004200210d420021090c010b20014110490d04200341086a29000021092003290000210d2003102a0b4200210e200241106a200c42004100109801220320046b2201200120034b1bad220f4200109f05200241206a200f420020084200109f0520024200420020084200109f054200210802402002290308200229031884420052200241286a290300220f200229030020022903107c7c220c200f54720d00200a200c200b2002290320220e56200a200c56200a200c511b22031b200c7d200b200e20031b220c200e54ad7d2108200c200e7d210e0b20082009200d200e56200920085620092008511b22031b2109200e200d20031b21080b200020083703002000200937030820024180016a24000f0b411041011037000b411441011037000b41c4d1c3004133200241e0006a419cd9c3001038000baf07030b7f037e037f230041f0006b22022400024002400240024002400240410e10282203450d00200341002900fbe140370000200341066a4100290081e2403700002002428e808080e001370234200220033602302001200241306a108f012002280238210320022802302101200241c0006a41186a22044200370300200241c0006a41106a22054200370300200241c0006a41086a220642003703002002420037034020012003200241c0006a1000200241106a41186a2004290300370300200241106a41106a2005290300370300200241106a41086a20062903003703002002200229034037031002402002280234450d002002280230102a0b20024100360240200241106a4120200241c0006a100621070240024020022802402208417f460d002002200836023420022007360230200241086a200241306a106c20022802080d07200228023422034160712201417f4c0d03200228020c2109024002402003410576220a0d004108210b0c010b20011028220b450d050b02402009450d004100210c41002106410021050340200241c0006a200241306a109b020240024020022d00404101460d00200228023422014110490d002002290041210d20022002280230220341106a3602302002200141706a220436023420044104490d00200341086a290000210e2003290000210f20022001416c6a22043602342002200341146a36023020040d010b200a450d0a200b102a0c0a0b200541016a210420032800102110200241e6006a41026a200241ed006a41026a2d000022113a0000200241e2006a41026a221220113a000020022001416b6a3602342002200341156a360230200220022f006d22013b0166200220013b016220032d0014210102402005200a470d00200c2004200c20044b1b220a41ffffff3f71200a470d09200a41057422034100480d090240024020050d0020031028210b0c010b200b20062003102c210b0b200b450d080b200b20066a2203411c6a20013a00002003200e3703082003200f370300200341146a200d370200200341106a20103602002003411d6a20022f01623b00002003411f6a20122d00003a0000200c41026a210c200641206a21062004210520092004470d000b0b200b450d072009ad422086200aad84210d02402008450d002007102a0b2000200d3702042000200b3602000c010b20004100360208200042083702000b200241f0006a24000f0b410e41011037000b1036000b200141081037000b200341081037000b1031000b41c4d1c3004133200241c0006a419cd9c3001038000bf00204027f017e017f077e0240024020012802042202450d0020012802002203310000210420012002417f6a22053602042001200341016a3602002005450d012003310001210620012002417e6a22053602042001200341026a3602002005450d012003310002210720012002417d6a22053602042001200341036a3602002005450d012003310003210820012002417c6a22053602042001200341046a3602002005450d012003310004210920012002417b6a22053602042001200341056a3602002005450d012003310005210a20012002417a6a22053602042001200341066a3602002005450d012003310006210b2001200241796a22053602042001200341076a3602002005450d01200041003a00002003310007210c2001200241786a3602042001200341086a3602002000200c423886200b42308684200a422886842009422086842008421886842007421086842006420886842004843700010f0b200041013a00000f0b200041013a00000bce1003077f027e027f230041d0006b220224000240024002400240024002400240024002400240024002400240410e10282203450d00200341002900fbe140370000200341066a4100290081e2403700002002428e808080e001370224200220033602202000200241206a108f012002280228210320022802202100200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020002003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b200128020021072001280208210320024100360238200242013703302003200241306a10b40102402003450d002003410574210841002106034002400240200228023420022802382203460d00200228023021000c010b200341016a22002003490d0f200341017422042000200420004b1b22044100480d0f0240024020030d002004102821000c010b200228023020032004102c21000b2000450d042002200436023420022000360230200228023821030b2002200341016a360238200020036a200720066a220341146a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d052002200536023420022004360230200228023821000b2002200041016a360238200420006a200341156a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d062002200536023420022004360230200228023821000b2002200041016a360238200420006a200341166a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d072002200536023420022004360230200228023821000b2002200041016a360238200420006a200341176a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d082002200536023420022004360230200228023821000b2002200041016a360238200420006a200341186a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d092002200536023420022004360230200228023821000b2002200041016a360238200420006a200341196a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d0a2002200536023420022004360230200228023821000b2002200041016a360238200420006a2003411a6a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d0b2002200536023420022004360230200228023821000b2002200041016a360238200420006a2003411b6a2d00003a0000200341086a29030021092003290300210a0240024020022802342205200228023822046b4110490d00200228023021000c010b200441106a22002004490d0f200541017422042000200420004b1b220b4100480d0f0240024020050d00200b102821000c010b20022802302005200b102c21000b2000450d0c2002200b3602342002200036023020022802382104200b21050b200020046a220b2009370008200b200a3700002002200441106a2204360238200341106a280200210b0240200520046b41034b0d00200441046a220c2004490d0f20054101742204200c2004200c4b1b22044100480d0f0240024020050d002004102821000c010b200020052004102c21000b2000450d0d2002200436023420022000360230200228023821040b2002200441046a360238200020046a200b36000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d0e2002200536023420022004360230200228023821000b2002200041016a360238200420006a2003411c6a2d00003a00002008200641206a2206470d000b0b2002280234210320024120200228023022002002280238100702402003450d002000102a0b0240200141046a280200450d002007102a0b200241d0006a24000f0b410e41011037000b200441011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200b41011037000b200441011037000b200541011037000b1031000bd00502067f047e230041d0006b220224000240024002400240411410282203450d00200341002900cfe140370000200341106a41002800dfe140360000200341086a41002900d7e14037000020024294808080c002370224200220033602202001200241206a108f012002280228210320022802202104200241306a41186a22054200370300200241306a41106a22064200370300200241306a41086a220742003703002002420037033020042003200241306a1000200241186a2005290300370300200241106a2006290300370300200241086a20072903003703002002200229033037030002402002280224450d002002280220102a0b2002410036023020024120200241306a100621030240024020022802302204417f470d0042002108420021090c010b20044110490d02200341086a2900002109200329000021082003102a0b411810282203450d02200341002900e3e140370000200341106a41002900f3e140370000200341086a41002900ebe140370000200242988080808003370224200220033602202001200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002410036023020024120200241306a100621030240024020022802302201417f470d004200210a4200210b0c010b20014110490d04200341086a290000210b2003290000210a2003102a0b2000200a20087c22083703002000200b20097c2008200a54ad7c370308200241d0006a24000f0b411441011037000b41c4d1c3004133200241306a419cd9c3001038000b411841011037000b41c4d1c3004133200241306a419cd9c3001038000bf00906017f037e017f017e017f037e230041c0016b220724004200210842002109024020050d00200741f0006a2006ad42004280c8afa0254200109f05200741f8006a2903002007290370220a4280a094a58d1d7c2208200a54ad7c21090b20074180016a41086a22054200370300200742003703800141bfa0c600411b20074180016a1008200741a0016a41086a220b200529030037030020072007290380013703a001200741e0006a200741a0016a109f02200728026021052007290368210a2007418094ebdc03360284012007200a420020051b220a200a423f87220c7c200c85220c200c428094ebdc037f220c4280ec94a37c7e7ca7220536028001200741d0006a417f2004418094ebdc032004418094ebdc03491b2204417f417f2004ad200ca7417f200c428080808010541bad7e220ca7200c422088a71b220620074180016a2005418094ebdc034b4102746a28020022052004418094ebdc036e220d6c2005ad2004200d4180ec94a37c6c6aad7e428094ebdc0380a76a6a220520052006491b22056a220620062004491b4100200420056b2205200520044b1b200a4200551bad420042e8074200109f0520074180016a2003427f200820072903507c220a20017c220c200c200a5422042009200741d0006a41086a2903007c200a200854ad7c220820027c2004ad7c220a200854200a2008511b22041b220e427f200a20041b220f4101109802024002402007280280014101470d0020004180023b0001200041013a0000200041036a41003a00000c010b200741206a2007290388012209420042044200109f05200741106a4200420020094200109f05200741306a2007290320200741206a41086a290300220820074180016a41106a290300220a42028620072903107c7c220c4205420010a00520072903182101200741306a41086a29030021022007290330211020074180016a10d301200741c0006a20074180016a42b3e6cc99b3e6cc99332010200a200a42ffffffffffffffff3f8352200142005272200c2008547222041b22082009200820095442b3e6cc99b3e6cc9933200220041b220c200a54200c200a511b22041b2208200c200a20041b220c10d001200741a0016a41106a200c200741c0006a41086a29030022027d20082007290340220154ad7d2002200c7d2001200854ad7d20012008582002200c582002200c5122041b22051b3703002007200820017d200120087d20051b3703a801200720012008562002200c5620041b2204ad3703a001200a200c7d2009200854ad7d210a200920087d21080240024020040d002007200b3602bc01200741bc016a109d010c010b2007200b3602bc01200741bc016a109c010b20074180016a10f801200720074180016a2008200a10d001200741b0016a200a200741086a29030022097d20082007290300220c54ad7d2009200a7d200c200854ad7d200c2008582009200a582009200a5122041b22051b37030020072008200c7d200c20087d20051b3703a8012007200c2008562009200a5620041b2204ad3703a001200741a0016a41086a21050240024020040d00200720053602bc01200741bc016a109d010c010b200720053602bc01200741bc016a109c010b200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a200e427f200f501b370300200041003a00000b200741c0016a24000b820102027f027e230041106b220224002002410036020420014110200241046a100621010240024020022802042203417f460d002001450d00024020034108490d00200129000021042001102a420121050c020b41c4d1c3004133200241086a419cd9c3001038000b420021050b2000200437030820002005370300200241106a24000b1300200041033602042000419ce2c0003602000bc70104017f017e027f017e230041206b2201240042002102200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a1006210302400240024020012802102204417f470d00420021050c010b20044110490d01200341086a2900002105200329000021022003102a0b2000200237030020002005370308200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000b3400200041b2f3c00036020420004100360200200041146a4105360200200041106a41bcf3c000360200200041086a42083702000b3701017f02404110102822020d00411041011037000b2002420037000820024200370000200042908080808002370204200020023602000b130020004105360204200041d884c1003602000be70302067f037e230041e0006b2204240020042001109d0202400240024002402004290300200441086a29030084500d00411410282205450d02200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370234200420053602302001200441306a108f012004280238210520042802302106200441c0006a41186a22074200370300200441c0006a41106a22084200370300200441c0006a41086a220942003703002004420037034020062005200441c0006a1000200441106a41186a2007290300370300200441106a41106a2008290300370300200441106a41086a20092903003703002004200429034037031002402004280234450d002004280230102a0b20044100360240200441106a4120200441c0006a100621050240024020042802402206417f470d004200210a4200210b0c010b20064110490d04200541086a290000210b2005290000210a2005102a0b2001200a20027c220c200b20037c200c200a54ad7c108f02200041106a2003370300200041086a2002370300410021010c010b200041b5dfc000360204200041086a4122360200410121010b20002001360200200441e0006a24000f0b411441011037000b41c4d1c3004133200441c0006a419cd9c3001038000b130020004101360204200041f88ac1003602000b3400200041b18cc10036020420004100360200200041146a4103360200200041106a41bc8cc100360200200041086a42083702000bef0a09037f017e067f037e017f027e077f017e017f230041306b2203240010980121042000280000210520003500042106200341106a2001109a02200328021021072003280214210802400240024002400240024002400240024020032802182209450d0020072009410574220a6a210b200341246a210c200721090340200941086a290300210d200941106a290300210e2009290300210f200341106a41186a200941186a290300370300200341106a41106a200e370300200341106a41086a200d3703002003200f370310200c2000460d02200c2900002000290000510d0202402003280220221020044d0d002003410e6a2003412f6a2d00003a0000200320032f002d3b010c200341186a290300210f427f210e200329031021114201210d20032d002c210c200329022421120c040b200941206a2109200a41606a220a0d000b0b41082113410021102008450d022007102a0c020b2003280220220c2002200c20024b1b211020032d002c410272210c427f21114200210e41002102200329022421124200210d41002105427f210f0b200341026a22142003410c6a41026a2d00003a0000200320032f010c3b010002400240412010282213450d00201320113703002013200c3a001c2013201237021420132010360210201320032f01003b001d2013200f3703082013411f6a20142d00003a000002400240200a4120470d0041012110200e210f410121140c010b200941206a2115200b41606a21162003412d6a2117200341246a210c200e210f4101211041012114034020152109024002400340200341106a41186a200941186a290300370300200341106a41106a200941106a290300370300200341106a41086a220a200941086a2903003703002003200929030037031002400240200c2000460d00200c2900002000290000510d002003280220221820044d0d012003410c6a41026a201741026a2d00003a0000200320172f00003b010c200a29030021112003290310211220032d002c21192003290224211a0c040b200d4201510d024200210e410021024200210f4200210d410021050b200b200941206a2209470d000c040b0b200a290300220d200f20032903102212200e56200d200f56200d200f511b220a1b21112012200e200a1b21122003280220220a2002200a20024b1b211820032d002c41027221194200210e410021022003290224211a4200210f4200210d410021050b200341046a41026a2003410c6a41026a2d0000220a3a0000200320032f010c22153b0104200341106a41026a221b200a3a0000200320153b0110024020142010470d00201041016a220a2010490d0a20104101742214200a2014200a4b1b221441ffffff3f712014470d0a2014410574220a4100480d0a0240024020100d00200a102821130c010b20132010410574200a102c21130b2013450d040b200941206a2115201320104105746a220a20193a001c200a2011370308200a2012370300200a201a370214200a2018360210200a20032f01103b001d200a411f6a201b2d00003a0000201041016a211020162009470d000b0b02402008450d002007102a0b200d4201520d0520102014470d040c030b412041081037000b200a41081037000b427f210e427f210f0b201041016a22092010490d03201041017422002009200020094b1b221441ffffff3f712014470d03201441057422094100480d030240024020100d002009102821130c010b201320104105742009102c21130b2013450d020b201320104105746a2209200f3703082009200e3703002009200536021420092002360210200941186a200642808080802084370300201041016a21100b2003201036021820032014360214200320133602102001200341106a109c02200341306a24000f0b200941081037000b1031000bef0a07037f027e047f087e017f047e027f230022062107200641c0006b41607122062400109801210820062003370310200620023703082006200436021842012109200642013703002006200028000036021c20003500042102200641206a2001109a0220022005ad42ff018342208684210a2006280220210b2006280224210c0240024002400240024020062802282205450d00200b200541057422046a210d200641346a210e2006290300220921032006290308220f2110200629031022112112200629031822132114200b21050340200541086a2903002102200541106a290300211520052903002116200641206a41186a200541186a290300370300200641206a41106a22172015370300200641206a41086a20023703002006201637032002400240200e2000460d00200e2900002000290000510d000240200628023020084b0d0020032102420021030c020b20172903002118200629032821192006290320211a2006290338211b20032102420121030c010b420021094200210f420021114200211342002102200a211b2010211a20122119201421180b20034201510d02200541206a210520022103200441606a22040d000b200620093703002006200f37030820062011370310200620133703180b41002104200c450d01200b102a0c010b200620023703002006201037030820062012370310200620143703180240412010282217450d002017201b3703182017201a37030020172019370308201741106a201837030002400240024020044120470d0041012104200221094101211c0c010b200541206a2105200641346a211d20022109410121044101211c034002400240201d2000460d00200221030340200641206a41186a200541186a290300370300200641206a41106a220e200541106a290300370300200641206a41086a200541086a2903003703002006200529030037032002400240201d2900002000290000510d000240200628023020084b0d0020032102420021030c020b200e290300211b20062903282116200629032021152006290338211a20032102420121030c010b42002109200642003703004200210220102115201221162014211b200a211a0b024020034201510d0020022103200d200541206a2205470d010c050b0b200541206a21050c010b024003402006420037030020024201510d0142002102200d200541206a2205470d000b420021090c030b200541206a2105420021094200210220102115201221162014211b200a211a0b0240201c2004470d00200441016a220e2004490d072004410174221c200e201c200e4b1b221c41ffffff3f71201c470d07201c410574220e4100480d070240024020040d00200e102821170c010b20172004410574200e102c21170b2017450d030b201720044105746a220e2016370308200e2015370300200e41106a201b370300200e41186a201a370300200441016a21042005200d470d000b0b200c450d03200b102a0c030b200e41081037000b412041081037000b4100211c410821170b0240024020094201520d00200641206a41106a22002006410872220541106a290300370300200641206a41086a220e200541086a2903003703002006200529030037032002402004201c470d00200441016a22052004490d03200441017422082005200820054b1b221c41ffffff3f71201c470d03201c41057422054100480d030240024020040d002005102821170c010b201720044105742005102c21170b2017450d020b201720044105746a22052006290320370300200541106a2000290300370300200541086a200e290300370300200541186a200a370300200441016a21040b200620043602282006201c360224200620173602202001200641206a109c02200724000f0b200541081037000b1031000bff0502067f057e230041d0006b220324000240024002400240411810282204450d00200441002900e3e140370000200441106a41002900f3e140370000200441086a41002900ebe140370000200342988080808003370224200320043602202000200341206a108f012003280228210420032802202105200341306a41186a22064200370300200341306a41106a22074200370300200341306a41086a220842003703002003420037033020052004200341306a1000200341186a2006290300370300200341106a2007290300370300200341086a20082903003703002003200329033037030002402003280224450d002003280220102a0b2003410036023020034120200341306a100621040240024020032802302205417f470d00420021094200210a0c010b20054110490d02200441086a290000210a200429000021092004102a0b411410282204450d02200441002900cfe140370000200441106a41002800dfe140360000200441086a41002900d7e14037000020034294808080c002370224200320043602202000200341206a108f012003280228210420032802202105200341306a41186a22064200370300200341306a41106a22074200370300200341306a41086a220842003703002003420037033020052004200341306a1000200341186a2006290300370300200341106a2007290300370300200341086a20082903003703002003200329033037030002402003280224450d002003280220102a0b2003410036023020034120200341306a100621040240024020032802302205417f470d004200210b4200210c0c010b20054110490d04200441086a290000210c2004290000210b2004102a0b2000200b200120092009200156200a200256200a2002511b22041b22017c220d200c2002200a20041b22027c200d200b54ad7c108f022000200920017d200a20027d2009200154ad7d109002200341d0006a24000f0b411841011037000b41c4d1c3004133200341306a419cd9c3001038000b411441011037000b41c4d1c3004133200341306a419cd9c3001038000bc70301047f230041106b2203240020034100360208200342013703002001200310b40102400240024002402001450d00200141216c210403400240024020002d00004101460d0002400240200328020420032802082201460d00200328020021050c010b200141016a22052001490d07200141017422062005200620054b1b22064100480d070240024020010d002006102821050c010b200328020020012006102c21050b2005450d052003200636020420032005360200200328020821010b2003200141016a360208200520016a41003a00000c010b02400240200328020420032802082201460d00200328020021050c010b200141016a22052001490d06200141017422062005200620054b1b22064100480d060240024020010d002006102821050c010b200328020020012006102c21050b2005450d052003200636020420032005360200200328020821010b2003200141016a360208200520016a41013a0000200041016a2003108f010b200041216a21002004415f6a22040d000b0b2003280204210020022802002002280204200328020022012003280208100702402000450d002001102a0b200341106a24000f0b200641011037000b200641011037000b1031000bdb0401057f230041106b2203240020034100360208200342013703002002200310b401024002400240024002402002450d0020024190016c2104034020032802042105200328020821020240024020012802004113470d000240024020052002460d00200328020021050c010b200241016a22052002490d08200241017422062005200620054b1b22064100480d080240024020020d002006102821050c010b200328020020022006102c21050b2005450d052003200636020420032005360200200328020821020b2003200241016a360208200520026a41003a00000c010b0240024020052002460d00200328020021050c010b200241016a22052002490d07200241017422062005200620054b1b22064100480d070240024020020d002006102821050c010b200328020020022006102c21050b2005450d052003200636020420032005360200200328020821020b2003200241016a360208200520026a41013a00002001200310eb0120014188016a28020021060240024020032802042205200328020822026b4104490d00200328020021050c010b200241046a22072002490d07200541017422022007200220074b1b22024100480d070240024020050d002002102821050c010b200328020020052002102c21050b2005450d062003200236020420032005360200200328020821020b2003200241046a360208200520026a20063600000b20014190016a2101200441f07e6a22040d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b200641011037000b200641011037000b200241011037000b1031000b6801037f024041094101200128020022024101461b220310282204450d000240024020020d00200441003a0000410121010c010b200441013a000020042001290204370001410921010b2000200136020820002003360204200020043602000f0b200341011037000bcc0902057f027e230041c0006b22022400024002400240024002402001280200417f6a220341024b0d0020030e03010203010b41a091c1001032000b410121030240024020012d00044101460d00200241026a200141046a220341036a2d00003a0000200241206a41086a200141146a290200370300200241306a2001411c6a290200370300200241386a200141246a2d00003a0000200220032f00013b010020022001410c6a290200370320200141086a2802002104410021030c010b200141086a28020021040b200020033a0004200020022f01003b000520004101360200200041286a2001290328370300200041086a20043602002000410c6a2002290320370200200041306a200141306a290300370300200041076a200241026a2d00003a0000200041146a200241206a41086a2903003702002000411c6a200241306a290300370200200041246a200241386a2802003602000c020b410121030240024020012d00044101460d00200241026a200141046a220341036a2d00003a0000200241206a41086a200141146a290200370300200241306a2001411c6a290200370300200241386a200141246a2d00003a0000200220032f00013b010020022001410c6a290200370320200141086a2802002104410021030c010b200141086a28020021040b200020033a0004200020022f01003b0005200041286a2001290328370300200041386a2001290338370300200041086a20043602002000410c6a2002290320370200200041306a200141306a290300370300200041c0006a200141c0006a290300370300200041076a200241026a2d00003a0000200041146a200241206a41086a2903003702002000411c6a200241306a290300370200200041246a200241386a280200360200200041023602000c010b200141286a2103410121040240024020012d00044101460d002002411e6a200141046a220441036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220042f00013b011c20022001410c6a290200370300200141086a2802002105410021040c010b200141086a28020021050b410121060240024020032d00004101460d002002413e6a200341036a2d00003a0000200241286a200141386a290200370300200241306a200141c0006a290200370300200241386a200141c8006a2d00003a0000200220032f00013b013c2002200141306a2902003703202001412c6a2802002103410021060c010b2001412c6a28020021030b200020043a0004200020022f011c3b0005200020022f013c3b0029200041086a20053602002000410c6a2002290300370200200041286a20063a0000200041076a2002411c6a41026a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602002000412b6a2002413c6a41026a2d00003a0000200141d8006a2903002107200129035021082000412c6a2003360200200041d0006a2008370300200041d8006a200737030020004103360200200041306a2002290320370200200041386a200241206a41086a290300370200200041c0006a200241206a41106a290300370200200041c8006a200241206a41186a2802003602000b200241c0006a24000b960403077f017e067f02400240024002402001410c6a2802002202417f4c0d0020012802042103200128020021040240024020020d0041012105410021060c010b20022106200210282205450d020b200520032002109a052107200141186a2802002208ad420c7e2209422088a70d002009a72203417f4c0d002001280210210a0240024020030d004104210b0c010b20031028220b450d030b0240024020080d004100210c0c010b200a2008410c6c6a210d4100210c200b21050340200a41086a2802002203417f4c0d02200a280200210e0240024020030d004101210f0c010b20031028220f450d060b200f200e2003109a05210e200541086a2003360200200541046a20033602002005200e3602002005410c6a2105200c41016a210c200a410c6a220a200d470d000b0b20002007360204200020043602002000200129021c37021c200041186a200c360200200041146a2008360200200041106a200b3602002000410c6a2002360200200041086a2006360200200020012902243702242000412c6a2001412c6a290200370200200041346a200141346a2902003702002000413c6a2001413c6a290200370200200041c4006a200141c4006a290200370200200041cc006a200141cc006a290200370200200041d4006a200141d4006a290200370200200041dc006a200141dc006a2902003702000f0b1036000b200241011037000b200341041037000b200341011037000bd90303027f017e027f02402001450d00034020002802e40121002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d0020002001410c6c6a220441e4006a2902002105200441e0006a2802002104200141016a21010c010b02400240200028020022010d002003ad210541002106410021010c010b20003301044220862003ad842105410121060b2000102a2005a72103024002402005422088a7220720012f01064f0d00200121040c010b034002400240200128020022040d002003ad2105410021040c010b200641016a210620013301044220862003ad8421050b2001102a2005a72103200421012005422088a7220720042f01064f0d000b0b200741027420046a41e8016a280200210020042007410c6c6a220141e4006a2902002105200141e0006a280200210402402006417f6a2201450d00034020002802e40121002001417f6a22010d000b0b410021010b2004450d012002417f6a210202402005a7450d002004102a0b20020d000b0b0240200041f8b9c000460d00200028020021012000102a2001450d00200128020021042001102a2004450d00024020042802002201450d0003402004102a2001210420012802002200210120000d000b0b2004102a0b0bd308030d7f017e017f230041a0016b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2205200128020422062f01064f0d01200241186a2207200620054105746a220341206a290000370300200241106a2208200341186a290000370300200241086a2209200341106a2900003703002002200341086a290000370300200241206a41286a220a2006200541306c6a22034190036a290300370300200241206a41206a220b20034188036a290300370300200241206a41186a220c20034180036a290300370300200241206a41106a220d200341f8026a290300370300200241206a41086a220e200341f0026a290300370300200341e8026a290300210f2001200541016a36020c20012004360208200120063602042002200f370320200241d0006a41186a2007290300370300200241d0006a41106a2008290300370300200241d0006a41086a200929030037030020022002290300370350200241d0006a41286a200e290300370300200241d0006a41306a200d29030037030020024188016a200c29030037030020024190016a200b29030037030020024198016a200a290300370300200220022903203703702000200241d0006a41d000109a051a0c020b200041003602400c010b2001280200210702400240200628020022030d002004ad210f410021030c010b200741016a210720063301044220862004ad84210f0b2006102a200fa7210502400240200f422088a7220420032f01064f0d00200321060c010b034002400240200328020022060d002005ad210f410021060c010b200741016a210720033301044220862005ad84210f0b2003102a200fa7210520062103200f422088a7220420062f01064f0d000b0b200241186a2208200620044105746a220341206a290000370300200241106a2209200341186a290000370300200241086a220a200341106a2900003703002002200341086a290000370300200241206a41286a220b2006200441306c6a22034190036a290300370300200241206a41206a220c20034188036a290300370300200241206a41186a220d20034180036a290300370300200241206a41106a220e200341f8026a290300370300200241206a41086a2210200341f0026a2903003703002002200341e8026a290300370320200441027420066a41fc066a280200210302402007417f6a2206450d00034020032802f80621032006417f6a22060d000b0b2001410036020c200120053602082001200336020420014100360200200241d0006a41186a2008290300370300200241d0006a41106a2009290300370300200241d0006a41086a200a290300370300200241d0006a41286a2010290300370300200241d0006a41306a200e29030037030020024188016a200d29030037030020024190016a200c29030037030020024198016a200b29030037030020022002290300370350200220022903203703702000200241d0006a41d000109a051a0b200241a0016a24000bbd0301057f230041106b2203240002400240024002400240200141046a2204417f4c0d000240024020040d00410121050c010b200410282205450d020b2003410036020820032004360204200320053602002001200310b4010240024020032802042206200328020822056b2001490d00200328020021040c010b200520016a22042005490d05200641017422072004200720044b1b22074100480d050240024020060d002007102821040c010b200328020020062007102c21040b2004450d032003200736020420032004360200200721060b200420056a20002001109a051a02400240200241046a2802002207200241086a28020022006b200520016a2201490d00200228020021050c010b200020016a22052000490d05200741017422002005200020054b1b22004100480d050240024020070d002000102821050c010b200228020020072000102c21050b2005450d0420022005360200200241046a2000360200200241086a28020021000b200241086a200020016a360200200520006a20042001109a051a02402006450d002004102a0b200341106a24000f0b1036000b200441011037000b200741011037000b200041011037000b1031000b880201057f230041d0006b220224000240411710282203450d00200341002900f1d8433700002003410f6a4100290080d943370000200341086a41002900f9d84337000020024297808080f002370224200220033602202000200241206a108f012002280228210320022802202100200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020002003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002200110e203200241d0006a24000f0b411741011037000b1000200028020020002802042001105f0baf0201037f23004180016b2202240002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001103f21000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000b130020004101360204200041cc9ac1003602000b130020004102360204200041849cc1003602000b3101017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241e8073600000b3101017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241e5003600000bd20903067f017e057f230041f0016b22022400024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002005417f6a220541014b0d0520050e020102010b200041023a00000c050b20064104490d012004280001210720012003417b6a22053602042001200441056a36020020054108490d02200429000521082001200341736a36020420012004410d6a36020041002105200241003a00b001410d20036b2109200341726a210603400240200920056a0d000240200541ff0171450d00200241003a00b0010b200041023a00000c060b20024190016a20056a200420056a220a410d6a2d00003a0000200120063602042001200a410e6a3602002002200541016a220a3a00b0012006417f6a2106200a2105200a4120470d000b200241f0006a41186a20024190016a41186a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41086a20024190016a41086a290300370300200220022903900137037041002105200241003a00d0012004200a6a2109200a20036b410d6a210a03400240200a20056a0d000240200541ff0171450d00200241003a00d0010b200041023a00000c060b20024190016a20056a200920056a2204410d6a2d00003a00002001200636020420012004410e6a3602002002200541016a22043a00d0012006417f6a210620042105200441c000470d000b200241106a41386a220120024190016a41386a290300370300200241106a41306a220520024190016a41306a290300370300200241106a41286a220620024190016a41286a290300370300200241106a41206a220420024190016a41206a290300370300200241106a41186a220a20024190016a41186a290300370300200241106a41106a220320024190016a41106a290300370300200241106a41086a220920024190016a41086a290300370300200241d0006a41086a220b200241f0006a41086a290300370300200241d0006a41106a220c200241f0006a41106a290300370300200241d0006a41186a220d200241f0006a41186a290300370300200220022903900137031020022002290370370350200041003a000020002002290350370001200041096a200b290300370000200041116a200c290300370000200041196a200d290300370000200041216a2002290310370000200041296a2009290300370000200041316a2003290300370000200041396a200a290300370000200041c1006a2004290300370000200041c9006a2006290300370000200041d1006a2005290300370000200041d9006a2001290300370000200041e3006a2002410f6a2d00003a0000200041e1006a20022f000d3b0000200041e8006a2008370300200041e4006a20073602000c040b0240024020064104490d002004280001210620012003417b6a22053602042001200441056a360200200541084f0d010b200041023a00000c040b200041013a0000200020022f00103b0001200429000521082001200341736a36020420012004410d6a360200200041086a2008370300200041046a2006360200200041036a200241126a2d00003a0000200041106a20024190016a41e000109a051a0c030b200041023a00000c020b200041023a00000c010b200041023a00000b200241f0016a24000be71207027f017e057f027e017f017e0a7f230041b0036b2202240020002802102203200328020041016a36020020002902142104200028020c2103200028020821052000280200210620002802042100200241f0016a41086a2207200141086a280200360200200220012902003703f001024002400240024020002f01062201410b490d00200241d0026a410272410041da001099051a200241386a41004184011099051a0240024041e40110282208450d0020084100360200200841046a200241d0026a41dc00109a051a200841e0006a200241386a418401109a052107200241386a41086a2209200041b0016a280200360200200220002902a8013703382000413c6a330000210a2000413e6a310000210b20002d003f210c2000350038210d200841086a200041c0006a20002f010641796a2201410374109a05210e2007200041b4016a2001410c6c109a052107200041063b0106200820013b0106200241d0026a41086a2009280200360200200220022903383703d002200d200a200b4210868442208684210a0240024020034107490d002003410374200e6a41506a200e200341796a22094103746a220e200141ffff037120096b410374109b051a200e20043700002003410c6c20076a220341b87f6a200341ac7f6a2203200841066a22012f010020096b410c6c109b051a200341086a200241f0016a41086a280200360200200320022903f0013702000c010b200041086a20034103746a220741086a2007200041066a22012f010020036b410374109b051a20072004370000200041e0006a2003410c6c6a2207410c6a200720012f010020036b410c6c109b051a200741086a200241f0016a41086a280200360200200720022903f0013702000b200120012f010041016a3b0100200241286a41086a220f200241d0026a41086a22102802002203360200200241086a221120033602002002200c3a0017200220022903d00222043703282002200a3e02102002200a4230883c00162002200a4220883d011420022004370300200229031021042000280200220c450d0320002f01042112200241d0026a410272211303402002200641016a22063602202002200c360224200f201128020036020020022002290300370328201241ffff03712109024002400240200c2f01062200410b490d002013410041da001099051a200241f0016a200241d0026a41dc00109a051a200241386a410041b4011099051a41940210282207450d0520074100360200200741046a200241f0016a41dc00109a051a200741e0006a200241386a41b401109a052103200c41386a290000210a200241386a41086a2214200c41b0016a2802003602002002200c41a8016a290200370338200741086a200c41c0006a200c2f0106220141796a2200410374109a0521152003200c41b4016a2000410c6c109a052116200741e4016a200c4180026a2001417a6a220e410274109a052117200c41063b0106200720003b01060240200e450d00410021002017210303402003280200220120003b010420012007360200200341046a2103200e200041016a2200470d000b0b20102014280200220036020020022002290338220b3703d002201420003602002002200b370338201241ffff037122034107490d0120152009417a6a22034103746a2015200941796a22004103746a220120072f010620006b410374109b051a200120043700002009410c6c20166a220141b87f6a200141ac7f6a220120072f0106220e20006b410c6c109b051a200141086a200f280200360200200120022903283702002007200e41016a22013b01062009410274221220176a416c6a201720034102746a220e200141ffff0371220920036b410274109b051a200e200836020020092003490d02200720126a41cc016a2103034020032802002201200041016a22003b010420012007360200200341046a210320002009490d000c030b0b200c41086a2201200941016a22034103746a200120094103746a2201200020096b2207410374109b051a20012004370000200c2009410c6c6a220141ec006a200141e0006a220e2007410c6c109b051a200141e8006a200241286a41086a280200360200200e2002290328370200200c200041016a22003b01062009410274200c41e4016a22016a41086a200120034102746a2201200041ffff0371220720036b410274109b051a20012008360200201241ffff037120074f0d07200c2003417f6a22004102746a41e8016a2103034020032802002201200041016a22003b01042001200c360200200341046a210320002007490d000c080b0b200c41086a2200200941016a220e4103746a200020094103746a2200200c2f0106220120096b2212410374109b051a20002004370000200c41e0006a2009410c6c6a2200410c6a20002012410c6c109b051a200041086a200f28020036020020002002290328370200200c200141016a22003b010620094102742217200c41e4016a22016a41086a2001200e4102746a2212200041ffff03712201200e6b410274109b051a20122008360200200320014f0d00200c20176a41e8016a2100034020002802002203200941016a22093b01042003200c360200200041046a210020012009470d000b0b200241106a41086a2014280200220036020020112000360200200220022903382204370310200220043703000240200c28020022000d0020072108200a21040c050b200c2f010421122000210c200a2104200721080c000b0b41e40141041037000b41940241041037000b200020034103746a220941106a200941086a2209200120036b410374109b051a2009200437000020002003410c6c6a220141ec006a200141e0006a220920002f010620036b410c6c109b051a200141e8006a2007280200360200200920022903f001370200200020002f010641016a3b01060c010b200241d0026a410272410041da001099051a200241f0016a200241d0026a41dc00109a051a200241386a410041b4011099051a41940210282200450d0120004100360200200041046a200241f0016a41dc00109a051a200041e0006a200241386a41b401109a0521012000200528020022033602e401200520003602002005200528020441016a360204200341003b010420032000360200200120002f01062203410c6c6a22012002290300370200200020034103746a41086a2004370000200141086a200241086a280200360200200041e4016a200341016a22034102746a2008360200200020033b0106200820033b0104200820003602000b200241b0036a24000f0b41940241041037000b8b0303017f017e027f02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d00410021034100210103402002417f6a210202400240200120002f01064f0d00200141016a21010c010b02400240200028020022010d002003ad210441002105410021010c010b20003301044220862003ad842104410121050b2000102a2004a72103024002402004422088a7220620012f01064f0d00200121000c010b034002400240200128020022000d002003ad2104410021000c010b200541016a210520013301044220862003ad8421040b2001102a2004a72103200021012004422088a7220620002f01064f0d000b0b200641027420006a4198036a280200210002402005417f6a2201450d00034020002802940321002001417f6a22010d000b0b410021010b20020d000b0b0240200041f8b9c000460d00200028020021012000102a2001450d00200128020021002001102a2000450d00024020002802002201450d0003402000102a2001210020012802002203210120030d000b0b2000102a0b0be480010d067f017e017f027e0b7f017e027f017e017f017e067f017e127f230041e0026b22012400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020004180c20370450d00200141e8006a21020c010b20014190026a41086a22034200370300200142003703900241f490c600411420014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a001200141e8006a4110200141a0016a100621030240024020012802a0012204417f460d0020030d010b200141e8006a21020c010b024002400240024002400240024020044104490d00200328000021042003102a200141e8006a21022004450d0720014190026a41086a22034200370300200142003703900241a9a2c100410f20014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a001200141e8006a4110200141a0016a100621030240024020012802a0012205417f460d002003450d0020012005360294022001200336029002200141a0016a20014190026a107d20012802a0012206450d0320012902a40121072005450d012003102a0c010b41042106420021070b20014190026a41086a22034200370300200142003703900241b8a2c100411420014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141a0016a200141e8006a10be020240024020012802a8012208450d002007422088a720012902ac012209422088a76b20012903a001220a422088a7220b6a2105200aa721032009a7450d012008102a0c010b2007422088a721054100210b10980121030b200520044f0d020c030b41c4d1c3004133200141d8026a419cd9c3001038000b41c4d1c3004133200141d8026a419cd9c3001038000b0240200b20044f0d00200b20046b22032007422088a722056a220420034f0d032006200441246c6a28022021030c010b20014190026a41086a22044200370300200142003703900241dca2c100411420014190026a1008200141e8006a41086a2004290300370300200120012903900237036841002105200141003602a001200141e8006a4110200141a0016a10062104024020012802a001220b417f460d002004450d00200b4104490d02200428000021052004102a0b200520036a21030b200341ffc1036a220320034180c203706b210302402007a7450d002006102a0b20032000470d0320014190026a41086a22034200370300200142003703900241a9a2c100410f20014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a001200141e8006a4110200141a0016a1006210302400240024020012802a0012204417f460d002003450d0020012004360294022001200336029002200141a0016a20014190026a107d20012802a001220c450d0220012902a401210a2004450d012003102a0c010b4104210c4200210a0b20014190026a41086a22034200370300200142003703900241f490c600411420014190026a1008200141e8006a41086a200329030037030020012001290390023703684100210d200141003602a001200141e8006a4110200141a0016a100621030240024020012802a0012204417f460d002003450d0020044104490d012003280000210d2003102a0b109801210e02400240200a422088a7220f41246c2204450d00200c41206a280200200e4d0d010b4101210b41002105410021060c050b200141a0016a41186a2203200c41186a290200370300200141a0016a41106a2205200c41106a290200370300200141a0016a41086a2206200c41086a2902003703002001200c2902003703a001024041201028220b450d00200b20012903a001370000200b41186a2003290300370000200b41106a2005290300370000200b41086a20062903003700000240200c41246a2203200c20046a470d0041012105410121060c060b200c200f41246c6a211041202108410121044101210503400240200341206a280200200e4d0d00200421060c070b200141b8026a41186a2211200341186a290200370300200141b8026a41106a2212200341106a290200370300200141b8026a41086a2213200341086a290200370300200120032902003703b8020240024020052004460d00200421060c010b200441016a22062004490d1e200441017422142006201420064b1b220641ffffff3f712006470d1e200641057422144100480d1e0240024020040d0020141028210b0c010b200b20044105742014102c210b0b200b0d00201441011037000b200b20086a220420012903b802370000200441186a2011290300370000200441106a2012290300370000200441086a2013290300370000200841206a2108200541016a2105200621042010200341246a2203460d060c000b0b412041011037000b41c4d1c3004133200141d8026a419cd9c3001038000b41c4d1c3004133200141d8026a419cd9c3001038000b41c4d1c3004133200141d8026a419cd9c3001038000b41cca2c100200420051034000b024002400240024002400240024002400240200d200f20056b22044d0d0020014190026a41086a22034200370300200142003703900241f0a2c100411c20014190026a1008200141e8006a41086a2003290300370300200120012903900237036841002108200141003602a001200141e8006a4110200141a0016a10062103024020012802a0012211417f460d002003450d0020114104490d02200328000021082003102a0b20014190026a41086a22034200370300200142003703900241b8a2c100411420014190026a1008200141e8006a41086a20032903003703002001200129039002370368410810282203450d0220014288808080c0003702a401200120033602a00120032008200e6a3600000240024020012802a401220820012802a80122036b4104490d0020012802a00121080c010b200341046a22112003490d20200841017422032011200320114b1b22034100480d200240024020080d002003102821080c010b20012802a00120082003102c21080b2008450d04200120033602a401200120083602a00120012802a80121030b2001200341046a3602a801200820036a200d20046b22133600002005200141a0016a10b40102402005450d0020054105742104200b210303402003200141a0016a108f01200341206a2103200441606a22040d000b0b20012802a4012103200141e8006a411020012802a001220420012802a801100702402003450d002004102a0b02402006450d00200b102a0b200141a8026a4200370300200141a0026a420037030020014198026a42003703002001420037039002201341066a220ead42307e2207422088a70d172007a72203417f4c0d170240024020030d0041082110410821040c010b200310282210450d05201021040b200141a0016a41186a221120014190026a41186a290300370300200141a0016a41106a221220014190026a41106a290300370300200141a0016a41086a20014190026a41086a29030037030020012001290390023703a001200e4102490d05200d20056a200f6b41056a2105200421030340200141b8026a41186a22062011290300370300200141b8026a41106a220b2012290300370300200141b8026a41086a2208200141a0016a41086a290300370300200120012903a0013703b8022003420037030820034200370300200341106a20012903b802370300200341186a2008290300370300200341206a200b290300370300200341286a2006290300370300200341306a21032005417f6a22050d000b201341056a21050c060b2006450d07200b102a0c070b41c4d1c3004133200141d8026a419cd9c3001038000b410841011037000b200341011037000b200341081037000b4100210520042103200e450d010b2003420037030820034200370300200320012903a001370310200341186a200141a8016a290300370300200341206a200141b0016a290300370300200341286a200141a0016a41186a290300370300200541016a21050b20014190026a41086a220342003703002001420037039002418ca3c100411320014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a801200142013703a0012005200141a0016a10b40102402005450d002004200541306c6a210b0340200441086a2903002107200429030021090240024020012802a401220520012802a80122036b4110490d0020012802a00121050c010b200341106a22062003490d1a200541017422032006200320064b1b22034100480d1a0240024020050d002003102821050c010b20012802a00120052003102c21050b2005450d05200120033602a401200120053602a00120012802a80121030b200520036a22052007370008200520093700002001200341106a3602a801200441106a200141a0016a108f01200441306a2204200b470d000b0b20012802a4012103200141e8006a411020012802a001220420012802a801100702402003450d002004102a0b0240200e450d002010102a0b200141083a00a001200141a0016a41086a2013360200200141023a00a40141014100200141a0016a10cc010b200aa7450d00200c102a0b20014190026a41086a22034200370300200142003703900241b8a2c100411420014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141a0016a200210be0220012802a8012215450d1820012902ac01211620012802a0012000470d1720014190026a41086a22034200370300200142003703900241b8a2c100411420014190026a1008200141e8006a41086a220020032903003703002001200129039002370368200141a0016a200210be02024020012802a80122170d0002402016a7450d002015102a0b41d5a3c100410f100b41e4a3c1004135100b0c190b20024110100920012802a401211820012902ac012119200342003703002001420037039002418ca3c100411320014190026a1008200020032903003703002001200129039002370368200141003602a00120024110200141a0016a100621030240024020012802a0012200417f460d002003450d0020012000360294022001200336029002200141a0016a20014190026a107820012802a001221a450d0320012902a401211b02402000450d002003102a0b2002411010090c010b4200211b4108211a0b109801211c20014190026a41086a22034200370300200142003703900241dca2c100411420014190026a1008200141e8006a41086a200329030037030020012001290390023703684100211d200141003602a00120024110200141a0016a10062103024020012802a0012200417f460d002003450d0020004104490d032003280000211d2003102a0b201a201b422088a7221e41306c6a210e0240024020180d004100211341002106410021000c010b2018417f6a2106410021000240201e450d000240201a201e41306c6a220341506a220e290300200e41086a2903008450450d00410121130c020b20014190026a41186a200341606a220341186a29000037030020014190026a41106a200341106a29000037030020014190026a41086a200341086a2900003703002001200329000037039002410121000b410021130b200141a9016a20014190026a41086a290300370000200141b1016a20014190026a41106a290300370000200141b9016a20014190026a41186a290300370000200120003a00a00120012001290390023700a101200141a0016a41017221032000450d0a20034280809aa6eaafe301420010aa02200141e8006a41086a200341086a290000370300200141e8006a41106a200341106a290000370300200141e8006a41186a200341186a2900003703002001200329000037036820012d00a0014101470d0b41201028221f450d03201f2001290368370000201f41186a200141e8006a41186a290300370000201f41106a200141e8006a41106a290300370000201f41086a200141e8006a41086a290300370000200141a0016a4101722103410221054120210441012120410121210340024002400240024020060d00410021060c010b2006417f6a2106201341ff01710d000240201a200e470d00410021130c010b200e41506a220b290300200b41086a290300844200520d0141012113200b210e0b200320012903b802370000200341086a200141b8026a41086a290300370000200341106a200141b8026a41106a290300370000200341186a200141b8026a41186a29030037000041002100200141003a00a0010c010b200141b8026a41186a200e41606a220041186a2900002207370300200141b8026a41106a200041106a2900002209370300200141b8026a41086a200041086a290000220a3703002001200029000022223703b80220032022370000200341086a200a370000200341106a2009370000200341186a2007370000200141013a00a00120034280809aa6eaafe301420010aa024100211320012d00a0012100200b210e0b20014190026a41186a220b200341186a29000037030020014190026a41106a2208200341106a29000037030020014190026a41086a2211200341086a29000037030020012003290000370390020240200041ff0171450d00200141a0016a41186a2212200b290300370300200141a0016a41106a220b2008290300370300200141a0016a41086a2208201129030037030020012001290390023703a001024020202021470d00202041016a22002020490d1820052000200520004b1b222141ffffff3f712021470d18202141057422004100480d180240024020200d0020001028211f0c010b201f20042000102c211f0b201f450d0c0b201f20046a220020012903a001370000200041186a2012290300370000200041106a200b290300370000200041086a2008290300370000200541026a2105200441206a2104202041016a21200c010b0b201f20046a21232020450d0c200141a0016a41086a2104201f210f0340200141306a200f10bf02024020012802304101470d002001280238210520014190016a10c002200128029001212402402001280298012203450d00200341216c2100202441016a21032005410876210841012005411f7174212520054105764107712211417f732126034002402003417f6a2d00004101470d00200141a0016a41186a200341186a290000370300200141a0016a41106a200341106a2900003703002004200341086a290000370300200120032900003703a001200120083602c00120014190026a200141a0016a10c1020240201120012802980222054f0d00200520266a220620054f0d0a200128029002220b20064102746a28020020257121050240200128029402450d00200b102a0b2005450d01411310282205450d0b200541002900c2a34122073700002005410f6a41002800d1a341220c360000200541086a41002900caa341220937000020014293808080b0023702a401200120053602a0012003200141a0016a108f0120012802a801211220012802a0012113200141b8026a41186a22054200370300200141b8026a41106a22064200370300200141b8026a41086a220b4200370300200142003703b80220132012200141b8026a1000200141106a41186a22102005290300370300200141106a41106a220d2006290300370300200141106a41086a2214200b290300370300200120012903b802370310024020012802a401450d0020012802a001102a0b200141003602a001200141106a4120200141a0016a1006210e024020012802a0012213417f460d00200120133602bc022001200e3602b802200141a0016a200141b8026a10c20220012903a0014201510d0d20014190026a41206a2227200441206a222828020036020020014190026a41186a2229200441186a222a29030037030020014190026a41106a222b200441106a222c29030037030020014190026a41086a2212200441086a222d290300370300200120042903003703900220012802cc01212e02402013450d00200e102a0b200141e8006a41206a20272802002213360200200141c0006a41086a220e2012290300370300200141c0006a41106a2227202b290300370300200141c0006a41186a222b2029290300370300200141c0006a41206a222920133602002001200129039002370340201242003703002001420037039002418891c600411120014190026a1008200141e8006a41086a20122903003703002001200129039002370368200141003602a00120024110200141a0016a1006211202400240024020012802a0012213417f470d00410021130c010b20134104490d01201228000021132012102a0b20042001290340370300202d200e290300370300202c2027290300370300202a202b29030037030020282029280200360200200142013703a0012001201341016a3602cc01411310282212450d10201220073700002012410f6a200c360000201241086a200937000020014293808080b002370294022001201236029002200320014190026a108f01200128029802211220012802900221132005420037030020064200370300200b4200370300200142003703b80220132012200141b8026a100020102005290300370300200d20062903003703002014200b290300370300200120012903b8023703100240200128029402450d00200128029002102a0b20014120360294022001200141106a36029002200420014190026a10c3020c030b41c4d1c3004133200141d8026a419cd9c3001038000b20042001290340370300200441086a200141c0006a41086a290300370300200441106a200141c0006a41106a290300370300200441186a200141c0006a41186a290300370300200441206a200141c0006a41206a280200360200200142003703a0012001202e3602cc01411310282212450d0d201220073700002012410f6a200c360000201241086a200937000020014293808080b002370294022001201236029002200320014190026a108f01200128029802211220012802900221132005420037030020064200370300200b4200370300200142003703b80220132012200141b8026a100020102005290300370300200d20062903003703002014200b290300370300200120012903b8023703100240200128029402450d00200128029002102a0b200141106a412010090c010b200128029402450d00200128029002102a0b200341216a21032000415f6a22000d000b0b200128029401450d002024102a0b2023200f41206a220f470d000c0d0b0b200341011037000b41c4d1c3004133200141d8026a419cd9c3001038000b41c4d1c3004133200141d8026a419cd9c3001038000b412041011037000b41cca2c100200620051034000b411341011037000b41c4d1c3004133200141d8026a419cd9c3001038000b411341011037000b411341011037000b200041011037000b200141e8006a41186a200341186a290000370300200141e8006a41106a200341106a290000370300200141e8006a41086a200341086a290000370300200120032900003703680b41002121410121234101211f410021200b20014190026a41086a22034200370300200142003703900241a9a2c100410f20014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a00120024110200141a0016a10062103024002400240024002400240024020012802a0012200417f460d002003450d0020012000360294022001200336029002200141a0016a20014190026a107d20012802a0012225450d0220012902a40121072000450d012003102a0c010b42002107410421250b20252007422088a7220841246c6a210d02402019422088a722050d004100212f41012130410021310c050b410021314100212f4101213002402005200d20256b41246e2203200320054b1b2203450d00200341057422004100480d0e200010282230450d022003212f0b20252103200521042030210003400240200d20036b41ec004b0d00200d2003460d062025200841246c6a21114101210b0240034020002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a2900003700002004200b2206460d01200641016a210b200041206a21002011200341246a2203470d000b0b203120066a21310c060b20002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000024020044101470d00203141017221310c060b20002003290024370020200041386a2003413c6a290000370000200041306a200341346a290000370000200041286a2003412c6a29000037000020044102460d0420002003290048370040200041d8006a200341e0006a290000370000200041d0006a200341d8006a290000370000200041c8006a200341d0006a29000037000020044103460d032000200329006c370060200041f8006a20034184016a290000370000200041f0006a200341fc006a290000370000200041e8006a200341f4006a290000370000203141046a213120004180016a210020034190016a21032004417c6a22040d000c050b0b41c4d1c3004133200141d8026a419cd9c3001038000b200041011037000b203141037221310c010b203141027221310b201d201c6a21262007a721270240024002400240024002402005450d00202521032008450d03200541016a2100200841246c2104202521030340200141b8026a41186a200341186a290200370300200141b8026a41106a200341106a290200370300200141b8026a41086a200341086a290200370300200120032902003703b8022000417f6a2200450d02200341246a21032004415c6a22040d000b200d21030c030b202521032008450d02200141a0016a41186a202541186a290200370300200141a0016a41106a202541106a290200370300200141a0016a41086a202541086a290200370300200120252902003703a001202541246a2103202528022021060c010b200341206a2802002106200141a0016a41186a200141b8026a41186a290300370300200141a0016a41106a200141b8026a41106a290300370300200141a0016a41086a200141b8026a41086a290300370300200120012903b8023703a001200341246a21030b20014190026a41186a200141a0016a41186a2200290300220737030020014190026a41106a200141a0016a41106a2204290300220937030020014190026a41086a200141a0016a41086a2205290300220a370300200120012903a00122223703900220002007370300200420093703002005200a370300200120223703a001417f200d20036b41246d22002023201f6b4105766a220420042000491b21054100210b200141a0016a2100201f21040c010b0240201f2023470d0002402027450d002025102a0b4100211c410421284100212c0c020b201f41086a2900002107201f41106a2900002109201f290000210a20014190026a41186a201f41186a290000222237030020014190026a41106a200937030020014190026a41086a20073703002001200a37039002200141a0016a41186a2022370300200141a0016a41106a2009370300200141a0016a41086a20073703002001200a3703a0012023201f41206a22046b41057621054102210b200141a0016a2100202621060b417f200541016a220820082005491b221cad42247e2207422088a70d012007a72205417f4c0d010240024002400240024002400240024020050d00410421280c010b200510282228450d010b20282000290200370200202841186a200041186a290200370200202841106a200041106a290200370200202841086a200041086a290200370200202820063602200240200b450d00024020042023470d004101212c0c050b200441086a2900002107200441106a29000021092004290000210a20014190026a41186a200441186a29000037030020014190026a41106a200937030020014190026a41086a20073703002001200a37039002200441206a21040c020b0240200d2003460d00200141a0016a41186a200341186a2902002209370300200141a0016a41106a200341106a290200220a370300200141a0016a41086a200341086a29020022223703002003290200210720014190026a41086a202237030020014190026a41106a200a37030020014190026a41186a2009370300200120073703a0012001200737039002200328022021134100210b200341246a21030c030b024020042023460d00200441086a2900002107200441106a29000021092004290000210a20014190026a41186a200441186a29000037030020014190026a41106a200937030020014190026a41086a20073703002001200a37039002200441206a21040c020b4101212c0c030b200541041037000b4102210b202621130b4102210641022100412421050340200141a0016a41186a220820014190026a41186a220e290300370300200141a0016a41106a221120014190026a41106a220c290300370300200141a0016a41086a221220014190026a41086a221029030037030020012001290390023703a00102402000222c417f6a2200201c470d000240024002400240200b41ff01710e03010200010b202320046b41057621140c020b417f200d20036b41246d2214202320046b4105766a220f200f2014491b21140c010b200d20036b41246d21140b2000417f201441016a220f200f2014491b6a22142000490d0e20062014200620144b1b221cad42247e2207422088a70d0e2007a722004100480d0e02400240202c4101470d002000102821280c010b202820052000102c21280b2028450d030b202820056a220020012903a001370200200041186a2008290300370200200041106a2011290300370200200041086a2012290300370200200041206a20133602000240024002400240200b41ff01710e03010200010b20042023460d04200441086a2900002107200441106a29000021092004290000210a200e200441186a290000370300200c2009370300201020073703002001200a37039002200441206a2104410121084102210b202621130c020b0240200d2003460d002008200341186a29020022093703002011200341106a290200220a3703002012200341086a29020022223703002003290200210720102022370300200c200a370300200e2009370300200120073703a001200120073703900220032802202113410121084100210b200341246a21030c020b4102210b024020042023470d00410021080c020b200441086a2900002107200441106a29000021092004290000210a200e200441186a290000370300200c2009370300201020073703002001200a37039002200441206a210441012108202621130c010b200d2003460d02200e200341186a290200370300200c200341106a2902003703002010200341086a2902003703002001200329020037039002200328022021134101210b200341246a2103410121080b200641026a2106202c41016a2100200541246a210520080d000b0b02402027450d002025102a0b202c4115490d01202c4101762232ad42247e2207422088a70d032007a72203417f4c0d0302400240024020030d004104212e410421080c010b20031028222e450d01202e21080b2028415c6a2133202841b47f6a21344104210c410021244100212641002113202c2125034020252106410021254101210502402006417f6a221d450d000240024002400240024002402028201d41246c6a41206a280200200641246c221220286a41586a2802002203490d002006417e6a2111203420126a210441002125410021000340024020112000470d00200621050c080b200041016a21002003200428020022054f210b2004415c6a210420052103200b0d000b200041016a21052000417f7320066a21040c010b203420126a2100201d210402400340024020044101470d00410021040c020b2004417f6a210420032000280200220549210b2000415c6a210020052103200b0d000b0b20062004490d012006202c4b0d03200620046b2205410176220b450d00203320126a21032028200441246c6a21000340200141a0016a41206a2211200041206a2212280200360200200141a0016a41186a220e200041186a2210290200370300200141a0016a41106a220d200041106a2214290200370300200141a0016a41086a220f200041086a2225290200370300200120002902003703a001200341206a22272802002129200341186a222a2902002107200341106a222b2902002109200341086a222d290200210a200020032902003702002025200a37020020142009370200201020073702002012202936020020272011280200360200202a200e290300370200202b200d290300370200202d200f290300370200200320012903a0013702002003415c6a2103200041246a2100200b417f6a220b0d000b0b024020040d00200421250c050b0240200541094d0d00200421250c050b2006202c4b0d012028200441246c6a2111034020062004417f6a2225490d040240200620256b22054102490d002028200441246c6a220041206a22032802002028202541246c6a221241206a220b280200220e4f0d00200141b8026a41186a2210201241186a220d290200370300200141b8026a41106a2214201241106a220f290200370300200141b8026a41086a2227201241086a2229290200370300200120122902003703b802201220002902003702002029200041086a290200370200200f200041106a290200370200200d200041186a290200370200200b2003280200360200024020054103490d00201d210b20112103201241e8006a280200200e4f0d000340200341206a200341c4006a280200360200200341186a2003413c6a290200370200200341106a200341346a290200370200200341086a2003412c6a2902003702002003200341246a22002902003702002004200b417f6a220b460d01200341e8006a2112200021032012280200200e490d000b0b200020012903b8023702002000200e360220200041186a2010290300370200200041106a2014290300370200200041086a20272903003702000b2025450d052011415c6a2111202521042005410a4f0d050c000b0b200420061044000b20062004417f6a2225490d010b2006202c103c000b202520061044000b02400240024020132024470d00202441016a22032024490d10202441017422002003200020034b1b220341ffffffff01712003470d10200341037422004100480d100240024020240d0020001028210c0c010b200c20244103742000102c210c0b200c450d0120032124202621130b200c20134103746a2203200536020420032025360200202641016a2213212620134102490d01024003400240024002400240200c2013417f6a22264103746a2203280200450d002013410374200c6a220541746a2802002204200328020422004d0d000240201341024b0d0020132126410221130c080b200c2013417d6a22104103746a2802042203200020046a4d0d010240201341034b0d0020132126410321130c080b200541646a280200200320046a4d0d01201321260c070b20134103490d0120032802042100200c2013417d6a22104103746a28020421030b20032000490d010b2013417e6a21100b0240024002400240024002402013201041016a22274b2229450d00201320104b222a450d01200c20104103746a220d280204222b200d2802006a2203200c20274103746a2214280200220f490d022003202c4b0d032028200f41246c6a22122014280204220e41246c22006a2106200341246c21042003200f6b220b200e6b2203200e4f0d04202e2006200341246c2200109a051a200820006a210502400240200e4101480d00200341014e0d010b20062103200821000c060b203320046a210420062103034020042003415c6a220b2005415c6a22112005417c6a2802002003417c6a2802004922061b2200290200370200200441206a200041206a280200360200200441186a200041186a290200370200200441106a200041106a290200370200200441086a200041086a2902003702002005201120061b210502402012200b200320061b2203490d00200821000c070b2004415c6a21042008210020082005490d000c060b0b41b8dbc000202720131034000b41b8dbc000201020131034000b200f20031044000b2003202c103c000b202e20122000109a051a200820006a210502400240200e4101480d00200b200e4a0d010b20122103200821000c010b202820046a211120082100201221030340200320062000200641206a280200200041206a28020049220b1b2204290200370200200341206a200441206a280200360200200341186a200441186a290200370200200341106a200441106a290200370200200341086a200441086a2902003702002000200041246a200b1b2100200341246a2103200641246a2006200b1b220620114f0d01200520004b0d000b0b20032000200520006b220420044124706b109a051a0240202a450d00200d200f360200200d41046a202b200e6a3602002029450d022014201441086a20132027417f736a410374109b051a20262113202641014d0d040c010b0b41c8dbc000201020131034000b41b0b1c0001032000b200041041037000b20250d000b02402024450d00200c102a0b2032450d03202e102a0c030b200341041037000b200041041037000b202c4102490d00202c417f6a21042028202c41246c6a21064100210b0340024002400240202c20042203417f6a2204490d00202c20046b22004102490d022028200341246c6a220341206a22052802002028200441246c6a220841206a221228020022114f0d02200141b8026a41186a2213200841186a220e290200370300200141b8026a41106a220c200841106a2210290200370300200141b8026a41086a220d200841086a2214290200370300200120082902003703b802200820032902003702002014200341086a2902003702002010200341106a290200370200200e200341186a2902003702002012200528020036020020004103490d01200b210520062100200841e8006a28020020114f0d01034020002203415c6a22002003290200370200200041206a200341206a280200360200200041186a200341186a290200370200200041106a200341106a290200370200200041086a200341086a2902003702002005417f6a2205450d02200341246a2100200341c4006a28020020114f0d020c000b0b2004202c1044000b200320012903b80237020020032011360220200341186a2013290300370200200341106a200c290300370200200341086a200d2903003702000b200b41016a210b2006415c6a210620040d000b0b20014190026a41086a22034200370300200142003703900241a9a2c100410f20014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a801200142013703a001202c200141a0016a10b4010240202c450d002028202c41246c6a210b2028210003402000200141a0016a108f01200041206a28020021050240024020012802a401220420012802a80122036b4104490d0020012802a00121040c010b200341046a22062003490d0b200441017422032006200320064b1b22034100480d0b0240024020040d002003102821040c010b20012802a00120042003102c21040b2004450d04200120033602a401200120043602a00120012802a80121030b2001200341046a3602a801200420036a2005360000200b200041246a2200470d000b0b20012802a40121032002411020012802a001220020012802a801100702402003450d002000102a0b202c41246c220341246d2106410021040240024020030d004101210b410021060c010b200641ffffff3f712006470d09200641057422034100480d0920031028220b450d030b0240202c450d00202c41246c210541002104200b2103202821000340200041086a2900002107200041106a29000021092000290000210a200341186a200041186a290000370000200341106a2009370000200341086a20073700002003200a370000200441016a2104200341206a2103200041246a21002005415c6a22050d000b0b0240201c450d002028102a0b200b2004410041202004676b10c40220302031200b200410c50202402006450d00200b102a0b20014190026a41086a22034200370300200142003703900241b0a3c100411220014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a00120024110200141a0016a100621030240024020012802a0012200417f460d002003450d0020012000360294022001200336029002200141a0016a20014190026a106d20012802a0012208450d0520012902a401210a2000450d012003102a0c010b4200210a410121080b200141b8016a4200370300200141b0016a4200370300200141a8016a4200370300200142003703a001200a422088a7221041ffffff3f712010470d0020104105742203417f4c0d000240024020030d00410121060c010b200310282206450d050b200141b8026a41186a2204200141a0016a41186a290300370300200141b8026a41106a2205200141a0016a41106a290300370300200141b8026a41086a220b200141a0016a41086a290300370300200120012903a0013703b80220104102490d052010417f6a2100200621030340200320012903b802370000200341186a2004290300370000200341106a2005290300370000200341086a200b290300370000200341206a21032000417f6a22000d000b2010417f6a210c0c060b1036000b200341011037000b200341011037000b41c4d1c3004133200141d8026a419cd9c3001038000b200341011037000b4100210c200621032010450d010b200320012903b802370000200341186a200141b8026a41186a290300370000200341106a200141b8026a41106a290300370000200341086a200141b8026a41086a290300370000200c41016a210c0b201a201e41306c6a2103201ba7210e410021140c010b1031000b0240024002400240034002402018450d002003201a460d02200341506a2203290300200341086a29030084500d022018417f6a2200450d000340201a2003460d03200341506a2203290300200341086a29030084500d032000417f6a22000d000b0b2003201a460d0102400340200341506a22042903002107200441086a290300210920014190026a41186a2205200341606a220041186a29030037030020014190026a41106a220b200041106a29030037030020014190026a41086a2211200041086a29030037030020012000290300370390022007200984500d01200141a0016a41186a22002005290300370300200141a0016a41106a2205200b290300370300200141a0016a41086a220b201129030037030020012001290390023703a00120014190016a200141a0016a10bf02200141c0006a41186a22112000290300370300200141c0006a41106a22122005290300370300200141c0006a41086a2213200b290300370300200120012903a00137034002402001280290014101460d0020042103201a2004470d010c040b0b200141106a41086a220d2013290300370300200141106a41106a22132012290300370300200141106a41186a221220112903003703002001200129034022073703b8022001200737031020012802980121042000201229030037030020052013290300370300200b200d290300370300200120012903103703a001200c20044d0d03200341506a2103200620044105746a220420012903a001370000200441186a2000290300370000200441106a2005290300370000200441086a200b290300370000201441016a2114410021180c010b0b200141b8026a41086a200141e8006a41086a290300370300200141b8026a41106a200141e8006a41106a290300370300200141b8026a41186a200141e8006a41186a290300370300200120012903683703b8020b0240200e450d00201a102a0b200c201041ffffff3f7122032003200c4b1b2211450d022008210b410021050340024020082006460d002008200541057422036a2200200620036a4120109c05450d00411610282203450d0320034100290093a2413700002003410e6a41002900a1a241370000200341086a410029009ba24137000020014296808080e0023702a401200120033602a0012000200141a0016a108f0120012802a801210320012802a0012104200141b8026a41186a22124200370300200141b8026a41106a22134200370300200141b8026a41086a220e4200370300200142003703b80220042003200141b8026a1000200141106a41186a2012290300370300200141106a41106a2013290300370300200141106a41086a200e290300370300200120012903b802370310024020012802a401450d0020012802a001102a0b200141106a41201009201f210303400240202320036b41e0004b0d00024020032023460d000340200b2003460d04200320004120109c05450d042023200341206a2203470d000b0b200120004280809aa6eaafe3014200108202200129030021072001200141086a2903003703a801200120073703a0012001200141a0016a3602900220014190026a109d010c020b20002003460d01200320004120109c05450d01200341206a22042000460d01200420004120109c05450d01200341c0006a22042000460d01200420004120109c05450d01200341e0006a22042000460d0120034180016a2103200420004120109c050d000b0b200b41206a210b200541016a22052011490d000c030b0b41a0a3c1002004200c1034000b411641011037000b2006200c4105746a2103200c2111024002400240200c4104490d00200141a0016a41206a2112200141e0016a2113200141a0016a41e0006a210e200141a0026a210d200141b8016a2104200141b0016a2105200141a8016a210b20032100200c211103402004420037030020054200370300200b4200370300200142003703a001024020122000460d00200041606a200141a0016a4120109c05450d002011417f6a21000c030b2004420037030020054200370300200b4200370300200142003703a001024020132000460d00200041406a200141a0016a4120109c05450d002011417e6a21000c030b2004420037030020054200370300200b4200370300200142003703a0010240200e2000460d00200041a07f6a200141a0016a4120109c05450d002011417d6a21000c030b2004420037030020054200370300200b4200370300200142003703a001200041807f6a210302400240200d2000460d002003200141a0016a4120109c050d010b2011417c6a211120032100200320066b41e0004b0d010c020b0b2011417c6a21000c010b20032006460d012011417f6a2100200141a0016a41206a2104200141b8016a2105200141b0016a210b200141a8016a2111034020054200370300200b420037030020114200370300200142003703a001024020042003460d00200341606a200141a0016a4120109c050d020b2000417f6a21002006200341606a2203470d000c020b0b200041016a210c0b200141bc016a2031360200200141b8016a202f360200200141b4016a2030360200200141a0016a41106a2020360200200141ac016a2021360200200141083a00a001200141a0016a41086a201f360200200141033a00a40141014100200141a0016a10cc0120014190026a41086a22034200370300200142003703900241b0a3c100411220014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a801200142013703a001200c200141a0016a10b4010240200c450d00200c41057421002006210303402003200141a0016a108f01200341206a2103200041606a22000d000b0b20012802a40121032002411020012802a001220020012802a801100702402003450d002000102a0b02402010450d002006102a0b20014190026a41086a22034200370300200142003703900241bf91c600411620014190026a1008200141e8006a41086a220020032903003703002001200129039002370368200120143602a00120024110200141a0016a41041007200342003703002001420037039002418891c600411120014190026a1008200020032903003703002001200129039002370368200141003602a00120024110200141a0016a100621030240024020012802a0012200417f470d00410121030c010b024020030d00410121030c010b20004104490d03200328000021002003102a200041016a21030b20014190026a41086a220042003703002001420037039002418891c600411120014190026a1008200141e8006a41086a20002903003703002001200129039002370368200120033602a00120024110200141a0016a410410070240200aa7450d002008102a0b2019a7450d002017102a0b2016a7450d002015102a0b200141e0026a24000f0b41c4d1c3004133200141d8026a419cd9c3001038000bef0101047f230041206b220224002002410036021020014110200241106a10062101024002400240024020022802102203417f460d0020010d010b200041003602080c010b200220013602082002200336020c20034104490d012002200141046a36020820022003417c6a220436020c20044104490d01200128000021042002200341786a36020c2002200141086a36020820012800042103200241106a200241086a106d20022802102205450d012000200229021437020c2000200536020820002003360204200020043602002001102a0b200241206a24000f0b41c4d1c3004133200241106a419cd9c3001038000bb70201057f230041d0006b220224000240411610282203450d0020034100290093a2413700002003410e6a41002900a1a241370000200341086a410029009ba24137000020024296808080e002370224200220033602202001200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b200241306a2002412010c6020240024020022802304101460d00200041003602000c010b20002002290234370204200041013602000b200241d0006a24000f0b411641011037000ba50708027f017e047f027e017f017e037f017e230041d0006b220124000240024002400240024002400240410e10282202450d00200241066a41002900b2a441370000200241002900aca4413700002002410e411c102c2202450d012002410036000e42002103200141286a41186a22044200370300200141286a41106a22054200370300200141286a41086a220642003703002001420037032820024112200141286a1000200141186a2004290300370300200141106a2005290300370300200141086a2006290300370300200120012903283703002002102a2001410036022820014120200141286a100621040240024020012802282202417f470d00410121070c010b2001200236022420012004360220200141286a200141206a107420012802282207450d03200129022c21032002450d002004102a0b02400240410e10282202450d0041002900b2a441210841002900aca4412109410121040340200241066a2008370000200220093700002002410e411c102c2202450d062002200436000e200141286a41186a22054200370300200141286a41106a22064200370300200141286a41086a220a42003703002001420037032820024112200141286a1000200141186a2005290300370300200141106a2006290300370300200141086a200a290300370300200120012903283703002002102a2001410036022820014120200141286a100621060240024020012802282202417f470d00410121054200210b0c010b2001200236022420012006360220200141286a200141206a107420012802282205450d08200129022c210b2002450d002006102a0b200b422088a72206450d0202402003a7220a2003422088a722026b200641216c220c41216d22064f0d00200220066a220d2002490d0a200a410174220e200d200e200d4b1bad220342217e220f422088a70d0a200fa7220d4100480d0a02400240200a0d00200d102821070c010b2007200a41216c200d102c21070b2007450d090b2007200241216c6a2005200c109a051a200342ffffffff0f832103200220066aad422086210f0240200ba7450d002005102a0b200441016a21042003200f842103410e102822020d000b0b410e41011037000b0240200ba7450d002005102a0b2000200337020420002007360200200141d0006a24000f0b410e41011037000b411c41011037000b41c4d1c3004133200141c8006a419cd9c3001038000b411c41011037000b41c4d1c3004133200141c8006a419cd9c3001038000b200d41011037000b1031000bcc0402057f017e230041e0006b220224000240024002400240411310282203450d0020034100290099a4413700002003410f6a41002800a8a441360000200341086a41002900a1a44137000020024293808080b00237022c200220033602282001200241286a108f012001280220210402400240200228022c2201200228023022036b4104490d00200228022821010c010b200341046a22052003490d03200141017422032005200320054b1b22034100480d030240024020010d002003102821010c010b200228022820012003102c21010b2001450d022002200336022c20022001360228200228023021030b2002200341046a360230200120036a20043600002002280230210320022802282101200241386a41186a22044200370300200241386a41106a22054200370300200241386a41086a220642003703002002420037033820012003200241386a1000200241086a41186a2004290300370300200241086a41106a2005290300370300200241086a41086a2006290300370300200220022903383703080240200228022c450d002002280228102a0b20024100360238200241086a4120200241386a100621010240024020022802382203417f460d002002200336022c20022001360228200241386a200241286a10820120022802382204450d05200229023c210702402003450d002001102a0b20002007370204200020043602000c010b20004100360208200042043702000b200241e0006a24000f0b411341011037000b200341011037000b1031000b41c4d1c3004133200241d8006a419cd9c3001038000bf70103017e057f027e420121020240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a360200200641034d0d00200428000421072001200341786a22063602042001200441086a36020020064110490d00200441106a2900002108200429000821092001200341686a22063602042001200441186a36020020064110490d0020002009370308200041186a2004290018370300200041106a20083703002000412c6a2007360200200041286a2005360200200041206a200441206a2900003703002001200341586a3602042001200441286a360200420021020b200020023703000bd30102027f027e200028022021020240024002400240410410282203450d002003200236000020002802242102200341044108102c2203450d0120032002360004200041086a290300210420002903002105200341084118102c2203450d0220032005370008200341106a2004370000200041186a290300210420002903102105200341184130102c2200450d0320002005370018200041206a2004370000200128020020012802042000412810072000102a0f0b410441011037000b410841011037000b411841011037000b413041011037000b942103157f037e077f230041c0026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110da032003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200a200a417f6a220d2000200a4105746a2000200d4105746a4120109c05220e410048220f1b2210200a41016a2211200d200a200f1b220a200020114105746a2000200a4105746a4120109c05220f4100481b220a2000200a4105746a200020104105746a4120109c0522104100481b210a200c200c417f6a220d2000200c4105746a2000200d4105746a4120109c05221141004822121b2213200c4101722214200d200c20121b220c200020144105746a2000200c4105746a4120109c0522124100481b220c2000200c4105746a200020134105746a4120109c0522134100481b210c200b200b417f6a220d2000200b4105746a2000200d4105746a4120109c05221441004822151b2216200b41016a2217200d200b20151b220b200020174105746a2000200b4105746a4120109c05220d4100481b220b2000200b4105746a200020164105746a4120109c0522154100481b210b200f411f76200e411f766a2010411f766a2011411f766a2012411f766a2013411f766a2014411f766a200d411f766a2015411f766a210d0b2000200c4105746a2000200a4105746a4120109c05220e411f76200d6a2000200b4105746a2000200a200c200e410048220e1b220f4105746a4120109c052210411f766a210d2000200b200f20104100481b220b4105746a2000200c200a200e1b22184105746a4120109c05417f4c0d01200b21180c020b2000200110db030c0f0b200d41016a220d410c490d0002402001410176220b450d00200020014105746a41606a210a2000210c0340200441206a41186a220d200c41186a220e290000370300200441206a41106a220f200c41106a2210290000370300200441206a41086a2211200c41086a22122900003703002004200c290000370320200a41086a22132900002119200a41106a2214290000211a200a41186a2215290000211b200c200a290000370000200e201b3700002010201a370000201220193700002015200d2903003700002014200f29030037000020132011290300370000200a2004290320370000200a41606a210a200c41206a210c200b417f6a220b0d000b0b20012018417f736a21184101210a0c010b200d45210a0b0240200a452009724101710d002000200110dc030d0d0b2002450d02201820014f0d0102402002200020184105746a220a4120109c0541004e0d0020002108200121070c040b200441206a41186a2212200041186a220f290000370300200441206a41106a2213200041106a2210290000370300200441206a41086a2214200041086a221129000037030020042000290000370320200a41086a220c2900002119200a41106a220b290000211a200a41186a220d290000211b2000200a290000370000200f201b3700002010201a37000020112019370000200d2012290300370000200b2013290300370000200c2014290300370000200a2004290320370000200441c0016a41186a2217200f290000370300200441c0016a41106a221c2010290000370300200441c0016a41086a22182011290000370300200420002900003703c001200041606a2115200041206a21164100210c2001210b03400240200c200b417f6a220d4f0d002016200c4105746a210a0340200441c0016a200a4120109c05417f4c0d01200a41206a210a200d200c41016a220c470d000b200d210c0b2015200b4105746a210a02400340200c200b417f6a220b4f0d01200441c0016a200a4120109c05210d200a41606a220e210a200d4100480d000b20122016200c4105746a220a41186a220d2900003703002013200a41106a221d2900003703002014200a41086a22062900003703002004200a290000370320200e41286a221e2900002119200e41306a221f290000211a200e41386a2220290000211b200a200e41206a220e290000370000200d201b370000201d201a3700002006201937000020202012290300370000201f2013290300370000201e2014290300370000200e2004290320370000200c41016a210c0c010b0b200020042903c001370000200f20172903003700002010201c2903003700002011201829030037000002402001200c41016a220a490d002000200a4105746a21002001200a6b220141154f0d010c0c0b0b200a20011044000b41a0cec300201820011034000b2007450d010b201820074f0d01200441206a41186a2216200841186a221e290000370300200441206a41106a2217200841106a221f290000370300200441206a41086a221c200841086a222029000037030020042008290000370320200820184105746a220a41086a220c2900002119200a41106a220b290000211a200a41186a220d290000211b2008200a290000370000201e201b370000201f201a37000020202019370000200d2016290300370000200b2017290300370000200c201c290300370000200a2004290320370000200441186a2205201e290000370300200441106a2209201f290000370300200441086a2221202029000037030020042008290000370300200841206a21014100211d2007417f6a220d450d022001210a0340200a20044120109c0541004e0d03200a41206a210a200d201d41016a221d470d000b200d211d0c020b4180cec300410041001034000b4190cec300201820071034000b200820074105746a210c200d210b02400340200c2100200b220a201d4d22060d01200a417f6a210b200041606a220c20044120109c05417f4a0d000b0b0240200a201d490d00200d200a490d0241800121144100210e410021124100210d4100211141800121152001201d4105746a2222210103400240200020016b220a419fc0004b22180d00200a410576220a41807f6a200a2012200e492011200d49220c72220b1b210a0240200b450d002015200a200c1b2115200a2014200c1b21140c010b200a200a41017622156b21140b02402011200d470d00024020150d00200441c0006a220d21110c010b4100210a200441c0006a2211210d2001210c0340200d200a3a0000200d200c20044120109c05417f73411f766a210d200c41206a210c2015200a41016a220a470d000b0b02402012200e470d00024020140d00200441c0016a220e21120c010b200041606a210a4100210c200441c0016a2212210e0340200e200c3a0000200e200a20044120109c05411f766a210e200a41606a210a2014200c41016a220c470d000b0b0240200e20126b220a200d20116b220c200c200a4b1b2213450d002016200120112d00004105746a220a41186a2900003703002017200a41106a290000370300201c200a41086a2900003703002004200a290000370320200120112d00004105746a220a200020122d0000417f734105746a220c290000370000200a41186a200c41186a290000370000200a41106a200c41106a290000370000200a41086a200c41086a290000370000024020134101460d004100210a034020002012200a6a220f2d0000417f734105746a220c20012011200a6a41016a22102d00004105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200120102d00004105746a220c2000200f41016a2d0000417f734105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200a41026a210c200a41016a220b210a200c2013490d000b2012200b6a21122011200b6a21110b200020122d0000417f734105746a220a2004290320370000200a41186a2016290300370000200a41106a2017290300370000200a41086a201c290300370000201241016a2112201141016a21110b200020144105746b20002012200e461b2100200120154105746a20012011200d461b210120180d000b024002402011200d4f0d002000210a034020162001200d417f6a220d2d00004105746a220c41186a220b2900003703002017200c41106a220e290000370300201c200c41086a22002900003703002004200c290000370320200a41606a220a41086a220f2900002119200a41106a2210290000211a200a41186a2212290000211b200c200a290000370000200b201b370000200e201a370000200020193700002012201629030037000020102017290300370000200f201c290300370000200a20042903203700002011200d490d000c020b0b2001210a2012200e4f0d000340200e417f6a220e2d0000210c2016200a41186a220b2900003703002017200a41106a220d290000370300201c200a41086a22012900003703002004200a2900003703202000200c417f734105746a220c41086a220f2900002119200c41106a2210290000211a200c41186a2211290000211b200a200c290000370000200b201b370000200d201a370000200120193700002011201629030037000020102017290300370000200f201c290300370000200c2004290320370000200a41206a210a2012200e490d000b0b20082004290300370000201e2005290300370000201f2009290300370000202020212903003700002007200a20226b410576201d6a22014d0d032016201e2900003703002017201f290000370300201c202029000037030020042008290000370320200820014105746a220a41086a220c2900002119200a41106a220b290000211a200a41186a220d290000211b2008200a290000370000201e201b370000201f201a37000020202019370000200d2016290300370000200b2017290300370000200c201c290300370000200a2004290320370000200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41206a2100024002402001200c417f6a220c490d002000200c200a200310c402200821000c010b200820012002200310c402200a2102200c21010b200b200d4f2105200141154f0d010c050b0b201d200a1044000b200a200d103c000b4190cec300200120071034000b41dc83c6001032000b20014102490d00200041406a210f410021104101210d0340200d410574210a200d417f6a210b200d41016a210d02402000200a6a220e2000200b4105746a220a4120109c05417f4a0d00200441c0016a41186a2211200e41186a220c290000370300200441c0016a41106a2212200e41106a2213290000370300200441c0016a41086a2214200e41086a22152900003703002004200e2900003703c001200e200a2900003700002015200a41086a2900003700002013200a41106a290000370000200c200a41186a29000037000002400240200b0d004100210b0c010b2010210c200f210a200441c0016a200e41406a4120109c05417f4a0d0002400340200a41d8006a200a41386a290000370000200a41d0006a200a41306a290000370000200a41c8006a200a41286a290000370000200a41c0006a200a41206a290000370000200c4101460d01200441c0016a200a4120109c05210e200c417f6a220b210c200a41606a210a200e4100480d000c020b0b4100210b0b2000200b4105746a220a20042903c001370000200a41186a2011290300370000200a41106a2012290300370000200a41086a20142903003700000b201041016a2110200f41206a210f200d2001470d000b0b200441c0026a24000bd9140a057f017e067f037e037f017e017f027e077f057e23002204210520044180026b4160712204240002400240200141ffffff3f712001470d0020014105742206417f4c0d0002400240024020060d00410121070c010b200610282207450d010b410021084100210602402001450d002001410574210820072106034020062000290000370000200641186a200041186a290000370000200641106a200041106a290000370000200641086a200041086a290000370000200641206a2106200041206a2100200841606a22080d000b200141057441606a41057641016a2106200121080b20042006360218200420083602142004200736021020072006410041202006676b10c40242002109200441b0016a41086a22004200370300200442003703b001419896c300411d200441b0016a1008200441e0016a41086a2000290300370300200420042903b0013703e001200441003602b001200441e0016a4110200441b0016a1006210602400240024020042802b0012200417f460d0020042000360294012004200636029001200441b0016a20044190016a106d20042802b001220a450d0220042902b40121092000450d012006102a0c010b4101210a0b2009422088a72200450d032000410574210b200441e0016a410c6a210c200441e0016a411472210d200441e0016a410872210e200441c0006a410c72210f200a210002400340200041086a2900002110200041106a290000211120002900002112200441206a41186a2213200041186a290000370300200441206a41106a22142011370300200441206a41086a22152010370300200420123703200240024002400240411a10282206450d00200641002900b596432216370000200641186a41002f00cd964322173b0000200641106a41002900c596432218370000200641086a41002900bd964322193700002004429a808080a0033702b401200420063602b0012004200441b0016a3602e001200441206a200441e0016a10c80120042802b001210720042802b801211a200441e0016a41186a22014200370300200441e0016a41106a22064200370300200441e0016a41086a22084200370300200442003703e0012007201a200441e0016a100020044190016a41186a221b200129030037030020044190016a41106a221c200629030037030020044190016a41086a221a2008290300370300200420042903e00137039001024020042802b401450d0020042802b001102a0b200441003602e00120044190016a4120200441e0016a1006211d20042802e0012207417f460d02200420073602642004201d360260200441e0016a200441e0006a10b30320042802e801221e450d01200441b0016a41086a221f200c41086a290200370300200441b0016a41106a2220200c41106a2802003602002004200c2902003703b00120042903e001211002402007450d00201d102a0b200f20042903b00122113702002006202028020022073602002008201f2903002212370300200f41086a2012370200200f41106a2007360200200420113703e001200420103703400c030b411a41011037000b41c4d1c3004133200441d0016a419cd9c3001038000b2006200441b0016a41106a2802003602002008200441b0016a41086a290300370300200420042903b0013703e0014100211e0b2004201e360248200441003602e80120042903582112200420042903f801222137035820042903502122200420042903f001222337035020042903402124200420042903e001221137034020042903482110200420042903e80122253703482025a72107024002402010a7221d0d002025211020232122202121120c010b200420243703e001200420103703e801200420223703f001200420123703f8012004201d2022a74105746a3602bc012004201d3602b80120042010422088a73602b4012004201d3602b0012004200441106a3602c00120044190016a200441b0016a108401200e41086a201a280200360200200e20042903900137020020042022422088a7221d2012422088a74105746a3602bc012004201d3602b80120042012a73602b4012004201d3602b0012004200441106a3602c00120044190016a200441b0016a108401200d41086a201a280200360200200d20042903900137020020042903e801211020042903e001211120042903f801211220042903f001212202402007450d002021a7211d02402025422088a7450d002007102a0b201d450d002023422088a7102a0b200420113703402004201037034820042022370350200420123703582010a721070b2004201137036020042010370368200420223703702004201237037802400240024020070d00200441b0016a41186a2013290300370300200441b0016a41106a2014290300370300200441b0016a41086a2015290300370300200420042903203703b001411a10282207450d0220072016370000200741186a20173b0000200741106a2018370000200741086a20193700002004429a808080a0033702d401200420073602d0012004200441d0016a3602e001200441b0016a200441e0016a10c80120042802d001210720042802d801211d200142003703002006420037030020084200370300200442003703e0012007201d200441e0016a1000201b2001290300370300201c2006290300370300201a2008290300370300200420042903e00137039001024020042802d401450d0020042802d001102a0b20044190016a412010090c010b200441b0016a41186a2013290300370300200441b0016a41106a2014290300370300200441b0016a41086a2015290300370300200420042903203703b001411a10282207450d0320072016370000200741186a20173b0000200741106a2018370000200741086a20193700002004429a808080a0033702d401200420073602d0012004200441d0016a3602e001200441b0016a200441e0016a10c80120042802d001210720042802d801211d200142003703002006420037030020084200370300200442003703e0012007201d200441e0016a1000201b2001290300370300201c2006290300370300201a2008290300370300200420042903e00137039001024020042802d401450d0020042802d001102a0b200441203602e401200420044190016a3602e001200441e0006a200441e0016a10b4030b02402010a72206450d002012a7210802402010422088a7450d002006102a0b2008450d002022422088a7102a0b200041206a2100200b41606a220b0d010c060b0b411a41011037000b411a41011037000b41c4d1c3004133200441d0016a419cd9c3001038000b200641011037000b1036000b02402009a7450d00200a102a0b200441003602e801200442013703e0012003200441e0016a10b40102402003450d002003410574210003402002200441e0016a108f01200241206a2102200041606a22000d000b0b20042802e401210620042802e801210820042802e0012100200441b0016a41086a22014200370300200442003703b00141fbefc200411b200441b0016a1008200441e0016a41086a2001290300370300200420042903b0013703e001200441e0016a411020002008100702402006450d002000102a0b02402004280214450d002004280210102a0b200524000ba50101027f230041206b22032400410021042003410036021420012002200341146a100621010240024020032802142202417f460d002001450d002003410036020c20024104490d0120012800002104200341003602102002417c714104460d01200128000421022001102a200041086a200236020020002004360204410121040b20002004360200200341206a24000f0b41c4d1c3004133200341186a419cd9c3001038000b13002000410a36020420004188a5c1003602000b3400200041fecbc10036020420004100360200200041146a4110360200200041106a4188ccc100360200200041086a42073702000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241003600000b2201017f230041106b22022400200241003602002000200210ad02200241106a24000b13002000410b360204200041c0e5c1003602000b3101017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241c0003600000b3d01017f02404110102822020d00411041011037000b200242003700082002428080e983b1de16370000200042908080808002370204200020023602000b3201017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180c2033600000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241013600000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241063600000b3d01017f02404110102822020d00411041011037000b200242003700082002428080d287e2bc2d370000200042908080808002370204200020023602000b3e01017f02404110102822020d00411041011037000b2002420037000820024280809aa6eaafe301370000200042908080808002370204200020023602000b9f0a01047f230041206b220224000240024002400240024002400240024002400240024002400240024002402001280200417f6a220341094b0d0020030e0a0102030405060708090a010b41c4f7c1001032000b2001410c6a2802002203417f4c0d0a200128020421044101210502402003450d00200310282205450d0c0b200520042003109a0521052000410c6a2003360200200041086a20033602002000200536020420004101360200200041206a200141206a290300370300200041186a2001290318370300200041106a20012902103703000c090b2001410c6a2802002203417f4c0d09200128020421050240024020030d00410121040c010b200310282204450d0c0b200420052003109a0521052000410c6a2003360200200041086a20033602002000200536020420004102360200200041206a200141206a290300370300200041186a2001290318370300200041106a20012902103703000c080b200128020421054101210302400240200141086a22042d00004101460d002002411e6a200441036a2d00003a0000200241086a200141186a290200370300200241106a200141206a290200370300200241186a200141286a2d00003a0000200220042f00013b011c2002200141106a2902003703002001410c6a2802002104410021030c010b2001410c6a28020021040b20002005360204200020022f011c3b0009200041086a20033a00002000410c6a2004360200200041106a20022903003702002000412c6a200129022c3702002000410b6a2002411e6a2d00003a0000200041186a200241086a290300370200200041206a200241106a290300370200200041286a200241186a280200360200200041033602000c070b20004104360200200020012802043602040c060b20004105360200200020012802043602040c050b410121030240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002105410021030c010b200141086a28020021050b200020033a0004200020022f011c3b0005200041306a2001290330370300200041086a20053602002000410c6a2002290300370200200041386a200141386a290300370300200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602002001280228210120004106360200200041286a20013602000c040b20004107360200200020012802043602040c030b410121030240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002101410021030c010b200141086a28020021010b200020033a0004200020022f011c3b000520004108360200200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c020b20004109360200200020012802043602040c010b2000410a360200200020012802043602040b200241206a24000f0b1036000b200341011037000b200341011037000bbf4305047f027e037f017e067f23004190026b22072400200741f0006a41086a220842003703002007420037037041b0a3c1004112200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0014100210920074100360270200741a0016a4110200741f0006a1006210802402007280270220a417f460d002008450d002007200a36027420072008360270200741306a200741f0006a106c0240024020072802300d00200728023421090c010b410021090b200a450d002008102a0b200741f0006a41086a220842003703002007420037037041b8a2c1004114200741f0006a1008200741a0016a41086a220a2008290300370300200720072903703703a001024002400240200741a0016a41104101410041001003417f460d0041effec1002108412e210a0c010b2008420037030020074200370370418891c6004111200741f0006a1008200a2008290300370300200720072903703703a00120074100360270200741a0016a4110200741f0006a1006210802400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402007280270220a417f470d004100210a0c010b024020080d004100210a0c010b200a4104490d012008280000210a2008102a0b0240200a2003460d00419dffc10021084114210a0c1e0b024020090d0041b1ffc100210841c100210a0c1e0b02402009200241086a2802004f0d0041f2ffc1002108413c210a0c1e0b02402005428080e983b1de165441002006501b450d0041ae80c20021084124210a0c1e0b200741206a2001109d02200741206a41086a290300210b2007290320210c411310282208450d01200c200554200b200654200b2006511b210a200841002900c2a3413700002008410f6a41002800d1a341360000200841086a41002900caa34137000020074293808080b002370274200720083602702001200741f0006a108f012007280278210820072802702109200741a0016a41186a220d4200370300200741a0016a41106a220e4200370300200741a0016a41086a220f4200370300200742003703a00120092008200741a0016a1000200741c0006a41186a200d290300370300200741c0006a41106a200e290300370300200741c0006a41086a200f290300370300200720072903a00137034002402007280274450d002007280270102a0b200b2006200a1b210b200c2005200a1b210620074100360270200741c0006a4120200741f0006a100621080240024002402007280270220a417f460d002008450d002007200a3602a401200720083602a001200741f0006a200741a0016a10c20220072903704201510d0520074180016a29030021052007290378210c0240200a450d002008102a0b410e10282208450d06200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d072008200441067636000e200741a0016a41186a220a4200370300200741a0016a41106a22094200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741f0006a41186a200a290300370300200741f0006a41106a2009290300370300200741f0006a41086a200d290300370300200720072903a0013703702008102a200741003602a001200741f0006a4120200741a0016a1006210820072802a001220a417f460d1b2008450d1b2007200a3602dc01200720083602d801200741a0016a200741d8016a107420072802a001220d450d082004413f71210920072902a40121100240200a450d002008102a0b4100210420092010422088a7490d010c190b200741106a20011091012007290310428080e983b1de1656200741186a29030022054200522005501b0d0141e380c20021084134210a0c1f0b200d200941216c6a22082d00004101470d17200741da016a200841036a2d00003a0000200741a0016a41086a200841146a290000370300200741ad016a200841196a290000370000200720082f00013b01d80120072008410c6a2900003703a001200841086a280000210a200841046a2800002108410121040c180b410e10282208450d06200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d0720082004410676220e36000e200741a0016a41186a220a4200370300200741a0016a41106a22094200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a200a290300370300200741c0006a41106a2009290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a20074100360270200741c0006a4120200741f0006a1006210802402007280270220a417f460d002008450d002007200a3602a401200720083602a001200741f0006a200741a0016a10742007280270220d450d092004413f712109200729027421050240200a450d002008102a0b41002108024020092005422088a74f0d0041014102200d200941216c6a2d00001b21080b02402005a7450d00200d102a0b20084102490d00410e10282208450d0a200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d0b2008200e36000e42002105200741a0016a41186a220a4200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a200a290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a20074100360270200741c0006a4120200741f0006a100621080240024020072802702204417f470d004101210a0c010b024020080d004101210a0c010b200720043602a401200720083602a001200741f0006a200741a0016a10742007280270220a450d0d200729027421052004450d002008102a0b200741c0006a41186a2204200141186a290000370300200741c0006a41106a220d200141106a290000370300200741c0006a41086a220f200141086a2900003703002007200129000037034020092005422088a722114f0d0d200a200941216c6a220841013a000020082007290340370001200841096a200f290300370000200841116a200d290300370000200841196a2004290300370000410e102821080240200a0d002008450d0f200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d102008200e36000e200741a0016a41186a220a4200370300200741a0016a41106a22094200370300200741a0016a41086a22044200370300200742003703a00120084112200741a0016a1000200741c0006a41186a200a290300370300200741c0006a41106a2009290300370300200741c0006a41086a2004290300370300200720072903a0013703402008102a200741c0006a412010090c170b2008450d10200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d112008200e36000e200741a0016a41186a22094200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a200741203602742007200741c0006a360270200a2011200741f0006a10ab022005a7450d16200a102a0c160b200741f0006a41086a2208420037030020074200370370419991c6004114200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0014100210a20074100360270200741a0016a4110200741f0006a10062108024020072802702209417f460d002008450d0020094104490d122008280000210a2008102a0b410e10282208450d12200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d132008200a36000e200741a0016a41186a22094200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a20074100360270200741c0006a4120200741f0006a1006210802400240024020072802702209417f460d002008450d002007200936027420072008360270200741086a200741f0006a106c0240024020072802080d00200728020c210d410021040c010b4101210441b8aec600210d0b02402009450d002008102a0b20040d00200d413f460d01200d0d170b200741f0006a2001428080d287e2bc2d4200410810980220072802704101470d012007280278210a200728027421080c1f0b200741f0006a41086a2208420037030020074200370370419991c6004114200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0012007200a41016a360270200741a0016a4110200741f0006a410410070c150b20072903782105200720074180016a29030037037820072005370370200b2006428080aef89dc3527c2205200654ad7c427f7c210b2007200741f0006a3602a001200741a0016a109d01200521060c140b41c4d1c3004133200741c0016a419cd9c3001038000b411341011037000b41c4d1c3004133200741c0016a419cd9c3001038000b410e41011037000b411c41011037000b41c4d1c3004133200741c0016a419cd9c3001038000b410e41011037000b411c41011037000b41c4d1c3004133200741c0016a419cd9c3001038000b410e41011037000b411c41011037000b41c4d1c3004133200741c0016a419cd9c3001038000b41a0a3c100200920111034000b410e41011037000b411c41011037000b410e41011037000b411c41011037000b41c4d1c3004133200741c0016a419cd9c3001038000b410e41011037000b411c41011037000b200741f9006a200141086a29000037000020074181016a200141106a29000037000020074189016a200141186a290000370000200741013a00702007200129000037007102400240024002400240024002400240024002400240024002400240024002400240410e10282208450d00200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d012008200a36000e200741a0016a41186a22094200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a200741003602a001200741c0006a4120200741a0016a100621080240024020072802a0012204417f460d002004210920080d010b200741003602a801200742013703a0014100200741a0016a10b40120072802a801210920072802a401210420072802a00121080b200720093602682007200436026420072008360260024002402009450d00200741a0016a20082009410110d60220072802a0014101470d012007280264450d122007280260102a0c120b4101200741e0006a10b401024020072d00704101460d0002400240200728026420072802682208460d00200728026021090c010b200841016a22092008490d1b200841017422042009200420094b1b22044100480d1b0240024020080d002004102821090c010b200728026020082004102c21090b2009450d052007200436026420072009360260200728026821080b2007200841016a360268200920086a41003a00000c100b02400240200728026420072802682208460d00200728026021090c010b200841016a22092008490d1a200841017422042009200420094b1b22044100480d1a0240024020080d002004102821090c010b200728026020082004102c21090b2009450d052007200436026420072009360260200728026821080b2007200841016a360268200920086a41013a0000200741f0006a410172200741e0006a108f010c0f0b20072802a401210d0240200741ac016a2802002208200741a8016a2802002209460d002007280268200820096b6a220441216a220e417f4c0d0502400240200e0d004101210f0c010b200e1028220f450d070b2007200e3602c4012007200f3602c001200720043602c8012007200741c0016a3602a001200d200741a0016a200810d70120042008490d0720072802c801220d2004490d082007280268220d2009490d0920072802c001210e2007280260210f2007200420086b22043602d0012007200d20096b220d3602d4012004200d470d0a200e20086a200f20096a2004109a051a0240024020072d00704101460d000240024020072802c40120072802c8012208460d0020072802c00121090c010b200841016a22092008490d1c200841017422042009200420094b1b22044100480d1c0240024020080d002004102821090c010b20072802c00120082004102c21090b2009450d0e200720043602c401200720093602c00120072802c80121080b2007200841016a3602c801200920086a41003a00000c010b0240024020072802c40120072802c8012208460d0020072802c00121090c010b200841016a22092008490d1b200841017422042009200420094b1b22044100480d1b0240024020080d002004102821090c010b20072802c00120082004102c21090b2009450d0e200720043602c401200720093602c00120072802c80121080b2007200841016a3602c801200920086a41013a0000200741f0006a410172200741c0016a108f010b20072802c801210920072802c401210420072802c00121082007280264450d102007280260102a0c100b2007200741e0006a3602a001200d200741a0016a200910d701024020072d00704101460d0002400240200728026420072802682208460d00200728026021090c010b200841016a22092008490d1a200841017422042009200420094b1b22044100480d1a0240024020080d002004102821090c010b200728026020082004102c21090b2009450d0e2007200436026420072009360260200728026821080b2007200841016a360268200920086a41003a00000c0f0b02400240200728026420072802682208460d00200728026021090c010b200841016a22092008490d19200841017422042009200420094b1b22044100480d190240024020080d002004102821090c010b200728026020082004102c21090b2009450d0e2007200436026420072009360260200728026821080b2007200841016a360268200920086a41013a0000200741f0006a410172200741e0006a108f010c0e0b410e41011037000b411c41011037000b200441011037000b200441011037000b1036000b200e41011037000b200820041044000b2004200d103c000b2009200d1044000b200741f0016a41146a4108360200200741fc016a4125360200200741d8016a41146a4103360200200742033702dc01200741c8afc6003602d801200741253602f4012007200741d0016a360288022007200741d4016a36028c02200742043703b001200742013702a4012007419cb0c6003602a0012007200741f0016a3602e8012007200741a0016a3602800220072007418c026a3602f801200720074188026a3602f001200741d8016a41d8b0c600103e000b200441011037000b200441011037000b200441011037000b200441011037000b2007280268210920072802642104200728026021080b2008450d00200741c0006a41202008200910072004450d012008102a0c010b024002400240412110282208450d0041002109024020072d00704101470d00200741b8016a20074189016a290000370300200741b0016a20074181016a290000370300200741a8016a200741f9006a290000370300200720072900713703a001410121090b200820093a0000200820072903a001370001200841096a200741a8016a290300370000200841116a200741b0016a290300370000200841196a200741b8016a290300370000410e10282209450d01200941066a41002900b2a441370000200941002900aca4413700002009410e411c102c2209450d022009200a36000e200741a0016a41186a220a4200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120094112200741a0016a1000200741c0006a41186a200a290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402009102a200741203602a4012007200741c0006a3602a00120084101200741a0016a10ab022008102a0c030b412141011037000b410e41011037000b411c41011037000b20072001428080e983b1de164200108302024020072802002208450d002007280204210a0c080b200741f0006a41086a220842003703002007420037037041ad91c6004112200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0014100210a20074100360270200741a0016a4110200741f0006a100621080240024020072802702209417f460d002008450d0020094104490d012008280000210a2008102a0b4200210c200741f0006a41086a220842003703002007420037037041ad91c6004112200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0012007200a41016a360270200741a0016a4110200741f0006a41041007420021050c060b41c4d1c3004133200741c0016a419cd9c3001038000b0b02402010a7450d00200d102a2004450d010c020b20040d010b410121094113210a419781c20021080c010b200741c0016a41026a200741d8016a41026a2d00003a0000200741f0006a41086a200741a0016a41086a290300370300200741f0006a410d6a200741a0016a410d6a290000370000200720072f01d8013b01c001200720072903a001370370410021090b200741e0006a41026a2204200741c0016a41026a2d00003a0000200741f0016a41086a220d200741f0006a41086a290300370300200741f0016a41106a200741f0006a41106a290300370300200720072f01c0013b0160200720072903703703f00120090d02200741d3006a200d290300370000200741d8006a200741fd016a290000370000200720072f01603b01402007200a36004720072008360043200720072903f00137004b200720042d00003a0042200741c0006a2001460d00200741c0006a20014120109c05450d0041d280c20021084111210a0c020b200742f0f2bda9c6add9b1f400370338200741386a20012006200b417f410f10a902200741f0006a41186a200b3703002007200637038001200720053703782007200c370370200720033602940120072003360290010240024002400240411310282208450d00200841002900c2a3413700002008410f6a41002800d1a341360000200841086a41002900caa34137000020074293808080b0023702f401200720083602f0012001200741f0016a108f0120072802f801210820072802f001210a200741a0016a41186a22094200370300200741a0016a41106a22034200370300200741a0016a41086a22044200370300200742003703a001200a2008200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2003290300370300200741c0006a41086a2004290300370300200720072903a001370340024020072802f401450d0020072802f001102a0b200741203602a4012007200741c0006a3602a001200741f0006a200741a0016a10c3022002280204210f20022802002103024002400240200241086a280200220941057622120d0041042113410421140c010b2012410274220810282213450d01201321140b2009450d030240024020120d00410410282213450d0141012112201321140b201441003602002009417f6a210441012115410021084100210a024003402014200a4102746a2202200320086a2d00002008411f717420022802006a360200024002400240024020042008460d00200841016a2202411f710d0320152012470d02201541016a220d2015490d0c2015410174220e200d200e200d4b1b221241ffffffff03712012470d0c2012410274220d41004e0d010c0c0b0240200f450d002003102a0b41002116024002400240024003402015410820154108491b220a410274220f10282208450d0120082014200f109a052111200741f0006a41186a200141186a290000370300200741f0006a41106a200141106a290000370300200741f0006a41086a200141086a290000370300200720163602900120072001290000370370411310282208450d0220084100290099a4413700002008410f6a41002800a8a441360000200841086a41002900a1a44137000020074293808080b0023702f401200720083602f001200741f0006a200741f0016a108f0120072802900121090240024020072802f401220220072802f80122086b4104490d0020072802f00121020c010b200841046a22032008490d11200241017422082003200820034b1b22084100480d110240024020020d002008102821020c010b20072802f00120022008102c21020b2002450d04200720083602f401200720023602f00120072802f80121080b2007200841046a3602f801200220086a200936000020072802f801210820072802f0012102200741a0016a41186a22094200370300200741a0016a41106a22034200370300200741a0016a41086a22044200370300200742003703a00120022008200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2003290300370300200741c0006a41086a2004290300370300200720072903a001370340024020072802f401450d0020072802f001102a0b2015200a6b21152014200f6a2114410021082007410036027820074201370370200a200741f0006a10b4014100200728027822046b210a200728027421030340200420086a2109201120086a280200210d024002402003200a6a4104490d00200728027021020c010b200941046a22022009490d122003410174220e2002200e20024b1b220e4100480d120240024020030d00200e102821020c010b20072802702003200e102c21020b2002450d062007200e36027420072002360270200e21030b2007200941046a360278200220046a20086a200d360000200a417c6a210a200f200841046a2208470d000b200741c0006a41202002200420086a100702402003450d002002102a0b2011102a201641016a211620150d000b410021082012450d0e2013102a0c0e0b200f41041037000b411341011037000b200841011037000b200e41011037000b0240024020150d00200d102821130c010b20132015410274200d102c21130b2013450d03201321140b201420154102746a4100360200200a41016a210a201541016a21150b200920024d0d05200221082015200a4b0d000b41a0a3c100200a20151034000b200d41041037000b410441041037000b200841041037000b411341011037000b41cca2c100200841016a20091034000b0240200f450d002003102a0b410021080b0c020b1031000b200241046a280200450d002002280200102a0b2000200a3602042000200836020020074190026a24000b810f03037f017e097f23004190016b2202240002400240024002400240024002400240024002400240410e10282203450d00200341066a41002900b2a441370000200341002900aca4413700002003410e411c102c2203450d0120032001410676220436000e42002105200241f0006a41186a22064200370300200241f0006a41106a22074200370300200241f0006a41086a220842003703002002420037037020034112200241f0006a1000200241086a41186a2006290300370300200241086a41106a2007290300370300200241086a41086a2008290300370300200220022903703703082003102a20024100360238200241086a4120200241386a100621030240024020022802382207417f470d00410121060c010b024020030d00410121060c010b2002200736027420022003360270200241386a200241f0006a107420022802382206450d03200229023c21052007450d002003102a0b2001413f7122032005422088a722074f0d032006200341216c6a220341003a000020032002290038370001200341096a200241c0006a290000370000200341116a200241c8006a290000370000200341196a200241d0006a290000370000410e10282203450d04200341066a41002900b2a441370000200341002900aca4413700002003410e411c102c2203450d052003200436000e200241f0006a41186a22044200370300200241f0006a41106a22084200370300200241f0006a41086a220142003703002002420037037020034112200241f0006a1000200241086a41186a2004290300370300200241086a41106a2008290300370300200241086a41086a2001290300370300200220022903703703082003102a2002412036023c2002200241086a36023820062007200241386a10ab0202402005a7450d002006102a0b200241386a41086a220342003703002002420037033841ad91c6004112200241386a1008200120032903003703002002200229033837037020024100360238200241f0006a4110200241386a10062103417f2106024020022802382201417f460d002003450d0020014104490d07200328000021062003102a2006417f6a21060b200241386a41086a220442003703002002420037033841ad91c6004112200241386a1008200241f0006a41086a220720042903003703002002200229033837037020022006360238200241f0006a4110200241386a41041007200241386a41186a2208200041186a2209290000370300200241386a41106a220a200041106a220b2900003703002004200041086a220c2900003703002002410036025820022000290000370338200241286a200241386a10c10202402002280230450d0041012106034020082009290000370300200a200b2900003703002004200c29000037030020022006417f6a36025820022000290000370338411310282203450d0920034100290099a4413700002003410f6a41002800a8a441360000200341086a41002900a1a44137000020024293808080b00237026420022003360260200241386a200241e0006a108f012002280258210d0240024020022802642201200228026822036b4104490d00200228026021010c010b200341046a220e2003490d0c20014101742203200e2003200e4b1b22034100480d0c0240024020010d002003102821010c010b200228026020012003102c21010b2001450d0b2002200336026420022001360260200228026821030b2002200341046a360268200120036a200d3600002002280268210320022802602101200241f0006a41186a220d4200370300200241f0006a41106a220e4200370300200742003703002002420037037020012003200241f0006a1000200241086a41186a200d290300370300200241086a41106a200e290300370300200241086a41086a20072903003703002002200229037037030802402002280264450d002002280260102a0b200241086a412010090240200228022c450d002002280228102a0b20082009290000370300200a200b2900003703002004200c2900003703002002200029000037033820022006360258200641016a2106200241286a200241386a10c10220022802300d000b0b0240200228022c450d002002280228102a0b411310282203450d0a200341002900c2a3413700002003410f6a41002800d1a341360000200341086a41002900caa34137000020024293808080b00237023c200220033602382000200241386a108f012002280240210320022802382106200241f0006a41186a22014200370300200241f0006a41106a22004200370300200241f0006a41086a220442003703002002420037037020062003200241f0006a1000200241086a41186a2001290300370300200241086a41106a2000290300370300200241086a41086a2004290300370300200220022903703703080240200228023c450d002002280238102a0b200241086a4120100920024190016a24000f0b410e41011037000b411c41011037000b41c4d1c3004133200241e0006a419cd9c3001038000b41a0a3c100200320071034000b410e41011037000b411c41011037000b41c4d1c3004133200241e0006a419cd9c3001038000b411341011037000b200341011037000b1031000b411341011037000bd40201027f0240024002402002450d002002417f6a2104024020012d0000220241037122054103460d000240024020050e03040001040b2004450d0220012d0001410874200272220241ffff0371418002490d02200241fcff037141027621020c040b20044103490d0120012f0001200141036a2d000041107472410874200272220241808004490d01200241027621020c030b200241034b0d0020044104490d002001280001220241ffffffff034b0d020b200041013602000f0b200241027621020b0240200220036a220120024f0d00200041013602000f0b41012103410121050240200241c000490d0041022105200241808001490d00410441052002418080808004491b21050b0240200141c000490d0041022103200141808001490d00410441052001418080808004491b21030b20002001360204200041003602002000410c6a2003360200200041086a20053602000b130020004101360204200041f486c2003602000b3400200041f487c20036020420004100360200200041146a4107360200200041106a418488c200360200200041086a420f3702000b2201017f230041106b22022400200241003602002000200210da02200241106a24000bd60201037f0240024002400240024002400240024002400240024002400240024020012802000e0400010203000b41012102410110282201450d05200141003a0000410121030c040b410110282202450d05200241013a000020012802042103200241014105102c2202450d062002200336000120012802082104410a210320024105410a102c2201450d07200120043600050c020b41012102410110282201450d07200141023a0000410121030c020b410110282202450d07200241033a000020012802042103200241014105102c2202450d082002200336000120012802082104410a210320024105410a102c2201450d09200120043600050b410921020b2000200236020820002003360204200020013602000f0b410141011037000b410141011037000b410541011037000b410a41011037000b410141011037000b410141011037000b410541011037000b410a41011037000b130020004101360204200041cc92c2003602000b34002000419596c20036020420004100360200200041146a4107360200200041106a419c96c200360200200041086a42073702000b130020004101360204200041aca3c2003602000b890201057f230041106b22022400024002400240411110282203450d002002421137020420022003360200410d200210b4010240024020022802042204200228020822036b410d490d002003410d6a2105200228020021040c010b2003410d6a22052003490d03200441017422062005200620054b1b22064100480d030240024020040d002006102821040c010b200228020020042006102c21040b2004450d0220022006360204200220043602000b20022005360208200420036a22034100290082a542370000200341056a4100290087a54237000020002002290300370200200041086a2002280208360200200241106a24000f0b411141011037000b200641011037000b1031000bce04010b7f230041106b220324002003420037030820012002200341086a102720032003290308370300200120026a21040240024002400240200241086a220520024f0d00200341086a2106200321074100210841002105410121094100210a0340200841017421022006200741016a220b6b210c034020072d00002107024002400240024020082005470d00200c2105024002400240200a41ff01710e03010200010b200420016b21050c010b417f200c200420016b6a22052005200c491b21050b2008417f200541016a220d200d2005491b6a22052008490d0920022005200220054b1b22054100480d090240024020080d002005102821090c010b200920082005102c21090b2009450d010b200920086a20073a00000240024002400240200a41ff01710e03010300010b20042001460d010c050b0240200b2006460d004100210a0c040b20042001470d040b200841016a21080c070b4101210a200b2006470d01200841016a21080c060b200541011037000b200841016a2108200b21070c020b200841016a21084102210a200241026a21022001220741016a21010c000b0b0b4101210902402005450d0020054100480d03200510282209450d020b410021080340200920086a200320086a2d00003a0000200841016a22084108470d000b024020020d00410821080c010b200920086a210a410021080340200a20086a200120086a2d00003a00002002200841016a2208470d000b200420016b41086a21080b200020083602082000200536020420002009360200200341106a24000f0b200541011037000b1031000bc30401047f230041206b22022400024002400240024002400240410110282203450d00200320012d00003a0000200341014102102c2203450d01200320012d00013a0001200341024104102c2203450d02200320012d00023a0002200320012d00033a0003200341044108102c2203450d03200320012d00043a0004200320012d00053a0005200320012d00063a0006200320012d00073a0007200341084110102c2203450d04200320012d00083a0008200320012d00093a0009200320012d000a3a000a200320012d000b3a000b200320012d000c3a000c200320012d000d3a000d200320012d000e3a000e200320012d000f3a000f200341104120102c2203450d05200320012d00103a0010200320012d00113a0011200320012d00123a0012200320012d00133a0013200320012d00143a0014200320012d00153a0015200320012d00163a0016200320012d00173a0017200320012d00183a0018200320012d00193a0019200320012d001a3a001a200320012d001b3a001b200320012d001c3a001c200320012d001d3a001d200320012d001e3a001e200320012d001f3a001f200241186a22014200370300200241106a22044200370300200241086a22054200370300200242003703002003412020021000200041186a2001290300370000200041106a2004290300370000200041086a2005290300370000200020022903003700002003102a200241206a24000f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000bd40201087f230041206b2203240020034100360208200342013703002001200310b401024002400240024020010d002003280208210420032802042105200328020021060c010b200141246c210720032802042105200328020821010340200341106a200010ec012003280210210802400240200520016b20032802182209490d00200120096a2104200328020021060c010b200120096a22042001490d04200541017422062004200620044b1b220a4100480d040240024020050d00200a102821060c010b20032802002005200a102c21060b2006450d032003200a36020420032006360200200a21050b20032004360208200620016a20082009109a051a02402003280214450d002008102a0b200041246a2100200421012007415c6a22070d000b0b2002280200200228020420062004100702402005450d002006102a0b200341206a24000f0b200a41011037000b1031000b130020004103360204200041a0a5c2003602000b340020004185acc20036020420004100360200200041146a4103360200200041106a4190acc200360200200041086a42083702000b130020004104360204200041a8b0c2003602000b0b00200041a0c21e10e6020b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200220013600000b3201017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180e1013600000b0b00200041d0860310e6020bdd0301047f230041d0026b2202240002400240024002400240411210282203450d00200341106a41002f008086423b0000200341086a41002900f88542370000200341002900f08542370000200341124124102c2203450d0120032001360012200241e8016a41186a22014200370300200241e8016a41106a22044200370300200241e8016a41086a22054200370300200242003703e80120034116200241e8016a1000200241e8006a41186a2001290300370300200241e8006a41106a2004290300370300200241e8006a41086a2005290300370300200220022903e8013703682003102a200241003602e801200241e8006a4120200241e8016a1006210120022802e8012203417f460d032002200336020c20022001360208200241e8016a200241086a10810220022903e8014201510d0220024188016a200241e8016a41086a41e000109a051a02402003450d002001102a0b200241086a20024188016a41e000109a051a200241e8016a200241086a41e000109a051a20004201370300200041086a200241e8016a41e000109a051a0c040b411241011037000b412441011037000b41c4d1c300413320024188016a419cd9c3001038000b200241e8016a200241086a41e000109a051a200042003703000b200241d0026a24000bc06709017f017e017f027e157f017e037f017e037f230041a0056b2201240010eb020240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020004101460d0042002102200141206a41086a2200420037030020014200370320418efcc5004110200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a100621000240024002400240024002400240024002400240024020012802e8032203417f460d002000450d0020034108490d01200029000021022000102a0b42002104200141206a41086a220042003703002001420037032041dffbc500410f200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034108490d02200029000021042000102a0b42002105200141206a41086a220042003703002001420037032041fefbc5004110200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034108490d03200029000021052000102a0b420020022005200442c8017e7c7d220420042002561b42c801540d0a200141206a41086a2200420037030020014200370320419499c6004114200141206a100820014188036a41086a2000290300370300200120012903203703880341002106200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034104490d04200028000021062000102a0b200141206a41086a220042003703002001420037032041a899c6004115200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a100621000240024020012802e8032203417f470d00410221070c010b024020000d00410221070c010b2003450d0520002d000021072000102a0b10fb01210820014188036a41086a22004200370300200142003703880341c2e1c000410d20014188036a1008200141e8036a41086a200029030037030020012001290388033703e80320014100360220200141e8036a4110200141206a100621000240024020012802202203417f460d002000450d00200120033602a401200120003602a001200141206a200141a0016a107c20012802202209450d07200129022421052003450d012000102a0c010b41012109420021050b200141206a41086a220042003703002001420037032041c785c2004112200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a100621000240024020012802e8032203417f460d002000450d002001200336022420012000360220200141e8036a200141206a106d20012802e803220a450d0820012902ec0321042003450d012000102a0c010b4101210a420021040b02402004422088a722000d004108210b4100210c4100210d0c0a0b2000410574210e200141e8036a41206a210f4100210c4100210d4108210b41002103200a2100034020014188026a41186a2210200041186a29000037030020014188026a41106a2211200041106a29000037030020014188026a41086a2212200041086a2900003703002001200029000037038802200141e8036a2008200310fc0120012802e803221320012802f00341014100410010032114024020012802ec03450d002013102a0b02402014417f470d00200141206a41186a22142010290300370300200141206a41106a22132011290300370300200141206a41086a221520122903003703002001200129038802370320200141e8036a200141206a10ec02200128028804450d09200141206a41286a2216200141e8036a41286a290300370300200141206a41206a2217200f2903003703002014200141e8036a41186a22182903003703002013200141e8036a41106a22192903003703002015200141e8036a41086a221a290300370300200120012903e8033703202018201029030037030020192011290300370300201a201229030037030020012001290388023703e803200f2001290320370300200f41086a2015290300370300200f41106a2013290300370300200f41186a2014290300370300200f41206a2017290300370300200f41286a20162903003703000240200c200d470d00200c41016a2214200c490d26200c41017422102014201020144b1b220dad42d0007e2202422088a70d262002a722144100480d2602400240200c0d0020141028210b0c010b200b200c41d0006c2014102c210b0b200b450d0b0b200b200c41d0006c6a200141e8036a41d000109a051a200c41016a210c0b200341016a2103200041206a2100200e41606a220e450d0a0c000b0b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41f187c1004192021050000b201441081037000b02402004a7450d00200a102a0b02400240200c450d002001410036022820014201370320200141f8036a200c360200200141f4036a200d3602002001200b3602f003200120054220883e02ec03200120083602e803200141206a200141e8036a10c5012005a7450d012009102a0c010b02402005a7450d002009102a0b200d450d00200b102a0b200141206a41086a220042003703002001420037032041f5b6c2004112200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a1006210b024002400240024002400240024002400240024002400240024002400240024002400240024020012802e8032216417f460d00200b450d00200120163602ac022001200b3602a802200141086a200141a8026a106c20012802080d2b20012802ac02220f41807f712200417f4c0d14200128020c211202400240200f41077622140d00410121150c010b200010282215450d100b02402012450d00200141e8036a41206a2113200141a0016a41017221084100210c0340200141003a00c001200c41016a210e4100210002400240024002400340200f2000460d01200141a0016a20006a20012802a80222032d00003a00002001200341016a3602a8022001200041016a22033a00c0012003210020034120470d000b20014188026a41086a2200200141a0016a41086a29030037030020014188026a41106a2210200141a0016a41106a29030037030020014188026a41186a2211200141a0016a41186a290300370300200120012903a001370388022001200f20036b3602ac02200141a0016a200141a8026a10e80120012d00a0014101460d01200141e8036a41186a2011290300370300200141e8036a41106a2010290300370300200141e8036a41086a200029030037030020012001290388023703e8032013200841e000109a051a200141206a200141e8036a418001109a051a2014200c470d03200c4101742200200e2000200e4b1b221441ffffff0f712014470d322014410774220041004e0d020c320b200141003602ac02200041ff0171450d00200141003a00c0010b2014450d2f2015102a0c2f0b02400240200c0d002000102821150c010b2015200c4107742000102c21150b2015450d050b2015200c4107746a200141206a418001109a051a200e2012460d0120012802ac02210f200e210c0c000b0b2015450d2b2012ad42208621022014ad210402402016450d00200b102a0b2002200484211b0c010b410121154200211b0b4100210002400240201b422088a72218410774220c0d004101211c4100211d0c010b200c41027622031028221c450d0d201841ffffff0f71211d0b200741ff0171210e02402018450d002018410774210f201c210020152103034020002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200041206a210020034180016a2103200f41807f6a220f0d000b201841077441807f6a41077641016a21000b200e410247210f200141206a41086a220342003703002001420037032041c785c2004112200141206a100820014188036a41086a20032903003703002001200129032037038803200141003602f003200142013703e8032000200141e8036a10b40102402000450d0020004105742103201c210003402000200141e8036a108f01200041206a2100200341606a22030d000b0b2007200f71211a20012802ec03210020014188036a411020012802e803220320012802f003100702402000450d002003102a0b0240201a450d00200141206a41086a220042003703002001420037032041bd99c600411a200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a1006210020012802e8032203417f460d002000450d002001200336022420012000360220200141e8036a200141206a10820120012802e803220f450d0c20012902ec03210202402003450d002000102a0b20014188036a411010092002a7450d00200f102a0b200141106a200641026a10ed02024002402001280210221e0d00200141206a41086a220042003703002001420037032041c785c2004112200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d002001200336022420012000360220200141e8036a200141206a106d20012802e803220d450d0d20012902ec03211f02402003450d002000102a0b410021200c020b410021204101210d4200211f0c010b410121202001290214211f201e210d0b200141206a41086a2200420037030020014200370320419499c6004114200141206a100820014188036a41086a20002903003703002001200129032037038803410121162001200641016a22063602e80320014188036a4110200141e8036a41041007200120203a001f20012015200c6a22073602ec04200120153602e8042001200141e8046a3602fc0420012001411f6a3602f8044100210e410021210240201f422088a722004105742203450d002003410575222141ffffff0f712021470d2b202141077422034100480d2b200310282216450d0a0b02402000450d002000410574210c200141206a410172210b200141e8036a41206a2108200141a8026a41c0006a2119200141a8026a41206a21174100210e20162114200d21000340200041086a2900002102200041106a29000021042000290000210520014188026a41186a2210200041186a29000037030020014188026a41106a2211200437030020014188026a41086a22122002370300200120053703880220014188056a20014188026a108b02200128029005210f2001280288052103200141003602202003200f200141206a1006210f0240024020012802202213417f460d00200f450d002001201336028c032001200f36028803200141206a20014188036a10e80120012d00204101460d0c200141a0016a200b41e000109a051a02402013450d00200f102a0b20014188036a200141a0016a41e000109a051a200141206a20014188036a41e000109a051a200141a0016a200141206a41e000109a051a4101210f0c010b200141206a20014188036a41e000109a051a4100210f0b0240200128028c05450d002003102a0b02400240200f0d00200141a8026a410041e0001099051a0c010b200141a8026a200141a0016a41e000109a051a0b024020012802f8042d00000d0020012802fc04220f2802002203200f280204460d00200f20034180016a36020002400240200141a8026a200341206a220f460d00200f200141a8026a4120109c050d010b02402017200341c0006a220f460d00200f20174120109c050d010b2019200341e0006a2203460d01200320194120109c05450d010b20012802f80441013a00000b200041206a2100200141e8036a41186a2010290300370300200141e8036a41106a2011290300370300200141e8036a41086a201229030037030020012001290388023703e8032008200141a8026a41e000109a051a200e41016a210e2014200141e8036a418001109a054180016a2114200c41606a220c0d000b0b0240201fa7450d00200d102a0b200e41ffffff0f71200e470d12200e4107742200417f4c0d1220012d001f21120240024020000d00410121110c010b200010282211450d080b410021000240200e450d002016200e4107746a2110200141e8036a41e0006a2103200141e8036a41c0006a210f200141e8036a41206a210c20112114201621000340200141e8036a41186a200041186a290000370300200141e8036a41106a200041106a290000370300200141e8036a41086a200041086a290000370300200120002900003703e803200c41186a200041386a290000370000200c41106a200041306a290000370000200c41086a200041286a290000370000200c200041206a290000370000200f41186a200041d8006a290000370000200f41106a200041d0006a290000370000200f41086a200041c8006a290000370000200f200041c0006a2900003700002003200041e0006a290000370000200341086a200041e8006a290000370000200341106a200041f0006a290000370000200341186a200041f8006a2900003700002014200141e8036a418001109a054180016a211420004180016a22002010470d000b200e41077441807f6a41077641016a21000b200141206a41086a220342003703002001420037032041f5b6c2004112200141206a100820014188036a41086a20032903003703002001200129032037038803200141003602f003200142013703e8032000200141e8036a10b40102402000450d00201120004107746a21032011210003402000200141e8036a108f01200041206a200141e8036a108f01200041c0006a200141e8036a108f01200041e0006a200141e8036a108f0120004180016a22002003470d000b0b20012802ec03210020014188036a411020012802e803220320012802f003100702402000450d002003102a0b0240200e450d002011102a0b200120123a00e803200141206a41086a220042003703002001420037032041a899c6004115200141206a100820014188036a41086a2000290300370300200120012903203703880320014188036a4110200141e8036a41011007200120063602ec03200141043a00e80341014100200141e8036a10cc01410810282203450d0620032007360204200320153602000240201a0d0042002102200141206a41086a220042003703002001420037032041e194c600411c200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e803220f417f460d002000450d00200f4108490d07200029000021022000102a0b200141206a41086a2200420037030020014200370320419499c6004114200141206a100820014188036a41086a200029030037030020012001290320370388034100210f200141003602e80320014188036a4110200141e8036a10062100024020012802e803220c417f460d002000450d00200c4104490d062000280000210f2000102a0b411c10282200450d04200041186a41002800959546360000200041106a410029008d9546370000200041086a41002900859546370000200041002900fd94463700002000411c4138102c2200450d032000200237001c20014188026a41186a220c420037030020014188026a41106a2214420037030020014188026a41086a2210420037030020014200370388022000412420014188026a1000200141e8036a41186a200c290300370300200141e8036a41106a2014290300370300200141e8036a41086a201029030037030020012001290388023703e8032000102a2001200f360220200141e8036a4120200141206a410410072003102a0c110b024002402018450d00200320154180016a2210360200200120152900223701ea032001201529002a3701f20320014188026a41086a220020012903f003370300200120152900323701fa0320014188026a41106a220f20012903f8033703002001201528003a36018204200120152f003e3b01860420014188026a41186a220c200129038004370300200141003a008804200120152d00213a00e903200120152d00203a00e803200120012903e8033703880220014188036a41186a2214200c29030037030020014188036a41106a220c200f29030037030020014188036a41086a220f2000290300370300200120012903880237038803200141206a41186a22002014290300370300200141206a41106a2214200c290300370300200141206a41086a220c200f290300370300200120012903880337032020150d010b2003102a4108211241002110410021000c100b200141a0016a41186a2000290300370300200141a0016a41106a2014290300370300200141a0016a41086a200c290300370300200120012903203703a001200720106b41077641016a220041286c220f417f4c0d12200f10282212450d01201220012903a00137030020124201370320201241186a200141a0016a41186a220a290300370300201241106a200141a0016a41106a2209290300370300201241086a200141a0016a41086a222229030037030002402003280200220f2003280204220d470d00410121100c0f0b2003200f4180016a22063602002001200f2900223701ea032001200f29002a3701f20320014188026a41086a221320012903f0033703002001200f2900323701fa0320014188026a41106a220820012903f8033703002001200f28003a360182042001200f2f003e3b01860420014188026a41186a220b200129038004370300200141003a0088042001200f2d00213a00e9032001200f2d00203a00e803200120012903e8033703880220014188036a41186a220f200b29030037030020014188036a41106a220c200829030037030020014188036a41086a22142013290300370300200120012903880237038803200141206a41186a2217200f290300370300200141206a41106a2218200c290300370300200141206a41086a2219201429030037030020012001290388033703204102211041c80021110340200a2017290300220237030020092018290300220437030020222019290300220537030020012001290320221f3703a001200f2002370300200c2004370300201420053703002001201f3703880302400240024002402010417f6a2000460d002000211a0c010b200d20066b41077620006a41016a221a2000490d2e2000410174220d201a200d201a4b1b221aad42287e2202422088a70d2e2002a7220d4100480d2e0240024020000d00200d102821120c010b2012200041286c200d102c21120b2012450d010b201220116a220d41606a220020012903880337030020142903002102200c2903002104200f2903002105200d4201370300200041186a2005370300200041106a2004370300200041086a2002370300200328020022002003280204220d470d01201a21000c110b200d41081037000b200320004180016a2206360200200120002900223701ea032001200029002a3701f203201320012903f003370300200120002900323701fa03200820012903f8033703002001200028003a36018204200120002f003e3b018604200b200129038004370300200141003a008804200120002d00213a00e903200120002d00203a00e803200120012903e80337038802200f200b290300370300200c2008290300370300201420132903003703002001200129038802370388032017200f2903003703002018200c290300370300201920142903003703002001200129038803370320201141286a2111201041016a2110201a21000c000b0b200041011037000b200f41081037000b413841011037000b411c41011037000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b410841041037000b200041011037000b41c4d1c300413320014198056a419cd9c3001038000b200341011037000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b200341011037000b200041011037000b2003102a0b200141206a41086a220342003703002001420037032041d985c2004117200141206a100820014188036a41086a20032903003703002001200129032037038803200141e8036a20014188036a411010c6020240024020012802e8034101460d00200120103602f003200120003602ec03200120123602e803200141e8036a41004100200110ee020c010b20014188036a4110100920012902ec032102200120103602f003200120003602ec03200120123602e803200141e8036a2002a741012002422088a710ee020b42002102200141206a41086a220042003703002001420037032041e194c600411c200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034108490d04200029000021022000102a0b200141206a41086a220042003703002001420037032041e194c600411c200141206a100820014188036a41086a2203200029030037030020012001290320370388032001200242017c22023703e80320014188036a4110200141e8036a410810072000420037030020014200370320419499c6004114200141206a100820032000290300370300200120012903203703880341002103200141003602e80320014188036a4110200141e8036a10062100024020012802e803220f417f460d002000450d00200f4104490d05200028000021032000102a0b411c10282200450d05200041186a41002800959546360000200041106a410029008d9546370000200041086a41002900859546370000200041002900fd94463700002000411c4138102c2200450d062000200237001c20014188026a41186a220f420037030020014188026a41106a220c420037030020014188026a41086a2214420037030020014200370388022000412420014188026a1000200141e8036a41186a200f290300370300200141e8036a41106a200c290300370300200141e8036a41086a201429030037030020012001290388023703e8032000102a20012003360220200141e8036a4120200141206a410410070b410810282200450d062000200736020420002015360200410810282219450d0720192016200e4107746a221a3602042019201636020042002102200141206a41086a220342003703002001420037032041dffbc500410f200141206a100820014188036a41086a20032903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062103024020012802e803220f417f460d002003450d00200f4108490d09200329000021022003102a0b200242017c22042002540d09200141206a41086a220342003703002001420037032041dffbc500410f200141206a100820014188036a41086a220f20032903003703002001200129032037038803200120043703e80320014188036a4110200141e8036a41081007200141e8046a20004188b7c20010880120012802ec04211020012802e804211420012802f0042100200342003703002001420037032041eefbc5004110200141206a1008200f20032903003703002001200129032037038803200141003602f003200142013703e8032000200141e8036a10b40102402000450d002014200041286c6a210e2014210303402003200141e8036a108f01200341206a29030021020240024020012802ec03220f20012802f00322006b4108490d0020012802e803210f0c010b200041086a220c2000490d1c200f4101742200200c2000200c4b1b22004100480d1c02400240200f0d0020001028210f0c010b20012802e803200f2000102c210f0b200f450d0d200120003602ec032001200f3602e80320012802f00321000b2001200041086a3602f003200f20006a2002370000200e200341286a2203470d000b0b20012802ec03210020014188036a411020012802e803220320012802f003100702402000450d002003102a0b02402010450d002014102a0b200442017c22022004540d0b200141206a41086a220042003703002001420037032041adfcc5004113200141206a100820014188036a41086a20002903003703002001200129032037038803200141e8036a20014188036a10ef0220012d00e803210020014188026a41186a220320014181046a29000037030020014188026a41106a220f200141f9036a29000037030020014188026a41086a220c200141f1036a290000370300200120012900e903370388020240024020004101460d00200141a0016a41186a4200370300200141a0016a41106a4200370300200141a0016a41086a4200370300200142003703a0010c010b200141a0016a41186a2003290300370300200141a0016a41106a200f290300370300200141a0016a41086a200c29030037030020012001290388023703a0010b200141206a41086a220042003703002001420037032041c0fcc5004111200141206a100820014188036a41086a2000290300370300200120012903203703880341002112200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034104490d0d200028000021122000102a0b200141206a41086a220042003703002001420037032041c0fcc5004111200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a41041007200141206a41186a200141a0016a41186a290300370300200141206a41106a200141a0016a41106a2903003703002000200141a0016a41086a290300370300200120012903a001370320417f201241016a220020002012491b410d74412872220b417f4c0d01200b10282208450d0d2008200129032037000020082002370020200841186a200141206a41186a290300370000200841106a200141206a41106a290300370000200841086a200141206a41086a2903003700004128211341002103410021004100211102400240024003400240024002400240024002402000450d00200f200c470d010b03402000210c200320124f0d02411610282200450d182000410e6a41002900dffc45370000200041086a41002900d9fc45370000200041002900d1fc4537000020004116412c102c2200450d192000200336001620014188026a41186a220f420037030020014188026a41106a220e420037030020014188026a41086a2214420037030020014200370388022000411a20014188026a100020014188036a41186a200f29030037030020014188036a41106a200e29030037030020014188036a41086a20142903003703002001200129038802370388032000102a200141003602a80220014188036a4120200141a8026a1006210e0240024020012802a802220f417f470d0041012100420021020c010b2001200f36028c022001200e36028802200141a8026a20014188026a107320012802a8022200450d1b20012902ac0221020240200f450d00200e102a0b20014188036a412010090b20002002422088a74105746a210f0240200c450d002010450d002011102a0b200341016a21032002a7211020002111200f2000460d000b200021112000210c0b200c41086a2900002102200c41106a2900002104200c2900002105200141e8036a41186a200c41186a290000221f370300200141e8036a41106a2004370300200141e8036a41086a2002370300200120053703e80320014188036a41186a2214201f37030020014188036a41106a2217200437030020014188036a41086a221820023703002001200537038803200b20136b411f4b0d03201341206a220e2013490d21200b410174220d200e200d200e4b1b220e4100480d21200b0d01200e102821080c020b0240200c450d002010450d002000102a0b20014188026a41186a2203420037030020014188026a41106a220f420037030020014188026a41086a220c420037030020014200370388022008201320014188026a1000200141e8036a41186a22142003290300370300200141e8036a41106a2210200f290300370300200141e8036a41086a2211200c29030037030020012001290388023703e8030240200b450d002008102a0b200141206a41086a220042003703002001420037032041adfcc5004113200141206a100820014188036a41086a220e2000290300370300200120012903203703880320014110360224200120014188036a360220200141e8036a200141206a10f002200141a8026a41186a200141a0016a41186a2903002202370300200141a8026a41106a200141a0016a41106a2903002204370300200141a8026a41086a200141a0016a41086a2903002205370300200120012903a001221f3703a8022014200237030020102004370300201120053703002001201f3703e8032000420037030020014200370320419efcc500410f200141206a1008200e2000290300370300200120012903203703880320014110360224200120014188036a360220200141e8036a200141206a10f002200141f8046a20194194b9c200108801200042003703002001420037032041adfcc5004113200141206a1008200e20002903003703002001200129032037038803200141e8036a20014188036a10ef0220012d00e8032100200320014181046a290000370300200f200141f9036a290000370300200c200141f1036a290000370300200120012900e9033703880220004101460d05200141a0036a420037030020014198036a420037030020014190036a420037030020014200370388030c060b2008200b200e102c21080b2008450d02200e210b0b200c41206a210c200820136a220e200129038803370000200e41186a2014290300370000200e41106a2017290300370000200e41086a2018290300370000201341206a21130c000b0b200e41011037000b20014188036a41186a20014188026a41186a29030037030020014188036a41106a20014188026a41106a29030037030020014188036a41086a20014188026a41086a2903003703002001200129038802370388030b200141206a41086a2200200141f8046a41086a280200360200200141206a41246a20014188036a41186a290300370200200141206a411c6a20014188036a41106a290300370200200141206a41146a20014188036a41086a290300370200200120012903f8042202370320200120012903880337022c20014194046a200141206a41286a280200360200200141e8036a41246a200141c0006a290300370200200141e8036a411c6a200141206a41186a290300370200200141e8036a41146a200141206a41106a290300370200200141f4036a220f2000290300370200200120023702ec03200141003602e803200141003602a801200142013703a001410110282200450d11200141013602a401200120012802a801220341016a3602a801200120003602a001200020036a41013a000020012802ec032103200f2802002200200141a0016a10b40102402000450d002003200041286c6a210e03402003200141a0016a108f01200341206a29030021020240024020012802a401220f20012802a80122006b4108490d0020012802a001210f0c010b200041086a220c2000490d1c200f4101742200200c2000200c4b1b22004100480d1c02400240200f0d0020001028210f0c010b20012802a001200f2000102c210f0b200f450d15200120003602a4012001200f3602a00120012802a80121000b2001200041086a3602a801200f20006a2002370000200e200341286a2203470d000b0b200141f8036a200141a0016a10f10220014193026a200141a0016a41086a280200360000200120012903a0012202370388052001200237008b02200141ac016a2001418f026a290000370000200141c28289aa043600a101200141023a00a00120012001290088023700a501200141a0016a10ce01024020012802e8030d00200141e8036a41086a280200450d0020012802ec03102a0b410810282203450d13200320073602042003201536020041081028220f450d14200f201a360204200f201636020010fb01210c411b10282200450d15200041176a41002800d89646360000200041106a41002900d19646370000200041086a41002900c99646370000200041002900c196463700002000411b4136102c2200450d162000200c36001b20014188026a41186a220c420037030020014188026a41106a220e420037030020014188026a41086a2214420037030020014200370388022000411f20014188026a100020014188036a41186a200c29030037030020014188036a41106a200e29030037030020014188036a41086a220c20142903003703002001200129038802370388032000102a20014188036a4120100e109801210e200141206a41086a2200420037030020014200370320419be1c0004111200141206a1008200c200029030037030020012001290320370388032001200e3602e80320014188036a4110200141e8036a41041007200141a0016a200341a0bbc200108301200042003703002001420037032041c2e1c000410d200141206a1008200c2000290300370300200120012903203703880320012802a001210c20012802a8012100200141003602f003200142013703e8032000200141e8036a10b40102402000450d0020004105742103200c210003402000200141e8036a108f01200041206a2100200341606a22030d000b0b20012802ec03210020014188036a411020012802e803220320012802f003100702402000450d002003102a0b024020012802a401450d00200c102a0b200f102a410810282200450d172000201a36020420002016360200200141a0016a200041acbdc200108301200141206a41086a2200420037030020014200370320419695c4004117200141206a1008200141e8036a41086a2000290300370300200120012903203703e80320012802a001210f20012802a801210020014100360228200142013703202000200141206a10b40102402000450d0020004105742103200f210003402000200141206a108f01200041206a2100200341606a22030d000b0b20012802242100200141e8036a4110200128022022032001280228100702402000450d002003102a0b024020012802a401450d00200f102a0b02402021450d002016102a0b02402020201e45720d002001280214450d00201e102a0b0240201d450d00201c102a0b201ba7450d002015102a0b200141a0056a24000f0b1036000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b411c41011037000b413841011037000b410841041037000b410841041037000b41c4d1c300413320014198056a419cd9c3001038000b41c0c7c20041c9001050000b200041011037000b41c0c7c20041c9001050000b41c4d1c300413320014198056a419cd9c3001038000b200b41011037000b411641011037000b412c41011037000b41c4d1c300413320014198056a419cd9c3001038000b410141011037000b200041011037000b410841041037000b410841041037000b411b41011037000b413641011037000b410841041037000b41c4d1c300413320014198056a419cd9c3001038000b1031000bd11906047f017e037f027e027f037e23004190046b22002400200041e8036a41086a22014200370300200042003703e80341e7fcc5004110200041e8036a100820004188036a41086a2001290300370300200020002903e80337038803200041e0016a20004188036a109a03024002400240024002400240024020002d00e0014102470d00200041e0016a41086a22024200370300200042003703e00141b1f0c200410d200041e0016a100820012002290300370300200020002903e0013703e803200041003602e001200041e8036a4110200041e0016a1006210102400240024002400240024020002802e0012202417f460d002001450d002000200236027420002001360270200041e0016a200041f0006a107620002802e0012203450d0220002902e40121042002450d012001102a0c010b41042103420021040b20032004422088a7220541246c22066a2102200321010240200641ed00490d00200321010340024020012d00004101470d00200141016a2800002106200141086a28020021072000200141106a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c050b0240200141246a2d00004101470d00200141256a28000021062001412c6a28020021072000200141346a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c050b0240200141c8006a2d00004101470d00200141c9006a2800002106200141d0006a28020021072000200141d8006a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c050b0240200141ec006a2d00004101470d00200141ed006a2800002106200141f4006a28020021072000200141fc006a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c050b200220014190016a22016b41ec004b0d000b0b20012002460d012003200541246c6a21020340024020012d00004101470d00200141016a2800002106200141086a28020021072000200141106a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c040b2002200141246a2201460d020c000b0b41c4d1c3004133200041e8026a419cd9c3001038000b410221070c010b20002002200141016a41ef00109a0522012800003602602000200141036a28000036006320002900772108200041086a200041ff006a41d800109a051a20002900d70121090b02402005450d00200541246c21022003210103400240024020012d0000220641034b0d0002400240024020060e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012002415c6a22020d000b0b02402004a7450d002003102a0b200020002802603602682000200028006336006b200041f0006a200041086a41d800109a051a41002101024020074102460d00200020002802683602e0022000200028006b3600e302200020083703d802200041e0016a200041f0006a41d800109a051a200020093703d002200041e8036a41086a22014200370300200042003703e80341fefbc5004110200041e8036a100820004188036a41086a2001290300370300200020002903e80337038803200041003602a80320004188036a4110200041a8036a100621010240024020002802a8032202417f460d002001450d0020024108490d04200129000021042001102a200450450d010b200041d8026a200041d0026a20074101461b2903002104200041e8036a41086a22014200370300200042003703e80341fefbc5004110200041e8036a100820004188036a41086a22022001290300370300200020002903e80337038803200020043703a80320004188036a4110200041a8036a4108100720014200370300200042003703e80341eefbc5004110200041e8036a100820022001290300370300200020002903e8033703880341002101200041003602a80320004188036a4110200041a8036a100621060240024020002802a8032202417f470d000c010b200020023602ec03200020063602e803200041a8036a200041e8036a107720002802a8032201450d0520002902ac0321042002450d002006102a0b200041e8036a41086a22024200370300200042003703e803419efcc500410f200041e8036a100820004188036a41086a22062002290300370300200020002903e80337038803200041a8036a20004188036a10ef0220002d00a8032103200041e8036a41186a220a200041c1036a290000370300200041e8036a41106a220b200041b9036a2900003703002002200041b1036a290000370300200020002900a9033703e8032001410820011b21050240024020034101460d0020004188036a41186a420037030020004188036a41106a42003703002006420037030020004200370388030c010b20004188036a41186a200a29030037030020004188036a41106a200b29030037030020062002290300370300200020002903e803370388030b200041e8026a41086a20004188036a41086a2903002209370300200041e8026a41106a20004188036a41106a290300220c370300200041e8026a41186a20004188036a41186a290300220d3703002000200029038803220e3703e802200041a8036a41086a2004420020011b370300200041a8036a41106a220a200e370300200041a8036a41186a2009370300200041c8036a200c370300200041a8036a41286a200d370300200020053602ac03200041003602a803200041003602f003200042013703e803410110282201450d05200041013602ec03200020002802f003220241016a3602f003200020013602e803200120026a41013a000020002802ac032102200041a8036a410c6a2802002201200041e8036a10b40102402001450d002002200141286c6a210503402002200041e8036a108f01200241206a29030021040240024020002802ec03220620002802f00322016b4108490d0020002802e80321060c010b200141086a22032001490d0a200641017422012003200120034b1b22014100480d0a0240024020060d002001102821060c010b20002802e80320062001102c21060b2006450d09200020013602ec03200020063602e80320002802f00321010b2000200141086a3602f003200620016a20043700002005200241286a2202470d000b0b200a200041e8036a10f10220004193036a200041f0036a280200360000200020002903e80322043703d8032000200437008b03200041e8036a410c6a2000418f036a290000370000200041c28289aa043600e903200041023a00e80320002000290088033700ed03200041e8036a10ce0120002802a8030d0020002802b003450d0020002802ac03102a0b200041d8026a200041d0026a20074101461b2903002104200041e8036a41086a22014200370300200042003703e803418efcc5004110200041e8036a100820004188036a41086a2001290300370300200020002903e80337038803200020043703a80320004188036a4110200041a8036a410810074100210120070d00200041a8036a41086a200041e0016a41086a290300370300200041a8036a41106a200041e0016a41106a2d00003a0000200020002800e3023600eb02200020002802e0023602e802200020002903e0013703a803410121010b200041e0016a41086a2008370300200041e0016a41106a20002903a803370300200041f8016a200041a8036a41086a29030037030020004180026a200041a8036a41106a2d00003a0000200020013a00e001200020002802e8023600e101200020002800eb023600e401200041e8036a41086a22024200370300200042003703e80341e7fcc5004110200041e8036a100820004188036a41086a2002290300370300200020002903e80337038803410110282202450d0620004201370274200020023602700240024020010d0020004101360278200241003a00000c010b20004101360278200241013a0000200041e0016a410172200041f0006a10f1020b2000280274210120004188036a411020002802702202200028027810072001450d002002102a0b20004190046a24000f0b41c4d1c3004133200041e8026a419cd9c3001038000b41c4d1c3004133200041e8026a419cd9c3001038000b410141011037000b200141011037000b1031000b410141011037000bec0501057f23004190016b2202240002400240410f10282203450d00200341002900edae44370000200341076a41002900f4ae443700002002428f808080f001370214200220033602102001200241106a108f012002280218210320022802102101200241e0006a41186a22044200370300200241e0006a41106a22054200370300200241e0006a41086a220642003703002002420037036020012003200241e0006a1000200241306a41186a2004290300370300200241306a41106a2005290300370300200241306a41086a20062903003703002002200229036037033002402002280214450d002002280210102a0b20024100360260200241306a4120200241e0006a100621040240024020022802602201417f470d00410021030c010b2002200136025420022004360250200241e0006a200241d0006a10d4012002280280012203450d02200241106a41186a200241e0006a41186a290300370300200241106a41106a200241e0006a41106a290300370300200241106a41086a200241e0006a41086a290300370300200241086a2002418c016a2802003602002002200229036037031020022002290284013703002001450d002004102a0b200241e0006a41086a2201200241106a41086a290300370300200241e0006a41106a2204200241106a41106a290300370300200241e0006a41186a2205200241106a41186a290300370300200241d0006a41086a2206200241086a2802003602002002200229031037036020022002290300370350024002402003450d002000200229036037030020002003360220200041246a2002290350370200200041186a2005290300370300200041106a2004290300370300200041086a20012903003703002000412c6a20062802003602000c010b2000420037030020004208370320200041186a4200370300200041106a4200370300200041086a4200370300200041286a41003602000b20024190016a24000f0b410f41011037000b41c4d1c3004133200241106a419cd9c3001038000b84fc0111067f017e037f017e027f017e047f017e037f017e017f0a7e017f027e017f0a7e2a7f230041a0196b22022400200241e00e6a41086a22034200370300200242003703e00e41cd9cc6004123200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f41002104200241003602f011200241900f6a4110200241f0116a10062103024002400240024002400240024002400240024020022802f0112205417f460d002003450d0020054104490d01200328000021042003102a0b2001417f6a2106200241e00e6a41086a22034200370300200242003703e00e418e9dc6004110200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a1006210302400240024020022802f0112201417f460d002003450d002001450d0220032d0000220141034f0d022003102a200141014b0d06024020010e020100010b200241e00e6a41086a22034200370300200242003703e00e418e9dc6004110200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241900f6a411010090c010b200620046b220320064b0d0520034106490d050b200241f0116a41086a22034200370300200242003703f01141c785c2004112200241f0116a1008200241e00e6a41086a2003290300370300200220022903f0113703e00e200241003602f011200241e00e6a4110200241f0116a1006210302400240024020022802f0112204417f460d002003450d00200220043602940f200220033602900f200241f0116a200241900f6a106d20022802f0112207450d0220022902f41121082004450d012003102a0c010b41012107420021080b410021090240024002402008422088a7220341057422010d004108210a4100210b0c010b2001410575220bad42d0007e220c422088a70d0c200ca722044100480d0c20041028220a450d010b2008a7210d02402003450d00200141606a210e200241f0116a41206a2103200a2105200721040340200441086a2900002108200441106a290000210c2004290000210f200241e00e6a41186a2210200441186a290000370300200241e00e6a41106a2211200c370300200241e00e6a41086a221220083703002002200f3703e00e200241900f6a200241e00e6a10ec02200241f0116a41186a2010290300370300200241f0116a41106a2011290300370300200241f0116a41086a2012290300370300200320022903900f370300200341086a200241900f6a41086a290300370300200341106a200241900f6a41106a290300370300200341186a200241900f6a41186a290300370300200341206a200241900f6a41206a290300370300200341286a200241900f6a41286a290300370300200220022903e00e3703f0112005200241f0116a41d000109a0541d0006a2105200441206a2104200141606a22010d000b200e41057641016a21090b0240200d450d002007102a0b200241e00e6a41086a22034200370300200242003703e00e41f09cc600411e200241e00e6a1008200241900f6a41086a22042003290300370300200220022903e00e3703900f200241f0116a200241900f6a10de030240024020022802f41122130d004104211342002114410021110c010b200241900f6a4110100920022802f011211120022903f81121140b10a003210820034200370300200242003703e00e41feadc4004117200241e00e6a100820042003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a1006210302400240024020022802f0112204417f470d004200210c0c010b024020030d004200210c0c010b20044108490d012003290000210c2003102a0b200241e00e6a41086a22154200370300200242003703e00e41feadc4004117200241e00e6a1008200241900f6a41086a22162015290300370300200220022903e00e3703900f200220083703f011200241900f6a4110200241f0116a41081007410021172008200c7d2218500d0620154200370300200242003703e00e41a5afc4004116200241e00e6a100820162015290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a1006210302400240024020022802f0112204417f460d002003450d00200220043602e40e200220033602e00e200241f0116a200241e00e6a106d20022802f0112219450d0220022902f411211a02402004450d002003102a0b201a422088a721040c010b410021044200211a410121190b4200210c200241e00e6a41086a22034200370300200242003703e00e4199fec4004111200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a1006210302400240024020022802f0112201417f470d004200210c4200211b0c010b024020030d004200211b0c010b20014110490d01200341086a290000211b2003290000210c2003102a0b200241800c6a10a102200241f00b6a20022903800c220f200241800c6a41086a2903002208428094ebdc03420010a005200241d00b6a200c201b2004ad4200109f05200241e00b6a20022903f00b221b200241f00b6a41086a290300221c4280ec94a37c427f109f052008200241d00b6a41086a290300221d20022903d00b221e200f56201d200856201d2008511b22031b2108200f201e20031b210c2018428086ebc7f5002018428086ebc7f500541b421f8042ffffffff0f83428094ebdc037e429880b5e50380211f200f20022903e00b7c210f410021034184c9c0002104024002400340024041accbc00020046b41184b0d000240200441accbc000460d000340200241c00b6a201b201c200435020022184200109f052003200c20022903c00b22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241c00b6a41086a2903002018202054ad7c22205a200820205122011b6a2103200c201854200820205420011b0d0441accbc000200441086a2204470d000b0b200241b00b6a201b201c42e8aafa0b4200109f05200241b80b6a29030020022903b00b220c200f42e8aafa0b7e428094ebdc038042ffffffff0f837c2208200c54ad7c210c0c030b200241a00b6a201b201c200435020022184200109f052003200c20022903a00b22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241a00b6a41086a2903002018202054ad7c22205a200820205122011b6a2103200c201854200820205420011b0d01200241900b6a201b201c200441086a35020022184200109f052003200c20022903900b22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241900b6a41086a2903002018202054ad7c22205a200820205122011b6a2103200c201854200820205420011b0d01200241800b6a201b201c200441106a35020022184200109f052003200c20022903800b22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241800b6a41086a2903002018202054ad7c22205a200820205122011b6a2103200c201854200820205420011b0d01200241f00a6a201b201c200441186a35020022184200109f052003200c20022903f00a22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241f00a6a41086a2903002018202054ad7c22205a200820205122011b6a2103200441206a2104200c201854200820205420011b450d000b0b02402003417f6a220420034d0d00200241f0096a201b201c42c0f0f50b4200109f05200241f8096a29030020022903f009220c200f42288042ffffffff0f837c2208200c54ad7c210c0c010b02400240200441244b0d00200241e00a6a201b201c200441037422014184c9c0006a2802002205ad22184200109f05200241c00a6a200c20022903e00a22202018200f7e428094ebdc038042ffffffff0f837c2218200c2018562008200241e00a6a41086a2903002018202054ad7c22205620082020511b22041b22212018200c20041b220c7d22182008202020041b2020200820041b7d2021200c54ad7d4100200341037422104184c9c0006a280200220320056b2205200520034b1b22034101200341014b1bad2208420010a005200241b00a6a20022903c00a220c200241c00a6a41086a290300222020084200109f05200241d00a6a201b201c20014188c9c0006a2802002203ad22214200109f05200241800a6a2020420020104188c9c0006a28020022012003200120034b22051b2003200120051b6bad221b4200109f05200241a00a6a200c4200201b4200109f05200241900a6a42004200200c4200109f05427f427f200241a00a6a41086a290300220c20022903800a20022903900a7c7c221c20022903880a20022903980a84420052201c200c547222051b221c427f20022903a00a20051b220c201820022903b00a7d201b7e2008807c2208200c542205ad7c221b2005201b201c542008200c5a1b22051b211c427f200820051b211b200241d00a6a41086a29030020022903d00a22082021200f7e428094ebdc038042ffffffff0f837c220c200854ad7c21082004200120034d730d0142002008201c7d200c201b54ad7d220f200c201b7d221b200c56200f200856200f2008511b22031b210c4200201b20031b21080c020b41acd9c300200441251034000b427f2008201c7c200c201b7c220f200c542203ad7c220c2003200c200854200c2008511b22031b210c427f200f20031b21080b42002122200241e0096a2008200c428094ebdc03420010a005200241d0096a20022903e009220c200241e0096a41086a290300220f4280ec94a37c427f109f05200241c0096a200c200f201f4200109f05201f200820022903d0097c7e428094ebdc038021080240201a422088a722030d00420021230c080b20132014422088a74102746a210e201920034105746a2124200241c0096a41086a29030020022903c009220c200842ffffffff0f837c2225200c54ad7c2126200241f0116a41086a2127200241900f6a41086a21122011ad21284200212242002123201321052019211003402005200e460d08024020052802002203450d00024002400240024002402011450d00200241b0096a202520262028420010a005200241a0096a20022903b0092208200241b0096a41086a290300220c20284200109f0520024190096a2008200c20112003200320114b1bad220f4200109f05202520022903a0097d200f7e2028802108200229039009210f20024190096a41086a290300211c411210282203450d01200341002900c1ae44370000200341106a41002f00d1ae443b0000200341086a41002900c9ae4437000020024292808080a0023702f411200220033602f0112010200241f0116a108f0120022802f811210320022802f0112104200241900c6a41186a22014200370300200241900c6a41106a22074200370300200241900c6a41086a220d4200370300200242003703900c20042003200241900c6a1000200241c00d6a41186a2001290300370300200241c00d6a41106a2007290300370300200241c00d6a41086a200d290300370300200220022903900c3703c00d024020022802f411450d0020022802f011102a0b200241003602f011200241c00d6a4120200241f0116a1006210320022802f0112204417f460d032003450d03200220043602f411200220033602f011200241f8086a200241f0116a109f0120022903f808a70d02200241f8086a41106a290300210c200229038009211b2004450d042003102a0c040b41acfec4001032000b411241011037000b41c4d1c300413320024198196a419cd9c3001038000b4200211b4200210c0b0240024002400240024002400240200f200842ffffffff0f837c2208201b2008201b200854200c201c2008200f54ad7c220f54200c200f511b22031b22297d222a200f200c200f20031b222b7d2008202954ad7d222c8450450d004200211f4200211c420021084200210c0c010b200241f0116a201010ec0220272903002208420020022903f011220c42015620084200522008501b22031b2108200c420120031b210f20022802901221070240024020022802981222030d004200211f200241f0076a200f2008428094ebdc03420010a005200241f0076a41086a290300212d20022903f007212e4200211c0c010b2007200341306c6a21014200211f200241e8086a200f2008428094ebdc03420010a005200241c8086a202a202c428094ebdc03420010a005200241d8086a202a202c428094ebdc03420010a105200241e8086a41086a290300222d420020022903e808222e420156202d420052202d501b22031b2118202e420120031b2120200241c8086a41086a290300212f20022903c808213020022903d80821314200211c200721030340200241b8086a200f2003290300220c200c200f56200341086a290300220c200856200c2008511b22041b2008200c20041b2020201810a00520022903b808221b428080808010544100200241b8086a41086a290300501b450d03200241a8086a200f20082020201810a00520022903a808220c428080808010544100200241a8086a41086a290300501b450d04024002400240200ca7450d0020024180086a2030202f201b42ffffffff0f83428094ebdc037e200c42ffffffff0f838042ffffffff0f83220c4200109f0520024190086a200341106a2203200229038008221b200c20317e428094ebdc038042ffffffff0f837c220c20024180086a41086a290300200c201b54ad7c10b404200229039008210c200229039808211b200241900f6a41106a20024190086a41106a29030022213703002002201b3703980f2002200c3703900f0240200ca74101470d00427f201c20217c201f201b7c221b201f542204ad7c220c2004200c201c54200c201c511b22041b211c427f201b20041b211f0c030b200c4201510d010c020b41acaac3001032000b200220123602e00e200241e00e6a109c010b200341206a22032001470d000b0b200241e0076a200f200229038012220c200c200f56200241f0116a41186a290300220c200856200c2008511b22031b2008200c20031b202e4201202e420156202d420052202d501b22031b220c202d420020031b221b10a00520022903e0072218428080808010544100200241e0076a41086a290300501b450d01200241d0076a200f2008200c201b10a00520022903d0072208428080808010544100200241d0076a41086a290300501b450d022008a7450d03200241c0076a202a202c428094ebdc03420010a005200241b0076a20022903c007220c200241c0076a41086a290300220f4280ec94a37c427f109f05200241a0076a200c200f201842ffffffff0f83428094ebdc037e200842ffffffff0f838042ffffffff0f8322084200109f0520022903a007220c2008202a20022903b0077c7e428094ebdc038042ffffffff0f837c2208200c54ad210c200241a0076a41086a290300210f0240200228029412450d002007102a0b200f200c7c210c0b20024188076a2010200820297c220f200c202b7c200f200854ad7c10b4042002290388072108200229039007210c200241f0116a41106a20024188076a41106a290300220f3703002002200c3703f811200220083703f01102402008a74101470d00427f201c200f7c201f200c7c220c201f542203ad7c220820032008201c542008201c511b22031b211c427f200c20031b211f0c050b20084201510d030c040b10d101000b10d201000b41acaac3001032000b200220273602900f200241900f6a109c010b427f2023201c7c2022201f7c220c2022542203ad7c22082003200820235420082023511b22031b2123427f200c20031b21220b200541046a2105201041206a22102024470d000c080b0b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b200441081037000b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b02402014a7450d002013102a0b20024188126a202337030020024180126a2022370300200241f8116a41003a0000200241033a00f0114101211741014100200241f0116a10cc01200220233703f811200220223703f0112002200241f0116a3602900f200241900f6a109c0102402022202384500d00201e201d84500d00200241f8066a10a10220022903f8062208201e7d220f200856200241f8066a41086a290300220c201d7d2008201e54ad7d2208200c562008200c511b0d00200241e8066a200f2008201e201d10a005200241b8066a200241e8066a41086a2903002208420020224200109f05200241c8066a2023420020022903e806220c4200109f05200241d8066a200c420020224200109f05200842005220234200527120022903c0064200527220022903d00642005272200241d8066a41086a290300220820022903b80620022903c8067c7c220f200854720d0020022903d806211b200241e00e6a41086a22034200370300200242003703e00e41ace1c0004116200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a100621030240024020022802f0112204417f460d002003450d00024020044110490d00200341086a290000210c200329000021082003102a0c020b41c4d1c300413320024198196a419cd9c3001038000b420021084200210c0b200241e00e6a41086a22034200370300200242003703e00e41ace1c0004116200241e00e6a1008200241900f6a41086a22042003290300370300200220022903e00e3703900f2002427f200c200f7c2008201b7c22182008542203ad7c221c2003201c200c54201c200c511b22031b3703f8112002427f201820031b3703f011200241900f6a4110200241f0116a41101007200241f0116a10d301200241a8066a200241f0116a2008427f85201b20031b2208200c427f85200f20031b220c10d001200241900f6a41106a200c200241a8066a41086a290300221b7d200820022903a806220f54ad7d201b200c7d200f200854ad7d200f200858201b200c58201b200c5122031b22011b37030020022008200f7d200f20087d20011b3703980f2002200f200856201b200c5620031b2203ad3703900f024020030d00200220043602e00e200241e00e6a109d010c010b200220043602e00e200241e00e6a109c010b201aa7450d002019102a0b20154200370300200242003703e00e41bb9cc6004112200241e00e6a100820162015290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a10062103024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022802f0112204417f470d00410021270c010b024020030d00410021270c010b20044104490d01200328000021272003102a0b200241e00e6a41086a22034200370300200242003703e00e41bb9cc6004112200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f2002202741016a22163602f011200241900f6a4110200241f0116a41041007411710282203450d012003410f6a41002900d3fe44370000200341086a41002900ccfe44370000200341002900c4fe4437000020034117412e102c2203450d0220032027360017200241900c6a41186a22044200370300200241900c6a41106a22014200370300200241900c6a41086a22054200370300200242003703900c2003411b200241900c6a1000200241c00d6a41186a2004290300370300200241c00d6a41106a2001290300370300200241c00d6a41086a2005290300370300200220022903900c3703c00d2003102a200241c00d6a41201009200241e00e6a41086a22034200370300200242003703e00e41cd9cc6004123200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a10062103024020022802f0112204417f460d002003450d00200441034d0d042003102a0b200241e00e6a41086a22154200370300200242003703e00e41cd9cc6004123200241e00e6a1008200241900f6a41086a22192015290300370300200220022903e00e3703900f200220063602f011200241900f6a4110200241f0116a41041007201641a105490d0920154200370300200242003703e00e41b99dc6004112200241e00e6a100820192015290300370300200220022903e00e3703900f41002112200241003602f011200241900f6a4110200241f0116a100621320240024020022802f0112233417f470d000c010b024020320d000c010b200220333602f411200220323602f011200241a0066a200241f0116a106c20022802a0060d2e20022802f41122104178712203417f4c0d2020022802a406210e02400240201041037622070d00410421120c010b200310282212450d060b0240200e450d004100211141002105410021010340200241003602e00e02400240024020104104490d0020022010417c6a22103602f411200220022802f011220341046a3602f0112003280000210d200241003602e00e20104104490d00200141016a210420022010417c6a22103602f4112002200341086a3602f0112003280004210320012007470d0220112004201120044b1b220741ffffffff01712007470d342007410374222441004e0d010c340b2007450d322012102a0c320b0240024020010d002024102821120c010b201220052024102c21120b2012450d090b201220056a2201200d360200200141046a2003360200201141026a2111200541086a210520042101200e2004470d000b0b2012450d2e200ead4220862007ad8421082033450d002032102a0b2012410420121b210e02402008420020121b2208422088220ca722032008a7470d00200341016a22042003490d2f200ca722054101742201200420042001491b220441ffffffff01712004470d2f200441037422014100480d2f0240024020030d0020011028210e0c010b200e20054103742001102c210e0b200e450d072008422088a721032004ad21080b202741e17a6a2104200e20034103746a2201200636020420012016360200200e200341016a22114103746a2110410021030240201141044f0d00200e21010c080b200e2105024003402005220128020020044f0d0a0240200141086a2802002004490d00200341016a21030c0b0b0240200141106a2802002004490d00200341026a21030c0b0b200141186a28020020044f0d01200341046a21032010200141206a22056b41184b0d000b200141206a21010c080b200341036a21030c080b41c4d1c300413320024198196a419cd9c3001038000b411741011037000b412e41011037000b41c4d1c300413320024198196a419cd9c3001038000b200341041037000b202441041037000b200141041037000b20012010460d00200e20114103746a21050340200128020020044f0d01200341016a21032005200141086a2201470d000b0b20112003490d01200842ffffffff0f8321080240201120036b2207450d0002402003450d00200e200e20034103746a2007410374109b051a0b200e280204210d200241e00e6a41086a22124200370300200242003703e00e418199c6004113200241e00e6a1008200241900f6a41086a22242012290300370300200220022903e00e3703900f200241f0116a200241900f6a411010c6024101210320022902f411210c0240024020022802f01122044101460d00200441014621030c010b200c422088a72206200d200d20064b1b2211200ca72204490d000240201120044d0d000340411a10282203450d06200341186a41002f00e0bb403b0000200341106a41002900d8bb40370000200341086a41002900d0bb40370000200341002900c8bb403700002003411a4134102c2203450d072003200436001a200241900c6a41186a22014200370300200241900c6a41106a22054200370300200241900c6a41086a22104200370300200242003703900c2003411e200241900c6a1000200241b00c6a41186a2001290300370300200241b00c6a41106a2005290300370300200241b00c6a41086a2010290300370300200220022903900c3703b00c2003102a200241b00c6a41201009200441016a2203210420112003470d000b0b200d2006492103200c428080808070832011ad84210c0b20124200370300200242003703e00e418199c6004113200241e00e6a100820242012290300370300200220022903e00e3703900f0240024020030d00200241900f6a411010090c010b410810282203450d062003200c422088a73600042003200ca7360000200241900f6a41102003410810072003102a0b20082007ad4220868421080b200241e00e6a41086a22034200370300200242003703e00e41b99dc6004112200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f0240200e0d00200241900f6a411010090c010b200241003602f811200242013703f0112008422088a72203200241f0116a10b4010240024020030d0020022802f811210320022802f411210120022802f01121040c010b200e20034103746a2106410020022802f81122116b210520022802f4112101410021030340201120036a2110200e20036a2212280200210702400240200120056a4104490d0020022802f01121040c010b201041046a22042010490d282001410174220d2004200d20044b1b220d4100480d280240024020010d00200d102821040c010b20022802f0112001200d102c21040b2004450d082002200d3602f411200220043602f011200d21010b2002201041046a220d3602f811200420116a20036a2007360000201241046a28020021070240200120056a417c6a41034b0d00200d41046a2224200d490d282001410174220d2024200d20244b1b220d4100480d280240024020010d00200d102821040c010b20042001200d102c21040b2004450d092002200d3602f411200220043602f011200d21010b2002201041086a3602f811200420116a20036a41046a2007360000200541786a2105200341086a2103201241086a2006470d000b201120036a21030b2008a72105200241900f6a411020042003100702402001450d002004102a0b2005450d00200e102a0b20154200370300200242003703e00e41889cc6004116200241e00e6a100820192015290300370300200220022903e00e3703900f41002134200241003602f011200241900f6a4110200241f0116a10062103024020022802f0112204417f460d002003450d0020044104490d07200328000021342003102a0b200241e00e6a41086a22034200370300200242003703e00e419e9cc600411d200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a10062103024002400240024020022802f0112204417f460d0020030d010b410421040c010b20044104490d09200328000021042003102a41012115200441014d0d010b200421150b200241900c6a41186a22034200370300200241900c6a41106a22044200370300200241900c6a41086a22014200370300200242003703900c41d3aec400411a200241900c6a1000200241f0116a41186a2003290300370300200241f0116a41106a2004290300370300200241f0116a41086a2001290300370300200220022903900c3703f011200241900e6a200241f0116a412010fd01200241e00e6a41206a200241900e6a41206a2d00003a0000200241e00e6a41186a200241900e6a41186a290300370300200241e00e6a41106a200241900e6a41106a290300370300200241e00e6a41086a200241900e6a41086a290300370300200220022903900e3703e00e200241f0116a200241e00e6a10ab010240024020022903f0114201510d004101211141002105410021060c010b200220022f01f8113b01e00c2002200229008b123703d00c2002200241fa116a2d00003a00e20c2002200241f0116a41206a2900003700d50c200241fb116a2800002103200241ff116a280000210420024183126a280000210120024187126a2800002105412010282211450d09201120022f01e00c3b00002011200536000f2011200136000b2011200436000720112003360003201120022903d00c370013201141026a20022d00e20c3a0000201141186a20022900d50c370000200241900f6a41206a200241e00e6a41206a2d00003a0000200241900f6a41186a200241e00e6a41186a290300370300200241900f6a41106a200241e00e6a41106a290300370300200241900f6a41086a200241e00e6a41086a290300370300200220022903e00e3703900f200241f0116a200241900f6a10ab0141012105024020022903f0114201510d00410121060c010b200241f0116a41086a2103410221104120210141012105410121060340200241b00c6a41186a200341186a2903002208370300200241b00c6a41106a200341106a290300220c370300200241b00c6a41086a200341086a290300220f37030020022003290300221b3703b00c200241900c6a41186a22122008370300200241900c6a41106a2207200c370300200241900c6a41086a220d200f3703002002201b3703900c024020052006470d00200541016a22042005490d2720102004201020044b1b220641ffffff3f712006470d27200641057422044100480d270240024020050d002004102821110c010b201120012004102c21110b2011450d110b201120016a220420022903900c370000200441186a2012290300370000200441106a2007290300370000200441086a200d290300370000201041026a2110200141206a2101200541016a2105200241f0116a200241900f6a10ab0120022903f0114201510d000b0b200241900c6a41186a22034200370300200241900c6a41106a22044200370300200241900c6a41086a22014200370300200242003703900c41a7aec400411a200241900c6a1000200241f0116a41186a2003290300370300200241f0116a41106a2004290300370300200241f0116a41086a2001290300370300200220022903900c3703f011200241e00d6a200241f0116a412010fd01200241900e6a41206a200241e00d6a41206a2d00003a0000200241900e6a41186a200241e00d6a41186a290300370300200241900e6a41106a200241e00d6a41106a290300370300200241900e6a41086a200241e00d6a41086a290300370300200220022903e00d3703900e200241f0116a200241900e6a10ad01024002402002280290120d004104213541002104410021360c010b412c10282235450d0a203520022903f011370200203541286a200241f0116a41286a2212280200360200203541206a200241f0116a41206a2207290300370200203541186a200241f0116a41186a220d290300370200203541106a200241f0116a41106a220e290300370200203541086a200241f0116a41086a2224290300370200200241e00e6a41206a200241900e6a41206a2d00003a0000200241e00e6a41186a200241900e6a41186a290300370300200241e00e6a41106a200241900e6a41106a290300370300200241e00e6a41086a200241900e6a41086a290300370300200220022903900e3703e00e200241900f6a200241e00e6a10ad01024020022802b00f0d0041012104410121360c010b41022110412c2101410121044101213603402012200241900f6a41286a2802003602002007200241900f6a41206a290300370300200d200241900f6a41186a290300370300200e200241900f6a41106a2903003703002024200241900f6a41086a290300370300200220022903900f3703f011024020042036470d00200441016a22032004490d2720102003201020034b1b2236ad422c7e2208422088a70d272008a722034100480d270240024020040d002003102821350c010b203520012003102c21350b2035450d0d0b203520016a220320022903f011370200200341286a2012280200360200200341206a2007290300370200200341186a200d290300370200200341106a200e290300370200200341086a2024290300370200201041026a21102001412c6a2101200441016a2104200241900f6a200241e00e6a10ad0120022802b00f0d000b0b200242003702ec0c200241f8b9c0003602e80c200420056a2201ad42d0007e2208422088a70d152008a72203417f4c0d150240024020030d00410821100c010b200310282210450d0c0b200241003602c80e200220013602c40e200220103602c00e200241900e6a41206a200241e80c6a360200200241003602a80e200241a40e6a20024198196a36020020022011200541057422016a220d36029c0e200220113602980e200220063602940e200220113602900e2002200241c00e6a3602ac0e200220024198196a3602a00e410221244101210e0240024020050d00201121030c010b4200211b2011210302400340200341086a2900002108200341106a290000210c2003290000210f200241f0116a41186a2205200341186a290000370300200241f0116a41106a2210200c370300200241f0116a41086a221220083703002002200f3703f01120024190066a200241f0116a10b004200241b00c6a41086a22072012290300370300200241b00c6a41106a22122010290300370300200241b00c6a41186a22102005290300370300200220022903f0113703b00c20024190066a41086a290300210c200229039006210f20024180066a10a102200241f0056a20022903800620024180066a41086a290300427f420010a005200241e0056a200f200c20022903f005220842012008420156200241f0056a41086a29030022084200522008501b22051b2008420020051b10a005200241900c6a41086a2007290300370300200241900c6a41106a2012290300370300200241900c6a41186a2010290300370300200220022903b00c3703900c20022903e005220850450d01200341206a2103200141606a22010d000b2002200d3602980e200d21030c010b200220022f01900c3b01e00c200220022d00920c3a00e20c200220022900a30c3703d00c200220022800f80c3602b80d2002200341206a22033602980e2002200241a80c6a2900003700d50c2002200241fb0c6a2800003600bb0d20022800930c210120022800970c2112200228009b0c2110200228009f0c2105200220022d00e20c3a00a20d200220022f01e00c3b01a00d200220022900d50c3700f511200220022903d00c3703f011200220022800bb0d3600c30d200220022802b80d3602c00d200220022d00a20d3a00aa0d200220022f01a00d3b01a80d200220022900f5113700e50e200220022903f0113703e00e200220022800c30d3600b30d200220022802c00d3602b00d4100210e410021240b200220022f01a80d3b01c00d200220022d00aa0d3a00c20d200220022903e00e3703f011200220022900e50e3700f511200220022802b00d3602a00d200220022800b30d3600a30d024002400240200e450d00200241023a00d00f0c010b200220022d00c20d3a009a0d200220022f01c00d3b01980d200220022903f0113703e00d200220022900f5113700e50d200220022802a00d3602880d200220022800a30d36008b0d200241013602a80e200220022d009a0d3a00960d200220022f01980d3b01940d200220022900e50d3700d50e200220022903e00d3703d00e20024190126a201b37030020024188126a200837030020024180126a4200370300200241a7126a2005360000200241a3126a20103600002002419f126a20123600002002419b126a2001360000200242003703f811200242003703f01120024198126a20022f01940d3b01002002419a126a20022d00960d3a0000200241f0116a41c8006a20243a0000200241ab126a20022903d00e370000200241b0126a20022900d50e370000200241bc126a200228008b0d360000200241b9126a20022802880d360000200241900f6a200241ac0e6a200241f0116a10fb0220022d00d00f4102470d010b02402003200d460d002002200d20036b41606a41607120036a41206a3602980e0b410021372006450d142011102a0c140b41c80010282238450d0c2038200241900f6a41c800109a051a200241e00e6a41086a200241900e6a41086a2903002208370300200241e00e6a41206a200241900e6a41206a280200360200200241e00e6a41186a200241900e6a41186a290300370300200241e00e6a41106a200241900e6a41106a290300370300200220022903900e3703e00e410121102008a7220320022802ec0e2201460d10200241b9126a210e200241fc0e6a21274200211b02400340200341086a2900002108200341106a290000210c2003290000210f200241f0116a41186a2205200341186a290000370300200241f0116a41106a2211200c370300200241f0116a41086a221220083703002002200f3703f011200241d0056a200241f0116a10b004200241b00c6a41086a22072012290300370300200241b00c6a41106a22122011290300370300200241b00c6a41186a22112005290300370300200220022903f0113703b00c200241d0056a41086a290300210c20022903d005210f200241c0056a10a102200241b0056a20022903c005200241c0056a41086a290300427f420010a005200241a0056a200f200c20022903b005220842012008420156200241b0056a41086a29030022084200522008501b22051b2008420020051b10a005200241900c6a41086a2007290300370300200241900c6a41106a2012290300370300200241900c6a41186a2011290300370300200220022903b00c3703900c20022903a005220850450d012001200341206a2203470d000b200220013602e80e200121030c110b200220022f01900c3b01e00c200220022d00920c3a00e20c200220022900a30c3703d00c200220022800f80c3602b80d2002200341206a22033602e80e2002200241900c6a41186a220d2900003700d50c2002200241f80c6a41036a22392800003600bb0d20022800930c211120022800970c2112200228009b0c2107200228009f0c2116200220022d00e20c3a008a0d200220022f01e00c3b01880d200220022900d50c3700e50d200220022903d00c3703e00d200220022800bb0d3600b30d200220022802b80d3602b00d20024198126a2124200241a30c6a213a20022802f80e2105200241f0116a410472220641086a2133200641106a213b200241ab126a223c41056a213d41012110410121370340200220022d008a0d22193a00aa0d200220022f01880d22323b01a80d200220022903e00d3703c00d200220022900e50d3700c50d200220022802b00d3602a00d200220022800b30d3600a30d200220193a00960d200220323b01940d2002200541016a22193602f80e200220022900c50d3700d50e200220022903c00d3703d00e200241f0116a41206a201b3703002006420037020020334200370200203b41003602002002200837038812200220053602f011202420022f01940d3b0100202441026a20022d00960d3a0000200220163600a712200220073600a3122002201236009f122002201136009b12203c20022903d00e370000203d20022900d50e370000200241003a00b812200e41036a20022800a30d360000200e20022802a00d360000200241900f6a2027200241f0116a10fb02024020022d00d00f4102470d00203821110c140b200241f0116a200241900f6a41c800109a051a024020372010470d00201041016a22052010490d26201041017422112005201120054b1b2237ad42c8007e2208422088a70d262008a722054100480d260240024020100d002005102821380c010b2038201041c8006c2005102c21380b2038450d0f0b2038201041c8006c6a200241f0116a41c800109a051a201041016a2110024020032001470d00200121030c130b02400340200241f0116a41186a2205200341186a290000370300200241f0116a41106a2211200341106a290000370300200241f0116a41086a2212200341086a290000370300200220032900003703f01120024190056a200241f0116a10b004200241b00c6a41086a22072012290300370300200241b00c6a41106a22122011290300370300200241b00c6a41186a22112005290300370300200220022903f0113703b00c20024190056a41086a290300210c200229039005210f20024180056a10a1024200211b200241f0046a20022903800520024180056a41086a290300427f420010a005200241e0046a200f200c20022903f004220842012008420156200241f0046a41086a29030022084200522008501b22051b2008420020051b10a005200241900c6a41086a2007290300370300200241900c6a41106a2012290300370300200d2011290300370300200220022903b00c3703900c20022903e004220850450d012001200341206a2203460d120c000b0b200220022f01900c3b01e00c200220022d00920c3a00e20c200220022800f80c3602b80d2002200341206a22033602e80e2002203a2900003703d00c2002203a41056a2900003700d50c200220392800003600bb0d20022800930c211120022800970c2112200228009b0c2107200228009f0c2116200220022d00e20c3a008a0d200220022f01e00c3b01880d200220022900d50c3700e50d200220022903d00c3703e00d200220022800bb0d3600b30d200220022802b80d3602b00d201921050c000b0b41e4e8c5001032000b411a41011037000b413441011037000b410841011037000b200d41011037000b200d41011037000b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b412041011037000b412c41041037000b200341041037000b200341081037000b41c80041081037000b200541081037000b200441011037000b200220013602e80e200121030c010b410121370b20382111200241023a00d00f0b024020032001460d002002200120036b41606a41607120036a41206a3602e80e0b20022802e40e450d0120022802e00e102a0c010b4108213841082111410021100b0240024002400240024002400240024020102015490d000240024020022802c40e220320022802c80e223d6b2004412c6c2201412c6d2205490d0020022802c00e21030c010b203d20056a2205203d490d18200341017422122005201220054b1b2205ad42d0007e2208422088a70d182008a722124100480d180240024020030d002012102821030c010b20022802c00e200341d0006c2012102c21030b2003450d02200220053602c40e200220033602c00e20022802c80e213d0b203520016a213e024020040d002035213b0c070b2003203d41d0006c6a2133203521030340200241c00d6a41186a2204200341186a290200370300200241c00d6a41106a2201200341106a290200370300200241c00d6a41086a2205200341086a290200370300200220032902003703c00d2003412c6a213b2003280220223c450d07200341286a2802002124200341246a280200213a200241900f6a41186a22392004290300370300200241900f6a41106a223f2001290300370300200241900f6a41086a22402005290300370300200220022903c00d3703900f200241d0046a200241900f6a10b0042024ad42387e2208422088a70d092008a72203417f4c0d09200241d0046a41086a290300211c20022903d00421180240024020030d00410821150c010b200310282215450d040b0240024020240d0041002124410021060c010b203c20244105746a213241002106203c21070340200741086a2900002108200741106a290000210c2007290000210f200241f0116a41186a2227200741186a290000370300200241f0116a41106a2216200c370300200241f0116a41086a221920083703002002200f3703f011200741206a2107200241e80c6a210320022802ec0c210d024003402003280200221241086a210420122f0106220e4105742103410021010240024003402003450d01200241f0116a20044120109c052205450d02200341606a2103200141016a2101200441206a21042005417f4a0d000b2001417f6a210e0b200d450d02200d417f6a210d2012200e4102746a4194036a21030c010b0b2010201220014102746a41e8026a220328020022044d0d072011200441c8006c6a22042903102108200441186a290300210c200241c0046a10a102200241b0046a20022903c004200241c0046a41086a290300427f420010a0052010200328020022044d0d08200241a0046a2018201c20022903b004220f4201200f420156200241b0046a41086a290300220f420052200f501b22011b200f420020011b10a0052011200441c8006c6a220441186a427f200c200820022903a0047c220f2008542201ad7c221b2001201b200c54200f20085a1b22011b3703002004427f200f20011b370310200241900c6a41186a22042027290300370300200241900c6a41106a22012016290300370300200241900c6a41086a22052019290300370300200220022903f0113703900c200328020021120240024020062024460d00200621030c010b202441016a22032024490d1c2024410174220d2003200d20034b1b220dad42387e2208422088a70d1c2008a722034100480d1c0240024020240d002003102821150c010b2015202441386c2003102c21150b2015450d0a20242103200d21240b2015200341386c6a220342003703082003420037030020032012360210200320022903900c3702142003411c6a2005290300370200200341246a20012903003702002003412c6a2004290300370200200641016a21060b20072032470d000b0b0240203a450d00203c102a0b200241b00c6a41186a22032039290300370300200241b00c6a41106a2204203f290300370300200241b00c6a41086a22012040290300370300200220022903900f3703b00c20024190046a10a10220024180046a20022903900420024190046a41086a290300427f420010a005200241f0036a2018201c20022903800422084201200842015620024180046a41086a29030022084200522008501b22051b2008420020051b10a00520334200370308203320022903f00337030020334200370310203341186a4200370300203320063602282033202436022420332015360220203320022903b00c37022c203341346a20012903003702002033413c6a2004290300370200203341c4006a2003290300370200203d41016a213d203341d0006a2133203b2103203b203e470d000b2002203d3602c80e0c070b02402037450d002038102a0b024020022802c80e2203450d00200341d0006c210120022802c00e41206a210303400240200341046a280200450d002003280200102a0b200341d0006a2103200141b07f6a22010d000b0b024020022802c40e450d0020022802c00e102a0b20022802e80c20022802ec0c20022802f00c10bc0202402004450d002004412c6c2104203541206a210303400240200341046a280200450d002003280200102a0b2003412c6a2103200441546a22040d000b0b2036450d0f2035102a0c0f0b201241081037000b200341081037000b41a09ec400200420101034000b41b09ec400200420101034000b200341081037000b2002203d3602c80e203b203e460d000340203b41206a2802002204450d01203b412c6a21030240203b41246a280200450d002004102a0b2003213b203e2003470d000b0b02402036450d002035102a0b2034ad42307e2208422088a70d002008a72203417f4c0d00024002400240024020030d00410821060c010b200310282206450d010b2034412c6c2203417f4c0d0202400240024020030d004104213f0c010b20031028223f450d010b4100213602402010203420102034491b223b0d0020342141410021390c030b2011201041c8006c22356a2127200241f0116a41106a2132200241f0116a41086a213320112103203421164100213941002119034002402010450d002035210403400240200341c0006a2d00000d00200241e0036a427f427f200341106a290300220842012008420156200341186a29030022084200522008501b22011b2008420020011b10a0052003200241e0036a41086a290300370308200320022903e0033703000b200341c8006a2103200441b87f6a22040d000b0b20022802c00e220520022802c80e220e41d0006c6a211502400240024002400240200e450d00200521120340024020122802282203450d00200341386c2101201228022041106a210303402010200328020022044d0d0402402011200441c8006c6a22042d00400d002004290310220c200441186a290300220f84500d00200241d0036a2012290300220842004280808080104200109f05200241a0036a4200420020084200109f05200241c0036a427f20022903d003201241086a290300220842ffffffff0f8320085220022903a80342005272200241d0036a41086a290300221b200842208620022903a0037c7c2208201b547222071b427f200820071b200c200f10a005200241b0036a201241146a350200201241186a290300220842208684200842208820022903c003200241c0036a41086a290300109f052004427f2004290300220820022903b0037c220c200c2008542207200441086a220d2903002208200241b0036a41086a2903007c2007ad7c220c200854200c2008511b22071b370300200d427f200c20071b3703000b200341386a2103200141486a22010d000b0b201241d0006a22122015470d000b0b201941016a21192011201041c8006c6a21122035210420112103024003402003210102400240201220036b41d8014d0d00200141c0006a2d00000d01200141c8006a21030c070b0340024020040d00201621410c0c0b200441b87f6a2104200141c0006a2107200141c8006a2203210120072d00000d000b200341b87f6a21010c060b20014188016a2d0000450d01200141d0016a2d0000450d03200441e07d6a2104200141a0026a210320014198026a2d00000d000b410321040c030b20014190016a2103410121040c020b41bcc0c200200420101034000b200141d8016a2103410221040b2001200441c8006c6a21010b024020032012460d00200141086a29030021082001290300210c0340200341c8006a21040240200341c0006a2d00000d00200341086a290300220f2008200c2003290300221b562008200f562008200f511b22121b2108201b200c20121b210c2003200120121b21010b2004210320272004470d000b0b200141013a00400240200e450d002001410c6a210d200141206a210e0340200541d0006a2124024020052802282204450d0020052802202103200441386c2104034002400240200d2003460d00200341146a200e4120109c050d010b200541186a22122903002108200141086a2207290300210c20032001290300220f2005290310221b7d3703002003200c20087d200f201b54ad7d3703082001290300210820122007290300370300200520083703100b200341386a2103200441486a22040d000b0b2024210520242015470d000b0b200129031021082032200141306a2900003703002033200141286a290000370300200141186a290300210c200241f0116a41186a2203200141386a290000370300200220012900203703f01102400240024020392016460d00201621410c010b201641016a22042016490d15201641017422012004200120044b1b2241ad42307e220f422088a70d15200fa722044100480d150240024020160d002004102821060c010b2006201641306c2004102c21060b2006450d0120162139204121160b2033290300210f2032290300211b2003290300211c20022903f01121182006203941306c6a2203200837032020032018370300200341286a200c370300200341186a201c370300200341106a201b370300200341086a200f370300203941016a2139201121032019203b4f0d040c010b0b200441081037000b200341041037000b200341081037000b024020022802c80e2203450d0020022802c00e2235200341d0006c6a2140200641e0006a213b2006203941306c22036a210d200241900e6a41186a213c200241900e6a41106a213d200241900e6a41086a213a20034191014921334100213602400340203c203541c4006a290000370300203d2035413c6a290000370300203a203541346a2900003703002002203529002c3703900e024020352802282203450d0020352802202204200341386c6a21322035412c6a211641002127410821194100211503402006210302400240024020330d00203b2103024002400240200441146a2201200241f0116a46220e450d0020062903202108200641086a290300210c200641106a290300210f200641186a290300211b2006290300211c200241f0116a41286a200641286a290300370300200241f0116a41186a201b370300200241f0116a41106a200f370300200241f0116a41086a200c37030020022008370390122002201c3703f0110c010b024002400340200341406a22102903002108200341a07f6a2205290300210c200541086a290300210f200541106a290300211b200541186a290300211c200241f0116a41286a2205201041086a290300370300200241f0116a41186a2210201c370300200241f0116a41106a2211201b370300200241f0116a41086a2212200f37030020022008370390122002200c3703f011200241f0116a20014120109c05450d03200341706a22242903002108200341506a2207290300210c200741086a290300210f200741106a290300211b200741186a290300211c2005202441086a2903003703002010201c3703002011201b3703002012200f37030020022008370390122002200c3703f0110240200e0d00200241f0116a20014120109c05450d00200341206a2903002108200341086a290300210c200341106a290300210f200341186a290300211b2003290300211c2005200341286a2903003703002010201b3703002011200f3703002012200c37030020022008370390122002201c3703f011200e0d03200241f0116a20014120109c05450d03200341d0006a2903002108200341306a290300210c200341386a290300210f200341c0006a290300211b200341c8006a290300211c2005200341d8006a2903003703002010201c3703002011201b3703002012200f37030020022008370390122002200c3703f011200e0d02200241f0116a20014120109c05450d02200341e0006a2105200341c0016a2103200d20056b4190014d0d050c010b0b200241900f6a41286a2005290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a2010290300370300200241900f6a41106a2011290300370300200241900f6a41086a2012290300370300200220022903f0113703900f0c050b200241900f6a41286a2005290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a2010290300370300200241900f6a41106a2011290300370300200241900f6a41086a2012290300370300200220022903f0113703900f0c040b200241900f6a41286a2005290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a2010290300370300200241900f6a41106a2011290300370300200241900f6a41086a2012290300370300200220022903f0113703900f0c030b200241900f6a41286a200241f0116a41286a290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a200241f0116a41186a290300370300200241900f6a41106a200241f0116a41106a290300370300200241900f6a41086a200241f0116a41086a290300370300200220022903f0113703900f0c020b200341a07f6a21030b2003200d460d0102400240200441146a2201200241f0116a470d0020032903202108200341086a290300210c200341106a290300210f200341186a290300211b2003290300211c200241f0116a41286a200341286a290300370300200241f0116a41186a201b370300200241f0116a41106a200f370300200241f0116a41086a200c37030020022008370390122002201c3703f0110c010b0340200341206a2903002108200341086a290300210c200341106a290300210f200341186a290300211b2003290300211c200241f0116a41286a200341286a290300370300200241f0116a41186a201b370300200241f0116a41106a200f370300200241f0116a41086a200c37030020022008370390122002201c3703f011200241f0116a20014120109c05450d01200d200341306a2203470d000c030b0b200241900f6a41286a200241f0116a41286a290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a200241f0116a41186a290300370300200241900f6a41106a200241f0116a41106a290300370300200241900f6a41086a200241f0116a41086a290300370300200220022903f0113703900f0b200241e00e6a41286a200241900f6a41286a2903002208370300200241e00e6a41206a200241900f6a41206a290300220c370300200241e00e6a41186a200241900f6a41186a290300220f370300200241e00e6a41106a200241900f6a41106a290300221b370300200241e00e6a41086a200241900f6a41086a290300221c370300200220022903900f22183703e00e200241f0116a41286a2008370300200241f0116a41206a200c370300200241f0116a41186a200f370300200241f0116a41106a201b370300200241f0116a41086a201c370300200220183703f011200241f0116a2016460d00200241f0116a20164120109c05450d00024002402035290310221b2004290300220c85203541186a290300220f200441086a2903002208858450450d0042002108428080808010210c0c010b20024190036a200c42004280808080104200109f0520024180036a42004200200c4200109f050240200842ffffffff0f832008522002290388034200527220024190036a41086a290300221c20084220862002290380037c7c2218201c54724101470d000240201b422088200f42208684221b200f422088220f84500d00200241e0026a200c2008201b200f10a005200241e0026a41086a290300210820022903e002210c0c020b41dcc0c2001032000b200241f0026a2002290390032018201b4201201b420156200f420052200f501b22031b200f420020031b10a005200241f0026a41086a290300210820022903f002210c0b200220042f00143b01a00d2002200441166a2d00003a00a20d2002200441276a2900003703f80c20022004412c6a2900003700fd0c200441236a28000021012004411f6a28000021052004411b6a2800002110200441176a280000211102400240024020152027460d00201521030c010b202741016a22032027490d17202741017422122003201220034b1b2212ad42307e220f422088a70d17200fa722034100480d170240024020270d002003102821190c010b2019202741306c2003102c21190b2019450d0120272103201221270b20022d00a20d211220022f01a00d21072019200341306c6a2203200136000f2003200536000b2003201036000720032011360003200320073b0100200341026a20123a00002003200c370320200341286a2008370300200320022903f80c370013200341186a20022900fd0c370000201541016a21150c010b200341081037000b200441386a22042032470d000b024020150d002027450d012019102a0c010b02400240201541306c22040d00420021084200210c0c010b201941206a2103420021084200210c0340200341086a290300200c7c2003290300220c20087c2208200c54ad7c210c200341306a2103200441506a22040d000b0b200241d0026a420042808080801020087d220f200f428080808010564200200c200842808080801056ad7c7d22084200522008501b22031b221c4200200820031b22082015ad2218420010a00520022903d002210f0240201c20185441002008501b0d00200241d0026a41086a290300211b2015417f6a2110201941206a21034100210403402003427f20032903002208200f7c220c200c2008542201200341086a22052903002208201b7c2001ad7c220c200854200c2008511b22011b3703002005427f200c20011b37030020102004460d01200341306a21032015200441016a22044b0d000b41ccc0c200200420151034000b200241c0026a200f200820182008109f050240201c20022903c0027da72205450d004100210303402019200320157041306c6a2204427f2004290320220842017c220c200c2008542201200441286a2204290300220f2001ad7c221b200f54200c20085a1b22011b3703202004427f201b20011b370300200341016a22032005490d000b0b200241f0116a41186a2204203c290300370300200241f0116a41106a2201203d290300370300200241f0116a41086a2205203a290300370300200220022903900e3703f011024020362034470d00203441016a22032034490d14203441017422102003201020034b1b2210ad422c7e2208422088a70d142008a722034100480d140240024020340d0020031028213f0c010b203f2034412c6c2003102c213f0b203f450d0320342136201021340b203f2036412c6c6a220320022903f011370200200529030021082001290300210c2004290300210f200320153602282003202736022420032019360220200341186a200f370200200341106a200c370200200341086a2008370200203641016a21360b203541d0006a22352040470d000c020b0b200341041037000b02402037450d002038102a0b024020022802c80e2203450d00200341d0006c210420022802c00e41206a210303400240200341046a280200450d002003280200102a0b200341d0006a2103200441b07f6a22040d000b0b024020022802c40e450d0020022802c00e102a0b20022802e80c20022802ec0c20022802f00c10bc022006450d08203941306c220341306e21040240024020030d0041012142420021300c010b200441057422014100480d10200110282242450d072004ad21300b024002402006200620036a470d00410021190c010b203941306c2101410021192042210320062104034020032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000201941016a2119200341206a2103200441306a2104200141506a22010d000b0b200242003702ec0c200241f8b9c0003602e80c024020194105742203450d00204220036a213b200241f0116a4102722143200241900c6a41136a213c200241b00c6a41136a2144204221070340200241b0026a200710b004200241b0026a41086a290300210c20022903b002210f200241a0026a10a10220024190026a20022903a002200241a0026a41086a290300427f420010a00520024180026a200f200c20022903900222084201200842015620024190026a41086a29030022084200522008501b22031b2008420020031b10a005200741086a2900002108200741106a290000210c2007290000210f200241e00e6a41186a220e200741186a290000370300200241e00e6a41106a2224200c370300200241e00e6a41086a221520083703002002200f3703e00e20022903800221080240024002400240024002400240024020022802e80c221041f8b9c000460d0020022802ec0c21110c010b200241900f6a410041e0021099051a200241f0116a41004190041099051a41f80610282210450d0141002111201041003b010620104100360200201041086a200241900f6a41e002109a051a201041e8026a200241f0116a419004109a051a200241003602ec0c200220103602e80c0b200741206a210702400340201041086a2104201041066a210d20102f01062212410574210341002101024003402003450d01200241e00e6a20044120109c052205450d03200341606a2103200141016a2101200441206a21042005417f4a0d000b2001417f6a21120b02402011450d002011417f6a2111201020124102746a41f8066a28020021100c010b0b200241c00d6a41186a2203200e290300370300200241c00d6a41106a2024290300220c370300200241c00d6a41086a2015290300220f370300200220022903e00e221b3703c00d200220022802f00c41016a3602f00c200241900e6a41106a2239200c370300200241900e6a41086a2240200f370300200241900e6a41186a223e20032903003703002002201b3703900e200d2f01002204410b490d04200241900f6a410041e0021099051a200241f0116a41004190041099051a41f80610282203450d02200341003b010620034100360200200341086a200241900f6a41e002109a052101200341e8026a200241f0116a419004109a052105200241b00c6a41086a2245201041d0016a290000370300200241b00c6a41106a2246201041d8016a290000370300200241b00c6a41186a2247201041e0016a290000370300200241f0116a41086a222720104190056a290300370300200241f0116a41106a221620104198056a290300370300200241f0116a41186a2232201041a0056a290300370300200241f0116a41206a2233201041a8056a290300370300200241f0116a41286a2235201041b0056a290300370300200220102900c8013703b00c20022010290388053703f0112001201041e8016a20102f010641796a2204410574109a0521012005201041b8056a200441306c109a052105201041063b0106200320043b0106200220022f01b00c3b01e00c200220022d00b20c3a00e20c200220442900003703d00c2002204441056a22482900003700d50c20022800b30c214920022800b70c214a20022800bb0c214b20022800bf0c214c200241900f6a41286a224d2035290300370300200241900f6a41206a224e2033290300370300200241900f6a41186a224f2032290300370300200241900f6a41106a22502016290300370300200241900f6a41086a22512027290300370300200220022903f0113703900f0240024020124107490d00201241057420016a41c07e6a2001201241796a22114105746a2201200441ffff037120116b410574109b051a200141186a203e290300370000200141106a2039290300370000200141086a2040290300370000200120022903900e370000201241306c20056a220441e07d6a200441b07d6a2204200341066a220d2f010020116b41306c109b051a200441186a4200370300200420083703102004420037030820042008370300200441286a4100360200200442083703200c010b201041086a20124105746a220441206a2004200d2f010020126b410574109b051a200441186a203e290300370000200441106a2039290300370000200441086a2040290300370000200420022903900e370000201041e8026a201241306c6a220441306a2004200d2f010020126b41306c109b051a200441186a4200370300200420083703102004420037030820042008370300200441286a4100360200200442083703200b200d200d2f010041016a3b0100200241d00e6a41026a220420022d00e20c3a00002015205129030037030020242050290300370300200e204f290300370300200241e00e6a41206a2238204e290300370300200241e00e6a41286a2237204d290300370300200220022f01e00c3b01d00e200220022903d00c3703900c200220022900d50c3700950c200220022903900f3703e00e200241e00d6a41286a22522037290300370300200241e00d6a41206a22532038290300370300200241e00d6a41186a2254200e290300370300200241e00d6a41106a22552024290300370300200241e00d6a41086a22562015290300370300200220022903e00e3703e00d200220022f01d00e3b01a00d200220042d00003a00a20d200220022903900c3703f80c200220022900950c3700fd0c0240201028020022110d00200241e80c6a2104200321010c060b20102f0104213d41002157200321580340200241b80d6a41026a225920022d00a20d3a0000200220022f01a00d3b01b80d200220022903f80c3703d00e200220022900fd0c3700d50e2037205229030037030020382053290300370300200e20542903003703002024205529030037030020152056290300370300200220022903e00d3703e00e203d41ffff0371211202400240024020112f01062203410b490d002043410041a2071099051a41a80710282205450d0720054100360200200541046a200241f0116a41a407109a051a2047201141e0016a2900003703002046201141d8016a2900003703002045201141d0016a290000370300200220112900c8013703b00c2035201141b0056a2903003703002033201141a8056a2903003703002032201141a0056a290300370300201620114198056a290300370300202720114190056a29030037030020022011290388053703f011200541086a201141e8016a20112f0106220441796a2203410574109a05215a200541e8026a201141b8056a200341306c109a05215b200541f8066a20114194076a2004417a6a220d410274109a05213a201141063b0106200520033b01060240200d450d0041002103203a210403402004280200220120033b010420012005360200200441046a2104200d200341016a2203470d000b0b204d2035290300370300204e2033290300370300204f20322903003703002050201629030037030020512027290300370300200220022903f0113703900f200220022f01b00c3b01e00c200220022d00b20c3a00e20c20022900b30c210820022900bb0c210c200220482900003700d50c200220442900003703d00c203c20022903d00c370000203c41056a220d20022900d50c370000200220022d00e20c3a00920c200220022f01e00c3b01900c2002200c37009b0c200220083700930c2035204d2903003703002033204e2903003703002032204f2903003703002016205029030037030020272051290300370300200220022903900f3703f011203d41ffff037122044107490d01205a2012417a6a22014105746a205a201241796a22034105746a220420052f010620036b410574109b051a200441186a20022900d50e3700002004204c36000f2004204b36000b2004204a36000720042049360003200441026a20592d00003a0000200420022f01b80d3b0000200420022903d00e370013201241306c205b6a220441e07d6a200441b07d6a220420052f0106223d20036b41306c109b051a200441286a2037290300370300200441206a2038290300370300200441186a200e290300370300200441106a2024290300370300200441086a2015290300370300200420022903e00e3703002005203d41016a22043b01062012410274223d203a6a416c6a203a20014102746a2212200441ffff037120016b410274109b051a20122058360200200120052f010622124b0d022005203d6a41e0066a2104034020042802002201200341016a22033b010420012005360200200441046a210420032012490d000c030b0b201141086a2204201241016a22014105746a200420124105746a2204200320126b2205410574109b051a2004204c36000f2004204b36000b2004204a36000720042049360003200441026a20592d00003a0000200420022f01b80d3b0000200420022903d00e370013200441186a20022900d50e3700002011201241306c6a22044198036a200441e8026a220d200541306c109b051a20044190036a203729030037030020044188036a203829030037030020044180036a200e290300370300200441f8026a2024290300370300200441f0026a2015290300370300200d20022903e00e3703002011200341016a22033b01062012410274201141f8066a22046a41086a200420014102746a2204200341ffff037120016b410274109b051a200420583602000240201220112f010622034f0d00205820013b010420582011360200200120034f0d002003417f6a210520112001417f6a22034102746a4180076a2104034020042802002201200341026a3b010420012011360200200441046a21042005200341016a2203470d000b0b41001a200241e80c6a1a20101a0c090b201141086a2203201241016a22014105746a200320124105746a220320112f0106223d20126b223a410574109b051a2003204c36000f2003204b36000b2003204a36000720032049360003200341026a20592d00003a0000200320022f01b80d3b0000200320022903d00e370013200341186a20022900d50e370000201141e8026a201241306c6a220341306a2003203a41306c109b051a200341286a2037290300370300200341206a2038290300370300200341186a200e290300370300200341106a2024290300370300200341086a2015290300370300200320022903e00e3703002011203d41016a22033b01062012410274223a201141f8066a223d6a41086a203d20014102746a223d200341ffff037120016b410274109b051a203d2058360200200420112f010622014f0d002011203a6a41fc066a2103034020032802002204201241016a22123b010420042011360200200341046a210320012012470d000b0b205741016a2112200241b00d6a41026a220320022d00920c3a00002040202729030037030020392016290300370300203e2032290300370300200241900e6a41206a22042033290300370300200241900e6a41286a22012035290300370300200220022f01900c3b01b00d200220022903f0113703900e2002203c2900003703c00e2002200d2900003700c50e20022800930c214920022800970c214a200228009b0c214b200228009f0c214c20522001290300370300205320042903003703002054203e2903003703002055203929030037030020562040290300370300200220022903900e3703e00d200220022f01b00d3b01a00d200220032d00003a00a20d200220022903c00e3703f80c200220022900c50e3700fd0c0240201128020022030d0020111a200241e80c6a22041a200521010c070b20112f0104213d200241e80c6a1a20111a2003211120052158201221570c000b0b2010200141306c6a22034180036a4200370300200341f8026a2008370300200341f0026a4200370300200341e8026a200837030020034190036a410036020020034188036a220128020021042003418c036a2802002103200142083703002004450d052003450d052004102a0c050b41f80641081037000b41f80641081037000b41a80741081037000b201020124105746a220341286a200341086a2201200420126b410574109b051a200341206a203e290300370000200341186a2039290300370000200341106a2040290300370000200120022903900e3700002010201241306c6a22034198036a200341e8026a220420102f010620126b41306c109b051a20034190036a410036020020034188036a420837030020034180036a4200370300200341f8026a2008370300200341f0026a420037030020042008370300201020102f010641016a3b01060c010b2043410041a2071099051a41a80710282203450d0820034100360200200341046a200241f0116a41a407109a051a2003200428020022053602f806200420033602002004200428020441016a360204200541003b010420052003360200200320032f010622054105746a220441086a20022f01a00d3b00002004410a6a20022d00a20d3a0000200441176a204c360000200441136a204b3600002004410f6a204a3600002004410b6a20493600002004411b6a20022903f80c370000200441206a20022900fd0c3700002003200541306c6a220441e8026a20022903e00d370300200441f0026a2056290300370300200441f8026a205529030037030020044180036a205429030037030020044188036a205329030037030020044190036a2052290300370300200341f8066a200541016a22044102746a2001360200200320043b0106200120043b01042001200336020020101a0b2007203b470d000b0b02402036412c6c2203450d00203f20036a2132203f210d03400240200d28022841306c2203450d00200d280220220e20036a21150340200241f0016a200d10b004200e221041286a2224290300210f20102903202108200241f0016a41086a290300211b20022903f001211c200241e0016a10a102200241d0016a20022903e001200241e0016a41086a290300427f420010a005200241c0016a201c201b20022903d001220c4201200c420156200241d0016a41086a290300220c420052200c501b22031b200c420020031b10a005200241a0016a200f420020022903c001220c4200109f05200241b0016a20084200200c4200109f0520024190016a4200420020084200109f0542ffffffff0f200241b0016a41086a290300220820022903a0012002290390017c7c220c42208820022903a80120022903980184420052200c2008547222031b2108427f20023502b401200c4220868420031b210c201041306a210e200241e80c6a210320022802ec0c21120240024003402003280200221141086a210420112f010622074105742103410021010240024003402003450d01201020044120109c052205450d02200341606a2103200141016a2101200441206a21042005417f4a0d000b2001417f6a21070b2012450d022012417f6a2112201120074102746a41f8066a21030c010b0b2011200141306c6a220341f8026a2204427f2004290300220f200c7c221b201b200f54220420034180036a2201290300220f20087c2004ad7c221b200f54201b200f511b22041b3703002001427f201b20041b370300200241f0116a41186a2211200d41186a290000370300200241f0116a41106a2212200d41106a290000370300200241f0116a41086a2207200d41086a2900003703002002200d2900003703f01120034188036a2105024020034190036a220128020022042003418c036a280200470d00200441016a22032004490d16200441017422272003202720034b1b2227ad42307e220f422088a70d16200fa722164100480d160240024020040d002016102821030c010b2005280200200441306c2016102c21030b2003450d0220052003360200200541046a2027360200200128020021040b2005280200200441306c6a220320022903f0113703002003200c370320200341186a2011290300370300200341106a2012290300370300200341086a2007290300370300200341286a20083703002001200128020041016a3602000b2010200c37032020242008370300200e2015460d020c010b0b201641081037000b200d412c6a220d2032470d000b0b200241e00e6a41086a22034200370300200242003703e00e41a5afc4004116200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a100621030240024020022802f0112204417f460d002003450d00200220043602e40e200220033602e00e200241f0116a200241e00e6a106d20022802f0112207450d0320022902f41121082004450d012003102a0c010b42002108410121070b02402007450d002008422088a72203450d0020034105742101200721040340410f10282203450d04200341002900edae44370000200341076a41002900f4ae443700002002428f808080f0013702f411200220033602f0112004200241f0116a108f0120022802f811210320022802f0112105200241900c6a41186a22104200370300200241900c6a41106a22114200370300200241900c6a41086a22124200370300200242003703900c20052003200241900c6a1000200241c00d6a41186a2010290300370300200241c00d6a41106a2011290300370300200241c00d6a41086a2012290300370300200220022903900c3703c00d024020022802f411450d0020022802f011102a0b200441206a2104200241c00d6a41201009200141606a22010d000b0b02402008a7450d002007102a0b20022802f00c211020022802e80c21030240024020022802ec0c22010d00200321040c010b2001210520032104034020042802f80621042005417f6a22050d000b0340200320032f01064102746a41f8066a28020021032001417f6a22010d000b0b200241ac0f6a20032f0106360200200241900f6a41186a4100360200200241a40f6a2003360200200220103602b00f200241003602a00f200242003703980f200220043602940f200241003602900f200241f0116a200241900f6a10b1020240200241b0126a223b280200220d0d00427f2120427f211c0c080b200241f0116a41106a2101200241a8126a2133200241f0116a41286a2135427f2120427f211c0340200241e00d6a41086a200241f0116a41086a22112903002208370300200241e00d6a41106a2001290300220c370300200241e00d6a41186a200241f0116a41186a2205290300220f370300200220022903f011221b3703e00d203329030021182035290300211f20022802b412212420022802b812210320022903a0122121200229039012212f200241900e6a41186a2215200f370300200241900e6a41106a2227200c370300200241900e6a41086a221620083703002002201b3703900e20024180016a10a102200241e0006a20022903800120024180016a41086a290300427f420010a005200241f0006a10a102200241c0006a2002290370200241f0006a41086a290300427f420010a005200241d0006a2002290360220842012008420156200241e0006a41086a29030022084200522008501b22041b2008420020041b202f201f109f05200241306a2002290340220842012008420156200241c0006a41086a29030022084200522008501b22041b2008420020041b20212018109f05200241d0006a41086a290300211f200241306a41086a290300211b4100211220022903502121200229033021184100210e410821070240200341306c2210450d00201041306d220ead42307e2208422088a70d112008a722044100480d11200410282207450d050b02402003450d00200341047441706a213220072103200d21040340200441286a290300210c200441206a290300210f2005200441186a2903003703002001200441106a2903003703002011200441086a290300370300200220042903003703f011200241206a10a102200241106a2002290320200241206a41086a290300427f420010a00520022002290310220842012008420156200241106a41086a29030022084200522008501b22121b2008420020121b200f200c109f052003200241086a29030037030820032002290300370300200341106a20022903f011370300200341186a2011290300370300200341206a2001290300370300200341286a2005290300370300200341306a2103200441306a2104201041506a22100d000b203241047641016a21120b02402024450d00200d102a0b2012ad42307e2208422088a70d012008a72203417f4c0d010240024020030d004108210d0c010b20031028220d450d060b0240024020120d00410021100c010b2007201241306c6a211141002110200d2103200721040340200320042903003703002003200441086a290300370308200341106a200441106a290300370300200341186a200441186a290300370300200341206a200441206a290300370300200341286a200441286a290300370300200341306a2103201041016a2110200441306a22042011470d000b0b2005201f3703002002202137038012200220183703f011200220103602981220022012360294122002200d360290122002201b3703f811200241e00e6a41186a2015290300370300200241e00e6a41106a2027290300370300200241e00e6a41086a2016290300370300200220022903900e3703e00e0240410f10282203450d00200341002900edae44370000200341076a41002900f4ae443700002002428f808080f0013702b40c200220033602b00c200241e00e6a200241b00c6a108f0120022802b80c210320022802b00c2104200241900c6a41186a22054200370300200241900c6a41106a22104200370300200241900c6a41086a22114200370300200242003703900c20042003200241900c6a1000200241c00d6a41186a2005290300370300200241c00d6a41106a2010290300370300200241c00d6a41086a2011290300370300200220022903900c3703c00d024020022802b40c450d0020022802b00c102a0b200241003602e80e200242013703e00e2002200241f0116a3602b00c200241b00c6a200241e00e6a10a301200220013602b00c200241b00c6a200241e00e6a10a30120022802901221032002280298122204200241e00e6a10b40102402004450d00200441306c21040340200341106a200241e00e6a108f01200220033602b00c200341306a2103200241b00c6a200241e00e6a10a301200441506a22040d000b0b20022802e40e2103200241c00d6a412020022802e00e220420022802e80e100702402003450d002004102a0b20182020542103201b201c512104201b201c5421050240200228029412450d00200228029012102a0b2003200520041b21030240200e450d002007102a0b201b201c20031b211c2018202020031b2120200241f0116a200241900f6a10b10220022802b012220d450d090c010b0b410f41011037000b1036000b41c4d1c300413320024198196a419cd9c3001038000b410f41011037000b200441081037000b200341081037000b41a80741081037000b200141011037000b200241f0116a200241900f6a10b1020240203b2802002203450d000340024020022802b412450d002003102a0b200241f0116a200241900f6a10b10220022802b01222030d000b0b024020022802940f220341f8b9c000460d00200328020021012003102a2001450d00200128020021042001102a2004450d00024020042802002203450d0003402004102a2003210420032802002201210320010d000b0b2004102a0b200241e00e6a41086a22034200370300200242003703e00e4199fec4004111200241e00e6a1008200241900f6a41086a22042003290300370300200220022903e00e3703900f2002201c3703f811200220203703f011200241900f6a4110200241f0116a4110100720034200370300200242003703e00e41a5afc4004116200241e00e6a100820042003290300370300200220022903e00e3703900f200241003602f811200242013703f0112019200241f0116a10b40102402019450d00201941057421042042210303402003200241f0116a108f01200341206a2103200441606a22040d000b0b20022802f4112103200241900f6a411020022802f011220420022802f811100702402003450d002004102a0b2019ad210802402036450d002036412c6c2104203f41206a210303400240200341046a280200450d002003280200102a0b2003412c6a2103200441546a22040d000b0b2008422086210802402034450d00203f102a0b203020088421082041450d012006102a0c010b200241e00e6a41086a22034200370300200242003703e00e4199fec4004111200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a10062103024020022802f0112204417f460d002004410f4d0d052003102a0b410021420b024020172014a745720d002013102a0b20420d0102402009450d00200941d0006c2104200a41c0006a210303400240200341046a280200450d002003280200102a0b200341d0006a2103200441b07f6a22040d000b0b200b450d00200a102a0b200041003602000c010b200020083702042000204236020002402009450d00200941d0006c2104200a41c0006a210303400240200341046a280200450d002003280200102a0b200341d0006a2103200441b07f6a22040d000b0b200b450d00200a102a0b200241a0196a24000f0b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b1031000baa0b02067f017e230041206b22042400200441106a41086a220542003703002004420037031041f9b5c200411d200441106a1008200441086a2005290300370300200420042903103703000240024002400240024002400240024002400240200441104101410041001003417f470d001098012106024002400240024020024101470d00200441106a41086a220542003703002004420037031041b8bfc200411a200441106a1008200441086a2005290300370300200420042903103703002004410036021020044110200441106a10062105024020042802102207417f460d002005450d0020074104490d06200528000021072005102a200720064b0d020b200441106a41086a220542003703002004420037031041b8bfc200411a200441106a1008200441086a2005290300370300200420042903103703002004200620014101746a36021020044110200441106a410410070b200028020821052000280204210820002802002109200441106a41086a220042003703002004420037031041f9b5c200411d200441106a1008200441086a2000290300370300200420042903103703002004410036021820044201370310410410282200450d052004410436021420042004280218220741046a36021820042000360210200020076a200636000020042802142206200428021822006b4104490d01200428021021060c020b200041046a280200450d0b2000280200102a0c0b0b200041046a22072000490d09200641017422002007200020074b1b22004100480d090240024020060d002000102821060c010b200428021020062000102c21060b2006450d042004200036021420042006360210200428021821000b2004200041046a360218200620006a20013600002005200441106a10b40102402005450d002009200541286c6a21072009210503402005200441106a108f01200541206a290300210a0240024020042802142201200428021822006b4108490d00200428021021010c010b200041086a22062000490d0b200141017422002006200020064b1b22004100480d0b0240024020010d002000102821010c010b200428021020012000102c21010b2001450d072004200036021420042001360210200428021821000b2004200041086a360218200120006a200a3700002007200541286a2205470d000b0b20042802142105200428021821000240024020024101460d000240024020052000460d00200428021021050c010b200041016a22052000490d0b200041017422012005200120054b1b22014100480d0b0240024020000d002001102821050c010b200428021020002001102c21050b2005450d082004200136021420042005360210200428021821000b2004200041016a360218200520006a41003a00000c010b0240024020052000460d00200428021021050c010b200041016a22052000490d0a200041017422012005200120054b1b22014100480d0a0240024020000d002001102821050c010b200428021020002001102c21050b2005450d082004200136021420042005360210200428021821000b2004200041016a360218200520006a41013a00000240024020042802142205200428021822006b4104490d00200428021021050c010b200041046a22012000490d0a200541017422002001200020014b1b22004100480d0a0240024020050d002000102821050c010b200428021020052000102c21050b2005450d092004200036021420042005360210200428021821000b2004200041046a360218200520006a20033600000b2004280214210020044110200428021022052004280218100702402000450d002005102a0b2008450d092009102a0c090b200041046a280200450d082000280200102a0c080b41c4d1c3004133200441106a419cd9c3001038000b410441011037000b200041011037000b200041011037000b200141011037000b200141011037000b200041011037000b1031000b200441206a24000bcb0201057f230041d0006b220224002002410036022820014110200241286a1006210302400240024020022802282204417f460d0020030d010b200041003a00000c010b41002101200241003a00480340024020042001470d000240200141ff0171450d00200241003a00480b41c4d1c3004133200241286a419cd9c3001038000b200241286a20016a200320016a2d00003a00002002200141016a22053a00482005210120054120470d000b200241086a41186a2201200241286a41186a290300370300200241086a41106a2205200241286a41106a290300370300200241086a41086a2206200241286a41086a2903003703002002200229032837030802402004450d002003102a0b20002002290308370001200041013a0000200041196a2001290300370000200041116a2005290300370000200041096a20062903003700000b200241d0006a24000bdf0301017f024002400240024002400240410110282202450d00200220002d00003a0000200241014102102c2202450d01200220002d00013a0001200241024104102c2202450d02200220002d00023a0002200220002d00033a0003200241044108102c2202450d03200220002d00043a0004200220002d00053a0005200220002d00063a0006200220002d00073a0007200241084110102c2202450d04200220002d00083a0008200220002d00093a0009200220002d000a3a000a200220002d000b3a000b200220002d000c3a000c200220002d000d3a000d200220002d000e3a000e200220002d000f3a000f200241104120102c2202450d05200220002d00103a0010200220002d00113a0011200220002d00123a0012200220002d00133a0013200220002d00143a0014200220002d00153a0015200220002d00163a0016200220002d00173a0017200220002d00183a0018200220002d00193a0019200220002d001a3a001a200220002d001b3a001b200220002d001c3a001c200220002d001d3a001d200220002d001e3a001e200220002d001f3a001f200128020020012802042002412010072002102a0f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b952801057f02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141046a2202280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00003a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0220012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00013a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0320012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00023a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0420012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00033a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0520012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00043a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0620012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00053a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0720012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00063a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0820012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00073a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0920012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00083a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0a20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00093a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0b20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000a3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0c20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000b3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000c3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000d3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000e3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1020012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000f3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00103a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1220012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00113a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1320012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00123a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1420012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00133a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1520012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00143a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1620012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00153a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1720012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00163a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1820012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00173a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1920012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00183a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1a20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00193a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1b20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001a3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1c20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001b3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001c3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001d3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001e3a000002400240200228020020032802002202460d00200128020021040c010b200241016a22042002490d21200241017422052004200520044b1b22054100480d210240024020020d002005102821040c010b200128020020022005102c21040b2004450d2020012004360200200141046a2005360200200141086a28020021020b2003200241016a360200200420026a20002d001f3a00000f0b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200541011037000b1031000b02000ba50201057f230041d0006b21020240200128020022032001280204470d00200041003602000f0b200120034180016a3602002002200329006237012a2002200329006a370132200241086a41086a220120022903303703002002200329007237013a200241086a41106a220420022903383703002002200328007a360142200220032f007e3b0146200241086a41186a22052002290340370300200220032f00603b012820022002290328370308200241286a41186a22062005290300370300200241286a41106a22052004290300370300200241286a41086a220420012903003703002002200229030837032820002003360200200020022903283702042000410c6a2004290300370200200041146a20052903003702002000411c6a20062903003702000b280020004101360204200041086a200128020420012802006b4107762201360200200020013602000bb905020b7f047e23004190016b22032400024002402001280200220420012802042205460d00200120044180016a22063602002003200441e2006a29000037016a2003200441ea006a290000370172200341c8006a41086a220720032903703703002003200441f2006a29000037017a200341c8006a41106a220820032903783703002003200441fa006a280000360182012003200441fe006a2f00003b018601200341c8006a41186a22092003290380013703002003200441e0006a2f00003b016820032003290368370348200341286a41186a220a2009290300370300200341286a41106a220b2008290300370300200341286a41086a220c200729030037030020032003290348370328200541807f6a210d02400340200341086a41186a200a290300220e370300200341086a41106a200b290300220f370300200341086a41086a200c2903002210370300200320032903282211370308200341e8006a41186a200e370300200341e8006a41106a200f370300200341e8006a41086a2010370300200320113703682002450d01200d2004460d02200120064180016a22053602002003200641e2006a29000037016a2003200641ea006a290000370172200720032903703703002003200641f2006a29000037017a200820032903783703002003200641fa006a280000360182012003200641fe006a2f00003b01860120092003290380013703002003200641e0006a2f00003b016820032003290368370348200a2009290300370300200b2008290300370300200c20072903003703002003200329034837032820044180016a21042002417f6a2102200521060c000b0b20002004360200200020032903683702042000410c6a200341f0006a290300370200200041146a200341f8006a2903003702002000411c6a20034180016a2903003702000c010b200041003602000b20034190016a24000ba50201057f230041d0006b21020240200128020022032001280204470d00200041003602000f0b200120034180016a3602002002200329004237012a2002200329004a370132200241086a41086a220120022903303703002002200329005237013a200241086a41106a220420022903383703002002200328005a360142200220032f005e3b0146200241086a41186a22052002290340370300200220032f00403b012820022002290328370308200241286a41186a22062005290300370300200241286a41106a22052004290300370300200241286a41086a220420012903003703002002200229030837032820002003360200200020022903283702042000410c6a2004290300370200200041146a20052903003702002000411c6a20062903003702000bb905020b7f047e23004190016b22032400024002402001280200220420012802042205460d00200120044180016a22063602002003200441c2006a29000037016a2003200441ca006a290000370172200341c8006a41086a220720032903703703002003200441d2006a29000037017a200341c8006a41106a220820032903783703002003200441da006a280000360182012003200441de006a2f00003b018601200341c8006a41186a22092003290380013703002003200441c0006a2f00003b016820032003290368370348200341286a41186a220a2009290300370300200341286a41106a220b2008290300370300200341286a41086a220c200729030037030020032003290348370328200541807f6a210d02400340200341086a41186a200a290300220e370300200341086a41106a200b290300220f370300200341086a41086a200c2903002210370300200320032903282211370308200341e8006a41186a200e370300200341e8006a41106a200f370300200341e8006a41086a2010370300200320113703682002450d01200d2004460d02200120064180016a22053602002003200641c2006a29000037016a2003200641ca006a290000370172200720032903703703002003200641d2006a29000037017a200820032903783703002003200641da006a280000360182012003200641de006a2f00003b01860120092003290380013703002003200641c0006a2f00003b016820032003290368370348200a2009290300370300200b2008290300370300200c20072903003703002003200329034837032820044180016a21042002417f6a2102200521060c000b0b20002004360200200020032903683702042000410c6a200341f0006a290300370200200041146a200341f8006a2903003702002000411c6a20034180016a2903003702000c010b200041003602000b20034190016a24000be6880106147f027e077f017e027f017e230041d0046b22042400200441c0036a20012002200310f903200441c0036a41086a280200210520042802c40321060240024020042802c0034101470d002000200636020420004101360200200041086a20053602000c010b200441d4036a280200220741306c2108200441d8036a2802002109200441d0036a280200210a200441cc036a280200210b4100210c4100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004102470d000b200441d0006a200b200d6a41546a10fa032004280250210c200428025421010b4100210e20014100200c1b210f200741306c2108200c4104200c1b21104100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004108470d000b200441c8006a200b200d6a41546a10fa032004280248210e200428024c21010b4100211120014100200e1b2112200741306c2108200e4104200e1b210d4100210102400340024020082001470d000c020b200b20016a2102200141306a220c210120022d00004104470d000b200441c0006a200b200c6a41546a10fa0320042802402111200428024421010b4100210e2001410020111b2113200741306c21082011410420111b21114100210102400340024020082001470d000c020b200b20016a2102200141306a220c210120022d00004103470d000b200441386a200b200c6a41546a10fa032004280238210e200428023c21010b41002102024020014100200e1b2201450d00200141286c2108200e4104200e1b41186a2101410021020340200220012d0000456a2102200141286a2101200841586a22080d000b0b0240024020120d00411e2101200041b98dc6003602040c010b200d201241146c6a211241002114410021150240024002400340200d450d0141d78dc600210841382101200d41086a280200417c6a220e41024b0d02200d280200210c024002400240200e0e03000501000b41012115200c41af8dc600460d01200c28000041e3c2b1e306460d010c040b41012114200c41b38dc600460d00200c41b38dc6004106109c050d030b0240200d410c6a280200450d0041132101200041d58ec6003602040c050b0240200d41106a280200220120026b220c20014d0d00412a2101200041e88ec6003602040c050b41af8ec6002108412621012013200c4d0d022011200c4102746a220c450d02418f8ec600210841202101200f200c280200220c4d0d022010200c4104746a220c450d0241928fc6002108411f2101200c2802080d02200c2d000d220c41077141044b0d020240200c0e050003030300000b200d41146a220d2012470d000b0b41b18fc60041b98dc600201441017122021b2108411c411e20021b21012002450d002015410171450d00200741306c2108410021010c010b200020083602040c010b0240034020082001460d01200b20016a2102200141306a220d210120022d00004106470d000b200441306a200b200d6a41546a10fa032004280234450d00200041fd8ac600360204411f21010c010b200741306c21082003280268210c410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004105470d000b200441286a200b200d6a41546a220110fa030240200428022c41014d0d00411821012000419c8bc6003602040c020b200441206a200110fa032004280224450d0020042802202201450d002001280200200c4d0d0041222101200041b48bc6003602040c010b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004107470d000b200441186a200b200d6a41546a10fa0320042802182201200428021c4104746a2108034020012008460d012001450d012001410c6a2102200141106a210120022d0000410271450d000b41322101200041c08cc6003602040c010b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d0000410c470d000b200b200d6a2201415c6a2802002202450d00200141546a280200220d200241186c6a210c0340200d220241186a210d2002280208410374210120022802002102024003402001450d01200141786a210120022d00042108200241086a21022008410271450d000b413121012000418f8cc6003602040c030b200d200c470d000b0b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004102470d000b200441106a200b200d6a41546a10fa0320042802142201450d002004280210220220014104746a211103402002450d01200241106a210e200420022d000d22083a00c0032002280200220120022802086a210c410021024100200441c0036a20084104461b210d024003400240024002400240200241ff01710e03000102000b2001200c460d014100210220012108200141016a21010c020b2001200c460d034101210220012108200141016a21010c010b200d450d0241022102200d21084100210d0b20082d0000410271450d000b41392101200041d68bc6003602040c030b200e2102200e2011470d000b0b200741306c21084100210c4100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004102470d000b200441086a200b200d6a41546a10fa032004280208210c200428020c21010b4100210e20014100200c1b2110200741306c2108200c4104200c1b21124100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004103470d000b2004200b200d6a41546a10fa032004280200210e200428020421010b200e4104200e1b220220014100200e1b41286c6a210d41002113024002400340024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402002200d460d00412d2101418e91c400210820022802084103470d2102402002280200220c41f8e2c500460d00200c41f8e2c5004103109c050d220b200241286a21114115210c418790c400210e4114210141fa90c400210802400240024020022d00180e0400240123000b4136210c41d18fc400210e2010200228021c22014d0d22201220014104746a220f450d222002280214210c200228020c210220092d00700d01200c410b470d014138210141c290c4002108200241ac81c600460d23200241ac81c600410b109c05450d230c210b412f210141bb91c400210820022802144106470d220240200228020c220c41cb8fc400460d00200c41cb8fc4004106109c050d230b02402013450d00411f2101200041ea91c4003602040c280b2002411c6a2113201121020c240b41262101419c90c4002108200c417d6a220c41134b0d2102400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200c0e14003e3e3e0e043e073c0b0a120114111b103e0c19000b200241effec500460d3d200241effec5004103109c05450d3d41effec50020024103109c050d3d41011028220e450d1d200e41003a0000200f2d000c41e000460d010c3a0b200241f2fec500460d0141f2fec5002002410f109c05450d0120024181ffc500460d034181ffc5002002410f109c05450d03024020024198ffc500460d004198ffc5002002410f109c050d3d0b41071028220e450d20200e4100360003200e41013a0002200e41003b0000200f2d000c41e000460d060c380b200f2802084101470d380240200f2802002214200e460d0041002102034020024101460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d3a0c000b0b200f2d000d4104470d38200e102a201121020c3d0b41041028220e450d1b200e4100360000200f2d000c41e000470d35200f2802084104470d350240200f2802002214200e460d0041002102034020024104460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d370c000b0b200f2d000d4104470d35200e102a201121020c3c0b024020024190ffc500460d00200229000042e5f0d1fbb5ac98b6ec00520d3a0b41071028220e450d1c200e4100360003200e41013a0002200e41003b0000200f2d000c41e000460d010c330b41011028220e450d1a200e41003a0000200f2d000c41e000470d31200f2802084101470d31200f2802002214200e460d3041002102034020024101460d31200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d320c000b0b200f2802084107470d31200f2802002214200e460d2e41002102034020024107460d2f200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d320c000b0b200241a7ffc500460d0141a7ffc5002002410a109c05450d010240200241b1ffc500460d0041b1ffc5002002410a109c050d060b4126210c419c90c400210e200f2d000c41e000470d35200f2802080d3520112102200f2d000d4104460d380c350b200f2802084107470d31200f2802002214200e460d2b41002102034020024107460d2c200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d320c000b0b41021028220e450d19200e41003b0000200f2d000c41e000470d29200f2802084102470d290240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d2b0c000b0b200f2d000d4104470d29200e102a201121020c360b0240200241c6ffc500460d0041c6ffc5002002410d109c050d340b4126210c419c90c400210e200f2d000c41e000470d32200f2802080d3220112102200f2d000d4104460d350c320b0240200241d3ffc500460d0041d3ffc5002002410c109c050d330b4126210c419c90c400210e200f2d000c41e000470d31200f2802080d3120112102200f2d000d4104460d340c310b0240200241eaffc500460d0041eaffc50020024115109c050d320b4126210c419c90c400210e200f2d000c41e000470d30200f2802080d3020112102200f2d000d4104460d330c300b0240200241ffffc500460d0041ffffc5002002410a109c050d310b41021028220e450d16200e41003b0000200f2d000c41e000460d010c240b02402002418980c600460d00418980c60020024107109c050d300b4126210c419c90c400210e200f2d000c41e000470d2e200f2802080d2e20112102200f2d000d4104460d310c2e0b200f2802084102470d220240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d240c000b0b200f2d000d4104470d22200e102a201121020c300b02402002419080c600460d00419080c60020024113109c050d2e0b4126210c419c90c400210e200f2d000c41e000470d2c200f2802080d2c20112102200f2d000d4104460d2f0c2c0b200241a380c600460d0141a380c60020024111109c05450d01200241e280c600460d0641e280c60020024111109c05450d060240200241f380c600460d0041f380c60020024111109c050d2d0b41041028220e450d17200e4100360000200f2d000c41e000460d080c1f0b0240200241b480c600460d0041b480c6002002410e109c050d2c0b41081028220e450d13200e4200370000200f2d000c41e000460d020c1d0b41021028220e450d11200e41003b0000200f2d000c41e000470d1b200f2802084102470d1b0240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d1d0c000b0b200f2d000d4104470d1b200e102a201121020c2c0b200241c280c600460d0141c280c60020024110109c05450d01200241d280c600460d0241d280c60020024110109c05450d020240200241b781c600460d0041b781c60020024110109c050d2a0b4126210c419c90c400210e200f2d000c41e000470d28200f2802080d2820112102200f2d000d4104460d2b0c280b200f2802084108470d1a0240200f2802002214200e460d0041002102034020024108460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d1c0c000b0b200f2d000d4104470d1a200e102a201121020c2a0b4126210c419c90c400210e200f2d000c41e000470d26200f2802080d26200f2d000d22014104460d2620112102200141fb0171450d290c260b41031028220e450d0f200e41003a0002200e41003b0000200f2d000c41e000470d16200f2802084103470d160240200f2802002214200e460d0041002102034020024103460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d180c000b0b200f2d000d4104470d16200e102a201121020c280b41021028220e450d0f200e41003b0000200f2d000c41e000470d14200f2802084102470d140240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d160c000b0b200f2d000d4104470d14200e102a201121020c270b02402002418481c600460d00418481c60020024116109c050d250b41021028220e450d10200e41003b0000200f2d000c41e000460d020c120b200f2802084104470d160240200f2802002214200e460d0041002102034020024104460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d180c000b0b200f2d000d4104470d16200e102a201121020c250b02402002419a81c600460d00419a81c60020024112109c050d230b4126210c419c90c400210e200f2d000c41e000470d21200f2802080d2120112102200f2d000d4104460d240c210b200f2802084102470d0f0240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d110c000b0b200f2d000d4104470d0f200e102a201121020c230b024020130d0041002116410021170c0e0b024020132802040d002000418992c400360204413221010c260b024020132802002216201341086a28020022174d0d00200041bb92c40036020441c90021010c260b201720032802644d0d0d2000418493c40036020441c10021010c250b410141011037000b410441011037000b410141011037000b410741011037000b410741011037000b410241011037000b410241011037000b410241011037000b410841011037000b410341011037000b410241011037000b410441011037000b410241011037000b20092903082118200441c0036a41086a22024200370300200441f8b9c0003602c4032009290310211920042018a7417f2018428080808010541b3602d00320042019a7417f2019428080808010541b3602c003200441c0036a4104722201410d10fb032001410c10fb032001410710fb032001410f10fb03200441d8006a41106a20042802d003360200200441d8006a41086a2002290300370300200420042903c003370358200441c0036a41106a22082007360200200441c0036a410c6a200a3602002004200b3602c803200420053602c403200420063602c003200441f0006a200441c0036a10fc03024002400240410110282201450d00200141003a0000200420042f01c003220d3b01b002200841e0083b01002002428180808010370300200420013602c403200441013602c0032004200d3b01d203200441f0006a200441c0036a10fd03210c0240410310282202450d00200241026a41002d00fae2453a0000200241002f00f8e2453b00000240410310282208450d00200841026a41002d00f1fe453a0000200841002f00effe453b0000200441b0026a41026a200441c0036a41026a220b2d000022073a0000200420042f00c003220e3b01b00220044184016a280200210d200441f0006a41106a2802002101200b20073a00002004200e3b01c00302400240024002400240024002400240200d2001470d00200141016a220d2001490d012001410174220b200d200b200d4b1b220dad42287e2218422088a70d012018a7220b4100480d010240024020010d00200b102821010c010b200428027c200141286c200b102c21010b2001450d072004200d360280012004200136027c200428028401210d0b200428027c200d41286c6a220141003a00182001200836020c200142838080803037020420012002360200200141106a428380808030370200200141196a20042f01c0033b00002001411b6a200441c2036a2d00003a00002001411c6a200c360200200420042802840141016a36028401200441c0036a200441f0006a418c01109a051a20044180026a200441c0036a10fe0320044180026a41106a280200220e41306c2101200428028802220741546a210202400340410021082001450d01200141506a21012002412c6a210d200241306a220c2102200d2d00004103470d000b200c41086a2802002201450d00200141286c2102200c28020041186a2101410021080340200820012d0000456a2108200141286a2101200241586a22020d000b0b200e41306c2101200741546a21022008417f6a210d02400340410021082001450d01200141506a21012002412c6a210c200241306a220b2102200c2d00004103470d000b200b41086a2802002201450d00200141286c2102200b28020041186a2101410021080340200820012d0000456a2108200141286a2101200241586a22020d000b0b200e41306c21012007415c6a21020240034041002111024020010d00410021010c020b200141506a2101200241246a210c200241306a220b2102200c2d00004104470d000b200b28020021010b0240024002400240200e450d00200120086a211a2007200e41306c6a2112200441d8006a410472211b4100211c4100211d0340024020072d000041786a220141044b0d00024002400240024020010e050301020400030b200728020c2201450d032007280204220c200141186c6a211e201d210103402001211d0240200c22082802144104742202450d00200828020c21010340024020012d0000410b470d00200141046a220c280200220b200d490d00200c200b41016a3602000b200141106a2101200241706a22020d000b0b200442003703d00320044280808080c0003703c803200442043703c003024002400240411010282201450d0020042802c8032102200420013602c003200441013602c403200120024104746a22014200370200200141056a4200370000200420042802c80341016a3602c80302402008280214221f450d0041002106201f210103400240024002400240024002400240024002400240024002400240200620014f0d004110210c0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200828020c222020064104746a2d000022140eac010001020202020202020202020202020303030404050506060707080809090a0a0b0b0c0d0d0e0e0f0f1010111213131414151516161717181819191a1a1b1b1c1c1d1d1e1e1f1f2020212122222323242425252627272828292a2a2b2b2c2d2d2e2e2f2f303031313232333434353536363737383839393a3a3b3b3c3c3d3d3e3e3f3f40404141424243434444454546464747484a4a4a4a49494a4a4a4a4a4a4a4a4a4a4a4a4a4a4b4b4b4b000b4111210c0c4a0b4112210c0c490b410a210c0c480b4108210c0c470b4108210c0c460b4104210c0c450b4104210c0c440b4104210c0c430b4104210c0c420b4104210c0c410b4104210c0c400b4104210c0c3f0b4105210c0c3e0b4105210c0c3d0b4105210c0c3c0b4105210c0c3b0b4105210c0c3a0b4113210c0c390b4114210c0c380b4106210c0c370b4107210c0c360b410b210c0c350b410b210c0c340b410b210c0c330b410b210c0c320b410b210c0c310b410b210c0c300b410b210c0c2f0b410b210c0c2e0b410b210c0c2d0b410b210c0c2c0b410b210c0c2b0b410c210c0c2a0b410c210c0c290b410c210c0c280b410c210c0c270b410c210c0c260b410c210c0c250b4100210c0c240b4100210c0c230b4101210c0c220b4102210c0c210b4103210c0c200b4103210c0c1f0b4100210c0c1e0b4100210c0c1d0b4100210c0c1c0b4100210c0c1b0b4100210c0c1a0b4100210c0c190b4101210c0c180b4102210c0c170b4103210c0c160b4103210c0c150b4100210c0c140b4100210c0c130b4100210c0c120b4100210c0c110b410d210c0c100b410d210c0c0f0b410d210c0c0e0b410d210c0c0d0b410d210c0c0c0b410d210c0c0b0b410d210c0c0a0b410d210c0c090b410d210c0c080b410d210c0c070b410d210c0c060b410d210c0c050b410d210c0c040b410d210c0c030b410e210c0c020b410e210c0c010b410f210c0b200641016a210a2004280260210f201b2101024003402001280200221141086a210520112f0106210b41002102024002400340200b20022201460d01200141016a210202404100417f4101200520016a2d00002213200c4b1b2013200c461b41016a0e03000301000b0b2002417f6a210b0b0240200f0d00200441d8006a21020c030b200f417f6a210f2011200b4102746a41ec006a21010c010b0b200441d8006a21020240201120014103746a41146a22012802000e04010d0001010b200141046a21020b20022802002102024002400240024002400240024002402014417e6a220141084b0d0020010e09010302120405050607010b20042802c8032201417f6a220c20014f0d12200c20014b0d1220042802c003200c4104746a220c280208220120026a22022001490d12200c41086a20023602000c130b20042802c8032201417f6a220c20014f0d11200c20014b0d1120042802c003200c4104746a220c280208220120026a22022001490d11200c41086a200236020020042802c8032201417f6a220c20014f0d11200c20014b0d1120042802c0032202200c4104746a280204210c02400240200120042802c403460d002001210b0c010b200141016a220b2001490d2320014101742211200b2011200b4b1b220b41ffffffff0071200b470d23200b41047422114100480d23200220014104742011102c2202450d082004200b3602c403200420023602c00320042802c803210b0b2002200b4104746a2202200e3b000d200241003a000c2002200c360204200220013602002002410f6a200e4110763a0000200241086a4100360200200420042802c80341016a3602c8030c120b20042802c8032201417f6a220c20014f0d10200c20014b0d1020042802c003200c4104746a220c280208220120026a22022001490d10200c41086a200236020020042802c803220221010240200220042802c403470d00200241016a22012002490d222002410174220c2001200c20014b1b220141ffffffff00712001470d222001410474220b4100480d220240024020020d00200b1028210c0c010b20042802c0032002410474200b102c210c0b200c450d08200420013602c4032004200c3602c00320042802c80321010b20042802c00320014104746a2201200e3b000d200141003a000c2001200a360204200120023602002001410f6a200e4110763a0000200141086a4100360200200420042802c80341016a3602c8030c110b20042802c8032201417f6a220c20014f0d0f200c20014b0d0f20042802c003200c4104746a220c280208220120026a22022001490d0f200c41086a200236020020042802c803220221010240200220042802c403470d00200241016a22012002490d212002410174220c2001200c20014b1b220141ffffffff00712001470d212001410474220b4100480d210240024020020d00200b1028210c0c010b20042802c0032002410474200b102c210c0b200c450d08200420013602c4032004200c3602c00320042802c80321010b20042802c00320014104746a2201200e3b000d200141013a000c2001200a360204200120023602002001410f6a200e4110763a0000200141086a4100360200200420042802c80341016a3602c8030c100b200441c0036a200610ff030d0e20042802c8032202450d0e20042002417f6a22013602c80320042802c003220c20014104746a220b2d000c4102460d0e2001450d0f2002417e6a220220014f0d0e200c20024104746a220c200b2802002202200c280200220c200c20024b1b360200200220014f0d0f200441c0036a200610ff030d0e0c0f0b20042802c8032201417f6a220c20014f0d0d200c20014b0d0d20042802c003200c4104746a220c280208220120026a22022001490d0d202020064104746a41046a280200210b200c41086a200236020020042802c8032201417f6a220220014b0d0d2002200b6b220120024b0d0d200441c0036a200610ff030d0d20042802c803220220014d0d0d20042802c003220c20014104746a2d000c0d0e2002410474200c6a41706a2202200120022802002202200220014b1b3602000c0e0b20042802c8032201417f6a220c20014f0d0c200c20014b0d0c20042802c003200c4104746a220c280208220120026a22022001490d0c200c41086a200236020020042802c8032201417f6a220520014b0d0c202020064104746a41046a280200220128020021022001280204210c2004200520012802086b220b20054b22013a00b00220010d0c410410282213450d052013200b36020002400240200c4104490d00200520022802006b220f20054b0d08200241046a21010c010b0240200c0d0041012102410121110c0b0b200520022802006b220f20054b0d07200241046a21010b2002200c4102746a2120410121114104210c4102210b41022102034002402002417f6a22142011470d00201441016a22112014490d1f200b2011200b20114b1b221141ffffffff03712011470d1f201141027422144100480d1f0240024020024101470d002014102821130c010b2013200c2014102c21130b2013450d090b2013200c6a200f36020002400240202020016b410d490d000240200520012802006b220f20054b0d00200141046a21010c020b200441013a00b0020c0d0b20202001460d0b200520012802006b220f20054b0d0a200141046a21010b200b41026a210b200241016a2102200c41046a210c0c000b0b20042802c8032201417f6a220c20014f0d0b200c20014b0d0b20042802c003200c4104746a220c280208220120026a22022001490d0b200c41086a2002360200200441c0036a200610ff030d0b20042802c8032201450d0b20042802c00322022d000c0d0c200141047420026a41706a41003602000c0c0b41fce2c500200620011034000b201141041037000b200b41041037000b200b41041037000b410441041037000b41012111200441013a00b0020c030b201441041037000b200441013a00b0020c010b20042d00b0020d002013450d022002ad4220862011ad842118410121050240200441c0036a200610ff030d0002402018422088a72201450d002001410274210c20132101034020042802c803220b200128020022024d0d02024020042802c003221120024104746a2d000c0d00200b41047420116a41706a220b2002200b280200220b200b20024b1b3602000b200141046a2101200c417c6a220c0d000b0b410021050b02402018a7450d002013102a0b20050d020c030b2011450d012013102a0c010b200441c0036a200610ff03450d010b024020042802c403450d0020042802c003102a0b024020042802d003450d0020042802cc03102a0b4101211c0c0a0b200a201f460d0120082802142101200a21060c000b0b20042802cc0320042802d4032201410041202001676b10800420042903d003212120042802cc03211f024020042802c403450d0020042802c003102a0b0240201f0d004101211c0c080b0240200828021422022021422088a722114101746a220141ffffffff00712001470d002001410474220c417f4c0d00024002400240200c0d004108210b0c010b200c1028220b450d01200828021421020b20084100360214200828020c21222008200b36020c200841106a220b2802002123200b2001360200202220024104746a210f201f20114103746a212041022111024020020d00201f210a202221010c040b41002101201f210a4100210c20222102024002400340200241016a2f0000200241036a2d000041107472210e024020022d0000221341ac01470d00200241106a21010c070b200241086a2900002118200241046a280000210502400240024020114102470d000240200a2020470d00410021112020210a0c020b200a2902002219422088a721152019a7211041012111200a41086a210a0b20114101470d00200c2010470d0002402001200b280200470d00200141016a22112001490d15200141017422062011200620114b1b221141ffffffff00712011470d15201141047422064100480d150240024020010d002006102821010c010b200828020c20014104742006102c21010b2001450d022008200136020c200b2011360200200828021421010b200828020c20014104746a220120042f00c0033b00012001412d3a000020012015360204200141036a200441c0036a41026a2d00003a00002008200828021441016a220136021402402001200b280200470d00200141016a22112001490d15200141017422062011200620114b1b221141ffffffff00712011470d15201141047422064100480d150240024020010d002006102821010c010b200828020c20014104742006102c21010b2001450d042008200136020c200b2011360200200828021421010b200828020c20014104746a220120042f00c0033b00012001410b3a00002001200d36020441022111200141036a200441c0036a41026a2d00003a00002008200828021441016a2201360214200c21100b02402001200b280200470d00200141016a22062001490d14200141017422142006201420064b1b220641ffffffff00712006470d14200641047422144100480d140240024020010d002014102821010c010b200828020c20014104742014102c21010b2001450d042008200136020c200b2006360200200828021421010b200c41016a210c200828020c20014104746a22012018370308200120053602042001200e3b0001200120133a0000200141036a200e4110763a00002008200828021441016a2201360214200241106a2202200f470d010c080b0b200641081037000b200641081037000b201441081037000b200c41081037000b1036000b411041041037000b2001200f460d0003400240024020012d000022024109460d00200241ac01470d010c030b0240200141046a280200220228020441ffffffff0371450d002002280200102a0b2002102a0b200141106a2201200f470d000b0b2021a7210102402023450d002022102a0b200a202047201120114102461b210202402001450d00201f102a0b024020024101470d004101211c0c050b200841186a210c024002402004280268450d0020082802142202450d00200828020c210120024104742102410021080340024020012d0000412c470d002001410b3a0000200141046a201a360200200841016a21080b200141106a2101200241706a22020d000b4101210120080d010b201d21010b200c201e470d000b2001211d0c030b20072802042201200d490d022007200141016a3602040c020b200728020c2201450d012007280204220c2001411c6c6a210b0340200c2201411c6a210c024020012802182202450d0020012802102101200241027421020340024020012802002208200d490d002001200841016a3602000b200141046a21012002417c6a22020d000b0b200c200b460d020c000b0b200728020c2201450d00200141146c2102200728020441106a2101034002402001417c6a2802000d0020012802002208200d490d002001200841016a3602000b200141146a21012002416c6a22020d000b0b200741306a22072012470d000b201c4101710d02201d4101710d01200428029002211120042802880221070b2004418c026a280200210f20042802840221132004280280022105410021060c020b200441c0036a41106a20044180026a41106a280200360200200441c0036a41086a20044180026a41086a29030037030020042004290380023703c003200441b0026a200441c0036a10fc03411010282202450d07200241063a0000410110282201450d06200141003a000041011028220c450d05200c20012d00003a00002001102a411010282208450d04200841063a000041f00010282201450d03200141063a00602001412c3b01502001200d3602442001410b3a0040200141d8003a0030200120042802683602242001412d3a0020200141003602142001410f3a0010200141003602042001410f3a0000024020082d00004109470d0002402008280204220d28020441ffffffff0371450d00200d280200102a2008280204210d0b200d102a0b2008102a024020022d00004109470d0002402002280204220828020441ffffffff0371450d002008280200102a200228020421080b2008102a0b2002102a200441e4036a4287808080f000370200200441e0036a2001360200200441dc036a4100360200200441c0036a410c6a4281808080800c370200200441c8036a4101360200200441003602ec03200442043702d4032004200c3602c403200441013602c003200441b0026a200441c0036a108104200441c0036a200441b0026a418c01109a051a20044198026a200441c0036a10fe0320044198026a410c6a280200210f200441a8026a28020021112004280298022105200428029c02211320042802a0022107410021060c010b2004418c026a280200210f200428028802210702402004280290022211450d00201141306c21022007210103402001108204200141306a2101200241506a22020d000b0b41012106411a211341f28cc60021050240200f450d002007102a0b0b200441e4006a280200210e200428025c21080240200441e0006a2802002201450d000340200828026c21082001417f6a22010d000b0b4100210d4100210102400340200e450d0102400240200120082f01064f0d00200820014103746a41146a2902002118200141016a21010c010b02400240200828020022010d00200dad21184100210c410021010c010b2008330104422086200dad8421184101210c0b2008102a2018a7210d024002402018422088a7220b20012f01064f0d00200121020c010b034002400240200128020022020d00200dad2118410021020c010b200c41016a210c2001330104422086200dad8421180b2001102a2018a7210d200221012018422088a7220b20022f01064f0d000b0b200b41027420026a41f0006a28020021082002200b4103746a41146a29020021180240200c417f6a2201450d000340200828026c21082001417f6a22010d000b0b410021010b200e417f6a210e2018a74103470d000b0b0240200841f8b9c000460d00200828020021012008102a2001450d00200128020021022001102a2002450d00024020022802002201450d0003402002102a2001210220012802002208210120080d000b0b2002102a0b02402006450d002000200536020420004101360200200041086a20133602000c250b200441b0026a41106a2011360200200441b0026a410c6a200f360200200420073602b802200420133602b402200420053602b002200441c0036a200441b0026a2009280260108304024020042802c0034101470d000240200441c0036a41086a280200450d0020042802c403102a0b2000418c8dc60036020420004101360200200041086a41233602000c250b200441d4036a2802002102200441c0036a41106a280200210f200441c0036a410c6a2802002106200441c8036a280200210d20042802c403210820032802582110200441003602a002200442013703980202400240410410282201450d002004410436029c02200420042802a002220c41046a3602a00220042001360298022001200c6a200836000002400240200428029c02220820042802a00222016b4104490d0020042802980221080c010b200141046a220c2001490d0320084101742201200c2001200c4b1b22014100480d030240024020080d002001102821080c010b20042802980220082001102c21080b2008450d022004200136029c02200420083602980220042802a00221010b2004200141046a3602a002200820016a200d3600002006200241306c22016a210d024020020d00200621010c0e0b200141506a2111200441c0036a4101722102200441c0036a41276a210c200441c0036a41206a210b200441c0036a41186a2107200441c0036a41086a210e20062101034020012d00002108200c200141286a290000370000200b200141216a2900003703002007200141196a290000370300200441c0036a41106a2203200141116a290000370300200e200141096a2900003703002004200141016a2900003703c003024020084110470d00200141306a21010c0f0b200441b0026a41276a2213200c290000370000200441b0026a41206a2205200b290300370300200441b0026a41186a20072903002218370300200441b0026a41106a20032903002219370300200441b0026a41086a200e2903002221370300200420042903c00322243703b00220022024370000200241086a2021370000200241106a2019370000200241186a2018370000200241206a2005290300370000200241276a2013290000370000200420083a00c003200441f0006a200441c0036a20044198026a10840420042d00702208411f470d0d201141506a2111200141306a2201200d470d000b200d21010c0d0b410441011037000b200141011037000b1031000b41f00041081037000b411041081037000b410141011037000b410141011037000b411041081037000b200b41041037000b410341011037000b410341011037000b410141011037000b200428027421122004280278211002402011450d00200141306a2101200441c0036a4101722102200441c0036a41276a210b200441c0036a41206a2107200441c0036a41186a210e200441c0036a41086a2111034020012d0000210c200b200141286a2900003700002007200141216a290000370300200e200141196a290000370300200441c0036a41106a2203200141116a2900003703002011200141096a2900003703002004200141016a2900003703c003200c4110460d01200441b0026a41276a2213200b290000370000200441b0026a41206a22052007290300370300200441b0026a41186a200e2903002218370300200441b0026a41106a20032903002219370300200441b0026a41086a20112903002221370300200420042903c00322243703b00220022024370000200241086a2021370000200241106a2019370000200241186a2018370000200241206a2005290300370000200241276a20132900003700002004200c3a00c003200441c0036a108204200141306a2201200d470d000b0b0240200f450d002006102a0b0240200428029c02450d00200428029802102a0b024020084105470d002010450d002012102a0b200041cd8fc60036020420004101360200200041086a41253602000c190b02402001200d460d00200441c0036a4101722102200441c0036a41276a210c200441c0036a41206a210b200441c0036a41186a2107200441c0036a41086a210e034020012d00002108200c200141286a290000370000200b200141216a2900003703002007200141196a290000370300200441c0036a41106a2211200141116a290000370300200e200141096a2900003703002004200141016a2900003703c00320084110460d01200441b0026a41276a2203200c290000370000200441b0026a41206a2213200b290300370300200441b0026a41186a20072903002218370300200441b0026a41106a20112903002219370300200441b0026a41086a200e2903002221370300200420042903c00322243703b00220022024370000200241086a2021370000200241106a2019370000200241186a2018370000200241206a2013290300370000200241276a2003290000370000200420083a00c003200441c0036a108204200141306a2201200d470d000b0b0240200f450d002006102a0b2004280298022101200429029c0221182000411c6a41003a0000200041146a2018370200200041106a20013602002000410c6a2017360200200041086a2016360200200020103602042000411d6a20042f0080023b0000200041003602002000411f6a20044182026a2d00003a00000c180b200e102a2000419c90c4003602040c160b200e102a2000419c90c4003602040c150b200e102a2000419c90c4003602040c140b200e102a2000419c90c4003602040c130b200e102a2000419c90c4003602040c120b200e102a2000419c90c4003602040c110b200e102a2000419c90c4003602040c100b200e102a2000419c90c4003602040c0f0b200f2d000d22024104460d05200241fb01710d05200e102a201121020c0b0b200f2d000d22024104460d02200241fb01710d02200e102a201121020c0a0b200f2d000d22024104460d00200241fb01710d00200e102a201121020c090b200e102a2000419c90c4003602040c0b0b200e102a2000419c90c4003602040c0a0b200e102a2000419c90c4003602040c090b200e102a2000419c90c4003602040c080b200e102a2000419c90c4003602040c070b02400240200241bbffc500460d0041bbffc5002002410b109c050d010b4126210c419c90c400210e200f2d000c41e000470d01200f2802080d0120112102200f2d000d4104460d040c010b0240200241dfffc500460d0041dfffc5002002410b109c050d030b4126210c419c90c400210e200f2d000c41e000470d00200f2802080d0020112102200f2d000d4104460d030b200e2108200c21010b200020083602040c040b0240200241ac81c600460d0041ac81c6002002410b109c050d030b024041021028220c450d00200c41003b0000200f2d000c41e000470d02200f2802084102470d020240200f280200220e200c460d0041002101034020014102460d01200c20016a2102200e20016a2108200141016a210120082d000020022d0000470d040c000b0b200f2d000d4104470d02200c102a201121020c010b0b410241011037000b200c102a0b412621012000419c90c4003602040b20004101360200200041086a200136020002402007450d00200b200741306c6a2111200b210703402007220041306a21070240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a280200102a0c0d0b0240200041086a280200450d00200041046a280200102a0b200041146a280200450d0c200041106a280200102a0c0c0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b200041086a280200450d0b2000280204102a0c0b0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200241586a22020d000b0b200041086a280200450d0a2000280204102a0c0a0b200041086a280200450d09200041046a280200102a0c090b200041086a280200450d08200041046a280200102a0c080b200041086a280200450d07200041046a280200102a0c070b02402000410c6a2802002201450d00200041046a280200220c20014104746a210e03400240200c2802082202450d00200c2802002101200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d002008280200102a200d28020021080b2008102a0b200141106a2101200241706a22020d000b0b200c41106a21010240200c41046a280200450d00200c280200102a0b2001210c2001200e470d000b0b200041086a280200450d062000280204102a0c060b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d002001280200102a0b200141146a21012002416c6a22020d000b0b200041086a280200450d052000280204102a0c050b02402000410c6a2802002201450d00200041046a280200220c2001411c6c6a210e03400240200c2802042201450d000240200c410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d002008280200102a200d28020021080b2008102a0b200141106a2101200241706a22020d000b0b200c41086a280200450d00200c280204102a0b200c411c6a21010240200c41146a280200450d00200c280210102a0b2001210c2001200e470d000b0b200041086a280200450d042000280204102a0c040b02402000410c6a2802002201450d00200041046a280200220c200141186c6a210e03400240200c41046a280200450d00200c280200102a0b0240200c41146a2802002202450d00200c28020c2101200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d002008280200102a200d28020021080b2008102a0b200141106a2101200241706a22020d000b0b200c41186a21010240200c41106a280200450d00200c28020c102a0b2001210c2001200e470d000b0b200041086a280200450d032000280204102a0c030b02402000410c6a2802002201450d00200041046a280200220c2001411c6c6a210e03400240200c2802042201450d000240200c410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d002008280200102a200d28020021080b2008102a0b200141106a2101200241706a22020d000b0b200c41086a280200450d00200c280204102a0b200c411c6a21010240200c41146a280200450d00200c280210102a0b2001210c2001200e470d000b0b200041086a280200450d022000280204102a0c020b0240200041046a2802002201450d00200041086a280200450d002001102a0b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002208450d00200141046a280200450d002008102a0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102a0b200041246a280200220c450d0102402000412c6a2802002201450d00200c20014104746a210e0340200c220d41106a210c0240200d2802042201450d000240200d410c6a2802002202450d002002410c6c21020340024020012802002208450d00200141046a280200450d002008102a0b2001410c6a2101200241746a22020d000b0b200d41086a280200450d00200d280204102a0b200c200e470d000b0b200041286a280200450d012000280224102a0c010b0240200041086a280200450d00200041046a280200102a0b0240200041146a2802002201450d00200041186a280200450d002001102a0b200041246a280200450d00200041206a280200102a0b20072011470d000b0b200a450d00200b102a0b200441d0046a24000ba20301067f230041106b2202240020024100360208200242013703002000200210a001200041046a200210a001200041086a200210a00120002d0018210302400240024002400240200228020420022802082204460d00200228020021050c010b200441016a22052004490d03200441017422062005200620054b1b22064100480d030240024020040d002006102821050c010b200228020020042006102c21050b2005450d0120022006360204200220053602000b2002200441016a360208200520046a20033a0000200028020c2106200041146a2802002204200210b4010240024020022802042203200228020822056b2004490d00200228020021000c010b200520046a22002005490d03200341017422072000200720004b1b22074100480d030240024020030d002007102821000c010b200228020020032007102c21000b2000450d022002200736020420022000360200200721030b200020056a20062004109a051a200128020020012802042000200520046a100702402003450d002000102a0b200241106a24000f0b200641011037000b200741011037000b1031000bd60801037f024002400240024002400240024002400240410110282202450d00200220002d00003a0000200241014102102c2202450d01200220002d00013a0001200241024104102c2202450d02200220002d00023a0002200220002d00033a0003200241044108102c2202450d03200220002d00043a0004200220002d00053a0005200220002d00063a0006200220002d00073a0007200241084110102c2202450d04200220002d00083a0008200220002d00093a0009200220002d000a3a000a200220002d000b3a000b200220002d000c3a000c200220002d000d3a000d200220002d000e3a000e200220002d000f3a000f200241104120102c2202450d05200220002d00103a0010200220002d00113a0011200220002d00123a0012200220002d00133a0013200220002d00143a0014200220002d00153a0015200220002d00163a0016200220002d00173a0017200220002d00183a0018200220002d00193a0019200220002d001a3a001a200220002d001b3a001b200220002d001c3a001c200220002d001d3a001d200220002d001e3a001e200220002d001f3a001f2002412041c000102c2202450d06200220002d00203a0020200220002d00213a0021200220002d00223a0022200220002d00233a0023200220002d00243a0024200220002d00253a0025200220002d00263a0026200220002d00273a0027200220002d00283a0028200220002d00293a0029200220002d002a3a002a200220002d002b3a002b200220002d002c3a002c200220002d002d3a002d200220002d002e3a002e200220002d002f3a002f200220002d00303a0030200220002d00313a0031200220002d00323a0032200220002d00333a0033200220002d00343a0034200220002d00353a0035200220002d00363a0036200220002d00373a0037200220002d00383a0038200220002d00393a0039200220002d003a3a003a200220002d003b3a003b200220002d003c3a003c200220002d003d3a003d200220002d003e3a003e200220002d003f3a003f024002402001280200220041046a2802002203200041086a28020022016b41c000490d00200028020021030c010b200141c0006a22042001490d09200341017422012004200120044b1b22014100480d090240024020030d002001102821030c010b200028020020032001102c21030b2003450d0820002003360200200041046a2001360200200041086a28020021010b200041086a200141c0006a360200200320016a220041386a200241386a290000370000200041306a200241306a290000370000200041286a200241286a290000370000200041206a200241206a290000370000200041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a290000370000200020022900003700002002102a0f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b41c00041011037000b200141011037000b1031000bc32205017f057e097f047e0f7f230041c0056b22032400200241206a2903002104200241186a2903002105200241106a2903002106200241c8006a29030021072002290308210820022802002109200341086a41186a220a200241c0006a220b290300370300200341086a41106a220c200241386a220d290300370300200341086a41086a220e200241306a220f2903003703002003200241286a2202290300370308200341286a41186a2210200b290300370300200341286a41106a2211200d290300370300200341286a41086a220d200f290300370300200320022903003703282001280200210b20034180026a41186a2202200a29030037030020034180026a41106a220f200c29030037030020034180026a41086a220c200e2903003703002003200329030837038002024002400240024041381028220a450d00200a4200370308200a4200370300200a2009360210200a2003290328370214200a411c6a200d290300370200200a41246a2011290300370200200a412c6a2010290300370200200341d0016a41086a200c290300370300200341d0016a41106a200f290300370300200341d0016a41186a200229030037030020032003290380023703d001024002400240200b2802082202200b41046a280200470d00200241016a220c2002490d012002410174220d200c200d200c4b1b220cad42d0007e2212422088a70d012012a7220d4100480d010240024020020d00200d102821020c010b200b280200200241d0006c200d102c21020b2002450d02200b2002360200200b41046a200c360200200b28020821020b200b280200200241d0006c6a2202420037031020022004370308200220053703002002200a360220200220032903d00137022c200241186a4200370300200241246a428180808010370200200241346a200341d0016a41086a220a2903003702002002413c6a200341d0016a41106a220e290300370200200241c4006a200341d0016a41186a2202290300370200200b200b28020841016a3602082001280204210f20034190016a41186a200341286a41186a29030037030020034190016a41106a200341286a41106a29030037030020034190016a41086a200341286a41086a2903003703002003200329032837039001024002400240200f280200220c41f8b9c000460d00200f280204210d0c010b4100210d20034180026a410041e0021099051a200341f8016a220b4100360200200341f0016a2201420037030020024200370300200e4200370300200a4200370300200342003703d0014194031028220c450d01200c41003b0106200c4100360200200c41086a20034180026a41e002109a051a200c4190036a200b280200360200200c4188036a2001290300370200200c4180036a200341e8016a290300370200200c41f8026a200341e0016a290300370200200c41f0026a200341d0016a41086a290300370200200c20032903d0013702e802200f4100360204200f200c3602000b02400340200c41086a210a200c41066a2110200c2f0106220e41057421024100210b0240024003402002450d0120034190016a200a4120109c052201450d02200241606a2102200b41016a210b200a41206a210a2001417f4a0d000b200b417f6a210e0b200d450d02200d417f6a210d200c200e4102746a4194036a280200210c0c010b0b200c200b4102746a41e8026a20093602000c060b200341c8006a41186a20034190016a41186a22022903002212370300200341c8006a41106a20034190016a41106a220a2903002213370300200341c8006a41086a20034190016a41086a220b290300221437030020032003290390012215370348200f200f28020841016a36020820022012370300200a2013370300200b20143703002003201537039001024002400240024020102f0100220d410b490d0020034180026a410041e0021099051a200341f8016a22024100360200200341f0016a220a4200370300200341d0016a41186a4200370300200341d0016a41106a4200370300200341d0016a41086a4200370300200342003703d00141940310282211450d03201141003b010620114100360200201141086a20034180026a41e002109a05210b20114190036a200228020036020020114188036a200a29030037020020114180036a200341d0016a41186a290300370200201141f8026a200341d0016a41106a290300370200201141f0026a200341d0016a41086a290300370200201120032903d0013702e8022003200c2f00c8013b01cc012003200c41ca016a2d00003a00ce01200c41cb016a2800002116200c41cf016a2800002117200c41d3016a2800002118200c41d7016a28000021192003200c41e0016a2900003700bd012003200c2900db013703b801200c28028003211a200b200c41e8016a200c2f010641796a2202410574109a05210b201141e8026a200c4184036a2002410274109a052101200c41063b0106201120023b0106200320032f01cc013b01b401200320032d00ce013a00b601200320032903b8013703d001200320032900bd013700d501200e4107490d01201141066a2110200b200e417a6a220d4105746a200b200e41796a220a4105746a220b200241ffff0371200a6b410574109b051a200b41186a20034190016a41186a290300370000200b41106a20034190016a41106a290300370000200b41086a20034190016a41086a290300370000200b2003290390013700002001200d4102746a210b2001200a4102746a21020c020b200c41086a2201200e41016a220f4105746a2001200e4105746a2201200d200e6b410574109b051a200141186a2002290300370000200141106a200a290300370000200141086a200b2903003700002001200329039001370000200c41e8026a2202200f4102746a2002200e4102746a2202200c2f0106200e6b410274109b051a20022009360200200c200c2f010641016a3b01060c080b200c41086a2202200e41016a220a4105746a2002200e4105746a220220102f0100200e6b410574109b051a200241186a20034190016a41186a290300370000200241106a20034190016a41106a290300370000200241086a20034190016a41086a2903003700002002200329039001370000200c41e8026a220b200e4102746a2102200b200a4102746a210b200e210a0b200b200220102f0100200a6b410274109b051a20022009360200201020102f010041016a3b0100200341b0016a41026a221b20032d00b60122023a0000200341fc006a41026a221c20023a0000200320032900d50137008501200320032903d00137038001200320032f01b40122023b01b001200320032900850137006d2003200329038001370368200320023b017c200c280200220d450d05200c2f0104211020034180026a410272211d0340201b201c2d00003a0000200320032f017c3b01b00120032003290368370390012003200329006d37009501201041ffff0371210c02400240024002400240200d2f01062202410b490d00201d410041be031099051a41c40310282201450d0320014100360200200141046a20034180026a41c003109a051a2003200d2f00c8013b01cc012003200d41ca016a2d00003a00ce012003200d41db016a2900003703b8012003200d41e0016a2900003700bd01200d41cb016a280000211e200d41cf016a280000211f200d41d3016a2800002120200d41d7016a2800002121200d4180036a2802002122200141086a200d41e8016a200d2f0106220a41796a2202410574109a052123200141e8026a200d4184036a2002410274109a05212420014194036a200d41b0036a200a417a6a220e410274109a052109200d41063b0106200120023b01060240200e450d00410021022009210a0340200a280200220b20023b0104200b2001360200200a41046a210a200e200241016a2202470d000b0b200320032d00ce0122023a00b601200320032f01cc01220a3b01b401200320032903b8013703d001200320032900bd013700d50120034180016a41026a220e20023a00002003200a3b018001200320032903d00137038002200320032900d50137008502201041ffff0371220a4107490d012023200c417a6a220b4105746a2023200c41796a22024105746a220a20012f010620026b410574109b051a200a41186a200329009501370000200a201936000f200a201836000b200a2017360007200a2016360003200a41026a201b2d00003a0000200a20032f01b0013b0000200a2003290390013700132024200b410274220a6a202420024102746a221020012f0106221620026b410274109b051a2010201a3602002001201641016a22103b0106200c410274221620096a416c6a2009200a6a220a201041ffff0371220c200b6b410274109b051a200a2011360200200c200b490d02200120166a41fc026a210a0340200a280200220b200241016a22023b0104200b2001360200200a41046a210a2002200c490d000c030b0b200d41086a220a200c41016a220b4105746a200a200c4105746a220a2002200c6b410574109b051a200a41186a200329009501370000200a201936000f200a201836000b200a2017360007200a2016360003200a41026a200341b0016a41026a2d00003a0000200a20032f01b0013b0000200a200329039001370013200d41e8026a2202200b410274220a6a2002200c41027422016a2202200d2f0106220e200c6b410274109b051a2002201a360200200d200e41016a22023b01062001200d4194036a220c6a41086a200c200a6a220a200241ffff03712201200b6b410274109b051a200a2011360200201041ffff037120014f0d0b200d200b417f6a22024102746a4198036a210a0340200a280200220b200241016a22023b0104200b200d360200200a41046a210a20022001490d000c0c0b0b200d41086a2202200c41016a22104105746a2002200c4105746a2202200d2f0106200c6b410574109b051a200241186a2003290095013700002002201936000f2002201836000b2002201736000720022016360003200241026a201b2d00003a0000200220032f01b0013b00002002200329039001370013200d41e8026a220b201041027422096a200b200c41027422026a220b200d2f01062216200c6b410274109b051a200b201a360200200d201641016a220b3b01062002200d4194036a22166a41086a201620096a2209200b41ffff0371220b20106b410274109b051a20092011360200200a200b4f0d00200d20026a4198036a210203402002280200220a200c41016a220c3b0104200a200d360200200241046a2102200b200c470d000b0b201c200e2d00003a0000200320032f0180013b017c2003200329038002370368200320032900850237006d200d28020022020d01201e21162021211920202118201f2117200121112022211a0c080b41c40341041037000b200d2f01042110201e21162021211920202118201f21172002210d2022211a200121110c000b0b41940341041037000b41940341041037000b1031000b200d41081037000b413841081037000b20034180026a410272410041be031099051a41c40310282202450d0120024100360200200241046a20034180026a41c003109a051a2002200f280200220a36029403200f2002360200200f200f28020441016a360204200a41003b0104200a2002360200200220022f0106220b4105746a220a41086a20032f017c3b0000200a410a6a200341fc006a41026a2d00003a0000200a41176a2019360000200a41136a2018360000200a410f6a2017360000200a410b6a2016360000200a411b6a2003290368370000200a41206a200329006d37000020024194036a200b41016a220a4102746a20113602002002200b4102746a41e8026a201a3602002002200a3b01062011200a3b0104201120023602000b20002005370310200020083703002000200329032837032020002007370340200041186a200437030020002006370308200041286a200341306a290300370300200041306a200341386a290300370300200041386a200341286a41186a290300370300200341c0056a24000f0b41c40341041037000b0a0041c8c2c2001032000b5101027e024002402003450d002002280200450d010b41b698c40041f4031050000b2001280218220342002003290308220420023502047d2205200520045622021b37030820004105410420021b3602000bee0201047f024002400240024002402002417f4c0d000240024020020d00410121060c010b200210282206450d020b200620012002109a0521062004417f4c0d000240024020040d0041012101410021070c010b20042107200410282201450d030b200120032004109a052103024020002802082201200041046a280200470d00200141016a22082001490d05200141017422092008200920084b1b220841ffffff3f712008470d05200841057422094100480d050240024020010d002009102821010c010b200028020020014105742009102c21010b2001450d0420002001360200200041046a2008360200200028020821010b200028020020014105746a220141003602182001200336020c2001200236020820012002360204200120063602002001411c6a2005360200200141146a2004360200200141106a20073602002000200028020841016a3602080f0b1036000b200241011037000b200441011037000b200941041037000b1031000bf90e05047f027e027f017e027f230041c00c6b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320022802042105200241246a2802002106200241346a280200210302400240200241146a2802002207450d004105210220012802002802182802402802bc012003490d010b200441286a4200370300200441206a4200370300200441186a420037030020012802182202420020022903082208427f20012802102903482209420586200942ffffffffffffffff07832009521b7d22092009200856220a1b3703082004420037031041052102200a0d000240024020012802142802082005200441106a4120101741026a220a41024b0d00200a0e03020001020b41a0fac5001032000b0240024020070d00410121034100210b0c010b2004200128021029034842002003ad220c4200109f052001280218220a4200200a2903082209427f200429030020042903084200521b7d22082008200956220a1b370308200a0d012003417f4c0d060240024020030d004101210b02402001280214280208200641014100101741026a220341024b0d0020030e03040002040b41a0fac5001032000b024002402003102e220b450d00024020012802142802082006200b2003101741026a220341024b0d0020030e03020003020b41a0fac5001032000b200341011037000b200b102a0c020b200c422086200c842109200b4521030b20012802002101200441306a41186a220a200441106a41186a290300370300200441306a41106a2205200441106a41106a290300370300200441306a41086a2206200441106a41086a2903003703002004200429031037033020012802182107024020030d0020072802402802bc012009422088a74f0d002009a7450d01200b102a0c010b200441d0006a41186a200a290300370300200441d0006a41106a2005290300370300200441d0006a41086a20062903003703002004200429033037035020072802180d062007417f360218200441a8016a200741e8006a290000370300200441a0016a200741e0006a29000037030020044198016a200741d8006a2900003703002004200729005037039001024002402007411c6a220d280200220a41f8b9c000460d00200741206a28020021060c010b41002106200441e0096a410041e0021099051a200441c0016a410041a0081099051a41880b1028220a450d08200a41003b0106200a4100360200200a41086a200441e0096a41e002109a051a200a41e8026a200441c0016a41a008109a051a200741206a41003602002007200a36021c0b024002400340200a2f0106220e4105742105410021024100210302400240034020052002460d0120044190016a200a20026a41086a4120109c052201450d02200241206a2102200341016a21032001417f4a0d000b2003417f6a210e0b2006450d022006417f6a2106200a200e4102746a41880b6a280200210a0c010b0b200741246a2101410121020c010b200441f0006a41186a20044190016a41186a290300370300200441f0006a41106a20044190016a41106a290300370300200441f0006a41086a20044190016a41086a2903003703002004200429039001370370200741246a210141002106200e2103410021020b0240024020020d00200441fc096a200441f0006a41086a290300370200200441840a6a200441f0006a41106a2903003702002004418c0a6a200441f0006a41186a290300370200200420013602f009200420033602ec092004200d3602e8092004200a3602e409200420063602e009200420042903703702f409200441e0016a20042903b001370300200441e8016a200441b0016a41086a290300370300200441f4016a4200370200200442003703d801200442003703c001200441f8b9c0003602f001200441003a00fc01200441fd016a20042900900137000020044185026a20044190016a41086a2900003700002004418d026a20044190016a41106a29000037000020044195026a20044190016a41186a290000370000200441003a009d02200441e0096a200441c0016a10b70121020c010b200441d8016a4200370300200441d4016a41f8b9c000360200200441003602e001200441003602d001200442003703c801200441f8b9c0003602c401200441003602c001200a200341e0006c6a41e8026a2102200441c0016a1095010b200441c0016a41186a200441d0006a41186a290300370300200441c0016a41106a200441d0006a41106a290300370300200441c0016a41086a200441d0006a41086a290300370300200420042903503703c00120042009370294012004200b36029001200441e0096a200241306a200441c0016a20044190016a10bd01024020042802e009450d0020042802e4092202450d00200441e8096a280200450d002002102a0b2007200728021841016a360218410421020b20002002360200200441c00c6a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b41a8b8c0004110200441c0016a41d0b8c0001038000b41880b41081037000b900302017f027e230041c0006b22042400024002402003450d0020022802000d0020022802042103200441186a4200370300200441106a4200370300200441086a420037030020012802182202420020022903082205427f20012802102903482206420586200642ffffffffffffffff07832006521b7d2206200620055622021b3703082004420037030002400240024020020d00024002402001280214280208200320044120101741026a220241024b0d0020020e03020001020b41a0fac5001032000b200441206a2001280200280218220241186a200241d0006a2002410c6a4100200228020c1b200410a7012004280220450d01200441306a41086a2203200441206a41086a28020036020020042004290320370330200141046a21020240200141086a280200450d002002280200102a0b20022004290330370200200241086a2003280200360200410021010c020b200041053602000c030b2001410c6a4100360200410121010b20004100360200200020013602040c010b41b698c40041f4031050000b200441c0006a24000bae0f06017f017e057f027e037f027e230041d0016b220424000240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042103200241286a2903002105200241346a2802002106200241c4006a2802002107200241d4006a2802002108200241e4006a2802002109200441286a20012802102903484200200241146a280200220aad4200109f052001280218220242002002290308220b427f200429032820042903304200521b7d220c200c200b5622021b370308024020020d00200a417f4c0d0802400240024002400240200a0d004101210d02402001280214280208200341014100101741026a220241024b0d00200141146a210e20020e03060002060b41a0fac5001032000b0240200a102e220d450d00024020012802142802082003200d200a101741026a220241024b0d00200141146a210e20020e03030002030b41a0fac5001032000b200a41011037000b41002102200441003a00980102400340200a2002460d01200441f8006a20026a200d20026a2d00003a00002004200241016a22033a0098012003210220034120470d000b200441a0016a41186a2202200441f8006a41186a290300370300200441a0016a41106a2203200441f8006a41106a290300370300200441a0016a41086a220f200441f8006a41086a290300370300200420042903783703a0010240200a450d00200d102a0b200441386a41086a200f290300370300200441386a41106a2003290300370300200441386a41186a2002290300370300200420042903a001370338200441186a200128021029034842002007ad4200109f052001280218220242002002290308220b427f200429031820042903204200521b7d220c200c200b5622021b37030820020d042007417f4c0d0c20070d03200e280200280208200641014100101741026a220241024b0d0220020e03040204040b0240200241ff0171450d00200441003a0098010b200a450d030b200d102a0c020b41a0fac5001032000b0240024002402007102e2202450d000240200e280200280208200620022007101741026a220341024b0d0020030e03030002030b41a0fac5001032000b200741011037000b2007410f4d0d00200241086a2900002110200229000021112002102a200441086a200128021029034842002009ad4200109f052001280218220242002002290308220b427f200429030820042903104200521b7d220c200c200b5622021b37030820020d01200141046a210a0240024020092001410c6a220d28020022034b0d00200921020c010b02400240200141086a280200220220036b200920036b2206490d00200a2802002107200321020c010b200320066a22072003490d0d2002410174220e2007200e20074b1b220e4100480d0d0240024020020d00200e102821070c010b200a2802002002200e102c21070b2007450d0c20012007360204200141086a200e3602002001410c6a28020021020b200720026a210e0240024020064102490d00200e410020092003417f7322036a22061099051a2007200920026a20036a6a210e200620026a21020c010b2006450d010b200e41003a0000200241016a21020b200d2002360200024002402001280214280208200820012802042002101741026a220241024b0d0020020e03030001030b41a0fac5001032000b2001410c6a2202280200210720024100360200200141086a28020021032001280204210d2001420137020420012802182202290308220c210b024002402005500d002005210b200c2005540d010b2002200c200b7d3703082002290310210c200441a0016a41186a200241186a2903003703002004200b3703a8012004200b3703a0012004200c3703b001200128020041186a2802002106200441f8006a41186a200441386a41186a290300370300200441f8006a41106a200441386a41106a290300370300200441f8006a41086a200441386a41086a29030037030020042004290338370378200420073602c801200420033602c4012004200d3602c001200441d8006a2006200441f8006a20112010200441a0016a200441c0016a10c101410121090240024020042802584101460d00200441d8006a410472210d200441d8006a41106a2d00002107200441e4006a2802002106200441e0006a2802002103410021090c010b200441e4006a210d200441ec006a2802002106200441d8006a41106a2802002103410021070b200d280200210d200220042903a80120022903087c370308200141086a2802002102024020090d0002402002450d00200a280200102a0b200a200d3602000c0e0b2002450d00200a280200102a0b200a200d3602004180022107410021060c0c0b2002102a0b200041053602000c0b0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b200e41011037000b1031000b2001410c6a2006360200200141086a200336020020004100360200200020073602040b200441d0016a24000bc71006017f017e057f027e037f027e230041e0016b2204240002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042103200241286a2903002105200241346a2802002106200241c4006a2802002107200241d4006a2802002108200241e4006a2802002109200441206a20012802102903484200200241146a280200220aad4200109f052001280218220242002002290308220b427f200429032020042903284200521b7d220c200c200b5622021b3703080240024020020d00200a417f4c0d0902400240024002400240200a0d004101210d02402001280214280208200341014100101741026a220241024b0d00200141146a210e20020e03060002060b41a0fac5001032000b0240200a102e220d450d00024020012802142802082003200d200a101741026a220241024b0d00200141146a210e20020e03030002030b41a0fac5001032000b200a41011037000b41002102200441003a00c80102400340200a2002460d01200441a8016a20026a200d20026a2d00003a00002004200241016a22033a00c8012003210220034120470d000b20044188016a41186a2202200441a8016a41186a29030037030020044188016a41106a2203200441a8016a41106a29030037030020044188016a41086a220f200441a8016a41086a290300370300200420042903a801370388010240200a450d00200d102a0b200441306a41086a200f290300370300200441306a41106a2003290300370300200441306a41186a20022903003703002004200429038801370330200441106a200128021029034842002007ad4200109f052001280218220242002002290308220b427f200429031020042903184200521b7d220c200c200b5622021b37030820020d042007417f4c0d0d20070d03200e280200280208200641014100101741026a220241024b0d0220020e03040204040b0240200241ff0171450d00200441003a00c8010b200a450d030b200d102a0c020b41a0fac5001032000b0240024002402007102e2202450d000240200e280200280208200620022007101741026a220341024b0d0020030e03030002030b41a0fac5001032000b200741011037000b2007410f4d0d00200241086a2900002110200229000021112002102a2004200128021029034842002009ad4200109f052001280218220242002002290308220b427f200429030020042903084200521b7d220c200c200b5622021b37030820020d01200141046a21070240024020092001410c6a220a28020022034b0d00200921020c010b02400240200141086a280200220220036b200920036b2206490d002007280200210d200321020c010b200320066a220d2003490d0e2002410174220e200d200e200d4b1b220e4100480d0e0240024020020d00200e1028210d0c010b20072802002002200e102c210d0b200d450d0d2001200d360204200141086a200e3602002001410c6a28020021020b200d20026a210e0240024020064102490d00200e410020092003417f7322036a22061099051a200d200920026a20036a6a210e200620026a21020c010b2006450d010b200e41003a0000200241016a21020b200a2002360200024002402001280214280208200820012802042002101741026a220241024b0d0020020e03030001030b41a0fac5001032000b2001410c6a2202280200210d20024100360200200141086a28020021032001280204210a2001420137020420012802182202290308220c210b0240024002402005500d002005210b200c2005540d010b2002200c200b7d3703082002290310210c20044188016a41186a200241186a2903003703002004200b370390012004200b370388012004200c37039801200128020041186a28020021062004200d360258200420033602542004200a360250200441a8016a20062011201020044188016a200441306a200441d0006a10b5014101210d0240024020042802a8014101460d00200441d0006a41086a200441a8016a41186a290300370300200441d0006a41106a200441c8016a2802003602002004200441a8016a41106a290300370350200441d8016a2d00002106200441d0016a2802002109200441cc016a2802002108200441b4016a280200210e200441a8016a41086a28020021034100210d20042802ac01210a0c010b200441bc016a280200210e200441b8016a2802002103200441b4016a280200210a410021060b200220042903900120022903087c370308200441f0006a41086a2202200441d0006a41086a290300370300200441f0006a41106a220f200441d0006a41106a280200360200200420042903503703700240200d0d00200441bc016a2002290300370200200441c4016a200f2802003602002004200e3602b001200420033602ac012004200a3602a801200420042903703702b4010240200141086a280200450d002007280200102a0b200120083602042001410c6a4100360200200141086a2009360200200641ff017122020d02200441a8016a2007108f010c020b200141086a280200450d002007280200102a0b2001200a3602042001410c6a4100360200200141086a200336020041800221020b20004100360200200020023602040c020b2002102a0b200041053602000b200441e0016a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b200e41011037000b1031000b9d0503027f037e057f230041206b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441106a20012802102903184200200241146a2802002203ad22064200109f0520012802182202420020022903082207427f200429031020042903184200521b7d2208200820075622021b370308024020020d0020042001280210290348420020064200109f0520012802182202420020022903082207427f200429030020042903084200521b7d2208200820075622021b37030820020d000240024020032001410c6a2209280200220a4b0d00200321020c010b02400240200141086a2802002202200a6b2003200a6b220b490d002001280204210c200a21020c010b200a200b6a220c200a490d062002410174220d200c200d200c4b1b220d4100480d060240024020020d00200d1028210c0c010b20012802042002200d102c210c0b200c450d052001200c360204200141086a200d3602002001410c6a28020021020b200c20026a210d02400240200b4102490d00200d41002003200a417f73220a6a220b1099051a200c200320026a200a6a6a210d200b20026a21020c010b200b450d010b200d41003a0000200241016a21020b20092002360200024002402001280214280208200520012802042002101741026a220241024b0d0020020e03020001020b41a0fac5001032000b2001410c6a2202280200210320024100360200200141086a280200210220012802042105200142013702040240200128021c220a450d00200141206a280200450d00200a102a0b2001200536021c200141246a2003360200200141206a20023602000b20004105360200200441206a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b200d41011037000b1031000b23002001410c6a4100360200200128020041206a200141046a108f01200041043602000b27002001410c6a4100360200200128020028021841d0006a200141046a108f01200041043602000bd50102027f027e410021042001410c6a41003602002001280218220541186a2903002106200529031021070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102821050c010b200128020420052004102c21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b200441011037000b1031000bc20103017f017e017f410021042001410c6a4100360200200128021829030821050240024002400240200141086a28020022064108490d00200128020421060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102821060c010b200128020420062004102c21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441086a360200200620046a2005370000200041043602000f0b200441011037000b1031000bb804020b7f027e230041206b220424002001410c6a41003602000240024002402001280200280218220528021841016a220641004c0d00200541d0006a2107200520063602182005411c6a2108200541206a28020021090240024003402008280200220a41086a210b200a2f0106220c41057421084100210d0240024003402008450d012007200b4120109c05220e450d02200841606a2108200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a210c0b2009450d022009417f6a2109200a200c4102746a41880b6a21080c010b0b200a200d41e0006c6a220841c5036a310000200841e8026a290300220f200f50220b1ba7450d004200200841f8026a290300200b1b210f4200200841f0026a290300200b1b21100c010b200441086a200541286a28020020072005412c6a28020028021c110500200441106a290300210f20052802182106200429030821100b20052006417f6a36021802400240200141086a280200220b2001410c6a28020022086b4110490d002001280204210b0c010b200841106a220d2008490d03200b4101742208200d2008200d4b1b22084100480d0302400240200b0d0020081028210b0c010b2001280204200b2008102c210b0b200b450d022001200b360204200141086a20083602002001410c6a28020021080b2001410c6a200841106a360200200b20086a2208200f3700082008201037000020004104360200200441206a24000f0b41b8b8c0004118200441186a41e0b8c0001038000b200841011037000b1031000bd50102027f027e410021042001410c6a41003602002001280200220541086a2903002106200529030021070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102821050c010b200128020420052004102c21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b200441011037000b1031000b860302047f027e230041c0006b220424000240024002402003450d0020022802000d0020034101460d0120022802100d01410521050240200241146a28020022032001280210220628026c4b0d0020022802042107200441086a200629034842002003ad4200109f0520012802182202420020022903082208427f200429030820042903104200521b7d2209200920085622021b37030820020d002003417f4c0d0302400240024020030d004101210202402001280214280208200741014100101741026a220641024b0d0020060e03040002040b41a0fac5001032000b02402003102e2202450d0002402001280214280208200720022003101741026a220641024b0d0020060e03030002030b41a0fac5001032000b200341011037000b2001410c6a4100360200200441186a2002200310a803410421052004200141046a36023c200441186a2004413c6a10c8012003450d010b2002102a0b20002005360200200441c0006a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b1036000bc20103017f017e017f410021042001410c6a4100360200200128020029031021050240024002400240200141086a28020022064108490d00200128020421060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102821060c010b200128020420062004102c21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441086a360200200620046a2005370000200041043602000f0b200441011037000b1031000bdc0102027f027e410021042001410c6a4100360200200128020028021828024022054180016a2903002106200529037821070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102821050c010b200128020420052004102c21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b200441011037000b1031000bb20803027f047e027f230041e0046b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441286a20012802102903484200200241146a2802002202ad4200109f0520012802182203420020032903082206427f200429032820042903304200521b7d2207200720065622031b3703080240024020030d002002417f4c0d0402400240024020020d004101210302402001280214280208200541014100101741026a220541024b0d0020050e03040002040b41a0fac5001032000b02402002102e2203450d0002402001280214280208200520032002101741026a220541024b0d0020050e03030002030b41a0fac5001032000b200241011037000b2004200236023c20042003360238200441d0036a200441386a108101024020042802d00322054113460d00200441c8026a200441d0036a410472418401109a051a02402002450d002003102a0b200441c0016a200441c8026a418401109a051a20042005360238200441386a410472200441c0016a418401109a051a200441003602d803200442013703d003200441386a200441d0036a10eb0120042802d8032103024020042802d403450d0020042802d003102a0b200128021822022903102206200241186a2903002207844200510d07200441186a2003ad42004280c8afa0254200109f05200441086a200429031822084280a094a58d1d7c2209200441186a41086a2903002009200854ad7c2006200710a00520024200200229030822062004290308427f200441086a41086a290300501b7d220720072006561b37030820072006580d03200441386a106a0c020b2002450d010b2003102a0b410521020c070b20012802002102200441c8026a200441386a418801109a051a200441c0016a41086a2002280218220241d8006a290000370300200441d0016a2203200241e0006a290000370300200441d8016a2205200241e8006a290000370300200420022900503703c001200441d7036a200441c8026a418801109a051a02402002413c6a2802002201200241386a280200470d00200141016a220a2001490d062001410174220b200a200b200a4b1b220aad42b0017e2206422088a70d062006a7220b4100480d060240024020010d00200b102821010c010b2002280234200141b0016c200b102c21010b2001450d0520022001360234200241386a200a360200200228023c21010b2002280234200141b0016c6a220141013a0000200120042903c001370001200141096a200441c8016a290300370000200141116a2003290300370000200141196a2005290300370000200141216a200441d0036a418f01109a051a2002200228023c41016a36023c410421020c060b41b698c40041f4031050000b41b698c40041f4031050000b1036000b419cb7c0001032000b200b41081037000b1031000b20002002360200200441e0046a24000b8c1705087f027e037f027e047f230041a0026b22042400024002400240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620034107460d0720022802700d0720022802042103200241246a2802002105200241346a2802002106200241c4006a2802002107200241d4006a2802002108200241e4006a2802002109200241f4006a280200210a200441206a20012802102903484200200241146a280200220bad4200109f052001280218220242002002290308220c427f200429032020042903284200521b7d220d200d200c5622021b3703080240024020020d00200b417f4c0d0a024002400240200b0d004101210e02402001280214280208200341014100101741026a220241024b0d00200141146a210f20020e03040002040b41a0fac5001032000b0240200b102e220e450d00024020012802142802082003200e200b101741026a220241024b0d00200141146a210f20020e03030002030b41a0fac5001032000b200b41011037000b41002102200441003a00f00102400340200b2002460d01200441d0016a20026a200e20026a2d00003a00002004200241016a22033a00f0012003210220034120470d000b20044180026a41086a2202200441d0016a41086a29030037030020044180026a41106a2203200441d0016a41106a29030037030020044180026a41186a2210200441d0016a41186a290300370300200420042903d001370380020240200b450d00200e102a0b200441306a41086a2002290300370300200441306a41106a2003290300370300200441306a41186a20102903003703002004200429038002370330200441106a200128021029034842002006ad4200109f052001280218220242002002290308220c427f200429031020042903184200521b7d220d200d200c5622021b3703082002450d030c100b0240200241ff0171450d00200441003a00f0010b200b450d010b200e102a0b200441f0006a41186a20044180026a41186a290300370300200441f0006a41106a20044180026a41106a290300370300200441f0006a41086a20044180026a41086a2903003703002004200429038002370370410521020c0e0b2006417f4c0d080240024002400240024020060d004101210b0240200f280200280208200541014100101741026a220241024b0d0020020e03120002120b41a0fac5001032000b02402006102e220b450d000240200f2802002802082005200b2006101741026a220241024b0d0020020e03030002030b41a0fac5001032000b200641011037000b41002102200441003a00f0010240034020062002460d01200441d0016a20026a200b20026a2d00003a00002004200241016a22033a00f0012003210220034120470d000b20044180026a41086a2202200441d0016a41086a29030037030020044180026a41106a2203200441d0016a41106a29030037030020044180026a41186a220e200441d0016a41186a290300370300200420042903d0013703800202402006450d00200b102a0b200441d0006a41086a2002290300370300200441d0006a41106a2003290300370300200441d0006a41186a200e29030037030020042004290380023703502004200128021029034842002008ad4200109f052001280218220242002002290308220c427f200429030020042903084200521b7d220d200d200c5622031b3703084105210220030d112008417f4c0d0c20080d03200f280200280208200741014100101741026a220341024b0d0220030e03110211110b0240200241ff0171450d00200441003a00f0010b2006450d0f0b200b102a410521020c0f0b41a0fac5001032000b024002400240024002402008102e2203450d000240200f280200280208200720032008101741026a220b41024b0d00200b0e03030002030b41a0fac5001032000b200841011037000b2008410f4d0d00200341086a2900002111200329000021122003102a024002400240200a0d00410121064100210b4100210e0c010b20044180026a41186a210320044180026a41106a210520044180026a41086a210841002110410021024100210b4100210e4101210603402003420037030020054200370300200842003703002001280218220742002007290308220d427f2001280210290348220c420586200c42ffffffffffffffff0783200c521b7d220c200c200d5622071b370308200442003703800220070d1102400240200f280200280208200920026a221320044180026a4120101741026a220741024b0d0020070e03130001130b41a0fac5001032000b200441d0016a41186a22142003290300370300200441d0016a41106a22152005290300370300200441d0016a41086a2216200829030037030020042004290380023703d0010240200b200e470d002010200b41016a220e2010200e4b1b220e41ffffff3f71200e470d03200e41057422074100480d0302400240200b0d002007102821060c010b200620022007102c21060b2006450d100b200620026a220720042903d001370000200741186a2014290300370000200741106a2015290300370000200741086a2016290300370000201341206a2013490d11201041026a2110200241206a2102200a200b41016a220b470d000b0b2001280200280218210320044190016a41086a200441306a41086a29030037030020044190016a41106a2201200441306a41106a29030037030020044190016a41186a2205200441306a41186a290300370300200441b0016a41086a200341d8006a290000370300200441b0016a41106a2208200341e0006a290000370300200441b0016a41186a2207200341e8006a2900003703002004200429033037039001200420032900503703b00120044180026a41186a220a200441d0006a41186a29030037030020044180026a41106a2209200441d0006a41106a29030037030020044180026a41086a200441d0006a41086a29030037030020042004290350370380022003413c6a2802002202200341386a280200470d03200241016a220f2002490d0020024101742210200f2010200f4b1b220fad42b0017e220c422088a70d00200ca7221041004e0d020b1031000b2003102a0c0f0b0240024020020d002010102821020c010b2003280234200241b0016c2010102c21020b2002450d0b20032002360234200341386a200f360200200328023c21020b2003280234200241b0016c6a220241023a0000200220042903b0013700012002200429039001370021200241096a200441b0016a41086a290300370000200241116a2008290300370000200241196a2007290300370000200241296a20044190016a41086a290300370000200241316a2001290300370000200241396a2005290300370000200220063600642002200e3600682002200b36006c20022012370370200241f8006a20113703002002200429038002370041200241c9006a20044180026a41086a290300370000200241d1006a2009290300370000200241d9006a200a290300370000200220042f00703b0061200241e3006a200441f0006a41026a2d00003a0000200220042903d0013703800120024188016a200441d0016a41086a29030037030020024190016a200441d0016a41106a29030037030020024198016a200441d0016a41186a290300370300200241a0016a200441f0016a290300370300200241a8016a200441f8016a2903003703002003200328023c41016a36023c410421020c0d0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b200741011037000b201041081037000b41052102200e450d012006102a0c010b410521020b20002002360200200441a0026a24000b16002000410036020020002001410c6a2802003602040bab0202057f027e230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d024105210302402001410c6a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d0020022802042107200128020421082004200128021029035042002005ad4200109f0520012802182202420020022903082209427f200429030020042903084200521b7d220a200a20095622021b37030820020d000240024020012802142802082007200820066a2005101841026a220241024b0d0020020e03020001020b41b0fbc5001032000b410421030b20002003360200200441106a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000bf90303027f027e067f230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002203ad4200109f0520012802182202420020022903082206427f200429030020042903084200521b7d2207200720065622021b37030841052108024020020d000240024020032001410c6a2209280200220a4b0d00200321020c010b02400240200141086a2802002202200a6b2003200a6b220b490d002001280204210c200a21020c010b200a200b6a220c200a490d062002410174220d200c200d200c4b1b220d4100480d060240024020020d00200d1028210c0c010b20012802042002200d102c210c0b200c450d052001200c360204200141086a200d3602002001410c6a28020021020b200c20026a210d02400240200b4102490d00200d41002003200a417f73220a6a220b1099051a200c200320026a200a6a6a210d200b20026a21020c010b200b450d010b200d41003a0000200241016a21020b20092002360200024002402001280214280208200520012802042002101741026a220141024b0d0020010e03020001020b41a0fac5001032000b410421080b20002008360200200441106a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b200d41011037000b1031000bbb0b05047f027e037f017e037f230041e0016b2204240002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d03200241246a2802002105200241346a280200210602400240024002400240200241146a2802002203450d0020022802042107200441306a200128021029034842002003ad4200109f0520012802182202420020022903082208427f200429033020042903384200521b7d22092009200856220a1b37030841052102200a0d0e2003417f4c0d092003102e220a450d0a024020012802142802082007200a2003101741026a220741024b0d0020070e03040002040b41a0fac5001032000b4101210b410021074100210c0c010b2004200336028c012004200a36028801200441c0006a20044188016a106d200429024421082004280240210b200a102a200b450d0c2008a7210c200128021028025c2008422088a72207490d0b0b200b2007410041202007676b10c402024020074102490d00200b21022007210303402002200241206a220a4120109c05450d0c200a21022003417f6a220341024f0d000b0b200441206a200128021029034842002006ad220d4200109f0520012802182202420020022903082208427f200429032020042903284200521b7d2209200920085622021b37030820020d0a2006417f4c0d060240024020060d004101210a02402001280214280208200541014100101741026a220241024b0d0020020e030d00020d0b41a0fac5001032000b024002402006102e220a450d00024020012802142802082005200a2006101741026a220241024b0d0020020e03020003020b41a0fac5001032000b200641011037000b200a102a0c0b0b20042001280210220329032842002007ad4200109f05200441106a20032903204200200d4200109f0520012802182102427f2109024020042903184200520d0020042903084200520d002004290310220820042903007c220d2008540d00427f200d20032903307c22082008200d541b21090b200242002002290308220820097d220920092008561b37030820092008580d012006450d0a200a102a0c0a0b200a102a0c0a0b200441b8016a41086a22052001280200280218220341d8006a290000370300200441b8016a41106a2201200341e0006a290000370300200441b8016a41186a220e200341e8006a290000370300200420032900503703b80102402003413c6a2802002202200341386a280200470d00200241016a220f2002490d0820024101742210200f2010200f4b1b2210ad42b0017e2208422088a70d082008a7220f4100480d080240024020020d00200f102821020c010b2003280234200241b0016c200f102c21020b2002450d0720032002360234200341386a2010360200200328023c21020b2003280234200241b0016c6a220241003a0000200220042f00dd013b0001200241053a00102002200736000c2002200c3600082002200b360004200220042903b801370011200241036a200441dd016a41026a2d00003a0000200241196a2005290300370000200241216a2001290300370000200241296a200e2903003700002002200a360034200220063600382002200636003c200220042f00b5013b0031200241336a200441b5016a41026a2d00003a00002002200429038801370340200241c8006a20044188016a41086a290300370300200241d0006a20044188016a41106a290300370300200241d8006a20044188016a41186a290300370300200241e0006a200441a8016a290300370300200241e8006a200441c0006a41c800109a051a2003200328023c41016a36023c410421020c090b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b200341011037000b200f41081037000b1031000b41052102200c450d00200b102a0b20002002360200200441e0016a24000b8e0a03027f027e057f230041e00b6b220424000240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002202ad4200109f0520012802182203420020032903082206427f200429030020042903084200521b7d2207200720065622081b3703084105210320080d052002417f4c0d02024020020d0002402001280214280208200541014100101741026a220241024b0d0020020e03070007070b41a0fac5001032000b02400240024002402002102e2208450d0002402001280214280208200520082002101741026a220541024b0d0020050e03030002030b41a0fac5001032000b200241011037000b2002410f4b0d010b2008102a0c060b200841086a2900002106200829000021072008102a200128020028021822092802180d032009417f360218200441c8006a200941e8006a290000370300200441c0006a200941e0006a290000370300200441306a41086a200941d8006a29000037030020042009290050370330024002402009411c6a220a280200220841f8b9c000460d00200941206a280200210b0c010b4100210b20044180096a410041e0021099051a200441e0006a410041a0081099051a41880b10282208450d05200841003b010620084100360200200841086a20044180096a41e002109a051a200841e8026a200441e0006a41a008109a051a200941206a41003602002009200836021c0b02400240034020082f0106220c4105742105410021024100210102400240034020052002460d01200441306a200820026a41086a4120109c052203450d02200241206a2102200141016a21012003417f4a0d000b2001417f6a210c0b200b450d02200b417f6a210b2008200c4102746a41880b6a28020021080c010b0b200941246a2103410121020c010b200441106a41186a200441306a41186a290300370300200441106a41106a200441306a41106a290300370300200441106a41086a200441306a41086a29030037030020042004290330370310200941246a21034100210b200c2101410021020b0240024020020d002004419c096a200441106a41086a290300370200200441a4096a200441106a41106a290300370200200441ac096a200441106a41186a29030037020020042003360290092004200136028c092004200a3602880920042008360284092004200b36028009200420042903103702940920044180016a200429035037030020044188016a200441d0006a41086a29030037030020044194016a42003702002004420037037820044200370360200441f8b9c00036029001200441003a009c012004419d016a2004290030370000200441a5016a200441306a41086a290000370000200441ad016a200441306a41106a290000370000200441b5016a200441306a41186a290000370000200441003a00bd0120044180096a200441e0006a10b70121020c010b200441f8006a4200370300200441f4006a41f8b9c00036020020044100360280012004410036027020044200370368200441f8b9c000360264200441003602602008200141e0006c6a41e8026a2102200441e0006a1095010b200241286a2006370300200241206a2007370300200242013703182009200928021841016a360218410421030c050b41b698c40041f4031050000b41b698c40041f4031050000b1036000b41a8b8c0004110200441e0006a41d0b8c0001038000b41880b41081037000b20002003360200200441e00b6a24000ba30203037f027e027f230041206b220424002001410c6a22054100360200200441086a2001280200280218220641186a200641d0006a10a801200441086a41106a290300210720042802082106200429031021080240024002400240200141086a2802002209200528020022056b4110490d00200128020421090c010b200541106a220a2005490d0220094101742205200a2005200a4b1b22054100480d020240024020090d002005102821090c010b200128020420092005102c21090b2009450d0120012009360204200141086a20053602002001410c6a28020021050b2001410c6a200541106a360200200920056a22012007427f20061b37000820012008427f20061b37000020004104360200200441206a24000f0b200541011037000b1031000bee0203027f027e017f230041206b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002202ad4200109f0520012802182203420020032903082206427f200429030020042903084200521b7d2207200720065622081b37030841052103024020080d002002417f4c0d0302400240024020020d004101210802402001280214280208200541014100101741026a220141024b0d0020010e03040002040b41a0fac5001032000b02402002102e2208450d0002402001280214280208200520082002101741026a220141024b0d0020010e03030002030b41a0fac5001032000b200241011037000b200441106a200820021054024020042802100d002004280214200441186a280200100b0b410421032002450d010b2008102a0b20002003360200200441206a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b1036000bbe0101037f410021042001410c6a4100360200200128020028021c21050240024002400240200141086a28020022064104490d00200128020421060c010b200641017422044104200441044b1b22044100480d020240024020060d002004102821060c010b200128020420062004102c21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441046a360200200620046a2005360000200041043602000f0b200441011037000b1031000bc205020a7f017e230041c0006b220424002004200136020c20042000410120011b3602082004200441086a106c024020042802000d000240024002400240024002400240200428020c22014170712200417f4c0d002004280204210502400240200141047622060d00410821070c010b200010282207450d020b02402005450d00200441206a4104722108410021094100210a410021000340200441206a200441086a109803200441306a41086a220b200841086a2802003602002004200829020037033002402004280220220c4104470d002006450d0a2007102a0c0a0b200041016a2101200441106a41086a220d200b28020036020020042004290330370310024020002006470d0020092001200920014b1b220641ffffffff00712006470d062006410474220b4100480d060240024020000d00200b102821070c010b2007200a200b102c21070b2007450d050b2007200a6a2200200c360200200041046a20042903103702002000410c6a200d280200360200200941026a2109200a41106a210a2001210020052001470d000b0b2007450d07200441206a200220072005200311060020042802202100410110282201450d042004428180808010370234200420013602300240024020004105460d00200141003a0000200141014102102c2101024020004104470d002001450d08200141003a00012004428280808020370234200420013602304202210e0c020b2001450d08200141013a0001200442828080802037023420042001360230200441206a200441306a1099032004350238210e200428023021010c010b200141013a00004201210e0b2001ad422086200e84210e02402006450d002007102a0b200441c0006a2400200e0f0b1036000b200041081037000b200b41081037000b1031000b410141011037000b410241011037000b410241011037000b41b8c6c20041f000200441206a41c0c5c2001038000bde0202047f017e02400240024002400240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a3602002004417f6a220441034b0d0520040e0401020304010b200041043602000f0b0240200541034b0d00200041043602000f0b200041003602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b024020054108490d0020004101360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b0240200541034b0d00200041043602000f0b200041023602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b024020054108490d0020004103360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b200041043602000b840b02037f017e024002400240024002400240024002400240024002400240024020002802000e0400010203000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0c200241017422042003200420034b1b22044100480d0c0240024020020d002004102821030c010b200128020020022004102c21030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d0c200241017422002004200020044b1b22004100480d0c0240024020020d002000102821020c010b200128020020022000102c21020b2002450d0520012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0b200241017422042003200420034b1b22044100480d0b0240024020020d002004102821030c010b200128020020022004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d0b200241017422002003200020034b1b22004100480d0b0240024020020d002000102821020c010b200128020020022000102c21020b2002450d0620012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0a200241017422042003200420034b1b22044100480d0a0240024020020d002004102821030c010b200128020020022004102c21030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d0a200241017422002004200020044b1b22004100480d0a0240024020020d002000102821020c010b200128020020022000102c21020b2002450d0720012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d09200241017422042003200420034b1b22044100480d090240024020020d002004102821030c010b200128020020022004102c21030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41043a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d09200241017422002003200020034b1b22004100480d090240024020020d002000102821020c010b200128020020022000102c21020b2002450d0820012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b200441011037000b200041011037000b200441011037000b200041011037000b200441011037000b200041011037000b200441011037000b200041011037000b1031000bfd0201057f230041d0006b220224002002410036022820014110200241286a10062103024002400240024020022802282204417f460d0020030d010b200041023a00000c010b2004450d0120032d0000220541014b0d01410021010240024020050e020100010b41002101200241003a00482004417f6a2105200341016a21060340024020052001470d00200141ff0171450d04200241003a00480c040b200241286a20016a200620016a2d00003a00002002200141016a22043a00482004210120044120470d000b200241086a41186a200241286a41186a290300370300200241086a41106a200241286a41106a290300370300200241086a41086a200241286a41086a29030037030020022002290328370308410121010b200020013a000020002002290308370001200041096a200241106a290300370000200041116a200241186a290300370000200041196a200241206a2903003700002003102a0b200241d0006a24000f0b41c4d1c3004133200241286a419cd9c3001038000b1300200041013602042000418cc8c2003602000b340020004195c9c20036020420004100360200200041146a4103360200200041106a41a0c9c200360200200041086a420a3702000b2f01017f02404101102822020d00410141011037000b200042818080801037020420002002360200200241003a00000b8b5606077f017e067f027e037f037e230041e0036b22012400200141d8006a41086a220242003703002001420037035841e7fcc5004110200141d8006a100820014190016a41086a20022903003703002001200129035837039001200141e8026a20014190016a109a0302400240024002400240024002400240024002400240024020012d00e80222024102470d00200141d8006a21030c010b20014190016a4110100920014188026a41086a200141f1026a29000037030020014188026a41106a200141e8026a41116a29000037030020014188026a41186a220420014181036a290000370300200120012900e90237038802200141d8006a21030240200241037122024103460d0020020e03010001010b200141a0016a41186a2004290300370300200141a0016a41106a20014188026a41106a290300370300200141a0016a41086a20014188026a41086a29030037030020012001290388023703a001200141d8006a41086a220242003703002001420037035841c0fcc5004111200141d8006a100820014190016a41086a2002290300370300200120012903583703900141002105200141003602e80220014190016a4110200141e8026a10062102024020012802e8022204417f460d002002450d0020044104490d02200228000021052002102a0b411610282202450d022002410e6a41002900dffc45370000200241086a41002900d9fc45370000200241002900d1fc4537000020024116412c102c2202450d0320022005360016200141d8006a41186a22044200370300200141d8006a41106a22064200370300200141d8006a41086a22074200370300200142003703582002411a200141d8006a1000200141e8026a41186a2004290300370300200141e8026a41106a2006290300370300200141e8026a41086a2007290300370300200120012903583703e8022002102a20014100360258200141e8026a4120200141d8006a1006210202400240024020012802582206417f460d002002450d0020012006360294012001200236029001200141d8006a20014190016a107320012802582204450d07200129025c210802402006450d002002102a0b200120043602782001200837027c2008a721022008422088a72206418002490d01412010282206450d08200620012903a001370000200641186a200141a0016a41186a290300370000200641106a200141a0016a41106a290300370000200641086a200141a0016a41086a29030037000020014281808080103702ec02200120063602e802200541016a2205200141e8026a109f032006102a200141d8006a41086a220642003703002001420037035841c0fcc5004111200141d8006a100820014190016a41086a20062903003703002001200129035837039001200120053602e80220014190016a4110200141e8026a410410070c020b4100210620014100360280012001420137037841012104410021020b200141e8026a41186a2209200141a0016a41186a290300370300200141e8026a41106a220a200141a0016a41106a290300370300200141e8026a41086a220b200141a0016a41086a290300370300200120012903a0013703e802024020062002470d00200241016a22072002490d0c2002410174220c2007200c20074b1b220741ffffff3f712007470d0c2007410574220c4100480d0c0240024020020d00200c102821040c010b20042002410574200c102c21040b2004450d082001200736027c20012004360278200721020b200420064105746a220720012903e802370000200741186a2009290300370000200741106a200a290300370000200741086a200b2903003700002001200641016a360280012005200141f8006a109f030b2002450d002004102a0b200141d8006a41086a220242003703002001420037035841d8a1c6004113200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141003602a001200141e8026a4110200141a0016a1006210202400240024020012802a0012204417f460d002002450d002004450d0120022d000021042002102a200141e8026a4110100920044102460d0020044101710d020b41c0acc3001032000b41c4d1c3004133200141d8036a419cd9c3001038000b200141d8006a41086a220242003703002001420037035841afc5c2004111200141d8006a100820014190016a41086a22042002290300370300200120012903583703900120014190016a41101009200242003703002001420037035841c8fbc5004117200141d8006a100820042002290300370300200120012903583703900120014190016a41101009200242003703002001420037035841feadc4004117200141d8006a1008200141e8026a41086a22042002290300370300200120012903583703e8020240200141e8026a41104101410041001003417f470d0010a0032108200242003703002001420037035841feadc4004117200141d8006a100820042002290300370300200120012903583703e802200120083703a001200141e8026a4110200141a0016a410810070b2002420037030020014200370358418194c1004110200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a1006210220012802e8022204417f460d072002450d0720044104490d062002280000210d2002102a200141a0016a41101009410121090c080b41c4d1c3004133200141d8036a419cd9c3001038000b411641011037000b412c41011037000b41c4d1c3004133200141d8036a419cd9c3001038000b412041011037000b200c41011037000b41c4d1c3004133200141d8036a419cd9c3001038000b410021090b200141d8006a41086a220242003703002001420037035841d591c6004115200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a10062102024002400240024002400240024002400240024002400240024020012802e8022204417f460d002002450d002004450d0b20022d000021042002102a20044102460d0020044101710d010b410410282204450d0120044100360200200141d8006a41086a2202420037030020014200370358419194c1004115200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602f002200142013703e8024101200141e8026a10b401200428020021070240024020012802ec02220520012802f00222066b4104490d0020012802e80221020c010b200641046a22022006490d0d2005410174220a2002200a20024b1b220a4100480d0d0240024020050d00200a102821020c010b20012802e8022005200a102c21020b2002450d032001200a3602ec02200120023602e802200a21050b2001200641046a220a3602f002200220066a2007360000200141a0016a41102002200a100702402005450d002002102a0b2004102a410410282204450d0320044100360200200141d8006a41086a2202420037030020014200370358418898c1004116200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602f002200142013703e8024101200141e8026a10b401200428020021070240024020012802ec02220520012802f00222066b4104490d0020012802e80221020c010b200641046a22022006490d0d2005410174220a2002200a20024b1b220a4100480d0d0240024020050d00200a102821020c010b20012802e8022005200a102c21020b2002450d052001200a3602ec02200120023602e802200a21050b2001200641046a220a3602f002200220066a2007360000200141a0016a41102002200a100702402005450d002002102a0b2004102a200141d8006a41086a2202420037030020014200370358419e98c1004110200141d8006a1008200141a0016a41086a22042002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a41041007200141013a00e802200242003703002001420037035841d591c6004115200141d8006a100820042002290300370300200120012903583703a001200141a0016a4110200141e8026a410110070b200141d8006a41086a2202420037030020014200370358419194c1004115200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a100621020240024020012802e8022204417f460d002002450d002001200436028c022001200236028802200141e8026a20014188026a10820120012802e802220e450d0620012902ec02210f2004450d012002102a0c010b4104210e4200210f0b200141d8006a41086a2202420037030020014200370358418898c1004116200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a100621020240024020012802e8022204417f460d002002450d002001200436028c022001200236028802200141e8026a20014188026a10820120012802e8022207450d0720012902ec02211002402004450d002002102a0b20012007360288022010422088a7210c0c010b4104210720014104360288024100210c420021100b200f422088a72111024020090d002011417f6a220220114f0d07200220114b0d07200e20024102746a280200210d0b41002011419c7f6a22022002201141016a4b1b221220114b0d07200e20124102746a21132012450d0a200cad2108200e210b0340200b2802002109024002400240024002402008a7220a41014b0d0041002102200a0e020201020b41002102200a2104034020022004410176220620026a22052009200720054102746a280200491b2102200420066b220441014b0d000b0b20092007200241027422046a2802002206460d022002200920064b6a21020c010b410021020b200120023602e80241d498c100412e200141e8026a418499c1001038000b20082002ad580d09200720046a2204200441046a2002417f73200a6a410274109b051a201042ffffffff0f83200a417f6a220cad422086842110200b41046a220b2013460d0b2008427f7c210820012802880221070c000b0b410441041037000b200a41011037000b410441041037000b200a41011037000b41c4d1c3004133200141d8036a419cd9c3001038000b41c4d1c3004133200141d8036a419cd9c3001038000b41ae98c10041261050000b41e4e8c5001032000b41b0b1c0001032000b41c4d1c3004133200141d8036a419cd9c3001038000b200f42ffffffff0f8321080240201120126b2202450d0002402012450d00200e20132002410274109b051a2010422088a7210c0b20082002ad4220868421080b2001280288022107410021020240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200c41014b0d00200c0e020201020b200c2104034020022004410176220620026a2205200d200720054102746a280200491b2102200420066b220441014b0d000b0b0240200d200720024102746a2802002204460d002002200d20044b6a21020b200c2002490d010b200c2010a7470d02200c41016a2204200c490d13200c41017422062004200620044b1b220441ffffffff03712004470d132004410274220641004e0d010c130b41f8b0c0001032000b02400240200c0d002006102821070c010b2007200c4102742006102c21070b2007450d0120012007360288022004ad21100b200720024102746a220441046a2004200c20026b410274109b051a2004200d36020002402008422088220fa722042008a7470d00200441016a22022004490d11200fa722054101742206200220022006491b220241ffffffff03712002470d11200241027422064100480d110240024020040d0020061028210e0c010b200e20054102742006102c210e0b200e450d022008422088a721042002ad21080b200e20044102746a200d3602000240200c41016a22130d00419499c1001032000b2013201341017622024d0d02200128028802220620024102746a280200210d024020134101710d0020132002417f6a22024d0d04200620024102746a280200200d6a410176210d0b200141d8006a41086a2202420037030020014200370358419194c1004115200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602f002200142013703e802200441016a2211200141e8026a10b4010240024020110d0020012802f002210920012802ec02210720012802e80221040c010b410020012802f00222026b2106200441027441046a210a20012802ec022107200e210503402005280200210b02400240200720066a4104490d0020012802e80221040c010b200241046a22042002490d13200741017422092004200920044b1b22094100480d130240024020070d002009102821040c010b20012802e80220072009102c21040b2004450d07200120093602ec02200120043602e802200921070b200541046a21052001200241046a22093602f002200420026a200b3600002006417c6a210620092102200a417c6a220a0d000b0b2008a72102200141a0016a411020042009100702402007450d002004102a0b02402002450d00200e102a0b200128028802210e200141d8006a41086a2202420037030020014200370358418898c1004116200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200142013703e802200141003602f0022013200141e8026a10b401200c41027441046a2109410020012802f00222026b21062010a7210c20012802ec022107200e210503402005280200210b02400240200720066a4104490d0020012802e80221040c010b200241046a22042002490d122007410174220a2004200a20044b1b220a4100480d120240024020070d00200a102821040c010b20012802e8022007200a102c21040b2004450d072001200a3602ec02200120043602e802200a21070b200541046a21052001200241046a220a3602f002200420026a200b3600002006417c6a2106200a21022009417c6a22090d000b200141a0016a41102004200a100702402007450d002004102a0b0240200c450d00200e102a0b200141d8006a41086a2202420037030020014200370358419e98c1004110200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a0012001200d3602e802200141a0016a4110200141e8026a410410070240201141e500470d00200d419a086a1098014b0d00200141d8006a41086a220442003703002001420037035841d985c2004117200141d8006a1008200141e8026a41086a2004290300370300200120012903583703e802410810282204450d072004200d360004200441e400360000200141e8026a41102004410810072004102a0b200242003703002001420037035841f9b5c200411d200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141003602a001200141e8026a4110200141a0016a10062102024020012802a0012204417f460d002002450d0020012002360288022001200436028c0220044104490d0c2001200241046a3602880220012004417c6a220636028c0220064104490d0c200228000021072001200441786a36028c022001200241086a360288022002280004210b200141a0016a20014188026a107720012802a001220a450d0c20012902a40121144100210502400240200128028c0222040d000c010b20012004417f6a220936028c022001200128028802220641016a36028802024020062d00004101460d000c010b20094104490d0020012004417b6a36028c022001200641056a360288022006280001210c410121050b2002102a2014422088a72109024020072000470d00024020050d002009ad42287e2208422088a70d0a2008a72202417f4c0d0a0240024020020d004108210c0c010b20021028220c450d0c0b4100210602402009450d00200941286c210541002106200c2102200a21040340200441086a2903002108200441106a2903002110200441186a290300210f20042903002115200241206a200441206a290300370300200241186a200f370300200241106a2010370300200241086a200837030020022015370300200241286a2102200641016a2106200441286a2104200541586a22050d000b0b200141b0016a200b360200200141a0016a410c6a2006360200200141a0016a41086a20093602002001200c3602a401200141003602a001200141e8026a200141a0016a10c30120014193026a200141e8026a41086a280200360000200120012903e80237008b02200141e8026a410c6a2001418f026a290000370000200141c6a4b9da043600e902200141023a00e80220012001290088023700ed02200141e8026a10ce012009450d01200c102a0c010b2009ad42287e2208422088a70d092008a72202417f4c0d090240024020020d00410821130c010b200210282213450d0c0b0240024020090d00410021060c010b200941286c21054100210620132102200a21040340200441086a2903002108200441106a2903002110200441186a290300210f20042903002115200241206a200441206a290300370300200241186a200f370300200241106a2010370300200241086a200837030020022015370300200241286a2102200641016a2106200441286a2104200541586a22050d000b0b200141b4016a200b360200200141b0016a2006360200200141a0016a410c6a2009360200200141a0016a41086a20133602002001200c3602a401200141013602a001200141e8026a200141a0016a10c30120014193026a200141e8026a41086a280200360000200120012903e80237008b02200141e8026a410c6a2001418f026a290000370000200141c6a4b9da043600e902200141023a00e80220012001290088023700ed02200141e8026a10ce012009450d002013102a0b2014a7210c0240200b20076a2000470d00200141d8006a41086a220242003703002001420037035841c694c600411b200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141003602a801200142013703a0012009200141a0016a10b40102402009450d00200a200941286c6a2107200a210403402004200141a0016a108f01200441206a29030021080240024020012802a401220620012802a80122026b4108490d0020012802a00121060c010b200241086a22052002490d15200641017422022005200220054b1b22024100480d150240024020060d002002102821060c010b20012802a00120062002102c21060b2006450d0f200120023602a401200120063602a00120012802a80121020b2001200241086a3602a801200620026a20083700002007200441286a2204470d000b0b20012802a4012102200141e8026a411020012802a001220420012802a801100702402002450d002004102a0b200141e8026a41106a2009360200200141f4026a200c360200200141e8026a41086a2202200a360200200141003602ec022001410a3a00e80241014100200141e8026a10cc01200141d8006a41086a220442003703002001420037035841f9b5c200411d200141d8006a100820022004290300370300200120012903583703e802200141e8026a411010090c010b200c450d00200a102a0b200141d8006a41086a22024200370300200142003703584196b6c2004115200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141003602a001200141e8026a4110200141a0016a1006210220012802a0012204417f460d0f2002450d0f2004450d0e20022d0000220641034b0d0e0240024020060e04010f0100010b2004417f6a41074b0d0d0c0f0b2002102a0c0f0b200641041037000b200641041037000b41ac99c100200220131034000b41ac99c100200220131034000b200941011037000b200a41011037000b410841011037000b1036000b200241081037000b200241081037000b200241011037000b41c4d1c3004133200141d8036a419cd9c3001038000b20022800052106200228000121042002102a024020042000470d00200141043602a001200120063602a401200141e8026a200141a0016a10c30120014193026a200141f0026a280200360000200120012903e80237008b02200141f4026a2001418f026a290000370000200141c6a4b9da043600e902200141023a00e80220012001290088023700ed02200141e8026a10ce010b200620046a2000470d022001410036028802200141d8006a41086a22024200370300200142003703584196b6c2004115200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141a0016a20014188026a10da02200141e8026a411020012802a001220220012802a8011007024020012802a401450d002002102a0b200141023602ec022001410a3a00e80241014100200141e8026a10cc010c020b2004417f6a4108490d0020022800052106200228000121042002102a024020042000470d00200141033602a001200120063602a401200141e8026a200141a0016a10c30120014193026a200141f0026a280200360000200120012903e80237008b02200141f4026a2001418f026a290000370000200141c6a4b9da043600e902200141023a00e80220012001290088023700ed02200141e8026a10ce010b200620046a2000470d012001410236028802200141d8006a41086a22024200370300200142003703584196b6c2004115200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141a0016a20014188026a10da02200141e8026a411020012802a001220220012802a8011007024020012802a401450d002002102a0b200141013602ec022001410a3a00e80241014100200141e8026a10cc010c010b41c4d1c3004133200141d8036a419cd9c3001038000b02400240024002400240024020004180e101700d00200141e8026a10d301200141c8006a200141e8026a1091012001200141c8006a41086a29030022083703800120012001290348221037037820014180036a2008370300200141e8026a41106a2010370300200141e8026a41086a220441013a00002001410b3a00e8024100210241014100200141e8026a10cc01200141003a008f012001420037039801200142003703900120044200370300200142003703e8024181a2c6004112200141e8026a1008200141a0016a41086a2004290300370300200120012903e8023703a001200141003602e802200141a0016a4110200141e8026a100621040240024020012802e8022206417f470d000c010b024020040d000c010b2001200636028c022001200436028802200141e8026a20014188026a10820120012802e8022202450d0620012902ec0221082006450d002004102a0b2002410420021b210c024002402008420020021b2214422088a722040d004100210b0c010b200141f1026a210d200141c8026a211320014188026a41206a210e200141a0016a41086a2109200141a0036a21114100210a4100210b41002102024003400240024002400240200b450d00200c20024102746a2106200c2002200a6a4102746a21050340200220044f0d02200141a0016a2006280200220710e90220012903a0014201520d0420014188026a200941e000109a051a2001290378220f200129038802221554200141f8006a41086a290300220820014188026a41086a29030022105420082010511b450d03200141013a008f010240200a20026a220720044f0d0020052006280200360200200641046a2106200541046a2105200241016a22022004490d010c070b0b41c4b2c000200720041034000b200c20024102746a21060340200220044f0d01200141a0016a2006280200220710e90220012903a0014201520d0320014188026a200941e000109a051a2001290378220f20012903880222155a200141f8006a41086a290300220820014188026a41086a29030022105a20082010511b0d02200641046a2106200141013a008f01200241016a22022004490d000b4100210b0c050b41e8b1c000200220041034000b2001200f20157d3703782001200820107d200f201554ad7d37038001411210282206450d05200641106a41002f008086423b0000200641086a41002900f88542370000200641002900f08542370000200641124124102c2206450d0620062007360012200341186a22054200370000200341106a22124200370000200341086a22004200370000200342003700002006411620031000200141e8026a41186a2005290000370300200141e8026a41106a2012290000370300200141e8026a41086a2000290000370300200120032900003703e8022006102a200141e8026a41201009200e20012903980220014188026a41186a29030010aa02200141386a201320012903880220014188026a41086a220629030010d00120014190016a41086a2205427f20052903002208200141386a41086a2903007c200129039001221020012903387c220f2010542205ad7c22102005201020085420102008511b22051b3703002001427f200f20051b37039001200129038802210820112006290300370300200d2013290000370000200d41086a201341086a290000370000200d41106a201341106a290000370000200d41186a201341186a2900003700002001200837039803200141023a00f0022001410b3a00e802200120073602940341014100200141e8026a10cc010b200a417f6a210a200b41016a210b200241016a22022004490d000b0b200b450d00200220044f0d00200c20024102746a2206200b4102746b2006200420026b410274109b051a0b200141e8026a41086a22024200370300200142003703e8024181a2c6004112200141e8026a1008200141a0016a41086a2002290300370300200120012903e8023703a00102400240200c0d00200141a0016a411010090c010b200141003602f002200142013703e8022004200b6b2204200141e8026a10b4010240024020040d0020012802f002210920012802ec02210720012802e80221040c010b410020012802f00222026b2106200c20044102746a210b20012802ec022107200c210503402005280200210a02400240200720066a4104490d0020012802e80221040c010b200241046a22042002490d0a200741017422092004200920044b1b22094100480d0a0240024020070d002009102821040c010b20012802e80220072009102c21040b2004450d07200120093602ec02200120043602e802200921070b2001200241046a22093602f002200420026a200a3600002006417c6a210620092102200b200541046a2205470d000b0b2014a72102200141a0016a411020042009100702402007450d002004102a0b2002450d00200c102a0b024020012d008f010d004200210f200141286a20012903782208200141f8006a41086a2202290300221042c0843d420010a005200141186a20012903282215200141286a41086a290300221442c0fb42427f109f05200141086a2015201442a0c21e4200109f05200220102010200141086a41086a29030020012903082215200820012903187c42018842ffffffff0f837c2214201554ad7c22152014200856201520105620152010511b22041b22157d20082008201420041b221054ad7d3703002001200820107d370378200141e8026a41086a22024200370300200142003703e80241ace1c0004116200141e8026a1008200141d8006a41086a2002290300370300200120012903e802370358200141003602e802200141d8006a4110200141e8026a100621020240024020012802e8022204417f470d00420021080c010b20044110490d06200241086a29000021082002290000210f2002102a0b200141e8026a41086a22044200370300200142003703e80241ace1c0004116200141e8026a1008200141d8006a41086a2004290300370300200120012903e80237035820014200200820157d200f201054ad7d2214200f20107d2216200f56201420085620142008511b22021b3703f00220014200201620021b3703e802200141d8006a4110200141e8026a4110100720014190016a41086a2206427f200629030022142008201520021b7c2001290390012208200f201020021b7c220f2008542202ad7c22082002200820145420082014511b22021b3703002001427f200f20021b3703900120014180036a2015370300200141e8026a41106a2010370300200441033a00002001410b3a00e80241014100200141e8026a10cc010b200141e8026a10d30120014188026a200141e8026a200129039001220820014190016a41086a29030022104102109802024002402001280288020d00200141a0016a41106a201020014188026a41106a29030022157d2008200129039002220f54ad7d201520107d200f200854ad7d200f2008582015201058201520105122021b22041b37030020012008200f7d200f20087d20041b3703a8012001200f200856201520105620021b2202ad3703a001200141a0016a41086a2104024020020d0020012004360258200141d8006a109c010c020b20012004360258200141d8006a109d010c010b41abb6c20041ca00100b200120103703a801200120083703a0012001200141a0016a3602880220014188026a109c010b2001290378210820014180036a200141f8006a41086a290300370300200141f8026a2008370300200141e8026a41086a41043a00002001410b3a00e80241014100200141e8026a10cc010b200141d8006a41086a220242003703002001420037035841affec5004111200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141e8026a41101009200141e0036a24000f0b411241011037000b412441011037000b200941011037000b41c4d1c3004133200141d8036a419cd9c3001038000b41c4d1c3004133200141d8036a419cd9c3001038000b1031000bf52901047f230041c0006b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240411610282203450d002003410e6a41002900dffc45370000200341086a41002900d9fc45370000200341002900d1fc4537000020034116412c102c2203450d0120032000360016200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a22054200370300200242003703202003411a200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002003102a200128020021032001280208210120024100360228200242013703202001200241206a10b40102402001450d00200320014105746a2105034002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d052002200436022420022000360220200228022821010b2002200141016a360228200020016a20032d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d062002200436022420022000360220200228022821010b2002200141016a360228200020016a200341016a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d072002200436022420022000360220200228022821010b2002200141016a360228200020016a200341026a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d082002200436022420022000360220200228022821010b2002200141016a360228200020016a200341036a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d092002200436022420022000360220200228022821010b2002200141016a360228200020016a200341046a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0a2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341056a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0b2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341066a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0c2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341076a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0d2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341086a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0e2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341096a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0f2002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410a6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d102002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410b6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d112002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410c6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d122002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410d6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d132002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410e6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d142002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410f6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d152002200436022420022000360220200228022821010b2002200141016a360228200020016a200341106a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d162002200436022420022000360220200228022821010b2002200141016a360228200020016a200341116a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d172002200436022420022000360220200228022821010b2002200141016a360228200020016a200341126a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d182002200436022420022000360220200228022821010b2002200141016a360228200020016a200341136a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d192002200436022420022000360220200228022821010b2002200141016a360228200020016a200341146a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1a2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341156a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1b2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341166a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1c2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341176a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1d2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341186a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1e2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341196a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1f2002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411a6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d202002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411b6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d212002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411c6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d222002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411d6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d232002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411e6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d242002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411f6a2d00003a0000200341206a22032005470d000b0b2002280224210320024120200228022022012002280228100702402003450d002001102a0b200241c0006a24000f0b411641011037000b412c41011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b1031000bab0103017f017e027f230041206b2200240042002101200041106a41086a220242003703002000420037031041feb3c300410d200041106a1008200041086a2002290300370300200020002903103703002000410036021020004110200041106a100621020240024020002802102203417f460d002002450d0020034108490d01200229000021012002102a0b200041206a240020010f0b41c4d1c3004133200041106a419cd9c3001038000b0a0041d0c5c2001032000b3400200041bfcec20036020420004100360200200041146a4109360200200041106a41c4cec200360200200041086a42043702000bcf0101017f024002400240024002400240410110282202450d00200241003a0000200241014102102c2202450d01200241003a0001200241024104102c2202450d02200241003b0002200241044108102c2202450d0320024100360004200241084110102c2202450d0420024200370008200241104120102c2202450d052002420037001820024200370010200042a08080808004370204200020023602000f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b130020004102360204200041a0e1c2003602000b3101017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242b8173700000b3101017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242c8013700000bcb0201047f230041d0006b220324002003410036022820012002200341286a1006210402400240024020032802282205417f460d0020040d010b200041003a00000c010b41002101200341003a00480340024020052001470d000240200141ff0171450d00200341003a00480b41c4d1c3004133200341286a419cd9c3001038000b200341286a20016a200420016a2d00003a00002003200141016a22023a00482002210120024120470d000b200341086a41186a2201200341286a41186a290300370300200341086a41106a2202200341286a41106a290300370300200341086a41086a2206200341286a41086a2903003703002003200329032837030802402005450d002004102a0b20002003290308370001200041013a0000200041196a2001290300370000200041116a2002290300370000200041096a20062903003700000b200341d0006a24000bd31803017f017e2b7f230041b00d6b22032400200320023602042003200136020042002104200341086a41086a220142003703002003420037030841aef2c2004115200341086a1008200341900d6a41086a2001290300370300200320032903083703900d200341e80c6a200341900d6a10a903024002400240024020032802ec0c22050d00410121050c010b20032903f00c220442ffffffff0f560d010b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b20032802e80c2101200341086a410041e00c1099051a200541206a21062001411874411875210120052004422088a74105746a210741002108410021094100210a4100210b4100210c4100210d4100210e4100210f410021104100211141002112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f4100212041002121410021224100212341002124410021254100212641002127200521024100212841d1002129024003402028212a02400240024002402001450d0020072005460d01200141016a210103400240024020022007470d002006212b200621022005212c0c010b2002212c200241206a222b21020b2001417f6a22010d000c030b0b024020022007460d00200241206a212b2002212c0c030b2006212b2005212c20072005460d040c010b200141016a2101034020072002460d04200241206a21022001417f6a22010d000b200241606a212c2002212b0b202c450d020b202b21020240024002400240024002402003280204220141056a222b417f4c0d002003280200212d02400240202b450d00202b10282228450d034100212e200341003602980d2003202b3602940d200320283602900d0c010b200341003602980d2003202b3602940d200341013602900d410110282228450d03200341013602940d200320283602900d20032802980d212e0b2003202e41016a3602980d2028202e6a202a3a00002001200341900d6a10b4010240024020032802940d222e20032802980d222b6b2001490d0020032802900d212e0c010b202b20016a2228202b490d05202e410174222b2028202b20284b1b222b4100480d0502400240202e0d00202b1028212e0c010b20032802900d202e202b102c212e0b202e450d042003202b3602940d2003202e3602900d20032802980d212b0b2003202b20016a3602980d202e202b6a202d2001109a051a2003200341900d6a36028c0d202c2003418c0d6a10c80120032802940d212c20032802900d210120032802980d212b200341900d6a41186a222e4200370300200341900d6a41106a22284200370300200341900d6a41086a222d4200370300200342003703900d2001202b200341900d6a1000200341e80c6a41186a222b202e290300370300200341e80c6a41106a222e2028290300370300200341e80c6a41086a222f202d290300370300200320032903900d3703e80c0240202c450d002001102a0b2029417f6a2129202a41016a2128200341086a202a4103704105746a220120032903e80c370000200141186a202b290300370000200141106a202e290300370000200141086a202f2903003700004100212c0340202a202a41036e222b417d6c6a4102470d06200341086a202c6a220141df006a2d000022082001411f6a2d000022097120082009722001413f6a2d00007172211f200141de006a2d000022082001411e6a2d000022097120082009722001413e6a2d00007172211e200141dd006a2d000022082001411d6a2d000022097120082009722001413d6a2d00007172211d200141dc006a2d000022082001411c6a2d000022097120082009722001413c6a2d00007172211c200141db006a2d000022082001411b6a2d000022097120082009722001413b6a2d00007172211b200141da006a2d000022082001411a6a2d000022097120082009722001413a6a2d00007172211a200141d9006a2d00002208200141196a2d00002209712008200972200141396a2d000071722119200141d8006a2d00002208200141186a2d00002209712008200972200141386a2d000071722118200141d7006a2d00002208200141176a2d00002209712008200972200141376a2d000071722117200141d6006a2d00002208200141166a2d00002209712008200972200141366a2d000071722116200141d5006a2d00002208200141156a2d00002209712008200972200141356a2d000071722115200141d4006a2d00002208200141146a2d00002209712008200972200141346a2d000071722114200141d3006a2d00002208200141136a2d00002209712008200972200141336a2d000071722113200141d2006a2d00002208200141126a2d00002209712008200972200141326a2d000071722112200141d1006a2d00002208200141116a2d00002209712008200972200141316a2d000071722111200141d0006a2d00002208200141106a2d00002209712008200972200141306a2d000071722110200141cf006a2d000022082001410f6a2d000022097120082009722001412f6a2d00007172210f200141ce006a2d000022082001410e6a2d000022097120082009722001412e6a2d00007172210e200141cd006a2d000022082001410d6a2d000022097120082009722001412d6a2d00007172210d200141cc006a2d000022082001410c6a2d000022097120082009722001412c6a2d00007172210c200141cb006a2d000022082001410b6a2d000022097120082009722001412b6a2d00007172210b200141ca006a2d000022082001410a6a2d000022097120082009722001412a6a2d00007172210a200141c9006a2d00002208200141096a2d00002209712008200972200141296a2d000071722109200141c8006a2d00002208200141086a2d00002220712008202072200141286a2d000071722108200141c7006a2d00002220200141076a2d00002221712020202172200141276a2d000071722120200141c6006a2d00002221200141066a2d00002222712021202272200141266a2d000071722121200141c5006a2d00002222200141056a2d00002223712022202372200141256a2d000071722122200141c4006a2d00002223200141046a2d00002224712023202472200141246a2d000071722123200141c3006a2d00002224200141036a2d00002225712024202572200141236a2d000071722124200141c2006a2d00002225200141026a2d00002226712025202672200141226a2d000071722125200141c1006a2d00002226200141016a2d00002227712026202772200141216a2d000071722126200141c0006a2d0000222720012d0000222e712027202e72200141206a2d000071722127202c41800c460d06200341086a202c202b410574202a41096e41e0006c6b6a6a220141ff006a201f3a0000200141fe006a201e3a0000200141fd006a201d3a0000200141fc006a201c3a0000200141fb006a201b3a0000200141fa006a201a3a0000200141f9006a20193a0000200141f8006a20183a0000200141f7006a20173a0000200141f6006a20163a0000200141f5006a20153a0000200141f4006a20143a0000200141f3006a20133a0000200141f2006a20123a0000200141f1006a20113a0000200141f0006a20103a0000200141ef006a200f3a0000200141ee006a200e3a0000200141ed006a200d3a0000200141ec006a200c3a0000200141eb006a200b3a0000200141ea006a200a3a0000200141e9006a20093a0000200141e8006a20083a0000200141e7006a20203a0000200141e6006a20213a0000200141e5006a20223a0000200141e4006a20233a0000200141e3006a20243a0000200141e2006a20253a0000200141e1006a20263a0000200141e0006a20273a0000202b212a202c41e0006a222c41e00c470d000c060b0b1036000b202b41011037000b410141011037000b202b41011037000b1031000b4100210120290d000b0b2000201f3a001f2000201e3a001e2000201d3a001d2000201c3a001c2000201b3a001b2000201a3a001a200020193a0019200020183a0018200020173a0017200020163a0016200020153a0015200020143a0014200020133a0013200020123a0012200020113a0011200020103a00102000200f3a000f2000200e3a000e2000200d3a000d2000200c3a000c2000200b3a000b2000200a3a000a200020093a0009200020083a0008200020203a0007200020213a0006200020223a0005200020233a0004200020243a0003200020253a0002200020263a0001200020273a00000b02402004a7450d002005102a0b200341b00d6a24000bfd0102057f017e230041306b220224002002410036022020014110200241206a10062101024002400240024020022802202203417f460d0020010d010b200041003602040c010b20022003360214200220013602102003450d0120022003417f6a3602142002200141016a36021020012d00002103200241206a200241106a106d20022802202204450d012002410c6a41026a2002411d6a41026a2d000022053a0000200220022f001d22063b010c20022902242107200020033a0000200020063b0001200041036a20053a000020002007370208200020043602042001102a0b200241306a24000f0b41c4d1c3004133200241206a419cd9c3001038000bfb0401057f230041106b2202240002400240024002400240024020002802704101460d0002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102821040c010b200128020020032005102c21040b2004450d0320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280274210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d06200441017422032005200320054b1b22034100480d060240024020040d002003102821040c010b200128020020042003102c21040b2004450d0420012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a20063600000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102821040c010b200128020020032005102c21040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00000b2000200110f1012000280278210320004180016a2802002200200110b40102402000450d002000410574210003402002200136020c20032002410c6a10c801200341206a2103200041606a22000d000b0b200241106a24000f0b200541011037000b200341011037000b200541011037000b1031000b860201017f0240024020002d00002201410e4b0d00024002400240024020010e0f050505050500050501050205030505050b200041086a2d00004101470d04200041146a280200450d04200041106a280200102a0c040b200041046a2d00004103470d0302402000410c6a280200450d00200041086a280200102a0b200041186a280200450d03200041146a280200102a0c030b200041046a2802000d022000410c6a280200450d02200041086a280200102a0c020b200041086a2d00004105490d01200041306a280200450d012000412c6a280200102a0c010b200041086a280200450d00200041046a280200102a0b0240200041fc006a280200450d002000280278102a0b0b130020004106360204200041c8f3c2003602000b3400200041d3f9c20036020420004100360200200041146a410f360200200041106a41dcf9c200360200200041086a42063702000b5501017f230041206b22022400200241003602082002420837030020024100360218200242013703104100200241106a10b401200041086a20022802183602002000200229031037020020021072200241206a24000b7201017f230041306b22022400200241186a4200370300200241106a4200370300200241086a42003703002002420037030020024100360228200242013703202002200241206a36022c20022002412c6a10c801200041086a200228022836020020002002290320370200200241306a24000b5d01027f230041106b2202240002404101102822030d00410141011037000b200341003a00002002428180808010370204200220033602004100200210b401200041086a200228020836020020002002290300370200200241106a24000b0900200042043702000b851805047f017e027f047e017f23004190026b22012400200141a8016a41086a22024200370300200142003703a80141f99fc6004115200141a8016a1008200141d0016a41086a22032002290300370300200120012903a8013703d001200141d0016a4110100920024200370300200142003703a801418ea0c600411a200141a8016a100820032002290300370300200120012903a8013703d00141002102200141003602a801200141d0016a4110200141a8016a100621030240024002400240024002400240024020012802a8012204417f460d002003450d0020044104490d01200328000021022003102a0b200141a8016a41086a22034200370300200142003703a80141bfa0c600411b200141a8016a1008200141d0016a41086a22042003290300370300200120012903a8013703d001200141186a200141d0016a109f02200129032021052001280218210620034200370300200142003703a80141bfa0c600411b200141a8016a1008200141086a4180e59af700200220024180e59af7004922071b20024180e59af70020071b6b2207ad2208420020084200109f0520042003290300370300200120012903a8013703d0012005420020061b2105200842a8c30180210842ffffffffffffffffff00428080808080808080807f20071b2001290308220920012903102009423f87521b42808090bbbad6adf00d7f210902400240200241ffe49af7004b0d0042ffffffffffffffffff00428080808080808080807f2005200820097d22097d22084200531b20082005427f5522022009427f554720022008427f5547711b22084280ec94a37c20084280ec94a37c551b21080c010b42ffffffffffffffffff00428080808080808080807f2005200820097c22097c22084200531b20082005427f5522022009427f554620022008427f5547711b21080b200120083703a801200141d0016a4110200141a8016a41081007200141a8016a41086a22024200370300200142003703a801418ea0c600411a200141a8016a1008200141d0016a41086a22032002290300370300200120012903a8013703d001200141d0016a4110100920024200370300200142003703a80141a8a0c6004117200141a8016a100820032002290300370300200120012903a8013703d001200141d0016a4110100920024200370300200142003703a80141d9efc200410d200141a8016a100820032002290300370300200120012903a8013703d00141002106200141003602a801200141d0016a4110200141a8016a10062102024020012802a8012203417f460d002002450d0020034104490d02200228000021062002102a200141d0016a411010090b200141a8016a41086a22024200370300200142003703a801419df2c2004111200141a8016a1008200141d0016a41086a2002290300370300200120012903a8013703d001200141a8016a200141d0016a411010a7030240024020012d00a8014101460d00200141286a41086a4200370300200141286a41106a4200370300200141286a41186a4200370300200141f0016a41186a200141c1016a290000370300200141f0016a41106a200141a8016a41116a290000370300200141f0016a41086a200141b1016a290000370300200120012900a9013703f00120014200370328200141f0016a21020c010b200141d0016a41101009200141f0016a41186a200141c1016a2900002208370300200141f0016a41106a200141a8016a41116a2900002205370300200141f0016a41086a200141b1016a2900002209370300200141286a41086a2009370300200141286a41106a2005370300200141286a41186a2008370300200120012900a90122083703f00120012008370328200141f0016a21020b42002108200141a8016a41086a22034200370300200142003703a80141b1f0c200410d200141a8016a1008200141d0016a41086a2003290300370300200120012903a8013703d001200141003602a801200141d0016a4110200141a8016a100621040240024020012802a8012203417f470d00410421070c010b200120033602f401200120043602f001200141a8016a200141f0016a107620012802a8012207450d0320012902ac01210802402003450d002004102a0b200141d0016a411010090b200141a8016a41086a22034200370300200142003703a80141e6efc2004115200141a8016a1008200141d0016a41086a2003290300370300200120012903a8013703d001200141a8016a200141d0016a411010a7030240024020012d00a8014101460d00200220012900a901370000200141c8006a41086a4200370300200141c8006a41106a4200370300200141c8006a41186a4200370300200241186a200141c1016a290000370000200241106a200141b9016a290000370000200241086a200141b1016a290000370000200142003703480c010b200141d0016a41101009200241186a200141c1016a2900002205370000200241106a200141b9016a2900002209370000200241086a200141b1016a290000220a370000200220012900a901220b370000200141c8006a41086a200a370300200141c8006a41106a2009370300200141c8006a41186a20053703002001200b3703480b0240200641fb01490d00200641857e6a2203450d00411010282202450d04200241086a41002900c6f042370000200241002900bef042370000200241104120102c2202450d0520022003360010200141a8016a41186a22034200370300200141a8016a41106a22044200370300200141a8016a41086a220c4200370300200142003703a80120024114200141a8016a1000200141f0016a41186a2003290300370300200141f0016a41106a2004290300370300200141f0016a41086a200c290300370300200120012903a8013703f0012002102a200141f0016a412010090b200141a8016a41186a22024200370300200141a8016a41106a22034200370300200141a8016a41086a22044200370300200142003703a801200141a8016a1014200141e8006a41186a2002290300370300200141e8006a41106a2003290300370300200141e8006a41086a2004290300370300200120012903a801370368200141f0016a41186a200141286a41186a290300370300200141f0016a41106a200141286a41106a290300370300200141f0016a41086a200141286a41086a290300370300200120012903283703f001200242003703002003420037030020044200370300200142003703a8010240200141f0016a4120200141a8016a1015450d0020014188016a41086a2004290300220537030020014188016a41106a2003290300220937030020014188016a41186a2002290300220a370300200120012903a801220b3703880120042005370300200320093703002002200a3703002001200b3703a8010240024020084220882205a722022008a7460d00200821090c010b200241016a22032002490d082005a74101742204200320032004491bad220942247e2205422088a70d082005a722034100480d080240024020020d002003102821070c010b2007200241246c2003102c21070b2007450d0720084220882205a721020b2007200241246c6a220241003a0000200220012903a801370001200241096a200141b0016a290300370000200241116a200141b8016a290300370000200241196a200141c0016a290300370000200220012f00f0013b0021200241236a200141f2016a2d00003a00002005422086200942ffffffff0f83844280808080107c21080b200020012903283700102000200636020020002001290368370030200041286a200141286a41186a290300370000200041206a200141286a41106a290300370000200041186a200141286a41086a290300370000200041386a200141e8006a41086a290300370000200041c0006a200141e8006a41106a290300370000200041c8006a200141e8006a41186a290300370000200041086a200837020020002007360204200041e8006a200141c8006a41186a290300370000200041e0006a200141c8006a41106a290300370000200041d8006a200141c8006a41086a2903003700002000200129034837005020014190026a24000f0b41c4d1c3004133200141a8016a419cd9c3001038000b41c4d1c3004133200141a8016a419cd9c3001038000b41c4d1c3004133200141a8016a419cd9c3001038000b411041011037000b412041011037000b200341041037000b1031000bb40202067f017e230041206b220224000240024002400240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a36020020064104490d01200428000421062001200341786a3602042001200441086a360200200241106a2001106d200228021022030d02200041003602080c030b200041003602080c020b200041003602080c010b200241106a41086a280200210720022802142104200241106a2001106d02402002280210450d00200241086a200241106a41086a2802002201360200200220022903102208370300200041106a20073602002000200436020c200020033602082000200636020420002005360200200041146a20083702002000411c6a20013602000c010b200041003602082004450d002003102a0b200241206a24000ba60301067f230041106b22022400200241003602082002420137030020002802002103024002400240410410282204450d0020024284808080c0003702042002200436020020042003360000200028020421050240024020022802042206200228020822046b4104490d00200441046a2103200228020021060c010b200441046a22032004490d03200641017422072003200720034b1b22074100480d030240024020060d002007102821060c010b200228020020062007102c21060b2006450d0220022007360204200220063602000b20022003360208200620046a200536000020002802082104200041106a2802002203200210b40102402003450d0020034105742103034020042002108f01200441206a2104200341606a22030d000b0b200028021421042000411c6a2802002203200210b40102402003450d0020034105742103034020042002108f01200441206a2104200341606a22030d000b0b2002280204210420012802002001280204200228020022032002280208100702402004450d002003102a0b200241106a24000f0b410441011037000b200741011037000b1031000b1300200041043602042000418897c3003602000b3400200041879fc30036020420004100360200200041146a4105360200200041106a41a0a2c300360200200041086a42133702000b34002000418ca2c30036020420004100360200200041146a4105360200200041106a41a0a2c300360200200041086a42133702000bf90101047f230041206b22032400200341106a41086a220442003703002003420037031041a8a0c6004117200341106a1008200341086a200429030037030020032003290310370300410021042003410036021020034110200341106a100621050240024020032802102206417f460d002005450d0020064104490d01200528000021042005102a0b02400240417f200420026a220520052004491b2204418080c002418080f00120011b4b0d00200041046a2004360200410021040c010b200041800c3b0001200041036a41003a0000410121040b200020043a0000200341206a24000f0b41c4d1c3004133200341106a419cd9c3001038000b850201047f230041206b22032400200341106a41086a2204420037030020034200370310418ea0c600411a200341106a1008200341086a200429030037030020032003290310370300410021042003410036021020034110200341106a100621050240024020032802102206417f460d002005450d0020064104490d01200528000021042005102a0b02400240417f2004418094ebdc034180afd0e50220021b2205200120052001491b6a220120012004491b220420054b0d00200041046a2004360200410021040c010b200041800c3b0001200041036a41003a0000410121040b200020043a0000200341206a24000f0b41c4d1c3004133200341106a419cd9c3001038000bef1a04057f017e037f017e230041e0016b220124000240024002400240024002400240024041880110282202450d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200028020022002802000e1500011402030405060708090a0b0c0d0e0f10111213000b0240024002400240024002400240200041086a280200417f6a220341054b0d004101210420030e06060102030405060b41e4f0c2001032000b200041146a2802002204417f4c0d1b2000410c6a28020021000240024020040d0020014200370360410121050c010b200410282205450d1d20014100360264200120043602600b20012004360264200520002004109a051a20012903602106410221040c040b200041106a2903002106410321040c030b200041146a2802002204417f4c0d192000410c6a28020021000240024020040d0020014200370360410121050c010b200410282205450d1c20014100360264200120043602600b20012004360264200520002004109a051a20012903602106410421040c020b200141e0006a2000410c6a106f2001290264210620012802602105410521040c010b200141e0006a2000410c6a10712001290264210620012802602105410621040b200220063703102002200536020c20022004360208200241003602000c140b10a103000b200141e0006a200041046a1070200241033602002002410c6a200141e8006a280200360200200220012903603702040c120b10bb03000b200141e0006a200041086a10ae02200241086a200141e0006a41e000109a051a200241053602000c100b200141e0006a200041086a10bc0320024106360200200241386a200141e0006a41306a290300370300200241306a200141e0006a41286a290300370300200241286a200141e0006a41206a290300370300200241206a200141e0006a41186a290300370300200241186a200141e0006a41106a290300370300200241106a200141e0006a41086a290300370300200220012903603703080c0f0b200141e0006a41186a200041286a290000370300200141e0006a41106a200041206a290000370300200141e8006a200041186a290000370300200141e0006a41286a200041386a290000370300200141e0006a41306a200041c0006a290000370300200141e0006a41386a200041c8006a290000370300200141e0006a41c8006a200041d8006a290000370300200141e0006a41d0006a200041e0006a290000370300200141e0006a41d8006a200041e8006a2900003703002001200041106a2900003703602001200041306a290000370380012001200041d0006a2900003703a0012000410c6a2802002205417f4c0d10200028020421030240024020050d0041012100410021040c010b20052104200510282200450d140b200020032005109a0521002001200141e0006a41e000109a0521032002200536020c2002200436020820022000360204200241106a200341e000109a051a200241073602000c0e0b200141e0006a200041086a10bd0320024108360200200241306a200141e0006a41286a290300370300200241286a200141e0006a41206a290300370300200241206a200141e0006a41186a290300370300200241186a200141e0006a41106a290300370300200241106a200141e0006a41086a290300370300200220012903603703080c0d0b02400240024002400240024020002d0004417f6a220541034b0d0020050e0401020304010b41c0f1c2001032000b200041106a280200220341ffffff3f712003470d1220034105742204417f4c0d12200041086a2802002100410121054101210702402004450d00200410282207450d170b024020030d0041002104410021030c040b2003410574210420072105034020052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a290000370000200541206a2105200041206a2100200441606a22040d000b41012105200341057441606a41057641016a21040c030b200041086a10ba032107410221050c020b200041086a28020021072000410c6a10ba032103410321050c010b200141026a200041046a220541036a2d00003a0000200141e0006a41086a2000411c6a290000370300200141e0006a41106a200041246a2d00003a0000200120052f00013b01002001200041146a29000037036020002d00254100472108200041286a2802002109200041106a28000021042000410c6a2800002103200041086a2800002107410421050b200220053a0004200220012f01003b0005200220043602102002200336020c200220073602082002200129036037021420022009360228200220083a002520024109360200200241076a200141026a2d00003a00002002411c6a200141e8006a290300370200200241246a200141f0006a2d00003a00000c0c0b02400240024002400240024020002d0004417f6a220541034b0d0020050e0401020304010b41c0f1c2001032000b200041106a280200220341ffffff3f712003470d1120034105742204417f4c0d11200041086a2802002100410121054101210702402004450d00200410282207450d170b024020030d0041002104410021030c040b2003410574210420072105034020052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a290000370000200541206a2105200041206a2100200441606a22040d000b41012105200341057441606a41057641016a21040c030b200041086a10ba032107410221050c020b200041086a28020021072000410c6a10ba032103410321050c010b200141026a200041046a220541036a2d00003a0000200141e0006a41086a2000411c6a290000370300200141e0006a41106a200041246a2d00003a0000200120052f00013b01002001200041146a29000037036020002d00254100472108200041286a2802002109200041106a28000021042000410c6a2800002103200041086a2800002107410421050b200220053a0004200220012f01003b0005200220043602102002200336020c200220073602082002200129036037021420022009360228200220083a00252002410a360200200241076a200141026a2d00003a00002002411c6a200141e8006a290300370200200241246a200141f0006a2d00003a00000c0b0b200141e0006a200041086a10d3022002410b360200200241c0006a200141e0006a41386a290300370300200241386a200141e0006a41306a290300370300200241306a200141e0006a41286a290300370300200241286a200141e0006a41206a290300370300200241206a200141e0006a41186a290300370300200241186a200141e0006a41106a290300370300200241106a200141e0006a41086a290300370300200220012903603703080c0a0b200141e0006a200041046a10be03200241046a200141e0006a41c400109a051a2002410c3602000c090b200028020421002002410d360200200220003602040c080b2000410c6a2802002205417f4c0d09200028020421030240024020050d0041012100410021040c010b20052104200510282200450d100b200020032005109a0521002002200536020c20022004360208200220003602042002410e3602000c070b024002400240024002400240200041086a280200417f6a220541024b0d0020050e03010203010b418486c2001032000b200041386a2903002106200041306a290300210a41012105024002402000410c6a2d00004101460d00200141e8006a2000411c6a290200370300200141e0006a41106a200041246a290200370300200141f8006a2000412c6a2d00003a00002001200041146a29020037036020002f000d2000410f6a2d0000411074722104200041106a2802002103410021050c010b200041106a28020021030b200141186a200141e0006a41186a280200360200200141106a200141e0006a41106a290300370300200141086a200141e0006a41086a29030037030020012001290360370300410121000c030b2000410c6a28020022054108762104410221000c010b2000410c6a28020022054108762104410321000b0b2002200a3703302002200336021020022000360208200220012903003702142002410f360200200241386a200637030020022004410874200541ff01717236020c2002411c6a200141086a290300370200200241246a200141106a2903003702002002412c6a200141186a2802003602000c060b200141e0006a200041086a10bf03200241086a200141e0006a418001109a051a200241103602000c050b200141e0006a200041046a10c003200241113602002002412c6a20014188016a280200360200200241246a20014180016a2903003702002002411c6a200141f8006a290300370200200241146a200141f0006a2903003702002002410c6a200141e8006a290300370200200220012903603702040c040b200141e0006a200041046a10af02200241046a200141e0006a41e400109a051a200241123602000c030b10c103000b10d501000b200041086a290300210620024102360200200220063703080b200141e0016a240020020f0b41880141081037000b1036000b200441011037000b200441011037000b200541011037000b200441011037000b200441011037000b200541011037000b0a0041acb4c3001032000b910c03047f017e057f230041206b2202240002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410c4b0d0020030e0d0102030405060708090a0b0c0d010b41e0ffc4001032000b4101210302400240200141046a2d00004101460d002002411e6a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b011c20022001410c6a290000370300200141086a2800002104410021030c010b200141086a28020021040b200041286a2001290328370300200041046a20033a0000200041056a20022f011c3b0000200041086a20043602002000410c6a2002290300370200200041306a200141306a290300370300200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a28020036020020012d00012101200041013a0000200020013a00010c0c0b200041023a0000200041106a200141106a290300370300200041086a200141086a2903003703000c0b0b200041033a0000200041106a200141106a290300370300200041086a200141086a2903003703000c0a0b200041043a00000c090b200041053a0000200041106a200141106a290300370300200041086a200141086a2903003703000c080b2001410c6a2802002205ad42247e2206422088a70d082006a72204417f4c0d08200141046a28020021030240024020040d00410421070c010b200410282207450d0a0b0240024020050d00410021040c010b200541246c2108410021042002411e6a21092007210103400240024020032d00004101460d002009200341036a2d00003a0000200341046a280000210a200341016a2f0000210b200241086a200341106a290000370300200241106a200341186a290000370300200241186a200341206a2d00003a00002002200b3b011c2002200341086a2900003703004100210b0c010b200341046a280200210a4101210b0b200341246a21032001200b3a0000200141046a200a360200200141016a20022f011c3b0000200141036a20092d00003a0000200141086a2002290300370200200141106a200241086a290300370200200141186a200241106a290300370200200141206a200241186a280200360200200141246a2101200441016a21042008415c6a22080d000b0b200041063a00002000410c6a2004360200200041086a2005360200200041046a20073602000c070b200041073a00000c060b200041083a0000200020012d00013a00010c050b4101210302400240200141046a2d00004101460d002002411e6a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b011c20022001410c6a290000370300200141086a2800002101410021030c010b200141086a28020021010b200041093a0000200041046a20033a0000200041056a20022f011c3b0000200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c040b2000410a3a0000200041046a200141046a2802003602000c030b2000410b3a00000c020b2000410c3a00000c010b2001410c6a280200220841ffffff3f712008470d0120084105742203417f4c0d01200141046a28020021010240024020030d004101210a0c010b20031028220a450d040b0240024020080d0041002108410021010c010b20084105742104200a2103034020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a290000370000200341206a2103200141206a2101200441606a22040d000b200841057441606a41057641016a21010b2000410d3a00002000410c6a2001360200200041086a2008360200200041046a200a3602000b200241206a24000f0b1036000b200441041037000b200341011037000bab0701017f024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220241104b0d0020020e110102030405060708090a0b0c0d0e0f1011010b41e8d0c5001032000b41880110282202450d102002200141046a28020010cf03200041046a2002360200200041013a0000200041106a200141106a290300370300200041086a200141086a2903003703000f0b200041023a0000200041046a200141046a2802003602000f0b200041033a0000200041046a200141046a280200360200200041026a200141026a2d00003a0000200020012d00014101713a00010f0b200041043a0000200041046a200141046a280200360200200041026a200141026a2d00003a0000200020012d00014101713a00010f0b200041053a0000200041046a200141046a2802003602000f0b41880110282202450d0c2002200141046a28020010cf03200041063a0000200041046a20023602000f0b41880110282202450d0c2002200141046a28020010cf03200041073a0000200041046a20023602000f0b41880110282202450d0c2002200141046a28020010cf03200041083a0000200041046a20023602000f0b200041093a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a2902003702000f0b2000410a3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b2000410b3a0000200041046a200141046a2802003602000f0b2000410c3a00002000410c6a2001410c6a280200360200200041046a200141046a2902003702000f0b2000410d3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b2000410e3a00000f0b2000410f3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b200041103a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041216a200141216a2d00003a00000f0b200041113a00000f0b41880141081037000b41880141081037000b41880141081037000b41880141081037000bb60401047f0240024002400240024020012d0000417f6a220241034b0d0020020e0401020304010b4188b5c3001032000b200041013a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b200041023a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b200041033a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a290000370000200041216a200141216a290000370000200041296a200141296a290000370000200041316a200141316a290000370000200041396a200141396a2900003700000f0b024002402001410c6a280200220341ffffff3f712003470d0020034105742202417f4c0d00200141046a28020021010240024020020d00410121040c010b200210282204450d020b0240024020030d0041002103410021010c010b2003410574210520042102034020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a290000370000200241206a2102200141206a2101200541606a22050d000b200341057441606a41057641016a21010b200041043a00002000410c6a2001360200200041086a2003360200200041046a20043602000f0b1036000b200241011037000b8d0c07037f017e017f017e017f017e017f230041c0006b220224000240024002400240024002400240024002400240024020012d0000417f6a220341044b0d0020030e050102030405010b41d093c4001032000b200041f9006a2002280020360000200041086a200141086a290300370300200041fc006a200241236a280000360000200041106a200141106a290300370300200041186a200141186a290300370300200041206a200141206a290300370300200041286a200141286a290300370300200041306a200141306a290300370300200041386a200141386a290300370300200041c0006a200141c0006a290300370300200041c8006a200141c8006a290300370300200041d0006a200141d0006a290300370300200041d8006a200141d8006a290300370300200041e0006a200141e0006a290300370300200041e8006a200141e8006a290300370300200041f0006a200141f0006a290300370300200041f8006a200141f8006a2d00004100473a0000200041013a00000c040b2001410c6a2802002203417f4c0d04200141046a2802002104200141106a29030021050240024020030d0041002101410121060c010b20032101200310282206450d060b200620042003109a0521042000410c6a2003360200200041086a2001360200200041046a2004360200200041106a2005370300200041023a00000c030b4101210402400240200141046a2d00004101460d00200241026a200141076a2d00003a0000200241206a41086a200141146a290000370300200241306a2001411c6a290000370300200241386a200141246a2d00003a00002002200141056a2f00003b010020022001410c6a290000370320200141086a2800002106410021040c010b200141086a28020021060b200141306a2802002203417f4c0d03200141c0006a29030021052001290338210720012802282108200129034821090240024020030d00410021014101210a0c010b2003210120031028220a450d060b200a20082003109a052108200041c0006a2005370300200041386a2007370300200041046a20043a0000200041086a2006360200200041c8006a2009370300200041306a20033602002000412c6a2001360200200041286a2008360200200041056a20022f01003b0000200041076a200241026a2d00003a00002000410c6a2002290320370200200041146a200241206a41086a2903003702002000411c6a200241306a290300370200200041246a200241386a280200360200200041033a00000c020b200141386a2903002105200141306a2903002107200141c0006a2903002109200241386a200141196a290000370300200241306a200141116a290000370300200241286a200141096a290000370300200220012900013703202001412c6a2802002203417f4c0d02200141246a28020021010240024020030d0041012104410021060c010b20032106200310282204450d060b200420012003109a052101200041386a2005370300200041306a2007370300200041c0006a20093703002000412c6a2003360200200041286a2006360200200041246a2001360200200041043a000020002002290320370001200041096a200241286a290300370000200041116a200241306a290300370000200041196a200241386a2903003700000c010b200241186a2204200141196a290000370300200241106a2206200141116a290000370300200241086a2208200141096a29000037030020022001290001370300410021030240200141216a2d00004101470d00200241206a41186a2001413a6a290000370300200241206a41106a200141326a290000370300200241206a41086a2001412a6a2900003703002002200141226a290000370320410121030b20002002290300370001200041216a20033a0000200041226a2002290320370000200041196a2004290300370000200041116a2006290300370000200041096a20082903003700002000412a6a200241206a41086a290300370000200041326a200241206a41106a2903003700002000413a6a200241206a41186a290300370000200041053a00000b200241c0006a24000f0b1036000b200341011037000b200341011037000b200341011037000b920501047f230041206b2202240002400240024002400240024002402001280200417f6a220341024b0d0020030e03010203010b41dc9cc4001032000b41880110282203450d032003200128020410cf0320004101360200200020033602040c020b410121030240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002101410021030c010b200141086a28020021010b200020033a0004200020022f011c3b000520004102360200200041086a20013602002000410c6a2002290300370200200041076a2002411c6a41026a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c010b410121040240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002105410021040c010b200141086a28020021050b41880110282203450d022003200128022810cf03200020043a0004200041086a2005360200200041286a200336020020004103360200200020022f011c3b0005200041076a2002411e6a2d00003a00002000410c6a2002290300370200200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000b200241206a24000f0b41880141081037000b41880141081037000b0a0041b095c4001032000bad0301047f230041106b22022400024002400240024002400240024002400240024002402001280200417f6a220341054b0d0020030e06010203040506010b41e4f0c2001032000b200041013602000c050b2001410c6a2802002203417f4c0d05200128020421010240024020030d0041002104410121050c010b20032104200310282205450d070b200520012003109a0521012000410c6a2003360200200041086a200436020020002001360204200041023602000c040b20004103360200200041086a200141086a2903003703000c030b2001410c6a2802002203417f4c0d03200128020421010240024020030d0041012104410021050c010b20032105200310282204450d060b200420012003109a0521012000410c6a2003360200200041086a200536020020002001360204200041043602000c020b2002200141046a106f200041053602002000410c6a200241086a280200360200200020022903003702040c010b2002200141046a1071200041063602002000410c6a200241086a280200360200200020022903003702040b200241106a24000f0b1036000b200341011037000b200341011037000bdd0301047f024002400240024002400240024020012d0000417f6a220241034b0d0020020e0401020304010b41c0f1c2001032000b2001410c6a280200220341ffffff3f712003470d0320034105742202417f4c0d03200141046a28020021010240024020020d00410121040c010b200210282204450d050b0240024020030d0041002103410021010c010b2003410574210520042102034020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a290000370000200241206a2102200141206a2101200541606a22050d000b200341057441606a41057641016a21010b200041013a00002000410c6a2001360200200041086a2003360200200041046a20043602000f0b200141046a10ba032101200041023a0000200041046a20013602000f0b200141046a2802002102200041086a200141086a10ba03360200200041046a2002360200200041033a00000f0b200041043a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a280200360200200041216a200141216a2d00004100473a00000f0b1036000b200241011037000b3400200041c5b6c30036020420004100360200200041146a4102360200200041106a41ccb6c300360200200041086a42073702000be40201047f230041c0006b2202240002400240410f10282203450d00200341076a4100290092b4433700002003410029008bb4433700002003410f411e102c2203450d012003200036000f200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034113200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002003102a200128020021042001280208210320024100360228200242013703202003200241206a10b40102402003450d00200341057421002004210303402003200241206a108f01200341206a2103200041606a22000d000b0b2002280224210320024120200228022022002002280228100702402003450d002000102a0b0240200141046a280200450d002004102a0b200241c0006a24000f0b410f41011037000b411e41011037000b8a1401037f200141046a2802002102200141086a28020021030240024002400240024002400240024002400240024002400240024002400240024020002d00004101460d000240024020022003460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d0220012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41003a00000240024002400240024002400240024020002d00010e080001020304050607000b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d18200341017422022000200220004b1b22024100480d180240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d17200341017422022000200220004b1b22024100480d170240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d16200341017422022000200220004b1b22024100480d160240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41023a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d15200341017422022000200220004b1b22024100480d150240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41033a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d14200341017422022000200220004b1b22024100480d140240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41043a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d13200341017422022000200220004b1b22024100480d130240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41053a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d12200341017422022000200220004b1b22024100480d120240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41063a00000f0b02400240200141046a28020020042802002203460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d0a20012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41073a000002400240200141046a28020020042802002203460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d0b20012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a20002d00023a00000f0b0240024020022003460d00200128020021020c010b200341016a22022003490d10200341017422042002200420024b1b22044100480d100240024020030d002004102821020c010b200128020020032004102c21020b2002450d0b20012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a41013a0000024020002d0001220341024b0d0002400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d13200341017422022000200220004b1b22024100480d130240024020030d002002102821000c010b200128020020032002102c21000b2000450d0f20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d12200341017422022000200220004b1b22024100480d120240024020030d002002102821000c010b200128020020032002102c21000b2000450d0f20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000f0b02400240200141046a280200200141086a2802002203460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d0f20012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41023a000002400240200141046a28020020042802002203460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d1020012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a20002d00023a00000b0f0b200441011037000b200241011037000b200241011037000b200241011037000b200241011037000b200241011037000b200241011037000b200241011037000b200441011037000b200441011037000b200441011037000b200241011037000b200241011037000b200441011037000b200441011037000b1031000bac64070e7f017e047f017e047f0f7e087f230041900b6b220124004100210241002103410421040240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000410c6a28020041246c2205450d00200028020421064104210441002102410021030340024020062d00004101470d00200641106a2802002207417f4c0d1a200641086a2802002108200641016a28000021090240024020070d004101210a4100210b0c010b2007210b20071028220a450d040b200a20082007109a05210a20014188076a41026a220c200141f0056a41026a2d00003a0000200141a0086a41086a220d200141c0096a41086a290200370300200120012f00f0053b018807200120012902c0093703a008024020022003470d00200241016a22082002490d1d2002410174220e2008200e20084b1b2203ad42247e220f422088a70d1d200fa722084100480d1d0240024020020d002008102821040c010b2004200241246c2008102c21040b2004450d050b2004200241246c6a220841013a000020082009360001200820073600102008200b36000c2008200a360008200820012f0188073b0005200841076a200c2d00003a0000200820012903a0083702142008411c6a200d290300370200200241016a21020b200641246a21062005415c6a22050d000b0b200141003602a0084188e8c2004110200141a0086a4104100720014188076a41086a22064200370300200142003703880741d9efc200410d20014188076a1008200141f0056a41086a2208200629030037030020012001290388073703f0052001200028020022073602a008200141f0056a4110200141a0086a4104100720064200370300200142003703880741b1f0c200410d20014188076a10082008200629030037030020012001290388073703f005200141103602a4082001200141f0056a3602a00820042002200141a0086a10e102200642003703002001420037038807419df2c200411120014188076a10082008200629030037030020012001290388073703f005200141103602a4082001200141f0056a3602a008200041106a2205200141a0086a10f002411010282206450d02200641086a41002900c6f042370000200641002900bef042370000200641104120102c2208450d0320082007417f6a360010200141d8046a41186a22064200370300200141d8046a41106a22074200370300200141d8046a41086a22094200370300200142003703d80420084114200141d8046a100020014188076a41186a200629030037030020014188076a41106a200729030037030020014188076a41086a22062009290300370300200120012903d804370388072008102a200141203602a408200120014188076a3602a0082005200141a0086a10f00220064200370300200142003703880741e6efc200411520014188076a1008200141f0056a41086a2208200629030037030020012001290388073703f005200141103602a4082001200141f0056a3602a008200041d0006a200141a0086a10f00220064200370300200142003703880741aef2c200411520014188076a10082008200629030037030020012001290388073703f005200141a0086a200141f0056a10a903024020012802a40822070d00200141013602d804410021094100210641002105410021080c060b200120073602d804200141ac086a280200210620012802a008210920012802a8082105024020012903a808220f422088a741d1004f0d00200fa721080c060b200141a0086a41186a220a200041286a290000370300200141a0086a41106a220b200041206a290000370300200141a0086a41086a220c200041186a290000370300200120002900103703a00820062009411874220941187522084d0d04200720084105746a220820012903a008370000200841186a200a290300370000200841106a200b290300370000200841086a200c290300370000200941808080086a41187541d1006f21090c060b200741011037000b200841041037000b411041011037000b412041011037000b41c4f2c200200820061034000b200141a0086a41186a220a200041286a290000370300200141a0086a41106a220b200041206a290000370300200141a0086a41086a220c200041186a290000370300200120002900103703a008024020062008470d0020052006470d00200641016a22082006490d14200641017422072008200720084b1b220541ffffff3f712005470d14200541057422074100480d140240024020060d002007102821080c010b20012802d80420064105742007102c21080b2008450d02200120083602d8040b20012802d804220720064105746a220820012903a008370000200841086a200c290300370000200841106a200b290300370000200841186a200a290300370000200641016a21060b20014188076a41086a22084200370300200142003703880741aef2c200411520014188076a1008200141f0056a41086a200829030037030020012001290388073703f0050240024020070d00200141f0056a411010090c010b410110282208450d0220014281808080103702a408200120083602a008200820093a00002006200141a0086a10b40102402006450d00200641057421082007210603402001200141a0086a3602c0092006200141c0096a10c801200641206a2106200841606a22080d000b0b20012802a4082106200141f0056a411020012802a008220820012802a808100702402006450d002008102a0b2007450d002005450d002007102a0b20014188076a41086a22084200370300200142003703880741d4f2c200410d20014188076a1008200141f0056a41086a2206200829030037030020012001290388073703f005200141f0056a4110100920084200370300200142003703880741eea0c600411120014188076a10082006200829030037030020012001290388073703f005200141f0056a41101009411210282206450d02200641106a41002f00f1f2423b0000200641086a41002900e9f242370000200641002900e1f242370000200141d8046a41186a22074200370300200141d8046a41106a22054200370300200141d8046a41086a22094200370300200142003703d80420064112200141d8046a100020014188076a41186a200729030037030020014188076a41106a200529030037030020082009290300370300200120012903d804370388072006102a20014188076a4120100e2000280200211010eb0220104105490d07200141f0056a41086a22064200370300200142003703f0054193cdc2004111200141f0056a1008200141a0086a41086a2006290300370300200120012903f0053703a008200141003602c009200141a0086a4110200141c0096a100621060240024020012802c0092208417f460d002006450d002001200836028c072001200636028807200141c0096a20014188076a107b20012802c009220a450d0520012902c409210f2008450d012006102a0c010b4104210a4200210f0b2010417b6a2105200a200f422088a7220b41c4006c22066a21090240200641cd014f0d0041002106200a21080c060b200a41d0016a21084100210603400240200841b07e6a22072d00004101460d00200841b47e6a28020020054f0d080b0240200741c4006a2d00004101460d00200841f87e6a2802002005490d00200641016a21060c080b024020074188016a2d00004101460d00200841bc7f6a2802002005490d00200641026a21060c080b02400240200741cc016a2d00004101460d00200828020020054f0d010b20084190026a2108200641046a2106200920074190026a6b41cc014d0d060c010b0b200641036a21060c060b200741011037000b410141011037000b411241011037000b41c4d1c3004133200141f0056a419cd9c3001038000b200841b07e6a21080b20082009460d00200a200b41c4006c6a21070340024020082d00004101460d00200841046a28020020054f0d020b200641016a21062007200841c4006a2208470d000b0b2006200b4b0d01200f42ffffffff0f83210f0240200b20066b2208450d0002402006450d00200a200a200641c4006c6a200841c4006c109b051a0b2008ad422086200f84210f0b200141f0056a41086a22064200370300200142003703f0054193cdc2004111200141f0056a1008200141a0086a41086a2006290300370300200120012903f0053703a008200141c0096a200a200f422088a7109202200141a0086a411020012802c009220820012802c8091007200fa72106024020012802c409450d002008102a0b2006450d00200a102a0b200141003a00c009200141f0056a41086a22064200370300200142003703f00541c8fbc5004117200141f0056a1008200141a0086a41086a22082006290300370300200120012903f0053703a008200141a0086a4110200141c0096a41011007200141a0086a10f801412410282206450d01200620012903a00837000020064114360220200641186a200141a0086a41186a290300370000200641106a200141a0086a41106a290300370000200641086a200829030037000020014281808080103702c409200120063602c009200141c0096a10f901201010ea0202400240201041809c3170450d0020014188076a21110c010b200141f0056a41086a22064200370300200142003703f00541d590c600411f200141f0056a100820014188076a41086a2006290300370300200120012903f00537038807200141003602a00820014188076a4110200141a0086a1006210602400240024020012802a0082208417f460d002006450d002008450d0120062d000021082006102a20014188076a4110100920084102460d0020084101710d020b20014188076a2111201010c803450d02201010c9031a0c020b41c4d1c3004133200141f0056a419cd9c3001038000b20014188076a2111201010c903450d00201010c8031a0b200141f0056a41086a22064200370300200142003703f00541c290c6004113200141f0056a100820014188076a41086a2006290300370300200120012903f0053703880741002106200141003602a00820114110200141a0086a10062108024020012802a0082207417f460d002008450d0020074104490d03200828000021062008102a0b200141f0056a41086a22084200370300200142003703f00541a990c6004119200141f0056a100820014188076a41086a2008290300370300200120012903f0053703880741002108200141003602a00820114110200141a0086a10062107024020012802a0082205417f460d002007450d0020054104490d04200728000021082007102a0b02400240200620084f0d0002400340200141c0096a200610ca0320012802c00922074113470d012008200641016a2206470d000c020b0b20014188076a200141c0096a410472419401109a051a200141f0056a20014188076a419401109a051a200141d8046a200141f0056a419401109a051a200120073602a80820012006ad220f3703a008200141ac086a200141d8046a419401109a052105200141b0096a2802002010460d01200141a8086a106a0b4108211241002106410021130c080b200141c0036a2005419401109a051a200141a0086a200141c0036a419401109a051a41a00110282212450d04201220073602082012200f3703002012410c6a200141a0086a419401109a051a02400240200641016a220720084f0d000340200141c0096a200710ca0320012802c00922054113470d022008200741016a2207470d000b0b41012106410121130c080b20014188076a200141c0096a410472220c419401109a051a200141f0056a20014188076a419401109a051a200141d8046a200141f0056a419401109a051a200120053602a80820012007ad220f3703a008200141a0086a410c6a200141d8046a419401109a05210a41012106200141a8086a210b200141b0096a2802002010470d06200741016a2107200141c0036a200a419401109a051a41012106410121130340200141a0086a200141c0036a419401109a051a024020132006470d00200641016a22092006490d0c2006410174220d2009200d20094b1b2213ad42a0017e2214422088a70d0c2014a722094100480d0c024002402006450d002012200641a0016c2009102c21120c010b2009102821120b2012450d070b2012200641a0016c6a220920053602082009200f3703002009410c6a200141a0086a419401109a051a200641016a2106200720084f0d0802400340200141c0096a200710ca03024020012802c00922054113460d0020014188076a200c419401109a051a200141f0056a20014188076a419401109a051a200141d8046a200141f0056a419401109a051a200120053602a80820012007ad220f3703a008200a200141d8046a419401109a05210920012802b0092010470d02200741016a2107200141c0036a2009419401109a051a0c030b2008200741016a2207470d000c0a0b0b0b200b106a0c070b41e4e8c5001032000b412441041037000b41c4d1c3004133200141f0056a419cd9c3001038000b41c4d1c3004133200141f0056a419cd9c3001038000b41a00141081037000b200941081037000b200b106a410121130b2012200641a0016c6a2115024020060d00201221160c020b20014188076a4104722106200141a0086a410472211720014198026a41086a21182012211603402016280200210520162802082108200141a0086a2016410c6a419401109a051a201641a0016a211620084113460d02200141c0096a200141a0086a419401109a051a200120083602a0082017200141c0096a419401109a051a200141f0056a200510cb0320012802f005210b0240024020012802f80522080d00420021194200211a4200211b4200211c4200211d4200211e0c010b200841057421094200211d200b21084200211e4200211b4200211c420021194200211a034020014198036a2008109d0220014198036a41086a2903002114200129039803210f20062008290000370000200641086a200841086a290000370000200641106a200841106a290000370000200641186a200841186a290000370000200120053602880720014190036a20014188076a10cc0320012d00900341017121070240024020012d009103220a0d00200141d0026a200f2014420a420010a00520012903d002221f210f200141d0026a41086a290300222021140c010b200141f0026a20144200200aad221f4200109f0520014180036a200f4200201f4200109f05200141e0026a42004200200f4200109f05427f20014180036a41086a290300221f20012903f00220012903e0027c7c222020012903f80220012903e802844200522020201f5472220a1b2120427f200129038003200a1b211f0b200841206a21084200202020071b201c7c4200201f20071b2221201b7c221b202154ad7c211c2020420020071b201a7c201f420020071b221f20197c2219201f54ad7c211a2014201e7c200f201d7c221d200f54ad7c211e200941606a22090d000b0b024020012802f405450d00200b102a0b200141f0056a200510cb0320012802f00521000240024020012802f80522080d004200212142002122420021234200212442002120420021250c010b2008410574210942002120200021084200212542002123420021244200212142002122034020062008290000370000200641086a200841086a2207290000370000200641106a200841106a220a290000370000200641186a200841186a220b2900003700002001200536028807200141c8026a20014188076a10cc0320012d00c802210c20012d00c902210d20014188076a41186a200b29000037030020014188076a41106a200a29000037030020014188076a41086a20072900003703002001200829000037038807200141a8026a200520014188076a200d411010cd03200141a8026a41186a29030020257c20012903b802220f20207c2220200f54ad7c21254200200141a8026a41086a290300220f200c41017122071b20247c420020012903a802221420071b221f20237c2223201f54ad7c2124200f420020071b20227c2014420020071b220f20217c2221200f54ad7c2122200841206a2108200941606a22090d000b0b024020012802f405450d002000102a0b20014198026a10a1022018290300210f2001290398022114024002402020201d7c221f4202882025201e7c201f202054ad7c2220423e8684221d2020420288221e84500d00201d201f85201e20208584500d00410021080240034020014188026a201f2020200841046a41fe0071109e05200841026a2108200129038802221d20014188026a41086a290300221e84500d01201d201f85201e2020858450450d000b0b200141f8016a201f2020200841fe0071109e0520012903f801200141f8016a41086a29030084211d4200211e024020080d00201d420052ad211d0c020b201d420052ad211d0340200141d8016a201f202041002008417e6a2207200720084b1b220841ff0071109e05200141e8016a201d42018622264201842225201e420186201d423f8884221e2025201e109f052026202520012903e80120012903d80156200141e8016a41086a290300221d200141d8016a41086a290300222756201d2027511b1b211d20080d000c020b0b4200211e201f202084420052ad211d0b024002402014420288200f423e8684221f200f420288222084500d00201f2014852020200f8584500d004100210802400340200141c8016a2014200f200841046a41fe0071109e05200841026a210820012903c801221f200141c8016a41086a290300222084500d01201f2014852020200f858450450d000b0b200141b8016a2014200f200841fe0071109e0520012903b801200141b8016a41086a29030084211f42002120024020080d00201f420052ad211f0c020b201f420052ad211f034020014198016a2014200f41002008417e6a2207200720084b1b220841ff0071109e05200141a8016a201f420186222642018422252020420186201f423f8884222020252020109f052026202520012903a80120012903980156200141a8016a41086a290300221f20014198016a41086a290300222756201f2027511b1b211f20080d000c020b0b420021202014200f84420052ad211f0b02400240024002400240201d201e8450450d004100210b0c010b2024201c7c2023201b7c2214202354ad7c21232022201a7c202120197c220f202154ad7c212102400240024020012d00b0090e03010200010b200f201456202120235620212023511b210b0c020b0340200141c8006a20142023201d201e10a005201f22192020221a844200510d04200141c8006a41086a290300211f20012903482120200141386a200f20212019201a10a0054101210b20202001290338221b54201f200141386a41086a290300222554201f20255122081b0d020240201b2020542025201f5420081b450d004100210b0c030b200141286a2020201f201d201e109f05200141186a201b20252019201a109f050240200f2001290318221f7d22202021200141186a41086a2903007d200f201f54ad7d222584500d002023200141286a41086a2903007d211b20142001290328220f5421082014200f7d211f201d210f201e21212020211d2025211e20192114201a2123201f201b2008ad7d222084500d030c010b0b4100210b0c010b0340201e2125201d2119201f2020844200510d02200141f8006a200f20212019202510a00520014188016a20142023201f202010a0054101210b200129038801221a2001290378221b5420014188016a41086a290300221d200141f8006a41086a290300221e54201d201e5122081b0d010240201b201a54201e201d5420081b450d004100210b0c020b200141e8006a201a201d201f2020109f05200141d8006a201b201e20192025109f050240200f2001290358221d7d221e2021200141d8006a41086a2903007d200f201d54ad7d221a8450450d004100210b0c020b2023200141e8006a41086a2903007d211b20142001290368220f5421082014200f7d211d201f210f20202121201e211f201a21202019211420252123201d201b2008ad7d221e844200520d000b0b20014188076a200510cb032001280288072128200128028c0721292001280290072208450d0220282008410574222a6a212b2028210802400340200141f0056a41186a2207200841186a220c290000370300200141f0056a41106a2209200841106a220d290000370300200141f0056a41086a220a200841086a2200290000370300200120082900003703f0052008290000210f200641186a222c200c2900003700002006200f370000200641086a222d2000290000370000200641106a222e200d2900003700002001200536028807200141106a20014188076a10cc0320012d0011210e20012d0010212f20014188076a41186a220c200729030037030020014188076a41106a220d200929030037030020014188076a41086a2200200a290300370300200120012903f005370388070240200b202f41017145734101470d00200841206a21080c020b200841206a2108202a41606a222a0d000c040b0b0340200141d8046a41186a200c290300220f370300200141d8046a41106a200d2903002214370300200141d8046a41086a2000290300221f370300200120012903880722203703d804200c200f370300200d20143703002000201f370300200142e4cab5fbb6ccdcb0e3003703a8032001202037038807200141a8036a20014188076a200e41187441187541027441f48fc6006a2802004180de346c20106a10a8022008202b460d03024003402007200841186a220e2900003703002009200841106a222f290000370300200a200841086a222a290000370300200120082900003703f0052001200536028807202a290000210f202f29000021142008290000211f202c200e290000370000202e2014370000202d200f3700002006201f370000200141086a20014188076a10cc0320012d0009210e20012d0008212f200c2007290300370300200d20092903003703002000200a290300370300200120012903f00537038807200b202f41017145730d01202b200841206a2208470d000c050b0b200841206a21080c000b0b41f895c1001032000b41f895c1001032000b02402029450d002028102a0b200510ce0302400240200b0d00200141053a009007200141053a00880720012005360294074101410020014188076a10cc01200141f0056a41086a22084200370300200142003703f00541c290c6004113200141f0056a100820014188076a41086a2008290300370300200120012903f005370388072001200541016a3602f00520114110200141f0056a41041007200141a0086a106a0c010b2001200536029407200141043a009007200141053a0088074101410020014188076a10cc01024020012802ac092207450d00200141f0056a200141a0086a418801109a051a200120053602f80602400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240411710282208450d002008410f6a41002900918945220f370000200841086a410029008a89452214370000200841002900828945221f37000020084117412e102c2208450d012008200720106a2200360017200141d8046a41186a22074200370300200141d8046a41106a22094200370300200141d8046a41086a220a4200370300200142003703d8042008411b200141d8046a100020014188076a41186a220e200729030037030020014188076a41106a222f200929030037030020014188076a41086a220c200a290300370300200120012903d804370388072008102a200141003602d80420014188076a4120200141d8046a1006210b0240024020012802d8042208417f470d00200141003602e004200142013703d8044100200141d8046a10b40120012802e004210820012802dc04210d20012802d804210b0c010b2008210d0b200120083602b8032001200d3602b4032001200b3602b003024002400240024002402008450d00200141d8046a200b2008410110d60220012802d8044101460d0420012802dc04212a20012802e404220820012802e004220b460d0320012802b8032008200b6b6a220d4190016a222c417f4c0d1f202c0d014101212d0c020b4101200141b0036a10b40120012802b403210b20012802b8032108024020012802f0054113470d0002400240200b2008460d0020012802b003210b0c010b200841016a220b2008490d222008410174220d200b200d200b4b1b220d4100480d220240024020080d00200d1028210b0c010b20012802b0032008200d102c210b0b200b450d082001200d3602b4032001200b3602b00320012802b80321080b2001200841016a3602b803200b20086a41003a00000c150b02400240200b2008460d0020012802b003210b0c010b200841016a220b2008490d212008410174220d200b200d200b4b1b220d4100480d210240024020080d00200d1028210b0c010b20012802b0032008200d102c210b0b200b450d082001200d3602b4032001200b3602b00320012802b80321080b2001200841016a3602b803200b20086a41013a0000200141f0056a200141b0036a10eb01200141f0056a4188016a280200210d0240024020012802b403220b20012802b80322086b4104490d0020012802b003210b0c010b200841046a222a2008490d21200b4101742208202a2008202a4b1b22084100480d2102400240200b0d0020081028210b0c010b20012802b003200b2008102c210b0b200b450d09200120083602b4032001200b3602b00320012802b80321080b2001200841046a3602b803200b20086a200d3600000c140b202c1028222d450d080b2001202c3602dc0a2001202d3602d80a2001200d3602e00a2001200141d80a6a3602d804202a200141d8046a200810d701200d2008490d0820012802e00a222a200d490d0920012802b803222a200b490d0a20012802d80a212c20012802b003212d2001200d20086b220d3602e80a2001202a200b6b222a3602ec0a200d202a470d0b202c20086a202d200b6a200d109a051a20012802dc0a210b20012802e00a21080240024020012802f0054113470d0002400240200b2008460d0020012802d80a210b0c010b200841016a220b2008490d212008410174220d200b200d200b4b1b220d4100480d210240024020080d00200d1028210b0c010b20012802d80a2008200d102c210b0b200b450d0f2001200d3602dc0a2001200b3602d80a20012802e00a21080b2001200841016a3602e00a200b20086a41003a00000c010b02400240200b2008460d0020012802d80a210b0c010b200841016a220b2008490d202008410174220d200b200d200b4b1b220d4100480d200240024020080d00200d1028210b0c010b20012802d80a2008200d102c210b0b200b450d0f2001200d3602dc0a2001200b3602d80a20012802e00a21080b2001200841016a3602e00a200b20086a41013a0000200141f0056a200141d80a6a10eb01200141f0056a4188016a280200210d0240024020012802dc0a220b20012802e00a22086b4104490d0020012802d80a210b0c010b200841046a222a2008490d20200b4101742208202a2008202a4b1b22084100480d2002400240200b0d0020081028210b0c010b20012802d80a200b2008102c210b0b200b450d10200120083602dc0a2001200b3602d80a20012802e00a21080b2001200841046a3602e00a200b20086a200d3600000b20012802e00a210b20012802dc0a210d20012802d80a210820012802b403450d1320012802b003102a0c130b2001200141b0036a3602d804202a200141d8046a200b10d70120012802b403210b20012802b8032108024020012802f0054113470d0002400240200b2008460d0020012802b003210b0c010b200841016a220b2008490d1f2008410174220d200b200d200b4b1b220d4100480d1f0240024020080d00200d1028210b0c010b20012802b0032008200d102c210b0b200b450d102001200d3602b4032001200b3602b00320012802b80321080b2001200841016a3602b803200b20086a41003a00000c120b02400240200b2008460d0020012802b003210b0c010b200841016a220b2008490d1e2008410174220d200b200d200b4b1b220d4100480d1e0240024020080d00200d1028210b0c010b20012802b0032008200d102c210b0b200b450d102001200d3602b4032001200b3602b00320012802b80321080b2001200841016a3602b803200b20086a41013a0000200141f0056a200141b0036a10eb01200141f0056a4188016a280200210d0240024020012802b403220b20012802b80322086b4104490d0020012802b003210b0c010b200841046a222a2008490d1e200b4101742208202a2008202a4b1b22084100480d1e02400240200b0d0020081028210b0c010b20012802b003200b2008102c210b0b200b450d11200120083602b4032001200b3602b00320012802b80321080b2001200841046a3602b803200b20086a200d3600000c110b20012802b403450d1220012802b003102a0c120b411741011037000b412e41011037000b200d41011037000b200d41011037000b200841011037000b202c41011037000b2008200d1044000b200d202a103c000b200b202a1044000b200141c0036a41146a4108360200200141cc036a4125360200200141f00a6a41146a4103360200200142033702f40a200141c8afc6003602f00a200141253602c4032001200141e80a6a3602880b2001200141ec0a6a36028c0b200142043703e804200142013702dc042001419cb0c6003602d8042001200141c0036a3602800b2001200141d8046a3602d00320012001418c0b6a3602c8032001200141880b6a3602c003200141f00a6a41d8b0c600103e000b200d41011037000b200d41011037000b200841011037000b200d41011037000b200d41011037000b200841011037000b20012802b803210b20012802b403210d20012802b00321080b2008450d0020014188076a41202008200b1007200d450d012008102a0c010b41900110282208450d014113210b024020012802f0054113460d0020014188076a200141f0056a10cf032001200141f0056a4188016a28020036029008200128028807210b200141d8046a2006418c01109a051a0b2008200b360200200841046a200141d8046a418c01109a051a41171028220b450d02200b410f6a200f370000200b41086a2014370000200b201f370000200b4117412e102c220b450d03200b20003600172007420037030020094200370300200a4200370300200142003703d804200b411b200141d8046a1000200e2007290300370300202f2009290300370300200c200a290300370300200120012903d80437038807200b102a200141d8046a2008410110ac0220014188076a412020012802d804220720012802e0041007024020012802dc04450d002007102a0b024020082802004113460d002008106a0b2008102a0b024020012802f0054113460d00200141f0056a106a0b200141f0056a41086a22084200370300200142003703f00541c290c6004113200141f0056a1008200c2008290300370300200120012903f005370388072001200541016a3602f00520114110200141f0056a410410070c040b41900141081037000b411741011037000b412e41011037000b20014188076a200141a0086a418801109a051a200141003b01f005200141d8046a20014188076a200141f0056a10f401200120012d00e0044102463a009107200141073a009007200141053a00880720012005360294074101410020014188076a10cc01200141f0056a41086a22084200370300200142003703f00541c290c6004113200141f0056a100820014188076a41086a2008290300370300200120012903f005370388072001200541016a3602f00520114110200141f0056a410410070b20162015470d000b201521160c010b1036000b024020162015460d00200141a0086a41086a2108200141a0086a410c6a21070340201641086a28020021062016290300210f200141a0086a2016410c6a419401109a051a20064113460d01200141c0096a200141a0086a419401109a051a200120063602a8082001200f3703a0082007200141c0096a419401109a051a2008106a201641a0016a22162015470d000b0b02402013450d002012102a0b0240024002400240411710282206450d002006410f6a41002900918945370000200641086a410029008a894537000020064100290082894537000020064117412e102c2206450d01200620103600174200210f200141d8046a41186a22084200370300200141d8046a41106a22074200370300200141d8046a41086a22054200370300200142003703d8042006411b200141d8046a100020014188076a41186a200829030037030020014188076a41106a200729030037030020014188076a41086a2005290300370300200120012903d804370388072006102a200141003602a00820014188076a4120200141a0086a100621080240024020012802a0082206417f470d004108210b0c010b200120063602c409200120083602c009200141a0086a200141c0096a10800120012802a008220b450d0320012902a408210f02402006450d002008102a0b20014188076a412010090b200b200f422088a722084190016c22076a2105200b210602402008450d00200741f07e6a2107200141a0086a410472210a200b21060240034020062802002108200141c0096a200641046a418401109a051a20084114460d01200141a0086a200141c0096a418401109a051a02400240024020084113470d0020070d01200521060c050b20064188016a280200210920014188076a200141a0086a418401109a051a200120083602a008200a20014188076a418401109a051a200141003b01c009200141f0056a200141a0086a200141c0096a10f40120012d00f8052108200120093602ac08200120084102463a00a908200141073a00a808200141053a00a00841014100200141a0086a10cc012007450d010b20064190016a2106200741f07e6a21070c010b0b200521060c010b20064190016a21060b200fa7210920062005460d03200141a0086a4104722107034020062802002108200141a0086a200641046a418c01109a051a20084114460d04200141c0096a200141a0086a418c01109a051a200120083602a0082007200141c0096a418c01109a051a024020084113460d00200141a0086a106a0b20064190016a22062005470d000c040b0b411741011037000b412e41011037000b41c4d1c3004133200141f0056a419cd9c3001038000b02402009450d00200b102a0b201010bd0202402002450d00200241246c21082004210603400240024020062d0000220741034b0d0002400240024020070e0404000102040b2006410c6a280200450d03200641086a280200102a0c030b2006410c6a280200450d02200641086a280200102a0c020b2006410c6a280200450d01200641086a280200102a0c010b200641086a280200450d00200641046a280200102a0b200641246a21062008415c6a22080d000b0b02402003450d002004102a0b200141900b6a24000f0b1031000be80201067f230041b0026b2201240020014198016a41086a22024200370300200142003703980141988bc500411620014198016a100820014188016a41086a2203200229030037030020012001290398013703880120014198016a20014188016a10df030240024020012802980122044113470d0041ae8bc50021020c010b20014188016a41101009200141046a20014198016a4104722205418401109a051a200141a0026a2d00002106200141013a00af0220024200370300200142003703980141d590c600411f20014198016a10082003200229030037030020012001290398013703880120014188016a4110200141af026a41011007200241023a0000200141053a009801410021024101410020014198016a10cc0120012004360298012005200141046a418401109a051a20014188016a200041809c316a20014198016a20064180de3410b7042001280288014101470d00200128028c0121020b200141b0026a240020020bc01802117f187e230041f0056b22012400200141a0046a41086a22024200370300200142003703a00441ac89c5004115200141a0046a1008200141306a41086a2002290300370300200120012903a004370330200141003602a004200141306a4110200141a0046a10062103024002400240024002400240024002400240024020012802a0042204417f460d002003450d002001200436024420012003360240200141286a200141c0006a106c20012802280d09200128024441b0016e220541b0016c2202417f4c0d02200128022c21060240024020020d00410821070c010b200210282207450d040b02402006450d0020014198036a4104722108410021094100210a0340024002400240200128024422024104490d002001280240220b280000210c20012002417c6a3602442001200b41046a360240200141a0046a200141c0006a10810120012802a0044113460d00200a41016a210d20014198036a200141a0046a418801109a051a4100210b200141003a00e8052001280244417f6a2102024003402002417f460d01200141c8056a200b6a2001280240220e2d00003a00002001200e41016a3602402001200b41016a220e3a00e805200120023602442002417f6a2102200e210b200e4120470d000b200141a8056a41186a2202200141c8056a41186a290300370300200141a8056a41106a220e200141c8056a41106a290300370300200141a8056a41086a220f200141c8056a41086a290300370300200120012903c8053703a805200128029803210b20014190026a2008418401109a051a200141f0016a41086a2210200f290300370300200141f0016a41106a220f200e290300370300200141f0016a41186a220e2002290300370300200120012903a8053703f001200b4113460d01200141ec006a20014190026a418401109a051a200141c8006a41186a2211200e290300370300200141c8006a41106a220e200f290300370300200141c8006a41086a220f2010290300370300200120012903f0013703482005200a470d030240200a4101742202200d2002200d4b1b2205ad42b0017e2212422088a70d002012a7220241004e0d030b1031000b0240200b41ff0171450d00200141003a00e8050b20014198036a106a0b0240200a450d002007210203402002106a200241b0016a2102200941d07e6a22090d000b0b2005450d0d2007102a0c0d0b02400240200a0d002002102821070c010b2007200a41b0016c2002102c21070b2007450d070b2007200a41b0016c6a2202200b360200200241046a200141ec006a418401109a051a2002200c360288012002200129034837028c0120024194016a200f2903003702002002419c016a200e290300370200200241a4016a2011290300370200200941b0016a2109200d210a200d2006470d000b0b2007450d092006ad42208621122005ad211302402004450d002003102a0b201220138421140c010b41082107420021140b024002402014422088a72204450d00200141a0046a20072802880110b8040240024020012802b00422020d0042002115420021120c010b200141186a20012903a004200141a0046a41086a290300200141b8046a3502004200109f05200141186a41086a29030021122001290318211520012802b404450d002002102a0b4100210e20044101460d012007200441b0016c6a210a200741b0016a21024100210e200721034101210b0340200141a0046a20024188016a28020010b8040240024020012802b00422090d0042002116420021130c010b200141086a20012903a004200141a0046a41086a29030020013502b8044200109f05200141086a41086a29030021132001290308211620012802b404450d002009102a0b201220132015201656201220135620122013511b22091b21122015201620091b21152003200220091b2103200e200b20091b210e200b41016a210b200241b0016a2202200a470d000b20030d01200441b0016c21092007210203402002106a200241b0016a2102200941d07e6a22090d000b0b41e789c50021022014a7450d072007102a0c070b200e20044f0d0320072004417f6a220941b0016c6a22024180016a290300211320024188016a290300211520024190016a290300211620024198016a2903002117200241e0006a2903002118200241e8006a2903002119200241f0006a290300211a200241f8006a290300211b200241c0006a290300211c200241c8006a290300211d200241d0006a290300211e200241d8006a290300211f200241206a2903002120200241286a2903002121200241306a2903002122200241386a2903002123200229030021242002290308212520022903102126200241186a2903002127200241a0016a2903002112200141306a41086a220b200241a8016a29030022283703002007200e41b0016c6a220241186a220e2903002129200e2027370300200229031021272002202637031020022903082126200220253703082002290300212520022024370300200241386a220e2902002124200e2023370200200241306a220e2902002123200e2022370200200241286a220e2902002122200e2021370200200241206a220e2902002121200e2020370200200241d8006a220e2902002120200e201f370200200241d0006a220e290200211f200e201e370200200241c8006a220e290200211e200e201d370200200241c0006a220e290200211d200e201c370200200241f8006a220e290200211c200e201b370200200241f0006a220e290200211b200e201a370200200241e8006a220e290200211a200e2019370200200241e0006a220e2902002119200e201837020020024198016a201737020020024190016a201637020020024188016a2203280200210e2003201537020020024180016a220329020021152003201337020020012012370330200241a0016a2012370200200241a8016a202837020020014198036a41f8006a201c37030020014198036a41f0006a201b37030020014198036a41e8006a201a37030020014198036a41e0006a201937030020014198036a41d8006a202037030020014198036a41d0006a201f37030020014198036a41c8006a201e37030020014198036a41c0006a201d37030020014198036a41386a202437030020014198036a41306a202337030020014198036a41286a202237030020014198036a41206a202137030020014198036a41186a202937030020014198036a4180016a2015370300200120273703a803200120263703a0032001202537039803200141a0046a41086a22024200370300200142003703a00441ac89c5004115200141a0046a1008200b2002290300370300200120012903a004370330200141103602a4042001200141306a3602a00420072009200141a0046a10ef0102402009450d00200441b0016c41d07e6a21092007210203402002106a200241b0016a2102200941d07e6a22090d000b0b02402014a7450d002007102a0b411310282202450d042002410f6a41002800e38945360000200241086a41002900dc8945370000200241002900d48945370000200241134126102c2202450d052002200e360013200141a8056a41186a22094200370300200141a8056a41106a220b4200370300200141a8056a41086a22034200370300200142003703a80520024117200141a8056a100020014190026a41186a200929030037030020014190026a41106a200b29030037030020014190026a41086a2003290300370300200120012903a805370390022002102a200141a0046a20014190026a10e003024020012802b004220b450d0020014190026a412010090b02400240200b450d00200141a8046a290300211220012903a004211320012802b40421030240200141a0046a41186a280200220a4105742209450d00200b2102034020022013201210aa02200241206a2102200941606a22090d000b0b200141c8046a2012370300200141c0046a2013370300200141b8046a200a360200200141b4046a2003360200200141b0046a200b360200200141ac046a200e360200200141a8046a41013a0000200141053a00a00441014100200141a0046a10cc01200141a0046a20014198036a418801109a051a20014190026a200041809c316a200141a0046a41004180de3410b7042001280290024101470d0120012802940221020c080b20014198036a106a0b410021020c060b1036000b200241081037000b200241081037000b41c489c500200e20041034000b411341011037000b412641011037000b200141f0056a240020020f0b41c4d1c3004133200141a0046a419cd9c3001038000b810601067f230041d0026b2202240002400240024002400240411a10282203450d00200341186a41002f00ce88453b0000200341106a41002900c68845370000200341086a41002900be8845370000200341002900b688453700002003411a4134102c2203450d012003200136001a200241c0016a41186a22014200370300200241c0016a41106a22044200370300200241c0016a41086a22054200370300200242003703c0012003411e200241c0016a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903c0013703002003102a200241003602c00120024120200241c0016a1006210320022802c0012201417f460d032003450d03200220033602282002200136022c20014104490d022003280000210620022001417c6a36022c2002200341046a360228200241c0016a200241286a10810120022802c0014113460d02200241386a200241c0016a418801109a051a02400240200228022c2207450d00200228022822012d0000210420022007417f6a220536022c2002200141016a360228200441034f0d00200541034b0d01200241386a106a0c040b200241386a106a0c030b2001280001210520022007417b6a36022c2002200141056a36022820022802382101200241c0016a200241386a410472418401109a051a200220022800303602202002200241336a28000036002320014113460d02200241386a200241c0016a418401109a051a20022002280023360033200220022802203602302003102a0c040b411a41011037000b413441011037000b41c4d1c3004133200241c8026a419cd9c3001038000b411321010b200241c0016a200241386a418401109a051a2002200228003336002b200220022802303602280240024020014113470d00200041133602000c010b20002001360200200041046a200241c0016a418401109a051a20004190016a20043a00002000418c016a200536020020004188016a2006360200200020022802283600910120004194016a200228002b3600000b200241d0026a24000bfb0202047f017e230041d0006b22022400024002400240411310282203450d002003410f6a41002800a88945360000200341086a41002900a18945370000200341002900998945370000200341134126102c2203450d0120032001360013200241286a41186a22014200370300200241286a41106a22044200370300200241286a41086a220542003703002002420037032820034117200241286a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903283703002003102a2002410036022820024120200241286a100621010240024020022802282203417f460d002002200336022420022001360220200241286a200241206a106d20022802282204450d04200229022c210602402003450d002001102a0b20002006370204200020043602000c010b20004100360208200042013702000b200241d0006a24000f0b411341011037000b412641011037000b41c4d1c3004133200241c8006a419cd9c3001038000ba40301057f230041d0006b22022400024002400240411010282203450d00200341002900a68845370000200341086a41002900ae88453700002002429080808080023702242002200336022020012802002104200341104120102c2203450d0120032004360010200242a0808080c00237022420022003360220200141046a200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b410021032002410036023020024120200241306a100621010240024020022802302204417f470d00410021010c010b2004450d0320012d0000220441ff0071220341074f0d032001102a200441077621010b200020033a0001200020013a0000200241d0006a24000f0b411041011037000b412041011037000b41c4d1c3004133200241306a419cd9c3001038000bf00b04017f047e117f087e23004190046b22052400024002400240024020040d00420021064200210742002108420021090c010b42002108200541f0036a41186a220a4200370300200541f0036a41106a220b4200370300200541f0036a41086a220c4200370300200542003703f00341e588c500411d200541f0036a100020054198036a41186a220d200a29030037030020054198036a41106a220e200b29030037030020054198036a41086a220f200c290300370300200520052903f0033703980320054198016a20054198036a412010fd01200541c0016a41206a20054198016a41206a2d00003a0000200541c0016a41186a20054198016a41186a290300370300200541c0016a41106a20054198016a41106a290300370300200541c0016a41086a20054198016a41086a29030037030020052005290398013703c001200541e8016a200541c0016a10af0142002109420021064200210720052d00a8024107460d002004417f6a2110200541b8036a4104722111200541f0026a2112200541b0026a41206a2113200541b0026a41186a211442002106420021074200210842002109034020142007370300200520063703c002200520083703b002200520093703b8022013200541e8016a41c100109a0521040240024020122002460d00201220024120109c050d010b20112004290200370200201141086a200441086a2215290200370200201141106a200441106a2216290200370200201141186a200441186a2217290200370200200520013602b803411010282218450d03201841002900a68845370000201841086a41002900ae88453700002005429080808080023702e403200520183602e00320052802b8032119201841104120102c2218450d04200541203602e403200520052802e803221a41046a3602e803200520183602e0032018201a6a20193600002011200541e0036a108f0120052802e803211820052802e0032119200a4200370300200b4200370300200c4200370300200542003703f00320192018200541f0036a1000200d200a290300370300200e200b290300370300200f200c290300370300200520052903f00337039803024020052802e403450d0020052802e003102a0b20054198036a41204101410041001003417f470d0020052d0090032118200a2017290000370300200b2016290000370300200c2015290000370300200520042900003703f00320054188016a200541f0036a109d0220054188016a41086a290300211b200529038801211c02400240201820032018200341ff0171491b220441ff01710d00200541086a201c201b420a420010a005200541b8036a41186a200a290300370300200541b8036a41106a200b290300370300200541b8036a41086a200c290300370300200520052903f0033703b803200541186a2001200541b8036a4100201010cd03200541186a41186a290300211d200541186a41086a290300211e2005290328211f2005290318212020052903082221211c200541086a41086a2903002222211b0c010b200541c8006a201b42002004ad42ff018322214200109f05200541d8006a201c420020214200109f05200541b8036a41186a200a290300370300200541b8036a41106a200b290300370300200541b8036a41086a200c290300370300200520052903f0033703b803200541e8006a2001200541b8036a2004201010cd03200541386a42004200201c4200109f05427f200541d8006a41086a2903002221200529034820052903387c7c221d2005290350200529034084420052201d2021547222041b2122427f200529035820041b2121200541e8006a41186a290300211d200541e8006a41086a290300211e2005290378211f200529036821200b201b20077c201c20067c2207201c54ad7c201d7c2007201f7c2206200754ad7c2107202220097c202120087c2209202154ad7c201e7c200920207c2208200954ad7c21090b200541e8016a200541c0016a10af0120052d00a8024107470d000b0b2000200637031020002008370300200041186a20073703002000200937030820054190046a24000f0b411041011037000b412041011037000be907030b7f047e027f230041a0016b22012400024002400240024002400240411a10282202450d00200241186a41002f00ce88453b0000200241106a41002900c68845370000200241086a41002900be8845370000200241002900b688453700002002411a4134102c2202450d012002200036001a20014180016a41186a2203420037030020014180016a41106a2204420037030020014180016a41086a2205420037030020014200370380012002411e20014180016a1000200141286a41186a2003290300370300200141286a41106a2004290300370300200141286a41086a200529030037030020012001290380013703282002102a200141286a41201009411310282202450d022002410f6a41002800a88945360000200241086a41002900a18945370000200241002900998945370000200241134126102c2202450d032002200036001320014180016a41186a2205420037030020014180016a41106a2206420037030020014180016a41086a2203420037030020014200370380012002411720014180016a1000200141286a41186a22072005290300370300200141286a41106a22082006290300370300200141286a41086a200329030037030020012001290380013703282002102a200141286a41201009200141c8006a200010cb03200128024c21092001280248210a024020012802502202450d002002410574210b200141c8006a4104722103200a21020340200141086a41186a200241186a290000220c370300200141086a41106a200241106a290000220d370300200141086a41086a200241086a290000220e37030020012002290000220f3703082003200f370200200341086a200e370200200341106a200d370200200341186a200c37020020012000360248411010282204450d06200441002900a68845370000200441086a41002900ae88453700002001429080808080023702742001200436027020012802482110200441104120102c2204450d072001412036027420012001280278221141046a36027820012004360270200420116a20103600002003200141f0006a108f012001280278210420012802702110200542003703002006420037030020014180016a41086a2211420037030020014200370380012010200420014180016a10002007200529030037030020082006290300370300200141286a41086a2011290300370300200120012903800137032802402001280274450d002001280270102a0b200241206a2102200141286a41201009200b41606a220b0d000b0b02402009450d00200a102a0b200141a0016a24000f0b411a41011037000b413441011037000b411341011037000b412641011037000b411041011037000b412041011037000b801102047f027e230041e0016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1514000102030405060708090a0b0c0d0e0f10111213140b10a103000b20004102360200200041086a200141086a2903003703000c130b200241e0006a200141046a1070200041033602002000410c6a200241e8006a280200360200200020022903603702040c120b10bb03000b200241e0006a200141086a10ae02200041086a200241e0006a41e000109a051a200041053602000c100b200241e0006a200141086a10bc0320004106360200200041386a200241e0006a41306a290300370300200041306a200241e0006a41286a290300370300200041286a200241e0006a41206a290300370300200041206a200241e0006a41186a290300370300200041186a200241e0006a41106a290300370300200041106a200241e0006a41086a290300370300200041086a20022903603703000c0f0b200241e0006a41186a200141286a290000370300200241e0006a41106a200141206a290000370300200241e8006a200141186a290000370300200241e0006a41286a200141386a290000370300200241e0006a41306a200141c0006a290000370300200241e0006a41386a200141c8006a290000370300200241e0006a41c8006a200141d8006a290000370300200241e0006a41d0006a200141e0006a290000370300200241e0006a41d8006a200141e8006a2900003703002002200141106a2900003703602002200141306a290000370380012002200141d0006a2900003703a0012001410c6a2802002203417f4c0d0f200128020421010240024020030d0041012104410021050c010b20032105200310282204450d110b200420012003109a0521012002200241e0006a41e000109a0521042000410c6a2003360200200041086a200536020020002001360204200041106a200441e000109a051a200041073602000c0e0b200241e0006a200141086a10bd0320004108360200200041306a200241e0006a41286a290300370300200041286a200241e0006a41206a290300370300200041206a200241e0006a41186a290300370300200041186a200241e0006a41106a290300370300200041106a200241e0006a41086a290300370300200041086a20022903603703000c0d0b200241e0006a200141046a10c30320004109360200200041246a20024180016a2903003702002000411c6a200241f8006a290300370200200041146a200241f0006a2903003702002000410c6a200241e8006a290300370200200020022903603702040c0c0b200241e0006a200141046a10c3032000410a360200200041246a20024180016a2903003702002000411c6a200241f8006a290300370200200041146a200241f0006a2903003702002000410c6a200241e8006a290300370200200020022903603702040c0b0b200241e0006a200141086a10d3022000410b360200200041c0006a200241e0006a41386a290300370300200041386a200241e0006a41306a290300370300200041306a200241e0006a41286a290300370300200041286a200241e0006a41206a290300370300200041206a200241e0006a41186a290300370300200041186a200241e0006a41106a290300370300200041106a200241e0006a41086a290300370300200041086a20022903603703000c0a0b200241e0006a200141046a10be03200041046a200241e0006a41c400109a051a2000410c3602000c090b2000410d360200200020012802043602040c080b2001410c6a2802002203417f4c0d08200128020421010240024020030d0041002104410121050c010b20032104200310282205450d0b0b200520012003109a0521012000410c6a2003360200200041086a2004360200200020013602042000410e3602000c070b024002400240024002400240200141086a280200417f6a220341024b0d0020030e03010203010b418486c2001032000b200141386a2903002106200141306a290300210741012103024002402001410c6a2d00004101460d00200241e8006a2001411c6a290200370300200241e0006a41106a200141246a290200370300200241f8006a2001412c6a2d00003a00002002200141146a29020037036020012f000d2001410f6a2d0000411074722104200141106a2802002105410021030c010b200141106a28020021050b200241186a200241e0006a41186a280200360200200241106a200241e0006a41106a290300370300200241086a200241e0006a41086a29030037030020022002290360370300410121010c030b2001410c6a28020022034108762104410221010c010b2001410c6a28020022034108762104410321010b0b2000410f360200200041386a2006370300200041306a2007370300200041106a2005360200200041086a2001360200200041146a20022903003702002000410c6a2004410874200341ff0171723602002000411c6a200241086a290300370200200041246a200241106a2903003702002000412c6a200241186a2802003602000c060b200241e0006a200141086a10bf03200041086a200241e0006a418001109a051a200041103602000c050b200241e0006a200141046a10c003200041113602002000412c6a20024188016a280200360200200041246a20024180016a2903003702002000411c6a200241f8006a290300370200200041146a200241f0006a2903003702002000410c6a200241e8006a290300370200200020022903603702040c040b200241e0006a200141046a10af02200041046a200241e0006a41e400109a051a200041123602000c030b10c103000b10d501000b200241e0006a200141086a10c20320004100360200200041106a200241e0006a41086a290300370300200041086a20022903603703000b200241e0016a24000f0b1036000b200341011037000b200341011037000bfe1a03087f047e037f23004180076b22042400200441c8036a200141a002109a051a200441e8016a200441c8036a10d10341012105024002400240024002400240024020042d00e8014101470d00200020042f00e9013b0001200041013a0000200041036a20042d00eb013a000020032802002106410021000c010b200441106a200441e8016a41086a41d801109a051a0240024002400240024002400240024002400240024020032802002206450d00200341086a28020021072003280204210841002109200441003602c8034188e8c2004110200441c8036a10062101024020042802c8032205417f460d002001450d0020054104490d02200128000021092001102a0b411410282201450d0241002105200141106a41002800eaa046360000200141086a41002900e2a046370000200141002900daa046370000200141144128102c2201450d0320012009360014200441e8016a41186a22094200370300200441e8016a41106a220a4200370300200441e8016a41086a220b4200370300200442003703e80120014118200441e8016a1000200441c0066a41186a2009290300370300200441c0066a41106a200a290300370300200441c0066a41086a200b290300370300200420042903e8013703c0062001102a200441203602cc032004200441c0066a3602c80320062007200441c8036a10cb012008450d002006102a0b200441086a200441106a41d0006a10f3012004280208210720042d000c2108200441c8036a200441106a41d801109a051a4100210120042903e803220c4202510d0c20044198066a41186a200441c8036a41186a29030037030020044198066a41106a200441c8036a41106a29030037030020044198066a41086a200441c8036a41086a290300370300200420042903c8033703980620044188046a290300210d20044180046a290300210e20044190046a280200210920042903f003210f200441e8016a41086a22014200370300200442003703e80141d9efc200410d200441e8016a1008200441c0066a41086a2001290300370300200420042903e8013703c006200441003602e801200441c0066a4110200441e8016a10062101024020042802e801220a417f460d002001450d00200a41034d0d042001102a0b0240200c4201520d00200f4200510d050b411310282201450d05200141002900cef0423700002001410f6a41002800ddf042360000200141086a41002900d6f04237000020044293808080b0023702fc05200420013602f80520044198066a200441f8056a108f01200428028006210120042802f805210a200441e8016a41186a220b4200370300200441e8016a41106a22104200370300200441e8016a41086a22114200370300200442003703e801200a2001200441e8016a1000200441c0066a41186a200b290300370300200441c0066a41106a2010290300370300200441c0066a41086a2011290300370300200420042903e8013703c006024020042802fc05450d0020042802f805102a0b200441003602e801200441c0066a4120200441e8016a1006210a0240024020042802e8012201417f470d00410021010c010b0240200a0d00410021010c010b20014104490d07200a2800002101200a102a0b200441c8036a41d0006a210a024020012009470d00411310282201450d0820084101712108200941016a2109200141002900cef0423700002001410f6a41002800ddf042360000200141086a41002900d6f04237000020044293808080b0023702fc05200420013602f80520044198066a200441f8056a108f01200428028006210120042802f805210b200441e8016a41186a22104200370300200441e8016a41106a22114200370300200441e8016a41086a22124200370300200442003703e801200b2001200441e8016a1000200441c0066a41186a2010290300370300200441c0066a41106a2011290300370300200441c0066a41086a2012290300370300200420042903e8013703c006024020042802fc05450d0020042802f805102a0b200420093602e801200441c0066a4120200441e8016a41041007200441e8016a2008200210b803024020042903e801220ca741ff01714101460d00200441e8016a41086a22014200370300200442003703e80141a8a0c6004117200441e8016a1008200441c0066a41086a22092001290300370300200420042903e8013703c0062004200c4220883e02e801200441c0066a4110200441e8016a41041007200441e8016a2007200810b90320042903e801220ca741ff01714101460d0020014200370300200442003703e801418ea0c600411a200441e8016a100820092001290300370300200420042903e8013703c0062004200c4220883e02e801200441c0066a4110200441e8016a410410070c0a0b200c420888a7220941ff01714104460d09200c421088a721010c0a0b41034102200120094b1b2101410021090c090b41c4d1c3004133200441e8016a419cd9c3001038000b411441011037000b412841011037000b41c4d1c3004133200441e8016a419cd9c3001038000b41fcf8c5001032000b411341011037000b41c4d1c3004133200441e8016a419cd9c3001038000b411341011037000b200441e8016a200e200d20044198066a200720082002109e020240024020042d00e8014101460d0020044194026a280200210920044190026a280200210b2004418c026a280200210720044184026a280200211020044180026a2802002108024020044188026a2802002201450d002001410c6c21022008210103400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b02402010450d002008102a0b02402009450d002009410c6c21022007210103400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b200b450d012007102a0c010b20042f01ea01210120042d00e9012209417e6a220241024b0d0120020e03000100000b200441e8016a200a10d203024020042d00e8014101460d0020044194026a280200210920044190026a280200210a2004418c026a280200210720044184026a280200210b20044180026a2802002108024020044188026a2802002201450d002001410c6c21022008210103400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b0240200b450d002008102a0b02402009450d002009410c6c21022007210103400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b200a450d032007102a0c030b20042f01ea01210120042d00e9012209417e6a220241024b0d0020020e03020002020b200a106a200441f0056a41026a200441f4056a41026a2d00003a0000200420042f00f4053b01f005200041036a20014108763a000020002001410874200941ff0171723b0001200041013a000020054521000b20000d032006450d03200341046a2802000d020c030b200441e0066a41186a20044198066a41186a290300370300200441e0066a41106a20044198066a41106a290300370300200441e0066a41086a20044198066a41086a29030037030020042004290398063703e006410121010b200441f8056a41186a2208200441e0066a41186a2202290300370300200441f8056a41106a220a200441e0066a41106a2209290300370300200441f8056a41086a220b200441e0066a41086a2207290300370300200420042903e0063703f805200441e8016a200441c8036a41d0006a418801109a051a200220082903003703002009200a2903003703002007200b290300370300200420042903f8053703e0064102210802402001450d00200441c0066a41186a2002290300370300200441c0066a41106a2009290300370300200441c0066a41086a2007290300370300200420042903e0063703c006410121080b200441a2066a200441c0066a41086a290300370100200441aa066a200441c0066a41106a290300370100200441b2066a200441c0066a41186a290300370100200420083a009906200420042903c00637019a06200441003a009806200441e0066a200441e8016a20044198066a10f401200441e8016a41026a200441eb066a2d00003a0000200420042f00e9063b01e80120042903e006210c024020042d00e80622014102460d0020044198066a41026a200441e8016a41026a2d00003a0000200420042f01e8013b0198060b200441ec056a41026a220220044198066a41026a2d00003a0000200420042f0198063b01ec05024020014102460d00200441e8016a41026a20022d00003a0000200420042f01ec053b01e8010b200441d4036a20013a0000200441d5036a20042f01e8013b0000200441d7036a200441e8016a41026a2d00003a00002004200c3702cc03200441003a00c8034101210941014100200441c8036a10cc01200441003602c8034188e8c2004110200441c8036a10062102024020042802c8032207417f460d002002450d0020074104490d03200228000021092002102a200941016a21090b200420093602c8034188e8c2004110200441c8036a410410072000410c6a20013a0000200041046a200c3702002000410d6a20042f01ec053b00002000410f6a200441ee056a2d00003a0000200041003a00002006450d012005450d01200341046a280200450d010b2006102a0b20044180076a24000f0b41c4d1c3004133200441e8016a419cd9c3001038000bf41f05017f037e077f017e037f230041a00a6b22022400420221030240024002400240024002400240024002400240024002400240200129036822044202520d00200220014198016a418801109a051a0c010b20024188026a200141dc006a29000037030020024180026a200141d4006a290000370300200241f8016a200141cc006a290000370300200241d0016a41206a200141c4006a290000370300200241d0016a41186a2001413c6a290000370300200241d0016a41106a200141346a290000370300200241d0016a41086a2001412c6a290000370300200220012900243703d00120024190026a41086a20014188016a29030037030020024190026a41106a20014190016a290300370300200220014180016a29030037039002200141f8006a2903002103200129037021052001280204210620012d00002107200241800a6a41026a2208200141036a2d00003a0000200241c8026a41086a2209200141106a290200370300200241c8026a41106a220a200141186a290200370300200241c8026a41186a220b200141206a280200360200200220012f00013b01800a200220012902083703c80202400240024020074101460d00200241e0096a41026a20082d00003a0000200241b0066a41086a2009290300370300200241b0066a41106a200a290300370300200241b0066a41186a200b2d00003a0000200220022f01800a3b01e009200220022903c8023703b0060c010b200241c0076a200641067610fe0120022802c00721070240024020022802c8072006413f7122064b0d00410021080c010b200241e0096a41026a200720064105746a220641026a2d00003a0000200241b8066a2006410f6a290000370300200241c0066a200641176a290000370300200241c8066a2006411f6a2d00003a0000200220062f00003b01e009200220062900073703b00620062800032106410121080b024020022802c407450d002007102a0b20080d00410121070c010b200241c0076a41026a200241e0096a41026a2d00003a0000200241c8026a41086a200241b0066a41086a290300370300200241c8026a41106a200241b0066a41106a290300370300200241c8026a41186a200241b0066a41186a2d00003a0000200220022f01e0093b01c007200220022903b0063703c802410021070b200241c0096a41026a2208200241c0076a41026a2d00003a0000200241a0056a41086a2209200241c8026a41086a290300370300200241a0056a41106a220a200241c8026a41106a290300370300200241a0056a41186a220b200241c8026a41186a2d00003a0000200220022f01c0073b01c009200220022903c8023703a00502402007450d00200041013b0001200041013a0000200041036a41003a000020014198016a106a0c0c0b200241b7026a2009290300370000200241bf026a200a290300370000200241c7026a200b2d00003a0000200220022f01c0093b01a802200220063600ab02200220022903a0053700af02200220082d00003a00aa02200241c0076a20014198016a418801109a051a200241c8086a41106a20024190026a41106a290300370300200241c8086a41086a20024190026a41086a29030037030020022002290390023703c80841002107200241800a6a410010f701200241c0096a41086a2002418b0a6a290000370300200241c0096a41106a200241930a6a290000370300200241d5096a200241800a6a41186a290000370000200220022900830a3703c00920022f01800a210b20022d00820a210c200241800a6a41086a22014200370300200242003703800a41d9efc200410d200241800a6a1008200241e0096a41086a2001290300370300200220022903800a3703e009200241003602800a200241e0096a4110200241800a6a10062101024020022802800a2206417f460d002001450d0020064104490d02200128000021072001102a0b41002106024020044201520d0020054200510d03417f21062007ad220d20032003200d541b220d200d20037d2005827d220d42ffffffff0f560d00200da721060b411010282201450d03200141086a41002900c6f042370000200141002900bef042370000200141104120102c2201450d0420012006360010200241800a6a41186a22074200370300200241800a6a41106a22084200370300200241800a6a41086a22094200370300200242003703800a20014114200241800a6a1000200241e0096a41186a2007290300370300200241e0096a41106a220a2008290300370300200241e0096a41086a2009290300370300200220022903800a3703e0092001102a4101210102400240200241e0096a41204101410041001003417f470d000c010b200241800a6a200610f701200241a0096a41086a2002418b0a6a290000370300200241a0096a41106a200241930a6a290000370300200241a0096a41156a2007290000370000200241e0096a41086a200241c0096a41086a290300370300200a200241c0096a41106a290300370300200241e0096a41156a200241c0096a41156a290000370000200220022900830a3703a009200220022903c0093703e00920022f01800a20022d00820a411074722106410021010b20024180096a41156a2207200241e0096a41156a29000037000020024180096a41106a2208200241e0096a41106a29030037030020024180096a41086a2209200241e0096a41086a290300370300200241e0086a41086a220a200241a0096a41086a290300370300200241e0086a41106a220e200241a0096a41106a290300370300200241e0086a41156a220f200241a0096a41156a290000370000200220022903e00937038009200220022903a0093703e00802402001450d00200241c0076a106a200041036a41003a0000200041800a3b0001200041013a00000c0c0b200241e8046a41156a22012007290000370000200241e8046a41106a22072008290300370300200241e8046a41086a22082009290300370300200241c8046a41086a2209200a290300370300200241c8046a41106a220a200e290300370300200241c8046a41156a220e200f29000037000020022002290380093703e804200220022903e0083703c80420024188056a41106a220f200241c8086a41106a29030037030020024188056a41086a2210200241c8086a41086a290300370300200220022903c80837038805200241b0066a41046a200241c0076a418801109a051a200241a0056a200241b0066a418c01109a051a200241c8026a200241a0056a41046a418801109a051a20024186046a200b200c41107472220b4110763a000020024184046a220c200b3b0100200241e0036a2003370300200241d8036a2005370300200241e8036a220b200229038805370300200241f0036a2010290300370300200241f8036a2210200f29030037030020024187046a20022903e8043700002002418f046a200829030037000020024197046a20072903003700002002419c046a2001290000370000200220043703d003200241a30136028004200241a6046a20064110763a0000200241a4046a220720063b0100200241a7046a20022903c804370000200241af046a2009290300370000200241b7046a200a290300370000200241bc046a200e290000370000410410282201450d05200242043702b406200220013602b006200241c8026a200241b0066a10eb010240024020022903d0034201510d000240024020022802b40620022802b8062201460d0020022802b00621060c010b200141016a22062001490d0c200141017422082006200820064b1b22084100480d0c0240024020010d002008102821060c010b20022802b00620012008102c21060b2006450d09200220083602b406200220063602b00620022802b80621010b2002200141016a3602b806200620016a41003a00000c010b20022903e00320022903d8032203420c882204420120044201561b8021040240024020022802b406220620022802b80622016b4102490d0020022802b00621060c010b200141026a22082001490d0b200641017422012008200120084b1b22014100480d0b0240024020060d002001102821060c010b20022802b00620062001102c21060b2006450d09200220013602b406200220063602b00620022802b80621010b2002200141026a3602b806200620016a2004a741047420037aa7417f6a22014101200141014b1b2201410f2001410f491b723b00000b2010200241b0066a10a0012002200b3602a005200241a0056a200241b0066a10a30120022802800421080240024020022802b406220620022802b80622016b4104490d0020022802b00621060c010b200141046a22092001490d0a200641017422012009200120094b1b22014100480d0a0240024020060d002001102821060c010b20022802b00620062001102c21060b2006450d09200220013602b406200220063602b00620022802b80621010b2002200141046a3602b806200620016a20083600002002200241b0066a3602a005200c200241a0056a10c8012002200241b0066a3602a0052007200241a0056a10c80120022802b006210120022802b40621060240024020022802b80622074180024b0d00200241d0016a20012007200241a8026a10dd0321070c010b200241800a6a41186a22084200370300200241800a6a41106a22094200370300200241800a6a41086a220a4200370300200242003703800a20012007200241800a6a1000200241e0096a41186a2008290300370300200241e0096a41106a2009290300370300200241e0096a41086a200a290300370300200220022903800a3703e009200241d0016a200241e0096a4120200241a8026a10dd0321070b02402006450d002001102a0b2007450d0a200241b0016a41086a200241a8026a41086a290300370300200241b0016a41106a200241a8026a41106a290300370300200241b0016a41186a200241a8026a41186a29030037030020024188016a41086a200241e0036a29030037030020024188016a41106a200241e8036a29030037030020024188016a41186a200241f0036a290300370300200241a8016a200241f8036a290300370300200220022903a8023703b0012002200241d8036a2903003703880120022903d00321032002200241c8026a418801109a051a0b200041086a20022903b001370300200041286a2003370300200041306a200229038801370300200041206a200241b0016a41186a290300370300200041186a200241b0016a41106a290300370300200041106a200241b0016a41086a290300370300200041386a20024188016a41086a290300370300200041c0006a20024188016a41106a290300370300200041c8006a20024188016a41186a290300370300200041d0006a20024188016a41206a290300370300200041d8006a2002418801109a051a200041003a0000200241a00a6a24000f0b41c4d1c3004133200241800a6a419cd9c3001038000b41fcf8c5001032000b411041011037000b412041011037000b410441011037000b200841011037000b200141011037000b200141011037000b1031000b20004180083b0001200041013a0000200041036a41003a0000200241c8026a106a0b200241a00a6a24000be00402037f017e230041306b220224000240024020012802004110460d00200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c010b024002400240024002400240200141086a2d00000e06050402010004050b200141c8006a21030c020b200141d0006a21030c010b200141186a21030b200241086a41086a220142003703002002420037030841affec5004111200241086a1008200241206a41086a20012903003703002002200229030837032020024100360208200241206a4110200241086a1006210102400240024020022802082204417f470d004280ade20421050c010b024020010d004280ade20421050c010b20044108490d01200129000021052001102a4280ade20420057d21050b024020032903002005560d00200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c040b200041800c3b0001200041013a0000200041036a41003a00000c030b41c4d1c3004133200241086a419cd9c3001038000b200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c010b2002411c6a41013602002002420137020c200241ccd1c50036020820024104360224200241ccd0c3003602202002200241206a360218200241086a41f0d0c300103e000b200241306a24000ba60201037f412e210241f8f4c50021030240024002402001417e6a22044102200441ff01714102491b41ff01710e03020001020b4130210241c8f4c50021030c010b20014180feff07714108762104024020014101710d00411f210241b4f5c50021030240024002400240024002400240200441ff01710e080006010203040508000b4120210241baf7c50021030c070b4127210241daf6c50021030c060b4117210241c3f6c50021030c050b41a4f6c50021030c040b4126210241fef5c50021030c030b412b210241d3f5c50021030c020b413921024181f7c50021030c010b411f210241daf7c500210302400240200441ff01710e03000102000b41c100210241baf8c50021030c010b41c100210241f9f7c50021030b20002002360204200020033602000b13002000410136020420004188bcc3003602000b3400200041e7bfc30036020420004100360200200041146a4102360200200041106a41f0bfc300360200200041086a42093702000b130020004101360204200041bcc2c3003602000b3101017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242dc0b3700000b130020004104360204200041e0c5c3003602000b3400200041beccc30036020420004100360200200041146a4101360200200041106a41d4ccc300360200200041086a42133702000beb050a067f017e017f017e017f017e017f017e017f017e230041206b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200020044105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c37000020052008370000024020032001490d00200321040c030b2006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d01200020034105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c370000200520083700002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200020044105746a22012900002108200020054105746a220041086a2205290000210a200041106a2204290000210c200041186a2203290000210e20012000290000370000200141186a220629000021102006200e370000200141106a2206290000210e2006200c370000200141086a2201290000210c2001200a370000200320103700002004200e3700002005200c370000200020083700000b200241206a24000f0b4190cec300200520011034000b4180cec300200420011034000be90609067f017e017f017e017f027e017f017e027f230041206b22022400024020014101762203450d0003402003417f6a2203210402400240024003402004410174220541017221060240200541026a220520014f0d00200620014f0d0220052006200020064105746a200020054105746a4120109c054100481b21060b200620014f0d03200420014f0d02200020044105746a2204200020064105746a22054120109c0541004e0d03200541086a22072900002108200541106a2209290000210a200541186a220b290000210c2004290000210d20042005290000370000200441186a220e290000210f200e200c370000200441106a220e290000210c200e200a370000200441086a2204290000210a20042008370000200b200f3700002009200c3700002007200a3700002005200d370000200621040c000b0b41c8cfc300200620011034000b41d8cfc300200420011034000b20030d000b0b0240024020014102490d002001210703402007417f6a220720014f0d02200241186a2209200041186a2204290000370300200241106a220b200041106a2205290000370300200241086a220e200041086a2203290000370300200020074105746a220641086a2900002108200641106a290000210a200641186a290000210c2000290000210d200020062900003700002004200c3700002005200a370000200320083700002002200d37030041002105024002400240034020062002290300370000200641186a2009290300370000200641106a200b290300370000200641086a200e2903003700002005410174220641017221040240200641026a220620074f0d00200420074f0d0220062004200020044105746a200020064105746a4120109c054100481b21040b200420074f0d03200520074f0d02200020054105746a2205200020044105746a22064120109c0541004e0d032009200541186a2203290000370300200b200541106a2210290000370300200e200541086a2211290000370300200641086a2900002108200641106a290000210a200641186a290000210c2005290000210d200520062900003700002003200c3700002010200a370000201120083700002002200d370300200421050c000b0b41c8cfc300200420071034000b41d8cfc300200520071034000b200741014b0d000b0b200241206a24000f0b4190cec300200720011034000b9009030a7f017e0a7f230041c0006b22022400200041807f6a21032001417f6a2104200141324921054101210641002107024003400240024020062001490d00410021080c010b41012108200020064105746a2209200941606a4120109c054100480d0003404101210a20042006460d03200641016a2106200941206a220a20094120109c052108200a21092008417f4a0d000b200620014921080b2006200146210a20050d0120062001460d01024002400240024002402006417f6a220920014f0d002008450d0120002006410574220b6a220a290000210c200a200020094105746a22092900003700002009200c370000200a41086a220d290000210c200d200941086a22082900003700002008200c370000200a41106a220e290000210c200e200941106a220f290000370000200f200c370000200a41186a2210290000210c2010200941186a22112900003700002011200c37000020064102490d04200920002006417e6a22124105746a22134120109c05417f4a0d042009290000210c20092013290000370000200241206a41186a22142011290000370300200241206a41106a2215200f290000370300200241206a41086a221620082900003703002008201341086a290000370000200f201341106a2900003700002011201341186a2900003700002002200c370320024020120d00410021120c040b200241206a20002006417d6a22084105746a4120109c05417f4a0d032003200b6a21090340200941d8006a200941386a290000370000200941d0006a200941306a290000370000200941c8006a200941286a290000370000200941c0006a200941206a2900003700002008450d032008417f6a2108200241206a20094120109c05210f200941606a2109200f4100480d000b200841016a21120c030b4180cec300200920011034000b4190cec300200620011034000b410021120b200020124105746a22092002290320370000200941186a2014290300370000200941106a2015290300370000200941086a20162903003700000b200741016a21070240200120066b220f4102490d00200a41206a2209200a4120109c05417f4a0d00200a290000210c200a2009290000370000200241206a41186a22112010290000370300200241206a41106a2213200e290000370300200241206a41086a2212200d290000370300200d200941086a290000370000200e200941106a2900003700002010200941186a2900003700002002200c3703204101210d0240200f4103490d00200a41c0006a2209200241206a4120109c05417f4a0d00410321084102210e02400340200e410574200a6a41606a220d2009290000370000200d41186a200941186a290000370000200d41106a200941106a290000370000200d41086a200941086a2900003700002008200f4f0d0120084105742109200e210d2008210e200841016a2108200a20096a2209200241206a4120109c054100480d000c020b0b200e210d0b200a200d4105746a22092002290320370000200941186a2011290300370000200941106a2013290300370000200941086a20122903003700000b20074105470d000b4100210a0b200241c0006a2400200a0b8305010f7f230041a0026b22042400200441c0016a41386a2205200041386a2206290000370300200441c0016a41306a2207200041306a2208290000370300200441c0016a41286a2209200041286a220a290000370300200441c0016a41206a220b200041206a220c290000370300200441c0016a41186a220d200041186a220e290000370300200441c0016a41106a220f200041106a2210290000370300200441c0016a41086a2211200041086a2212290000370300200420002900003703c0010240024020012002200441c0016a2003100a0d00410121000c010b20052006290000370300200720082900003703002009200a290000370300200b200c290000370300200d200e290000370300200f20102900003703002011201229000037030020044188026a2205200341086a29000037030020044190026a2206200341106a29000037030020044198026a2207200341186a290000370300200420002900003703c00120042003290000370380022004200441c0016a41e000109a05220041c0016a200041e000109a051a200041e0006a41386a200041386a290000370300200041e0006a41306a200041306a290000370300200041e0006a41286a200041286a290000370300200041e0006a41206a200041206a290000370300200041e0006a41186a200041186a290000370300200041e0006a41106a200041106a290000370300200041e0006a41086a200041086a29000037030020002000290000370360200041a0016a41186a2007290300370300200041a0016a41106a2006290300370300200041a0016a41086a200529030037030020002000290380023703a00120012002200041e0006a200041a0016a10164521000b200441a0026a240020000bc50101037f230041206b220224002002410036021020014110200241106a10062101024002400240024020022802102203417f460d0020010d010b200041003602040c010b200220013602082002200336020c20034104490d0120022003417c6a36020c2002200141046a36020820012800002103200241106a200241086a10820120022802102204450d012000200229021437020820002004360204200020033602002001102a0b200241206a24000f0b41c4d1c3004133200241106a419cd9c3001038000be80201057f230041b0036b22022400200241003602a80220014110200241a8026a1006210302400240024020022802a8022201417f470d00200041133602000c010b20022001360294012002200336029001200241a8026a20024190016a10810120022802a8024113460d01200241a0016a200241a8026a418801109a051a024002402002280294012204450d0020022802900122052d0000210620022004417f6a360294012002200541016a3602900120064103490d010b200241a0016a106a0c020b20022802a00121042002410c6a200241a0016a410472418401109a051a2002200228009901360204200220024199016a41036a28000036000720044113460d0120002004360200200041046a2002410c6a418401109a051a20004188016a20063a000020002002280204360089012000418c016a20022800073600002001450d002003102a0b200241b0036a24000f0b41c4d1c3004133200241a8026a419cd9c3001038000bdb0102027f037e230041206b220224002002410036021020014120200241106a10062101024002400240024020022802102203417f460d0020010d010b200041003602100c010b200220013602082002200336020c20034110490d012002200341706a36020c2002200141106a360208200141086a290000210420012900002105200241106a200241086a106d20022802102203450d0120022902142106200020043703082000200537030020002006370214200020033602102001102a0b200241206a24000f0b41c4d1c3004133200241106a419cd9c3001038000bc40101037f230041206b220224002002410036021020014120200241106a10062101024002400240024020022802102203417f460d0020010d010b200041003602040c010b200220013602082002200336020c20034104490d0120022003417c6a36020c2002200141046a36020820012800002103200241106a200241086a106d20022802102204450d012000200229021437020820002004360204200020033602002001102a0b200241206a24000f0b41c4d1c3004133200241106a419cd9c3001038000bd20101037f230041106b22022400200241003602082002420137030020012d00002103410110282104024002400240024020034101460d002004450d02200242818080801037020420022004360200200441003a0000200141086a200210e3030c010b2004450d02200242818080801037020420022004360200200441013a00002002200236020c200141016a2002410c6a10c8010b2002280204210420004120200228020022012002280208100702402004450d002001102a0b200241106a24000f0b410141011037000b410141011037000ba60a02067f027e230041106b2202240020002802102103200041186a2802002204200110b4010240024002400240024002400240024002400240200141046a2802002205200141086a28020022066b2004490d00200128020021050c010b200620046a22072006490d08200541017422062007200620074b1b22064100480d080240024020050d002006102821050c010b200128020020052006102c21050b2005450d0120012005360200200141046a2006360200200141086a28020021060b200141086a2207200620046a360200200520066a20032004109a051a200028021c210502400240200141046a2802002206200728020022046b4104490d00200128020021060c010b200441046a22032004490d08200641017422042003200420034b1b22044100480d080240024020060d002004102821060c010b200128020020062004102c21060b2006450d0220012006360200200141046a2004360200200141086a28020021040b200141086a2203200441046a360200200620046a20053600002002200136020c2000412c6a2002410c6a10c801200041086a29030021082000290300210902400240200141046a2802002206200328020022046b4110490d00200128020021060c010b200441106a22052004490d08200641017422042005200420054b1b22044100480d080240024020060d002004102821060c010b200128020020062004102c21060b2006450d0320012006360200200141046a2004360200200141086a28020021040b200141086a2205200441106a360200200620046a22042008370008200420093700002000280220210302400240200141046a2802002206200528020022046b4104490d00200128020021060c010b200441046a22052004490d08200641017422042005200420054b1b22044100480d080240024020060d002004102821060c010b200128020020062004102c21060b2006450d0420012006360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200620046a20033600000240024020002802244101460d0002400240200141046a28020020052802002200460d00200128020021040c010b200041016a22042000490d0a200041017422062004200620044b1b22064100480d0a0240024020000d002006102821040c010b200128020020002006102c21040b2004450d0720012004360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200420006a41003a00000c010b02400240200141046a28020020052802002204460d00200128020021060c010b200441016a22062004490d09200441017422052006200520064b1b22054100480d090240024020040d002005102821060c010b200128020020042005102c21060b2006450d0720012006360200200141046a2005360200200141086a28020021040b200141086a2205200441016a360200200620046a41013a00002000280228210602400240200141046a2802002204200528020022006b4104490d00200128020021040c010b200041046a22052000490d09200441017422002005200020054b1b22004100480d090240024020040d002000102821040c010b200128020020042000102c21040b2004450d0820012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a20063600000b200241106a24000f0b200641011037000b200441011037000b200441011037000b200441011037000b200641011037000b200541011037000b200041011037000b1031000b910101047f230041106b2201240041002102200141003602044188e8c2004110200141046a1006210302400240024020012802042204417f470d000c010b024020030d000c010b20044104490d01200328000021042003102a4188e8c20041101009410121020b2000200236020020002004360204200141106a24000f0b41c4d1c3004133200141086a419cd9c3001038000bfb0103017f017e027f230041206b2201240042002102200141106a41086a220342003703002001420037031041affec5004111200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a100621030240024020012802102204417f460d002003450d0020044108490d01200329000021022003102a0b200141106a41086a220342003703002001420037031041affec5004111200141106a1008200141086a2003290300370300200120012903103703002001200220007c37031020014110200141106a41081007200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000b1300200041053602042000418cdac3003602000b3400200041a4d5c30036020420004100360200200041146a4107360200200041106a41e4ecc300360200200041086a42083702000b3701017f02404110102822020d00411041011037000b2002420037000820024201370000200042908080808002370204200020023602000bc70101017f23004190016b22022400200241003a00782002428080848080023703682002420137035820024201370350200242af0137034820024287013703402002420137033820024201370330200242013703282002420137032020024201370318200242013703102002420137030820024280808080c00037036020024280808180800437037020024100360288012002420137038001200241086a20024180016a10ee01200041086a200228028801360200200020022903800137020020024190016a24000b130020004110360204200041c0f6c3003602000b3301017f02404108102822020d00410841011037000b2000428880808080013702042000200236020020024280ade2043700000b3201017f02404104102822020d00410441011037000b20004284808080c000370204200020023602002002418080013600000b3101017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180083600000b3101017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242e8073700000b3c01017f02404110102822020d00411041011037000b2002420037000820024280a094a58d1d370000200042908080808002370204200020023602000b3b01017f02404110102822020d00411041011037000b2002420037000820024280c8afa025370000200042908080808002370204200020023602000b3e01017f02404110102822020d00411041011037000b20024200370008200242808086bdbacdd21a370000200042908080808002370204200020023602000b3f01017f02404110102822020d00411041011037000b200242003700082002428080a8ec85afd1b101370000200042908080808002370204200020023602000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241083600000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241023600000bc81603027f047e117f230041a0096b22072400200741e0006a41186a200141186a290000370300200741e0006a41106a200141106a290000370300200741e0006a41086a200141086a2900003703002007200129000037036020074180016a41186a200241186a29000037030020074180016a41106a200241106a29000037030020074180016a41086a200241086a2900003703002007200229000037038001200628020021012006280204210220062802082108200741d0006a10f6030240024002400240024020072903502209200741d0006a41086a290300220a8450450d004200210b4200210c0c010b200741306a200a420020054200109f05200741c0006a2009420020054200109f05200741206a4200420020094200109f0502402007290338200729032884420052200741c0006a41086a290300220b200729033020072903207c7c220c200b5472450d004127210641a6b5c00021080c020b2007290340210b0b200741c0016a200741e0006a200b200c41081098024101210d20072802c0014101470d0120072802c801210620072802c40121080b2000200836020420004101360200200041146a41003602002000410c6a4201370200200041086a20063602002002450d012001102a0c010b200741c0016a41106a290300210b20072903c801210c200741a0016a41186a220e200a370300200720093703b001200720053703a801200720053703a001200741c0016a10f703200741c0026a4200370300200741f0026a4200370300200741e0026a4200370300200741d0026a42003703002007428080e983b1de163703b80220074280a094a58d1d3703e80220074280a094a58d1d3703d80220074280a094a58d1d3703c802200742808880808080103703f8022007200741c0016a360280032007200741c0016a36028403200741d0056a41186a220f200741e0006a41186a290300370300200741d0056a41106a2206200741e0006a41106a290300370300200741d0056a41086a2210200741e0006a41086a290300370300200720072903603703d00510a00321051098012111200741c0036a4200370300200741b4036a41d0b5c000360200200741b0036a4101360200200741a8036a4200370300200741a4036a41f8b9c000360200200741e0036a2010290300370300200741e8036a2006290300370300200741f0036a200f29030037030020074200370390032007428080808080013703b803200741003602a003200720072903d0053703d803200720074184036a3602d003200720074180036a3602cc032007200741c0016a3602c803200720113602d4032007200537038803200f20074180016a41186a290300370300200620074180016a41106a290300370300201020074180016a41086a29030037030020072007290380013703d005200720083602a804200720023602a404200720013602a004200741f8036a20074188036a200741d0056a20032004200741a0016a200741a0046a10c101024020072802f8030d00200741f8036a41106a2d00000d00200741d0056a41086a200741a8036a290300370300200741a0046a41086a200741dc056a280200360200200720072903a0033703d005200720072902d4053703a00420074198096a200741a0046a1092014100210d0b200720072903b001200e29030020072903a80122054200109f0520072903a00120057d10e503200741106a200741e0006a2007290300200741086a29030010d0012006200b200741106a41086a29030022097d200c2007290310220554ad7d2009200b7d2005200c54ad7d2005200c582009200b582009200b5122021b22011b220a3703002007200c20057d2005200c7d20011b22033703d80520072005200c562009200b5620021b2202ad22053703d00541012101024020020d00200720033703a0042007200a3703a8042007200741a0046a3602e007200741e0076a109d014100210120072903d00521050b0240024020054200520d002001450d01200720103602a004200741a0046a109d010c010b200720103602a004200741a0046a109c010b20072802c403210120072802c0032106200720072802bc032202360298042007200636029404200720023602900420072002200141b0016c6a221236029c0402402001450d00200741e0076a410172211320074187076a2114200741e9076a210820074180076a4102722110200741d0056a41106a2115200741f8056a2116200741b4066a211720074191066a210f200741f1056a210e200741d0056a4101722118200741c8066a2119034020022d00002101200741a0046a200241016a41af01109a051a0240024020014103460d00200720013a00d0052018200741a0046a41af01109a052106024002400240024020010e03000102000b20072802d805211a20072802dc05210620072802d40521012014201541d800109a051a2007410c3a00e007201320074180076a41df00109a051a20012006200741e0076a10cc0141012106410021110240201a450d002001102a0b4100211a0c020b200741e8086a41186a2201200641186a2211290000370300200741e8086a41106a221a200641106a221b290000370300200741e8086a41086a221c200641086a221d290000370300200720062900003703e808200741e0076a2016418801109a051a20102006290000370000201041086a201d290000370000201041106a201b290000370000201041186a201129000037000020074180023b01800720074188096a200741e0076a20074180076a10f40120072d0090092106200820072903e808370000200841086a201c290300370000200841106a201a290300370000200841186a2001290300370000200741043a00e8072007410c3a00e007200720064102463a008908410021064101211141014100200741e0076a10cc014100211a0c010b2019290300210520072903c0062109200741e8086a41186a200641186a290000370300200741e8086a41106a200641106a290000370300200741e8086a41086a200641086a290000370300200720062900003703e80820074180076a41186a200e41186a29000037030020074180076a41106a200e41106a29000037030020074180076a41086a200e41086a2900003703002007200e29000037038007200741e0076a41186a200f41186a290000370300200741e0076a41106a200f41106a290000370300200741e0076a41086a200f41086a2900003703002007200f2900003703e00720074188096a41086a201741086a2802003602002007201729020037038809200741e8086a20074180076a200741e0076a2009200520074188096a10f80341012111410121064101211a0b024020072d00d005220141014b0d000240024020010e020001000b2011450d03024020072802d805450d0020072802d405102a0b20072d00e0054105490d03200728028806450d03200728028406102a0c030b2006450d022016106a0c020b201a20072802b80645720d0120072802b406102a0c010b2007200241b0016a360298040c020b200241b0016a22022012470d000b20072012360298040b20074190046a1069200041106a200741f8036a41106a290300370200200041086a200741f8036a41086a290300370200200020072903f80337020002402007280294032202450d0020074188036a41106a280200450d002002102a0b200d450d0020074188036a411c6a280200210220072802ac0321080240024020072802a80322060d00200221010c010b2006210020022101034020012802880b21012000417f6a22000d000b0340200220022f01064102746a41880b6a28020021022006417f6a22060d000b0b200741d0056a411c6a20022f0106360200200741e8056a4100360200200741e4056a2002360200200720083602f005200741003602e005200742003703d805200720013602d405200741003602d005200741d0056a109b010b200741a0096a24000bc70104017f017e027f017e230041206b2201240042002102200141106a41086a22034200370300200142003703104188d9c3004111200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a1006210302400240024020012802102204417f470d00420121050c010b20044110490d01200341086a2900002102200329000021052003102a0b2000200537030020002002370308200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000be20301047f23004190026b2201240020014190016a41086a22024200370300200142003703900141c0fec500411820014190016a100820014180016a41086a2002290300370300200120012903900137038001200141003602900120014180016a411020014190016a100621030240024002402001280290012204417f470d00410221020c010b2001200436028c02200120033602880220014190016a20014188026a10ea0120012d00800222024102460d01200141106a20014190016a41f000109a051a200120014184026a28000036000b20012001280081023602082004450d002003102a0b20014190016a200141106a41f000109a051a2001200128000b3600830120012001280208360280010240024020024102470d002000428080818080043703682000428080848080023703602000420137035020004201370348200042af0137034020004287013703382000420137033020004201370328200042013703202000420137031820004201370310200042013703082000420137030020004280808080c000370358410021020c010b200020014190016a41f000109a05220441f4006a20012800830136000020042001280280013600710b200020023a007020014190026a24000f0b41c4d1c3004133200141106a419cd9c3001038000b891d01117f230041b0036b2206240020064190026a2000108c01410221070240024020062d00900222084102470d00410121094134210a410221080c010b20064190036a41086a2209200641a4026a29020037030020064190036a41106a220b200641ac026a29020037030020064190036a41186a220c200641b4026a290200370300200641e8026a41086a220d200641c8026a290300370300200641e8026a41106a220e200641d0026a290300370300200641e8026a41186a220f200641d8026a290300370300200641e8026a41206a2210200641e0026a29030037030020062006419c026a290200370390032006200641c0026a2903003703e80220064190026a41086a280200210a024020080d00200641bc026a2802002107200641e8016a41186a200c290300370300200641e8016a41106a200b290300370300200641e8016a41086a2009290300370300200641c0016a41086a200d290300370300200641c0016a41106a200e290300370300200641c0016a41186a200f290300370300200641c0016a41206a201029030037030020062006290390033703e801200620062903e8023703c0010b41022108024020074102470d00410121094134210a0c010b200641e8026a41186a200641e8016a41186a290300370300200641e8026a41106a200641e8016a41106a290300370300200641e8026a41086a200641e8016a41086a29030037030020064190026a41086a200641c0016a41086a29030037030020064190026a41106a200641c0016a41106a29030037030020064190026a41186a200641c0016a41186a29030037030020064190026a41206a200641c0016a41206a290300370300200620062903e8013703e802200620062903c0013703900241002109200721080b200641a0016a41086a2207200641e8026a41086a290300370300200641a0016a41106a220b200641e8026a41106a290300370300200641a0016a41186a220c200641e8026a41186a290300370300200641f8006a41086a220d20064190026a41086a290300370300200641f8006a41106a220e20064190026a41106a290300370300200641f8006a41186a220f20064190026a41186a290300370300200641f8006a41206a221020064190026a41206a290300370300200620062903e8023703a00120062006290390023703780240024020090d00200641d0006a22112006290378370300200641346a20072903003702002006413c6a200b290300370200200641c4006a200c290300370200200641d8006a200d290300370300200641e0006a200e290300370300200641e8006a200f290300370300200641f0006a20102903003703002006200a360228200620062903a00137022c2006200836024c41012109109801210d0240024020084101470d002011280200200d460d010b20064190026a2001108c010240024020062d009002220a4102470d00412e210a419d8fc400210b0c010b200641e8016a41026a20062d0093023a0000200641e8026a41086a2209200641a4026a280200360200200620062f0091023b01e80120062006419c026a2902003703e802200641ac026a2802002108200641a8026a28020021070240200a0d0041012109412e210a419d8fc400210b024020080d000c020b2007102a0c010b20064190026a41086a280200210a200628029402210b200641a0016a41026a200641e8016a41026a2d00003a0000200641c0016a41086a2009280200360200200620062f01e8013b01a001200620062903e8023703c001200641b0026a2d0000210c410021090b2006418c026a41026a200641a0016a41026a2d00003a000020064190036a41086a220e200641c0016a41086a280200360200200620062f01a0013b018c02200620062903c0013703900320090d002006418b016a200e280200360000200620062f018c023b01782006200a36007f2006200b36007b2006200629039003370083012006200c3a00970120062008360093012006200736008f0120062006418e026a2d00003a007a200628024c211220062802502113200620052802002211200541086a28020022144105746a3602940320062011360290032006200641286a3602980320064190026a20064190036a106802400240024002400240024002400240024002402006280290020d0041002109200641003602f001200642043703e801410421074100210a0c010b411010282207450d012007200629039002370200200741086a20064190026a41086a220b290300370200200641c0016a41086a20064190036a41086a28020036020020062006290390033703c001200641e8026a200641c0016a10680240024020062802e8020d00410121094101210a0c010b410121084101210a0340200b200641e8026a41086a290300370300200620062903e8023703900202400240200a2008460d00200841016a21090c010b200841016a22092008490d082008410174220a2009200a20094b1b220a41ffffffff0071200a470d08200a410474220c4100480d080240024020080d00200c102821070c010b20072008410474200c102c21070b2007450d050b200720084104746a2208200629039002370200200841086a200b290300370200200641e8026a200641c0016a10682009210820062802e8020d000b0b200620093602f0012006200a3602ec01200620073602e8010b200641286a41186a28020021082006280238210b2006410036029002200b200820064190026a100d2110200628029002220f417f460d02200641e8026a41186a200241186a290000370300200641e8026a41106a200241106a290000370300200641e8026a41086a200241086a290000370300200620022900003703e802200641003602980320064201370390032010200f20064190036a10b20202400240200628029403220e200628029803220c6b4120490d00200c41206a210b20062802900321080c010b200c41206a220b200c490d05200e4101742208200b2008200b4b1b22154100480d0502400240200e0d002015102821080c010b200628029003200e2015102c21080b2008450d04200620153602940320062008360290032015210e0b2006200b360298032008200c6a220c20062903e802370000200c41086a200641e8026a41086a290300370000200c41106a200641e8026a41106a290300370000200c41186a200641e8026a41186a29030037000020064190026a41186a220c420037030020064190026a41106a2215420037030020064190026a41086a2216420037030020064200370390022008200b20064190026a1000200641c0016a41186a200c290300370300200641c0016a41106a2015290300370300200641c0016a41086a201629030037030020062006290390023703c0010240200e450d002008102a0b0240200f450d002010102a0b0240200641c0016a200641f8006a4120109c050d000240024020090d004100210b0c010b2009410474210c2007410c6a21084100210b03402008280200200b6a210b200841106a2108200c41706a220c0d000b0b20062006280244200b6b360244411710282208450d06200d201320141b210f4101201220141b2110200641286a41106a210b200841002900f1d8433700002008410f6a4100290080d943370000200841086a41002900f9d84337000020064297808080f002370294032006200836029003200020064190036a108f012006280298032115200628029003211620064190026a41186a2208420037030020064190026a41106a220c420037030020064190026a41086a220e420037030020064200370390022016201520064190026a1000200641e8026a41186a2008290300370300200641e8026a41106a200c290300370300200641e8026a41086a200e29030037030020062006290390023703e8020240200628029403450d00200628029003102a0b200641e8026a41201009200c2004370300200641c0026a200f360200200641bc026a2010360200200641b8026a200d360200200641b4026a20062802443602002008200b29030037030020064190026a41206a200b41086a280200360200200641c4026a2002290000370200200641cc026a200241086a290000370200200641d4026a200241106a290000370200200641dc026a200241186a2900003702002006200337039802200641003a009002200120064190026a109a01200641186a2000109101200641186a41086a29030021032006290318210420064190026a200042004200109401024002402006290390024200520d002006200e3602e802200641e8026a109c010c010b2006200e3602e802200641e8026a109d010b200641086a20012004200310d0012006200641106a290300370398022006200629030837039002200620064190026a3602e802200641e8026a109c0102402009450d0020094104742109200741046a210803400240200841046a280200450d002008280200102a0b200841106a2108200941706a22090d000b0b0240200a450d002007102a0b200541046a280200450d0b2011102a0c0b0b200720094104746a2101200721082009450d0620072108034002402008280200220b0d00200841106a21080c080b200841046a2802002109200841086a28020021002008410c6a280200210c200628024021022006280238210d20064190026a41186a220e420037030020064190026a41106a220f420037030020064190026a41086a221042003703002006420037039002200b412020064190026a1000200641e8026a41186a200e290300370300200641e8026a41106a200f290300370300200641e8026a41086a201029030037030020062006290390023703e802200d2002200641e8026a41202009200c100502402000450d002009102a0b200841106a22082001470d000c080b0b411041041037000b200c41041037000b41eef3c50041381050000b201541011037000b1031000b411741011037000b20082001460d0003402008280200450d010240200841086a280200450d00200841046a280200102a0b200841106a22082001470d000b0b200a450d002007102a0b2006413c6a280200450d002006280238102a0b200541046a280200450d002005280200102a0b200641b0036a24000bf46504177f017e077f017e23004180036b2204240041002105200441003602f002200420023602ec02200420013602e8020240024002400240024002400240200241034b0d0041012106200441013a00d002200441ec016a4101360200200442013702dc01200441a4e2c5003602d801200441263602c4022004200441c0026a3602e8012004200441d0026a3602c00220044180016a200441d8016a10332004280280012107200428028401210820042802880121094105210a4100210b0c010b200441043602f002024020012800004180c2cdeb06460d004101210a410121060c010b024002402002417c714104460d00200241074b0d0141082002103c000b41012106200441013a00d002200441ec016a4101360200200442013702dc01200441a4e2c5003602d801200441263602c4022004200441c0026a3602e8012004200441d0026a3602c00220044180016a200441d8016a10332004280280012107200428028401210820042802880121094105210a410021054100210b0c010b200441083602f002410121060240200128000422074101460d004102210a0c010b200441d8016a200441e8026a10fa0402400240024020042802d8014101470d00410421084100210c410021090c010b200441d8016a410572210d41042108412c210a410021054100210c410021094100210b02400340200441d0026a41026a2201200d41026a2d00003a00002004200d2f00003b01d002200428028802210e200428028402210f200428028002211020042802fc01211120042802f801211220042802f401211320042802f001211420042802ec01211520042802e801211620042802e401211720042802e0012118024020042d00dc012206417e6a41ff0171410b4b0d0041002119024002400240024002400240024002400240024002400240024020060e100c0c000102030405060708090a0b0c0c0c0b410121190c0b0b410221190c0a0b410321190c090b410421190c080b410521190c070b410621190c060b410721190c050b410821190c040b410921190c030b410a21190c020b410b21190c010b410c21190b0240200b41ff0171221a20194d0d004113210a0c030b41002119024002400240024002400240024002400240024002400240024020060e100c0c000102030405060708090a0b0c0c0c0b410121190c0b0b410221190c0a0b410321190c090b410421190c080b410521190c070b410621190c060b410721190c050b410821190c040b410921190c030b410a21190c020b410b21190c010b410c21190b0240201a2019470d004114210a0c030b4100210b02400240024002400240024002400240024002400240024020060e100c0c000102030405060708090a0b0c0c0c0b4101210b0c0b0b4102210b0c0a0b4103210b0c090b4104210b0c080b4105210b0c070b4106210b0c060b4107210b0c050b4108210b0c040b4109210b0c030b410a210b0c020b410b210b0c010b410c210b0b20044180016a41026a221920012d00003a0000200420042f01d0023b01800102400240200c2009470d00200c41016a2201200c490d0720052001200520014b1b2209ad42307e221b422088a70d07201ba722014100480d0702400240200c0d002001102821080c010b2008200a41546a2001102c21080b2008450d010b2008200a6a220141546a20063a00002001200e3602002001417c6a200f360200200141786a2010360200200141746a2011360200200141706a20123602002001416c6a2013360200200141686a2014360200200141646a2015360200200141606a20163602002001415c6a2017360200200141586a2018360200200141556a220120042f0180013b0000200141026a20192d00003a0000200541026a2105200a41306a210a200c41016a210c200441d8016a200441e8026a10fa0420042802d8014101460d030c010b0b200141041037000b024002402006410e4b0d00024002400240024002400240024002400240024002400240024020060e0f0001020304050607080e090e0a0b0c000b2017450d0d2018102a0c0d0b02402017450d002018102a0b2014450d0c2015102a0c0c0b02402016450d00201641047421062018210103400240200141046a280200450d002001280200102a0b200141106a2101200641706a22060d000b0b2017450d0b2018102a0c0b0b02402016450d00201641286c21062018210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200641586a22060d000b0b2017450d0a2018102a0c0a0b2017450d092018102a0c090b2017450d082018102a0c080b2017450d072018102a0c070b02402016450d00201820164104746a2114201821160340024020162802082206450d0020162802002101200641047421060340024020012d00004109470d000240200141046a220d280200220528020441ffffffff0371450d002005280200102a200d28020021050b2005102a0b200141106a2101200641706a22060d000b0b201641106a21010240201641046a280200450d002016280200102a0b2001211620012014470d000b0b2017450d062018102a0c060b02402016450d00201641146c21062018210103400240200141046a280200450d002001280200102a0b200141146a21012006416c6a22060d000b0b2017450d052018102a0c050b02402016450d0020182016411c6c6a2114201821160340024020162802042201450d0002402016410c6a2802002206450d00200641047421060340024020012d00004109470d000240200141046a220d280200220528020441ffffffff0371450d002005280200102a200d28020021050b2005102a0b200141106a2101200641706a22060d000b0b201641086a280200450d002016280204102a0b2016411c6a21010240201641146a280200450d002016280210102a0b2001211620012014470d000b0b2017450d042018102a0c040b02402016450d002018201641186c6a21142018211603400240201641046a280200450d002016280200102a0b0240201641146a2802002206450d00201628020c2101200641047421060340024020012d00004109470d000240200141046a220d280200220528020441ffffffff0371450d002005280200102a200d28020021050b2005102a0b200141106a2101200641706a22060d000b0b201641186a21010240201641106a280200450d00201628020c102a0b2001211620012014470d000b0b2017450d032018102a0c030b02402016450d0020182016411c6c6a2114201821160340024020162802042201450d0002402016410c6a2802002206450d00200641047421060340024020012d00004109470d000240200141046a220d280200220528020441ffffffff0371450d002005280200102a200d28020021050b2005102a0b200141106a2101200641706a22060d000b0b201641086a280200450d002016280204102a0b2016411c6a21010240201641146a280200450d002016280210102a0b2001211620012014470d000b0b2017450d022018102a0c020b02402018450d002017450d002018102a0b02402014450d0002402012450d002012410c6c2106201421010340024020012802002205450d00200141046a280200450d002005102a0b2001410c6a2101200641746a22060d000b0b2013450d002014102a0b2010450d010240200e450d002010200e4104746a21172010211803402018220d41106a21180240200d2802042201450d000240200d410c6a2802002206450d002006410c6c21060340024020012802002205450d00200141046a280200450d002005102a0b2001410c6a2101200641746a22060d000b0b200d41086a280200450d00200d280204102a0b20182017470d000b0b200f450d012010102a0c010b02402017450d002018102a0b02402014450d002013450d002014102a0b2010450d002011102a0b0c010b024020042d00dc010d002008200c41306c6a21062008210102400340024020062001470d004100210d0c020b20012d0000210a200141306a220b2101200a410c470d000b200b415c6a280200210d0b2008200c41306c6a210b20082101024003404100210a0240200b2001470d00410021010c020b20012d00002106200141306a2205210120064104470d000b200441f8006a200541546a10fa03200428027c21010b0240200d2001470d004101210741e100210b41f3da012105410021060c030b0240200c450d00200c41306c210a2008210103402001108204200141306a2101200a41506a220a0d000b0b41012106411a210a024020090d000c030b2008102a0c020b20042802dc01220a4110762105200a410876210b200441d8016a41106a280200210d200441e4016a2802002118200441d8016a41086a28020021070b0240200c450d00200c41306c21062008210103402001108204200141306a2101200641506a22060d000b0b4101210602402009450d002008102a0b200d2109201821080b02402006450d00200821060c040b20042802f0022002470d022005411074200b41ff017141087472200a41ff017172211c2008200c41306c6a210a200821010240024002400240024002400240024002400240024002400340200a2001460d0120012d00002102200141306a2206210120024102470d000b200441f0006a200641546a10fa034104211d02402004280274221e0d004100211e0c020b201e41047422014100480d0c2004280270210220011028221d450d0a201e410474210641002115201d21010340200241086a280200220a417f4c0d042002410c6a2d0000210b2002280200210502400240200a0d004101210d0c010b200a1028220d450d060b200d2005200a109a0521052001410d6a2002410d6a2d00003a00002001410c6a200b3a0000200141086a200a360200200141046a200a36020020012005360200200141106a2101201541016a2115200241106a2102200641706a22060d000b201d0d020b4100211e4104211d0b410021150b2008200c41306c6a210a2008210102400340410021174104210b0240200a2001470d0041042102410021010c020b20012d00002102200141306a2206210120024103470d000b200441e8006a200641546a10fa0341042102410021012004280268220a450d00200428026c2101200a21020b024020010d004101211a41002102410021184100210541002110410121124100210a4100211141042116410021064100211f410421134100210e0c090b200141286c210d2002411c6a21014104210b410021174101211a41002102410021184100210541002110410121124100210a4100211141042116410021064100211f410421134100210e0340024002400240024002402001417c6a2d00000e0400010203000b20012802002114024020022018470d00200241016a22182002490d0f2002410174220f2018200f20184b1b221841ffffffff03712018470d0f2018410274220f4100480d0f0240024020020d00200f1028210b0c010b200b2002410274200f102c210b0b200b450d080b200b20024102746a2014360200200241016a21020c030b200441d8016a41086a2214200141086a280200360200200420012902003703d8010240200a2011470d00200a41016a2211200a490d0e200a410174220f2011200f20114b1b2211ad420c7e221b422088a70d0e201ba7220f4100480d0e02400240200a0d00200f102821160c010b2016200a410c6c200f102c21160b2016450d080b2016200a410c6c6a220f20042903d801370200200f41086a2014280200360200200a41016a210a0c020b200441d8016a41086a2214200141086a280200360200200420012902003703d80102402006201f470d00200641016a220f2006490d0d20064101742219200f2019200f4b1b221fad420c7e221b422088a70d0d201ba7220f4100480d0d0240024020060d00200f102821130c010b20132006410c6c200f102c21130b2013450d080b20132006410c6c6a220f20042903d801370200200f41086a2014280200360200200641016a21060c010b2001417e6a22142d0000210f2001417d6a22192d00002120024020052010470d00200541016a22102005490d0c200541017422212010202120104b1b221020106a22222010490d0c20224100480d0c0240024020050d002022102821120c010b201220212022102c21120b2012450d080b201220054101746a2222200f4101713a0001202220203a000020142d0000211420192d0000210f02400240200e2017460d00200e21190c010b201741016a22192017490d0c201741017422222019202220194b1b222020206a22192020490d0c20194100480d0c0240024020170d0020191028211a0c010b201a20222019102c211a0b201a450d0920172119202021170b200541016a2105201a20194101746a221920144101713a00012019200f3a0000200e41016a210e0b200141286a2101200d41586a220d450d090c000b0b1036000b200a41011037000b200f41041037000b200f41041037000b200f41041037000b202241011037000b201941011037000b200141041037000b2008200c41306c6a21142008210102400240024002400240024002400240024002400240024002400240034020142001460d0120012d0000210d200141306a220f2101200d4104470d000b200441e0006a200f41546a10fa0320042802642201450d002004280260210d2001410274210f20024101742114200241027421010340200d2802002119024020022018470d00200241016a22182002490d1020142018201420184b1b221841ffffffff03712018470d10201841027422204100480d100240024020020d0020201028210b0c010b200b20012020102c210b0b200b450d030b200d41046a210d200b20016a2019360200201441026a2114200141046a2101200241016a2102200f417c6a220f0d000b0b2008200c41306c6a21142008210102400240034020142001460d0120012d0000210d200141306a220f2101200d4105470d000b200441d8006a200f41546a10fa03200428025c410c6c2219450d0020042802582101200a4101742114200a410c6c210d0340200141086a210f024002400240200141046a2802004101470d002004200f28020022203602c0022001280200222220204b0d010b20044100360280010c010b200441023602ec01200442023702dc01200441e8a7c6003602d801200441013602f402200441013602ec02200420223602d0022004200441e8026a3602e8012004200441d0026a3602f0022004200441c0026a3602e80220044180016a200441d8016a1033200428028001450d0020044180016a21010c0e0b2001290200211b200441d8016a41086a2220200f2802003602002004201b3703d8010240200a2011470d00200a41016a2211200a490d1120142011201420114b1b2211ad420c7e221b422088a70d11201ba7220f4100480d1102400240200a0d00200f102821160c010b2016200d200f102c21160b2016450d030b2001410c6a21012016200d6a220f20042903d801370200200f41086a2020280200360200201441026a2114200d410c6a210d200a41016a210a201941746a22190d000b0b2008200c41306c6a21142008210102400240034020142001460d0120012d0000210d200141306a220f2101200d4106470d000b200441d0006a200f41546a10fa032004280254220d450d0020042802502101200d410c6c210f200641017421142006410c6c210d0340200441d8016a2001108305024020042802d801450d00200441d8016a21010c0f0b2001290200211b200441d8016a41086a2219200141086a2802003602002004201b3703d80102402006201f470d00200641016a221f2006490d122014201f2014201f4b1b221fad420c7e221b422088a70d12201ba722204100480d120240024020060d002020102821130c010b2013200d2020102c21130b2013450d030b2001410c6a21012013200d6a222020042903d801370200202041086a2019280200360200201441026a2114200d410c6a210d200641016a2106200f41746a220f0d000b0b2008200c41306c6a21142008210102400240034020142001460d0120012d0000210d200141306a220f2101200d4107470d000b200441c8006a200f41546a10fa03200428024c220d450d0020042802482201200d4104746a21222005410174210d200441d8016a41047221200340200441d8016a2001201a200e10840502400240024020042d00d8014101460d00200420042d00d90122143a00c002024020142001410c6a2d0000220f470d0020044100360280010c030b200441023602ec01200442023702dc01200441fca8c6003602d801200441273602f402200441273602ec022004200f3a00d0022004200441e8026a3602e8012004200441c0026a3602f0022004200441d0026a3602e80220044180016a200441d8016a10330c010b20044180016a41086a202041086a28020036020020042020290200370380010b0240200428028001450d0020044180016a21010c110b2001410c6a2d000021140b2001410d6a2d0000210f024020052010470d00200541016a22102005490d13200d2010200d20104b1b221020106a22192010490d1320194100480d130240024020050d002019102821120c010b2012200d2019102c21120b2012450d030b2012200d6a221920143a0000201941016a200f4101713a0000200d41026a210d200541016a2105200141106a22012022470d000b0b200441b8016a2002360200200441b4016a2018360200200441ac016a2015360200200441a8016a201e360200200441a0016a20053602002004419c016a201036020020044194016a200a36020020044190016a20113602002004200b3602b0012004201d3602a40120042012360298012004201636028c0120042006360288012004201f3602840120042013360280012008200c41306c6a210a20082101024003400240200a2001470d004100210b0c020b20012d00002102200141306a2206210120024104470d000b200441c0006a200641546a10fa032004280244210b0b2004200b3602bc012008200c41306c6a210a20082101024003400240200a2001470d00410021010c020b20012d00002102200141306a220621012002410c470d000b2006415c6a28020021010b200420013602c001200b2001470d0a024002400240200b450d002008200c41306c6a210a200821010340200a2001460d0320012d00002102200141306a2206210120024104470d000b2008200c41306c6a210b200821010340200b2001460d0220012d00002102200141306a220a21012002410c470d000b200441386a200641546a10fa03200428023c2201450d002004280238220d20014102746a2114200a415c6a2118200a41546a211620044191026a210f410021050340200420053602c4012018280200210120162802002102200442013702dc012004418487c6003602d801200441013602d402200441013602ec012004200441d0026a3602e8012004200441c4016a3602d002200441e8026a200441d8016a103320042802e802210a20042902ec02211b200120054d0d100240201ba7450d00200a102a0b2004200d28020022013602c002024002400240024020042802ac0120014b0d00200441013602ec01200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a103320042902ec02221b422088a7210120042802e8022106201ba721020c010b0240024002402002200541186c6a22022802142215450d0020042802a40120014104746a220a2d000d2110200a2802002111200228020c210120022802002113200a2802082212210602402002280208220e450d00200e410374210b201221022013210a034002402002200a2802006a220620024f0d0002404120102822060d00412041011037000b200641186a41002900e8ae46370000200641106a41002900e0ae46370000200641086a41002900d8ae46370000200641002900d0ae463700000c040b200a41086a210a20062102200b41786a220b0d000b0b0240410810282202450d0020022010ad42ff0183422886370200200441d0026a41026a220a200441e8026a41026a2d00003a0000200420042f00e8023b01d002200420103a00900220044180800136028c022004428180808010370284022004200236028002200442808080808080103703f801200442013703f001200420063602ec012004200e3602e801200420133602e401200420123602e001200420113602dc01200420044180016a3602d801200f20042f01d0023b0000200f41026a200a2d00003a00002015410474210a41002102034020042002360298022004200136029c02200441b0026a200441d8016a2001108505024020042802b002450d00200441c0026a41086a200441b0026a41086a280200360200200420042903b0023703c002200441033602e402200442033702d402200441e881c6003602d002200441283602fc02200441013602f402200441293602ec022004200441e8026a3602e0022004200441c0026a3602f802200420044198026a3602f00220042004419c026a3602e802200441a0026a200441d0026a1033024020042802c402450d0020042802c002102a0b20042802a0022206450d0020042902a402211b024020042802f401450d0020042802f001102a0b201b42208821230240200428028402450d00200428028002102a0b2023a72101201ba721020c070b200141106a2101200241016a2102200a41706a220a0d000b02402004280288020d00024020042802f401450d0020042802f001102a0b200428028402450d07200428028002102a0c070b418082c6001032000b410841041037000b412010282206450d01200641186a41002900df8146370000200641106a41002900d78146370000200641086a41002900cf8146370000200641002900c781463700000b41202102412021010c010b412041011037000b2006450d010b200420063602d00220042001ad4220862002ad843702d4022004200441d0026a3602c002200441023602ec01200442023702dc012004418c87c6003602d8012004412a3602f402200441013602ec022004200441e8026a3602e8012004200441c0026a3602f0022004200441c4016a3602e802200441c8016a200441d8016a1033024020042802d402450d0020042802d002102a0b20042802c801220a450d0020042902cc01211b0c110b200541016a2105200d41046a220d2014470d000b0b2008200c41306c6a210a200821010240024002400340200a2001460d0120012d00002102200141306a2206210120024109470d000b2004200641546a28020022013602b002024020042802b80120014b0d00200441ec016a4101360200200442023702dc01200441e4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c0c0b200420042802b00120014102746a28020022013602c002024020042802ac0120014b0d00200441ec016a4101360200200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c0c0b20042802a40120014104746a220131000d4220862001350208844280808080c000510d00412d1028220a450d01200a41256a41002900c18746370000200a41206a41002900bc8746370000200a41186a41002900b48746370000200a41106a41002900ac8746370000200a41086a41002900a48746370000200a410029009c874637000042ad808080d005211b0c110b2008200c41306c6a210a200821010340200a2001460d0a20012d00002102200141306a2206210120024108470d000b200441306a200641546a221610fa03200428023021014100210a02400240200428023422020d004104210b410021180c010b200241ffffffff01712002470d15200241037422064100480d1520061028220b450d02200221180b02402002450d002001200241146c6a21062002410274417c6a2105200b210203402001280200210a200241046a200141086a2802003602002002200a360200200241086a2102200141146a22012006470d000b200541027641016a210a0b200b200a200441d8016a41004120200a676b10fd04200b200a4103746a2206200b460d084101210a200b2101200b2102034002400240200a450d00200620016b410376200a4d0d0b2001200a4103746a22010d010c0b0b20062001460d0a0b200420023602c00202400240200241046a280200220a200141046a280200470d00200228020022052001280200220d460d012005200d200a109c05450d010b200141086a21014100210a200241086a22022006470d010c0a0b0b200441ec016a4101360200200442013702dc01200441cc87c6003602d8012004412b3602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c0c0b412d41011037000b200641041037000b41ba86c60041c8001050000b419c86c600411e1050000b201941011037000b202041041037000b200f41041037000b202041041037000b200441286a201610fa030240200428022c2201450d00200141146c2102200428022841106a210102400340024002400240024002402001417c6a2802000e0400030201000b20042001280200220a3602b002024020042802b801200a4b0d00200441ec016a4101360200200442023702dc01200441e4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c0b0b200420042802b001200a4102746a280200220a3602c00220042802ac01200a4b0d03200441013602ec01200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c0a0b20042001280200220a3602b002024020042802a001200a4b0d00200441ec016a4101360200200442023702dc01200441a8acc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c0a0b200428029801200a4101746a2d0001450d02200441ec016a4101360200200442023702dc01200441c8acc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c090b20042001280200220a3602c002200428028801200a4b0d01200441013602ec01200442023702dc0120044194abc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a103320042802e802220a0d090c010b20042001280200220a3602c002200428029401200a4d0d020b200141146a21012002416c6a22020d000c020b0b200441ec016a4101360200200442023702dc01200441c4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c040b2018450d00200b102a0b2008200c41306c6a210a2008210102400340200a2001460d0120012d00002102200141306a2206210120024103470d000b200441206a200641546a10fa0320042802242201450d0020042802202106200141286c210b41002101034002400240024002400240200620016a220241186a2d00000e0400030201000b20042002411c6a28020022023602c00220042802ac0120024b0d03200441ec016a4101360200200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c060b2002411a6a2d0000450d022002410c6a2802002101200241146a2802002102200441d8016a41146a4101360200200420023602d402200420013602d002200441043602c402200442013702dc01200441d487c6003602d8012004200441d0026a3602c0022004200441c0026a3602e801200441e8026a200441d8016a10330c050b200441d8016a2002411c6a10830520042802d801220a450d0120042902dc01211b0c0a0b200241206a2802004101470d002002411c6a280200210a2004200241246a28020022023602b002200a20024d0d00200441023602ec01200442023702dc01200441e8a7c6003602d801200441013602f402200441013602ec022004200a3602c0022004200441e8026a3602e8012004200441c0026a3602f0022004200441b0026a3602e802200441d0026a200441d8016a103320042802d002220a0d080b200b200141286a2201470d000b0b02400240024002400240200428029401220141014b0d00200428028801220141014b0d012008200c41306c6a210a200821010240024002400240024002400340200a2001460d0120012d00002102200141306a220621012002410d470d000b200441186a200641546a10fa0320042802182201200428021c411c6c6a2106034020012006460d012004200128020022023602c002024020042802880120024b0d00200441013602ec01200442023702dc0120044194abc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a103320042802e802220a450d0020042902ec02211b0c130b200141046a2201280200450d02200441d8016a200120042802980120042802a00110840520042d00d8014101460d03200141186a210120042d00d901450d000b41201028220a450d08200a41186a41002900848846370000200a41106a41002900fc8746370000200a41086a41002900f48746370000200a41002900ec874637000042a08080808004211b0c110b2008200c41306c6a210a2008210102400340200a2001460d0120012d00002102200141306a220621012002410a470d000b200441106a200641546a10fa0320042802142201450d002004280210220b2001411c6c6a21050340200b450d012004200b28020022013602c00220042802940120014d0d04200b280204450d05200441d8016a200b41046a20042802980120042802a00110840520042d00d8014101460d0620042d00d9010d0d200441086a200b10cd0402400240200428020c2201450d00200428020821022001410274210a20042802b801210603402004200228020022013602b0020240200620014b0d00200441ec016a4101360200200442023702dc01200441e4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c100b200420042802b00120014102746a28020022013602c00220042802ac0120014d0d02200241046a2102200a417c6a220a0d000b0b200b411c6a220b2005460d020c010b0b200441013602ec01200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c0b0b0240200428028401450d00200428028001102a0b0240200428029001450d00200428028c01102a0b0240200428029c01450d00200428029801102a0b024020042802ac012202450d0020042802a40121012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b024020042802a801450d0020042802a401102a0b024020042802b401450d0020042802b001102a0b2017450d13201a102a0c130b41291028220a450d07200a41286a41002d00b488463a0000200a41206a41002900ac8846370000200a41186a41002900a48846370000200a41106a410029009c8846370000200a41086a41002900948846370000200a410029008c884637000042a98080809005211b0c0f0b200441e0016a290300211b20042802dc01210a0c0e0b200441ec016a4101360200200442023702dc01200441c4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c070b412a1028220a450d05200a41286a41002f00dd88463b0000200a41206a41002900d58846370000200a41186a41002900cd8846370000200a41106a41002900c58846370000200a41086a41002900bd8846370000200a41002900b5884637000042aa808080a005211b0c0c0b200441e0016a290300211b20042802dc01210a0c0b0b200441ec016a4101360200200442013702dc01200441dc87c6003602d801200441013602d402200420013602c0022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c040b200441ec016a4101360200200442013702dc01200441e487c6003602d801200441013602d402200420013602c0022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c030b412041011037000b412941011037000b412a41011037000b20042802e802210a20042902ec02211b0c050b024041201028220a450d00200a41186a41002900848846370000200a41106a41002900fc8746370000200a41086a41002900f48746370000200a41002900ec874637000042a08080808004211b0c050b412041011037000b20042802e802210a0b20042902ec02211b2018450d02200b102a0c020b200441ec016a4102360200200441f4026a4101360200200442023702dc012004418c86c6003602d801200441013602ec022004200441e8026a3602e8012004200441c0016a3602f0022004200441bc016a3602e802200441d0026a200441d8016a103320042802d002210a0b20042902d402211b0b0240200428028401450d00200428028001102a0b0240200428029001450d00200428028c01102a0b0240200428029c01450d00200428029801102a0b024020042802ac012202450d0020042802a40121012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b024020042802a801450d0020042802a401102a0b024020042802b401450d0020042802b001102a0b2017450d01201a102a200a0d040c020b2001290204211b2001280200210a02402017450d00201a102a0b0240201f450d002013102a0b02402011450d002016102a0b02402010450d002012102a0b02402015450d0020154104742102201d210103400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b0240201e450d00201d102a0b2018450d00200b102a0b200a0d020b2000201c36020420004100360200200041186a2003360200200041146a200c360200200041106a20093602002000410c6a2008360200200041086a20073602000c040b1031000b0240201ba7450d00200a102a0b200041ea8ac60036020420004101360200200041086a41133602000240200c450d00200c41306c21022008210103402001108204200141306a2101200241506a22020d000b0b2009450d022008102a0c020b200441003a00d002200441ec016a4101360200200442013702dc01200441a4e2c5003602d801200441263602c4022004200441c0026a3602e8012004200441d0026a3602c00220044180016a200441d8016a1033200428028001210720042802840121060240200c450d00200c41306c21022008210103402001108204200141306a2101200241506a22020d000b0b4105210a2009450d002008102a0b02402006450d00200a41ff01714105470d002007102a0b200041d48ac60036020420004101360200200041086a41163602000b20044180036a24000b160020002001280208360204200020012802003602000bd21301177f23004190026b220224000240024002400240024002402000280200220341f8b9c000460d00200028020421040c010b41002104200241b8016a410041d8001099051a2002411f6a220542003700002002420037011a41ec0010282203450d0120034100360200200320022902183702042003410b6a2005290000370000200341136a200241b7016a41d900109a051a20004100360204200020033602000b200141ff0171210602400340200341066a210720032f01062108410c21094100210502400240034020082005460d01200320056a210a200941086a2109200541016a210502404100417f4101200a41086a2d0000220a20064b1b200a2006461b41016a0e03000301000b0b2005417f6a21080b2004450d022004417f6a2104200320084102746a41ec006a28020021030c010b0b200320096a42013702000c030b2000200028020841016a360208024002400240024020072f01002205410b490d00200241276a41016a410041d8001099051a200241003a001941ec001028220b450d03200b4100360200200b410036000f200b4200370007200b20022f01183b0005200b41136a200241276a41d900109a051a2003410e6a2d0000210c2003280248210d2003280244210e200b41086a2003410f6a20032f010641796a2205109a052109200b41146a200341cc006a2005410374109a052106200341063b0106200b20053b010620084107490d0120092008417a6a220a6a2009200841796a22086a2209200541ffff037120086b109b051a200920013a00002006200a4103746a200620084103746a2205200b41066a22072f010020086b410374109b051a2005410136020020072f010021050c020b200341086a2209200841016a22066a200920086a2209200520086b220a109b051a200920013a0000200341146a220920064103746a200920084103746a2209200a410374109b051a200941013602002003200541016a3b01060c050b200341086a2205200841016a22096a200520086a220620072f0100220520086b220a109b051a200620013a0000200341146a220620094103746a200620084103746a2209200a410374109b051a200941013602000b2007200541016a3b01002003280200220a450d02200341046a2105200241276a41016a210f200241a8016a2101200241a0016a211020024198016a211120024190016a211220024180016a41086a2113034020052f0100210602400240024002400240200a2f01062205410b490d00200f410041d8001099051a200241003a0019200220022f01183b0108200241b7016a200241276a41d900109a051a20014200370300201042003703002011420037030020124200370300201342003703002002420037038001419c0110282209450d03200941003602002009410036000f20094200370007200920022f01083b0005200941136a200241b7016a41d900109a051a20094194016a20012903003702002009418c016a201029030037020020094184016a2011290300370200200941fc006a2012290300370200200941f4006a2013290300370200200920022903800137026c200a41c8006a2802002114200a41c4006a2802002115200a410e6a2d00002116200941086a200a410f6a200a2f0106220341796a2205109a052117200941146a200a41cc006a2005410374109a052118200941ec006a200a4188016a2003417a6a2204410274109a052107200a41063b0106200920053b010602402004450d00410021052007210303402003280200220820053b010420082009360200200341046a21032004200541016a2205470d000b0b20064107490d0120172006417a6a22036a2017200641796a22056a220820092f010620056b109b051a2008200c3a0000201820034103746a201820054103746a220820092f010620056b410374109b051a2008200e3602002008200d360204200920092f010641016a22083b01062006410274220c20076a416c6a200720034102746a2204200841ffff0371220620036b410274109b051a2004200b36020020062003490d022009200c6a41d4006a2103034020032802002208200541016a22053b010420082009360200200341046a210320052006490d000c030b0b200a41086a2209200641016a22036a200920066a2209200520066b2208109b051a2009200c3a0000200a41146a220920034103746a200920064103746a22092008410374109b051a2009200e3602002009200d360204200a200541016a22053b01062006410274200a41ec006a22096a41086a200920034102746a2209200541ffff0371220820036b410274109b051a2009200b360200200620084f0d08200a2003417f6a22054102746a41f0006a2103034020032802002209200541016a22053b01042009200a360200200341046a210320052008490d000c090b0b200a41086a2203200641016a22056a200320066a2203200a2f0106220820066b2204109b051a2003200c3a0000200a41146a220320054103746a200320064103746a22032004410374109b051a2003200e3602002003200d360204200a200841016a22033b010620064102742207200a41ec006a22086a41086a200820054102746a2204200341ffff0371220820056b410274109b051a2004200b360200200620084f0d00200a20076a41f0006a2105034020052802002203200641016a22063b01042003200a360200200541046a210520082006470d000b0b200a28020022030d012009210b2014210d2015210e2016210c0c050b419c0141041037000b200a41046a21052003210a2016210c2015210e2014210d2009210b0c000b0b41ec0041041037000b41ec0041041037000b200241b7016a41016a410041d8001099051a2002411f6a220542003700002002420037011a200220022902183703082002200529000037000f200241276a200241b7016a41d900109a051a200241a8016a22034200370300200241a0016a2209420037030020024180016a41186a2208420037030020024190016a2206420037030020024180016a41086a220a42003703002002420037038001419c0110282205450d0120054100360200200520022903083702042005410b6a200229000f370000200541136a200241276a41d900109a051a20054194016a20032903003702002005418c016a200929030037020020054184016a2008290300370200200541fc006a2006290300370200200541f4006a200a290300370200200520022903800137026c20052000280200220336026c200020053602002000200028020441016a360204200341003b010420032005360200200520052f010622034103746a220941186a200d360200200941146a200e360200200520036a41086a200c3a0000200541ec006a200341016a22034102746a200b360200200520033b0106200b20033b0104200b20053602000b20024190026a24000f0b419c0141041037000b822701377f2001410c6a28020021022001280208210341002104024002400240200141106a28020022050d00410021064100210741002108410021094100210a4100210b4100210c4100210d4100210e410021050c010b410021044100210e4100210d4100210c4100210b4100210a4100210941002108410021074100210f4100211002400340200121112010210620032005417f6a220541306c6a220128002c2112200128002821132001280024211420012800202115200128001c2116200128001821172001280014211820012800102119200128000c211a2001280008211b2001280004211c41012110024002400240024002400240024020012d0000221d417e6a221e410e4d0d004101211f0c010b4101211f4101212041012121410121224101212341012124201c21010240024002400240024002400240024002400240024002400240024002400240024002400240201e0e0f00010203040506180717080917171a000b0240200f0d002006211020112101201c210f201b2125201a21260c180b02402026450d0020264104742110200f210103400240200141046a280200450d002001280200102a0b200141106a2101201041706a22100d000b0b4101211f410021102025450d11200f102a0c110b024020070d002006211020112101201c2107201b2127201a21280c170b02402028450d00202841286c21102007210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101201041586a22100d000b0b4100211f410121102027450d0f2007102a0c0f0b2029450d0d2008450d0d2008102a0c0d0b202a450d0b2009450d0b2009102a0c0b0b202b450d09200a450d09200a102a0c090b0240200b0d002006211020112101201c210b201b212c201a212d0c130b0240202d450d00200b202d4104746a2121200b21200340024020202802082210450d0020202802002101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041106a21010240202041046a280200450d002020280200102a0b2001212020012021470d000b0b4100212041012110202c450d07200b102a0c070b0240200c0d002006211020112101201c210c201b212e201a212f0c120b0240202f450d00202f41146c2110200c210103400240200141046a280200450d002001280200102a0b200141146a21012010416c6a22100d000b0b4100212141012110202e450d05200c102a0c050b0240200d0d002006211020112101201c210d201b2130201a21310c110b02402031450d00200d2031411c6c6a2121200d21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b2001212020012021470d000b0b41002122410121102030450d03200d102a0c030b0240200e0d002006211020112101201c210e201b2132201a21330c100b02402033450d00200e203341186c6a2121200e212003400240202041046a280200450d002020280200102a0b0240202041146a2802002210450d00202028020c2101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041186a21010240202041106a280200450d00202028020c102a0b2001212020012021470d000b0b41002123410121102032450d01200e102a0c010b024020040d002006211020112101201a2134201b2135201c21040c0f0b02402034450d0020042034411c6c6a2121200421200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b2001212020012021470d000b0b410021244101211002402035450d002004102a0b201c2104201b2135201a21344101211f410121204101212141012122410121230c0d0b201a2133201b2132201c210e4101211f4101212041012121410121220c0b0b201a2131201b2130201c210d4101211f4101212041012121410121230c0a0b201a212f201b212e201c210c4101211f410121200c080b201a212d201b212c201c210b4101211f0c060b2006211020112101201c210a201b212b201a21360c090b2006211020112101201c2109201b212a201a21370c080b2006211020112101201c2108201b2129201a21380c070b201a2128201b2127201c21070c010b201a2126201b2125201c210f0b410121200b410121210b41012122410121230b410121240b024002400240201e410b4b0d000240024002400240024002400240024002400240201e0e0c000102030405060a070a0809000b2010450d0b0240201a450d00201a4104742110201c210103400240200141046a280200450d002001280200102a0b200141106a2101201041706a22100d000b0b201b450d0b0c0a0b201f450d0a0240201a450d00201a41286c2110201c210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101201041586a22100d000b0b201b0d090c0a0b41000d09201b0d080c090b41000d08201b0d070c080b41000d07201b0d060c070b2020450d060240201a450d00201c201a4104746a211e201c21200340024020202802082210450d0020202802002101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041106a21010240202041046a280200450d002020280200102a0b200121202001201e470d000b0b201b0d050c060b2021450d050240201a450d00201a41146c2110201c210103400240200141046a280200450d002001280200102a0b200141146a21012010416c6a22100d000b0b201b0d040c050b2022450d040240201a450d00201c201a411c6c6a211e201c21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b200121202001201e470d000b0b201b0d030c040b2023450d030240201a450d00201c201a41186c6a211e201c212003400240202041046a280200450d002020280200102a0b0240202041146a2802002210450d00202028020c2101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041186a21010240202041106a280200450d00202028020c102a0b200121202001201e470d000b0b201b0d020c030b2024450d020240201a450d00201c201a411c6c6a211e201c21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b200121202001201e470d000b0b201b0d010c020b0240201d410e4b0d00200621102011210102400240024002400240024002400240024002400240201d0e0f0001020304040405060e070e08090a000b201b0d0b0c0c0b0240201b450d00201c102a0b2018450d0b2019102a0c0b0b0240201a450d00201a4104742110201c210103400240200141046a280200450d002001280200102a0b200141106a2101201041706a22100d000b0b201b0d090c0a0b201a450d00201a41286c2110201c210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101201041586a22100d000b0b201b0d070c080b0240201a450d00201c201a4104746a211e201c21200340024020202802082210450d0020202802002101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041106a21010240202041046a280200450d002020280200102a0b200121202001201e470d000b0b201b0d060c070b0240201a450d00201a41146c2110201c210103400240200141046a280200450d002001280200102a0b200141146a21012010416c6a22100d000b0b201b0d050c060b0240201a450d00201c201a411c6c6a211e201c21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b200121202001201e470d000b0b201b0d040c050b0240201a450d00201c201a41186c6a211e201c212003400240202041046a280200450d002020280200102a0b0240202041146a2802002210450d00202028020c2101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041186a21010240202041106a280200450d00202028020c102a0b200121202001201e470d000b0b201b0d030c040b0240201a450d00201c201a411c6c6a211e201c21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b200121202001201e470d000b0b201b0d020c030b0240201c450d00201b450d00201c102a0b02402018450d0002402016450d002016410c6c2110201821010340024020012802002224450d00200141046a280200450d002024102a0b2001410c6a2101201041746a22100d000b0b2017450d002018102a0b2014450d0202402012450d00201420124104746a211c2014212003402020221f41106a21200240201f2802042201450d000240201f410c6a2802002210450d002010410c6c21100340024020012802002224450d00200141046a280200450d002024102a0b2001410c6a2101201041746a22100d000b0b201f41086a280200450d00201f280204102a0b2020201c470d000b0b2013450d022014102a0c020b0240201b450d00201c102a0b02402018450d002017450d002018102a0b2014450d012015102a0c010b201c102a0b20062110201121010b20050d000b4100210520012111201021060b200f0d010b4104210f41002125410021260b20002003360280012000200636025420002026360208200020253602042000200f36020020004188016a200536020020004184016a2002360200200041fc006a2034410020041b360200200041f8006a2035410020041b36020020002004410420041b360274200041f0006a20334100200e1b360200200041ec006a20324100200e1b3602002000200e4104200e1b360268200041e4006a20314100200d1b360200200041e0006a20304100200d1b3602002000200d4104200d1b36025c200041d8006a2011360200200041d0006a202f4100200c1b360200200041cc006a202e4100200c1b3602002000200c4104200c1b360248200041c4006a202d4100200b1b360200200041c0006a202c4100200b1b3602002000200b4104200b1b36023c200041386a20364100200a1b360200200041346a202b4100200a1b3602002000200a4104200a1b3602302000412c6a2037410020091b360200200041286a202a410020091b36020020002009410420091b360224200041206a2038410020081b3602002000411c6a2029410020081b36020020002008410420081b360218200041146a2028410020071b360200200041106a2027410020071b36020020002007410420071b36020c0bb10a010e7f230041106b2202240002400240024002400240024020012802004101470d00200141106a2d000021032001410c6a2802002104200141086a280200210520012f0112210620012d0011210720012802042108200241086a200010fa0320022802082201200228020c22094104746a210a4100210b20094104490d01200341ff0171210c02400340024020012d000c200c470d0020012802082004470d000240200128020022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b200741ff0171220941044720012d000d220e410446220d460d00200e2009460d0520094104460d05200d0d050b02400240024002402001411c6a2d0000200c470d00200141186a2802002004470d000240200128021022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b200741ff0171220941044720012d001d220e410446220d460d00200e2009460d0120094104460d01200d0d010b2001412c6a2d0000200c470d02200141286a2802002004470d02200128022022092008460d012004450d012004210d2008210e034020092d0000200e2d0000470d03200941016a2109200e41016a210e200d417f6a220d450d020c000b0b200b410172210b0c060b200741ff0171220941044720012d002d220e410446220d460d00200e2009460d0220094104460d02200d0d020b024002402001413c6a2d0000200c470d00200141386a2802002004470d000240200128023022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b200741ff0171220941044720012d003d220e410446220d460d00200e2009460d0120094104460d01200d0d010b200b41046a210b200a200141c0006a22016b41304d0d040c010b0b200b410372210b0c030b200b410272210b0c020b2001280204210b0c030b2001200a460d0102400240200741ff0171220f4104460d00200341ff0171210c0c010b200341ff0171210c0340024020012d000c200c470d0020012802082004470d000240200128020022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b20012d000d4104460d030b200b41016a210b200141106a2201200a470d000c030b0b0340024020012d000c200c470d0020012802082004470d000240200128020022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b20012d000d2209200f470d0020094104470d020b200b41016a210b200141106a2201200a460d020c000b0b2005450d012008102a0c010b024020002802082201200041046a280200470d0002400240200141016a22092001490d002001410174220e2009200e20094b1b220941ffffffff00712009470d002009410474220e41004e0d010b1031000b0240024020010d00200e102821010c010b20002802002001410474200e102c21010b2001450d0220002001360200200041046a2009360200200028020821010b200028020020014104746a220120063b010e200120073a000d200120033a000c2001200436020820012005360204200120083602002000200028020841016a3602082002200010fa032002280204417f6a210b0b200241106a2400200b0f0b200e41041037000bf722032d7f017e017f230041306b22022400200241043602002001280204210320012802002104410121050240024002400240024002400240024002400240024002400240024002400240200128020822060d0041002107410121080c010b413010282207450d012007200636000c200720033600082007200436000420022007360200200741023a000041002108410121070b200141106a2802002109200128020c210a02400240200141146a280200220b0d002007210c0c010b2007410174220d200741016a220c200d200c4b1b220c41306c210e0240024020070d00200e1028210d0c010b2002280200200741306c200e102c210d0b200d450d022002200d360200200d200741306c6a220d41033a0000200d20022f002d3b0001200d200b36000c200d2009360008200d200a360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021050b2001411c6a280200210f200128021821104100211102400240200141206a28020022120d00200c210e410021130c010b024002402007200c460d00200c210e0c010b41000d0e41000d0e200c410174220d200c41016a220e200d200e4b1b220ead42307ea722144100480d0e02400240200c0d0020141028210d0c010b2002280200200c41306c2014102c210d0b200d450d042002200d3602000b2002280200200741306c6a220d41043a0000200d20022f002d3b0001200d201236000c200d200f360008200d2010360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012113200741016a21070b200141286a280200211420012802242115024002402001412c6a28020022120d00200e210c0c010b024002402007200e460d00200e210c0c010b41000d0e41000d0e200e410174220d200e41016a220c200d200c4b1b220cad42307ea722114100480d0e02400240200e0d0020111028210d0c010b2002280200200e41306c2011102c210d0b200d450d052002200d3602000b2002280200200741306c6a220d41053a0000200d20022f002d3b0001200d201236000c200d2014360008200d2015360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012111200741016a21070b200141346a28020021162001280230211702400240200141386a280200220e0d00410021180c010b02402007200c470d0041000d0e41000d0e200c410174220d200c41016a2212200d20124b1b2212ad42307ea722194100480d0e02400240200c0d0020191028210d0c010b2002280200200c41306c2019102c210d0b200d450d062002200d3602002012210c0b2002280200200741306c6a220d41063a0000200d20022f002d3b0001200d200e36000c200d2016360008200d2017360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012118200741016a21070b200141c0006a280200211a200128023c211b4101211902400240200141c4006a280200221c0d00200c210e4101211d0c010b024002402007200c460d00200c210e0c010b41000d0e41000d0e200c410174220d200c41016a220e200d200e4b1b220ead42307ea722124100480d0e02400240200c0d0020121028210d0c010b2002280200200c41306c2012102c210d0b200d450d072002200d3602000b2002280200200741306c6a220d41073a0000200d20022f002d3b0001200d201c36000c200d201a360008200d201b360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a21074100211d0b200141cc006a280200211e2001280248211f02400240200141d0006a28020022200d00200e21120c010b024002402007200e460d00200e21120c010b41000d0e41000d0e200e410174220d200e41016a220c200d200c4b1b2212ad42307ea7220c4100480d0e02400240200e0d00200c1028210d0c010b2002280200200e41306c200c102c210d0b200d450d082002200d3602000b2002280200200741306c6a220d41083a0000200d20022f002d3b0001200d202036000c200d201e360008200d201f360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a200241046a41086a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021190b410121210240024020012802544101460d002012210c0c010b200141d8006a280200210e0240024020072012460d002012210c0c010b41000d0e41000d0e2012410174220d201241016a220c200d200c4b1b220cad42307ea722224100480d0e0240024020120d0020221028210d0c010b2002280200201241306c2022102c210d0b200d450d092002200d3602000b2002280200200741306c6a220d41093a0000200d20022f002d3b0001200d200e360204200d2002290204370208200d41036a2002412f6a2d00003a0000200d41106a2002410c6a290200370200200d41186a200241046a41106a290200370200200d41206a200241046a41186a290200370200200d41286a200241046a41206a290200370200200741016a21070b200141e0006a2802002123200128025c212402400240200141e4006a28020022250d00200c210e0c010b024002402007200c460d00200c210e0c010b41000d0e41000d0e200c410174220d200c41016a220e200d200e4b1b220ead42307ea722124100480d0e02400240200c0d0020121028210d0c010b2002280200200c41306c2012102c210d0b200d450d0a2002200d3602000b2002280200200741306c6a220d410a3a0000200d20022f002d3b0001200d202536000c200d2023360008200d2024360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021210b200141ec006a2802002126200128026821274101212202400240200141f0006a28020022280d00200e2112410121290c010b024002402007200e460d00200e21120c010b41000d0e41000d0e200e410174220d200e41016a220c200d200c4b1b2212ad42307ea7220c4100480d0e02400240200e0d00200c1028210d0c010b2002280200200e41306c200c102c210d0b200d450d0b2002200d3602000b2002280200200741306c6a220d410c3a0000200d20022f002d3b0001200d202836000c200d2026360008200d2027360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021290b200141f8006a280200212a2001280274212b02400240200141fc006a280200222c0d002012210c0c010b0240024020072012460d002012210c0c010b41000d0e41000d0e2012410174220d201241016a220c200d200c4b1b220cad42307ea7220e4100480d0e0240024020120d00200e1028210d0c010b2002280200201241306c200e102c210d0b200d450d0c2002200d3602000b2002280200200741306c6a220d410d3a0000200d20022f002d3b0001200d202c36000c200d202a360008200d202b360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021220b20014184016a2802002112200128028001210d02400240200c20076b20014188016a28020041306c222d41306d220e490d00200228020021010c010b2007200e6a22012007490d0d200c410174222e2001202e20014b1b222ead42307e222f422088a70d0d202fa722304100480d0d02400240200c0d002030102821010c010b2002280200200c41306c2030102c21010b2001450d0c20022001360200202e210c0b2001200741306c6a200d202d109a051a2007200e6a210702402012450d00200d102a0b2000200136020820004280c2cdeb16370200200041106a20073602002000410c6a200c3602002022450d0d0240202c450d00202b202c411c6c6a210e202b21000340024020002802042201450d0002402000410c6a2802002207450d00200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102a200c280200210d0b200d102a0b200141106a2101200741706a22070d000b0b200041086a280200450d002000280204102a0b2000411c6a21010240200041146a280200450d002000280210102a0b200121002001200e470d000b0b202a450d0d202b102a0c0d0b413041041037000b200e41041037000b201441041037000b201141041037000b201941041037000b201241041037000b200c41041037000b202241041037000b201241041037000b200c41041037000b200e41041037000b203041041037000b1031000b02402029450d0002402028450d002027202841186c6a210e2027210003400240200041046a280200450d002000280200102a0b0240200041146a2802002207450d00200028020c2101200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102a200c280200210d0b200d102a0b200141106a2101200741706a22070d000b0b200041186a21010240200041106a280200450d00200028020c102a0b200121002001200e470d000b0b2026450d002027102a0b02402021450d0002402025450d0020242025411c6c6a210e202421000340024020002802042201450d0002402000410c6a2802002207450d00200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102a200c280200210d0b200d102a0b200141106a2101200741706a22070d000b0b200041086a280200450d002000280204102a0b2000411c6a21010240200041146a280200450d002000280210102a0b200121002001200e470d000b0b2023450d002024102a0b02402019450d0002402020450d00202041146c2107201f210103400240200141046a280200450d002001280200102a0b200141146a21012007416c6a22070d000b0b201e450d00201f102a0b0240201d450d000240201c450d00201b201c4104746a210e201b21000340024020002802082207450d0020002802002101200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102a200c280200210d0b200d102a0b200141106a2101200741706a22070d000b0b200041106a21010240200041046a280200450d002000280200102a0b200121002001200e470d000b0b201a450d00201b102a0b02402016410047201841017371450d002017102a0b02402014410047201141017371450d002015102a0b0240200f410047201341017371450d002010102a0b02402005450d000240200b450d00200b41286c2107200a210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200741586a22070d000b0b2009450d00200a102a0b02402008450d0002402006450d00200641047421072004210103400240200141046a280200450d002001280200102a0b200141106a2101200741706a22070d000b0b2003450d002004102a0b200241306a24000bee0203037f017e027f410121020240024002400240200041086a2802002203417f6a220420034f0d00200420034b0d00200028020020044104746a220329020421052003200141016aad3702042005a721012005422088a721030240200041086a28020022024101460d002002450d0220002802002002417e6a4104746a22022802042001470d002002200228020820036a36020841000f0b410021022003450d000240200041146a2802002204200041106a280200470d00200441016a22062004490d04200441017422072006200720064b1b220641ffffffff01712006470d04200641037422074100480d040240024020040d002007102821040c010b200028020c20044103742007102c21040b2004450d032000200436020c200041106a2006360200200028021421040b200028020c20044103746a22042003360204200420013602002000200028021441016a3602140b20020f0b41ede3c500413f1050000b200741041037000b1031000b8a1302147f027e23004180026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110de042003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200b200b417f6a220d2000200b4103746a280200220e2000200d4103746a280200220f4922101b2211200b41016a2212200d200b20101b200020124103746a280200220b200f200e20101b220d49220f1b200b200d200f1b200020114103746a2802004922131b210b200c200c417f6a220d2000200c4103746a28020022112000200d4103746a280200221249220e1b2214200c4101722206200d200c200e1b200020064103746a280200220c20122011200e1b220d4922111b200c200d20111b200020144103746a2802004922141b210c200a200a417f6a22122000200a4103746a2802002206200020124103746a280200221549220d1b2216200a41016a22172012200a200d1b200020174103746a280200220a20152006200d1b22064922121b200a200620121b200020164103746a2802004922061b210a41024101200d1b200d20121b20066a200e6a20116a20146a20106a200f6a20136a210d0b200d2000200c4103746a280200220e2000200a4103746a280200220f4922106a2000200b4103746a280200220d200f200e20101b221149220f6a210e200d2011200f1b2000200c200a20101b220d4103746a280200490d01200b200a200c20101b200f1b210d0c020b2000200110df040c0f0b200e41016a220e410c490d0002402001410176220b450d00200020014103746a41786a210a2000210c0340200c2902002118200c200a290200370200200a2018370200200c41086a210c200a41786a210a200b417f6a220b0d000b0b2001200d417f736a210d4101210a0c010b200e45210a0b0240200a452009724101710d002000200110e0040d0d0b2002450d02200d20014f0d01024020022802002000200d4103746a220a2802004f0d0020002108200121070c040b200029020021182000200a290200370200200a2018370200200041786a210f200041086a211120002902002218a721104100210c2001210b03400240200c200b417f6a220d4f0d002011200c4103746a210a0340200a28020020104b0d01200a41086a210a200d200c41016a220c470d000b200d210c0b200f200b4103746a210a02400340200c200b417f6a220b4f0d01200a280200210d200a41786a220e210a200d20104b0d000b2011200c4103746a220a2902002119200a200e41086a220d290200370200200d2019370200200c41016a210c0c010b0b2000201837020002402001200c41016a220a490d002000200a4103746a21002001200a6b220141154f0d010c0c0b0b200a20011044000b41b8e9c500200d20011034000b2007450d010b200d20074f0d012008290200211820082008200d4103746a220a290200370200200a2018370200200841086a210e20082902002219a72111410021142007417f6a2210450d02200e210a0340200a28020020114f0d03200a41086a210a2010201441016a2214470d000b201021140c020b4198e9c500410041001034000b41a8e9c500200d20071034000b200820074103746a210c2010210b02400340200c210d200b220a20144d22060d01200a417f6a210b200d41786a220c28020020114f0d000b0b0240200a2014490d002010200a490d0241800121054100210b410021014100210c4100210f4180012109200e20144103746a2215211003400240200d20106b220a4187104b22130d00200a410376220a41807f6a200a2001200b49200f200c49220e7222001b210a02402000450d002009200a200e1b2109200a2005200e1b21050c010b200a200a41017622096b21050b0240200f200c470d00024020090d002004220c210f0c010b4100210a2004220f210c2010210e0340200c200a3a0000200c200e28020020114f6a210c200e41086a210e2009200a41016a220a470d000b0b02402001200b470d00024020050d0020044180016a220b21010c010b200d41786a210a4100210e20044180016a2201210b0340200b200e3a0000200b200a2802002011496a210b200a41786a210a2005200e41016a220e470d000b0b0240200b20016b220a200c200f6b220e200e200a4b1b2212450d002010200f2d00004103746a220a2902002118200a200d20012d0000417f734103746a290200370200024020124101460d004100210a0340200d2001200a6a220e2d0000417f734103746a2010200f200a6a41016a22002d00004103746a290200370200201020002d00004103746a200d200e41016a2d0000417f734103746a290200370200200a41026a210e200a41016a2200210a200e2012490d000b200120006a2101200f20006a210f0b200d20012d0000417f734103746a2018370200200141016a2101200f41016a210f0b200d20054103746b200d2001200b461b210d201020094103746a2010200f200c461b211020130d000b02400240200f200c4f0d00200d210a03402010200c417f6a220c2d00004103746a220b2902002118200b200a41786a220a290200370200200a2018370200200f200c490d000c020b0b2010210a2001200b4f0d000340200a2902002118200a200d200b417f6a220b2d0000417f734103746a220c290200370200200c2018370200200a41086a210a2001200b490d000b0b200820193702002007200a20156b41037620146a22014d0d032008200820014103746a220a290200370200200a2019370200200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41086a2100024002402001200c417f6a220c490d002000200c200a2003108004200821000c010b2008200120022003108004200a2102200c21010b200b200d4f2105200141154f0d010c050b0b2014200a1044000b200a2010103c000b41a8e9c500200120071034000b41dc83c6001032000b20014102490d00200041786a21104100210e4101210b0340200b410374210c200b417f6a210a200b41016a210b02402000200c6a220d2802002000200a4103746a220f2802004f0d00200d2902002118200d200f2902003702000240200a450d00200e210c2010210a200d41706a2802002018a7220d4d0d00024002400340200a41086a200a290200370200200c4101460d01200c417f6a210c200a41786a220a280200200d4b0d000c020b0b4100210c0b2000200c4103746a210f0b200f20183702000b200e41016a210e201041086a2110200b2001470d000b0b20044180026a24000be00402097f017e230041306b22022400200241106a2203200141246a290200370300200241086a22042001411c6a29020037030020022001290214370300200241186a41106a2205200141106a280200360200200241186a41086a2206200141086a290200370300200220012902003703182000200241186a10fd0321070240024002400240200041206a28020022082000411c6a280200470d00200841016a22092008490d032008410174220a2009200a20094b1b220941ffffffff03712009470d032009410274220a4100480d030240024020080d00200a102821080c010b20002802182008410274200a102c21080b2008450d01200020083602182000411c6a2009360200200028022021080b200028021820084102746a20073602002000200028022041016a3602202005200329030037030020062004290300370300200220022903003703180240200041f0006a22032802002208200041ec006a280200470d00200841016a22042008490d03200841017422052004200520044b1b2204ad42187e220b422088a70d03200ba722054100480d030240024020080d002005102821080c010b2000280268200841186c2005102c21080b2008450d0220002008360268200041ec006a2004360200200041f0006a28020021080b2000280268200841186c6a22082002290318370200200841106a200241186a41106a290300370200200841086a200241186a41086a29030037020020032003280200220841016a360200024020012d002c450d0020004101360254200041d8006a20083602000b200241306a24000f0b200a41041037000b200541041037000b1031000bb20c01067f0240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a280200102a0f0b0240200041086a280200450d00200041046a280200102a0b200041146a280200450d0c200041106a280200102a0f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b200041086a280200450d0b2000280204102a0f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200241586a22020d000b0b200041086a280200450d0a2000280204102a0f0b200041086a280200450d09200041046a280200102a0f0b200041086a280200450d08200041046a280200102a0f0b200041086a280200450d07200041046a280200102a0f0b02402000410c6a2802002201450d00200041046a280200220320014104746a21040340024020032802082202450d0020032802002101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341106a21010240200341046a280200450d002003280200102a0b2001210320012004470d000b0b200041086a280200450d062000280204102a0f0b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d002001280200102a0b200141146a21012002416c6a22020d000b0b200041086a280200450d052000280204102a0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102a0b2003411c6a21010240200341146a280200450d002003280210102a0b2001210320012004470d000b0b200041086a280200450d042000280204102a0f0b02402000410c6a2802002201450d00200041046a2802002203200141186c6a210403400240200341046a280200450d002003280200102a0b0240200341146a2802002202450d00200328020c2101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341186a21010240200341106a280200450d00200328020c102a0b2001210320012004470d000b0b200041086a280200450d032000280204102a0f0b200041046a220110f904200041086a280200450d022001280200102a0f0b0240200041046a2802002201450d00200041086a280200450d002001102a0b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102a0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102a0b200041246a2802002203450d0102402000412c6a2802002201450d00200320014104746a210403402003220541106a2103024020052802042201450d0002402005410c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102a0b2001410c6a2101200241746a22020d000b0b200541086a280200450d002005280204102a0b20032004470d000b0b200041286a280200450d012000280224102a0c010b0240200041086a280200450d00200041046a280200102a0b0240200041146a2802002201450d00200041186a280200450d002001102a0b200041246a280200450d00200041206a280200102a0f0b0bff7f05077f017e277f037e0f7f23002203210420034180096b4160712203240002400240024002400240024002400240024002400240411010282205450d00200541063a0000412010282206450d01200641063a001020064100360204200620032f00f0053b00012006412d3a0000200641036a200341f2056a2d00003a0000024020052d00004109470d0002402005280204220728020441ffffffff0371450d002007280200102a200528020421070b2007102a0b2005102a200141106a28020041306c2105200128020841546a210702400340024020050d00411010282207450d0520074180023b010c200742828080802037020420072006360200200720032f01d0033b010e0240200128021022052001410c6a280200470d00200541016a22082005490d0e200541017422092008200920084b1b2208ad42307e220a422088a70d0e200aa722094100480d0e0240024020050d002009102821050c010b2001280208200541306c2009102c21050b2005450d07200120053602082001410c6a2008360200200128021021050b2001280208200541306c6a220520032f00e0043b0001200541073a0000200542818080801037000820052007360004200520032902f005370210200541036a200341e2046a2d00003a0000200541186a200341f8056a290200370200200541206a20034180066a290200370200200541286a200341f0056a41186a2902003702002001200128021041016a220b3602104100210c0c020b200541506a21052007412c6a2108200741306a2209210720082d00004107470d000b200320032f01d0033b01f0050240200941086a22072802002205200941046a280200470d00200541016a22082005490d0c2005410174220d2008200d20084b1b220841ffffffff00712008470d0c2008410474220d4100480d0c0240024020050d00200d102821050c010b20092802002005410474200d102c21050b2005450d0620092005360200200941046a2008360200200941086a28020021050b200928020020054104746a22054180023b010c200542828080802037020420052006360200200520032f01f0053b010e2007200728020041016a360200200341c0006a200910fa032003280244417f6a210c2001280210210b0b200b41306c21052001280208220e41546a210702400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200b41306c2105200e41546a210702400340410021092005450d01200541506a21052007412c6a2106200741306a220d210720062d00004103470d000b200d41086a2802002205450d00200541286c2107200d28020041186a2105410021090340200920052d0000456a2109200541286a2105200741586a22070d000b0b200b41306c2105200e415c6a2107024003404100210f024020050d00410021050c020b200541506a2105200741246a2106200741306a220d210720062d00004104470d000b200d28020021050b200341003602e0040240200520096a220b0d0041042110410021110c080b02402008450d00200342003703f005410021050c060b200341f0056a4100200110d60420032802f405210520032802f0054101470d05200341f8056a290300210a024020032802e0042207450d0020032802e404450d002007102a0b2003200a3702e404200320053602e00441002111410421104100210f0c060b411041081037000b412041081037000b411041041037000b200941041037000b200d41041037000b0240024002400240410410282210450d0020102005360200200b4102490d02024020084102490d00200342003703f0054100210d0c020b200341f0056a4101200110d60420032802f405210d20032802f0054101470d01200341f8056a290300210a024020032802e004450d0020032802e404450d0020032802e004102a0b2003200a3702e4042003200d3602e0040c020b410441041037000b410221064104210741012109410121110340200941016a210502400240024020092011470d0020062005200620054b1b221141ffffffff03712011470d0a2011410274220e4100480d0a20102007200e102c2210450d010b201020076a200d36020002402005200b4f0d000240200820054d0d00200342003703f0054100210d0c030b200341f0056a2005200110d60420032802f405210d20032802f0054101470d0220032903f805210a024020032802e004450d0020032802e404450d0020032802e004102a0b200941016a210f2003200a3702e4042003200d3602e0040c050b200941016a210f0c040b200e41041037000b200641026a2106200741046a2107200521090c000b0b4101210f410121110b20032802e00421050b2005450d0020032902e404210a02402011450d002010102a0b2000200536020420004101360200200041086a200a3702000c010b024020012802102205450d0020012802082212200541306c6a2113200341e0046a41146a2114200341e0076a211520034194066a2116200341a4066a2117200341b4066a2118200341c4066a2119200341d4066a211a200341e4066a211b200341f4066a211c20034184076a211d20034194076a211e200341a4076a211f200341b4076a2120200341c4076a2121200341d4076a212202400240024002400340024020122d0000410c470d00201228020c2205450d0020122802042206200541186c6a212303400240200641146a220e2802002205450d002006410c6a212441002109024002400340200920054f0d014101210502402024280200200941047422256a22072d0000410b470d002003200741046a22073602c00220072802002207200f4f0d03201020074102746a2802002208450d002003200c3602d407200341133a00d007200341d7003a00c007200320083602b4072003412d3a00b0072003200c3602a407200341123a00a00720032007360294072003410b3a009007200341063a008007200341003a00f00620034184083b01e006200341373a00d006200320023602c4062003412d3a00c0062003200c3602b406200341123a00b0062003200c3602a406200341133a00a006200341d6003a00900620032008360284062003412d3a0080062003200c3602f405200341123a00f005200e280200222620094d0d09200e2009360200200628020c2105200320153602f804200320243602f0042003200520256a220b41106a220d3602e8042003200941016a22273602e0042003202620276b22283602e40420032005202741047422296a222a3602ec042003200341f0056a3602f404200d21050240200b2d0000220841ac01460d004100210502400340200b20056a21070240200841ff01714109470d000240200741046a280200220828020441ffffffff0371450d002008280200102a0b2008102a0b2005450d012003200741206a3602e804200541106a2105200741106a2d0000220841ac01470d000b200b20056a41106a21050c010b200741106a21050b02402005202a460d0003402003200541106a22073602e80420052d0000220841ac01460d01024020084109470d000240200541046a280200220528020441ffffffff0371450d002005280200102a0b2005102a0b20072105200d2007470d000b0b02400240024002402028450d000240202720062802142205470d00200341f0056a21052015210b0c030b2025200541047422056b2108200628020c20056a2107200341f0056a21052015210d0340024002402005200d470d00410021050c010b2003200541106a3602f4040b200341d0036a200510d30420032d00d00341ac01460d04200720032903d003370300200741086a200341d0036a41086a2903003703002006200628021441016a3602142008450d02200741106a2107200841706a210820032802f804210d20032802f40421050c000b0b2024201410d7040c020b20032802f804210b20032802f40421050b0240200b20056b2207450d000240024020032802f004220d41046a222a280200222520266b20074104762208490d00200d28020021070c010b202620086a22072026490d12202541017422262007202620074b1b222641ffffffff00712026470d122026410474222b4100480d120240024020250d00202b102821070c010b200d2802002025410474202b102c21070b2007450d0d200d2007360200202a20263602000b2007202720086a22254104746a200720296a2028410474109b051a200320253602e0042025200d2802082207460d00200920086a410474200741047422076b2108200d28020020076a21070340024002402005200b470d00410021050c010b2003200541106a3602f4040b200341d0036a200510d30420032d00d00341ac01460d02200720032903d003370300200741086a200341d0036a41086a290300370300200d200d28020841016a3602082008450d01200741106a2107200841706a210820032802f804210b20032802f40421050c000b0b200341003602d803200342083703d003200341d0036a201410d70420032802d003222820032802d8032207410474220b6a210d20032802d40321292028210502402007450d000240024020032802f004222541046a222a280200220520032802e404222720032802e00422076a22266b200b4104752208490d00202528020021050c010b202620086a222b2026490d1220054101742226202b2026202b4b1b222641ffffffff00712026470d122026410474222b4100480d120240024020050d00202b102821050c010b20252802002005410474202b102c21050b2005450d0e20252005360200202a20263602000b2005200720086a220841047422266a200520074104746a2027410474109b051a200320083602e00420282105200820252802082207460d002025280200220520266a212a200520074104746a21082028210703400240200b0d00200d21050c020b200341d0036a41026a2205200741036a2d00003a0000200320072f00013b01d003024020072d0000222741ac01470d00200741106a21050c020b200741046a2802002126200741086a290300210a200820273a0000200841086a200a370300200841046a202636020020032f01d0032127200841036a20052d00003a0000200841016a20273b00002025202528020841016a360208200b41706a210b200741106a22052107200841106a2208202a470d000b0b02402005200d460d0003400240024020052d000022074109460d00200741ac01470d010c030b0240200541046a280200220728020441ffffffff0371450d002007280200102a0b2007102a0b200541106a2205200d470d000b0b2029450d002028102a0b024020032802e804220520032802ec04220d460d0003402003200541106a22073602e80420052d0000220841ac01460d01024020084109470d000240200541046a280200220528020441ffffffff0371450d002005280200102a0b2005102a0b20072105200d2007470d000b0b024020032802e4042205450d00024020032802e004220d20032802f004220b41086a22082802002207460d00200b280200220b20074104746a200b200d4104746a2005410474109b051a0b2008200520076a3602000b024020032d00f0054109470d00024020032802f405220528020441ffffffff0371450d002005280200102a20032802f40521050b2005102a0b024020032d0080064109470d000240200341f0056a41146a280200220528020441ffffffff0371450d002005280200102a20032802840621050b2005102a0b024020032d0090064109470d0002402016280200220528020441ffffffff0371450d002005280200102a20032802940621050b2005102a0b024020032d00a0064109470d0002402017280200220528020441ffffffff0371450d002005280200102a20032802a40621050b2005102a0b024020032d00b0064109470d0002402018280200220528020441ffffffff0371450d002005280200102a20032802b40621050b2005102a0b024020032d00c0064109470d0002402019280200220528020441ffffffff0371450d002005280200102a20032802c40621050b2005102a0b024020032d00d0064109470d000240201a280200220528020441ffffffff0371450d002005280200102a20032802d40621050b2005102a0b024020032d00e0064109470d000240201b280200220528020441ffffffff0371450d002005280200102a20032802e40621050b2005102a0b024020032d00f0064109470d000240201c280200220528020441ffffffff0371450d002005280200102a20032802f40621050b2005102a0b024020032d0080074109470d000240201d280200220528020441ffffffff0371450d002005280200102a20032802840721050b2005102a0b024020032d0090074109470d000240201e280200220528020441ffffffff0371450d002005280200102a20032802940721050b2005102a0b024020032d00a0074109470d000240201f280200220528020441ffffffff0371450d002005280200102a20032802a40721050b2005102a0b024020032d00b0074109470d0002402020280200220528020441ffffffff0371450d002005280200102a20032802b40721050b2005102a0b024020032d00c0074109470d0002402021280200220528020441ffffffff0371450d002005280200102a20032802c40721050b2005102a0b024020032d00d0074109470d0002402022280200220528020441ffffffff0371450d002005280200102a20032802d40721050b2005102a0b410f21050b200520096a2209200e2802002205490d000c030b0b41ace4c500200920051034000b2003410136028406200342013702f405200341bce4c5003602f0052003412c3602d4032003200341d0036a360280062003200341c0026a3602d003200341e0046a200341f0056a103320032802e00422050d040b200641186a22062023470d000b0b201241306a22122013470d000c050b0b20032902e404210a2000200536020420004101360200200041086a200a3702002011450d042010102a0c040b41e4e8c5001032000b202b41081037000b202b41081037000b200341c8006a41106a200141106a2802002220360200200341c8006a41086a200141086a290200220a37030020032001290200370348202041306c2105200aa7221241546a210702400340024020050d00410021080c020b200541506a21052007412c6a2108200741306a2209210720082d00004108470d000b200341386a200910fa0320032802382108200328023c21050b2005410020081b210d202041306c2105201241546a21072008410420081b210802400340024020050d00410021090c020b200541506a21052007412c6a2109200741306a2206210720092d0000410a470d000b200341306a200610fa0320032802302109200328023421050b2005410020091b210b202041306c2105201241546a21072009410420091b211702400340024020050d004100211c0c020b200541506a21052007412c6a2109200741306a2206210720092d00004109470d000b200628020021074101211c0b20034200370274200341f8b9c0003602702017200b411c6c6a211f2008200d41146c6a210d200341e0046a410272221b41266a2121201b41186a2122201b41086a212b4104211641002124410021264100211e4100211d410021140240024002400240410041ff01710e03000102000b410021050c020b410221050c010b410121050b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e03000104040b0240201441ff01710e03020300020b201e4101470d04410021050c0b0b201c450d0f4100211c410221284100212a200721050c1d0b034002400240024002400240200d200822056b413c4b0d002005200d470d01200521080c020b200528020c0d03200541146a2108200541106a28020021050c1f0b200541106a21090340200528020c450d02200941146a2109200541146a2205200d470d000b200d21080b201e4101470d07410021050c0a0b200941046a2108200928020021050c1c0b200541206a280200450d1a200541346a280200450d19200541d0006a2108200541c8006a280200450d180c000b0b0340024002400240200d200822056b413c4b0d00410121142005200d470d01200521080c2b0b200528020c0d01200541146a2108200541106a28020021050c180b200541106a210902400340200528020c450d01200941146a2109200541146a2205200d470d000b200d21080c2a0b200941046a2108200928020021050c170b200541206a280200450d15200541346a280200450d14200541d0006a2108200541c8006a280200450d130c000b0b024002400240201441ff01710e03010200010b201e4101470d03410021050c080b034002400240024002400240200d200822056b413c4b0d002005200d470d01200521080c020b200528020c0d03200541146a2108200541106a28020021050c160b200541106a21090340200528020c450d02200941146a2109200541146a2205200d470d000b200d21080b201e4101470d07410021050c080b200941046a2108200928020021050c130b200541206a280200450d11200541346a280200450d10200541d0006a2108200541c8006a280200450d0f0c000b0b0340024002400240200d200822056b413c4b0d002005200d460d10200541106a21090340200528020c450d02200941146a2109200541146a2205200d470d000c110b0b200528020c0d01200541146a2108200541106a28020021050c0e0b200941046a2108200928020021050c0d0b200541206a280200450d0b200541346a280200450d0a200541d0006a2108200541c8006a280200450d090c000b0b410121050c060b410121050c040b410121050c020b410121050b0340024002400240024020050e020001010b2029201d470d01410121050c030b2017201f460d0a200341206a201710cd0420032802202229450d0a2017411c6a2117202920032802244102746a211d0c010b2029450d09202928020021054101211e41022114202941046a2129410121280c160b410021050c000b0b0340024002400240024020050e020001010b2029201d470d014101211e2029211d410121050c030b410221142017201f460d22200341106a201710cd042017411c6a211720032802102205450d23200520032802144102746a211d200521290c010b202941046a2109024020290d00410221144101211e200921290c230b2029280200210541002128410221144101211e200921290c150b410021050c000b0b0340024002400240024020050e020001010b2029201d470d01410121050c030b2017201f460d08200341286a201710cd0420032802282229450d082017411c6a21172029200328022c4102746a211d0c010b2029450d07202928020021054101211e41022114202941046a2129410121280c140b410021050c000b0b0340024002400240024020050e020001010b2029201d470d014101211e2029211d410121050c030b410221142017201f460d20200341186a201710cd042017411c6a211720032802182205450d212005200328021c4102746a211d200521290c010b202941046a2109024020290d00410221144101211e200921290c210b2029280200210541002128410221144101211e200921290c130b410021050c000b0b200541cc006a28020021050c020b2005413c6a2108200541386a28020021050c010b200541286a2108200541246a28020021050b41012114410121280c0d0b200341e0006a41086a200341f0006a41086a280200360200200320032903703703602003280258220d41306c21052003280250220b41546a210702400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200d41306c2105200b415c6a210702400340024020050d00410021050c020b200541506a2105200741246a2109200741306a2206210720092d00004104470d000b200628020021050b200341f0056a41106a2228200341c8006a41106a280200360200200341f0056a41086a200341c8006a41086a290300370300200320032903483703f005200341b0016a200341f0056a10fc0302402026450d00201620264102746a212a200520086a2125200341f0056a41e0016a210f200341f0056a41d0016a2115200341f0056a41c0016a2129200341f0056a41b0016a2114200341f0056a41a0016a2117200341f0056a4190016a2118200341f0056a4180016a2119200341f0056a41f0006a211a200341f0056a41e0006a211b200341f0056a41d0006a211c200341f0056a41c0006a211d200341f0056a41306a211e200341f0056a41206a211f200341e7046a212020034184066a212120034194066a2122200341b4066a212b200341c4066a2123200341d4066a2112200341e4066a2101200341f4066a211320034184076a212c20034194076a212d200341a4076a212e200341b4076a212f200341c4076a2130200341d4076a21312016212703402027220541046a212720052802002106200341e0006a21052003280264210b03402005280200220d41086a2107200d2f0106220e4102742105417f210802400340024020050d00200e21080c020b20072802002109200841016a21082005417c6a2105200741046a21070240417f2009200647200920064b1b41016a0e03020001020b0b200d41346a20084105746a220e2802182107200e28021c21052003200c3602d407200341133a00d007200341d7003a00c007200320053602b4072003412d3a00b0072003200c3602a407200341123a00a00720032007360294072003410b3a009007200341063a008007200341003a00f00620034184083b01e006200341373a00d006200320023602c4062003412d3a00c0062003200c3602b406200341123a00b0062003200c3602a406200341133a00a006200341d6003a00900620032005360284062003412d3a0080062003200c3602f405200341123a00f005200e280208220d41106a220541ffffffff00712005470d1220054104742207417f4c0d12200e41086a21260240024002400240024020070d00410821060c010b200710282206450d012026280200210d0b0240200d0d00410021080c030b41002109410021070340024020072005470d00200541016a22082005490d262005410174220b2008200b20084b1b220841ffffffff00712008470d262008410474220b4100480d260240024020050d00200b102821060c010b20062005410474200b102c21060b2006450d03200821050b200620096a2208410f3a0000200841046a2007360200200841016a20032f01d0033b0000200841036a200341d0036a41026a2d00003a0000200941106a2109200741016a22082107200d2008460d030c000b0b200741081037000b200b41081037000b02400240024002400240024002400240200520086b410e4d0d00200521090c010b2008410f6a22072008490d28200541017422092007200920074b1b220941ffffffff00712009470d28200941047422074100480d280240024020050d002007102821060c010b200620054104742007102c21060b2006450d010b200341e0046a200341f0056a10d904200620084104746a220520032903e004370300200541086a200341e0046a41086a2207290300370300200341e0046a202810d904200541186a2007290300370300200520032903e004370310200341e0046a201f10d904200541286a2007290300370300200541206a20032903e004370300200341e0046a201e10d904200541386a2007290300370300200541306a20032903e004370300200341e0046a201d10d904200541c8006a2007290300370300200541c0006a20032903e004370300200341e0046a201c10d904200541d8006a2007290300370300200541d0006a20032903e004370300200341e0046a201b10d904200541e8006a2007290300370300200541e0006a20032903e004370300200341e0046a201a10d904200541f8006a2007290300370300200541f0006a20032903e004370300200341e0046a201910d90420054188016a200729030037030020054180016a20032903e004370300200341e0046a201810d90420054198016a200729030037030020054190016a20032903e004370300200341e0046a201710d904200541a8016a2007290300370300200541a0016a20032903e004370300200341e0046a201410d904200541b8016a2007290300370300200541b0016a20032903e004370300200341e0046a202910d904200541c8016a2007290300370300200541c0016a20032903e004370300200341e0046a201510d904200541d8016a2007290300370300200541d0016a20032903e004370300200341e0046a200f10d904200541e8016a2007290300370300200541e0016a20032903e004370300024002402008410f6a22052009460d002009210d200521090c010b200941016a22052009490d28200941017422072005200720054b1b220d41ffffffff0071200d470d28200d41047422054100480d280240024020090d002005102821060c010b200620094104742005102c21060b2006450d020b200620094104746a220541063a0000200520032900e004370001200541086a2020290000370000200341e0046a200341b0016a418c01109a051a411010282207450d02200741063a0000200341d0036a200341e0046a418c01109a051a20262802002205417f4c0d18200e28020021090240024020050d004101210b410120092005109a05220920092005109a051a2005ad2132410021050c010b20051028220b450d04200b20092005109a05210920051028220b450d05200b20092005109a051a2009102a2005ad21320b200341e0046a200341d0036a418c01109a051a200e31000d2133200341d0036a200341e0046a418c01109a051a200341e0046a200341d0036a418c01109a051a200341c0026a200341e0046a418c01109a051a411010282209450d05200841106a2108200a428080808080804083220a2032842033422886844280808080800c842132200941063a00002009102a200341d0036a200341c0026a418c01109a051a200341e0046a200341d0036a418c01109a051a024020072d00004109470d0002402007280204220928020441ffffffff0371450d002009280200102a200728020421090b2009102a0b2007102a200341c0026a200341e0046a418c01109a051a200341e0046a200341c0026a418c01109a051a200341003602fc03200320083602f8032003200d3602f403200320063602f003200341003602ec03200342043702e403200320323702dc03200320053602d8032003200b3602d403200341013602d003200341e0046a200341d0036a108104200341b0016a200341e0046a418c01109a051a200e4101360210200e2025360214024020032d00f0054109470d00024020032802f405220528020441ffffffff0371450d002005280200102a20032802f40521050b2005102a0b024020032d0080064109470d0002402021280200220528020441ffffffff0371450d002005280200102a20032802840621050b2005102a0b024020032d0090064109470d0002402022280200220528020441ffffffff0371450d002005280200102a20032802940621050b2005102a0b024020032d00a0064109470d000240200341f0056a41346a280200220528020441ffffffff0371450d002005280200102a20032802a40621050b2005102a0b024020032d00b0064109470d000240202b280200220528020441ffffffff0371450d002005280200102a20032802b40621050b2005102a0b024020032d00c0064109470d0002402023280200220528020441ffffffff0371450d002005280200102a20032802c40621050b2005102a0b024020032d00d0064109470d0002402012280200220528020441ffffffff0371450d002005280200102a20032802d40621050b2005102a0b024020032d00e0064109470d0002402001280200220528020441ffffffff0371450d002005280200102a20032802e40621050b2005102a0b024020032d00f0064109470d0002402013280200220528020441ffffffff0371450d002005280200102a20032802f40621050b2005102a0b024020032d0080074109470d000240202c280200220528020441ffffffff0371450d002005280200102a20032802840721050b2005102a0b024020032d0090074109470d000240202d280200220528020441ffffffff0371450d002005280200102a20032802940721050b2005102a0b024020032d00a0074109470d000240202e280200220528020441ffffffff0371450d002005280200102a20032802a40721050b2005102a0b024020032d00b0074109470d000240202f280200220528020441ffffffff0371450d002005280200102a20032802b40721050b2005102a0b024020032d00c0074109470d0002402030280200220528020441ffffffff0371450d002005280200102a20032802c40721050b2005102a0b024020032d00d0074109470d0002402031280200220528020441ffffffff0371450d002005280200102a20032802d40721050b2005102a0b200a4280808080808c0184210a202541016a21252027202a470d080c090b200741081037000b200541081037000b411041081037000b200541011037000b200541011037000b411041081037000b0240200b450d00200b417f6a210b200d20084102746a4194036a21050c010b0b0b4198ebc5004180011050000b02402024450d002016102a0b200341f0056a200341b0016a418c01109a051a200341e0046a200341f0056a10fe030240200341e0046a41106a2802002205450d0020032802e8042228200541306c6a212a0340024020282d000041786a220541024b0d0002400240024020050e03000102000b202828020c2205450d0220282802042208200541146c6a210c03400240200828020c0d002008280210210d200341e0006a21052003280264210e03402005280200220b41086a2107200b2f010622244102742105417f210902400340024020050d00202421090c020b20072802002106200941016a21092005417c6a2105200741046a21070240417f2006200d472006200d4b1b41016a0e03020001020b0b0240200b41346a20094105746a2205280210450d00200820052802143602100c030b4198ecc50041351050000b200e450d01200e417f6a210e200b20094102746a4194036a21050c000b0b200841146a2208200c470d000c030b0b20282802042106200341e0006a21052003280264210b03402005280200220d41086a2107200d2f0106220e4102742105417f210802400340024020050d00200e21080c020b20072802002109200841016a21082005417c6a2105200741046a21070240417f2009200647200920064b1b41016a0e03020001020b0b0240200d41346a20084105746a2205280210450d00202820052802143602040c040b4198ecc50041351050000b200b450d02200b417f6a210b200d20084102746a4194036a21050c000b0b202828020c2205450d00202828020422272005411c6c6a21260340024020272802182205450d002027280210220e20054102746a21250340200e220c41046a210e200c2802002106200341e0006a21052003280264210b03402005280200220d41086a2107200d2f010622244102742105417f2108024002400340024020050d00202421080c020b20072802002109200841016a21082005417c6a2105200741046a21070240417f2009200647200920064b1b41016a0e03020001020b0b0240200d41346a20084105746a2205280210450d00200c20052802143602000c020b4198ecc50041351050000b200b450d00200b417f6a210b200d20084102746a4194036a21050c010b0b200e2025470d000b0b2027411c6a22272026470d000b0b202841306a2228202a470d000b0b200341ec046a290200210a20032802e004210520032902e404213220032802602003280264200328026810da04200041106a200a370200200041086a203237020020002005360204200041003602002011450d1c2010102a200424000f0b200541cc006a28020021050c020b2005413c6a2108200541386a28020021050c010b200541286a2108200541246a28020021050b41012128410021140c080b200541cc006a28020021050c020b2005413c6a2108200541386a28020021050c010b200541286a2108200541246a28020021050b41002128410121140c040b200541cc006a28020021050c020b2005413c6a2108200541386a28020021050c010b200541286a2108200541246a28020021050b41002114410021280b2007212a0b2003200536027c02402005200f490d002003410136028406200342023702f40520034188ebc5003602f005200341013602d4032003200341d0036a360280062003200341fc006a3602d003200341e0046a200341f0056a103320032902e404220a422088a7210820032802e0042125200aa7211a0c0a0b201020054102746a2802002207450d050240024020262024460d0020242115202621240c010b202441016a22092024490d10202441017422062009200620094b1b221541ffffffff03712015470d10201541027422094100480d100240024020240d002009102821160c010b201620244102742009102c21160b2016450d020b201620244102746a2005360200200341f0056a200328027c220b200341c8006a10db0420032802f805211a20032802f4052125024020032802f00522194101470d0020032802fc052108201521240c0a0b20252802082205417f4c0d002025280200210920252d000c210602400240024020050d004100210e410121240c010b2005210e200510282224450d010b202420092005109a05210920032005360288012003200e360284012003200936028001200320063a008c01200320252d000d3a008d0120034100360290012003200328027c360298012003200736029c010240024002402003280270220741f8b9c000460d00200328027421270c010b20214200370100201b41206a420037010020224200370100201b41106a4200370100202b4200370100201b4200370100200341f0056a410041e0021099051a41940310282207450d014100212720074100360200200720032903e0043702042007410c6a200341e0046a41086a290300370200200741146a200341e0046a41106a2903003702002007411c6a200341e0046a41186a290300370200200741246a200341e0046a41206a2903003702002007412c6a200341e0046a41286a290300370200200741346a200341f0056a41e002109a051a20034100360274200320073602700b202641016a2126034020072f0106221841027421244100210541142106417f210902400340024020242005470d00201821090c020b200720056a210e200941016a2109200641206a2106200541046a21050240417f200e41086a280200220e200b47200e200b4b1b41016a0e03020001020b0b200720066a2205290200210a2005200329038001370200200541186a200329039801370200200541106a220729020021322007200329039001370200200541086a200329038801370200203242ffffffff0f83420285500d08200a42808080807083500d08200aa7102a0c080b02402027450d002027417f6a2127200720094102746a4194036a28020021070c010b0b2003200328027841016a360278200329039801210a20032903900121322003290388012133200329038001213420072f01062206410b490d0420214200370100201b41206a2235420037010020224200370100201b41106a22364200370100202b4200370100201b4200370100200341f0056a410041e0021099051a024041940310282205450d0020054100360200200520032903e0043702042005410c6a200341e0046a41086a222c290300370200200541146a200341e0046a41106a222d2903003702002005411c6a200341e0046a41186a222e290300370200200541246a200341e0046a41206a22372903003702002005412c6a200341e0046a41286a2238290300370200200541346a200341f0056a41e002109a05210e200341f0056a41086a2227200741fc016a290200370300200341f0056a41106a221820074184026a290200370300200341f0056a41186a22232007418c026a290200370300200320072902f4013703f00520072802202139200541086a200741246a20072f010641796a2206410274109a052124200e20074194026a2006410574109a05210e200741063b0106200520063b0106202e2023290300370300202d2018290300370300202c2027290300370300200320032903f0053703e0040240024020094107490d0020242009417a6a22134102746a2024200941796a22014102746a2209200641ffff037120016b410274109b051a2009200b360200200e20134105746a200e20014105746a2209200541066a22062f010020016b410574109b051a200941186a200a37020020092032370210200920333702082009203437020020062f0100210e0c010b200741086a2206200941016a22244102746a200620094102746a2201200741066a22062f0100220e20096b2213410274109b051a2001200b360200200741346a220b20244105746a200b20094105746a22092013410574109b051a200941186a200a3702002009203237021020092033370208200920343702000b2006200e41016a3b0100200341d0036a41186a222f202e290300220a370300200341d0036a41106a2230202d2903002232370300200341d0036a41086a2231202c2903002233370300200341b0016a41186a223a200a370300200341b0016a41106a223b2032370300200341b0016a41086a223c2033370300200320032903e004220a3703d0032003200a3703b00102402007280200220e0d00200521090c070b20072f010421012005213d0340200341c0026a41186a223e203a290300370300200341c0026a41106a223f203b290300370300200341c0026a41086a2240203c290300370300200320032903b0013703c002200141ffff0371210b02400240024002400240200e2f01062205410b490d0020214200370100203542003701002022420037010020364200370100202b4200370100201b42003701002031202c2903003703002030202d290300370300202f202e290300370300200341d0036a41206a22052037290300370300200341d0036a41286a22072038290300370300200320032903e0043703d003200341f0056a41004190031099051a41c40310282209450d0320094100360200200920032903d0033702042009410c6a2031290300370200200941146a20302903003702002009411c6a202f290300370200200941246a20052903003702002009412c6a2007290300370200200941346a200341f0056a419003109a052107200e41206a28020021412023200e418c026a2902003703002018200e4184026a2902003703002027200e41fc016a2902003703002003200e41f4016a2902003703f005200941086a200e41246a200e2f0106220641796a2205410274109a0521422007200e4194026a2005410574109a05214320094194036a200e41b0036a2006417a6a2224410274109a052113200e41063b0106200920053b010602402024450d00410021052013210703402007280200220620053b010420062009360200200741046a21072024200541016a2205470d000b0b202e2023290300220a370300202d20182903002232370300202c20272903002233370300200320032903f00522343703e0042023200a3703002018203237030020272033370300200320343703f005200141ffff037122074107490d012042200b417a6a220641027422246a2042200b41796a22054102746a220720092f010620056b410274109b051a20072039360200204320064105746a204320054105746a220720092f010620056b410574109b051a200741186a203e290300370200200741106a203f290300370200200741086a2040290300370200200720032903c002370200200920092f010641016a22073b0106200b410274220120136a416c6a201320246a2224200741ffff0371220b20066b410274109b051a2024203d360200200b2006490d02200920016a41fc026a2107034020072802002206200541016a22053b010420062009360200200741046a21072005200b490d000c030b0b200e41086a2207200b41016a220941027422066a2007200b41027422246a22072005200b6b2227410274109b051a20072039360200200e41346a220720094105746a2007200b4105746a22072027410574109b051a200741186a203e290300370200200741106a203f290300370200200741086a2040290300370200200720032903c002370200200e200541016a22053b01062024200e4194036a22076a41086a200720066a2207200541ffff0371220620096b410274109b051a2007203d360200200b20064f0d0c200e2009417f6a22054102746a4198036a2107034020072802002209200541016a22053b01042009200e360200200741046a210720052006490d000c0d0b0b200e41086a2205200b41016a222441027422066a2005200b41027422016a2205200e2f01062213200b6b2242410274109b051a20052039360200200e41346a220520244105746a2005200b4105746a22052042410574109b051a200541186a203e290300370200200541106a203f290300370200200541086a2040290300370200200520032903c002370200200e201341016a22053b01062001200e4194036a22136a41086a201320066a2213200541ffff0371220620246b410274109b051a2013203d360200200720064f0d00200e20016a4198036a2105034020052802002207200b41016a220b3b01042007200e360200200541046a21052006200b470d000b0b203a2023290300370300203b2018290300370300203c2027290300370300200320032903f0053703b001200e28020022050d01204121390c090b41c40341041037000b200e2f010421012005210e204121392009213d0c000b0b41940341041037000b41940341041037000b200541011037000b1036000b200941041037000b200741086a2205200941016a220e4102746a200520094102746a2205200620096b2224410274109b051a2005200b360200200741346a2205200e4105746a200520094105746a22052024410574109b051a200541186a200a3702002005203237021020052033370208200520343702002007200641016a3b01060c010b20214200370100203542003701002022420037010020364200370100202b4200370100201b42003701002031202c2903003703002030202d290300370300202f202e290300370300200341d0036a41206a22072037290300370300200341d0036a41286a22062038290300370300200320032903e0043703d003200341f0056a41004190031099051a41c40310282205450d0220054100360200200520032903d0033702042005410c6a2031290300370200200541146a20302903003702002005411c6a202f290300370200200541246a20072903003702002005412c6a2006290300370200200541346a200341f0056a419003109a05210b20052003280270220736029403200320053602702003200328027441016a36027420072005360200200741003b0104200b20052f010622064105746a220720032903b001370200200741186a203a290300370200200741106a203b290300370200200741086a203c290300370200200520064102746a41086a203936020020054194036a200641016a22074102746a2009360200200520073b0106200920073b0104200920053602000b02402019450d00201a450d002025102a0b201521240b202a2107202841ff01710e03010205010b41c40341041037000b410021050c040b410221050c030b20032802702003280274200328027810da0402402024450d002016102a0b02402020450d00202041306c2107201221050340200510dc04200541306a2105200741506a22070d000b0b0240200341d4006a280200450d002012102a0b2000202536020420004101360200200041086a2008ad422086201aad843702002011450d042010102a200424000f0b201f21170b410121050c000b0b024020012802102205450d0020012802082103200541306c21050340200310dc04200341306a2103200541506a22050d000b0b2001410c6a280200450d002001280208102a0b200424000f0b1031000bfc8c0204117f017e0b7f017e230041e0006b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e100100021817161514130d0b0c09080706010b200141186a2802002104200141146a2802002105200141106a28020021062001410c6a2802002107200141086a2802002108200141046a28020021090240200241046a280200200241086a280200220a460d002002280200210b0c1e0b200a41016a220b200a490d1a200a410174220c200b200c200b4b1b220c4100480d1a02400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d042002200b360200200241046a200c360200200241086a280200210a0c1d0b2001410c6a280200210b200141086a2802002105200141046a280200210420012d0001210d02400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d1a200a4101742206200c2006200c4b1b22064100480d1a02400240200a0d0020061028210c0c010b2002280200200a2006102c210c0b200c450d032002200c360200200241046a2006360200200241086a280200210a0b200241086a2206200a41016a360200200c200a6a200d3a000002400240200241046a280200220c2006280200220a6b200b490d002002280200210c0c010b200a200b6a220d200a490d1a200c410174220a200d200a200d4b1b220a4100480d1a02400240200c0d00200a1028210c0c010b2002280200200c200a102c210c0b200c450d022002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2004200b109a051a4100210b4101210d024020050d004101210c0c270b2004102a4101210c0c260b2001410c6a2802002106200141086a280200210e200141046a280200210f024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d1a200a410174220c200b200c200b4b1b220c4100480d1a02400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41013a0000200f20064104746a21104100210c4100210b41002105410121042006210a024003400240200b2005470d00200c200b41016a220d200c200d4b1b22054100480d1c02400240200c0d002005102821040c010b2004200b2005102c21040b2004450d020b2004200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b024020060d00200f21080c190b200f210a02400340200a41106a2108200a2d000d22114105460d1a200a2d000c210c200a2802082109200a2802042112200a28020021130240024002400240024002402005200b470d00200b41016a220a200b490d22200b410174220d200a200d200a4b1b22054100480d2202400240200b0d002005102821040c010b2004200b2005102c21040b2004450d010b2004200b6a200c3a0000200b41016a210a200b410174220b41046a2107200b41026a210c2009210b0340200721060240200a2005470d00200a41016a220d200a490d23200c200d200c200d4b1b22054100480d2302400240200a0d002005102821040c010b2004200a2005102c21040b2004450d030b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200641026a2107200c41026a210c200a41016a210a200d210b200d0d000b0240024020090d00200a210b0c010b4100210c0340200a200c6a210b41fc00210d02400240024002402013200c6a2d00000e050200010305020b41fe00210d0c020b41fd00210d0c010b41ff00210d0b0240200b2005470d00200b41016a2205200b490d2420062005200620054b1b22054100480d2402400240200b0d002005102821040c010b2004200b2005102c21040b2004450d050b2004200a6a200c6a200d3a0000200641026a21062009200c41016a220c470d000b200a200c6a210b0b20120d030c040b200541011037000b200541011037000b200541011037000b2013102a0b4100210a0240024020114104460d0002402005200b470d00200b41016a220a200b490d1f200b410174220c200a200c200a4b1b22054100480d1f02400240200b0d002005102821040c010b2004200b2005102c21040b2004450d020b2004200b6a41013a0000200b41016a210b201141077141ff0073210a0b02402005200b470d00200b41016a220c200b490d1e200b410174220d200c200d200c4b1b22054100480d1e02400240200b0d002005102821040c010b2004200b2005102c21040b2004450d030b2004200b6a200a3a0000200b41016a210b2008210a20082010470d010c1c0b0b200541011037000b200541011037000b200541011037000b200c41011037000b200a41011037000b200641011037000b200c41011037000b200141286a2802002113200141246a280200210f200141206a28020021082001411c6a2802002107200141186a2802002112200141146a28020021092001410c6a2902002114200141086a2802002110200141046a28020021110240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d27200a410174220c200b200c200b4b1b220c4100480d2702400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41003a0000200341dc006a410036020020034201370254200320023602502014422088a7210d4100210a4100210b2014a72206210c034002400240200a200b460d002003280254210a0c010b200a41016a2204200a490d28200a41017422052004200520044b1b22044100480d2802400240200a0d0020041028210a0c010b2003280254200a2004102c210a0b200a450d03200320043602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c41077622041b3a00002003280258210a200328025c210b2004210c20040d000b02400240200a200b6b2006490d00200328025421040c010b200b20066a220c200b490d27200a4101742204200c2004200c4b1b220c4100480d2702400240200a0d00200c102821040c010b2003280254200a200c102c21040b2004450d032003200c36025820032004360254200c210a0b2003200b20066a220c36025c2004200b6a20112006109a051a02402010450d002011102a0b034002400240200a200c460d002003280254210a0c010b200a41016a220b200a490d28200a4101742204200b2004200b4b1b220b4100480d2802400240200a0d00200b1028210a0c010b2003280254200a200b102c210a0b200a450d052003200b3602582003200a3602540b2003200c41016a36025c200a200c6a200d41807f72200d41ff0071200d410776220b1b3a00000240200b450d002003280258210a200328025c210c200b210d0c010b0b4101211102402009450d002007210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d29200a410174220d200c200d200c4b1b220d4100480d2902400240200a0d00200d1028210c0c010b2003280254200a200d102c210c0b200c450d072003200d3602582003200c3602540b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2007490d002003280254210b0c010b200a20076a220c200a490d28200b410174220d200c200d200c4b1b220c4100480d2802400240200b0d00200c1028210b0c010b2003280254200b200c102c210b0b200b450d072003200c3602582003200b3602540b2003200a20076a36025c200b200a6a20092007109a051a410021112012450d002009102a0b200820134104746a21062013210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d28200a410174220d200c200d200c4b1b220d4100480d2802400240200a0d00200d1028210c0c010b2003280254200a200d102c210c0b200c450d082003200d3602582003200c3602540b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b2008210402402013450d00411021072008210403402004220b41106a2104200b280200220c4108460d01200b410c6a2802002102200b41086a280200210a200b280204210b024002400240024002400240024002400240200c0e080001020304050607000b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d31200c4101742205200d2005200d4b1b22054100480d3102400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d12200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41003a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d32200c4101742205200d2005200d4b1b22054100480d3202400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d14200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d32200b410174220d200c200d200c4b1b220d4100480d3202400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d152003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c080b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d30200c4101742205200d2005200d4b1b22054100480d3002400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d14200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41013a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d31200c4101742205200d2005200d4b1b22054100480d3102400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d16200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d31200b410174220d200c200d200c4b1b220d4100480d3102400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d172003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c070b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2f200c4101742205200d2005200d4b1b22054100480d2f02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d16200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41023a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d30200c4101742205200d2005200d4b1b22054100480d3002400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d18200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d30200b410174220d200c200d200c4b1b220d4100480d3002400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d192003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c060b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2e200c4101742205200d2005200d4b1b22054100480d2e02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d18200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41033a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2f200c4101742205200d2005200d4b1b22054100480d2f02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1a200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2f200b410174220d200c200d200c4b1b220d4100480d2f02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d1b2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10eb0420032d0000220a411f460d0420032f000120032d000341107472210d0c280b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2d200c4101742205200d2005200d4b1b22054100480d2d02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1a200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41043a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2e200c4101742205200d2005200d4b1b22054100480d2e02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1c200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2e200b410174220d200c200d200c4b1b220d4100480d2e02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d1d2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10eb0420032d0000220a411f460d0320032f000120032d000341107472210d0c270b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2c200c4101742205200d2005200d4b1b22054100480d2c02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1c200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41053a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2d200c4101742205200d2005200d4b1b22054100480d2d02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1e200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2d200b410174220d200c200d200c4b1b220d4100480d2d02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d1f2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10eb0420032d0000220a411f460d0220032f000120032d000341107472210d0c260b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2b200c4101742205200d2005200d4b1b22054100480d2b02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1e200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41063a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2c200c4101742205200d2005200d4b1b22054100480d2c02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d20200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2c200b410174220d200c200d200c4b1b220d4100480d2c02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d212003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c020b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2a200c4101742205200d2005200d4b1b22054100480d2a02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d20200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41073a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2b200c4101742205200d2005200d4b1b22054100480d2b02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d22200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2b200b410174220d200c200d200c4b1b220d4100480d2b02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d232003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b0b200741106a210720042006470d000b200621040b0240034020062004460d012004280200210a200441106a2104200a4108470d000b0b0240200f450d002008102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d28200a4101742206200c2006200c4b1b22064100480d2802400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d212004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d27200b410174220a200c200a200c4b1b220a4100480d2702400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d212004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021104101210d2009450d222011450d222012450d222009102a0c220b200c41011037000b200441011037000b200c41011037000b200b41011037000b200d41011037000b200c41011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200641011037000b200a41011037000b20032903082114200328020421042013410474210c02400340200c2007460d01200820076a210b200741106a2107200b2802004108470d000b0b0240200f450d002008102a0b02402003280258450d002003280254102a0b02402009450d002011450d002012450d002009102a0b200a411f470d17410021104101210d0b4101210b4101210c410121044101210641012105410121074101210241012112410121084101210941012113410121110c3a0b2001412c6a280200210e200141286a2802002115200141246a2802002111200141206a28020021162001411c6a2802002117200141186a2802002118200141146a28020021102001410c6a2902002114200141086a2802002119200141046a28020021120240024002400240024002400240024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d14200a410174220c200b200c200b4b1b220c4100480d1402400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b4101210d200241086a200a41016a36020041002109200b200a6a41003a0000024041041028220f450d00200f41eec2b5ab063600000240024002400240024020120d00410021044100211a0c010b410121074100210a410021062014a72209210b034002400240200a2006460d00200a21082006210c0c010b200a41016a220c200a490d1a200a410174220d200c200d200c4b1b22084100480d1a02400240200a0d002008102821070c010b2007200a2008102c21070b02402007450d00200a210c2008210a0c010b200841011037000b2007200c6a200b41807f72200b41ff0071200b410776220d1b3a0000200c41016a2106200d210b200d0d000b02400240024002400240200820066b20094f0d00200620096a220a2006490d1d2008410174220b200a200b200a4b1b220a4100480d1d0240024020080d00200a102821070c010b20072008200a102c21070b2007450d01200a21080b200720066a20122009109a051a02402019450d002012102a0b41011028220d450d07200d41003a0000410221054101210a41012104200620096a2213210b03400240200a2004470d002005200a41016a2204200520044b1b22044100480d1e200d200a2004102c220d450d080b200d200a6a200b41807f72200b41ff0071200b41077622061b3a0000200541026a2105200a41016a210a2006210b20060d000b2004200a6b20134f0d03200a20136a220b200a490d1c20044101742205200b2005200b4b1b220b4100480d1c20040d01200b1028210d0c020b200a41011037000b200d2004200b102c210d0b200d450d02200b21040b200d200a6a20072013109a051a4101211a2009200c6a200a6a41016a21092008450d002007102a0b0240024002400240024020100d004101211b0c010b4100211b20034100360240200342013703382003410c6a2017360200200341086a201836020020032010360204200320144220883e0200200341d0006a2003200341386a10f104024020032d00502213411f460d0020032f005120032d0053411074722108200341d0006a41086a290300211420032802542116200328023c0d140c150b024020042009470d00200941016a220a2009490d1c2009410174220b200a200b200a4b1b22044100480d1c0240024020090d0020041028210d0c010b200d20092004102c210d0b200d450d040b200d20096a41013a0000200941016a210a200941017441026a210c20032802402206210b03400240200a2004470d00200a41016a2204200a490d1d200c2004200c20044b1b22044100480d1d02400240200a0d0020041028210d0c010b200d200a2004102c210d0b200d450d040b200d200a6a200b41807f72200b41ff0071200b41077622051b3a0000200c41026a210c200a41016a210a2005210b20050d000b2003280238210b02402004200a6b20064f0d00200a20066a220c200a490d1c20044101742205200c2005200c4b1b220c4100480d1c0240024020040d00200c1028210d0c010b200d2004200c102c210d0b200d450d02200c21040b200d200a6a200b2006109a051a0240200328023c450d00200b102a0b2006200a6a21094100211b0b024020110d00410021050c0e0b2003410036024020034201370338410121064100210c4100210a2016210b024003400240200a200c470d00200c41016a2205200c490d1d200c41017422072005200720054b1b22054100480d1d02400240200c0d002005102821060c010b2006200c2005102c21060b2006450d022003200536023c200320063602382005210c0b2003200a41016a22073602402006200a6a200b41807f72200b41ff0071200b41077622051b3a00002007210a2005210b20050d000b2011200e4104746a21080240200e0d00201121050c0c0b201121052016450d0b200841706a211c4100210a2011211d0340201d210502400340200541046a28020022130d01200a41016a210a2008200541106a2205470d000c0f0b0b200541106a211d200a41016a211e2016417f6a2116200541086a29020021142005280200211f200328023c210c2003280240210b02400240034002400240200b200c460d00200328023821060c010b200c41016a2206200c490d20200c41017422072006200720064b1b22074100480d2002400240200c0d002007102821060c010b2003280238200c2007102c21060b2006450d022003200736023c200320063602382007210c0b2003200b41016a22073602402006200b6a200a41807f72200a41ff0071200a41077622061b3a00002007210b2006210a20060d000b20032014370308200320133602042003201f360200200341d0006a2003200341386a10f10420032d00502213411f460d010c0c0b200741011037000b201c2005460d0b201e210a20160d000c0b0b0b200541011037000b200c41011037000b200441011037000b200441011037000b200b41011037000b200441011037000b410141011037000b410441011037000b200c41011037000b20032d0053211d20032f0051211f20032802542116200329035821140240200841706a2005460d00200541106a210503402005220a41106a21050240200a2802042206450d00200a28020821070240200a410c6a280200220a450d00200a410c6c210b2006210a03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b2007450d002006102a0b20052008470d000b0b02402015450d002011102a0b2013411f460d03201f201d41107472210841012105200328023c450d0b2003280238102a0c0b0b200541106a21050b20052008460d0003402005220a41106a21050240200a2802042206450d00200a28020821070240200a410c6a280200220a450d00200a410c6c210b2006210a03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b2007450d002006102a0b20052008470d000b0b2015450d002011102a0b024020042009470d00200941016a220a2009490d0e2009410174220b200a200b200a4b1b22044100480d0e0240024020090d0020041028210d0c010b200d20092004102c210d0b200d450d020b200d20096a41023a0000200941016a210a200941017441026a210c20032802402206210b03400240200a2004470d00200a41016a2204200a490d0f200c2004200c20044b1b22044100480d0f02400240200a0d0020041028210d0c010b200d200a2004102c210d0b200d450d040b200d200a6a200b41807f72200b41ff0071200b41077622051b3a0000200c41026a210c200a41016a210a2005210b20050d000b2003280238210b02402004200a6b20064f0d00200a20066a220c200a490d0e20044101742205200c2005200c4b1b220c4100480d0e0240024020040d00200c1028210d0c010b200d2004200c102c210d0b200d450d04200c21040b200d200a6a200b2006109a051a0240200328023c450d00200b102a0b2006200a6a2109410121050b201a201245720d032019450d032012102a0c030b200441011037000b200441011037000b200c41011037000b02402010450d00201b4101730d0002402017450d002017410c6c210b2010210a03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b2018450d002010102a0b2011452005720d030240200e450d002011200e4104746a21072011210603402006220541106a210602402005280204220a450d0002402005410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200541086a280200450d002005280204102a0b20062007470d000b0b2015450d032011102a0c030b2003280238102a0b410021050b0240201a201245720d002019450d002012102a0b02402010450d00201b4101730d0002402017450d002017410c6c210b2010210a03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b2018450d002010102a0b02402005201145720d000240200e450d002011200e4104746a21072011210603402006220541106a210602402005280204220a450d0002402005410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200541086a280200450d002005280204102a0b20062007470d000b0b2015450d002011102a0b2013411f460d002008410874201372210a02402004450d00200d102a0b2000200a360200200041086a2014370200200041046a2016360200200f102a0c010b200341146a2009360200200341106a20043602002003200d36020c20034284808080c0003702042003200f360200200341d0006a2003200210f504200320032900513703382003200341d0006a41086a29000037003f20032d0050220a411f460d012000200a3a000020002003290338370001200041086a200329003f3700000b410021084101210d4101210c4101210b4101210441012105410121064101210741012102410121090c1f0b410021114101210d4101210b4101210c4101210441012106410121054101210741012102410121124101210841012109410121130c380b2001410c6a2802002105200141086a2802002107200141046a28020021060240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d04200a410174220c200b200c200b4b1b220c4100480d0402400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a410b3a0000200341c4006a41003602002003420137023c2003200236023820062005411c6c6a21114100210a4100210b2005210c0240034002400240200a200b460d00200328023c210a0c010b200a41016a220d200a490d06200a4101742204200d2004200d4b1b220d4100480d0602400240200a0d00200d1028210a0c010b200328023c200a200d102c210a0b200a450d022003200d3602402003200a36023c0b2003200b41016a360244200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210a2003280244210b200c210c0c010b0b2003201136025c2003200636025820032007360254200320063602502005450d02034020032006220a411c6a2206360258200a2802102207450d03200a410c6a2802002102200a41086a2802002108200a2802042105200a41146a2902002114200a280200210b024002400240024003400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d0b200a410174220d200c200d200c4b1b220d4100480d0b02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d022003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002400240024020050d00410121130c010b200320023602302003200836022c200320053602282003200341286a200341386a10e80420032d0000220a411f470d01410021130b2014a721092014422088a72204210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d0d200a410174220d200c200d200c4b1b220d4100480d0d02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d052003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280240220b2003280244220a6b2004490d00200328023c210b0c010b200a20046a220c200a490d0c200b410174220a200c200a200c4b1b220a4100480d0c02400240200b0d00200a1028210b0c010b200328023c200b200a102c210b0b200b450d052003200a3602402003200b36023c2003280244210a0b2003200a20046a360244200b200a6a20072004109a051a02402009450d002007102a0b2005450d0520130d010c050b20032d0003411074210b20032f0001210c200329030821202003280204210d02402014a7450d002007102a0b200c200b72210b200341d0006a10f60402402003280240450d00200328023c102a0b2000200b3b00012000200a3a0000200041036a200b4110763a0000200041086a2020370000200041046a200d360000410021024101210d4101210c4101210b410121044101210541012106410121070c250b02402002450d002002410474210b2005210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b2008450d032005102a0c030b200d41011037000b200d41011037000b200a41011037000b20062011470d000c030b0b200d41011037000b200c41011037000b200341d0006a10f60420032802402108200328023c21022003280238220441086a210d200441046a210520032802442207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d05200a4101742206200c2006200c4b1b22064100480d0502400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d04200b410174220a200c200a200c4b1b220a4100480d0402400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021134101210d4101210b4101210c4101210441012106410121054101210741012102410121124101210841012109410121110c390b200641011037000b200a41011037000b2001410c6a2802002106200141086a2802002107200141046a280200210d0240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d14200a410174220c200b200c200b4b1b220c4100480d1402400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a410a3a0000200341246a41003602002003420137021c20032002360218200d200641186c6a210f4100210a4100210b2006210c0240034002400240200a200b460d00200328021c210a0c010b200a41016a2204200a490d16200a41017422052004200520044b1b22044100480d1602400240200a0d0020041028210a0c010b200328021c200a2004102c210a0b200a450d02200320043602202003200a36021c0b2003200b41016a360224200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280220210a2003280224210b200c210c0c010b0b2003200f3602342003200d3602302003200736022c2003200d3602282006450d0220034101722102200341026a2107024003402003200d41186a2213360230200d2802002208450d04200d41146a2802002111200d41106a2802002110200d28020c2109200d280208210c200d28020421124100210b200341003602442003420137023c2008200c4103746a21062003200341186a3602384100210a02400240034002400240200b200a460d00200328023c210b0c010b200b41016a220a200b490d1a200b410174220d200a200d200a4b1b220a4100480d1a02400240200b0d00200a1028210b0c010b200328023c200b200a102c210b0b200b450d022003200a3602402003200b36023c2003280244210a0b2003200a41016a360244200b200a6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210b2003280244210a200c210c0c010b0b024020062008470d00200821040c020b2008210a0340200a41086a2104200a2902002214422088a7220a41ff01714104460d02200a41187441187521052014a7210b02400240024003400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d0d200a410174220d200c200d200c4b1b220d4100480d0d02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d022003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024020032802402003280244220a460d00200328023c210b0c030b200a41016a220b200a490d0b200a410174220c200b200c200b4b1b220c4100480d0b02400240200a0d00200c1028210b0c010b200328023c200a200c102c210b0b200b450d012003200c3602402003200b36023c2003280244210a0c020b200d41011037000b200c41011037000b2003200a41016a360244200b200a6a2005417f73220a413f7141c00072200a2005417f4a1b3a00002004210a20042006470d000b200621040c010b200a41011037000b0240034020062004460d0120042d0004210a200441086a2104200a4104470d000b0b02402012450d002008102a0b20092011410474220a6a210c0240024002400240024020110d002009210a0c010b200a41706a210d2009210a0340200a2d0000210b2007200a41036a2d00003a00002003200a41016a2f00003b01000240200b41ac01470d00200a41106a210a0c020b200341cc006a41026a20072d000022043a0000200320032f010022053b014c200a41046a2802002106200a41086a2903002114200220053b0000200241026a20043a00002003200b3a00002003201437030820032006360204200341d0006a2003200341386a10f004024020032d00502204411f46220b450d00200d41706a210d200a41106a220a200c470d010c030b0b20032d0053210520032f0051210620032802542108200329035821140240200d450d00200a41106a210a034002400240200a2d0000220d4109460d00200d41ac01470d010c030b0240200a41046a280200220d28020441ffffffff0371450d00200d280200102a0b200d102a0b200a41106a220a200c470d000b0b02402010450d002009102a0b02402003280240450d00200328023c102a0b200b0d022006200541107472210a200341286a10f70402402003280220450d00200328021c102a0b2000200a3b0001200020043a0000200041036a200a4110763a0000200041086a2014370000200041046a2008360000410021074101210d4101210c4101210b4101210441012105410121060c230b200a200c460d00034002400240200a2d0000220b4109460d00200b41ac01470d010c030b0240200a41046a280200220b28020441ffffffff0371450d00200b280200102a0b200b102a0b200a41106a220a200c470d000b0b02402010450d002009102a0b20032802402111200328023c21092003280238210c20032802442208210b034002400240200c41086a2205280200200c410c6a2204280200220a460d00200c280204210d0c010b200a41016a220d200a490d09200a4101742206200d2006200d4b1b22064100480d0902400240200a0d0020061028210d0c010b200c280204200a2006102c210d0b200d450d03200c200d360204200520063602002004280200210a0b2004200a41016a360200200d200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402005280200220b2004280200220a6b2008490d00200c280204210b0c010b200a20086a220d200a490d08200b410174220a200d200a200d4b1b220a4100480d0802400240200b0d00200a1028210b0c010b200c280204200b200a102c210b0b200b450d04200c200b3602042005200a3602002004280200210a0b2004200a20086a360200200b200a6a20092008109a051a2011450d002009102a0b2013210d2013200f470d010c050b0b200641011037000b200a41011037000b200441011037000b200c41011037000b200341286a10f70420032802202108200328021c21022003280218220441086a210d200441046a210520032802242207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d04200a4101742206200c2006200c4b1b22064100480d0402400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d03200b410174220a200c200a200c4b1b220a4100480d0302400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021094101210d4101210b4101210c410121044101210641012105410121074101210241012112410121080c280b200641011037000b200a41011037000b1031000b2001410c6a2802002105200141086a2802002106200141046a28020021080240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d12200a410174220c200b200c200b4b1b220c4100480d1202400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41093a0000200341c4006a41003602002003420137023c2003200236023820082005411c6c6a21124100210a4100210b2005210c0240034002400240200a200b460d00200328023c210a0c010b200a41016a220d200a490d14200a4101742204200d2004200d4b1b220d4100480d1402400240200a0d00200d1028210a0c010b200328023c200a200d102c210a0b200a450d022003200d3602402003200a36023c0b2003200b41016a360244200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210a2003280244210b200c210c0c010b0b2003201236025c2003200836025820032006360254200320083602502005450d02034020032008220a411c6a2208360258200a2802102206450d03200a410c6a2802002102200a41086a2802002109200a2802042107200a41146a2902002114200a280200210b024002400240024003400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d19200a410174220d200c200d200c4b1b220d4100480d1902400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d022003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002400240024020070d00410121110c010b200320023602302003200936022c200320073602282003200341286a200341386a10e80420032d0000220a411f470d01410021110b20062014422088a7220b4102746a21052014a7211303400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d1b200a410174220d200c200d200c4b1b220d4100480d1b02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d052003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024020052006460d002006210403402004280200210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d1d200a410174220d200c200d200c4b1b220d4100480d1d02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d082003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b200441046a22042005470d000b0b02402013450d002006102a0b2007450d0520110d010c050b20032d0003411074210b20032f0001210c200329030821202003280204210d02402014a7450d002006102a0b200c200b72210b200341d0006a10f80402402003280240450d00200328023c102a0b2000200b3b00012000200a3a0000200041036a200b4110763a0000200041086a2020370000200041046a200d360000410021064101210d4101210c4101210b41012104410121050c200b02402002450d002002410474210b2007210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b2009450d032007102a0c030b200d41011037000b200d41011037000b200d41011037000b20082012470d000c030b0b200d41011037000b200c41011037000b200341d0006a10f80420032802402108200328023c21022003280238220441086a210d200441046a210520032802442207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d13200a4101742206200c2006200c4b1b22064100480d1302400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d12200b410174220a200c200a200c4b1b220a4100480d1202400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021084101210d4101210b4101210c4101210441012106410121054101210741012102410121120c250b200641011037000b200a41011037000b200141046a280200210a024002400240024002400240200241046a280200200241086a280200220b460d002002280200210c0c010b200b41016a220c200b490d13200b410174220d200c200d200c4b1b220d4100480d1302400240200b0d00200d1028210c0c010b2002280200200b200d102c210c0b200c450d012002200c360200200241046a200d360200200241086a280200210b0b200241086a200b41016a360200200c200b6a410c3a00004100210c4100210b410021064101210503400240200b2006470d00200c200b41016a220d200c200d4b1b22064100480d1402400240200c0d002006102821050c010b2005200b2006102c21050b2005450d030b2005200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b200b417f6a2109200241086a2104200241046a2107200b210c03400240024020072802002004280200220a460d002002280200210d0c010b200a41016a220d200a490d14200a4101742208200d2008200d4b1b22084100480d1402400240200a0d0020081028210d0c010b2002280200200a2008102c210d0b200d450d042002200d360200200720083602002004280200210a0b2004200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b20094d0d002002280200210c0c010b200a200b6a220d200a490d13200c410174220a200d200a200d4b1b220a4100480d1302400240200c0d00200a1028210c0c010b2002280200200c200a102c210c0b200c450d042002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2005200b109a051a4101210d2006450d052005102a0c050b200d41011037000b200641011037000b200841011037000b200a41011037000b200141046a280200210a02400240200241046a280200200241086a280200220b460d002002280200210c0c010b200b41016a220c200b490d0e200b410174220d200c200d200c4b1b220d4100480d0e02400240200b0d00200d1028210c0c010b2002280200200b200d102c210c0b200c450d022002200c360200200241046a200d360200200241086a280200210b0b200241086a200b41016a360200200c200b6a41083a00004100210c4100210b410021064101210503400240200b2006470d00200c200b41016a220d200c200d4b1b22064100480d0f02400240200c0d002006102821050c010b2005200b2006102c21050b2005450d040b2005200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b200b417f6a2109200241086a2104200241046a2107200b210c03400240024020072802002004280200220a460d002002280200210d0c010b200a41016a220d200a490d0f200a4101742208200d2008200d4b1b22084100480d0f02400240200a0d0020081028210d0c010b2002280200200a2008102c210d0b200d450d052002200d360200200720083602002004280200210a0b2004200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b20094d0d002002280200210c0c010b200a200b6a220d200a490d0e200c410174220a200d200a200d4b1b220a4100480d0e02400240200c0d00200a1028210c0c010b2002280200200c200a102c210c0b200c450d052002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2005200b109a051a4101210d2006450d002005102a0b4101210b4101210c0c190b200d41011037000b200641011037000b200841011037000b200a41011037000b2001410c6a2802002106200141086a280200210f200141046a28020021100240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d10200a410174220c200b200c200b4b1b220c4100480d1002400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41073a00002010200641146c6a2112410021044100210a4100210c4101210b2006210d03400240200a200c470d002004200a41016a220c2004200c4b1b220c4100480d110240024020040d00200c1028210b0c010b200b200a200c102c210b0b200b450d030b200b200a6a200d41807f72200d41ff0071200d41077622051b3a0000200441026a2104200a41016a210a2005210d20050d000b024020060d00201021080c070b201021040340200441146a2108200428020c22134104460d072004280204211120042802002109200a4101742105200441106a280200210d20042802082207210403400240200a200c470d00200a41016a220c200a490d122005200c2005200c4b1b220c4100480d1202400240200a0d00200c1028210b0c010b200b200a200c102c210b0b200b450d050b200b200a6a200441807f72200441ff0071200441077622061b3a0000200541026a2105200a41016a210a2006210420060d000b02400240200c200a6b2007490d00200c21040c010b200a20076a2204200a490d11200c41017422052004200520044b1b22044100480d1102400240200c0d0020041028210b0c010b200b200c2004102c210b0b200b450d050b200b200a6a20092007109a051a200720046b200a6a210c02402011450d002009102a0b02400240200c450d002004210c0c010b200441016a220c2004490d1120044101742205200c2005200c4b1b220c4100480d110240024020040d00200c1028210b0c010b200b2004200c102c210b0b200b450d060b200b20076a200a6a20133a00002007200a6a41016a210a03400240200a200c470d00200a41016a220c200a490d12200a4101742204200c2004200c4b1b220c4100480d1202400240200a0d00200c1028210b0c010b200b200a200c102c210b0b200b450d080b200b200a6a200d41807f72200d41ff0071200d41077622041b3a0000200a41016a210a2004210d20040d000b2008210420082012470d000c080b0b200c41011037000b200c41011037000b200c41011037000b200441011037000b200c41011037000b200c41011037000b20082012460d0003402008410c6a2802004104460d010240200841046a280200450d002008280200102a0b200841146a22082012470d000b0b0240200f450d002010102a0b200241086a2106200241046a2107200a210402400240024003400240024020072802002006280200220d460d00200228020021050c010b200d41016a2205200d490d0c200d41017422082005200820054b1b22084100480d0c02400240200d0d002008102821050c010b2002280200200d2008102c21050b2005450d0220022005360200200720083602002006280200210d0b2006200d41016a3602002005200d6a200441807f72200441ff00712004410776220d1b3a0000200d2104200d0d000b02400240200241046a2802002204200241086a280200220d6b200a490d00200228020021040c010b200d200a6a2205200d490d0b2004410174220d2005200d20054b1b220d4100480d0b0240024020040d00200d102821040c010b20022802002004200d102c21040b2004450d0220022004360200200241046a200d360200200241086a280200210d0b200241086a200d200a6a3602002004200d6a200b200a109a051a410021124101210d200c450d02200b102a0c020b200841011037000b200d41011037000b4101210b4101210c41012104410121064101210541012107410121020c1a0b2001410c6a2802002105200141086a2802002112200141046a2802002108024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d0e200a410174220c200b200c200b4b1b220c4100480d0e02400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41063a0000200341dc006a41003602002003420137025420032002360250200820054104746a21134100210a4100210b2005210c034002400240200a200b460d002003280254210a0c010b200a41016a220d200a490d0f200a4101742204200d2004200d4b1b220d4100480d0f02400240200a0d00200d1028210a0c010b2003280254200a200d102c210a0b200a450d032003200d3602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280258210a200328025c210b200c210c0c010b0b200821042005450d05200541047421114100210c034002402008200c6a220b410d6a2d000022044102470d00200b41106a21040c070b200b2802002105200b41086a2802002106200b41046a2802002107200b410c6a2d00002102024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d0f200a4101742209200d2009200d4b1b22094100480d0f02400240200a0d0020091028210d0c010b2003280254200a2009102c210d0b200d450d04200320093602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a200241ff00733a0000024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d0f200a4101742202200d2002200d4b1b22024100480d0f02400240200a0d0020021028210d0c010b2003280254200a2002102c210d0b200d450d05200320023602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a20043a0000200320063602402003200736023c200320053602382003200341386a200341d0006a10e80420032d00002205411f470d052011200c41106a220c470d000c070b0b200c41011037000b200d41011037000b200941011037000b200241011037000b20032d0003210220032f0001210920032802042111200329030821140240200b41106a2013460d00200b41106a210403402004410d6a2d00004102460d01200428020421072004280200210602402004280208220a450d00200a410474210b2006210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441106a210402402007450d002006102a0b20042013470d000b0b2002411074210a02402012450d002008102a0b2009200a72210a02402003280258450d002003280254102a0b2000200a3b0001200020053a0000200041036a200a4110763a0000200041086a2014370000200041046a2011360000410021054101210d4101210c4101210b410121040c0f0b20042013460d0003402004410d6a2d00004102460d01200428020421062004280200210502402004280208220a450d00200a410474210b2005210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441106a210402402006450d002005102a0b20042013470d000b0b02402012450d002008102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d0a200a4101742206200c2006200c4b1b22064100480d0a02400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d09200b410174220a200c200a200c4b1b220a4100480d0902400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021024101210d4101210b4101210c410121044101210641012105410121070c1a0b200641011037000b200a41011037000b2001410c6a2802002107200141086a2802002108200141046a280200210602400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d09200a410174220c200b200c200b4b1b220c4100480d0902400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41053a0000200341d0006a410c6a4100360200200342013702542003200236025020062007410c6c6a2102410121044100210c4100210a2007210b03400240200a200c470d00200c41016a220d200c490d0a200c4101742205200d2005200d4b1b220d4100480d0a02400240200c0d00200d102821040c010b2004200c200d102c21040b2004450d04200d210c0b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200a41016a210a200d210b200d0d000b2003200c3602582003200a36025c200320043602542006210a2007450d012007410c6c210d4100210b0340024002402006200b6a220a41046a280200220c4102460d002003200a280200200c200a41086a280200200341d0006a10f20420032d00002204411f460d0120032f000120032d00034110747221052003290308211420032802042107200a410c6a210c200d200b6b41746a210a02400340200a450d01200a41746a210a200c280204210b200c410c6a210c200b4102470d000b0b02402008450d002006102a0b02402003280258450d002003280254102a0b200020053b0001200020043a0000200041036a20054110763a0000200041086a2014370000200041046a2007360000410021044101210d4101210c4101210b0c110b200a410c6a210a0c030b200d200b410c6a220b470d000b2002210a0c010b200c41011037000b200a410020076b410c6c6a210b024003402006200b460d01200b410c6a210b200a280204210c200a410c6a210a200c4102470d000b0b02402008450d002006102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d0a200a4101742206200c2006200c4b1b22064100480d0a02400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d09200b410174220a200c200a200c4b1b220a4100480d0902400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021074101210d4101210b4101210c4101210441012106410121050c190b200641011037000b200a41011037000b200d41011037000b2001410c6a2802002109200141086a2802002113200141046a2802002106024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d09200a410174220c200b200c200b4b1b220c4100480d0902400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41043a0000200341d0006a410c6a4100360200200342013702542003200236025020062009410c6c6a2111410121044100210c4100210a2009210b03400240200a200c470d00200c41016a220d200c490d0a200c4101742205200d2005200d4b1b220d4100480d0a02400240200c0d00200d102821040c010b2004200c200d102c21040b2004450d05200d210c0b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200a41016a210a200d210b200d0d000b2003200c3602582003200a36025c200320043602542006210a2009450d022009410c6c21084100210c03400240024002402006200c6a220b41046a28020022044102460d00200b2802002105200b41086a28020021072003280258200328025c220a460d012003280254210d0c020b200b410c6a210a0c050b200a41016a220d200a490d0a200a4101742202200d2002200d4b1b22024100480d0a02400240200a0d0020021028210d0c010b2003280254200a2002102c210d0b200d450d03200320023602582003200d3602540b2003200a41016a36025c200d200a6a41f0003a00002003200520042007200341d0006a10f204024020032d0000220d411f460d0020032f000120032d00034110747221042003290308211420032802042105200b410c6a210b2008200c6b41746a210a02400340200a450d01200a41746a210a200b280204210c200b410c6a210b200c4102470d000b0b02402013450d002006102a0b02402003280258450d002003280254102a0b200020043b00012000200d3a0000200041036a20044110763a0000200041086a2014370000200041046a20053600004100210b4101210d4101210c0c0f0b2008200c410c6a220c470d000b2011210a0c020b200c41011037000b200241011037000b200a410020096b410c6c6a210b024003402006200b460d01200b410c6a210b200a280204210c200a410c6a210a200c4102470d000b0b02402013450d002006102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d09200a4101742206200c2006200c4b1b22064100480d0902400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d08200b410174220a200c200a200c4b1b220a4100480d0802400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021054101210d4101210b4101210c41012104410121060c170b200641011037000b200a41011037000b200d41011037000b2001410c6a2802002106200141086a2802002109200141046a280200210802400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d0a200a410174220c200b200c200b4b1b220c4100480d0a02400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41033a0000200820064102746a21074100210c4100210a41002105410121042006210b03400240200a2005470d00200c200a41016a220d200c200d4b1b22054100480d0b02400240200c0d002005102821040c010b2004200a2005102c21040b2004450d030b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200c41026a210c200a41016a210a200d210b200d0d000b02402006450d00200821060340200a410174210c2006280200210b03400240200a2005470d00200a41016a220d200a490d0d200c200d200c200d4b1b22054100480d0d02400240200a0d002005102821040c010b2004200a2005102c21040b2004450d060b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200c41026a210c200a41016a210a200d210b200d0d000b200641046a22062007470d000b0b02402009450d002008102a0b200241086a2106200241046a2107200a210c03400240024020072802002006280200220b460d002002280200210d0c010b200b41016a220d200b490d0b200b4101742208200d2008200d4b1b22084100480d0b02400240200b0d0020081028210d0c010b2002280200200b2008102c210d0b200d450d052002200d360200200720083602002006280200210b0b2006200b41016a360200200d200b6a200c41807f72200c41ff0071200c410776220b1b3a0000200b210c200b0d000b02400240200241046a280200220c200241086a280200220b6b200a490d002002280200210c0c010b200b200a6a220d200b490d0a200c410174220b200d200b200d4b1b220b4100480d0a02400240200c0d00200b1028210c0c010b2002280200200c200b102c210c0b200c450d052002200c360200200241046a200b360200200241086a280200210b0b200241086a200b200a6a360200200c200b6a2004200a109a051a410021064101210d2005450d052004102a0c050b200c41011037000b200541011037000b200541011037000b200841011037000b200b41011037000b4101210b4101210c410121040c120b2001410c6a2802002106200141086a2802002117200141046a280200210e0240024002400240024002400240024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d14200a410174220c200b200c200b4b1b220c4100480d1402400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41023a0000200341dc006a41003602002003420137025420032002360250200e200641286c6a21094100210a4100210b2006210c034002400240200a200b460d002003280254210a0c010b200a41016a220d200a490d15200a4101742204200d2004200d4b1b220d4100480d1502400240200a0d00200d1028210a0c010b2003280254200a200d102c210a0b200a450d032003200d3602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280258210a200328025c210b200c210c0c010b0b200e21052006450d0f200e210503402005220a41286a2105200a2d001822134104460d10200a41206a2900002114200a411c6a2800002104200a411a6a2d0000210f200a41196a2c00002110200a41146a2802002106200a41106a2802002111200a28020c2102200a2802042112200a2802002108200a2802082207210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d16200a410174220d200c200d200c4b1b220d4100480d1602400240200a0d00200d1028210c0c010b2003280254200a200d102c210c0b200c450d052003200d3602582003200c360254200328025c210a0b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2007490d002003280254210b0c010b200a20076a220c200a490d15200b410174220a200c200a200c4b1b220a4100480d1502400240200b0d00200a1028210b0c010b2003280254200b200a102c210b0b200b450d052003200a3602582003200b360254200328025c210a0b2003200a20076a36025c200b200a6a20082007109a051a02402012450d002008102a0b2006210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d16200a410174220d200c200d200c4b1b220d4100480d1602400240200a0d00200d1028210c0c010b2003280254200a200d102c210c0b200c450d072003200d3602582003200c360254200328025c210a0b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2006490d002003280254210b0c010b200a20066a220c200a490d15200b410174220a200c200a200c4b1b220a4100480d1502400240200b0d00200a1028210b0c010b2003280254200b200a102c210b0b200b450d072003200a3602582003200b360254200328025c210a0b2003200a20066a36025c200b200a6a20022006109a051a02402011450d002002102a0b0240024002400240024020130e0400010203000b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d19200a410174220c200b200c200b4b1b220c4100480d1902400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0c2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41003a00000340024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d1a200a410174220c200b200c200b4b1b220c4100480d1a02400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0e2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a200441807f72200441ff00712004410776220a1b3a0000200a2104200a0d000c040b0b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d18200a410174220c200b200c200b4b1b220c4100480d1802400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0d2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41013a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d18200a410174220c200b200c200b4b1b220c4100480d1802400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0e2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41f0003a0000200320042014a72014422088a7200341d0006a10f20420032d0000220a411f460d0220032f000120032d000341107472210d0c120b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d17200a410174220c200b200c200b4b1b220c4100480d1702400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0e2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41023a0000200320042014a72014422088a7200341d0006a10f20420032d0000220a411f460d0120032f000120032d000341107472210d0c110b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d16200a410174220c200b200c200b4b1b220c4100480d1602400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0e2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41033a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d16200a410174220c200b200c200b4b1b220c4100480d1602400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0f2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a2010417f73220a413f7141c00072200a2010417f4a1b3a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d16200a410174220c200b200c200b4b1b220c4100480d1602400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d102003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a200f41ff01714100473a00000b20052009470d000c110b0b200c41011037000b200d41011037000b200d41011037000b200a41011037000b200d41011037000b200a41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b2003290308211420032802042104024020052009460d000340200541186a2d00004104460d01200541106a280200210b2005410c6a280200210c0240200541046a280200450d002005280200102a0b0240200b450d00200c102a0b200541286a22052009470d000b0b02402017450d00200e102a0b02402003280258450d002003280254102a0b2000200d3b00012000200a3a0000200041036a200d4110763a0000200041086a2014370000200041046a20043600004100210c4101210d0c080b20052009460d000340200541186a2d00004104460d01200541106a280200210a2005410c6a280200210b0240200541046a280200450d002005280200102a0b0240200a450d00200b102a0b200541286a22052009470d000b0b02402017450d00200e102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d06200a4101742206200c2006200c4b1b22064100480d0602400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d05200b410174220a200c200a200c4b1b220a4100480d0502400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021044101210d4101210b4101210c0c120b200641011037000b200a41011037000b20082010460d0003402008410d6a2d00004105460d010240200841046a280200450d002008280200102a0b200841106a22082010470d000b0b0240200e450d00200f102a0b200241086a2106200241046a2107200b210c0240024003400240024020072802002006280200220a460d002002280200210d0c010b200a41016a220d200a490d04200a4101742208200d2008200d4b1b22084100480d0402400240200a0d0020081028210d0c010b2002280200200a2008102c210d0b200d450d022002200d360200200720083602002006280200210a0b2006200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b200b490d002002280200210c0c010b200a200b6a220d200a490d03200c410174220a200d200a200d4b1b220a4100480d0302400240200c0d00200a1028210c0c010b2002280200200c200a102c210c0b200c450d022002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2004200b109a051a4100210c4101210d2005450d032004102a0c030b200841011037000b200a41011037000b1031000b4101210b0c0b0b2000200d3b00012000200a3a0000200041036a200d4110763a0000200041086a2014370000200041046a2004360000410021094101210d4101210c4101210b4101210441012105410121064101210741012102410121080c080b4101210c200241086a200a41016a3602004100210d200b200a6a41003a0000200341146a2004360200200341106a20053602002003200636020c200320073602082003200836020420032009360200200341d0006a2003200210f504200320032900513703382003200341d0006a41086a29000037003f20032d0050220a411f460d082000200a3a000020002003290338370001200041086a200329003f3700000b4101210b0b410121040b410121050b410121060b410121070b410121020b41012108410121090b20012d0000220a410f4b0d18200a0e100a0b0c0d0e0f101112181318141516170a0b4101210b4100210d4101210c0b410121040b410121060b410121050b410121070b410121020b410121120b410121080b410121090b41012113410121110c0f0b200141086a280200450d10200141046a280200102a0c100b200d450d0f0240200141086a280200450d00200141046a280200102a0b200141146a280200450d0f200141106a280200102a0c0f0b02402001410c6a280200220b450d00200141046a280200210a200b410474210b03400240200a41046a280200450d00200a280200102a0b200a41106a210a200b41706a220b0d000b0b200141086a280200450d0e2001280204102a0c0e0b200c450d0d02402001410c6a280200220b450d00200141046a280200210a200b41286c210b03400240200a41046a280200450d00200a280200102a0b0240200a41106a280200450d00200a410c6a280200102a0b200a41286a210a200b41586a220b0d000b0b200141086a280200450d0d2001280204102a0c0d0b200141086a280200450d0c200141046a280200102a0c0c0b200b450d0b200141086a280200450d0b200141046a280200102a0c0b0b2004450d0a200141086a280200450d0a200141046a280200102a0c0a0b2005450d0902402001410c6a280200220a450d00200141046a2802002204200a4104746a2105034002402004280208220b450d002004280200210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441106a210a0240200441046a280200450d002004280200102a0b200a2104200a2005470d000b0b200141086a280200450d092001280204102a0c090b02402001410c6a280200220b450d00200141046a280200210a200b41146c210b03400240200a41046a280200450d00200a280200102a0b200a41146a210a200b416c6a220b0d000b0b200141086a280200450d082001280204102a0c080b2006450d0702402001410c6a280200220a450d00200141046a2802002204200a411c6c6a2105034002402004280204220a450d0002402004410c6a280200220b450d00200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441086a280200450d002004280204102a0b2004411c6a210a0240200441146a280200450d002004280210102a0b200a2104200a2005470d000b0b200141086a280200450d072001280204102a0c070b2007450d0602402001410c6a280200220a450d00200141046a2802002204200a41186c6a210503400240200441046a280200450d002004280200102a0b0240200441146a280200220b450d00200428020c210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441186a210a0240200441106a280200450d00200428020c102a0b200a2104200a2005470d000b0b200141086a280200450d062001280204102a0c060b2002450d05200141046a220a10f904200141086a280200450d05200a280200102a0c050b2008450d040240200141046a280200220a450d00200141086a280200450d00200a102a0b0240200141146a280200220a450d0002402001411c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200141186a280200450d002001280214102a0b200141246a2802002204450d0402402001412c6a280200220a450d002004200a4104746a210503402004220d41106a21040240200d280204220a450d000240200d410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200d41086a280200450d00200d280204102a0b20042005470d000b0b200141286a280200450d042001280224102a0c040b2009450d030240200141086a280200450d00200141046a280200102a0b0240200141146a280200220a450d00200141186a280200450d00200a102a0b200141246a280200450d03200141206a280200102a0c030b20011082040c020b410121100b2000411f3a0000024020012d0000220a410f4b0d0002400240024002400240024002400240024002400240024002400240200a0e100001020304050607080e090e0a0b0c0d000b200b450d0e200141086a280200450d0e200141046a280200102a0c0e0b200d450d0d0240200141086a280200450d00200141046a280200102a0b200141146a280200450d0d200141106a280200102a0c0d0b200c450d0c02402001410c6a280200220b450d00200141046a280200210a200b410474210b03400240200a41046a280200450d00200a280200102a0b200a41106a210a200b41706a220b0d000b0b200141086a280200450d0c2001280204102a0c0c0b2004450d0b02402001410c6a280200220b450d00200141046a280200210a200b41286c210b03400240200a41046a280200450d00200a280200102a0b0240200a41106a280200450d00200a410c6a280200102a0b200a41286a210a200b41586a220b0d000b0b200141086a280200450d0b2001280204102a0c0b0b2006450d0a200141086a280200450d0a200141046a280200102a0c0a0b2005450d09200141086a280200450d09200141046a280200102a0c090b2007450d08200141086a280200450d08200141046a280200102a0c080b2002450d0702402001410c6a280200220a450d00200141046a2802002204200a4104746a2105034002402004280208220b450d002004280200210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441106a210a0240200441046a280200450d002004280200102a0b200a2104200a2005470d000b0b200141086a280200450d072001280204102a0c070b2012450d0602402001410c6a280200220b450d00200141046a280200210a200b41146c210b03400240200a41046a280200450d00200a280200102a0b200a41146a210a200b416c6a220b0d000b0b200141086a280200450d062001280204102a0c060b2008450d0502402001410c6a280200220a450d00200141046a2802002204200a411c6c6a2105034002402004280204220a450d0002402004410c6a280200220b450d00200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441086a280200450d002004280204102a0b2004411c6a210a0240200441146a280200450d002004280210102a0b200a2104200a2005470d000b0b200141086a280200450d052001280204102a0c050b2009450d0402402001410c6a280200220a450d00200141046a2802002204200a41186c6a210503400240200441046a280200450d002004280200102a0b0240200441146a280200220b450d00200428020c210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441186a210a0240200441106a280200450d00200428020c102a0b200a2104200a2005470d000b0b200141086a280200450d042001280204102a0c040b2013450d03200141046a220a10f904200141086a280200450d03200a280200102a0c030b2011450d020240200141046a280200220a450d00200141086a280200450d00200a102a0b0240200141146a280200220a450d0002402001411c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200141186a280200450d002001280214102a0b200141246a2802002204450d0202402001412c6a280200220a450d002004200a4104746a210503402004220d41106a21040240200d280204220a450d000240200d410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200d41086a280200450d00200d280204102a0b20042005470d000b0b200141286a280200450d022001280224102a0c020b2010450d010240200141086a280200450d00200141046a280200102a0b0240200141146a280200220a450d00200141186a280200450d00200a102a0b200141246a280200450d01200141206a280200102a0c010b20011082040b200341e0006a24000bb309010a7f230041b0016b2202240041002103024020012802102204450d0020012802082205200128020c460d00200128021421062001200541246a360208200241c4006a41026a2207200541036a2d00003a0000200241286a41086a2208200541106a290000370300200241286a41106a2209200541186a290000370300200241286a41186a220a200541206a280000360200200220052f00013b01442002200541086a29000037032820052d0000220b4102460d00200541046a280000210520012004417f6a360210200241086a41026a20072d00003a000020024190016a41086a200829030037030020024190016a41106a200929030037030020024190016a41186a200a280200360200200220022f01443b01082002200229032837039001024002400240200b4101460d002002418c016a41026a200241086a41026a2d00003a0000200241f0006a41086a20024190016a41086a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41186a20024190016a41186a2d00003a0000200220022f01083b018c0120022002290390013703700c010b200241c8006a200541067610fe01200228024821040240024020022802502005413f7122014b0d00410021010c010b2002418c016a41026a200420014105746a220141026a2d00003a0000200241f8006a2001410f6a29000037030020024180016a200141176a29000037030020024188016a2001411f6a2d00003a0000200220012f00003b018c012002200129000737037020012800032105410121010b0240200228024c450d002004102a0b20010d00410121010c010b200241ec006a41026a2002418c016a41026a2d00003a000020024190016a41086a200241f0006a41086a29030037030020024190016a41106a200241f0006a41106a29030037030020024190016a41186a200241f0006a41186a2d00003a0000200220022f018c013b016c2002200229037037039001410021010b200241e8006a41026a2204200241ec006a41026a2d00003a0000200241c8006a41086a220720024190016a41086a290300370300200241c8006a41106a220820024190016a41106a290300370300200241c8006a41186a220920024190016a41186a2d00003a0000200220022f016c3b016820022002290390013703480240024020010d002002418c016a41026a20042d00003a0000200241f0006a41086a2007290300370300200241f0006a41106a2008290300370300200241f0006a41186a20092d00003a0000200220022f01683b018c0120022002290348370370410121010c010b200641013a0000410021010b200241246a41026a22042002418c016a41026a2d00003a0000200241086a41086a2207200241f0006a41086a290300370300200241086a41106a2208200241f0006a41106a290300370300200241086a41186a2209200241f0006a41186a2d00003a0000200220022f018c013b0124200220022903703703082001450d00200020022f01243b0001200041046a2005360000200041086a2002290308370000200041036a20042d00003a0000200041106a2007290300370000200041186a2008290300370000200041206a20092d00003a0000410121030b200020033a0000200241b0016a24000bd50505067f017e047f017e027f23004180026b22022400024002400240024002402000280200220320002802044f0d00200028020c2104200141086a2105200241a0016a4102722106024003402000200341016a360200200241186a20002802082802002207109b0220022d00184101460d0120022900192108200241086a2007106c20022802080d012007280204200228020c2203490d012003417f4c0d0302400240024020030d00410121090c010b2003102e2209450d0820072802042003490d01200920072802002003109a051a2007280204220a2003490d062007200a20036b3602042007200728020020036a3602000b20022008370310024002402001280200220b41f8b9c000460d002001280204210c0c010b2006410041da001099051a200241186a41004184011099051a41e4011028220b450d074100210c200b4100360200200b41046a200241a0016a41dc00109a051a200b41e0006a200241186a418401109a051a200141003602042001200b3602000b2003ad220d422086200d84210d024002400340200b41086a2107200b2f0106220e41037421034100210a024003402003450d01200241106a20074108109c05220f450d03200341786a2103200a41016a210a200741086a2107200f417f4a0d000b200a417f6a210e0b0240200c450d00200c417f6a210c200b200e4102746a41e4016a280200210b0c010b0b2002200837022c200220053602282002200e360224200220013602202002200b36021c200241003602182002200d3702a401200220093602a001200241186a200241a0016a10bb020c010b200b200a410c6c6a220341e4006a2207280200210a2007200d370200200341e0006a22072802002103200720093602002003450d00200a450d002003102a0b200028020022032000280204490d010c030b0b2009102a0b200441013a00000b20024180026a24000f0b1036000b2003200a1044000b41e40141041037000b200341011037000bfd0e03047f027e087f230041206b2202240002400240024002400240024002400240024002400240024002400240024041a20210282203450d00200241a20236020420022003360200200341003b0000200241023602080240024020012903684202520d00024020022802044102470d00200228020041024104102c2203450d0420024104360204200220033602000b200228020041033a00022002200228020841016a3602080c010b024020022802044102470d00200228020041024104102c2203450d0420024104360204200220033602000b20022802004183013a00022002200228020841016a3602082001200210a60120022002360210200141246a200241106a10fa020240024020012903684201510d0002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102821040c010b200228020020032005102c21040b2004450d072002200536020420022004360200200228020821030b2002200341016a360208200420036a41003a00000c010b200141f8006a29030020012903702206420c882207420120074201561b8021070240024020022802042204200228020822036b4102490d00200228020021040c010b200341026a22052003490d11200441017422032005200320054b1b22034100480d110240024020040d002003102821040c010b200228020020042003102c21040b2004450d072002200336020420022004360200200228020821030b2002200341026a360208200420036a2007a741047420067aa7417f6a22034101200341014b1b2203410f2003410f491b723b00000b20014190016a200210a001200220014180016a360210200241106a200210a3010b20014198016a200210eb012002280208210120024100360218200242013703102001417e6a200241106a10b4012002280208220341014d0d052002280218210520022802142108200228021021092002410036020820022802002101024002402003417e6a220a450d004102210b2005450d0d200120092d00003a00004101210c2002200228020841016a36020820054101460d0d200920056a210d200120092d00013a00012002200228020841016a3602084102210b200941026a21042005417e6a220e0d014100210e0c0b0b0240024002402002280204220320054f0d00200341017422042005200420054b1b22044100480d120240024020030d002004102821010c010b200120032004102c21010b2001450d0a20022004360204200220013602002002280208210b0c010b4100210b2005450d010b2001200b6a220320092d00003a0000024020054101470d00200b41016a210b0c010b2005417f6a2104200941016a2101200341016a21030340200320012d00003a0000200341016a2103200141016a21012004417f6a22040d000b200b20056a210b0b2002200b3602084102210b0c0b0b024002402002280204220120036b200e490d00200228020021010c010b2003200e6a220b2003490d0f20014101742203200b2003200b4b1b22034100480d0f0240024020010d002003102821010c010b200228020020012003102c21010b2001450d0820022003360204200220013602000b200120056a200141026a200a109b051a0240200520022802082201460d00200520016b210b2005417e6a2103200228020020016a210c410021010340024020032001470d002005210b0c0d0b200c20016a20042d00003a00002002200228020841016a360208200441016a2104200b200141016a2201470d000b200d20046b220e0d004100210e4101210c0c090b200e4100480d0e200e1028220c0d08200e41011037000b41a20241011037000b410441011037000b410441011037000b200541011037000b200341011037000b41e4e8c5001032000b200441011037000b200341011037000b2005210b0b0240200d2004460d00200c20042d00003a00004101210f02400240200441016a2201200d470d00200c41016a21050c010b200c41016a21032009200520046b6a21040340200320012d00003a0000200341016a2103200d200141016a2201470d000b2004450d01200c20046a21052004210f0b0240024020022802042201200a200b6a22036b200f490d00200228020021010c010b2003200f6a22042003490d06200141017422032004200320044b1b22034100480d060240024020010d002003102821010c010b200228020020012003102c21010b2001450d0520022003360204200220013602000b2001200b200f6a220d6a2001200b6a200a109b051a0240200d20022802082201460d00200228020020016a2103200b200f6a20016b2104200c2101034020052001460d01200320012d00003a00002002200228020841016a360208200141016a2101200341016a21032004417f6a22040d000b0b200d210b0b200e450d00200c102a0b200a450d010b0240200b20022802082201460d002002280200220320016a2003200b6a200a109b051a0b2002200a20016a3602080b02402008450d002009102a0b20002002290300370200200041086a200241086a280200360200200241206a24000f0b200341011037000b1031000b130020004103360204200041889fc4003602000b340020004196a6c40036020420004100360200200041146a4101360200200041106a419ca6c400360200200041086a42043702000b4001017f230041206b22022400200241186a4200370300200241106a4200370300200241086a42003703002002420037030020002002108b04200241206a24000bde0301017f024002400240024002400240410110282202450d00200220012d00003a0000200241014102102c2202450d01200220012d00013a0001200241024104102c2202450d02200220012d00023a0002200220012d00033a0003200241044108102c2202450d03200220012d00043a0004200220012d00053a0005200220012d00063a0006200220012d00073a0007200241084110102c2202450d04200220012d00083a0008200220012d00093a0009200220012d000a3a000a200220012d000b3a000b200220012d000c3a000c200220012d000d3a000d200220012d000e3a000e200220012d000f3a000f200241104120102c2202450d05200220012d00103a0010200220012d00113a0011200220012d00123a0012200220012d00133a0013200220012d00143a0014200220012d00153a0015200220012d00163a0016200220012d00173a0017200220012d00183a0018200220012d00193a0019200220012d001a3a001a200220012d001b3a001b200220012d001c3a001c200220012d001d3a001d200220012d001e3a001e200220012d001f3a001f200042a08080808004370204200020023602000f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000bb31102077f027e230041106b2202240020024100360208200242013703004104200210b4010240024002400240024002400240024002400240024002400240024002400240024020022802042203200228020822046b4104490d00200441046a2105200228020021030c010b200441046a22052004490d0f200341017422062005200620054b1b22064100480d0f0240024020030d002006102821030c010b200228020020032006102c21030b2003450d0120022006360204200220033602000b20022005360208200320046a41eede91ab06360000410e200210b4010240024020022802042203200228020822066b410e490d002006410e6a2104200228020021050c010b2006410e6a22042006490d0f200341017422052004200520044b1b22074100480d0f0240024020030d002007102821050c010b200228020020032007102c21050b2005450d022002200736020420022005360200200721030b20022004360208200520066a220641002900e4c740370000200641066a41002900eac7403700000240200320046b41034b0d00200441046a22062004490d0f200341017422072006200720064b1b22064100480d0f0240024020030d002006102821050c010b200520032006102c21050b2005450d0320022006360204200220053602000b2002200441046a360208200520046a410a3600000240024020022802042205200228020822046b4104490d00200228020021050c010b200441046a22032004490d0f200541017422062003200620034b1b22034100480d0f0240024020050d002003102821050c010b200228020020052003102c21050b2005450d0420022003360204200220053602000b2002200441046a360208200520046a41a3013600000240024020022802042205200228020822046b4104490d00200228020021050c010b200441046a22032004490d0f200541017422062003200620034b1b22034100480d0f0240024020050d002003102821050c010b200228020020052003102c21050b2005450d0520022003360204200220053602000b2002200441046a360208200520046a41a301360000410b200210b40141f4c7c0002104034002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0720022006360204200220033602000b2002200541016a360208200320056a20042d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0820022006360204200220033602000b2002200541016a360208200320056a200441016a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0920022006360204200220033602000b2002200541016a360208200320056a200441026a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0a20022006360204200220033602000b2002200541016a360208200320056a200441036a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0b20022006360204200220033602000b2002200541016a360208200320056a200441046a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0c20022006360204200220033602000b2002200541016a360208200320056a200441056a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0d20022006360204200220033602000b2002200541016a360208200320056a200441066a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0e20022006360204200220033602000b2002200541016a360208200320056a200441076a2d00003a0000200441086a28020021060240024020022802042203200228020822056b4104490d00200228020021030c010b200541046a22072005490d10200341017422082007200820074b1b22074100480d100240024020030d002007102821030c010b200228020020032007102c21030b2003450d0f20022007360204200220033602000b2002200541046a360208200320056a20063600002004410c6a220441f8c8c000470d000b200235020821092002350200210a200241106a2400200a2009422086840f0b200641011037000b200741011037000b200641011037000b200341011037000b200341011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200741011037000b1031000b961b04057f017e037f017e230041800a6b22022400024002402001450d00200220003602180c010b200241013602180b2002200136021c200241e0076a200241186a107f024020022802e4072203450d00200241e0076a410c6a280200210120022802e807210420022802e0072100200241b0046a200241e0076a41106a41e000109a051a200241e0076a200241186a1079024020022802e007450d0020024180036a41086a2205200241e0076a41086a280200360200200220022903e00737038003200241e0076a200241b0046a41e000109a051a200241306a200241e0076a41e000109a051a200241206a41086a22062005280200360200200220022903800337032020024190016a410c6a200136020020024190016a41086a20043602002002200336029401200220003602900120024190016a41106a200241306a41e000109a05210120024188026a2006280200360200200220022903203703800220024190016a10c703024002402002280290012200450d00200241e0076a2000417f6a10f701200241e0076a20014120109c050d000240024020024188026a28020022030d004100210341042104410021010c010b024002402003ad420c7e2207422088a70d002007a722014100480d0020022802800221002001102822040d01200141041037000b1031000b200341a0026c210520034105742106200421010340200241e0076a2000108704200141086a200241e0076a41086a280200360200200120022903e0073702002001410c6a2101200041a0026a2100200541e07d6a22050d000b200641606a41057641016a21010b200220013602b804200220033602b404200220043602b004200241e0076a200241b0046a108e040240200241e0016a2201200241e0076a4120109c05450d004190fac500410e100b200141201019200241e0076a412010190b02402001200241e0076a4120109c050d0020024184026a28020021082002280280022109200228028802210520024190026a20024190016a41f000109a051a2009200541a0026c6a2100200228029002210a20092101024002402005450d00200241b0046a41f0006a21042009210102400340200241f8066a200141e800109a051a200141e8006a290300210720024180036a200141f0006a41b001109a051a20074203510d01200241b0046a200241f8066a41e800109a051a2002200737039805200420024180036a41b001109a051a200241e0076a200241b0046a10870420022802e8072105024020022802e407450d0020022802e007102a0b200241e0076a200241b0046a41a002109a051a200241003602e006200241d0066a200241e0076a2005200241e0066a10d00320022d00d0064101460d03024020022d00dc0622054102460d0020023100de06210720023100dd06210b20022802d806210620022802d406210341f19ec600410d100b02402005450d00200b100c0b2007100c2003450d0020032006100b0b200141a0026a22012000470d000b200021010c010b200141a0026a21010b20012000460d03200241f8086a2105200241e0076a41f0006a2103034020024180036a200141e800109a051a200141e8006a2903002107200241e0076a200141f0006a41b001109a051a20074203510d04200241f8066a20024180036a41e800109a051a200241b0046a200241e0076a41b001109a051a200241e0076a200241f8066a41e800109a051a200220073703c8082003200241b0046a41b001109a051a2005106a200141a0026a22012000470d000c040b0b200241106a20022f00d10620022d00d3064110747210d30320022903102107200241ec076a42c4808080d01b370200200241323602f407200241b8b9c3003602e807200220073703e007200241e0076a1032000b41a0b9c3001032000b4188b9c3001032000b02402008450d002009102a0b200241086a10e403200228020c210120022802082100200241e0076a41086a22054200370300200242003703e00741f99fc6004115200241e0076a1008200241b0046a41086a2005290300370300200220022903e0073703b00420022001410020001b3602e007200241b0046a4110200241e0076a41041007200a109e03200241e0076a10b203200220024190026a410c6a28020022033602f00620022802940221062002200241e0076a410c6a28020022013602f406024020032001470d0002402003450d0020022802e407210941002105034002400240024002400240024002400240200620056a22012d00002204200920056a22002d0000470d000240024002400240024020040e050001020304000b20012000460d09200141016a200041016a4120109c050d040c090b024020012000460d00200141016a280000200041016a280000470d040b200141106a2802002204200041106a280200470d03200141086a2802002208200041086a280200220a460d072008200a2004109c050d030c070b024020012000460d00200141016a280000200041016a280000470d030b200141106a2802002204200041106a280200470d02200141086a2802002208200041086a280200220a460d052008200a2004109c050d020c050b024020012000460d00200141016a280000200041016a280000470d020b200141106a2802002204200041106a280200470d01200141086a2802002208200041086a280200220a460d032008200a2004109c050d010c030b2001410c6a28020022042000410c6a280200470d00200141046a2802002208200041046a280200220a460d012008200a2004109c05450d010b41df86c2004114100b200241b0046a200110ec0120022802b004220420022802b8041019024020022802b404450d002004102a0b200241b0046a200010ec0120022802b004220420022802b8041019024020022802b404450d002004102a0b20012d000020002d00002204470d0520040e050403020100040b2001410c6a28020022042000410c6a280200470d04200141046a2802002201200041046a2802002200460d05200120002004109c050d040c050b024020012000460d00200141016a280000200041016a280000470d040b200141106a2802002204200041106a280200470d03200141086a2802002201200041086a2802002200460d04200120002004109c05450d040c030b024020012000460d00200141016a280000200041016a280000470d030b200141106a2802002204200041106a280200470d02200141086a2802002201200041086a2802002200460d03200120002004109c050d020c030b024020012000460d00200141016a280000200041016a280000470d020b200141106a2802002204200041106a280200470d01200141086a2802002201200041086a2802002200460d02200120002004109c050d010c020b20012000460d01200141016a200041016a4120109c05450d010b4194bac3001032000b200541246a21052003417f6a22030d000b0b024020024190026a41306a2201200241e0076a41306a22004120109c05450d004190fac500410e100b2001412010192000412010190b0240200120004120109c05450d0041acbac3001032000b024020022802ec072200450d0020022802e4072101200041246c210003400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b0240200241e8076a280200450d0020022802e407102a0b0240200228029c022200450d002002280294022101200041246c210003400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b024020024198026a280200450d00200228029402102a0b200241800a6a240042010f0b20024180036a41146a410836020020024180036a410c6a4125360200200241f8066a41146a4103360200200242033702fc06200241c8afc6003602f80620024125360284032002200241f0066a3602e0062002200241f4066a3602d006200242043703c004200242013702b404200241fcb9c3003602b004200220024180036a360288072002200241b0046a360290032002200241d0066a360288032002200241e0066a36028003200241f8066a4184bac300103e000b02402001450d00200141246c21002003210103400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b2004450d002003102a0b200241f4076a4102360200200241bc046a4104360200200242023702e407200241bca7c4003602e007200241043602b404200241b4a7c4003602b0042002410036028403200241b8aec600360280032002200241b0046a3602f007200220024180036a3602b804200241e0076a41cca7c400103e000b8d05030b7f017e037f230041206b220224002001280200220320012802082204410c6c6a21052001280204210602400240024020040d00410421074100210841012109410021014100210a200321040c010b41012109410021084100210441042107410021014100210a2003210b0240024003400240200b280200220c0d00200b410c6a21040c040b024002400240200820046b200b41046a290200220d422088a7220e490d002004200e6a210f0c010b2004200e6a220f2004490d0420084101742210200f2010200f4b1b22104100480d040240024020080d002010102821090c010b200920082010102c21090b2009450d01201021080b200920046a200c200e109a051a02400240200a2001460d0020012110200a21010c010b200141016a22042001490d04200141017422102004201020044b1b221041ffffffff03712010470d04201041027422044100480d040240024020010d002004102821070c010b200720014102742004102c21070b2007450d030b200720014102746a200e3602000240200da7450d00200c102a0b200a41016a210a200f210420102101200b410c6a220b2005470d010c050b0b201041011037000b200441041037000b1031000b024020042005460d0003402004280200220b450d010240200441046a280200450d00200b102a0b2004410c6a22042005470d000b0b200121100b02402006450d002003102a0b200241186a22014200370300200241106a22044200370300200241086a220b42003703002002420037030020092007200a20021023200041186a2001290300370000200041106a2004290300370000200041086a200b2903003700002000200229030037000002402010450d002007102a0b02402008450d002009102a0b200241206a24000ba10301027f23004180026b22022400024002402001450d00200220003602000c010b200241013602000b20022001360204200241f8006a2002107f0240200228027c450d00200241086a200241f8006a41f000109a051a200241086a10c7030240200241086a410c6a2802002200450d00200228020c2101200041246c210003400240024020012d0000220341034b0d0002400240024020030e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b0240200241106a280200450d00200228020c102a0b20024180026a240042010f0b200241f4016a41043602002002411c6a41023602002002420237020c200241bca7c400360208200241043602ec01200241c8a8c4003602e801200241003602fc01200241b8aec6003602f8012002200241e8016a3602182002200241f8016a3602f001200241086a41cca7c400103e000be328010b7f230041d0006b220224002002410036022820024201370320024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240410410282203450d0020024284808080c00037022420022003360220200341edcad18b0636000002400240200228022420022802282203460d00200228022021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0220022005360224200220043602200b2002200341016a360228200420036a41073a00004115200241206a10b40141accbc000210603402006280204210720062802082203200241206a10b4010240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d1c200541017422042008200420084b1b22044100480d1c0240024020050d002004102821050c010b200228022020052004102c21050b2005450d042002200436022420022005360220200228022821040b2002200420036a360228200520046a20072003109a051a200228022421042002280228210302400240200628020c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102821040c010b200228022020032005102c21040b2004450d072002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102821040c010b200228022020032005102c21040b2004450d072002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628020c4101460d00200241306a20062802101103002002280234210720022802382203200241206a10b4010240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d1e200541017422042008200420084b1b22044100480d1e0240024020050d002004102821050c010b200228022020052004102c21050b2005450d092002200436022420022005360220200228022821040b2002200420036a360228200520046a20072003109a051a200228024021050240200228023c4101460d0020052002280244200241206a1091040c020b200520022802482203200241206a10910402402003450d00200341d8006c21074100210403400240200520046a220341346a280200450d002003413c6a280200450d00200341386a280200102a0b0240200341c4006a280200450d00200341cc006a280200450d00200341c8006a280200102a0b2007200441d8006a2204470d000b0b2002280244450d012005102a0c010b2006280214210720062802182203200241206a10b4010240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d1d200541017422042008200420084b1b22044100480d1d0240024020050d002004102821050c010b200228022020052004102c21050b2005450d092002200436022420022005360220200228022821040b2002200420036a360228200520046a20072003109a051a200628022021030240200628021c4101460d002003200641246a280200200241206a1091040c010b20032006280228200241206a1091040b200228022421042002280228210302400240200628022c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0b2002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0b2002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628022c4101460d00200241186a200628023011030020022802182104200228021c2203200241206a10b4012003450d012003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10b4010240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d1f20074101742205200a2005200a4b1b22054100480d1f0240024020070d002005102821070c010b200228022020072005102c21070b2007450d0e2002200536022420022007360220200228022821050b2002200520046a360228200720056a20092004109a051a200341706a200241206a1092042003200241206a1093042003412c6a2103200841546a22080d000c020b0b2006280230210420062802382203200241206a10b4012003450d002003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10b4010240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d1e20074101742205200a2005200a4b1b22054100480d1e0240024020070d002005102821070c010b200228022020072005102c21070b2007450d0e2002200536022420022007360220200228022821050b2002200520046a360228200720056a20092004109a051a200341706a200241206a1092042003200241206a1093042003412c6a2103200841546a22080d000b0b200228022421042002280228210302400240200628023c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0f2002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0f2002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628023c4101460d00200241106a20062802401103002002280210210420022802142203200241206a10b4012003450d012003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10b4010240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d1f20074101742205200a2005200a4b1b22054100480d1f0240024020070d002005102821070c010b200228022020072005102c21070b2007450d122002200536022420022007360220200228022821050b2002200520046a360228200720056a20092004109a051a200341706a200241206a1093042003200241206a1093042003412c6a2103200841546a22080d000c020b0b2006280240210420062802482203200241206a10b4012003450d002003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10b4010240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d1e20074101742205200a2005200a4b1b22054100480d1e0240024020070d002005102821070c010b200228022020072005102c21070b2007450d122002200536022420022007360220200228022821050b2002200520046a360228200720056a20092004109a051a200341706a200241206a1093042003200241206a1093042003412c6a2103200841546a22080d000b0b02400240200628024c4101460d00200241086a20062802501103002002280208210b200228020c2203200241206a10b4012003450d01200341386c210c410021070340200b20076a220341046a2802002109200341086a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1f20084101742205200a2005200a4b1b22054100480d1f0240024020080d002005102821080c010b200228022020082005102c21080b2008450d142002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a200341106a2802002109200341146a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1f20084101742205200a2005200a4b1b22054100480d1f0240024020080d002005102821080c010b200228022020082005102c21080b2008450d152002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a02400240200341186a2802004101460d00200241306a2003411c6a280200200341206a28020028020c1102002002280230210920022802382204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d2120084101742205200a2005200a4b1b22054100480d210240024020080d002005102821080c010b200228022020082005102c21080b2008450d182002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a2002280234450d012009102a0c010b2003411c6a2802002109200341246a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d2020084101742205200a2005200a4b1b22054100480d200240024020080d002005102821080c010b200228022020082005102c21080b2008450d182002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a0b200341286a200241206a109304200c200741386a2207470d000c020b0b2006280250210b20062802582203200241206a10b4012003450d00200341386c210c410021070340200b20076a220341046a2802002109200341086a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1e20084101742205200a2005200a4b1b22054100480d1e0240024020080d002005102821080c010b200228022020082005102c21080b2008450d172002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a200341106a2802002109200341146a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1e20084101742205200a2005200a4b1b22054100480d1e0240024020080d002005102821080c010b200228022020082005102c21080b2008450d182002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a02400240200341186a2802004101460d00200241306a2003411c6a280200200341206a28020028020c1102002002280230210920022802382204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d2020084101742205200a2005200a4b1b22054100480d200240024020080d002005102821080c010b200228022020082005102c21080b2008450d1b2002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a2002280234450d012009102a0c010b2003411c6a2802002109200341246a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1f20084101742205200a2005200a4b1b22054100480d1f0240024020080d002005102821080c010b200228022020082005102c21080b2008450d1b2002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a0b200341286a200241206a109304200c200741386a2207470d000b0b200641dc006a220641b8dac000470d000b2002280228220341046a2204417f4c0d1720022802242108200228022021070240024020040d00410121050c010b200410282205450d190b2002410036023820022004360234200220053602302003200241306a10b4010240024020022802342205200228023822046b2003490d00200228023021050c010b200420036a22092004490d1b2005410174220a2009200a20094b1b22094100480d1b0240024020050d002009102821050c010b200228023020052009102c21050b2005450d1a20022009360234200220053602300b200520046a20072003109a051a200420036a210302402008450d002007102a0b200241d0006a24002003ad4220862005ad840f0b410441011037000b200541011037000b200441011037000b200541011037000b200541011037000b200441011037000b200441011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b1036000b200441011037000b200941011037000b1031000b9c1d010a7f230041106b220324002001200210b401024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001450d00200141d8006c2104410021050340200020056a220641046a2802002107200641086a2802002208200210b40102400240200241046a2209280200220a200241086a2201280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d18200a410174220b200c200b200c4b1b220b4100480d1802400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d032002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a200641d4006a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1820084101742207200b2007200b4b1b22074100480d180240024020080d0020071028210b0c010b200228020020082007102c210b0b200b450d042002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a000002402006410c6a2d0000220841024b0d0002400240024020080e03000102000b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1b2008410174220a200b200a200b4b1b220a4100480d1b0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d082002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41003a0000200641146a2802002107200641186a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d1b200a410174220b200c200b200c4b1b220b4100480d1b02400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d092002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a0c020b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1a2008410174220a200b200a200b4b1b220a4100480d1a0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d092002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41013a00002006410d6a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1a20084101742207200b2007200b4b1b22074100480d1a0240024020080d0020071028210b0c010b200228020020082007102c210b0b200b450d0a2002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a0000200641146a2802002107200641186a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d1a200a410174220b200c200b200c4b1b220b4100480d1a02400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d0b2002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a200641206a2802002107200641246a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d1a200a410174220b200c200b200c4b1b220b4100480d1a02400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d0c2002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1a2008410174220a200b200a200b4b1b220a4100480d1a0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d0d2002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a2006410e6a2d00003a00000c010b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d192008410174220a200b200a200b4b1b220a4100480d190240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d0d2002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41023a00002006410d6a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1920084101742207200b2007200b4b1b22074100480d190240024020080d0020071028210b0c010b200228020020082007102c210b0b200b450d0e2002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a0000200641146a2802002107200641186a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d19200a410174220b200c200b200c4b1b220b4100480d1902400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d0f2002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a200641206a2802002107200641246a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d19200a410174220b200c200b200c4b1b220b4100480d1902400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d102002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a2006412c6a2802002107200641306a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d19200a410174220b200c200b200c4b1b220b4100480d1902400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d112002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a2006410e6a2d0000220841044b0d000240024002400240024020080e050001020304000b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1d2008410174220a200b200a200b4b1b220a4100480d1d0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41003a00000c040b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1c2008410174220a200b200a200b4b1b220a4100480d1c0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41013a00000c030b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1b2008410174220a200b200a200b4b1b220a4100480d1b0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41023a00000c020b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1a2008410174220a200b200a200b4b1b220a4100480d1a0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41033a00000c010b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d192008410174220a200b200a200b4b1b220a4100480d190240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41043a00000b02400240200641346a2802004101460d002003200641386a2802002006413c6a28020028020c1102002003280200210720032802082208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d1a200a410174220b200c200b200c4b1b220b4100480d1a02400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d182002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a2003280204450d012007102a0c010b200641386a2802002107200641c0006a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d19200a410174220b200c200b200c4b1b220b4100480d1902400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d182002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a0b200641c4006a20021093042004200541d8006a2205470d000b0b200341106a24000f0b200b41011037000b200741011037000b200a41011037000b200b41011037000b200a41011037000b200741011037000b200b41011037000b200b41011037000b200a41011037000b200a41011037000b200741011037000b200b41011037000b200b41011037000b200b41011037000b200a41011037000b200a41011037000b200a41011037000b200a41011037000b200a41011037000b200b41011037000b200b41011037000b1031000b840701087f20002802042102024002400240024002400240024020002802004101460d00200041086a2802002200200110b4012000450d01200041186c2103200241146a2100200141086a2102200141046a21040340200041706a2802002105200041746a2802002206200110b4010240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d08200741017422082009200820094b1b22084100480d080240024020070d002008102821070c010b200128020020072008102c21070b2007450d042001200736020020042008360200200228020021080b2002200820066a360200200720086a20052006109a051a2000417c6a280200210520002802002206200110b4010240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d08200741017422082009200820094b1b22084100480d080240024020070d002008102821070c010b200128020020072008102c21070b2007450d052001200736020020042008360200200228020021080b2002200820066a360200200720086a20052006109a051a200041186a2100200341686a22030d000c020b0b2000410c6a2802002200200110b4012000450d00200041186c2103200241146a2100200141086a2102200141046a21040340200041706a2802002105200041746a2802002206200110b4010240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d07200741017422082009200820094b1b22084100480d070240024020070d002008102821070c010b200128020020072008102c21070b2007450d052001200736020020042008360200200228020021080b2002200820066a360200200720086a20052006109a051a2000417c6a280200210520002802002206200110b4010240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d07200741017422082009200820094b1b22084100480d070240024020070d002008102821070c010b200128020020072008102c21070b2007450d062001200736020020042008360200200228020021080b2002200820066a360200200720086a20052006109a051a200041186a2100200341686a22030d000b0b0f0b200841011037000b200841011037000b200841011037000b200841011037000b1031000b840401087f200028020421020240024002400240024020002802004101460d00200041086a2802002200200110b40120004103742200450d01200220006a2103200141086a2104034020022802002105200241046a2802002200200110b40102400240200141046a22062802002207200428020022086b2000490d00200128020021070c010b200820006a22092008490d06200741017422082009200820094b1b22084100480d060240024020070d002008102821070c010b200128020020072008102c21070b2007450d042001200736020020062008360200200428020021080b2004200820006a360200200720086a20052000109a051a200241086a22022003470d000c020b0b2000410c6a2802002200200110b40120004103742200450d00200220006a2103200141086a2104034020022802002105200241046a2802002200200110b40102400240200141046a22062802002207200428020022086b2000490d00200128020021070c010b200820006a22092008490d05200741017422082009200820094b1b22084100480d050240024020070d002008102821070c010b200128020020072008102c21070b2007450d042001200736020020062008360200200428020021080b2004200820006a360200200720086a20052000109a051a200241086a22022003470d000b0b0f0b200841011037000b200841011037000b1031000bd10f02037f027e230041a0076b22022400024002402001450d00200220003602080c010b200241013602080b2002200136020c200241f0046a200241086a107a02400240024002400240024002400240024002400240024020022903d8054203510d00200241106a200241f0046a41a002109a051a200241c0026a200241106a41a002109a051a200241e0046a200241c0026a10870420022802e8042101200241f0046a200241c0026a41a002109a051a20024198076a20022802e804360200200220022903e00437039007200241b0026a200241f0046a200120024190076a10d0034101410220022d00b00241014622001b220310282201450d01200241003602f804200220033602f404200220013602f0040240024020000d00200241013602f804200141003a000020022802f404210020022802f80421010240200241bc026a2d000022034102470d000240024020002001460d0020022802f00421000c010b200141016a22002001490d0f200141017422032000200320004b1b22034100480d0f0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d06200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41003a00000c020b0240024020002001460d0020022802f00421000c010b200141016a22002001490d0e200141017422042000200420004b1b22044100480d0e0240024020010d002004102821000c010b20022802f00420012004102c21000b2000450d06200220043602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41013a00000240024020034101460d000240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d10200141017422032000200320004b1b22034100480d100240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d09200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41003a00000c010b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0f200141017422032000200320004b1b22034100480d0f0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d09200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41013a00000240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0f200141017422032000200320004b1b22034100480d0f0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0a200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a20022d00bd023a00000b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0e200141017422032000200320004b1b22034100480d0e0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0a200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a20022d00be023a00000c010b200241013602f804200141013a000020022d00b102417e6a22014102200141ff01714102491b41ff0171220141024b0d0002400240024020010e03000102000b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0f200141017422032000200320004b1b22034100480d0f0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0c200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41003a00000c020b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0e200141017422032000200320004b1b22034100480d0e0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0c200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41013a00000c010b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0d200141017422032000200320004b1b22034100480d0d0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0c200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41023a0000200241b0026a410172200241f0046a10c6030b20023502f804210520023502f0042106200241a0076a240020062005422086840f0b2002411c6a4104360200200241d4026a4102360200200242023702c402200241bca7c4003602c00220024104360214200241e0a8c400360210200241003602b402200241b8aec6003602b0022002200241106a3602d0022002200241b0026a360218200241c0026a41cca7c400103e000b200341011037000b200341011037000b200441011037000b200341011037000b200341011037000b200341011037000b200341011037000b200341011037000b200341011037000b200341011037000b1031000baf0d04067f017e057f017e230041c0016b22022400200241086a10e403200228020c21032002280208210420024180016a41086a22054200370300200242003703800141f99fc600411520024180016a1008200241106a41086a2005290300370300200220022903800137031020022003410020041b3602a001200241106a4110200241a0016a41041007109801109e0320054200370300200242003703800141f99fc600411520024180016a100820024190016a41086a20052903003703002002200229038001370390012002410036021020024190016a4110200241106a1006210502400240024002400240024020022802102203417f460d002005450d00200341034d0d05200528000021062005102a20060d010b41042107410021060c010b2006ad420c7e2208422088a70d012008a722054100480d01200510282207450d022007210341002104034002400240024002400240411410282205450d00200541106a41002800eaa046360000200541086a41002900e2a046370000200541002900daa046370000200541144128102c2205450d0120052004360014200241106a41186a22094200370300200241106a41106a220a4200370300200241106a41086a220b42003703002002420037031020054118200241106a1000200241a0016a41186a2009290300370300200241a0016a41106a200a290300370300200241a0016a41086a200b290300370300200220022903103703a0012005102a20024100360210200241a0016a4120200241106a1006210a2002280210220b417f460d03200a450d032002200b3602142002200a3602102002200241106a106c02400240024020022802000d002002280214220c20022802042209490d002009417f4c0d050240024020090d00410121050c010b2009102e2205450d0220052002280210220d2009109a051a2002200c20096b3602142002200d20096a3602100b20050d020b41c4d1c300413320024180016a419cd9c3001038000b200941011037000b2009ad2208422086210e0240200b450d00200a102a0b200e2008842108200241a0016a412010090c040b411441011037000b412841011037000b1036000b41012105420021080b20032005360200200341046a20083702002003410c6a21032006200441016a2204470d000b0b200220063602182002200636021420022007360210200241a0016a200241106a108e04200241106a41186a200241a0016a41186a290300370300200241106a41106a2205200241a0016a41106a290300370300200241106a41086a200241a0016a41086a290300370300200220022903a00137031020024180016a41086a22034200370300200242003703800141e6efc200411520024180016a100820024190016a41086a20032903003703002002200229038001370390012002411036028401200220024190016a36028001200241106a20024180016a10f002200241106a10b20320024100360298012002420137039001200220024190016a3602a0012005200241a0016a10c801200241106a20024190016a10a001200220024190016a3602a001200241c0006a200241a0016a10c801200220024190016a3602a001200241e0006a200241a0016a10c801200228021421042002411c6a280200220520024190016a10b401024002402005450d00200541246c210b0340200241a0016a200410ec0120022802a001210a02400240200228029401220920022802980122056b20022802a8012203490d0020022802900121090c010b200520036a22062005490d04200941017422052006200520064b1b22054100480d040240024020090d002005102821090c010b20022802900120092005102c21090b2009450d032002200536029401200220093602900120022802980121050b2002200520036a36029801200920056a200a2003109a051a024020022802a401450d00200a102a0b200441246a2104200b415c6a220b0d000b0b200235029801210820022802900121090240200228021c2203450d0020022802142105200341246c210303400240024020052d0000220441034b0d0002400240024020040e0404000102040b2005410c6a280200450d03200541086a280200102a0c030b2005410c6a280200450d02200541086a280200102a0c020b2005410c6a280200450d01200541086a280200102a0c010b200541086a280200450d00200541046a280200102a0b200541246a21052003415c6a22030d000b0b0240200241186a280200450d002002280214102a0b200241c0016a240020084220862009ad840f0b200541011037000b1031000b200541041037000b41c4d1c300413320024180016a419cd9c3001038000bee2605017f027e0d7f027e067f230041b0036b22022400024002402001450d00200220003602080c010b200241013602080b2002200136020c2002200241086a106c024020022802000d00200228020421012002200241086a36029801200241003a0090032002420037028402200241f8b9c000360280022002200136022420024100360220200220024190036a36022c200220024198016a360228200241206a20024180026a10860420022802800221012002290284022103024020022d009003450d0020012003a72003422088a710b0020c010b2001450d002002200337021420022001360210200241206a200241106a1097040240024002400240024002400240024002400240024020022802204101460d00200241206a41086a2201290300210342002104200142003703002002420037032041feb3c300410d200241206a100820024180026a41086a200129030037030020022002290320370380022002410036022020024180026a4110200241206a100621010240024020022802202200417f460d002001450d0020004108490d01200129000021042001102a0b024041a00210282205450d0020054102360298012005420237036820052003200442dc0b7c220420032004561b3703a001200241106a21012002280214210603402001280200220741086a210020072f010622084103742101410021090240024003402001450d0141bee6c20020004108109c05220a450d02200141786a2101200941016a2109200041086a2100200a417f4a0d000b2009417f6a21080b024020060d004101210b0c080b2006417f6a2106200720084102746a41e4016a21010c010b0b200220072009410c6c6a220141e8006a280200360284022002200141e0006a28020036028002200241206a20024180026a107e02402002280220220c0d004101210b0c060b2002280224210d200241206a41086a22012802002208450d0320014200370300200242003703204193cdc2004111200241206a100820024180026a41086a200129030037030020022002290320370380022002410036022020024180026a4110200241206a1006210102400240024020022802202200417f460d002001450d002002200036029c012002200136029801200241206a20024198016a107b20022802202206450d02200229022421032000450d012001102a0c010b42002103410421060b2003a7210b2006210020062101024002400240024002402003422088a7220e450d002006200e41c4006c6a21004100210902400340200620096a22012d0000210a200241206a200141016a41c300109a051a200a4102460d0120024180026a41186a200241206a41186a29000037030020024180026a41106a200241206a41106a29000037030020024180026a41086a200241206a41086a2900003703002002200229002037038002200a4101460d03200941c4006a2109200141c4006a2000470d000b200021010c010b200141c4006a21010b0240034020002001460d0120012d00002109200141c4006a210120094102470d000b0b410121074100210f0240200b0d00410021100c020b2006102a410021100c010b20024198016a41086a220a20024180026a41086a29030037030020024198016a41106a220f20024180026a41106a29030037030020024198016a41186a221120024180026a41186a290300370300200220022903800222033703f0022002200337039801412010282207450d022007200229039801370000200741186a2011290300370000200741106a200f290300370000200741086a200a2903003700004101210f024002400240200e41c4006c41bc7f6a2009470d00410121100c010b200141c4006a2d00002109200241206a200141c5006a41c300109a051a20014188016a210a024020094102470d0041012110200a21010c020b4101210f410121100340200a21010240034020024180026a41186a220a200241206a41186a29000037030020024180026a41106a220e200241206a41106a29000037030020024180026a41086a2211200241206a41086a2900003703002002200229002037038002200941ff01714101460d0120002001460d0320012d00002109200241206a200141016a41c300109a051a200141c4006a210120094102460d040c000b0b20024198016a41086a2011290300220337030020024198016a41106a200e290300220437030020024198016a41186a200a29030022123703002002200229038002221337039801200241f0026a41186a220a2012370300200241f0026a41106a220e2004370300200241f0026a41086a22112003370300200220133703f00202402010200f470d00200f41016a2209200f490d14200f41017422142009201420094b1b221041ffffff3f712010470d14201041057422094100480d1402400240200f0d002009102821070c010b2007200f4105742009102c21070b2007450d050b2007200f4105746a220920022903f002370000200941186a200a290300370000200941106a200e290300370000200941086a2011290300370000200f41016a210f20002001460d0120012d00002109200241206a200141016a41c300109a051a200141c4006a210a20094102470d000b200141c4006a21010c010b200021010b0240034020002001460d0120012d00002109200141c4006a210120094102470d000b0b200b450d002006102a0b200c200841f0006c6a210820024180026a41106a211520024180026a41086a21144200210341042116200c210a02400340200a2802042101200a2802002100200241206a200a41086a41e800109a051a200a41f0006a210a024020010d00200a2008460d0a0340200a2802042206450d0b200a41086a280200210b0240200a410c6a2802002201450d00200141246c21002006210103400240024020012d0000220941034b0d0002400240024020090e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b200a41f0006a210a0240200b450d002006102a0b200a2008470d000c0b0b0b20024198016a200241206a41e800109a051a20022001360284022002200036028002201420024198016a41e800109a051a109801210120024190036a20024180026a10f6010240024002400240200228028002417f6a220020014f0d00200241206a200010f701200241206a20154120109c050d00200228028002221741002001417b6a2200200020014b1b490d0020024190036a20076b220641606a210e200641406a2111200641a07f6a21182007200f41057422096a210b410021010240024002400340024002400240200b200720016a22006b41e0004b0d00200f4105742001470d01410021000c060b024020062001470d0020024190036a21000c060b200020024190036a4120109c05450d05200e2001470d0120024190036a21000c050b0340024020024190036a2000470d0020024190036a21000c060b200020024190036a4120109c05450d05200041206a2100200941606a22090d000b410021000c040b200041206a221920024190036a4120109c05450d02024020112001470d0020024190036a21000c040b200041c0006a221920024190036a4120109c05450d01024020182001470d0020024190036a21000c040b200941807f6a210920014180016a2101200041e0006a20024190036a4120109c050d000b200720016a41606a21000c020b201921000c010b201921000b200241206a201710f701200241206a20024190036a4120109c05210120000d0020010d010b0240200228028c022200450d002002280284022101200041246c210003400240024020012d0000220941034b0d0002400240024020090e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b200228028802450d01200228028402102a0c010b20024190036a20024180026a10f601200241206a20024180026a41f000109a051a0240024020034220882204a722012003a7460d00200121000c010b200141016a22092001490d142004a722004101742206200920092006491bad220342f0007e2204422088a70d142004a722094100480d140240024020010d002009102821160c010b2016200141f0006c2009102c21160b2016450d020b2016200041f0006c6a200241206a41f000109a051a200241206a41186a220920024190036a41186a290300370300200241206a41106a220620024190036a41106a290300370300200241206a41086a220b20024190036a41086a29030037030020022002290390033703200240200f2010470d00200f41016a2201200f490d14200f410174220e2001200e20014b1b221041ffffff3f712010470d14201041057422014100480d1402400240200f0d002001102821070c010b2007200f4105742001102c21070b2007450d040b200342ffffffff0f83200041016aad4220868421032007200f4105746a22012002290320370000200141186a2009290300370000200141106a2006290300370000200141086a200b290300370000200f41016a210f0b200a2008470d010c0a0b0b200941041037000b200141011037000b200941011037000b412041011037000b41c4d1c300413320024190036a419cd9c3001038000b41a00241081037000b41c4d1c300413320024190036a419cd9c3001038000b2002200229022437038002419db6c300412820024180026a419cb4c3001038000b4101210b200d450d01200c102a0c010b0240200d450d00200c102a0b02402010450d002007102a0b0240200342ffffffff0f560d004101210b2003a7450d012016102a0c010b024020160d004101210b0c010b200541a00241c004102c2205450d01200541a0026a20024180026a41e800109a051a2005420237038803200520033703c003200520163602bc03200541033602b80320052002290398013703900320054198036a200241a0016a290300370300200541a0036a200241a8016a290300370300200541a8036a200241b0016a290300370300200541b0036a200241b8016a290300370300200541c8036a200241206a41f800109a051a4102210b0b200241106a210120022802142106024003402001280200220741086a210020072f010622084103742101410021090240024003402001450d0141a7c5c20020004108109c05220a450d02200141786a2101200941016a2109200041086a2100200a417f4a0d000b2009417f6a21080b2006450d022006417f6a2106200720084102746a41e4016a21010c010b0b200741e0006a2009410c6c6a22012802084104490d002001280200280000210742002103200241206a41086a2201420037030020024200370320419194c1004115200241206a100820024180026a41086a200129030037030020022002290320370380022002410036022020024180026a4110200241206a100621000240024020022802202201417f460d002002200136029c012002200036029801200241206a20024198016a10820120022802202209450d04200229022421032001450d012000102a0c010b410421090b4100210002402003422088a72201417f6a220a20014b0d00200a20014f0d002009200a4102746a2201450d00200128020020074721000b02402003a7450d002009102a0b20000d030b200b210f0c030b41c00441081037000b41c4d1c300413320024190036a419cd9c3001038000b2005200b41a0026c2201200b4101742200200b41016a220f2000200f4b1b41a0026c2200102c2205450d01200520016a20024180026a41e800109a05220142023703682001200229039801370370200141f8006a200241a0016a29030037030020014180016a200241a8016a29030037030020014188016a200241b0016a29030037030020014190016a200241b8016a2903003703002001419c016a20073602002001410d36029801200141a8016a200241206a41f800109a051a0b20022802102002280214200228021810b00220024100360288022002420137038002200f20024180026a10b401200f41a0026c210b20022802840221062002280288022101200521090340200241206a20091087042002280220210802400240200620016b20022802282207490d00200120076a2100200228028002210a0c010b200120076a22002001490d042006410174220a2000200a20004b1b220e4100480d040240024020060d00200e1028210a0c010b2002280280022006200e102c210a0b200a450d032002200e360284022002200a36028002200e21060b2002200036028802200a20016a20082007109a051a02402002280224450d002008102a0b200941a0026a210920002101200b41e07d6a220b0d000b200f41a0026c210920054198016a210103402001106a200141a0026a2101200941e07d6a22090d000b2005102a200241b0036a24002000ad422086200aad840f0b200041081037000b200e41011037000b1031000b2002418c026a4104360200200241346a410236020020024202370224200241bca7c4003602202002410436028402200241f8a8c400360280022002410036029c01200241b8aec60036029801200220024180026a360230200220024198016a36028802200241206a41cca7c400103e000bf00101067f2001280204210202400240024003402001280200220341086a210420032f01062205410374210141002106024003402001450d0141ffa0c60020044108109c052207450d03200141786a2101200641016a2106200441086a21042007417f4a0d000b2006417f6a21050b02402002450d002002417f6a2102200320054102746a41e4016a21010c010b0b20004187a1c600360204200041086a41283602000c010b200341e0006a2006410c6c6a220128020841074b0d01200041afa1c600360204200041086a41293602000b200041013602000f0b200041086a2001280200290000370300200041003602000be92c06087f017e097f027e017f027e230041b0026b22022400024002402001450d00200220003602100c010b200241013602100b20022001360214200241c8006a200241106a107f02400240200228024c2203450d00200241d4006a280200210420022802502105200241c8006a200241106a1079200228024822060d0102402004450d00200441246c21002003210103400240024020012d0000220741034b0d0002400240024020070e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b2005450d002003102a0b200241dc016a4104360200200241dc006a41023602002002420237024c200241bca7c400360248200241043602d40120024194a9c4003602d0012002410036022c200241b8aec6003602282002200241d0016a3602582002200241286a3602d801200241c8006a41cca7c400103e000b200241d0006a2802002108200228024c2109200241086a200241106a106c0240024020022802080d00200228020c21012002200241106a360228200241003a0038200242003702d401200241f8b9c0003602d0012002200136024c200241003602482002200241386a3602542002200241286a360250200241c8006a200241d0016a10860420022802d001210120022902d401210a024020022d0038450d002001200aa7200a422088a710b0020c010b20010d010b200241dc016a4104360200200241dc006a41023602002002420237024c200241bca7c400360248200241043602d40120024194a9c4003602d0012002410036022c200241b8aec6003602282002200241d0016a3602582002200241286a3602d801200241c8006a41cca7c400103e000b2002200a37021c20022001360218200241013b01342002420037022c200241f8b9c000360228200241286a41086a210b024002400240024002402008450d002006200841a0026c6a210c200241d0016a410272210d2006210e024002400240024002400240024002400340200e41e8006a2903004202520d0902400240200e28029801410247220f0d00200e2903a001210a200241186a2101200228021c211002400240024002400240024002400240024002400240024002400240024002400240024003402001280200221141086a210020112f010622124103742101410021070240024003402001450d0141f7fcc50020004108109c052213450d02200141786a2101200741016a2107200041086a21002013417f4a0d000b2007417f6a21120b2010450d022010417f6a2110201120124102746a41e4016a21010c010b0b0240201141e0006a2007410c6c6a220128020841074b0d00201442808080807083422984210a41fffcc50021120c020b200a42b8178020012802002900002214510d0341c6e6c2002112413121100c020b201442808080807083421c84210a41a8fdc50021120b200aa721100b024002400240024020022d0035450d004131210141f7e6c20021000c010b2002280228200228022c200228023010b0022002420037022c200241f8b9c000360228200242e2c289abb68edbb7f400370338200241d0016a410272410041da001099051a200241c8006a41004184011099051a41e40110282213450d0420134100360200201341046a200241d0016a41dc00109a051a201341e0006a200241c8006a418401109a051a2002410036022c2002201336022820132f0106220e4103742111417f210041002101024002400340024020112001470d00200e21000c020b200241386a201320016a41086a4108109c052207450d02200141086a2101200041016a2100200741004e0d000b0b200242e2c289abb68edbb7f40037025c2002200b360258200220003602542002201336024c200241003602482002200241286a360250201041046a2200417f4c0d062000450d02200010282201450d07200241003602ac02200220013602d0012010413f4b0d03200120104102743a0000410121070c1b0b412d210141a8e7c20021000b2002200136024c2002200036024841d5e7c2004122200241c8006a41f8e7c2001038000b200241003602ac0241012100200241013602d001410110282201450d05200141033a0000200241013602ac02200220013602d001410521070c130b201041808001490d162010418080808004490d150c100b200f0d0e200e2903a0012115200241c8006a200241186a10970402400240024020022802484101470d002002350250210a200228024c21160c010b2002290350210a200241c8006a41086a220142003703002002420037034841feb3c300410d200241c8006a1008200241d0016a41086a2001290300370300200220022903483703d00120024100360248200241d0016a4110200241c8006a100621010240024020022802482200417f470d00420021170c010b024020010d00420021170c010b200041074d0d07200129000021172001102a0b02402015200a423c7c560d004100210f2015201742dc0b7c220a540d020c110b201842808080807083422584210a41f8b5c30021160b4101210f0b024020022d0035450d004131210141f7e6c20021000c080b0240200f450d002002280228200228022c200228023010b0022002420037022c200241f8b9c000360228200242f4d2b59bc7ae98b8303703380c060b20022802282111200242f4d2b59bc7ae98b830370338201141f8b9c000460d05200228022c21100c060b41e40141041037000b1036000b200041011037000b410141011037000b41c4d1c3004133200241c8006a419cd9c3001038000b200d410041da001099051a200241c8006a41004184011099051a41e40110282211450d034100211020114100360200201141046a200241d0016a41dc00109a051a201141e0006a200241c8006a418401109a051a2002410036022c200220113602280b0340201141086a210020112f010622124103742101410021070240024003402001450d01200241386a20004108109c052213450d02200141786a2101200741016a2107200041086a21002013417f4a0d000b2007417f6a21120b2010450d032010417f6a2110201120124102746a41e4016a28020021110c010b0b412d210141a8e7c20021000b2002200136024c2002200036024841d5e7c2004122200241c8006a41f8e7c2001038000b200242f4d2b59bc7ae98b83037025c2002200b360258200220123602542002201136024c200241003602482002200241286a360250200241003602d801200242013703d00141011028210102400240200f0d002001450d03200141003a000020024281808080103702d401200220013602d001200141014109102c2201450d042001200a3700012002428980808090013702d401200220013602d0010c010b2001450d04200141013a000020024281808080103702d401200220013602d001200aa72201200241d0016a10b4010240024020022802d401220720022802d80122006b2001490d0020022802d00121070c010b200020016a22132000490d14200741017422112013201120134b1b22134100480d140240024020070d002013102821070c010b20022802d00120072013102c21070b2007450d06200220133602d401200220073602d0010b2002200020016a3602d801200720006a20162001109a051a0b200241386a41086a200241d0016a41086a280200360200200220022903d001370338200241c8006a200241386a10bb022002200f3a0035200241003a0034200a2118200f450d05200241d0016a41086a200241286a41086a290300370300200220022903283703d0010c110b41e40141041037000b410141011037000b410941011037000b410141011037000b201341011037000b200e41a0026a220e200c470d010c0a0b0b200141033a0000200241013602ac022000417f6a41034b0d01200041017422074105200741054b1b22074100480d0a0b200120002007102c2201450d01200220013602d001200721000b20012010360001410521070c030b200741011037000b02400240200041034b0d00200041017422074104200741044b1b22074100480d08200120002007102c2201450d01200220013602d001200721000b20012010410274410272360000410421070c020b200741011037000b0240200041014b0d0020012000200041017422074102200741024b1b2207102c2201450d02200220013602d001200721000b41022107200120104102744101723b00000b200220073602ac0202400240200020076b2010490d00200021130c010b200720106a22132007490d05200041017422112013201120134b1b22134100480d05200120002013102c2201450d02200220013602d0010b2002200720106a3602ac02200120076a20122010109a051a2002201336023c200220022802d001360238200220022802ac02360240200241c8006a200241386a10bb0220024180023b0134200241d0016a41086a200241286a41086a290300370300200220022903283703d0010c030b200741011037000b201341011037000b200241d0016a41086a200b290300370300200220022903283703d0010b2002280218200228021c200228022010b00202402004450d00200441246c21002003210103400240024020012d0000220741034b0d0002400240024020070e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b02402005450d002003102a0b02402008450d00200841a0026c210020064198016a210103402001106a200141a0026a2101200041e07d6a22000d000b0b02402009450d002006102a0b2002410036025020024201370348410110282201450d022002410136024c20022002280250220041016a36025020022001360248200120006a20022d00dc013a000002400240200228024c20022802502201460d00200228024821000c010b200141016a22002001490d01200141017422072000200720004b1b22074100480d010240024020010d002007102821000c010b200228024820012007102c21000b2000450d022002200736024c20022000360248200228025021010b2002200141016a360250200020016a20022d00dd013a000020022802d801200241c8006a10b40120022802d00122072100024020022802d4012213450d002013210120072100034020002802e40121002001417f6a22010d000b0b0240024002400240024002400240024002400240024020022802d80122120d00410021010c010b200241d0016a210f41002113034002400240201320002f01064f0d0020002013410c6c6a41e0006a2111200020134103746a41086a2101201341016a21130c010b02400240200028020022010d00201542808080807083200fad84211541002107410021010c010b2000330104422086200fad842115410121070b201521142015210a02402015422088a7220020012f0106490d000340200a221442ffffffff0f83210a200741016a210720012f01042200200128020022012f01064f0d000b0b20012000410c6c6a2113200120004103746a2110200041027420016a41e8016a28020021002014a7210f02402007417f6a2201450d00034020002802e40121002001417f6a22010d000b0b201341e0006a2111201041086a2101410021130b02400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d032002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00003a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d042002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00013a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d052002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00023a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d062002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00033a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d072002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00043a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d082002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00053a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d092002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00063a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d0a2002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00073a00002011280200211020112802082201200241c8006a10b40102400240200228024c2211200228025022076b2001490d00200228024821110c010b200720016a220e2007490d0c20114101742207200e2007200e4b1b22074100480d0c0240024020110d002007102821110c010b200228024820112007102c21110b2011450d0b2002200736024c20022011360248200228025021070b2002200720016a360250201120076a20102001109a051a2012417f6a22120d000b20022802d801210120022802d401211320022802d00121070b2002350248210a2002350250211420072013200110b002200241b0026a2400200a2014422086840f0b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200741011037000b1031000b200741011037000b410141011037000b5702017f027e230041306b2202240020024101410010a80320024100360228200242013703202002200241206a36022c20022002412c6a10c8012002350228210320023502202104200241306a240020042003422086840bba48030b7f047e017f230041d00c6b22022400024002402001450d00200220003602100c010b200241013602100b20022001360214200241f0066a200241106a107a024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022903d8074203510d00200241186a200241f0066a41a002109a051a200241f0026a200241186a41a002109a051a200241f0066a200241f0026a10870420022802f8062103024020022802f406450d0020022802f006102a0b200241f0066a200241f0026a41a002109a051a20024190056a200241f0066a10d10341012100024020022d0090054101470d00200220022d0093053a00bb02200220022f0091053b00b902200241013a00b8020c180b200241f0066a20024190056a41086a41d801109a051a200241086a200241c0076a220410f301024002402002290390074202520d00200241b8026a41206a22014200370300200241b8026a41186a22004280808080c000370300200241013a00e002200242043703c8022002427f3703c002200242003703b80220024190056a41206a2203420037030020024190056a41186a22054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241c8096a200241b8026a20024190056a109b04200241b8026a41286a2206200241c8096a41286a2903003703002001200241c8096a41206a2903003703002000200241c8096a41186a290300370300200241b8026a41106a2207200241c8096a41106a290300370300200241b8026a41086a2208200241c8096a41086a290300370300200220022903c8093703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241f8096a200241b8026a20024190056a109b042006200241f8096a41286a2903003703002001200241f8096a41206a2903003703002000200241f8096a41186a2903003703002007200241f8096a41106a2903003703002008200241f8096a41086a290300370300200220022903f8093703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241a80a6a200241b8026a20024190056a109b042006200241a80a6a41286a2903003703002001200241a80a6a41206a2903003703002000200241a80a6a41186a2903003703002007200241a80a6a41106a2903003703002008200241a80a6a41086a290300370300200220022903a80a3703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241d80a6a200241b8026a20024190056a109b042006200241d80a6a41286a2903003703002001200241d80a6a41206a2903003703002000200241d80a6a41186a2903003703002007200241d80a6a41106a2903003703002008200241d80a6a41086a290300370300200220022903d80a3703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241880b6a200241b8026a20024190056a109b042006200241880b6a41286a2903003703002001200241880b6a41206a2903003703002000200241880b6a41186a2903003703002007200241880b6a41106a2903003703002008200241880b6a41086a290300370300200220022903880b3703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241b80b6a200241b8026a20024190056a109b04200241980c6a41286a2203200241b80b6a41286a290300370300200241980c6a41206a2206200241b80b6a41206a290300370300200241980c6a41186a2205200241b80b6a41186a290300370300200241980c6a41106a2207200241b80b6a41106a290300370300200241980c6a41086a2208200241b80b6a41086a290300370300200220022903b80b3703980c2001420037030020004280808080c000370300200241013a00e002200242043703c8022002427f3703c002200242003703b802200241e80b6a200241980c6a200241b8026a109b042002419c056a2201200241e80b6a41086a290300370200200241a4056a2200200241e80b6a41106a290300370200200241ac056a2209200241e80b6a41186a290300370200200241b4056a220a200241e80b6a41206a290300370200200241bc056a220b200241e80b6a41286a290300370200200220022903e80b3702940520024198096a41286a220c200b29020037030020024198096a41206a220b200a29020037030020024198096a41186a220a200929020037030020024198096a41106a2209200029020037030020024198096a41086a220020012902003703002002200229029405370398092003200c2903003703002006200b2903003703002005200a290300370300200720092903003703002008200029030037030020022002290398093703980c418102210120022802c0074112460d010c170b20022d000c210b20022802082108200241b8026a41206a22014200370300200241b8026a41186a22004280808080c000370300200241013a00e002200242043703c8022002427f3703c002200242003703b80220024190056a41206a2205420037030020024190056a41186a22064280808080c000370300200241013a00b805200242043703a0052002427f37039805200242003703900520024198096a200241b8026a20024190056a109b04200241b8026a41286a220720024198096a41286a290300370300200120024198096a41206a290300370300200020024198096a41186a290300370300200241b8026a41106a220920024198096a41106a290300370300200241b8026a41086a220a20024198096a41086a29030037030020022002290398093703b8022005420037030020064280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241c8096a200241b8026a20024190056a109b042007200241c8096a41286a2903003703002001200241c8096a41206a2903003703002000200241c8096a41186a2903003703002009200241c8096a41106a290300370300200a200241c8096a41086a290300370300200220022903c8093703b802200241b80b6a41086a22014200370300200242003703b80b41d9efc200410d200241b80b6a1008200241880b6a41086a2001290300370300200220022903b80b3703880b410021002002410036029005200241880b6a411020024190056a1006210102402002280290052205417f460d002001450d0020054104490d03200128000021002001102a0b2000ad210d427f210e02402002290390074201520d00200229039807220e4200510d04200d200241a0076a290300220f200f200d541b2210200e7c2010200f7d200e827d210e0b20024190056a41206a420037030020024190056a41186a4280808080c000370300200241bc056a2002419b0c6a280000360000200241013a00b805200242043703a0052002420037039005200220022800980c3600b90520024200200e200d7d220d200d200e561b37039805200241f8096a200241b8026a20024190056a109b04200241980c6a41286a200241f8096a41286a290300370300200241980c6a41206a200241f8096a41206a290300370300200241980c6a41186a200241f8096a41186a290300370300200241980c6a41106a200241f8096a41106a290300370300200241980c6a41086a200241f8096a41086a290300370300200220022903f8093703980c20022802b8072100411310282201450d04200141002900cef0423700002001410f6a41002800ddf042360000200141086a41002900d6f04237000020024293808080b0023702bc0b200220013602b80b200241f0066a200241b80b6a108f0120022802c00b210120022802b80b2105200241b8026a41186a22064200370300200241b8026a41106a22074200370300200241b8026a41086a22094200370300200242003703b80220052001200241b8026a1000200241e80b6a41186a2006290300370300200241e80b6a41106a2007290300370300200241e80b6a41086a2009290300370300200220022903b8023703e80b024020022802bc0b450d0020022802b80b102a0b200241003602b802200241e80b6a4120200241b8026a100621010240024020022802b8022205417f460d002001450d00024020054104490d00200128000021092001102a200920004d0d02200220022800880b3602900920022002418b0b6a28000036009309200241003a00bb0220024180063b00b902200241013a00b80220022802a80c21030240200241b00c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241ac0c6a280200450d002003102a0b20022802b40c21030240200241bc0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241b80c6a280200450d1a2003102a0c1a0b41c4d1c3004133200241c80c6a419cd9c3001038000b410021090b410c10282205450d05410410282201450d06200242043702bc02200220013602b802200241f0066a200241b8026a108f010240024020022802bc02220620022802c00222016b4104490d0020022802b80221070c010b200141046a22072001490d1a200641017422012007200120074b1b22014100480d1a0240024020060d002001102821070c010b20022802b80220062001102c21070b2007450d08200220013602bc02200220073602b80220022802c00221010b410421062002200141046a3602c002200720016a2000360000200241e80b6a41086a20022802c0022201360200200220022903b802220e3703e80b200541086a20013602002005200e370200410021010240200920004f0d00410c10282206450d09410410282201450d0a200242043702bc02200220013602b802200241f0066a200241b8026a108f010240024020022802bc02220720022802c00222016b4104490d0020022802b80221070c010b200141046a22092001490d1b200741017422012009200120094b1b22014100480d1b0240024020070d002001102821070c010b20022802b80220072001102c21070b2007450d0c200220013602bc02200220073602b80220022802c00221010b2002200141046a3602c002200720016a2000417f6a360000200241e80b6a41086a20022802c0022201360200200220022903b802220e3703e80b200641086a20013602002006200e370200410121010b20024190056a41206a42818080801037030020024190056a41186a2001360200200241a4056a2001360200200220022800880b3602900920022002418b0b6a28000036009309200241bc056a200228009309360000200241013a00b805200220053602ac05200220063602a0052002427f3703980520022008ad220e3703900520022002280290093600b905200241a80a6a200241980c6a20024190056a109b04200241980c6a41286a200241a80a6a41286a290300370300200241980c6a41206a200241a80a6a41206a290300370300200241980c6a41186a200241a80a6a41186a290300370300200241980c6a41106a200241a80a6a41106a290300370300200241980c6a41086a200241a80a6a41086a290300370300200220022903a80a3703980c200241b8026a200b4101712201200310b80320022d00b8020d14200241b8026a2008200110b90320022d00b802450d1320022f00b90220022d00bb024110747221010c150b200241e4076a2802002100200241b8026a10fb01200010fc0120022802b802220120022802c00241014100410010032103024020022802bc02450d002001102a0b41800621012003417f470d1510fb01220c200241e0076a280200470d15200241b80b6a41086a22014200370300200242003703b80b41c2e1c000410d200241b80b6a1008200241880b6a41086a2001290300370300200220022903b80b3703880b200241003602b802200241880b6a4110200241b8026a100621010240024020022802b8022203417f460d002001450d00200220033602bc0b200220013602b80b200241b8026a200241b80b6a107c20022802b802220b450d0c20022902bc02210e2003450d012001102a0c010b4101210b4200210e20022802e40721000b024002402000200e422088a74f0d00200b20004105746a2211450d00200241003602c002200242013703b802200241c4076a2802002100410410282201450d0d20024284808080c0003702bc02200220013602b80220012000360000200241c8076a2802002106200241d0076a2802002201200241b8026a10b4010240024020022802bc02220320022802c00222006b2001490d0020022802b80221030c010b200020016a22072000490d1b200341017422082007200820074b1b22074100480d1b0240024020030d002007102821030c010b20022802b80220032007102c21030b2003450d0f200220073602bc02200220033602b8020b2002200020016a3602c002200320006a20062001109a051a200241d4076a2802002100200241dc076a2802002201200241b8026a10b4010240024020010d0020022802bc02210620022802c00221090c010b20002001410c6c6a210a034020002802002108200041086a2802002201200241b8026a10b4010240024020022802bc02220620022802c00222036b2001490d0020022802b80221070c010b200320016a22072003490d1d200641017422092007200920074b1b22094100480d1d0240024020060d002009102821070c010b20022802b80220062009102c21070b2007450d12200220093602bc02200220073602b802200921060b2002200320016a22093602c002200720036a20082001109a051a2000410c6a2200200a470d000b0b20022802e007210302400240200620096b4104490d0020022802b80221010c010b200941046a22012009490d1b200641017422002001200020014b1b22004100480d1b0240024020060d002000102821010c010b20022802b80220062000102c21010b2001450d11200220003602bc02200220013602b802200021060b2002200941046a22003602c002200120096a200336000020022802e407210702400240200620006b41034d0d00200621030c010b200041046a22032000490d1b200641017422082003200820034b1b22034100480d1b0240024020060d002003102821010c010b200120062003102c21010b2001450d12200220033602bc02200220013602b8020b200120006a20073600002001200941086a200241e8076a2011100a210002402003450d002001102a0b2000450d010b4180082101200ea7450d16200b102a0c160b410c10282201450d10410410282200450d1120024284808080c0003702bc02200220003602b8022000200c3600002011200241b8026a108f01200241b80b6a41086a20022802c0022200360200200220022903b802220d3703b80b200141086a20003602002001200d370200200220022800880b3602d80a20022002418b0b6a2800003600db0a0240200ea7450d00200b102a0b20024190056a41206a42818080801037030020024190056a41186a4100360200200241bc056a20022800db0a360000200241013a00b805200220013602ac05200242043703a0052002427f370398052002420037039005200220022802d80a3600b905200241e80b6a200241980c6a20024190056a109b04200241b8026a41086a20022903e80b370300200241b8026a41106a200241e80b6a41086a290300370300200241b8026a41186a200241e80b6a41106a290300370300200241b8026a41206a200241e80b6a41186a290300370300200241b8026a41286a200241e80b6a41206a290300370300200241e8026a200241e80b6a41286a290300370300200241003a00b8020c160b200241246a410436020020024184036a4102360200200242023702f402200241bca7c4003602f0022002410436021c200241aca9c4003602182002410036029405200241b8aec600360290052002200241186a36028003200220024190056a360220200241f0026a41cca7c400103e000b41c4d1c3004133200241c80c6a419cd9c3001038000b41fcf8c5001032000b411341011037000b410c41041037000b410441011037000b200141011037000b410c41041037000b410441011037000b200141011037000b41c4d1c3004133200241c80c6a419cd9c3001038000b410441011037000b200741011037000b200941011037000b200041011037000b200341011037000b410c41041037000b410441011037000b20024190056a41206a2205420037030020024190056a41186a22064280808080c000370300200220022800880b3602e80b20022002418b0b6a2800003600eb0b200241bc056a20022800eb0b360000200242043703a0052002427f370398052002427f200e20011b37039005200220022802e80b3600b905200241013a00b805200241d80a6a200241980c6a20024190056a109b04200241e80b6a41286a2207200241d80a6a41286a290300370300200241e80b6a41206a2209200241d80a6a41206a290300370300200241e80b6a41186a2200200241d80a6a41186a290300370300200241e80b6a41106a220a200241d80a6a41106a290300370300200241e80b6a41086a220b200241d80a6a41086a290300370300200220022903d80a3703e80b20024190056a20022903a807200241b0076a290300200241f0066a200820012003109e02024020022d0090054101470d00200220022d0093053a00bb02200220022f0091053b00b902200241013a00b80220022802f80b2103024020002802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241fc0b6a280200450d002003102a0b20022802840c210302402002418c0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241880c6a280200450d042003102a0c040b200241980c6a41286a20024190056a41306a2201290300370300200241980c6a41206a20024190056a41286a290300370300200241980c6a41186a2005290300370300200241980c6a41106a2006290300370300200241980c6a41086a20024190056a41106a29030037030020022002290398053703980c200241880b6a200241e80b6a200241980c6a109b042007200241880b6a41286a2903003703002009200241880b6a41206a2903003703002000200241880b6a41186a290300370300200a200241880b6a41106a290300370300200b200241880b6a41086a290300370300200220022903880b3703e80b20024190056a200410d203024020022d0090054101470d00200220022d0093053a00bb02200220022f0091053b00b902200241013a00b80220022802f80b21030240200241800c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241fc0b6a280200450d002003102a0b20022802840c210302402002418c0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241880c6a280200450d042003102a0c040b200241980c6a41286a2001290300370300200241980c6a41206a20024190056a41286a290300370300200241980c6a41186a20024190056a41206a290300370300200241980c6a41106a20024190056a41186a290300370300200241980c6a41086a20024190056a41106a29030037030020022002290398053703980c200241b80b6a200241e80b6a200241980c6a109b04200241b8026a41086a20022903b80b370300200241b8026a41106a200241b80b6a41086a290300370300200241b8026a41186a200241b80b6a41106a290300370300200241b8026a41206a200241b80b6a41186a290300370300200241b8026a41286a200241b80b6a41206a290300370300200241b8026a41306a200241b80b6a41286a290300370300200241003a00b8020c030b20022f00b90220022d00bb024110747221010b200220022800880b3602e80b20022002418b0b6a2800003600eb0b200241013a00b802200220013b00b902200220014110763a00bb0220022802a80c21030240200241b00c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241ac0c6a280200450d002003102a0b20022802b40c21030240200241bc0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241b80c6a280200450d012003102a0c010b200241003a00bb02200220013b00b902200241013a00b80220022802a80c2103024020052802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241ac0c6a280200450d002003102a0b20022802b40c21030240200241bc0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241b80c6a280200450d002003102a0b2004106a20022d00b80221000b024002400240024002400240410110282201450d00200242013702f406200220013602f00602400240200041ff01714101460d00200241013602f806200141003a0000200241c0026a290300210e024020022802f4062200417f6a41074b0d00200041017422034109200341094b1b22034100480d09200120002003102c2201450d04200220033602f406200220013602f0060b200241093602f8062001200e370001200241d0026a2802002100200241d8026a2802002201200241f0066a10b40102402001450d0020002001410c6c6a2108034020002802002106200041086a2802002201200241f0066a10b4010240024020022802f406220520022802f80622036b2001490d0020022802f00621050c010b200320016a22072003490d0b200541017422042007200420074b1b22074100480d0b0240024020050d002007102821050c010b20022802f00620052007102c21050b2005450d07200220073602f406200220053602f0060b2002200320016a3602f806200520036a20062001109a051a2000410c6a22002008470d000b0b200241dc026a2802002100200241e4026a2802002201200241f0066a10b4010240024020010d0020022802f406210620022802f80621080c010b20002001410c6c6a2104034020002802002107200041086a2802002201200241f0066a10b4010240024020022802f406220620022802f80622036b2001490d0020022802f00621050c010b200320016a22052003490d0b200641017422082005200820054b1b22084100480d0b0240024020060d002008102821050c010b20022802f00620062008102c21050b2005450d08200220083602f406200220053602f006200821060b2002200320016a22083602f806200520036a20072001109a051a2000410c6a22002004470d000b0b200241c8026a290300210e02400240200620086b4108490d0020022802f00621030c010b200841086a22012008490d09200641017422002001200020014b1b22014100480d090240024020060d002001102821030c010b20022802f00620062001102c21030b2003450d07200220013602f406200220033602f0060b2002200841086a3602f806200320086a200e370000024020022802f40620022802f8062201470d00200141016a22002001490d09200141017422052000200520004b1b22004100480d090240024020010d002000102821030c010b200320012000102c21030b2003450d08200220003602f406200220033602f0060b2002200141016a22053602f806200320016a20022d00e8023a00000c010b200241013602f806200141013a0000200241b8026a410172200241f0066a10c60320022802f806210520022802f00621030b024020022d00b8020d000240200241d8026a2802002200450d00200241d0026a28020021012000410c6c210003400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241d4026a280200450d0020022802d002102a0b0240200241e4026a2802002200450d00200241dc026a28020021012000410c6c210003400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241e0026a280200450d0020022802dc02102a0b200241d00c6a24002005ad4220862003ad840f0b410141011037000b200341011037000b200741011037000b200841011037000b200141011037000b200041011037000b1031000bd40505017f027e077f017e017f230041206b220324002002290300210420012903002105200141106a2106200228021021070240024002400240024002400240200141146a2802002208200141186a28020022096b200241186a280200220a490d00200628020021080c010b2009200a6a220b2009490d032008410174220c200b200c200b4b1b220bad420c7e220d422088a70d03200da7220c4100480d030240024020080d00200c102821080c010b20062802002008410c6c200c102c21080b2008450d0120012008360210200141146a200b3602000b20082009410c6c6a2007200a410c6c109a051a200141186a2009200a6a36020020024100360218200341086a200641086a280200360200200320062902003703002001411c6a2106200228021c210b02400240200141206a2802002208200141246a28020022096b200241246a280200220a490d00200628020021080c010b2009200a6a220c2009490d032008410174220e200c200e200c4b1b220cad420c7e220d422088a70d03200da7220e4100480d030240024020080d00200e102821080c010b20062802002008410c6c200e102c21080b2008450d022001200836021c200141206a200c3602000b427f200520047c220420042005541b210520082009410c6c6a200b200a410c6c109a051a200141246a2009200a6a36020020024100360224200341106a41086a200641086a28020036020020032006290200370310200229030822042001290308220d200d2004561b210420012d0028450d034101210120022d0028450d030c040b200c41041037000b200e41041037000b1031000b410021010b20002005370300200020032903003702102000200329031037021c200020013a002820002004370308200041186a200341086a280200360200200041246a200341106a41086a2802003602000240200241146a280200450d002007102a0b0240200241206a280200450d00200b102a0b200341206a24000ba13507037f017e037f017e147f027e107f230041d0036b2202240002400240024002400240024002400240024020014104490d0020002800002103101a4101470d07200241a8016a41086a22004200370300200242003703a801419be1c0004111200241a8016a1008200241e8006a41086a2000290300370300200220022903a80137036841002101200241003602a801200241e8006a4110200241a8016a100621000240024020022802a8012204417f460d002000450d0020044104490d01200028000021012000102a0b200241003602a801410141838ac100411c200241a8016a101b2100024002400240024020022802a8012204417f470d00410121040c010b2004ad22054220862005842105200045210420000d010b41002100410121060c010b2005422088a74105490d04200028000121070240024020002d00000d0020072003460d0141002106200720034f0d02410121060c020b4101210620072001490d010b410021060b200120034f0d022006450d020240410110282201450d00200141003a00000240200141014105102c2201450d0020012003360001410141838ac100411c4100200020041b22062005422088a7417f20061b20014105101c21062001102a024020042005a745720d002000102a0b20060d0a200241a8016a41086a22004200370300200242003703a80141c2e1c000410d200241a8016a1008200241e8006a41086a2000290300370300200220022903a801370368200241003602a801200241e8006a4110200241a8016a1006210002400240024020022802a8012201417f460d002000450d002002200136022c20022000360228200241a8016a200241286a107c20022802a8012208450d0220022902ac0121092001450d012000102a0c010b42002109410121080b200241186a109d042002280218210a2002280220220b4115490d07200b410176220c41ffffff3f71200c470d09200c4105742200417f4c0d094101210d024002402000450d0020001028220d450d010b200a41606a210e200a41a07f6a210f41002110410021114104211241002113200b211403400240024020142215417f6a22040d0041012107410021140c010b024002400240024002400240200a20044105746a20154105742216200a6a41406a4120109c054100480d002015417e6a2106200f20166a210041002114410021010340024020062001470d00201521070c080b200141016a2101200041206a20004120109c052104200041606a21002004417f4a0d000b200141016a21072001417f7320156a21040c010b200f20166a210002400340024020044101470d00410021040c020b2004417f6a2104200041206a20004120109c052101200041606a210020014100480d000b0b20152004490d012015200b4b0d03201520046b22074101762206450d00200e20166a2100200a20044105746a21010340200241a8016a41186a2216200141186a2217290000370300200241a8016a41106a2218200141106a2219290000370300200241a8016a41086a221a200141086a221b290000370300200220012900003703a801200041086a221c2900002105200041106a221d290000211e200041186a2214290000211f200120002900003700002017201f3700002019201e370000201b200537000020142016290300370000201d2018290300370000201c201a290300370000200020022903a801370000200041606a2100200141206a21012006417f6a22060d000b0b024020040d00200421140c050b0240200741094d0d00200421140c050b2015200b4b0d01201520046b2106200a20044105746a2116034020152004417f6a2214490d040240201520146b22074102490d00200a20044105746a2200200a20144105746a22044120109c05417f4a0d002004290000210520042000290000370000200241a8016a41186a221a200441186a2201290000370300200241a8016a41106a221b200441106a2217290000370300200241a8016a41086a221c200441086a22182900003703002018200041086a2900003700002017200041106a2900003700002001200041186a290000370000200220053703a80141012119024020074103490d00200441c0006a200241a8016a4120109c05417f4a0d00410221012016210002400340200041186a200041386a290000370000200041106a200041306a290000370000200041086a200041286a2900003700002000200041206a221729000037000020062001460d01200041c0006a21182001211920172100200141016a21012018200241a8016a4120109c05417f4a0d020c000b0b200121190b200420194105746a220020022903a801370000200041186a201a290300370000200041106a201b290300370000200041086a201c2903003700000b2014450d05201641606a2116200641016a2106201421042007410a4f0d050c000b0b200420151044000b20152004417f6a2214490d010b2015200b103c000b201420151044000b02400240024020132011470d00201141016a22002011490d11201141017422012000200120004b1b220041ffffffff01712000470d11200041037422014100480d110240024020110d002001102821120c010b201220114103742001102c21120b2012450d0120002111201021130b201220134103746a2200200736020420002014360200201041016a2213211020134102490d0102400340024002400240024020122013417f6a22104103746a2200280200450d00201341037420126a220641746a2802002204200028020422014d0d000240201341024b0d0020132110410221130c080b20122013417d6a221a4103746a2802042200200120046a4d0d010240201341034b0d0020132110410321130c080b200641646a280200200020046a4d0d01201321100c070b20134103490d012000280204210120122013417d6a221a4103746a28020421000b20002001490d010b2013417e6a211a0b0240024002400240024002402013201a41016a22204b2221450d002013201a4b2222450d012012201a4103746a221b2802042223201b2802006a2200201220204103746a221c280200221d490d022000200b4b0d03200a201d4105746a2218201c280204221941057422016a2106200041057421042000201d6b221520196b220020194f0d04200d200620004105742201109a05221720016a21070240024020194101480d00200041014e0d010b20062100201721010c060b200e20046a21042006210003402004200041606a2206200741606a2215201520064120109c0541004822161b2201290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a2900003700002007201520161b2107024020182006200020161b2200490d00201721010c070b200441606a21042017210120172007490d000c060b0b41b8dbc000202020131034000b41b8dbc000201a20131034000b201d20001044000b2000200b103c000b200d20182001109a05221720016a21070240024020194101480d00201520194a0d010b20182100201721010c010b200a20046a211620172101201821000340200020062001200620014120109c0541004822151b2204290000370000200041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a2900003700002001200141206a20151b2101200041206a2100200641206a200620151b220620164f0d01200720014b0d000b0b20002001200720016b416071109a051a02402022450d00201b201d360200201b41046a202320196a3602002021450d02201c201c41086a20132020417f736a410374109b051a20102113201041014d0d040c010b0b41c8dbc000201a20131034000b41b0b1c0001032000b200141041037000b20140d000b02402011450d002012102a0b200c450d09200d102a0c090b200041011037000b41c4d1c3004133200241186a419cd9c3001038000b410541011037000b410141011037000b41c4d1c3004133200241186a419cd9c3001038000b200241f4006a4104360200200241bc016a4102360200200242023702ac01200241bca7c4003602a8012002410436026c200241c8a9c4003602682002410036022c200241b8aec6003602282002200241e8006a3602b8012002200241286a360270200241a8016a41cca7c400103e000b20042005a745720d052000102a0c050b02402005a7450d002000102a0b41e695c600412d100b0c040b200b4102490d00200a200b417f6a22014105746a21074101210403400240024002400240200b20012200417f6a2201490d00200b20016b22154102490d03200a20004105746a2200200a20014105746a22064120109c05417f4a0d032006290000210520062000290000370000200241a8016a41186a2213200641186a2216290000370300200241a8016a41106a2219200641106a2217290000370300200241a8016a41086a2212200641086a22182900003703002018200041086a2900003700002017200041106a2900003700002016200041186a290000370000200220053703a8014101210020154103490d02200641c0006a200241a8016a4120109c05417f4a0d0241002115200721000340200041186a200041386a290000370000200041106a200041306a290000370000200041086a200041286a2900003700002000200041206a2217290000370000200420152216460d022016417f6a2115200041c0006a2118201721002018200241a8016a4120109c05417f4a0d020c000b0b2001200b1044000b410220166b21000b200620004105746a220020022903a801370000200041186a2013290300370000200041106a2019290300370000200041086a20122903003700000b200741606a21072004417f6a210420010d000b0b2009a721102009422088a72200450d01200820004105746a2118200241a8016a41016a211a200241c0026a2124200241e9026a211b200241e0016a2125200241a8016a41306a2126200241a8016a41286a212741002115200821070240024002400240024002400340024002400240200b41014b0d000240200b0e020c000c0b0340200241a8016a41186a200741186a290000370300200241a8016a41106a200741106a290000370300200241a8016a41086a200741086a290000370300200220072900003703a801200a200241a8016a4120109c05450d02201541016a21152018200741206a2207470d000c0c0b0b0340200241a8016a41186a200741186a290000370300200241a8016a41106a200741106a290000370300200241a8016a41086a200741086a290000370300200220072900003703a801200741206a21070240200b450d0041002100200b210103402001410176220420006a22062000200a20064105746a200241a8016a4120109c054101481b2100200120046b220141014b0d000b200a20004105746a200241a8016a4120109c05450d030b201541016a211520072018460d0b0c000b0b200741206a2107410021000b0240024002400240024002400240200b20004d0d0020024100360268200241e8006a101d2104024020022802682201417f470d00410221060c0a0b200220013602ac01200220043602a8012001450d0320042d0000210620022001417f6a3602ac012002200441016a3602a801200641014b0d030240024020060e020100010b410021202021210c2012211c2019211420132128201721292016211d2021212a2012212b2019212c2013212d2017212e2016212f0c060b200241106a200241a8016a106c20022802100d0320022802ac0122062002280214222b490d03202b417f4c0d0e02400240202b0d004101212041010d010c050b202b102e2220450d02202020022802a801221c202b109a05211d20022006202b6b3602ac012002201c202b6a3602a801201d450d040b200241086a200241a8016a106c20022802080d0220022802ac01410c6e222e410c6c2206417f4c0d0e200228020c212f0240024002400240024020060d004104212d0c010b20061028222d450d010b024002400240202f0d00202d212c0c010b4100210c4100211c41002114202d212c03402002200241a8016a106c20022802000d0220022802ac01221d20022802042206490d022006417f4c0d140240024020060d00410121290c010b2006102e2229450d05202920022802a80122282006109a051a2002201d20066b3602ac012002202820066a3602a8010b201441016a211d02402014202e470d00200c201d200c201d4b1b222ead420c7e2205422088a70d182005a722284100480d180240024020140d0020281028212d0c010b202d201c2028102c212d0b202d450d06202d212c0b202c201c6a22142029360200201441046a2006ad2205422086200584370200200c41026a210c201c410c6a211c201d2114202f201d470d000b0b202c450d06202b212a202f211d202e2129202d2128202c2114202b211c202b210c20200d080c070b02402014450d004100210603400240202c20066a221d41046a280200450d00201d280200102a0b201c2006410c6a2206470d000b0b202e450d05202d102a0c050b200641041037000b200641011037000b202841041037000b41a08ac1002000200b1034000b202b41011037000b202b450d002020102a0b410021202016212f2017212e2013212d2019212c2012212b2021212a2022211d20232129200d212820112114200e211c200f210c0b2001450d010b2004102a0b024020200d00410221060c030b10fb012121200241003602b001200242013703a80102400240024002400240410410282201450d0020024284808080c0003702ac01200220013602a80120012003360000201c200241a8016a10b4010240024020022802ac01220420022802b00122016b201c490d0020022802a80121040c010b2001201c6a22062001490d10200441017422162006201620064b1b22064100480d100240024020040d002006102821040c010b20022802a80120042006102c21040b2004450d02200220063602ac01200220043602a8010b20022001201c6a3602b001200420016a2020201c109a051a201d200241a8016a10b401201d450d022014201d410c6c6a211220142104034020042802002113200441086a2802002201200241a8016a10b4010240024020022802ac01221620022802b00122066b2001490d0020022802a80121170c010b200620016a22172006490d11201641017422192017201920174b1b22194100480d110240024020160d002019102821170c010b20022802a80120162019102c21170b2017450d05200220193602ac01200220173602a801201921160b2002200620016a22193602b001201720066a20132001109a051a2004410c6a22042012470d000c050b0b410441011037000b200641011037000b20022802ac01211620022802b00121190c010b201941011037000b02400240201620196b4104490d0020022802a80121010c010b201941046a22012019490d0b201641017422042001200420014b1b22044100480d0b0240024020160d002004102821010c010b20022802a80120162004102c21010b2001450d04200220043602ac01200220013602a801200421160b2002201941046a22043602b001200120196a202136000002400240201620046b41034d0d00201621060c010b200441046a22062004490d0b201641017422172006201720064b1b22064100480d0b0240024020160d002006102821010c010b200120162006102c21010b2001450d05200220063602ac01200220013602a8010b200120046a2015360000200241e9dabdf3063602cc03202542003703002026420037030020274200370300200241a8016a41206a4200370300200241a8016a41186a4200370300200241a8016a41106a4200370300200241a8016a41086a4200370300200242003703a8010240200241cc036a200a20004105746a2001201941086a200241a8016a101e0d00200241e8006a41086a2200201a41086a290000370300200241e8006a41106a2204201a41106a290000370300200241e8006a41186a2216201a41186a290000370300200241e8006a41206a2217201a41206a290000370300200241e8006a41286a2213201a41286a290000370300200241e8006a41306a2219201a41306a290000370300200241e8006a41376a2212201a41376a2900003700002002201a29000037036820022d00a8012122200241286a41086a22232000290300370300200241286a41106a22002004290300370300200241286a41186a22042016290300370300200241286a41206a22162017290300370300200241286a41286a22172013290300370300200241286a41306a22132019290300370300200241286a41376a221920122900003700002002200229036837032802402006450d002001102a0b201b2002290328370000201b41086a2023290300370000201b41106a2000290300370000201b41186a2004290300370000201b41206a2016290300370000201b41286a2017290300370000201b41306a2013290300370000201b41376a2019290000370000200220223a00e802200220153602e402200220213602e0022002201d3602dc02200220293602d802200220283602d4022002201c3602d0022002200c3602cc02200220203602c802200220033602c402200241123602c0022002420237039002200241e8006a200241a8016a108704200228026c2100200228026822042002280270101f210102402000450d002004102a0b2024106a20010d02410110282200450d06200041013a0000200041014105102c2200450d07201541016a211520002003360001410141838ac100411c2000410510202000102a202f2116202e2117202d2113202c2119202b2112202a2121201d2122202921232028210d20142111201c210e200c210f20072018470d010c090b0b02402006450d002001102a0b0240200c450d002020102a0b0240201d450d00201d410c6c210003400240201441046a280200450d002014280200102a0b2014410c6a2114200041746a22000d000b0b410121062029450d012028102a0c010b410321060b02402010450d002008102a0b0240200228021c450d00200a102a0b412e2104419396c6002100200241186a2101024002400240024020060e0400010203000b412d210441e695c6002100200241286a21010c020b411f210441c795c6002100200241e8006a21010c010b419995c6002100200241a8016a21010b200120043602042001200036020020002004100b0c060b200441011037000b200641011037000b410141011037000b410541011037000b1036000b02402010450d002008102a0b200228021c450d00200a102a0b200241d0036a240042010f0b1031000bcb06020d7f037e230041e0006b22012400200141e9dabdf306360208410021022001410036020c200141086a2001410c6a102621032001200128020c360214200120033602102001200141106a106c2001280204210441002105024002400240024020012802000d00200128021422034160712206417f4c0d0202400240200341057622070d00410121050c010b200610282205450d020b2004450d0041002108034020032109200141003a00582008220a41016a2108410021030240024002400240034020092003460d01200141386a20036a200128021022062d00003a00002001200641016a3602102001200341016a22063a00582006210320064120470d000b200141186a41186a220b200141386a41186a290300370300200141186a41106a220c200141386a41106a290300370300200141186a41086a220d200141386a41086a290300370300200120012903383703182007200a470d03200a41017422032008200320084b1b220741ffffff3f712007470d082007410574220341004e0d010c080b200141003602140240200341ff0171450d00200141003a00580b2007450d012005102a0c010b02400240200a0d002003102821050c010b2005200a4105742003102c21050b20050d01200341011037000b410021050c020b200920066b21032005200a4105746a220a2001290318370000200a41186a200b290300370000200a41106a200c290300370000200a41086a200d29030037000020082004470d000b2001200920066b3602140b4101210a2005410120051b21084100210302402004410020051b2206450d0020064105742203410575220241ffffff3f712002470d03200241057422094100480d03024020091028220a0d00200941011037000b200820036a210420064105742109200a2103200821060340200641086a290000210e200641106a290000210f20062900002110200341186a200641186a290000370000200341106a200f370000200341086a200e37000020032010370000200341206a2103200641206a2106200941606a22090d000b200420086b41606a41057641016a21030b02402005450d002007450d002008102a0b20002003360208200020023602042000200a360200200141e0006a24000f0b200641011037000b1036000b1031000bf80303047f027e037f230041306b22022400200241106a41086a220342003703002002420037031041c694c600411b200241106a1008200241086a200329030037030020022002290310370300410021032002410036021020024110200241106a100621040240024002400240024020022802102205417f470d000c010b2002200536022420022004360220200241106a200241206a107720022802102203450d01200229021421062005450d002004102a0b20024100360218200242013703102006420020031b2207422088a72205200241106a10b4012003410820031b210802402005450d002008200541286c6a21092008210503402005200241106a108f01200541206a29030021060240024020022802142204200228021822036b4108490d00200228021021040c010b200341086a220a2003490d0520044101742203200a2003200a4b1b22034100480d050240024020040d002003102821040c010b200228021020042003102c21040b2004450d042002200336021420022004360210200228021821030b2002200341086a360218200420036a20063700002009200541286a2205470d000b0b200235021821062002280210210302402007a7450d002008102a0b200241306a240020064220862003ad840f0b41c4d1c3004133200241286a419cd9c3001038000b200341011037000b1031000b9d0d04047f017e027f017e230041c0016b22022400200241086a41086a220342003703002002420037030841eefbc5004110200241086a1008200241a0016a41086a2003290300370300200220022903083703a0014100210320024100360208200241a0016a4110200241086a10062104024002400240024002400240024002400240024020022802082205417f470d000c010b024020040d000c010b2002200536027c20022004360278200241086a200241f8006a107720022802082203450d01200229020c21062005450d002004102a0b200241086a41086a2205420037030020024200370308419efcc500410f200241086a1008200241a0016a41086a22042005290300370300200220022903083703a001200241f8006a200241a0016a10ef0220022d00782105200241a0016a41186a220720024191016a290000370300200241a0016a41106a220820024189016a290000370300200420024181016a290000370300200220022900793703a0012006420020031b21062003410820031b21030240024020054101460d00200241d8006a41186a4200370300200241d8006a41106a4200370300200241d8006a41086a4200370300200242003703580c010b200241d8006a41186a2007290300370300200241d8006a41106a2008290300370300200241d8006a41086a2004290300370300200220022903a0013703580b2002412c6a2006370200200241086a41186a42043703002002413c6a200241d8006a41086a290300370200200241c4006a200241e8006a290300370200200241cc006a200241d8006a41186a2903003702002002200336022820024201370318200242c801370310200242b81737030820022002290358370234200241013a0054200241003602800120024201370378410810282203450d012002410836027c2002200228028001220441086a3602800120022003360278200320046a42b8173700002002290310210602400240200228027c220420022802800122036b4108490d00200228027821040c010b200341086a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102821040c010b200228027820042003102c21040b2004450d032002200336027c2002200436027820022802800121030b2002200341086a36028001200420036a20063700002002290318210602400240200228027c220420022802800122036b4108490d00200228027821040c010b200341086a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102821040c010b200228027820042003102c21040b2004450d042002200336027c2002200436027820022802800121030b2002200341086a36028001200420036a20063700002002290320210602400240200228027c220420022802800122036b4108490d00200228027821040c010b200341086a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102821040c010b200228027820042003102c21040b2004450d052002200336027c2002200436027820022802800121030b2002200341086a36028001200420036a200637000020022802282104200241086a41286a2802002203200241f8006a10b40102402003450d002004200341286c6a210803402004200241f8006a108f01200441206a290300210602400240200228027c220520022802800122036b4108490d00200228027821050c010b200341086a22072003490d0a200541017422032007200320074b1b22034100480d0a0240024020050d002003102821050c010b200228027820052003102c21050b2005450d082002200336027c2002200536027820022802800121030b2002200341086a36028001200520036a20063700002008200441286a2204470d000b0b200241346a200241f8006a10f10202400240200228027c2002280280012203460d00200228027821040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102821040c010b200228027820032005102c21040b2004450d072002200536027c2002200436027820022802800121030b2002200341016a36028001200420036a20022d00543a00002002350280012106200235027821090240200228022c450d002002280228102a0b200241c0016a240020064220862009840f0b41c4d1c3004133200241d8006a419cd9c3001038000b410841011037000b200341011037000b200341011037000b200341011037000b200341011037000b200541011037000b1031000baa0607017f017e077f017e027f017e027f230041c0006b2202240042002103200241086a2204420037030020024200370300419695c400411720021008200241206a41086a20042903003703002002200229030037032020024100360200200241206a411020021006210502400240024002400240024020022802002204417f460d0020022004360234200220053602302002200241306a107c20022802002206450d02200229020421032004450d012005102a0c010b410121060b41002107024002402003422088a7220441057422080d00410421094100210a0c010b2008410575220aad420c7e220b422088a70d04200ba722054100480d04200510282209450d020b2003a7210c02402004450d00200841606a210d20092105200621040340200441086a2900002103200441106a290000210b2004290000210e200241186a200441186a290000370300200241106a200b370300200241086a20033703002002200e370300200241206a2002108b04200541086a200241206a41086a280200360200200520022903203702002005410c6a2105200441206a2104200841606a22080d000b200d41057641016a21070b0240200c450d002006102a0b20024100360208200242013703002007200210b4010240024020070d002002280208210d200228020021060c010b20092007410c6c6a210f2009210503402005280200210c200541086a2802002204200210b4010240024020022802042206200228020822086b2004490d00200228020021060c010b200820046a220d2008490d0620064101742210200d2010200d4b1b220d4100480d060240024020060d00200d102821060c010b20022802002006200d102c21060b2006450d052002200d360204200220063602000b2002200820046a220d360208200620086a200c2004109a051a2005410c6a2205200f470d000b2007410c6c21052009210403400240200441046a280200450d002004280200102a0b2004410c6a2104200541746a22050d000b0b0240200a450d002009102a0b200241c0006a2400200dad4220862006ad840f0b41c4d1c3004133200241386a419cd9c3001038000b200541041037000b200d41011037000b1031000baf1905047f017e057f037e3c7f230041d0016b22022400024002402001450d00200220003602100c010b200241013602100b20022001360214200241086a200241106a106c024002400240024002400240024002400240024002400240024020022802080d0020022802142201200228020c2200490d002000417f4c0d010240024020000d00410121030c010b2000102e2203450d032003200228021022042000109a051a2002200120006b3602142002200420006a3602100b2003450d0020024188016a41086a220142003703002002420037038801419695c400411720024188016a1008200241e8006a41086a200129030037030020022002290388013703682002410036028801200241e8006a411020024188016a10062101024002402002280288012204417f460d002001450d002002200436025c2002200136025820024188016a200241d8006a107c2002280288012205450d05200229028c0121062004450d012001102a0c010b41012105420021060b200241d8006a109d044100210702402006422088a72201450d00200520014105746a21082002280258220920022802604105746a210a2005210b0340200b41086a290000210c200b41106a290000210d200b290000210e20024188016a41186a200b41186a29000037030020024188016a41106a200d37030020024188016a41086a200c3703002002200e37038801200b41206a210b20092101024003400240200a20016b41e0004b0d0002402001200a460d00034020024188016a2001460d04200120024188016a4120109c05450d04200a200141206a2201470d000b0b200b2008470d030c040b200120024188016a460d01200120024188016a4120109c05450d01200141206a220420024188016a460d01200420024188016a4120109c05450d01200141c0006a220420024188016a460d01200420024188016a4120109c05450d01200141e0006a220420024188016a460d0120014180016a2101200420024188016a4120109c050d000b0b0b200241e8006a41186a20024188016a41186a290300220c370300200241386a41086a20024188016a41086a290300370300200241386a41106a20024188016a41106a290300370300200241386a41186a200c3703002002200229038801370338410121070b2006a721010240200228025c450d002002280258102a0b02402001450d002005102a0b200241e8006a41186a2201200241386a41186a290300370300200241e8006a41106a2204200241386a41106a290300370300200241e8006a41086a220b200241386a41086a290300370300200220022903383703682007450d0b200241186a41186a2001290300370300200241186a41106a2004290300370300200241186a41086a200b29030037030020022002290368370318200241e9dabdf306360268200241c0016a4200370300200241b8016a4200370300200241b0016a4200370300200241a8016a420037030020024188016a41186a420037030020024188016a41106a420037030020024188016a41086a4200370300200242003703880102400240200241e8006a200241186a2003200020024188016a101e450d00410021010c010b4101210120022d00c701210f20022d00c601211020022d00c501211120022d00c401211220022d00c301211320022d00c201211420022d00c101211520022d00c001211620022d00bf01211720022d00be01211820022d00bd01211920022d00bc01211a20022d00bb01211b20022d00ba01211c20022d00b901211d20022d00b801211e20022d00b701211f20022d00b601212020022d00b501212120022d00b401212220022d00b301212320022d00b201212420022d00b101212520022d00b001212620022d00af01212720022d00ae01212820022d00ad01212920022d00ac01212a20022d00ab01212b20022d00aa01212c20022d00a901212d20022d00a801212e20022d00a701212f20022d00a601213020022d00a501213120022d00a401213220022d00a301213320022d00a201213420022d00a101213520022d00a001213620022d009f01213720022d009e01213820022d009d01213920022d009c01213a20022d009b01213b20022d009a01213c20022d009901213d20022d009801213e20022d009701213f20022d009601214020022d009501214120022d009401214220022d009301214320022d009201214420022d009101214520022d009001214620022d008f01214720022d008e01214820022d008d01214920022d008c01214a20022d008b01210820022d008a01210920022d008901210720022d00880121050b20024188016a41186a2204200241186a41186a29030037030020024188016a41106a220b200241186a41106a29030037030020024188016a41086a220a200241186a41086a29030037030020022002290318370388012001450d0b200241e8006a41186a20042903002206370300200241e8006a41106a200b290300220c370300200241e8006a41086a200a290300220d3703002002200229038801220e37036820042006370300200b200c370300200a200d3703002002200e37038801410110282201450d04200120053a0000200141014102102c2201450d05200120073a0001200141024104102c2201450d06200120083a0003200120093a0002200141044108102c2201450d07200120473a0007200120483a0006200120493a00052001204a3a0004200141084110102c2201450d082001203f3a000f200120403a000e200120413a000d200120423a000c200120433a000b200120443a000a200120453a0009200120463a0008200141104120102c2201450d092001202f3a001f200120303a001e200120313a001d200120323a001c200120333a001b200120343a001a200120353a0019200120363a0018200120373a0017200120383a0016200120393a00152001203a3a00142001203b3a00132001203c3a00122001203d3a00112001203e3a00102001412041c000102c2201450d0a2001200f3a003f200120103a003e200120113a003d200120123a003c200120133a003b200120143a003a200120153a0039200120163a0038200120173a0037200120183a0036200120193a00352001201a3a00342001201b3a00332001201c3a00322001201d3a00312001201e3a00302001201f3a002f200120203a002e200120213a002d200120223a002c200120233a002b200120243a002a200120253a0029200120263a0028200120273a0027200120283a0026200120293a00252001202a3a00242001202b3a00232001202c3a00222001202d3a00212001202e3a0020200241386a20024188016a108b042002280240210b200228023c2109200228023821050c0c0b200241f4006a41043602002002419c016a41023602002002420237028c01200241bca7c400360288012002410436026c200241e0a9c4003602682002410036023c200241b8aec6003602382002200241e8006a360298012002200241386a36027020024188016a41cca7c400103e000b1036000b200041011037000b41c4d1c3004133200241c8016a419cd9c3001038000b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b41c00041011037000b410021010b0240024002400240410110282204450d00200242818080801037028c0120022004360288010240024020010d00200441003a000042808080801021060c010b200441013a000041c00020024188016a10b40102400240200228028c01220720022802900122046b41c000490d00200441c0006a210a20022802880121070c010b200441c0006a220a2004490d0520074101742208200a2008200a4b1b22084100480d050240024020070d002008102821070c010b20022802880120072008102c21070b2007450d032002200836028c0120022007360288010b200720046a220441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a290000370000200441206a200141206a290000370000200441286a200141286a290000370000200441306a200141306a290000370000200441386a200141386a2900003700002002200a3602900120042001290000370000200b20024188016a10b40102400240200228028c012204200228029001220a6b200b490d0020022802880121040c010b200a200b6a2207200a490d05200441017422082007200820074b1b22074100480d050240024020040d002007102821040c010b20022802880120042007102c21040b2004450d042002200736028c0120022004360288010b2002200a200b6a2207360290012004200a6a2005200b109a051a2001102a2007ad42208621062009450d002005102a0b02402000450d002003102a0b200241d0016a240020062004ad840f0b410141011037000b200841011037000b200741011037000b1031000baf0e04077f027e047f077e23004190026b22022400024002402001450d00200220003602200c010b200241013602200b20022001360224200241186a200241206a106c024002400240024020022802180d0020022802242201200228021c2203490d000240024002402003417f4c0d000240024020030d00410121040c010b2003102e2204450d022004200228022022002003109a051a2002200120036b3602242002200020036a3602200b2004450d03200241106a200241206a106c20022802100d052002280224220120022802142200490d052000417f4c0d000240024020000d00410121050c010b2000102e2205450d032005200228022022062000109a051a2002200120006b3602242002200620006a3602200b2005450d05200241086a200241206a106c024020022802080d0020022802242206200228020c2201490d002001417f4c0d010240024020010d00410121070c010b2001102e2207450d062007200228022022082001109a051a2002200620016b3602242002200820016a3602200b2007450d002001ad2209422086200984210941002101200241003a00c8012000ad220a422086200a84220a422088a72108200521000240024002400240034020082001460d0120024188016a20016a20002d00003a00002002200141016a22063a00c801200041016a210020062101200641c000470d000b200241d0016a41386a220120024188016a41386a290300370300200241d0016a41306a220020024188016a41306a290300370300200241d0016a41286a220820024188016a41286a290300370300200241d0016a41206a220b20024188016a41206a290300370300200241d0016a41186a220c20024188016a41186a290300370300200241d0016a41106a220d20024188016a41106a290300370300200241d0016a41086a220e20024188016a41086a29030037030020022002290388013703d001200641ff017141c000490d02200241c8006a41386a22062001290300370300200241c8006a41306a2000290300220f370300200241c8006a41286a20082903002210370300200241c8006a41206a200b2903002211370300200241c8006a41186a200c2903002212370300200241c8006a41106a200d2903002213370300200241c8006a41086a200e2903002214370300200220022903d00122153703482000200f37030020082010370300200b2011370300200c2012370300200d2013370300200e201437030020012006290300370300200220153703d00141002101200241003a00a8012009422088a7210820072100034020082001460d0220024188016a20016a20002d00003a00002002200141016a22063a00a801200041016a21002006210120064120470d000b200241286a41186a220120024188016a41186a2200290300370300200241286a41106a220620024188016a41106a2208290300370300200241286a41086a220b20024188016a41086a220c290300370300200220022903880137032820024188016a41386a200241d0016a41386a29030037030020024188016a41306a200241d0016a41306a29030037030020024188016a41286a200241d0016a41286a29030037030020024188016a41206a200241d0016a41206a2903003703002000200241d0016a41186a2903003703002008200241d0016a41106a290300370300200c200241d0016a41086a290300370300200220022903d00137038801200241c8006a41186a2001290300370300200241c8006a41106a2006290300370300200241c8006a41086a200b290300370300200220022903283703482004200320024188016a200241c8006a100a4521000c030b200141ff0171450d01200241003a00c8010c010b200141ff0171450d00200241003a00a8010b410021000b410110282201450d07200120003a000002402009a7450d002007102a0b0240200aa7450d002005102a0b02402003450d002004102a0b20024190026a24002001ad428080808010840f0b200241dc016a41043602002002419c016a41023602002002420237028c01200241bca7c40036028801200241043602d401200241eca9c4003602d0012002410036024c200241b8aec6003602482002200241d0016a360298012002200241c8006a3602d80120024188016a41cca7c400103e000b1036000b200341011037000b200041011037000b200241dc016a41043602002002419c016a41023602002002420237028c01200241bca7c40036028801200241043602d401200241eca9c4003602d0012002410036024c200241b8aec6003602482002200241d0016a360298012002200241c8006a3602d80120024188016a41cca7c400103e000b200141011037000b200241dc016a41043602002002419c016a41023602002002420237028c01200241bca7c40036028801200241043602d401200241eca9c4003602d0012002410036024c200241b8aec6003602482002200241d0016a360298012002200241c8006a3602d80120024188016a41cca7c400103e000b410141011037000be30503037f047e017f230041a0016b2202240041002103200241003a00482000410120011b2104024002400240024002400240034020012003460d01200241286a20036a200420036a2d00003a00002002200341016a22003a00482000210320004120470d000b200241086a41186a200241286a41186a22002903002205370300200241086a41106a200241286a41106a22012903002206370300200241086a41086a200241286a41086a22042903002207370300200220022903282208370308200241d0006a41186a2005370300200241d0006a41106a2006370300200241d0006a41086a200737030020022008370350411310282203450d03200341002900cef0423700002003410f6a41002800ddf042360000200341086a41002900d6f04237000020024293808080b002370294012002200336029001200241d0006a20024190016a108f01200228029801210320022802900121092000420037030020014200370300200442003703002002420037032820092003200241286a1000200241f0006a41186a2000290300370300200241f0006a41106a2001290300370300200241f0006a41086a2004290300370300200220022903283703700240200228029401450d00200228029001102a0b20024100360228200241f0006a4120200241286a1006210320022802282200417f470d01410021000c020b0240200341ff0171450d00200241003a00480b2002413c6a4102360200200241fc006a41043602002002420237022c200241bca7c40036022820024104360274200241fca9c40036027020024100360254200241b8aec6003602502002200241f0006a3602382002200241d0006a360278200241286a41cca7c400103e000b024020030d00410021000c010b20004104490d02200328000021002003102a0b410410282203450d0220032000360000200241a0016a24002003ad4280808080c000840f0b411341011037000b41c4d1c3004133200241286a419cd9c3001038000b410441011037000b880f03057f037e017f230041c0016b22022400024020010d00410121000b200220003602082002200136020c41002103200241003a00702001417f6a21040340024020012003470d000240200341ff0171450d00200241003a00700b200241e4006a41023602002002419c016a410436020020024202370254200241bca7c400360250200241043602940120024194aac4003602900120024100360234200241b8aec600360230200220024190016a3602602002200241306a36029801200241d0006a41cca7c400103e000b200241d0006a20036a200020036a22052d00003a00002002200541016a3602082002200341016a22053a00702002200436020c2004417f6a21042005210320054120470d000b200241106a41086a200241d0006a41086a290300370300200241106a41106a200241d0006a41106a290300370300200241106a41186a200241d0006a41186a2903003703002002200229035037031041002103200241003a0070200120056b2106200020056a2100417f21010340024020062003470d000240200341ff0171450d00200241003a00700b200241e4006a41023602002002419c016a410436020020024202370254200241bca7c400360250200241043602940120024194aac4003602900120024100360234200241b8aec600360230200220024190016a3602602002200241306a36029801200241d0006a41cca7c400103e000b200241d0006a20036a200020036a22052d00003a00002002200420036b36020c2002200541016a3602082002200341016a22053a00702001417f6a21012005210320054120470d000b200241306a41086a200241d0006a41086a290300370300200241306a41106a200241d0006a41106a290300370300200241306a41186a200241d0006a41186a290300370300200220022903503703300240024002400240024002400240024002400240024002400240200420056b220441016a4110490d002002200020056a220341106a3602082002200441716a220536020c20054108490d0220032900002107200341086a29000021082002200441696a36020c2002200341186a360208200341106a29000021092002200241086a106c20022802000d0c200228020c2205200228020422034f0d010c0c0b2002419c016a4104360200200241e4006a410236020020024202370254200241bca7c400360250200241043602940120024194aac400360290012002410036027c200241b8aec600360278200220024190016a3602602002200241f8006a36029801200241d0006a41cca7c400103e000b2003417f4c0d0302400240024020030d00410121044101450d0d0c010b2003102e2204450d012004200228020822012003109a0521002002200520036b36020c2002200120036a3602082000450d0c0b20024190016a41186a200241106a41186a29030037030020024190016a41106a200241106a41106a29030037030020024190016a41086a200241106a41086a2903003703002002200229031037039001200241d0006a41186a200241306a41186a290300370300200241d0006a41106a200241306a41106a290300370300200241d0006a41086a200241306a41086a29030037030020022002290330370350200220033602b801200220033602b401200220043602b001200241f8006a20024190016a200241d0006a200720082009200241b0016a10f50320022802784101460d0220024184016a2802002104200241f8006a41086a2802002100200228027c210520022d00880121010c030b200341011037000b2002419c016a4104360200200241e4006a410236020020024202370254200241bca7c400360250200241043602940120024194aac400360290012002410036027c200241b8aec600360278200220024190016a3602602002200241f8006a36029801200241d0006a41cca7c400103e000b0240200228028801450d0020024184016a280200102a0b410021050b200241003602582002420137035041011028210302402005450d002003450d02200242818080801037025420022003360250200341003a0000200341014102102c2203450d03200242828080802037025420022003360250200320013a00012004200241d0006a10b401024020022802542203200228025822016b2004490d00200228025021030c070b0240200120046a22062001490d002003410174220a2006200a20064b1b22064100480d000240024020030d002006102821030c010b200228025020032006102c21030b2003450d0520022006360254200220033602500c070b1031000b2003450d04200242818080801037025420022003360250200341013a000042808080801021070c060b1036000b410141011037000b410241011037000b200641011037000b410141011037000b2002200120046a2206360258200320016a20052004109a051a2006ad42208621072005450d002000450d002005102a0b200241c0016a240020072003ad840f0b2002419c016a4104360200200241e4006a410236020020024202370254200241bca7c400360250200241043602940120024194aac400360290012002410036027c200241b8aec600360278200220024190016a3602602002200241f8006a36029801200241d0006a41cca7c400103e000bc00c03047f017e067f23004180026b220224000240024020010d002002200136020c200241013602080c010b20022001417f6a36020c410121032002200041016a36020820002d0000220141014b0d0041002104410021000240024002400240024002400240024020010e020100010b2002200241086a106c20022802000d07200228020c220120022802042200490d072000417f4c0d010240024020000d00410121040c010b2000102e2204450d032004200228020822052000109a051a2002200120006b36020c2002200520006a3602080b2004450d07200241106a20042000ad22064220862006842206422088a7105420022802104101460d03200241186a280200210520022802142100410021030b2002200536021420022000360210200241e7e485f3063602b001200241d0016a41186a22074200370300200241d0016a41106a22084200370300200241d0016a41086a22094200370300200242003703d00141002101200241106a410020001b210a0240024020000d004100210b0c010b200a41046a280200210c200a280200210b0b200241b0016a200b4101200b1b200c4100200b1b200241d0016a1021200241f0006a41186a2007290300370300200241f0006a41106a2008290300370300200241f0006a41086a2009290300370300200220022903d0013703702002200536021420022000360210200241e2c289ab063602b001200742003703002008420037030020094200370300200242003703d0010240024020000d000c010b200a41046a280200210b200a28020021010b200241b0016a2001410120011b200b410020011b200241d0016a102220024190016a41186a2207200241d0016a41186a220129030037030020024190016a41106a2208200241d0016a41106a220b29030037030020024190016a41086a2209200241d0016a41086a220a290300370300200220022903d00137039001200220053602fc01200220003602f801200241e9dabdf3063602f40120014200370300200b4200370300200a4200370300200242003703d0010240024020000d00410021000c010b200241f8016a410020001b220041046a2802002105200028020021000b200241f4016a2000410120001b2005410020001b200241d0016a1022200241b0016a41186a22002001290300370300200241b0016a41106a2201200b290300370300200241b0016a41086a2205200a290300370300200241106a41086a200241f0006a41086a290300370300200241106a41106a200241f0006a41106a290300370300200241106a41186a200241f0006a41186a290300370300200220022903d0013703b00120022002290370370310200241c8006a2007290300370300200241c0006a2008290300370300200241386a20092903003703002002200229039001370330200241e8006a2000290300370300200241e0006a2001290300370300200241d8006a2005290300370300200220022903b001370350200241003602d801200242013703d001200241106a200241d0016a108f01200241306a200241d0016a108f01200241d0006a200241d0016a108f0120022802d801210020022802d401210a20022802d001210b024020032006a745720d002004102a0b200041046a2201417f4c0d000240024020010d00410121050c010b200110282205450d040b2002410036021820022001360214200220053602102000200241106a10b4010240024020022802142205200228021822016b2000490d00200228021021050c010b200120006a22042001490d06200541017422072004200720044b1b22044100480d060240024020050d002004102821050c010b200228021020052004102c21050b2005450d0520022004360214200220053602100b200520016a200b2000109a051a200120006a21000240200a450d00200b102a0b20024180026a24002000ad4220862005ad840f0b1036000b200041011037000b200220022902143703d001419fdbc0004116200241d0016a41d4c7c0001038000b200141011037000b200441011037000b1031000b200241dc016a4104360200200241246a410236020020024202370214200241bca7c400360210200241043602d4012002419caac4003602d001200241003602b401200241b8aec6003602b0012002200241d0016a3602202002200241b0016a3602d801200241106a41cca7c400103e000b823305087f017e067f037e037f23004180066b220124000240024002400240411210282202450d00200241002900c1ae44370000200241106a41002f00d1ae443b0000200241086a41002900c9ae4437000020014292808080a0023702e404200120023602e0042000200141e0046a108f0120012802e804210220012802e0042100200141a0046a41186a22034200370300200141a0046a41106a22044200370300200141a0046a41086a22054200370300200142003703a00420002002200141a0046a1000200141c8006a41186a2003290300370300200141c8006a41106a2004290300370300200141c8006a41086a2005290300370300200120012903a004370348024020012802e404450d0020012802e004102a0b200141003602e004200141c8006a4120200141e0046a1006210620012802e0042207417f460d022006450d02200120073602e405200120063602e005200141306a200141e0056a109f0120012802300d0120012802e4052202450d0120012002417f6a22033602e405200120012802e005220541016a22043602e00520052d0000220241014b0d01410021080240024020020e020100010b41002102200141003a0080050340024020032002470d00200141003602e405200241ff0171450d04200141003a0080050c040b200141e0046a20026a200520026a220041016a2d00003a00002001200041026a3602e0052001200241016a22003a0080052000210220004120470d000b200141a0046a41086a200141e0046a41086a2903002209370300200141e8016a41186a200141e0046a41186a290300370300200141e8016a41106a200141e0046a41106a290300370300200141e8016a41086a20093703002001200320006b22033602e405200120012903e00422093703a004200120093703e80141012108200520006a41016a21040b20014180046a41186a200141e8016a41186a29030037030020014180046a41106a200141e8016a41106a29030037030020014180046a41086a200141e8016a41086a290300370300200120012903e801370380042003450d0120012003417f6a22033602e4052001200441016a3602e00520042d0000220041014b0d01410021020240024020000e020100010b41002102200141003a0080050340024020032002470d00200141003602e405200241ff0171450d04200141003a0080050c040b200141e0046a20026a200420026a220041016a2d00003a00002001200041026a3602e0052001200241016a22003a0080052000210220004120470d000b200141c0046a41086a200141e0046a41086a2903002209370300200141e8016a41186a200141e0046a41186a290300370300200141e8016a41106a200141e0046a41106a290300370300200141e8016a41086a20093703002001200320006b3602e405200120012903e00422093703c004200120093703e801410121020b200141c0036a41186a2205200141e8016a41186a2200290300370300200141c0036a41106a220a200141e8016a41106a2203290300370300200141c0036a41086a220b200141e8016a41086a2204290300370300200141e0036a41086a220c20014180046a41086a290300370300200141e0036a41106a220d20014180046a41106a290300370300200141e0036a41186a220e20014180046a41186a290300370300200120012903e8013703c00320012001290380043703e003200141a0036a41186a220f200e290300370300200141a0036a41106a220e200d290300370300200141a0036a41086a220d200c290300370300200120012903e0033703a00320014180036a41186a220c200529030037030020014180036a41106a2205200a29030037030020014180036a41086a220a200b290300370300200120012903c00337038003200141e0046a41186a220b200f290300370300200141e0046a41106a220f200e290300370300200141e0046a41086a220e200d290300370300200120012903a0033703e0042000200c290300370300200320052903003703002004200a29030037030020012001290380033703e801200141c0056a41046a2205200141fa026a41046a2f01003b0100200120012801fa023602c00520084102460d01200141d8026a41186a200b290300370300200141d8026a41106a200f290300370300200141d8026a41086a200e290300370300200141b8026a41086a2004290300370300200141b8026a41106a2003290300370300200141b8026a41186a2000290300370300200141b0026a41046a20052f01003b0100200120012903e0043703d802200120012903e8013703b802200120012802c0053602b00202402007450d002006102a0b200141c8006a412010090c030b411241011037000b41c4d1c3004133200141a0046a419cd9c3001038000b410221080b20014188016a41186a2200200141d8026a41186a29030037030020014188016a41106a2203200141d8026a41106a29030037030020014188016a41086a2204200141d8026a41086a290300370300200141e8006a41086a2205200141b8026a41086a290300370300200141e8006a41106a2206200141b8026a41106a290300370300200141e8006a41186a2207200141b8026a41186a290300370300200120012903d80237038801200120012903b802370368200141c8016a41086a220a2004290300370300200141c8016a41106a22042003290300370300200141c8016a41186a2203200029030037030020012001290388013703c801200141a8016a41086a22002005290300370300200141a8016a41106a22052006290300370300200141a8016a41186a22062007290300370300200120012903683703a8010240024020084102460d002001418a026a220720012903a801370100200141f1016a200a290300370000200141f9016a200429030037000020014181026a200329030037000020014192026a20002903003701002001419a026a2005290300370100200141a2026a2006290300370100200120083a00e801200120012903c8013700e901200120023a0089024100210602400240024002400240024002400240200241ff01714101470d00200141e0046a200710ac01200141e0056a41186a200141e0046a41186a22022900002209370300200141e0056a41106a200141e0046a41106a22002900002210370300200141e0056a41086a200141e0046a41086a22032900002211370300200120012900e00422123703e005200220093703002000201037030020032011370300200120123703e004412010282206450d01200620012903e004370000200641186a2002290300370000200641106a2000290300370000200641086a200329030037000020012d00e80121080b0240200841ff01714101460d0020012d0089024101460d03200141c0056a41186a22024200370300200141c0056a41106a22004200370300200141c0056a41086a22034200370300200142003703c00541d3aec400411a200141c0056a1000200141e0046a41186a2002290300370300200141e0046a41106a2000290300370300200141e0046a41086a2003290300370300200120012903c0053703e004200141e0046a412010090c060b200141e0046a200141e8016a41017210ac01200141e0056a41186a200141e0046a41186a22022903002209370300200141e0056a41106a200141e0046a41106a22002903002210370300200141e0056a41086a200141e0046a41086a22032903002211370300200120012903e00422123703e005200220093703002000201037030020032011370300200120123703e004412010282208450d01200820012903e004370000200841186a2002290300370000200841106a2000290300370000200841086a2003290300370000200141003602e00420084120200141e0046a1006210720012802e004220b417f460d032007450d032001200b360284042001200736028004200141186a20014180046a109f012001290318a70d042001280284042202450d04200141286a29030021092001290320211020012002417f6a2203360284042001200128028004220541016a22043602800420052d0000220241014b0d044100210a0240024020020e020100010b41002102200141003a0080050340024020032002470d002001410036028404200241ff0171450d07200141003a0080050c070b200141e0046a20026a200520026a220041016a2d00003a00002001200041026a360280042001200241016a22003a0080052000210220004120470d000b200141e0056a41086a200141e0046a41086a290300370300200141e0056a41106a200141e0046a41106a290300370300200141e0056a41186a200141e0046a41186a290300370300200120012903e0043703e0052001200320006b2203360284044101210a200520006a41016a21040b200141c0056a41186a200141e0056a41186a290300370300200141c0056a41106a200141e0056a41106a290300370300200141c0056a41086a200141e0056a41086a290300370300200120012903e0053703c0052003450d0420012003417f6a2203360284042001200441016a3602800420042d0000220241014b0d040240024020020e020100010b41002102200141003a0080050340024020032002470d002001410036028404200241ff0171450d07200141003a0080050c070b200141e0046a20026a200420026a220041016a2d00003a00002001200041026a360280042001200241016a22003a0080052000210220004120470d000b200141a0046a41086a200141e0046a41086a2903002211370300200141e0056a41186a200141e0046a41186a290300370300200141e0056a41106a200141e0046a41106a290300370300200141e0056a41086a20113703002001200320006b36028404200120012903e00422113703a004200120113703e0050b200141c0036a41186a2202200141e0056a41186a2200290300370300200141c0036a41106a2203200141e0056a41106a2204290300370300200141c0036a41086a2205200141e0056a41086a220c290300370300200141e0036a41086a220d200141c0056a41086a290300370300200141e0036a41106a220e200141c0056a41106a290300370300200141e0036a41186a220f200141c0056a41186a290300370300200120012903e0053703c003200120012903c0053703e003200141a0036a41186a2213200f290300370300200141a0036a41106a220f200e290300370300200141a0036a41086a220e200d290300370300200120012903e0033703a00320014180036a41186a200229030037030020014180036a41106a200329030037030020014180036a41086a2005290300370300200120012903c00337038003200141e0046a41186a22032013290300370300200141e0046a41106a2205200f290300370300200141e0046a41086a220d200e290300370300200120012903a0033703e004200141c0056a41046a220e200141fa026a41046a2f01003b0100200120012801fa023602c005200a4102460d0420014189026a21022000200329030037030020042005290300370300200c200d290300370300200141c0046a41046a200e2f01003b0100200120012903e0043703e005200120012802c0053602c0040240200b450d002007102a0b200141f1046a20012903e005370000200141f9046a200141e0056a41086a29030037000020014181056a200141e0056a41106a29030037000020014189056a200141e0056a41186a290300370000200141b6056a200141c4046a2f01003b0100200120103703e0042001200a3a00f004200120012802c0043601b205200120093703e80420014191056a200229000037000020014199056a200241086a290000370000200141a1056a200241106a290000370000200141a9056a200241186a290000370000200141b1056a200241206a2d00003a0000200141003602e805200142013703e0052001200141e0046a3602c005200141c0056a200141e0056a10a301200141e0046a41106a200141e0056a10a90120012802e40521022008412020012802e005220020012802e805100702402002450d002000102a0b2008102a4101210a0c060b412041011037000b412041011037000b200141c0056a41186a22024200370300200141c0056a41106a22004200370300200141c0056a41086a22034200370300200142003703c00541d3aec400411a200141c0056a1000200141e0046a41186a2002290300370300200141e0046a41106a2000290300370300200141e0046a41086a2003290300370300200120012903c0053703e004200141203602e4052001200141e0046a3602e0052007200141e0056a10ff010c020b41e2bbc00041d8001050000b41c4d1c3004133200141a0046a419cd9c3001038000b410021084100210a0b0240024002400240024020060d00410021020c010b200141003602e00420064120200141e0046a1006210720012802e004220b417f460d012007450d012001200b3602bc05200120073602b8052001200141b8056a109f012001290300a70d0520012802bc052202450d05200141106a29030021092001290308211020012002417f6a22033602bc05200120012802b805220541016a22043602b80520052d0000220241014b0d054100210c0240024020020e020100010b41002102200141003a0080050340024020032002470d00200141003602bc05200241ff0171450d08200141003a0080050c080b200141e0046a20026a200520026a220041016a2d00003a00002001200041026a3602b8052001200241016a22003a0080052000210220004120470d000b20014180046a41106a200141e0046a41106a2903002211370300200141e0056a41086a200141e0046a41086a290300370300200141e0056a41106a2011370300200141e0056a41186a200141e0046a41186a2903003703002001200320006b22033602bc05200120012903e0043703e0054101210c200520006a41016a21040b200141c0056a41186a200141e0056a41186a290300370300200141c0056a41106a200141e0056a41106a290300370300200141c0056a41086a200141e0056a41086a290300370300200120012903e0053703c0052003450d0520012003417f6a22033602bc052001200441016a3602b80520042d0000220241014b0d05410021050240024020020e020100010b41002102200141003a0080050340024020032002470d00200141003602bc05200241ff0171450d08200141003a0080050c080b200141e0046a20026a200420026a220041016a2d00003a00002001200041026a3602b8052001200241016a22003a0080052000210220004120470d000b200141c0046a41086a200141e0046a41086a2903002211370300200141e0056a41186a200141e0046a41186a290300370300200141e0056a41106a200141e0046a41106a290300370300200141e0056a41086a20113703002001200320006b3602bc05200120012903e00422113703c004200120113703e005410121050b200141c0036a41186a2204200141e0056a41186a2202290300370300200141c0036a41106a220d200141e0056a41106a2200290300370300200141c0036a41086a220e200141e0056a41086a2203290300370300200141e0036a41086a220f200141c0056a41086a290300370300200141e0036a41106a2213200141c0056a41106a290300370300200141e0036a41186a2214200141c0056a41186a290300370300200120012903e0053703c003200120012903c0053703e003200141a0036a41186a22152014290300370300200141a0036a41106a22142013290300370300200141a0036a41086a2213200f290300370300200120012903e0033703a00320014180036a41186a220f200429030037030020014180036a41106a2204200d29030037030020014180036a41086a220d200e290300370300200120012903c00337038003200141e0046a41186a220e2015290300370300200141e0046a41106a22152014290300370300200141e0046a41086a22142013290300370300200120012903a0033703e0042002200f290300370300200020042903003703002003200d29030037030020012001290380033703e005200141c0056a41046a2204200141fa026a41046a2f01003b0100200120012801fa023602c005200c4102460d05200141d8026a41186a200e290300370300200141d8026a41106a2015290300370300200141d8026a41086a2014290300370300200141b8026a41086a2003290300370300200141b8026a41106a2000290300370300200141b8026a41186a2002290300370300200141b0026a41046a20042f01003b0100200120012903e0043703d802200120012903e0053703b802200120012802c0053602b0020240200b450d002007102a0b20014191056a20053a000020014192056a20012903b8023701002001419a056a200141b8026a41086a290300370100200141a2056a200141b8026a41106a290300370100200141aa056a200141b8026a41186a290300370100200141b6056a200141b4026a2f01003b0100200120103703e004200120012802b0023601b205200120093703e80420014190056a200141e8016a41206a2d00003a000020014188056a200141e8016a41186a290300370300200141e0046a41206a200141e8016a41106a290300370300200141e0046a41186a200141e8016a41086a290300370300200120012903e8013703f004200141003602e805200142013703e0052001200141e0046a3602c005200141c0056a200141e0056a10a301200141e0046a41106a200141e0056a10a90120012802e40521022006412020012802e005220020012802e805100702402002450d002000102a0b2006102a410121020b200a20084572450d010c020b41e2bbc00041d8001050000b2008102a0b2006452002720d002006102a0b20014180066a24000f0b41c4d1c3004133200141a0046a419cd9c3001038000bde3305097f017e077f037e057f230041a0056b22012400024002400240024002400240411210282202450d0020024100290095ae44370000200241106a41002f00a5ae443b0000200241086a410029009dae4437000020014292808080a00237028c042001200236028804200020014188046a108f0120012802900421022001280288042100200141c8036a41186a22034200370300200141c8036a41106a22044200370300200141c8036a41086a22054200370300200142003703c80320002002200141c8036a1000200141186a2003290300370300200141106a2004290300370300200141086a2005290300370300200120012903c8033703000240200128028c04450d00200128028804102a0b20014100360288042001412020014188046a100621032001280288042204417f460d042003450d04200120043602e404200120033602e00420014180056a200141e0046a106d2001280280052206450d02200128028405210720012802e4042202450d0120012002417f6a22053602e404200120012802e004220841016a22093602e00420082d0000220041014b0d01410021020240024020000e020100010b41002102200141003a00a8040340024020052002470d00200141003602e404200241ff0171450d04200141003a00a8040c040b20014188046a20026a200820026a220041016a2d00003a00002001200041026a3602e0042001200241016a22003a00a8042000210220004120470d000b200141c8036a41086a20014188046a41086a290300220a370300200141a0016a41186a20014188046a41186a290300370300200141a0016a41106a20014188046a41106a290300370300200141a0016a41086a200a3703002001200520006b22053602e4042001200129038804220a3703c8032001200a3703a00141012102200820006a41016a21090b200141a8036a41186a200141a0016a41186a290300370300200141a8036a41106a200141a0016a41106a290300370300200141a8036a41086a200141a0016a41086a290300370300200120012903a0013703a8032005450d0120012005417f6a22083602e4042001200941016a3602e00420092d0000220541014b0d01410021000240024020050e020100010b41002100200141003a00a8040340024020082000470d00200141003602e404200041ff0171450d04200141003a00a8040c040b20014188046a20006a200920006a220541016a2d00003a00002001200541026a3602e0042001200041016a22053a00a8042005210020054120470d000b200141e8036a41086a20014188046a41086a290300220a370300200141a0016a41186a20014188046a41186a290300370300200141a0016a41106a20014188046a41106a290300370300200141a0016a41086a200a3703002001200820056b3602e4042001200129038804220a3703e8032001200a3703a001410121000b200141e8026a41186a2205200141a0016a41186a2208290300370300200141e8026a41106a2209200141a0016a41106a220b290300370300200141e8026a41086a220c200141a0016a41086a220d29030037030020014188036a41086a220e200141a8036a41086a29030037030020014188036a41106a220f200141a8036a41106a29030037030020014188036a41186a2210200141a8036a41186a290300370300200120012903a0013703e802200120012903a80337038803200141c8026a41186a22112010290300370300200141c8026a41106a2210200f290300370300200141c8026a41086a220f200e29030037030020012001290388033703c802200141a8026a41186a220e2005290300370300200141a8026a41106a22052009290300370300200141a8026a41086a2209200c290300370300200120012903e8023703a80220014188046a41186a201129030037030020014188046a41106a201029030037030020014188046a41086a200f290300370300200120012903c802370388042008200e290300370300200b2005290300370300200d2009290300370300200120012903a8023703a0010c030b411241011037000b2007450d002006102a0b410221020b024020024102460d0020014188026a41186a20014188046a41186a29030037030020014188026a41106a20014188046a41106a29030037030020014188026a41086a20014188046a41086a290300370300200141e8016a41086a200141a0016a41086a290300370300200141e8016a41106a200141a0016a41106a290300370300200141e8016a41186a200141a0016a41186a290300370300200120012903880437038802200120012903a0013703e801200120012f0180053b01e60102402004450d002003102a0b2001412010090c020b41c4d1c3004133200141a8036a419cd9c3001038000b410221020b200141c0006a41186a220320014188026a41186a290300370300200141c0006a41106a220420014188026a41106a290300370300200141c0006a41086a220520014188026a41086a290300370300200141206a41086a2208200141e8016a41086a290300370300200141206a41106a2209200141e8016a41106a290300370300200141206a41186a220b200141e8016a41186a2903003703002001200129038802370340200120012903e80137032020014180016a41086a220c200529030037030020014180016a41106a2205200429030037030020014180016a41186a220420032903003703002001200129034037038001200141e0006a41086a22032008290300370300200141e0006a41106a22082009290300370300200141e0006a41186a2209200b29030037030020012001290320370360024020024102460d00200141c2016a220b2001290360370100200141a9016a200c290300370000200141b1016a2005290300370000200141b9016a2004290300370000200141ca016a2003290300370100200141d2016a2008290300370100200141da016a2009290300370100200120023a00a00120012001290380013700a101200120003a00c101410021030240024002400240024002400240024002400240200041ff01714101470d0020014188046a200b10ae0120014180056a41186a20014188046a41186a2202290000220a37030020014180056a41106a20014188046a41106a2200290000221237030020014180056a41086a20014188046a41086a2204290000221337030020012001290088042214370380052002200a37030020002012370300200420133703002001201437038804412010282203450d012003200129038804370000200341186a2002290300370000200341106a2000290300370000200341086a200429030037000020012d00a00121020b0240200241ff01714101460d0020012d00c1014101460d03200141e0046a41186a22024200370300200141e0046a41106a22004200370300200141e0046a41086a22044200370300200142003703e00441a7aec400411a200141e0046a100020014188046a41186a200229030037030020014188046a41106a200029030037030020014188046a41086a2004290300370300200120012903e0043703880420014188046a412010090c080b20014188046a200141a0016a41017210ae0120014180056a41186a20014188046a41186a2202290300220a37030020014180056a41106a20014188046a41106a2200290300221237030020014180056a41086a20014188046a41086a2205290300221337030020012001290388042214370380052002200a37030020002012370300200520133703002001201437038804412010282204450d012004200129038804370000200441186a2002290300370000200441106a2000290300370000200441086a200529030037000020014100360288042004412020014188046a10062109200128028804220d417f460d032009450d032001200d3602cc03200120093602c803200141e8036a200141c8036a106d20012802e8032202450d0520012802ec03210c20012802cc032200450d04200141f0036a280200210820012000417f6a220e3602cc03200120012802c803220f41016a22103602c803200f2d0000220041014b0d044100210b0240024020000e020100010b41002100200141003a00a80403400240200e2000470d00200141003602cc03200041ff0171450d07200141003a00a8040c070b20014188046a20006a200f20006a220541016a2d00003a00002001200541026a3602c8032001200041016a22053a00a8042005210020054120470d000b20014180056a41086a20014188046a41086a29030037030020014180056a41106a20014188046a41106a29030037030020014180056a41186a20014188046a41186a2903003703002001200129038804370380052001200e20056b220e3602cc034101210b200f20056a41016a21100b200141e0046a41186a20014180056a41186a290300370300200141e0046a41106a20014180056a41106a290300370300200141e0046a41086a20014180056a41086a29030037030020012001290380053703e004200e450d042001200e417f6a220e3602cc032001201041016a3602c80320102d0000220041014b0d040240024020000e020100010b41002100200141003a00a80403400240200e2000470d00200141003602cc03200041ff0171450d07200141003a00a8040c070b20014188046a20006a201020006a220541016a2d00003a00002001200541026a3602c8032001200041016a22053a00a8042005210020054120470d000b200141a8036a41106a20014188046a41106a290300220a37030020014180056a41086a20014188046a41086a29030037030020014180056a41106a200a37030020014180056a41186a20014188046a41186a2903003703002001200e20056b3602cc032001200129038804370380050b200141e8026a41186a220020014180056a41186a290300370300200141e8026a41106a220520014180056a41106a290300370300200141e8026a41086a220e20014180056a41086a29030037030020014188036a41086a220f200141e0046a41086a29030037030020014188036a41106a2210200141e0046a41106a29030037030020014188036a41186a2211200141e0046a41186a29030037030020012001290380053703e802200120012903e00437038803200141c8026a41186a22152011290300370300200141c8026a41106a22112010290300370300200141c8026a41086a2210200f29030037030020012001290388033703c802200141a8026a41186a2000290300370300200141a8026a41106a2005290300370300200141a8026a41086a200e290300370300200120012903e8023703a80220014188046a41186a201529030037030020014188046a41106a201129030037030020014188046a41086a2010290300370300200120012903c802370388040c060b412041011037000b412041011037000b200141e0046a41186a22024200370300200141e0046a41106a22004200370300200141e0046a41086a22044200370300200142003703e00441a7aec400411a200141e0046a100020014188046a41186a200229030037030020014188046a41106a200029030037030020014188046a41086a2004290300370300200120012903e004370388042001412036028405200120014188046a36028005200b20014180056a10ff010c040b41e2bbc00041d8001050000b200c450d002002102a0b4102210b0b0240200b4102460d00200141c1016a210020014180056a41186a220520014188046a41186a29030037030020014180056a41106a220e20014188046a41106a29030037030020014180056a41086a220f20014188046a41086a290300370300200120012903880437038005200120012f01e0043b01e8030240200d450d002009102a0b20014195046a2001290380053700002001419d046a200f290300370000200141a5046a200e290300370000200141ad046a20052903003700002001200b3a00940420012008360290042001200c36028c042001200236028804200120012f01e8033b01d604200141b5046a2000290000370000200141bd046a200041086a290000370000200141c5046a200041106a290000370000200141cd046a200041186a290000370000200141d5046a200041206a2d00003a000020014100360288052001420137038005200820014180056a10b40120014194046a210502402008450d00200841057421000340200220014180056a108f01200241206a2102200041606a22000d000b0b200520014180056a10a9012001280284052102200441202001280280052200200128028805100702402002450d002000102a0b0240200128028c04450d00200128028804102a0b2004102a410121090c020b41c4d1c3004133200141a8036a419cd9c3001038000b41002104410021090b0240024002400240024020030d00410021020c010b20014100360288042003412020014188046a100621080240024002400240200128028804220b417f460d002008450d002001200b3602dc04200120083602d804200141a8036a200141d8046a106d4200211220012802a8032202450d0220012802ac03211020012802dc042200450d01200141b0036a350200210a20012000417f6a220c3602dc04200120012802d804220d41016a220f3602d804200d2d0000220041014b0d014100210e0240024020000e020100010b41002100200141003a00a80403400240200c2000470d00200141003602dc04200041ff0171450d04200141003a00a8040c040b20014188046a20006a200d20006a220541016a2d00003a00002001200541026a3602d8042001200041016a22053a00a8042005210020054120470d000b200141c8036a41086a20014188046a41086a290300221337030020014180056a41186a20014188046a41186a29030037030020014180056a41106a20014188046a41106a29030037030020014180056a41086a20133703002001200c20056b220c3602dc04200120012903880422133703c80320012013370380054101210e200d20056a41016a210f0b200141e0046a41186a20014180056a41186a290300370300200141e0046a41106a20014180056a41106a290300370300200141e0046a41086a20014180056a41086a29030037030020012001290380053703e004200c450d012001200c417f6a220c3602dc042001200f41016a3602d804200f2d0000220541014b0d01410021000240024020050e020100010b41002100200141003a00a80403400240200c2000470d00200141003602dc04200041ff0171450d04200141003a00a8040c040b20014188046a20006a200f20006a220541016a2d00003a00002001200541026a3602d8042001200041016a22053a00a8042005210020054120470d000b200141e8036a41086a20014188046a41086a290300221237030020014180056a41186a20014188046a41186a29030037030020014180056a41106a20014188046a41106a29030037030020014180056a41086a20123703002001200c20056b3602dc04200120012903880422123703e8032001201237038005410121000b200141e8026a41186a220520014180056a41186a220c290300370300200141e8026a41106a220d20014180056a41106a220f290300370300200141e8026a41086a221120014180056a41086a221529030037030020014188036a41086a2216200141e0046a41086a29030037030020014188036a41106a2217200141e0046a41106a29030037030020014188036a41186a2218200141e0046a41186a29030037030020012001290380053703e802200120012903e00437038803200141c8026a41186a22192018290300370300200141c8026a41106a22182017290300370300200141c8026a41086a2217201629030037030020012001290388033703c802200141a8026a41186a22162005290300370300200141a8026a41106a2205200d290300370300200141a8026a41086a220d2011290300370300200120012903e8023703a80220014188046a41186a201929030037030020014188046a41106a201829030037030020014188046a41086a2017290300370300200120012903c80237038804200c2016290300370300200f20052903003703002015200d290300370300200120012903a80237038005200a422086210a2010ad21120c030b41e2bbc00041d8001050000b2010450d002002102a0b4102210e4200210a0b200e4102460d0120014188026a41186a20014188046a41186a29030037030020014188026a41106a20014188046a41106a29030037030020014188026a41086a20014188046a41086a290300370300200141e8016a41086a220520014180056a41086a290300370300200141e8016a41106a220c20014180056a41106a290300370300200141e8016a41186a220d20014180056a41186a29030037030020012001290388043703880220012001290380053703e801200120012f01e0043b01e601200a20128421120240200b450d002008102a0b200141b5046a20003a0000200141b6046a20012903e801370100200141be046a2005290300370100200141c6046a200c290300370100200141ce046a200d2903003701002001419c046a200141a0016a41086a290300370200200141a4046a200141a0016a41106a290300370200200141ac046a200141a0016a41186a290300370200200141b4046a200141a0016a41206a2d00003a00002001201237028c042001200236028804200120012f01e6013b01d604200120012903a0013702940420014100360288052001420137038005200a422088a7220020014180056a10b40120014194046a210502402000450d00200041057421000340200220014180056a108f01200241206a2102200041606a22000d000b0b200520014180056a10a9012001280284052102200341202001280280052200200128028805100702402002450d002000102a0b0240200128028c04450d00200128028804102a0b2003102a410121020b200920044572450d010c020b41c4d1c3004133200141a8036a419cd9c3001038000b2004102a0b02402003452002720d002003102a0b2006450d002007450d002006102a0b200141a0056a24000b13002000410d360204200041bcafc4003602000b3400200041d9dbc40036020420004100360200200041146a4113360200200041106a41e0dbc400360200200041086a42073702000b09002000410010e6020b6c01027f230041106b22022400200241003602082002420137030002404104102822030d00410441011037000b2003410036000020024284808080c000370204200220033602004100200210b401200041086a200228020836020020002002290300370200200241106a24000b3001017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242003700000b8e0201037f230041c0006b22022400200241186a4200370300200241106a22034200370300200241086a4200370300200241286a22044100360200200242003703002002420837032020024100360238200242013703302002200236023c2002413c6a200241306a10a3012002200336023c2002413c6a200241306a10a3012002280220210320042802002204200241306a10b40102402004450d00200441306c21040340200341106a200241306a108f012002200336023c200341306a21032002413c6a200241306a10a301200441506a22040d000b0b20002002290330370200200041086a200241306a41086a28020036020002402002280224450d002002280220102a0b200241c0006a24000b7001027f230041306b2202240020024200370310200242003703082002200241086a36021c02404101102822030d00410141011037000b20024201370224200220033602202002411c6a200241206a10a301200041086a200228022836020020002002290320370200200241306a24000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241043600000b9c0402057f027e230041d0016b220224002002200110b1040240024020022d00004101470d00200241286a41186a200241196a290000370300200241286a41106a200241116a290000370300200241286a41086a200241096a2900003703002002200229000137032802400240410e10282201450d002001410029008aaf44370000200141066a4100290090af443700002002428e808080e00137026c20022001360268200241286a200241e8006a108f012002280270210120022802682103200241f8006a41186a22044200370300200241f8006a41106a22054200370300200241f8006a41086a220642003703002002420037037820032001200241f8006a1000200241c8006a41186a2004290300370300200241c8006a41106a2005290300370300200241c8006a41086a2006290300370300200220022903783703480240200228026c450d002002280268102a0b20024100360278200241c8006a4120200241f8006a100621040240024020022802782203417f470d00410021010c010b2002200336026c20022004360268200241f8006a200241e8006a108a022002280298012201450d0220024190016a29030021072002290388012108200228029c0121052003450d002004102a0b2001450d022005450d032001102a0c030b410e41011037000b41c4d1c3004133200241c8016a419cd9c3001038000b42002108420021070b2000200837030020002007370308200241d0016a24000bb70301057f230041f0006b220224000240410e10282203450d00200341002900fcae44370000200341066a4100290082af443700002002428e808080e001370254200220033602502001200241d0006a108f012002280258210320022802502101200241086a41186a22044200370300200241086a41106a22054200370300200241086a41086a220642003703002002420037030820012003200241086a1000200241306a41186a2004290300370300200241306a41106a2005290300370300200241306a41086a20062903003703002002200229030837033002402002280254450d002002280250102a0b200241086a200241306a412010fd01200241d0006a41086a200241086a41096a290000370300200241d0006a41106a200241086a41116a290000370300200241d0006a41186a200241086a41196a290000370300200220022900093703500240024020022d00084101460d00200041003a00000c010b200041013a000020002002290350370001200041096a200241d8006a290300370000200041116a200241e0006a290300370000200041196a200241e8006a2903003700000b200241f0006a24000f0b410e41011037000b13002000410236020420004184fcc4003602000b3101017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241a0053600000bdf14030d7f077e0b7f23004180046b22042400024002400240024002400240410d10282205450d0020054100290098af44370000200541056a410029009daf443700002004428d808080d0013702ec02200420053602e8022001200441e8026a108f0120042802f002210520042802e8022106200441a8036a41186a22074200370300200441a8036a41106a22084200370300200441a8036a41086a22094200370300200442003703a80320062005200441a8036a100020044198016a41186a200729030037030020044198016a41106a200829030037030020044198016a41086a2009290300370300200420042903a80337039801024020042802ec02450d0020042802e802102a0b200441003602a80320044198016a4120200441a8036a1006210502400240024020042802a8032206417f460d002005450d002006450d0420052d0000220641034f0d042005102a20060e03000201000b200441f0006a200110b10420042d00704101470d06200441b8016a41186a20044189016a290000370300200441b8016a41106a20044181016a290000370300200441b8016a41086a200441f9006a290000370300200420042900713703b801410e10282205450d042005410029008aaf44370000200541066a4100290090af443700002004428e808080e0013702ec02200420053602e802200441b8016a200441e8026a108f0120042802f002210520042802e8022106200441a8036a41186a22074200370300200441a8036a41106a22084200370300200441a8036a41086a22094200370300200442003703a80320062005200441a8036a100020044198016a41186a200729030037030020044198016a41106a200829030037030020044198016a41086a2009290300370300200420042903a80337039801024020042802ec02450d0020042802e802102a0b200441003602a80320044198016a4120200441a8036a100621070240024020042802a8032206417f470d00410021050c010b200420063602cc02200420073602c802200441a8036a200441c8026a108a0220042802c8032205450d06200441a8026a41186a200441a8036a41186a290300370300200441a8026a41106a200441a8036a41106a290300370300200441a8026a41086a200441a8036a41086a290300370300200441e8026a41086a200441d4036a290200370300200441e8026a41106a200441dc036a290200370300200441e8026a41186a200441e4036a29020037030020044188036a200441ec036a29020037030020044190036a200441f4036a280200360200200420042903a8033703a802200420042902cc033703e8022006450d002007102a0b200441c8026a41086a2209200441a8026a41086a290300370300200441c8026a41106a220a200441a8026a41106a290300370300200441c8026a41186a220b200441a8026a41186a290300370300200441a8036a41086a220c200441e8026a41086a2206290300370300200441a8036a41106a220d200441e8026a41106a2207290300370300200441a8036a41186a220e200441e8026a41186a2208290300370300200441a8036a41206a220f200441e8026a41206a290300370300200441a8036a41286a2210200441e8026a41286a280200360200200420042903a8023703c802200420042903e8023703a80302402005450d0020044188026a41186a200b29030037030020044188026a41106a200a29030037030020044188026a41086a2009290300370300200441d8016a41086a200c290300370300200441d8016a41106a200d290300370300200441d8016a41186a200e290300370300200441d8016a41206a200f290300370300200441d8016a41286a2010280200360200200420042903c80237038802200420042903a8033703d8010b2008200441b8016a41186a2903003703002007200441b8016a41106a2903003703002006200441b8016a41086a290300370300200420042903b8013703e8022005450d06200441306a41206a220c2004290388022211370300200441a8036a41186a2206200441e8026a41186a220d2903002212370300200441a8036a41106a2207200441e8026a41106a220e2903002213370300200441a8036a41086a2208200441e8026a41086a220f2903002214370300200441a8036a41286a20044188026a41086a2903002215370300200441a8036a41306a20044188026a41106a2903002216370300200441a8036a41386a20044188026a41186a2903002217370300200441306a41386a22102017370300200441306a41306a22182016370300200441306a41286a22192015370300200441306a41186a22092012370300200441306a41106a220a2013370300200441306a41086a220b2014370300200420042903e80222123703a803200420113703c80320042012370330200441286a221a200441d8016a41286a280200360200200441206a221b200441d8016a41206a290300370300200441186a221c200441d8016a41186a221d290300370300200441106a221e200441d8016a41106a221f290300370300200441086a2220200441d8016a41086a2221290300370300200420042903d801370300200441e8026a41386a22222010290300370300200441e8026a41306a22102018290300370300200441e8026a41286a22182019290300370300200441e8026a41206a2219200c290300370300200d2009290300370300200e200a290300370300200f200b290300370300200420042903303703e802201d2009290300370300201f200a2903003703002021200b290300370300200420042903303703d801200620222903003703002007201029030037030020082018290300370300200420053602c803200420192903003703a803200441cc036a22052004290300370200200441d4036a2020290300370200200441dc036a201e290300370200200441e4036a201c290300370200200441ec036a201b290300370200200441f4036a201a2802003602002006290300211120072007290300221220027c22133703002006201120037c2013201254ad7c37030020082903002111200420042903a803221220027c22133703a8032008201120037c2013201254ad7c370300200441f0006a20012002200310a50220043502702102200441f0006a41106a2903002111200441f0006a41086a2903002103200441d8016a200441a8036a10b50402402005280200450d0020042802c803102a0b200242018521020c070b200441a8036a200110b10420042d00a8034101470d0520044180036a200441c1036a290000370300200441e8026a41106a200441b9036a290000370300200441e8026a41086a200441b1036a290000370300200420042900a9033703e802200441306a200441e8026a2002200310a50220043502304201852102200441306a41106a2903002111200441306a41086a29030021030c060b200441a8036a20012002200310a50220043502a8034201852102200441b8036a2903002111200441b0036a29030021030c050b410d41011037000b41c4d1c3004133200441f8036a419cd9c3001038000b410e41011037000b41c4d1c3004133200441f8036a419cd9c3001038000b420021020b2000200337030820002002370300200041106a201137030020044180046a24000bc80201057f230041e0006b22022400200242f3e885db96cddbb320370308200241086a2001412c6a2001290300200141086a290300417f410f10a9020240410e10282203450d002003410029008aaf44370000200341066a4100290090af443700002002428e808080e001370234200220033602302000200241306a108f012002280238210320022802302100200241c0006a41186a22044200370300200241c0006a41106a22054200370300200241c0006a41086a220642003703002002420037034020002003200241c0006a1000200241106a41186a2004290300370300200241106a41106a2005290300370300200241106a41086a20062903003703002002200229034037031002402002280234450d002002280230102a0b200241203602442002200241106a3602402001200241c0006a10b604200241e0006a24000f0b410e41011037000bce0101027f230041106b2202240020024100360208200242013703002000412c6a2002108f012002200036020c2002410c6a200210a3012002200041106a36020c2002410c6a200210a30120002802202103200041286a2802002200200210b40102402000450d002003200041186c6a210003402002200336020c2002410c6a200210a301200341106a200210a0012000200341186a2203470d000b0b2002280204210320012802002001280204200228020022002002280208100702402003450d002000102a0b200241106a24000bf30901047f230041e0026b22052400200541a0016a41086a22064200370300200542003703a00141a990c6004119200541a0016a1008200541086a41086a2006290300370300200520052903a00137030841002106200541003602a001200541086a4110200541a0016a10062107024002400240024020052802a0012208417f460d002007450d0020084104490d01200728000021062007102a0b02402006417f6a220720064d0d00200541133602080c020b200541086a200710ca0320052802084113460d01200541a0016a200541086a419801109a051a20052802a8022107200541a0016a106a200720014d0d01200041828ac50036020420004101360200200041086a41c7003602002002106a0c020b41c4d1c3004133200541a0016a419cd9c3001038000b200541a0016a41086a22074200370300200542003703a00141a990c6004119200541a0016a1008200541086a41086a2007290300370300200520052903a0013703082005200641016a3602a001200541086a4110200541a0016a41041007200541a0016a2002418801109a051a200520033a00b002200520043602ac02200520013602a802024002400240024002400240411a10282207450d00200741186a41002f00ce88453b0000200741106a41002900c68845370000200741086a41002900be8845370000200741002900b688453700002007411a4134102c2207450d012007200636001a200541086a41186a22014200370300200541086a41106a22024200370300200541086a41086a22044200370300200542003703082007411e200541086a1000200541b8026a41186a2001290300370300200541b8026a41106a2002290300370300200541b8026a41086a2004290300370300200520052903083703b8022007102a200541003602102005420137030820052802a8022101410410282207450d022005410436020c20052005280210220241046a36021020052007360208200720026a2001360000200541a0016a200541086a10eb01024020052d00b002220741024b0d00024002400240024020070e03000102000b410021010c020b410121010c010b410221010b200520013a00df0202400240200528020c20052802102207460d00200528020821020c010b200741016a22022007490d07200741017422042002200420024b1b22044100480d070240024020070d002004102821020c010b200528020820072004102c21020b2002450d052005200436020c20052002360208200528021021070b2005200741016a360210200220076a20013a00000b20052802ac02210202400240200528020c2201200528021022076b4104490d00200528020821010c010b200741046a22042007490d06200141017422072004200720044b1b22074100480d060240024020010d002007102821010c010b200528020820012007102c21010b2001450d052005200736020c20052001360208200528021021070b2005200741046a360210200120076a2002360000200528020c2107200541b8026a4120200528020822012005280210100702402007450d002001102a0b200541a0016a106a200541ac016a2006360200200541a9016a20033a0000200541a8016a41033a0000200541053a00a00141014100200541a0016a10cc0120004100360200200020063602040c060b411a41011037000b413441011037000b410441011037000b200441011037000b200741011037000b1031000b200541e0026a24000bfe0201047f230041e0006b2202240002400240411310282203450d002003410f6a41002800e38945360000200341086a41002900dc8945370000200341002900d48945370000200341134126102c2203450d0120032001360013200241c0006a41186a22044200370300200241c0006a41106a22054200370300200241c0006a41086a220142003703002002420037034020034117200241c0006a1000200241186a2004290300370300200241106a2005290300370300200241086a2001290300370300200220022903403703002003102a200241c0006a200210e003200241306a41086a2001290300370300200241206a41086a200241c0006a411c6a2802003602002002200229034037033020022002290254370320024020022802502203450d002000200229033037030020002002290320370214200041086a200241306a41086a2903003703002000411c6a200241206a41086a2802003602000b20002003360210200241e0006a24000f0b411341011037000b412641011037000b130020004111360204200041cc8bc5003602000b3400200041f9aac50036020420004100360200200041146a410f360200200041106a4184abc500360200200041086a42093702000b4f01027f230041106b2202240002404101102822030d00410141011037000b200341003a0000200041086a4101360200200241013602042002200336020020002002290300370200200241106a24000b5b01027f23004190016b22022400200241133602000240410110282203450d00200341003a0000200042818080801037020420002003360200024020022802004113460d002002106a0b20024190016a24000f0b410141011037000bfd0201057f230041c0006b22022400200241206a4200370300200241186a4200370300200241086a41086a4200370300200241003a0028200242003703082002410036023820024201370330200241086a200241306a108f0102400240024020022d0028220341064b0d000240024002400240024002400240024020030e0700010203040506000b410021040c060b410121040c050b410221040c040b410321040c030b410421040c020b410521040c010b410621040b200220043a003f02400240200228023420022802382203460d00200228023021050c010b200341016a22052003490d03200341017422062005200620054b1b22064100480d030240024020030d002006102821050c010b200228023020032006102c21050b2005450d022002200636023420022005360230200228023821030b2002200341016a360238200520036a20043a00000b20002002290330370200200041086a200241306a41086a280200360200200241c0006a24000f0b200641011037000b1031000b4001017f230041106b2202240020024100360208200242013703004100200210b401200041086a200228020836020020002002290300370200200241106a24000b130020004106360204200041acc7c5003602000b3201017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241809c313600000b3201017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180a3053600000b3e01017f02404110102822020d00411041011037000b20024200370008200242808084fea6dee111370000200042908080808002370204200020023602000b3201017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180de343600000ba30301047f230041c0006b22022400024002400240411310282203450d002003410f6a41002800e38945360000200341086a41002900dc8945370000200341002900d48945370000200341134126102c2203450d0120032000360013200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034117200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002003102a411010282203450d02200320012903003700002003200141086a2903003700082002429080808080023702242002200336022020012802102104200141186a2802002203200241206a10b40102402003450d00200341057421002004210303402003200241206a108f01200341206a2103200041606a22000d000b0b2002280224210320024120200228022022002002280228100702402003450d002000102a0b0240200141146a280200450d002004102a0b200241c0006a24000f0b411341011037000b412641011037000b411041011037000bc01401077f230041d0016b2204240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240411a10282205450d00200541186a41002f00ce88453b0000200541106a41002900c68845370000200541086a41002900be8845370000200541002900b688453700002005411a4134102c2205450d012005200136001a200441e0006a41186a22064200370300200441e0006a41106a22074200370300200441e0006a41086a22084200370300200442003703602005411e200441e0006a1000200441306a41186a2006290300370300200441306a41106a2007290300370300200441306a41086a2008290300370300200420042903603703302005102a0240200441306a41204101410041001003417f470d0041b7d5c50021000c110b200441146a200041086a2900003702002004411c6a200041106a290000370200200441246a200041186a290000370200200420013602082004200029000037020c411010282205450d02200541002900a68845370000200541086a41002900ae88453700002004429080808080023702b401200420053602b001200541104120102c2205450d03200441203602b401200420042802b801220641046a3602b801200420053602b001200520066a2001360000200441086a410472200441b0016a108f0120042802b801210520042802b0012106200441e0006a41186a22074200370300200441e0006a41106a22084200370300200441e0006a41086a220942003703002004420037036020062005200441e0006a1000200441306a41186a2007290300370300200441306a41106a2008290300370300200441306a41086a200929030037030020042004290360370330024020042802b401450d0020042802b001102a0b200441306a41204101410041001003417f470d0f200441086a41186a200041186a290000370300200441086a41106a200041106a290000370300200441086a41086a200041086a29000037030020042000290000370308411310282205450d042005410f6a41002800a88945360000200541086a41002900a18945370000200541002900998945370000200541134126102c2205450d0520052001360013200441e0006a41186a22064200370300200441e0006a41106a22074200370300200441e0006a41086a220842003703002004420037036020054117200441e0006a1000200441306a41186a2006290300370300200441306a41106a2007290300370300200441306a41086a2008290300370300200420042903603703302005102a20044100360260200441306a4120200441e0006a100621050240024020042802602207417f460d002007210620050d010b20044100360268200442013703604100200441e0006a10b4012004280268210620042802642107200428026021050b200420063602582004200736025420042005360250024002402006450d00200441e0006a20052006410110d60220042802604101470d012004280254450d102004280250102a0c100b4101200441d0006a10b401200441086a200441d0006a108f010c0d0b200428026421080240200441ec006a2802002205200441e8006a2802002206460d002004280258200520066b6a220741206a2209417f4c0d070240024020090d004101210a0c010b20091028220a450d090b20042009360284012004200a360280012004200736028801200420044180016a3602602008200441e0006a200510d70120072005490d0920042802880122082007490d0a200428025822082006490d0b20042802800121092004280250210a2004200720056b2207360290012004200820066b22083602940120072008470d0c200920056a200a20066a2007109a051a200441086a20044180016a108f012004280288012106200428028401210720042802800121052004280254450d0e2004280250102a0c0e0b2004200441d0006a3602602008200441e0006a200610d701200441086a200441d0006a108f010c0c0b411a41011037000b413441011037000b411041011037000b412041011037000b411341011037000b412641011037000b1036000b200941011037000b200520071044000b20072008103c000b200620081044000b200441b0016a41146a4108360200200441bc016a412536020020044198016a41146a41033602002004420337029c01200441c8afc60036029801200441253602b401200420044190016a3602c801200420044194016a3602cc0120044204370370200442013702642004419cb0c6003602602004200441b0016a3602a8012004200441e0006a3602c0012004200441cc016a3602b8012004200441c8016a3602b00120044198016a41d8b0c600103e000b2004280258210620042802542107200428025021050b2005450d00200441306a41202005200610072007450d012005102a0c010b412010282206450d0220062004290308370000200641186a200441086a41186a290300370000200641106a200441086a41106a290300370000200641086a200441086a41086a290300370000411310282207450d03410021052007410f6a41002800a88945360000200741086a41002900a18945370000200741002900998945370000200741134126102c2207450d0420072001360013200441e0006a41186a22084200370300200441e0006a41106a22094200370300200441e0006a41086a220a42003703002004420037036020074117200441e0006a1000200441306a41186a2008290300370300200441306a41106a2009290300370300200441306a41086a200a290300370300200420042903603703302007102a20044100360268200442013703604101200441e0006a10b4010340200620056a200441e0006a108f014120200541206a2205470d000b20042802642105200441306a4120200428026022072004280268100702402005450d002007102a0b2006102a0b200441146a200041086a2900003702002004411c6a200041106a290000370200200441246a200041186a290000370200200420013602082004200029000037020c411010282205450d04200541002900a68845370000200541086a41002900ae88453700002004429080808080023702b401200420053602b001200541104120102c2205450d05200441203602b401200420042802b801220041046a3602b801200420053602b001200520006a2001360000200441086a410472200441b0016a108f0120042802b801210520042802b0012100200441e0006a41186a22064200370300200441e0006a41106a22014200370300200441e0006a41086a220742003703002004420037036020002005200441e0006a1000200441306a41186a2006290300370300200441306a41106a2001290300370300200441306a41086a200729030037030020042004290360370330024020042802b401450d0020042802b001102a0b410110282205450d0641002100200541807f410020021b2003723a0000200441306a41202005410110072005102a0b200441d0016a240020000f0b412041011037000b411341011037000b412641011037000b411041011037000b412041011037000b410141011037000bc76501037f230041206b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00000eac010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab0100010b2002200128021841dfd6c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000cab010b2002200128021841f0d6c500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000caa010b2002200128021841fbd6c50041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca9010b2002200128021841fed6c50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a4184d7c500105d21000ca8010b200220012802184194d7c50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a4184d7c500105d21000ca7010b200220012802184198d7c50041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a4184d7c500105d21000ca6010b20022001280218419ad7c50041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca5010b20022001280218419ed7c50041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca4010b2002200128021841a1d7c50041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000ca3010b2002200128021841a3d7c50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000ca2010b2002200128021841a7d7c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41b0d7c500105d21000ca1010b2002200128021841c0d7c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca0010b2002200128021841c6d7c50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c9f010b2002200128021841cad7c500410c2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041016a36020c20012002410c6a41d8d7c500105d21000c9e010b2002200128021841e8d7c50041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9d010b2002200128021841ecd7c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9c010b2002200128021841f2d7c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c9b010b2002200128021841fad7c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c9a010b200220012802184182d8c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c99010b20022001280218418ad8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c98010b200220012802184193d8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c97010b20022001280218419cd8c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c96010b2002200128021841a3d8c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c95010b2002200128021841aad8c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c94010b2002200128021841b1d8c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c93010b2002200128021841b8d8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c92010b2002200128021841c1d8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c91010b2002200128021841cad8c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c90010b2002200128021841d4d8c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8f010b2002200128021841ded8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8e010b2002200128021841e7d8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8d010b2002200128021841f0d8c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8c010b2002200128021841fad8c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8b010b200220012802184184d9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8a010b20022001280218418ed9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c89010b200220012802184198d9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c88010b2002200128021841a0d9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c87010b2002200128021841a8d9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c86010b2002200128021841b0d9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c85010b2002200128021841b8d9c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c84010b2002200128021841c1d9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c83010b2002200128021841cbd9c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c82010b2002200128021841d4d9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c81010b2002200128021841ded9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c80010b2002200128021841e8d9c500410d2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41d8d7c500105d21000c7f0b2002200128021841f5d9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41d8d7c500105d21000c7e0b2002200128021841ffd9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4188dac500105d21000c7d0b200220012802184198dac50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41a0dac500105d21000c7c0b2002200128021841b0dac50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c7b0b2002200128021841b8dac50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41c0dac500105d21000c7a0b2002200128021841d0dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c790b2002200128021841d6dac50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c780b2002200128021841dbdac50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c770b2002200128021841e0dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c760b2002200128021841e6dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c750b2002200128021841ecdac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c740b2002200128021841f2dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c730b2002200128021841f8dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c720b2002200128021841fedac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c710b200220012802184184dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c700b20022001280218418adbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6f0b200220012802184190dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6e0b200220012802184196dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6d0b20022001280218419bdbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6c0b2002200128021841a0dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6b0b2002200128021841a6dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6a0b2002200128021841acdbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c690b2002200128021841b2dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c680b2002200128021841b8dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c670b2002200128021841bedbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c660b2002200128021841c4dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c650b2002200128021841cadbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c640b2002200128021841d0dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c630b2002200128021841d5dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c620b2002200128021841dadbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c610b2002200128021841dfdbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c600b2002200128021841e4dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5f0b2002200128021841e9dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5e0b2002200128021841eedbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5d0b2002200128021841f3dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5c0b2002200128021841f8dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5b0b2002200128021841fddbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5a0b200220012802184182dcc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c590b200220012802184187dcc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c580b20022001280218418cdcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c570b200220012802184192dcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c560b200220012802184198dcc50041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c550b2002200128021841a1dcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c540b2002200128021841a7dcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c530b2002200128021841addcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c520b2002200128021841b3dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c510b2002200128021841badcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c500b2002200128021841c1dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4f0b2002200128021841c8dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4e0b2002200128021841cfdcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4d0b2002200128021841d5dcc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4c0b2002200128021841dadcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4b0b2002200128021841e0dcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4a0b2002200128021841e6dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c490b2002200128021841eddcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c480b2002200128021841f4dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c470b2002200128021841fbdcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c460b200220012802184182ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c450b200220012802184188ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c440b20022001280218418eddc50041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c430b200220012802184197ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c420b20022001280218419dddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c410b2002200128021841a3ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c400b2002200128021841a9ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3f0b2002200128021841b0ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3e0b2002200128021841b7ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3d0b2002200128021841beddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3c0b2002200128021841c5ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3b0b2002200128021841cbddc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3a0b2002200128021841d0ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c390b2002200128021841d6ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c380b2002200128021841dcddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c370b2002200128021841e3ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c360b2002200128021841eaddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c350b2002200128021841f1ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c340b2002200128021841f8ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c330b2002200128021841feddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c320b200220012802184184dec50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c310b20022001280218418bdec50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c300b200220012802184193dec50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2f0b20022001280218419bdec500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2e0b2002200128021841a5dec50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2d0b2002200128021841acdec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2c0b2002200128021841b2dec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2b0b2002200128021841b8dec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2a0b2002200128021841bedec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c290b2002200128021841c4dec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c280b2002200128021841cadec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c270b2002200128021841d0dec500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c260b2002200128021841dbdec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c250b2002200128021841e1dec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c240b2002200128021841e7dec50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c230b2002200128021841eedec50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c220b2002200128021841f6dec50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c210b2002200128021841fedec500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c200b200220012802184188dfc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1f0b20022001280218418fdfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1e0b200220012802184195dfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1d0b20022001280218419bdfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1c0b2002200128021841a1dfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1b0b2002200128021841a7dfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1a0b2002200128021841addfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c190b2002200128021841b3dfc500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c180b2002200128021841bedfc500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c170b2002200128021841c8dfc500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c160b2002200128021841d4dfc500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c150b2002200128021841e0dfc500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c140b2002200128021841ecdfc500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c130b2002200128021841f8dfc500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c120b200220012802184185e0c500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c110b200220012802184192e0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c100b20022001280218419ee0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0f0b2002200128021841aae0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0e0b2002200128021841b6e0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0d0b2002200128021841c2e0c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0c0b2002200128021841d0e0c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0b0b2002200128021841dee0c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0a0b2002200128021841ece0c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c090b2002200128021841fae0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c080b200220012802184186e1c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c070b200220012802184194e1c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c060b2002200128021841a2e1c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c050b2002200128021841b0e1c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c040b2002200128021841bee1c500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c030b2002200128021841cbe1c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c020b2002200128021841dce1c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c010b2002200128021841ede1c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000b20002d00082101024020002802042203450d00200141ff0171210441012101024020040d00024020034101470d0020002d0009450d00200028020022042d00004104710d0041012101200428021841f4afc00041012004411c6a28020028020c1100000d010b2000280200220128021841c8a4c60041012001411c6a28020028020c11000021010b200020013a00080b200241206a2400200141ff01714100470bcd0203027f017e017f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210020034120710d012000ac22042004423f8722047c2004852000417f73411f762001103f21000c020b20002802002103410021000340200220006a41ff006a2003410f712205413072200541d7006a2005410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021030340200220036a41ff006a2000410f712205413072200541376a2005410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d0220014101419087c0004102200220036a4180016a410020036b104221000b20024180016a240020000f0b20034180011044000b20004180011044000bcd0202027f027e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d0120042004423f8722057c2005852004427f552001103f21000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20034180011044000b20034180011044000bc00201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d0020002d0000210420034120710d012004ad42ff018341012001103f21000c020b20002d00002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000bd30101017f230041106b22022400024002400240024020002d00000e03010200010b2002200128021841fee1c500410b2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b200220012802184189e2c500410c2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b200220012802184195e2c500410d2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000b8a0201027f230041106b2202240020002802002802002100200128021841b8d6c500410b2001411c6a28020028020c1100002103200241003a0005200220033a0004200220013602002002200036020c200241c3d6c50041052002410c6a41c8d6c500105c21012002200041086a36020c200141d8d6c50041072002410c6a41a8d6c500105c1a20022d00042101024020022d0005450d00200141ff0171210041012101024020000d0020022802002201411c6a28020028020c210020012802182103024020012d00004104710d00200341eeafc0004102200011000021010c010b200341f0afc0004101200011000021010b200220013a00040b200241106a2400200141ff01714100470b890501047f230041d0006b220224002000280200220041046a28020021032000280200210041012104200128021841adafc00041012001411c6a28020028020c110000210502402003450d0020022000360204024020050d00024020012d0000410471450d0041012104200128021841afafc0004101200128021c28020c1100000d012001280200210541012104200241013a001720022005360218200241b0afc00036023420022001290218370308200220012d00303a00482002200128020436021c200220012902283703402002200129022037033820022001290210370328200220012902083703202002200241176a3602102002200241086a360230200241046a200241186a10d8010d01200228023041c8afc0004102200228023428020c11000021040c010b200241046a200110d80121040b024020034101470d00200421050c010b200041046a21002003410274417c6a210320042105034020022000360204200541ff0171210441012105024020040d00024020012802002204410471450d00200241013a001720022004360218200241b0afc00036023420022001290218370308200220012d00303a00482002200128020436021c200220012902283703402002200129022037033820022001290210370328200220012902083703202002200241176a3602102002200241086a360230200241046a200241186a10d8010d01200228023041c8afc0004102200228023428020c11000021050c010b200128021841caafc0004102200128021c28020c1100000d00200241046a200110d80121050b200041046a21002003417c6a22030d000b0b41012100024020050d00200128021841aeafc0004101200128021c28020c11000021000b200241d0006a240020000b19002000200141186a280200360204200020012802103602000bc50201037f230041206b2202240002400240200028020022002d00004104470d002002200128021841b7e2c50041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841bfe2c50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a41c4e2c500105d210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841f4afc00041012004411c6a28020028020c1100000d010b2001280200220028021841c8a4c60041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470b0c002000280200200110d0040b8f0201017f230041106b220224000240024002400240024020002d00000e0401020300010b2002200128021841d4e2c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c030b2002200128021841d7e2c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b2002200128021841dae2c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841dde2c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000bc00201037f230041206b220224000240024020002d00004104470d002002200128021841b7e2c50041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841bfe2c50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a41c4e2c500105d210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841f4afc00041012004411c6a28020028020c1100000d010b2001280200220028021841c8a4c60041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470b0c002000280200200110c6040bed0902067f017e024020010d00200041ac013a00000f0b024002400240024002400240024020012d00002202414f6a41fb004f0d000c010b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e312c2c0001022c2c0304052c06072c2c08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292c0b20012d00012103410221020c2b0b20012d00012103410321020c2a0b20012d00012103410421020c290b200141046a2802002104410721020c270b200141046a2802002104410821020c260b200141046a2802002105410c10282204450d272005280204220641ffffffff03712006470d2820064102742201417f4c0d280240024020010d00410421070c010b200110282207450d2a0b02402006450d00200528020021012006410274210320072102034020022001280200360200200241046a2102200141046a21012003417c6a22030d000b0b200420063602042004200736020020042005280208360208410921020c250b200141046a2802002104410b21020c240b200141046a280200210420012d00012103410c21020c240b200141046a2802002104410f21020c220b200141046a2802002104411021020c210b200141046a2802002104411121020c200b200141046a2802002104411221020c1f0b200141046a2802002104411321020c1e0b200141046a280200210420013502082108411421020c1d0b200141046a280200210420013502082108411521020c1c0b200141046a280200210420013502082108411621020c1b0b200141046a280200210420013502082108411721020c1a0b200141046a280200210420013502082108411821020c190b200141046a280200210420013502082108411921020c180b200141046a280200210420013502082108411a21020c170b200141046a280200210420013502082108411b21020c160b200141046a280200210420013502082108411c21020c150b200141046a280200210420013502082108411d21020c140b200141046a280200210420013502082108411e21020c130b200141046a280200210420013502082108411f21020c120b200141046a280200210420013502082108412021020c110b200141046a280200210420013502082108412121020c100b200141046a280200210420013502082108412221020c0f0b200141046a280200210420013502082108412321020c0e0b200141046a280200210420013502082108412421020c0d0b200141046a280200210420013502082108412521020c0c0b200141046a280200210420013502082108412621020c0b0b200141046a280200210420013502082108412721020c0a0b200141046a280200210420013502082108412821020c090b200141046a280200210420013502082108412921020c080b200141046a280200210420013502082108412a21020c070b20012d00012103412b21020c070b20012d00012103412c21020c060b200141046a2802002104412d21020c040b20012903082108412e21020c020b200141046a2802002104412f21020c020b20012903082108413021020b0b0b200020033a0001200020023a0000200041086a2008370300200041046a20043602000f0b410c41041037000b1036000b200141041037000bba0201037f230041106b220224000240024020002802000d002002200128021841e0e2c50041042001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841e4e2c50041042001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41e8e2c500105d210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841f4afc00041012004411c6a28020028020c1100000d010b2001280200220028021841c8a4c60041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470b22002001419daec0004198aec00020002802002d000022001b4104410520001b10450bd60501087f230041106b220324002002280208220441546a2105200241106a280200220641306c210702400340410021082007450d01200741506a21072005412c6a2109200541306a220a210520092d00004103470d000b200a41086a2802002207450d00200741286c2105200a28020041186a2107410021080340200820072d0000456a2108200741286a2107200541586a22050d000b0b02400240024002400240024002400240200120086b220a20014b0d00200641306c2107200441546a210503402007450d02200741506a21072005412c6a2108200541306a2209210520082d0000410c470d000b200941086a280200200a4b0d02411e102822070d05411e41011037000b412c102822070d02412c41011037000b412c102822070d02412c41011037000b2009280200200a41186c6a28020821072003200a200210dd0420032802004101460d0320032802042105200041003602002000200520076a3602040c040b2000200736020420004101360200200741286a41002800fee545360000200741206a41002900f6e545370000200741186a41002900eee545370000200741106a41002900e6e545370000200741086a41002900dee545370000200741002900d6e545370000200041086a42ac808080c0053702000c030b2000200736020420004101360200200741286a41002800aae645360000200741206a41002900a2e645370000200741186a410029009ae645370000200741106a4100290092e645370000200741086a410029008ae64537000020074100290082e645370000200041086a42ac808080c0053702000c020b2000200736020420004101360200200741166a41002900c4e645370000200741106a41002900bee645370000200741086a41002900b6e645370000200741002900aee645370000200041086a429e808080e0033702000c010b20002003290204370204200041013602002000410c6a2003410c6a2802003602000b200341106a24000b8d0301067f230041106b220224000240024002400240200041046a2802002203200041086a28020022046b20012802042205200128020022066b4104762207490d00200028020021030c010b200420076a22062004490d02200341017422052006200520064b1b220641ffffffff00712006470d02200641047422054100480d020240024020030d002005102821030c010b200028020020034104742005102c21030b2003450d0120002003360200200041046a2006360200200041086a280200210420012802042105200128020021060b0240024020062005470d00410021060c010b2001200641106a3602000b2002200610d304024020022d000041ac01460d00200320044104746a2106034020062002290300370300200641086a200241086a29030037030002400240200128020022052001280204470d00410021050c010b2001200541106a3602000b200441016a2104200641106a21062002200510d30420022d000041ac01470d000b0b200041086a2004360200200241106a24000f0b200541081037000b1031000b1000200028020035020041012001103f0be00a01067f024002400240024020012d00002202414f6a41fb00490d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e312a2a0001022a2a0304052a06072a2a08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a0b200020012d00013a0001200041023a00000f0b200020012d00013a0001200041033a00000f0b200020012d00013a0001200041043a00000f0b200041046a200141046a280200360200200041073a00000f0b200041046a200141046a280200360200200041083a00000f0b200141046a2802002103410c10282204450d252003280204220541ffffffff03712005470d2620054102742201417f4c0d260240024020010d00410421060c010b200110282206450d280b02402005450d00200328020021012005410274210720062102034020022001280200360200200241046a2102200141046a21012007417c6a22070d000b0b200420053602042004200636020020042003280208360208200041046a2004360200200041093a00000f0b200041046a200141046a2802003602002000410b3a00000f0b200020012d00013a0001200041046a200141046a2802003602002000410c3a00000f0b200041046a200141046a2802003602002000410f3a00000f0b200041046a200141046a280200360200200041103a00000f0b200041046a200141046a280200360200200041113a00000f0b200041046a200141046a280200360200200041123a00000f0b200041046a200141046a280200360200200041133a00000f0b200041046a200141046a290200370200200041143a00000f0b200041046a200141046a290200370200200041153a00000f0b200041046a200141046a290200370200200041163a00000f0b200041046a200141046a290200370200200041173a00000f0b200041046a200141046a290200370200200041183a00000f0b200041046a200141046a290200370200200041193a00000f0b200041046a200141046a2902003702002000411a3a00000f0b200041046a200141046a2902003702002000411b3a00000f0b200041046a200141046a2902003702002000411c3a00000f0b200041046a200141046a2902003702002000411d3a00000f0b200041046a200141046a2902003702002000411e3a00000f0b200041046a200141046a2902003702002000411f3a00000f0b200041046a200141046a290200370200200041203a00000f0b200041046a200141046a290200370200200041213a00000f0b200041046a200141046a290200370200200041223a00000f0b200041046a200141046a290200370200200041233a00000f0b200041046a200141046a290200370200200041243a00000f0b200041046a200141046a290200370200200041253a00000f0b200041046a200141046a290200370200200041263a00000f0b200041046a200141046a290200370200200041273a00000f0b200041046a200141046a290200370200200041283a00000f0b200041046a200141046a290200370200200041293a00000f0b200041046a200141046a2902003702002000412a3a00000f0b200020012d00013a00012000412b3a00000f0b200020012d00013a00012000412c3a00000f0b200041046a200141046a2802003602002000412d3a00000f0b200041086a200141086a2903003703002000412e3a00000f0b200041046a200141046a2802003602002000412f3a00000f0b200041086a200141086a290300370300413021020b200020023a00000f0b410c41041037000b1036000b200141041037000bea0302057f017e02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d00200020014105746a220441c4006a2802002105200441386a2802002106200441346a2802002107200141016a21010c010b02400240200028020022010d002003ad210841002104410021010c010b20003301044220862003ad842108410121040b2000102a2008a72103024002402008422088a7220620012f01064f0d00200121050c010b034002400240200128020022050d002003ad2108410021050c010b200441016a210420013301044220862003ad8421080b2001102a2008a72103200521012008422088a7220620052f01064f0d000b0b200641027420056a4198036a2802002100200520064105746a220141c4006a2802002105200141386a2802002106200141346a280200210702402004417f6a2201450d00034020002802940321002001417f6a22010d000b0b410021010b20054102460d012002417f6a210202402006450d002007102a0b20020d000b0b0240200041f8b9c000460d00200028020021012000102a2001450d00200128020021052001102a2005450d00024020052802002201450d0003402005102a2001210520012802002200210120000d000b0b2005102a0b0bba09010b7f230041e0006b22032400200320013602202002280208220441546a2105200241106a280200220641306c210202400340024020020d00410021070c020b200241506a21022005412c6a2107200541306a2208210520072d00004102470d000b200341186a200810fa0320032802182107200328021c21020b2002410020071b2109200641306c2102200441546a21052007410420071b210a02400340024020020d004100210b0c020b200241506a21022005412c6a2107200541306a2208210520072d00004104470d000b200341106a200810fa032003280210210b2003280214210c0b200641306c2102200441546a2105200b4104200b1b210d02400240024002400240024003402002450d01200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200841086a2802002202450d00200241286c2107200828020041186a2102410021050340200520022d0000456a2105200241286a2102200741586a22070d000b200520014d0d01200641306c2102200441546a2105024003402002450d01200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200341086a200810fa0320032802082202200328020c41286c6a21070240024002400340024002400240200720026b41f8004b0d0020022007460d0d2002411c6a2105034020022d0018450d02200541286a2105200241286a22022007470d000c0e0b0b20022d00180d01200241186a2105200241286a21080c040b2005410c6a21080c040b200241c0006a22052d0000450d010240200241e8006a22052d0000450d0020024190016a2105200241a0016a2208210220052d00000d010c030b0b200241f8006a21080c010b200241d0006a21080b200541046a21050b2001450d0303402001417f6a210120082102024002400340024002400240200720026b41f8004b0d0020022007460d0d2002411c6a2105034020022d0018450d02200541286a2105200241286a22022007460d0e0c000b0b20022d00180d01200241186a2105200241286a21080c040b2005410c6a210820010d040c080b200241c0006a22052d0000450d010240200241e8006a22052d0000450d0020024190016a2105200241a0016a2208210220052d00000d010c030b0b200241f8006a21080c010b200241d0006a21080b20010d000b200541046a21050c030b41cce6c50041c2001050000b410021050b0240200c4100200b1b200120056b22024d0d00200d20024102746a22050d010b200341cc006a41013602002003420237023c200341ece7c5003602382003410136022c2003200341286a3602482003200341206a360228200341d0006a200341386a1033200341d0006a21020c010b2003200528020022023602240240200920024d0d00200a20024104746a2202450d0020002002360204410021020c020b200341cc006a4102360200200341dc006a41013602002003420337023c200341fce7c500360238200341013602542003200341d0006a3602482003200341206a3602582003200341246a360250200341286a200341386a1033200341286a21020b20022802002105200041086a200229020437020020002005360204410121020b20002002360200200341e0006a24000f0b418ee7c50041dd001050000bf80d01067f0240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a280200102a0f0b0240200041086a280200450d00200041046a280200102a0b200041146a280200450d0c200041106a280200102a0f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b200041086a280200450d0b2000280204102a0f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200241586a22020d000b0b200041086a280200450d0a2000280204102a0f0b200041086a280200450d09200041046a280200102a0f0b200041086a280200450d08200041046a280200102a0f0b200041086a280200450d07200041046a280200102a0f0b02402000410c6a2802002201450d00200041046a280200220320014104746a21040340024020032802082202450d0020032802002101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341106a21010240200341046a280200450d002003280200102a0b2001210320012004470d000b0b200041086a280200450d062000280204102a0f0b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d002001280200102a0b200141146a21012002416c6a22020d000b0b200041086a280200450d052000280204102a0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102a0b2003411c6a21010240200341146a280200450d002003280210102a0b2001210320012004470d000b0b200041086a280200450d042000280204102a0f0b02402000410c6a2802002201450d00200041046a2802002203200141186c6a210403400240200341046a280200450d002003280200102a0b0240200341146a2802002202450d00200328020c2101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341186a21010240200341106a280200450d00200328020c102a0b2001210320012004470d000b0b200041086a280200450d032000280204102a0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102a0b2003411c6a21010240200341146a280200450d002003280210102a0b2001210320012004470d000b0b200041086a280200450d022000280204102a0f0b0240200041046a2802002201450d00200041086a280200450d002001102a0b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102a0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102a0b200041246a2802002203450d0102402000412c6a2802002201450d00200320014104746a210403402003220541106a2103024020052802042201450d0002402005410c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102a0b2001410c6a2101200241746a22020d000b0b200541086a280200450d002005280204102a0b20032004470d000b0b200041286a280200450d012000280224102a0c010b0240200041086a280200450d00200041046a280200102a0b0240200041146a2802002201450d00200041186a280200450d002001102a0b200041246a280200450d00200041206a280200102a0f0b0bd65e010c7f23004190016b220324002003200136021c2002280208220441546a2105200241106a280200220641306c21010240024002400240024002400240024002400240024002400240024003402001450d01200141506a21012005412c6a2107200541306a2208210520072d00004104470d000b200641306c2101200441546a210503402001450d02200141506a21012005412c6a2107200541306a2209210520072d0000410c470d000b200641306c2101200441546a210503402001450d03200141506a21012005412c6a2107200541306a2204210520072d00004102470d000b02404100280280b1464105490d002003410136023c20032003411c6a3602384100280284b146210120034188016a41980136020020034180016a42ed80808010370300200341f8006a4125360200200341f0006a4101360200200341e0006a4201370300200341d8006a410a360200200341fcf0c50036027c200341d7f0c500360274200341ec006a200341386a360200200341f8edc50036025c200341cdf0c500360254200341053602504188b1c60041b8aec600200141024622011b200341d0006a41c8b0c00041e0b0c00020011b2802101102000b200341106a200810fa032003280214200328021c22014d0d03200328021020014102746a2201450d03200341086a200410fa030240200328020c200128020022014d0d00200328020820014104746a22010d050b412510282201450d052001411d6a410029009dee45370000200141186a4100290098ee45370000200141106a4100290090ee45370000200141086a4100290088ee4537000020014100290080ee45370000200041086a42a5808080d00437020020002001360204200041013602000c0d0b411310282201450d082001410f6a41002800d3ed45360000200141086a41002900cced45370000200141002900c4ed45370000200041086a4293808080b00237020020002001360204200041013602000c0c0b410f10282201450d06200141076a41002900deed45370000200141002900d7ed45370000200041086a428f808080f00137020020002001360204200041013602000c0b0b410f10282201450d04200141076a41002900eded45370000200141002900e6ed45370000200041086a428f808080f00137020020002001360204200041013602000c0a0b412510282201450d022001411d6a410029009dee45370000200141186a4100290098ee45370000200141106a4100290090ee45370000200141086a4100290088ee4537000020014100290080ee45370000200041086a42a5808080d00437020020002001360204200041013602000c090b02400240200941086a280200200328021c22054b0d00412710282201450d012001411f6a41002900c4ee45370000200141186a41002900bdee45370000200141106a41002900b5ee45370000200141086a41002900adee45370000200141002900a5ee45370000200041086a42a7808080f00437020020002001360204200041013602000c0a0b20092802002109200341206a41086a420037030020034280808080c00037032020012d000d2107410021012003410036024020032007410447220a36023c2003200a360238200341003a0044024002400240024002404100280280b14641044b0d00200341d0006a41086a200341386a41086a29030037030020032003290338370350200341206a410472210b200341d0006a21070c010b2003412d36024c2003200341386a3602484100280284b146210120034188016a41cb0036020020034180016a42ed80808010370300200341f8006a4125360200200341f0006a4101360200200341e0006a4201370300200341d0006a41086a2207410a360200200341fcf0c50036027c200341d7f0c500360274200341ec006a200341c8006a360200200341cceec50036025c200341cdf0c500360254200341053602504188b1c60041b8aec600200141024622011b200341d0006a41c8b0c00041e0b0c00020011b280210110200200328022c2108200328022821012007200341386a41086a29030037030020032003290338370350200341206a410472210b200341d0006a210720082001470d010b200141016a22082001490d01200141017422062008200620084b1b220841ffffffff00712008470d01200841047422064100480d010240024020010d002006102821010c010b200b28020020014104742006102c21010b2001450d02200b200136020020032008360228200328022c21080b200b28020020084104746a22012007290200370200200141086a200741086a2902003702002003200328022c41016a36022c410021072009200541186c6a2201280214450d092009200541186c6a410c6a2109200141146a2108200341d0006a410472210c410021074100210103400240200328022020074d0d00200341d0006a200341206a410010e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c0d0b2007200328022020032802542d000c1b21070b02400240024002400240024002402001200828020022054f0d002003200928020020014104746a220536023402404100280280b1464105490d002003412936023c2003200341346a3602384100280284b1462105200341c90136028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341b0aec60036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328023421050b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020052d000022060eac0102220000002201030405060708090a0b0c0d0e0f1010101010101010101010101010111111111111111111121314141414151616161616161616161615161616161616161616161616161616161616161616161717171818181818181818181818181818181717171818181818181818181818181818181717171717171718181818181818171717171717171818181818181819191919191919191919191919191919191919191919191919020b20052d00012105200320032802203602402003200541044722053602382003200641034720057136023c200341003a004402404100280280b1464105490d002003412d36024c2003200341386a3602484100280284b1462105200341cb0036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341cceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341c8006a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b200341d0006a41086a2206200341386a41086a290300370300200320032903383703500240200328022c22052003280228470d00200541016a220d2005490d242005410174220e200d200e200d4b1b220d41ffffffff0071200d470d24200d410474220e4100480d240240024020050d00200e102821050c010b200b2802002005410474200e102c21050b2005450d1d200b20053602002003200d360228200328022c21050b200b28020020054104746a22052003290350370200200541086a20062903003702002003200328022c41016a36022c0c210b4100210502404100280280b1464105490d000240200328022c2206417f6a220d20064b0d00200b280200200d4104746a4100200d2006491b21050b2003412e36024c200320053602382003200341386a3602484100280284b1462105200341d30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341d4eec50036025c2003410a360258200341cdf0c500360254200341053602502003200341c8006a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b0240200328022c2205450d0020032005417f6a220536022c200b28020020054104746a22052d000c4102470d1a0b411710282201450d1c2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c2c0b02404100280280b1464105490d004100280284b1462105200341c10036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003420437026c20034201370360200341f4eec50036025c2003410a360258200341cdf0c500360254200341053602504188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b0240200328022c2205417f6a220620054f0d00200620054d0d180b411710282201450d1e2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c2b0b200341d0006a200341206a200541046a28020010e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c2b0b200341d0006a200341206a200328025428020410e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c2b0b02404100280280b1464105490d004100280284b1462105200341c10036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003420437026c20034201370360200341f4eec50036025c2003410a360258200341cdf0c500360254200341053602504188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102822010d01411741011037000b200b28020020064104746a41013a000c0c1f0b2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c2a0b200341d0006a200341206a200541046a28020010e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c2a0b200341d0006a200341206a2003280254280204220510e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c2a0b200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c2a0b2003200536024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c1e0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c290b200341d0006a200341206a200541046a28020028020810e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c290b2003280254280204210d2005280204220628020441027421052006280200210602400340024020050d00200341d0006a200341206a200d10e4042003280250450d0220002003290350370204200041013602002000410c6a200341d8006a2802003602000c2b0b200341d0006a200341206a200628020010e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c2b0b2005417c6a2105200641046a21062003280254280204200d460d000b412710282201450d1a2001411f6a41002900b1ef45370000200141186a41002900aaef45370000200141106a41002900a2ef45370000200141086a410029009aef4537000020014100290092ef45370000200041086a42a7808080f00437020020002001360204200041013602000c290b02404100280280b1464105490d004100280284b1462105200341c10036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003420437026c20034201370360200341f4eec50036025c2003410a360258200341cdf0c500360254200341053602504188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102822010d01411741011037000b200b28020020064104746a41013a000c0c1d0b2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c280b200341d0006a200341206a200a10e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c280b02404100280280b1464105490d004100280284b1462105200341c10036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003420437026c20034201370360200341f4eec50036025c2003410a360258200341cdf0c500360254200341053602504188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102822010d01411741011037000b200b28020020064104746a41013a000c0c1c0b2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c270b200341d0006a200541046a280200200210db04024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c270b200341d0006a200341206a2003280254220528020810e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c270b200320052d000d410447220536024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c1b0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c260b2003200410fa03024002402003280204200541046a28020022054d0d002003280200220620054104746a220d0d010b410e10282201450d18200141066a41002900bfef45370000200141002900b9ef45370000200041086a428e808080e00137020020002001360204200041013602000c260b200341d0006a200341206a200620054104746a28020810e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c260b2003200d2d000d410447220536024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c1a0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c250b200341d0006a200341206a410110e4042003280250450d1820002003290350370204200041013602002000410c6a200341d8006a2802003602000c240b200341d0006a200341206a410210e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c240b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c240b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c180b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c230b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c170b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c220b200341d0006a200341206a410110e4042003280250450d1520002003290350370204200041013602002000410c6a200341d8006a2802003602000c210b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c210b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c150b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c200b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c140b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c1f0b200341d0006a200341206a410110e4042003280250450d1220002003290350370204200041013602002000410c6a200341d8006a2802003602000c1e0b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1e0b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c120b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c1d0b200341d0006a200341206a410210e4042003280250450d1020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1c0b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c100b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c1b0b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1b0b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0f0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c1a0b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0e0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c190b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c190b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0d0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c180b200341d0006a200341206a410210e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c180b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0c0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c170b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c170b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0b0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c160b200341d0006a200341206a410210e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c160b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0a0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c150b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c150b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c090b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c140b200b28020020064104746a41013a000c0c070b2005280200210620032005280208220536023802404100280280b1464105490d002003410136024c2003200341386a3602484100280284b1462105200341db0036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341c8efc50036025c2003410a360258200341cdf0c500360254200341053602502003200341c8006a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328023821050b200320053602202003200636024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b28021011020020032802202105200328024821060b0240200520066a220620054f0d00410e102822010d11410e41011037000b200320063602200c060b41d0efc500200120051034000b200e41041037000b411741011037000b412741011037000b410e41011037000b411741011037000b200141016a22012008280200490d000c0a0b0b1031000b200641041037000b412741011037000b412541011037000b412541011037000b410f41011037000b410f41011037000b411341011037000b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c010b20004100360200200020073602042003280228450d01200b280200102a0c010b2003280228450d00200b280200102a0b20034190016a24000bf50202057f017e02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034103746a220329020021072003200020044103746a220429020037020020042007370200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024103746a220329020021072003200020044103746a2204290200370200200420073702002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034103746a220129020021072001200020044103746a2200290200370200200020073702000b0f0b41a8e9c500200420011034000b4198e9c500200320011034000bd50302047f017e024020014101762202450d0003402002417f6a2202210302400240024003402003410174220441017221050240200441026a220420014f0d00200520014f0d0220042005200020054103746a280200200020044103746a280200491b21050b200520014f0d03200320014f0d02200020034103746a2203280200200020054103746a22042802004f0d03200329020021062003200429020037020020042006370200200521030c000b0b41e8eac500200520011034000b41f8eac500200320011034000b20020d000b0b0240024020014102490d002001210403402004417f6a220420014f0d02200029020021062000200020044103746a2205290200370200200520063702004100210302400240024003402003410174220241017221050240200241026a220220044f0d00200520044f0d0220022005200020054103746a280200200020024103746a280200491b21050b200520044f0d03200320044f0d02200020034103746a2203280200200020054103746a22022802004f0d03200329020021062003200229020037020020022006370200200521030c000b0b41e8eac500200520041034000b41f8eac500200320041034000b200441014b0d000b0b0f0b41a8e9c500200420011034000bea04050a7f017e017f017e027f200041686a21022001417f6a2103200041086a2104410021052001413249210641012107024003400240024020072001490d00410021080c010b410121082000200741037422096a220a280200220b200a41786a280200490d00200420096a210803404101210a20032007460d03200741016a21072008280200220a200b4f2109200841086a2108200a210b20090d000b200720014921080b2007200146210a20060d0120072001460d010240024002400240024002402007417f6a220b20014f0d002008450d012000200b4103746a220b290200210c200b20002007410374220d6a2208290200220e3702002008200c37020020074102490d0520002007417e6a220a4103746a220f280200200ea722094d0d05200b200f290200370200200a450d0420002007417d6a220a4103746a28020020094d0d042002200d6a210b0340200b41086a200b290200370200200a450d03200a417f6a210a200b41786a220b28020020094b0d000b200a41016a210b0c030b4198e9c500200b20011034000b41a8e9c500200720011034000b4100210b0b2000200b4103746a210f0b200f200e3702000b200541016a21050240200120076b220a4102490d00200828020820082802004f0d002008290200210c20082008290208370200200841086a210f0240200a4103490d002008280210200ca722104f0d00200841106a21094103210b4102210d0340200d41037420086a220f41786a2009290200370200200b200a4f0d01200b4103742109200b210d200b41016a210b200820096a22092802002010490d000b0b200f200c3702000b20054105470d000b4100210a0b200a0bcc0201027f230041106b2202240020002802002802002100200128021841ebecc50041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c200241f0ecc500410e2002410c6a4180edc500105c21012002200036020c20014190edc50041092002410c6a419cedc500105c21012002200041046a36020c200141acedc500410c2002410c6a419cedc500105c21012002200041086a36020c200141b8edc500410c2002410c6a419cedc500105c1a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d00200341eeafc0004102200111000021000c010b200341f0afc0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470bc20201027f230041106b22022400200128021841ebecc50041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c200241f0ecc500410e2002410c6a4180edc500105c21012002200036020c20014190edc50041092002410c6a419cedc500105c21012002200041046a36020c200141acedc500410c2002410c6a419cedc500105c21012002200041086a36020c200141b8edc500410c2002410c6a419cedc500105c1a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d00200341eeafc0004102200111000021000c010b200341f0afc0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470b9b0201027f024002400240024002402001410c6a2802002203417f6a220420034d0d00411610282201450d01200020013602042001410e6a41002900ddf245370000200141086a41002900d7f245370000200141002900cff245370000200041086a4296808080e0023702000c040b0240200420026b220220044d0d00411b10282201450d0220002001360204200141176a41002800fcf245360000200141106a41002900f5f245370000200141086a41002900edf245370000200141002900e5f245370000200041086a429b808080b0033702000c040b200320024d0d022000200128020420024104746a360204200041003602000f0b411641011037000b411b41011037000b4180f3c500200220031034000b200041013602000bc50401027f230041d0006b220324002003200236020402404100280280b1464105490d002003410136020c2003200341046a3602084100280284b1462102200341c8006a41ef00360200200341c0006a42ed80808010370300200341386a4125360200200341306a4101360200200341206a4201370300200341186a410a360200200341fcf0c50036023c200341d7f0c5003602342003412c6a200341086a360200200341f8f1c50036021c200341cdf0c500360214200341053602104188b1c60041b8aec600200241024622021b200341106a41c8b0c00041e0b0c00020021b280210110200200328020421020b0240024002402002450d00200341106a2001410010e30420032802104101470d012000200341106a4104722202290200370200200041086a200241086a2802003602000c020b200041003602000c010b02400240024002402001280200220220032802142204280208460d00200220032802046b220420024d0d02410f102822020d01410f41011037000b024020042d000c0d00412510282202450d03200042a5808080d004370204200020023602002002411d6a410029009df245370000200241186a4100290098f245370000200241106a4100290090f245370000200241086a4100290088f24537000020024100290080f2453700000c040b200041003602000c030b2000428f808080f00137020420002002360200200241076a41002900acf245370000200241002900a5f2453700000c020b20004100360200200120043602000c010b412541011037000b200341d0006a24000bac0301047f230041c0006b2202240020002802002100410121030240200128021841baaec000410c2001411c6a28020028020c1100000d0002400240200028020822030d0020002802002203200028020428020c11070042e4aec285979ba58811520d012002200336020c2002412b36021420022002410c6a36021020012802182104200128021c2105410121032002413c6a41013602002002420237022c200241c8aec0003602282002200241106a36023820042005200241286a10350d020c010b2002200336020c2002412f36021420022002410c6a36021020012802182104200128021c2105410121032002413c6a41013602002002420237022c200241c8aec0003602282002200241106a36023820042005200241286a10350d010b200241106a41146a4101360200200241106a410c6a4101360200200241043602142002200041186a3602202002200041146a36021820022000410c6a36021020012802182100200128021c2101200241286a41146a41033602002002420337022c200241d8aec0003602282002200241106a36023820002001200241286a103521030b200241c0006a240020030b1500200120002802002200280200200028020410450b080020002001100b0bbe04020d7f017e230041c0006b22032400200128020022042001280208220541047422066a210720012802042108200421010240024002402005450d00200641706a2109200341306a410172210a200341306a41026a2106200341206a410172220b41076a210c20042101034020012d000021052006200141036a2d00003a00002003200141016a2f00003b01300240200541ac01470d00200141106a21010c020b2003410c6a41026a20062d0000220d3a0000200320032f0130220e3b010c200141046a280200210f200141086a2903002110200a200e3b0000200a41026a200d3a0000200320053a0030200320103703382003200f360234200341206a200341306a200210e9042003200b2900003703102003200c290000370017024020032d00202205411f470d00200941706a2109200141106a22012007470d010c030b0b200020053a000020002003290310370001200041086a200329001737000002402009450d00200141106a210103400240024020012d000022054109460d00200541ac01470d010c030b0240200141046a280200220528020441ffffffff0371450d002005280200102a0b2005102a0b200141106a22012007470d000b0b2008450d022004102a0c020b20012007460d0003400240024020012d000022054109460d00200541ac01470d010c030b0240200141046a280200220528020441ffffffff0371450d002005280200102a0b2005102a0b200141106a22012007470d000b0b02402008450d002004102a0b2000411f3a00000b200341c0006a24000bcbd60202097f017e230041106b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df501200441017422082005200820054b1b22084100480df5010240024020040d002008102821050c010b200628020020042008102c21050b2005450dad0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df501200441017422082005200820054b1b22084100480df5010240024020040d002008102821050c010b200628020020042008102c21050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df401200441017422082005200820054b1b22084100480df4010240024020040d002008102821050c010b200628020020042008102c21050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df401200441017422082005200820054b1b22084100480df4010240024020040d002008102821050c010b200628020020042008102c21050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df301200441017422082005200820054b1b22084100480df3010240024020040d002008102821050c010b200628020020042008102c21050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df301200441017422082005200820054b1b22084100480df3010240024020040d002008102821050c010b200628020020042008102c21050b2005450db00120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490df001200441017422072006200720064b1b22074100480df0010240024020040d002007102821060c010b200928020020042007102c21060b2006450db00120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df1012004410174220a2006200a20064b1b220a4100480df1010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490def01200441017422072006200720064b1b22074100480def010240024020040d002007102821060c010b200928020020042007102c21060b2006450db10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df0012004410174220a2006200a20064b1b220a4100480df0010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490dee01200441017422062005200620054b1b22064100480dee010240024020040d002006102821050c010b200928020020042006102c21050b2005450db20120022005360204200241086a20063602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a410e3a0000200320012802042204280204220520042802002204200420054102746a200210ea042003210420032d0000411f470d930320012802042802082105200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490def012004410174220a2006200a20064b1b220a4100480def010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db401200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490ded01200441017422062005200620054b1b22064100480ded010240024020040d002006102821050c010b200228020420042006102c21050b2005450db30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490dec01200441017422072006200720064b1b22074100480dec010240024020040d002007102821060c010b200928020020042007102c21060b2006450db30120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490ded012004410174220a2006200a20064b1b220a4100480ded010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490deb01200441017422072006200720064b1b22074100480deb010240024020040d002007102821060c010b200928020020042007102c21060b2006450db40120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490dec012004410174220a2006200a20064b1b220a4100480dec010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490deb01200441017422062005200620054b1b22064100480deb010240024020040d002006102821050c010b200928020020042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dea01200441017422062005200620054b1b22064100480dea010240024020040d002006102821050c010b200228020420042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490de901200441017422062005200620054b1b22064100480de9010240024020040d002006102821050c010b200228020420042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de801200441017422072006200720064b1b22074100480de8010240024020040d002007102821060c010b200928020020042007102c21060b2006450db60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de9012004410174220a2006200a20064b1b220a4100480de9010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db801200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de701200441017422072006200720064b1b22074100480de7010240024020040d002007102821060c010b200928020020042007102c21060b2006450db70120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de8012004410174220a2006200a20064b1b220a4100480de8010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db901200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de601200441017422072006200720064b1b22074100480de6010240024020040d002007102821060c010b200928020020042007102c21060b2006450db80120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de7012004410174220a2006200a20064b1b220a4100480de7010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dba01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de501200441017422072006200720064b1b22074100480de5010240024020040d002007102821060c010b200928020020042007102c21060b2006450db90120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de6012004410174220a2006200a20064b1b220a4100480de6010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dbb01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de401200441017422072006200720064b1b22074100480de4010240024020040d002007102821060c010b200928020020042007102c21060b2006450dba0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de5012004410174220a2006200a20064b1b220a4100480de5010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dbc01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de301200441017422082007200820074b1b22084100480de3010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de4012004410174220b2007200b20074b1b220b4100480de4010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dbd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de401200441017422092006200920064b1b22094100480de4010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dbe012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de201200441017422082007200820074b1b22084100480de2010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de3012004410174220b2007200b20074b1b220b4100480de3010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dbf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de301200441017422092006200920064b1b22094100480de3010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de101200441017422082007200820074b1b22084100480de1010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de2012004410174220b2007200b20074b1b220b4100480de2010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de201200441017422092006200920064b1b22094100480de2010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de001200441017422082007200820074b1b22084100480de0010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de1012004410174220b2007200b20074b1b220b4100480de1010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de101200441017422092006200920064b1b22094100480de1010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddf01200441017422082007200820074b1b22084100480ddf010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de0012004410174220b2007200b20074b1b220b4100480de0010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de001200441017422092006200920064b1b22094100480de0010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dde01200441017422082007200820074b1b22084100480dde010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddf012004410174220b2007200b20074b1b220b4100480ddf010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddf01200441017422092006200920064b1b22094100480ddf010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc8012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c93010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddd01200441017422082007200820074b1b22084100480ddd010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc70120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dde012004410174220b2007200b20074b1b220b4100480dde010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dde01200441017422092006200920064b1b22094100480dde010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dca012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddc01200441017422082007200820074b1b22084100480ddc010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc90120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddd012004410174220b2007200b20074b1b220b4100480ddd010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcb01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddd01200441017422092006200920064b1b22094100480ddd010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dcc012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddb01200441017422082007200820074b1b22084100480ddb010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddc012004410174220b2007200b20074b1b220b4100480ddc010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddc01200441017422092006200920064b1b22094100480ddc010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dce012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dda01200441017422082007200820074b1b22084100480dda010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddb012004410174220b2007200b20074b1b220b4100480ddb010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddb01200441017422092006200920064b1b22094100480ddb010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8f010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd901200441017422082007200820074b1b22084100480dd9010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dda012004410174220b2007200b20074b1b220b4100480dda010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dda01200441017422092006200920064b1b22094100480dda010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd801200441017422082007200820074b1b22084100480dd8010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd9012004410174220b2007200b20074b1b220b4100480dd9010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd901200441017422092006200920064b1b22094100480dd9010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd701200441017422082007200820074b1b22084100480dd7010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd8012004410174220b2007200b20074b1b220b4100480dd8010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd801200441017422092006200920064b1b22094100480dd8010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd601200441017422082007200820074b1b22084100480dd6010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da3022004410174220b2007200b20074b1b220b4100480da3020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da302200441017422092006200920064b1b22094100480da3020240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da102200441017422082007200820074b1b22084100480da1020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da2022004410174220b2007200b20074b1b220b4100480da2020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dda01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da202200441017422092006200920064b1b22094100480da2020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da002200441017422082007200820074b1b22084100480da0020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dda0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da1022004410174220b2007200b20074b1b220b4100480da1020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450ddc01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da102200441017422092006200920064b1b22094100480da1020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddd012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9f02200441017422082007200820074b1b22084100480d9f020240024020040d002008102821070c010b200a28020020042008102c21070b2007450ddc0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da0022004410174220b2007200b20074b1b220b4100480da0020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dde01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da002200441017422092006200920064b1b22094100480da0020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddf012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9e02200441017422082007200820074b1b22084100480d9e020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dde0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9f022004410174220b2007200b20074b1b220b4100480d9f020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9f02200441017422092006200920064b1b22094100480d9f020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de1012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c87010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9d02200441017422082007200820074b1b22084100480d9d020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de00120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9e022004410174220b2007200b20074b1b220b4100480d9e020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9e02200441017422092006200920064b1b22094100480d9e020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de3012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9c02200441017422082007200820074b1b22084100480d9c020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de20120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9d022004410174220b2007200b20074b1b220b4100480d9d020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9d02200441017422092006200920064b1b22094100480d9d020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de5012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9b02200441017422082007200820074b1b22084100480d9b020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de40120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9c022004410174220b2007200b20074b1b220b4100480d9c020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9c02200441017422092005200920054b1b22094100480d9c020240024020040d002009102821050c010b200a28020020042009102c21050b2005450de7012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a02200441017422082007200820074b1b22084100480d9a020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de60120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b022004410174220b2007200b20074b1b220b4100480d9b020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b02200441017422092006200920064b1b22094100480d9b020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9902200441017422082007200820074b1b22084100480d99020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a022004410174220b2007200b20074b1b220b4100480d9a020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dea01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a02200441017422092006200920064b1b22094100480d9a020240024020040d002009102821060c010b200a28020020042009102c21060b2006450deb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9802200441017422082005200820054b1b22084100480d98020240024020040d002008102821050c010b200628020020042008102c21050b2005450dea0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d9802200441017422082005200820054b1b22084100480d98020240024020040d002008102821050c010b200628020020042008102c21050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9702200441017422082005200820054b1b22084100480d97020240024020040d002008102821050c010b200628020020042008102c21050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d9702200441017422082005200820054b1b22084100480d97020240024020040d002008102821050c010b200628020020042008102c21050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9602200441017422072005200720054b1b22074100480d96020240024020040d002007102821050c010b200228020420042007102c21050b2005450dec0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a000020032006200210eb042003210420032d0000411f470def020c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9502200441017422062005200620054b1b22064100480d95020240024020040d002006102821050c010b200228020420042006102c21050b2005450dec0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c200210ec042003210420032d0000411f470dee020c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9402200441017422082005200820054b1b22084100480d94020240024020040d002008102821050c010b200628020020042008102c21050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d9402200541017422042008200420084b1b22044100480d94020240024020050d002004102821050c010b200628020020052004102c21050b2005450ded0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9302200441017422072005200720054b1b22074100480d93020240024020040d002007102821050c010b200628020020042007102c21050b2005450ded0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d9302200541017422042007200420074b1b22044100480d93020240024020050d002004102821050c010b200628020020052004102c21050b2005450dee0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9202200441017422062005200620054b1b22064100480d92020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9102200441017422062005200620054b1b22064100480d91020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9002200441017422062005200620054b1b22064100480d90020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f02200441017422062005200620054b1b22064100480d8f020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e02200441017422062005200620054b1b22064100480d8e020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d02200441017422062005200620054b1b22064100480d8d020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c02200441017422062005200620054b1b22064100480d8c020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b02200441017422062005200620054b1b22064100480d8b020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a02200441017422062005200620054b1b22064100480d8a020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8902200441017422062005200620054b1b22064100480d89020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8802200441017422062005200620054b1b22064100480d88020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8702200441017422062005200620054b1b22064100480d87020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8602200441017422062005200620054b1b22064100480d86020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8502200441017422062005200620054b1b22064100480d85020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8402200441017422062005200620054b1b22064100480d84020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8302200441017422062005200620054b1b22064100480d83020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8202200441017422062005200620054b1b22064100480d82020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8102200441017422062005200620054b1b22064100480d81020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8002200441017422062005200620054b1b22064100480d80020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff01200441017422062005200620054b1b22064100480dff010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe01200441017422062005200620054b1b22064100480dfe010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd01200441017422062005200620054b1b22064100480dfd010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df001200441017422062005200620054b1b22064100480df0010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490def01200441017422062005200620054b1b22064100480def010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dba02200441017422062005200620054b1b22064100480dba020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db902200441017422062005200620054b1b22064100480db9020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db802200441017422062005200620054b1b22064100480db8020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db702200441017422062005200620054b1b22064100480db7020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db602200441017422062005200620054b1b22064100480db6020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db502200441017422062005200620054b1b22064100480db5020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db402200441017422062005200620054b1b22064100480db4020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db302200441017422062005200620054b1b22064100480db3020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db202200441017422062005200620054b1b22064100480db2020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db102200441017422062005200620054b1b22064100480db1020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db002200441017422062005200620054b1b22064100480db0020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daf02200441017422062005200620054b1b22064100480daf020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae02200441017422062005200620054b1b22064100480dae020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad02200441017422062005200620054b1b22064100480dad020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dac02200441017422062005200620054b1b22064100480dac020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dab02200441017422062005200620054b1b22064100480dab020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daa02200441017422062005200620054b1b22064100480daa020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da902200441017422062005200620054b1b22064100480da9020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da802200441017422062005200620054b1b22064100480da8020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da702200441017422062005200620054b1b22064100480da7020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da602200441017422062005200620054b1b22064100480da6020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da502200441017422062005200620054b1b22064100480da5020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da402200441017422062005200620054b1b22064100480da4020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da302200441017422062005200620054b1b22064100480da3020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da202200441017422062005200620054b1b22064100480da2020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da102200441017422062005200620054b1b22064100480da1020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da002200441017422062005200620054b1b22064100480da0020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9f02200441017422062005200620054b1b22064100480d9f020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9e02200441017422062005200620054b1b22064100480d9e020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9d02200441017422062005200620054b1b22064100480d9d020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9c02200441017422062005200620054b1b22064100480d9c020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9b02200441017422062005200620054b1b22064100480d9b020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9a02200441017422062005200620054b1b22064100480d9a020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9902200441017422062005200620054b1b22064100480d99020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9802200441017422062005200620054b1b22064100480d98020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9702200441017422062005200620054b1b22064100480d97020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9602200441017422062005200620054b1b22064100480d96020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9502200441017422062005200620054b1b22064100480d95020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9402200441017422062005200620054b1b22064100480d94020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9302200441017422062005200620054b1b22064100480d93020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9202200441017422062005200620054b1b22064100480d92020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9102200441017422062005200620054b1b22064100480d91020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9002200441017422062005200620054b1b22064100480d90020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f02200441017422062005200620054b1b22064100480d8f020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e02200441017422062005200620054b1b22064100480d8e020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d02200441017422062005200620054b1b22064100480d8d020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c02200441017422062005200620054b1b22064100480d8c020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b02200441017422062005200620054b1b22064100480d8b020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a02200441017422062005200620054b1b22064100480d8a020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8902200441017422062005200620054b1b22064100480d89020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8802200441017422062005200620054b1b22064100480d88020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8702200441017422062005200620054b1b22064100480d87020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8602200441017422062005200620054b1b22064100480d86020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8502200441017422062005200620054b1b22064100480d85020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8402200441017422062005200620054b1b22064100480d84020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8302200441017422062005200620054b1b22064100480d83020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8202200441017422062005200620054b1b22064100480d82020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8102200441017422062005200620054b1b22064100480d81020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8002200441017422062005200620054b1b22064100480d80020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff01200441017422062005200620054b1b22064100480dff010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe01200441017422062005200620054b1b22064100480dfe010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd01200441017422062005200620054b1b22064100480dfd010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df001200441017422062005200620054b1b22064100480df0010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411f3a000020012d00004109470df1010240200141046a280200220228020441ffffffff0371450d002002280200102a200128020421020b2002102a0cf1010b200641011037000b200641011037000b200841011037000b200841011037000b200841011037000b200841011037000b200841011037000b200841011037000b200641011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200641011037000b200a41011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200641011037000b200641011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b1031000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200841011037000b200841011037000b200841011037000b200741011037000b200641011037000b200841011037000b200441011037000b200741011037000b200441011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d002002280200102a200128020421020b2002102a0b200341106a24000bb60301057f2004410c6a2105200441086a2106024002400240034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d04200741017422092008200920084b1b22094100480d040240024020070d002009102821080c010b200428020420072009102c21080b2008450d022004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b024020022003460d002004410c6a2105200441086a2106034020022802002101034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d06200741017422092008200920084b1b22094100480d060240024020070d002009102821080c010b200428020420072009102c21080b2008450d052004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b200241046a22022003470d000b0b2000411f3a00000f0b200941011037000b200941011037000b1031000baf0301067f024002400240024020014107752203200141c00071220472452003417f4720044572460d002002410c6a2105200241086a2106034002400240200628020020052802002204460d00200228020421070c010b200441016a22072004490d05200441017422082007200820074b1b22084100480d050240024020040d002008102821070c010b200228020420042008102c21070b2007450d032002200736020420062008360200200528020021040b2005200441016a360200200720046a200141807f723a0000200341c000712104200321012003410775220721032007200472452007417f4720044572470d000b0b02400240200241086a2802002002410c6a2802002204460d00200228020421030c010b200441016a22032004490d03200441017422072003200720034b1b22074100480d030240024020040d002007102821030c010b200228020420042007102c21030b2003450d0220022003360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200320046a200141ff00713a00002000411f3a00000f0b200841011037000b200741011037000b1031000bb30302017e067f024002400240024020014207872203502001a7220441c00071452205712003427f52200572460d002002410c6a2106200241086a2107034002400240200728020020062802002205460d00200228020421080c010b200541016a22082005490d05200541017422092008200920084b1b22094100480d050240024020050d002009102821080c010b200228020420052009102c21080b2008450d032002200836020420072009360200200628020021050b2006200541016a360200200820056a200441807f723a00002003a72104200342078722012103200150200441c00071452205712001427f52200572470d000b0b02400240200241086a2802002002410c6a2802002205460d00200228020421080c010b200541016a22082005490d03200541017422062008200620084b1b22064100480d030240024020050d002006102821080c010b200228020420052006102c21080b2008450d0220022008360204200241086a20063602002002410c6a28020021050b2002410c6a200541016a360200200820056a200441ff00713a00002000411f3a00000f0b200941011037000b200641011037000b1031000be103010a7f230041306b22022400200241216a220341076a210441002105410021064100210741002108410821090240024002400340200241186a200110ee04024020022802184101470d002000200229021c370204200041013602002000410c6a200241186a410c6a29020037020002402007450d00200921070340024020072d00004109470d000240200741046a220a280200220528020441ffffffff0371450d002005280200102a200a28020021050b2005102a0b200741106a2107200641706a22060d000b0b2008450d042009102a0c040b200220032900003703082002200429000037000f20022d0020210a2002200229000f37001f200220022903083703180240024020072008470d00200741016a220b2007490d032005200b2005200b4b1b220841ffffffff00712008470d032008410474220b4100480d030240024020070d00200b102821090c010b20092006200b102c21090b2009450d010b200920066a220b200a3a0000200b41016a2002290318370000200b41086a200229001f370000200541026a2105200641106a2106200741016a2107200a41ff01714106460d030c010b0b200b41081037000b1031000b20002009360204200041003602002000410c6a2007360200200041086a20083602000b200241306a24000b80b601020b7f017e230041f0006b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d02200320054f0d0120052003103c000b200241013a0048200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1033200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c640b2001280200220620046a2d000021072001410c6a2208200536020002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200741bf014b0d0020070ec001b902b902010203b90200000000000405060708090a00000000000000000b0c000000000d0e0f101100000012131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901b9020b2000410b3a000420004101360200200041056a20073a00000cbc020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da302200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410221070cbf020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1033200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbf020b4102210a410221070cba020b4103210a410221070cb9020b4101210a0b410221070cb7020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da302200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410321070cbe020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1033200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbe020b4102210a410321070cb9020b4103210a410321070cb8020b4101210a0b410321070cb6020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da302200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410421070cbd020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1033200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbd020b4102210a410421070cb8020b4103210a410421070cb7020b4101210a0b410421070cb5020b410621070cb4020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb8020b410721070cb3020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb7020b410821070cb2020b200241d8006a200110ef044104210a200228025822074101460da201200241e0006a280200210b41002106200228025c210c02400240200241e4006a280200220941027422050d00410021040c010b2005410275220441ffffffff03712004470dda01200441027422034100480dda0120031028220a450dd9010b02402009450d00200941027421032005417c6a2106200a2109200c2105034020092005280200360200200941046a2109200541046a21052003417c6a22030d000b200641027641016a21060b0240200b450d00200c102a0b20022d005c4105470db0022007450db00220022802640da3010cb0020b410a21070cb0020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb4020b410b21070caf020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22044f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210720082004360200200741ff00712001411f71742009722109200141076a2101200421052007418001710d000b20014120490d01410d210120074110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb3020b0240024020032004460d00200441016a22012004490ddb01200320014f0d0120012003103c000b200241013a0048200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1033200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000cb3020b200620046a2d0000210520082001360200024020050d00410c21074100210a0caf020b200041163a000420004101360200200041056a20053a00000cb2020b410d21070cad020b410e21070cac020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb0020b410f21070cab020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000caf020b411021070caa020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cae020b411121070ca9020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cad020b411221070ca8020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cac020b411321070ca7020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddd01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000cab020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9c010b20032001460d9a012001417f460dd9012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9b010b200aad210d411421070ca6020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dde01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000caa020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9d010b20032001460d9b012001417f460dda012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9c010b200aad210d411521070ca5020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddf01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca9020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9e010b20032001460d9c012001417f460ddb012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9d010b200aad210d411621070ca4020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de001200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca8020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9f010b20032001460d9d012001417f460ddc012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9e010b200aad210d411721070ca3020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de101200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca7020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca0010b20032001460d9e012001417f460ddd012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9f010b200aad210d411821070ca2020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de201200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca6020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca1010b20032001460d9f012001417f460dde012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da0010b200aad210d411921070ca1020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de301200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca5020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca2010b20032001460da0012001417f460ddf012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da1010b200aad210d411a21070ca0020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de401200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca4020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca3010b20032001460da1012001417f460de0012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da2010b200aad210d411b21070c9f020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de501200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca3020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca4010b20032001460da2012001417f460de1012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da3010b200aad210d411c21070c9e020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de601200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca2020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca5010b20032001460da3012001417f460de2012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da4010b200aad210d411d21070c9d020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de701200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca1020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca6010b20032001460da4012001417f460de3012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da5010b200aad210d411e21070c9c020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de801200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca0020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca7010b20032001460da5012001417f460de4012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da6010b200aad210d411f21070c9b020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de901200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9f020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca8010b20032001460da6012001417f460de5012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b41202107024020054120490d00410d21012004410f4b0da7010b200aad210d0c9a020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dea01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9e020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca9010b20032001460da7012001417f460de6012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da8010b200aad210d412121070c99020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450deb01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9d020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010caa010b20032001460da8012001417f460de7012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da9010b200aad210d412221070c98020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dec01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cab010b20032001460da9012001417f460de8012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0daa010b200aad210d412321070c97020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ded01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9b020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cac010b20032001460daa012001417f460de9012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dab010b200aad210d412421070c96020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dee01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9a020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cad010b20032001460dab012001417f460dea012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dac010b200aad210d412521070c95020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450def01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c99020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cae010b20032001460dac012001417f460deb012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dad010b200aad210d412621070c94020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df001200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c98020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010caf010b20032001460dad012001417f460dec012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dae010b200aad210d412721070c93020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df101200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c97020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb0010b20032001460dae012001417f460ded012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0daf010b200aad210d412821070c92020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df201200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c96020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb1010b20032001460daf012001417f460dee012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0db0010b200aad210d412921070c91020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df301200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c95020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb2010b20032001460db0012001417f460def012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0db1010b200aad210d412a21070c90020b0240024020032005460d00200441026a21012005417f460df001200320014f0d0120012003103c000b200241013a0048200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1033200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c94020b200620056a2d0000210920082001360200024020090d00412b21074100210a0c90020b200041153a000420004101360200200041056a20093a00000c93020b0240024020032005460d00200441026a21012005417f460df001200320014f0d0120012003103c000b200241013a0048200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1033200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c93020b200620056a2d0000210920082001360200024020090d00412c21074100210a0c8f020b200041153a000420004101360200200041056a20093a00000c92020b41002101410021090240024002400340410d210a2001411f4b0d010240024020032005460d002005417f460df4012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a10334105210a0c020b200620056a2c0000210420082007360200200441ff00712001411f71742009722109200141076a21012007210520044100480d000b200441c00071210502402001411f4b0d0020050d020b0240024020014120490d0020050d010b200441ff01714108490d0320014120490d032005450d010c030b20044180017241ff017141f7014b0d020b2000200a36020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c93020b2009417f2001411f71747221090b412d21070c8d020b4200210d4100210102400240024002400340410e21072001413f4b0d010240024020032005460d002005417f460df5012003200541016a22094f0d01200541016a2003103c000b200241013a0008200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241086a360238200241286a200241d8006a10332002290328210d20022802302101410521070c030b200620056a2d0000210420082009360200200441ff0071220aad2001413f71ad86200d84210d200141076a210120092105200441187441187522094100480d000b200941c00071210502402001413f4b0d0020050d030b02400240200141c000490d0020050d010b200141c000490d0420090d010c040b200a41ff00460d030b0b200020073a0004200020022f00183b000520004101360200200041106a2001360200200041086a200d370200200041076a2002411a6a2d00003a00000c92020b200d427f2001413f71ad8684210d0b412e21070c8c020b02400240200320056b4104490d00200441056a21012005417b4b0df001200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320004281808080d000370300200041086a2002290228370200200041106a200241286a41086a2802003602000c90020b200620056a280000210920082001360200412f21070c8b020b02400240200320056b4108490d00200441096a2101200541774b0df001200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a10332002290328210d200041106a2002280230360200200041086a200d37020020004281808080d0003703000c8f020b200620056a290000210d20082001360200413021070c8a020b413121070c89020b413221070c88020b413321070c87020b413421070c86020b413521070c85020b413621070c84020b413721070c83020b413821070c82020b413921070c81020b413a21070c80020b413b21070cff010b413c21070cfe010b413d21070cfd010b413e21070cfc010b413f21070cfb010b41c00021070cfa010b41c10021070cf9010b41c20021070cf8010b41c30021070cf7010b41c40021070cf6010b41c50021070cf5010b41c60021070cf4010b41c70021070cf3010b41c80021070cf2010b41c90021070cf1010b41ca0021070cf0010b41cb0021070cef010b41cc0021070cee010b41cd0021070ced010b41ce0021070cec010b41cf0021070ceb010b41d00021070cea010b41d10021070ce9010b41d20021070ce8010b41d30021070ce7010b41d40021070ce6010b41d50021070ce5010b41d60021070ce4010b41d70021070ce3010b41d80021070ce2010b41d90021070ce1010b41da0021070ce0010b41db0021070cdf010b41dc0021070cde010b41dd0021070cdd010b41de0021070cdc010b41df0021070cdb010b41e00021070cda010b41e10021070cd9010b41e20021070cd8010b41e30021070cd7010b41e40021070cd6010b41e50021070cd5010b41e60021070cd4010b41e70021070cd3010b41e80021070cd2010b41e90021070cd1010b41ea0021070cd0010b41eb0021070ccf010b41ec0021070cce010b41ed0021070ccd010b41ee0021070ccc010b41ef0021070ccb010b41f00021070cca010b41f10021070cc9010b41f20021070cc8010b41f30021070cc7010b41f40021070cc6010b41f50021070cc5010b41f60021070cc4010b41f70021070cc3010b41f80021070cc2010b41f90021070cc1010b41fa0021070cc0010b41fb0021070cbf010b41fc0021070cbe010b41fd0021070cbd010b41fe0021070cbc010b41ff0021070cbb010b41800121070cba010b41810121070cb9010b41820121070cb8010b41830121070cb7010b41840121070cb6010b41850121070cb5010b41860121070cb4010b41870121070cb3010b41880121070cb2010b41890121070cb1010b418a0121070cb0010b418b0121070caf010b418c0121070cae010b418d0121070cad010b418e0121070cac010b418f0121070cab010b41900121070caa010b41910121070ca9010b41920121070ca8010b41930121070ca7010b41940121070ca6010b41950121070ca5010b41960121070ca4010b41970121070ca3010b41980121070ca2010b41990121070ca1010b419a0121070ca0010b419b0121070c9f010b419c0121070c9e010b419d0121070c9d010b419e0121070c9c010b419f0121070c9b010b41a00121070c9a010b41a10121070c99010b41a20121070c98010b41a30121070c97010b41a40121070c96010b41a50121070c95010b41a60121070c94010b41a70121070c93010b41a80121070c92010b41a90121070c91010b41aa0121070c90010b41ab0121070c8f010b200041013602002000200241d8006a41047222012902003702042000410c6a200141086a2902003702000c92010b2002280260102a0c8c010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c8f010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c8d010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c8b010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c89010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c87010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c85010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c83010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c81010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7f0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7d0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7b0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c790b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c770b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c750b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c730b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c710b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6f0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6d0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6b0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c690b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c670b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c650b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c630b417f20051044000b417f20091044000b417f20091044000b417f20091044000b417f200541016a1044000b417f200541016a1044000b200341041037000b1031000b417f200541016a1044000b417f200541016a1044000b417f20011044000b417f200541016a1044000b417f200541016a1044000b417f200541016a1044000b417f200541016a1044000b417f200541016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f20011044000b417f200541016a1044000b417f200541016a1044000b200520011044000b200520011044000b20092003103c000b20092003103c000b20092003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b02400240024002400240024020042006460d0020042006490d01024020060d00024020040d004104210a0c020b200a102a4104210a0c010b200a200441027420064102742209102c220a450d020b4100210941002104034002402009411f4d0d00410f21010c0a0b20012802082207200128020c2205460d08200541016a22032005490d0320072003490d04200128020020056a2d0000210520082003360200200541ff00712009411f71742004722104200941076a21092005418001710d000b20094120490d04410d21012005410f4b0d080c040b41dcfdc5001032000b200941041037000b417f20031044000b20032007103c000b410c10282209450d0120092004360208200920063602042009200a360200410921070b20004100360200200041106a200d3703002000410c6a2009360200200041096a200a3a0000200041086a20073a00000c030b410c41041037000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a280200360200200641ffffffff0371450d00200a102a0b200241f0006a24000bd60703067f017e067f230041d0006b220224004100210341002104024002400240024002400240024002400240024002400240034002402003411f4d0d00410f21030c020b0240024020012802082205200128020c2206460d00200641016a22072006490d05200520074f0d0120072005103c000b200241013a0027200241cc006a41013602002002420137023c200241a4e2c5003602382002412636021c2002200241186a3602482002200241276a360218200241286a200241386a1033410521030c020b200128020020066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b20034120490d01410d210320064110490d010b200241086a41086a200241286a41086a280200220136020020022002290228220837030820002003360204200041086a2008370200200041106a2001360200200041013602000c0a0b20024100360210200242043703082004450d0841042109410021034100210a03402003210b200a220c41016a210a410021034100210503402003411f4b0d04024002402001280208220d200128020c2206460d00200641016a22072006490d05200d20074f0d012007200d103c000b2002200b36020c2002200c360210200241013a0027200241cc006a41013602002002420137023c200241a4e2c5003602382002412636021c2002200241186a3602482002200241276a360218200241286a200241386a103320022802282103200228022c2106200228023021074100210e410521010c090b200128020020066a2d000021062001200736020c200641ff00712003411f71742005722105200341076a21032006418001710d000b024020034120490d002006410f4d0d002002200b36020c2002200c360210410d21010c070b02400240200c200b460d00200b2103200c210b0c010b200b41016a2203200b490d06200b41017422062003200620034b1b220341ffffffff03712003470d06200341027422064100480d0602400240200b0d002006102821090c010b2009200b4102742006102c21090b2009450d05200220093602080b2005410876210e2009200b4102746a2005360200200a2004460d080c000b0b417f20071044000b417f20071044000b2002200b36020c2002200c360210410f21010c020b200641041037000b1031000b0b20004101360200200041106a20073602002000410c6a2006360200200041086a20033602002000200e410874200172360204200b450d022009102a0c020b2002200336020c2002200a3602100b20002002290308370204200041003602002000410c6a200241106a2802003602000b200241d0006a24000bcbd60202097f017e230041106b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df501200441017422082005200820054b1b22084100480df5010240024020040d002008102821050c010b200628020020042008102c21050b2005450dad0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df501200441017422082005200820054b1b22084100480df5010240024020040d002008102821050c010b200628020020042008102c21050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df401200441017422082005200820054b1b22084100480df4010240024020040d002008102821050c010b200628020020042008102c21050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df401200441017422082005200820054b1b22084100480df4010240024020040d002008102821050c010b200628020020042008102c21050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df301200441017422082005200820054b1b22084100480df3010240024020040d002008102821050c010b200628020020042008102c21050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df301200441017422082005200820054b1b22084100480df3010240024020040d002008102821050c010b200628020020042008102c21050b2005450db00120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490df001200441017422072006200720064b1b22074100480df0010240024020040d002007102821060c010b200928020020042007102c21060b2006450db00120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df1012004410174220a2006200a20064b1b220a4100480df1010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490def01200441017422072006200720064b1b22074100480def010240024020040d002007102821060c010b200928020020042007102c21060b2006450db10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df0012004410174220a2006200a20064b1b220a4100480df0010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490dee01200441017422062005200620054b1b22064100480dee010240024020040d002006102821050c010b200928020020042006102c21050b2005450db20120022005360204200241086a20063602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a410e3a0000200320012802042204280204220520042802002204200420054102746a200210ea042003210420032d0000411f470d930320012802042802082105200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490def012004410174220a2006200a20064b1b220a4100480def010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db401200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490ded01200441017422062005200620054b1b22064100480ded010240024020040d002006102821050c010b200228020420042006102c21050b2005450db30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490dec01200441017422072006200720064b1b22074100480dec010240024020040d002007102821060c010b200928020020042007102c21060b2006450db30120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490ded012004410174220a2006200a20064b1b220a4100480ded010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490deb01200441017422072006200720064b1b22074100480deb010240024020040d002007102821060c010b200928020020042007102c21060b2006450db40120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490dec012004410174220a2006200a20064b1b220a4100480dec010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490deb01200441017422062005200620054b1b22064100480deb010240024020040d002006102821050c010b200928020020042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dea01200441017422062005200620054b1b22064100480dea010240024020040d002006102821050c010b200228020420042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490de901200441017422062005200620054b1b22064100480de9010240024020040d002006102821050c010b200228020420042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de801200441017422072006200720064b1b22074100480de8010240024020040d002007102821060c010b200928020020042007102c21060b2006450db60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de9012004410174220a2006200a20064b1b220a4100480de9010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db801200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de701200441017422072006200720064b1b22074100480de7010240024020040d002007102821060c010b200928020020042007102c21060b2006450db70120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de8012004410174220a2006200a20064b1b220a4100480de8010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db901200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de601200441017422072006200720064b1b22074100480de6010240024020040d002007102821060c010b200928020020042007102c21060b2006450db80120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de7012004410174220a2006200a20064b1b220a4100480de7010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dba01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de501200441017422072006200720064b1b22074100480de5010240024020040d002007102821060c010b200928020020042007102c21060b2006450db90120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de6012004410174220a2006200a20064b1b220a4100480de6010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dbb01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de401200441017422072006200720064b1b22074100480de4010240024020040d002007102821060c010b200928020020042007102c21060b2006450dba0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de5012004410174220a2006200a20064b1b220a4100480de5010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dbc01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de301200441017422082007200820074b1b22084100480de3010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de4012004410174220b2007200b20074b1b220b4100480de4010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dbd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de401200441017422092006200920064b1b22094100480de4010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dbe012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de201200441017422082007200820074b1b22084100480de2010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de3012004410174220b2007200b20074b1b220b4100480de3010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dbf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de301200441017422092006200920064b1b22094100480de3010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de101200441017422082007200820074b1b22084100480de1010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de2012004410174220b2007200b20074b1b220b4100480de2010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de201200441017422092006200920064b1b22094100480de2010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de001200441017422082007200820074b1b22084100480de0010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de1012004410174220b2007200b20074b1b220b4100480de1010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de101200441017422092006200920064b1b22094100480de1010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddf01200441017422082007200820074b1b22084100480ddf010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de0012004410174220b2007200b20074b1b220b4100480de0010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de001200441017422092006200920064b1b22094100480de0010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dde01200441017422082007200820074b1b22084100480dde010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddf012004410174220b2007200b20074b1b220b4100480ddf010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddf01200441017422092006200920064b1b22094100480ddf010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc8012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c93010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddd01200441017422082007200820074b1b22084100480ddd010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc70120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dde012004410174220b2007200b20074b1b220b4100480dde010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dde01200441017422092006200920064b1b22094100480dde010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dca012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddc01200441017422082007200820074b1b22084100480ddc010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc90120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddd012004410174220b2007200b20074b1b220b4100480ddd010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcb01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddd01200441017422092006200920064b1b22094100480ddd010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dcc012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddb01200441017422082007200820074b1b22084100480ddb010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddc012004410174220b2007200b20074b1b220b4100480ddc010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddc01200441017422092006200920064b1b22094100480ddc010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dce012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dda01200441017422082007200820074b1b22084100480dda010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddb012004410174220b2007200b20074b1b220b4100480ddb010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddb01200441017422092006200920064b1b22094100480ddb010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8f010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd901200441017422082007200820074b1b22084100480dd9010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dda012004410174220b2007200b20074b1b220b4100480dda010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dda01200441017422092006200920064b1b22094100480dda010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd801200441017422082007200820074b1b22084100480dd8010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd9012004410174220b2007200b20074b1b220b4100480dd9010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd901200441017422092006200920064b1b22094100480dd9010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd701200441017422082007200820074b1b22084100480dd7010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd8012004410174220b2007200b20074b1b220b4100480dd8010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd801200441017422092006200920064b1b22094100480dd8010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd601200441017422082007200820074b1b22084100480dd6010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da3022004410174220b2007200b20074b1b220b4100480da3020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da302200441017422092006200920064b1b22094100480da3020240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da102200441017422082007200820074b1b22084100480da1020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da2022004410174220b2007200b20074b1b220b4100480da2020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dda01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da202200441017422092006200920064b1b22094100480da2020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da002200441017422082007200820074b1b22084100480da0020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dda0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da1022004410174220b2007200b20074b1b220b4100480da1020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450ddc01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da102200441017422092006200920064b1b22094100480da1020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddd012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9f02200441017422082007200820074b1b22084100480d9f020240024020040d002008102821070c010b200a28020020042008102c21070b2007450ddc0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da0022004410174220b2007200b20074b1b220b4100480da0020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dde01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da002200441017422092006200920064b1b22094100480da0020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddf012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9e02200441017422082007200820074b1b22084100480d9e020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dde0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9f022004410174220b2007200b20074b1b220b4100480d9f020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9f02200441017422092006200920064b1b22094100480d9f020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de1012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c87010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9d02200441017422082007200820074b1b22084100480d9d020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de00120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9e022004410174220b2007200b20074b1b220b4100480d9e020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9e02200441017422092006200920064b1b22094100480d9e020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de3012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9c02200441017422082007200820074b1b22084100480d9c020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de20120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9d022004410174220b2007200b20074b1b220b4100480d9d020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9d02200441017422092006200920064b1b22094100480d9d020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de5012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9b02200441017422082007200820074b1b22084100480d9b020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de40120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9c022004410174220b2007200b20074b1b220b4100480d9c020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9c02200441017422092005200920054b1b22094100480d9c020240024020040d002009102821050c010b200a28020020042009102c21050b2005450de7012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a02200441017422082007200820074b1b22084100480d9a020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de60120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b022004410174220b2007200b20074b1b220b4100480d9b020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b02200441017422092006200920064b1b22094100480d9b020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9902200441017422082007200820074b1b22084100480d99020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a022004410174220b2007200b20074b1b220b4100480d9a020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dea01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a02200441017422092006200920064b1b22094100480d9a020240024020040d002009102821060c010b200a28020020042009102c21060b2006450deb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9802200441017422082005200820054b1b22084100480d98020240024020040d002008102821050c010b200628020020042008102c21050b2005450dea0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d9802200441017422082005200820054b1b22084100480d98020240024020040d002008102821050c010b200628020020042008102c21050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9702200441017422082005200820054b1b22084100480d97020240024020040d002008102821050c010b200628020020042008102c21050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d9702200441017422082005200820054b1b22084100480d97020240024020040d002008102821050c010b200628020020042008102c21050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9602200441017422072005200720054b1b22074100480d96020240024020040d002007102821050c010b200228020420042007102c21050b2005450dec0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a000020032006200210eb042003210420032d0000411f470def020c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9502200441017422062005200620054b1b22064100480d95020240024020040d002006102821050c010b200228020420042006102c21050b2005450dec0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c200210ec042003210420032d0000411f470dee020c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9402200441017422082005200820054b1b22084100480d94020240024020040d002008102821050c010b200628020020042008102c21050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d9402200541017422042008200420084b1b22044100480d94020240024020050d002004102821050c010b200628020020052004102c21050b2005450ded0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9302200441017422072005200720054b1b22074100480d93020240024020040d002007102821050c010b200628020020042007102c21050b2005450ded0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d9302200541017422042007200420074b1b22044100480d93020240024020050d002004102821050c010b200628020020052004102c21050b2005450dee0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9202200441017422062005200620054b1b22064100480d92020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9102200441017422062005200620054b1b22064100480d91020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9002200441017422062005200620054b1b22064100480d90020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f02200441017422062005200620054b1b22064100480d8f020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e02200441017422062005200620054b1b22064100480d8e020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d02200441017422062005200620054b1b22064100480d8d020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c02200441017422062005200620054b1b22064100480d8c020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b02200441017422062005200620054b1b22064100480d8b020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a02200441017422062005200620054b1b22064100480d8a020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8902200441017422062005200620054b1b22064100480d89020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8802200441017422062005200620054b1b22064100480d88020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8702200441017422062005200620054b1b22064100480d87020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8602200441017422062005200620054b1b22064100480d86020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8502200441017422062005200620054b1b22064100480d85020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8402200441017422062005200620054b1b22064100480d84020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8302200441017422062005200620054b1b22064100480d83020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8202200441017422062005200620054b1b22064100480d82020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8102200441017422062005200620054b1b22064100480d81020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8002200441017422062005200620054b1b22064100480d80020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff01200441017422062005200620054b1b22064100480dff010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe01200441017422062005200620054b1b22064100480dfe010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd01200441017422062005200620054b1b22064100480dfd010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df001200441017422062005200620054b1b22064100480df0010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490def01200441017422062005200620054b1b22064100480def010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dba02200441017422062005200620054b1b22064100480dba020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db902200441017422062005200620054b1b22064100480db9020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db802200441017422062005200620054b1b22064100480db8020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db702200441017422062005200620054b1b22064100480db7020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db602200441017422062005200620054b1b22064100480db6020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db502200441017422062005200620054b1b22064100480db5020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db402200441017422062005200620054b1b22064100480db4020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db302200441017422062005200620054b1b22064100480db3020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db202200441017422062005200620054b1b22064100480db2020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db102200441017422062005200620054b1b22064100480db1020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db002200441017422062005200620054b1b22064100480db0020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daf02200441017422062005200620054b1b22064100480daf020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae02200441017422062005200620054b1b22064100480dae020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad02200441017422062005200620054b1b22064100480dad020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dac02200441017422062005200620054b1b22064100480dac020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dab02200441017422062005200620054b1b22064100480dab020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daa02200441017422062005200620054b1b22064100480daa020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da902200441017422062005200620054b1b22064100480da9020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da802200441017422062005200620054b1b22064100480da8020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da702200441017422062005200620054b1b22064100480da7020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da602200441017422062005200620054b1b22064100480da6020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da502200441017422062005200620054b1b22064100480da5020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da402200441017422062005200620054b1b22064100480da4020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da302200441017422062005200620054b1b22064100480da3020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da202200441017422062005200620054b1b22064100480da2020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da102200441017422062005200620054b1b22064100480da1020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da002200441017422062005200620054b1b22064100480da0020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9f02200441017422062005200620054b1b22064100480d9f020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9e02200441017422062005200620054b1b22064100480d9e020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9d02200441017422062005200620054b1b22064100480d9d020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9c02200441017422062005200620054b1b22064100480d9c020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9b02200441017422062005200620054b1b22064100480d9b020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9a02200441017422062005200620054b1b22064100480d9a020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9902200441017422062005200620054b1b22064100480d99020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9802200441017422062005200620054b1b22064100480d98020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9702200441017422062005200620054b1b22064100480d97020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9602200441017422062005200620054b1b22064100480d96020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9502200441017422062005200620054b1b22064100480d95020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9402200441017422062005200620054b1b22064100480d94020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9302200441017422062005200620054b1b22064100480d93020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9202200441017422062005200620054b1b22064100480d92020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9102200441017422062005200620054b1b22064100480d91020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9002200441017422062005200620054b1b22064100480d90020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f02200441017422062005200620054b1b22064100480d8f020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e02200441017422062005200620054b1b22064100480d8e020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d02200441017422062005200620054b1b22064100480d8d020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c02200441017422062005200620054b1b22064100480d8c020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b02200441017422062005200620054b1b22064100480d8b020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a02200441017422062005200620054b1b22064100480d8a020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8902200441017422062005200620054b1b22064100480d89020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8802200441017422062005200620054b1b22064100480d88020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8702200441017422062005200620054b1b22064100480d87020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8602200441017422062005200620054b1b22064100480d86020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8502200441017422062005200620054b1b22064100480d85020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8402200441017422062005200620054b1b22064100480d84020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8302200441017422062005200620054b1b22064100480d83020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8202200441017422062005200620054b1b22064100480d82020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8102200441017422062005200620054b1b22064100480d81020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8002200441017422062005200620054b1b22064100480d80020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff01200441017422062005200620054b1b22064100480dff010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe01200441017422062005200620054b1b22064100480dfe010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd01200441017422062005200620054b1b22064100480dfd010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df001200441017422062005200620054b1b22064100480df0010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411f3a000020012d00004109470df1010240200141046a280200220228020441ffffffff0371450d002002280200102a200128020421020b2002102a0cf1010b200641011037000b200641011037000b200841011037000b200841011037000b200841011037000b200841011037000b200841011037000b200841011037000b200641011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200641011037000b200a41011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200641011037000b200641011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b1031000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200841011037000b200841011037000b200841011037000b200741011037000b200641011037000b200841011037000b200441011037000b200741011037000b200441011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d002002280200102a200128020421020b2002102a0b200341106a24000bfb07030e7f017e017f200241086a2103200241046a210420012802002205210602400240024002400240034002400240200428020020032802002207460d00200228020021080c010b200741016a22082007490d02200741017422092008200920084b1b22094100480d020240024020070d002009102821080c010b200228020020072009102c21080b2008450d032002200836020020042009360200200328020021070b2003200741016a360200200820076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b2001280204220a2001410c6a2802002206410c6c6a210b200141086a280200210c200a21072006450d03200a21072005450d03200b41746a210d200241086a210841002107200a210e02400340200e2103024003402003280200220f0d01200741016a2107200b2003410c6a2203470d000c080b0b2003410c6a210e200741016a21102005417f6a2105200341046a290200211102400240034002400240200241046a220428020020082802002206460d00200228020021090c010b200641016a22092006490d06200641017422012009200120094b1b22014100480d060240024020060d002001102821090c010b200228020020062001102c21090b2009450d022002200936020020042001360200200828020021060b2008200641016a360200200920066a200741807f72200741ff0071200741077622061b3a0000200621072006450d020c000b0b200141011037000b2011422088a7221221060240034002400240200428020020082802002207460d00200228020021090c010b200741016a22092007490d05200741017422012009200120094b1b22014100480d050240024020070d002001102821090c010b200228020020072001102c21090b2009450d022002200936020020042001360200200828020021070b2008200741016a360200200920076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b0240024020042802002206200828020022076b2012490d00200228020021060c010b200720126a22092007490d04200641017422072009200720094b1b22074100480d040240024020060d002007102821060c010b200228020020062007102c21060b2006450d032002200636020020042007360200200828020021070b2008200720126a360200200620076a200f2012109a051a02402011a7450d00200f102a0b200d2003460d052010210720050d010c050b0b200141011037000b200741011037000b1031000b200941011037000b2003410c6a21070b2007200b460d000340024020072802002206450d00200741046a280200450d002006102a0b2007410c6a2207200b470d000b0b0240200c450d00200a102a0b2000411f3a00000bcb0401067f200441046a2105024002400240024002400240200441086a2802002004410c6a2802002206460d00200528020021070c010b200641016a22072006490d04200641017422082007200820074b1b22084100480d040240024020060d002008102821070c010b200528020020062008102c21070b2007450d0120042007360204200441086a20083602002004410c6a28020021060b2004410c6a2208200641016a360200200720066a20024101463a0000200441086a2109034002400240200928020020082802002206460d00200528020021070c010b200641016a22072006490d052006410174220a2007200a20074b1b220a4100480d050240024020060d00200a102821070c010b20052802002006200a102c21070b2007450d03200420073602042009200a360200200828020021060b2008200641016a360200200720066a200141807f72200141ff0071200141077622061b3a00002006210120060d000b024020024101470d002004410c6a2107200441086a2108034002400240200828020020072802002206460d00200528020021010c010b200641016a22012006490d06200641017422092001200920014b1b22094100480d060240024020060d002009102821010c010b200528020020062009102c21010b2001450d052004200136020420082009360200200728020021060b2007200641016a360200200120066a200341807f72200341ff0071200341077622061b3a00002006210320060d000b0b2000411f3a00000f0b200841011037000b200a41011037000b200941011037000b1031000bb007010a7f230041d0006b2202240002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d02200320054f0d0120052003103c000b200241013a001f200241cc006a41013602002002420137023c200241a4e2c500360238200241263602342002200241306a36024820022002411f6a360230200241206a200241386a10332002411b6a200241286a28020036000020022002290320370013200220022900103703002002200241176a290000370007200041053a0004200020022903003700052000410c6a2002290007370000200041013602000c040b2001280200220620046a2d000021072001200536020c024020074102490d00200041173a000420004101360200200041056a20073a00000c040b410120036b2108200441026a2104410021054100210902400240034002402005411f4d0d00410f21050c020b02400240200820046a4102460d002004450d06200320044f0d0120042003103c000b200241013a0000200241cc006a41013602002002420137023c200241a4e2c500360238200241263602342002200241306a36024820022002360230200241106a200241386a1033410521050c020b200620046a417f6a2d0000210a2001200436020c200a41ff00712005411f71742009722109200441016a2104200541076a2105200a418001710d000b20054120490d01410d2105200a4110490d010b2000200536020420004101360200200041086a2002290210370200200041106a200241106a41086a2802003602000c040b4100210502402007410171450d002004417f6a2104410021054100210b02400240034002402005411f4d0d00410f21040c020b0240024020032004460d002004417f460d082003200441016a22084f0d01200441016a2003103c000b200241013a0000200241cc006a41013602002002420137023c200241a4e2c500360238200241263602342002200241306a36024820022002360230200241106a200241386a1033410521040c020b200620046a2d0000210a2001200836020c200a41ff00712005411f7174200b72210b200541076a210520082104200a418001710d000b20054120490d01410d2104200a4110490d010b2000200436020420004101360200200041086a2002290210370200200041106a200241106a41086a2802003602000c050b410121050b20002009360204200041003602002000410c6a200b360200200041086a20053602000c030b417f20051044000b417f20041044000b417f200441016a1044000b200241d0006a24000bee0201067f230041c0006b2202240041002103410021040240024003400240024002402003411f4b0d002001280204220520012802082206460d01200641016a22072006490d04200520074f0d0220072005103c000b200041013602002000410f3a00040c040b200241013a000f200241346a410136020020024201370224200241a4e2c5003602202002412636023c2002200241386a36023020022002410f6a360238200241106a200241206a10332002410b6a200241186a28020036000020022002290310370003200041053a0004200020022900003700052000410c6a200241076a290000370000200041013602000c030b200128020020066a2d0000210620012007360208200641ff00712003411f71742004722104200341076a21032006418001710d000b0240024020034120490d002006410f4b0d010b20004100360200200020043602040c020b200041013602002000410d3a00040c010b417f20071044000b200241c0006a24000bd806010a7f20012802042103200128020021044100210541002106410021074101210820012802082209210a02400240024002400340024020062007470d002005200641016a220b2005200b4b1b22074100480d050240024020060d002007102821080c010b200820062007102c21080b2008450d020b200820066a200a41807f72200a41ff0071200a410776220b1b3a0000200541026a2105200641016a2106200b210a200b0d000b0240200720066b20094f0d00200620096a220a2006490d0420074101742205200a2005200a4b1b220a4100480d040240024020070d00200a102821080c010b20082007200a102c21080b2008450d02200a21070b200820066a20042009109a051a02402003450d002004102a0b200128020c210c0240200720096b20066b200141146a280200220a490d002009200a6a20066a21030c030b200920066a2205200a6a22032005490d03200741017422052003200520034b1b22054100480d030240024020070d002005102821080c010b200820072005102c21080b02402008450d00200521070c030b200541011037000b200741011037000b200a41011037000b200820096a20066a200c200a109a051a200241086a210b200241046a21092003210a024002400340024002402009280200200b2802002206460d00200228020021050c010b200641016a22052006490d04200641017422042005200420054b1b22044100480d040240024020060d002004102821050c010b200228020020062004102c21050b2005450d022002200536020020092004360200200b28020021060b200b200641016a360200200520066a200a41807f72200a41ff0071200a41077622061b3a00002006210a20060d000b02400240200241046a280200220a200241086a28020022066b2003490d002002280200210a0c010b200620036a22052006490d03200a41017422062005200620054b1b22064100480d0302400240200a0d0020061028210a0c010b2002280200200a2006102c210a0b200a450d022002200a360200200241046a2006360200200241086a28020021060b200241086a200620036a360200200a20066a20082003109a051a02402007450d002008102a0b2000411f3a00000240200141106a280200450d00200c102a0b0f0b200441011037000b200641011037000b1031000bf20103027f017e057f024020002802082201200028020c460d00034020002001411c6a36020820012802102202450d01200141146a2902002103024020012802042204450d00200141086a280200210502402001410c6a2802002201450d0020014104742106200421010340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102a200728020021080b2008102a0b200141106a2101200641706a22060d000b0b2005450d002004102a0b02402003a7450d002002102a0b20002802082201200028020c470d000b0b02402000280204450d002000280200102a0b0be50101067f024020002802082201200028020c460d0003402000200141186a36020820012802002202450d01200141146a2802002103200141106a2802002104200128020c210502402001280204450d002002102a0b02402003450d0020034104742103200521010340024020012d00004109470d000240200141046a2206280200220228020441ffffffff0371450d002002280200102a200628020021020b2002102a0b200141106a2101200341706a22030d000b0b02402004450d002005102a0b20002802082201200028020c470d000b0b02402000280204450d002000280200102a0b0bf20103027f017e057f024020002802082201200028020c460d00034020002001411c6a36020820012802102202450d01200141146a2902002103024020012802042204450d00200141086a280200210502402001410c6a2802002201450d0020014104742106200421010340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102a200728020021080b2008102a0b200141106a2101200641706a22060d000b0b2005450d002004102a0b02402003a7450d002002102a0b20002802082201200028020c470d000b0b02402000280204450d002000280200102a0b0bce0101057f024020002802082201450d00200028020022022001411c6c6a21030340024020022802042200450d0002402002410c6a2802002201450d00200141047421010340024020002d00004109470d000240200041046a2204280200220528020441ffffffff0371450d002005280200102a200428020021050b2005102a0b200041106a2100200141706a22010d000b0b200241086a280200450d002002280204102a0b2002411c6a21000240200241146a280200450d002002280210102a0b2000210220002003470d000b0b0b90d20106067f017e057f017e117f027e2300419081046b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280204220320012802082204460d00200441016a22052004490d02200320054f0d0120052003103c000b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022802f88004210420022802fc8004210120004101360200200041003a00042001450d2b2004102a0c2b0b200128020020046a2d00002104200120053602082004410c4b0d03024002400240024020040e0d0001161514131211060d0c0b05000b200241e8006a200110f40441012106200228026c2107024020022802684101470d0020074108762101200241f8006a2802002104200241e8006a41086a29030021080c270b41002109200241e8006a4100418080011099051a410021034100210a2007450d20410021054100210a410121064100210b0340024002402001280204220c200128020822036b2007200b6b220441808001200441808001491b2204490d00200320046a220d2003490d05200c200d4f0d01200d200c103c000b200241013a00e880042002418c81046a4101360200200242013702fc8004200241a4e2c5003602f880042002412636021c2002200241186a36028881042002200241e880046a360218200241306a200241f880046a10332002290330210820022802382104410521070240200a450d002006102a0b0c280b200241e8006a200128020020036a2004109a051a2001200d36020802400240200a20056b2004490d00200520046a21030c010b200520046a22032005490d23200a410174220d2003200d20034b1b220d4100480d2302400240200a0d00200d102821060c010b2006200a200d102c21060b2006450d03200d210a0b200620056a200241e8006a2004109a051a2003210520072004200b6a220b4b0d000c210b0b200241e8006a200110fb04024020022802684101470d00200228026c22044108762105200241e8006a41086a2903002208422088210e200241f8006a28020021030c1f0b200241fc006a280200210f200241f8006a2802002101200241f4006a2802002103200241f0006a2802002110200228026c210b4100210441002109024002400240034002402004411f4d0d00410f21040c020b0240024020032001460d002001417f460d052003200141016a22054f0d01200141016a2003103c000b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241c8006a200241e8006a1033410521040c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b20044120490d01410d210420064110490d010b200241f880046a41086a200241c8006a41086a28020022033602002002200229034822083703f880042008422088a721092008a721060c1f0b200241003602602002420437035802400240024020090d00410421010c010b410020036b2111200b41026a2112410120036b21134100210a410421014100211441002115410021160340201621170240024020032005460d000240200541016a22042005490d000240024020032004490d000240200b20056a2d0000220441e000460d00411821050c250b201741016a211641022118200541026a210441002106410321192012211a4100211b024002400340201a21072019210c2018210d02402006411f4d0d00410f21050c020b02400240201320046a4102460d002004450d06200320044f0d0120042003103c000b200241013a00302002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f88004370320410521050c020b200b20046a417f6a2d0000221c41ff00712006411f7174201b72211b200d41016a2118200c41016a2119200741016a211a200441016a2104200641076a2106201c418001710d000b20064120490d01201c4110490d01410d21050b200241e880046a41086a200241206a41086a28020022033602002002200229032022083703e880042008a721064100210420022802ec800421090c240b41002118200241003602382002420137033002400240201b0d002004417f6a21064101211c4100211a4100211d0c010b201120056a211e410021194101211c4100211a034002400240024002400240201e200d6a450d002005200c6a2204450d02200320044f0d0120042003103c000b200220193602342002201a3602382002201c360230200241013a00e880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022802f88004210620022802fc80042109200228028081042103410521050c280b200720056a2c000022044100480d0102400240200441c00071450d00200441807f72220441ff017141fb014b0d010b200220193602342002201a3602382002201c360230410621050c270b0240201a2019460d002019211d201a21060c030b201941016a22062019490d2e2019410174221d2006201d20064b1b221d4100480d2e0240024020190d00201d1028211c0c010b201c2019201d102c211c0b0240201c450d0020192106201d21190c030b201d41011037000b417f20041044000b200220193602342002201a3602382002201c360230411921050c240b201c20066a2004417f733a0000200d41016a210d200c41016a210c200741016a2107201b201a41016a221a470d000b2002201d3602342002201a3602382002201c3602302005200d6a21060b201c411076411074221b201c41087641ff0171410874221972201c41ff0171221c72210c4100210d024003404100210402402018411f4d0d00410f21050c230b0240024020032006460d002006417f460d032003200641016a22054f0d01200641016a2003103c000b200241013a00302002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050c230b200b20066a2d0000220741ff00712018411f7174200d72210d201841076a2118200521062007418001710d000b20184120490d052007410f4d0d05410d21050c210b417f200641016a1044000b20042003103c000b417f20041044000b417f20041044000b200241013a00302002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050c200b0240200d41014d0d004104210541e885c6002106412421090c1b0b024002400240200d0e020001000b410421060c010b20032005460d1a024002400240200541016a220d2005490d002003200d490d010240200b20056a2c0000220441004e0d00411921050c200b41062105200441c00071450d02200441807f72220441ff017141fb014d0d022004417f732106200d21050c030b417f200541016a1044000b200541016a2003103c000b0c1c0b024020172015470d00024020142015460d00201421150c010b201441016a22042014490d252014410174220d2004200d20044b1b221541ffffffff00712015470d25201541047422044100480d250240024020140d002004102821010c010b200120144104742004102c21010b2001450d032002201536025c20022001360258201521140b200120174104746a2204201f4180807c71200641ff01714108747241e00072221f36020c2004201a3602082004201d36020420042019201c72201b72360200200a41106a210a2002201636026020162009470d000b0b2005200f462104200229025c2208422088210e02402010450d00200b102a0b200ea721052008a721092004450d1e2005ad4220862009ad842108410221030c2a0b200441041037000b417f200141016a1044000b200d41011037000b2003200d1044000b417f20051044000b200241e8006a200110fb04024020022802684101470d00200041013602002000200241e8006a41047222012902003702042000410c6a200141086a2902003702000c290b200241fc006a280200210d200241f8006a2802002104200241f4006a2802002105200241f0006a280200210a200228026c210b410021034100210102400240034002402003411f4d0d00410f21040c080b20052004460d062004417f460d012005200441016a2206490d02200b20046a2d0000220941ff00712003411f71742001722101200341076a2103200621042009418001710d000b20034120490d04410d21042009410f4b0d060c040b417f200441016a1044000b200441016a2005103c000b200241e8006a200110fb04024020022802684101470d00200041013602002000200241e8006a41047222012902003702042000410c6a200141086a2902003702000c280b200241fc006a280200210d200241f8006a2802002104200241f4006a2802002105200241f0006a280200210a200228026c210b410021034100210102400240034002402003411f4d0d00410f21040c0d0b20052004460d0b2004417f460d012005200441016a2206490d02200b20046a2d0000220941ff00712003411f71742001722101200341076a2103200621042009418001710d000b20034120490d09410d21042009410f4b0d0b0c090b417f200441016a1044000b200441016a2005103c000b200041123a000420004101360200200041056a20043a00000c260b200d20064621040240200a450d00200b102a0b02402004450d00410b21030c220b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a10332002418381046a200241386a280200360000200220022903303700fb8004200041053a0004200020022900f880043700052000410c6a200241ff80046a290000370000200041013602000c250b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1033410521040b2000200436020420004101360200200041086a20022902f88004370200200041106a200241f880046a41086a280200360200200a450d23200b102a0c230b200241e8006a200110fb040240024020022802684101470d00200228026c22014108762106200241e8006a41086a2903002208422088210e200241f8006a280200210b0c010b200241c0006a200241fc006a280200360200200241386a200241f4006a2902003703002002200229026c37033041002101410021050240024002400240024002400240034002402001411f4d0d00410f210d0c020b0240024020022802382209200228023c2204460d00200441016a22032004490d05200920034f0d0120032009103c000b200241013a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241c8006a200241e8006a10334105210d0c020b200228023020046a2d000021042002200336023c200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210d20044110490d010b200241f880046a41086a200241c8006a41086a280200220b3602002002200229034822083703f880042008422088a721072008a7210c410021060c040b200241003602502002420437034802400240024020050d00410421010c010b4100210d0340200d41016a210d41002101410021090240024002400240024002400240034002402001411f4d0d00410f210d0c030b20022802382206200228023c2204460d01200441016a22032004490d0420062003490d06200228023020046a2d000021042002200336023c200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d022004410f4d0d02410d210d0c010b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241f880046a200241e8006a1033200241e880046a41086a200241f880046a41086a280200360200200220022903f8800422083703e880042008a7210c4105210d0b20022802f08004210b20022802ec80042107410021060c0a0b200241e8006a200241306a10ed04024020022802684101470d00200228026c220d41087621062002280278210b200228027421072002280270210c0c0a0b200228027421192002280270211c200228026c211a410021044100210b02400240034002402004411f4d0d00410f210d0c020b0240024020022802382206200228023c2203460d00200341016a22012003490d06200620014f0d0120012006103c000b200241013a00e880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f8800422083703202008a7210c4105210d0c030b2002280230220a20036a2d000021032002200136023c200341ff00712004411f7174200b72210b200441076a21042003418001710d000b20044120490d0520034110490d05410d210d0b0b2002280228210b200228022421070c080b417f20031044000b417f20011044000b20032006103c000b4100211b200241e8006a4100418080041099051a02400240200b0d00410121184100210c0c010b4100211b41012118410021034100210702400240034002400240200620016b200b20076b220441808004200441808004491b2204490d00200120046a220c2001490d032006200c4f0d01200c2006103c000b200241013a00202002410136028c8104200242013702fc8004200241a4e2c5003602f880042002412636021c2002200241186a36028881042002200241206a360218200241e880046a200241f880046a103320022802e88004210c20022802ec8004210720022802f08004210b4105210d201b450d092018102a0c090b200241e8006a200a20016a2004109a051a2002200c36023c02400240201b20036b2004490d00200320046a210c0c010b200320046a220c2003490d24201b4101742201200c2001200c4b1b22014100480d2402400240201b0d002001102821180c010b2018201b2001102c21180b2018450d032001211b0b201820036a200241e8006a2004109a051a200b200420076a22074d0d03200228023c2101200228023821062002280230210a200c21030c000b0b2001200c1044000b200141011037000b024020022802502203200228024c470d00200341016a22012003490d20200341017422042001200420014b1b2204ad421c7e2208422088a70d202008a722064100480d200240024020030d002006102821010c010b20022802482003411c6c2006102c21010b2001450d032002200436024c200220013602480b200228024822012003411c6c6a2204200941087622063b0001200420183602102004201a360204200420093a0000200441036a20064110763a0000200441186a200c360200200441146a201b3602002004410c6a2019360200200441086a201c3602002002200341016a360250200d2005470d000b0b200228023c2002280240462104200229024c2208422088210e02402002280234450d002002280230102a0b20014108762105200ea721032008a7210a2004450d052005410874200141ff01717221012003ad422086200aad842108410d21030c250b200641041037000b417f20031044000b02402019450d0020194104742104201a21010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b41002106201c450d00201a102a0b2002280248211b024020022802502201450d00201b2001411c6c6a210a201b21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102a0b2009411c6a21010240200941146a280200450d002009280210102a0b200121092001200a470d000b0b200228024c450d00201b102a0b2006410874200d41ff01717221012007ad220e422086200cad8421082002280234450d012002280230102a0c010b2005410874200141ff017172210d20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022903f88004210820022802808104210b02402003450d00200d2003411c6c6a2106200d21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102a0b2009411c6a21010240200941146a280200450d002009280210102a0b2001210920012006470d000b0b2008422088210e4105210141002106200a450d00200d102a0b20004101360200200041106a200b360200200041086a200e422086200842ffffffff0f838437020020002006410874200141ff0171723602040c220b200241e8006a200110fb040240024020022802684101470d00200228026c220a4108762104200241e8006a41086a2903002208422088210e200241f8006a280200210d0c010b200241fc006a280200211b200241f8006a2802002101200241f4006a2802002105200241f0006a2802002107200228026c210b410021044100210902400240024002400240024002400240024002400240034002402004411f4d0d00410f210a0c020b0240024020052001460d002001417f460d052005200141016a22034f0d01200141016a2005103c000b200241013a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a10334105210a0c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200321012006418001710d000b20044120490d01410d210a20064110490d010b200241306a41086a200241f880046a41086a280200220d360200200220022902f8800422083703302008422088a7210c2008a7211b0c080b2002410036026020024204370358024002400240024020090d00410421010c010b200241f1006a21104100211c0340201c41016a211c410021014100210602400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f210a0c020b0240024020052003460d002003417f460d062005200341016a22044f0d01200341016a2005103c000b200241013a00f880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241f880046a360218200241c8006a200241e8006a10334105210a2002280248211b0c030b200b20036a2d0000220a41ff00712001411f71742006722106200141076a210120042103200a418001710d000b20014120490d02200a4110490d02410d210a0b0b2002280250210d200228024c210c0c160b4100210c200241e8006a4100418080011099051a410121180240024020060d00200421034100211a4100210a0c010b4100210d4100211a41002119034002400240200520046b200620196b220141808001200141808001491b2201490d00200420016a22032004490d05200520034f0d0120032005103c000b200241013a00482002410136028c8104200242013702fc8004200241a4e2c5003602f880042002412636021c2002200241186a36028881042002200241c8006a360218200241e880046a200241f880046a103320022802e88004211b20022802ec8004210c20022802f08004210d4105210a201a450d182018102a0c180b200241e8006a200b20046a2001109a051a02400240201a200d6b2001490d00200d20016a210a0c010b200d20016a220a200d490d31201a4101742204200a2004200a4b1b22044100480d3102400240201a0d002004102821180c010b2018201a2004102c21180b2018450d052004211a0b2018200d6a200241e8006a2001109a051a20032104200a210d2006200120196a22194b0d000b0b2002200a3602402002410036023c2002200a3602382002201aad4220862018ad84370330410021014100210d02400240034002402001411f4d0d00410f210a0c020b02400240200a200c460d00200c417f460d08200a200c41016a22064f0d01200c41016a200a103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f880043703204105210a0c020b2018200c6a2d000021042002200636023c200441ff00712001411f7174200d72210d200141076a21012006210c2004418001710d000b20014120490d0120044110490d01410d210a0b200241e880046a41086a200241206a41086a280200220d3602002002200229032022083703e880042008a7211b20022802ec8004210c0c150b41002119200241003602f08004200242043703e8800402400240200d0d004104210f41002118410021160c010b410021184104210f410021160340201821172016221d41016a2116410021014100210c024002400240034002402001411f4d0d00410f21040c020b0240024020022802382218200228023c2204460d00200441016a22062004490d0c201820064f0d0120062018103c000b200241013a00f880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241f880046a360218200241c8006a200241e8006a1033410521042002280248211b0c030b2002280230221a20046a2d0000210a2002200636023c200a41ff00712001411f7174200c72210c200141076a2101200a418001710d000b20014120490d02200a4110490d02410d21040b0b2002280250210d200228024c210c410021010c0c0b02400240024020182006460d00200441026a21042006417f460d0a20182004490d0c201a20066a2c000021012002200436023c0240200141004e0d00411921040c0f0b41062104200141c00071450d0d200141807f72220141ff017141fb014d0d0d201d2017460d0120172118201d21170c020b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241f880046a200241e8006a103320022802f88004211b20022802fc8004210c20022802808104210d410521040c0d0b201741016a22042017490d31201741017422062004200620044b1b221841ffffffff01712018470d31201841037422044100480d310240024020170d0020041028210f0c010b200f20174103742004102c210f0b200f450d092002200f3602e880040b200f20174103746a2204201341807e712001417f7341ff01717222133a00042004200c3602002016200d470d000b200220183602ec8004200220163602f080040b200f20164103746a210d200f2101200f210602400340200d20066b41184d0d01201920012802006a22042019490d132004200141086a2802006a22062004490d132006200141106a2802006a22042006490d13200141186a210a200141206a220621012004200a2802006a22192004490d130c000b0b0340200d2001460d0b201920012802006a22042019492106200141086a21012004211920060d120c000b0b417f200341016a1044000b200420031044000b200441011037000b417f200c41016a1044000b417f20061044000b417f20041044000b200441041037000b20042018103c000b0b200220173602ec80042002201d3602f08004200141ff0171410874200472210a20170d090c0a0b4101210a410021044108211a410021060340200241e8006a200241306a10ee04024020022802684101470d002002280278210d2002280274210c2002280270211b200228026c210a0c070b200241f880046a41026a2201201041026a2d00003a0000200220102f00003b01f8800420022802742117200229037821080240024002400240024020022d0070220d4106470d00200a417f6a210a0c010b200d417e6a41034f0d00200a41016a220c200a4f2119200c210a20190d004115210c41c4fdc500211b4104210a200d4109460d010c0a0b200241e8006a41026a220c20012d00003a0000200220022f01f880043b016820062004460d01200421190c020b0240201728020441ffffffff0371450d002017280200102a0b2017102a0c080b200441016a22012004490d25200441017422062001200620014b1b221941ffffffff00712019470d25201941047422014100480d250240024020040d0020011028211a0c010b201a20044104742001102c211a0b201a450d0420042106201921040b201a20064104746a2201200d3a00002001200837030820012017360204200120022f01683b0001200141036a200c2d00003a0000200641016a2106200a0d000b200228023c200228024046210102402002280234450d002002280230102a0b0240024002402001450d002002280260220a200228025c470d02200a41016a2201200a490d26200a41017422042001200420014b1b220dad42187e2208422088a70d262008a7220441004e0d010c260b20024103410220011b3a00e880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022802f88004211b20022802fc8004210c20022802808104210d02402006450d0020064104742104201a21010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b02402019450d00201a102a0b4105210a2018450d0c200f102a0c0c0b02400240200a0d002004102821010c010b2002280258200a41186c2004102c21010b2001450d042002200d36025c200220013602580b20022802582201200a41186c6a2204201a36020c20042016360208200420183602042004200f360200200441146a2006360200200441106a20193602002002200a41016a360260201c2009470d000b0b2003201b462104200229025c2208422088210e02402007450d00200b102a0b200ea721032008a721072004450d0a2003ad4220862007ad842108410c21030c290b200141081037000b200441041037000b417f200141016a1044000b02402006450d0020064104742103201a21010340024020012d00004109470d000240200141046a2209280200220528020441ffffffff0371450d002005280200102a200928020021050b2005102a0b200141106a2101200341706a22030d000b0b2004450d01201a102a0c010b20022802808104210d20022802fc8004210c411c210a0b2018450d010b200f102a0b2002280234450d002002280230102a0b20022802582118024020022802602201450d002018200141186c6a21062018210903400240200941046a280200450d002009280200102a0b0240200941146a2802002204450d00200928020c2101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941186a21010240200941106a280200450d00200928020c102a0b2001210920012006470d000b0b200228025c450d002018102a0b200a4108762104200cad220e422086201bad8421082007450d01200b102a0c010b20024103410220041b3a0030200241e8006a41146a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022903f88004210820022802808104210d02402003450d002001200341186c6a210b2001210603400240200641046a280200450d002006280200102a0b0240200641146a2802002203450d00200628020c2104200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102a200928020021050b2005102a0b200441106a2104200341706a22030d000b0b200641186a21040240200641106a280200450d00200628020c102a0b200421062004200b470d000b0b2008422088210e4105210a410021042007450d002001102a0b20004101360200200041106a200d360200200041086a200e422086200842ffffffff0f838437020020002004410874200a41ff0171723602040c210b200241e8006a200110fb040240024020022802684101470d00200228026c22044108762106200241e8006a41086a2903002208422088210e200241f8006a280200210b0c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f880044100210141002105024002400240024002400240024002400240034002402001411f4d0d00410f210d0c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103c000b200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241e880046a41086a200241306a41086a280200360200200220022903303703e880044105210d0c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210d20044110490d010b200241c8006a41086a200241e880046a41086a280200220b360200200220022903e8800422083703482008422088a721072008a7210c410021060c060b200241003602f08004200242043703e880040240024020050d00410421010c010b4100210b0340200b41016a210b410021014100210902400240024002400240034002402001411f4d0d00410f210d0c030b200228028081042206200228028481042204460d01200441016a22032004490d0920062003490d0c20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d022004410f4d0d02410d210d0c010b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a2802003602002002200229033022083703202008a7210c4105210d0b2002280228210b20022802242107410021060c010b200241e8006a200241f880046a10ed04024020022802684101470d00200228026c220d41087621062002280278210b200228027421072002280270210c0c010b2002280274211b20022802702119200228026c2118200241e8006a200241f880046a10ef0420022802684101470d01200228026c210d2002280278210b200228027421072002280270210c0240201b450d00201b4104742104201821010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200d41087621062019450d002018102a0b20022802e88004211b024020022802f080042201450d00201b2001411c6c6a210a201b21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102a0b2009411c6a21010240200941146a280200450d002009280210102a0b200121092001200a470d000b0b20022802ec8004450d08201b102a0c080b4100210a2002280270210c200228026c2107024002402002280274220141027422030d004104210d410021060c010b2003410275220641ffffffff03712006470d1f200641027422044100480d1f20041028220d450d050b02402001450d002003417c6a210a200d210120072104034020012004280200360200200141046a2101200441046a21042003417c6a22030d000b200a41027641016a210a0b0240200c450d002007102a0b024020022802f08004220320022802ec8004470d00200341016a22012003490d1f200341017422042001200420014b1b2204ad421c7e2208422088a70d1f2008a722074100480d1f0240024020030d002007102821010c010b20022802e880042003411c6c2007102c21010b2001450d06200220043602ec8004200220013602e880040b20022802e8800422012003411c6c6a2204200941087622073b00012004200d36021020042018360204200420093a0000200441036a20074110763a0000200441186a200a360200200441146a20063602002004410c6a201b360200200441086a20193602002002200341016a3602f08004200b2005470d000b0b200228028481042002280288810446210420022902ec80042208422088210e024020022802fc8004450d0020022802f88004102a0b200ea721032008a7210d2004450d062003ad422086200dad842108410a21030c240b417f20031044000b417f20031044000b200441041037000b200741041037000b20032006103c000b2006410874200d41ff01717221042007ad220e422086200cad84210820022802fc8004450d0120022802f88004102a0c010b20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1033200229033021082002280238210b02402003450d0020012003411c6c6a210a200121060340024020062802042204450d0002402006410c6a2802002203450d00200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102a200928020021050b2005102a0b200441106a2104200341706a22030d000b0b200641086a280200450d002006280204102a0b2006411c6a21040240200641146a280200450d002006280210102a0b200421062004200a470d000b0b2008422088210e4105210441002106200d450d002001102a0b20004101360200200041106a200b360200200041086a200e422086200842ffffffff0f838437020020002006410874200441ff0171723602040c200b200d20064621040240200a450d00200b102a0b02402004450d00410921030c1c0b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a10332002418381046a200241386a280200360000200220022903303700fb8004200041053a0004200020022900f880043700052000410c6a200241ff80046a290000370000200041013602000c1f0b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1033410521040b2000200436020420004101360200200041086a20022902f88004370200200041106a200241f880046a41086a280200360200200a450d1d200b102a0c1d0b200241e8006a200110fb040240024020022802684101470d00200228026c22034108762104200241e8006a41086a2903002208422088210e200241f8006a28020021090c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f880044100210141002105024002400240024002400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f21030c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103c000b200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a28020036020020022002290330370320410521030c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210320044110490d010b200241e880046a41086a200241206a41086a28020022093602002002200229032022083703e880042008422088a721062008a7210b0c100b20024100360260200242043703584104210102402005450d004100211b4100210c4100211a0340200241e8006a200241f880046a10fc04024020022802684101470d002002200229027422083703e880042002280270210b200228026c21032008a721060c100b20022802702118200228026c211902400240200228028081042203200228028481042209460d00200941016a22042009490d05200320044f0d0120042003103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10330c0d0b2002280274211c20022802f88004220620096a2d000021072002200436028481040240200741034d0d00410a21040c0f0b0240024002400240024020070e0400010203000b410021074100210b4100210903400240200b411f4d0d00410f21040c140b20032004460d122004417f460d092003200441016a220d490d0e200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41002107200b4120490d03200a410f4d0d03410d21040c120b4100210b410021090340200b411f4b0d0f0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10330c110b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41012107200b4120490d02200a410f4d0d020c0d0b4100210b410021090340200b411f4b0d0e0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10330c100b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41022107200b4120490d01200a410f4b0d0c0c010b4100210b410021090340200b411f4b0d0d0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10330c0f0b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41032107200b4120490d00200a410f4b0d0b0b200220093602f08004200220073602ec800420022902ec8004210802400240200c201b460d00201b21030c010b201b41016a2204201b490d24201b41017422032004200320044b1b2203ad42147e220e422088a70d24200ea722044100480d2402400240201b0d002004102821010c010b2001201b41146c2004102c21010b2001450d0920022001360258201b210c2003211b0b2001200c41146c6a2204200837020c2004201c3602082004201836020420042019360200200c41016a210c201a41016a221a2005470d000b2002200336025c2002200c3602600b2002280284810420022802888104462104200229025c2208422088210e024020022802fc8004450d0020022802f88004102a0b200ea721032008a721052004450d0e2003ad4220862005ad842108410821030c290b417f20031044000b417f20041044000b417f200441016a1044000b417f200441016a1044000b417f200441016a1044000b417f200441016a1044000b200441041037000b200441016a2003103c000b410d2104410021070c030b410f2104410021070c020b2002280230210b2002290234210841052104410021070c010b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10332002280230210b20022902342108410521040b20074108742004722103200220083703e880042008a721062018450d002019102a0b2002200c3602602002201b36025c20022802ec800421090240200c450d00200c41146c21052001210403400240200441046a280200450d002004280200102a0b200441146a21042005416c6a22050d000b0b201b450d012001102a0c010b20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1033200229033021082002280238210902402003450d00200341146c21032001210403400240200441046a280200450d002004280200102a0b200441146a21042003416c6a22030d000b0b2008422088210e41052103410021042005450d012001102a0c010b200341087621042006ad220e422086200bad84210820022802fc8004450d0020022802f88004102a0b20004101360200200041106a2009360200200041086a200e422086200842ffffffff0f838437020020002004410874200341ff0171723602040c1c0b200241e8006a200110fb040240024020022802684101470d00200228026c220b4108762104200241e8006a41086a2903002208422088210e200241f8006a28020021060c010b200241c0006a200241fc006a280200360200200241386a200241f4006a2902003703002002200229026c37033041002101410021090240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f210b0c020b0240024020022802382205200228023c2204460d00200441016a22032004490d05200520034f0d0120032005103c000b200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f880043703204105210b0c020b2002280230220620046a2d000021042002200336023c200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d01410d210b20044110490d010b200241e880046a41086a200241206a41086a28020022063602002002200229032022083703e880042008422088a721072008a7210d0c0b0b20024100360260200242043703580240024020090d00410421010c010b2009417f6a211b4104210141042110410421094104211c4104211a4100210a4100210c03400240024020052003460d00200341016a220b2003490d052005200b4f0d01200b2005103c000b2002200a36025c2002200c360260200241013a0048200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241e880046a200241e8006a103320022802e88004210d20022802ec8004210720022802f080042106410521010c090b200620036a2c000021042002200b36023c20044100480d0402400240200441c00071450d00200441807f72220441ff017141fb014b0d010b2002200a36025c2002200c360260410621010c080b024002400240024002402005200b460d00200341026a210d200b417f460d0a2005200d4f0d01200d2005103c000b2002200a36025c2002200c360260200241013a0048200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241e880046a200241e8006a103320022802e88004210d20022802ec8004210720022802f080042106410521010c010b2006200b6a2d000021032002200d36023c0240200341014b0d004100210520030e020302030b2002200a36025c2002200c360260410c21010b2002418881046a20063602002002418481046a20073602002002418081046a200d360200200220033a00fd8004200220013a00fc80040c0b0b41800221050b200241e8006a200241306a10ed04200228027421072002280270210d200228026c210b024020022802684101470d002002200a36025c2002200c360260200241f8006a28020021060c0b0b02400240200c200a460d00200a2118200c210a0c010b200a41016a2201200a490d1e200a41017422032001200320014b1b221841ffffffff00712018470d1e201841047422034100480d1e02400240200a0d002003102821010c010b201c200a4104742003102c21010b2001450d072002200136025820012110200121092001211c2001211a0b201a200a4104746a220320194180807c712004417f7341ff017172200572221936020c200320073602082003200d3602042003200b360200200a41016a210c0240201b450d00201b417f6a211b200228023c210320022802382105200228023021062018210a0c010b0b2002201836025c2002200c3602600b200228023c2002280240462104200229025c2208422088210e02402002280234450d002002280230102a0b200ea721032008a7210d2004450d092003ad422086200dad842108410721030c230b417f20031044000b417f200b1044000b2002200a36025c2002200c360260411921010c020b417f200d1044000b200341041037000b0b2002418881046a20063602002002418481046a20073602002002418081046a200d360200200220043a00fd8004200220013a00fc80040b200241013a00f8800420022802fc8004210b0b0240200c450d002009200c4104746a210c0340024020092802082204450d0020092802002101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941106a21010240200941046a280200450d002009280200102a0b200121092001200c470d000b0b200a450d012010102a0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022903f88004210820022802808104210602402003450d00200120034104746a210a2001210b03400240200b2802082203450d00200b2802002104200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102a200928020021050b2005102a0b200441106a2104200341706a22030d000b0b200b41106a21040240200b41046a280200450d00200b280200102a0b2004210b2004200a470d000b0b2008422088210e4105210b41002104200d450d012001102a0c010b200b41087621042007ad220e422086200dad8421082002280234450d002002280230102a0b20004101360200200041106a2006360200200041086a200e422086200842ffffffff0f838437020020002004410874200b41ff0171723602040c1b0b200241e8006a200110fb040240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a29020022083703002002200229026c220e3703f88004200ea7210b2008a7210541002104200228028481042101410021030240024002400240024002400240024003402004411f4b0d010240024020052001460d002001417f460d072005200141016a22094f0d01200141016a2005103c000b200220053602848104200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a280200360200200220022903303703204105210b0c030b200b20016a2d0000220641ff00712004411f71742003722103200441076a2104200921012006418001710d000b200220093602848104024020044120490d00410d210b2006410f4b0d020b200241003602382002420437033020030d02410421010c030b200220013602848104410f210b0b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008422088a7210a2008a7210d410021090c040b4104210141002105410021060340200241e8006a200241f880046a10f30420022f006d20022d006f4110747221092002280274210a2002280270210d20022d006c210b024020022802684101470d002002200536023420022006360238200241f8006a28020021042005450d052001102a0c050b0240024020062005460d0020052107200621040c010b200541016a22042005490d16200541017422072004200720044b1b2207ad420c7e2208422088a70d162008a722044100480d160240024020050d002004102821010c010b20012005410c6c2004102c21010b2001450d042002200136023020052104200721050b20012004410c6c6a220420093b00012004200d3602042004200b3a0000200441036a20094110763a0000200441086a200a3602002003200641016a2206470d000b20022007360234200220063602380b200228028481042002280288810446210420022902342108024020022802fc8004450d0020022802f88004102a0b2008a721092004450d032008422088a7ad4220862009ad842108410621030c1b0b417f200141016a1044000b200441041037000b200941ffffff07712205410874200b41ff0171722103200aad220e422086200dad84210820022802fc8004450d0120022802f88004102a0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a103320022903302208422088210e2002280238210441052103410021052009450d002001102a0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c1a0b200241e8006a200110fb040240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a29020022083703002002200229026c220e3703f88004200ea7210b2008a721034100210420022802848104210141002109024002400240024002400240024002400240024003402004411f4b0d010240024020032001460d002001417f460d072003200141016a22054f0d01200141016a2003103c000b200220033602848104200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a280200360200200220022903303703204105210a0c030b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b200220053602848104024020044120490d00410d210a2006410f4b0d020b41002107200241003602f08004200242043703e8800420090d02410421014100210d0c030b200220013602848104410f210a0b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008a7210b4100210320022802ec8004210d0c060b4104210141012107410021060340024002400240024020032005460d00200541016a22042005490d0720032004490d09200b20056a2c000021032002200436028481040240200341004e0d004119210a0c020b4107210a0240200341c000710d000c020b200341807f7222034170470d02200241e8006a200241f880046a10f30420022f006d20022d006f41107472210320022d006c210a20022802684101470d0320034180feff07714108762105200228027821042002280274210d2002280270210b0c020b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10332002280230210b2002280234210d200228023821044105210a0b0b200220063602ec800420022007417f6a3602f080042005410874200341ff01717221032006450d072001102a0c070b200228027421052002280270210b024002402007417f6a22042006460d002006210d200421060c010b200641016a22042006490d172006410174220d2004200d20044b1b220dad420c7e2208422088a70d172008a722044100480d170240024020060d002004102821010c010b20012006410c6c2004102c21010b2001450d05200220013602e880040b20012006410c6c6a220420033b0001200420053602082004200b3602042004200a3a0000200441036a20034110763a0000024020092007460d00200741016a210720022802848104210520022802808104210320022802f88004210b200d21060c010b0b2002200d3602ec8004200220073602f080040b2002280284810420022802888104462104024020022802fc8004450d0020022802f88004102a0b2004450d052007ad422086200dad842108410521030c1c0b417f200141016a1044000b417f20041044000b200441041037000b20042003103c000b200341ffffff07712205410874200a41ff0171722103200dad220e422086200bad84210820022802fc8004450d0120022802f88004102a0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a103320022903302208422088210e200228023821044105210341002105200d450d002001102a0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c190b200241e8006a200110fb040240024020022802684101470d00200228026c22044108762105200241e8006a41086a2903002208422088210e200241f8006a28020021030c010b200241fc006a280200210c200241f8006a2802002101200241f4006a2802002103200241f0006a2802002107200228026c210b41002104410021090240024002400240024002400240024002400240034002402004411f4d0d00410f21040c020b0240024020032001460d002001417f460d052003200141016a22054f0d01200141016a2003103c000b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f88004370320410521040c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b20044120490d01410d210420064110490d010b200241e880046a41086a200241206a41086a28020022033602002002200229032022083703e880042008a7210520022802ec800421090c070b4100211b20024100360238200242043703300240024020090d0041042101410021060c010b41042101410021064100211b034020062118201b221941016a211b20052104410021064100210a03402006411f4b0d050240024020032004460d002004417f460d062003200441016a22054f0d01200441016a2003103c000b2002201836023420022019360238200241013a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022802f88004210520022802fc80042109200228028081042103410521040c090b200b20046a2d0000220d41ff00712006411f7174200a72210a200641076a210620052104200d418001710d000b024020064120490d00200d410f4d0d002002201836023420022019360238410d21040c070b0240024020192018460d0020182106201921180c010b201841016a22042018490d18201841017422062004200620044b1b220641ffffffff03712006470d18200641027422044100480d180240024020180d002004102821010c010b200120184102742004102c21010b2001450d06200220013602300b200120184102746a200a360200201b2009470d000b200220063602342002201b3602380b2005200c46210402402007450d00200b102a0b2004450d07201bad4220862006ad842108410421030c1d0b417f200141016a1044000b417f200441016a1044000b2002201836023420022019360238410f21040c010b200441041037000b0b2018450d002001102a0b2009ad220e4220862005ad842108410021052007450d01200b102a0c010b20024103410220041b3a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022903f880042208422088210e20022802808104210341052104410021052006450d002001102a0b20004101360200200041106a2003360200200041086a200e422086200842ffffffff0f838437020020002005410874200441ff0171723602040c180b200241e8006a200110fb040240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f8800441002101410021050240024002400240024002400240024002400240034002402001411f4d0d00410f21030c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103c000b200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a28020036020020022002290330370320410521030c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210320044110490d010b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008422088a721092008a721060c080b200241003602f08004200242043703e8800402400240024020050d00410421010c010b20022802ec8004210720022802f08004210d410021100340200241e8006a200241f880046a10fc042002280274210920022802702118200228026c211a024020022802684101470d002002280278210420182106201a21030c090b200241e8006a200241f880046a10fc042002280274211320022802702119200228026c211c024020022802684101470d00200228027821042019210620132109201c21030c080b0240024002400240024002400240024002400240024002400240024002400240200228028081042203200228028481042206460d00200641016a22012006490d02200320014f0d0120012003103c000b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200228023021062002290234210e4105210a4100211b410021030c150b20022802f88004220c20066a2d000021042002200136028481044100211b0240200441034d0d004109210a410021030c150b024002400240024020040e0400010203000b4100211b410021044100210a034002402004411f4d0d00410f210a0c170b0240024020032001460d002001417f460d072003200141016a220b4f0d01200141016a2003103c000b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200228023021062002290234210e4105210a4100211b0c180b200c20016a2d000021062002200b3602848104200641ff00712004411f7174200a72210a200441076a2104200b21012006418001710d000b4100211b20044120490d0f2006410f4d0d0f410d210a0c150b0240024020032001460d00200641026a21042001417f460d0620032004490d07200c20016a2c0000210120022004360284810402402001417f4a0d00411921030c0e0b200141c000710d010c0c0b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10332002290330210820022802382104410521030c0c0b200141807f7222014170470d0a200241e8006a200241f880046a10f30420022903702108200228026c210a024020022802684101470d00200228027821040c0d0b4101211b0c0f0b200241e8006a200241f880046a10f30420022903702108200228026c210a024020022802684101460d004102211b0c0f0b20022002280278360270200a418080807871211b200a4180807c712103200a41087621040c0c0b0240024020032001460d00200641026a210b2001417f460d062003200b490d08200c20016a2c000021042002200b36028481040240200441004e0d004119210a410021030c170b200441c000710d010c090b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10334105210a2002290234210e20022802302106410021030c150b200441807f72220441ff017141fc01490d07024002402003200b460d00200641036a2101200b417f460d07200320014f0d0120012003103c000b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200228023021062002290234210e4105210a410021030c150b200c200b6a2d0000210b200220013602848104410021030240200b41014d0d00410c210a4100211b200b21040c150b2004417f7321064103211b0240200b0e020e000e0b410121030c0d0b417f20011044000b417f200141016a1044000b417f20041044000b20042003103c000b417f200b1044000b417f20011044000b200b2003103c000b4106210a410021030c0c0b410721030b200141ff0171410874200372210a0b20022004360270200a418080807871211b200a4180807c712103200a41087621040b20022008370368200229026c210e2008a721060c080b0b02400240200d2007460d002007210b0c010b200741016a22012007490d18200741017422042001200420014b1b220bad42287e220e422088a70d18200ea722044100480d180240024020070d002004102821010c010b20022802e88004200741286c2004102c21010b2001450d03200220013602e880042007210d200b21070b20022802e880042201200d41286c6a2204201c36020c20042009360208200420183602042004201a360200200441206a20083702002004411c6a200a3602002004411a6a20033a0000200441196a20063a0000200441186a201b3a0000200441146a2013360200200441106a2019360200200d41016a210d201041016a22102005470d000b2002200b3602ec80042002200d3602f080040b200228028481042002280288810446210420022902ec80042208422088210e024020022802fc8004450d0020022802f88004102a0b200ea721032008a721092004450d072003ad4220862009ad842108410321030c1d0b200441041037000b417f20031044000b0b41002103410021040b200a41ff0171200441ff0171410874722003418080fc077172201b722103200e422088a72104200ea721092019450d00201c102a0b2018450d00201a102a0b200220073602ec80042002200d3602f0800420022802e88004210b0240200d450d00200d41286c2105200b210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200541586a22050d000b0b2007450d01200b102a0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1033200229033021082002280238210402402003450d00200341286c21052001210303400240200341046a280200450d002003280200102a0b0240200341106a280200450d002003410c6a280200102a0b200341286a2103200541586a22050d000b0b2008422088210e41052103410021052009450d012001102a0c010b200341087621052009ad220e4220862006ad84210820022802fc8004450d0020022802f88004102a0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c170b200241013a00302002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050b0b201d450d03200c102a0c030b0b2019450d00201c102a0b2003411076210d200341087621070b200741ff0171410874200341ff0171722103200d411074210d200441ff0171410874210702402017450d002001210403400240200441046a280200450d002004280200102a0b200441106a2104200a41706a220a0d000b0b2003200d722103200720057221042014450d012001102a0c010b20024103410220041b3a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022903f88004210820022802808104210302402005450d00200541047421052001210403400240200441046a280200450d002004280200102a0b200441106a2104200541706a22050d000b0b2008422088210e41052104410021052009450d012001102a0c010b200441087621052009ad220e4220862006ad8421082010450d00200b102a0b20004101360200200041106a2003360200200041086a200e422086200842ffffffff0f838437020020002005410874200441ff0171723602040c0d0b41002101410021040240024002400340024020094105470d00410f21070c020b0240024020032009460d00200320094b0d01200941016a2003103c000b200241013a00f88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241f880046a360218200241206a200241e8006a103341052107200229032021080c030b200620096a2d0000220541ff00712001411f71742004722104200141076a2101200941016a220b21092005418001710d000b20014120490d0220054110490d02410d21070b0b2008422088a72109200228022821042008a7210d0c050b024020040d00410021054101211b410021094100210d0c080b200241e8006a41004180081099051a410021054100210d4101211b410021070340024002402003200b6b200420076b22014180082001418008491b2201490d00200b20016a220c200b490d042003200c4f0d01200c2003103c000b200241013a00e880042002418c81046a4101360200200242013702fc8004200241a4e2c5003602f880042002412636021c2002200241186a36028881042002200241e880046a360218200241306a200241f880046a103320022903302208422088a72109200228023821042008a72101410521070240200d450d00201b102a0b2001210d0c060b200241e8006a2006200b6a2001109a051a02400240200d20056b2001490d00200520016a21090c010b200520016a22092005490d02200d410174220b2009200b20094b1b220b4100480d0202400240200d0d00200b1028211b0c010b201b200d200b102c211b0b201b450d04200b210d0b201b20056a200241e8006a2001109a051a20092105200c210b2004200120076a22074d0d040c000b0b1031000b200b200c1044000b200b41011037000b200241e8006a201b2009105420022802684101470d02410821070240200d450d00201b102a0b0b2009ad422086200dad84210841002101200a450d002006102a0b20004101360200200041106a2004360200200041086a200837020020002001410874200741ff0171723602040c060b201b4108762105200c210b0b2003200b490d012003200b6b2201417f4c0d020240024020010d00410121040c010b200110282204450d040b2009ad4220862108200dad210e20042006200b6a2001109a051a2001ad222042208621210240200a450d002006102a0b2008200e8421082021202084210e2005410874201b41ff0171722101410121030b200020033a000420004100360200200041056a20022f00153b0000200041186a200e370200200041146a20043602002000410c6a2008370200200041086a2001360200200041206a2002290200370200200041076a200241176a2d00003a0000200041286a200241086a290200370200200041306a200241106a2802003602000c030b200b20031044000b1036000b200141011037000b2002419081046a24000bf304010b7f230041c080016b220224002002200110f404410121030240024020022802004101470d0020002002290204370204200041013602002000410c6a2002410c6a2902003702000c010b2002280204210420024100418080011099052105410021064100210702400240024002402004450d00410021084100210641012103410021090340024002402001280204220a200128020822076b200420096b220b41808001200b41808001491b220b490d002007200b6a220c2007490d04200a200c4f0d01200c200a103c000b200541013a008f8001200541b480016a4101360200200542013702a48001200541a4e2c5003602a08001200541263602bc80012005200541b880016a3602b0800120052005418f80016a3602b880012005419080016a200541a080016a10332005418b80016a2005419880016a2802003600002005200529039080013700838001200041053a00042000200529008080013700052000410c6a2005418780016a290000370000200041013602002006450d062003102a0c060b2005200128020020076a200b109a05210a2001200c36020802400240200620086b200b490d002008200b6a21070c010b2008200b6a22072008490d052006410174220c2007200c20074b1b220c4100480d050240024020060d00200c102821030c010b20032006200c102c21030b2003450d04200c21060b200320086a200a200b109a051a200721082004200b20096a22094b0d000b0b2000200336020420004100360200200041146a2007360200200041106a41003602002000410c6a2007360200200041086a20063602000c030b2007200c1044000b200c41011037000b1031000b200241c080016a24000b8607010b7f230041d0086b22022400410021034100210402400240024002400240024002400240034002402003411f4d0d00410f21030c020b0240024020012802082205200128020c2206460d00200641016a22072006490d05200520074f0d0120072005103c000b200241013a0089082002411c6a41013602002002420137020c200241a4e2c5003602082002412636029c08200220024198086a360218200220024189086a36029808200241b8086a200241086a1033410521030c020b2001280200220820066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b20034120490d01410d210320064110490d010b2000200336020420004101360200200041086a20022902b808370200200041106a200241b8086a41086a2802003602000c060b024020040d002000428080808010370200200041086a42003702000c060b200241086a41004180081099051a41002106410021094101210a4100210b034002400240200520076b2004200b6b22034180082003418008491b2203490d00200720036a220c2007490d042005200c4f0d01200c2005103c000b200241013a00a708200241cc086a4101360200200242013702bc08200241a4e2c5003602b8082002412636029c08200220024198086a3602c8082002200241a7086a36029808200241a8086a200241b8086a103320024194086a200241b0086a280200360000200220022903a80837008c08200041053a000420002002290089083700052000410c6a20024190086a290000370000200041013602002009450d07200a102a0c070b200241086a200820076a2003109a051a2001200c36020c02400240200920066b2003490d00200620036a210c0c010b200620036a220c2006490d0520094101742207200c2007200c4b1b22074100480d050240024020090d0020071028210a0c010b200a20092007102c210a0b200a450d04200721090b200a20066a200241086a2003109a051a20042003200b6a220b4d0d05200128020c21072001280208210520012802002108200c21060c000b0b417f20071044000b2007200c1044000b200741011037000b1031000b200241086a200a200c1054024020022802084101470d0002402009450d00200a102a0b200041083a0004200041013602000c010b2000200a3602042000410c6a200c360200200041086a2009360200200041003602000b200241d0086a24000b881f03127f017e037f23004180026b220524000240024020014115490d00410121064101210702400240034020012108200021092006200771410173210a024002400240034002400240024002402004450d00024020064101710d002000200110fe042004417f6a21040b2001410276220741036c210b2007410174210c4100210d20014132490d03200741016a210e200020074103746a220f28020020002007417f6a220d4103746a2210280200201041046a2802002210200f41046a280200220f200f20104b1b109c052211450d01417f410120114100481b21100c020b2000200110ff040c0b0b417f200f201047200f2010491b21100b2007200d2010417f4622101b210f024002402000200e4103746a22112802002000200d200720101b22124103746a2207280200200741046a2802002207201141046a280200220d200d20074b1b109c052211450d00417f410120114100481b21070c010b417f200d200747200d2007491b21070b4102410120101b20102007417f4622071b210d024002402000200e201220071b22114103746a22102802002000200f4103746a2207280200200741046a2802002207201041046a2802002210201020074b1b109c05220e450d00417f4101200e4100481b21100c010b417f201020074720102007491b21100b200c4101722107200d2010417f4622126a2113024002402000200c4103746a220d2802002000200c417f6a22104103746a220e280200200e41046a280200220e200d41046a280200220d200d200e4b1b109c052214450d00417f410120144100481b210e0c010b417f200d200e47200d200e491b210e0b200c2010200e417f46220e1b210d2013200e6a211302400240200020074103746a221428020020002010200c200e1b220e4103746a220c280200200c41046a280200220c201441046a28020022102010200c4b1b109c052214450d00417f410120144100481b210c0c010b417f2010200c472010200c491b210c0b2013200c417f46220c6a21100240024020002007200e200c1b22134103746a220c2802002000200d4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b109c05220e450d00417f4101200e4100481b210c0c010b417f200c200747200c2007491b210c0b200b41016a21072010200c417f4622146a2115024002402000200b4103746a220e2802002000200b417f6a220c4103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b109c052216450d00417f410120164100481b21100c010b417f200e201047200e2010491b21100b200b200c2010417f4622101b210e201520106a211502400240200020074103746a22162802002000200c200b20101b22104103746a220c280200200c41046a280200220c201641046a280200220b200b200c4b1b109c052216450d00417f410120164100481b210c0c010b417f200b200c47200b200c491b210c0b2015200c417f46220c6a211502400240200020072010200c1b220b4103746a220c2802002000200e4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b109c052210450d00417f410120104100481b21100c010b417f200c200747200c2007491b21100b200f201120121b2107200d201320141b210c200e200b2010417f4622101b210b201520106a210d0b024002402000200c4103746a220e280200200020074103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b109c05220f450d00417f4101200f4100481b21100c010b417f200e201047200e2010491b21100b200c20072010417f46220e1b2110200d200e6a210d024002402000200b4103746a220f28020020002007200c200e1b220e4103746a2207280200200741046a2802002207200f41046a280200220c200c20074b1b109c05220f450d00417f4101200f4100481b21070c010b417f200c200747200c2007491b21070b200d2007417f46220c6a2107024002400240024002402000200b200e200c1b220d4103746a220b280200200020104103746a220c280200200c41046a280200220c200b41046a280200220b200b200c4b1b109c05220e450d00200e4100480d010c020b200b200c4f0d010b200741016a2207410c490d0102402001410176220b450d00200020014103746a41786a21072000210c0340200c2902002117200c200729020037020020072017370200200c41086a210c200741786a2107200b417f6a220b0d000b0b20012010417f736a2110410121070c020b200d21100b20074521070b0240200745200a724101710d00200020011080050d090b2003450d010240201020014f0d00024002402003280200200020104103746a2207280200200741046a280200220c200341046a280200220b200b200c4b1b109c05220e450d00200e41004e0d010c050b200b200c490d040b200029020021172000200729020037020020072017370200200041786a21122000410c6a2113200041086a2114200028020421072000280200210d4100210b2001210e0340024002400240200b200e417f6a22114f0d002013200b4103746a210c034002400240200d200c417c6a280200200c28020022102007200720104b1b109c05220f450d00200f4100480d030c010b20072010490d020b200c41086a210c2011200b41016a220b470d000c020b0b0240200b20114f0d002012200e4103746a210c2011210e034002400240200d200c280200200c41046a28020022102007200720104b1b109c05220f450d00200f4100480d010c050b200720104f0d040b200c41786a210c200b200e417f6a220e490d000b0b200b21110b200020073602042000200d36020002402001201141016a2207490d00200020074103746a2100200120076b220141154f0d040c0b0b200720011044000b2014200b4103746a221029020021172010200c290200370200200c2017370200200b41016a210b0c000b0b0b41f483c600201020011034000b20080d0141bc83c600410041001034000b20002109200121080b201020084f0d02200929020021172009200920104103746a2207290200370200200720173702002009280204210c2009280200211241002100410021184100211902402008417f6a220e450d002009410c6a21074100211803400240024002402007417c6a2802002012200c2007280200220b200b200c4b1b109c052210450d00201041004e0d010c020b200b200c490d010b200e21190240200e20184d0d00200920084103746a41786a2107200e211903400240024020072802002012200c200741046a280200220b200b200c4b1b109c052210450d00201041004e0d010c030b200b200c490d020b200741786a21072019417f6a221920184b0d000b0b0240024020192018490d00200e2019490d010c040b201820191044000b2019200e103c000b200741086a2107200e201841016a2218470d000b200e2118200e21190b200941086a220720194103746a210e41800121144100211141002110410021014180012106200720184103746a221a210d03400240200e200d6b22074187104b220a0d002007410376220741807f6a200720112000492001201049220b72220f1b21070240200f450d0020062007200b1b210620072014200b1b21140c010b2007200741017622066b21140b024020012010470d00024020060d002005221021010c010b4100210720052110200d210b0340201020073a0000200741016a210702400240200b2802002012200c200b41046a280200220f200f200c4b1b109c052201450d00417f410120014100481b210f0c010b417f200f200c47200f200c491b210f0b200b41086a210b2010200f417f476a211020062007470d000b200521010b024020112000470d00024020140d0020054180016a220021110c010b200e41786a21074100210b20054180016a210003402000200b3a0000200b41016a210b0240024020072802002012200c200741046a280200220f200f200c4b1b109c052211450d00417f410120114100481b210f0c010b417f200f200c47200f200c491b210f0b200741786a21072000200f417f466a21002014200b470d000b20054180016a21110b0240200020116b2207201020016b220b200b20074b1b2213450d00200d20012d00004103746a22072802042115200728020021162007200e20112d0000417f734103746a290200370200024020134101460d00410021070340200e201120076a220b2d0000417f734103746a200d200120076a41016a220f2d00004103746a290200370200200d200f2d00004103746a200e200b41016a2d0000417f734103746a290200370200200741026a210b200741016a220f2107200b2013490d000b2011200f6a21112001200f6a21010b200e20112d0000417f734103746a2207201536020420072016360200201141016a2111200141016a21010b200e20144103746b200e20112000461b210e200d20064103746a200d20012010461b210d200a0d000b02400240200120104f0d00200e21070340200d2010417f6a22102d00004103746a220b2902002117200b200741786a22072902003702002007201737020020012010490d000c020b0b200d2107201120004f0d000340200729020021172007200e2000417f6a22002d0000417f734103746a220b290200370200200b2017370200200741086a210720112000490d000b0b2009200c36020420092012360200024020082007201a6b41037620186a22014d0d00200929020021172009200920014103746a220729020037020020072017370200200820016b220c450d02200c20012001200c4b1b210b20084103762110200741086a2100024002402001200c417f6a220c490d002000200c20022007200410fd04200921000c010b2009200120022003200410fd0420072103200c21010b200b20104f2106201920184d2107200141154f0d010c040b0b41cc83c600200120081034000b41dc83c6001032000b41cc83c600201020081034000b20014102490d00200041786a211341002114410121120340201241037421072012417f6a2110201241016a2112024002400240200020076a22072802002211200020104103746a220f280200200f41046a280200220c200741046a280200220b200b200c4b1b109c05220e450d00200e4100480d010c020b200b200c4f0d010b2007200f29020037020002402010450d002014210c20132107024003400240024020112007280200200741046a280200220e200b200b200e4b1b109c05220d450d00200d4100480d010c030b200b200e4f0d030b20002010417f6a22104103746a210f200741086a2007290200370200200741786a2107200c41016a220e200c49210d200e210c200d450d000b0b200741086a210f0b200f200b360204200f20113602000b2014417f6a2114201341086a211320122001470d000b0b20054180026a24000bf50202057f017e02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034103746a220329020021072003200020044103746a220429020037020020042007370200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024103746a220329020021072003200020044103746a2204290200370200200420073702002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034103746a220129020021072001200020044103746a2200290200370200200020073702000b0f0b41cc83c600200420011034000b41bc83c600200320011034000bb20102037f017e024020014101762202450d00200020012002417f6a1081052002417e6a210203402002417f460d012000200120021081052002417f6a21020c000b0b0240024020014102490d00200141037420006a41786a21022001210303402003417f6a220420014f0d02200029020021052000200229020037020020022005370200200020044100108105200241786a210220042103200441014b0d000b0b0f0b41cc83c6002003417f6a20011034000b9a06050a7f017e017f017e037f200041686a2102200041786a2103200141324921044101210541002106024003400240024020052001490d00410021070c010b200320054103746a210841012107034002400240200841086a22092802002008280200200841046a280200220a2008410c6a28020022082008200a4b1b109c05220b450d00200b4100480d030c010b2008200a490d020b4101210a200541016a220520014921072009210820012005470d000c030b0b2005200146210a20040d0120052001460d01024002400240024002402005417f6a220820014f0d002007410171450d01200020084103746a2208290200210c200820002005410374220d6a220b290200220e370200200b200c37020020054102490d0402400240200ea7220f20002005417e6a220a4103746a2210280200201041046a2802002207200841046a2802002209200920074b1b109c052211450d0020114100480d010c060b200920074f0d050b20082010290200370200200a450d032002200d6a2108034002400240200f2008280200200841046a28020022072009200920074b1b109c05220d450d00200d4100480d010c050b200920074f0d050b2000200a417f6a220a4103746a2110200841086a2008290200370200200841786a2108200a0d000c030b0b41bc83c600200820011034000b41cc83c600200520011034000b200841086a21100b201020093602042010200f3602000b200641016a21060240200120056b220d4102490d0002400240200b280208200b280200220f200b41046a2802002209200b410c6a2802002208200820094b1b109c05220a450d00200a4100480d010c020b200820094f0d010b200b41086a2111200b200b2902083702000240200d4103490d004103210a41022107034002400240200b20074103746a2208280200200f2009200841046a2802002207200720094b1b109c052210450d00201041004e0d030c010b200720094f0d020b200841786a20082902003702000240200a200d4f0d00200a2107200a41016a210a200821110c010b0b200821110b2011200f360200201120093602040b20064105470d000b4100210a0b200a0bb60202057f017e03402002410174220341017221040240024002400240200341026a220320014f0d00200420014f0d0102400240200020044103746a2205280200200020034103746a2206280200200641046a2802002206200541046a2802002205200520064b1b109c052207450d00417f410120074100481b21060c010b417f200520064720052006491b21060b200320042006417f461b21040b0240200420014f0d00200220014f0d020240200020024103746a2202280200200020044103746a2203280200200341046a2802002206200241046a2802002205200520064b1b109c052207450d00200741004e0d010c040b20052006490d030b0f0b41c885c600200420011034000b41d885c600200220011034000b200229020021082002200329020037020020032008370200200421020c000b0b1500200120002802002200280200200028020810450bf30201037f230041c0006b22022400200141086a2802002103200128020421042002200128020022013602100240024002402001418080044b0d0002402004450d0020022003360214200120034b0d022003418080044d0d002002413c6a41013602002002420237022c200241f8a7c6003602282002410136021c200241d4a7c6003602182002200241186a3602382002200241286a10330c030b200241003602000c020b2002413c6a41013602002002420237022c200241d8a7c6003602282002410136021c200241d4a7c6003602182002200241186a3602382002200241286a10330c010b200241246a41013602002002413c6a41023602002002420237022c200241e8a7c6003602282002410136021c2002200241186a3602382002200241106a3602202002200241146a3602182002200241286a10330b024002402002280200450d0020002002290300370200200041086a200241086a2802003602000c010b200041003602000b200241c0006a24000bf80501037f230041f0006b2204240002400240024002400240024020012802084102460d00412e10282201450d01200041013a0000200141266a41002900eca946370000200141206a41002900e6a946370000200141186a41002900dea946370000200141106a41002900d6a946370000200141086a41002900cea946370000200141002900c6a946370000200041086a42ae808080e005370200200041046a20013602000c050b02400240024002400240200128020022052d0000416e6a2201411e4b0d004100210620010e1f03000000000000000000000000000000000000000000000000000008040102030b412010282201450d05200041013a0000200141186a410029008caa46370000200141106a4100290084aa46370000200141086a41002900fca946370000200141002900f4a946370000200041086a42a08080808004370200200041046a20013602000c080b410221060c060b410321060c050b20042005280204220136020c0240024020012003490d004194aac6002105200441e8006a2103200441d0006a2101200441c0006a21020c010b200220014101746a22012d0001450d0441a4aac6002105200441386a2103200441206a2101200441106a21020b20034101360204200141146a410136020020012003360210200142023702042001200536020020032004410c6a360200200220011033200041013a00002000410c6a200241086a280200360200200041046a20022902003702000c050b410121060c030b412e41011037000b412041011037000b20012d000021060b0240200541106a2d00004106470d00200041003a0000200020063a00010c010b0240412910282201450d00200041013a0000200141286a41002d00dcaa463a0000200141206a41002900d4aa46370000200141186a41002900ccaa46370000200141106a41002900c4aa46370000200141086a41002900bcaa46370000200141002900b4aa46370000200041086a42a98080809005370200200041046a20013602000c010b412941011037000b200441f0006a24000b86c30103087f027e017f230041f0006b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022d00000eac0100e1010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01000b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810282200450dab012003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c200320013602584193a2c600413b200341d8006a41d0a2c6001038000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490de0012007410174220a2009200a20094b1b22094100480de0010240024020070d002009102821070c010b200128021820072009102c21070b2007450dad01200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a22021099051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060ce0010b0240200141306a2802002204200141346a22052802004f0d002002310001210b200141206a350200210c024020042001412c6a280200470d00200441016a22022004490ddf01200441017422052002200520024b1b220241ffffffff01712002470ddf01200241037422054100480ddf010240024020040d002005102821040c010b200128022820044103742005102c21040b2004450dad01200120043602282001412c6a2002360200200141306a28020021040b200128022820044103746a200b422886200c84370200200141306a2201200128020041016a3602000ce0010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450ddf012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddf012000200329023c370204200020013602000ce0010b0240200141306a2802002204200141346a22052802004f0d002002310001210b200141206a350200210c024020042001412c6a280200470d00200441016a22022004490dde01200441017422052002200520024b1b220241ffffffff01712002470dde01200241037422054100480dde010240024020040d002005102821040c010b200128022820044103742005102c21040b2004450dad01200120043602282001412c6a2002360200200141306a28020021040b200128022820044103746a200b422886200c8442808080803084370200200141306a2201200128020041016a3602000cdf010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450dde012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dde012000200329023c370204200020013602000cdf010b2002310001210b200341d8006a200141186a200141286a22044100108905024020032d00584101470d002000200329025c370200200041086a200341e4006a2802003602000cdf010b0240200141306a2802002202200141346a22052802004f0d00200141206a350200210c024020022001412c6a280200470d00200241016a22052002490ddd01200241017422062005200620054b1b220541ffffffff01712005470ddd01200541037422064100480ddd010240024020020d002006102821020c010b200428020020024103742006102c21020b2002450dad01200120023602282001412c6a2005360200200141306a28020021020b200128022820024103746a200b422886200c8442808080801084370200200141306a2201200128020041016a3602000cde010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450ddd012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddd012000200329023c370204200020013602000cde010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810282200450dac012003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c2003200136025841e0a2c6004134200341d8006a41d0a2c6001038000b02400240200141286a220228020020044103746a22042d00044101470d002004310005210b200341d8006a200141186a2002108a052003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cdf010b411a10282201450dad01200141186a41002f00aca3463b0000200141106a41002900a4a346370000200141086a410029009ca34637000020014100290094a3463700002000429a808080a003370204200020013602000cde010b0240200141306a2802002204200141346a22052802004f0d00200141206a350200210c024020042001412c6a280200470d00200441016a22052004490ddc01200441017422062005200620054b1b220541ffffffff01712005470ddc01200541037422064100480ddc010240024020040d002006102821020c010b200228020020044103742006102c21020b2002450daf01200120023602282001412c6a2005360200200141306a28020021040b200128022820044103746a200b422886200c8442808080802084370200200141306a2201200128020041016a3602000cdd010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450ddc012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddc012000200329023c370204200020013602000cdd010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810282200450dae012003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c2003200136025841e0a2c6004134200341d8006a41d0a2c6001038000b200141286a220628020020044103746a22042d00052105024020042d00044101470d00200541ff01714104470daf010b0240024020024101460d00200341d8006a200141186a22022006108a052003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cde010b20012d003822024104460ddb01200341d8006a200141186a2205200620021089050240024020032d00584101460d000240200141206a2802002204200141246a22072802004f0d00024020042001411c6a280200470d00200441016a22072004490dde01200441017422082007200820074b1b22074100480dde010240024020040d002007102821040c010b200528020020042007102c21040b2004450db401200120043602182001411c6a2007360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cde010b200341ec006a220241013602002003420137025c20034190aec600360258200341013602042003200736020020032003360268200341106a200341d8006a103320032802102204450ddd012003200329021437021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450ddd01200329023c210b0c010b200328025c2202450ddc01200341e0006a290300210b0b2000200b370204200020023602000cdd010b200541ff01714104460ddb010240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490ddb01200441017422072006200720064b1b22064100480ddb010240024020040d002006102821020c010b200228020020042006102c21020b2002450db201200120023602182001411c6a2006360200200141206a28020021040b200128021820046a20053a0000200141206a2201200128020041016a3602000cdc010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102202450ddb012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddb012000200329023c370204200020013602000cdc010b2003200241046a280200220236024802400240200141306a280200220420024d0d0020042002417f736a22022004490d0141f2adc600411d1050000b200341ec006a220241023602002003411c6a41013602002003420237025c200341b0adc60036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1033200328023821042003200329023c37021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a10332003280214450dd1012003280210102a0cd1010b200141286a220428020020024103746a22022d00044103460dd10120022d0005220241ff01714104460dd101200341d8006a200141186a220520042002108905024020032d00584101460d000240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490ddb01200441017422072006200720064b1b22064100480ddb010240024020040d002006102821040c010b200528020020042006102c21040b2004450db301200120043602182001411c6a2006360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cd3010b200341ec006a220241013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102204450dd2012003200329021437021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a10332003280214450dd1012003280210102a0cd1010b200328025c2202450dd101200341e0006a290300210b0cd2010b200241046a2802002102200341d8006a200141186a2206200141286a220541001089050240024020032d00584101470d00200341e0006a290300210b200328025c22010d010cdb010b200141306a28020021042003200236024802400240200420024d0d0020042002417f736a22022004490d0141f2adc600411d1050000b200341ec006a220141023602002003411c6a41013602002003420237025c200341b0adc60036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1033200328023821022003200329023c37021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b200329023c210b200328023822010d010cdb010b200528020020024103746a22022d00044103460dda0120022d0005220241ff01714104460dda01200341d8006a200620052002108905024020032d00584101460d000240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490ddb01200441017422072005200720054b1b22054100480ddb010240024020040d002005102821040c010b200628020020042005102c21040b2004450db401200120043602182001411c6a2005360200200141206a28020021040b200128021820046a20023a0000200141206a2201200128020041016a3602000cdc010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450ddb012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddb01200329023c210b0c010b200328025c2201450dda01200341e0006a290300210b0b2000200b370204200020013602000cda010b200241046a280200220228020421062002280200210420032002280208220536024802400240200141306a280200220220054d0d0020022005417f736a22052002490d0141f2adc600411d1050000b200341ec006a220441023602002003411c6a41013602002003420237025c200341b0adc60036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1033200328023821022003200329023c37021420032002360210200441013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b2003200329023c370204200320032802383602000ccd010b410421090240200141286a220d280200220720054103746a22052d00044103460d0020052d000521090b200320093a00302006450dc801200941ff0171220a4104460dc701200641027421060340200320042802002205360248200220054d0dca0120022005417f736a220520024f0dce01200720054103746a22052d00044103460dcb0120052d000522084104460dcb01200a2008470dcb01200441046a21042006417c6a22060d000cc9010b0b20012d003822024104460dc501200341d8006a200141186a2205200141286a20021089050240024020032d00584101460d000240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490dd901200441017422072006200720064b1b22064100480dd9010240024020040d002006102821040c010b200528020020042006102c21040b2004450db301200120043602182001411c6a2006360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cc8010b200341ec006a220241013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102204450dc7012003200329021437021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450dc701200329023c210b0c010b200328025c2202450dc601200341e0006a290300210b0b2000200b370204200020023602000cd8010b200128020021042003200241046a2802002202360254024002400240200441386a28020020024b0d00200341ec006a41013602002003420237025c200341e4abc600360258200341013602342003200341306a3602682003200341d4006a360230200341386a200341d8006a1033200341186a200329023c370300200341013602102003200328023822043602140c010b2003200428023020024102746a2802002202360200024002402004412c6a28020020024b0d0041012105200341ec006a41013602002003420237025c20034188acc6003602582003410136024c2003200341c8006a36026820032003360248200341386a200341d8006a1033200341186a200329023c220b370300200b422088a7210720032802382104200ba721020c010b2003411c6a200428022420024104746a22042d000d22073a0000200341186a2004280208220236020020042802002104410021050b20032005360210200320043602142005450d010b200341186a21010cc3010b02402002450d002004417f6a2104200141286a2105200141186a21060340200341d8006a20062005200420026a2d0000108905024020032d00584101470d00200341e0006a2101200328025c21040cc5010b2002417f6a22020d000b0b200741ff01714104460dd6010240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490dd601200241017422052004200520044b1b22044100480dd6010240024020020d002004102821020c010b200128021820022004102c21020b2002450db101200120023602182001411c6a2004360200200141206a28020021020b200128021820026a20073a0000200141206a2201200128020041016a3602000cd7010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450dd6012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382204450dd601200329023c210b0cc3010b200241046a28020021062001280200210220034100360238024002400240200241146a2802000d00200341d8006a41146a41013602002003420237025c200341c4abc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10330c010b200341d8006a200141186a2204200141286a22054100108905024020032d00584101470d00200341e0006a290300210b0cc2010b20012802002207412c6a280200210220032006360238200220064b0d01200341ec006a41013602002003420237025c20034188acc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10330b2003290214210b200328021022010dc1010cd6010b200728022420064104746a22062d000d2107024020062802082202450d002006280200417f6a21060340200341d8006a20042005200620026a2d0000108905024020032d00584101470d00200341e0006a290300210b0cc2010b2002417f6a22020d000b0b200741ff01714104460dd5010240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dd501200241017422062005200620054b1b22054100480dd5010240024020020d002005102821020c010b200428020020022005102c21020b2002450db101200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20073a0000200141206a2201200128020041016a3602000cd6010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450dd5012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd501200329023c210b0cc0010b200341d8006a200141186a200141286a410410890520032d00584101470dd401200328025c2201450dd4012000200341e0006a290300370204200020013602000cd5010b200341d8006a200141186a2204200141286a22054100108905200341d8006a21020240024020032d00584101460d00200341d8006a200420054104108905200341d8006a210220032d00584101460d00200341d8006a2004200520032d00592206108905200341d8006a210220032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dd501200241017422072005200720054b1b22054100480dd5010240024020020d002005102821020c010b200428020020022005102c21020b2002450db201200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20063a0000200141206a2201200128020041016a3602000cd6010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450dd5012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd501200329023c210b0c010b200241046a2802002201450dd401200241086a290200210b0b2000200b370204200020013602000cd4010b200341d8006a200141046a200241046a280200108b050240024020032d00584101460d000240200141206a2802002202200141246a22042802004f0d0020032d00592104024020022001411c6a280200470d00200241016a22052002490dd401200241017422062005200620054b1b22054100480dd4010240024020020d002005102821020c010b200128021820022005102c21020b2002450db201200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cd5010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450dd4012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd401200329023c210b0c010b200328025c2201450dd301200341e0006a290300210b0b2000200b370204200020013602000cd3010b2003200241046a2802002202360200200341d8006a200141046a2002108b05024020032d00584101470d002003200328025c22013602382003200341e0006a290300220b37023c0cbb010b200320032d005922023a0030200341d8006a200141186a200141286a4104108905024020032d00584101470d00200341c0006a200341e4006a2802003602002003200329025c3703380cba010b200320032d005922013a004820014104460dd101200241ff01712001460dd101200341106a41146a41303602002003411c6a4127360200200341d8006a41146a41033602002003420337025c200341d0a3c600360258200341013602142003200341106a3602682003200341c8006a3602202003200341306a36021820032003360210200341386a200341d8006a10330cb9010b200341d8006a200141046a200241046a280200108b050240024020032d00584101460d00200341d8006a200141186a2205200141286a20032d00592204108905024020032d00584101460d000240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490dd301200241017422072006200720064b1b22064100480dd3010240024020020d002006102821020c010b200528020020022006102c21020b2002450db201200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cd4010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102202450dd3012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd301200329023c210b0c020b200328025c2201450dd201200341e0006a290300210b0c010b200328025c2201450dd101200341e0006a290300210b0b2000200b370204200020013602000cd1010b200128020021042003200241046a280200220236023802400240200441206a28020020024d0d000240200141206a2802002205200141246a22062802004f0d00200428021820024101746a2d00002102024020052001411c6a280200470d00200541016a22042005490dd101200541017422062004200620044b1b22044100480dd1010240024020050d002004102821050c010b200128021820052004102c21050b2005450db101200120053602182001411c6a2004360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000cd2010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102202450dd1012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd101200329023c210b0c010b200341ec006a41013602002003420237025c200341a8acc6003602582003410136024c2003200341c8006a3602682003200341386a360248200341106a200341d8006a103320032802102201450dd0012003290214210b0b2000200b370204200020013602000cd0010b2003200241046a28020022023602282001280200210420032002360254024002400240200441206a28020020024b0d00200341ec006a41013602002003420237025c200341a8acc6003602582003410136024c2003200341c8006a3602682003200341d4006a360248200341106a200341d8006a10330c010b200428021820024101746a22022d00010d01200341ec006a41013602002003420237025c200341b8acc60036025820034101360204200320033602682003200341d4006a360200200341106a200341d8006a10330b2003280210210120032003290214220b37023c200320013602380cb6010b200320022d000022023a002f200341d8006a200141186a200141286a4104108905024020032d00584101470d00200341c0006a200341e4006a2802003602002003200329025c3703380cb5010b200320032d005922013a00002001200241ff0171460dce0120014104460dce01200341106a41146a41303602002003411c6a4130360200200341d8006a41146a41033602002003420337025c200341e8a3c600360258200341013602142003200341106a3602682003200336022020032003412f6a3602182003200341286a360210200341386a200341d8006a10330cb4010b200341d8006a2001200241046a28020041044100108d052003280258450dcd0120002003290358370200200041086a200341d8006a41086a2802003602000cce010b200341d8006a2001200241046a28020041084101108d052003280258450dcc0120002003290358370200200041086a200341d8006a41086a2802003602000ccd010b200341d8006a2001200241046a28020041044102108d052003280258450dcb0120002003290358370200200041086a200341d8006a41086a2802003602000ccc010b200341d8006a2001200241046a28020041084103108d052003280258450dca0120002003290358370200200041086a200341d8006a41086a2802003602000ccb010b200341d8006a2001200241046a28020041014100108d052003280258450dc90120002003290358370200200041086a200341d8006a41086a2802003602000cca010b200341d8006a2001200241046a28020041014100108d052003280258450dc80120002003290358370200200041086a200341d8006a41086a2802003602000cc9010b200341d8006a2001200241046a28020041024100108d052003280258450dc70120002003290358370200200041086a200341d8006a41086a2802003602000cc8010b200341d8006a2001200241046a28020041024100108d052003280258450dc60120002003290358370200200041086a200341d8006a41086a2802003602000cc7010b200341d8006a2001200241046a28020041014101108d052003280258450dc50120002003290358370200200041086a200341d8006a41086a2802003602000cc6010b200341d8006a2001200241046a28020041014101108d052003280258450dc40120002003290358370200200041086a200341d8006a41086a2802003602000cc5010b200341d8006a2001200241046a28020041024101108d052003280258450dc30120002003290358370200200041086a200341d8006a41086a2802003602000cc4010b200341d8006a2001200241046a28020041024101108d052003280258450dc20120002003290358370200200041086a200341d8006a41086a2802003602000cc3010b200341d8006a2001200241046a28020041044101108d052003280258450dc10120002003290358370200200041086a200341d8006a41086a2802003602000cc2010b200341d8006a2001200241046a28020041044101108d052003280258450dc00120002003290358370200200041086a200341d8006a41086a2802003602000cc1010b200341d8006a2001200241046a28020041044100108e052003280258450dbf0120002003290358370200200041086a200341d8006a41086a2802003602000cc0010b200341d8006a2001200241046a28020041084101108e052003280258450dbe0120002003290358370200200041086a200341d8006a41086a2802003602000cbf010b200341d8006a2001200241046a28020041044102108e052003280258450dbd0120002003290358370200200041086a200341d8006a41086a2802003602000cbe010b200341d8006a2001200241046a28020041084103108e052003280258450dbc0120002003290358370200200041086a200341d8006a41086a2802003602000cbd010b200341d8006a2001200241046a28020041014100108e052003280258450dbb0120002003290358370200200041086a200341d8006a41086a2802003602000cbc010b200341d8006a2001200241046a28020041024100108e052003280258450dba0120002003290358370200200041086a200341d8006a41086a2802003602000cbb010b200341d8006a2001200241046a28020041014101108e052003280258450db90120002003290358370200200041086a200341d8006a41086a2802003602000cba010b200341d8006a2001200241046a28020041024101108e052003280258450db80120002003290358370200200041086a200341d8006a41086a2802003602000cb9010b200341d8006a2001200241046a28020041044101108e052003280258450db70120002003290358370200200041086a200341d8006a41086a2802003602000cb8010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c20034194abc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103320032802102202450d002003290214210b0c010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db701200241017422052004200520044b1b22044100480db7010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9801200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb8010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db7012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450db701200329023c210b0b2000200b370204200020023602000cb7010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c20034194abc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103320032802102202450d002003290214210b0c010b200341d8006a200141186a2204200141286a4100108905024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490db701200241017422062005200620054b1b22054100480db7010240024020020d002005102821020c010b200428020020022005102c21020b2002450d9901200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb8010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450db7012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450db701200329023c210b0c010b200328025c2202450db601200341e0006a290300210b0b2000200b370204200020023602000cb6010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db401200241017422052004200520044b1b22044100480db4010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb5010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db4012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450db4012000200329023c370204200020013602000cb5010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db301200241017422052004200520044b1b22044100480db3010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000cb4010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db3012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450db3012000200329023c370204200020013602000cb4010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db201200241017422052004200520044b1b22044100480db2010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000cb3010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db2012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450db2012000200329023c370204200020013602000cb3010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db101200241017422052004200520044b1b22044100480db1010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000cb2010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db1012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450db1012000200329023c370204200020013602000cb2010b200341d8006a20014100108f052003280258450db00120002003290358370200200041086a200341d8006a41086a2802003602000cb1010b200341d8006a200141001090052003280258450daf0120002003290358370200200041086a200341d8006a41086a2802003602000cb0010b200341d8006a200141001090052003280258450dae0120002003290358370200200041086a200341d8006a41086a2802003602000caf010b200341d8006a200141001090052003280258450dad0120002003290358370200200041086a200341d8006a41086a2802003602000cae010b200341d8006a200141001090052003280258450dac0120002003290358370200200041086a200341d8006a41086a2802003602000cad010b200341d8006a200141001090052003280258450dab0120002003290358370200200041086a200341d8006a41086a2802003602000cac010b200341d8006a200141001090052003280258450daa0120002003290358370200200041086a200341d8006a41086a2802003602000cab010b200341d8006a200141001090052003280258450da90120002003290358370200200041086a200341d8006a41086a2802003602000caa010b200341d8006a200141001090052003280258450da80120002003290358370200200041086a200341d8006a41086a2802003602000ca9010b200341d8006a200141001090052003280258450da70120002003290358370200200041086a200341d8006a41086a2802003602000ca8010b200341d8006a200141001090052003280258450da60120002003290358370200200041086a200341d8006a41086a2802003602000ca7010b200341d8006a20014101108f052003280258450da50120002003290358370200200041086a200341d8006a41086a2802003602000ca6010b200341d8006a200141011090052003280258450da40120002003290358370200200041086a200341d8006a41086a2802003602000ca5010b200341d8006a200141011090052003280258450da30120002003290358370200200041086a200341d8006a41086a2802003602000ca4010b200341d8006a200141011090052003280258450da20120002003290358370200200041086a200341d8006a41086a2802003602000ca3010b200341d8006a200141011090052003280258450da10120002003290358370200200041086a200341d8006a41086a2802003602000ca2010b200341d8006a200141011090052003280258450da00120002003290358370200200041086a200341d8006a41086a2802003602000ca1010b200341d8006a200141011090052003280258450d9f0120002003290358370200200041086a200341d8006a41086a2802003602000ca0010b200341d8006a200141011090052003280258450d9e0120002003290358370200200041086a200341d8006a41086a2802003602000c9f010b200341d8006a200141011090052003280258450d9d0120002003290358370200200041086a200341d8006a41086a2802003602000c9e010b200341d8006a200141011090052003280258450d9c0120002003290358370200200041086a200341d8006a41086a2802003602000c9d010b200341d8006a200141011090052003280258450d9b0120002003290358370200200041086a200341d8006a41086a2802003602000c9c010b200341d8006a200141021090052003280258450d9a0120002003290358370200200041086a200341d8006a41086a2802003602000c9b010b200341d8006a200141021090052003280258450d990120002003290358370200200041086a200341d8006a41086a2802003602000c9a010b200341d8006a200141021090052003280258450d980120002003290358370200200041086a200341d8006a41086a2802003602000c99010b200341d8006a200141021090052003280258450d970120002003290358370200200041086a200341d8006a41086a2802003602000c98010b200341d8006a200141021090052003280258450d960120002003290358370200200041086a200341d8006a41086a2802003602000c97010b200341d8006a200141021090052003280258450d950120002003290358370200200041086a200341d8006a41086a2802003602000c96010b200341d8006a200141031090052003280258450d940120002003290358370200200041086a200341d8006a41086a2802003602000c95010b200341d8006a200141031090052003280258450d930120002003290358370200200041086a200341d8006a41086a2802003602000c94010b200341d8006a200141031090052003280258450d920120002003290358370200200041086a200341d8006a41086a2802003602000c93010b200341d8006a200141031090052003280258450d910120002003290358370200200041086a200341d8006a41086a2802003602000c92010b200341d8006a200141031090052003280258450d900120002003290358370200200041086a200341d8006a41086a2802003602000c91010b200341d8006a200141031090052003280258450d8f0120002003290358370200200041086a200341d8006a41086a2802003602000c90010b200341d8006a200141001091052003280258450d8e0120002003290358370200200041086a200341d8006a41086a2802003602000c8f010b200341d8006a200141001091052003280258450d8d0120002003290358370200200041086a200341d8006a41086a2802003602000c8e010b200341d8006a200141001091052003280258450d8c0120002003290358370200200041086a200341d8006a41086a2802003602000c8d010b200341d8006a200141001092052003280258450d8b0120002003290358370200200041086a200341d8006a41086a2802003602000c8c010b200341d8006a200141001092052003280258450d8a0120002003290358370200200041086a200341d8006a41086a2802003602000c8b010b200341d8006a200141001092052003280258450d890120002003290358370200200041086a200341d8006a41086a2802003602000c8a010b200341d8006a200141001092052003280258450d880120002003290358370200200041086a200341d8006a41086a2802003602000c89010b200341d8006a200141001092052003280258450d870120002003290358370200200041086a200341d8006a41086a2802003602000c88010b200341d8006a200141001092052003280258450d860120002003290358370200200041086a200341d8006a41086a2802003602000c87010b200341d8006a200141001092052003280258450d850120002003290358370200200041086a200341d8006a41086a2802003602000c86010b200341d8006a200141001092052003280258450d840120002003290358370200200041086a200341d8006a41086a2802003602000c85010b200341d8006a200141001092052003280258450d830120002003290358370200200041086a200341d8006a41086a2802003602000c84010b200341d8006a200141001092052003280258450d820120002003290358370200200041086a200341d8006a41086a2802003602000c83010b200341d8006a200141001092052003280258450d810120002003290358370200200041086a200341d8006a41086a2802003602000c82010b200341d8006a200141001092052003280258450d800120002003290358370200200041086a200341d8006a41086a2802003602000c81010b200341d8006a200141001092052003280258450d7f20002003290358370200200041086a200341d8006a41086a2802003602000c80010b200341d8006a200141001092052003280258450d7e20002003290358370200200041086a200341d8006a41086a2802003602000c7f0b200341d8006a200141001092052003280258450d7d20002003290358370200200041086a200341d8006a41086a2802003602000c7e0b200341d8006a200141011091052003280258450d7c20002003290358370200200041086a200341d8006a41086a2802003602000c7d0b200341d8006a200141011091052003280258450d7b20002003290358370200200041086a200341d8006a41086a2802003602000c7c0b200341d8006a200141011091052003280258450d7a20002003290358370200200041086a200341d8006a41086a2802003602000c7b0b200341d8006a200141011092052003280258450d7920002003290358370200200041086a200341d8006a41086a2802003602000c7a0b200341d8006a200141011092052003280258450d7820002003290358370200200041086a200341d8006a41086a2802003602000c790b200341d8006a200141011092052003280258450d7720002003290358370200200041086a200341d8006a41086a2802003602000c780b200341d8006a200141011092052003280258450d7620002003290358370200200041086a200341d8006a41086a2802003602000c770b200341d8006a200141011092052003280258450d7520002003290358370200200041086a200341d8006a41086a2802003602000c760b200341d8006a200141011092052003280258450d7420002003290358370200200041086a200341d8006a41086a2802003602000c750b200341d8006a200141011092052003280258450d7320002003290358370200200041086a200341d8006a41086a2802003602000c740b200341d8006a200141011092052003280258450d7220002003290358370200200041086a200341d8006a41086a2802003602000c730b200341d8006a200141011092052003280258450d7120002003290358370200200041086a200341d8006a41086a2802003602000c720b200341d8006a200141011092052003280258450d7020002003290358370200200041086a200341d8006a41086a2802003602000c710b200341d8006a200141011092052003280258450d6f20002003290358370200200041086a200341d8006a41086a2802003602000c700b200341d8006a200141011092052003280258450d6e20002003290358370200200041086a200341d8006a41086a2802003602000c6f0b200341d8006a200141011092052003280258450d6d20002003290358370200200041086a200341d8006a41086a2802003602000c6e0b200341d8006a200141011092052003280258450d6c20002003290358370200200041086a200341d8006a41086a2802003602000c6d0b200341d8006a200141011092052003280258450d6b20002003290358370200200041086a200341d8006a41086a2802003602000c6c0b200341d8006a200141021091052003280258450d6a20002003290358370200200041086a200341d8006a41086a2802003602000c6b0b200341d8006a200141021091052003280258450d6920002003290358370200200041086a200341d8006a41086a2802003602000c6a0b200341d8006a200141021091052003280258450d6820002003290358370200200041086a200341d8006a41086a2802003602000c690b200341d8006a200141021091052003280258450d6720002003290358370200200041086a200341d8006a41086a2802003602000c680b200341d8006a200141021091052003280258450d6620002003290358370200200041086a200341d8006a41086a2802003602000c670b200341d8006a200141021091052003280258450d6520002003290358370200200041086a200341d8006a41086a2802003602000c660b200341d8006a200141021091052003280258450d6420002003290358370200200041086a200341d8006a41086a2802003602000c650b200341d8006a200141021092052003280258450d6320002003290358370200200041086a200341d8006a41086a2802003602000c640b200341d8006a200141021092052003280258450d6220002003290358370200200041086a200341d8006a41086a2802003602000c630b200341d8006a200141021092052003280258450d6120002003290358370200200041086a200341d8006a41086a2802003602000c620b200341d8006a200141021092052003280258450d6020002003290358370200200041086a200341d8006a41086a2802003602000c610b200341d8006a200141021092052003280258450d5f20002003290358370200200041086a200341d8006a41086a2802003602000c600b200341d8006a200141021092052003280258450d5e20002003290358370200200041086a200341d8006a41086a2802003602000c5f0b200341d8006a200141021092052003280258450d5d20002003290358370200200041086a200341d8006a41086a2802003602000c5e0b200341d8006a200141031091052003280258450d5c20002003290358370200200041086a200341d8006a41086a2802003602000c5d0b200341d8006a200141031091052003280258450d5b20002003290358370200200041086a200341d8006a41086a2802003602000c5c0b200341d8006a200141031091052003280258450d5a20002003290358370200200041086a200341d8006a41086a2802003602000c5b0b200341d8006a200141031091052003280258450d5920002003290358370200200041086a200341d8006a41086a2802003602000c5a0b200341d8006a200141031091052003280258450d5820002003290358370200200041086a200341d8006a41086a2802003602000c590b200341d8006a200141031091052003280258450d5720002003290358370200200041086a200341d8006a41086a2802003602000c580b200341d8006a200141031091052003280258450d5620002003290358370200200041086a200341d8006a41086a2802003602000c570b200341d8006a200141031092052003280258450d5520002003290358370200200041086a200341d8006a41086a2802003602000c560b200341d8006a200141031092052003280258450d5420002003290358370200200041086a200341d8006a41086a2802003602000c550b200341d8006a200141031092052003280258450d5320002003290358370200200041086a200341d8006a41086a2802003602000c540b200341d8006a200141031092052003280258450d5220002003290358370200200041086a200341d8006a41086a2802003602000c530b200341d8006a200141031092052003280258450d5120002003290358370200200041086a200341d8006a41086a2802003602000c520b200341d8006a200141031092052003280258450d5020002003290358370200200041086a200341d8006a41086a2802003602000c510b200341d8006a200141031092052003280258450d4f20002003290358370200200041086a200341d8006a41086a2802003602000c500b200341d8006a2001410141001093052003280258450d4e20002003290358370200200041086a200341d8006a41086a2802003602000c4f0b200341d8006a2001410241001093052003280258450d4d20002003290358370200200041086a200341d8006a41086a2802003602000c4e0b200341d8006a2001410241001093052003280258450d4c20002003290358370200200041086a200341d8006a41086a2802003602000c4d0b200341d8006a2001410341001093052003280258450d4b20002003290358370200200041086a200341d8006a41086a2802003602000c4c0b200341d8006a2001410341001093052003280258450d4a20002003290358370200200041086a200341d8006a41086a2802003602000c4b0b200341d8006a2001410041011093052003280258450d4920002003290358370200200041086a200341d8006a41086a2802003602000c4a0b200341d8006a2001410041011093052003280258450d4820002003290358370200200041086a200341d8006a41086a2802003602000c490b200341d8006a2001410241011093052003280258450d4720002003290358370200200041086a200341d8006a41086a2802003602000c480b200341d8006a2001410241011093052003280258450d4620002003290358370200200041086a200341d8006a41086a2802003602000c470b200341d8006a2001410341011093052003280258450d4520002003290358370200200041086a200341d8006a41086a2802003602000c460b200341d8006a2001410341011093052003280258450d4420002003290358370200200041086a200341d8006a41086a2802003602000c450b200341d8006a2001410041021093052003280258450d4320002003290358370200200041086a200341d8006a41086a2802003602000c440b200341d8006a2001410041021093052003280258450d4220002003290358370200200041086a200341d8006a41086a2802003602000c430b200341d8006a2001410141021093052003280258450d4120002003290358370200200041086a200341d8006a41086a2802003602000c420b200341d8006a2001410141021093052003280258450d4020002003290358370200200041086a200341d8006a41086a2802003602000c410b200341d8006a2001410341021093052003280258450d3f20002003290358370200200041086a200341d8006a41086a2802003602000c400b200341d8006a2001410041031093052003280258450d3e20002003290358370200200041086a200341d8006a41086a2802003602000c3f0b200341d8006a2001410041031093052003280258450d3d20002003290358370200200041086a200341d8006a41086a2802003602000c3e0b200341d8006a2001410141031093052003280258450d3c20002003290358370200200041086a200341d8006a41086a2802003602000c3d0b200341d8006a2001410141031093052003280258450d3b20002003290358370200200041086a200341d8006a41086a2802003602000c3c0b200341d8006a2001410241031093052003280258450d3a20002003290358370200200041086a200341d8006a41086a2802003602000c3b0b200341d8006a2001410241001093052003280258450d3920002003290358370200200041086a200341d8006a41086a2802003602000c3a0b200341d8006a2001410341011093052003280258450d3820002003290358370200200041086a200341d8006a41086a2802003602000c390b200341d8006a2001410041021093052003280258450d3720002003290358370200200041086a200341d8006a41086a2802003602000c380b200341d8006a20014101410310930520032802580d1b0c360b411841011037000b200941011037000b200541041037000b200541041037000b200641041037000b411841011037000b411a41011037000b200641041037000b411841011037000b200341ec006a41013602002003420237025c200341b0a3c6003602582003413136023c2003200441056a3602382003200341386a360268200341106a200341d8006a1033200041086a200341106a41086a280200360200200020032903103702000c2d0b200741011037000b200641011037000b200641011037000b200541011037000b200641011037000b200441011037000b200541011037000b200541011037000b200541011037000b200641011037000b200441011037000b200441011037000b200541011037000b200441011037000b200441011037000b200441011037000b200441011037000b20002003290358370200200041086a200341d8006a41086a2802003602000c1b0b200329023c210b200328023821010b2001450d182000200b370204200020013602000c190b200329023c210b200328023821010b2001450d162000200b370204200020013602000c170b200328025c2201450d150b2000200b370204200020013602000c150b2004450d132001290200210b0b2000200b370204200020043602000c130b02400240024002400240200141306a2802002202417f6a220420024f0d00200420024b0d00200128022820044103746a22052802002204200141206a220628020022024b0d01200421010c020b411810282200450d022003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c200320013602584193a2c600413b200341d8006a41d0a2c6001038000b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d132007410174220a2009200a20094b1b22094100480d130240024020070d002009102821070c010b200128021820072009102c21070b2007450d03200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a22021099051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c130b411841011037000b200941011037000b200641027421060340200320042802002205360248200220054d0d0220022005417f736a220520024f0d060240200720054103746a22052d00044103460d0020052d00054104470d040b200441046a21042006417c6a22060d000b410421090b200341d8006a200141186a2202200d410010890520032d00584101470d02200341086a200341e4006a2802003602002003200329025c3703000c030b200341ec006a220441023602002003411c6a41013602002003420237025c200341b0adc60036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1033200328023821022003200329023c37021420032002360210200441013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b2003200329023c370204200320032802383602000c020b2003411c6a4131360200200341ec006a41023602002003420237025c200341c0a3c6003602582003200541056a360218200341313602142003200341106a3602682003200341306a3602102003200341d8006a10330c010b0240200941ff01714104460d00200341d8006a2002200d200910890502400240024020032d00584101460d000240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490d10200441017422062005200620054b1b22054100480d100240024020040d002005102821020c010b200228020020042005102c21020b2002450d04200120023602182001411c6a2005360200200141206a28020021040b200128021820046a20093a0000200141206a2202200228020041016a3602000c040b200341ec006a220241013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102204450d032003200329021437021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450d03200329023c210b0c010b200328025c2202450d02200341e0006a290300210b0b2003200b370204200320023602000c020b200541011037000b200341003602000b024020032802002202450d0020002003290204370204200020023602000c0d0b0240024002400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810282200450d012003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c200320013602584193a2c600413b200341d8006a41d0a2c6001038000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d0d2007410174220a2009200a20094b1b22094100480d0d0240024020070d002009102821070c010b200128021820072009102c21070b2007450d03200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a22021099051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c0d0b411841011037000b200941011037000b41f2adc600411d1050000b20032802382202450d00200329023c210b0c010b200141306a2802002202417f6a220420024f0d01200420024b0d01200128022820044103746a22052802002204200141206a220628020022024b0d02200421010c030b2000200b370204200020023602000c080b411810282200450d022003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c200320013602584193a2c600413b200341d8006a41d0a2c6001038000b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d042007410174220a2009200a20094b1b22094100480d040240024020070d002009102821070c010b200128021820072009102c21070b2007450d03200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a22021099051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c040b411841011037000b200941011037000b1031000b200341d8006a200141186a2006108a052003280258450d0020002003290358370200200041086a200341d8006a41086a2802003602000c010b200041003602000b200341f0006a24000b6401017f230041206b2202240020024132360204200220003602002001411c6a2802002100200128021821012002411c6a41013602002002420137020c200241b0aec6003602082002200236021820012000200241086a10352101200241206a240020010b810101017f024002400240200041046a280200220320016b20024f0d00200120026a22022001490d02200341017422012002200120024b1b22014100480d020240024020030d002001102821020c010b200028020020032001102c21020b2002450d0120002002360200200041046a20013602000b0f0b200141011037000b1031000bd90101017f230041e0006b22042400200420013602082004200336020c024020012003470d00200020022001109a051a200441e0006a24000f0b200441286a41146a4108360200200441346a4125360200200441106a41146a410336020020044203370214200441c8afc6003602102004412536022c2004200441086a36024020042004410c6a360244200442043703582004420137024c2004419cb0c6003602482004200441286a3602202004200441c8006a3602382004200441c4006a3602302004200441c0006a360228200441106a41d8b0c600103e000bb90601037f230041d0006b22042400200420033a000f0240024002400240024020022802082205417f6a220620054f0d00200620054d0d010b411810282202450d012004421837023420042002360230200441306a4100411810870520042004280238220241186a3602382002200428023022056a41184196adc6004118108805200420042902343702342004200536023041e0a2c6004134200441306a41d0a2c6001038000b200141086a2802002105200228020020064103746a2206280200210202400240024020062d0006450d0020052002460d010b024002400240200520024d0d00200141086a2005417f6a2202360200200128020020026a2d00002205417c6a220241014b0d02024020020e020400040b4118102822020d01411841011037000b412b10282202450d05200041013a0000200241276a41002800fea646360000200241206a41002900f7a646370000200241186a41002900efa646370000200241106a41002900e7a646370000200241086a41002900dfa646370000200241002900d7a646370000200041086a42ab808080b005370200200041046a20023602000c060b200241106a41002900a6ad46370000200241086a410029009ead4637000020024100290096ad4637000020044298808080800337022420042002360220200441c4006a410136020020044201370234200441c4a7c6003602302004412836024c2004200441c8006a3602402004200441206a360248200441106a200441306a103302402004280224450d002004280220102a0b200041013a0000200041046a20042903103702002000410c6a200441106a41086a2802003602000c050b0240200341ff017122024104460d0020052002470d020b200041003a0000200020053a00010c040b20004180083b01000c030b200420053a0048200441c4006a4102360200200441206a410c6a41303602002004420237023420044184a7c600360230200441303602242004200441206a3602402004200441c8006a36022820042004410f6a360220200441106a200441306a10332000410c6a200441186a280200360200200041046a2004290310370200200041013a00000c020b411841011037000b412b41011037000b200441d0006a24000bbd0502047f017e230041d0006b22032400024002400240024002400240200241086a2802002204417f6a220520044f0d00200520044d0d010b411810282202450d01200241106a41002900a6ad46370000200241086a410029009ead4637000020024100290096ad4637000020034298808080800337022420032002360220200341cc006a41013602002003420137023c200341c4a7c600360238200341283602142003200341106a3602482003200341206a3602102000200341386a10332003280224450d042003280220102a0c040b0240024002402002280200220620054103746a2d000522054104460d00200341386a200120022005108905024020032d00384101470d002000200329023c370200200041086a200341c4006a2802003602000c070b200241086a2802002204450d01200228020021060b200241086a2004417f6a2202360200200620024103746a290200220742808080808080c0ff0083428080808080808001520d010b411810282202450d02200241106a41002900a6ad46370000200241086a410029009ead4637000020024100290096ad4637000020034298808080800337022420032002360220200341cc006a41013602002003420137023c200341c4a7c600360238200341283602142003200341106a3602482003200341206a3602102000200341386a10332003280224450d042003280220102a0c040b200141086a28020021022003200737030820022007a7470d02200041003602000c030b411841011037000b411841011037000b200341cc006a41023602002003412c6a41013602002003420237023c200341a4a6c60036023820034101360224200320023602342003200341206a3602482003200341086a3602282003200341346a360220200341106a200341386a1033200041086a200341106a41086a280200360200200020032903103702000b200341d0006a24000bac0301057f230041c0006b2203240020032002360200024002402001280204220420024b0d002001280208417c6a21052001410c6a280200410374210102400340024020010d00200320043602042003412c6a4102360200200341306a410c6a41013602002003420337021c200341f0aec600360218200341013602342003200341306a3602282003200341046a36023820032003360230200341086a200341186a10332000410c6a200341106a280200360200200041046a2003290308370200200041013a00000c040b02402004200541046a2802006a220620044f0d00412010282204450d02200041013a0000200441186a41002900e8ae46370000200441106a41002900e0ae46370000200441086a41002900d8ae46370000200441002900d0ae46370000200041086a42a08080808004370200200041046a20043602000c040b200141786a2101200541086a2105200420024b21072006210420070d0020062104200620024d0d000b20052d00002104200041003a0000200020043a00010c020b412041011037000b200041003a00002000200128020020026a2d00003a00010b200341c0006a24000bbd0201037f230041106b220224000240024020002d00004104470d00200220012802184181a5c60041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b200220012802184184a5c60041082001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a418ca5c600105d210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841f4afc00041012004411c6a28020028020c1100000d010b2001280200220028021841c8a4c60041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470bfe0501037f230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200541386a200141186a2203200141286a410010890520052d00384101470d012000200529023c370200200041086a200541c4006a2802003602000c020b200541cc006a41023602002005411c6a41013602002005420337023c20054180a4c600360238200541013602142005200541106a36024820052005410c6a3602182005200541086a360210200541206a200541386a1033200041086a200541206a41086a280200360200200020052903203702000c010b2001280200210220054100360220024020022802080d00200541cc006a41013602002005420237023c20054194abc600360238200541013602342005200541306a3602482005200541206a360230200541106a200541386a103320052802102202450d0020002005290214370204200020023602000c010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d03200241017422072006200720064b1b22064100480d030240024020020d002006102821020c010b200328020020022006102c21020b2002450d02200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2202200228020041016a3602000c030b200541cc006a220241013602002005420137023c20054190aec60036023820054101360234200520063602302005200541306a360248200541106a200541386a103320052802102201450d022005200529021437021420052001360210200241013602002005420137023c200541c4a7c600360238200541283602342005200541306a3602482005200541106a360230200541206a200541386a103302402005280214450d002005280210102a0b20052802202202450d0220002005290224370204200020023602000c030b200641011037000b1031000b200041003602000b200541d0006a24000bae0301017f230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200128020021022005410036023420022802080d01200541cc006a41013602002005420237023c20054194abc600360238200541013602142005200541106a3602482005200541346a360210200541206a200541386a103320052802202202450d0120002005290224370204200020023602000c020b200541cc006a41023602002005412c6a41013602002005420337023c20054180a4c600360238200541013602242005200541206a36024820052005410c6a3602282005200541086a360220200541106a200541386a1033200041086a200541106a41086a280200360200200020052903103702000c010b200541386a200141186a2202200141286a22032004108905024020052d00384101470d002000200529023c370200200041086a200541c4006a2802003602000c010b200541386a200220034100108905024020052d00384101470d002000200529023c370200200041086a200541c4006a2802003602000c010b200041003602000b200541d0006a24000be50301047f230041c0006b22032400200341286a200141186a2204200141286a20021089050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d03200241017422062005200620054b1b22054100480d030240024020020d002005102821020c010b200428020020022005102c21020b2002450d02200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c20034190aec60036022820034101360214200320053602102003200341106a360238200341186a200341286a103320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341c4a7c600360228200341283602142003200341106a3602382003200341186a3602102003200341286a10330240200328021c450d002003280218102a0b20032802002201450d0220002003290204370204200020013602000c030b200541011037000b1031000b200041003602000b200341c0006a24000b9e0401047f230041c0006b22032400200341286a200141186a2204200141286a220520021089050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b200341286a200420052002108905024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d03200241017422062005200620054b1b22054100480d030240024020020d002005102821020c010b200428020020022005102c21020b2002450d02200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c20034190aec60036022820034101360214200320053602102003200341106a360238200341186a200341286a103320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341c4a7c600360228200341283602142003200341106a3602382003200341186a3602102003200341286a10330240200328021c450d002003280218102a0b20032802002201450d0220002003290204370204200020013602000c030b200541011037000b1031000b200041003602000b200341c0006a24000be50301057f230041c0006b22032400200341286a200141186a2204200141286a20021089050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d03200541017422072006200720064b1b22064100480d030240024020050d002006102821050c010b200428020020052006102c21050b2005450d02200120053602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c20034190aec60036022820034101360214200320063602102003200341106a360238200341186a200341286a103320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341c4a7c600360228200341283602142003200341106a3602382003200341186a3602102003200341286a10330240200328021c450d002003280218102a0b20032802002201450d0220002003290204370204200020013602000c030b200641011037000b1031000b200041003602000b200341c0006a24000b9e0401057f230041c0006b22032400200341286a200141186a2204200141286a220520021089050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b200341286a200420052002108905024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d03200541017422072006200720064b1b22064100480d030240024020050d002006102821040c010b200428020020052006102c21040b2004450d02200120043602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c20034190aec60036022820034101360214200320063602102003200341106a360238200341186a200341286a103320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341c4a7c600360228200341283602142003200341106a3602382003200341186a3602102003200341286a10330240200328021c450d002003280218102a0b20032802002201450d0220002003290204370204200020013602000c030b200641011037000b1031000b200041003602000b200341c0006a24000be50301047f230041c0006b22042400200441286a200141186a2205200141286a20021089050240024020042d00284101470d002000200429022c370200200041086a200441346a2802003602000c010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d03200241017422072006200720064b1b22064100480d030240024020020d002006102821020c010b200528020020022006102c21020b2002450d02200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20033a0000200141206a2201200128020041016a3602000c030b2004413c6a220141013602002004420137022c20044190aec60036022820044101360214200420063602102004200441106a360238200441186a200441286a103320042802182202450d022004200429021c37021c20042002360218200141013602002004420137022c200441c4a7c600360228200441283602142004200441106a3602382004200441186a3602102004200441286a10330240200428021c450d002004280218102a0b20042802002201450d0220002004290204370204200020013602000c030b200641011037000b1031000b200041003602000b200441c0006a24000b02000b17000240200041046a280200450d002000280200102a0b0b15002000280200220028020020002802082001105f0b100020012000280200200028020810450bfb0101027f230041106b220224002002200128021841b8aec60041052001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41c0aec600105d1a20022d00082101024020022802042203450d00200141ff0171210041012101024020000d00024020034101470d0020022d000941ff0171450d00200228020022002d00004104710d0041012101200028021841f4afc00041012000411c6a28020028020c1100000d010b2002280200220128021841c8a4c60041012001411c6a28020028020c11000021010b200220013a00080b200241106a2400200141ff01714100470b2c01017f02402002450d00200021030340200320013a0000200341016a21032002417f6a22020d000b0b20000b3601017f02402002450d00200021030340200320012d00003a0000200341016a2103200141016a21012002417f6a22020d000b0b20000b7101017f0240024020012000490d002002450d01200021030340200320012d00003a0000200141016a2101200341016a21032002417f6a22020d000c020b0b2002450d002001417f6a21012000417f6a21030340200320026a200120026a2d00003a00002002417f6a22020d000b0b20000b4a01037f4100210302402002450d000240034020002d0000220420012d00002205470d01200141016a2101200041016a21002002417f6a2202450d020c000b0b200420056b21030b20030b5701017e02400240200341c000710d002003450d012001410020036b413f71ad8820022003413f71ad220486842102200120048621010c010b20012003413f71ad862102420021010b20002001370300200020023703080b5701017e02400240200341c000710d002003450d0120012003413f71ad2204882002410020036b413f71ad86842101200220048821020c010b20022003413f71ad882101420021020b20002001370300200020023703080b7501027e200020034220882205200142208822067e200320027e7c200420017e7c200342ffffffff0f832203200142ffffffff0f8322017e2204422088200320067e7c22034220887c200342ffffffff0f83200520017e7c22034220887c37030820002003422086200442ffffffff0f83843703000b3e01017f230041106b2205240020052001200220032004410010a205200529030021012000200541086a29030037030820002001370300200541106a24000b4c01017f230041206b22052400200542003703182005420037031020052001200220032004200541106a10a205200529031021012000200529031837030820002001370300200541206a24000be20502037f067e230041306b2206240002400240024002400240024002400240024002402002500d002003500d012004500d02200479a7200279a76b2207413f4b0d0341ff0020076b2108200741016a21070c080b02402004500d0020050d040c060b024002402005450d0020034200510d0620054200370308200520012003823703000c010b20034200510d050b200120038021010c060b2004500d030240024002402001500d0020047b4201510d01200479a7200279a76b2207413e4b0d0241ff0020076b2108200741016a21070c090b02402005450d0020054200370300200520022004823703080b200220048021010c070b02402005450d002005200137030020052004427f7c2002833703080b200220047a423f838821010c060b2005450d040c020b024020037b4201510d0041bf7f200379a7200279a76b22076b2108200741c1006a21070c060b02402005450d002005420037030820052003427f7c2001833703000b20034201510d06200641206a2001200220037aa7109e05200641286a2903002102200629032021010c060b2005450d020b2005200137030020052002370308420021010c020b00000b420021010b420021020c010b200620012002200841ff0071109d05200641106a20012002200741ff0071109e05200641086a2903002102200641106a41086a2903002109200629030021012006290310210a0240024020070d004200210b4200210c0c010b4200210c4200210d03402009420186200a423f8884220b200b427f8520047c200a4201862002423f8884220a427f85220b20037c200b54ad7c423f87220b2004837d200a200b200383220e54ad7d2109200a200e7d210a420020024201862001423f8884842102200d2001420186842101200b420183220b210d2007417f6a22070d000b0b02402005450d002005200a370300200520093703080b200c20024201862001423f8884842102200b20014201868421010b2000200137030020002002370308200641306a24000b0b9bb1060200418080c0000b80b1061800100011000000187f11001700000009030000050000006361706163697479206f766572666c6f77000000a00010004600000063010000130000003300000004000000040000003400000035000000360000006120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f72003700000000000000010000003800000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f666d742f6d6f642e72730101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020202020202020202020202020202020202020202020202020202020202030303030303030303030303030303030404040404000000000000000000000000000802100020000000280210001200000037000000000000000100000039000000696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e646578206973203030303130323033303430353036303730383039313031313132313331343135313631373138313932303231323232333234323532363237323832393330333133323333333433353336333733383339343034313432343334343435343634373438343935303531353235333534353535363537353835393630363136323633363436353636363736383639373037313732373337343735373637373738373938303831383238333834383538363837383838393930393139323933393439353936393739383939000024031000060000002a031000220000006898110018000000170a000005000000696e64657820206f7574206f662072616e676520666f7220736c696365206f66206c656e677468206c03100016000000820310000d00000068981100180000001d0a000005000000736c69636520696e64657820737461727473206174202062757420656e6473206174206030785b2e2e2e5d00560410000b00000002171000160000008f0310000100000040041000160000000308000009000000e01610000e000000ee16100004000000f2161000100000008f0310000100000040041000160000000708000005000000a01610002b000000cb161000150000007a01000015000000560410000b000000610410002600000087041000080000008f041000060000008f03100001000000400410001600000014080000050000007372632f6c6962636f72652f7374722f6d6f642e72736279746520696e64657820206973206e6f742061206368617220626f756e646172793b20697420697320696e7369646520202862797465732029206f662060000000d604100002000000c0041000160000006204000011000000c00410001600000056040000280000007372632f6c6962636f72652f666d742f6d6f642e72732e2e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000f8030000000000000000000000000000000000000000000000000000000000000000feffffffffbfb6000000000000000000ff070000000000f8ffff0000010000000000000000000000c09f9f3d0000000002000000ffffff0700000000000000000000c0ff01000000000000f80f20801010004a000000d012100000020000d01410003a00000000010203040506070809080a0b0c0d0e0f10111213140215161718191a1b1c1d1e1f2002020202020202020202210202020202020202020202020202222324252602270228020202292a2b022c2d2e2f300202310202023202020202020202023302023402020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023502360237020202020202020238023902020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023a3b3c020202023d02023e3f4041424344454602020247020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202024802020202020202020202024902020202023b020001020202020302020202040205060202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020207020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200010305050606030706080809110a1c0b190c140d120e0d0f0410031212130916011705180219031a071c021d011f1620032b042c022d0b2e01300331023201a702a902aa04ab08fa02fb05fd04fe03ff09ad78798b8da23057588b8c901c1ddd0e0f4b4cfbfc2e2f3f5c5d5fb5e2848d8e9192a9b1babbc5c6c9cadee4e5ff00041112293134373a3b3d494a5d848e92a9b1b4babbc6cacecfe4e500040d0e11122931343a3b4546494a5e646584919b9dc9cecf0d112945495764658d91a9b4babbc5c9dfe4e5f0040d1145496465808184b2bcbebfd5d7f0f183858ba4a6bebfc5c7cecfdadb4898bdcdc6cecf494e4f57595e5f898e8fb1b6b7bfc1c6c7d71116175b5cf6f7feff800d6d71dedf0e0f1f6e6f1c1d5f7d7eaeafbbbcfa16171e1f46474e4f585a5c5e7e7fb5c5d4d5dcf0f1f572738f747596972f5f262e2fa7afb7bfc7cfd7df9a409798308f1fc0c1ceff4e4f5a5b07080f10272feeef6e6f373d3f42459091feff536775c8c9d0d1d8d9e7feff00205f2282df048244081b04061181ac0e80ab351e1580e003190801042f043404070301070607110a500f1207550802041c0a090308030703020303030c0405030b06010e15053a0311070605100757070207150d500443032d03010411060f0c3a041d255f206d046a2580c80582b0031a0682fd035907150b1709140c140c6a060a061a0659072b05460a2c040c040103310b2c041a060b0380ac060a061f414c042d0374083c030f033c0738082b0582ff1118082f112d032010210f808c048297190b158894052f053b07020e180980b030740c80d61a0c0580ff0580b605240c9bc60ad23010848d033709815c1480b80880c73035040a06380846080c06740b1e035a0459098083181c0a16094808808a06aba40c170431a10481da26070c050580a511816d1078282a064c04808d0480be031b030f0d0006010103010402080809020a050b02100111041205131114021502170219041c051d0824016a036b02bc02d102d40cd509d602d702da01e005e102e802ee20f004f906fa020c273b3e4e4f8f9e9e9f060709363d3e56f3d0d104141836375657bd35cecfe01287898e9e040d0e11122931343a4546494a4e4f64655a5cb6b71b1ca8a9d8d909379091a8070a3b3e66698f926f5feeef5a629a9b2728559da0a1a3a4a7a8adbabcc4060b0c151d3a3f4551a6a7cccda007191a22253e3fc5c604202325262833383a484a4c50535556585a5c5e606365666b73787d7f8aa4aaafb0c0d00c72a3a4cbcc6e6f5e227b0503042d036504012f2e80821d03310f1c0424091e052b0544040e2a80aa06240424042808340b018090813709160a088098390363080930160521031b05014038044b052f040a070907402027040c0936033a051a07040c07504937330d33072e080a81261f808128082a808617094e041e0f430e19070a0647092709750b3f412a063b050a0651060105100305808b602048080a80a65e22450b0a060d1339070a362c041080c03c64530c0180a0451b4808531d398107460a1d03474937030e080a0639070a81361980c7320d839b66750b80c48abc842f8fd18247a1b98239072a040260260a460a28051382b05b654b0439071140041c97f80882f3a50d811f3103110408818c89046b050d03090710936080f60a73086e1746809a140c570919808781470385420f1585502b80d52d031a040281703a0501850080d7294c040a04028311444c3d80c23c06010455051b3402810e2c04640c560a0d035d033d391d0d2c040907020e06809a83d60a0d030b05740c59070c140c0438080a0628081e527703310380a60c14040305030d06856a000000601010002000000027000000190000006010100020000000280000002000000060101000200000002a0000001900000060101000200000002b0000001800000060101000200000002c0000002000000000000000000000007372632f6c6962636f72652f756e69636f64652f626f6f6c5f747269652e72730000c0fbef3e00000000000e0000000000000000000000000000f8fffbffffff0700000000000014fe21fe000c00000002000000000000501e2080000c00004006000000000000108639020000002300be2100000c0000fc02000000000000d01e20c0000c0000000400000000000040012080000000000011000000000000c0c13d60000c0000000200000000000090443060000c00000003000000000000581e2080000c00000000845c8000000000000000000000f207807f000000000000000000000000f21f003f000000000000000000030000a002000000000000fe7fdfe0fffeffffff1f40000000000000000000000000e0fd66000000c301001e006420002000000000000000e00000000000001c0000001c0000000c0000000c00000000000000b03f40fe0f200000000000380000000000006000000000020000000000008701040e00008009000000000000407fe51ff89f000000000000ff7f0f0000000000f0170400000000f80f00030000003c3b00000000000040a303000000000000f0cf000000f7fffd211003fffffffffffffffb00100000000000000000ffffffff01000000000000800300000000000000008000000000ffffffff0000000000fc00000000000600000000000000000080f73f000000c0000000000000000000000300440800006000000030000000ffff038000000000c03f000080ff030000000000070000000000c833000000002000000000000000007e660008100000000000100000000000009dc1020000000030400000000000202100000000004000000000ffff0000ffff00000000000000000001000000020003000000000000000000000000000000000000000000000000000004000005000000000000000006000000000000000007000008090a000b0c0d0e0f000010111200001314151600001718191a1b001c0000001d0000000000001e1f202100000000002200230024252600000000270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002829000000000000000000000000000000002a2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000002d2e00002f0000000000000000000000000000000000000000000000000000000000003031320000000000000000000000000000000000000000003300000029000000000000340000000000000000000000000000000000000000000000350036000000000000000000000000000000000000000000000000000037380000383838390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000001000000000000000000c0076ef0000000000087000000006000000000000000f0000000c0ff01000000000002000000000000ff7f0000000000008003000000000078060700000080ef1f000000000000000800030000000000c07f001e000000000000000000000080d34000000080f8070000030000000000005801008000c01f1f0000000000000000ff5c00004000000000000000000000f9a50d000000000000000000000000803cb00100003000000000000000000000f8a70100000000000000000000000028bf00000000e0bc0f0000000000000080ff060000f00c01000000fe0700000000f87980007e0e0000000000fc7f03000000000000000000007fbf0000fcfffffc6d000000000000007eb4bf000000000000000000a3000000000000000000000018000000000000001f000000000000007f0000800000000000000080070000000000000000600000000000000000a0c307f8e70f0000003c00001c00000000000000ffffffffffff7ff8ffffffffff1f2000100000f8feff00007ffffff9db0700000000000000f0000000007f0000000000f00700000000000000000000ffffffffffffffffffffffffffffffffffff000063616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c75657372632f6c6962636f72652f6f7074696f6e2e7273626567696e203c3d20656e642028203c3d2029207768656e20736c6963696e672060206973206f7574206f6620626f756e6473206f66206066616c736574727565426f72726f774572726f72426f72726f774d75744572726f7270616e69636b6564206174200000711710000100000072171000030000003897110000000000701710000100000070171000010000003a27272c20000000cb16100015000000a60400000500000098171000150000008d040000050000007372632f6c6962636f72652f726573756c742e72735b5d0a3a0000000c000000040000003b0000003c0000003d0000002c0a2c203300000004000000040000003e0000003f0000004000000020202020207b20207b0a207d7d28280a2c0000003300000004000000040000004100000033000000040000000400000042000000557466384572726f7276616c69645f75705f746f6572726f725f6c656e00000033000000040000000400000043000000370000000000000001000000440000004500000046000000370000000000000001000000440000004500000046000000901810001e0000005074110013000000b903000009000000617373657274696f6e206661696c65643a20696e646578203c3d206c656e0000c81810001d0000005074110013000000e103000009000000617373657274696f6e206661696c65643a20696e646578203c206c656e0000000019100043000000f60a00003000000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962616c6c6f632f7665632e7273000019100043000000020b00002c0000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d7363616c652d636f6465632d312e302e352f7372632f636f6d706163742e72736865616420697320736574207768656e20666972737420656c656d656e7420697320696e7365727465640a090909090909616e6420756e736574207768656e206c61737420656c656d656e742069732072656d6f7665643b0a0909090909096966206865616420697320536f6d65207468656e20697420706f696e747320746f206578697374696e67206b65793b2071656470726576696f75732f6e657874206f6e6c7920636f6e7461696e206578697374696e6720656e74697265733b0a090909090909776520656e756d6572617465207573696e67206e6578743b20656e747279206578697374733b207165646f766572666c6f77206d756c7469706c79696e6720676173206c696d69742062792070726963650000003700000000000000010000004700000048000000490000004a0000004b0000004c0000000c1b1000330000003f1b10004b000000f600000005000000636f6e74726163742073756273797374656d20726573756c74696e6720696e20706f73697469766520696d62616c616e6365212f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f6163636f756e745f64622e72734f6666656e636573205265706f7274730000c01b100019000000e01b100048000000bb0100002d000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f6f70732f61726974682e7273616c726561647920626f72726f776564616c7265616479206d757461626c7920626f72726f7765643700000000000000010000004d0000003700000000000000010000004e000000387d110028000000881c10004300000055000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f6f6666656e6365732f7372632f6c69622e727300881c1000430000005500000001000000551d10003600000054191000630000005e01000005000000000000000000000000000000181d10003d00000054191000630000006501000005000000736869667465642073756666696369656e74206269747320726967687420746f206c656164206f6e6c79206c656164696e67207a65726f733b2071656450726576696f7573206d617463682061726d206d61746368657320616e7974696e67206c657373207468616e20325e33303b2071656400551d10003600000054191000630000008a0100000500000000000000000000000000000000000000000000005419100063000000910100000500000053657373696f6e20486973746f726963616c53657373696f6e734c696e6b616765206973207570646174656420696e206361736520656e7472792069732072656d6f7665643b0a0909090909697420616c7761797320706f696e747320746f206578697374696e67206b6579733b20716564000000000000441f10000700000001010000000000004b1f10000d00000000000000581f10003400000000000000000000000000000000000000389711008c1f100000000000000000009c1f100001000000000000000000000000000000a41f10001600000002010100000000006f8c11000400000000000000738c11000e00000000000000ba1f1000120000000000000038971100cc1f10000000000000000000dc1f100001000000000000000100000000000000e41f10001200000001010000000000006f8c11000400000000000000e7ea1000070000000000000000000000000000000000000038971100f81f10000000000000000000082010000600000000000000010000005265706f7274735265706f727449644f663c543e4f6666656e636544657461696c733c543a3a4163636f756e7449642c20543a3a4964656e74696669636174696f6e5475706c653e3700000000000000010000004f000000a121100052000000436f6e63757272656e745265706f727473496e6465785665633c5265706f727449644f663c543e3e37000000000000000100000050000000572110004a0000005265706f72747342794b696e64496e646578000037000000000000000100000051000000382010004400000038971100000000007c2010002f0000003897110000000000ab20100052000000fd2010005a00000020456e756d65726174657320616c6c207265706f727473206f662061206b696e6420616c6f6e672077697468207468652074696d6520746865792068617070656e65642e20416c6c207265706f7274732061726520736f72746564206279207468652074696d65206f66206f6666656e63652e204e6f74652074686174207468652061637475616c2074797065206f662074686973206d617070696e6720697320605665633c75383e602c207468697320697320626563617573652076616c756573206f6620646966666572656e7420747970657320617265206e6f7420737570706f7274656420617420746865206d6f6d656e7420736f2077652061726520646f696e6720746865206d616e75616c2073657269616c697a6174696f6e2e204120766563746f72206f66207265706f727473206f66207468652073616d65206b696e6420746861742068617070656e6564206174207468652073616d652074696d6520736c6f742e20546865207072696d61727920737472756374757265207468617420686f6c647320616c6c206f6666656e6365207265636f726473206b65796564206279207265706f7274206964656e746966696572732e72656163686564206d6178696d756d2064657074682c2063616e6e6f7420696e7374616e7469617465520000001800000004000000530000005400000055000000560000005700000058000000696e73756666696369656e742072656d61696e696e672062616c616e6365416c69766520636f6e7472616374206f7220746f6d6273746f6e6520616c7265616479206578697374736e6f7420656e6f7567682067617320746f20706179206261736520696e7374616e7469617465206665656e6f7420656e6f7567682067617320746f20706179207472616e736665722066656572656163686564206d6178696d756d2064657074682c2063616e6e6f74206d616b6520612063616c6c6e6f7420656e6f7567682067617320746f2070617920626173652063616c6c20666565636f6e747261637420686173206265656e2065766963746564636f6e74726163742063616e6e6f742062652064657374726f79656420647572696e672072656375727369766520657865637574696f6e61206e657374656420657865637574696f6e20636f6e74657874206d7573742068617665206120706172656e743b20716564696d2d6f6e6c696e653a6f66666c696e4f6666656e63657320436f6e63757272656e745265706f727473496e6465780000005900000008000000040000005a0000007375627374726174652d6e6f64650000df6acb689907609b0200000037e397fc7c91f5e40100000040fe3ad401f8959a03000000d2bc9897eed08f1501000000f78b278be53f454c01000000ed99c5acb25eedf502000000cbca25e39f14238701000000687ad44ad37f03c201000000bc9d89904f5b923f0100000068b66ba122c93fa701000000ab3c0572291feb8b010000006772616e62616265696d6f6e0000000040787d010065cd1d00e1f505d85aae1ec0542205b0508f1f38e4750488467020d853e903603c5121d0bf760338323222a8591903402013236039cd02480ef423a82a8f0268f8d42470955c02b8dab525c05a3302d8c4962648bd1102e0b27727a855f601e8a05828e8fedf0180773929c0cacd01586d1a2af8f1be019053fb2a50d8b201d00edc2be0fca80138edbc2c48f2a001e06d9d2d80669a01c80d7e2e500f9501c0575e2f08b6900140323f30e0278d0148202031b0418a0108a3ff3120e8870120bedf32f0fb85013856c03398698401f0fda03478218301b8d87f35d8178201d8c26036183d8101b8223e37508d800188d21c38c8fc7f0168b5f93898877f01a829d139d8297f0120d6ab3ab8db7e0168ae803b389d7e0100ca9a3b68957e0100000000d3bc100006000000000000005b000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000005d0000000000000000000000000000005e0000000000000000000000000000003fa7100004000000000000005f000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000020000000000000000000000000000000000000060000000000000000000000000000000e7df10000900000000000000610000000000000000000000000000000000000000000000000000000000000062000000000000000000000002000000000000000000000000000000000000006300000000000000000000000000000095a410000a00000000000000640000000000000000000000000000000000000000000000000000000000000065000000000000000000000002000000000000000000000000000000000000005e00000000000000000000000000000045db1000070000000000000066000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000670000000000000000000000000000005e000000000000000000000000000000b239100008000000000000006800000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000006a0000000000000000000000000000006b000000000000000000000000000000d92d110007000000000000006c000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000006e0000000000000000000000000000006f000000000000000000000000000000158b1000070000000000000070000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000072000000000000000000000000000000730000000000000000000000000000007955110009000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000007600000000000000000000000000000077000000000000000000000000000000fe65100007000000000000007800000000000000000000000000000000000000000000000000000000000000790000000000000000000000000000007a0000000000000000000000000000005e000000000000000000000000000000382d100012000000000000007b00000000000000000000000000000000000000000000000000000000000000790000000000000000000000000000007a0000000000000000000000000000005e0000000000000000000000000000004a2d100009000000000000007c000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000007e0000000000000000000000000000007f000000000000000000000000000000532d10001300000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000820000000000000000000000000000005e000000000000000000000000000000662d10000f000000020000000000000000000000000000000000000000000000000000000000000000000000830000000000000000000000020000000000000000000000000000000000000084000000000000000000000000000000752d10000700000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000870000000000000000000000000000005e0000000000000000000000000000000596100008000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000008a0000000000000000000000000000008b0000000000000000000000000000007c2d100009000000000000008c000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000008e0000000000000000000000000000008f000000000000000000000000000000161311000400000000000000900000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000920000000000000000000000000000005e000000000000000000000000000000314610000800000000000000930000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000950000000000000000000000000000005e000000000000000000000000000000852d1000120000000200000000000000000000000000000000000000000000000000000000000000000000005e000000000000000000000002000000000000000000000000000000000000005e000000000000000000000000000000972d1000080000000000000096000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000970000000000000000000000000000005e0000000000000000000000546563686e6963616c436f6d6d6974746565456c656374696f6e73546563686e6963616c4d656d6265727368697046696e616c697479547261636b65724772616e647061436f6e747261637473417574686f72697479446973636f766572794f6666656e6365735365656420697320616e207574663820737472696e67000000e02d1000480000009b0a00000a000000e02d100048000000a10a00000e00000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000ac2e10000a00000000000000e0151100020000000000000000000000b82e1000010000000000000000000000c02e10000d00000000000000a8431100010000000000000000000000d02e100001000000000000000000000000ea10000800000000000000d82e1000040000000000000000000000f82e100001000000000000004e65774163636f756e740000432f10001b0000005265617065644163636f756e740000002c2f100017000000d043110009000000d04311000900000011441100070000001144110007000000002f10002c000000205472616e7366657220737563636565646564202866726f6d2c20746f2c2076616c75652c2066656573292e20416e206163636f756e7420776173207265617065642e2041206e6577206163636f756e742077617320637265617465642e76657374696e672062616c616e636520746f6f206869676820746f2073656e642076616c75656163636f756e74206c6971756964697479207265737472696374696f6e732070726576656e74207769746864726177616c62656e6566696369617279206163636f756e74206d757374207072652d6578697374746f6f2066657720667265652066756e647320696e206163636f756e747061796d656e7420776f756c64206b696c6c206163636f756e740000000000003c3010001100000000000000503010000100000000000000000000005830100001000000000000004865617274626561745265636569766564000000903010000b00000060301000300000002041206e657720686561727462656174207761732072656365697665642066726f6d2060417574686f72697479496460417574686f726974794964496d4f6e6c696e6520476f73736970417442616c616e63657320546f74616c49737375616e6365496d4f6e6c696e65204b65797342616c616e636573204672656542616c616e636542616c616e63657320526573657276656442616c616e636542616c616e636573204c6f636b7342616c616e6365732056657374696e6700000000000000a03110000800000000000000a8311000020000000000000000000000d8311000170000000000000000000000903210000b000000000000009c321000030000000000000000000000e43210000d00000000000000000000004c3310000e000000000000005c331000030000000000000000000000a433100002000000000000007472616e736665720000000046f1100004000000000000004b22110023000000000000005f55110005000000000000001934100013000000ed35100036000000389711000000000023361000420000006536100048000000ad36100045000000f23610002d00000038971100000000001f371000460000003897110000000000c54d11000b000000653710004c000000b137100033000000e43710005a00000038971100000000003e3810001300000038971100000000005138100054000000a53810004b000000f03810003500000025391000370000005c391000560000003897110000000000d84d11000c0000007365745f62616c616e636500000000005712110003000000000000004b2211002300000000000000d93510000800000000000000193410001300000000000000e13510000c0000000000000019341000130000002c34100025000000389711000000000051341000480000009934100042000000db34100046000000213510003a00000038971100000000005b3510002d0000003897110000000000c54d11000b0000008835100020000000a835100031000000d84d11000c000000666f7263655f7472616e736665720000000000001334100006000000000000004b221100230000000000000046f1100004000000000000004b22110023000000000000005f55110005000000000000001934100013000000b433100054000000083410000b0000002045786163746c7920617320607472616e73666572602c2065786365707420746865206f726967696e206d75737420626520726f6f7420616e642074686520736f75726365206163636f756e74206d6179206265207370656369666965642e736f75726365436f6d706163743c543a3a42616c616e63653e20536574207468652062616c616e636573206f66206120676976656e206163636f756e742e20546869732077696c6c20616c74657220604672656542616c616e63656020616e642060526573657276656442616c616e63656020696e2073746f726167652e2069742077696c6c20616c736f2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d202860546f74616c49737375616e636560292e20496620746865206e65772066726565206f722072657365727665642062616c616e63652069732062656c6f7720746865206578697374656e7469616c206465706f7369742c2069742077696c6c20726573657420746865206163636f756e74206e6f6e636520286073797374656d3a3a4163636f756e744e6f6e636560292e20546865206469737061746368206f726967696e20666f7220746869732063616c6c2069732060726f6f74602e202d20496e646570656e64656e74206f662074686520617267756d656e74732e202d20436f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e64207772697465732e6e65775f667265656e65775f7265736572766564205472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572206163636f756e742e20607472616e73666572602077696c6c207365742074686520604672656542616c616e636560206f66207468652073656e64657220616e642072656365697665722e2049742077696c6c2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d2062792074686520605472616e73666572466565602e204966207468652073656e6465722773206163636f756e742069732062656c6f7720746865206578697374656e7469616c206465706f736974206173206120726573756c74206f6620746865207472616e736665722c20746865206163636f756e742077696c6c206265207265617065642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605369676e65646020627920746865207472616e736163746f722e202d20446570656e64656e74206f6e20617267756d656e747320627574206e6f7420637269746963616c2c20676976656e2070726f70657220696d706c656d656e746174696f6e7320666f72202020696e70757420636f6e6669672074797065732e205365652072656c617465642066756e6374696f6e732062656c6f772e202d20497420636f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e642077726974657320696e7465726e616c6c7920616e64206e6f20636f6d706c657820636f6d7075746174696f6e2e2052656c617465642066756e6374696f6e733a2020202d2060656e737572655f63616e5f77697468647261776020697320616c776179732063616c6c656420696e7465726e616c6c792062757420686173206120626f756e64656420636f6d706c65786974792e2020202d205472616e7366657272696e672062616c616e63657320746f206163636f756e7473207468617420646964206e6f74206578697374206265666f72652077696c6c20636175736520202020202060543a3a4f6e4e65774163636f756e743a3a6f6e5f6e65775f6163636f756e746020746f2062652063616c6c65642e2020202d2052656d6f76696e6720656e6f7567682066756e64732066726f6d20616e206163636f756e742077696c6c2074726967676572202020202060543a3a4475737452656d6f76616c3a3a6f6e5f756e62616c616e6365646020616e642060543a3a4f6e4672656542616c616e63655a65726f3a3a6f6e5f667265655f62616c616e63655f7a65726f602e42616c616e636573000000000000743b10000d0000000000000000000000813b10000a0000000000000000000000000000000000000000000000000000000000000038971100543c100000000000000000008c3b100001000000000000000100000000000000943b10000700000001010000000000000b4e11000c000000000000009b3b10002b0000000000000000000000000000000000000038971100c83b10000000000000000000d83b100001000000000000000000000000000000e03b10000b00000001010000000000000b4e11000c00000000000000813b10000a0000000000000000000000000000000000000038971100543c10000000000000000000ec3b10000b000000000000000100000000000000443c10000f00000001010000000000000b4e11000c00000000000000813b10000a0000000000000000000000000000000000000038971100543c10000000000000000000643c10000b000000000000000100000000000000bc3c10000500000001010000000000000b4e11000c00000000000000c13c10002c0000000000000000000000000000000000000038971100f03c10000000000000000000003d1000010000000000000001000000546f74616c49737375616e6365543a3a42616c616e636500314210002600000056657374696e6756657374696e675363686564756c653c543a3a42616c616e63652c20543a3a426c6f636b4e756d6265723e00003700000000000000010000004f000000fb411000360000004672656542616c616e636500813f1000270000003897110000000000a83f100050000000f83f10005d0000005540100055000000aa4010004f000000f9401000510000004a4110001500000038971100000000005f41100057000000b641100045000000526573657276656442616c616e63650037000000000000000100000098000000363d10005d000000933d1000270000003897110000000000ba3d10005b000000153e10004900000038971100000000005e3e10005d000000bb3e10002d0000003897110000000000e83e1000530000003b3f1000460000004c6f636b735665633c42616c616e63654c6f636b3c543a3a42616c616e63652c20543a3a426c6f636b4e756d6265723e3e00000037000000000000000100000050000000083d10002e00000020416e79206c6971756964697479206c6f636b73206f6e20736f6d65206163636f756e742062616c616e6365732e2054686520616d6f756e74206f66207468652062616c616e6365206f66206120676976656e206163636f756e7420746861742069732065787465726e616c6c792072657365727665643b20746869732063616e207374696c6c2067657420736c61736865642c20627574206765747320736c6173686564206c617374206f6620616c6c2e20546869732062616c616e63652069732061202772657365727665272062616c616e63652074686174206f746865722073756273797374656d732075736520696e206f7264657220746f2073657420617369646520746f6b656e73207468617420617265207374696c6c20276f776e65642720627920746865206163636f756e7420686f6c6465722c20627574207768696368206172652073757370656e6461626c652e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e2074686973202772657365727665206163636f756e74272069732064656c657465643a207370656369666963616c6c792c2060526573657276656442616c616e6365602e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c6574656420696620604672656542616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e2920546865202766726565272062616c616e6365206f66206120676976656e206163636f756e742e205468697320697320746865206f6e6c792062616c616e63652074686174206d61747465727320696e207465726d73206f66206d6f7374206f7065726174696f6e73206f6e20746f6b656e732e20497420616c6f6e65206973207573656420746f2064657465726d696e65207468652062616c616e6365207768656e20696e2074686520636f6e747261637420657865637574696f6e20656e7669726f6e6d656e742e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e20746865202763757272656e74206163636f756e74272069732064656c657465643a207370656369666963616c6c7920604672656542616c616e6365602e20467572746865722c2074686520604f6e4672656542616c616e63655a65726f602063616c6c6261636b20697320696e766f6b65642c20676976696e672061206368616e636520746f2065787465726e616c206d6f64756c657320746f20636c65616e2075702064617461206173736f6369617465642077697468207468652064656c65746564206163636f756e742e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c657465642069662060526573657276656442616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e20496e666f726d6174696f6e20726567617264696e67207468652076657374696e67206f66206120676976656e206163636f756e742e2054686520746f74616c20756e6974732069737375656420696e207468652073797374656d2e0000000000704310001200000000000000813b10000a000000000000003897110084431000000000000000000094431000010000000000000000000000000011000b00000000000000813b10000a00000000000000389711009c43100000000000000000000c001100010000000000000000000000140011000b00000000000000813b10000a00000000000000389711009c431000000000000000000020001100010000000000000000000000280011001200000000000000813b10000a00000000000000389711009c43100000000000000000003c001100010000000000000000000000440011001200000000000000813b10000a0000000000000038971100ac43100000000000000000006800110001000000000000004578697374656e7469616c4465706f736974000037000000000000000100000099000000bc431000350000003700000000000000010000009a0000003700000000000000010000009b00000020546865206d696e696d756d20616d6f756e7420726571756972656420746f206b65657020616e206163636f756e74206f70656e2e776520676f74207468652076616c696461746f725f69642066726f6d2063757272656e745f76616c696461746f72733b0a09090909090963757272656e745f76616c696461746f727320697320736574206f662063757272656e746c7920616374696e672076616c696461746f72733b0a090909090909746865206d617070696e67206265747765656e207468652076616c696461746f7220696420616e64206974732066756c6c206964656e74696669636174696f6e2073686f756c642062652076616c69643b0a09090909090974687573206046756c6c4964656e74696669636174696f6e4f663a3a636f6e76657274602063616e27742072657475726e20604e6f6e65603b0a09090909090971656473726d6c2f696d2d6f6e6c696e652d776f726b65722d7374617475730030451000480000009b0a00000a0000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000a44510000900000000000000b045100002000000000000000000000038971100000000000000000068656172746265617400000000000000a44510000900000000000000e04510001900000000000000f94510000900000000000000024610002f0000004865617274626561743c543a3a426c6f636b4e756d6265723e7369676e61747572653c543a3a417574686f7269747949642061732052756e74696d654170705075626c69633e3a3a5369676e6174757265496d4f6e6c696e650000000000000044471000080000000000000000000000925111000e00000000000000000000000000000000000000000000000000000000000000389711004c47100000000000000000005c4710000100000000000000010000000000000064471000040000000000000000000000684710001300000000000000000000000000000000000000000000000000000000000000389711007c47100000000000000000008c47100001000000000000000100000000000000944710001200000002010100000000009f8d11000c00000000000000a64710000900000000000000e7ea1000070000000000000038971100b04710000000000000000000c0471000020000000000000001000000476f7373697041743700000000000000010000009c00000061481000280000004b6579735665633c543a3a417574686f7269747949643e00370000000000000001000000500000002d4810003400000052656365697665644865617274626561747341757468496e6465780037000000000000000100000051000000d04710003a0000000a4810002300000020466f7220656163682073657373696f6e20696e646578207765206b6565702061206d617070696e67206f662060417574686f7269747949646020746f20606f6666636861696e3a3a4f70617175654e6574776f726b5374617465602e205468652063757272656e7420736574206f66206b6579732074686174206d61792069737375652061206865617274626561742e2054686520626c6f636b206e756d626572207768656e2077652073686f756c6420676f737369702e6e6f7420656e6f75676820667265652066756e64730000387d110028000000b84810004300000096010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f62616c616e6365732f7372632f6c69622e72734f75746461746564206865617274626561742072656365697665642e496e76616c696420686561727462656174207369676e61747572652e4475706c696361746564206865617274626561742e4e6f6e206578697374656e74207075626c6963206b65792eb8481000430000009601000001000000676f74206f766572666c6f7720616674657220616464696e6720612066656520746f2076616c756562616c616e636520746f6f206c6f7720746f2073656e642076616c756564657374696e6174696f6e2062616c616e636520746f6f206869676820746f20726563656976652076616c756576616c756520746f6f206c6f7720746f20637265617465206163636f756e7454696d657374616d702055706461746554696d657374616d7020526563656e7448696e74730000404a100031000000714a10004b0000007d0000000400000046696e616c2068696e74206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b2f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f66696e616c6974792d747261636b65722f7372632f6c69622e7273d44a100023000000714a10004b0000007e0000000400000046696e616c697a6564206865696768742061626f766520626c6f636b206e756d62657200104b100019000000304b100048000000bb0100002d000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f6f70732f61726974682e7273576974686472617720686173206265656e20636865636b65642061626f76653b0a090909647565735f6c696d69746564203c2072656e745f627564676574203c2062616c616e6365202d2073756273697374656e6365203c2062616c616e6365202d206578697374656e7469616c5f6465706f7369743b0a09090971656400005900000008000000040000009d00000054696d657374616d70204f72646572656448696e747354696d657374616d70204d656469616e616c77617973206174206c65617374206f6e6520726563656e742073616d706c653b20716564726563656e7420616e64206f72646572656420636f6e7461696e207468652073616d65206974656d733b2071656400003300000004000000040000009e000000084d100043000000714a10004b000000b600000004000000c04c1000480000009b0a00000a000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e72737072756e696e672064696374617465642062792077696e646f775f73697a6520776869636820697320616c776179732073617475726174656420617420313b207165640000000000784d10000a00000000000000844d10000100000000000000000000009c4d1000020000000000000066696e616c5f68696e74000000000000f26510000400000000000000de4e110017000000ac4d10003d000000e94d10001b0000002048696e7420746861742074686520617574686f72206f66207468697320626c6f636b207468696e6b732074686520626573742066696e616c697a656420626c6f636b2069732074686520676976656e206e756d6265722e00000000744e10000a00000000000000925111000e0000000000000038971100804e10000000000000000000904e1000010000000000000000000000984e10000d00000000000000925111000e0000000000000038971100a84e10000000000000000000b84e1000010000000000000057696e646f7753697a6500003700000000000000010000009f000000074f1000460000005265706f72744c6174656e6379000000370000000000000001000000a0000000c04e100047000000205468652064656c617920616674657220776869636820706f696e74207468696e6773206265636f6d6520737573706963696f75732e2044656661756c7420697320313030302e20546865206e756d626572206f6620726563656e742073616d706c657320746f206b6565702066726f6d207468697320636861696e2e2044656661756c74206973203130312e00000000000000005010000b000000000000008c4311000200000000000000000000000c501000010000000000000000000000145010001000000000000000a8431100010000000000000000000000245010000100000000000000000000002c5010000c0000000000000068ea100001000000000000000000000038501000010000000000000000000000405010000e0000000000000050501000020000000000000000000000605010000100000000000000566f74657252656170656400fe50100015000000426164526561706572536c6173686564ef5010000f00000054616c6c7953746172746564ba5010003500000054616c6c7946696e616c697a65640000184411000e000000184411000e000000685010005200000020412074616c6c792028666f7220617070726f76616c20766f746573206f662073656174287329292068617320656e646564202877697468206f6e65206f72206d6f7265206e6577206d656d62657273292e20412074616c6c792028666f7220617070726f76616c20766f746573206f662073656174287329292068617320737461727465642e20736c6173686564207265617065722072656170656420766f7465722c20726561706572436f756e63696c205265676973746572496e666f4f66436f756e63696c204d656d62657273436f756e63696c204e65787446696e616c697a6540521000480000009b0a00000a000000436f756e63696c205465726d4475726174696f6e436f756e63696c2050726573656e746174696f6e4475726174696f6e436f756e63696c204c6561646572626f617264004052100048000000a10a00000e000000436f756e63696c2043616e64696461746573436f756e63696c20566f746572496e666f4f6647757275206d656469746174696f6e66696e616c697a652063616e206f6e6c792062652063616c6c656420616674657220612074616c6c7920697320737461727465642e436f756e63696c20417070726f76616c734f66436f756e63696c20566f746572730000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000405410000d0000000000000050541000040000000000000000000000b05410001800000000000000000000007055100013000000000000005054100004000000000000000000000084551000060000000000000000000000b45510001300000000000000c8551000040000000000000000000000285610000c0000000000000000000000885610000d0000000000000098561000010000000000000000000000b05610000a000000000000000000000000571000100000000000000010571000010000000000000000000000285710000d0000000000000000000000905710000e00000000000000a0571000030000000000000000000000e8571000090000000000000000000000305810001100000000000000445810000100000000000000000000005c581000030000000000000000000000cce310000d00000000000000745810000100000000000000000000008c581000040000000000000000000000ac5810001900000000000000c8581000010000000000000000000000e0581000020000000000000000000000f05810001100000000000000c85810000100000000000000000000000459100002000000000000007365745f617070726f76616c7300000000000000e46510000500000000000000e96510000900000000000000e4cd10000500000000000000ac5c10001200000000000000f26510000400000000000000f665100008000000000000005f55110005000000000000007a6511000c0000009161100058000000e9611000100000003897110000000000f9611000530000004c6210003000000038971100000000007c62100035000000b162100055000000066310002a00000030631000530000008363100057000000da631000510000002b6410003b0000006664100057000000bd641000370000003897110000000000f46410005400000048651000340000003897110000000000c54d11000b000000d04d1100080000007c65100027000000a365100041000000d84d11000c00000070726f78795f7365745f617070726f76616c7300e060100059000000396110001c0000003897110000000000c54d11000b000000556110003c000000d84d11000c000000726561705f696e6163746976655f766f7465720000000000b76010000e00000000000000fa4e11000c000000000000005712110003000000000000004b2211002300000000000000c56010000900000000000000fa4e11000c00000000000000ce6010001200000000000000ac5c100012000000565f100058000000ae5f100056000000046010002e00000038971100000000003260100045000000389711000000000077601000400000003897110000000000c54d11000b000000d04d1100080000002f5f100027000000d84d11000c000000726574726163745f766f74657200000000000000e4cd10000500000000000000fa4e11000c000000535e10004b00000038971100000000009e5e1000420000003897110000000000e05e10004f0000003897110000000000c54d11000b000000d04d1100080000002f5f100027000000d84d11000c0000007375626d69745f63616e646964616379000000004f5e10000400000000000000fa4e11000c000000be5c10001e0000003897110000000000dc5c1000440000003897110000000000205d100048000000685d100051000000b95d10004c000000055e10001e0000003897110000000000c54d11000b000000235e1000180000003b5e100014000000d84d11000c00000070726573656e745f77696e6e65720000000000009e5c100009000000000000004b2211002300000000000000a75c10000500000000000000645511001500000000000000e4cd10000500000000000000ac5c1000120000007b5b100058000000d35b1000580000002b5c100057000000825c1000070000003897110000000000c54d11000b000000895c100015000000b712110011000000d84d11000c0000007365745f646573697265645f736561747300000000000000d65910000500000000000000fa4e11000c000000bb5a100059000000145b100052000000665b100015000000000000005712110003000000000000004b22110023000000db591000480000003897110000000000235a1000480000006b5a1000500000007365745f70726573656e746174696f6e5f6475726174696f6e00000000000000d65910000500000000000000de4e110017000000805910005600000068591000180000007365745f7465726d5f6475726174696f6e0000001459100054000000685910001800000020536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e74206120766f7465206265696e672070726573656e74656420666f722c2077696c6c20696e766f6b65206066696e616c697a655f766f7465602e20536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e746c79206120766f7465206265696e672070726573656e74656420666f722c2077696c6c636f756e742052656d6f7665206120706172746963756c6172206d656d6265722066726f6d20746865207365742e20546869732069732065666665637469766520696d6d6564696174656c792e204e6f74653a20412074616c6c792073686f756c642068617070656e20696e7374616e746c7920286966206e6f7420616c726561647920696e20612070726573656e746174696f6e20706572696f642920746f2066696c6c2074686520736561742069662072656d6f76616c206d65616e732074686174207468652064657369726564206d656d6265727320617265206e6f74206d65742e20536574207468652064657369726564206d656d62657220636f756e743b206966206c6f776572207468616e207468652063757272656e7420636f756e742c207468656e2073656174732077696c6c206e6f7420626520757020656c656374696f6e207768656e2074686579206578706972652e204966206d6f72652c207468656e2061206e657720766f74652077696c6c2062652073746172746564206966206f6e65206973206e6f7420616c726561647920696e2070726f67726573732e20436c61696d2074686174206063616e64696461746560206973206f6e65206f662074686520746f70206063617272795f636f756e74202b20646573697265645f7365617473602063616e646964617465732e204f6e6c7920776f726b7320696666207468652070726573656e746174696f6e20706572696f64206973206163746976652e206063616e646964617465602073686f756c642068617665206174206c6561737420636f6c6c656374656420736f6d65206e6f6e2d7a65726f2060746f74616c6020766f74657320616e6420606f726967696e60206d757374206861766520656e6f7567682066756e647320746f2070617920666f72206120706f74656e7469616c20736c6173682e202d204f28766f746572732920636f6d707574652e63616e646964617465746f74616c436f6d706163743c566f7465496e6465783e205375626d6974206f6e6573656c6620666f722063616e6469646163792e204163636f756e74206d757374206861766520656e6f756768207472616e736665727261626c652066756e647320696e20697420746f207061792074686520626f6e642e204e4f54453a20696620606f726967696e602068617320616c72656164792061737369676e656420617070726f76616c7320766961205b607365745f617070726f76616c73605d2c2069742077696c6c204e4f54206861766520616e7920757361626c652066756e647320746f20706173732063616e64696461637920626f6e6420616e64206d75737420666972737420726574726163742e204e6f746520746861742073657474696e6720617070726f76616c732077696c6c206c6f636b2074686520656e746972652062616c616e6365206f662074686520766f74657220756e74696c2072657472616374696f6e206f72206265696e67207265706f727465642e202d20496e646570656e64656e74206f6620696e7075742e202d205468726565204442206368616e6765732e736c6f742052656d6f7665206120766f7465722e20416c6c20766f746573206172652063616e63656c6c656420616e642074686520766f746572206465706f7369742069732072657475726e65642e2054686520696e646578206d7573742062652070726f7669646564206173206578706c61696e656420696e205b60766f7465725f6174605d2066756e6374696f6e2e20416c736f2072656d6f76657320746865206c6f636b206f6e207468652062616c616e6365206f662074686520766f7465722e20536565205b60646f5f7365745f617070726f76616c732829605d2e202d2054776f20666577657220444220656e74726965732c206f6e65204442206368616e67652e2052656d6f7665206120766f7465722e20466f72206974206e6f7420746f206265206120626f6e642d636f6e73756d696e67206e6f2d6f702c20616c6c20617070726f7665642063616e64696461746520696e6469636573206d757374206e6f772062652065697468657220756e72656769737465726564206f72207265676973746572656420746f20612063616e646964617465207468617420726567697374657265642074686520736c6f742061667465722074686520766f7465722067617665207468656972206c61737420617070726f76616c207365742e20426f746820696e6469636573206d7573742062652070726f7669646564206173206578706c61696e656420696e205b60766f7465725f6174605d2066756e6374696f6e2e204d61792062652063616c6c656420627920616e796f6e652e2052657475726e732074686520766f746572206465706f73697420746f20607369676e6564602e7265706f727465725f696e64657877686f5f696e646578617373756d65645f766f74655f696e646578205365742063616e64696461746520617070726f76616c732066726f6d20612070726f78792e20417070726f76616c20736c6f747320737461792076616c6964206173206c6f6e672061732063616e6469646174657320696e2074686f736520736c6f74732061726520726567697374657265642e202d2053616d6520617320607365745f617070726f76616c73602077697468206f6e65206164646974696f6e616c2073746f7261676520726561642e205365742063616e64696461746520617070726f76616c732e20417070726f76616c20736c6f747320737461792076616c6964206173206c6f6e672061732063616e6469646174657320696e2074686f736520736c6f74732061726520726567697374657265642e204c6f636b73206076616c7565602066726f6d207468652062616c616e6365206f6620606f726967696e6020696e646566696e6974656c792e204f6e6c79205b60726574726163745f766f746572605d206f72205b60726561705f696e6163746976655f766f746572605d2063616e20756e6c6f636b207468652062616c616e63652e206068696e746020617267756d656e7420697320696e74657270726574656420646966666572656e746c79206261736564206f6e3a202d20696620606f726967696e602069732073657474696e6720617070726f76616c7320666f72207468652066697273742074696d653a2054686520696e6465782077696c6c20626520636865636b656420666f722020206265696e6720612076616c6964205f686f6c655f20696e2074686520766f746572206c6973742e2020202d206966207468652068696e7420697320636f72726563746c7920706f696e74696e6720746f206120686f6c652c206e6f206665652069732064656475637465642066726f6d20606f726967696e602e2020202d204f74686572776973652c207468652063616c6c2077696c6c2073756363656564206275742074686520696e6465782069732069676e6f72656420616e642073696d706c792061207075736820746f2074686520202020206c617374206368756e6b207769746820667265652073706163652068617070656e732e20496620746865206e65772070757368206361757365732061206e6577206368756e6b20746f2062652020202020637265617465642c20612066656520696e64696361746564206279205b60566f74696e67466565605d2069732064656475637465642e202d20696620606f726967696e6020697320616c7265616479206120766f7465723a2074686520696e646578205f5f6d7573745f5f2062652076616c696420616e6420706f696e7420746f2074686520636f7272656374202020706f736974696f6e206f662074686520606f726967696e6020696e207468652063757272656e7420766f74657273206c6973742e204e6f7465207468617420616e7920747261696c696e67206066616c73656020766f74657320696e2060766f746573602069732069676e6f7265643b20496e20617070726f76616c20766f74696e672c206e6f7420766f74696e6720666f7220612063616e64696461746520616e6420766f74696e672066616c73652c2061726520657175616c2e202d2054776f20657874726120444220656e74726965732c206f6e65204442206368616e67652e202d20417267756d656e742060766f74657360206973206c696d6974656420696e206c656e67746820746f206e756d626572206f662063616e646964617465732e766f7465735665633c626f6f6c3e68696e74536574496e646578436f756e63696c00000000000000886b1000140000000000000000000000925111000e00000000000000000000000000000000000000000000000000000000000000389711008c76100000000000000000009c6b100001000000000000000100000000000000a46b10000c0000000000000000000000925111000e00000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000b06b100001000000000000000100000000000000b86b10000c0000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000c46b100001000000000000000100000000000000ace61000070000000000000000000000cc6b1000230000000000000000000000000000000000000000000000000000000000000038971100386d10000000000000000000f06b100004000000000000000100000000000000106c1000090000000000000000000000196c10000900000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000246c1000010000000000000001000000000000002c6c10000b0000000101000000000000376c100018000000000000004f6c1000110000000000000000000000000000000000000038971100386d100000000000000000003897110000000000000000000100000000000000606c10000e00000001010000000000000b4e11000c000000000000006e6c1000100000000000000000000000000000000000000038971100806c10000000000000000000906c100002000000000000000000000000000000a06c10000b00000001010000000000000b4e11000c00000000000000ab6c1000170000000000000000000000000000000000000038971100c46c10000000000000000000d46c100001000000000000000000000000000000dc6c1000060000000101000000000000f66510000800000000000000e26c1000190000000000000000000000000000000000000038971100386d10000000000000000000fc6c100001000000000000000100000000000000046d10000c0000000000000000000000f66510000800000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000106d100001000000000000000100000000000000186d10000a0000000000000000000000f66510000800000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000246d1000010000000000000001000000000000002c6d10000a0000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100386d10000000000000000000486d100001000000000000000100000000000000506d10000e0000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000606d100001000000000000000100000000000000686d10000c0000000000000000000000746d10002800000000000000000000000000000000000000000000000000000000000000389711009c6d10000000000000000000ac6d100001000000000000000000000000000000b46d10000b0000000000000000000000bf6d1000210000000000000000000000000000000000000000000000000000000000000038971100e06d10000000000000000000f06d100003000000000000000000000000000000a85c11000500000001010000000000000b4e11000c000000000000000b4e11000c0000000000000000000000000000000000000038971100086e10000000000000000000c05c110002000000000000000000000050726573656e746174696f6e4475726174696f6e6f7210004f0000005465726d4475726174696f6e49721000260000004465736972656453656174730f7210003a0000005665633c28543a3a4163636f756e7449642c20543a3a426c6f636b4e756d626572293e00e37010005500000038711000550000008d71100054000000e17110002e000000566f7465436f756e74566f7465496e64657800009c70100047000000417070726f76616c734f6628543a3a4163636f756e7449642c20536574496e646578295665633c417070726f76616c466c61673e5265676973746572496e666f4f6628566f7465496e6465782c20753332290000370000000000000001000000a100000027701000570000007e7010001e000000566f746572496e666f4f66566f746572496e666f3c42616c616e63654f663c543e3e00003700000000000000010000004f0000000670100021000000566f746572735665633c4f7074696f6e3c543a3a4163636f756e7449643e3e00c36f1000430000004e657874566f746572536574846f10003f000000566f746572436f756e7400006a6f10001a00000043616e646964617465730000370000000000000001000000500000004e6f10001c00000043616e646964617465436f756e7400002a6f1000240000004e65787446696e616c697a6528543a3a426c6f636b4e756d6265722c207533322c205665633c543a3a4163636f756e7449643e29370000000000000001000000a2000000e26e1000480000004c6561646572626f6172645665633c2842616c616e63654f663c543e2c20543a3a4163636f756e744964293e3700000000000000010000004f000000186e100058000000706e100059000000c96e1000190000003700000000000000010000004f0000002047657420746865206c6561646572626f61726420696620776527726520696e207468652070726573656e746174696f6e2070686173652e2054686520666972737420656c656d656e742069732074686520776569676874206f66206561636820656e7472793b204974206d617920626520746865206469726563742073756d6d656420617070726f76616c207374616b65732c206f7220612077656967687465642076657273696f6e206f662069742e20536f727465642066726f6d206c6f7720746f20686967682e20546865206163636f756e747320686f6c64696e672074686520736561747320746861742077696c6c206265636f6d652066726565206f6e20746865206e6578742074616c6c792e2043757272656e74206e756d626572206f66206163746976652063616e64696461746573205468652070726573656e742063616e646964617465206c6973742e2043757272656e74206e756d626572206f6620566f746572732e20746865206e65787420667265652073657420746f2073746f7265206120766f74657220696e2e20546869732077696c6c206b6565702067726f77696e672e205468652070726573656e7420766f746572206c69737420286368756e6b656420616e6420636170706564206174205b60564f5445525f5345545f53495a45605d292e20426173696320696e666f726d6174696f6e2061626f7574206120766f7465722e2054686520766f746520696e64657820616e64206c69737420736c6f742074686174207468652063616e646964617465206077686f60207761732072656769737465726564206f7220604e6f6e6560206966207468657920617265206e6f742063757272656e746c7920726567697374657265642e2054686520746f74616c206e756d626572206f6620766f746520726f756e6473207468617420686176652068617070656e6564206f722061726520696e2070726f67726573732e20205468652063757272656e74206d656d626572736869702e205768656e2074686572652773206120766f746520676f696e67206f6e2c20746869732073686f756c64207374696c6c206265207573656420666f722020657865637574697665206d6174746572732e2054686520626c6f636b206e756d62657220287365636f6e6420656c656d656e7420696e20746865207475706c65292069732074686520626c6f636b20746861742020746865697220706f736974696f6e2069732061637469766520756e74696c202863616c63756c61746564206279207468652073756d206f662074686520626c6f636b206e756d626572207768656e2074686520206d656d6265722077617320656c656374656420616e64207468656972207465726d206475726174696f6e292e204e756d626572206f66206163636f756e747320746861742073686f756c6420636f6e737469747574652074686520636f6c6c6563746976652e20486f77206c6f6e67206561636820706f736974696f6e2069732061637469766520666f722e20486f77206c6f6e6720746f2067697665206561636820746f702063616e64696461746520746f2070726573656e74207468656d73656c7665732061667465722074686520766f746520656e64732e000000000000287510000d000000000000007a6511000c000000000000003897110038751000000000000000000048751000020000000000000000000000587510000a000000000000007a6511000c0000000000000038971100687610000000000000000000647510000100000000000000000000006c75100009000000000000007a6511000c0000000000000038971100787510000000000000000000887510000200000000000000000000009875100014000000000000007a6511000c0000000000000038971100ac7510000000000000000000bc751000020000000000000000000000cc7510000a0000000000000076341100030000000000000038971100d87510000000000000000000e8751000020000000000000000000000f87510001300000000000000196c10000900000000000000389711000c76100000000000000000001c761000030000000000000000000000586511000c00000000000000925111000e0000000000000038971100347610000000000000000000447610000200000000000000000000005476100011000000000000007a6511000c000000000000003897110068761000000000000000000078761000010000000000000000000000807610000a00000000000000763411000300000000000000389711008c76100000000000000000009c761000050000000000000000000000c47610000e0000000000000076341100030000000000000038971100d47610000000000000000000e4761000010000000000000000000000ec76100011000000000000007634110003000000000000003897110000771000000000000000000010771000010000000000000043616e646964616379426f6e64000000370000000000000001000000a30000005f7b10004e000000ad7b100014000000566f74696e67426f6e6400001d7b100042000000566f74696e67466565000000370000000000000001000000a4000000b67a10004a000000007b10001d00000050726573656e74536c617368506572566f7465723700000000000000010000009a000000527a100045000000977a10001f0000004361727279436f756e740000370000000000000001000000a5000000e4791000470000002b7a100027000000496e6163746976654772616365506572696f6400370000000000000001000000a6000000477910004c000000937910004b000000de79100006000000370000000000000001000000a7000000f5781000490000003e791000090000004d696e696d756d566f74696e674c6f636b00000037000000000000000100000099000000b67810003f0000004465636179526174696f00003700000000000000010000009c000000637710004d000000b077100041000000f177100047000000387810004a0000008278100034000000564f5445525f5345545f53495a450000370000000000000001000000a80000003f77100024000000415050524f56414c5f5345545f53495a45000000370000000000000001000000a9000000187710002700000020546865206368756e6b2073697a65206f662074686520617070726f76616c20766563746f722e20546865206368756e6b2073697a65206f662074686520766f74657220766563746f722e20446563617920666163746f72206f6620776569676874207768656e206265696e6720616363756d756c617465642e2049742073686f756c64207479706963616c6c792062652073657420746f205f5f6174206c656173745f5f20606d656d626572736869705f73697a65202d316020746f206b6565702074686520636f6c6c656374697665207365637572652e205768656e2073657420746f20604e602c20697420696e64696361746573206028312f4e295e7460206f66207374616b656420697320646563617965642061742077656967687420696e6372656d656e742073746570206074602e20302077696c6c20726573756c7420696e206e6f20776569676874206265696e6720616464656420617420616c6c20286e6f726d616c20617070726f76616c20766f74696e67292e204120726561736f6e61626c652064656661756c742076616c75652069732032342e204d696e696d756d2061626f757420746861742063616e206265207573656420617320746865206c6f636b65642076616c756520666f7220766f74696e672e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e204120726561736f6e61626c652064656661756c742076616c756520697320313030302e20486f77206d616e7920766f746520696e6469636573206e65656420746f20676f20627920616674657220612074617267657420766f7465722773206c61737420766f7465206265666f726520746865792063616e2062652072656170656420696620746865697220617070726f76616c7320617265206d6f6f742e204120726561736f6e61626c652064656661756c742076616c756520697320312e20486f77206d616e792072756e6e6572732d75702073686f756c64206861766520746865697220617070726f76616c73207065727369737420756e74696c20746865206e65787420766f74652e204120726561736f6e61626c652064656661756c742076616c756520697320322e205468652070756e6973686d656e742c2070657220766f7465722c20696620796f752070726f7669646520616e20696e76616c69642070726573656e746174696f6e2e204120726561736f6e61626c652064656661756c742076616c756520697320312e2054686520616d6f756e74206f662066656520706169642075706f6e206561636820766f7465207375626d697373696f6e2c20756e6c6573732069662074686579207375626d69742061205f686f6c655f20696e64657820616e64207265706c6163652069742e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f2062652061626c6520746f207375626d697420766f7465732e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f207375626d6974206f6e6527732063616e6469646163792e204120726561736f6e61626c652064656661756c742076616c756520697320392e000000387d110028000000dc7b1000440000000e010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f656c656374696f6e732f7372632f6c69622e7273dc7b1000440000000e01000001000000436f756e63696c2050726f787963616e6e6f74207265617020647572696e672070726573656e746174696f6e20706572696f64766f746520696e646578206e6f742063757272656e7463616e6e6f74207265617020647572696e6720677261636520706572696f6474617267657420666f7220696e616374697669747920636c65616e7570206d757374206265206163746976657265706f72746572206d757374206265206120766f746572696e76616c6964207265706f7274657220696e646578696e76616c69642074617267657420696e646578626164207265706f7274657220696e6465786261642074617267657420696e64657872657472616374696f6e20696e64657820696e76616c696472657472616374696f6e20696e646578206d69736d6174636863616e6e6f742072657472616374207768656e2070726573656e74696e6763616e6e6f742072657472616374206e6f6e2d766f7465726475706c69636174652063616e646964617465207375626d697373696f6e696e76616c69642063616e64696461746520736c6f7463616e64696461746520686173206e6f7420656e6f7567682066756e647363616e6e6f742070726573656e74206f757473696465206f662070726573656e746174696f6e20706572696f64696e646578206e6f742063757272656e747374616b65206465706f736974656420746f2070726573656e742077696e6e657220616e6420626520616464656420746f206c6561646572626f6172642073686f756c64206265206e6f6e2d7a65726f6c6561646572626f617264206d757374206578697374207768696c652070726573656e742070686173652061637469766570726573656e746572206d75737420686176652073756666696369656e7420736c61736861626c652066756e647370726573656e7465642063616e646964617465206d7573742062652063757272656e7463616e646964617465206e6f7420776f72746879206f66206c6561646572626f61726463616e646964617465206d757374206e6f7420666f726d2061206475706c696361746564206d656d62657220696620656c65637465646475706c69636174652070726573656e746174696f6e696e636f727265637420746f74616c6e6f20617070726f76616c206368616e67657320647572696e672070726573656e746174696f6e20706572696f64696e636f727265637420766f746520696e646578616d6f756e74206f662063616e6469646174657320746f207265636569766520617070726f76616c20766f7465732073686f756c64206265206e6f6e2d7a65726f616d6f756e74206f662063616e64696461746520766f7465732063616e6e6f742065786365656420616d6f756e74206f662063616e646964617465736c6f636b65642076616c7565206d757374206265206d6f7265207468616e206c696d697477726f6e6720766f74657220696e6465786e657720766f746572206d75737420686176652073756666696369656e742066756e647320746f207061792074686520626f6e64696e76616c696420766f74657220696e646578000000000000e442110008000000000000008881100001000000000000000000000090811000010000000000000000000000988110000800000000000000c8151100010000000000000000000000a0811000010000000000000000000000a88110000700000000000000b0811000030000000000000000000000c8811000010000000000000000000000d08110000500000000000000c8151100010000000000000000000000d8811000010000000000000000000000e08110000800000000000000c8151100010000000000000000000000e88110000100000000000000ccb710000d000000b98210000e0000005370656e64696e677f8210003a0000004177617264656400ccb710000d0000001144110007000000d0431100090000005f821000200000004275726e740000003c82100023000000526f6c6c6f766572f08110004c000000205370656e64696e67206861732066696e69736865643b20746869732069732074686520616d6f756e74207468617420726f6c6c73206f76657220756e74696c206e657874207370656e642e20536f6d65206f66206f75722066756e64732068617665206265656e206275726e742e20536f6d652066756e64732068617665206265656e20616c6c6f63617465642e205765206861766520656e6465642061207370656e6420706572696f6420616e642077696c6c206e6f7720616c6c6f636174652066756e64732e204e65772070726f706f73616c2e53657373696f6e2056616c696461746f72734772616e64706146696e616c697479205374616c6c656454726561737572792050726f706f73616c730000387d1100280000001c831000430000007f000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f74726561737572792f7372632f6c69622e72734469676573744974656d206e6f7420657175616c0000000000a08310001200000000000000b4831000010000000000000000000000cc83100001000000000000007265706f72745f6d69736265686176696f72000000000000ed8310000700000000000000e7ea100007000000d483100019000000205265706f727420736f6d65206d69736265686176696f722e5f7265706f72744772616e64706146696e616c697479000000000070aa10000b0000000000000000000000238a11002300000000000000000000000000000000000000000000000000000000000000389711008897100000000000000000006c8610000100000000000000010000000000000074861000050000000000000000000000798610001b0000000000000000000000000000000000000000000000000000000000000038971100948610000000000000000000a486100001000000000000000100000000000000ac8610000d0000000000000000000000b9861000230000000000000000000000000000000000000000000000000000000000000038971100b48e10000000000000000000dc86100001000000000000000000000000000000e48610000a0000000000000000000000925111000e0000000000000000000000000000000000000000000000000000000000000038971100788710000000000000000000f086100001000000000000000000000000000000f8861000070000000000000000000000ff8610002000000000000000000000000000000000000000000000000000000000000000389711002087100000000000000000003087100001000000000000000000000000000000388710000c0000000000000000000000448710000500000000000000000000000000000000000000000000000000000000000000389711004c87100000000000000000005c871000020000000000000001000000000000006c8710000c00000001010000000000004487100005000000000000009f8d11000c000000000000000000000000000000000000003897110078871000000000000000000088871000010000000000000000000000308910001b000000537461746553746f72656453746174653c543a3a426c6f636b4e756d6265723e370000000000000001000000aa0000000c8910002400000050656e64696e674368616e676553746f72656450656e64696e674368616e67653c543a3a426c6f636b4e756d6265723edb881000310000004e657874466f726365640000ac8810002f0000005374616c6c656428543a3a426c6f636b4e756d6265722c20543a3a426c6f636b4e756d6265722900370000000000000001000000a1000000888810002400000043757272656e7453657449645365744964000000370000000000000001000000ab00000000881000570000005788100031000000536574496453657373696f6e3700000000000000010000004f00000090871000700000002041206d617070696e672066726f6d206772616e6470612073657420494420746f2074686520696e646578206f6620746865202a6d6f737420726563656e742a2073657373696f6e20666f7220776869636820697473206d656d62657273207765726520726573706f6e7369626c652e20546865206e756d626572206f66206368616e6765732028626f746820696e207465726d73206f66206b65797320616e6420756e6465726c79696e672065636f6e6f6d696320726573706f6e736962696c69746965732920696e20746865202273657422206f66204772616e6470612076616c696461746f72732066726f6d2067656e657369732e20607472756560206966207765206172652063757272656e746c79207374616c6c65642e206e65787420626c6f636b206e756d6265722077686572652077652063616e20666f7263652061206368616e67652e2050656e64696e67206368616e67653a20287369676e616c65642061742c207363686564756c6564206368616e6765292e205374617465206f66207468652063757272656e7420617574686f72697479207365742e205468652063757272656e7420617574686f72697479207365742e000000000078891000080000000000000080891000020000000000000000000000b08910000a000000000000007365745f6b65797300000000dabb10000400000000000000098b10000700000000000000108b10000500000000000000e7ea100007000000008a100039000000398a100048000000818a1000310000003897110000000000b28a1000350000003897110000000000c54d11000b000000e78a100022000000f34d110016000000d84d11000c0000002053657473207468652073657373696f6e206b6579287329206f66207468652066756e6374696f6e2063616c6c657220746f20606b6579602e20416c6c6f777320616e206163636f756e7420746f20736574206974732073657373696f6e206b6579207072696f7220746f206265636f6d696e6720612076616c696461746f722e205468697320646f65736e27742074616b652065666665637420756e74696c20746865206e6578742073657373696f6e2e20546865206469737061746368206f726967696e206f6620746869732066756e6374696f6e206d757374206265207369676e65642e202d204f286c6f67206e2920696e206e756d626572206f66206163636f756e74732e543a3a4b65797370726f6f6653657373696f6e00000000543511000a0000000000000000000000848d1000130000000000000000000000000000000000000000000000000000000000000038971100889710000000000000000000988d100001000000000000000100000000000000a08d10000c00000000000000000000009f8d11000c0000000000000000000000000000000000000000000000000000000000000038971100189710000000000000000000ac8d100001000000000000000100000000000000b48d10000d0000000000000000000000f7431100040000000000000000000000000000000000000000000000000000000000000038971100c48d10000000000000000000d48d100002000000000000000100000000000000e48d10000a0000000000000000000000ee8d10001e00000000000000000000000000000000000000000000000000000000000000389711008897100000000000000000000c8e1000020000000000000001000000000000001c8e10001200000000000000000000002e8e1000080000000000000000000000000000000000000000000000000000000000000038971100889710000000000000000000388e100003000000000000000100000000000000508e1000080000000204010000000000e7ea10000700000000000000588e10000e00000000000000098b1000070000000000000038971100688e10000000000000000000788e100004000000000000000000000000000000988e1000080000000204010000000000e7ea10000700000000000000a08e10001400000000000000588e10000e0000000000000038971100b48e10000000000000000000c48e10000400000000000000000000005665633c543a3a56616c696461746f7249643e008b9110001f00000043757272656e74496e6465786d9110001e0000005175657565644368616e6765640000003700000000000000010000004f000000f69010004e00000044911000290000005175657565644b6579735665633c28543a3a56616c696461746f7249642c20543a3a4b657973293e6f9010004f000000be9010003800000044697361626c656456616c696461746f72735665633c7533323e000002901000200000003897110000000000229010004d0000004e6578744b657973543a3a56616c696461746f72496400003700000000000000010000004f000000db8f10002700000038971100000000002d8f100056000000838f1000580000004b65794f776e6572284b65795479706549642c205665633c75383e293700000000000000010000004f000000e48e10004900000038971100000000002d8f100056000000838f10005800000020546865206f776e6572206f662061206b65792e20546865207365636f6e64206b65792069732074686520604b657954797065496460202b2074686520656e636f646564206b65792e20546865206669727374206b657920697320616c77617973206044454455505f4b45595f5052454649586020746f206861766520616c6c20746865206461746120696e207468652073616d65206272616e6368206f662074686520747269652e20486176696e6720616c6c206461746120696e207468652073616d65206272616e63682073686f756c642070726576656e7420736c6f77696e6720646f776e206f7468657220717565726965732e20546865206e6578742073657373696f6e206b65797320666f7220612076616c696461746f722e20496e6469636573206f662064697361626c65642076616c696461746f72732e205468652073657420697320636c6561726564207768656e20606f6e5f73657373696f6e5f656e64696e67602072657475726e732061206e657720736574206f66206964656e7469746965732e2054686520717565756564206b65797320666f7220746865206e6578742073657373696f6e2e205768656e20746865206e6578742073657373696f6e20626567696e732c207468657365206b6579732077696c6c206265207573656420746f2064657465726d696e65207468652076616c696461746f7227732073657373696f6e206b6579732e20547275652069662074686520756e6465726c79696e672065636f6e6f6d6963206964656e746974696573206f7220776569676874696e6720626568696e64207468652076616c696461746f727320686173206368616e67656420696e20746865207175657565642076616c696461746f72207365742e2043757272656e7420696e646578206f66207468652073657373696f6e2e205468652063757272656e7420736574206f662076616c696461746f72732e000000000000e49110001000000000000000f4911000050000000000000038971100fc91100000000000000000000c921000020000000000000044454455505f4b45595f505245464958265b75385d000000370000000000000001000000ac0000001c92100059000000759210000d0000002055736564206173206669727374206b657920666f7220604e6578744b6579736020616e6420604b65794f776e65726020746f2070757420616c6c20746865206461746120696e746f207468652073616d65206272616e6368206f662074686520747269652e3a73657373696f6e3a6b65797353657373696f6e204e6578744b6579730000000000249310000d000000000000003493100002000000000000000000000064931000090000000000000000000000ac9310000f00000000000000bc931000010000000000000000000000d49310000700000000000000000000000c9410001000000000000000bc9310000100000000000000000000001c941000080000000000000070726f706f73655f7370656e64000000000000005f5511000500000000000000645511001500000000000000fa9510000b000000000000004b22110023000000289510004b000000739510004d000000c0951000150000003897110000000000c54d11000b000000d04d110008000000f111110019000000d595100025000000d84d11000c00000072656a6563745f70726f706f73616c00000000001d9510000b00000000000000e9cd100016000000de9410003f0000003897110000000000c54d11000b000000d04d110008000000f111110019000000514e110010000000d84d11000c000000617070726f76655f70726f706f73616c5c94100057000000b39410002b0000003897110000000000c54d11000b000000d04d110008000000f111110019000000b712110011000000d84d11000c00000020417070726f766520612070726f706f73616c2e2041742061206c617465722074696d652c207468652070726f706f73616c2077696c6c20626520616c6c6f636174656420746f207468652062656e656669636961727920616e6420746865206f726967696e616c206465706f7369742077696c6c2062652072657475726e65642e2052656a65637420612070726f706f736564207370656e642e20546865206f726967696e616c206465706f7369742077696c6c20626520736c61736865642e70726f706f73616c5f69642050757420666f727761726420612073756767657374696f6e20666f72207370656e64696e672e2041206465706f7369742070726f706f7274696f6e616c20746f207468652076616c756520697320726573657276656420616e6420736c6173686564206966207468652070726f706f73616c2069732072656a65637465642e2049742069732072657475726e6564206f6e6365207468652070726f706f73616c20697320617761726465642e202d204f6e65204442206368616e67652c206f6e6520657874726120444220656e7472792e62656e656669636961727954726561737572790000000000000008d010000d0000000000000000000000ccb710000d000000000000000000000000000000000000000000000000000000000000003897110018971000000000000000000028971000010000000000000001000000000000009acf1000090000000101000000000000ccb710000d000000000000003097100024000000000000000000000000000000000000003897110054971000000000000000000064971000010000000000000000000000000000006c97100009000000000000000000000075971000120000000000000000000000000000000000000000000000000000000000000038971100889710000000000000000000989710000100000000000000010000003700000000000000010000009c000000fd9710002900000050726f706f73616c3c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3700000000000000010000004f000000de9710001f000000417070726f76616c735665633c50726f706f73616c496e6465783e0037000000000000000100000050000000a09710003e0000002050726f706f73616c20696e646963657320746861742068617665206265656e20617070726f76656420627574206e6f742079657420617761726465642e2050726f706f73616c7320746861742068617665206265656e206d6164652e204e756d626572206f662070726f706f73616c7320746861742068617665206265656e206d6164652e000000000000089910000c00000000000000149910000700000000000000389711001c99100000000000000000002c9910000200000000000000000000003c99100013000000000000007a6511000c000000000000003897110050991000000000000000000060991000010000000000000000000000689910000b00000000000000925111000e0000000000000038971100749910000000000000000000849910000100000000000000000000008c991000040000000000000014991000070000000000000038971100909910000000000000000000a0991000010000000000000050726f706f73616c426f6e645065726d696c6c00370000000000000001000000ad000000609a100055000000b59a10004400000050726f706f73616c426f6e644d696e696d756d00370000000000000001000000990000000e9a1000520000005370656e64506572696f6400370000000000000001000000ae000000ec991000220000004275726e370000000000000001000000af000000a8991000440000002050657263656e74616765206f662073706172652066756e64732028696620616e7929207468617420617265206275726e7420706572207370656e6420706572696f642e20506572696f64206265747765656e2073756363657373697665207370656e64732e204d696e696d756d20616d6f756e74206f662066756e647320746861742073686f756c6420626520706c6163656420696e2061206465706f73697420666f72206d616b696e6720612070726f706f73616c2e204672616374696f6e206f6620612070726f706f73616c27732076616c756520746861742073686f756c6420626520626f6e64656420696e206f7264657220746f20706c616365207468652070726f706f73616c2e20416e2061636365707465642070726f706f73616c2067657473207468657365206261636b2e20412072656a65637465642070726f706f73616c20646f6573206e6f742e4772616e64706146696e616c6974792050656e64696e674368616e67654772616e64706146696e616c697479205374617465496e636f6e73697374656e74207374617465202d20636f756c646e277420736574746c6520696d62616c616e636520666f722066756e6473207370656e7420627920747265617375727953657373696f6e205175657565644b65797300590000000800000004000000b0000000b10000000000000000000000b20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000590000000800000004000000b0000000b10000000000000000000000b20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000590000000800000004000000b3000000b10000000000000000000000b40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000590000000800000004000000b3000000b10000000000000000000000b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004772616e64706146696e616c697479204e657874466f72636564636f6465206973206e6f7420666f756e647072697374696e6520636f6465206973206e6f7420666f756e647468657265206973206e6f7420656e6f7567682067617320666f722073746f72696e672074686520636f646553657373696f6e204b65794f776e6572000000f0a0100048000000a10a00000e000000f0a01000480000009b0a00000a00000080a0100019000000a0a01000430000003401000009000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f70687261676d656e2f7372632f6c69622e7273000000000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e72733897110000000000391411000200000060a110007c000000dca11000490000007900000006000000657865632e7072656661625f6d6f64756c652e696e697469616c2063616e27742062652067726561746572207468616e20657865632e7072656661625f6d6f64756c652e6d6178696d756d3b0a09090909090974687573204d656d6f72793a3a6e6577206d757374206e6f74206661696c3b0a0909090909097165642f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f7761736d2f6d6f642e72736e6f206173736f6369617465642076616c696461746f7220494420666f72206163636f756e742e72656769737465726564206475706c6963617465206b65791c831000430000007f0000000100000050726f706f73657227732062616c616e636520746f6f206c6f774e6f2070726f706f73616c206174207468617420696e64657866696e616c6e756d417574686f727368697020417574686f7237000000000000000100000038000000387d110028000000e8a210003f000000bf000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f626162652f7372632f6c69622e727300e8a210003f000000bf0000000100000073657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a090909716564387d110028000000607d110050000000370100000900000065706f636820696e64696365732077696c6c206e6576657220726561636820325e3634206265666f726520746865206465617468206f662074686520756e6976657273653b207165640000000000000038a410000a0000000000000044a410000100000000000000000000005ca4100001000000000000007365745f756e636c65730000000000007da410000a0000000000000087a410000e00000064a41000190000002050726f76696465206120736574206f6620756e636c65732e6e65775f756e636c65735665633c543a3a4865616465723e417574686f72736869700000000000a8a51000060000000000000000000000aea510003a0000000000000000000000000000000000000000000000000000000000000038971100e8a510000000000000000000f8a510000100000000000000010000000000000000a610000600000000000000000000000b4e11000c000000000000000000000000000000000000000000000000000000000000003897110008a61000000000000000000018a610000100000000000000000000000000000020a610000c0000000000000000000000f74311000400000000000000000000000000000000000000000000000000000000000000389711002ca6100000000000000000003ca61000010000000000000001000000556e636c65735665633c556e636c65456e7472794974656d3c543a3a426c6f636b4e756d6265722c20543a3a486173682c20543a3a4163636f756e7449643e3e370000000000000001000000500000008ca6100007000000417574686f7200003700000000000000010000004f00000073a6100019000000446964536574556e636c65733700000000000000010000004f00000044a610002f000000205768657468657220756e636c6573207765726520616c72656164792073657420696e207468697320626c6f636b2e20417574686f72206f662063757272656e7420626c6f636b2e20556e636c6573417574686f727368697020556e636c6573556e636c657320616c72656164792073657420696e20626c6f636b2e756e636c6520616c726561647920696e636c75646564756e636c652069732067656e65736973756e636c6520697320746f6f206869676820696e20636861696e756e636c6520706172656e74206e6f7420696e20636861696e756e636c65206e6f7420726563656e7420656e6f75676820746f20626520696e636c756465644261626500000000005caa10000a000000000000000000000076f91000030000000000000000000000000000000000000000000000000000000000000038971100e4aa1000000000000000000068aa10000100000000000000010000000000000070aa10000b00000000000000000000007baa1000270000000000000000000000000000000000000000000000000000000000000038971100a4aa10000000000000000000b4aa100001000000000000000100000000000000bcaa10000b000000000000000000000076f91000030000000000000000000000000000000000000000000000000000000000000038971100e4aa10000000000000000000c8aa100002000000000000000100000000000000d8aa10000b000000000000000000000076f91000030000000000000000000000000000000000000000000000000000000000000038971100e4aa10000000000000000000f4aa100001000000000000000100000000000000fcaa10000a000000000000000000000006ab100008000000000000000000000000000000000000000000000000000000000000003897110070ab1000000000000000000010ab10000a00000000000000010000000000000060ab10000e000000000000000000000006ab100008000000000000000000000000000000000000000000000000000000000000003897110070ab1000000000000000000080ab10000100000000000000010000000000000088ab10000c00000000000000000000007634110003000000000000000000000000000000000000000000000000000000000000003897110094ab10000000000000000000a4ab100009000000000000000100000000000000ecab1000110000000101000000000000763411000300000000000000fdab10000d00000000000000000000000000000000000000389711000cac1000000000000000000038971100000000000000000001000000000000001cac10000b000000000000000000000027ac100008000000000000000000000000000000000000000000000000000000000000003897110030ac1000000000000000000040ac100002000000000000000000000045706f6368496e64657800008bb0100015000000417574686f7269746965735665633c28417574686f7269747949642c2042616265417574686f72697479576569676874293e00003700000000000000010000005000000070b010001b00000047656e65736973536c6f74000eb010003e0000004cb010002400000043757272656e74536c6f7400370000000000000001000000ab000000f9af10001500000052616e646f6d6e6573735b75383b2033325d000033ae10002e000000389711000000000061ae10000b00000038971100000000006cae100041000000adae10003e000000ebae10004500000030af10004500000075af100041000000b6af1000430000004e65787452616e646f6d6e6573730000370000000000000001000000b50000001cae1000170000005365676d656e74496e6465783700000000000000010000009c000000d7ac10001f0000003897110000000000f6ac10003d00000033ad10004000000073ad100025000000389711000000000098ad10003b000000d3ad10004200000015ae100007000000556e646572436f6e737472756374696f6e5665633c5b75383b2033325d3e000037000000000000000100000050000000496e697469616c697a65644d61796265567266003700000000000000010000004f00000050ac10004000000090ac1000470000002054656d706f726172792076616c75652028636c656172656420617420626c6f636b2066696e616c697a6174696f6e292077686963682069732060536f6d6560206966207065722d626c6f636b20696e697469616c697a6174696f6e2068617320616c7265616479206265656e2063616c6c656420666f722063757272656e7420626c6f636b2e2052616e646f6d6e65737320756e64657220636f6e737472756374696f6e2e205765206d616b6520612074726164656f6666206265747765656e2073746f7261676520616363657373657320616e64206c697374206c656e6774682e2057652073746f72652074686520756e6465722d636f6e737472756374696f6e2072616e646f6d6e65737320696e207365676d656e7473206f6620757020746f2060554e4445525f434f4e535452554354494f4e5f5345474d454e545f4c454e475448602e204f6e63652061207365676d656e7420726561636865732074686973206c656e6774682c20776520626567696e20746865206e657874206f6e652e20576520726573657420616c6c207365676d656e747320616e642072657475726e20746f206030602061742074686520626567696e6e696e67206f662065766572792065706f63682e204e6578742065706f63682072616e646f6d6e6573732e205468652065706f63682072616e646f6d6e65737320666f7220746865202a63757272656e742a2065706f63682e20232053656375726974792054686973204d555354204e4f54206265207573656420666f722067616d626c696e672c2061732069742063616e20626520696e666c75656e6365642062792061206d616c6963696f75732076616c696461746f7220696e207468652073686f7274207465726d2e204974204d4159206265207573656420696e206d616e792063727970746f677261706869632070726f746f636f6c732c20686f77657665722c20736f206c6f6e67206173206f6e652072656d656d626572732074686174207468697320286c696b652065766572797468696e6720656c7365206f6e2d636861696e29206974206973207075626c69632e20466f72206578616d706c652c2069742063616e20626520757365642077686572652061206e756d626572206973206e656564656420746861742063616e6e6f742068617665206265656e2063686f73656e20627920616e206164766572736172792c20666f7220707572706f7365732073756368206173207075626c69632d636f696e207a65726f2d6b6e6f776c656467652070726f6f66732e2043757272656e7420736c6f74206e756d6265722e2054686520736c6f74206174207768696368207468652066697273742065706f63682061637475616c6c7920737461727465642e2054686973206973203020756e74696c2074686520666972737420626c6f636b206f662074686520636861696e2e2043757272656e742065706f636820617574686f7269746965732e2043757272656e742065706f636820696e6465782e0000000010b110000d0000000000000076f9100003000000000000003897110020b11000000000000000000030b1100002000000000000000000000040b110001100000000000000a3e0100009000000000000003897110054b11000000000000000000064b11000050000000000000045706f63684475726174696f6e000000370000000000000001000000b6000000bcb2100043000000ffb210003f0000004578706563746564426c6f636b54696d65000000370000000000000001000000b70000008cb1100041000000cdb110004400000011b210004100000052b210004200000094b210002800000020546865206578706563746564206176657261676520626c6f636b2074696d6520617420776869636820424142452073686f756c64206265206372656174696e6720626c6f636b732e2053696e636520424142452069732070726f626162696c6973746963206974206973206e6f74207472697669616c20746f20666967757265206f7574207768617420746865206578706563746564206176657261676520626c6f636b2074696d652073686f756c64206265206261736564206f6e2074686520736c6f74206475726174696f6e20616e642074686520736563757269747920706172616d657465722060636020287768657265206031202d20636020726570726573656e7473207468652070726f626162696c697479206f66206120736c6f74206265696e6720656d707479292e20546865206e756d626572206f66202a2a736c6f74732a2a207468617420616e2065706f63682074616b65732e20576520636f75706c652073657373696f6e7320746f2065706f6368732c20692e652e2077652073746172742061206e65772073657373696f6e206f6e636520746865206e65772065706f636820626567696e732e756e636c6573303074696d657374616d702073657420696e20626c6f636b20646f65736e2774206d6174636820736c6f7420696e207365616c4e6f206f74686572206572726f72732061726520616363657074656420616674657220616e2068617264206572726f7221496e686572656e7420776974682073616d65206964656e74696669657220616c726561647920657869737473215468657265206973206f6e6c79206f6e6520666174616c206572726f723b20716564005900000008000000040000009d0000003a65787472696e7369635f696e64657800000000e4421100080000000000000020b5100004000000000000000000000040b5100002000000000000000000000050b51000050000000000000058b5100005000000000000000000000080b5100002000000000000000000000090b51000080000000000000048ea100001000000000000000000000098b51000010000000000000000000000a0b510000b0000000000000048ea1000010000000000000000000000acb51000010000000000000000000000664311000800000000000000b4b51000020000000000000000000000c4b51000010000000000000000000000ccb510000e00000000000000b4b51000020000000000000000000000dcb510000100000000000000d043110009000000ccb710000d000000d9431100040000005eb710000b00000069b7100053000000bcb7100010000000566f746564000000d043110009000000d943110004000000f7431100040000005eb710000b0000005eb710000b000000d6b610004200000018b7100046000000417070726f766564a5b6100031000000446973617070726f7665640070b6100035000000d943110004000000f7431100040000002fb61000410000004d656d62657245786563757465640000e4b510004b00000020412073696e676c65206d656d6265722064696420736f6d6520616374696f6e3b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e207761732065786563757465643b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e20776173206e6f7420617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2077617320617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2028676976656e20686173682920686173206265656e20766f746564206f6e20627920676976656e206163636f756e742c206c656176696e6720612074616c6c79202879657320766f74657320616e64206e6f20766f74657320676976656e20726573706563746976656c7920617320604d656d626572436f756e7460292e4d656d626572436f756e742041206d6f74696f6e2028676976656e20686173682920686173206265656e2070726f706f7365642028627920676976656e206163636f756e742920776974682061207468726573686f6c642028676976656e20604d656d626572436f756e7460292e50726f706f73616c496e64657853797374656d204e756d62657253797374656d2045787472696e73696373526f6f74496e7374616e636531436f6c6c656374697665204d656d62657273496e7374616e636532436f6c6c656374697665204d656d6265727353797374656d2044696765737453797374656d20426c6f636b4861736853797374656d204163636f756e744e6f6e6365000000387d1100280000007cb8100041000000e9000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f73797374656d2f7372632f6c69622e7273000000387d110028000000d8b810004500000083000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6c6c6563746976652f7372632f6c69622e727353797374656d20506172656e744861736853797374656d2052616e646f6d4d6174657269616c0080b9100048000000a10a00000e00000053797374656d204576656e747353797374656d204576656e74546f70696373000000000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000d0ba10000a0000000000000038971100000000000000000000000000dcba1000010000000000000000000000e4ba10000600000000000000ecba100001000000000000000000000004bb10000100000000000000000000000cbb10000e000000000000001cbb100001000000000000000000000034bb10000100000000000000000000003cbb1000080000000000000044bb10000100000000000000000000005cbb100001000000000000000000000064bb10000b0000000000000070bb100001000000000000000000000088bb100001000000000000000000000090bb10000c000000000000009cbb1000010000000000000000000000b4bb1000010000000000000066696c6c5f626c6f636b00008bbc10004800000072656d61726b00000000000084bc10000700000000000000e7ea10000700000069bc10001b0000007365745f686561705f706167657300000000000064bc1000050000000000000076f910000300000025bc10003f0000007365745f636f646500000000fc2011000300000000000000e7ea10000700000013bc1000120000007365745f73746f72616765000000000001bc1000050000000000000006bc10000d000000e6bb10001b0000006b696c6c5f73746f7261676500000000dabb10000400000000000000debb100008000000bcbb10001e000000204b696c6c20736f6d65206974656d732066726f6d2073746f726167652e6b6579735665633c4b65793e2053657420736f6d65206974656d73206f662073746f726167652e6974656d735665633c4b657956616c75653e2053657420746865206e657720636f64652e2053657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e7061676573204d616b6520736f6d65206f6e2d636861696e2072656d61726b2e5f72656d61726b20412062696720646973706174636820746861742077696c6c20646973616c6c6f7720616e79206f74686572207472616e73616374696f6e20746f20626520696e636c756465642e53797374656d0000000000000004c210000c00000001010000000000000b4e11000c0000000000000010c21000080000000000000000000000000000000000000038971100e8d21000000000000000000018c210000100000000000000010000000000000020c210000e0000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711006cc21000000000000000000030c210000100000000000000000000000000000038c210001300000000000000000000004bc210000600000000000000000000000000000000000000000000000000000000000000389711006cc21000000000000000000054c21000010000000000000000000000000000005cc21000100000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711006cc2100000000000000000007cc210000100000000000000000000000000000084c2100014000000000000000000000098c21000100000000000000000000000000000000000000000000000000000000000000038971100a8c210000000000000000000b8c2100002000000000000000100000000000000c8c21000090000000101000000000000925111000e000000000000007c4f110007000000000000000000000000000000000000003897110078c310000000000000000000d4c2100001000000000000000100000000000000dcc210000d0000000101000000000000763411000300000000000000e7ea1000070000000000000000000000000000000000000038971100ecc210000000000000000000fcc210000100000000000000010000000000000004c310000e000000000000000000000012c3100012000000000000000000000000000000000000000000000000000000000000003897110024c31000000000000000000034c310000200000000000000010000000000000044c31000060000000000000000000000925111000e0000000000000000000000000000000000000000000000000000000000000038971100e8d2100000000000000000004cc310000100000000000000010000000000000054c310000a00000000000000000000007c4f110007000000000000000000000000000000000000000000000000000000000000003897110078c31000000000000000000060c310000100000000000000010000000000000068c310000e00000000000000000000007c4f110007000000000000000000000000000000000000000000000000000000000000003897110078c31000000000000000000088c310000100000000000000010000000000000090c3100006000000000000000000000096c310000b0000000000000000000000000000000000000000000000000000000000000038971100a4c310000000000000000000b4c3100001000000000000000100000000000000bcc31000060000000000000000000000c2c31000230000000000000000000000000000000000000000000000000000000000000038971100e8c310000000000000000000f8c310000100000000000000010000000000000000c410000a00000000000000000000000ac410000a0000000000000000000000000000000000000000000000000000000000000038971100e8d21000000000000000000014c41000010000000000000001000000000000001cc410000b000000020101000000000027c4100002000000000000007c4f1100070000000000000029c41000210000000000000038971100f8d2100000000000000000004cc410000d00000000000000010000004163636f756e744e6f6e6365543a3a496e646578f9ca10001f00000045787472696e736963436f756e740000cbca10002e000000416c6c45787472696e7369637357656967687457656967687400000086ca100045000000416c6c45787472696e736963734c656e3700000000000000010000004f00000036ca1000500000004e6578745765696768744d756c7469706c6965725765696768744d756c7469706c696572370000000000000001000000ab000000c2c91000590000001bca10001b000000426c6f636b486173680000009cc910002600000045787472696e73696344617461000000370000000000000001000000510000004dc910004f00000052616e646f6d4d6174657269616c2869382c205665633c543a3a486173683e29370000000000000001000000b800000090c8100069000000f9c81000540000004e756d62657200004ec8100042000000506172656e7448617368000032c810001c00000045787472696e73696373526f6f740000370000000000000001000000b9000000edc71000450000004469676573744469676573744f663c543e00000037000000000000000100000050000000b1c710003c0000004576656e74735665633c4576656e745265636f72643c543a3a4576656e742c20543a3a486173683e3e000000370000000000000001000000ba00000089c71000280000004576656e74436f756e744576656e74496e6465785bc710002e0000004576656e74546f7069637328295665633c28543a3a426c6f636b4e756d6265722c204576656e74496e646578293e0000b4c4100049000000fdc4100025000000389711000000000022c510004b0000006dc510002a000000389711000000000097c5100054000000ebc51000510000003cc6100039000000389711000000000075c6100053000000c8c61000530000001bc7100040000000204d617070696e67206265747765656e206120746f7069632028726570726573656e74656420627920543a3a486173682920616e64206120766563746f72206f6620696e6465786573206f66206576656e747320696e2074686520603c4576656e74733c543e3e60206c6973742e20546865206669727374206b657920736572766573206e6f20707572706f73652e2054686973206669656c64206973206465636c6172656420617320646f75626c655f6d6170206a75737420666f7220636f6e76656e69656e6365206f66207573696e67206072656d6f76655f707265666978602e20416c6c20746f70696320766563746f727320686176652064657465726d696e69737469632073746f72616765206c6f636174696f6e7320646570656e64696e67206f6e2074686520746f7069632e205468697320616c6c6f7773206c696768742d636c69656e747320746f206c6576657261676520746865206368616e67657320747269652073746f7261676520747261636b696e67206d656368616e69736d20616e6420696e2063617365206f66206368616e67657320666574636820746865206c697374206f66206576656e7473206f6620696e7465726573742e205468652076616c756520686173207468652074797065206028543a3a426c6f636b4e756d6265722c204576656e74496e646578296020626563617573652069662077652075736564206f6e6c79206a7573742074686520604576656e74496e64657860207468656e20696e20636173652069662074686520746f70696320686173207468652073616d6520636f6e74656e7473206f6e20746865206e65787420626c6f636b206e6f206e6f74696669636174696f6e2077696c6c20626520747269676765726564207468757320746865206576656e74206d69676874206265206c6f73742e20546865206e756d626572206f66206576656e747320696e2074686520604576656e74733c543e60206c6973742e204576656e7473206465706f736974656420666f72207468652063757272656e7420626c6f636b2e20446967657374206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2045787472696e7369637320726f6f74206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2048617368206f66207468652070726576696f757320626c6f636b2e205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e20536572696573206f6620626c6f636b20686561646572732066726f6d20746865206c61737420383120626c6f636b73207468617420616374732061732072616e646f6d2073656564206d6174657269616c2e205468697320697320617272616e67656420617320612072696e6720627566666572207769746820746865206069386020707265666978206265696e672074686520696e64657820696e746f20746865206056656360206f6620746865206f6c6465737420686173682e2045787472696e73696373206461746120666f72207468652063757272656e7420626c6f636b20286d61707320616e2065787472696e736963277320696e64657820746f206974732064617461292e204d6170206f6620626c6f636b206e756d6265727320746f20626c6f636b206861736865732e20546865206e65787420776569676874206d756c7469706c6965722e20546869732073686f756c6420626520757064617465642061742074686520656e64206f66206561636820626c6f636b206261736564206f6e207468652073617475726174696f6e206c6576656c2028776569676874292e20546f74616c206c656e6774682028696e2062797465732920666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2077656967687420666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2065787472696e7369637320636f756e7420666f72207468652063757272656e7420626c6f636b2e2045787472696e73696373206e6f6e636520666f72206163636f756e74732e496e7374616e636531436f6c6c6563746976652050726f706f73616c73496e7374616e636531436f6c6c65637469766520566f74696e67496e7374616e636532436f6c6c6563746976652050726f706f73616c73496e7374616e636532436f6c6c65637469766520566f74696e6700000000000038cc10000b0000000000000044cc10000100000000000000000000005ccc10000400000000000000000000007ccc1000070000000000000084cc10000100000000000000000000009ccc1000030000000000000000000000b84811000700000000000000b4cc1000020000000000000000000000e4cc100004000000000000000000000070491100040000000000000004cd10000300000000000000000000004ccd100004000000000000007365745f6d656d6265727300000000007ccf10000b00000000000000255c110011000000fbce1000540000004fcf100017000000389711000000000066cf10001600000065786563757465000000000058531100080000000000000075ce10001e00000093ce10003d0000003897110000000000d0ce10002b0000000000000058ce1000090000000000000061ce1000140000000000000058531100080000000000000075ce10001e000000c54d11000b00000006ce1000240000002ace10002e000000d84d11000c000000000000005853110008000000000000007c4f11000700000000000000e4cd10000500000000000000e9cd10001600000000000000ffcd10000700000000000000f743110004000000c54d11000b0000006ccd1000230000008fcd100055000000d84d11000c000000202d20426f756e6465642073746f72616765207265616420616e64207772697465732e202d2057696c6c20626520736c696768746c792068656176696572206966207468652070726f706f73616c20697320617070726f766564202f20646973617070726f7665642061667465722074686520766f74652e696e646578436f6d706163743c50726f706f73616c496e6465783e617070726f7665202d20426f756e6465642073746f7261676520726561647320616e64207772697465732e202d20417267756d656e7420607468726573686f6c6460206861732062656172696e67206f6e207765696768742e7468726573686f6c64436f6d706163743c4d656d626572436f756e743e426f783c3c542061732054726169743c493e3e3a3a50726f706f73616c3e20446973706174636820612070726f706f73616c2066726f6d2061206d656d626572207573696e672074686520604d656d62657260206f726967696e2e204f726967696e206d7573742062652061206d656d626572206f662074686520636f6c6c6563746976652e205365742074686520636f6c6c6563746976652773206d656d62657273686970206d616e75616c6c7920746f20606e65775f6d656d62657273602e204265206e69636520746f2074686520636861696e20616e642070726f76696465206974207072652d736f727465642e20526571756972657320726f6f74206f726967696e2e6e65775f6d656d62657273496e7374616e636531436f6c6c65637469766550726f706f73616c735665633c543a3a486173683e00e8d010002400000050726f706f73616c4f663c542061732054726169743c493e3e3a3a50726f706f73616c00b5d0100033000000566f74696e67566f7465733c543a3a4163636f756e7449643e00000088d010002d00000050726f706f73616c436f756e7400000076d010001200000028d010004e000000205468652063757272656e74206d656d62657273206f662074686520636f6c6c6563746976652e20546869732069732073746f72656420736f7274656420286a7573742062792076616c7565292e2050726f706f73616c7320736f206661722e20566f746573206f6e206120676976656e2070726f706f73616c2c206966206974206973206f6e676f696e672e2041637475616c2070726f706f73616c20666f72206120676976656e20686173682c20696620697427732063757272656e742e2054686520686173686573206f6620746865206163746976652070726f706f73616c732e496e7374616e636532436f6c6c65637469766500000000009acf1000090000000000000000000000a3cf10000c0000000000000000000000000000000000000000000000000000000000000038971100f8d210000000000000000000b0cf100001000000000000000100000000000000b8cf10000a00000001010000000000007c4f11000700000000000000c2cf1000190000000000000000000000000000000000000038971100d8d210000000000000000000dccf100001000000000000000000000000000000e4cf10000600000001010000000000007c4f11000700000000000000eacf1000130000000000000000000000000000000000000038971100d8d21000000000000000000000d010000100000000000000000000000000000008d010000d000000000000000000000076341100030000000000000000000000000000000000000000000000000000000000000038971100e8d21000000000000000000018d0100001000000000000000100000000000000ace61000070000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100f8d21000000000000000000020d010000100000000000000010000003700000000000000010000004f0000003700000000000000010000009c000000370000000000000001000000500000007cb8100041000000e9000000010000003a6865617070616765733a636f646500d8b8100045000000830000000100000070726f706f736572206e6f742061206d656d6265726475706c69636174652070726f706f73616c73206e6f7420616c6c6f776564496e7374616e636531436f6c6c6563746976652050726f706f73616c4f66496e7374616e636531436f6c6c6563746976652050726f706f73616c436f756e7470726f706f73616c206d757374206578697374766f746572206e6f742061206d656d6265726d69736d61746368656420696e6465786475706c696361746520766f74652069676e6f726564496e7374616e636532436f6c6c6563746976652050726f706f73616c4f66496e7374616e636532436f6c6c6563746976652050726f706f73616c436f756e740000000000000064d410000f0000000000000074d4100002000000000000000000000084d4100004000000000000004e65774163636f756e74496e64657800d0431100090000001fd510000c000000a4d41000220000003897110000000000c6d410004100000007d51000180000002041206e6577206163636f756e7420696e646578207761732061737369676e65642e2054686973206576656e74206973206e6f7420747269676765726564207768656e20616e206578697374696e6720696e64657820697320726561737369676e656420746f20616e6f7468657220604163636f756e744964602e4163636f756e74496e6465780050d510001900000070d5100048000000230100000e000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f6c69622e7273d0d510000e000000ded5100048000000220100004a0000006578706c696369742070616e69632f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f6c69622e72730000d0d510000e000000ded5100048000000210100004a00000058d610002b00000083d6100044000000ef0000000400000054696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b2f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f74696d657374616d702f7372632f6c69622e727300e0d610003000000083d6100044000000e30000000400000054696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b28d710004e00000083d6100044000000e40000000400000054696d657374616d70206d75737420696e6372656d656e74206279206174206c65617374203c4d696e696d756d506572696f643e206265747765656e2073657175656e7469616c20626c6f636b7300000000000054d810000b000000000000003897110000000000000000000000000060d8100001000000000000000000000068d810000d000000000000003897110000000000000000000000000078d8100001000000000000000000000080d810000e000000000000003897110000000000000000000000000090d8100001000000000000000000000098d810000c0000000000000038971100000000000000000000000000a4d81000010000000000000000000000acd810000500000000000000b4d81000010000000000000000000000bcd8100001000000000000004d656d626572416464656400c5d91000390000004d656d62657252656d6f7665640000008ad910003b0000004d656d6265727353776170706564000053d91000370000004d656d6265727352657365740dd910004600000044756d6d79000000e0d810002d000000c4d810001c000000205068616e746f6d206d656d6265722c206e6576657220757365642e727374643a3a6d61726b65723a3a5068616e746f6d446174613c284163636f756e7449642c204576656e74293e20546865206d656d62657273686970207761732072657365743b2073656520746865207472616e73616374696f6e20666f722077686f20746865206e6577207365742069732e2054776f206d656d62657273207765726520737761707065643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732072656d6f7665643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732061646465643b2073656520746865207472616e73616374696f6e20666f722077686f2e54696d657374616d70204e6f77496e646963657320456e756d53657400005900000008000000040000009d000000387d11002800000044da1000420000004a000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f696e64696365732f7372632f6c69622e72730000387d110028000000a0da1000450000005c000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f6d656d626572736869702f7372632f6c69622e727300000044da1000420000004a0000000100000054696d657374616d7020746f6f2066617220696e2066757475726520746f206163636570744765747320616e64206465636f6465732074696d657374616d7020696e686572656e742064617461496e646963657300000000fcdb10000b000000000000000000000007dc10000f000000000000000000000000000000000000000000000000000000000000003897110018dc1000000000000000000028dc10000100000000000000010000000000000030dc100007000000010100000000000007dc10000f00000000000000255c1100110000000000000000000000000000000000000038971100b4e61000000000000000000038dc10000100000000000000010000004e657874456e756d536574543a3a4163636f756e74496e64657800003700000000000000010000009c00000056dc10001f000000456e756d5365740040dc1000160000002054686520656e756d65726174696f6e20736574732e20546865206e657874206672656520656e756d65726174696f6e207365742e496e6469636573204e657874456e756d536574e9dd10001c000000b8dc1000440000009e00000003000000c5dd100024000000b8dc100044000000a7000000030000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f6578656375746976652f7372632f6c69622e727393dd100032000000b8dc10004400000001010000030000006cdd100027000000b8dc100044000000090100000400000044dd100028000000b8dc1000440000000f0100000300000053746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e446967657374206974656d206d757374206d6174636820746861742063616c63756c617465642e4e756d626572206f6620646967657374206974656d73206d757374206d6174636820746861742063616c63756c617465642e5472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642e506172656e7420686173682073686f756c642062652076616c69642e0000000000000034de1000030000000000000038de100001000000000000000000000050de100009000000000000007365740000000000d2df10000300000000000000d5df10001200000098de1000160000003897110000000000aede10005600000004df10003600000038971100000000003adf1000510000008bdf10001100000038971100000000009cdf10003600000020536574207468652063757272656e742074696d652e20546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6e2070686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e205468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e742073706563696669656420627920604d696e696d756d506572696f64602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652060496e686572656e74602e6e6f77436f6d706163743c543a3a4d6f6d656e743e54696d657374616d7000000000a0e01000030000000000000000000000a3e01000090000000000000000000000000000000000000000000000000000000000000038971100ace010000000000000000000bce0100001000000000000000100000000000000c4e01000090000000000000000000000f7431100040000000000000000000000000000000000000000000000000000000000000038971100d0e010000000000000000000e0e010000100000000000000010000004e6f77543a3a4d6f6d656e74370000000000000001000000ab00000015e11000240000004469645570646174650000003700000000000000010000004f000000e8e010002d00000020446964207468652074696d657374616d7020676574207570646174656420696e207468697320626c6f636b3f2043757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e0000000000000074e110000d00000000000000a3e0100009000000000000003897110084e11000000000000000000094e1100004000000000000004d696e696d756d506572696f64000000370000000000000001000000bb000000b4e110005a0000000ee210005a00000068e2100059000000c1e210001c00000020546865206d696e696d756d20706572696f64206265747765656e20626c6f636b732e204265776172652074686174207468697320697320646966666572656e7420746f20746865202a65787065637465642a20706572696f6420746861742074686520626c6f636b2070726f64756374696f6e206170706172617475732070726f76696465732e20596f75722063686f73656e20636f6e73656e7375732073797374656d2077696c6c2067656e6572616c6c7920776f726b2077697468207468697320746f2064657465726d696e6520612073656e7369626c6520626c6f636b2074696d652e20652e672e20466f7220417572612c2069742077696c6c20626520646f75626c65207468697320706572696f64206f6e2064656661756c742073657474696e67732e0000000000000090e310000a000000000000009ce31000010000000000000000000000b4e31000030000000000000000000000cce310000d000000000000009ce31000010000000000000000000000dce31000030000000000000000000000f4e310000b0000000000000000e4100002000000000000000000000030e4100003000000000000000000000048e410000d0000000000000058e4100001000000000000000000000070e4100004000000000000006164645f6d656d6265720000000000005712110003000000000000000b4e11000c000000f2e510001f000000389711000000000011e610002d00000072656d6f76655f6d656d6265720000009ee51000240000003897110000000000c2e5100030000000737761705f6d656d626572000000000095e5100006000000000000000b4e11000c000000000000009be5100003000000000000000b4e11000c00000037e5100030000000389711000000000067e510002e00000072657365745f6d656d626572730000000000000030e510000700000000000000255c11001100000090e4100056000000e6e410001b000000389711000000000001e510002f000000204368616e676520746865206d656d6265727368697020746f2061206e6577207365742c20646973726567617264696e6720746865206578697374696e67206d656d626572736869702e204265206e69636520616e64207061737320606d656d6265727360207072652d736f727465642e204d6179206f6e6c792062652063616c6c65642066726f6d206052657365744f726967696e60206f7220726f6f742e6d656d626572732053776170206f7574206f6e65206d656d626572206072656d6f76656020666f7220616e6f746865722060616464602e204d6179206f6e6c792062652063616c6c65642066726f6d2060537761704f726967696e60206f7220726f6f742e72656d6f76656164642052656d6f76652061206d656d626572206077686f602066726f6d20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d206052656d6f76654f726967696e60206f7220726f6f742e204164642061206d656d626572206077686f6020746f20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d20604164644f726967696e60206f7220726f6f742e496e7374616e6365314d656d6265727368697000000000000000ace61000070000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100b4e610000000000000000000c4e610000100000000000000010000004d656d626572730037000000000000000100000050000000cce6100032000000205468652063757272656e74206d656d626572736869702c2073746f72656420617320616e206f726465726564205665632e000080e7100048000000b10100002300000080e7100048000000b20100002300000030e7100049000000870200001d0000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f736f72742e7273000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727330e71000490000009d0000003a00000030e7100049000000a400000030000000a0da1000450000005c00000001000000496e7374616e6365314d656d62657273686970204d656d62657273616c72656164792061206d656d626572626164206f726967696e6e6f742061206d656d62657200000080e7100048000000a10a00000e00000054e810001c00000056617269616e74206973206e6576657220636f6e737472756374656480e81000440000000a040000220000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f6c69622e727373746f72616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c69642074797065000000000000ea1000080000000000000008ea100003000000000000000000000020ea100001000000000000000000000028ea10000c000000000000008c43110002000000000000000000000034ea10000100000000000000000000003cea10000a0000000000000048ea100001000000000000000000000050ea100001000000000000000000000058ea10000f0000000000000068ea100001000000000000000000000070ea100001000000000000000000000078ea10000a0000000000000084ea100002000000000000000000000094ea1000020000000000000000000000a4ea10000800000000000000acea1000020000000000000000000000bcea100001000000000000005472616e73666572d043110009000000d0431100090000001144110007000000eeeb10005a000000496e7374616e746961746564b7eb100037000000436f646553746f7265640000d94311000400000089eb10002e0000005363686564756c655570646174656400763411000300000059eb100030000000446973706174636865640000d043110009000000f743110004000000eeea10004e0000003ceb10001d000000436f6e7472616374d043110009000000e7ea100007000000c4ea10002300000020416e206576656e742066726f6d20636f6e7472616374206f66206163636f756e742e5665633c75383e20412063616c6c2077617320646973706174636865642066726f6d2074686520676976656e206163636f756e742e2054686520626f6f6c207369676e616c73207768657468657220697420776173207375636365737366756c20657865637574696f6e206f72206e6f742e20547269676765726564207768656e207468652063757272656e74207363686564756c6520697320757064617465642e20436f646520776974682074686520737065636966696564206861736820686173206265656e2073746f7265642e20436f6e7472616374206465706c6f7965642062792061646472657373206174207468652073706563696669656420616464726573732e205472616e736665722068617070656e6564206066726f6d6020746f2060746f60207769746820676976656e206076616c7565602061732070617274206f662061206063616c6c60206f722060696e7374616e7469617465602e436f6e7472616374205072697374696e65436f6465436f6e747261637420436f646553746f72616765436f6e747261637420436f6e7472616374496e666f4f66436f6e747261637420476173507269636500000037000000000000000100000038000000c0ec10004a0000003200000006000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f63757276652e7273000000000000e8ed10000f00000000000000f8ed100001000000000000000000000010ee100003000000000000000000000028ee1000080000000000000030ee100002000000000000000000000060ee1000020000000000000000000000af861100040000000000000070ee1000040000000000000000000000d0ee100007000000000000000000000008ef10000b0000000000000014ef100004000000000000000000000074ef10000a0000000000000000000000c4ef10000f00000000000000d4ef100002000000000000000000000004f0100005000000000000007570646174655f7363686564756c65000000000054f6100008000000000000005cf6100008000000e4f510002d000000389711000000000011f61000430000007075745f636f64650000000092f3100009000000000000009bf310000c00000000000000e0f510000400000000000000e7ea10000700000054f5100057000000abf51000350000000000000046f1100004000000000000004b22110023000000000000005f551100050000000000000064551100150000000000000092f3100009000000000000009bf310000c00000000000000bbf310000400000000000000e7ea100007000000bff3100042000000389711000000000001f410004a0000004bf410002c00000077f4100046000000bdf41000520000000ff5100045000000696e7374616e7469617465000000000089f31000090000000000000064551100150000000000000092f3100009000000000000009bf310000c00000000000000a7f310000900000000000000b0f310000b00000000000000bbf310000400000000000000e7ea10000700000068f110006f0000003897110000000000d7f11000260000003897110000000000fdf11000500000004df21000410000008ef210005b000000e9f210005700000040f310002a0000006af310001f000000636c61696d5f737572636861726765000000000046f1100004000000000000000b4e11000c000000000000004af110000a0000000000000054f11000140000002cf010005c00000088f01000450000003897110000000000cdf010004e0000001bf110002b00000020416c6c6f777320626c6f636b2070726f64756365727320746f20636c61696d206120736d616c6c2072657761726420666f72206576696374696e67206120636f6e74726163742e204966206120626c6f636b2070726f6475636572206661696c7320746f20646f20736f2c206120726567756c61722075736572732077696c6c20626520616c6c6f77656420746f20636c61696d20746865207265776172642e20496620636f6e7472616374206973206e6f742065766963746564206173206120726573756c74206f6620746869732063616c6c2c206e6f20616374696f6e73206172652074616b656e20616e64207468652073656e646572206973206e6f7420656c696769626c6520666f7220746865207265776172642e646573746175785f73656e6465724f7074696f6e3c543a3a4163636f756e7449643e20496e7374616e7469617465732061206e657720636f6e74726163742066726f6d207468652060636f646568617368602067656e65726174656420627920607075745f636f6465602c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e20496e7374616e74696174696f6e20697320657865637574656420617320666f6c6c6f77733a202d205468652064657374696e6174696f6e206164647265737320697320636f6d7075746564206261736564206f6e207468652073656e64657220616e642068617368206f662074686520636f64652e202d2054686520736d6172742d636f6e7472616374206163636f756e7420697320637265617465642061742074686520636f6d707574656420616464726573732e202d20546865206063746f725f636f64656020697320657865637574656420696e2074686520636f6e74657874206f6620746865206e65776c792d63726561746564206163636f756e742e204275666665722072657475726e656420202061667465722074686520657865637574696f6e206973207361766564206173207468652060636f646560206f6620746865206163636f756e742e205468617420636f64652077696c6c20626520696e766f6b656420202075706f6e20616e792063616c6c2072656365697665642062792074686973206163636f756e742e202d2054686520636f6e747261637420697320696e697469616c697a65642e656e646f776d656e746761735f6c696d6974436f6d706163743c4761733e636f64655f68617368436f6465486173683c543e64617461204d616b657320612063616c6c20746f20616e206163636f756e742c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e202a20496620746865206163636f756e74206973206120736d6172742d636f6e7472616374206163636f756e742c20746865206173736f63696174656420636f64652077696c6c20626520657865637574656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e202a20496620746865206163636f756e74206973206120726567756c6172206163636f756e742c20616e792076616c75652077696c6c206265207472616e736665727265642e202a204966206e6f206163636f756e742065786973747320616e64207468652063616c6c2076616c7565206973206e6f74206c657373207468616e20606578697374656e7469616c5f6465706f736974602c206120726567756c6172206163636f756e742077696c6c206265206372656174656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e2053746f7265732074686520676976656e2062696e617279205761736d20636f646520696e746f2074686520636861696e27732073746f7261676520616e642072657475726e73206974732060636f646568617368602e20596f752063616e20696e7374616e746961746520636f6e747261637473206f6e6c7920776974682073746f72656420636f64652e636f6465205570646174657320746865207363686564756c6520666f72206d65746572696e6720636f6e7472616374732e20546865207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652073746f726564207363686564756c652e7363686564756c655363686564756c6500000000ccf81000080000000000000000000000d4f810000300000000000000000000000000000000000000000000000000000000000000389711007cf910000000000000000000d8f8100001000000000000000100000000000000e0f810000f00000000000000000000005cf61000080000000000000000000000000000000000000000000000000000000000000038971100f0f81000000000000000000000f910000100000000000000010000000000000008f910000c0000000101000000000000b0f310000b00000000000000e7ea100007000000000000000000000000000000000000003897110014f91000000000000000000024f91000010000000000000000000000000000002cf910000b0000000101000000000000b0f310000b0000000000000037f9100016000000000000000000000000000000000000003897110050f91000000000000000000060f910000100000000000000000000000000000068f910000e000000000000000000000076f910000300000000000000000000000000000000000000000000000000000000000000389711007cf9100000000000000000008cf910000100000000000000010000000000000094f910000e00000001010000000000000b4e11000c00000000000000a2f910000f0000000000000000000000000000000000000038971100b4f910000000000000000000c4f9100001000000000000000000000000000000ccf910000800000000000000000000007a6511000c0000000000000000000000000000000000000000000000000000000000000038971100d4f910000000000000000000e4f910000100000000000000010000004761735370656e744761730020fb10002000000043757272656e745363686564756c6500370000000000000001000000bc000000fbfa1000250000005072697374696e65436f64653700000000000000010000004f000000a2fa100059000000436f646553746f726167657761736d3a3a5072656661625761736d4d6f64756c650000003700000000000000010000004f00000049fa1000590000004163636f756e74436f756e746572753634000000370000000000000001000000ab00000034fa100015000000436f6e7472616374496e666f4f66436f6e7472616374496e666f3c543e0000003700000000000000010000004f0000000afa10002a0000004761735072696365370000000000000001000000bd000000ecf910001e00000020546865207072696365206f66206f6e6520756e6974206f66206761732e2054686520636f6465206173736f6369617465642077697468206120676976656e206163636f756e742e20546865207375627472696520636f756e7465722e2041206d617070696e67206265747765656e20616e206f726967696e616c20636f6465206861736820616e6420696e737472756d656e746564207761736d20636f64652c20726561647920666f7220657865637574696f6e2e2041206d617070696e672066726f6d20616e206f726967696e616c20636f6465206861736820746f20746865206f726967696e616c20636f64652c20756e746f756368656420627920696e737472756d656e746174696f6e2e2043757272656e7420636f7374207363686564756c6520666f7220636f6e7472616374732e20476173207370656e7420736f2066617220696e207468697320626c6f636b2e00000000c0fe10001300000000000000925111000e0000000000000038971100d4fe10000000000000000000e4fe100004000000000000000000000004ff100010000000000000007a6511000c00000000000000389711005cff1000000000000000000014ff10000100000000000000000000001cff100011000000000000007634110003000000000000003897110030ff1000000000000000000040ff100002000000000000000000000050ff10000b000000000000007a6511000c00000000000000389711005cff100000000000000000006cff100001000000000000000000000074ff100011000000000000007a6511000c000000000000003897110088ff1000000000000000000098ff1000070000000000000000000000d0ff10000f000000000000007a6511000c0000000000000038971100e0ff10000000000000000000f0ff1000020000000000000000000000000011000b000000000000007a6511000c00000000000000389711007c00110000000000000000000c001100010000000000000000000000140011000b000000000000007a6511000c00000000000000389711007c0011000000000000000000200011000100000000000000000000002800110012000000000000007a6511000c00000000000000389711007c00110000000000000000003c0011000100000000000000000000004400110012000000000000007a6511000c000000000000003897110058001100000000000000000068001100010000000000000000000000700011000b000000000000007a6511000c00000000000000389711007c00110000000000000000008c0011000200000000000000000000009c0011000b00000000000000d4f81000030000000000000038971100cc0011000000000000000000a8001100020000000000000000000000b80011001200000000000000d4f81000030000000000000038971100cc0011000000000000000000dc001100020000000000000000000000ec001100080000000000000076341100030000000000000038971100f4001100000000000000000004011100020000000000000000000000140111000c000000000000007634110003000000000000003897110020011100000000000000000030011100010000000000000000000000380111000d00000000000000d4f810000300000000000000389711004801110000000000000000005801110002000000000000005369676e6564436c61696d48616e646963617000370000000000000001000000be000000080711003800000038971100000000004007110043000000830711001a000000546f6d6273746f6e654465706f736974d30611003500000053746f7261676553697a654f6666736574000000370000000000000001000000a90000005606110054000000aa0611002900000052656e74427974654665650037000000000000000100000099000000090611004d00000052656e744465706f7369744f6666736574000000370000000000000001000000bf0000009104110041000000d2041100160000003897110000000000e80411005a00000042051100560000009805110053000000eb0511001e00000053757263686172676552657761726400370000000000000001000000c00000003e04110039000000770411001a0000005472616e736665724665650019041100250000004372656174696f6e46656500f2031100270000005472616e73616374696f6e426173654665650000bb031100370000005472616e73616374696f6e4279746546656500003700000000000000010000009b0000007803110043000000436f6e7472616374466565003700000000000000010000009a0000002103110050000000710311000700000043616c6c4261736546656500cc02110047000000130311000e000000496e7374616e7469617465426173654665650000370000000000000001000000c1000000760211004e000000c4021100080000004d61784465707468370000000000000001000000c20000001c0211004c000000680211000e0000004d617856616c756553697a65370000000000000001000000c3000000ce0111004e000000426c6f636b4761734c696d6974000000370000000000000001000000c40000006801110049000000b10111001d00000020546865206d6178696d756d20616d6f756e74206f6620676173207468617420636f756c6420626520657870656e6465642070657220626c6f636b2e204120726561736f6e61626c652064656661756c742076616c75652069732031305f3030305f3030302e20546865206d6178696d756d2073697a65206f6620612073746f726167652076616c756520696e2062797465732e204120726561736f6e61626c652064656661756c74206973203136204b69422e20546865206d6178696d756d206e657374696e67206c6576656c206f6620612063616c6c2f696e7374616e746961746520737461636b2e204120726561736f6e61626c652064656661756c742076616c7565206973203130302e20546865206261736520666565206368617267656420666f7220696e7374616e74696174696e67206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203137352e20546865206261736520666565206368617267656420666f722063616c6c696e6720696e746f206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203133352e205468652066656520726571756972656420746f20696e7374616e7469617465206120636f6e747261637420696e7374616e63652e204120726561736f6e61626c652064656661756c742076616c75652069732032312e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b20746865207065722d6279746520706f7274696f6e2e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b2074686520626173652e205468652066656520726571756972656420746f2063726561746520616e206163636f756e742e205468652066656520726571756972656420746f206d616b652061207472616e736665722e205265776172642074686174206973207265636569766564206279207468652070617274792077686f736520746f75636820686173206c656420746f2072656d6f76616c206f66206120636f6e74726163742e2054686520616d6f756e74206f662066756e6473206120636f6e74726163742073686f756c64206465706f73697420696e206f7264657220746f206f66667365742074686520636f7374206f66206f6e6520627974652e204c6574277320737570706f736520746865206465706f73697420697320312c303030204255202862616c616e636520756e697473292f6279746520616e64207468652072656e7420697320312042552f627974652f6461792c207468656e206120636f6e7472616374207769746820312c3030302c3030302042552074686174207573657320312c303030206279746573206f662073746f7261676520776f756c6420706179206e6f2072656e742e20427574206966207468652062616c616e6365207265647563656420746f203530302c30303020425520616e64207468652073746f7261676520737461796564207468652073616d6520617420312c3030302c207468656e20697420776f756c6420706179203530302042552f6461792e205072696365206f6620612062797465206f662073746f7261676520706572206f6e6520626c6f636b20696e74657276616c2e2053686f756c642062652067726561746572207468616e20302e2053697a65206f66206120636f6e7472616374206174207468652074696d65206f6620696e7374616e746961696f6e2e205468697320697320612073696d706c652077617920746f20656e73757265207468617420656d70747920636f6e747261637473206576656e7475616c6c7920676574732064656c657465642e20546865206d696e696d756d20616d6f756e7420726571756972656420746f2067656e6572617465206120746f6d6273746f6e652e204e756d626572206f6620626c6f636b2064656c617920616e2065787472696e73696320636c61696d20737572636861726765206861732e205768656e20636c61696d207375726368617267652069732063616c6c656420627920616e2065787472696e736963207468652072656e7420697320636865636b656420666f722063757272656e745f626c6f636b202d2064656c617943616e6e6f7420726573746f726520746f20696e6578697374696e67206f7220616c69766520636f6e74726163746d656d6f727976616c69646174696f6e3a20696d706f727420656e74727920706f696e747320746f2061206e6f6e2d6578697374656e74207479706543616e6e6f7420696d706f727420676c6f62616c736d6f64756c6520696d706f7274732061206e6f6e2d6578697374656e742066756e6374696f6e6d6f64756c6520696d706f72747320606578745f7072696e746c6e60206275742064656275672066656174757265732064697361626c656443616e6e6f7420696d706f7274207461626c65736d6f64756c652068617320696d706f7274732066726f6d2061206e6f6e2d27656e7627206e616d6573706163654d656d6f727920696d706f7274206d757374206861766520746865206669656c64206e616d6520276d656d6f7279274d756c7469706c65206d656d6f727920696d706f72747320646566696e65644d6178696d756d206e756d626572206f662070616765732073686f756c6420626520616c77617973206465636c617265642e52657175657374656420696e697469616c206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520726571756573746564206d6178696d756d4d6178696d756d206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520636f6e66696775726564206d6178696d756d2e64656661756c743a000000387d11002800000080e8100044000000c80100000100000080e8100044000000c8010000010000006e6577207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e2063757272656e74496e76616c69642073757263686172676520636c61696d3a206f726967696e206d757374206265207369676e6564206f7220696e686572656e7420616e6420617578696c696172792073656e646572206f6e6c792070726f7669646564206f6e20696e686572656e74417574686f72697479446973636f76657279204b657973000000387d110028000000c80a11004e00000034000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f617574686f726974792d646973636f766572792f7372632f6c69622e72730000c80a11004e000000340000000100000000000000ac0b11000500000000000000b40b1100010000000000000000000000bc0b1100010000000000000000000000c40b11000a00000000000000a8431100010000000000000000000000d00b1100010000000000000000000000d80b11000a00000000000000b40b1100010000000000000000000000bc0b110001000000000000005375646964000000f7431100040000001e0c1100180000004b65794368616e6765640000e20b11003c0000005375646f4173446f6e6520546865207375646f6572206a757374207377697463686564206964656e746974793b20746865206f6c64206b657920697320737570706c6965642e2041207375646f206a75737420746f6f6b20706c6163652e707265636f6e646974696f6e3a20616c6c20696d706f7274732073686f756c6420626520636865636b656420616761696e737420746865207369676e617475726573206f6620636f72726573706f6e64696e670a09090909090966756e6374696f6e7320646566696e65642062792060646566696e655f656e762160206d6163726f206279207468652075736572206f6620746865206d6163726f3b0a0909090909097369676e617475726573206f662074686573652066756e6374696f6e7320646566696e6564206279206024706172616d73603b0a09090909090963616c6c7320616c77617973206d616465207769746820617267756d656e7473207479706573206f662077686963682061726520646566696e65642062792074686520636f72726573706f6e64696e6720696d706f7274733b0a09090909090974687573207479706573206f6620617267756d656e74732073686f756c6420626520657175616c20746f2074797065206c69737420696e206024706172616d736020616e640a0909090909096c656e677468206f6620617267756d656e74206c69737420616e642024706172616d732073686f756c6420626520657175616c3b0a0909090909097468757320746869732063616e206e6576657220626520604e6f6e65603b0a0909090909097165643b0a09090909090972657475726e2074797065206572726f7276616c69646174696f6e206572726f72647572696e6720657865637574696f6e00387d110028000000740e11003f00000068000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f7375646f2f7372632f6c69622e727300740e11003f00000068000000010000006f6e6c79207468652063757272656e74207375646f206b65792063616e207375646f5375646f204b65796f6e6c79207468652063757272656e74207375646f206b65792063616e206368616e676520746865207375646f206b657900400f1100480000009b0a00000a000000400f110048000000a10a00000e0000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e7273000000000c1011000400000000000000684a1100010000000000000000000000101011000a00000000000000000000006010110007000000000000006810110001000000000000000000000080101100090000000000000000000000c81011000700000000000000d0101100020000000000000000000000001111000b000000000000007375646fc81211004e0000003897110000000000bd111100340000003897110000000000c54d11000b000000d04d110008000000f1111100190000000a121100180000002212110035000000d84d11000c0000007365745f6b65790000000000fc20110003000000000000004b221100230000005a1211005d0000003897110000000000bd111100340000003897110000000000c54d11000b000000d04d110008000000f111110019000000b712110011000000d84d11000c0000007375646f5f617300000000005712110003000000000000004b221100230000000000000058531100080000000000000060531100100000005811110054000000ac111100110000003897110000000000bd111100340000003897110000000000c54d11000b000000d04d110008000000f1111100190000000a121100180000002212110035000000d84d11000c0000002041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c207769746820605369676e656460206f726967696e2066726f6d206120676976656e206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2e202d204c696d697465642073746f726167652072656164732e202d204f6e6520444220777269746520286576656e74292e202d20556e6b6e6f776e20776569676874206f662064657269766174697665206070726f706f73616c6020657865637574696f6e2e77686f2041757468656e74696361746573207468652063757272656e74207375646f206b657920616e6420736574732074686520676976656e204163636f756e7449642028606e6577602920617320746865206e6577207375646f206b65792e202d204f6e65204442206368616e67652e2041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c20776974682060526f6f7460206f726967696e2e5375646f000000000000741311000300000000000000000000000b4e11000c0000000000000000000000000000000000000000000000000000000000000038971100781311000000000000000000881311000100000000000000010000004b657900370000000000000001000000c500000090131100210000002054686520604163636f756e74496460206f6620746865207375646f206b65792e0000003b1411000d0000001e1411001b0000003914110002000000dc131100420000001f020000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6e6f64652f72756e74696d652f7372632f6c69622e727342616420696e70757420646174612070726f766964656420746f203a20657865637574655f626c6f636b5014110010000000696e697469616c697a655f626c6f636b681411000f0000006170706c795f65787472696e736963008014110013000000696e686572656e745f65787472696e73696373009c1411000f000000636865636b5f696e686572656e747300b41411001400000076616c69646174655f7472616e73616374696f6ed01411000f0000006f6666636861696e5f776f726b657200e8141100040000007369676ef4141100060000007665726966790000041511000d0000006163636f756e745f6e6f6e6365000000af86110004000000241511001500000067656e65726174655f73657373696f6e5f6b65797300000000000000c01511000600000000000000c8151100010000000000000000000000d0151100010000000000000000000000d81511000500000000000000e0151100020000000000000000000000f0151100010000000000000000000000f81511001a00000000000000108d110001000000000000000000000014161100020000000000000052657761726400001144110007000000c616110038000000536c617368000000d04311000900000011441100070000007d161100490000004f6c64536c617368696e675265706f7274446973636172646564000024161100470000006b1611001200000020416e206f6c6420736c617368696e67207265706f72742066726f6d2061207072696f72206572612077617320646973636172646564206265636175736520697420636f756c64206e6f742062652070726f6365737365642e204f6e652076616c696461746f722028616e6420697473206e6f6d696e61746f72732920686173206265656e20736c61736865642062792074686520676976656e20616d6f756e742e20416c6c2076616c696461746f72732068617665206265656e2072657761726465642062792074686520676976656e2062616c616e63652e5374616b696e672043757272656e7445726153746172745374616b696e67204e6f6d696e61746f727368656164206f66205374616b696e67204e6f6d696e61746f72735374616b696e672056616c696461746f727368656164206f66205374616b696e672056616c696461746f72735374616b696e67205374616b6572735374616b696e6720426f6e6465645374616b696e67204c65646765725374616b696e672050617965655374616b696e672043757272656e74456c65637465640000000000f81911000400000000000000fc191100030000000000000000000000441a11000f0000000000000000000000bc1a11000a00000000000000c81a1100010000000000000000000000e01a11000e0000000000000000000000501b11000600000000000000581b1100010000000000000000000000701b1100170000000000000000000000281c11001100000000000000389711000000000000000000000000003c1c1100100000000000000000000000bc1c11000800000000000000c41c1100010000000000000000000000dc1c11000b0000000000000000000000341d110008000000000000003c1d1100010000000000000000000000541d11000b0000000000000000000000ac1d1100050000000000000038971100000000000000000000000000b41d11000b00000000000000000000000c1e11000900000000000000181e1100010000000000000000000000301e11000b0000000000000000000000881e11000e00000000000000981e1100010000000000000000000000b01e11000b0000000000000000000000081f110013000000000000001c1f1100010000000000000000000000341f11000100000000000000000000003c1f11000d00000000000000389711000000000000000000000000004c1f1100050000000000000000000000741f11000d0000000000000038971100000000000000000000000000841f1100060000000000000000000000b41f11001100000000000000c81f1100010000000000000000000000e01f11000100000000000000626f6e6400000000412211000a000000000000004b22110023000000000000005f5511000500000000000000645511001500000000000000f12211000500000000000000f622110011000000d72b110059000000302c1100210000003897110000000000512c11004c00000038971100000000009d2c1100490000003897110000000000c54d11000b000000e62c110035000000d04d1100080000001b2d11001a0000003897110000000000352d11005b000000902d110049000000d84d11000c000000626f6e645f6578747261000000000000c92b11000e000000000000006455110015000000a32a110059000000fc2a11000d0000003897110000000000092b1100540000005d2b110059000000b62b11001300000038971100000000005a211100550000003897110000000000c54d11000b000000af2111003a000000d04d1100080000001d55110010000000d84d11000c000000756e626f6e640000000000005f55110005000000000000006455110015000000c8261100550000001d271100400000005d271100490000003897110000000000a627110052000000f8271100300000003897110000000000282811004f000000772811004f000000c62811003f00000038971100000000009c22110055000000389711000000000005291100260000003897110000000000c54d11000b0000002b29110050000000e9211100260000007b29110059000000d42911005c000000302a1100690000001d55110010000000992a11000a00000077697468647261775f756e626f6e646564000000c12411004b00000038971100000000000c2511004d000000592511001300000038971100000000009c2211005500000038971100000000006c2511001b0000003897110000000000c54d11000b0000008725110055000000dc251100510000002d2611003d0000006a2611005e0000000f22110032000000d84d11000c00000076616c696461746500000000a02411000500000000000000a52411001c000000662411003a0000003897110000000000232111003700000038971100000000009c221100550000003897110000000000c54d11000b000000af2111003a000000e9211100260000000f22110032000000d84d11000c0000006e6f6d696e617465000000003724110007000000000000003e241100280000004e231100440000003897110000000000232111003700000038971100000000009c221100550000003897110000000000c54d11000b0000009223110049000000db231100260000000124110036000000d84d11000c0000006368696c6c00000007231100320000003897110000000000232111003700000038971100000000009c221100550000003897110000000000c54d11000b000000af2111003a00000039231100150000000f22110032000000d84d11000c0000007365745f706179656500000000000000f12211000500000000000000f6221100110000006e2211002e0000003897110000000000232111003700000038971100000000009c221100550000003897110000000000c54d11000b000000af2111003a000000e9211100260000000f22110032000000d84d11000c0000007365745f636f6e74726f6c6c6572000000000000412211000a000000000000004b22110023000000ff201100240000003897110000000000232111003700000038971100000000005a211100550000003897110000000000c54d11000b000000af2111003a000000e9211100260000000f22110032000000d84d11000c0000007365745f76616c696461746f725f636f756e740000000000fc2011000300000000000000fa4e11000c000000dc20110020000000666f7263655f6e6f5f65726173000000b02011002c0000003897110000000000c54d11000b000000a020110010000000d84d11000c000000666f7263655f6e65775f657261000000252011005300000078201100280000003897110000000000c54d11000b000000a020110010000000d84d11000c0000007365745f696e76756c6e657261626c6573000000000000001b2011000a00000000000000255c110011000000e81f11003300000020536574207468652076616c696461746f72732077686f2063616e6e6f7420626520736c61736865642028696620616e79292e76616c696461746f727320466f72636520746865726520746f2062652061206e6577206572612061742074686520656e64206f6620746865206e6578742073657373696f6e2e20416674657220746869732c2069742077696c6c20626520726573657420746f206e6f726d616c20286e6f6e2d666f7263656429206265686176696f75722e202d204e6f20617267756d656e74732e20466f72636520746865726520746f206265206e6f206e6577206572617320696e646566696e6974656c792e2054686520696465616c206e756d626572206f662076616c696461746f72732e6e6577202852652d297365742074686520636f6e74726f6c6c6572206f6620612073746173682e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f206279207468652073746173682c206e6f742074686520636f6e74726f6c6c65722e202d20496e646570656e64656e74206f662074686520617267756d656e74732e20496e7369676e69666963616e7420636f6d706c65786974792e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732e202d2057726974657320617265206c696d6974656420746f2074686520606f726967696e60206163636f756e74206b65792e636f6e74726f6c6c65723c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f75726365202852652d2973657420746865207061796d656e742074617267657420666f72206120636f6e74726f6c6c65722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2062792074686520636f6e74726f6c6c65722c206e6f74207468652073746173682e706179656552657761726444657374696e6174696f6e204465636c617265206e6f2064657369726520746f206569746865722076616c6964617465206f72206e6f6d696e6174652e202d20436f6e7461696e73206f6e6520726561642e204465636c617265207468652064657369726520746f206e6f6d696e6174652060746172676574736020666f7220746865206f726967696e20636f6e74726f6c6c65722e202d20546865207472616e73616374696f6e277320636f6d706c65786974792069732070726f706f7274696f6e616c20746f207468652073697a65206f66206074617267657473602c2077686963682069732063617070656420617420604d41585f4e4f4d494e4154494f4e53602e202d20426f74682074686520726561647320616e642077726974657320666f6c6c6f7720612073696d696c6172207061747465726e2e746172676574735665633c3c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f757263653e204465636c617265207468652064657369726520746f2076616c696461746520666f7220746865206f726967696e20636f6e74726f6c6c65722e707265667356616c696461746f7250726566733c42616c616e63654f663c543e3e2052656d6f766520616e7920756e6c6f636b6564206368756e6b732066726f6d207468652060756e6c6f636b696e67602071756575652066726f6d206f7572206d616e6167656d656e742e205468697320657373656e7469616c6c7920667265657320757020746861742062616c616e636520746f206265207573656420627920746865207374617368206163636f756e7420746f20646f2077686174657665722069742077616e74732e2053656520616c736f205b6043616c6c3a3a756e626f6e64605d2e202d20436f756c6420626520646570656e64656e74206f6e2074686520606f726967696e6020617267756d656e7420616e6420686f77206d7563682060756e6c6f636b696e6760206368756e6b732065786973742e2020497420696d706c6965732060636f6e736f6c69646174655f756e6c6f636b656460207768696368206c6f6f7073206f76657220604c65646765722e756e6c6f636b696e67602c2077686963682069732020696e6469726563746c7920757365722d636f6e74726f6c6c65642e20536565205b60756e626f6e64605d20666f72206d6f72652064657461696c2e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732c20796574207468652073697a65206f6620776869636820636f756c64206265206c61726765206261736564206f6e20606c6564676572602e205363686564756c65206120706f7274696f6e206f662074686520737461736820746f20626520756e6c6f636b656420726561647920666f72207472616e73666572206f75742061667465722074686520626f6e6420706572696f6420656e64732e2049662074686973206c656176657320616e20616d6f756e74206163746976656c7920626f6e646564206c657373207468616e20543a3a43757272656e63793a3a6d696e696d756d5f62616c616e636528292c207468656e20697420697320696e6372656173656420746f207468652066756c6c20616d6f756e742e204f6e63652074686520756e6c6f636b20706572696f6420697320646f6e652c20796f752063616e2063616c6c206077697468647261775f756e626f6e6465646020746f2061637475616c6c79206d6f7665207468652066756e6473206f7574206f66206d616e6167656d656e7420726561647920666f72207472616e736665722e204e6f206d6f7265207468616e2061206c696d69746564206e756d626572206f6620756e6c6f636b696e67206368756e6b73202873656520604d41585f554e4c4f434b494e475f4348554e4b5360292063616e20636f2d657869737473206174207468652073616d652074696d652e20496e207468617420636173652c205b6043616c6c3a3a77697468647261775f756e626f6e646564605d206e65656420746f2062652063616c6c656420666972737420746f2072656d6f766520736f6d65206f6620746865206368756e6b732028696620706f737369626c65292e2053656520616c736f205b6043616c6c3a3a77697468647261775f756e626f6e646564605d2e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204c696d697465642062757420706f74656e7469616c6c79206578706c6f697461626c6520636f6d706c65786974792e202d20456163682063616c6c20287265717569726573207468652072656d61696e646572206f662074686520626f6e6465642062616c616e636520746f2062652061626f766520606d696e696d756d5f62616c616e6365602920202077696c6c2063617573652061206e657720656e74727920746f20626520696e73657274656420696e746f206120766563746f722028604c65646765722e756e6c6f636b696e676029206b65707420696e2073746f726167652e202020546865206f6e6c792077617920746f20636c65616e207468652061666f72656d656e74696f6e65642073746f72616765206974656d20697320616c736f20757365722d636f6e74726f6c6c656420766961206077697468647261775f756e626f6e646564602e203c2f7765696768743e2041646420736f6d6520657874726120616d6f756e742074686174206861766520617070656172656420696e207468652073746173682060667265655f62616c616e63656020696e746f207468652062616c616e636520757020666f72207374616b696e672e20557365207468697320696620746865726520617265206164646974696f6e616c2066756e647320696e20796f7572207374617368206163636f756e74207468617420796f75207769736820746f20626f6e642e20556e6c696b65205b60626f6e64605d206f72205b60756e626f6e64605d20746869732066756e6374696f6e20646f6573206e6f7420696d706f736520616e79206c696d69746174696f6e206f6e2074686520616d6f756e7420746861742063616e2062652061646465642e6d61785f6164646974696f6e616c2054616b6520746865206f726967696e206163636f756e74206173206120737461736820616e64206c6f636b207570206076616c756560206f66206974732062616c616e63652e2060636f6e74726f6c6c6572602077696c6c20626520746865206163636f756e74207468617420636f6e74726f6c732069742e206076616c756560206d757374206265206d6f7265207468616e2074686520606d696e696d756d5f62616c616e636560207370656369666965642062792060543a3a43757272656e6379602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20627920746865207374617368206163636f756e742e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204d6f64657261746520636f6d706c65786974792e202d20546872656520657874726120444220656e74726965732e204e4f54453a2054776f206f66207468652073746f726167652077726974657320286053656c663a3a626f6e646564602c206053656c663a3a7061796565602920617265205f6e657665725f20636c65616e656420756e6c6573732074686520606f726967696e602066616c6c732062656c6f77205f6578697374656e7469616c206465706f7369745f20616e6420676574732072656d6f76656420617320647573742e5374616b696e6700000000683411000e0000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711006c36110000000000000000007c3411000100000000000000010000000000000084341100150000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711009c3411000000000000000000ac34110001000000000000000100000000000000b43411000d0000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100d03711000000000000000000c434110003000000000000000100000000000000dc3411000600000001010000000000000b4e11000c000000000000000b4e11000c00000000000000000000000000000000000000389711001c3511000000000000000000e434110001000000000000000000000000000000ec3411000600000001010000000000000b4e11000c00000000000000f23411002900000000000000000000000000000000000000389711001c35110000000000000000002c35110001000000000000000000000000000000343511000500000001010000000000000b4e11000c00000000000000f62211001100000000000000000000000000000000000000389711003c35110000000000000000004c35110001000000000000000100000000000000543511000a00000001010100000000000b4e11000c00000000000000a52411001c00000000000000000000000000000000000000389711006035110000000000000000007035110001000000000000000100000000000000783511000a00000001010100000000000b4e11000c00000000000000255c1100110000000000000000000000000000000000000038971100d0371100000000000000000084351100010000000000000001000000000000008c3511000700000001010000000000000b4e11000c0000000000000093351100240000000000000000000000000000000000000038971100b83511000000000000000000c835110004000000000000000100000000000000e83511000e0000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100d03711000000000000000000f835110001000000000000000100000000000000003611000a00000000000000000000000a3611000800000000000000000000000000000000000000000000000000000000000000389711006c361100000000000000000014361100010000000000000001000000000000001c3611000f00000000000000000000002b3611000b00000000000000000000000000000000000000000000000000000000000000389711003836110000000000000000004836110001000000000000000100000000000000503611001b00000000000000000000009f8d11000c00000000000000000000000000000000000000000000000000000000000000389711006c36110000000000000000007c36110001000000000000000100000000000000843611001600000000000000000000009a361100090000000000000000000000000000000000000000000000000000000000000038971100a43611000000000000000000b436110001000000000000000100000000000000bc3611000900000000000000000000007a6511000c0000000000000000000000000000000000000000000000000000000000000038971100c83611000000000000000000d836110003000000000000000100000000000000f0361100080000000000000000000000f83611000700000000000000000000000000000000000000000000000000000000000000389711000037110000000000000000001037110001000000000000000100000000000000183711001300000000000000000000002b37110007000000000000000000000000000000000000000000000000000000000000003897110034371100000000000000000044371100030000000000000001000000000000005c3711000a0000000000000000000000663711001d0000000000000000000000000000000000000000000000000000000000000038971100d0371100000000000000000084371100010000000000000001000000000000008c3711000f00000001010000000000000a36110008000000000000009b371100320000000000000000000000000000000000000038971100d03711000000000000000000e037110001000000000000000100000056616c696461746f72436f756e74753332000000da3d11002a0000004d696e696d756d56616c696461746f72436f756e74000000370000000000000001000000c60000008a3d110050000000496e76756c6e657261626c6573000000b63c1100560000000c3d1100530000005f3d11002b000000426f6e6465640000763c1100400000004c65646765725374616b696e674c65646765723c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e003700000000000000010000004f000000253c11005100000050617965650000003700000000000000010000004f000000ec3b11003900000056616c696461746f72730000370000000000000001000000c70000009b3b1100510000004e6f6d696e61746f72730000423b1100590000005374616b6572734578706f737572653c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e00370000000000000001000000c8000000853a110053000000d83a11004600000038971100000000001e3b11002400000043757272656e74456c65637465640000463a11003f00000043757272656e74457261457261496e64657800002f3a11001700000043757272656e7445726153746172744d6f6d656e744f663c543e0000370000000000000001000000ab000000113a11001e00000043757272656e74457261537461727453657373696f6e496e646578003700000000000000010000009c000000dd3911003400000043757272656e74457261506f696e74734561726e6564457261506f696e747300370000000000000001000000c90000009a39110043000000536c6f745374616b65000000370000000000000001000000980000001e3911004c00000038971100000000006a39110030000000466f726365457261466f7263696e67003700000000000000010000004f000000d738110047000000536c6173685265776172644672616374696f6e50657262696c6c0000370000000000000001000000ca000000603811003e00000038971100000000009e38110039000000426f6e646564457261735665633c28457261496e6465782c2053657373696f6e496e646578293e001738110049000000457261536c6173684a6f75726e616c5665633c536c6173684a6f75726e616c456e7472793c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3e00000037000000000000000100000050000000e83711002f00000020416c6c20736c617368657320746861742068617665206f6363757272656420696e206120676976656e206572612e2041206d617070696e672066726f6d207374696c6c2d626f6e646564206572617320746f207468652066697273742073657373696f6e20696e646578206f662074686174206572612e205468652070657263656e74616765206f662074686520736c617368207468617420697320646973747269627574656420746f207265706f72746572732e205468652072657374206f662074686520736c61736865642076616c75652069732068616e646c6564206279207468652060536c617368602e205472756520696620746865206e6578742073657373696f6e206368616e67652077696c6c2062652061206e657720657261207265676172646c657373206f6620696e6465782e2054686520616d6f756e74206f662062616c616e6365206163746976656c79206174207374616b6520666f7220656163682076616c696461746f7220736c6f742c2063757272656e746c792e2054686973206973207573656420746f20646572697665207265776172647320616e642070756e6973686d656e74732e205265776172647320666f72207468652063757272656e74206572612e205573696e6720696e6469636573206f662063757272656e7420656c6563746564207365742e205468652073657373696f6e20696e646578206174207768696368207468652063757272656e742065726120737461727465642e20546865207374617274206f66207468652063757272656e74206572612e205468652063757272656e742065726120696e6465782e205468652063757272656e746c7920656c65637465642076616c696461746f7220736574206b65796564206279207374617368206163636f756e742049442e204e6f6d696e61746f727320666f72206120706172746963756c6172206163636f756e74207468617420697320696e20616374696f6e207269676874206e6f772e20596f752063616e27742069746572617465207468726f7567682076616c696461746f727320686572652c2062757420796f752063616e2066696e64207468656d20696e207468652053657373696f6e206d6f64756c652e2054686973206973206b6579656420627920746865207374617368206163636f756e742e20546865206d61702066726f6d206e6f6d696e61746f72207374617368206b657920746f2074686520736574206f66207374617368206b657973206f6620616c6c2076616c696461746f727320746f206e6f6d696e6174652e20546865206d61702066726f6d202877616e6e616265292076616c696461746f72207374617368206b657920746f2074686520707265666572656e636573206f6620746861742076616c696461746f722e2057686572652074686520726577617264207061796d656e742073686f756c64206265206d6164652e204b657965642062792073746173682e204d61702066726f6d20616c6c2028756e6c6f636b6564292022636f6e74726f6c6c657222206163636f756e747320746f2074686520696e666f20726567617264696e6720746865207374616b696e672e204d61702066726f6d20616c6c206c6f636b65642022737461736822206163636f756e747320746f2074686520636f6e74726f6c6c6572206163636f756e742e20416e792076616c696461746f72732074686174206d6179206e6576657220626520736c6173686564206f7220666f726369626c79206b69636b65642e20497427732061205665632073696e63652074686579277265206561737920746f20696e697469616c697a6520616e642074686520706572666f726d616e636520686974206973206d696e696d616c2028776520657870656374206e6f206d6f7265207468616e20666f757220696e76756c6e657261626c65732920616e64207265737472696374656420746f20746573746e6574732e204d696e696d756d206e756d626572206f66207374616b696e67207061727469636970616e7473206265666f726520656d657267656e637920636f6e646974696f6e732061726520696d706f7365642e2054686520696465616c206e756d626572206f66207374616b696e67207061727469636970616e74732e00000000743e11000e000000000000009f8d11000c0000000000000038971100843e11000000000000000000943e11000100000000000000000000009c3e11000f000000000000000a361100080000000000000038971100ac3e11000000000000000000bc3e1100010000000000000053657373696f6e735065724572610000370000000000000001000000a5000000fd3e11001c000000426f6e64696e674475726174696f6e00370000000000000001000000cb000000c43e110039000000204e756d626572206f6620657261732074686174207374616b65642066756e6473206d7573742072656d61696e20626f6e64656420666f722e204e756d626572206f662073657373696f6e7320706572206572612e5374616b696e6720536c6f745374616b650000603f110019000000803f110048000000bb0100002d0000005374616b696e6720457261536c6173684a6f75726e616c0000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f6f70732f61726974682e72735374616b696e6720496e76756c6e657261626c6573000000387d110028000000f83f1100420000009c020000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f7374616b696e672f7372632f6c69622e72730000f83f1100420000009c02000001000000636f6e74726f6c6c657220616c72656164792070616972656463616e206e6f7420626f6e6420776974682076616c7565206c657373207468616e206d696e696d756d2062616c616e6365737461736820616c726561647920626f6e6465646e6f7420612073746173686e6f74206120636f6e74726f6c6c657263616e206e6f74207363686564756c65206d6f726520756e6c6f636b206368756e6b73746172676574732063616e6e6f7420626520656d7074790000000000e44211000800000000000000ec42110002000000000000000000000038971100000000000000000000000000fc421100060000000000000004431100030000000000000000000000389711000000000000000000000000001c4311000e0000000000000038971100000000000000000000000000389711000000000000000000000000002a431100070000000000000034431100020000000000000000000000389711000000000000000000000000004443110006000000000000004c431100010000000000000000000000389711000000000000000000000000005443110009000000000000004c431100010000000000000000000000389711000000000000000000000000005d43110009000000000000004c4311000100000000000000000000003897110000000000000000000000000066431100080000000000000070431100020000000000000000000000389711000000000000000000000000008043110009000000000000008c431100020000000000000000000000389711000000000000000000000000009c4311000b00000000000000a843110001000000000000000000000038971100000000000000000000000000b04311000600000000000000b843110003000000000000000000000038971100000000000000000050726f706f736564084411000900000011441100070000005461626c6564000008441100090000001144110007000000184411000e00000045787465726e616c5461626c656453746172746564000000e84311000f000000fb4311000d0000005061737365640000e84311000f0000004e6f7450617373656443616e63656c6c656445786563757465640000e84311000f000000f74311000400000044656c656761746564000000d043110009000000d043110009000000556e64656c65676174656400d0431100090000005665746f65640000d043110009000000d943110004000000dd4311000b0000004163636f756e74496448617368426c6f636b4e756d6265725265666572656e64756d496e646578626f6f6c566f74655468726573686f6c6450726f70496e64657842616c616e63655665633c4163636f756e7449643e44656d6f637261637920566f74654f6644656d6f6372616379205265666572656e64756d496e666f4f6644656d6f63726163792044656c65676174696f6e7368656164206f662044656d6f63726163792044656c65676174696f6e7344656d6f6372616379204469737061746368517565756544656d6f637261637920566f74657273466f7244656d6f6372616379205075626c696350726f70730000005045110048000000a10a00000e00000044656d6f6372616379204465706f7369744f664e6f207075626c69632070726f706f73616c732077616974696e6743616e6e6f7420696e6a6563742061207265666572656e64756d207468617420656e6473206561726c696572207468616e2070726563656564696e67207265666572656e64756d000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727344656d6f6372616379204e65787445787465726e616c4e6f2065787465726e616c2070726f706f73616c2077616974696e67000000000000b84811000700000000000000c0481100020000000000000000000000f0481100060000000000000000000000204911000600000000000000284911000100000000000000000000004049110006000000000000000000000070491100040000000000000074491100020000000000000000000000a4491100070000000000000000000000dc4911000a0000000000000074491100020000000000000000000000e8491100070000000000000000000000204a11001000000000000000304a1100010000000000000000000000484a1100020000000000000000000000584a11001000000000000000684a1100010000000000000000000000804a1100020000000000000000000000904a11001900000000000000684a1100010000000000000000000000ac4a1100050000000000000000000000d44a11001800000000000000684a1100010000000000000000000000ec4a1100050000000000000000000000144b11000a00000000000000204b1100030000000000000000000000684b1100080000000000000000000000a84b11000d00000000000000b84b1100010000000000000000000000d04b1100010000000000000000000000d84b11001100000000000000ec4b1100010000000000000000000000044c11000100000000000000000000000c4c11000d000000000000001c4c1100030000000000000000000000644c11000100000000000000000000006c4c11000900000000000000784c1100010000000000000000000000904c1100050000000000000000000000b84c11000c0000000000000038971100000000000000000000000000c44c1100050000000000000000000000ec4c11000c00000000000000784c1100010000000000000000000000f84c1100050000000000000000000000204d11000800000000000000284d1100020000000000000000000000584d1100050000000000000000000000804d11000a00000000000000389711000000000000000000000000008c4d1100050000000000000070726f706f736500000000005853110008000000000000006053110010000000000000005f55110005000000000000006455110015000000f5541100280000003897110000000000c54d11000b000000d04d1100080000003f55110020000000d84d11000c0000007365636f6e640000000000005853110008000000000000002d55110012000000f5541100280000003897110000000000c54d11000b000000d04d1100080000001d55110010000000d84d11000c000000766f746500000000374f110009000000000000000a4f11001800000000000000704911000400000000000000f154110004000000755411004d000000c25411002f0000003897110000000000c54d11000b000000d04d110008000000565411001f000000d84d11000c00000070726f78795f766f74650000c453110054000000185411003e0000003897110000000000c54d11000b000000d04d110008000000565411001f000000d84d11000c000000656d657267656e63795f63616e63656c00000000374f11000900000000000000e84311000f00000070531100540000004c5311000c00000065787465726e616c5f70726f706f7365000000005853110008000000000000006053110010000000005311004c0000004c5311000c00000065787465726e616c5f70726f706f73655f6d616a6f726974790000009252110056000000e852110018000000389711000000000018521100530000006b5211002700000065787465726e616c5f70726f706f73655f64656661756c74a551110052000000f751110021000000389711000000000018521100530000006b52110027000000666173745f747261636b0000000000006f4f11000d000000000000007c4f11000700000000000000855111000d00000000000000925111000e00000000000000a05111000500000000000000925111000e000000834f110054000000d74f110059000000305011003b00000038971100000000006b5011003e000000a95011004b000000f450110055000000495111003c0000007665746f5f65787465726e616c000000000000006f4f11000d000000000000007c4f110007000000404f11002f00000063616e63656c5f7265666572656e64756d00000000000000374f110009000000000000000a4f110018000000224f11001500000063616e63656c5f71756575656400000000000000da4e11000400000000000000de4e11001700000000000000f54e11000500000000000000fa4e11000c00000000000000064f110004000000000000000a4f110018000000b24e1100280000007365745f70726f787900000000000000ad4e110005000000000000000b4e11000c000000874e1100260000003897110000000000c54d11000b000000f34d110016000000d84d11000c00000072657369676e5f70726f7879614e1100260000003897110000000000c54d11000b000000514e110010000000d84d11000c00000072656d6f76655f70726f78792b4e1100260000003897110000000000c54d11000b000000514e110010000000d84d11000c00000064656c656761746500000000094e110002000000000000000b4e11000c00000000000000174e11000a00000000000000214e11000a000000e44d11000f0000003897110000000000c54d11000b000000f34d110016000000d84d11000c000000756e64656c65676174650000b44d1100110000003897110000000000c54d11000b000000d04d110008000000d84d11000c00000020556e64656c656761746520766f74652e2023203c7765696768743e202d204f2831292e2023203c2f7765696768743e2044656c656761746520766f74652e202d204f6e6520657874726120444220656e7472792e746f543a3a4163636f756e744964636f6e76696374696f6e436f6e76696374696f6e20436c656172207468652070726f78792e2043616c6c6564206279207468652073746173682e202d204f6e6520444220636c6561722e20436c656172207468652070726f78792e2043616c6c6564206279207468652070726f78792e205370656369667920612070726f78792e2043616c6c6564206279207468652073746173682e70726f78792043616e63656c20612070726f706f73616c2071756575656420666f7220656e6163746d656e742e7768656e436f6d706163743c543a3a426c6f636b4e756d6265723e7768696368436f6d706163743c7533323e77686174436f6d706163743c5265666572656e64756d496e6465783e2052656d6f76652061207265666572656e64756d2e7265665f696e646578205665746f20616e6420626c61636b6c697374207468652065787465726e616c2070726f706f73616c20686173682e70726f706f73616c5f68617368543a3a48617368205363686564756c65207468652063757272656e746c792065787465726e616c6c792d70726f706f736564206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c656420696d6d6564696174656c792e204966207468657265206973206e6f2065787465726e616c6c792d70726f706f736564207265666572656e64756d2063757272656e746c792c206f72206966207468657265206973206f6e6520627574206974206973206e6f742061206d616a6f726974792d63617272696573207265666572656e64756d207468656e206974206661696c732e202d206070726f706f73616c5f68617368603a205468652068617368206f66207468652063757272656e742065787465726e616c2070726f706f73616c2e202d2060766f74696e675f706572696f64603a2054686520706572696f64207468617420697320616c6c6f77656420666f7220766f74696e67206f6e20746869732070726f706f73616c2e202d206064656c6179603a20546865206e756d626572206f6620626c6f636b20616674657220766f74696e672068617320656e64656420696e20617070726f76616c20616e6420746869732073686f756c64206265202020656e61637465642e20496e6372656173656420746f2060456d657267656e6379566f74696e67506572696f646020696620746f6f206c6f772e766f74696e675f706572696f64543a3a426c6f636b4e756d62657264656c6179205363686564756c652061206e656761746976652d7475726e6f75742d62696173207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20556e6c696b65206065787465726e616c5f70726f706f7365602c20626c61636b6c697374696e6720686173206e6f20656666656374206f6e207468697320616e64206974206d6179207265706c6163652061207072652d7363686564756c6564206065787465726e616c5f70726f706f7365602063616c6c2e205363686564756c652061206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e205363686564756c652061207265666572656e64756d20746f206265207461626c6564206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e70726f706f73616c426f783c543a3a50726f706f73616c3e205363686564756c6520616e20656d657267656e63792063616e63656c6c6174696f6e206f662061207265666572656e64756d2e2043616e6e6f742068617070656e20747769636520746f207468652073616d6520566f746520696e2061207265666572656e64756d206f6e20626568616c66206f6620612073746173682e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b20206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e202d204f6e65204442206368616e67652c206f6e6520444220656e7472792e20566f746520696e2061207265666572656e64756d2e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e566f74652050726f706f736520612073656e73697469766520616374696f6e20746f2062652074616b656e2e202d204f6e6520444220656e7472792e436f6d706163743c50726f70496e6465783e202d2054776f204442206368616e6765732c206f6e6520444220656e7472792e76616c7565436f6d706163743c42616c616e63654f663c543e3e44656d6f6372616379000000000000ac5a11000f0000000000000000000000084411000900000000000000000000000000000000000000000000000000000000000000389711006c5b11000000000000000000bc5a110001000000000000000100000000000000c45a11000b0000000000000000000000cf5a11002b0000000000000000000000000000000000000000000000000000000000000038971100385c11000000000000000000fc5a110001000000000000000100000000000000045b11000900000001010000000000000844110009000000000000000d5b1100210000000000000000000000000000000000000038971100305b11000000000000000000405b110001000000000000000000000000000000485b11000f0000000000000000000000e84311000f00000000000000000000000000000000000000000000000000000000000000389711006c5b11000000000000000000585b110001000000000000000100000000000000605b1100090000000000000000000000e84311000f00000000000000000000000000000000000000000000000000000000000000389711006c5b110000000000000000007c5b110001000000000000000100000000000000845b1100100000000101000000000000e84311000f00000000000000945b11002d0000000000000000000000000000000000000038971100b05c11000000000000000000c45b110001000000000000000000000000000000cc5b11000d0000000101000000000000925111000e00000000000000d95b11002b0000000000000000000000000000000000000038971100045c11000000000000000000145c1100010000000000000001000000000000001c5c1100090000000101000000000000e84311000f00000000000000255c1100110000000000000000000000000000000000000038971100385c11000000000000000000485c110001000000000000000100000000000000505c1100060000000101000000000000565c11001f00000000000000f1541100040000000000000000000000000000000000000038971100785c11000000000000000000885c110004000000000000000100000000000000a85c11000500000001010000000000000b4e11000c000000000000000b4e11000c0000000000000000000000000000000000000038971100b05c11000000000000000000c05c110002000000000000000000000000000000d05c11000b00000001010100000000000b4e11000c00000000000000db5c11001a0000000000000000000000000000000000000038971100f85c11000000000000000000085d110001000000000000000100000000000000105d1100150000000000000000000000f7431100040000000000000000000000000000000000000000000000000000000000000038971100ec5d11000000000000000000285d110002000000000000000100000000000000385d11000c0000000000000000000000445d11001c0000000000000000000000000000000000000000000000000000000000000038971100605d11000000000000000000705d110004000000000000000000000000000000905d11000900000001010000000000007c4f11000700000000000000995d1100230000000000000000000000000000000000000038971100bc5d11000000000000000000cc5d110002000000000000000000000000000000dc5d11000d00000001010000000000007c4f11000700000000000000f7431100040000000000000000000000000000000000000038971100ec5d11000000000000000000fc5d11000100000000000000010000005075626c696350726f70436f756e74006c6311003d0000005075626c696350726f70735665633c2850726f70496e6465782c20543a3a50726f706f73616c2c20543a3a4163636f756e744964293e00004c631100200000004465706f7369744f662842616c616e63654f663c543e2c205665633c543a3a4163636f756e7449643e290000370000000000000001000000a20000002b631100210000005265666572656e64756d436f756e7400df6211004c0000004e65787454616c6c790000003700000000000000010000009c000000ad621100320000005265666572656e64756d496e666f4f66285265666572656e64756d496e666f3c543a3a426c6f636b4e756d6265722c20543a3a50726f706f73616c3e29000000806211002d000000446973706174636851756575655665633c4f7074696f6e3c28543a3a50726f706f73616c2c205265666572656e64756d496e646578293e3e370000000000000001000000500000005062110030000000566f74657273466f725665633c543a3a4163636f756e7449643e0000370000000000000001000000500000002762110029000000566f74654f66285265666572656e64756d496e6465782c20543a3a4163636f756e744964290000003700000000000000010000004f000000e86011005800000040611100530000009361110057000000ea6111003d00000050726f78790000003700000000000000010000004f0000007a6011004c000000c66011002200000044656c65676174696f6e7328543a3a4163636f756e7449642c20436f6e76696374696f6e29000000370000000000000001000000cc0000002a601100500000004c6173745461626c656457617345787465726e616c000000ca5f110056000000206011000a0000004e65787445787465726e616c28543a3a50726f706f73616c2c20566f74655468726573686f6c6429370000000000000001000000cd000000dc5e110056000000325f110055000000875f110029000000b05f11001a000000426c61636b6c69737428543a3a426c6f636b4e756d6265722c205665633c543a3a4163636f756e7449643e29370000000000000001000000a20000004e5e110054000000a25e11003a00000043616e63656c6c6174696f6e730000003700000000000000010000004f000000045e11004a000000205265636f7264206f6620616c6c2070726f706f73616c7320746861742068617665206265656e207375626a65637420746f20656d657267656e63792063616e63656c6c6174696f6e2e2041207265636f7264206f662077686f207665746f656420776861742e204d6170732070726f706f73616c206861736820746f206120706f737369626c65206578697374656e7420626c6f636b206e756d6265722028756e74696c207768656e206974206d6179206e6f742062652072657375626d69747465642920616e642077686f207665746f65642069742e20546865207265666572656e64756d20746f206265207461626c6564207768656e6576657220697420776f756c642062652076616c696420746f207461626c6520616e2065787465726e616c2070726f706f73616c2e20546869732068617070656e73207768656e2061207265666572656e64756d206e6565647320746f206265207461626c656420616e64206f6e65206f662074776f20636f6e646974696f6e7320617265206d65743a202d20604c6173745461626c656457617345787465726e616c60206973206066616c7365603b206f72202d20605075626c696350726f70736020697320656d7074792e205472756520696620746865206c617374207265666572656e64756d207461626c656420776173207375626d69747465642065787465726e616c6c792e2046616c7365206966206974207761732061207075626c69632070726f706f73616c2e2047657420746865206163636f756e742028616e64206c6f636b20706572696f64732920746f20776869636820616e6f74686572206163636f756e742069732064656c65676174696e6720766f74652e2057686f2069732061626c6520746f20766f746520666f722077686f6d2e2056616c7565206973207468652066756e642d686f6c64696e67206163636f756e742c206b65792069732074686520766f74652d7472616e73616374696f6e2d73656e64696e67206163636f756e742e204765742074686520766f746520696e206120676976656e207265666572656e64756d206f66206120706172746963756c617220766f7465722e2054686520726573756c74206973206d65616e696e6766756c206f6e6c792069662060766f746572735f666f726020696e636c756465732074686520766f746572207768656e2063616c6c6564207769746820746865207265666572656e64756d2028796f75276c6c20676574207468652064656661756c742060566f7465602076616c7565206f7468657277697365292e20496620796f7520646f6e27742077616e7420746f20636865636b2060766f746572735f666f72602c207468656e20796f752063616e20616c736f20636865636b20666f722073696d706c65206578697374656e636520776974682060566f74654f663a3a657869737473602066697273742e204765742074686520766f7465727320666f72207468652063757272656e742070726f706f73616c2e205175657565206f66207375636365737366756c207265666572656e646120746f20626520646973706174636865642e20496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e20546865206e657874207265666572656e64756d20696e64657820746861742073686f756c642062652074616c6c6965642e20546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e6461207374617274656420736f206661722e2054686f73652077686f2068617665206c6f636b65642061206465706f7369742e20546865207075626c69632070726f706f73616c732e20556e736f727465642e20546865206e756d626572206f6620287075626c6963292070726f706f73616c7320746861742068617665206265656e206d61646520736f206661722e00000000000000fc6411000f00000000000000925111000e00000000000000389711000c65110000000000000000001c651100050000000000000000000000446511000c00000000000000925111000e0000000000000038971100e0651100000000000000000050651100010000000000000000000000586511000c00000000000000925111000e0000000000000038971100e06511000000000000000000646511000100000000000000000000006c6511000e000000000000007a6511000c000000000000003897110088651100000000000000000098651100010000000000000000000000a06511001500000000000000925111000e0000000000000038971100b86511000000000000000000c8651100010000000000000000000000d06511000d00000000000000925111000e0000000000000038971100e06511000000000000000000f06511000100000000000000456e6163746d656e74506572696f6400370000000000000001000000ce0000003f6711005c00000038971100000000009b6711004c000000e76711005a00000041681100270000004c61756e6368506572696f640667110039000000566f74696e67506572696f64d86611002e0000004d696e696d756d4465706f73697442616c616e63654f663c543e0000370000000000000001000000cf0000008b6611004d000000456d657267656e6379566f74696e67506572696f64000000370000000000000001000000d0000000506611003b000000436f6f6c6f6666506572696f64000000370000000000000001000000d1000000f86511005800000020506572696f6420696e20626c6f636b7320776865726520616e2065787465726e616c2070726f706f73616c206d6179206e6f742062652072652d7375626d6974746564206166746572206265696e67207665746f65642e204d696e696d756d20766f74696e6720706572696f6420616c6c6f77656420666f7220616e20656d657267656e6379207265666572656e64756d2e20546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e20486f77206f6674656e2028696e20626c6f636b7329206e6577207075626c6963207265666572656e646120617265206c61756e636865642e20546865206d696e696d756d20706572696f64206f66206c6f636b696e6720616e642074686520706572696f64206265747765656e20612070726f706f73616c206265696e6720617070726f76656420616e6420656e61637465642e2049742073686f756c642067656e6572616c6c792062652061206c6974746c65206d6f7265207468616e2074686520756e7374616b6520706572696f6420746f20656e73757265207468617420766f74696e67207374616b657273206861766520616e206f70706f7274756e69747920746f2072656d6f7665207468656d73656c7665732066726f6d207468652073797374656d20696e207468652063617365207768657265207468657920617265206f6e20746865206c6f73696e672073696465206f66206120766f74652e387d11002800000080681100440000004f010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f64656d6f63726163792f7372632f6c69622e7273036b110023000000d96a11002a00000080681100440000004f0100000100000076616c756520746f6f206c6f7770726f706f73657227732062616c616e636520746f6f206c6f7763616e206f6e6c79207365636f6e6420616e206578697374696e672070726f706f73616c7365636f6e64657227732062616c616e636520746f6f206c6f7744656d6f63726163792050726f78796e6f7420612070726f787944656d6f63726163792043616e63656c6c6174696f6e7370726f706f73616c207374696c6c20626c61636b6c697374656470726f706f73616c20616c7265616479206d61646544656d6f637261637920426c61636b6c697374696e76616c696420686173686e6578742065787465726e616c2070726f706f73616c206e6f742073696d706c65206d616a6f726974796e6f2070726f706f73616c206d616465756e6b6e6f776e2070726f706f73616c6e6f2065787465726e616c2070726f706f73616c6964656e74697479206d6179206e6f74207665746f20612070726f706f73616c207477696365616c726561647920612070726f787977726f6e672070726f78796e6f742064656c656761746564756e6b6e6f776e20696e64657863616e6e6f742063616e63656c207468652073616d652070726f706f73616c20747769636570726f706f73616c206e6f7420666f756e64766f746520676976656e20666f7220696e76616c6964207265666572656e64756d2e696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64653a205f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e00003300000004000000040000002500000042725461626c65446174617461626c65330000000400000004000000d200000064656661756c744636345265696e74657270726574493634556e726561636861626c654e6f70426c6f636b00330000000400000004000000d30000004c6f6f704966456c7365456e6442724272496642725461626c650000330000000400000004000000d400000052657475726e43616c6c43616c6c496e6469726563740000330000000400000004000000d500000044726f7053656c6563744765744c6f63616c5365744c6f63616c5465654c6f63616c476574476c6f62616c536574476c6f62616c4933324c6f61644936344c6f61644633324c6f61644636344c6f61644933324c6f616438534933324c6f616438554933324c6f61643136534933324c6f61643136554936344c6f616438534936344c6f616438554936344c6f61643136534936344c6f61643136554936344c6f61643332534936344c6f616433325549333253746f726549363453746f726546333253746f726546363453746f726549333253746f72653849333253746f7265313649363453746f72653849363453746f7265313649363453746f7265333243757272656e744d656d6f727947726f774d656d6f7279493332436f6e737400330000000400000004000000d6000000493634436f6e7374330000000400000004000000d7000000463332436f6e7374463634436f6e73743300000004000000040000000900000049333245717a49333245714933324e654933324c74534933324c74554933324774534933324774554933324c65534933324c655549333247655349333247655549363445717a49363445714936344e654936344c74534936344c74554936344774534936344774554936344c65534936344c655549363447655349363447655546333245714633324e654633324c7446333247744633324c65463332476546363445714636344e654636344c7446363447744636344c654636344765493332436c7a49333243747a493332506f70636e744933324164644933325375624933324d756c493332446976534933324469765549333252656d5349333252656d55493332416e644933324f72493332586f7249333253686c4933325368725349333253687255493332526f746c493332526f7472493634436c7a49363443747a493634506f70636e744936344164644936345375624936344d756c493634446976534936344469765549363452656d5349363452656d55493634416e644936344f72493634586f7249363453686c4936345368725349363453687255493634526f746c493634526f74724633324162734633324e65674633324365696c463332466c6f6f724633325472756e634633324e656172657374463332537172744633324164644633325375624633324d756c4633324469764633324d696e4633324d6178463332436f70797369676e4636344162734636344e65674636344365696c463634466c6f6f724636345472756e634636344e656172657374463634537172744636344164644636345375624636344d756c4636344469764636344d696e4636344d6178463634436f70797369676e493332577261704936344933325472756e63534633324933325472756e63554633324933325472756e63534636344933325472756e6355463634493634457874656e6453493332493634457874656e64554933324936345472756e63534633324936345472756e63554633324936345472756e63534636344936345472756e6355463634463332436f6e7665727453493332463332436f6e7665727455493332463332436f6e7665727453493634463332436f6e766572745549363446333244656d6f7465463634463634436f6e7665727453493332463634436f6e7665727455493332463634436f6e7665727453493634463634436f6e766572745549363446363450726f6d6f74654633324933325265696e746572707265744633324936345265696e746572707265744636344633325265696e74657270726574493332496e76616c696444617461547261696c696e6744617461556e6578706563746564456f6600002c7111000b000000492f4f204572726f723a204e6f526573756c7456616c7565330000000400000004000000d80000004636344933324936344633324e6f6e65536f6d65330000000400000004000000d9000000656e7600907111005d0000001201000016000000000000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31312e302f7372632f6761732f6d6f642e72736c6173745f696e6465782069732067726561746572207468616e20303b206c6173745f696e64657820697320737461636b2073697a65202d20313b2071656470721100660000001001000017000000447211002500000043616c6c20746f2066756e6374696f6e2074686174206f75742d6f662d626f756e64733a20000000000000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31312e302f7372632f737461636b5f6865696768742f6d6f642e7273546869732073686f756c64206265206120696e646578206f66206120646566696e65642066756e6374696f6e44756520746f2076616c69646174696f6e20636f64652073656374696f6e2073686f756c642065786973747346756e6374696f6e20626f6479206973206f7574206f6620626f756e647366756e6374696f6e20696d706f727420636f756e74206973206e6f74207a65726f3b20696d706f72742073656374696f6e206d757374206578697374733b2071656466756e635f696478206973206c657373207468616e2066756e6374696f6e20696d706f72747320636f756e743b0a090909096e74682066756e6374696f6e20696d706f7274206d7573742062652060536f6d65603b0a0909090971656400f495110012000000417411000f000000147411000a0000001e74110014000000327411000f0000005369676e61747572652020287370656369666965642062792066756e6320292069736e277420646566696e6564206973206e6f7420646566696e65647372632f6c6962616c6c6f632f7665632e7273007c7411001c0000005074110013000000cc04000009000000617373657274696f6e206661696c65643a20656e64203c3d206c656e2075110048000000b1010000230000002075110048000000b201000023000000d074110049000000870200001d00000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f736f72742e7273000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e7273d0741100490000009d0000003a000000d074110049000000a4000000300000004d761100120000005f7611000c0000006066756e635f696478602073686f756c6420636f6d652066726f6d20606e6565645f7468756e6b73603b0a09090909606e6565645f7468756e6b736020697320706f70756c617465642077697468207468652073616d65206974656d73207468617420696e20607265706c6163656d656e745f6d6170603b0a090909097165644174207468697320706f696e7420616e20696e646578206d7573742062652061737369676e656420746f2065616368207468756e6b66756e6374696f6e207769746820696478202069736e277420666f756e644672616d6569735f706f6c796d6f72706869630000330000000400000004000000da000000656e645f6172697479000000330000000400000004000000250000006272616e63685f617269747973746172745f6865696768744e6f2066756e6374696f6e2073656374696f6e4e6f20636f64652073656374696f6e4e6f20747970652073656374696f6e000000e47911000a00000046756e6374696f6e206973206e6f7420666f756e6420696e2066756e632073656374696f6e46756e6374696f6e20626f647920666f722074686520696e6465782069736e277420666f756e64d87911000c000000447911000b000000737461636b206d757374206265206e6f6e2d656d70747900397911000b000000f078110006000000737461636b206f766572666c6f774172697479206f6620616c6c206a756d702d74617267657473206d75737420626520657175616c54797065206e6f7420666f756e6400e978110007000000e07711006d000000c8000000110000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31312e302f7372632f737461636b5f6865696768742f6d61785f6865696768742e72736d61785f686569676874707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768742f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31312e302f7372632f737461636b5f6865696768742f6d61785f6865696768742e72737472756e633a20707573683a2000003479110005000000747279696e6720746f20706f70206d6f72652076616c756573207468616e20707573686564737461636b20756e646572666c6f77706f703a20756e726561636861626c65706f705f6672616d653a20636f6e74726f6c20737461636b20697320656d707479636f6e74726f6c20737461636b206f75742d6f662d626f756e647390791100480000009b0a00000a0000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e7273707573685f6672616d653a2066756e635f6964783a206578745f6368696c645f73746f726167655f726f6f74206e657665722072657475726e73207533323a3a6d61785f76616c75653b2071656452756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e6753797374656d2073746174652063757272656e746c792070726576656e74732074686973207472616e73616374696f6e5472616e73616374696f6e20646f6573206e6f742068617665207265717569726564207065726d697373696f6e73496e76616c6964206f726967696e496e76616c69645472616e73616374696f6e20637573746f6d206572726f725472616e73616374696f6e20776f756c642065786861757374732074686520626c6f636b206c696d6974735472616e73616374696f6e2068617320616e20616e6369656e7420626972746820626c6f636b5472616e73616374696f6e20686173206120626164207369676e61747572655472616e73616374696f6e206973206f757464617465645472616e73616374696f6e2077696c6c2062652076616c696420696e2074686520667574757265496e6162696c69747920746f2070617920736f6d6520666565732028652e672e206163636f756e742062616c616e636520746f6f206c6f77295472616e73616374696f6e2063616c6c206973206e6f74206578706563746564556e6b6e6f776e5472616e73616374696f6e20637573746f6d206572726f72436f756c64206e6f742066696e6420616e20756e7369676e65642076616c696461746f7220666f722074686520756e7369676e6564207472616e73616374696f6e436f756c64206e6f74206c6f6f6b757020696e666f726d6174696f6e20726571756972656420746f2076616c696461746520746865207472616e73616374696f6e00a07c110019000000c07c1100500000005800000022000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f67656e657269632f6572612e727348617368206e6f7420657175616c0000387d110028000000607d1100500000008700000009000000696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64652f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d73616e64626f782f7372632f2e2e2f776974686f75745f7374642e7273387d110028000000607d1100500000009000000009000000417574686f727368697020446964536574556e636c6573426162652045706f6368496e6465784261626520417574686f726974696573426162652047656e65736973536c6f74426162652043757272656e74536c6f74426162652052616e646f6d6e65737342616265204e65787452616e646f6d6e65737342616265205365676d656e74496e6465784261626520556e646572436f6e737472756374696f6e4261626520496e697469616c697a656462616265736c6f74436f756c64206e6f74206465636f64652072657175657374656420696e686572656e742074797065214241424520696e686572656e742064617461206e6f7420666f756e64746f6f206d616e7920696e737472756374696f6e73000000f47e110024000000187f1100170000005d02000009000000547269656420746f20736872696e6b20746f2061206c61726765722063617061636974797372632f6c6962616c6c6f632f7261775f7665632e7273436f6e7472616374204761735370656e74436f6e74726163742043757272656e745363686564756c65436f6e7472616374204163636f756e74436f756e7465726761736578745f7365745f73746f726167656578745f6765745f73746f726167656578745f63616c6c6578745f696e7374616e74696174656578745f72657475726e6578745f63616c6c65726578745f616464726573736578745f6761735f70726963656578745f6761735f6c6566746578745f62616c616e63656578745f76616c75655f7472616e736665727265646578745f72616e646f6d6578745f6e6f776578745f6d696e696d756d5f62616c616e63656578745f64697370617463685f63616c6c6578745f726573746f72655f746f6578745f736372617463685f73697a656578745f736372617463685f726561646578745f736372617463685f77726974656578745f6465706f7369745f6576656e746578745f7365745f72656e745f616c6c6f77616e63656578745f72656e745f616c6c6f77616e63656578745f7072696e746c6e6578745f626c6f636b5f6e756d6265724e6f6e2d656d7074792066756e6374696f6e20626f647920657870656374656400a68111000f000000b581110002000000b7811100030000001881110030000000488111005e0000007a00000005000000617373657274696f6e206661696c65643a20636f6e746578742e6672616d655f737461636b2e69735f656d70747928292f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e322e302f7372632f66756e632e7273417420696e737472756374696f6e202840293a2000008082110048000000b1010000230000008082110048000000b201000023000000598211001c0000006898110018000000e50300000d0000001082110049000000870200001d0000000000000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f736f72742e7273617373657274696f6e206661696c65643a206d6964203c3d206c656e00000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727310821100490000009d0000003a0000001082110049000000a40000003000000052657475726e207479706573206c656e6774682073686f756c642062652030206f722031178511001e000000358511001f00000066756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2071656466756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2066756e6374696f6e5f73656374696f6e5f6c656e203d3d20636f64655f73656374696f6e5f6c656e3b207165640000fd8411001a000000d88411000a000000e28411001b00000073746172742066756e6374696f6e20657870656374656420746f20686176652074797065205b5d202d3e205b5d000000c784110011000000a78411002000000087841100200000005f841100280000007365676d656e74206f66667365742073686f756c642072657475726e2049333270617373697665206d656d6f7279207365676d656e747320617265206e6f7420737570706f727465647061737369766520656c656d656e74207365676d656e747320617265206e6f7420737570706f72746564746f6f206d616e79206d656d6f727920726567696f6e7320696e20696e6465782073706163653a20746f6f206d616e79207461626c657320696e20696e6465782073706163653a20747279696e6720746f20696d706f7274206d757461626c6520676c6f62616c206475706c6963617465206578706f72742046756e6374696f6e20232072656164696e672f76616c69646174696f6e206572726f723a204d697373696e6720626f647920666f722066756e6374696f6e206c656e677468206f662066756e6374696f6e2073656374696f6e206973202c207768696c65206c656e206f6620636f64652073656374696f6e2069732043616e2774206465636f6465207761736d20636f64654d6f64756c65206973206e6f742076616c69646d6f64756c65206465636c6172657320696e7465726e616c206d656d6f72796d756c7469706c65207461626c6573206465636c617265647461626c652065786365656473206d6178696d756d2073697a6520616c6c6f776564757365206f6620666c6f6174696e6720706f696e74207479706520696e2066756e6374696f6e20747970657320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e206c6f63616c7320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e20676c6f62616c7320697320666f7262696464656e67617320696e737472756d656e746174696f6e206661696c6564737461636b2068656967687420696e737472756d656e746174696f6e206661696c656463616c6c6465706c6f796465706c6f792066756e6374696f6e2069736e2774206578706f72746564756e6b6e6f776e206578706f72743a20657870656374696e67206f6e6c79206465706c6f7920616e642063616c6c2066756e6374696f6e7366756e6374696f6e206861732061206e6f6e2d6578697374656e7420747970656578706f72742072656665727320746f206e6f6e2d6578697374656e742066756e6374696f6e657870656374656420612066756e6374696f6e656e74727920706f696e7420706f696e747320746f20616e20696d706f727465642066756e6374696f6e656e74727920706f696e74206861732077726f6e67207369676e617475726563616c6c2066756e6374696f6e2069736e2774206578706f727465646572726f722073657269616c697a696e6720696e737472756d656e746564206d6f64756c6500000000000001000000020000000400000008000000100000002000000044656d6f6372616379205075626c696350726f70436f756e7444656d6f6372616379205265666572656e64756d436f756e7444656d6f6372616379204e65787454616c6c7944656d6f6372616379204c6173745461626c656457617345787465726e616c436f756e63696c20446573697265645365617473436f756e63696c20566f7465436f756e74436f756e63696c204e657874566f746572536574436f756e63696c20566f746572436f756e74436f756e63696c2043616e646964617465436f756e7454696d657374616d7020496e697469616c697a6564000000000000708911000e0000000000000080891100010000000000000000000000888911000100000000000000000000009089110006000000000000003897110000000000000000000000000098891100010000000000000000000000a0891100070000000000000038971100000000000000000000000000a889110001000000000000004e6577417574686f7269746965730000238a110023000000ff891100240000005061757365640000d889110027000000526573756d656400b0891100280000002043757272656e7420617574686f726974792073657420686173206265656e20726573756d65642e2043757272656e7420617574686f726974792073657420686173206265656e207061757365642e204e657720617574686f726974792073657420686173206265656e206170706c6965642e5665633c28417574686f7269747949642c20417574686f72697479576569676874293e4772616e64706146696e616c69747920417574686f7269746965734772616e64706146696e616c6974792043757272656e7453657449644772616e64706146696e616c69747920536574496453657373696f6e4f6666636861696e206572726f723a206665746368696e67206e6574776f726b207374617465206661696c6564214f6666636861696e206572726f723a207369676e696e67206661696c6564214f6666636861696e206572726f723a206465636f64696e6720576f726b6572537461747573206661696c6564214f6666636861696e206572726f723a207375626d697474696e67207472616e73616374696f6e206661696c656421496d4f6e6c696e65205265636569766564486561727462656174734f6666656e636573205265706f72747342794b696e64496e6465780000000000a48b11000700000000000000ac8b1100020000000000000000000000bc8b110002000000000000004f6666656e6365006f8c110004000000738c11000e000000cc8b110055000000218c11004e00000020546865726520697320616e206f6666656e6365207265706f72746564206f662074686520676976656e20606b696e64602068617070656e656420617420746865206073657373696f6e5f696e6465786020616e6420286b696e642d7370656369666963292074696d6520736c6f742e2054686973206576656e74206973206e6f74206465706f736974656420666f72206475706c696361746520736c61736865732e4b696e644f706171756554696d65536c6f7453657373696f6e2053746f72656452616e676553657373696f6e2043757272656e74496e64657853657373696f6e205175657565644368616e67656453657373696f6e2044697361626c656456616c696461746f72730000000000048d11000a00000000000000108d1100010000000000000000000000188d110002000000000000004e657753657373696f6e00009f8d11000c000000288d1100550000007d8d110022000000204e65772073657373696f6e206861732068617070656e65642e204e6f746520746861742074686520617267756d656e74206973207468652073657373696f6e20696e6465782c206e6f742074686520626c6f636b206e756d626572206173207468652074797065206d6967687420737567676573742e53657373696f6e496e64657800c08d110048000000a10a00000e000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e72735374616b696e672056616c696461746f72436f756e745374616b696e67204d696e696d756d56616c696461746f72436f756e745374616b696e672043757272656e744572615374616b696e672043757272656e74457261537461727453657373696f6e496e6465785374616b696e672043757272656e74457261506f696e74734561726e65645374616b696e6720466f7263654572615374616b696e6720536c6173685265776172644672616374696f6e5374616b696e6720426f6e646564457261730000000000248f1100100000000000000038971100000000000000000000000000348f11000100000000000000000000003c8f11000f000000000000004c8f1100010000000000000000000000548f1100010000000000000045787472696e736963537563636573737e8f11002500000045787472696e7369634661696c656400718f11000d0000005c8f11001500000020416e2065787472696e736963206661696c65642e44697370617463684572726f7220416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e52657175697265526f6f744f726967696e526571756972655369676e65644f726967696e426c6f636b46756c6c4261645369676e617475726543616e206e6f74206c6f6f6b7570526571756972654e6f4f726967696e53797374656d2045787472696e736963436f756e7453797374656d20416c6c45787472696e7369637357656967687453797374656d20416c6c45787472696e736963734c656e53797374656d204e6578745765696768744d756c7469706c69657253797374656d2045787472696e7369634461746153797374656d204576656e74436f756e7474696d737461703054696d657374616d7020696e686572656e742064617461206973206e6f742070726f76696465642e496e76616c69642074696d657374616d7020696e686572656e74206461746120656e636f64696e672e54696d657374616d702044696455706461746554726561737572792050726f706f73616c436f756e74547265617375727920417070726f76616c736d616b655f746f705f6672616d655f706f6c796d6f72706869632069732063616c6c6564207769746820656d707479206672616d6520737461636b0000db0000000c00000004000000dc000000746869732066756e6374696f6e2063616e27742062652063616c6c6564207769746820656d707479206672616d6520737461636b4d6973706c6163656420656c736520696e737472756374696f6e0000d8921100470000001f931100050000009c92110037000000d3921100050000006a921100170000006192110009000000b29411001400000049921100180000006192110009000000b294110014000000189211001d00000035921100130000004892110001000000546f6f206c61726765206d656d6f727920616c69676e6d656e7420325e20286578706563746564206174206d6f73742029547279696e6720746f2075706461746520676c6f62616c20206f66207479706520547279696e6720746f20757064617465206c6f63616c20416e795370656369666963330000000400000004000000d80000004c6162656c7320696e2062725f7461626c6520706f696e747320746f20626c6f636b206f6620646966666572656e742074797065733a2020616e6420496620626c6f636b20776974686f757420656c736520726571756972656420746f2068617665204e6f526573756c7420626c6f636b20747970652e204275742069742068617320207479706534931100180000004c9311000b000000556e657870656374656420737461636b20686569676874202c20657870656374656420547279696e6720746f2061636365737320706172656e74206672616d6520737461636b2076616c7565732e00009493110017000000ab9311001600000045787065637465642076616c7565206f66207479706520206f6e20746f70206f6620737461636b2e20476f7420000000cc93110007000000537461636b3a20000000010056941100240000002c94110006000000329411000e000000409411001600000008941100240000002c941100060000006d6178696d756d206d656d6f72792073697a65206d757374206265206174206d6f7374202070616765736d6178696d756d206c696d697420206973206c657373207468616e206d696e696d756d20696e697469616c206d656d6f72792073697a65206d757374206265206174206d6f73742000008c94110026000000b294110014000000547279696e6720746f20696e697469616c697a65207661726961626c65206f6620747970652020776974682076616c7565206f66207479706520496e69742065787072657373696f6e2073686f756c6420616c776179732062652077697468206c656e67746820324e6f6e20636f6e7374616e74206f70636f646520696e20696e697420657870725d951100070000006f951100220000005d95110007000000649511000b00000045787072657373696f6e20646f65736e277420656e647320776974682060656e6460206f70636f6465476c6f62616c20206973206d757461626c6520646f65736e277420657869737473206f72206e6f742079657420646566696e6564000000a495110010000000b49511000f0000004d656d6f727920617420696e6465782020646f65736e27742065786973747300d49511000f000000b49511000f0000005461626c6520617420696e6465782000f495110012000000b49511000f00000046756e6374696f6e20617420696e646578200000189611000e000000b49511000f0000005479706520617420696e6465782000008696110010000000b49511000f0000005896110010000000789611000e00000058961100100000006896110010000000457870656374656420676c6f62616c2020746f20626520696d6d757461626c6520746f206265206d757461626c65476c6f62616c20617420696e646578206e6f6e2d656d70747920737461636b2065787065637465640000c096110020000000e096110012000000747279696e6720746f206765742076616c756520617420706f736974696f6e20206f6e20737461636b206f662073697a6520636865636b656420636f75706c65206f66206c696e65732061626f7665001897110015000000657863656564656420737461636b206c696d69742000000038971100000000004572726f72000000330000000400000004000000dd0000004c6f63616c732072616e6765206e6f7420696e2033322d6269742072616e67658897110022000000aa97110015000000bf97110007000000547279696e6720746f20616363657373206c6f63616c207769746820696e64657820207768656e20746865726520617265206f6e6c7920206c6f63616c730000e09711002d0000000d9811000c0000001998110003000000617373657274696f6e206661696c65643a2060286c656674203d3d20726967687429600a20206c6566743a2060602c0a2072696768743a2060603a20249811003400000064657374696e6174696f6e20616e6420736f7572636520736c69636573206861766520646966666572656e74206c656e67746873689811001800000058080000090000007372632f6c6962636f72652f736c6963652f6d6f642e7273004180b1c6000b08000000000000000000bfbb03046e616d6501b6bb03a305000e6578745f626c616b65325f323536011f6578745f6765745f616c6c6f63617465645f6368696c645f73746f7261676502176578745f636c6561725f6368696c645f73746f7261676503146578745f6765745f73746f726167655f696e746f04166578745f6b696c6c5f6368696c645f73746f7261676505156578745f7365745f6368696c645f73746f7261676506196578745f6765745f616c6c6f63617465645f73746f72616765070f6578745f7365745f73746f72616765080c6578745f74776f785f31323809116578745f636c6561725f73746f726167650a126578745f737232353531395f7665726966790b0e6578745f7072696e745f757466380c0d6578745f7072696e745f6e756d0d166578745f6368696c645f73746f726167655f726f6f740e106578745f636c6561725f7072656669780f166578745f73616e64626f785f6d656d6f72795f6e6577101b6578745f73616e64626f785f6d656d6f72795f74656172646f776e11176578745f73616e64626f785f696e7374616e746961746512126578745f73616e64626f785f696e766f6b65131d6578745f73616e64626f785f696e7374616e63655f74656172646f776e14106578745f73746f726167655f726f6f7415186578745f73746f726167655f6368616e6765735f726f6f7416126578745f656432353531395f76657269667917166578745f73616e64626f785f6d656d6f72795f67657418166578745f73616e64626f785f6d656d6f72795f736574190d6578745f7072696e745f6865781a106578745f69735f76616c696461746f721b156578745f6c6f63616c5f73746f726167655f6765741c216578745f6c6f63616c5f73746f726167655f636f6d706172655f616e645f7365741d116578745f6e6574776f726b5f73746174651e106578745f737232353531395f7369676e1f166578745f7375626d69745f7472616e73616374696f6e20156578745f6c6f63616c5f73746f726167655f73657421146578745f656432353531395f67656e657261746522146578745f737232353531395f67656e657261746523236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74240a6578745f6d616c6c6f6325086578745f6672656526176578745f737232353531395f7075626c69635f6b657973270b6578745f74776f785f3634280c5f5f727573745f616c6c6f63290a5f5f72675f616c6c6f632a0e5f5f727573745f6465616c6c6f632b0c5f5f72675f6465616c6c6f632c0e5f5f727573745f7265616c6c6f632d0c5f5f72675f7265616c6c6f632e135f5f727573745f616c6c6f635f7a65726f65642f115f5f72675f616c6c6f635f7a65726f65643009686173685f746573743134616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a68636164633139656466653965313035353229636f72653a3a70616e69636b696e673a3a70616e69633a3a68613237623135356231613762656131643325616c6c6f633a3a666d743a3a666f726d61743a3a68373139333337636638383237333534323436636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68613834643033333136663462356666613523636f72653a3a666d743a3a77726974653a3a68373639626232616366663461376638613648616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303032666333346665303731316264303708727573745f6f6f6d382e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6864623133323335353631653632346136393a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68633133653134623932623865333434343a3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68373137336662316338303332343364353b3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68613062616630316338386562366162373c34636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68656632663938626564366266373533643d4e636f72653a3a666d743a3a6e756d3a3a696d703a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207533323e3a3a666d743a3a68303438303937613766373038326163303e2d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a68346637396263373939663330393733323f2f636f72653a3a666d743a3a6e756d3a3a696d703a3a666d745f7536343a3a68383932326134393263623337346536624011727573745f626567696e5f756e77696e6441313c5420617320636f72653a3a616e793a3a416e793e3a3a747970655f69643a3a68303837626662333038396434323234304235636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a68313538353734313262386634366265634343636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a77726974655f7072656669783a3a68363936303565363538343765653566304436636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a6835353833396665343434333633396662452c636f72653a3a666d743a3a466f726d61747465723a3a7061643a3a6862663133663132313734343633363530462e636f72653a3a7374723a3a736c6963655f6572726f725f6661696c3a3a686237366535353838326633366137346647323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6830303136373764333333316431623262484a3c636f72653a3a6f70733a3a72616e67653a3a52616e67653c4964783e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686339373033363631643132393261316649323c6368617220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68303731343665363835653563656332624a3d636f72653a3a756e69636f64653a3a626f6f6c5f747269653a3a426f6f6c547269653a3a6c6f6f6b75703a3a68616234336463613764383766373731634b49636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a68373032373631646266343866333635364c34636f72653a3a666d743a3a417267756d656e7456313a3a73686f775f7573697a653a3a68303764326632623133316361643036374d453c636f72653a3a63656c6c3a3a426f72726f774572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68326433626561393162376638333331354e483c636f72653a3a63656c6c3a3a426f72726f774d75744572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68383634373335313833373766363262364f323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6836323735643962386134343631633938502e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a683163333163613936623063653034653051303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6864396534343966646163316334353532522e636f72653a3a736c6963653a3a6d656d6368723a3a6d656d6368723a3a6839323166353536393537323230396564538001636f72653a3a7374723a3a7472616974733a3a3c696d706c20636f72653a3a736c6963653a3a536c696365496e6465783c7374723e20666f7220636f72653a3a6f70733a3a72616e67653a3a52616e67653c7573697a653e3e3a3a696e6465783a3a7b7b636c6f737572657d7d3a3a68376561353565643561313134353233665427636f72653a3a7374723a3a66726f6d5f757466383a3a68393936353463313839323463653036345530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a683566363963313432356330613037353356533c636f72653a3a666d743a3a6275696c646572733a3a5061644164617074657220617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6865393736373038366566313830663239572f636f72653a3a666d743a3a57726974653a3a77726974655f636861723a3a6835376138336636353030656231663365582e636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a6835616339306139346131333230656233593a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68306138363933663139633766366666665a3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68636638393338356535396637623637615b3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68383637616663663734396563326230325c3a636f72653a3a666d743a3a6275696c646572733a3a44656275675374727563743a3a6669656c643a3a68646430303731316136373965613430345d39636f72653a3a666d743a3a6275696c646572733a3a44656275675475706c653a3a6669656c643a3a68393065333464346262613566643437365e443c636f72653a3a666d743a3a417267756d656e747320617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68626634386164393337636464313931615f313c73747220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686637313733623038663233376563326360303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686530393630373933333765373636363961303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683931653862363165666339613332346262423c636f72653a3a7374723a3a557466384572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686166363337373838663261376137313063303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6833396433666631363039386537383237643e3c636f72653a3a666d743a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686464366234323235356566653732333065383c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a686365346336373635363834626464353866343c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a686463373536653930643966306231373167363c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a666c7573683a3a683533303838393235643430663439313868693c636f72653a3a697465723a3a61646170746572733a3a46696c7465724d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6838653863316664626539333838346163694b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68663530663164396638316533336133346a30636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68323434346236303933336133646533306b7d7061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72202851302c205230293e3a3a6465636f64653a3a68333464663538646264396436366233626c6b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68323661353531326466306130366630326d543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68376638333330366130393338636466636e2d616c6c6f633a3a7665633a3a5665633c543e3a3a72657461696e3a3a68356638643836666366306661623534356f443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a683032363437663936366662386566376170443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a683339393163366632303237333937323471443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a686566656166643264633364616137393472463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683162353632313133646564343136383473543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683039636136373637663535386430666574543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683134393565336533346436663466623675543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683136303731343633646432653861656276543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683262653166343131363934633333326577543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683266353961316562306564306263356578543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683266666136396263346264313332613379543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68343634633337336136666331646362347a9f013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68383962656633636262333533326338617b543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68353335363332653631633034346136637c543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68383862356330343234613539346162647d543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68393130613036323863303037356534637e543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68613962383762393439623233386535347f753c73725f7072696d6974697665733a3a67656e657269633a3a6865616465723a3a4865616465723c4e756d6265722c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68316665643862623861336335356666388001543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a686337333532366633613336356262663281017f6e6f64655f72756e74696d653a3a5f494d504c5f4445434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a6465636f64653a3a68333130306265306638643432366337618201543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68646332643431646231373737373966618301513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68333930383730653562343365626334618401513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68346235353034353038313230323761658501693c636f72653a3a697465723a3a61646170746572733a3a46696c7465724d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6864386638303832353262313639643938860168636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a68616338303437376531623137353030658701513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68376163313434383630363561393861358801513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6838646539353166376338633363373834890130636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68303032396532383461626336653161348a01793c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a68346366353833643730356531323330398b017b3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a68373233336337366666386563623337638c017273726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a68633632613631323832356230656538308d0180013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a68363336343837393532646263326661308e017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a68626433333036616562666336626362358f01463c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68653566313862323833376430363465349001793c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6834396339306230636239366136303838910185013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a667265655f62616c616e63653a3a68383966356130363566393565373865319201743c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a68643530643334363435306561343137639301723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a683833306434623064366665663163303194018d013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6d616b655f667265655f62616c616e63655f62653a3a68386234623564326136633936643835629501613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683131363062303861386164636233646296017573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6866633362376362623662393231306232970191013c73726d6c5f636f6e7472616374733a3a54726965496446726f6d506172656e74436f756e7465723c543e2061732073726d6c5f636f6e7472616374733a3a54726965496447656e657261746f723c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a747269655f69643a3a686161356339313864623663376232333398013773726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a626c6f636b5f6e756d6265723a3a68653533383938356333383936373334639901723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a68363064383435646236353836623862669a017573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a68383232653933386530363765323330359b01613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68373635323739333664343963626361349c017773726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a76616c75653a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f7261676556616c75653c543e20666f7220473e3a3a6d75746174653a3a68363839653731333562643437646538339d017773726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a76616c75653a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f7261676556616c75653c543e20666f7220473e3a3a6d75746174653a3a68323138376639326134336161343632319e016b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68616238326334383138373537326534309f016c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830386561633136356661396637393538a001713c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6864653530373162386130653734333633a101713c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6835653932376533663634393764666562a201303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836633166636332326337613565393130a301723c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6865323831616332613336303138303565a401303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6861393633376463316164363838343137a501783c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6837313537343363326237386233626138a6017b3c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832626663373164323632393930636138a7017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6839346337326433373239326630393437a80184013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a6838626464373063336465333638653932a901cd0173726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a5f494d504c5f454e434f44455f464f525f4c696e6b6167653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4c696e6b6167653c4b65793e3e3a3a656e636f64655f746f3a3a6835333330396563306462363039336239aa01cd0173726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a5f494d504c5f454e434f44455f464f525f4c696e6b6167653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4c696e6b6167653c4b65793e3e3a3a656e636f64655f746f3a3a6865393330353763396263376337323461ab0184013c73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c473e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6838643238373730663035386262636565ac016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a53746f726167654c696e6b65644d61703a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a6838383431306663323634343831633764ad0184013c73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c473e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6865386566633638356136363861353930ae016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a53746f726167654c696e6b65644d61703a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a6835313634396637613236326262653938af0184013c73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c473e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6866396432363165633964396131623766b0016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a53746f726167654c696e6b65644d61703a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a6835356235363734623230613437653865b1017d7061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72202851302c205230293e3a3a6465636f64653a3a6865373864623462383164613762393330b2013d73726d6c5f6f6666656e6365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6836363030663338636433666133303631b301743c73726d6c5f6f6666656e6365733a3a5f5f476574427974655374727563745265706f72747342794b696e64496e6465783c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831636238373936303566366365663164b4016c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832333939613538336430656438336234b5014d73726d6c5f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a696e7374616e74696174653a3a6836623966633736373531646261363534b60181013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6836616130363564356539663732313132b7014b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6861613261623366303331336232356636b8013173726d6c5f636f6e7472616374733a3a657865633a3a7472616e736665723a3a6837373362356236396662646161313137b9013973726d6c5f636f6e7472616374733a3a7761736d3a3a636f64655f63616368653a3a6c6f61643a3a6866323337613535386232383836373039ba01593c73726d6c5f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732073726d6c5f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a6831333937356561393739303766376236bb01783c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6836616339326635393738306465653137bc018c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a656e737572655f63616e5f77697468647261773a3a6839626535636564373733626261363035bd0148616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6832343561663334383230376130353433be0130636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6835323765316362333634383130643564bf017f3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6866353465663532326365346138316461c0017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6831313131303862313035626263336366c1014673726d6c5f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a63616c6c3a3a6839353866323730643039323832636563c2014273726d6c5f636f6e7472616374733a3a72656e743a3a7472795f65766963745f6f725f616e645f7061795f72656e743a3a6863336336633731646632616562646432c3013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6864633565333763353634646262616336c4013f7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64655f746f3a3a6831613165646131353962323138616264c501c7013c73726d6c5f6f6666656e6365733a3a4d6f64756c653c543e2061732073725f7374616b696e675f7072696d6974697665733a3a6f6666656e63653a3a5265706f72744f6666656e63653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c542061732073726d6c5f6f6666656e6365733a3a54726169743e3a3a4964656e74696669636174696f6e5475706c652c4f3e3e3a3a7265706f72745f6f6666656e63653a3a6832383939313265386363346166666539c6014b3c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832633136623336633063663237386639c7016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6838636333303466313030626264666365c801437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6861623165653031323634626232353937c90141616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a7365617263683a3a7365617263685f747265653a3a6834353339376134376233366633383934ca01613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6863623836653530643234616238333461cb01437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6831633062376138643436393335636534cc014073726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6576656e745f696e64657865643a3a6834313461616236326136396366376638cd0134636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f6e7461696e733a3a6863616665643431346630633236373166ce013673726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6c6f673a3a6865613866373434663735656363653135cf017e3c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736c6173683a3a6866643562376165396361393035363832d00189013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6465706f7369745f6372656174696e673a3a6836373839333262303737623239363337d1015373725f7072696d6974697665733a3a50657262696c6c3a3a66726f6d5f726174696f6e616c5f617070726f78696d6174696f6e3a3a7b7b636c6f737572657d7d3a3a6838323439353335646130363233616166d2015373725f7072696d6974697665733a3a50657262696c6c3a3a66726f6d5f726174696f6e616c5f617070726f78696d6174696f6e3a3a7b7b636c6f737572657d7d3a3a6833333938303938366437323438633665d3014b73725f7072696d6974697665733a3a7472616974733a3a4163636f756e744964436f6e76657273696f6e3a3a696e746f5f6163636f756e743a3a6839633438346130663064333336626130d4019a0173726d6c5f7374616b696e673a3a5f494d504c5f4445434f44455f464f525f4578706f737572653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f7374616b696e673a3a4578706f737572653c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6837393935333333636162333938616263d501483c73726d6c5f6f6666656e6365733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837303239393466376333643337643031d6015c3c73726d6c5f6f6666656e6365733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6832386366306335363565653635396665d701703c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6830373463363933373136623438643830d801303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830313735343962623362373765363161d901406e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f73797374656d3a3a6838353435663263626138613161386365da01416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f696e64696365733a3a6839656632383931386338356161373231db01426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f62616c616e6365733a3a6835613762623764323431326363363930dc01416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f7374616b696e673a3a6861386530623037316263646566366661dd01416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f73657373696f6e3a3a6837336536323763303639326138663139de01436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f64656d6f63726163793a3a6863633261336536646130336365323230df014e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f6c6c6563746976655f496e7374616e6365313a3a6836656163653863306136333236353131e001436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f656c656374696f6e733a3a6832623263323461633638353163356334e1014e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6d656d626572736869705f496e7374616e6365313a3a6863616165316234326264323238666536e201416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6772616e6470613a3a6834613630316463343234393033386164e301426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f74726561737572793a3a6863333761653137623166353232663861e401436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f6e7472616374733a3a6865343131326666386464386131633438e5013e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f7375646f3a3a6861316434653964343230393738353039e601436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f696d5f6f6e6c696e653a3a6836356133633932336635663033326535e701426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6f6666656e6365733a3a6862633937306433383331323331343235e8018d016e6f64655f72756e74696d653a3a5f494d504c5f4445434f44455f464f525f53657373696f6e4b6579733a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a53657373696f6e4b6579733e3a3a6465636f64653a3a6834616339333937656166633633346665e9018a0173726d6c5f636f6c6c6563746976653a3a5f494d504c5f4445434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a6465636f64653a3a6831333130353934363139353131333335ea018b0173726d6c5f636f6e7472616374733a3a5f494d504c5f4445434f44455f464f525f5363686564756c653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6e7472616374733a3a5363686564756c653e3a3a6465636f64653a3a6834396636343234393334303165366132eb0182016e6f64655f72756e74696d653a3a5f494d504c5f454e434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a656e636f64655f746f3a3a6832373361383431636330393135346263ec01723c73725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573744974656d3c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6830376364313565343730393839633137ed018d0173726d6c5f636f6c6c6563746976653a3a5f494d504c5f454e434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a656e636f64655f746f3a3a6835626138363964316265616430313464ee018e0173726d6c5f636f6e7472616374733a3a5f494d504c5f454e434f44455f464f525f5363686564756c653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6e7472616374733a3a5363686564756c653e3a3a656e636f64655f746f3a3a6866346132356361353138616335333261ef01437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6834306664363130326135353165306162f0012b616c6c6f633a3a736c6963653a3a6d657267655f736f72743a3a6833316161333833653836616137363032f10184016e6f64655f72756e74696d653a3a5f494d504c5f454e434f44455f464f525f4576656e743a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a656e636f64655f746f3a3a6836643335653535356638613331303163f201a20173726d6c5f636f6c6c6563746976653a3a5f494d504c5f454e434f44455f464f525f5261774576656e743a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6c6c6563746976653a3a5261774576656e743c486173682c4163636f756e7449642c493e3e3a3a656e636f64655f746f3a3a6834343930633836383033333235343464f301653c6e6f64655f72756e74696d653a3a43616c6c2061732073725f7072696d6974697665733a3a776569676874733a3a4765744469737061746368496e666f3e3a3a6765745f64697370617463685f696e666f3a3a6830343764353632386132636561316131f401583c6e6f64655f72756e74696d653a3a43616c6c2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6838336539363263643433313230313431f501583c73726d6c5f626162653a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6830613865393037323432653436316137f601437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6862373562336361323964663636363363f7017273726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a6836313935643964653537363138303536f8013573726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a617574686f723a3a6837616231333433646161623761326263f9013973726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a7265776172645f62795f6964733a3a6834663135326364303734323563613964fa01673c73726d6c5f617574686f726974795f646973636f766572793a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6862373861323639343666653063343330fb013973726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a63757272656e745f696e6465783a3a6862643032343430373930666636353431fc016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6863323531613265623837643836373037fd013773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6865363039313833643065313763373335fe013473726d6c5f696e64696365733a3a4d6f64756c653c543e3a3a656e756d5f7365743a3a6834626439326135376534613539343639ff014a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a683331333837306130366564383137366380025d3c73726d6c5f636f6e7472616374733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683337653735393432376661653439323181029c0173726d6c5f74726561737572793a3a5f494d504c5f4445434f44455f464f525f50726f706f73616c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f74726561737572793a3a50726f706f73616c3c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6862653536383862356333373963656531820291013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736c6173685f72657365727665643a3a683935323531313561306238396239363483028a013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a726573657276653a3a6835373538346635383335346464633662840295013c73726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a686361376465303135316236633762653285024a73726d6c5f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733a3a7365745f6d656d626572735f736f727465643a3a683538373630336262373262373332656386025d3c73726d6c5f656c656374696f6e733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68343237636433356333343061653264318702603c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68613438353966393862646662343236348802603c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683732373531613862373434313363383089025d3c73726d6c5f64656d6f63726163793a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68653734393864343238613132313430328a02a40173726d6c5f7374616b696e673a3a5f494d504c5f4445434f44455f464f525f5374616b696e674c65646765723a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f7374616b696e673a3a5374616b696e674c65646765723c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a68323763626335363133383261626464638b026f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68316232373866353234623633623030388c026f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68643338646665333337366133616133618d025b3c73726d6c5f7374616b696e673a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68326662643138643966363865313162638e0281013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7472616e736665723a3a68393839356531356133343461393931338f023f73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7365745f667265655f62616c616e63653a3a686338383364396561623864346264333390024373726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7365745f72657365727665645f62616c616e63653a3a686434313335333537336630653135303591025b3c73726d6c5f696e64696365733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683836643831653663633431313261616292023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a683235616265373531383235343639656293027f3c73726d6c5f696e64696365733a3a4d6f64756c653c543e2061732073726d6c5f73797374656d3a3a4f6e4e65774163636f756e743c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f6e65775f6163636f756e743a3a683233616438626236666435383861326194023873726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a686461366639373031343963386135303795023673726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6b696c6c5f73746173683a3a683130383536663739323263306461306596023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686634613737393939303031643038636297027573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6837383737326333616663356337353965980281013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a77697468647261773a3a683562396534326566383633636534646199023e73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a76657374696e675f62616c616e63653a3a68626238373339643133333535626236339a023473726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6c6f636b733a3a68333638393134633832333539393965379b02483c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68353835323237626435376637343932309c027573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a68633038636165316435373833636636349d0286013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a746f74616c5f62616c616e63653a3a68643763643637643234383134613861659e02653c73726d6c5f62616c616e6365733a3a54616b65466565733c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a5369676e6564457874656e73696f6e3e3a3a76616c69646174653a3a68376236613935643336393266623835389f023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830653936393331313632366135383439a0023d73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6862323666653064306530393634336432a1023d73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a746f74616c5f69737375616e63653a3a6862373662663765313663613336633032a2023f73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6835653663653264363439656133316565a3026f3c73726d6c5f62616c616e6365733a3a5f5f476574427974655374727563744672656542616c616e63653c542c493e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861383137633863343936663239343566a4024873726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6834313966353063313539363139383666a5028e013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6465706f7369745f696e746f5f6578697374696e673a3a6830386464613432346263363434343536a6023c73726d6c5f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6862663230666535343038633831396532a7023e73726d6c5f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6861643765666566376438653664313064a8028c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a657874656e645f6c6f636b3a3a6862363338363539643233333631623664a90289013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7365745f6c6f636b3a3a6836396238393930643162313061313162aa028c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a756e726573657276653a3a6832313164383839393835333764303834ab02437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830666563303961653439666334326261ac023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6864663432393736333738383031613830ad023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6862353065623633303432396164376434ae024a3c73726d6c5f62616c616e6365733a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6865353039326631653139383330613864af02493c73726d6c5f696d5f6f6e6c696e653a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831666134356231303637653363663366b002613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6835313936613536623066393933653735b102723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6832366232363063316563313961636339b202437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6833353837313637353866383936316335b3027573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6839613865636263363866646163613530b402303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832336661343463613531383764656463b5024d636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a68373032373631646266343866333635362e323334b6024373726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6837323862643265653064663338323230b7024e73726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6863643962646630323731313235383765b8029f013c73726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5265706f72744c6174656e637944656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865613333313236376432326439396637b9029c013c73726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a57696e646f7753697a6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865373839396264363034313435393935ba02d5017375627374726174655f636f6e73656e7375735f626162655f7072696d6974697665733a3a6469676573743a3a5f494d504c5f4445434f44455f464f525f526177426162655072654469676573743a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72207375627374726174655f636f6e73656e7375735f626162655f7072696d6974697665733a3a6469676573743a3a526177426162655072654469676573743e3a3a6465636f64653a3a6831633662323537393730353733386134bb024b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6831626132303333613836643063323539bc02613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6830346361333431346265366331306336bd028c013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a4f6e496e697469616c697a653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6830613231343334363663376138326632be023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831396564393438326431653338623932bf024073726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a63616e6469646174655f7265675f696e666f3a3a6831373937623930333666633766346466c0023873726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a616c6c5f766f746572733a3a6861316534646265623437323035653037c1023a73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a617070726f76616c735f6f663a3a6832306234303633356262643638613261c202960173726d6c5f656c656374696f6e733a3a5f494d504c5f4445434f44455f464f525f566f746572496e666f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f656c656374696f6e733a3a566f746572496e666f3c42616c616e63653e3e3a3a6465636f64653a3a6830316262336439643662306561626533c3024a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6836306436643261353030666463656265c4022d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6835643130393431636331373563363639c50295013c73726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a6864653264326333356566393630353236c6023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6835393066393834646333383132663735c7023c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6831343362643439666263383664393238c8023e73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6866653130333861666166393439343565c902713c73726d6c5f656c656374696f6e733a3a5f5f4765744279746553747275637443616e646964617465436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834643433333035643361333633333334ca02713c73726d6c5f656c656374696f6e733a3a5f5f476574427974655374727563745265676973746572496e666f4f663c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837363362656236383261363832343365cb024773726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6862376137636130316332323031333132cc0299013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a564f5445525f5345545f53495a4544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866366135363965663662643639346637cd0295013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e67426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838613264656532666338373233633965ce0297013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e67506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863653338613432616462313537383438cf029e013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a496e6163746976654772616365506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866363330386163656461376137343234d00295013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4361727279436f756e7444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833653330626135303162636236366136d10294013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e6746656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864333434393535393035313936363639d20298013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616e646964616379426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839393639666163356137666662626663d302493c73726d6c5f656c656374696f6e733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6838393533343563316230373032343266d4023e73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a646f5f7365745f617070726f76616c733a3a6830356233326237643335643433376531d5023a73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a72656d6f76655f766f7465723a3a6864343234646366303966313037613632d602497061726974795f7363616c655f636f6465633a3a656e636f64655f617070656e643a3a657874726163745f6c656e6774685f646174613a3a6866643865656134353734643132643761d7023a73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6830316131646133303365313665336564d8023c73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6864313433326339303364323232303332d902663c73726d6c5f6772616e6470613a3a5f5f4765744279746553747275637453746174653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861633430666337353837316663386439da023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6866613262363366396564623731643938db023a73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6839336165366236373664623230343535dc023c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6835383233613635353036306435633137dd024573726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864363061643832333262393932383237de0299013c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a44454455505f4b45595f50524546495844656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861626566343565663162336261356236df02763c73726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a54776f783634436f6e6361742061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a53746f726167654861736865723e3a3a686173683a3a6830336164393834343263623061383436e002437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6866396638336564633862303663363035e102437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6839623462623063373566323965326431e2023b73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6864623530656536616665326164663166e3023d73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6866303933303965666331326462656261e4024673726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6865616232643963386538373037313930e5028e013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4275726e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862376133356263656433663732633433e602870173725f7072696d6974697665733a3a5f494d504c5f454e434f44455f464f525f50657262696c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073725f7072696d6974697665733a3a50657262696c6c3e3a3a656e636f64653a3a6830306536383731383739316332643562e70295013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5370656e64506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864653636393366366136366337323939e80296013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a50726f706f73616c426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830656261613063366636366431356332e9023673726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a70726f706f73616c733a3a6863663030323230323662663936306562ea028a013c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a4f6e496e697469616c697a653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6835333934366339396564396363636432eb023673726d6c5f626162653a3a4d6f64756c653c543e3a3a646f5f696e697469616c697a653a3a6832613837383633353631643739633635ec023373726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a7374616b6572733a3a6861393931653433343637656664343439ed0286013c73726d6c5f7374616b696e673a3a4d6f64756c653c543e2061732073726d6c5f73657373696f6e3a3a4f6e53657373696f6e456e64696e673c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f73657373696f6e5f656e64696e673a3a6831616537633337663639326237646539ee023b73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a7363686564756c655f6368616e67653a3a6863663437383934313665623338366464ef023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864313234373039313533353736666336f002437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6837383364333039663738623432326336f1024b3c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832333063333531613138336135356361f20230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6835363637303838653535663233666638f302633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6832303361323762636366356561396333f402683c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a73697a655f68696e743a3a6832346639626639393362356461613335f5023e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6833383534363563373835376562323363f602633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6835333163646162346661313032336566f7023e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6830656136623430363665613539646464f8024273726d6c5f636f6e7472616374733a3a7761736d3a3a707265706172653a3a707265706172655f636f6e74726163743a3a6836323964316235366163326233306638f9024a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6833663662373961343438356135623362fa02437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6839303831646161613832616561363963fb026a636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4f6e63653c413e20666f7220266d757420463e3a3a63616c6c5f6f6e63653a3a6833313938663239346337633037623537fc02663c73726d6c5f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732073726d6c5f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a7b7b636c6f737572657d7d3a3a6832326566363933396635303938656631fd027d3c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6761733a3a6832623037396439643933646632663439fe025273725f73616e64626f783a3a696d703a3a456e7669726f6e6d656e74446566696e6974696f6e4275696c6465723c543e3a3a6164645f686f73745f66756e633a3a6837613337346132656234333561666165ff0289013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f73746f726167653a3a6833316361656264633564353264303138800389013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f73746f726167653a3a6831306431663335653165616632636130810382013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c3a3a6862623530306664353561356239323037820389013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f696e7374616e74696174653a3a6832616439353630656131333639626339830384013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72657475726e3a3a6861636564646338343232366335616233840384013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c65723a3a6834636231663539323330323861356630850385013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f616464726573733a3a6833613661303262393533303630646139860387013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f70726963653a3a6864376232663834643362623864393663870386013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f6c6566743a3a6861373962343335303839303935373465880385013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f62616c616e63653a3a686339306131366437336261366433336589038f013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f76616c75655f7472616e736665727265643a3a68336165393265656438623133313066658a0384013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72616e646f6d3a3a68643635336131613637663332626464368b0381013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6e6f773a3a68616461313738623139303562636263618c038d013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6d696e696d756d5f62616c616e63653a3a68613038303466373261376563343666378d038b013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f64697370617463685f63616c6c3a3a68383035303832366164303961386335628e0388013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f726573746f72655f746f3a3a68633132333439626561366435393336308f038a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f73697a653a3a683538306530613263333566306331646490038a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f726561643a3a683663373534623336306337633265613991038b013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f77726974653a3a683632343433353932626339633736616592038b013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6465706f7369745f6576656e743a3a6838306238323039323537373365616633930390013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f72656e745f616c6c6f77616e63653a3a683466323433313333626532356363666194038c013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72656e745f616c6c6f77616e63653a3a6839363463323461623138626436633334950385013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7072696e746c6e3a3a686637366431396430353439356163373596038a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f626c6f636b5f6e756d6265723a3a686433623536316436376666623763643497033273725f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a68386536656133346363343135383566389803ad017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f4445434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a6465636f64653a3a68363636646563623130363065303136389903b0017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f454e434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a656e636f64655f746f3a3a68366638396436616535373364656261659a033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68656566626338616663316366666162389b033d73726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68613865633662663666313730656535339c033f73726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68323836393939663633396233306133669d03703c73726d6c5f617574686f72736869703a3a5f5f47657442797465537472756374446964536574556e636c65733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68356131666536346139393034343766639e038a033c285475706c65456c656d656e74302c205475706c65456c656d656e74312c205475706c65456c656d656e74322c205475706c65456c656d656e74332c205475706c65456c656d656e74342c205475706c65456c656d656e74352c205475706c65456c656d656e74362c205475706c65456c656d656e74372c205475706c65456c656d656e74382c205475706c65456c656d656e74392c205475706c65456c656d656e7431302c205475706c65456c656d656e7431312c205475706c65456c656d656e7431322c205475706c65456c656d656e7431332c205475706c65456c656d656e7431342c205475706c65456c656d656e7431352c205475706c65456c656d656e7431362c205475706c65456c656d656e7431372c205475706c65456c656d656e7431382c205475706c65456c656d656e743139292061732073725f7072696d6974697665733a3a7472616974733a3a4f6e46696e616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c697a653a3a68326334616136396565373634306235359f037573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6835326236326535373661623038396433a0033173726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a6e6f773a3a6834363532613662336165366264626163a103443c73726d6c5f626162653a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6835316562616163646438636565393939a2033973726d6c5f626162653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838626464366437316663366336386133a303683c73726d6c5f626162653a3a5f5f4765744279746553747275637452616e646f6d6e6573733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831646266336432303235653433663633a4034273726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6832653030663433376237636334623732a50397013c73726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4578706563746564426c6f636b54696d6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834383432303533646236336462623264a60393013c73726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a45706f63684475726174696f6e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866373362303132363134623132356364a7033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6837346264393230333636623666316562a8033173726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a72616e646f6d3a3a6836306461326464656333373364646436a9033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861623464373335663864656363386661aa03930173726d6c5f73797374656d3a3a5f494d504c5f454e434f44455f464f525f4576656e745265636f72643a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f73797374656d3a3a4576656e745265636f72643c452c543e3e3a3a656e636f64655f746f3a3a6831323131373037393638613835333637ab0330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6836616262343766373764373233383832ac033973726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6839396533616666666131613734653864ad033b73726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838613435343333313564303062363733ae03663c73726d6c5f73797374656d3a3a5f5f476574427974655374727563744576656e74733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837643032313739653635613738326563af03693c73726d6c5f73797374656d3a3a5f5f47657442797465537472756374426c6f636b486173683c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831343962353364336363646564316439b0036e3c73726d6c5f73797374656d3a3a5f5f4765744279746553747275637452616e646f6d4d6174657269616c3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838346564373366313834376166366434b1034473726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6834613439316239383530666636343565b2033373726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a66696e616c697a653a3a6861336164316265613362353165373663b303920173726d6c5f636f6c6c6563746976653a3a5f494d504c5f4445434f44455f464f525f566f7465733a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6c6c6563746976653a3a566f7465733c4163636f756e7449643e3e3a3a6465636f64653a3a6831666334646262316561653233396639b4034a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6865373436613266666630383837623565b5033f73726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6866373435383836616563616334393835b6034173726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6831336536643135376135613433613432b7034173726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6834353831653732656334363130393330b8034273726d6c5f73797374656d3a3a436865636b5765696768743c543e3a3a636865636b5f626c6f636b5f6c656e6774683a3a6837666561303334346333386136616365b9033c73726d6c5f73797374656d3a3a436865636b5765696768743c543e3a3a636865636b5f7765696768743a3a6834326632643563336464616539323165ba03463c616c6c6f633a3a626f7865643a3a426f783c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831393764386331333362343930343066bb03473c73726d6c5f696e64696365733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831303562663766353932313861333062bc03473c73726d6c5f7374616b696e673a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831396539646437656462396264616366bd03493c73726d6c5f64656d6f63726163793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6836636635383139356236626464353231be034c3c73726d6c5f6d656d626572736869703a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837323735633464666230386236643532bf03493c73726d6c5f636f6e7472616374733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6862373936623731343832366162363138c003443c73726d6c5f7375646f3a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6865393938653136373161363737386139c103533c73726d6c5f617574686f726974795f646973636f766572793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837346565386530313939376239383937c203463c73726d6c5f73797374656d3a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6833626664323638333734663362376338c3034c3c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837663834326331386439383539653138c4033c73726d6c5f696e64696365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6837303666626537316539373135376665c5037573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6862383665646132366239376363326534c603d80173725f7072696d6974697665733a3a7472616e73616374696f6e5f76616c69646974793a3a5f494d504c5f454e434f44455f464f525f5472616e73616374696f6e56616c69646974794572726f723a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073725f7072696d6974697665733a3a7472616e73616374696f6e5f76616c69646974793a3a5472616e73616374696f6e56616c69646974794572726f723e3a3a656e636f64655f746f3a3a6831626165383133323764396564653362c7037173726d6c5f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a696e697469616c697a655f626c6f636b3a3a6834626664366136356235623930656539c8033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f65787465726e616c3a3a6862613562643931393264343264353735c9033b73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f7075626c69633a3a6864623438343534306330333732386561ca033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a7265666572656e64756d5f696e666f3a3a6833333765323135653936613163383731cb033873726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f746572735f666f723a3a6837306138346438373431306364346230cc033573726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f74655f6f663a3a6831613037316366663431353331376631cd033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a64656c6567617465645f766f7465733a3a6832663566356266663563303233643636ce033e73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a636c6561725f7265666572656e64756d3a3a6866666637373262613837616630303565cf03443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6832616531373964653035366164666439d0037973726d6c5f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a6170706c795f65787472696e7369635f776974685f6c656e3a3a6830363363313039363438386337343964d103a5013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e2061732073725f7072696d6974697665733a3a7472616974733a3a436865636b61626c653c4c6f6f6b75703e3e3a3a636865636b3a3a6835353432373336616466623430333761d2036e3c73726d6c5f636f6e7472616374733a3a436865636b426c6f636b4761734c696d69743c543e2061732073725f7072696d6974697665733a3a7472616974733a3a5369676e6564457874656e73696f6e3e3a3a76616c69646174653a3a6834613539353938646632343262313836d303363c5420617320636f72653a3a636f6e766572743a3a496e746f3c553e3e3a3a696e746f3a3a6832653964376331393038323734626436d4033c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6836356634343632646235343435393338d5033e73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6865636431373939313835396165306236d6034773726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864353861656165393464373762386164d70398013c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864623734353962613435343235656461d8033f73726d6c5f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6861613637353666646431666439393661d9034173726d6c5f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6838656137343163663931396330333264da0334636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6861613934663035386431333531633466db032e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6834333461393733383437303165333236dc033c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6835653664306564386338306561613034dd03593c73725f7072696d6974697665733a3a416e795369676e61747572652061732073725f7072696d6974697665733a3a7472616974733a3a5665726966793e3a3a7665726966793a3a6865653661376232666164623063306337de033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831313330393632353863393833353939df033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831333135303466353262396465616136e0033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861656430393864653237386637643631e1033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861666432643465663565656365613936e2033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a7075743a3a6838333637626463333564323039376438e303c40173726d6c5f636f6e7472616374733a3a5f494d504c5f454e434f44455f464f525f526177416c697665436f6e7472616374496e666f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6e7472616374733a3a526177416c697665436f6e7472616374496e666f3c436f6465486173682c42616c616e63652c426c6f636b4e756d6265723e3e3a3a656e636f64655f746f3a3a6837343039376637333530333664356132e4033873726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6839643530626664316331393964383432e5037773726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a76616c75653a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f7261676556616c75653c543e20666f7220473e3a3a6d75746174653a3a6833393630323862623831616532396435e6033c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6865373235383163383635373736343031e7033e73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838353138373039636366353134386634e8036b3c73726d6c5f636f6e7472616374733a3a5f5f4765744279746553747275637447617350726963653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837646161333630313731323962626161e903723c73726d6c5f636f6e7472616374733a3a5f5f4765744279746553747275637443757272656e745363686564756c653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830613432353664383239653035616630ea034773726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6839373030323763326334383864663966eb0398013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426c6f636b4761734c696d697444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835326264363965373737633864653839ec0397013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d617856616c756553697a6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863653266336335666664386535346666ed0393013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178446570746844656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839373239663263633533653864316636ee0396013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616c6c4261736546656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830613062653632333537663633303232ef0396013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a436f6e747261637446656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836643062623334363530643336623765f0039d013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5472616e73616374696f6e4279746546656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861653066326564313066333062336431f1039a013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53757263686172676552657761726444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835643765346164343430313363316363f2039c013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744465706f7369744f666673657444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830653366346264376531366535323031f3039c013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53746f7261676553697a654f666673657444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836666162343733336233653630636665f4039e013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5369676e6564436c61696d48616e646963617044656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832363431363262343562363133336365f5033773726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a626172655f63616c6c3a3a6862393261343137333037323335353038f6033773726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6761735f70726963653a3a6861353534306331613131336131343632f7033e73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a63757272656e745f7363686564756c653a3a6835393231353035363931356330383436f8033873726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a726573746f72655f746f3a3a6863613537313665383565633061613434f9034573726d6c5f636f6e7472616374733a3a7761736d3a3a707265706172653a3a436f6e74726163744d6f64756c653a3a6e65773a3a6838326533383933383863653766636635fa03467061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a436f646553656374696f6e3a3a626f646965733a3a6864393864326364313131613035613531fb0348616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6865373064323632373339343561313363fc033c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a66726f6d5f6d6f64756c653a3a6834643832616331306433343833336233fd03537061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a7265736f6c76655f747970655f7265663a3a6861643034326537313830333035313963fe03a9017061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c6553636166666f6c643e20666f72207061726974795f7761736d3a3a656c656d656e74733a3a6d6f64756c653a3a4d6f64756c653e3a3a66726f6d3a3a6836643231633062653130613035343964ff0344707761736d5f7574696c733a3a6761733a3a436f756e7465723a3a66696e616c697a655f6d6574657265645f626c6f636b3a3a686362636565306234333463346631643080042d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a68656165383561343031313132353734348104507061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a707573685f66756e6374696f6e3a3a6865396131343838383163653163323132820430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a686464633764633436363333376535353783043c707761736d5f7574696c733a3a737461636b5f6865696768743a3a696e6a6563745f6c696d697465723a3a686635333865316430386135653339666384046b3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683633316637353930306465663336646285046b3c636f72653a3a697465723a3a61646170746572733a3a526573756c745368756e743c492c453e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a686536383437396137393936386537646686046f3c636f72653a3a697465723a3a61646170746572733a3a526573756c745368756e743c492c453e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a7472795f666f6c643a3a686631323333633761626466646630306287049f013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a686661623762663862623438396439613888043773726d6c5f7375646f3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683535306364366435376331373164303289043973726d6c5f7375646f3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68303362303139613732626139303138328a04613c73726d6c5f7375646f3a3a5f5f476574427974655374727563744b65793c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68383731363333663133333061636665378b04a5017375627374726174655f7072696d6974697665733a3a737232353531393a3a5f494d504c5f454e434f44455f464f525f5075626c69633a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72207375627374726174655f7072696d6974697665733a3a737232353531393a3a5075626c69633e3a3a656e636f64653a3a68613163366230616563303734343431648c040c436f72655f76657273696f6e8d0412436f72655f657865637574655f626c6f636b8e04693c73725f7072696d6974697665733a3a7472616974733a3a426c616b6554776f3235362061732073725f7072696d6974697665733a3a7472616974733a3a486173683e3a3a6f7264657265645f747269655f726f6f743a3a68373739373939656532646161363861618f0415436f72655f696e697469616c697a655f626c6f636b9004114d657461646174615f6d657461646174619104483c5b545d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68666533386331353361356163326164389204683c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68393131356662623533323965303964399304683c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683930613566666362353464373266346694041c426c6f636b4275696c6465725f6170706c795f65787472696e73696395041b426c6f636b4275696c6465725f66696e616c697a655f626c6f636b960420426c6f636b4275696c6465725f696e686572656e745f65787472696e7369637397043873726d6c5f74696d657374616d703a3a657874726163745f696e686572656e745f646174613a3a686362316436643834626362643035333698041c426c6f636b4275696c6465725f636865636b5f696e686572656e7473990418426c6f636b4275696c6465725f72616e646f6d5f736565649a042b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e9b045673725f7072696d6974697665733a3a7472616e73616374696f6e5f76616c69646974793a3a56616c69645472616e73616374696f6e3a3a636f6d62696e655f776974683a3a68353736346238623566396161613662309c04214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b65729d0480013c73726d6c5f696d5f6f6e6c696e653a3a737232353531393a3a6170705f737232353531393a3a5075626c6963206173207375627374726174655f6170706c69636174696f6e5f63727970746f3a3a7472616974733a3a52756e74696d654170705075626c69633e3a3a616c6c3a3a68613834343166646339353935386136399e041e4772616e6470614170695f6772616e6470615f617574686f7269746965739f0415426162654170695f636f6e66696775726174696f6ea00421417574686f72697479446973636f766572794170695f617574686f726974696573a1041a417574686f72697479446973636f766572794170695f7369676ea2041c417574686f72697479446973636f766572794170695f766572696679a3041d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e6365a40411436f6e7472616374734170695f63616c6ca5042153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b657973a604820173726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654c696e6b65644d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6838663434353163653739313862313333a704820173726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654c696e6b65644d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6861663431626330376265363732653261a8043a73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6832383266383039373163393635623735a9043c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6830613933393034626364613731633464aa04743c73726d6c5f7374616b696e673a3a5f5f47657442797465537472756374536c6173685265776172644672616374696f6e3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830373539636563383531333663626462ab04773c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637443757272656e74457261506f696e74734561726e65643c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863346466393062396266616466383466ac04703c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637443757272656e7445726153746172743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861346332306237316637343535343862ad04683c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563745374616b6572733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834653030616266353365363433633733ae046b3c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637456616c696461746f72733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839633736316334353032636466336536af04763c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563744d696e696d756d56616c696461746f72436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861336434623962346538633532666237b0044073726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a736c61736861626c655f62616c616e63655f6f663a3a6861636135383433363936353265613265b1043273726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a626f6e6465643a3a6830636562393635626631386363616232b2044573726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6837306665313036376639643939383935b30498013c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426f6e64696e674475726174696f6e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832623535646136383130626464303061b4043773726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d616b655f7061796f75743a3a6832376631663237613230333735323861b5043973726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a7570646174655f6c65646765723a3a6832376563613564613530643864656139b6044a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6866633236366266623663653230323433b7043f73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a696e6a6563745f7265666572656e64756d3a3a6866346266323835623039613038383533b8043873726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6465706f7369745f6f663a3a6833636363393431363966326232643635b9043c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6831646437343931353664623131643533ba043e73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838336233383939373363343862666435bb046c3c73726d6c5f64656d6f63726163793a3a5f5f47657442797465537472756374426c61636b6c6973743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838623533343432616361336431616461bc046f3c73726d6c5f64656d6f63726163793a3a5f5f476574427974655374727563744e65787445787465726e616c3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837643466363231333432643433663038bd046e3c73726d6c5f64656d6f63726163793a3a5f5f4765744279746553747275637444656c65676174696f6e733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833626665323435333261616465653139be04703c73726d6c5f64656d6f63726163793a3a5f5f47657442797465537472756374446973706174636851756575653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835356135336235653738653362353537bf044773726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864666466353637383338323064313530c00497013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4c61756e6368506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865623830643136316665383833373935c104a0013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456d657267656e6379566f74696e67506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833316232323132653732363163316232c20499013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d4465706f73697444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832363265623533316566353366303065c3049a013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456e6163746d656e74506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838343565333534353965616136613466c4047573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6832623431383266303634326531386431c5043573726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a646f5f766f74653a3a6834376438626636343531373064396363c604553c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832333130333466623262396161316637c704303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830376539663164633463383837333064c804303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6833613863363935663762313962666661c904303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862343766326134326533363431363234ca04443c7061726974795f7761736d3a3a696f3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836656663396633373739323336343738cb04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6863373733386638313465306262636138cc04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6865336235353835366335366563383866cd04457061726974795f7761736d3a3a656c656d656e74733a3a7365676d656e743a3a446174615365676d656e743a3a76616c75653a3a6861333366626161653136643036353336ce04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831613930373663633036623361623965cf04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835653364383861646633663531633032d004553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832333362653833316563653732373563d104553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a426c6f636b5479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838376433336131303565663737663430d204303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839343630376237663435333334613836d30433636f72653a3a6f7074696f6e3a3a4f7074696f6e3c26543e3a3a636c6f6e65643a3a6833336430666462656635333766383862d404453c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834643038393932373338626235366665d504303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839626562663532613237376634306665d60440707761736d5f7574696c733a3a737461636b5f6865696768743a3a636f6d707574655f737461636b5f636f73743a3a6832656332613464616131633336616664d704533c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a737065635f657874656e643a3a6833663135373864636638623165303366d804323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6833333964366132336633616239353839d904593c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6832303531346563626537613764663764da04613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6865646336386533623863393232303938db043f707761736d5f7574696c733a3a737461636b5f6865696768743a3a7265736f6c76655f66756e635f747970653a3a6835666661376165643139363735653632dc0430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6834383364613531306533653334653735dd0441707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a636f6d707574653a3a6830646665316537373831363437623164de0434636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6835353237373135663731363338343330df042e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6833386430383365613239326630376635e0043c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6833396131373737326563303238336633e104303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830316234393736623730636366393962e2045a3c707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a4672616d6520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837373362393934386530363033303234e30446707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a6672616d653a3a6838653765623332646462333937343230e4044b707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a706f705f76616c7565733a3a6837613665336661633565303837386131e504323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6839353333633564346536303161336562e604323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6838333065633835663931653437646439e7044e73725f696f3a3a696d703a3a6578743a3a65787465726e5f66756e6374696f6e735f686f73745f696d706c3a3a6578745f7072696e745f757466383a3a6831316330336538356431303265376435e804683c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6833643262383038376431613430623032e9046b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6861376364656439653336396133323630ea047d3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973745772697465723c492c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6835653237663566326461333132313031eb046f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6833356432333232326631633463663837ec046f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743634206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6836666134636162356466656233633936ed046c3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6861353061613066336466316663643961ee046f3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6838663538373638626466643663363436ef04793c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973743c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6830326534363637616133663639633832f0046b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6866616531383734653335636562616238f104713c7061726974795f7761736d3a3a656c656d656e74733a3a696e6465785f6d61703a3a496e6465784d61703c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6837353163336164613534326365643464f204783c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6866653634336337356161613937393331f3047c3c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6834643135366137643832646366653437f404743c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6862396165303366373735323163303237f504713c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a437573746f6d53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6864383435613264366361663338313736f6044b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833303831373966353539376166373962f7044b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6862636562656465393336303030353930f8044b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6864356438333636626133356134666363f904463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6830393432356365343637643235646564fa046f3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6835373532633363323332363061333635fb04457061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e5265616465723a3a6e65773a3a6866656161316461386338643835366362fc0486017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a646573657269616c697a653a3a6832303434366565303237346466653739fd042d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6862353339623432353939316562373937fe0434636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6866623631656536316166636362646537ff042e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a683038653936383835383561383932643480053c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a683631623461353636613537323964363781053b636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a7b7b636c6f737572657d7d3a3a68343831336137356561636161653734378205323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68663961303537303266333235643366618305397761736d695f76616c69646174696f6e3a3a76616c69646174655f6d656d6f72795f747970653a3a68386330623261323731393065373038328405347761736d695f76616c69646174696f6e3a3a657870725f636f6e73745f747970653a3a683232363566313162343233326265373685054a7761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a737465703a3a68353864303463346465383638653431658605473c7761736d695f76616c69646174696f6e3a3a4572726f7220617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6837353566373166363063653234393764870537616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a683462396237323936623436336634353588053b636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f70795f66726f6d5f736c6963653a3a68383832353431646433666436326537318905347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f76616c75653a3a68656337393434626366663764623131668a05347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f6c6162656c3a3a68326336353735376131376361383336338b05407761736d695f76616c69646174696f6e3a3a7574696c3a3a4c6f63616c733a3a747970655f6f665f6c6f63616c3a3a68383162303837636564666462346434388c05543c7761736d695f76616c69646174696f6e3a3a66756e633a3a537461636b56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68633739643161663136313838663435368d05537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6c6f61643a3a68366138333538613164613464626566308e05547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f73746f72653a3a68636564333562656564653636653562628f05557761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f746573746f703a3a68616533303233333361636330633266319005547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f72656c6f703a3a68376534356165623939363562643230379105537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f756e6f703a3a68313765386433643566626361383862399205547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f62696e6f703a3a68333830663663353461613061383264399305547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6376746f703a3a6835353663323836383738376336363661940530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6830363931663361393762336664333466950530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68613966613837316265643663366635309605303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68393761376132643963636263616632399705453c616c6c6f633a3a737472696e673a3a537472696e6720617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683630376665306161343865353334636298054c3c7761736d695f76616c69646174696f6e3a3a737461636b3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68653966363833643036366338313166359905066d656d7365749a05066d656d6370799b05076d656d6d6f76659c05066d656d636d709d05095f5f6173686c7469339e05095f5f6c7368727469339f05085f5f6d756c746933a005095f5f75646976746933a105095f5f756d6f64746933a2050c5f5f756469766d6f6474693400550970726f64756365727302086c616e6775616765010452757374000c70726f6365737365642d62790105727573746325312e33392e302d6e696768746c79202831646431383834383920323031392d30392d323229", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579730cd914acf7b89329ae59e8f7e3b8f1ee7a4f5f68d4749cca82814f2f5b1d6bbb": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0xc98362e2ca21b342cc749022ed9b560e4d29ec9862a960c2538c314f1d279635": "0x149ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e3180973474718099c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d1268655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x6e4ab2ac5a7cf9b1829eacc84a75bde0804be01fc31c9419ea72407f50a33384": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x366a192e1ce90bf109f11cf4d4bdab1ce310d835c09411b1be3ad53814e33196": "0x000001547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0x125dc846383907f5846f72ce53ca0e4b": "0x00ca9a3b000000000000000000000000", - "0x46cef122497fefa60faf6c66d3ef05caf9870446796ae11f0a4f734fee993d8b": "0x00", - "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b6579737f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0x71020fee971bd00e8248d1830b8cffbe5b9cf4de1ea2911a1665c44fd70ab6f3": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630f0000c16ff286230f0000c16ff2862300", - "0xfff675c76ad8a5dfbd7db9a4e80f7c0ece595ad1878d2b6fca6086b2483a055b": "0x0000c16ff28623000000000000000000", - "0x2b334d6ac6698775ed17edf8cd3cbd9dae56cead0d69cb54f6af6aaecba544d8": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0xdfaac108e0d4bc78fc9419a7fcfa84dc": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d6568655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde789c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x3ae31af9a378162eb2736f26855c9ad8": "0x4545454545454545454545454545454545454545454545454545454545454545", - "0x3a65787472696e7369635f696e646578": "0x00000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797346c8960f8387b17441ee2be48a0896e48d3580e922c6e1cd8f53a621370c1e49": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0x7e6064dc0e78ffebb59b3053826a9467": "0x109c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d1268655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0xc1fdc3d212357bc2fa98f2a77b941f0c": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d6568655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde789c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797301dd273832961ca94116fd224019ea1370c0e3d27bebb1041b35651146d17832": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0x686f6c72b7b80bad8dba022335cb7c9e4556ac7ea200008da8046e3178eb89c1": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x2d5205eddfc20f1a616c0391abb78a3920e823abe7ed33cfd7945dd1a1bf8651": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff0f", - "0x040ff70c23416b89ce6afb75ee0d362e": "0x00000000", - "0x121725e2f949944d00a8c011c0db54ae07b84a6ca772adf3c65417345d91522d": "0x0000c16ff28623000000000000000000", - "0x9c16fd03b96712dc0751bb0d63bc05aa": "0x00e1f505", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973d1ae046d940202772415992434f839d8c546542e3055143c430f7eec87f7cb69": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0xccea67b51b4fa33ecbff70a8977ad91d9c60d620f3ab5ac9626dea15cde023b7": "0x0ff6ffc06ff286230ff6ffc06ff2862300", - "0x886726f904d8372fdabb7707870c2fad": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f43780100000000000000482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a0100000000000000482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e01000000000000006e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91060100000000000000", - "0x68c8d2f39c4605e65218c22c5664917047e4900c797b7dd33999d94213c75049": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff0f", - "0x7eb7a404bf7e3466c3f6c5914e25edfaab48b1e24fd29ea5a94deaaa1aba80e6": "0x0001547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65019c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0xdfa1667c116b77971ada377f9bd9c485a0566b8e477ae01969120423f2f124ea": "0x4545454545454545454545454545454545454545454545454545454545454545", - "0x92f53c21a80e624b3c606bc8ec0ce2a3003c4fe385bed33998bf4dc79b8970f2": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d650f0000c16ff286230f0000c16ff2862300", - "0xb2029f8665aac509629f2d28cea790a3": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b657973e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a", - "0x78f4ad73d6b7279f8d06f359e363c829": "0x0000a49d8fc957363600000000000000", - "0xfd0cbba69a04d769ddcdbb15f5123c98041978f5241f33f78f62b48e3a02b740": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff0f", - "0x26ac4a74e1ba94e0e7dbfc3b2aea083cf3c0f0d80eb999c7cebb340ee8934da9": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde780f0000c16ff286230f0000c16ff2862300", - "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b65797394f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378", - "0x4ac2684a5a20e7a5adf17ed7aa792a3f6334a0505f02b2a44c3934d36cc4ee0a": "0xc8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e", - "0xa5e869ecc1b914a6b0cf5f02b874f5eb90f1739fbd3edd01e5835d1517fd9f72": "0x781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276" - }, - {} - ] - } -} diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs deleted file mode 100644 index 360421bda1087..0000000000000 --- a/node/cli/src/chain_spec.rs +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate chain configurations. - -use chain_spec::ChainSpecExtension; -use primitives::{Pair, Public, crypto::UncheckedInto, sr25519}; -use serde::{Serialize, Deserialize}; -use node_runtime::{ - AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, - ElectionsConfig, GrandpaConfig, ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, - StakingConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, WASM_BINARY, -}; -use node_runtime::Block; -use node_runtime::constants::{time::*, currency::*}; -use substrate_service; -use hex_literal::hex; -use substrate_telemetry::TelemetryEndpoints; -use grandpa_primitives::{AuthorityId as GrandpaId}; -use babe_primitives::{AuthorityId as BabeId}; -use im_online::sr25519::{AuthorityId as ImOnlineId}; -use sr_primitives::{Perbill, traits::{Verify, IdentifyAccount}}; - -pub use node_primitives::{AccountId, Balance, Signature}; -pub use node_runtime::GenesisConfig; - -type AccountPublic = ::Signer; - -const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; - -/// Node `ChainSpec` extensions. -/// -/// Additional parameters for some Substrate core modules, -/// customizable from the chain spec. -#[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)] -pub struct Extensions { - /// Block numbers with known hashes. - pub fork_blocks: client::ForkBlocks, -} - -/// Specialized `ChainSpec`. -pub type ChainSpec = substrate_service::ChainSpec< - GenesisConfig, - Extensions, ->; -/// Flaming Fir testnet generator -pub fn flaming_fir_config() -> Result { - ChainSpec::from_json_bytes(&include_bytes!("../res/flaming-fir.json")[..]) -} - -fn session_keys(grandpa: GrandpaId, babe: BabeId, im_online: ImOnlineId) -> SessionKeys { - SessionKeys { grandpa, babe, im_online, } -} - -fn staging_testnet_config_genesis() -> GenesisConfig { - // stash, controller, session-key - // generated with secret: - // for i in 1 2 3 4 ; do for j in stash controller; do subkey inspect "$secret"/fir/$j/$i; done; done - // and - // for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 inspect "$secret"//fir//$j//$i; done; done - - let initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId)> = vec![( - // 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy - hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].into(), - // 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq - hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].into(), - // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC - hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), - // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 - hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), - // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 - hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), - ),( - // 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2 - hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].into(), - // 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF - hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].into(), - // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE - hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), - // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ - hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), - // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ - hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), - ),( - // 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp - hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].into(), - // 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9 - hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].into(), - // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d - hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), - // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH - hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), - // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH - hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), - ),( - // 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9 - hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].into(), - // 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn - hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].into(), - // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 - hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), - // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x - hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), - // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x - hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), - )]; - - // generated with secret: subkey inspect "$secret"/fir - let root_key: AccountId = hex![ - // 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo - "9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809" - ].into(); - - let endowed_accounts: Vec = vec![root_key.clone()]; - - testnet_genesis( - initial_authorities, - root_key, - Some(endowed_accounts), - false, - ) -} - -/// Staging testnet config. -pub fn staging_testnet_config() -> ChainSpec { - let boot_nodes = vec![]; - ChainSpec::from_genesis( - "Staging Testnet", - "staging_testnet", - staging_testnet_config_genesis, - boot_nodes, - Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)])), - None, - None, - Default::default(), - ) -} - -/// Helper function to generate a crypto pair from seed -pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) - .expect("static values are valid; qed") - .public() -} - -/// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId where - AccountPublic: From<::Public> -{ - AccountPublic::from(get_from_seed::(seed)).into_account() -} - -/// Helper function to generate stash, controller and session key from seed -pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, GrandpaId, BabeId, ImOnlineId) { - ( - get_account_id_from_seed::(&format!("{}//stash", seed)), - get_account_id_from_seed::(seed), - get_from_seed::(seed), - get_from_seed::(seed), - get_from_seed::(seed), - ) -} - -/// Helper function to create GenesisConfig for testing -pub fn testnet_genesis( - initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId)>, - root_key: AccountId, - endowed_accounts: Option>, - enable_println: bool, -) -> GenesisConfig { - let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(|| { - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - ] - }); - - const ENDOWMENT: Balance = 10_000_000 * DOLLARS; - const STASH: Balance = 100 * DOLLARS; - - GenesisConfig { - system: Some(SystemConfig { - code: WASM_BINARY.to_vec(), - changes_trie_config: Default::default(), - }), - balances: Some(BalancesConfig { - balances: endowed_accounts.iter().cloned() - .map(|k| (k, ENDOWMENT)) - .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) - .collect(), - vesting: vec![], - }), - indices: Some(IndicesConfig { - ids: endowed_accounts.iter().cloned() - .chain(initial_authorities.iter().map(|x| x.0.clone())) - .collect::>(), - }), - session: Some(SessionConfig { - keys: initial_authorities.iter().map(|x| { - (x.0.clone(), session_keys(x.2.clone(), x.3.clone(), x.4.clone())) - }).collect::>(), - }), - staking: Some(StakingConfig { - current_era: 0, - validator_count: initial_authorities.len() as u32 * 2, - minimum_validator_count: initial_authorities.len() as u32, - stakers: initial_authorities.iter().map(|x| { - (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator) - }).collect(), - invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), - slash_reward_fraction: Perbill::from_percent(10), - .. Default::default() - }), - democracy: Some(DemocracyConfig::default()), - collective_Instance1: Some(CouncilConfig { - members: vec![], - phantom: Default::default(), - }), - collective_Instance2: Some(TechnicalCommitteeConfig { - members: vec![], - phantom: Default::default(), - }), - elections_phragmen: Some(ElectionsConfig { - members: endowed_accounts.iter().take(2).cloned().collect(), - term_duration: 28 * DAYS, - desired_members: 4, - desired_runners_up: 1, - }), - contracts: Some(ContractsConfig { - current_schedule: contracts::Schedule { - enable_println, // this should only be enabled on development chains - ..Default::default() - }, - gas_price: 1 * MILLICENTS, - }), - sudo: Some(SudoConfig { - key: root_key, - }), - babe: Some(BabeConfig { - authorities: vec![], - }), - im_online: Some(ImOnlineConfig { - keys: vec![], - }), - authority_discovery: Some(AuthorityDiscoveryConfig{ - keys: vec![], - }), - grandpa: Some(GrandpaConfig { - authorities: vec![], - }), - membership_Instance1: Some(Default::default()), - treasury: Some(Default::default()), - } -} - -fn development_config_genesis() -> GenesisConfig { - testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - ], - get_account_id_from_seed::("Alice"), - None, - true, - ) -} - -/// Development config (single validator Alice) -pub fn development_config() -> ChainSpec { - ChainSpec::from_genesis( - "Development", - "dev", - development_config_genesis, - vec![], - None, - None, - None, - Default::default(), - ) -} - -fn local_testnet_genesis() -> GenesisConfig { - testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - get_authority_keys_from_seed("Bob"), - ], - get_account_id_from_seed::("Alice"), - None, - false, - ) -} - -/// Local testnet config (multivalidator Alice + Bob) -pub fn local_testnet_config() -> ChainSpec { - ChainSpec::from_genesis( - "Local Testnet", - "local_testnet", - local_testnet_genesis, - vec![], - None, - None, - None, - Default::default(), - ) -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::service::new_full; - use substrate_service::Roles; - use service_test; - - fn local_testnet_genesis_instant_single() -> GenesisConfig { - testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - ], - get_account_id_from_seed::("Alice"), - None, - false, - ) - } - - /// Local testnet config (single validator - Alice) - pub fn integration_test_config_with_single_authority() -> ChainSpec { - ChainSpec::from_genesis( - "Integration Test", - "test", - local_testnet_genesis_instant_single, - vec![], - None, - None, - None, - Default::default(), - ) - } - - /// Local testnet config (multivalidator Alice + Bob) - pub fn integration_test_config_with_two_authorities() -> ChainSpec { - ChainSpec::from_genesis( - "Integration Test", - "test", - local_testnet_genesis, - vec![], - None, - None, - None, - Default::default(), - ) - } - - #[test] - #[ignore] - fn test_connectivity() { - service_test::connectivity( - integration_test_config_with_two_authorities(), - |config| new_full(config), - |mut config| { - // light nodes are unsupported - config.roles = Roles::FULL; - new_full(config) - }, - true, - ); - } -} diff --git a/node/cli/src/lib.rs b/node/cli/src/lib.rs deleted file mode 100644 index d339952ca83ba..0000000000000 --- a/node/cli/src/lib.rs +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate CLI library. - -#![warn(missing_docs)] -#![warn(unused_extern_crates)] - -pub use cli::error; -pub mod chain_spec; -#[macro_use] -mod service; -mod factory_impl; - -use tokio::prelude::Future; -use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; -pub use cli::{VersionInfo, IntoExit, NoCustom, SharedParams, ExecutionStrategyParam}; -use substrate_service::{AbstractService, Roles as ServiceRoles, Configuration}; -use log::info; -use structopt::{StructOpt, clap::App}; -use cli::{AugmentClap, GetLogFilter, parse_and_prepare, ParseAndPrepare}; -use crate::factory_impl::FactoryState; -use transaction_factory::RuntimeAdapter; -use client::ExecutionStrategies; - -/// The chain specification option. -#[derive(Clone, Debug, PartialEq)] -pub enum ChainSpec { - /// Whatever the current runtime is, with just Alice as an auth. - Development, - /// Whatever the current runtime is, with simple Alice/Bob auths. - LocalTestnet, - /// The Flaming Fir testnet. - FlamingFir, - /// Whatever the current runtime is with the "global testnet" defaults. - StagingTestnet, -} - -/// Custom subcommands. -#[derive(Clone, Debug, StructOpt)] -pub enum CustomSubcommands { - /// The custom factory subcommmand for manufacturing transactions. - #[structopt( - name = "factory", - about = "Manufactures num transactions from Alice to random accounts. \ - Only supported for development or local testnet." - )] - Factory(FactoryCmd), -} - -impl GetLogFilter for CustomSubcommands { - fn get_log_filter(&self) -> Option { - None - } -} - -/// The `factory` command used to generate transactions. -/// Please note: this command currently only works on an empty database! -#[derive(Debug, StructOpt, Clone)] -pub struct FactoryCmd { - /// How often to repeat. This option only has an effect in mode `MasterToNToM`. - #[structopt(long="rounds", default_value = "1")] - pub rounds: u64, - - /// MasterToN: Manufacture `num` transactions from the master account - /// to `num` randomly created accounts, one each. - /// - /// MasterTo1: Manufacture `num` transactions from the master account - /// to exactly one other randomly created account. - /// - /// MasterToNToM: Manufacture `num` transactions from the master account - /// to `num` randomly created accounts. - /// From each of these randomly created accounts manufacture - /// a transaction to another randomly created account. - /// Repeat this `rounds` times. If `rounds` = 1 the behavior - /// is the same as `MasterToN`.{n} - /// A -> B, A -> C, A -> D, ... x `num`{n} - /// B -> E, C -> F, D -> G, ...{n} - /// ... x `rounds` - /// - /// These three modes control manufacturing. - #[structopt(long="mode", default_value = "MasterToN")] - pub mode: transaction_factory::Mode, - - /// Number of transactions to generate. In mode `MasterNToNToM` this is - /// the number of transactions per round. - #[structopt(long="num", default_value = "8")] - pub num: u64, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub shared_params: SharedParams, - - /// The means of execution used when calling into the runtime while importing blocks. - #[structopt( - long = "execution", - value_name = "STRATEGY", - possible_values = &ExecutionStrategyParam::variants(), - case_insensitive = true, - default_value = "NativeElseWasm" - )] - pub execution: ExecutionStrategyParam, -} - -impl AugmentClap for FactoryCmd { - fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { - FactoryCmd::augment_clap(app) - } -} - -/// Get a chain config from a spec setting. -impl ChainSpec { - pub(crate) fn load(self) -> Result { - Ok(match self { - ChainSpec::FlamingFir => chain_spec::flaming_fir_config()?, - ChainSpec::Development => chain_spec::development_config(), - ChainSpec::LocalTestnet => chain_spec::local_testnet_config(), - ChainSpec::StagingTestnet => chain_spec::staging_testnet_config(), - }) - } - - pub(crate) fn from(s: &str) -> Option { - match s { - "dev" => Some(ChainSpec::Development), - "local" => Some(ChainSpec::LocalTestnet), - "" | "fir" | "flaming-fir" => Some(ChainSpec::FlamingFir), - "staging" => Some(ChainSpec::StagingTestnet), - _ => None, - } - } -} - -fn load_spec(id: &str) -> Result, String> { - Ok(match ChainSpec::from(id) { - Some(spec) => Some(spec.load()?), - None => None, - }) -} - -/// Parse command line arguments into service configuration. -pub fn run(args: I, exit: E, version: cli::VersionInfo) -> error::Result<()> where - I: IntoIterator, - T: Into + Clone, - E: IntoExit, -{ - type Config = Configuration<(), A, B>; - - match parse_and_prepare::(&version, "substrate-node", args) { - ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, - |exit, _cli_args, _custom_args, config: Config<_, _>| { - info!("{}", version.name); - info!(" version {}", config.full_version()); - info!(" by Parity Technologies, 2017-2019"); - info!("Chain specification: {}", config.chain_spec.name()); - info!("Node name: {}", config.name); - info!("Roles: {:?}", config.roles); - let runtime = RuntimeBuilder::new().name_prefix("main-tokio-").build() - .map_err(|e| format!("{:?}", e))?; - match config.roles { - ServiceRoles::LIGHT => run_until_exit( - runtime, - service::new_light(config)?, - exit - ), - _ => run_until_exit( - runtime, - service::new_full(config)?, - exit - ), - } - }), - ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec), - ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| - Ok(new_full_start!(config).0), load_spec, exit), - ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| - Ok(new_full_start!(config).0), load_spec, exit), - ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_, _>| - Ok(new_full_start!(config).0), load_spec), - ParseAndPrepare::CustomCommand(CustomSubcommands::Factory(cli_args)) => { - let mut config: Config<_, _> = cli::create_config_with_db_path( - load_spec, - &cli_args.shared_params, - &version, - )?; - config.execution_strategies = ExecutionStrategies { - importing: cli_args.execution.into(), - block_construction: cli_args.execution.into(), - other: cli_args.execution.into(), - ..Default::default() - }; - - match ChainSpec::from(config.chain_spec.id()) { - Some(ref c) if c == &ChainSpec::Development || c == &ChainSpec::LocalTestnet => {}, - _ => panic!("Factory is only supported for development and local testnet."), - } - - let factory_state = FactoryState::new( - cli_args.mode.clone(), - cli_args.num, - cli_args.rounds, - ); - - let service_builder = new_full_start!(config).0; - transaction_factory::factory::, _, _, _, _, _>( - factory_state, - service_builder.client(), - service_builder.select_chain() - .expect("The select_chain is always initialized by new_full_start!; QED") - ).map_err(|e| format!("Error in transaction factory: {}", e))?; - - Ok(()) - } - } -} - -fn run_until_exit( - mut runtime: Runtime, - service: T, - e: E, -) -> error::Result<()> -where - T: AbstractService, - E: IntoExit, -{ - let (exit_send, exit) = exit_future::signal(); - - let informant = cli::informant::build(&service); - runtime.executor().spawn(exit.until(informant).map(|_| ())); - - // we eagerly drop the service so that the internal exit future is fired, - // but we need to keep holding a reference to the global telemetry guard - let _telemetry = service.telemetry(); - - let service_res = { - let exit = e.into_exit().map_err(|_| error::Error::Other("Exit future failed.".into())); - let service = service.map_err(|err| error::Error::Service(err)); - let select = service.select(exit).map(|_| ()).map_err(|(err, _)| err); - runtime.block_on(select) - }; - - exit_send.fire(); - - // TODO [andre]: timeout this future #1318 - let _ = runtime.shutdown_on_idle().wait(); - - service_res -} diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs deleted file mode 100644 index 2f18efc13e4e3..0000000000000 --- a/node/cli/src/service.rs +++ /dev/null @@ -1,588 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![warn(unused_extern_crates)] - -//! Service implementation. Specialized wrapper over substrate service. - -use std::sync::Arc; - -use babe; -use client::{self, LongestChain}; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; -use futures03::prelude::*; -use node_executor; -use node_primitives::Block; -use node_runtime::{GenesisConfig, RuntimeApi}; -use substrate_service::{ - AbstractService, ServiceBuilder, config::Configuration, error::{Error as ServiceError}, -}; -use transaction_pool::{self, txpool::{Pool as TransactionPool}}; -use inherents::InherentDataProviders; -use network::construct_simple_protocol; - -use substrate_service::{Service, NetworkStatus}; -use client::{Client, LocalCallExecutor}; -use client_db::Backend; -use sr_primitives::traits::Block as BlockT; -use node_executor::NativeExecutor; -use network::NetworkService; -use offchain::OffchainWorkers; -use primitives::Blake2Hasher; - -construct_simple_protocol! { - /// Demo protocol attachment for substrate. - pub struct NodeProtocol where Block = Block { } -} - -/// Starts a `ServiceBuilder` for a full service. -/// -/// Use this macro if you don't actually need the full service, but just the builder in order to -/// be able to perform chain operations. -macro_rules! new_full_start { - ($config:expr) => {{ - type RpcExtension = jsonrpc_core::IoHandler; - let mut import_setup = None; - let inherent_data_providers = inherents::InherentDataProviders::new(); - - let builder = substrate_service::ServiceBuilder::new_full::< - node_primitives::Block, node_runtime::RuntimeApi, node_executor::Executor - >($config)? - .with_select_chain(|_config, backend| { - Ok(client::LongestChain::new(backend.clone())) - })? - .with_transaction_pool(|config, client| - Ok(transaction_pool::txpool::Pool::new(config, transaction_pool::FullChainApi::new(client))) - )? - .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { - let select_chain = select_chain.take() - .ok_or_else(|| substrate_service::Error::SelectChainRequired)?; - let (grandpa_block_import, grandpa_link) = - grandpa::block_import::<_, _, _, node_runtime::RuntimeApi, _, _>( - client.clone(), &*client, select_chain - )?; - let justification_import = grandpa_block_import.clone(); - - let (block_import, babe_link) = babe::block_import( - babe::Config::get_or_compute(&*client)?, - grandpa_block_import, - client.clone(), - client.clone(), - )?; - - let import_queue = babe::import_queue( - babe_link.clone(), - block_import.clone(), - Some(Box::new(justification_import)), - None, - client.clone(), - client, - inherent_data_providers.clone(), - )?; - - import_setup = Some((block_import, grandpa_link, babe_link)); - Ok(import_queue) - })? - .with_rpc_extensions(|client, pool| -> RpcExtension { - node_rpc::create(client, pool) - })?; - - (builder, import_setup, inherent_data_providers) - }} -} - -/// Creates a full service from the configuration. -/// -/// We need to use a macro because the test suit doesn't work with an opaque service. It expects -/// concrete types instead. -macro_rules! new_full { - ($config:expr, $with_startup_data: expr) => {{ - use futures::sync::mpsc; - use network::DhtEvent; - - let ( - is_authority, - force_authoring, - name, - disable_grandpa - ) = ( - $config.roles.is_authority(), - $config.force_authoring, - $config.name.clone(), - $config.disable_grandpa - ); - - let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config); - - // Dht event channel from the network to the authority discovery module. Use bounded channel to ensure - // back-pressure. Authority discovery is triggering one event per authority within the current authority set. - // This estimates the authority set size to be somewhere below 10 000 thereby setting the channel buffer size to - // 10 000. - let (dht_event_tx, dht_event_rx) = - mpsc::channel::(10000); - - let service = builder.with_network_protocol(|_| Ok(crate::service::NodeProtocol::new()))? - .with_finality_proof_provider(|client, backend| - Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, client)) as _) - )? - .with_dht_event_tx(dht_event_tx)? - .build()?; - - let (block_import, grandpa_link, babe_link) = import_setup.take() - .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); - - ($with_startup_data)(&block_import, &babe_link); - - if is_authority { - let proposer = substrate_basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; - - let client = service.client(); - let select_chain = service.select_chain() - .ok_or(substrate_service::Error::SelectChainRequired)?; - - let babe_config = babe::BabeParams { - keystore: service.keystore(), - client, - select_chain, - env: proposer, - block_import, - sync_oracle: service.network(), - inherent_data_providers: inherent_data_providers.clone(), - force_authoring, - babe_link, - }; - - let babe = babe::start_babe(babe_config)?; - service.spawn_essential_task(babe); - - let authority_discovery = authority_discovery::AuthorityDiscovery::new( - service.client(), - service.network(), - dht_event_rx, - ); - - service.spawn_task(authority_discovery); - } - - let config = grandpa::Config { - // FIXME #1578 make this available through chainspec - gossip_duration: std::time::Duration::from_millis(333), - justification_period: 512, - name: Some(name), - keystore: Some(service.keystore()), - }; - - match (is_authority, disable_grandpa) { - (false, false) => { - // start the lightweight GRANDPA observer - service.spawn_task(grandpa::run_grandpa_observer( - config, - grandpa_link, - service.network(), - service.on_exit(), - )?.map(|()| Ok::<(), ()>(())).compat()); - }, - (true, false) => { - // start the full GRANDPA voter - let grandpa_config = grandpa::GrandpaParams { - config: config, - link: grandpa_link, - network: service.network(), - inherent_data_providers: inherent_data_providers.clone(), - on_exit: service.on_exit(), - telemetry_on_connect: Some(service.telemetry_on_connect_stream()), - voting_rule: grandpa::VotingRulesBuilder::default().build(), - }; - // the GRANDPA voter task is considered infallible, i.e. - // if it fails we take down the service with it. - service.spawn_essential_task(grandpa::run_grandpa_voter(grandpa_config)? - .map(|()| Ok::<(), ()>(())).compat()); - }, - (_, true) => { - grandpa::setup_disabled_grandpa( - service.client(), - &inherent_data_providers, - service.network(), - )?; - }, - } - - Ok((service, inherent_data_providers)) - }}; - ($config:expr) => {{ - new_full!($config, |_, _| {}) - }} -} - -#[allow(dead_code)] -type ConcreteBlock = node_primitives::Block; -#[allow(dead_code)] -type ConcreteClient = - Client< - Backend, - LocalCallExecutor, - NativeExecutor>, - ConcreteBlock, - node_runtime::RuntimeApi - >; -#[allow(dead_code)] -type ConcreteBackend = Backend; - -/// A specialized configuration object for setting up the node.. -pub type NodeConfiguration = Configuration; - -/// Builds a new service for a full client. -pub fn new_full(config: NodeConfiguration) --> Result< - Service< - ConcreteBlock, - ConcreteClient, - LongestChain, - NetworkStatus, - NetworkService::Hash>, - TransactionPool>, - OffchainWorkers< - ConcreteClient, - >::OffchainStorage, - ConcreteBlock, - > - >, - ServiceError, -> -{ - new_full!(config).map(|(service, _)| service) -} - -/// Builds a new service for a light client. -pub fn new_light(config: NodeConfiguration) --> Result { - type RpcExtension = jsonrpc_core::IoHandler; - let inherent_data_providers = InherentDataProviders::new(); - - let service = ServiceBuilder::new_light::(config)? - .with_select_chain(|_config, backend| { - Ok(LongestChain::new(backend.clone())) - })? - .with_transaction_pool(|config, client| - Ok(TransactionPool::new(config, transaction_pool::FullChainApi::new(client))) - )? - .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { - let fetch_checker = fetcher - .map(|fetcher| fetcher.checker().clone()) - .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; - let grandpa_block_import = grandpa::light_block_import::<_, _, _, RuntimeApi, _>( - client.clone(), backend, Arc::new(fetch_checker), client.clone() - )?; - - let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = - finality_proof_import.create_finality_proof_request_builder(); - - let (babe_block_import, babe_link) = babe::block_import( - babe::Config::get_or_compute(&*client)?, - grandpa_block_import, - client.clone(), - client.clone(), - )?; - - let import_queue = babe::import_queue( - babe_link, - babe_block_import, - None, - Some(Box::new(finality_proof_import)), - client.clone(), - client, - inherent_data_providers.clone(), - )?; - - Ok((import_queue, finality_proof_request_builder)) - })? - .with_network_protocol(|_| Ok(NodeProtocol::new()))? - .with_finality_proof_provider(|client, backend| - Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) - )? - .with_rpc_extensions(|client, pool| -> RpcExtension { - node_rpc::create(client, pool) - })? - .build()?; - - Ok(service) -} - -#[cfg(test)] -mod tests { - use std::sync::Arc; - use babe::CompatibleDigestItem; - use consensus_common::{ - Environment, Proposer, BlockImportParams, BlockOrigin, ForkChoiceStrategy, BlockImport, - }; - use node_primitives::{Block, DigestItem, Signature}; - use node_runtime::{BalancesCall, Call, UncheckedExtrinsic, Address}; - use node_runtime::constants::{currency::CENTS, time::SLOT_DURATION}; - use codec::{Encode, Decode}; - use primitives::{crypto::Pair as CryptoPair, H256}; - use sr_primitives::{ - generic::{BlockId, Era, Digest, SignedPayload}, - traits::Block as BlockT, - traits::Verify, - OpaqueExtrinsic, - }; - use timestamp; - use finality_tracker; - use keyring::AccountKeyring; - use substrate_service::{AbstractService, Roles}; - use crate::service::new_full; - use sr_primitives::traits::IdentifyAccount; - - type AccountPublic = ::Signer; - - #[cfg(feature = "rhd")] - fn test_sync() { - use primitives::ed25519::Pair; - - use {service_test, Factory}; - use client::{BlockImportParams, BlockOrigin}; - - let alice: Arc = Arc::new(Keyring::Alice.into()); - let bob: Arc = Arc::new(Keyring::Bob.into()); - let validators = vec![alice.public().0.into(), bob.public().0.into()]; - let keys: Vec<&ed25519::Pair> = vec![&*alice, &*bob]; - let dummy_runtime = ::tokio::runtime::Runtime::new().unwrap(); - let block_factory = |service: &::FullService| { - let block_id = BlockId::number(service.client().info().chain.best_number); - let parent_header = service.client().header(&block_id).unwrap().unwrap(); - let consensus_net = ConsensusNetwork::new(service.network(), service.client().clone()); - let proposer_factory = consensus::ProposerFactory { - client: service.client().clone(), - transaction_pool: service.transaction_pool().clone(), - network: consensus_net, - force_delay: 0, - handle: dummy_runtime.executor(), - }; - let (proposer, _, _) = proposer_factory.init(&parent_header, &validators, alice.clone()).unwrap(); - let block = proposer.propose().expect("Error making test block"); - BlockImportParams { - origin: BlockOrigin::File, - justification: Vec::new(), - internal_justification: Vec::new(), - finalized: true, - body: Some(block.extrinsics), - header: block.header, - auxiliary: Vec::new(), - } - }; - let extrinsic_factory = - |service: &SyncService<::FullService>| - { - let payload = ( - 0, - Call::Balances(BalancesCall::transfer(RawAddress::Id(bob.public().0.into()), 69.into())), - Era::immortal(), - service.client().genesis_hash() - ); - let signature = alice.sign(&payload.encode()).into(); - let id = alice.public().0.into(); - let xt = UncheckedExtrinsic { - signature: Some((RawAddress::Id(id), signature, payload.0, Era::immortal())), - function: payload.1, - }.encode(); - let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); - OpaqueExtrinsic(v) - }; - service_test::sync( - chain_spec::integration_test_config(), - |config| new_full(config), - |mut config| { - // light nodes are unsupported - config.roles = Roles::FULL; - new_full(config) - }, - block_factory, - extrinsic_factory, - ); - } - - #[test] - #[ignore] - fn test_sync() { - let keystore_path = tempfile::tempdir().expect("Creates keystore path"); - let keystore = keystore::Store::open(keystore_path.path(), None) - .expect("Creates keystore"); - let alice = keystore.write().insert_ephemeral_from_seed::("//Alice") - .expect("Creates authority pair"); - - let chain_spec = crate::chain_spec::tests::integration_test_config_with_single_authority(); - - // For the block factory - let mut slot_num = 1u64; - - // For the extrinsics factory - let bob = Arc::new(AccountKeyring::Bob.pair()); - let charlie = Arc::new(AccountKeyring::Charlie.pair()); - let mut index = 0; - - service_test::sync( - chain_spec, - |config| { - let mut setup_handles = None; - new_full!(config, | - block_import: &babe::BabeBlockImport<_, _, Block, _, _, _>, - babe_link: &babe::BabeLink, - | { - setup_handles = Some((block_import.clone(), babe_link.clone())); - }).map(move |(node, x)| (node, (x, setup_handles.unwrap()))) - }, - |mut config| { - // light nodes are unsupported - config.roles = Roles::FULL; - new_full(config) - }, - |service, &mut (ref inherent_data_providers, (ref mut block_import, ref babe_link))| { - let mut inherent_data = inherent_data_providers - .create_inherent_data() - .expect("Creates inherent data."); - inherent_data.replace_data(finality_tracker::INHERENT_IDENTIFIER, &1u64); - - let parent_id = BlockId::number(service.client().info().chain.best_number); - let parent_header = service.client().header(&parent_id).unwrap().unwrap(); - let mut proposer_factory = substrate_basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; - - let mut digest = Digest::::default(); - - // even though there's only one authority some slots might be empty, - // so we must keep trying the next slots until we can claim one. - let babe_pre_digest = loop { - inherent_data.replace_data(timestamp::INHERENT_IDENTIFIER, &(slot_num * SLOT_DURATION)); - if let Some(babe_pre_digest) = babe::test_helpers::claim_slot( - slot_num, - &parent_header, - &*service.client(), - &keystore, - &babe_link, - ) { - break babe_pre_digest; - } - - slot_num += 1; - }; - - digest.push(::babe_pre_digest(babe_pre_digest)); - - let mut proposer = proposer_factory.init(&parent_header).unwrap(); - let new_block = futures03::executor::block_on(proposer.propose( - inherent_data, - digest, - std::time::Duration::from_secs(1), - )).expect("Error making test block"); - - let (new_header, new_body) = new_block.deconstruct(); - let pre_hash = new_header.hash(); - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let to_sign = pre_hash.encode(); - let signature = alice.sign(&to_sign[..]); - let item = ::babe_seal( - signature.into(), - ); - slot_num += 1; - - let params = BlockImportParams { - origin: BlockOrigin::File, - header: new_header, - justification: None, - post_digests: vec![item], - body: Some(new_body), - finalized: true, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; - - block_import.import_block(params, Default::default()) - .expect("error importing test block"); - }, - |service, _| { - let amount = 5 * CENTS; - let to: Address = AccountPublic::from(bob.public()).into_account().into(); - let from: Address = AccountPublic::from(charlie.public()).into_account().into(); - let genesis_hash = service.client().block_hash(0).unwrap().unwrap(); - let best_block_id = BlockId::number(service.client().info().chain.best_number); - let version = service.client().runtime_version_at(&best_block_id).unwrap().spec_version; - let signer = charlie.clone(); - - let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); - - let check_version = system::CheckVersion::new(); - let check_genesis = system::CheckGenesis::new(); - let check_era = system::CheckEra::from(Era::Immortal); - let check_nonce = system::CheckNonce::from(index); - let check_weight = system::CheckWeight::new(); - let payment = transaction_payment::ChargeTransactionPayment::from(0); - let extra = ( - check_version, - check_genesis, - check_era, - check_nonce, - check_weight, - payment, - Default::default(), - ); - let raw_payload = SignedPayload::from_raw( - function, - extra, - (version, genesis_hash, genesis_hash, (), (), (), ()) - ); - let signature = raw_payload.using_encoded(|payload| { - signer.sign(payload) - }); - let (function, extra, _) = raw_payload.deconstruct(); - let xt = UncheckedExtrinsic::new_signed( - function, - from.into(), - signature.into(), - extra, - ).encode(); - let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); - - index += 1; - OpaqueExtrinsic(v) - }, - ); - } - - #[test] - #[ignore] - fn test_consensus() { - service_test::consensus( - crate::chain_spec::tests::integration_test_config_with_two_authorities(), - |config| new_full(config), - |mut config| { - // light nodes are unsupported - config.roles = Roles::FULL; - new_full(config) - }, - vec![ - "//Alice".into(), - "//Bob".into(), - ], - ) - } -} diff --git a/node/executor/Cargo.toml b/node/executor/Cargo.toml deleted file mode 100644 index 1908443ca9519..0000000000000 --- a/node/executor/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "node-executor" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Substrate node implementation in Rust." -edition = "2018" - -[dependencies] -trie-root = "0.15.2" -codec = { package = "parity-scale-codec", version = "1.0.0" } -runtime_io = { package = "sr-io", path = "../../core/sr-io" } -state_machine = { package = "substrate-state-machine", path = "../../core/state-machine" } -substrate-executor = { path = "../../core/executor" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -trie = { package = "substrate-trie", path = "../../core/trie" } -node-primitives = { path = "../primitives" } -node-runtime = { path = "../runtime" } - -[dev-dependencies] -node-testing = { path = "../testing" } -test-client = { package = "substrate-test-client", path = "../../core/test-client" } -sr-primitives = { path = "../../core/sr-primitives" } -runtime_support = { package = "srml-support", path = "../../srml/support" } -balances = { package = "srml-balances", path = "../../srml/balances" } -transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment" } -session = { package = "srml-session", path = "../../srml/session" } -system = { package = "srml-system", path = "../../srml/system" } -timestamp = { package = "srml-timestamp", path = "../../srml/timestamp" } -treasury = { package = "srml-treasury", path = "../../srml/treasury" } -contracts = { package = "srml-contracts", path = "../../srml/contracts" } -grandpa = { package = "srml-grandpa", path = "../../srml/grandpa" } -indices = { package = "srml-indices", path = "../../srml/indices" } -wabt = "0.9.2" - -[features] -benchmarks = [] -stress-test = [] diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs deleted file mode 100644 index 39727d1d5503e..0000000000000 --- a/node/executor/src/lib.rs +++ /dev/null @@ -1,1228 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! A `CodeExecutor` specialization which uses natively compiled runtime when the wasm to be -//! executed is equivalent to the natively compiled code. - -#![cfg_attr(feature = "benchmarks", feature(test))] - -#[cfg(feature = "benchmarks")] extern crate test; - -pub use substrate_executor::NativeExecutor; -use substrate_executor::native_executor_instance; - -// Declare an instance of the native executor named `Executor`. Include the wasm binary as the -// equivalent wasm code. -native_executor_instance!( - pub Executor, - node_runtime::api::dispatch, - node_runtime::native_version -); - -#[cfg(test)] -mod tests { - use substrate_executor::error::Result; - use super::Executor; - use {balances, contracts, indices, system, timestamp}; - use codec::{Encode, Decode, Joiner}; - use runtime_support::{Hashable, StorageValue, StorageMap, traits::Currency}; - use state_machine::TestExternalities as CoreTestExternalities; - use primitives::{ - Blake2Hasher, NeverNativeValue, NativeOrEncoded, map, - traits::{CodeExecutor, Externalities}, storage::well_known_keys, - }; - use sr_primitives::{ - Fixed64, - traits::{Header as HeaderT, Hash as HashT, Convert}, ApplyResult, - transaction_validity::InvalidTransaction, weights::GetDispatchInfo, - }; - use contracts::ContractAddressFor; - use substrate_executor::{NativeExecutor, WasmExecutionMethod}; - use system::{EventRecord, Phase}; - use node_runtime::{ - Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, - System, TransactionPayment, Event, TransferFee, TransactionBaseFee, TransactionByteFee, - WeightFeeCoefficient, constants::currency::*, - }; - use node_runtime::impls::LinearWeightToFee; - use node_primitives::{Balance, Hash, BlockNumber}; - use node_testing::keyring::*; - use wabt; - - /// The wasm runtime code. - /// - /// `compact` since it is after post-processing with wasm-gc which performs tree-shaking thus - /// making the binary slimmer. There is a convention to use compact version of the runtime - /// as canonical. This is why `native_executor_instance` also uses the compact version of the - /// runtime. - const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; - - /// The wasm runtime binary which hasn't undergone the compacting process. - /// - /// The idea here is to pass it as the current runtime code to the executor so the executor will - /// have to execute provided wasm code instead of the native equivalent. This trick is used to - /// test code paths that differ between native and wasm versions. - const BLOATY_CODE: &[u8] = node_runtime::WASM_BINARY_BLOATY; - - const GENESIS_HASH: [u8; 32] = [69u8; 32]; - - const VERSION: u32 = node_runtime::VERSION.spec_version; - - type TestExternalities = CoreTestExternalities; - - fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { - node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) - } - - /// Default transfer fee - fn transfer_fee(extrinsic: &E, fee_multiplier: Fixed64) -> Balance { - let length_fee = TransactionBaseFee::get() + - TransactionByteFee::get() * - (extrinsic.encode().len() as Balance); - - let weight = default_transfer_call().get_dispatch_info().weight; - let weight_fee = ::WeightToFee::convert(weight); - - fee_multiplier.saturated_multiply_accumulate(length_fee + weight_fee) + TransferFee::get() - } - - fn default_transfer_call() -> balances::Call { - balances::Call::transfer::(bob().into(), 69 * DOLLARS) - } - - fn xt() -> UncheckedExtrinsic { - sign(CheckedExtrinsic { - signed: Some((alice(), signed_extra(0, 0))), - function: Call::Balances(default_transfer_call()), - }) - } - - fn from_block_number(n: u32) -> Header { - Header::new(n, Default::default(), Default::default(), [69; 32].into(), Default::default()) - } - - fn executor() -> NativeExecutor { - NativeExecutor::new(WasmExecutionMethod::Interpreted, None) - } - - fn set_heap_pages(ext: &mut E, heap_pages: u64) { - ext.place_storage(well_known_keys::HEAP_PAGES.to_vec(), Some(heap_pages.encode())); - } - - fn executor_call< - R:Decode + Encode + PartialEq, - NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe - >( - t: &mut TestExternalities, - method: &str, - data: &[u8], - use_native: bool, - native_call: Option, - ) -> (Result>, bool) { - let mut t = t.ext(); - executor().call::<_, R, NC>( - &mut t, - method, - data, - use_native, - native_call, - ) - } - - #[test] - fn panic_execution_with_foreign_code_gives_error() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, (map![ - >::hashed_key_for(alice()) => { - 69_u128.encode() - }, - >::hashed_key().to_vec() => { - 69_u128.encode() - }, - >::hashed_key().to_vec() => { - 0_u128.encode() - }, - >::hashed_key_for(0) => { - vec![0u8; 32] - } - ], map![])); - - let r = executor_call:: _>( - &mut t, - "Core_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - None, - ).0; - assert!(r.is_ok()); - let v = executor_call:: _>( - &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(InvalidTransaction::Payment.into())); - } - - #[test] - fn bad_extrinsic_with_native_equivalent_code_gives_error() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, (map![ - >::hashed_key_for(alice()) => { - 69_u128.encode() - }, - >::hashed_key().to_vec() => { - 69_u128.encode() - }, - >::hashed_key().to_vec() => { - 0_u128.encode() - }, - >::hashed_key_for(0) => { - vec![0u8; 32] - } - ], map![])); - - let r = executor_call:: _>( - &mut t, - "Core_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - None, - ).0; - assert!(r.is_ok()); - let v = executor_call:: _>( - &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(InvalidTransaction::Payment.into())); - } - - #[test] - fn successful_execution_with_native_equivalent_code_gives_ok() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, (map![ - >::hashed_key_for(alice()) => { - (111 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => vec![0u8; 16], - >::hashed_key_for(0) => vec![0u8; 32] - ], map![])); - - let r = executor_call:: _>( - &mut t, - "Core_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - None, - ).0; - assert!(r.is_ok()); - - let fm = t.execute_with(TransactionPayment::next_fee_multiplier); - - let r = executor_call:: _>( - &mut t, - "BlockBuilder_apply_extrinsic", - &vec![].and(&xt()), - true, - None, - ).0; - assert!(r.is_ok()); - - t.execute_with(|| { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); - assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); - }); - } - - #[test] - fn successful_execution_with_foreign_code_gives_ok() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, (map![ - >::hashed_key_for(alice()) => { - (111 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => vec![0u8; 16], - >::hashed_key_for(0) => vec![0u8; 32] - ], map![])); - - let r = executor_call:: _>( - &mut t, - "Core_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - None, - ).0; - assert!(r.is_ok()); - - let fm = t.execute_with(TransactionPayment::next_fee_multiplier); - - let r = executor_call:: _>( - &mut t, - "BlockBuilder_apply_extrinsic", - &vec![].and(&xt()), - true, - None, - ).0; - assert!(r.is_ok()); - - t.execute_with(|| { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); - assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); - }); - } - - fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities { - let mut ext = TestExternalities::new_with_code( - code, - node_testing::genesis::config(support_changes_trie, Some(code)).build_storage().unwrap(), - ); - ext.changes_trie_storage().insert(0, GENESIS_HASH.into(), Default::default()); - ext - } - - fn construct_block( - env: &mut TestExternalities, - number: BlockNumber, - parent_hash: Hash, - extrinsics: Vec, - ) -> (Vec, Hash) { - use trie::{TrieConfiguration, trie_types::Layout}; - - // sign extrinsics. - let extrinsics = extrinsics.into_iter().map(sign).collect::>(); - - // calculate the header fields that we can. - let extrinsics_root = Layout::::ordered_trie_root( - extrinsics.iter().map(Encode::encode) - ).to_fixed_bytes() - .into(); - - let header = Header { - parent_hash, - number, - extrinsics_root, - state_root: Default::default(), - digest: Default::default(), - }; - - // execute the block to get the real header. - executor_call:: _>( - env, - "Core_initialize_block", - &header.encode(), - true, - None, - ).0.unwrap(); - - for i in extrinsics.iter() { - executor_call:: _>( - env, - "BlockBuilder_apply_extrinsic", - &i.encode(), - true, - None, - ).0.unwrap(); - } - - let header = match executor_call:: _>( - env, - "BlockBuilder_finalize_block", - &[0u8;0], - true, - None, - ).0.unwrap() { - NativeOrEncoded::Native(_) => unreachable!(), - NativeOrEncoded::Encoded(h) => Header::decode(&mut &h[..]).unwrap(), - }; - - let hash = header.blake2_256(); - (Block { header, extrinsics }.encode(), hash.into()) - } - - fn changes_trie_block() -> (Vec, Hash) { - construct_block( - &mut new_test_ext(COMPACT_CODE, true), - 1, - GENESIS_HASH.into(), - vec![ - CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(42 * 1000)), - }, - CheckedExtrinsic { - signed: Some((alice(), signed_extra(0, 0))), - function: Call::Balances(balances::Call::transfer(bob().into(), 69 * DOLLARS)), - }, - ] - ) - } - - // 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 * 1000)), - }, - CheckedExtrinsic { - signed: Some((alice(), signed_extra(0, 0))), - function: Call::Balances(balances::Call::transfer(bob().into(), 69 * DOLLARS)), - }, - ] - ); - let block2 = construct_block( - &mut t, - 2, - block1.1.clone(), - vec![ - CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(52 * 1000)), - }, - CheckedExtrinsic { - signed: Some((bob(), signed_extra(0, 0))), - function: Call::Balances(balances::Call::transfer(alice().into(), 5 * DOLLARS)), - }, - CheckedExtrinsic { - signed: Some((alice(), signed_extra(1, 0))), - function: Call::Balances(balances::Call::transfer(bob().into(), 15 * DOLLARS)), - } - ] - ); - - // session change => consensus authorities change => authorities change digest item appears - let digest = Header::decode(&mut &block2.0[..]).unwrap().digest; - assert_eq!(digest.logs().len(), 0); - - (block1, block2) - } - - fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec, Hash) { - construct_block( - &mut new_test_ext(COMPACT_CODE, false), - 1, - GENESIS_HASH.into(), - vec![ - CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(time * 1000)), - }, - CheckedExtrinsic { - signed: Some((alice(), signed_extra(nonce, 0))), - function: Call::System(system::Call::remark(vec![0; size])), - } - ] - ) - } - - #[test] - fn full_native_block_import_works() { - let mut t = new_test_ext(COMPACT_CODE, false); - - let (block1, block2) = blocks(); - - let mut alice_last_known_balance: Balance = Default::default(); - let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier); - - executor_call:: _>( - &mut t, - "Core_execute_block", - &block1.0, - true, - None, - ).0.unwrap(); - - t.execute_with(|| { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); - assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); - alice_last_known_balance = Balances::total_balance(&alice()); - let events = vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: Event::system(system::Event::ExtrinsicSuccess), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(1), - event: Event::balances(balances::RawEvent::Transfer( - alice().into(), - bob().into(), - 69 * DOLLARS, - 1 * CENTS - )), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(1), - event: Event::system(system::Event::ExtrinsicSuccess), - topics: vec![], - }, - ]; - assert_eq!(System::events(), events); - }); - - fm = t.execute_with(TransactionPayment::next_fee_multiplier); - - executor_call:: _>( - &mut t, - "Core_execute_block", - &block2.0, - true, - None, - ).0.unwrap(); - - t.execute_with(|| { - assert_eq!( - Balances::total_balance(&alice()), - alice_last_known_balance - 10 * DOLLARS - transfer_fee(&xt(), fm), - ); - assert_eq!( - Balances::total_balance(&bob()), - 179 * DOLLARS - transfer_fee(&xt(), fm), - ); - let events = vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: Event::system(system::Event::ExtrinsicSuccess), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(1), - event: Event::balances( - balances::RawEvent::Transfer( - bob().into(), - alice().into(), - 5 * DOLLARS, - 1 * CENTS, - ) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(1), - event: Event::system(system::Event::ExtrinsicSuccess), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(2), - event: Event::balances( - balances::RawEvent::Transfer( - alice().into(), - bob().into(), - 15 * DOLLARS, - 1 * CENTS, - ) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(2), - event: Event::system(system::Event::ExtrinsicSuccess), - topics: vec![], - }, - ]; - assert_eq!(System::events(), events); - }); - } - - #[test] - fn full_wasm_block_import_works() { - let mut t = new_test_ext(COMPACT_CODE, false); - - let (block1, block2) = blocks(); - - let mut alice_last_known_balance: Balance = Default::default(); - let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier); - - executor_call:: _>( - &mut t, - "Core_execute_block", - &block1.0, - false, - None, - ).0.unwrap(); - - t.execute_with(|| { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); - assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); - alice_last_known_balance = Balances::total_balance(&alice()); - }); - - fm = t.execute_with(TransactionPayment::next_fee_multiplier); - - executor_call:: _>( - &mut t, - "Core_execute_block", - &block2.0, - false, - None, - ).0.unwrap(); - - t.execute_with(|| { - assert_eq!( - Balances::total_balance(&alice()), - alice_last_known_balance - 10 * DOLLARS - transfer_fee(&xt(), fm), - ); - assert_eq!( - Balances::total_balance(&bob()), - 179 * DOLLARS - 1 * transfer_fee(&xt(), fm), - ); - }); - } - - 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" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - (func (export "deploy") - ) - (func (export "call") - (block $fail - ;; load and check the input data (which is stored in the scratch buffer). - ;; fail if the input size is not != 4 - (br_if $fail - (i32.ne - (i32.const 4) - (call $ext_scratch_size) - ) - ) - - (call $ext_scratch_read - (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) - ) - ) - - (drop - (call $ext_call - (i32.const 4) ;; Pointer to "callee" address. - (i32.const 32) ;; Length of "callee" address. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 36) ;; Pointer to the buffer with value to transfer - (i32.const 16) ;; Length of the buffer with value to transfer. - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - ) - ) - - (return) - ) - unreachable - ) - ;; Destination AccountId to transfer the funds. - ;; Represented by H256 (32 bytes long) in little endian. - (data (i32.const 4) - "\09\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" - "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" - "\00\00\00\00" - ) - ;; Amount of value to transfer. - ;; Represented by u128 (16 bytes long) in little endian. - (data (i32.const 36) - "\06\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" - "\00\00" - ) -) -"#; - - #[test] - fn deploying_wasm_contract_should_work() { - let transfer_code = wabt::wat2wasm(CODE_TRANSFER).unwrap(); - let transfer_ch = ::Hashing::hash(&transfer_code); - - let addr = ::DetermineContractAddress::contract_address_for( - &transfer_ch, - &[], - &charlie(), - ); - - let b = construct_block( - &mut new_test_ext(COMPACT_CODE, false), - 1, - GENESIS_HASH.into(), - vec![ - CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(42 * 1000)), - }, - CheckedExtrinsic { - signed: Some((charlie(), signed_extra(0, 0))), - function: Call::Contracts( - contracts::Call::put_code::(10_000, transfer_code) - ), - }, - CheckedExtrinsic { - signed: Some((charlie(), signed_extra(1, 0))), - function: Call::Contracts( - contracts::Call::instantiate::(1 * DOLLARS, 10_000, transfer_ch, Vec::new()) - ), - }, - CheckedExtrinsic { - signed: Some((charlie(), signed_extra(2, 0))), - function: Call::Contracts( - contracts::Call::call::( - indices::address::Address::Id(addr.clone()), - 10, - 10_000, - vec![0x00, 0x01, 0x02, 0x03] - ) - ), - }, - ] - ); - - let mut t = new_test_ext(COMPACT_CODE, false); - - executor_call:: _>( - &mut t, - "Core_execute_block", - &b.0, - false, - None, - ).0.unwrap(); - - t.execute_with(|| { - // Verify that the contract constructor worked well and code of TRANSFER contract is actually deployed. - assert_eq!( - &contracts::ContractInfoOf::::get(addr) - .and_then(|c| c.get_alive()) - .unwrap() - .code_hash, - &transfer_ch - ); - }); - } - - #[test] - fn wasm_big_block_import_fails() { - let mut t = new_test_ext(COMPACT_CODE, false); - - set_heap_pages(&mut t.ext(), 4); - - let result = executor_call:: _>( - &mut t, - "Core_execute_block", - &block_with_size(42, 0, 120_000).0, - false, - None, - ).0; - assert!(result.is_err()); // Err(Wasmi(Trap(Trap { kind: Host(AllocatorOutOfSpace) }))) - } - - #[test] - fn native_big_block_import_succeeds() { - let mut t = new_test_ext(COMPACT_CODE, false); - - executor_call:: _>( - &mut t, - "Core_execute_block", - &block_with_size(42, 0, 120_000).0, - true, - None, - ).0.unwrap(); - } - - #[test] - fn native_big_block_import_fails_on_fallback() { - let mut t = new_test_ext(COMPACT_CODE, false); - - assert!( - executor_call:: _>( - &mut t, - "Core_execute_block", - &block_with_size(42, 0, 120_000).0, - false, - None, - ).0.is_err() - ); - } - - #[test] - fn panic_execution_gives_error() { - let mut t = TestExternalities::::new_with_code(BLOATY_CODE, (map![ - >::hashed_key_for(alice()) => { - 0_u128.encode() - }, - >::hashed_key().to_vec() => { - 0_u128.encode() - }, - >::hashed_key().to_vec() => vec![0u8; 16], - >::hashed_key_for(0) => vec![0u8; 32] - ], map![])); - - let r = executor_call:: _>( - &mut t, - "Core_initialize_block", - &vec![].and(&from_block_number(1u32)), - false, - None, - ).0; - assert!(r.is_ok()); - let r = executor_call:: _>( - &mut t, - "BlockBuilder_apply_extrinsic", - &vec![].and(&xt()), - false, - None, - ).0.unwrap().into_encoded(); - let r = ApplyResult::decode(&mut &r[..]).unwrap(); - assert_eq!(r, Err(InvalidTransaction::Payment.into())); - } - - #[test] - fn successful_execution_gives_ok() { - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, (map![ - >::hashed_key_for(alice()) => { - (111 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => { - (111 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => vec![0u8; 16], - >::hashed_key_for(0) => vec![0u8; 32] - ], map![])); - - let r = executor_call:: _>( - &mut t, - "Core_initialize_block", - &vec![].and(&from_block_number(1u32)), - false, - None, - ).0; - assert!(r.is_ok()); - let fm = t.execute_with(TransactionPayment::next_fee_multiplier); - let r = executor_call:: _>( - &mut t, - "BlockBuilder_apply_extrinsic", - &vec![].and(&xt()), - false, - None, - ).0.unwrap().into_encoded(); - ApplyResult::decode(&mut &r[..]) - .unwrap() - .expect("Extrinsic could be applied") - .expect("Extrinsic did not fail"); - - t.execute_with(|| { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt(), fm)); - assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); - }); - } - - #[test] - fn full_native_block_import_works_with_changes_trie() { - 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_call:: _>( - &mut t, - "Core_execute_block", - &block.encode(), - true, - None, - ).0.unwrap(); - - assert!(t.ext().storage_changes_root(GENESIS_HASH.into()).unwrap().is_some()); - } - - #[test] - fn full_wasm_block_import_works_with_changes_trie() { - let block1 = changes_trie_block(); - - let mut t = new_test_ext(COMPACT_CODE, true); - executor_call:: _>( - &mut t, - "Core_execute_block", - &block1.0, - false, - None, - ).0.unwrap(); - - assert!(t.ext().storage_changes_root(GENESIS_HASH.into()).unwrap().is_some()); - } - - #[test] - fn should_import_block_with_test_client() { - use node_testing::client::{ClientExt, TestClientBuilderExt, TestClientBuilder, consensus::BlockOrigin}; - - let client = TestClientBuilder::new().build(); - let block1 = changes_trie_block(); - let block_data = block1.0; - let block = node_primitives::Block::decode(&mut &block_data[..]).unwrap(); - - client.import(BlockOrigin::Own, block).unwrap(); - } - - - #[test] - fn fee_multiplier_increases_and_decreases_on_big_weight() { - let mut t = new_test_ext(COMPACT_CODE, false); - - // initial fee multiplier must be zero - let mut prev_multiplier = Fixed64::from_parts(0); - - t.execute_with(|| { - assert_eq!(TransactionPayment::next_fee_multiplier(), prev_multiplier); - }); - - let mut tt = new_test_ext(COMPACT_CODE, false); - - // big one in terms of weight. - let block1 = construct_block( - &mut tt, - 1, - GENESIS_HASH.into(), - vec![ - CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(42 * 1000)), - }, - CheckedExtrinsic { - signed: Some((charlie(), signed_extra(0, 0))), - function: Call::System(system::Call::fill_block()), - } - ] - ); - - // small one in terms of weight. - let block2 = construct_block( - &mut tt, - 2, - block1.1.clone(), - vec![ - CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(52 * 1000)), - }, - CheckedExtrinsic { - signed: Some((charlie(), signed_extra(1, 0))), - function: Call::System(system::Call::remark(vec![0; 1])), - } - ] - ); - - println!("++ Block 1 size: {} / Block 2 size {}", block1.0.encode().len(), block2.0.encode().len()); - - // execute a big block. - executor_call:: _>( - &mut t, - "Core_execute_block", - &block1.0, - true, - None, - ).0.unwrap(); - - // weight multiplier is increased for next block. - t.execute_with(|| { - let fm = TransactionPayment::next_fee_multiplier(); - println!("After a big block: {:?} -> {:?}", prev_multiplier, fm); - assert!(fm > prev_multiplier); - prev_multiplier = fm; - }); - - // execute a big block. - executor_call:: _>( - &mut t, - "Core_execute_block", - &block2.0, - true, - None, - ).0.unwrap(); - - // weight multiplier is increased for next block. - t.execute_with(|| { - let fm = TransactionPayment::next_fee_multiplier(); - println!("After a small block: {:?} -> {:?}", prev_multiplier, fm); - assert!(fm < prev_multiplier); - }); - } - - #[test] - fn transaction_fee_is_correct_ultimate() { - // This uses the exact values of substrate-node. - // - // weight of transfer call as of now: 1_000_000 - // if weight of the cheapest weight would be 10^7, this would be 10^9, which is: - // - 1 MILLICENTS in substrate node. - // - 1 milli-dot based on current polkadot runtime. - // (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`) - let mut t = TestExternalities::::new_with_code(COMPACT_CODE, (map![ - >::hashed_key_for(alice()) => { - (100 * DOLLARS).encode() - }, - >::hashed_key_for(bob()) => { - (10 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => { - (110 * DOLLARS).encode() - }, - >::hashed_key().to_vec() => vec![0u8; 16], - >::hashed_key_for(0) => vec![0u8; 32] - ], map![])); - - let tip = 1_000_000; - let xt = sign(CheckedExtrinsic { - signed: Some((alice(), signed_extra(0, tip))), - function: Call::Balances(default_transfer_call()), - }); - - let r = executor_call:: _>( - &mut t, - "Core_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - None, - ).0; - - assert!(r.is_ok()); - let r = executor_call:: _>( - &mut t, - "BlockBuilder_apply_extrinsic", - &vec![].and(&xt.clone()), - true, - None, - ).0; - assert!(r.is_ok()); - - t.execute_with(|| { - assert_eq!(Balances::total_balance(&bob()), (10 + 69) * DOLLARS); - // Components deducted from alice's balances: - // - Weight fee - // - Length fee - // - Tip - // - Creation-fee of bob's account. - let mut balance_alice = (100 - 69) * DOLLARS; - - let length_fee = TransactionBaseFee::get() + - TransactionByteFee::get() * - (xt.clone().encode().len() as Balance); - balance_alice -= length_fee; - - let weight = default_transfer_call().get_dispatch_info().weight; - let weight_fee = LinearWeightToFee::::convert(weight); - - // we know that weight to fee multiplier is effect-less in block 1. - assert_eq!(weight_fee as Balance, MILLICENTS); - balance_alice -= weight_fee; - - balance_alice -= tip; - balance_alice -= TransferFee::get(); - - assert_eq!(Balances::total_balance(&alice()), balance_alice); - }); - } - - #[test] - #[should_panic] - #[cfg(feature = "stress-test")] - fn block_weight_capacity_report() { - // Just report how many transfer calls you could fit into a block. The number should at least - // be a few hundred (250 at the time of writing but can change over time). Runs until panic. - use node_primitives::Index; - - // execution ext. - let mut t = new_test_ext(COMPACT_CODE, false); - // setup ext. - let mut tt = new_test_ext(COMPACT_CODE, false); - - let factor = 50; - let mut time = 10; - let mut nonce: Index = 0; - let mut block_number = 1; - let mut previous_hash: Hash = GENESIS_HASH.into(); - - loop { - let num_transfers = block_number * factor; - let mut xts = (0..num_transfers).map(|i| CheckedExtrinsic { - signed: Some((charlie(), signed_extra(nonce + i as Index, 0))), - function: Call::Balances(balances::Call::transfer(bob().into(), 0)), - }).collect::>(); - - xts.insert(0, CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(time * 1000)), - }); - - // NOTE: this is super slow. Can probably be improved. - let block = construct_block( - &mut tt, - block_number, - previous_hash, - xts - ); - - let len = block.0.len(); - print!( - "++ Executing block with {} transfers. Block size = {} bytes / {} kb / {} mb", - num_transfers, - len, - len / 1024, - len / 1024 / 1024, - ); - - let r = executor_call:: _>( - &mut t, - "Core_execute_block", - &block.0, - true, - None, - ).0; - - println!(" || Result = {:?}", r); - assert!(r.is_ok()); - - previous_hash = block.1; - nonce += num_transfers; - time += 10; - block_number += 1; - } - } - - #[test] - #[should_panic] - #[cfg(feature = "stress-test")] - fn block_length_capacity_report() { - // Just report how big a block can get. Executes until panic. Should be ignored unless if - // manually inspected. The number should at least be a few megabytes (5 at the time of - // writing but can change over time). - use node_primitives::Index; - - // execution ext. - let mut t = new_test_ext(COMPACT_CODE, false); - // setup ext. - let mut tt = new_test_ext(COMPACT_CODE, false); - - let factor = 256 * 1024; - let mut time = 10; - let mut nonce: Index = 0; - let mut block_number = 1; - let mut previous_hash: Hash = GENESIS_HASH.into(); - - loop { - // NOTE: this is super slow. Can probably be improved. - let block = construct_block( - &mut tt, - block_number, - previous_hash, - vec![ - CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(time * 1000)), - }, - CheckedExtrinsic { - signed: Some((charlie(), signed_extra(nonce, 0))), - function: Call::System(system::Call::remark(vec![0u8; (block_number * factor) as usize])), - }, - ] - ); - - let len = block.0.len(); - print!( - "++ Executing block with big remark. Block size = {} bytes / {} kb / {} mb", - len, - len / 1024, - len / 1024 / 1024, - ); - - let r = executor_call:: _>( - &mut t, - "Core_execute_block", - &block.0, - true, - None, - ).0; - - println!(" || Result = {:?}", r); - assert!(r.is_ok()); - - previous_hash = block.1; - nonce += 1; - time += 10; - block_number += 1; - } - } - - #[cfg(feature = "benchmarks")] - mod benches { - use super::*; - use test::Bencher; - - #[bench] - fn wasm_execute_block(b: &mut Bencher) { - let (block1, block2) = blocks(); - - b.iter(|| { - let mut t = new_test_ext(COMPACT_CODE, false); - WasmExecutor::new().call(&mut t, "Core_execute_block", &block1.0).unwrap(); - WasmExecutor::new().call(&mut t, "Core_execute_block", &block2.0).unwrap(); - }); - } - } -} diff --git a/node/primitives/Cargo.toml b/node/primitives/Cargo.toml deleted file mode 100644 index 25725449a3a5a..0000000000000 --- a/node/primitives/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "node-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } - -[dev-dependencies] -substrate-serializer = { path = "../../core/serializer" } -pretty_assertions = "0.6.1" - -[features] -default = ["std"] -std = [ - "primitives/std", - "sr-primitives/std", -] diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs deleted file mode 100644 index b6a5ec05655c5..0000000000000 --- a/node/primitives/src/lib.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Low-level types used throughout the Substrate code. - -#![warn(missing_docs)] - -#![cfg_attr(not(feature = "std"), no_std)] - -use sr_primitives::{ - generic, traits::{Verify, BlakeTwo256, IdentifyAccount}, OpaqueExtrinsic, MultiSignature -}; - -/// An index to a block. -pub type BlockNumber = u32; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -/// The type for looking up accounts. We don't expect more than 4 billion of them. -pub type AccountIndex = u32; - -/// Balance of an account. -pub type Balance = u128; - -/// Type used for expressing timestamp. -pub type Moment = u64; - -/// Index of a transaction in the chain. -pub type Index = u32; - -/// A hash of some data used by the chain. -pub type Hash = primitives::H256; - -/// A timestamp: milliseconds since the unix epoch. -/// `u64` is enough to represent a duration of half a billion years, when the -/// time scale is milliseconds. -pub type Timestamp = u64; - -/// Digest item type. -pub type DigestItem = generic::DigestItem; -/// Header type. -pub type Header = generic::Header; -/// Block type. -pub type Block = generic::Block; -/// Block ID. -pub type BlockId = generic::BlockId; diff --git a/node/rpc-client/Cargo.toml b/node/rpc-client/Cargo.toml deleted file mode 100644 index e377f89359582..0000000000000 --- a/node/rpc-client/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "node-rpc-client" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -env_logger = "0.7.0" -futures = "0.1.29" -hyper = "0.12.35" -jsonrpc-core-client = { version = "13.1.0", features = ["http", "ws"] } -log = "0.4.8" -node-primitives = { path = "../primitives" } -substrate-rpc = { path = "../../core/rpc", version = "2.0.0" } diff --git a/node/rpc-client/src/main.rs b/node/rpc-client/src/main.rs deleted file mode 100644 index fe057bcbeaf42..0000000000000 --- a/node/rpc-client/src/main.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![warn(missing_docs)] - -//! Example substrate RPC client code. -//! -//! This module shows how you can write a Rust RPC client that connects to a running -//! substrate node and use staticly typed RPC wrappers. - -use futures::Future; -use hyper::rt; -use node_primitives::Hash; -use substrate_rpc::author::{ - AuthorClient, - hash::ExtrinsicOrHash, -}; -use jsonrpc_core_client::{ - transports::http, - RpcError, -}; - -fn main() { - env_logger::init(); - - rt::run(rt::lazy(|| { - let uri = "http://localhost:9933"; - - http::connect(uri) - .and_then(|client: AuthorClient| { - remove_all_extrinsics(client) - }) - .map_err(|e| { - println!("Error: {:?}", e); - }) - })) -} - -/// Remove all pending extrinsics from the node. -/// -/// The example code takes `AuthorClient` and first: -/// 1. Calls the `pending_extrinsics` method to get all extrinsics in the pool. -/// 2. Then calls `remove_extrinsic` passing the obtained raw extrinsics. -/// -/// As the resul of running the code the entire content of the transaction pool is going -/// to be removed and the extrinsics are going to be temporarily banned. -fn remove_all_extrinsics(client: AuthorClient) -> impl Future { - client.pending_extrinsics() - .and_then(move |pending| { - client.remove_extrinsic( - pending.into_iter().map(|tx| ExtrinsicOrHash::Extrinsic(tx.into())).collect() - ) - }) - .map(|removed| { - println!("Removed extrinsics: {:?}", removed); - }) -} diff --git a/node/rpc/Cargo.toml b/node/rpc/Cargo.toml deleted file mode 100644 index 5d2ca81e0ff84..0000000000000 --- a/node/rpc/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "node-rpc" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../../core/client" } -jsonrpc-core = "13.2.0" -node-primitives = { path = "../primitives" } -sr-primitives = { path = "../../core/sr-primitives" } -srml-contracts-rpc = { path = "../../srml/contracts/rpc/" } -srml-system-rpc = { path = "../../srml/system/rpc/" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } diff --git a/node/rpc/src/lib.rs b/node/rpc/src/lib.rs deleted file mode 100644 index 398d458e63a20..0000000000000 --- a/node/rpc/src/lib.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! A collection of node-specific RPC methods. -//! -//! Since `substrate` core functionality makes no assumptions -//! about the modules used inside the runtime, so do -//! RPC methods defined in `substrate-rpc` crate. -//! It means that `core/rpc` can't have any methods that -//! need some strong assumptions about the particular runtime. -//! -//! The RPCs available in this crate however can make some assumptions -//! about how the runtime is constructed and what `SRML` modules -//! are part of it. Therefore all node-runtime-specific RPCs can -//! be placed here or imported from corresponding `SRML` RPC definitions. - -#![warn(missing_docs)] - -use std::sync::Arc; - -use node_primitives::{Block, AccountId, Index, Balance}; -use sr_primitives::traits::ProvideRuntimeApi; -use transaction_pool::txpool::{ChainApi, Pool}; - -/// Instantiate all RPC extensions. -pub fn create(client: Arc, pool: Arc>) -> jsonrpc_core::IoHandler where - C: ProvideRuntimeApi, - C: client::blockchain::HeaderBackend, - C: Send + Sync + 'static, - C::Api: srml_system_rpc::AccountNonceApi, - C::Api: srml_contracts_rpc::ContractsRuntimeApi, - P: ChainApi + Sync + Send + 'static, - M: jsonrpc_core::Metadata + Default, -{ - use srml_system_rpc::{System, SystemApi}; - use srml_contracts_rpc::{Contracts, ContractsApi}; - - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with( - SystemApi::to_delegate(System::new(client.clone(), pool)) - ); - io.extend_with( - ContractsApi::to_delegate(Contracts::new(client)) - ); - io -} diff --git a/node/runtime/Cargo.toml b/node/runtime/Cargo.toml deleted file mode 100644 index 9169f26dc376a..0000000000000 --- a/node/runtime/Cargo.toml +++ /dev/null @@ -1,111 +0,0 @@ -[package] -name = "node-runtime" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -build = "build.rs" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -integer-sqrt = { version = "0.1.2" } -rustc-hex = { version = "2.0", optional = true } -safe-mix = { version = "1.0", default-features = false } -serde = { version = "1.0.101", optional = true } - -authority-discovery-primitives = { package = "substrate-authority-discovery-primitives", path = "../../core/authority-discovery/primitives", default-features = false } -babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false } -client = { package = "substrate-client", path = "../../core/client", default-features = false } -node-primitives = { path = "../primitives", default-features = false } -offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } -substrate-keyring = { path = "../../core/keyring", optional = true } -substrate-session = { path = "../../core/session", default-features = false } -version = { package = "sr-version", path = "../../core/sr-version", default-features = false } - -authority-discovery = { package = "srml-authority-discovery", path = "../../srml/authority-discovery", default-features = false } -authorship = { package = "srml-authorship", path = "../../srml/authorship", default-features = false } -babe = { package = "srml-babe", path = "../../srml/babe", default-features = false } -balances = { package = "srml-balances", path = "../../srml/balances", default-features = false } -collective = { package = "srml-collective", path = "../../srml/collective", default-features = false } -contracts = { package = "srml-contracts", path = "../../srml/contracts", default-features = false } -contracts-rpc-runtime-api = { package = "srml-contracts-rpc-runtime-api", path = "../../srml/contracts/rpc/runtime-api/", default-features = false } -democracy = { package = "srml-democracy", path = "../../srml/democracy", default-features = false } -elections-phragmen = { package = "srml-elections-phragmen", path = "../../srml/elections-phragmen", default-features = false } -executive = { package = "srml-executive", path = "../../srml/executive", default-features = false } -finality-tracker = { package = "srml-finality-tracker", path = "../../srml/finality-tracker", default-features = false } -grandpa = { package = "srml-grandpa", path = "../../srml/grandpa", default-features = false } -im-online = { package = "srml-im-online", path = "../../srml/im-online", default-features = false } -indices = { package = "srml-indices", path = "../../srml/indices", default-features = false } -membership = { package = "srml-membership", path = "../../srml/membership", default-features = false } -nicks = { package = "srml-nicks", path = "../../srml/nicks", default-features = false } -offences = { package = "srml-offences", path = "../../srml/offences", default-features = false } -randomness-collective-flip = { package = "srml-randomness-collective-flip", path = "../../srml/randomness-collective-flip", default-features = false } -session = { package = "srml-session", path = "../../srml/session", default-features = false, features = ["historical"] } -staking = { package = "srml-staking", path = "../../srml/staking", default-features = false } -srml-staking-reward-curve = { path = "../../srml/staking/reward-curve"} -sudo = { package = "srml-sudo", path = "../../srml/sudo", default-features = false } -support = { package = "srml-support", path = "../../srml/support", default-features = false } -system = { package = "srml-system", path = "../../srml/system", default-features = false } -system-rpc-runtime-api = { package = "srml-system-rpc-runtime-api", path = "../../srml/system/rpc/runtime-api/", default-features = false } -timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default-features = false } -treasury = { package = "srml-treasury", path = "../../srml/treasury", default-features = false } -utility = { package = "srml-utility", path = "../../srml/utility", default-features = false } -transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment", default-features = false } - -[build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.4", path = "../../core/utils/wasm-builder-runner" } - -[dev-dependencies] -runtime_io = { package = "sr-io", path = "../../core/sr-io" } - -[features] -default = ["std"] -std = [ - "authority-discovery-primitives/std", - "authority-discovery/std", - "authorship/std", - "babe-primitives/std", - "babe/std", - "balances/std", - "client/std", - "codec/std", - "collective/std", - "contracts/std", - "contracts-rpc-runtime-api/std", - "democracy/std", - "elections-phragmen/std", - "executive/std", - "finality-tracker/std", - "grandpa/std", - "im-online/std", - "indices/std", - "membership/std", - "nicks/std", - "node-primitives/std", - "offchain-primitives/std", - "offences/std", - "primitives/std", - "randomness-collective-flip/std", - "rstd/std", - "rustc-hex", - "safe-mix/std", - "serde", - "session/std", - "sr-primitives/std", - "sr-staking-primitives/std", - "staking/std", - "substrate-keyring", - "substrate-session/std", - "sudo/std", - "support/std", - "system/std", - "system-rpc-runtime-api/std", - "timestamp/std", - "treasury/std", - "utility/std", - "transaction-payment/std", - "version/std", -] diff --git a/node/runtime/build.rs b/node/runtime/build.rs deleted file mode 100644 index f5c2f98a75c8a..0000000000000 --- a/node/runtime/build.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; - -fn main() { - build_current_project_with_rustflags( - "wasm_binary.rs", - WasmBuilderSource::CratesOrPath { - path: "../../core/utils/wasm-builder", - version: "1.0.8", - }, - // This instructs LLD to export __heap_base as a global variable, which is used by the - // external memory allocator. - "-Clink-arg=--export=__heap_base", - ); -} diff --git a/node/runtime/src/impls.rs b/node/runtime/src/impls.rs deleted file mode 100644 index 2e9bd38c8f822..0000000000000 --- a/node/runtime/src/impls.rs +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Some configurable implementations as associated type for the substrate runtime. - -use node_primitives::Balance; -use sr_primitives::weights::Weight; -use sr_primitives::traits::{Convert, Saturating}; -use sr_primitives::{Fixed64, Perbill}; -use support::traits::{OnUnbalanced, Currency, Get}; -use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance}; - -pub struct Author; -impl OnUnbalanced for Author { - fn on_unbalanced(amount: NegativeImbalance) { - Balances::resolve_creating(&Authorship::author(), amount); - } -} - -/// Struct that handles the conversion of Balance -> `u64`. This is used for staking's election -/// calculation. -pub struct CurrencyToVoteHandler; - -impl CurrencyToVoteHandler { - fn factor() -> Balance { (Balances::total_issuance() / u64::max_value() as Balance).max(1) } -} - -impl Convert for CurrencyToVoteHandler { - fn convert(x: Balance) -> u64 { (x / Self::factor()) as u64 } -} - -impl Convert for CurrencyToVoteHandler { - fn convert(x: u128) -> Balance { x * Self::factor() } -} - -/// Convert from weight to balance via a simple coefficient multiplication -/// The associated type C encapsulates a constant in units of balance per weight -pub struct LinearWeightToFee(rstd::marker::PhantomData); - -impl> Convert for LinearWeightToFee { - fn convert(w: Weight) -> Balance { - // substrate-node a weight of 10_000 (smallest non-zero weight) to be mapped to 10^7 units of - // fees, hence: - let coefficient = C::get(); - Balance::from(w).saturating_mul(coefficient) - } -} - -/// Update the given multiplier based on the following formula -/// -/// diff = (target_weight - previous_block_weight) -/// v = 0.00004 -/// next_weight = weight * (1 + (v . diff) + (v . diff)^2 / 2) -/// -/// Where `target_weight` must be given as the `Get` implementation of the `T` generic type. -/// https://research.web3.foundation/en/latest/polkadot/Token%20Economics/#relay-chain-transaction-fees -pub struct TargetedFeeAdjustment(rstd::marker::PhantomData); - -impl> Convert for TargetedFeeAdjustment { - fn convert(multiplier: Fixed64) -> Fixed64 { - let block_weight = System::all_extrinsics_weight(); - let max_weight = MaximumBlockWeight::get(); - let target_weight = (T::get() * max_weight) as u128; - let block_weight = block_weight as u128; - - // determines if the first_term is positive - let positive = block_weight >= target_weight; - let diff_abs = block_weight.max(target_weight) - block_weight.min(target_weight); - // diff is within u32, safe. - let diff = Fixed64::from_rational(diff_abs as i64, max_weight as u64); - let diff_squared = diff.saturating_mul(diff); - - // 0.00004 = 4/100_000 = 40_000/10^9 - let v = Fixed64::from_rational(4, 100_000); - // 0.00004^2 = 16/10^10 ~= 2/10^9. Taking the future /2 into account, then it is just 1 - // parts from a billionth. - let v_squared_2 = Fixed64::from_rational(1, 1_000_000_000); - - let first_term = v.saturating_mul(diff); - // It is very unlikely that this will exist (in our poor perbill estimate) but we are giving - // it a shot. - let second_term = v_squared_2.saturating_mul(diff_squared); - - if positive { - // Note: this is merely bounded by how big the multiplier and the inner value can go, - // not by any economical reasoning. - let excess = first_term.saturating_add(second_term); - multiplier.saturating_add(excess) - } else { - // Proof: first_term > second_term. Safe subtraction. - let negative = first_term - second_term; - multiplier.saturating_sub(negative) - // despite the fact that apply_to saturates weight (final fee cannot go below 0) - // it is crucially important to stop here and don't further reduce the weight fee - // multiplier. While at -1, it means that the network is so un-congested that all - // transactions have no weight fee. We stop here and only increase if the network - // became more busy. - .max(Fixed64::from_rational(-1, 1)) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sr_primitives::weights::Weight; - use sr_primitives::assert_eq_error_rate; - use crate::{MaximumBlockWeight, AvailableBlockRatio, Runtime}; - use crate::{constants::currency::*, TransactionPayment, TargetBlockFullness}; - - fn max() -> Weight { - MaximumBlockWeight::get() - } - - fn target() -> Weight { - TargetBlockFullness::get() * max() - } - - // poc reference implementation. - fn fee_multiplier_update(block_weight: Weight, previous: Fixed64) -> Fixed64 { - let block_weight = block_weight as f32; - let v: f32 = 0.00004; - - // maximum tx weight - let m = max() as f32; - // Ideal saturation in terms of weight - let ss = target() as f32; - // Current saturation in terms of weight - let s = block_weight; - - let fm = v * (s/m - ss/m) + v.powi(2) * (s/m - ss/m).powi(2) / 2.0; - let addition_fm = Fixed64::from_parts((fm * 1_000_000_000_f32).round() as i64); - previous.saturating_add(addition_fm) - } - - fn feemul(parts: i64) -> Fixed64 { - Fixed64::from_parts(parts) - } - - fn run_with_system_weight(w: Weight, assertions: F) where F: Fn() -> () { - let mut t: runtime_io::TestExternalities = - system::GenesisConfig::default().build_storage::().unwrap().into(); - t.execute_with(|| { - System::set_block_limits(w, 0); - assertions() - }); - } - - #[test] - fn fee_multiplier_update_poc_works() { - let fm = Fixed64::from_rational(0, 1); - let test_set = vec![ - (0, fm.clone()), - (100, fm.clone()), - (target(), fm.clone()), - (max() / 2, fm.clone()), - (max(), fm.clone()), - ]; - test_set.into_iter().for_each(|(w, fm)| { - run_with_system_weight(w, || { - assert_eq_error_rate!( - fee_multiplier_update(w, fm).into_inner(), - TargetedFeeAdjustment::::convert(fm).into_inner(), - 5, - ); - }) - }) - } - - #[test] - fn empty_chain_simulation() { - // just a few txs per_block. - let block_weight = 0; - run_with_system_weight(block_weight, || { - let mut fm = Fixed64::default(); - let mut iterations: u64 = 0; - loop { - let next = TargetedFeeAdjustment::::convert(fm); - fm = next; - if fm == Fixed64::from_rational(-1, 1) { break; } - iterations += 1; - } - println!("iteration {}, new fm = {:?}. Weight fee is now zero", iterations, fm); - assert!(iterations > 50_000, "This assertion is just a warning; Don't panic. \ - Current substrate/polkadot node are configured with a _slow adjusting fee_ \ - mechanism. Hence, it is really unlikely that fees collapse to zero even on an \ - empty chain in less than at least of couple of thousands of empty blocks. But this \ - simulation indicates that fees collapsed to zero after {} almost-empty blocks. \ - Check it", - iterations, - ); - }) - } - - #[test] - #[ignore] - fn congested_chain_simulation() { - // `cargo test congested_chain_simulation -- --nocapture` to get some insight. - - // almost full. The entire quota of normal transactions is taken. - let block_weight = AvailableBlockRatio::get() * max() - 100; - - // Default substrate minimum. - let tx_weight = 10_000; - - run_with_system_weight(block_weight, || { - // initial value configured on module - let mut fm = Fixed64::default(); - assert_eq!(fm, TransactionPayment::next_fee_multiplier()); - - let mut iterations: u64 = 0; - loop { - let next = TargetedFeeAdjustment::::convert(fm); - // if no change, panic. This should never happen in this case. - if fm == next { panic!("The fee should ever increase"); } - fm = next; - iterations += 1; - let fee = ::WeightToFee::convert(tx_weight); - let adjusted_fee = fm.saturated_multiply_accumulate(fee); - println!( - "iteration {}, new fm = {:?}. Fee at this point is: {} units / {} millicents, \ - {} cents, {} dollars", - iterations, - fm, - adjusted_fee, - adjusted_fee / MILLICENTS, - adjusted_fee / CENTS, - adjusted_fee / DOLLARS, - ); - } - }); - } - - #[test] - fn stateless_weight_mul() { - run_with_system_weight(target() / 4, || { - // Light block. Fee is reduced a little. - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(-7500), - ); - }); - run_with_system_weight(target() / 2, || { - // a bit more. Fee is decreased less, meaning that the fee increases as the block grows. - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(-5000), - ); - - }); - run_with_system_weight(target(), || { - // ideal. Original fee. No changes. - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(0), - ); - }); - run_with_system_weight(target() * 2, || { - // // More than ideal. Fee is increased. - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(10000), - ); - }); - } - - #[test] - fn stateful_weight_mul_grow_to_infinity() { - run_with_system_weight(target() * 2, || { - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(10000) - ); - assert_eq!( - TargetedFeeAdjustment::::convert(feemul(10000)), - feemul(20000) - ); - assert_eq!( - TargetedFeeAdjustment::::convert(feemul(20000)), - feemul(30000) - ); - // ... - assert_eq!( - TargetedFeeAdjustment::::convert(feemul(1_000_000_000)), - feemul(1_000_000_000 + 10000) - ); - }); - } - - #[test] - fn stateful_weight_mil_collapse_to_minus_one() { - run_with_system_weight(0, || { - assert_eq!( - TargetedFeeAdjustment::::convert(Fixed64::default()), - feemul(-10000) - ); - assert_eq!( - TargetedFeeAdjustment::::convert(feemul(-10000)), - feemul(-20000) - ); - assert_eq!( - TargetedFeeAdjustment::::convert(feemul(-20000)), - feemul(-30000) - ); - // ... - assert_eq!( - TargetedFeeAdjustment::::convert(feemul(1_000_000_000 * -1)), - feemul(-1_000_000_000) - ); - }) - } - - #[test] - fn weight_to_fee_should_not_overflow_on_large_weights() { - let kb = 1024 as Weight; - let mb = kb * kb; - let max_fm = Fixed64::from_natural(i64::max_value()); - - // check that for all values it can compute, correctly. - vec![ - 0, - 1, - 10, - 1000, - kb, - 10 * kb, - 100 * kb, - mb, - 10 * mb, - Weight::max_value() / 2, - Weight::max_value() - ].into_iter().for_each(|i| { - run_with_system_weight(i, || { - let next = TargetedFeeAdjustment::::convert(Fixed64::default()); - let truth = fee_multiplier_update(i, Fixed64::default()); - assert_eq_error_rate!(truth.into_inner(), next.into_inner(), 5); - }); - }); - - // Some values that are all above the target and will cause an increase. - let t = target(); - vec![t + 100, t * 2, t * 4] - .into_iter() - .for_each(|i| { - run_with_system_weight(i, || { - let fm = TargetedFeeAdjustment::::convert(max_fm); - // won't grow. The convert saturates everything. - assert_eq!(fm, max_fm); - }) - }); - } -} diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs deleted file mode 100644 index d81ed2ebbdbc1..0000000000000 --- a/node/runtime/src/lib.rs +++ /dev/null @@ -1,738 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! The Substrate runtime. This can be compiled with ``#[no_std]`, ready for Wasm. - -#![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit="256"] - -use rstd::prelude::*; -use support::{ - construct_runtime, parameter_types, traits::{SplitTwoWays, Currency, Randomness} -}; -use primitives::u32_trait::{_1, _2, _3, _4}; -use node_primitives::{ - AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, - Moment, Signature, -}; -use babe_primitives::{AuthorityId as BabeId, AuthoritySignature as BabeSignature}; -use grandpa::fg_primitives; -use client::{ - block_builder::api::{self as block_builder_api, InherentData, CheckInherentsResult}, - runtime_api as client_api, impl_runtime_apis -}; -use sr_primitives::{ - Permill, Perbill, ApplyResult, impl_opaque_keys, generic, create_runtime_str, key_types -}; -use sr_primitives::curve::PiecewiseLinear; -use sr_primitives::transaction_validity::TransactionValidity; -use sr_primitives::weights::Weight; -use sr_primitives::traits::{ - self, BlakeTwo256, Block as BlockT, NumberFor, StaticLookup, SaturatedConversion, -}; -use version::RuntimeVersion; -#[cfg(any(feature = "std", test))] -use version::NativeVersion; -use primitives::OpaqueMetadata; -use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight}; -use im_online::sr25519::{AuthorityId as ImOnlineId}; -use authority_discovery_primitives::{AuthorityId as EncodedAuthorityId, Signature as EncodedSignature}; -use codec::{Encode, Decode}; -use system::offchain::TransactionSubmitter; - -#[cfg(any(feature = "std", test))] -pub use sr_primitives::BuildStorage; -pub use timestamp::Call as TimestampCall; -pub use balances::Call as BalancesCall; -pub use contracts::Gas; -pub use support::StorageValue; -pub use staking::StakerStatus; - -/// Implementations of some helper traits passed into runtime modules as associated types. -pub mod impls; -use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustment}; - -/// Constant values used within the runtime. -pub mod constants; -use constants::{time::*, currency::*}; - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -/// Runtime version. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("node"), - impl_name: create_runtime_str!("substrate-node"), - authoring_version: 10, - // Per convention: if the runtime behavior changes, increment spec_version - // and set impl_version to equal spec_version. If only runtime - // implementation changes and behavior does not, then leave spec_version as - // is and increment impl_version. - spec_version: 188, - impl_version: 188, - apis: RUNTIME_API_VERSIONS, -}; - -/// Native version. -#[cfg(any(feature = "std", test))] -pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } -} - -type NegativeImbalance = >::NegativeImbalance; - -pub type DealWithFees = SplitTwoWays< - Balance, - NegativeImbalance, - _4, Treasury, // 4 parts (80%) goes to the treasury. - _1, Author, // 1 part (20%) goes to the block author. ->; - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 1_000_000_000; - pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; - pub const Version: RuntimeVersion = VERSION; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); -} - -impl system::Trait for Runtime { - type Origin = Origin; - type Call = Call; - type Index = Index; - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = Indices; - type Header = generic::Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = Version; -} - -impl utility::Trait for Runtime { - type Event = Event; - type Call = Call; -} - -parameter_types! { - pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS; - pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK; -} - -impl babe::Trait for Runtime { - type EpochDuration = EpochDuration; - type ExpectedBlockTime = ExpectedBlockTime; - type EpochChangeTrigger = babe::ExternalTrigger; -} - -impl indices::Trait for Runtime { - type AccountIndex = AccountIndex; - type IsDeadAccount = Balances; - type ResolveHint = indices::SimpleResolveHint; - type Event = Event; -} - -parameter_types! { - pub const ExistentialDeposit: Balance = 1 * DOLLARS; - pub const TransferFee: Balance = 1 * CENTS; - pub const CreationFee: Balance = 1 * CENTS; -} - -impl balances::Trait for Runtime { - type Balance = Balance; - type OnFreeBalanceZero = ((Staking, Contracts), Session); - type OnNewAccount = Indices; - type Event = Event; - type DustRemoval = (); - type TransferPayment = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} - -parameter_types! { - pub const TransactionBaseFee: Balance = 1 * CENTS; - pub const TransactionByteFee: Balance = 10 * MILLICENTS; - // setting this to zero will disable the weight fee. - pub const WeightFeeCoefficient: Balance = 1_000; - // for a sane configuration, this should always be less than `AvailableBlockRatio`. - pub const TargetBlockFullness: Perbill = Perbill::from_percent(25); -} - -impl transaction_payment::Trait for Runtime { - type Currency = Balances; - type OnTransactionPayment = DealWithFees; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = LinearWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -parameter_types! { - pub const MinimumPeriod: Moment = SLOT_DURATION / 2; -} -impl timestamp::Trait for Runtime { - type Moment = Moment; - type OnTimestampSet = Babe; - type MinimumPeriod = MinimumPeriod; -} - -parameter_types! { - pub const UncleGenerations: BlockNumber = 5; -} - -impl authorship::Trait for Runtime { - type FindAuthor = session::FindAccountFromAuthorIndex; - type UncleGenerations = UncleGenerations; - type FilterUncle = (); - type EventHandler = Staking; -} - -type SessionHandlers = (Grandpa, Babe, ImOnline, AuthorityDiscovery); - -impl_opaque_keys! { - pub struct SessionKeys { - #[id(key_types::GRANDPA)] - pub grandpa: GrandpaId, - #[id(key_types::BABE)] - pub babe: BabeId, - #[id(key_types::IM_ONLINE)] - pub im_online: ImOnlineId, - } -} - -// NOTE: `SessionHandler` and `SessionKeys` are co-dependent: One key will be used for each handler. -// The number and order of items in `SessionHandler` *MUST* be the same number and order of keys in -// `SessionKeys`. -// TODO: Introduce some structure to tie these together to make it a bit less of a footgun. This -// should be easy, since OneSessionHandler trait provides the `Key` as an associated type. #2858 -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); -} - -impl session::Trait for Runtime { - type OnSessionEnding = Staking; - type SessionHandler = SessionHandlers; - type ShouldEndSession = Babe; - type Event = Event; - type Keys = SessionKeys; - type ValidatorId = ::AccountId; - type ValidatorIdOf = staking::StashOf; - type SelectInitialValidators = Staking; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; -} - -impl session::historical::Trait for Runtime { - type FullIdentification = staking::Exposure; - type FullIdentificationOf = staking::ExposureOf; -} - -srml_staking_reward_curve::build! { - const REWARD_CURVE: PiecewiseLinear<'static> = curve!( - min_inflation: 0_025_000, - max_inflation: 0_100_000, - ideal_stake: 0_500_000, - falloff: 0_050_000, - max_piece_count: 40, - test_precision: 0_005_000, - ); -} - -parameter_types! { - pub const SessionsPerEra: sr_staking_primitives::SessionIndex = 6; - pub const BondingDuration: staking::EraIndex = 24 * 28; - pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; -} - -impl staking::Trait for Runtime { - type Currency = Balances; - type Time = Timestamp; - type CurrencyToVote = CurrencyToVoteHandler; - type OnRewardMinted = Treasury; - type Event = Event; - type Slash = Treasury; // send the slashed funds to the treasury. - type Reward = (); // rewards are minted from the void - type SessionsPerEra = SessionsPerEra; - type BondingDuration = BondingDuration; - type SessionInterface = Self; - type RewardCurve = RewardCurve; -} - -parameter_types! { - pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; - pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; - pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES; - pub const MinimumDeposit: Balance = 100 * DOLLARS; - pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; - pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; -} - -impl democracy::Trait for Runtime { - type Proposal = Call; - type Event = Event; - type Currency = Balances; - type EnactmentPeriod = EnactmentPeriod; - type LaunchPeriod = LaunchPeriod; - type VotingPeriod = VotingPeriod; - type EmergencyVotingPeriod = EmergencyVotingPeriod; - type MinimumDeposit = MinimumDeposit; - /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>; - /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; - /// A unanimous council can have the next scheduled referendum be a straight default-carries - /// (NTB) vote. - type ExternalDefaultOrigin = collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>; - /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote - /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>; - // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>; - // Any single technical committee member may veto a coming council proposal, however they can - // only do it once and it lasts only for the cooloff period. - type VetoOrigin = collective::EnsureMember; - type CooloffPeriod = CooloffPeriod; -} - -type CouncilCollective = collective::Instance1; -impl collective::Trait for Runtime { - type Origin = Origin; - type Proposal = Call; - type Event = Event; -} - -parameter_types! { - pub const CandidacyBond: Balance = 10 * DOLLARS; - pub const VotingBond: Balance = 1 * DOLLARS; -} - -impl elections_phragmen::Trait for Runtime { - type Event = Event; - type Currency = Balances; - type CurrencyToVote = CurrencyToVoteHandler; - type CandidacyBond = CandidacyBond; - type VotingBond = VotingBond; - type LoserCandidate = (); - type BadReport = (); - type KickedMember = (); - type ChangeMembers = Council; -} - -type TechnicalCollective = collective::Instance2; -impl collective::Trait for Runtime { - type Origin = Origin; - type Proposal = Call; - type Event = Event; -} - -impl membership::Trait for Runtime { - type Event = Event; - type AddOrigin = collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type RemoveOrigin = collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type SwapOrigin = collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type ResetOrigin = collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type MembershipInitialized = TechnicalCommittee; - type MembershipChanged = TechnicalCommittee; -} - -parameter_types! { - pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: Balance = 1 * DOLLARS; - pub const SpendPeriod: BlockNumber = 1 * DAYS; - pub const Burn: Permill = Permill::from_percent(50); -} - -impl treasury::Trait for Runtime { - type Currency = Balances; - type ApproveOrigin = collective::EnsureMembers<_4, AccountId, CouncilCollective>; - type RejectOrigin = collective::EnsureMembers<_2, AccountId, CouncilCollective>; - type Event = Event; - type ProposalRejection = (); - type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; - type SpendPeriod = SpendPeriod; - type Burn = Burn; -} - -parameter_types! { - pub const ContractTransferFee: Balance = 1 * CENTS; - pub const ContractCreationFee: Balance = 1 * CENTS; - pub const ContractTransactionBaseFee: Balance = 1 * CENTS; - pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS; - pub const ContractFee: Balance = 1 * CENTS; - pub const TombstoneDeposit: Balance = 1 * DOLLARS; - pub const RentByteFee: Balance = 1 * DOLLARS; - pub const RentDepositOffset: Balance = 1000 * DOLLARS; - pub const SurchargeReward: Balance = 150 * DOLLARS; -} - -impl contracts::Trait for Runtime { - type Currency = Balances; - type Time = Timestamp; - type Randomness = RandomnessCollectiveFlip; - type Call = Call; - type Event = Event; - type DetermineContractAddress = contracts::SimpleAddressDeterminator; - type ComputeDispatchFee = contracts::DefaultDispatchFeeComputor; - type TrieIdGenerator = contracts::TrieIdFromParentCounter; - type GasPayment = (); - type RentPayment = (); - type SignedClaimHandicap = contracts::DefaultSignedClaimHandicap; - type TombstoneDeposit = TombstoneDeposit; - type StorageSizeOffset = contracts::DefaultStorageSizeOffset; - type RentByteFee = RentByteFee; - type RentDepositOffset = RentDepositOffset; - type SurchargeReward = SurchargeReward; - type TransferFee = ContractTransferFee; - type CreationFee = ContractCreationFee; - type TransactionBaseFee = ContractTransactionBaseFee; - type TransactionByteFee = ContractTransactionByteFee; - type ContractFee = ContractFee; - type CallBaseFee = contracts::DefaultCallBaseFee; - type InstantiateBaseFee = contracts::DefaultInstantiateBaseFee; - type MaxDepth = contracts::DefaultMaxDepth; - type MaxValueSize = contracts::DefaultMaxValueSize; - type BlockGasLimit = contracts::DefaultBlockGasLimit; -} - -impl sudo::Trait for Runtime { - type Event = Event; - type Proposal = Call; -} - -type SubmitTransaction = TransactionSubmitter; - -impl im_online::Trait for Runtime { - type AuthorityId = ImOnlineId; - type Call = Call; - type Event = Event; - type SubmitTransaction = SubmitTransaction; - type ReportUnresponsiveness = Offences; -} - -impl offences::Trait for Runtime { - type Event = Event; - type IdentificationTuple = session::historical::IdentificationTuple; - type OnOffenceHandler = Staking; -} - -impl authority_discovery::Trait for Runtime { - type AuthorityId = BabeId; -} - -impl grandpa::Trait for Runtime { - type Event = Event; -} - -parameter_types! { - pub const WindowSize: BlockNumber = 101; - pub const ReportLatency: BlockNumber = 1000; -} - -impl finality_tracker::Trait for Runtime { - type OnFinalizationStalled = Grandpa; - type WindowSize = WindowSize; - type ReportLatency = ReportLatency; -} - -parameter_types! { - pub const ReservationFee: Balance = 1 * DOLLARS; - pub const MinLength: usize = 3; - pub const MaxLength: usize = 16; -} - -impl nicks::Trait for Runtime { - type Event = Event; - type Currency = Balances; - type ReservationFee = ReservationFee; - type Slashed = Treasury; - type ForceOrigin = collective::EnsureMember; - type MinLength = MinLength; - type MaxLength = MaxLength; -} - -impl system::offchain::CreateTransaction for Runtime { - type Public = ::Signer; - type Signature = Signature; - - fn create_transaction>( - call: Call, - public: Self::Public, - account: AccountId, - index: Index, - ) -> Option<(Call, ::SignaturePayload)> { - let period = 1 << 8; - let current_block = System::block_number().saturated_into::(); - let tip = 0; - let extra: SignedExtra = ( - system::CheckVersion::::new(), - system::CheckGenesis::::new(), - system::CheckEra::::from(generic::Era::mortal(period, current_block)), - system::CheckNonce::::from(index), - system::CheckWeight::::new(), - transaction_payment::ChargeTransactionPayment::::from(tip), - Default::default(), - ); - let raw_payload = SignedPayload::new(call, extra).ok()?; - let signature = F::sign(public, &raw_payload)?; - let address = Indices::unlookup(account); - let (call, extra, _) = raw_payload.deconstruct(); - Some((call, (address, signature, extra))) - } -} - -construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = node_primitives::Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Module, Call, Storage, Config, Event}, - Utility: utility::{Module, Call, Event}, - Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)}, - Timestamp: timestamp::{Module, Call, Storage, Inherent}, - Authorship: authorship::{Module, Call, Storage, Inherent}, - Indices: indices, - Balances: balances::{default, Error}, - TransactionPayment: transaction_payment::{Module, Storage}, - Staking: staking::{default, OfflineWorker}, - Session: session::{Module, Call, Storage, Event, Config}, - Democracy: democracy::{Module, Call, Storage, Config, Event}, - Council: collective::::{Module, Call, Storage, Origin, Event, Config}, - TechnicalCommittee: collective::::{Module, Call, Storage, Origin, Event, Config}, - Elections: elections_phragmen::{Module, Call, Storage, Event, Config}, - TechnicalMembership: membership::::{Module, Call, Storage, Event, Config}, - FinalityTracker: finality_tracker::{Module, Call, Inherent}, - Grandpa: grandpa::{Module, Call, Storage, Config, Event}, - Treasury: treasury::{Module, Call, Storage, Config, Event}, - Contracts: contracts, - Sudo: sudo, - ImOnline: im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, - AuthorityDiscovery: authority_discovery::{Module, Call, Config}, - Offences: offences::{Module, Call, Storage, Event}, - RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage}, - Nicks: nicks::{Module, Call, Storage, Event}, - } -); - -/// The address format for describing accounts. -pub type Address = ::Source; -/// Block header type as expected by this runtime. -pub type Header = generic::Header; -/// Block type as expected by this runtime. -pub type Block = generic::Block; -/// A Block signed with a Justification -pub type SignedBlock = generic::SignedBlock; -/// BlockId type as expected by this runtime. -pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( - system::CheckVersion, - system::CheckGenesis, - system::CheckEra, - system::CheckNonce, - system::CheckWeight, - transaction_payment::ChargeTransactionPayment, - contracts::CheckBlockGasLimit, -); -/// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; -/// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; -/// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; -/// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive, Runtime, AllModules>; - -impl_runtime_apis! { - impl client_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block) - } - - fn initialize_block(header: &::Header) { - Executive::initialize_block(header) - } - } - - impl client_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 finalize_block() -> ::Header { - Executive::finalize_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 { - RandomnessCollectiveFlip::random_seed() - } - } - - impl client_api::TaggedTransactionQueue for Runtime { - fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { - Executive::validate_transaction(tx) - } - } - - impl offchain_primitives::OffchainWorkerApi for Runtime { - fn offchain_worker(number: NumberFor) { - Executive::offchain_worker(number) - } - } - - impl fg_primitives::GrandpaApi for Runtime { - fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> { - Grandpa::grandpa_authorities() - } - } - - impl babe_primitives::BabeApi for Runtime { - fn configuration() -> babe_primitives::BabeConfiguration { - // The choice of `c` parameter (where `1 - c` represents the - // probability of a slot being empty), is done in accordance to the - // slot duration and expected target block time, for safely - // resisting network delays of maximum two seconds. - // - babe_primitives::BabeConfiguration { - slot_duration: Babe::slot_duration(), - epoch_length: EpochDuration::get(), - c: PRIMARY_PROBABILITY, - genesis_authorities: Babe::authorities(), - randomness: Babe::randomness(), - secondary_slots: true, - } - } - } - - impl authority_discovery_primitives::AuthorityDiscoveryApi for Runtime { - fn authorities() -> Vec { - AuthorityDiscovery::authorities().into_iter() - .map(|id| id.encode()) - .map(EncodedAuthorityId) - .collect() - } - - fn sign(payload: &Vec) -> Option<(EncodedSignature, EncodedAuthorityId)> { - AuthorityDiscovery::sign(payload).map(|(sig, id)| { - (EncodedSignature(sig.encode()), EncodedAuthorityId(id.encode())) - }) - } - - fn verify(payload: &Vec, signature: &EncodedSignature, authority_id: &EncodedAuthorityId) -> bool { - let signature = match BabeSignature::decode(&mut &signature.0[..]) { - Ok(s) => s, - _ => return false, - }; - - let authority_id = match BabeId::decode(&mut &authority_id.0[..]) { - Ok(id) => id, - _ => return false, - }; - - AuthorityDiscovery::verify(payload, signature, authority_id) - } - } - - impl system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Index { - System::account_nonce(account) - } - } - - impl contracts_rpc_runtime_api::ContractsApi for Runtime { - fn call( - origin: AccountId, - dest: AccountId, - value: Balance, - gas_limit: u64, - input_data: Vec, - ) -> contracts_rpc_runtime_api::ContractExecResult { - use contracts_rpc_runtime_api::ContractExecResult; - - let exec_result = Contracts::bare_call( - origin, - dest.into(), - value, - gas_limit, - input_data, - ); - match exec_result { - Ok(v) => ContractExecResult::Success { - status: v.status, - data: v.data, - }, - Err(_) => ContractExecResult::Error, - } - } - } - - impl substrate_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string")); - SessionKeys::generate(seed) - } - } -} -#[cfg(test)] -mod tests { - use super::*; - use system::offchain::SubmitSignedTransaction; - - fn is_submit_signed_transaction(_arg: T) where - T: SubmitSignedTransaction< - Runtime, - Call, - Extrinsic=UncheckedExtrinsic, - CreateTransaction=Runtime, - Signer=ImOnlineId, - >, - {} - - #[test] - fn validate_bounds() { - let x = SubmitTransaction::default(); - is_submit_signed_transaction(x); - } -} diff --git a/node/src/main.rs b/node/src/main.rs deleted file mode 100644 index 9f76cf638c964..0000000000000 --- a/node/src/main.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate Node CLI - -#![warn(missing_docs)] - -use cli::VersionInfo; -use futures::sync::oneshot; -use futures::{future, Future}; - -use std::cell::RefCell; - -// handles ctrl-c -struct Exit; -impl cli::IntoExit for Exit { - type Exit = future::MapErr, fn(oneshot::Canceled) -> ()>; - fn into_exit(self) -> Self::Exit { - // can't use signal directly here because CtrlC takes only `Fn`. - 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) - } -} - -fn main() -> Result<(), cli::error::Error> { - let version = VersionInfo { - name: "Substrate Node", - commit: env!("VERGEN_SHA_SHORT"), - version: env!("CARGO_PKG_VERSION"), - executable_name: "substrate", - author: "Parity Technologies ", - description: "Generic substrate node", - support_url: "https://github.com/paritytech/substrate/issues/new", - }; - - cli::run(std::env::args(), Exit, version) -} diff --git a/node/testing/Cargo.toml b/node/testing/Cargo.toml deleted file mode 100644 index 8a4c08ed11bd2..0000000000000 --- a/node/testing/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "node-testing" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Test utilities for Substrate node." -edition = "2018" - -[dependencies] -balances = { package = "srml-balances", path = "../../srml/balances" } -client = { package = "substrate-client", path = "../../core/client" } -contracts = { package = "srml-contracts", path = "../../srml/contracts" } -grandpa = { package = "srml-grandpa", path = "../../srml/grandpa" } -indices = { package = "srml-indices", path = "../../srml/indices" } -keyring = { package = "substrate-keyring", path = "../../core/keyring" } -node-executor = { path = "../executor" } -node-primitives = { path = "../primitives" } -node-runtime = { path = "../runtime" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -sr-io = { path = "../../core/sr-io" } -sr-primitives = { path = "../../core/sr-primitives" } -runtime_support = { package = "srml-support", path = "../../srml/support" } -session = { package = "srml-session", path = "../../srml/session" } -staking = { package = "srml-staking", path = "../../srml/staking" } -substrate-executor = { path = "../../core/executor" } -system = { package = "srml-system", path = "../../srml/system" } -test-client = { package = "substrate-test-client", path = "../../core/test-client" } -timestamp = { package = "srml-timestamp", path = "../../srml/timestamp" } -treasury = { package = "srml-treasury", path = "../../srml/treasury" } -transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment" } -wabt = "0.9.2" diff --git a/node/testing/src/client.rs b/node/testing/src/client.rs deleted file mode 100644 index 3b16f2cbcb97d..0000000000000 --- a/node/testing/src/client.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Utilites to build a `TestClient` for `node-runtime`. - -use sr_primitives::BuildStorage; - -/// Re-export test-client utilities. -pub use test_client::*; - -/// Call executor for `node-runtime` `TestClient`. -pub type Executor = substrate_executor::NativeExecutor; - -/// Default backend type. -pub type Backend = client_db::Backend; - -/// Test client type. -pub type Client = client::Client< - Backend, - client::LocalCallExecutor, - node_primitives::Block, - node_runtime::RuntimeApi, ->; - -/// Genesis configuration parameters for `TestClient`. -#[derive(Default)] -pub struct GenesisParameters { - support_changes_trie: bool, -} - -impl test_client::GenesisInit for GenesisParameters { - fn genesis_storage(&self) -> (StorageOverlay, ChildrenStorageOverlay) { - crate::genesis::config(self.support_changes_trie, None).build_storage().unwrap() - } -} - -/// A `test-runtime` extensions to `TestClientBuilder`. -pub trait TestClientBuilderExt: Sized { - /// Create test client builder. - fn new() -> Self; - - /// Build the test client. - fn build(self) -> Client; -} - -impl TestClientBuilderExt for test_client::TestClientBuilder< - client::LocalCallExecutor, - Backend, - GenesisParameters, -> { - fn new() -> Self{ - Self::default() - } - - fn build(self) -> Client { - self.build_with_native_executor(None).0 - } -} - - diff --git a/node/testing/src/genesis.rs b/node/testing/src/genesis.rs deleted file mode 100644 index 5220d1774be89..0000000000000 --- a/node/testing/src/genesis.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Genesis Configuration. - -use crate::keyring::*; -use keyring::{Ed25519Keyring, Sr25519Keyring}; -use node_runtime::{ - GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, SystemConfig, - GrandpaConfig, IndicesConfig, ContractsConfig, WASM_BINARY, -}; -use node_runtime::constants::currency::*; -use primitives::ChangesTrieConfiguration; -use sr_primitives::Perbill; - - -/// Create genesis runtime configuration for tests. -pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig { - GenesisConfig { - system: Some(SystemConfig { - changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration { - digest_interval: 2, - digest_levels: 2, - }) } else { None }, - code: code.map(|x| x.to_vec()).unwrap_or_else(|| WASM_BINARY.to_vec()), - }), - indices: Some(IndicesConfig { - ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()], - }), - balances: Some(BalancesConfig { - balances: vec![ - (alice(), 111 * DOLLARS), - (bob(), 100 * DOLLARS), - (charlie(), 100_000_000 * DOLLARS), - (dave(), 111 * DOLLARS), - (eve(), 101 * DOLLARS), - (ferdie(), 100 * DOLLARS), - ], - vesting: vec![], - }), - session: Some(SessionConfig { - keys: vec![ - (alice(), to_session_keys( - &Ed25519Keyring::Alice, - &Sr25519Keyring::Alice, - )), - (bob(), to_session_keys( - &Ed25519Keyring::Bob, - &Sr25519Keyring::Bob, - )), - (charlie(), to_session_keys( - &Ed25519Keyring::Charlie, - &Sr25519Keyring::Charlie, - )), - ] - }), - staking: Some(StakingConfig { - current_era: 0, - stakers: vec![ - (dave(), alice(), 111 * DOLLARS, staking::StakerStatus::Validator), - (eve(), bob(), 100 * DOLLARS, staking::StakerStatus::Validator), - (ferdie(), charlie(), 100 * DOLLARS, staking::StakerStatus::Validator) - ], - validator_count: 3, - minimum_validator_count: 0, - slash_reward_fraction: Perbill::from_percent(10), - invulnerables: vec![alice(), bob(), charlie()], - .. Default::default() - }), - contracts: Some(ContractsConfig { - current_schedule: Default::default(), - gas_price: 1 * MILLICENTS, - }), - babe: Some(Default::default()), - grandpa: Some(GrandpaConfig { - authorities: vec![], - }), - im_online: Some(Default::default()), - authority_discovery: Some(Default::default()), - democracy: Some(Default::default()), - collective_Instance1: Some(Default::default()), - collective_Instance2: Some(Default::default()), - membership_Instance1: Some(Default::default()), - elections_phragmen: Some(Default::default()), - sudo: Some(Default::default()), - treasury: Some(Default::default()), - } -} diff --git a/node/testing/src/lib.rs b/node/testing/src/lib.rs deleted file mode 100644 index 71a22d9b57f25..0000000000000 --- a/node/testing/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! A set of testing utilities for Substrate Node. - -#![warn(missing_docs)] - -pub mod client; -pub mod genesis; -pub mod keyring; - diff --git a/primitives/api/Cargo.toml b/primitives/api/Cargo.toml new file mode 100644 index 0000000000000..1e3e555456000 --- /dev/null +++ b/primitives/api/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "sp-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-api-proc-macro = { version = "2.0.0", path = "proc-macro" } +sp-core = { version = "2.0.0", default-features = false, path = "../core" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } +sp-version = { version = "2.0.0", default-features = false, path = "../version" } +sp-state-machine = { version = "2.0.0", optional = true, path = "../../primitives/state-machine" } +hash-db = { version = "0.15.2", optional = true } + +[dev-dependencies] +sp-test-primitives = { version = "2.0.0", path = "../test-primitives" } + +[features] +default = [ "std" ] +std = [ + "codec/std", + "sp-core/std", + "sp-std/std", + "sp-runtime/std", + "sp-state-machine", + "sp-version/std", + "hash-db", +] diff --git a/primitives/api/proc-macro/Cargo.toml b/primitives/api/proc-macro/Cargo.toml new file mode 100644 index 0000000000000..122c889add499 --- /dev/null +++ b/primitives/api/proc-macro/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "sp-api-proc-macro" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0.2" +syn = { version = "1.0.8", features = ["full", "fold", "extra-traits", "visit"] } +proc-macro2 = "1.0.6" +blake2-rfc = "0.2.18" +proc-macro-crate = "0.1.4" + +# Required for the doc tests +[features] +default = [ "std" ] +std = [] diff --git a/core/sr-api-macros/src/decl_runtime_apis.rs b/primitives/api/proc-macro/src/decl_runtime_apis.rs similarity index 80% rename from core/sr-api-macros/src/decl_runtime_apis.rs rename to primitives/api/proc-macro/src/decl_runtime_apis.rs index 12639bd1c1f17..459707bdb53f4 100644 --- a/core/sr-api-macros/src/decl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/decl_runtime_apis.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,9 +16,10 @@ use crate::utils::{ generate_crate_access, generate_hidden_includes, generate_runtime_mod_name_for_trait, - fold_fn_decl_for_client_side, unwrap_or_error, extract_parameter_names_types_and_borrows, + fold_fn_decl_for_client_side, extract_parameter_names_types_and_borrows, generate_native_call_generator_fn_name, return_type_extract_type, generate_method_runtime_api_impl_name, generate_call_api_at_fn_name, prefix_function_with_trait, + replace_wild_card_parameter_names, }; use proc_macro2::{TokenStream, Span}; @@ -27,9 +28,8 @@ use quote::quote; use syn::{ spanned::Spanned, parse_macro_input, parse::{Parse, ParseStream, Result, Error}, ReturnType, - fold::{self, Fold}, parse_quote, ItemTrait, Generics, GenericParam, Attribute, FnArg, - visit::{Visit, self}, Pat, TraitBound, Meta, NestedMeta, Lit, TraitItem, Ident, Type, - TraitItemMethod + fold::{self, Fold}, parse_quote, ItemTrait, Generics, GenericParam, Attribute, FnArg, Type, + visit::{Visit, self}, TraitBound, Meta, NestedMeta, Lit, TraitItem, Ident, TraitItemMethod, }; use std::collections::HashMap; @@ -95,9 +95,9 @@ impl Parse for RuntimeApiDecls { fn extend_generics_with_block(generics: &mut Generics) { let c = generate_crate_access(HIDDEN_INCLUDES_ID); - generics.lt_token = Some(parse_quote!(<)); - generics.params.insert(0, parse_quote!( Block: #c::runtime_api::BlockT )); - generics.gt_token = Some(parse_quote!(>)); + generics.lt_token = Some(Default::default()); + generics.params.insert(0, parse_quote!( Block: #c::BlockT )); + generics.gt_token = Some(Default::default()); } /// Remove all attributes from the vector that are supported by us in the declaration of a runtime @@ -182,26 +182,26 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); // Auxiliary function that is used to convert between types that use different block types. - // The function expects that both a convertable by encoding the one and decoding the other. + // The function expects that both are convertible by encoding the one and decoding the other. result.push(quote!( #[cfg(any(feature = "std", test))] fn convert_between_block_types - ( + ( input: &I, error_desc: &'static str, ) -> std::result::Result { - ::decode( - &mut &#crate_::runtime_api::Encode::encode(input)[..], + ::decode( + &mut &#crate_::Encode::encode(input)[..], ).map_err(|e| format!("{} {}", error_desc, e.what())) } )); // Generate a native call generator for each function of the given trait. for fn_ in fns { - let params = extract_parameter_names_types_and_borrows(&fn_.decl)?; + let params = extract_parameter_names_types_and_borrows(&fn_)?; let trait_fn_name = &fn_.ident; let fn_name = generate_native_call_generator_fn_name(&fn_.ident); - let output = return_type_replace_block_with_node_block(fn_.decl.output.clone()); + let output = return_type_replace_block_with_node_block(fn_.output.clone()); let output_ty = return_type_extract_type(&output); let output = quote!( std::result::Result<#output_ty, String> ); @@ -217,7 +217,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { }); // Same as for the input types, we need to check if we also need to convert the output, // before returning it. - let output_conversion = if return_type_is_using_block(&fn_.decl.output) { + let output_conversion = if return_type_is_using_block(&fn_.output) { quote!( convert_between_block_types( &res, @@ -234,22 +234,21 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { // the user. Otherwise if it is not using the block, we don't need to add anything. let input_borrows = params .iter() - .map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { quote!() }); + .map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { None }); // Replace all `Block` with `NodeBlock`, add `'a` lifetime to references and collect // all the function inputs. let fn_inputs = fn_ - .decl .inputs .iter() .map(|v| fn_arg_replace_block_with_node_block(v.clone())) .map(|v| match v { - FnArg::Captured(ref arg) => { + FnArg::Typed(ref arg) => { let mut arg = arg.clone(); - if let Type::Reference(ref mut r) = arg.ty { + if let Type::Reference(ref mut r) = *arg.ty { r.lifetime = Some(parse_quote!( 'a )); } - FnArg::Captured(arg) + FnArg::Typed(arg) }, r => r.clone(), }); @@ -273,7 +272,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { result.push(quote!( #[cfg(any(feature = "std", test))] pub fn #fn_name< - 'a, ApiImpl: #trait_ #ty_generics, NodeBlock: #crate_::runtime_api::BlockT + 'a, ApiImpl: #trait_ #ty_generics, NodeBlock: #crate_::BlockT #(, #impl_generics_params)* >( #( #fn_inputs ),* @@ -310,15 +309,15 @@ fn parse_renamed_attribute(renamed: &Attribute) -> Result<(String, u32)> { } else { let mut itr = list.nested.iter(); let old_name = match itr.next() { - Some(NestedMeta::Literal(Lit::Str(i))) => { + Some(NestedMeta::Lit(Lit::Str(i))) => { i.value() }, _ => return err, }; let version = match itr.next() { - Some(NestedMeta::Literal(Lit::Int(i))) => { - i.value() as u32 + Some(NestedMeta::Lit(Lit::Int(i))) => { + i.base10_parse()? }, _ => return err, }; @@ -397,24 +396,27 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { result.push(quote!( #[cfg(any(feature = "std", test))] pub fn #fn_name< - R: #crate_::runtime_api::Encode + #crate_::runtime_api::Decode + PartialEq, + R: #crate_::Encode + #crate_::Decode + PartialEq, NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe, - Block: #crate_::runtime_api::BlockT, - T: #crate_::runtime_api::CallRuntimeAt, - C: #crate_::runtime_api::Core, + Block: #crate_::BlockT, + T: #crate_::CallApiAt, + C: #crate_::Core, >( call_runtime_at: &T, core_api: &C, - at: &#crate_::runtime_api::BlockId, + at: &#crate_::BlockId, args: Vec, - changes: &std::cell::RefCell<#crate_::runtime_api::OverlayedChanges>, - initialized_block: &std::cell::RefCell>>, + changes: &std::cell::RefCell<#crate_::OverlayedChanges>, + storage_transaction_cache: &std::cell::RefCell< + #crate_::StorageTransactionCache + >, + initialized_block: &std::cell::RefCell>>, native_call: Option, - context: #crate_::runtime_api::ExecutionContext, - recorder: &Option>>>, - ) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded> { + context: #crate_::ExecutionContext, + recorder: &Option<#crate_::ProofRecorder>, + ) -> std::result::Result<#crate_::NativeOrEncoded, T::Error> { let version = call_runtime_at.runtime_version_at(at)?; - use #crate_::runtime_api::InitializeBlock; + use #crate_::InitializeBlock; let initialize_block = if #skip_initialize_block { InitializeBlock::Skip } else { @@ -427,34 +429,40 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { if version.apis.iter().any(|(s, v)| { s == &ID && *v < #versions }) { - let ret = call_runtime_at.call_api_at:: _, _>( + let params = #crate_::CallApiAtParams::<_, _, fn() -> _, _> { core_api, at, - #old_names, - args, - changes, + function: #old_names, + native_call: None, + arguments: args, + overlayed_changes: changes, + storage_transaction_cache, initialize_block, - None, context, recorder, - )?; + }; + + let ret = call_runtime_at.call_api_at(params)?; update_initialized_block(); - return Ok(ret); + return Ok(ret) } )* - let ret = call_runtime_at.call_api_at( + let params = #crate_::CallApiAtParams { core_api, at, - #trait_fn_name, - args, - changes, - initialize_block, + function: #trait_fn_name, native_call, + arguments: args, + overlayed_changes: changes, + storage_transaction_cache, + initialize_block, context, recorder, - )?; + }; + + let ret = call_runtime_at.call_api_at(params)?; update_initialized_block(); Ok(ret) @@ -466,7 +474,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { } /// Generate the declaration of the trait for the runtime. -fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { +fn generate_runtime_decls(decls: &[ItemTrait]) -> Result { let mut result = Vec::new(); for decl in decls { @@ -474,12 +482,12 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { extend_generics_with_block(&mut decl.generics); let mod_name = generate_runtime_mod_name_for_trait(&decl.ident); let found_attributes = remove_supported_attributes(&mut decl.attrs); - let api_version = unwrap_or_error(get_api_version(&found_attributes).map(|v| { + let api_version = get_api_version(&found_attributes).map(|v| { generate_runtime_api_version(v as u32) - })); + })?; let id = generate_runtime_api_id(&decl.ident.to_string()); - let call_api_at_calls = unwrap_or_error(generate_call_api_at_calls(&decl)); + let call_api_at_calls = generate_call_api_at_calls(&decl)?; // Remove methods that have the `changed_in` attribute as they are not required for the // runtime anymore. @@ -488,13 +496,15 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { if remove_supported_attributes(&mut method.attrs).contains_key(CHANGED_IN_ATTRIBUTE) { None } else { + // Make sure we replace all the wild card parameter names. + replace_wild_card_parameter_names(&mut method.sig); Some(TraitItem::Method(method.clone())) } } r => Some(r.clone()), }).collect(); - let native_call_generators = unwrap_or_error(generate_native_call_generators(&decl)); + let native_call_generators = generate_native_call_generators(&decl)?; result.push(quote!( #[doc(hidden)] @@ -516,7 +526,7 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { )); } - quote!( #( #result )* ) + Ok(quote!( #( #result )* )) } /// Modify the given runtime api declaration to be usable on the client side. @@ -552,7 +562,7 @@ impl<'a> ToClientSideDecl<'a> { fn fold_trait_item_method(&mut self, method: TraitItemMethod) -> (TraitItemMethod, Option, TraitItemMethod) { let crate_ = self.crate_; - let context = quote!( #crate_::runtime_api::ExecutionContext::OffchainCall(None) ); + let context = quote!( #crate_::ExecutionContext::OffchainCall(None) ); let fn_impl = self.create_method_runtime_api_impl(method.clone()); let fn_decl = self.create_method_decl(method.clone(), context); let fn_decl_ctx = self.create_method_decl_with_context(method); @@ -562,10 +572,10 @@ impl<'a> ToClientSideDecl<'a> { 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 context_arg: syn::FnArg = parse_quote!( context: #crate_::ExecutionContext ); let mut fn_decl_ctx = self.create_method_decl(method, quote!( context )); fn_decl_ctx.sig.ident = Ident::new(&format!("{}_with_context", &fn_decl_ctx.sig.ident), Span::call_site()); - fn_decl_ctx.sig.decl.inputs.insert(2, context_arg); + fn_decl_ctx.sig.inputs.insert(2, context_arg); fn_decl_ctx } @@ -577,12 +587,12 @@ impl<'a> ToClientSideDecl<'a> { return None; } - let fn_decl = &method.sig.decl; - let ret_type = return_type_extract_type(&fn_decl.output); + let fn_sig = &method.sig; + let ret_type = return_type_extract_type(&fn_sig.output); // Get types and if the value is borrowed from all parameters. // If there is an error, we push it as the block to the user. - let param_types = match extract_parameter_names_types_and_borrows(fn_decl) { + let param_types = match extract_parameter_names_types_and_borrows(fn_sig) { Ok(res) => res.into_iter().map(|v| { let ty = v.1; let borrow = v.2; @@ -603,10 +613,10 @@ impl<'a> ToClientSideDecl<'a> { fn #name( &self, at: &#block_id, - context: #crate_::runtime_api::ExecutionContext, + context: #crate_::ExecutionContext, params: Option<( #( #param_types ),* )>, params_encoded: Vec, - ) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>>; + ) -> std::result::Result<#crate_::NativeOrEncoded<#ret_type>, Self::Error>; } ) } @@ -614,8 +624,12 @@ impl<'a> ToClientSideDecl<'a> { /// Takes the method declared by the user and creates the declaration we require for the runtime /// api client side. This method will call by default the `method_runtime_api_impl` for doing /// the actual call into the runtime. - fn create_method_decl(&mut self, mut method: TraitItemMethod, context: TokenStream) -> TraitItemMethod { - let params = match extract_parameter_names_types_and_borrows(&method.sig.decl) { + fn create_method_decl( + &mut self, + mut method: TraitItemMethod, + context: TokenStream, + ) -> TraitItemMethod { + let params = match extract_parameter_names_types_and_borrows(&method.sig) { Ok(res) => res.into_iter().map(|v| v.0).collect::>(), Err(e) => { self.errors.push(e.to_compile_error()); @@ -623,13 +637,10 @@ impl<'a> ToClientSideDecl<'a> { } }; let params2 = params.clone(); - let ret_type = return_type_extract_type(&method.sig.decl.output); + let ret_type = return_type_extract_type(&method.sig.output); + + fold_fn_decl_for_client_side(&mut method.sig, &self.block_id); - method.sig.decl = fold_fn_decl_for_client_side( - method.sig.decl.clone(), - &self.block_id, - &self.crate_ - ); let name_impl = generate_method_runtime_api_impl_name(&self.trait_, &method.sig.ident); let crate_ = self.crate_; @@ -650,7 +661,7 @@ impl<'a> ToClientSideDecl<'a> { let ident = Ident::new( &format!("{}_before_version_{}", method.sig.ident, version), - method.sig.ident.span() + method.sig.ident.span(), ); method.sig.ident = ident; method.attrs.push(parse_quote!( #[deprecated] )); @@ -672,24 +683,30 @@ impl<'a> ToClientSideDecl<'a> { 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[..]) - .map_err(|err| - #crate_::error::Error::CallResultDecode( - #function_name, err - ).into() - ) - } + #crate_::Encode::encode(&( #( &#params ),* )); + + self.#name_impl( + __runtime_api_at_param__, + #context, + #param_tuple, + runtime_api_impl_params_encoded, + ).and_then(|r| + match r { + #crate_::NativeOrEncoded::Native(n) => { + #native_handling + }, + #crate_::NativeOrEncoded::Encoded(r) => { + <#ret_type as #crate_::Decode>::decode(&mut &r[..]) + .map_err(|err| + format!( + "Failed to decode result of `{}`: {}", + #function_name, + err.what(), + ).into() + ) } - ) + } + ) } } ); @@ -714,12 +731,12 @@ impl<'a> Fold for ToClientSideDecl<'a> { 'static + Send + Sync - + #crate_::runtime_api::ApiExt<#block_ident> + + #crate_::ApiErrorExt ); } else { // Add the `Core` runtime api as super trait. let crate_ = &self.crate_; - input.supertraits.push(parse_quote!( #crate_::runtime_api::Core<#block_ident> )); + input.supertraits.push(parse_quote!( #crate_::Core<#block_ident> )); } // The client side trait is only required when compiling with the feature `std` or `test`. @@ -745,15 +762,12 @@ fn parse_runtime_api_version(version: &Attribute) -> Result { match meta { Meta::List(list) => { - if list.nested.len() > 1 && list.nested.is_empty() { + if list.nested.len() != 1 { err + } else if let Some(NestedMeta::Lit(Lit::Int(i))) = list.nested.first() { + i.base10_parse() } else { - match list.nested.first().as_ref().map(|v| v.value()) { - Some(NestedMeta::Literal(Lit::Int(i))) => { - Ok(i.value()) - }, - _ => err, - } + err } }, _ => err, @@ -780,12 +794,24 @@ fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream { let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let id = generate_runtime_api_id(&trait_name.to_string()); let version = generate_runtime_api_version(version as u32); - let (impl_generics, ty_generics, where_clause) = trait_.generics.split_for_impl(); + + let impl_generics = trait_.generics.type_params().map(|t| { + let ident = &t.ident; + let colon_token = &t.colon_token; + let bounds = &t.bounds; + + quote! { #ident #colon_token #bounds } + }).chain(std::iter::once(quote! { __Sr_Api_Error__ })); + + let ty_generics = trait_.generics.type_params().map(|t| { + let ident = &t.ident; + quote! { #ident } + }).chain(std::iter::once(quote! { Error = __Sr_Api_Error__ })); quote!( #[cfg(any(feature = "std", test))] - impl #impl_generics #crate_::runtime_api::RuntimeApiInfo - for #trait_name #ty_generics #where_clause + impl < #( #impl_generics, )* > #crate_::RuntimeApiInfo + for #trait_name < #( #ty_generics, )* > { #id #version @@ -806,14 +832,14 @@ fn get_api_version(found_attributes: &HashMap<&'static str, Attribute>) -> Resul } /// Generate the declaration of the trait for the client side. -fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream { +fn generate_client_side_decls(decls: &[ItemTrait]) -> Result { let mut result = Vec::new(); for decl in decls { let decl = decl.clone(); let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); - let block_id = quote!( #crate_::runtime_api::BlockId ); + let block_id = quote!( #crate_::BlockId ); let mut found_attributes = HashMap::new(); let mut errors = Vec::new(); let trait_ = decl.ident.clone(); @@ -831,14 +857,12 @@ fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream { let api_version = get_api_version(&found_attributes); - let runtime_info = unwrap_or_error( - api_version.map(|v| generate_runtime_info_impl(&decl, v)) - ); + let runtime_info = api_version.map(|v| generate_runtime_info_impl(&decl, v))?; result.push(quote!( #decl #runtime_info #( #errors )* )); } - quote!( #( #result )* ) + Ok(quote!( #( #result )* )) } /// Checks that a trait declaration is in the format we expect. @@ -848,32 +872,8 @@ struct CheckTraitDecl { impl<'ast> Visit<'ast> for CheckTraitDecl { fn visit_fn_arg(&mut self, input: &'ast FnArg) { - match input { - FnArg::Captured(ref arg) => { - match arg.pat { - Pat::Ident(ref pat) if pat.ident == "at" => { - self.errors.push( - Error::new( - pat.span(), - "`decl_runtime_apis!` adds automatically a parameter \ - `at: &BlockId`. Please rename/remove your parameter." - ) - ) - }, - _ => {} - } - }, - FnArg::SelfRef(_) | FnArg::SelfValue(_) => { - self.errors.push(Error::new(input.span(), "Self values are not supported.")) - } - _ => { - self.errors.push( - Error::new( - input.span(), - "Only function arguments in the form `pat: type` are supported." - ) - ) - } + if let FnArg::Receiver(_) = input { + self.errors.push(Error::new(input.span(), "`self` as argument not supported.")) } visit::visit_fn_arg(self, input); @@ -897,7 +897,7 @@ impl<'ast> Visit<'ast> for CheckTraitDecl { } fn visit_trait_bound(&mut self, input: &'ast TraitBound) { - if let Some(last_ident) = input.path.segments.last().map(|v| &v.value().ident) { + if let Some(last_ident) = input.path.segments.last().map(|v| &v.ident) { if last_ident == "BlockT" || last_ident == BLOCK_GENERIC_IDENT { self.errors.push( Error::new( @@ -915,15 +915,17 @@ impl<'ast> Visit<'ast> for CheckTraitDecl { } /// Check that the trait declarations are in the format we expect. -fn check_trait_decls(decls: &[ItemTrait]) -> Option { +fn check_trait_decls(decls: &[ItemTrait]) -> Result<()> { let mut checker = CheckTraitDecl { errors: Vec::new() }; decls.iter().for_each(|decl| visit::visit_item_trait(&mut checker, &decl)); - if checker.errors.is_empty() { - None + if let Some(err) = checker.errors.pop() { + Err(checker.errors.into_iter().fold(err, |mut err, other| { + err.combine(other); + err + })) } else { - let errors = checker.errors.into_iter().map(|e| e.to_compile_error()); - Some(quote!( #( #errors )* )) + Ok(()) } } @@ -932,19 +934,23 @@ pub fn decl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::Tok // Parse all trait declarations let RuntimeApiDecls { decls: api_decls } = parse_macro_input!(input as RuntimeApiDecls); - if let Some(errors) = check_trait_decls(&api_decls) { - return errors.into(); - } + decl_runtime_apis_impl_inner(&api_decls).unwrap_or_else(|e| e.to_compile_error()).into() +} + +fn decl_runtime_apis_impl_inner(api_decls: &[ItemTrait]) -> Result { + check_trait_decls(&api_decls)?; let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID); - let runtime_decls = generate_runtime_decls(&api_decls); - let client_side_decls = generate_client_side_decls(&api_decls); + let runtime_decls = generate_runtime_decls(api_decls)?; + let client_side_decls = generate_client_side_decls(api_decls)?; - quote!( - #hidden_includes + Ok( + quote!( + #hidden_includes - #runtime_decls + #runtime_decls - #client_side_decls - ).into() + #client_side_decls + ) + ) } diff --git a/primitives/api/proc-macro/src/impl_runtime_apis.rs b/primitives/api/proc-macro/src/impl_runtime_apis.rs new file mode 100644 index 0000000000000..dc4031fbc4b8a --- /dev/null +++ b/primitives/api/proc-macro/src/impl_runtime_apis.rs @@ -0,0 +1,746 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::utils::{ + generate_crate_access, generate_hidden_includes, + 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, generate_call_api_at_fn_name, prefix_function_with_trait, + extract_all_signature_types, +}; + +use proc_macro2::{Span, TokenStream}; + +use quote::quote; + +use syn::{ + spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, Path, Signature, + ImplItem, parse::{Parse, ParseStream, Result, Error}, PathArguments, GenericArgument, TypePath, + fold::{self, Fold}, parse_quote, +}; + +use std::{collections::HashSet, iter}; + +/// Unique identifier used to make the hidden includes unique for this macro. +const HIDDEN_INCLUDES_ID: &str = "IMPL_RUNTIME_APIS"; + +/// The structure used for parsing the runtime api implementations. +struct RuntimeApiImpls { + impls: Vec, +} + +impl Parse for RuntimeApiImpls { + fn parse(input: ParseStream) -> Result { + let mut impls = Vec::new(); + + while !input.is_empty() { + impls.push(ItemImpl::parse(input)?); + } + + if impls.is_empty() { + Err(Error::new(Span::call_site(), "No api implementation given!")) + } else { + Ok(Self { impls }) + } + } +} + +/// Generates the call to the implementation of the requested function. +/// The generated code includes decoding of the input arguments and encoding of the output. +fn generate_impl_call( + signature: &Signature, + runtime: &Type, + input: &Ident, + impl_trait: &Path +) -> Result { + let params = extract_parameter_names_types_and_borrows(signature)?; + + 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 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!( + #( + let #pnames : #ptypes = match #c_iter::Decode::decode(&mut #input) { + Ok(input) => input, + Err(e) => panic!("Bad input data provided to {}: {}", #fn_name_str, e.what()), + }; + )* + + #[allow(deprecated)] + <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*) + ) + ) +} + +/// Extract the trait that is implemented in the given `ItemImpl`. +fn extract_impl_trait<'a>(impl_: &'a ItemImpl) -> Result<&'a Path> { + impl_.trait_.as_ref().map(|v| &v.1).ok_or_else( + || Error::new(impl_.span(), "Only implementation of traits are supported!") + ).and_then(|p| { + if p.segments.len() > 1 { + Ok(p) + } else { + Err( + Error::new( + p.span(), + "The implemented trait has to be referenced with a path, \ + e.g. `impl client::Core for Runtime`." + ) + ) + } + }) +} + +/// Extracts the runtime block identifier. +fn extract_runtime_block_ident(trait_: &Path) -> Result<&TypePath> { + let span = trait_.span(); + let generics = trait_ + .segments + .last() + .ok_or_else(|| Error::new(span, "Empty path not supported"))?; + + match &generics.arguments { + PathArguments::AngleBracketed(ref args) => { + args.args.first().and_then(|v| match v { + GenericArgument::Type(Type::Path(ref block)) => Some(block), + _ => None + }).ok_or_else(|| Error::new(args.span(), "Missing `Block` generic parameter.")) + }, + PathArguments::None => { + let span = trait_.segments.last().as_ref().unwrap().span(); + Err(Error::new(span, "Missing `Block` generic parameter.")) + }, + PathArguments::Parenthesized(_) => { + Err(Error::new(generics.arguments.span(), "Unexpected parentheses in path!")) + } + } +} + +/// Generate all the implementation calls for the given functions. +fn generate_impl_calls( + impls: &[ItemImpl], + input: &Ident +) -> Result> { + let mut impl_calls = Vec::new(); + + for impl_ in impls { + let impl_trait_path = extract_impl_trait(impl_)?; + let impl_trait = extend_with_runtime_decl_path(impl_trait_path.clone()); + let impl_trait_ident = &impl_trait_path + .segments + .last() + .ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))? + .ident; + + for item in &impl_.items { + if let ImplItem::Method(method) = item { + let impl_call = generate_impl_call( + &method.sig, + &impl_.self_ty, + input, + &impl_trait + )?; + + impl_calls.push( + (impl_trait_ident.clone(), method.sig.ident.clone(), impl_call) + ); + } + } + } + + Ok(impl_calls) +} + +/// Generate the dispatch function that is used in native to call into the runtime. +fn generate_dispatch_function(impls: &[ItemImpl]) -> Result { + let data = Ident::new("data", Span::call_site()); + let c = generate_crate_access(HIDDEN_INCLUDES_ID); + let impl_calls = generate_impl_calls(impls, &data)? + .into_iter() + .map(|(trait_, fn_name, impl_)| { + let name = prefix_function_with_trait(&trait_, &fn_name); + quote!( #name => Some(#c::Encode::encode(&{ #impl_ })), ) + }); + + Ok(quote!( + #[cfg(feature = "std")] + pub fn dispatch(method: &str, mut #data: &[u8]) -> Option> { + match method { + #( #impl_calls )* + _ => None, + } + } + )) +} + +/// Generate the interface functions that are used to call into the runtime in wasm. +fn generate_wasm_interface(impls: &[ItemImpl]) -> Result { + let input = Ident::new("input", Span::call_site()); + let c = generate_crate_access(HIDDEN_INCLUDES_ID); + let impl_calls = generate_impl_calls(impls, &input)? + .into_iter() + .map(|(trait_, fn_name, impl_)| { + let fn_name = Ident::new( + &prefix_function_with_trait(&trait_, &fn_name), + Span::call_site() + ); + + quote!( + #[cfg(not(feature = "std"))] + #[no_mangle] + pub fn #fn_name(input_data: *mut u8, input_len: usize) -> u64 { + let mut #input = if input_len == 0 { + &[0u8; 0] + } else { + unsafe { + #c::slice::from_raw_parts(input_data, input_len) + } + }; + + let output = { #impl_ }; + #c::to_substrate_wasm_fn_return_value(&output) + } + ) + }); + + Ok(quote!( #( #impl_calls )* )) +} + +fn generate_runtime_api_base_structures() -> Result { + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + + Ok(quote!( + pub struct RuntimeApi {} + /// Implements all runtime apis for the client side. + #[cfg(any(feature = "std", test))] + pub struct RuntimeApiImpl + 'static> + where + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + C::StateBackend: #crate_::StateBackend<#crate_::HasherFor>, + { + call: &'static C, + commit_on_success: std::cell::RefCell, + initialized_block: std::cell::RefCell>>, + changes: std::cell::RefCell<#crate_::OverlayedChanges>, + storage_transaction_cache: std::cell::RefCell< + #crate_::StorageTransactionCache + >, + recorder: Option<#crate_::ProofRecorder>, + } + + // `RuntimeApi` itself is not threadsafe. However, an instance is only available in a + // `ApiRef` object and `ApiRef` also has an associated lifetime. This lifetimes makes it + // impossible to move `RuntimeApi` into another thread. + #[cfg(any(feature = "std", test))] + unsafe impl> Send + for RuntimeApiImpl + where + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + C::StateBackend: #crate_::StateBackend<#crate_::HasherFor>, + {} + + #[cfg(any(feature = "std", test))] + unsafe impl> Sync + for RuntimeApiImpl + where + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + C::StateBackend: #crate_::StateBackend<#crate_::HasherFor>, + {} + + #[cfg(any(feature = "std", test))] + impl> #crate_::ApiErrorExt + for RuntimeApiImpl + where + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + C::StateBackend: #crate_::StateBackend<#crate_::HasherFor>, + { + type Error = C::Error; + } + + #[cfg(any(feature = "std", test))] + impl> #crate_::ApiExt for + RuntimeApiImpl + where + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + C::StateBackend: #crate_::StateBackend<#crate_::HasherFor>, + { + type StateBackend = C::StateBackend; + + fn map_api_result std::result::Result, R, E>( + &self, + map_call: F, + ) -> std::result::Result where Self: Sized { + *self.commit_on_success.borrow_mut() = false; + let res = map_call(self); + *self.commit_on_success.borrow_mut() = true; + + self.commit_on_ok(&res); + + res + } + + fn runtime_version_at( + &self, + at: &#crate_::BlockId, + ) -> std::result::Result<#crate_::RuntimeVersion, C::Error> { + self.call.runtime_version_at(at) + } + + fn record_proof(&mut self) { + self.recorder = Some(Default::default()); + } + + fn extract_proof(&mut self) -> Option<#crate_::StorageProof> { + self.recorder + .take() + .map(|recorder| { + let trie_nodes = recorder.read() + .iter() + .filter_map(|(_k, v)| v.as_ref().map(|v| v.to_vec())) + .collect(); + #crate_::StorageProof::new(trie_nodes) + }) + } + + fn into_storage_changes< + T: #crate_::ChangesTrieStorage<#crate_::HasherFor, #crate_::NumberFor> + >( + &self, + backend: &Self::StateBackend, + changes_trie_storage: Option<&T>, + parent_hash: Block::Hash, + ) -> std::result::Result< + #crate_::StorageChanges, + String + > where Self: Sized { + self.initialized_block.borrow_mut().take(); + self.changes.replace(Default::default()).into_storage_changes( + backend, + changes_trie_storage, + parent_hash, + self.storage_transaction_cache.replace(Default::default()), + ) + } + } + + #[cfg(any(feature = "std", test))] + impl #crate_::ConstructRuntimeApi + for RuntimeApi + where + C: #crate_::CallApiAt + 'static, + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + C::StateBackend: #crate_::StateBackend<#crate_::HasherFor>, + { + type RuntimeApi = RuntimeApiImpl; + + fn construct_runtime_api<'a>( + call: &'a C, + ) -> #crate_::ApiRef<'a, Self::RuntimeApi> { + RuntimeApiImpl { + call: unsafe { std::mem::transmute(call) }, + commit_on_success: true.into(), + initialized_block: None.into(), + changes: Default::default(), + recorder: Default::default(), + storage_transaction_cache: Default::default(), + }.into() + } + } + + #[cfg(any(feature = "std", test))] + impl> RuntimeApiImpl + where + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + C::StateBackend: #crate_::StateBackend<#crate_::HasherFor>, + { + fn call_api_at< + R: #crate_::Encode + #crate_::Decode + PartialEq, + F: FnOnce( + &C, + &Self, + &std::cell::RefCell<#crate_::OverlayedChanges>, + &std::cell::RefCell<#crate_::StorageTransactionCache>, + &std::cell::RefCell>>, + &Option<#crate_::ProofRecorder>, + ) -> std::result::Result<#crate_::NativeOrEncoded, E>, + E, + >( + &self, + call_api_at: F, + ) -> std::result::Result<#crate_::NativeOrEncoded, E> { + let res = call_api_at( + &self.call, + self, + &self.changes, + &self.storage_transaction_cache, + &self.initialized_block, + &self.recorder, + ); + + self.commit_on_ok(&res); + res + } + + fn commit_on_ok(&self, res: &std::result::Result) { + if *self.commit_on_success.borrow() { + if res.is_err() { + self.changes.borrow_mut().discard_prospective(); + } else { + self.changes.borrow_mut().commit_prospective(); + } + } + } + } + )) +} + +/// Extend the given trait path with module that contains the declaration of the trait for the +/// runtime. +fn extend_with_runtime_decl_path(mut trait_: Path) -> Path { + let runtime = { + let trait_name = &trait_ + .segments + .last() + .as_ref() + .expect("Trait path should always contain at least one item; qed") + .ident; + + generate_runtime_mod_name_for_trait(trait_name) + }; + + let pos = trait_.segments.len() - 1; + trait_.segments.insert(pos, runtime.clone().into()); + trait_ +} + +/// Generates the implementations of the apis for the runtime. +fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result { + let mut impls_prepared = Vec::new(); + + // We put `runtime` before each trait to get the trait that is intended for the runtime and + // we put the `RuntimeBlock` as first argument for the trait generics. + for impl_ in impls.iter() { + let mut impl_ = impl_.clone(); + let trait_ = extract_impl_trait(&impl_)?.clone(); + let trait_ = extend_with_runtime_decl_path(trait_); + + impl_.trait_.as_mut().unwrap().1 = trait_; + impls_prepared.push(impl_); + } + + Ok(quote!( #( #impls_prepared )* )) +} + + +/// 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 +/// with code that calls into the runtime. +struct ApiRuntimeImplToApiRuntimeApiImpl<'a> { + runtime_block: &'a TypePath, + runtime_mod_path: &'a Path, + runtime_type: &'a Type, + trait_generic_arguments: &'a [GenericArgument], + impl_trait: &'a Ident, +} + +impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { + fn fold_type_path(&mut self, input: TypePath) -> TypePath { + let new_ty_path = if input == *self.runtime_block { + parse_quote!( __SR_API_BLOCK__ ) + } else { + input + }; + + fold::fold_type_path(self, new_ty_path) + } + + 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 native_call_generator_ident = + generate_native_call_generator_fn_name(&input.sig.ident); + let call_api_at_call = generate_call_api_at_fn_name(&input.sig.ident); + let trait_generic_arguments = self.trait_generic_arguments; + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + + // Generate the access to the native parameters + let param_tuple_access = if input.sig.inputs.len() == 1 { + vec![ quote!( p ) ] + } else { + input.sig.inputs.iter().enumerate().map(|(i, _)| { + let i = syn::Index::from(i); + quote!( p.#i ) + }).collect::>() + }; + + let (param_types, error) = match extract_parameter_names_types_and_borrows(&input.sig) { + 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())), + }; + + // Rewrite the input parameters. + input.sig.inputs = parse_quote! { + &self, + at: &#crate_::BlockId<__SR_API_BLOCK__>, + context: #crate_::ExecutionContext, + params: Option<( #( #param_types ),* )>, + params_encoded: Vec, + }; + + input.sig.ident = generate_method_runtime_api_impl_name( + &self.impl_trait, + &input.sig.ident, + ); + let ret_type = return_type_extract_type(&input.sig.output); + + // Generate the correct return type. + input.sig.output = parse_quote!( + -> std::result::Result<#crate_::NativeOrEncoded<#ret_type>, RuntimeApiImplCall::Error> + ); + + // Generate the new method implementation that calls into the runtime. + parse_quote!( + { + // Get the error to the user (if we have one). + #error + + self.call_api_at( + | + call_runtime_at, + core_api, + changes, + storage_transaction_cache, + initialized_block, + recorder + | { + #runtime_mod_path #call_api_at_call( + call_runtime_at, + core_api, + at, + params_encoded, + changes, + storage_transaction_cache, + initialized_block, + params.map(|p| { + #runtime_mod_path #native_call_generator_ident :: + <#runtime, __SR_API_BLOCK__ #(, #trait_generic_arguments )*> ( + #( #param_tuple_access ),* + ) + }), + context, + recorder, + ) + } + ) + } + ) + }; + + 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 { + // All this `UnwindSafe` magic below here is required for this rust bug: + // https://github.com/rust-lang/rust/issues/24159 + // Before we directly had the final block type and rust could determine that it is unwind + // safe, but now we just have a generic parameter `Block`. + + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + + // Implement the trait for the `RuntimeApiImpl` + input.self_ty = Box::new( + parse_quote!( RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall> ) + ); + + input.generics.params.push( + parse_quote!( + __SR_API_BLOCK__: #crate_::BlockT + std::panic::UnwindSafe + + std::panic::RefUnwindSafe + ) + ); + input.generics.params.push( + parse_quote!( RuntimeApiImplCall: #crate_::CallApiAt<__SR_API_BLOCK__> + 'static ) + ); + + let where_clause = input.generics.make_where_clause(); + + where_clause.predicates.push( + parse_quote! { + RuntimeApiImplCall::StateBackend: + #crate_::StateBackend<#crate_::HasherFor<__SR_API_BLOCK__>> + } + ); + + // Require that all types used in the function signatures are unwind safe. + extract_all_signature_types(&input.items).iter().for_each(|i| { + where_clause.predicates.push( + parse_quote! { + #i: std::panic::UnwindSafe + std::panic::RefUnwindSafe + } + ); + }); + + where_clause.predicates.push( + parse_quote! { + __SR_API_BLOCK__::Header: std::panic::UnwindSafe + std::panic::RefUnwindSafe + } + ); + + // 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) + } +} + +/// Generate the implementations of the runtime apis for the `RuntimeApi` type. +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_path = extract_impl_trait(&impl_)?; + let impl_trait = &impl_trait_path + .segments + .last() + .ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))? + .clone(); + let runtime_block = extract_runtime_block_ident(impl_trait_path)?; + 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, + runtime_mod_path: &runtime_mod_path, + runtime_type: &*runtime_type, + trait_generic_arguments: &trait_generic_arguments, + impl_trait: &impl_trait.ident, + }; + + result.push(visitor.fold_item_impl(impl_.clone())); + } + Ok(quote!( #( #result )* )) +} + +/// Generates `RUNTIME_API_VERSIONS` that holds all version information about the implemented +/// runtime apis. +fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result { + let mut result = Vec::with_capacity(impls.len()); + let mut processed_traits = HashSet::new(); + + for impl_ in impls { + let mut path = extend_with_runtime_decl_path(extract_impl_trait(&impl_)?.clone()); + // Remove the trait + let trait_ = path + .segments + .pop() + .expect("extract_impl_trait already checks that this is valid; qed") + .into_value() + .ident; + + let span = trait_.span(); + if !processed_traits.insert(trait_) { + return Err( + Error::new( + span, + "Two traits with the same name detected! \ + The trait name is used to generate its ID. \ + Please rename one trait at the declaration!" + ) + ) + } + + let id: Path = parse_quote!( #path ID ); + let version: Path = parse_quote!( #path VERSION ); + + result.push(quote!( (#id, #version) )); + } + + let c = generate_crate_access(HIDDEN_INCLUDES_ID); + + Ok(quote!( + const RUNTIME_API_VERSIONS: #c::ApisVec = #c::create_apis_vec!([ #( #result ),* ]); + )) +} + +/// The implementation of the `impl_runtime_apis!` macro. +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); + + impl_runtime_apis_impl_inner(&api_impls).unwrap_or_else(|e| e.to_compile_error()).into() +} + +fn impl_runtime_apis_impl_inner(api_impls: &[ItemImpl]) -> Result { + let dispatch_impl = generate_dispatch_function(api_impls)?; + let api_impls_for_runtime = generate_api_impl_for_runtime(api_impls)?; + let base_runtime_api = generate_runtime_api_base_structures()?; + let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID); + let runtime_api_versions = generate_runtime_api_versions(api_impls)?; + let wasm_interface = generate_wasm_interface(api_impls)?; + let api_impls_for_runtime_api = generate_api_impl_for_runtime_api(api_impls)?; + + Ok( + quote!( + #hidden_includes + + #base_runtime_api + + #api_impls_for_runtime + + #api_impls_for_runtime_api + + #runtime_api_versions + + pub mod api { + use super::*; + + #dispatch_impl + + #wasm_interface + } + ) + ) +} diff --git a/primitives/api/proc-macro/src/lib.rs b/primitives/api/proc-macro/src/lib.rs new file mode 100644 index 0000000000000..a1fd11188feb8 --- /dev/null +++ b/primitives/api/proc-macro/src/lib.rs @@ -0,0 +1,36 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Macros for declaring and implementing runtime apis. + +#![recursion_limit = "512"] +extern crate proc_macro; + +use proc_macro::TokenStream; + +mod impl_runtime_apis; +mod decl_runtime_apis; +mod utils; + +#[proc_macro] +pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { + impl_runtime_apis::impl_runtime_apis_impl(input) +} + +#[proc_macro] +pub fn decl_runtime_apis(input: TokenStream) -> TokenStream { + decl_runtime_apis::decl_runtime_apis_impl(input) +} diff --git a/primitives/api/proc-macro/src/utils.rs b/primitives/api/proc-macro/src/utils.rs new file mode 100644 index 0000000000000..8330624bf26d7 --- /dev/null +++ b/primitives/api/proc-macro/src/utils.rs @@ -0,0 +1,201 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use proc_macro2::{TokenStream, Span}; + +use syn::{ + Result, Ident, Signature, parse_quote, Type, Pat, spanned::Spanned, FnArg, Error, token::And, + ImplItem, ReturnType, +}; + +use quote::quote; + +use std::env; + +use proc_macro_crate::crate_name; + +fn generate_hidden_includes_mod_name(unique_id: &'static str) -> Ident { + Ident::new(&format!("sp_api_hidden_includes_{}", unique_id), Span::call_site()) +} + +/// Generates the hidden includes that are required to make the macro independent from its scope. +pub fn generate_hidden_includes(unique_id: &'static str) -> TokenStream { + if env::var("CARGO_PKG_NAME").unwrap() == "sp-api" { + TokenStream::new() + } else { + let mod_name = generate_hidden_includes_mod_name(unique_id); + match crate_name("sp-api") { + 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 sp_api; + } + ) + }, + Err(e) => { + let err = Error::new(Span::call_site(), &e).to_compile_error(); + quote!( #err ) + } + } + + }.into() +} + +/// Generates the access to the `sc_client` crate. +pub fn generate_crate_access(unique_id: &'static str) -> TokenStream { + if env::var("CARGO_PKG_NAME").unwrap() == "sp-api" { + quote!( sp_api ) + } else { + let mod_name = generate_hidden_includes_mod_name(unique_id); + quote!( self::#mod_name::sp_api ) + }.into() +} + +/// Generates the name of the module that contains the trait declaration for the runtime. +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(trait_: &Ident, method: &Ident) -> Ident { + Ident::new(&format!("{}_{}_runtime_api_impl", trait_, method), Span::call_site()) +} + +/// Get the type of a `syn::ReturnType`. +pub fn return_type_extract_type(rt: &ReturnType) -> Type { + match rt { + ReturnType::Default => parse_quote!( () ), + ReturnType::Type(_, ref ty) => *ty.clone(), + } +} + +/// Replace the `_` (wild card) parameter names in the given signature with unique identifiers. +pub fn replace_wild_card_parameter_names(input: &mut Signature) { + let mut generated_pattern_counter = 0; + input.inputs.iter_mut().for_each(|arg| if let FnArg::Typed(arg) = arg { + arg.pat = Box::new( + generate_unique_pattern((*arg.pat).clone(), &mut generated_pattern_counter), + ); + }); +} + +/// Fold the given `Signature` to make it usable on the client side. +pub fn fold_fn_decl_for_client_side( + input: &mut Signature, + block_id: &TokenStream, +) { + replace_wild_card_parameter_names(input); + + // Add `&self, at:& BlockId` as parameters to each function at the beginning. + input.inputs.insert(0, parse_quote!( __runtime_api_at_param__: &#block_id )); + input.inputs.insert(0, parse_quote!( &self )); + + // Wrap the output in a `Result` + input.output = { + let ty = return_type_extract_type(&input.output); + parse_quote!( -> std::result::Result<#ty, Self::Error> ) + }; +} + +/// 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 signature. +pub fn extract_parameter_names_types_and_borrows(sig: &Signature) + -> Result)>> +{ + let mut result = Vec::new(); + let mut generated_pattern_counter = 0; + for input in sig.inputs.iter() { + match input { + FnArg::Typed(arg) => { + let (ty, borrow) = match &*arg.ty { + Type::Reference(t) => { + ((*t.elem).clone(), Some(t.and_token)) + }, + t => { (t.clone(), None) }, + }; + + let name = + generate_unique_pattern((*arg.pat).clone(), &mut generated_pattern_counter); + result.push((name, ty, borrow)); + }, + FnArg::Receiver(_) => { + return Err(Error::new(input.span(), "`self` parameter not supported!")) + } + } + } + + 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()) +} + +/// Generates the name for the call api at function. +pub fn generate_call_api_at_fn_name(fn_name: &Ident) -> Ident { + Ident::new(&format!("{}_call_api_at", fn_name.to_string()), Span::call_site()) +} + +/// Prefix the given function with the trait name. +pub fn prefix_function_with_trait(trait_: &Ident, function: &F) -> String { + format!("{}_{}", trait_.to_string(), function.to_string()) +} + +/// Extract all types that appear in signatures in the given `ImplItem`'s. +/// +/// If a type is a reference, the inner type is extracted (without the reference). +pub fn extract_all_signature_types(items: &[ImplItem]) -> Vec { + items.iter() + .filter_map(|i| match i { + ImplItem::Method(method) => Some(&method.sig), + _ => None, + }) + .map(|sig| { + let ret_ty = match &sig.output { + ReturnType::Default => None, + ReturnType::Type(_, ty) => Some((**ty).clone()), + }; + + sig.inputs.iter().filter_map(|i| match i { + FnArg::Typed(arg) => Some(&arg.ty), + _ => None, + }).map(|ty| match &**ty { + Type::Reference(t) => (*t.elem).clone(), + _ => (**ty).clone(), + }).chain(ret_ty) + }) + .flatten() + .collect() +} diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs new file mode 100644 index 0000000000000..122e863228966 --- /dev/null +++ b/primitives/api/src/lib.rs @@ -0,0 +1,486 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate runtime api +//! +//! The Substrate runtime api is the crucial interface between the node and the runtime. +//! Every call that goes into the runtime is done with a runtime api. The runtime apis are not fixed. +//! Every Substrate user can define its own apis with +//! [`decl_runtime_apis`](macro.decl_runtime_apis.html) and implement them in +//! the runtime with [`impl_runtime_apis`](macro.impl_runtime_apis.html). +//! +//! Every Substrate runtime needs to implement the [`Core`] runtime api. This api provides the basic +//! functionality that every runtime needs to export. +//! +//! Besides the macros and the [`Core`] runtime api, this crates provides the [`Metadata`] runtime +//! api, the [`ApiExt`] trait, the [`CallApiAt`] trait and the [`ConstructRuntimeApi`] trait. + +#![cfg_attr(not(feature = "std"), no_std)] + +// Make doc tests happy +extern crate self as sp_api; + +#[doc(hidden)] +#[cfg(feature = "std")] +pub use sp_state_machine::{ + OverlayedChanges, StorageProof, Backend as StateBackend, ChangesTrieStorage, +}; +#[doc(hidden)] +#[cfg(feature = "std")] +pub use sp_core::NativeOrEncoded; +#[doc(hidden)] +#[cfg(feature = "std")] +pub use hash_db::Hasher; +#[doc(hidden)] +#[cfg(not(feature = "std"))] +pub use sp_core::to_substrate_wasm_fn_return_value; +#[doc(hidden)] +pub use sp_runtime::{ + traits::{ + Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, HasherFor, NumberFor, + Header as HeaderT, Hash as HashT, + }, + generic::BlockId, transaction_validity::TransactionValidity, +}; +#[doc(hidden)] +pub use sp_core::{offchain, ExecutionContext}; +#[doc(hidden)] +pub use sp_version::{ApiId, RuntimeVersion, ApisVec, create_apis_vec}; +#[doc(hidden)] +pub use sp_std::{slice, mem}; +#[cfg(feature = "std")] +use sp_std::result; +#[doc(hidden)] +pub use codec::{Encode, Decode}; +use sp_core::OpaqueMetadata; +#[cfg(feature = "std")] +use std::{panic::UnwindSafe, cell::RefCell}; + +/// Declares given traits as runtime apis. +/// +/// The macro will create two declarations, one for using on the client side and one for using +/// on the runtime side. The declaration for the runtime side is hidden in its own module. +/// The client side declaration gets two extra parameters per function, +/// `&self` and `at: &BlockId`. The runtime side declaration will match the given trait +/// declaration. Besides one exception, the macro adds an extra generic parameter `Block: BlockT` +/// to the client side and the runtime side. This generic parameter is usable by the user. +/// +/// For implementing these macros you should use the `impl_runtime_apis!` macro. +/// +/// # Example +/// +/// ```rust +/// sp_api::decl_runtime_apis! { +/// /// Declare the api trait. +/// pub trait Balance { +/// /// Get the balance. +/// fn get_balance() -> u64; +/// /// Set the balance. +/// fn set_balance(val: u64); +/// } +/// +/// /// You can declare multiple api traits in one macro call. +/// /// In one module you can call the macro at maximum one time. +/// pub trait BlockBuilder { +/// /// The macro adds an explicit `Block: BlockT` generic parameter for you. +/// /// You can use this generic parameter as you would defined it manually. +/// fn build_block() -> Block; +/// } +/// } +/// +/// # fn main() {} +/// ``` +/// +/// # Runtime api trait versioning +/// +/// 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. 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 +/// sp_api::decl_runtime_apis! { +/// /// Declare the api trait. +/// #[api_version(2)] +/// pub trait Balance { +/// /// Get the balance. +/// fn get_balance() -> u64; +/// /// 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: u16); +/// /// In version 2, we added this new function. +/// fn increase_balance(val: u64); +/// } +/// } +/// +/// # fn main() {} +/// ``` +/// +/// To check if a given runtime implements a runtime api trait, the `RuntimeVersion` has the +/// function `has_api()`. Also the `ApiExt` provides a function `has_api(at: &BlockId)` to +/// check if the runtime at the given block id implements the requested runtime api trait. +pub use sp_api_proc_macro::decl_runtime_apis; + +/// Tags given trait implementations as runtime apis. +/// +/// All traits given to this macro, need to be declared with the `decl_runtime_apis!` macro. +/// The implementation of the trait should follow the declaration given to the `decl_runtime_apis!` +/// macro, besides the `Block` type that is required as first generic parameter for each runtime +/// api trait. When implementing a runtime api trait, it is required that the trait is referenced +/// by a path, e.g. `impl my_trait::MyTrait for Runtime`. The macro will use this path to access +/// the declaration of the trait for the runtime side. +/// +/// The macro also generates the api implementations for the client side and provides it through +/// the `RuntimeApi` type. The `RuntimeApi` is hidden behind a `feature` called `std`. +/// +/// To expose version information about all implemented api traits, the constant +/// `RUNTIME_API_VERSIONS` is generated. This constant should be used to instantiate the `apis` +/// field of `RuntimeVersion`. +/// +/// # Example +/// +/// ```rust +/// use sp_version::create_runtime_str; +/// # +/// # use sp_runtime::traits::{GetNodeBlockType, Block as BlockT}; +/// # use sp_test_primitives::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. +/// # pub struct Runtime {} +/// # impl GetNodeBlockType for Runtime { +/// # type NodeBlock = Block; +/// # } +/// # +/// # sp_api::decl_runtime_apis! { +/// # /// Declare the api trait. +/// # pub trait Balance { +/// # /// Get the balance. +/// # fn get_balance() -> u64; +/// # /// Set the balance. +/// # fn set_balance(val: u64); +/// # } +/// # pub trait BlockBuilder { +/// # fn build_block() -> Block; +/// # } +/// # } +/// +/// /// All runtime api implementations need to be done in one call of the macro! +/// sp_api::impl_runtime_apis! { +/// # impl sp_api::Core for Runtime { +/// # fn version() -> sp_version::RuntimeVersion { +/// # unimplemented!() +/// # } +/// # fn execute_block(_block: Block) {} +/// # fn initialize_block(_header: &::Header) {} +/// # } +/// +/// impl self::Balance for Runtime { +/// fn get_balance() -> u64 { +/// 1 +/// } +/// fn set_balance(_bal: u64) { +/// // Store the balance +/// } +/// } +/// +/// impl self::BlockBuilder for Runtime { +/// fn build_block() -> Block { +/// unimplemented!("Please implement me!") +/// } +/// } +/// } +/// +/// /// Runtime version. This needs to be declared for each runtime. +/// pub const VERSION: sp_version::RuntimeVersion = sp_version::RuntimeVersion { +/// spec_name: create_runtime_str!("node"), +/// impl_name: create_runtime_str!("test-node"), +/// authoring_version: 1, +/// spec_version: 1, +/// impl_version: 0, +/// // Here we are exposing the runtime api versions. +/// apis: RUNTIME_API_VERSIONS, +/// }; +/// +/// # fn main() {} +/// ``` +pub use sp_api_proc_macro::impl_runtime_apis; + +/// A type that records all accessed trie nodes and generates a proof out of it. +#[cfg(feature = "std")] +pub type ProofRecorder = sp_state_machine::ProofRecorder< + <<::Header as HeaderT>::Hashing as HashT>::Hasher +>; + +/// A type that is used as cache for the storage transactions. +#[cfg(feature = "std")] +pub type StorageTransactionCache = + sp_state_machine::StorageTransactionCache< + >>::Transaction, HasherFor, NumberFor + >; + +#[cfg(feature = "std")] +pub type StorageChanges = + sp_state_machine::StorageChanges< + >>::Transaction, + HasherFor, + NumberFor + >; + +/// Extract the state backend type for a type that implements `ProvideRuntimeApi`. +#[cfg(feature = "std")] +pub type StateBackendFor = + <

>::Api as ApiExt>::StateBackend; + +/// Extract the state backend transaction type for a type that implements `ProvideRuntimeApi`. +#[cfg(feature = "std")] +pub type TransactionFor = + as StateBackend>>::Transaction; + +/// Something that can be constructed to a runtime api. +#[cfg(feature = "std")] +pub trait ConstructRuntimeApi> { + /// The actual runtime api that will be constructed. + type RuntimeApi: ApiExt; + + /// Construct an instance of the runtime api. + fn construct_runtime_api<'a>(call: &'a C) -> ApiRef<'a, Self::RuntimeApi>; +} + +/// Extends the runtime api traits with an associated error type. This trait is given as super +/// trait to every runtime api trait. +#[cfg(feature = "std")] +pub trait ApiErrorExt { + /// Error type used by the runtime apis. + type Error: std::fmt::Debug + From; +} + +/// Extends the runtime api implementation with some common functionality. +#[cfg(feature = "std")] +pub trait ApiExt: ApiErrorExt { + /// The state backend that is used to store the block states. + type StateBackend: StateBackend>; + + /// The given closure will be called with api instance. Inside the closure any api call is + /// allowed. After doing the api call, the closure is allowed to map the `Result` to a + /// different `Result` type. This can be important, as the internal data structure that keeps + /// track of modifications to the storage, discards changes when the `Result` is an `Err`. + /// On `Ok`, the structure commits the changes to an internal buffer. + fn map_api_result result::Result, R, E>( + &self, + map_call: F, + ) -> result::Result where Self: Sized; + + /// Checks if the given api is implemented and versions match. + fn has_api( + &self, + at: &BlockId, + ) -> Result where Self: Sized { + self.runtime_version_at(at).map(|v| v.has_api_with(&A::ID, |v| v == A::VERSION)) + } + + /// Check if the given api is implemented and the version passes a predicate. + fn has_api_with bool>( + &self, + at: &BlockId, + pred: P, + ) -> Result where Self: Sized { + self.runtime_version_at(at).map(|v| v.has_api_with(&A::ID, pred)) + } + + /// Returns the runtime version at the given block id. + fn runtime_version_at(&self, at: &BlockId) -> Result; + + /// Start recording all accessed trie nodes for generating proofs. + fn record_proof(&mut self); + + /// Extract the recorded proof. + /// + /// This stops the proof recording. + /// + /// If `record_proof` was not called before, this will return `None`. + fn extract_proof(&mut self) -> Option; + + /// Convert the api object into the storage changes that were done while executing runtime + /// api functions. + /// + /// After executing this function, all collected changes are reset. + fn into_storage_changes, NumberFor>>( + &self, + backend: &Self::StateBackend, + changes_trie_storage: Option<&T>, + parent_hash: Block::Hash, + ) -> Result, String> where Self: Sized; +} + +/// Before calling any runtime api function, the runtime need to be initialized +/// at the requested block. However, some functions like `execute_block` or +/// `initialize_block` itself don't require to have the runtime initialized +/// at the requested block. +/// +/// `call_api_at` is instructed by this enum to do the initialization or to skip +/// it. +#[cfg(feature = "std")] +#[derive(Clone, Copy)] +pub enum InitializeBlock<'a, Block: BlockT> { + /// Skip initializing the runtime for a given block. + /// + /// This is used by functions who do the initialization by themselves or don't require it. + Skip, + /// Initialize the runtime for a given block. + /// + /// If the stored `BlockId` is `Some(_)`, the runtime is currently initialized at this block. + Do(&'a RefCell>>), +} + +/// Parameters for [`CallApiAt::call_api_at`]. +#[cfg(feature = "std")] +pub struct CallApiAtParams<'a, Block: BlockT, C, NC, Backend: StateBackend>> { + /// A reference to something that implements the [`Core`] api. + pub core_api: &'a C, + /// The block id that determines the state that should be setup when calling the function. + pub at: &'a BlockId, + /// The name of the function that should be called. + pub function: &'static str, + /// An optional native call that calls the `function`. This is an optimization to call into a + /// native runtime without requiring to encode/decode the parameters. The native runtime can + /// still be called when this value is `None`, we then just fallback to encoding/decoding the + /// parameters. + pub native_call: Option, + /// The encoded arguments of the function. + pub arguments: Vec, + /// The overlayed changes that are on top of the state. + pub overlayed_changes: &'a RefCell, + /// The cache for storage transactions. + pub storage_transaction_cache: &'a RefCell>, + /// Determines if the function requires that `initialize_block` should be called before calling + /// the actual function. + pub initialize_block: InitializeBlock<'a, Block>, + /// The context this function is executed in. + pub context: ExecutionContext, + /// The optional proof recorder for recording storage accesses. + pub recorder: &'a Option>, +} + +/// Something that can call into the an api at a given block. +#[cfg(feature = "std")] +pub trait CallApiAt { + /// Error type used by the implementation. + type Error: std::fmt::Debug + From; + + /// The state backend that is used to store the block states. + type StateBackend: StateBackend>; + + /// Calls the given api function with the given encoded arguments at the given block and returns + /// the encoded result. + fn call_api_at< + 'a, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + C: Core, + >( + &self, + params: CallApiAtParams<'a, Block, C, NC, Self::StateBackend>, + ) -> Result, Self::Error>; + + /// Returns the runtime version at the given block. + fn runtime_version_at(&self, at: &BlockId) -> Result; +} + +/// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. +#[cfg(feature = "std")] +pub struct ApiRef<'a, T>(T, std::marker::PhantomData<&'a ()>); + +#[cfg(feature = "std")] +impl<'a, T> From for ApiRef<'a, T> { + fn from(api: T) -> Self { + ApiRef(api, Default::default()) + } +} + +#[cfg(feature = "std")] +impl<'a, T> std::ops::Deref for ApiRef<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[cfg(feature = "std")] +impl<'a, T> std::ops::DerefMut for ApiRef<'a, T> { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +/// Something that provides a runtime api. +#[cfg(feature = "std")] +pub trait ProvideRuntimeApi { + /// The concrete type that provides the api. + type Api: ApiExt; + + /// Returns the runtime api. + /// The returned instance will keep track of modifications to the storage. Any successful + /// call to an api function, will `commit` its changes to an internal buffer. Otherwise, + /// the modifications will be `discarded`. The modifications will not be applied to the + /// storage, even on a `commit`. + fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api>; +} + +/// Something that provides information about a runtime api. +#[cfg(feature = "std")] +pub trait RuntimeApiInfo { + /// The identifier of the runtime api. + const ID: [u8; 8]; + /// The version of the runtime api. + const VERSION: u32; +} + +/// Extracts the `Api::Error` for a type that provides a runtime api. +#[cfg(feature = "std")] +pub type ApiErrorFor = <>::Api as ApiErrorExt>::Error; + +decl_runtime_apis! { + /// The `Core` runtime api that every Substrate runtime needs to implement. + #[core_trait] + #[api_version(2)] + pub trait Core { + /// Returns the version of the runtime. + fn version() -> RuntimeVersion; + /// Execute the given block. + #[skip_initialize_block] + fn execute_block(block: Block); + /// Initialize a block with the given header. + #[renamed("initialise_block", 2)] + #[skip_initialize_block] + #[initialize_block] + fn initialize_block(header: &::Header); + } + + /// The `Metadata` api trait that returns metadata for the runtime. + pub trait Metadata { + /// Returns the metadata of a runtime. + fn metadata() -> OpaqueMetadata; + } +} diff --git a/primitives/api/test/Cargo.toml b/primitives/api/test/Cargo.toml new file mode 100644 index 0000000000000..f1f0dfb50f12b --- /dev/null +++ b/primitives/api/test/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "sp-api-test" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-api = { version = "2.0.0", path = "../" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } +sp-version = { version = "2.0.0", path = "../../version" } +sp-runtime = { version = "2.0.0", path = "../../runtime" } +sp-blockchain = { version = "2.0.0", path = "../../blockchain" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +sp-state-machine = { version = "2.0.0", path = "../../../primitives/state-machine" } +trybuild = "1.0.17" +rustversion = "1.0.0" + +[dev-dependencies] +criterion = "0.3.0" +substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } + +[[bench]] +name = "bench" +harness = false + +# We only need this to generate the correct code. +[features] +default = [ "std" ] +std = [] diff --git a/primitives/api/test/benches/bench.rs b/primitives/api/test/benches/bench.rs new file mode 100644 index 0000000000000..9a90ca6e38b85 --- /dev/null +++ b/primitives/api/test/benches/bench.rs @@ -0,0 +1,73 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use criterion::{Criterion, criterion_group, criterion_main}; +use substrate_test_runtime_client::{ + DefaultTestClientBuilderExt, TestClientBuilder, + TestClientBuilderExt, runtime::TestAPI, +}; +use sp_runtime::generic::BlockId; +use sp_state_machine::ExecutionStrategy; +use sp_api::ProvideRuntimeApi; + +fn sp_api_benchmark(c: &mut Criterion) { + c.bench_function("add one with same runtime api", |b| { + let client = substrate_test_runtime_client::new(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.chain_info().best_number); + + b.iter(|| runtime_api.benchmark_add_one(&block_id, &1)) + }); + + c.bench_function("add one with recreating runtime api", |b| { + let client = substrate_test_runtime_client::new(); + let block_id = BlockId::Number(client.chain_info().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 = substrate_test_runtime_client::new(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.chain_info().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 = substrate_test_runtime_client::new(); + let block_id = BlockId::Number(client.chain_info().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 = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::AlwaysWasm).build(); + let block_id = BlockId::Number(client.chain_info().best_number); + b.iter(|| client.runtime_api().benchmark_indirect_call(&block_id).unwrap()) + }); + + c.bench_function("calling function in wasm", |b| { + let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::AlwaysWasm).build(); + let block_id = BlockId::Number(client.chain_info().best_number); + b.iter(|| client.runtime_api().benchmark_direct_call(&block_id).unwrap()) + }); +} + +criterion_group!(benches, sp_api_benchmark); +criterion_main!(benches); diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs new file mode 100644 index 0000000000000..d5a668dec1245 --- /dev/null +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -0,0 +1,131 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sp_api::{RuntimeApiInfo, decl_runtime_apis, impl_runtime_apis}; + +use sp_runtime::{traits::{GetNodeBlockType, Block as BlockT}, generic::BlockId}; + +use substrate_test_runtime_client::runtime::Block; +use sp_blockchain::Result; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +pub struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + fn something_with_block(block: Block) -> Block; + fn function_with_two_args(data: u64, block: Block); + fn same_name(); + fn wild_card(_: u32); + } + + #[api_version(2)] + pub trait ApiWithCustomVersion { + fn same_name(); + #[changed_in(2)] + fn same_name() -> String; + } +} + +impl_runtime_apis! { + impl self::Api for Runtime { + fn test(_: u64) { + unimplemented!() + } + + fn something_with_block(_: Block) -> Block { + unimplemented!() + } + + fn function_with_two_args(_: u64, _: Block) { + unimplemented!() + } + + fn same_name() {} + + fn wild_card(_: u32) {} + } + + impl self::ApiWithCustomVersion for Runtime { + fn same_name() {} + } + + impl sp_api::Core for Runtime { + fn version() -> sp_version::RuntimeVersion { + unimplemented!() + } + fn execute_block(_: Block) { + unimplemented!() + } + fn initialize_block(_: &::Header) { + unimplemented!() + } + } +} + +type TestClient = substrate_test_runtime_client::sc_client::Client< + substrate_test_runtime_client::Backend, + substrate_test_runtime_client::Executor, + Block, + RuntimeApi, +>; + +#[test] +fn test_client_side_function_signature() { + 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] +fn check_runtime_api_info() { + assert_eq!(&Api::::ID, &runtime_decl_for_Api::ID); + assert_eq!(Api::::VERSION, runtime_decl_for_Api::VERSION); + assert_eq!(Api::::VERSION, 1); + + assert_eq!( + ApiWithCustomVersion::::VERSION, + runtime_decl_for_ApiWithCustomVersion::VERSION, + ); + assert_eq!( + &ApiWithCustomVersion::::ID, + &runtime_decl_for_ApiWithCustomVersion::ID, + ); + assert_eq!(ApiWithCustomVersion::::VERSION, 2); +} + +fn check_runtime_api_versions_contains() { + assert!(RUNTIME_API_VERSIONS.iter().any(|v| v == &(T::ID, T::VERSION))); +} + +#[test] +fn check_runtime_api_versions() { + check_runtime_api_versions_contains::>(); + check_runtime_api_versions_contains::>(); + check_runtime_api_versions_contains::>(); +} diff --git a/core/sr-api-macros/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs similarity index 82% rename from core/sr-api-macros/tests/runtime_calls.rs rename to primitives/api/test/tests/runtime_calls.rs index ce6300bc41282..f45df7c517254 100644 --- a/core/sr-api-macros/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,27 +14,25 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use test_client::{ +use sp_api::ProvideRuntimeApi; +use substrate_test_runtime_client::{ prelude::*, DefaultTestClientBuilderExt, TestClientBuilder, runtime::{TestAPI, DecodeFails, Transfer, Header}, }; -use sr_primitives::{ - generic::BlockId, - traits::{ProvideRuntimeApi, Header as HeaderT, Hash as HashT}, -}; -use state_machine::{ +use sp_runtime::{generic::BlockId, traits::{Header as HeaderT, Hash as HashT}}; +use sp_state_machine::{ ExecutionStrategy, create_proof_check_backend, execution_proof_check_on_trie_backend, }; -use consensus_common::SelectChain; +use sp_consensus::SelectChain; use codec::Encode; fn calling_function_with_strat(strat: ExecutionStrategy) { let client = TestClientBuilder::new().set_execution_strategy(strat).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert_eq!(runtime_api.benchmark_add_one(&block_id, &1).unwrap(), 2); } @@ -57,7 +55,7 @@ fn calling_wasm_runtime_function() { fn calling_native_runtime_function_with_non_decodable_parameter() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); runtime_api.fail_convert_parameter(&block_id, DecodeFails::new()).unwrap(); } @@ -66,7 +64,7 @@ fn calling_native_runtime_function_with_non_decodable_parameter() { fn calling_native_runtime_function_with_non_decodable_return_value() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); runtime_api.fail_convert_return_value(&block_id).unwrap(); } @@ -74,7 +72,7 @@ fn calling_native_runtime_function_with_non_decodable_return_value() { fn calling_native_runtime_signature_changed_function() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert_eq!(runtime_api.function_signature_changed(&block_id).unwrap(), 1); } @@ -83,7 +81,7 @@ fn calling_native_runtime_signature_changed_function() { fn calling_wasm_runtime_signature_changed_old_function() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::AlwaysWasm).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); #[allow(deprecated)] let res = runtime_api.function_signature_changed_before_version_2(&block_id).unwrap(); @@ -94,7 +92,7 @@ fn calling_wasm_runtime_signature_changed_old_function() { fn calling_with_both_strategy_and_fail_on_wasm_should_return_error() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert!(runtime_api.fail_on_wasm(&block_id).is_err()); } @@ -102,7 +100,7 @@ fn calling_with_both_strategy_and_fail_on_wasm_should_return_error() { fn calling_with_both_strategy_and_fail_on_native_should_work() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert_eq!(runtime_api.fail_on_native(&block_id).unwrap(), 1); } @@ -111,7 +109,7 @@ fn calling_with_both_strategy_and_fail_on_native_should_work() { fn calling_with_native_else_wasm_and_fail_on_wasm_should_work() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeElseWasm).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert_eq!(runtime_api.fail_on_wasm(&block_id).unwrap(), 1); } @@ -119,7 +117,7 @@ fn calling_with_native_else_wasm_and_fail_on_wasm_should_work() { fn calling_with_native_else_wasm_and_fail_on_native_should_work() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeElseWasm).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert_eq!(runtime_api.fail_on_native(&block_id).unwrap(), 1); } @@ -127,7 +125,7 @@ fn calling_with_native_else_wasm_and_fail_on_native_should_work() { fn use_trie_function() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::AlwaysWasm).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert_eq!(runtime_api.use_trie(&block_id).unwrap(), 2); } @@ -135,7 +133,7 @@ fn use_trie_function() { fn initialize_block_works() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert_eq!(runtime_api.get_block_number(&block_id).unwrap(), 1); } @@ -143,7 +141,7 @@ fn initialize_block_works() { fn initialize_block_is_called_only_once() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert_eq!(runtime_api.take_block_number(&block_id).unwrap(), Some(1)); assert_eq!(runtime_api.take_block_number(&block_id).unwrap(), None); } @@ -152,7 +150,7 @@ fn initialize_block_is_called_only_once() { fn initialize_block_is_skipped() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build(); let runtime_api = client.runtime_api(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); assert!(runtime_api.without_initialize_block(&block_id).unwrap()); } @@ -162,7 +160,7 @@ fn record_proof_works() { .set_execution_strategy(ExecutionStrategy::Both) .build_with_longest_chain(); - let block_id = BlockId::Number(client.info().chain.best_number); + let block_id = BlockId::Number(client.chain_info().best_number); let storage_root = longest_chain.best_chain().unwrap().state_root().clone(); let transaction = Transfer { @@ -174,10 +172,10 @@ fn record_proof_works() { // Build the block and record proof let mut builder = client - .new_block_at_with_proof_recording(&block_id, Default::default()) + .new_block_at(&block_id, Default::default(), true) .expect("Creates block builder"); builder.push(transaction.clone()).unwrap(); - let (block, proof) = builder.bake_and_extract_proof().expect("Bake block"); + let (block, _, proof) = builder.build().expect("Bake block").into_inner(); let backend = create_proof_check_backend::<<

{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone() + } + } +} + pub fn extract_type_option(typ: &syn::Type) -> Option { if let syn::Type::Path(ref path) = typ { let v = path.path.segments.last()?; - if v.value().ident == "Option" { + if v.ident == "Option" { // Option has only one type argument in angle bracket. - if let syn::PathArguments::AngleBracketed(a) = &v.value().arguments { - if let syn::GenericArgument::Type(typ) = a.args.last()?.value() { + if let syn::PathArguments::AngleBracketed(a) = &v.arguments { + if let syn::GenericArgument::Type(typ) = a.args.last()? { return Some(typ.clone()) } } @@ -230,7 +243,7 @@ impl<'ast> Visit<'ast> for ContainsIdent<'ast> { } fn visit_macro(&mut self, input: &'ast syn::Macro) { - self.visit_tokenstream(input.tts.clone()); + self.visit_tokenstream(input.tokens.clone()); visit::visit_macro(self, input); } } diff --git a/srml/support/src/debug.rs b/frame/support/src/debug.rs similarity index 92% rename from srml/support/src/debug.rs rename to frame/support/src/debug.rs index 1c4e463bf1234..0316fb979725c 100644 --- a/srml/support/src/debug.rs +++ b/frame/support/src/debug.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ //! this that are described below. //! //! First component to utilize debug-printing and loggin is actually -//! located in `primitives` crate: `primitives::RuntimeDebug`. +//! located in `primitives` crate: `sp_core::RuntimeDebug`. //! This custom-derive generates `core::fmt::Debug` implementation, //! just like regular `derive(Debug)`, however it does not generate //! any code when the code is compiled to WASM. This means that @@ -35,9 +35,9 @@ //! that WASM debug formatting of structs will be empty. //! //! ```rust,no_run -//! use srml_support::debug; +//! use frame_support::debug; //! -//! #[derive(primitives::RuntimeDebug)] +//! #[derive(sp_core::RuntimeDebug)] //! struct MyStruct { //! a: u64, //! } @@ -66,9 +66,9 @@ //! logs conditionally and strips out logs in WASM. //! //! ```rust,no_run -//! use srml_support::debug::native; +//! use frame_support::debug::native; //! -//! #[derive(primitives::RuntimeDebug)] +//! #[derive(sp_core::RuntimeDebug)] //! struct MyStruct { //! a: u64, //! } @@ -86,8 +86,8 @@ //! native::print!("My struct: {:?}", x); //! ``` -use rstd::vec::Vec; -use rstd::fmt::{self, Debug}; +use sp_std::vec::Vec; +use sp_std::fmt::{self, Debug}; pub use log::{info, debug, error, trace, warn}; pub use crate::runtime_print as print; @@ -120,6 +120,12 @@ pub mod native { } /// Print out a formatted message. +/// +/// # Example +/// +/// ``` +/// frame_support::runtime_print!("my value is {}", 3); +/// ``` #[macro_export] macro_rules! runtime_print { ($($arg:tt)+) => { @@ -149,7 +155,7 @@ impl fmt::Write for Writer { impl Writer { /// Print the content of this `Writer` out. pub fn print(&self) { - runtime_io::print_utf8(&self.0) + sp_io::misc::print_utf8(&self.0) } } @@ -198,9 +204,9 @@ impl log::Log for RuntimeLogger { let mut w = Writer::default(); let _ = core::write!(&mut w, "{}", record.args()); - runtime_io::log( + sp_io::logging::log( record.level().into(), - record.target().as_bytes(), + record.target(), &w.0, ); } diff --git a/srml/support/src/dispatch.rs b/frame/support/src/dispatch.rs similarity index 83% rename from srml/support/src/dispatch.rs rename to frame/support/src/dispatch.rs index df86f436117a1..b2d7e6e1d409e 100644 --- a/srml/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,27 +17,21 @@ //! Dispatch system. Contains a macro for defining runtime modules and //! generating values representing lazy module function calls. -pub use crate::rstd::{result, fmt, prelude::{Vec, Clone, Eq, PartialEq}, marker}; +pub use crate::sp_std::{result, fmt, prelude::{Vec, Clone, Eq, PartialEq}, marker}; pub use crate::codec::{Codec, EncodeLike, Decode, Encode, Input, Output, HasCompact, EncodeAsRef}; -pub use srml_metadata::{ +pub use frame_metadata::{ FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata, ModuleConstantMetadata, DefaultByte, DefaultByteGetter, ModuleErrorMetadata, ErrorMetadata }; -pub use sr_primitives::{ - weights::{ - SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, - TransactionPriority - }, - traits::{Dispatchable, DispatchResult, ModuleDispatchError}, - DispatchError, +pub use crate::weights::{ + SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, + TransactionPriority, Weight, WeighBlock, PaysFee, }; +pub use sp_runtime::{traits::Dispatchable, DispatchError, DispatchResult}; /// A type that cannot be instantiated. pub enum Never {} -/// Result with string error message. This exists for backward compatibility purpose. -pub type Result = DispatchResult<&'static str>; - /// Serializable version of Dispatchable. /// This value can be used as a "function" in an extrinsic. pub trait Callable { @@ -48,6 +42,9 @@ pub trait Callable { // https://github.com/rust-lang/rust/issues/51331 pub type CallableCallFor = >::Call; +/// A type that can be used as a parameter in a dispatchable function. +/// +/// When using `decl_module` all arguments for call functions must implement this trait. pub trait Parameter: Codec + EncodeLike + Clone + Eq + fmt::Debug {} impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} @@ -57,22 +54,22 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// /// ``` /// # #[macro_use] -/// # extern crate srml_support; -/// # use srml_support::dispatch::Result; -/// # use srml_system::{self as system, Trait, ensure_signed}; +/// # extern crate frame_support; +/// # use frame_support::dispatch; +/// # use frame_system::{self as system, Trait, ensure_signed}; /// decl_module! { /// pub struct Module for enum Call where origin: T::Origin { /// /// // Private functions are dispatchable, but not available to other /// // SRML modules. -/// fn my_function(origin, var: u64) -> Result { +/// fn my_function(origin, var: u64) -> dispatch::DispatchResult { /// // Your implementation /// Ok(()) /// } /// /// // Public functions are both dispatchable and available to other /// // SRML modules. -/// pub fn my_public_function(origin) -> Result { +/// pub fn my_public_function(origin) -> dispatch::DispatchResult { /// // Your implementation /// Ok(()) /// } @@ -92,18 +89,18 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// /// ### Shorthand Example /// -/// The macro automatically expands a shorthand function declaration to return the `Result` type. -/// These functions are the same: +/// The macro automatically expands a shorthand function declaration to return the +/// [`DispatchResult`] type. These functions are the same: /// /// ``` /// # #[macro_use] -/// # extern crate srml_support; -/// # use srml_support::dispatch::Result; -/// # use srml_system::{self as system, Trait, ensure_signed}; +/// # extern crate frame_support; +/// # use frame_support::dispatch; +/// # use frame_system::{self as system, Trait, ensure_signed}; /// decl_module! { /// pub struct Module for enum Call where origin: T::Origin { /// -/// fn my_long_function(origin) -> Result { +/// fn my_long_function(origin) -> dispatch::DispatchResult { /// // Your implementation /// Ok(()) /// } @@ -122,12 +119,12 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// /// ``` /// # #[macro_use] -/// # extern crate srml_support; -/// # use srml_support::dispatch::Result; -/// # use srml_system::{self as system, Trait, ensure_signed, ensure_root}; +/// # extern crate frame_support; +/// # use frame_support::dispatch; +/// # use frame_system::{self as system, Trait, ensure_signed, ensure_root}; /// decl_module! { /// pub struct Module for enum Call where origin: T::Origin { -/// fn my_privileged_function(origin) -> Result { +/// fn my_privileged_function(origin) -> dispatch::DispatchResult { /// ensure_root(origin)?; /// // Your implementation /// Ok(()) @@ -140,15 +137,15 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// ## Multiple Module Instances Example /// /// A Substrate module can be built such that multiple instances of the same module can be used within a single -/// runtime. For example, the [Balances module](../srml_balances/index.html) can be added multiple times to your +/// runtime. For example, the [Balances module](../pallet_balances/index.html) can be added multiple times to your /// runtime in order to support multiple, independent currencies for your blockchain. Here is an example of how /// you would declare such a module using the `decl_module!` macro: /// /// ``` /// # #[macro_use] -/// # extern crate srml_support; -/// # use srml_support::dispatch::Result; -/// # use srml_system::{self as system, ensure_signed}; +/// # extern crate frame_support; +/// # use frame_support::dispatch; +/// # use frame_system::{self as system, ensure_signed}; /// # pub struct DefaultInstance; /// # pub trait Instance {} /// # impl Instance for DefaultInstance {} @@ -174,9 +171,9 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// /// ``` /// # #[macro_use] -/// # extern crate srml_support; -/// # use srml_support::dispatch::Result; -/// # use srml_system::{self as system, ensure_signed}; +/// # extern crate frame_support; +/// # use frame_support::dispatch; +/// # use frame_system::{self as system, ensure_signed}; /// pub trait Trait: system::Trait where Self::AccountId: From {} /// /// decl_module! { @@ -192,19 +189,19 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// The following are reserved function signatures: /// /// * `deposit_event`: Helper function for depositing an [event](https://docs.substrate.dev/docs/event-enum). -/// The default behavior is to call `deposit_event` from the [System module](../srml_system/index.html). +/// The default behavior is to call `deposit_event` from the [System module](../frame_system/index.html). /// However, you can write your own implementation for events in your runtime. To use the default behavior, /// add `fn deposit_event() = default;` to your `Module`. /// /// The following reserved functions also take the block number (with type `T::BlockNumber`) as an optional input: /// /// * `on_initialize`: Executes at the beginning of a block. Using this function will -/// implement the [`OnInitialize`](../sr_primitives/traits/trait.OnInitialize.html) trait. +/// implement the [`OnInitialize`](../sp_runtime/traits/trait.OnInitialize.html) trait. /// * `on_finalize`: Executes at the end of a block. Using this function will -/// implement the [`OnFinalize`](../sr_primitives/traits/trait.OnFinalize.html) trait. +/// implement the [`OnFinalize`](../sp_runtime/traits/trait.OnFinalize.html) trait. /// * `offchain_worker`: Executes at the beginning of a block and produces extrinsics for a future block /// upon completion. Using this function will implement the -/// [`OffchainWorker`](../sr_primitives/traits/trait.OffchainWorker.html) trait. +/// [`OffchainWorker`](../sp_runtime/traits/trait.OffchainWorker.html) trait. #[macro_export] macro_rules! decl_module { // Entry point #1. @@ -320,6 +317,7 @@ macro_rules! decl_module { "`deposit_event` function is reserved and must follow the syntax: `$vis:vis fn deposit_event() = default;`" ); }; + // Add on_finalize, without a given weight. (@normalize $(#[$attr:meta])* pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> @@ -343,7 +341,10 @@ macro_rules! decl_module { { $( $other_where_bounds )* } { $( $deposit_event )* } { $( $on_initialize )* } - { fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } } + { + #[weight = $crate::dispatch::SimpleDispatchInfo::zero()] + fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } + } { $( $offchain )* } { $( $constants )* } { $( $error_type )* } @@ -351,12 +352,51 @@ macro_rules! decl_module { $($rest)* ); }; + // Add on_finalize, given weight. (@normalize $(#[$attr:meta])* pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident { $( $other_where_bounds:tt )* } { $( $deposit_event:tt )* } + { $( $on_initialize:tt )* } + {} + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + #[weight = $weight:expr] + fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> + for enum $call_type where origin: $origin_type, system = $system + { $( $other_where_bounds )* } + { $( $deposit_event )* } + { $( $on_initialize )* } + { + #[weight = $weight] + fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } + } + { $( $offchain )* } + { $( $constants )* } + { $( $error_type )* } + [ $( $dispatchables )* ] + $($rest)* + ); + }; + // Add on_initialize, without a given weight. + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident< + $trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)? + > + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $other_where_bounds:tt )* } + { $( $deposit_event:tt )* } {} { $( $on_finalize:tt )* } { $( $offchain:tt )* } @@ -373,7 +413,48 @@ macro_rules! decl_module { for enum $call_type where origin: $origin_type, system = $system { $( $other_where_bounds )* } { $( $deposit_event )* } - { fn on_initialize( $( $param_name : $param ),* ) { $( $impl )* } } + { + #[weight = $crate::dispatch::SimpleDispatchInfo::zero()] + fn on_initialize( $( $param_name : $param ),* ) { $( $impl )* } + } + { $( $on_finalize )* } + { $( $offchain )* } + { $( $constants )* } + { $( $error_type )* } + [ $( $dispatchables )* ] + $($rest)* + ); + }; + // Add on_initialize, given weight. + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident< + $trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)? + > + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $other_where_bounds:tt )* } + { $( $deposit_event:tt )* } + {} + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { $( $error_type:tt )* } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + #[weight = $weight:expr] + fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> + for enum $call_type where origin: $origin_type, system = $system + { $( $other_where_bounds )* } + { $( $deposit_event )* } + { + #[weight = $weight] + fn on_initialize( $( $param_name : $param ),* ) { $( $impl )* } + } { $( $on_finalize )* } { $( $offchain )* } { $( $constants )* } @@ -770,26 +851,44 @@ macro_rules! decl_module { (@impl_on_initialize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } + #[weight = $weight:expr] fn on_initialize() { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OnInitialize<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OnInitialize<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { - fn on_initialize(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } + fn on_initialize(_block_number_not_used: $trait_instance::BlockNumber) { + use $crate::sp_std::if_std; + if_std! { + use $crate::tracing; + let span = tracing::span!(tracing::Level::DEBUG, "on_initialize"); + let _enter = span.enter(); + } + { $( $impl )* } + } } }; (@impl_on_initialize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } + #[weight = $weight:expr] fn on_initialize($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OnInitialize<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OnInitialize<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { - fn on_initialize($param: $param_ty) { $( $impl )* } + fn on_initialize($param: $param_ty) { + use $crate::sp_std::if_std; + if_std! { + use $crate::tracing; + let span = tracing::span!(tracing::Level::DEBUG, "on_initialize"); + let _enter = span.enter(); + } + { $( $impl )* } + } } }; @@ -798,7 +897,7 @@ macro_rules! decl_module { { $( $other_where_bounds:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OnInitialize<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OnInitialize<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* {} }; @@ -806,26 +905,44 @@ macro_rules! decl_module { (@impl_on_finalize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } + #[weight = $weight:expr] fn on_finalize() { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OnFinalize<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OnFinalize<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { - fn on_finalize(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } + fn on_finalize(_block_number_not_used: $trait_instance::BlockNumber) { + use $crate::sp_std::if_std; + if_std! { + use $crate::tracing; + let span = tracing::span!(tracing::Level::DEBUG, "on_finalize"); + let _enter = span.enter(); + } + { $( $impl )* } + } } }; (@impl_on_finalize $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } + #[weight = $weight:expr] fn on_finalize($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OnFinalize<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OnFinalize<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { - fn on_finalize($param: $param_ty) { $( $impl )* } + fn on_finalize($param: $param_ty) { + use $crate::sp_std::if_std; + if_std! { + use $crate::tracing; + let span = tracing::span!(tracing::Level::DEBUG, "on_finalize"); + let _enter = span.enter(); + } + { $( $impl )* } + } } }; @@ -834,22 +951,51 @@ macro_rules! decl_module { { $( $other_where_bounds:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OnFinalize<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OnFinalize<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { } }; + (@impl_block_hooks_weight + $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; + { $( $other_where_bounds:tt )* } + @init $( + #[weight = $weight_initialize:expr] + fn on_initialize($( $param_initialize:ident : $param_ty_initialize:ty )*) { $( $impl_initialize:tt )* } + )? + @fin $( + #[weight = $weight_finalize:expr] + fn on_finalize($( $param_finalize:ident : $param_ty_finalize:ty )*) { $( $impl_finalize:tt )* } + )? + ) => { + impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> + $crate::dispatch::WeighBlock<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where + $( $other_where_bounds )* + { + $( + fn on_initialize(n: $trait_instance::BlockNumber) -> $crate::dispatch::Weight { + >::weigh_data(&$weight_initialize, n) + } + )? + $( + fn on_finalize(n: $trait_instance::BlockNumber) -> $crate::dispatch::Weight { + >::weigh_data(&$weight_finalize, n) + } + )? + } + }; + (@impl_offchain $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; { $( $other_where_bounds:tt )* } fn offchain_worker() { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OffchainWorker<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OffchainWorker<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { - fn generate_extrinsics(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } + fn offchain_worker(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* } } }; @@ -859,10 +1005,10 @@ macro_rules! decl_module { fn offchain_worker($param:ident : $param_ty:ty) { $( $impl:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OffchainWorker<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OffchainWorker<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* { - fn generate_extrinsics($param: $param_ty) { $( $impl )* } + fn offchain_worker($param: $param_ty) { $( $impl )* } } }; @@ -871,7 +1017,7 @@ macro_rules! decl_module { { $( $other_where_bounds:tt )* } ) => { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> - $crate::sr_primitives::traits::OffchainWorker<$trait_instance::BlockNumber> + $crate::sp_runtime::traits::OffchainWorker<$trait_instance::BlockNumber> for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )* {} }; @@ -891,10 +1037,16 @@ macro_rules! decl_module { #[allow(unreachable_code)] $vis fn $name( $origin: $origin_ty $(, $param: $param_ty )* - ) -> $crate::dispatch::DispatchResult<$error_type> { - { $( $impl )* } - // May be unreachable. - Ok(()) + ) -> $crate::dispatch::DispatchResult { + $crate::sp_std::if_std! { + use $crate::tracing; + let span = tracing::span!(tracing::Level::DEBUG, stringify!($name)); + let _enter = span.enter(); + } + { + { $( $impl )* } + Ok(()) + } } }; @@ -911,13 +1063,18 @@ macro_rules! decl_module { ) => { $(#[doc = $doc_attr])* $vis fn $name($origin: $origin_ty $(, $param: $param_ty )* ) -> $result { - $( $impl )* + use $crate::sp_std::if_std; + if_std! { + use $crate::tracing; + let span = tracing::span!(tracing::Level::DEBUG, stringify!($name)); + let _enter = span.enter(); + } + { $( $impl )* } } }; // Declare a `Call` variant parameter that should be encoded `compact`. (@create_call_enum - $( #[$attr:meta] )* $call_type:ident; <$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> { $( $other_where_bounds:tt )* } @@ -931,7 +1088,6 @@ macro_rules! decl_module { ) => { $crate::decl_module! { @create_call_enum - $( #[$attr] )* $call_type; <$trait_instance: $trait_name $(, $instance: $instantiable $(= $module_default_instance)? )?> { $( $other_where_bounds )* } @@ -949,7 +1105,6 @@ macro_rules! decl_module { // Declare a `Call` variant parameter. (@create_call_enum - $( #[$attr:meta] )* $call_type:ident; <$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> { $( $other_where_bounds:tt )* } @@ -962,7 +1117,6 @@ macro_rules! decl_module { ) => { $crate::decl_module! { @create_call_enum - $( #[$attr] )* $call_type; <$trait_instance: $trait_name $(, $instance: $instantiable $(= $module_default_instance)? )?> { $( $other_where_bounds )* } @@ -978,7 +1132,6 @@ macro_rules! decl_module { }; (@create_call_enum - $( #[$attr:meta] )* $call_type:ident; <$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> { $( $other_where_bounds:tt )* } @@ -993,7 +1146,6 @@ macro_rules! decl_module { ) => { $crate::decl_module! { @create_call_enum - $( #[$attr] )* $call_type; <$trait_instance: $trait_name $(, $instance: $instantiable $(= $module_default_instance)? )?> { $( $other_where_bounds )* } @@ -1014,21 +1166,22 @@ macro_rules! decl_module { }; (@create_call_enum - $( #[$attr:meta] )* $call_type:ident; <$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?> { $( $other_where_bounds:tt )* } { $( $generated_variants:tt )* } {} ) => { + /// Dispatchable calls. + /// + /// Each variant of this enum maps to a dispatchable function from the associated module. #[derive($crate::codec::Encode, $crate::codec::Decode)] - $( #[$attr] )* pub enum $call_type<$trait_instance: $trait_name$(, $instance: $instantiable $( = $module_default_instance)?)?> where $( $other_where_bounds )* { #[doc(hidden)] #[codec(skip)] - __PhantomItem($crate::rstd::marker::PhantomData<($trait_instance $(, $instance)?)>, $crate::dispatch::Never), + __PhantomItem($crate::sp_std::marker::PhantomData<($trait_instance, $($instance)?)>, $crate::dispatch::Never), $( $generated_variants )* } }; @@ -1063,10 +1216,11 @@ macro_rules! decl_module { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Copy, PartialEq, Eq, $crate::RuntimeDebug)] + $( #[$attr] )* pub struct $mod_type< $trait_instance: $trait_name $(, $instance: $instantiable $( = $module_default_instance)?)? - >($crate::rstd::marker::PhantomData<($trait_instance $(, $instance)?)>) where + >($crate::sp_std::marker::PhantomData<($trait_instance, $( $instance)?)>) where $( $other_where_bounds )*; $crate::decl_module! { @@ -1083,6 +1237,14 @@ macro_rules! decl_module { $( $on_finalize )* } + $crate::decl_module! { + @impl_block_hooks_weight + $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; + { $( $other_where_bounds )* } + @init $( $on_initialize )* + @fin $( $on_finalize )* + } + $crate::decl_module! { @impl_offchain $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?>; @@ -1120,7 +1282,6 @@ macro_rules! decl_module { $crate::decl_module! { @create_call_enum - $( #[$attr] )* $call_type; <$trait_instance: $trait_name $(, $instance: $instantiable $(= $module_default_instance)? )?> { $( $other_where_bounds )* } @@ -1151,7 +1312,11 @@ macro_rules! decl_module { &$weight, ($( $param_name, )*) ); - return $crate::dispatch::DispatchInfo { weight, class }; + let pays_fee = >::pays_fee( + &$weight, + ($( $param_name, )*) + ); + return $crate::dispatch::DispatchInfo { weight, class, pays_fee }; } if let $call_type::__PhantomItem(_, _) = self { unreachable!("__PhantomItem should never be used.") } )* @@ -1167,7 +1332,11 @@ macro_rules! decl_module { &$crate::dispatch::SimpleDispatchInfo::default(), () ); - $crate::dispatch::DispatchInfo { weight, class } + let pays_fee = >::pays_fee( + &$crate::dispatch::SimpleDispatchInfo::default(), + () + ); + $crate::dispatch::DispatchInfo { weight, class, pays_fee } } } @@ -1238,8 +1407,7 @@ macro_rules! decl_module { { type Trait = $trait_instance; type Origin = $origin_type; - type Error = $error_type; - fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResult { + fn dispatch(self, _origin: Self::Origin) -> $crate::sp_runtime::DispatchResult { match self { $( $call_type::$fn_name( $( $param_name ),* ) => { @@ -1267,7 +1435,7 @@ macro_rules! decl_module { pub fn dispatch>( d: D, origin: D::Origin - ) -> $crate::dispatch::DispatchResult { + ) -> $crate::sp_runtime::DispatchResult { d.dispatch(origin) } } @@ -1335,11 +1503,10 @@ macro_rules! impl_outer_dispatch { impl $crate::dispatch::Dispatchable for $call_type { type Origin = $origin; type Trait = $call_type; - type Error = $crate::dispatch::DispatchError; fn dispatch( self, origin: $origin, - ) -> $crate::dispatch::DispatchResult<$crate::dispatch::DispatchError> { + ) -> $crate::sp_runtime::DispatchResult { $crate::impl_outer_dispatch! { @DISPATCH_MATCH self @@ -1386,11 +1553,7 @@ macro_rules! impl_outer_dispatch { $origin { $( $generated )* - $call_type::$name(call) => call.dispatch($origin).map_err(|e| { - let mut error: $crate::dispatch::DispatchError = e.into(); - error.module = Some($index); - error - }), + $call_type::$name(call) => call.dispatch($origin), } $index + 1; $( $rest ),* @@ -1505,7 +1668,7 @@ macro_rules! __impl_module_constants_metadata { , $const_instance: $const_instantiable )? >($crate::dispatch::marker::PhantomData< - ($const_trait_instance $(, $const_instance)?) + ($const_trait_instance, $( $const_instance)?) >); impl<$const_trait_instance: 'static + $const_trait_name $( , $const_instance: $const_instantiable)? @@ -1706,8 +1869,8 @@ macro_rules! __check_reserved_fn_name { #[allow(dead_code)] mod tests { use super::*; - use crate::sr_primitives::traits::{OnInitialize, OnFinalize}; - use sr_primitives::weights::{DispatchInfo, DispatchClass}; + use crate::sp_runtime::traits::{OnInitialize, OnFinalize}; + use crate::weights::{DispatchInfo, DispatchClass}; pub trait Trait: system::Trait + Sized where Self::AccountId: From { type Origin; @@ -1716,29 +1879,39 @@ mod tests { } pub mod system { - use super::Result; + use super::*; pub trait Trait { type AccountId; } - pub fn ensure_root(_: R) -> Result { + pub fn ensure_root(_: R) -> DispatchResult { Ok(()) } } + struct BLockWeight; + impl> WeighData for BLockWeight { + fn weigh_data(&self, target: BlockNumber) -> Weight { + let target: u32 = target.into(); + if target % 2 == 0 { 10 } else { 0 } + } + } + decl_module! { pub struct Module for enum Call where origin: T::Origin, T::AccountId: From { /// Hi, this is a comment. - fn aux_0(_origin) -> Result { unreachable!() } - fn aux_1(_origin, #[compact] _data: u32,) -> Result { unreachable!() } - fn aux_2(_origin, _data: i32, _data2: String) -> Result { unreachable!() } + fn aux_0(_origin) -> DispatchResult { unreachable!() } + fn aux_1(_origin, #[compact] _data: u32,) -> DispatchResult { unreachable!() } + fn aux_2(_origin, _data: i32, _data2: String) -> DispatchResult { unreachable!() } #[weight = SimpleDispatchInfo::FixedNormal(3)] - fn aux_3(_origin) -> Result { unreachable!() } - fn aux_4(_origin, _data: i32) -> Result { unreachable!() } - fn aux_5(_origin, _data: i32, #[compact] _data2: u32,) -> Result { unreachable!() } + fn aux_3(_origin) -> DispatchResult { unreachable!() } + fn aux_4(_origin, _data: i32) -> DispatchResult { unreachable!() } + fn aux_5(_origin, _data: i32, #[compact] _data2: u32,) -> DispatchResult { unreachable!() } + #[weight = SimpleDispatchInfo::FixedNormal(7)] fn on_initialize(n: T::BlockNumber,) { if n.into() == 42 { panic!("on_initialize") } } + #[weight = BLockWeight] fn on_finalize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalize") } } fn offchain_worker() {} @@ -1886,17 +2059,29 @@ mod tests { // operational. assert_eq!( Call::::operational().get_dispatch_info(), - DispatchInfo { weight: 5, class: DispatchClass::Operational }, + DispatchInfo { weight: 5, class: DispatchClass::Operational, pays_fee: true }, ); // default weight. assert_eq!( Call::::aux_0().get_dispatch_info(), - DispatchInfo { weight: 10_000, class: DispatchClass::Normal }, + DispatchInfo { weight: 10_000, class: DispatchClass::Normal, pays_fee: true }, ); // custom basic assert_eq!( Call::::aux_3().get_dispatch_info(), - DispatchInfo { weight: 3, class: DispatchClass::Normal }, + DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: true }, ); } + + #[test] + fn weight_for_block_hooks() { + // independent of block number + assert_eq!(>::on_initialize(0), 7); + assert_eq!(>::on_initialize(10), 7); + assert_eq!(>::on_initialize(100), 7); + + // dependent + assert_eq!(>::on_finalize(2), 10); + assert_eq!(>::on_finalize(3), 0); + } } diff --git a/frame/support/src/error.rs b/frame/support/src/error.rs new file mode 100644 index 0000000000000..34de38108f254 --- /dev/null +++ b/frame/support/src/error.rs @@ -0,0 +1,200 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Macro for declaring a module error. + +#[doc(hidden)] +pub use sp_runtime::traits::{LookupError, BadOrigin}; +#[doc(hidden)] +pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent}; + +/// Declare an error type for a runtime module. +/// +/// `decl_error!` supports only variants that do not hold any data. The dispatchable +/// functions return [`DispatchResult`](sp_runtime::DispatchResult). The error type +/// implements `From for DispatchResult` to make the error type usable as error +/// in the dispatchable functions. +/// +/// It is required that the error type is registed in `decl_module!` to make the error +/// exported in the metadata. +/// +/// # Usage +/// +/// ``` +/// # use frame_support::{decl_error, decl_module}; +/// decl_error! { +/// /// Errors that can occur in my module. +/// pub enum MyError for Module { +/// /// Hey this is an error message that indicates bla. +/// MyCoolErrorMessage, +/// /// You are just not cool enough for my module! +/// YouAreNotCoolEnough, +/// } +/// } +/// +/// # use frame_system::{self as system, Trait}; +/// +/// // You need to register the error type in `decl_module!` as well to make the error +/// // exported in the metadata. +/// +/// decl_module! { +/// pub struct Module for enum Call where origin: T::Origin { +/// type Error = MyError; +/// +/// fn do_something(origin) -> frame_support::dispatch::DispatchResult { +/// Err(MyError::::YouAreNotCoolEnough.into()) +/// } +/// } +/// } +/// +/// # fn main() {} +/// ``` +/// +/// For instantiable modules you also need to give the instance generic type and bound to the +/// error declaration. +#[macro_export] +macro_rules! decl_error { + ( + $(#[$attr:meta])* + pub enum $error:ident + for $module:ident< + $generic:ident: $trait:path + $(, $inst_generic:ident: $instance:path)? + > + { + $( + $( #[doc = $doc_attr:tt] )* + $name:ident + ),* + $(,)? + } + ) => { + $(#[$attr])* + pub enum $error<$generic: $trait $(, $inst_generic: $instance)?> { + #[doc(hidden)] + __Ignore( + $crate::sp_std::marker::PhantomData<($generic, $( $inst_generic)?)>, + $crate::dispatch::Never, + ), + $( + $( #[doc = $doc_attr] )* + $name + ),* + } + + impl<$generic: $trait $(, $inst_generic: $instance)?> $crate::sp_std::fmt::Debug + for $error<$generic $(, $inst_generic)?> + { + fn fmt(&self, f: &mut $crate::sp_std::fmt::Formatter<'_>) -> $crate::sp_std::fmt::Result { + f.write_str(self.as_str()) + } + } + + impl<$generic: $trait $(, $inst_generic: $instance)?> $error<$generic $(, $inst_generic)?> { + fn as_u8(&self) -> u8 { + $crate::decl_error! { + @GENERATE_AS_U8 + self + $error + {} + 0, + $( $name ),* + } + } + + fn as_str(&self) -> &'static str { + match self { + Self::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"), + $( + $error::$name => stringify!($name), + )* + } + } + } + + impl<$generic: $trait $(, $inst_generic: $instance)?> From<$error<$generic $(, $inst_generic)?>> + for &'static str + { + fn from(err: $error<$generic $(, $inst_generic)?>) -> &'static str { + err.as_str() + } + } + + impl<$generic: $trait $(, $inst_generic: $instance)?> From<$error<$generic $(, $inst_generic)?>> + for $crate::sp_runtime::DispatchError + { + fn from(err: $error<$generic $(, $inst_generic)?>) -> Self { + let index = <$generic::ModuleToIndex as $crate::traits::ModuleToIndex> + ::module_to_index::<$module<$generic $(, $inst_generic)?>>() + .expect("Every active module has an index in the runtime; qed") as u8; + + $crate::sp_runtime::DispatchError::Module { + index, + error: err.as_u8(), + message: Some(err.as_str()), + } + } + } + + impl<$generic: $trait $(, $inst_generic: $instance)?> $crate::error::ModuleErrorMetadata + for $error<$generic $(, $inst_generic)?> + { + fn metadata() -> &'static [$crate::error::ErrorMetadata] { + &[ + $( + $crate::error::ErrorMetadata { + name: $crate::error::DecodeDifferent::Encode(stringify!($name)), + documentation: $crate::error::DecodeDifferent::Encode(&[ + $( $doc_attr ),* + ]), + } + ),* + ] + } + } + }; + (@GENERATE_AS_U8 + $self:ident + $error:ident + { $( $generated:tt )* } + $index:expr, + $name:ident + $( , $rest:ident )* + ) => { + $crate::decl_error! { + @GENERATE_AS_U8 + $self + $error + { + $( $generated )* + $error::$name => $index, + } + $index + 1, + $( $rest ),* + } + }; + (@GENERATE_AS_U8 + $self:ident + $error:ident + { $( $generated:tt )* } + $index:expr, + ) => { + match $self { + $error::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"), + $( $generated )* + } + } +} diff --git a/frame/support/src/event.rs b/frame/support/src/event.rs new file mode 100644 index 0000000000000..3ff6d4ab45c2d --- /dev/null +++ b/frame/support/src/event.rs @@ -0,0 +1,831 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +//! 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 . + +pub use frame_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEncode}; + +/// Implement the `Event` for a module. +/// +/// # Simple Event Example: +/// +/// ```rust +/// frame_support::decl_event!( +/// pub enum Event { +/// Success, +/// Failure(String), +/// } +/// ); +/// +///# fn main() {} +/// ``` +/// +/// # Generic Event Example: +/// +/// ```rust +/// trait Trait { +/// type Balance; +/// type Token; +/// } +/// +/// mod event1 { +/// // Event that specifies the generic parameter explicitly (`Balance`). +/// frame_support::decl_event!( +/// pub enum Event where Balance = ::Balance { +/// Message(Balance), +/// } +/// ); +/// } +/// +/// mod event2 { +/// // Event that uses the generic parameter `Balance`. +/// // If no name for the generic parameter is specified explicitly, +/// // the name will be taken from the type name of the trait. +/// frame_support::decl_event!( +/// pub enum Event where ::Balance { +/// Message(Balance), +/// } +/// ); +/// } +/// +/// mod event3 { +/// // And we even support declaring multiple generic parameters! +/// frame_support::decl_event!( +/// pub enum Event where ::Balance, ::Token { +/// Message(Balance, Token), +/// } +/// ); +/// } +/// +///# fn main() {} +/// ``` +/// +/// The syntax for generic events requires the `where`. +/// +/// # Generic Event with Instance Example: +/// +/// ```rust +///# struct DefaultInstance; +///# trait Instance {} +///# impl Instance for DefaultInstance {} +/// trait Trait { +/// type Balance; +/// type Token; +/// } +/// +/// // For module with instances, DefaultInstance is optional +/// frame_support::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 $(, $instance:ident $(: $instantiable:ident)? $( = $event_default_instance:path)? )?> where + $( $tt:tt )* + ) => { + $crate::__decl_generic_event!( + $( #[ $attr ] )*; + $evt_generic_param; + $($instance $( = $event_default_instance)? )?; + { $( $tt )* }; + ); + }; + ( + $(#[$attr:meta])* + pub enum Event { + $( + $events:tt + )* + } + ) => { + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive( + Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + /// Events for this module. + /// + $(#[$attr])* + pub enum Event { + $( + $events + )* + } + impl From for () { + fn from(_: Event) -> () { () } + } + impl Event { + #[allow(dead_code)] + #[doc(hidden)] + pub fn metadata() -> &'static [ $crate::event::EventMetadata ] { + $crate::__events_to_metadata!(; $( $events )* ) + } + } + } +} + +#[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; + $($instance:ident $( = $event_default_instance:path)? )?; + { $( $tt:tt )* }; + ) => { + $crate::__decl_generic_event!(@format_generic + $( #[ $attr ] )*; + $event_generic_param; + $($instance $( = $event_default_instance)? )?; + { $( $tt )* }; + {}; + ); + }; + // Finish formatting on an unnamed one + (@format_generic + $(#[$attr:meta])*; + $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; + { <$generic:ident as $trait:path>::$trait_type:ident $(,)? { $( $events:tt )* } }; + {$( $parsed:tt)*}; + ) => { + $crate::__decl_generic_event!(@generate + $( #[ $attr ] )*; + $event_generic_param; + $($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; + $($instance:ident $( = $event_default_instance:path)? )?; + { $generic_rename:ident = $generic_type:ty $(,)? { $( $events:tt )* } }; + { $($parsed:tt)* }; + ) => { + $crate::__decl_generic_event!(@generate + $(#[$attr])*; + $event_generic_param; + $($instance $( = $event_default_instance)? )?; + { $($events)* }; + { $($parsed)*, $generic_rename = $generic_type }; + ); + }; + // Parse named + (@format_generic + $(#[$attr:meta])*; + $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; + { $generic_rename:ident = $generic_type:ty, $($rest:tt)* }; + {$( $parsed:tt)*}; + ) => { + $crate::__decl_generic_event!(@format_generic + $( #[ $attr ] )*; + $event_generic_param; + $( $instance $( = $event_default_instance)? )?; + { $($rest)* }; + { $($parsed)*, $generic_rename = $generic_type }; + ); + }; + // Parse unnamed + (@format_generic + $(#[$attr:meta])*; + $event_generic_param:ident; + $($instance:ident $( = $event_default_instance:path)? )?; + { <$generic:ident as $trait:path>::$trait_type:ident, $($rest:tt)* }; + {$($parsed:tt)*}; + ) => { + $crate::__decl_generic_event!(@format_generic + $( #[ $attr ] )*; + $event_generic_param; + $($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); + }; + // 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)? >; + + #[derive( + Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + /// Events for this module. + /// + $(#[$attr])* + pub enum RawEvent<$( $generic_param ),* $(, $instance)? > { + $( + $events + )* + $( + #[doc(hidden)] + #[codec(skip)] + PhantomData($crate::sp_std::marker::PhantomData<$instance>), + )? + } + impl<$( $generic_param ),* $(, $instance)? > From> for () { + fn from(_: RawEvent<$( $generic_param ),* $(, $instance)?>) -> () { () } + } + impl<$( $generic_param ),* $(, $instance)?> RawEvent<$( $generic_param ),* $(, $instance)?> { + #[allow(dead_code)] + pub fn metadata() -> &'static [$crate::event::EventMetadata] { + $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), "`")); + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __events_to_metadata { + ( + $( $metadata:expr ),*; + $( #[doc = $doc_attr:tt] )* + $event:ident $( ( $( $param:path ),* $(,)? ) )*, + $( $rest:tt )* + ) => { + $crate::__events_to_metadata!( + $( $metadata, )* + $crate::event::EventMetadata { + name: $crate::event::DecodeDifferent::Encode(stringify!($event)), + arguments: $crate::event::DecodeDifferent::Encode(&[ + $( $( stringify!($param) ),* )* + ]), + documentation: $crate::event::DecodeDifferent::Encode(&[ + $( $doc_attr ),* + ]), + }; + $( $rest )* + ) + }; + ( + $( $metadata:expr ),*; + ) => { + &[ $( $metadata ),* ] + } +} + +/// Constructs an Event type for a runtime. This is usually called automatically by the +/// construct_runtime 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_event_without_system:tt )* + } + ) => { + $crate::impl_outer_event!( + $( #[$attr] )*; + $name; + $runtime; + system; + Modules { $( $rest_event_without_system )* }; + ; + ); + }; + ( + $(#[$attr:meta])* + pub enum $name:ident for $runtime:ident where system = $system:ident { + $( $rest_event_with_system:tt )* + } + ) => { + $crate::impl_outer_event!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_event_with_system )* }; + ; + ); + }; + // Generic + Instance + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules { + $module:ident $instance:ident, + $( $rest_event_generic_instance:tt )* + }; + $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; + ) => { + $crate::impl_outer_event!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_event_generic_instance )* }; + $( $module_name::Event $( <$generic_param> )? $( { $generic_instance } )?, )* $module::Event<$runtime>{ $instance },; + ); + }; + // Instance + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules { + $module:ident $instance:ident, + $( $rest_event_instance:tt )* + }; + $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; + ) => { + $crate::impl_outer_event!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_event_instance )* }; + $( $module_name::Event $( <$generic_param> )* $( { $generic_instance } )?, )* $module::Event { $instance },; + ); + }; + // Generic + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules { + $module:ident, + $( $rest_event_generic:tt )* + }; + $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; + ) => { + $crate::impl_outer_event!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_event_generic )* }; + $( $module_name::Event $( <$generic_param> )? $( { $generic_instance } )?, )* $module::Event<$runtime>,; + ); + }; + // No Generic and no Instance + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules { + $module:ident, + $( $rest_event_no_generic_no_instance:tt )* + }; + $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; + ) => { + $crate::impl_outer_event!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_event_no_generic_no_instance )* }; + $( $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> )? $( { $generic_instance:ident } )?, )*; + ) => { + $crate::paste::item! { + #[derive( + Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + $(#[$attr])* + #[allow(non_camel_case_types)] + pub enum $name { + system($system::Event), + $( + [< $module_name $(_ $generic_instance )? >]( + $module_name::Event < $( $generic_param )? $(, $module_name::$generic_instance )? > + ), + )* + } + impl From<$system::Event> for $name { + fn from(x: $system::Event) -> Self { + $name::system(x) + } + } + $( + impl From<$module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >> for $name { + fn from(x: $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >) -> Self { + $name::[< $module_name $(_ $generic_instance )? >](x) + } + } + impl $crate::sp_std::convert::TryInto< + $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? > + > for $name { + type Error = (); + + fn try_into(self) -> $crate::sp_std::result::Result< + $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >, Self::Error + > { + match self { + Self::[< $module_name $(_ $generic_instance )? >](evt) => Ok(evt), + _ => Err(()), + } + } + } + )* + } + $crate::__impl_outer_event_json_metadata!( + $runtime; + $name; + $system; + $( + $module_name::Event + < $( $generic_param )? $(, $module_name::$generic_instance )? > + $( $generic_instance )?, + )*; + ); + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_outer_event_json_metadata { + ( + $runtime:ident; + $event_name:ident; + $system:ident; + $( $module_name:ident::Event < $( $generic_params:path ),* > $( $instance:ident )?, )*; + ) => { + impl $runtime { + #[allow(dead_code)] + pub fn outer_event_metadata() -> $crate::event::OuterEventMetadata { + $crate::event::OuterEventMetadata { + name: $crate::event::DecodeDifferent::Encode(stringify!($event_name)), + events: $crate::event::DecodeDifferent::Encode(&[ + ("system", $crate::event::FnEncode($system::Event::metadata)) + $( + , ( + stringify!($module_name), + $crate::event::FnEncode( + $module_name::Event ::< $( $generic_params ),* > ::metadata + ) + ) + )* + ]) + } + } + + $crate::__impl_outer_event_json_metadata! { + @DECL_MODULE_EVENT_FNS + $system <> ; + $( $module_name < $( $generic_params ),* > $( $instance )? ; )* + } + } + }; + + (@DECL_MODULE_EVENT_FNS + $( + $module_name:ident < $( $generic_params:path ),* > $( $instance:ident )? ; + )* + ) => { + $crate::paste::item! { + $( + #[allow(dead_code)] + pub fn [< __module_events_ $module_name $( _ $instance )? >] () -> + &'static [$crate::event::EventMetadata] + { + $module_name::Event ::< $( $generic_params ),* > ::metadata() + } + )* + } + } +} + +#[cfg(test)] +#[allow(dead_code)] +mod tests { + use super::*; + use serde::Serialize; + use codec::{Encode, Decode}; + + mod system { + pub trait Trait { + type Origin; + type BlockNumber; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + pub enum Event { + SystemEvent, + } + ); + } + + mod system_renamed { + pub trait Trait { + type Origin; + type BlockNumber; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + pub enum Event { + SystemEvent, + } + ); + } + + mod event_module { + pub trait Trait { + type Origin; + type Balance; + type BlockNumber; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + /// Event without renaming the generic parameter `Balance` and `Origin`. + pub enum Event where ::Balance, ::Origin + { + /// Hi, I am a comment. + TestEvent(Balance, Origin), + /// Dog + EventWithoutParams, + } + ); + } + + mod event_module2 { + pub trait Trait { + type Origin; + type Balance; + type BlockNumber; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + /// Event with renamed generic parameter + pub enum Event where + BalanceRenamed = ::Balance, + OriginRenamed = ::Origin + { + TestEvent(BalanceRenamed), + TestOrigin(OriginRenamed), + } + ); + } + + mod event_module3 { + decl_event!( + pub enum Event { + HiEvent, + } + ); + } + + mod event_module4 { + pub trait Trait { + type Origin; + type Balance; + type BlockNumber; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + /// Event finish formatting on an unnamed one with trailling comma + pub enum Event where + ::Balance, + ::Origin, + { + TestEvent(Balance, Origin), + } + ); + } + + mod event_module5 { + pub trait Trait { + type Origin; + type Balance; + type BlockNumber; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + decl_event!( + /// Event finish formatting on an named one with trailing comma + pub enum Event where + BalanceRenamed = ::Balance, + OriginRenamed = ::Origin, + { + TestEvent(BalanceRenamed, OriginRenamed), + TrailingCommaInArgs( + u32, + u32, + ), + } + ); + } + + #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)] + pub struct TestRuntime; + + impl_outer_event! { + pub enum TestEvent for TestRuntime { + event_module, + event_module2, + event_module3, + } + } + + #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)] + pub struct TestRuntime2; + + impl_outer_event! { + pub enum TestEventSystemRenamed for TestRuntime2 where system = system_renamed { + event_module, + event_module2, + event_module3, + } + } + + impl event_module::Trait for TestRuntime { + type Origin = u32; + type Balance = u32; + type BlockNumber = u32; + } + + impl event_module2::Trait for TestRuntime { + type Origin = u32; + type Balance = u32; + type BlockNumber = u32; + } + + impl system::Trait for TestRuntime { + type Origin = u32; + type BlockNumber = u32; + } + + impl event_module::Trait for TestRuntime2 { + type Origin = u32; + type Balance = u32; + type BlockNumber = u32; + } + + impl event_module2::Trait for TestRuntime2 { + type Origin = u32; + type Balance = u32; + type BlockNumber = u32; + } + + impl system_renamed::Trait for TestRuntime2 { + type Origin = u32; + type BlockNumber = u32; + } + + const EXPECTED_METADATA: OuterEventMetadata = OuterEventMetadata { + name: DecodeDifferent::Encode("TestEvent"), + events: DecodeDifferent::Encode(&[ + ( + "system", + FnEncode(|| &[ + EventMetadata { + name: DecodeDifferent::Encode("SystemEvent"), + arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[]), + } + ]) + ), + ( + "event_module", + FnEncode(|| &[ + EventMetadata { + name: DecodeDifferent::Encode("TestEvent"), + arguments: DecodeDifferent::Encode(&[ "Balance", "Origin" ]), + documentation: DecodeDifferent::Encode(&[ " Hi, I am a comment." ]) + }, + EventMetadata { + name: DecodeDifferent::Encode("EventWithoutParams"), + arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[ " Dog" ]), + }, + ]) + ), + ( + "event_module2", + FnEncode(|| &[ + EventMetadata { + name: DecodeDifferent::Encode("TestEvent"), + arguments: DecodeDifferent::Encode(&[ "BalanceRenamed" ]), + documentation: DecodeDifferent::Encode(&[]) + }, + EventMetadata { + name: DecodeDifferent::Encode("TestOrigin"), + arguments: DecodeDifferent::Encode(&[ "OriginRenamed" ]), + documentation: DecodeDifferent::Encode(&[]), + }, + ]) + ), + ( + "event_module3", + FnEncode(|| &[ + EventMetadata { + name: DecodeDifferent::Encode("HiEvent"), + arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[]) + } + ]) + ) + ]) + }; + + #[test] + fn outer_event_metadata() { + assert_eq!(EXPECTED_METADATA, TestRuntime::outer_event_metadata()); + } +} diff --git a/frame/support/src/hash.rs b/frame/support/src/hash.rs new file mode 100644 index 0000000000000..aae4aceb7fe82 --- /dev/null +++ b/frame/support/src/hash.rs @@ -0,0 +1,137 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Hash utilities. + +use codec::Codec; +use sp_std::prelude::Vec; +use sp_io::hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256}; + +// This trait must be kept coherent with frame-support-procedural HasherKind usage +pub trait Hashable: Sized { + fn blake2_128(&self) -> [u8; 16]; + fn blake2_256(&self) -> [u8; 32]; + fn blake2_128_concat(&self) -> Vec; + fn twox_128(&self) -> [u8; 16]; + fn twox_256(&self) -> [u8; 32]; + fn twox_64_concat(&self) -> Vec; +} + +impl Hashable for T { + fn blake2_128(&self) -> [u8; 16] { + self.using_encoded(blake2_128) + } + fn blake2_256(&self) -> [u8; 32] { + self.using_encoded(blake2_256) + } + fn blake2_128_concat(&self) -> Vec { + self.using_encoded(Blake2_128Concat::hash) + } + fn twox_128(&self) -> [u8; 16] { + self.using_encoded(twox_128) + } + fn twox_256(&self) -> [u8; 32] { + self.using_encoded(twox_256) + } + fn twox_64_concat(&self) -> Vec { + self.using_encoded(Twox64Concat::hash) + } +} + +/// Hasher to use to hash keys to insert to storage. +pub trait StorageHasher: 'static { + type Output: AsRef<[u8]>; + fn hash(x: &[u8]) -> Self::Output; +} + +/// Hash storage keys with `concat(twox64(key), key)` +pub struct Twox64Concat; +impl StorageHasher for Twox64Concat { + type Output = Vec; + fn hash(x: &[u8]) -> Vec { + twox_64(x) + .iter() + .chain(x.into_iter()) + .cloned() + .collect::>() + } +} + +/// Hash storage keys with `concat(blake2_128(key), key)` +pub struct Blake2_128Concat; +impl StorageHasher for Blake2_128Concat { + type Output = Vec; + fn hash(x: &[u8]) -> Vec { + blake2_128(x) + .iter() + .chain(x.into_iter()) + .cloned() + .collect::>() + } +} + +/// Hash storage keys with blake2 128 +pub struct Blake2_128; +impl StorageHasher for Blake2_128 { + type Output = [u8; 16]; + fn hash(x: &[u8]) -> [u8; 16] { + blake2_128(x) + } +} + +/// Hash storage keys with blake2 256 +pub struct Blake2_256; +impl StorageHasher for Blake2_256 { + type Output = [u8; 32]; + fn hash(x: &[u8]) -> [u8; 32] { + blake2_256(x) + } +} + +/// Hash storage keys with twox 128 +pub struct Twox128; +impl StorageHasher for Twox128 { + type Output = [u8; 16]; + fn hash(x: &[u8]) -> [u8; 16] { + twox_128(x) + } +} + +/// Hash storage keys with twox 256 +pub struct Twox256; +impl StorageHasher for Twox256 { + type Output = [u8; 32]; + fn hash(x: &[u8]) -> [u8; 32] { + twox_256(x) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_twox_64_concat() { + let r = Twox64Concat::hash(b"foo"); + assert_eq!(r.split_at(8), (&twox_128(b"foo")[..8], &b"foo"[..])) + } + + #[test] + fn test_blake2_128_concat() { + let r = Blake2_128Concat::hash(b"foo"); + assert_eq!(r.split_at(16), (&blake2_128(b"foo")[..], &b"foo"[..])) + } +} diff --git a/srml/support/src/inherent.rs b/frame/support/src/inherent.rs similarity index 92% rename from srml/support/src/inherent.rs rename to frame/support/src/inherent.rs index 935d3b4e74e4f..a21bd361b618d 100644 --- a/srml/support/src/inherent.rs +++ b/frame/support/src/inherent.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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 crate::rstd::vec::Vec; +pub use crate::sp_std::vec::Vec; #[doc(hidden)] -pub use crate::sr_primitives::traits::{Block as BlockT, Extrinsic}; +pub use crate::sp_runtime::traits::{Block as BlockT, Extrinsic}; #[doc(hidden)] -pub use inherents::{InherentData, ProvideInherent, CheckInherentsResult, IsFatalError}; +pub use sp_inherents::{InherentData, ProvideInherent, CheckInherentsResult, IsFatalError}; /// Implement the outer inherent. diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs new file mode 100644 index 0000000000000..ebfc7bbe97ebe --- /dev/null +++ b/frame/support/src/lib.rs @@ -0,0 +1,624 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Support code for the runtime. + +#![cfg_attr(not(feature = "std"), no_std)] + +/// Export ourself as `frame_support` to make tests happy. +extern crate self as frame_support; + +#[macro_use] +extern crate bitmask; +#[cfg(feature = "std")] +pub extern crate tracing; + +#[cfg(feature = "std")] +pub use serde; +#[doc(hidden)] +pub use sp_std; +#[doc(hidden)] +pub use codec; +#[cfg(feature = "std")] +#[doc(hidden)] +pub use once_cell; +#[doc(hidden)] +pub use paste; +#[cfg(feature = "std")] +#[doc(hidden)] +pub use sp_state_machine::BasicExternalities; +#[doc(hidden)] +pub use sp_io::storage::root as storage_root; +#[doc(hidden)] +pub use sp_runtime::RuntimeDebug; + +#[macro_use] +pub mod debug; +#[macro_use] +pub mod dispatch; +pub mod storage; +mod hash; +#[macro_use] +pub mod event; +#[macro_use] +mod origin; +#[macro_use] +pub mod metadata; +#[macro_use] +pub mod inherent; +#[macro_use] +pub mod unsigned; +#[macro_use] +pub mod error; +pub mod traits; +pub mod weights; + +pub use self::hash::{ + Twox256, Twox128, Blake2_256, Blake2_128, Twox64Concat, Blake2_128Concat, Hashable +}; +pub use self::storage::{ + StorageValue, StorageMap, StorageLinkedMap, StorageDoubleMap, StoragePrefixedMap +}; +pub use self::dispatch::{Parameter, Callable, IsSubType}; +pub use sp_runtime::{self, ConsensusEngineId, print, traits::Printable}; + +/// Macro for easily creating a new implementation of the `Get` trait. Use similarly to +/// how you would declare a `const`: +/// +/// ```no_compile +/// parameter_types! { +/// pub const Argument: u64 = 42; +/// } +/// trait Config { +/// type Parameter: Get; +/// } +/// struct Runtime; +/// impl Config for Runtime { +/// type Parameter = Argument; +/// } +/// ``` +#[macro_export] +macro_rules! parameter_types { + ( + $( #[ $attr:meta ] )* + $vis:vis const $name:ident: $type:ty = $value:expr; + $( $rest:tt )* + ) => ( + $( #[ $attr ] )* + $vis struct $name; + $crate::parameter_types!{IMPL $name , $type , $value} + $crate::parameter_types!{ $( $rest )* } + ); + () => (); + (IMPL $name:ident , $type:ty , $value:expr) => { + impl $name { + pub fn get() -> $type { + $value + } + } + impl> $crate::traits::Get for $name { + fn get() -> I { + I::from($value) + } + } + } +} + +/// Macro for easily creating a new implementation of both the `Get` and `Contains` traits. Use +/// exactly as with `parameter_types`, only the type must be `Ord`. +#[macro_export] +macro_rules! ord_parameter_types { + ( + $( #[ $attr:meta ] )* + $vis:vis const $name:ident: $type:ty = $value:expr; + $( $rest:tt )* + ) => ( + $( #[ $attr ] )* + $vis struct $name; + $crate::parameter_types!{IMPL $name , $type , $value} + $crate::ord_parameter_types!{IMPL $name , $type , $value} + $crate::ord_parameter_types!{ $( $rest )* } + ); + () => (); + (IMPL $name:ident , $type:ty , $value:expr) => { + impl $crate::traits::Contains<$type> for $name { + fn contains(t: &$type) -> bool { &$value == t } + fn sorted_members() -> $crate::sp_std::prelude::Vec<$type> { vec![$value] } + fn count() -> usize { 1 } + } + } +} + +#[doc(inline)] +pub use frame_support_procedural::{decl_storage, construct_runtime}; + +/// Return Err of the expression: `return Err($expression);`. +/// +/// Used as `fail!(expression)`. +#[macro_export] +macro_rules! fail { + ( $y:expr ) => {{ + return Err($y.into()); + }} +} + +/// Evaluate `$x:expr` and if not true return `Err($y:expr)`. +/// +/// Used as `ensure!(expression_to_ensure, expression_to_return_on_false)`. +#[macro_export] +macro_rules! ensure { + ( $x:expr, $y:expr $(,)? ) => {{ + if !$x { + $crate::fail!($y); + } + }} +} + +/// Evaluate an expression, assert it returns an expected `Err` value and that +/// runtime storage has not been mutated (i.e. expression is a no-operation). +/// +/// Used as `assert_noop(expression_to_assert, expected_error_expression)`. +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_noop { + ( + $x:expr, + $y:expr $(,)? + ) => { + let h = $crate::storage_root(); + $crate::assert_err!($x, $y); + assert_eq!(h, $crate::storage_root()); + } +} + +/// Panic if an expression doesn't evaluate to an `Err`. +/// +/// Used as `assert_err!(expression_to_assert, expected_err_expression)`. + +/// Assert an expression returns an error specified. +/// +/// Used as `assert_err!(expression_to_assert, expected_error_expression)` +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_err { + ( $x:expr , $y:expr $(,)? ) => { + assert_eq!($x, Err($y.into())); + } +} + +/// Panic if an expression doesn't evaluate to `Ok`. +/// +/// Used as `assert_ok!(expression_to_assert, expected_ok_expression)`, +/// or `assert_ok!(expression_to_assert)` which would assert against `Ok(())`. +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_ok { + ( $x:expr $(,)? ) => { + assert_eq!($x, Ok(())); + }; + ( $x:expr, $y:expr $(,)? ) => { + assert_eq!($x, Ok($y)); + } +} + +/// The void type - it cannot exist. +// Oh rust, you crack me up... +#[derive(Clone, Eq, PartialEq, RuntimeDebug)] +pub enum Void {} + +#[cfg(feature = "std")] +#[doc(hidden)] +pub use serde::{Serialize, Deserialize}; + +#[cfg(test)] +mod tests { + use super::*; + use codec::{Codec, EncodeLike}; + use frame_metadata::{ + DecodeDifferent, StorageEntryMetadata, StorageMetadata, StorageEntryType, + StorageEntryModifier, DefaultByteGetter, StorageHasher, + }; + use sp_std::marker::PhantomData; + + pub trait Trait { + type BlockNumber: Codec + EncodeLike + 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(fn data) build(|_| vec![(15u32, 42u64)]): + linked_map hasher(twox_64_concat) u32 => u64; + pub OptionLinkedMap: linked_map u32 => Option; + pub GenericData get(fn generic_data): + linked_map hasher(twox_128) T::BlockNumber => T::BlockNumber; + pub GenericData2 get(fn generic_data2): + linked_map T::BlockNumber => Option; + pub GetterNoFnKeyword get(no_fn): Option; + + pub DataDM config(test_config) build(|_| vec![(15u32, 16u32, 42u64)]): + double_map hasher(twox_64_concat) u32, hasher(blake2_256) u32 => u64; + pub GenericDataDM: + double_map T::BlockNumber, hasher(twox_128) T::BlockNumber => T::BlockNumber; + pub GenericData2DM: + double_map T::BlockNumber, hasher(twox_256) T::BlockNumber => Option; + pub AppendableDM: double_map u32, T::BlockNumber => Vec; + } + } + + struct Test; + impl Trait for Test { + type BlockNumber = u32; + type Origin = u32; + } + + fn new_test_ext() -> sp_io::TestExternalities { + GenesisConfig::default().build_storage().unwrap().into() + } + + type Map = Data; + + #[test] + fn linked_map_issue_3318() { + new_test_ext().execute_with(|| { + OptionLinkedMap::insert(1, 1); + assert_eq!(OptionLinkedMap::get(1), Some(1)); + OptionLinkedMap::insert(1, 2); + assert_eq!(OptionLinkedMap::get(1), Some(2)); + }); + } + + #[test] + fn linked_map_swap_works() { + new_test_ext().execute_with(|| { + OptionLinkedMap::insert(0, 0); + OptionLinkedMap::insert(1, 1); + OptionLinkedMap::insert(2, 2); + OptionLinkedMap::insert(3, 3); + + let collect = || OptionLinkedMap::enumerate().collect::>(); + assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); + + // Two existing + OptionLinkedMap::swap(1, 2); + assert_eq!(collect(), vec![(3, 3), (2, 1), (1, 2), (0, 0)]); + + // Back to normal + OptionLinkedMap::swap(2, 1); + assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); + + // Left existing + OptionLinkedMap::swap(2, 5); + assert_eq!(collect(), vec![(5, 2), (3, 3), (1, 1), (0, 0)]); + + // Right existing + OptionLinkedMap::swap(5, 2); + assert_eq!(collect(), vec![(2, 2), (3, 3), (1, 1), (0, 0)]); + }); + } + + #[test] + fn double_map_swap_works() { + new_test_ext().execute_with(|| { + DataDM::insert(0, 1, 1); + DataDM::insert(1, 0, 2); + DataDM::insert(1, 1, 3); + + let get_all = || vec![ + DataDM::get(0, 1), + DataDM::get(1, 0), + DataDM::get(1, 1), + DataDM::get(2, 0), + DataDM::get(2, 1), + ]; + assert_eq!(get_all(), vec![1, 2, 3, 0, 0]); + + // Two existing + DataDM::swap(0, 1, 1, 0); + assert_eq!(get_all(), vec![2, 1, 3, 0, 0]); + + // Left existing + DataDM::swap(1, 0, 2, 0); + assert_eq!(get_all(), vec![2, 0, 3, 1, 0]); + + // Right existing + DataDM::swap(2, 1, 1, 1); + assert_eq!(get_all(), vec![2, 0, 0, 1, 3]); + }); + } + + #[test] + fn linked_map_basic_insert_remove_should_work() { + new_test_ext().execute_with(|| { + // initialized 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 linked_map_enumeration_and_head_should_work() { + new_test_ext().execute_with(|| { + 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![]); + }); + } + + #[test] + fn double_map_basic_insert_remove_remove_prefix_should_work() { + new_test_ext().execute_with(|| { + type DoubleMap = DataDM; + // initialized during genesis + assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64); + + // get / insert / take + let key1 = 17u32; + let key2 = 18u32; + assert_eq!(DoubleMap::get(&key1, &key2), 0u64); + DoubleMap::insert(&key1, &key2, &4u64); + assert_eq!(DoubleMap::get(&key1, &key2), 4u64); + assert_eq!(DoubleMap::take(&key1, &key2), 4u64); + assert_eq!(DoubleMap::get(&key1, &key2), 0u64); + + // mutate + DoubleMap::mutate(&key1, &key2, |val| { + *val = 15; + }); + assert_eq!(DoubleMap::get(&key1, &key2), 15u64); + + // remove + DoubleMap::remove(&key1, &key2); + assert_eq!(DoubleMap::get(&key1, &key2), 0u64); + + // remove prefix + DoubleMap::insert(&key1, &key2, &4u64); + DoubleMap::insert(&key1, &(key2 + 1), &4u64); + DoubleMap::insert(&(key1 + 1), &key2, &4u64); + DoubleMap::insert(&(key1 + 1), &(key2 + 1), &4u64); + DoubleMap::remove_prefix(&key1); + assert_eq!(DoubleMap::get(&key1, &key2), 0u64); + assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64); + assert_eq!(DoubleMap::get(&(key1 + 1), &key2), 4u64); + assert_eq!(DoubleMap::get(&(key1 + 1), &(key2 + 1)), 4u64); + + }); + } + + #[test] + fn double_map_append_should_work() { + new_test_ext().execute_with(|| { + type DoubleMap = AppendableDM; + + let key1 = 17u32; + let key2 = 18u32; + + DoubleMap::insert(&key1, &key2, &vec![1]); + DoubleMap::append(&key1, &key2, &[2, 3]).unwrap(); + assert_eq!(DoubleMap::get(&key1, &key2), &[1, 2, 3]); + }); + } + + const EXPECTED_METADATA: StorageMetadata = StorageMetadata { + prefix: DecodeDifferent::Encode("Example"), + entries: DecodeDifferent::Encode( + &[ + StorageEntryMetadata { + name: DecodeDifferent::Encode("Data"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Map{ + hasher: StorageHasher::Twox64Concat, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("u64"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructData(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("OptionLinkedMap"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("u32"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructOptionLinkedMap(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GenericData"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Map{ + hasher: StorageHasher::Twox128, + key: DecodeDifferent::Encode("T::BlockNumber"), + value: DecodeDifferent::Encode("T::BlockNumber"), + is_linked: true + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericData(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GenericData2"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Map{ + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("T::BlockNumber"), + value: DecodeDifferent::Encode("T::BlockNumber"), + is_linked: true + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericData2(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GetterNoFnKeyword"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGetterNoFnKeyword(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("DataDM"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::DoubleMap{ + hasher: StorageHasher::Twox64Concat, + key1: DecodeDifferent::Encode("u32"), + key2: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("u64"), + key2_hasher: StorageHasher::Blake2_256, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructDataDM(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GenericDataDM"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::DoubleMap{ + hasher: StorageHasher::Blake2_256, + key1: DecodeDifferent::Encode("T::BlockNumber"), + key2: DecodeDifferent::Encode("T::BlockNumber"), + value: DecodeDifferent::Encode("T::BlockNumber"), + key2_hasher: StorageHasher::Twox128, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericDataDM(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GenericData2DM"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::DoubleMap{ + hasher: StorageHasher::Blake2_256, + key1: DecodeDifferent::Encode("T::BlockNumber"), + key2: DecodeDifferent::Encode("T::BlockNumber"), + value: DecodeDifferent::Encode("T::BlockNumber"), + key2_hasher: StorageHasher::Twox256, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("AppendableDM"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::DoubleMap{ + hasher: StorageHasher::Blake2_256, + key1: DecodeDifferent::Encode("u32"), + key2: DecodeDifferent::Encode("T::BlockNumber"), + value: DecodeDifferent::Encode("Vec"), + key2_hasher: StorageHasher::Blake2_256, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + ] + ), + }; + + #[test] + fn store_metadata() { + let metadata = Module::::storage_metadata(); + pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata); + } +} diff --git a/frame/support/src/metadata.rs b/frame/support/src/metadata.rs new file mode 100644 index 0000000000000..110df87c644b6 --- /dev/null +++ b/frame/support/src/metadata.rs @@ -0,0 +1,551 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +pub use frame_metadata::{ + DecodeDifferent, FnEncode, RuntimeMetadata, ModuleMetadata, RuntimeMetadataLastVersion, + DefaultByteGetter, RuntimeMetadataPrefixed, StorageEntryMetadata, StorageMetadata, + StorageEntryType, StorageEntryModifier, DefaultByte, StorageHasher, ModuleErrorMetadata +}; + +/// Implements the metadata support for the given runtime and all its modules. +/// +/// Example: +/// ``` +///# mod module0 { +///# pub trait Trait { +///# type Origin; +///# type BlockNumber; +///# } +///# frame_support::decl_module! { +///# pub struct Module for enum Call where origin: T::Origin {} +///# } +///# +///# frame_support::decl_storage! { +///# trait Store for Module as TestStorage {} +///# } +///# } +///# use module0 as module1; +///# use module0 as module2; +///# impl module0::Trait for Runtime { +///# type Origin = u32; +///# type BlockNumber = u32; +///# } +/// +/// struct Runtime; +/// frame_support::impl_runtime_metadata! { +/// for Runtime with modules +/// module0::Module as Module0 with, +/// module1::Module as Module1 with, +/// module2::Module as Module2 with Storage, +/// }; +/// ``` +/// +/// In this example, just `MODULE3` implements the `Storage` trait. +#[macro_export] +macro_rules! impl_runtime_metadata { + ( + for $runtime:ident with modules + $( $rest:tt )* + ) => { + impl $runtime { + pub fn metadata() -> $crate::metadata::RuntimeMetadataPrefixed { + $crate::metadata::RuntimeMetadataLastVersion { + modules: $crate::__runtime_modules_to_metadata!($runtime;; $( $rest )*), + }.into() + } + } + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __runtime_modules_to_metadata { + ( + $runtime: ident; + $( $metadata:expr ),*; + $mod:ident::$module:ident $( < $instance:ident > )? as $name:ident $(with)+ $($kw:ident)*, + $( $rest:tt )* + ) => { + $crate::__runtime_modules_to_metadata!( + $runtime; + $( $metadata, )* $crate::metadata::ModuleMetadata { + name: $crate::metadata::DecodeDifferent::Encode(stringify!($name)), + 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)* + ), + constants: $crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode( + $mod::$module::<$runtime $(, $mod::$instance )?>::module_constants_metadata + ) + ), + errors: $crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode( + <$mod::$module::<$runtime $(, $mod::$instance )?> as $crate::metadata::ModuleErrorMetadata>::metadata + ) + ) + }; + $( $rest )* + ) + }; + ( + $runtime:ident; + $( $metadata:expr ),*; + ) => { + $crate::metadata::DecodeDifferent::Encode(&[ $( $metadata ),* ]) + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __runtime_modules_to_metadata_calls_call { + ( + $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_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 )?>::storage_metadata + ) + )) + }; + ( + $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 frame_metadata::{ + EventMetadata, StorageEntryModifier, StorageEntryType, FunctionMetadata, StorageEntryMetadata, + ModuleMetadata, RuntimeMetadataPrefixed, DefaultByte, ModuleConstantMetadata, DefaultByteGetter, + ErrorMetadata, + }; + use codec::{Encode, Decode}; + use crate::traits::Get; + + mod system { + use super::*; + + pub trait Trait: 'static { + const ASSOCIATED_CONST: u64 = 500; + type Origin: Into, Self::Origin>> + + From>; + type AccountId: From + Encode; + type BlockNumber: From + Encode; + type SomeValue: Get; + type ModuleToIndex: crate::traits::ModuleToIndex; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Hi, I am a comment. + const BlockNumber: T::BlockNumber = 100.into(); + const GetType: T::AccountId = T::SomeValue::get().into(); + const ASSOCIATED_CONST: u64 = T::ASSOCIATED_CONST.into(); + } + } + + decl_event!( + pub enum Event { + SystemEvent, + } + ); + + #[derive(Clone, PartialEq, Eq, Debug)] + pub enum RawOrigin { + Root, + Signed(AccountId), + None, + } + + impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::None, + } + } + } + + pub type Origin = RawOrigin<::AccountId>; + } + + mod event_module { + use crate::dispatch::DispatchResult; + + pub trait Trait: super::system::Trait { + type Balance; + } + + decl_event!( + pub enum Event where ::Balance + { + /// Hi, I am a comment. + TestEvent(Balance), + } + ); + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn aux_0(_origin) -> DispatchResult { unreachable!() } + } + } + + crate::decl_error! { + pub enum Error for Module { + /// Some user input error + UserInputError, + /// Something bad happened + /// this could be due to many reasons + BadThingHappened, + } + } + } + + mod event_module2 { + pub trait Trait { + type Origin; + type Balance; + type BlockNumber; + } + + decl_event!( + pub enum Event where ::Balance + { + TestEvent(Balance), + } + ); + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + crate::decl_storage! { + trait Store for Module as TestStorage { + StorageMethod : Option; + } + add_extra_genesis { + build(|_| {}); + } + } + } + + type EventModule = event_module::Module; + type EventModule2 = event_module2::Module; + + #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] + pub struct TestRuntime; + + impl_outer_event! { + pub enum TestEvent for TestRuntime { + event_module, + event_module2, + } + } + + impl_outer_origin! { + pub enum Origin for TestRuntime {} + } + + impl_outer_dispatch! { + pub enum Call for TestRuntime where origin: Origin { + event_module::EventModule, + event_module2::EventModule2, + } + } + + impl event_module::Trait for TestRuntime { + type Balance = u32; + } + + impl event_module2::Trait for TestRuntime { + type Origin = Origin; + type Balance = u32; + type BlockNumber = u32; + } + + crate::parameter_types! { + pub const SystemValue: u32 = 600; + } + + impl system::Trait for TestRuntime { + type Origin = Origin; + type AccountId = u32; + type BlockNumber = u32; + type SomeValue = SystemValue; + type ModuleToIndex = (); + } + + impl_runtime_metadata!( + for TestRuntime with modules + system::Module as System with Event, + event_module::Module as Module with Event Call, + event_module2::Module as Module2 with Event Storage Call, + ); + + struct ConstantBlockNumberByteGetter; + impl DefaultByte for ConstantBlockNumberByteGetter { + fn default_byte(&self) -> Vec { + 100u32.encode() + } + } + + struct ConstantGetTypeByteGetter; + impl DefaultByte for ConstantGetTypeByteGetter { + fn default_byte(&self) -> Vec { + SystemValue::get().encode() + } + } + + struct ConstantAssociatedConstByteGetter; + impl DefaultByte for ConstantAssociatedConstByteGetter { + fn default_byte(&self) -> Vec { + ::ASSOCIATED_CONST.encode() + } + } + + const EXPECTED_METADATA: RuntimeMetadataLastVersion = RuntimeMetadataLastVersion { + modules: DecodeDifferent::Encode(&[ + ModuleMetadata { + name: DecodeDifferent::Encode("System"), + storage: None, + calls: None, + event: Some(DecodeDifferent::Encode( + FnEncode(||&[ + EventMetadata { + name: DecodeDifferent::Encode("SystemEvent"), + arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[]) + } + ]) + )), + constants: DecodeDifferent::Encode( + FnEncode(|| &[ + ModuleConstantMetadata { + name: DecodeDifferent::Encode("BlockNumber"), + ty: DecodeDifferent::Encode("T::BlockNumber"), + value: DecodeDifferent::Encode( + DefaultByteGetter(&ConstantBlockNumberByteGetter) + ), + documentation: DecodeDifferent::Encode(&[" Hi, I am a comment."]), + }, + ModuleConstantMetadata { + name: DecodeDifferent::Encode("GetType"), + ty: DecodeDifferent::Encode("T::AccountId"), + value: DecodeDifferent::Encode( + DefaultByteGetter(&ConstantGetTypeByteGetter) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + ModuleConstantMetadata { + name: DecodeDifferent::Encode("ASSOCIATED_CONST"), + ty: DecodeDifferent::Encode("u64"), + value: DecodeDifferent::Encode( + DefaultByteGetter(&ConstantAssociatedConstByteGetter) + ), + documentation: DecodeDifferent::Encode(&[]), + } + ]) + ), + errors: DecodeDifferent::Encode(FnEncode(|| &[])), + }, + ModuleMetadata { + name: DecodeDifferent::Encode("Module"), + storage: None, + calls: Some( + DecodeDifferent::Encode(FnEncode(|| &[ + FunctionMetadata { + name: DecodeDifferent::Encode("aux_0"), + arguments: DecodeDifferent::Encode(&[]), + documentation: DecodeDifferent::Encode(&[]), + } + ]))), + event: Some(DecodeDifferent::Encode( + FnEncode(||&[ + EventMetadata { + name: DecodeDifferent::Encode("TestEvent"), + arguments: DecodeDifferent::Encode(&["Balance"]), + documentation: DecodeDifferent::Encode(&[" Hi, I am a comment."]) + } + ]) + )), + constants: DecodeDifferent::Encode(FnEncode(|| &[])), + errors: DecodeDifferent::Encode(FnEncode(|| &[ + ErrorMetadata { + name: DecodeDifferent::Encode("UserInputError"), + documentation: DecodeDifferent::Encode(&[" Some user input error"]), + }, + ErrorMetadata { + name: DecodeDifferent::Encode("BadThingHappened"), + documentation: DecodeDifferent::Encode(&[ + " Something bad happened", + " this could be due to many reasons", + ]), + }, + ])), + }, + ModuleMetadata { + name: DecodeDifferent::Encode("Module2"), + storage: Some(DecodeDifferent::Encode( + FnEncode(|| StorageMetadata { + prefix: DecodeDifferent::Encode("TestStorage"), + entries: DecodeDifferent::Encode( + &[ + StorageEntryMetadata { + name: DecodeDifferent::Encode("StorageMethod"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::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(&[]) + } + ]) + )), + constants: DecodeDifferent::Encode(FnEncode(|| &[])), + errors: DecodeDifferent::Encode(FnEncode(|| &[])), + }, + ]) + }; + + #[test] + fn runtime_metadata() { + let metadata_encoded = TestRuntime::metadata().encode(); + let metadata_decoded = RuntimeMetadataPrefixed::decode(&mut &metadata_encoded[..]); + let expected_metadata: RuntimeMetadataPrefixed = EXPECTED_METADATA.into(); + + pretty_assertions::assert_eq!(expected_metadata, metadata_decoded.unwrap()); + } +} diff --git a/srml/support/src/origin.rs b/frame/support/src/origin.rs similarity index 95% rename from srml/support/src/origin.rs rename to frame/support/src/origin.rs index 6da9bc1385836..43d2e70953af9 100644 --- a/srml/support/src/origin.rs +++ b/frame/support/src/origin.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -178,8 +178,8 @@ macro_rules! impl_outer_origin { $name::system(x) } } - impl Into<$crate::rstd::result::Result<$system::Origin<$runtime>, $name>> for $name { - fn into(self) -> $crate::rstd::result::Result<$system::Origin<$runtime>, Self> { + impl Into<$crate::sp_std::result::Result<$system::Origin<$runtime>, $name>> for $name { + fn into(self) -> $crate::sp_std::result::Result<$system::Origin<$runtime>, Self> { if let $name::system(l) = self { Ok(l) } else { @@ -200,12 +200,12 @@ macro_rules! impl_outer_origin { } } impl Into< - $crate::rstd::result::Result< + $crate::sp_std::result::Result< $module::Origin < $( $generic )? $(, $module::$generic_instance )? >, $name, >> for $name { - fn into(self) -> $crate::rstd::result::Result< + fn into(self) -> $crate::sp_std::result::Result< $module::Origin < $( $generic )? $(, $module::$generic_instance )? >, Self, > { diff --git a/frame/support/src/storage/child.rs b/frame/support/src/storage/child.rs new file mode 100644 index 0000000000000..f549ffc25fd94 --- /dev/null +++ b/frame/support/src/storage/child.rs @@ -0,0 +1,229 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Operation on runtime child storages. +//! +//! This module is a currently only a variant of unhashed with additional `storage_key`. +//! Note that `storage_key` must be unique and strong (strong in the sense of being long enough to +//! avoid collision from a resistant hash function (which unique implies)). +//! +//! A **key collision free** unique id is required as parameter to avoid key collision +//! between child tries. +//! This unique id management and generation responsability is delegated to pallet module. +// NOTE: could replace unhashed by having only one kind of storage (root being null storage key (storage_key can become Option<&[u8]>). + +use crate::sp_std::prelude::*; +use codec::{Codec, Encode, Decode}; +pub use sp_core::storage::ChildInfo; + +/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. +pub fn get( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], +) -> Option { + let (data, child_type) = child_info.info(); + sp_io::storage::child_get( + storage_key, + data, + child_type, + key, + ).and_then(|v| { + Decode::decode(&mut &v[..]).map(Some).unwrap_or_else(|_| { + // TODO #3700: error should be handleable. + runtime_print!("ERROR: Corrupted state in child trie at {:?}/{:?}", storage_key, key); + None + }) + }) +} + +/// Return the value of the item in storage under `key`, or the type's default if there is no +/// explicit entry. +pub fn get_or_default( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], +) -> T { + get(storage_key, child_info, key).unwrap_or_else(Default::default) +} + +/// Return the value of the item in storage under `key`, or `default_value` if there is no +/// explicit entry. +pub fn get_or( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + default_value: T, +) -> T { + get(storage_key, child_info, key).unwrap_or(default_value) +} + +/// Return the value of the item in storage under `key`, or `default_value()` if there is no +/// explicit entry. +pub fn get_or_else T>( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + default_value: F, +) -> T { + get(storage_key, child_info, key).unwrap_or_else(default_value) +} + +/// Put `value` in storage under `key`. +pub fn put( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + value: &T, +) { + let (data, child_type) = child_info.info(); + value.using_encoded(|slice| + sp_io::storage::child_set( + storage_key, + data, + child_type, + key, + slice, + ) + ); +} + +/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. +pub fn take( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], +) -> Option { + let r = get(storage_key, child_info, key); + if r.is_some() { + kill(storage_key, child_info, key); + } + r +} + +/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, +/// the default for its type. +pub fn take_or_default( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], +) -> T { + take(storage_key, child_info, key).unwrap_or_else(Default::default) +} + +/// Return the value of the item in storage under `key`, or `default_value` if there is no +/// explicit entry. Ensure there is no explicit entry on return. +pub fn take_or( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + default_value: T, +) -> T { + take(storage_key, child_info, key).unwrap_or(default_value) +} + +/// Return the value of the item in storage under `key`, or `default_value()` if there is no +/// explicit entry. Ensure there is no explicit entry on return. +pub fn take_or_else T>( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + default_value: F, +) -> T { + take(storage_key, child_info, key).unwrap_or_else(default_value) +} + +/// Check to see if `key` has an explicit entry in storage. +pub fn exists( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], +) -> bool { + let (data, child_type) = child_info.info(); + sp_io::storage::child_read( + storage_key, data, child_type, + key, &mut [0;0][..], 0, + ).is_some() +} + +/// Remove all `storage_key` key/values +pub fn kill_storage( + storage_key: &[u8], + child_info: ChildInfo, +) { + let (data, child_type) = child_info.info(); + sp_io::storage::child_storage_kill( + storage_key, + data, + child_type, + ) +} + +/// Ensure `key` has no explicit entry in storage. +pub fn kill( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], +) { + let (data, child_type) = child_info.info(); + sp_io::storage::child_clear( + storage_key, + data, + child_type, + key, + ); +} + +/// Get a Vec of bytes from storage. +pub fn get_raw( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], +) -> Option> { + let (data, child_type) = child_info.info(); + sp_io::storage::child_get( + storage_key, + data, + child_type, + key, + ) +} + +/// Put a raw byte slice into storage. +pub fn put_raw( + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + value: &[u8], +) { + let (data, child_type) = child_info.info(); + sp_io::storage::child_set( + storage_key, + data, + child_type, + key, + value, + ) +} + +/// Calculate current child root value. +pub fn child_root( + storage_key: &[u8], +) -> Vec { + sp_io::storage::child_root( + storage_key, + ) +} diff --git a/frame/support/src/storage/generator/double_map.rs b/frame/support/src/storage/generator/double_map.rs new file mode 100644 index 0000000000000..947235c4bd44f --- /dev/null +++ b/frame/support/src/storage/generator/double_map.rs @@ -0,0 +1,310 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sp_std::prelude::*; +use sp_std::borrow::Borrow; +use codec::{Ref, FullCodec, FullEncode, Encode, EncodeLike, EncodeAppend}; +use crate::{storage::{self, unhashed}, hash::{StorageHasher, Twox128}, traits::Len}; + +/// Generator for `StorageDoubleMap` used by `decl_storage`. +/// +/// # Mapping of keys to a storage path +/// +/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. +/// The first part is a hash of a concatenation of the `key1_prefix` and `Key1`. And the second part +/// is a hash of a `Key2`. +/// +/// Thus value for (key1, key2) is stored at: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++ Hasher2(encode(key2)) +/// ``` +/// +/// # Warning +/// +/// If the key1s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as +/// `blake2_256` must be used for Hasher1. Otherwise, other values in storage can be compromised. +/// If the key2s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as +/// `blake2_256` must be used for Hasher2. Otherwise, other items in storage with the same first +/// key can be compromised. +pub trait StorageDoubleMap { + /// The type that get/take returns. + type Query; + + /// Hasher for the first key. + type Hasher1: StorageHasher; + + /// Hasher for the second key. + type Hasher2: StorageHasher; + + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; + + /// Convert an optional value retrieved from storage to the type queried. + fn from_optional_value_to_query(v: Option) -> Self::Query; + + /// Convert a query to an optional value into storage. + fn from_query_to_optional_value(v: Self::Query) -> Option; + + /// Generate the first part of the key used in top storage. + fn storage_double_map_final_key1(k1: KArg1) -> Vec + where + KArg1: EncodeLike, + { + let module_prefix_hashed = Twox128::hash(Self::module_prefix()); + let storage_prefix_hashed = Twox128::hash(Self::storage_prefix()); + let key_hashed = k1.borrow().using_encoded(Self::Hasher1::hash); + + let mut final_key = Vec::with_capacity( + module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len() + ); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key_hashed.as_ref()); + + final_key + } + + /// Generate the full key used in top storage. + fn storage_double_map_final_key(k1: KArg1, k2: KArg2) -> Vec + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + let mut final_key = Self::storage_double_map_final_key1(k1); + final_key.extend_from_slice(k2.using_encoded(Self::Hasher2::hash).as_ref()); + final_key + } +} + +impl storage::StorageDoubleMap for G +where + K1: FullEncode, + K2: FullEncode, + V: FullCodec, + G: StorageDoubleMap, +{ + type Query = G::Query; + + fn hashed_key_for(k1: KArg1, k2: KArg2) -> Vec + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + Self::storage_double_map_final_key(k1, k2) + } + + fn exists(k1: KArg1, k2: KArg2) -> bool + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + unhashed::exists(&Self::storage_double_map_final_key(k1, k2)) + } + + fn get(k1: KArg1, k2: KArg2) -> Self::Query + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + G::from_optional_value_to_query(unhashed::get(&Self::storage_double_map_final_key(k1, k2))) + } + + fn take(k1: KArg1, k2: KArg2) -> Self::Query + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + let final_key = Self::storage_double_map_final_key(k1, k2); + + let value = unhashed::take(&final_key); + G::from_optional_value_to_query(value) + } + + fn swap(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2) + where + XKArg1: EncodeLike, + XKArg2: EncodeLike, + YKArg1: EncodeLike, + YKArg2: EncodeLike + { + let final_x_key = Self::storage_double_map_final_key(x_k1, x_k2); + let final_y_key = Self::storage_double_map_final_key(y_k1, y_k2); + + let v1 = unhashed::get_raw(&final_x_key); + if let Some(val) = unhashed::get_raw(&final_y_key) { + unhashed::put_raw(&final_x_key, &val); + } else { + unhashed::kill(&final_x_key) + } + if let Some(val) = v1 { + unhashed::put_raw(&final_y_key, &val); + } else { + unhashed::kill(&final_y_key) + } + } + + fn insert(k1: KArg1, k2: KArg2, val: VArg) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + VArg: EncodeLike, + { + unhashed::put(&Self::storage_double_map_final_key(k1, k2), &val.borrow()) + } + + fn remove(k1: KArg1, k2: KArg2) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + unhashed::kill(&Self::storage_double_map_final_key(k1, k2)) + } + + fn remove_prefix(k1: KArg1) where KArg1: EncodeLike { + unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref()) + } + + fn iter_prefix(k1: KArg1) -> storage::PrefixIterator + where KArg1: ?Sized + EncodeLike + { + let prefix = Self::storage_double_map_final_key1(k1); + storage::PrefixIterator:: { + prefix: prefix.clone(), + previous_key: prefix, + phantom_data: Default::default(), + } + } + + fn mutate(k1: KArg1, k2: KArg2, f: F) -> R + where + KArg1: EncodeLike, + KArg2: EncodeLike, + F: FnOnce(&mut Self::Query) -> R, + { + let final_key = Self::storage_double_map_final_key(k1, k2); + let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref())); + + let ret = f(&mut val); + match G::from_query_to_optional_value(val) { + Some(ref val) => unhashed::put(final_key.as_ref(), val), + None => unhashed::kill(final_key.as_ref()), + } + ret + } + + fn append( + k1: KArg1, + k2: KArg2, + items: Items, + ) -> Result<(), &'static str> + where + KArg1: EncodeLike, + KArg2: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator + { + let final_key = Self::storage_double_map_final_key(k1, k2); + + let encoded_value = unhashed::get_raw(&final_key) + .unwrap_or_else(|| { + match G::from_query_to_optional_value(G::from_optional_value_to_query(None)) { + Some(value) => value.encode(), + None => Vec::new(), + } + }); + + let new_val = V::append_or_new( + encoded_value, + items, + ).map_err(|_| "Could not append given item")?; + unhashed::put_raw(&final_key, &new_val); + + Ok(()) + } + + fn append_or_insert( + k1: KArg1, + k2: KArg2, + items: Items, + ) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator + { + Self::append(Ref::from(&k1), Ref::from(&k2), items.clone()) + .unwrap_or_else(|_| Self::insert(k1, k2, items)); + } + + fn decode_len(key1: KArg1, key2: KArg2) -> Result + where KArg1: EncodeLike, + KArg2: EncodeLike, + V: codec::DecodeLength + Len, + { + let final_key = Self::storage_double_map_final_key(key1, key2); + if let Some(v) = unhashed::get_raw(&final_key) { + ::len(&v).map_err(|e| e.what()) + } else { + let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) + .map(|v| v.len()) + .unwrap_or(0); + + Ok(len) + } + } +} + +#[cfg(test)] +mod test { + use sp_io::TestExternalities; + use crate::storage::{self, StorageDoubleMap}; + use crate::hash::Twox128; + + #[test] + fn iter_prefix_works() { + TestExternalities::default().execute_with(|| { + struct MyStorage; + impl storage::generator::StorageDoubleMap for MyStorage { + type Query = Option; + fn module_prefix() -> &'static [u8] { b"MyModule" } + fn storage_prefix() -> &'static [u8] { b"MyStorage" } + type Hasher1 = Twox128; + type Hasher2 = Twox128; + fn from_optional_value_to_query(v: Option) -> Self::Query { v } + fn from_query_to_optional_value(v: Self::Query) -> Option { v } + } + + MyStorage::insert(1, 3, 7); + MyStorage::insert(1, 4, 8); + MyStorage::insert(2, 5, 9); + MyStorage::insert(2, 6, 10); + + assert_eq!(MyStorage::iter_prefix(1).collect::>(), vec![7, 8]); + assert_eq!(MyStorage::iter_prefix(2).collect::>(), vec![10, 9]); + }); + } +} diff --git a/frame/support/src/storage/generator/linked_map.rs b/frame/support/src/storage/generator/linked_map.rs new file mode 100644 index 0000000000000..14bef77c9e40b --- /dev/null +++ b/frame/support/src/storage/generator/linked_map.rs @@ -0,0 +1,497 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::{FullCodec, Encode, Decode, EncodeLike, Ref}; +use crate::{storage::{self, unhashed}, hash::{StorageHasher, Twox128}, traits::Len}; +use sp_std::{prelude::*, marker::PhantomData}; + +/// Generator for `StorageLinkedMap` used by `decl_storage`. +/// +/// By default final key generation rely on `KeyFormat`. +pub trait StorageLinkedMap { + /// The type that get/take returns. + type Query; + + /// The family of key formats used for this map. + type KeyFormat: KeyFormat; + + /// Convert an optional value retrieved from storage to the type queried. + fn from_optional_value_to_query(v: Option) -> Self::Query; + + /// Convert a query to an optional value into storage. + fn from_query_to_optional_value(v: Self::Query) -> Option; + + /// Generate the full key used in top storage. + fn storage_linked_map_final_key(key: KeyArg) -> Vec + where + KeyArg: EncodeLike, + { + ::storage_linked_map_final_key::(&key) + } + + /// Generate the hashed key for head + fn storage_linked_map_final_head_key() -> Vec { + ::storage_linked_map_final_head_key() + } +} + +/// A type-abstracted key format used for a family of linked-map types. +/// +/// # Default mapping of keys to a storage path +/// +/// The key for the head of the map is stored at one fixed path: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(head_prefix) +/// ``` +/// +/// For each key, the value stored under that key is appended with a +/// [`Linkage`](struct.Linkage.html) (which hold previous and next key) at the path: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key)) +/// ``` +/// +/// Enumeration is done by getting the head of the linked map and then iterating getting the +/// value and linkage stored at the key until the found linkage has no next key. +/// +/// # Warning +/// +/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as +/// `blake2_256` must be used. Otherwise, other values in storage can be compromised. +pub trait KeyFormat { + /// Hasher. Used for generating final key and final head key. + type Hasher: StorageHasher; + + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final head key. + fn head_prefix() -> &'static [u8]; + + /// Generate the full key used in top storage. + fn storage_linked_map_final_key(key: &K) -> Vec + where + K: Encode, + { + let module_prefix_hashed = Twox128::hash(Self::module_prefix()); + let storage_prefix_hashed = Twox128::hash(Self::storage_prefix()); + let key_hashed = key.using_encoded(Self::Hasher::hash); + + let mut final_key = Vec::with_capacity( + module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len() + ); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key_hashed.as_ref()); + + final_key + } + + /// Generate the full key used in top storage to store the head of the linked map. + fn storage_linked_map_final_head_key() -> Vec { + [ + Twox128::hash(Self::module_prefix()), + Twox128::hash(Self::head_prefix()), + ].concat() + } +} + +/// Linkage data of an element (it's successor and predecessor) +#[derive(Encode, Decode)] +pub struct Linkage { + /// Previous element key in storage (None for the first element) + pub previous: Option, + /// Next element key in storage (None for the last element) + pub next: Option, +} + +impl Default for Linkage { + fn default() -> Self { + Self { + previous: None, + next: None, + } + } +} + +// Encode like a linkage. +#[derive(Encode)] +struct EncodeLikeLinkage, NKey: EncodeLike, Key: Encode> { + // Previous element key in storage (None for the first element) + previous: Option, + // Next element key in storage (None for the last element) + next: Option, + // The key of the linkage this type encode to + phantom: core::marker::PhantomData, +} + +/// A key-value pair iterator for enumerable map. +pub struct Enumerator { + next: Option, + _phantom: PhantomData<(V, F)>, +} + +impl Enumerator { + /// Create an explicit enumerator for testing. + #[cfg(test)] + pub fn from_head(head: K) -> Self { + Enumerator { + next: Some(head), + _phantom: Default::default(), + } + } +} + +impl Iterator for Enumerator +where + K: FullCodec, + V: FullCodec, + F: KeyFormat, +{ + type Item = (K, V); + + fn next(&mut self) -> Option { + let next = self.next.take()?; + + let (val, linkage): (V, Linkage) = { + let next_full_key = F::storage_linked_map_final_key(&next); + match read_with_linkage::(next_full_key.as_ref()) { + Some(value) => value, + None => { + // TODO #3700: error should be handleable. + runtime_print!( + "ERROR: Corrupted state: linked map {:?}{:?}: \ + next value doesn't exist at {:?}", + F::module_prefix(), F::storage_prefix(), next_full_key, + ); + return None + } + } + }; + + self.next = linkage.next; + Some((next, val)) + } +} + +/// Update linkage when this element is removed. +/// +/// Takes care of updating previous and next elements points +/// as well as updates head if the element is first or last. +fn remove_linkage(linkage: Linkage) +where + K: FullCodec, + V: FullCodec, + F: KeyFormat, +{ + let next_key = linkage.next.as_ref().map(|k| F::storage_linked_map_final_key(k)); + let prev_key = linkage.previous.as_ref().map(|k| F::storage_linked_map_final_key(k)); + + if let Some(prev_key) = prev_key { + // Retrieve previous element and update `next` + if let Some(mut res) = read_with_linkage::(prev_key.as_ref()) { + res.1.next = linkage.next; + unhashed::put(prev_key.as_ref(), &res); + } else { + // TODO #3700: error should be handleable. + runtime_print!( + "ERROR: Corrupted state: linked map {:?}{:?}: \ + previous value doesn't exist at {:?}", + F::module_prefix(), F::storage_prefix(), prev_key, + ); + } + } else { + // we were first so let's update the head + write_head::<&K, K, F>(linkage.next.as_ref()); + } + if let Some(next_key) = next_key { + // Update previous of next element + if let Some(mut res) = read_with_linkage::(next_key.as_ref()) { + res.1.previous = linkage.previous; + unhashed::put(next_key.as_ref(), &res); + } else { + // TODO #3700: error should be handleable. + runtime_print!( + "ERROR: Corrupted state: linked map {:?}{:?}: \ + next value doesn't exist at {:?}", + F::module_prefix(), F::storage_prefix(), next_key, + ); + } + } +} + +/// Read the contained data and its linkage. +pub(super) fn read_with_linkage(key: &[u8]) -> Option<(V, Linkage)> +where + K: Decode, + V: Decode, +{ + unhashed::get(key) +} + +/// Generate linkage for newly inserted element. +/// +/// Takes care of updating head and previous head's pointer. +pub(super) fn new_head_linkage(key: KeyArg) -> Linkage +where + KeyArg: EncodeLike, + K: FullCodec, + V: FullCodec, + F: KeyFormat, +{ + if let Some(head) = read_head::() { + // update previous head predecessor + { + let head_key = F::storage_linked_map_final_key(&head); + if let Some((data, linkage)) = read_with_linkage::(head_key.as_ref()) { + let new_linkage = EncodeLikeLinkage::<_, _, K> { + previous: Some(Ref::from(&key)), + next: linkage.next.as_ref(), + phantom: Default::default(), + }; + unhashed::put(head_key.as_ref(), &(data, new_linkage)); + } else { + // TODO #3700: error should be handleable. + runtime_print!( + "ERROR: Corrupted state: linked map {:?}{:?}: \ + head value doesn't exist at {:?}", + F::module_prefix(), F::storage_prefix(), head_key, + ); + // Thus we consider we are first - update the head and produce empty linkage + + write_head::<_, _, F>(Some(key)); + return Linkage::default(); + } + } + // update to current head + write_head::<_, _, F>(Some(key)); + // return linkage with pointer to previous head + let mut linkage = Linkage::default(); + linkage.next = Some(head); + linkage + } else { + // we are first - update the head and produce empty linkage + write_head::<_, _, F>(Some(key)); + Linkage::default() + } +} + +/// Read current head pointer. +pub(crate) fn read_head() -> Option +where + K: Decode, + F: KeyFormat, +{ + unhashed::get(F::storage_linked_map_final_head_key().as_ref()) +} + +/// Overwrite current head pointer. +/// +/// If `None` is given head is removed from storage. +pub(super) fn write_head(head: Option) +where + KeyArg: EncodeLike, + K: FullCodec, + F: KeyFormat, +{ + match head.as_ref() { + Some(head) => unhashed::put(F::storage_linked_map_final_head_key().as_ref(), head), + None => unhashed::kill(F::storage_linked_map_final_head_key().as_ref()), + } +} + +impl storage::StorageLinkedMap for G +where + K: FullCodec, + V: FullCodec, + G: StorageLinkedMap, +{ + type Query = G::Query; + + type Enumerator = Enumerator; + + fn exists>(key: KeyArg) -> bool { + unhashed::exists(Self::storage_linked_map_final_key(key).as_ref()) + } + + fn get>(key: KeyArg) -> Self::Query { + let val = unhashed::get(Self::storage_linked_map_final_key(key).as_ref()); + G::from_optional_value_to_query(val) + } + + fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2) { + let final_key1 = Self::storage_linked_map_final_key(Ref::from(&key1)); + let final_key2 = Self::storage_linked_map_final_key(Ref::from(&key2)); + let full_value_1 = read_with_linkage::(final_key1.as_ref()); + let full_value_2 = read_with_linkage::(final_key2.as_ref()); + + match (full_value_1, full_value_2) { + // Just keep linkage in order and only swap values. + (Some((value1, linkage1)), Some((value2, linkage2))) => { + unhashed::put(final_key1.as_ref(), &(value2, linkage1)); + unhashed::put(final_key2.as_ref(), &(value1, linkage2)); + } + // Remove key and insert the new one. + (Some((value, _linkage)), None) => { + Self::remove(key1); + let linkage = new_head_linkage::<_, _, V, G::KeyFormat>(key2); + unhashed::put(final_key2.as_ref(), &(value, linkage)); + } + // Remove key and insert the new one. + (None, Some((value, _linkage))) => { + Self::remove(key2); + let linkage = new_head_linkage::<_, _, V, G::KeyFormat>(key1); + unhashed::put(final_key1.as_ref(), &(value, linkage)); + } + // No-op. + (None, None) => (), + } + } + + fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg) { + let final_key = Self::storage_linked_map_final_key(Ref::from(&key)); + let linkage = match read_with_linkage::<_, V>(final_key.as_ref()) { + // overwrite but reuse existing linkage + Some((_data, linkage)) => linkage, + // create new linkage + None => new_head_linkage::<_, _, V, G::KeyFormat>(key), + }; + unhashed::put(final_key.as_ref(), &(val, linkage)) + } + + fn remove>(key: KeyArg) { + G::take(key); + } + + fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R { + let final_key = Self::storage_linked_map_final_key(Ref::from(&key)); + + let (mut val, _linkage) = read_with_linkage::(final_key.as_ref()) + .map(|(data, linkage)| (G::from_optional_value_to_query(Some(data)), Some(linkage))) + .unwrap_or_else(|| (G::from_optional_value_to_query(None), None)); + + let ret = f(&mut val); + match G::from_query_to_optional_value(val) { + Some(ref val) => G::insert(key, val), + None => G::remove(key), + } + ret + } + + fn take>(key: KeyArg) -> Self::Query { + let final_key = Self::storage_linked_map_final_key(key); + + let full_value: Option<(V, Linkage)> = unhashed::take(final_key.as_ref()); + + let value = full_value.map(|(data, linkage)| { + remove_linkage::(linkage); + data + }); + + G::from_optional_value_to_query(value) + } + + fn enumerate() -> Self::Enumerator { + Enumerator::<_, _, G::KeyFormat> { + next: read_head::<_, G::KeyFormat>(), + _phantom: Default::default(), + } + } + + fn head() -> Option { + read_head::<_, G::KeyFormat>() + } + + fn decode_len>(key: KeyArg) -> Result + where V: codec::DecodeLength + Len + { + let key = Self::storage_linked_map_final_key(key); + if let Some(v) = unhashed::get_raw(key.as_ref()) { + ::len(&v).map_err(|e| e.what()) + } else { + let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) + .map(|v| v.len()) + .unwrap_or(0); + + Ok(len) + } + } + + fn translate(translate_key: TK, translate_val: TV) -> Result<(), Option> + where K2: FullCodec + Clone, V2: Decode, TK: Fn(K2) -> K, TV: Fn(V2) -> V + { + let head_key = read_head::().ok_or(None)?; + + let mut last_key = None; + let mut current_key = head_key.clone(); + + write_head::<&K, K, G::KeyFormat>(Some(&translate_key(head_key))); + + let translate_linkage = |old: Linkage| -> Linkage { + Linkage { + previous: old.previous.map(&translate_key), + next: old.next.map(&translate_key), + } + }; + + loop { + let old_raw_key = G::KeyFormat::storage_linked_map_final_key(¤t_key); + let x = unhashed::take(old_raw_key.as_ref()); + let (val, linkage): (V2, Linkage) = match x { + Some(v) => v, + None => { + // we failed to read value and linkage. Update the last key's linkage + // to end the map early, since it's impossible to iterate further. + if let Some(last_key) = last_key { + let last_raw_key = G::storage_linked_map_final_key(&last_key); + if let Some((val, mut linkage)) + = read_with_linkage::(last_raw_key.as_ref()) + { + // defensive: should always happen, since it was just written + // in the last iteration of the loop. + linkage.next = None; + unhashed::put(last_raw_key.as_ref(), &(&val, &linkage)); + } + } + + return Err(Some(current_key)); + } + }; + let next = linkage.next.clone(); + + let val = translate_val(val); + let linkage = translate_linkage(linkage); + + // and write in the value and linkage under the new key. + let new_key = translate_key(current_key.clone()); + let new_raw_key = G::storage_linked_map_final_key(&new_key); + unhashed::put(new_raw_key.as_ref(), &(&val, &linkage)); + + match next { + None => break, + Some(next) => { + last_key = Some(new_key); + current_key = next + }, + } + } + + Ok(()) + } +} diff --git a/srml/support/src/storage/generator/map.rs b/frame/support/src/storage/generator/map.rs similarity index 80% rename from srml/support/src/storage/generator/map.rs rename to frame/support/src/storage/generator/map.rs index 3c3edac28a42a..78f261e7daf48 100644 --- a/srml/support/src/storage/generator/map.rs +++ b/frame/support/src/storage/generator/map.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,16 +15,16 @@ // along with Substrate. If not, see . #[cfg(not(feature = "std"))] -use rstd::prelude::*; -use rstd::borrow::Borrow; +use sp_std::prelude::*; +use sp_std::borrow::Borrow; use codec::{FullCodec, FullEncode, Encode, EncodeLike, Ref, EncodeAppend}; -use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len}; +use crate::{storage::{self, unhashed}, hash::{StorageHasher, Twox128}, traits::Len}; /// Generator for `StorageMap` used by `decl_storage`. /// -/// For each key value is stored at: +/// By default each key value is stored at: /// ```nocompile -/// Hasher(prefix ++ key) +/// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key)) /// ``` /// /// # Warning @@ -35,11 +35,14 @@ pub trait StorageMap { /// The type that get/take returns. type Query; - /// Hasher used to insert into storage. + /// Hasher. Used for generating final key. type Hasher: StorageHasher; - /// Prefix used to prepend each key. - fn prefix() -> &'static [u8]; + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; /// Convert an optional value retrieved from storage to the type queried. fn from_optional_value_to_query(v: Option) -> Self::Query; @@ -48,13 +51,23 @@ pub trait StorageMap { fn from_query_to_optional_value(v: Self::Query) -> Option; /// Generate the full key used in top storage. - fn storage_map_final_key(key: KeyArg) -> ::Output + fn storage_map_final_key(key: KeyArg) -> Vec where KeyArg: EncodeLike, { - let mut final_key = Self::prefix().to_vec(); - key.borrow().encode_to(&mut final_key); - Self::Hasher::hash(&final_key) + let module_prefix_hashed = Twox128::hash(Self::module_prefix()); + let storage_prefix_hashed = Twox128::hash(Self::storage_prefix()); + let key_hashed = key.borrow().using_encoded(Self::Hasher::hash); + + let mut final_key = Vec::with_capacity( + module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len() + ); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key_hashed.as_ref()); + + final_key } } @@ -62,7 +75,7 @@ impl> storage::StorageMap type Query = G::Query; fn hashed_key_for>(key: KeyArg) -> Vec { - Self::storage_map_final_key(key).as_ref().to_vec() + Self::storage_map_final_key(key) } fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2) { @@ -130,7 +143,7 @@ impl> storage::StorageMap .unwrap_or_else(|| { match G::from_query_to_optional_value(G::from_optional_value_to_query(None)) { Some(value) => value.encode(), - None => vec![], + None => Vec::new(), } }); diff --git a/frame/support/src/storage/generator/mod.rs b/frame/support/src/storage/generator/mod.rs new file mode 100644 index 0000000000000..386e3d1cecaef --- /dev/null +++ b/frame/support/src/storage/generator/mod.rs @@ -0,0 +1,128 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generators are a set of trait on which storage traits are implemented. +//! +//! (i.e. implementing the generator for StorageValue on a type will automatically derive the +//! implementation of StorageValue for this type). +//! +//! They are used by `decl_storage`. + +mod linked_map; +mod map; +mod double_map; +mod value; + +pub use linked_map::{StorageLinkedMap, Enumerator, Linkage, KeyFormat as LinkedMapKeyFormat}; +pub use map::StorageMap; +pub use double_map::StorageDoubleMap; +pub use value::StorageValue; + + +#[cfg(test)] +#[allow(dead_code)] +mod tests { + use sp_io::TestExternalities; + use codec::{Encode, Decode}; + use crate::storage::{unhashed, generator::{StorageValue, StorageLinkedMap}}; + + struct Runtime {} + pub trait Trait { + type Origin; + type BlockNumber; + } + + impl Trait for Runtime { + type Origin = u32; + type BlockNumber = u32; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + #[derive(Encode, Decode, Clone, Debug, Eq, PartialEq)] + struct NumberNumber { + a: u32, + b: u32, + } + + crate::decl_storage! { + trait Store for Module as Runtime { + Value get(fn value) config(): (u64, u64); + NumberMap: linked_map NumberNumber => u64; + } + } + + #[test] + fn value_translate_works() { + let t = GenesisConfig::default().build_storage().unwrap(); + TestExternalities::new(t).execute_with(|| { + // put the old value `1111u32` in the storage. + let key = Value::storage_value_final_key(); + unhashed::put_raw(&key, &1111u32.encode()); + + // translate + let translate_fn = |old: Option| -> Option<(u64, u64)> { + old.map(|o| (o.into(), (o*2).into())) + }; + let _ = Value::translate(translate_fn); + + // new storage should be `(1111, 1111 * 2)` + assert_eq!(Value::get(), (1111, 2222)); + }) + } + + #[test] + fn linked_map_translate_works() { + use super::linked_map::{self, Enumerator, KeyFormat}; + + type Format = >::KeyFormat; + + let t = GenesisConfig::default().build_storage().unwrap(); + TestExternalities::new(t).execute_with(|| { + // start with a map of u32 -> u32. + for i in 0u32..100u32 { + let final_key = ::storage_linked_map_final_key(&i); + + let linkage = linked_map::new_head_linkage::<_, u32, u32, Format>(&i); + unhashed::put(final_key.as_ref(), &(&i, linkage)); + } + + let head = linked_map::read_head::().unwrap(); + + assert_eq!( + Enumerator::::from_head(head).collect::>(), + (0..100).rev().map(|x| (x, x)).collect::>(), + ); + + // do translation. + NumberMap::translate( + |k: u32| NumberNumber { a: k, b: k }, + |v: u32| (v as u64) << 32 | v as u64, + ).unwrap(); + + assert!(linked_map::read_head::().is_some()); + assert_eq!( + NumberMap::enumerate().collect::>(), + (0..100u32).rev().map(|x| ( + NumberNumber { a: x, b: x }, + (x as u64) << 32 | x as u64, + )).collect::>(), + ); + }) + } +} diff --git a/srml/support/src/storage/generator/value.rs b/frame/support/src/storage/generator/value.rs similarity index 78% rename from srml/support/src/storage/generator/value.rs rename to frame/support/src/storage/generator/value.rs index 8423503dde20e..44641b85f7a3e 100644 --- a/srml/support/src/storage/generator/value.rs +++ b/frame/support/src/storage/generator/value.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,22 +15,25 @@ // along with Substrate. If not, see . #[cfg(not(feature = "std"))] -use rstd::prelude::*; -use codec::{FullCodec, Encode, EncodeAppend, EncodeLike}; +use sp_std::prelude::*; +use codec::{FullCodec, Encode, EncodeAppend, EncodeLike, Decode}; use crate::{storage::{self, unhashed}, hash::{Twox128, StorageHasher}, traits::Len}; /// Generator for `StorageValue` used by `decl_storage`. /// -/// Value is stored at: +/// By default value is stored at: /// ```nocompile -/// Twox128(unhashed_key) +/// Twox128(module_prefix) ++ Twox128(storage_prefix) /// ``` pub trait StorageValue { /// The type that get/take returns. type Query; - /// Unhashed key used in storage - fn unhashed_key() -> &'static [u8]; + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; /// Convert an optional value retrieved from storage to the type queried. fn from_optional_value_to_query(v: Option) -> Self::Query; @@ -39,15 +42,18 @@ pub trait StorageValue { fn from_query_to_optional_value(v: Self::Query) -> Option; /// Generate the full key used in top storage. - fn storage_value_final_key() -> [u8; 16] { - Twox128::hash(Self::unhashed_key()) + fn storage_value_final_key() -> [u8; 32] { + let mut final_key = [0u8; 32]; + final_key[0..16].copy_from_slice(&Twox128::hash(Self::module_prefix())); + final_key[16..32].copy_from_slice(&Twox128::hash(Self::storage_prefix())); + final_key } } impl> storage::StorageValue for G { type Query = G::Query; - fn hashed_key() -> [u8; 16] { + fn hashed_key() -> [u8; 32] { Self::storage_value_final_key() } @@ -60,6 +66,23 @@ impl> storage::StorageValue for G { G::from_optional_value_to_query(value) } + fn translate) -> Option>(f: F) -> Result, ()> { + let key = Self::storage_value_final_key(); + + // attempt to get the length directly. + let maybe_old = match unhashed::get_raw(&key) { + Some(old_data) => Some(O::decode(&mut &old_data[..]).map_err(|_| ())?), + None => None, + }; + let maybe_new = f(maybe_old); + if let Some(new) = maybe_new.as_ref() { + new.using_encoded(|d| unhashed::put_raw(&key, d)); + } else { + unhashed::kill(&key); + } + Ok(maybe_new) + } + fn put>(val: Arg) { unhashed::put(&Self::storage_value_final_key(), &val) } @@ -104,7 +127,7 @@ impl> storage::StorageValue for G { .unwrap_or_else(|| { match G::from_query_to_optional_value(G::from_optional_value_to_query(None)) { Some(value) => value.encode(), - None => vec![], + None => Vec::new(), } }); diff --git a/srml/support/src/storage/hashed.rs b/frame/support/src/storage/hashed.rs similarity index 98% rename from srml/support/src/storage/hashed.rs rename to frame/support/src/storage/hashed.rs index 2eca8f5bcafbc..a3ffddcb84105 100644 --- a/srml/support/src/storage/hashed.rs +++ b/frame/support/src/storage/hashed.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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 @@ //! Operation on runtime storage using hashed keys. use super::unhashed; -use rstd::prelude::*; +use sp_std::prelude::*; use codec::{Encode, Decode}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. diff --git a/frame/support/src/storage/mod.rs b/frame/support/src/storage/mod.rs new file mode 100644 index 0000000000000..0908adae3b604 --- /dev/null +++ b/frame/support/src/storage/mod.rs @@ -0,0 +1,554 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Stuff to do with the runtime's storage. + +use sp_std::{prelude::*, marker::PhantomData}; +use codec::{FullCodec, FullEncode, Encode, EncodeAppend, EncodeLike, Decode}; +use crate::{traits::Len, hash::{Twox128, StorageHasher}}; + +pub mod unhashed; +pub mod hashed; +pub mod child; +pub mod generator; + +/// A trait for working with macro-generated storage values under the substrate storage API. +/// +/// Details on implementation can be found at +/// [`generator::StorageValue`] +pub trait StorageValue { + /// The type that get/take return. + type Query; + + /// Get the storage key. + fn hashed_key() -> [u8; 32]; + + /// Does the value (explicitly) exist in storage? + fn exists() -> bool; + + /// Load the value from the provided storage instance. + fn get() -> Self::Query; + + /// Translate a value from some previous type (`O`) to the current type. + /// + /// `f: F` is the translation function. + /// + /// Returns `Err` if the storage item could not be interpreted as the old type, and Ok, along + /// with the new value if it could. + /// + /// NOTE: This operates from and to `Option<_>` types; no effort is made to respect the default + /// value of the original type. + /// + /// # Warning + /// + /// This function must be used with care, before being updated the storage still contains the + /// old type, thus other calls (such as `get`) will fail at decoding it. + /// + /// # Usage + /// + /// This would typically be called inside the module implementation of on_initialize, while + /// ensuring **no usage of this storage are made before the call to `on_initialize`**. (More + /// precisely prior initialized modules doesn't make use of this storage). + fn translate) -> Option>(f: F) -> Result, ()>; + + /// Store a value under this key into the provided storage instance. + fn put>(val: Arg); + + /// Mutate the value + fn mutate R>(f: F) -> R; + + /// Clear the storage value. + fn kill(); + + /// Take a value from storage, removing it afterwards. + fn take() -> Self::Query; + + /// Append the given item to the value in the storage. + /// + /// `T` is required to implement `codec::EncodeAppend`. + fn append(items: Items) -> Result<(), &'static str> + where + Item: Encode, + EncodeLikeItem: EncodeLike, + T: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator; + + /// Append the given items to the value in the storage. + /// + /// `T` is required to implement `Codec::EncodeAppend`. + /// + /// Upon any failure, it replaces `items` as the new value (assuming that the previous stored + /// data is simply corrupt and no longer usable). + /// + /// ### WARNING + /// + /// use with care; if your use-case is not _exactly_ as what this function is doing, + /// you should use append and sensibly handle failure within the runtime code if it happens. + fn append_or_put(items: Items) where + Item: Encode, + EncodeLikeItem: EncodeLike, + T: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator; + + + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `T` is required to implement `Codec::DecodeLength`. + fn decode_len() -> Result + where T: codec::DecodeLength + Len; +} + +/// A strongly-typed map in storage. +/// +/// Details on implementation can be found at +/// [`generator::StorageMap`] +pub trait StorageMap { + /// The type that get/take return. + type Query; + + /// Get the storage key used to fetch a value corresponding to a specific key. + fn hashed_key_for>(key: KeyArg) -> Vec; + + /// Does the value (explicitly) exist in storage? + fn exists>(key: KeyArg) -> bool; + + /// Load the value associated with the given key from the map. + fn get>(key: KeyArg) -> Self::Query; + + /// Swap the values of two keys. + fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2); + + /// Store a value to be associated with the given key from the map. + fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg); + + /// Remove the value under a key. + fn remove>(key: KeyArg); + + /// Mutate the value under a key. + fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R; + + /// Take the value under a key. + fn take>(key: KeyArg) -> Self::Query; + + /// Append the given items to the value in the storage. + /// + /// `V` is required to implement `codec::EncodeAppend`. + fn append(key: KeyArg, items: Items) -> Result<(), &'static str> + where + KeyArg: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator; + + /// Safely append the given items to the value in the storage. If a codec error occurs, then the + /// old (presumably corrupt) value is replaced with the given `items`. + /// + /// `V` is required to implement `codec::EncodeAppend`. + fn append_or_insert(key: KeyArg, items: Items) + where + KeyArg: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator; + + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `T` is required to implement `Codec::DecodeLength`. + /// + /// Note that `0` is returned as the default value if no encoded value exists at the given key. + /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` + /// function for this purpose. + fn decode_len>(key: KeyArg) -> Result + where V: codec::DecodeLength + Len; +} + +/// A strongly-typed linked map in storage. +/// +/// Similar to `StorageMap` but allows to enumerate other elements and doesn't implement append. +/// +/// Details on implementation can be found at +/// [`generator::StorageLinkedMap`] +pub trait StorageLinkedMap { + /// The type that get/take return. + type Query; + + /// The type that iterates over all `(key, value)`. + type Enumerator: Iterator; + + /// Does the value (explicitly) exist in storage? + fn exists>(key: KeyArg) -> bool; + + /// Load the value associated with the given key from the map. + fn get>(key: KeyArg) -> Self::Query; + + /// Swap the values of two keys. + fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2); + + /// Store a value to be associated with the given key from the map. + fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg); + + /// Remove the value under a key. + fn remove>(key: KeyArg); + + /// Mutate the value under a key. + fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R; + + /// Take the value under a key. + fn take>(key: KeyArg) -> Self::Query; + + /// Return current head element. + fn head() -> Option; + + /// Enumerate all elements in the map. + fn enumerate() -> Self::Enumerator; + + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `T` is required to implement `Codec::DecodeLength`. + /// + /// Note that `0` is returned as the default value if no encoded value exists at the given key. + /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` + /// function for this purpose. + fn decode_len>(key: KeyArg) -> Result + where V: codec::DecodeLength + Len; + + /// Translate the keys and values from some previous `(K2, V2)` to the current type. + /// + /// `TK` translates keys from the old type, and `TV` translates values. + /// + /// Returns `Err` if the map could not be interpreted as the old type, and Ok if it could. + /// The `Err` contains the first key which could not be migrated, or `None` if the + /// head of the list could not be read. + /// + /// # Warning + /// + /// This function must be used with care, before being updated the storage still contains the + /// old type, thus other calls (such as `get`) will fail at decoding it. + /// + /// # Usage + /// + /// This would typically be called inside the module implementation of on_initialize, while + /// ensuring **no usage of this storage are made before the call to `on_initialize`**. (More + /// precisely prior initialized modules doesn't make use of this storage). + fn translate(translate_key: TK, translate_val: TV) -> Result<(), Option> + where K2: FullCodec + Clone, V2: Decode, TK: Fn(K2) -> K, TV: Fn(V2) -> V; +} + +/// 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. +/// +/// Details on implementation can be found at +/// [`generator::StorageDoubleMap`] +pub trait StorageDoubleMap { + /// The type that get/take returns. + type Query; + + fn hashed_key_for(k1: KArg1, k2: KArg2) -> Vec + where + KArg1: EncodeLike, + KArg2: EncodeLike; + + fn exists(k1: KArg1, k2: KArg2) -> bool + where + KArg1: EncodeLike, + KArg2: EncodeLike; + + fn get(k1: KArg1, k2: KArg2) -> Self::Query + where + KArg1: EncodeLike, + KArg2: EncodeLike; + + fn take(k1: KArg1, k2: KArg2) -> Self::Query + where + KArg1: EncodeLike, + KArg2: EncodeLike; + + /// Swap the values of two key-pairs. + fn swap(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2) + where + XKArg1: EncodeLike, + XKArg2: EncodeLike, + YKArg1: EncodeLike, + YKArg2: EncodeLike; + + fn insert(k1: KArg1, k2: KArg2, val: VArg) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + VArg: EncodeLike; + + fn remove(k1: KArg1, k2: KArg2) + where + KArg1: EncodeLike, + KArg2: EncodeLike; + + fn remove_prefix(k1: KArg1) where KArg1: ?Sized + EncodeLike; + + fn iter_prefix(k1: KArg1) -> PrefixIterator + where KArg1: ?Sized + EncodeLike; + + fn mutate(k1: KArg1, k2: KArg2, f: F) -> R + where + KArg1: EncodeLike, + KArg2: EncodeLike, + F: FnOnce(&mut Self::Query) -> R; + + fn append( + k1: KArg1, + k2: KArg2, + items: Items, + ) -> Result<(), &'static str> + where + KArg1: EncodeLike, + KArg2: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator; + + fn append_or_insert( + k1: KArg1, + k2: KArg2, + items: Items, + ) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator; + + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `V` is required to implement `Codec::DecodeLength`. + /// + /// Note that `0` is returned as the default value if no encoded value exists at the given key. + /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` + /// function for this purpose. + fn decode_len(key1: KArg1, key2: KArg2) -> Result + where + KArg1: EncodeLike, + KArg2: EncodeLike, + V: codec::DecodeLength + Len; +} + +/// Iterator for prefixed map. +pub struct PrefixIterator { + prefix: Vec, + previous_key: Vec, + phantom_data: PhantomData, +} + +impl Iterator for PrefixIterator { + type Item = Value; + + fn next(&mut self) -> Option { + match sp_io::storage::next_key(&self.previous_key) + .filter(|n| n.starts_with(&self.prefix[..])) + { + Some(next_key) => { + let value = unhashed::get(&next_key); + + if value.is_none() { + runtime_print!( + "ERROR: returned next_key has no value:\nkey is {:?}\nnext_key is {:?}", + &self.previous_key, &next_key, + ); + } + + self.previous_key = next_key; + + value + }, + _ => None, + } + } +} + +/// Trait for maps that store all its value after a unique prefix. +/// +/// By default the final prefix is: +/// ```nocompile +/// Twox128(module_prefix) ++ Twox128(storage_prefix) +/// ``` +pub trait StoragePrefixedMap { + + /// Module prefix. Used for generating final key. + fn module_prefix() -> &'static [u8]; + + /// Storage prefix. Used for generating final key. + fn storage_prefix() -> &'static [u8]; + + /// Final full prefix that prefixes all keys. + fn final_prefix() -> [u8; 32] { + let mut final_key = [0u8; 32]; + final_key[0..16].copy_from_slice(&Twox128::hash(Self::module_prefix())); + final_key[16..32].copy_from_slice(&Twox128::hash(Self::storage_prefix())); + final_key + } + + /// Remove all value of the storage. + fn remove_all() { + sp_io::storage::clear_prefix(&Self::final_prefix()) + } + + /// Iter over all value of the storage. + fn iter() -> PrefixIterator { + let prefix = Self::final_prefix(); + PrefixIterator { + prefix: prefix.to_vec(), + previous_key: prefix.to_vec(), + phantom_data: Default::default(), + } + } + + /// Translate the values from some previous `OldValue` to the current type. + /// + /// `TV` translates values. + /// + /// Returns `Err` if the map could not be interpreted as the old type, and Ok if it could. + /// The `Err` contains the number of value that couldn't be interpreted, those value are + /// removed from the map. + /// + /// # Warning + /// + /// This function must be used with care, before being updated the storage still contains the + /// old type, thus other calls (such as `get`) will fail at decoding it. + /// + /// # Usage + /// + /// This would typically be called inside the module implementation of on_initialize, while + /// ensuring **no usage of this storage are made before the call to `on_initialize`**. (More + /// precisely prior initialized modules doesn't make use of this storage). + fn translate_values(translate_val: TV) -> Result<(), u32> + where OldValue: Decode, TV: Fn(OldValue) -> Value + { + let prefix = Self::final_prefix(); + let mut previous_key = prefix.to_vec(); + let mut errors = 0; + while let Some(next_key) = sp_io::storage::next_key(&previous_key) + .filter(|n| n.starts_with(&prefix[..])) + { + if let Some(value) = unhashed::get(&next_key) { + unhashed::put(&next_key[..], &translate_val(value)); + } else { + // We failed to read the value. Remove the key and increment errors. + unhashed::kill(&next_key[..]); + errors += 1; + } + + previous_key = next_key; + } + + if errors == 0 { + Ok(()) + } else { + Err(errors) + } + } +} + +#[cfg(test)] +mod test { + use sp_core::hashing::twox_128; + use sp_io::TestExternalities; + use crate::storage::{unhashed, StoragePrefixedMap}; + + #[test] + fn prefixed_map_works() { + TestExternalities::default().execute_with(|| { + struct MyStorage; + impl StoragePrefixedMap for MyStorage { + fn module_prefix() -> &'static [u8] { + b"MyModule" + } + + fn storage_prefix() -> &'static [u8] { + b"MyStorage" + } + } + + let key_before = { + let mut k = MyStorage::final_prefix(); + let last = k.iter_mut().last().unwrap(); + *last = last.checked_sub(1).unwrap(); + k + }; + let key_after = { + let mut k = MyStorage::final_prefix(); + let last = k.iter_mut().last().unwrap(); + *last = last.checked_add(1).unwrap(); + k + }; + + unhashed::put(&key_before[..], &32u64); + unhashed::put(&key_after[..], &33u64); + + let k = [twox_128(b"MyModule"), twox_128(b"MyStorage")].concat(); + assert_eq!(MyStorage::final_prefix().to_vec(), k); + + // test iteration + assert_eq!(MyStorage::iter().collect::>(), vec![]); + + unhashed::put(&[&k[..], &vec![1][..]].concat(), &1u64); + unhashed::put(&[&k[..], &vec![1, 1][..]].concat(), &2u64); + unhashed::put(&[&k[..], &vec![8][..]].concat(), &3u64); + unhashed::put(&[&k[..], &vec![10][..]].concat(), &4u64); + + assert_eq!(MyStorage::iter().collect::>(), vec![1, 2, 3, 4]); + + // test removal + MyStorage::remove_all(); + assert_eq!(MyStorage::iter().collect::>(), vec![]); + + // test migration + unhashed::put(&[&k[..], &vec![1][..]].concat(), &1u32); + unhashed::put(&[&k[..], &vec![8][..]].concat(), &2u32); + + assert_eq!(MyStorage::iter().collect::>(), vec![]); + MyStorage::translate_values(|v: u32| v as u64).unwrap(); + assert_eq!(MyStorage::iter().collect::>(), vec![1, 2]); + MyStorage::remove_all(); + + // test migration 2 + unhashed::put(&[&k[..], &vec![1][..]].concat(), &1u128); + unhashed::put(&[&k[..], &vec![1, 1][..]].concat(), &2u64); + unhashed::put(&[&k[..], &vec![8][..]].concat(), &3u128); + unhashed::put(&[&k[..], &vec![10][..]].concat(), &4u32); + + // (contains some value that successfully decoded to u64) + assert_eq!(MyStorage::iter().collect::>(), vec![1, 2, 3]); + assert_eq!(MyStorage::translate_values(|v: u128| v as u64), Err(2)); + assert_eq!(MyStorage::iter().collect::>(), vec![1, 3]); + MyStorage::remove_all(); + + // test that other values are not modified. + assert_eq!(unhashed::get(&key_before[..]), Some(32u64)); + assert_eq!(unhashed::get(&key_after[..]), Some(33u64)); + }); + } +} diff --git a/srml/support/src/storage/unhashed.rs b/frame/support/src/storage/unhashed.rs similarity index 85% rename from srml/support/src/storage/unhashed.rs rename to frame/support/src/storage/unhashed.rs index 6397fd39fcd2d..54910e99a4d86 100644 --- a/srml/support/src/storage/unhashed.rs +++ b/frame/support/src/storage/unhashed.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,13 +16,17 @@ //! Operation on unhashed runtime storage. -use rstd::prelude::*; +use sp_std::prelude::*; use codec::{Encode, Decode}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(key: &[u8]) -> Option { - runtime_io::storage(key).map(|val| { - Decode::decode(&mut &val[..]).expect("storage is not null, therefore must be a valid type") + sp_io::storage::get(key).and_then(|val| { + Decode::decode(&mut &val[..]).map(Some).unwrap_or_else(|_| { + // TODO #3700: error should be handleable. + runtime_print!("ERROR: Corrupted state at {:?}", key); + None + }) }) } @@ -46,7 +50,7 @@ pub fn get_or_else T>(key: &[u8], default_valu /// Put `value` in storage under `key`. pub fn put(key: &[u8], value: &T) { - value.using_encoded(|slice| runtime_io::set_storage(key, slice)); + value.using_encoded(|slice| sp_io::storage::set(key, slice)); } /// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. @@ -78,25 +82,25 @@ pub fn take_or_else T>(key: &[u8], default_val /// Check to see if `key` has an explicit entry in storage. pub fn exists(key: &[u8]) -> bool { - runtime_io::read_storage(key, &mut [0;0][..], 0).is_some() + sp_io::storage::read(key, &mut [0;0][..], 0).is_some() } /// Ensure `key` has no explicit entry in storage. pub fn kill(key: &[u8]) { - runtime_io::clear_storage(key); + sp_io::storage::clear(key); } /// Ensure keys with the given `prefix` have no entries in storage. pub fn kill_prefix(prefix: &[u8]) { - runtime_io::clear_prefix(prefix); + sp_io::storage::clear_prefix(prefix); } /// Get a Vec of bytes from storage. pub fn get_raw(key: &[u8]) -> Option> { - runtime_io::storage(key) + sp_io::storage::get(key) } /// Put a raw byte slice into storage. pub fn put_raw(key: &[u8], value: &[u8]) { - runtime_io::set_storage(key, value) + sp_io::storage::set(key, value) } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs new file mode 100644 index 0000000000000..cb2228392454f --- /dev/null +++ b/frame/support/src/traits.rs @@ -0,0 +1,804 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Traits for SRML. +//! +//! NOTE: If you're looking for `parameter_types`, it has moved in to the top-level module. + +use sp_std::{prelude::*, result, marker::PhantomData, ops::Div, fmt::Debug}; +use codec::{FullCodec, Codec, Encode, Decode}; +use sp_core::u32_trait::Value as U32; +use sp_runtime::{ + ConsensusEngineId, DispatchResult, DispatchError, + traits::{MaybeSerializeDeserialize, SimpleArithmetic, Saturating, TrailingZeroInput}, +}; + +use crate::dispatch::Parameter; + +/// Anything that can have a `::len()` method. +pub trait Len { + /// Return the length of data type. + fn len(&self) -> usize; +} + +impl Len for T where ::IntoIter: ExactSizeIterator { + fn len(&self) -> usize { + self.clone().into_iter().len() + } +} + +/// A trait for querying a single fixed value from a type. +pub trait Get { + /// Return a constant value. + fn get() -> T; +} + +impl Get for () { + fn get() -> T { T::default() } +} + +/// A trait for querying whether a type can be said to statically "contain" a value. Similar +/// in nature to `Get`, except it is designed to be lazy rather than active (you can't ask it to +/// enumerate all values that it contains) and work for multiple values rather than just one. +pub trait Contains { + /// Return `true` if this "contains" the given value `t`. + fn contains(t: &T) -> bool { Self::sorted_members().binary_search(t).is_ok() } + + /// Get a vector of all members in the set, ordered. + fn sorted_members() -> Vec; + + /// Get the number of items in the set. + fn count() -> usize { Self::sorted_members().len() } +} + +/// The account with the given id was killed. +#[impl_trait_for_tuples::impl_for_tuples(30)] +pub trait OnFreeBalanceZero { + /// The account with the given id was killed. + fn on_free_balance_zero(who: &AccountId); +} + +/// The account with the given id was reaped. +#[impl_trait_for_tuples::impl_for_tuples(30)] +pub trait OnReapAccount { + /// The account with the given id was reaped. + fn on_reap_account(who: &AccountId); +} + +/// Outcome of a balance update. +pub enum UpdateBalanceOutcome { + /// Account balance was simply updated. + Updated, + /// The update led to killing the account. + AccountKilled, +} + +/// A trait for finding the author of a block header based on the `PreRuntime` digests contained +/// within it. +pub trait FindAuthor { + /// Find the author of a block based on the pre-runtime digests. + fn find_author<'a, I>(digests: I) -> Option + where I: 'a + IntoIterator; +} + +impl FindAuthor for () { + fn find_author<'a, I>(_: I) -> Option + where I: 'a + IntoIterator + { + None + } +} + +/// A trait for verifying the seal of a header and returning the author. +pub trait VerifySeal { + /// Verify a header and return the author, if any. + fn verify_seal(header: &Header) -> Result, &'static str>; +} + +/// Something which can compute and check proofs of +/// a historical key owner and return full identification data of that +/// key owner. +pub trait KeyOwnerProofSystem { + /// The proof of membership itself. + type Proof: Codec; + /// The full identification of a key owner and the stash account. + type IdentificationTuple: Codec; + + /// Prove membership of a key owner in the current block-state. + /// + /// This should typically only be called off-chain, since it may be + /// computationally heavy. + /// + /// Returns `Some` iff the key owner referred to by the given `key` is a + /// member of the current set. + fn prove(key: Key) -> Option; + + /// Check a proof of membership on-chain. Return `Some` iff the proof is + /// valid and recent enough to check. + fn check_proof(key: Key, proof: Self::Proof) -> Option; +} + +/// Handler for when some currency "account" decreased in balance for +/// some reason. +/// +/// The only reason at present for an increase would be for validator rewards, but +/// there may be other reasons in the future or for other chains. +/// +/// Reasons for decreases include: +/// +/// - Someone got slashed. +/// - Someone paid for a transaction to be included. +pub trait OnUnbalanced { + /// Handler for some imbalance. Infallible. + fn on_unbalanced(amount: Imbalance) { + amount.try_drop().unwrap_or_else(Self::on_nonzero_unbalanced) + } + + /// Actually handle a non-zero imbalance. You probably want to implement this rather than + /// `on_unbalanced`. + fn on_nonzero_unbalanced(amount: Imbalance); +} + +impl OnUnbalanced for () { + fn on_nonzero_unbalanced(amount: Imbalance) { drop(amount); } +} + +/// Simple boolean for whether an account needs to be kept in existence. +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum ExistenceRequirement { + /// Operation must not result in the account going out of existence. + /// + /// Note this implies that if the account never existed in the first place, then the operation + /// may legitimately leave the account unchanged and still non-existent. + KeepAlive, + /// Operation may result in account going out of existence. + AllowDeath, +} + +/// A type for which some values make sense to be able to drop without further consideration. +pub trait TryDrop: Sized { + /// Drop an instance cleanly. Only works if its value represents "no-operation". + fn try_drop(self) -> Result<(), Self>; +} + +/// A trait for a not-quite Linear Type that tracks an imbalance. +/// +/// Functions that alter account balances return an object of this trait to +/// express how much account balances have been altered in aggregate. If +/// dropped, the currency system will take some default steps to deal with +/// the imbalance (`balances` module simply reduces or increases its +/// total issuance). Your module should generally handle it in some way, +/// good practice is to do so in a configurable manner using an +/// `OnUnbalanced` type for each situation in which your module needs to +/// handle an imbalance. +/// +/// Imbalances can either be Positive (funds were added somewhere without +/// being subtracted elsewhere - e.g. a reward) or Negative (funds deducted +/// somewhere without an equal and opposite addition - e.g. a slash or +/// system fee payment). +/// +/// Since they are unsigned, the actual type is always Positive or Negative. +/// The trait makes no distinction except to define the `Opposite` type. +/// +/// New instances of zero value can be created (`zero`) and destroyed +/// (`drop_zero`). +/// +/// Existing instances can be `split` and merged either consuming `self` with +/// `merge` or mutating `self` with `subsume`. If the target is an `Option`, +/// then `maybe_merge` and `maybe_subsume` might work better. Instances can +/// also be `offset` with an `Opposite` that is less than or equal to in value. +/// +/// You can always retrieve the raw balance value using `peek`. +#[must_use] +pub trait Imbalance: Sized + TryDrop { + /// The oppositely imbalanced type. They come in pairs. + type Opposite: Imbalance; + + /// The zero imbalance. Can be destroyed with `drop_zero`. + fn zero() -> Self; + + /// Drop an instance cleanly. Only works if its `self.value()` is zero. + fn drop_zero(self) -> Result<(), Self>; + + /// Consume `self` and return two independent instances; the first + /// is guaranteed to be at most `amount` and the second will be the remainder. + fn split(self, amount: Balance) -> (Self, Self); + + /// Consume `self` and an `other` to return a new instance that combines + /// both. + fn merge(self, other: Self) -> Self; + + /// Consume `self` and maybe an `other` to return a new instance that combines + /// both. + fn maybe_merge(self, other: Option) -> Self { + if let Some(o) = other { + self.merge(o) + } else { + self + } + } + + /// Consume an `other` to mutate `self` into a new instance that combines + /// both. + fn subsume(&mut self, other: Self); + + /// Maybe consume an `other` to mutate `self` into a new instance that combines + /// both. + fn maybe_subsume(&mut self, other: Option) { + if let Some(o) = other { + self.subsume(o) + } + } + + /// Consume self and along with an opposite counterpart to return + /// a combined result. + /// + /// Returns `Ok` along with a new instance of `Self` if this instance has a + /// greater value than the `other`. Otherwise returns `Err` with an instance of + /// the `Opposite`. In both cases the value represents the combination of `self` + /// and `other`. + fn offset(self, other: Self::Opposite) -> Result; + + /// The raw value of self. + fn peek(&self) -> Balance; +} + +/// Either a positive or a negative imbalance. +pub enum SignedImbalance>{ + /// A positive imbalance (funds have been created but none destroyed). + Positive(P), + /// A negative imbalance (funds have been destroyed but none created). + Negative(P::Opposite), +} + +impl< + P: Imbalance, + N: Imbalance, + B: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default, +> SignedImbalance { + pub fn zero() -> Self { + SignedImbalance::Positive(P::zero()) + } + + pub fn drop_zero(self) -> Result<(), Self> { + match self { + SignedImbalance::Positive(x) => x.drop_zero().map_err(SignedImbalance::Positive), + SignedImbalance::Negative(x) => x.drop_zero().map_err(SignedImbalance::Negative), + } + } + + /// Consume `self` and an `other` to return a new instance that combines + /// both. + pub fn merge(self, other: Self) -> Self { + match (self, other) { + (SignedImbalance::Positive(one), SignedImbalance::Positive(other)) => + SignedImbalance::Positive(one.merge(other)), + (SignedImbalance::Negative(one), SignedImbalance::Negative(other)) => + SignedImbalance::Negative(one.merge(other)), + (SignedImbalance::Positive(one), SignedImbalance::Negative(other)) => + if one.peek() > other.peek() { + SignedImbalance::Positive(one.offset(other).ok().unwrap_or_else(P::zero)) + } else { + SignedImbalance::Negative(other.offset(one).ok().unwrap_or_else(N::zero)) + }, + (one, other) => other.merge(one), + } + } +} + +/// Split an unbalanced amount two ways between a common divisor. +pub struct SplitTwoWays< + Balance, + Imbalance, + Part1, + Target1, + Part2, + Target2, +>(PhantomData<(Balance, Imbalance, Part1, Target1, Part2, Target2)>); + +impl< + Balance: From + Saturating + Div, + I: Imbalance, + Part1: U32, + Target1: OnUnbalanced, + Part2: U32, + Target2: OnUnbalanced, +> OnUnbalanced for SplitTwoWays +{ + fn on_nonzero_unbalanced(amount: I) { + let total: u32 = Part1::VALUE + Part2::VALUE; + let amount1 = amount.peek().saturating_mul(Part1::VALUE.into()) / total.into(); + let (imb1, imb2) = amount.split(amount1); + Target1::on_unbalanced(imb1); + Target2::on_unbalanced(imb2); + } +} + +/// Abstraction over a fungible assets system. +pub trait Currency { + /// The balance of an account. + type Balance: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default; + + /// The opaque token type for an imbalance. This is returned by unbalanced operations + /// and must be dealt with. It may be dropped but cannot be cloned. + type PositiveImbalance: Imbalance; + + /// The opaque token type for an imbalance. This is returned by unbalanced operations + /// and must be dealt with. It may be dropped but cannot be cloned. + type NegativeImbalance: Imbalance; + + // PUBLIC IMMUTABLES + + /// The combined balance of `who`. + fn total_balance(who: &AccountId) -> Self::Balance; + + /// Same 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; + + /// The total amount of issuance in the system. + fn total_issuance() -> Self::Balance; + + /// The minimum balance any single account may have. This is equivalent to the `Balances` module's + /// `ExistentialDeposit`. + fn minimum_balance() -> Self::Balance; + + /// Reduce the total issuance by `amount` and return the according imbalance. The imbalance will + /// typically be used to reduce an account by the same amount with e.g. `settle`. + /// + /// This is infallible, but doesn't guarantee that the entire `amount` is burnt, for example + /// in the case of underflow. + fn burn(amount: Self::Balance) -> Self::PositiveImbalance; + + /// Increase the total issuance by `amount` and return the according imbalance. The imbalance + /// will typically be used to increase an account by the same amount with e.g. + /// `resolve_into_existing` or `resolve_creating`. + /// + /// This is infallible, but doesn't guarantee that the entire `amount` is issued, for example + /// in the case of overflow. + fn issue(amount: Self::Balance) -> Self::NegativeImbalance; + + /// The 'free' balance of a given account. + /// + /// This is the only balance that matters in terms of most operations on tokens. It alone + /// is 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`. Further, the `OnFreeBalanceZero` callback + /// is invoked, giving a chance to external modules to clean up 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; + + /// Returns `Ok` iff the account is able to make a withdrawal of the given amount + /// for the given reason. Basically, it's just a dry-run of `withdraw`. + /// + /// `Err(...)` with the reason why not otherwise. + fn ensure_can_withdraw( + who: &AccountId, + _amount: Self::Balance, + reasons: WithdrawReasons, + new_balance: Self::Balance, + ) -> DispatchResult; + + // PUBLIC MUTABLES (DANGEROUS) + + /// Transfer some liquid free balance to another staker. + /// + /// This is a very high-level function. It will ensure all appropriate fees are paid + /// and no imbalance in the system remains. + fn transfer( + source: &AccountId, + dest: &AccountId, + value: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> DispatchResult; + + /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the + /// free balance. This function cannot fail. + /// + /// The resulting imbalance is the first item of the tuple returned. + /// + /// As much funds up to `value` will be deducted as possible. If this is less than `value`, + /// then a non-zero second item will be returned. + fn slash( + who: &AccountId, + value: Self::Balance + ) -> (Self::NegativeImbalance, Self::Balance); + + /// Mints `value` to the free balance of `who`. + /// + /// If `who` doesn't exist, nothing is done and an Err returned. + fn deposit_into_existing( + who: &AccountId, + value: Self::Balance + ) -> result::Result; + + /// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on + /// success. + fn resolve_into_existing( + who: &AccountId, + value: Self::NegativeImbalance, + ) -> result::Result<(), Self::NegativeImbalance> { + let v = value.peek(); + match Self::deposit_into_existing(who, v) { + Ok(opposite) => Ok(drop(value.offset(opposite))), + _ => Err(value), + } + } + + /// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created. + /// + /// Infallible. + fn deposit_creating( + who: &AccountId, + value: Self::Balance, + ) -> Self::PositiveImbalance; + + /// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on + /// success. + fn resolve_creating( + who: &AccountId, + value: Self::NegativeImbalance, + ) { + let v = value.peek(); + drop(value.offset(Self::deposit_creating(who, v))); + } + + /// Removes some free balance from `who` account for `reason` if possible. If `liveness` is + /// `KeepAlive`, then no less than `ExistentialDeposit` must be left remaining. + /// + /// This checks any locks, vesting, and liquidity requirements. If the removal is not possible, + /// then it returns `Err`. + /// + /// If the operation is successful, this will return `Ok` with a `NegativeImbalance` whose value + /// is `value`. + fn withdraw( + who: &AccountId, + value: Self::Balance, + reasons: WithdrawReasons, + liveness: ExistenceRequirement, + ) -> result::Result; + + /// Similar to withdraw, only accepts a `PositiveImbalance` and returns nothing on success. + fn settle( + who: &AccountId, + value: Self::PositiveImbalance, + reasons: WithdrawReasons, + liveness: ExistenceRequirement, + ) -> result::Result<(), Self::PositiveImbalance> { + let v = value.peek(); + match Self::withdraw(who, v, reasons, liveness) { + Ok(opposite) => Ok(drop(value.offset(opposite))), + _ => Err(value), + } + } + + /// Ensure an account's free balance equals some value; this will create the account + /// if needed. + /// + /// Returns a signed imbalance and status to indicate if the account was successfully updated or update + /// has led to killing of the account. + fn make_free_balance_be( + who: &AccountId, + balance: Self::Balance, + ) -> ( + SignedImbalance, + UpdateBalanceOutcome, + ); +} + +/// A currency where funds can be reserved from the user. +pub trait ReservableCurrency: Currency { + /// 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; + + /// 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 the reserve balance of `who` + /// is less than `value`, then a non-zero second item will be returned. + fn slash_reserved( + who: &AccountId, + value: Self::Balance + ) -> (Self::NegativeImbalance, 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. + /// + /// 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; + + + /// 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 behavior than `unreserve`. + fn reserve(who: &AccountId, value: Self::Balance) -> DispatchResult; + + /// Moves up to `value` from reserved balance to free balance. This function cannot fail. + /// + /// As much funds up to `value` will be moved as possible. If the reserve balance of `who` + /// is less than `value`, then the remaining amount will be returned. + /// + /// # NOTES + /// + /// - This is different from `reserve`. + /// - If the remaining reserved balance is less than `ExistentialDeposit`, it will + /// invoke `on_reserved_too_low` and could reap the account. + fn unreserve(who: &AccountId, value: Self::Balance) -> Self::Balance; + + /// 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 deducted as possible. If this is less than `value`, + /// then `Ok(non_zero)` will be returned. + fn repatriate_reserved( + slashed: &AccountId, + beneficiary: &AccountId, + value: Self::Balance + ) -> result::Result; +} + +/// 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; + + /// Create a new balance lock on account `who`. + /// + /// If the new lock is valid (i.e. not already expired), it will push the struct to + /// the `Locks` vec in storage. Note that you can lock more funds than a user has. + /// + /// If the lock `id` already exists, this will update it. + fn set_lock( + id: LockIdentifier, + who: &AccountId, + amount: Self::Balance, + until: Self::Moment, + reasons: WithdrawReasons, + ); + + /// Changes a balance lock (selected by `id`) so that it becomes less liquid in all + /// parameters or creates a new one if it does not exist. + /// + /// Calling `extend_lock` on an existing lock `id` differs from `set_lock` in that it + /// applies the most severe constraints of the two, while `set_lock` replaces the lock + /// with the new parameters. As in, `extend_lock` will set: + /// - maximum `amount` + /// - farthest duration (`until`) + /// - bitwise mask of all `reasons` + 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, + ); +} + +/// A currency whose accounts can have balances which vest over time. +pub trait VestingCurrency: Currency { + /// The quantity used to denote time; usually just a `BlockNumber`. + type Moment; + + /// Get the amount that is currently being vested and cannot be transferred out of this account. + fn vesting_balance(who: &AccountId) -> Self::Balance; + + /// Adds a vesting schedule to a given account. + /// + /// If there already exists a vesting schedule for the given account, an `Err` is returned + /// and nothing is updated. + fn add_vesting_schedule( + who: &AccountId, + locked: Self::Balance, + per_block: Self::Balance, + starting_block: Self::Moment, + ) -> DispatchResult; + + /// Remove a vesting schedule for a given account. + fn remove_vesting_schedule(who: &AccountId); +} + +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, + /// In order to pay some other (higher-level) fees. + Fee = 0b00001000, + /// In order to tip a validator for transaction inclusion. + Tip = 0b00010000, + } +} + +pub trait Time { + type Moment: SimpleArithmetic + Parameter + Default + Copy; + + fn now() -> Self::Moment; +} + +impl WithdrawReasons { + /// Choose all variants except for `one`. + /// + /// ```rust + /// # use frame_support::traits::{WithdrawReason, WithdrawReasons}; + /// # fn main() { + /// assert_eq!( + /// WithdrawReason::Fee | WithdrawReason::Transfer | WithdrawReason::Reserve | WithdrawReason::Tip, + /// WithdrawReasons::except(WithdrawReason::TransactionPayment), + /// ); + /// # } + /// ``` + pub fn except(one: WithdrawReason) -> WithdrawReasons { + let mut mask = Self::all(); + mask.toggle(one); + mask + } +} + +/// Trait for type that can handle incremental changes to a set of account IDs. +pub trait ChangeMembers { + /// A number of members `incoming` just joined the set and replaced some `outgoing` ones. The + /// new set is given by `new`, and need not be sorted. + fn change_members(incoming: &[AccountId], outgoing: &[AccountId], mut new: Vec) { + new.sort_unstable(); + Self::change_members_sorted(incoming, outgoing, &new[..]); + } + + /// A number of members `_incoming` just joined the set and replaced some `_outgoing` ones. The + /// new set is thus given by `sorted_new` and **must be sorted**. + /// + /// NOTE: This is the only function that needs to be implemented in `ChangeMembers`. + fn change_members_sorted( + incoming: &[AccountId], + outgoing: &[AccountId], + sorted_new: &[AccountId], + ); + + /// Set the new members; they **must already be sorted**. This will compute the diff and use it to + /// call `change_members_sorted`. + fn set_members_sorted(new_members: &[AccountId], old_members: &[AccountId]) { + let (incoming, outgoing) = Self::compute_members_diff(new_members, old_members); + Self::change_members_sorted(&incoming[..], &outgoing[..], &new_members); + } + + /// Set the new members; they **must already be sorted**. This will compute the diff and use it to + /// call `change_members_sorted`. + fn compute_members_diff( + new_members: &[AccountId], + old_members: &[AccountId] + ) -> (Vec, Vec) { + let mut old_iter = old_members.iter(); + let mut new_iter = new_members.iter(); + let mut incoming = Vec::new(); + let mut outgoing = Vec::new(); + let mut old_i = old_iter.next(); + let mut new_i = new_iter.next(); + loop { + match (old_i, new_i) { + (None, None) => break, + (Some(old), Some(new)) if old == new => { + old_i = old_iter.next(); + new_i = new_iter.next(); + } + (Some(old), Some(new)) if old < new => { + outgoing.push(old.clone()); + old_i = old_iter.next(); + } + (Some(old), None) => { + outgoing.push(old.clone()); + old_i = old_iter.next(); + } + (_, Some(new)) => { + incoming.push(new.clone()); + new_i = new_iter.next(); + } + } + } + (incoming, outgoing) + } +} + +impl ChangeMembers for () { + fn change_members(_: &[T], _: &[T], _: Vec) {} + fn change_members_sorted(_: &[T], _: &[T], _: &[T]) {} + fn set_members_sorted(_: &[T], _: &[T]) {} +} + +/// Trait for type that can handle the initialization of account IDs at genesis. +pub trait InitializeMembers { + /// Initialize the members to the given `members`. + fn initialize_members(members: &[AccountId]); +} + +impl InitializeMembers for () { + fn initialize_members(_: &[T]) {} +} + +// A trait that is able to provide randomness. +pub trait Randomness { + /// Get a "random" value + /// + /// Being a deterministic blockchain, real randomness is difficult to come by. This gives you + /// something that approximates it. `subject` is a context identifier and allows you to get a + /// different result to other callers of this function; use it like + /// `random(&b"my context"[..])`. + fn random(subject: &[u8]) -> Output; + + /// Get the basic random seed. + /// + /// In general you won't want to use this, but rather `Self::random` which allows you to give a + /// subject for the random result and whose value will be independently low-influence random + /// from any other such seeds. + fn random_seed() -> Output { + Self::random(&[][..]) + } +} + +impl Randomness for () { + fn random(subject: &[u8]) -> Output { + Output::decode(&mut TrailingZeroInput::new(subject)).unwrap_or_default() + } +} + +/// Implementors of this trait provide information about whether or not some validator has +/// been registered with them. The [Session module](../../pallet_session/index.html) is an implementor. +pub trait ValidatorRegistration { + /// Returns true if the provided validator ID has been registered with the implementing runtime + /// module + fn is_registered(id: &ValidatorId) -> bool; +} + +/// Something that can convert a given module into the index of the module in the runtime. +/// +/// The index of a module is determined by the position it appears in `construct_runtime!`. +pub trait ModuleToIndex { + /// Convert the given module `M` into an index. + fn module_to_index() -> Option; +} + +impl ModuleToIndex for () { + fn module_to_index() -> Option { Some(0) } +} diff --git a/srml/support/src/unsigned.rs b/frame/support/src/unsigned.rs similarity index 75% rename from srml/support/src/unsigned.rs rename to frame/support/src/unsigned.rs index 4d2ceddd79f4a..319fa3adb448f 100644 --- a/srml/support/src/unsigned.rs +++ b/frame/support/src/unsigned.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -15,11 +15,12 @@ // along with Substrate. If not, see . #[doc(hidden)] -pub use crate::sr_primitives::traits::ValidateUnsigned; +#[allow(deprecated)] +pub use crate::sp_runtime::traits::ValidateUnsigned; #[doc(hidden)] -pub use crate::sr_primitives::transaction_validity::{TransactionValidity, UnknownTransaction}; -#[doc(hidden)] -pub use crate::sr_primitives::ApplyError; +pub use crate::sp_runtime::transaction_validity::{ + TransactionValidity, UnknownTransaction, TransactionValidityError, +}; /// Implement `ValidateUnsigned` for `Runtime`. @@ -31,10 +32,10 @@ pub use crate::sr_primitives::ApplyError; /// # mod timestamp { /// # pub struct Module; /// # -/// # impl srml_support::unsigned::ValidateUnsigned for Module { +/// # impl frame_support::unsigned::ValidateUnsigned for Module { /// # type Call = Call; /// # -/// # fn validate_unsigned(call: &Self::Call) -> srml_support::unsigned::TransactionValidity { +/// # fn validate_unsigned(call: &Self::Call) -> frame_support::unsigned::TransactionValidity { /// # unimplemented!(); /// # } /// # } @@ -52,7 +53,7 @@ pub use crate::sr_primitives::ApplyError; /// # #[allow(unused)] /// pub struct Runtime; /// -/// srml_support::impl_outer_validate_unsigned! { +/// frame_support::impl_outer_validate_unsigned! { /// impl ValidateUnsigned for Runtime { /// Timestamp /// } @@ -65,9 +66,20 @@ macro_rules! impl_outer_validate_unsigned { $( $module:ident )* } ) => { + #[allow(deprecated)] // Allow ValidateUnsigned impl $crate::unsigned::ValidateUnsigned for $runtime { type Call = Call; + fn pre_dispatch(call: &Self::Call) -> Result<(), $crate::unsigned::TransactionValidityError> { + #[allow(unreachable_patterns)] + match call { + $( Call::$module(inner_call) => $module::pre_dispatch(inner_call), )* + // pre-dispatch should not stop inherent extrinsics, validation should prevent + // including arbitrary (non-inherent) extrinsics to blocks. + _ => Ok(()), + } + } + fn validate_unsigned(call: &Self::Call) -> $crate::unsigned::TransactionValidity { #[allow(unreachable_patterns)] match call { @@ -97,6 +109,7 @@ mod test_partial_and_full_call { pub mod timestamp { pub struct Module; + #[allow(deprecated)] // Allow ValidateUnsigned impl super::super::ValidateUnsigned for Module { type Call = Call; diff --git a/frame/support/src/weights.rs b/frame/support/src/weights.rs new file mode 100644 index 0000000000000..f1092b500230b --- /dev/null +++ b/frame/support/src/weights.rs @@ -0,0 +1,273 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Primitives for transaction weighting. +//! +//! All dispatchable functions defined in `decl_module!` must provide two trait implementations: +//! - [`WeightData`]: To determine the weight of the dispatch. +//! - [`ClassifyDispatch`]: To determine the class of the dispatch. See the enum definition for +//! more information on dispatch classes. +//! +//! Every dispatchable function is responsible for providing this data via an optional `#[weight = +//! $x]` attribute. In this snipped, `$x` can be any user provided struct that implements the +//! two aforementioned traits. +//! +//! Substrate then bundles then output information of the two traits into [`DispatchInfo`] struct +//! and provides it by implementing the [`GetDispatchInfo`] for all `Call` variants, and opaque +//! extrinsic types. +//! +//! If no `#[weight]` is defined, the macro automatically injects the `Default` implementation of +//! the [`SimpleDispatchInfo`]. +//! +//! Note that the decl_module macro _cannot_ enforce this and will simply fail if an invalid struct +//! (something that does not implement `Weighable`) is passed in. + +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use impl_trait_for_tuples::impl_for_tuples; +use codec::{Encode, Decode}; +use sp_arithmetic::traits::{Bounded, Zero}; +use sp_runtime::{ + RuntimeDebug, + traits::SignedExtension, + generic::{CheckedExtrinsic, UncheckedExtrinsic}, +}; + +/// Re-export priority as type +pub use sp_runtime::transaction_validity::TransactionPriority; + +/// Numeric range of a transaction weight. +pub type Weight = u32; + +/// Means of weighing some particular kind of data (`T`). +pub trait WeighData { + /// Weigh the data `T` given by `target`. When implementing this for a dispatchable, `T` will be + /// a tuple of all arguments given to the function (except origin). + fn weigh_data(&self, target: T) -> Weight; +} + +/// Means of classifying a dispatchable function. +pub trait ClassifyDispatch { + /// Classify the dispatch function based on input data `target` of type `T`. When implementing + /// this for a dispatchable, `T` will be a tuple of all arguments given to the function (except + /// origin). + fn classify_dispatch(&self, target: T) -> DispatchClass; +} + +/// Means of determining the weight of a block's lifecycle hooks: on_initialize, on_finalize and +/// such. +pub trait WeighBlock { + /// Return the weight of the block's on_initialize hook. + fn on_initialize(_: BlockNumber) -> Weight { Zero::zero() } + /// Return the weight of the block's on_finalize hook. + fn on_finalize(_: BlockNumber) -> Weight { Zero::zero() } +} + +/// Indicates if dispatch function should pay fees or not. +/// If set to false, the block resource limits are applied, yet no fee is deducted. +pub trait PaysFee { + fn pays_fee(&self, _target: T) -> bool { + true + } +} + +/// Maybe I can do something to remove the duplicate code here. +#[impl_for_tuples(30)] +impl WeighBlock for SingleModule { + fn on_initialize(n: BlockNumber) -> Weight { + let mut accumulated_weight: Weight = Zero::zero(); + for_tuples!( + #( accumulated_weight = accumulated_weight.saturating_add(SingleModule::on_initialize(n)); )* + ); + accumulated_weight + } + + fn on_finalize(n: BlockNumber) -> Weight { + let mut accumulated_weight: Weight = Zero::zero(); + for_tuples!( + #( accumulated_weight = accumulated_weight.saturating_add(SingleModule::on_finalize(n)); )* + ); + accumulated_weight + } +} + +/// A generalized group of dispatch types. This is only distinguishing normal, user-triggered transactions +/// (`Normal`) and anything beyond which serves a higher purpose to the system (`Operational`). +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)] +pub enum DispatchClass { + /// A normal dispatch. + Normal, + /// An operational dispatch. + Operational, +} + +impl Default for DispatchClass { + fn default() -> Self { + DispatchClass::Normal + } +} + +impl From for DispatchClass { + fn from(tx: SimpleDispatchInfo) -> Self { + match tx { + SimpleDispatchInfo::FixedOperational(_) => DispatchClass::Operational, + SimpleDispatchInfo::MaxOperational => DispatchClass::Operational, + SimpleDispatchInfo::FreeOperational => DispatchClass::Operational, + + SimpleDispatchInfo::FixedNormal(_) => DispatchClass::Normal, + SimpleDispatchInfo::MaxNormal => DispatchClass::Normal, + SimpleDispatchInfo::FreeNormal => DispatchClass::Normal, + } + } +} + +/// A bundle of static information collected from the `#[weight = $x]` attributes. +#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)] +pub struct DispatchInfo { + /// Weight of this transaction. + pub weight: Weight, + /// Class of this transaction. + pub class: DispatchClass, + /// Does this transaction pay fees. + pub pays_fee: bool, +} + +/// A `Dispatchable` function (aka transaction) that can carry some static information along with +/// it, using the `#[weight]` attribute. +pub trait GetDispatchInfo { + /// Return a `DispatchInfo`, containing relevant information of this dispatch. + /// + /// This is done independently of its encoded size. + fn get_dispatch_info(&self) -> DispatchInfo; +} + +/// Default type used with the `#[weight = x]` attribute in a substrate chain. +/// +/// A user may pass in any other type that implements the correct traits. If not, the `Default` +/// implementation of [`SimpleDispatchInfo`] is used. +/// +/// For each generalized group (`Normal` and `Operation`): +/// - A `Fixed` variant means weight fee is charged normally and the weight is the number +/// specified in the inner value of the variant. +/// - A `Free` variant is equal to `::Fixed(0)`. Note that this does not guarantee inclusion. +/// - A `Max` variant is equal to `::Fixed(Weight::max_value())`. +/// +/// As for the generalized groups themselves: +/// - `Normal` variants will be assigned a priority proportional to their weight. They can only +/// consume a portion (defined in the system module) of the maximum block resource limits. +/// - `Operational` variants will be assigned the maximum priority. They can potentially consume +/// the entire block resource limit. +#[derive(Clone, Copy)] +pub enum SimpleDispatchInfo { + /// A normal dispatch with fixed weight. + FixedNormal(Weight), + /// A normal dispatch with the maximum weight. + MaxNormal, + /// A normal dispatch with no weight. + FreeNormal, + /// An operational dispatch with fixed weight. + FixedOperational(Weight), + /// An operational dispatch with the maximum weight. + MaxOperational, + /// An operational dispatch with no weight. + FreeOperational, +} + +impl WeighData for SimpleDispatchInfo { + fn weigh_data(&self, _: T) -> Weight { + match self { + SimpleDispatchInfo::FixedNormal(w) => *w, + SimpleDispatchInfo::MaxNormal => Bounded::max_value(), + SimpleDispatchInfo::FreeNormal => Bounded::min_value(), + + SimpleDispatchInfo::FixedOperational(w) => *w, + SimpleDispatchInfo::MaxOperational => Bounded::max_value(), + SimpleDispatchInfo::FreeOperational => Bounded::min_value(), + } + } +} + +impl ClassifyDispatch for SimpleDispatchInfo { + fn classify_dispatch(&self, _: T) -> DispatchClass { + DispatchClass::from(*self) + } +} + +impl PaysFee for SimpleDispatchInfo { + fn pays_fee(&self, _: T) -> bool { + match self { + SimpleDispatchInfo::FixedNormal(_) => true, + SimpleDispatchInfo::MaxNormal => true, + SimpleDispatchInfo::FreeNormal => true, + + SimpleDispatchInfo::FixedOperational(_) => true, + SimpleDispatchInfo::MaxOperational => true, + SimpleDispatchInfo::FreeOperational => false, + } + } +} + +impl Default for SimpleDispatchInfo { + fn default() -> Self { + // Default weight of all transactions. + SimpleDispatchInfo::FixedNormal(10_000) + } +} + +impl SimpleDispatchInfo { + /// An _additive zero_ variant of SimpleDispatchInfo. + pub fn zero() -> Self { + Self::FixedNormal(0) + } +} + +/// Implementation for unchecked extrinsic. +impl GetDispatchInfo + for UncheckedExtrinsic +where + Call: GetDispatchInfo, + Extra: SignedExtension, +{ + fn get_dispatch_info(&self) -> DispatchInfo { + self.function.get_dispatch_info() + } +} + +/// Implementation for checked extrinsic. +impl GetDispatchInfo + for CheckedExtrinsic +where + Call: GetDispatchInfo, +{ + fn get_dispatch_info(&self) -> DispatchInfo { + self.function.get_dispatch_info() + } +} + +/// Implementation for test extrinsic. +#[cfg(feature = "std")] +impl GetDispatchInfo for sp_runtime::testing::TestXt { + fn get_dispatch_info(&self) -> DispatchInfo { + // for testing: weight == size. + DispatchInfo { + weight: self.encode().len() as _, + pays_fee: true, + ..Default::default() + } + } +} diff --git a/frame/support/test/Cargo.toml b/frame/support/test/Cargo.toml new file mode 100644 index 0000000000000..92dc32e478f1d --- /dev/null +++ b/frame/support/test/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "frame-support-test" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-io ={ path = "../../../primitives/io", default-features = false } +sp-state-machine = { version = "2.0.0", optional = true, path = "../../../primitives/state-machine" } +frame-support = { version = "2.0.0", default-features = false, path = "../" } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../../primitives/inherents" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-core = { version = "2.0.0", default-features = false, path = "../../../primitives/core" } +trybuild = "1.0.17" +pretty_assertions = "0.6.1" + +[features] +default = ["std"] +std = [ + "serde/std", + "codec/std", + "sp-io/std", + "frame-support/std", + "sp-inherents/std", + "sp-core/std", + "sp-runtime/std", + "sp-state-machine", +] diff --git a/frame/support/test/src/lib.rs b/frame/support/test/src/lib.rs new file mode 100644 index 0000000000000..f62f5522680eb --- /dev/null +++ b/frame/support/test/src/lib.rs @@ -0,0 +1,35 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test crate for frame_support. Allow to make use of `frame_support::decl_storage`. +//! See tests directory. + +// Make sure we fail compilation on warnings +#![warn(missing_docs)] +#![deny(warnings)] + +/// The configuration trait +pub trait Trait { + /// The runtime origin type. + type Origin; + /// The block number type. + type BlockNumber; +} + +frame_support::decl_module! { + /// Some test module + pub struct Module for enum Call where origin: T::Origin {} +} diff --git a/frame/support/test/tests/construct_runtime_ui.rs b/frame/support/test/tests/construct_runtime_ui.rs new file mode 100644 index 0000000000000..acddf01f037a6 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui.rs @@ -0,0 +1,10 @@ +use std::env; + +#[test] +fn ui() { + // As trybuild is using `cargo check`, we don't need the real WASM binaries. + env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + + let t = trybuild::TestCases::new(); + t.compile_fail("tests/construct_runtime_ui/*.rs"); +} diff --git a/frame/support/test/tests/construct_runtime_ui/abundant_where_param.rs b/frame/support/test/tests/construct_runtime_ui/abundant_where_param.rs new file mode 100644 index 0000000000000..d5e9f225219de --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/abundant_where_param.rs @@ -0,0 +1,12 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + Block = Block1, + UncheckedExtrinsic = Uxt, + {} +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/abundant_where_param.stderr b/frame/support/test/tests/construct_runtime_ui/abundant_where_param.stderr new file mode 100644 index 0000000000000..4bac57d63c851 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/abundant_where_param.stderr @@ -0,0 +1,5 @@ +error: `Block` was declared above. Please use exactly one delcataion for `Block`. + --> $DIR/abundant_where_param.rs:7:3 + | +7 | Block = Block1, + | ^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/default_module_invalid_arg.rs b/frame/support/test/tests/construct_runtime_ui/default_module_invalid_arg.rs new file mode 100644 index 0000000000000..92a5ffff73f3c --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/default_module_invalid_arg.rs @@ -0,0 +1,14 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + Balance: balances::{default, Error}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/default_module_invalid_arg.stderr b/frame/support/test/tests/construct_runtime_ui/default_module_invalid_arg.stderr new file mode 100644 index 0000000000000..d4a46a3491027 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/default_module_invalid_arg.stderr @@ -0,0 +1,5 @@ +error: Only the following modules are allowed: `Module`, `Call`, `Storage`, `Event`, `Config`, `Origin`, `Inherent`, `ValidateUnsigned` + --> $DIR/default_module_invalid_arg.rs:10:32 + | +10 | Balance: balances::{default, Error}, + | ^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/double_module_parts.rs b/frame/support/test/tests/construct_runtime_ui/double_module_parts.rs new file mode 100644 index 0000000000000..0907f0bfb35d5 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/double_module_parts.rs @@ -0,0 +1,14 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + Balance: balances::{Config, Call, Config, Origin}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/double_module_parts.stderr b/frame/support/test/tests/construct_runtime_ui/double_module_parts.stderr new file mode 100644 index 0000000000000..9d10474ce85ab --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/double_module_parts.stderr @@ -0,0 +1,5 @@ +error: `Config` was already declared before. Please remove the duplicate declaration + --> $DIR/double_module_parts.rs:10:37 + | +10 | Balance: balances::{Config, Call, Config, Origin}, + | ^^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/double_module_parts_default.rs b/frame/support/test/tests/construct_runtime_ui/double_module_parts_default.rs new file mode 100644 index 0000000000000..3d61abebe8da1 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/double_module_parts_default.rs @@ -0,0 +1,14 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + Balance: balances::{default, Config}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/double_module_parts_default.stderr b/frame/support/test/tests/construct_runtime_ui/double_module_parts_default.stderr new file mode 100644 index 0000000000000..d8205acc4a104 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/double_module_parts_default.stderr @@ -0,0 +1,5 @@ +error: `Config` is already included in `default`. Either remove `default` or remove `Config` + --> $DIR/double_module_parts_default.rs:10:32 + | +10 | Balance: balances::{default, Config}, + | ^^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/generics_in_invalid_module.rs b/frame/support/test/tests/construct_runtime_ui/generics_in_invalid_module.rs new file mode 100644 index 0000000000000..5a9a4612ed0a4 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/generics_in_invalid_module.rs @@ -0,0 +1,14 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + Balance: balances::::{Call, Origin}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/generics_in_invalid_module.stderr b/frame/support/test/tests/construct_runtime_ui/generics_in_invalid_module.stderr new file mode 100644 index 0000000000000..fe880549211bc --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/generics_in_invalid_module.stderr @@ -0,0 +1,5 @@ +error: `Call` is not allowed to have generics. Only the following modules are allowed to have generics: `Event`, `Origin`, `Config`. + --> $DIR/generics_in_invalid_module.rs:10:36 + | +10 | Balance: balances::::{Call, Origin}, + | ^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_module_details.rs b/frame/support/test/tests/construct_runtime_ui/invalid_module_details.rs new file mode 100644 index 0000000000000..336e27e915176 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_module_details.rs @@ -0,0 +1,13 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + system: System::(), + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_module_details.stderr b/frame/support/test/tests/construct_runtime_ui/invalid_module_details.stderr new file mode 100644 index 0000000000000..559a4637d67ff --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_module_details.stderr @@ -0,0 +1,5 @@ +error: expected curly braces + --> $DIR/invalid_module_details.rs:9:19 + | +9 | system: System::(), + | ^^ diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_module_details_keyword.rs b/frame/support/test/tests/construct_runtime_ui/invalid_module_details_keyword.rs new file mode 100644 index 0000000000000..0891483c92116 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_module_details_keyword.rs @@ -0,0 +1,13 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + system: System::{enum}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_module_details_keyword.stderr b/frame/support/test/tests/construct_runtime_ui/invalid_module_details_keyword.stderr new file mode 100644 index 0000000000000..4441f6dc0f6a2 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_module_details_keyword.stderr @@ -0,0 +1,5 @@ +error: expected `default` or identifier + --> $DIR/invalid_module_details_keyword.rs:9:20 + | +9 | system: System::{enum}, + | ^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_module_entry.rs b/frame/support/test/tests/construct_runtime_ui/invalid_module_entry.rs new file mode 100644 index 0000000000000..db1250cdf4d6e --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_module_entry.rs @@ -0,0 +1,14 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + Balance: balances::{Error}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_module_entry.stderr b/frame/support/test/tests/construct_runtime_ui/invalid_module_entry.stderr new file mode 100644 index 0000000000000..da38a82d7e2b0 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_module_entry.stderr @@ -0,0 +1,5 @@ +error: Only the following modules are allowed: `Module`, `Call`, `Storage`, `Event`, `Config`, `Origin`, `Inherent`, `ValidateUnsigned` + --> $DIR/invalid_module_entry.rs:10:23 + | +10 | Balance: balances::{Error}, + | ^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.rs b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.rs new file mode 100644 index 0000000000000..448ae913f3f8d --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.rs @@ -0,0 +1,13 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + system: System ? + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.stderr b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.stderr new file mode 100644 index 0000000000000..8a6f15f7915b2 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_module.stderr @@ -0,0 +1,5 @@ +error: expected `,` + --> $DIR/invalid_token_after_module.rs:9:18 + | +9 | system: System ? + | ^ diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_token_after_name.rs b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_name.rs new file mode 100644 index 0000000000000..43538789f1119 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_name.rs @@ -0,0 +1,13 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + system ? + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_token_after_name.stderr b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_name.stderr new file mode 100644 index 0000000000000..eaae082c8460c --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_token_after_name.stderr @@ -0,0 +1,5 @@ +error: expected `:` + --> $DIR/invalid_token_after_name.rs:9:10 + | +9 | system ? + | ^ diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_where_param.rs b/frame/support/test/tests/construct_runtime_ui/invalid_where_param.rs new file mode 100644 index 0000000000000..13536338e07a6 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_where_param.rs @@ -0,0 +1,12 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + TypeX = Block, + UnchekcedExtrinsic = UnchekcedExtrinsic, + {} +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/invalid_where_param.stderr b/frame/support/test/tests/construct_runtime_ui/invalid_where_param.stderr new file mode 100644 index 0000000000000..9e358b6a21fab --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/invalid_where_param.stderr @@ -0,0 +1,5 @@ +error: expected one of: `Block`, `NodeBlock`, `UncheckedExtrinsic` + --> $DIR/invalid_where_param.rs:7:3 + | +7 | TypeX = Block, + | ^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/missing_event_generic_on_module_with_instance.rs b/frame/support/test/tests/construct_runtime_ui/missing_event_generic_on_module_with_instance.rs new file mode 100644 index 0000000000000..928871fab234f --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_event_generic_on_module_with_instance.rs @@ -0,0 +1,14 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + Balance: balances::::{Event}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/missing_event_generic_on_module_with_instance.stderr b/frame/support/test/tests/construct_runtime_ui/missing_event_generic_on_module_with_instance.stderr new file mode 100644 index 0000000000000..f80b4bd66abdd --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_event_generic_on_module_with_instance.stderr @@ -0,0 +1,5 @@ +error: Instantiable module with no generic `Event` cannot be constructed: module `Balance` must have generic `Event` + --> $DIR/missing_event_generic_on_module_with_instance.rs:10:3 + | +10 | Balance: balances::::{Event}, + | ^^^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/missing_module_instance.rs b/frame/support/test/tests/construct_runtime_ui/missing_module_instance.rs new file mode 100644 index 0000000000000..fbc4b60db8b78 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_module_instance.rs @@ -0,0 +1,13 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + system: System::<>, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/missing_module_instance.stderr b/frame/support/test/tests/construct_runtime_ui/missing_module_instance.stderr new file mode 100644 index 0000000000000..6303c74e42e5c --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_module_instance.stderr @@ -0,0 +1,5 @@ +error: expected identifier + --> $DIR/missing_module_instance.rs:9:20 + | +9 | system: System::<>, + | ^ diff --git a/frame/support/test/tests/construct_runtime_ui/missing_origin_generic_on_module_with_instance.rs b/frame/support/test/tests/construct_runtime_ui/missing_origin_generic_on_module_with_instance.rs new file mode 100644 index 0000000000000..35a5c8201ba03 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_origin_generic_on_module_with_instance.rs @@ -0,0 +1,14 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + Balance: balances::::{Origin}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/missing_origin_generic_on_module_with_instance.stderr b/frame/support/test/tests/construct_runtime_ui/missing_origin_generic_on_module_with_instance.stderr new file mode 100644 index 0000000000000..0f7d36aafb863 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_origin_generic_on_module_with_instance.stderr @@ -0,0 +1,5 @@ +error: Instantiable module with no generic `Origin` cannot be constructed: module `Balance` must have generic `Origin` + --> $DIR/missing_origin_generic_on_module_with_instance.rs:10:3 + | +10 | Balance: balances::::{Origin}, + | ^^^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/missing_system_module.rs b/frame/support/test/tests/construct_runtime_ui/missing_system_module.rs new file mode 100644 index 0000000000000..71dabf91c1d20 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_system_module.rs @@ -0,0 +1,12 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/missing_system_module.stderr b/frame/support/test/tests/construct_runtime_ui/missing_system_module.stderr new file mode 100644 index 0000000000000..5964a8aa769a6 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_system_module.stderr @@ -0,0 +1,7 @@ +error: `System` module declaration is missing. Please add this line: `System: system::{Module, Call, Storage, Config, Event},` + --> $DIR/missing_system_module.rs:8:2 + | +8 | { + | _____^ +9 | | } + | |_____^ diff --git a/frame/support/test/tests/construct_runtime_ui/missing_where_block.rs b/frame/support/test/tests/construct_runtime_ui/missing_where_block.rs new file mode 100644 index 0000000000000..5148330ae585c --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_where_block.rs @@ -0,0 +1,7 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime {} +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/missing_where_block.stderr b/frame/support/test/tests/construct_runtime_ui/missing_where_block.stderr new file mode 100644 index 0000000000000..4af672a2610b6 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_where_block.stderr @@ -0,0 +1,5 @@ +error: expected `where` + --> $DIR/missing_where_block.rs:4:19 + | +4 | pub enum Runtime {} + | ^^ diff --git a/frame/support/test/tests/construct_runtime_ui/missing_where_param.rs b/frame/support/test/tests/construct_runtime_ui/missing_where_param.rs new file mode 100644 index 0000000000000..2e311c5ea01ae --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_where_param.rs @@ -0,0 +1,10 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + {} +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/missing_where_param.stderr b/frame/support/test/tests/construct_runtime_ui/missing_where_param.stderr new file mode 100644 index 0000000000000..ac7313523c0c4 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/missing_where_param.stderr @@ -0,0 +1,5 @@ +error: Missing associated type for `UncheckedExtrinsic`. Add `UncheckedExtrinsic` = ... to where section. + --> $DIR/missing_where_param.rs:7:2 + | +7 | {} + | ^^ diff --git a/frame/support/test/tests/construct_runtime_ui/no_comma_after_where.rs b/frame/support/test/tests/construct_runtime_ui/no_comma_after_where.rs new file mode 100644 index 0000000000000..954fadefa1794 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/no_comma_after_where.rs @@ -0,0 +1,13 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + UncheckedExtrinsic = UncheckedExtrinsic + Block = Block, + NodeBlock = Block, + { + System: system, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/no_comma_after_where.stderr b/frame/support/test/tests/construct_runtime_ui/no_comma_after_where.stderr new file mode 100644 index 0000000000000..caf4a7401b08e --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/no_comma_after_where.stderr @@ -0,0 +1,5 @@ +error: Expected `,` or `{` + --> $DIR/no_comma_after_where.rs:6:3 + | +6 | Block = Block, + | ^^^^^ diff --git a/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.rs b/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.rs new file mode 100644 index 0000000000000..a739277d62099 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.rs @@ -0,0 +1,14 @@ +use frame_support::construct_runtime; + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system, + Balance: balances::::{Call(toto), Origin}, + } +} + +fn main() {} diff --git a/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.stderr b/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.stderr new file mode 100644 index 0000000000000..58f35720e31f7 --- /dev/null +++ b/frame/support/test/tests/construct_runtime_ui/params_in_invalid_module.stderr @@ -0,0 +1,5 @@ +error: `Call` is not allowed to have arguments in parens. Only the following modules are allowed to have arguments in parens: `Inherent`. + --> $DIR/params_in_invalid_module.rs:10:40 + | +10 | Balance: balances::::{Call(toto), Origin}, + | ^^^^^^ diff --git a/frame/support/test/tests/decl_error.rs b/frame/support/test/tests/decl_error.rs new file mode 100644 index 0000000000000..b90c870c313f5 --- /dev/null +++ b/frame/support/test/tests/decl_error.rs @@ -0,0 +1,135 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![recursion_limit="128"] + +use sp_runtime::{generic, traits::{BlakeTwo256, Block as _, Verify}, DispatchError}; +use sp_core::{H256, sr25519}; + +mod system; + +pub trait Currency {} + +mod module1 { + use super::*; + + pub trait Trait: system::Trait {} + + frame_support::decl_module! { + pub struct Module, I: Instance = DefaultInstance> for enum Call + where origin: ::Origin + { + pub fn fail(_origin) -> frame_support::dispatch::DispatchResult { + Err(Error::::Something.into()) + } + } + } + + frame_support::decl_error! { + pub enum Error for Module, I: Instance> { + Something + } + } + + frame_support::decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as Module {} + } +} + +mod module2 { + use super::*; + + pub trait Trait: system::Trait {} + + frame_support::decl_module! { + pub struct Module for enum Call + where origin: ::Origin + { + pub fn fail(_origin) -> frame_support::dispatch::DispatchResult { + Err(Error::::Something.into()) + } + } + } + + frame_support::decl_error! { + pub enum Error for Module { + Something + } + } + + frame_support::decl_storage! { + trait Store for Module as Module {} + } +} + +impl module1::Trait for Runtime {} +impl module1::Trait for Runtime {} +impl module2::Trait for Runtime {} + +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 AccountId = AccountId; + type Event = Event; + type ModuleToIndex = ModuleToIndex; +} + +frame_support::construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event}, + Module1_1: module1::::{Module, Call, Storage}, + Module2: module2::{Module, Call, Storage}, + Module1_2: module1::::{Module, Call, Storage}, + } +); + +pub type Header = generic::Header; +pub type Block = generic::Block; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + +#[test] +fn check_module1_1_error_type() { + assert_eq!( + Module1_1::fail(system::Origin::::Root.into()), + Err(DispatchError::Module { index: 1, error: 0, message: Some("Something") }), + ); +} + +#[test] +fn check_module1_2_error_type() { + assert_eq!( + Module1_2::fail(system::Origin::::Root.into()), + Err(DispatchError::Module { index: 3, error: 0, message: Some("Something") }), + ); +} + +#[test] +fn check_module2_error_type() { + assert_eq!( + Module2::fail(system::Origin::::Root.into()), + Err(DispatchError::Module { index: 2, error: 0, message: Some("Something") }), + ); +} diff --git a/frame/support/test/tests/decl_storage.rs b/frame/support/test/tests/decl_storage.rs new file mode 100644 index 0000000000000..15a0807fa5701 --- /dev/null +++ b/frame/support/test/tests/decl_storage.rs @@ -0,0 +1,698 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#[cfg(test)] +// Do not complain about unused `dispatch` and `dispatch_aux`. +#[allow(dead_code)] +mod tests { + use frame_support::metadata::*; + use sp_io::TestExternalities; + use std::marker::PhantomData; + use codec::{Encode, Decode, EncodeLike}; + + frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + pub trait Trait { + type Origin: Encode + Decode + EncodeLike + std::default::Default; + type BlockNumber; + } + + frame_support::decl_storage! { + trait Store for Module as TestStorage { + // non-getters: pub / $default + + /// Hello, this is doc! + U32 : Option; + pub PUBU32 : Option; + U32MYDEF : Option; + pub PUBU32MYDEF : Option; + + // getters: pub / $default + // we need at least one type which uses T, otherwise GenesisConfig will complain. + GETU32 get(fn u32_getter): T::Origin; + pub PUBGETU32 get(fn pub_u32_getter): u32; + GETU32WITHCONFIG get(fn u32_getter_with_config) config(): u32; + pub PUBGETU32WITHCONFIG get(fn pub_u32_getter_with_config) config(): u32; + GETU32MYDEF get(fn u32_getter_mydef): Option; + pub PUBGETU32MYDEF get(fn pub_u32_getter_mydef) config(): u32 = 3; + GETU32WITHCONFIGMYDEF get(fn u32_getter_with_config_mydef) config(): u32 = 2; + pub PUBGETU32WITHCONFIGMYDEF get(fn pub_u32_getter_with_config_mydef) config(): u32 = 1; + PUBGETU32WITHCONFIGMYDEFOPT get(fn pub_u32_getter_with_config_mydef_opt) config(): Option; + + GetU32WithBuilder get(fn u32_with_builder) build(|_| 1): u32; + GetOptU32WithBuilderSome get(fn opt_u32_with_builder_some) build(|_| Some(1)): Option; + GetOptU32WithBuilderNone get(fn opt_u32_with_builder_none) build(|_| None): Option; + + // map non-getters: pub / $default + MAPU32 : map u32 => Option; + pub PUBMAPU32 : map u32 => Option; + MAPU32MYDEF : map u32 => Option; + pub PUBMAPU32MYDEF : map u32 => Option; + + // map getters: pub / $default + GETMAPU32 get(fn map_u32_getter): map u32 => String; + pub PUBGETMAPU32 get(fn pub_map_u32_getter): map u32 => String; + + GETMAPU32MYDEF get(fn map_u32_getter_mydef): map u32 => String = "map".into(); + pub PUBGETMAPU32MYDEF get(fn pub_map_u32_getter_mydef): map u32 => String = "pubmap".into(); + + // linked map + LINKEDMAPU32 : linked_map u32 => Option; + pub PUBLINKEDMAPU32MYDEF : linked_map u32 => Option; + GETLINKEDMAPU32 get(fn linked_map_u32_getter): linked_map u32 => String; + pub PUBGETLINKEDMAPU32MYDEF get(fn pub_linked_map_u32_getter_mydef): linked_map u32 => String = "pubmap".into(); + + COMPLEXTYPE1: ::std::vec::Vec<::Origin>; + COMPLEXTYPE2: (Vec)>>, u32); + COMPLEXTYPE3: [u32;25]; + } + add_extra_genesis { + build(|_| {}); + } + } + + struct TraitImpl {} + + impl Trait for TraitImpl { + type Origin = u32; + type BlockNumber = u32; + } + + const EXPECTED_METADATA: StorageMetadata = StorageMetadata { + prefix: DecodeDifferent::Encode("TestStorage"), + entries: DecodeDifferent::Encode( + &[ + StorageEntryMetadata { + name: DecodeDifferent::Encode("U32"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[ " Hello, this is doc!" ]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBU32"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("U32MYDEF"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBU32MYDEF"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GETU32"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("T::Origin")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBGETU32"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GETU32WITHCONFIG"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETU32WITHCONFIG(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBGETU32WITHCONFIG"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIG(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GETU32MYDEF"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBGETU32MYDEF"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GETU32WITHCONFIGMYDEF"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETU32WITHCONFIGMYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEF"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIGMYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEFOPT"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIGMYDEFOPT(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GetU32WithBuilder"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGetU32WithBuilder(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GetOptU32WithBuilderSome"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGetOptU32WithBuilderSome(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GetOptU32WithBuilderNone"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGetOptU32WithBuilderNone(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("MAPU32"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructMAPU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBMAPU32"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBMAPU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("MAPU32MYDEF"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBMAPU32MYDEF"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GETMAPU32"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETMAPU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBGETMAPU32"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETMAPU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GETMAPU32MYDEF"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBGETMAPU32MYDEF"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: false, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("LINKEDMAPU32"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructLINKEDMAPU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBLINKEDMAPU32MYDEF"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBLINKEDMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GETLINKEDMAPU32"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGETLINKEDMAPU32(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("PUBGETLINKEDMAPU32MYDEF"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Map { + hasher: StorageHasher::Blake2_256, + key: DecodeDifferent::Encode("u32"), + value: DecodeDifferent::Encode("String"), + is_linked: true, + }, + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructPUBGETLINKEDMAPU32MYDEF(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("COMPLEXTYPE1"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("::std::vec::Vec<::Origin>")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructCOMPLEXTYPE1(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("COMPLEXTYPE2"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("(Vec)>>, u32)")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructCOMPLEXTYPE2(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("COMPLEXTYPE3"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("[u32; 25]")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructCOMPLEXTYPE3(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + ] + ), + }; + + #[test] + fn store_metadata() { + let metadata = Module::::storage_metadata(); + pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata); + } + + #[test] + fn check_genesis_config() { + let config = GenesisConfig::default(); + assert_eq!(config.u32_getter_with_config, 0u32); + assert_eq!(config.pub_u32_getter_with_config, 0u32); + + assert_eq!(config.pub_u32_getter_mydef, 3u32); + assert_eq!(config.u32_getter_with_config_mydef, 2u32); + assert_eq!(config.pub_u32_getter_with_config_mydef, 1u32); + assert_eq!(config.pub_u32_getter_with_config_mydef_opt, 0u32); + } + + #[test] + fn check_builder_config() { + let config = GenesisConfig::default(); + let storage = config.build_storage().unwrap(); + TestExternalities::from(storage).execute_with(|| { + assert_eq!(Module::::u32_with_builder(), 1); + assert_eq!(Module::::opt_u32_with_builder_some(), Some(1)); + assert_eq!(Module::::opt_u32_with_builder_none(), None); + }) + } +} + +#[cfg(test)] +#[allow(dead_code)] +mod test2 { + pub trait Trait { + type Origin; + type BlockNumber; + } + + frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + type PairOf = (T, T); + + frame_support::decl_storage! { + trait Store for Module as TestStorage { + SingleDef : u32; + PairDef : PairOf; + Single : Option; + Pair : (u32, u32); + } + add_extra_genesis { + config(_marker) : ::std::marker::PhantomData; + config(extra_field) : u32 = 32; + build(|_| {}); + } + } + + struct TraitImpl {} + + impl Trait for TraitImpl { + type Origin = u32; + type BlockNumber = u32; + } +} + +#[cfg(test)] +#[allow(dead_code)] +mod test3 { + pub trait Trait { + type Origin; + type BlockNumber; + } + frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + frame_support::decl_storage! { + trait Store for Module as Test { + Foo get(fn foo) config(initial_foo): u32; + } + } + + type PairOf = (T, T); + + struct TraitImpl {} + + impl Trait for TraitImpl { + type Origin = u32; + type BlockNumber = u32; + } +} + +#[cfg(test)] +#[allow(dead_code)] +mod test_append_and_len { + use sp_io::TestExternalities; + use codec::{Encode, Decode}; + + pub trait Trait { + type Origin; + type BlockNumber; + } + + frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + #[derive(PartialEq, Eq, Clone, Encode, Decode)] + struct NoDef(u32); + + frame_support::decl_storage! { + trait Store for Module as Test { + NoDefault: Option; + + JustVec: Vec; + JustVecWithDefault: Vec = vec![6, 9]; + OptionVec: Option>; + + MapVec: map u32 => Vec; + MapVecWithDefault: map u32 => Vec = vec![6, 9]; + OptionMapVec: map u32 => Option>; + + DoubleMapVec: double_map u32, u32 => Vec; + DoubleMapVecWithDefault: double_map u32, u32 => Vec = vec![6, 9]; + OptionDoubleMapVec: double_map u32, u32 => Option>; + + LinkedMapVec: linked_map u32 => Vec; + LinkedMapVecWithDefault: linked_map u32 => Vec = vec![6, 9]; + OptionLinkedMapVec: linked_map u32 => Option>; + } + } + + struct Test {} + + impl Trait for Test { + type Origin = u32; + type BlockNumber = u32; + } + + #[test] + fn default_for_option() { + TestExternalities::default().execute_with(|| { + assert_eq!(OptionVec::get(), None); + assert_eq!(JustVec::get(), vec![]); + }); + } + + #[test] + fn append_works() { + TestExternalities::default().execute_with(|| { + let _ = MapVec::append(1, [1, 2, 3].iter()); + let _ = MapVec::append(1, [4, 5].iter()); + assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); + + let _ = JustVec::append([1, 2, 3].iter()); + let _ = JustVec::append([4, 5].iter()); + assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); + }); + } + + #[test] + fn append_works_for_default() { + TestExternalities::default().execute_with(|| { + assert_eq!(JustVecWithDefault::get(), vec![6, 9]); + let _ = JustVecWithDefault::append([1].iter()); + assert_eq!(JustVecWithDefault::get(), vec![6, 9, 1]); + + assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); + let _ = MapVecWithDefault::append(0, [1].iter()); + assert_eq!(MapVecWithDefault::get(0), vec![6, 9, 1]); + + assert_eq!(OptionVec::get(), None); + let _ = OptionVec::append([1].iter()); + assert_eq!(OptionVec::get(), Some(vec![1])); + }); + } + + #[test] + fn append_or_put_works() { + TestExternalities::default().execute_with(|| { + let _ = MapVec::append_or_insert(1, &[1, 2, 3][..]); + let _ = MapVec::append_or_insert(1, &[4, 5][..]); + assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); + + let _ = JustVec::append_or_put(&[1, 2, 3][..]); + let _ = JustVec::append_or_put(&[4, 5][..]); + assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); + + let _ = OptionVec::append_or_put(&[1, 2, 3][..]); + let _ = OptionVec::append_or_put(&[4, 5][..]); + assert_eq!(OptionVec::get(), Some(vec![1, 2, 3, 4, 5])); + }); + } + + #[test] + fn len_works() { + TestExternalities::default().execute_with(|| { + JustVec::put(&vec![1, 2, 3, 4]); + OptionVec::put(&vec![1, 2, 3, 4, 5]); + MapVec::insert(1, &vec![1, 2, 3, 4, 5, 6]); + LinkedMapVec::insert(2, &vec![1, 2, 3]); + DoubleMapVec::insert(0, 1, &vec![1, 2]); + + assert_eq!(JustVec::decode_len().unwrap(), 4); + assert_eq!(OptionVec::decode_len().unwrap(), 5); + assert_eq!(MapVec::decode_len(1).unwrap(), 6); + assert_eq!(LinkedMapVec::decode_len(2).unwrap(), 3); + assert_eq!(DoubleMapVec::decode_len(0, 1).unwrap(), 2); + }); + } + + #[test] + fn len_works_for_default() { + TestExternalities::default().execute_with(|| { + // vec + assert_eq!(JustVec::get(), vec![]); + assert_eq!(JustVec::decode_len(), Ok(0)); + + assert_eq!(JustVecWithDefault::get(), vec![6, 9]); + assert_eq!(JustVecWithDefault::decode_len(), Ok(2)); + + assert_eq!(OptionVec::get(), None); + assert_eq!(OptionVec::decode_len(), Ok(0)); + + // map + assert_eq!(MapVec::get(0), vec![]); + assert_eq!(MapVec::decode_len(0), Ok(0)); + + assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); + assert_eq!(MapVecWithDefault::decode_len(0), Ok(2)); + + assert_eq!(OptionMapVec::get(0), None); + assert_eq!(OptionMapVec::decode_len(0), Ok(0)); + + // linked map + assert_eq!(LinkedMapVec::get(0), vec![]); + assert_eq!(LinkedMapVec::decode_len(0), Ok(0)); + + assert_eq!(LinkedMapVecWithDefault::get(0), vec![6, 9]); + assert_eq!(LinkedMapVecWithDefault::decode_len(0), Ok(2)); + + assert_eq!(OptionLinkedMapVec::get(0), None); + assert_eq!(OptionLinkedMapVec::decode_len(0), Ok(0)); + + // Double map + assert_eq!(DoubleMapVec::get(0, 0), vec![]); + assert_eq!(DoubleMapVec::decode_len(0, 1), Ok(0)); + + assert_eq!(DoubleMapVecWithDefault::get(0, 0), vec![6, 9]); + assert_eq!(DoubleMapVecWithDefault::decode_len(0, 1), Ok(2)); + + assert_eq!(OptionDoubleMapVec::get(0, 0), None); + assert_eq!(OptionDoubleMapVec::decode_len(0, 1), Ok(0)); + }); + } +} diff --git a/srml/support/test/tests/decl_storage_ui.rs b/frame/support/test/tests/decl_storage_ui.rs similarity index 94% rename from srml/support/test/tests/decl_storage_ui.rs rename to frame/support/test/tests/decl_storage_ui.rs index 32c15eb390f8b..3aee5e9866413 100644 --- a/srml/support/test/tests/decl_storage_ui.rs +++ b/frame/support/test/tests/decl_storage_ui.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/srml/support/test/tests/decl_storage_ui/config_duplicate.rs b/frame/support/test/tests/decl_storage_ui/config_duplicate.rs similarity index 89% rename from srml/support/test/tests/decl_storage_ui/config_duplicate.rs rename to frame/support/test/tests/decl_storage_ui/config_duplicate.rs index bdd7da7449aa8..0f2759e740d7d 100644 --- a/srml/support/test/tests/decl_storage_ui/config_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/config_duplicate.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,11 +19,11 @@ pub trait Trait { type BlockNumber: codec::Codec + codec::EncodeLike + Default + Clone; } -support::decl_module! { +frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } -support::decl_storage!{ +frame_support::decl_storage!{ trait Store for Module as FinalKeysNone { pub Value config(value): u32; pub Value2 config(value): u32; diff --git a/srml/support/test/tests/decl_storage_ui/config_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/config_duplicate.stderr similarity index 100% rename from srml/support/test/tests/decl_storage_ui/config_duplicate.stderr rename to frame/support/test/tests/decl_storage_ui/config_duplicate.stderr diff --git a/srml/support/test/tests/decl_storage_ui/config_get_duplicate.rs b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs similarity index 89% rename from srml/support/test/tests/decl_storage_ui/config_get_duplicate.rs rename to frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs index 2bf8df45322cc..a4e0158d5c5c5 100644 --- a/srml/support/test/tests/decl_storage_ui/config_get_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,11 +19,11 @@ pub trait Trait { type BlockNumber: codec::Codec + codec::EncodeLike + Default + Clone; } -support::decl_module! { +frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } -support::decl_storage!{ +frame_support::decl_storage!{ trait Store for Module as FinalKeysNone { pub Value get(fn value) config(): u32; pub Value2 config(value): u32; diff --git a/srml/support/test/tests/decl_storage_ui/config_get_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr similarity index 100% rename from srml/support/test/tests/decl_storage_ui/config_get_duplicate.stderr rename to frame/support/test/tests/decl_storage_ui/config_get_duplicate.stderr diff --git a/srml/support/test/tests/decl_storage_ui/get_duplicate.rs b/frame/support/test/tests/decl_storage_ui/get_duplicate.rs similarity index 89% rename from srml/support/test/tests/decl_storage_ui/get_duplicate.rs rename to frame/support/test/tests/decl_storage_ui/get_duplicate.rs index 41ca708352e8b..9edbc25bf9d83 100644 --- a/srml/support/test/tests/decl_storage_ui/get_duplicate.rs +++ b/frame/support/test/tests/decl_storage_ui/get_duplicate.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,11 +19,11 @@ pub trait Trait { type BlockNumber: codec::Codec + codec::EncodeLike + Default + Clone; } -support::decl_module! { +frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } -support::decl_storage!{ +frame_support::decl_storage!{ trait Store for Module as FinalKeysNone { pub Value get(fn value) config(): u32; pub Value2 get(fn value) config(): u32; diff --git a/srml/support/test/tests/decl_storage_ui/get_duplicate.stderr b/frame/support/test/tests/decl_storage_ui/get_duplicate.stderr similarity index 100% rename from srml/support/test/tests/decl_storage_ui/get_duplicate.stderr rename to frame/support/test/tests/decl_storage_ui/get_duplicate.stderr diff --git a/frame/support/test/tests/final_keys.rs b/frame/support/test/tests/final_keys.rs new file mode 100644 index 0000000000000..9f1b379e2544d --- /dev/null +++ b/frame/support/test/tests/final_keys.rs @@ -0,0 +1,239 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use frame_support::storage::unhashed; +use codec::Encode; +use frame_support::{StorageDoubleMap, StorageLinkedMap, StorageMap, StorageValue, StoragePrefixedMap}; +use sp_io::{TestExternalities, hashing::{twox_128, blake2_128, blake2_256}}; + +mod no_instance { + use codec::{Encode, Decode, EncodeLike}; + + pub trait Trait { + type Origin; + type BlockNumber: Encode + Decode + EncodeLike + Default + Clone; + } + + frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + frame_support::decl_storage!{ + trait Store for Module as FinalKeysNone { + pub Value config(value): u32; + + pub Map: map u32 => u32; + pub Map2: map hasher(twox_128) u32 => u32; + + pub LinkedMap: linked_map u32 => u32; + pub LinkedMap2: linked_map hasher(twox_128) u32 => u32; + + pub DoubleMap: double_map u32, u32 => u32; + pub DoubleMap2: double_map hasher(twox_128) u32, hasher(blake2_128) u32 => u32; + + pub TestGenericValue get(fn test_generic_value) config(): Option; + pub TestGenericDoubleMap get(fn foo2) config(test_generic_double_map): + double_map u32, T::BlockNumber => Option; + } + } +} + +mod instance { + pub trait Trait: super::no_instance::Trait {} + + frame_support::decl_module! { + pub struct Module, I: Instantiable = DefaultInstance> + for enum Call where origin: T::Origin {} + } + + frame_support::decl_storage!{ + trait Store for Module, I: Instantiable = DefaultInstance> + as FinalKeysSome + { + pub Value config(value): u32; + + pub Map: map u32 => u32; + pub Map2: map hasher(twox_128) u32 => u32; + + pub LinkedMap: linked_map u32 => u32; + pub LinkedMap2: linked_map hasher(twox_128) u32 => u32; + + pub DoubleMap: double_map u32, u32 => u32; + pub DoubleMap2: double_map hasher(twox_128) u32, hasher(blake2_128) u32 => u32; + + pub TestGenericValue get(fn test_generic_value) config(): Option; + pub TestGenericDoubleMap get(fn foo2) config(test_generic_double_map): + double_map u32, T::BlockNumber => Option; + } + add_extra_genesis { + // See `decl_storage` limitation. + config(phantom): core::marker::PhantomData; + } + } +} + +#[test] +fn final_keys_no_instance() { + TestExternalities::default().execute_with(|| { + no_instance::Value::put(1); + let k = [twox_128(b"FinalKeysNone"), twox_128(b"Value")].concat(); + assert_eq!(unhashed::get::(&k), Some(1u32)); + + no_instance::Map::insert(1, 2); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"Map")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &::final_prefix()); + + no_instance::Map2::insert(1, 2); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"Map2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &::final_prefix()); + + let head = [twox_128(b"FinalKeysNone"), twox_128(b"HeadOfLinkedMap")].concat(); + assert_eq!(unhashed::get::(&head), None); + + no_instance::LinkedMap::insert(1, 2); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"LinkedMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(unhashed::get::(&head), Some(1u32)); + assert_eq!(&k[..32], &::final_prefix()); + + no_instance::LinkedMap2::insert(1, 2); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"LinkedMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &::final_prefix()); + + no_instance::DoubleMap::insert(&1, &2, &3); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"DoubleMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + k.extend(2u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(3u32)); + assert_eq!(&k[..32], &::final_prefix()); + + no_instance::DoubleMap2::insert(&1, &2, &3); + let mut k = [twox_128(b"FinalKeysNone"), twox_128(b"DoubleMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + k.extend(2u32.using_encoded(blake2_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(3u32)); + assert_eq!(&k[..32], &::final_prefix()); + }); +} + +#[test] +fn final_keys_default_instance() { + TestExternalities::default().execute_with(|| { + >::put(1); + let k = [twox_128(b"FinalKeysSome"), twox_128(b"Value")].concat(); + assert_eq!(unhashed::get::(&k), Some(1u32)); + + >::insert(1, 2); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"Map")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + >::insert(1, 2); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"Map2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + let head = [twox_128(b"FinalKeysSome"), twox_128(b"HeadOfLinkedMap")].concat(); + assert_eq!(unhashed::get::(&head), None); + + >::insert(1, 2); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"LinkedMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(unhashed::get::(&head), Some(1u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + >::insert(1, 2); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"LinkedMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + >::insert(&1, &2, &3); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"DoubleMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + k.extend(2u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(3u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + >::insert(&1, &2, &3); + let mut k = [twox_128(b"FinalKeysSome"), twox_128(b"DoubleMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + k.extend(2u32.using_encoded(blake2_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(3u32)); + assert_eq!(&k[..32], &>::final_prefix()); + }); +} + +#[test] +fn final_keys_instance_2() { + TestExternalities::default().execute_with(|| { + >::put(1); + let k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"Value")].concat(); + assert_eq!(unhashed::get::(&k), Some(1u32)); + + >::insert(1, 2); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"Map")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + >::insert(1, 2); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"Map2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + let head = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"HeadOfLinkedMap")].concat(); + assert_eq!(unhashed::get::(&head), None); + + >::insert(1, 2); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"LinkedMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(unhashed::get::(&head), Some(1u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + >::insert(1, 2); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"LinkedMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(2u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + >::insert(&1, &2, &3); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"DoubleMap")].concat(); + k.extend(1u32.using_encoded(blake2_256).to_vec()); + k.extend(2u32.using_encoded(blake2_256).to_vec()); + assert_eq!(unhashed::get::(&k), Some(3u32)); + assert_eq!(&k[..32], &>::final_prefix()); + + >::insert(&1, &2, &3); + let mut k = [twox_128(b"Instance2FinalKeysSome"), twox_128(b"DoubleMap2")].concat(); + k.extend(1u32.using_encoded(twox_128).to_vec()); + k.extend(2u32.using_encoded(blake2_128).to_vec()); + assert_eq!(unhashed::get::(&k), Some(3u32)); + assert_eq!(&k[..32], &>::final_prefix()); + }); +} diff --git a/srml/support/test/tests/genesisconfig.rs b/frame/support/test/tests/genesisconfig.rs similarity index 85% rename from srml/support/test/tests/genesisconfig.rs rename to frame/support/test/tests/genesisconfig.rs index e945c774c0d07..dee7aefe0aaa3 100644 --- a/srml/support/test/tests/genesisconfig.rs +++ b/frame/support/test/tests/genesisconfig.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,13 +19,13 @@ pub trait Trait { type Origin; } -support::decl_module! { +frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } -support::decl_storage! { +frame_support::decl_storage! { trait Store for Module as Example { - pub AppendableDM config(t): double_map u32, blake2_256(T::BlockNumber) => Vec; + pub AppendableDM config(t): double_map u32, T::BlockNumber => Vec; } } diff --git a/srml/support/test/tests/instance.rs b/frame/support/test/tests/instance.rs similarity index 90% rename from srml/support/test/tests/instance.rs rename to frame/support/test/tests/instance.rs index 282fb9a6e299f..879ef4fa684d2 100644 --- a/srml/support/test/tests/instance.rs +++ b/frame/support/test/tests/instance.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -16,8 +16,8 @@ #![recursion_limit="128"] -use sr_primitives::{generic, BuildStorage, traits::{BlakeTwo256, Block as _, Verify}}; -use support::{ +use sp_runtime::{generic, BuildStorage, traits::{BlakeTwo256, Block as _, Verify}}; +use frame_support::{ Parameter, traits::Get, parameter_types, metadata::{ DecodeDifferent, StorageMetadata, StorageEntryModifier, StorageEntryType, DefaultByteGetter, @@ -25,10 +25,8 @@ use support::{ }, StorageValue, StorageMap, StorageLinkedMap, StorageDoubleMap, }; -use inherents::{ - ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError -}; -use primitives::{H256, sr25519}; +use sp_inherents::{ProvideInherent, InherentData, InherentIdentifier, MakeFatalError}; +use sp_core::{H256, sr25519}; mod system; @@ -48,7 +46,7 @@ mod module1 { type GenericType: Default + Clone + codec::Codec + codec::EncodeLike; } - support::decl_module! { + frame_support::decl_module! { pub struct Module, I: InstantiableThing> for enum Call where origin: ::Origin, T::BlockNumber: From @@ -64,7 +62,7 @@ mod module1 { } } - support::decl_storage! { + frame_support::decl_storage! { trait Store for Module, I: InstantiableThing> as Module1 where T::BlockNumber: From + std::fmt::Display { @@ -81,14 +79,14 @@ mod module1 { } } - support::decl_event! { + frame_support::decl_event! { pub enum Event where Phantom = std::marker::PhantomData { _Phantom(Phantom), AnotherVariant(u32), } } - #[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] + #[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] pub enum Origin, I> where T::BlockNumber: From { Members(u32), _Phantom(std::marker::PhantomData<(T, I)>), @@ -100,7 +98,7 @@ mod module1 { T::BlockNumber: From { type Call = Call; - type Error = MakeFatalError; + type Error = MakeFatalError; const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; fn create_inherent(_data: &InherentData) -> Option { @@ -127,7 +125,7 @@ mod module2 { impl, I: Instance> Currency for Module {} - support::decl_module! { + frame_support::decl_module! { pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { @@ -135,22 +133,22 @@ mod module2 { } } - support::decl_storage! { + frame_support::decl_storage! { trait Store for Module, I: Instance=DefaultInstance> as Module2 { pub Value config(value): T::Amount; pub Map config(map): map u64 => u64; pub LinkedMap config(linked_map): linked_map u64 => Vec; - pub DoubleMap config(double_map): double_map u64, blake2_256(u64) => u64; + pub DoubleMap config(double_map): double_map u64, u64 => u64; } } - support::decl_event! { + frame_support::decl_event! { pub enum Event where Amount = >::Amount { Variant(Amount), } } - #[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] + #[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] pub enum Origin, I=DefaultInstance> { Members(u32), _Phantom(std::marker::PhantomData<(T, I)>), @@ -160,7 +158,7 @@ mod module2 { impl, I: Instance> ProvideInherent for Module { type Call = Call; - type Error = MakeFatalError; + type Error = MakeFatalError; const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; fn create_inherent(_data: &InherentData) -> Option { @@ -183,7 +181,7 @@ mod module3 { type Currency2: Currency; } - support::decl_module! { + frame_support::decl_module! { pub struct Module for enum Call where origin: ::Origin {} } } @@ -240,9 +238,10 @@ impl system::Trait for Runtime { type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; + type ModuleToIndex = (); } -support::construct_runtime!( +frame_support::construct_runtime!( pub enum Runtime where Block = Block, NodeBlock = Block, @@ -273,7 +272,7 @@ pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; -fn new_test_ext() -> runtime_io::TestExternalities { +fn new_test_ext() -> sp_io::TestExternalities { GenesisConfig{ module1_Instance1: Some(module1::GenesisConfig { value: 3, @@ -302,8 +301,11 @@ fn new_test_ext() -> runtime_io::TestExternalities { #[test] fn storage_instance_independance() { - let mut storage = (std::collections::HashMap::new(), std::collections::HashMap::new()); - runtime_io::with_storage(&mut storage, || { + let mut storage = sp_core::storage::Storage { + top: std::collections::BTreeMap::new(), + children: std::collections::HashMap::new() + }; + sp_state_machine::BasicExternalities::execute_with_storage(&mut storage, || { module2::Value::::put(0); module2::Value::::put(0); module2::Value::::put(0); @@ -322,7 +324,7 @@ fn storage_instance_independance() { module2::DoubleMap::::insert(&0, &0, &0); }); // 16 storage values + 4 linked_map head. - assert_eq!(storage.0.len(), 16 + 4); + assert_eq!(storage.top.len(), 16 + 4); } #[test] @@ -474,14 +476,3 @@ fn test_instance_storage_metadata() { let metadata = Module2_2::storage_metadata(); pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata); } - -#[test] -fn instance_prefix_is_prefix_of_entries() { - use module2::Instance; - - let prefix = module2::Instance2::PREFIX; - assert!(module2::Instance2::PREFIX_FOR_Value.starts_with(prefix)); - assert!(module2::Instance2::PREFIX_FOR_Map.starts_with(prefix)); - assert!(module2::Instance2::PREFIX_FOR_LinkedMap.starts_with(prefix)); - assert!(module2::Instance2::PREFIX_FOR_DoubleMap.starts_with(prefix)); -} diff --git a/srml/support/test/tests/issue2219.rs b/frame/support/test/tests/issue2219.rs similarity index 93% rename from srml/support/test/tests/issue2219.rs rename to frame/support/test/tests/issue2219.rs index 72e0bc8caf198..f3ce4dac80e25 100644 --- a/srml/support/test/tests/issue2219.rs +++ b/frame/support/test/tests/issue2219.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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 support::sr_primitives::generic; -use support::sr_primitives::traits::{BlakeTwo256, Block as _, Verify}; -use support::codec::{Encode, Decode}; -use primitives::{H256, sr25519}; +use frame_support::sp_runtime::generic; +use frame_support::sp_runtime::traits::{BlakeTwo256, Block as _, Verify}; +use frame_support::codec::{Encode, Decode}; +use sp_core::{H256, sr25519}; use serde::{Serialize, Deserialize}; mod system; @@ -82,7 +82,7 @@ mod module { pub trait Trait: system::Trait {} - support::decl_module! { + frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } @@ -99,7 +99,7 @@ mod module { } } - support::decl_storage! { + frame_support::decl_storage! { trait Store for Module as Actors { /// requirements to enter and maintain status in roles pub Parameters get(fn parameters) build(|config: &GenesisConfig| { @@ -160,11 +160,12 @@ impl system::Trait for Runtime { type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; + type ModuleToIndex = (); } impl module::Trait for Runtime {} -support::construct_runtime!( +frame_support::construct_runtime!( pub enum Runtime where Block = Block, NodeBlock = Block, diff --git a/srml/support/test/tests/reserved_keyword.rs b/frame/support/test/tests/reserved_keyword.rs similarity index 94% rename from srml/support/test/tests/reserved_keyword.rs rename to frame/support/test/tests/reserved_keyword.rs index 898d61b8279e9..d6cc4bba3b0b0 100644 --- a/srml/support/test/tests/reserved_keyword.rs +++ b/frame/support/test/tests/reserved_keyword.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/frame/support/test/tests/reserved_keyword/on_initialize.rs b/frame/support/test/tests/reserved_keyword/on_initialize.rs new file mode 100644 index 0000000000000..e389529bca57e --- /dev/null +++ b/frame/support/test/tests/reserved_keyword/on_initialize.rs @@ -0,0 +1,32 @@ +macro_rules! reserved { + ($($reserved:ident)*) => { + $( + mod $reserved { + pub use frame_support::dispatch; + + pub trait Trait { + type Origin; + type BlockNumber: Into; + } + + pub mod system { + use frame_support::dispatch; + + pub fn ensure_root(_: R) -> dispatch::DispatchResult { + Ok(()) + } + } + + frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn $reserved(_origin) -> dispatch::DispatchResult { unreachable!() } + } + } + } + )* + } +} + +reserved!(on_finalize on_initialize on_finalise on_initialise offchain_worker deposit_event); + +fn main() {} diff --git a/srml/support/test/tests/reserved_keyword/on_initialize.stderr b/frame/support/test/tests/reserved_keyword/on_initialize.stderr similarity index 100% rename from srml/support/test/tests/reserved_keyword/on_initialize.stderr rename to frame/support/test/tests/reserved_keyword/on_initialize.stderr diff --git a/frame/support/test/tests/system.rs b/frame/support/test/tests/system.rs new file mode 100644 index 0000000000000..c5b591642b820 --- /dev/null +++ b/frame/support/test/tests/system.rs @@ -0,0 +1,79 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use frame_support::codec::{Encode, Decode, EncodeLike}; + +pub trait Trait: 'static + Eq + Clone { + type Origin: Into, Self::Origin>> + + From>; + + type BlockNumber: Decode + Encode + EncodeLike + Clone + Default; + type Hash; + type AccountId: Encode + EncodeLike + Decode; + type Event: From; + type ModuleToIndex: frame_support::traits::ModuleToIndex; +} + +frame_support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} +} + +impl Module { + pub fn deposit_event(_event: impl Into) {} +} + +frame_support::decl_event!( + pub enum Event { + ExtrinsicSuccess, + ExtrinsicFailed, + } +); + +frame_support::decl_error! { + pub enum Error for Module { + /// Test error documentation + TestError, + /// Error documentation + /// with multiple lines + AnotherError + } +} + +/// Origin for the system module. +#[derive(PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] +pub enum RawOrigin { + Root, + Signed(AccountId), + None, +} + +impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::None, + } + } +} + +pub type Origin = RawOrigin<::AccountId>; + +#[allow(dead_code)] +pub fn ensure_root(o: OuterOrigin) -> Result<(), &'static str> + where OuterOrigin: Into, OuterOrigin>> +{ + o.into().map(|_| ()).map_err(|_| "bad origin: expected to be a root origin") +} diff --git a/frame/system/Cargo.toml b/frame/system/Cargo.toml new file mode 100644 index 0000000000000..227aecee2ee43 --- /dev/null +++ b/frame/system/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "frame-system" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +safe-mix = { version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io ={ path = "../../primitives/io", default-features = false } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-version = { version = "2.0.0", default-features = false, path = "../../primitives/version" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +impl-trait-for-tuples = "0.1.3" + +[dev-dependencies] +criterion = "0.2.11" + +[features] +default = ["std"] +std = [ + "serde", + "safe-mix/std", + "codec/std", + "sp-core/std", + "sp-std/std", + "sp-io/std", + "frame-support/std", + "sp-runtime/std", + "sp-version/std", +] + +[[bench]] +name = "bench" +harness = false diff --git a/frame/system/benches/bench.rs b/frame/system/benches/bench.rs new file mode 100644 index 0000000000000..42a35c49a1176 --- /dev/null +++ b/frame/system/benches/bench.rs @@ -0,0 +1,106 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use criterion::{Criterion, criterion_group, criterion_main, black_box}; +use frame_system as system; +use frame_support::{decl_module, decl_event, impl_outer_origin, impl_outer_event, weights::Weight}; +use sp_core::H256; +use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + +mod module { + use super::*; + + pub trait Trait: system::Trait { + type Event: From + Into<::Event>; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { + pub fn deposit_event() = default; + } + } + + decl_event!( + pub enum Event { + Complex(Vec, u32, u16, u128), + } + ); +} + +impl_outer_origin!{ + pub enum Origin for Runtime {} +} + +impl_outer_event! { + pub enum Event for Runtime { + module, + } +} + +frame_support::parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 4 * 1024 * 1024; + pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); +} +#[derive(Clone, Eq, PartialEq)] +pub struct Runtime; +impl system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +impl module::Trait for Runtime { + type Event = Event; +} + +fn new_test_ext() -> sp_io::TestExternalities { + system::GenesisConfig::default().build_storage::().unwrap().into() +} + +fn deposit_events(n: usize) { + let mut t = new_test_ext(); + t.execute_with(|| { + for _ in 0..n { + module::Module::::deposit_event( + module::Event::Complex(vec![1, 2, 3], 2, 3, 899) + ); + } + }); +} + +fn sr_system_benchmark(c: &mut Criterion) { + c.bench_function("deposit 100 events", |b| { + b.iter(|| deposit_events(black_box(100))) + }); +} + +criterion_group!(benches, sr_system_benchmark); +criterion_main!(benches); diff --git a/frame/system/rpc/runtime-api/Cargo.toml b/frame/system/rpc/runtime-api/Cargo.toml new file mode 100644 index 0000000000000..f9beb848aad36 --- /dev/null +++ b/frame/system/rpc/runtime-api/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "frame-system-rpc-runtime-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-api = { version = "2.0.0", default-features = false, path = "../../../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } + +[features] +default = ["std"] +std = [ + "sp-api/std", + "codec/std", +] diff --git a/frame/system/rpc/runtime-api/src/lib.rs b/frame/system/rpc/runtime-api/src/lib.rs new file mode 100644 index 0000000000000..3b05bd162468e --- /dev/null +++ b/frame/system/rpc/runtime-api/src/lib.rs @@ -0,0 +1,34 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime API definition required by System RPC extensions. +//! +//! This API should be imported and implemented by the runtime, +//! of a node that wants to use the custom RPC extension +//! adding System access methods. + +#![cfg_attr(not(feature = "std"), no_std)] + +sp_api::decl_runtime_apis! { + /// The API to query account nonce (aka transaction index). + pub trait AccountNonceApi where + AccountId: codec::Codec, + Index: codec::Codec, + { + /// Get current account nonce of given `AccountId`. + fn account_nonce(account: AccountId) -> Index; + } +} diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs new file mode 100644 index 0000000000000..9e7678a7ede34 --- /dev/null +++ b/frame/system/src/lib.rs @@ -0,0 +1,1565 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # System Module +//! +//! The System module provides low-level access to core types and cross-cutting utilities. +//! It acts as the base layer for other SRML modules to interact with the Substrate framework components. +//! +//! - [`system::Trait`](./trait.Trait.html) +//! +//! ## Overview +//! +//! The System module defines the core data types used in a Substrate runtime. +//! It also provides several utility functions (see [`Module`](./struct.Module.html)) for other runtime modules. +//! +//! In addition, it manages the storage items for extrinsics data, indexes, event records, and digest items, +//! among other things that support the execution of the current block. +//! +//! It also handles low-level tasks like depositing logs, basic set up and take down of +//! temporary storage entries, and access to previous block hashes. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! The System module does not implement any dispatchable functions. +//! +//! ### Public Functions +//! +//! See the [`Module`](./struct.Module.html) struct for details of publicly available functions. +//! +//! ### Signed Extensions +//! +//! The system module defines the following extensions: +//! +//! - [`CheckWeight`]: Checks the weight and length of the block and ensure that it does not +//! exceed the limits. +//! - [`CheckNonce`]: Checks the nonce of the transaction. Contains a single payload of type +//! `T::Index`. +//! - [`CheckEra`]: Checks the era of the transaction. Contains a single payload of type `Era`. +//! - [`CheckGenesis`]: Checks the provided genesis hash of the transaction. Must be a part of the +//! signed payload of the transaction. +//! - [`CheckVersion`]: Checks that the runtime version is the same as the one encoded in the +//! transaction. +//! +//! Lookup the runtime aggregator file (e.g. `node/runtime`) to see the full list of signed +//! extensions included in a chain. +//! +//! ## Usage +//! +//! ### Prerequisites +//! +//! Import the System module and derive your module's configuration trait from the system trait. +//! +//! ### Example - Get extrinsic count and parent hash for the current block +//! +//! ``` +//! use frame_support::{decl_module, dispatch}; +//! use frame_system::{self as system, ensure_signed}; +//! +//! pub trait Trait: system::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn system_module_example(origin) -> dispatch::DispatchResult { +//! let _sender = ensure_signed(origin)?; +//! let _extrinsic_count = >::extrinsic_count(); +//! let _parent_hash = >::parent_hash(); +//! Ok(()) +//! } +//! } +//! } +//! # fn main() { } +//! ``` + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +use serde::Serialize; +use sp_std::prelude::*; +#[cfg(any(feature = "std", test))] +use sp_std::map; +use sp_std::marker::PhantomData; +use sp_std::fmt::Debug; +use sp_version::RuntimeVersion; +use sp_runtime::{ + RuntimeDebug, + generic::{self, Era}, Perbill, DispatchOutcome, DispatchError, + transaction_validity::{ + ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError, + InvalidTransaction, TransactionValidity, + }, + traits::{ + self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Lookup, LookupError, + SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, BadOrigin, SaturatedConversion, + MaybeSerialize, MaybeSerializeDeserialize, StaticLookup, One, Bounded, + }, +}; + +use sp_core::storage::well_known_keys; +use frame_support::{ + decl_module, decl_event, decl_storage, decl_error, storage, Parameter, + traits::{Contains, Get, ModuleToIndex, OnReapAccount}, + weights::{Weight, DispatchInfo, DispatchClass, SimpleDispatchInfo}, +}; +use codec::{Encode, Decode}; + +#[cfg(any(feature = "std", test))] +use sp_io::TestExternalities; + +#[cfg(any(feature = "std", test))] +use sp_core::ChangesTrieConfiguration; + +pub mod offchain; + +/// Handler for when a new account has been created. +#[impl_trait_for_tuples::impl_for_tuples(30)] +pub trait OnNewAccount { + /// A new account `who` has been registered. + fn on_new_account(who: &AccountId); +} + +/// Determiner 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 trie root of a list of extrinsics. +pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { + extrinsics_data_root::(extrinsics.iter().map(codec::Encode::encode).collect()) +} + +/// Compute the trie root of a list of extrinsics. +pub fn extrinsics_data_root(xts: Vec>) -> H::Output { + H::ordered_trie_root(xts) +} + +pub trait Trait: 'static + Eq + Clone { + /// The aggregated `Origin` type used by dispatchable calls. + type Origin: + Into, Self::Origin>> + + From> + + Clone; + + /// The aggregated `Call` type. + type Call: Debug; + + /// Account index (aka nonce) type. This stores the number of previous transactions associated + /// with a sender account. + type Index: + Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + SimpleArithmetic + + Copy; + + /// The block number type used by the runtime. + type BlockNumber: + Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleArithmetic + + Default + Bounded + Copy + sp_std::hash::Hash + sp_std::str::FromStr; + + /// The output of the `Hashing` function. + type Hash: + Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleBitOps + Ord + + Default + Copy + CheckEqual + sp_std::hash::Hash + AsRef<[u8]> + AsMut<[u8]>; + + /// The hashing system (algorithm) being used in the runtime (e.g. Blake2). + type Hashing: Hash; + + /// The user account identifier type for the runtime. + type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + + Default; + + /// Converting trait to take a source type and convert to `AccountId`. + /// + /// Used to define the type and conversion mechanism for referencing accounts in transactions. + /// It's perfectly reasonable for this to be an identity conversion (with the source type being + /// `AccountId`), but other modules (e.g. Indices module) may provide more functional/efficient + /// alternatives. + type Lookup: StaticLookup; + + /// The block header. + type Header: Parameter + traits::Header< + Number = Self::BlockNumber, + Hash = Self::Hash, + >; + + /// The aggregated event type of the runtime. + type Event: Parameter + Member + From + Debug; + + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount: Get; + + /// The maximum weight of a block. + type MaximumBlockWeight: Get; + + /// The maximum length of a block (in bytes). + type MaximumBlockLength: Get; + + /// The portion of the block that is available to normal transaction. The rest can only be used + /// by operational transactions. This can be applied to any resource limit managed by the system + /// module, including weight and length. + type AvailableBlockRatio: Get; + + /// Get the chain's current version. + type Version: Get; + + /// Convert a module to its index in the runtime. + /// + /// Expects the `ModuleToIndex` type that is being generated by `construct_runtime!` in the + /// runtime. For tests it is okay to use `()` as type (returns `0` for each input). + type ModuleToIndex: ModuleToIndex; +} + +pub type DigestOf = generic::Digest<::Hash>; +pub type DigestItemOf = generic::DigestItem<::Hash>; + +pub type Key = Vec; +pub type KeyValue = (Vec, Vec); + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + /// A big dispatch that will disallow any other transaction to be included. + // TODO: this must be preferable available for testing really (not possible at the moment). + #[weight = SimpleDispatchInfo::MaxOperational] + fn fill_block(origin) { + ensure_root(origin)?; + } + + /// Make some on-chain remark. + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn remark(origin, _remark: Vec) { + ensure_signed(origin)?; + } + + /// Set the number of pages in the WebAssembly environment's heap. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn set_heap_pages(origin, pages: u64) { + ensure_root(origin)?; + storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode()); + } + + /// Set the new code. + #[weight = SimpleDispatchInfo::FixedOperational(200_000)] + pub fn set_code(origin, new: Vec) { + ensure_root(origin)?; + storage::unhashed::put_raw(well_known_keys::CODE, &new); + } + + /// Set some items of storage. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn set_storage(origin, items: Vec) { + ensure_root(origin)?; + for i in &items { + storage::unhashed::put_raw(&i.0, &i.1); + } + } + + /// Kill some items from storage. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn kill_storage(origin, keys: Vec) { + ensure_root(origin)?; + for key in &keys { + storage::unhashed::kill(&key); + } + } + + /// Kill all storage items with a key that starts with the given prefix. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn kill_prefix(origin, prefix: Key) { + ensure_root(origin)?; + storage::unhashed::kill_prefix(&prefix); + } + } +} + +/// A phase of a block's execution. +#[derive(Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))] +pub enum Phase { + /// Applying an extrinsic. + ApplyExtrinsic(u32), + /// The end. + Finalization, +} + +/// Record of an event happening. +#[derive(Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))] +pub struct EventRecord { + /// The phase of the block it happened in. + pub phase: Phase, + /// The event itself. + pub event: E, + /// The list of the topics this event has. + pub topics: Vec, +} + +decl_event!( + /// Event for the System module. + pub enum Event { + /// An extrinsic completed successfully. + ExtrinsicSuccess(DispatchInfo), + /// An extrinsic failed. + ExtrinsicFailed(DispatchError, DispatchInfo), + } +); + +decl_error! { + /// Error for the System module + pub enum Error for Module {} +} + +/// Origin for the System module. +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +pub enum RawOrigin { + /// The system itself ordained this dispatch to happen: this is the highest privilege level. + Root, + /// It is signed by some public key and we provide the `AccountId`. + Signed(AccountId), + /// It is signed by nobody, can be either: + /// * included and agreed upon by the validators anyway, + /// * or unsigned transaction validated by a module. + None, +} + +impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::None, + } + } +} + +/// Exposed trait-generic origin type. +pub type Origin = RawOrigin<::AccountId>; + +// 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 +} + +/// This type alias represents an index of an event. +/// +/// We use `u32` here because this index is used as index for `Events` +/// which can't contain more than `u32::max_value()` items. +type EventIndex = u32; + +decl_storage! { + trait Store for Module as System { + /// Extrinsics nonce for accounts. + pub AccountNonce get(fn account_nonce): map T::AccountId => T::Index; + /// Total extrinsics count for the current block. + ExtrinsicCount: Option; + /// Total weight for all extrinsics put together, for the current block. + AllExtrinsicsWeight: Option; + /// Total length (in bytes) for all extrinsics put together, for the current block. + AllExtrinsicsLen: Option; + /// Map of block numbers to block hashes. + pub BlockHash get(fn block_hash) build(|_| vec![(T::BlockNumber::zero(), hash69())]): map T::BlockNumber => T::Hash; + /// Extrinsics data for the current block (maps an extrinsic's index to its data). + ExtrinsicData get(fn extrinsic_data): map u32 => Vec; + /// The current block number being processed. Set by `execute_block`. + Number get(fn block_number) build(|_| 1.into()): T::BlockNumber; + /// Hash of the previous block. + ParentHash get(fn parent_hash) build(|_| hash69()): T::Hash; + /// Extrinsics root of the current block, also part of the block header. + ExtrinsicsRoot get(fn extrinsics_root): T::Hash; + /// Digest of the current block, also part of the block header. + Digest get(fn digest): DigestOf; + /// Events deposited for the current block. + Events get(fn events): Vec>; + /// The number of events in the `Events` list. + EventCount get(fn event_count): EventIndex; + + // TODO: https://github.com/paritytech/substrate/issues/2553 + // Possibly, we can improve it by using something like: + // `Option<(BlockNumber, Vec)>`, however in this case we won't be able to use + // `EventTopics::append`. + + /// Mapping between a topic (represented by T::Hash) and a vector of indexes + /// of events in the `>` list. + /// + /// All topic vectors have deterministic storage locations depending on the topic. This + /// allows light-clients to leverage the changes trie storage tracking mechanism and + /// in case of changes fetch the list of events of interest. + /// + /// The value has the type `(T::BlockNumber, EventIndex)` because if we used only just + /// the `EventIndex` then in case if the topic has the same contents on the next block + /// no notification will be triggered thus the event might be lost. + EventTopics get(fn event_topics): map T::Hash => Vec<(T::BlockNumber, EventIndex)>; + } + add_extra_genesis { + config(changes_trie_config): Option; + #[serde(with = "sp_core::bytes")] + config(code): Vec; + + build(|config: &GenesisConfig| { + use codec::Encode; + + sp_io::storage::set(well_known_keys::CODE, &config.code); + sp_io::storage::set(well_known_keys::EXTRINSIC_INDEX, &0u32.encode()); + + if let Some(ref changes_trie_config) = config.changes_trie_config { + sp_io::storage::set( + well_known_keys::CHANGES_TRIE_CONFIG, + &changes_trie_config.encode(), + ); + } + }); + } +} + +pub struct EnsureRoot(sp_std::marker::PhantomData); +impl< + O: Into, O>> + From>, + AccountId, +> EnsureOrigin for EnsureRoot { + type Success = (); + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + RawOrigin::Root => Ok(()), + r => Err(O::from(r)), + }) + } +} + +pub struct EnsureSigned(sp_std::marker::PhantomData); +impl< + O: Into, O>> + From>, + AccountId, +> EnsureOrigin for EnsureSigned { + type Success = AccountId; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + RawOrigin::Signed(who) => Ok(who), + r => Err(O::from(r)), + }) + } +} + +pub struct EnsureSignedBy(sp_std::marker::PhantomData<(Who, AccountId)>); +impl< + O: Into, O>> + From>, + Who: Contains, + AccountId: PartialEq + Clone + Ord, +> EnsureOrigin for EnsureSignedBy { + type Success = AccountId; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + RawOrigin::Signed(ref who) if Who::contains(who) => Ok(who.clone()), + r => Err(O::from(r)), + }) + } +} + +pub struct EnsureNone(sp_std::marker::PhantomData); +impl< + O: Into, O>> + From>, + AccountId, +> EnsureOrigin for EnsureNone { + type Success = (); + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + RawOrigin::None => Ok(()), + r => Err(O::from(r)), + }) + } +} + +pub struct EnsureNever(sp_std::marker::PhantomData); +impl EnsureOrigin for EnsureNever { + type Success = T; + fn try_origin(o: O) -> Result { + Err(o) + } +} + +/// Ensure that the origin `o` represents a signed extrinsic (i.e. transaction). +/// Returns `Ok` with the account that signed the extrinsic or an `Err` otherwise. +pub fn ensure_signed(o: OuterOrigin) -> Result + where OuterOrigin: Into, OuterOrigin>> +{ + match o.into() { + Ok(RawOrigin::Signed(t)) => Ok(t), + _ => Err(BadOrigin), + } +} + +/// Ensure that the origin `o` represents the root. Returns `Ok` or an `Err` otherwise. +pub fn ensure_root(o: OuterOrigin) -> Result<(), BadOrigin> + where OuterOrigin: Into, OuterOrigin>> +{ + match o.into() { + Ok(RawOrigin::Root) => Ok(()), + _ => Err(BadOrigin), + } +} + +/// Ensure that the origin `o` represents an unsigned extrinsic. Returns `Ok` or an `Err` otherwise. +pub fn ensure_none(o: OuterOrigin) -> Result<(), BadOrigin> + where OuterOrigin: Into, OuterOrigin>> +{ + match o.into() { + Ok(RawOrigin::None) => Ok(()), + _ => Err(BadOrigin), + } +} + +/// A type of block initialization to perform. +pub enum InitKind { + /// Leave inspectable storage entries in state. + /// + /// i.e. `Events` are not being reset. + /// Should only be used for off-chain calls, + /// regular block execution should clear those. + Inspection, + + /// Reset also inspectable storage entries. + /// + /// This should be used for regular block execution. + Full, +} + +impl Default for InitKind { + fn default() -> Self { + InitKind::Full + } +} + +impl Module { + /// Deposits an event into this block's event record. + pub fn deposit_event(event: impl Into) { + Self::deposit_event_indexed(&[], event.into()); + } + + /// Deposits an event into this block's event record adding this event + /// to the corresponding topic indexes. + /// + /// This will update storage entries that correspond to the specified topics. + /// It is expected that light-clients could subscribe to this topics. + pub fn deposit_event_indexed(topics: &[T::Hash], event: T::Event) { + let extrinsic_index = Self::extrinsic_index(); + let phase = extrinsic_index.map_or(Phase::Finalization, |c| Phase::ApplyExtrinsic(c)); + let event = EventRecord { + phase, + event, + topics: topics.iter().cloned().collect::>(), + }; + + // Index of the to be added event. + let event_idx = { + let old_event_count = EventCount::get(); + let new_event_count = match old_event_count.checked_add(1) { + // We've reached the maximum number of events at this block, just + // don't do anything and leave the event_count unaltered. + None => return, + Some(nc) => nc, + }; + EventCount::put(new_event_count); + old_event_count + }; + + // Appending can only fail if `Events` can not be decoded or + // when we try to insert more than `u32::max_value()` events. + // + // We perform early return if we've reached the maximum capacity of the event list, + // so `Events` seems to be corrupted. Also, this has happened after the start of execution + // (since the event list is cleared at the block initialization). + if >::append([event].iter()).is_err() { + // The most sensible thing to do here is to just ignore this event and wait until the + // new block. + return; + } + + let block_no = Self::block_number(); + for topic in topics { + // The same applies here. + if >::append(topic, &[(block_no, event_idx)]).is_err() { + return; + } + } + } + + /// Gets the index of extrinsic that is currently executing. + pub fn extrinsic_index() -> Option { + storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX) + } + + /// Gets extrinsics count. + pub fn extrinsic_count() -> u32 { + ExtrinsicCount::get().unwrap_or_default() + } + + /// Gets a total weight of all executed extrinsics. + pub fn all_extrinsics_weight() -> Weight { + AllExtrinsicsWeight::get().unwrap_or_default() + } + + pub fn all_extrinsics_len() -> u32 { + AllExtrinsicsLen::get().unwrap_or_default() + } + + /// Inform the system module of some additional weight that should be accounted for, in the + /// current block. + /// + /// NOTE: use with extra care; this function is made public only be used for certain modules + /// that need it. A runtime that does not have dynamic calls should never need this and should + /// stick to static weights. A typical use case for this is inner calls or smart contract calls. + /// Furthermore, it only makes sense to use this when it is presumably _cheap_ to provide the + /// argument `weight`; In other words, if this function is to be used to account for some + /// unknown, user provided call's weight, it would only make sense to use it if you are sure you + /// can rapidly compute the weight of the inner call. + /// + /// Even more dangerous is to note that this function does NOT take any action, if the new sum + /// of block weight is more than the block weight limit. This is what the _unchecked_. + /// + /// Another potential use-case could be for the `on_initialise` and `on_finalize` hooks. + /// + /// If no previous weight exists, the function initializes the weight to zero. + pub fn register_extra_weight_unchecked(weight: Weight) { + let current_weight = AllExtrinsicsWeight::get().unwrap_or_default(); + let next_weight = current_weight.saturating_add(weight).min(T::MaximumBlockWeight::get()); + AllExtrinsicsWeight::put(next_weight); + } + + /// Start the execution of a particular block. + pub fn initialize( + number: &T::BlockNumber, + parent_hash: &T::Hash, + txs_root: &T::Hash, + digest: &DigestOf, + kind: InitKind, + ) { + // populate environment + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); + >::put(number); + >::put(digest); + >::put(parent_hash); + >::insert(*number - One::one(), parent_hash); + >::put(txs_root); + + if let InitKind::Full = kind { + >::kill(); + EventCount::kill(); + >::remove_all(); + } + } + + /// Remove temporary "environment" entries in storage. + pub fn finalize() -> T::Header { + ExtrinsicCount::kill(); + AllExtrinsicsWeight::kill(); + AllExtrinsicsLen::kill(); + + let number = >::take(); + let parent_hash = >::take(); + let mut digest = >::take(); + let extrinsics_root = >::take(); + + // move block hash pruning window by one block + let block_hash_count = ::get(); + if number > block_hash_count { + let to_remove = number - block_hash_count - One::one(); + + // keep genesis hash + if to_remove != Zero::zero() { + >::remove(to_remove); + } + } + + let storage_root = T::Hash::decode(&mut &sp_io::storage::root()[..]) + .expect("Node is configured to use the same hash; qed"); + let storage_changes_root = sp_io::storage::changes_root(&parent_hash.encode()); + + // we can't compute changes trie root earlier && put it to the Digest + // because it will include all currently existing temporaries. + if let Some(storage_changes_root) = storage_changes_root { + let item = generic::DigestItem::ChangesTrieRoot( + T::Hash::decode(&mut &storage_changes_root[..]) + .expect("Node is configured to use the same hash; qed") + ); + digest.push(item); + } + + // The following fields + // + // - > + // - > + // - > + // + // stay to be inspected by the client and will be cleared by `Self::initialize`. + + ::new(number, extrinsics_root, storage_root, parent_hash, digest) + } + + /// Deposits a log and ensures it matches the block's log data. + pub fn deposit_log(item: DigestItemOf) { + let mut l = >::get(); + l.push(item); + >::put(l); + } + + /// Get the basic externalities for this module, useful for tests. + #[cfg(any(feature = "std", test))] + pub fn externalities() -> TestExternalities { + TestExternalities::new(sp_core::storage::Storage { + top: map![ + >::hashed_key_for(T::BlockNumber::zero()) => [69u8; 32].encode(), + >::hashed_key().to_vec() => T::BlockNumber::one().encode(), + >::hashed_key().to_vec() => [69u8; 32].encode() + ], + children: map![], + }) + } + + /// Set the block number to something in particular. Can be used as an alternative to + /// `initialize` for tests that don't need to bother with the other environment entries. + #[cfg(any(feature = "std", test))] + pub fn set_block_number(n: T::BlockNumber) { + >::put(n); + } + + /// Sets the index of extrinsic that is currently executing. + #[cfg(any(feature = "std", test))] + pub fn set_extrinsic_index(extrinsic_index: u32) { + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &extrinsic_index) + } + + /// Set the parent hash number to something in particular. Can be used as an alternative to + /// `initialize` for tests that don't need to bother with the other environment entries. + #[cfg(any(feature = "std", test))] + pub fn set_parent_hash(n: T::Hash) { + >::put(n); + } + + /// Set the current block weight. This should only be used in some integration tests. + #[cfg(any(feature = "std", test))] + pub fn set_block_limits(weight: Weight, len: usize) { + AllExtrinsicsWeight::put(weight); + AllExtrinsicsLen::put(len as u32); + } + + /// Return the chain's current runtime version. + pub fn runtime_version() -> RuntimeVersion { T::Version::get() } + + /// Increment a particular account's nonce by 1. + pub fn inc_account_nonce(who: &T::AccountId) { + >::insert(who, Self::account_nonce(who) + T::Index::one()); + } + + /// 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) { + ExtrinsicData::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: &DispatchOutcome, _encoded_len: u32, info: DispatchInfo) { + Self::deposit_event( + match r { + Ok(()) => Event::ExtrinsicSuccess(info), + Err(err) => Event::ExtrinsicFailed(err.clone(), info), + } + ); + + let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32; + + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &next_extrinsic_index); + } + + /// To be called immediately after `note_applied_extrinsic` of the last extrinsic of the block + /// has been called. + pub fn note_finished_extrinsics() { + let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX) + .unwrap_or_default(); + ExtrinsicCount::put(extrinsic_index); + } + + /// Remove all extrinsic data and save the extrinsics trie root. + pub fn derive_extrinsics() { + let extrinsics = (0..ExtrinsicCount::get().unwrap_or_default()) + .map(ExtrinsicData::take).collect(); + let xts_root = extrinsics_data_root::(extrinsics); + >::put(xts_root); + } +} + +impl OnReapAccount for Module { + /// Remove the nonce for the account. Account is considered fully removed from the system. + fn on_reap_account(who: &T::AccountId) { + >::remove(who); + } +} + +/// resource limit check. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckWeight(PhantomData); + +impl CheckWeight { + /// Get the quota ratio of each dispatch class type. This indicates that all operational + /// dispatches can use the full capacity of any resource, while user-triggered ones can consume + /// a portion. + fn get_dispatch_limit_ratio(class: DispatchClass) -> Perbill { + match class { + DispatchClass::Operational => Perbill::one(), + DispatchClass::Normal => T::AvailableBlockRatio::get(), + } + } + + /// Checks if the current extrinsic can fit into the block with respect to block weight limits. + /// + /// Upon successes, it returns the new block weight as a `Result`. + fn check_weight( + info: ::DispatchInfo, + ) -> Result { + let current_weight = Module::::all_extrinsics_weight(); + let maximum_weight = T::MaximumBlockWeight::get(); + let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_weight; + let added_weight = info.weight.min(limit); + let next_weight = current_weight.saturating_add(added_weight); + if next_weight > limit { + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(next_weight) + } + } + + /// Checks if the current extrinsic can fit into the block with respect to block length limits. + /// + /// Upon successes, it returns the new block length as a `Result`. + fn check_block_length( + info: ::DispatchInfo, + len: usize, + ) -> Result { + let current_len = Module::::all_extrinsics_len(); + let maximum_len = T::MaximumBlockLength::get(); + let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_len; + let added_len = len as u32; + let next_len = current_len.saturating_add(added_len); + if next_len > limit { + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(next_len) + } + } + + /// get the priority of an extrinsic denoted by `info`. + fn get_priority(info: ::DispatchInfo) -> TransactionPriority { + match info.class { + DispatchClass::Normal => info.weight.into(), + DispatchClass::Operational => Bounded::max_value() + } + } + + /// Creates new `SignedExtension` to check weight of the extrinsic. + pub fn new() -> Self { + Self(PhantomData) + } +} + +impl SignedExtension for CheckWeight { + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = (); + type DispatchInfo = DispatchInfo; + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + info: Self::DispatchInfo, + len: usize, + ) -> Result<(), TransactionValidityError> { + let next_len = Self::check_block_length(info, len)?; + AllExtrinsicsLen::put(next_len); + let next_weight = Self::check_weight(info)?; + AllExtrinsicsWeight::put(next_weight); + Ok(()) + } + + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + info: Self::DispatchInfo, + len: usize, + ) -> TransactionValidity { + // There is no point in writing to storage here since changes are discarded. This basically + // discards any transaction which is bigger than the length or weight limit **alone**, which + // is a guarantee that it will fail in the pre-dispatch phase. + if let Err(e) = Self::check_block_length(info, len) { + return Err(e); + } + + if let Err(e) = Self::check_weight(info) { + return Err(e); + } + + Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) + } +} + +impl Debug for CheckWeight { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckWeight") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +/// Nonce check and increment to give replay protection for transactions. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckNonce(#[codec(compact)] T::Index); + +impl CheckNonce { + /// utility constructor. Used only in client/factory code. + pub fn from(nonce: T::Index) -> Self { + Self(nonce) + } +} + +impl Debug for CheckNonce { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + self.0.fmt(f) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for CheckNonce { + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = (); + type DispatchInfo = DispatchInfo; + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn pre_dispatch( + self, + who: &Self::AccountId, + _call: &Self::Call, + _info: Self::DispatchInfo, + _len: usize, + ) -> Result<(), TransactionValidityError> { + let expected = >::get(who); + if self.0 != expected { + return Err( + if self.0 < expected { + InvalidTransaction::Stale + } else { + InvalidTransaction::Future + }.into() + ) + } + + >::insert(who, expected + T::Index::one()); + Ok(()) + } + + fn validate( + &self, + who: &Self::AccountId, + _call: &Self::Call, + info: Self::DispatchInfo, + _len: usize, + ) -> TransactionValidity { + // check index + let expected = >::get(who); + if self.0 < expected { + return InvalidTransaction::Stale.into() + } + + let provides = vec![Encode::encode(&(who, self.0))]; + let requires = if expected < self.0 { + vec![Encode::encode(&(who, self.0 - One::one()))] + } else { + vec![] + }; + + Ok(ValidTransaction { + priority: info.weight as TransactionPriority, + requires, + provides, + longevity: TransactionLongevity::max_value(), + propagate: true, + }) + } +} + +/// Check for transaction mortality. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckEra((Era, sp_std::marker::PhantomData)); + +impl CheckEra { + /// utility constructor. Used only in client/factory code. + pub fn from(era: Era) -> Self { + Self((era, sp_std::marker::PhantomData)) + } +} + +impl Debug for CheckEra { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + self.0.fmt(f) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for CheckEra { + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = T::Hash; + type DispatchInfo = DispatchInfo; + type Pre = (); + + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: Self::DispatchInfo, + _len: usize, + ) -> TransactionValidity { + let current_u64 = >::block_number().saturated_into::(); + let valid_till = (self.0).0.death(current_u64); + Ok(ValidTransaction { + longevity: valid_till.saturating_sub(current_u64), + ..Default::default() + }) + } + + fn additional_signed(&self) -> Result { + let current_u64 = >::block_number().saturated_into::(); + let n = (self.0).0.birth(current_u64).saturated_into::(); + if !>::exists(n) { + Err(InvalidTransaction::AncientBirthBlock.into()) + } else { + Ok(>::block_hash(n)) + } + } +} + +/// Nonce check and increment to give replay protection for transactions. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckGenesis(sp_std::marker::PhantomData); + +impl Debug for CheckGenesis { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckGenesis") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl CheckGenesis { + /// Creates new `SignedExtension` to check genesis hash. + pub fn new() -> Self { + Self(sp_std::marker::PhantomData) + } +} + +impl SignedExtension for CheckGenesis { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = T::Hash; + type DispatchInfo = DispatchInfo; + type Pre = (); + + fn additional_signed(&self) -> Result { + Ok(>::block_hash(T::BlockNumber::zero())) + } +} + +/// Ensure the runtime version registered in the transaction is the same as at present. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckVersion(sp_std::marker::PhantomData); + +impl Debug for CheckVersion { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "CheckVersion") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +impl CheckVersion { + /// Create new `SignedExtension` to check runtime version. + pub fn new() -> Self { + Self(sp_std::marker::PhantomData) + } +} + +impl SignedExtension for CheckVersion { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = u32; + type DispatchInfo = DispatchInfo; + type Pre = (); + + fn additional_signed(&self) -> Result { + Ok(>::runtime_version().spec_version) + } +} + +pub struct ChainContext(sp_std::marker::PhantomData); +impl Default for ChainContext { + fn default() -> Self { + ChainContext(sp_std::marker::PhantomData) + } +} + +impl Lookup for ChainContext { + type Source = ::Source; + type Target = ::Target; + + fn lookup(&self, s: Self::Source) -> Result { + ::lookup(s) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::H256; + use sp_runtime::{traits::{BlakeTwo256, IdentityLookup}, testing::Header, DispatchError}; + use frame_support::{impl_outer_origin, parameter_types}; + + impl_outer_origin! { + pub enum Origin for Test where system = super {} + } + + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + + parameter_types! { + pub const BlockHashCount: u64 = 10; + pub const MaximumBlockWeight: Weight = 1024; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + pub const MaximumBlockLength: u32 = 1024; + } + + impl Trait for Test { + type Origin = Origin; + type Call = (); + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = u16; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + + impl From for u16 { + fn from(e: Event) -> u16 { + match e { + Event::ExtrinsicSuccess(..) => 100, + Event::ExtrinsicFailed(..) => 101, + } + } + } + + type System = Module; + + const CALL: &::Call = &(); + + fn new_test_ext() -> sp_io::TestExternalities { + GenesisConfig::default().build_storage::().unwrap().into() + } + + fn normal_weight_limit() -> Weight { + ::AvailableBlockRatio::get() * ::MaximumBlockWeight::get() + } + + fn normal_length_limit() -> u32 { + ::AvailableBlockRatio::get() * ::MaximumBlockLength::get() + } + + #[test] + fn origin_works() { + let o = Origin::from(RawOrigin::::Signed(1u64)); + let x: Result, Origin> = o.into(); + assert_eq!(x, Ok(RawOrigin::::Signed(1u64))); + } + + #[test] + fn deposit_event_should_work() { + new_test_ext().execute_with(|| { + System::initialize( + &1, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + System::note_finished_extrinsics(); + System::deposit_event(1u16); + System::finalize(); + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Finalization, + event: 1u16, + topics: vec![], + } + ] + ); + + System::initialize( + &2, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + System::deposit_event(42u16); + System::note_applied_extrinsic(&Ok(()), 0, Default::default()); + System::note_applied_extrinsic(&Err(DispatchError::BadOrigin), 0, Default::default()); + System::note_finished_extrinsics(); + System::deposit_event(3u16); + System::finalize(); + assert_eq!( + System::events(), + vec![ + EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, + EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, + EventRecord { phase: Phase::ApplyExtrinsic(1), event: 101u16, topics: vec![] }, + EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } + ] + ); + }); + } + + #[test] + fn deposit_event_topics() { + new_test_ext().execute_with(|| { + const BLOCK_NUMBER: u64 = 1; + + System::initialize( + &BLOCK_NUMBER, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + System::note_finished_extrinsics(); + + let topics = vec![ + H256::repeat_byte(1), + H256::repeat_byte(2), + H256::repeat_byte(3), + ]; + + // We deposit a few events with different sets of topics. + System::deposit_event_indexed(&topics[0..3], 1u16); + System::deposit_event_indexed(&topics[0..1], 2u16); + System::deposit_event_indexed(&topics[1..2], 3u16); + + System::finalize(); + + // Check that topics are reflected in the event record. + assert_eq!( + System::events(), + vec![ + EventRecord { + phase: Phase::Finalization, + event: 1u16, + topics: topics[0..3].to_vec(), + }, + EventRecord { + phase: Phase::Finalization, + event: 2u16, + topics: topics[0..1].to_vec(), + }, + EventRecord { + phase: Phase::Finalization, + event: 3u16, + topics: topics[1..2].to_vec(), + } + ] + ); + + // Check that the topic-events mapping reflects the deposited topics. + // Note that these are indexes of the events. + assert_eq!( + System::event_topics(&topics[0]), + vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 1)], + ); + assert_eq!( + System::event_topics(&topics[1]), + vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 2)], + ); + assert_eq!( + System::event_topics(&topics[2]), + vec![(BLOCK_NUMBER, 0)], + ); + }); + } + + #[test] + fn prunes_block_hash_mappings() { + new_test_ext().execute_with(|| { + // simulate import of 15 blocks + for n in 1..=15 { + System::initialize( + &n, + &[n as u8 - 1; 32].into(), + &[0u8; 32].into(), + &Default::default(), + InitKind::Full, + ); + + System::finalize(); + } + + // first 5 block hashes are pruned + for n in 0..5 { + assert_eq!( + System::block_hash(n), + H256::zero(), + ); + } + + // the remaining 10 are kept + for n in 5..15 { + assert_eq!( + System::block_hash(n), + [n as u8; 32].into(), + ); + } + }) + } + + #[test] + fn signed_ext_check_nonce_works() { + new_test_ext().execute_with(|| { + >::insert(1, 1); + let info = DispatchInfo::default(); + let len = 0_usize; + // stale + assert!(CheckNonce::(0).validate(&1, CALL, info, len).is_err()); + assert!(CheckNonce::(0).pre_dispatch(&1, CALL, info, len).is_err()); + // correct + assert!(CheckNonce::(1).validate(&1, CALL, info, len).is_ok()); + assert!(CheckNonce::(1).pre_dispatch(&1, CALL, info, len).is_ok()); + // future + assert!(CheckNonce::(5).validate(&1, CALL, info, len).is_ok()); + assert!(CheckNonce::(5).pre_dispatch(&1, CALL, info, len).is_err()); + }) + } + + #[test] + fn signed_ext_check_weight_works_normal_tx() { + new_test_ext().execute_with(|| { + let normal_limit = normal_weight_limit(); + let small = DispatchInfo { weight: 100, ..Default::default() }; + let medium = DispatchInfo { + weight: normal_limit - 1, + ..Default::default() + }; + let big = DispatchInfo { + weight: normal_limit + 1, + ..Default::default() + }; + let len = 0_usize; + + let reset_check_weight = |i, f, s| { + AllExtrinsicsWeight::put(s); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, i, len); + if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } + }; + + reset_check_weight(small, false, 0); + reset_check_weight(medium, false, 0); + reset_check_weight(big, true, 1); + }) + } + + #[test] + fn signed_ext_check_weight_fee_works() { + new_test_ext().execute_with(|| { + let free = DispatchInfo { weight: 0, ..Default::default() }; + let len = 0_usize; + + assert_eq!(System::all_extrinsics_weight(), 0); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, free, len); + assert!(r.is_ok()); + assert_eq!(System::all_extrinsics_weight(), 0); + }) + } + + #[test] + fn signed_ext_check_weight_max_works() { + new_test_ext().execute_with(|| { + let max = DispatchInfo { weight: Weight::max_value(), ..Default::default() }; + let len = 0_usize; + let normal_limit = normal_weight_limit(); + + assert_eq!(System::all_extrinsics_weight(), 0); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, max, len); + assert!(r.is_ok()); + assert_eq!(System::all_extrinsics_weight(), normal_limit); + }) + } + + #[test] + fn signed_ext_check_weight_works_operational_tx() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo { weight: 100, ..Default::default() }; + let op = DispatchInfo { weight: 100, class: DispatchClass::Operational, pays_fee: true }; + let len = 0_usize; + let normal_limit = normal_weight_limit(); + + // given almost full block + AllExtrinsicsWeight::put(normal_limit); + // will not fit. + assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, normal, len).is_err()); + // will fit. + assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, op, len).is_ok()); + + // likewise for length limit. + let len = 100_usize; + AllExtrinsicsLen::put(normal_length_limit()); + assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, normal, len).is_err()); + assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, op, len).is_ok()); + }) + } + + #[test] + fn signed_ext_check_weight_priority_works() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: true }; + let op = DispatchInfo { weight: 100, class: DispatchClass::Operational, pays_fee: true }; + let len = 0_usize; + + let priority = CheckWeight::(PhantomData) + .validate(&1, CALL, normal, len) + .unwrap() + .priority; + assert_eq!(priority, 100); + + let priority = CheckWeight::(PhantomData) + .validate(&1, CALL, op, len) + .unwrap() + .priority; + assert_eq!(priority, Bounded::max_value()); + }) + } + + #[test] + fn signed_ext_check_weight_block_size_works() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo::default(); + let normal_limit = normal_weight_limit() as usize; + let reset_check_weight = |tx, s, f| { + AllExtrinsicsLen::put(0); + let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, tx, s); + if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } + }; + + reset_check_weight(normal, normal_limit - 1, false); + reset_check_weight(normal, normal_limit, false); + reset_check_weight(normal, normal_limit + 1, true); + + // Operational ones don't have this limit. + let op = DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: true }; + reset_check_weight(op, normal_limit, false); + reset_check_weight(op, normal_limit + 100, false); + reset_check_weight(op, 1024, false); + reset_check_weight(op, 1025, true); + }) + } + + #[test] + fn signed_ext_check_era_should_work() { + new_test_ext().execute_with(|| { + // future + assert_eq!( + CheckEra::::from(Era::mortal(4, 2)).additional_signed().err().unwrap(), + InvalidTransaction::AncientBirthBlock.into(), + ); + + // correct + System::set_block_number(13); + >::insert(12, H256::repeat_byte(1)); + assert!(CheckEra::::from(Era::mortal(4, 12)).additional_signed().is_ok()); + }) + } + + #[test] + fn signed_ext_check_era_should_change_longevity() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal, pays_fee: true }; + let len = 0_usize; + let ext = ( + CheckWeight::(PhantomData), + CheckEra::::from(Era::mortal(16, 256)), + ); + System::set_block_number(17); + >::insert(16, H256::repeat_byte(1)); + + assert_eq!(ext.validate(&1, CALL, normal, len).unwrap().longevity, 15); + }) + } +} diff --git a/frame/system/src/offchain.rs b/frame/system/src/offchain.rs new file mode 100644 index 0000000000000..f5fda34585d4d --- /dev/null +++ b/frame/system/src/offchain.rs @@ -0,0 +1,364 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Module helpers for off-chain calls. + +use codec::Encode; +use sp_std::convert::TryInto; +use sp_std::prelude::Vec; +use sp_runtime::app_crypto::{RuntimeAppPublic, AppPublic, AppSignature}; +use sp_runtime::traits::{Extrinsic as ExtrinsicT, IdentifyAccount}; +use frame_support::debug; + +/// Creates runtime-specific signed transaction. +/// +/// This trait should be implemented by your `Runtime` to be able +/// to submit `SignedTransaction`s` to the pool from off-chain code. +pub trait CreateTransaction { + /// A `Public` key representing a particular `AccountId`. + type Public: IdentifyAccount + Clone; + /// A `Signature` generated by the `Signer`. + type Signature; + + /// Attempt to create signed extrinsic data that encodes call from given account. + /// + /// Runtime implementation is free to construct the payload to sign and the signature + /// in any way it wants. + /// Returns `None` if signed extrinsic could not be created (either because signing failed + /// or because of any other runtime-specific reason). + fn create_transaction>( + call: Extrinsic::Call, + public: Self::Public, + account: T::AccountId, + nonce: T::Index, + ) -> Option<(Extrinsic::Call, Extrinsic::SignaturePayload)>; +} + +/// A trait responsible for signing a payload using given account. +/// +/// This trait is usually going to represent a local public key +/// that has ability to sign arbitrary `Payloads`. +/// +/// NOTE: Most likely you don't need to implement this trait manually. +/// It has a blanket implementation for all `RuntimeAppPublic` types, +/// so it's enough to pass an application-specific crypto type. +/// +/// To easily create `SignedTransaction`s have a look at the +/// [`TransactionSubmitter`] type. +pub trait Signer { + /// Sign any encodable payload with given account and produce a signature. + /// + /// Returns `Some` if signing succeeded and `None` in case the `account` couldn't + /// be used (for instance we couldn't convert it to required application specific crypto). + fn sign(public: Public, payload: &Payload) -> Option; +} + +/// A `Signer` implementation for any `AppPublic` type. +/// +/// This implementation additionaly supports conversion to/from multi-signature/multi-signer +/// wrappers. +/// If the wrapped crypto doesn't match `AppPublic`s crypto `None` is returned. +impl Signer for TAnyAppPublic where + TAnyAppPublic: RuntimeAppPublic + + AppPublic + + From<::Generic>, + ::Signature: AppSignature, + Signature: From< + <::Signature as AppSignature>::Generic + >, + Public: TryInto<::Generic> +{ + fn sign(public: Public, raw_payload: &Payload) -> Option { + raw_payload.using_encoded(|payload| { + let public = public.try_into().ok()?; + TAnyAppPublic::from(public).sign(&payload) + .map( + <::Signature as AppSignature> + ::Generic::from + ) + .map(Signature::from) + }) + } +} + +/// Retrieves a public key type for given `SignAndSubmitTransaction`. +pub type PublicOf = < + >::CreateTransaction + as + CreateTransaction>::Extrinsic> +>::Public; + +/// A trait to sign and submit transactions in off-chain calls. +/// +/// NOTE: Most likely you should not implement this trait yourself. +/// There is an implementation for +/// [`TransactionSubmitter`] type, which +/// you should use. +pub trait SignAndSubmitTransaction { + /// Unchecked extrinsic type. + type Extrinsic: ExtrinsicT + codec::Encode; + + /// A runtime-specific type to produce signed data for the extrinsic. + type CreateTransaction: CreateTransaction; + + /// A type used to sign transactions created using `CreateTransaction`. + type Signer: Signer< + PublicOf, + >::Signature, + >; + + /// Sign given call and submit it to the transaction pool. + /// + /// Returns `Ok` if the transaction was submitted correctly + /// and `Err` if the key for given `id` was not found or the + /// transaction was rejected from the pool. + fn sign_and_submit(call: impl Into, public: PublicOf) -> Result<(), ()> { + let call = call.into(); + let id = public.clone().into_account(); + let expected = >::account_nonce(&id); + debug::native::debug!( + target: "offchain", + "Creating signed transaction from account: {:?} (nonce: {:?})", + id, + expected, + ); + let (call, signature_data) = Self::CreateTransaction + ::create_transaction::(call, public, id.clone(), expected) + .ok_or(())?; + // increment the nonce. This is fine, since the code should always + // be running in off-chain context, so we NEVER persists data. + >::inc_account_nonce(&id); + + let xt = Self::Extrinsic::new(call, Some(signature_data)).ok_or(())?; + sp_io::offchain::submit_transaction(xt.encode()) + } +} + +/// A trait to submit unsigned transactions in off-chain calls. +/// +/// NOTE: Most likely you should not implement this trait yourself. +/// There is an implementation for +/// [`TransactionSubmitter`] type, which +/// you should use. +pub trait SubmitUnsignedTransaction { + /// Unchecked extrinsic type. + type Extrinsic: ExtrinsicT + codec::Encode; + + /// Submit given call to the transaction pool as unsigned transaction. + /// + /// Returns `Ok` if the transaction was submitted correctly + /// and `Err` if transaction was rejected from the pool. + fn submit_unsigned(call: impl Into) -> Result<(), ()> { + let xt = Self::Extrinsic::new(call.into(), None).ok_or(())?; + sp_io::offchain::submit_transaction(xt.encode()) + } +} + +/// A utility trait to easily create signed transactions +/// from accounts in node's local keystore. +/// +/// NOTE: Most likely you should not implement this trait yourself. +/// There is an implementation for +/// [`TransactionSubmitter`] type, which +/// you should use. +pub trait SubmitSignedTransaction { + /// A `SignAndSubmitTransaction` implementation. + type SignAndSubmit: SignAndSubmitTransaction; + + /// Find local keys that match given list of accounts. + /// + /// Technically it finds an intersection between given list of `AccountId`s + /// and accounts that are represented by public keys in local keystore. + /// If `None` is passed it returns all accounts in the keystore. + /// + /// Returns both public keys and `AccountId`s of accounts that are available. + /// Such accounts can later be used to sign a payload or send signed transactions. + fn find_local_keys(accounts: Option>) -> Vec<( + T::AccountId, + PublicOf, + )>; + + /// Find all available local keys. + /// + /// This is equivalent of calling `find_local_keys(None)`. + fn find_all_local_keys() -> Vec<(T::AccountId, PublicOf)> { + Self::find_local_keys(None as Option>) + } + + /// Check if there are keys for any of given accounts that could be used to send a transaction. + /// + /// This check can be used as an early-exit condition to avoid doing too + /// much work, before we actually realise that there are no accounts that you + /// we could use for signing. + fn can_sign_with(accounts: Option>) -> bool { + !Self::find_local_keys(accounts).is_empty() + } + + /// Check if there are any keys that could be used for signing. + /// + /// This is equivalent of calling `can_sign_with(None)`. + fn can_sign() -> bool { + Self::can_sign_with(None as Option>) + } + + /// Create and submit signed transactions from supported accounts. + /// + /// This method should intersect given list of accounts with the ones + /// supported locally and submit signed transaction containing given `Call` + /// with every of them. + /// + /// Returns a vector of results and account ids that were supported. + #[must_use] + fn submit_signed_from( + call: impl Into + Clone, + accounts: impl IntoIterator, + ) -> Vec<(T::AccountId, Result<(), ()>)> { + let keys = Self::find_local_keys(Some(accounts)); + keys.into_iter().map(|(account, pub_key)| { + let call = call.clone().into(); + ( + account, + Self::SignAndSubmit::sign_and_submit(call, pub_key) + ) + }).collect() + } + + /// Create and submit signed transactions from all local accounts. + /// + /// This method submits a signed transaction from all local accounts + /// for given application crypto. + /// + /// Returns a vector of results and account ids that were supported. + #[must_use] + fn submit_signed( + call: impl Into + Clone, + ) -> Vec<(T::AccountId, Result<(), ()>)> { + let keys = Self::find_all_local_keys(); + keys.into_iter().map(|(account, pub_key)| { + let call = call.clone().into(); + ( + account, + Self::SignAndSubmit::sign_and_submit(call, pub_key) + ) + }).collect() + } +} + +/// A default type used to submit transactions to the pool. +/// +/// This is passed into each runtime as an opaque associated type that can have either of: +/// - [`SignAndSubmitTransaction`] +/// - [`SubmitUnsignedTransaction`] +/// - [`SubmitSignedTransaction`] +/// and used accordingly. +/// +/// This struct should be constructed by providing the following generic parameters: +/// * `Signer` - Usually the application specific key type (see `app_crypto`). +/// * `CreateTransaction` - A type that is able to produce signed transactions, +/// usually it's going to be the entire `Runtime` object. +/// * `Extrinsic` - A runtime-specific type for in-block extrinsics. +/// +/// If you only need the ability to submit unsigned transactions, +/// you may substitute both `Signer` and `CreateTransaction` with any type. +pub struct TransactionSubmitter { + _signer: sp_std::marker::PhantomData<(Signer, CreateTransaction, Extrinsic)>, +} + +impl Default for TransactionSubmitter { + fn default() -> Self { + Self { + _signer: Default::default(), + } + } +} + +/// A blanket implementation to simplify creation of transaction signer & submitter in the runtime. +impl SignAndSubmitTransaction for TransactionSubmitter where + T: crate::Trait, + C: CreateTransaction, + S: Signer<>::Public, >::Signature>, + E: ExtrinsicT + codec::Encode, +{ + type Extrinsic = E; + type CreateTransaction = C; + type Signer = S; +} + +/// A blanket implementation to use the same submitter for unsigned transactions as well. +impl SubmitUnsignedTransaction for TransactionSubmitter where + T: crate::Trait, + E: ExtrinsicT + codec::Encode, +{ + type Extrinsic = E; +} + +/// A blanket implementation to support local keystore of application-crypto types. +impl SubmitSignedTransaction for TransactionSubmitter where + T: crate::Trait, + C: CreateTransaction, + E: ExtrinsicT + codec::Encode, + S: Signer<>::Public, >::Signature>, + // Make sure we can unwrap the app crypto key. + S: RuntimeAppPublic + AppPublic + Into<::Generic>, + // Make sure we can convert from wrapped crypto to public key (e.g. `MultiSigner`) + S::Generic: Into>, + // For simplicity we require the same trait to implement `SignAndSubmitTransaction` too. + Self: SignAndSubmitTransaction, +{ + type SignAndSubmit = Self; + + fn find_local_keys(accounts: Option>) -> Vec<( + T::AccountId, + PublicOf, + )> { + // Convert app-specific keys into generic ones. + let local_accounts_and_keys = S::all() + .into_iter() + .map(|app_key| { + // unwrap app-crypto + let generic_pub_key: ::Generic = app_key.into(); + // convert to expected public key type (might be MultiSigner) + let signer_pub_key: PublicOf = generic_pub_key.into(); + // lookup accountid for that pubkey + let account = signer_pub_key.clone().into_account(); + (account, signer_pub_key) + }).collect::>(); + + if let Some(accounts) = accounts { + let mut local_accounts_and_keys = local_accounts_and_keys; + // sort by accountId to allow bin-search. + local_accounts_and_keys.sort_by(|a, b| a.0.cmp(&b.0)); + + // get all the matching accounts + accounts.into_iter().filter_map(|acc| { + let idx = local_accounts_and_keys.binary_search_by(|a| a.0.cmp(&acc)).ok()?; + local_accounts_and_keys.get(idx).cloned() + }).collect() + } else { + // just return all account ids and keys + local_accounts_and_keys + } + } + + fn can_sign_with(accounts: Option>) -> bool { + // early exit if we care about any account. + if accounts.is_none() { + !S::all().is_empty() + } else { + !Self::find_local_keys(accounts).is_empty() + } + } +} diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml new file mode 100644 index 0000000000000..354a4740b712c --- /dev/null +++ b/frame/timestamp/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "pallet-timestamp" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +sp-timestamp = { version = "2.0.0", default-features = false, path = "../../primitives/timestamp" } +impl-trait-for-tuples = "0.1.3" + +[dev-dependencies] +sp-io ={ version = "2.0.0", path = "../../primitives/io" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } + +[features] +default = ["std"] +std = [ + "sp-inherents/std", + "codec/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", + "serde", + "frame-system/std", + "sp-timestamp/std" +] diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs new file mode 100644 index 0000000000000..1c16ed6380a92 --- /dev/null +++ b/frame/timestamp/src/lib.rs @@ -0,0 +1,318 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Timestamp Module +//! +//! The Timestamp module provides functionality to get and set the on-chain time. +//! +//! - [`timestamp::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Overview +//! +//! The Timestamp module allows the validators to set and validate a timestamp with 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 number based time measurement can cause issues +//! because of cumulative calculation errors and hence should be avoided. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! * `set` - Sets the current time. +//! +//! ### Public functions +//! +//! * `get` - Gets the current time for the current block. If this function is called prior to +//! setting the timestamp, it will return the timestamp of the previous block. +//! +//! ### Trait Getters +//! +//! * `MinimumPeriod` - 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 into your custom module and derive the module configuration +//! trait from the timestamp trait. +//! +//! ### Get current timestamp +//! +//! ``` +//! use frame_support::{decl_module, dispatch}; +//! # use pallet_timestamp as timestamp; +//! use frame_system::{self as 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) -> dispatch::DispatchResult { +//! let _sender = ensure_signed(origin)?; +//! let _now = >::get(); +//! Ok(()) +//! } +//! } +//! } +//! # fn main() {} +//! ``` +//! +//! ### Example from the SRML +//! +//! The [Session module](https://github.com/paritytech/substrate/blob/master/frame/session/src/lib.rs) uses +//! the Timestamp module for session management. +//! +//! ## Related Modules +//! +//! * [Session](../pallet_session/index.html) + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{result, cmp}; +use sp_inherents::{ProvideInherent, InherentData, InherentIdentifier}; +use frame_support::{Parameter, decl_storage, decl_module}; +use frame_support::traits::{Time, Get}; +use sp_runtime::{ + RuntimeString, + traits::{ + SimpleArithmetic, Zero, SaturatedConversion, Scale + } +}; +use frame_support::weights::SimpleDispatchInfo; +use frame_system::ensure_none; +use sp_timestamp::{ + InherentError, INHERENT_IDENTIFIER, InherentType, + OnTimestampSet, +}; + +/// The module configuration trait +pub trait Trait: frame_system::Trait { + /// Type used for expressing timestamp. + type Moment: Parameter + Default + SimpleArithmetic + + Scale + Copy; + + /// Something which can be notified when the timestamp is set. Set this to `()` if not needed. + type OnTimestampSet: OnTimestampSet; + + /// The minimum period between blocks. Beware that this is different to the *expected* period + /// that the block production apparatus provides. Your chosen consensus system will generally + /// work with this to determine a sensible block time. e.g. For Aura, it will be double this + /// period on default settings. + type MinimumPeriod: Get; +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// The minimum period between blocks. Beware that this is different to the *expected* period + /// that the block production apparatus provides. Your chosen consensus system will generally + /// work with this to determine a sensible block time. e.g. For Aura, it will be double this + /// period on default settings. + const MinimumPeriod: T::Moment = T::MinimumPeriod::get(); + + /// Set the current time. + /// + /// 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 + /// `MinimumPeriod`. + /// + /// The dispatch origin for this call must be `Inherent`. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn set(origin, #[compact] now: T::Moment) { + ensure_none(origin)?; + assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); + assert!( + Self::now().is_zero() || now >= Self::now() + T::MinimumPeriod::get(), + "Timestamp must increment by at least between sequential blocks" + ); + ::Now::put(now); + ::DidUpdate::put(true); + + >::on_timestamp_set(now); + } + + fn on_finalize() { + assert!(::DidUpdate::take(), "Timestamp must be updated once in the block"); + } + } +} + +decl_storage! { + trait Store for Module as Timestamp { + /// Current time for the current block. + pub Now get(fn now) build(|_| 0.into()): T::Moment; + + /// Did the timestamp get updated in this block? + DidUpdate: bool; + } +} + +impl Module { + /// Get the current time for the current block. + /// + /// 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() + } + + /// Set the timestamp to something in particular. Only used for tests. + #[cfg(feature = "std")] + pub fn set_timestamp(now: T::Moment) { + ::Now::put(now); + } +} + +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 Call = Call; + type Error = InherentError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + let data: T::Moment = extract_inherent_data(data) + .expect("Gets and decodes timestamp inherent data") + .saturated_into(); + + let next_time = cmp::max(data, Self::now() + T::MinimumPeriod::get()); + Some(Call::set(next_time.into())) + } + + fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> { + const MAX_TIMESTAMP_DRIFT_MILLIS: u64 = 30 * 1000; + + let t: u64 = match call { + Call::set(ref t) => t.clone().saturated_into::(), + _ => return Ok(()), + }; + + let data = extract_inherent_data(data).map_err(|e| InherentError::Other(e))?; + + let minimum = (Self::now() + T::MinimumPeriod::get()).saturated_into::(); + if t > data + MAX_TIMESTAMP_DRIFT_MILLIS { + Err(InherentError::Other("Timestamp too far in future to accept".into())) + } else if t < minimum { + Err(InherentError::ValidAtTimestamp(minimum)) + } else { + Ok(()) + } + } +} + +impl Time for Module { + type Moment = T::Moment; + + /// Before the first set of now with inherent the value returned is zero. + fn now() -> Self::Moment { + Self::now() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use frame_support::{impl_outer_origin, assert_ok, parameter_types, weights::Weight}; + use sp_io::TestExternalities; + use sp_core::H256; + use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + } + parameter_types! { + pub const MinimumPeriod: u64 = 5; + } + impl Trait for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + } + type Timestamp = Module; + + #[test] + fn timestamp_works() { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t).execute_with(|| { + Timestamp::set_timestamp(42); + assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); + assert_eq!(Timestamp::now(), 69); + }); + } + + #[test] + #[should_panic(expected = "Timestamp must be updated only once in the block")] + fn double_timestamp_should_fail() { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t).execute_with(|| { + Timestamp::set_timestamp(42); + assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); + let _ = Timestamp::dispatch(Call::set(70), Origin::NONE); + }); + } + + #[test] + #[should_panic(expected = "Timestamp must increment by at least between sequential blocks")] + fn block_period_minimum_enforced() { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t).execute_with(|| { + Timestamp::set_timestamp(42); + let _ = Timestamp::dispatch(Call::set(46), Origin::NONE); + }); + } +} diff --git a/frame/transaction-payment/Cargo.toml b/frame/transaction-payment/Cargo.toml new file mode 100644 index 0000000000000..ceb1ba9ebb586 --- /dev/null +++ b/frame/transaction-payment/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "pallet-transaction-payment" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "./rpc/runtime-api" } + +[dev-dependencies] +sp-io = { version = "2.0.0", path = "../../primitives/io" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "pallet-transaction-payment-rpc-runtime-api/std" +] diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml new file mode 100644 index 0000000000000..b8d1c35492242 --- /dev/null +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "pallet-transaction-payment-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0" } +jsonrpc-core = "14.0.3" +jsonrpc-core-client = "14.0.3" +jsonrpc-derive = "14.0.3" +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-rpc = { version = "2.0.0", path = "../../../primitives/rpc" } +serde = { version = "1.0.101", features = ["derive"] } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0", path = "./runtime-api" } diff --git a/frame/transaction-payment/rpc/runtime-api/Cargo.toml b/frame/transaction-payment/rpc/runtime-api/Cargo.toml new file mode 100644 index 0000000000000..3cf28bf662a24 --- /dev/null +++ b/frame/transaction-payment/rpc/runtime-api/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "pallet-transaction-payment-rpc-runtime-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-api = { version = "2.0.0", default-features = false, path = "../../../../primitives/api" } +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../../../primitives/std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../../../support" } + +[dev-dependencies] +serde_json = "1.0.41" + +[features] +default = ["std"] +std = [ + "serde", + "sp-api/std", + "codec/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", +] diff --git a/frame/transaction-payment/rpc/runtime-api/src/lib.rs b/frame/transaction-payment/rpc/runtime-api/src/lib.rs new file mode 100644 index 0000000000000..6e7425f8b8e35 --- /dev/null +++ b/frame/transaction-payment/rpc/runtime-api/src/lib.rs @@ -0,0 +1,106 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime API definition for transaction payment module. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use frame_support::weights::{Weight, DispatchClass}; +use codec::{Encode, Codec, Decode}; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use sp_runtime::traits::{UniqueSaturatedInto, SaturatedConversion}; + +/// Some information related to a dispatchable that can be queried from the runtime. +#[derive(Eq, PartialEq, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct RuntimeDispatchInfo { + /// Weight of this dispatch. + pub weight: Weight, + /// Class of this dispatch. + pub class: DispatchClass, + /// The partial inclusion fee of this dispatch. This does not include tip or anything else which + /// is dependent on the signature (aka. depends on a `SignedExtension`). + pub partial_fee: Balance, +} + +/// A capped version of `RuntimeDispatchInfo`. +/// +/// The `Balance` is capped (or expanded) to `u64` to avoid serde issues with `u128`. +#[derive(Eq, PartialEq, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +pub struct CappedDispatchInfo { + /// Weight of this dispatch. + pub weight: Weight, + /// Class of this dispatch. + pub class: DispatchClass, + /// The partial inclusion fee of this dispatch. This does not include tip or anything else which + /// is dependent on the signature (aka. depends on a `SignedExtension`). + pub partial_fee: u64, +} + +impl CappedDispatchInfo { + /// Create a new `CappedDispatchInfo` from `RuntimeDispatchInfo`. + pub fn new>( + dispatch: RuntimeDispatchInfo, + ) -> Self { + let RuntimeDispatchInfo { + weight, + class, + partial_fee, + } = dispatch; + + Self { + weight, + class, + partial_fee: partial_fee.saturated_into(), + } + } +} + +sp_api::decl_runtime_apis! { + pub trait TransactionPaymentApi where + Balance: Codec, + Extrinsic: Codec, + { + fn query_info(uxt: Extrinsic, len: u32) -> RuntimeDispatchInfo; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_serialize_properly_with_u64() { + let info = RuntimeDispatchInfo { + weight: 5, + class: DispatchClass::Normal, + partial_fee: 1_000_000_u64, + }; + + let info = CappedDispatchInfo::new(info); + assert_eq!( + serde_json::to_string(&info).unwrap(), + r#"{"weight":5,"class":"normal","partialFee":1000000}"#, + ); + + // should not panic + serde_json::to_value(&info).unwrap(); + } +} diff --git a/frame/transaction-payment/rpc/src/lib.rs b/frame/transaction-payment/rpc/src/lib.rs new file mode 100644 index 0000000000000..aadc33759ede4 --- /dev/null +++ b/frame/transaction-payment/rpc/src/lib.rs @@ -0,0 +1,104 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! RPC interface for the transaction payment module. + +use std::sync::Arc; +use codec::{Codec, Decode}; +use sp_blockchain::HeaderBackend; +use jsonrpc_core::{Error as RpcError, ErrorCode, Result}; +use jsonrpc_derive::rpc; +use sp_runtime::{generic::BlockId, traits::{Block as BlockT, UniqueSaturatedInto}}; +use sp_api::ProvideRuntimeApi; +use sp_core::Bytes; +use pallet_transaction_payment_rpc_runtime_api::CappedDispatchInfo; +pub use pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi as TransactionPaymentRuntimeApi; +pub use self::gen_client::Client as TransactionPaymentClient; + +#[rpc] +pub trait TransactionPaymentApi { + #[rpc(name = "payment_queryInfo")] + fn query_info( + &self, + encoded_xt: Bytes, + at: Option + ) -> Result; +} + +/// A struct that implements the [`TransactionPaymentApi`]. +pub struct TransactionPayment { + client: Arc, + _marker: std::marker::PhantomData

::Hashing as HashT>::Hasher>( storage_root, @@ -193,6 +191,5 @@ fn record_proof_works() { &executor, "Core_execute_block", &block.encode(), - None, ).expect("Executes block while using the proof backend"); } diff --git a/primitives/api/test/tests/trybuild.rs b/primitives/api/test/tests/trybuild.rs new file mode 100644 index 0000000000000..910771f938969 --- /dev/null +++ b/primitives/api/test/tests/trybuild.rs @@ -0,0 +1,27 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::env; + +#[rustversion::attr(not(stable), ignore)] +#[test] +fn ui() { + // As trybuild is using `cargo check`, we don't need the real WASM binaries. + env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/primitives/api/test/tests/ui/adding_self_parameter.rs b/primitives/api/test/tests/ui/adding_self_parameter.rs new file mode 100644 index 0000000000000..117fa261886b9 --- /dev/null +++ b/primitives/api/test/tests/ui/adding_self_parameter.rs @@ -0,0 +1,7 @@ +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(&self); + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/adding_self_parameter.stderr b/primitives/api/test/tests/ui/adding_self_parameter.stderr new file mode 100644 index 0000000000000..894713d35eef8 --- /dev/null +++ b/primitives/api/test/tests/ui/adding_self_parameter.stderr @@ -0,0 +1,5 @@ +error: `self` as argument not supported. + --> $DIR/adding_self_parameter.rs:3:11 + | +3 | fn test(&self); + | ^ diff --git a/primitives/api/test/tests/ui/changed_in_unknown_version.rs b/primitives/api/test/tests/ui/changed_in_unknown_version.rs new file mode 100644 index 0000000000000..151f3e5f4d637 --- /dev/null +++ b/primitives/api/test/tests/ui/changed_in_unknown_version.rs @@ -0,0 +1,19 @@ +use sp_runtime::traits::GetNodeBlockType; +use substrate_test_runtime_client::runtime::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +sp_api::decl_runtime_apis! { + pub trait Api { + #[changed_in(2)] + fn test(data: u64); + fn test(data: u64); + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/changed_in_unknown_version.stderr b/primitives/api/test/tests/ui/changed_in_unknown_version.stderr new file mode 100644 index 0000000000000..cf03ee4530ab7 --- /dev/null +++ b/primitives/api/test/tests/ui/changed_in_unknown_version.stderr @@ -0,0 +1,5 @@ +error: `changed_in` version can not be greater than the `api_version` + --> $DIR/changed_in_unknown_version.rs:14:3 + | +14 | fn test(data: u64); + | ^^ diff --git a/primitives/api/test/tests/ui/declaring_old_block.rs b/primitives/api/test/tests/ui/declaring_old_block.rs new file mode 100644 index 0000000000000..ba98bf9bf6883 --- /dev/null +++ b/primitives/api/test/tests/ui/declaring_old_block.rs @@ -0,0 +1,9 @@ +use sp_runtime::traits::Block as BlockT; + +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(); + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/declaring_old_block.stderr b/primitives/api/test/tests/ui/declaring_old_block.stderr new file mode 100644 index 0000000000000..448dc38594321 --- /dev/null +++ b/primitives/api/test/tests/ui/declaring_old_block.stderr @@ -0,0 +1,19 @@ +error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally. + --> $DIR/declaring_old_block.rs:4:23 + | +4 | pub trait Api { + | ^^^^^^ + +error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! + --> $DIR/declaring_old_block.rs:4:16 + | +4 | pub trait Api { + | ^^^^^ + +warning: unused import: `sp_runtime::traits::Block as BlockT` + --> $DIR/declaring_old_block.rs:1:5 + | +1 | use sp_runtime::traits::Block as BlockT; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs new file mode 100644 index 0000000000000..67bb9cab10502 --- /dev/null +++ b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.rs @@ -0,0 +1,9 @@ +use sp_runtime::traits::Block as BlockT; + +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(); + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr new file mode 100644 index 0000000000000..fe445b822dd88 --- /dev/null +++ b/primitives/api/test/tests/ui/declaring_own_block_with_different_name.stderr @@ -0,0 +1,13 @@ +error: `Block: BlockT` generic parameter will be added automatically by the `decl_runtime_apis!` macro! If you try to use a different trait than the substrate `Block` trait, please rename it locally. + --> $DIR/declaring_own_block_with_different_name.rs:4:19 + | +4 | pub trait Api { + | ^^^^^^ + +warning: unused import: `sp_runtime::traits::Block as BlockT` + --> $DIR/declaring_own_block_with_different_name.rs:1:5 + | +1 | use sp_runtime::traits::Block as BlockT; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.rs b/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.rs new file mode 100644 index 0000000000000..93343fb72ab5d --- /dev/null +++ b/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.rs @@ -0,0 +1,19 @@ +use sp_runtime::traits::GetNodeBlockType; +use substrate_test_runtime_client::runtime::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } +} + +sp_api::impl_runtime_apis! {} + +fn main() {} diff --git a/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr new file mode 100644 index 0000000000000..f927912879ad0 --- /dev/null +++ b/primitives/api/test/tests/ui/empty_impl_runtime_apis_call.stderr @@ -0,0 +1,5 @@ +error: No api implementation given! + --> $DIR/empty_impl_runtime_apis_call.rs:17:1 + | +17 | sp_api::impl_runtime_apis! {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs new file mode 100644 index 0000000000000..19dfdda836236 --- /dev/null +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs @@ -0,0 +1,35 @@ +use sp_runtime::traits::{GetNodeBlockType, Block as BlockT}; +use substrate_test_runtime_client::runtime::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } +} + +sp_api::impl_runtime_apis! { + impl self::Api for Runtime { + fn test(data: String) {} + } + + impl sp_api::Core for Runtime { + fn version() -> sp_api::RuntimeVersion { + unimplemented!() + } + fn execute_block(_: Block) { + unimplemented!() + } + fn initialize_block(_: &::Header) { + unimplemented!() + } + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr new file mode 100644 index 0000000000000..ca7e519344f3e --- /dev/null +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr @@ -0,0 +1,64 @@ +error[E0053]: method `test` has an incompatible type for trait + --> $DIR/impl_incorrect_method_signature.rs:19:17 + | +13 | fn test(data: u64); + | --- type in trait +... +19 | fn test(data: String) {} + | ^^^^^^ expected u64, found struct `std::string::String` + | + = note: expected type `fn(u64)` + found type `fn(std::string::String)` + +error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for trait + --> $DIR/impl_incorrect_method_signature.rs:17:1 + | +11 | / sp_api::decl_runtime_apis! { +12 | | pub trait Api { +13 | | fn test(data: u64); +14 | | } +15 | | } + | |_- type in trait +16 | +17 | sp_api::impl_runtime_apis! { + | -^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | _expected u64, found struct `std::string::String` + | | +18 | | impl self::Api for Runtime { +19 | | fn test(data: String) {} +20 | | } +... | +32 | | } +33 | | } + | |_- in this macro invocation + | + = note: expected type `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, >::Error>` + found type `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, >::Error>` + +error[E0308]: mismatched types + --> $DIR/impl_incorrect_method_signature.rs:17:1 + | +17 | / sp_api::impl_runtime_apis! { +18 | | impl self::Api for Runtime { +19 | | fn test(data: String) {} +20 | | } +... | +32 | | } +33 | | } + | | ^ + | | | + | |_expected u64, found struct `std::string::String` + | in this macro invocation + | + = note: expected type `u64` + found type `std::string::String` + +error[E0308]: mismatched types + --> $DIR/impl_incorrect_method_signature.rs:19:11 + | +19 | fn test(data: String) {} + | ^^^^ expected u64, found struct `std::string::String` + | + = note: expected type `u64` + found type `std::string::String` diff --git a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs new file mode 100644 index 0000000000000..2122a6991ae5a --- /dev/null +++ b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.rs @@ -0,0 +1,37 @@ +use sp_runtime::traits::GetNodeBlockType; +use substrate_test_runtime_client::runtime::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } +} + +mod second { + use super::*; + + sp_api::decl_runtime_apis! { + pub trait Api { + fn test2(data: u64); + } + } +} + +sp_api::impl_runtime_apis! { + impl self::Api for Runtime { + fn test(data: u64) {} + } + + impl second::Api for Runtime { + fn test2(data: u64) {} + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr new file mode 100644 index 0000000000000..24ee66f84b314 --- /dev/null +++ b/primitives/api/test/tests/ui/impl_two_traits_with_same_name.stderr @@ -0,0 +1,13 @@ +error: Two traits with the same name detected! The trait name is used to generate its ID. Please rename one trait at the declaration! + --> $DIR/impl_two_traits_with_same_name.rs:32:15 + | +32 | impl second::Api for Runtime { + | ^^^ + +warning: unused import: `super::*` + --> $DIR/impl_two_traits_with_same_name.rs:18:6 + | +18 | use super::*; + | ^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default diff --git a/primitives/api/test/tests/ui/invalid_api_version.rs b/primitives/api/test/tests/ui/invalid_api_version.rs new file mode 100644 index 0000000000000..e038dd0aa6585 --- /dev/null +++ b/primitives/api/test/tests/ui/invalid_api_version.rs @@ -0,0 +1,8 @@ +sp_api::decl_runtime_apis! { + #[api_version] + pub trait Api { + fn test(data: u64); + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/invalid_api_version.stderr b/primitives/api/test/tests/ui/invalid_api_version.stderr new file mode 100644 index 0000000000000..7770bc70e72d6 --- /dev/null +++ b/primitives/api/test/tests/ui/invalid_api_version.stderr @@ -0,0 +1,5 @@ +error: Unexpected `api_version` attribute. The supported format is `api_version(1)` + --> $DIR/invalid_api_version.rs:2:4 + | +2 | #[api_version] + | ^^^^^^^^^^^ diff --git a/primitives/api/test/tests/ui/invalid_api_version_2.rs b/primitives/api/test/tests/ui/invalid_api_version_2.rs new file mode 100644 index 0000000000000..bb8ed8ed11fea --- /dev/null +++ b/primitives/api/test/tests/ui/invalid_api_version_2.rs @@ -0,0 +1,8 @@ +sp_api::decl_runtime_apis! { + #[api_version("1")] + pub trait Api { + fn test(data: u64); + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/invalid_api_version_2.stderr b/primitives/api/test/tests/ui/invalid_api_version_2.stderr new file mode 100644 index 0000000000000..7ca6a7eebe49c --- /dev/null +++ b/primitives/api/test/tests/ui/invalid_api_version_2.stderr @@ -0,0 +1,5 @@ +error: Unexpected `api_version` attribute. The supported format is `api_version(1)` + --> $DIR/invalid_api_version_2.rs:2:4 + | +2 | #[api_version("1")] + | ^^^^^^^^^^^ diff --git a/primitives/api/test/tests/ui/invalid_api_version_3.rs b/primitives/api/test/tests/ui/invalid_api_version_3.rs new file mode 100644 index 0000000000000..d010866e23731 --- /dev/null +++ b/primitives/api/test/tests/ui/invalid_api_version_3.rs @@ -0,0 +1,8 @@ +sp_api::decl_runtime_apis! { + #[api_version()] + pub trait Api { + fn test(data: u64); + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/invalid_api_version_3.stderr b/primitives/api/test/tests/ui/invalid_api_version_3.stderr new file mode 100644 index 0000000000000..cef4763a6de96 --- /dev/null +++ b/primitives/api/test/tests/ui/invalid_api_version_3.stderr @@ -0,0 +1,5 @@ +error: Unexpected `api_version` attribute. The supported format is `api_version(1)` + --> $DIR/invalid_api_version_3.rs:2:4 + | +2 | #[api_version()] + | ^^^^^^^^^^^ diff --git a/primitives/api/test/tests/ui/missing_block_generic_parameter.rs b/primitives/api/test/tests/ui/missing_block_generic_parameter.rs new file mode 100644 index 0000000000000..e194fdbf4ab65 --- /dev/null +++ b/primitives/api/test/tests/ui/missing_block_generic_parameter.rs @@ -0,0 +1,25 @@ +use sp_runtime::traits::GetNodeBlockType; +use substrate_test_runtime_client::runtime::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } +} + +sp_api::impl_runtime_apis! { + impl self::Api for Runtime { + fn test(data: u64) { + unimplemented!() + } + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/missing_block_generic_parameter.stderr b/primitives/api/test/tests/ui/missing_block_generic_parameter.stderr new file mode 100644 index 0000000000000..d626eda2496f4 --- /dev/null +++ b/primitives/api/test/tests/ui/missing_block_generic_parameter.stderr @@ -0,0 +1,5 @@ +error: Missing `Block` generic parameter. + --> $DIR/missing_block_generic_parameter.rs:18:13 + | +18 | impl self::Api for Runtime { + | ^^^ diff --git a/primitives/api/test/tests/ui/missing_path_for_trait.rs b/primitives/api/test/tests/ui/missing_path_for_trait.rs new file mode 100644 index 0000000000000..d7540ce88a8a1 --- /dev/null +++ b/primitives/api/test/tests/ui/missing_path_for_trait.rs @@ -0,0 +1,25 @@ +use sp_runtime::traits::GetNodeBlockType; +use substrate_test_runtime_client::runtime::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } +} + +sp_api::impl_runtime_apis! { + impl Api for Runtime { + fn test(data: u64) { + unimplemented!() + } + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/missing_path_for_trait.stderr b/primitives/api/test/tests/ui/missing_path_for_trait.stderr new file mode 100644 index 0000000000000..729ff0bad18d8 --- /dev/null +++ b/primitives/api/test/tests/ui/missing_path_for_trait.stderr @@ -0,0 +1,5 @@ +error: The implemented trait has to be referenced with a path, e.g. `impl client::Core for Runtime`. + --> $DIR/missing_path_for_trait.rs:18:7 + | +18 | impl Api for Runtime { + | ^^^ diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs new file mode 100644 index 0000000000000..a82fb9a1595db --- /dev/null +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs @@ -0,0 +1,37 @@ +use sp_runtime::traits::{GetNodeBlockType, Block as BlockT}; +use substrate_test_runtime_client::runtime::Block; + +/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` +/// trait are done by the `construct_runtime!` macro in a real runtime. +struct Runtime {} +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +sp_api::decl_runtime_apis! { + pub trait Api { + fn test(data: u64); + } +} + +sp_api::impl_runtime_apis! { + impl self::Api for Runtime { + fn test(data: &u64) { + unimplemented!() + } + } + + impl sp_api::Core for Runtime { + fn version() -> sp_api::RuntimeVersion { + unimplemented!() + } + fn execute_block(_: Block) { + unimplemented!() + } + fn initialize_block(_: &::Header) { + unimplemented!() + } + } +} + +fn main() {} diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr new file mode 100644 index 0000000000000..b793d832ff224 --- /dev/null +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr @@ -0,0 +1,67 @@ +error[E0053]: method `test` has an incompatible type for trait + --> $DIR/type_reference_in_impl_runtime_apis_call.rs:19:17 + | +13 | fn test(data: u64); + | --- type in trait +... +19 | fn test(data: &u64) { + | ^^^^ expected u64, found &u64 + | + = note: expected type `fn(u64)` + found type `fn(&u64)` + +error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for trait + --> $DIR/type_reference_in_impl_runtime_apis_call.rs:17:1 + | +11 | / sp_api::decl_runtime_apis! { +12 | | pub trait Api { +13 | | fn test(data: u64); +14 | | } +15 | | } + | |_- type in trait +16 | +17 | sp_api::impl_runtime_apis! { + | -^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | _expected u64, found &u64 + | | +18 | | impl self::Api for Runtime { +19 | | fn test(data: &u64) { +20 | | unimplemented!() +... | +34 | | } +35 | | } + | |_- in this macro invocation + | + = note: expected type `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, >::Error>` + found type `fn(&RuntimeApiImpl<__SR_API_BLOCK__, RuntimeApiImplCall>, &sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::BlockId<__SR_API_BLOCK__>, sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ExecutionContext, std::option::Option<&u64>, std::vec::Vec) -> std::result::Result, >::Error>` + +error[E0308]: mismatched types + --> $DIR/type_reference_in_impl_runtime_apis_call.rs:17:1 + | +17 | / sp_api::impl_runtime_apis! { +18 | | impl self::Api for Runtime { +19 | | fn test(data: &u64) { +20 | | unimplemented!() +... | +34 | | } +35 | | } + | | ^ + | | | + | |_expected u64, found &u64 + | in this macro invocation + | + = note: expected type `u64` + found type `&u64` + +error[E0308]: mismatched types + --> $DIR/type_reference_in_impl_runtime_apis_call.rs:19:11 + | +19 | fn test(data: &u64) { + | ^^^^^^^ + | | + | expected u64, found &u64 + | help: consider removing the borrow: `data` + | + = note: expected type `u64` + found type `&u64` diff --git a/primitives/application-crypto/Cargo.toml b/primitives/application-crypto/Cargo.toml new file mode 100644 index 0000000000000..f6487ebc298c3 --- /dev/null +++ b/primitives/application-crypto/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "sp-application-crypto" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +description = "Provides facilities for generating application specific crypto wrapper types." + +[dependencies] +sp-core = { version = "2.0.0", default-features = false, path = "../core" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } + +[features] +default = [ "std" ] +std = [ "full_crypto", "sp-core/std", "codec/std", "serde", "sp-std/std", "sp-io/std" ] + +# This feature enables all crypto primitives for `no_std` builds like microcontrollers +# or Intel SGX. +# For the regular wasm runtime builds this should not be used. +full_crypto = [ + "sp-core/full_crypto" +] diff --git a/primitives/application-crypto/src/ed25519.rs b/primitives/application-crypto/src/ed25519.rs new file mode 100644 index 0000000000000..c92c70495e6cb --- /dev/null +++ b/primitives/application-crypto/src/ed25519.rs @@ -0,0 +1,56 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Ed25519 crypto types. + +use crate::{RuntimePublic, KeyTypeId}; + +use sp_std::vec::Vec; + +pub use sp_core::ed25519::*; + +mod app { + use sp_core::testing::ED25519; + crate::app_crypto!(super, ED25519); + + impl crate::traits::BoundToRuntimeAppPublic for Public { + type Public = Self; + } +} + +pub use app::{Public as AppPublic, Signature as AppSignature}; +#[cfg(feature = "full_crypto")] +pub use app::Pair as AppPair; + +impl RuntimePublic for Public { + type Signature = Signature; + + fn all(key_type: KeyTypeId) -> crate::Vec { + sp_io::crypto::ed25519_public_keys(key_type) + } + + fn generate_pair(key_type: KeyTypeId, seed: Option>) -> Self { + sp_io::crypto::ed25519_generate(key_type, seed) + } + + fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option { + sp_io::crypto::ed25519_sign(key_type, self, msg.as_ref()) + } + + fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { + sp_io::crypto::ed25519_verify(&signature, msg.as_ref(), self) + } +} diff --git a/primitives/application-crypto/src/lib.rs b/primitives/application-crypto/src/lib.rs new file mode 100644 index 0000000000000..db1bdf0c7a523 --- /dev/null +++ b/primitives/application-crypto/src/lib.rs @@ -0,0 +1,434 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Traits and macros for constructing application specific strongly typed crypto wrappers. + +#![warn(missing_docs)] + +#![cfg_attr(not(feature = "std"), no_std)] + +#[doc(hidden)] +pub use sp_core::{self, crypto::{CryptoType, Public, Derive, IsWrappedBy, Wraps}, RuntimeDebug}; +#[doc(hidden)] +#[cfg(feature = "full_crypto")] +pub use sp_core::crypto::{SecretStringError, DeriveJunction, Ss58Codec, Pair}; +pub use sp_core::{crypto::{KeyTypeId, key_types}}; + +#[doc(hidden)] +pub use codec; +#[doc(hidden)] +#[cfg(feature = "std")] +pub use serde; +#[doc(hidden)] +pub use sp_std::{ops::Deref, vec::Vec}; + +pub mod ed25519; +pub mod sr25519; +mod traits; + +pub use traits::*; + +/// Declares Public, Pair, Signature types which are functionally equivalent to `$pair`, but are new +/// Application-specific types whose identifier is `$key_type`. +/// +/// ```rust +///# use sp_application_crypto::{app_crypto, wrap, ed25519, KeyTypeId}; +/// // Declare a new set of crypto types using Ed25519 logic that identifies as `KeyTypeId` +/// // of value `b"fuba"`. +/// app_crypto!(ed25519, KeyTypeId(*b"_uba")); +/// ``` +#[cfg(feature = "full_crypto")] +#[macro_export] +macro_rules! app_crypto { + ($module:ident, $key_type:expr) => { + $crate::app_crypto_public_full_crypto!($module::Public, $key_type); + $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type); + $crate::app_crypto_signature_full_crypto!($module::Signature, $key_type); + $crate::app_crypto_signature_common!($module::Signature, $key_type); + $crate::app_crypto_pair!($module::Pair, $key_type); + }; +} + +/// Declares Public, Pair, Signature types which are functionally equivalent to `$pair`, but are new +/// Application-specific types whose identifier is `$key_type`. +/// +/// ```rust +///# use sp_application_crypto::{app_crypto, wrap, ed25519, KeyTypeId}; +/// // Declare a new set of crypto types using Ed25519 logic that identifies as `KeyTypeId` +/// // of value `b"fuba"`. +/// app_crypto!(ed25519, KeyTypeId(*b"_uba")); +/// ``` +#[cfg(not(feature = "full_crypto"))] +#[macro_export] +macro_rules! app_crypto { + ($module:ident, $key_type:expr) => { + $crate::app_crypto_public_not_full_crypto!($module::Public, $key_type); + $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type); + $crate::app_crypto_signature_not_full_crypto!($module::Signature, $key_type); + $crate::app_crypto_signature_common!($module::Signature, $key_type); + }; +} + +/// Declares Pair type which is functionally equivalent to `$pair`, but is new +/// Application-specific type whose identifier is `$key_type`. +#[macro_export] +macro_rules! app_crypto_pair { + ($pair:ty, $key_type:expr) => { + $crate::wrap!{ + /// A generic `AppPublic` wrapper type over $pair crypto; this has no specific App. + #[derive(Clone)] + pub struct Pair($pair); + } + + impl $crate::CryptoType for Pair { + type Pair = Pair; + } + + impl $crate::Pair for Pair { + type Public = Public; + type Seed = <$pair as $crate::Pair>::Seed; + type Signature = Signature; + type DeriveError = <$pair as $crate::Pair>::DeriveError; + + #[cfg(feature = "std")] + fn generate_with_phrase(password: Option<&str>) -> (Self, String, Self::Seed) { + let r = <$pair>::generate_with_phrase(password); + (Self(r.0), r.1, r.2) + } + #[cfg(feature = "std")] + fn from_phrase(phrase: &str, password: Option<&str>) + -> Result<(Self, Self::Seed), $crate::SecretStringError> + { + <$pair>::from_phrase(phrase, password).map(|r| (Self(r.0), r.1)) + } + fn derive< + Iter: Iterator + >(&self, path: Iter, seed: Option) -> Result<(Self, Option), Self::DeriveError> { + self.0.derive(path, seed).map(|x| (Self(x.0), x.1)) + } + fn from_seed(seed: &Self::Seed) -> Self { Self(<$pair>::from_seed(seed)) } + fn from_seed_slice(seed: &[u8]) -> Result { + <$pair>::from_seed_slice(seed).map(Self) + } + fn sign(&self, msg: &[u8]) -> Self::Signature { + Signature(self.0.sign(msg)) + } + fn verify>( + sig: &Self::Signature, + message: M, + pubkey: &Self::Public, + ) -> bool { + <$pair>::verify(&sig.0, message, pubkey.as_ref()) + } + fn verify_weak, M: AsRef<[u8]>>( + sig: &[u8], + message: M, + pubkey: P, + ) -> bool { + <$pair>::verify_weak(sig, message, pubkey) + } + fn public(&self) -> Self::Public { Public(self.0.public()) } + fn to_raw_vec(&self) -> $crate::Vec { self.0.to_raw_vec() } + } + + impl $crate::AppKey for Pair { + type UntypedGeneric = $pair; + type Public = Public; + type Pair = Pair; + type Signature = Signature; + const ID: $crate::KeyTypeId = $key_type; + } + + impl $crate::AppPair for Pair { + type Generic = $pair; + } + }; +} + +/// Declares Public type which is functionally equivalent to `$public`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// can only be used together with `full_crypto` feature +/// For full functionality, app_crypto_public_common! must be called too. +#[macro_export] +macro_rules! app_crypto_public_full_crypto { + ($public:ty, $key_type:expr) => { + $crate::wrap!{ + /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. + #[derive( + Clone, Default, Eq, PartialEq, Ord, PartialOrd, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + #[derive(Hash)] + pub struct Public($public); + } + + impl $crate::CryptoType for Public { + type Pair = Pair; + } + + impl $crate::AppKey for Public { + type UntypedGeneric = $public; + type Public = Public; + type Pair = Pair; + type Signature = Signature; + const ID: $crate::KeyTypeId = $key_type; + } + } +} + +/// Declares Public type which is functionally equivalent to `$public`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// can only be used without `full_crypto` feature +/// For full functionality, app_crypto_public_common! must be called too. +#[macro_export] +macro_rules! app_crypto_public_not_full_crypto { + ($public:ty, $key_type:expr) => { + $crate::wrap!{ + /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. + #[derive( + Clone, Default, Eq, PartialEq, Ord, PartialOrd, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + pub struct Public($public); + } + + impl $crate::CryptoType for Public {} + + impl $crate::AppKey for Public { + type UntypedGeneric = $public; + type Public = Public; + type Signature = Signature; + const ID: $crate::KeyTypeId = $key_type; + } + } +} + +/// Declares Public type which is functionally equivalent to `$public`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// For full functionality, app_crypto_public_(not)_full_crypto! must be called too. +#[macro_export] +macro_rules! app_crypto_public_common { + ($public:ty, $sig:ty, $key_type:expr) => { + impl $crate::Derive for Public { + #[cfg(feature = "std")] + fn derive>(&self, + path: Iter + ) -> Option { + self.0.derive(path).map(Self) + } + } + + #[cfg(feature = "std")] + impl std::fmt::Display for Public { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use $crate::Ss58Codec; + write!(f, "{}", self.0.to_ss58check()) + } + } + #[cfg(feature = "std")] + impl $crate::serde::Serialize for Public { + fn serialize(&self, serializer: S) -> std::result::Result where + S: $crate::serde::Serializer + { + use $crate::Ss58Codec; + serializer.serialize_str(&self.to_ss58check()) + } + } + #[cfg(feature = "std")] + impl<'de> $crate::serde::Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> std::result::Result where + D: $crate::serde::Deserializer<'de> + { + use $crate::Ss58Codec; + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| $crate::serde::de::Error::custom(format!("{:?}", e))) + } + } + + impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { self.0.as_ref() } + } + + impl AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { self.0.as_mut() } + } + + impl $crate::Public for Public { + fn from_slice(x: &[u8]) -> Self { Self(<$public>::from_slice(x)) } + } + + impl $crate::AppPublic for Public { + type Generic = $public; + } + + impl $crate::RuntimeAppPublic for Public where $public: $crate::RuntimePublic { + const ID: $crate::KeyTypeId = $key_type; + type Signature = Signature; + + fn all() -> $crate::Vec { + <$public as $crate::RuntimePublic>::all($key_type).into_iter().map(Self).collect() + } + + fn generate_pair(seed: Option<$crate::Vec>) -> Self { + Self(<$public as $crate::RuntimePublic>::generate_pair($key_type, seed)) + } + + fn sign>(&self, msg: &M) -> Option { + <$public as $crate::RuntimePublic>::sign( + self.as_ref(), + $key_type, + msg, + ).map(Signature) + } + + fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { + <$public as $crate::RuntimePublic>::verify(self.as_ref(), msg, &signature.as_ref()) + } + } + } +} + +/// Declares Signature type which is functionally equivalent to `$sig`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// can only be used together with `full_crypto` feature +/// For full functionality, app_crypto_public_common! must be called too. +#[macro_export] +macro_rules! app_crypto_signature_full_crypto { + ($sig:ty, $key_type:expr) => { + $crate::wrap! { + /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. + #[derive(Clone, Default, Eq, PartialEq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + #[derive(Hash)] + pub struct Signature($sig); + } + + impl $crate::CryptoType for Signature { + type Pair = Pair; + } + + impl $crate::AppKey for Signature { + type UntypedGeneric = $sig; + type Public = Public; + type Pair = Pair; + type Signature = Signature; + const ID: $crate::KeyTypeId = $key_type; + } + } +} + +/// Declares Signature type which is functionally equivalent to `$sig`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// can only be used without `full_crypto` feature +/// For full functionality, app_crypto_public_common! must be called too. +#[macro_export] +macro_rules! app_crypto_signature_not_full_crypto { + ($sig:ty, $key_type:expr) => { + $crate::wrap! { + /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. + #[derive(Clone, Default, Eq, PartialEq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + pub struct Signature($sig); + } + + impl $crate::CryptoType for Signature {} + + impl $crate::AppKey for Signature { + type UntypedGeneric = $sig; + type Public = Public; + type Signature = Signature; + const ID: $crate::KeyTypeId = $key_type; + } + } +} + +/// Declares Signature type which is functionally equivalent to `$sig`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// For full functionality, app_crypto_public_(not)_full_crypto! must be called too. +#[macro_export] +macro_rules! app_crypto_signature_common { + ($sig:ty, $key_type:expr) => { + impl $crate::Deref for Signature { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { self.0.as_ref() } + } + + impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { self.0.as_ref() } + } + + impl $crate::AppSignature for Signature { + type Generic = $sig; + } + } +} + +/// Implement bidirectional `From` and on-way `AsRef`/`AsMut` for two types, `$inner` and `$outer`. +/// +/// ```rust +/// sp_application_crypto::wrap! { +/// pub struct Wrapper(u32); +/// } +/// ``` +#[macro_export] +macro_rules! wrap { + ($( #[ $attr:meta ] )* struct $outer:ident($inner:ty);) => { + $( #[ $attr ] )* + struct $outer( $inner ); + $crate::wrap!($inner, $outer); + }; + ($( #[ $attr:meta ] )* pub struct $outer:ident($inner:ty);) => { + $( #[ $attr ] )* + pub struct $outer( $inner ); + $crate::wrap!($inner, $outer); + }; + ($inner:ty, $outer:ty) => { + impl $crate::Wraps for $outer { + type Inner = $inner; + } + impl From<$inner> for $outer { + fn from(inner: $inner) -> Self { + Self(inner) + } + } + impl From<$outer> for $inner { + fn from(outer: $outer) -> Self { + outer.0 + } + } + impl AsRef<$inner> for $outer { + fn as_ref(&self) -> &$inner { + &self.0 + } + } + impl AsMut<$inner> for $outer { + fn as_mut(&mut self) -> &mut $inner { + &mut self.0 + } + } + } +} diff --git a/primitives/application-crypto/src/sr25519.rs b/primitives/application-crypto/src/sr25519.rs new file mode 100644 index 0000000000000..34d9797bd4ea8 --- /dev/null +++ b/primitives/application-crypto/src/sr25519.rs @@ -0,0 +1,56 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Sr25519 crypto types. + +use crate::{RuntimePublic, KeyTypeId}; + +use sp_std::vec::Vec; + +pub use sp_core::sr25519::*; + +mod app { + use sp_core::testing::SR25519; + crate::app_crypto!(super, SR25519); + + impl crate::traits::BoundToRuntimeAppPublic for Public { + type Public = Self; + } +} + +pub use app::{Public as AppPublic, Signature as AppSignature}; +#[cfg(feature = "full_crypto")] +pub use app::Pair as AppPair; + +impl RuntimePublic for Public { + type Signature = Signature; + + fn all(key_type: KeyTypeId) -> crate::Vec { + sp_io::crypto::sr25519_public_keys(key_type) + } + + fn generate_pair(key_type: KeyTypeId, seed: Option>) -> Self { + sp_io::crypto::sr25519_generate(key_type, seed) + } + + fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option { + sp_io::crypto::sr25519_sign(key_type, self, msg.as_ref()) + } + + fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { + sp_io::crypto::sr25519_verify(&signature, msg.as_ref(), self) + } +} diff --git a/primitives/application-crypto/src/traits.rs b/primitives/application-crypto/src/traits.rs new file mode 100644 index 0000000000000..4b500bb2a63c9 --- /dev/null +++ b/primitives/application-crypto/src/traits.rs @@ -0,0 +1,145 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#[cfg(feature = "full_crypto")] +use sp_core::crypto::Pair; + +use codec::Codec; +use sp_core::crypto::{KeyTypeId, CryptoType, IsWrappedBy, Public}; +use sp_std::{fmt::Debug, vec::Vec}; + +/// An application-specific key. +pub trait AppKey: 'static + Send + Sync + Sized + CryptoType + Clone { + /// The corresponding type as a generic crypto type. + type UntypedGeneric: IsWrappedBy; + + /// The corresponding public key type in this application scheme. + type Public: AppPublic; + + /// The corresponding key pair type in this application scheme. + #[cfg(feature = "full_crypto")] + type Pair: AppPair; + + /// The corresponding signature type in this application scheme. + type Signature: AppSignature; + + /// An identifier for this application-specific key type. + const ID: KeyTypeId; +} + +/// Type which implements Hash in std, not when no-std (std variant). +#[cfg(any(feature = "std", feature = "full_crypto"))] +pub trait MaybeHash: sp_std::hash::Hash {} +#[cfg(any(feature = "std", feature = "full_crypto"))] +impl MaybeHash for T {} + +/// Type which implements Hash in std, not when no-std (no-std variant). +#[cfg(all(not(feature = "std"), not(feature = "full_crypto")))] +pub trait MaybeHash {} +#[cfg(all(not(feature = "std"), not(feature = "full_crypto")))] +impl MaybeHash for T {} + +/// Type which implements Debug and Hash in std, not when no-std (no-std variant with crypto). +#[cfg(all(not(feature = "std"), feature = "full_crypto"))] +pub trait MaybeDebugHash: sp_std::hash::Hash {} +#[cfg(all(not(feature = "std"), feature = "full_crypto"))] +impl MaybeDebugHash for T {} + +/// A application's public key. +pub trait AppPublic: + AppKey + Public + Ord + PartialOrd + Eq + PartialEq + Debug + MaybeHash + codec::Codec +{ + /// The wrapped type which is just a plain instance of `Public`. + type Generic: + IsWrappedBy + Public + Ord + PartialOrd + Eq + PartialEq + Debug + MaybeHash + codec::Codec; +} + +/// A application's key pair. +#[cfg(feature = "full_crypto")] +pub trait AppPair: AppKey + Pair::Public> { + /// The wrapped type which is just a plain instance of `Pair`. + type Generic: IsWrappedBy + Pair::Public as AppPublic>::Generic>; +} + +/// A application's signature. +pub trait AppSignature: AppKey + Eq + PartialEq + Debug + MaybeHash { + /// The wrapped type which is just a plain instance of `Signature`. + type Generic: IsWrappedBy + Eq + PartialEq + Debug + MaybeHash; +} + +/// A runtime interface for a public key. +pub trait RuntimePublic: Sized { + /// The signature that will be generated when signing with the corresponding private key. + type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone; + + /// Returns all public keys for the given key type in the keystore. + fn all(key_type: KeyTypeId) -> crate::Vec; + + /// Generate a public/private pair for the given key type with an optional `seed` and + /// store it in the keystore. + /// + /// The `seed` needs to be valid utf8. + /// + /// Returns the generated public key. + fn generate_pair(key_type: KeyTypeId, seed: Option>) -> Self; + + /// Sign the given message with the corresponding private key of this public key. + /// + /// The private key will be requested from the keystore using the given key type. + /// + /// Returns the signature or `None` if the private key could not be found or some other error + /// occurred. + fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option; + + /// Verify that the given signature matches the given message using this public key. + fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool; +} + +/// A runtime interface for an application's public key. +pub trait RuntimeAppPublic: Sized { + /// An identifier for this application-specific key type. + const ID: KeyTypeId; + + /// The signature that will be generated when signing with the corresponding private key. + type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone; + + /// Returns all public keys for this application in the keystore. + fn all() -> crate::Vec; + + /// Generate a public/private pair with an optional `seed` and store it in the keystore. + /// + /// The `seed` needs to be valid utf8. + /// + /// Returns the generated public key. + fn generate_pair(seed: Option>) -> Self; + + /// Sign the given message with the corresponding private key of this public key. + /// + /// The private key will be requested from the keystore. + /// + /// Returns the signature or `None` if the private key could not be found or some other error + /// occurred. + fn sign>(&self, msg: &M) -> Option; + + /// Verify that the given signature matches the given message using this public key. + fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool; +} + +/// Something that bound to a fixed `RuntimeAppPublic`. +pub trait BoundToRuntimeAppPublic { + /// The `RuntimeAppPublic` this type is bound to. + type Public: RuntimeAppPublic; +} diff --git a/primitives/application-crypto/test/Cargo.toml b/primitives/application-crypto/test/Cargo.toml new file mode 100644 index 0000000000000..1931e6f84be11 --- /dev/null +++ b/primitives/application-crypto/test/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "sp-application-crypto-test" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +description = "Integration tests for application-crypto" +publish = false + +[dependencies] +sp-core = { version = "2.0.0", default-features = false, path = "../../core" } +substrate-test-runtime-client = { version = "2.0.0", path = "../../../test-utils/runtime/client" } +sp-runtime = { version = "2.0.0", path = "../../runtime" } +sp-api = { version = "2.0.0", path = "../../api" } +sp-application-crypto = { version = "2.0.0", path = "../" } diff --git a/primitives/application-crypto/test/src/ed25519.rs b/primitives/application-crypto/test/src/ed25519.rs new file mode 100644 index 0000000000000..400edfd6ae440 --- /dev/null +++ b/primitives/application-crypto/test/src/ed25519.rs @@ -0,0 +1,40 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Integration tests for ed25519 + +use sp_runtime::generic::BlockId; +use sp_core::{testing::{KeyStore, ED25519}, crypto::Pair}; +use substrate_test_runtime_client::{ + TestClientBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt, + runtime::TestAPI, +}; +use sp_api::ProvideRuntimeApi; +use sp_application_crypto::ed25519::{AppPair, AppPublic}; + +#[test] +fn ed25519_works_in_runtime() { + let keystore = KeyStore::new(); + let test_client = TestClientBuilder::new().set_keystore(keystore.clone()).build(); + let (signature, public) = test_client.runtime_api() + .test_ed25519_crypto(&BlockId::Number(0)) + .expect("Tests `ed25519` crypto."); + + let key_pair = keystore.read().ed25519_key_pair(ED25519, &public.as_ref()) + .expect("There should be at a `ed25519` key in the keystore for the given public key."); + + assert!(AppPair::verify(&signature, "ed25519", &AppPublic::from(key_pair.public()))); +} diff --git a/primitives/application-crypto/test/src/lib.rs b/primitives/application-crypto/test/src/lib.rs new file mode 100644 index 0000000000000..cb045e81a7871 --- /dev/null +++ b/primitives/application-crypto/test/src/lib.rs @@ -0,0 +1,22 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Integration tests for application crypto + +#[cfg(test)] +mod ed25519; +#[cfg(test)] +mod sr25519; \ No newline at end of file diff --git a/primitives/application-crypto/test/src/sr25519.rs b/primitives/application-crypto/test/src/sr25519.rs new file mode 100644 index 0000000000000..49bb3c2a83640 --- /dev/null +++ b/primitives/application-crypto/test/src/sr25519.rs @@ -0,0 +1,41 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Integration tests for sr25519 + + +use sp_runtime::generic::BlockId; +use sp_core::{testing::{KeyStore, SR25519}, crypto::Pair}; +use substrate_test_runtime_client::{ + TestClientBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt, + runtime::TestAPI, +}; +use sp_api::ProvideRuntimeApi; +use sp_application_crypto::sr25519::{AppPair, AppPublic}; + +#[test] +fn sr25519_works_in_runtime() { + let keystore = KeyStore::new(); + let test_client = TestClientBuilder::new().set_keystore(keystore.clone()).build(); + let (signature, public) = test_client.runtime_api() + .test_sr25519_crypto(&BlockId::Number(0)) + .expect("Tests `sr25519` crypto."); + + let key_pair = keystore.read().sr25519_key_pair(SR25519, public.as_ref()) + .expect("There should be at a `sr25519` key in the keystore for the given public key."); + + assert!(AppPair::verify(&signature, "sr25519", &AppPublic::from(key_pair.public()))); +} diff --git a/primitives/arithmetic/Cargo.toml b/primitives/arithmetic/Cargo.toml new file mode 100644 index 0000000000000..71be14862a0ab --- /dev/null +++ b/primitives/arithmetic/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "sp-arithmetic" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +integer-sqrt = "0.1.2" +num-traits = { version = "0.2.8", default-features = false } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-debug-derive = { version = "2.0.0", default-features = false, path = "../../primitives/debug-derive" } + +[dev-dependencies] +primitive-types = "0.6.0" +rand = "0.7.2" +criterion = "0.3" + +[features] +default = ["std"] +std = [ + "codec/std", + "num-traits/std", + "sp-std/std", + "serde", + "sp-debug-derive/std", +] + +[[bench]] +name = "bench" +harness = false diff --git a/primitives/arithmetic/benches/bench.rs b/primitives/arithmetic/benches/bench.rs new file mode 100644 index 0000000000000..1025e883ef69e --- /dev/null +++ b/primitives/arithmetic/benches/bench.rs @@ -0,0 +1,80 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use criterion::{Criterion, Throughput, BenchmarkId, criterion_group, criterion_main}; +use sp_arithmetic::biguint::{BigUint, Single}; +use rand::Rng; + +fn random_big_uint(size: usize) -> BigUint { + let mut rng = rand::thread_rng(); + let digits: Vec<_> = (0..size).map(|_| rng.gen_range(0, Single::max_value())).collect(); + BigUint::from_limbs(&digits) +} + +fn bench_op(c: &mut Criterion, name: &str, op: F) { + let mut group = c.benchmark_group(name); + + for size in [2, 4, 6, 8, 10].iter() { + group.throughput(Throughput::Elements(*size)); + group.bench_with_input(BenchmarkId::from_parameter(size), size, |bencher, &size| { + let a = random_big_uint(size as usize); + let b = random_big_uint(size as usize); + + bencher.iter(|| op(&a, &b)); + }); + } +} + +fn bench_addition(c: &mut Criterion) { + bench_op(c, "addition", |a, b| { + let _ = a.clone().add(&b); + }); +} + +fn bench_subtraction(c: &mut Criterion) { + bench_op(c, "subtraction", |a, b| { + let _ = a.clone().sub(&b); + }); +} + +fn bench_multiplication(c: &mut Criterion) { + bench_op(c, "multiplication", |a, b| { + let _ = a.clone().mul(&b); + }); +} + +fn bench_division(c: &mut Criterion) { + let mut group = c.benchmark_group("division"); + + for size in [4, 6, 8, 10].iter() { + group.throughput(Throughput::Elements(*size)); + group.bench_with_input(BenchmarkId::from_parameter(size), size, |bencher, &size| { + let a = random_big_uint(size as usize); + let b = random_big_uint(rand::thread_rng().gen_range(2, size as usize)); + + bencher.iter(|| { + let _ = a.clone().div(&b, true); + }); + }); + } +} + +criterion_group!{ + name = benches; + config = Criterion::default(); + targets = bench_addition, bench_subtraction, bench_multiplication, bench_division +} +criterion_main!(benches); diff --git a/core/sr-arithmetic/fuzzer/.gitignore b/primitives/arithmetic/fuzzer/.gitignore similarity index 100% rename from core/sr-arithmetic/fuzzer/.gitignore rename to primitives/arithmetic/fuzzer/.gitignore diff --git a/core/sr-arithmetic/fuzzer/Cargo.lock b/primitives/arithmetic/fuzzer/Cargo.lock similarity index 80% rename from core/sr-arithmetic/fuzzer/Cargo.lock rename to primitives/arithmetic/fuzzer/Cargo.lock index f6ce6f1d4797d..de8a764f1f9b1 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.lock +++ b/primitives/arithmetic/fuzzer/Cargo.lock @@ -25,7 +25,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byte-slice-cast" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -53,18 +53,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "fixed-hash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -84,7 +84,7 @@ dependencies = [ [[package]] name = "impl-codec" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -153,9 +153,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-slice-cast 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -176,12 +176,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "primitive-types" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -189,7 +189,7 @@ name = "proc-macro-crate" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -229,7 +229,7 @@ name = "rand" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -250,7 +250,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -266,77 +266,63 @@ name = "rustc-hex" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "serde" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "sr-arithmetic" +name = "sp-arithmetic" version = "2.0.0" dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 2.0.0", + "sp-std 2.0.0", ] [[package]] -name = "sr-arithmetic-fuzzer" +name = "sp-arithmetic-fuzzer" version = "2.0.0" dependencies = [ "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-arithmetic 2.0.0", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-arithmetic 2.0.0", ] [[package]] -name = "sr-std" +name = "sp-debug-derive" version = "2.0.0" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sp-std" +version = "2.0.0" + [[package]] name = "static_assertions" -version = "0.2.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -351,7 +337,7 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.5" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -361,20 +347,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "uint" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -416,15 +403,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9633b74910e1870f50f5af189b08487195cdb83c0e27a71d6f64d5e09dd0538b" -"checksum byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7cbcbf18128ec71d8d4a0d054461ec59fff5b75b7d10a4c9b7c7cb1a379c3e77" +"checksum byte-slice-cast 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f6209f3b2c1edea170002e016d5ead6903d3bb0a846477f53bbeb614967a52a9" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6357b15872f8126e4ea7cf79d579473f132ccd2de239494ad1bf4aa892faea68" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72fe7539e2c5692c6989f2f9c0457e42f1e5768f96b85c87d273574670ae459f" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)" = "24c27b4aa3049d6d10d8e33d52c9d03ca9aec18f8a449b246f8c4a5b0c10fb34" -"checksum impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa0086251524c50fd53b32e7b05eb6d79e2f97221eaf0c53c0ca9c3096f21d3" +"checksum impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" @@ -436,7 +423,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "001fbbb956d8593f321c7a784f64d16b2c99b2657823976eea729006ad2c3668" "checksum parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42af752f59119656fa3cb31e8852ed24e895b968c0bdb41847da7f0cea6d155f" "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" -"checksum primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97b5a08dda18910f056e5c2060c034e77cab18e0bd7d895e44f03207af4c71d5" +"checksum primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0253db64c26d8b4e7896dd2063b516d2a1b9e0a5da26b5b78335f236d1e9522" "checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" @@ -447,16 +434,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" +"checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8" +"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" -"checksum uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8f0f47ed099f0db671ce82c66548c5de012e3c0cba3963514d1db15c7588701" +"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" +"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" +"checksum uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" diff --git a/primitives/arithmetic/fuzzer/Cargo.toml b/primitives/arithmetic/fuzzer/Cargo.toml new file mode 100644 index 0000000000000..e8568db3707fb --- /dev/null +++ b/primitives/arithmetic/fuzzer/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sp-arithmetic-fuzzer" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-arithmetic = { version = "2.0.0", path = ".." } +honggfuzz = "0.5" +primitive-types = "0.6" +num-bigint = "0.2" +num-traits = "0.2" + +[workspace] + +[[bin]] +name = "biguint" +path = "src/biguint.rs" + +[[bin]] +name = "rational128" +path = "src/rational128.rs" diff --git a/primitives/arithmetic/fuzzer/src/biguint.rs b/primitives/arithmetic/fuzzer/src/biguint.rs new file mode 100644 index 0000000000000..1e2ec2a502b56 --- /dev/null +++ b/primitives/arithmetic/fuzzer/src/biguint.rs @@ -0,0 +1,181 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run biguint`. `honggfuzz` CLI options can +//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. +//! +//! # Debugging a panic +//! Once a panic is found, it can be debugged with +//! `cargo hfuzz run-debug biguint hfuzz_workspace/biguint/*.fuzz`. +//! +//! # More infomation +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/). + +use honggfuzz::fuzz; +use sp_arithmetic::biguint::{BigUint, Single}; +use std::convert::TryFrom; + +fn main() { + loop { + fuzz!(|data: (Vec, Vec, bool)| { + let (mut digits_u, mut digits_v, return_remainder) = data; + + let mut u = BigUint::from_limbs(&digits_u); + let mut v = BigUint::from_limbs(&digits_v); + + u.lstrip(); + v.lstrip(); + + let ue = u128::try_from(u.clone()); + let ve = u128::try_from(v.clone()); + + digits_u.reverse(); + digits_v.reverse(); + + let num_u = num_bigint::BigUint::new(digits_u.clone()); + let num_v = num_bigint::BigUint::new(digits_v.clone()); + + if check_digit_lengths(&u, &v, 4) { + assert_eq!(u.cmp(&v), ue.cmp(&ve)); + assert_eq!(u.eq(&v), ue.eq(&ve)); + } + + if check_digit_lengths(&u, &v, 3) { + let expected = ue.unwrap() + ve.unwrap(); + let t = u.clone().add(&v); + assert_eq!( + u128::try_from(t.clone()).unwrap(), expected, + "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + + if check_digit_lengths(&u, &v, 4) { + let expected = ue.unwrap().checked_sub(ve.unwrap()); + let t = u.clone().sub(&v); + if expected.is_none() { + assert!(t.is_err()) + } else { + let t = t.unwrap(); + let expected = expected.unwrap(); + assert_eq!( + u128::try_from(t.clone()).unwrap(), expected, + "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + } + + if check_digit_lengths(&u, &v, 2) { + let expected = ue.unwrap() * ve.unwrap(); + let t = u.clone().mul(&v); + assert_eq!( + u128::try_from(t.clone()).unwrap(), expected, + "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + + if check_digit_lengths(&u, &v, 4) { + let (ue, ve) = (ue.unwrap(), ve.unwrap()); + if ve == 0 { + return; + } + let (q, r) = (ue / ve, ue % ve); + if let Some((qq, rr)) = u.clone().div(&v, true) { + assert_eq!( + u128::try_from(qq.clone()).unwrap(), q, + "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + assert_eq!( + u128::try_from(rr.clone()).unwrap(), r, + "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, + ); + } else if v.len() == 1 { + let qq = u.clone().div_unit(ve as Single); + assert_eq!( + u128::try_from(qq.clone()).unwrap(), q, + "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + } else if v.msb() != 0 && u.msb() != 0 && u.len() > v.len() { + panic!("div returned none for an unexpected reason"); + } + } + + // Test against num_bigint + + // Equality + + assert_eq!(u.cmp(&v), num_u.cmp(&num_v)); + + // Addition + + let w = u.clone().add(&v); + let num_w = num_u.clone() + &num_v; + + assert_biguints_eq(&w, &num_w); + + // Subtraction + + if let Ok(w) = u.clone().sub(&v) { + let num_w = num_u.clone() - &num_v; + + assert_biguints_eq(&w, &num_w); + } + + // Multiplication + + let w = u.clone().mul(&v); + let num_w = num_u.clone() * &num_v; + + assert_biguints_eq(&w, &num_w); + + // Division + + if v.len() == 1 && v.get(0) != 0 { + let w = u.clone().div_unit(v.get(0)); + let num_w = num_u.clone() / &num_v; + assert_biguints_eq(&w, &num_w); + } else if u.len() > v.len() && v.len() > 0 { + let num_remainder = num_u.clone() % num_v.clone(); + + let (w, remainder) = u.clone().div(&v, return_remainder).unwrap(); + let num_w = num_u.clone() / &num_v; + + assert_biguints_eq(&w, &num_w); + + if return_remainder { + assert_biguints_eq(&remainder, &num_remainder); + } + } + }); + } +} + +fn check_digit_lengths(u: &BigUint, v: &BigUint, max_limbs: usize) -> bool { + 1 <= u.len() && u.len() <= max_limbs && 1 <= v.len() && v.len() <= max_limbs +} + +fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { + let mut a = a.clone(); + a.lstrip(); + + // `num_bigint::BigUint` doesn't expose it's internals, so we need to convert into that to + // compare. + let limbs = (0 .. a.len()).map(|i| a.get(i)).collect(); + let num_a = num_bigint::BigUint::new(limbs); + + assert!(&num_a == b, "\narithmetic: {:?}\nnum-bigint: {:?}", a, b); +} diff --git a/primitives/arithmetic/fuzzer/src/rational128.rs b/primitives/arithmetic/fuzzer/src/rational128.rs new file mode 100644 index 0000000000000..60aa315c18aee --- /dev/null +++ b/primitives/arithmetic/fuzzer/src/rational128.rs @@ -0,0 +1,77 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run rational128`. `honggfuzz` CLI options can +//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. +//! +//! # Debugging a panic +//! Once a panic is found, it can be debugged with +//! `cargo hfuzz run-debug rational128 hfuzz_workspace/rational128/*.fuzz`. +//! +//! # More infomation +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/). + +use honggfuzz::fuzz; +use sp_arithmetic::{helpers_128bit::multiply_by_rational, traits::Zero}; + +fn main() { + loop { + fuzz!(|data: ([u8; 16], [u8; 16], [u8; 16])| { + let (a_bytes, b_bytes, c_bytes) = data; + let (a, b, c) = ( + u128::from_be_bytes(a_bytes), + u128::from_be_bytes(b_bytes), + u128::from_be_bytes(c_bytes), + ); + + println!("++ Equation: {} * {} / {}", a, b, c); + + // The point of this fuzzing is to make sure that `multiply_by_rational` is 100% + // accurate as long as the value fits in a u128. + if let Ok(result) = multiply_by_rational(a, b, c) { + let truth = mul_div(a, b, c); + + if result != truth && result != truth + 1 { + println!("++ Expected {}", truth); + println!("+++++++ Got {}", result); + panic!(); + } + } + }) + } +} + +fn mul_div(a: u128, b: u128, c: u128) -> u128 { + use primitive_types::U256; + if a.is_zero() { + return Zero::zero(); + } + let c = c.max(1); + + // e for extended + let ae: U256 = a.into(); + let be: U256 = b.into(); + let ce: U256 = c.into(); + + let r = ae * be / ce; + if r > u128::max_value().into() { + a + } else { + r.as_u128() + } +} diff --git a/primitives/arithmetic/src/biguint.rs b/primitives/arithmetic/src/biguint.rs new file mode 100644 index 0000000000000..6c3ca58a52d1f --- /dev/null +++ b/primitives/arithmetic/src/biguint.rs @@ -0,0 +1,735 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Infinite precision unsigned integer for substrate runtime. + +use num_traits::Zero; +use sp_std::{cmp::Ordering, ops, prelude::*, cell::RefCell, convert::TryFrom}; + +// A sensible value for this would be half of the dword size of the host machine. Since the +// runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively +// should yield the most performance. +/// Representation of a single limb. +pub type Single = u32; +/// Representation of two limbs. +pub type Double = u64; +/// Difference in the number of bits of [`Single`] and [`Double`]. +const SHIFT: usize = 32; +/// short form of _Base_. Analogous to the value 10 in base-10 decimal numbers. +const B: Double = Single::max_value() as Double + 1; + +/// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers. +pub fn split(a: Double) -> (Single, Single) { + let al = a as Single; + let ah = (a >> SHIFT) as Single; + (ah, al) +} + +/// Assumed as a given primitive. +/// +/// Multiplication of two singles, which at most yields 1 double. +pub fn mul_single(a: Single, b: Single) -> Double { + let a: Double = a.into(); + let b: Double = b.into(); + a * b +} + +/// Assumed as a given primitive. +/// +/// Addition of two singles, which at most takes a single limb of result and a carry, +/// returned as a tuple respectively. +pub fn add_single(a: Single, b: Single) -> (Single, Single) { + let a: Double = a.into(); + let b: Double = b.into(); + let q = a + b; + let (carry, r) = split(q); + (r, carry) +} + +/// Assumed as a given primitive. +/// +/// Division of double by a single limb. Always returns a double limb of quotient and a single +/// limb of remainder. +fn div_single(a: Double, b: Single) -> (Double, Single) { + let b: Double = b.into(); + let q = a / b; + let r = a % b; + // both conversions are trivially safe. + (q, r as Single) +} + +/// Simple wrapper around an infinitely large integer, represented as limbs of [`Single`]. +#[derive(Clone, Default)] +pub struct BigUint { + /// digits (limbs) of this number (sorted as msb -> lsd). + pub(crate) digits: Vec, +} + +impl BigUint { + /// Create a new instance with `size` limbs. This prevents any number with zero limbs to be + /// created. + /// + /// The behavior of the type is undefined with zero limbs. + pub fn with_capacity(size: usize) -> Self { + Self { digits: vec![0; size.max(1)] } + } + + /// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is + /// used. + pub fn from_limbs(limbs: &[Single]) -> Self { + if !limbs.is_empty() { + Self { digits: limbs.to_vec() } + } else { + Zero::zero() + } + } + + /// Number of limbs. + pub fn len(&self) -> usize { self.digits.len() } + + /// A naive getter for limb at `index`. Note that the order is lsb -> msb. + /// + /// #### Panics + /// + /// This panics if index is out of range. + pub fn get(&self, index: usize) -> Single { + self.digits[self.len() - 1 - index] + } + + /// A naive getter for limb at `index`. Note that the order is lsb -> msb. + pub fn checked_get(&self, index: usize) -> Option { + let i = self.len().checked_sub(1)?; + let j = i.checked_sub(index)?; + self.digits.get(j).cloned() + } + + /// A naive setter for limb at `index`. Note that the order is lsb -> msb. + /// + /// #### Panics + /// + /// This panics if index is out of range. + pub fn set(&mut self, index: usize, value: Single) { + let len = self.digits.len(); + self.digits[len - 1 - index] = value; + } + + /// returns the least significant limb of the number. + /// + /// #### Panics + /// + /// While the constructor of the type prevents this, this can panic if `self` has no digits. + pub fn lsb(&self) -> Single { + self.digits[self.len() - 1] + } + + /// returns the most significant limb of the number. + /// + /// #### Panics + /// + /// While the constructor of the type prevents this, this can panic if `self` has no digits. + pub fn msb(&self) -> Single { + self.digits[0] + } + + /// Strips zeros from the left side (the most significant limbs) of `self`, if any. + pub fn lstrip(&mut self) { + // by definition, a big-int number should never have leading zero limbs. This function + // has the ability to cause this. There is nothing to do if the number already has 1 + // limb only. call it a day and return. + if self.len().is_zero() { return; } + let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(0); + + if index > 0 { + self.digits = self.digits[index..].to_vec() + } + } + + /// Zero-pad `self` from left to reach `size` limbs. Will not make any difference if `self` + /// is already bigger than `size` limbs. + pub fn lpad(&mut self, size: usize) { + let n = self.len(); + if n >= size { return; } + let pad = size - n; + let mut new_digits = (0..pad).map(|_| 0).collect::>(); + new_digits.extend(self.digits.iter()); + self.digits = new_digits; + } + + /// Adds `self` with `other`. self and other do not have to have any particular size. Given + /// that the `n = max{size(self), size(other)}`, it will produce a number with `n + 1` + /// limbs. + /// + /// This function does not strip the output and returns the original allocated `n + 1` + /// limbs. The caller may strip the output if desired. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn add(self, other: &Self) -> Self { + let n = self.len().max(other.len()); + let mut k: Double = 0; + let mut w = Self::with_capacity(n + 1); + + for j in 0..n { + let u = Double::from(self.checked_get(j).unwrap_or(0)); + let v = Double::from(other.checked_get(j).unwrap_or(0)); + let s = u + v + k; + w.set(j, (s % B) as Single); + k = s / B; + } + // k is always 0 or 1. + w.set(n, k as Single); + w + } + + /// Subtracts `other` from `self`. self and other do not have to have any particular size. + /// Given that the `n = max{size(self), size(other)}`, it will produce a number of size `n`. + /// + /// If `other` is bigger than `self`, `Err(B - borrow)` is returned. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn sub(self, other: &Self) -> Result { + let n = self.len().max(other.len()); + let mut k = 0; + let mut w = Self::with_capacity(n); + for j in 0..n { + let s = { + let u = Double::from(self.checked_get(j).unwrap_or(0)); + let v = Double::from(other.checked_get(j).unwrap_or(0)); + let mut needs_borrow = false; + let mut t = 0; + + if let Some(v) = u.checked_sub(v) { + if let Some(v2) = v.checked_sub(k) { + t = v2 % B; + k = 0; + } else { + needs_borrow = true; + } + } else { + needs_borrow = true; + } + if needs_borrow { + t = u + B - v - k; + k = 1; + } + t + }; + // PROOF: t either comes from `v2 % B`, or from `u + B - v - k`. The former is + // trivial. The latter will not overflow this branch will only happen if the sum of + // `u - v - k` part has been negative, hence `u + B - v - k < b`. + w.set(j, s as Single); + } + + if k.is_zero() { + Ok(w) + } else { + Err(w) + } + } + + /// Multiplies n-limb number `self` with m-limb number `other`. + /// + /// The resulting number will always have `n + m` limbs. + /// + /// This function does not strip the output and returns the original allocated `n + m` + /// limbs. The caller may strip the output if desired. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn mul(self, other: &Self) -> Self { + let n = self.len(); + let m = other.len(); + let mut w = Self::with_capacity(m + n); + + for j in 0..n { + if self.get(j) == 0 { + // Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if + // otherwise. + continue; + } + + let mut k = 0; + for i in 0..m { + // PROOF: (B−1) × (B−1) + (B−1) + (B−1) = B^2 −1 < B^2. addition is safe. + let t = + mul_single(self.get(j), other.get(i)) + + Double::from(w.get(i + j)) + + Double::from(k); + w.set(i + j, (t % B) as Single); + // PROOF: (B^2 - 1) / B < B. conversion is safe. + k = (t / B) as Single; + } + w.set(j + m, k); + } + w + } + + /// Divides `self` by a single limb `other`. This can be used in cases where the original + /// division cannot work due to the divisor (`other`) being just one limb. + /// + /// Invariant: `other` cannot be zero. + pub fn div_unit(self, mut other: Single) -> Self { + other = other.max(1); + let n = self.len(); + let mut out = Self::with_capacity(n); + let mut r: Single = 0; + // PROOF: (B-1) * B + (B-1) still fits in double + let with_r = |x: Double, r: Single| { Double::from(r) * B + x }; + for d in (0..n).rev() { + let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ; + out.set(d, q as Single); + r = rr; + } + out + } + + /// Divides an `n + m` limb self by a `n` limb `other`. The result is a `m + 1` limb + /// quotient and a `n` limb remainder, if enabled by passing `true` in `rem` argument, both + /// in the form of an option's `Ok`. + /// + /// - requires `other` to be stripped and have no leading zeros. + /// - requires `self` to be stripped and have no leading zeros. + /// - requires `other` to have at least two limbs. + /// - requires `self` to have a greater length compared to `other`. + /// + /// All arguments are examined without being stripped for the above conditions. If any of + /// the above fails, `None` is returned.` + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn div(self, other: &Self, rem: bool) -> Option<(Self, Self)> { + if other.len() <= 1 + || other.msb() == 0 + || self.msb() == 0 + || self.len() <= other.len() + { + return None + } + let n = other.len(); + let m = self.len() - n; + + let mut q = Self::with_capacity(m + 1); + let mut r = Self::with_capacity(n); + + // PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are + // safe. + let normalizer_bits = other.msb().leading_zeros() as Single; + let normalizer = (2 as Single).pow(normalizer_bits as u32) as Single; + + // step D1. + let mut self_norm = self.mul(&Self::from(normalizer)); + let mut other_norm = other.clone().mul(&Self::from(normalizer)); + + // defensive only; the mul implementation should always create this. + self_norm.lpad(n + m + 1); + other_norm.lstrip(); + + // step D2. + for j in (0..=m).rev() { + // step D3.0 Find an estimate of q[j], named qhat. + let (qhat, rhat) = { + // PROOF: this always fits into `Double`. In the context of Single = u8, and + // Double = u16, think of 255 * 256 + 255 which is just u16::max_value(). + let dividend = + Double::from(self_norm.get(j + n)) + * B + + Double::from(self_norm.get(j + n - 1)); + let divisor = other_norm.get(n - 1); + div_single(dividend, divisor) + }; + + // D3.1 test qhat + // replace qhat and rhat with RefCells. This helps share state with the closure + let qhat = RefCell::new(qhat); + let rhat = RefCell::new(Double::from(rhat)); + + let test = || { + // decrease qhat if it is bigger than the base (B) + let qhat_local = *qhat.borrow(); + let rhat_local = *rhat.borrow(); + let predicate_1 = qhat_local >= B; + let predicate_2 = { + let lhs = qhat_local * Double::from(other_norm.get(n - 2)); + let rhs = B * rhat_local + Double::from(self_norm.get(j + n - 2)); + lhs > rhs + }; + if predicate_1 || predicate_2 { + *qhat.borrow_mut() -= 1; + *rhat.borrow_mut() += Double::from(other_norm.get(n - 1)); + true + } else { + false + } + }; + + test(); + while (*rhat.borrow() as Double) < B { + if !test() { break; } + } + + let qhat = qhat.into_inner(); + // we don't need rhat anymore. just let it go out of scope when it does. + + // step D4 + let lhs = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; + let rhs = other_norm.clone().mul(&Self::from(qhat)); + + let maybe_sub = lhs.sub(&rhs); + let mut negative = false; + let sub = match maybe_sub { + Ok(t) => t, + Err(t) => { negative = true; t } + }; + (j..=j+n).for_each(|d| { self_norm.set(d, sub.get(d - j)); }); + + // step D5 + // PROOF: the `test()` specifically decreases qhat until it is below `B`. conversion + // is safe. + q.set(j, qhat as Single); + + // step D6: add back if negative happened. + if negative { + q.set(j, q.get(j) - 1); + let u = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; + let r = other_norm.clone().add(&u); + (j..=j+n).rev().for_each(|d| { self_norm.set(d, r.get(d - j)); }) + } + } + + // if requested, calculate remainder. + if rem { + // undo the normalization. + if normalizer_bits > 0 { + let s = SHIFT as u32; + let nb = normalizer_bits; + for d in 0..n-1 { + let v = self_norm.get(d) >> nb + | self_norm.get(d + 1).overflowing_shl(s - nb).0; + r.set(d, v); + } + r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits); + } else { + r = self_norm; + } + } + + Some((q, r)) + } +} + +impl sp_std::fmt::Debug for BigUint { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + write!( + f, + "BigUint {{ {:?} ({:?})}}", + self.digits, + u128::try_from(self.clone()).unwrap_or(0), + ) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + Ok(()) + } + +} + +impl PartialEq for BigUint { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for BigUint {} + +impl Ord for BigUint { + fn cmp(&self, other: &Self) -> Ordering { + let lhs_first = self.digits.iter().position(|&e| e != 0); + let rhs_first = other.digits.iter().position(|&e| e != 0); + + match (lhs_first, rhs_first) { + // edge cases that should not happen. This basically means that one or both were + // zero. + (None, None) => Ordering::Equal, + (Some(_), None) => Ordering::Greater, + (None, Some(_)) => Ordering::Less, + (Some(lhs_idx), Some(rhs_idx)) => { + let lhs = &self.digits[lhs_idx..]; + let rhs = &other.digits[rhs_idx..]; + let len_cmp = lhs.len().cmp(&rhs.len()); + match len_cmp { + Ordering::Equal => lhs.cmp(rhs), + _ => len_cmp, + } + } + } + } +} + +impl PartialOrd for BigUint { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl ops::Add for BigUint { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + self.add(&rhs) + } +} + +impl ops::Sub for BigUint { + type Output = Self; + fn sub(self, rhs: Self) -> Self::Output { + self.sub(&rhs).unwrap_or_else(|e| e) + } +} + +impl ops::Mul for BigUint { + type Output = Self; + fn mul(self, rhs: Self) -> Self::Output { + self.mul(&rhs) + } +} + +impl Zero for BigUint { + fn zero() -> Self { + Self { digits: vec![Zero::zero()] } + } + + fn is_zero(&self) -> bool { + self.digits.iter().all(|d| d.is_zero()) + } +} + +macro_rules! impl_try_from_number_for { + ($([$type:ty, $len:expr]),+) => { + $( + impl TryFrom for $type { + type Error = &'static str; + fn try_from(mut value: BigUint) -> Result<$type, Self::Error> { + value.lstrip(); + let error_message = concat!("cannot fit a number into ", stringify!($type)); + if value.len() * SHIFT > $len { + Err(error_message) + } else { + let mut acc: $type = Zero::zero(); + for (i, d) in value.digits.iter().rev().cloned().enumerate() { + let d: $type = d.into(); + acc += d << (SHIFT * i); + } + Ok(acc) + } + } + } + )* + }; +} +// can only be implemented for sizes bigger than two limb. +impl_try_from_number_for!([u128, 128], [u64, 64]); + +macro_rules! impl_from_for_smaller_than_word { + ($($type:ty),+) => { + $(impl From<$type> for BigUint { + fn from(a: $type) -> Self { + Self { digits: vec! [a.into()] } + } + })* + } +} +impl_from_for_smaller_than_word!(u8, u16, Single); + +impl From for BigUint { + fn from(a: Double) -> Self { + let (ah, al) = split(a); + Self { digits: vec![ah, al] } + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + + fn with_limbs(n: usize) -> BigUint { + BigUint { digits: vec![1; n] } + } + + #[test] + fn split_works() { + let a = SHIFT / 2; + let b = SHIFT * 3 / 2; + let num: Double = 1 << a | 1 << b; + // example when `Single = u8` + // assert_eq!(num, 0b_0001_0000_0001_0000) + assert_eq!(split(num), (1 << a, 1 << a)); + } + + #[test] + fn strip_works() { + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![1, 0] }); + + let mut a = BigUint::from_limbs(&[0, 0, 1]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![1] }); + + let mut a = BigUint::from_limbs(&[0, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![0] }); + + let mut a = BigUint::from_limbs(&[0, 0, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![0] }); + } + + #[test] + fn lpad_works() { + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(2); + assert_eq!(a.digits, vec![0, 1, 0]); + + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(3); + assert_eq!(a.digits, vec![0, 1, 0]); + + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(4); + assert_eq!(a.digits, vec![0, 0, 1, 0]); + } + + #[test] + fn equality_works() { + assert_eq!( + BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + true, + ); + assert_eq!( + BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + false, + ); + assert_eq!( + BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + true, + ); + } + + #[test] + fn ordering_works() { + assert!(BigUint { digits: vec![0] } < BigUint { digits: vec![1] }); + assert!(BigUint { digits: vec![0] } == BigUint { digits: vec![0] }); + assert!(BigUint { digits: vec![] } == BigUint { digits: vec![0] }); + assert!(BigUint { digits: vec![] } == BigUint { digits: vec![] }); + assert!(BigUint { digits: vec![] } < BigUint { digits: vec![1] }); + + assert!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); + + assert!(BigUint { digits: vec![1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![0, 1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![1, 2, 1, 0] } > BigUint { digits: vec![1, 2, 3] }); + + assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] }); + } + + #[test] + fn can_try_build_numbers_from_types() { + use sp_std::convert::TryFrom; + assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1); + assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::max_value() as u64 + 2); + assert_eq!( + u64::try_from(with_limbs(3)).unwrap_err(), + "cannot fit a number into u64", + ); + assert_eq!( + u128::try_from(with_limbs(3)).unwrap(), + u32::max_value() as u128 + u64::max_value() as u128 + 3 + ); + } + + #[test] + fn zero_works() { + assert_eq!(BigUint::zero(), BigUint { digits: vec![0] }); + assert_eq!(BigUint { digits: vec![0, 1, 0] }.is_zero(), false); + assert_eq!(BigUint { digits: vec![0, 0, 0] }.is_zero(), true); + + let a = BigUint::zero(); + let b = BigUint::zero(); + let c = a * b; + assert_eq!(c.digits, vec![0, 0]); + } + + #[test] + fn sub_negative_works() { + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(5 as Single)).unwrap(), + BigUint::from(5 as Single) + ); + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(10 as Single)).unwrap(), + BigUint::from(0 as Single) + ); + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(13 as Single)).unwrap_err(), + BigUint::from((B - 3) as Single), + ); + } + + #[test] + fn mul_always_appends_one_digit() { + let a = BigUint::from(10 as Single); + let b = BigUint::from(4 as Single); + assert_eq!(a.len(), 1); + assert_eq!(b.len(), 1); + + let n = a.mul(&b); + + assert_eq!(n.len(), 2); + assert_eq!(n.digits, vec![0, 40]); + } + + #[test] + fn div_conditions_work() { + let a = BigUint { digits: vec![2] }; + let b = BigUint { digits: vec![1, 2] }; + let c = BigUint { digits: vec![1, 1, 2] }; + let d = BigUint { digits: vec![0, 2] }; + let e = BigUint { digits: vec![0, 1, 1, 2] }; + + assert!(a.clone().div(&b, true).is_none()); + assert!(c.clone().div(&a, true).is_none()); + assert!(c.clone().div(&d, true).is_none()); + assert!(e.clone().div(&a, true).is_none()); + + assert!(c.clone().div(&b, true).is_some()); + } + + #[test] + fn div_unit_works() { + let a = BigUint { digits: vec![100] }; + let b = BigUint { digits: vec![1, 100] }; + + assert_eq!(a.clone().div_unit(1), a); + assert_eq!(a.clone().div_unit(0), a); + assert_eq!(a.clone().div_unit(2), BigUint::from(50 as Single)); + assert_eq!(a.clone().div_unit(7), BigUint::from(14 as Single)); + + assert_eq!(b.clone().div_unit(1), b); + assert_eq!(b.clone().div_unit(0), b); + assert_eq!(b.clone().div_unit(2), BigUint::from(((B + 100) / 2) as Single)); + assert_eq!(b.clone().div_unit(7), BigUint::from(((B + 100) / 7) as Single)); + + } +} diff --git a/primitives/arithmetic/src/fixed64.rs b/primitives/arithmetic/src/fixed64.rs new file mode 100644 index 0000000000000..eea1ab68a3bb2 --- /dev/null +++ b/primitives/arithmetic/src/fixed64.rs @@ -0,0 +1,326 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sp_std::{ + ops, prelude::*, + convert::{TryFrom, TryInto}, +}; +use codec::{Encode, Decode}; +use crate::{ + Perbill, + traits::{ + SaturatedConversion, CheckedSub, CheckedAdd, CheckedDiv, Bounded, UniqueSaturatedInto, Saturating + } +}; + +/// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036] +/// with fixed point accuracy of one billion. +#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Fixed64(i64); + +/// The accuracy of the `Fixed64` type. +const DIV: i64 = 1_000_000_000; + +impl Fixed64 { + /// creates self from a natural number. + /// + /// Note that this might be lossy. + pub fn from_natural(int: i64) -> Self { + Self(int.saturating_mul(DIV)) + } + + /// Return the accuracy of the type. Given that this function returns the value `X`, it means + /// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`. + pub fn accuracy() -> i64 { + DIV + } + + /// Consume self and return the inner value. + /// + /// This should only be used for testing. + #[cfg(any(feature = "std", test))] + pub fn into_inner(self) -> i64 { self.0 } + + /// Raw constructor. Equal to `parts / 1_000_000_000`. + pub fn from_parts(parts: i64) -> Self { + Self(parts) + } + + /// creates self from a rational number. Equal to `n/d`. + /// + /// Note that this might be lossy. + pub fn from_rational(n: i64, d: u64) -> Self { + Self( + (i128::from(n).saturating_mul(i128::from(DIV)) / i128::from(d).max(1)) + .try_into() + .unwrap_or_else(|_| Bounded::max_value()) + ) + } + + /// Performs a saturated multiply and accumulate by unsigned number. + /// + /// Returns a saturated `int + (self * int)`. + pub fn saturated_multiply_accumulate(self, int: N) -> N + where + N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + + ops::Rem + ops::Div + ops::Mul + + ops::Add, + { + let div = DIV as u64; + let positive = self.0 > 0; + // safe to convert as absolute value. + let parts = self.0.checked_abs().map(|v| v as u64).unwrap_or(i64::max_value() as u64 + 1); + + + // will always fit. + let natural_parts = parts / div; + // might saturate. + let natural_parts: N = natural_parts.saturated_into(); + // fractional parts can always fit into u32. + let perbill_parts = (parts % div) as u32; + + let n = int.clone().saturating_mul(natural_parts); + let p = Perbill::from_parts(perbill_parts) * int.clone(); + + // everything that needs to be either added or subtracted from the original weight. + let excess = n.saturating_add(p); + + if positive { + int.saturating_add(excess) + } else { + int.saturating_sub(excess) + } + } +} + +impl Saturating for Fixed64 { + fn saturating_add(self, rhs: Self) -> Self { + Self(self.0.saturating_add(rhs.0)) + } + fn saturating_mul(self, rhs: Self) -> Self { + Self(self.0.saturating_mul(rhs.0) / DIV) + } + fn saturating_sub(self, rhs: Self) -> Self { + Self(self.0.saturating_sub(rhs.0)) + } +} + +/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait +/// for safe addition. +impl ops::Add for Fixed64 { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } +} + +/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait +/// for safe subtraction. +impl ops::Sub for Fixed64 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } +} + +/// Note that this is a standard, _potentially-panicking_, implementation. Use `CheckedDiv` trait +/// for safe division. +impl ops::Div for Fixed64 { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + if rhs.0 == 0 { + let zero = 0; + return Fixed64::from_parts( self.0 / zero); + } + let (n, d) = if rhs.0 < 0 { + (-self.0, rhs.0.abs() as u64) + } else { + (self.0, rhs.0 as u64) + }; + Fixed64::from_rational(n, d) + } +} + +impl CheckedSub for Fixed64 { + fn checked_sub(&self, rhs: &Self) -> Option { + self.0.checked_sub(rhs.0).map(Self) + } +} + +impl CheckedAdd for Fixed64 { + fn checked_add(&self, rhs: &Self) -> Option { + self.0.checked_add(rhs.0).map(Self) + } +} + +impl CheckedDiv for Fixed64 { + fn checked_div(&self, rhs: &Self) -> Option { + if rhs.0 == 0 { + None + } else { + Some(*self / *rhs) + } + } +} + +impl sp_std::fmt::Debug for Fixed64 { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "Fixed64({},{})", self.0 / DIV, (self.0 % DIV) / 1000) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn max() -> Fixed64 { + Fixed64::from_parts(i64::max_value()) + } + + #[test] + fn fixed64_semantics() { + assert_eq!(Fixed64::from_rational(5, 2).0, 5 * 1_000_000_000 / 2); + assert_eq!(Fixed64::from_rational(5, 2), Fixed64::from_rational(10, 4)); + assert_eq!(Fixed64::from_rational(5, 0), Fixed64::from_rational(5, 1)); + + // biggest value that can be created. + assert_ne!(max(), Fixed64::from_natural(9_223_372_036)); + assert_eq!(max(), Fixed64::from_natural(9_223_372_037)); + } + + #[test] + fn fixed_64_growth_decrease_curve() { + let test_set = vec![0u32, 1, 10, 1000, 1_000_000_000]; + + // negative (1/2) + let mut fm = Fixed64::from_rational(-1, 2); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i) as i32, i as i32 - i as i32 / 2); + }); + + // unit (1) multiplier + fm = Fixed64::from_parts(0); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i); + }); + + // i.5 multiplier + fm = Fixed64::from_rational(1, 2); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i * 3 / 2); + }); + + // dual multiplier + fm = Fixed64::from_rational(1, 1); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i * 2); + }); + } + + macro_rules! saturating_mul_acc_test { + ($num_type:tt) => { + assert_eq!( + Fixed64::from_rational(100, 1).saturated_multiply_accumulate(10 as $num_type), + 1010, + ); + assert_eq!( + Fixed64::from_rational(100, 2).saturated_multiply_accumulate(10 as $num_type), + 510, + ); + assert_eq!( + Fixed64::from_rational(100, 3).saturated_multiply_accumulate(0 as $num_type), + 0, + ); + assert_eq!( + Fixed64::from_rational(5, 1).saturated_multiply_accumulate($num_type::max_value()), + $num_type::max_value() + ); + assert_eq!( + max().saturated_multiply_accumulate($num_type::max_value()), + $num_type::max_value() + ); + } + } + + #[test] + fn fixed64_multiply_accumulate_works() { + saturating_mul_acc_test!(u32); + saturating_mul_acc_test!(u64); + saturating_mul_acc_test!(u128); + } + + #[test] + fn div_works() { + let a = Fixed64::from_rational(12, 10); + let b = Fixed64::from_rational(10, 1); + assert_eq!(a / b, Fixed64::from_rational(12, 100)); + + let a = Fixed64::from_rational(12, 10); + let b = Fixed64::from_rational(1, 100); + assert_eq!(a / b, Fixed64::from_rational(120, 1)); + + let a = Fixed64::from_rational(12, 100); + let b = Fixed64::from_rational(10, 1); + assert_eq!(a / b, Fixed64::from_rational(12, 1000)); + + let a = Fixed64::from_rational(12, 100); + let b = Fixed64::from_rational(1, 100); + assert_eq!(a / b, Fixed64::from_rational(12, 1)); + + let a = Fixed64::from_rational(-12, 10); + let b = Fixed64::from_rational(10, 1); + assert_eq!(a / b, Fixed64::from_rational(-12, 100)); + + let a = Fixed64::from_rational(12, 10); + let b = Fixed64::from_rational(-10, 1); + assert_eq!(a / b, Fixed64::from_rational(-12, 100)); + + let a = Fixed64::from_rational(-12, 10); + let b = Fixed64::from_rational(-10, 1); + assert_eq!(a / b, Fixed64::from_rational(12, 100)); + } + + #[test] + #[should_panic(expected = "attempt to divide by zero")] + fn div_zero() { + let a = Fixed64::from_rational(12, 10); + let b = Fixed64::from_natural(0); + let _ = a / b; + } + + #[test] + fn checked_div_zero() { + let a = Fixed64::from_rational(12, 10); + let b = Fixed64::from_natural(0); + assert_eq!(a.checked_div(&b), None); + } + + #[test] + fn checked_div_non_zero() { + let a = Fixed64::from_rational(12, 10); + let b = Fixed64::from_rational(1, 100); + assert_eq!(a.checked_div(&b), Some(Fixed64::from_rational(120, 1))); + } +} diff --git a/core/sr-arithmetic/src/helpers_128bit.rs b/primitives/arithmetic/src/helpers_128bit.rs similarity index 97% rename from core/sr-arithmetic/src/helpers_128bit.rs rename to primitives/arithmetic/src/helpers_128bit.rs index 10cc94ae777e6..bf8315b9b6648 100644 --- a/core/sr-arithmetic/src/helpers_128bit.rs +++ b/primitives/arithmetic/src/helpers_128bit.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ use crate::biguint; use num_traits::Zero; -use rstd::{cmp::{min, max}, convert::TryInto, mem}; +use sp_std::{cmp::{min, max}, convert::TryInto, mem}; /// Helper gcd function used in Rational128 implementation. pub fn gcd(a: u128, b: u128) -> u128 { diff --git a/primitives/arithmetic/src/lib.rs b/primitives/arithmetic/src/lib.rs new file mode 100644 index 0000000000000..0beef84758feb --- /dev/null +++ b/primitives/arithmetic/src/lib.rs @@ -0,0 +1,44 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Minimal fixed point arithmetic primitives and types for runtime. + +#![cfg_attr(not(feature = "std"), no_std)] + +/// Copied from `sp-runtime` and documented there. +#[cfg(test)] +macro_rules! assert_eq_error_rate { + ($x:expr, $y:expr, $error:expr $(,)?) => { + assert!( + ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), + "{:?} != {:?} (with error rate {:?})", + $x, + $y, + $error, + ); + }; +} + +pub mod biguint; +pub mod helpers_128bit; +pub mod traits; +mod per_things; +mod fixed64; +mod rational128; + +pub use fixed64::Fixed64; +pub use per_things::{Percent, Permill, Perbill, Perquintill}; +pub use rational128::Rational128; diff --git a/core/sr-arithmetic/src/per_things.rs b/primitives/arithmetic/src/per_things.rs similarity index 97% rename from core/sr-arithmetic/src/per_things.rs rename to primitives/arithmetic/src/per_things.rs index 2dd1e62d0b4db..554f3c3c2128b 100644 --- a/core/sr-arithmetic/src/per_things.rs +++ b/primitives/arithmetic/src/per_things.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,18 +17,18 @@ #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; -use rstd::{ops, prelude::*, convert::TryInto}; +use sp_std::{ops, prelude::*, convert::TryInto}; use codec::{Encode, Decode, CompactAs}; use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating}; -use substrate_debug_derive::RuntimeDebug; +use sp_debug_derive::RuntimeDebug; macro_rules! implement_per_thing { ($name:ident, $test_mod:ident, [$($test_units:tt),+], $max:tt, $type:ty, $upper_type:ty, $title:expr $(,)?) => { /// A fixed point representation of a number between in the range [0, 1]. /// #[doc = $title] - #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Ord, PartialOrd))] - #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, CompactAs)] + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] + #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, CompactAs)] pub struct $name($type); impl $name { @@ -54,7 +54,7 @@ macro_rules! implement_per_thing { Self([parts, $max][(parts > $max) as usize]) } - /// Converts from a percent. Equal to `x / 100`. + /// Converts a percent into `Self`. Equal to `x / 100`. /// /// This can be created at compile time. pub const fn from_percent(x: $type) -> Self { @@ -69,7 +69,7 @@ macro_rules! implement_per_thing { Self::from_rational_approximation(p, q) } - /// Converts a fraction into `Permill`. + /// Converts a fraction into `Self`. #[cfg(feature = "std")] pub fn from_fraction(x: f64) -> Self { Self((x * ($max as f64)) as $type) } @@ -299,7 +299,6 @@ macro_rules! implement_per_thing { assert_eq!($name::from_percent(34) * 10u64, 3); assert_eq!($name::from_percent(35) * 10u64, 3); assert_eq!($name::from_percent(36) * 10u64, 4); - assert_eq!($name::from_percent(36) * 10u64, 4); } #[test] diff --git a/primitives/arithmetic/src/rational128.rs b/primitives/arithmetic/src/rational128.rs new file mode 100644 index 0000000000000..248df70794c63 --- /dev/null +++ b/primitives/arithmetic/src/rational128.rs @@ -0,0 +1,384 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sp_std::{cmp::Ordering, prelude::*}; +use crate::helpers_128bit; +use num_traits::Zero; +use sp_debug_derive::RuntimeDebug; + +/// A wrapper for any rational number with a 128 bit numerator and denominator. +#[derive(Clone, Copy, Default, Eq, RuntimeDebug)] +pub struct Rational128(u128, u128); + +impl Rational128 { + /// Nothing. + pub fn zero() -> Self { + Self(0, 1) + } + + /// If it is zero or not + pub fn is_zero(&self) -> bool { + self.0.is_zero() + } + + /// Build from a raw `n/d`. + pub fn from(n: u128, d: u128) -> Self { + Self(n, d.max(1)) + } + + /// Build from a raw `n/d`. This could lead to / 0 if not properly handled. + pub fn from_unchecked(n: u128, d: u128) -> Self { + Self(n, d) + } + + /// Return the numerator. + pub fn n(&self) -> u128 { + self.0 + } + + /// Return the denominator. + pub fn d(&self) -> u128 { + self.1 + } + + /// Convert `self` to a similar rational number where denominator is the given `den`. + // + /// This only returns if the result is accurate. `Err` is returned if the result cannot be + /// accurately calculated. + pub fn to_den(self, den: u128) -> Result { + if den == self.1 { + Ok(self) + } else { + helpers_128bit::multiply_by_rational(self.0, den, self.1).map(|n| Self(n, den)) + } + } + + /// Get the least common divisor of `self` and `other`. + /// + /// This only returns if the result is accurate. `Err` is returned if the result cannot be + /// accurately calculated. + pub fn lcm(&self, other: &Self) -> Result { + // this should be tested better: two large numbers that are almost the same. + if self.1 == other.1 { return Ok(self.1) } + let g = helpers_128bit::gcd(self.1, other.1); + helpers_128bit::multiply_by_rational(self.1 , other.1, g) + } + + /// A saturating add that assumes `self` and `other` have the same denominator. + pub fn lazy_saturating_add(self, other: Self) -> Self { + if other.is_zero() { + self + } else { + Self(self.0.saturating_add(other.0) ,self.1) + } + } + + /// A saturating subtraction that assumes `self` and `other` have the same denominator. + pub fn lazy_saturating_sub(self, other: Self) -> Self { + if other.is_zero() { + self + } else { + Self(self.0.saturating_sub(other.0) ,self.1) + } + } + + /// Addition. Simply tries to unify the denominators and add the numerators. + /// + /// Overflow might happen during any of the steps. Error is returned in such cases. + pub fn checked_add(self, other: Self) -> Result { + let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; + let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let n = self_scaled.0.checked_add(other_scaled.0) + .ok_or("overflow while adding numerators")?; + Ok(Self(n, self_scaled.1)) + } + + /// Subtraction. Simply tries to unify the denominators and subtract the numerators. + /// + /// Overflow might happen during any of the steps. None is returned in such cases. + pub fn checked_sub(self, other: Self) -> Result { + let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; + let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + + let n = self_scaled.0.checked_sub(other_scaled.0) + .ok_or("overflow while subtracting numerators")?; + Ok(Self(n, self_scaled.1)) + } +} + +impl PartialOrd for Rational128 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Rational128 { + fn cmp(&self, other: &Self) -> Ordering { + // handle some edge cases. + if self.1 == other.1 { + self.0.cmp(&other.0) + } else if self.1.is_zero() { + Ordering::Greater + } else if other.1.is_zero() { + Ordering::Less + } else { + // Don't even compute gcd. + let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); + let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); + self_n.cmp(&other_n) + } + } +} + +impl PartialEq for Rational128 { + fn eq(&self, other: &Self) -> bool { + // handle some edge cases. + if self.1 == other.1 { + self.0.eq(&other.0) + } else { + let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); + let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); + self_n.eq(&other_n) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use super::helpers_128bit::*; + + const MAX128: u128 = u128::max_value(); + const MAX64: u128 = u64::max_value() as u128; + const MAX64_2: u128 = 2 * u64::max_value() as u128; + + fn r(p: u128, q: u128) -> Rational128 { + Rational128(p, q) + } + + fn mul_div(a: u128, b: u128, c: u128) -> u128 { + use primitive_types::U256; + if a.is_zero() { return Zero::zero(); } + let c = c.max(1); + + // e for extended + let ae: U256 = a.into(); + let be: U256 = b.into(); + let ce: U256 = c.into(); + + let r = ae * be / ce; + if r > u128::max_value().into() { + a + } else { + r.as_u128() + } + } + + #[test] + fn truth_value_function_works() { + assert_eq!( + mul_div(2u128.pow(100), 8, 4), + 2u128.pow(101) + ); + assert_eq!( + mul_div(2u128.pow(100), 4, 8), + 2u128.pow(99) + ); + + // and it returns a if result cannot fit + assert_eq!(mul_div(MAX128 - 10, 2, 1), MAX128 - 10); + } + + #[test] + fn to_denom_works() { + // simple up and down + assert_eq!(r(1, 5).to_den(10), Ok(r(2, 10))); + assert_eq!(r(4, 10).to_den(5), Ok(r(2, 5))); + + // up and down with large numbers + assert_eq!(r(MAX128 - 10, MAX128).to_den(10), Ok(r(10, 10))); + assert_eq!(r(MAX128 / 2, MAX128).to_den(10), Ok(r(5, 10))); + + // large to perbill. This is very well needed for phragmen. + assert_eq!( + r(MAX128 / 2, MAX128).to_den(1000_000_000), + Ok(r(500_000_000, 1000_000_000)) + ); + + // large to large + assert_eq!(r(MAX128 / 2, MAX128).to_den(MAX128/2), Ok(r(MAX128/4, MAX128/2))); + } + + #[test] + fn gdc_works() { + assert_eq!(gcd(10, 5), 5); + assert_eq!(gcd(7, 22), 1); + } + + #[test] + fn lcm_works() { + // simple stuff + assert_eq!(r(3, 10).lcm(&r(4, 15)).unwrap(), 30); + assert_eq!(r(5, 30).lcm(&r(1, 7)).unwrap(), 210); + assert_eq!(r(5, 30).lcm(&r(1, 10)).unwrap(), 30); + + // large numbers + assert_eq!( + r(1_000_000_000, MAX128).lcm(&r(7_000_000_000, MAX128-1)), + Err("result cannot fit in u128"), + ); + assert_eq!( + r(1_000_000_000, MAX64).lcm(&r(7_000_000_000, MAX64-1)), + Ok(340282366920938463408034375210639556610), + ); + assert!(340282366920938463408034375210639556610 < MAX128); + assert!(340282366920938463408034375210639556610 == MAX64 * (MAX64 - 1)); + } + + #[test] + fn add_works() { + // works + assert_eq!(r(3, 10).checked_add(r(1, 10)).unwrap(), r(2, 5)); + assert_eq!(r(3, 10).checked_add(r(3, 7)).unwrap(), r(51, 70)); + + // errors + assert_eq!( + r(1, MAX128).checked_add(r(1, MAX128-1)), + Err("failed to scale to denominator"), + ); + assert_eq!( + r(7, MAX128).checked_add(r(MAX128, MAX128)), + Err("overflow while adding numerators"), + ); + assert_eq!( + r(MAX128, MAX128).checked_add(r(MAX128, MAX128)), + Err("overflow while adding numerators"), + ); + } + + #[test] + fn sub_works() { + // works + assert_eq!(r(3, 10).checked_sub(r(1, 10)).unwrap(), r(1, 5)); + assert_eq!(r(6, 10).checked_sub(r(3, 7)).unwrap(), r(12, 70)); + + // errors + assert_eq!( + r(2, MAX128).checked_sub(r(1, MAX128-1)), + Err("failed to scale to denominator"), + ); + assert_eq!( + r(7, MAX128).checked_sub(r(MAX128, MAX128)), + Err("overflow while subtracting numerators"), + ); + assert_eq!( + r(1, 10).checked_sub(r(2,10)), + Err("overflow while subtracting numerators"), + ); + } + + #[test] + fn ordering_and_eq_works() { + assert!(r(1, 2) > r(1, 3)); + assert!(r(1, 2) > r(2, 6)); + + assert!(r(1, 2) < r(6, 6)); + assert!(r(2, 1) > r(2, 6)); + + assert!(r(5, 10) == r(1, 2)); + assert!(r(1, 2) == r(1, 2)); + + assert!(r(1, 1490000000000200000) > r(1, 1490000000000200001)); + } + + #[test] + fn multiply_by_rational_works() { + assert_eq!(multiply_by_rational(7, 2, 3).unwrap(), 7 * 2 / 3); + assert_eq!(multiply_by_rational(7, 20, 30).unwrap(), 7 * 2 / 3); + assert_eq!(multiply_by_rational(20, 7, 30).unwrap(), 7 * 2 / 3); + + assert_eq!( + // MAX128 % 3 == 0 + multiply_by_rational(MAX128, 2, 3).unwrap(), + MAX128 / 3 * 2, + ); + assert_eq!( + // MAX128 % 7 == 3 + multiply_by_rational(MAX128, 5, 7).unwrap(), + (MAX128 / 7 * 5) + (3 * 5 / 7), + ); + assert_eq!( + // MAX128 % 7 == 3 + multiply_by_rational(MAX128, 11 , 13).unwrap(), + (MAX128 / 13 * 11) + (8 * 11 / 13), + ); + assert_eq!( + // MAX128 % 1000 == 455 + multiply_by_rational(MAX128, 555, 1000).unwrap(), + (MAX128 / 1000 * 555) + (455 * 555 / 1000), + ); + + assert_eq!( + multiply_by_rational(2 * MAX64 - 1, MAX64, MAX64).unwrap(), + 2 * MAX64 - 1, + ); + assert_eq!( + multiply_by_rational(2 * MAX64 - 1, MAX64 - 1, MAX64).unwrap(), + 2 * MAX64 - 3, + ); + + assert_eq!( + multiply_by_rational(MAX64 + 100, MAX64_2, MAX64_2 / 2).unwrap(), + (MAX64 + 100) * 2, + ); + assert_eq!( + multiply_by_rational(MAX64 + 100, MAX64_2 / 100, MAX64_2 / 200).unwrap(), + (MAX64 + 100) * 2, + ); + + assert_eq!( + multiply_by_rational(2u128.pow(66) - 1, 2u128.pow(65) - 1, 2u128.pow(65)).unwrap(), + 73786976294838206461, + ); + assert_eq!( + multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), + 250000000, + ); + } + + #[test] + fn multiply_by_rational_a_b_are_interchangeable() { + assert_eq!( + multiply_by_rational(10, MAX128, MAX128 / 2), + Ok(20), + ); + assert_eq!( + multiply_by_rational(MAX128, 10, MAX128 / 2), + Ok(20), + ); + } + + #[test] + #[ignore] + fn multiply_by_rational_fuzzed_equation() { + assert_eq!( + multiply_by_rational(154742576605164960401588224, 9223376310179529214, 549756068598), + Ok(2596149632101417846585204209223679) + ); + } +} diff --git a/primitives/arithmetic/src/traits.rs b/primitives/arithmetic/src/traits.rs new file mode 100644 index 0000000000000..ab525527e9064 --- /dev/null +++ b/primitives/arithmetic/src/traits.rs @@ -0,0 +1,143 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for the runtime modules. + +use sp_std::{self, convert::{TryFrom, TryInto}}; +use codec::HasCompact; +pub use integer_sqrt::IntegerSquareRoot; +pub use num_traits::{ + Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, + CheckedShl, CheckedShr +}; +use sp_std::ops::{ + Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, + RemAssign, Shl, Shr +}; + +/// A meta trait for arithmetic. +/// +/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to +/// be able to represent at least `u32` values without loss, hence the trait implies `From` +/// and smaller ints. All other conversions are fallible. +pub trait SimpleArithmetic: + Zero + One + IntegerSquareRoot + + From + From + From + TryInto + TryInto + TryInto + + TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + + UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + + UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign + + Shl + Shr + + CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + + Saturating + PartialOrd + Ord + Bounded + + HasCompact + Sized +{} +impl + From + From + TryInto + TryInto + TryInto + + TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + + UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + + UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign + + Shl + Shr + + CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + + Saturating + PartialOrd + Ord + Bounded + + HasCompact + Sized +> SimpleArithmetic for T {} + +/// Just like `From` except that if the source value is too big to fit into the destination type +/// then it'll saturate the destination. +pub trait UniqueSaturatedFrom: Sized { + /// Convert from a value of `T` into an equivalent instance of `Self`. + fn unique_saturated_from(t: T) -> Self; +} + +/// Just like `Into` except that if the source value is too big to fit into the destination type +/// then it'll saturate the destination. +pub trait UniqueSaturatedInto: Sized { + /// Consume self to return an equivalent value of `T`. + fn unique_saturated_into(self) -> T; +} + +impl + Bounded + Sized> UniqueSaturatedFrom for S { + fn unique_saturated_from(t: T) -> Self { + S::try_from(t).unwrap_or_else(|_| Bounded::max_value()) + } +} + +impl + Sized> UniqueSaturatedInto for S { + fn unique_saturated_into(self) -> T { + self.try_into().unwrap_or_else(|_| Bounded::max_value()) + } +} + +/// Simple trait to use checked mul and max value to give a saturated mul operation over +/// supported types. +pub trait Saturating { + /// Saturated addition - if the product can't fit in the type then just use max-value. + fn saturating_add(self, o: Self) -> Self; + + /// Saturated subtraction - if the product can't fit in the type then just use max-value. + fn saturating_sub(self, o: Self) -> Self; + + /// Saturated multiply - if the product can't fit in the type then just use max-value. + fn saturating_mul(self, o: Self) -> Self; +} + +impl Saturating for T { + fn saturating_add(self, o: Self) -> Self { + ::saturating_add(self, o) + } + fn saturating_sub(self, o: Self) -> Self { + ::saturating_sub(self, o) + } + fn saturating_mul(self, o: Self) -> Self { + self.checked_mul(&o).unwrap_or_else(Bounded::max_value) + } +} + +/// Convenience type to work around the highly unergonomic syntax needed +/// to invoke the functions of overloaded generic traits, in this case +/// `SaturatedFrom` and `SaturatedInto`. +pub trait SaturatedConversion { + /// Convert from a value of `T` into an equivalent instance of `Self`. + /// + /// This just uses `UniqueSaturatedFrom` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn saturated_from(t: T) -> Self where Self: UniqueSaturatedFrom { + >::unique_saturated_from(t) + } + + /// Consume self to return an equivalent value of `T`. + /// + /// This just uses `UniqueSaturatedInto` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn saturated_into(self) -> T where Self: UniqueSaturatedInto { + >::unique_saturated_into(self) + } +} +impl SaturatedConversion for T {} diff --git a/primitives/authority-discovery/Cargo.toml b/primitives/authority-discovery/Cargo.toml new file mode 100644 index 0000000000000..516ea413acd55 --- /dev/null +++ b/primitives/authority-discovery/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sp-authority-discovery" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Authority discovery primitives" +edition = "2018" + +[dependencies] +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../application-crypto" } +codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-api = { version = "2.0.0", default-features = false, path = "../api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } + +[features] +default = ["std"] +std = [ + "sp-application-crypto/std", + "codec/std", + "sp-std/std", + "sp-api/std", + "sp-runtime/std" +] diff --git a/primitives/authority-discovery/src/lib.rs b/primitives/authority-discovery/src/lib.rs new file mode 100644 index 0000000000000..fc76da61afa53 --- /dev/null +++ b/primitives/authority-discovery/src/lib.rs @@ -0,0 +1,47 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime Api to help discover authorities. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::vec::Vec; + +mod app { + use sp_application_crypto::{app_crypto, key_types::AUTHORITY_DISCOVERY, sr25519}; + app_crypto!(sr25519, AUTHORITY_DISCOVERY); +} + +/// An authority discovery authority keypair. +#[cfg(feature = "std")] +pub type AuthorityPair = app::Pair; + +/// An authority discovery authority identifier. +pub type AuthorityId = app::Public; + +/// An authority discovery authority signature. +pub type AuthoritySignature = app::Signature; + +sp_api::decl_runtime_apis! { + /// The authority discovery api. + /// + /// This api is used by the `client/authority-discovery` module to retrieve identifiers + /// of the current authority set. + pub trait AuthorityDiscoveryApi { + /// Retrieve authority identifiers of the current authority set. + fn authorities() -> Vec; + } +} diff --git a/primitives/authorship/Cargo.toml b/primitives/authorship/Cargo.toml new file mode 100644 index 0000000000000..d8ddbb7a9218a --- /dev/null +++ b/primitives/authorship/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "sp-authorship" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Authorship primitives" +edition = "2018" + +[dependencies] +sp-inherents = { version = "2.0.0", default-features = false, path = "../inherents" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } + +[features] +default = [ "std" ] +std = [ + "codec/std", + "sp-std/std", + "sp-inherents/std", + "sp-runtime/std", +] diff --git a/primitives/authorship/src/lib.rs b/primitives/authorship/src/lib.rs new file mode 100644 index 0000000000000..53dac56dc473c --- /dev/null +++ b/primitives/authorship/src/lib.rs @@ -0,0 +1,91 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Authorship Primitives + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{result::Result, prelude::*}; + +use codec::{Encode, Decode}; +use sp_inherents::{Error, InherentIdentifier, InherentData, IsFatalError}; +use sp_runtime::RuntimeString; + +/// The identifier for the `uncles` inherent. +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"uncles00"; + +/// Errors that can occur while checking the authorship inherent. +#[derive(Encode, sp_runtime::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode))] +pub enum InherentError { + Uncles(RuntimeString), +} + +impl IsFatalError for InherentError { + fn is_fatal_error(&self) -> bool { + match self { + InherentError::Uncles(_) => true, + } + } +} + +/// Auxiliary trait to extract uncles inherent data. +pub trait UnclesInherentData { + /// Get uncles. + fn uncles(&self) -> Result, Error>; +} + +impl UnclesInherentData for InherentData { + fn uncles(&self) -> Result, Error> { + Ok(self.get_data(&INHERENT_IDENTIFIER)?.unwrap_or_default()) + } +} + +/// Provider for inherent data. +#[cfg(feature = "std")] +pub struct InherentDataProvider { + inner: F, + _marker: std::marker::PhantomData, +} + +#[cfg(feature = "std")] +impl InherentDataProvider { + pub fn new(uncles_oracle: F) -> Self { + InherentDataProvider { inner: uncles_oracle, _marker: Default::default() } + } +} + +#[cfg(feature = "std")] +impl sp_inherents::ProvideInherentData for InherentDataProvider +where F: Fn() -> Vec +{ + fn inherent_identifier(&self) -> &'static InherentIdentifier { + &INHERENT_IDENTIFIER + } + + fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> { + let uncles = (self.inner)(); + if !uncles.is_empty() { + inherent_data.put_data(INHERENT_IDENTIFIER, &uncles) + } else { + Ok(()) + } + } + + fn error_to_string(&self, _error: &[u8]) -> Option { + Some(format!("no further information")) + } +} diff --git a/primitives/block-builder/Cargo.toml b/primitives/block-builder/Cargo.toml new file mode 100644 index 0000000000000..5bbe9ea123faf --- /dev/null +++ b/primitives/block-builder/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sp-block-builder" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } +sp-api = { version = "2.0.0", default-features = false, path = "../api" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false } +sp-inherents = { version = "2.0.0", default-features = false, path = "../inherents" } + +[features] +default = [ "std" ] +std = [ + "sp-runtime/std", + "codec/std", + "sp-inherents/std", + "sp-api/std", + "sp-std/std", +] diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs new file mode 100644 index 0000000000000..d963fb7e3067e --- /dev/null +++ b/primitives/block-builder/src/lib.rs @@ -0,0 +1,73 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! The block builder runtime api. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; + +use sp_inherents::{InherentData, CheckInherentsResult}; + +/// Definitions for supporting the older version of API: v3 +/// +/// These definitions are taken from the 2c58e30246a029b53d51e5b24c31974ac539ee8b git revision. +#[deprecated(note = "These definitions here are only for compatibility reasons")] +pub mod compatability_v3 { + use sp_runtime::{DispatchOutcome, transaction_validity}; + use codec::{Encode, Decode}; + + #[derive(Eq, PartialEq, Clone, Copy, Decode, Encode, Debug)] + pub enum ApplyError { + NoPermission, + BadState, + Validity(transaction_validity::TransactionValidityError), + } + + // `ApplyOutcome` was renamed to `DispatchOutcome` with the layout preserved. + pub type ApplyResult = Result; +} + +sp_api::decl_runtime_apis! { + /// The `BlockBuilder` api trait that provides the required functionality for building a block. + #[api_version(4)] + pub trait BlockBuilder { + /// Compatibility version of `apply_extrinsic` for v3. + /// + /// Only the return type is changed. + #[changed_in(4)] + #[allow(deprecated)] + fn apply_extrinsic(extrinsic: ::Extrinsic) + -> self::compatability_v3::ApplyResult; + + /// Apply the given extrinsic. + /// + /// Returns an inclusion outcome which specifies if this extrinsic is included in + /// this block or not. + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult; + /// Finish the current block. + #[renamed("finalise_block", 3)] + fn finalize_block() -> ::Header; + /// Generate inherent extrinsics. The inherent data will vary from chain to chain. + fn inherent_extrinsics( + inherent: InherentData, + ) -> sp_std::vec::Vec<::Extrinsic>; + /// Check that the inherents are valid. The inherent data will vary from chain to chain. + fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; + /// Generate a random seed. + fn random_seed() -> ::Hash; + } +} diff --git a/primitives/blockchain/Cargo.toml b/primitives/blockchain/Cargo.toml new file mode 100644 index 0000000000000..4f3f0d0b5fad0 --- /dev/null +++ b/primitives/blockchain/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sp-blockchain" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4.8" +lru = "0.4.0" +parking_lot = "0.9.0" +derive_more = "0.99.2" +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-consensus = { version = "0.8", path = "../consensus/common" } +sp-runtime = { version = "2.0.0", path = "../runtime" } +sp-block-builder = { version = "2.0.0", path = "../block-builder" } +sp-state-machine = { version = "2.0.0", path = "../state-machine" } diff --git a/primitives/blockchain/src/backend.rs b/primitives/blockchain/src/backend.rs new file mode 100644 index 0000000000000..8571d76801079 --- /dev/null +++ b/primitives/blockchain/src/backend.rs @@ -0,0 +1,275 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate blockchain trait + +use std::sync::Arc; + +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; +use sp_runtime::generic::BlockId; +use sp_runtime::Justification; +use log::warn; +use parking_lot::RwLock; + +use crate::header_metadata::HeaderMetadata; + +use crate::error::{Error, Result}; + +/// Blockchain database header backend. Does not perform any validation. +pub trait HeaderBackend: Send + Sync { + /// Get block header. Returns `None` if block is not found. + fn header(&self, id: BlockId) -> Result>; + /// Get blockchain info. + fn info(&self) -> Info; + /// Get block status. + fn status(&self, id: BlockId) -> Result; + /// Get block number by hash. Returns `None` if the header is not in the chain. + fn number(&self, hash: Block::Hash) -> Result::Header as HeaderT>::Number>>; + /// Get block hash by number. Returns `None` if the header is not in the chain. + fn hash(&self, number: NumberFor) -> Result>; + + /// Convert an arbitrary block ID into a block hash. + fn block_hash_from_id(&self, id: &BlockId) -> Result> { + match *id { + BlockId::Hash(h) => Ok(Some(h)), + BlockId::Number(n) => self.hash(n), + } + } + + /// Convert an arbitrary block ID into a block hash. + fn block_number_from_id(&self, id: &BlockId) -> Result>> { + match *id { + BlockId::Hash(_) => Ok(self.header(*id)?.map(|h| h.number().clone())), + BlockId::Number(n) => Ok(Some(n)), + } + } + + /// Get block header. Returns `UnknownBlock` error if block is not found. + fn expect_header(&self, id: BlockId) -> Result { + self.header(id)?.ok_or_else(|| Error::UnknownBlock(format!("{}", id))) + } + + /// Convert an arbitrary block ID into a block number. Returns `UnknownBlock` error if block is not found. + fn expect_block_number_from_id(&self, id: &BlockId) -> Result> { + self.block_number_from_id(id) + .and_then(|n| n.ok_or_else(|| Error::UnknownBlock(format!("{}", id)))) + } + + /// Convert an arbitrary block ID into a block hash. Returns `UnknownBlock` error if block is not found. + fn expect_block_hash_from_id(&self, id: &BlockId) -> Result { + self.block_hash_from_id(id) + .and_then(|n| n.ok_or_else(|| Error::UnknownBlock(format!("{}", id)))) + } +} + +/// Blockchain database backend. Does not perform any validation. +pub trait Backend: HeaderBackend + HeaderMetadata { + /// Get block body. Returns `None` if block is not found. + fn body(&self, id: BlockId) -> Result::Extrinsic>>>; + /// Get block justification. Returns `None` if justification does not exist. + fn justification(&self, id: BlockId) -> Result>; + /// Get last finalized block hash. + fn last_finalized(&self) -> Result; + /// Returns data cache reference, if it is enabled on this backend. + fn cache(&self) -> Option>>; + + /// Returns hashes of all blocks that are leaves of the block tree. + /// in other words, that have no children, are chain heads. + /// Results must be ordered best (longest, highest) 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>; + + /// Get the most recent block hash of the best (longest) chains + /// that contain block with the given `target_hash`. + /// + /// The search space is always limited to blocks which are in the finalized + /// chain or descendents of it. + /// + /// If `maybe_max_block_number` is `Some(max_block_number)` + /// the search is limited to block `numbers <= max_block_number`. + /// in other words as if there were no blocks greater `max_block_number`. + /// Returns `Ok(None)` if `target_hash` is not found in search space. + /// TODO: document time complexity of this, see [#1444](https://github.com/paritytech/substrate/issues/1444) + fn best_containing( + &self, + target_hash: Block::Hash, + maybe_max_number: Option>, + import_lock: &RwLock<()>, + ) -> Result> { + let target_header = { + match self.header(BlockId::Hash(target_hash))? { + Some(x) => x, + // target not in blockchain + None => { return Ok(None); }, + } + }; + + if let Some(max_number) = maybe_max_number { + // target outside search range + if target_header.number() > &max_number { + return Ok(None); + } + } + + let leaves = { + // ensure no blocks are imported during this code block. + // an import could trigger a reorg which could change the canonical chain. + // we depend on the canonical chain staying the same during this code block. + let _import_guard = import_lock.read(); + + let info = self.info(); + + // this can be `None` if the best chain is shorter than the target header. + let maybe_canon_hash = self.hash(*target_header.number())?; + + if maybe_canon_hash.as_ref() == Some(&target_hash) { + // if a `max_number` is given we try to fetch the block at the + // given depth, if it doesn't exist or `max_number` is not + // provided, we continue to search from all leaves below. + if let Some(max_number) = maybe_max_number { + if let Some(header) = self.hash(max_number)? { + return Ok(Some(header)); + } + } + } else if info.finalized_number >= *target_header.number() { + // header is on a dead fork. + return Ok(None); + } + + self.leaves()? + }; + + // for each chain. longest chain first. shortest last + for leaf_hash in leaves { + // start at the leaf + let mut current_hash = leaf_hash; + + // if search is not restricted then the leaf is the best + let mut best_hash = leaf_hash; + + // go backwards entering the search space + // waiting until we are <= max_number + if let Some(max_number) = maybe_max_number { + loop { + let current_header = self.header(BlockId::Hash(current_hash.clone()))? + .ok_or_else(|| Error::from(format!("failed to get header for hash {}", current_hash)))?; + + if current_header.number() <= &max_number { + best_hash = current_header.hash(); + break; + } + + current_hash = *current_header.parent_hash(); + } + } + + // go backwards through the chain (via parent links) + loop { + // until we find target + if current_hash == target_hash { + return Ok(Some(best_hash)); + } + + let current_header = self.header(BlockId::Hash(current_hash.clone()))? + .ok_or_else(|| Error::from(format!("failed to get header for hash {}", current_hash)))?; + + // stop search in this chain once we go below the target's block number + if current_header.number() < target_header.number() { + break; + } + + current_hash = *current_header.parent_hash(); + } + } + + // header may be on a dead fork -- the only leaves that are considered are + // those which can still be finalized. + // + // FIXME #1558 only issue this warning when not on a dead fork + warn!( + "Block {:?} exists in chain but not found when following all \ + leaves backwards. Number limit = {:?}", + target_hash, + maybe_max_number, + ); + + Ok(None) + } +} + +/// Provides access to the optional cache. +pub trait ProvideCache { + /// Returns data cache reference, if it is enabled on this backend. + fn cache(&self) -> Option>>; +} + +/// Blockchain optional data cache. +pub trait Cache: Send + Sync { + /// Initialize genesis value for the given cache. + /// + /// The operation should be performed once before anything else is inserted in the cache. + /// Otherwise cache may end up in inconsistent state. + fn initialize(&self, key: &well_known_cache_keys::Id, value_at_genesis: Vec) -> Result<()>; + /// Returns cached value by the given key. + /// + /// Returned tuple is the range where value has been active and the value itself. + fn get_at( + &self, + key: &well_known_cache_keys::Id, + block: &BlockId, + ) -> Option<((NumberFor, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)>; +} + +/// Blockchain info +#[derive(Debug)] +pub struct Info { + /// Best block hash. + pub best_hash: Block::Hash, + /// Best block number. + pub best_number: <::Header as HeaderT>::Number, + /// Genesis block hash. + pub genesis_hash: Block::Hash, + /// The head of the finalized chain. + pub finalized_hash: Block::Hash, + /// Last finalized block number. + pub finalized_number: <::Header as HeaderT>::Number, +} + +/// Block status. +#[derive(Debug, PartialEq, Eq)] +pub enum BlockStatus { + /// Already in the blockchain. + InChain, + /// Not in the queue or the blockchain. + Unknown, +} + +/// A list of all well known keys in the blockchain cache. +pub mod well_known_cache_keys { + /// The type representing cache keys. + pub type Id = sp_consensus::import_queue::CacheKeyId; + + /// A list of authorities. + pub const AUTHORITIES: Id = *b"auth"; + + /// Current Epoch data. + pub const EPOCH: Id = *b"epch"; + + /// Changes trie configuration. + pub const CHANGES_TRIE_CONFIG: Id = *b"chtr"; +} diff --git a/primitives/blockchain/src/error.rs b/primitives/blockchain/src/error.rs new file mode 100644 index 0000000000000..dbab93738e79f --- /dev/null +++ b/primitives/blockchain/src/error.rs @@ -0,0 +1,168 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate client possible errors. + +use std::{self, error, result}; +use sp_state_machine; +use sp_runtime::transaction_validity::TransactionValidityError; +#[allow(deprecated)] +use sp_block_builder::compatability_v3; +use sp_consensus; +use derive_more::{Display, From}; +use codec::Error as CodecError; + +/// Client Result type alias +pub type Result = result::Result; + +/// Error when the runtime failed to apply an extrinsic. +#[derive(Debug, Display)] +pub enum ApplyExtrinsicFailed { + /// The transaction cannot be included into the current block. + /// + /// This doesn't necessary mean that the transaction itself is invalid, but it might be just + /// unappliable onto the current block. + #[display(fmt = "Extrinsic is not valid: {:?}", _0)] + Validity(TransactionValidityError), + /// This is used for miscelanious errors that can be represented by string and not handleable. + /// + /// This will become obsolete with complete migration to v4 APIs. + #[display(fmt = "Extrinsic failed: {:?}", _0)] + Msg(String), +} + +/// Substrate Client error +#[derive(Debug, Display, From)] +pub enum Error { + /// Consensus Error + #[display(fmt = "Consensus: {}", _0)] + Consensus(sp_consensus::Error), + /// Backend error. + #[display(fmt = "Backend error: {}", _0)] + #[from(ignore)] + Backend(String), + /// Unknown block. + #[display(fmt = "UnknownBlock: {}", _0)] + #[from(ignore)] + UnknownBlock(String), + /// The `apply_extrinsic` is not valid due to the given `TransactionValidityError`. + #[display(fmt = "{:?}", _0)] + ApplyExtrinsicFailed(ApplyExtrinsicFailed), + /// Execution error. + #[display(fmt = "Execution: {}", _0)] + Execution(Box), + /// Blockchain error. + #[display(fmt = "Blockchain: {}", _0)] + Blockchain(Box), + /// Invalid authorities set received from the runtime. + #[display(fmt = "Current state of blockchain has invalid authorities set")] + InvalidAuthoritiesSet, + /// Could not get runtime version. + #[display(fmt = "Failed to get runtime version: {}", _0)] + #[from(ignore)] + VersionInvalid(String), + /// Genesis config is invalid. + #[display(fmt = "Genesis config provided is invalid")] + GenesisInvalid, + /// Error decoding header justification. + #[display(fmt = "error decoding justification for header")] + JustificationDecode, + /// Justification for header is correctly encoded, but invalid. + #[display(fmt = "bad justification for header: {}", _0)] + #[from(ignore)] + BadJustification(String), + /// Not available on light client. + #[display(fmt = "This method is not currently available when running in light client mode")] + NotAvailableOnLightClient, + /// Invalid remote CHT-based proof. + #[display(fmt = "Remote node has responded with invalid header proof")] + InvalidCHTProof, + /// Remote fetch has been cancelled. + #[display(fmt = "Remote data fetch has been cancelled")] + RemoteFetchCancelled, + /// Remote fetch has been failed. + #[display(fmt = "Remote data fetch has been failed")] + RemoteFetchFailed, + /// Error decoding call result. + #[display(fmt = "Error decoding call result of {}: {}", _0, _1)] + CallResultDecode(&'static str, CodecError), + /// Error converting a parameter between runtime and node. + #[display(fmt = "Error converting `{}` between runtime and node", _0)] + #[from(ignore)] + RuntimeParamConversion(String), + /// Changes tries are not supported. + #[display(fmt = "Changes tries are not supported by the runtime")] + ChangesTriesNotSupported, + /// Key changes query has failed. + #[display(fmt = "Failed to check changes proof: {}", _0)] + #[from(ignore)] + ChangesTrieAccessFailed(String), + /// Last finalized block not parent of current. + #[display(fmt = "Did not finalize blocks in sequential order.")] + #[from(ignore)] + NonSequentialFinalization(String), + /// Safety violation: new best block not descendent of last finalized. + #[display(fmt = "Potential long-range attack: block not in finalized chain.")] + NotInFinalizedChain, + /// Hash that is required for building CHT is missing. + #[display(fmt = "Failed to get hash of block for building CHT")] + MissingHashRequiredForCHT, + /// Invalid calculated state root on block import. + #[display(fmt = "Calculated state root does not match.")] + InvalidStateRoot, + /// A convenience variant for String + #[display(fmt = "{}", _0)] + Msg(String), +} + +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + Error::Consensus(e) => Some(e), + Error::Blockchain(e) => Some(e), + _ => None, + } + } +} + +impl<'a> From<&'a str> for Error { + fn from(s: &'a str) -> Self { + Error::Msg(s.into()) + } +} + +#[allow(deprecated)] +impl From for ApplyExtrinsicFailed { + fn from(e: compatability_v3::ApplyError) -> Self { + use self::compatability_v3::ApplyError::*; + match e { + Validity(tx_validity) => Self::Validity(tx_validity), + e => Self::Msg(format!("Apply extrinsic failed: {:?}", e)), + } + } +} + +impl Error { + /// Chain a blockchain error. + pub fn from_blockchain(e: Box) -> Self { + Error::Blockchain(e) + } + + /// Chain a state error. + pub fn from_state(e: Box) -> Self { + Error::Execution(e) + } +} diff --git a/primitives/blockchain/src/header_metadata.rs b/primitives/blockchain/src/header_metadata.rs new file mode 100644 index 0000000000000..fcd8062d1d6d5 --- /dev/null +++ b/primitives/blockchain/src/header_metadata.rs @@ -0,0 +1,281 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implements tree backend, cached header metadata and algorithms +//! to compute routes efficiently over the tree of headers. + +use sp_runtime::traits::{Block as BlockT, NumberFor, Header}; +use parking_lot::RwLock; +use lru::LruCache; + +/// Set to the expected max difference between `best` and `finalized` blocks at sync. +const LRU_CACHE_SIZE: usize = 5_000; + +/// Get lowest common ancestor between two blocks in the tree. +/// +/// This implementation is efficient because our trees have very few and +/// small branches, and because of our current query pattern: +/// lca(best, final), lca(best + 1, final), lca(best + 2, final), etc. +/// The first call is O(h) but the others are O(1). +pub fn lowest_common_ancestor>( + backend: &T, + id_one: Block::Hash, + id_two: Block::Hash, +) -> Result, T::Error> { + let mut header_one = backend.header_metadata(id_one)?; + let mut header_two = backend.header_metadata(id_two)?; + + let mut orig_header_one = header_one.clone(); + let mut orig_header_two = header_two.clone(); + + // We move through ancestor links as much as possible, since ancestor >= parent. + + while header_one.number > header_two.number { + let ancestor_one = backend.header_metadata(header_one.ancestor)?; + + if ancestor_one.number >= header_two.number { + header_one = ancestor_one; + } else { + break + } + } + + while header_one.number < header_two.number { + let ancestor_two = backend.header_metadata(header_two.ancestor)?; + + if ancestor_two.number >= header_one.number { + header_two = ancestor_two; + } else { + break + } + } + + // Then we move the remaining path using parent links. + + while header_one.hash != header_two.hash { + if header_one.number > header_two.number { + header_one = backend.header_metadata(header_one.parent)?; + } else { + header_two = backend.header_metadata(header_two.parent)?; + } + } + + // Update cached ancestor links. + + if orig_header_one.number > header_one.number { + orig_header_one.ancestor = header_one.hash; + backend.insert_header_metadata(orig_header_one.hash, orig_header_one); + } + + if orig_header_two.number > header_one.number { + orig_header_two.ancestor = header_one.hash; + backend.insert_header_metadata(orig_header_two.hash, orig_header_two); + } + + Ok(HashAndNumber { + hash: header_one.hash, + number: header_one.number, + }) +} + +/// Compute a tree-route between two blocks. See tree-route docs for more details. +pub fn tree_route>( + backend: &T, + from: Block::Hash, + to: Block::Hash, +) -> Result, T::Error> { + let mut from = backend.header_metadata(from)?; + let mut to = backend.header_metadata(to)?; + + let mut from_branch = Vec::new(); + let mut to_branch = Vec::new(); + + while to.number > from.number { + to_branch.push(HashAndNumber { + number: to.number, + hash: to.hash, + }); + + to = backend.header_metadata(to.parent)?; + } + + while from.number > to.number { + from_branch.push(HashAndNumber { + number: from.number, + hash: from.hash, + }); + from = backend.header_metadata(from.parent)?; + } + + // numbers are equal now. walk backwards until the block is the same + + while to.hash != from.hash { + to_branch.push(HashAndNumber { + number: to.number, + hash: to.hash, + }); + to = backend.header_metadata(to.parent)?; + + from_branch.push(HashAndNumber { + number: from.number, + hash: from.hash, + }); + from = backend.header_metadata(from.parent)?; + } + + // add the pivot block. and append the reversed to-branch (note that it's reverse order originals) + let pivot = from_branch.len(); + from_branch.push(HashAndNumber { + number: to.number, + hash: to.hash, + }); + from_branch.extend(to_branch.into_iter().rev()); + + Ok(TreeRoute { + route: from_branch, + pivot, + }) +} + +/// Hash and number of a block. +#[derive(Debug)] +pub struct HashAndNumber { + /// The number of the block. + pub number: NumberFor, + /// The hash of the block. + pub hash: Block::Hash, +} + +/// A tree-route from one block to another in the chain. +/// +/// All blocks prior to the pivot in the deque is the reverse-order unique ancestry +/// of the first block, the block at the pivot index is the common ancestor, +/// and all blocks after the pivot is the ancestry of the second block, in +/// order. +/// +/// The ancestry sets will include the given blocks, and thus the tree-route is +/// never empty. +/// +/// ```text +/// Tree route from R1 to E2. Retracted is [R1, R2, R3], Common is C, enacted [E1, E2] +/// <- R3 <- R2 <- R1 +/// / +/// C +/// \-> E1 -> E2 +/// ``` +/// +/// ```text +/// Tree route from C to E2. Retracted empty. Common is C, enacted [E1, E2] +/// C -> E1 -> E2 +/// ``` +#[derive(Debug)] +pub struct TreeRoute { + route: Vec>, + pivot: usize, +} + +impl TreeRoute { + /// Get a slice of all retracted blocks in reverse order (towards common ancestor) + pub fn retracted(&self) -> &[HashAndNumber] { + &self.route[..self.pivot] + } + + /// Get the common ancestor block. This might be one of the two blocks of the + /// route. + pub fn common_block(&self) -> &HashAndNumber { + self.route.get(self.pivot).expect("tree-routes are computed between blocks; \ + which are included in the route; \ + thus it is never empty; qed") + } + + /// Get a slice of enacted blocks (descendents of the common ancestor) + pub fn enacted(&self) -> &[HashAndNumber] { + &self.route[self.pivot + 1 ..] + } +} + +/// Handles header metadata: hash, number, parent hash, etc. +pub trait HeaderMetadata { + /// Error used in case the header metadata is not found. + type Error; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error>; + fn insert_header_metadata(&self, hash: Block::Hash, header_metadata: CachedHeaderMetadata); + fn remove_header_metadata(&self, hash: Block::Hash); +} + +/// Caches header metadata in an in-memory LRU cache. +pub struct HeaderMetadataCache { + cache: RwLock>>, +} + +impl HeaderMetadataCache { + /// Creates a new LRU header metadata cache with `capacity`. + pub fn new(capacity: usize) -> Self { + HeaderMetadataCache { + cache: RwLock::new(LruCache::new(capacity)), + } + } +} + +impl Default for HeaderMetadataCache { + fn default() -> Self { + HeaderMetadataCache { + cache: RwLock::new(LruCache::new(LRU_CACHE_SIZE)), + } + } +} + +impl HeaderMetadata for HeaderMetadataCache { + type Error = String; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.cache.write().get(&hash).cloned() + .ok_or("header metadata not found in cache".to_owned()) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.cache.write().put(hash, metadata); + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.cache.write().pop(&hash); + } +} + +/// Cached header metadata. Used to efficiently traverse the tree. +#[derive(Debug, Clone)] +pub struct CachedHeaderMetadata { + /// Hash of the header. + pub hash: Block::Hash, + /// Block number. + pub number: NumberFor, + /// Hash of parent header. + pub parent: Block::Hash, + /// Hash of an ancestor header. Used to jump through the tree. + ancestor: Block::Hash, +} + +impl From<&Block::Header> for CachedHeaderMetadata { + fn from(header: &Block::Header) -> Self { + CachedHeaderMetadata { + hash: header.hash().clone(), + number: header.number().clone(), + parent: header.parent_hash().clone(), + ancestor: header.parent_hash().clone(), + } + } +} diff --git a/primitives/blockchain/src/lib.rs b/primitives/blockchain/src/lib.rs new file mode 100644 index 0000000000000..21c5bc99d20cf --- /dev/null +++ b/primitives/blockchain/src/lib.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate blockchain traits and primtives + +mod backend; +mod header_metadata; +mod error; + +pub use error::*; +pub use backend::*; +pub use header_metadata::*; diff --git a/primitives/consensus/aura/Cargo.toml b/primitives/consensus/aura/Cargo.toml new file mode 100644 index 0000000000000..57958ed851d34 --- /dev/null +++ b/primitives/consensus/aura/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "sp-consensus-aura" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "Primitives for Aura consensus" +edition = "2018" + +[dependencies] +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../../application-crypto" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-std = { version = "2.0.0", default-features = false, path = "../../std" } +sp-api = { version = "2.0.0", default-features = false, path = "../../api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../runtime" } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../inherents" } +sp-timestamp = { version = "2.0.0", default-features = false, path = "../../timestamp" } + +[features] +default = ["std"] +std = [ + "sp-application-crypto/std", + "codec/std", + "sp-std/std", + "sp-api/std", + "sp-runtime/std", + "sp-inherents/std", + "sp-timestamp/std", +] diff --git a/primitives/consensus/aura/src/inherents.rs b/primitives/consensus/aura/src/inherents.rs new file mode 100644 index 0000000000000..77ec03c6f4342 --- /dev/null +++ b/primitives/consensus/aura/src/inherents.rs @@ -0,0 +1,98 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +/// Contains the inherents for the AURA module + +use sp_inherents::{InherentIdentifier, InherentData, Error}; + +#[cfg(feature = "std")] +use sp_inherents::{InherentDataProviders, ProvideInherentData}; + +/// The Aura inherent identifier. +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"auraslot"; + +/// The type of the Aura inherent. +pub type InherentType = u64; + +/// Auxiliary trait to extract Aura inherent data. +pub trait AuraInherentData { + /// Get aura inherent data. + fn aura_inherent_data(&self) ->Result; + /// Replace aura inherent data. + fn aura_replace_inherent_data(&mut self, new: InherentType); +} + +impl AuraInherentData for InherentData { + fn aura_inherent_data(&self) ->Result { + self.get_data(&INHERENT_IDENTIFIER) + .and_then(|r| r.ok_or_else(|| "Aura inherent data not found".into())) + } + + fn aura_replace_inherent_data(&mut self, new: InherentType) { + self.replace_data(INHERENT_IDENTIFIER, &new); + } +} + +/// Provides the slot duration inherent data for `Aura`. +#[cfg(feature = "std")] +pub struct InherentDataProvider { + slot_duration: u64, +} + +#[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<(), Error> { + if !providers.has_provider(&sp_timestamp::INHERENT_IDENTIFIER) { + // Add the timestamp inherent data provider, as we require it. + providers.register_provider(sp_timestamp::InherentDataProvider) + } else { + Ok(()) + } + } + + fn inherent_identifier(&self) -> &'static InherentIdentifier { + &INHERENT_IDENTIFIER + } + + fn provide_inherent_data( + &self, + inherent_data: &mut InherentData, + ) ->Result<(), Error> { + use sp_timestamp::TimestampInherentData; + + 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 { + use codec::Decode; + + sp_inherents::Error::decode(&mut &error[..]).map(|e| e.into_string()).ok() + } +} diff --git a/primitives/consensus/aura/src/lib.rs b/primitives/consensus/aura/src/lib.rs new file mode 100644 index 0000000000000..4f2045666793a --- /dev/null +++ b/primitives/consensus/aura/src/lib.rs @@ -0,0 +1,91 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for Aura. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Encode, Decode, Codec}; +use sp_std::vec::Vec; +use sp_runtime::ConsensusEngineId; + +pub mod inherents; + +pub mod sr25519 { + mod app_sr25519 { + use sp_application_crypto::{app_crypto, key_types::AURA, sr25519}; + app_crypto!(sr25519, AURA); + } + + /// An Aura authority keypair using S/R 25519 as its crypto. + #[cfg(feature = "std")] + pub type AuthorityPair = app_sr25519::Pair; + + /// An Aura authority signature using S/R 25519 as its crypto. + pub type AuthoritySignature = app_sr25519::Signature; + + /// An Aura authority identifier using S/R 25519 as its crypto. + pub type AuthorityId = app_sr25519::Public; +} + +pub mod ed25519 { + mod app_ed25519 { + use sp_application_crypto::{app_crypto, key_types::AURA, ed25519}; + app_crypto!(ed25519, AURA); + } + + /// An Aura authority keypair using Ed25519 as its crypto. + #[cfg(feature = "std")] + pub type AuthorityPair = app_ed25519::Pair; + + /// An Aura authority signature using Ed25519 as its crypto. + pub type AuthoritySignature = app_ed25519::Signature; + + /// An Aura authority identifier using Ed25519 as its crypto. + pub type AuthorityId = app_ed25519::Public; +} + +/// The `ConsensusEngineId` of AuRa. +pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a']; + +/// The index of an authority. +pub type AuthorityIndex = u32; + +/// An consensus log item for Aura. +#[derive(Decode, Encode)] +pub enum ConsensusLog { + /// The authorities have changed. + #[codec(index = "1")] + AuthoritiesChange(Vec), + /// Disable the authority with given index. + #[codec(index = "2")] + OnDisabled(AuthorityIndex), +} + +sp_api::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; + + // Return the current set of authorities. + fn authorities() -> Vec; + } +} diff --git a/primitives/consensus/babe/Cargo.toml b/primitives/consensus/babe/Cargo.toml new file mode 100644 index 0000000000000..11c186faa9a1b --- /dev/null +++ b/primitives/consensus/babe/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "sp-consensus-babe" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "Primitives for BABE consensus" +edition = "2018" + +[dependencies] +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../../application-crypto" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-std = { version = "2.0.0", default-features = false, path = "../../std" } +schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated"], optional = true } +sp-api = { version = "2.0.0", default-features = false, path = "../../api" } +sp-consensus = { version = "0.8", optional = true, path = "../common" } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../inherents" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../runtime" } +sp-timestamp = { version = "2.0.0", default-features = false, path = "../../timestamp" } + +[features] +default = ["std"] +std = [ + "sp-application-crypto/std", + "codec/std", + "sp-std/std", + "schnorrkel", + "sp-api/std", + "sp-consensus", + "sp-inherents/std", + "sp-runtime/std", + "sp-timestamp/std", +] diff --git a/primitives/consensus/babe/src/digest.rs b/primitives/consensus/babe/src/digest.rs new file mode 100644 index 0000000000000..cca088b92bdd5 --- /dev/null +++ b/primitives/consensus/babe/src/digest.rs @@ -0,0 +1,284 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Private implementation details of BABE digests. + +#[cfg(feature = "std")] +use super::{BABE_ENGINE_ID, AuthoritySignature}; +#[cfg(not(feature = "std"))] +use super::{VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH}; +use super::{AuthorityId, AuthorityIndex, SlotNumber, BabeAuthorityWeight}; +#[cfg(feature = "std")] +use sp_runtime::{DigestItem, generic::OpaqueDigestItemId}; +#[cfg(feature = "std")] +use std::fmt::Debug; +use codec::{Decode, Encode}; +#[cfg(feature = "std")] +use codec::{Codec, Input, Error}; +#[cfg(feature = "std")] +use schnorrkel::{ + SignatureError, errors::MultiSignatureStage, + vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH} +}; +use sp_std::vec::Vec; + + +/// A BABE pre-runtime digest. This contains all data required to validate a +/// block and for the BABE runtime module. Slots can be assigned to a primary +/// (VRF based) and to a secondary (slot number based). +#[cfg(feature = "std")] +#[derive(Clone, Debug)] +pub enum BabePreDigest { + /// A primary VRF-based slot assignment. + Primary { + /// VRF output + vrf_output: VRFOutput, + /// VRF proof + vrf_proof: VRFProof, + /// Authority index + authority_index: super::AuthorityIndex, + /// Slot number + slot_number: SlotNumber, + }, + /// A secondary deterministic slot assignment. + Secondary { + /// Authority index + authority_index: super::AuthorityIndex, + /// Slot number + slot_number: SlotNumber, + }, +} + +#[cfg(feature = "std")] +impl BabePreDigest { + /// Returns the slot number of the pre digest. + pub fn authority_index(&self) -> AuthorityIndex { + match self { + BabePreDigest::Primary { authority_index, .. } => *authority_index, + BabePreDigest::Secondary { authority_index, .. } => *authority_index, + } + } + + /// Returns the slot number of the pre digest. + pub fn slot_number(&self) -> SlotNumber { + match self { + BabePreDigest::Primary { slot_number, .. } => *slot_number, + BabePreDigest::Secondary { slot_number, .. } => *slot_number, + } + } + + /// Returns the weight _added_ by this digest, not the cumulative weight + /// of the chain. + pub fn added_weight(&self) -> crate::BabeBlockWeight { + match self { + BabePreDigest::Primary { .. } => 1, + BabePreDigest::Secondary { .. } => 0, + } + } +} + +/// The prefix used by BABE for its VRF keys. +pub const BABE_VRF_PREFIX: &[u8] = b"substrate-babe-vrf"; + +/// A raw version of `BabePreDigest`, usable on `no_std`. +#[derive(Copy, Clone, Encode, Decode)] +pub enum RawBabePreDigest { + /// A primary VRF-based slot assignment. + #[codec(index = "1")] + Primary { + /// Authority index + authority_index: AuthorityIndex, + /// Slot number + slot_number: SlotNumber, + /// VRF output + vrf_output: [u8; VRF_OUTPUT_LENGTH], + /// VRF proof + vrf_proof: [u8; VRF_PROOF_LENGTH], + }, + /// A secondary deterministic slot assignment. + #[codec(index = "2")] + Secondary { + /// Authority index + /// + /// This is not strictly-speaking necessary, since the secondary slots + /// are assigned based on slot number and epoch randomness. But including + /// it makes things easier for higher-level users of the chain data to + /// be aware of the author of a secondary-slot block. + authority_index: AuthorityIndex, + /// Slot number + slot_number: SlotNumber, + }, +} + +impl RawBabePreDigest { + /// Returns the slot number of the pre digest. + pub fn slot_number(&self) -> SlotNumber { + match self { + RawBabePreDigest::Primary { slot_number, .. } => *slot_number, + RawBabePreDigest::Secondary { slot_number, .. } => *slot_number, + } + } +} + +#[cfg(feature = "std")] +impl Encode for BabePreDigest { + fn encode(&self) -> Vec { + let raw = match self { + BabePreDigest::Primary { + vrf_output, + vrf_proof, + authority_index, + slot_number, + } => { + RawBabePreDigest::Primary { + vrf_output: *vrf_output.as_bytes(), + vrf_proof: vrf_proof.to_bytes(), + authority_index: *authority_index, + slot_number: *slot_number, + } + }, + BabePreDigest::Secondary { + authority_index, + slot_number, + } => { + RawBabePreDigest::Secondary { + authority_index: *authority_index, + slot_number: *slot_number, + } + }, + }; + + codec::Encode::encode(&raw) + } +} + +#[cfg(feature = "std")] +impl codec::EncodeLike for BabePreDigest {} + +#[cfg(feature = "std")] +impl Decode for BabePreDigest { + fn decode(i: &mut R) -> Result { + let pre_digest = match Decode::decode(i)? { + RawBabePreDigest::Primary { vrf_output, vrf_proof, authority_index, slot_number } => { + // Verify (at compile time) that the sizes in babe_primitives are correct + let _: [u8; super::VRF_OUTPUT_LENGTH] = vrf_output; + let _: [u8; super::VRF_PROOF_LENGTH] = vrf_proof; + + BabePreDigest::Primary { + vrf_proof: VRFProof::from_bytes(&vrf_proof).map_err(convert_error)?, + vrf_output: VRFOutput::from_bytes(&vrf_output).map_err(convert_error)?, + authority_index, + slot_number, + } + }, + RawBabePreDigest::Secondary { authority_index, slot_number } => { + BabePreDigest::Secondary { authority_index, slot_number } + }, + }; + + Ok(pre_digest) + } +} + +/// Information about the next epoch. This is broadcast in the first block +/// of the epoch. +#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, sp_runtime::RuntimeDebug)] +pub struct NextEpochDescriptor { + /// The authorities. + pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + + /// The value of randomness to use for the slot-assignment. + pub randomness: [u8; VRF_OUTPUT_LENGTH], +} + +/// A digest item which is usable with BABE consensus. +#[cfg(feature = "std")] +pub trait CompatibleDigestItem: Sized { + /// Construct a digest item which contains a BABE pre-digest. + fn babe_pre_digest(seal: BabePreDigest) -> Self; + + /// If this item is an BABE pre-digest, return it. + fn as_babe_pre_digest(&self) -> Option; + + /// Construct a digest item which contains a BABE seal. + fn babe_seal(signature: AuthoritySignature) -> Self; + + /// If this item is a BABE signature, return the signature. + fn as_babe_seal(&self) -> Option; + + /// If this item is a BABE epoch, return it. + fn as_next_epoch_descriptor(&self) -> Option; +} + +#[cfg(feature = "std")] +impl CompatibleDigestItem for DigestItem where + Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static +{ + fn babe_pre_digest(digest: BabePreDigest) -> Self { + DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode()) + } + + fn as_babe_pre_digest(&self) -> Option { + self.try_to(OpaqueDigestItemId::PreRuntime(&BABE_ENGINE_ID)) + } + + fn babe_seal(signature: AuthoritySignature) -> Self { + DigestItem::Seal(BABE_ENGINE_ID, signature.encode()) + } + + fn as_babe_seal(&self) -> Option { + self.try_to(OpaqueDigestItemId::Seal(&BABE_ENGINE_ID)) + } + + fn as_next_epoch_descriptor(&self) -> Option { + self.try_to(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)) + .and_then(|x: super::ConsensusLog| match x { + super::ConsensusLog::NextEpochData(n) => Some(n), + _ => None, + }) + } +} + +#[cfg(feature = "std")] +fn convert_error(e: SignatureError) -> codec::Error { + use SignatureError::*; + use MultiSignatureStage::*; + match e { + EquationFalse => "Signature error: `EquationFalse`".into(), + PointDecompressionError => "Signature error: `PointDecompressionError`".into(), + ScalarFormatError => "Signature error: `ScalarFormatError`".into(), + NotMarkedSchnorrkel => "Signature error: `NotMarkedSchnorrkel`".into(), + BytesLengthError { .. } => "Signature error: `BytesLengthError`".into(), + MuSigAbsent { musig_stage: Commitment } => + "Signature error: `MuSigAbsent` at stage `Commitment`".into(), + MuSigAbsent { musig_stage: Reveal } => + "Signature error: `MuSigAbsent` at stage `Reveal`".into(), + MuSigAbsent { musig_stage: Cosignature } => + "Signature error: `MuSigAbsent` at stage `Commitment`".into(), + MuSigInconsistent { musig_stage: Commitment, duplicate: true } => + "Signature error: `MuSigInconsistent` at stage `Commitment` on duplicate".into(), + MuSigInconsistent { musig_stage: Commitment, duplicate: false } => + "Signature error: `MuSigInconsistent` at stage `Commitment` on not duplicate".into(), + MuSigInconsistent { musig_stage: Reveal, duplicate: true } => + "Signature error: `MuSigInconsistent` at stage `Reveal` on duplicate".into(), + MuSigInconsistent { musig_stage: Reveal, duplicate: false } => + "Signature error: `MuSigInconsistent` at stage `Reveal` on not duplicate".into(), + MuSigInconsistent { musig_stage: Cosignature, duplicate: true } => + "Signature error: `MuSigInconsistent` at stage `Cosignature` on duplicate".into(), + MuSigInconsistent { musig_stage: Cosignature, duplicate: false } => + "Signature error: `MuSigInconsistent` at stage `Cosignature` on not duplicate".into(), + } +} diff --git a/primitives/consensus/babe/src/inherents.rs b/primitives/consensus/babe/src/inherents.rs new file mode 100644 index 0000000000000..7c0744ac6e13a --- /dev/null +++ b/primitives/consensus/babe/src/inherents.rs @@ -0,0 +1,90 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . +//! Inherents for BABE + +use sp_inherents::{Error, InherentData, InherentIdentifier}; +#[cfg(feature = "std")] +use sp_inherents::{InherentDataProviders, ProvideInherentData}; +#[cfg(feature = "std")] +use sp_timestamp::TimestampInherentData; + +#[cfg(feature = "std")] +use codec::Decode; +use sp_std::result::Result; + +/// The BABE inherent identifier. +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot"; + +/// The type of the BABE inherent. +pub type InherentType = u64; +/// Auxiliary trait to extract BABE inherent data. +pub trait BabeInherentData { + /// Get BABE inherent data. + fn babe_inherent_data(&self) -> Result; + /// Replace BABE inherent data. + fn babe_replace_inherent_data(&mut self, new: InherentType); +} + +impl BabeInherentData for InherentData { + fn babe_inherent_data(&self) -> Result { + self.get_data(&INHERENT_IDENTIFIER) + .and_then(|r| r.ok_or_else(|| "BABE inherent data not found".into())) + } + + fn babe_replace_inherent_data(&mut self, new: InherentType) { + self.replace_data(INHERENT_IDENTIFIER, &new); + } +} + +/// Provides the slot duration inherent data for BABE. +#[cfg(feature = "std")] +pub struct InherentDataProvider { + slot_duration: u64, +} + +#[cfg(feature = "std")] +impl InherentDataProvider { + /// Constructs `Self` + pub fn new(slot_duration: u64) -> Self { + Self { slot_duration } + } +} + +#[cfg(feature = "std")] +impl ProvideInherentData for InherentDataProvider { + fn on_register(&self, providers: &InherentDataProviders) -> Result<(), Error> { + if !providers.has_provider(&sp_timestamp::INHERENT_IDENTIFIER) { + // Add the timestamp inherent data provider, as we require it. + providers.register_provider(sp_timestamp::InherentDataProvider) + } else { + Ok(()) + } + } + + fn inherent_identifier(&self) -> &'static InherentIdentifier { + &INHERENT_IDENTIFIER + } + + fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> { + let timestamp = inherent_data.timestamp_inherent_data()?; + let slot_number = timestamp / self.slot_duration; + inherent_data.put_data(INHERENT_IDENTIFIER, &slot_number) + } + + fn error_to_string(&self, error: &[u8]) -> Option { + Error::decode(&mut &error[..]).map(|e| e.into_string()).ok() + } +} diff --git a/primitives/consensus/babe/src/lib.rs b/primitives/consensus/babe/src/lib.rs new file mode 100644 index 0000000000000..4cdeb072bd5e9 --- /dev/null +++ b/primitives/consensus/babe/src/lib.rs @@ -0,0 +1,177 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for BABE. +#![deny(warnings)] +#![forbid(unsafe_code, missing_docs, unused_variables, unused_imports)] +#![cfg_attr(not(feature = "std"), no_std)] + +mod digest; +pub mod inherents; + +use codec::{Encode, Decode}; +use sp_std::vec::Vec; +use sp_runtime::{ConsensusEngineId, RuntimeDebug}; + +#[cfg(feature = "std")] +pub use digest::{BabePreDigest, CompatibleDigestItem}; +pub use digest::{BABE_VRF_PREFIX, RawBabePreDigest, NextEpochDescriptor}; + +mod app { + use sp_application_crypto::{app_crypto, key_types::BABE, sr25519}; + app_crypto!(sr25519, BABE); +} + +/// A Babe authority keypair. Necessarily equivalent to the schnorrkel public key used in +/// the main Babe module. If that ever changes, then this must, too. +#[cfg(feature = "std")] +pub type AuthorityPair = app::Pair; + +/// A Babe authority signature. +pub type AuthoritySignature = app::Signature; + +/// A Babe authority identifier. Necessarily equivalent to the schnorrkel public key used in +/// the main Babe module. If that ever changes, then this must, too. +pub type AuthorityId = app::Public; + +/// The `ConsensusEngineId` of BABE. +pub const BABE_ENGINE_ID: ConsensusEngineId = *b"BABE"; + +/// The length of the VRF output +pub const VRF_OUTPUT_LENGTH: usize = 32; + +/// The length of the VRF proof +pub const VRF_PROOF_LENGTH: usize = 64; + +/// The length of the public key +pub const PUBLIC_KEY_LENGTH: usize = 32; + +/// How many blocks to wait before running the median algorithm for relative time +/// This will not vary from chain to chain as it is not dependent on slot duration +/// or epoch length. +pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by w3f-research. + +/// The index of an authority. +pub type AuthorityIndex = u32; + +/// A slot number. +pub type SlotNumber = u64; + +/// The weight of an authority. +// NOTE: we use a unique name for the weight to avoid conflicts with other +// `Weight` types, since the metadata isn't able to disambiguate. +pub type BabeAuthorityWeight = u64; + +/// The weight of a BABE block. +pub type BabeBlockWeight = u32; + +/// BABE epoch information +#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, RuntimeDebug)] +pub struct Epoch { + /// The epoch index + pub epoch_index: u64, + /// The starting slot of the epoch, + pub start_slot: SlotNumber, + /// The duration of this epoch + pub duration: SlotNumber, + /// The authorities and their weights + pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + /// Randomness for this epoch + pub randomness: [u8; VRF_OUTPUT_LENGTH], +} + +impl Epoch { + /// "increment" the epoch, with given descriptor for the next. + pub fn increment(&self, descriptor: NextEpochDescriptor) -> Epoch { + Epoch { + epoch_index: self.epoch_index + 1, + start_slot: self.start_slot + self.duration, + duration: self.duration, + authorities: descriptor.authorities, + randomness: descriptor.randomness, + } + } + + /// Produce the "end slot" of the epoch. This is NOT inclusive to the epoch, + // i.e. the slots covered by the epoch are `self.start_slot .. self.end_slot()`. + pub fn end_slot(&self) -> SlotNumber { + self.start_slot + self.duration + } +} + +/// An consensus log item for BABE. +#[derive(Decode, Encode, Clone, PartialEq, Eq)] +pub enum ConsensusLog { + /// The epoch has changed. This provides information about the _next_ + /// epoch - information about the _current_ epoch (i.e. the one we've just + /// entered) should already be available earlier in the chain. + #[codec(index = "1")] + NextEpochData(NextEpochDescriptor), + /// Disable the authority with given index. + #[codec(index = "2")] + OnDisabled(AuthorityIndex), +} + +/// Configuration data used by the BABE consensus engine. +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub struct BabeConfiguration { + /// The slot duration in milliseconds for BABE. Currently, only + /// the value provided by this type at genesis will be used. + /// + /// Dynamic slot duration may be supported in the future. + pub slot_duration: u64, + + /// The duration of epochs in slots. + pub epoch_length: SlotNumber, + + /// A constant value that is used in the threshold calculation formula. + /// Expressed as a rational where the first member of the tuple is the + /// numerator and the second is the denominator. The rational should + /// represent a value between 0 and 1. + /// In the threshold formula calculation, `1 - c` represents the probability + /// of a slot being empty. + pub c: (u64, u64), + + /// The authorities for the genesis epoch. + pub genesis_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + + /// The randomness for the genesis epoch. + pub randomness: [u8; VRF_OUTPUT_LENGTH], + + /// Whether this chain should run with secondary slots, which are assigned + /// in round-robin manner. + pub secondary_slots: bool, +} + +#[cfg(feature = "std")] +impl sp_consensus::SlotData for BabeConfiguration { + fn slot_duration(&self) -> u64 { + self.slot_duration + } + + const SLOT_KEY: &'static [u8] = b"babe_configuration"; +} + +sp_api::decl_runtime_apis! { + /// API necessary for block authorship with BABE. + pub trait BabeApi { + /// Return the configuration for BABE. Currently, + /// only the value provided by this type at genesis will be used. + /// + /// Dynamic configuration may be supported in the future. + fn configuration() -> BabeConfiguration; + } +} diff --git a/primitives/consensus/common/Cargo.toml b/primitives/consensus/common/Cargo.toml new file mode 100644 index 0000000000000..4c38e31914700 --- /dev/null +++ b/primitives/consensus/common/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "sp-consensus" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "Common utilities for substrate consensus" +edition = "2018" + +[dependencies] +derive_more = "0.99.2" +libp2p = { version = "0.14.0-alpha.1", default-features = false } +log = "0.4.8" +sp-core = { path= "../../core" } +sp-inherents = { version = "2.0.0", path = "../../inherents" } +sp-state-machine = { version = "2.0.0", path = "../../../primitives/state-machine" } +futures = { version = "0.3.1", features = ["thread-pool"] } +futures-timer = "0.4.0" +sp-std = { version = "2.0.0", path = "../../std" } +sp-version = { version = "2.0.0", path = "../../version" } +sp-runtime = { version = "2.0.0", path = "../../runtime" } +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } +parking_lot = "0.9.0" + +[dev-dependencies] +sp-test-primitives = { version = "2.0.0", path = "../../test-primitives" } + +[features] +default = [] diff --git a/primitives/consensus/common/src/block_import.rs b/primitives/consensus/common/src/block_import.rs new file mode 100644 index 0000000000000..f8d05e10548d2 --- /dev/null +++ b/primitives/consensus/common/src/block_import.rs @@ -0,0 +1,322 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Block import helpers. + +use sp_runtime::{ + Justification, + traits::{Block as BlockT, DigestItemFor, Header as HeaderT, NumberFor, HasherFor}, +}; +use std::borrow::Cow; +use std::collections::HashMap; +use std::sync::Arc; + +use crate::import_queue::{Verifier, CacheKeyId}; + +/// Block import result. +#[derive(Debug, PartialEq, Eq)] +pub enum ImportResult { + /// Block imported. + Imported(ImportedAux), + /// Already in the blockchain. + AlreadyInChain, + /// Block or parent is known to be bad. + KnownBad, + /// Block parent is not in the chain. + UnknownParent, + /// Parent state is missing. + MissingState, +} + +/// Auxiliary data associated with an imported block result. +#[derive(Debug, Default, PartialEq, Eq)] +pub struct ImportedAux { + /// Only the header has been imported. Block body verification was skipped. + pub header_only: bool, + /// 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, + /// Request a finality proof for the given block. + pub needs_finality_proof: bool, + /// Whether the block that was imported is the new best block. + pub is_new_best: bool, +} + +impl ImportResult { + /// Returns default value for `ImportResult::Imported` with + /// `clear_justification_requests`, `needs_justification`, + /// `bad_justification` and `needs_finality_proof` set to false. + pub fn imported(is_new_best: bool) -> ImportResult { + let mut aux = ImportedAux::default(); + aux.is_new_best = is_new_best; + + ImportResult::Imported(aux) + } +} + +/// Block data origin. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum BlockOrigin { + /// Genesis block built into the client. + Genesis, + /// Block is part of the initial sync with the network. + NetworkInitialSync, + /// Block was broadcasted on the network. + NetworkBroadcast, + /// Block that was received from the network and validated in the consensus process. + ConsensusBroadcast, + /// Block that was collated by this node. + Own, + /// Block was imported from a file. + 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 check validity of a Block. +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct BlockCheckParams { + /// Hash of the block that we verify. + pub hash: Block::Hash, + /// Block number of the block that we verify. + pub number: NumberFor, + /// Parent hash of the block that we verify. + pub parent_hash: Block::Hash, + /// Allow importing the block skipping state verification if parent state is missing. + pub allow_missing_state: bool, + /// Re-validate existing block. + pub import_existing: bool, +} + +/// Data required to import a Block. +pub struct BlockImportParams { + /// Origin of the Block + pub origin: BlockOrigin, + /// The header, without consensus post-digests applied. This should be in the same + /// state as it comes out of the runtime. + /// + /// Consensus engines which alter the header (by adding post-runtime digests) + /// should strip those off in the initial verification process and pass them + /// via the `post_digests` field. During block authorship, they should + /// not be pushed to the header directly. + /// + /// The reason for this distinction is so the header can be directly + /// re-executed in a runtime that checks digest equivalence -- the + /// post-runtime digests are pushed back on after. + pub header: Block::Header, + /// Justification provided for this block from the outside. + pub justification: Option, + /// Digest items that have been added after the runtime for external + /// work, like a consensus signature. + pub post_digests: Vec>, + /// The body of the block. + pub body: Option>, + /// The changes to the storage to create the state for the block. If this is `Some(_)`, + /// the block import will not need to re-execute the block for importing it. + pub storage_changes: Option< + sp_state_machine::StorageChanges, NumberFor> + >, + /// Is this block finalized already? + /// `true` implies instant finality. + pub finalized: bool, + /// Auxiliary consensus data produced by the block. + /// 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. This should only be set by a + /// synchronous import, otherwise it may race against other imports. + pub fork_choice: ForkChoiceStrategy, + /// Allow importing the block skipping state verification if parent state is missing. + pub allow_missing_state: bool, + /// Re-validate existing block. + pub import_existing: bool, +} + +impl BlockImportParams { + /// Deconstruct the justified header into parts. + pub fn into_inner(self) + -> ( + BlockOrigin, + ::Header, + Option, + Vec>, + Option>, + Option, NumberFor>>, + bool, + Vec<(Vec, Option>)>, + ) { + ( + self.origin, + self.header, + self.justification, + self.post_digests, + self.body, + self.storage_changes, + self.finalized, + self.auxiliary, + ) + } + + /// Get a handle to full header (with post-digests applied). + pub fn post_header(&self) -> Cow { + if self.post_digests.is_empty() { + Cow::Borrowed(&self.header) + } else { + Cow::Owned({ + let mut hdr = self.header.clone(); + for digest_item in &self.post_digests { + hdr.digest_mut().push(digest_item.clone()); + } + + hdr + }) + } + } + + /// Auxiliary function for "converting" the transaction type. + /// + /// Actually this just sets `storage_changes` to `None` and makes rustc think that `Self` now + /// uses a different transaction type. + pub fn convert_transaction(self) -> BlockImportParams { + BlockImportParams { + origin: self.origin, + header: self.header, + justification: self.justification, + post_digests: self.post_digests, + body: self.body, + storage_changes: None, + finalized: self.finalized, + auxiliary: self.auxiliary, + allow_missing_state: self.allow_missing_state, + fork_choice: self.fork_choice, + import_existing: self.import_existing, + } + } +} + +/// Block import trait. +pub trait BlockImport { + /// The error type. + type Error: std::error::Error + Send + 'static; + /// The transaction type used by the backend. + type Transaction; + + /// Check block preconditions. + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result; + + /// Import a block. + /// + /// Cached data can be accessed through the blockchain cache. + fn import_block( + &mut self, + block: BlockImportParams, + cache: HashMap>, + ) -> Result; +} + +impl BlockImport for crate::import_queue::BoxBlockImport { + type Error = crate::error::Error; + type Transaction = Transaction; + + /// Check block preconditions. + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + (**self).check_block(block) + } + + /// Import a block. + /// + /// Cached data can be accessed through the blockchain cache. + fn import_block( + &mut self, + block: BlockImportParams, + cache: HashMap>, + ) -> Result { + (**self).import_block(block, cache) + } +} + +impl BlockImport for Arc + where for<'r> &'r T: BlockImport +{ + type Error = E; + type Transaction = Transaction; + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + (&**self).check_block(block) + } + + fn import_block( + &mut self, + block: BlockImportParams, + cache: HashMap>, + ) -> Result { + (&**self).import_block(block, cache) + } +} + +/// Justification import trait +pub trait JustificationImport { + type Error: std::error::Error + Send + 'static; + + /// Called by the import queue when it is started. Returns a list of justifications to request + /// from the network. + fn on_start(&mut self) -> Vec<(B::Hash, NumberFor)> { Vec::new() } + + /// Import a Block justification and finalize the given block. + fn import_justification( + &mut self, + hash: B::Hash, + number: NumberFor, + justification: Justification, + ) -> Result<(), Self::Error>; +} + +/// Finality proof import trait. +pub trait FinalityProofImport { + type Error: std::error::Error + Send + 'static; + + /// Called by the import queue when it is started. Returns a list of finality proofs to request + /// from the network. + fn on_start(&mut self) -> Vec<(B::Hash, NumberFor)> { Vec::new() } + + /// Import a Block justification and finalize the given block. Returns finalized block or error. + fn import_finality_proof( + &mut self, + hash: B::Hash, + number: NumberFor, + finality_proof: Vec, + verifier: &mut dyn Verifier, + ) -> Result<(B::Hash, NumberFor), Self::Error>; +} diff --git a/core/consensus/common/src/block_validation.rs b/primitives/consensus/common/src/block_validation.rs similarity index 95% rename from core/consensus/common/src/block_validation.rs rename to primitives/consensus/common/src/block_validation.rs index be181b05c6f4d..e8054f3ae40d7 100644 --- a/core/consensus/common/src/block_validation.rs +++ b/primitives/consensus/common/src/block_validation.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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 @@ //! Block announcement validation. use crate::BlockStatus; -use sr_primitives::{generic::BlockId, traits::Block}; +use sp_runtime::{generic::BlockId, traits::Block}; use std::{error::Error, sync::Arc}; /// A type which provides access to chain information. diff --git a/primitives/consensus/common/src/error.rs b/primitives/consensus/common/src/error.rs new file mode 100644 index 0000000000000..972e4a2d48b21 --- /dev/null +++ b/primitives/consensus/common/src/error.rs @@ -0,0 +1,86 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Error types in Consensus +use sp_version::RuntimeVersion; +use sp_core::ed25519::{Public, Signature}; +use std::error; + +/// Result type alias. +pub type Result = std::result::Result; + +/// Error type. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Missing state at block with given descriptor. + #[display(fmt="State unavailable at block {}", _0)] + StateUnavailable(String), + /// I/O terminated unexpectedly + #[display(fmt="I/O terminated unexpectedly.")] + IoTerminated, + /// Unable to schedule wakeup. + #[display(fmt="Timer error: {}", _0)] + FaultyTimer(std::io::Error), + /// Error while working with inherent data. + #[display(fmt="InherentData error: {}", _0)] + InherentData(sp_inherents::Error), + /// Unable to propose a block. + #[display(fmt="Unable to create block proposal.")] + CannotPropose, + /// Error checking signature + #[display(fmt="Message signature {:?} by {:?} is invalid.", _0, _1)] + InvalidSignature(Signature, Public), + /// Invalid authorities set received from the runtime. + #[display(fmt="Current state of blockchain has invalid authorities set")] + InvalidAuthoritiesSet, + /// Account is not an authority. + #[display(fmt="Message sender {:?} is not a valid authority.", _0)] + InvalidAuthority(Public), + /// Authoring interface does not match the runtime. + #[display(fmt="Authoring for current \ + runtime is not supported. Native ({}) cannot author for on-chain ({}).", native, on_chain)] + IncompatibleAuthoringRuntime { native: RuntimeVersion, on_chain: RuntimeVersion }, + /// Authoring interface does not match the runtime. + #[display(fmt="Authoring for current runtime is not supported since it has no version.")] + RuntimeVersionMissing, + /// Authoring interface does not match the runtime. + #[display(fmt="Authoring in current build is not supported since it has no runtime.")] + NativeRuntimeMissing, + /// Justification requirements not met. + #[display(fmt="Invalid justification.")] + InvalidJustification, + /// Some other error. + #[display(fmt="Other error: {}", _0)] + Other(Box), + /// Error from the client while importing + #[display(fmt="Import failed: {}", _0)] + #[from(ignore)] + ClientImport(String), + /// Error from the client while importing + #[display(fmt="Chain lookup failed: {}", _0)] + #[from(ignore)] + ChainLookup(String), +} + +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + Error::FaultyTimer(ref err) => Some(err), + Error::Other(ref err) => Some(&**err), + _ => None, + } + } +} diff --git a/core/consensus/common/src/evaluation.rs b/primitives/consensus/common/src/evaluation.rs similarity index 95% rename from core/consensus/common/src/evaluation.rs rename to primitives/consensus/common/src/evaluation.rs index 7a3e565aa09d1..5542042fedb1c 100644 --- a/core/consensus/common/src/evaluation.rs +++ b/primitives/consensus/common/src/evaluation.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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 super::MAX_BLOCK_SIZE; use codec::Encode; -use sr_primitives::traits::{Block as BlockT, Header as HeaderT, One, CheckedConversion}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, One, CheckedConversion}; // This is just a best effort to encode the number. None indicated that it's too big to encode // in a u128. diff --git a/core/consensus/common/src/import_queue.rs b/primitives/consensus/common/src/import_queue.rs similarity index 85% rename from core/consensus/common/src/import_queue.rs rename to primitives/consensus/common/src/import_queue.rs index dc1678fcf189d..2da0bcac0c17b 100644 --- a/core/consensus/common/src/import_queue.rs +++ b/primitives/consensus/common/src/import_queue.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -26,7 +26,7 @@ //! queues to be instantiated simply. use std::collections::HashMap; -use sr_primitives::{Justification, traits::{Block as BlockT, Header as _, NumberFor}}; +use sp_runtime::{Justification, traits::{Block as BlockT, Header as _, NumberFor}}; use crate::error::Error as ConsensusError; use crate::block_import::{ BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult, @@ -39,13 +39,17 @@ mod basic_queue; pub mod buffered_link; /// Shared block import struct used by the queue. -pub type BoxBlockImport = Box + Send + Sync>; +pub type BoxBlockImport = Box< + dyn BlockImport + Send + Sync +>; /// Shared justification import struct used by the queue. pub type BoxJustificationImport = Box + Send + Sync>; /// Shared finality proof import struct used by the queue. -pub type BoxFinalityProofImport = Box + Send + Sync>; +pub type BoxFinalityProofImport = Box< + dyn FinalityProofImport + Send + Sync +>; /// Maps to the Origin used by the network. pub type Origin = libp2p::PeerId; @@ -63,6 +67,10 @@ pub struct IncomingBlock { pub justification: Option, /// The peer, we received this from pub origin: Option, + /// Allow importing the block skipping state verification if parent state is missing. + pub allow_missing_state: bool, + /// Re-validate existing block. + pub import_existing: bool, } /// Type of keys in the blockchain cache that consensus module could use for its needs. @@ -79,7 +87,7 @@ pub trait Verifier: Send + Sync { header: B::Header, justification: Option, body: Option>, - ) -> Result<(BlockImportParams, Option)>>), String>; + ) -> Result<(BlockImportParams, Option)>>), String>; } /// Blocks import queue API. @@ -161,6 +169,8 @@ pub enum BlockImportError { VerificationFailed(Option, String), /// Block is known to be Bad BadBlock(Option), + /// Parent state is missing. + MissingState, /// Block has an unknown parent UnknownParent, /// Block import has been cancelled. This can happen if the parent block fails to be imported. @@ -170,8 +180,8 @@ pub enum BlockImportError { } /// Single block import function. -pub fn import_single_block>( - import_handle: &mut dyn BlockImport, +pub fn import_single_block, Transaction>( + import_handle: &mut dyn BlockImport, block_origin: BlockOrigin, block: IncomingBlock, verifier: &mut V, @@ -203,6 +213,10 @@ pub fn import_single_block>( Ok(BlockImportResult::ImportedKnown(number)) }, Ok(ImportResult::Imported(aux)) => Ok(BlockImportResult::ImportedUnknown(number, aux, peer.clone())), + Ok(ImportResult::MissingState) => { + debug!(target: "sync", "Parent state is missing for {}: {:?}, parent: {:?}", number, hash, parent_hash); + Err(BlockImportError::MissingState) + }, Ok(ImportResult::UnknownParent) => { debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent_hash); Err(BlockImportError::UnknownParent) @@ -217,12 +231,18 @@ pub fn import_single_block>( } } }; - match import_error(import_handle.check_block(BlockCheckParams { hash, number, parent_hash }))? { + match import_error(import_handle.check_block(BlockCheckParams { + hash, + number, + parent_hash, + allow_missing_state: block.allow_missing_state, + import_existing: block.import_existing, + }))? { BlockImportResult::ImportedUnknown { .. } => (), r => return Ok(r), // Any other successful result means that the block is already imported. } - let (import_block, maybe_keys) = verifier.verify(block_origin, header, justification, block.body) + let (mut import_block, maybe_keys) = verifier.verify(block_origin, header, justification, block.body) .map_err(|msg| { if let Some(ref peer) = peer { trace!(target: "sync", "Verifying {}({}) from {} failed: {}", number, hash, peer, msg); @@ -236,6 +256,7 @@ pub fn import_single_block>( if let Some(keys) = maybe_keys { cache.extend(keys.into_iter()); } + import_block.allow_missing_state = block.allow_missing_state; - import_error(import_handle.import_block(import_block, cache)) + import_error(import_handle.import_block(import_block.convert_transaction(), cache)) } diff --git a/core/consensus/common/src/import_queue/basic_queue.rs b/primitives/consensus/common/src/import_queue/basic_queue.rs similarity index 89% rename from core/consensus/common/src/import_queue/basic_queue.rs rename to primitives/consensus/common/src/import_queue/basic_queue.rs index 2ab6d0c5e3b7d..4dcb7eeb45047 100644 --- a/core/consensus/common/src/import_queue/basic_queue.rs +++ b/primitives/consensus/common/src/import_queue/basic_queue.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 std::{mem, pin::Pin, time::Duration}; +use std::{mem, pin::Pin, time::Duration, marker::PhantomData}; use futures::{prelude::*, channel::mpsc, task::Context, task::Poll}; use futures_timer::Delay; -use sr_primitives::{Justification, traits::{Block as BlockT, Header as HeaderT, NumberFor}}; +use sp_runtime::{Justification, traits::{Block as BlockT, Header as HeaderT, NumberFor}}; use crate::block_import::BlockOrigin; use crate::import_queue::{ @@ -29,7 +29,7 @@ use crate::import_queue::{ /// Interface to a basic block import queue that is importing blocks sequentially in a separate /// task, with pluggable verification. -pub struct BasicQueue { +pub struct BasicQueue { /// Channel to send messages to the background task. sender: mpsc::UnboundedSender>, /// Results coming from the worker task. @@ -40,16 +40,17 @@ pub struct BasicQueue { manual_poll: Option + Send>>>, /// A thread pool where the background worker is being run. pool: Option, + _phantom: PhantomData, } -impl BasicQueue { +impl BasicQueue { /// Instantiate a new basic queue, with given verifier. /// /// This creates a background task, and calls `on_start` on the justification importer and /// finality proof importer. pub fn new>( verifier: V, - block_import: BoxBlockImport, + block_import: BoxBlockImport, justification_import: Option>, finality_proof_import: Option>, ) -> Self { @@ -81,11 +82,12 @@ impl BasicQueue { result_port, manual_poll, pool, + _phantom: PhantomData, } } } -impl ImportQueue for BasicQueue { +impl ImportQueue for BasicQueue { fn import_blocks(&mut self, origin: BlockOrigin, blocks: Vec>) { if blocks.is_empty() { return; @@ -102,12 +104,24 @@ impl ImportQueue for BasicQueue { number: NumberFor, justification: Justification ) { - let _ = self.sender.unbounded_send(ToWorkerMsg::ImportJustification(who.clone(), hash, number, justification)); + let _ = self.sender + .unbounded_send( + ToWorkerMsg::ImportJustification(who.clone(), hash, number, justification) + ); } - fn import_finality_proof(&mut self, who: Origin, hash: B::Hash, number: NumberFor, finality_proof: Vec) { + fn import_finality_proof( + &mut self, + who: Origin, + hash: B::Hash, + number: NumberFor, + finality_proof: Vec, + ) { trace!(target: "sync", "Scheduling finality proof of {}/{} for import", number, hash); - let _ = self.sender.unbounded_send(ToWorkerMsg::ImportFinalityProof(who, hash, number, finality_proof)); + let _ = self.sender + .unbounded_send( + ToWorkerMsg::ImportFinalityProof(who, hash, number, finality_proof) + ); } fn poll_actions(&mut self, cx: &mut Context, link: &mut dyn Link) { @@ -132,18 +146,19 @@ enum ToWorkerMsg { ImportFinalityProof(Origin, B::Hash, NumberFor, Vec), } -struct BlockImportWorker { +struct BlockImportWorker { result_sender: BufferedLinkSender, justification_import: Option>, finality_proof_import: Option>, delay_between_blocks: Duration, + _phantom: PhantomData, } -impl BlockImportWorker { +impl BlockImportWorker { fn new>( result_sender: BufferedLinkSender, verifier: V, - block_import: BoxBlockImport, + block_import: BoxBlockImport, justification_import: Option>, finality_proof_import: Option>, ) -> (impl Future + Send, mpsc::UnboundedSender>) { @@ -154,6 +169,7 @@ impl BlockImportWorker { justification_import, finality_proof_import, delay_between_blocks: Duration::new(0, 0), + _phantom: PhantomData, }; // Let's initialize `justification_import` and `finality_proof_import`. @@ -237,11 +253,11 @@ impl BlockImportWorker { /// yielded back in the output once the import is finished. fn import_a_batch_of_blocks>( &mut self, - block_import: BoxBlockImport, + block_import: BoxBlockImport, verifier: V, origin: BlockOrigin, blocks: Vec> - ) -> impl Future, V)> { + ) -> impl Future, V)> { let mut result_sender = self.result_sender.clone(); import_many_blocks(block_import, origin, blocks, verifier, self.delay_between_blocks) @@ -309,16 +325,22 @@ impl BlockImportWorker { /// /// The returned `Future` yields at every imported block, which makes the execution more /// fine-grained and making it possible to interrupt the process. -fn import_many_blocks>( - import_handle: BoxBlockImport, +fn import_many_blocks, Transaction>( + import_handle: BoxBlockImport, blocks_origin: BlockOrigin, blocks: Vec>, verifier: V, delay_between_blocks: Duration, -) -> impl Future>, BlockImportError>, - B::Hash, -)>, BoxBlockImport, V)> { +) -> impl Future< + Output = ( + usize, + usize, + Vec<(Result>, BlockImportError>, B::Hash,)>, + BoxBlockImport, + V + ) +> +{ let count = blocks.len(); let blocks_range = match ( diff --git a/core/consensus/common/src/import_queue/buffered_link.rs b/primitives/consensus/common/src/import_queue/buffered_link.rs similarity index 94% rename from core/consensus/common/src/import_queue/buffered_link.rs rename to primitives/consensus/common/src/import_queue/buffered_link.rs index b88f1bfd1e884..143ab0eef8090 100644 --- a/core/consensus/common/src/import_queue/buffered_link.rs +++ b/primitives/consensus/common/src/import_queue/buffered_link.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -21,9 +21,9 @@ //! # Example //! //! ``` -//! use substrate_consensus_common::import_queue::Link; -//! # use substrate_consensus_common::import_queue::buffered_link::buffered_link; -//! # use test_client::runtime::Block; +//! use sp_consensus::import_queue::Link; +//! # use sp_consensus::import_queue::buffered_link::buffered_link; +//! # use sp_test_primitives::Block; //! # struct DummyLink; impl Link for DummyLink {} //! # let mut my_link = DummyLink; //! let (mut tx, mut rx) = buffered_link::(); @@ -38,7 +38,7 @@ //! use futures::{prelude::*, channel::mpsc}; -use sr_primitives::traits::{Block as BlockT, NumberFor}; +use sp_runtime::traits::{Block as BlockT, NumberFor}; use std::{pin::Pin, task::Context, task::Poll}; use crate::import_queue::{Origin, Link, BlockImportResult, BlockImportError}; @@ -161,7 +161,7 @@ impl BufferedLinkReceiver { #[cfg(test)] mod tests { - use test_client::runtime::Block; + use sp_test_primitives::Block; #[test] fn is_closed() { diff --git a/primitives/consensus/common/src/lib.rs b/primitives/consensus/common/src/lib.rs new file mode 100644 index 0000000000000..1b98ede376857 --- /dev/null +++ b/primitives/consensus/common/src/lib.rs @@ -0,0 +1,258 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate Consensus Common. + +// Substrate Demo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate Consensus Common is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate Consensus Common. If not, see . + +//! 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)] + +// our error-chain could potentially blow up otherwise +#![recursion_limit="128"] + +#[macro_use] extern crate log; + +use std::sync::Arc; +use std::time::Duration; + +use sp_runtime::{ + generic::BlockId, traits::{Block as BlockT, DigestFor, NumberFor, HasherFor}, +}; +use futures::prelude::*; +pub use sp_inherents::InherentData; + +pub mod block_validation; +pub mod offline_tracker; +pub mod error; +pub mod block_import; +mod select_chain; +pub mod import_queue; +pub mod evaluation; + +// block size limit. +const MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024 + 512; + +pub use self::error::Error; +pub use block_import::{ + BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams, + ImportResult, JustificationImport, FinalityProofImport, +}; +pub use select_chain::SelectChain; +pub use sp_state_machine::Backend as StateBackend; + +/// Block status. +#[derive(Debug, PartialEq, Eq)] +pub enum BlockStatus { + /// Added to the import queue. + Queued, + /// Already in the blockchain and the state is available. + InChainWithState, + /// In the blockchain, but the state is not available. + InChainPruned, + /// Block or parent is known to be bad. + KnownBad, + /// Not in the queue or the blockchain. + Unknown, +} + +/// Environment producer for a Consensus instance. Creates proposer instance and communication streams. +pub trait Environment { + /// The proposer type this creates. + type Proposer: Proposer + 'static; + /// Error which can occur upon creation. + type Error: From + std::fmt::Debug + 'static; + + /// Initialize the proposal logic on top of a specific header. Provide + /// the authorities at that header. + fn init(&mut self, parent_header: &B::Header) -> Result; +} + +/// A proposal that is created by a [`Proposer`]. +pub struct Proposal { + /// The block that was build. + pub block: Block, + /// Optional proof that was recorded while building the block. + pub proof: Option, + /// The storage changes while building this block. + pub storage_changes: sp_state_machine::StorageChanges, NumberFor>, +} + +/// Used as parameter to [`Proposer`] to tell the requirement on recording a proof. +/// +/// When `RecordProof::Yes` is given, all accessed trie nodes should be saved. These recorded +/// trie nodes can be used by a third party to proof this proposal without having access to the +/// full storage. +#[derive(Copy, Clone, PartialEq)] +pub enum RecordProof { + /// `Yes`, record a proof. + Yes, + /// `No`, don't record any proof. + No, +} + +impl RecordProof { + /// Returns if `Self` == `Yes`. + pub fn yes(&self) -> bool { + match self { + Self::Yes => true, + Self::No => false, + } + } +} + +impl From for RecordProof { + fn from(val: bool) -> Self { + if val { + Self::Yes + } else { + Self::No + } + } +} + +/// Logic for a proposer. +/// +/// This will encapsulate creation and evaluation of proposals at a specific +/// block. +/// +/// Proposers are generic over bits of "consensus data" which are engine-specific. +pub trait Proposer { + /// Error type which can occur when proposing or evaluating. + type Error: From + std::fmt::Debug + 'static; + /// The transaction type used by the backend. + type Transaction: Default + Send + 'static; + /// Future that resolves to a committed proposal with an optional proof. + type Proposal: Future, Self::Error>> + + Send + Unpin + 'static; + + /// Create a proposal. + /// + /// Gets the `inherent_data` and `inherent_digests` as input for the proposal. Additionally + /// a maximum duration for building this proposal is given. If building the proposal takes + /// longer than this maximum, the proposal will be very likely discarded. + /// + /// # Return + /// + /// Returns a future that resolves to a [`Proposal`] or to [`Self::Error`]. + fn propose( + &mut self, + inherent_data: InherentData, + inherent_digests: DigestFor, + max_duration: Duration, + record_proof: RecordProof, + ) -> Self::Proposal; +} + +/// An oracle for when major synchronization work is being undertaken. +/// +/// Generally, consensus authoring work isn't undertaken while well behind +/// the head of the chain. +pub trait SyncOracle { + /// Whether the synchronization service is undergoing major sync. + /// Returns true if so. + fn is_major_syncing(&mut self) -> bool; + /// Whether the synchronization service is offline. + /// Returns true if so. + fn is_offline(&mut self) -> bool; +} + +/// A synchronization oracle for when there is no network. +#[derive(Clone, Copy, Debug)] +pub struct NoNetwork; + +impl SyncOracle for NoNetwork { + fn is_major_syncing(&mut self) -> bool { false } + fn is_offline(&mut self) -> bool { false } +} + +impl SyncOracle for Arc where T: ?Sized, for<'r> &'r T: SyncOracle { + fn is_major_syncing(&mut self) -> bool { + <&T>::is_major_syncing(&mut &**self) + } + + fn is_offline(&mut self) -> bool { + <&T>::is_offline(&mut &**self) + } +} + +/// Checks if the current active native block authoring implementation can author with the runtime +/// at the given block. +pub trait CanAuthorWith { + /// See trait docs for more information. + /// + /// # Return + /// + /// - Returns `Ok(())` when authoring is supported. + /// - Returns `Err(_)` when authoring is not supported. + fn can_author_with(&self, at: &BlockId) -> Result<(), String>; +} + +/// Checks if the node can author blocks by using +/// [`NativeVersion::can_author_with`](sp_version::NativeVersion::can_author_with). +pub struct CanAuthorWithNativeVersion(T); + +impl CanAuthorWithNativeVersion { + /// Creates a new instance of `Self`. + pub fn new(inner: T) -> Self { + Self(inner) + } +} + +impl, Block: BlockT> CanAuthorWith + for CanAuthorWithNativeVersion +{ + fn can_author_with(&self, at: &BlockId) -> Result<(), String> { + match self.0.runtime_version(at) { + Ok(version) => self.0.native_version().can_author_with(&version), + Err(e) => { + Err(format!( + "Failed to get runtime version at `{}` and will disable authoring. Error: {}", + at, + e, + )) + } + } + } +} + +/// Returns always `true` for `can_author_with`. This is useful for tests. +pub struct AlwaysCanAuthor; + +impl CanAuthorWith for AlwaysCanAuthor { + fn can_author_with(&self, _: &BlockId) -> Result<(), String> { + Ok(()) + } +} + +/// A type from which a slot duration can be obtained. +pub trait SlotData { + /// Gets the slot duration. + fn slot_duration(&self) -> u64; + + /// The static slot key + const SLOT_KEY: &'static [u8]; +} + +impl SlotData for u64 { + fn slot_duration(&self) -> u64 { + *self + } + + const SLOT_KEY: &'static [u8] = b"aura_slot_duration"; +} diff --git a/core/consensus/common/src/offline_tracker.rs b/primitives/consensus/common/src/offline_tracker.rs similarity index 98% rename from core/consensus/common/src/offline_tracker.rs rename to primitives/consensus/common/src/offline_tracker.rs index f5adbdc0e041d..b4959503b1d39 100644 --- a/core/consensus/common/src/offline_tracker.rs +++ b/primitives/consensus/common/src/offline_tracker.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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/consensus/common/src/select_chain.rs b/primitives/consensus/common/src/select_chain.rs similarity index 95% rename from core/consensus/common/src/select_chain.rs rename to primitives/consensus/common/src/select_chain.rs index e696db6b877b4..3ce2c6ccd0ec9 100644 --- a/core/consensus/common/src/select_chain.rs +++ b/primitives/consensus/common/src/select_chain.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate Consensus Common. // Substrate Demo is free software: you can redistribute it and/or modify @@ -15,7 +15,7 @@ // along with Substrate Consensus Common. If not, see . use crate::error::Error; -use sr_primitives::traits::{Block as BlockT, NumberFor}; +use sp_runtime::traits::{Block as BlockT, NumberFor}; /// The SelectChain trait defines the strategy upon which the head is chosen diff --git a/primitives/consensus/pow/Cargo.toml b/primitives/consensus/pow/Cargo.toml new file mode 100644 index 0000000000000..12e97890d7a1c --- /dev/null +++ b/primitives/consensus/pow/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sp-consensus-pow" +version = "0.8.0" +authors = ["Parity Technologies "] +description = "Primitives for Aura consensus" +edition = "2018" + +[dependencies] +sp-api = { version = "2.0.0", default-features = false, path = "../../api" } +sp-std = { version = "2.0.0", default-features = false, path = "../../std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../runtime" } +sp-core = { version = "2.0.0", default-features = false, path = "../../core" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } + +[features] +default = ["std"] +std = [ + "sp-std/std", + "sp-api/std", + "sp-runtime/std", + "sp-core/std", + "codec/std", +] diff --git a/primitives/consensus/pow/src/lib.rs b/primitives/consensus/pow/src/lib.rs new file mode 100644 index 0000000000000..fa8f75d1be64c --- /dev/null +++ b/primitives/consensus/pow/src/lib.rs @@ -0,0 +1,64 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for Substrate Proof-of-Work (PoW) consensus. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::vec::Vec; +use sp_runtime::ConsensusEngineId; +use codec::Decode; + +/// The `ConsensusEngineId` of PoW. +pub const POW_ENGINE_ID: ConsensusEngineId = [b'p', b'o', b'w', b'_']; + +/// Type of seal. +pub type Seal = Vec; + +/// Define methods that total difficulty should implement. +pub trait TotalDifficulty { + fn increment(&mut self, other: Self); +} + +impl TotalDifficulty for sp_core::U256 { + fn increment(&mut self, other: Self) { + let ret = self.saturating_add(other); + *self = ret; + } +} + +impl TotalDifficulty for u128 { + fn increment(&mut self, other: Self) { + let ret = self.saturating_add(other); + *self = ret; + } +} + +sp_api::decl_runtime_apis! { + /// API necessary for timestamp-based difficulty adjustment algorithms. + pub trait TimestampApi { + /// Return the timestamp in the current block. + fn timestamp() -> Moment; + } + + /// API for those chains that put their difficulty adjustment algorithm directly + /// onto runtime. Note that while putting difficulty adjustment algorithm to + /// runtime is safe, putting the PoW algorithm on runtime is not. + pub trait DifficultyApi { + /// Return the target difficulty of the next block. + fn difficulty() -> Difficulty; + } +} diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml new file mode 100644 index 0000000000000..8242ff8044466 --- /dev/null +++ b/primitives/core/Cargo.toml @@ -0,0 +1,114 @@ +[package] +name = "sp-core" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +rustc-hex = { version = "2.0.1", default-features = false } +log = { version = "0.4.8", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +byteorder = { version = "1.3.2", default-features = false } +primitive-types = { version = "0.6", default-features = false, features = ["codec"] } +impl-serde = { version = "0.2.3", optional = true } +wasmi = { version = "0.6.2", optional = true } +hash-db = { version = "0.15.2", default-features = false } +hash256-std-hasher = { version = "0.15.2", default-features = false } +base58 = { version = "0.1.0", optional = true } +rand = { version = "0.7.2", optional = true } +substrate-bip39 = { version = "0.3.1", optional = true } +tiny-bip39 = { version = "0.6.2", optional = true } +regex = { version = "1.3.1", optional = true } +num-traits = { version = "0.2.8", default-features = false } +zeroize = { version = "1.0.0", default-features = false } +lazy_static = { version = "1.4.0", default-features = false, optional = true } +parking_lot = { version = "0.9.0", optional = true } +sp-debug-derive = { version = "2.0.0", path = "../debug-derive" } +sp-externalities = { version = "2.0.0", optional = true, path = "../externalities" } +sp-storage = { version = "2.0.0", default-features = false, path = "../storage" } +libsecp256k1 = { version = "0.3.2", default-features = false } + +# full crypto +ed25519-dalek = { version = "1.0.0-pre.3", default-features = false, features = ["u64_backend", "alloc"], optional = true } +blake2-rfc = { version = "0.2.18", default-features = false, optional = true } +tiny-keccak = { version = "2.0.1", features = ["keccak"], optional = true } +schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated", "u64_backend"], default-features = false, optional = true } +sha2 = { version = "0.8.0", default-features = false, optional = true } +hex = { version = "0.4", default-features = false, optional = true } +twox-hash = { version = "1.5.0", default-features = false, optional = true } + +sp-runtime-interface = { version = "2.0.0", default-features = false, path = "../runtime-interface" } + +[dev-dependencies] +sp-serializer = { version = "2.0.0", path = "../serializer" } +pretty_assertions = "0.6.1" +hex-literal = "0.2.1" +rand = "0.7.2" +criterion = "0.2.11" +serde_json = "1.0" + +[[bench]] +name = "bench" +harness = false + +[lib] +bench = false + +[features] +default = ["std"] +std = [ + "full_crypto", + "log/std", + "wasmi", + "lazy_static", + "parking_lot", + "primitive-types/std", + "primitive-types/serde", + "primitive-types/byteorder", + "primitive-types/rustc-hex", + "primitive-types/libc", + "impl-serde", + "codec/std", + "hash256-std-hasher/std", + "hash-db/std", + "sp-std/std", + "serde", + "rustc-hex/std", + "twox-hash/std", + "blake2-rfc/std", + "ed25519-dalek/std", + "hex/std", + "base58", + "substrate-bip39", + "tiny-bip39", + "serde", + "byteorder/std", + "rand", + "sha2/std", + "schnorrkel/std", + "regex", + "num-traits/std", + "libsecp256k1/std", + "tiny-keccak", + "sp-debug-derive/std", + "sp-externalities", + "sp-storage/std", + "sp-runtime-interface/std", + "zeroize/alloc" +] + +# This feature enables all crypto primitives for `no_std` builds like microcontrollers +# or Intel SGX. +# For the regular wasm runtime builds this should not be used. +full_crypto = [ + "ed25519-dalek", + "blake2-rfc", + "tiny-keccak", + "schnorrkel", + "hex", + "sha2", + "twox-hash", + "sp-runtime-interface/disable_target_static_assertions", +] diff --git a/primitives/core/benches/bench.rs b/primitives/core/benches/bench.rs new file mode 100644 index 0000000000000..36728742d8949 --- /dev/null +++ b/primitives/core/benches/bench.rs @@ -0,0 +1,94 @@ +// Copyright 2019-2020 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#[macro_use] +extern crate criterion; + +use criterion::{Criterion, black_box, Bencher, Fun}; +use std::time::Duration; +use sp_core::crypto::Pair as _; +use sp_core::hashing::{twox_128, blake2_128}; + +const MAX_KEY_SIZE: u32 = 32; + +fn get_key(key_size: u32) -> Vec { + use rand::SeedableRng; + use rand::Rng; + + let rnd: [u8; 32] = rand::rngs::StdRng::seed_from_u64(12).gen(); + let mut rnd = rnd.iter().cycle(); + + (0..key_size) + .map(|_| rnd.next().unwrap().clone()) + .collect() +} + +fn bench_blake2_128(b: &mut Bencher, key: &Vec) { + b.iter(|| { + let _a = blake2_128(black_box(key)); + }); +} + +fn bench_twox_128(b: &mut Bencher, key: &Vec) { + b.iter(|| { + let _a = twox_128(black_box(key)); + }); +} + +fn bench_hash_128_fix_size(c: &mut Criterion) { + let key = get_key(MAX_KEY_SIZE); + let blake_fn = Fun::new("blake2_128", bench_blake2_128); + let twox_fn = Fun::new("twox_128", bench_twox_128); + let fns = vec![blake_fn, twox_fn]; + + c.bench_functions("fixed size hashing", fns, key); +} + +fn bench_hash_128_dyn_size(c: &mut Criterion) { + let mut keys = Vec::new(); + for i in (2..MAX_KEY_SIZE).step_by(4) { + keys.push(get_key(i).clone()) + } + + c.bench_function_over_inputs("dyn size hashing - blake2", |b, key| bench_blake2_128(b, &key), keys.clone()); + c.bench_function_over_inputs("dyn size hashing - twox", |b, key| bench_twox_128(b, &key), keys); +} + +fn bench_ed25519(c: &mut Criterion) { + c.bench_function_over_inputs("signing - ed25519", |b, &msg_size| { + let msg = (0..msg_size) + .map(|_| rand::random::()) + .collect::>(); + let key = sp_core::ed25519::Pair::generate().0; + b.iter(|| key.sign(&msg)) + }, vec![32, 1024, 1024 * 1024]); + + c.bench_function_over_inputs("verifying - ed25519", |b, &msg_size| { + let msg = (0..msg_size) + .map(|_| rand::random::()) + .collect::>(); + let key = sp_core::ed25519::Pair::generate().0; + let sig = key.sign(&msg); + let public = key.public(); + b.iter(|| sp_core::ed25519::Pair::verify(&sig, &msg, &public)) + }, vec![32, 1024, 1024 * 1024]); +} + +criterion_group!{ + name = benches; + config = Criterion::default().warm_up_time(Duration::from_millis(500)).without_plots(); + targets = bench_hash_128_fix_size, bench_hash_128_dyn_size, bench_ed25519 +} +criterion_main!(benches); diff --git a/core/primitives/src/changes_trie.rs b/primitives/core/src/changes_trie.rs similarity index 94% rename from core/primitives/src/changes_trie.rs rename to primitives/core/src/changes_trie.rs index 5e88485a03994..65619a9d45315 100644 --- a/core/primitives/src/changes_trie.rs +++ b/primitives/core/src/changes_trie.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -57,8 +57,8 @@ impl ChangesTrieConfiguration { ) -> bool where Number: From + PartialEq + - ::rstd::ops::Rem + ::rstd::ops::Sub + - ::rstd::cmp::PartialOrd + Zero, + ::sp_std::ops::Rem + ::sp_std::ops::Sub + + ::sp_std::cmp::PartialOrd + Zero, { block > zero && self.is_digest_build_enabled() @@ -92,8 +92,8 @@ impl ChangesTrieConfiguration { ) -> Option where Number: Clone + From + PartialOrd + PartialEq + - ::rstd::ops::Add + ::rstd::ops::Sub + - ::rstd::ops::Div + ::rstd::ops::Mul + Zero, + ::sp_std::ops::Add + ::sp_std::ops::Sub + + ::sp_std::ops::Div + ::sp_std::ops::Mul + Zero, { if block <= zero { return None; @@ -126,8 +126,8 @@ impl ChangesTrieConfiguration { ) -> Option<(Number, Number)> where Number: Clone + From + PartialOrd + PartialEq + - ::rstd::ops::Add + ::rstd::ops::Sub + - ::rstd::ops::Div + ::rstd::ops::Mul, + ::sp_std::ops::Add + ::sp_std::ops::Sub + + ::sp_std::ops::Div + ::sp_std::ops::Mul, { if !self.is_digest_build_enabled() { return None; @@ -160,8 +160,8 @@ impl ChangesTrieConfiguration { pub fn digest_level_at_block(&self, zero: Number, block: Number) -> Option<(u32, u32, u32)> where Number: Clone + From + PartialEq + - ::rstd::ops::Rem + ::rstd::ops::Sub + - ::rstd::cmp::PartialOrd + Zero, + ::sp_std::ops::Rem + ::sp_std::ops::Sub + + ::sp_std::cmp::PartialOrd + Zero, { if !self.is_digest_build_required_at_block(zero.clone(), block.clone()) { return None; diff --git a/core/primitives/src/crypto.rs b/primitives/core/src/crypto.rs similarity index 87% rename from core/primitives/src/crypto.rs rename to primitives/core/src/crypto.rs index 6e46793432db8..ce2b75c37535d 100644 --- a/core/primitives/src/crypto.rs +++ b/primitives/core/src/crypto.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,9 +18,12 @@ //! Cryptographic utilities. // end::description[] +use sp_std::hash::Hash; +#[cfg(feature = "full_crypto")] +use sp_std::vec::Vec; #[cfg(feature = "std")] -use rstd::convert::TryInto; -use rstd::convert::TryFrom; +use sp_std::convert::TryInto; +use sp_std::convert::TryFrom; #[cfg(feature = "std")] use parking_lot::Mutex; #[cfg(feature = "std")] @@ -30,11 +33,11 @@ use codec::{Encode, Decode}; use regex::Regex; #[cfg(feature = "std")] use base58::{FromBase58, ToBase58}; -#[cfg(feature = "std")] -use std::hash::Hash; + use zeroize::Zeroize; #[doc(hidden)] -pub use rstd::ops::Deref; +pub use sp_std::ops::Deref; +use sp_runtime_interface::pass_by::PassByInner; /// The root phrase for our publicly known keys. pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; @@ -48,7 +51,7 @@ pub enum Infallible {} /// The length of the junction identifier. Note that this is also referred to as the /// `CHAIN_CODE_LENGTH` in the context of Schnorrkel. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub const JUNCTION_ID_LEN: usize = 32; /// Similar to `From`, except that the onus is on the part of the caller to ensure @@ -85,7 +88,7 @@ impl AsRef for Protected { } } -impl rstd::ops::Deref for Protected { +impl sp_std::ops::Deref for Protected { type Target = T; fn deref(&self) -> &T { @@ -120,7 +123,7 @@ impl Drop for Protected { /// An error with the interpretation of a secret. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub enum SecretStringError { /// The overall format was invalid (e.g. the seed phrase contained symbols). InvalidFormat, @@ -140,7 +143,7 @@ pub enum SecretStringError { /// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex` /// a new public key from an existing public key. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)] -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub enum DeriveJunction { /// Soft (vanilla) derivation. Public keys have a correspondent derivation. Soft([u8; JUNCTION_ID_LEN]), @@ -148,7 +151,7 @@ pub enum DeriveJunction { Hard([u8; JUNCTION_ID_LEN]), } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl DeriveJunction { /// Consume self to return a soft derive junction with the same chain code. pub fn soften(self) -> Self { DeriveJunction::Soft(self.unwrap_inner()) } @@ -209,7 +212,7 @@ impl DeriveJunction { } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl> From for DeriveJunction { fn from(j: T) -> DeriveJunction { let j = j.as_ref(); @@ -236,7 +239,7 @@ impl> From for DeriveJunction { } /// An error type for SS58 decoding. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum PublicError { /// Bad alphabet. @@ -254,21 +257,20 @@ pub enum PublicError { } /// Key that can be encoded to/from SS58. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { /// Some if the string is a properly encoded SS58Check address. + #[cfg(feature = "std")] fn from_ss58check(s: &str) -> Result { Self::from_ss58check_with_version(s) .and_then(|(r, v)| match v { - Ss58AddressFormat::SubstrateAccountDirect => Ok(r), - Ss58AddressFormat::PolkadotAccountDirect => Ok(r), - Ss58AddressFormat::KusamaAccountDirect => Ok(r), - Ss58AddressFormat::DothereumAccountDirect => Ok(r), + v if !v.is_custom() => Ok(r), v if v == *DEFAULT_VERSION.lock() => Ok(r), _ => Err(PublicError::UnknownVersion), }) } /// Some if the string is a properly encoded SS58Check address. + #[cfg(feature = "std")] fn from_ss58check_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> { let mut res = Self::default(); let len = res.as_mut().len(); @@ -288,19 +290,19 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { } /// Some if the string is a properly encoded SS58Check address, optionally with /// a derivation path following. + #[cfg(feature = "std")] fn from_string(s: &str) -> Result { Self::from_string_with_version(s) .and_then(|(r, v)| match v { - Ss58AddressFormat::SubstrateAccountDirect => Ok(r), - Ss58AddressFormat::PolkadotAccountDirect => Ok(r), - Ss58AddressFormat::KusamaAccountDirect => Ok(r), - Ss58AddressFormat::DothereumAccountDirect => Ok(r), + v if !v.is_custom() => Ok(r), v if v == *DEFAULT_VERSION.lock() => Ok(r), _ => Err(PublicError::UnknownVersion), }) } /// Return the ss58-check string for this key. + + #[cfg(feature = "std")] fn to_ss58check_with_version(&self, version: Ss58AddressFormat) -> String { let mut v = vec![version.into()]; v.extend(self.as_ref()); @@ -309,9 +311,11 @@ pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { v.to_base58() } /// Return the ss58-check string for this key. + #[cfg(feature = "std")] fn to_ss58check(&self) -> String { self.to_ss58check_with_version(*DEFAULT_VERSION.lock()) } /// Some if the string is a properly encoded SS58Check address, optionally with /// a derivation path following. + #[cfg(feature = "std")] fn from_string_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> { Self::from_ss58check_with_version(s) } @@ -345,85 +349,107 @@ lazy_static::lazy_static! { = Mutex::new(Ss58AddressFormat::SubstrateAccountDirect); } -/// A known address (sub)format/network ID for SS58. -#[cfg(feature = "std")] -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum Ss58AddressFormat { - /// Any Substrate network, direct checksum, standard account (*25519). - SubstrateAccountDirect, - /// Polkadot Relay-chain, direct checksum, standard account (*25519). - PolkadotAccountDirect, - /// Kusama Relay-chain, direct checksum, standard account (*25519). - KusamaAccountDirect, - /// Dothereum Para-chain, direct checksum, standard account (*25519). - DothereumAccountDirect, - /// Use a manually provided numeric value. - Custom(u8), -} +#[cfg(feature = "full_crypto")] +macro_rules! ss58_address_format { + ( $( $identifier:tt => ($number:expr, $name:expr, $desc:tt) )* ) => ( + /// A known address (sub)format/network ID for SS58. + #[derive(Copy, Clone, PartialEq, Eq)] + pub enum Ss58AddressFormat { + $(#[doc = $desc] $identifier),*, + /// Use a manually provided numeric value. + Custom(u8), + } -#[cfg(feature = "std")] -impl From for u8 { - fn from(x: Ss58AddressFormat) -> u8 { - match x { - Ss58AddressFormat::SubstrateAccountDirect => 42, - Ss58AddressFormat::PolkadotAccountDirect => 0, - Ss58AddressFormat::KusamaAccountDirect => 2, - Ss58AddressFormat::DothereumAccountDirect => 20, - Ss58AddressFormat::Custom(n) => n, + static ALL_SS58_ADDRESS_FORMATS: [Ss58AddressFormat; 0 $(+ { let _ = $number; 1})*] = [ + $(Ss58AddressFormat::$identifier),*, + ]; + + impl Ss58AddressFormat { + /// All known address formats. + pub fn all() -> &'static [Ss58AddressFormat] { + &ALL_SS58_ADDRESS_FORMATS + } + + /// Whether the address is custom. + pub fn is_custom(&self) -> bool { + match self { + Self::Custom(_) => true, + _ => false, + } + } } - } -} -#[cfg(feature = "std")] -impl TryFrom for Ss58AddressFormat { - type Error = (); - fn try_from(x: u8) -> Result { - match x { - 42 => Ok(Ss58AddressFormat::SubstrateAccountDirect), - 0 => Ok(Ss58AddressFormat::PolkadotAccountDirect), - 2 => Ok(Ss58AddressFormat::KusamaAccountDirect), - 20 => Ok(Ss58AddressFormat::DothereumAccountDirect), - _ => Err(()), + impl From for u8 { + fn from(x: Ss58AddressFormat) -> u8 { + match x { + $(Ss58AddressFormat::$identifier => $number),*, + Ss58AddressFormat::Custom(n) => n, + } + } } - } -} -#[cfg(feature = "std")] -impl<'a> TryFrom<&'a str> for Ss58AddressFormat { - type Error = (); - fn try_from(x: &'a str) -> Result { - match x { - "substrate" => Ok(Ss58AddressFormat::SubstrateAccountDirect), - "polkadot" => Ok(Ss58AddressFormat::PolkadotAccountDirect), - "kusama" => Ok(Ss58AddressFormat::KusamaAccountDirect), - "dothereum" => Ok(Ss58AddressFormat::DothereumAccountDirect), - a => a.parse::().map(Ss58AddressFormat::Custom).map_err(|_| ()), + impl TryFrom for Ss58AddressFormat { + type Error = (); + + fn try_from(x: u8) -> Result { + match x { + $($number => Ok(Ss58AddressFormat::$identifier)),*, + _ => Err(()), + } + } } - } -} -#[cfg(feature = "std")] -impl From for String { - fn from(x: Ss58AddressFormat) -> String { - match x { - Ss58AddressFormat::SubstrateAccountDirect => "substrate".into(), - Ss58AddressFormat::PolkadotAccountDirect => "polkadot".into(), - Ss58AddressFormat::KusamaAccountDirect => "kusama".into(), - Ss58AddressFormat::DothereumAccountDirect => "dothereum".into(), - Ss58AddressFormat::Custom(x) => x.to_string(), + impl<'a> TryFrom<&'a str> for Ss58AddressFormat { + type Error = (); + + fn try_from(x: &'a str) -> Result { + match x { + $($name => Ok(Ss58AddressFormat::$identifier)),*, + a => a.parse::().map(Ss58AddressFormat::Custom).map_err(|_| ()), + } + } } - } + + #[cfg(feature = "std")] + impl Default for Ss58AddressFormat { + fn default() -> Self { + *DEFAULT_VERSION.lock() + } + } + + #[cfg(feature = "std")] + impl From for String { + fn from(x: Ss58AddressFormat) -> String { + match x { + $(Ss58AddressFormat::$identifier => $name.into()),*, + Ss58AddressFormat::Custom(x) => x.to_string(), + } + } + } + ) } +#[cfg(feature = "full_crypto")] +ss58_address_format!( + SubstrateAccountDirect => + (42, "substrate", "Any Substrate network, direct checksum, standard account (*25519).") + PolkadotAccountDirect => + (0, "polkadot", "Polkadot Relay-chain, direct checksum, standard account (*25519).") + KusamaAccountDirect => + (2, "kusama", "Kusama Relay-chain, direct checksum, standard account (*25519).") + DothereumAccountDirect => + (20, "dothereum", "Dothereum Para-chain, direct checksum, standard account (*25519).") + KulupuAccountDirect => + (16, "kulupu", "Kulupu mainnet, direct checksum, standard account (*25519).") + EdgewareAccountDirect => + (7, "edgeware", "Edgeware mainnet, direct checksum, standard account (*25519).") +); + /// Set the default "version" (actually, this is a bit of a misnomer and the version byte is /// typically used not just to encode format/version but also network identity) that is used for /// encoding and decoding SS58 addresses. If an unknown version is provided then it fails. /// -/// Current known "versions" are: -/// - 0 direct (payload) checksum for 32-byte *25519 Polkadot addresses. -/// - 2 direct (payload) checksum for 32-byte *25519 Kusama addresses. -/// - 20 direct (payload) checksum for 32-byte *25519 Dothereum addresses. -/// - 42 direct (payload) checksum for 32-byte *25519 addresses on any Substrate-based network. +/// See `ss58_address_format!` for all current known "versions". #[cfg(feature = "std")] pub fn set_default_ss58_version(version: Ss58AddressFormat) { *DEFAULT_VERSION.lock() = version @@ -544,7 +570,7 @@ impl From<[u8; 32]> for AccountId32 { } } -impl<'a> rstd::convert::TryFrom<&'a [u8]> for AccountId32 { +impl<'a> sp_std::convert::TryFrom<&'a [u8]> for AccountId32 { type Error = (); fn try_from(x: &'a [u8]) -> Result { if x.len() == 32 { @@ -570,15 +596,15 @@ impl std::fmt::Display for AccountId32 { } } -impl rstd::fmt::Debug for AccountId32 { +impl sp_std::fmt::Debug for AccountId32 { #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { let s = self.to_ss58check(); write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) } #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { Ok(()) } } @@ -617,7 +643,7 @@ mod dummy { fn as_mut(&mut self) -> &mut[u8] { unsafe { #[allow(mutable_transmutes)] - rstd::mem::transmute::<_, &'static mut [u8]>(&b""[..]) + sp_std::mem::transmute::<_, &'static mut [u8]>(&b""[..]) } } } @@ -640,7 +666,9 @@ mod dummy { type Seed = Dummy; type Signature = Dummy; type DeriveError = (); + #[cfg(feature = "std")] fn generate_with_phrase(_: Option<&str>) -> (Self, String, Self::Seed) { Default::default() } + #[cfg(feature = "std")] fn from_phrase(_: &str, _: Option<&str>) -> Result<(Self, Self::Seed), SecretStringError> { @@ -662,7 +690,7 @@ mod dummy { /// Trait suitable for typical cryptographic PKI key pair type. /// /// For now it just specifies how to create a key from a phrase and derivation path. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// The type which is used to encode a public key. type Public: Public + Hash; @@ -682,6 +710,7 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// /// This is only for ephemeral keys really, since you won't have access to the secret key /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. + #[cfg(feature = "std")] fn generate() -> (Self, Self::Seed) { let mut seed = Self::Seed::default(); OsRng.fill_bytes(seed.as_mut()); @@ -694,9 +723,11 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// /// This is generally slower than `generate()`, so prefer that unless you need to persist /// the key from the current session. + #[cfg(feature = "std")] fn generate_with_phrase(password: Option<&str>) -> (Self, String, Self::Seed); /// Returns the KeyPair from the English BIP39 seed `phrase`, or `None` if it's invalid. + #[cfg(feature = "std")] fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Self, Self::Seed), SecretStringError>; /// Derive a child key from a series of given junctions. @@ -758,7 +789,10 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// be equivalent to no password at all. /// /// `None` is returned if no matches are found. - fn from_string_with_seed(s: &str, password_override: Option<&str>) -> Result<(Self, Option), SecretStringError> { + #[cfg(feature = "std")] + fn from_string_with_seed(s: &str, password_override: Option<&str>) + -> Result<(Self, Option), SecretStringError> + { let re = Regex::new(r"^(?P[\d\w ]+)?(?P(//?[^/]+)*)(///(?P.*))?$") .expect("constructed from known-good static value; qed"); let cap = re.captures(s).ok_or(SecretStringError::InvalidFormat)?; @@ -793,6 +827,7 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// Interprets the string `s` in order to generate a key pair. /// /// See [`from_string_with_seed`](Self::from_string_with_seed) for more extensive documentation. + #[cfg(feature = "std")] fn from_string(s: &str, password_override: Option<&str>) -> Result { Self::from_string_with_seed(s, password_override).map(|x| x.0) } @@ -839,7 +874,7 @@ impl UncheckedFrom for Outer where /// Type which has a particular kind of crypto associated with it. pub trait CryptoType { /// The pair key type of this crypto. - #[cfg(feature="std")] + #[cfg(feature = "full_crypto")] type Pair: Pair; } @@ -850,8 +885,10 @@ pub trait CryptoType { /// /// Values whose first character is `_` are reserved for private use and won't conflict with any /// public modules. -#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)] -#[derive(crate::RuntimeDebug)] +#[derive( + Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode, PassByInner, + crate::RuntimeDebug +)] pub struct KeyTypeId(pub [u8; 4]); impl From for KeyTypeId { @@ -897,8 +934,9 @@ pub mod key_types { pub const AURA: KeyTypeId = KeyTypeId(*b"aura"); /// Key type for ImOnline module, built-in. pub const IM_ONLINE: KeyTypeId = KeyTypeId(*b"imon"); + /// Key type for AuthorityDiscovery module, built-in. + pub const AUTHORITY_DISCOVERY: KeyTypeId = KeyTypeId(*b"audi"); /// A key type ID useful for tests. - #[cfg(feature = "std")] pub const DUMMY: KeyTypeId = KeyTypeId(*b"dumy"); } diff --git a/primitives/core/src/ecdsa.rs b/primitives/core/src/ecdsa.rs new file mode 100644 index 0000000000000..afd75dae99522 --- /dev/null +++ b/primitives/core/src/ecdsa.rs @@ -0,0 +1,697 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Simple ECDSA API. +// end::description[] + +#[cfg(feature = "full_crypto")] +use sp_std::vec::Vec; + +use sp_std::cmp::Ordering; +use codec::{Encode, Decode}; + +#[cfg(feature = "full_crypto")] +use core::convert::{TryFrom, TryInto}; +#[cfg(feature = "std")] +use substrate_bip39::seed_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "full_crypto")] +use crate::{hashing::blake2_256, crypto::{Pair as TraitPair, DeriveJunction, SecretStringError}}; +#[cfg(feature = "std")] +use crate::crypto::Ss58Codec; +#[cfg(feature = "std")] +use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; +use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}; +#[cfg(feature = "full_crypto")] +use secp256k1::{PublicKey, SecretKey}; + +/// A secret seed (which is bytewise essentially equivalent to a SecretKey). +/// +/// We need it as a different type because `Seed` is expected to be AsRef<[u8]>. +#[cfg(feature = "full_crypto")] +type Seed = [u8; 32]; + +/// The ECDSA public key. +#[derive(Clone, Encode, Decode)] +pub enum Public { + /// A full raw ECDSA public key. + Full([u8; 64]), + /// A compressed ECDSA public key. + Compressed([u8; 33]), +} + +impl PartialOrd for Public { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Public { + fn cmp(&self, other: &Self) -> Ordering { + self.as_ref().cmp(&other.as_ref()) + } +} + +impl PartialEq for Public { + fn eq(&self, other: &Self) -> bool { + self.as_ref() == other.as_ref() + } +} + +impl Eq for Public {} + +/// An error type for SS58 decoding. +#[cfg(feature = "std")] +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub enum PublicError { + /// Bad alphabet. + BadBase58, + /// Bad length. + BadLength, + /// Unknown version. + UnknownVersion, + /// Invalid checksum. + InvalidChecksum, +} + +impl Public { + /// A new instance from the given 64-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; 64]) -> Self { + Self::Full(data) + } + + /// A new instance from the given 65-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_full(data: [u8; 65]) -> Self { + let raw_key = &data[1..]; + let mut key = [0u8; 64]; + key.copy_from_slice(raw_key); + Self::Full(key) + } + + /// Return in compressed format. + /// + /// Returns an error if `self` is an invalid full public key. + pub fn as_compressed(&self) -> Result<[u8; 33], ()> { + match self { + Self::Full(d) => secp256k1::PublicKey::parse_slice(d, None) + .map(|k| k.serialize_compressed()) + .map_err(|_| ()), + Self::Compressed(d) => Ok(*d), + } + } + + /// Convert `Self` into a compressed public key. + /// + /// Returns an error if `self` is an invalid full public key. + pub fn into_compressed(self) -> Result { + self.as_compressed().map(Self::Compressed) + } +} + +impl TraitPublic for Public { + /// A new instance from the given slice that should be 33 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + fn from_slice(data: &[u8]) -> Self { + if data.len() == 33 { + let mut r = [0u8; 33]; + r.copy_from_slice(data); + Self::Compressed(r) + } else { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Self::Full(r) + } + } +} + +impl Derive for Public {} + +impl Default for Public { + fn default() -> Self { + Public::Full([0u8; 64]) + } +} + +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + match self { + Self::Full(d) => &d[..], + Self::Compressed(d) => &d[..], + } + } +} + +impl AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { + match self { + Self::Full(d) => &mut d[..], + Self::Compressed(d) => &mut d[..], + } + } +} + +impl sp_std::convert::TryFrom<&[u8]> for Public { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 33 || data.len() == 64 { + Ok(Self::from_slice(data)) + } else { + Err(()) + } + } +} + +#[cfg(feature = "full_crypto")] +impl From for Public { + fn from(x: Pair) -> Self { + x.public() + } +} + +impl UncheckedFrom<[u8; 64]> for Public { + fn unchecked_from(x: [u8; 64]) -> Self { + Public::Full(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.as_ref()), &s[0..8]) + } +} + +#[cfg(feature = "std")] +impl Serialize for Public { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +#[cfg(feature = "full_crypto")] +impl sp_std::hash::Hash for Public { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + } +} + +/// A signature (a 512-bit value, plus 8 bits for recovery ID). +#[derive(Encode, Decode)] +pub struct Signature([u8; 65]); + +impl sp_std::convert::TryFrom<&[u8]> for Signature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(Signature(inner)) + } else { + Err(()) + } + } +} + +#[cfg(feature = "std")] +impl Serialize for Signature { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&hex::encode(self)) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Signature { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + Ok(Signature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?) + } +} + +impl Clone for Signature { + fn clone(&self) -> Self { + let mut r = [0u8; 65]; + r.copy_from_slice(&self.0[..]); + Signature(r) + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0u8; 65]) + } +} + +impl PartialEq for Signature { + fn eq(&self, b: &Self) -> bool { + self.0[..] == b.0[..] + } +} + +impl Eq for Signature {} + +impl From for [u8; 65] { + fn from(v: Signature) -> [u8; 65] { + v.0 + } +} + +impl AsRef<[u8; 65]> for Signature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for Signature { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "full_crypto")] +impl sp_std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + sp_std::hash::Hash::hash(&self.0[..], state); + } +} + +impl Signature { + /// A new instance from the given 65-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_raw(data: [u8; 65]) -> Signature { + Signature(data) + } + + /// A new instance from the given slice that should be 65 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; 65]; + r.copy_from_slice(data); + Signature(r) + } + + /// Recover the public key from this signature and a message. + #[cfg(feature = "full_crypto")] + pub fn recover>(&self, message: M) -> Option { + let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); + let sig: (_, _) = self.try_into().ok()?; + secp256k1::recover(&message, &sig.0, &sig.1).ok() + .map(|recovered| Public::from_full(recovered.serialize())) + } +} + +#[cfg(feature = "full_crypto")] +impl From<(secp256k1::Signature, secp256k1::RecoveryId)> for Signature { + fn from(x: (secp256k1::Signature, secp256k1::RecoveryId)) -> Signature { + let mut r = Self::default(); + r.0[0..64].copy_from_slice(&x.0.serialize()[..]); + r.0[64] = x.1.serialize(); + r + } +} + +#[cfg(feature = "full_crypto")] +impl<'a> TryFrom<&'a Signature> for (secp256k1::Signature, secp256k1::RecoveryId) { + type Error = (); + fn try_from(x: &'a Signature) -> Result<(secp256k1::Signature, secp256k1::RecoveryId), Self::Error> { + Ok(( + secp256k1::Signature::parse_slice(&x.0[0..64]).expect("hardcoded to 64 bytes; qed"), + secp256k1::RecoveryId::parse(x.0[64]).map_err(|_| ())?, + )) + } +} + +/// Derive a single hard junction. +#[cfg(feature = "full_crypto")] +fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + ("Secp256k1HDKD", secret_seed, cc).using_encoded(|data| { + let mut res = [0u8; 32]; + res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); + res + }) +} + +/// An error when deriving a key. +#[cfg(feature = "full_crypto")] +pub enum DeriveError { + /// A soft key was found in the path (and is unsupported). + SoftKeyInPath, +} + +/// A key pair. +#[cfg(feature = "full_crypto")] +#[derive(Clone)] +pub struct Pair { + public: PublicKey, + secret: SecretKey, +} + +#[cfg(feature = "full_crypto")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = DeriveError; + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + #[cfg(feature = "std")] + fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + let (pair, seed) = Self::from_phrase(phrase, password) + .expect("All phrases generated by Mnemonic are valid; qed"); + ( + pair, + phrase.to_owned(), + seed, + ) + } + + /// Generate key pair from given recovery phrase and password. + #[cfg(feature = "std")] + fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { + let big_seed = seed_from_entropy( + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(), + password.unwrap_or(""), + ).map_err(|_| SecretStringError::InvalidSeed)?; + let mut seed = Seed::default(); + seed.copy_from_slice(&big_seed[0..32]); + Self::from_seed_slice(&big_seed[0..32]).map(|x| (x, seed)) + } + + /// Make a new key pair from secret seed material. + /// + /// You should never need to use this; generate(), generate_with_phrase + fn from_seed(seed: &Seed) -> Pair { + Self::from_seed_slice(&seed[..]).expect("seed has valid length; qed") + } + + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// You should never need to use this; generate(), generate_with_phrase + fn from_seed_slice(seed_slice: &[u8]) -> Result { + let secret = SecretKey::parse_slice(seed_slice) + .map_err(|_| SecretStringError::InvalidSeedLength)?; + let public = PublicKey::from_secret_key(&secret); + Ok(Pair{ secret, public }) + } + + /// Derive a child key from a series of given junctions. + fn derive>(&self, + path: Iter, + _seed: Option + ) -> Result<(Pair, Option), DeriveError> { + let mut acc = self.secret.serialize(); + for j in path { + match j { + DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), + DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), + } + } + Ok((Self::from_seed(&acc), Some(acc))) + } + + /// Get the public key. + fn public(&self) -> Public { + Public::from_full(self.public.serialize()) + } + + /// Sign a message. + fn sign(&self, message: &[u8]) -> Signature { + let message = secp256k1::Message::parse(&blake2_256(message)); + secp256k1::sign(&message, &self.secret).into() + } + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { + let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); + let sig: (_, _) = match sig.try_into() { Ok(x) => x, _ => return false }; + match secp256k1::recover(&message, &sig.0, &sig.1) { + Ok(actual) => pubkey.as_compressed() + .map(|p| &p[..] == &actual.serialize_compressed()[..]) + .unwrap_or(false), + _ => false, + } + } + + /// Verify a signature on a message. Returns true if the signature is good. + /// + /// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct + /// size. Use it only if you're coming from byte buffers and need the speed. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { + let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); + if sig.len() != 65 { return false } + let ri = match secp256k1::RecoveryId::parse(sig[64]) { Ok(x) => x, _ => return false }; + let sig = match secp256k1::Signature::parse_slice(&sig[0..64]) { Ok(x) => x, _ => return false }; + match secp256k1::recover(&message, &sig, &ri) { + Ok(actual) => pubkey.as_ref() == &actual.serialize()[1..], + _ => false, + } + } + + /// Return a vec filled with raw data. + fn to_raw_vec(&self) -> Vec { + self.seed().to_vec() + } +} + +#[cfg(feature = "full_crypto")] +impl Pair { + /// Get the seed for this key. + pub fn seed(&self) -> Seed { + self.secret.serialize() + } + + /// Exactly as `from_string` except that if no matches are found then, the the first 32 + /// characters are taken (padded with spaces as necessary) and used as the MiniSecretKey. + #[cfg(feature = "std")] + pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair { + Self::from_string(s, password_override).unwrap_or_else(|_| { + let mut padded_seed: Seed = [' ' as u8; 32]; + let len = s.len().min(32); + padded_seed[..len].copy_from_slice(&s.as_bytes()[..len]); + Self::from_seed(&padded_seed) + }) + } +} + +impl CryptoType for Public { + #[cfg(feature="full_crypto")] + type Pair = Pair; +} + +impl CryptoType for Signature { + #[cfg(feature="full_crypto")] + type Pair = Pair; +} + +#[cfg(feature="full_crypto")] +impl CryptoType for Pair { + type Pair = Pair; +} + +#[cfg(test)] +mod test { + use super::*; + use hex_literal::hex; + use crate::crypto::DEV_PHRASE; + use serde_json; + + #[test] + fn default_phrase_should_be_used() { + assert_eq!( + Pair::from_string("//Alice///password", None).unwrap().public(), + Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), + ); + } + + #[test] + fn seed_and_derive_should_work() { + let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); + let pair = Pair::from_seed(&seed); + assert_eq!(pair.seed(), seed); + let path = vec![DeriveJunction::Hard([0u8; 32])]; + let derived = pair.derive(path.into_iter(), None).ok().unwrap(); + assert_eq!( + derived.0.seed(), + hex!("b8eefc4937200a8382d00050e050ced2d4ab72cc2ef1b061477afb51564fdd61") + ); + } + + #[test] + fn test_vector_should_work() { + let pair = Pair::from_seed( + &hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") + ); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("8db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd913ebbe148dd17c56551a52952371071a6c604b3f3abe8f2c8fa742158ea6dd7d4") + )); + let message = b""; + let signature = hex!("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00"); + let signature = Signature::from_raw(signature); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn test_vector_by_string_should_work() { + let pair = Pair::from_string( + "0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + None + ).unwrap(); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("8db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd913ebbe148dd17c56551a52952371071a6c604b3f3abe8f2c8fa742158ea6dd7d4") + )); + let message = b""; + let signature = hex!("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00"); + let signature = Signature::from_raw(signature); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let (pair, _) = Pair::generate(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(Pair::verify(&signature, &message[..], &public)); + assert!(!Pair::verify(&signature, b"Something else", &public)); + } + + #[test] + fn seeded_pair_should_work() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("5676109c54b9a16d271abeb4954316a40a32bcce023ac14c8e26e958aa68fba995840f3de562156558efbfdac3f16af0065e5f66795f4dd8262a228ef8c6d813") + )); + let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); + let signature = pair.sign(&message[..]); + println!("Correct signature: {:?}", signature); + assert!(Pair::verify(&signature, &message[..], &public)); + assert!(!Pair::verify(&signature, "Other message", &public)); + } + + #[test] + fn generate_with_phrase_recovery_possible() { + let (pair1, phrase, _) = Pair::generate_with_phrase(None); + let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); + } + + #[test] + fn generate_with_password_phrase_recovery_possible() { + let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); + let (pair2, _) = Pair::from_phrase(&phrase, Some("password")).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); + } + + #[test] + fn password_does_something() { + let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); + let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); + + assert_ne!(pair1.public(), pair2.public()); + } + + #[test] + fn ss58check_roundtrip_works() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + let s = public.to_ss58check(); + println!("Correct: {}", s); + let cmp = Public::from_ss58check(&s).unwrap(); + assert_eq!(cmp, public); + } + + #[test] + fn signature_serialization_works() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + let serialized_signature = serde_json::to_string(&signature).unwrap(); + // Signature is 65 bytes, so 130 chars + 2 quote chars + assert_eq!(serialized_signature.len(), 132); + let signature = serde_json::from_str(&serialized_signature).unwrap(); + assert!(Pair::verify(&signature, &message[..], &pair.public())); + } + + #[test] + fn signature_serialization_doesnt_panic() { + fn deserialize_signature(text: &str) -> Result { + Ok(serde_json::from_str(text)?) + } + assert!(deserialize_signature("Not valid json.").is_err()); + assert!(deserialize_signature("\"Not an actual signature.\"").is_err()); + // Poorly-sized + assert!(deserialize_signature("\"abc123\"").is_err()); + } +} diff --git a/primitives/core/src/ed25519.rs b/primitives/core/src/ed25519.rs new file mode 100644 index 0000000000000..f3aba47c20457 --- /dev/null +++ b/primitives/core/src/ed25519.rs @@ -0,0 +1,689 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Simple Ed25519 API. +// end::description[] + +#[cfg(feature = "full_crypto")] +use sp_std::vec::Vec; + +use crate::{hash::H256, hash::H512}; +use codec::{Encode, Decode}; + +#[cfg(feature = "full_crypto")] +use blake2_rfc; +#[cfg(feature = "full_crypto")] +use core::convert::TryFrom; +#[cfg(feature = "std")] +use substrate_bip39::seed_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "full_crypto")] +use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError}; +#[cfg(feature = "std")] +use crate::crypto::Ss58Codec; +#[cfg(feature = "std")] +use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; +use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}}; +use sp_runtime_interface::pass_by::PassByInner; +use sp_std::ops::Deref; + +/// 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 = "full_crypto")] +type Seed = [u8; 32]; + +/// A public key. +#[cfg_attr(feature = "full_crypto", derive(Hash))] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner)] +pub struct Public(pub [u8; 32]); + +/// A key pair. +#[cfg(feature = "full_crypto")] +pub struct Pair(ed25519_dalek::Keypair); + +#[cfg(feature = "full_crypto")] +impl Clone for Pair { + fn clone(&self) -> Self { + Pair(ed25519_dalek::Keypair { + public: self.0.public.clone(), + secret: ed25519_dalek::SecretKey::from_bytes(self.0.secret.as_bytes()) + .expect("key is always the correct size; qed") + }) + } +} + +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 Deref for Public { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl sp_std::convert::TryFrom<&[u8]> for Public { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 32 { + let mut inner = [0u8; 32]; + inner.copy_from_slice(data); + Ok(Public(inner)) + } else { + Err(()) + } + } +} + +impl From for [u8; 32] { + fn from(x: Public) -> Self { + x.0 + } +} + +#[cfg(feature = "full_crypto")] +impl From for Public { + fn from(x: Pair) -> Self { + x.public() + } +} + +impl From for H256 { + fn from(x: Public) -> Self { + x.0.into() + } +} + +#[cfg(feature = "std")] +impl std::str::FromStr for Public { + type Err = crate::crypto::PublicError; + + fn from_str(s: &str) -> Result { + Self::from_ss58check(s) + } +} + +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()) + } +} + +impl sp_std::fmt::Debug for Public { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +#[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))) + } +} + +/// A signature (a 512-bit value). +#[derive(Encode, Decode, PassByInner)] +pub struct Signature(pub [u8; 64]); + +impl sp_std::convert::TryFrom<&[u8]> for Signature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 64 { + let mut inner = [0u8; 64]; + inner.copy_from_slice(data); + Ok(Signature(inner)) + } else { + Err(()) + } + } +} + +#[cfg(feature = "std")] +impl Serialize for Signature { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&hex::encode(self)) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Signature { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + Ok(Signature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?) + } +} + +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[..] + } +} + +impl sp_std::fmt::Debug for Signature { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +#[cfg(feature = "full_crypto")] +impl sp_std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + sp_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. + BadBase58, + /// Bad length. + BadLength, + /// Unknown version. + UnknownVersion, + /// Invalid checksum. + InvalidChecksum, +} + +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 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 slice filled with raw data. + pub fn as_array_ref(&self) -> &[u8; 32] { + self.as_ref() + } +} + +impl TraitPublic for Public { + /// 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! + fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Public(r) + } +} + +impl Derive for Public {} + +/// Derive a single hard junction. +#[cfg(feature = "full_crypto")] +fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + ("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 + }) +} + +/// An error when deriving a key. +#[cfg(feature = "full_crypto")] +pub enum DeriveError { + /// A soft key was found in the path (and is unsupported). + SoftKeyInPath, +} + +#[cfg(feature = "full_crypto")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = DeriveError; + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + #[cfg(feature = "std")] + fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + let (pair, seed) = Self::from_phrase(phrase, password) + .expect("All phrases generated by Mnemonic are valid; qed"); + ( + pair, + phrase.to_owned(), + seed, + ) + } + + /// Generate key pair from given recovery phrase and password. + #[cfg(feature = "std")] + fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { + let big_seed = seed_from_entropy( + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(), + password.unwrap_or(""), + ).map_err(|_| SecretStringError::InvalidSeed)?; + let mut seed = Seed::default(); + seed.copy_from_slice(&big_seed[0..32]); + Self::from_seed_slice(&big_seed[0..32]).map(|x| (x, seed)) + } + + /// Make a new key pair from secret seed material. + /// + /// You should never need to use this; generate(), generate_with_phrasee + fn from_seed(seed: &Seed) -> Pair { + Self::from_seed_slice(&seed[..]).expect("seed has valid length; qed") + } + + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// You should never need to use this; generate(), generate_with_phrase + fn from_seed_slice(seed_slice: &[u8]) -> Result { + let secret = ed25519_dalek::SecretKey::from_bytes(seed_slice) + .map_err(|_| SecretStringError::InvalidSeedLength)?; + let public = ed25519_dalek::PublicKey::from(&secret); + Ok(Pair(ed25519_dalek::Keypair { secret, public })) + } + + /// Derive a child key from a series of given junctions. + fn derive>(&self, + path: Iter, + _seed: Option, + ) -> Result<(Pair, Option), DeriveError> { + let mut acc = self.0.secret.to_bytes(); + for j in path { + match j { + DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), + DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), + } + } + Ok((Self::from_seed(&acc), Some(acc))) + } + + /// Get the public key. + fn public(&self) -> Public { + let mut r = [0u8; 32]; + let pk = self.0.public.as_bytes(); + r.copy_from_slice(pk); + Public(r) + } + + /// Sign a message. + fn sign(&self, message: &[u8]) -> Signature { + let r = self.0.sign(message).to_bytes(); + Signature::from_raw(r) + } + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { + Self::verify_weak(&sig.0[..], message.as_ref(), pubkey) + } + + /// 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 = match ed25519_dalek::PublicKey::from_bytes(pubkey.as_ref()) { + Ok(pk) => pk, + Err(_) => return false, + }; + + let sig = match ed25519_dalek::Signature::from_bytes(sig) { + Ok(s) => s, + Err(_) => return false + }; + + match public_key.verify(message.as_ref(), &sig) { + Ok(_) => true, + _ => false, + } + } + + /// Return a vec filled with raw data. + fn to_raw_vec(&self) -> Vec { + self.seed().to_vec() + } +} + +#[cfg(feature = "full_crypto")] +impl Pair { + /// Get the seed for this key. + pub fn seed(&self) -> &Seed { + self.0.secret.as_bytes() + } + + /// Exactly as `from_string` except that if no matches are found then, the the first 32 + /// characters are taken (padded with spaces as necessary) and used as the MiniSecretKey. + #[cfg(feature = "std")] + pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair { + Self::from_string(s, password_override).unwrap_or_else(|_| { + let mut padded_seed: Seed = [' ' as u8; 32]; + let len = s.len().min(32); + padded_seed[..len].copy_from_slice(&s.as_bytes()[..len]); + Self::from_seed(&padded_seed) + }) + } +} + +impl CryptoType for Public { + #[cfg(feature = "full_crypto")] + type Pair = Pair; +} + +impl CryptoType for Signature { + #[cfg(feature = "full_crypto")] + type Pair = Pair; +} + +#[cfg(feature = "full_crypto")] +impl CryptoType for Pair { + type Pair = Pair; +} + +#[cfg(test)] +mod test { + use super::*; + use hex_literal::hex; + use crate::crypto::DEV_PHRASE; + use serde_json; + + #[test] + fn default_phrase_should_be_used() { + assert_eq!( + Pair::from_string("//Alice///password", None).unwrap().public(), + Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), + ); + } + + #[test] + fn seed_and_derive_should_work() { + let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); + let pair = Pair::from_seed(&seed); + assert_eq!(pair.seed(), &seed); + let path = vec![DeriveJunction::Hard([0u8; 32])]; + let derived = pair.derive(path.into_iter(), None).ok().unwrap().0; + assert_eq!( + derived.seed(), + &hex!("ede3354e133f9c8e337ddd6ee5415ed4b4ffe5fc7d21e933f4930a3730e5b21c") + ); + } + + #[test] + fn test_vector_should_work() { + let pair = Pair::from_seed( + &hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") + ); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a") + )); + let message = b""; + let signature = hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"); + let signature = Signature::from_raw(signature); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn test_vector_by_string_should_work() { + let pair = Pair::from_string( + "0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + None + ).unwrap(); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a") + )); + let message = b""; + let signature = hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"); + let signature = Signature::from_raw(signature); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let (pair, _) = Pair::generate(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(Pair::verify(&signature, &message[..], &public)); + assert!(!Pair::verify(&signature, b"Something else", &public)); + } + + #[test] + fn seeded_pair_should_work() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee") + )); + let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); + let signature = pair.sign(&message[..]); + println!("Correct signature: {:?}", signature); + assert!(Pair::verify(&signature, &message[..], &public)); + assert!(!Pair::verify(&signature, "Other message", &public)); + } + + #[test] + fn generate_with_phrase_recovery_possible() { + let (pair1, phrase, _) = Pair::generate_with_phrase(None); + let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); + } + + #[test] + fn generate_with_password_phrase_recovery_possible() { + let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); + let (pair2, _) = Pair::from_phrase(&phrase, Some("password")).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); + } + + #[test] + fn password_does_something() { + let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); + let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); + + assert_ne!(pair1.public(), pair2.public()); + } + + #[test] + fn ss58check_roundtrip_works() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + let s = public.to_ss58check(); + println!("Correct: {}", s); + let cmp = Public::from_ss58check(&s).unwrap(); + assert_eq!(cmp, public); + } + + #[test] + fn signature_serialization_works() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + let serialized_signature = serde_json::to_string(&signature).unwrap(); + // Signature is 64 bytes, so 128 chars + 2 quote chars + assert_eq!(serialized_signature.len(), 130); + let signature = serde_json::from_str(&serialized_signature).unwrap(); + assert!(Pair::verify(&signature, &message[..], &pair.public())); + } + + #[test] + fn signature_serialization_doesnt_panic() { + fn deserialize_signature(text: &str) -> Result { + Ok(serde_json::from_str(text)?) + } + assert!(deserialize_signature("Not valid json.").is_err()); + assert!(deserialize_signature("\"Not an actual signature.\"").is_err()); + // Poorly-sized + assert!(deserialize_signature("\"abc123\"").is_err()); + } +} diff --git a/primitives/core/src/hash.rs b/primitives/core/src/hash.rs new file mode 100644 index 0000000000000..424fefbe6a470 --- /dev/null +++ b/primitives/core/src/hash.rs @@ -0,0 +1,81 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A fixed hash type. + +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. +/// Panics if used to convert between different hash types. +pub fn convert_hash, H2: AsRef<[u8]>>(src: &H2) -> H1 { + let mut dest = H1::default(); + assert_eq!(dest.as_mut().len(), src.as_ref().len()); + dest.as_mut().copy_from_slice(src.as_ref()); + dest +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_serializer as ser; + + #[test] + fn test_h160() { + let tests = vec![ + (Default::default(), "0x0000000000000000000000000000000000000000"), + (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 { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number)); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } + } + + #[test] + fn test_h256() { + let tests = vec![ + (Default::default(), "0x0000000000000000000000000000000000000000000000000000000000000000"), + (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 { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number)); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } + } + + #[test] + fn test_invalid() { + assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"10\"").unwrap_err().is_data()); + } +} diff --git a/core/primitives/src/hasher.rs b/primitives/core/src/hasher.rs similarity index 96% rename from core/primitives/src/hasher.rs rename to primitives/core/src/hasher.rs index 4562180a1a454..68fce90644b70 100644 --- a/core/primitives/src/hasher.rs +++ b/primitives/core/src/hasher.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// Copyright 2018-2020 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/hashing.rs b/primitives/core/src/hashing.rs similarity index 86% rename from core/primitives/src/hashing.rs rename to primitives/core/src/hashing.rs index 87312ce6e46e9..87f6469b573e1 100644 --- a/core/primitives/src/hashing.rs +++ b/primitives/core/src/hashing.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -17,6 +17,8 @@ //! Hashing functions. use blake2_rfc; +use sha2::{Digest, Sha256}; +use tiny_keccak::{Hasher, Keccak}; use twox_hash; /// Do a Blake2 512-bit hash and place result in `dest`. @@ -121,3 +123,21 @@ pub fn twox_256(data: &[u8]) -> [u8; 32] { twox_256_into(data, &mut r); r } + +/// Do a keccak 256-bit hash and return result. +pub fn keccak_256(data: &[u8]) -> [u8; 32] { + let mut keccak = Keccak::v256(); + keccak.update(data); + let mut output = [0u8; 32]; + keccak.finalize(&mut output); + output +} + +/// Do a sha2 256-bit hash and return result. +pub fn sha2_256(data: &[u8]) -> [u8; 32] { + let mut hasher = Sha256::new(); + hasher.input(data); + let mut output = [0u8; 32]; + output.copy_from_slice(&hasher.result()); + output +} diff --git a/core/primitives/src/hexdisplay.rs b/primitives/core/src/hexdisplay.rs similarity index 88% rename from core/primitives/src/hexdisplay.rs rename to primitives/core/src/hexdisplay.rs index 2c8533e25b5f8..14fedc205c49e 100644 --- a/core/primitives/src/hexdisplay.rs +++ b/primitives/core/src/hexdisplay.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,8 +24,8 @@ impl<'a> HexDisplay<'a> { pub fn from(d: &'a R) -> Self { HexDisplay(d.as_bytes_ref()) } } -impl<'a> rstd::fmt::Display for HexDisplay<'a> { - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> Result<(), rstd::fmt::Error> { +impl<'a> sp_std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> Result<(), sp_std::fmt::Error> { if self.0.len() < 1027 { for byte in self.0 { f.write_fmt(format_args!("{:02x}", byte))?; @@ -43,8 +43,8 @@ impl<'a> rstd::fmt::Display for HexDisplay<'a> { } } -impl<'a> rstd::fmt::Debug for HexDisplay<'a> { - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> Result<(), rstd::fmt::Error> { +impl<'a> sp_std::fmt::Debug for HexDisplay<'a> { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> Result<(), sp_std::fmt::Error> { for byte in self.0 { f.write_fmt(format_args!("{:02x}", byte))?; } @@ -58,7 +58,7 @@ pub trait AsBytesRef { fn as_bytes_ref(&self) -> &[u8]; } -impl<'a> AsBytesRef for &'a [u8] { +impl AsBytesRef for &[u8] { fn as_bytes_ref(&self) -> &[u8] { self } } diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs new file mode 100644 index 0000000000000..32e65de40dbaa --- /dev/null +++ b/primitives/core/src/lib.rs @@ -0,0 +1,311 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Shareable Substrate types. + +#![warn(missing_docs)] + +#![cfg_attr(not(feature = "std"), no_std)] + +/// Initialize 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 ),* $(,)? ) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ); +} + +use sp_std::prelude::*; +use sp_std::ops::Deref; +#[cfg(feature = "std")] +use std::borrow::Cow; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +#[cfg(feature = "std")] +pub use serde; +#[doc(hidden)] +pub use codec::{Encode, Decode}; + +pub use sp_debug_derive::RuntimeDebug; + +#[cfg(feature = "std")] +pub use impl_serde::serialize as bytes; + +#[cfg(feature = "full_crypto")] +pub mod hashing; +#[cfg(feature = "full_crypto")] +pub use hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256, keccak_256}; +#[cfg(feature = "std")] +pub mod hexdisplay; +pub mod crypto; + +pub mod u32_trait; + +pub mod ed25519; +pub mod sr25519; +pub mod ecdsa; +pub mod hash; +mod hasher; +pub mod offchain; +pub mod sandbox; +pub mod uint; +mod changes_trie; +#[cfg(feature = "std")] +pub mod traits; +pub mod testing; + +#[cfg(test)] +mod tests; + +pub use self::hash::{H160, H256, H512, convert_hash}; +pub use self::uint::U256; +pub use changes_trie::ChangesTrieConfiguration; +#[cfg(feature = "full_crypto")] +pub use crypto::{DeriveJunction, Pair, Public}; + +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; + +pub use sp_storage as storage; + +#[doc(hidden)] +pub use sp_std; + +/// Context for executing a call into the runtime. +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 offchain calls. + /// + /// This allows passing offchain extension and customizing available capabilities. + OffchainCall(Option<(Box, offchain::Capabilities)>), +} + +impl ExecutionContext { + /// Returns the capabilities of particular context. + pub fn capabilities(&self) -> offchain::Capabilities { + use ExecutionContext::*; + + match self { + Importing | Syncing | BlockConstruction => + offchain::Capabilities::none(), + // Enable keystore by default for offchain calls. CC @bkchr + OffchainCall(None) => [offchain::Capability::Keystore][..].into(), + OffchainCall(Some((_, capabilities))) => *capabilities, + } + } +} + +/// Hex-serialized shim for `Vec`. +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord))] +pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); + +impl From> for Bytes { + fn from(s: Vec) -> Self { Bytes(s) } +} + +impl From for Bytes { + fn from(s: OpaqueMetadata) -> Self { Bytes(s.0) } +} + +impl Deref for Bytes { + type Target = [u8]; + fn deref(&self) -> &[u8] { &self.0[..] } +} + +/// Stores the encoded `RuntimeMetadata` for the native side as opaque type. +#[derive(Encode, Decode, PartialEq)] +pub struct OpaqueMetadata(Vec); + +impl OpaqueMetadata { + /// Creates a new instance with the given metadata blob. + pub fn new(metadata: Vec) -> Self { + OpaqueMetadata(metadata) + } +} + +impl sp_std::ops::Deref for OpaqueMetadata { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &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 sp_std::fmt::Debug for NativeOrEncoded { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + hexdisplay::HexDisplay::from(&self.as_encoded().as_ref()).fmt(f) + } +} + +#[cfg(feature = "std")] +impl NativeOrEncoded { + /// Return the value as the encoded format. + pub fn as_encoded(&self) -> Cow<'_, [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) == codec::Decode::decode(&mut &e[..]).ok().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 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 codec::EncodeLike for NeverNativeValue {} + +#[cfg(feature = "std")] +impl codec::Decode for NeverNativeValue { + fn decode(_: &mut I) -> Result { + Err("`NeverNativeValue` should never be decoded".into()) + } +} + +/// Provide a simple 4 byte identifier for a type. +pub trait TypeId { + /// Simple 4 byte identifier. + const TYPE_ID: [u8; 4]; +} + +/// A log level matching the one from `log` crate. +/// +/// Used internally by `sp_io::log` method. +#[derive(Encode, Decode, sp_runtime_interface::pass_by::PassByEnum, Copy, Clone)] +pub enum LogLevel { + /// `Error` log level. + Error = 1, + /// `Warn` log level. + Warn = 2, + /// `Info` log level. + Info = 3, + /// `Debug` log level. + Debug = 4, + /// `Trace` log level. + Trace = 5, +} + +impl From for LogLevel { + fn from(val: u32) -> Self { + match val { + x if x == LogLevel::Warn as u32 => LogLevel::Warn, + x if x == LogLevel::Info as u32 => LogLevel::Info, + x if x == LogLevel::Debug as u32 => LogLevel::Debug, + x if x == LogLevel::Trace as u32 => LogLevel::Trace, + _ => LogLevel::Error, + } + } +} + +impl From for LogLevel { + fn from(l: log::Level) -> Self { + use log::Level::*; + match l { + Error => Self::Error, + Warn => Self::Warn, + Info => Self::Info, + Debug => Self::Debug, + Trace => Self::Trace, + } + } +} + +impl From for log::Level { + fn from(l: LogLevel) -> Self { + use self::LogLevel::*; + match l { + Error => Self::Error, + Warn => Self::Warn, + Info => Self::Info, + Debug => Self::Debug, + Trace => Self::Trace, + } + } +} + +/// Encodes the given value into a buffer and returns the pointer and the length as a single `u64`. +/// +/// When Substrate calls into Wasm it expects a fixed signature for functions exported +/// from the Wasm blob. The return value of this signature is always a `u64`. +/// This `u64` stores the pointer to the encoded return value and the length of this encoded value. +/// The low `32bits` are reserved for the pointer, followed by `32bit` for the length. +#[cfg(not(feature = "std"))] +pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 { + let encoded = value.encode(); + + let ptr = encoded.as_ptr() as u64; + let length = encoded.len() as u64; + let res = ptr | (length << 32); + + // Leak the output vector to avoid it being freed. + // This is fine in a WASM context since the heap + // will be discarded after the call. + sp_std::mem::forget(encoded); + + res +} diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs new file mode 100644 index 0000000000000..e2e00c36e0769 --- /dev/null +++ b/primitives/core/src/offchain/mod.rs @@ -0,0 +1,739 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Offchain workers types + +use codec::{Encode, Decode}; +use sp_std::{prelude::{Vec, Box}, convert::TryFrom}; +use crate::RuntimeDebug; +use sp_runtime_interface::pass_by::{PassByCodec, PassByInner, PassByEnum}; + +pub use crate::crypto::KeyTypeId; + +#[cfg(feature = "std")] +pub mod storage; +#[cfg(feature = "std")] +pub mod testing; + +/// Offchain workers local storage. +pub trait OffchainStorage: Clone + Send + Sync { + /// Persist a value in storage under given key and prefix. + fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]); + + /// Retrieve a value from storage under given key and prefix. + fn get(&self, prefix: &[u8], key: &[u8]) -> Option>; + + /// Replace the value in storage if given old_value matches the current one. + /// + /// Returns `true` if the value has been set and false otherwise. + fn compare_and_set( + &mut self, + prefix: &[u8], + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool; +} + +/// A type of supported crypto. +#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug, PassByEnum)] +#[repr(C)] +pub enum StorageKind { + /// Persistent storage is non-revertible and not fork-aware. It means that any value + /// set by the offchain worker triggered at block `N(hash1)` is persisted even + /// if that block is reverted as non-canonical and is available for the worker + /// that is re-run at block `N(hash2)`. + /// This storage can be used by offchain workers to handle forks + /// and coordinate offchain workers running on different forks. + PERSISTENT = 1, + /// Local storage is revertible and fork-aware. It means that any value + /// set by the offchain worker triggered at block `N(hash1)` is reverted + /// if that block is reverted as non-canonical and is NOT available for the worker + /// that is re-run at block `N(hash2)`. + LOCAL = 2, +} + +impl TryFrom for StorageKind { + type Error = (); + + fn try_from(kind: u32) -> Result { + match kind { + e if e == u32::from(StorageKind::PERSISTENT as u8) => Ok(StorageKind::PERSISTENT), + e if e == u32::from(StorageKind::LOCAL as u8) => Ok(StorageKind::LOCAL), + _ => Err(()), + } + } +} + +impl From for u32 { + fn from(c: StorageKind) -> Self { + c as u8 as u32 + } +} + +/// Opaque type for offchain http requests. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, Encode, Decode, PassByInner)] +#[cfg_attr(feature = "std", derive(Hash))] +pub struct HttpRequestId(pub u16); + +impl From for u32 { + fn from(c: HttpRequestId) -> Self { + c.0 as u32 + } +} + +/// An error enum returned by some http methods. +#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug, Encode, Decode, PassByEnum)] +#[repr(C)] +pub enum HttpError { + /// The requested action couldn't been completed within a deadline. + DeadlineReached = 1, + /// There was an IO Error while processing the request. + IoError = 2, + /// The ID of the request is invalid in this context. + Invalid = 3, +} + +impl TryFrom for HttpError { + type Error = (); + + fn try_from(error: u32) -> Result { + match error { + e if e == HttpError::DeadlineReached as u8 as u32 => Ok(HttpError::DeadlineReached), + e if e == HttpError::IoError as u8 as u32 => Ok(HttpError::IoError), + e if e == HttpError::Invalid as u8 as u32 => Ok(HttpError::Invalid), + _ => Err(()) + } + } +} + +impl From for u32 { + fn from(c: HttpError) -> Self { + c as u8 as u32 + } +} + +/// Status of the HTTP request +#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug, Encode, Decode, PassByCodec)] +pub enum HttpRequestStatus { + /// Deadline was reached while we waited for this request to finish. + /// + /// Note the deadline is controlled by the calling part, it not necessarily + /// means that the request has timed out. + DeadlineReached, + /// An error has occured during the request, for example a timeout or the + /// remote has closed our socket. + /// + /// The request is now considered destroyed. To retry the request you need + /// to construct it again. + IoError, + /// The passed ID is invalid in this context. + Invalid, + /// The request has finished with given status code. + Finished(u16), +} + +impl From for u32 { + fn from(status: HttpRequestStatus) -> Self { + match status { + HttpRequestStatus::Invalid => 0, + HttpRequestStatus::DeadlineReached => 10, + HttpRequestStatus::IoError => 20, + HttpRequestStatus::Finished(code) => u32::from(code), + } + } +} + +impl TryFrom for HttpRequestStatus { + type Error = (); + + fn try_from(status: u32) -> Result { + match status { + 0 => Ok(HttpRequestStatus::Invalid), + 10 => Ok(HttpRequestStatus::DeadlineReached), + 20 => Ok(HttpRequestStatus::IoError), + 100..=999 => u16::try_from(status).map(HttpRequestStatus::Finished).map_err(|_| ()), + _ => Err(()), + } + } +} + +/// A blob to hold information about the local node's network state +/// without committing to its format. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByCodec)] +#[cfg_attr(feature = "std", derive(Default))] +pub struct OpaqueNetworkState { + /// PeerId of the local node. + pub peer_id: OpaquePeerId, + /// List of addresses the node knows it can be reached as. + pub external_addresses: Vec, +} + +/// Simple blob to hold a `PeerId` without committing to its format. +#[derive(Default, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByInner)] +pub struct OpaquePeerId(pub Vec); + +impl OpaquePeerId { + /// Create new `OpaquePeerId` + pub fn new(vec: Vec) -> Self { + OpaquePeerId(vec) + } +} + +/// Simple blob to hold a `Multiaddr` without committing to its format. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByInner)] +pub struct OpaqueMultiaddr(pub Vec); + +impl OpaqueMultiaddr { + /// Create new `OpaqueMultiaddr` + pub fn new(vec: Vec) -> Self { + OpaqueMultiaddr(vec) + } +} + +/// Opaque timestamp type +#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug, PassByInner, Encode, Decode)] +pub struct Timestamp(u64); + +/// Duration type +#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug, PassByInner, Encode, Decode)] +pub struct Duration(u64); + +impl Duration { + /// Create new duration representing given number of milliseconds. + pub fn from_millis(millis: u64) -> Self { + Duration(millis) + } + + /// Returns number of milliseconds this Duration represents. + pub fn millis(&self) -> u64 { + self.0 + } +} + +impl Timestamp { + /// Creates new `Timestamp` given unix timestamp in miliseconds. + pub fn from_unix_millis(millis: u64) -> Self { + Timestamp(millis) + } + + /// Increase the timestamp by given `Duration`. + pub fn add(&self, duration: Duration) -> Timestamp { + Timestamp(self.0.saturating_add(duration.0)) + } + + /// Decrease the timestamp by given `Duration` + pub fn sub(&self, duration: Duration) -> Timestamp { + Timestamp(self.0.saturating_sub(duration.0)) + } + + /// Returns a saturated difference (Duration) between two Timestamps. + pub fn diff(&self, other: &Self) -> Duration { + Duration(self.0.saturating_sub(other.0)) + } + + /// Return number of milliseconds since UNIX epoch. + pub fn unix_millis(&self) -> u64 { + self.0 + } +} + +/// Execution context extra capabilities. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[repr(u8)] +pub enum Capability { + /// Access to transaction pool. + TransactionPool = 1, + /// External http calls. + Http = 2, + /// Keystore access. + Keystore = 4, + /// Randomness source. + Randomness = 8, + /// Access to opaque network state. + NetworkState = 16, + /// Access to offchain worker DB (read only). + OffchainWorkerDbRead = 32, + /// Access to offchain worker DB (writes). + OffchainWorkerDbWrite = 64, +} + +/// A set of capabilities +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Capabilities(u8); + +impl Capabilities { + /// Return an object representing an empty set of capabilities. + pub fn none() -> Self { + Self(0) + } + + /// Return an object representing all capabilities enabled. + pub fn all() -> Self { + Self(u8::max_value()) + } + + /// Return capabilities for rich offchain calls. + /// + /// Those calls should be allowed to sign and submit transactions + /// and access offchain workers database (but read only!). + pub fn rich_offchain_call() -> Self { + [ + Capability::TransactionPool, + Capability::Keystore, + Capability::OffchainWorkerDbRead, + ][..].into() + } + + /// Check if particular capability is enabled. + pub fn has(&self, capability: Capability) -> bool { + self.0 & capability as u8 != 0 + } + + /// Check if this capability object represents all capabilities. + pub fn has_all(&self) -> bool { + self == &Capabilities::all() + } +} + +impl<'a> From<&'a [Capability]> for Capabilities { + fn from(list: &'a [Capability]) -> Self { + Capabilities(list.iter().fold(0_u8, |a, b| a | *b as u8)) + } +} + +/// An extended externalities for offchain workers. +pub trait Externalities: Send { + /// Returns if the local node is a potential validator. + /// + /// Even if this function returns `true`, it does not mean that any keys are configured + /// and that the validator is registered in the chain. + fn is_validator(&self) -> bool; + + /// Returns information about the local node's network state. + fn network_state(&self) -> Result; + + /// Returns current UNIX timestamp (in millis) + fn timestamp(&mut self) -> Timestamp; + + /// Pause the execution until `deadline` is reached. + fn sleep_until(&mut self, deadline: Timestamp); + + /// Returns a random seed. + /// + /// This is a trully random non deterministic seed generated by host environment. + /// Obviously fine in the off-chain worker context. + fn random_seed(&mut self) -> [u8; 32]; + + /// Sets a value in the local storage. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]); + + /// Sets a value in the local storage if it matches current value. + /// + /// Since multiple offchain workers may be running concurrently, to prevent + /// data races use CAS to coordinate between them. + /// + /// Returns `true` if the value has been set, `false` otherwise. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_compare_and_set( + &mut self, + kind: StorageKind, + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool; + + /// Gets a value from the local storage. + /// + /// If the value does not exist in the storage `None` will be returned. + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option>; + + /// Initiates a http request given HTTP verb and the URL. + /// + /// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters. + /// Returns the id of newly started request. + /// + /// Returns an error if: + /// - No new request identifier could be allocated. + /// - The method or URI contain invalid characters. + /// + fn http_request_start( + &mut self, + method: &str, + uri: &str, + meta: &[u8] + ) -> Result; + + /// Append header to the request. + /// + /// Calling this function multiple times with the same header name continues appending new + /// headers. In other words, headers are never replaced. + /// + /// Returns an error if: + /// - The request identifier is invalid. + /// - You have called `http_request_write_body` on that request. + /// - The name or value contain invalid characters. + /// + /// An error doesn't poison the request, and you can continue as if the call had never been + /// made. + /// + fn http_request_add_header( + &mut self, + request_id: HttpRequestId, + name: &str, + value: &str + ) -> Result<(), ()>; + + /// Write a chunk of request body. + /// + /// Calling this function with a non-empty slice may or may not start the + /// HTTP request. Calling this function with an empty chunks finalizes the + /// request and always starts it. It is no longer valid to write more data + /// afterwards. + /// Passing `None` as deadline blocks forever. + /// + /// Returns an error if: + /// - The request identifier is invalid. + /// - `http_response_wait` has already been called on this request. + /// - The deadline is reached. + /// - An I/O error has happened, for example the remote has closed our + /// request. The request is then considered invalid. + /// + fn http_request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option + ) -> Result<(), HttpError>; + + /// Block and wait for the responses for given requests. + /// + /// Returns a vector of request statuses (the len is the same as ids). + /// Note that if deadline is not provided the method will block indefinitely, + /// otherwise unready responses will produce `DeadlineReached` status. + /// + /// If a response returns an `IoError`, it is then considered destroyed. + /// Its id is then invalid. + /// + /// Passing `None` as deadline blocks forever. + fn http_response_wait( + &mut self, + ids: &[HttpRequestId], + deadline: Option + ) -> Vec; + + /// Read all response headers. + /// + /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. + /// + /// Dispatches the request if it hasn't been done yet. It is no longer + /// valid to modify the headers or write data to the request. + /// + /// Returns an empty list if the identifier is unknown/invalid, hasn't + /// received a response, or has finished. + fn http_response_headers( + &mut self, + request_id: HttpRequestId + ) -> Vec<(Vec, Vec)>; + + /// Read a chunk of body response to given buffer. + /// + /// Dispatches the request if it hasn't been done yet. It is no longer + /// valid to modify the headers or write data to the request. + /// + /// Returns the number of bytes written or an error in case a deadline + /// is reached or server closed the connection. + /// Passing `None` as a deadline blocks forever. + /// + /// If `Ok(0)` or `Err(IoError)` is returned, the request is considered + /// destroyed. Doing another read or getting the response's headers, for + /// example, is then invalid. + /// + /// Returns an error if: + /// - The request identifier is invalid. + /// - The deadline is reached. + /// - An I/O error has happened, for example the remote has closed our + /// request. The request is then considered invalid. + /// + fn http_response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option + ) -> Result; + +} +impl Externalities for Box { + fn is_validator(&self) -> bool { + (& **self).is_validator() + } + + fn network_state(&self) -> Result { + (& **self).network_state() + } + + fn timestamp(&mut self) -> Timestamp { + (&mut **self).timestamp() + } + + fn sleep_until(&mut self, deadline: Timestamp) { + (&mut **self).sleep_until(deadline) + } + + fn random_seed(&mut self) -> [u8; 32] { + (&mut **self).random_seed() + } + + fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { + (&mut **self).local_storage_set(kind, key, value) + } + + fn local_storage_compare_and_set( + &mut self, + kind: StorageKind, + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool { + (&mut **self).local_storage_compare_and_set(kind, key, old_value, new_value) + } + + fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { + (&mut **self).local_storage_get(kind, key) + } + + fn http_request_start(&mut self, method: &str, uri: &str, meta: &[u8]) -> Result { + (&mut **self).http_request_start(method, uri, meta) + } + + fn http_request_add_header(&mut self, request_id: HttpRequestId, name: &str, value: &str) -> Result<(), ()> { + (&mut **self).http_request_add_header(request_id, name, value) + } + + fn http_request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option + ) -> Result<(), HttpError> { + (&mut **self).http_request_write_body(request_id, chunk, deadline) + } + + fn http_response_wait(&mut self, ids: &[HttpRequestId], deadline: Option) -> Vec { + (&mut **self).http_response_wait(ids, deadline) + } + + fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { + (&mut **self).http_response_headers(request_id) + } + + fn http_response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option + ) -> Result { + (&mut **self).http_response_read_body(request_id, buffer, deadline) + } +} +/// An `OffchainExternalities` implementation with limited capabilities. +pub struct LimitedExternalities { + capabilities: Capabilities, + externalities: T, +} + +impl LimitedExternalities { + /// Create new externalities limited to given `capabilities`. + pub fn new(capabilities: Capabilities, externalities: T) -> Self { + Self { + capabilities, + externalities, + } + } + + /// Check if given capability is allowed. + /// + /// Panics in case it is not. + fn check(&self, capability: Capability, name: &'static str) { + if !self.capabilities.has(capability) { + panic!("Accessing a forbidden API: {}. No: {:?} capability.", name, capability); + } + } +} + +impl Externalities for LimitedExternalities { + fn is_validator(&self) -> bool { + self.check(Capability::Keystore, "is_validator"); + self.externalities.is_validator() + } + + fn network_state(&self) -> Result { + self.check(Capability::NetworkState, "network_state"); + self.externalities.network_state() + } + + fn timestamp(&mut self) -> Timestamp { + self.check(Capability::Http, "timestamp"); + self.externalities.timestamp() + } + + fn sleep_until(&mut self, deadline: Timestamp) { + self.check(Capability::Http, "sleep_until"); + self.externalities.sleep_until(deadline) + } + + fn random_seed(&mut self) -> [u8; 32] { + self.check(Capability::Randomness, "random_seed"); + self.externalities.random_seed() + } + + fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { + self.check(Capability::OffchainWorkerDbWrite, "local_storage_set"); + self.externalities.local_storage_set(kind, key, value) + } + + fn local_storage_compare_and_set( + &mut self, + kind: StorageKind, + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool { + self.check(Capability::OffchainWorkerDbWrite, "local_storage_compare_and_set"); + self.externalities.local_storage_compare_and_set(kind, key, old_value, new_value) + } + + fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { + self.check(Capability::OffchainWorkerDbRead, "local_storage_get"); + self.externalities.local_storage_get(kind, key) + } + + fn http_request_start(&mut self, method: &str, uri: &str, meta: &[u8]) -> Result { + self.check(Capability::Http, "http_request_start"); + self.externalities.http_request_start(method, uri, meta) + } + + fn http_request_add_header(&mut self, request_id: HttpRequestId, name: &str, value: &str) -> Result<(), ()> { + self.check(Capability::Http, "http_request_add_header"); + self.externalities.http_request_add_header(request_id, name, value) + } + + fn http_request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option + ) -> Result<(), HttpError> { + self.check(Capability::Http, "http_request_write_body"); + self.externalities.http_request_write_body(request_id, chunk, deadline) + } + + fn http_response_wait(&mut self, ids: &[HttpRequestId], deadline: Option) -> Vec { + self.check(Capability::Http, "http_response_wait"); + self.externalities.http_response_wait(ids, deadline) + } + + fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { + self.check(Capability::Http, "http_response_headers"); + self.externalities.http_response_headers(request_id) + } + + fn http_response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option + ) -> Result { + self.check(Capability::Http, "http_response_read_body"); + self.externalities.http_response_read_body(request_id, buffer, deadline) + } +} + +#[cfg(feature = "std")] +sp_externalities::decl_extension! { + /// The offchain extension that will be registered at the Substrate externalities. + pub struct OffchainExt(Box); +} + +#[cfg(feature = "std")] +impl OffchainExt { + /// Create a new instance of `Self`. + pub fn new(offchain: O) -> Self { + Self(Box::new(offchain)) + } +} + +/// Abstraction over transaction pool. +/// +/// This trait is currently used within the `ExternalitiesExtension` +/// to provide offchain calls with access to the transaction pool without +/// tight coupling with any pool implementation. +#[cfg(feature = "std")] +pub trait TransactionPool { + /// Submit transaction. + /// + /// The transaction will end up in the pool and be propagated to others. + fn submit_transaction(&mut self, extrinsic: Vec) -> Result<(), ()>; +} + +#[cfg(feature = "std")] +sp_externalities::decl_extension! { + /// An externalities extension to submit transactions to the pool. + pub struct TransactionPoolExt(Box); +} + +#[cfg(feature = "std")] +impl TransactionPoolExt { + /// Create a new instance of `TransactionPoolExt`. + pub fn new(pool: O) -> Self { + Self(Box::new(pool)) + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn timestamp_ops() { + let t = Timestamp(5); + assert_eq!(t.add(Duration::from_millis(10)), Timestamp(15)); + assert_eq!(t.sub(Duration::from_millis(10)), Timestamp(0)); + assert_eq!(t.diff(&Timestamp(3)), Duration(2)); + } + + #[test] + fn capabilities() { + let none = Capabilities::none(); + let all = Capabilities::all(); + let some = Capabilities::from(&[Capability::Keystore, Capability::Randomness][..]); + + assert!(!none.has(Capability::Keystore)); + assert!(all.has(Capability::Keystore)); + assert!(some.has(Capability::Keystore)); + assert!(!none.has(Capability::TransactionPool)); + assert!(all.has(Capability::TransactionPool)); + assert!(!some.has(Capability::TransactionPool)); + } +} diff --git a/primitives/core/src/offchain/storage.rs b/primitives/core/src/offchain/storage.rs new file mode 100644 index 0000000000000..31b6423e5d81c --- /dev/null +++ b/primitives/core/src/offchain/storage.rs @@ -0,0 +1,60 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! In-memory implementation of offchain workers database. + +use std::collections::hash_map::{HashMap, Entry}; +use crate::offchain::OffchainStorage; + +/// In-memory storage for offchain workers. +#[derive(Debug, Clone, Default)] +pub struct InMemOffchainStorage { + storage: HashMap, Vec>, +} + +impl OffchainStorage for InMemOffchainStorage { + fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) { + let key = prefix.iter().chain(key).cloned().collect(); + self.storage.insert(key, value.to_vec()); + } + + fn get(&self, prefix: &[u8], key: &[u8]) -> Option> { + let key: Vec = prefix.iter().chain(key).cloned().collect(); + self.storage.get(&key).cloned() + } + + fn compare_and_set( + &mut self, + prefix: &[u8], + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool { + let key = prefix.iter().chain(key).cloned().collect(); + + match self.storage.entry(key) { + Entry::Vacant(entry) => if old_value.is_none() { + entry.insert(new_value.to_vec()); + true + } else { false }, + Entry::Occupied(ref mut entry) if Some(entry.get().as_slice()) == old_value => { + entry.insert(new_value.to_vec()); + true + }, + _ => false, + } + } +} diff --git a/primitives/core/src/offchain/testing.rs b/primitives/core/src/offchain/testing.rs new file mode 100644 index 0000000000000..82438dd6f8519 --- /dev/null +++ b/primitives/core/src/offchain/testing.rs @@ -0,0 +1,339 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Utilities for offchain calls testing. +//! +//! Namely all ExecutionExtensions that allow mocking +//! the extra APIs. + +use std::{ + collections::BTreeMap, + sync::Arc, +}; +use crate::offchain::{ + self, + storage::InMemOffchainStorage, + HttpError, + HttpRequestId as RequestId, + HttpRequestStatus as RequestStatus, + Timestamp, + StorageKind, + OpaqueNetworkState, + TransactionPool, + OffchainStorage, +}; +use parking_lot::RwLock; + +/// Pending request. +#[derive(Debug, Default, PartialEq, Eq)] +pub struct PendingRequest { + /// HTTP method + pub method: String, + /// URI + pub uri: String, + /// Encoded Metadata + pub meta: Vec, + /// Request headers + pub headers: Vec<(String, String)>, + /// Request body + pub body: Vec, + /// Has the request been sent already. + pub sent: bool, + /// Response body + pub response: Option>, + /// Number of bytes already read from the response body. + pub read: usize, + /// Response headers + pub response_headers: Vec<(String, String)>, +} + +/// Internal state of the externalities. +/// +/// This can be used in tests to respond or assert stuff about interactions. +#[derive(Debug, Default)] +pub struct OffchainState { + /// A list of pending requests. + pub requests: BTreeMap, + expected_requests: BTreeMap, + /// Persistent local storage + pub persistent_storage: InMemOffchainStorage, + /// Local storage + pub local_storage: InMemOffchainStorage, +} + +impl OffchainState { + /// Asserts that pending request has been submitted and fills it's response. + pub fn fulfill_pending_request( + &mut self, + id: u16, + expected: PendingRequest, + response: impl Into>, + response_headers: impl IntoIterator, + ) { + match self.requests.get_mut(&RequestId(id)) { + None => { + panic!("Missing pending request: {:?}.\n\nAll: {:?}", id, self.requests); + } + Some(req) => { + assert_eq!( + *req, + expected, + ); + req.response = Some(response.into()); + req.response_headers = response_headers.into_iter().collect(); + } + } + } + + fn fulfill_expected(&mut self, id: u16) { + if let Some(mut req) = self.expected_requests.remove(&RequestId(id)) { + let response = req.response.take().expect("Response checked while added."); + let headers = std::mem::replace(&mut req.response_headers, vec![]); + self.fulfill_pending_request(id, req, response, headers); + } + } + + /// Add expected HTTP request. + /// + /// This method can be used to initialize expected HTTP requests and their responses + /// before running the actual code that utilizes them (for instance before calling into runtime). + /// Expected request has to be fulfilled before this struct is dropped, + /// the `response` and `response_headers` fields will be used to return results to the callers. + pub fn expect_request(&mut self, id: u16, expected: PendingRequest) { + if expected.response.is_none() { + panic!("Expected request needs to have a response."); + } + self.expected_requests.insert(RequestId(id), expected); + } +} + +impl Drop for OffchainState { + fn drop(&mut self) { + // If we panic! while we are already in a panic, the test dies with an illegal instruction. + if !self.expected_requests.is_empty() && !std::thread::panicking() { + panic!("Unfulfilled expected requests: {:?}", self.expected_requests); + } + } +} + +/// Implementation of offchain externalities used for tests. +#[derive(Clone, Default, Debug)] +pub struct TestOffchainExt(pub Arc>); + +impl TestOffchainExt { + /// Create new `TestOffchainExt` and a reference to the internal state. + pub fn new() -> (Self, Arc>) { + let ext = Self::default(); + let state = ext.0.clone(); + (ext, state) + } +} + +impl offchain::Externalities for TestOffchainExt { + fn is_validator(&self) -> bool { + unimplemented!("not needed in tests so far") + } + + fn network_state(&self) -> Result { + Ok(OpaqueNetworkState { + peer_id: Default::default(), + external_addresses: vec![], + }) + } + + fn timestamp(&mut self) -> Timestamp { + unimplemented!("not needed in tests so far") + } + + fn sleep_until(&mut self, _deadline: Timestamp) { + unimplemented!("not needed in tests so far") + } + + fn random_seed(&mut self) -> [u8; 32] { + unimplemented!("not needed in tests so far") + } + + fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { + let mut state = self.0.write(); + match kind { + StorageKind::LOCAL => &mut state.local_storage, + StorageKind::PERSISTENT => &mut state.persistent_storage, + }.set(b"", key, value); + } + + fn local_storage_compare_and_set( + &mut self, + kind: StorageKind, + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8] + ) -> bool { + let mut state = self.0.write(); + match kind { + StorageKind::LOCAL => &mut state.local_storage, + StorageKind::PERSISTENT => &mut state.persistent_storage, + }.compare_and_set(b"", key, old_value, new_value) + } + + fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { + let state = self.0.read(); + match kind { + StorageKind::LOCAL => &state.local_storage, + StorageKind::PERSISTENT => &state.persistent_storage, + }.get(b"", key) + } + + fn http_request_start(&mut self, method: &str, uri: &str, meta: &[u8]) -> Result { + let mut state = self.0.write(); + let id = RequestId(state.requests.len() as u16); + state.requests.insert(id.clone(), PendingRequest { + method: method.into(), + uri: uri.into(), + meta: meta.into(), + ..Default::default() + }); + Ok(id) + } + + fn http_request_add_header( + &mut self, + request_id: RequestId, + name: &str, + value: &str, + ) -> Result<(), ()> { + let mut state = self.0.write(); + if let Some(req) = state.requests.get_mut(&request_id) { + req.headers.push((name.into(), value.into())); + Ok(()) + } else { + Err(()) + } + } + + fn http_request_write_body( + &mut self, + request_id: RequestId, + chunk: &[u8], + _deadline: Option + ) -> Result<(), HttpError> { + let mut state = self.0.write(); + + let sent = { + let req = state.requests.get_mut(&request_id).ok_or(HttpError::IoError)?; + req.body.extend(chunk); + if chunk.is_empty() { + req.sent = true; + } + req.sent + }; + + if sent { + state.fulfill_expected(request_id.0); + } + + Ok(()) + } + + fn http_response_wait( + &mut self, + ids: &[RequestId], + _deadline: Option, + ) -> Vec { + let state = self.0.read(); + + ids.iter().map(|id| match state.requests.get(id) { + Some(req) if req.response.is_none() => + panic!("No `response` provided for request with id: {:?}", id), + None => RequestStatus::Invalid, + _ => RequestStatus::Finished(200), + }).collect() + } + + fn http_response_headers(&mut self, request_id: RequestId) -> Vec<(Vec, Vec)> { + let state = self.0.read(); + if let Some(req) = state.requests.get(&request_id) { + req.response_headers + .clone() + .into_iter() + .map(|(k, v)| (k.into_bytes(), v.into_bytes())) + .collect() + } else { + Default::default() + } + } + + fn http_response_read_body( + &mut self, + request_id: RequestId, + buffer: &mut [u8], + _deadline: Option + ) -> Result { + let mut state = self.0.write(); + if let Some(req) = state.requests.get_mut(&request_id) { + let response = req.response + .as_mut() + .expect(&format!("No response provided for request: {:?}", request_id)); + + if req.read >= response.len() { + // Remove the pending request as per spec. + state.requests.remove(&request_id); + Ok(0) + } else { + let read = std::cmp::min(buffer.len(), response[req.read..].len()); + buffer[0..read].copy_from_slice(&response[req.read..read]); + req.read += read; + Ok(read) + } + } else { + Err(HttpError::IoError) + } + } +} + +/// The internal state of the fake transaction pool. +#[derive(Default)] +pub struct PoolState { + /// A vector of transactions submitted from the runtime. + pub transactions: Vec>, +} + +/// Implementation of transaction pool used for test. +/// +/// Note that this implementation does not verify correctness +/// of sent extrinsics. It's meant to be used in contexts +/// where an actual runtime is not known. +/// +/// It's advised to write integration tests that include the +/// actual transaction pool to make sure the produced +/// transactions are valid. +#[derive(Default)] +pub struct TestTransactionPoolExt(Arc>); + +impl TestTransactionPoolExt { + /// Create new `TestTransactionPoolExt` and a reference to the internal state. + pub fn new() -> (Self, Arc>) { + let ext = Self::default(); + let state = ext.0.clone(); + (ext, state) + } +} + +impl TransactionPool for TestTransactionPoolExt { + fn submit_transaction(&mut self, extrinsic: Vec) -> Result<(), ()> { + self.0.write().transactions.push(extrinsic); + Ok(()) + } +} diff --git a/primitives/core/src/sandbox.rs b/primitives/core/src/sandbox.rs new file mode 100644 index 0000000000000..a0673c49db102 --- /dev/null +++ b/primitives/core/src/sandbox.rs @@ -0,0 +1,220 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Definition of a sandbox environment. + +use codec::{Encode, Decode}; +use sp_std::vec::Vec; + +/// Error error that can be returned from host function. +#[derive(Encode, Decode)] +#[derive(crate::RuntimeDebug)] +pub struct HostError; + +/// Representation of a typed wasm value. +#[derive(Clone, Copy, PartialEq, Encode, Decode)] +#[derive(crate::RuntimeDebug)] +pub enum TypedValue { + /// Value of 32-bit signed or unsigned integer. + #[codec(index = "1")] + I32(i32), + + /// Value of 64-bit signed or unsigned integer. + #[codec(index = "2")] + I64(i64), + + /// Value of 32-bit IEEE 754-2008 floating point number represented as a bit pattern. + #[codec(index = "3")] + F32(i32), + + /// Value of 64-bit IEEE 754-2008 floating point number represented as a bit pattern. + #[codec(index = "4")] + F64(i64), +} + +impl TypedValue { + /// Returns `Some` if this value of type `I32`. + pub fn as_i32(&self) -> Option { + match *self { + TypedValue::I32(v) => Some(v), + _ => None, + } + } +} + +#[cfg(feature = "std")] +impl From<::wasmi::RuntimeValue> for TypedValue { + fn from(val: ::wasmi::RuntimeValue) -> TypedValue { + use ::wasmi::RuntimeValue; + match val { + RuntimeValue::I32(v) => TypedValue::I32(v), + RuntimeValue::I64(v) => TypedValue::I64(v), + RuntimeValue::F32(v) => TypedValue::F32(v.to_bits() as i32), + RuntimeValue::F64(v) => TypedValue::F64(v.to_bits() as i64), + } + } +} + +#[cfg(feature = "std")] +impl From for ::wasmi::RuntimeValue { + fn from(val: TypedValue) -> ::wasmi::RuntimeValue { + use ::wasmi::RuntimeValue; + use ::wasmi::nan_preserving_float::{F32, F64}; + match val { + TypedValue::I32(v) => RuntimeValue::I32(v), + TypedValue::I64(v) => RuntimeValue::I64(v), + TypedValue::F32(v_bits) => RuntimeValue::F32(F32::from_bits(v_bits as u32)), + TypedValue::F64(v_bits) => RuntimeValue::F64(F64::from_bits(v_bits as u64)), + } + } +} + +/// Typed value that can be returned from a function. +/// +/// Basically a `TypedValue` plus `Unit`, for functions which return nothing. +#[derive(Clone, Copy, PartialEq, Encode, Decode)] +#[derive(crate::RuntimeDebug)] +pub enum ReturnValue { + /// For returning nothing. + Unit, + /// For returning some concrete value. + Value(TypedValue), +} + +impl From for ReturnValue { + fn from(v: TypedValue) -> ReturnValue { + ReturnValue::Value(v) + } +} + +impl ReturnValue { + /// Maximum number of bytes `ReturnValue` might occupy when serialized with + /// `Codec`. + /// + /// Breakdown: + /// 1 byte for encoding unit/value variant + /// 1 byte for encoding value type + /// 8 bytes for encoding the biggest value types available in wasm: f64, i64. + pub const ENCODED_MAX_SIZE: usize = 10; +} + +#[test] +fn return_value_encoded_max_size() { + let encoded = ReturnValue::Value(TypedValue::I64(-1)).encode(); + assert_eq!(encoded.len(), ReturnValue::ENCODED_MAX_SIZE); +} + +/// Describes an entity to define or import into the environment. +#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[derive(crate::RuntimeDebug)] +pub enum ExternEntity { + /// Function that is specified by an index in a default table of + /// a module that creates the sandbox. + #[codec(index = "1")] + Function(u32), + + /// Linear memory that is specified by some identifier returned by sandbox + /// module upon creation new sandboxed memory. + #[codec(index = "2")] + Memory(u32), +} + +/// An entry in a environment definition table. +/// +/// Each entry has a two-level name and description of an entity +/// being defined. +#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[derive(crate::RuntimeDebug)] +pub struct Entry { + /// Module name of which corresponding entity being defined. + pub module_name: Vec, + /// Field name in which corresponding entity being defined. + pub field_name: Vec, + /// External entity being defined. + pub entity: ExternEntity, +} + +/// Definition of runtime that could be used by sandboxed code. +#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[derive(crate::RuntimeDebug)] +pub struct EnvironmentDefinition { + /// Vector of all entries in the environment definition. + pub entries: Vec, +} + +/// Constant for specifying no limit when creating a sandboxed +/// memory instance. For FFI purposes. +pub const MEM_UNLIMITED: u32 = -1i32 as u32; + +/// No error happened. +/// +/// For FFI purposes. +pub const ERR_OK: u32 = 0; + +/// Validation or instantiation error occurred when creating new +/// sandboxed module instance. +/// +/// For FFI purposes. +pub const ERR_MODULE: u32 = -1i32 as u32; + +/// Out-of-bounds access attempted with memory or table. +/// +/// For FFI purposes. +pub const ERR_OUT_OF_BOUNDS: u32 = -2i32 as u32; + +/// Execution error occurred (typically trap). +/// +/// For FFI purposes. +pub const ERR_EXECUTION: u32 = -3i32 as u32; + +#[cfg(test)] +mod tests { + use super::*; + use std::fmt; + use codec::Codec; + + fn roundtrip(s: S) { + let encoded = s.encode(); + assert_eq!(S::decode(&mut &encoded[..]).unwrap(), s); + } + + #[test] + fn env_def_roundtrip() { + roundtrip(EnvironmentDefinition { + entries: vec![], + }); + + roundtrip(EnvironmentDefinition { + entries: vec![ + Entry { + module_name: b"kernel"[..].into(), + field_name: b"memory"[..].into(), + entity: ExternEntity::Memory(1337), + }, + ], + }); + + roundtrip(EnvironmentDefinition { + entries: vec![ + Entry { + module_name: b"env"[..].into(), + field_name: b"abort"[..].into(), + entity: ExternEntity::Function(228), + }, + ], + }); + } +} diff --git a/primitives/core/src/sr25519.rs b/primitives/core/src/sr25519.rs new file mode 100644 index 0000000000000..6e542f230f258 --- /dev/null +++ b/primitives/core/src/sr25519.rs @@ -0,0 +1,794 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// 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 = "full_crypto")] +use sp_std::vec::Vec; +#[cfg(feature = "full_crypto")] +use schnorrkel::{signing_context, ExpansionMode, Keypair, SecretKey, MiniSecretKey, PublicKey, + derive::{Derivation, ChainCode, CHAIN_CODE_LENGTH} +}; +#[cfg(feature = "full_crypto")] +use core::convert::TryFrom; +#[cfg(feature = "std")] +use substrate_bip39::mini_secret_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "full_crypto")] +use crate::crypto::{ + Pair as TraitPair, DeriveJunction, Infallible, SecretStringError +}; +#[cfg(feature = "std")] +use crate::crypto::Ss58Codec; + +use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}}; +use crate::hash::{H256, H512}; +use codec::{Encode, Decode}; +use sp_std::ops::Deref; + +#[cfg(feature = "std")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "full_crypto")] +use schnorrkel::keys::{MINI_SECRET_KEY_LENGTH, SECRET_KEY_LENGTH}; +use sp_runtime_interface::pass_by::PassByInner; + +// signing context +#[cfg(feature = "full_crypto")] +const SIGNING_CTX: &[u8] = b"substrate"; + +/// An Schnorrkel/Ristretto x25519 ("sr25519") public key. +#[cfg_attr(feature = "full_crypto", derive(Hash))] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Encode, Decode, Default, PassByInner)] +pub struct Public(pub [u8; 32]); + +/// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. +#[cfg(feature = "full_crypto")] +pub struct Pair(Keypair); + +#[cfg(feature = "full_crypto")] +impl Clone for Pair { + fn clone(&self) -> Self { + Pair(schnorrkel::Keypair { + public: self.0.public, + secret: schnorrkel::SecretKey::from_bytes(&self.0.secret.to_bytes()[..]) + .expect("key is always the correct size; qed") + }) + } +} + +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 Deref for Public { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &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() + } +} + +#[cfg(feature = "std")] +impl std::str::FromStr for Public { + type Err = crate::crypto::PublicError; + + fn from_str(s: &str) -> Result { + Self::from_ss58check(s) + } +} + +impl sp_std::convert::TryFrom<&[u8]> for Public { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 32 { + let mut inner = [0u8; 32]; + inner.copy_from_slice(data); + Ok(Public(inner)) + } else { + Err(()) + } + } +} + +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()) + } +} + +impl sp_std::fmt::Debug for Public { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +#[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))) + } +} + +/// 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, PassByInner)] +pub struct Signature(pub [u8; 64]); + +impl sp_std::convert::TryFrom<&[u8]> for Signature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 64 { + let mut inner = [0u8; 64]; + inner.copy_from_slice(data); + Ok(Signature(inner)) + } else { + Err(()) + } + } +} + +#[cfg(feature = "std")] +impl Serialize for Signature { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&hex::encode(self)) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Signature { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + Ok(Signature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?) + } +} + +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 = "full_crypto")] +impl From for Signature { + fn from(s: schnorrkel::Signature) -> Signature { + Signature(s.to_bytes()) + } +} + +impl sp_std::fmt::Debug for Signature { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + +#[cfg(feature = "full_crypto")] +impl sp_std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + sp_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, or if you + /// immediately verify the signature. All functions that verify signatures + /// will fail if the `Signature` is not actually a valid signature. + 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()) + } +} + +impl Derive for Public { + /// Derive a child key from a series of given junctions. + /// + /// `None` if there are any hard junctions in there. + #[cfg(feature = "std")] + 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 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 slice filled with raw data. + pub fn as_array_ref(&self) -> &[u8; 32] { + self.as_ref() + } +} + +impl TraitPublic for Public { + /// 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! + fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Public(r) + } +} + +#[cfg(feature = "std")] +impl From for Pair { + fn from(sec: MiniSecretKey) -> Pair { + Pair(sec.expand_to_keypair(ExpansionMode::Ed25519)) + } +} + +#[cfg(feature = "std")] +impl From for Pair { + fn from(sec: SecretKey) -> Pair { + Pair(Keypair::from(sec)) + } +} + +#[cfg(feature = "full_crypto")] +impl From for Pair { + fn from(p: schnorrkel::Keypair) -> Pair { + Pair(p) + } +} + +#[cfg(feature = "full_crypto")] +impl From for schnorrkel::Keypair { + fn from(p: Pair) -> schnorrkel::Keypair { + p.0 + } +} + +#[cfg(feature = "full_crypto")] +impl AsRef for Pair { + fn as_ref(&self) -> &schnorrkel::Keypair { + &self.0 + } +} + +/// Derive a single hard junction. +#[cfg(feature = "full_crypto")] +fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> MiniSecretKey { + secret.hard_derive_mini_secret_key(Some(ChainCode(cc.clone())), b"").0 +} + +/// The raw secret seed, which can be used to recreate the `Pair`. +#[cfg(feature = "full_crypto")] +type Seed = [u8; MINI_SECRET_KEY_LENGTH]; + +#[cfg(feature = "full_crypto")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = Infallible; + + /// 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 { + Self::from_seed_slice(&seed[..]) + .expect("32 bytes can always build a key; qed") + } + + /// 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 { + match seed.len() { + MINI_SECRET_KEY_LENGTH => { + Ok(Pair( + MiniSecretKey::from_bytes(seed) + .map_err(|_| SecretStringError::InvalidSeed)? + .expand_to_keypair(ExpansionMode::Ed25519) + )) + } + SECRET_KEY_LENGTH => { + Ok(Pair( + SecretKey::from_bytes(seed) + .map_err(|_| SecretStringError::InvalidSeed)? + .to_keypair() + )) + } + _ => Err(SecretStringError::InvalidSeedLength) + } + } + #[cfg(feature = "std")] + fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + let (pair, seed) = Self::from_phrase(phrase, password) + .expect("All phrases generated by Mnemonic are valid; qed"); + ( + pair, + phrase.to_owned(), + seed, + ) + } + #[cfg(feature = "std")] + fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase) + .map(|m| Self::from_entropy(m.entropy(), password)) + } + + fn derive>(&self, + path: Iter, + seed: Option, + ) -> Result<(Pair, Option), Self::DeriveError> { + let seed = if let Some(s) = seed { + if let Ok(msk) = MiniSecretKey::from_bytes(&s) { + if msk.expand(ExpansionMode::Ed25519) == self.0.secret { + Some(msk) + } else { None } + } else { None } + } else { None }; + let init = self.0.secret.clone(); + let (result, seed) = path.fold((init, seed), |(acc, acc_seed), j| match (j, acc_seed) { + (DeriveJunction::Soft(cc), _) => + (acc.derived_key_simple(ChainCode(cc), &[]).0, None), + (DeriveJunction::Hard(cc), maybe_seed) => { + let seed = derive_hard_junction(&acc, &cc); + (seed.expand(ExpansionMode::Ed25519), maybe_seed.map(|_| seed)) + } + }); + Ok((Self(result.into()), seed.map(|s| MiniSecretKey::to_bytes(&s)))) + } + + 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>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { + Self::verify_weak(&sig.0[..], message, pubkey) + } + + /// 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 { + // Match both schnorrkel 0.1.1 and 0.8.0+ signatures, supporting both wallets + // that have not been upgraded and those that have. To swap to 0.8.0 only, + // create `schnorrkel::Signature` and pass that into `verify_simple` + match PublicKey::from_bytes(pubkey.as_ref()) { + Ok(pk) => pk.verify_simple_preaudit_deprecated( + SIGNING_CTX, message.as_ref(), &sig, + ).is_ok(), + Err(_) => false, + } + } + + /// Return a vec filled with raw data. + fn to_raw_vec(&self) -> Vec { + self.0.secret.to_bytes().to_vec() + } +} + +#[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, Seed) { + 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(ExpansionMode::Ed25519); + (Pair(kp), mini_key.to_bytes()) + } +} + +impl CryptoType for Public { + #[cfg(feature = "full_crypto")] + type Pair = Pair; +} + +impl CryptoType for Signature { + #[cfg(feature = "full_crypto")] + type Pair = Pair; +} + +#[cfg(feature = "full_crypto")] +impl CryptoType for Pair { + type Pair = Pair; +} + +#[cfg(test)] +mod compatibility_test { + use super::*; + use crate::crypto::{DEV_PHRASE}; + use hex_literal::hex; + + // NOTE: tests to ensure addresses that are created with the `0.1.x` version (pre-audit) are + // still functional. + + #[test] + fn derive_soft_known_pair_should_work() { + let pair = Pair::from_string(&format!("{}/Alice", DEV_PHRASE), None).unwrap(); + // known address of DEV_PHRASE with 1.1 + let known = hex!("d6c71059dbbe9ad2b0ed3f289738b800836eb425544ce694825285b958ca755e"); + assert_eq!(pair.public().to_raw_vec(), known); + } + + #[test] + fn derive_hard_known_pair_should_work() { + let pair = Pair::from_string(&format!("{}//Alice", DEV_PHRASE), None).unwrap(); + // known address of DEV_PHRASE with 1.1 + let known = hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); + assert_eq!(pair.public().to_raw_vec(), known); + } + + #[test] + fn verify_known_message_should_work() { + let public = Public::from_raw(hex!("b4bfa1f7a5166695eb75299fd1c4c03ea212871c342f2c5dfea0902b2c246918")); + // signature generated by the 1.1 version with the same ^^ public key. + let signature = Signature::from_raw(hex!( + "5a9755f069939f45d96aaf125cf5ce7ba1db998686f87f2fb3cbdea922078741a73891ba265f70c31436e18a9acd14d189d73c12317ab6c313285cd938453202" + )); + let message = b"Verifying that I am the owner of 5G9hQLdsKQswNPgB499DeA5PkFBbgkLPJWkkS6FAM6xGQ8xD. Hash: 221455a3\n"; + assert!(Pair::verify(&signature, &message[..], &public)); + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::crypto::{Ss58Codec, DEV_PHRASE, DEV_ADDRESS}; + use hex_literal::hex; + use serde_json; + + #[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::from_seed(&hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let derive_1 = pair.derive(Some(DeriveJunction::soft(1)).into_iter(), None).unwrap().0; + let derive_1b = pair.derive(Some(DeriveJunction::soft(1)).into_iter(), None).unwrap().0; + let derive_2 = pair.derive(Some(DeriveJunction::soft(2)).into_iter(), None).unwrap().0; + assert_eq!(derive_1.public(), derive_1b.public()); + assert_ne!(derive_1.public(), derive_2.public()); + } + + #[test] + fn derive_hard_should_work() { + let pair = Pair::from_seed(&hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let derive_1 = pair.derive(Some(DeriveJunction::hard(1)).into_iter(), None).unwrap().0; + let derive_1b = pair.derive(Some(DeriveJunction::hard(1)).into_iter(), None).unwrap().0; + let derive_2 = pair.derive(Some(DeriveJunction::hard(2)).into_iter(), None).unwrap().0; + assert_eq!(derive_1.public(), derive_1b.public()); + assert_ne!(derive_1.public(), derive_2.public()); + } + + #[test] + fn derive_soft_public_should_work() { + let pair = Pair::from_seed(&hex!( + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" + )); + let path = Some(DeriveJunction::soft(1)); + let pair_1 = pair.derive(path.clone().into_iter(), None).unwrap().0; + let public_1 = pair.public().derive(path.into_iter()).unwrap(); + assert_eq!(pair_1.public(), public_1); + } + + #[test] + fn derive_hard_public_should_fail() { + let 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::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 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)); + } + + #[test] + fn signature_serialization_works() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + let serialized_signature = serde_json::to_string(&signature).unwrap(); + // Signature is 64 bytes, so 128 chars + 2 quote chars + assert_eq!(serialized_signature.len(), 130); + let signature = serde_json::from_str(&serialized_signature).unwrap(); + assert!(Pair::verify(&signature, &message[..], &pair.public())); + } + + #[test] + fn signature_serialization_doesnt_panic() { + fn deserialize_signature(text: &str) -> Result { + Ok(serde_json::from_str(text)?) + } + assert!(deserialize_signature("Not valid json.").is_err()); + assert!(deserialize_signature("\"Not an actual signature.\"").is_err()); + // Poorly-sized + assert!(deserialize_signature("\"abc123\"").is_err()); + } +} diff --git a/primitives/core/src/testing.rs b/primitives/core/src/testing.rs new file mode 100644 index 0000000000000..35286acb63f31 --- /dev/null +++ b/primitives/core/src/testing.rs @@ -0,0 +1,273 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Types that should only be used for testing! + +#[cfg(feature = "std")] +use crate::{ed25519, sr25519, crypto::{Public, Pair}}; +use crate::crypto::KeyTypeId; + +/// Key type for generic Ed25519 key. +pub const ED25519: KeyTypeId = KeyTypeId(*b"ed25"); +/// Key type for generic Sr 25519 key. +pub const SR25519: KeyTypeId = KeyTypeId(*b"sr25"); + +/// A keystore implementation usable in tests. +#[cfg(feature = "std")] +#[derive(Default)] +pub struct KeyStore { + /// `KeyTypeId` maps to public keys and public keys map to private keys. + keys: std::collections::HashMap, String>>, +} + +#[cfg(feature = "std")] +impl KeyStore { + /// Creates a new instance of `Self`. + pub fn new() -> crate::traits::BareCryptoStorePtr { + std::sync::Arc::new(parking_lot::RwLock::new(Self::default())) + } +} + +#[cfg(feature = "std")] +impl crate::traits::BareCryptoStore for KeyStore { + fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec { + self.keys.get(&id) + .map(|keys| + keys.values() + .map(|s| sr25519::Pair::from_string(s, None).expect("`sr25519` seed slice is valid")) + .map(|p| p.public()) + .collect() + ) + .unwrap_or_default() + } + + fn sr25519_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> Result { + match seed { + Some(seed) => { + let pair = sr25519::Pair::from_string(seed, None).expect("Generates an `sr25519` pair."); + self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into()); + Ok(pair.public()) + }, + None => { + let (pair, phrase, _) = sr25519::Pair::generate_with_phrase(None); + self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), phrase); + Ok(pair.public()) + } + } + } + + fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option { + self.keys.get(&id) + .and_then(|inner| + inner.get(pub_key.as_slice()) + .map(|s| sr25519::Pair::from_string(s, None).expect("`sr25519` seed slice is valid")) + ) + } + + fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec { + self.keys.get(&id) + .map(|keys| + keys.values() + .map(|s| ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid")) + .map(|p| p.public()) + .collect() + ) + .unwrap_or_default() + } + + fn ed25519_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> Result { + match seed { + Some(seed) => { + let pair = ed25519::Pair::from_string(seed, None).expect("Generates an `ed25519` pair."); + self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into()); + Ok(pair.public()) + }, + None => { + let (pair, phrase, _) = ed25519::Pair::generate_with_phrase(None); + self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), phrase); + Ok(pair.public()) + } + } + } + + fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option { + self.keys.get(&id) + .and_then(|inner| + inner.get(pub_key.as_slice()) + .map(|s| ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid")) + ) + } + + fn insert_unknown(&mut self, id: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> { + self.keys.entry(id).or_default().insert(public.to_owned(), suri.to_string()); + Ok(()) + } + + fn password(&self) -> Option<&str> { + None + } +} + +/// Macro for exporting functions from wasm in with the expected signature for using it with the +/// wasm executor. This is useful for tests where you need to call a function in wasm. +/// +/// The input parameters are expected to be SCALE encoded and will be automatically decoded for you. +/// The output value is also SCALE encoded when returned back to the host. +/// +/// The functions are feature-gated with `#[cfg(not(feature = "std"))]`, so they are only available +/// from within wasm. +/// +/// # Example +/// +/// ``` +/// # use sp_core::wasm_export_functions; +/// +/// wasm_export_functions! { +/// fn test_in_wasm(value: bool, another_value: Vec) -> bool { +/// value && another_value.is_empty() +/// } +/// +/// fn without_return_value() { +/// // do something +/// } +/// } +/// ``` +#[macro_export] +macro_rules! wasm_export_functions { + ( + $( + fn $name:ident ( + $( $arg_name:ident: $arg_ty:ty ),* $(,)? + ) $( -> $ret_ty:ty )? { $( $fn_impl:tt )* } + )* + ) => { + $( + $crate::wasm_export_functions! { + @IMPL + fn $name ( + $( $arg_name: $arg_ty ),* + ) $( -> $ret_ty )? { $( $fn_impl )* } + } + )* + }; + (@IMPL + fn $name:ident ( + $( $arg_name:ident: $arg_ty:ty ),* + ) { $( $fn_impl:tt )* } + ) => { + #[no_mangle] + #[allow(unreachable_code)] + #[cfg(not(feature = "std"))] + pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { + let input: &[u8] = if input_len == 0 { + &[0u8; 0] + } else { + unsafe { + $crate::sp_std::slice::from_raw_parts(input_data, input_len) + } + }; + + { + let ($( $arg_name ),*) : ($( $arg_ty ),*) = $crate::Decode::decode( + &mut &input[..], + ).expect("Input data is correctly encoded"); + + $( $fn_impl )* + } + + $crate::to_substrate_wasm_fn_return_value(&()) + } + }; + (@IMPL + fn $name:ident ( + $( $arg_name:ident: $arg_ty:ty ),* + ) $( -> $ret_ty:ty )? { $( $fn_impl:tt )* } + ) => { + #[no_mangle] + #[allow(unreachable_code)] + #[cfg(not(feature = "std"))] + pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { + let input: &[u8] = if input_len == 0 { + &[0u8; 0] + } else { + unsafe { + $crate::sp_std::slice::from_raw_parts(input_data, input_len) + } + }; + + let output $( : $ret_ty )? = { + let ($( $arg_name ),*) : ($( $arg_ty ),*) = $crate::Decode::decode( + &mut &input[..], + ).expect("Input data is correctly encoded"); + + $( $fn_impl )* + }; + + $crate::to_substrate_wasm_fn_return_value(&output) + } + }; +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::sr25519; + use crate::testing::{ED25519, SR25519}; + + #[test] + fn store_key_and_extract() { + let store = KeyStore::new(); + + let public = store.write() + .ed25519_generate_new(ED25519, None) + .expect("Genrates key"); + + let store_key_pair = store.read() + .ed25519_key_pair(ED25519, &public) + .expect("Key should exists in store"); + + assert_eq!(public, store_key_pair.public()); + } + + #[test] + fn store_unknown_and_extract_it() { + let store = KeyStore::new(); + + let secret_uri = "//Alice"; + let key_pair = sr25519::Pair::from_string(secret_uri, None).expect("Generates key pair"); + + store.write().insert_unknown( + SR25519, + secret_uri, + key_pair.public().as_ref(), + ).expect("Inserts unknown key"); + + let store_key_pair = store.read().sr25519_key_pair( + SR25519, + &key_pair.public(), + ).expect("Gets key pair from keystore"); + + assert_eq!(key_pair.public(), store_key_pair.public()); + } +} diff --git a/primitives/core/src/tests.rs b/primitives/core/src/tests.rs new file mode 100644 index 0000000000000..1eda2157c4106 --- /dev/null +++ b/primitives/core/src/tests.rs @@ -0,0 +1,17 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests. diff --git a/primitives/core/src/traits.rs b/primitives/core/src/traits.rs new file mode 100644 index 0000000000000..cd188e3367707 --- /dev/null +++ b/primitives/core/src/traits.rs @@ -0,0 +1,101 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Shareable Substrate traits. + +use crate::{crypto::KeyTypeId, ed25519, sr25519}; + +use std::{ + fmt::{Debug, Display}, + panic::UnwindSafe, + sync::Arc, +}; + +pub use sp_externalities::{Externalities, ExternalitiesExt}; + +/// Something that generates, stores and provides access to keys. +pub trait BareCryptoStore: Send + Sync { + /// Returns all sr25519 public keys for the given key type. + fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec; + /// Generate a new sr25519 key pair for the given key type and an optional seed. + /// + /// If the given seed is `Some(_)`, the key pair will only be stored in memory. + /// + /// Returns the public key of the generated key pair. + fn sr25519_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> Result; + /// Returns the sr25519 key pair for the given key type and public key combination. + fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option; + + /// Returns all ed25519 public keys for the given key type. + fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec; + /// Generate a new ed25519 key pair for the given key type and an optional seed. + /// + /// If the given seed is `Some(_)`, the key pair will only be stored in memory. + /// + /// Returns the public key of the generated key pair. + fn ed25519_generate_new( + &mut self, + id: KeyTypeId, + seed: Option<&str>, + ) -> Result; + + /// Returns the ed25519 key pair for the given key type and public key combination. + fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option; + + /// Insert a new key. This doesn't require any known of the crypto; but a public key must be + /// manually provided. + /// + /// Places it into the file system store. + /// + /// `Err` if there's some sort of weird filesystem error, but should generally be `Ok`. + fn insert_unknown(&mut self, _key_type: KeyTypeId, _suri: &str, _public: &[u8]) -> Result<(), ()>; + + /// Get the password for this store. + fn password(&self) -> Option<&str>; +} + +/// A pointer to the key store. +pub type BareCryptoStorePtr = Arc>; + +sp_externalities::decl_extension! { + /// The keystore extension to register/retrieve from the externalities. + pub struct KeystoreExt(BareCryptoStorePtr); +} + +/// Code execution engine. +pub trait CodeExecutor: Sized + Send + Sync { + /// Externalities error type. + type Error: Display + Debug + Send + 'static; + + /// Call a given method in the runtime. Returns a tuple of the result (either the output data + /// or an execution error) together with a `bool`, which is true if native execution was used. + fn call< + E: Externalities, + R: codec::Codec + PartialEq, + NC: FnOnce() -> Result + UnwindSafe, + >( + &self, + ext: &mut E, + method: &str, + data: &[u8], + use_native: bool, + native_call: Option, + ) -> (Result, Self::Error>, bool); +} diff --git a/core/primitives/src/u32_trait.rs b/primitives/core/src/u32_trait.rs similarity index 99% rename from core/primitives/src/u32_trait.rs rename to primitives/core/src/u32_trait.rs index d8fac34c301ab..975b4aa90990e 100644 --- a/core/primitives/src/u32_trait.rs +++ b/primitives/core/src/u32_trait.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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/primitives/core/src/uint.rs similarity index 95% rename from core/primitives/src/uint.rs rename to primitives/core/src/uint.rs index b41596a910326..54ed7ca317f00 100644 --- a/core/primitives/src/uint.rs +++ b/primitives/core/src/uint.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,7 +22,7 @@ pub use primitive_types::U256; mod tests { use super::*; use codec::{Encode, Decode}; - use substrate_serializer as ser; + use sp_serializer as ser; macro_rules! test { ($name: ident, $test_name: ident) => { @@ -91,7 +91,9 @@ mod tests { "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" ); assert!( - ser::from_str::("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data() + ser::from_str::("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"") + .unwrap_err() + .is_data() ); } } diff --git a/primitives/debug-derive/Cargo.toml b/primitives/debug-derive/Cargo.toml new file mode 100644 index 0000000000000..9c65cb34f5fa9 --- /dev/null +++ b/primitives/debug-derive/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "sp-debug-derive" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0.2" +syn = "1.0.7" +proc-macro2 = "1.0" + +[features] +std = [] + +[dev-dependencies] + diff --git a/primitives/debug-derive/src/impls.rs b/primitives/debug-derive/src/impls.rs new file mode 100644 index 0000000000000..b0e6dfa3eec4b --- /dev/null +++ b/primitives/debug-derive/src/impls.rs @@ -0,0 +1,217 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use quote::quote; +use proc_macro2::TokenStream; +use syn::{Data, DeriveInput, parse_quote}; + +pub fn debug_derive(ast: DeriveInput) -> proc_macro::TokenStream { + let name_str = ast.ident.to_string(); + let implementation = implementation::derive(&name_str, &ast.data); + let name = &ast.ident; + let mut generics = ast.generics.clone(); + let (impl_generics, ty_generics, where_clause) = { + let wh = generics.make_where_clause(); + for t in ast.generics.type_params() { + let name = &t.ident; + wh.predicates.push(parse_quote!{ #name : core::fmt::Debug }); + } + generics.split_for_impl() + }; + let gen = quote!{ + impl #impl_generics core::fmt::Debug for #name #ty_generics #where_clause { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { + #implementation + } + } + }; + + gen.into() +} + +#[cfg(not(feature = "std"))] +mod implementation { + use super::*; + + /// Derive the inner implementation of `Debug::fmt` function. + /// + /// Non-std environment. We do nothing to prevent bloating the size of runtime. + /// Implement `Printable` if you need to print the details. + pub fn derive(_name_str: &str, _data: &Data) -> TokenStream { + quote! { + fmt.write_str("") + } + } +} + +#[cfg(feature = "std")] +mod implementation { + use super::*; + use proc_macro2::Span; + use syn::{Ident, Index, token::SelfValue}; + + /// Derive the inner implementation of `Debug::fmt` function. + pub fn derive(name_str: &str, data: &Data) -> TokenStream { + match *data { + Data::Struct(ref s) => derive_struct(&name_str, &s.fields), + Data::Union(ref u) => derive_fields(&name_str, Fields::new(u.fields.named.iter(), None)), + Data::Enum(ref e) => derive_enum(&name_str, &e), + } + } + + enum Fields { + Indexed { + indices: Vec, + }, + Unnamed { + vars: Vec, + }, + Named { + names: Vec, + this: Option, + }, + } + + impl Fields { + fn new<'a>(fields: impl Iterator, this: Option) -> Self { + let mut indices = vec![]; + let mut names = vec![]; + + for (i, f) in fields.enumerate() { + if let Some(ident) = f.ident.clone() { + names.push(ident); + } else { + indices.push(Index::from(i)); + } + } + + if names.is_empty() { + Self::Indexed { + indices, + } + } else { + Self::Named { + names, + this, + } + } + } + } + + fn derive_fields<'a>( + name_str: &str, + fields: Fields, + ) -> TokenStream { + match fields { + Fields::Named { names, this } => { + let names_str: Vec<_> = names.iter() + .map(|x| x.to_string()) + .collect(); + + let fields = match this { + None => quote! { #( .field(#names_str, #names) )* }, + Some(this) => quote! { #( .field(#names_str, &#this.#names) )* }, + }; + + quote! { + fmt.debug_struct(#name_str) + #fields + .finish() + } + + }, + Fields::Indexed { indices } => { + quote! { + fmt.debug_tuple(#name_str) + #( .field(&self.#indices) )* + .finish() + } + }, + Fields::Unnamed { vars } => { + quote! { + fmt.debug_tuple(#name_str) + #( .field(#vars) )* + .finish() + } + }, + } + } + + fn derive_enum( + name: &str, + e: &syn::DataEnum, + ) -> TokenStream { + let v = e.variants + .iter() + .map(|v| { + let name = format!("{}::{}", name, v.ident); + let ident = &v.ident; + match v.fields { + syn::Fields::Named(ref f) => { + let names: Vec<_> = f.named.iter().flat_map(|f| f.ident.clone()).collect(); + let fields_impl = derive_fields(&name, Fields::Named { + names: names.clone(), + this: None, + }); + (ident, (quote!{ { #( ref #names ),* } }, fields_impl)) + }, + syn::Fields::Unnamed(ref f) => { + let names = f.unnamed.iter() + .enumerate() + .map(|(id, _)| Ident::new(&format!("a{}", id), Span::call_site())) + .collect::>(); + let fields_impl = derive_fields(&name, Fields::Unnamed { vars: names.clone() }); + (ident, (quote! { ( #( ref #names ),* ) }, fields_impl)) + }, + syn::Fields::Unit => { + let fields_impl = derive_fields(&name, Fields::Indexed { indices: vec![] }); + (ident, (quote! { }, fields_impl)) + }, + } + }); + + type Vecs = (Vec, Vec); + let (variants, others): Vecs<_, _> = v.unzip(); + let (match_fields, variants_impl): Vecs<_, _> = others.into_iter().unzip(); + + quote! { + match self { + #( Self::#variants #match_fields => #variants_impl, )* + _ => Ok(()), + } + } + } + + fn derive_struct( + name_str: &str, + fields: &syn::Fields, + ) -> TokenStream { + match *fields { + syn::Fields::Named(ref f) => derive_fields( + name_str, + Fields::new(f.named.iter(), Some(syn::Token!(self)(Span::call_site()))), + ), + syn::Fields::Unnamed(ref f) => derive_fields( + name_str, + Fields::new(f.unnamed.iter(), None), + ), + syn::Fields::Unit => derive_fields( + name_str, + Fields::Indexed { indices: vec![] }, + ), + } + } +} diff --git a/primitives/debug-derive/src/lib.rs b/primitives/debug-derive/src/lib.rs new file mode 100644 index 0000000000000..f338c2869ea49 --- /dev/null +++ b/primitives/debug-derive/src/lib.rs @@ -0,0 +1,44 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Macros to derive runtime debug implementation. +//! +//! This custom derive implements a `core::fmt::Debug` trait, +//! but in case the `std` feature is enabled the implementation +//! will actually print out the structure as regular `derive(Debug)` +//! would do. If `std` is disabled the implementation will be empty. +//! +//! This behaviour is useful to prevent bloating the runtime WASM +//! blob from unneeded code. +//! +//! ```rust +//! #[derive(sp_debug_derive::RuntimeDebug)] +//! struct MyStruct; +//! +//! assert_eq!(format!("{:?}", MyStruct), "MyStruct"); +//! ``` + +extern crate proc_macro; + +mod impls; + +use proc_macro::TokenStream; + +#[proc_macro_derive(RuntimeDebug)] +pub fn debug_derive(input: TokenStream) -> TokenStream { + impls::debug_derive(syn::parse_macro_input!(input)) +} + diff --git a/primitives/debug-derive/tests/tests.rs b/primitives/debug-derive/tests/tests.rs new file mode 100644 index 0000000000000..77b3d53a2d4ad --- /dev/null +++ b/primitives/debug-derive/tests/tests.rs @@ -0,0 +1,63 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sp_debug_derive::RuntimeDebug; + +#[derive(RuntimeDebug)] +struct Unnamed(u64, String); + +#[derive(RuntimeDebug)] +struct Named { + a: u64, + b: String, +} + +#[derive(RuntimeDebug)] +enum EnumLongName { + A, + B(A, String), + VariantLongName { + a: A, + b: String, + }, +} + + +#[test] +fn should_display_proper_debug() { + use self::EnumLongName as Enum; + + assert_eq!( + format!("{:?}", Unnamed(1, "abc".into())), + "Unnamed(1, \"abc\")" + ); + assert_eq!( + format!("{:?}", Named { a: 1, b: "abc".into() }), + "Named { a: 1, b: \"abc\" }" + ); + assert_eq!( + format!("{:?}", Enum::::A), + "EnumLongName::A" + ); + assert_eq!( + format!("{:?}", Enum::B(1, "abc".into())), + "EnumLongName::B(1, \"abc\")" + ); + assert_eq!( + format!("{:?}", Enum::VariantLongName { a: 1, b: "abc".into() }), + "EnumLongName::VariantLongName { a: 1, b: \"abc\" }" + ); +} diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml new file mode 100644 index 0000000000000..09ce3253f2d98 --- /dev/null +++ b/primitives/externalities/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "sp-externalities" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-storage = { version = "2.0.0", path = "../storage" } +sp-std = { version = "2.0.0", path = "../std" } +environmental = { version = "1.0.2" } diff --git a/core/externalities/src/extensions.rs b/primitives/externalities/src/extensions.rs similarity index 84% rename from core/externalities/src/extensions.rs rename to primitives/externalities/src/extensions.rs index c7d7bc48538ac..a61c03534fb0d 100644 --- a/core/externalities/src/extensions.rs +++ b/primitives/externalities/src/extensions.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -27,7 +27,12 @@ use std::{collections::HashMap, any::{Any, TypeId}, ops::DerefMut}; /// /// As extensions are stored as `Box`, this trait should give more confidence that the correct /// type is registered and requested. -pub trait Extension: Sized {} +pub trait Extension: Send + Any { + /// Return the extension as `&mut dyn Any`. + /// + /// This is a trick to make the trait type castable into an `Any`. + fn as_mut_any(&mut self) -> &mut dyn Any; +} /// Macro for declaring an extension that usable with [`Extensions`]. /// @@ -36,7 +41,7 @@ pub trait Extension: Sized {} /// /// # Example /// ``` -/// # use substrate_externalities::decl_extension; +/// # use sp_externalities::decl_extension; /// decl_extension! { /// /// Some test extension /// struct TestExt(String); @@ -51,7 +56,11 @@ macro_rules! decl_extension { $( #[ $attr ] )* $vis struct $ext_name (pub $inner); - impl $crate::Extension for $ext_name {} + impl $crate::Extension for $ext_name { + fn as_mut_any(&mut self) -> &mut dyn std::any::Any { + self + } + } impl std::ops::Deref for $ext_name { type Target = $inner; @@ -83,7 +92,7 @@ pub trait ExtensionStore { /// Stores extensions that should be made available through the externalities. #[derive(Default)] pub struct Extensions { - extensions: HashMap>, + extensions: HashMap>, } impl Extensions { @@ -93,13 +102,13 @@ impl Extensions { } /// Register the given extension. - pub fn register(&mut self, ext: E) { + pub fn register(&mut self, ext: E) { self.extensions.insert(ext.type_id(), Box::new(ext)); } /// Return a mutable reference to the requested extension. pub fn get_mut(&mut self, ext_type_id: TypeId) -> Option<&mut dyn Any> { - self.extensions.get_mut(&ext_type_id).map(DerefMut::deref_mut) + self.extensions.get_mut(&ext_type_id).map(DerefMut::deref_mut).map(Extension::as_mut_any) } } @@ -107,11 +116,12 @@ impl Extensions { mod tests { use super::*; - struct DummyExt(u32); - impl Extension for DummyExt {} - - struct DummyExt2(u32); - impl Extension for DummyExt2 {} + decl_extension! { + struct DummyExt(u32); + } + decl_extension! { + struct DummyExt2(u32); + } #[test] fn register_and_retrieve_extension() { diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs new file mode 100644 index 0000000000000..350b65d190840 --- /dev/null +++ b/primitives/externalities/src/lib.rs @@ -0,0 +1,217 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate externalities abstraction +//! +//! The externalities mainly provide access to storage and to registered extensions. Extensions +//! are for example the keystore or the offchain externalities. These externalities are used to +//! access the node from the runtime via the runtime interfaces. +//! +//! This crate exposes the main [`Externalities`] trait. + +use std::any::{Any, TypeId}; + +use sp_storage::{ChildStorageKey, ChildInfo}; + +pub use scope_limited::{set_and_run_with_externalities, with_externalities}; +pub use extensions::{Extension, Extensions, ExtensionStore}; + +mod extensions; +mod scope_limited; + +/// The Substrate externalities. +/// +/// Provides access to the storage and to other registered extensions. +pub trait Externalities: ExtensionStore { + /// Read runtime storage. + fn storage(&self, key: &[u8]) -> Option>; + + /// Get storage value hash. This may be optimized for large values. + fn storage_hash(&self, key: &[u8]) -> Option>; + + /// Get child storage value hash. This may be optimized for large values. + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn child_storage_hash( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option>; + + /// Read original runtime storage, ignoring any overlayed changes. + fn original_storage(&self, key: &[u8]) -> Option>; + + /// Read original runtime child storage, ignoring any overlayed changes. + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn original_child_storage( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option>; + + /// Get original storage value hash, ignoring any overlayed changes. + /// This may be optimized for large values. + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn original_storage_hash(&self, key: &[u8]) -> Option>; + + /// Get original child storage value hash, ignoring any overlayed changes. + /// This may be optimized for large values. + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn original_child_storage_hash( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option>; + + /// Read child runtime storage. + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn child_storage( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option>; + + /// Set storage entry `key` of current contract being called (effective immediately). + fn set_storage(&mut self, key: Vec, value: Vec) { + self.place_storage(key, Some(value)); + } + + /// Set child storage entry `key` of current contract being called (effective immediately). + fn set_child_storage( + &mut self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: Vec, + value: Vec, + ) { + self.place_child_storage(storage_key, child_info, key, Some(value)) + } + + /// Clear a storage entry (`key`) of current contract being called (effective immediately). + fn clear_storage(&mut self, key: &[u8]) { + self.place_storage(key.to_vec(), None); + } + + /// Clear a child storage entry (`key`) of current contract being called (effective immediately). + fn clear_child_storage( + &mut self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) { + self.place_child_storage(storage_key, child_info, key.to_vec(), None) + } + + /// Whether a storage entry exists. + fn exists_storage(&self, key: &[u8]) -> bool { + self.storage(key).is_some() + } + + /// Whether a child storage entry exists. + fn exists_child_storage( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> bool { + self.child_storage(storage_key, child_info, key).is_some() + } + + /// Returns the key immediately following the given key, if it exists. + fn next_storage_key(&self, key: &[u8]) -> Option>; + + /// Returns the key immediately following the given key, if it exists, in child storage. + fn next_child_storage_key( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option>; + + /// Clear an entire child storage. + fn kill_child_storage(&mut self, storage_key: ChildStorageKey, child_info: ChildInfo); + + /// Clear storage entries which keys are start with the given prefix. + fn clear_prefix(&mut self, prefix: &[u8]); + + /// Clear child storage entries which keys are start with the given prefix. + fn clear_child_prefix( + &mut self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + prefix: &[u8], + ); + + /// Set or clear a storage entry (`key`) of current contract being called (effective immediately). + fn place_storage(&mut self, key: Vec, value: Option>); + + /// Set or clear a child storage entry. Return whether the operation succeeds. + fn place_child_storage( + &mut self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: Vec, + value: Option>, + ); + + /// Get the identity of the chain. + fn chain_id(&self) -> u64; + + /// Get the trie root of the current storage map. This will also update all child storage keys + /// in the top-level storage map. + /// + /// The hash is defined by the `Block`. + /// + /// Returns the SCALE encoded hash. + fn storage_root(&mut self) -> Vec; + + /// Get the trie root of a child storage map. This will also update the value of the child + /// storage keys in the top-level storage map. + /// If the storage root equals the default hash as defined by the trie, the key in the top-level + /// storage map will be removed. + fn child_storage_root( + &mut self, + storage_key: ChildStorageKey, + ) -> Vec; + + /// Get the change trie root of the current storage overlay at a block with given parent. + /// `parent` is expects a SCALE endcoded hash. + /// + /// The hash is defined by the `Block`. + /// + /// Returns the SCALE encoded hash. + fn storage_changes_root(&mut self, parent: &[u8]) -> Result>, ()>; +} + +/// Extension for the [`Externalities`] trait. +pub trait ExternalitiesExt { + /// Tries to find a registered extension and returns a mutable reference. + fn extension(&mut self) -> Option<&mut T>; +} + +impl ExternalitiesExt for &mut dyn Externalities { + fn extension(&mut self) -> Option<&mut T> { + self.extension_by_type_id(TypeId::of::()).and_then(Any::downcast_mut) + } +} diff --git a/core/externalities/src/scope_limited.rs b/primitives/externalities/src/scope_limited.rs similarity index 96% rename from core/externalities/src/scope_limited.rs rename to primitives/externalities/src/scope_limited.rs index ae185449be2b0..263858aa5f5ce 100644 --- a/core/externalities/src/scope_limited.rs +++ b/primitives/externalities/src/scope_limited.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml new file mode 100644 index 0000000000000..c2856e524ff21 --- /dev/null +++ b/primitives/finality-grandpa/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "sp-finality-grandpa" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +app-crypto = { version = "2.0.0", default-features = false, package = "sp-application-crypto", path = "../application-crypto" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-api = { version = "2.0.0", default-features = false, path = "../api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } + +[features] +default = ["std"] +std = [ + "app-crypto/std", + "codec/std", + "sp-std/std", + "serde", + "sp-api/std", + "sp-runtime/std", +] diff --git a/primitives/finality-grandpa/src/lib.rs b/primitives/finality-grandpa/src/lib.rs new file mode 100644 index 0000000000000..f1481c0aed4e5 --- /dev/null +++ b/primitives/finality-grandpa/src/lib.rs @@ -0,0 +1,233 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for GRANDPA integration, suitable for WASM compilation. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate alloc; + +#[cfg(feature = "std")] +use serde::Serialize; +use codec::{Encode, Decode, Input, Codec}; +use sp_runtime::{ConsensusEngineId, RuntimeDebug}; +use sp_std::borrow::Cow; +use sp_std::vec::Vec; + +mod app { + use app_crypto::{app_crypto, key_types::GRANDPA, ed25519}; + app_crypto!(ed25519, GRANDPA); +} + +/// The grandpa crypto scheme defined via the keypair type. +#[cfg(feature = "std")] +pub type AuthorityPair = app::Pair; + +/// Identity of a Grandpa authority. +pub type AuthorityId = app::Public; + +/// Signature for a Grandpa authority. +pub type AuthoritySignature = app::Signature; + +/// The `ConsensusEngineId` of GRANDPA. +pub const GRANDPA_ENGINE_ID: ConsensusEngineId = *b"FRNK"; + +/// The storage key for the current set of weighted Grandpa authorities. +/// The value stored is an encoded VersionedAuthorityList. +pub const GRANDPA_AUTHORITIES_KEY: &'static [u8] = b":grandpa_authorities"; + +/// The weight of an authority. +pub type AuthorityWeight = u64; + +/// The index of an authority. +pub type AuthorityIndex = u64; + +/// The monotonic identifier of a GRANDPA set of authorities. +pub type SetId = u64; + +/// The round indicator. +pub type RoundNumber = u64; + +/// A list of Grandpa authorities with associated weights. +pub type AuthorityList = Vec<(AuthorityId, AuthorityWeight)>; + +/// A scheduled change of authority set. +#[cfg_attr(feature = "std", derive(Serialize))] +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] +pub struct ScheduledChange { + /// The new authorities after the change, along with their respective weights. + pub next_authorities: AuthorityList, + /// The number of blocks to delay. + pub delay: N, +} + +/// An consensus log item for GRANDPA. +#[cfg_attr(feature = "std", derive(Serialize))] +#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)] +pub enum ConsensusLog { + /// Schedule an authority set change. + /// + /// The earliest digest of this type in a single block will be respected, + /// provided that there is no `ForcedChange` digest. If there is, then the + /// `ForcedChange` will take precedence. + /// + /// No change should be scheduled if one is already and the delay has not + /// passed completely. + /// + /// 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. + #[codec(index = "1")] + ScheduledChange(ScheduledChange), + /// Force an authority set change. + /// + /// Forced changes are applied after a delay of _imported_ blocks, + /// while pending changes are applied after a delay of _finalized_ blocks. + /// + /// The earliest digest of this type in a single block will be respected, + /// with others ignored. + /// + /// No change should be scheduled if one is already and the delay has not + /// passed completely. + /// + /// 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. + #[codec(index = "2")] + ForcedChange(N, ScheduledChange), + /// Note that the authority with given index is disabled until the next change. + #[codec(index = "3")] + OnDisabled(AuthorityIndex), + /// A signal to pause the current authority set after the given delay. + /// After finalizing the block at _delay_ the authorities should stop voting. + #[codec(index = "4")] + Pause(N), + /// A signal to resume the current authority set after the given delay. + /// After authoring the block at _delay_ the authorities should resume voting. + #[codec(index = "5")] + Resume(N), +} + +impl ConsensusLog { + /// Try to cast the log entry as a contained signal. + pub fn try_into_change(self) -> Option> { + match self { + ConsensusLog::ScheduledChange(change) => Some(change), + _ => None, + } + } + + /// Try to cast the log entry as a contained forced signal. + pub fn try_into_forced_change(self) -> Option<(N, ScheduledChange)> { + match self { + ConsensusLog::ForcedChange(median, change) => Some((median, change)), + _ => None, + } + } + + /// Try to cast the log entry as a contained pause signal. + pub fn try_into_pause(self) -> Option { + match self { + ConsensusLog::Pause(delay) => Some(delay), + _ => None, + } + } + + /// Try to cast the log entry as a contained resume signal. + pub fn try_into_resume(self) -> Option { + match self { + ConsensusLog::Resume(delay) => Some(delay), + _ => None, + } + } +} + +/// WASM function call to check for pending changes. +pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change"; +/// WASM function call to get current GRANDPA authorities. +pub const AUTHORITIES_CALL: &str = "grandpa_authorities"; + +/// The current version of the stored AuthorityList type. The encoding version MUST be updated any +/// time the AuthorityList type changes. +const AUTHORITIES_VERISON: u8 = 1; + +/// An AuthorityList that is encoded with a version specifier. The encoding version is updated any +/// time the AuthorityList type changes. This ensures that encodings of different versions of an +/// AuthorityList are differentiable. Attempting to decode an authority list with an unknown +/// version will fail. +#[derive(Default)] +pub struct VersionedAuthorityList<'a>(Cow<'a, AuthorityList>); + +impl<'a> From for VersionedAuthorityList<'a> { + fn from(authorities: AuthorityList) -> Self { + VersionedAuthorityList(Cow::Owned(authorities)) + } +} + +impl<'a> From<&'a AuthorityList> for VersionedAuthorityList<'a> { + fn from(authorities: &'a AuthorityList) -> Self { + VersionedAuthorityList(Cow::Borrowed(authorities)) + } +} + +impl<'a> Into for VersionedAuthorityList<'a> { + fn into(self) -> AuthorityList { + self.0.into_owned() + } +} + +impl<'a> Encode for VersionedAuthorityList<'a> { + fn size_hint(&self) -> usize { + (AUTHORITIES_VERISON, self.0.as_ref()).size_hint() + } + + fn using_encoded R>(&self, f: F) -> R { + (AUTHORITIES_VERISON, self.0.as_ref()).using_encoded(f) + } +} + +impl<'a> Decode for VersionedAuthorityList<'a> { + fn decode(value: &mut I) -> Result { + let (version, authorities): (u8, AuthorityList) = Decode::decode(value)?; + if version != AUTHORITIES_VERISON { + return Err("unknown Grandpa authorities version".into()); + } + Ok(authorities.into()) + } +} + +sp_api::decl_runtime_apis! { + /// APIs for integrating the GRANDPA finality gadget into runtimes. + /// This should be implemented on the runtime side. + /// + /// This is primarily used for negotiating authority-set changes for the + /// gadget. GRANDPA uses a signaling model of changing authority sets: + /// changes should be signaled with a delay of N blocks, and then automatically + /// applied in the runtime after those N blocks have passed. + /// + /// The consensus protocol will coordinate the handoff externally. + #[api_version(2)] + pub trait GrandpaApi { + /// 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() -> AuthorityList; + } +} diff --git a/primitives/finality-tracker/Cargo.toml b/primitives/finality-tracker/Cargo.toml new file mode 100644 index 0000000000000..32458039458fd --- /dev/null +++ b/primitives/finality-tracker/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "sp-finality-tracker" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-std/std", + "sp-inherents/std", +] diff --git a/primitives/finality-tracker/src/lib.rs b/primitives/finality-tracker/src/lib.rs new file mode 100644 index 0000000000000..0c462c405262d --- /dev/null +++ b/primitives/finality-tracker/src/lib.rs @@ -0,0 +1,76 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! SRML module that tracks the last finalized block, as perceived by block authors. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_inherents::{InherentIdentifier, InherentData, Error}; +use codec::Decode; + +#[cfg(feature = "std")] +use codec::Encode; + +/// 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 sp_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<(), Error> { + (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")) + } +} diff --git a/primitives/inherents/Cargo.toml b/primitives/inherents/Cargo.toml new file mode 100644 index 0000000000000..0dc465e2883d1 --- /dev/null +++ b/primitives/inherents/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sp-inherents" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +parking_lot = { version = "0.9.0", optional = true } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-core = { version = "2.0.0", default-features = false, path = "../core" } +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } +derive_more = { version = "0.99.2", optional = true } + +[features] +default = [ "std" ] +std = [ + "parking_lot", + "sp-std/std", + "codec/std", + "sp-core/std", + "derive_more", +] diff --git a/primitives/inherents/src/lib.rs b/primitives/inherents/src/lib.rs new file mode 100644 index 0000000000000..f79d8357a566c --- /dev/null +++ b/primitives/inherents/src/lib.rs @@ -0,0 +1,582 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Provides types and traits for creating and checking inherents. +//! +//! Each inherent is added to a produced block. Each runtime decides on which inherents it +//! wants 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)] +#![warn(missing_docs)] + +use codec::{Encode, Decode}; + +use sp_std::{collections::btree_map::{BTreeMap, IntoIter, Entry}, vec::Vec}; + +#[cfg(feature = "std")] +use parking_lot::RwLock; + +#[cfg(feature = "std")] +use std::{sync::Arc, format}; + +/// An error that can occur within the inherent data system. +#[cfg(feature = "std")] +#[derive(Debug, Encode, Decode, derive_more::Display)] +pub struct Error(String); + +#[cfg(feature = "std")] +impl> From for Error { + fn from(data: T) -> Error { + Self(data.into()) + } +} + +#[cfg(feature = "std")] +impl Error { + /// Convert this error into a `String`. + pub fn into_string(self) -> String { + self.0 + } +} + +/// An error that can occur within the inherent data system. +#[derive(Encode, sp_core::RuntimeDebug)] +#[cfg(not(feature = "std"))] +pub struct Error(&'static str); + +#[cfg(not(feature = "std"))] +impl From<&'static str> for Error { + fn from(data: &'static str) -> Error { + Self(data) + } +} + +/// An identifier for an inherent. +pub type InherentIdentifier = [u8; 8]; + +/// Inherent data to include in a block. +#[derive(Clone, Default, Encode, Decode)] +pub struct InherentData { + /// All inherent data encoded with parity-scale-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 and 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<(), Error> { + 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, Error> { + match self.data.get(identifier) { + Some(inherent) => + I::decode(&mut &inherent[..]) + .map_err(|_| { + "Could not decode requested inherent type!".into() + }) + .map(Some), + None => Ok(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 occurs, all other errors are removed and the implementation needs to +/// abort 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<(), Error> { + // 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, Error> { + 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<(), Error> { + 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<(), Error> { + 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<(), Error>; + + /// 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<(), Error> { + *self.registered.write() = true; + Ok(()) + } + + fn inherent_identifier(&self) -> &'static InherentIdentifier { + &TEST_INHERENT_0 + } + + fn provide_inherent_data(&self, data: &mut InherentData) -> Result<(), Error> { + 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/primitives/io/Cargo.toml b/primitives/io/Cargo.toml new file mode 100644 index 0000000000000..04350c9479ede --- /dev/null +++ b/primitives/io/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "sp-io" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false } +hash-db = { version = "0.15.2", default-features = false } +sp-core = { version = "2.0.0", default-features = false, path = "../core" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +libsecp256k1 = { version = "0.3.4", optional = true } +sp-state-machine = { version = "2.0.0", optional = true, path = "../../primitives/state-machine" } +sp-runtime-interface = { version = "2.0.0", default-features = false, path = "../runtime-interface" } +sp-trie = { version = "2.0.0", optional = true, path = "../../primitives/trie" } +sp-externalities = { version = "2.0.0", optional = true, path = "../externalities" } +log = { version = "0.4.8", optional = true } + +[features] +default = ["std"] +std = [ + "sp-core/std", + "codec/std", + "sp-std/std", + "hash-db/std", + "sp-trie", + "sp-state-machine", + "libsecp256k1", + "sp-runtime-interface/std", + "sp-externalities", + "log", +] + +# These two features are used for `no_std` builds for the environments which already provides +# `#[panic_handler]`, `#[alloc_error_handler]` and `#[global_allocator]`. +# +# For the regular wasm runtime builds those are not used. +disable_panic_handler = [] +disable_oom = [] +disable_allocator = [] diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs new file mode 100644 index 0000000000000..7ac2ae1012272 --- /dev/null +++ b/primitives/io/src/lib.rs @@ -0,0 +1,969 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This is part of the Substrate runtime. + +#![warn(missing_docs)] + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] +#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] + +#![cfg_attr(feature = "std", + doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] +#![cfg_attr(not(feature = "std"), + doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] + +use sp_std::vec::Vec; + +#[cfg(feature = "std")] +use sp_std::ops::Deref; + +#[cfg(feature = "std")] +use sp_core::{ + crypto::Pair, + traits::KeystoreExt, + offchain::{OffchainExt, TransactionPoolExt}, + hexdisplay::HexDisplay, + storage::{ChildStorageKey, ChildInfo}, +}; + +use sp_core::{ + crypto::KeyTypeId, ed25519, sr25519, H256, LogLevel, + offchain::{ + Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, + }, +}; + +#[cfg(feature = "std")] +use ::sp_trie::{TrieConfiguration, trie_types::Layout}; + +use sp_runtime_interface::{runtime_interface, Pointer}; + +use codec::{Encode, Decode}; + +#[cfg(feature = "std")] +use sp_externalities::{ExternalitiesExt, Externalities}; + +/// Error verifying ECDSA signature +#[derive(Encode, Decode)] +pub enum EcdsaVerifyError { + /// Incorrect value of R or S + BadRS, + /// Incorrect value of V + BadV, + /// Invalid signature + BadSignature, +} + +/// Returns a `ChildStorageKey` if the given `storage_key` slice is a valid storage +/// key or panics otherwise. +/// +/// Panicking here is aligned with what the `without_std` environment would do +/// in the case of an invalid child storage key. +#[cfg(feature = "std")] +fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { + match ChildStorageKey::from_slice(storage_key) { + Some(storage_key) => storage_key, + None => panic!("child storage key is invalid"), + } +} + +/// Interface for accessing the storage from within the runtime. +#[runtime_interface] +pub trait Storage { + /// Returns the data for `key` in the storage or `None` if the key can not be found. + fn get(&self, key: &[u8]) -> Option> { + self.storage(key).map(|s| s.to_vec()) + } + + /// All Child api uses : + /// - A `child_storage_key` to define the anchor point for the child proof + /// (commonly the location where the child root is stored in its parent trie). + /// - A `child_storage_types` to identify the kind of the child type and how its + /// `child definition` parameter is encoded. + /// - A `child_definition_parameter` which is the additional information required + /// to use the child trie. For instance defaults child tries requires this to + /// contain a collision free unique id. + /// + /// This function specifically returns the data for `key` in the child storage or `None` + /// if the key can not be found. + fn child_get( + &self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + ) -> Option> { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.child_storage(storage_key, child_info, key).map(|s| s.to_vec()) + } + + /// Get `key` from storage, placing the value into `value_out` and return the number of + /// bytes that the entry in storage has beyond the offset or `None` if the storage entry + /// doesn't exist at all. + /// If `value_out` length is smaller than the returned length, only `value_out` length bytes + /// are copied into `value_out`. + fn read(&self, key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option { + self.storage(key).map(|value| { + let value_offset = value_offset as usize; + let data = &value[value_offset.min(value.len())..]; + let written = std::cmp::min(data.len(), value_out.len()); + value_out[..written].copy_from_slice(&data[..written]); + value.len() as u32 + }) + } + + /// Get `key` from child storage, placing the value into `value_out` and return the number + /// of bytes that the entry in storage has beyond the offset or `None` if the storage entry + /// doesn't exist at all. + /// If `value_out` length is smaller than the returned length, only `value_out` length bytes + /// are copied into `value_out`. + /// + /// See `child_get` for common child api parameters. + fn child_read( + &self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + value_out: &mut [u8], + value_offset: u32, + ) -> Option { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.child_storage(storage_key, child_info, key) + .map(|value| { + let value_offset = value_offset as usize; + let data = &value[value_offset.min(value.len())..]; + let written = std::cmp::min(data.len(), value_out.len()); + value_out[..written].copy_from_slice(&data[..written]); + value.len() as u32 + }) + } + + /// Set `key` to `value` in the storage. + fn set(&mut self, key: &[u8], value: &[u8]) { + self.set_storage(key.to_vec(), value.to_vec()); + } + + /// Set `key` to `value` in the child storage denoted by `child_storage_key`. + /// + /// See `child_get` for common child api parameters. + fn child_set( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + value: &[u8], + ) { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.set_child_storage(storage_key, child_info, key.to_vec(), value.to_vec()); + } + + /// Clear the storage of the given `key` and its value. + fn clear(&mut self, key: &[u8]) { + self.clear_storage(key) + } + + /// Clear the given child storage of the given `key` and its value. + /// + /// See `child_get` for common child api parameters. + fn child_clear( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + ) { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.clear_child_storage(storage_key, child_info, key); + } + + /// Clear an entire child storage. + /// + /// See `child_get` for common child api parameters. + fn child_storage_kill( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + ) { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.kill_child_storage(storage_key, child_info); + } + + /// Check whether the given `key` exists in storage. + fn exists(&self, key: &[u8]) -> bool { + self.exists_storage(key) + } + + /// Check whether the given `key` exists in storage. + /// + /// See `child_get` for common child api parameters. + fn child_exists( + &self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + ) -> bool { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.exists_child_storage(storage_key, child_info, key) + } + + /// Clear the storage of each key-value pair where the key starts with the given `prefix`. + fn clear_prefix(&mut self, prefix: &[u8]) { + Externalities::clear_prefix(*self, prefix) + } + + /// Clear the child storage of each key-value pair where the key starts with the given `prefix`. + /// + /// See `child_get` for common child api parameters. + fn child_clear_prefix( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + prefix: &[u8], + ) { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.clear_child_prefix(storage_key, child_info, prefix); + } + + /// "Commit" all existing operations and compute the resulting storage root. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns the SCALE encoded hash. + fn root(&mut self) -> Vec { + self.storage_root() + } + + /// "Commit" all existing operations and compute the resulting child storage root. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns the SCALE encoded hash. + /// + /// See `child_get` for common child api parameters. + fn child_root( + &mut self, + child_storage_key: &[u8], + ) -> Vec { + let storage_key = child_storage_key_or_panic(child_storage_key); + self.child_storage_root(storage_key) + } + + /// "Commit" all existing operations and get the resulting storage change root. + /// `parent_hash` is a SCALE encoded hash. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn changes_root(&mut self, parent_hash: &[u8]) -> Option> { + self.storage_changes_root(parent_hash) + .expect("Invalid `parent_hash` given to `changes_root`.") + } + + /// Get the next key in storage after the given one in lexicographic order. + fn next_key(&mut self, key: &[u8]) -> Option> { + self.next_storage_key(&key) + } + + /// Get the next key in storage after the given one in lexicographic order in child storage. + fn child_next_key( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + ) -> Option> { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.next_child_storage_key(storage_key, child_info, key) + } +} + +/// Interface that provides trie related functionality. +#[runtime_interface] +pub trait Trie { + /// A trie root formed from the iterated items. + fn blake2_256_root(input: Vec<(Vec, Vec)>) -> H256 { + Layout::::trie_root(input) + } + + /// A trie root formed from the enumerated items. + fn blake2_256_ordered_root(input: Vec>) -> H256 { + Layout::::ordered_trie_root(input) + } +} + +/// Interface that provides miscellaneous functions for communicating between the runtime and the node. +#[runtime_interface] +pub trait Misc { + /// The current relay chain identifier. + fn chain_id(&self) -> u64 { + sp_externalities::Externalities::chain_id(*self) + } + + /// Print a number. + fn print_num(val: u64) { + log::debug!(target: "runtime", "{}", val); + } + + /// Print any valid `utf8` buffer. + fn print_utf8(utf8: &[u8]) { + if let Ok(data) = std::str::from_utf8(utf8) { + log::debug!(target: "runtime", "{}", data) + } + } + + /// Print any `u8` slice as hex. + fn print_hex(data: &[u8]) { + log::debug!(target: "runtime", "{}", HexDisplay::from(&data)); + } +} + +/// Interfaces for working with crypto related types from within the runtime. +#[runtime_interface] +pub trait Crypto { + /// Returns all `ed25519` public keys for the given key id from the keystore. + fn ed25519_public_keys(&mut self, id: KeyTypeId) -> Vec { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .ed25519_public_keys(id) + } + + /// Generate an `ed22519` key for the given key type using an optional `seed` and + /// store it in the keystore. + /// + /// The `seed` needs to be a valid utf8. + /// + /// Returns the public key. + fn ed25519_generate(&mut self, id: KeyTypeId, seed: Option>) -> ed25519::Public { + let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!")); + self.extension::() + .expect("No `keystore` associated for the current context!") + .write() + .ed25519_generate_new(id, seed) + .expect("`ed25519_generate` failed") + } + + /// Sign the given `msg` with the `ed25519` key that corresponds to the given public key and + /// key type in the keystore. + /// + /// Returns the signature. + fn ed25519_sign( + &mut self, + id: KeyTypeId, + pub_key: &ed25519::Public, + msg: &[u8], + ) -> Option { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .ed25519_key_pair(id, &pub_key) + .map(|k| k.sign(msg)) + } + + /// Verify an `ed25519` signature. + /// + /// Returns `true` when the verification in successful. + fn ed25519_verify( + &self, + sig: &ed25519::Signature, + msg: &[u8], + pub_key: &ed25519::Public, + ) -> bool { + ed25519::Pair::verify(sig, msg, pub_key) + } + + /// Returns all `sr25519` public keys for the given key id from the keystore. + fn sr25519_public_keys(&mut self, id: KeyTypeId) -> Vec { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .sr25519_public_keys(id) + } + + /// Generate an `sr22519` key for the given key type using an optional seed and + /// store it in the keystore. + /// + /// The `seed` needs to be a valid utf8. + /// + /// Returns the public key. + fn sr25519_generate(&mut self, id: KeyTypeId, seed: Option>) -> sr25519::Public { + let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!")); + self.extension::() + .expect("No `keystore` associated for the current context!") + .write() + .sr25519_generate_new(id, seed) + .expect("`sr25519_generate` failed") + } + + /// Sign the given `msg` with the `sr25519` key that corresponds to the given public key and + /// key type in the keystore. + /// + /// Returns the signature. + fn sr25519_sign( + &mut self, + id: KeyTypeId, + pub_key: &sr25519::Public, + msg: &[u8], + ) -> Option { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .sr25519_key_pair(id, &pub_key) + .map(|k| k.sign(msg)) + } + + /// Verify an `sr25519` signature. + /// + /// Returns `true` when the verification in successful. + fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool { + sr25519::Pair::verify(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). + 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) + } + + /// Verify and recover a SECP256k1 ECDSA signature. + /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. + /// - returns `Err` if the signature is bad, otherwise the 33-byte compressed pubkey. + fn secp256k1_ecdsa_recover_compressed( + sig: &[u8; 65], + msg: &[u8; 32], + ) -> Result<[u8; 33], EcdsaVerifyError> { + let rs = secp256k1::Signature::parse_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) + .map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + Ok(pubkey.serialize_compressed()) + } +} + +/// Interface that provides functions for hashing with different algorithms. +#[runtime_interface] +pub trait Hashing { + /// Conduct a 256-bit Keccak hash. + fn keccak_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::keccak_256(data) + } + + /// Conduct a 256-bit Sha2 hash. + fn sha2_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::sha2_256(data) + } + + /// Conduct a 128-bit Blake2 hash. + fn blake2_128(data: &[u8]) -> [u8; 16] { + sp_core::hashing::blake2_128(data) + } + + /// Conduct a 256-bit Blake2 hash. + fn blake2_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::blake2_256(data) + } + + /// Conduct four XX hashes to give a 256-bit result. + fn twox_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::twox_256(data) + } + + /// Conduct two XX hashes to give a 128-bit result. + fn twox_128(data: &[u8]) -> [u8; 16] { + sp_core::hashing::twox_128(data) + } + + /// Conduct two XX hashes to give a 64-bit result. + fn twox_64(data: &[u8]) -> [u8; 8] { + sp_core::hashing::twox_64(data) + } +} + +/// Interface that provides functions to access the offchain functionality. +#[runtime_interface] +pub trait Offchain { + /// Returns if the local node is a potential validator. + /// + /// Even if this function returns `true`, it does not mean that any keys are configured + /// and that the validator is registered in the chain. + fn is_validator(&mut self) -> bool { + self.extension::() + .expect("is_validator can be called only in the offchain worker context") + .is_validator() + } + + /// Submit an encoded transaction to the pool. + /// + /// The transaction will end up in the pool. + fn submit_transaction(&mut self, data: Vec) -> Result<(), ()> { + self.extension::() + .expect("submit_transaction can be called only in the offchain call context with + TransactionPool capabilities enabled") + .submit_transaction(data) + } + + /// Returns information about the local node's network state. + fn network_state(&mut self) -> Result { + self.extension::() + .expect("network_state can be called only in the offchain worker context") + .network_state() + } + + /// Returns current UNIX timestamp (in millis) + fn timestamp(&mut self) -> Timestamp { + self.extension::() + .expect("timestamp can be called only in the offchain worker context") + .timestamp() + } + + /// Pause the execution until `deadline` is reached. + fn sleep_until(&mut self, deadline: Timestamp) { + self.extension::() + .expect("sleep_until can be called only in the offchain worker context") + .sleep_until(deadline) + } + + /// Returns a random seed. + /// + /// This is a trully random non deterministic seed generated by host environment. + /// Obviously fine in the off-chain worker context. + fn random_seed(&mut self) -> [u8; 32] { + self.extension::() + .expect("random_seed can be called only in the offchain worker context") + .random_seed() + } + + /// Sets a value in the local storage. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { + self.extension::() + .expect("local_storage_set can be called only in the offchain worker context") + .local_storage_set(kind, key, value) + } + + /// Sets a value in the local storage if it matches current value. + /// + /// Since multiple offchain workers may be running concurrently, to prevent + /// data races use CAS to coordinate between them. + /// + /// Returns `true` if the value has been set, `false` otherwise. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_compare_and_set( + &mut self, + kind: StorageKind, + key: &[u8], + old_value: Option>, + new_value: &[u8], + ) -> bool { + self.extension::() + .expect("local_storage_compare_and_set can be called only in the offchain worker context") + .local_storage_compare_and_set(kind, key, old_value.as_ref().map(|v| v.deref()), new_value) + } + + /// Gets a value from the local storage. + /// + /// If the value does not exist in the storage `None` will be returned. + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { + self.extension::() + .expect("local_storage_get can be called only in the offchain worker context") + .local_storage_get(kind, key) + } + + /// Initiates a http request given HTTP verb and the URL. + /// + /// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters. + /// Returns the id of newly started request. + fn http_request_start( + &mut self, + method: &str, + uri: &str, + meta: &[u8], + ) -> Result { + self.extension::() + .expect("http_request_start can be called only in the offchain worker context") + .http_request_start(method, uri, meta) + } + + /// Append header to the request. + fn http_request_add_header( + &mut self, + request_id: HttpRequestId, + name: &str, + value: &str, + ) -> Result<(), ()> { + self.extension::() + .expect("http_request_add_header can be called only in the offchain worker context") + .http_request_add_header(request_id, name, value) + } + + /// Write a chunk of request body. + /// + /// Writing an empty chunks finalizes the request. + /// Passing `None` as deadline blocks forever. + /// + /// Returns an error in case deadline is reached or the chunk couldn't be written. + fn http_request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option, + ) -> Result<(), HttpError> { + self.extension::() + .expect("http_request_write_body can be called only in the offchain worker context") + .http_request_write_body(request_id, chunk, deadline) + } + + /// Block and wait for the responses for given requests. + /// + /// Returns a vector of request statuses (the len is the same as ids). + /// Note that if deadline is not provided the method will block indefinitely, + /// otherwise unready responses will produce `DeadlineReached` status. + /// + /// Passing `None` as deadline blocks forever. + fn http_response_wait( + &mut self, + ids: &[HttpRequestId], + deadline: Option, + ) -> Vec { + self.extension::() + .expect("http_response_wait can be called only in the offchain worker context") + .http_response_wait(ids, deadline) + } + + /// Read all response headers. + /// + /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. + /// NOTE response headers have to be read before response body. + fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { + self.extension::() + .expect("http_response_headers can be called only in the offchain worker context") + .http_response_headers(request_id) + } + + /// Read a chunk of body response to given buffer. + /// + /// Returns the number of bytes written or an error in case a deadline + /// is reached or server closed the connection. + /// If `0` is returned it means that the response has been fully consumed + /// and the `request_id` is now invalid. + /// NOTE this implies that response headers must be read before draining the body. + /// Passing `None` as a deadline blocks forever. + fn http_response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option, + ) -> Result { + self.extension::() + .expect("http_response_read_body can be called only in the offchain worker context") + .http_response_read_body(request_id, buffer, deadline) + .map(|r| r as u32) + } +} + +/// Wasm only interface that provides functions for calling into the allocator. +#[runtime_interface(wasm_only)] +trait Allocator { + /// Malloc the given number of bytes and return the pointer to the allocated memory location. + fn malloc(&mut self, size: u32) -> Pointer { + self.allocate_memory(size).expect("Failed to allocate memory") + } + + /// Free the given pointer. + fn free(&mut self, ptr: Pointer) { + self.deallocate_memory(ptr).expect("Failed to deallocate memory") + } +} + +/// Interface that provides functions for logging from within the runtime. +#[runtime_interface] +pub trait Logging { + /// Request to print a log message on the host. + /// + /// Note that this will be only displayed if the host is enabled to display log messages with + /// given level and target. + /// + /// Instead of using directly, prefer setting up `RuntimeLogger` and using `log` macros. + fn log(level: LogLevel, target: &str, message: &[u8]) { + if let Ok(message) = std::str::from_utf8(message) { + log::log!( + target: target, + log::Level::from(level), + "{}", + message, + ) + } + } +} + +/// Wasm-only interface that provides functions for interacting with the sandbox. +#[runtime_interface(wasm_only)] +pub trait Sandbox { + /// Instantiate a new sandbox instance with the given `wasm_code`. + fn instantiate( + &mut self, + dispatch_thunk: u32, + wasm_code: &[u8], + env_def: &[u8], + state_ptr: Pointer, + ) -> u32 { + self.sandbox() + .instance_new(dispatch_thunk, wasm_code, env_def, state_ptr.into()) + .expect("Failed to instantiate a new sandbox") + } + + /// Invoke `function` in the sandbox with `sandbox_idx`. + fn invoke( + &mut self, + instance_idx: u32, + function: &str, + args: &[u8], + return_val_ptr: Pointer, + return_val_len: u32, + state_ptr: Pointer, + ) -> u32 { + self.sandbox().invoke( + instance_idx, + &function, + &args, + return_val_ptr, + return_val_len, + state_ptr.into(), + ).expect("Failed to invoke function with sandbox") + } + + /// Create a new memory instance with the given `initial` and `maximum` size. + fn memory_new(&mut self, initial: u32, maximum: u32) -> u32 { + self.sandbox() + .memory_new(initial, maximum) + .expect("Failed to create new memory with sandbox") + } + + /// Get the memory starting at `offset` from the instance with `memory_idx` into the buffer. + fn memory_get( + &mut self, + memory_idx: u32, + offset: u32, + buf_ptr: Pointer, + buf_len: u32, + ) -> u32 { + self.sandbox() + .memory_get(memory_idx, offset, buf_ptr, buf_len) + .expect("Failed to get memory with sandbox") + } + + /// Set the memory in the given `memory_idx` to the given value at `offset`. + fn memory_set( + &mut self, + memory_idx: u32, + offset: u32, + val_ptr: Pointer, + val_len: u32, + ) -> u32 { + self.sandbox() + .memory_set(memory_idx, offset, val_ptr, val_len) + .expect("Failed to set memory with sandbox") + } + + /// Teardown the memory instance with the given `memory_idx`. + fn memory_teardown(&mut self, memory_idx: u32) { + self.sandbox().memory_teardown(memory_idx).expect("Failed to teardown memory with sandbox") + } + + /// Teardown the sandbox instance with the given `instance_idx`. + fn instance_teardown(&mut self, instance_idx: u32) { + self.sandbox().instance_teardown(instance_idx).expect("Failed to teardown sandbox instance") + } +} + +/// Allocator used by Substrate when executing the Wasm runtime. +#[cfg(not(feature = "std"))] +struct WasmAllocator; + +#[cfg(all(not(feature = "disable_allocator"), not(feature = "std")))] +#[global_allocator] +static ALLOCATOR: WasmAllocator = WasmAllocator; + +#[cfg(not(feature = "std"))] +mod allocator_impl { + use super::*; + use core::alloc::{GlobalAlloc, Layout}; + + unsafe impl GlobalAlloc for WasmAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + allocator::malloc(layout.size() as u32) + } + + unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { + allocator::free(ptr) + } + } +} + +/// A default panic handler for WASM environment. +#[cfg(all(not(feature = "disable_panic_handler"), not(feature = "std")))] +#[panic_handler] +#[no_mangle] +pub fn panic(info: &core::panic::PanicInfo) -> ! { + unsafe { + let message = sp_std::alloc::format!("{}", info); + logging::log(LogLevel::Error, "runtime", message.as_bytes()); + core::intrinsics::abort() + } +} + +/// A default OOM handler for WASM environment. +#[cfg(all(not(feature = "disable_oom"), not(feature = "std")))] +#[alloc_error_handler] +pub fn oom(_: core::alloc::Layout) -> ! { + unsafe { + logging::log(LogLevel::Error, "runtime", b"Runtime memory exhausted. Aborting"); + core::intrinsics::abort(); + } +} + +/// Type alias for Externalities implementation used in tests. +#[cfg(feature = "std")] +pub type TestExternalities = sp_state_machine::TestExternalities; + +/// The host functions Substrate provides for the Wasm runtime environment. +/// +/// All these host functions will be callable from inside the Wasm environment. +#[cfg(feature = "std")] +pub type SubstrateHostFunctions = ( + storage::HostFunctions, + misc::HostFunctions, + offchain::HostFunctions, + crypto::HostFunctions, + hashing::HostFunctions, + allocator::HostFunctions, + logging::HostFunctions, + sandbox::HostFunctions, + crate::trie::HostFunctions, +); + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::map; + use sp_state_machine::BasicExternalities; + use sp_core::storage::Storage; + + #[test] + fn storage_works() { + let mut t = BasicExternalities::default(); + t.execute_with(|| { + assert_eq!(storage::get(b"hello"), None); + storage::set(b"hello", b"world"); + assert_eq!(storage::get(b"hello"), Some(b"world".to_vec())); + assert_eq!(storage::get(b"foo"), None); + storage::set(b"foo", &[1, 2, 3][..]); + }); + + t = BasicExternalities::new(Storage { + top: map![b"foo".to_vec() => b"bar".to_vec()], + children: map![], + }); + + t.execute_with(|| { + assert_eq!(storage::get(b"hello"), None); + assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec())); + }); + } + + #[test] + fn read_storage_works() { + let mut t = BasicExternalities::new(Storage { + top: map![b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec()], + children: map![], + }); + + t.execute_with(|| { + let mut v = [0u8; 4]; + assert!(storage::read(b":test", &mut v[..], 0).unwrap() >= 4); + assert_eq!(v, [11u8, 0, 0, 0]); + let mut w = [0u8; 11]; + assert!(storage::read(b":test", &mut w[..], 4).unwrap() >= 11); + assert_eq!(&w, b"Hello world"); + }); + } + + #[test] + fn clear_prefix_works() { + let mut t = BasicExternalities::new(Storage { + top: 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(), + b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec() + ], + children: map![], + }); + + t.execute_with(|| { + storage::clear_prefix(b":abc"); + + assert!(storage::get(b":a").is_some()); + assert!(storage::get(b":abdd").is_some()); + assert!(storage::get(b":abcd").is_none()); + assert!(storage::get(b":abc").is_none()); + }); + } +} diff --git a/primitives/keyring/Cargo.toml b/primitives/keyring/Cargo.toml new file mode 100644 index 0000000000000..61ebf89ad2464 --- /dev/null +++ b/primitives/keyring/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "sp-keyring" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-core = { version = "2.0.0", path = "../core" } +sp-runtime = { version = "2.0.0", path = "../runtime" } +lazy_static = "1.4.0" +strum = { version = "0.16.0", features = ["derive"] } diff --git a/primitives/keyring/src/ed25519.rs b/primitives/keyring/src/ed25519.rs new file mode 100644 index 0000000000000..197b9ded8794b --- /dev/null +++ b/primitives/keyring/src/ed25519.rs @@ -0,0 +1,209 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Support code for the runtime. A set of test accounts. + +use std::{collections::HashMap, ops::Deref}; +use lazy_static::lazy_static; +use sp_core::{ed25519::{Pair, Public, Signature}, Pair as PairT, Public as PublicT, H256}; +pub use sp_core::ed25519; +use sp_runtime::AccountId32; + +/// Set of test accounts. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter)] +pub enum Keyring { + Alice, + Bob, + Charlie, + Dave, + Eve, + Ferdie, + One, + Two, +} + +impl Keyring { + pub fn from_public(who: &Public) -> Option { + Self::iter().find(|&k| &Public::from(k) == who) + } + + pub fn from_account_id(who: &AccountId32) -> Option { + Self::iter().find(|&k| &k.to_account_id() == who) + } + + pub fn from_raw_public(who: [u8; 32]) -> Option { + Self::from_public(&Public::from_raw(who)) + } + + 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 to_account_id(self) -> AccountId32 { + self.to_raw_public().into() + } + + 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") + } + + /// Returns an iterator over all test accounts. + pub fn iter() -> impl Iterator { + ::iter() + } + + pub fn public(self) -> Public { + self.pair().public() + } + + pub fn to_seed(self) -> String { + format!("//{}", self) + } +} + +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", + } + } +} + +impl From for sp_runtime::MultiSigner { + fn from(x: Keyring) -> Self { + sp_runtime::MultiSigner::Ed25519(x.into()) + } +} + +lazy_static! { + static ref PRIVATE_KEYS: HashMap = { + Keyring::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 AccountId32 { + fn from(k: Keyring) -> Self { + k.to_account_id() + } +} + +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 sp_core::{ed25519::Pair, Pair as PairT}; + + #[test] + fn should_work() { + assert!( + Pair::verify( + &Keyring::Alice.sign(b"I am Alice!"), + b"I am Alice!", + &Keyring::Alice.public(), + ) + ); + assert!( + !Pair::verify( + &Keyring::Alice.sign(b"I am Alice!"), + b"I am Bob!", + &Keyring::Alice.public(), + ) + ); + assert!( + !Pair::verify( + &Keyring::Alice.sign(b"I am Alice!"), + b"I am Alice!", + &Keyring::Bob.public(), + ) + ); + } +} diff --git a/primitives/keyring/src/lib.rs b/primitives/keyring/src/lib.rs new file mode 100644 index 0000000000000..18f8cdf2c4ab9 --- /dev/null +++ b/primitives/keyring/src/lib.rs @@ -0,0 +1,36 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Support code for the runtime. A set of test accounts. + +/// Test account crypto for sr25519. +pub mod sr25519; + +/// Test account crypto for ed25519. +pub mod ed25519; + +/// Convenience export: Sr25519's Keyring is exposed as `AccountKeyring`, +/// since it tends to be used for accounts (although it may also be used +/// by authorities). +pub use sr25519::Keyring as AccountKeyring; + +pub use ed25519::Keyring as Ed25519Keyring; +pub use sr25519::Keyring as Sr25519Keyring; + +pub mod test { + /// The keyring for use with accounts when using the test runtime. + pub use super::ed25519::Keyring as AccountKeyring; +} diff --git a/primitives/keyring/src/sr25519.rs b/primitives/keyring/src/sr25519.rs new file mode 100644 index 0000000000000..27627a0c50d7e --- /dev/null +++ b/primitives/keyring/src/sr25519.rs @@ -0,0 +1,210 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Support code for the runtime. A set of test accounts. + +use std::collections::HashMap; +use std::ops::Deref; +use lazy_static::lazy_static; +use sp_core::{sr25519::{Pair, Public, Signature}, Pair as PairT, Public as PublicT, H256}; +pub use sp_core::sr25519; +use sp_runtime::AccountId32; + +/// Set of test accounts. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, strum::EnumIter)] +pub enum Keyring { + Alice, + Bob, + Charlie, + Dave, + Eve, + Ferdie, + One, + Two, +} + +impl Keyring { + pub fn from_public(who: &Public) -> Option { + Self::iter().find(|&k| &Public::from(k) == who) + } + + pub fn from_account_id(who: &AccountId32) -> Option { + Self::iter().find(|&k| &k.to_account_id() == who) + } + + pub fn from_raw_public(who: [u8; 32]) -> Option { + Self::from_public(&Public::from_raw(who)) + } + + 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 to_account_id(self) -> AccountId32 { + self.to_raw_public().into() + } + + 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") + } + + /// Returns an iterator over all test accounts. + pub fn iter() -> impl Iterator { + ::iter() + } + + pub fn public(self) -> Public { + self.pair().public() + } + + pub fn to_seed(self) -> String { + format!("//{}", self) + } +} + +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", + } + } +} + +impl From for sp_runtime::MultiSigner { + fn from(x: Keyring) -> Self { + sp_runtime::MultiSigner::Sr25519(x.into()) + } +} + +lazy_static! { + static ref PRIVATE_KEYS: HashMap = { + Keyring::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 AccountId32 { + fn from(k: Keyring) -> Self { + k.to_account_id() + } +} + +impl From for Public { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().clone() + } +} + +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 sp_core::{sr25519::Pair, Pair as PairT}; + + #[test] + fn should_work() { + assert!( + Pair::verify( + &Keyring::Alice.sign(b"I am Alice!"), + b"I am Alice!", + &Keyring::Alice.public(), + ) + ); + assert!( + !Pair::verify( + &Keyring::Alice.sign(b"I am Alice!"), + b"I am Bob!", + &Keyring::Alice.public(), + ) + ); + assert!( + !Pair::verify( + &Keyring::Alice.sign(b"I am Alice!"), + b"I am Alice!", + &Keyring::Bob.public(), + ) + ); + } +} diff --git a/primitives/offchain/Cargo.toml b/primitives/offchain/Cargo.toml new file mode 100644 index 0000000000000..ef6d0a6d2c7ee --- /dev/null +++ b/primitives/offchain/Cargo.toml @@ -0,0 +1,18 @@ +[package] +description = "Substrate offchain workers primitives" +name = "sp-offchain" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-api = { version = "2.0.0", default-features = false, path = "../api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } + +[features] +default = ["std"] +std = [ + "sp-api/std", + "sp-runtime/std" +] diff --git a/primitives/offchain/src/lib.rs b/primitives/offchain/src/lib.rs new file mode 100644 index 0000000000000..1dd20db0dd846 --- /dev/null +++ b/primitives/offchain/src/lib.rs @@ -0,0 +1,40 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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 Offchain Worker runtime api primitives. + +#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] + +use sp_runtime::traits::NumberFor; + +/// Local Storage Prefix used by the Offchain Worker API to +pub const STORAGE_PREFIX: &[u8] = b"storage"; + +sp_api::decl_runtime_apis! { + /// The offchain worker api. + #[api_version(2)] + pub trait OffchainWorkerApi { + /// Starts the off-chain task for given block number. + #[skip_initialize_block] + #[changed_in(2)] + fn offchain_worker(number: NumberFor); + + /// Starts the off-chain task for given block header. + #[skip_initialize_block] + fn offchain_worker(header: &Block::Header); + } +} diff --git a/primitives/panic-handler/Cargo.toml b/primitives/panic-handler/Cargo.toml new file mode 100644 index 0000000000000..19e34352cf806 --- /dev/null +++ b/primitives/panic-handler/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "sp-panic-handler" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Substrate panic handler." +edition = "2018" + +[dependencies] +backtrace = "0.3.38" +log = "0.4.8" diff --git a/primitives/panic-handler/src/lib.rs b/primitives/panic-handler/src/lib.rs new file mode 100644 index 0000000000000..c0f70d9d145c8 --- /dev/null +++ b/primitives/panic-handler/src/lib.rs @@ -0,0 +1,191 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Custom panic hook with bug report link +//! +//! This crate provides the [`set`] function, which wraps around [`std::panic::set_hook`] and +//! sets up a panic hook that prints a backtrace and invites the user to open an issue to the +//! given URL. +//! +//! By default, the panic handler aborts the process by calling [`std::process::exit`]. This can +//! temporarily be disabled by using an [`AbortGuard`]. + +use backtrace::Backtrace; +use std::io::{self, Write}; +use std::marker::PhantomData; +use std::panic::{self, PanicInfo}; +use std::cell::Cell; +use std::thread; + +thread_local! { + static ON_PANIC: Cell = Cell::new(OnPanic::Abort); +} + +/// Panic action. +#[derive(Debug, Clone, Copy, PartialEq)] +enum OnPanic { + /// Abort when panic occurs. + Abort, + /// Unwind when panic occurs. + Unwind, + /// Always unwind even if someone changes strategy to Abort afterwards. + NeverAbort, +} + +/// Set the panic hook. +/// +/// Calls [`std::panic::set_hook`] to set up the panic hook. +/// +/// The `bug_url` parameter is an invitation for users to visit that URL to submit a bug report +/// in the case where a panic happens. +pub fn set(bug_url: &'static str, version: &str) { + panic::set_hook(Box::new({ + let version = version.to_string(); + move |c| { + panic_hook(c, bug_url, &version) + } + })); +} + +macro_rules! ABOUT_PANIC { + () => (" +This is a bug. Please report it at: + + {} +")} + +/// Set aborting flag. Returns previous value of the flag. +fn set_abort(on_panic: OnPanic) -> OnPanic { + ON_PANIC.with(|val| { + let prev = val.get(); + match prev { + OnPanic::Abort | OnPanic::Unwind => val.set(on_panic), + OnPanic::NeverAbort => (), + } + prev + }) +} + +/// RAII guard for whether panics in the current thread should unwind or abort. +/// +/// Sets a thread-local abort flag on construction and reverts to the previous setting when dropped. +/// Does not implement `Send` on purpose. +/// +/// > **Note**: Because we restore the previous value when dropped, you are encouraged to leave +/// > the `AbortGuard` on the stack and let it destroy itself naturally. +pub struct AbortGuard { + /// Value that was in `ABORT` before we created this guard. + previous_val: OnPanic, + /// Marker so that `AbortGuard` doesn't implement `Send`. + _not_send: PhantomData> +} + +impl AbortGuard { + /// Create a new guard. While the guard is alive, panics that happen in the current thread will + /// unwind the stack (unless another guard is created afterwards). + pub fn force_unwind() -> AbortGuard { + AbortGuard { + previous_val: set_abort(OnPanic::Unwind), + _not_send: PhantomData + } + } + + /// Create a new guard. While the guard is alive, panics that happen in the current thread will + /// abort the process (unless another guard is created afterwards). + pub fn force_abort() -> AbortGuard { + AbortGuard { + previous_val: set_abort(OnPanic::Abort), + _not_send: PhantomData + } + } + + /// Create a new guard. While the guard is alive, panics that happen in the current thread will + /// **never** abort the process (even if `AbortGuard::force_abort()` guard will be created afterwards). + pub fn never_abort() -> AbortGuard { + AbortGuard { + previous_val: set_abort(OnPanic::NeverAbort), + _not_send: PhantomData + } + } +} + +impl Drop for AbortGuard { + fn drop(&mut self) { + set_abort(self.previous_val); + } +} + +/// Function being called when a panic happens. +fn panic_hook(info: &PanicInfo, report_url: &'static str, version: &str) { + let location = info.location(); + let file = location.as_ref().map(|l| l.file()).unwrap_or(""); + let line = location.as_ref().map(|l| l.line()).unwrap_or(0); + + let msg = match info.payload().downcast_ref::<&'static str>() { + Some(s) => *s, + None => match info.payload().downcast_ref::() { + Some(s) => &s[..], + None => "Box", + } + }; + + let thread = thread::current(); + let name = thread.name().unwrap_or(""); + + let backtrace = Backtrace::new(); + + let mut stderr = io::stderr(); + + let _ = writeln!(stderr, ""); + let _ = writeln!(stderr, "===================="); + let _ = writeln!(stderr, ""); + let _ = writeln!(stderr, "Version: {}", version); + let _ = writeln!(stderr, ""); + let _ = writeln!(stderr, "{:?}", backtrace); + let _ = writeln!(stderr, ""); + let _ = writeln!( + stderr, + "Thread '{}' panicked at '{}', {}:{}", + name, msg, file, line + ); + + let _ = writeln!(stderr, ABOUT_PANIC!(), report_url); + ON_PANIC.with(|val| { + if val.get() == OnPanic::Abort { + ::std::process::exit(1); + } + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn does_not_abort() { + set("test", "1.2.3"); + let _guard = AbortGuard::force_unwind(); + ::std::panic::catch_unwind(|| panic!()).ok(); + } + + #[test] + fn does_not_abort_after_never_abort() { + set("test", "1.2.3"); + let _guard = AbortGuard::never_abort(); + let _guard = AbortGuard::force_abort(); + std::panic::catch_unwind(|| panic!()).ok(); + } +} diff --git a/primitives/phragmen/Cargo.toml b/primitives/phragmen/Cargo.toml new file mode 100644 index 0000000000000..92807376de3b5 --- /dev/null +++ b/primitives/phragmen/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sp-phragmen" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } + +[dev-dependencies] +substrate-test-utils = { version = "2.0.0", path = "../../test-utils" } +sp-io ={ version = "2.0.0", path = "../../primitives/io" } +rand = "0.7.2" + +[features] +default = ["std"] +std = [ + "serde", + "sp-std/std", + "sp-runtime/std", +] diff --git a/core/phragmen/benches/phragmen.rs b/primitives/phragmen/benches/phragmen.rs similarity index 98% rename from core/phragmen/benches/phragmen.rs rename to primitives/phragmen/benches/phragmen.rs index b73811b33fa55..7bebda564e435 100644 --- a/core/phragmen/benches/phragmen.rs +++ b/primitives/phragmen/benches/phragmen.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies +// Copyright 2019-2020 Parity Technologies // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,11 +23,11 @@ extern crate test; use test::Bencher; use rand::{self, Rng}; -extern crate substrate_phragmen as phragmen; +extern crate sp_phragmen as phragmen; use phragmen::{Support, SupportMap, PhragmenStakedAssignment}; use std::collections::BTreeMap; -use sr_primitives::traits::{Convert, SaturatedConversion}; +use sp_runtime::traits::{Convert, SaturatedConversion}; const VALIDATORS: u64 = 1000; const NOMINATORS: u64 = 10_000; diff --git a/primitives/phragmen/src/lib.rs b/primitives/phragmen/src/lib.rs new file mode 100644 index 0000000000000..d9712d6ffbd35 --- /dev/null +++ b/primitives/phragmen/src/lib.rs @@ -0,0 +1,537 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Rust implementation of the Phragmén election algorithm. This is used in several SRML modules to +//! optimally distribute the weight of a set of voters among an elected set of candidates. In the +//! context of staking this is mapped to validators and nominators. +//! +//! The algorithm has two phases: +//! - Sequential phragmen: performed in [`elect`] function which is first pass of the distribution +//! The results are not optimal but the execution time is less. +//! - Equalize post-processing: tries to further distribute the weight fairly among candidates. +//! Incurs more execution time. +//! +//! The main objective of the assignments done by phragmen is to maximize the minimum backed +//! candidate in the elected set. +//! +//! Reference implementation: https://github.com/w3f/consensus +//! Further details: +//! https://research.web3.foundation/en/latest/polkadot/NPoS/4.%20Sequential%20Phragm%C3%A9n%E2%80%99s%20method/ + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{prelude::*, collections::btree_map::BTreeMap}; +use sp_runtime::RuntimeDebug; +use sp_runtime::{helpers_128bit::multiply_by_rational, Perbill, Rational128}; +use sp_runtime::traits::{Zero, Convert, Member, SimpleArithmetic, Saturating, Bounded}; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +/// A type in which performing operations on balances and stakes of candidates and voters are safe. +/// +/// This module's functions expect a `Convert` type to convert all balances to u64. Hence, u128 is +/// a safe type for arithmetic operations over them. +/// +/// Balance types converted to `ExtendedBalance` are referred to as `Votes`. +pub type ExtendedBalance = u128; + +/// The denominator used for loads. Since votes are collected as u64, the smallest ratio that we +/// might collect is `1/approval_stake` where approval stake is the sum of votes. Hence, some number +/// bigger than u64::max_value() is needed. For maximum accuracy we simply use u128; +const DEN: u128 = u128::max_value(); + +/// A candidate entity for phragmen election. +#[derive(Clone, Default, RuntimeDebug)] +pub struct Candidate { + /// Identifier. + pub who: AccountId, + /// Intermediary value used to sort candidates. + pub score: Rational128, + /// Sum of the stake of this candidate based on received votes. + approval_stake: ExtendedBalance, + /// Flag for being elected. + elected: bool, +} + +/// A voter entity. +#[derive(Clone, Default, RuntimeDebug)] +pub struct Voter { + /// Identifier. + who: AccountId, + /// List of candidates proposed by this voter. + edges: Vec>, + /// The stake of this voter. + budget: ExtendedBalance, + /// Incremented each time a candidate that this voter voted for has been elected. + load: Rational128, +} + +/// A candidate being backed by a voter. +#[derive(Clone, Default, RuntimeDebug)] +pub struct Edge { + /// Identifier. + who: AccountId, + /// Load of this vote. + load: Rational128, + /// Index of the candidate stored in the 'candidates' vector. + candidate_index: usize, +} + +/// Means a particular `AccountId` was backed by `Perbill`th of a nominator's stake. +pub type PhragmenAssignment = (AccountId, Perbill); + +/// Means a particular `AccountId` was backed by `ExtendedBalance` of a nominator's stake. +pub type PhragmenStakedAssignment = (AccountId, ExtendedBalance); + +/// Final result of the phragmen election. +#[derive(RuntimeDebug)] +pub struct PhragmenResult { + /// Just winners zipped with their approval stake. Note that the approval stake is merely the + /// sub of their received stake and could be used for very basic sorting and approval voting. + pub winners: Vec<(AccountId, ExtendedBalance)>, + /// Individual assignments. for each tuple, the first elements is a voter and the second + /// is the list of candidates that it supports. + pub assignments: Vec<(AccountId, Vec>)> +} + +/// A structure to demonstrate the phragmen result from the perspective of the candidate, i.e. how +/// much support each candidate is receiving. +/// +/// This complements the [`PhragmenResult`] and is needed to run the equalize post-processing. +/// +/// This, at the current version, resembles the `Exposure` defined in the staking SRML module, yet +/// they do not necessarily have to be the same. +#[derive(Default, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Support { + /// The amount of support as the effect of self-vote. + pub own: ExtendedBalance, + /// Total support. + pub total: ExtendedBalance, + /// Support from voters. + pub others: Vec>, +} + +/// A linkage from a candidate and its [`Support`]. +pub type SupportMap = BTreeMap>; + +/// Perform election based on Phragmén algorithm. +/// +/// Returns an `Option` the set of winners and their detailed support ratio from each voter if +/// enough candidates are provided. Returns `None` otherwise. +/// +/// * `candidate_count`: number of candidates to elect. +/// * `minimum_candidate_count`: minimum number of candidates to elect. If less candidates exist, +/// `None` is returned. +/// * `initial_candidates`: candidates list to be elected from. +/// * `initial_voters`: voters list. +/// * `stake_of`: something that can return the stake stake of a particular candidate or voter. +/// +/// This function does not strip out candidates who do not have any backing stake. It is the +/// responsibility of the caller to make sure only those candidates who have a sensible economic +/// value are passed in. From the perspective of this function, a candidate can easily be among the +/// winner with no backing stake. +pub fn elect( + candidate_count: usize, + minimum_candidate_count: usize, + initial_candidates: Vec, + initial_voters: Vec<(AccountId, Vec)>, + stake_of: FS, +) -> Option> where + AccountId: Default + Ord + Member, + Balance: Default + Copy + SimpleArithmetic, + for<'r> FS: Fn(&'r AccountId) -> Balance, + C: Convert + Convert, +{ + let to_votes = |b: Balance| >::convert(b) as ExtendedBalance; + + // return structures + let mut elected_candidates: Vec<(AccountId, ExtendedBalance)>; + let mut assigned: Vec<(AccountId, Vec>)>; + + // used to cache and access candidates index. + let mut c_idx_cache = BTreeMap::::new(); + + // voters list. + let num_voters = initial_candidates.len() + initial_voters.len(); + let mut voters: Vec> = Vec::with_capacity(num_voters); + + // Iterate once to create a cache of candidates indexes. This could be optimized by being + // provided by the call site. + let mut candidates = initial_candidates + .into_iter() + .enumerate() + .map(|(idx, who)| { + c_idx_cache.insert(who.clone(), idx); + Candidate { who, ..Default::default() } + }) + .collect::>>(); + + // early return if we don't have enough candidates + if candidates.len() < minimum_candidate_count { return None; } + + // collect voters. use `c_idx_cache` for fast access and aggregate `approval_stake` of + // candidates. + voters.extend(initial_voters.into_iter().map(|(who, votes)| { + let voter_stake = stake_of(&who); + let mut edges: Vec> = Vec::with_capacity(votes.len()); + for v in votes { + if let Some(idx) = c_idx_cache.get(&v) { + // This candidate is valid + already cached. + candidates[*idx].approval_stake = candidates[*idx].approval_stake + .saturating_add(to_votes(voter_stake)); + edges.push(Edge { who: v.clone(), candidate_index: *idx, ..Default::default() }); + } // else {} would be wrong votes. We don't really care about it. + } + Voter { + who, + edges: edges, + budget: to_votes(voter_stake), + load: Rational128::zero(), + } + })); + + + // we have already checked that we have more candidates than minimum_candidate_count. + // run phragmen. + let to_elect = candidate_count.min(candidates.len()); + elected_candidates = Vec::with_capacity(candidate_count); + assigned = Vec::with_capacity(candidate_count); + + // main election loop + for _round in 0..to_elect { + // loop 1: initialize score + for c in &mut candidates { + if !c.elected { + // 1 / approval_stake == (DEN / approval_stake) / DEN. If approval_stake is zero, + // then the ratio should be as large as possible, essentially `infinity`. + if c.approval_stake.is_zero() { + c.score = Rational128::from_unchecked(DEN, 0); + } else { + c.score = Rational128::from(DEN / c.approval_stake, DEN); + } + } + } + + // loop 2: increment score + for n in &voters { + for e in &n.edges { + let c = &mut candidates[e.candidate_index]; + if !c.elected && !c.approval_stake.is_zero() { + let temp_n = multiply_by_rational( + n.load.n(), + n.budget, + c.approval_stake, + ).unwrap_or(Bounded::max_value()); + let temp_d = n.load.d(); + let temp = Rational128::from(temp_n, temp_d); + c.score = c.score.lazy_saturating_add(temp); + } + } + } + + // loop 3: find the best + if let Some(winner) = candidates + .iter_mut() + .filter(|c| !c.elected) + .min_by_key(|c| c.score) + { + // loop 3: update voter and edge load + winner.elected = true; + for n in &mut voters { + for e in &mut n.edges { + if e.who == winner.who { + e.load = winner.score.lazy_saturating_sub(n.load); + n.load = winner.score; + } + } + } + + elected_candidates.push((winner.who.clone(), winner.approval_stake)); + } else { + break + } + } // end of all rounds + + // update backing stake of candidates and voters + for n in &mut voters { + let mut assignment = (n.who.clone(), vec![]); + for e in &mut n.edges { + if elected_candidates.iter().position(|(ref c, _)| *c == e.who).is_some() { + let per_bill_parts = + { + if n.load == e.load { + // Full support. No need to calculate. + Perbill::accuracy().into() + } else { + if e.load.d() == n.load.d() { + // return e.load / n.load. + let desired_scale: u128 = Perbill::accuracy().into(); + multiply_by_rational( + desired_scale, + e.load.n(), + n.load.n(), + ).unwrap_or(Bounded::max_value()) + } else { + // defensive only. Both edge and nominator loads are built from + // scores, hence MUST have the same denominator. + Zero::zero() + } + } + }; + // safer to .min() inside as well to argue as u32 is safe. + let per_thing = Perbill::from_parts( + per_bill_parts.min(Perbill::accuracy().into()) as u32 + ); + assignment.1.push((e.who.clone(), per_thing)); + } + } + + if assignment.1.len() > 0 { + // To ensure an assertion indicating: no stake from the nominator going to waste, + // we add a minimal post-processing to equally assign all of the leftover stake ratios. + let vote_count = assignment.1.len() as u32; + let len = assignment.1.len(); + let sum = assignment.1.iter() + .map(|a| a.1.deconstruct()) + .sum::(); + let accuracy = Perbill::accuracy(); + let diff = accuracy.checked_sub(sum).unwrap_or(0); + let diff_per_vote = (diff / vote_count).min(accuracy); + + if diff_per_vote > 0 { + for i in 0..len { + let current_ratio = assignment.1[i % len].1; + let next_ratio = current_ratio + .saturating_add(Perbill::from_parts(diff_per_vote)); + assignment.1[i % len].1 = next_ratio; + } + } + + // `remainder` is set to be less than maximum votes of a nominator (currently 16). + // safe to cast it to usize. + let remainder = diff - diff_per_vote * vote_count; + for i in 0..remainder as usize { + let current_ratio = assignment.1[i % len].1; + let next_ratio = current_ratio.saturating_add(Perbill::from_parts(1)); + assignment.1[i % len].1 = next_ratio; + } + assigned.push(assignment); + } + } + + Some(PhragmenResult { + winners: elected_candidates, + assignments: assigned, + }) +} + +/// Build the support map from the given phragmen result. +pub fn build_support_map( + elected_stashes: &Vec, + assignments: &Vec<(AccountId, Vec>)>, + stake_of: FS, +) -> SupportMap where + AccountId: Default + Ord + Member, + Balance: Default + Copy + SimpleArithmetic, + C: Convert + Convert, + for<'r> FS: Fn(&'r AccountId) -> Balance, +{ + let to_votes = |b: Balance| >::convert(b) as ExtendedBalance; + // Initialize the support of each candidate. + let mut supports = >::new(); + elected_stashes + .iter() + .for_each(|e| { supports.insert(e.clone(), Default::default()); }); + + // build support struct. + for (n, assignment) in assignments.iter() { + for (c, per_thing) in assignment.iter() { + let nominator_stake = to_votes(stake_of(n)); + // AUDIT: it is crucially important for the `Mul` implementation of all + // per-things to be sound. + let other_stake = *per_thing * nominator_stake; + if let Some(support) = supports.get_mut(c) { + if c == n { + // This is a nomination from `n` to themselves. This will increase both the + // `own` and `total` field. + debug_assert!(*per_thing == Perbill::one()); // TODO: deal with this: do we want it? + support.own = support.own.saturating_add(other_stake); + support.total = support.total.saturating_add(other_stake); + } else { + // This is a nomination from `n` to someone else. Increase `total` and add an entry + // inside `others`. + // For an astronomically rich validator with more astronomically rich + // set of nominators, this might saturate. + support.total = support.total.saturating_add(other_stake); + support.others.push((n.clone(), other_stake)); + } + } + } + } + supports +} + +/// Performs equalize post-processing to the output of the election algorithm. This happens in +/// rounds. The number of rounds and the maximum diff-per-round tolerance can be tuned through input +/// parameters. +/// +/// No value is returned from the function and the `supports` parameter is updated. +/// +/// * `assignments`: exactly the same is the output of phragmen. +/// * `supports`: mutable reference to s `SupportMap`. This parameter is updated. +/// * `tolerance`: maximum difference that can occur before an early quite happens. +/// * `iterations`: maximum number of iterations that will be processed. +/// * `stake_of`: something that can return the stake stake of a particular candidate or voter. +pub fn equalize( + mut assignments: Vec<(AccountId, Vec>)>, + supports: &mut SupportMap, + tolerance: ExtendedBalance, + iterations: usize, + stake_of: FS, +) where + C: Convert + Convert, + for<'r> FS: Fn(&'r AccountId) -> Balance, + AccountId: Ord + Clone, +{ + // prepare the data for equalise + for _i in 0..iterations { + let mut max_diff = 0; + + for (voter, assignment) in assignments.iter_mut() { + let voter_budget = stake_of(&voter); + + let diff = do_equalize::<_, _, C>( + voter, + voter_budget, + assignment, + supports, + tolerance, + ); + if diff > max_diff { max_diff = diff; } + } + + if max_diff < tolerance { + break; + } + } +} + +/// actually perform equalize. same interface is `equalize`. Just called in loops with a check for +/// maximum difference. +fn do_equalize( + voter: &AccountId, + budget_balance: Balance, + elected_edges: &mut Vec>, + support_map: &mut SupportMap, + tolerance: ExtendedBalance +) -> ExtendedBalance where + C: Convert + Convert, + AccountId: Ord + Clone, +{ + let to_votes = |b: Balance| + >::convert(b) as ExtendedBalance; + let budget = to_votes(budget_balance); + + // Nothing to do. This voter had nothing useful. + // Defensive only. Assignment list should always be populated. + if elected_edges.is_empty() { return 0; } + + let stake_used = elected_edges + .iter() + .fold(0 as ExtendedBalance, |s, e| s.saturating_add(e.1)); + + let backed_stakes_iter = elected_edges + .iter() + .filter_map(|e| support_map.get(&e.0)) + .map(|e| e.total); + + let backing_backed_stake = elected_edges + .iter() + .filter(|e| e.1 > 0) + .filter_map(|e| support_map.get(&e.0)) + .map(|e| e.total) + .collect::>(); + + let mut difference; + if backing_backed_stake.len() > 0 { + let max_stake = backing_backed_stake + .iter() + .max() + .expect("vector with positive length will have a max; qed"); + let min_stake = backed_stakes_iter + .min() + .expect("iterator with positive length will have a min; qed"); + + difference = max_stake.saturating_sub(min_stake); + difference = difference.saturating_add(budget.saturating_sub(stake_used)); + if difference < tolerance { + return difference; + } + } else { + difference = budget; + } + + // Undo updates to support + elected_edges.iter_mut().for_each(|e| { + if let Some(support) = support_map.get_mut(&e.0) { + support.total = support.total.saturating_sub(e.1); + support.others.retain(|i_support| i_support.0 != *voter); + } + e.1 = 0; + }); + + elected_edges.sort_unstable_by_key(|e| + if let Some(e) = support_map.get(&e.0) { e.total } else { Zero::zero() } + ); + + let mut cumulative_stake: ExtendedBalance = 0; + let mut last_index = elected_edges.len() - 1; + let mut idx = 0usize; + for e in &mut elected_edges[..] { + if let Some(support) = support_map.get_mut(&e.0) { + let stake = support.total; + let stake_mul = stake.saturating_mul(idx as ExtendedBalance); + let stake_sub = stake_mul.saturating_sub(cumulative_stake); + if stake_sub > budget { + last_index = idx.checked_sub(1).unwrap_or(0); + break; + } + cumulative_stake = cumulative_stake.saturating_add(stake); + } + idx += 1; + } + + let last_stake = elected_edges[last_index].1; + let split_ways = last_index + 1; + let excess = budget + .saturating_add(cumulative_stake) + .saturating_sub(last_stake.saturating_mul(split_ways as ExtendedBalance)); + elected_edges.iter_mut().take(split_ways).for_each(|e| { + if let Some(support) = support_map.get_mut(&e.0) { + e.1 = (excess / split_ways as ExtendedBalance) + .saturating_add(last_stake) + .saturating_sub(support.total); + support.total = support.total.saturating_add(e.1); + support.others.push((voter.clone(), e.1)); + } + }); + + difference +} diff --git a/primitives/phragmen/src/mock.rs b/primitives/phragmen/src/mock.rs new file mode 100644 index 0000000000000..32de65f0e6008 --- /dev/null +++ b/primitives/phragmen/src/mock.rs @@ -0,0 +1,405 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Mock file for phragmen. + +#![cfg(test)] + +use crate::{elect, PhragmenResult, PhragmenAssignment}; +use sp_runtime::{ + assert_eq_error_rate, Perbill, + traits::{Convert, Member, SaturatedConversion} +}; +use sp_std::collections::btree_map::BTreeMap; + +pub(crate) struct TestCurrencyToVote; +impl Convert for TestCurrencyToVote { + fn convert(x: Balance) -> u64 { x.saturated_into() } +} +impl Convert for TestCurrencyToVote { + fn convert(x: u128) -> Balance { x } +} + +#[derive(Default, Debug)] +pub(crate) struct _Candidate { + who: A, + score: f64, + approval_stake: f64, + elected: bool, +} + +#[derive(Default, Debug)] +pub(crate) struct _Voter { + who: A, + edges: Vec<_Edge>, + budget: f64, + load: f64, +} + +#[derive(Default, Debug)] +pub(crate) struct _Edge { + who: A, + load: f64, + candidate_index: usize, +} + +#[derive(Default, Debug, PartialEq)] +pub(crate) struct _Support { + pub own: f64, + pub total: f64, + pub others: Vec<_PhragmenAssignment>, +} + +pub(crate) type _PhragmenAssignment = (A, f64); +pub(crate) type _SupportMap = BTreeMap>; + +pub(crate) type Balance = u128; +pub(crate) type AccountId = u64; + +#[derive(Debug, Clone)] +pub(crate) struct _PhragmenResult { + pub winners: Vec<(A, Balance)>, + pub assignments: Vec<(A, Vec<_PhragmenAssignment>)> +} + +pub(crate) fn auto_generate_self_voters(candidates: &[A]) -> Vec<(A, Vec)> { + candidates.iter().map(|c| (c.clone(), vec![c.clone()])).collect() +} + +pub(crate) fn elect_float( + candidate_count: usize, + minimum_candidate_count: usize, + initial_candidates: Vec, + initial_voters: Vec<(A, Vec)>, + stake_of: FS, +) -> Option<_PhragmenResult> where + A: Default + Ord + Member + Copy, + for<'r> FS: Fn(&'r A) -> Balance, +{ + let mut elected_candidates: Vec<(A, Balance)>; + let mut assigned: Vec<(A, Vec<_PhragmenAssignment>)>; + let mut c_idx_cache = BTreeMap::::new(); + let num_voters = initial_candidates.len() + initial_voters.len(); + let mut voters: Vec<_Voter> = Vec::with_capacity(num_voters); + + let mut candidates = initial_candidates + .into_iter() + .enumerate() + .map(|(idx, who)| { + c_idx_cache.insert(who.clone(), idx); + _Candidate { who, ..Default::default() } + }) + .collect::>>(); + + if candidates.len() < minimum_candidate_count { + return None; + } + + voters.extend(initial_voters.into_iter().map(|(who, votes)| { + let voter_stake = stake_of(&who) as f64; + let mut edges: Vec<_Edge> = Vec::with_capacity(votes.len()); + for v in votes { + if let Some(idx) = c_idx_cache.get(&v) { + candidates[*idx].approval_stake = candidates[*idx].approval_stake + voter_stake; + edges.push( + _Edge { who: v.clone(), candidate_index: *idx, ..Default::default() } + ); + } + } + _Voter { + who, + edges: edges, + budget: voter_stake, + load: 0f64, + } + })); + + let to_elect = candidate_count.min(candidates.len()); + elected_candidates = Vec::with_capacity(candidate_count); + assigned = Vec::with_capacity(candidate_count); + + for _round in 0..to_elect { + for c in &mut candidates { + if !c.elected { + c.score = 1.0 / c.approval_stake; + } + } + for n in &voters { + for e in &n.edges { + let c = &mut candidates[e.candidate_index]; + if !c.elected && !(c.approval_stake == 0f64) { + c.score += n.budget * n.load / c.approval_stake; + } + } + } + + if let Some(winner) = candidates + .iter_mut() + .filter(|c| !c.elected) + .min_by(|x, y| x.score.partial_cmp(&y.score).unwrap_or(sp_std::cmp::Ordering::Equal)) + { + winner.elected = true; + for n in &mut voters { + for e in &mut n.edges { + if e.who == winner.who { + e.load = winner.score - n.load; + n.load = winner.score; + } + } + } + + elected_candidates.push((winner.who.clone(), winner.approval_stake as Balance)); + } else { + break + } + } + + for n in &mut voters { + let mut assignment = (n.who.clone(), vec![]); + for e in &mut n.edges { + if let Some(c) = elected_candidates.iter().cloned().map(|(c, _)| c).find(|c| *c == e.who) { + if c != n.who { + let ratio = e.load / n.load; + assignment.1.push((e.who.clone(), ratio)); + } + } + } + if assignment.1.len() > 0 { + assigned.push(assignment); + } + } + + Some(_PhragmenResult { + winners: elected_candidates, + assignments: assigned, + }) +} + +pub(crate) fn equalize_float( + mut assignments: Vec<(A, Vec<_PhragmenAssignment>)>, + supports: &mut _SupportMap, + tolerance: f64, + iterations: usize, + stake_of: FS, +) where + for<'r> FS: Fn(&'r A) -> Balance, + A: Ord + Clone + std::fmt::Debug, +{ + for _i in 0..iterations { + let mut max_diff = 0.0; + for (voter, assignment) in assignments.iter_mut() { + let voter_budget = stake_of(&voter); + let diff = do_equalize_float( + voter, + voter_budget, + assignment, + supports, + tolerance, + ); + if diff > max_diff { max_diff = diff; } + } + + if max_diff < tolerance { + break; + } + } +} + +pub(crate) fn do_equalize_float( + voter: &A, + budget_balance: Balance, + elected_edges: &mut Vec<_PhragmenAssignment>, + support_map: &mut _SupportMap, + tolerance: f64 +) -> f64 where + A: Ord + Clone, +{ + let budget = budget_balance as f64; + if elected_edges.is_empty() { return 0.0; } + + let stake_used = elected_edges + .iter() + .fold(0.0, |s, e| s + e.1); + + let backed_stakes_iter = elected_edges + .iter() + .filter_map(|e| support_map.get(&e.0)) + .map(|e| e.total); + + let backing_backed_stake = elected_edges + .iter() + .filter(|e| e.1 > 0.0) + .filter_map(|e| support_map.get(&e.0)) + .map(|e| e.total) + .collect::>(); + + let mut difference; + if backing_backed_stake.len() > 0 { + let max_stake = backing_backed_stake + .iter() + .max_by(|x, y| x.partial_cmp(&y).unwrap_or(sp_std::cmp::Ordering::Equal)) + .expect("vector with positive length will have a max; qed"); + let min_stake = backed_stakes_iter + .min_by(|x, y| x.partial_cmp(&y).unwrap_or(sp_std::cmp::Ordering::Equal)) + .expect("iterator with positive length will have a min; qed"); + + difference = max_stake - min_stake; + difference = difference + budget - stake_used; + if difference < tolerance { + return difference; + } + } else { + difference = budget; + } + + // Undo updates to support + elected_edges.iter_mut().for_each(|e| { + if let Some(support) = support_map.get_mut(&e.0) { + support.total = support.total - e.1; + support.others.retain(|i_support| i_support.0 != *voter); + } + e.1 = 0.0; + }); + + elected_edges.sort_unstable_by(|x, y| + support_map.get(&x.0) + .and_then(|x| support_map.get(&y.0).and_then(|y| x.total.partial_cmp(&y.total))) + .unwrap_or(sp_std::cmp::Ordering::Equal) + ); + + let mut cumulative_stake = 0.0; + let mut last_index = elected_edges.len() - 1; + elected_edges.iter_mut().enumerate().for_each(|(idx, e)| { + if let Some(support) = support_map.get_mut(&e.0) { + let stake = support.total; + let stake_mul = stake * (idx as f64); + let stake_sub = stake_mul - cumulative_stake; + if stake_sub > budget { + last_index = idx.checked_sub(1).unwrap_or(0); + return + } + cumulative_stake = cumulative_stake + stake; + } + }); + + let last_stake = elected_edges[last_index].1; + let split_ways = last_index + 1; + let excess = budget + cumulative_stake - last_stake * (split_ways as f64); + elected_edges.iter_mut().take(split_ways).for_each(|e| { + if let Some(support) = support_map.get_mut(&e.0) { + e.1 = excess / (split_ways as f64) + last_stake - support.total; + support.total = support.total + e.1; + support.others.push((voter.clone(), e.1)); + } + }); + + difference +} + + +pub(crate) fn create_stake_of(stakes: &[(AccountId, Balance)]) + -> Box Balance> +{ + let mut storage = BTreeMap::::new(); + stakes.iter().for_each(|s| { storage.insert(s.0, s.1); }); + let stake_of = move |who: &AccountId| -> Balance { storage.get(who).unwrap().to_owned() }; + Box::new(stake_of) +} + + +pub fn check_assignments(assignments: Vec<(AccountId, Vec>)>) { + for (_, a) in assignments { + let sum: u32 = a.iter().map(|(_, p)| p.deconstruct()).sum(); + assert_eq_error_rate!(sum, Perbill::accuracy(), 5); + } +} + +pub(crate) fn run_and_compare( + candidates: Vec, + voters: Vec<(AccountId, Vec)>, + stake_of: Box Balance>, + to_elect: usize, + min_to_elect: usize, +) { + // run fixed point code. + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + to_elect, + min_to_elect, + candidates.clone(), + voters.clone(), + &stake_of, + ).unwrap(); + + // run float poc code. + let truth_value = elect_float( + to_elect, + min_to_elect, + candidates, + voters, + &stake_of, + ).unwrap(); + + assert_eq!(winners, truth_value.winners); + + for (nominator, assigned) in assignments.clone() { + if let Some(float_assignments) = truth_value.assignments.iter().find(|x| x.0 == nominator) { + for (candidate, per_thingy) in assigned { + if let Some(float_assignment) = float_assignments.1.iter().find(|x| x.0 == candidate ) { + assert_eq_error_rate!( + Perbill::from_fraction(float_assignment.1).deconstruct(), + per_thingy.deconstruct(), + 1, + ); + } else { + panic!("candidate mismatch. This should never happen.") + } + } + } else { + panic!("nominator mismatch. This should never happen.") + } + } + + check_assignments(assignments); +} + +pub(crate) fn build_support_map( + result: &mut _PhragmenResult, + stake_of: FS, +) -> _SupportMap + where for<'r> FS: Fn(&'r AccountId) -> Balance +{ + let mut supports = <_SupportMap>::new(); + result.winners + .iter() + .map(|(e, _)| (e, stake_of(e) as f64)) + .for_each(|(e, s)| { + let item = _Support { own: s, total: s, ..Default::default() }; + supports.insert(e.clone(), item); + }); + + for (n, assignment) in result.assignments.iter_mut() { + for (c, r) in assignment.iter_mut() { + let nominator_stake = stake_of(n) as f64; + let other_stake = nominator_stake * *r; + if let Some(support) = supports.get_mut(c) { + support.total = support.total + other_stake; + support.others.push((n.clone(), other_stake)); + } + *r = other_stake; + } + } + supports +} diff --git a/primitives/phragmen/src/tests.rs b/primitives/phragmen/src/tests.rs new file mode 100644 index 0000000000000..f3974d07d3b99 --- /dev/null +++ b/primitives/phragmen/src/tests.rs @@ -0,0 +1,407 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for phragmen. + +#![cfg(test)] + +use crate::mock::*; +use crate::{elect, PhragmenResult}; +use substrate_test_utils::assert_eq_uvec; +use sp_runtime::Perbill; + +#[test] +fn float_phragmen_poc_works() { + let candidates = vec![1, 2, 3]; + let voters = vec![ + (10, vec![1, 2]), + (20, vec![1, 3]), + (30, vec![2, 3]), + ]; + let stake_of = create_stake_of(&[(10, 10), (20, 20), (30, 30), (1, 0), (2, 0), (3, 0)]); + let mut phragmen_result = elect_float(2, 2, candidates, voters, &stake_of).unwrap(); + let winners = phragmen_result.clone().winners; + let assignments = phragmen_result.clone().assignments; + + assert_eq_uvec!(winners, vec![(2, 40), (3, 50)]); + assert_eq_uvec!( + assignments, + vec![ + (10, vec![(2, 1.0)]), + (20, vec![(3, 1.0)]), + (30, vec![(2, 0.5), (3, 0.5)]), + ] + ); + + let mut support_map = build_support_map(&mut phragmen_result, &stake_of); + + assert_eq!( + support_map.get(&2).unwrap(), + &_Support { own: 0.0, total: 25.0, others: vec![(10u64, 10.0), (30u64, 15.0)]} + ); + assert_eq!( + support_map.get(&3).unwrap(), + &_Support { own: 0.0, total: 35.0, others: vec![(20u64, 20.0), (30u64, 15.0)]} + ); + + equalize_float(phragmen_result.assignments, &mut support_map, 0.0, 2, stake_of); + + assert_eq!( + support_map.get(&2).unwrap(), + &_Support { own: 0.0, total: 30.0, others: vec![(10u64, 10.0), (30u64, 20.0)]} + ); + assert_eq!( + support_map.get(&3).unwrap(), + &_Support { own: 0.0, total: 30.0, others: vec![(20u64, 20.0), (30u64, 10.0)]} + ); +} + +#[test] +fn phragmen_poc_works() { + let candidates = vec![1, 2, 3]; + let voters = vec![ + (10, vec![1, 2]), + (20, vec![1, 3]), + (30, vec![2, 3]), + ]; + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + voters, + create_stake_of(&[(10, 10), (20, 20), (30, 30)]), + ).unwrap(); + + assert_eq_uvec!(winners, vec![(2, 40), (3, 50)]); + assert_eq_uvec!( + assignments, + vec![ + (10, vec![(2, Perbill::from_percent(100))]), + (20, vec![(3, Perbill::from_percent(100))]), + (30, vec![(2, Perbill::from_percent(100/2)), (3, Perbill::from_percent(100/2))]), + ] + ); +} + +#[test] +fn phragmen_poc_2_works() { + let candidates = vec![10, 20, 30]; + let voters = vec![ + (2, vec![10, 20, 30]), + (4, vec![10, 20, 40]), + ]; + let stake_of = create_stake_of(&[ + (10, 1000), + (20, 1000), + (30, 1000), + (40, 1000), + (2, 500), + (4, 500), + ]); + + run_and_compare(candidates, voters, stake_of, 2, 2); +} + +#[test] +fn phragmen_poc_3_works() { + let candidates = vec![10, 20, 30]; + let voters = vec![ + (2, vec![10, 20, 30]), + (4, vec![10, 20, 40]), + ]; + let stake_of = create_stake_of(&[ + (10, 1000), + (20, 1000), + (30, 1000), + (2, 50), + (4, 1000), + ]); + + run_and_compare(candidates, voters, stake_of, 2, 2); +} + +#[test] +fn phragmen_accuracy_on_large_scale_only_validators() { + // because of this particular situation we had per_u128 and now rational128. In practice, a + // candidate can have the maximum amount of tokens, and also supported by the maximum. + let candidates = vec![1, 2, 3, 4, 5]; + let stake_of = create_stake_of(&[ + (1, (u64::max_value() - 1).into()), + (2, (u64::max_value() - 4).into()), + (3, (u64::max_value() - 5).into()), + (4, (u64::max_value() - 3).into()), + (5, (u64::max_value() - 2).into()), + ]); + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates.clone(), + auto_generate_self_voters(&candidates), + stake_of, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(1, 18446744073709551614u128), (5, 18446744073709551613u128)]); + assert_eq!(assignments.len(), 2); + check_assignments(assignments); +} + +#[test] +fn phragmen_accuracy_on_large_scale_validators_and_nominators() { + let candidates = vec![1, 2, 3, 4, 5]; + let mut voters = vec![ + (13, vec![1, 3, 5]), + (14, vec![2, 4]), + ]; + voters.extend(auto_generate_self_voters(&candidates)); + let stake_of = create_stake_of(&[ + (1, (u64::max_value() - 1).into()), + (2, (u64::max_value() - 4).into()), + (3, (u64::max_value() - 5).into()), + (4, (u64::max_value() - 3).into()), + (5, (u64::max_value() - 2).into()), + (13, (u64::max_value() - 10).into()), + (14, u64::max_value().into()), + ]); + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + voters, + stake_of, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(2, 36893488147419103226u128), (1, 36893488147419103219u128)]); + assert_eq!( + assignments, + vec![ + (13, vec![(1, Perbill::one())]), + (14, vec![(2, Perbill::one())]), + (1, vec![(1, Perbill::one())]), + (2, vec![(2, Perbill::one())]), + ] + ); + check_assignments(assignments); +} + +#[test] +fn phragmen_accuracy_on_small_scale_self_vote() { + let candidates = vec![40, 10, 20, 30]; + let voters = auto_generate_self_voters(&candidates); + let stake_of = create_stake_of(&[ + (40, 0), + (10, 1), + (20, 2), + (30, 1), + ]); + + let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>( + 3, + 3, + candidates, + voters, + stake_of, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(20, 2), (10, 1), (30, 1)]); +} + +#[test] +fn phragmen_accuracy_on_small_scale_no_self_vote() { + let candidates = vec![40, 10, 20, 30]; + let voters = vec![ + (1, vec![10]), + (2, vec![20]), + (3, vec![30]), + (4, vec![40]), + ]; + let stake_of = create_stake_of(&[ + (40, 1000), // don't care + (10, 1000), // don't care + (20, 1000), // don't care + (30, 1000), // don't care + (4, 0), + (1, 1), + (2, 2), + (3, 1), + ]); + + let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>( + 3, + 3, + candidates, + voters, + stake_of, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(20, 2), (10, 1), (30, 1)]); +} + +#[test] +fn phragmen_large_scale_test() { + let candidates = vec![2, 4, 6, 8, 10, 12, 14, 16 ,18, 20, 22, 24]; + let mut voters = vec![ + (50, vec![2, 4, 6, 8, 10, 12, 14, 16 ,18, 20, 22, 24]), + ]; + voters.extend(auto_generate_self_voters(&candidates)); + let stake_of = create_stake_of(&[ + (2, 1), + (4, 100), + (6, 1000000), + (8, 100000000001000), + (10, 100000000002000), + (12, 100000000003000), + (14, 400000000000000), + (16, 400000000001000), + (18, 18000000000000000), + (20, 20000000000000000), + (22, 500000000000100000), + (24, 500000000000200000), + (50, 990000000000000000), + ]); + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + voters, + stake_of, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(24, 1490000000000200000u128), (22, 1490000000000100000u128)]); + check_assignments(assignments); +} + +#[test] +fn phragmen_large_scale_test_2() { + let nom_budget: u64 = 1_000_000_000_000_000_000; + let c_budget: u64 = 4_000_000; + + let candidates = vec![2, 4]; + let mut voters = vec![(50, vec![2, 4])]; + voters.extend(auto_generate_self_voters(&candidates)); + + let stake_of = create_stake_of(&[ + (2, c_budget.into()), + (4, c_budget.into()), + (50, nom_budget.into()), + ]); + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + voters, + stake_of, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(2, 1000000000004000000u128), (4, 1000000000004000000u128)]); + assert_eq!( + assignments, + vec![ + (50, vec![(2, Perbill::from_parts(500000001)), (4, Perbill::from_parts(499999999))]), + (2, vec![(2, Perbill::one())]), + (4, vec![(4, Perbill::one())]), + ], + ); + check_assignments(assignments); +} + +#[test] +fn phragmen_linear_equalize() { + let candidates = vec![11, 21, 31, 41, 51, 61, 71]; + let voters = vec![ + (2, vec![11]), + (4, vec![11, 21]), + (6, vec![21, 31]), + (8, vec![31, 41]), + (110, vec![41, 51]), + (120, vec![51, 61]), + (130, vec![61, 71]), + ]; + let stake_of = create_stake_of(&[ + (11, 1000), + (21, 1000), + (31, 1000), + (41, 1000), + (51, 1000), + (61, 1000), + (71, 1000), + + (2, 2000), + (4, 1000), + (6, 1000), + (8, 1000), + (110, 1000), + (120, 1000), + (130, 1000), + ]); + + run_and_compare(candidates, voters, stake_of, 2, 2); +} + +#[test] +fn elect_has_no_entry_barrier() { + let candidates = vec![10, 20, 30]; + let voters = vec![ + (1, vec![10]), + (2, vec![20]), + ]; + let stake_of = create_stake_of(&[ + (1, 10), + (2, 10), + ]); + + let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>( + 3, + 3, + candidates, + voters, + stake_of, + ).unwrap(); + + // 30 is elected with stake 0. The caller is responsible for stripping this. + assert_eq_uvec!(winners, vec![ + (10, 10), + (20, 10), + (30, 0), + ]); +} + +#[test] +fn minimum_to_elect_is_respected() { + let candidates = vec![10, 20, 30]; + let voters = vec![ + (1, vec![10]), + (2, vec![20]), + ]; + let stake_of = create_stake_of(&[ + (1, 10), + (2, 10), + ]); + + let maybe_result = elect::<_, _, _, TestCurrencyToVote>( + 10, + 10, + candidates, + voters, + stake_of, + ); + + assert!(maybe_result.is_none()); +} diff --git a/primitives/rpc/Cargo.toml b/primitives/rpc/Cargo.toml new file mode 100644 index 0000000000000..33a854e6b79f1 --- /dev/null +++ b/primitives/rpc/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "sp-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", features = ["derive"] } +sp-core = { version = "2.0.0", path = "../core" } + +[dev-dependencies] +serde_json = "1.0.41" diff --git a/primitives/rpc/src/lib.rs b/primitives/rpc/src/lib.rs new file mode 100644 index 0000000000000..7c22daf5cd94f --- /dev/null +++ b/primitives/rpc/src/lib.rs @@ -0,0 +1,38 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate RPC primitives and utilities. + +#![warn(missing_docs)] + +pub mod number; +pub mod list; + +/// A util function to assert the result of serialization and deserialization is the same. +#[cfg(test)] +pub(crate) fn assert_deser(s: &str, expected: T) where + T: std::fmt::Debug + serde::ser::Serialize + serde::de::DeserializeOwned + PartialEq +{ + assert_eq!( + serde_json::from_str::(s).unwrap(), + expected + ); + assert_eq!( + serde_json::to_string(&expected).unwrap(), + s + ); +} + diff --git a/primitives/rpc/src/list.rs b/primitives/rpc/src/list.rs new file mode 100644 index 0000000000000..b8b7c537c4c4c --- /dev/null +++ b/primitives/rpc/src/list.rs @@ -0,0 +1,75 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! RPC a lenient list or value type. + +use serde::{Serialize, Deserialize}; + +/// RPC list or value wrapper. +/// +/// For some RPCs it's convenient to call them with either +/// a single value or a whole list of values to get a proper response. +/// In theory you could do a batch query, but it's: +/// 1. Less convient in client libraries +/// 2. If the response value is small, the protocol overhead might be dominant. +/// +/// Also it's nice to be able to maintain backward compatibility for methods that +/// were initially taking a value and now we want to expand them to take a list. +#[derive(Serialize, Deserialize, Debug, PartialEq)] +#[serde(untagged)] +pub enum ListOrValue { + /// A list of values of given type. + List(Vec), + /// A single value of given type. + Value(T), +} + +impl ListOrValue { + /// Map every contained value using function `F`. + /// + /// This allows to easily convert all values in any of the variants. + pub fn map X, X>(self, f: F) -> ListOrValue { + match self { + ListOrValue::List(v) => ListOrValue::List(v.into_iter().map(f).collect()), + ListOrValue::Value(v) => ListOrValue::Value(f(v)), + } + } +} + +impl From for ListOrValue { + fn from(n: T) -> Self { + ListOrValue::Value(n) + } +} + +impl From> for ListOrValue { + fn from(n: Vec) -> Self { + ListOrValue::List(n) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::assert_deser; + + #[test] + fn should_serialize_and_deserialize() { + assert_deser(r#"5"#, ListOrValue::Value(5_u64)); + assert_deser(r#""str""#, ListOrValue::Value("str".to_string())); + assert_deser(r#"[1,2,3]"#, ListOrValue::List(vec![1_u64, 2_u64, 3_u64])); + } +} diff --git a/core/rpc/primitives/src/number.rs b/primitives/rpc/src/number.rs similarity index 81% rename from core/rpc/primitives/src/number.rs rename to primitives/rpc/src/number.rs index 0637e3decf396..1d41dd234f704 100644 --- a/core/rpc/primitives/src/number.rs +++ b/primitives/rpc/src/number.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 serde::{Serialize, Deserialize}; use std::{convert::TryFrom, fmt::Debug}; -use primitives::U256; +use sp_core::U256; /// RPC Block number type /// @@ -27,7 +27,7 @@ use primitives::U256; /// or we attempt to parse given hex value. /// We do that for consistency with the returned type, default generic header /// serializes block number as hex to avoid overflows in JavaScript. -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(untagged)] pub enum NumberOrHex { /// The original header number type of block. @@ -72,3 +72,18 @@ impl From for NumberOrHex { NumberOrHex::Hex(n) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::assert_deser; + + #[test] + fn should_serialize_and_deserialize() { + assert_deser(r#""0x1234""#, NumberOrHex::::Hex(0x1234.into())); + assert_deser(r#""0x0""#, NumberOrHex::::Hex(0.into())); + assert_deser(r#"5"#, NumberOrHex::Number(5_u64)); + assert_deser(r#"10000"#, NumberOrHex::Number(10000_u32)); + assert_deser(r#"0"#, NumberOrHex::Number(0_u16)); + } +} diff --git a/primitives/runtime-interface/Cargo.toml b/primitives/runtime-interface/Cargo.toml new file mode 100644 index 0000000000000..cdc94b6a2f226 --- /dev/null +++ b/primitives/runtime-interface/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "sp-runtime-interface" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-wasm-interface = { version = "2.0.0", optional = true, path = "../wasm-interface" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-runtime-interface-proc-macro = { version = "2.0.0", path = "proc-macro" } +sp-externalities = { version = "2.0.0", optional = true, path = "../externalities" } +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false } +environmental = { version = "1.0.2", optional = true } +static_assertions = "1.0.0" +primitive-types = { version = "0.6.1", default-features = false } + +[dev-dependencies] +sp-runtime-interface-test-wasm = { version = "2.0.0", path = "test-wasm" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } +sp-core = { version = "2.0.0", path = "../core" } +sp-io = { version = "2.0.0", path = "../io" } +rustversion = "1.0.0" +trybuild = "1.0.17" + +[features] +default = [ "std" ] +std = [ + "sp-wasm-interface", + "sp-std/std", + "codec/std", + "sp-externalities", + "environmental", + "primitive-types/std", +] + +# ATTENTION +# +# Only use when you know what you are doing. +# +# Disables static assertions in `impls.rs` that checks the word size. To prevent any footgun, the +# check is changed into a runtime check. +disable_target_static_assertions = [] diff --git a/primitives/runtime-interface/proc-macro/Cargo.toml b/primitives/runtime-interface/proc-macro/Cargo.toml new file mode 100644 index 0000000000000..a5d12de0a648b --- /dev/null +++ b/primitives/runtime-interface/proc-macro/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "sp-runtime-interface-proc-macro" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "1.0.5", features = ["full", "visit", "fold", "extra-traits"] } +quote = "1.0.2" +proc-macro2 = "1.0.3" +Inflector = "0.11.4" +proc-macro-crate = "0.1.4" diff --git a/primitives/runtime-interface/proc-macro/src/lib.rs b/primitives/runtime-interface/proc-macro/src/lib.rs new file mode 100644 index 0000000000000..47c9fd6bb78c2 --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/lib.rs @@ -0,0 +1,65 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This crate provides procedural macros for usage within the context of the Substrate runtime +//! interface. +//! +//! The following macros are provided: +//! +//! 1. The [`#[runtime_interface]`](attr.runtime_interface.html) attribute macro for generating the +//! runtime interfaces. +//! 2. The [`PassByCodec`](derive.PassByCodec.html) derive macro for implementing `PassBy` with `Codec`. +//! 3. The [`PassByEnum`](derive.PassByInner.html) derive macro for implementing `PassBy` with `Enum`. +//! 4. The [`PassByInner`](derive.PassByInner.html) derive macro for implementing `PassBy` with `Inner`. + +extern crate proc_macro; + +use syn::{parse_macro_input, ItemTrait, DeriveInput}; + +mod pass_by; +mod runtime_interface; +mod utils; + +#[proc_macro_attribute] +pub fn runtime_interface( + attrs: proc_macro::TokenStream, + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let trait_def = parse_macro_input!(input as ItemTrait); + let wasm_only = parse_macro_input!(attrs as Option); + + runtime_interface::runtime_interface_impl(trait_def, wasm_only.is_some()) + .unwrap_or_else(|e| e.to_compile_error()) + .into() +} + +#[proc_macro_derive(PassByCodec)] +pub fn pass_by_codec(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as DeriveInput); + pass_by::codec_derive_impl(input).unwrap_or_else(|e| e.to_compile_error()).into() +} + +#[proc_macro_derive(PassByInner)] +pub fn pass_by_inner(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as DeriveInput); + pass_by::inner_derive_impl(input).unwrap_or_else(|e| e.to_compile_error()).into() +} + +#[proc_macro_derive(PassByEnum)] +pub fn pass_by_enum(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as DeriveInput); + pass_by::enum_derive_impl(input).unwrap_or_else(|e| e.to_compile_error()).into() +} diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs b/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs new file mode 100644 index 0000000000000..5e30870a82d2e --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/pass_by/codec.rs @@ -0,0 +1,58 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Derive macro implementation of `PassBy` with the associated type set to `Codec`. +//! +//! It is required that the type implements `Encode` and `Decode` from the `parity-scale-codec` +//! crate. + +use crate::utils::{generate_crate_access, generate_runtime_interface_include}; + +use syn::{DeriveInput, Result, Generics, parse_quote}; + +use quote::quote; + +use proc_macro2::TokenStream; + +/// The derive implementation for `PassBy` with `Codec`. +pub fn derive_impl(mut input: DeriveInput) -> Result { + add_trait_bounds(&mut input.generics); + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let crate_include = generate_runtime_interface_include(); + let crate_ = generate_crate_access(); + let ident = input.ident; + + let res = quote! { + const _: () = { + #crate_include + + impl #impl_generics #crate_::pass_by::PassBy for #ident #ty_generics #where_clause { + type PassBy = #crate_::pass_by::Codec<#ident>; + } + }; + }; + + Ok(res) +} + +/// Add the `codec::Codec` trait bound to every type parameter. +fn add_trait_bounds(generics: &mut Generics) { + let crate_ = generate_crate_access(); + + generics.type_params_mut() + .for_each(|type_param| type_param.bounds.push(parse_quote!(#crate_::codec::Codec))); +} + diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs new file mode 100644 index 0000000000000..5d5b3ae43bdf5 --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/pass_by/enum_.rs @@ -0,0 +1,101 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Derive macro implementation of `PassBy` with the associated type set to `Enum`. +//! +//! Besides `PassBy`, `TryFrom` and `From for u8` are implemented for the type. + +use crate::utils::{generate_crate_access, generate_runtime_interface_include}; + +use syn::{DeriveInput, Result, Data, Fields, Error, Ident}; + +use quote::quote; + +use proc_macro2::{TokenStream, Span}; + +/// The derive implementation for `PassBy` with `Enum`. +pub fn derive_impl(input: DeriveInput) -> Result { + let crate_include = generate_runtime_interface_include(); + let crate_ = generate_crate_access(); + let ident = input.ident; + let enum_fields = get_enum_field_idents(&input.data)? + .enumerate() + .map(|(i, v)| { + let i = i as u8; + + v.map(|v| (quote!(#i => Ok(#ident::#v)), quote!(#ident::#v => #i))) + }) + .collect::>>()?; + let try_from_variants = enum_fields.iter().map(|i| &i.0); + let into_variants = enum_fields.iter().map(|i| &i.1); + + let res = quote! { + const _: () = { + #crate_include + + impl #crate_::pass_by::PassBy for #ident { + type PassBy = #crate_::pass_by::Enum<#ident>; + } + + impl #crate_::sp_std::convert::TryFrom for #ident { + type Error = (); + + fn try_from(inner: u8) -> #crate_::sp_std::result::Result { + match inner { + #( #try_from_variants, )* + _ => Err(()), + } + } + } + + impl From<#ident> for u8 { + fn from(var: #ident) -> u8 { + match var { + #( #into_variants ),* + } + } + } + }; + }; + + Ok(res) +} + +/// Get the enum fields idents of the given `data` object as iterator. +/// +/// Returns an error if the number of variants is greater than `256`, the given `data` is not an +/// enum or a variant is not an unit. +fn get_enum_field_idents<'a>(data: &'a Data) -> Result>> { + match data { + Data::Enum(d) => { + if d.variants.len() <= 256 { + Ok( + d.variants.iter().map(|v| if let Fields::Unit = v.fields { + Ok(&v.ident) + } else { + Err(Error::new( + Span::call_site(), + "`PassByEnum` only supports unit variants.", + )) + }) + ) + } else { + Err(Error::new(Span::call_site(), "`PassByEnum` only supports `256` variants.")) + } + }, + _ => Err(Error::new(Span::call_site(), "`PassByEnum` only supports enums as input type.")) + } +} diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs b/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs new file mode 100644 index 0000000000000..2e1caaa96c61f --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/pass_by/inner.rs @@ -0,0 +1,110 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Derive macro implementation of `PassBy` with the associated type set to `Inner` and of the +//! helper trait `PassByInner`. +//! +//! It is required that the type is a newtype struct, otherwise an error is generated. + +use crate::utils::{generate_crate_access, generate_runtime_interface_include}; + +use syn::{DeriveInput, Result, Generics, parse_quote, Type, Data, Error, Fields, Ident}; + +use quote::quote; + +use proc_macro2::{TokenStream, Span}; + +/// The derive implementation for `PassBy` with `Inner` and `PassByInner`. +pub fn derive_impl(mut input: DeriveInput) -> Result { + add_trait_bounds(&mut input.generics); + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let crate_include = generate_runtime_interface_include(); + let crate_ = generate_crate_access(); + let ident = input.ident; + let (inner_ty, inner_name) = extract_inner_ty_and_name(&input.data)?; + + let access_inner = match inner_name { + Some(ref name) => quote!(self.#name), + None => quote!(self.0), + }; + + let from_inner = match inner_name { + Some(name) => quote!(Self { #name: inner }), + None => quote!(Self(inner)), + }; + + let res = quote! { + const _: () = { + #crate_include + + impl #impl_generics #crate_::pass_by::PassBy for #ident #ty_generics #where_clause { + type PassBy = #crate_::pass_by::Inner<#ident, #inner_ty>; + } + + impl #impl_generics #crate_::pass_by::PassByInner for #ident #ty_generics #where_clause { + type Inner = #inner_ty; + + fn into_inner(self) -> Self::Inner { + #access_inner + } + + fn inner(&self) -> &Self::Inner { + &#access_inner + } + + fn from_inner(inner: Self::Inner) -> Self { + #from_inner + } + } + }; + }; + + Ok(res) +} + +/// Add the `RIType` trait bound to every type parameter. +fn add_trait_bounds(generics: &mut Generics) { + let crate_ = generate_crate_access(); + + generics.type_params_mut() + .for_each(|type_param| type_param.bounds.push(parse_quote!(#crate_::RIType))); +} + +/// Extract the inner type and optional name from given input data. +/// +/// It also checks that the input data is a newtype struct. +fn extract_inner_ty_and_name(data: &Data) -> Result<(Type, Option)> { + if let Data::Struct(ref struct_data) = data { + match struct_data.fields { + Fields::Named(ref named) if named.named.len() == 1 => { + let field = &named.named[0]; + return Ok((field.ty.clone(), field.ident.clone())) + }, + Fields::Unnamed(ref unnamed) if unnamed.unnamed.len() == 1 => { + let field = &unnamed.unnamed[0]; + return Ok((field.ty.clone(), field.ident.clone())) + } + _ => {}, + } + } + + Err( + Error::new( + Span::call_site(), + "Only newtype/one field structs are supported by `PassByInner`!", + ) + ) +} diff --git a/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs b/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs new file mode 100644 index 0000000000000..1466af598ea7c --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/pass_by/mod.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! All the `PassBy*` derive implementations. + +mod codec; +mod enum_; +mod inner; + +pub use self::codec::derive_impl as codec_derive_impl; +pub use enum_::derive_impl as enum_derive_impl; +pub use inner::derive_impl as inner_derive_impl; diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs new file mode 100644 index 0000000000000..55b5eb3a4d616 --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/bare_function_interface.rs @@ -0,0 +1,186 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generates the bare function interface for a given trait definition. +//! +//! The bare functions are the ones that will be called by the user. On the native/host side, these +//! functions directly execute the provided implementation. On the wasm side, these +//! functions will prepare the parameters for the FFI boundary, call the external host function +//! exported into wasm and convert back the result. +//! +//! [`generate`](bare_function_interface::generate) is the entry point for generating for each +//! trait method one bare function. +//! +//! [`function_for_method`](bare_function_interface::function_for_method) generates the bare +//! function per trait method. Each bare function contains both implementations. The implementations +//! are feature-gated, so that one is compiled for the native and the other for the wasm side. + +use crate::utils::{ + generate_crate_access, create_exchangeable_host_function_ident, get_function_arguments, + get_function_argument_names, get_trait_methods, +}; + +use syn::{ + Ident, ItemTrait, TraitItemMethod, FnArg, Signature, Result, spanned::Spanned, parse_quote, +}; + +use proc_macro2::{TokenStream, Span}; + +use quote::{quote, quote_spanned}; + +use std::iter; + +/// Generate one bare function per trait method. The name of the bare function is equal to the name +/// of the trait method. +pub fn generate(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { + let trait_name = &trait_def.ident; + get_trait_methods(trait_def).try_fold(TokenStream::new(), |mut t, m| { + t.extend(function_for_method(trait_name, m, is_wasm_only)?); + Ok(t) + }) +} + +/// Generates the bare function implementation for the given method for the host and wasm side. +fn function_for_method( + trait_name: &Ident, + method: &TraitItemMethod, + is_wasm_only: bool, +) -> Result { + let std_impl = function_std_impl(trait_name, method, is_wasm_only)?; + let no_std_impl = function_no_std_impl(method)?; + + Ok( + quote! { + #std_impl + + #no_std_impl + } + ) +} + +/// Generates the bare function implementation for `cfg(not(feature = "std"))`. +fn function_no_std_impl(method: &TraitItemMethod) -> Result { + let function_name = &method.sig.ident; + let host_function_name = create_exchangeable_host_function_ident(&method.sig.ident); + let args = get_function_arguments(&method.sig); + let arg_names = get_function_argument_names(&method.sig); + let return_value = &method.sig.output; + let attrs = &method.attrs; + + Ok( + quote! { + #[cfg(not(feature = "std"))] + #( #attrs )* + pub fn #function_name( #( #args, )* ) #return_value { + // Call the host function + #host_function_name.get()( #( #arg_names, )* ) + } + } + ) +} + +/// Generates the bare function implementation for `cfg(feature = "std")`. +fn function_std_impl( + trait_name: &Ident, + method: &TraitItemMethod, + is_wasm_only: bool, +) -> Result { + let function_name = &method.sig.ident; + let crate_ = generate_crate_access(); + let args = get_function_arguments(&method.sig).map(FnArg::Typed).chain( + // Add the function context as last parameter when this is a wasm only interface. + iter::from_fn(|| + if is_wasm_only { + Some( + parse_quote!( + mut __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext + ) + ) + } else { + None + } + ).take(1), + ); + let return_value = &method.sig.output; + let attrs = &method.attrs; + // Don't make the function public accessible when this is a wasm only interface. + let vis = if is_wasm_only { quote!() } else { quote!(pub) }; + let call_to_trait = generate_call_to_trait(trait_name, method, is_wasm_only); + + Ok( + quote_spanned! { method.span() => + #[cfg(feature = "std")] + #( #attrs )* + #vis fn #function_name( #( #args, )* ) #return_value { + #call_to_trait + } + } + ) +} + +/// Generate the call to the interface trait. +fn generate_call_to_trait( + trait_name: &Ident, + method: &TraitItemMethod, + is_wasm_only: bool, +) -> TokenStream { + let crate_ = generate_crate_access(); + let method_name = &method.sig.ident; + let expect_msg = format!( + "`{}` called outside of an Externalities-provided environment.", + method_name, + ); + let arg_names = get_function_argument_names(&method.sig); + + if takes_self_argument(&method.sig) { + let instance = if is_wasm_only { + Ident::new("__function_context__", Span::call_site()) + } else { + Ident::new("__externalities__", Span::call_site()) + }; + + let impl_ = quote!( #trait_name::#method_name(&mut #instance, #( #arg_names, )*) ); + + if is_wasm_only { + quote_spanned! { method.span() => #impl_ } + } else { + quote_spanned! { method.span() => + #crate_::with_externalities(|mut #instance| #impl_).expect(#expect_msg) + } + } + } else { + // The name of the trait the interface trait is implemented for + let impl_trait_name = if is_wasm_only { + quote!( #crate_::sp_wasm_interface::FunctionContext ) + } else { + quote!( #crate_::Externalities ) + }; + + quote_spanned! { method.span() => + <&mut dyn #impl_trait_name as #trait_name>::#method_name( + #( #arg_names, )* + ) + } + } +} + +/// Returns if the given `Signature` takes a `self` argument. +fn takes_self_argument(sig: &Signature) -> bool { + match sig.inputs.first() { + Some(FnArg::Receiver(_)) => true, + _ => false, + } +} diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs new file mode 100644 index 0000000000000..42bfe3c712b9e --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/host_function_interface.rs @@ -0,0 +1,415 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generates the extern host functions and the implementation for these host functions. +//! +//! The extern host functions will be called by the bare function interface from the Wasm side. +//! The implementation of these host functions will be called on the host side from the Wasm +//! executor. These implementations call the bare function interface. + +use crate::utils::{ + generate_crate_access, create_host_function_ident, get_function_argument_names, + get_function_argument_types_without_ref, get_function_argument_types_ref_and_mut, + get_function_argument_names_and_types_without_ref, get_trait_methods, get_function_arguments, + get_function_argument_types, create_exchangeable_host_function_ident, +}; + +use syn::{ + ItemTrait, TraitItemMethod, Result, ReturnType, Ident, TraitItem, Pat, Error, Signature, + spanned::Spanned, +}; + +use proc_macro2::{TokenStream, Span}; + +use quote::{quote, ToTokens}; + +use inflector::Inflector; + +use std::iter::{Iterator, self}; + +/// Generate the extern host functions for wasm and the `HostFunctions` struct that provides the +/// implementations for the host functions on the host. +pub fn generate(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { + let trait_name = &trait_def.ident; + let extern_host_function_impls = get_trait_methods(trait_def) + .try_fold(TokenStream::new(), |mut t, m| { + t.extend(generate_extern_host_function(m, trait_name)?); + Ok::<_, Error>(t) + })?; + let exchangeable_host_functions = get_trait_methods(trait_def) + .try_fold(TokenStream::new(), |mut t, m| { + t.extend(generate_exchangeable_host_function(m)?); + Ok::<_, Error>(t) + })?; + let host_functions_struct = generate_host_functions_struct(trait_def, is_wasm_only)?; + + Ok( + quote! { + /// The implementations of the extern host functions. This special implementation module + /// is required to change the extern host functions signature to + /// `unsafe fn name(args) -> ret` to make the function implementations exchangeable. + #[cfg(not(feature = "std"))] + mod extern_host_function_impls { + use super::*; + + #extern_host_function_impls + } + + #exchangeable_host_functions + + #host_functions_struct + } + ) +} + +/// Generate the extern host function for the given method. +fn generate_extern_host_function(method: &TraitItemMethod, trait_name: &Ident) -> Result { + let crate_ = generate_crate_access(); + let args = get_function_arguments(&method.sig); + let arg_types = get_function_argument_types_without_ref(&method.sig); + let arg_types2 = get_function_argument_types_without_ref(&method.sig); + let arg_names = get_function_argument_names(&method.sig); + let arg_names2 = get_function_argument_names(&method.sig); + let arg_names3 = get_function_argument_names(&method.sig); + let function = &method.sig.ident; + let ext_function = create_host_function_ident(&method.sig.ident, trait_name); + let doc_string = format!( + " Default extern host function implementation for [`super::{}`].", + method.sig.ident, + ); + let return_value = &method.sig.output; + + let ffi_return_value = match method.sig.output { + ReturnType::Default => quote!(), + ReturnType::Type(_, ref ty) => quote! { + -> <#ty as #crate_::RIType>::FFIType + }, + }; + + let convert_return_value = match return_value { + ReturnType::Default => quote!(), + ReturnType::Type(_, ref ty) => quote! { + <#ty as #crate_::wasm::FromFFIValue>::from_ffi_value(result) + } + }; + + Ok( + quote! { + #[doc = #doc_string] + pub fn #function ( #( #args ),* ) #return_value { + extern "C" { + /// The extern function. + pub fn #ext_function ( + #( #arg_names: <#arg_types as #crate_::RIType>::FFIType ),* + ) #ffi_return_value; + } + + // Generate all wrapped ffi values. + #( + let #arg_names2 = <#arg_types2 as #crate_::wasm::IntoFFIValue>::into_ffi_value( + &#arg_names2, + ); + )* + + let result = unsafe { #ext_function( #( #arg_names3.get() ),* ) }; + + #convert_return_value + } + } + ) +} + +/// Generate the host exchangeable function for the given method. +fn generate_exchangeable_host_function(method: &TraitItemMethod) -> Result { + let crate_ = generate_crate_access(); + let arg_types = get_function_argument_types(&method.sig); + let function = &method.sig.ident; + let exchangeable_function = create_exchangeable_host_function_ident(&method.sig.ident); + let doc_string = format!(" Exchangeable host function used by [`{}`].", method.sig.ident); + let output = &method.sig.output; + + Ok( + quote! { + #[cfg(not(feature = "std"))] + #[allow(non_upper_case_globals)] + #[doc = #doc_string] + pub static #exchangeable_function : #crate_::wasm::ExchangeableFunction< + fn ( #( #arg_types ),* ) #output + > = #crate_::wasm::ExchangeableFunction::new(extern_host_function_impls::#function); + } + ) +} + +/// Generate the `HostFunctions` struct that implements `wasm-interface::HostFunctions` to provide +/// implementations for the extern host functions. +fn generate_host_functions_struct(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { + let crate_ = generate_crate_access(); + let host_functions = trait_def + .items + .iter() + .filter_map(|i| match i { + TraitItem::Method(ref method) => Some(method), + _ => None, + }) + .map(|m| generate_host_function_implementation(&trait_def.ident, m, is_wasm_only)) + .collect::>>()?; + + Ok( + quote! { + /// Provides implementations for the extern host functions. + #[cfg(feature = "std")] + pub struct HostFunctions; + + #[cfg(feature = "std")] + impl #crate_::sp_wasm_interface::HostFunctions for HostFunctions { + fn host_functions() -> Vec<&'static dyn #crate_::sp_wasm_interface::Function> { + vec![ #( #host_functions ),* ] + } + } + } + ) +} + +/// Generates the host function struct that implements `wasm_interface::Function` and returns a static +/// reference to this struct. +/// +/// When calling from wasm into the host, we will call the `execute` function that calls the native +/// implementation of the function. +fn generate_host_function_implementation( + trait_name: &Ident, + method: &TraitItemMethod, + is_wasm_only: bool, +) -> Result { + let name = create_host_function_ident(&method.sig.ident, trait_name).to_string(); + let struct_name = Ident::new(&name.to_pascal_case(), Span::call_site()); + let crate_ = generate_crate_access(); + let signature = generate_wasm_interface_signature_for_host_function(&method.sig)?; + let wasm_to_ffi_values = generate_wasm_to_ffi_values( + &method.sig, + trait_name, + ).collect::>>()?; + let ffi_to_host_values = generate_ffi_to_host_value(&method.sig).collect::>>()?; + let host_function_call = generate_host_function_call(&method.sig, is_wasm_only); + let into_preallocated_ffi_value = generate_into_preallocated_ffi_value(&method.sig)?; + let convert_return_value = generate_return_value_into_wasm_value(&method.sig); + + Ok( + quote! { + { + struct #struct_name; + + #[allow(unused)] + impl #crate_::sp_wasm_interface::Function for #struct_name { + fn name(&self) -> &str { + #name + } + + fn signature(&self) -> #crate_::sp_wasm_interface::Signature { + #signature + } + + fn execute( + &self, + __function_context__: &mut dyn #crate_::sp_wasm_interface::FunctionContext, + args: &mut dyn Iterator, + ) -> std::result::Result, String> { + #( #wasm_to_ffi_values )* + #( #ffi_to_host_values )* + #host_function_call + #into_preallocated_ffi_value + #convert_return_value + } + } + + &#struct_name as &dyn #crate_::sp_wasm_interface::Function + } + } + ) +} + +/// Generate the `wasm_interface::Signature` for the given host function `sig`. +fn generate_wasm_interface_signature_for_host_function(sig: &Signature) -> Result { + let crate_ = generate_crate_access(); + let return_value = match &sig.output { + ReturnType::Type(_, ty) => + quote! { + Some( <<#ty as #crate_::RIType>::FFIType as #crate_::sp_wasm_interface::IntoValue>::VALUE_TYPE ) + }, + ReturnType::Default => quote!( None ), + }; + let arg_types = get_function_argument_types_without_ref(sig) + .map(|ty| quote! { + <<#ty as #crate_::RIType>::FFIType as #crate_::sp_wasm_interface::IntoValue>::VALUE_TYPE + }); + + Ok( + quote! { + #crate_::sp_wasm_interface::Signature { + args: std::borrow::Cow::Borrowed(&[ #( #arg_types ),* ][..]), + return_value: #return_value, + } + } + ) +} + +/// Generate the code that converts the wasm values given to `HostFunctions::execute` into the FFI +/// values. +fn generate_wasm_to_ffi_values<'a>( + sig: &'a Signature, + trait_name: &'a Ident, +) -> impl Iterator> + 'a { + let crate_ = generate_crate_access(); + let function_name = &sig.ident; + let error_message = format!( + "Number of arguments given to `{}` does not match the expected number of arguments!", + function_name, + ); + + get_function_argument_names_and_types_without_ref(sig) + .map(move |(name, ty)| { + let try_from_error = format!( + "Could not instantiate `{}` from wasm value while executing `{}` from interface `{}`!", + name.to_token_stream(), + function_name, + trait_name, + ); + + let var_name = generate_ffi_value_var_name(&name)?; + + Ok(quote! { + let val = args.next().ok_or_else(|| #error_message)?; + let #var_name = < + <#ty as #crate_::RIType>::FFIType as #crate_::sp_wasm_interface::TryFromValue + >::try_from_value(val).ok_or_else(|| #try_from_error)?; + }) + }) +} + +/// Generate the code to convert the ffi values on the host to the host values using `FromFFIValue`. +fn generate_ffi_to_host_value<'a>( + sig: &'a Signature, +) -> impl Iterator> + 'a { + let mut_access = get_function_argument_types_ref_and_mut(sig); + let crate_ = generate_crate_access(); + + get_function_argument_names_and_types_without_ref(sig) + .zip(mut_access.map(|v| v.and_then(|m| m.1))) + .map(move |((name, ty), mut_access)| { + let ffi_value_var_name = generate_ffi_value_var_name(&name)?; + + Ok( + quote! { + let #mut_access #name = <#ty as #crate_::host::FromFFIValue>::from_ffi_value( + __function_context__, + #ffi_value_var_name, + )?; + } + ) + }) +} + +/// Generate the code to call the host function and the ident that stores the result. +fn generate_host_function_call(sig: &Signature, is_wasm_only: bool) -> TokenStream { + let host_function_name = &sig.ident; + let result_var_name = generate_host_function_result_var_name(&sig.ident); + let ref_and_mut = get_function_argument_types_ref_and_mut(sig).map(|ram| + ram.map(|(vr, vm)| quote!(#vr #vm)) + ); + let names = get_function_argument_names(sig); + + let var_access = names.zip(ref_and_mut) + .map(|(n, ref_and_mut)| { + quote!( #ref_and_mut #n ) + }) + // If this is a wasm only interface, we add the function context as last parameter. + .chain( + iter::from_fn(|| if is_wasm_only { Some(quote!(__function_context__)) } else { None }) + .take(1) + ); + + quote! { + let #result_var_name = #host_function_name ( #( #var_access ),* ); + } +} + +/// Generate the variable name that stores the result of the host function. +fn generate_host_function_result_var_name(name: &Ident) -> Ident { + Ident::new(&format!("{}_result", name), Span::call_site()) +} + +/// Generate the variable name that stores the FFI value. +fn generate_ffi_value_var_name(pat: &Pat) -> Result { + match pat { + Pat::Ident(pat_ident) => { + if let Some(by_ref) = pat_ident.by_ref { + Err(Error::new(by_ref.span(), "`ref` not supported!")) + } else if let Some(sub_pattern) = &pat_ident.subpat { + Err(Error::new(sub_pattern.0.span(), "Not supported!")) + } else { + Ok(Ident::new(&format!("{}_ffi_value", pat_ident.ident), Span::call_site())) + } + } + _ => Err(Error::new(pat.span(), "Not supported as variable name!")) + } +} + +/// Generate code that copies data from the host back to preallocated wasm memory. +/// +/// Any argument that is given as `&mut` is interpreted as preallocated memory and it is expected +/// that the type implements `IntoPreAllocatedFFIValue`. +fn generate_into_preallocated_ffi_value(sig: &Signature) -> Result { + let crate_ = generate_crate_access(); + let ref_and_mut = get_function_argument_types_ref_and_mut(sig).map(|ram| + ram.and_then(|(vr, vm)| vm.map(|v| (vr, v))) + ); + let names_and_types = get_function_argument_names_and_types_without_ref(sig); + + ref_and_mut.zip(names_and_types) + .filter_map(|(ram, (name, ty))| ram.map(|_| (name, ty))) + .map(|(name, ty)| { + let ffi_var_name = generate_ffi_value_var_name(&name)?; + + Ok( + quote! { + <#ty as #crate_::host::IntoPreallocatedFFIValue>::into_preallocated_ffi_value( + #name, + __function_context__, + #ffi_var_name, + )?; + } + ) + }) + .collect() +} + +/// Generate the code that converts the return value into the appropriate wasm value. +fn generate_return_value_into_wasm_value(sig: &Signature) -> TokenStream { + let crate_ = generate_crate_access(); + + match &sig.output { + ReturnType::Default => quote!( Ok(None) ), + ReturnType::Type(_, ty) => { + let result_var_name = generate_host_function_result_var_name(&sig.ident); + + quote! { + <#ty as #crate_::host::IntoFFIValue>::into_ffi_value( + #result_var_name, + __function_context__, + ).map(#crate_::sp_wasm_interface::IntoValue::into_value).map(Some) + } + } + } +} diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs new file mode 100644 index 0000000000000..1c88198d6ea44 --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/mod.rs @@ -0,0 +1,65 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::utils::generate_runtime_interface_include; + +use proc_macro2::{Span, TokenStream}; + +use syn::{Ident, ItemTrait, Result}; + +use inflector::Inflector; + +use quote::quote; + +mod bare_function_interface; +mod host_function_interface; +mod trait_decl_impl; + +/// Custom keywords supported by the `runtime_interface` attribute. +pub mod keywords { + // Custom keyword `wasm_only` that can be given as attribute to [`runtime_interface`]. + syn::custom_keyword!(wasm_only); +} + +/// Implementation of the `runtime_interface` attribute. +/// +/// It expects the trait definition the attribute was put above and if this should be an wasm only +/// interface. +pub fn runtime_interface_impl(trait_def: ItemTrait, is_wasm_only: bool) -> Result { + let bare_functions = bare_function_interface::generate(&trait_def, is_wasm_only)?; + let crate_include = generate_runtime_interface_include(); + let mod_name = Ident::new(&trait_def.ident.to_string().to_snake_case(), Span::call_site()); + let trait_decl_impl = trait_decl_impl::process(&trait_def, is_wasm_only)?; + let host_functions = host_function_interface::generate(&trait_def, is_wasm_only)?; + let vis = trait_def.vis; + let attrs = &trait_def.attrs; + + let res = quote! { + #( #attrs )* + #vis mod #mod_name { + use super::*; + #crate_include + + #bare_functions + + #trait_decl_impl + + #host_functions + } + }; + + Ok(res) +} diff --git a/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs new file mode 100644 index 0000000000000..af71ba3241721 --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/runtime_interface/trait_decl_impl.rs @@ -0,0 +1,146 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Checks the trait declaration, makes the trait declaration module local, removes all method +//! default implementations and implements the trait for `&mut dyn Externalities`. + +use crate::utils::{generate_crate_access, get_function_argument_types_without_ref}; + +use syn::{ + ItemTrait, TraitItemMethod, Result, TraitItem, Error, fold::{self, Fold}, spanned::Spanned, + Visibility, Receiver, Type, Generics, +}; + +use proc_macro2::TokenStream; + +use quote::quote; + +/// Process the given trait definition, by checking that the definition is valid, fold it to the +/// essential definition and implement this essential definition for `dyn Externalities`. +pub fn process(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { + let impl_trait = impl_trait_for_externalities(trait_def, is_wasm_only)?; + let essential_trait_def = ToEssentialTraitDef::convert(trait_def.clone())?; + + Ok( + quote! { + #impl_trait + + #essential_trait_def + } + ) +} + +/// Converts the given trait definition into the essential trait definition without method +/// default implementations and visibility set to inherited. +struct ToEssentialTraitDef { + /// All errors found while doing the conversion. + errors: Vec, +} + +impl ToEssentialTraitDef { + /// Convert the given trait definition to the essential trait definition. + fn convert(trait_def: ItemTrait) -> Result { + let mut folder = ToEssentialTraitDef { + errors: Vec::new(), + }; + + let res = folder.fold_item_trait(trait_def); + + if let Some(first_error) = folder.errors.pop() { + Err( + folder.errors.into_iter().fold(first_error, |mut o, n| { + o.combine(n); + o + }) + ) + } else { + Ok(res) + } + } + + fn push_error(&mut self, span: &S, msg: &str) { + self.errors.push(Error::new(span.span(), msg)); + } + + fn error_on_generic_parameters(&mut self, generics: &Generics) { + if let Some(param) = generics.params.first() { + self.push_error(param, "Generic parameters not supported."); + } + } +} + +impl Fold for ToEssentialTraitDef { + fn fold_trait_item_method(&mut self, mut method: TraitItemMethod) -> TraitItemMethod { + if method.default.take().is_none() { + self.push_error(&method, "Methods need to have an implementation."); + } + + let arg_types = get_function_argument_types_without_ref(&method.sig); + arg_types.filter_map(|ty| + match *ty { + Type::ImplTrait(impl_trait) => Some(impl_trait), + _ => None + } + ).for_each(|invalid| self.push_error(&invalid, "`impl Trait` syntax not supported.")); + + self.error_on_generic_parameters(&method.sig.generics); + + fold::fold_trait_item_method(self, method) + } + + fn fold_item_trait(&mut self, mut trait_def: ItemTrait) -> ItemTrait { + self.error_on_generic_parameters(&trait_def.generics); + + trait_def.vis = Visibility::Inherited; + fold::fold_item_trait(self, trait_def) + } + + fn fold_receiver(&mut self, receiver: Receiver) -> Receiver { + if receiver.reference.is_none() { + self.push_error(&receiver, "Taking `Self` by value is not allowed."); + } + + fold::fold_receiver(self, receiver) + } +} + +/// Implements the given trait definition for `dyn Externalities`. +fn impl_trait_for_externalities(trait_def: &ItemTrait, is_wasm_only: bool) -> Result { + let trait_ = &trait_def.ident; + let crate_ = generate_crate_access(); + let methods = trait_def + .items + .iter() + .filter_map(|i| match i { + TraitItem::Method(ref method) => Some(method), + _ => None, + }); + + let impl_type = if is_wasm_only { + quote!( &mut dyn #crate_::sp_wasm_interface::FunctionContext ) + } else { + quote!( &mut dyn #crate_::Externalities ) + }; + + Ok( + quote! { + #[cfg(feature = "std")] + impl #trait_ for #impl_type { + #( #methods )* + } + } + ) +} diff --git a/primitives/runtime-interface/proc-macro/src/utils.rs b/primitives/runtime-interface/proc-macro/src/utils.rs new file mode 100644 index 0000000000000..15c65f11caf29 --- /dev/null +++ b/primitives/runtime-interface/proc-macro/src/utils.rs @@ -0,0 +1,162 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see + +//! Util function used by this crate. + +use proc_macro2::{TokenStream, Span}; + +use syn::{ + Ident, Error, Signature, Pat, PatType, FnArg, Type, token, TraitItemMethod, ItemTrait, + TraitItem, parse_quote, spanned::Spanned, +}; + +use proc_macro_crate::crate_name; + +use std::env; + +use quote::quote; + +use inflector::Inflector; + +/// Generates the include for the runtime-interface crate. +pub fn generate_runtime_interface_include() -> TokenStream { + if env::var("CARGO_PKG_NAME").unwrap() == "sp-runtime-interface" { + TokenStream::new() + } else { + match crate_name("sp-runtime-interface") { + Ok(crate_name) => { + let crate_name = Ident::new(&crate_name, Span::call_site()); + quote!( + #[doc(hidden)] + extern crate #crate_name as proc_macro_runtime_interface; + ) + }, + Err(e) => { + let err = Error::new(Span::call_site(), &e).to_compile_error(); + quote!( #err ) + } + } + } +} + +/// Generates the access to the `sp-runtime-interface` crate. +pub fn generate_crate_access() -> TokenStream { + if env::var("CARGO_PKG_NAME").unwrap() == "sp-runtime-interface" { + quote!( sp_runtime_interface ) + } else { + quote!( proc_macro_runtime_interface ) + } +} + +/// Create the exchangeable host function identifier for the given function name. +pub fn create_exchangeable_host_function_ident(name: &Ident) -> Ident { + Ident::new(&format!("host_{}", name), Span::call_site()) +} + +/// Create the host function identifier for the given function name. +pub fn create_host_function_ident(name: &Ident, trait_name: &Ident) -> Ident { + Ident::new( + &format!( + "ext_{}_{}_version_1", + trait_name.to_string().to_snake_case(), + name, + ), + Span::call_site(), + ) +} + +/// Returns the function arguments of the given `Signature`, minus any `self` arguments. +pub fn get_function_arguments<'a>(sig: &'a Signature) -> impl Iterator + 'a { + sig.inputs + .iter() + .filter_map(|a| match a { + FnArg::Receiver(_) => None, + FnArg::Typed(pat_type) => Some(pat_type), + }) + .enumerate() + .map(|(i, arg)| { + let mut res = arg.clone(); + if let Pat::Wild(wild) = &*arg.pat { + let ident = Ident::new( + &format!("__runtime_interface_generated_{}_", i), + wild.span(), + ); + + res.pat = Box::new(parse_quote!( #ident )) + } + + res + }) +} + +/// Returns the function argument names of the given `Signature`, minus any `self`. +pub fn get_function_argument_names<'a>(sig: &'a Signature) -> impl Iterator> + 'a { + get_function_arguments(sig).map(|pt| pt.pat) +} + +/// Returns the function argument types of the given `Signature`, minus any `Self` type. +pub fn get_function_argument_types<'a>(sig: &'a Signature) -> impl Iterator> + 'a { + get_function_arguments(sig).map(|pt| pt.ty) +} + +/// Returns the function argument types, minus any `Self` type. If any of the arguments +/// is a reference, the underlying type without the ref is returned. +pub fn get_function_argument_types_without_ref<'a>( + sig: &'a Signature, +) -> impl Iterator> + 'a { + get_function_arguments(sig) + .map(|pt| pt.ty) + .map(|ty| match *ty { + Type::Reference(type_ref) => type_ref.elem, + _ => ty, + }) +} + +/// Returns the function argument names and types, minus any `self`. If any of the arguments +/// is a reference, the underlying type without the ref is returned. +pub fn get_function_argument_names_and_types_without_ref<'a>( + sig: &'a Signature, +) -> impl Iterator, Box)> + 'a { + get_function_arguments(sig) + .map(|pt| match *pt.ty { + Type::Reference(type_ref) => (pt.pat, type_ref.elem), + _ => (pt.pat, pt.ty), + }) +} + +/// Returns the `&`/`&mut` for all function argument types, minus the `self` arg. If a function +/// argument is not a reference, `None` is returned. +pub fn get_function_argument_types_ref_and_mut<'a>( + sig: &'a Signature, +) -> impl Iterator)>> + 'a { + get_function_arguments(sig) + .map(|pt| pt.ty) + .map(|ty| match *ty { + Type::Reference(type_ref) => Some((type_ref.and_token, type_ref.mutability)), + _ => None, + }) +} + +/// Returns an iterator over all trait methods for the given trait definition. +pub fn get_trait_methods<'a>(trait_def: &'a ItemTrait) -> impl Iterator { + trait_def + .items + .iter() + .filter_map(|i| match i { + TraitItem::Method(ref method) => Some(method), + _ => None, + }) +} diff --git a/primitives/runtime-interface/src/host.rs b/primitives/runtime-interface/src/host.rs new file mode 100644 index 0000000000000..2fc272165f33c --- /dev/null +++ b/primitives/runtime-interface/src/host.rs @@ -0,0 +1,62 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Traits required by the runtime interface from the host side. + +use crate::RIType; + +use sp_wasm_interface::{FunctionContext, Result}; + +/// Something that can be converted into a ffi value. +pub trait IntoFFIValue: RIType { + /// Convert `self` into a ffi value. + fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result; +} + +/// Something that can be converted into a preallocated ffi value. +/// +/// Every type parameter that should be given as `&mut` into a runtime interface function, needs +/// to implement this trait. After executing the host implementation of the runtime interface +/// function, the value is copied into the preallocated wasm memory. +/// +/// This should only be used for types which have a fixed size, like slices. Other types like a vec +/// do not work with this interface, as we can not call into wasm to reallocate memory. So, this +/// trait should be implemented carefully. +pub trait IntoPreallocatedFFIValue: RIType { + /// As `Self` can be an unsized type, it needs to be represented by a sized type at the host. + /// This `SelfInstance` is the sized type. + type SelfInstance; + + /// Convert `self_instance` into the given preallocated ffi value. + fn into_preallocated_ffi_value( + self_instance: Self::SelfInstance, + context: &mut dyn FunctionContext, + allocated: Self::FFIType, + ) -> Result<()>; +} + +/// Something that can be created from a ffi value. +pub trait FromFFIValue: RIType { + /// As `Self` can be an unsized type, it needs to be represented by a sized type at the host. + /// This `SelfInstance` is the sized type. + type SelfInstance; + + /// Create `SelfInstance` from the given + fn from_ffi_value( + context: &mut dyn FunctionContext, + arg: Self::FFIType, + ) -> Result; +} diff --git a/primitives/runtime-interface/src/impls.rs b/primitives/runtime-interface/src/impls.rs new file mode 100644 index 0000000000000..23be7fd35adfc --- /dev/null +++ b/primitives/runtime-interface/src/impls.rs @@ -0,0 +1,473 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Provides implementations for the runtime interface traits. + +use crate::{ + RIType, Pointer, pass_by::{PassBy, Codec, Inner, PassByInner}, + util::{unpack_ptr_and_len, pack_ptr_and_len}, +}; +#[cfg(feature = "std")] +use crate::host::*; +#[cfg(not(feature = "std"))] +use crate::wasm::*; + +#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))] +use static_assertions::assert_eq_size; + +#[cfg(feature = "std")] +use sp_wasm_interface::{FunctionContext, Result}; + +use codec::{Encode, Decode}; + +use sp_std::{any::TypeId, mem, vec::Vec}; + +#[cfg(feature = "std")] +use sp_std::borrow::Cow; + +#[cfg(not(feature = "std"))] +use sp_std::{slice, boxed::Box}; + +// Make sure that our assumptions for storing a pointer + its size in `u64` is valid. +#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))] +assert_eq_size!(usize, u32); +#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))] +assert_eq_size!(*const u8, u32); + +/// Implement the traits for the given primitive traits. +macro_rules! impl_traits_for_primitives { + ( + $( + $rty:ty, $fty:ty, + )* + ) => { + $( + /// The type is passed directly. + impl RIType for $rty { + type FFIType = $fty; + } + + #[cfg(not(feature = "std"))] + impl IntoFFIValue for $rty { + type Owned = (); + + fn into_ffi_value(&self) -> WrappedFFIValue<$fty> { + (*self as $fty).into() + } + } + + #[cfg(not(feature = "std"))] + impl FromFFIValue for $rty { + fn from_ffi_value(arg: $fty) -> $rty { + arg as $rty + } + } + + #[cfg(feature = "std")] + impl FromFFIValue for $rty { + type SelfInstance = $rty; + + fn from_ffi_value(_: &mut dyn FunctionContext, arg: $fty) -> Result<$rty> { + Ok(arg as $rty) + } + } + + #[cfg(feature = "std")] + impl IntoFFIValue for $rty { + fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result<$fty> { + Ok(self as $fty) + } + } + )* + } +} + +impl_traits_for_primitives! { + u8, u8, + u16, u16, + u32, u32, + u64, u64, + i8, i8, + i16, i16, + i32, i32, + i64, i64, +} + +/// `bool` is passed as `u8`. +/// +/// - `1`: true +/// - `0`: false +impl RIType for bool { + type FFIType = u8; +} + +#[cfg(not(feature = "std"))] +impl IntoFFIValue for bool { + type Owned = (); + + fn into_ffi_value(&self) -> WrappedFFIValue { + if *self { 1 } else { 0 }.into() + } +} + +#[cfg(not(feature = "std"))] +impl FromFFIValue for bool { + fn from_ffi_value(arg: u8) -> bool { + arg == 1 + } +} + +#[cfg(feature = "std")] +impl FromFFIValue for bool { + type SelfInstance = bool; + + fn from_ffi_value(_: &mut dyn FunctionContext, arg: u8) -> Result { + Ok(arg == 1) + } +} + +#[cfg(feature = "std")] +impl IntoFFIValue for bool { + fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result { + Ok(if self { 1 } else { 0 }) + } +} + +/// The type is passed as `u64`. +/// +/// The `u64` value is build by `length 32bit << 32 | pointer 32bit` +/// +/// If `T == u8` the length and the pointer are taken directly from the `Self`. +/// Otherwise `Self` is encoded and the length and the pointer are taken from the encoded vector. +impl RIType for Vec { + type FFIType = u64; +} + +#[cfg(feature = "std")] +impl IntoFFIValue for Vec { + fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result { + let vec: Cow<'_, [u8]> = if TypeId::of::() == TypeId::of::() { + unsafe { Cow::Borrowed(mem::transmute(&self[..])) } + } else { + Cow::Owned(self.encode()) + }; + + let ptr = context.allocate_memory(vec.as_ref().len() as u32)?; + context.write_memory(ptr, &vec)?; + + Ok(pack_ptr_and_len(ptr.into(), vec.len() as u32)) + } +} + +#[cfg(feature = "std")] +impl FromFFIValue for Vec { + type SelfInstance = Vec; + + fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result> { + <[T] as FromFFIValue>::from_ffi_value(context, arg) + } +} + +#[cfg(not(feature = "std"))] +impl IntoFFIValue for Vec { + type Owned = Vec; + + fn into_ffi_value(&self) -> WrappedFFIValue> { + self[..].into_ffi_value() + } +} + +#[cfg(not(feature = "std"))] +impl FromFFIValue for Vec { + fn from_ffi_value(arg: u64) -> Vec { + let (ptr, len) = unpack_ptr_and_len(arg); + let len = len as usize; + + if TypeId::of::() == TypeId::of::() { + unsafe { mem::transmute(Vec::from_raw_parts(ptr as *mut u8, len, len)) } + } else { + let slice = unsafe { slice::from_raw_parts(ptr as *const u8, len) }; + Self::decode(&mut &slice[..]).expect("Host to wasm values are encoded correctly; qed") + } + } +} + +/// The type is passed as `u64`. +/// +/// The `u64` value is build by `length 32bit << 32 | pointer 32bit` +/// +/// If `T == u8` the length and the pointer are taken directly from the `Self`. +/// Otherwise `Self` is encoded and the length and the pointer are taken from the encoded vector. +impl RIType for [T] { + type FFIType = u64; +} + +#[cfg(feature = "std")] +impl FromFFIValue for [T] { + type SelfInstance = Vec; + + fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result> { + let (ptr, len) = unpack_ptr_and_len(arg); + + let vec = context.read_memory(Pointer::new(ptr), len)?; + + if TypeId::of::() == TypeId::of::() { + Ok(unsafe { mem::transmute(vec) }) + } else { + Ok(Vec::::decode(&mut &vec[..]).expect("Wasm to host values are encoded correctly; qed")) + } + } +} + +#[cfg(feature = "std")] +impl IntoPreallocatedFFIValue for [u8] { + type SelfInstance = Vec; + + fn into_preallocated_ffi_value( + self_instance: Self::SelfInstance, + context: &mut dyn FunctionContext, + allocated: u64, + ) -> Result<()> { + let (ptr, len) = unpack_ptr_and_len(allocated); + + if (len as usize) < self_instance.len() { + Err( + format!( + "Preallocated buffer is not big enough (given {} vs needed {})!", + len, + self_instance.len() + ) + ) + } else { + context.write_memory(Pointer::new(ptr), &self_instance) + } + } +} + +#[cfg(not(feature = "std"))] +impl IntoFFIValue for [T] { + type Owned = Vec; + + fn into_ffi_value(&self) -> WrappedFFIValue> { + if TypeId::of::() == TypeId::of::() { + let slice = unsafe { mem::transmute::<&[T], &[u8]>(self) }; + pack_ptr_and_len(slice.as_ptr() as u32, slice.len() as u32).into() + } else { + let data = self.encode(); + let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32); + (ffi_value, data).into() + } + } +} + +/// Implement the traits for the `[u8; N]` arrays, where `N` is the input to this macro. +macro_rules! impl_traits_for_arrays { + ( + $( + $n:expr + ),* + $(,)? + ) => { + $( + /// The type is passed as `u32`. + /// + /// The `u32` is the pointer to the array. + impl RIType for [u8; $n] { + type FFIType = u32; + } + + #[cfg(not(feature = "std"))] + impl IntoFFIValue for [u8; $n] { + type Owned = (); + + fn into_ffi_value(&self) -> WrappedFFIValue { + (self.as_ptr() as u32).into() + } + } + + #[cfg(not(feature = "std"))] + impl FromFFIValue for [u8; $n] { + fn from_ffi_value(arg: u32) -> [u8; $n] { + let mut res = [0u8; $n]; + res.copy_from_slice(unsafe { slice::from_raw_parts(arg as *const u8, $n) }); + + // Make sure we free the pointer. + let _ = unsafe { Box::from_raw(arg as *mut u8) }; + + res + } + } + + #[cfg(feature = "std")] + impl FromFFIValue for [u8; $n] { + type SelfInstance = [u8; $n]; + + fn from_ffi_value(context: &mut dyn FunctionContext, arg: u32) -> Result<[u8; $n]> { + let data = context.read_memory(Pointer::new(arg), $n)?; + let mut res = [0u8; $n]; + res.copy_from_slice(&data); + Ok(res) + } + } + + #[cfg(feature = "std")] + impl IntoFFIValue for [u8; $n] { + fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result { + let addr = context.allocate_memory($n)?; + context.write_memory(addr, &self)?; + Ok(addr.into()) + } + } + + #[cfg(feature = "std")] + impl IntoPreallocatedFFIValue for [u8; $n] { + type SelfInstance = [u8; $n]; + + fn into_preallocated_ffi_value( + self_instance: Self::SelfInstance, + context: &mut dyn FunctionContext, + allocated: u32, + ) -> Result<()> { + context.write_memory(Pointer::new(allocated), &self_instance) + } + } + )* + } +} + +impl_traits_for_arrays! { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, +} + +impl PassBy for sp_std::result::Result { + type PassBy = Codec; +} + +impl PassBy for Option { + type PassBy = Codec; +} + +/// Implement `PassBy` with `Inner` for the given fixed sized hash types. +macro_rules! for_primitive_types { + { $( $hash:ident $n:expr ),* $(,)? } => { + $( + impl PassBy for primitive_types::$hash { + type PassBy = Inner; + } + + impl PassByInner for primitive_types::$hash { + type Inner = [u8; $n]; + + fn inner(&self) -> &Self::Inner { + &self.0 + } + + fn into_inner(self) -> Self::Inner { + self.0 + } + + fn from_inner(inner: Self::Inner) -> Self { + Self(inner) + } + } + )* + } +} + +for_primitive_types! { + H160 20, + H256 32, + H512 64, +} + +/// The type is passed as `u64`. +/// +/// The `u64` value is build by `length 32bit << 32 | pointer 32bit` +/// +/// The length and the pointer are taken directly from the `Self`. +impl RIType for str { + type FFIType = u64; +} + +#[cfg(feature = "std")] +impl FromFFIValue for str { + type SelfInstance = String; + + fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result { + let (ptr, len) = unpack_ptr_and_len(arg); + + let vec = context.read_memory(Pointer::new(ptr), len)?; + + // The data is valid utf8, as it is stored as `&str` in wasm. + String::from_utf8(vec).map_err(|_| "Invalid utf8 data provided".into()) + } +} + +#[cfg(not(feature = "std"))] +impl IntoFFIValue for str { + type Owned = (); + + fn into_ffi_value(&self) -> WrappedFFIValue { + let bytes = self.as_bytes(); + pack_ptr_and_len(bytes.as_ptr() as u32, bytes.len() as u32).into() + } +} + +#[cfg(feature = "std")] +impl RIType for Pointer { + type FFIType = u32; +} + +/// The type is passed as `u32`. +#[cfg(not(feature = "std"))] +impl RIType for Pointer { + type FFIType = u32; +} + +#[cfg(not(feature = "std"))] +impl IntoFFIValue for Pointer { + type Owned = (); + + fn into_ffi_value(&self) -> WrappedFFIValue { + (*self as u32).into() + } +} + +#[cfg(not(feature = "std"))] +impl FromFFIValue for Pointer { + fn from_ffi_value(arg: u32) -> Self { + arg as _ + } +} + +#[cfg(feature = "std")] +impl FromFFIValue for Pointer { + type SelfInstance = Self; + + fn from_ffi_value(_: &mut dyn FunctionContext, arg: u32) -> Result { + Ok(Pointer::new(arg)) + } +} + +#[cfg(feature = "std")] +impl IntoFFIValue for Pointer { + fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result { + Ok(self.into()) + } +} diff --git a/primitives/runtime-interface/src/lib.rs b/primitives/runtime-interface/src/lib.rs new file mode 100644 index 0000000000000..330b1699a609f --- /dev/null +++ b/primitives/runtime-interface/src/lib.rs @@ -0,0 +1,267 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate runtime interface +//! +//! This crate provides types, traits and macros around runtime interfaces. A runtime interface is +//! a fixed interface between a Substrate runtime and a Substrate node. For a native runtime the +//! interface maps to a direct function call of the implementation. For a wasm runtime the interface +//! maps to an external function call. These external functions are exported by the wasm executor +//! and they map to the same implementation as the native calls. +//! +//! # Using a type in a runtime interface +//! +//! Any type that should be used in a runtime interface as argument or return value needs to +//! implement [`RIType`]. The associated type `FFIType` is the type that is used in the FFI +//! function to represent the actual type. For example `[T]` is represented by an `u64`. The slice +//! pointer and the length will be mapped to an `u64` value. For more information, see the +//! implementation of [`RIType`] for [`T`]. The FFI function definition is used when calling from +//! the wasm runtime into the node. +//! +//! Traits are used to convert from a type to the corresponding [`RIType::FFIType`]. +//! Depending on where and how a type should be used in a function signature, a combination of the +//! following traits need to be implemented: +//! +//! 1. Pass as function argument: [`wasm::IntoFFIValue`] and [`host::FromFFIValue`] +//! 2. As function return value: [`wasm::FromFFIValue`] and [`host::IntoFFIValue`] +//! 3. Pass as mutable function argument: [`host::IntoPreallocatedFFIValue`] +//! +//! The traits are implemented for most of the common types like `[T]`, `Vec`, arrays and +//! primitive types. +//! +//! For custom types, we provide the [`PassBy`](pass_by::PassBy) trait and strategies that define +//! how a type is passed between the wasm runtime and the node. Each strategy also provides a derive +//! macro to simplify the implementation. +//! +//! # Performance +//! +//! To not waste any more performance when calling into the node, not all types are SCALE encoded +//! when being passed as arguments between the wasm runtime and the node. For most types that +//! are raw bytes like `Vec`, `[u8]` or `[u8; N]` we pass them directly, without SCALE encoding +//! them in front of. The implementation of [`RIType`] each type provides more information on how +//! the data is passed. +//! +//! # Declaring a runtime interface +//! +//! Declaring a runtime interface is similar to declaring a trait in Rust: +//! +//! ``` +//! #[sp_runtime_interface::runtime_interface] +//! trait RuntimeInterface { +//! fn some_function(value: &[u8]) -> bool { +//! value.iter().all(|v| *v > 125) +//! } +//! } +//! ``` +//! +//! For more information on declaring a runtime interface, see +//! [`#[runtime_interface]`](attr.runtime_interface.html). + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate self as sp_runtime_interface; + +#[doc(hidden)] +#[cfg(feature = "std")] +pub use sp_wasm_interface; + +#[doc(hidden)] +pub use sp_std; + +/// Attribute macro for transforming a trait declaration into a runtime interface. +/// +/// A runtime interface is a fixed interface between a Substrate compatible runtime and the native +/// node. This interface is callable from a native and a wasm runtime. The macro will generate the +/// corresponding code for the native implementation and the code for calling from the wasm +/// side to the native implementation. +/// +/// The macro expects the runtime interface declaration as trait declaration: +/// +/// ``` +/// # use sp_runtime_interface::runtime_interface; +/// +/// #[runtime_interface] +/// trait Interface { +/// /// A function that can be called from native/wasm. +/// /// +/// /// The implementation given to this function is only compiled on native. +/// fn call_some_complex_code(data: &[u8]) -> Vec { +/// // Here you could call some rather complex code that only compiles on native or +/// // is way faster in native than executing it in wasm. +/// Vec::new() +/// } +/// +/// /// A function can take a `&self` or `&mut self` argument to get access to the +/// /// `Externalities`. (The generated method does not require +/// /// this argument, so the function can be called just with the `optional` argument) +/// fn set_or_clear(&mut self, optional: Option>) { +/// match optional { +/// Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value), +/// None => self.clear_storage(&[1, 2, 3, 4]), +/// } +/// } +/// } +/// ``` +/// +/// +/// The given example will generate roughly the following code for native: +/// +/// ``` +/// // The name of the trait is converted to snake case and used as mod name. +/// // +/// // Be aware that this module is not `public`, the visibility of the module is determined based +/// // on the visibility of the trait declaration. +/// mod interface { +/// trait Interface { +/// fn call_some_complex_code(data: &[u8]) -> Vec; +/// fn set_or_clear(&mut self, optional: Option>); +/// } +/// +/// impl Interface for &mut dyn sp_externalities::Externalities { +/// fn call_some_complex_code(data: &[u8]) -> Vec { Vec::new() } +/// fn set_or_clear(&mut self, optional: Option>) { +/// match optional { +/// Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value), +/// None => self.clear_storage(&[1, 2, 3, 4]), +/// } +/// } +/// } +/// +/// pub fn call_some_complex_code(data: &[u8]) -> Vec { +/// <&mut dyn sp_externalities::Externalities as Interface>::call_some_complex_code(data) +/// } +/// +/// pub fn set_or_clear(optional: Option>) { +/// sp_externalities::with_externalities(|mut ext| Interface::set_or_clear(&mut ext, optional)) +/// .expect("`set_or_clear` called outside of an Externalities-provided environment.") +/// } +/// +/// /// This type implements the `HostFunctions` trait (from `sp-wasm-interface`) and +/// /// provides the host implementation for the wasm side. The host implementation converts the +/// /// arguments from wasm to native and calls the corresponding native function. +/// /// +/// /// This type needs to be passed to the wasm executor, so that the host functions will be +/// /// registered in the executor. +/// pub struct HostFunctions; +/// } +/// ``` +/// +/// +/// The given example will generate roughly the following code for wasm: +/// +/// ``` +/// mod interface { +/// mod extern_host_functions_impls { +/// extern "C" { +/// /// Every function is exported as `ext_TRAIT_NAME_FUNCTION_NAME_version_VERSION`. +/// /// +/// /// `TRAIT_NAME` is converted into snake case. +/// /// +/// /// The type for each argument of the exported function depends on +/// /// `::FFIType`. +/// /// +/// /// `data` holds the pointer and the length to the `[u8]` slice. +/// pub fn ext_Interface_call_some_complex_code_version_1(data: u64) -> u64; +/// /// `optional` holds the pointer and the length of the encoded value. +/// pub fn ext_Interface_set_or_clear_version_1(optional: u64); +/// } +/// } +/// +/// /// The type is actually `ExchangeableFunction` (from `sp-runtime-interface`). +/// /// +/// /// This can be used to replace the implementation of the `call_some_complex_code` function. +/// /// Instead of calling into the host, the callee will automatically call the other +/// /// implementation. +/// /// +/// /// To replace the implementation: +/// /// +/// /// `host_call_some_complex_code.replace_implementation(some_other_impl)` +/// pub static host_call_some_complex_code: () = (); +/// pub static host_set_or_clear: () = (); +/// +/// pub fn call_some_complex_code(data: &[u8]) -> Vec { +/// // This is the actual call: `host_call_some_complex_code.get()(data)` +/// // +/// // But that does not work for several reasons in this example, so we just return an +/// // empty vector. +/// Vec::new() +/// } +/// +/// pub fn set_or_clear(optional: Option>) { +/// // Same as above +/// } +/// } +/// ``` +/// +/// # Argument types +/// +/// The macro supports any kind of argument type, as long as it implements [`RIType`] and the +/// required `FromFFIValue`/`IntoFFIValue`. The macro will convert each +/// argument to the corresponding FFI representation and will call into the host using this FFI +/// representation. On the host each argument is converted back to the native representation and +/// the native implementation is called. Any return value is handled in the same way. +/// +/// # Wasm only interfaces +/// +/// Some interfaces are only required from within the wasm runtime e.g. the allocator interface. +/// To support this, the macro can be called like `#[runtime_interface(wasm_only)]`. This instructs +/// the macro to make two significant changes to the generated code: +/// +/// 1. The generated functions are not callable from the native side. +/// 2. The trait as shown above is not implemented for `Externalities` and is instead implemented +/// for `FunctionExecutor` (from `sp-wasm-interface`). +pub use sp_runtime_interface_proc_macro::runtime_interface; + +#[doc(hidden)] +#[cfg(feature = "std")] +pub use sp_externalities::{ + set_and_run_with_externalities, with_externalities, Externalities, ExternalitiesExt, ExtensionStore, +}; + +#[doc(hidden)] +pub use codec; + +pub(crate) mod impls; +#[cfg(feature = "std")] +pub mod host; +#[cfg(not(feature = "std"))] +pub mod wasm; +pub mod pass_by; + +mod util; + +pub use util::unpack_ptr_and_len; + +/// Something that can be used by the runtime interface as type to communicate between wasm and the +/// host. +/// +/// Every type that should be used in a runtime interface function signature needs to implement +/// this trait. +pub trait RIType { + /// The ffi type that is used to represent `Self`. + #[cfg(feature = "std")] + type FFIType: sp_wasm_interface::IntoValue + sp_wasm_interface::TryFromValue; + #[cfg(not(feature = "std"))] + type FFIType; +} + +/// A pointer that can be used in a runtime interface function signature. +#[cfg(not(feature = "std"))] +pub type Pointer = *mut T; + +/// A pointer that can be used in a runtime interface function signature. +#[cfg(feature = "std")] +pub type Pointer = sp_wasm_interface::Pointer; diff --git a/primitives/runtime-interface/src/pass_by.rs b/primitives/runtime-interface/src/pass_by.rs new file mode 100644 index 0000000000000..81da2fe7e6a3a --- /dev/null +++ b/primitives/runtime-interface/src/pass_by.rs @@ -0,0 +1,447 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Provides the [`PassBy`](pass_by::PassBy) trait to simplify the implementation of the +//! runtime interface traits for custom types. +//! +//! [`Codec`](pass_by::Codec), [`Inner`](pass_by::Inner) and [`Enum`](pass_by::Enum) are the +//! provided strategy implementations. + +use crate::{RIType, util::{unpack_ptr_and_len, pack_ptr_and_len}}; + +#[cfg(feature = "std")] +use crate::host::*; +#[cfg(not(feature = "std"))] +use crate::wasm::*; + +#[cfg(feature = "std")] +use sp_wasm_interface::{FunctionContext, Pointer, Result}; + +use sp_std::{marker::PhantomData, convert::TryFrom}; + +#[cfg(not(feature = "std"))] +use sp_std::{slice, vec::Vec}; + +/// Derive macro for implementing [`PassBy`] with the [`Codec`] strategy. +/// +/// This requires that the type implements [`Encode`](codec::Encode) and [`Decode`](codec::Decode) +/// from `parity-scale-codec`. +/// +/// # Example +/// +/// ``` +/// # use sp_runtime_interface::pass_by::PassByCodec; +/// # use codec::{Encode, Decode}; +/// #[derive(PassByCodec, Encode, Decode)] +/// struct EncodableType { +/// name: Vec, +/// param: u32, +/// } +/// ``` +pub use sp_runtime_interface_proc_macro::PassByCodec; + +/// Derive macro for implementing [`PassBy`] with the [`Inner`] strategy. +/// +/// Besides implementing [`PassBy`], this derive also implements the helper trait [`PassByInner`]. +/// +/// The type is required to be a struct with just one field. The field type needs to implement +/// the required traits to pass it between the wasm and the native side. (See the runtime interface +/// crate for more information about these traits.) +/// +/// # Example +/// +/// ``` +/// # use sp_runtime_interface::pass_by::PassByInner; +/// #[derive(PassByInner)] +/// struct Data([u8; 32]); +/// ``` +/// +/// ``` +/// # use sp_runtime_interface::pass_by::PassByInner; +/// #[derive(PassByInner)] +/// struct Data { +/// data: [u8; 32], +/// } +/// ``` +pub use sp_runtime_interface_proc_macro::PassByInner; + +/// Derive macro for implementing [`PassBy`] with the [`Enum`] strategy. +/// +/// Besides implementing [`PassBy`], this derive also implements `TryFrom` and +/// `From for u8` for the type. +/// +/// The type is required to be an enum with only unit variants and at maximum `256` variants. Also +/// it is required that the type implements `Copy`. +/// +/// # Example +/// +/// ``` +/// # use sp_runtime_interface::pass_by::PassByEnum; +/// #[derive(PassByEnum, Copy, Clone)] +/// enum Data { +/// Okay, +/// NotOkay, +/// // This will not work with the derive. +/// //Why(u32), +/// } +/// ``` +pub use sp_runtime_interface_proc_macro::PassByEnum; + +/// Something that should be passed between wasm and the host using the given strategy. +/// +/// See [`Codec`], [`Inner`] or [`Enum`] for more information about the provided strategies. +pub trait PassBy: Sized { + /// The strategy that should be used to pass the type. + type PassBy: PassByImpl; +} + +/// Something that provides a strategy for passing a type between wasm and the host. +/// +/// This trait exposes the same functionality as [`crate::host::IntoFFIValue`] and +/// [`crate::host::FromFFIValue`] to delegate the implementation for a type to a different type. +/// +/// This trait is used for the host implementation. +#[cfg(feature = "std")] +pub trait PassByImpl: RIType { + /// Convert the given instance to the ffi value. + /// + /// For more information see: [`crate::host::IntoFFIValue::into_ffi_value`] + fn into_ffi_value( + instance: T, + context: &mut dyn FunctionContext, + ) -> Result; + + /// Create `T` from the given ffi value. + /// + /// For more information see: [`crate::host::FromFFIValue::from_ffi_value`] + fn from_ffi_value( + context: &mut dyn FunctionContext, + arg: Self::FFIType, + ) -> Result; +} + +/// Something that provides a strategy for passing a type between wasm and the host. +/// +/// This trait exposes the same functionality as [`crate::wasm::IntoFFIValue`] and +/// [`crate::wasm::FromFFIValue`] to delegate the implementation for a type to a different type. +/// +/// This trait is used for the wasm implementation. +#[cfg(not(feature = "std"))] +pub trait PassByImpl: RIType { + /// The owned rust type that is stored with the ffi value in [`crate::wasm::WrappedFFIValue`]. + type Owned; + + /// Convert the given `instance` into [`crate::wasm::WrappedFFIValue`]. + /// + /// For more information see: [`crate::wasm::IntoFFIValue::into_ffi_value`] + fn into_ffi_value(instance: &T) -> WrappedFFIValue; + + /// Create `T` from the given ffi value. + /// + /// For more information see: [`crate::wasm::FromFFIValue::from_ffi_value`] + fn from_ffi_value(arg: Self::FFIType) -> T; +} + +impl RIType for T { + type FFIType = ::FFIType; +} + +#[cfg(feature = "std")] +impl IntoFFIValue for T { + fn into_ffi_value( + self, + context: &mut dyn FunctionContext, + ) -> Result<::FFIType> { + T::PassBy::into_ffi_value(self, context) + } +} + +#[cfg(feature = "std")] +impl FromFFIValue for T { + type SelfInstance = Self; + + fn from_ffi_value( + context: &mut dyn FunctionContext, + arg: ::FFIType, + ) -> Result { + T::PassBy::from_ffi_value(context, arg) + } +} + +#[cfg(not(feature = "std"))] +impl IntoFFIValue for T { + type Owned = >::Owned; + + fn into_ffi_value(&self) -> WrappedFFIValue<::FFIType, Self::Owned> { + T::PassBy::into_ffi_value(self) + } +} + +#[cfg(not(feature = "std"))] +impl FromFFIValue for T { + fn from_ffi_value(arg: ::FFIType) -> Self { + T::PassBy::from_ffi_value(arg) + } +} + +/// The implementation of the pass by codec strategy. This strategy uses a SCALE encoded +/// representation of the type between wasm and the host. +/// +/// Use this type as associated type for [`PassBy`] to implement this strategy for a type. +/// +/// This type expects the type that wants to implement this strategy as generic parameter. +/// +/// [`PassByCodec`](derive.PassByCodec.html) is a derive macro to implement this strategy. +/// +/// # Example +/// ``` +/// # use sp_runtime_interface::pass_by::{PassBy, Codec}; +/// #[derive(codec::Encode, codec::Decode)] +/// struct Test; +/// +/// impl PassBy for Test { +/// type PassBy = Codec; +/// } +/// ``` +pub struct Codec(PhantomData); + +#[cfg(feature = "std")] +impl PassByImpl for Codec { + fn into_ffi_value( + instance: T, + context: &mut dyn FunctionContext, + ) -> Result { + let vec = instance.encode(); + let ptr = context.allocate_memory(vec.len() as u32)?; + context.write_memory(ptr, &vec)?; + + Ok(pack_ptr_and_len(ptr.into(), vec.len() as u32)) + } + + fn from_ffi_value( + context: &mut dyn FunctionContext, + arg: Self::FFIType, + ) -> Result { + let (ptr, len) = unpack_ptr_and_len(arg); + let vec = context.read_memory(Pointer::new(ptr), len)?; + T::decode(&mut &vec[..]) + .map_err(|e| format!("Could not decode value from wasm: {}", e.what())) + } +} + +#[cfg(not(feature = "std"))] +impl PassByImpl for Codec { + type Owned = Vec; + + fn into_ffi_value(instance: &T) -> WrappedFFIValue { + let data = instance.encode(); + let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32); + (ffi_value, data).into() + } + + fn from_ffi_value(arg: Self::FFIType) -> T { + let (ptr, len) = unpack_ptr_and_len(arg); + let len = len as usize; + + let slice = unsafe { slice::from_raw_parts(ptr as *const u8, len) }; + T::decode(&mut &slice[..]).expect("Host to wasm values are encoded correctly; qed") + } +} + +/// The type is passed as `u64`. +/// +/// The `u64` value is build by `length 32bit << 32 | pointer 32bit` +/// +/// `Self` is encoded and the length and the pointer are taken from the encoded vector. +impl RIType for Codec { + type FFIType = u64; +} + +/// Trait that needs to be implemented by a type that should be passed between wasm and the host, +/// by using the inner type. See [`Inner`] for more information. +pub trait PassByInner: Sized { + /// The inner type that is wrapped by `Self`. + type Inner: RIType; + + /// Consumes `self` and returns the inner type. + fn into_inner(self) -> Self::Inner; + + /// Returns the reference to the inner type. + fn inner(&self) -> &Self::Inner; + + /// Construct `Self` from the given `inner`. + fn from_inner(inner: Self::Inner) -> Self; +} + +/// The implementation of the pass by inner type strategy. The type that uses this strategy will be +/// passed between wasm and the host by using the wrapped inner type. So, this strategy is only +/// usable by newtype structs. +/// +/// Use this type as associated type for [`PassBy`] to implement this strategy for a type. Besides +/// that the `PassByInner` trait need to be implemented as well. +/// +/// This type expects the type that wants to use this strategy as generic parameter `T` and the +/// inner type as generic parameter `I`. +/// +/// [`PassByInner`](derive.PassByInner.html) is a derive macro to implement this strategy. +/// +/// # Example +/// ``` +/// # use sp_runtime_interface::pass_by::{PassBy, Inner, PassByInner}; +/// struct Test([u8; 32]); +/// +/// impl PassBy for Test { +/// type PassBy = Inner; +/// } +/// +/// impl PassByInner for Test { +/// type Inner = [u8; 32]; +/// +/// fn into_inner(self) -> [u8; 32] { +/// self.0 +/// } +/// fn inner(&self) -> &[u8; 32] { +/// &self.0 +/// } +/// fn from_inner(inner: [u8; 32]) -> Self { +/// Self(inner) +/// } +/// } +/// ``` +pub struct Inner, I: RIType>(PhantomData<(T, I)>); + +#[cfg(feature = "std")] +impl, I: RIType> PassByImpl for Inner + where I: IntoFFIValue + FromFFIValue +{ + fn into_ffi_value( + instance: T, + context: &mut dyn FunctionContext, + ) -> Result { + instance.into_inner().into_ffi_value(context) + } + + fn from_ffi_value( + context: &mut dyn FunctionContext, + arg: Self::FFIType, + ) -> Result { + I::from_ffi_value(context, arg).map(T::from_inner) + } +} + +#[cfg(not(feature = "std"))] +impl, I: RIType> PassByImpl for Inner + where I: IntoFFIValue + FromFFIValue +{ + type Owned = I::Owned; + + fn into_ffi_value(instance: &T) -> WrappedFFIValue { + instance.inner().into_ffi_value() + } + + fn from_ffi_value(arg: Self::FFIType) -> T { + T::from_inner(I::from_ffi_value(arg)) + } +} + +/// The type is passed as the inner type. +impl, I: RIType> RIType for Inner { + type FFIType = I::FFIType; +} + +/// The implementation of the pass by enum strategy. This strategy uses an `u8` internally to pass +/// the enum between wasm and the host. So, this strategy only supports enums with unit variants. +/// +/// Use this type as associated type for [`PassBy`] to implement this strategy for a type. +/// +/// This type expects the type that wants to implement this strategy as generic parameter. Besides +/// that the type needs to implement `TryFrom` and `From for u8`. +/// +/// [`PassByEnum`](derive.PassByEnum.html) is a derive macro to implement this strategy. +/// +/// # Example +/// ``` +/// # use sp_runtime_interface::pass_by::{PassBy, Enum}; +/// #[derive(Clone, Copy)] +/// enum Test { +/// Test1, +/// Test2, +/// } +/// +/// impl From for u8 { +/// fn from(val: Test) -> u8 { +/// match val { +/// Test::Test1 => 0, +/// Test::Test2 => 1, +/// } +/// } +/// } +/// +/// impl std::convert::TryFrom for Test { +/// type Error = (); +/// +/// fn try_from(val: u8) -> Result { +/// match val { +/// 0 => Ok(Test::Test1), +/// 1 => Ok(Test::Test2), +/// _ => Err(()), +/// } +/// } +/// } +/// +/// impl PassBy for Test { +/// type PassBy = Enum; +/// } +/// ``` +pub struct Enum + TryFrom>(PhantomData); + +#[cfg(feature = "std")] +impl + TryFrom> PassByImpl for Enum { + fn into_ffi_value( + instance: T, + _: &mut dyn FunctionContext, + ) -> Result { + Ok(instance.into()) + } + + fn from_ffi_value( + _: &mut dyn FunctionContext, + arg: Self::FFIType, + ) -> Result { + T::try_from(arg).map_err(|_| format!("Invalid enum discriminant: {}", arg)) + } +} + +#[cfg(not(feature = "std"))] +impl + TryFrom> PassByImpl for Enum { + type Owned = (); + + fn into_ffi_value(instance: &T) -> WrappedFFIValue { + let value: u8 = (*instance).into(); + value.into() + } + + fn from_ffi_value(arg: Self::FFIType) -> T { + T::try_from(arg).expect("Host to wasm provides a valid enum discriminant; qed") + } +} + +/// The type is passed as `u8`. +/// +/// The value is corresponds to the discriminant of the variant. +impl + TryFrom> RIType for Enum { + type FFIType = u8; +} diff --git a/primitives/runtime-interface/src/util.rs b/primitives/runtime-interface/src/util.rs new file mode 100644 index 0000000000000..fa7016a2b01a6 --- /dev/null +++ b/primitives/runtime-interface/src/util.rs @@ -0,0 +1,59 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Various utilities that help interfacing with wasm runtime code. + +/// Pack a pointer and length into an `u64`. +pub fn pack_ptr_and_len(ptr: u32, len: u32) -> u64 { + // The static assertions from above are changed into a runtime check. + #[cfg(all(not(feature = "std"), feature = "disable_target_static_assertions"))] + assert_eq!(4, sp_std::mem::size_of::()); + + (u64::from(len) << 32) | u64::from(ptr) +} + +/// Unpacks an `u64` into the pointer and length. +/// +/// Runtime API functions return a 64-bit value which encodes a pointer in the least-significant +/// 32-bits and a length in the most-significant 32 bits. This interprets the returned value as a pointer, +/// length tuple. +pub fn unpack_ptr_and_len(val: u64) -> (u32, u32) { + // The static assertions from above are changed into a runtime check. + #[cfg(all(not(feature = "std"), feature = "disable_target_static_assertions"))] + assert_eq!(4, sp_std::mem::size_of::()); + + let ptr = (val & (!0u32 as u64)) as u32; + let len = (val >> 32) as u32; + + (ptr, len) +} + +#[cfg(test)] +mod tests { + use super::{pack_ptr_and_len, unpack_ptr_and_len}; + + #[test] + fn ptr_len_packing_unpacking() { + const PTR: u32 = 0x1337; + const LEN: u32 = 0x7f000000; + + let packed = pack_ptr_and_len(PTR, LEN); + let (ptr, len) = unpack_ptr_and_len(packed); + + assert_eq!(PTR, ptr); + assert_eq!(LEN, len); + } +} diff --git a/primitives/runtime-interface/src/wasm.rs b/primitives/runtime-interface/src/wasm.rs new file mode 100644 index 0000000000000..476dfb8a4ce5a --- /dev/null +++ b/primitives/runtime-interface/src/wasm.rs @@ -0,0 +1,142 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Traits required by the runtime interface from the wasm side. + +use crate::RIType; + +use sp_std::cell::Cell; + +/// Something that can be created from a ffi value. +/// +/// # Safety +/// +/// It is unsafe behavior to call `Something::into_ffi_value().get()` and take this as input for +/// `from_ffi_value`. Implementations are safe to assume that the `arg` given to `from_ffi_value` +/// is only generated by the corresponding `host::IntoFFIValue` implementation. +pub trait FromFFIValue: Sized + RIType { + /// Create `Self` from the given ffi value. + fn from_ffi_value(arg: Self::FFIType) -> Self; +} + +/// Something that can be converted into a ffi value. +pub trait IntoFFIValue: RIType { + /// The owned rust type that is stored with the ffi value in [`WrappedFFIValue`]. + /// + /// If no owned value is required, `()` can be used as a type. + type Owned; + + /// Convert `self` into a [`WrappedFFIValue`]. + fn into_ffi_value(&self) -> WrappedFFIValue; +} + +/// Represents a wrapped ffi value. +/// +/// It is either the ffi value itself or the ffi value plus some other owned value. By providing +/// support for storing another owned value besides the actual ffi value certain performance +/// optimizations can be applied. For example using the pointer to a `Vec`, while using the +/// pointer to a SCALE encoded `Vec` that is stored in this wrapper for any other `Vec`. +pub enum WrappedFFIValue { + Wrapped(T), + WrappedAndOwned(T, O), +} + +impl WrappedFFIValue { + /// Returns the wrapped ffi value. + pub fn get(&self) -> T { + match self { + Self::Wrapped(data) | Self::WrappedAndOwned(data, _) => *data, + } + } +} + +impl From for WrappedFFIValue { + fn from(val: T) -> Self { + WrappedFFIValue::Wrapped(val) + } +} + +impl From<(T, O)> for WrappedFFIValue { + fn from(val: (T, O)) -> Self { + WrappedFFIValue::WrappedAndOwned(val.0, val.1) + } +} + +/// The state of an exchangeable function. +#[derive(Clone, Copy)] +enum ExchangeableFunctionState { + /// Original function is present + Original, + /// The function has been replaced. + 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")); + } +} diff --git a/primitives/runtime-interface/test-wasm/Cargo.toml b/primitives/runtime-interface/test-wasm/Cargo.toml new file mode 100644 index 0000000000000..b3a400a12d393 --- /dev/null +++ b/primitives/runtime-interface/test-wasm/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "sp-runtime-interface-test-wasm" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" + +[dependencies] +sp-runtime-interface = { version = "2.0.0", default-features = false, path = "../" } +sp-std = { version = "2.0.0", default-features = false, path = "../../std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../io" } +sp-core = { version = "2.0.0", default-features = false, path = "../../core" } + +[build-dependencies] +wasm-builder-runner = { version = "1.0.3", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } + +[features] +default = [ "std" ] +std = [ "sp-runtime-interface/std", "sp-std/std", "sp-core/std", "sp-io/std" ] diff --git a/primitives/runtime-interface/test-wasm/build.rs b/primitives/runtime-interface/test-wasm/build.rs new file mode 100644 index 0000000000000..8e1d17e821195 --- /dev/null +++ b/primitives/runtime-interface/test-wasm/build.rs @@ -0,0 +1,30 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; + +fn main() { + build_current_project_with_rustflags( + "wasm_binary.rs", + WasmBuilderSource::CratesOrPath { + path: "../../../utils/wasm-builder", + version: "1.0.6", + }, + // This instructs LLD to export __heap_base as a global variable, which is used by the + // external memory allocator. + "-Clink-arg=--export=__heap_base", + ); +} diff --git a/primitives/runtime-interface/test-wasm/src/lib.rs b/primitives/runtime-interface/test-wasm/src/lib.rs new file mode 100644 index 0000000000000..a7e7e3e983a97 --- /dev/null +++ b/primitives/runtime-interface/test-wasm/src/lib.rs @@ -0,0 +1,194 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the runtime interface traits and proc macros. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_runtime_interface::runtime_interface; + +#[cfg(not(feature = "std"))] +use sp_std::{vec, vec::Vec, mem, convert::TryFrom}; + +use sp_core::{sr25519::Public, wasm_export_functions}; + +// Inlucde the WASM binary +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +/// Used in the `test_array_as_mutable_reference` test. +const TEST_ARRAY: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + +#[runtime_interface] +pub trait TestApi { + /// Returns the input data as result. + fn return_input(data: Vec) -> Vec { + data + } + + /// Set the storage at key with value. + fn set_storage(&mut self, key: &[u8], data: &[u8]) { + self.place_storage(key.to_vec(), Some(data.to_vec())); + } + + /// Copy `hello` into the given mutable reference + fn return_value_into_mutable_reference(&self, data: &mut [u8]) { + let res = "hello"; + data[..res.as_bytes().len()].copy_from_slice(res.as_bytes()); + } + + /// Returns the input data wrapped in an `Option` as result. + fn return_option_input(data: Vec) -> Option> { + Some(data) + } + + /// Get an array as input and returns a subset of this array. + fn get_and_return_array(data: [u8; 34]) -> [u8; 16] { + let mut res = [0u8; 16]; + res.copy_from_slice(&data[..16]); + res + } + + /// Take and fill mutable array. + fn array_as_mutable_reference(data: &mut [u8; 16]) { + data.copy_from_slice(&TEST_ARRAY); + } + + /// Returns the given public key as result. + fn return_input_public_key(key: Public) -> Public { + key + } + + /// A function that is called with invalid utf8 data from the runtime. + /// + /// This also checks that we accept `_` (wild card) argument names. + fn invalid_utf8_data(_: &str) {} + + /// Overwrite the native implementation in wasm. The native implementation always returns + /// `false` and the replacement function will return always `true`. + fn overwrite_native_function_implementation() -> bool { + false + } +} + +/// Two random external functions from the old runtime interface. +/// This ensures that we still inherently export these functions from the host and that we are still +/// compatible with old wasm runtimes. +extern "C" { + pub fn ext_clear_storage(key_data: *const u8, key_len: u32); + pub fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8); +} + +/// Make sure the old runtime interface needs to be imported. +#[no_mangle] +pub fn force_old_runtime_interface_import() { + unsafe { ext_clear_storage(sp_std::ptr::null(), 0); } + unsafe { ext_keccak_256(sp_std::ptr::null(), 0, sp_std::ptr::null_mut()); } +} + +/// This function is not used, but we require it for the compiler to include `sp-io`. +/// `sp-io` is required for its panic and oom handler. +#[no_mangle] +pub fn import_sp_io() { + sp_io::misc::print_utf8(&[]); +} + +wasm_export_functions! { + fn test_return_data() { + let input = vec![1, 2, 3, 4, 5, 6]; + let res = test_api::return_input(input.clone()); + + assert_eq!(input, res); + } + + fn test_return_option_data() { + let input = vec![1, 2, 3, 4, 5, 6]; + let res = test_api::return_option_input(input.clone()); + + assert_eq!(Some(input), res); + } + + fn test_set_storage() { + let key = "hello"; + let value = "world"; + + test_api::set_storage(key.as_bytes(), value.as_bytes()); + } + + fn test_return_value_into_mutable_reference() { + let mut data = vec![1, 2, 3, 4, 5, 6]; + + test_api::return_value_into_mutable_reference(&mut data); + + let expected = "hello"; + assert_eq!(expected.as_bytes(), &data[..expected.len()]); + } + + fn test_get_and_return_array() { + let mut input = unsafe { mem::MaybeUninit::<[u8; 34]>::zeroed().assume_init() }; + input.copy_from_slice(&[ + 24, 3, 23, 20, 2, 16, 32, 1, 12, 26, 27, 8, 29, 31, 6, 5, 4, 19, 10, 28, 34, 21, 18, 33, 9, + 13, 22, 25, 15, 11, 30, 7, 14, 17, + ]); + + let res = test_api::get_and_return_array(input); + + assert_eq!(&res, &input[..16]); + } + + fn test_array_as_mutable_reference() { + let mut array = [0u8; 16]; + test_api::array_as_mutable_reference(&mut array); + + assert_eq!(array, TEST_ARRAY); + } + + fn test_return_input_public_key() { + let key = Public::try_from( + &[ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, + ][..], + ).unwrap(); + let ret_key = test_api::return_input_public_key(key.clone()); + + let key_data: &[u8] = key.as_ref(); + let ret_key_data: &[u8] = ret_key.as_ref(); + assert_eq!(key_data, ret_key_data); + } + + fn test_invalid_utf8_data_should_return_an_error() { + let data = vec![0, 159, 146, 150]; + // I'm an evil hacker, trying to hack! + let data_str = unsafe { sp_std::str::from_utf8_unchecked(&data) }; + + test_api::invalid_utf8_data(data_str); + } + + fn test_overwrite_native_function_implementation() { + fn new_implementation() -> bool { + true + } + + // Check native implementation + assert!(!test_api::overwrite_native_function_implementation()); + + let _guard = test_api::host_overwrite_native_function_implementation + .replace_implementation(new_implementation); + + assert!(test_api::overwrite_native_function_implementation()); + } +} diff --git a/primitives/runtime-interface/test/Cargo.toml b/primitives/runtime-interface/test/Cargo.toml new file mode 100644 index 0000000000000..35eb8cb8e1f56 --- /dev/null +++ b/primitives/runtime-interface/test/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "sp-runtime-interface-test" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +publish = false + +[dependencies] +sp-runtime-interface = { version = "2.0.0", path = "../" } +sc-executor = { version = "2.0.0", path = "../../../client/executor" } +sp-runtime-interface-test-wasm = { version = "2.0.0", path = "../test-wasm" } +sp-state-machine = { version = "2.0.0", path = "../../../primitives/state-machine" } +sp-core = { version = "2.0.0", path = "../../core" } +sp-io = { version = "2.0.0", path = "../../io" } diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs new file mode 100644 index 0000000000000..3cfb589b05519 --- /dev/null +++ b/primitives/runtime-interface/test/src/lib.rs @@ -0,0 +1,111 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Integration tests for runtime interface primitives +#![cfg(test)] + +#![cfg(test)] + +use sp_runtime_interface::*; +use sp_runtime_interface_test_wasm::{WASM_BINARY, test_api::HostFunctions}; +use sp_wasm_interface::HostFunctions as HostFunctionsT; + +type TestExternalities = sp_state_machine::TestExternalities; + +fn call_wasm_method(method: &str) -> TestExternalities { + let mut ext = TestExternalities::default(); + let mut ext_ext = ext.ext(); + + sc_executor::call_in_wasm::< + _, + ( + HF, + sp_io::SubstrateHostFunctions, + sc_executor::deprecated_host_interface::SubstrateExternals + ) + >( + method, + &[], + sc_executor::WasmExecutionMethod::Interpreted, + &mut ext_ext, + &WASM_BINARY[..], + 8, + false, + ).expect(&format!("Executes `{}`", method)); + + ext +} + +#[test] +fn test_return_data() { + call_wasm_method::("test_return_data"); +} + +#[test] +fn test_return_option_data() { + call_wasm_method::("test_return_option_data"); +} + +#[test] +fn test_set_storage() { + let mut ext = call_wasm_method::("test_set_storage"); + + let expected = "world"; + assert_eq!(expected.as_bytes(), &ext.ext().storage("hello".as_bytes()).unwrap()[..]); +} + +#[test] +fn test_return_value_into_mutable_reference() { + call_wasm_method::("test_return_value_into_mutable_reference"); +} + +#[test] +fn test_get_and_return_array() { + call_wasm_method::("test_get_and_return_array"); +} + +#[test] +fn test_array_as_mutable_reference() { + call_wasm_method::("test_array_as_mutable_reference"); +} + +#[test] +fn test_return_input_public_key() { + call_wasm_method::("test_return_input_public_key"); +} + +#[test] +#[should_panic( + expected = "Other(\"Instantiation: Export ext_test_api_return_input_version_1 not found\")" +)] +fn host_function_not_found() { + call_wasm_method::<()>("test_return_data"); +} + +#[test] +#[should_panic( + expected = + "FunctionExecution(\"ext_test_api_invalid_utf8_data_version_1\", \ + \"Invalid utf8 data provided\")" +)] +fn test_invalid_utf8_data_should_return_an_error() { + call_wasm_method::("test_invalid_utf8_data_should_return_an_error"); +} + +#[test] +fn test_overwrite_native_function_implementation() { + call_wasm_method::("test_overwrite_native_function_implementation"); +} diff --git a/primitives/runtime-interface/tests/ui.rs b/primitives/runtime-interface/tests/ui.rs new file mode 100644 index 0000000000000..910771f938969 --- /dev/null +++ b/primitives/runtime-interface/tests/ui.rs @@ -0,0 +1,27 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::env; + +#[rustversion::attr(not(stable), ignore)] +#[test] +fn ui() { + // As trybuild is using `cargo check`, we don't need the real WASM binaries. + env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/primitives/runtime-interface/tests/ui/no_generic_parameters.rs b/primitives/runtime-interface/tests/ui/no_generic_parameters.rs new file mode 100644 index 0000000000000..17ddb00fab3b7 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/no_generic_parameters.rs @@ -0,0 +1,8 @@ +use sp_runtime_interface::runtime_interface; + +#[runtime_interface] +trait Test { + fn test() {} +} + +fn main() {} diff --git a/primitives/runtime-interface/tests/ui/no_generic_parameters.stderr b/primitives/runtime-interface/tests/ui/no_generic_parameters.stderr new file mode 100644 index 0000000000000..c3e46655e5be7 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/no_generic_parameters.stderr @@ -0,0 +1,11 @@ +error: Generic parameters not supported. + --> $DIR/no_generic_parameters.rs:5:10 + | +5 | fn test() {} + | ^ + +error: Generic parameters not supported. + --> $DIR/no_generic_parameters.rs:4:12 + | +4 | trait Test { + | ^ diff --git a/primitives/runtime-interface/tests/ui/no_method_implementation.rs b/primitives/runtime-interface/tests/ui/no_method_implementation.rs new file mode 100644 index 0000000000000..e3cd93e4a97b2 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/no_method_implementation.rs @@ -0,0 +1,8 @@ +use sp_runtime_interface::runtime_interface; + +#[runtime_interface] +trait Test { + fn test(); +} + +fn main() {} diff --git a/primitives/runtime-interface/tests/ui/no_method_implementation.stderr b/primitives/runtime-interface/tests/ui/no_method_implementation.stderr new file mode 100644 index 0000000000000..31b2d39762340 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/no_method_implementation.stderr @@ -0,0 +1,5 @@ +error: Methods need to have an implementation. + --> $DIR/no_method_implementation.rs:5:2 + | +5 | fn test(); + | ^^ diff --git a/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.rs b/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.rs new file mode 100644 index 0000000000000..6f4ae37ea466e --- /dev/null +++ b/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.rs @@ -0,0 +1,6 @@ +use sp_runtime_interface::pass_by::PassByEnum; + +#[derive(PassByEnum)] +struct Test; + +fn main() {} diff --git a/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr b/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr new file mode 100644 index 0000000000000..6502a36fc18b7 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/pass_by_enum_with_struct.stderr @@ -0,0 +1,5 @@ +error: `PassByEnum` only supports enums as input type. + --> $DIR/pass_by_enum_with_struct.rs:3:10 + | +3 | #[derive(PassByEnum)] + | ^^^^^^^^^^ diff --git a/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.rs b/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.rs new file mode 100644 index 0000000000000..a03bfdc1aed81 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.rs @@ -0,0 +1,8 @@ +use sp_runtime_interface::pass_by::PassByEnum; + +#[derive(PassByEnum)] +enum Test { + Var0(u32), +} + +fn main() {} diff --git a/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr b/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr new file mode 100644 index 0000000000000..1f03436d4e007 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/pass_by_enum_with_value_variant.stderr @@ -0,0 +1,5 @@ +error: `PassByEnum` only supports unit variants. + --> $DIR/pass_by_enum_with_value_variant.rs:3:10 + | +3 | #[derive(PassByEnum)] + | ^^^^^^^^^^ diff --git a/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.rs b/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.rs new file mode 100644 index 0000000000000..f496bc3700106 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.rs @@ -0,0 +1,9 @@ +use sp_runtime_interface::pass_by::PassByInner; + +#[derive(PassByInner)] +struct Test { + data: u32, + data2: u32, +} + +fn main() {} diff --git a/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr b/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr new file mode 100644 index 0000000000000..7f576a69f0e50 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/pass_by_inner_with_two_fields.stderr @@ -0,0 +1,5 @@ +error: Only newtype/one field structs are supported by `PassByInner`! + --> $DIR/pass_by_inner_with_two_fields.rs:3:10 + | +3 | #[derive(PassByInner)] + | ^^^^^^^^^^^ diff --git a/primitives/runtime-interface/tests/ui/take_self_by_value.rs b/primitives/runtime-interface/tests/ui/take_self_by_value.rs new file mode 100644 index 0000000000000..9c12614d93077 --- /dev/null +++ b/primitives/runtime-interface/tests/ui/take_self_by_value.rs @@ -0,0 +1,8 @@ +use sp_runtime_interface::runtime_interface; + +#[runtime_interface] +trait Test { + fn test(self) {} +} + +fn main() {} diff --git a/primitives/runtime-interface/tests/ui/take_self_by_value.stderr b/primitives/runtime-interface/tests/ui/take_self_by_value.stderr new file mode 100644 index 0000000000000..9b17a63a35cbc --- /dev/null +++ b/primitives/runtime-interface/tests/ui/take_self_by_value.stderr @@ -0,0 +1,5 @@ +error: Taking `Self` by value is not allowed. + --> $DIR/take_self_by_value.rs:5:10 + | +5 | fn test(self) {} + | ^^^^ diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml new file mode 100644 index 0000000000000..2574fef4b9826 --- /dev/null +++ b/primitives/runtime/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "sp-runtime" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.1.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0", default-features = false, path = "../core" } +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../application-crypto" } +sp-arithmetic = { version = "2.0.0", default-features = false, path = "../arithmetic" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-io = { version = "2.0.0", default-features = false, path = "../io" } +log = { version = "0.4.8", optional = true } +paste = "0.1.6" +rand = { version = "0.7.2", optional = true } +impl-trait-for-tuples = "0.1.3" +sp-inherents = { version = "2.0.0", default-features = false, path = "../inherents" } + +[dev-dependencies] +serde_json = "1.0.41" +rand = "0.7.2" + +[features] +bench = [] +default = ["std"] +std = [ + "sp-application-crypto/std", + "sp-arithmetic/std", + "codec/std", + "log", + "sp-core/std", + "rand", + "sp-std/std", + "sp-io/std", + "serde", + "sp-inherents/std", +] diff --git a/core/sr-primitives/src/curve.rs b/primitives/runtime/src/curve.rs similarity index 95% rename from core/sr-primitives/src/curve.rs rename to primitives/runtime/src/curve.rs index 6f25af3e10b6e..b45501fdb764e 100644 --- a/core/sr-primitives/src/curve.rs +++ b/primitives/runtime/src/curve.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -20,10 +20,12 @@ use crate::{Perbill, traits::{SimpleArithmetic, SaturatedConversion}}; use core::ops::Sub; /// Piecewise Linear function in [0, 1] -> [0, 1]. -#[derive(PartialEq, Eq, primitives::RuntimeDebug)] +#[derive(PartialEq, Eq, sp_core::RuntimeDebug)] pub struct PiecewiseLinear<'a> { /// Array of points. Must be in order from the lowest abscissas to the highest. - pub points: &'a [(Perbill, Perbill)] + pub points: &'a [(Perbill, Perbill)], + /// The maximum value that can be returned. + pub maximum: Perbill, } fn abs_sub + Clone>(a: N, b: N) -> N where { @@ -135,7 +137,8 @@ fn test_calculate_for_fraction_times_denominator() { (Perbill::from_parts(0_000_000_000), Perbill::from_parts(0_500_000_000)), (Perbill::from_parts(0_500_000_000), Perbill::from_parts(1_000_000_000)), (Perbill::from_parts(1_000_000_000), Perbill::from_parts(0_000_000_000)), - ] + ], + maximum: Perbill::from_parts(1_000_000_000), }; pub fn formal_calculate_for_fraction_times_denominator(n: u64, d: u64) -> u64 { diff --git a/core/sr-primitives/src/generic/block.rs b/primitives/runtime/src/generic/block.rs similarity index 97% rename from core/sr-primitives/src/generic/block.rs rename to primitives/runtime/src/generic/block.rs index 3383e257605aa..21e65d1fb5233 100644 --- a/core/sr-primitives/src/generic/block.rs +++ b/primitives/runtime/src/generic/block.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -22,8 +22,8 @@ use std::fmt; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; -use rstd::prelude::*; -use primitives::RuntimeDebug; +use sp_std::prelude::*; +use sp_core::RuntimeDebug; use crate::codec::{Codec, Encode, Decode}; use crate::traits::{self, Member, Block as BlockT, Header as HeaderT, MaybeSerialize}; use crate::Justification; diff --git a/primitives/runtime/src/generic/checked_extrinsic.rs b/primitives/runtime/src/generic/checked_extrinsic.rs new file mode 100644 index 0000000000000..b2d247ef5f913 --- /dev/null +++ b/primitives/runtime/src/generic/checked_extrinsic.rs @@ -0,0 +1,90 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generic implementation of an extrinsic that has passed the verification +//! stage. + +use crate::traits::{ + self, Member, MaybeDisplay, SignedExtension, Dispatchable, +}; +#[allow(deprecated)] +use crate::traits::ValidateUnsigned; +use crate::transaction_validity::TransactionValidity; + +/// Definition of something that the external world might want to say; its +/// existence implies that it has been checked and is good, particularly with +/// regards to the signature. +#[derive(PartialEq, Eq, Clone, sp_core::RuntimeDebug)] +pub struct CheckedExtrinsic { + /// Who this purports to be from and the number of extrinsics have come before + /// from the same signer, if anyone (note this is not a signature). + pub signed: Option<(AccountId, Extra)>, + + /// The function that should be called. + pub function: Call, +} + +impl traits::Applyable for + CheckedExtrinsic +where + AccountId: Member + MaybeDisplay, + Call: Member + Dispatchable, + Extra: SignedExtension, + Origin: From>, + Info: Clone, +{ + type AccountId = AccountId; + type Call = Call; + type DispatchInfo = Info; + + fn sender(&self) -> Option<&Self::AccountId> { + self.signed.as_ref().map(|x| &x.0) + } + + #[allow(deprecated)] // Allow ValidateUnsigned + fn validate>( + &self, + info: Self::DispatchInfo, + len: usize, + ) -> TransactionValidity { + if let Some((ref id, ref extra)) = self.signed { + Extra::validate(extra, id, &self.function, info.clone(), len) + } else { + let valid = Extra::validate_unsigned(&self.function, info, len)?; + let unsigned_validation = U::validate_unsigned(&self.function)?; + Ok(valid.combine_with(unsigned_validation)) + } + } + + #[allow(deprecated)] // Allow ValidateUnsigned + fn apply>( + self, + info: Self::DispatchInfo, + len: usize, + ) -> crate::ApplyExtrinsicResult { + let (maybe_who, pre) = if let Some((id, extra)) = self.signed { + let pre = Extra::pre_dispatch(extra, &id, &self.function, info.clone(), len)?; + (Some(id), pre) + } else { + let pre = Extra::pre_dispatch_unsigned(&self.function, info.clone(), len)?; + U::pre_dispatch(&self.function)?; + (None, pre) + }; + let res = self.function.dispatch(Origin::from(maybe_who)); + Extra::post_dispatch(pre, info.clone(), len); + Ok(res.map_err(Into::into)) + } +} diff --git a/primitives/runtime/src/generic/digest.rs b/primitives/runtime/src/generic/digest.rs new file mode 100644 index 0000000000000..6653cfb8a86b3 --- /dev/null +++ b/primitives/runtime/src/generic/digest.rs @@ -0,0 +1,376 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generic implementation of a digest. + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +use sp_std::prelude::*; + +use crate::ConsensusEngineId; +use crate::codec::{Decode, Encode, Input, Error}; +use sp_core::RuntimeDebug; + +/// Generic header digest. +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Digest { + /// A list of logs in the digest. + pub logs: Vec>, +} + +impl Default for Digest { + fn default() -> Self { + Digest { logs: Vec::new(), } + } +} + +impl Digest { + /// Get reference to all digest items. + pub fn logs(&self) -> &[DigestItem] { + &self.logs + } + + /// Push new digest item. + pub fn push(&mut self, item: DigestItem) { + self.logs.push(item); + } + + /// Pop a digest item. + pub fn pop(&mut self) -> Option> { + self.logs.pop() + } + + /// Get reference to the first digest item that matches the passed predicate. + pub fn log) -> Option<&T>>(&self, predicate: F) -> Option<&T> { + self.logs().iter() + .filter_map(predicate) + .next() + } + + /// Get a conversion of the first digest item that successfully converts using the function. + pub fn convert_first) -> Option>(&self, predicate: F) -> Option { + self.logs().iter() + .filter_map(predicate) + .next() + } +} + + +/// Digest item that is able to encode/decode 'system' digest items and +/// provide opaque access to other items. +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +pub enum DigestItem { + /// System digest item that contains the root of changes trie at given + /// block. It is created for every block iff runtime supports changes + /// trie creation. + ChangesTrieRoot(Hash), + + /// A pre-runtime digest. + /// + /// These are messages from the consensus engine to the runtime, although + /// the consensus engine can (and should) read them itself to avoid + /// code and state duplication. It is erroneous for a runtime to produce + /// these, but this is not (yet) checked. + PreRuntime(ConsensusEngineId, Vec), + + /// A message from the runtime to the consensus engine. This should *never* + /// be generated by the native code of any consensus engine, but this is not + /// checked (yet). + Consensus(ConsensusEngineId, Vec), + + /// Put a Seal on it. This is only used by native code, and is never seen + /// by runtimes. + Seal(ConsensusEngineId, Vec), + + /// Some other thing. Unsupported and experimental. + Other(Vec), +} + +#[cfg(feature = "std")] +impl serde::Serialize for DigestItem { + fn serialize(&self, seq: S) -> Result where S: serde::Serializer { + self.using_encoded(|bytes| { + sp_core::bytes::serialize(bytes, seq) + }) + } +} + +#[cfg(feature = "std")] +impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem { + fn deserialize(de: D) -> Result where + D: serde::Deserializer<'a>, + { + let r = sp_core::bytes::deserialize(de)?; + Decode::decode(&mut &r[..]) + .map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e))) + } +} + +/// 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, RuntimeDebug)] +pub enum DigestItemRef<'a, Hash: 'a> { + /// Reference to `DigestItem::ChangesTrieRoot`. + ChangesTrieRoot(&'a Hash), + /// A pre-runtime digest. + /// + /// These are messages from the consensus engine to the runtime, although + /// the consensus engine can (and should) read them itself to avoid + /// code and state duplication. It is erroneous for a runtime to produce + /// these, but this is not (yet) checked. + PreRuntime(&'a ConsensusEngineId, &'a Vec), + /// A message from the runtime to the consensus engine. This should *never* + /// be generated by the native code of any consensus engine, but this is not + /// checked (yet). + Consensus(&'a ConsensusEngineId, &'a Vec), + /// Put a Seal on it. This is only used by native code, and is never seen + /// by runtimes. + Seal(&'a ConsensusEngineId, &'a Vec), + /// Any 'non-system' digest item, opaque to the native code. + Other(&'a Vec), +} + +/// Type of the digest item. Used to gain explicit control over `DigestItem` encoding +/// process. We need an explicit control, because final runtimes are encoding their own +/// digest items using `DigestItemRef` type and we can't auto-derive `Decode` +/// trait for `DigestItemRef`. +#[repr(u32)] +#[derive(Encode, Decode)] +pub enum DigestItemType { + ChangesTrieRoot = 2, + PreRuntime = 6, + Consensus = 4, + Seal = 5, + Other = 0, +} + +/// Type of a digest item that contains raw data; this also names the consensus engine ID where +/// applicable. Used to identify one or more digest items of interest. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub enum OpaqueDigestItemId<'a> { + /// Type corresponding to DigestItem::PreRuntime. + PreRuntime(&'a ConsensusEngineId), + /// Type corresponding to DigestItem::Consensus. + Consensus(&'a ConsensusEngineId), + /// Type corresponding to DigestItem::Seal. + Seal(&'a ConsensusEngineId), + /// Some other (non-prescribed) type. + Other, +} + +impl DigestItem { + /// Returns a 'referencing view' for this digest item. + pub fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash> { + match *self { + DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), + DigestItem::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s), + DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s), + DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s), + DigestItem::Other(ref v) => DigestItemRef::Other(v), + } + } + + /// Returns `Some` if the entry is the `ChangesTrieRoot` entry. + pub fn as_changes_trie_root(&self) -> Option<&Hash> { + self.dref().as_changes_trie_root() + } + + /// Returns `Some` if this entry is the `PreRuntime` entry. + pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> { + self.dref().as_pre_runtime() + } + + /// Returns `Some` if this entry is the `Consensus` entry. + pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &[u8])> { + self.dref().as_consensus() + } + + /// Returns `Some` if this entry is the `Seal` entry. + pub fn as_seal(&self) -> Option<(ConsensusEngineId, &[u8])> { + self.dref().as_seal() + } + + /// Returns Some if `self` is a `DigestItem::Other`. + pub fn as_other(&self) -> Option<&[u8]> { + match *self { + DigestItem::Other(ref v) => Some(&v[..]), + _ => None, + } + } + + /// Returns the opaque data contained in the item if `Some` if this entry has the id given. + pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&[u8]> { + self.dref().try_as_raw(id) + } + + /// Returns the data contained in the item if `Some` if this entry has the id given, decoded + /// to the type provided `T`. + pub fn try_to(&self, id: OpaqueDigestItemId) -> Option { + self.dref().try_to::(id) + } +} + +impl Encode for DigestItem { + fn encode(&self) -> Vec { + self.dref().encode() + } +} + +impl codec::EncodeLike for DigestItem {} + +impl Decode for DigestItem { + #[allow(deprecated)] + fn decode(input: &mut I) -> Result { + let item_type: DigestItemType = Decode::decode(input)?; + match item_type { + DigestItemType::ChangesTrieRoot => Ok(DigestItem::ChangesTrieRoot( + Decode::decode(input)?, + )), + DigestItemType::PreRuntime => { + let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; + Ok(DigestItem::PreRuntime(vals.0, vals.1)) + }, + DigestItemType::Consensus => { + let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; + Ok(DigestItem::Consensus(vals.0, vals.1)) + } + DigestItemType::Seal => { + let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; + Ok(DigestItem::Seal(vals.0, vals.1)) + }, + DigestItemType::Other => Ok(DigestItem::Other( + Decode::decode(input)?, + )), + } + } +} + +impl<'a, Hash> DigestItemRef<'a, Hash> { + /// 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), + _ => None, + } + } + + /// Cast this digest item into `PreRuntime` + pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &'a [u8])> { + match *self { + DigestItemRef::PreRuntime(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), + _ => None, + } + } + + /// Cast this digest item into `Consensus` + pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &'a [u8])> { + match *self { + DigestItemRef::Consensus(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), + _ => None, + } + } + + /// Cast this digest item into `Seal` + pub fn as_seal(&self) -> Option<(ConsensusEngineId, &'a [u8])> { + match *self { + DigestItemRef::Seal(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), + _ => None, + } + } + + /// Cast this digest item into `PreRuntime` + pub fn as_other(&self) -> Option<&'a [u8]> { + match *self { + DigestItemRef::Other(ref data) => Some(data), + _ => None, + } + } + + /// Try to match this digest item to the given opaque item identifier; if it matches, then + /// return the opaque data it contains. + pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&'a [u8]> { + match (id, self) { + (OpaqueDigestItemId::Consensus(w), &DigestItemRef::Consensus(v, s)) | + (OpaqueDigestItemId::Seal(w), &DigestItemRef::Seal(v, s)) | + (OpaqueDigestItemId::PreRuntime(w), &DigestItemRef::PreRuntime(v, s)) + if v == w => Some(&s[..]), + (OpaqueDigestItemId::Other, &DigestItemRef::Other(s)) => Some(&s[..]), + _ => None, + } + } + + /// Try to match this digest item to the given opaque item identifier; if it matches, then + /// try to cast to the given datatype; if that works, return it. + pub fn try_to(&self, id: OpaqueDigestItemId) -> Option { + self.try_as_raw(id).and_then(|mut x| Decode::decode(&mut x).ok()) + } +} + +impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> { + fn encode(&self) -> Vec { + let mut v = Vec::new(); + + match *self { + DigestItemRef::ChangesTrieRoot(changes_trie_root) => { + DigestItemType::ChangesTrieRoot.encode_to(&mut v); + changes_trie_root.encode_to(&mut v); + }, + DigestItemRef::Consensus(val, data) => { + DigestItemType::Consensus.encode_to(&mut v); + (val, data).encode_to(&mut v); + }, + DigestItemRef::Seal(val, sig) => { + DigestItemType::Seal.encode_to(&mut v); + (val, sig).encode_to(&mut v); + }, + DigestItemRef::PreRuntime(val, data) => { + DigestItemType::PreRuntime.encode_to(&mut v); + (val, data).encode_to(&mut v); + }, + DigestItemRef::Other(val) => { + DigestItemType::Other.encode_to(&mut v); + val.encode_to(&mut v); + }, + } + + v + } +} + +impl<'a, Hash: Encode> codec::EncodeLike for DigestItemRef<'a, Hash> {} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_serialize_digest() { + let digest = Digest { + logs: vec![ + DigestItem::ChangesTrieRoot(4), + DigestItem::Other(vec![1, 2, 3]), + DigestItem::Seal(*b"test", vec![1, 2, 3]) + ], + }; + + assert_eq!( + ::serde_json::to_string(&digest).unwrap(), + r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"# + ); + } +} diff --git a/core/sr-primitives/src/generic/era.rs b/primitives/runtime/src/generic/era.rs similarity index 92% rename from core/sr-primitives/src/generic/era.rs rename to primitives/runtime/src/generic/era.rs index 305951b1ee391..238130db00c7e 100644 --- a/core/sr-primitives/src/generic/era.rs +++ b/primitives/runtime/src/generic/era.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -28,7 +28,7 @@ pub type Period = u64; pub type Phase = u64; /// An era to describe the longevity of a transaction. -#[derive(PartialEq, Eq, Clone, Copy, primitives::RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, Copy, sp_core::RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Era { /// The transaction is valid forever. The genesis hash must be present in the signed content. @@ -40,6 +40,9 @@ pub enum Era { /// implies which block hash is included in the signature material). If the `period` is /// greater than 1 << 12, then it will be a factor of the times greater than 1<<12 that /// `period` is. + /// + /// When used on `FRAME`-based runtimes, `period` cannot exceed `BlockHashCount` parameter + /// of `system` module. Mortal(Period, Phase), } @@ -55,6 +58,10 @@ n = Q(current - phase, period) + phase impl Era { /// Create a new era based on a period (which should be a power of two between 4 and 65536 inclusive) /// and a block number on which it should start (or, for long periods, be shortly after the start). + /// + /// If using `Era` in the context of `FRAME` runtime, make sure that `period` + /// does not exceed `BlockHashCount` parameter passed to `system` module, since that + /// prunes old blocks and renders transactions immediately invalid. pub fn mortal(period: u64, current: u64) -> Self { let period = period.checked_next_power_of_two() .unwrap_or(1 << 16) diff --git a/core/sr-primitives/src/generic/header.rs b/primitives/runtime/src/generic/header.rs similarity index 90% rename from core/sr-primitives/src/generic/header.rs rename to primitives/runtime/src/generic/header.rs index 75994749c572e..51f31af0781d0 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/primitives/runtime/src/generic/header.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -24,14 +24,14 @@ use crate::traits::{ MaybeSerializeDeserialize, MaybeSerialize, MaybeDisplay, }; use crate::generic::Digest; -use primitives::U256; -use rstd::{ +use sp_core::U256; +use sp_std::{ convert::TryFrom, fmt::Debug, }; /// Abstraction over a block header for a substrate chain. -#[derive(PartialEq, Eq, Clone, primitives::RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, sp_core::RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] @@ -104,10 +104,10 @@ impl codec::EncodeLike for Header where {} impl traits::Header for Header where - Number: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash + MaybeDisplay + - SimpleArithmetic + Codec + Copy + Into + TryFrom, + Number: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + MaybeDisplay + + SimpleArithmetic + Codec + Copy + Into + TryFrom + sp_std::str::FromStr, Hash: HashT, - Hash::Output: Default + rstd::hash::Hash + Copy + Member + + Hash::Output: Default + sp_std::hash::Hash + Copy + Member + Ord + MaybeSerialize + Debug + MaybeDisplay + SimpleBitOps + Codec, { type Number = Number; @@ -152,9 +152,9 @@ impl traits::Header for Header where } impl Header where - Number: Member + rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec + Into + TryFrom, + Number: Member + sp_std::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec + Into + TryFrom, Hash: HashT, - Hash::Output: Default + rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, + Hash::Output: Default + sp_std::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, { /// Convenience helper for computing the hash of the header without having /// to import the trait. diff --git a/primitives/runtime/src/generic/mod.rs b/primitives/runtime/src/generic/mod.rs new file mode 100644 index 0000000000000..2416bb70470be --- /dev/null +++ b/primitives/runtime/src/generic/mod.rs @@ -0,0 +1,62 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Generic implementations of Extrinsic/Header/Block. +// end::description[] + +mod unchecked_extrinsic; +mod era; +mod checked_extrinsic; +mod header; +mod block; +mod digest; +#[cfg(test)] +mod tests; + +pub use self::unchecked_extrinsic::{UncheckedExtrinsic, SignedPayload}; +pub use self::era::{Era, Phase}; +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, OpaqueDigestItemId +}; + +use crate::codec::Encode; +use sp_std::prelude::*; + +fn encode_with_vec_prefix)>(encoder: F) -> Vec { + let size = ::sp_std::mem::size_of::(); + let reserve = match size { + 0..=0b00111111 => 1, + 0..=0b00111111_11111111 => 2, + _ => 4, + }; + let mut v = Vec::with_capacity(reserve + size); + v.resize(reserve, 0); + encoder(&mut v); + + // need to prefix with the total length to ensure it's binary compatible with + // Vec. + let mut length: Vec<()> = Vec::new(); + length.resize(v.len() - reserve, ()); + length.using_encoded(|s| { + v.splice(0..reserve, s.iter().cloned()); + }); + + v +} diff --git a/primitives/runtime/src/generic/tests.rs b/primitives/runtime/src/generic/tests.rs new file mode 100644 index 0000000000000..de2f4a19d99cf --- /dev/null +++ b/primitives/runtime/src/generic/tests.rs @@ -0,0 +1,60 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the generic implementations of Extrinsic/Header/Block. + +use crate::codec::{Decode, Encode}; +use sp_core::H256; +use super::DigestItem; + +#[test] +fn system_digest_item_encoding() { + let item = DigestItem::ChangesTrieRoot::(H256::default()); + let encoded = item.encode(); + assert_eq!(encoded, vec![ + // type = DigestItemType::ChangesTrieRoot + 2, + // trie root + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + ]); + + 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 encoded = item.encode(); + assert_eq!(encoded, vec![ + // type = DigestItemType::Other + 0, + // length of other data + 12, + // authorities + 10, 20, 30, + ]); + + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + assert_eq!(item, decoded); +} diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/primitives/runtime/src/generic/unchecked_extrinsic.rs similarity index 97% rename from core/sr-primitives/src/generic/unchecked_extrinsic.rs rename to primitives/runtime/src/generic/unchecked_extrinsic.rs index c7bff1f4c8b36..0a435242485cb 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/primitives/runtime/src/generic/unchecked_extrinsic.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 @@ //! Generic implementation of an unchecked (pre-verification) extrinsic. -use rstd::prelude::*; -use rstd::fmt; -use runtime_io::blake2_256; +use sp_std::{fmt, prelude::*}; +use sp_io::hashing::blake2_256; use codec::{Decode, Encode, EncodeLike, Input, Error}; use crate::{ traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic, IdentifyAccount}, @@ -283,7 +282,7 @@ where #[cfg(test)] mod tests { use super::*; - use runtime_io::blake2_256; + use sp_io::hashing::blake2_256; use crate::codec::{Encode, Decode}; use crate::traits::{SignedExtension, IdentifyAccount, IdentityLookup}; use serde::{Serialize, Deserialize}; @@ -320,9 +319,10 @@ mod tests { type AccountId = u64; type Call = (); type AdditionalSigned = (); + type DispatchInfo = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } } type Ex = UncheckedExtrinsic; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs new file mode 100644 index 0000000000000..c010ea0456d9e --- /dev/null +++ b/primitives/runtime/src/lib.rs @@ -0,0 +1,748 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime Modules shared primitive types. + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +// to allow benchmarking +#![cfg_attr(feature = "bench", feature(test))] +#[cfg(feature = "bench")] extern crate test; + +#[doc(hidden)] +pub use codec; +#[cfg(feature = "std")] +#[doc(hidden)] +pub use serde; +#[doc(hidden)] +pub use sp_std; + +#[doc(hidden)] +pub use paste; + +#[doc(hidden)] +pub use sp_application_crypto as app_crypto; + +#[cfg(feature = "std")] +pub use sp_core::storage::{Storage, StorageChild}; + +use sp_std::prelude::*; +use sp_std::convert::TryFrom; +use sp_core::{crypto, ed25519, sr25519, ecdsa, hash::{H256, H512}}; +use codec::{Encode, Decode}; + +pub mod curve; +pub mod generic; +pub mod offchain; +#[cfg(feature = "std")] +pub mod testing; +pub mod traits; +pub mod transaction_validity; +pub mod random_number_generator; + +/// Re-export these since they're only "kind of" generic. +pub use generic::{DigestItem, Digest}; + +/// Re-export this since it's part of the API of this crate. +pub use sp_core::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, AccountId32}}; +pub use sp_application_crypto::{RuntimeAppPublic, BoundToRuntimeAppPublic}; + +/// Re-export `RuntimeDebug`, to avoid dependency clutter. +pub use sp_core::RuntimeDebug; + +/// Re-export top-level arithmetic stuff. +pub use sp_arithmetic::{Perquintill, Perbill, Permill, Percent, Rational128, Fixed64}; +/// Re-export 128 bit helpers. +pub use sp_arithmetic::helpers_128bit; +/// Re-export big_uint stuff. +pub use sp_arithmetic::biguint; + +pub use random_number_generator::RandomNumberGenerator; + +/// An abstraction over justification for a block's validity under a consensus algorithm. +/// +/// Essentially a finality proof. The exact formulation will vary between consensus +/// algorithms. In the case where there are multiple valid proofs, inclusion within +/// the block itself would allow swapping justifications to change the block's hash +/// (and thus fork the chain). Sending a `Justification` alongside a block instead +/// bypasses this problem. +pub type Justification = Vec; + +use traits::{Verify, Lazy}; + +/// A module identifier. These are per module and should be stored in a registry somewhere. +#[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)] +pub struct ModuleId(pub [u8; 8]); + +impl TypeId for ModuleId { + const TYPE_ID: [u8; 4] = *b"modl"; +} + +/// 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; + +/// Create a const [`RuntimeString`]. +#[cfg(feature = "std")] +#[macro_export] +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 { + ( $y:expr ) => {{ $y }} +} + +#[cfg(feature = "std")] +pub use serde::{Serialize, Deserialize, de::DeserializeOwned}; +use crate::traits::IdentifyAccount; + +/// Complex storage builder stuff. +#[cfg(feature = "std")] +pub trait BuildStorage: Sized { + /// Build the storage out of this builder. + fn build_storage(&self) -> Result { + let mut storage = Default::default(); + self.assimilate_storage(&mut storage)?; + Ok(storage) + } + /// Assimilate the storage for this module into pre-existing overlays. + fn assimilate_storage( + &self, + storage: &mut sp_core::storage::Storage, + ) -> Result<(), String>; +} + +/// Something that can build the genesis storage of a module. +#[cfg(feature = "std")] +pub trait BuildModuleGenesisStorage: Sized { + /// Create the module genesis storage into the given `storage` and `child_storage`. + fn build_module_genesis_storage( + &self, + storage: &mut sp_core::storage::Storage, + ) -> Result<(), String>; +} + +#[cfg(feature = "std")] +impl BuildStorage for sp_core::storage::Storage { + fn assimilate_storage( + &self, + storage: &mut sp_core::storage::Storage, + )-> Result<(), String> { + storage.top.extend(self.top.iter().map(|(k, v)| (k.clone(), v.clone()))); + for (k, other_map) in self.children.iter() { + let k = k.clone(); + if let Some(map) = storage.children.get_mut(&k) { + map.data.extend(other_map.data.iter().map(|(k, v)| (k.clone(), v.clone()))); + if !map.child_info.try_update(other_map.child_info.as_ref()) { + return Err("Incompatible child info update".to_string()); + } + } else { + storage.children.insert(k, other_map.clone()); + } + } + Ok(()) + } +} + +#[cfg(feature = "std")] +impl BuildStorage for () { + fn assimilate_storage( + &self, + _: &mut sp_core::storage::Storage, + )-> Result<(), String> { + Err("`assimilate_storage` not implemented for `()`".into()) + } +} + +/// Consensus engine unique ID. +pub type ConsensusEngineId = [u8; 4]; + +/// Signature verify that can work with any known signature types.. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug)] +pub enum MultiSignature { + /// An Ed25519 signature. + Ed25519(ed25519::Signature), + /// An Sr25519 signature. + Sr25519(sr25519::Signature), + /// An ECDSA/SECP256k1 signature. + Ecdsa(ecdsa::Signature), +} + +impl From for MultiSignature { + fn from(x: ed25519::Signature) -> Self { + MultiSignature::Ed25519(x) + } +} + +impl From for MultiSignature { + fn from(x: sr25519::Signature) -> Self { + MultiSignature::Sr25519(x) + } +} + +impl From for MultiSignature { + fn from(x: ecdsa::Signature) -> Self { + MultiSignature::Ecdsa(x) + } +} + +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, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum MultiSigner { + /// An Ed25519 identity. + Ed25519(ed25519::Public), + /// An Sr25519 identity. + Sr25519(sr25519::Public), + /// An SECP256k1/ECDSA identity (actually, the Blake2 hash of the compressed pub key). + Ecdsa(ecdsa::Public), +} + +impl Default for MultiSigner { + fn default() -> Self { + MultiSigner::Ed25519(Default::default()) + } +} + +/// NOTE: This implementations is required by `SimpleAddressDeterminator`, +/// we convert the hash into some AccountId, it's fine to use any scheme. +impl> crypto::UncheckedFrom for MultiSigner { + fn unchecked_from(x: T) -> Self { + ed25519::Public::unchecked_from(x.into()).into() + } +} + +impl AsRef<[u8]> for MultiSigner { + fn as_ref(&self) -> &[u8] { + match *self { + MultiSigner::Ed25519(ref who) => who.as_ref(), + MultiSigner::Sr25519(ref who) => who.as_ref(), + MultiSigner::Ecdsa(ref who) => who.as_ref(), + } + } +} + +impl traits::IdentifyAccount for MultiSigner { + type AccountId = AccountId32; + fn into_account(self) -> AccountId32 { + match self { + MultiSigner::Ed25519(who) => <[u8; 32]>::from(who).into(), + MultiSigner::Sr25519(who) => <[u8; 32]>::from(who).into(), + MultiSigner::Ecdsa(who) => sp_io::hashing::blake2_256( + &who.as_compressed().expect("`who` is a valid `ECDSA` public key; qed")[..], + ).into(), + } + } +} + +impl From for MultiSigner { + fn from(x: ed25519::Public) -> Self { + MultiSigner::Ed25519(x) + } +} + +impl TryFrom for ed25519::Public { + type Error = (); + fn try_from(m: MultiSigner) -> Result { + if let MultiSigner::Ed25519(x) = m { Ok(x) } else { Err(()) } + } +} + +impl From for MultiSigner { + fn from(x: sr25519::Public) -> Self { + MultiSigner::Sr25519(x) + } +} + +impl TryFrom for sr25519::Public { + type Error = (); + fn try_from(m: MultiSigner) -> Result { + if let MultiSigner::Sr25519(x) = m { Ok(x) } else { Err(()) } + } +} + +impl From for MultiSigner { + fn from(x: ecdsa::Public) -> Self { + MultiSigner::Ecdsa(x) + } +} + +impl TryFrom for ecdsa::Public { + type Error = (); + fn try_from(m: MultiSigner) -> Result { + if let MultiSigner::Ecdsa(x) = m { Ok(x) } else { Err(()) } + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for MultiSigner { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + match *self { + MultiSigner::Ed25519(ref who) => write!(fmt, "ed25519: {}", who), + MultiSigner::Sr25519(ref who) => write!(fmt, "sr25519: {}", who), + MultiSigner::Ecdsa(ref who) => write!(fmt, "ecdsa: {}", who), + } + } +} + +impl Verify for MultiSignature { + type Signer = MultiSigner; + fn verify>(&self, mut msg: L, signer: &AccountId32) -> bool { + use sp_core::crypto::Public; + match (self, signer) { + (MultiSignature::Ed25519(ref sig), who) => sig.verify(msg, &ed25519::Public::from_slice(who.as_ref())), + (MultiSignature::Sr25519(ref sig), who) => sig.verify(msg, &sr25519::Public::from_slice(who.as_ref())), + (MultiSignature::Ecdsa(ref sig), who) => { + let m = sp_io::hashing::blake2_256(msg.get()); + match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { + Ok(pubkey) => + &sp_io::hashing::blake2_256(pubkey.as_ref()) + == >::as_ref(who), + _ => false, + } + } + } + } +} + +/// Signature verify that can work with any known signature types.. +#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct AnySignature(H512); + +impl Verify for AnySignature { + type Signer = sr25519::Public; + fn verify>(&self, mut msg: L, signer: &sr25519::Public) -> bool { + use sp_core::crypto::Public; + let msg = msg.get(); + sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref()) + .map(|s| s.verify(msg, signer)) + .unwrap_or(false) + || ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref()) + .map(|s| s.verify(msg, &ed25519::Public::from_slice(signer.as_ref()))) + .unwrap_or(false) + } +} + +impl From for AnySignature { + fn from(s: sr25519::Signature) -> Self { + AnySignature(s.into()) + } +} + +impl From for AnySignature { + fn from(s: ed25519::Signature) -> Self { + AnySignature(s.into()) + } +} + +impl From for DispatchOutcome { + fn from(err: DispatchError) -> Self { + Err(err) + } +} + +/// Result of a module function call; either nothing (functions are only called for "side effects") +/// or an error message. +pub type DispatchResult = sp_std::result::Result<(), DispatchError>; + +/// Reason why a dispatch call failed +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize))] +pub enum DispatchError { + /// Some error occurred. + Other(#[codec(skip)] &'static str), + /// Failed to lookup some data. + CannotLookup, + /// A bad origin. + BadOrigin, + /// A custom error in a module + Module { + /// Module index, matching the metadata module index + index: u8, + /// Module specific error value + error: u8, + /// Optional error message. + #[codec(skip)] + message: Option<&'static str>, + }, +} + +impl DispatchError { + /// Return the same error but without the attached message. + pub fn stripped(self) -> Self { + match self { + DispatchError::Module { index, error, message: Some(_) } + => DispatchError::Module { index, error, message: None }, + m => m, + } + } +} + +impl From for DispatchError { + fn from(_: crate::traits::LookupError) -> Self { + Self::CannotLookup + } +} + +impl From for DispatchError { + fn from(_: crate::traits::BadOrigin) -> Self { + Self::BadOrigin + } +} + +impl From<&'static str> for DispatchError { + fn from(err: &'static str) -> DispatchError { + DispatchError::Other(err) + } +} + +impl Into<&'static str> for DispatchError { + fn into(self) -> &'static str { + match self { + Self::Other(msg) => msg, + Self::CannotLookup => "Can not lookup", + Self::BadOrigin => "Bad origin", + Self::Module { message, .. } => message.unwrap_or("Unknown module error"), + } + } +} + +impl traits::Printable for DispatchError { + fn print(&self) { + "DispatchError".print(); + match self { + Self::Other(err) => err.print(), + Self::CannotLookup => "Can not lookup".print(), + Self::BadOrigin => "Bad origin".print(), + Self::Module { index, error, message } => { + index.print(); + error.print(); + if let Some(msg) = message { + msg.print(); + } + } + } + } +} + +/// This type specifies the outcome of dispatching a call to a module. +/// +/// In case of failure an error specific to the module is returned. +/// +/// Failure of the module call dispatching doesn't invalidate the extrinsic and it is still included +/// in the block, therefore all state changes performed by the dispatched call are still persisted. +/// +/// For example, if the dispatching of an extrinsic involves inclusion fee payment then these +/// changes are going to be preserved even if the call dispatched failed. +pub type DispatchOutcome = Result<(), DispatchError>; + +/// The result of applying of an extrinsic. +/// +/// This type is typically used in the context of `BlockBuilder` to signal that the extrinsic +/// in question cannot be included. +/// +/// A block containing extrinsics that have a negative inclusion outcome is invalid. A negative +/// result can only occur during the block production, where such extrinsics are detected and +/// removed from the block that is being created and the transaction pool. +/// +/// To rehash: every extrinsic in a valid block must return a positive `ApplyExtrinsicResult`. +/// +/// Examples of reasons preventing inclusion in a block: +/// - More block weight is required to process the extrinsic than is left in the block being built. +/// This doesn't neccessarily mean that the extrinsic is invalid, since it can still be +/// included in the next block if it has enough spare weight available. +/// - The sender doesn't have enough funds to pay the transaction inclusion fee. Including such +/// a transaction in the block doesn't make sense. +/// - The extrinsic supplied a bad signature. This transaction won't become valid ever. +pub type ApplyExtrinsicResult = Result; + +/// Verify a signature on an encoded value in a lazy manner. This can be +/// an optimization if the signature scheme has an "unsigned" escape hash. +pub fn verify_encoded_lazy( + sig: &V, + item: &T, + signer: &::AccountId +) -> bool { + // The `Lazy` trait expresses something like `X: FnMut &'a T>`. + // unfortunately this is a lifetime relationship that can't + // be expressed without generic associated types, better unification of HRTBs in type position, + // and some kind of integration into the Fn* traits. + struct LazyEncode { + inner: F, + encoded: Option>, + } + + impl Vec> traits::Lazy<[u8]> for LazyEncode { + fn get(&mut self) -> &[u8] { + self.encoded.get_or_insert_with(&self.inner).as_slice() + } + } + + sig.verify( + LazyEncode { inner: || item.encode(), encoded: None }, + signer, + ) +} + +/// Helper macro for `impl_outer_config` +#[macro_export] +macro_rules! __impl_outer_config_types { + // Generic + Instance + ( + $concrete:ident $config:ident $snake:ident { $instance:ident } < $ignore:ident >; + $( $rest:tt )* + ) => { + #[cfg(any(feature = "std", test))] + pub type $config = $snake::GenesisConfig<$concrete, $snake::$instance>; + $crate::__impl_outer_config_types! { $concrete $( $rest )* } + }; + // Generic + ( + $concrete:ident $config:ident $snake:ident < $ignore:ident >; + $( $rest:tt )* + ) => { + #[cfg(any(feature = "std", test))] + pub type $config = $snake::GenesisConfig<$concrete>; + $crate::__impl_outer_config_types! { $concrete $( $rest )* } + }; + // No Generic and maybe Instance + ( + $concrete:ident $config:ident $snake:ident $( { $instance:ident } )?; + $( $rest:tt )* + ) => { + #[cfg(any(feature = "std", test))] + pub type $config = $snake::GenesisConfig; + $crate::__impl_outer_config_types! { $concrete $( $rest )* } + }; + ($concrete:ident) => () +} + +/// Implement the output "meta" module configuration struct, +/// which is basically: +/// pub struct GenesisConfig { +/// rust_module_one: Option, +/// ... +/// } +#[macro_export] +macro_rules! impl_outer_config { + ( + pub struct $main:ident for $concrete:ident { + $( $config:ident => + $snake:ident $( $instance:ident )? $( <$generic:ident> )*, )* + } + ) => { + $crate::__impl_outer_config_types! { + $concrete $( $config $snake $( { $instance } )? $( <$generic> )*; )* + } + + $crate::paste::item! { + #[cfg(any(feature = "std", test))] + #[derive($crate::serde::Serialize, $crate::serde::Deserialize)] + #[serde(rename_all = "camelCase")] + #[serde(deny_unknown_fields)] + pub struct $main { + $( + pub [< $snake $(_ $instance )? >]: Option<$config>, + )* + } + #[cfg(any(feature = "std", test))] + impl $crate::BuildStorage for $main { + fn assimilate_storage( + &self, + storage: &mut $crate::Storage, + ) -> std::result::Result<(), String> { + $( + if let Some(ref extra) = self.[< $snake $(_ $instance )? >] { + $crate::impl_outer_config! { + @CALL_FN + $concrete; + $snake; + $( $instance )?; + extra; + storage; + } + } + )* + Ok(()) + } + } + } + }; + (@CALL_FN + $runtime:ident; + $module:ident; + $instance:ident; + $extra:ident; + $storage:ident; + ) => { + $crate::BuildModuleGenesisStorage::<$runtime, $module::$instance>::build_module_genesis_storage( + $extra, + $storage, + )?; + }; + (@CALL_FN + $runtime:ident; + $module:ident; + ; + $extra:ident; + $storage:ident; + ) => { + $crate::BuildModuleGenesisStorage::<$runtime, $module::__InherentHiddenInstance>::build_module_genesis_storage( + $extra, + $storage, + )?; + } +} + +/// Checks that `$x` is equal to `$y` with an error rate of `$error`. +/// +/// # Example +/// +/// ```rust +/// # fn main() { +/// sp_runtime::assert_eq_error_rate!(10, 10, 0); +/// sp_runtime::assert_eq_error_rate!(10, 11, 1); +/// sp_runtime::assert_eq_error_rate!(12, 10, 2); +/// # } +/// ``` +/// +/// ```rust,should_panic +/// # fn main() { +/// sp_runtime::assert_eq_error_rate!(12, 10, 1); +/// # } +/// ``` +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_eq_error_rate { + ($x:expr, $y:expr, $error:expr $(,)?) => { + assert!( + ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), + "{:?} != {:?} (with error rate {:?})", + $x, + $y, + $error, + ); + }; +} + +/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized +/// correctly. +#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] +pub struct OpaqueExtrinsic(pub Vec); + +impl sp_std::fmt::Debug for OpaqueExtrinsic { + #[cfg(feature = "std")] + fn fmt(&self, fmt: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(fmt, "{}", sp_core::hexdisplay::HexDisplay::from(&self.0)) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _fmt: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + Ok(()) + } +} + + +#[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| ::sp_core::bytes::serialize(bytes, seq)) + } +} + +#[cfg(feature = "std")] +impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic { + fn deserialize(de: D) -> Result where D: ::serde::Deserializer<'a> { + let r = ::sp_core::bytes::deserialize(de)?; + Decode::decode(&mut &r[..]) + .map_err(|e| ::serde::de::Error::custom(format!("Decode error: {}", e))) + } +} + +impl traits::Extrinsic for OpaqueExtrinsic { + type Call = (); + type SignaturePayload = (); +} + +/// Print something that implements `Printable` from the runtime. +pub fn print(print: impl traits::Printable) { + print.print(); +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::{Encode, Decode}; + use sp_core::crypto::Pair; + + #[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 dispatch_error_encoding() { + let error = DispatchError::Module { + index: 1, + error: 2, + message: Some("error message"), + }; + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![3, 1, 2]); + assert_eq!( + decoded, + DispatchError::Module { + index: 1, + error: 2, + message: None, + }, + ); + } + + #[test] + fn multi_signature_ecdsa_verify_works() { + let msg = &b"test-message"[..]; + let (pair, _) = ecdsa::Pair::generate(); + + let signature = pair.sign(&msg); + assert!(ecdsa::Pair::verify(&signature, msg, &pair.public())); + + let multi_sig = MultiSignature::from(signature); + let multi_signer = MultiSigner::from(pair.public()); + assert!(multi_sig.verify(msg, &multi_signer.into_account())); + + let multi_signer = MultiSigner::from(pair.public().into_compressed().unwrap()); + assert!(multi_sig.verify(msg, &multi_signer.into_account())); + } +} diff --git a/primitives/runtime/src/offchain/http.rs b/primitives/runtime/src/offchain/http.rs new file mode 100644 index 0000000000000..50c4a5eae6c1c --- /dev/null +++ b/primitives/runtime/src/offchain/http.rs @@ -0,0 +1,606 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A high-level helpers for making HTTP requests from Offchain Workers. +//! +//! `sp-io` crate exposes a low level methods to make and control HTTP requests +//! available only for Offchain Workers. Those might be hard to use +//! and usually that level of control is not really necessary. +//! This module aims to provide high-level wrappers for those APIs +//! to simplify making HTTP requests. +//! +//! +//! Example: +//! ```rust,no_run +//! use sp_runtime::offchain::http::Request; +//! +//! // initiate a GET request to localhost:1234 +//! let request: Request = Request::get("http://localhost:1234"); +//! let pending = request +//! .add_header("X-Auth", "hunter2") +//! .send() +//! .unwrap(); +//! +//! // wait for the response indefinitely +//! let mut response = pending.wait().unwrap(); +//! +//! // then check the headers +//! let mut headers = response.headers().into_iter(); +//! assert_eq!(headers.current(), None); +//! +//! // and collect the body +//! let body = response.body(); +//! assert_eq!(body.clone().collect::>(), b"1234".to_vec()); +//! assert_eq!(body.error(), &None); +//! ``` + +use sp_std::str; +use sp_std::prelude::Vec; +#[cfg(not(feature = "std"))] +use sp_std::prelude::vec; +use sp_core::RuntimeDebug; +use sp_core::offchain::{ + Timestamp, + HttpRequestId as RequestId, + HttpRequestStatus as RequestStatus, + HttpError, +}; + +/// Request method (HTTP verb) +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] +pub enum Method { + /// GET request + Get, + /// POST request + Post, + /// PUT request + Put, + /// PATCH request + Patch, + /// DELETE request + Delete, + /// Custom verb + Other(&'static str), +} + +impl AsRef for Method { + fn as_ref(&self) -> &str { + match *self { + Method::Get => "GET", + Method::Post => "POST", + Method::Put => "PUT", + Method::Patch => "PATCH", + Method::Delete => "DELETE", + Method::Other(m) => m, + } + } +} + +mod header { + use super::*; + + /// A header type. + #[derive(Clone, PartialEq, Eq, RuntimeDebug)] + pub struct Header { + name: Vec, + value: Vec, + } + + impl Header { + /// Creates new header given it's name and value. + pub fn new(name: &str, value: &str) -> Self { + Header { + name: name.as_bytes().to_vec(), + value: value.as_bytes().to_vec(), + } + } + + /// Returns the name of this header. + pub fn name(&self) -> &str { + // Header keys are always produced from `&str` so this is safe. + // we don't store them as `Strings` to avoid bringing `alloc::String` to sp-std + // or here. + unsafe { str::from_utf8_unchecked(&self.name) } + } + + /// Returns the value of this header. + pub fn value(&self) -> &str { + // Header values are always produced from `&str` so this is safe. + // we don't store them as `Strings` to avoid bringing `alloc::String` to sp-std + // or here. + unsafe { str::from_utf8_unchecked(&self.value) } + } + } +} + +/// An HTTP request builder. +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] +pub struct Request<'a, T = Vec<&'static [u8]>> { + /// Request method + pub method: Method, + /// Request URL + pub url: &'a str, + /// Body of the request + pub body: T, + /// Deadline to finish sending the request + pub deadline: Option, + /// Request list of headers. + headers: Vec, +} + +impl Default for Request<'static, T> { + fn default() -> Self { + Request { + method: Method::Get, + url: "http://localhost", + headers: Vec::new(), + body: Default::default(), + deadline: None, + } + } +} + +impl<'a> Request<'a> { + /// Start a simple GET request + pub fn get(url: &'a str) -> Self { + Self::new(url) + } +} + +impl<'a, T> Request<'a, T> { + /// Create new POST request with given body. + pub fn post(url: &'a str, body: T) -> Self { + let req: Request = Request::default(); + + Request { + url, + body, + method: Method::Post, + headers: req.headers, + deadline: req.deadline, + } + } +} + +impl<'a, T: Default> Request<'a, T> { + /// Create a new Request builder with the given URL. + pub fn new(url: &'a str) -> Self { + Request::default().url(url) + } + + /// Change the method of the request + pub fn method(mut self, method: Method) -> Self { + self.method = method; + self + } + + /// Change the URL of the request. + pub fn url(mut self, url: &'a str) -> Self { + self.url = url; + self + } + + /// Set the body of the request. + pub fn body(mut self, body: T) -> Self { + self.body = body; + self + } + + /// Add a header. + pub fn add_header(mut self, name: &str, value: &str) -> Self { + self.headers.push(header::Header::new(name, value)); + self + } + + /// Set the deadline of the request. + pub fn deadline(mut self, deadline: Timestamp) -> Self { + self.deadline = Some(deadline); + self + } +} + +impl<'a, I: AsRef<[u8]>, T: IntoIterator> Request<'a, T> { + /// Send the request and return a handle. + /// + /// Err is returned in case the deadline is reached + /// or the request timeouts. + pub fn send(self) -> Result { + let meta = &[]; + + // start an http request. + let id = sp_io::offchain::http_request_start( + self.method.as_ref(), + self.url, + meta, + ).map_err(|_| HttpError::IoError)?; + + // add custom headers + for header in &self.headers { + sp_io::offchain::http_request_add_header( + id, + header.name(), + header.value(), + ).map_err(|_| HttpError::IoError)? + } + + // write body + for chunk in self.body { + sp_io::offchain::http_request_write_body(id, chunk.as_ref(), self.deadline)?; + } + + // finalise the request + sp_io::offchain::http_request_write_body(id, &[], self.deadline)?; + + Ok(PendingRequest { + id, + }) + } +} + +/// A request error +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] +pub enum Error { + /// Deadline has been reached. + DeadlineReached, + /// Request had timed out. + IoError, + /// Unknown error has been ecountered. + Unknown, +} + +/// A struct representing an uncompleted http request. +#[derive(PartialEq, Eq, RuntimeDebug)] +pub struct PendingRequest { + /// Request ID + pub id: RequestId, +} + +/// A result of waiting for a pending request. +pub type HttpResult = Result; + +impl PendingRequest { + /// Wait for the request to complete. + /// + /// NOTE this waits for the request indefinitely. + pub fn wait(self) -> HttpResult { + match self.try_wait(None) { + Ok(res) => res, + Err(_) => panic!("Since `None` is passed we will never get a deadline error; qed"), + } + } + + /// Attempts to wait for the request to finish, + /// but will return `Err` in case the deadline is reached. + pub fn try_wait(self, deadline: impl Into>) -> Result { + Self::try_wait_all(vec![self], deadline).pop().expect("One request passed, one status received; qed") + } + + /// Wait for all provided requests. + pub fn wait_all(requests: Vec) -> Vec { + Self::try_wait_all(requests, None) + .into_iter() + .map(|r| match r { + Ok(r) => r, + Err(_) => panic!("Since `None` is passed we will never get a deadline error; qed"), + }) + .collect() + } + + /// Attempt to wait for all provided requests, but up to given deadline. + /// + /// Requests that are complete will resolve to an `Ok` others will return a `DeadlineReached` error. + pub fn try_wait_all( + requests: Vec, + deadline: impl Into> + ) -> Vec> { + let ids = requests.iter().map(|r| r.id).collect::>(); + let statuses = sp_io::offchain::http_response_wait(&ids, deadline.into()); + + statuses + .into_iter() + .zip(requests.into_iter()) + .map(|(status, req)| match status { + RequestStatus::DeadlineReached => Err(req), + RequestStatus::IoError => Ok(Err(Error::IoError)), + RequestStatus::Invalid => Ok(Err(Error::Unknown)), + RequestStatus::Finished(code) => Ok(Ok(Response::new(req.id, code))), + }) + .collect() + } +} + +/// A HTTP response. +#[derive(RuntimeDebug)] +pub struct Response { + /// Request id + pub id: RequestId, + /// Response status code + pub code: u16, + /// A collection of headers. + headers: Option, +} + +impl Response { + fn new(id: RequestId, code: u16) -> Self { + Self { + id, + code, + headers: None, + } + } + + /// Retrieve the headers for this response. + pub fn headers(&mut self) -> &Headers { + if self.headers.is_none() { + self.headers = Some( + Headers { raw: sp_io::offchain::http_response_headers(self.id) }, + ); + } + self.headers.as_ref().expect("Headers were just set; qed") + } + + /// Retrieve the body of this response. + pub fn body(&self) -> ResponseBody { + ResponseBody::new(self.id) + } +} + +/// A buffered byte iterator over response body. +/// +/// Note that reading the body may return `None` in following cases: +/// 1. Either the deadline you've set is reached (check via `#error`; +/// In such case you can resume the reader by setting a new deadline) +/// 2. Or because of IOError. In such case the reader is not resumable and will keep +/// returning `None`. +/// 3. The body has been returned. The reader will keep returning `None`. +#[derive(Clone)] +pub struct ResponseBody { + id: RequestId, + error: Option, + buffer: [u8; 4096], + filled_up_to: Option, + position: usize, + deadline: Option, +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for ResponseBody { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.debug_struct("ResponseBody") + .field("id", &self.id) + .field("error", &self.error) + .field("buffer", &self.buffer.len()) + .field("filled_up_to", &self.filled_up_to) + .field("position", &self.position) + .field("deadline", &self.deadline) + .finish() + } +} + +impl ResponseBody { + fn new(id: RequestId) -> Self { + ResponseBody { + id, + error: None, + buffer: [0_u8; 4096], + filled_up_to: None, + position: 0, + deadline: None, + } + } + + /// Set the deadline for reading the body. + pub fn deadline(&mut self, deadline: impl Into>) { + self.deadline = deadline.into(); + self.error = None; + } + + /// Return an error that caused the iterator to return `None`. + /// + /// If the error is `DeadlineReached` you can resume the iterator by setting + /// a new deadline. + pub fn error(&self) -> &Option { + &self.error + } +} + +impl Iterator for ResponseBody { + type Item = u8; + + fn next(&mut self) -> Option { + if self.error.is_some() { + return None; + } + + if self.filled_up_to.is_none() { + let result = sp_io::offchain::http_response_read_body( + self.id, + &mut self.buffer, + self.deadline); + match result { + Err(e) => { + self.error = Some(e); + return None; + } + Ok(0) => { + return None; + } + Ok(size) => { + self.position = 0; + self.filled_up_to = Some(size as usize); + } + } + } + + if Some(self.position) == self.filled_up_to { + self.filled_up_to = None; + return self.next(); + } + + let result = self.buffer[self.position]; + self.position += 1; + Some(result) + } +} + +/// A collection of Headers in the response. +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] +pub struct Headers { + /// Raw headers + pub raw: Vec<(Vec, Vec)>, +} + +impl Headers { + /// Retrieve a single header from the list of headers. + /// + /// Note this method is linearly looking from all the headers + /// comparing them with the needle byte-by-byte. + /// If you want to consume multiple headers it's better to iterate + /// and collect them on your own. + pub fn find(&self, name: &str) -> Option<&str> { + let raw = name.as_bytes(); + for &(ref key, ref val) in &self.raw { + if &**key == raw { + return str::from_utf8(&val).ok() + } + } + None + } + + /// Convert this headers into an iterator. + pub fn into_iter(&self) -> HeadersIterator { + HeadersIterator { collection: &self.raw, index: None } + } +} + +/// A custom iterator traversing all the headers. +#[derive(Clone, RuntimeDebug)] +pub struct HeadersIterator<'a> { + collection: &'a [(Vec, Vec)], + index: Option, +} + +impl<'a> HeadersIterator<'a> { + /// Move the iterator to the next position. + /// + /// Returns `true` is `current` has been set by this call. + pub fn next(&mut self) -> bool { + let index = self.index.map(|x| x + 1).unwrap_or(0); + self.index = Some(index); + index < self.collection.len() + } + + /// Returns current element (if any). + /// + /// Note that you have to call `next` prior to calling this + pub fn current(&self) -> Option<(&str, &str)> { + self.collection.get(self.index?) + .map(|val| (str::from_utf8(&val.0).unwrap_or(""), str::from_utf8(&val.1).unwrap_or(""))) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_io::TestExternalities; + use sp_core::offchain::{ + OffchainExt, + testing, + }; + + #[test] + fn should_send_a_basic_request_and_get_response() { + let (offchain, state) = testing::TestOffchainExt::new(); + let mut t = TestExternalities::default(); + t.register_extension(OffchainExt::new(offchain)); + + t.execute_with(|| { + let request: Request = Request::get("http://localhost:1234"); + let pending = request + .add_header("X-Auth", "hunter2") + .send() + .unwrap(); + // make sure it's sent correctly + state.write().fulfill_pending_request( + 0, + testing::PendingRequest { + method: "GET".into(), + uri: "http://localhost:1234".into(), + headers: vec![("X-Auth".into(), "hunter2".into())], + sent: true, + ..Default::default() + }, + b"1234".to_vec(), + None, + ); + + // wait + let mut response = pending.wait().unwrap(); + + // then check the response + let mut headers = response.headers().into_iter(); + assert_eq!(headers.current(), None); + assert_eq!(headers.next(), false); + assert_eq!(headers.current(), None); + + let body = response.body(); + assert_eq!(body.clone().collect::>(), b"1234".to_vec()); + assert_eq!(body.error(), &None); + }) + } + + #[test] + fn should_send_a_post_request() { + let (offchain, state) = testing::TestOffchainExt::new(); + let mut t = TestExternalities::default(); + t.register_extension(OffchainExt::new(offchain)); + + t.execute_with(|| { + let pending = Request::default() + .method(Method::Post) + .url("http://localhost:1234") + .body(vec![b"1234"]) + .send() + .unwrap(); + // make sure it's sent correctly + state.write().fulfill_pending_request( + 0, + testing::PendingRequest { + method: "POST".into(), + uri: "http://localhost:1234".into(), + body: b"1234".to_vec(), + sent: true, + ..Default::default() + }, + b"1234".to_vec(), + Some(("Test".to_owned(), "Header".to_owned())), + ); + + // wait + let mut response = pending.wait().unwrap(); + + // then check the response + let mut headers = response.headers().into_iter(); + assert_eq!(headers.current(), None); + assert_eq!(headers.next(), true); + assert_eq!(headers.current(), Some(("Test", "Header"))); + + let body = response.body(); + assert_eq!(body.clone().collect::>(), b"1234".to_vec()); + assert_eq!(body.error(), &None); + }) + } +} diff --git a/primitives/runtime/src/offchain/mod.rs b/primitives/runtime/src/offchain/mod.rs new file mode 100644 index 0000000000000..742388f9ec422 --- /dev/null +++ b/primitives/runtime/src/offchain/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A collection of higher lever helpers for offchain calls. + +pub mod http; diff --git a/primitives/runtime/src/random_number_generator.rs b/primitives/runtime/src/random_number_generator.rs new file mode 100644 index 0000000000000..e741aac09766f --- /dev/null +++ b/primitives/runtime/src/random_number_generator.rs @@ -0,0 +1,103 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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 simple pseudo random number generator that allows a stream of random numbers to be efficiently +//! created from a single initial seed hash. + +use codec::{Encode, Decode}; +use crate::traits::{Hash, TrailingZeroInput}; + +/// Pseudo-random number streamer. This retains the state of the random number stream. It's as +/// secure as the combination of the seed with which it is constructed and the hash function it uses +/// to cycle elements. +/// +/// It can be saved and later reloaded using the Codec traits. +/// +/// Example: +/// ``` +/// use sp_runtime::traits::{Hash, BlakeTwo256}; +/// use sp_runtime::RandomNumberGenerator; +/// let random_seed = BlakeTwo256::hash(b"Sixty-nine"); +/// let mut rng = >::new(random_seed); +/// assert_eq!(rng.pick_u32(100), 59); +/// assert_eq!(rng.pick_item(&[1, 2, 3]), Some(&1)); +/// ``` +/// +/// This can use any cryptographic `Hash` function as the means of entropy-extension, and avoids +/// needless extensions of entropy. +/// +/// If you're persisting it over blocks, be aware that the sequence will start to repeat. This won't +/// be a practical issue unless you're using tiny hash types (e.g. 64-bit) and pulling hundred of +/// megabytes of data from it. +#[derive(Encode, Decode)] +pub struct RandomNumberGenerator { + current: Hashing::Output, + offset: u32, +} + +impl RandomNumberGenerator { + /// A new source of random data. + pub fn new(seed: Hashing::Output) -> Self { + Self { + current: seed, + offset: 0, + } + } + + fn offset(&self) -> usize { self.offset as usize } + + /// Returns a number at least zero, at most `max`. + pub fn pick_u32(&mut self, max: u32) -> u32 { + let needed = (4 - max.leading_zeros() / 8) as usize; + let top = ((1 << (needed as u64 * 8)) / ((max + 1) as u64) * ((max + 1) as u64) - 1) as u32; + loop { + if self.offset() + needed > self.current.as_ref().len() { + // rehash + self.current = Hashing::hash(self.current.as_ref()); + self.offset = 0; + } + let data = &self.current.as_ref()[self.offset()..self.offset() + needed]; + self.offset += needed as u32; + let raw = u32::decode(&mut TrailingZeroInput::new(data)).unwrap_or(0); + if raw <= top { + break if max < u32::max_value() { + raw % (max + 1) + } else { + raw + } + } + } + } + + /// Returns a number at least zero, at most `max`. + /// + /// This returns a `usize`, but internally it only uses `u32` so avoid consensus problems. + pub fn pick_usize(&mut self, max: usize) -> usize { + self.pick_u32(max as u32) as usize + } + + /// Pick a random element from an array of `items`. + /// + /// This is guaranteed to return `Some` except in the case that the given array `items` is + /// empty. + pub fn pick_item<'a, T>(&mut self, items: &'a [T]) -> Option<&'a T> { + if items.is_empty() { + None + } else { + Some(&items[self.pick_usize(items.len() - 1)]) + } + } +} diff --git a/primitives/runtime/src/testing.rs b/primitives/runtime/src/testing.rs new file mode 100644 index 0000000000000..516d58112647d --- /dev/null +++ b/primitives/runtime/src/testing.rs @@ -0,0 +1,368 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Testing utilities. + +use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer}; +use std::{fmt::Debug, ops::Deref, fmt, cell::RefCell}; +use crate::codec::{Codec, Encode, Decode}; +use crate::traits::{ + self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, + SignedExtension, Dispatchable, +}; +#[allow(deprecated)] +use crate::traits::ValidateUnsigned; +use crate::{generic, KeyTypeId, ApplyExtrinsicResult}; +pub use sp_core::{H256, sr25519}; +use sp_core::{crypto::{CryptoType, Dummy, key_types, Public}, U256}; +use crate::transaction_validity::{TransactionValidity, TransactionValidityError}; + +/// Authority Id +#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug, Hash, Serialize, Deserialize, PartialOrd, Ord)] +pub struct UintAuthorityId(pub u64); + +impl From for UintAuthorityId { + fn from(id: u64) -> Self { + UintAuthorityId(id) + } +} + +impl From for u64 { + fn from(id: UintAuthorityId) -> u64 { + id.0 + } +} + +impl UintAuthorityId { + /// Convert this authority id into a public key. + pub fn to_public_key(&self) -> T { + let bytes: [u8; 32] = U256::from(self.0).into(); + T::from_slice(&bytes) + } +} + +impl CryptoType for UintAuthorityId { + type Pair = Dummy; +} + +impl AsRef<[u8]> for UintAuthorityId { + fn as_ref(&self) -> &[u8] { + // Unsafe, i know, but it's test code and it's just there because it's really convenient to + // keep `UintAuthorityId` as a u64 under the hood. + unsafe { + std::slice::from_raw_parts(&self.0 as *const u64 as *const _, std::mem::size_of::()) + } + } +} + +thread_local! { + /// A list of all UintAuthorityId keys returned to the runtime. + static ALL_KEYS: RefCell> = RefCell::new(vec![]); +} + +impl UintAuthorityId { + /// Set the list of keys returned by the runtime call for all keys of that type. + pub fn set_all_keys>(keys: impl IntoIterator) { + ALL_KEYS.with(|l| *l.borrow_mut() = keys.into_iter().map(Into::into).collect()) + } +} + +impl sp_application_crypto::RuntimeAppPublic for UintAuthorityId { + const ID: KeyTypeId = key_types::DUMMY; + + type Signature = u64; + + fn all() -> Vec { + ALL_KEYS.with(|l| l.borrow().clone()) + } + + fn generate_pair(_: Option>) -> Self { + use rand::RngCore; + UintAuthorityId(rand::thread_rng().next_u64()) + } + + fn sign>(&self, msg: &M) -> Option { + let mut signature = [0u8; 8]; + msg.as_ref().iter() + .chain(std::iter::repeat(&42u8)) + .take(8) + .enumerate() + .for_each(|(i, v)| { signature[i] = *v; }); + + Some(u64::from_le_bytes(signature)) + } + + fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { + let mut msg_signature = [0u8; 8]; + msg.as_ref().iter() + .chain(std::iter::repeat(&42)) + .take(8) + .enumerate() + .for_each(|(i, v)| { msg_signature[i] = *v; }); + + u64::from_le_bytes(msg_signature) == *signature + } +} + +impl OpaqueKeys for UintAuthorityId { + type KeyTypeIdProviders = (); + + fn key_ids() -> &'static [KeyTypeId] { + &[key_types::DUMMY] + } + + fn get_raw(&self, _: KeyTypeId) -> &[u8] { + self.as_ref() + } + + fn get(&self, _: KeyTypeId) -> Option { + self.using_encoded(|mut x| T::decode(&mut x)).ok() + } +} + +impl crate::BoundToRuntimeAppPublic for UintAuthorityId { + type Public = Self; +} + +/// Digest item +pub type DigestItem = generic::DigestItem; + +/// Header Digest +pub type Digest = generic::Digest; + +/// Block Header +#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode, Default)] +#[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, +} + +impl traits::Header for Header { + type Number = u64; + type Hashing = BlakeTwo256; + type Hash = H256; + + fn number(&self) -> &Self::Number { &self.number } + fn set_number(&mut self, num: Self::Number) { self.number = num } + + fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root } + fn set_extrinsics_root(&mut self, root: Self::Hash) { self.extrinsics_root = root } + + fn state_root(&self) -> &Self::Hash { &self.state_root } + fn set_state_root(&mut self, root: Self::Hash) { self.state_root = root } + + fn parent_hash(&self) -> &Self::Hash { &self.parent_hash } + fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash } + + fn digest(&self) -> &Digest { &self.digest } + fn digest_mut(&mut self) -> &mut Digest { &mut self.digest } + + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Digest, + ) -> Self { + Header { + number, + extrinsics_root, + state_root, + parent_hash, + digest, + } + } +} + +impl Header { + /// A new header with the given number and default hash for all other fields. + pub fn new_from_number(number: ::Number) -> Self { + Self { + number, + ..Default::default() + } + } +} + +impl<'a> Deserialize<'a> for Header { + fn deserialize>(de: D) -> Result { + let r = >::deserialize(de)?; + Decode::decode(&mut &r[..]) + .map_err(|e| DeError::custom(format!("Invalid value passed into decode: {}", e.what()))) + } +} + +/// An opaque extrinsic wrapper type. +#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] +pub struct ExtrinsicWrapper(Xt); + +impl traits::Extrinsic for ExtrinsicWrapper { + type Call = (); + type SignaturePayload = (); + + fn is_signed(&self) -> Option { + None + } +} + +impl serde::Serialize for ExtrinsicWrapper { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + self.using_encoded(|bytes| seq.serialize_bytes(bytes)) + } +} + +impl From for ExtrinsicWrapper { + fn from(xt: Xt) -> Self { + ExtrinsicWrapper(xt) + } +} + +impl Deref for ExtrinsicWrapper { + type Target = Xt; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +/// Testing block +#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] +pub struct Block { + /// Block header + pub header: Header, + /// List of extrinsics + pub extrinsics: Vec, +} + +impl traits::Block + for Block +{ + type Extrinsic = Xt; + type Header = Header; + type Hash =
::Hash; + + fn header(&self) -> &Self::Header { + &self.header + } + fn extrinsics(&self) -> &[Self::Extrinsic] { + &self.extrinsics[..] + } + fn deconstruct(self) -> (Self::Header, Vec) { + (self.header, self.extrinsics) + } + fn new(header: Self::Header, extrinsics: Vec) -> Self { + Block { header, extrinsics } + } + fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec { + (header, extrinsics).encode() + } +} + +impl<'a, Xt> Deserialize<'a> for Block where Block: Decode { + fn deserialize>(de: D) -> Result { + let r = >::deserialize(de)?; + Decode::decode(&mut &r[..]) + .map_err(|e| DeError::custom(format!("Invalid value passed into decode: {}", e.what()))) + } +} + +/// Test transaction, tuple of (sender, call, signed_extra) +/// with index only used if sender is some. +/// +/// If sender is some then the transaction is signed otherwise it is unsigned. +#[derive(PartialEq, Eq, Clone, Encode, Decode)] +pub struct TestXt(pub Option<(u64, Extra)>, pub Call); + +impl Serialize for TestXt where TestXt: Encode { + fn serialize(&self, seq: S) -> Result where S: Serializer { + self.using_encoded(|bytes| seq.serialize_bytes(bytes)) + } +} + +impl Debug for TestXt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "TestXt({:?}, ...)", self.0.as_ref().map(|x| &x.0)) + } +} + +impl Checkable for TestXt { + type Checked = Self; + fn check(self, _: &Context) -> Result { Ok(self) } +} +impl traits::Extrinsic for TestXt { + type Call = Call; + type SignaturePayload = (u64, Extra); + + fn is_signed(&self) -> Option { + Some(self.0.is_some()) + } + + fn new(c: Call, sig: Option) -> Option { + Some(TestXt(sig, c)) + } +} + +impl Applyable for TestXt where + Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Dispatchable, + Extra: SignedExtension, + Origin: From>, + Info: Clone, +{ + type AccountId = u64; + type Call = Call; + type DispatchInfo = Info; + + fn sender(&self) -> Option<&Self::AccountId> { self.0.as_ref().map(|x| &x.0) } + + /// Checks to see if this is a valid *transaction*. It returns information on it if so. + #[allow(deprecated)] // Allow ValidateUnsigned + fn validate>( + &self, + _info: Self::DispatchInfo, + _len: usize, + ) -> TransactionValidity { + Ok(Default::default()) + } + + /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, + /// index and sender. + #[allow(deprecated)] // Allow ValidateUnsigned + fn apply>( + self, + info: Self::DispatchInfo, + len: usize, + ) -> ApplyExtrinsicResult { + let maybe_who = if let Some((who, extra)) = self.0 { + Extra::pre_dispatch(extra, &who, &self.1, info, len)?; + Some(who) + } else { + Extra::pre_dispatch_unsigned(&self.1, info, len)?; + None + }; + + Ok(self.1.dispatch(maybe_who.into()).map_err(Into::into)) + } +} diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs new file mode 100644 index 0000000000000..c02856d20d917 --- /dev/null +++ b/primitives/runtime/src/traits.rs @@ -0,0 +1,1362 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for the runtime modules. + +use sp_std::prelude::*; +use sp_std::{self, result, marker::PhantomData, convert::{TryFrom, TryInto}, fmt::Debug}; +use sp_io; +#[cfg(feature = "std")] +use std::fmt::Display; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize, de::DeserializeOwned}; +use sp_core::{self, Hasher, Blake2Hasher, TypeId, RuntimeDebug}; +use crate::codec::{Codec, Encode, Decode}; +use crate::transaction_validity::{ + ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction, +}; +use crate::generic::{Digest, DigestItem}; +pub use sp_arithmetic::traits::{ + SimpleArithmetic, UniqueSaturatedInto, UniqueSaturatedFrom, Saturating, SaturatedConversion, + Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, + CheckedShl, CheckedShr, IntegerSquareRoot +}; +use sp_application_crypto::AppKey; +use impl_trait_for_tuples::impl_for_tuples; + +/// 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; +} + +impl<'a> Lazy<[u8]> for &'a [u8] { + fn get(&mut self) -> &[u8] { &**self } +} + +/// Some type that is able to be collapsed into an account ID. It is not possible to recreate the +/// original value from the account ID. +pub trait IdentifyAccount { + /// The account ID that this can be transformed into. + type AccountId; + /// Transform into an account. + fn into_account(self) -> Self::AccountId; +} + +impl IdentifyAccount for sp_core::ed25519::Public { + type AccountId = Self; + fn into_account(self) -> Self { self } +} + +impl IdentifyAccount for sp_core::sr25519::Public { + type AccountId = Self; + fn into_account(self) -> Self { self } +} + +impl IdentifyAccount for sp_core::ecdsa::Public { + type AccountId = Self; + fn into_account(self) -> Self { self } +} + +/// Means of signature verification. +pub trait Verify { + /// Type of the signer. + type Signer: IdentifyAccount; + /// Verify a signature. Return `true` if signature is valid for the value. + fn verify>(&self, msg: L, signer: &::AccountId) -> bool; +} + +impl Verify for sp_core::ed25519::Signature { + type Signer = sp_core::ed25519::Public; + fn verify>(&self, mut msg: L, signer: &sp_core::ed25519::Public) -> bool { + sp_io::crypto::ed25519_verify(self, msg.get(), signer) + } +} + +impl Verify for sp_core::sr25519::Signature { + type Signer = sp_core::sr25519::Public; + fn verify>(&self, mut msg: L, signer: &sp_core::sr25519::Public) -> bool { + sp_io::crypto::sr25519_verify(self, msg.get(), signer) + } +} + +impl Verify for sp_core::ecdsa::Signature { + type Signer = sp_core::ecdsa::Public; + fn verify>(&self, mut msg: L, signer: &sp_core::ecdsa::Public) -> bool { + match sp_io::crypto::secp256k1_ecdsa_recover_compressed( + self.as_ref(), + &sp_io::hashing::blake2_256(msg.get()), + ) { + Ok(pubkey) => signer.as_compressed().map(|s| &s[..] == &pubkey[..]).unwrap_or(false), + _ => false, + } + } +} + +/// Means of signature verification of an application key. +pub trait AppVerify { + /// Type of the signer. + type AccountId; + /// Verify a signature. Return `true` if signature is valid for the value. + fn verify>(&self, msg: L, signer: &Self::AccountId) -> bool; +} + +impl< + S: Verify::Public as sp_application_crypto::AppPublic>::Generic> + From, + T: sp_application_crypto::Wraps + sp_application_crypto::AppKey + sp_application_crypto::AppSignature + + AsRef + AsMut + From, +> AppVerify for T where + ::Signer: IdentifyAccount::Signer>, + <::Public as sp_application_crypto::AppPublic>::Generic: + IdentifyAccount::Public as sp_application_crypto::AppPublic>::Generic>, +{ + type AccountId = ::Public; + fn verify>(&self, msg: L, signer: &::Public) -> bool { + use sp_application_crypto::IsWrappedBy; + let inner: &S = self.as_ref(); + let inner_pubkey = <::Public as sp_application_crypto::AppPublic>::Generic::from_ref(&signer); + Verify::verify(inner, msg, inner_pubkey) + } +} + +/// An error type that indicates that the origin is invalid. +#[derive(Encode, Decode)] +pub struct BadOrigin; + +impl From for &'static str { + fn from(_: BadOrigin) -> &'static str { + "Bad origin" + } +} + +/// Some sort of check on the origin is performed by this object. +pub trait EnsureOrigin { + /// A return type. + type Success; + /// Perform the origin check. + fn ensure_origin(o: OuterOrigin) -> result::Result { + Self::try_origin(o).map_err(|_| BadOrigin) + } + /// Perform the origin check. + fn try_origin(o: OuterOrigin) -> result::Result; +} + +/// An error that indicates that a lookup failed. +#[derive(Encode, Decode, RuntimeDebug)] +pub struct LookupError; + +impl From for &'static str { + fn from(_: LookupError) -> &'static str { + "Can not lookup" + } +} + +impl From for TransactionValidityError { + fn from(_: LookupError) -> Self { + UnknownTransaction::CannotLookup.into() + } +} + +/// Means of changing one type into another in a manner dependent on the source type. +pub trait Lookup { + /// Type to lookup from. + type Source; + /// Type to lookup into. + type Target; + /// Attempt a lookup. + fn lookup(&self, s: Self::Source) -> 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 + Debug; + /// Type to lookup into. + type Target; + /// Attempt a lookup. + fn lookup(s: Self::Source) -> 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 { Ok(x) } + fn unlookup(x: T) -> T { x } +} + +impl Lookup for IdentityLookup { + type Source = T; + type Target = T; + fn lookup(&self, x: T) -> Result { Ok(x) } +} + +/// 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 } +} + +/// A structure that performs standard conversion using the standard Rust conversion traits. +pub struct ConvertInto; +impl> Convert for ConvertInto { + fn convert(a: A) -> B { a.into() } +} + +/// Convenience type to work around the highly unergonomic syntax needed +/// to invoke the functions of overloaded generic traits, in this case +/// `TryFrom` and `TryInto`. +pub trait CheckedConversion { + /// Convert from a value of `T` into an equivalent instance of `Option`. + /// + /// This just uses `TryFrom` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn checked_from(t: T) -> Option where Self: TryFrom { + >::try_from(t).ok() + } + /// Consume self to return `Some` equivalent value of `Option`. + /// + /// This just uses `TryInto` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn checked_into(self) -> Option where Self: TryInto { + >::try_into(self).ok() + } +} +impl CheckedConversion for T {} + +/// Multiply and divide by a number that isn't necessarily the same type. Basically just the same +/// as `Mul` and `Div` except it can be used for all basic numeric types. +pub trait Scale { + /// The output type of the product of `self` and `Other`. + type Output; + + /// @return the product of `self` and `other`. + fn mul(self, other: Other) -> Self::Output; + + /// @return the integer division of `self` and `other`. + fn div(self, other: Other) -> Self::Output; + + /// @return the modulo remainder of `self` and `other`. + fn rem(self, other: Other) -> Self::Output; +} +macro_rules! impl_scale { + ($self:ty, $other:ty) => { + impl Scale<$other> for $self { + type Output = Self; + fn mul(self, other: $other) -> Self::Output { self * (other as Self) } + fn div(self, other: $other) -> Self::Output { self / (other as Self) } + fn rem(self, other: $other) -> Self::Output { self % (other as Self) } + } + } +} +impl_scale!(u128, u128); +impl_scale!(u128, u64); +impl_scale!(u128, u32); +impl_scale!(u128, u16); +impl_scale!(u128, u8); +impl_scale!(u64, u64); +impl_scale!(u64, u32); +impl_scale!(u64, u16); +impl_scale!(u64, u8); +impl_scale!(u32, u32); +impl_scale!(u32, u16); +impl_scale!(u32, u8); +impl_scale!(u16, u16); +impl_scale!(u16, u8); +impl_scale!(u8, u8); + +/// Trait for things that can be clear (have no bits set). For numeric types, essentially the same +/// as `Zero`. +pub trait Clear { + /// True iff no bits are set. + fn is_clear(&self) -> bool; + + /// Return the value of Self that is clear. + fn clear() -> Self; +} + +impl Clear for T { + fn is_clear(&self) -> bool { *self == Self::clear() } + fn clear() -> Self { Default::default() } +} + +/// A meta trait for all bit ops. +pub trait SimpleBitOps: + Sized + Clear + + sp_std::ops::BitOr + + sp_std::ops::BitXor + + sp_std::ops::BitAnd +{} +impl + + sp_std::ops::BitXor + + sp_std::ops::BitAnd +> SimpleBitOps for T {} + +/// The block finalization trait. Implementing this lets you express what should happen +/// for your module when the block is ending. +#[impl_for_tuples(30)] +pub trait OnFinalize { + /// The block is being finalized. Implement to have something happen. + fn on_finalize(_n: BlockNumber) {} +} + +/// The block initialization trait. Implementing this lets you express what should happen +/// for your module when the block is beginning (right before the first extrinsic is executed). +#[impl_for_tuples(30)] +pub trait OnInitialize { + /// The block is being initialized. Implement to have something happen. + fn on_initialize(_n: BlockNumber) {} +} + +/// Off-chain computation trait. +/// +/// Implementing this trait on a module allows you to perform long-running tasks +/// that make (by default) validators generate transactions that feed results +/// of those long-running computations back on chain. +/// +/// NOTE: This function runs off-chain, so it can access the block state, +/// but cannot preform any alterations. More specifically alterations are +/// not forbidden, but they are not persisted in any way after the worker +/// has finished. +#[impl_for_tuples(30)] +pub trait OffchainWorker { + /// This function is being called after every block import (when fully synced). + /// + /// Implement this and use any of the `Offchain` `sp_io` set of APIs + /// to perform off-chain computations, calls and submit transactions + /// with results to trigger any on-chain changes. + /// Any state alterations are lost and are not persisted. + fn offchain_worker(_n: BlockNumber) {} +} + +/// Abstraction around hashing +// Stupid bug in the Rust compiler believes derived +// traits must be fulfilled by all type parameters. +pub trait Hash: 'static + MaybeSerializeDeserialize + Debug + Clone + Eq + PartialEq { + /// The hash type produced. + type Output: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + Encode + Decode; + + /// The associated hash_db Hasher type. + type Hasher: Hasher; + + /// Produce the hash of some byte-slice. + fn hash(s: &[u8]) -> Self::Output; + + /// Produce the hash of some codec-encodable value. + fn hash_of(s: &S) -> Self::Output { + Encode::using_encoded(s, Self::hash) + } + + /// The ordered Patricia tree root of the given `input`. + fn ordered_trie_root(input: Vec>) -> Self::Output; + + /// The Patricia tree root of the given mapping. + fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output; +} + +/// Blake2-256 Hash implementation. +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BlakeTwo256; + +impl Hash for BlakeTwo256 { + type Output = sp_core::H256; + type Hasher = Blake2Hasher; + fn hash(s: &[u8]) -> Self::Output { + sp_io::hashing::blake2_256(s).into() + } + + fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { + sp_io::trie::blake2_256_root(input) + } + + fn ordered_trie_root(input: Vec>) -> Self::Output { + sp_io::trie::blake2_256_ordered_root(input) + } +} + +/// 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); +} + +impl CheckEqual for sp_core::H256 { + #[cfg(feature = "std")] + fn check_equal(&self, other: &Self) { + use sp_core::hexdisplay::HexDisplay; + if self != other { + println!( + "Hash: given={}, expected={}", + HexDisplay::from(self.as_fixed_bytes()), + HexDisplay::from(other.as_fixed_bytes()), + ); + } + } + + #[cfg(not(feature = "std"))] + fn check_equal(&self, other: &Self) { + if self != other { + "Hash not equal".print(); + self.as_bytes().print(); + other.as_bytes().print(); + } + } +} + +impl CheckEqual for super::generic::DigestItem where H: Encode { + #[cfg(feature = "std")] + fn check_equal(&self, other: &Self) { + if self != other { + println!("DigestItem: given={:?}, expected={:?}", self, other); + } + } + + #[cfg(not(feature = "std"))] + fn check_equal(&self, other: &Self) { + if self != other { + "DigestItem not equal".print(); + (&Encode::encode(self)[..]).print(); + (&Encode::encode(other)[..]).print(); + } + } +} + +macro_rules! impl_maybe_marker { + ( $( $(#[$doc:meta])+ $trait_name:ident: $($trait_bound:path),+ );+ ) => { + $( + $(#[$doc])+ + #[cfg(feature = "std")] + pub trait $trait_name: $($trait_bound +)+ {} + #[cfg(feature = "std")] + impl $trait_name for T {} + + $(#[$doc])+ + #[cfg(not(feature = "std"))] + pub trait $trait_name {} + #[cfg(not(feature = "std"))] + impl $trait_name for T {} + )+ + } +} + +impl_maybe_marker!( + /// A type that implements Display when in std environment. + MaybeDisplay: Display; + + /// A type that implements Hash when in std environment. + MaybeHash: sp_std::hash::Hash; + + /// A type that implements Serialize when in std environment. + MaybeSerialize: Serialize; + + /// A type that implements Serialize, DeserializeOwned and Debug when in std environment. + MaybeSerializeDeserialize: DeserializeOwned, Serialize +); + +/// A type that provides a randomness beacon. +pub trait RandomnessBeacon { + /// Returns 32 bytes of random data. The output will change eventually, but + /// is not guaranteed to be different between any two calls. + /// + /// # Security + /// + /// This MUST NOT be used for gambling, as it can be influenced by a + /// malicious validator in the short term. It MAY be used in many + /// cryptographic protocols, however, so long as one remembers that this + /// (like everything else on-chain) is public. For example, it can be + /// used where a number is needed that cannot have been chosen by an + /// adversary, for purposes such as public-coin zero-knowledge proofs. + fn random() -> [u8; 32]; +} + +/// A type that can be used in runtime structures. +pub trait Member: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static {} +impl Member for T {} + +/// Determine if a `MemberId` is a valid member. +pub trait IsMember { + /// Is the given `MemberId` a valid member? + fn is_member(member_id: &MemberId) -> bool; +} + +/// Something which fulfills the abstract idea of a Substrate header. It has types for a `Number`, +/// a `Hash` and a `Hashing`. It provides access to an `extrinsics_root`, `state_root` and +/// `parent_hash`, as well as a `digest` and a block `number`. +/// +/// You can also create a `new` one from those fields. +pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerialize + Debug + 'static { + /// Header number. + type Number: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + + Copy + MaybeDisplay + SimpleArithmetic + Codec + sp_std::str::FromStr; + /// Header hash type + type Hash: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + Ord + + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; + /// Hashing algorithm + type Hashing: Hash; + + /// Creates new header. + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Digest, + ) -> Self; + + /// Returns a reference to the header number. + fn number(&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; + /// 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; + /// 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; + /// Sets the parent hash. + fn set_parent_hash(&mut self, hash: Self::Hash); + + /// Returns a reference to the digest. + fn digest(&self) -> &Digest; + /// Get a mutable reference to the digest. + fn digest_mut(&mut self) -> &mut Digest; + + /// Returns the hash of the header. + fn hash(&self) -> Self::Hash { + ::hash_of(self) + } +} + +/// Something which fulfills the abstract idea of a Substrate block. It has types for +/// `Extrinsic` pieces 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 + MaybeSerialize + Debug + 'static { + /// Type for extrinsics. + type Extrinsic: Member + Codec + Extrinsic + MaybeSerialize; + /// Header type. + type Header: Header; + /// Block hash type. + type Hash: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + Ord + + 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()) + } + /// Creates an encoded block from the given `header` and `extrinsics` without requiring the + /// creation of an instance. + fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec; +} + +/// Something that acts like an `Extrinsic`. +pub trait Extrinsic: Sized { + /// The function call. + type Call; + + /// The payload we carry for signed extrinsics. + /// + /// Usually it will contain a `Signature` and + /// may include some additional data that are specific to signed + /// extrinsics. + type SignaturePayload; + + /// Is this `Extrinsic` signed? + /// If no information are available about signed/unsigned, `None` should be returned. + fn is_signed(&self) -> Option { None } + + /// Create new instance of the extrinsic. + /// + /// Extrinsics can be split into: + /// 1. Inherents (no signature; created by validators during block production) + /// 2. Unsigned Transactions (no signature; represent "system calls" or other special kinds of calls) + /// 3. Signed Transactions (with signature; a regular transactions with known origin) + fn new(_call: Self::Call, _signed_data: Option) -> Option { None } +} + +/// Extract the hasher type for a block. +pub type HasherFor = as Hash>::Hasher; +/// Extract the hashing type for a block. +pub type HashFor = <::Header as Header>::Hashing; +/// Extract the number type for a block. +pub type NumberFor = <::Header as Header>::Number; +/// Extract the digest type for a block. +pub type DigestFor = Digest<<::Header as Header>::Hash>; +/// Extract the digest item type for a block. +pub type DigestItemFor = DigestItem<<::Header as Header>::Hash>; + +/// 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. +/// Implement for pieces of information that require some additional context `Context` in order to be +/// checked. +pub trait Checkable: Sized { + /// Returned if `check` succeeds. + type Checked; + + /// Check self, given an instance of Context. + fn check(self, c: &Context) -> Result; +} + +/// 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. +/// Implement for pieces of information that don't require additional context in order to be +/// checked. +pub trait BlindCheckable: Sized { + /// Returned if `check` succeeds. + type Checked; + + /// Check self. + fn check(self) -> Result; +} + +// Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`. +impl Checkable for T { + type Checked = ::Checked; + + fn check(self, _c: &Context) -> Result { + BlindCheckable::check(self) + } +} + +/// A lazy call (module function and argument values) that can be executed via its `dispatch` +/// method. +pub trait Dispatchable { + /// Every function call from 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; + /// Actually dispatch this call and result the result of it. + fn dispatch(self, origin: Self::Origin) -> crate::DispatchResult; +} + +/// Means by which a transaction may be extended. This type embodies both the data and the logic +/// that should be additionally associated with the transaction. It should be plain old data. +pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq { + /// The type which encodes the sender identity. + type AccountId; + + /// The type which encodes the call to be dispatched. + type Call; + + /// Any additional data that will go into the signed payload. This may be created dynamically + /// from the transaction using the `additional_signed` function. + type AdditionalSigned: Encode; + + /// The type that encodes information that can be passed from pre_dispatch to post-dispatch. + type Pre: Default; + + /// An opaque set of information attached to the transaction. This could be constructed anywhere + /// down the line in a runtime. The current Substrate runtime uses a struct with the same name + /// to represent the dispatch class and weight. + type DispatchInfo: Clone; + + /// Construct any additional data that should be in the signed payload of the transaction. Can + /// also perform any pre-signature-verification checks and return an error if needed. + fn additional_signed(&self) -> Result; + + /// Validate a signed transaction for the transaction queue. + /// + /// This function can be called frequently by the transaction queue, + /// to obtain transaction validity against current state. + /// It should perform all checks that determine a valid transaction, + /// that can pay for its execution and quickly eliminate ones + /// that are stale or incorrect. + /// + /// Make sure to perform the same checks in `pre_dispatch` function. + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: Self::DispatchInfo, + _len: usize, + ) -> TransactionValidity { + Ok(ValidTransaction::default()) + } + + /// Do any pre-flight stuff for a signed transaction. + /// + /// Note this function by default delegates to `validate`, so that + /// all checks performed for the transaction queue are also performed during + /// the dispatch phase (applying the extrinsic). + /// + /// If you ever override this function, you need to make sure to always + /// perform the same validation as in `validate`. + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: Self::DispatchInfo, + len: usize, + ) -> Result { + self.validate(who, call, info.clone(), len) + .map(|_| Self::Pre::default()) + .map_err(Into::into) + } + + /// Validate an unsigned transaction for the transaction queue. + /// + /// This function can be called frequently by the transaction queue + /// to obtain transaction validity against current state. + /// It should perform all checks that determine a valid unsigned transaction, + /// and quickly eliminate ones that are stale or incorrect. + /// + /// Make sure to perform the same checks in `pre_dispatch_unsigned` function. + fn validate_unsigned( + _call: &Self::Call, + _info: Self::DispatchInfo, + _len: usize, + ) -> TransactionValidity { + Ok(ValidTransaction::default()) + } + + /// Do any pre-flight stuff for a unsigned transaction. + /// + /// Note this function by default delegates to `validate_unsigned`, so that + /// all checks performed for the transaction queue are also performed during + /// the dispatch phase (applying the extrinsic). + /// + /// If you ever override this function, you need to make sure to always + /// perform the same validation as in `validate_unsigned`. + fn pre_dispatch_unsigned( + call: &Self::Call, + info: Self::DispatchInfo, + len: usize, + ) -> Result { + Self::validate_unsigned(call, info.clone(), len) + .map(|_| Self::Pre::default()) + .map_err(Into::into) + } + + /// Do any post-flight stuff for a transaction. + fn post_dispatch(_pre: Self::Pre, _info: Self::DispatchInfo, _len: usize) { } +} + +#[impl_for_tuples(1, 12)] +impl SignedExtension for Tuple { + for_tuples!( where #( Tuple: SignedExtension )* ); + type AccountId = AccountId; + type Call = Call; + type DispatchInfo = Info; + for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); + for_tuples!( type Pre = ( #( Tuple::Pre ),* ); ); + + fn additional_signed(&self) -> Result { + Ok(for_tuples!( ( #( Tuple.additional_signed()? ),* ) )) + } + + fn validate( + &self, + who: &Self::AccountId, + call: &Self::Call, + info: Self::DispatchInfo, + len: usize, + ) -> TransactionValidity { + let valid = ValidTransaction::default(); + for_tuples!( #( let valid = valid.combine_with(Tuple.validate(who, call, info.clone(), len)?); )* ); + Ok(valid) + } + + fn pre_dispatch(self, who: &Self::AccountId, call: &Self::Call, info: Self::DispatchInfo, len: usize) + -> Result + { + Ok(for_tuples!( ( #( Tuple.pre_dispatch(who, call, info.clone(), len)? ),* ) )) + } + + fn validate_unsigned( + call: &Self::Call, + info: Self::DispatchInfo, + len: usize, + ) -> TransactionValidity { + let valid = ValidTransaction::default(); + for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info.clone(), len)?); )* ); + Ok(valid) + } + + fn pre_dispatch_unsigned( + call: &Self::Call, + info: Self::DispatchInfo, + len: usize, + ) -> Result { + Ok(for_tuples!( ( #( Tuple::pre_dispatch_unsigned(call, info.clone(), len)? ),* ) )) + } + + fn post_dispatch( + pre: Self::Pre, + info: Self::DispatchInfo, + len: usize, + ) { + for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info.clone(), len); )* ) + } +} + +/// Only for bare bone testing when you don't care about signed extensions at all. +#[cfg(feature = "std")] +impl SignedExtension for () { + type AccountId = u64; + type AdditionalSigned = (); + type Call = (); + type Pre = (); + type DispatchInfo = (); + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } +} + +/// 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 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; + + /// Type by which we can dispatch. Restricts the `UnsignedValidator` type. + type Call; + + /// An opaque set of information attached to the transaction. + type DispatchInfo: Clone; + + /// Returns a reference to the sender if any. + fn sender(&self) -> Option<&Self::AccountId>; + + /// Checks to see if this is a valid *transaction*. It returns information on it if so. + #[allow(deprecated)] // Allow ValidateUnsigned + fn validate>( + &self, + info: Self::DispatchInfo, + len: usize, + ) -> TransactionValidity; + + /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, + /// index and sender. + #[allow(deprecated)] // Allow ValidateUnsigned + fn apply>( + self, + info: Self::DispatchInfo, + len: usize, + ) -> crate::ApplyExtrinsicResult; +} + +/// A marker trait for something that knows the type of the runtime block. +pub trait GetRuntimeBlockType { + /// The `RuntimeBlock` type. + type RuntimeBlock: self::Block; +} + +/// A marker trait for something that knows the type of the node block. +pub trait GetNodeBlockType { + /// The `NodeBlock` type. + type NodeBlock: self::Block; +} + +/// Something that can validate unsigned extrinsics for the transaction pool. +/// +/// Note that any checks done here are only used for determining the validity of +/// the transaction for the transaction pool. +/// During block execution phase one need to perform the same checks anyway, +/// since this function is not being called. +#[deprecated(note = "Use SignedExtensions instead.")] +pub trait ValidateUnsigned { + /// The call to validate + type Call; + + /// Validate the call right before dispatch. + /// + /// This method should be used to prevent transactions already in the pool + /// (i.e. passing `validate_unsigned`) from being included in blocks + /// in case we know they now became invalid. + /// + /// By default it's a good idea to call `validate_unsigned` from within + /// this function again to make sure we never include an invalid transaction. + /// + /// Changes made to storage WILL be persisted if the call returns `Ok`. + fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { + Self::validate_unsigned(call) + .map(|_| ()) + .map_err(Into::into) + } + + /// Return the validity of the call + /// + /// This doesn't execute any side-effects; it merely checks + /// whether the transaction would panic if it were included or not. + /// + /// Changes made to storage should be discarded by caller. + fn validate_unsigned(call: &Self::Call) -> TransactionValidity; +} + +/// Opaque datatype that may be destructured into a series of raw byte slices (which represent +/// individual keys). +pub trait OpaqueKeys: Clone { + /// Types bound to this opaque keys that provide the key type ids returned. + type KeyTypeIdProviders; + + /// Return the key-type IDs supported by this set. + fn key_ids() -> &'static [crate::KeyTypeId]; + /// Get the raw bytes of key with key-type ID `i`. + fn get_raw(&self, i: super::KeyTypeId) -> &[u8]; + /// Get the decoded key with index `i`. + fn get(&self, i: super::KeyTypeId) -> Option { + T::decode(&mut self.get_raw(i)).ok() + } + /// Verify a proof of ownership for the keys. + fn ownership_proof_is_valid(&self, _proof: &[u8]) -> bool { true } +} + +/// Input that adds infinite number of zero after wrapped input. +/// +/// This can add an infinite stream of zeros onto any input, not just a slice as with +/// `TrailingZerosInput`. +pub struct AppendZerosInput<'a, T>(&'a mut T); + +impl<'a, T> AppendZerosInput<'a, T> { + /// Create a new instance from the given byte array. + pub fn new(input: &'a mut T) -> Self { + Self(input) + } +} + +impl<'a, T: codec::Input> codec::Input for AppendZerosInput<'a, T> { + fn remaining_len(&mut self) -> Result, codec::Error> { + Ok(None) + } + + fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> { + let remaining = self.0.remaining_len()?; + let completed = if let Some(n) = remaining { + let readable = into.len().min(n); + // this should never fail if `remaining_len` API is implemented correctly. + self.0.read(&mut into[..readable])?; + readable + } else { + // Fill it byte-by-byte. + let mut i = 0; + while i < into.len() { + if let Ok(b) = self.0.read_byte() { + into[i] = b; + i += 1; + } else { + break; + } + } + i + }; + // Fill the rest with zeros. + for i in &mut into[completed..] { + *i = 0; + } + Ok(()) + } +} + +/// Input that adds infinite number of zero after wrapped input. +pub struct TrailingZeroInput<'a>(&'a [u8]); + +impl<'a> TrailingZeroInput<'a> { + /// Create a new instance from the given byte array. + pub fn new(data: &'a [u8]) -> Self { + Self(data) + } +} + +impl<'a> codec::Input for TrailingZeroInput<'a> { + fn remaining_len(&mut self) -> Result, codec::Error> { + Ok(None) + } + + fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> { + let len_from_inner = into.len().min(self.0.len()); + into[..len_from_inner].copy_from_slice(&self.0[..len_from_inner]); + for i in &mut into[len_from_inner..] { + *i = 0; + } + self.0 = &self.0[len_from_inner..]; + + Ok(()) + } +} + +/// This type can be converted into and possibly from an AccountId (which itself is generic). +pub trait AccountIdConversion: Sized { + /// Convert into an account ID. This is infallible. + fn into_account(&self) -> AccountId { self.into_sub_account(&()) } + + /// Try to convert an account ID into this type. Might not succeed. + fn try_from_account(a: &AccountId) -> Option { + Self::try_from_sub_account::<()>(a).map(|x| x.0) + } + + /// Convert this value amalgamated with the a secondary "sub" value into an account ID. This is + /// infallible. + /// + /// NOTE: The account IDs from this and from `into_account` are *not* guaranteed to be distinct + /// for any given value of `self`, nor are different invocations to this with different types + /// `T`. For example, the following will all encode to the same account ID value: + /// - `self.into_sub_account(0u32)` + /// - `self.into_sub_account(vec![0u8; 0])` + /// - `self.into_account()` + fn into_sub_account(&self, sub: S) -> AccountId; + + /// Try to convert an account ID into this type. Might not succeed. + fn try_from_sub_account(x: &AccountId) -> Option<(Self, S)>; +} + +/// Format is TYPE_ID ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing zeroes to +/// fill AccountId. +impl AccountIdConversion for Id { + fn into_sub_account(&self, sub: S) -> T { + (Id::TYPE_ID, self, sub).using_encoded(|b| + T::decode(&mut TrailingZeroInput(b)) + ).unwrap_or_default() + } + + fn try_from_sub_account(x: &T) -> Option<(Self, S)> { + x.using_encoded(|d| { + if &d[0..4] != Id::TYPE_ID { return None } + let mut cursor = &d[4..]; + let result = Decode::decode(&mut cursor).ok()?; + if cursor.iter().all(|x| *x == 0) { + Some(result) + } else { + None + } + }) + } +} + +/// Calls a given macro a number of times with a set of fixed params and an incrementing numeral. +/// e.g. +/// ```nocompile +/// count!(println ("{}",) foo, bar, baz); +/// // Will result in three `println!`s: "0", "1" and "2". +/// ``` +#[macro_export] +macro_rules! count { + ($f:ident ($($x:tt)*) ) => (); + ($f:ident ($($x:tt)*) $x1:tt) => { $f!($($x)* 0); }; + ($f:ident ($($x:tt)*) $x1:tt, $x2:tt) => { $f!($($x)* 0); $f!($($x)* 1); }; + ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt) => { $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); }; + ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt) => { + $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); + }; + ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt, $x5:tt) => { + $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); $f!($($x)* 4); + }; +} + +/// Implement `OpaqueKeys` for a described struct. +/// +/// Every field type must implement [`BoundToRuntimeAppPublic`](crate::BoundToRuntimeAppPublic). +/// `KeyTypeIdProviders` is set to the types given as fields. +/// +/// ```rust +/// use sp_runtime::{ +/// impl_opaque_keys, KeyTypeId, BoundToRuntimeAppPublic, app_crypto::{sr25519, ed25519} +/// }; +/// +/// pub struct KeyModule; +/// impl BoundToRuntimeAppPublic for KeyModule { type Public = ed25519::AppPublic; } +/// +/// pub struct KeyModule2; +/// impl BoundToRuntimeAppPublic for KeyModule2 { type Public = sr25519::AppPublic; } +/// +/// impl_opaque_keys! { +/// pub struct Keys { +/// pub key_module: KeyModule, +/// pub key_module2: KeyModule2, +/// } +/// } +/// ``` +#[macro_export] +macro_rules! impl_opaque_keys { + ( + pub struct $name:ident { + $( + pub $field:ident: $type:ty, + )* + } + ) => { + #[derive( + Default, Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + #[cfg_attr(feature = "std", derive($crate::serde::Serialize, $crate::serde::Deserialize))] + pub struct $name { + $( + pub $field: <$type as $crate::BoundToRuntimeAppPublic>::Public, + )* + } + + impl $name { + /// Generate a set of keys with optionally using the given seed. + /// + /// The generated key pairs are stored in the keystore. + /// + /// Returns the concatenated SCALE encoded public keys. + pub fn generate(seed: Option<$crate::sp_std::vec::Vec>) -> $crate::sp_std::vec::Vec { + let keys = Self{ + $( + $field: < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::generate_pair(seed.clone()), + )* + }; + $crate::codec::Encode::encode(&keys) + } + } + + impl $crate::traits::OpaqueKeys for $name { + type KeyTypeIdProviders = ( $( $type, )* ); + + fn key_ids() -> &'static [$crate::KeyTypeId] { + &[ + $( + < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::ID + ),* + ] + } + + fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] { + match i { + $( + i if i == < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::ID => + self.$field.as_ref(), + )* + _ => &[], + } + } + } + }; +} + +/// Trait for things which can be printed from the runtime. +pub trait Printable { + /// Print the object. + fn print(&self); +} + +impl Printable for u8 { + fn print(&self) { + (*self as u64).print() + } +} + +impl Printable for u32 { + fn print(&self) { + (*self as u64).print() + } +} + +impl Printable for usize { + fn print(&self) { + (*self as u64).print() + } +} + +impl Printable for u64 { + fn print(&self) { + sp_io::misc::print_num(*self); + } +} + +impl Printable for &[u8] { + fn print(&self) { + sp_io::misc::print_hex(self); + } +} + +impl Printable for &str { + fn print(&self) { + sp_io::misc::print_utf8(self.as_bytes()); + } +} + +#[impl_for_tuples(1, 12)] +impl Printable for Tuple { + fn print(&self) { + for_tuples!( #( Tuple.print(); )* ) + } +} + +/// Something that can convert a [`BlockId`] to a number or a hash. +#[cfg(feature = "std")] +pub trait BlockIdTo { + /// The error type that will be returned by the functions. + type Error: std::fmt::Debug; + + /// Convert the given `block_id` to the corresponding block hash. + fn to_hash( + &self, + block_id: &crate::generic::BlockId, + ) -> Result, Self::Error>; + + /// Convert the given `block_id` to the corresponding block number. + fn to_number( + &self, + block_id: &crate::generic::BlockId, + ) -> Result>, Self::Error>; +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::codec::{Encode, Decode, Input}; + use sp_core::{crypto::Pair, ecdsa}; + + mod t { + use sp_core::crypto::KeyTypeId; + use sp_application_crypto::{app_crypto, sr25519}; + app_crypto!(sr25519, KeyTypeId(*b"test")); + } + + #[test] + fn app_verify_works() { + use t::*; + use super::AppVerify; + + let s = Signature::default(); + let _ = s.verify(&[0u8; 100][..], &Public::default()); + } + + #[derive(Encode, Decode, Default, PartialEq, Debug)] + struct U32Value(u32); + impl super::TypeId for U32Value { + const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca]; + } + // cafef00d + + #[derive(Encode, Decode, Default, PartialEq, Debug)] + struct U16Value(u16); + impl super::TypeId for U16Value { + const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0]; + } + // f00dcafe + + type AccountId = u64; + + #[test] + fn into_account_should_work() { + let r: AccountId = U32Value::into_account(&U32Value(0xdeadbeef)); + assert_eq!(r, 0x_deadbeef_cafef00d); + } + + #[test] + fn try_from_account_should_work() { + let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64); + assert_eq!(r.unwrap(), U32Value(0xdeadbeef)); + } + + #[test] + fn into_account_with_fill_should_work() { + let r: AccountId = U16Value::into_account(&U16Value(0xc0da)); + assert_eq!(r, 0x_0000_c0da_f00dcafe); + } + + #[test] + fn try_from_account_with_fill_should_work() { + let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64); + assert_eq!(r.unwrap(), U16Value(0xc0da)); + } + + #[test] + fn bad_try_from_account_should_fail() { + let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64); + assert!(r.is_none()); + let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64); + assert!(r.is_none()); + } + + #[test] + fn trailing_zero_should_work() { + let mut t = super::TrailingZeroInput(&[1, 2, 3]); + assert_eq!(t.remaining_len(), Ok(None)); + let mut buffer = [0u8; 2]; + assert_eq!(t.read(&mut buffer), Ok(())); + assert_eq!(t.remaining_len(), Ok(None)); + assert_eq!(buffer, [1, 2]); + assert_eq!(t.read(&mut buffer), Ok(())); + assert_eq!(t.remaining_len(), Ok(None)); + assert_eq!(buffer, [3, 0]); + assert_eq!(t.read(&mut buffer), Ok(())); + assert_eq!(t.remaining_len(), Ok(None)); + assert_eq!(buffer, [0, 0]); + } + + #[test] + fn ecdsa_verify_works() { + let msg = &b"test-message"[..]; + let (pair, _) = ecdsa::Pair::generate(); + + let signature = pair.sign(&msg); + assert!(ecdsa::Pair::verify(&signature, msg, &pair.public())); + + assert!(signature.verify(msg, &pair.public())); + assert!(signature.verify(msg, &pair.public().into_compressed().unwrap())); + } +} diff --git a/core/sr-primitives/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs similarity index 95% rename from core/sr-primitives/src/transaction_validity.rs rename to primitives/runtime/src/transaction_validity.rs index 3e765215b979a..6dfb80b6d7e45 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 @@ //! Transaction validity interface. -use rstd::prelude::*; +use sp_std::prelude::*; use crate::codec::{Encode, Decode}; use crate::RuntimeDebug; @@ -146,18 +146,6 @@ impl From for TransactionValidityError { } } -impl From for crate::ApplyError { - fn from(invalid: InvalidTransaction) -> crate::ApplyError { - TransactionValidityError::from(invalid).into() - } -} - -impl From for crate::ApplyError { - fn from(unknown: UnknownTransaction) -> crate::ApplyError { - TransactionValidityError::from(unknown).into() - } -} - /// Information on a transaction's validity and, if valid, on how it relates to other transactions. pub type TransactionValidity = Result; diff --git a/primitives/sandbox/Cargo.toml b/primitives/sandbox/Cargo.toml new file mode 100755 index 0000000000000..ff3b7662cd5a5 --- /dev/null +++ b/primitives/sandbox/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "sp-sandbox" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +wasmi = { version = "0.6.2", optional = true } +sp-core = { version = "2.0.0", default-features = false, path = "../core" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-io = { version = "2.0.0", default-features = false, path = "../io" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } + +[dev-dependencies] +wabt = "0.9.2" +assert_matches = "1.3.0" + +[features] +default = ["std"] +std = [ + "wasmi", + "sp-core/std", + "sp-std/std", + "codec/std", + "sp-io/std", +] +strict = [] diff --git a/primitives/sandbox/src/lib.rs b/primitives/sandbox/src/lib.rs new file mode 100755 index 0000000000000..86098e73af15b --- /dev/null +++ b/primitives/sandbox/src/lib.rs @@ -0,0 +1,208 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This crate provides means to instantiate and execute wasm modules. +//! +//! It works even when the user of this library executes from +//! inside the wasm VM. In this case the same VM is used for execution +//! of both the sandbox owner and the sandboxed module, without compromising security +//! and without the performance penalty of full wasm emulation inside wasm. +//! +//! This is achieved by using bindings to the wasm VM, which are published by the host API. +//! This API is thin and consists of only a handful functions. It contains functions for instantiating +//! modules and executing them, but doesn't contain functions for inspecting the module +//! structure. The user of this library is supposed to read the wasm module. +//! +//! When this crate is used in the `std` environment all these functions are implemented by directly +//! calling the wasm VM. +//! +//! Examples of possible use-cases for this library are not limited to the following: +//! +//! - implementing smart-contract runtimes that use wasm for contract code +//! - executing a wasm substrate runtime inside of a wasm parachain + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] + +use sp_std::prelude::*; + +pub use sp_core::sandbox::{TypedValue, ReturnValue, HostError}; + +mod imp { + #[cfg(feature = "std")] + include!("../with_std.rs"); + + #[cfg(not(feature = "std"))] + include!("../without_std.rs"); +} + +/// Error that can occur while using this crate. +#[derive(sp_core::RuntimeDebug)] +pub enum Error { + /// Module is not valid, couldn't be instantiated. + Module, + + /// Access to a memory or table was made with an address or an index which is out of bounds. + /// + /// Note that if wasm module makes an out-of-bounds access then trap will occur. + OutOfBounds, + + /// Failed to invoke the start function or an exported function for some reason. + Execution, +} + +impl From for HostError { + fn from(_e: Error) -> HostError { + HostError + } +} + +/// Function pointer for specifying functions by the +/// supervisor in [`EnvironmentDefinitionBuilder`]. +/// +/// [`EnvironmentDefinitionBuilder`]: struct.EnvironmentDefinitionBuilder.html +pub type HostFuncType = fn(&mut T, &[TypedValue]) -> Result; + +/// Reference to a sandboxed linear memory, that +/// will be used by the guest module. +/// +/// The memory can't be directly accessed by supervisor, but only +/// through designated functions [`get`] and [`set`]. +/// +/// [`get`]: #method.get +/// [`set`]: #method.set +#[derive(Clone)] +pub struct Memory { + inner: imp::Memory, +} + +impl Memory { + /// Construct a new linear memory instance. + /// + /// The memory allocated with initial number of pages specified by `initial`. + /// Minimal possible value for `initial` is 0 and maximum possible is `65536`. + /// (Since maximum addressable memory is 232 = 4GiB = 65536 * 64KiB). + /// + /// It is possible to limit maximum number of pages this memory instance can have by specifying + /// `maximum`. If not specified, this memory instance would be able to allocate up to 4GiB. + /// + /// Allocated memory is always zeroed. + pub fn new(initial: u32, maximum: Option) -> Result { + Ok(Memory { + inner: imp::Memory::new(initial, maximum)?, + }) + } + + /// Read a memory area at the address `ptr` with the size of the provided slice `buf`. + /// + /// Returns `Err` if the range is out-of-bounds. + pub fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error> { + self.inner.get(ptr, buf) + } + + /// Write a memory area at the address `ptr` with contents of the provided slice `buf`. + /// + /// Returns `Err` if the range is out-of-bounds. + pub fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error> { + self.inner.set(ptr, value) + } +} + +/// Struct that can be used for defining an environment for a sandboxed module. +/// +/// The sandboxed module can access only the entities which were defined and passed +/// to the module at the instantiation time. +pub struct EnvironmentDefinitionBuilder { + inner: imp::EnvironmentDefinitionBuilder, +} + +impl EnvironmentDefinitionBuilder { + /// Construct a new `EnvironmentDefinitionBuilder`. + pub fn new() -> EnvironmentDefinitionBuilder { + EnvironmentDefinitionBuilder { + inner: imp::EnvironmentDefinitionBuilder::new(), + } + } + + /// 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 + /// the same function (i.e. with same `module` and `field`) several times. It's up to + /// the user code to check or constrain the types of signatures. + pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) + where + N1: Into>, + N2: Into>, + { + self.inner.add_host_func(module, field, f); + } + + /// Register a memory in this environment definition. + pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) + where + N1: Into>, + N2: Into>, + { + self.inner.add_memory(module, field, mem.inner); + } +} + +/// Sandboxed instance of a wasm module. +/// +/// This instance can be used for invoking exported functions. +pub struct Instance { + inner: imp::Instance, +} + +impl Instance { + /// Instantiate a module with the given [`EnvironmentDefinitionBuilder`]. It will + /// run the `start` function (if it is present in the module) with the given `state`. + /// + /// Returns `Err(Error::Module)` if this module can't be instantiated with the given + /// environment. If execution of `start` function generated a trap, then `Err(Error::Execution)` will + /// be returned. + /// + /// [`EnvironmentDefinitionBuilder`]: struct.EnvironmentDefinitionBuilder.html + pub fn new(code: &[u8], env_def_builder: &EnvironmentDefinitionBuilder, state: &mut T) + -> Result, Error> + { + Ok(Instance { + inner: imp::Instance::new(code, &env_def_builder.inner, state)?, + }) + } + + /// Invoke an exported function with the given name. + /// + /// # Errors + /// + /// Returns `Err(Error::Execution)` if: + /// + /// - An export function name isn't a proper utf8 byte sequence, + /// - This module doesn't have an exported function with the given name, + /// - If types of the arguments passed to the function doesn't match function signature + /// then trap occurs (as if the exported function was called via call_indirect), + /// - Trap occured at the execution time. + pub fn invoke( + &mut self, + name: &str, + args: &[TypedValue], + state: &mut T, + ) -> Result { + self.inner.invoke(name, args, state) + } +} diff --git a/primitives/sandbox/with_std.rs b/primitives/sandbox/with_std.rs new file mode 100755 index 0000000000000..5f20342a5a9e4 --- /dev/null +++ b/primitives/sandbox/with_std.rs @@ -0,0 +1,485 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use sp_std::collections::btree_map::BTreeMap; +use sp_std::fmt; + +use wasmi::{ + Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef, ImportResolver, + MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef, + RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, TrapKind +}; +use wasmi::memory_units::Pages; +use super::{Error, TypedValue, ReturnValue, HostFuncType, HostError}; + +#[derive(Clone)] +pub struct Memory { + memref: MemoryRef, +} + +impl Memory { + pub fn new(initial: u32, maximum: Option) -> Result { + Ok(Memory { + memref: MemoryInstance::alloc( + Pages(initial as usize), + maximum.map(|m| Pages(m as usize)), + ).map_err(|_| Error::Module)?, + }) + } + + pub fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error> { + self.memref.get_into(ptr, buf).map_err(|_| Error::OutOfBounds)?; + Ok(()) + } + + pub fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error> { + self.memref.set(ptr, value).map_err(|_| Error::OutOfBounds)?; + Ok(()) + } +} + +struct HostFuncIndex(usize); + +struct DefinedHostFunctions { + funcs: Vec>, +} + +impl Clone for DefinedHostFunctions { + fn clone(&self) -> DefinedHostFunctions { + DefinedHostFunctions { + funcs: self.funcs.clone(), + } + } +} + +impl DefinedHostFunctions { + fn new() -> DefinedHostFunctions { + DefinedHostFunctions { + funcs: Vec::new(), + } + } + + fn define(&mut self, f: HostFuncType) -> HostFuncIndex { + let idx = self.funcs.len(); + self.funcs.push(f); + HostFuncIndex(idx) + } +} + +#[derive(Debug)] +struct DummyHostError; + +impl fmt::Display for DummyHostError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "DummyHostError") + } +} + +impl wasmi::HostError for DummyHostError { +} + +fn from_runtime_value(v: RuntimeValue) -> TypedValue { + match v { + RuntimeValue::I32(v) => TypedValue::I32(v), + RuntimeValue::I64(v) => TypedValue::I64(v), + RuntimeValue::F32(v) => TypedValue::F32(v.to_bits() as i32), + RuntimeValue::F64(v) => TypedValue::F64(v.to_bits() as i64), + } +} + +fn to_runtime_value(v: TypedValue) -> RuntimeValue { + 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), + TypedValue::F32(v_bits) => RuntimeValue::F32(F32::from_bits(v_bits as u32)), + TypedValue::F64(v_bits) => RuntimeValue::F64(F64::from_bits(v_bits as u64)), + } +} + +struct GuestExternals<'a, T: 'a> { + state: &'a mut T, + defined_host_functions: &'a DefinedHostFunctions, +} + +impl<'a, T> Externals for GuestExternals<'a, T> { + fn invoke_index( + &mut self, + index: usize, + args: RuntimeArgs, + ) -> Result, Trap> { + let args = args.as_ref() + .iter() + .cloned() + .map(from_runtime_value) + .collect::>(); + + let result = (self.defined_host_functions.funcs[index])(self.state, &args); + match result { + Ok(value) => Ok(match value { + ReturnValue::Value(v) => Some(to_runtime_value(v)), + ReturnValue::Unit => None, + }), + Err(HostError) => Err(TrapKind::Host(Box::new(DummyHostError)).into()), + } + } +} + +enum ExternVal { + HostFunc(HostFuncIndex), + Memory(Memory), +} + +pub struct EnvironmentDefinitionBuilder { + map: BTreeMap<(Vec, Vec), ExternVal>, + defined_host_functions: DefinedHostFunctions, +} + +impl EnvironmentDefinitionBuilder { + pub fn new() -> EnvironmentDefinitionBuilder { + EnvironmentDefinitionBuilder { + map: BTreeMap::new(), + defined_host_functions: DefinedHostFunctions::new(), + } + } + + pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) + where + N1: Into>, + N2: Into>, + { + let idx = self.defined_host_functions.define(f); + self.map + .insert((module.into(), field.into()), ExternVal::HostFunc(idx)); + } + + pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) + where + N1: Into>, + N2: Into>, + { + self.map + .insert((module.into(), field.into()), ExternVal::Memory(mem)); + } +} + +impl ImportResolver for EnvironmentDefinitionBuilder { + fn resolve_func( + &self, + module_name: &str, + field_name: &str, + signature: &Signature, + ) -> Result { + let key = ( + module_name.as_bytes().to_owned(), + field_name.as_bytes().to_owned(), + ); + let externval = self.map.get(&key).ok_or_else(|| { + wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name)) + })?; + let host_func_idx = match *externval { + ExternVal::HostFunc(ref idx) => idx, + _ => { + return Err(wasmi::Error::Instantiation(format!( + "Export {}:{} is not a host func", + module_name, field_name + ))) + } + }; + Ok(FuncInstance::alloc_host(signature.clone(), host_func_idx.0)) + } + + fn resolve_global( + &self, + _module_name: &str, + _field_name: &str, + _global_type: &GlobalDescriptor, + ) -> Result { + Err(wasmi::Error::Instantiation(format!( + "Importing globals is not supported yet" + ))) + } + + fn resolve_memory( + &self, + module_name: &str, + field_name: &str, + _memory_type: &MemoryDescriptor, + ) -> Result { + let key = ( + module_name.as_bytes().to_owned(), + field_name.as_bytes().to_owned(), + ); + let externval = self.map.get(&key).ok_or_else(|| { + wasmi::Error::Instantiation(format!("Export {}:{} not found", module_name, field_name)) + })?; + let memory = match *externval { + ExternVal::Memory(ref m) => m, + _ => { + return Err(wasmi::Error::Instantiation(format!( + "Export {}:{} is not a memory", + module_name, field_name + ))) + } + }; + Ok(memory.memref.clone()) + } + + fn resolve_table( + &self, + _module_name: &str, + _field_name: &str, + _table_type: &TableDescriptor, + ) -> Result { + Err(wasmi::Error::Instantiation(format!( + "Importing tables is not supported yet" + ))) + } +} + +pub struct Instance { + instance: ModuleRef, + defined_host_functions: DefinedHostFunctions, + _marker: ::std::marker::PhantomData, +} + +impl Instance { + pub fn new( + code: &[u8], + env_def_builder: &EnvironmentDefinitionBuilder, + state: &mut T, + ) -> Result, Error> { + let module = Module::from_buffer(code).map_err(|_| Error::Module)?; + let not_started_instance = ModuleInstance::new(&module, env_def_builder) + .map_err(|_| Error::Module)?; + + + let defined_host_functions = env_def_builder.defined_host_functions.clone(); + let instance = { + let mut externals = GuestExternals { + state, + defined_host_functions: &defined_host_functions, + }; + let instance = not_started_instance.run_start(&mut externals) + .map_err(|_| Error::Execution)?; + instance + }; + + Ok(Instance { + instance, + defined_host_functions, + _marker: ::std::marker::PhantomData::, + }) + } + + pub fn invoke( + &mut self, + name: &str, + args: &[TypedValue], + state: &mut T, + ) -> Result { + let args = args.iter().cloned().map(Into::into).collect::>(); + + let mut externals = GuestExternals { + state, + defined_host_functions: &self.defined_host_functions, + }; + let result = self.instance + .invoke_export(&name, &args, &mut externals); + + match result { + Ok(None) => Ok(ReturnValue::Unit), + Ok(Some(val)) => Ok(ReturnValue::Value(val.into())), + Err(_err) => Err(Error::Execution), + } + } +} + +#[cfg(test)] +mod tests { + use wabt; + use crate::{Error, TypedValue, ReturnValue, HostError, EnvironmentDefinitionBuilder, Instance}; + use assert_matches::assert_matches; + + fn execute_sandboxed(code: &[u8], args: &[TypedValue]) -> Result { + struct State { + counter: u32, + } + + fn env_assert(_e: &mut State, args: &[TypedValue]) -> Result { + if args.len() != 1 { + return Err(HostError); + } + let condition = args[0].as_i32().ok_or_else(|| HostError)?; + if condition != 0 { + Ok(ReturnValue::Unit) + } else { + Err(HostError) + } + } + fn env_inc_counter(e: &mut State, args: &[TypedValue]) -> Result { + if args.len() != 1 { + return Err(HostError); + } + let inc_by = args[0].as_i32().ok_or_else(|| HostError)?; + e.counter += inc_by as u32; + Ok(ReturnValue::Value(TypedValue::I32(e.counter as i32))) + } + /// Function that takes one argument of any type and returns that value. + fn env_polymorphic_id(_e: &mut State, args: &[TypedValue]) -> Result { + if args.len() != 1 { + return Err(HostError); + } + Ok(ReturnValue::Value(args[0])) + } + + let mut state = State { counter: 0 }; + + let mut env_builder = EnvironmentDefinitionBuilder::new(); + env_builder.add_host_func("env", "assert", env_assert); + env_builder.add_host_func("env", "inc_counter", env_inc_counter); + env_builder.add_host_func("env", "polymorphic_id", env_polymorphic_id); + + let mut instance = Instance::new(code, &env_builder, &mut state)?; + let result = instance.invoke("call", args, &mut state); + + result.map_err(|_| HostError) + } + + #[test] + fn invoke_args() { + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + + (func (export "call") (param $x i32) (param $y i64) + ;; assert that $x = 0x12345678 + (call $assert + (i32.eq + (get_local $x) + (i32.const 0x12345678) + ) + ) + + (call $assert + (i64.eq + (get_local $y) + (i64.const 0x1234567887654321) + ) + ) + ) + ) + "#).unwrap(); + + let result = execute_sandboxed( + &code, + &[ + TypedValue::I32(0x12345678), + TypedValue::I64(0x1234567887654321), + ] + ); + assert!(result.is_ok()); + } + + #[test] + fn return_value() { + let code = wabt::wat2wasm(r#" + (module + (func (export "call") (param $x i32) (result i32) + (i32.add + (get_local $x) + (i32.const 1) + ) + ) + ) + "#).unwrap(); + + let return_val = execute_sandboxed( + &code, + &[ + TypedValue::I32(0x1336), + ] + ).unwrap(); + assert_eq!(return_val, ReturnValue::Value(TypedValue::I32(0x1337))); + } + + #[test] + fn signatures_dont_matter() { + let code = wabt::wat2wasm(r#" + (module + (import "env" "polymorphic_id" (func $id_i32 (param i32) (result i32))) + (import "env" "polymorphic_id" (func $id_i64 (param i64) (result i64))) + (import "env" "assert" (func $assert (param i32))) + + (func (export "call") + ;; assert that we can actually call the "same" function with different + ;; signatures. + (call $assert + (i32.eq + (call $id_i32 + (i32.const 0x012345678) + ) + (i32.const 0x012345678) + ) + ) + (call $assert + (i64.eq + (call $id_i64 + (i64.const 0x0123456789abcdef) + ) + (i64.const 0x0123456789abcdef) + ) + ) + ) + ) + "#).unwrap(); + + let return_val = execute_sandboxed(&code, &[]).unwrap(); + assert_eq!(return_val, ReturnValue::Unit); + } + + #[test] + fn cant_return_unmatching_type() { + fn env_returns_i32(_e: &mut (), _args: &[TypedValue]) -> Result { + Ok(ReturnValue::Value(TypedValue::I32(42))) + } + + let mut env_builder = EnvironmentDefinitionBuilder::new(); + env_builder.add_host_func("env", "returns_i32", env_returns_i32); + + let code = wabt::wat2wasm(r#" + (module + ;; It's actually returns i32, but imported as if it returned i64 + (import "env" "returns_i32" (func $returns_i32 (result i64))) + + (func (export "call") + (drop + (call $returns_i32) + ) + ) + ) + "#).unwrap(); + + // It succeeds since we are able to import functions with types we want. + let mut instance = Instance::new(&code, &env_builder, &mut ()).unwrap(); + + // But this fails since we imported a function that returns i32 as if it returned i64. + assert_matches!( + instance.invoke("call", &[], &mut ()), + Err(Error::Execution) + ); + } +} diff --git a/primitives/sandbox/without_std.rs b/primitives/sandbox/without_std.rs new file mode 100755 index 0000000000000..901354aee34cc --- /dev/null +++ b/primitives/sandbox/without_std.rs @@ -0,0 +1,278 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::{Decode, Encode}; +use sp_core::sandbox as sandbox_primitives; +use sp_io::sandbox; +use sp_std::{prelude::*, slice, marker, mem, vec, rc::Rc}; +use super::{Error, TypedValue, ReturnValue, HostFuncType}; + +mod ffi { + use sp_std::mem; + use super::HostFuncType; + + /// Index into the default table that points to a `HostFuncType`. + pub type HostFuncIndex = usize; + + /// Coerce `HostFuncIndex` to a callable host function pointer. + /// + /// # Safety + /// + /// This function should be only called with a `HostFuncIndex` that was previously registered + /// in the environment definition. Typically this should only + /// be called with an argument received in `dispatch_thunk`. + pub unsafe fn coerce_host_index_to_func(idx: HostFuncIndex) -> HostFuncType { + // We need to ensure that sizes of a callable function pointer and host function index is + // indeed equal. + // We can't use `static_assertions` create because it makes compiler panic, fallback to runtime assert. + // const_assert!(mem::size_of::() == mem::size_of::>(),); + assert!(mem::size_of::() == mem::size_of::>()); + mem::transmute::>(idx) + } +} + +struct MemoryHandle { + memory_idx: u32, +} + +impl Drop for MemoryHandle { + fn drop(&mut self) { + sandbox::memory_teardown(self.memory_idx); + } +} + +#[derive(Clone)] +pub struct Memory { + // Handle to memory instance is wrapped to add reference-counting semantics + // to `Memory`. + handle: Rc, +} + +impl Memory { + pub fn new(initial: u32, maximum: Option) -> Result { + let maximum = if let Some(maximum) = maximum { + maximum + } else { + sandbox_primitives::MEM_UNLIMITED + }; + + match sandbox::memory_new(initial, maximum) { + sandbox_primitives::ERR_MODULE => Err(Error::Module), + memory_idx => Ok(Memory { + handle: Rc::new(MemoryHandle { memory_idx, }), + }), + } + } + + pub fn get(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> { + let result = sandbox::memory_get( + self.handle.memory_idx, + offset, + buf.as_mut_ptr(), + buf.len() as u32, + ); + match result { + sandbox_primitives::ERR_OK => Ok(()), + sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds), + _ => unreachable!(), + } + } + + pub fn set(&self, offset: u32, val: &[u8]) -> Result<(), Error> { + let result = sandbox::memory_set( + self.handle.memory_idx, + offset, + val.as_ptr() as _ , + val.len() as u32, + ); + match result { + sandbox_primitives::ERR_OK => Ok(()), + sandbox_primitives::ERR_OUT_OF_BOUNDS => Err(Error::OutOfBounds), + _ => unreachable!(), + } + } +} + +pub struct EnvironmentDefinitionBuilder { + env_def: sandbox_primitives::EnvironmentDefinition, + retained_memories: Vec, + _marker: marker::PhantomData, +} + +impl EnvironmentDefinitionBuilder { + pub fn new() -> EnvironmentDefinitionBuilder { + EnvironmentDefinitionBuilder { + env_def: sandbox_primitives::EnvironmentDefinition { + entries: Vec::new(), + }, + retained_memories: Vec::new(), + _marker: marker::PhantomData::, + } + } + + fn add_entry( + &mut self, + module: N1, + field: N2, + extern_entity: sandbox_primitives::ExternEntity, + ) where + N1: Into>, + N2: Into>, + { + let entry = sandbox_primitives::Entry { + module_name: module.into(), + field_name: field.into(), + entity: extern_entity, + }; + self.env_def.entries.push(entry); + } + + pub fn add_host_func(&mut self, module: N1, field: N2, f: HostFuncType) + where + N1: Into>, + N2: Into>, + { + let f = sandbox_primitives::ExternEntity::Function(f as u32); + self.add_entry(module, field, f); + } + + pub fn add_memory(&mut self, module: N1, field: N2, mem: Memory) + where + N1: Into>, + N2: Into>, + { + // We need to retain memory to keep it alive while the EnvironmentDefinitionBuilder alive. + self.retained_memories.push(mem.clone()); + + let mem = sandbox_primitives::ExternEntity::Memory(mem.handle.memory_idx as u32); + self.add_entry(module, field, mem); + } +} + +pub struct Instance { + instance_idx: u32, + _retained_memories: Vec, + _marker: marker::PhantomData, +} + +/// The primary responsibility of this thunk is to deserialize arguments and +/// call the original function, specified by the index. +extern "C" fn dispatch_thunk( + serialized_args_ptr: *const u8, + serialized_args_len: usize, + state: usize, + f: ffi::HostFuncIndex, +) -> u64 { + let serialized_args = unsafe { + if serialized_args_len == 0 { + &[] + } else { + slice::from_raw_parts(serialized_args_ptr, serialized_args_len) + } + }; + let args = Vec::::decode(&mut &serialized_args[..]).expect( + "serialized args should be provided by the runtime; + correctly serialized data should be deserializable; + qed", + ); + + unsafe { + // This should be safe since `coerce_host_index_to_func` is called with an argument + // received in an `dispatch_thunk` implementation, so `f` should point + // on a valid host function. + let f = ffi::coerce_host_index_to_func(f); + + // This should be safe since mutable reference to T is passed upon the invocation. + let state = &mut *(state as *mut T); + + // Pass control flow to the designated function. + let result = f(state, &args).encode(); + + // Leak the result vector and return the pointer to return data. + let result_ptr = result.as_ptr() as u64; + let result_len = result.len() as u64; + mem::forget(result); + + (result_ptr << 32) | result_len + } +} + +impl Instance { + pub fn new( + code: &[u8], + env_def_builder: &EnvironmentDefinitionBuilder, + state: &mut T, + ) -> Result, Error> { + let serialized_env_def: Vec = env_def_builder.env_def.encode(); + // It's very important to instantiate thunk with the right type. + let dispatch_thunk = dispatch_thunk::; + let result = sandbox::instantiate( + dispatch_thunk as u32, + code, + &serialized_env_def, + state as *const T as _, + ); + + let instance_idx = match result { + sandbox_primitives::ERR_MODULE => return Err(Error::Module), + sandbox_primitives::ERR_EXECUTION => return Err(Error::Execution), + instance_idx => instance_idx, + }; + + // We need to retain memories to keep them alive while the Instance is alive. + let retained_memories = env_def_builder.retained_memories.clone(); + Ok(Instance { + instance_idx, + _retained_memories: retained_memories, + _marker: marker::PhantomData::, + }) + } + + pub fn invoke( + &mut self, + name: &str, + args: &[TypedValue], + state: &mut T, + ) -> Result { + let serialized_args = args.to_vec().encode(); + let mut return_val = vec![0u8; sandbox_primitives::ReturnValue::ENCODED_MAX_SIZE]; + + let result = sandbox::invoke( + self.instance_idx, + name, + &serialized_args, + return_val.as_mut_ptr() as _, + return_val.len() as u32, + state as *const T as _, + ); + + match result { + sandbox_primitives::ERR_OK => { + let return_val = sandbox_primitives::ReturnValue::decode(&mut &return_val[..]) + .map_err(|_| Error::Execution)?; + Ok(return_val) + } + sandbox_primitives::ERR_EXECUTION => Err(Error::Execution), + _ => unreachable!(), + } + } +} + +impl Drop for Instance { + fn drop(&mut self) { + sandbox::instance_teardown(self.instance_idx); + } +} diff --git a/primitives/serializer/Cargo.toml b/primitives/serializer/Cargo.toml new file mode 100644 index 0000000000000..39fdeb0e7ee3c --- /dev/null +++ b/primitives/serializer/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sp-serializer" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = "1.0.101" +serde_json = "1.0.41" diff --git a/primitives/serializer/src/lib.rs b/primitives/serializer/src/lib.rs new file mode 100644 index 0000000000000..3138c3e63bcb0 --- /dev/null +++ b/primitives/serializer/src/lib.rs @@ -0,0 +1,41 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate customizable serde serializer. +//! +//! The idea is that we can later change the implementation +//! to something more compact, but for now we're using JSON. + +#![warn(missing_docs)] + +pub use serde_json::{from_str, from_slice, from_reader, Result, Error}; + +const PROOF: &str = "Serializers are infallible; qed"; + +/// Serialize the given data structure as a pretty-printed String of JSON. +pub fn to_string_pretty(value: &T) -> String { + serde_json::to_string_pretty(value).expect(PROOF) +} + +/// Serialize the given data structure as a JSON byte vector. +pub fn encode(value: &T) -> Vec { + serde_json::to_vec(value).expect(PROOF) +} + +/// Serialize the given data structure as JSON into the IO stream. +pub fn to_writer(writer: W, value: &T) -> Result<()> { + serde_json::to_writer(writer, value) +} diff --git a/primitives/session/Cargo.toml b/primitives/session/Cargo.toml new file mode 100644 index 0000000000000..b7c72e0c681fe --- /dev/null +++ b/primitives/session/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "sp-session" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-api = { version = "2.0.0", default-features = false, path = "../api" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0", optional = true, path = "../runtime" } + +[features] +default = [ "std" ] +std = [ "sp-api/std", "sp-std/std", "sp-runtime" ] diff --git a/primitives/session/src/lib.rs b/primitives/session/src/lib.rs new file mode 100644 index 0000000000000..c61218ca6bacd --- /dev/null +++ b/primitives/session/src/lib.rs @@ -0,0 +1,62 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate core types around sessions. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::vec::Vec; + +#[cfg(feature = "std")] +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +#[cfg(feature = "std")] +use sp_api::ProvideRuntimeApi; + +sp_api::decl_runtime_apis! { + /// Session keys runtime api. + pub trait SessionKeys { + /// Generate a set of session keys with optionally using the given seed. + /// The keys should be stored within the keystore exposed via runtime + /// externalities. + /// + /// The seed needs to be a valid `utf8` string. + /// + /// Returns the concatenated SCALE encoded public keys. + fn generate_session_keys(seed: Option>) -> Vec; + } +} + +/// Generate the initial session keys with the given seeds, at the given block and store them in +/// the client's keystore. +#[cfg(feature = "std")] +pub fn generate_initial_session_keys( + client: std::sync::Arc, + at: &BlockId, + seeds: Vec, +) -> Result<(), sp_api::ApiErrorFor> +where + Block: BlockT, + T: ProvideRuntimeApi, + T::Api: SessionKeys, +{ + let runtime_api = client.runtime_api(); + + for seed in seeds { + runtime_api.generate_session_keys(at, Some(seed.as_bytes().to_vec()))?; + } + + Ok(()) +} diff --git a/primitives/sr-api/proc-macro/src/lib.rs b/primitives/sr-api/proc-macro/src/lib.rs new file mode 100644 index 0000000000000..589d0749a00ea --- /dev/null +++ b/primitives/sr-api/proc-macro/src/lib.rs @@ -0,0 +1,189 @@ +// 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 . + +//! Macros for declaring and implementing runtime apis. + +#![recursion_limit = "512"] +extern crate proc_macro; + +use proc_macro::TokenStream; + +mod impl_runtime_apis; +mod decl_runtime_apis; +mod utils; + +/// Tags given trait implementations as runtime apis. +/// +/// All traits given to this macro, need to be declared with the `decl_runtime_apis!` macro. +/// The implementation of the trait should follow the declaration given to the `decl_runtime_apis!` +/// macro, besides the `Block` type that is required as first generic parameter for each runtime +/// api trait. When implementing a runtime api trait, it is required that the trait is referenced +/// by a path, e.g. `impl my_trait::MyTrait for Runtime`. The macro will use this path to access +/// the declaration of the trait for the runtime side. +/// +/// The macro also generates the api implementations for the client side and provides it through +/// the `RuntimeApi` type. The `RuntimeApi` is hidden behind a `feature` called `std`. +/// +/// To expose version information about all implemented api traits, the constant +/// `RUNTIME_API_VERSIONS` is generated. This constant should be used to instantiate the `apis` +/// field of `RuntimeVersion`. +/// +/// # Example +/// +/// ```rust +/// use sp_version::create_runtime_str; +/// # +/// # use sp_runtime::traits::{GetNodeBlockType, Block as BlockT}; +/// # 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. +/// # pub struct Runtime {} +/// # impl GetNodeBlockType for Runtime { +/// # type NodeBlock = Block; +/// # } +/// # +/// # sp_api::decl_runtime_apis! { +/// # /// Declare the api trait. +/// # pub trait Balance { +/// # /// Get the balance. +/// # fn get_balance() -> u64; +/// # /// Set the balance. +/// # fn set_balance(val: u64); +/// # } +/// # pub trait BlockBuilder { +/// # fn build_block() -> Block; +/// # } +/// # } +/// +/// /// All runtime api implementations need to be done in one call of the macro! +/// sp_api::impl_runtime_apis! { +/// # impl sp_api::Core for Runtime { +/// # fn version() -> sp_version::RuntimeVersion { +/// # unimplemented!() +/// # } +/// # fn execute_block(_block: Block) {} +/// # fn initialize_block(_header: &::Header) {} +/// # } +/// +/// impl self::Balance for Runtime { +/// fn get_balance() -> u64 { +/// 1 +/// } +/// fn set_balance(_bal: u64) { +/// // Store the balance +/// } +/// } +/// +/// impl self::BlockBuilder for Runtime { +/// fn build_block() -> Block { +/// unimplemented!("Please implement me!") +/// } +/// } +/// } +/// +/// /// Runtime version. This needs to be declared for each runtime. +/// pub const VERSION: sp_version::RuntimeVersion = sp_version::RuntimeVersion { +/// spec_name: create_runtime_str!("node"), +/// impl_name: create_runtime_str!("test-node"), +/// authoring_version: 1, +/// spec_version: 1, +/// impl_version: 0, +/// // Here we are exposing the runtime api versions. +/// apis: RUNTIME_API_VERSIONS, +/// }; +/// +/// # fn main() {} +/// ``` +#[proc_macro] +pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { + impl_runtime_apis::impl_runtime_apis_impl(input) +} + +/// Declares given traits as runtime apis. +/// +/// The macro will create two declarations, one for using on the client side and one for using +/// on the runtime side. The declaration for the runtime side is hidden in its own module. +/// The client side declaration gets two extra parameters per function, +/// `&self` and `at: &BlockId`. The runtime side declaration will match the given trait +/// declaration. Besides one exception, the macro adds an extra generic parameter `Block: BlockT` +/// to the client side and the runtime side. This generic parameter is usable by the user. +/// +/// For implementing these macros you should use the `impl_runtime_apis!` macro. +/// +/// # Example +/// +/// ```rust +/// sp_api::decl_runtime_apis! { +/// /// Declare the api trait. +/// pub trait Balance { +/// /// Get the balance. +/// fn get_balance() -> u64; +/// /// Set the balance. +/// fn set_balance(val: u64); +/// } +/// +/// /// You can declare multiple api traits in one macro call. +/// /// In one module you can call the macro at maximum one time. +/// pub trait BlockBuilder { +/// /// The macro adds an explicit `Block: BlockT` generic parameter for you. +/// /// You can use this generic parameter as you would defined it manually. +/// fn build_block() -> Block; +/// } +/// } +/// +/// # fn main() {} +/// ``` +/// +/// # Runtime api trait versioning +/// +/// 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. 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 +/// sp_api::decl_runtime_apis! { +/// /// Declare the api trait. +/// #[api_version(2)] +/// pub trait Balance { +/// /// Get the balance. +/// fn get_balance() -> u64; +/// /// 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: u16); +/// /// In version 2, we added this new function. +/// fn increase_balance(val: u64); +/// } +/// } +/// +/// # fn main() {} +/// ``` +/// +/// To check if a given runtime implements a runtime api trait, the `RuntimeVersion` has the +/// function `has_api()`. Also the `ApiExt` provides a function `has_api(at: &BlockId)` to +/// check if the runtime at the given block id implements the requested runtime api trait. +#[proc_macro] +pub fn decl_runtime_apis(input: TokenStream) -> TokenStream { + decl_runtime_apis::decl_runtime_apis_impl(input) +} diff --git a/primitives/staking/Cargo.toml b/primitives/staking/Cargo.toml new file mode 100644 index 0000000000000..35725c72e334b --- /dev/null +++ b/primitives/staking/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "sp-staking" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/primitives/staking/src/lib.rs b/primitives/staking/src/lib.rs new file mode 100644 index 0000000000000..3f6c1873ff031 --- /dev/null +++ b/primitives/staking/src/lib.rs @@ -0,0 +1,23 @@ + +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +#![cfg_attr(not(feature = "std"), no_std)] + +//! A crate which contains primitives that are useful for implementation that uses staking +//! approaches in general. Definitions related to sessions, slashing, etc go here. + +pub mod offence; + +/// Simple index type with which we can count sessions. +pub type SessionIndex = u32; diff --git a/core/sr-staking-primitives/src/offence.rs b/primitives/staking/src/offence.rs similarity index 94% rename from core/sr-staking-primitives/src/offence.rs rename to primitives/staking/src/offence.rs index db51f75df1bf3..cac1ed065ceb7 100644 --- a/core/sr-staking-primitives/src/offence.rs +++ b/primitives/staking/src/offence.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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 @@ //! Common traits and types that are useful for describing offences for usage in environments //! that use staking. -use rstd::vec::Vec; +use sp_std::vec::Vec; use codec::{Encode, Decode}; -use sr_primitives::Perbill; +use sp_runtime::Perbill; use crate::SessionIndex; @@ -117,9 +117,12 @@ pub trait OnOffenceHandler { /// the authorities should be slashed and is computed /// according to the `OffenceCount` already. This is of the same length as `offenders.` /// Zero is a valid value for a fraction. + /// + /// The `session` parameter is the session index of the offence. fn on_offence( offenders: &[OffenceDetails], slash_fraction: &[Perbill], + session: SessionIndex, ); } @@ -127,11 +130,12 @@ impl OnOffenceHandler for () { fn on_offence( _offenders: &[OffenceDetails], _slash_fraction: &[Perbill], + _session: SessionIndex, ) {} } /// A details about an offending authority for a particular kind of offence. -#[derive(Clone, PartialEq, Eq, Encode, Decode, sr_primitives::RuntimeDebug)] +#[derive(Clone, PartialEq, Eq, Encode, Decode, sp_runtime::RuntimeDebug)] pub struct OffenceDetails { /// The offending authority id pub offender: Offender, diff --git a/primitives/state-machine/Cargo.toml b/primitives/state-machine/Cargo.toml new file mode 100644 index 0000000000000..1424845ea6cc9 --- /dev/null +++ b/primitives/state-machine/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "sp-state-machine" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Substrate State Machine" +edition = "2018" + +[dependencies] +log = "0.4.8" +parking_lot = "0.9.0" +hash-db = "0.15.2" +trie-db = "0.18.1" +trie-root = "0.15.2" +sp-trie = { version = "2.0.0", path = "../trie" } +sp-core = { version = "2.0.0", path = "../core" } +sp-panic-handler = { version = "2.0.0", path = "../panic-handler" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +num-traits = "0.2.8" +rand = "0.7.2" +sp-externalities = { version = "2.0.0", path = "../externalities" } + +[dev-dependencies] +hex-literal = "0.2.1" + +[features] +default = [] diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs new file mode 100644 index 0000000000000..75733d68b3ffa --- /dev/null +++ b/primitives/state-machine/src/backend.rs @@ -0,0 +1,351 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! State machine backends. These manage the code and storage of contracts. + +use log::warn; +use hash_db::Hasher; +use codec::Encode; + +use sp_core::storage::{ChildInfo, OwnedChildInfo}; +use sp_trie::{TrieMut, MemoryDB, trie_types::TrieDBMut}; + +use crate::{ + trie_backend::TrieBackend, + trie_backend_essence::TrieBackendStorage, + UsageInfo, +}; + +/// A state backend is used to read state data and can have changes committed +/// to it. +/// +/// The clone operation (if implemented) should be cheap. +pub trait Backend: std::fmt::Debug { + /// An error type when fetching data is not possible. + type Error: super::Error; + + /// Storage changes to be applied if committing + type Transaction: Consolidate + Default + Send; + + /// Type of trie backend storage. + type TrieBackendStorage: TrieBackendStorage; + + /// Get keyed storage or None if there is nothing associated. + fn storage(&self, key: &[u8]) -> Result>, Self::Error>; + + /// 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], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error>; + + /// Get child keyed storage value hash or None if there is nothing associated. + fn child_storage_hash( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result, Self::Error> { + self.child_storage(storage_key, child_info, key).map(|v| v.map(|v| H::hash(&v))) + } + + /// true if a key exists in storage. + fn exists_storage(&self, key: &[u8]) -> Result { + Ok(self.storage(key)?.is_some()) + } + + /// true if a key exists in child storage. + fn exists_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result { + Ok(self.child_storage(storage_key, child_info, key)?.is_some()) + } + + /// Return the next key in storage in lexicographic order or `None` if there is no value. + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error>; + + /// Return the next key in child storage in lexicographic order or `None` if there is no value. + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8] + ) -> Result>, Self::Error>; + + /// Retrieve all entries keys of child storage and call `f` for each of those keys. + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + f: F, + ); + + /// Retrieve all entries keys which start with the given prefix and + /// call `f` for each of those keys. + fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { + self.for_key_values_with_prefix(prefix, |k, _v| f(k)) + } + + /// Retrieve all entries keys and values of which start with the given prefix and + /// call `f` for each of those keys. + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F); + + + /// Retrieve all child entries keys which start with the given prefix and + /// call `f` for each of those keys. + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + f: F, + ); + + /// Calculate the storage root, with given delta over what is already stored in + /// the backend, and produce a "transaction" that can be used to commit. + /// Does not include child storage updates. + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord; + + /// Calculate the child storage root, with given delta over what is already stored in + /// the backend, and produce a "transaction" that can be used to commit. The second argument + /// is true if child storage root equals default storage root. + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (H::Out, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord; + + /// Get all key/value pairs into a Vec. + fn pairs(&self) -> Vec<(Vec, Vec)>; + + /// Get all keys with given prefix + fn keys(&self, prefix: &[u8]) -> Vec> { + let mut all = Vec::new(); + self.for_keys_with_prefix(prefix, |k| all.push(k.to_vec())); + all + } + + /// Get all keys of child storage with given prefix + fn child_keys( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + ) -> Vec> { + let mut all = Vec::new(); + self.for_child_keys_with_prefix(storage_key, child_info, prefix, |k| all.push(k.to_vec())); + all + } + + /// Try convert into trie backend. + fn as_trie_backend(&mut self) -> Option<&TrieBackend> { + None + } + + /// Calculate the storage root, with given delta over what is already stored + /// in the backend, and produce a "transaction" that can be used to commit. + /// Does include child storage updates. + fn full_storage_root( + &self, + delta: I1, + child_deltas: I2) + -> (H::Out, Self::Transaction) + where + I1: IntoIterator, Option>)>, + I2i: IntoIterator, Option>)>, + I2: IntoIterator, I2i, OwnedChildInfo)>, + H::Out: Ord + Encode, + { + let mut txs: Self::Transaction = Default::default(); + let mut child_roots: Vec<_> = Default::default(); + // child first + for (storage_key, child_delta, child_info) in child_deltas { + let (child_root, empty, child_txs) = + self.child_storage_root(&storage_key[..], child_info.as_ref(), child_delta); + txs.consolidate(child_txs); + if empty { + child_roots.push((storage_key, None)); + } else { + child_roots.push((storage_key, Some(child_root.encode()))); + } + } + let (root, parent_txs) = self.storage_root( + delta.into_iter().chain(child_roots.into_iter()) + ); + txs.consolidate(parent_txs); + (root, txs) + } + + /// Query backend usage statistics (i/o, memory) + /// + /// Not all implementations are expected to be able to do this. In the + /// case when thay don't, empty statistics is returned. + fn usage_info(&self) -> UsageInfo { + UsageInfo::empty() + } +} + +impl<'a, T: Backend, H: Hasher> Backend for &'a T { + type Error = T::Error; + type Transaction = T::Transaction; + type TrieBackendStorage = T::TrieBackendStorage; + + fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + (*self).storage(key) + } + + fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + (*self).child_storage(storage_key, child_info, key) + } + + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + f: F, + ) { + (*self).for_keys_in_child_storage(storage_key, child_info, f) + } + + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + (*self).next_storage_key(key) + } + + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + (*self).next_child_storage_key(storage_key, child_info, key) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + (*self).for_keys_with_prefix(prefix, f) + } + + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + f: F, + ) { + (*self).for_child_keys_with_prefix(storage_key, child_info, prefix, f) + } + + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord, + { + (*self).storage_root(delta) + } + + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (H::Out, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord, + { + (*self).child_storage_root(storage_key, child_info, delta) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + (*self).pairs() + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + (*self).for_key_values_with_prefix(prefix, f); + } + + fn usage_info(&self) -> UsageInfo { + (*self).usage_info() + } + } + +/// Trait that allows consolidate two transactions together. +pub trait Consolidate { + /// Consolidate two transactions into one. + fn consolidate(&mut self, other: Self); +} + +impl Consolidate for () { + fn consolidate(&mut self, _: Self) { + () + } +} + +impl Consolidate for Vec<( + Option<(Vec, OwnedChildInfo)>, + Vec<(Vec, Option>)>, + )> { + fn consolidate(&mut self, mut other: Self) { + self.append(&mut other); + } +} + +impl> Consolidate for sp_trie::GenericMemoryDB { + fn consolidate(&mut self, other: Self) { + sp_trie::GenericMemoryDB::consolidate(self, other) + } +} + +/// Insert input pairs into memory db. +pub(crate) fn insert_into_memory_db(mdb: &mut MemoryDB, input: I) -> Option + where + H: Hasher, + I: IntoIterator, Vec)>, +{ + let mut root = ::Out::default(); + { + let mut trie = TrieDBMut::::new(mdb, &mut root); + for (key, value) in input { + if let Err(e) = trie.insert(&key, &value) { + warn!(target: "trie", "Failed to write to trie: {}", e); + return None; + } + } + } + + Some(root) +} diff --git a/primitives/state-machine/src/basic.rs b/primitives/state-machine/src/basic.rs new file mode 100644 index 0000000000000..d06aedfc4b6ee --- /dev/null +++ b/primitives/state-machine/src/basic.rs @@ -0,0 +1,376 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Basic implementation for Externalities. + +use std::{ + collections::BTreeMap, any::{TypeId, Any}, iter::FromIterator, ops::Bound +}; +use crate::{Backend, InMemoryBackend}; +use hash_db::Hasher; +use sp_trie::{TrieConfiguration, default_child_trie_root}; +use sp_trie::trie_types::Layout; +use sp_core::{ + storage::{ + well_known_keys::is_child_storage_key, ChildStorageKey, Storage, + ChildInfo, StorageChild, + }, + traits::Externalities, Blake2Hasher, +}; +use log::warn; +use codec::Encode; + +/// Simple Map-based Externalities impl. +#[derive(Debug)] +pub struct BasicExternalities { + inner: Storage, +} + +impl BasicExternalities { + /// Create a new instance of `BasicExternalities` + pub fn new(inner: Storage) -> Self { + BasicExternalities { inner } + } + + /// Insert key/value + pub fn insert(&mut self, k: Vec, v: Vec) -> Option> { + self.inner.top.insert(k, v) + } + + /// Consume self and returns inner storages + pub fn into_storages(self) -> Storage { + self.inner + } + + /// Execute the given closure `f` with the externalities set and initialized with `storage`. + /// + /// Returns the result of the closure and updates `storage` with all changes. + pub fn execute_with_storage( + storage: &mut sp_core::storage::Storage, + f: impl FnOnce() -> R, + ) -> R { + let mut ext = Self { inner: Storage { + top: std::mem::replace(&mut storage.top, Default::default()), + children: std::mem::replace(&mut storage.children, Default::default()), + }}; + + let r = ext.execute_with(f); + + *storage = ext.into_storages(); + + r + } + + /// Execute the given closure while `self` is set as externalities. + /// + /// Returns the result of the given closure. + pub fn execute_with(&mut self, f: impl FnOnce() -> R) -> R { + sp_externalities::set_and_run_with_externalities(self, f) + } +} + +impl PartialEq for BasicExternalities { + fn eq(&self, other: &BasicExternalities) -> bool { + self.inner.top.eq(&other.inner.top) + && self.inner.children.eq(&other.inner.children) + } +} + +impl FromIterator<(Vec, Vec)> for BasicExternalities { + fn from_iter, Vec)>>(iter: I) -> Self { + let mut t = Self::default(); + t.inner.top.extend(iter); + t + } +} + +impl Default for BasicExternalities { + fn default() -> Self { Self::new(Default::default()) } +} + +impl From, Vec>> for BasicExternalities { + fn from(hashmap: BTreeMap, Vec>) -> Self { + BasicExternalities { inner: Storage { + top: hashmap, + children: Default::default(), + }} + } +} + +impl Externalities for BasicExternalities { + fn storage(&self, key: &[u8]) -> Option> { + self.inner.top.get(key).cloned() + } + + fn storage_hash(&self, key: &[u8]) -> Option> { + self.storage(key).map(|v| Blake2Hasher::hash(&v).encode()) + } + + fn original_storage(&self, key: &[u8]) -> Option> { + self.storage(key) + } + + fn original_storage_hash(&self, key: &[u8]) -> Option> { + self.storage_hash(key) + } + + fn child_storage( + &self, + storage_key: ChildStorageKey, + _child_info: ChildInfo, + key: &[u8], + ) -> Option> { + self.inner.children.get(storage_key.as_ref()).and_then(|child| child.data.get(key)).cloned() + } + + fn child_storage_hash( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option> { + self.child_storage(storage_key, child_info, key).map(|v| Blake2Hasher::hash(&v).encode()) + } + + fn original_child_storage_hash( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option> { + self.child_storage_hash(storage_key, child_info, key) + } + + fn original_child_storage( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option> { + Externalities::child_storage(self, storage_key, child_info, key) + } + + fn next_storage_key(&self, key: &[u8]) -> Option> { + let range = (Bound::Excluded(key), Bound::Unbounded); + self.inner.top.range::<[u8], _>(range).next().map(|(k, _)| k).cloned() + } + + fn next_child_storage_key( + &self, + storage_key: ChildStorageKey, + _child_info: ChildInfo, + key: &[u8], + ) -> Option> { + let range = (Bound::Excluded(key), Bound::Unbounded); + self.inner.children.get(storage_key.as_ref()) + .and_then(|child| child.data.range::<[u8], _>(range).next().map(|(k, _)| k).cloned()) + } + + fn place_storage(&mut self, key: Vec, maybe_value: Option>) { + if is_child_storage_key(&key) { + warn!(target: "trie", "Refuse to set child storage key via main storage"); + return; + } + + match maybe_value { + Some(value) => { self.inner.top.insert(key, value); } + None => { self.inner.top.remove(&key); } + } + } + + fn place_child_storage( + &mut self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: Vec, + value: Option>, + ) { + let child_map = self.inner.children.entry(storage_key.into_owned()) + .or_insert_with(|| StorageChild { + data: Default::default(), + child_info: child_info.to_owned(), + }); + if let Some(value) = value { + child_map.data.insert(key, value); + } else { + child_map.data.remove(&key); + } + } + + fn kill_child_storage( + &mut self, + storage_key: ChildStorageKey, + _child_info: ChildInfo, + ) { + self.inner.children.remove(storage_key.as_ref()); + } + + fn clear_prefix(&mut self, prefix: &[u8]) { + if is_child_storage_key(prefix) { + warn!( + target: "trie", + "Refuse to clear prefix that is part of child storage key via main storage" + ); + return; + } + + let to_remove = self.inner.top.range::<[u8], _>((Bound::Included(prefix), Bound::Unbounded)) + .map(|(k, _)| k) + .take_while(|k| k.starts_with(prefix)) + .cloned() + .collect::>(); + + for key in to_remove { + self.inner.top.remove(&key); + } + } + + fn clear_child_prefix( + &mut self, + storage_key: ChildStorageKey, + _child_info: ChildInfo, + prefix: &[u8], + ) { + if let Some(child) = self.inner.children.get_mut(storage_key.as_ref()) { + let to_remove = child.data.range::<[u8], _>((Bound::Included(prefix), Bound::Unbounded)) + .map(|(k, _)| k) + .take_while(|k| k.starts_with(prefix)) + .cloned() + .collect::>(); + + for key in to_remove { + child.data.remove(&key); + } + } + } + + fn chain_id(&self) -> u64 { 42 } + + fn storage_root(&mut self) -> Vec { + let mut top = self.inner.top.clone(); + let keys: Vec<_> = self.inner.children.keys().map(|k| k.to_vec()).collect(); + // Single child trie implementation currently allows using the same child + // empty root for all child trie. Using null storage key until multiple + // type of child trie support. + let empty_hash = default_child_trie_root::>(&[]); + for storage_key in keys { + let child_root = self.child_storage_root( + ChildStorageKey::from_slice(storage_key.as_slice()) + .expect("Map only feed by valid keys; qed"), + ); + if &empty_hash[..] == &child_root[..] { + top.remove(storage_key.as_slice()); + } else { + top.insert(storage_key, child_root); + } + } + + Layout::::trie_root(self.inner.top.clone()).as_ref().into() + } + + fn child_storage_root( + &mut self, + storage_key: ChildStorageKey, + ) -> Vec { + if let Some(child) = self.inner.children.get(storage_key.as_ref()) { + let delta = child.data.clone().into_iter().map(|(k, v)| (k, Some(v))); + + InMemoryBackend::::default() + .child_storage_root(storage_key.as_ref(), child.child_info.as_ref(), delta).0 + } else { + default_child_trie_root::>(storage_key.as_ref()) + }.encode() + } + + fn storage_changes_root(&mut self, _parent: &[u8]) -> Result>, ()> { + Ok(None) + } +} + +impl sp_externalities::ExtensionStore for BasicExternalities { + fn extension_by_type_id(&mut self, _: TypeId) -> Option<&mut dyn Any> { + warn!("Extensions are not supported by `BasicExternalities`."); + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::map; + use sp_core::storage::{Storage, StorageChild}; + use sp_core::storage::well_known_keys::CODE; + use hex_literal::hex; + + const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1"); + + #[test] + fn commit_should_work() { + let mut ext = BasicExternalities::default(); + ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); + ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); + ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); + const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa"); + + assert_eq!(&ext.storage_root()[..], &ROOT); + } + + #[test] + fn set_and_retrieve_code() { + let mut ext = BasicExternalities::default(); + + let code = vec![1, 2, 3]; + ext.set_storage(CODE.to_vec(), code.clone()); + + assert_eq!(&ext.storage(CODE).unwrap(), &code); + } + + #[test] + fn children_works() { + let child_storage = b":child_storage:default:test".to_vec(); + + let mut ext = BasicExternalities::new(Storage { + top: Default::default(), + children: map![ + child_storage.clone() => StorageChild { + data: map![ b"doe".to_vec() => b"reindeer".to_vec() ], + child_info: CHILD_INFO_1.to_owned(), + } + ] + }); + + let child = || ChildStorageKey::from_vec(child_storage.clone()).unwrap(); + + assert_eq!(ext.child_storage(child(), CHILD_INFO_1, b"doe"), Some(b"reindeer".to_vec())); + + ext.set_child_storage(child(), CHILD_INFO_1, b"dog".to_vec(), b"puppy".to_vec()); + assert_eq!(ext.child_storage(child(), CHILD_INFO_1, b"dog"), Some(b"puppy".to_vec())); + + ext.clear_child_storage(child(), CHILD_INFO_1, b"dog"); + assert_eq!(ext.child_storage(child(), CHILD_INFO_1, b"dog"), None); + + ext.kill_child_storage(child(), CHILD_INFO_1); + assert_eq!(ext.child_storage(child(), CHILD_INFO_1, b"doe"), None); + } + + #[test] + fn basic_externalities_is_empty() { + // Make sure no values are set by default in `BasicExternalities`. + let storage = BasicExternalities::new(Default::default()).into_storages(); + assert!(storage.top.is_empty()); + assert!(storage.children.is_empty()); + } +} diff --git a/primitives/state-machine/src/changes_trie/build.rs b/primitives/state-machine/src/changes_trie/build.rs new file mode 100644 index 0000000000000..ded8e4f6d19ed --- /dev/null +++ b/primitives/state-machine/src/changes_trie/build.rs @@ -0,0 +1,775 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Structures and functions required to build changes trie for given block. + +use std::collections::{BTreeMap, BTreeSet}; +use std::collections::btree_map::Entry; +use codec::{Decode, Encode}; +use hash_db::Hasher; +use num_traits::One; +use crate::backend::Backend; +use crate::overlayed_changes::OverlayedChanges; +use crate::trie_backend_essence::TrieBackendEssence; +use crate::changes_trie::build_iterator::digest_build_iterator; +use crate::changes_trie::input::{InputKey, InputPair, DigestIndex, ExtrinsicIndex}; +use crate::changes_trie::{AnchorBlockId, ConfigurationRange, Storage, BlockNumber}; +use crate::changes_trie::input::ChildIndex; + +/// Prepare input pairs for building a changes trie of given block. +/// +/// Returns Err if storage error has occurred OR if storage haven't returned +/// required data. +pub(crate) fn prepare_input<'a, B, H, Number>( + backend: &'a B, + storage: &'a dyn Storage, + config: ConfigurationRange<'a, Number>, + changes: &'a OverlayedChanges, + parent: &'a AnchorBlockId, +) -> Result<( + impl Iterator> + 'a, + Vec<(ChildIndex, impl Iterator> + 'a)>, + Vec, + ), String> + where + B: Backend, + H: Hasher + 'a, + H::Out: Encode, + Number: BlockNumber, +{ + let number = parent.number.clone() + One::one(); + let (extrinsics_input, children_extrinsics_input) = prepare_extrinsics_input( + backend, + &number, + changes, + )?; + let (digest_input, mut children_digest_input, digest_input_blocks) = prepare_digest_input::( + parent, + config, + number, + storage, + )?; + + let mut children_digest = Vec::with_capacity(children_extrinsics_input.len()); + for (child_index, ext_iter) in children_extrinsics_input.into_iter() { + let dig_iter = children_digest_input.remove(&child_index); + children_digest.push(( + child_index, + Some(ext_iter).into_iter().flatten() + .chain(dig_iter.into_iter().flatten()), + )); + } + for (child_index, dig_iter) in children_digest_input.into_iter() { + children_digest.push(( + child_index, + None.into_iter().flatten() + .chain(Some(dig_iter).into_iter().flatten()), + )); + } + + Ok(( + extrinsics_input.chain(digest_input), + children_digest, + digest_input_blocks, + )) +} +/// Prepare ExtrinsicIndex input pairs. +fn prepare_extrinsics_input<'a, B, H, Number>( + backend: &'a B, + block: &Number, + changes: &'a OverlayedChanges, +) -> Result<( + impl Iterator> + 'a, + BTreeMap, impl Iterator> + 'a>, + ), String> + where + B: Backend, + H: Hasher + 'a, + Number: BlockNumber, +{ + + let mut children_keys = BTreeSet::>::new(); + let mut children_result = BTreeMap::new(); + for (storage_key, _) in changes.prospective.children.iter() + .chain(changes.committed.children.iter()) { + children_keys.insert(storage_key.clone()); + } + for storage_key in children_keys { + let child_index = ChildIndex:: { + block: block.clone(), + storage_key: storage_key.clone(), + }; + + let iter = prepare_extrinsics_input_inner(backend, block, changes, Some(storage_key))?; + children_result.insert(child_index, iter); + } + + let top = prepare_extrinsics_input_inner(backend, block, changes, None)?; + + Ok((top, children_result)) +} + +fn prepare_extrinsics_input_inner<'a, B, H, Number>( + backend: &'a B, + block: &Number, + changes: &'a OverlayedChanges, + storage_key: Option>, +) -> Result> + 'a, String> + where + B: Backend, + H: Hasher, + Number: BlockNumber, +{ + let (committed, prospective, child_info) = if let Some(sk) = storage_key.as_ref() { + let child_info = changes.child_info(sk).cloned(); + ( + changes.committed.children.get(sk).map(|c| &c.0), + changes.prospective.children.get(sk).map(|c| &c.0), + child_info, + ) + } else { + (Some(&changes.committed.top), Some(&changes.prospective.top), None) + }; + committed.iter().flat_map(|c| c.iter()) + .chain(prospective.iter().flat_map(|c| c.iter())) + .filter(|( _, v)| v.extrinsics.is_some()) + .try_fold(BTreeMap::new(), |mut map: BTreeMap<&[u8], (ExtrinsicIndex, Vec)>, (k, v)| { + match map.entry(k) { + Entry::Vacant(entry) => { + // ignore temporary values (values that have null value at the end of operation + // AND are not in storage at the beginning of operation + if let Some(sk) = storage_key.as_ref() { + if !changes.child_storage(sk, k).map(|v| v.is_some()).unwrap_or_default() { + if let Some(child_info) = child_info.as_ref() { + if !backend.exists_child_storage(sk, child_info.as_ref(), k) + .map_err(|e| format!("{}", e))? { + return Ok(map); + } + } + } + } else { + if !changes.storage(k).map(|v| v.is_some()).unwrap_or_default() { + if !backend.exists_storage(k).map_err(|e| format!("{}", e))? { + return Ok(map); + } + } + }; + + let extrinsics = v.extrinsics.as_ref() + .expect("filtered by filter() call above; qed") + .iter().cloned().collect(); + entry.insert((ExtrinsicIndex { + block: block.clone(), + key: k.to_vec(), + }, extrinsics)); + }, + Entry::Occupied(mut entry) => { + // we do not need to check for temporary values here, because entry is Occupied + // AND we are checking it before insertion + let extrinsics = &mut entry.get_mut().1; + extrinsics.extend( + v.extrinsics.as_ref() + .expect("filtered by filter() call above; qed") + .iter() + .cloned() + ); + extrinsics.sort_unstable(); + }, + } + + Ok(map) + }) + .map(|pairs| pairs.into_iter().map(|(_, (k, v))| InputPair::ExtrinsicIndex(k, v))) +} + + +/// Prepare DigestIndex input pairs. +fn prepare_digest_input<'a, H, Number>( + parent: &'a AnchorBlockId, + config: ConfigurationRange, + block: Number, + storage: &'a dyn Storage, +) -> Result<( + impl Iterator> + 'a, + BTreeMap, impl Iterator> + 'a>, + Vec, + ), String> + where + H: Hasher, + H::Out: 'a + Encode, + Number: BlockNumber, +{ + let build_skewed_digest = config.end.as_ref() == Some(&block); + let block_for_digest = if build_skewed_digest { + config.config.next_max_level_digest_range(config.zero.clone(), block.clone()) + .map(|(_, end)| end) + .unwrap_or_else(|| block.clone()) + } else { + block.clone() + }; + + let digest_input_blocks = digest_build_iterator(config, block_for_digest).collect::>(); + digest_input_blocks.clone().into_iter() + .try_fold( + (BTreeMap::new(), BTreeMap::new()), move |(mut map, mut child_map), digest_build_block| { + let extrinsic_prefix = ExtrinsicIndex::key_neutral_prefix(digest_build_block.clone()); + let digest_prefix = DigestIndex::key_neutral_prefix(digest_build_block.clone()); + let child_prefix = ChildIndex::key_neutral_prefix(digest_build_block.clone()); + let trie_root = storage.root(parent, digest_build_block.clone())?; + let trie_root = trie_root.ok_or_else(|| format!("No changes trie root for block {}", digest_build_block.clone()))?; + + let insert_to_map = |map: &mut BTreeMap<_,_>, key: Vec| { + match map.entry(key.clone()) { + Entry::Vacant(entry) => { + entry.insert((DigestIndex { + block: block.clone(), + key, + }, vec![digest_build_block.clone()])); + }, + Entry::Occupied(mut entry) => { + // DigestIndexValue must be sorted. Here we are relying on the fact that digest_build_iterator() + // returns blocks in ascending order => we only need to check for duplicates + // + // is_dup_block could be true when key has been changed in both digest block + // AND other blocks that it covers + let is_dup_block = entry.get().1.last() == Some(&digest_build_block); + if !is_dup_block { + entry.get_mut().1.push(digest_build_block.clone()); + } + }, + } + }; + + // try to get all updated keys from cache + let populated_from_cache = storage.with_cached_changed_keys( + &trie_root, + &mut |changed_keys| { + for (storage_key, changed_keys) in changed_keys { + let map = match storage_key { + Some(storage_key) => child_map + .entry(ChildIndex:: { + block: block.clone(), + storage_key: storage_key.clone(), + }) + .or_default(), + None => &mut map, + }; + for changed_key in changed_keys.iter().cloned() { + insert_to_map(map, changed_key); + } + } + } + ); + if populated_from_cache { + return Ok((map, child_map)); + } + + let mut children_roots = BTreeMap::, _>::new(); + { + let trie_storage = TrieBackendEssence::<_, H>::new( + crate::changes_trie::TrieBackendStorageAdapter(storage), + trie_root, + ); + + trie_storage.for_key_values_with_prefix(&child_prefix, |key, value| + if let Ok(InputKey::ChildIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + if let Ok(value) = >::decode(&mut &value[..]) { + let mut trie_root = ::Out::default(); + trie_root.as_mut().copy_from_slice(&value[..]); + children_roots.insert(trie_key.storage_key, trie_root); + } + }); + + trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key| + if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + insert_to_map(&mut map, trie_key.key); + }); + + trie_storage.for_keys_with_prefix(&digest_prefix, |key| + if let Ok(InputKey::DigestIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + insert_to_map(&mut map, trie_key.key); + }); + } + + for (storage_key, trie_root) in children_roots.into_iter() { + let child_index = ChildIndex:: { + block: block.clone(), + storage_key, + }; + + let mut map = child_map.entry(child_index).or_default(); + let trie_storage = TrieBackendEssence::<_, H>::new( + crate::changes_trie::TrieBackendStorageAdapter(storage), + trie_root, + ); + trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key| + if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + insert_to_map(&mut map, trie_key.key); + }); + + trie_storage.for_keys_with_prefix(&digest_prefix, |key| + if let Ok(InputKey::DigestIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + insert_to_map(&mut map, trie_key.key); + }); + } + Ok((map, child_map)) + }) + .map(|(pairs, child_pairs)| ( + pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v)), + child_pairs.into_iter().map(|(sk, pairs)| + (sk, pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v)))).collect(), + digest_input_blocks, + )) +} + +#[cfg(test)] +mod test { + use codec::Encode; + use sp_core::Blake2Hasher; + use sp_core::storage::well_known_keys::EXTRINSIC_INDEX; + use sp_core::storage::ChildInfo; + use crate::InMemoryBackend; + use crate::changes_trie::{RootsStorage, Configuration, storage::InMemoryStorage}; + use crate::changes_trie::build_cache::{IncompleteCacheAction, IncompleteCachedBuildData}; + use crate::overlayed_changes::{OverlayedValue, OverlayedChangeSet}; + use super::*; + + const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1"); + const CHILD_INFO_2: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_2"); + + fn prepare_for_build(zero: u64) -> ( + InMemoryBackend, + InMemoryStorage, + OverlayedChanges, + Configuration, + ) { + let config = Configuration { digest_interval: 4, digest_levels: 2 }; + let backend: InMemoryBackend<_> = vec![ + (vec![100], vec![255]), + (vec![101], vec![255]), + (vec![102], vec![255]), + (vec![103], vec![255]), + (vec![104], vec![255]), + (vec![105], vec![255]), + ].into_iter().collect::>().into(); + let child_trie_key1 = b"1".to_vec(); + let child_trie_key2 = b"2".to_vec(); + let storage = InMemoryStorage::with_inputs(vec![ + (zero + 1, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![100] }, vec![1, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![101] }, vec![0, 2]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![105] }, vec![0, 2, 4]), + ]), + (zero + 2, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 2, key: vec![102] }, vec![0]), + ]), + (zero + 3, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 3, key: vec![100] }, vec![0]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 3, key: vec![105] }, vec![1]), + ]), + (zero + 4, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![103] }, vec![0, 1]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1, zero + 3]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1, zero + 3]), + ]), + (zero + 5, Vec::new()), + (zero + 6, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 6, key: vec![105] }, vec![2]), + ]), + (zero + 7, Vec::new()), + (zero + 8, vec![ + InputPair::DigestIndex(DigestIndex { block: zero + 8, key: vec![105] }, vec![zero + 6]), + ]), + (zero + 9, Vec::new()), (zero + 10, Vec::new()), (zero + 11, Vec::new()), (zero + 12, Vec::new()), + (zero + 13, Vec::new()), (zero + 14, Vec::new()), (zero + 15, Vec::new()), + ], vec![(child_trie_key1.clone(), vec![ + (zero + 1, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![100] }, vec![1, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![101] }, vec![0, 2]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![105] }, vec![0, 2, 4]), + ]), + (zero + 2, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 2, key: vec![102] }, vec![0]), + ]), + (zero + 4, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 2, key: vec![102] }, vec![0, 3]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + ]), + ]), + ]); + let changes = OverlayedChanges { + prospective: OverlayedChangeSet { top: vec![ + (vec![100], OverlayedValue { + value: Some(vec![200]), + extrinsics: Some(vec![0, 2].into_iter().collect()) + }), + (vec![103], OverlayedValue { + value: None, + extrinsics: Some(vec![0, 1].into_iter().collect()) + }), + ].into_iter().collect(), + children: vec![ + (child_trie_key1.clone(), (vec![ + (vec![100], OverlayedValue { + value: Some(vec![200]), + extrinsics: Some(vec![0, 2].into_iter().collect()) + }) + ].into_iter().collect(), CHILD_INFO_1.to_owned())), + (child_trie_key2, (vec![ + (vec![100], OverlayedValue { + value: Some(vec![200]), + extrinsics: Some(vec![0, 2].into_iter().collect()) + }) + ].into_iter().collect(), CHILD_INFO_2.to_owned())), + ].into_iter().collect() + }, + committed: OverlayedChangeSet { top: vec![ + (EXTRINSIC_INDEX.to_vec(), OverlayedValue { + value: Some(3u32.encode()), + extrinsics: None, + }), + (vec![100], OverlayedValue { + value: Some(vec![202]), + extrinsics: Some(vec![3].into_iter().collect()) + }), + (vec![101], OverlayedValue { + value: Some(vec![203]), + extrinsics: Some(vec![1].into_iter().collect()) + }), + ].into_iter().collect(), + children: vec![ + (child_trie_key1, (vec![ + (vec![100], OverlayedValue { + value: Some(vec![202]), + extrinsics: Some(vec![3].into_iter().collect()) + }) + ].into_iter().collect(), CHILD_INFO_1.to_owned())), + ].into_iter().collect(), + }, + changes_trie_config: Some(config.clone()), + }; + + (backend, storage, changes, config) + } + + fn configuration_range<'a>(config: &'a Configuration, zero: u64) -> ConfigurationRange<'a, u64> { + ConfigurationRange { + config, + zero, + end: None, + } + } + + #[test] + fn build_changes_trie_nodes_on_non_digest_block() { + fn test_with_zero(zero: u64) { + let (backend, storage, changes, config) = prepare_for_build(zero); + let parent = AnchorBlockId { hash: Default::default(), number: zero + 4 }; + let changes_trie_nodes = prepare_input( + &backend, + &storage, + configuration_range(&config, zero), + &changes, + &parent, + ).unwrap(); + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![103] }, vec![0, 1]), + ]); + assert_eq!(changes_trie_nodes.1.into_iter() + .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ + (ChildIndex { block: zero + 5u64, storage_key: b"1".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5u64, key: vec![100] }, vec![0, 2, 3]), + ]), + (ChildIndex { block: zero + 5, storage_key: b"2".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![100] }, vec![0, 2]), + ]), + ]); + + } + + test_with_zero(0); + test_with_zero(16); + test_with_zero(17); + } + + #[test] + fn build_changes_trie_nodes_on_digest_block_l1() { + fn test_with_zero(zero: u64) { + let (backend, storage, changes, config) = prepare_for_build(zero); + let parent = AnchorBlockId { hash: Default::default(), number: zero + 3 }; + let changes_trie_nodes = prepare_input( + &backend, + &storage, + configuration_range(&config, zero), + &changes, + &parent, + ).unwrap(); + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![103] }, vec![0, 1]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1, zero + 3]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1, zero + 3]), + ]); + assert_eq!(changes_trie_nodes.1.into_iter() + .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ + (ChildIndex { block: zero + 4u64, storage_key: b"1".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4u64, key: vec![100] }, vec![0, 2, 3]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1]), + ]), + (ChildIndex { block: zero + 4, storage_key: b"2".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2]), + ]), + ]); + + } + + test_with_zero(0); + test_with_zero(16); + test_with_zero(17); + } + + #[test] + fn build_changes_trie_nodes_on_digest_block_l2() { + fn test_with_zero(zero: u64) { + let (backend, storage, changes, config) = prepare_for_build(zero); + let parent = AnchorBlockId { hash: Default::default(), number: zero + 15 }; + let changes_trie_nodes = prepare_input( + &backend, + &storage, + configuration_range(&config, zero), + &changes, + &parent, + ).unwrap(); + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![103] }, vec![0, 1]), + + InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![100] }, vec![zero + 4]), + InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![101] }, vec![zero + 4]), + InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![102] }, vec![zero + 4]), + InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![103] }, vec![zero + 4]), + InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![105] }, vec![zero + 4, zero + 8]), + ]); + assert_eq!(changes_trie_nodes.1.into_iter() + .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ + (ChildIndex { block: zero + 16u64, storage_key: b"1".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16u64, key: vec![100] }, vec![0, 2, 3]), + + InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![102] }, vec![zero + 4]), + ]), + (ChildIndex { block: zero + 16, storage_key: b"2".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![100] }, vec![0, 2]), + ]), + ]); + + } + + test_with_zero(0); + test_with_zero(16); + test_with_zero(17); + } + + #[test] + fn build_changes_trie_nodes_on_skewed_digest_block() { + fn test_with_zero(zero: u64) { + let (backend, storage, changes, config) = prepare_for_build(zero); + let parent = AnchorBlockId { hash: Default::default(), number: zero + 10 }; + + let mut configuration_range = configuration_range(&config, zero); + let changes_trie_nodes = prepare_input( + &backend, + &storage, + configuration_range.clone(), + &changes, + &parent, + ).unwrap(); + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![103] }, vec![0, 1]), + ]); + + configuration_range.end = Some(zero + 11); + let changes_trie_nodes = prepare_input( + &backend, + &storage, + configuration_range, + &changes, + &parent, + ).unwrap(); + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![103] }, vec![0, 1]), + + InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![100] }, vec![zero + 4]), + InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![101] }, vec![zero + 4]), + InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![102] }, vec![zero + 4]), + InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![103] }, vec![zero + 4]), + InputPair::DigestIndex(DigestIndex { block: zero + 11, key: vec![105] }, vec![zero + 4, zero + 8]), + ]); + } + + test_with_zero(0); + test_with_zero(16); + test_with_zero(17); + } + + #[test] + fn build_changes_trie_nodes_ignores_temporary_storage_values() { + fn test_with_zero(zero: u64) { + let (backend, storage, mut changes, config) = prepare_for_build(zero); + + // 110: missing from backend, set to None in overlay + changes.prospective.top.insert(vec![110], OverlayedValue { + value: None, + extrinsics: Some(vec![1].into_iter().collect()) + }); + + let parent = AnchorBlockId { hash: Default::default(), number: zero + 3 }; + let changes_trie_nodes = prepare_input( + &backend, + &storage, + configuration_range(&config, zero), + &changes, + &parent, + ).unwrap(); + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![103] }, vec![0, 1]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1, zero + 3]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1, zero + 3]), + ]); + assert_eq!(changes_trie_nodes.1.into_iter() + .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ + (ChildIndex { block: zero + 4u64, storage_key: b"1".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4u64, key: vec![100] }, vec![0, 2, 3]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1]), + ]), + (ChildIndex { block: zero + 4, storage_key: b"2".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2]), + ]), + ]); + + } + + test_with_zero(0); + test_with_zero(16); + test_with_zero(17); + } + + #[test] + fn cache_is_used_when_changes_trie_is_built() { + let (backend, mut storage, changes, _) = prepare_for_build(0); + let config = changes.changes_trie_config.as_ref().unwrap(); + let parent = AnchorBlockId { hash: Default::default(), number: 15 }; + + // override some actual values from storage with values from the cache + // + // top-level storage: + // (keys 100, 101, 103, 105 are now missing from block#4 => they do not appear + // in l2 digest at block 16) + // + // "1" child storage: + // key 102 is now missing from block#4 => it doesn't appear in l2 digest at block 16 + // (keys 103, 104) are now added to block#4 => they appear in l2 digest at block 16 + // + // "2" child storage: + // (keys 105, 106) are now added to block#4 => they appear in l2 digest at block 16 + let trie_root4 = storage.root(&parent, 4).unwrap().unwrap(); + let cached_data4 = IncompleteCacheAction::CacheBuildData(IncompleteCachedBuildData::new()) + .set_digest_input_blocks(vec![1, 2, 3]) + .insert(None, vec![vec![100], vec![102]].into_iter().collect()) + .insert(Some(b"1".to_vec()), vec![vec![103], vec![104]].into_iter().collect()) + .insert(Some(b"2".to_vec()), vec![vec![105], vec![106]].into_iter().collect()) + .complete(4, &trie_root4); + storage.cache_mut().perform(cached_data4); + + let (root_changes_trie_nodes, child_changes_tries_nodes, _) = prepare_input( + &backend, + &storage, + configuration_range(&config, 0), + &changes, + &parent, + ).unwrap(); + assert_eq!(root_changes_trie_nodes.collect::>>(), vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![103] }, vec![0, 1]), + + InputPair::DigestIndex(DigestIndex { block: 16, key: vec![100] }, vec![4]), + InputPair::DigestIndex(DigestIndex { block: 16, key: vec![102] }, vec![4]), + InputPair::DigestIndex(DigestIndex { block: 16, key: vec![105] }, vec![8]), + ]); + + let child_changes_tries_nodes = child_changes_tries_nodes + .into_iter() + .map(|(k, i)| (k, i.collect::>())) + .collect::>(); + assert_eq!( + child_changes_tries_nodes.get(&ChildIndex { block: 16u64, storage_key: b"1".to_vec() }).unwrap(), + &vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16u64, key: vec![100] }, vec![0, 2, 3]), + + InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![103] }, vec![4]), + InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![104] }, vec![4]), + ], + ); + assert_eq!( + child_changes_tries_nodes.get(&ChildIndex { block: 16u64, storage_key: b"2".to_vec() }).unwrap(), + &vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16u64, key: vec![100] }, vec![0, 2]), + + InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![105] }, vec![4]), + InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![106] }, vec![4]), + ], + ); + + } +} diff --git a/core/state-machine/src/changes_trie/build_cache.rs b/primitives/state-machine/src/changes_trie/build_cache.rs similarity index 99% rename from core/state-machine/src/changes_trie/build_cache.rs rename to primitives/state-machine/src/changes_trie/build_cache.rs index f5c7c28b6b801..76e3652e16681 100644 --- a/core/state-machine/src/changes_trie/build_cache.rs +++ b/primitives/state-machine/src/changes_trie/build_cache.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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/state-machine/src/changes_trie/build_iterator.rs b/primitives/state-machine/src/changes_trie/build_iterator.rs similarity index 99% rename from core/state-machine/src/changes_trie/build_iterator.rs rename to primitives/state-machine/src/changes_trie/build_iterator.rs index 36b6dd198316d..bb93ce98a855d 100644 --- a/core/state-machine/src/changes_trie/build_iterator.rs +++ b/primitives/state-machine/src/changes_trie/build_iterator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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/state-machine/src/changes_trie/changes_iterator.rs b/primitives/state-machine/src/changes_trie/changes_iterator.rs similarity index 97% rename from core/state-machine/src/changes_trie/changes_iterator.rs rename to primitives/state-machine/src/changes_trie/changes_iterator.rs index e8730a1bddedb..9f2d44967d716 100644 --- a/core/state-machine/src/changes_trie/changes_iterator.rs +++ b/primitives/state-machine/src/changes_trie/changes_iterator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -19,16 +19,16 @@ use std::cell::RefCell; use std::collections::VecDeque; -use codec::{Decode, Encode}; +use codec::{Decode, Encode, Codec}; use hash_db::Hasher; use num_traits::Zero; -use trie::Recorder; +use sp_trie::Recorder; use crate::changes_trie::{AnchorBlockId, ConfigurationRange, RootsStorage, Storage, BlockNumber}; use crate::changes_trie::input::{DigestIndex, ExtrinsicIndex, DigestIndexValue, ExtrinsicIndexValue}; use crate::changes_trie::storage::{TrieBackendAdapter, InMemoryStorage}; use crate::changes_trie::input::ChildIndex; use crate::changes_trie::surface_iterator::{surface_iterator, SurfaceIterator}; -use crate::proving_backend::ProvingBackendEssence; +use crate::proving_backend::ProvingBackendRecorder; use crate::trie_backend_essence::{TrieBackendEssence}; /// Return changes of given key at given blocks range. @@ -81,7 +81,7 @@ pub fn key_changes_proof<'a, H: Hasher, Number: BlockNumber>( max: Number, storage_key: Option<&[u8]>, key: &[u8], -) -> Result>, String> { +) -> Result>, String> where H::Out: Codec { // we can't query any roots before root let max = ::std::cmp::min(max.clone(), end.number.clone()); @@ -129,7 +129,7 @@ pub fn key_changes_proof_check<'a, H: Hasher, Number: BlockNumber>( max: Number, storage_key: Option<&[u8]>, key: &[u8] -) -> Result, String> { +) -> Result, String> where H::Out: Encode { key_changes_proof_check_with_db( config, roots_storage, @@ -152,7 +152,7 @@ pub fn key_changes_proof_check_with_db<'a, H: Hasher, Number: BlockNumber>( max: Number, storage_key: Option<&[u8]>, key: &[u8] -) -> Result, String> { +) -> Result, String> where H::Out: Encode { // we can't query any roots before root let max = ::std::cmp::min(max.clone(), end.number.clone()); @@ -316,8 +316,8 @@ pub struct DrilldownIterator<'a, H, Number> essence: DrilldownIteratorEssence<'a, H, Number>, } -impl<'a, H: Hasher, Number: BlockNumber> Iterator - for DrilldownIterator<'a, H, Number> +impl<'a, H: Hasher, Number: BlockNumber> Iterator for DrilldownIterator<'a, H, Number> + where H::Out: Encode { type Item = Result<(Number, u32), String>; @@ -358,7 +358,7 @@ impl<'a, H, Number> Iterator for ProvingDrilldownIterator<'a, H, Number> where Number: BlockNumber, H: Hasher, - H::Out: 'a, + H::Out: 'a + Codec, { type Item = Result<(Number, u32), String>; @@ -366,7 +366,7 @@ impl<'a, H, Number> Iterator for ProvingDrilldownIterator<'a, H, Number> let proof_recorder = &mut *self.proof_recorder.try_borrow_mut() .expect("only fails when already borrowed; storage() is non-reentrant; qed"); self.essence.next(|storage, root, key| - ProvingBackendEssence::<_, H> { + ProvingBackendRecorder::<_, H> { backend: &TrieBackendEssence::new(TrieBackendAdapter::new(storage), root), proof_recorder, }.storage(key)) @@ -376,7 +376,7 @@ impl<'a, H, Number> Iterator for ProvingDrilldownIterator<'a, H, Number> #[cfg(test)] mod tests { use std::iter::FromIterator; - use primitives::Blake2Hasher; + use sp_core::Blake2Hasher; use crate::changes_trie::Configuration; use crate::changes_trie::input::InputPair; use crate::changes_trie::storage::InMemoryStorage; diff --git a/core/state-machine/src/changes_trie/input.rs b/primitives/state-machine/src/changes_trie/input.rs similarity index 99% rename from core/state-machine/src/changes_trie/input.rs rename to primitives/state-machine/src/changes_trie/input.rs index e0bcad18be114..9b3341ca5842b 100644 --- a/core/state-machine/src/changes_trie/input.rs +++ b/primitives/state-machine/src/changes_trie/input.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/primitives/state-machine/src/changes_trie/mod.rs b/primitives/state-machine/src/changes_trie/mod.rs new file mode 100644 index 0000000000000..cb19d157dd80a --- /dev/null +++ b/primitives/state-machine/src/changes_trie/mod.rs @@ -0,0 +1,352 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Changes trie related structures and functions. +//! +//! Changes trie is a trie built of { storage key => extrinsiscs } pairs +//! at the end of each block. For every changed storage key it contains +//! a pair, mapping key to the set of extrinsics where it has been changed. +//! +//! Optionally, every N blocks, additional level1-digest nodes are appended +//! to the changes trie, containing pairs { storage key => blocks }. For every +//! storage key that has been changed in PREVIOUS N-1 blocks (except for genesis +//! block) it contains a pair, mapping this key to the set of blocks where it +//! has been changed. +//! +//! Optionally, every N^digest_level (where digest_level > 1) blocks, additional +//! digest_level digest is created. It is built out of pairs { storage key => digest +//! block }, containing entries for every storage key that has been changed in +//! the last N*digest_level-1 blocks (except for genesis block), mapping these keys +//! to the set of lower-level digest blocks. +//! +//! Changes trie configuration could change within a time. The range of blocks, where +//! configuration has been active, is given by two blocks: zero and end. Zero block is +//! the block where configuration has been set. But the first changes trie that uses +//! this configuration will be built at the block zero+1. If configuration deactivates +//! at some block, this will be the end block of the configuration. It is also the +//! zero block of the next configuration. +//! +//! If configuration has the end block, it also means that 'skewed digest' has/should +//! been built at that block. If this is the block where max-level digest should have +//! been created, than it is simply max-level digest of this configuration. Otherwise, +//! it is the digest that covers all blocks since last max-level digest block was +//! created. +//! +//! Changes trie only contains the top level storage changes. Sub-level changes +//! are propagated through its storage root on the top level storage. + +mod build; +mod build_cache; +mod build_iterator; +mod changes_iterator; +mod input; +mod prune; +mod storage; +mod surface_iterator; + +pub use self::build_cache::{BuildCache, CachedBuildData, CacheAction}; +pub use self::storage::InMemoryStorage; +pub use self::changes_iterator::{ + key_changes, key_changes_proof, + key_changes_proof_check, key_changes_proof_check_with_db, +}; +pub use self::prune::{prune, oldest_non_pruned_trie}; + +use std::collections::{HashMap, HashSet}; +use std::convert::TryInto; +use hash_db::{Hasher, Prefix}; +use crate::backend::Backend; +use num_traits::{One, Zero}; +use codec::{Decode, Encode}; +use sp_core; +use crate::changes_trie::build::prepare_input; +use crate::changes_trie::build_cache::{IncompleteCachedBuildData, IncompleteCacheAction}; +use crate::overlayed_changes::OverlayedChanges; +use sp_trie::{MemoryDB, DBValue, TrieMut}; +use sp_trie::trie_types::TrieDBMut; + +/// Changes that are made outside of extrinsics are marked with this index; +pub const NO_EXTRINSIC_INDEX: u32 = 0xffffffff; + +/// Requirements for block number that can be used with changes tries. +pub trait BlockNumber: + Send + Sync + 'static + + std::fmt::Display + + Clone + + From + TryInto + One + Zero + + PartialEq + Ord + + std::hash::Hash + + std::ops::Add + ::std::ops::Sub + + std::ops::Mul + ::std::ops::Div + + std::ops::Rem + + std::ops::AddAssign + + num_traits::CheckedMul + num_traits::CheckedSub + + Decode + Encode +{} + +impl BlockNumber for T where T: + Send + Sync + 'static + + std::fmt::Display + + Clone + + From + TryInto + One + Zero + + PartialEq + Ord + + std::hash::Hash + + std::ops::Add + ::std::ops::Sub + + std::ops::Mul + ::std::ops::Div + + std::ops::Rem + + std::ops::AddAssign + + num_traits::CheckedMul + num_traits::CheckedSub + + Decode + Encode, +{} + +/// Block identifier that could be used to determine fork of this block. +#[derive(Debug)] +pub struct AnchorBlockId { + /// Hash of this block. + pub hash: Hash, + /// Number of this block. + pub number: Number, +} + +/// Changes trie storage. Provides access to trie roots and trie nodes. +pub trait RootsStorage: Send + Sync { + /// Resolve hash of the block into anchor. + fn build_anchor(&self, hash: H::Out) -> Result, String>; + /// Get changes trie root for the block with given number which is an ancestor (or the block + /// itself) of the anchor_block (i.e. anchor_block.number >= block). + fn root(&self, anchor: &AnchorBlockId, block: Number) -> Result, String>; +} + +/// Changes trie storage. Provides access to trie roots and trie nodes. +pub trait Storage: RootsStorage { + /// Casts from self reference to RootsStorage reference. + fn as_roots_storage(&self) -> &dyn RootsStorage; + /// Execute given functor with cached entry for given trie root. + /// Returns true if the functor has been called (cache entry exists) and false otherwise. + fn with_cached_changed_keys( + &self, + root: &H::Out, + functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool; + /// Get a trie node. + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String>; +} + +/// Changes trie storage -> trie backend essence adapter. +pub struct TrieBackendStorageAdapter<'a, H: Hasher, Number: BlockNumber>(pub &'a dyn Storage); + +impl<'a, H: Hasher, N: BlockNumber> crate::TrieBackendStorage for TrieBackendStorageAdapter<'a, H, N> { + type Overlay = sp_trie::MemoryDB; + + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { + self.0.get(key, prefix) + } +} + +/// Changes trie configuration. +pub type Configuration = sp_core::ChangesTrieConfiguration; + +/// Blocks range where configuration has been constant. +#[derive(Clone)] +pub struct ConfigurationRange<'a, N> { + /// Active configuration. + pub config: &'a Configuration, + /// Zero block of this configuration. The configuration is active starting from the next block. + pub zero: N, + /// End block of this configuration. It is the last block where configuration has been active. + pub end: Option, +} + +/// Compute the changes trie root and transaction for given block. +/// Returns Err(()) if unknown `parent_hash` has been passed. +/// Returns Ok(None) if there's no data to perform computation. +/// Panics if background storage returns an error (and `panic_on_storage_error` is `true`) OR +/// if insert to MemoryDB fails. +pub fn build_changes_trie<'a, B: Backend, S: Storage, H: Hasher, Number: BlockNumber>( + backend: &B, + storage: Option<&'a S>, + changes: &OverlayedChanges, + parent_hash: H::Out, + panic_on_storage_error: bool, +) -> Result, H::Out, CacheAction)>, ()> + where + H::Out: Ord + 'static + Encode, +{ + let (storage, config) = match (storage, changes.changes_trie_config.as_ref()) { + (Some(storage), Some(config)) => (storage, config), + _ => return Ok(None), + }; + + /// Panics when `res.is_err() && panic`, otherwise it returns `Err(())` on an error. + fn maybe_panic( + res: std::result::Result, + panic: bool, + ) -> std::result::Result { + res.map(Ok) + .unwrap_or_else(|e| if panic { + panic!("changes trie: storage access is not allowed to fail within runtime: {:?}", e) + } else { + Err(()) + }) + } + + // FIXME: remove this in https://github.com/paritytech/substrate/pull/3201 + let config = ConfigurationRange { + config, + zero: Zero::zero(), + end: None, + }; + + // build_anchor error should not be considered fatal + let parent = storage.build_anchor(parent_hash).map_err(|_| ())?; + let block = parent.number.clone() + One::one(); + + // storage errors are considered fatal (similar to situations when runtime fetches values from storage) + let (input_pairs, child_input_pairs, digest_input_blocks) = maybe_panic( + prepare_input::( + backend, + storage, + config.clone(), + changes, + &parent, + ), + panic_on_storage_error, + )?; + + // prepare cached data + let mut cache_action = prepare_cached_build_data(config, block.clone()); + let needs_changed_keys = cache_action.collects_changed_keys(); + cache_action = cache_action.set_digest_input_blocks(digest_input_blocks); + + let mut mdb = MemoryDB::default(); + let mut child_roots = Vec::with_capacity(child_input_pairs.len()); + for (child_index, input_pairs) in child_input_pairs { + let mut not_empty = false; + let mut root = Default::default(); + { + let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + let mut storage_changed_keys = HashSet::new(); + for input_pair in input_pairs { + if needs_changed_keys { + if let Some(key) = input_pair.key() { + storage_changed_keys.insert(key.to_vec()); + } + } + + let (key, value) = input_pair.into(); + not_empty = true; + maybe_panic(trie.insert(&key, &value), panic_on_storage_error)?; + } + + cache_action = cache_action.insert( + Some(child_index.storage_key.clone()), + storage_changed_keys, + ); + } + if not_empty { + child_roots.push(input::InputPair::ChildIndex(child_index, root.as_ref().to_vec())); + } + } + let mut root = Default::default(); + { + let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + for (key, value) in child_roots.into_iter().map(Into::into) { + maybe_panic(trie.insert(&key, &value), panic_on_storage_error)?; + } + + let mut storage_changed_keys = HashSet::new(); + for input_pair in input_pairs { + if needs_changed_keys { + if let Some(key) = input_pair.key() { + storage_changed_keys.insert(key.to_vec()); + } + } + + let (key, value) = input_pair.into(); + maybe_panic(trie.insert(&key, &value), panic_on_storage_error)?; + } + + cache_action = cache_action.insert( + None, + storage_changed_keys, + ); + } + + let cache_action = cache_action.complete(block, &root); + Ok(Some((mdb, root, cache_action))) +} + +/// Prepare empty cached build data for given block. +fn prepare_cached_build_data( + config: ConfigurationRange, + block: Number, +) -> IncompleteCacheAction { + // when digests are not enabled in configuration, we do not need to cache anything + // because it'll never be used again for building other tries + // => let's clear the cache + if !config.config.is_digest_build_enabled() { + return IncompleteCacheAction::Clear; + } + + // when this is the last block where current configuration is active + // => let's clear the cache + if config.end.as_ref() == Some(&block) { + return IncompleteCacheAction::Clear; + } + + // we do not need to cache anything when top-level digest trie is created, because + // it'll never be used again for building other tries + // => let's clear the cache + match config.config.digest_level_at_block(config.zero.clone(), block) { + Some((digest_level, _, _)) if digest_level == config.config.digest_levels => IncompleteCacheAction::Clear, + _ => IncompleteCacheAction::CacheBuildData(IncompleteCachedBuildData::new()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cache_is_cleared_when_digests_are_disabled() { + let config = Configuration { digest_interval: 0, digest_levels: 0 }; + let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; + assert_eq!(prepare_cached_build_data(config_range, 8u32), IncompleteCacheAction::Clear); + } + + #[test] + fn build_data_is_cached_when_digests_are_enabled() { + let config = Configuration { digest_interval: 8, digest_levels: 2 }; + let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; + assert!(prepare_cached_build_data(config_range.clone(), 4u32).collects_changed_keys()); + assert!(prepare_cached_build_data(config_range.clone(), 7u32).collects_changed_keys()); + assert!(prepare_cached_build_data(config_range, 8u32).collects_changed_keys()); + } + + #[test] + fn cache_is_cleared_when_digests_are_enabled_and_top_level_digest_is_built() { + let config = Configuration { digest_interval: 8, digest_levels: 2 }; + let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; + assert_eq!(prepare_cached_build_data(config_range, 64u32), IncompleteCacheAction::Clear); + } + + #[test] + fn cache_is_cleared_when_end_block_of_configuration_is_built() { + let config = Configuration { digest_interval: 8, digest_levels: 2 }; + let config_range = ConfigurationRange { zero: 0, end: Some(4u32), config: &config }; + assert_eq!(prepare_cached_build_data(config_range.clone(), 4u32), IncompleteCacheAction::Clear); + } +} diff --git a/core/state-machine/src/changes_trie/prune.rs b/primitives/state-machine/src/changes_trie/prune.rs similarity index 92% rename from core/state-machine/src/changes_trie/prune.rs rename to primitives/state-machine/src/changes_trie/prune.rs index 1dc7c3e6c07b2..e16daea15821e 100644 --- a/core/state-machine/src/changes_trie/prune.rs +++ b/primitives/state-machine/src/changes_trie/prune.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 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 @@ //! Changes trie pruning-related functions. use hash_db::Hasher; -use trie::Recorder; +use sp_trie::Recorder; use log::warn; use num_traits::{One, Zero}; -use crate::proving_backend::ProvingBackendEssence; +use crate::proving_backend::ProvingBackendRecorder; use crate::trie_backend_essence::TrieBackendEssence; use crate::changes_trie::{AnchorBlockId, Configuration, Storage, BlockNumber}; use crate::changes_trie::storage::TrieBackendAdapter; use crate::changes_trie::input::{ChildIndex, InputKey}; -use codec::Decode; +use codec::{Decode, Codec}; /// Get number of oldest block for which changes trie is not pruned /// given changes trie configuration, pruning parameter and number of @@ -55,7 +55,7 @@ pub fn prune, H: Hasher, Number: BlockNumber, F: FnMut(H:: min_blocks_to_keep: Number, current_block: &AnchorBlockId, mut remove_trie_node: F, -) { +) where H::Out: Codec { // select range for pruning let (first, last) = match pruning_range(config, min_blocks_to_keep, current_block.number.clone()) { @@ -116,13 +116,13 @@ fn prune_trie, H: Hasher, Number: BlockNumber, F: FnMut(H: storage: &S, root: H::Out, remove_trie_node: &mut F, -) { +) where H::Out: Codec { // enumerate all changes trie' keys, recording all nodes that have been 'touched' // (effectively - all changes trie nodes) let mut proof_recorder: Recorder = Default::default(); { - let mut trie = ProvingBackendEssence::<_, H> { + let mut trie = ProvingBackendRecorder::<_, H> { backend: &TrieBackendEssence::new(TrieBackendAdapter::new(storage), root), proof_recorder: &mut proof_recorder, }; @@ -168,7 +168,9 @@ fn pruning_range( // last block for which changes trie is pruned let last_block_to_prune = blocks_to_keep.and_then(|b| block.checked_sub(&b)); - let first_block_to_prune = last_block_to_prune.clone().and_then(|b| b.checked_sub(&prune_interval.into())); + let first_block_to_prune = last_block_to_prune + .clone() + .and_then(|b| b.checked_sub(&prune_interval.into())); last_block_to_prune .and_then(|last| first_block_to_prune.map(|first| (first + One::one(), last))) @@ -200,8 +202,8 @@ fn max_digest_intervals_to_keep( #[cfg(test)] mod tests { use std::collections::HashSet; - use trie::MemoryDB; - use primitives::Blake2Hasher; + use sp_trie::MemoryDB; + use sp_core::Blake2Hasher; use crate::backend::insert_into_memory_db; use crate::changes_trie::storage::InMemoryStorage; use codec::Encode; @@ -219,10 +221,15 @@ mod tests { storage: &S, min_blocks_to_keep: u64, current_block: u64, - ) -> HashSet { + ) -> HashSet where H::Out: Codec { let mut pruned_trie_nodes = HashSet::new(); - prune(config, storage, min_blocks_to_keep, &AnchorBlockId { hash: Default::default(), number: current_block }, - |node| { pruned_trie_nodes.insert(node); }); + prune( + config, + storage, + min_blocks_to_keep, + &AnchorBlockId { hash: Default::default(), number: current_block }, + |node| { pruned_trie_nodes.insert(node); }, + ); pruned_trie_nodes } @@ -232,18 +239,22 @@ mod tests { let child_key = ChildIndex { block: 67u64, storage_key: b"1".to_vec() }.encode(); let mut mdb1 = MemoryDB::::default(); - let root1 = insert_into_memory_db::(&mut mdb1, vec![(vec![10], vec![20])]).unwrap(); + let root1 = insert_into_memory_db::( + &mut mdb1, vec![(vec![10], vec![20])]).unwrap(); let mut mdb2 = MemoryDB::::default(); - let root2 = insert_into_memory_db::(&mut mdb2, vec![(vec![11], vec![21]), (vec![12], vec![22])]).unwrap(); + let root2 = insert_into_memory_db::( + &mut mdb2, vec![(vec![11], vec![21]), (vec![12], vec![22])]).unwrap(); let mut mdb3 = MemoryDB::::default(); - let ch_root3 = insert_into_memory_db::(&mut mdb3, vec![(vec![110], vec![120])]).unwrap(); + let ch_root3 = insert_into_memory_db::( + &mut mdb3, vec![(vec![110], vec![120])]).unwrap(); let root3 = insert_into_memory_db::(&mut mdb3, vec![ (vec![13], vec![23]), (vec![14], vec![24]), (child_key, ch_root3.as_ref().encode()), ]).unwrap(); let mut mdb4 = MemoryDB::::default(); - let root4 = insert_into_memory_db::(&mut mdb4, vec![(vec![15], vec![25])]).unwrap(); + let root4 = insert_into_memory_db::( + &mut mdb4, vec![(vec![15], vec![25])]).unwrap(); let storage = InMemoryStorage::new(); storage.insert(65, root1, mdb1); storage.insert(66, root2, mdb2); diff --git a/primitives/state-machine/src/changes_trie/storage.rs b/primitives/state-machine/src/changes_trie/storage.rs new file mode 100644 index 0000000000000..163ea7f412251 --- /dev/null +++ b/primitives/state-machine/src/changes_trie/storage.rs @@ -0,0 +1,208 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Changes trie storage utilities. + +use std::collections::{BTreeMap, HashSet, HashMap}; +use hash_db::{Hasher, Prefix, EMPTY_PREFIX}; +use sp_trie::DBValue; +use sp_trie::MemoryDB; +use parking_lot::RwLock; +use crate::changes_trie::{BuildCache, RootsStorage, Storage, AnchorBlockId, BlockNumber}; +use crate::trie_backend_essence::TrieBackendStorage; + +#[cfg(test)] +use crate::backend::insert_into_memory_db; +#[cfg(test)] +use crate::changes_trie::input::{InputPair, ChildIndex}; + +/// In-memory implementation of changes trie storage. +pub struct InMemoryStorage { + data: RwLock>, + cache: BuildCache, +} + +/// Adapter for using changes trie storage as a TrieBackendEssence' storage. +pub struct TrieBackendAdapter<'a, H: Hasher, Number: BlockNumber> { + storage: &'a dyn Storage, + _hasher: std::marker::PhantomData<(H, Number)>, +} + +struct InMemoryStorageData { + roots: BTreeMap, + mdb: MemoryDB, +} + +impl InMemoryStorage { + /// Creates storage from given in-memory database. + pub fn with_db(mdb: MemoryDB) -> Self { + Self { + data: RwLock::new(InMemoryStorageData { + roots: BTreeMap::new(), + mdb, + }), + cache: BuildCache::new(), + } + } + + /// Creates storage with empty database. + pub fn new() -> Self { + Self::with_db(Default::default()) + } + + /// Creates storage with given proof. + pub fn with_proof(proof: Vec>) -> Self { + use hash_db::HashDB; + + let mut proof_db = MemoryDB::::default(); + for item in proof { + proof_db.insert(EMPTY_PREFIX, &item); + } + Self::with_db(proof_db) + } + + /// Get mutable cache reference. + pub fn cache_mut(&mut self) -> &mut BuildCache { + &mut self.cache + } + + /// Create the storage with given blocks. + pub fn with_blocks(blocks: Vec<(Number, H::Out)>) -> Self { + Self { + data: RwLock::new(InMemoryStorageData { + roots: blocks.into_iter().collect(), + mdb: MemoryDB::default(), + }), + cache: BuildCache::new(), + } + } + + #[cfg(test)] + pub fn with_inputs( + mut top_inputs: Vec<(Number, Vec>)>, + children_inputs: Vec<(Vec, Vec<(Number, Vec>)>)>, + ) -> Self { + let mut mdb = MemoryDB::default(); + let mut roots = BTreeMap::new(); + for (storage_key, child_input) in children_inputs { + for (block, pairs) in child_input { + let root = insert_into_memory_db::(&mut mdb, pairs.into_iter().map(Into::into)); + + if let Some(root) = root { + let ix = if let Some(ix) = top_inputs.iter().position(|v| v.0 == block) { + ix + } else { + top_inputs.push((block.clone(), Default::default())); + top_inputs.len() - 1 + }; + top_inputs[ix].1.push(InputPair::ChildIndex( + ChildIndex { block: block.clone(), storage_key: storage_key.clone() }, + root.as_ref().to_vec(), + )); + } + } + } + + for (block, pairs) in top_inputs { + let root = insert_into_memory_db::(&mut mdb, pairs.into_iter().map(Into::into)); + if let Some(root) = root { + roots.insert(block, root); + } + } + + InMemoryStorage { + data: RwLock::new(InMemoryStorageData { + roots, + mdb, + }), + cache: BuildCache::new(), + } + } + + #[cfg(test)] + pub fn clear_storage(&self) { + self.data.write().mdb = MemoryDB::default(); // use new to be more correct + } + + #[cfg(test)] + pub fn remove_from_storage(&self, keys: &HashSet) { + let mut data = self.data.write(); + for key in keys { + data.mdb.remove_and_purge(key, hash_db::EMPTY_PREFIX); + } + } + + #[cfg(test)] + pub fn into_mdb(self) -> MemoryDB { + self.data.into_inner().mdb + } + + /// Insert changes trie for given block. + pub fn insert(&self, block: Number, changes_trie_root: H::Out, trie: MemoryDB) { + let mut data = self.data.write(); + data.roots.insert(block, changes_trie_root); + data.mdb.consolidate(trie); + } +} + +impl RootsStorage for InMemoryStorage { + fn build_anchor(&self, parent_hash: H::Out) -> Result, String> { + self.data.read().roots.iter() + .find(|(_, v)| **v == parent_hash) + .map(|(k, _)| AnchorBlockId { hash: parent_hash, number: k.clone() }) + .ok_or_else(|| format!("Can't find associated number for block {:?}", parent_hash)) + } + + fn root(&self, _anchor_block: &AnchorBlockId, block: Number) -> Result, String> { + Ok(self.data.read().roots.get(&block).cloned()) + } +} + +impl Storage for InMemoryStorage { + fn as_roots_storage(&self) -> &dyn RootsStorage { + self + } + + fn with_cached_changed_keys( + &self, + root: &H::Out, + functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool { + self.cache.with_changed_keys(root, functor) + } + + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { + MemoryDB::::get(&self.data.read().mdb, key, prefix) + } +} + +impl<'a, H: Hasher, Number: BlockNumber> TrieBackendAdapter<'a, H, Number> { + pub fn new(storage: &'a dyn Storage) -> Self { + Self { storage, _hasher: Default::default() } + } +} + +impl<'a, H, Number> TrieBackendStorage for TrieBackendAdapter<'a, H, Number> + where + Number: BlockNumber, + H: Hasher, +{ + type Overlay = MemoryDB; + + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { + self.storage.get(key, prefix) + } +} diff --git a/core/state-machine/src/changes_trie/surface_iterator.rs b/primitives/state-machine/src/changes_trie/surface_iterator.rs similarity index 99% rename from core/state-machine/src/changes_trie/surface_iterator.rs rename to primitives/state-machine/src/changes_trie/surface_iterator.rs index f3583e2f57e6b..02a7c277d965c 100644 --- a/core/state-machine/src/changes_trie/surface_iterator.rs +++ b/primitives/state-machine/src/changes_trie/surface_iterator.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/primitives/state-machine/src/error.rs b/primitives/state-machine/src/error.rs new file mode 100644 index 0000000000000..464403c2f844a --- /dev/null +++ b/primitives/state-machine/src/error.rs @@ -0,0 +1,47 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +/// State Machine Errors + +use std::fmt; + +/// State Machine Error bound. +/// +/// This should reflect Wasm error type bound for future compatibility. +pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} + +impl Error for T {} + +/// Externalities Error. +/// +/// Externalities are not really allowed to have errors, since it's assumed that dependent code +/// would not be executed unless externalities were available. This is included for completeness, +/// and as a transition away from the pre-existing framework. +#[derive(Debug, Eq, PartialEq)] +pub enum ExecutionError { + /// Backend error. + Backend(String), + /// The entry `:code` doesn't exist in storage so there's no way we can execute anything. + CodeEntryDoesNotExist, + /// Backend is incompatible with execution proof generation process. + UnableToGenerateProof, + /// Invalid execution proof. + InvalidProof, +} + +impl fmt::Display for ExecutionError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Externalities Error") } +} diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs new file mode 100644 index 0000000000000..6fc4312d1079d --- /dev/null +++ b/primitives/state-machine/src/ext.rs @@ -0,0 +1,771 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Concrete externalities implementation. + +use crate::{ + backend::Backend, OverlayedChanges, StorageTransactionCache, + changes_trie::Storage as ChangesTrieStorage, +}; + +use hash_db::Hasher; +use sp_core::{ + storage::{ChildStorageKey, well_known_keys::is_child_storage_key, ChildInfo}, + traits::Externalities, hexdisplay::HexDisplay, +}; +use sp_trie::{trie_types::Layout, default_child_trie_root}; +use sp_externalities::Extensions; +use codec::{Decode, Encode}; + +use std::{error, fmt, any::{Any, TypeId}}; +use log::{warn, trace}; + +const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime"; + +/// Errors that can occur when interacting with the externalities. +#[derive(Debug, Copy, Clone)] +pub enum Error { + /// Failure to load state data from the backend. + #[allow(unused)] + Backend(B), + /// Failure to execute a function. + #[allow(unused)] + Executor(E), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Error::Backend(ref e) => write!(f, "Storage backend error: {}", e), + Error::Executor(ref e) => write!(f, "Sub-call execution error: {}", e), + } + } +} + +impl error::Error for Error { + fn description(&self) -> &str { + match *self { + Error::Backend(..) => "backend error", + Error::Executor(..) => "executor error", + } + } +} + +/// Wraps a read-only backend, call executor, and current overlayed changes. +pub struct Ext<'a, H, N, B, T> + where + H: Hasher, + B: 'a + Backend, + N: crate::changes_trie::BlockNumber, +{ + /// The overlayed changes to write to. + overlay: &'a mut OverlayedChanges, + /// The storage backend to read from. + backend: &'a B, + /// The cache for the storage transactions. + storage_transaction_cache: &'a mut StorageTransactionCache, + /// Changes trie storage to read from. + changes_trie_storage: Option<&'a T>, + /// Pseudo-unique id used for tracing. + pub id: u16, + /// Dummy usage of N arg. + _phantom: std::marker::PhantomData, + /// Extensions registered with this instance. + extensions: Option<&'a mut Extensions>, +} + +impl<'a, H, N, B, T> Ext<'a, H, N, B, T> +where + H: Hasher, + H::Out: Ord + 'static + codec::Codec, + B: 'a + Backend, + T: 'a + ChangesTrieStorage, + N: crate::changes_trie::BlockNumber, +{ + + /// Create a new `Ext` from overlayed changes and read-only backend + pub fn new( + overlay: &'a mut OverlayedChanges, + storage_transaction_cache: &'a mut StorageTransactionCache, + backend: &'a B, + changes_trie_storage: Option<&'a T>, + extensions: Option<&'a mut Extensions>, + ) -> Self { + Ext { + overlay, + backend, + changes_trie_storage, + storage_transaction_cache, + id: rand::random(), + _phantom: Default::default(), + extensions, + } + } + + /// Invalidates the currently cached storage root and the db transaction. + /// + /// Called when there are changes that likely will invalidate the storage root. + fn mark_dirty(&mut self) { + self.storage_transaction_cache.reset(); + } +} + +#[cfg(test)] +impl<'a, H, N, B, T> Ext<'a, H, N, B, T> +where + H: Hasher, + H::Out: Ord + 'static, + B: 'a + Backend, + T: 'a + ChangesTrieStorage, + N: crate::changes_trie::BlockNumber, +{ + pub fn storage_pairs(&self) -> Vec<(Vec, Vec)> { + use std::collections::HashMap; + + self.backend.pairs().iter() + .map(|&(ref k, ref v)| (k.to_vec(), Some(v.to_vec()))) + .chain(self.overlay.committed.top.clone().into_iter().map(|(k, v)| (k, v.value))) + .chain(self.overlay.prospective.top.clone().into_iter().map(|(k, v)| (k, v.value))) + .collect::>() + .into_iter() + .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) + .collect() + } +} + +impl<'a, H, B, T, N> Externalities for Ext<'a, H, N, B, T> +where + H: Hasher, + H::Out: Ord + 'static + codec::Codec, + B: 'a + Backend, + T: 'a + ChangesTrieStorage, + N: crate::changes_trie::BlockNumber, +{ + fn storage(&self, key: &[u8]) -> Option> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| + self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL)); + trace!(target: "state-trace", "{:04x}: Get {}={:?}", + self.id, + HexDisplay::from(&key), + result.as_ref().map(HexDisplay::from) + ); + result + } + + fn storage_hash(&self, key: &[u8]) -> Option> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = self.overlay + .storage(key) + .map(|x| x.map(|x| H::hash(x))) + .unwrap_or_else(|| self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL)); + + trace!(target: "state-trace", "{:04x}: Hash {}={:?}", + self.id, + HexDisplay::from(&key), + result, + ); + result.map(|r| r.encode()) + } + + fn original_storage(&self, key: &[u8]) -> Option> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL); + + trace!(target: "state-trace", "{:04x}: GetOriginal {}={:?}", + self.id, + HexDisplay::from(&key), + result.as_ref().map(HexDisplay::from) + ); + result + } + + fn original_storage_hash(&self, key: &[u8]) -> Option> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL); + + trace!(target: "state-trace", "{:04x}: GetOriginalHash {}={:?}", + self.id, + HexDisplay::from(&key), + result, + ); + result.map(|r| r.encode()) + } + + fn child_storage( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = self.overlay + .child_storage(storage_key.as_ref(), key) + .map(|x| x.map(|x| x.to_vec())) + .unwrap_or_else(|| + self.backend.child_storage(storage_key.as_ref(), child_info, key) + .expect(EXT_NOT_ALLOWED_TO_FAIL) + ); + + trace!(target: "state-trace", "{:04x}: GetChild({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result.as_ref().map(HexDisplay::from) + ); + + result + } + + fn child_storage_hash( + &self, + storage_key: ChildStorageKey, + _child_info: ChildInfo, + key: &[u8], + ) -> Option> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = self.overlay + .child_storage(storage_key.as_ref(), key) + .map(|x| x.map(|x| H::hash(x))) + .unwrap_or_else(|| + self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL) + ); + + trace!(target: "state-trace", "{:04x}: ChildHash({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result, + ); + + result.map(|r| r.encode()) + } + + fn original_child_storage( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = self.backend + .child_storage(storage_key.as_ref(), child_info, key) + .expect(EXT_NOT_ALLOWED_TO_FAIL); + + trace!(target: "state-trace", "{:04x}: ChildOriginal({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result.as_ref().map(HexDisplay::from), + ); + + result + } + + fn original_child_storage_hash( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = self.backend + .child_storage_hash(storage_key.as_ref(), child_info, key) + .expect(EXT_NOT_ALLOWED_TO_FAIL); + + trace!(target: "state-trace", "{}: ChildHashOriginal({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result, + ); + result.map(|r| r.encode()) + } + + fn exists_storage(&self, key: &[u8]) -> bool { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let result = match self.overlay.storage(key) { + Some(x) => x.is_some(), + _ => self.backend.exists_storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL), + }; + + trace!(target: "state-trace", "{:04x}: Exists {}={:?}", + self.id, + HexDisplay::from(&key), + result, + ); + + result + } + + fn exists_child_storage( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> bool { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + + let result = match self.overlay.child_storage(storage_key.as_ref(), key) { + Some(x) => x.is_some(), + _ => self.backend + .exists_child_storage(storage_key.as_ref(), child_info, key) + .expect(EXT_NOT_ALLOWED_TO_FAIL), + }; + + trace!(target: "state-trace", "{:04x}: ChildExists({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result, + ); + result + } + + fn next_storage_key(&self, key: &[u8]) -> Option> { + let next_backend_key = self.backend.next_storage_key(key).expect(EXT_NOT_ALLOWED_TO_FAIL); + let next_overlay_key_change = self.overlay.next_storage_key_change(key); + + match (next_backend_key, next_overlay_key_change) { + (Some(backend_key), Some(overlay_key)) if &backend_key[..] < overlay_key.0 => Some(backend_key), + (backend_key, None) => backend_key, + (_, Some(overlay_key)) => if overlay_key.1.value.is_some() { + Some(overlay_key.0.to_vec()) + } else { + self.next_storage_key(&overlay_key.0[..]) + }, + } + } + + fn next_child_storage_key( + &self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: &[u8], + ) -> Option> { + let next_backend_key = self.backend + .next_child_storage_key(storage_key.as_ref(), child_info, key) + .expect(EXT_NOT_ALLOWED_TO_FAIL); + let next_overlay_key_change = self.overlay.next_child_storage_key_change( + storage_key.as_ref(), + key + ); + + match (next_backend_key, next_overlay_key_change) { + (Some(backend_key), Some(overlay_key)) if &backend_key[..] < overlay_key.0 => Some(backend_key), + (backend_key, None) => backend_key, + (_, Some(overlay_key)) => if overlay_key.1.value.is_some() { + Some(overlay_key.0.to_vec()) + } else { + self.next_child_storage_key( + storage_key, + child_info, + &overlay_key.0[..], + ) + }, + } + } + + fn place_storage(&mut self, key: Vec, value: Option>) { + trace!(target: "state-trace", "{:04x}: Put {}={:?}", + self.id, + HexDisplay::from(&key), + value.as_ref().map(HexDisplay::from) + ); + let _guard = sp_panic_handler::AbortGuard::force_abort(); + if is_child_storage_key(&key) { + warn!(target: "trie", "Refuse to directly set child storage key"); + return; + } + + self.mark_dirty(); + self.overlay.set_storage(key, value); + } + + fn place_child_storage( + &mut self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + key: Vec, + value: Option>, + ) { + trace!(target: "state-trace", "{:04x}: PutChild({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + value.as_ref().map(HexDisplay::from) + ); + let _guard = sp_panic_handler::AbortGuard::force_abort(); + + self.mark_dirty(); + self.overlay.set_child_storage(storage_key.into_owned(), child_info, key, value); + } + + fn kill_child_storage( + &mut self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + ) { + trace!(target: "state-trace", "{:04x}: KillChild({})", + self.id, + HexDisplay::from(&storage_key.as_ref()), + ); + let _guard = sp_panic_handler::AbortGuard::force_abort(); + + self.mark_dirty(); + self.overlay.clear_child_storage(storage_key.as_ref(), child_info); + self.backend.for_keys_in_child_storage(storage_key.as_ref(), child_info, |key| { + self.overlay.set_child_storage(storage_key.as_ref().to_vec(), child_info, key.to_vec(), None); + }); + } + + fn clear_prefix(&mut self, prefix: &[u8]) { + trace!(target: "state-trace", "{:04x}: ClearPrefix {}", + self.id, + HexDisplay::from(&prefix), + ); + let _guard = sp_panic_handler::AbortGuard::force_abort(); + if is_child_storage_key(prefix) { + warn!(target: "trie", "Refuse to directly clear prefix that is part of child storage key"); + return; + } + + self.mark_dirty(); + self.overlay.clear_prefix(prefix); + self.backend.for_keys_with_prefix(prefix, |key| { + self.overlay.set_storage(key.to_vec(), None); + }); + } + + fn clear_child_prefix( + &mut self, + storage_key: ChildStorageKey, + child_info: ChildInfo, + prefix: &[u8], + ) { + trace!(target: "state-trace", "{:04x}: ClearChildPrefix({}) {}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&prefix), + ); + let _guard = sp_panic_handler::AbortGuard::force_abort(); + + self.mark_dirty(); + self.overlay.clear_child_prefix(storage_key.as_ref(), child_info, prefix); + self.backend.for_child_keys_with_prefix(storage_key.as_ref(), child_info, prefix, |key| { + self.overlay.set_child_storage(storage_key.as_ref().to_vec(), child_info, key.to_vec(), None); + }); + } + + fn chain_id(&self) -> u64 { + 42 + } + + fn storage_root(&mut self) -> Vec { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + if let Some(ref root) = self.storage_transaction_cache.transaction_storage_root { + trace!(target: "state-trace", "{:04x}: Root (cached) {}", + self.id, + HexDisplay::from(&root.as_ref()), + ); + return root.encode(); + } + + let root = self.overlay.storage_root(self.backend, self.storage_transaction_cache); + trace!(target: "state-trace", "{:04x}: Root {}", self.id, HexDisplay::from(&root.as_ref())); + root.encode() + } + + fn child_storage_root( + &mut self, + storage_key: ChildStorageKey, + ) -> Vec { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + if self.storage_transaction_cache.transaction_storage_root.is_some() { + let root = self + .storage(storage_key.as_ref()) + .and_then(|k| Decode::decode(&mut &k[..]).ok()) + .unwrap_or( + default_child_trie_root::>(storage_key.as_ref()) + ); + trace!(target: "state-trace", "{:04x}: ChildRoot({}) (cached) {}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&root.as_ref()), + ); + root.encode() + } else { + let storage_key = storage_key.as_ref(); + + if let Some(child_info) = self.overlay.child_info(storage_key).cloned() { + let (root, is_empty, _) = { + let delta = self.overlay.committed.children.get(storage_key) + .into_iter() + .flat_map(|(map, _)| map.clone().into_iter().map(|(k, v)| (k, v.value))) + .chain( + self.overlay.prospective.children.get(storage_key) + .into_iter() + .flat_map(|(map, _)| map.clone().into_iter().map(|(k, v)| (k, v.value))) + ); + + self.backend.child_storage_root(storage_key, child_info.as_ref(), delta) + }; + + let root = root.encode(); + // We store update in the overlay in order to be able to use 'self.storage_transaction' + // cache. This is brittle as it rely on Ext only querying the trie backend for + // storage root. + // A better design would be to manage 'child_storage_transaction' in a + // similar way as 'storage_transaction' but for each child trie. + if is_empty { + self.overlay.set_storage(storage_key.into(), None); + } else { + self.overlay.set_storage(storage_key.into(), Some(root.clone())); + } + + trace!(target: "state-trace", "{:04x}: ChildRoot({}) {}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&root.as_ref()), + ); + root + } else { + // empty overlay + let root = self + .storage(storage_key.as_ref()) + .and_then(|k| Decode::decode(&mut &k[..]).ok()) + .unwrap_or( + default_child_trie_root::>(storage_key.as_ref()) + ); + trace!(target: "state-trace", "{:04x}: ChildRoot({}) (no change) {}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&root.as_ref()), + ); + root.encode() + } + } + } + + fn storage_changes_root(&mut self, parent_hash: &[u8]) -> Result>, ()> { + let _guard = sp_panic_handler::AbortGuard::force_abort(); + let root = self.overlay.changes_trie_root( + self.backend, + self.changes_trie_storage.clone(), + Decode::decode(&mut &parent_hash[..]).map_err(|e| + trace!( + target: "state-trace", + "Failed to decode changes root parent hash: {}", + e, + ) + )?, + true, + self.storage_transaction_cache, + ); + + trace!(target: "state-trace", "{:04x}: ChangesRoot({}) {:?}", + self.id, + HexDisplay::from(&parent_hash), + root, + ); + + root.map(|r| r.map(|o| o.encode())) + } +} + +impl<'a, H, B, T, N> sp_externalities::ExtensionStore for Ext<'a, H, N, B, T> +where + H: Hasher, + B: 'a + Backend, + T: 'a + ChangesTrieStorage, + N: crate::changes_trie::BlockNumber, +{ + fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> { + self.extensions.as_mut().and_then(|exts| exts.get_mut(type_id)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + use codec::Encode; + use sp_core::{H256, Blake2Hasher, storage::well_known_keys::EXTRINSIC_INDEX, map}; + use crate::{ + changes_trie::{ + Configuration as ChangesTrieConfiguration, + InMemoryStorage as InMemoryChangesTrieStorage, + }, InMemoryBackend, overlayed_changes::OverlayedValue, + }; + use sp_core::storage::{Storage, StorageChild}; + + type TestBackend = InMemoryBackend; + type TestChangesTrieStorage = InMemoryChangesTrieStorage; + type TestExt<'a> = Ext<'a, Blake2Hasher, u64, TestBackend, TestChangesTrieStorage>; + + fn prepare_overlay_with_changes() -> OverlayedChanges { + OverlayedChanges { + prospective: vec![ + (EXTRINSIC_INDEX.to_vec(), OverlayedValue { + value: Some(3u32.encode()), + extrinsics: Some(vec![1].into_iter().collect()) + }), + (vec![1], OverlayedValue { + value: Some(vec![100].into_iter().collect()), + extrinsics: Some(vec![1].into_iter().collect()) + }), + ].into_iter().collect(), + committed: Default::default(), + changes_trie_config: Some(ChangesTrieConfiguration { + digest_interval: 0, + digest_levels: 0, + }), + } + } + + #[test] + fn storage_changes_root_is_none_when_storage_is_not_provided() { + let mut overlay = prepare_overlay_with_changes(); + let mut cache = StorageTransactionCache::default(); + let backend = TestBackend::default(); + let mut ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + assert_eq!(ext.storage_changes_root(&H256::default().encode()).unwrap(), None); + } + + #[test] + fn storage_changes_root_is_none_when_extrinsic_changes_are_none() { + let mut overlay = prepare_overlay_with_changes(); + let mut cache = StorageTransactionCache::default(); + overlay.changes_trie_config = None; + let storage = TestChangesTrieStorage::with_blocks(vec![(100, Default::default())]); + let backend = TestBackend::default(); + let mut ext = TestExt::new(&mut overlay, &mut cache, &backend, Some(&storage), None); + assert_eq!(ext.storage_changes_root(&H256::default().encode()).unwrap(), None); + } + + #[test] + fn storage_changes_root_is_some_when_extrinsic_changes_are_non_empty() { + let mut overlay = prepare_overlay_with_changes(); + let mut cache = StorageTransactionCache::default(); + let storage = TestChangesTrieStorage::with_blocks(vec![(99, Default::default())]); + let backend = TestBackend::default(); + let mut ext = TestExt::new(&mut overlay, &mut cache, &backend, Some(&storage), None); + assert_eq!( + ext.storage_changes_root(&H256::default().encode()).unwrap(), + Some(hex!("bb0c2ef6e1d36d5490f9766cfcc7dfe2a6ca804504c3bb206053890d6dd02376").to_vec()), + ); + } + + #[test] + fn storage_changes_root_is_some_when_extrinsic_changes_are_empty() { + let mut overlay = prepare_overlay_with_changes(); + let mut cache = StorageTransactionCache::default(); + overlay.prospective.top.get_mut(&vec![1]).unwrap().value = None; + let storage = TestChangesTrieStorage::with_blocks(vec![(99, Default::default())]); + let backend = TestBackend::default(); + let mut ext = TestExt::new(&mut overlay, &mut cache, &backend, Some(&storage), None); + assert_eq!( + ext.storage_changes_root(&H256::default().encode()).unwrap(), + Some(hex!("96f5aae4690e7302737b6f9b7f8567d5bbb9eac1c315f80101235a92d9ec27f4").to_vec()), + ); + } + + #[test] + fn next_storage_key_works() { + let mut cache = StorageTransactionCache::default(); + let mut overlay = OverlayedChanges::default(); + overlay.set_storage(vec![20], None); + overlay.set_storage(vec![30], Some(vec![31])); + let backend = Storage { + top: map![ + vec![10] => vec![10], + vec![20] => vec![20], + vec![40] => vec![40] + ], + children: map![] + }.into(); + + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + + // next_backend < next_overlay + assert_eq!(ext.next_storage_key(&[5]), Some(vec![10])); + + // next_backend == next_overlay but next_overlay is a delete + assert_eq!(ext.next_storage_key(&[10]), Some(vec![30])); + + // next_overlay < next_backend + assert_eq!(ext.next_storage_key(&[20]), Some(vec![30])); + + // next_backend exist but next_overlay doesn't exist + assert_eq!(ext.next_storage_key(&[30]), Some(vec![40])); + + drop(ext); + overlay.set_storage(vec![50], Some(vec![50])); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + + // next_overlay exist but next_backend doesn't exist + assert_eq!(ext.next_storage_key(&[40]), Some(vec![50])); + } + + #[test] + fn next_child_storage_key_works() { + const CHILD_KEY_1: &[u8] = b":child_storage:default:Child1"; + + const CHILD_UUID_1: &[u8] = b"unique_id_1"; + const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(CHILD_UUID_1); + + let mut cache = StorageTransactionCache::default(); + let child = || ChildStorageKey::from_slice(CHILD_KEY_1).unwrap(); + let mut overlay = OverlayedChanges::default(); + overlay.set_child_storage(child().as_ref().to_vec(), CHILD_INFO_1, vec![20], None); + overlay.set_child_storage(child().as_ref().to_vec(), CHILD_INFO_1, vec![30], Some(vec![31])); + let backend = Storage { + top: map![], + children: map![ + child().as_ref().to_vec() => StorageChild { + data: map![ + vec![10] => vec![10], + vec![20] => vec![20], + vec![40] => vec![40] + ], + child_info: CHILD_INFO_1.to_owned(), + } + ], + }.into(); + + + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + + // next_backend < next_overlay + assert_eq!(ext.next_child_storage_key(child(), CHILD_INFO_1, &[5]), Some(vec![10])); + + // next_backend == next_overlay but next_overlay is a delete + assert_eq!(ext.next_child_storage_key(child(), CHILD_INFO_1, &[10]), Some(vec![30])); + + // next_overlay < next_backend + assert_eq!(ext.next_child_storage_key(child(), CHILD_INFO_1, &[20]), Some(vec![30])); + + // next_backend exist but next_overlay doesn't exist + assert_eq!(ext.next_child_storage_key(child(), CHILD_INFO_1, &[30]), Some(vec![40])); + + drop(ext); + overlay.set_child_storage(child().as_ref().to_vec(), CHILD_INFO_1, vec![50], Some(vec![50])); + let ext = TestExt::new(&mut overlay, &mut cache, &backend, None, None); + + // next_overlay exist but next_backend doesn't exist + assert_eq!(ext.next_child_storage_key(child(), CHILD_INFO_1, &[40]), Some(vec![50])); + } +} diff --git a/primitives/state-machine/src/in_memory_backend.rs b/primitives/state-machine/src/in_memory_backend.rs new file mode 100644 index 0000000000000..ae1a214a72c92 --- /dev/null +++ b/primitives/state-machine/src/in_memory_backend.rs @@ -0,0 +1,378 @@ +// 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 . + +//! State machine in memory backend. + +use crate::{trie_backend::TrieBackend, backend::{Backend, insert_into_memory_db}}; +use std::{error, fmt, collections::{BTreeMap, HashMap}, marker::PhantomData, ops}; +use hash_db::Hasher; +use sp_trie::{ + MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration, trie_types::Layout, +}; +use codec::Codec; +use sp_core::storage::{ChildInfo, OwnedChildInfo, Storage}; + +/// Error impossible. +// FIXME: use `!` type when stabilized. https://github.com/rust-lang/rust/issues/35121 +#[derive(Debug)] +pub enum Void {} + +impl fmt::Display for Void { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + match *self {} + } +} + +impl error::Error for Void { + fn description(&self) -> &str { "unreachable error" } +} + +/// In-memory backend. Fully recomputes tries each time `as_trie_backend` is called but useful for +/// tests and proof checking. +pub struct InMemory { + inner: HashMap, OwnedChildInfo)>, BTreeMap, Vec>>, + // This field is only needed for returning reference in `as_trie_backend`. + trie: Option, H>>, + _hasher: PhantomData, +} + +impl std::fmt::Debug for InMemory { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "InMemory ({} values)", self.inner.len()) + } +} + +impl Default for InMemory { + fn default() -> Self { + InMemory { + inner: Default::default(), + trie: None, + _hasher: PhantomData, + } + } +} + +impl Clone for InMemory { + fn clone(&self) -> Self { + InMemory { + inner: self.inner.clone(), + trie: None, + _hasher: PhantomData, + } + } +} + +impl PartialEq for InMemory { + fn eq(&self, other: &Self) -> bool { + self.inner.eq(&other.inner) + } +} + +impl InMemory { + /// Copy the state, with applied updates + pub fn update< + T: IntoIterator, OwnedChildInfo)>, Vec<(Vec, Option>)>)> + >( + &self, + changes: T, + ) -> Self { + let mut inner = self.inner.clone(); + for (child_info, key_values) in changes.into_iter() { + let entry = inner.entry(child_info).or_default(); + for (key, val) in key_values { + match val { + Some(v) => { entry.insert(key, v); }, + None => { entry.remove(&key); }, + } + } + } + inner.into() + } +} + +impl From, OwnedChildInfo)>, BTreeMap, Vec>>> + for InMemory +{ + fn from(inner: HashMap, OwnedChildInfo)>, BTreeMap, Vec>>) -> Self { + InMemory { + inner, + trie: None, + _hasher: PhantomData, + } + } +} + +impl From for InMemory { + fn from(inners: Storage) -> Self { + let mut inner: HashMap, OwnedChildInfo)>, BTreeMap, Vec>> + = inners.children.into_iter().map(|(k, c)| (Some((k, c.child_info)), c.data)).collect(); + inner.insert(None, inners.top); + InMemory { + inner, + trie: None, + _hasher: PhantomData, + } + } +} + +impl From, Vec>> for InMemory { + fn from(inner: BTreeMap, Vec>) -> Self { + let mut expanded = HashMap::new(); + expanded.insert(None, inner); + InMemory { + inner: expanded, + trie: None, + _hasher: PhantomData, + } + } +} + +impl From, OwnedChildInfo)>, Vec<(Vec, Option>)>)>> + for InMemory { + fn from( + inner: Vec<(Option<(Vec, OwnedChildInfo)>, Vec<(Vec, Option>)>)>, + ) -> Self { + let mut expanded: HashMap, OwnedChildInfo)>, BTreeMap, Vec>> + = HashMap::new(); + for (child_info, key_values) in inner { + let entry = expanded.entry(child_info).or_default(); + for (key, value) in key_values { + if let Some(value) = value { + entry.insert(key, value); + } + } + } + expanded.into() + } +} + +impl InMemory { + /// child storage key iterator + pub fn child_storage_keys(&self) -> impl Iterator { + self.inner.iter().filter_map(|item| + item.0.as_ref().map(|v|(&v.0[..], v.1.as_ref())) + ) + } +} + +impl Backend for InMemory where H::Out: Codec { + type Error = Void; + type Transaction = Vec<( + Option<(Vec, OwnedChildInfo)>, + Vec<(Vec, Option>)>, + )>; + type TrieBackendStorage = MemoryDB; + + fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + Ok(self.inner.get(&None).and_then(|map| map.get(key).map(Clone::clone))) + } + + fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + Ok(self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) + .and_then(|map| map.get(key).map(Clone::clone))) + } + + fn exists_storage(&self, key: &[u8]) -> Result { + Ok(self.inner.get(&None).map(|map| map.get(key).is_some()).unwrap_or(false)) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + self.inner.get(&None) + .map(|map| map.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f)); + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], mut f: F) { + self.inner.get(&None).map(|map| map.iter().filter(|(key, _val)| key.starts_with(prefix)) + .for_each(|(k, v)| f(k, v))); + } + + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + mut f: F, + ) { + self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) + .map(|map| map.keys().for_each(|k| f(&k))); + } + + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + f: F, + ) { + self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) + .map(|map| map.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f)); + } + + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where + I: IntoIterator, Option>)>, + ::Out: Ord, + { + let existing_pairs = self.inner.get(&None) + .into_iter() + .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), Some(v.clone())))); + + let transaction: Vec<_> = delta.into_iter().collect(); + let root = Layout::::trie_root(existing_pairs.chain(transaction.iter().cloned()) + .collect::>() + .into_iter() + .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) + ); + + let full_transaction = transaction.into_iter().collect(); + + (root, vec![(None, full_transaction)]) + } + + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (H::Out, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord + { + let storage_key = storage_key.to_vec(); + let child_info = Some((storage_key.clone(), child_info.to_owned())); + + let existing_pairs = self.inner.get(&child_info) + .into_iter() + .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), Some(v.clone())))); + + let transaction: Vec<_> = delta.into_iter().collect(); + let root = child_trie_root::, _, _, _>( + &storage_key, + existing_pairs.chain(transaction.iter().cloned()) + .collect::>() + .into_iter() + .filter_map(|(k, maybe_val)| maybe_val.map(|val| (k, val))) + ); + + let full_transaction = transaction.into_iter().collect(); + + let is_default = root == default_child_trie_root::>(&storage_key); + + (root, is_default, vec![(child_info, full_transaction)]) + } + + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + let range = (ops::Bound::Excluded(key), ops::Bound::Unbounded); + let next_key = self.inner.get(&None) + .and_then(|map| map.range::<[u8], _>(range).next().map(|(k, _)| k).cloned()); + + Ok(next_key) + } + + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + let range = (ops::Bound::Excluded(key), ops::Bound::Unbounded); + let next_key = self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) + .and_then(|map| map.range::<[u8], _>(range).next().map(|(k, _)| k).cloned()); + + Ok(next_key) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + self.inner.get(&None) + .into_iter() + .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.clone()))) + .collect() + } + + fn keys(&self, prefix: &[u8]) -> Vec> { + self.inner.get(&None) + .into_iter() + .flat_map(|map| map.keys().filter(|k| k.starts_with(prefix)).cloned()) + .collect() + } + + fn child_keys( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + ) -> Vec> { + self.inner.get(&Some((storage_key.to_vec(), child_info.to_owned()))) + .into_iter() + .flat_map(|map| map.keys().filter(|k| k.starts_with(prefix)).cloned()) + .collect() + } + + fn as_trie_backend(&mut self)-> Option<&TrieBackend> { + let mut mdb = MemoryDB::default(); + let mut new_child_roots = Vec::new(); + let mut root_map = None; + for (child_info, map) in &self.inner { + if let Some((storage_key, _child_info)) = child_info.as_ref() { + // no need to use child_info at this point because we use a MemoryDB for + // proof (with PrefixedMemoryDB it would be needed). + let ch = insert_into_memory_db::(&mut mdb, map.clone().into_iter())?; + new_child_roots.push((storage_key.clone(), ch.as_ref().into())); + } else { + root_map = Some(map); + } + } + let root = match root_map { + Some(map) => insert_into_memory_db::( + &mut mdb, + map.clone().into_iter().chain(new_child_roots.into_iter()), + )?, + None => insert_into_memory_db::( + &mut mdb, + new_child_roots.into_iter(), + )?, + }; + self.trie = Some(TrieBackend::new(mdb, root)); + self.trie.as_ref() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Assert in memory backend with only child trie keys works as trie backend. + #[test] + fn in_memory_with_child_trie_only() { + let storage = InMemory::::default(); + let child_info = OwnedChildInfo::new_default(b"unique_id_1".to_vec()); + let mut storage = storage.update( + vec![( + Some((b"1".to_vec(), child_info.clone())), + vec![(b"2".to_vec(), Some(b"3".to_vec()))] + )] + ); + let trie_backend = storage.as_trie_backend().unwrap(); + assert_eq!(trie_backend.child_storage(b"1", child_info.as_ref(), b"2").unwrap(), + Some(b"3".to_vec())); + assert!(trie_backend.storage(b"1").unwrap().is_some()); + } +} diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs new file mode 100644 index 0000000000000..c8329178c6c4d --- /dev/null +++ b/primitives/state-machine/src/lib.rs @@ -0,0 +1,1151 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate state machine implementation. + +#![warn(missing_docs)] + +use std::{fmt, result, collections::HashMap, panic::UnwindSafe, marker::PhantomData}; +use log::{warn, trace}; +use hash_db::Hasher; +use codec::{Decode, Encode, Codec}; +use sp_core::{ + storage::{well_known_keys, ChildInfo}, NativeOrEncoded, NeverNativeValue, + traits::CodeExecutor, hexdisplay::HexDisplay +}; +use overlayed_changes::OverlayedChangeSet; +use sp_externalities::Extensions; + +pub mod backend; +mod in_memory_backend; +mod changes_trie; +mod error; +mod ext; +mod testing; +mod basic; +mod overlayed_changes; +mod proving_backend; +mod trie_backend; +mod trie_backend_essence; +mod stats; + +pub use sp_trie::{trie_types::{Layout, TrieDBMut}, TrieMut, DBValue, MemoryDB}; +pub use testing::TestExternalities; +pub use basic::BasicExternalities; +pub use ext::Ext; +pub use backend::Backend; +pub use changes_trie::{ + AnchorBlockId as ChangesTrieAnchorBlockId, + Storage as ChangesTrieStorage, + RootsStorage as ChangesTrieRootsStorage, + InMemoryStorage as InMemoryChangesTrieStorage, + BuildCache as ChangesTrieBuildCache, + CacheAction as ChangesTrieCacheAction, + ConfigurationRange as ChangesTrieConfigurationRange, + key_changes, key_changes_proof, key_changes_proof_check, + prune as prune_changes_tries, + oldest_non_pruned_trie as oldest_non_pruned_changes_trie, + BlockNumber as ChangesTrieBlockNumber, +}; +pub use overlayed_changes::{OverlayedChanges, StorageChanges, StorageTransactionCache}; +pub use proving_backend::{ + create_proof_check_backend, create_proof_check_backend_storage, merge_storage_proofs, + ProofRecorder, ProvingBackend, ProvingBackendRecorder, StorageProof, +}; +pub use trie_backend_essence::{TrieBackendStorage, Storage}; +pub use trie_backend::TrieBackend; +pub use error::{Error, ExecutionError}; +pub use in_memory_backend::InMemory as InMemoryBackend; +pub use stats::{UsageInfo, UsageUnit}; + +type CallResult = Result, E>; + +/// Default handler of the execution manager. +pub type DefaultHandler = fn(CallResult, CallResult) -> CallResult; + +/// Type of changes trie transaction. +pub type ChangesTrieTransaction = ( + MemoryDB, + ChangesTrieCacheAction<::Out, N>, +); + +/// Strategy for executing a call into the runtime. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum ExecutionStrategy { + /// Execute with the native equivalent if it is compatible with the given wasm module; otherwise fall back to the wasm. + NativeWhenPossible, + /// Use the given wasm module. + AlwaysWasm, + /// Run with both the wasm and the native variant (if compatible). Report any discrepancy as an error. + Both, + /// First native, then if that fails or is not possible, wasm. + NativeElseWasm, +} + +/// Storage backend trust level. +#[derive(Debug, Clone)] +pub enum BackendTrustLevel { + /// Panics from trusted backends are considered justified, and never caught. + Trusted, + /// Panics from untrusted backend are caught and interpreted as runtime error. + /// Untrusted backend may be missing some parts of the trie, so panics are not considered + /// fatal. + Untrusted, +} + +/// Like `ExecutionStrategy` only it also stores a handler in case of consensus failure. +#[derive(Clone)] +pub enum ExecutionManager { + /// Execute with the native equivalent if it is compatible with the given wasm module; otherwise fall back to the wasm. + NativeWhenPossible, + /// Use the given wasm module. The backend on which code is executed code could be + /// trusted to provide all storage or not (i.e. the light client cannot be trusted to provide + /// for all storage queries since the storage entries it has come from an external node). + AlwaysWasm(BackendTrustLevel), + /// Run with both the wasm and the native variant (if compatible). Call `F` in the case of any discrepancy. + Both(F), + /// First native, then if that fails or is not possible, wasm. + NativeElseWasm, +} + +impl<'a, F> From<&'a ExecutionManager> for ExecutionStrategy { + fn from(s: &'a ExecutionManager) -> Self { + match *s { + ExecutionManager::NativeWhenPossible => ExecutionStrategy::NativeWhenPossible, + ExecutionManager::AlwaysWasm(_) => ExecutionStrategy::AlwaysWasm, + ExecutionManager::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(BackendTrustLevel::Trusted), + 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, + ); + warn!(" Native result {:?}", native_result); + warn!(" Wasm result {:?}", wasm_result); + wasm_result + }), + } + } +} + +/// Evaluate to ExecutionManager::NativeElseWasm, without having to figure out the type. +pub fn native_else_wasm() -> ExecutionManager> { + ExecutionManager::NativeElseWasm +} + +/// Evaluate to ExecutionManager::AlwaysWasm with trusted backend, without having to figure out the type. +fn always_wasm() -> ExecutionManager> { + ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted) +} + +/// Evaluate ExecutionManager::AlwaysWasm with untrusted backend, without having to figure out the type. +fn always_untrusted_wasm() -> ExecutionManager> { + ExecutionManager::AlwaysWasm(BackendTrustLevel::Untrusted) +} + +/// The substrate state machine. +pub struct StateMachine<'a, B, H, N, T, Exec> + where + H: Hasher, + B: Backend, + N: ChangesTrieBlockNumber, +{ + backend: &'a B, + exec: &'a Exec, + method: &'a str, + call_data: &'a [u8], + overlay: &'a mut OverlayedChanges, + extensions: Extensions, + changes_trie_storage: Option<&'a T>, + _marker: PhantomData<(H, N)>, + storage_transaction_cache: Option<&'a mut StorageTransactionCache>, +} + +impl<'a, B, H, N, T, Exec> StateMachine<'a, B, H, N, T, Exec> where + H: Hasher, + H::Out: Ord + 'static + codec::Codec, + Exec: CodeExecutor, + B: Backend, + T: ChangesTrieStorage, + N: crate::changes_trie::BlockNumber, +{ + /// Creates new substrate state machine. + pub fn new( + backend: &'a B, + changes_trie_storage: Option<&'a T>, + overlay: &'a mut OverlayedChanges, + exec: &'a Exec, + method: &'a str, + call_data: &'a [u8], + extensions: Extensions, + ) -> Self { + Self { + backend, + exec, + method, + call_data, + extensions, + overlay, + changes_trie_storage, + _marker: PhantomData, + storage_transaction_cache: None, + } + } + + /// Use given `cache` as storage transaction cache. + /// + /// The cache will be used to cache storage transactions that can be build while executing a + /// function in the runtime. For example, when calculating the storage root a transaction is + /// build that will be cached. + pub fn with_storage_transaction_cache( + mut self, + cache: Option<&'a mut StorageTransactionCache>, + ) -> Self { + self.storage_transaction_cache = cache; + self + } + + /// Execute a call using the given state backend, overlayed changes, and call executor. + /// + /// 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. + /// + /// Returns the SCALE encoded result of the executed function. + pub fn execute(&mut self, strategy: ExecutionStrategy) -> Result, 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(), + None, + ).map(NativeOrEncoded::into_encoded) + } + + fn execute_aux( + &mut self, + use_native: bool, + native_call: Option, + ) -> ( + CallResult, + bool, + ) where + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + { + let mut cache = StorageTransactionCache::default(); + + let cache = match self.storage_transaction_cache.as_mut() { + Some(cache) => cache, + None => &mut cache, + }; + + let mut ext = Ext::new( + self.overlay, + cache, + self.backend, + self.changes_trie_storage.clone(), + Some(&mut self.extensions), + ); + + let id = ext.id; + trace!( + target: "state-trace", "{:04x}: Call {} at {:?}. Input={:?}", + id, + self.method, + self.backend, + HexDisplay::from(&self.call_data), + ); + + let (result, was_native) = self.exec.call( + &mut ext, + self.method, + self.call_data, + use_native, + native_call, + ); + + trace!( + target: "state-trace", "{:04x}: Return. Native={:?}, Result={:?}", + id, + was_native, + result, + ); + + (result, was_native) + } + + fn execute_call_with_both_strategy( + &mut self, + mut native_call: Option, + orig_prospective: OverlayedChangeSet, + on_consensus_failure: Handler, + ) -> CallResult + where + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + Handler: FnOnce( + CallResult, + CallResult, + ) -> CallResult + { + let (result, was_native) = self.execute_aux(true, native_call.take()); + + if was_native { + self.overlay.prospective = orig_prospective.clone(); + let (wasm_result, _) = self.execute_aux( + 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 + } else { + on_consensus_failure(wasm_result, result) + } + } else { + result + } + } + + fn execute_call_with_native_else_wasm_strategy( + &mut self, + mut native_call: Option, + orig_prospective: OverlayedChangeSet, + ) -> CallResult + where + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + { + let (result, was_native) = self.execute_aux( + true, + native_call.take(), + ); + + if !was_native || result.is_ok() { + result + } else { + self.overlay.prospective = orig_prospective.clone(); + let (wasm_result, _) = self.execute_aux( + false, + native_call, + ); + wasm_result + } + } + + /// Execute a call using the given state backend, overlayed changes, and call executor. + /// + /// 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. + /// + /// Returns the result of the executed function either in native reprensentation `R` or + /// in SCALE encoded representation. + pub fn execute_using_consensus_failure_handler( + &mut self, + manager: ExecutionManager, + mut native_call: Option, + ) -> Result, 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 init_overlay = |overlay: &mut OverlayedChanges, final_check: bool, backend: &B| { + 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, &self.backend)?; + + let result = { + let orig_prospective = self.overlay.prospective.clone(); + + match manager { + ExecutionManager::Both(on_consensus_failure) => { + self.execute_call_with_both_strategy( + native_call.take(), + orig_prospective, + on_consensus_failure, + ) + }, + ExecutionManager::NativeElseWasm => { + self.execute_call_with_native_else_wasm_strategy( + native_call.take(), + orig_prospective, + ) + }, + ExecutionManager::AlwaysWasm(trust_level) => { + let _abort_guard = match trust_level { + BackendTrustLevel::Trusted => None, + BackendTrustLevel::Untrusted => Some(sp_panic_handler::AbortGuard::never_abort()), + }; + self.execute_aux(false, native_call).0 + }, + ExecutionManager::NativeWhenPossible => { + self.execute_aux(true, native_call).0 + }, + } + }; + + if result.is_ok() { + init_overlay(self.overlay, true, self.backend)?; + } + + result.map_err(|e| Box::new(e) as _) + } +} + +/// Prove execution using the given state backend, overlayed changes, and call executor. +pub fn prove_execution( + mut backend: B, + overlay: &mut OverlayedChanges, + exec: &Exec, + method: &str, + call_data: &[u8], +) -> Result<(Vec, StorageProof), Box> +where + B: Backend, + H: Hasher, + H::Out: Ord + 'static + codec::Codec, + Exec: CodeExecutor, +{ + let trie_backend = backend.as_trie_backend() + .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; + prove_execution_on_trie_backend(trie_backend, overlay, exec, method, call_data) +} + +/// Prove execution using the given trie 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. +/// Execution proof is the set of all 'touched' storage DBValues from the backend. +/// +/// 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 prove_execution_on_trie_backend( + trie_backend: &TrieBackend, + overlay: &mut OverlayedChanges, + exec: &Exec, + method: &str, + call_data: &[u8], +) -> Result<(Vec, StorageProof), Box> +where + S: trie_backend_essence::TrieBackendStorage, + H: Hasher, + H::Out: Ord + 'static + codec::Codec, + Exec: CodeExecutor, +{ + let proving_backend = proving_backend::ProvingBackend::new(trie_backend); + let mut sm = StateMachine::<_, H, _, InMemoryChangesTrieStorage, Exec>::new( + &proving_backend, None, overlay, exec, method, call_data, Extensions::default(), + ); + + let result = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + always_wasm(), + None, + )?; + let proof = sm.backend.extract_proof(); + Ok((result.into_encoded(), proof)) +} + +/// Check execution proof, generated by `prove_execution` call. +pub fn execution_proof_check( + root: H::Out, + proof: StorageProof, + overlay: &mut OverlayedChanges, + exec: &Exec, + method: &str, + call_data: &[u8], +) -> Result, Box> +where + H: Hasher, + Exec: CodeExecutor, + H::Out: Ord + 'static + codec::Codec, +{ + let trie_backend = create_proof_check_backend::(root.into(), proof)?; + execution_proof_check_on_trie_backend(&trie_backend, overlay, exec, method, call_data) +} + +/// Check execution proof on proving backend, generated by `prove_execution` call. +pub fn execution_proof_check_on_trie_backend( + trie_backend: &TrieBackend, H>, + overlay: &mut OverlayedChanges, + exec: &Exec, + method: &str, + call_data: &[u8], +) -> Result, Box> +where + H: Hasher, + H::Out: Ord + 'static + codec::Codec, + Exec: CodeExecutor, +{ + let mut sm = StateMachine::<_, H, _, InMemoryChangesTrieStorage, Exec>::new( + trie_backend, None, overlay, exec, method, call_data, Extensions::default(), + ); + + sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + always_untrusted_wasm(), + None, + ).map(NativeOrEncoded::into_encoded) +} + +/// Generate storage read proof. +pub fn prove_read( + mut backend: B, + keys: I, +) -> Result> +where + B: Backend, + H: Hasher, + H::Out: Ord + Codec, + I: IntoIterator, + I::Item: AsRef<[u8]>, +{ + let trie_backend = backend.as_trie_backend() + .ok_or_else( + || Box::new(ExecutionError::UnableToGenerateProof) as Box + )?; + prove_read_on_trie_backend(trie_backend, keys) +} + +/// Generate child storage read proof. +pub fn prove_child_read( + mut backend: B, + storage_key: &[u8], + child_info: ChildInfo, + keys: I, +) -> Result> +where + B: Backend, + H: Hasher, + H::Out: Ord + Codec, + I: IntoIterator, + I::Item: AsRef<[u8]>, +{ + let trie_backend = backend.as_trie_backend() + .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; + prove_child_read_on_trie_backend(trie_backend, storage_key, child_info, keys) +} + +/// Generate storage read proof on pre-created trie backend. +pub fn prove_read_on_trie_backend( + trie_backend: &TrieBackend, + keys: I, +) -> Result> +where + S: trie_backend_essence::TrieBackendStorage, + H: Hasher, + H::Out: Ord + Codec, + I: IntoIterator, + I::Item: AsRef<[u8]>, +{ + let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend); + for key in keys.into_iter() { + proving_backend + .storage(key.as_ref()) + .map_err(|e| Box::new(e) as Box)?; + } + Ok(proving_backend.extract_proof()) +} + +/// Generate storage read proof on pre-created trie backend. +pub fn prove_child_read_on_trie_backend( + trie_backend: &TrieBackend, + storage_key: &[u8], + child_info: ChildInfo, + keys: I, +) -> Result> +where + S: trie_backend_essence::TrieBackendStorage, + H: Hasher, + H::Out: Ord + Codec, + I: IntoIterator, + I::Item: AsRef<[u8]>, +{ + let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend); + for key in keys.into_iter() { + proving_backend + .child_storage(storage_key, child_info.clone(), key.as_ref()) + .map_err(|e| Box::new(e) as Box)?; + } + Ok(proving_backend.extract_proof()) +} + +/// Check storage read proof, generated by `prove_read` call. +pub fn read_proof_check( + root: H::Out, + proof: StorageProof, + keys: I, +) -> Result, Option>>, Box> +where + H: Hasher, + H::Out: Ord + Codec, + I: IntoIterator, + I::Item: AsRef<[u8]>, +{ + let proving_backend = create_proof_check_backend::(root, proof)?; + let mut result = HashMap::new(); + for key in keys.into_iter() { + let value = read_proof_check_on_proving_backend(&proving_backend, key.as_ref())?; + result.insert(key.as_ref().to_vec(), value); + } + Ok(result) +} + +/// Check child storage read proof, generated by `prove_child_read` call. +pub fn read_child_proof_check( + root: H::Out, + proof: StorageProof, + storage_key: &[u8], + keys: I, +) -> Result, Option>>, Box> +where + H: Hasher, + H::Out: Ord + Codec, + I: IntoIterator, + I::Item: AsRef<[u8]>, +{ + let proving_backend = create_proof_check_backend::(root, proof)?; + let mut result = HashMap::new(); + for key in keys.into_iter() { + let value = read_child_proof_check_on_proving_backend( + &proving_backend, + storage_key, + key.as_ref(), + )?; + result.insert(key.as_ref().to_vec(), value); + } + Ok(result) +} + +/// Check storage read proof on pre-created proving backend. +pub fn read_proof_check_on_proving_backend( + proving_backend: &TrieBackend, H>, + key: &[u8], +) -> Result>, Box> +where + H: Hasher, + H::Out: Ord + Codec, +{ + proving_backend.storage(key).map_err(|e| Box::new(e) as Box) +} + +/// Check child storage read proof on pre-created proving backend. +pub fn read_child_proof_check_on_proving_backend( + proving_backend: &TrieBackend, H>, + storage_key: &[u8], + key: &[u8], +) -> Result>, Box> +where + H: Hasher, + H::Out: Ord + Codec, +{ + // Not a prefixed memory db, using empty unique id and include root resolution. + proving_backend.child_storage(storage_key, ChildInfo::new_default(&[]), key) + .map_err(|e| Box::new(e) as Box) +} + +/// Sets overlayed changes' changes trie configuration. Returns error if configuration +/// differs from previous OR config decode has failed. +fn set_changes_trie_config( + overlay: &mut OverlayedChanges, + config: Option>, + final_check: bool, +) -> Result<(), Box> { + let config = match config { + Some(v) => Some(Decode::decode(&mut &v[..]) + .map_err(|_| Box::new("Failed to decode changes trie configuration".to_owned()) as Box)?), + None => None, + }; + + if final_check && overlay.changes_trie_config.is_some() != config.is_some() { + return Err(Box::new("Changes trie configuration change is not supported".to_owned())); + } + + if let Some(config) = config { + if !overlay.set_changes_trie_config(config) { + return Err(Box::new("Changes trie configuration change is not supported".to_owned())); + } + } + Ok(()) +} + +/// Reads storage value from overlay or from the backend. +fn try_read_overlay_value( + overlay: &OverlayedChanges, + backend: &B, key: &[u8], +) -> Result>, Box> where H: Hasher, B: Backend { + match overlay.storage(key).map(|x| x.map(|x| x.to_vec())) { + Some(value) => Ok(value), + None => backend + .storage(key) + .map_err(|err| Box::new(ExecutionError::Backend(format!("{}", err))) as Box), + } +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + use codec::Encode; + use overlayed_changes::OverlayedValue; + use super::*; + use super::ext::Ext; + use super::changes_trie::{ + InMemoryStorage as InMemoryChangesTrieStorage, + Configuration as ChangesTrieConfig, + }; + use sp_core::{Blake2Hasher, map, traits::Externalities, storage::ChildStorageKey}; + + struct DummyCodeExecutor { + change_changes_trie_config: bool, + native_available: bool, + native_succeeds: bool, + fallback_succeeds: bool, + } + + const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1"); + + impl CodeExecutor for DummyCodeExecutor { + type Error = u8; + + fn call< + E: Externalities, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result, + >( + &self, + ext: &mut E, + _method: &str, + _data: &[u8], + 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() + ) + ); + } + + let using_native = use_native && self.native_available; + match (using_native, self.native_succeeds, self.fallback_succeeds) { + (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), + } + } + } + + #[test] + fn execute_works() { + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + &backend, + Some(&changes_trie_storage), + &mut overlayed_changes, + &DummyCodeExecutor { + change_changes_trie_config: false, + native_available: true, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + Default::default(), + ); + + assert_eq!( + state_machine.execute(ExecutionStrategy::NativeWhenPossible).unwrap(), + vec![66], + ); + } + + + #[test] + fn execute_works_with_native_else_wasm() { + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + &backend, + Some(&changes_trie_storage), + &mut overlayed_changes, + &DummyCodeExecutor { + change_changes_trie_config: false, + native_available: true, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + Default::default(), + ); + + assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap(), vec![66]); + } + + #[test] + fn dual_execution_strategy_detects_consensus_failure() { + let mut consensus_failed = false; + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + &backend, + Some(&changes_trie_storage), + &mut overlayed_changes, + &DummyCodeExecutor { + change_changes_trie_config: false, + native_available: true, + native_succeeds: true, + fallback_succeeds: false, + }, + "test", + &[], + Default::default(), + ); + + assert!( + state_machine.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + ExecutionManager::Both(|we, _ne| { + consensus_failed = true; + we + }), + None, + ).is_err() + ); + assert!(consensus_failed); + } + + #[test] + fn prove_execution_and_proof_check_works() { + let executor = DummyCodeExecutor { + change_changes_trie_config: false, + native_available: true, + native_succeeds: true, + fallback_succeeds: true, + }; + + // fetch execution proof from 'remote' full node + let remote_backend = trie_backend::tests::test_trie(); + let remote_root = remote_backend.storage_root(std::iter::empty()).0; + let (remote_result, remote_proof) = prove_execution( + remote_backend, + &mut Default::default(), + &executor, + "test", + &[], + ).unwrap(); + + // check proof locally + let local_result = execution_proof_check::( + remote_root, + remote_proof, + &mut Default::default(), + &executor, + "test", + &[], + ).unwrap(); + + // check that both results are correct + assert_eq!(remote_result, vec![66]); + assert_eq!(remote_result, local_result); + } + + #[test] + fn clear_prefix_in_ext_works() { + let initial: BTreeMap<_, _> = map![ + b"aaa".to_vec() => b"0".to_vec(), + b"abb".to_vec() => b"1".to_vec(), + b"abc".to_vec() => b"2".to_vec(), + b"bbb".to_vec() => b"3".to_vec() + ]; + let mut state = InMemoryBackend::::from(initial); + let backend = state.as_trie_backend().unwrap(); + let mut overlay = OverlayedChanges { + committed: map![ + b"aba".to_vec() => OverlayedValue::from(Some(b"1312".to_vec())), + b"bab".to_vec() => OverlayedValue::from(Some(b"228".to_vec())) + ], + prospective: map![ + b"abd".to_vec() => OverlayedValue::from(Some(b"69".to_vec())), + b"bbd".to_vec() => OverlayedValue::from(Some(b"42".to_vec())) + ], + ..Default::default() + }; + + { + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + let mut cache = StorageTransactionCache::default(); + let mut ext = Ext::new( + &mut overlay, + &mut cache, + backend, + Some(&changes_trie_storage), + None, + ); + ext.clear_prefix(b"ab"); + } + overlay.commit_prospective(); + + assert_eq!( + overlay.committed, + map![ + b"abc".to_vec() => None.into(), + b"abb".to_vec() => None.into(), + b"aba".to_vec() => None.into(), + b"abd".to_vec() => None.into(), + + b"bab".to_vec() => Some(b"228".to_vec()).into(), + b"bbd".to_vec() => Some(b"42".to_vec()).into() + ], + ); + } + + #[test] + fn set_child_storage_works() { + let mut state = InMemoryBackend::::default(); + let backend = state.as_trie_backend().unwrap(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + let mut overlay = OverlayedChanges::default(); + let mut cache = StorageTransactionCache::default(); + let mut ext = Ext::new( + &mut overlay, + &mut cache, + backend, + Some(&changes_trie_storage), + None, + ); + + ext.set_child_storage( + ChildStorageKey::from_slice(b":child_storage:default:testchild").unwrap(), + CHILD_INFO_1, + b"abc".to_vec(), + b"def".to_vec() + ); + assert_eq!( + ext.child_storage( + ChildStorageKey::from_slice(b":child_storage:default:testchild").unwrap(), + CHILD_INFO_1, + b"abc" + ), + Some(b"def".to_vec()) + ); + ext.kill_child_storage( + ChildStorageKey::from_slice(b":child_storage:default:testchild").unwrap(), + CHILD_INFO_1, + ); + assert_eq!( + ext.child_storage( + ChildStorageKey::from_slice(b":child_storage:default:testchild").unwrap(), + CHILD_INFO_1, + b"abc" + ), + None + ); + } + + #[test] + fn prove_read_and_proof_check_works() { + // fetch read proof from 'remote' full node + let remote_backend = trie_backend::tests::test_trie(); + let remote_root = remote_backend.storage_root(::std::iter::empty()).0; + let remote_proof = prove_read(remote_backend, &[b"value2"]).unwrap(); + // check proof locally + let local_result1 = read_proof_check::( + remote_root, + remote_proof.clone(), + &[b"value2"], + ).unwrap(); + let local_result2 = read_proof_check::( + remote_root, + remote_proof.clone(), + &[&[0xff]], + ).is_ok(); + // check that results are correct + assert_eq!( + local_result1.into_iter().collect::>(), + vec![(b"value2".to_vec(), Some(vec![24]))], + ); + assert_eq!(local_result2, false); + // on child trie + let remote_backend = trie_backend::tests::test_trie(); + let remote_root = remote_backend.storage_root(::std::iter::empty()).0; + let remote_proof = prove_child_read( + remote_backend, + b":child_storage:default:sub1", + CHILD_INFO_1, + &[b"value3"], + ).unwrap(); + let local_result1 = read_child_proof_check::( + remote_root, + remote_proof.clone(), + b":child_storage:default:sub1", + &[b"value3"], + ).unwrap(); + let local_result2 = read_child_proof_check::( + remote_root, + remote_proof.clone(), + b":child_storage:default:sub1", + &[b"value2"], + ).unwrap(); + assert_eq!( + local_result1.into_iter().collect::>(), + vec![(b"value3".to_vec(), Some(vec![142]))], + ); + assert_eq!( + local_result2.into_iter().collect::>(), + vec![(b"value2".to_vec(), None)], + ); + } + + #[test] + fn cannot_change_changes_trie_config() { + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + &backend, + Some(&changes_trie_storage), + &mut overlayed_changes, + &DummyCodeExecutor { + change_changes_trie_config: true, + native_available: false, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + Default::default(), + ); + + assert!(state_machine.execute(ExecutionStrategy::NativeWhenPossible).is_err()); + } + + #[test] + fn child_storage_uuid() { + const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1"); + const CHILD_INFO_2: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_2"); + use crate::trie_backend::tests::test_trie; + let mut overlay = OverlayedChanges::default(); + + let subtrie1 = ChildStorageKey::from_slice(b":child_storage:default:sub_test1").unwrap(); + let subtrie2 = ChildStorageKey::from_slice(b":child_storage:default:sub_test2").unwrap(); + let mut transaction = { + let backend = test_trie(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + let mut cache = StorageTransactionCache::default(); + let mut ext = Ext::new( + &mut overlay, + &mut cache, + &backend, + Some(&changes_trie_storage), + None, + ); + ext.set_child_storage(subtrie1, CHILD_INFO_1, b"abc".to_vec(), b"def".to_vec()); + ext.set_child_storage(subtrie2, CHILD_INFO_2, b"abc".to_vec(), b"def".to_vec()); + ext.storage_root(); + cache.transaction.unwrap() + }; + let mut duplicate = false; + for (k, (value, rc)) in transaction.drain().iter() { + // look for a key inserted twice: transaction rc is 2 + if *rc == 2 { + duplicate = true; + println!("test duplicate for {:?} {:?}", k, value); + } + } + assert!(!duplicate); + } + + #[test] + fn cannot_change_changes_trie_config_with_native_else_wasm() { + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + &backend, + Some(&changes_trie_storage), + &mut overlayed_changes, + &DummyCodeExecutor { + change_changes_trie_config: true, + native_available: false, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + Default::default(), + ); + + assert!(state_machine.execute(ExecutionStrategy::NativeElseWasm).is_err()); + } +} diff --git a/primitives/state-machine/src/overlayed_changes.rs b/primitives/state-machine/src/overlayed_changes.rs new file mode 100644 index 0000000000000..eafd31241038b --- /dev/null +++ b/primitives/state-machine/src/overlayed_changes.rs @@ -0,0 +1,925 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! The overlayed changes to state. + +use crate::{ + backend::Backend, ChangesTrieTransaction, + changes_trie::{ + NO_EXTRINSIC_INDEX, Configuration as ChangesTrieConfig, BlockNumber, build_changes_trie, + Storage as ChangesTrieStorage, + }, +}; + +#[cfg(test)] +use std::iter::FromIterator; +use std::collections::{HashMap, BTreeMap, BTreeSet}; +use codec::{Decode, Encode}; +use sp_core::storage::{well_known_keys::EXTRINSIC_INDEX, OwnedChildInfo, ChildInfo}; +use std::{mem, ops}; + +use hash_db::Hasher; + +/// The overlayed changes to state to be queried on top of the backend. +/// +/// A transaction shares all prospective changes within an inner overlay +/// that can be cleared. +#[derive(Debug, Default, Clone)] +pub struct OverlayedChanges { + /// Changes that are not yet committed. + pub(crate) prospective: OverlayedChangeSet, + /// Committed changes. + pub(crate) committed: OverlayedChangeSet, + /// Changes trie configuration. None by default, but could be installed by the + /// runtime if it supports change tries. + pub(crate) changes_trie_config: Option, +} + +/// The storage value, used inside OverlayedChanges. +#[derive(Debug, Default, Clone)] +#[cfg_attr(test, derive(PartialEq))] +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 has announced changes trie support. + pub extrinsics: Option>, +} + +/// Prospective or committed overlayed change set. +#[derive(Debug, Default, Clone)] +#[cfg_attr(test, derive(PartialEq))] +pub struct OverlayedChangeSet { + /// Top level storage changes. + pub top: BTreeMap, OverlayedValue>, + /// Child storage changes. + pub children: HashMap, (BTreeMap, OverlayedValue>, OwnedChildInfo)>, +} + +/// A storage changes structure that can be generated by the data collected in [`OverlayedChanges`]. +/// +/// This contains all the changes to the storage and transactions to apply theses changes to the +/// backend. +pub struct StorageChanges { + /// All changes to the main storage. + /// + /// A value of `None` means that it was deleted. + pub main_storage_changes: Vec<(Vec, Option>)>, + /// All changes to the child storages. + pub child_storage_changes: Vec<(Vec, Vec<(Vec, Option>)>)>, + /// A transaction for the backend that contains all changes from + /// [`main_storage_changes`](Self::main_storage_changes) and from + /// [`child_storage_changes`](Self::child_storage_changes). + pub transaction: Transaction, + /// The storage root after applying the transaction. + pub transaction_storage_root: H::Out, + /// Contains the transaction for the backend for the changes trie. + /// + /// If changes trie is disabled the value is set to `None`. + pub changes_trie_transaction: Option>, +} + +impl StorageChanges { + /// Deconstruct into the inner values + pub fn into_inner(self) -> ( + Vec<(Vec, Option>)>, + Vec<(Vec, Vec<(Vec, Option>)>)>, + Transaction, + H::Out, + Option>, + ) { + ( + self.main_storage_changes, + self.child_storage_changes, + self.transaction, + self.transaction_storage_root, + self.changes_trie_transaction, + ) + } +} + +/// The storage transaction are calculated as part of the `storage_root` and +/// `changes_trie_storage_root`. These transactions can be reused for importing the block into the +/// storage. So, we cache them to not require a recomputation of those transactions. +pub struct StorageTransactionCache { + /// Contains the changes for the main and the child storages as one transaction. + pub(crate) transaction: Option, + /// The storage root after applying the transaction. + pub(crate) transaction_storage_root: Option, + /// Contains the changes trie transaction. + pub(crate) changes_trie_transaction: Option>>, + /// The storage root after applying the changes trie transaction. + pub(crate) changes_trie_transaction_storage_root: Option>, +} + +impl StorageTransactionCache { + /// Reset the cached transactions. + pub fn reset(&mut self) { + *self = Self::default(); + } +} + +impl Default for StorageTransactionCache { + fn default() -> Self { + Self { + transaction: None, + transaction_storage_root: None, + changes_trie_transaction: None, + changes_trie_transaction_storage_root: None, + } + } +} + +impl Default for StorageChanges { + fn default() -> Self { + Self { + main_storage_changes: Default::default(), + child_storage_changes: Default::default(), + transaction: Default::default(), + transaction_storage_root: Default::default(), + changes_trie_transaction: None, + } + } +} + +#[cfg(test)] +impl FromIterator<(Vec, OverlayedValue)> for OverlayedChangeSet { + fn from_iter, OverlayedValue)>>(iter: T) -> Self { + Self { + top: iter.into_iter().collect(), + children: Default::default(), + } + } +} + +impl OverlayedChangeSet { + /// Whether the change set is empty. + pub fn is_empty(&self) -> bool { + self.top.is_empty() && self.children.is_empty() + } + + /// Clear the change set. + pub fn clear(&mut self) { + self.top.clear(); + self.children.clear(); + } +} + +impl OverlayedChanges { + /// Whether the overlayed changes are empty. + pub fn is_empty(&self) -> bool { + self.prospective.is_empty() && self.committed.is_empty() + } + + /// Sets the changes trie configuration. + /// + /// Returns false if configuration has been set already and we now trying + /// to install different configuration. This isn't supported now. + pub(crate) fn set_changes_trie_config(&mut self, config: ChangesTrieConfig) -> bool { + if let Some(ref old_config) = self.changes_trie_config { + // we do not support changes trie configuration' change now + if *old_config != config { + return false; + } + } + + self.changes_trie_config = Some(config); + true + } + + /// Returns a double-Option: None if the key is unknown (i.e. and the query should be referred + /// to the backend); Some(None) if the key has been deleted. Some(Some(...)) for a key whose + /// value has been set. + pub fn storage(&self, key: &[u8]) -> Option> { + self.prospective.top.get(key) + .or_else(|| self.committed.top.get(key)) + .map(|x| x.value.as_ref().map(AsRef::as_ref)) + } + + /// Returns a double-Option: None if the key is unknown (i.e. and the query should be referred + /// to the backend); Some(None) if the key has been deleted. Some(Some(...)) for a key whose + /// value has been set. + pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option> { + if let Some(map) = self.prospective.children.get(storage_key) { + if let Some(val) = map.0.get(key) { + return Some(val.value.as_ref().map(AsRef::as_ref)); + } + } + + if let Some(map) = self.committed.children.get(storage_key) { + if let Some(val) = map.0.get(key) { + return Some(val.value.as_ref().map(AsRef::as_ref)); + } + } + + None + } + + /// Inserts the given key-value pair into the prospective change set. + /// + /// `None` can be used to delete a value specified by the given key. + pub(crate) fn set_storage(&mut self, key: Vec, val: Option>) { + let extrinsic_index = self.extrinsic_index(); + let entry = self.prospective.top.entry(key).or_default(); + entry.value = val; + + if let Some(extrinsic) = extrinsic_index { + entry.extrinsics.get_or_insert_with(Default::default) + .insert(extrinsic); + } + } + + /// Inserts the given key-value pair into the prospective child change set. + /// + /// `None` can be used to delete a value specified by the given key. + pub(crate) fn set_child_storage( + &mut self, + storage_key: Vec, + child_info: ChildInfo, + key: Vec, + val: Option>, + ) { + let extrinsic_index = self.extrinsic_index(); + let map_entry = self.prospective.children.entry(storage_key) + .or_insert_with(|| (Default::default(), child_info.to_owned())); + let updatable = map_entry.1.try_update(child_info); + debug_assert!(updatable); + + let entry = map_entry.0.entry(key).or_default(); + entry.value = val; + + if let Some(extrinsic) = extrinsic_index { + entry.extrinsics.get_or_insert_with(Default::default) + .insert(extrinsic); + } + } + + /// Clear child storage of given storage key. + /// + /// NOTE that this doesn't take place immediately but written into the prospective + /// change set, and still can be reverted by [`discard_prospective`]. + /// + /// [`discard_prospective`]: #method.discard_prospective + pub(crate) fn clear_child_storage( + &mut self, + storage_key: &[u8], + child_info: ChildInfo, + ) { + let extrinsic_index = self.extrinsic_index(); + let map_entry = self.prospective.children.entry(storage_key.to_vec()) + .or_insert_with(|| (Default::default(), child_info.to_owned())); + let updatable = map_entry.1.try_update(child_info); + debug_assert!(updatable); + + map_entry.0.values_mut().for_each(|e| { + if let Some(extrinsic) = extrinsic_index { + e.extrinsics.get_or_insert_with(Default::default) + .insert(extrinsic); + } + + e.value = None; + }); + + if let Some((committed_map, _child_info)) = self.committed.children.get(storage_key) { + for (key, value) in committed_map.iter() { + if !map_entry.0.contains_key(key) { + map_entry.0.insert(key.clone(), OverlayedValue { + value: None, + extrinsics: extrinsic_index.map(|i| { + let mut e = value.extrinsics.clone() + .unwrap_or_else(|| BTreeSet::default()); + e.insert(i); + e + }), + }); + } + } + } + } + + /// Removes all key-value pairs which keys share the given prefix. + /// + /// NOTE that this doesn't take place immediately but written into the prospective + /// change set, and still can be reverted by [`discard_prospective`]. + /// + /// [`discard_prospective`]: #method.discard_prospective + pub(crate) fn clear_prefix(&mut self, prefix: &[u8]) { + let extrinsic_index = self.extrinsic_index(); + + // Iterate over all prospective and mark all keys that share + // the given prefix as removed (None). + for (key, entry) in self.prospective.top.iter_mut() { + if key.starts_with(prefix) { + entry.value = None; + + if let Some(extrinsic) = extrinsic_index { + entry.extrinsics.get_or_insert_with(Default::default) + .insert(extrinsic); + } + } + } + + // Then do the same with keys from committed changes. + // NOTE that we are making changes in the prospective change set. + for key in self.committed.top.keys() { + if key.starts_with(prefix) { + let entry = self.prospective.top.entry(key.clone()).or_default(); + entry.value = None; + + if let Some(extrinsic) = extrinsic_index { + entry.extrinsics.get_or_insert_with(Default::default) + .insert(extrinsic); + } + } + } + } + + pub(crate) fn clear_child_prefix( + &mut self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + ) { + let extrinsic_index = self.extrinsic_index(); + let map_entry = self.prospective.children.entry(storage_key.to_vec()) + .or_insert_with(|| (Default::default(), child_info.to_owned())); + let updatable = map_entry.1.try_update(child_info); + debug_assert!(updatable); + + for (key, entry) in map_entry.0.iter_mut() { + if key.starts_with(prefix) { + entry.value = None; + + if let Some(extrinsic) = extrinsic_index { + entry.extrinsics.get_or_insert_with(Default::default) + .insert(extrinsic); + } + } + } + + if let Some((child_committed, _child_info)) = self.committed.children.get(storage_key) { + // Then do the same with keys from commited changes. + // NOTE that we are making changes in the prospective change set. + for key in child_committed.keys() { + if key.starts_with(prefix) { + let entry = map_entry.0.entry(key.clone()).or_default(); + entry.value = None; + + if let Some(extrinsic) = extrinsic_index { + entry.extrinsics.get_or_insert_with(Default::default) + .insert(extrinsic); + } + } + } + } + } + + /// Discard prospective changes to state. + pub fn discard_prospective(&mut self) { + self.prospective.clear(); + } + + /// Commit prospective changes to state. + pub fn commit_prospective(&mut self) { + if self.committed.is_empty() { + mem::swap(&mut self.prospective, &mut self.committed); + } else { + let top_to_commit = mem::replace(&mut self.prospective.top, BTreeMap::new()); + for (key, val) in top_to_commit.into_iter() { + let entry = self.committed.top.entry(key).or_default(); + entry.value = val.value; + + if let Some(prospective_extrinsics) = val.extrinsics { + entry.extrinsics.get_or_insert_with(Default::default) + .extend(prospective_extrinsics); + } + } + for (storage_key, (map, child_info)) in self.prospective.children.drain() { + let child_content = self.committed.children.entry(storage_key) + .or_insert_with(|| (Default::default(), child_info)); + // No update to child info at this point (will be needed for deletion). + for (key, val) in map.into_iter() { + let entry = child_content.0.entry(key).or_default(); + entry.value = val.value; + + if let Some(prospective_extrinsics) = val.extrinsics { + entry.extrinsics.get_or_insert_with(Default::default) + .extend(prospective_extrinsics); + } + } + } + } + } + + /// Consume `OverlayedChanges` and take committed set. + /// + /// Panics: + /// Will panic if there are any uncommitted prospective changes. + pub fn into_committed(self) -> ( + impl Iterator, Option>)>, + impl Iterator, (impl Iterator, Option>)>, OwnedChildInfo))>, + ){ + assert!(self.prospective.is_empty()); + ( + self.committed.top.into_iter().map(|(k, v)| (k, v.value)), + self.committed.children.into_iter() + .map(|(sk, (v, ci))| (sk, (v.into_iter().map(|(k, v)| (k, v.value)), ci))) + ) + } + + /// Convert this instance with all changes into a [`StorageChanges`] instance. + pub fn into_storage_changes< + B: Backend, H: Hasher, N: BlockNumber, T: ChangesTrieStorage + >( + self, + backend: &B, + changes_trie_storage: Option<&T>, + parent_hash: H::Out, + mut cache: StorageTransactionCache, + ) -> Result, String> where H::Out: Ord + Encode + 'static { + // If the transaction does not exist, we generate it. + if cache.transaction.is_none() { + self.storage_root(backend, &mut cache); + } + + let (transaction, transaction_storage_root) = cache.transaction.take() + .and_then(|t| cache.transaction_storage_root.take().map(|tr| (t, tr))) + .expect("Transaction was be generated as part of `storage_root`; qed"); + + // If the transaction does not exist, we generate it. + if cache.changes_trie_transaction.is_none() { + self.changes_trie_root( + backend, + changes_trie_storage, + parent_hash, + false, + &mut cache, + ).map_err(|_| "Failed to generate changes trie transaction")?; + } + + let changes_trie_transaction = cache.changes_trie_transaction + .take() + .expect("Changes trie transaction was generated by `changes_trie_root`; qed"); + + let (main_storage_changes, child_storage_changes) = self.into_committed(); + + Ok(StorageChanges { + main_storage_changes: main_storage_changes.collect(), + child_storage_changes: child_storage_changes.map(|(sk, it)| (sk, it.0.collect())).collect(), + transaction, + transaction_storage_root, + changes_trie_transaction, + }) + } + + /// Inserts storage entry responsible for current extrinsic index. + #[cfg(test)] + pub(crate) fn set_extrinsic_index(&mut self, extrinsic_index: u32) { + self.prospective.top.insert(EXTRINSIC_INDEX.to_vec(), OverlayedValue { + value: Some(extrinsic_index.encode()), + extrinsics: None, + }); + } + + /// Returns current extrinsic index to use in changes trie construction. + /// None is returned if it is not set or changes trie config is not set. + /// Persistent value (from the backend) can be ignored because runtime must + /// set this index before first and unset after last extrinsic is executed. + /// Changes that are made outside of extrinsics, are marked with + /// `NO_EXTRINSIC_INDEX` index. + fn extrinsic_index(&self) -> Option { + match self.changes_trie_config.is_some() { + true => Some( + self.storage(EXTRINSIC_INDEX) + .and_then(|idx| idx.and_then(|idx| Decode::decode(&mut &*idx).ok())) + .unwrap_or(NO_EXTRINSIC_INDEX)), + false => None, + } + } + + /// Generate the storage root using `backend` and all changes from `prospective` and `committed`. + /// + /// Returns the storage root and caches storage transaction in the given `cache`. + pub fn storage_root>( + &self, + backend: &B, + cache: &mut StorageTransactionCache, + ) -> H::Out + where H::Out: Ord + Encode, + { + let child_storage_keys = self.prospective.children.keys() + .chain(self.committed.children.keys()); + let child_delta_iter = child_storage_keys.map(|storage_key| + ( + storage_key.clone(), + self.committed.children.get(storage_key) + .into_iter() + .flat_map(|(map, _)| map.iter().map(|(k, v)| (k.clone(), v.value.clone()))) + .chain( + self.prospective.children.get(storage_key) + .into_iter() + .flat_map(|(map, _)| map.iter().map(|(k, v)| (k.clone(), v.value.clone()))) + ), + self.child_info(storage_key).cloned() + .expect("child info initialized in either committed or prospective"), + ) + ); + + // compute and memoize + let delta = self.committed.top.iter().map(|(k, v)| (k.clone(), v.value.clone())) + .chain(self.prospective.top.iter().map(|(k, v)| (k.clone(), v.value.clone()))); + + let (root, transaction) = backend.full_storage_root(delta, child_delta_iter); + + cache.transaction = Some(transaction); + cache.transaction_storage_root = Some(root); + + root + } + + /// Generate the changes trie root. + /// + /// Returns the changes trie root and caches the storage transaction into the given `cache`. + /// + /// # Panics + /// + /// Panics on storage error, when `panic_on_storage_error` is set. + pub fn changes_trie_root, T: ChangesTrieStorage>( + &self, + backend: &B, + changes_trie_storage: Option<&T>, + parent_hash: H::Out, + panic_on_storage_error: bool, + cache: &mut StorageTransactionCache, + ) -> Result, ()> where H::Out: Ord + Encode + 'static { + build_changes_trie::<_, T, H, N>( + backend, + changes_trie_storage, + self, + parent_hash, + panic_on_storage_error, + ).map(|r| { + let root = r.as_ref().map(|r| r.1).clone(); + cache.changes_trie_transaction = Some(r.map(|(db, _, cache)| (db, cache))); + cache.changes_trie_transaction_storage_root = Some(root); + root + }) + } + + /// Get child info for a storage key. + /// Take the latest value so prospective first. + pub fn child_info(&self, storage_key: &[u8]) -> Option<&OwnedChildInfo> { + if let Some((_, ci)) = self.prospective.children.get(storage_key) { + return Some(&ci); + } + if let Some((_, ci)) = self.committed.children.get(storage_key) { + return Some(&ci); + } + None + } + + /// Returns the next (in lexicographic order) storage key in the overlayed alongside its value. + /// If no value is next then `None` is returned. + pub fn next_storage_key_change(&self, key: &[u8]) -> Option<(&[u8], &OverlayedValue)> { + let range = (ops::Bound::Excluded(key), ops::Bound::Unbounded); + + let next_prospective_key = self.prospective.top + .range::<[u8], _>(range) + .next() + .map(|(k, v)| (&k[..], v)); + + let next_committed_key = self.committed.top + .range::<[u8], _>(range) + .next() + .map(|(k, v)| (&k[..], v)); + + match (next_committed_key, next_prospective_key) { + // Committed is strictly less than prospective + (Some(committed_key), Some(prospective_key)) if committed_key.0 < prospective_key.0 => + Some(committed_key), + (committed_key, None) => committed_key, + // Prospective key is less or equal to committed or committed doesn't exist + (_, prospective_key) => prospective_key, + } + } + + /// Returns the next (in lexicographic order) child storage key in the overlayed alongside its + /// value. If no value is next then `None` is returned. + pub fn next_child_storage_key_change( + &self, + storage_key: &[u8], + key: &[u8] + ) -> Option<(&[u8], &OverlayedValue)> { + let range = (ops::Bound::Excluded(key), ops::Bound::Unbounded); + + let next_prospective_key = self.prospective.children.get(storage_key) + .and_then(|(map, _)| map.range::<[u8], _>(range).next().map(|(k, v)| (&k[..], v))); + + let next_committed_key = self.committed.children.get(storage_key) + .and_then(|(map, _)| map.range::<[u8], _>(range).next().map(|(k, v)| (&k[..], v))); + + match (next_committed_key, next_prospective_key) { + // Committed is strictly less than prospective + (Some(committed_key), Some(prospective_key)) if committed_key.0 < prospective_key.0 => + Some(committed_key), + (committed_key, None) => committed_key, + // Prospective key is less or equal to committed or committed doesn't exist + (_, prospective_key) => prospective_key, + } + } +} + +#[cfg(test)] +impl From>> for OverlayedValue { + fn from(value: Option>) -> OverlayedValue { + OverlayedValue { value, ..Default::default() } + } +} + +#[cfg(test)] +mod tests { + use hex_literal::hex; + use sp_core::{ + Blake2Hasher, traits::Externalities, storage::well_known_keys::EXTRINSIC_INDEX, + }; + use crate::InMemoryBackend; + use crate::changes_trie::InMemoryStorage as InMemoryChangesTrieStorage; + use crate::ext::Ext; + use super::*; + + fn strip_extrinsic_index(map: &BTreeMap, OverlayedValue>) + -> BTreeMap, OverlayedValue> + { + let mut clone = map.clone(); + clone.remove(&EXTRINSIC_INDEX.to_vec()); + clone + } + + #[test] + fn overlayed_storage_works() { + let mut overlayed = OverlayedChanges::default(); + + let key = vec![42, 69, 169, 142]; + + assert!(overlayed.storage(&key).is_none()); + + overlayed.set_storage(key.clone(), Some(vec![1, 2, 3])); + assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..])); + + overlayed.commit_prospective(); + assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..])); + + overlayed.set_storage(key.clone(), Some(vec![])); + assert_eq!(overlayed.storage(&key).unwrap(), Some(&[][..])); + + overlayed.set_storage(key.clone(), None); + assert!(overlayed.storage(&key).unwrap().is_none()); + + overlayed.discard_prospective(); + assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..])); + + overlayed.set_storage(key.clone(), None); + overlayed.commit_prospective(); + assert!(overlayed.storage(&key).unwrap().is_none()); + } + + #[test] + fn overlayed_storage_root_works() { + let initial: BTreeMap<_, _> = vec![ + (b"doe".to_vec(), b"reindeer".to_vec()), + (b"dog".to_vec(), b"puppyXXX".to_vec()), + (b"dogglesworth".to_vec(), b"catXXX".to_vec()), + (b"doug".to_vec(), b"notadog".to_vec()), + ].into_iter().collect(); + let backend = InMemoryBackend::::from(initial); + let mut overlay = OverlayedChanges { + committed: vec![ + (b"dog".to_vec(), Some(b"puppy".to_vec()).into()), + (b"dogglesworth".to_vec(), Some(b"catYYY".to_vec()).into()), + (b"doug".to_vec(), Some(vec![]).into()), + ].into_iter().collect(), + prospective: vec![ + (b"dogglesworth".to_vec(), Some(b"cat".to_vec()).into()), + (b"doug".to_vec(), None.into()), + ].into_iter().collect(), + ..Default::default() + }; + + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + let mut cache = StorageTransactionCache::default(); + let mut ext = Ext::new( + &mut overlay, + &mut cache, + &backend, + Some(&changes_trie_storage), + None, + ); + const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa"); + + assert_eq!(&ext.storage_root()[..], &ROOT); + } + + #[test] + fn changes_trie_configuration_is_saved() { + let mut overlay = OverlayedChanges::default(); + assert!(overlay.changes_trie_config.is_none()); + assert_eq!( + overlay.set_changes_trie_config( + ChangesTrieConfig { digest_interval: 4, digest_levels: 1, }, + ), + true, + ); + assert!(overlay.changes_trie_config.is_some()); + } + + #[test] + fn changes_trie_configuration_is_saved_twice() { + let mut overlay = OverlayedChanges::default(); + assert!(overlay.changes_trie_config.is_none()); + assert_eq!(overlay.set_changes_trie_config(ChangesTrieConfig { + digest_interval: 4, digest_levels: 1, + }), true); + overlay.set_extrinsic_index(0); + overlay.set_storage(vec![1], Some(vec![2])); + assert_eq!(overlay.set_changes_trie_config(ChangesTrieConfig { + digest_interval: 4, digest_levels: 1, + }), true); + assert_eq!( + strip_extrinsic_index(&overlay.prospective.top), + vec![ + (vec![1], OverlayedValue { value: Some(vec![2]), + extrinsics: Some(vec![0].into_iter().collect()) }), + ].into_iter().collect(), + ); + } + + #[test] + fn panics_when_trying_to_save_different_changes_trie_configuration() { + let mut overlay = OverlayedChanges::default(); + assert_eq!(overlay.set_changes_trie_config(ChangesTrieConfig { + digest_interval: 4, digest_levels: 1, + }), true); + assert_eq!(overlay.set_changes_trie_config(ChangesTrieConfig { + digest_interval: 2, digest_levels: 1, + }), false); + } + + #[test] + fn extrinsic_changes_are_collected() { + let mut overlay = OverlayedChanges::default(); + let _ = overlay.set_changes_trie_config(ChangesTrieConfig { + digest_interval: 4, digest_levels: 1, + }); + + overlay.set_storage(vec![100], Some(vec![101])); + + overlay.set_extrinsic_index(0); + overlay.set_storage(vec![1], Some(vec![2])); + + overlay.set_extrinsic_index(1); + overlay.set_storage(vec![3], Some(vec![4])); + + overlay.set_extrinsic_index(2); + overlay.set_storage(vec![1], Some(vec![6])); + + assert_eq!(strip_extrinsic_index(&overlay.prospective.top), + vec![ + (vec![1], OverlayedValue { value: Some(vec![6]), + extrinsics: Some(vec![0, 2].into_iter().collect()) }), + (vec![3], OverlayedValue { value: Some(vec![4]), + extrinsics: Some(vec![1].into_iter().collect()) }), + (vec![100], OverlayedValue { value: Some(vec![101]), + extrinsics: Some(vec![NO_EXTRINSIC_INDEX].into_iter().collect()) }), + ].into_iter().collect()); + + overlay.commit_prospective(); + + overlay.set_extrinsic_index(3); + overlay.set_storage(vec![3], Some(vec![7])); + + overlay.set_extrinsic_index(4); + overlay.set_storage(vec![1], Some(vec![8])); + + assert_eq!(strip_extrinsic_index(&overlay.committed.top), + vec![ + (vec![1], OverlayedValue { value: Some(vec![6]), + extrinsics: Some(vec![0, 2].into_iter().collect()) }), + (vec![3], OverlayedValue { value: Some(vec![4]), + extrinsics: Some(vec![1].into_iter().collect()) }), + (vec![100], OverlayedValue { value: Some(vec![101]), + extrinsics: Some(vec![NO_EXTRINSIC_INDEX].into_iter().collect()) }), + ].into_iter().collect()); + + assert_eq!(strip_extrinsic_index(&overlay.prospective.top), + vec![ + (vec![1], OverlayedValue { value: Some(vec![8]), + extrinsics: Some(vec![4].into_iter().collect()) }), + (vec![3], OverlayedValue { value: Some(vec![7]), + extrinsics: Some(vec![3].into_iter().collect()) }), + ].into_iter().collect()); + + overlay.commit_prospective(); + + assert_eq!(strip_extrinsic_index(&overlay.committed.top), + vec![ + (vec![1], OverlayedValue { value: Some(vec![8]), + extrinsics: Some(vec![0, 2, 4].into_iter().collect()) }), + (vec![3], OverlayedValue { value: Some(vec![7]), + extrinsics: Some(vec![1, 3].into_iter().collect()) }), + (vec![100], OverlayedValue { value: Some(vec![101]), + extrinsics: Some(vec![NO_EXTRINSIC_INDEX].into_iter().collect()) }), + ].into_iter().collect()); + + assert_eq!(overlay.prospective, + Default::default()); + } + + #[test] + fn next_storage_key_change_works() { + let mut overlay = OverlayedChanges::default(); + overlay.set_storage(vec![20], Some(vec![20])); + overlay.set_storage(vec![30], Some(vec![30])); + overlay.set_storage(vec![40], Some(vec![40])); + overlay.commit_prospective(); + overlay.set_storage(vec![10], Some(vec![10])); + overlay.set_storage(vec![30], None); + + // next_prospective < next_committed + let next_to_5 = overlay.next_storage_key_change(&[5]).unwrap(); + assert_eq!(next_to_5.0.to_vec(), vec![10]); + assert_eq!(next_to_5.1.value, Some(vec![10])); + + // next_committed < next_prospective + let next_to_10 = overlay.next_storage_key_change(&[10]).unwrap(); + assert_eq!(next_to_10.0.to_vec(), vec![20]); + assert_eq!(next_to_10.1.value, Some(vec![20])); + + // next_committed == next_prospective + let next_to_20 = overlay.next_storage_key_change(&[20]).unwrap(); + assert_eq!(next_to_20.0.to_vec(), vec![30]); + assert_eq!(next_to_20.1.value, None); + + // next_committed, no next_prospective + let next_to_30 = overlay.next_storage_key_change(&[30]).unwrap(); + assert_eq!(next_to_30.0.to_vec(), vec![40]); + assert_eq!(next_to_30.1.value, Some(vec![40])); + + overlay.set_storage(vec![50], Some(vec![50])); + // next_prospective, no next_committed + let next_to_40 = overlay.next_storage_key_change(&[40]).unwrap(); + assert_eq!(next_to_40.0.to_vec(), vec![50]); + assert_eq!(next_to_40.1.value, Some(vec![50])); + } + + #[test] + fn next_child_storage_key_change_works() { + let child = b"Child1".to_vec(); + let child_info = ChildInfo::new_default(b"uniqueid"); + let mut overlay = OverlayedChanges::default(); + overlay.set_child_storage(child.clone(), child_info, vec![20], Some(vec![20])); + overlay.set_child_storage(child.clone(), child_info, vec![30], Some(vec![30])); + overlay.set_child_storage(child.clone(), child_info, vec![40], Some(vec![40])); + overlay.commit_prospective(); + overlay.set_child_storage(child.clone(), child_info, vec![10], Some(vec![10])); + overlay.set_child_storage(child.clone(), child_info, vec![30], None); + + // next_prospective < next_committed + let next_to_5 = overlay.next_child_storage_key_change(&child, &[5]).unwrap(); + assert_eq!(next_to_5.0.to_vec(), vec![10]); + assert_eq!(next_to_5.1.value, Some(vec![10])); + + // next_committed < next_prospective + let next_to_10 = overlay.next_child_storage_key_change(&child, &[10]).unwrap(); + assert_eq!(next_to_10.0.to_vec(), vec![20]); + assert_eq!(next_to_10.1.value, Some(vec![20])); + + // next_committed == next_prospective + let next_to_20 = overlay.next_child_storage_key_change(&child, &[20]).unwrap(); + assert_eq!(next_to_20.0.to_vec(), vec![30]); + assert_eq!(next_to_20.1.value, None); + + // next_committed, no next_prospective + let next_to_30 = overlay.next_child_storage_key_change(&child, &[30]).unwrap(); + assert_eq!(next_to_30.0.to_vec(), vec![40]); + assert_eq!(next_to_30.1.value, Some(vec![40])); + + overlay.set_child_storage(child.clone(), child_info, vec![50], Some(vec![50])); + // next_prospective, no next_committed + let next_to_40 = overlay.next_child_storage_key_change(&child, &[40]).unwrap(); + assert_eq!(next_to_40.0.to_vec(), vec![50]); + assert_eq!(next_to_40.1.value, Some(vec![50])); + } +} diff --git a/primitives/state-machine/src/proving_backend.rs b/primitives/state-machine/src/proving_backend.rs new file mode 100644 index 0000000000000..70124927fdd2e --- /dev/null +++ b/primitives/state-machine/src/proving_backend.rs @@ -0,0 +1,541 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Proving state machine backend. + +use std::sync::Arc; +use parking_lot::RwLock; +use codec::{Decode, Encode, Codec}; +use log::debug; +use hash_db::{Hasher, HashDB, EMPTY_PREFIX, Prefix}; +use sp_trie::{ + MemoryDB, default_child_trie_root, read_trie_value_with, read_child_trie_value_with, + record_all_keys +}; +pub use sp_trie::Recorder; +pub use sp_trie::trie_types::{Layout, TrieError}; +use crate::trie_backend::TrieBackend; +use crate::trie_backend_essence::{Ephemeral, TrieBackendEssence, TrieBackendStorage}; +use crate::{Error, ExecutionError, Backend}; +use std::collections::{HashMap, HashSet}; +use crate::DBValue; +use sp_core::storage::ChildInfo; + +/// Patricia trie-based backend specialized in get value proofs. +pub struct ProvingBackendRecorder<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { + pub(crate) backend: &'a TrieBackendEssence, + pub(crate) proof_recorder: &'a mut Recorder, +} + +/// A proof that some set of key-value pairs are included in the storage trie. The proof contains +/// the storage values so that the partial storage backend can be reconstructed by a verifier that +/// does not already have access to the key-value pairs. +/// +/// The proof consists of the set of serialized nodes in the storage trie accessed when looking up +/// the keys covered by the proof. Verifying the proof requires constructing the partial trie from +/// the serialized nodes and performing the key lookups. +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +pub struct StorageProof { + trie_nodes: Vec>, +} + +impl StorageProof { + /// Constructs a storage proof from a subset of encoded trie nodes in a storage backend. + pub fn new(trie_nodes: Vec>) -> Self { + StorageProof { trie_nodes } + } + + /// Returns a new empty proof. + /// + /// An empty proof is capable of only proving trivial statements (ie. that an empty set of + /// key-value pairs exist in storage). + pub fn empty() -> Self { + StorageProof { + trie_nodes: Vec::new(), + } + } + + /// Returns whether this is an empty proof. + pub fn is_empty(&self) -> bool { + self.trie_nodes.is_empty() + } + + /// Create an iterator over trie nodes constructed from the proof. The nodes are not guaranteed + /// to be traversed in any particular order. + pub fn iter_nodes(self) -> StorageProofNodeIterator { + StorageProofNodeIterator::new(self) + } +} + +/// An iterator over trie nodes constructed from a storage proof. The nodes are not guaranteed to +/// be traversed in any particular order. +pub struct StorageProofNodeIterator { + inner: > as IntoIterator>::IntoIter, +} + +impl StorageProofNodeIterator { + fn new(proof: StorageProof) -> Self { + StorageProofNodeIterator { + inner: proof.trie_nodes.into_iter(), + } + } +} + +impl Iterator for StorageProofNodeIterator { + type Item = Vec; + + fn next(&mut self) -> Option { + self.inner.next() + } +} + +/// Merges multiple storage proofs covering potentially different sets of keys into one proof +/// covering all keys. The merged proof output may be smaller than the aggregate size of the input +/// proofs due to deduplication of trie nodes. +pub fn merge_storage_proofs(proofs: I) -> StorageProof + where I: IntoIterator +{ + let trie_nodes = proofs.into_iter() + .flat_map(|proof| proof.iter_nodes()) + .collect::>() + .into_iter() + .collect(); + StorageProof { trie_nodes } +} + +impl<'a, S, H> ProvingBackendRecorder<'a, S, H> + where + S: TrieBackendStorage, + H: Hasher, + H::Out: Codec, +{ + /// Produce proof for a key query. + pub fn storage(&mut self, key: &[u8]) -> Result>, String> { + let mut read_overlay = S::Overlay::default(); + let eph = Ephemeral::new( + self.backend.backend_storage(), + &mut read_overlay, + ); + + let map_e = |e| format!("Trie lookup error: {}", e); + + read_trie_value_with::, _, Ephemeral>( + &eph, + self.backend.root(), + key, + &mut *self.proof_recorder, + ).map_err(map_e) + } + + /// Produce proof for a child key query. + pub fn child_storage( + &mut self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8] + ) -> Result>, String> { + let root = self.storage(storage_key)? + .and_then(|r| Decode::decode(&mut &r[..]).ok()) + .unwrap_or(default_child_trie_root::>(storage_key)); + + let mut read_overlay = S::Overlay::default(); + let eph = Ephemeral::new( + self.backend.backend_storage(), + &mut read_overlay, + ); + + let map_e = |e| format!("Trie lookup error: {}", e); + + read_child_trie_value_with::, _, _>( + storage_key, + child_info.keyspace(), + &eph, + &root.as_ref(), + key, + &mut *self.proof_recorder + ).map_err(map_e) + } + + /// Produce proof for the whole backend. + pub fn record_all_keys(&mut self) { + let mut read_overlay = S::Overlay::default(); + let eph = Ephemeral::new( + self.backend.backend_storage(), + &mut read_overlay, + ); + + let mut iter = move || -> Result<(), Box>> { + let root = self.backend.root(); + record_all_keys::, _>(&eph, root, &mut *self.proof_recorder) + }; + + if let Err(e) = iter() { + debug!(target: "trie", "Error while recording all keys: {}", e); + } + } +} + +/// Global proof recorder, act as a layer over a hash db for recording queried +/// data. +pub type ProofRecorder = Arc::Out, Option>>>; + +/// Patricia trie-based backend which also tracks all touched storage trie values. +/// These can be sent to remote node and used as a proof of execution. +pub struct ProvingBackend<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> ( + TrieBackend, H>, +); + +/// Trie backend storage with its proof recorder. +pub struct ProofRecorderBackend<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { + backend: &'a S, + proof_recorder: ProofRecorder, +} + +impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> ProvingBackend<'a, S, H> + where H::Out: Codec +{ + /// Create new proving backend. + pub fn new(backend: &'a TrieBackend) -> Self { + let proof_recorder = Default::default(); + Self::new_with_recorder(backend, proof_recorder) + } + + /// Create new proving backend with the given recorder. + pub fn new_with_recorder( + backend: &'a TrieBackend, + proof_recorder: ProofRecorder, + ) -> Self { + let essence = backend.essence(); + let root = essence.root().clone(); + let recorder = ProofRecorderBackend { + backend: essence.backend_storage(), + proof_recorder: proof_recorder, + }; + ProvingBackend(TrieBackend::new(recorder, root)) + } + + /// Extracting the gathered unordered proof. + pub fn extract_proof(&self) -> StorageProof { + let trie_nodes = self.0.essence().backend_storage().proof_recorder + .read() + .iter() + .filter_map(|(_k, v)| v.as_ref().map(|v| v.to_vec())) + .collect(); + StorageProof::new(trie_nodes) + } +} + +impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> TrieBackendStorage + for ProofRecorderBackend<'a, S, H> +{ + type Overlay = S::Overlay; + + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { + if let Some(v) = self.proof_recorder.read().get(key) { + return Ok(v.clone()); + } + let backend_value = self.backend.get(key, prefix)?; + self.proof_recorder.write().insert(key.clone(), backend_value.clone()); + Ok(backend_value) + } +} + +impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> std::fmt::Debug + for ProvingBackend<'a, S, H> +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ProvingBackend") + } +} + +impl<'a, S, H> Backend for ProvingBackend<'a, S, H> + where + S: 'a + TrieBackendStorage, + H: 'a + Hasher, + H::Out: Ord + Codec, +{ + type Error = String; + type Transaction = S::Overlay; + type TrieBackendStorage = S; + + fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + self.0.storage(key) + } + + fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.0.child_storage(storage_key, child_info, key) + } + + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + f: F, + ) { + self.0.for_keys_in_child_storage(storage_key, child_info, f) + } + + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + self.0.next_storage_key(key) + } + + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.0.next_child_storage_key(storage_key, child_info, key) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + self.0.for_keys_with_prefix(prefix, f) + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.0.for_key_values_with_prefix(prefix, f) + } + + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + f: F, + ) { + self.0.for_child_keys_with_prefix(storage_key, child_info, prefix, f) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + self.0.pairs() + } + + fn keys(&self, prefix: &[u8]) -> Vec> { + self.0.keys(prefix) + } + + fn child_keys( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + ) -> Vec> { + self.0.child_keys(storage_key, child_info, prefix) + } + + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where I: IntoIterator, Option>)> + { + self.0.storage_root(delta) + } + + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (H::Out, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord + { + self.0.child_storage_root(storage_key, child_info, delta) + } +} + +/// Create proof check backend. +pub fn create_proof_check_backend( + root: H::Out, + proof: StorageProof, +) -> Result, H>, Box> +where + H: Hasher, + H::Out: Codec, +{ + let db = create_proof_check_backend_storage(proof); + + if db.contains(&root, EMPTY_PREFIX) { + Ok(TrieBackend::new(db, root)) + } else { + Err(Box::new(ExecutionError::InvalidProof)) + } +} + +/// Create in-memory storage of proof check backend. +pub fn create_proof_check_backend_storage( + proof: StorageProof, +) -> MemoryDB +where + H: Hasher, +{ + let mut db = MemoryDB::default(); + for item in proof.iter_nodes() { + db.insert(EMPTY_PREFIX, &item); + } + db +} + +#[cfg(test)] +mod tests { + use crate::InMemoryBackend; + use crate::trie_backend::tests::test_trie; + use super::*; + use sp_core::{Blake2Hasher, storage::ChildStorageKey}; + use crate::proving_backend::create_proof_check_backend; + use sp_trie::PrefixedMemoryDB; + + const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_1"); + const CHILD_INFO_2: ChildInfo<'static> = ChildInfo::new_default(b"unique_id_2"); + + fn test_proving<'a>( + trie_backend: &'a TrieBackend,Blake2Hasher>, + ) -> ProvingBackend<'a, PrefixedMemoryDB, Blake2Hasher> { + ProvingBackend::new(trie_backend) + } + + #[test] + fn proof_is_empty_until_value_is_read() { + let trie_backend = test_trie(); + assert!(test_proving(&trie_backend).extract_proof().is_empty()); + } + + #[test] + fn proof_is_non_empty_after_value_is_read() { + let trie_backend = test_trie(); + let backend = test_proving(&trie_backend); + assert_eq!(backend.storage(b"key").unwrap(), Some(b"value".to_vec())); + assert!(!backend.extract_proof().is_empty()); + } + + #[test] + fn proof_is_invalid_when_does_not_contains_root() { + use sp_core::H256; + let result = create_proof_check_backend::( + H256::from_low_u64_be(1), + StorageProof::empty() + ); + assert!(result.is_err()); + } + + #[test] + fn passes_throgh_backend_calls() { + let trie_backend = test_trie(); + let proving_backend = test_proving(&trie_backend); + assert_eq!(trie_backend.storage(b"key").unwrap(), proving_backend.storage(b"key").unwrap()); + assert_eq!(trie_backend.pairs(), proving_backend.pairs()); + + let (trie_root, mut trie_mdb) = trie_backend.storage_root(::std::iter::empty()); + let (proving_root, mut proving_mdb) = proving_backend.storage_root(::std::iter::empty()); + assert_eq!(trie_root, proving_root); + assert_eq!(trie_mdb.drain(), proving_mdb.drain()); + } + + #[test] + fn proof_recorded_and_checked() { + let contents = (0..64).map(|i| (vec![i], Some(vec![i]))).collect::>(); + let in_memory = InMemoryBackend::::default(); + let mut in_memory = in_memory.update(vec![(None, contents)]); + let in_memory_root = in_memory.storage_root(::std::iter::empty()).0; + (0..64).for_each(|i| assert_eq!(in_memory.storage(&[i]).unwrap().unwrap(), vec![i])); + + let trie = in_memory.as_trie_backend().unwrap(); + let trie_root = trie.storage_root(::std::iter::empty()).0; + assert_eq!(in_memory_root, trie_root); + (0..64).for_each(|i| assert_eq!(trie.storage(&[i]).unwrap().unwrap(), vec![i])); + + let proving = ProvingBackend::new(trie); + assert_eq!(proving.storage(&[42]).unwrap().unwrap(), vec![42]); + + let proof = proving.extract_proof(); + + let proof_check = create_proof_check_backend::(in_memory_root.into(), proof).unwrap(); + assert_eq!(proof_check.storage(&[42]).unwrap().unwrap(), vec![42]); + } + + #[test] + fn proof_recorded_and_checked_with_child() { + let subtrie1 = ChildStorageKey::from_slice(b":child_storage:default:sub1").unwrap(); + let subtrie2 = ChildStorageKey::from_slice(b":child_storage:default:sub2").unwrap(); + let own1 = subtrie1.into_owned(); + let own2 = subtrie2.into_owned(); + let contents = vec![ + (None, (0..64).map(|i| (vec![i], Some(vec![i]))).collect()), + (Some((own1.clone(), CHILD_INFO_1.to_owned())), + (28..65).map(|i| (vec![i], Some(vec![i]))).collect()), + (Some((own2.clone(), CHILD_INFO_2.to_owned())), + (10..15).map(|i| (vec![i], Some(vec![i]))).collect()), + ]; + let in_memory = InMemoryBackend::::default(); + let mut in_memory = in_memory.update(contents); + let in_memory_root = in_memory.full_storage_root::<_, Vec<_>, _>( + ::std::iter::empty(), + in_memory.child_storage_keys().map(|k|(k.0.to_vec(), Vec::new(), k.1.to_owned())) + ).0; + (0..64).for_each(|i| assert_eq!( + in_memory.storage(&[i]).unwrap().unwrap(), + vec![i] + )); + (28..65).for_each(|i| assert_eq!( + in_memory.child_storage(&own1[..], CHILD_INFO_1, &[i]).unwrap().unwrap(), + vec![i] + )); + (10..15).for_each(|i| assert_eq!( + in_memory.child_storage(&own2[..], CHILD_INFO_2, &[i]).unwrap().unwrap(), + vec![i] + )); + + let trie = in_memory.as_trie_backend().unwrap(); + let trie_root = trie.storage_root(::std::iter::empty()).0; + assert_eq!(in_memory_root, trie_root); + (0..64).for_each(|i| assert_eq!( + trie.storage(&[i]).unwrap().unwrap(), + vec![i] + )); + + let proving = ProvingBackend::new(trie); + assert_eq!(proving.storage(&[42]).unwrap().unwrap(), vec![42]); + + let proof = proving.extract_proof(); + + let proof_check = create_proof_check_backend::( + in_memory_root.into(), + proof + ).unwrap(); + assert!(proof_check.storage(&[0]).is_err()); + assert_eq!(proof_check.storage(&[42]).unwrap().unwrap(), vec![42]); + // note that it is include in root because proof close + assert_eq!(proof_check.storage(&[41]).unwrap().unwrap(), vec![41]); + assert_eq!(proof_check.storage(&[64]).unwrap(), None); + + let proving = ProvingBackend::new(trie); + assert_eq!(proving.child_storage(&own1[..], CHILD_INFO_1, &[64]), Ok(Some(vec![64]))); + + let proof = proving.extract_proof(); + let proof_check = create_proof_check_backend::( + in_memory_root.into(), + proof + ).unwrap(); + assert_eq!( + proof_check.child_storage(&own1[..], CHILD_INFO_1, &[64]).unwrap().unwrap(), + vec![64] + ); + } +} diff --git a/primitives/state-machine/src/stats.rs b/primitives/state-machine/src/stats.rs new file mode 100644 index 0000000000000..38286be545af5 --- /dev/null +++ b/primitives/state-machine/src/stats.rs @@ -0,0 +1,62 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Usage statistics for state db + +use std::time::{Instant, Duration}; + +/// Measured count of operations and total bytes. +#[derive(Clone, Debug, Default)] +pub struct UsageUnit { + /// Number of operations. + pub ops: u64, + /// Number of bytes. + pub bytes: u64, +} + +/// Usage statistics for state backend. +#[derive(Clone, Debug)] +pub struct UsageInfo { + /// Read statistics (total). + pub reads: UsageUnit, + /// Write statistics. + pub writes: UsageUnit, + /// Cache read statistics. + pub cache_reads: UsageUnit, + /// Memory used. + pub memory: usize, + + /// Moment at which current statistics has been started being collected. + pub started: Instant, + /// Timespan of the statistics. + pub span: Duration, +} + +impl UsageInfo { + /// Empty statistics. + /// + /// Means no data was collected. + pub fn empty() -> Self { + Self { + reads: UsageUnit::default(), + writes: UsageUnit::default(), + cache_reads: UsageUnit::default(), + memory: 0, + started: Instant::now(), + span: Default::default(), + } + } +} \ No newline at end of file diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs new file mode 100644 index 0000000000000..1baf6d6b4da70 --- /dev/null +++ b/primitives/state-machine/src/testing.rs @@ -0,0 +1,220 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test implementation for Externalities. + +use std::any::{Any, TypeId}; +use hash_db::Hasher; +use crate::{ + backend::Backend, OverlayedChanges, StorageTransactionCache, ext::Ext, InMemoryBackend, + changes_trie::{ + InMemoryStorage as ChangesTrieInMemoryStorage, + BlockNumber as ChangesTrieBlockNumber, + }, +}; +use sp_core::{ + storage::{ + well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES, is_child_storage_key}, + Storage, + }, + Blake2Hasher, +}; +use codec::Encode; +use sp_externalities::{Extensions, Extension}; + +/// Simple HashMap-based Externalities impl. +pub struct TestExternalities +where + H::Out: codec::Codec, +{ + overlay: OverlayedChanges, + storage_transaction_cache: StorageTransactionCache< + as Backend>::Transaction, H, N + >, + backend: InMemoryBackend, + changes_trie_storage: ChangesTrieInMemoryStorage, + extensions: Extensions, +} + +impl TestExternalities + where + H::Out: Ord + 'static + codec::Codec +{ + /// Get externalities implementation. + pub fn ext(&mut self) -> Ext, ChangesTrieInMemoryStorage> { + Ext::new( + &mut self.overlay, + &mut self.storage_transaction_cache, + &self.backend, + Some(&self.changes_trie_storage), + Some(&mut self.extensions), + ) + } + + /// Create a new instance of `TestExternalities` with storage. + pub fn new(storage: Storage) -> Self { + Self::new_with_code(&[], storage) + } + + /// Create a new instance of `TestExternalities` with code and storage. + pub fn new_with_code(code: &[u8], mut storage: Storage) -> Self { + let mut overlay = OverlayedChanges::default(); + + assert!(storage.top.keys().all(|key| !is_child_storage_key(key))); + assert!(storage.children.keys().all(|key| is_child_storage_key(key))); + + super::set_changes_trie_config( + &mut overlay, + storage.top.get(&CHANGES_TRIE_CONFIG.to_vec()).cloned(), + false, + ).expect("changes trie configuration is correct in test env; qed"); + + storage.top.insert(HEAP_PAGES.to_vec(), 8u64.encode()); + storage.top.insert(CODE.to_vec(), code.to_vec()); + + TestExternalities { + overlay, + changes_trie_storage: ChangesTrieInMemoryStorage::new(), + backend: storage.into(), + extensions: Default::default(), + storage_transaction_cache: Default::default(), + } + } + + /// Insert key/value into backend + pub fn insert(&mut self, k: Vec, v: Vec) { + self.backend = self.backend.update(vec![(None, vec![(k, Some(v))])]); + } + + /// Registers the given extension for this instance. + pub fn register_extension(&mut self, ext: E) { + self.extensions.register(ext); + } + + /// Get mutable reference to changes trie storage. + pub fn changes_trie_storage(&mut self) -> &mut ChangesTrieInMemoryStorage { + &mut self.changes_trie_storage + } + + /// Return a new backend with all pending value. + pub fn commit_all(&self) -> InMemoryBackend { + let top: Vec<_> = self.overlay.committed.top.clone().into_iter() + .chain(self.overlay.prospective.top.clone().into_iter()) + .map(|(k, v)| (k, v.value)).collect(); + let mut transaction = vec![(None, top)]; + + self.overlay.committed.children.clone().into_iter() + .chain(self.overlay.prospective.children.clone().into_iter()) + .for_each(|(keyspace, (map, child_info))| { + transaction.push(( + Some((keyspace, child_info)), + map.into_iter() + .map(|(k, v)| (k, v.value)) + .collect::>(), + )) + }); + + self.backend.update(transaction) + } + + /// Execute the given closure while `self` is set as externalities. + /// + /// Returns the result of the given closure. + pub fn execute_with(&mut self, execute: impl FnOnce() -> R) -> R { + let mut ext = self.ext(); + sp_externalities::set_and_run_with_externalities(&mut ext, execute) + } +} + +impl std::fmt::Debug for TestExternalities + where H::Out: codec::Codec, +{ + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "overlay: {:?}\nbackend: {:?}", self.overlay, self.backend.pairs()) + } +} + +impl PartialEq for TestExternalities + where + H::Out: Ord + 'static + codec::Codec +{ + /// This doesn't test if they are in the same state, only if they contains the + /// same data at this state + fn eq(&self, other: &TestExternalities) -> bool { + self.commit_all().eq(&other.commit_all()) + } +} + +impl Default for TestExternalities + where + H::Out: Ord + 'static + codec::Codec, +{ + fn default() -> Self { Self::new(Default::default()) } +} + +impl From for TestExternalities + where + H::Out: Ord + 'static + codec::Codec, +{ + fn from(storage: Storage) -> Self { + Self::new(storage) + } +} + +impl sp_externalities::ExtensionStore for TestExternalities where + H: Hasher, + H::Out: codec::Codec, + N: ChangesTrieBlockNumber, +{ + fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> { + self.extensions.get_mut(type_id) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::traits::Externalities; + use hex_literal::hex; + + #[test] + fn commit_should_work() { + let mut ext = TestExternalities::::default(); + let mut ext = ext.ext(); + ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); + ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); + ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); + const ROOT: [u8; 32] = hex!("2a340d3dfd52f5992c6b117e9e45f479e6da5afffafeb26ab619cf137a95aeb8"); + assert_eq!(&ext.storage_root()[..], &ROOT); + } + + #[test] + fn set_and_retrieve_code() { + let mut ext = TestExternalities::::default(); + let mut ext = ext.ext(); + + let code = vec![1, 2, 3]; + ext.set_storage(CODE.to_vec(), code.clone()); + + assert_eq!(&ext.storage(CODE).unwrap(), &code); + } + + #[test] + fn check_send() { + fn assert_send() {} + assert_send::>(); + } +} diff --git a/core/state-machine/src/trie_backend.rs b/primitives/state-machine/src/trie_backend.rs similarity index 76% rename from core/state-machine/src/trie_backend.rs rename to primitives/state-machine/src/trie_backend.rs index 432ccf3e75f0e..1920ea40a88b5 100644 --- a/core/state-machine/src/trie_backend.rs +++ b/primitives/state-machine/src/trie_backend.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -18,17 +18,19 @@ use log::{warn, debug}; use hash_db::Hasher; -use trie::{Trie, delta_trie_root, default_child_trie_root, child_delta_trie_root}; -use trie::trie_types::{TrieDB, TrieError, Layout}; +use sp_trie::{Trie, delta_trie_root, default_child_trie_root, child_delta_trie_root}; +use sp_trie::trie_types::{TrieDB, TrieError, Layout}; use crate::trie_backend_essence::{TrieBackendEssence, TrieBackendStorage, Ephemeral}; use crate::Backend; +use sp_core::storage::ChildInfo; +use codec::{Codec, Decode}; /// Patricia trie-based backend. Transaction type is an overlay of changes to commit. pub struct TrieBackend, H: Hasher> { essence: TrieBackendEssence, } -impl, H: Hasher> TrieBackend { +impl, H: Hasher> TrieBackend where H::Out: Codec { /// Create new trie-based backend. pub fn new(storage: S, root: H::Out) -> Self { TrieBackend { @@ -64,7 +66,7 @@ impl, H: Hasher> std::fmt::Debug for TrieBackend } impl, H: Hasher> Backend for TrieBackend where - H::Out: Ord, + H::Out: Ord + Codec, { type Error = String; type Transaction = S::Overlay; @@ -74,8 +76,26 @@ impl, H: Hasher> Backend for TrieBackend where self.essence.storage(key) } - fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { - self.essence.child_storage(storage_key, key) + fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.essence.child_storage(storage_key, child_info, key) + } + + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + self.essence.next_storage_key(key) + } + + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.essence.next_child_storage_key(storage_key, child_info, key) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { @@ -86,12 +106,23 @@ impl, H: Hasher> Backend for TrieBackend where self.essence.for_key_values_with_prefix(prefix, f) } - fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { - self.essence.for_keys_in_child_storage(storage_key, f) + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + f: F, + ) { + self.essence.for_keys_in_child_storage(storage_key, child_info, f) } - fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { - self.essence.for_child_keys_with_prefix(storage_key, prefix, f) + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + f: F, + ) { + self.essence.for_child_keys_with_prefix(storage_key, child_info, prefix, f) } fn pairs(&self) -> Vec<(Vec, Vec)> { @@ -159,16 +190,22 @@ impl, H: Hasher> Backend for TrieBackend where (root, write_overlay) } - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)>, - H::Out: Ord + H::Out: Ord, { let default_root = default_child_trie_root::>(storage_key); let mut write_overlay = S::Overlay::default(); let mut root = match self.storage(storage_key) { - Ok(value) => value.unwrap_or(default_root.clone()), + Ok(value) => + value.and_then(|r| Decode::decode(&mut &r[..]).ok()).unwrap_or(default_root.clone()), Err(e) => { warn!(target: "trie", "Failed to read child storage root: {}", e); default_root.clone() @@ -181,10 +218,11 @@ impl, H: Hasher> Backend for TrieBackend where &mut write_overlay, ); - match child_delta_trie_root::, _, _, _, _>( + match child_delta_trie_root::, _, _, _, _, _>( storage_key, + child_info.keyspace(), &mut eph, - root.clone(), + root, delta ) { Ok(ret) => root = ret, @@ -205,15 +243,21 @@ impl, H: Hasher> Backend for TrieBackend where #[cfg(test)] pub mod tests { use std::collections::HashSet; - use primitives::{Blake2Hasher, H256}; + use sp_core::{Blake2Hasher, H256}; use codec::Encode; - use trie::{TrieMut, PrefixedMemoryDB, trie_types::TrieDBMut}; + use sp_trie::{TrieMut, PrefixedMemoryDB, trie_types::TrieDBMut, KeySpacedDBMut}; use super::*; + const CHILD_KEY_1: &[u8] = b":child_storage:default:sub1"; + + const CHILD_UUID_1: &[u8] = b"unique_id_1"; + const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(CHILD_UUID_1); + fn test_db() -> (PrefixedMemoryDB, H256) { let mut root = H256::default(); let mut mdb = PrefixedMemoryDB::::default(); { + let mut mdb = KeySpacedDBMut::new(&mut mdb, CHILD_UUID_1); let mut trie = TrieDBMut::new(&mut mdb, &mut root); trie.insert(b"value3", &[142]).expect("insert failed"); trie.insert(b"value4", &[124]).expect("insert failed"); @@ -223,7 +267,7 @@ pub mod tests { let mut sub_root = Vec::new(); root.encode_to(&mut sub_root); let mut trie = TrieDBMut::new(&mut mdb, &mut root); - trie.insert(b":child_storage:default:sub1", &sub_root).expect("insert failed"); + trie.insert(CHILD_KEY_1, &sub_root[..]).expect("insert failed"); trie.insert(b"key", b"value").expect("insert failed"); trie.insert(b"value1", &[42]).expect("insert failed"); trie.insert(b"value2", &[24]).expect("insert failed"); @@ -245,6 +289,15 @@ pub mod tests { assert_eq!(test_trie().storage(b"key").unwrap(), Some(b"value".to_vec())); } + #[test] + fn read_from_child_storage_returns_some() { + let test_trie = test_trie(); + assert_eq!( + test_trie.child_storage(CHILD_KEY_1, CHILD_INFO_1, b"value3").unwrap(), + Some(vec![142u8]), + ); + } + #[test] fn read_from_storage_returns_none() { assert_eq!(test_trie().storage(b"non-existing-key").unwrap(), None); diff --git a/primitives/state-machine/src/trie_backend_essence.rs b/primitives/state-machine/src/trie_backend_essence.rs new file mode 100644 index 0000000000000..f7f5006f41dab --- /dev/null +++ b/primitives/state-machine/src/trie_backend_essence.rs @@ -0,0 +1,498 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Trie-based state machine backend essence used to read values +//! from storage. + +use std::ops::Deref; +use std::sync::Arc; +use log::{debug, warn}; +use hash_db::{self, Hasher, EMPTY_PREFIX, Prefix}; +use sp_trie::{Trie, MemoryDB, PrefixedMemoryDB, DBValue, + default_child_trie_root, read_trie_value, read_child_trie_value, + for_keys_in_child_trie, KeySpacedDB}; +use sp_trie::trie_types::{TrieDB, TrieError, Layout}; +use crate::backend::Consolidate; +use sp_core::storage::ChildInfo; +use codec::Encode; + +/// Patricia trie-based storage trait. +pub trait Storage: Send + Sync { + /// Get a trie node. + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String>; +} + +/// Patricia trie-based pairs storage essence. +pub struct TrieBackendEssence, H: Hasher> { + storage: S, + root: H::Out, +} + +impl, H: Hasher> TrieBackendEssence where H::Out: Encode { + /// Create new trie-based backend. + pub fn new(storage: S, root: H::Out) -> Self { + TrieBackendEssence { + storage, + root, + } + } + + /// Get backend storage reference. + pub fn backend_storage(&self) -> &S { + &self.storage + } + + /// Get trie root. + pub fn root(&self) -> &H::Out { + &self.root + } + + /// Consumes self and returns underlying storage. + pub fn into_storage(self) -> S { + self.storage + } + + /// Return the next key in the trie i.e. the minimum key that is strictly superior to `key` in + /// lexicographic order. + pub fn next_storage_key(&self, key: &[u8]) -> Result>, String> { + self.next_storage_key_from_root(&self.root, None, key) + } + + /// Return the next key in the child trie i.e. the minimum key that is strictly superior to + /// `key` in lexicographic order. + pub fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, String> { + let child_root = match self.storage(storage_key)? { + Some(child_root) => child_root, + None => return Ok(None), + }; + + let mut hash = H::Out::default(); + + if child_root.len() != hash.as_ref().len() { + return Err(format!("Invalid child storage hash at {:?}", storage_key)); + } + // note: child_root and hash must be same size, panics otherwise. + hash.as_mut().copy_from_slice(&child_root[..]); + + self.next_storage_key_from_root(&hash, Some(child_info), key) + } + + /// Return next key from main trie or child trie by providing corresponding root. + fn next_storage_key_from_root( + &self, + root: &H::Out, + child_info: Option, + key: &[u8], + ) -> Result>, String> { + let mut read_overlay = S::Overlay::default(); + let eph = Ephemeral { + storage: &self.storage, + overlay: &mut read_overlay, + }; + let dyn_eph: &dyn hash_db::HashDBRef<_, _>; + let keyspace_eph; + if let Some(child_info) = child_info.as_ref() { + keyspace_eph = KeySpacedDB::new(&eph, child_info.keyspace()); + dyn_eph = &keyspace_eph; + } else { + dyn_eph = &eph; + } + + let trie = TrieDB::::new(dyn_eph, root) + .map_err(|e| format!("TrieDB creation error: {}", e))?; + let mut iter = trie.iter() + .map_err(|e| format!("TrieDB iteration error: {}", e))?; + + // The key just after the one given in input, basically `key++0`. + // Note: We are sure this is the next key if: + // * size of key has no limit (i.e. we can always add 0 to the path), + // * and no keys can be inserted between `key` and `key++0` (this is ensured by sp-io). + let mut potential_next_key = Vec::with_capacity(key.len() + 1); + potential_next_key.extend_from_slice(key); + potential_next_key.push(0); + + iter.seek(&potential_next_key) + .map_err(|e| format!("TrieDB iterator seek error: {}", e))?; + + let next_element = iter.next(); + + let next_key = if let Some(next_element) = next_element { + let (next_key, _) = next_element + .map_err(|e| format!("TrieDB iterator next error: {}", e))?; + Some(next_key) + } else { + None + }; + + Ok(next_key) + } + + /// Get the value of storage at given key. + pub fn storage(&self, key: &[u8]) -> Result>, String> { + let mut read_overlay = S::Overlay::default(); + let eph = Ephemeral { + storage: &self.storage, + overlay: &mut read_overlay, + }; + + let map_e = |e| format!("Trie lookup error: {}", e); + + read_trie_value::, _>(&eph, &self.root, key).map_err(map_e) + } + + /// Get the value of child storage at given key. + pub fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, String> { + let root = self.storage(storage_key)? + .unwrap_or(default_child_trie_root::>(storage_key).encode()); + + let mut read_overlay = S::Overlay::default(); + let eph = Ephemeral { + storage: &self.storage, + overlay: &mut read_overlay, + }; + + let map_e = |e| format!("Trie lookup error: {}", e); + + read_child_trie_value::, _>(storage_key, child_info.keyspace(), &eph, &root, key) + .map_err(map_e) + } + + /// Retrieve all entries keys of child storage and call `f` for each of those keys. + pub fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + f: F, + ) { + let root = match self.storage(storage_key) { + Ok(v) => v.unwrap_or(default_child_trie_root::>(storage_key).encode()), + Err(e) => { + debug!(target: "trie", "Error while iterating child storage: {}", e); + return; + } + }; + + let mut read_overlay = S::Overlay::default(); + let eph = Ephemeral { + storage: &self.storage, + overlay: &mut read_overlay, + }; + + if let Err(e) = for_keys_in_child_trie::, _, Ephemeral>( + storage_key, + child_info.keyspace(), + &eph, + &root, + f, + ) { + debug!(target: "trie", "Error while iterating child storage: {}", e); + } + } + + /// Execute given closure for all keys starting with prefix. + pub fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + mut f: F, + ) { + let root_vec = match self.storage(storage_key) { + Ok(v) => v.unwrap_or(default_child_trie_root::>(storage_key).encode()), + Err(e) => { + debug!(target: "trie", "Error while iterating child storage: {}", e); + return; + } + }; + let mut root = H::Out::default(); + root.as_mut().copy_from_slice(&root_vec); + self.keys_values_with_prefix_inner(&root, prefix, |k, _v| f(k), Some(child_info)) + } + + /// Execute given closure for all keys starting with prefix. + pub fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { + self.keys_values_with_prefix_inner(&self.root, prefix, |k, _v| f(k), None) + } + + fn keys_values_with_prefix_inner( + &self, + root: &H::Out, + prefix: &[u8], + mut f: F, + child_info: Option, + ) { + let mut read_overlay = S::Overlay::default(); + let eph = Ephemeral { + storage: &self.storage, + overlay: &mut read_overlay, + }; + + let mut iter = move |db| -> Result<(), Box>> { + let trie = TrieDB::::new(db, root)?; + let mut iter = trie.iter()?; + + iter.seek(prefix)?; + + for x in iter { + let (key, value) = x?; + + if !key.starts_with(prefix) { + break; + } + + f(&key, &value); + } + + Ok(()) + }; + + let result = if let Some(child_info) = child_info { + let db = KeySpacedDB::new(&eph, child_info.keyspace()); + iter(&db) + } else { + iter(&eph) + }; + if let Err(e) = result { + debug!(target: "trie", "Error while iterating by prefix: {}", e); + } + } + + /// Execute given closure for all key and values starting with prefix. + pub fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.keys_values_with_prefix_inner(&self.root, prefix, f, None) + } +} + +pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { + storage: &'a S, + overlay: &'a mut S::Overlay, +} + +impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> hash_db::AsPlainDB + for Ephemeral<'a, S, H> +{ + fn as_plain_db<'b>(&'b self) -> &'b (dyn hash_db::PlainDB + 'b) { self } + fn as_plain_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::PlainDB + 'b) { + self + } +} + +impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> hash_db::AsHashDB + for Ephemeral<'a, S, H> +{ + fn as_hash_db<'b>(&'b self) -> &'b (dyn hash_db::HashDB + 'b) { self } + fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB + 'b) { self } +} + +impl<'a, S: TrieBackendStorage, H: Hasher> Ephemeral<'a, S, H> { + pub fn new(storage: &'a S, overlay: &'a mut S::Overlay) -> Self { + Ephemeral { + storage, + overlay, + } + } +} + +impl<'a, S: 'a + TrieBackendStorage, H: Hasher> hash_db::PlainDB + for Ephemeral<'a, S, H> +{ + fn get(&self, key: &H::Out) -> Option { + if let Some(val) = hash_db::HashDB::get(self.overlay, key, EMPTY_PREFIX) { + Some(val) + } else { + match self.storage.get(&key, EMPTY_PREFIX) { + Ok(x) => x, + Err(e) => { + warn!(target: "trie", "Failed to read from DB: {}", e); + None + }, + } + } + } + + fn contains(&self, key: &H::Out) -> bool { + hash_db::HashDB::get(self, key, EMPTY_PREFIX).is_some() + } + + fn emplace(&mut self, key: H::Out, value: DBValue) { + hash_db::HashDB::emplace(self.overlay, key, EMPTY_PREFIX, value) + } + + fn remove(&mut self, key: &H::Out) { + hash_db::HashDB::remove(self.overlay, key, EMPTY_PREFIX) + } +} + +impl<'a, S: 'a + TrieBackendStorage, H: Hasher> hash_db::PlainDBRef + for Ephemeral<'a, S, H> +{ + 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> +{ + fn get(&self, key: &H::Out, prefix: Prefix) -> Option { + if let Some(val) = hash_db::HashDB::get(self.overlay, key, prefix) { + Some(val) + } else { + match self.storage.get(&key, prefix) { + Ok(x) => x, + Err(e) => { + warn!(target: "trie", "Failed to read from DB: {}", e); + None + }, + } + } + } + + fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { + hash_db::HashDB::get(self, key, prefix).is_some() + } + + fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out { + hash_db::HashDB::insert(self.overlay, prefix, value) + } + + fn emplace(&mut self, key: H::Out, prefix: Prefix, value: DBValue) { + hash_db::HashDB::emplace(self.overlay, key, prefix, value) + } + + fn remove(&mut self, key: &H::Out, prefix: Prefix) { + hash_db::HashDB::remove(self.overlay, key, prefix) + } +} + +impl<'a, S: 'a + TrieBackendStorage, H: Hasher> hash_db::HashDBRef + for Ephemeral<'a, S, H> +{ + fn get(&self, key: &H::Out, prefix: Prefix) -> Option { + hash_db::HashDB::get(self, key, prefix) + } + + fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { + hash_db::HashDB::contains(self, key, prefix) + } +} + +/// Key-value pairs storage that is used by trie backend essence. +pub trait TrieBackendStorage: Send + Sync { + /// Type of in-memory overlay. + type Overlay: hash_db::HashDB + Default + Consolidate; + /// Get the value stored at key. + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String>; +} + +// This implementation is used by normal storage trie clients. +impl TrieBackendStorage for Arc> { + type Overlay = PrefixedMemoryDB; + + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { + Storage::::get(self.deref(), key, prefix) + } +} + +// This implementation is used by test storage trie clients. +impl TrieBackendStorage for PrefixedMemoryDB { + type Overlay = PrefixedMemoryDB; + + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { + Ok(hash_db::HashDB::get(self, key, prefix)) + } +} + +impl TrieBackendStorage for MemoryDB { + type Overlay = MemoryDB; + + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { + Ok(hash_db::HashDB::get(self, key, prefix)) + } +} + +#[cfg(test)] +mod test { + use sp_core::{Blake2Hasher, H256}; + use sp_trie::{TrieMut, PrefixedMemoryDB, trie_types::TrieDBMut, KeySpacedDBMut}; + use super::*; + + #[test] + fn next_storage_key_and_next_child_storage_key_work() { + let child_info = ChildInfo::new_default(b"uniqueid"); + // Contains values + let mut root_1 = H256::default(); + // Contains child trie + let mut root_2 = H256::default(); + + let mut mdb = PrefixedMemoryDB::::default(); + { + let mut trie = TrieDBMut::new(&mut mdb, &mut root_1); + trie.insert(b"3", &[1]).expect("insert failed"); + trie.insert(b"4", &[1]).expect("insert failed"); + trie.insert(b"6", &[1]).expect("insert failed"); + } + { + let mut mdb = KeySpacedDBMut::new(&mut mdb, child_info.keyspace()); + // reuse of root_1 implicitly assert child trie root is same + // as top trie (contents must remain the same). + let mut trie = TrieDBMut::new(&mut mdb, &mut root_1); + trie.insert(b"3", &[1]).expect("insert failed"); + trie.insert(b"4", &[1]).expect("insert failed"); + trie.insert(b"6", &[1]).expect("insert failed"); + } + { + let mut trie = TrieDBMut::new(&mut mdb, &mut root_2); + trie.insert(b"MyChild", root_1.as_ref()).expect("insert failed"); + }; + + let essence_1 = TrieBackendEssence::new(mdb, root_1); + + assert_eq!(essence_1.next_storage_key(b"2"), Ok(Some(b"3".to_vec()))); + assert_eq!(essence_1.next_storage_key(b"3"), Ok(Some(b"4".to_vec()))); + assert_eq!(essence_1.next_storage_key(b"4"), Ok(Some(b"6".to_vec()))); + assert_eq!(essence_1.next_storage_key(b"5"), Ok(Some(b"6".to_vec()))); + assert_eq!(essence_1.next_storage_key(b"6"), Ok(None)); + + let mdb = essence_1.into_storage(); + let essence_2 = TrieBackendEssence::new(mdb, root_2); + + assert_eq!( + essence_2.next_child_storage_key(b"MyChild", child_info, b"2"), Ok(Some(b"3".to_vec())) + ); + assert_eq!( + essence_2.next_child_storage_key(b"MyChild", child_info, b"3"), Ok(Some(b"4".to_vec())) + ); + assert_eq!( + essence_2.next_child_storage_key(b"MyChild", child_info, b"4"), Ok(Some(b"6".to_vec())) + ); + assert_eq!( + essence_2.next_child_storage_key(b"MyChild", child_info, b"5"), Ok(Some(b"6".to_vec())) + ); + assert_eq!( + essence_2.next_child_storage_key(b"MyChild", child_info, b"6"), Ok(None) + ); + } +} diff --git a/primitives/std/Cargo.toml b/primitives/std/Cargo.toml new file mode 100644 index 0000000000000..7fdf7d1144b7b --- /dev/null +++ b/primitives/std/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sp-std" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[features] +default = ["std"] +std = [] diff --git a/primitives/std/src/lib.rs b/primitives/std/src/lib.rs new file mode 100644 index 0000000000000..3fcf5daeb4b00 --- /dev/null +++ b/primitives/std/src/lib.rs @@ -0,0 +1,80 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Lowest-abstraction level for the Substrate runtime: just exports useful primitives from std +//! or client/alloc to be used with any code that depends on the runtime. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] + +#![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.")] + +#[macro_export] +macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) +} + +/// Feature gate some code that should only be run when `std` feature is enabled. +/// +/// # Example +/// +/// ``` +/// use sp_std::if_std; +/// +/// if_std! { +/// // This code is only being compiled and executed when the `std` feature is enabled. +/// println!("Hello native world"); +/// } +/// ``` +#[cfg(feature = "std")] +#[macro_export] +macro_rules! if_std { + ( $( $code:tt )* ) => { + $( $code )* + } +} + +#[cfg(not(feature = "std"))] +#[macro_export] +macro_rules! if_std { + ( $( $code:tt )* ) => {} +} + +#[cfg(feature = "std")] +include!("../with_std.rs"); + +#[cfg(not(feature = "std"))] +include!("../without_std.rs"); + +/// Prelude of common useful imports. +/// +/// This should include only things which are in the normal std prelude. +pub mod prelude { + pub use crate::vec::Vec; + pub use crate::boxed::Box; + pub use crate::cmp::{Eq, PartialEq, Reverse}; + 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/primitives/std/with_std.rs b/primitives/std/with_std.rs new file mode 100644 index 0000000000000..657d51dbf193c --- /dev/null +++ b/primitives/std/with_std.rs @@ -0,0 +1,44 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +pub use std::alloc; +pub use std::any; +pub use std::borrow; +pub use std::boxed; +pub use std::cell; +pub use std::clone; +pub use std::cmp; +pub use std::convert; +pub use std::default; +pub use std::fmt; +pub use std::hash; +pub use std::iter; +pub use std::marker; +pub use std::mem; +pub use std::num; +pub use std::ops; +pub use std::ptr; +pub use std::rc; +pub use std::result; +pub use std::slice; +pub use std::str; +pub use std::vec; + +pub mod collections { + pub use std::collections::btree_map; + pub use std::collections::btree_set; + pub use std::collections::vec_deque; +} diff --git a/primitives/std/without_std.rs b/primitives/std/without_std.rs new file mode 100755 index 0000000000000..ad587531ddc97 --- /dev/null +++ b/primitives/std/without_std.rs @@ -0,0 +1,54 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +pub extern crate alloc; + +pub use alloc::boxed; +pub use alloc::rc; +pub use alloc::vec; +pub use core::any; +pub use core::cell; +pub use core::clone; +pub use core::cmp; +pub use core::convert; +pub use core::default; +pub use core::fmt; +pub use core::hash; +pub use core::intrinsics; +pub use core::iter; +pub use core::marker; +pub use core::mem; +pub use core::num; +pub use core::ops; +pub use core::ptr; +pub use core::result; +pub use core::slice; +// Allow intepreting vectors of bytes as strings, but not constructing them. +pub use core::str; +// We are trying to avoid certain things here, such as `core::string` +// (if you need `String` you are probably doing something wrong, since +// runtime doesn't require anything human readable). + +pub mod collections { + pub use alloc::collections::btree_map; + pub use alloc::collections::btree_set; + pub use alloc::collections::vec_deque; +} + +pub mod borrow { + pub use core::borrow::*; + pub use alloc::borrow::*; +} diff --git a/primitives/storage/Cargo.toml b/primitives/storage/Cargo.toml new file mode 100644 index 0000000000000..384519cc1d69d --- /dev/null +++ b/primitives/storage/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sp-storage" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +description = "Storage related primitives" + +[dependencies] +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +impl-serde = { version = "0.2.3", optional = true } +sp-debug-derive = { version = "2.0.0", path = "../debug-derive" } + +[features] +default = [ "std" ] +std = [ "sp-std/std", "serde", "impl-serde" ] diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs new file mode 100644 index 0000000000000..d32c54aae8c47 --- /dev/null +++ b/primitives/storage/src/lib.rs @@ -0,0 +1,305 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitive types for storage related stuff. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use sp_debug_derive::RuntimeDebug; + +use sp_std::{vec::Vec, borrow::Cow}; + +/// Storage key. +#[derive(PartialEq, Eq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))] +pub struct StorageKey( + #[cfg_attr(feature = "std", serde(with="impl_serde::serialize"))] + pub Vec, +); + +/// Storage data associated to a [`StorageKey`]. +#[derive(PartialEq, Eq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))] +pub struct StorageData( + #[cfg_attr(feature = "std", serde(with="impl_serde::serialize"))] + pub Vec, +); + +/// Map of data to use in a storage, it is a collection of +/// byte key and values. +#[cfg(feature = "std")] +pub type StorageMap = std::collections::BTreeMap, Vec>; + +#[cfg(feature = "std")] +#[derive(Debug, PartialEq, Eq, Clone)] +/// Child trie storage data. +pub struct StorageChild { + /// Child data for storage. + pub data: StorageMap, + /// Associated child info for a child + /// trie. + pub child_info: OwnedChildInfo, +} + +#[cfg(feature = "std")] +#[derive(Default, Debug, Clone)] +/// Struct containing data needed for a storage. +pub struct Storage { + /// Top trie storage data. + pub top: StorageMap, + /// Children trie storage data by storage key. + pub children: std::collections::HashMap, StorageChild>, +} + +/// Storage change set +#[derive(RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, PartialEq, Eq))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +pub struct StorageChangeSet { + /// Block hash + pub block: Hash, + /// A list of changes + pub changes: Vec<(StorageKey, Option)>, +} + +/// List of all well known keys and prefixes in storage. +pub mod well_known_keys { + /// Wasm code of the runtime. + /// + /// Stored as a raw byte vector. Required by substrate. + pub const CODE: &'static [u8] = b":code"; + + /// Number of wasm linear memory pages required for execution of the runtime. + /// + /// The type of this value is encoded `u64`. + pub const HEAP_PAGES: &'static [u8] = b":heappages"; + + /// Current extrinsic index (u32) is stored under this key. + pub const EXTRINSIC_INDEX: &'static [u8] = b":extrinsic_index"; + + /// Changes trie configuration is stored under this key. + pub const CHANGES_TRIE_CONFIG: &'static [u8] = b":changes_trie"; + + /// Prefix of child storage keys. + pub const CHILD_STORAGE_KEY_PREFIX: &'static [u8] = b":child_storage:"; + + /// Whether a key is a child storage key. + /// + /// This is convenience function which basically checks if the given `key` starts + /// with `CHILD_STORAGE_KEY_PREFIX` and doesn't do anything apart from that. + pub fn is_child_storage_key(key: &[u8]) -> bool { + // Other code might depend on this, so be careful changing this. + key.starts_with(CHILD_STORAGE_KEY_PREFIX) + } + + /// Determine whether a child trie key is valid. + /// + /// For now, the only valid child trie keys are those starting with `:child_storage:default:`. + /// + /// `child_trie_root` and `child_delta_trie_root` can panic if invalid value is provided to them. + pub fn is_child_trie_key_valid(storage_key: &[u8]) -> bool { + let has_right_prefix = storage_key.starts_with(b":child_storage:default:"); + if has_right_prefix { + // This is an attempt to catch a change of `is_child_storage_key`, which + // just checks if the key has prefix `:child_storage:` at the moment of writing. + debug_assert!( + is_child_storage_key(&storage_key), + "`is_child_trie_key_valid` is a subset of `is_child_storage_key`", + ); + } + has_right_prefix + } +} + +/// A wrapper around a child storage key. +/// +/// This wrapper ensures that the child storage key is correct and properly used. It is +/// impossible to create an instance of this struct without providing a correct `storage_key`. +pub struct ChildStorageKey<'a> { + storage_key: Cow<'a, [u8]>, +} + +impl<'a> ChildStorageKey<'a> { + /// Create new instance of `Self`. + fn new(storage_key: Cow<'a, [u8]>) -> Option { + if well_known_keys::is_child_trie_key_valid(&storage_key) { + Some(ChildStorageKey { storage_key }) + } else { + None + } + } + + /// Create a new `ChildStorageKey` from a vector. + /// + /// `storage_key` need to start with `:child_storage:default:` + /// See `is_child_trie_key_valid` for more details. + pub fn from_vec(key: Vec) -> Option { + Self::new(Cow::Owned(key)) + } + + /// Create a new `ChildStorageKey` from a slice. + /// + /// `storage_key` need to start with `:child_storage:default:` + /// See `is_child_trie_key_valid` for more details. + pub fn from_slice(key: &'a [u8]) -> Option { + Self::new(Cow::Borrowed(key)) + } + + /// Get access to the byte representation of the storage key. + /// + /// This key is guaranteed to be correct. + pub fn as_ref(&self) -> &[u8] { + &*self.storage_key + } + + /// Destruct this instance into an owned vector that represents the storage key. + /// + /// This key is guaranteed to be correct. + pub fn into_owned(self) -> Vec { + self.storage_key.into_owned() + } +} + +#[derive(Clone, Copy)] +/// Information related to a child state. +pub enum ChildInfo<'a> { + Default(ChildTrie<'a>), +} + +/// Owned version of `ChildInfo`. +/// To be use in persistence layers. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash, PartialOrd, Ord))] +pub enum OwnedChildInfo { + Default(OwnedChildTrie), +} + +impl<'a> ChildInfo<'a> { + /// Instantiates information for a default child trie. + pub const fn new_default(unique_id: &'a[u8]) -> Self { + ChildInfo::Default(ChildTrie { + data: unique_id, + }) + } + + /// Instantiates a owned version of this child info. + pub fn to_owned(&self) -> OwnedChildInfo { + match self { + ChildInfo::Default(ChildTrie { data }) + => OwnedChildInfo::Default(OwnedChildTrie { + data: data.to_vec(), + }), + } + } + + /// Create child info from a linear byte packed value and a given type. + pub fn resolve_child_info(child_type: u32, data: &'a[u8]) -> Option { + match child_type { + x if x == ChildType::CryptoUniqueId as u32 => Some(ChildInfo::new_default(data)), + _ => None, + } + } + + /// Return a single byte vector containing packed child info content and its child info type. + /// This can be use as input for `resolve_child_info`. + pub fn info(&self) -> (&[u8], u32) { + match self { + ChildInfo::Default(ChildTrie { + data, + }) => (data, ChildType::CryptoUniqueId as u32), + } + } + + /// Return byte sequence (keyspace) that can be use by underlying db to isolate keys. + /// This is a unique id of the child trie. The collision resistance of this value + /// depends on the type of child info use. For `ChildInfo::Default` it is and need to be. + pub fn keyspace(&self) -> &[u8] { + match self { + ChildInfo::Default(ChildTrie { + data, + }) => &data[..], + } + } +} + +/// Type of child. +/// It does not strictly define different child type, it can also +/// be related to technical consideration or api variant. +#[repr(u32)] +pub enum ChildType { + /// Default, it uses a cryptographic strong unique id as input. + CryptoUniqueId = 1, +} + +impl OwnedChildInfo { + /// Instantiates info for a default child trie. + pub fn new_default(unique_id: Vec) -> Self { + OwnedChildInfo::Default(OwnedChildTrie { + data: unique_id, + }) + } + + /// Try to update with another instance, return false if both instance + /// are not compatible. + pub fn try_update(&mut self, other: ChildInfo) -> bool { + match self { + OwnedChildInfo::Default(owned_child_trie) => owned_child_trie.try_update(other), + } + } + + /// Get `ChildInfo` reference to this owned child info. + pub fn as_ref(&self) -> ChildInfo { + match self { + OwnedChildInfo::Default(OwnedChildTrie { data }) + => ChildInfo::Default(ChildTrie { + data: data.as_slice(), + }), + } + } +} + +/// A child trie of default type. +/// Default is the same implementation as the top trie. +/// It share its trie node storage with any kind of key, +/// and its unique id needs to be collision free (eg strong +/// crypto hash). +#[derive(Clone, Copy)] +pub struct ChildTrie<'a> { + /// Data containing unique id. + /// Unique id must but unique and free of any possible key collision + /// (depending on its storage behavior). + data: &'a[u8], +} + +/// Owned version of default child trie `ChildTrie`. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash, PartialOrd, Ord))] +pub struct OwnedChildTrie { + /// See `ChildTrie` reference field documentation. + data: Vec, +} + +impl OwnedChildTrie { + /// Try to update with another instance, return false if both instance + /// are not compatible. + fn try_update(&mut self, other: ChildInfo) -> bool { + match other { + ChildInfo::Default(other) => self.data[..] == other.data[..], + } + } +} diff --git a/primitives/test-primitives/Cargo.toml b/primitives/test-primitives/Cargo.toml new file mode 100644 index 0000000000000..5c2f2dcc0a68e --- /dev/null +++ b/primitives/test-primitives/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "sp-test-primitives" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../application-crypto" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-core = { version = "2.0.0", default-features = false, path = "../core" } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } + +[features] +default = [ + "std", +] +std = [ + "sp-application-crypto/std", + "serde", +] diff --git a/primitives/test-primitives/src/lib.rs b/primitives/test-primitives/src/lib.rs new file mode 100644 index 0000000000000..74115bdb8f46b --- /dev/null +++ b/primitives/test-primitives/src/lib.rs @@ -0,0 +1,85 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU 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 primitives to share + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Encode, Decode}; + +use sp_application_crypto::sr25519; +pub use sp_application_crypto; + +pub use sp_core::{hash::H256, RuntimeDebug}; +use sp_runtime::traits::{BlakeTwo256, Verify, Extrinsic as ExtrinsicT,}; + +/// Extrinsic for test-runtime. +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub enum Extrinsic { + IncludeData(Vec), + StorageChange(Vec, Option>), +} + +#[cfg(feature = "std")] +impl serde::Serialize for Extrinsic { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + self.using_encoded(|bytes| seq.serialize_bytes(bytes)) + } +} + +impl ExtrinsicT for Extrinsic { + type Call = Extrinsic; + type SignaturePayload = (); + + fn is_signed(&self) -> Option { + if let Extrinsic::IncludeData(_) = *self { + Some(false) + } else { + Some(true) + } + } + + fn new(call: Self::Call, _signature_payload: Option) -> Option { + Some(call) + } +} + +/// The signature type used by accounts/transactions. +pub type AccountSignature = sr25519::Signature; +/// An identifier for an account on this system. +pub type AccountId = ::Signer; +/// A simple hash type for all our hashing. +pub type Hash = H256; +/// The block number type used in this runtime. +pub type BlockNumber = u64; +/// Index of a transaction. +pub type Index = u64; +/// The item of a block digest. +pub type DigestItem = sp_runtime::generic::DigestItem; +/// The digest of a block. +pub type Digest = sp_runtime::generic::Digest; +/// A test block. +pub type Block = sp_runtime::generic::Block; +/// A test block's header. +pub type Header = sp_runtime::generic::Header; + +/// Changes trie configuration (optionally) used in tests. +pub fn changes_trie_config() -> sp_core::ChangesTrieConfiguration { + sp_core::ChangesTrieConfiguration { + digest_interval: 4, + digest_levels: 2, + } +} diff --git a/primitives/timestamp/Cargo.toml b/primitives/timestamp/Cargo.toml new file mode 100644 index 0000000000000..ee86d6e3bc97f --- /dev/null +++ b/primitives/timestamp/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sp-timestamp" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sp-api = { version = "2.0.0", default-features = false, path = "../api" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-inherents = { version = "2.0.0", default-features = false, path = "../inherents" } +impl-trait-for-tuples = "0.1.3" + +[features] +default = [ "std" ] +std = [ + "sp-api/std", + "sp-std/std", + "sp-runtime/std", + "codec/std", + "sp-inherents/std", +] diff --git a/primitives/timestamp/src/lib.rs b/primitives/timestamp/src/lib.rs new file mode 100644 index 0000000000000..50b871d73ea6b --- /dev/null +++ b/primitives/timestamp/src/lib.rs @@ -0,0 +1,115 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate core types and inherents for timestamps. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::Encode; +#[cfg(feature = "std")] +use codec::Decode; +#[cfg(feature = "std")] +use sp_inherents::ProvideInherentData; +use sp_inherents::{InherentIdentifier, IsFatalError, InherentData}; + +use sp_runtime::RuntimeString; + +/// 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, sp_runtime::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode))] +pub enum InherentError { + /// The timestamp is valid in the future. + /// This is a non-fatal-error and will not stop checking the inherents. + ValidAtTimestamp(InherentType), + /// Some other error. + Other(RuntimeString), +} + +impl IsFatalError for InherentError { + fn is_fatal_error(&self) -> bool { + match self { + InherentError::ValidAtTimestamp(_) => false, + InherentError::Other(_) => true, + } + } +} + +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[..]).ok() + } 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<(), sp_inherents::Error> { + 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_millis() as u64; + 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. +#[impl_trait_for_tuples::impl_for_tuples(30)] +pub trait OnTimestampSet { + fn on_timestamp_set(moment: Moment); +} diff --git a/primitives/transaction-pool/Cargo.toml b/primitives/transaction-pool/Cargo.toml new file mode 100644 index 0000000000000..3a3e15e611af1 --- /dev/null +++ b/primitives/transaction-pool/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "sp-transaction-pool" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", optional = true } +derive_more = { version = "0.99.2", optional = true } +futures = { version = "0.3.1", optional = true } +log = { version = "0.4.8", optional = true } +serde = { version = "1.0.101", features = ["derive"], optional = true} +sp-api = { version = "2.0.0", default-features = false, path = "../api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } + +[features] +default = [ "std" ] +std = [ + "codec", + "derive_more", + "futures", + "log", + "serde", + "sp-api/std", + "sp-runtime/std", +] diff --git a/primitives/transaction-pool/src/error.rs b/primitives/transaction-pool/src/error.rs new file mode 100644 index 0000000000000..ecce202d7d879 --- /dev/null +++ b/primitives/transaction-pool/src/error.rs @@ -0,0 +1,82 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Transaction pool errors. + +use sp_runtime::transaction_validity::{ + TransactionPriority as Priority, InvalidTransaction, UnknownTransaction, +}; + +/// Transaction pool result. +pub type Result = std::result::Result; + +/// Transaction pool error type. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Transaction is not verifiable yet, but might be in the future. + #[display(fmt="Unknown transaction validity: {:?}", _0)] + UnknownTransaction(UnknownTransaction), + /// Transaction is invalid. + #[display(fmt="Invalid transaction validity: {:?}", _0)] + InvalidTransaction(InvalidTransaction), + /// The transaction validity returned no "provides" tag. + /// + /// Such transactions are not accepted to the pool, since we use those tags + /// to define identity of transactions (occupance of the same "slot"). + #[display(fmt="The transaction does not provide any tags, so the pool can't identify it.")] + NoTagsProvided, + /// The transaction is temporarily banned. + #[display(fmt="Temporarily Banned")] + TemporarilyBanned, + /// The transaction is already in the pool. + #[display(fmt="[{:?}] Already imported", _0)] + AlreadyImported(Box), + /// The transaction cannot be imported cause it's a replacement and has too low priority. + #[display(fmt="Too low priority ({} > {})", old, new)] + TooLowPriority { + /// Transaction already in the pool. + old: Priority, + /// Transaction entering the pool. + new: Priority + }, + /// Deps cycle etected and we couldn't import transaction. + #[display(fmt="Cycle Detected")] + CycleDetected, + /// Transaction was dropped immediately after it got inserted. + #[display(fmt="Transaction couldn't enter the pool because of the limit.")] + ImmediatelyDropped, + /// Invalid block id. + InvalidBlockId(String), + /// The pool is not accepting future transactions. + #[display(fmt="The pool is not accepting future transactions")] + RejectedFutureTransaction, +} + +impl std::error::Error for Error {} + +/// Transaction pool error conversion. +pub trait IntoPoolError: std::error::Error + Send + Sized { + /// Try to extract original `Error` + /// + /// This implementation is optional and used only to + /// provide more descriptive error messages for end users + /// of RPC API. + fn into_pool_error(self) -> std::result::Result { Err(self) } +} + +impl IntoPoolError for Error { + fn into_pool_error(self) -> std::result::Result { Ok(self) } +} diff --git a/primitives/transaction-pool/src/lib.rs b/primitives/transaction-pool/src/lib.rs new file mode 100644 index 0000000000000..9abbcfbdf28aa --- /dev/null +++ b/primitives/transaction-pool/src/lib.rs @@ -0,0 +1,33 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Transaction pool primitives types & Runtime API. + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod runtime_api; +#[cfg(feature = "std")] +pub mod error; +#[cfg(feature = "std")] +mod pool; + +#[cfg(feature = "std")] +pub use pool::*; + +pub use sp_runtime::transaction_validity::{ + TransactionLongevity, TransactionPriority, TransactionTag, +}; diff --git a/primitives/transaction-pool/src/pool.rs b/primitives/transaction-pool/src/pool.rs new file mode 100644 index 0000000000000..e67a9890755d7 --- /dev/null +++ b/primitives/transaction-pool/src/pool.rs @@ -0,0 +1,372 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Transaction pool primitives types & Runtime API. + +use std::{ + collections::HashMap, + hash::Hash, + sync::Arc, +}; +use futures::{ + Future, Stream, + channel::mpsc, +}; +use serde::{Deserialize, Serialize}; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, Member}, + transaction_validity::{ + TransactionLongevity, TransactionPriority, TransactionTag, + }, +}; + +/// Transaction pool status. +#[derive(Debug)] +pub struct PoolStatus { + /// Number of transactions in the ready queue. + pub ready: usize, + /// Sum of bytes of ready transaction encodings. + pub ready_bytes: usize, + /// Number of transactions in the future queue. + pub future: usize, + /// Sum of bytes of ready transaction encodings. + pub future_bytes: usize, +} + +impl PoolStatus { + /// Returns true if the are no transactions in the pool. + pub fn is_empty(&self) -> bool { + self.ready == 0 && self.future == 0 + } +} + +/// Possible transaction status events. +/// +/// This events are being emitted by `TransactionPool` watchers, +/// which are also exposed over RPC. +/// +/// The status events can be grouped based on their kinds as: +/// 1. Entering/Moving within the pool: +/// - `Future` +/// - `Ready` +/// 2. Inside `Ready` queue: +/// - `Broadcast` +/// 3. Leaving the pool: +/// - `InBlock` +/// - `Invalid` +/// - `Usurped` +/// - `Dropped` +/// +/// The events will always be received in the order described above, however +/// there might be cases where transactions alternate between `Future` and `Ready` +/// pool, and are `Broadcast` in the meantime. +/// +/// There is also only single event causing the transaction to leave the pool. +/// +/// Note that there are conditions that may cause transactions to reappear in the pool. +/// 1. Due to possible forks, the transaction that ends up being in included +/// in one block, may later re-enter the pool or be marked as invalid. +/// 2. Transaction `Dropped` at one point, may later re-enter the pool if some other +/// transactions are removed. +/// 3. `Invalid` transaction may become valid at some point in the future. +/// (Note that runtimes are encouraged to use `UnknownValidity` to inform the pool about +/// such case). +/// +/// However the user needs to re-subscribe to receive such notifications. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum TransactionStatus { + /// Transaction is part of the future queue. + Future, + /// Transaction is part of the ready queue. + Ready, + /// The transaction has been broadcast to the given peers. + Broadcast(Vec), + /// Transaction has been included in block with given hash. + #[serde(rename = "finalized")] // See #4438 + InBlock(BlockHash), + /// Transaction has been replaced in the pool, by another transaction + /// that provides the same tags. (e.g. same (sender, nonce)). + Usurped(Hash), + /// Transaction has been dropped from the pool because of the limit. + Dropped, + /// Transaction is no longer valid in the current state. + Invalid, +} + +/// The stream of transaction events. +pub type TransactionStatusStream = dyn Stream> + Send + Unpin; + +/// The import notification event stream. +pub type ImportNotificationStream = mpsc::UnboundedReceiver<()>; + +/// Transaction hash type for a pool. +pub type TxHash

=

::Hash; +/// Block hash type for a pool. +pub type BlockHash

= <

::Block as BlockT>::Hash; +/// Transaction type for a pool. +pub type TransactionFor

= <

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

= TransactionStatusStream, BlockHash

>; + +/// In-pool transaction interface. +/// +/// The pool is container of transactions that are implementing this trait. +/// See `sp_runtime::ValidTransaction` for details about every field. +pub trait InPoolTransaction { + /// Transaction type. + type Transaction; + /// Transaction hash type. + type Hash; + + /// Get the reference to the transaction data. + fn data(&self) -> &Self::Transaction; + /// Get hash of the transaction. + fn hash(&self) -> &Self::Hash; + /// Get priority of the transaction. + fn priority(&self) -> &TransactionPriority; + /// Get longevity of the transaction. + fn longevity(&self) ->&TransactionLongevity; + /// Get transaction dependencies. + fn requires(&self) -> &[TransactionTag]; + /// Get tags that transaction provides. + fn provides(&self) -> &[TransactionTag]; + /// Return a flag indicating if the transaction should be propagated to other peers. + fn is_propagateable(&self) -> bool; +} + +/// Transaction pool interface. +pub trait TransactionPool: Send + Sync { + /// Block type. + type Block: BlockT; + /// Transaction hash type. + type Hash: Hash + Eq + Member + Serialize; + /// In-pool transaction type. + type InPoolTransaction: InPoolTransaction< + Transaction = TransactionFor, + Hash = TxHash + >; + /// Error type. + type Error: From + crate::error::IntoPoolError; + + // Networking + + /// Returns a future that imports a bunch of unverified transactions to the pool. + fn submit_at( + &self, + at: &BlockId, + xts: impl IntoIterator> + 'static, + ) -> Box, Self::Error>>, + Self::Error + >> + Send + Unpin>; + + /// Returns a future that imports one unverified transaction to the pool. + fn submit_one( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box, + Self::Error + >> + Send + Unpin>; + + // RPC + + /// Returns a future that import a single transaction and starts to watch their progress in the pool. + fn submit_and_watch( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box>, Self::Error>> + Send + Unpin>; + + + // Block production / Networking + + /// Get an iterator for ready transactions ordered by priority + fn ready(&self) -> Box>>; + + + // Block production + + /// Remove transactions identified by given hashes (and dependent transactions) from the pool. + fn remove_invalid(&self, hashes: &[TxHash]) -> Vec>; + + // logging + + /// Returns pool status. + fn status(&self) -> PoolStatus; + + // logging / RPC / networking + + /// Return an event stream of transactions imported to the pool. + fn import_notification_stream(&self) -> ImportNotificationStream; + + // networking + + /// Notify the pool about transactions broadcast. + fn on_broadcasted(&self, propagations: HashMap, Vec>); + + /// Returns transaction hash + fn hash_of(&self, xt: &TransactionFor) -> TxHash; +} + +/// An abstraction for transaction pool. +/// +/// This trait is used by offchain calls to be able to submit transactions. +/// The main use case is for offchain workers, to feed back the results of computations, +/// but since the transaction pool access is a separate `ExternalitiesExtension` it can +/// be also used in context of other offchain calls. For one may generate and submit +/// a transaction for some misbehavior reports (say equivocation). +pub trait OffchainSubmitTransaction: Send + Sync { + /// Submit transaction. + /// + /// The transaction will end up in the pool and be propagated to others. + fn submit_at( + &self, + at: &BlockId, + extrinsic: Block::Extrinsic, + ) -> Result<(), ()>; +} + +impl OffchainSubmitTransaction for TPool { + fn submit_at( + &self, + at: &BlockId, + extrinsic: ::Extrinsic, + ) -> Result<(), ()> { + log::debug!( + target: "txpool", + "(offchain call) Submitting a transaction to the pool: {:?}", + extrinsic + ); + + let result = futures::executor::block_on(self.submit_one(&at, extrinsic)); + + result.map(|_| ()) + .map_err(|e| log::warn!( + target: "txpool", + "(offchain call) Error submitting a transaction to the pool: {:?}", + e + )) + } +} + +/// Transaction pool maintainer interface. +pub trait TransactionPoolMaintainer: Send + Sync { + /// Block type. + type Block: BlockT; + /// Transaction Hash type. + type Hash: Hash + Eq + Member + Serialize; + + /// Returns a future that performs maintenance procedures on the pool when + /// with given hash is imported. + fn maintain( + &self, + id: &BlockId, + retracted: &[Self::Hash], + ) -> Box + Send + Unpin>; +} + +/// Maintainable pool implementation. +pub struct MaintainableTransactionPool { + pool: Pool, + maintainer: Maintainer, +} + +impl MaintainableTransactionPool { + /// Create new maintainable pool using underlying pool and maintainer. + pub fn new(pool: Pool, maintainer: Maintainer) -> Self { + MaintainableTransactionPool { pool, maintainer } + } +} + +impl TransactionPool for MaintainableTransactionPool + where + Pool: TransactionPool, + Maintainer: Send + Sync, +{ + type Block = Pool::Block; + type Hash = Pool::Hash; + type InPoolTransaction = Pool::InPoolTransaction; + type Error = Pool::Error; + + fn submit_at( + &self, + at: &BlockId, + xts: impl IntoIterator> + 'static, + ) -> Box, Self::Error>>, Self::Error>> + Send + Unpin> { + self.pool.submit_at(at, xts) + } + + fn submit_one( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box, Self::Error>> + Send + Unpin> { + self.pool.submit_one(at, xt) + } + + fn submit_and_watch( + &self, + at: &BlockId, + xt: TransactionFor, + ) -> Box>, Self::Error>> + Send + Unpin> { + self.pool.submit_and_watch(at, xt) + } + + fn remove_invalid(&self, hashes: &[TxHash]) -> Vec> { + self.pool.remove_invalid(hashes) + } + + fn status(&self) -> PoolStatus { + self.pool.status() + } + + fn ready(&self) -> Box>> { + self.pool.ready() + } + + fn import_notification_stream(&self) -> ImportNotificationStream { + self.pool.import_notification_stream() + } + + fn hash_of(&self, xt: &TransactionFor) -> TxHash { + self.pool.hash_of(xt) + } + + fn on_broadcasted(&self, propagations: HashMap, Vec>) { + self.pool.on_broadcasted(propagations) + } +} + +impl TransactionPoolMaintainer for MaintainableTransactionPool + where + Pool: Send + Sync, + Maintainer: TransactionPoolMaintainer +{ + type Block = Maintainer::Block; + type Hash = Maintainer::Hash; + + fn maintain( + &self, + id: &BlockId, + retracted: &[Self::Hash], + ) -> Box + Send + Unpin> { + self.maintainer.maintain(id, retracted) + } +} diff --git a/primitives/transaction-pool/src/runtime_api.rs b/primitives/transaction-pool/src/runtime_api.rs new file mode 100644 index 0000000000000..e30ce7c8289da --- /dev/null +++ b/primitives/transaction-pool/src/runtime_api.rs @@ -0,0 +1,28 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tagged Transaction Queue Runtime API. + +use sp_runtime::transaction_validity::TransactionValidity; +use sp_runtime::traits::Block as BlockT; + +sp_api::decl_runtime_apis! { + /// The `TaggedTransactionQueue` api trait for interfering with the transaction queue. + pub trait TaggedTransactionQueue { + /// Validate the given transaction. + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity; + } +} diff --git a/primitives/trie/Cargo.toml b/primitives/trie/Cargo.toml new file mode 100644 index 0000000000000..78e32e33334df --- /dev/null +++ b/primitives/trie/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "sp-trie" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Patricia trie stuff using a parity-scale-codec node format" +repository = "https://github.com/paritytech/substrate" +license = "GPL-3.0" +edition = "2018" + +[[bench]] +name = "bench" +harness = false + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +hash-db = { version = "0.15.2", default-features = false } +trie-db = { version = "0.18.1", default-features = false } +trie-root = { version = "0.15.2", default-features = false } +memory-db = { version = "0.18.0", default-features = false } +sp-core = { version = "2.0.0", default-features = false, path = "../core" } + +[dev-dependencies] +trie-bench = "0.18.0" +trie-standardmap = "0.15.2" +criterion = "0.2.11" +hex-literal = "0.2.1" + +[features] +default = ["std"] +std = [ + "sp-std/std", + "codec/std", + "hash-db/std", + "memory-db/std", + "trie-db/std", + "trie-root/std", + "sp-core/std", +] diff --git a/primitives/trie/benches/bench.rs b/primitives/trie/benches/bench.rs new file mode 100644 index 0000000000000..72a53c18d2526 --- /dev/null +++ b/primitives/trie/benches/bench.rs @@ -0,0 +1,30 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use criterion::{Criterion, criterion_group, criterion_main}; +criterion_group!(benches, benchmark); +criterion_main!(benches); + +fn benchmark(c: &mut Criterion) { + trie_bench::standard_benchmark::< + sp_trie::Layout, + sp_trie::TrieStream, + >(c, "substrate-blake2"); + trie_bench::standard_benchmark::< + sp_trie::Layout, + sp_trie::TrieStream, + >(c, "substrate-keccak"); +} diff --git a/primitives/trie/src/error.rs b/primitives/trie/src/error.rs new file mode 100644 index 0000000000000..2d3a1b79287c3 --- /dev/null +++ b/primitives/trie/src/error.rs @@ -0,0 +1,47 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[cfg(feature="std")] +use std::fmt; +#[cfg(feature="std")] +use std::error::Error as StdError; + +#[derive(Debug, PartialEq, Eq, Clone)] +/// Error for trie node decoding. +pub enum Error { + /// Bad format. + BadFormat, + /// Decoding error. + Decode(codec::Error) +} + +impl From for Error { + fn from(x: codec::Error) -> Self { + Error::Decode(x) + } +} + +#[cfg(feature="std")] +impl StdError for Error { + fn description(&self) -> &str { + match self { + Error::BadFormat => "Bad format error", + Error::Decode(_) => "Decoding error", + } + } +} + +#[cfg(feature="std")] +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::Decode(e) => write!(f, "Decode error: {}", e.what()), + Error::BadFormat => write!(f, "Bad format"), + } + } +} diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs new file mode 100644 index 0000000000000..4ca26542dd4bb --- /dev/null +++ b/primitives/trie/src/lib.rs @@ -0,0 +1,730 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Utility functions to interact with Substrate's Base-16 Modified Merkle Patricia tree ("trie"). + +#![cfg_attr(not(feature = "std"), no_std)] + +mod error; +mod node_header; +mod node_codec; +mod trie_stream; + +use sp_std::boxed::Box; +use sp_std::marker::PhantomData; +use sp_std::vec::Vec; +use hash_db::{Hasher, Prefix}; +/// Our `NodeCodec`-specific error. +pub use error::Error; +/// The Substrate format implementation of `TrieStream`. +pub use trie_stream::TrieStream; +/// The Substrate format implementation of `NodeCodec`. +pub use node_codec::NodeCodec; +/// Various re-exports from the `trie-db` crate. +pub use trie_db::{ + Trie, TrieMut, DBValue, Recorder, CError, Query, TrieLayout, TrieConfiguration, nibble_ops, +}; +/// Various re-exports from the `memory-db` crate. +pub use memory_db::KeyFunction; +pub use memory_db::prefixed_key; +/// Various re-exports from the `hash-db` crate. +pub use hash_db::{HashDB as HashDBT, EMPTY_PREFIX}; + +#[derive(Default)] +/// substrate trie layout +pub struct Layout(sp_std::marker::PhantomData); + +impl TrieLayout for Layout { + const USE_EXTENSION: bool = false; + type Hash = H; + type Codec = NodeCodec; +} + +impl TrieConfiguration for Layout { + fn trie_root(input: I) -> ::Out where + I: IntoIterator, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, + { + trie_root::trie_root_no_extension::(input) + } + + fn trie_root_unhashed(input: I) -> Vec where + I: IntoIterator, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, + { + trie_root::unhashed_trie_no_extension::(input) + } + + fn encode_index(input: u32) -> Vec { + codec::Encode::encode(&codec::Compact(input)) + } +} + +/// TrieDB error over `TrieConfiguration` trait. +pub type TrieError = trie_db::TrieError, CError>; +/// Reexport from `hash_db`, with genericity set for `Hasher` trait. +pub trait AsHashDB: hash_db::AsHashDB {} +impl> AsHashDB for T {} +/// Reexport from `hash_db`, with genericity set for `Hasher` trait. +pub type HashDB<'a, H> = dyn hash_db::HashDB + 'a; +/// Reexport from `hash_db`, with genericity set for key only. +pub type PlainDB<'a, K> = dyn hash_db::PlainDB + 'a; +/// Reexport from `hash_db`, with genericity set for `Hasher` trait. +/// This uses a `KeyFunction` for prefixing keys internally (avoiding +/// key conflict for non random keys). +pub type PrefixedMemoryDB = memory_db::MemoryDB, trie_db::DBValue>; +/// Reexport from `hash_db`, with genericity set for `Hasher` trait. +/// This uses the `KeyFunction` for prefixing keys internally (avoiding +/// This uses a noops `KeyFunction` (key addressing must be hashed or using +/// an encoding scheme that avoid key conflict). +pub type MemoryDB = memory_db::MemoryDB, trie_db::DBValue>; +/// Reexport from `hash_db`, with genericity set for `Hasher` trait. +pub type GenericMemoryDB = memory_db::MemoryDB; + +/// Persistent trie database read-access interface for the a given hasher. +pub type TrieDB<'a, L> = trie_db::TrieDB<'a, L>; +/// Persistent trie database write-access interface for the a given hasher. +pub type TrieDBMut<'a, L> = trie_db::TrieDBMut<'a, L>; +/// Querying interface, as in `trie_db` but less generic. +pub type Lookup<'a, L, Q> = trie_db::Lookup<'a, L, Q>; +/// Hash type for a trie layout. +pub type TrieHash = <::Hash as Hasher>::Out; + +/// This module is for non generic definition of trie type. +/// Only the `Hasher` trait is generic in this case. +pub mod trie_types { + pub type Layout = super::Layout; + /// Persistent trie database read-access interface for the a given hasher. + pub type TrieDB<'a, H> = super::TrieDB<'a, Layout>; + /// Persistent trie database write-access interface for the a given hasher. + pub type TrieDBMut<'a, H> = super::TrieDBMut<'a, Layout>; + /// Querying interface, as in `trie_db` but less generic. + pub type Lookup<'a, H, Q> = trie_db::Lookup<'a, Layout, Q>; + /// As in `trie_db`, but less generic, error type for the crate. + pub type TrieError = trie_db::TrieError; +} + +/// Determine a trie root given a hash DB and delta values. +pub fn delta_trie_root( + db: &mut DB, + mut root: TrieHash, + delta: I +) -> Result, Box>> where + I: IntoIterator)>, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, + DB: hash_db::HashDB, +{ + { + let mut trie = TrieDBMut::::from_existing(&mut *db, &mut root)?; + + for (key, change) in delta { + match change { + Some(val) => trie.insert(key.as_ref(), val.as_ref())?, + None => trie.remove(key.as_ref())?, + }; + } + } + + Ok(root) +} + +/// Read a value from the trie. +pub fn read_trie_value>( + db: &DB, + root: &TrieHash, + 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< + L: TrieConfiguration, + Q: Query, + DB: hash_db::HashDBRef +>( + db: &DB, + root: &TrieHash, + key: &[u8], + query: Q +) -> Result>, Box>> { + Ok(TrieDB::::new(&*db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) +} + +/// Determine the default child trie root. +pub fn default_child_trie_root( + _storage_key: &[u8], +) -> ::Out { + L::trie_root::<_, Vec, Vec>(core::iter::empty()) +} + +/// Determine a child trie root given its ordered contents, closed form. H is the default hasher, +/// but a generic implementation may ignore this type parameter and use other hashers. +pub fn child_trie_root( + _storage_key: &[u8], + input: I, +) -> ::Out + where + I: IntoIterator, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, +{ + L::trie_root(input) +} + +/// 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], + keyspace: &[u8], + db: &mut DB, + root_data: RD, + delta: I, +) -> Result<::Out, Box>> + where + I: IntoIterator)>, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, + RD: AsRef<[u8]>, + DB: hash_db::HashDB + + hash_db::PlainDB, trie_db::DBValue>, +{ + let mut root = TrieHash::::default(); + // root is fetched from DB, not writable by runtime, so it's always valid. + root.as_mut().copy_from_slice(root_data.as_ref()); + + { + let mut db = KeySpacedDBMut::new(&mut *db, keyspace); + 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())?, + }; + } + } + + Ok(root) +} + +/// Call `f` for all keys in a child trie. +pub fn for_keys_in_child_trie( + _storage_key: &[u8], + keyspace: &[u8], + db: &DB, + root_slice: &[u8], + mut f: F +) -> Result<(), Box>> + where + DB: hash_db::HashDBRef + + hash_db::PlainDBRef, trie_db::DBValue>, +{ + let mut root = TrieHash::::default(); + // root is fetched from DB, not writable by runtime, so it's always valid. + root.as_mut().copy_from_slice(root_slice); + + let db = KeySpacedDB::new(&*db, keyspace); + let trie = TrieDB::::new(&db, &root)?; + let iter = trie.iter()?; + + for x in iter { + let (key, _) = x?; + f(&key); + } + + Ok(()) +} + +/// Record all keys for a given root. +pub fn record_all_keys( + db: &DB, + root: &TrieHash, + recorder: &mut Recorder> +) -> Result<(), Box>> where + DB: hash_db::HashDBRef +{ + let trie = TrieDB::::new(&*db, root)?; + let iter = trie.iter()?; + + for x in iter { + let (key, _) = x?; + + // there's currently no API like iter_with() + // => use iter to enumerate all keys AND lookup each + // key using get_with + trie.get_with(&key, &mut *recorder)?; + } + + Ok(()) +} + +/// Read a value from the child trie. +pub fn read_child_trie_value( + _storage_key: &[u8], + keyspace: &[u8], + db: &DB, + root_slice: &[u8], + key: &[u8] +) -> Result>, Box>> + where + DB: hash_db::HashDBRef + + hash_db::PlainDBRef, trie_db::DBValue>, +{ + let mut root = TrieHash::::default(); + // root is fetched from DB, not writable by runtime, so it's always valid. + root.as_mut().copy_from_slice(root_slice); + + let db = KeySpacedDB::new(&*db, keyspace); + 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, DB>( + _storage_key: &[u8], + keyspace: &[u8], + db: &DB, + root_slice: &[u8], + key: &[u8], + query: Q +) -> Result>, Box>> + where + DB: hash_db::HashDBRef + + hash_db::PlainDBRef, trie_db::DBValue>, +{ + let mut root = TrieHash::::default(); + // root is fetched from DB, not writable by runtime, so it's always valid. + root.as_mut().copy_from_slice(root_slice); + + let db = KeySpacedDB::new(&*db, keyspace); + Ok(TrieDB::::new(&db, &root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) +} + +/// `HashDB` implementation that append a encoded prefix (unique id bytes) in addition to the +/// prefix of every key value. +pub struct KeySpacedDB<'a, DB, H>(&'a DB, &'a [u8], PhantomData); + +/// `HashDBMut` implementation that append a encoded prefix (unique id bytes) in addition to the +/// prefix of every key value. +/// +/// Mutable variant of `KeySpacedDB`, see [`KeySpacedDB`]. +pub struct KeySpacedDBMut<'a, DB, H>(&'a mut DB, &'a [u8], PhantomData); + +/// Utility function used to merge some byte data (keyspace) and `prefix` data +/// before calling key value database primitives. +fn keyspace_as_prefix_alloc(ks: &[u8], prefix: Prefix) -> (Vec, Option) { + let mut result = sp_std::vec![0; ks.len() + prefix.0.len()]; + result[..ks.len()].copy_from_slice(ks); + result[ks.len()..].copy_from_slice(prefix.0); + (result, prefix.1) +} + +impl<'a, DB, H> KeySpacedDB<'a, DB, H> where + H: Hasher, +{ + /// instantiate new keyspaced db + pub fn new(db: &'a DB, ks: &'a [u8]) -> Self { + KeySpacedDB(db, ks, PhantomData) + } +} + +impl<'a, DB, H> KeySpacedDBMut<'a, DB, H> where + H: Hasher, +{ + /// instantiate new keyspaced db + pub fn new(db: &'a mut DB, ks: &'a [u8]) -> Self { + KeySpacedDBMut(db, ks, PhantomData) + } +} + +impl<'a, DB, H, T> hash_db::HashDBRef for KeySpacedDB<'a, DB, H> where + DB: hash_db::HashDBRef, + H: Hasher, + T: From<&'static [u8]>, +{ + fn get(&self, key: &H::Out, prefix: Prefix) -> Option { + let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix); + self.0.get(key, (&derived_prefix.0, derived_prefix.1)) + } + + fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { + let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix); + self.0.contains(key, (&derived_prefix.0, derived_prefix.1)) + } +} + +impl<'a, DB, H, T> hash_db::HashDB for KeySpacedDBMut<'a, DB, H> where + DB: hash_db::HashDB, + H: Hasher, + T: Default + PartialEq + for<'b> From<&'b [u8]> + Clone + Send + Sync, +{ + fn get(&self, key: &H::Out, prefix: Prefix) -> Option { + let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix); + self.0.get(key, (&derived_prefix.0, derived_prefix.1)) + } + + fn contains(&self, key: &H::Out, prefix: Prefix) -> bool { + let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix); + self.0.contains(key, (&derived_prefix.0, derived_prefix.1)) + } + + fn insert(&mut self, prefix: Prefix, value: &[u8]) -> H::Out { + let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix); + self.0.insert((&derived_prefix.0, derived_prefix.1), value) + } + + fn emplace(&mut self, key: H::Out, prefix: Prefix, value: T) { + let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix); + self.0.emplace(key, (&derived_prefix.0, derived_prefix.1), value) + } + + fn remove(&mut self, key: &H::Out, prefix: Prefix) { + let derived_prefix = keyspace_as_prefix_alloc(self.1, prefix); + self.0.remove(key, (&derived_prefix.0, derived_prefix.1)) + } +} + +impl<'a, DB, H, T> hash_db::AsHashDB for KeySpacedDBMut<'a, DB, H> where + DB: hash_db::HashDB, + H: Hasher, + T: Default + PartialEq + for<'b> From<&'b [u8]> + Clone + Send + Sync, +{ + fn as_hash_db(&self) -> &dyn hash_db::HashDB { &*self } + + fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn hash_db::HashDB + 'b) { + &mut *self + } +} + +/// Constants used into trie simplification codec. +mod trie_constants { + pub const EMPTY_TRIE: u8 = 0; + pub const NIBBLE_SIZE_BOUND: usize = u16::max_value() as usize; + pub const LEAF_PREFIX_MASK: u8 = 0b_01 << 6; + pub const BRANCH_WITHOUT_MASK: u8 = 0b_10 << 6; + pub const BRANCH_WITH_MASK: u8 = 0b_11 << 6; +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::{Encode, Compact}; + use sp_core::Blake2Hasher; + use hash_db::{HashDB, Hasher}; + use trie_db::{DBValue, TrieMut, Trie, NodeCodec as NodeCodecT}; + use trie_standardmap::{Alphabet, ValueMode, StandardMap}; + use hex_literal::hex; + + type Layout = super::Layout; + + fn hashed_null_node() -> TrieHash { + ::hashed_null_node() + } + + fn check_equivalent(input: &Vec<(&[u8], &[u8])>) { + { + let closed_form = T::trie_root(input.clone()); + let d = T::trie_root_unhashed(input.clone()); + println!("Data: {:#x?}, {:#x?}", d, Blake2Hasher::hash(&d[..])); + let persistent = { + let mut memdb = MemoryDB::default(); + let mut root = Default::default(); + let mut t = TrieDBMut::::new(&mut memdb, &mut root); + for (x, y) in input.iter().rev() { + t.insert(x, y).unwrap(); + } + t.root().clone() + }; + assert_eq!(closed_form, persistent); + } + } + + fn check_iteration(input: &Vec<(&[u8], &[u8])>) { + let mut memdb = MemoryDB::default(); + let mut root = Default::default(); + { + let mut t = TrieDBMut::::new(&mut memdb, &mut root); + for (x, y) in input.clone() { + t.insert(x, y).unwrap(); + } + } + { + let t = TrieDB::::new(&mut memdb, &root).unwrap(); + assert_eq!( + input.iter().map(|(i, j)| (i.to_vec(), j.to_vec())).collect::>(), + t.iter().unwrap() + .map(|x| x.map(|y| (y.0, y.1.to_vec())).unwrap()) + .collect::>() + ); + } + } + + #[test] + fn default_trie_root() { + let mut db = MemoryDB::default(); + let mut root = TrieHash::::default(); + let mut empty = TrieDBMut::::new(&mut db, &mut root); + empty.commit(); + let root1 = empty.root().as_ref().to_vec(); + let root2: Vec = Layout::trie_root::<_, Vec, Vec>( + std::iter::empty(), + ).as_ref().iter().cloned().collect(); + + assert_eq!(root1, root2); + } + + #[test] + fn empty_is_equivalent() { + let input: Vec<(&[u8], &[u8])> = vec![]; + check_equivalent::(&input); + check_iteration::(&input); + } + + #[test] + fn leaf_is_equivalent() { + let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &[0xbb][..])]; + check_equivalent::(&input); + check_iteration::(&input); + } + + #[test] + fn branch_is_equivalent() { + let input: Vec<(&[u8], &[u8])> = vec![ + (&[0xaa][..], &[0x10][..]), + (&[0xba][..], &[0x11][..]), + ]; + check_equivalent::(&input); + check_iteration::(&input); + } + + #[test] + fn extension_and_branch_is_equivalent() { + let input: Vec<(&[u8], &[u8])> = vec![ + (&[0xaa][..], &[0x10][..]), + (&[0xab][..], &[0x11][..]), + ]; + check_equivalent::(&input); + check_iteration::(&input); + } + + #[test] + fn standard_is_equivalent() { + let st = StandardMap { + alphabet: Alphabet::All, + min_key: 32, + journal_key: 0, + value_mode: ValueMode::Random, + count: 1000, + }; + let mut d = st.make(); + d.sort_unstable_by(|&(ref a, _), &(ref b, _)| a.cmp(b)); + let dr = d.iter().map(|v| (&v.0[..], &v.1[..])).collect(); + check_equivalent::(&dr); + check_iteration::(&dr); + } + + #[test] + fn extension_and_branch_with_value_is_equivalent() { + let input: Vec<(&[u8], &[u8])> = vec![ + (&[0xaa][..], &[0xa0][..]), + (&[0xaa, 0xaa][..], &[0xaa][..]), + (&[0xaa, 0xbb][..], &[0xab][..]) + ]; + check_equivalent::(&input); + check_iteration::(&input); + } + + #[test] + fn bigger_extension_and_branch_with_value_is_equivalent() { + let input: Vec<(&[u8], &[u8])> = vec![ + (&[0xaa][..], &[0xa0][..]), + (&[0xaa, 0xaa][..], &[0xaa][..]), + (&[0xaa, 0xbb][..], &[0xab][..]), + (&[0xbb][..], &[0xb0][..]), + (&[0xbb, 0xbb][..], &[0xbb][..]), + (&[0xbb, 0xcc][..], &[0xbc][..]), + ]; + check_equivalent::(&input); + check_iteration::(&input); + } + + #[test] + fn single_long_leaf_is_equivalent() { + let input: Vec<(&[u8], &[u8])> = vec![ + (&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]), + (&[0xba][..], &[0x11][..]), + ]; + check_equivalent::(&input); + check_iteration::(&input); + } + + #[test] + fn two_long_leaves_is_equivalent() { + let input: Vec<(&[u8], &[u8])> = vec![ + (&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]), + (&[0xba][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]) + ]; + check_equivalent::(&input); + check_iteration::(&input); + } + + fn populate_trie<'db, T: TrieConfiguration>( + db: &'db mut dyn HashDB, + root: &'db mut TrieHash, + v: &[(Vec, Vec)] + ) -> TrieDBMut<'db, T> { + let mut t = TrieDBMut::::new(db, root); + for i in 0..v.len() { + let key: &[u8]= &v[i].0; + let val: &[u8] = &v[i].1; + t.insert(key, val).unwrap(); + } + t + } + + fn unpopulate_trie<'db, T: TrieConfiguration>( + t: &mut TrieDBMut<'db, T>, + v: &[(Vec, Vec)], + ) { + for i in v { + let key: &[u8]= &i.0; + t.remove(key).unwrap(); + } + } + + #[test] + fn random_should_work() { + let mut seed = ::Out::zero(); + for test_i in 0..10000 { + if test_i % 50 == 0 { + println!("{:?} of 10000 stress tests done", test_i); + } + let x = StandardMap { + alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()), + min_key: 5, + journal_key: 0, + value_mode: ValueMode::Index, + count: 100, + }.make_with(seed.as_fixed_bytes_mut()); + + let real = Layout::trie_root(x.clone()); + let mut memdb = MemoryDB::default(); + let mut root = Default::default(); + let mut memtrie = populate_trie::(&mut memdb, &mut root, &x); + + memtrie.commit(); + if *memtrie.root() != real { + println!("TRIE MISMATCH"); + println!(""); + println!("{:?} vs {:?}", memtrie.root(), real); + for i in &x { + println!("{:#x?} -> {:#x?}", i.0, i.1); + } + } + assert_eq!(*memtrie.root(), real); + unpopulate_trie::(&mut memtrie, &x); + memtrie.commit(); + let hashed_null_node = hashed_null_node::(); + if *memtrie.root() != hashed_null_node { + println!("- TRIE MISMATCH"); + println!(""); + println!("{:?} vs {:?}", memtrie.root(), hashed_null_node); + for i in &x { + println!("{:#x?} -> {:#x?}", i.0, i.1); + } + } + assert_eq!(*memtrie.root(), hashed_null_node); + } + } + + fn to_compact(n: u8) -> u8 { + Compact(n).encode()[0] + } + + #[test] + fn codec_trie_empty() { + let input: Vec<(&[u8], &[u8])> = vec![]; + let trie = Layout::trie_root_unhashed::<_, _, _>(input); + println!("trie: {:#x?}", trie); + assert_eq!(trie, vec![0x0]); + } + + #[test] + fn codec_trie_single_tuple() { + let input = vec![ + (vec![0xaa], vec![0xbb]) + ]; + let trie = Layout::trie_root_unhashed::<_, _, _>(input); + println!("trie: {:#x?}", trie); + assert_eq!(trie, vec![ + 0x42, // leaf 0x40 (2^6) with (+) key of 2 nibbles (0x02) + 0xaa, // key data + to_compact(1), // length of value in bytes as Compact + 0xbb // value data + ]); + } + + #[test] + fn codec_trie_two_tuples_disjoint_keys() { + let input = vec![(&[0x48, 0x19], &[0xfe]), (&[0x13, 0x14], &[0xff])]; + let trie = Layout::trie_root_unhashed::<_, _, _>(input); + println!("trie: {:#x?}", trie); + let mut ex = Vec::::new(); + ex.push(0x80); // branch, no value (0b_10..) no nibble + ex.push(0x12); // slots 1 & 4 are taken from 0-7 + ex.push(0x00); // no slots from 8-15 + ex.push(to_compact(0x05)); // first slot: LEAF, 5 bytes long. + ex.push(0x43); // leaf 0x40 with 3 nibbles + ex.push(0x03); // first nibble + ex.push(0x14); // second & third nibble + ex.push(to_compact(0x01)); // 1 byte data + ex.push(0xff); // value data + ex.push(to_compact(0x05)); // second slot: LEAF, 5 bytes long. + ex.push(0x43); // leaf with 3 nibbles + ex.push(0x08); // first nibble + ex.push(0x19); // second & third nibble + ex.push(to_compact(0x01)); // 1 byte data + ex.push(0xfe); // value data + + assert_eq!(trie, ex); + } + + #[test] + fn iterator_works() { + let pairs = vec![ + (hex!("0103000000000000000464").to_vec(), hex!("0400000000").to_vec()), + (hex!("0103000000000000000469").to_vec(), hex!("0401000000").to_vec()), + ]; + + let mut mdb = MemoryDB::default(); + let mut root = Default::default(); + let _ = populate_trie::(&mut mdb, &mut root, &pairs); + + let trie = TrieDB::::new(&mdb, &root).unwrap(); + + let iter = trie.iter().unwrap(); + let mut iter_pairs = Vec::new(); + for pair in iter { + let (key, value) = pair.unwrap(); + iter_pairs.push((key, value.to_vec())); + } + + assert_eq!(pairs, iter_pairs); + } +} diff --git a/primitives/trie/src/node_codec.rs b/primitives/trie/src/node_codec.rs new file mode 100644 index 0000000000000..8a61f372cf2aa --- /dev/null +++ b/primitives/trie/src/node_codec.rs @@ -0,0 +1,292 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! `NodeCodec` implementation for Substrate's trie format. + +use sp_std::marker::PhantomData; +use sp_std::ops::Range; +use sp_std::vec::Vec; +use sp_std::borrow::Borrow; +use codec::{Encode, Decode, Input, Compact}; +use hash_db::Hasher; +use trie_db::{self, node::{NibbleSlicePlan, NodePlan, NodeHandlePlan}, ChildReference, + nibble_ops, Partial, NodeCodec as NodeCodecT}; +use crate::error::Error; +use crate::trie_constants; +use super::{node_header::{NodeHeader, NodeKind}}; + +/// Helper struct for trie node decoder. This implements `codec::Input` on a byte slice, while +/// tracking the absolute position. This is similar to `std::io::Cursor` but does not implement +/// `Read` and `io` is not in `sp-std`. +struct ByteSliceInput<'a> { + data: &'a [u8], + offset: usize, +} + +impl<'a> ByteSliceInput<'a> { + fn new(data: &'a [u8]) -> Self { + ByteSliceInput { + data, + offset: 0, + } + } + + fn take(&mut self, count: usize) -> Result, codec::Error> { + if self.offset + count > self.data.len() { + return Err("out of data".into()); + } + + let range = self.offset..(self.offset + count); + self.offset += count; + Ok(range) + } +} + +impl<'a> Input for ByteSliceInput<'a> { + fn remaining_len(&mut self) -> Result, codec::Error> { + let remaining = if self.offset <= self.data.len() { + Some(self.data.len() - self.offset) + } else { + None + }; + Ok(remaining) + } + + fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> { + let range = self.take(into.len())?; + into.copy_from_slice(&self.data[range]); + Ok(()) + } + + fn read_byte(&mut self) -> Result { + if self.offset + 1 > self.data.len() { + return Err("out of data".into()); + } + + let byte = self.data[self.offset]; + self.offset += 1; + Ok(byte) + } +} + +/// Concrete implementation of a `NodeCodec` with Parity Codec encoding, generic over the `Hasher` +#[derive(Default, Clone)] +pub struct NodeCodec(PhantomData); + +impl NodeCodecT for NodeCodec { + type Error = Error; + type HashOut = H::Out; + + fn hashed_null_node() -> ::Out { + H::hash(::empty_node()) + } + + fn decode_plan(data: &[u8]) -> sp_std::result::Result { + let mut input = ByteSliceInput::new(data); + match NodeHeader::decode(&mut input)? { + NodeHeader::Null => Ok(NodePlan::Empty), + NodeHeader::Branch(has_value, nibble_count) => { + let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0; + // check that the padding is valid (if any) + if padding && nibble_ops::pad_left(data[input.offset]) != 0 { + return Err(Error::BadFormat); + } + let partial = input.take( + (nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) / nibble_ops::NIBBLE_PER_BYTE, + )?; + let partial_padding = nibble_ops::number_padding(nibble_count); + let bitmap_range = input.take(BITMAP_LENGTH)?; + let bitmap = Bitmap::decode(&data[bitmap_range])?; + let value = if has_value { + let count = >::decode(&mut input)?.0 as usize; + Some(input.take(count)?) + } else { + None + }; + let mut children = [ + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + ]; + for i in 0..nibble_ops::NIBBLE_LENGTH { + if bitmap.value_at(i) { + let count = >::decode(&mut input)?.0 as usize; + let range = input.take(count)?; + children[i] = Some(if count == H::LENGTH { + NodeHandlePlan::Hash(range) + } else { + NodeHandlePlan::Inline(range) + }); + } + } + Ok(NodePlan::NibbledBranch { + partial: NibbleSlicePlan::new(partial, partial_padding), + value, + children, + }) + } + NodeHeader::Leaf(nibble_count) => { + let padding = nibble_count % nibble_ops::NIBBLE_PER_BYTE != 0; + // check that the padding is valid (if any) + if padding && nibble_ops::pad_left(data[input.offset]) != 0 { + return Err(Error::BadFormat); + } + let partial = input.take( + (nibble_count + (nibble_ops::NIBBLE_PER_BYTE - 1)) / nibble_ops::NIBBLE_PER_BYTE, + )?; + let partial_padding = nibble_ops::number_padding(nibble_count); + let count = >::decode(&mut input)?.0 as usize; + Ok(NodePlan::Leaf { + partial: NibbleSlicePlan::new(partial, partial_padding), + value: input.take(count)?, + }) + } + } + } + + fn is_empty_node(data: &[u8]) -> bool { + data == ::empty_node() + } + + fn empty_node() -> &'static [u8] { + &[trie_constants::EMPTY_TRIE] + } + + fn leaf_node(partial: Partial, value: &[u8]) -> Vec { + let mut output = partial_encode(partial, NodeKind::Leaf); + value.encode_to(&mut output); + output + } + + fn extension_node( + _partial: impl Iterator, + _nbnibble: usize, + _child: ChildReference<::Out>, + ) -> Vec { + unreachable!() + } + + fn branch_node( + _children: impl Iterator::Out>>>>, + _maybe_value: Option<&[u8]>, + ) -> Vec { + unreachable!() + } + + fn branch_node_nibbled( + partial: impl Iterator, + number_nibble: usize, + children: impl Iterator::Out>>>>, + maybe_value: Option<&[u8]>, + ) -> Vec { + let mut output = if maybe_value.is_some() { + partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchWithValue) + } else { + partial_from_iterator_encode(partial, number_nibble, NodeKind::BranchNoValue) + }; + let bitmap_index = output.len(); + let mut bitmap: [u8; BITMAP_LENGTH] = [0; BITMAP_LENGTH]; + (0..BITMAP_LENGTH).for_each(|_|output.push(0)); + if let Some(value) = maybe_value { + value.encode_to(&mut output); + }; + Bitmap::encode(children.map(|maybe_child| match maybe_child.borrow() { + Some(ChildReference::Hash(h)) => { + h.as_ref().encode_to(&mut output); + true + } + &Some(ChildReference::Inline(inline_data, len)) => { + inline_data.as_ref()[..len].encode_to(&mut output); + true + } + None => false, + }), bitmap.as_mut()); + output[bitmap_index..bitmap_index + BITMAP_LENGTH] + .copy_from_slice(&bitmap[..BITMAP_LENGTH]); + output + } + +} + +// utils + +/// Encode and allocate node type header (type and size), and partial value. +/// It uses an iterator over encoded partial bytes as input. +fn partial_from_iterator_encode>( + partial: I, + nibble_count: usize, + node_kind: NodeKind, +) -> Vec { + let nibble_count = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibble_count); + + let mut output = Vec::with_capacity(3 + (nibble_count / nibble_ops::NIBBLE_PER_BYTE)); + match node_kind { + NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output), + NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output), + NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output), + }; + output.extend(partial); + output +} + +/// Encode and allocate node type header (type and size), and partial value. +/// Same as `partial_from_iterator_encode` but uses non encoded `Partial` as input. +fn partial_encode(partial: Partial, node_kind: NodeKind) -> Vec { + let number_nibble_encoded = (partial.0).0 as usize; + let nibble_count = partial.1.len() * nibble_ops::NIBBLE_PER_BYTE + number_nibble_encoded; + + let nibble_count = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibble_count); + + let mut output = Vec::with_capacity(3 + partial.1.len()); + match node_kind { + NodeKind::Leaf => NodeHeader::Leaf(nibble_count).encode_to(&mut output), + NodeKind::BranchWithValue => NodeHeader::Branch(true, nibble_count).encode_to(&mut output), + NodeKind::BranchNoValue => NodeHeader::Branch(false, nibble_count).encode_to(&mut output), + }; + if number_nibble_encoded > 0 { + output.push(nibble_ops::pad_right((partial.0).1)); + } + output.extend_from_slice(&partial.1[..]); + output +} + +const BITMAP_LENGTH: usize = 2; + +/// Radix 16 trie, bitmap encoding implementation, +/// it contains children mapping information for a branch +/// (children presence only), it encodes into +/// a compact bitmap encoding representation. +pub(crate) struct Bitmap(u16); + +impl Bitmap { + pub fn decode(data: &[u8]) -> Result { + Ok(Bitmap(u16::decode(&mut &data[..])?)) + } + + pub fn value_at(&self, i: usize) -> bool { + self.0 & (1u16 << i) != 0 + } + + pub fn encode>(has_children: I , dest: &mut [u8]) { + let mut bitmap: u16 = 0; + let mut cursor: u16 = 1; + for v in has_children { + if v { bitmap |= cursor } + cursor <<= 1; + } + dest[0] = (bitmap % 256) as u8; + dest[1] = (bitmap / 256) as u8; + } +} diff --git a/core/trie/src/node_header.rs b/primitives/trie/src/node_header.rs similarity index 92% rename from core/trie/src/node_header.rs rename to primitives/trie/src/node_header.rs index 616273e574d60..edcd28a568bcd 100644 --- a/core/trie/src/node_header.rs +++ b/primitives/trie/src/node_header.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// Copyright 2015-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -18,11 +18,11 @@ use crate::trie_constants; use codec::{Encode, Decode, Input, Output}; -use rstd::iter::once; +use sp_std::iter::once; /// A node header #[derive(Copy, Clone, PartialEq, Eq)] -#[derive(primitives::RuntimeDebug)] +#[derive(sp_core::RuntimeDebug)] pub(crate) enum NodeHeader { Null, Branch(bool, usize), @@ -72,9 +72,9 @@ impl Decode for NodeHeader { /// Size encoding allows unlimited, length unefficient, representation, but /// is bounded to 16 bit maximum value to avoid possible DOS. pub(crate) fn size_and_prefix_iterator(size: usize, prefix: u8) -> impl Iterator { - let size = rstd::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, size); + let size = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, size); - let l1 = rstd::cmp::min(62, size); + let l1 = sp_std::cmp::min(62, size); let (first_byte, mut rem) = if size == l1 { (once(prefix + l1 as u8), 0) } else { @@ -94,7 +94,7 @@ pub(crate) fn size_and_prefix_iterator(size: usize, prefix: u8) -> impl Iterator None } }; - first_byte.chain(rstd::iter::from_fn(next_bytes)) + first_byte.chain(sp_std::iter::from_fn(next_bytes)) } /// Encodes size and prefix to a stream output. diff --git a/core/trie/src/trie_stream.rs b/primitives/trie/src/trie_stream.rs similarity index 95% rename from core/trie/src/trie_stream.rs rename to primitives/trie/src/trie_stream.rs index 2629cefac8c5e..0c92e673aae93 100644 --- a/core/trie/src/trie_stream.rs +++ b/primitives/trie/src/trie_stream.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// Copyright 2015-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Parity is free software: you can redistribute it and/or modify @@ -19,7 +19,7 @@ use hash_db::Hasher; use trie_root; use codec::Encode; -use rstd::vec::Vec; +use sp_std::vec::Vec; use crate::trie_constants; use crate::node_header::{NodeKind, size_and_prefix_iterator}; use crate::node_codec::Bitmap; @@ -51,7 +51,7 @@ fn branch_node_bit_mask(has_children: impl Iterator) -> (u8, u8) { /// Create a leaf/branch node, encoding a number of nibbles. fn fuse_nibbles_node<'a>(nibbles: &'a [u8], kind: NodeKind) -> impl Iterator + 'a { - let size = rstd::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibbles.len()); + let size = sp_std::cmp::min(trie_constants::NIBBLE_SIZE_BOUND, nibbles.len()); let iter_start = match kind { NodeKind::Leaf => size_and_prefix_iterator(size, trie_constants::LEAF_PREFIX_MASK), @@ -125,7 +125,7 @@ fn branch_node(has_value: bool, has_children: impl Iterator) -> [u8 result } -fn branch_node_buffered(has_value: bool, has_children: I, output: &mut[u8]) +fn branch_node_buffered(has_value: bool, has_children: I, output: &mut[u8]) where I: Iterator, { diff --git a/primitives/version/Cargo.toml b/primitives/version/Cargo.toml new file mode 100644 index 0000000000000..fbbf0cfa94607 --- /dev/null +++ b/primitives/version/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sp-version" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +impl-serde = { version = "0.2.3", optional = true } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.5", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } + +[features] +default = ["std"] +std = [ + "impl-serde", + "serde", + "codec/std", + "sp-std/std", + "sp-runtime/std", +] diff --git a/primitives/version/src/lib.rs b/primitives/version/src/lib.rs new file mode 100644 index 0000000000000..3211c46253631 --- /dev/null +++ b/primitives/version/src/lib.rs @@ -0,0 +1,270 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Version module for the Substrate runtime; Provides a function that returns the runtime version. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +#[cfg(feature = "std")] +use std::fmt; +#[cfg(feature = "std")] +use std::collections::HashSet; + +use codec::Encode; +#[cfg(feature = "std")] +use codec::Decode; +use sp_runtime::RuntimeString; +pub use sp_runtime::create_runtime_str; + +#[cfg(feature = "std")] +use sp_runtime::{traits::Block as BlockT, generic::BlockId}; + +/// The identity of a particular API interface that the runtime might provide. +pub type ApiId = [u8; 8]; + +/// A vector of pairs of `ApiId` and a `u32` for version. For `"std"` builds, this +/// is a `Cow`. +#[cfg(feature = "std")] +pub type ApisVec = std::borrow::Cow<'static, [(ApiId, u32)]>; +/// A vector of pairs of `ApiId` and a `u32` for version. For `"no-std"` builds, this +/// is just a reference. +#[cfg(not(feature = "std"))] +pub type ApisVec = &'static [(ApiId, u32)]; + +/// Create a vector of Api declarations. +#[macro_export] +#[cfg(feature = "std")] +macro_rules! create_apis_vec { + ( $y:expr ) => { std::borrow::Cow::Borrowed(& $y) } +} +#[macro_export] +#[cfg(not(feature = "std"))] +macro_rules! create_apis_vec { + ( $y:expr ) => { & $y } +} + +/// Runtime version. +/// This should not be thought of as classic Semver (major/minor/tiny). +/// This triplet have different semantics and mis-interpretation could cause problems. +/// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`, +/// absolutely not `impl_version` since they change the semantics of the runtime. +#[derive(Clone, PartialEq, Eq, Encode, Default, sp_runtime::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Decode))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +pub struct RuntimeVersion { + /// Identifies the different Substrate runtimes. There'll be at least polkadot and node. + /// A different on-chain spec_name to that of the native runtime would normally result + /// in node not attempting to sync or author blocks. + pub spec_name: RuntimeString, + + /// Name of the implementation of the spec. This is of little consequence for the node + /// and serves only to differentiate code of different implementation teams. For this + /// codebase, it will be parity-polkadot. If there were a non-Rust implementation of the + /// Polkadot runtime (e.g. C++), then it would identify itself with an accordingly different + /// `impl_name`. + pub impl_name: RuntimeString, + + /// `authoring_version` is the version of the authorship interface. An authoring node + /// will not attempt to author blocks unless this is equal to its native runtime. + pub authoring_version: u32, + + /// Version of the runtime specification. A full-node will not attempt to use its native + /// runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, + /// `spec_version` and `authoring_version` are the same between Wasm and native. + pub spec_version: u32, + + /// Version of the implementation of the specification. Nodes are free to ignore this; it + /// serves only as an indication that the code is different; as long as the other two versions + /// are the same then while the actual code may be different, it is nonetheless required to + /// do the same thing. + /// Non-consensus-breaking optimizations are about the only changes that could be made which + /// would result in only the `impl_version` changing. + pub impl_version: u32, + + /// List of supported API "features" along with their versions. + #[cfg_attr( + feature = "std", + serde( + serialize_with = "apis_serialize::serialize", + deserialize_with = "apis_serialize::deserialize", + ) + )] + pub apis: ApisVec, +} + +#[cfg(feature = "std")] +impl fmt::Display for RuntimeVersion { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}-{}:{}({}-{})", + self.spec_name, + self.spec_version, + self.authoring_version, + self.impl_name, + self.impl_version + ) + } +} + +#[cfg(feature = "std")] +impl RuntimeVersion { + /// Check if this version matches other version for calling into runtime. + pub fn can_call_with(&self, other: &RuntimeVersion) -> bool { + self.spec_version == other.spec_version && + self.spec_name == other.spec_name && + self.authoring_version == other.authoring_version + } + + /// Check if the given api with `api_id` is implemented and the version passes the given + /// `predicate`. + pub fn has_api_with bool>( + &self, + id: &ApiId, + predicate: P, + ) -> bool { + self.apis.iter().any(|(s, v)| s == id && predicate(*v)) + } +} + +#[cfg(feature = "std")] +#[derive(Debug)] +pub struct NativeVersion { + /// Basic runtime version info. + pub runtime_version: RuntimeVersion, + /// Authoring runtimes that this native runtime supports. + pub can_author_with: HashSet, +} + +#[cfg(feature = "std")] +impl NativeVersion { + /// Check if this version matches other version for authoring blocks. + /// + /// # Return + /// + /// - Returns `Ok(())` when authoring is supported. + /// - Returns `Err(_)` with a detailed error when authoring is not supported. + pub fn can_author_with(&self, other: &RuntimeVersion) -> Result<(), String> { + if self.runtime_version.spec_name != other.spec_name { + Err(format!( + "`spec_name` does not match `{}` vs `{}`", + self.runtime_version.spec_name, + other.spec_name, + )) + } else if self.runtime_version.authoring_version != other.authoring_version + && !self.can_author_with.contains(&other.authoring_version) + { + Err(format!( + "`authoring_version` does not match `{version}` vs `{other_version}` and \ + `can_author_with` not contains `{other_version}`", + version = self.runtime_version.authoring_version, + other_version = other.authoring_version, + )) + } else { + Ok(()) + } + } +} + +/// Something that can provide the runtime version at a given block and the native runtime version. +#[cfg(feature = "std")] +pub trait GetRuntimeVersion { + /// Returns the version of the native runtime. + fn native_version(&self) -> &NativeVersion; + + /// Returns the version of runtime at the given block. + fn runtime_version(&self, at: &BlockId) -> Result; +} + +#[cfg(feature = "std")] +impl, Block: BlockT> GetRuntimeVersion for std::sync::Arc { + fn native_version(&self) -> &NativeVersion { + (&**self).native_version() + } + + fn runtime_version(&self, at: &BlockId) -> Result { + (&**self).runtime_version(at) + } +} + +#[cfg(feature = "std")] +mod apis_serialize { + use super::*; + use impl_serde::serialize as bytes; + use serde::{Serializer, de, 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) + } + + #[derive(Deserialize)] + struct ApiIdOwned( + #[serde(deserialize_with="deserialize_bytes")] + super::ApiId, + u32, + ); + + pub fn deserialize<'de, D>(deserializer: D) -> Result where + D: de::Deserializer<'de>, + { + struct Visitor; + impl<'de> de::Visitor<'de> for Visitor { + type Value = ApisVec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence of api id and version tuples") + } + + fn visit_seq(self, mut visitor: V) -> Result where + V: de::SeqAccess<'de>, + { + let mut apis = Vec::new(); + while let Some(value) = visitor.next_element::()? { + apis.push((value.0, value.1)); + } + Ok(apis.into()) + } + } + deserializer.deserialize_seq(Visitor) + } + + pub fn deserialize_bytes<'de, D>(d: D) -> Result where + D: de::Deserializer<'de> + { + let mut arr = [0; 8]; + bytes::deserialize_check_len(d, bytes::ExpectedLen::Exact(&mut arr[..]))?; + Ok(arr) + } +} diff --git a/primitives/wasm-interface/Cargo.toml b/primitives/wasm-interface/Cargo.toml new file mode 100644 index 0000000000000..8f44c8895cfa7 --- /dev/null +++ b/primitives/wasm-interface/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sp-wasm-interface" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +wasmi = "0.6.2" +impl-trait-for-tuples = "0.1.2" diff --git a/primitives/wasm-interface/src/lib.rs b/primitives/wasm-interface/src/lib.rs new file mode 100644 index 0000000000000..bc34bfda9700b --- /dev/null +++ b/primitives/wasm-interface/src/lib.rs @@ -0,0 +1,405 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Types and traits for interfacing between the host and the wasm runtime. + +use std::{borrow::Cow, marker::PhantomData, mem, iter::Iterator, result}; + +mod wasmi_impl; + +/// Result type used by traits in this crate. +pub type Result = result::Result; + +/// Value types supported by Substrate on the boundary between host/Wasm. +#[derive(Copy, Clone, PartialEq, Debug, Eq)] +pub enum ValueType { + /// An `i32` value type. + I32, + /// An `i64` value type. + I64, + /// An `f32` value type. + F32, + /// An `f64` value type. + F64, +} + +/// Values supported by Substrate on the boundary between host/Wasm. +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum Value { + /// An `i32` value. + I32(i32), + /// An `i64` value. + I64(i64), + /// An nan-preserving `f32` value. + F32(u32), + /// An nan-preserving `f64` value. + F64(u64), +} + +impl Value { + /// Returns the type of this value. + pub fn value_type(&self) -> ValueType { + match self { + Value::I32(_) => ValueType::I32, + Value::I64(_) => ValueType::I64, + Value::F32(_) => ValueType::F32, + Value::F64(_) => ValueType::F64, + } + } +} + +/// Provides `Sealed` trait to prevent implementing trait `PointerType` outside of this crate. +mod private { + pub trait Sealed {} + + impl Sealed for u8 {} + impl Sealed for u16 {} + impl Sealed for u32 {} + impl Sealed for u64 {} +} + +/// Something that can be wrapped in a wasm `Pointer`. +/// +/// This trait is sealed. +pub trait PointerType: Sized { + /// The size of the type in wasm. + const SIZE: u32 = mem::size_of::() as u32; +} + +impl PointerType for u8 {} +impl PointerType for u16 {} +impl PointerType for u32 {} +impl PointerType for u64 {} + +/// Type to represent a pointer in wasm at the host. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Pointer { + ptr: u32, + _marker: PhantomData, +} + +impl Pointer { + /// Create a new instance of `Self`. + pub fn new(ptr: u32) -> Self { + Self { + ptr, + _marker: Default::default(), + } + } + + /// Calculate the offset from this pointer. + /// + /// `offset` is in units of `T`. So, `3` means `3 * mem::size_of::()` as offset to the pointer. + /// + /// Returns an `Option` to respect that the pointer could probably overflow. + pub fn offset(self, offset: u32) -> Option { + offset.checked_mul(T::SIZE).and_then(|o| self.ptr.checked_add(o)).map(|ptr| { + Self { + ptr, + _marker: Default::default(), + } + }) + } + + /// Create a null pointer. + pub fn null() -> Self { + Self::new(0) + } + + /// Cast this pointer of type `T` to a pointer of type `R`. + pub fn cast(self) -> Pointer { + Pointer::new(self.ptr) + } +} + +impl From> for u32 { + fn from(ptr: Pointer) -> Self { + ptr.ptr + } +} + +impl From> for u64 { + fn from(ptr: Pointer) -> Self { + u64::from(ptr.ptr) + } +} + +impl From> for usize { + fn from(ptr: Pointer) -> Self { + ptr.ptr as _ + } +} + +impl IntoValue for Pointer { + const VALUE_TYPE: ValueType = ValueType::I32; + fn into_value(self) -> Value { Value::I32(self.ptr as _) } +} + +impl TryFromValue for Pointer { + fn try_from_value(val: Value) -> Option { + match val { + Value::I32(val) => Some(Self::new(val as _)), + _ => None, + } + } +} + +/// The word size used in wasm. Normally known as `usize` in Rust. +pub type WordSize = u32; + +/// The Signature of a function +#[derive(Eq, PartialEq, Debug, Clone)] +pub struct Signature { + /// The arguments of a function. + pub args: Cow<'static, [ValueType]>, + /// The optional return value of a function. + pub return_value: Option, +} + +impl Signature { + /// Create a new instance of `Signature`. + pub fn new>>(args: T, return_value: Option) -> Self { + Self { + args: args.into(), + return_value, + } + } + + /// Create a new instance of `Signature` with the given `args` and without any return value. + pub fn new_with_args>>(args: T) -> Self { + Self { + args: args.into(), + return_value: None, + } + } + +} + +/// Something that provides a function implementation on the host for a wasm function. +pub trait Function: std::panic::RefUnwindSafe + Send + Sync { + /// Returns the name of this function. + fn name(&self) -> &str; + /// Returns the signature of this function. + fn signature(&self) -> Signature; + /// Execute this function with the given arguments. + fn execute( + &self, + context: &mut dyn FunctionContext, + args: &mut dyn Iterator, + ) -> Result>; +} + +impl PartialEq for dyn Function { + fn eq(&self, other: &Self) -> bool { + other.name() == self.name() && other.signature() == self.signature() + } +} + +/// Context used by `Function` to interact with the allocator and the memory of the wasm instance. +pub trait FunctionContext { + /// Read memory from `address` into a vector. + fn read_memory(&self, address: Pointer, size: WordSize) -> Result> { + let mut vec = Vec::with_capacity(size as usize); + vec.resize(size as usize, 0); + self.read_memory_into(address, &mut vec)?; + Ok(vec) + } + /// Read memory into the given `dest` buffer from `address`. + fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> Result<()>; + /// Write the given data at `address` into the memory. + fn write_memory(&mut self, address: Pointer, data: &[u8]) -> Result<()>; + /// Allocate a memory instance of `size` bytes. + fn allocate_memory(&mut self, size: WordSize) -> Result>; + /// Deallocate a given memory instance. + fn deallocate_memory(&mut self, ptr: Pointer) -> Result<()>; + /// Provides access to the sandbox. + fn sandbox(&mut self) -> &mut dyn Sandbox; +} + +/// Sandbox memory identifier. +pub type MemoryId = u32; + +/// Something that provides access to the sandbox. +pub trait Sandbox { + /// Get sandbox memory from the `memory_id` instance at `offset` into the given buffer. + fn memory_get( + &mut self, + memory_id: MemoryId, + offset: WordSize, + buf_ptr: Pointer, + buf_len: WordSize, + ) -> Result; + /// Set sandbox memory from the given value. + fn memory_set( + &mut self, + memory_id: MemoryId, + offset: WordSize, + val_ptr: Pointer, + val_len: WordSize, + ) -> Result; + /// Delete a memory instance. + fn memory_teardown(&mut self, memory_id: MemoryId) -> Result<()>; + /// Create a new memory instance with the given `initial` size and the `maximum` size. + /// The size is given in wasm pages. + fn memory_new(&mut self, initial: u32, maximum: u32) -> Result; + /// Invoke an exported function by a name. + fn invoke( + &mut self, + instance_id: u32, + export_name: &str, + args: &[u8], + return_val: Pointer, + return_val_len: WordSize, + state: u32, + ) -> Result; + /// Delete a sandbox instance. + fn instance_teardown(&mut self, instance_id: u32) -> Result<()>; + /// Create a new sandbox instance. + fn instance_new( + &mut self, + dispatch_thunk_id: u32, + wasm: &[u8], + raw_env_def: &[u8], + state: u32, + ) -> Result; +} + +/// Something that provides implementations for host functions. +pub trait HostFunctions: 'static { + /// Returns the host functions `Self` provides. + fn host_functions() -> Vec<&'static dyn Function>; +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl HostFunctions for Tuple { + fn host_functions() -> Vec<&'static dyn Function> { + let mut host_functions = Vec::new(); + + for_tuples!( #( host_functions.extend(Tuple::host_functions()); )* ); + + host_functions + } +} + +/// Something that can be converted into a wasm compatible `Value`. +pub trait IntoValue { + /// The type of the value in wasm. + const VALUE_TYPE: ValueType; + + /// Convert `self` into a wasm `Value`. + fn into_value(self) -> Value; +} + +/// Something that can may be created from a wasm `Value`. +pub trait TryFromValue: Sized { + /// Try to convert the given `Value` into `Self`. + fn try_from_value(val: Value) -> Option; +} + +macro_rules! impl_into_and_from_value { + ( + $( + $type:ty, $( < $gen:ident >, )? $value_variant:ident, + )* + ) => { + $( + impl $( <$gen> )? IntoValue for $type { + const VALUE_TYPE: ValueType = ValueType::$value_variant; + fn into_value(self) -> Value { Value::$value_variant(self as _) } + } + + impl $( <$gen> )? TryFromValue for $type { + fn try_from_value(val: Value) -> Option { + match val { + Value::$value_variant(val) => Some(val as _), + _ => None, + } + } + } + )* + } +} + +impl_into_and_from_value! { + u8, I32, + u16, I32, + u32, I32, + u64, I64, + i8, I32, + i16, I32, + i32, I32, + i64, I64, +} + +/// Something that can write a primitive to wasm memory location. +pub trait WritePrimitive { + /// Write the given value `t` to the given memory location `ptr`. + fn write_primitive(&mut self, ptr: Pointer, t: T) -> Result<()>; +} + +impl WritePrimitive for &mut dyn FunctionContext { + fn write_primitive(&mut self, ptr: Pointer, t: u32) -> Result<()> { + let r = t.to_le_bytes(); + self.write_memory(ptr.cast(), &r) + } +} + +impl WritePrimitive for &mut dyn FunctionContext { + fn write_primitive(&mut self, ptr: Pointer, t: u64) -> Result<()> { + let r = t.to_le_bytes(); + self.write_memory(ptr.cast(), &r) + } +} + +/// Something that can read a primitive from a wasm memory location. +pub trait ReadPrimitive { + /// Read a primitive from the given memory location `ptr`. + fn read_primitive(&self, ptr: Pointer) -> Result; +} + +impl ReadPrimitive for &mut dyn FunctionContext { + fn read_primitive(&self, ptr: Pointer) -> Result { + let mut r = [0u8; 4]; + self.read_memory_into(ptr.cast(), &mut r)?; + Ok(u32::from_le_bytes(r)) + } +} + +impl ReadPrimitive for &mut dyn FunctionContext { + fn read_primitive(&self, ptr: Pointer) -> Result { + let mut r = [0u8; 8]; + self.read_memory_into(ptr.cast(), &mut r)?; + Ok(u64::from_le_bytes(r)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn pointer_offset_works() { + let ptr = Pointer::::null(); + + assert_eq!(ptr.offset(10).unwrap(), Pointer::new(40)); + assert_eq!(ptr.offset(32).unwrap(), Pointer::new(128)); + + let ptr = Pointer::::null(); + + assert_eq!(ptr.offset(10).unwrap(), Pointer::new(80)); + assert_eq!(ptr.offset(32).unwrap(), Pointer::new(256)); + } +} diff --git a/core/wasm-interface/src/wasmi_impl.rs b/primitives/wasm-interface/src/wasmi_impl.rs similarity index 97% rename from core/wasm-interface/src/wasmi_impl.rs rename to primitives/wasm-interface/src/wasmi_impl.rs index be9b724d29b74..dea8519b711a7 100644 --- a/core/wasm-interface/src/wasmi_impl.rs +++ b/primitives/wasm-interface/src/wasmi_impl.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify diff --git a/scripts/common.sh b/scripts/common.sh deleted file mode 100644 index 8aff9acc578ec..0000000000000 --- a/scripts/common.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -ROOT=`dirname "$0"` - -# A list of directories which contain wasm projects. -SRCS=( - "core/executor/wasm" - "node/runtime/wasm" - "node-template/runtime/wasm" - "core/test-runtime/wasm" -) - -# Make pushd/popd silent. - -pushd () { - command pushd "$@" > /dev/null -} - -popd () { - command popd "$@" > /dev/null -} diff --git a/scripts/node-template-release.sh b/scripts/node-template-release.sh deleted file mode 100755 index 3b2c0d6f0f6b8..0000000000000 --- a/scripts/node-template-release.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/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/src/main.rs b/scripts/node-template-release/src/main.rs deleted file mode 100644 index e1db5af649748..0000000000000 --- a/scripts/node-template-release/src/main.rs +++ /dev/null @@ -1,242 +0,0 @@ -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()); -} - -/// Update the top level (workspace) `Cargo.toml` file. -/// -/// - Adds `profile.release` = `panic = unwind` -/// - Adds `workspace` definition -fn update_top_level_cargo_toml( - cargo_toml: &mut CargoToml, - workspace_members: Vec<&PathBuf>, - node_template_path: &Path, -) { - let mut panic_unwind = toml::value::Table::new(); - panic_unwind.insert("panic".into(), "unwind".into()); - - let mut profile = toml::value::Table::new(); - profile.insert("release".into(), panic_unwind.into()); - - cargo_toml.insert("profile".into(), profile.into()); - - let members = workspace_members.iter() - .map(|p| - p.strip_prefix(node_template_path) - .expect("Workspace member is a child of the node template path!") - .parent() - // We get the `Cargo.toml` paths as workspace members, but for the `members` field - // we just need the path. - .expect("The given path ends with `Cargo.toml` as file name!") - .display() - .to_string() - ) - .collect::>(); - - let mut members_section = toml::value::Table::new(); - members_section.insert("members".into(), members.into()); - - cargo_toml.insert("workspace".into(), members_section.into()); -} - -fn write_cargo_toml(path: &Path, cargo_toml: CargoToml) { - 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 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); - let top_level_cargo_toml_path = node_template_path.join("Cargo.toml"); - - cargo_tomls.iter().for_each(|t| { - let mut cargo_toml = parse_cargo_toml(&t); - replace_path_dependencies_with_git(&t, &commit_id, &mut cargo_toml); - - // Check if this is the top level `Cargo.toml`, as this requires some special treatments. - if top_level_cargo_toml_path == *t { - // All workspace member `Cargo.toml` file paths. - let workspace_members = cargo_tomls.iter() - .filter(|p| **p != top_level_cargo_toml_path) - .collect(); - - update_top_level_cargo_toml(&mut cargo_toml, workspace_members, &node_template_path); - } - - write_cargo_toml(&t, cargo_toml); - }); - - 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/scripts/update.sh b/scripts/update.sh deleted file mode 100755 index a264fab43df30..0000000000000 --- a/scripts/update.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -# This script assumes that all pre-requisites are installed. - -set -e - -PROJECT_ROOT=`git rev-parse --show-toplevel` -source `dirname "$0"`/common.sh - -export CARGO_INCREMENTAL=0 - -# Save current directory. -pushd . - -cd $ROOT - -for SRC in "${SRCS[@]}" -do - echo "*** Updating and building wasm binaries in $SRC" - cd "$PROJECT_ROOT/$SRC" - - cargo update - ./build.sh "$@" - - cd - >> /dev/null -done - -# Restore initial directory. -popd diff --git a/srml/README.adoc b/srml/README.adoc deleted file mode 100644 index 05da2de0a0357..0000000000000 --- a/srml/README.adoc +++ /dev/null @@ -1,26 +0,0 @@ - -= SRML - -The Substrate Runtime Module Library (SRML) is a collection of runtime modules. - -== What are runtime modules? - -A Substrate runtime can be composed of several smaller components for separation of concerns. These components are called runtime _modules_. Each runtime module packages together a set of functions (dispatchable extrinsic calls, public or private, mutable or immutable), storage items, and events. - -There are four primary components that support runtime modules: - -=== system module - -https://github.com/paritytech/substrate/tree/master/srml/system[`system`] provides low-level APIs and utilities for other modules. https://github.com/paritytech/substrate/tree/master/srml/system[`system`] also defines all core types and extrinsic events for the Substrate runtime. *All modules depend on the system module.* - -=== executive module - -https://github.com/paritytech/substrate/tree/master/srml/executive[`executive`] dispatches incoming extrinsic calls to the respective modules in the runtime. - -=== support macros - -https://github.com/paritytech/substrate/tree/master/srml/support[`support` macros] are a collection of Rust macros to facilitate the implementation of common module components. https://github.com/paritytech/substrate/tree/master/srml/support[`support` macros] expand at runtime to generate types (e.g. `Module`, `Call`, `Store`, `Event`) which are thereafter used by the runtime to communicate with the modules. Common support macros include https://crates.parity.io/srml_support/macro.decl_module.html[`decl_module`], https://crates.parity.io/srml_support_procedural/macro.decl_storage.html[`decl_storage`], https://crates.parity.io/srml_support/macro.decl_event.html[`decl_event`], and https://crates.parity.io/srml_support/macro.ensure.html[`ensure`]. - -=== runtime - -The runtime expands the support macros to get type and trait implementations for each module before calling https://github.com/paritytech/substrate/tree/master/srml/executive[`executive`] to dispatch calls to the individual modules. To see an example of how this might look, see https://github.com/paritytech/substrate/blob/master/node/runtime/src/lib.rs[`../node/runtime`]. \ No newline at end of file diff --git a/srml/assets/Cargo.toml b/srml/assets/Cargo.toml deleted file mode 100644 index 052a3045b2164..0000000000000 --- a/srml/assets/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "srml-assets" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -# Needed for various traits. In our case, `OnFinalize`. -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -# Needed for type-safe access to storage DB. -support = { package = "srml-support", path = "../support", default-features = false } -# `system` module provides us with all sorts of useful stuff and macros depend on it being around. -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -rstd = { package = "sr-std", path = "../../core/sr-std" } -runtime-io = { package = "sr-io", path = "../../core/sr-io" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "sr-primitives/std", - "support/std", - "system/std", -] diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs deleted file mode 100644 index 5c8b1bbd610a3..0000000000000 --- a/srml/assets/src/lib.rs +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Assets Module -//! -//! A simple, secure module for dealing with fungible assets. -//! -//! ## Overview -//! -//! The Assets module provides functionality for asset management of fungible asset classes -//! with a fixed supply, including: -//! -//! * Asset Issuance -//! * Asset Transfer -//! * Asset Destruction -//! -//! To use it in your runtime, you need to implement the assets [`Trait`](./trait.Trait.html). -//! -//! The supported dispatchable functions are documented in the [`Call`](./enum.Call.html) enum. -//! -//! ### Terminology -//! -//! * **Asset issuance:** The creation of a new asset, whose total supply will belong to the -//! account that issues the asset. -//! * **Asset transfer:** The action of transferring assets from one account to another. -//! * **Asset destruction:** The process of an account removing its entire holding of an asset. -//! * **Fungible asset:** An asset whose units are interchangeable. -//! * **Non-fungible asset:** An asset for which each unit has unique characteristics. -//! -//! ### Goals -//! -//! The assets system in Substrate is designed to make the following possible: -//! -//! * Issue a unique asset to its creator's account. -//! * Move assets between accounts. -//! * Remove an account's balance of an asset when requested by that account's owner and update -//! the asset's total supply. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! * `issue` - Issues the total supply of a new fungible asset to the account of the caller of the function. -//! * `transfer` - Transfers an `amount` of units of fungible asset `id` from the balance of -//! the function caller's account (`origin`) to a `target` account. -//! * `destroy` - Destroys the entire holding of a fungible asset `id` associated with the account -//! that called the function. -//! -//! Please refer to the [`Call`](./enum.Call.html) enum and its associated variants for documentation on each function. -//! -//! ### Public Functions -//! -//! -//! * `balance` - Get the asset `id` balance of `who`. -//! * `total_supply` - Get the total supply of an asset `id`. -//! -//! Please refer to the [`Module`](./struct.Module.html) struct for details on publicly available functions. -//! -//! ## Usage -//! -//! The following example shows how to use the Assets module in your runtime by exposing public functions to: -//! -//! * Issue a new fungible asset for a token distribution event (airdrop). -//! * Query the fungible asset holding balance of an account. -//! * Query the total supply of a fungible asset that has been issued. -//! -//! ### Prerequisites -//! -//! Import the Assets module and types and derive your runtime's configuration traits from the Assets module trait. -//! -//! ### Simple Code Snippet -//! -//! ```rust,ignore -//! use support::{decl_module, dispatch::Result}; -//! use system::ensure_signed; -//! -//! pub trait Trait: assets::Trait { } -//! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! pub fn issue_token_airdrop(origin) -> Result { -//! const ACCOUNT_ALICE: u64 = 1; -//! const ACCOUNT_BOB: u64 = 2; -//! const COUNT_AIRDROP_RECIPIENTS = 2; -//! const TOKENS_FIXED_SUPPLY: u64 = 100; -//! -//! ensure!(!COUNT_AIRDROP_RECIPIENTS.is_zero(), "Divide by zero error."); -//! -//! let sender = ensure_signed(origin)?; -//! let asset_id = Self::next_asset_id(); -//! -//! >::mutate(|asset_id| *asset_id += 1); -//! >::insert((asset_id, &ACCOUNT_ALICE), TOKENS_FIXED_SUPPLY / COUNT_AIRDROP_RECIPIENTS); -//! >::insert((asset_id, &ACCOUNT_BOB), TOKENS_FIXED_SUPPLY / COUNT_AIRDROP_RECIPIENTS); -//! >::insert(asset_id, TOKENS_FIXED_SUPPLY); -//! -//! Self::deposit_event(RawEvent::Issued(asset_id, sender, TOKENS_FIXED_SUPPLY)); -//! Ok(()) -//! } -//! } -//! } -//! ``` -//! -//! ## Assumptions -//! -//! Below are assumptions that must be held when using this module. If any of -//! them are violated, the behavior of this module is undefined. -//! -//! * The total count of assets should be less than -//! `Trait::AssetId::max_value()`. -//! -//! ## Related Modules -//! -//! * [`System`](../srml_system/index.html) -//! * [`Support`](../srml_support/index.html) - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -use support::{Parameter, decl_module, decl_event, decl_storage, ensure}; -use sr_primitives::traits::{Member, SimpleArithmetic, Zero, StaticLookup}; -use system::ensure_signed; -use sr_primitives::traits::One; - -/// The module configuration trait. -pub trait Trait: system::Trait { - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// The units in which we record balances. - type Balance: Member + Parameter + SimpleArithmetic + Default + Copy; - - /// The arithmetic type of asset identifier. - type AssetId: Parameter + SimpleArithmetic + Default + Copy; -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - 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, #[compact] total: T::Balance) { - let origin = ensure_signed(origin)?; - - let id = Self::next_asset_id(); - >::mutate(|id| *id += One::one()); - - >::insert((id, &origin), total); - >::insert(id, total); - - Self::deposit_event(RawEvent::Issued(id, origin, total)); - } - - /// Move some assets from one holder to another. - fn transfer(origin, - #[compact] id: T::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"); - - Self::deposit_event(RawEvent::Transferred(id, origin, target.clone(), amount)); - >::insert(origin_account, origin_balance - amount); - >::mutate((id, target), |balance| *balance += amount); - } - - /// Destroy any assets of `id` owned by `origin`. - fn destroy(origin, #[compact] id: T::AssetId) { - let origin = ensure_signed(origin)?; - let balance = >::take((id, &origin)); - ensure!(!balance.is_zero(), "origin balance should be non-zero"); - - >::mutate(id, |total_supply| *total_supply -= balance); - Self::deposit_event(RawEvent::Destroyed(id, origin, balance)); - } - } -} - -decl_event!( - pub enum Event where - ::AccountId, - ::Balance, - ::AssetId, - { - /// Some assets were issued. - Issued(AssetId, AccountId, Balance), - /// Some assets were transferred. - Transferred(AssetId, AccountId, AccountId, Balance), - /// Some assets were destroyed. - Destroyed(AssetId, AccountId, Balance), - } -); - -decl_storage! { - trait Store for Module as Assets { - /// The number of units of assets held by any given account. - Balances: map (T::AssetId, T::AccountId) => T::Balance; - /// The next asset identifier up for grabs. - NextAssetId get(fn next_asset_id): T::AssetId; - /// The total unit supply of an asset. - TotalSupply: map T::AssetId => T::Balance; - } -} - -// The main implementation block for the module. -impl Module { - // Public immutables - - /// Get the asset `id` balance of `who`. - pub fn balance(id: T::AssetId, who: T::AccountId) -> T::Balance { - >::get((id, who)) - } - - /// Get the total supply of an asset `id`. - pub fn total_supply(id: T::AssetId) -> T::Balance { - >::get(id) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use support::{impl_outer_origin, assert_ok, assert_noop, parameter_types}; - use primitives::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. - use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - // For testing the module, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of modules we want to use. - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type Call = (); - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - impl Trait for Test { - type Event = (); - type Balance = u64; - type AssetId = u32; - } - type Assets = 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().into() - } - - #[test] - fn issuing_asset_units_to_issuer_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Assets::issue(Origin::signed(1), 100)); - assert_eq!(Assets::balance(0, 1), 100); - }); - } - - #[test] - fn querying_total_supply_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Assets::issue(Origin::signed(1), 100)); - assert_eq!(Assets::balance(0, 1), 100); - assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); - assert_eq!(Assets::balance(0, 1), 50); - assert_eq!(Assets::balance(0, 2), 50); - assert_ok!(Assets::transfer(Origin::signed(2), 0, 3, 31)); - assert_eq!(Assets::balance(0, 1), 50); - assert_eq!(Assets::balance(0, 2), 19); - assert_eq!(Assets::balance(0, 3), 31); - assert_ok!(Assets::destroy(Origin::signed(3), 0)); - assert_eq!(Assets::total_supply(0), 69); - }); - } - - #[test] - fn transferring_amount_above_available_balance_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Assets::issue(Origin::signed(1), 100)); - assert_eq!(Assets::balance(0, 1), 100); - assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); - assert_eq!(Assets::balance(0, 1), 50); - assert_eq!(Assets::balance(0, 2), 50); - }); - } - - #[test] - fn transferring_amount_more_than_available_balance_should_not_work() { - new_test_ext().execute_with(|| { - assert_ok!(Assets::issue(Origin::signed(1), 100)); - assert_eq!(Assets::balance(0, 1), 100); - assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); - assert_eq!(Assets::balance(0, 1), 50); - assert_eq!(Assets::balance(0, 2), 50); - assert_ok!(Assets::destroy(Origin::signed(1), 0)); - assert_eq!(Assets::balance(0, 1), 0); - assert_noop!(Assets::transfer(Origin::signed(1), 0, 1, 50), "origin account balance must be greater than or equal to the transfer amount"); - }); - } - - #[test] - fn transferring_less_than_one_unit_should_not_work() { - new_test_ext().execute_with(|| { - assert_ok!(Assets::issue(Origin::signed(1), 100)); - assert_eq!(Assets::balance(0, 1), 100); - assert_noop!(Assets::transfer(Origin::signed(1), 0, 2, 0), "transfer amount should be non-zero"); - }); - } - - #[test] - fn transferring_more_units_than_total_supply_should_not_work() { - new_test_ext().execute_with(|| { - assert_ok!(Assets::issue(Origin::signed(1), 100)); - assert_eq!(Assets::balance(0, 1), 100); - assert_noop!(Assets::transfer(Origin::signed(1), 0, 2, 101), "origin account balance must be greater than or equal to the transfer amount"); - }); - } - - #[test] - fn destroying_asset_balance_with_positive_balance_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Assets::issue(Origin::signed(1), 100)); - assert_eq!(Assets::balance(0, 1), 100); - assert_ok!(Assets::destroy(Origin::signed(1), 0)); - }); - } - - #[test] - fn destroying_asset_balance_with_zero_balance_should_not_work() { - new_test_ext().execute_with(|| { - assert_ok!(Assets::issue(Origin::signed(1), 100)); - assert_eq!(Assets::balance(0, 2), 0); - assert_noop!(Assets::destroy(Origin::signed(2), 0), "origin balance should be non-zero"); - }); - } -} diff --git a/srml/aura/Cargo.toml b/srml/aura/Cargo.toml deleted file mode 100644 index f1c37b7c08d45..0000000000000 --- a/srml/aura/Cargo.toml +++ /dev/null @@ -1,41 +0,0 @@ -[package] -name = "srml-aura" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -serde = { version = "1.0.101", optional = true } -session = { package = "srml-session", path = "../session", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -substrate-consensus-aura-primitives = { path = "../../core/consensus/aura/primitives", default-features = false} -system = { package = "srml-system", path = "../system", default-features = false } -timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } - -[dev-dependencies] -lazy_static = "1.4.0" -parking_lot = "0.9.0" - -[features] -default = ["std"] -std = [ - "app-crypto/std", - "codec/std", - "inherents/std", - "runtime-io/std", - "primitives/std", - "rstd/std", - "serde", - "sr-primitives/std", - "support/std", - "substrate-consensus-aura-primitives/std", - "system/std", - "timestamp/std", -] diff --git a/srml/aura/src/lib.rs b/srml/aura/src/lib.rs deleted file mode 100644 index f9034c7ca046b..0000000000000 --- a/srml/aura/src/lib.rs +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Aura Module -//! -//! - [`aura::Trait`](./trait.Trait.html) -//! - [`Module`](./struct.Module.html) -//! -//! ## Overview -//! -//! The Aura module extends Aura consensus by managing offline reporting. -//! -//! ## Interface -//! -//! ### Public Functions -//! -//! - `slot_duration` - Determine the Aura slot-duration based on the Timestamp module configuration. -//! -//! ## Related Modules -//! -//! - [Timestamp](../srml_timestamp/index.html): The Timestamp module is used in Aura to track -//! consensus rounds (via `slots`). -//! - [Consensus](../srml_consensus/index.html): The Consensus module does not relate directly to Aura, -//! but serves to manage offline reporting by implementing `ProvideInherent` in a similar way. -//! -//! ## References -//! -//! If you're interested in hacking on this module, it is useful to understand the interaction with -//! `substrate/core/inherents/src/lib.rs` and, specifically, the required implementation of -//! [`ProvideInherent`](../substrate_inherents/trait.ProvideInherent.html) and -//! [`ProvideInherentData`](../substrate_inherents/trait.ProvideInherentData.html) to create and check inherents. - -#![cfg_attr(not(feature = "std"), no_std)] - -pub use timestamp; - -use rstd::{result, prelude::*}; -use codec::{Encode, Decode}; -use support::{ - decl_storage, decl_module, Parameter, traits::{Get, FindAuthor}, - ConsensusEngineId, -}; -use sr_primitives::{ - RuntimeAppPublic, - traits::{SaturatedConversion, Saturating, Zero, Member, IsMember}, generic::DigestItem, -}; -use timestamp::OnTimestampSet; -#[cfg(feature = "std")] -use timestamp::TimestampInherentData; -use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; -#[cfg(feature = "std")] -use inherents::{InherentDataProviders, ProvideInherentData}; -use substrate_consensus_aura_primitives::{AURA_ENGINE_ID, ConsensusLog, AuthorityIndex}; - -mod mock; -mod tests; - -/// The Aura inherent identifier. -pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"auraslot"; - -/// The type of the Aura inherent. -pub type InherentType = u64; - -/// 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); -} - -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())) - } - - fn aura_replace_inherent_data(&mut self, new: InherentType) { - self.replace_data(INHERENT_IDENTIFIER, &new); - } -} - -/// Provides the slot duration inherent data for `Aura`. -#[cfg(feature = "std")] -pub struct InherentDataProvider { - slot_duration: u64, -} - -#[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).ok() - } -} - -pub trait Trait: timestamp::Trait { - /// The identifier type for an authority. - type AuthorityId: Member + Parameter + RuntimeAppPublic + Default; -} - -decl_storage! { - trait Store for Module as Aura { - /// The last timestamp. - LastTimestamp get(fn last) build(|_| 0.into()): T::Moment; - - /// The current authorities - pub Authorities get(fn authorities): Vec; - } - add_extra_genesis { - config(authorities): Vec; - build(|config| Module::::initialize_authorities(&config.authorities)) - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { } -} - -impl Module { - fn change_authorities(new: Vec) { - >::put(&new); - - let log: DigestItem = DigestItem::Consensus( - AURA_ENGINE_ID, - ConsensusLog::AuthoritiesChange(new).encode() - ); - >::deposit_log(log.into()); - } - - fn initialize_authorities(authorities: &[T::AuthorityId]) { - if !authorities.is_empty() { - assert!(>::get().is_empty(), "Authorities are already initialized!"); - >::put(authorities); - } - } -} - -impl session::OneSessionHandler for Module { - type Key = T::AuthorityId; - - fn on_genesis_session<'a, I: 'a>(validators: I) - where I: Iterator - { - let authorities = validators.map(|(_, k)| k).collect::>(); - Self::initialize_authorities(&authorities); - } - - fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) - where I: Iterator - { - // instant changes - if changed { - let next_authorities = validators.map(|(_, k)| k).collect::>(); - let last_authorities = >::authorities(); - if next_authorities != last_authorities { - Self::change_authorities(next_authorities); - } - } - } - - fn on_disabled(i: usize) { - let log: DigestItem = DigestItem::Consensus( - AURA_ENGINE_ID, - ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), - ); - - >::deposit_log(log.into()); - } -} - -impl FindAuthor for Module { - fn find_author<'a, I>(digests: I) -> Option where - I: 'a + IntoIterator - { - for (id, mut data) in digests.into_iter() { - if id == AURA_ENGINE_ID { - if let Ok(slot_num) = u64::decode(&mut data) { - let author_index = slot_num % Self::authorities().len() as u64; - return Some(author_index as u32) - } - } - } - - None - } -} - -impl IsMember for Module { - fn is_member(authority_id: &T::AuthorityId) -> bool { - Self::authorities() - .iter() - .any(|id| id == authority_id) - } -} - -impl Module { - /// Determine the Aura slot-duration based on the Timestamp module configuration. - pub fn slot_duration() -> T::Moment { - // we double the minimum block-period so each author can always propose within - // the majority of its slot. - ::MinimumPeriod::get().saturating_mul(2.into()) - } - - fn on_timestamp_set(now: T::Moment, slot_duration: T::Moment) { - let last = Self::last(); - ::LastTimestamp::put(now); - - if last.is_zero() { - return; - } - - assert!(!slot_duration.is_zero(), "Aura slot duration cannot be zero."); - - let last_slot = last / slot_duration; - let cur_slot = now / slot_duration; - - assert!(last_slot < cur_slot, "Only one block may be authored per slot."); - - // TODO [#3398] Generate offence report for all authorities that skipped their slots. - } -} - -impl OnTimestampSet for Module { - fn on_timestamp_set(moment: T::Moment) { - Self::on_timestamp_set(moment, Self::slot_duration()) - } -} - -impl ProvideInherent for Module { - type Call = timestamp::Call; - type Error = MakeFatalError; - const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; - - fn create_inherent(_: &InherentData) -> Option { - None - } - - /// Verify the validity of the inherent using the timestamp. - 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 / Self::slot_duration(); - - let seal_slot = data.aura_inherent_data()?.saturated_into(); - - 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 deleted file mode 100644 index 5c55e8bdd58df..0000000000000 --- a/srml/aura/src/mock.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -#![cfg(test)] - -use crate::{Trait, Module, GenesisConfig}; -use substrate_consensus_aura_primitives::ed25519::AuthorityId; -use sr_primitives::{ - traits::IdentityLookup, Perbill, - testing::{Header, UintAuthorityId}, -}; -use support::{impl_outer_origin, parameter_types}; -use runtime_io; -use primitives::H256; - -impl_outer_origin!{ - pub enum Origin for Test {} -} - -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Test; - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - pub const MinimumPeriod: u64 = 1; -} - -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = ::sr_primitives::traits::BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); -} - -impl timestamp::Trait for Test { - type Moment = u64; - type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; -} - -impl Trait for Test { - type AuthorityId = AuthorityId; -} - -pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig::{ - authorities: authorities.into_iter().map(|a| UintAuthorityId(a).to_public_key()).collect(), - }.assimilate_storage(&mut t).unwrap(); - t.into() -} - -pub type Aura = Module; diff --git a/srml/aura/src/tests.rs b/srml/aura/src/tests.rs deleted file mode 100644 index a90ec3a861e84..0000000000000 --- a/srml/aura/src/tests.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the module. - -#![cfg(test)] - -use crate::mock::{Aura, new_test_ext}; - -#[test] -fn initial_values() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { - assert_eq!(Aura::last(), 0u64); - assert_eq!(Aura::authorities().len(), 4); - }); -} diff --git a/srml/authority-discovery/Cargo.toml b/srml/authority-discovery/Cargo.toml deleted file mode 100644 index 3968ab52aec66..0000000000000 --- a/srml/authority-discovery/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "srml-authority-discovery" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -serde = { version = "1.0.101", optional = true } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -session = { package = "srml-session", path = "../session", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false } -sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } - -[features] -default = ["std"] -std = [ - "app-crypto/std", - "codec/std", - "primitives/std", - "rstd/std", - "runtime-io/std", - "serde", - "session/std", - "sr-primitives/std", - "support/std", - "system/std", -] diff --git a/srml/authority-discovery/src/lib.rs b/srml/authority-discovery/src/lib.rs deleted file mode 100644 index c82d580fd9e2f..0000000000000 --- a/srml/authority-discovery/src/lib.rs +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Authority discovery module. -//! -//! This module is used by the `core/authority-discovery` to retrieve the -//! current set of authorities, learn its own authority id as well as sign and -//! verify messages to and from other authorities. -//! -//! ## Dependencies -//! -//! This module depends on an externally defined session key type, specified via -//! `Trait::AuthorityId` in the respective node runtime implementation. - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -use app_crypto::RuntimeAppPublic; -use codec::FullCodec; -use rstd::prelude::*; -use support::{decl_module, decl_storage}; - -/// The module's config trait. -pub trait Trait: system::Trait + session::Trait { - type AuthorityId: RuntimeAppPublic + Default + FullCodec + PartialEq; -} - -decl_storage! { - trait Store for Module as AuthorityDiscovery { - /// The current set of keys that may issue a heartbeat. - Keys get(fn keys): Vec; - } - add_extra_genesis { - config(keys): Vec; - build(|config| Module::::initialize_keys(&config.keys)) - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - } -} - -impl Module { - /// Returns own authority identifier iff it is part of the current authority - /// set, otherwise this function returns None. The restriction might be - /// softened in the future in case a consumer needs to learn own authority - /// identifier. - fn authority_id() -> Option { - let authorities = Keys::::get(); - - let local_keys = T::AuthorityId::all(); - - authorities.into_iter().find_map(|authority| { - if local_keys.contains(&authority) { - Some(authority) - } else { - None - } - }) - } - - /// Retrieve authority identifiers of the current authority set. - pub fn authorities() -> Vec { - Keys::::get() - } - - /// Sign the given payload with the private key corresponding to the given authority id. - pub fn sign( - payload: &Vec, - ) -> Option<( - <::AuthorityId as RuntimeAppPublic>::Signature, - T::AuthorityId, - )> { - let authority_id = Module::::authority_id()?; - authority_id.sign(payload).map(|s| (s, authority_id)) - } - - /// Verify the given signature for the given payload with the given - /// authority identifier. - pub fn verify( - payload: &Vec, - signature: <::AuthorityId as RuntimeAppPublic>::Signature, - authority_id: T::AuthorityId, - ) -> bool { - authority_id.verify(payload, &signature) - } - - fn initialize_keys(keys: &[T::AuthorityId]) { - if !keys.is_empty() { - assert!(Keys::::get().is_empty(), "Keys are already initialized!"); - Keys::::put(keys); - } - } -} - -impl session::OneSessionHandler for Module { - type Key = T::AuthorityId; - - fn on_genesis_session<'a, I: 'a>(validators: I) - where - I: Iterator, - { - let keys = validators.map(|x| x.1).collect::>(); - Self::initialize_keys(&keys); - } - - fn on_new_session<'a, I: 'a>(_changed: bool, _validators: I, next_validators: I) - where - I: Iterator, - { - // Remember who the authorities are for the new session. - Keys::::put(next_validators.map(|x| x.1).collect::>()); - } - - fn on_disabled(_i: usize) { - // ignore - } -} - -#[cfg(test)] -mod tests { - use super::*; - use app_crypto::Pair; - use primitives::{testing::KeyStore, crypto::key_types, sr25519, H256, traits::KeystoreExt}; - use runtime_io::TestExternalities; - use sr_primitives::{ - testing::{Header, UintAuthorityId}, traits::{ConvertInto, IdentityLookup, OpaqueKeys}, - Perbill, - }; - use support::{impl_outer_origin, parameter_types}; - - type AuthorityDiscovery = Module; - type SessionIndex = u32; - - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - impl Trait for Test { - type AuthorityId = babe_primitives::AuthorityId; - } - - type AuthorityId = babe_primitives::AuthorityId; - - pub struct TestOnSessionEnding; - impl session::OnSessionEnding for TestOnSessionEnding { - fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { - None - } - } - - parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); - } - - impl session::Trait for Test { - type OnSessionEnding = TestOnSessionEnding; - type Keys = UintAuthorityId; - type ShouldEndSession = session::PeriodicSessions; - type SessionHandler = TestSessionHandler; - type Event = (); - type ValidatorId = AuthorityId; - type ValidatorIdOf = ConvertInto; - type SelectInitialValidators = (); - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; - } - - impl session::historical::Trait for Test { - type FullIdentification = (); - type FullIdentificationOf = (); - } - - pub type BlockNumber = u64; - - parameter_types! { - pub const Period: BlockNumber = 1; - pub const Offset: BlockNumber = 0; - pub const UncleGenerations: u64 = 0; - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = BlockNumber; - type Call = (); - type Hash = H256; - type Hashing = ::sr_primitives::traits::BlakeTwo256; - type AccountId = AuthorityId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - - impl_outer_origin! { - pub enum Origin for Test {} - } - - pub struct TestSessionHandler; - impl session::SessionHandler for TestSessionHandler { - fn on_new_session( - _changed: bool, - _validators: &[(AuthorityId, Ks)], - _queued_validators: &[(AuthorityId, Ks)], - ) { - } - - fn on_disabled(_validator_index: usize) {} - - fn on_genesis_session(_validators: &[(AuthorityId, Ks)]) {} - } - - #[test] - fn authority_id_fn_returns_intersection_of_current_authorities_and_keys_in_key_store() { - // Create keystore and generate key. - let key_store = KeyStore::new(); - key_store - .write() - .sr25519_generate_new(key_types::BABE, None) - .expect("Generates key."); - - // Retrieve key to later check if we got the right one. - let public_key = key_store - .read() - .sr25519_public_keys(key_types::BABE) - .pop() - .unwrap(); - let authority_id = AuthorityId::from(public_key); - - // Build genesis. - let mut t = system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - GenesisConfig:: { - keys: vec![authority_id.clone()], - } - .assimilate_storage(&mut t) - .unwrap(); - - // Create externalities. - let mut externalities = TestExternalities::new(t); - externalities.register_extension(KeystoreExt(key_store)); - - externalities.execute_with(|| { - assert_eq!( - authority_id, - AuthorityDiscovery::authority_id().expect("Retrieving public key.") - ); - }); - } - - #[test] - fn authority_id_fn_does_not_return_key_outside_current_authority_set() { - // Create keystore and generate key. - let key_store = KeyStore::new(); - key_store - .write() - .sr25519_generate_new(key_types::BABE, None) - .expect("Generates key."); - - // Build genesis. - let mut t = system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - // Generate random authority set. - let keys = vec![(); 5] - .iter() - .map(|_x| sr25519::Pair::generate_with_phrase(None).0.public()) - .map(AuthorityId::from) - .collect(); - - GenesisConfig:: { keys: keys } - .assimilate_storage(&mut t) - .unwrap(); - - // Create externalities. - let mut externalities = TestExternalities::new(t); - externalities.register_extension(KeystoreExt(key_store)); - - externalities.execute_with(|| { - assert_eq!(None, AuthorityDiscovery::authority_id()); - }); - } - - #[test] - fn sign_and_verify_workflow() { - // Create keystore and generate key. - let key_store = KeyStore::new(); - key_store - .write() - .sr25519_generate_new(key_types::BABE, None) - .expect("Generates key."); - - // Retrieve key to later check if we got the right one. - let public_key = key_store - .read() - .sr25519_public_keys(key_types::BABE) - .pop() - .unwrap(); - let authority_id = AuthorityId::from(public_key); - - // Build genesis. - let mut t = system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - GenesisConfig:: { - keys: vec![authority_id.clone()], - } - .assimilate_storage(&mut t) - .unwrap(); - - // Create externalities. - let mut externalities = TestExternalities::new(t); - externalities.register_extension(KeystoreExt(key_store)); - - externalities.execute_with(|| { - let payload = String::from("test payload").into_bytes(); - let (sig, authority_id) = AuthorityDiscovery::sign(&payload).expect("signature"); - - assert!(AuthorityDiscovery::verify( - &payload, - sig.clone(), - authority_id.clone(), - )); - - assert!(!AuthorityDiscovery::verify( - &String::from("other payload").into_bytes(), - sig, - authority_id, - )) - }); - } -} diff --git a/srml/authorship/Cargo.toml b/srml/authorship/Cargo.toml deleted file mode 100644 index e860be2f64484..0000000000000 --- a/srml/authorship/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "srml-authorship" -version = "0.1.0" -description = "Block and Uncle Author tracking for the SRML" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } -impl-trait-for-tuples = "0.1.2" - -[features] -default = ["std"] -std = [ - "codec/std", - "primitives/std", - "inherents/std", - "sr-primitives/std", - "rstd/std", - "support/std", - "system/std", - "runtime-io/std", -] diff --git a/srml/authorship/src/lib.rs b/srml/authorship/src/lib.rs deleted file mode 100644 index 173af5f729cbb..0000000000000 --- a/srml/authorship/src/lib.rs +++ /dev/null @@ -1,729 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Authorship tracking for SRML runtimes. -//! -//! This tracks the current author of the block and recent uncles. - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::{result, prelude::*}; -use rstd::collections::btree_set::BTreeSet; -use support::{decl_module, decl_storage}; -use support::traits::{FindAuthor, VerifySeal, Get}; -use support::dispatch::Result as DispatchResult; -use codec::{Encode, Decode}; -use system::ensure_none; -use sr_primitives::traits::{Header as HeaderT, One, Zero}; -use sr_primitives::weights::SimpleDispatchInfo; -use inherents::{ - RuntimeString, InherentIdentifier, ProvideInherent, - InherentData, MakeFatalError, -}; - -/// The identifier for the `uncles` inherent. -pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"uncles00"; - -/// Auxiliary trait to extract uncles inherent data. -pub trait UnclesInherentData { - /// Get uncles. - fn uncles(&self) -> Result, RuntimeString>; -} - -impl UnclesInherentData for InherentData { - fn uncles(&self) -> Result, RuntimeString> { - Ok(self.get_data(&INHERENT_IDENTIFIER)?.unwrap_or_default()) - } -} - -/// Provider for inherent data. -#[cfg(feature = "std")] -pub struct InherentDataProvider { - inner: F, - _marker: std::marker::PhantomData, -} - -#[cfg(feature = "std")] -impl InherentDataProvider { - pub fn new(uncles_oracle: F) -> Self { - InherentDataProvider { inner: uncles_oracle, _marker: Default::default() } - } -} - -#[cfg(feature = "std")] -impl inherents::ProvideInherentData for InherentDataProvider -where F: Fn() -> Vec -{ - fn inherent_identifier(&self) -> &'static InherentIdentifier { - &INHERENT_IDENTIFIER - } - - fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), RuntimeString> { - let uncles = (self.inner)(); - if !uncles.is_empty() { - inherent_data.put_data(INHERENT_IDENTIFIER, &uncles) - } else { - Ok(()) - } - } - - fn error_to_string(&self, _error: &[u8]) -> Option { - Some(format!("no further information")) - } -} - -pub trait Trait: system::Trait { - /// Find the author of a block. - type FindAuthor: FindAuthor; - /// The number of blocks back we should accept uncles. - /// This means that we will deal with uncle-parents that are - /// `UncleGenerations + 1` before `now`. - type UncleGenerations: Get; - /// A filter for uncles within a block. This is for implementing - /// further constraints on what uncles can be included, other than their ancestry. - /// - /// For PoW, as long as the seals are checked, there is no need to use anything - /// but the `VerifySeal` implementation as the filter. This is because the cost of making many equivocating - /// uncles is high. - /// - /// For PoS, there is no such limitation, so a further constraint must be imposed - /// beyond a seal check in order to prevent an arbitrary number of - /// equivocating uncles from being included. - /// - /// The `OnePerAuthorPerHeight` filter is good for many slot-based PoS - /// engines. - type FilterUncle: FilterUncle; - /// An event handler for authored blocks. - type EventHandler: EventHandler; -} - -/// An event handler for the authorship module. There is a dummy implementation -/// for `()`, which does nothing. -#[impl_trait_for_tuples::impl_for_tuples(30)] -pub trait EventHandler { - /// Note that the given account ID is the author of the current block. - fn note_author(author: Author); - - /// Note that the given account ID authored the given uncle, and how many - /// blocks older than the current block it is (age >= 0, so siblings are allowed) - fn note_uncle(author: Author, age: BlockNumber); -} - -/// Additional filtering on uncles that pass preliminary ancestry checks. -/// -/// This should do work such as checking seals -pub trait FilterUncle { - /// An accumulator of data about uncles included. - /// - /// In practice, this is used to validate uncles against others in the same block. - type Accumulator: Default; - - /// Do additional filtering on a seal-checked uncle block, with the accumulated - /// filter. - fn filter_uncle(header: &Header, acc: &mut Self::Accumulator) - -> Result, &'static str>; -} - -impl FilterUncle for () { - type Accumulator = (); - fn filter_uncle(_: &H, _acc: &mut Self::Accumulator) - -> Result, &'static str> - { - Ok(None) - } -} - -/// A filter on uncles which verifies seals and does no additional checks. -/// This is well-suited to consensus modes such as PoW where the cost of -/// equivocating is high. -pub struct SealVerify(rstd::marker::PhantomData); - -impl> FilterUncle - for SealVerify -{ - type Accumulator = (); - - fn filter_uncle(header: &Header, _acc: &mut ()) - -> Result, &'static str> - { - T::verify_seal(header) - } -} - -/// A filter on uncles which verifies seals and ensures that there is only -/// one uncle included per author per height. -/// -/// This does O(n log n) work in the number of uncles included. -pub struct OnePerAuthorPerHeight(rstd::marker::PhantomData<(T, N)>); - -impl FilterUncle - for OnePerAuthorPerHeight -where - Header: HeaderT + PartialEq, - Header::Number: Ord, - Author: Clone + PartialEq + Ord, - T: VerifySeal, -{ - type Accumulator = BTreeSet<(Header::Number, Author)>; - - fn filter_uncle(header: &Header, acc: &mut Self::Accumulator) - -> Result, &'static str> - { - let author = T::verify_seal(header)?; - let number = header.number(); - - if let Some(ref author) = author { - if !acc.insert((number.clone(), author.clone())) { - return Err("more than one uncle per number per author included"); - } - } - - Ok(author) - } -} - -#[derive(Encode, Decode, sr_primitives::RuntimeDebug)] -#[cfg_attr(any(feature = "std", test), derive(PartialEq))] -enum UncleEntryItem { - InclusionHeight(BlockNumber), - Uncle(Hash, Option), -} - -decl_storage! { - trait Store for Module as Authorship { - /// Uncles - Uncles: Vec>; - /// Author of current block. - Author: Option; - /// Whether uncles were already set in this block. - DidSetUncles: bool; - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn on_initialize(now: T::BlockNumber) { - let uncle_generations = T::UncleGenerations::get(); - // prune uncles that are older than the allowed number of generations. - if uncle_generations <= now { - let minimum_height = now - uncle_generations; - Self::prune_old_uncles(minimum_height) - } - - ::DidSetUncles::put(false); - - T::EventHandler::note_author(Self::author()); - } - - fn on_finalize() { - // ensure we never go to trie with these values. - ::Author::kill(); - ::DidSetUncles::kill(); - } - - /// Provide a set of uncles. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_uncles(origin, new_uncles: Vec) -> DispatchResult { - ensure_none(origin)?; - - if ::DidSetUncles::get() { - return Err("Uncles already set in block."); - } - ::DidSetUncles::put(true); - - Self::verify_and_import_uncles(new_uncles) - } - } -} - -impl Module { - /// Fetch the author of the block. - /// - /// This is safe to invoke in `on_initialize` implementations, as well - /// as afterwards. - pub fn author() -> T::AccountId { - // Check the memoized storage value. - if let Some(author) = ::Author::get() { - return author; - } - - let digest = >::digest(); - let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); - if let Some(author) = T::FindAuthor::find_author(pre_runtime_digests) { - ::Author::put(&author); - author - } else { - Default::default() - } - } - - fn verify_and_import_uncles(new_uncles: Vec) -> DispatchResult { - let now = >::block_number(); - - let mut uncles = ::Uncles::get(); - uncles.push(UncleEntryItem::InclusionHeight(now)); - - let mut acc: >::Accumulator = Default::default(); - - for uncle in new_uncles { - let prev_uncles = uncles.iter().filter_map(|entry| - match entry { - UncleEntryItem::InclusionHeight(_) => None, - UncleEntryItem::Uncle(h, _) => Some(h), - }); - let author = Self::verify_uncle(&uncle, prev_uncles, &mut acc)?; - let hash = uncle.hash(); - - T::EventHandler::note_uncle( - author.clone().unwrap_or_default(), - now - uncle.number().clone(), - ); - uncles.push(UncleEntryItem::Uncle(hash, author)); - } - - ::Uncles::put(&uncles); - Ok(()) - } - - fn verify_uncle<'a, I: IntoIterator>( - uncle: &T::Header, - existing_uncles: I, - accumulator: &mut >::Accumulator, - ) -> Result, &'static str> - { - let now = >::block_number(); - - let (minimum_height, maximum_height) = { - let uncle_generations = T::UncleGenerations::get(); - let min = if now >= uncle_generations { - now - uncle_generations - } else { - Zero::zero() - }; - - (min, now) - }; - - let hash = uncle.hash(); - - if uncle.number() < &One::one() { - return Err("uncle is genesis"); - } - - if uncle.number() > &maximum_height { - return Err("uncle is too high in chain"); - } - - { - let parent_number = uncle.number().clone() - One::one(); - let parent_hash = >::block_hash(&parent_number); - if &parent_hash != uncle.parent_hash() { - return Err("uncle parent not in chain"); - } - } - - if uncle.number() < &minimum_height { - return Err("uncle not recent enough to be included"); - } - - let duplicate = existing_uncles.into_iter().find(|h| **h == hash).is_some(); - let in_chain = >::block_hash(uncle.number()) == hash; - - if duplicate || in_chain { - return Err("uncle already included") - } - - // check uncle validity. - T::FilterUncle::filter_uncle(&uncle, accumulator) - } - - fn prune_old_uncles(minimum_height: T::BlockNumber) { - let mut uncles = ::Uncles::get(); - let prune_entries = uncles.iter().take_while(|item| match item { - UncleEntryItem::Uncle(_, _) => true, - UncleEntryItem::InclusionHeight(height) => height < &minimum_height, - }); - let prune_index = prune_entries.count(); - - let _ = uncles.drain(..prune_index); - ::Uncles::put(uncles); - } -} - -impl ProvideInherent for Module { - type Call = Call; - type Error = MakeFatalError<()>; - const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; - - fn create_inherent(data: &InherentData) -> Option { - let uncles = data.uncles().unwrap_or_default(); - let mut set_uncles = Vec::new(); - - if !uncles.is_empty() { - let prev_uncles = ::Uncles::get(); - let mut existing_hashes: Vec<_> = prev_uncles.into_iter().filter_map(|entry| - match entry { - UncleEntryItem::InclusionHeight(_) => None, - UncleEntryItem::Uncle(h, _) => Some(h), - } - ).collect(); - - let mut acc: >::Accumulator = Default::default(); - - for uncle in uncles { - match Self::verify_uncle(&uncle, &existing_hashes, &mut acc) { - Ok(_) => { - let hash = uncle.hash(); - set_uncles.push(uncle); - existing_hashes.push(hash); - } - Err(_) => { - // skip this uncle - } - } - } - } - - if set_uncles.is_empty() { - None - } else { - Some(Call::set_uncles(set_uncles)) - } - } - - fn check_inherent(_call: &Self::Call, _data: &InherentData) -> result::Result<(), Self::Error> { - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use primitives::H256; - use sr_primitives::{ - traits::{BlakeTwo256, IdentityLookup}, testing::Header, generic::DigestItem, Perbill, - }; - use support::{parameter_types, impl_outer_origin, ConsensusEngineId}; - - impl_outer_origin!{ - pub enum Origin for Test {} - } - - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - - parameter_types! { - pub const UncleGenerations: u64 = 5; - } - - impl Trait for Test { - type FindAuthor = AuthorGiven; - type UncleGenerations = UncleGenerations; - type FilterUncle = SealVerify; - type EventHandler = (); - } - - type System = system::Module; - type Authorship = Module; - - const TEST_ID: ConsensusEngineId = [1, 2, 3, 4]; - - pub struct AuthorGiven; - - impl FindAuthor for AuthorGiven { - fn find_author<'a, I>(digests: I) -> Option - where I: 'a + IntoIterator - { - for (id, data) in digests { - if id == TEST_ID { - return u64::decode(&mut &data[..]).ok(); - } - } - - None - } - } - - pub struct VerifyBlock; - - impl VerifySeal for VerifyBlock { - fn verify_seal(header: &Header) -> Result, &'static str> { - let pre_runtime_digests = header.digest.logs.iter().filter_map(|d| d.as_pre_runtime()); - let seals = header.digest.logs.iter().filter_map(|d| d.as_seal()); - - let author = match AuthorGiven::find_author(pre_runtime_digests) { - None => return Err("no author"), - Some(author) => author, - }; - - for (id, seal) in seals { - if id == TEST_ID { - match u64::decode(&mut &seal[..]) { - Err(_) => return Err("wrong seal"), - Ok(a) => { - if a != author { - return Err("wrong author in seal"); - } - break - } - } - } - } - - Ok(Some(author)) - } - } - - fn seal_header(mut header: Header, author: u64) -> Header { - { - let digest = header.digest_mut(); - digest.logs.push(DigestItem::PreRuntime(TEST_ID, author.encode())); - digest.logs.push(DigestItem::Seal(TEST_ID, author.encode())); - } - - header - } - - fn create_header(number: u64, parent_hash: H256, state_root: H256) -> Header { - Header::new( - number, - Default::default(), - state_root, - parent_hash, - Default::default(), - ) - } - - fn new_test_ext() -> runtime_io::TestExternalities { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - t.into() - } - - #[test] - fn prune_old_uncles_works() { - use UncleEntryItem::*; - new_test_ext().execute_with(|| { - let hash = Default::default(); - let author = Default::default(); - let uncles = vec![ - InclusionHeight(1u64), Uncle(hash, Some(author)), Uncle(hash, None), Uncle(hash, None), - InclusionHeight(2u64), Uncle(hash, None), - InclusionHeight(3u64), Uncle(hash, None), - ]; - - ::Uncles::put(uncles); - Authorship::prune_old_uncles(3); - - let uncles = ::Uncles::get(); - assert_eq!(uncles, vec![InclusionHeight(3u64), Uncle(hash, None)]); - }) - } - - #[test] - fn rejects_bad_uncles() { - new_test_ext().execute_with(|| { - let author_a = 69; - - struct CanonChain { - inner: Vec

, - } - - impl CanonChain { - fn best_hash(&self) -> H256 { - self.inner.last().unwrap().hash() - } - - fn canon_hash(&self, index: usize) -> H256 { - self.inner[index].hash() - } - - fn header(&self, index: usize) -> &Header { - &self.inner[index] - } - - fn push(&mut self, header: Header) { - self.inner.push(header) - } - } - - let mut canon_chain = CanonChain { - inner: vec![seal_header(create_header(0, Default::default(), Default::default()), 999)], - }; - - for number in 1..8 { - System::initialize(&number, &canon_chain.best_hash(), &Default::default(), &Default::default()); - let header = seal_header(System::finalize(), author_a); - canon_chain.push(header); - } - - // initialize so system context is set up correctly. - System::initialize(&8, &canon_chain.best_hash(), &Default::default(), &Default::default()); - - // 2 of the same uncle at once - { - let uncle_a = seal_header( - create_header(3, canon_chain.canon_hash(2), [1; 32].into()), - author_a, - ); - assert_eq!( - Authorship::verify_and_import_uncles(vec![uncle_a.clone(), uncle_a.clone()]), - Err("uncle already included"), - ); - } - - // 2 of the same uncle at different times. - { - let uncle_a = seal_header( - create_header(3, canon_chain.canon_hash(2), [1; 32].into()), - author_a, - ); - - assert!(Authorship::verify_and_import_uncles(vec![uncle_a.clone()]).is_ok()); - - assert_eq!( - Authorship::verify_and_import_uncles(vec![uncle_a.clone()]), - Err("uncle already included"), - ); - } - - // same uncle as ancestor. - { - let uncle_clone = canon_chain.header(5).clone(); - - assert_eq!( - Authorship::verify_and_import_uncles(vec![uncle_clone]), - Err("uncle already included"), - ); - } - - // uncle without valid seal. - { - let unsealed = create_header(3, canon_chain.canon_hash(2), [2; 32].into()); - assert_eq!( - Authorship::verify_and_import_uncles(vec![unsealed]), - Err("no author"), - ); - } - - // old uncles can't get in. - { - assert_eq!(System::block_number(), 8); - - let gen_2 = seal_header( - create_header(2, canon_chain.canon_hash(1), [3; 32].into()), - author_a, - ); - - assert_eq!( - Authorship::verify_and_import_uncles(vec![gen_2]), - Err("uncle not recent enough to be included"), - ); - } - - // siblings are also allowed - { - let other_8 = seal_header( - create_header(8, canon_chain.canon_hash(7), [1; 32].into()), - author_a, - ); - - assert!(Authorship::verify_and_import_uncles(vec![other_8]).is_ok()); - } - }); - } - - #[test] - fn sets_author_lazily() { - new_test_ext().execute_with(|| { - let author = 42; - let mut header = seal_header( - create_header(1, Default::default(), [1; 32].into()), - author, - ); - - header.digest_mut().pop(); // pop the seal off. - System::initialize(&1, &Default::default(), &Default::default(), header.digest()); - - assert_eq!(Authorship::author(), author); - }); - } - - #[test] - fn one_uncle_per_author_per_number() { - type Filter = OnePerAuthorPerHeight; - - let author_a = 42; - let author_b = 43; - - let mut acc: >::Accumulator = Default::default(); - let header_a1 = seal_header( - create_header(1, Default::default(), [1; 32].into()), - author_a, - ); - let header_b1 = seal_header( - create_header(1, Default::default(), [1; 32].into()), - author_b, - ); - - let header_a2_1 = seal_header( - create_header(2, Default::default(), [1; 32].into()), - author_a, - ); - let header_a2_2 = seal_header( - create_header(2, Default::default(), [2; 32].into()), - author_a, - ); - - let mut check_filter = move |uncle| { - Filter::filter_uncle(uncle, &mut acc) - }; - - // same height, different author is OK. - assert_eq!(check_filter(&header_a1), Ok(Some(author_a))); - assert_eq!(check_filter(&header_b1), Ok(Some(author_b))); - - // same author, different height. - assert_eq!(check_filter(&header_a2_1), Ok(Some(author_a))); - - // same author, same height (author a, height 2) - assert!(check_filter(&header_a2_2).is_err()); - } -} diff --git a/srml/babe/Cargo.toml b/srml/babe/Cargo.toml deleted file mode 100644 index dc82906650bef..0000000000000 --- a/srml/babe/Cargo.toml +++ /dev/null @@ -1,44 +0,0 @@ -[package] -name = "srml-babe" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -hex-literal = "0.2.1" -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", optional = true } -inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } -session = { package = "srml-session", path = "../session", default-features = false } -babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false } -runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } - -[dev-dependencies] -lazy_static = "1.4.0" -parking_lot = "0.9.0" -sr-version = { path = "../../core/sr-version", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -test-runtime = { package = "substrate-test-runtime", path = "../../core/test-runtime" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "rstd/std", - "support/std", - "sr-primitives/std", - "sr-staking-primitives/std", - "system/std", - "timestamp/std", - "inherents/std", - "babe-primitives/std", - "session/std", - "runtime-io/std", -] diff --git a/srml/babe/src/lib.rs b/srml/babe/src/lib.rs deleted file mode 100644 index ee2d66fbe690f..0000000000000 --- a/srml/babe/src/lib.rs +++ /dev/null @@ -1,623 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Consensus extension module for BABE consensus. Collects on-chain randomness -//! from VRF outputs and manages epoch transitions. - -#![cfg_attr(not(feature = "std"), no_std)] -#![forbid(unused_must_use, unsafe_code, unused_variables, unused_must_use)] -#![deny(unused_imports)] -pub use timestamp; - -use rstd::{result, prelude::*}; -use support::{decl_storage, decl_module, traits::FindAuthor, traits::Get}; -use timestamp::OnTimestampSet; -use sr_primitives::{generic::DigestItem, ConsensusEngineId, Perbill}; -use sr_primitives::traits::{IsMember, SaturatedConversion, Saturating, RandomnessBeacon}; -use sr_staking_primitives::{ - SessionIndex, - offence::{Offence, Kind}, -}; -#[cfg(feature = "std")] -use timestamp::TimestampInherentData; -use codec::{Encode, Decode}; -use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; -#[cfg(feature = "std")] -use inherents::{InherentDataProviders, ProvideInherentData}; -use babe_primitives::{ - BABE_ENGINE_ID, ConsensusLog, BabeAuthorityWeight, NextEpochDescriptor, RawBabePreDigest, - SlotNumber, -}; -pub use babe_primitives::{AuthorityId, VRF_OUTPUT_LENGTH, PUBLIC_KEY_LENGTH}; - -#[cfg(all(feature = "std", test))] -mod tests; - -#[cfg(all(feature = "std", test))] -mod mock; - -/// The BABE inherent identifier. -pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot"; - -/// The type of the BABE inherent. -pub type InherentType = u64; -/// Auxiliary trait to extract BABE inherent data. -pub trait BabeInherentData { - /// Get BABE inherent data. - fn babe_inherent_data(&self) -> result::Result; - /// Replace BABE inherent data. - fn babe_replace_inherent_data(&mut self, new: InherentType); -} - -impl BabeInherentData for InherentData { - fn babe_inherent_data(&self) -> result::Result { - self.get_data(&INHERENT_IDENTIFIER) - .and_then(|r| r.ok_or_else(|| "BABE inherent data not found".into())) - } - - fn babe_replace_inherent_data(&mut self, new: InherentType) { - self.replace_data(INHERENT_IDENTIFIER, &new); - } -} - -/// Provides the slot duration inherent data for BABE. -#[cfg(feature = "std")] -pub struct InherentDataProvider { - slot_duration: u64, -} - -#[cfg(feature = "std")] -impl InherentDataProvider { - /// Constructs `Self` - 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_number = timestamp / self.slot_duration; - inherent_data.put_data(INHERENT_IDENTIFIER, &slot_number) - } - - fn error_to_string(&self, error: &[u8]) -> Option { - RuntimeString::decode(&mut &error[..]).map(Into::into).ok() - } -} - -pub trait Trait: timestamp::Trait { - /// The amount of time, in slots, that each epoch should last. - type EpochDuration: Get; - - /// The expected average block time at which BABE should be creating - /// blocks. Since BABE is probabilistic it is not trivial to figure out - /// what the expected average block time should be based on the slot - /// duration and the security parameter `c` (where `1 - c` represents - /// the probability of a slot being empty). - type ExpectedBlockTime: Get; - - /// BABE requires some logic to be triggered on every block to query for whether an epoch - /// has ended and to perform the transition to the next epoch. - /// - /// Typically, the `ExternalTrigger` type should be used. An internal trigger should only be used - /// when no other module is responsible for changing authority set. - type EpochChangeTrigger: EpochChangeTrigger; -} - -/// Trigger an epoch change, if any should take place. -pub trait EpochChangeTrigger { - /// Trigger an epoch change, if any should take place. This should be called - /// during every block, after initialization is done. - fn trigger(now: T::BlockNumber); -} - -/// A type signifying to BABE that an external trigger -/// for epoch changes (e.g. srml-session) is used. -pub struct ExternalTrigger; - -impl EpochChangeTrigger for ExternalTrigger { - fn trigger(_: T::BlockNumber) { } // nothing - trigger is external. -} - -/// A type signifying to BABE that it should perform epoch changes -/// with an internal trigger, recycling the same authorities forever. -pub struct SameAuthoritiesForever; - -impl EpochChangeTrigger for SameAuthoritiesForever { - fn trigger(now: T::BlockNumber) { - if >::should_epoch_change(now) { - let authorities = >::authorities(); - let next_authorities = authorities.clone(); - - >::enact_epoch_change(authorities, next_authorities); - } - } -} - -/// The length of the BABE randomness -pub const RANDOMNESS_LENGTH: usize = 32; - -const UNDER_CONSTRUCTION_SEGMENT_LENGTH: usize = 256; - -type MaybeVrf = Option<[u8; 32 /* VRF_OUTPUT_LENGTH */]>; - -decl_storage! { - trait Store for Module as Babe { - /// Current epoch index. - pub EpochIndex get(fn epoch_index): u64; - - /// Current epoch authorities. - pub Authorities get(fn authorities): Vec<(AuthorityId, BabeAuthorityWeight)>; - - /// The slot at which the first epoch actually started. This is 0 - /// until the first block of the chain. - pub GenesisSlot get(fn genesis_slot): u64; - - /// Current slot number. - pub CurrentSlot get(fn current_slot): u64; - - /// The epoch randomness for the *current* epoch. - /// - /// # Security - /// - /// This MUST NOT be used for gambling, as it can be influenced by a - /// malicious validator in the short term. It MAY be used in many - /// cryptographic protocols, however, so long as one remembers that this - /// (like everything else on-chain) it is public. For example, it can be - /// used where a number is needed that cannot have been chosen by an - /// adversary, for purposes such as public-coin zero-knowledge proofs. - // NOTE: the following fields don't use the constants to define the - // array size because the metadata API currently doesn't resolve the - // variable to its underlying value. - pub Randomness get(fn randomness): [u8; 32 /* RANDOMNESS_LENGTH */]; - - /// Next epoch randomness. - NextRandomness: [u8; 32 /* RANDOMNESS_LENGTH */]; - - /// Randomness under construction. - /// - /// We make a tradeoff between storage accesses and list length. - /// We store the under-construction randomness in segments of up to - /// `UNDER_CONSTRUCTION_SEGMENT_LENGTH`. - /// - /// Once a segment reaches this length, we begin the next one. - /// We reset all segments and return to `0` at the beginning of every - /// epoch. - SegmentIndex build(|_| 0): u32; - UnderConstruction: map u32 => Vec<[u8; 32 /* VRF_OUTPUT_LENGTH */]>; - - /// Temporary value (cleared at block finalization) which is `Some` - /// if per-block initialization has already been called for current block. - Initialized get(fn initialized): Option; - } - add_extra_genesis { - config(authorities): Vec<(AuthorityId, BabeAuthorityWeight)>; - build(|config| Module::::initialize_authorities(&config.authorities)) - } -} - -decl_module! { - /// The BABE SRML module - pub struct Module for enum Call where origin: T::Origin { - /// The number of **slots** that an epoch takes. We couple sessions to - /// epochs, i.e. we start a new session once the new epoch begins. - const EpochDuration: u64 = T::EpochDuration::get(); - - /// The expected average block time at which BABE should be creating - /// blocks. Since BABE is probabilistic it is not trivial to figure out - /// what the expected average block time should be based on the slot - /// duration and the security parameter `c` (where `1 - c` represents - /// the probability of a slot being empty). - const ExpectedBlockTime: T::Moment = T::ExpectedBlockTime::get(); - - /// Initialization - fn on_initialize(now: T::BlockNumber) { - Self::do_initialize(now); - } - - /// Block finalization - fn on_finalize() { - // at the end of the block, we can safely include the new VRF output - // from this block into the under-construction randomness. If we've determined - // that this block was the first in a new epoch, the changeover logic has - // already occurred at this point, so the under-construction randomness - // will only contain outputs from the right epoch. - if let Some(Some(vrf_output)) = Initialized::take() { - Self::deposit_vrf_output(&vrf_output); - } - } - } -} - -impl RandomnessBeacon for Module { - fn random() -> [u8; VRF_OUTPUT_LENGTH] { - Self::randomness() - } -} - -/// A BABE public key -pub type BabeKey = [u8; PUBLIC_KEY_LENGTH]; - -impl FindAuthor for Module { - fn find_author<'a, I>(digests: I) -> Option where - I: 'a + IntoIterator - { - for (id, mut data) in digests.into_iter() { - if id == BABE_ENGINE_ID { - let pre_digest = RawBabePreDigest::decode(&mut data).ok()?; - return Some(match pre_digest { - RawBabePreDigest::Primary { authority_index, .. } => - authority_index, - RawBabePreDigest::Secondary { authority_index, .. } => - authority_index, - }); - } - } - - return None; - } -} - -impl IsMember for Module { - fn is_member(authority_id: &AuthorityId) -> bool { - >::authorities() - .iter() - .any(|id| &id.0 == authority_id) - } -} - -impl session::ShouldEndSession for Module { - fn should_end_session(now: T::BlockNumber) -> bool { - // it might be (and it is in current implementation) that session module is calling - // should_end_session() from it's own on_initialize() handler - // => because session on_initialize() is called earlier than ours, let's ensure - // that we have synced with digest before checking if session should be ended. - Self::do_initialize(now); - - Self::should_epoch_change(now) - } -} - -// TODO [slashing]: @marcio use this, remove the dead_code annotation. -/// A BABE equivocation offence report. -/// -/// When a validator released two or more blocks at the same slot. -#[allow(dead_code)] -struct BabeEquivocationOffence { - /// A babe slot number in which this incident happened. - slot: u64, - /// The session index in which the incident happened. - session_index: SessionIndex, - /// The size of the validator set at the time of the offence. - validator_set_count: u32, - /// The authority that produced the equivocation. - offender: FullIdentification, -} - -impl Offence for BabeEquivocationOffence { - const ID: Kind = *b"babe:equivocatio"; - type TimeSlot = u64; - - fn offenders(&self) -> Vec { - vec![self.offender.clone()] - } - - fn session_index(&self) -> SessionIndex { - self.session_index - } - - fn validator_set_count(&self) -> u32 { - self.validator_set_count - } - - fn time_slot(&self) -> Self::TimeSlot { - self.slot - } - - fn slash_fraction( - offenders_count: u32, - validator_set_count: u32, - ) -> Perbill { - // the formula is min((3k / n)^2, 1) - let x = Perbill::from_rational_approximation(3 * offenders_count, validator_set_count); - // _ ^ 2 - x.square() - } -} - -impl Module { - /// Determine the BABE slot duration based on the Timestamp module configuration. - pub fn slot_duration() -> T::Moment { - // we double the minimum block-period so each author can always propose within - // the majority of their slot. - ::MinimumPeriod::get().saturating_mul(2.into()) - } - - /// Determine whether an epoch change should take place at this block. - /// Assumes that initialization has already taken place. - pub fn should_epoch_change(now: T::BlockNumber) -> bool { - // The epoch has technically ended during the passage of time - // between this block and the last, but we have to "end" the epoch now, - // since there is no earlier possible block we could have done it. - // - // The exception is for block 1: the genesis has slot 0, so we treat - // epoch 0 as having started at the slot of block 1. We want to use - // the same randomness and validator set as signalled in the genesis, - // so we don't rotate the epoch. - now != sr_primitives::traits::One::one() && { - let diff = CurrentSlot::get().saturating_sub(Self::current_epoch_start()); - diff >= T::EpochDuration::get() - } - } - - /// DANGEROUS: Enact an epoch change. Should be done on every block where `should_epoch_change` has returned `true`, - /// and the caller is the only caller of this function. - /// - /// Typically, this is not handled directly by the user, but by higher-level validator-set manager logic like - /// `srml-session`. - pub fn enact_epoch_change( - authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - next_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, - ) { - // PRECONDITION: caller has done initialization and is guaranteed - // by the session module to be called before this. - #[cfg(debug_assertions)] - { - assert!(Self::initialized().is_some()) - } - - // Update epoch index - let epoch_index = EpochIndex::get() - .checked_add(1) - .expect("epoch indices will never reach 2^64 before the death of the universe; qed"); - - EpochIndex::put(epoch_index); - Authorities::put(authorities); - - // Update epoch randomness. - let next_epoch_index = epoch_index - .checked_add(1) - .expect("epoch indices will never reach 2^64 before the death of the universe; qed"); - - // Returns randomness for the current epoch and computes the *next* - // epoch randomness. - let randomness = Self::randomness_change_epoch(next_epoch_index); - Randomness::put(randomness); - - // After we update the current epoch, we signal the *next* epoch change - // so that nodes can track changes. - let next_randomness = NextRandomness::get(); - - let next = NextEpochDescriptor { - authorities: next_authorities, - randomness: next_randomness, - }; - - Self::deposit_consensus(ConsensusLog::NextEpochData(next)) - } - - // finds the start slot of the current epoch. only guaranteed to - // give correct results after `do_initialize` of the first block - // in the chain (as its result is based off of `GenesisSlot`). - fn current_epoch_start() -> SlotNumber { - (EpochIndex::get() * T::EpochDuration::get()) + GenesisSlot::get() - } - - fn deposit_consensus(new: U) { - let log: DigestItem = DigestItem::Consensus(BABE_ENGINE_ID, new.encode()); - >::deposit_log(log.into()) - } - - fn deposit_vrf_output(vrf_output: &[u8; VRF_OUTPUT_LENGTH]) { - let segment_idx = ::get(); - let mut segment = ::get(&segment_idx); - if segment.len() < UNDER_CONSTRUCTION_SEGMENT_LENGTH { - // push onto current segment: not full. - segment.push(*vrf_output); - ::insert(&segment_idx, &segment); - } else { - // move onto the next segment and update the index. - let segment_idx = segment_idx + 1; - ::insert(&segment_idx, &vec![*vrf_output]); - ::put(&segment_idx); - } - } - - fn do_initialize(now: T::BlockNumber) { - // since do_initialize can be called twice (if session module is present) - // => let's ensure that we only modify the storage once per block - let initialized = Self::initialized().is_some(); - if initialized { - return; - } - - let maybe_pre_digest = >::digest() - .logs - .iter() - .filter_map(|s| s.as_pre_runtime()) - .filter_map(|(id, mut data)| if id == BABE_ENGINE_ID { - RawBabePreDigest::decode(&mut data).ok() - } else { - None - }) - .next(); - - let maybe_vrf = maybe_pre_digest.and_then(|digest| { - // on the first non-zero block (i.e. block #1) - // this is where the first epoch (epoch #0) actually starts. - // we need to adjust internal storage accordingly. - if GenesisSlot::get() == 0 { - GenesisSlot::put(digest.slot_number()); - debug_assert_ne!(GenesisSlot::get(), 0); - - // deposit a log because this is the first block in epoch #0 - // we use the same values as genesis because we haven't collected any - // randomness yet. - let next = NextEpochDescriptor { - authorities: Self::authorities(), - randomness: Self::randomness(), - }; - - Self::deposit_consensus(ConsensusLog::NextEpochData(next)) - } - - CurrentSlot::put(digest.slot_number()); - - if let RawBabePreDigest::Primary { vrf_output, .. } = digest { - // place the VRF output into the `Initialized` storage item - // and it'll be put onto the under-construction randomness - // later, once we've decided which epoch this block is in. - Some(vrf_output) - } else { - None - } - }); - - Initialized::put(maybe_vrf); - - // enact epoch change, if necessary. - T::EpochChangeTrigger::trigger::(now) - } - - /// Call this function exactly once when an epoch changes, to update the - /// randomness. Returns the new randomness. - fn randomness_change_epoch(next_epoch_index: u64) -> [u8; RANDOMNESS_LENGTH] { - let this_randomness = NextRandomness::get(); - let segment_idx: u32 = ::mutate(|s| rstd::mem::replace(s, 0)); - - // overestimate to the segment being full. - let rho_size = segment_idx.saturating_add(1) as usize * UNDER_CONSTRUCTION_SEGMENT_LENGTH; - - let next_randomness = compute_randomness( - this_randomness, - next_epoch_index, - (0..segment_idx).flat_map(|i| ::take(&i)), - Some(rho_size), - ); - NextRandomness::put(&next_randomness); - this_randomness - } - - fn initialize_authorities(authorities: &[(AuthorityId, BabeAuthorityWeight)]) { - if !authorities.is_empty() { - assert!(Authorities::get().is_empty(), "Authorities are already initialized!"); - Authorities::put(authorities); - } - } -} - -impl OnTimestampSet for Module { - fn on_timestamp_set(_moment: T::Moment) { } -} - -impl session::OneSessionHandler for Module { - type Key = AuthorityId; - - fn on_genesis_session<'a, I: 'a>(validators: I) - where I: Iterator - { - let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); - Self::initialize_authorities(&authorities); - } - - fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, queued_validators: I) - where I: Iterator - { - let authorities = validators.map(|(_account, k)| { - (k, 1) - }).collect::>(); - - let next_authorities = queued_validators.map(|(_account, k)| { - (k, 1) - }).collect::>(); - - Self::enact_epoch_change(authorities, next_authorities) - } - - fn on_disabled(i: usize) { - Self::deposit_consensus(ConsensusLog::OnDisabled(i as u32)) - } -} - -// compute randomness for a new epoch. rho is the concatenation of all -// VRF outputs in the prior epoch. -// -// an optional size hint as to how many VRF outputs there were may be provided. -fn compute_randomness( - last_epoch_randomness: [u8; RANDOMNESS_LENGTH], - epoch_index: u64, - rho: impl Iterator, - rho_size_hint: Option, -) -> [u8; RANDOMNESS_LENGTH] { - let mut s = Vec::with_capacity(40 + rho_size_hint.unwrap_or(0) * VRF_OUTPUT_LENGTH); - s.extend_from_slice(&last_epoch_randomness); - s.extend_from_slice(&epoch_index.to_le_bytes()); - - for vrf_output in rho { - s.extend_from_slice(&vrf_output[..]); - } - - runtime_io::blake2_256(&s) -} - -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 / Self::slot_duration()).saturated_into::(); - let seal_slot = data.babe_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/babe/src/mock.rs b/srml/babe/src/mock.rs deleted file mode 100644 index 5a6b80a2a6717..0000000000000 --- a/srml/babe/src/mock.rs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities -#![allow(dead_code, unused_imports)] - -use super::{Trait, Module, GenesisConfig}; -use babe_primitives::AuthorityId; -use sr_primitives::{ - traits::IdentityLookup, Perbill, - testing::{Header, UintAuthorityId}, - impl_opaque_keys, key_types::DUMMY, -}; -use sr_version::RuntimeVersion; -use support::{impl_outer_origin, parameter_types}; -use runtime_io; -use primitives::{H256, Blake2Hasher}; - -impl_outer_origin!{ - pub enum Origin for Test {} -} - -type DummyValidatorId = u64; - -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Test; - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - pub const MinimumPeriod: u64 = 1; - pub const EpochDuration: u64 = 3; - pub const ExpectedBlockTime: u64 = 1; - pub const Version: RuntimeVersion = test_runtime::VERSION; - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(16); -} - -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Version = Version; - type Hashing = sr_primitives::traits::BlakeTwo256; - type AccountId = DummyValidatorId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; -} - -impl_opaque_keys! { - pub struct MockSessionKeys { - #[id(DUMMY)] - pub dummy: UintAuthorityId, - } -} - -impl session::Trait for Test { - type Event = (); - type ValidatorId = ::AccountId; - type ShouldEndSession = Babe; - type SessionHandler = (Babe,Babe,); - type OnSessionEnding = (); - type ValidatorIdOf = (); - type SelectInitialValidators = (); - type Keys = MockSessionKeys; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; -} - -impl timestamp::Trait for Test { - type Moment = u64; - type OnTimestampSet = Babe; - type MinimumPeriod = MinimumPeriod; -} - -impl Trait for Test { - type EpochDuration = EpochDuration; - type ExpectedBlockTime = ExpectedBlockTime; - type EpochChangeTrigger = crate::ExternalTrigger; -} - -pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig { - authorities: authorities.into_iter().map(|a| (UintAuthorityId(a).to_public_key(), 1)).collect(), - }.assimilate_storage::(&mut t).unwrap(); - t.into() -} - -pub type System = system::Module; -pub type Babe = Module; diff --git a/srml/babe/src/tests.rs b/srml/babe/src/tests.rs deleted file mode 100644 index f860375de487a..0000000000000 --- a/srml/babe/src/tests.rs +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Consensus extension module tests for BABE consensus. - -use super::*; -use mock::{new_test_ext, Babe, Test}; -use sr_primitives::{traits::OnFinalize, testing::{Digest, DigestItem}}; -use session::ShouldEndSession; - -const EMPTY_RANDOMNESS: [u8; 32] = [ - 74, 25, 49, 128, 53, 97, 244, 49, - 222, 202, 176, 2, 231, 66, 95, 10, - 133, 49, 213, 228, 86, 161, 164, 127, - 217, 153, 138, 37, 48, 192, 248, 0, -]; - -fn make_pre_digest( - authority_index: babe_primitives::AuthorityIndex, - slot_number: babe_primitives::SlotNumber, - vrf_output: [u8; babe_primitives::VRF_OUTPUT_LENGTH], - vrf_proof: [u8; babe_primitives::VRF_PROOF_LENGTH], -) -> Digest { - let digest_data = babe_primitives::RawBabePreDigest::Primary { - authority_index, - slot_number, - vrf_output, - vrf_proof, - }; - let log = DigestItem::PreRuntime(babe_primitives::BABE_ENGINE_ID, digest_data.encode()); - Digest { logs: vec![log] } -} - -#[test] -fn empty_randomness_is_correct() { - let s = compute_randomness([0; RANDOMNESS_LENGTH], 0, std::iter::empty(), None); - assert_eq!(s, EMPTY_RANDOMNESS); -} - -#[test] -fn initial_values() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { - assert_eq!(Babe::authorities().len(), 4) - }) -} - -#[test] -fn check_module() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { - assert!(!Babe::should_end_session(0), "Genesis does not change sessions"); - assert!(!Babe::should_end_session(200000), - "BABE does not include the block number in epoch calculations"); - }) -} - -type System = system::Module; - -#[test] -fn first_block_epoch_zero_start() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { - let genesis_slot = 100; - let first_vrf = [1; 32]; - let pre_digest = make_pre_digest( - 0, - genesis_slot, - first_vrf, - [0xff; 64], - ); - - assert_eq!(Babe::genesis_slot(), 0); - System::initialize(&1, &Default::default(), &Default::default(), &pre_digest); - - // see implementation of the function for details why: we issue an - // epoch-change digest but don't do it via the normal session mechanism. - assert!(!Babe::should_end_session(1)); - assert_eq!(Babe::genesis_slot(), genesis_slot); - assert_eq!(Babe::current_slot(), genesis_slot); - assert_eq!(Babe::epoch_index(), 0); - - Babe::on_finalize(1); - let header = System::finalize(); - - assert_eq!(SegmentIndex::get(), 0); - assert_eq!(UnderConstruction::get(0), vec![first_vrf]); - assert_eq!(Babe::randomness(), [0; 32]); - assert_eq!(NextRandomness::get(), [0; 32]); - - assert_eq!(header.digest.logs.len(), 2); - assert_eq!(pre_digest.logs.len(), 1); - assert_eq!(header.digest.logs[0], pre_digest.logs[0]); - - let authorities = Babe::authorities(); - let consensus_log = babe_primitives::ConsensusLog::NextEpochData( - babe_primitives::NextEpochDescriptor { - authorities, - randomness: Babe::randomness(), - } - ); - let consensus_digest = DigestItem::Consensus(BABE_ENGINE_ID, consensus_log.encode()); - - // first epoch descriptor has same info as last. - assert_eq!(header.digest.logs[1], consensus_digest.clone()) - }) -} - -#[test] -fn authority_index() { - new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { - assert_eq!( - Babe::find_author((&[(BABE_ENGINE_ID, &[][..])]).into_iter().cloned()), None, - "Trivially invalid authorities are ignored") - }) -} diff --git a/srml/balances/Cargo.toml b/srml/balances/Cargo.toml deleted file mode 100644 index f7f6041c6bb16..0000000000000 --- a/srml/balances/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "srml-balances" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -substrate-keyring = { path = "../../core/keyring", optional = true } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -runtime-io = { package = "sr-io", path = "../../core/sr-io" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -transaction-payment = { package = "srml-transaction-payment", path = "../transaction-payment" } - -[features] -default = ["std"] -std = [ - "serde", - "safe-mix/std", - "substrate-keyring", - "codec/std", - "rstd/std", - "support/std", - "sr-primitives/std", - "system/std", -] diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs deleted file mode 100644 index 3c354da50881b..0000000000000 --- a/srml/balances/src/lib.rs +++ /dev/null @@ -1,1153 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Balances Module -//! -//! The Balances module provides functionality for handling accounts and balances. -//! -//! - [`balances::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! - [`Module`](./struct.Module.html) -//! -//! ## Overview -//! -//! The Balances module provides functions for: -//! -//! - Getting and setting free balances. -//! - Retrieving total, reserved and unreserved balances. -//! - Repatriating a reserved balance to a beneficiary account that exists. -//! - Transferring a balance between accounts (when not reserved). -//! - Slashing an account balance. -//! - Account creation and removal. -//! - Managing total issuance. -//! - Setting and managing locks. -//! -//! ### Terminology -//! -//! - **Existential Deposit:** The minimum balance required to create or keep an account open. This prevents -//! "dust accounts" from filling storage. -//! - **Total Issuance:** The total number of units in existence in a system. -//! - **Reaping an account:** The act of removing an account by resetting its nonce. Happens after its balance is set -//! to zero. -//! - **Free Balance:** The portion of a balance that is not reserved. The free balance is the only balance that matters -//! for most operations. When this balance falls below the existential deposit, most functionality of the account is -//! removed. When both it and the reserved balance are deleted, then the account is said to be dead. -//! - **Reserved Balance:** Reserved balance still belongs to the account holder, but is suspended. Reserved balance -//! can still be slashed, but only after all the free balance has been slashed. If the reserved balance falls below the -//! existential deposit then it and any related functionality will be deleted. When both it and the free balance are -//! deleted, then the account is said to be dead. -//! - **Imbalance:** A condition when some funds were credited or debited without equal and opposite accounting -//! (i.e. a difference between total issuance and account balances). Functions that result in an imbalance will -//! return an object of the `Imbalance` trait that can be managed within your runtime logic. (If an imbalance is -//! simply dropped, it should automatically maintain any book-keeping such as total issuance.) -//! - **Lock:** A freeze on a specified amount of an account's free balance until a specified block number. Multiple -//! locks always operate over the same funds, so they "overlay" rather than "stack". -//! - **Vesting:** Similar to a lock, this is another, but independent, liquidity restriction that reduces linearly -//! over time. -//! -//! ### Implementations -//! -//! The Balances module provides implementations for the following traits. If these traits provide the functionality -//! that you need, then you can avoid coupling with the Balances module. -//! -//! - [`Currency`](../srml_support/traits/trait.Currency.html): Functions for dealing with a -//! fungible assets system. -//! - [`ReservableCurrency`](../srml_support/traits/trait.ReservableCurrency.html): -//! Functions for dealing with assets that can be reserved from an account. -//! - [`LockableCurrency`](../srml_support/traits/trait.LockableCurrency.html): Functions for -//! dealing with accounts that allow liquidity restrictions. -//! - [`Imbalance`](../srml_support/traits/trait.Imbalance.html): Functions for handling -//! imbalances between total issuance in the system and account balances. Must be used when a function -//! creates new funds (e.g. a reward) or destroys some funds (e.g. a system fee). -//! - [`IsDeadAccount`](../srml_system/trait.IsDeadAccount.html): Determiner to say whether a -//! given account is unused. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! - `transfer` - Transfer some liquid free balance to another account. -//! - `set_balance` - Set the balances of a given account. The origin of this call must be root. -//! -//! ### Public Functions -//! -//! - `vesting_balance` - Get the amount that is currently being vested and cannot be transferred out of this account. -//! -//! ## Usage -//! -//! The following examples show how to use the Balances module in your custom module. -//! -//! ### Examples from the SRML -//! -//! The Contract module uses the `Currency` trait to handle gas payment, and its types inherit from `Currency`: -//! -//! ``` -//! use support::traits::Currency; -//! # pub trait Trait: system::Trait { -//! # type Currency: Currency; -//! # } -//! -//! pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -//! pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; -//! -//! # fn main() {} -//! ``` -//! -//! The Staking module uses the `LockableCurrency` trait to lock a stash account's funds: -//! -//! ``` -//! use support::traits::{WithdrawReasons, LockableCurrency}; -//! use sr_primitives::traits::Bounded; -//! pub trait Trait: system::Trait { -//! type Currency: LockableCurrency; -//! } -//! # struct StakingLedger { -//! # stash: ::AccountId, -//! # total: <::Currency as support::traits::Currency<::AccountId>>::Balance, -//! # phantom: std::marker::PhantomData, -//! # } -//! # const STAKING_ID: [u8; 8] = *b"staking "; -//! -//! fn update_ledger( -//! controller: &T::AccountId, -//! ledger: &StakingLedger -//! ) { -//! T::Currency::set_lock( -//! STAKING_ID, -//! &ledger.stash, -//! ledger.total, -//! T::BlockNumber::max_value(), -//! WithdrawReasons::all() -//! ); -//! // >::insert(controller, ledger); // Commented out as we don't have access to Staking's storage here. -//! } -//! # fn main() {} -//! ``` -//! -//! ## Genesis config -//! -//! The Balances module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). -//! -//! ## Assumptions -//! -//! * Total issued balanced of all accounts should be less than `Trait::Balance::max_value()`. - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::prelude::*; -use rstd::{cmp, result, mem, fmt::Debug}; -use codec::{Codec, Encode, Decode}; -use support::{ - StorageValue, Parameter, decl_event, decl_storage, decl_module, - traits::{ - UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnUnbalanced, - WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, - Imbalance, SignedImbalance, ReservableCurrency, Get, - }, - dispatch::Result, -}; -use sr_primitives::{ - RuntimeDebug, - traits::{ - Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDeserialize, - Saturating, Bounded, - }, - weights::SimpleDispatchInfo, -}; -use system::{IsDeadAccount, OnNewAccount, ensure_signed, ensure_root}; - -mod mock; -mod tests; - -pub use self::imbalances::{PositiveImbalance, NegativeImbalance}; - -pub trait Subtrait: system::Trait { - /// The balance of an account. - type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + - MaybeSerializeDeserialize + Debug + From; - - /// A function that 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; - - /// Handler for when a new account is created. - type OnNewAccount: OnNewAccount; - - /// The minimum amount required to keep an account open. - type ExistentialDeposit: Get; - - /// The fee required to make a transfer. - type TransferFee: Get; - - /// The fee required to create an account. - type CreationFee: Get; -} - -pub trait Trait: system::Trait { - /// The balance of an account. - type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + - MaybeSerializeDeserialize + Debug + From; - - /// A function that 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; - - /// Handler for when a new account is created. - type OnNewAccount: OnNewAccount; - - /// Handler for the unbalanced reduction when taking fees associated with balance - /// transfer (which may also include account creation). - type TransferPayment: OnUnbalanced>; - - /// Handler for the unbalanced reduction when removing a dust account. - type DustRemoval: OnUnbalanced>; - - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// The minimum amount required to keep an account open. - type ExistentialDeposit: Get; - - /// The fee required to make a transfer. - type TransferFee: Get; - - /// The fee required to create an account. - type CreationFee: Get; -} - -impl, I: Instance> Subtrait for T { - type Balance = T::Balance; - type OnFreeBalanceZero = T::OnFreeBalanceZero; - type OnNewAccount = T::OnNewAccount; - type ExistentialDeposit = T::ExistentialDeposit; - type TransferFee = T::TransferFee; - type CreationFee = T::CreationFee; -} - -decl_event!( - pub enum Event where - ::AccountId, - >::Balance - { - /// A new account was created. - NewAccount(AccountId, Balance), - /// An account was reaped. - ReapedAccount(AccountId), - /// Transfer succeeded (from, to, value, fees). - Transfer(AccountId, AccountId, Balance, Balance), - } -); - -/// Struct to encode the vesting schedule of an individual account. -#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct VestingSchedule { - /// Locked amount at genesis. - pub locked: Balance, - /// Amount that gets unlocked every block after `starting_block`. - pub per_block: Balance, - /// Starting block for unlocking(vesting). - pub starting_block: BlockNumber, -} - -impl VestingSchedule { - /// Amount locked at block `n`. - pub fn locked_at(&self, n: BlockNumber) -> Balance - where Balance: From - { - // Number of blocks that count toward vesting - // Saturating to 0 when n < starting_block - let vested_block_count = n.saturating_sub(self.starting_block); - // Return amount that is still locked in vesting - if let Some(x) = Balance::from(vested_block_count).checked_mul(&self.per_block) { - self.locked.max(x) - x - } else { - Zero::zero() - } - } -} - -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct BalanceLock { - pub id: LockIdentifier, - pub amount: Balance, - pub until: BlockNumber, - pub reasons: WithdrawReasons, -} - -decl_storage! { - trait Store for Module, I: Instance=DefaultInstance> as Balances { - /// The total units issued in the system. - pub TotalIssuance get(fn total_issuance) build(|config: &GenesisConfig| { - config.balances.iter().fold(Zero::zero(), |acc: T::Balance, &(_, n)| acc + n) - }): T::Balance; - - /// Information regarding the vesting of a given account. - pub Vesting get(fn vesting) build(|config: &GenesisConfig| { - // Generate initial vesting configuration - // * who - Account which we are generating vesting configuration for - // * begin - Block when the account will start to vest - // * length - Number of blocks from `begin` until fully vested - // * liquid - Number of units which can be spent before vesting begins - config.vesting.iter().filter_map(|&(ref who, begin, length, liquid)| { - let length = >::from(length); - - config.balances.iter() - .find(|&&(ref w, _)| w == who) - .map(|&(_, balance)| { - // Total genesis `balance` minus `liquid` equals funds locked for vesting - let locked = balance.saturating_sub(liquid); - // Number of units unlocked per block after `begin` - let per_block = locked / length.max(sr_primitives::traits::One::one()); - - (who.clone(), VestingSchedule { - locked: locked, - per_block: per_block, - starting_block: begin - }) - }) - }).collect::>() - }): map T::AccountId => Option>; - - /// The 'free' balance of a given account. - /// - /// This is the only balance that matters in terms of most operations on tokens. It - /// alone is 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`. Further, the `OnFreeBalanceZero` callback - /// is invoked, giving a chance to external modules to clean up 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`. - pub FreeBalance get(fn 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. - /// - /// 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. - /// - /// 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`.) - pub ReservedBalance get(fn reserved_balance): map T::AccountId => T::Balance; - - /// Any liquidity locks on some account balances. - pub Locks get(fn locks): map T::AccountId => Vec>; - } - add_extra_genesis { - config(balances): Vec<(T::AccountId, T::Balance)>; - config(vesting): Vec<(T::AccountId, T::BlockNumber, T::BlockNumber, T::Balance)>; - // ^^ begin, length, amount liquid at genesis - } -} - -decl_module! { - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { - /// The minimum amount required to keep an account open. - const ExistentialDeposit: T::Balance = T::ExistentialDeposit::get(); - - /// The fee required to make a transfer. - const TransferFee: T::Balance = T::TransferFee::get(); - - /// The fee required to create an account. - const CreationFee: T::Balance = T::CreationFee::get(); - - fn deposit_event() = default; - - /// Transfer some liquid free balance to another account. - /// - /// `transfer` will set the `FreeBalance` of the sender and receiver. - /// It will decrease the total issuance of the system by the `TransferFee`. - /// If the sender's account is below the existential deposit as a result - /// of the transfer, the account will be reaped. - /// - /// The dispatch origin for this call must be `Signed` by the transactor. - /// - /// # - /// - Dependent on arguments but not critical, given proper implementations for - /// input config types. See related functions below. - /// - It contains a limited number of reads and writes internally and no complex computation. - /// - /// Related functions: - /// - /// - `ensure_can_withdraw` is always called internally but has a bounded complexity. - /// - Transferring balances to accounts that did not exist before will cause - /// `T::OnNewAccount::on_new_account` to be called. - /// - Removing enough funds from an account will trigger - /// `T::DustRemoval::on_unbalanced` and `T::OnFreeBalanceZero::on_free_balance_zero`. - /// - /// # - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] - pub fn transfer( - origin, - dest: ::Source, - #[compact] value: T::Balance - ) { - let transactor = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; - >::transfer(&transactor, &dest, value)?; - } - - /// Set the balances of a given account. - /// - /// This will alter `FreeBalance` and `ReservedBalance` in storage. it will - /// also decrease the total issuance of the system (`TotalIssuance`). - /// If the new free or reserved balance is below the existential deposit, - /// it will reset the account nonce (`system::AccountNonce`). - /// - /// The dispatch origin for this call is `root`. - /// - /// # - /// - Independent of the arguments. - /// - Contains a limited number of reads and writes. - /// # - #[weight = SimpleDispatchInfo::FixedOperational(50_000)] - fn set_balance( - origin, - who: ::Source, - #[compact] new_free: T::Balance, - #[compact] new_reserved: T::Balance - ) { - ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; - - let current_free = >::get(&who); - if new_free > current_free { - mem::drop(PositiveImbalance::::new(new_free - current_free)); - } else if new_free < current_free { - mem::drop(NegativeImbalance::::new(current_free - new_free)); - } - Self::set_free_balance(&who, new_free); - - let current_reserved = >::get(&who); - if new_reserved > current_reserved { - mem::drop(PositiveImbalance::::new(new_reserved - current_reserved)); - } else if new_reserved < current_reserved { - mem::drop(NegativeImbalance::::new(current_reserved - new_reserved)); - } - Self::set_reserved_balance(&who, new_reserved); - } - - /// Exactly as `transfer`, except the origin must be root and the source account may be - /// specified. - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] - pub fn force_transfer( - origin, - source: ::Source, - dest: ::Source, - #[compact] value: T::Balance - ) { - ensure_root(origin)?; - let source = T::Lookup::lookup(source)?; - let dest = T::Lookup::lookup(dest)?; - >::transfer(&source, &dest, value)?; - } - } -} - -impl, I: Instance> Module { - - // PUBLIC IMMUTABLES - - /// Get the amount that is currently being vested and cannot be transferred 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() - } - } - - // PRIVATE MUTABLES - - /// Set the reserved balance of an account to some new value. Will enforce `ExistentialDeposit` - /// law, annulling the account as needed. - /// - /// Doesn't do any preparatory work for creating a new account, so should only be used when it - /// is known that the account already exists. - /// - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { - if balance < T::ExistentialDeposit::get() { - >::insert(who, balance); - Self::on_reserved_too_low(who); - UpdateBalanceOutcome::AccountKilled - } else { - >::insert(who, balance); - UpdateBalanceOutcome::Updated - } - } - - /// Set the free balance of an account to some new value. Will enforce `ExistentialDeposit` - /// law, annulling the account as needed. - /// - /// Doesn't do any preparatory work for creating a new account, so should only be used when it - /// is known that the account already exists. - /// - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { - // Commented out for now - but consider it instructive. - // assert!(!Self::total_balance(who).is_zero()); - // assert!(Self::free_balance(who) > T::ExistentialDeposit::get()); - if balance < T::ExistentialDeposit::get() { - >::insert(who, balance); - Self::on_free_too_low(who); - UpdateBalanceOutcome::AccountKilled - } else { - >::insert(who, balance); - UpdateBalanceOutcome::Updated - } - } - - /// Register a new account (with existential balance). - /// - /// This just calls appropriate hooks. It doesn't (necessarily) make any state changes. - fn new_account(who: &T::AccountId, balance: T::Balance) { - T::OnNewAccount::on_new_account(&who); - Self::deposit_event(RawEvent::NewAccount(who.clone(), balance.clone())); - } - - /// Unregister an account. - /// - /// This just removes the nonce and leaves an event. - fn reap_account(who: &T::AccountId) { - >::remove(who); - Self::deposit_event(RawEvent::ReapedAccount(who.clone())); - } - - /// Account's free balance has dropped below existential deposit. Kill its - /// free side and the account completely if its reserved size is already dead. - /// - /// Will maintain total issuance. - fn on_free_too_low(who: &T::AccountId) { - let dust = >::take(who); - >::remove(who); - - // underflow should never happen, but if it does, there's not much we can do about it. - if !dust.is_zero() { - T::DustRemoval::on_unbalanced(NegativeImbalance::new(dust)); - } - - T::OnFreeBalanceZero::on_free_balance_zero(who); - - if Self::reserved_balance(who).is_zero() { - Self::reap_account(who); - } - } - - /// Account's reserved balance has dropped below existential deposit. Kill its - /// reserved side and the account completely if its free size is already dead. - /// - /// Will maintain total issuance. - fn on_reserved_too_low(who: &T::AccountId) { - let dust = >::take(who); - - // underflow should never happen, but it if does, there's nothing to be done here. - if !dust.is_zero() { - T::DustRemoval::on_unbalanced(NegativeImbalance::new(dust)); - } - - if Self::free_balance(who).is_zero() { - Self::reap_account(who); - } - } -} - -// wrapping these imbalances in a private module is necessary to ensure absolute privacy -// of the inner member. -mod imbalances { - use super::{ - result, Subtrait, DefaultInstance, Imbalance, Trait, Zero, Instance, Saturating, - StorageValue, - }; - use rstd::mem; - - /// Opaque, move-only struct with private fields that serves as a token denoting that - /// funds have been created without any equal and opposite accounting. - #[must_use] - pub struct PositiveImbalance, I: Instance=DefaultInstance>(T::Balance); - - impl, I: Instance> PositiveImbalance { - /// Create a new positive imbalance from a balance. - pub fn new(amount: T::Balance) -> Self { - PositiveImbalance(amount) - } - } - - /// Opaque, move-only struct with private fields that serves as a token denoting that - /// funds have been destroyed without any equal and opposite accounting. - #[must_use] - pub struct NegativeImbalance, I: Instance=DefaultInstance>(T::Balance); - - impl, I: Instance> NegativeImbalance { - /// Create a new negative imbalance from a balance. - pub fn new(amount: T::Balance) -> Self { - NegativeImbalance(amount) - } - } - - impl, I: Instance> Imbalance for PositiveImbalance { - type Opposite = NegativeImbalance; - - fn zero() -> Self { - Self(Zero::zero()) - } - fn drop_zero(self) -> result::Result<(), Self> { - if self.0.is_zero() { - Ok(()) - } else { - Err(self) - } - } - fn split(self, amount: T::Balance) -> (Self, Self) { - let first = self.0.min(amount); - let second = self.0 - first; - - mem::forget(self); - (Self(first), Self(second)) - } - fn merge(mut self, other: Self) -> Self { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - - self - } - fn subsume(&mut self, other: Self) { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - } - fn offset(self, other: Self::Opposite) -> result::Result { - let (a, b) = (self.0, other.0); - mem::forget((self, other)); - - if a >= b { - Ok(Self(a - b)) - } else { - Err(NegativeImbalance::new(b - a)) - } - } - fn peek(&self) -> T::Balance { - self.0.clone() - } - } - - impl, I: Instance> Imbalance for NegativeImbalance { - type Opposite = PositiveImbalance; - - fn zero() -> Self { - Self(Zero::zero()) - } - fn drop_zero(self) -> result::Result<(), Self> { - if self.0.is_zero() { - Ok(()) - } else { - Err(self) - } - } - fn split(self, amount: T::Balance) -> (Self, Self) { - let first = self.0.min(amount); - let second = self.0 - first; - - mem::forget(self); - (Self(first), Self(second)) - } - fn merge(mut self, other: Self) -> Self { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - - self - } - fn subsume(&mut self, other: Self) { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - } - fn offset(self, other: Self::Opposite) -> result::Result { - let (a, b) = (self.0, other.0); - mem::forget((self, other)); - - if a >= b { - Ok(Self(a - b)) - } else { - Err(PositiveImbalance::new(b - a)) - } - } - fn peek(&self) -> T::Balance { - self.0.clone() - } - } - - impl, I: Instance> Drop for PositiveImbalance { - /// Basic drop handler will just square up the total issuance. - fn drop(&mut self) { - , I>>::mutate( - |v| *v = v.saturating_add(self.0) - ); - } - } - - impl, I: Instance> Drop for NegativeImbalance { - /// Basic drop handler will just square up the total issuance. - fn drop(&mut self) { - , I>>::mutate( - |v| *v = v.saturating_sub(self.0) - ); - } - } -} - -// TODO: #2052 -// Somewhat ugly hack in order to gain access to module's `increase_total_issuance_by` -// using only the Subtrait (which defines only the types that are not dependent -// on Positive/NegativeImbalance). Subtrait must be used otherwise we end up with a -// circular dependency with Trait having some types be dependent on PositiveImbalance -// and PositiveImbalance itself depending back on Trait for its Drop impl (and thus -// its type declaration). -// This works as long as `increase_total_issuance_by` doesn't use the Imbalance -// types (basically for charging fees). -// This should eventually be refactored so that the three type items that do -// depend on the Imbalance type (TransferPayment, DustRemoval) -// are placed in their own SRML module. -struct ElevatedTrait, I: Instance>(T, I); -impl, I: Instance> Clone for ElevatedTrait { - fn clone(&self) -> Self { unimplemented!() } -} -impl, I: Instance> PartialEq for ElevatedTrait { - fn eq(&self, _: &Self) -> bool { unimplemented!() } -} -impl, I: Instance> Eq for ElevatedTrait {} -impl, I: Instance> system::Trait for ElevatedTrait { - type Origin = T::Origin; - type Call = T::Call; - type Index = T::Index; - type BlockNumber = T::BlockNumber; - type Hash = T::Hash; - type Hashing = T::Hashing; - type AccountId = T::AccountId; - type Lookup = T::Lookup; - type Header = T::Header; - type Event = (); - type BlockHashCount = T::BlockHashCount; - type MaximumBlockWeight = T::MaximumBlockWeight; - type MaximumBlockLength = T::MaximumBlockLength; - type AvailableBlockRatio = T::AvailableBlockRatio; - type Version = T::Version; -} -impl, I: Instance> Trait for ElevatedTrait { - type Balance = T::Balance; - type OnFreeBalanceZero = T::OnFreeBalanceZero; - type OnNewAccount = T::OnNewAccount; - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = T::ExistentialDeposit; - type TransferFee = T::TransferFee; - type CreationFee = T::CreationFee; -} - -impl, I: Instance> Currency for Module -where - T::Balance: MaybeSerializeDeserialize + Debug -{ - type Balance = T::Balance; - type PositiveImbalance = PositiveImbalance; - type NegativeImbalance = NegativeImbalance; - - 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 total_issuance() -> Self::Balance { - >::get() - } - - fn minimum_balance() -> Self::Balance { - T::ExistentialDeposit::get() - } - - fn free_balance(who: &T::AccountId) -> Self::Balance { - >::get(who) - } - - fn burn(mut amount: Self::Balance) -> Self::PositiveImbalance { - >::mutate(|issued| { - *issued = issued.checked_sub(&amount).unwrap_or_else(|| { - amount = *issued; - Zero::zero() - }); - }); - PositiveImbalance::new(amount) - } - - fn issue(mut amount: Self::Balance) -> Self::NegativeImbalance { - >::mutate(|issued| - *issued = issued.checked_add(&amount).unwrap_or_else(|| { - amount = Self::Balance::max_value() - *issued; - Self::Balance::max_value() - }) - ); - NegativeImbalance::new(amount) - } - - // # - // Despite iterating over a list of locks, they are limited by the number of - // lock IDs, which means the number of runtime modules that intend to use and create locks. - // # - fn ensure_can_withdraw( - who: &T::AccountId, - _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 locks.into_iter() - .all(|l| - now >= l.until - || new_balance >= l.amount - || !l.reasons.contains(reason) - ) - { - Ok(()) - } else { - Err("account liquidity restrictions prevent withdrawal") - } - } - - fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::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 { T::CreationFee::get() } else { T::TransferFee::get() }; - 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 < T::ExistentialDeposit::get() { - return Err("value too low to create account"); - } - Self::ensure_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); - if !>::exists(dest) { - Self::new_account(dest, new_to_balance); - } - Self::set_free_balance(dest, new_to_balance); - T::TransferPayment::on_unbalanced(NegativeImbalance::new(fee)); - Self::deposit_event(RawEvent::Transfer(transactor.clone(), dest.clone(), value, fee)); - } - - Ok(()) - } - - fn withdraw( - who: &T::AccountId, - value: Self::Balance, - reason: WithdrawReason, - liveness: ExistenceRequirement, - ) -> result::Result { - let old_balance = Self::free_balance(who); - if let Some(new_balance) = old_balance.checked_sub(&value) { - // if we need to keep the account alive... - if liveness == ExistenceRequirement::KeepAlive - // ...and it would be dead afterwards... - && new_balance < T::ExistentialDeposit::get() - // ...yet is was alive before - && old_balance >= T::ExistentialDeposit::get() - { - return Err("payment would kill account") - } - Self::ensure_can_withdraw(who, value, reason, new_balance)?; - Self::set_free_balance(who, new_balance); - Ok(NegativeImbalance::new(value)) - } else { - Err("too few free funds in account") - } - } - - fn slash( - who: &T::AccountId, - value: Self::Balance - ) -> (Self::NegativeImbalance, Self::Balance) { - let free_balance = Self::free_balance(who); - let free_slash = cmp::min(free_balance, value); - Self::set_free_balance(who, free_balance - free_slash); - let remaining_slash = value - free_slash; - // NOTE: `slash()` prefers free balance, but assumes that reserve balance can be drawn - // from in extreme circumstances. `can_slash()` should be used prior to `slash()` to avoid having - // to draw from reserved funds, however we err on the side of punishment if things are inconsistent - // or `can_slash` wasn't used appropriately. - if !remaining_slash.is_zero() { - let reserved_balance = Self::reserved_balance(who); - let reserved_slash = cmp::min(reserved_balance, remaining_slash); - Self::set_reserved_balance(who, reserved_balance - reserved_slash); - (NegativeImbalance::new(free_slash + reserved_slash), remaining_slash - reserved_slash) - } else { - (NegativeImbalance::new(value), Zero::zero()) - } - } - - fn deposit_into_existing( - who: &T::AccountId, - value: Self::Balance - ) -> result::Result { - if Self::total_balance(who).is_zero() { - return Err("beneficiary account must pre-exist"); - } - Self::set_free_balance(who, Self::free_balance(who) + value); - Ok(PositiveImbalance::new(value)) - } - - fn deposit_creating( - who: &T::AccountId, - value: Self::Balance, - ) -> Self::PositiveImbalance { - let (imbalance, _) = Self::make_free_balance_be(who, Self::free_balance(who) + value); - if let SignedImbalance::Positive(p) = imbalance { - p - } else { - // Impossible, but be defensive. - Self::PositiveImbalance::zero() - } - } - - fn make_free_balance_be(who: &T::AccountId, balance: Self::Balance) -> ( - SignedImbalance, - UpdateBalanceOutcome - ) { - let original = Self::free_balance(who); - if balance < T::ExistentialDeposit::get() && original.is_zero() { - // If we're attempting to set an existing account to less than ED, then - // bypass the entire operation. It's a no-op if you follow it through, but - // since this is an instance where we might account for a negative imbalance - // (in the dust cleaner of set_free_balance) before we account for its actual - // equal and opposite cause (returned as an Imbalance), then in the - // instance that there's no other accounts on the system at all, we might - // underflow the issuance and our arithmetic will be off. - return ( - SignedImbalance::Positive(Self::PositiveImbalance::zero()), - UpdateBalanceOutcome::AccountKilled, - ) - } - let imbalance = if original <= balance { - SignedImbalance::Positive(PositiveImbalance::new(balance - original)) - } else { - SignedImbalance::Negative(NegativeImbalance::new(original - balance)) - }; - // 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 - // the term "balance" is used *here* it should be assumed to mean "free balance" - // in the rest of the module. - // Free balance can never be less than ED. If that happens, it gets reduced to zero - // and the account information relevant to this subsystem is deleted (i.e. the - // account is reaped). - let outcome = if balance < T::ExistentialDeposit::get() { - Self::set_free_balance(who, balance); - UpdateBalanceOutcome::AccountKilled - } else { - if !>::exists(who) { - Self::new_account(&who, balance); - } - Self::set_free_balance(who, balance); - UpdateBalanceOutcome::Updated - }; - (imbalance, outcome) - } -} - -impl, I: Instance> ReservableCurrency for Module -where - T::Balance: MaybeSerializeDeserialize + Debug -{ - fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { - Self::free_balance(who) - .checked_sub(&value) - .map_or(false, |new_balance| - Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve, new_balance).is_ok() - ) - } - - fn reserved_balance(who: &T::AccountId) -> Self::Balance { - >::get(who) - } - - 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") - } - let new_balance = b - value; - Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve, new_balance)?; - Self::set_reserved_balance(who, Self::reserved_balance(who) + value); - Self::set_free_balance(who, new_balance); - Ok(()) - } - - fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance { - let b = Self::reserved_balance(who); - let actual = cmp::min(b, value); - Self::set_free_balance(who, Self::free_balance(who) + actual); - Self::set_reserved_balance(who, b - actual); - value - actual - } - - fn slash_reserved( - who: &T::AccountId, - value: Self::Balance - ) -> (Self::NegativeImbalance, Self::Balance) { - let b = Self::reserved_balance(who); - let slash = cmp::min(b, value); - // underflow should never happen, but it if does, there's nothing to be done here. - Self::set_reserved_balance(who, b - slash); - (NegativeImbalance::new(slash), value - slash) - } - - fn repatriate_reserved( - slashed: &T::AccountId, - beneficiary: &T::AccountId, - value: Self::Balance, - ) -> result::Result { - if Self::total_balance(beneficiary).is_zero() { - return Err("beneficiary account must pre-exist"); - } - let b = Self::reserved_balance(slashed); - let slash = cmp::min(b, value); - Self::set_free_balance(beneficiary, Self::free_balance(beneficiary) + slash); - Self::set_reserved_balance(slashed, b - slash); - Ok(value - slash) - } -} - -impl, I: Instance> LockableCurrency for Module -where - T::Balance: MaybeSerializeDeserialize + Debug -{ - type Moment = T::BlockNumber; - - 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 { - None - }).collect::>(); - if let Some(lock) = new_lock { - locks.push(lock) - } - >::insert(who, locks); - } - - 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); - } - - 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); - } -} - -impl, I: Instance> IsDeadAccount for Module -where - T::Balance: MaybeSerializeDeserialize + Debug -{ - fn is_dead_account(who: &T::AccountId) -> bool { - Self::total_balance(who).is_zero() - } -} diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs deleted file mode 100644 index 600d0e6fb7879..0000000000000 --- a/srml/balances/src/mock.rs +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -#![cfg(test)] - -use sr_primitives::{Perbill, traits::{ConvertInto, IdentityLookup}, testing::Header, - weights::{DispatchInfo, Weight}}; -use primitives::H256; -use runtime_io; -use support::{impl_outer_origin, parameter_types}; -use support::traits::Get; -use std::cell::RefCell; -use crate::{GenesisConfig, Module, Trait}; - -impl_outer_origin!{ - pub enum Origin for Runtime {} -} - -thread_local! { - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); - static TRANSFER_FEE: RefCell = RefCell::new(0); - static CREATION_FEE: RefCell = RefCell::new(0); -} - -pub struct ExistentialDeposit; -impl Get for ExistentialDeposit { - fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } -} - -pub struct TransferFee; -impl Get for TransferFee { - fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) } -} - -pub struct CreationFee; -impl Get for CreationFee { - fn get() -> u64 { CREATION_FEE.with(|v| *v.borrow()) } -} - -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Runtime; -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl system::Trait for Runtime { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = ::sr_primitives::traits::BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} -parameter_types! { - pub const TransactionBaseFee: u64 = 0; - pub const TransactionByteFee: u64 = 1; -} -impl transaction_payment::Trait for Runtime { - type Currency = Module; - type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; - type FeeMultiplierUpdate = (); -} -impl Trait for Runtime { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = (); - type DustRemoval = (); - type TransferPayment = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} - -pub struct ExtBuilder { - existential_deposit: u64, - transfer_fee: u64, - creation_fee: u64, - monied: bool, - vesting: bool, -} -impl Default for ExtBuilder { - fn default() -> Self { - Self { - existential_deposit: 0, - transfer_fee: 0, - creation_fee: 0, - monied: false, - vesting: false, - } - } -} -impl ExtBuilder { - pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { - self.existential_deposit = existential_deposit; - self - } - #[allow(dead_code)] - pub fn transfer_fee(mut self, transfer_fee: u64) -> Self { - self.transfer_fee = transfer_fee; - self - } - pub fn creation_fee(mut self, creation_fee: u64) -> Self { - self.creation_fee = creation_fee; - self - } - pub fn monied(mut self, monied: bool) -> Self { - self.monied = monied; - if self.existential_deposit == 0 { - self.existential_deposit = 1; - } - self - } - pub fn vesting(mut self, vesting: bool) -> Self { - self.vesting = vesting; - self - } - pub fn set_associated_consts(&self) { - EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); - TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee); - CREATION_FEE.with(|v| *v.borrow_mut() = self.creation_fee); - } - pub fn build(self) -> runtime_io::TestExternalities { - self.set_associated_consts(); - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig:: { - balances: if self.monied { - vec![ - (1, 10 * self.existential_deposit), - (2, 20 * self.existential_deposit), - (3, 30 * self.existential_deposit), - (4, 40 * self.existential_deposit), - (12, 10 * self.existential_deposit) - ] - } else { - vec![] - }, - vesting: if self.vesting && self.monied { - vec![ - (1, 0, 10, 5 * self.existential_deposit), - (2, 10, 20, 0), - (12, 10, 20, 5 * self.existential_deposit) - ] - } else { - vec![] - }, - }.assimilate_storage(&mut t).unwrap(); - t.into() - } -} - -pub type System = system::Module; -pub type Balances = Module; - -pub const CALL: &::Call = &(); - -/// create a transaction info struct from weight. Handy to avoid building the whole struct. -pub fn info_from_weight(w: Weight) -> DispatchInfo { - DispatchInfo { weight: w, ..Default::default() } -} diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs deleted file mode 100644 index 839ac67991c83..0000000000000 --- a/srml/balances/src/tests.rs +++ /dev/null @@ -1,748 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the module. - -#![cfg(test)] - -use super::*; -use mock::{Balances, ExtBuilder, Runtime, System, info_from_weight, CALL}; -use sr_primitives::traits::SignedExtension; -use support::{ - assert_noop, assert_ok, assert_err, - traits::{LockableCurrency, LockIdentifier, WithdrawReason, WithdrawReasons, - Currency, ReservableCurrency} -}; -use transaction_payment::ChargeTransactionPayment; -use system::RawOrigin; - -const ID_1: LockIdentifier = *b"1 "; -const ID_2: LockIdentifier = *b"2 "; -const ID_3: LockIdentifier = *b"3 "; - -#[test] -fn basic_locking_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - assert_eq!(Balances::free_balance(&1), 10); - Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all()); - assert_noop!( - >::transfer(&1, &2, 5), - "account liquidity restrictions prevent withdrawal" - ); - }); -} - -#[test] -fn partial_locking_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); - }); -} - -#[test] -fn lock_removal_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); - Balances::remove_lock(ID_1, &1); - assert_ok!(>::transfer(&1, &2, 1)); - }); -} - -#[test] -fn lock_replacement_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); - Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); - }); -} - -#[test] -fn double_locking_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - Balances::set_lock(ID_2, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); - }); -} - -#[test] -fn combination_locking_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, u64::max_value(), 0, WithdrawReasons::none()); - Balances::set_lock(ID_2, &1, 0, u64::max_value(), WithdrawReasons::none()); - Balances::set_lock(ID_3, &1, 0, 0, WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); - }); -} - -#[test] -fn lock_value_extension_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_noop!( - >::transfer(&1, &2, 6), - "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() { - ExtBuilder::default() - .existential_deposit(1) - .monied(true) - .build() - .execute_with(|| { - Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into()); - assert_noop!( - >::transfer(&1, &2, 1), - "account liquidity restrictions prevent withdrawal" - ); - assert_ok!(>::reserve(&1, 1)); - // NOTE: this causes a fee payment. - assert!( as SignedExtension>::pre_dispatch( - ChargeTransactionPayment::from(1), - &1, - CALL, - info_from_weight(1), - 0, - ).is_ok()); - - 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!( as SignedExtension>::pre_dispatch( - ChargeTransactionPayment::from(1), - &1, - CALL, - info_from_weight(1), - 0, - ).is_ok()); - - 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!( as SignedExtension>::pre_dispatch( - ChargeTransactionPayment::from(1), - &1, - CALL, - info_from_weight(1), - 0, - ).is_err()); - }); -} - -#[test] -fn lock_block_number_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); - assert_noop!( - >::transfer(&1, &2, 1), - "account liquidity restrictions prevent withdrawal" - ); - - System::set_block_number(2); - assert_ok!(>::transfer(&1, &2, 1)); - }); -} - -#[test] -fn lock_block_number_extension_should_work() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); - assert_noop!( - >::transfer(&1, &2, 6), - "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() { - ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { - Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into()); - assert_noop!( - >::transfer(&1, &2, 6), - "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] -fn default_indexing_on_new_accounts_should_not_work2() { - ExtBuilder::default() - .existential_deposit(10) - .creation_fee(50) - .monied(true) - .build() - .execute_with(|| { - assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist - // ext_deposit is 10, value is 9, not satisfies for ext_deposit - assert_noop!( - Balances::transfer(Some(1).into(), 5, 9), - "value too low to create account", - ); - assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist - assert_eq!(Balances::free_balance(&1), 100); - }); -} - -#[test] -fn reserved_balance_should_prevent_reclaim_count() { - ExtBuilder::default() - .existential_deposit(256 * 1) - .monied(true) - .build() - .execute_with(|| { - System::inc_account_nonce(&2); - assert_eq!(Balances::is_dead_account(&2), false); - assert_eq!(Balances::is_dead_account(&5), true); - 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!(Balances::is_dead_account(&2), false); - assert_eq!(System::account_nonce(&2), 1); - - // account 4 tries to take index 1 for account 5. - assert_ok!(Balances::transfer(Some(4).into(), 5, 256 * 1 + 0x69)); - assert_eq!(Balances::total_balance(&5), 256 * 1 + 0x69); - assert_eq!(Balances::is_dead_account(&5), false); - - assert!(Balances::slash(&2, 256 * 18 + 2).1.is_zero()); // account 2 gets slashed - // "reserve" account reduced to 255 (below ED) so account deleted - assert_eq!(Balances::total_balance(&2), 0); - assert_eq!(System::account_nonce(&2), 0); // nonce zero - assert_eq!(Balances::is_dead_account(&2), true); - - // account 4 tries to take index 1 again for account 6. - assert_ok!(Balances::transfer(Some(4).into(), 6, 256 * 1 + 0x69)); - assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); - assert_eq!(Balances::is_dead_account(&6), false); - }); -} - - -#[test] -fn reward_should_work() { - ExtBuilder::default().monied(true).build().execute_with(|| { - assert_eq!(Balances::total_balance(&1), 10); - assert_ok!(Balances::deposit_into_existing(&1, 10).map(drop)); - assert_eq!(Balances::total_balance(&1), 20); - assert_eq!(>::get(), 120); - }); -} - -#[test] -fn dust_account_removal_should_work() { - ExtBuilder::default() - .existential_deposit(100) - .monied(true) - .build() - .execute_with(|| { - System::inc_account_nonce(&2); - assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Balances::total_balance(&2), 2000); - - assert_ok!(Balances::transfer(Some(2).into(), 5, 1901)); // index 1 (account 2) becomes zombie - assert_eq!(Balances::total_balance(&2), 0); - assert_eq!(Balances::total_balance(&5), 1901); - assert_eq!(System::account_nonce(&2), 0); - }); -} - -#[test] -fn dust_account_removal_should_work2() { - ExtBuilder::default() - .existential_deposit(100) - .creation_fee(50) - .monied(true) - .build() - .execute_with(|| { - System::inc_account_nonce(&2); - assert_eq!(System::account_nonce(&2), 1); - assert_eq!(Balances::total_balance(&2), 2000); - // index 1 (account 2) becomes zombie for 256*10 + 50(fee) < 256 * 10 (ext_deposit) - assert_ok!(Balances::transfer(Some(2).into(), 5, 1851)); - assert_eq!(Balances::total_balance(&2), 0); - assert_eq!(Balances::total_balance(&5), 1851); - assert_eq!(System::account_nonce(&2), 0); - }); -} - -#[test] -fn balance_works() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 42); - assert_eq!(Balances::free_balance(&1), 42); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(Balances::total_balance(&1), 42); - assert_eq!(Balances::free_balance(&2), 0); - assert_eq!(Balances::reserved_balance(&2), 0); - assert_eq!(Balances::total_balance(&2), 0); - }); -} - -#[test] -fn balance_transfer_works() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_ok!(Balances::transfer(Some(1).into(), 2, 69)); - assert_eq!(Balances::total_balance(&1), 42); - assert_eq!(Balances::total_balance(&2), 69); - }); -} - -#[test] -fn force_transfer_works() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_noop!( - Balances::force_transfer(Some(2).into(), 1, 2, 69), - "RequireRootOrigin", - ); - assert_ok!(Balances::force_transfer(RawOrigin::Root.into(), 1, 2, 69)); - assert_eq!(Balances::total_balance(&1), 42); - assert_eq!(Balances::total_balance(&2), 69); - }); -} - -#[test] -fn reserving_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - - assert_eq!(Balances::total_balance(&1), 111); - assert_eq!(Balances::free_balance(&1), 111); - assert_eq!(Balances::reserved_balance(&1), 0); - - assert_ok!(Balances::reserve(&1, 69)); - - assert_eq!(Balances::total_balance(&1), 111); - assert_eq!(Balances::free_balance(&1), 42); - assert_eq!(Balances::reserved_balance(&1), 69); - }); -} - -#[test] -fn balance_transfer_when_reserved_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_ok!(Balances::reserve(&1, 69)); - assert_noop!( - Balances::transfer(Some(1).into(), 2, 69), - "balance too low to send value", - ); - }); -} - -#[test] -fn deducting_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_ok!(Balances::reserve(&1, 69)); - assert_eq!(Balances::free_balance(&1), 42); - }); -} - -#[test] -fn refunding_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 42); - Balances::set_reserved_balance(&1, 69); - Balances::unreserve(&1, 69); - assert_eq!(Balances::free_balance(&1), 111); - assert_eq!(Balances::reserved_balance(&1), 0); - }); -} - -#[test] -fn slashing_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_ok!(Balances::reserve(&1, 69)); - assert!(Balances::slash(&1, 69).1.is_zero()); - assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(Balances::reserved_balance(&1), 42); - assert_eq!(>::get(), 42); - }); -} - -#[test] -fn slashing_incomplete_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 42); - assert_ok!(Balances::reserve(&1, 21)); - assert_eq!(Balances::slash(&1, 69).1, 27); - assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(>::get(), 0); - }); -} - -#[test] -fn unreserving_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_ok!(Balances::reserve(&1, 111)); - Balances::unreserve(&1, 42); - assert_eq!(Balances::reserved_balance(&1), 69); - assert_eq!(Balances::free_balance(&1), 42); - }); -} - -#[test] -fn slashing_reserved_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_ok!(Balances::reserve(&1, 111)); - assert_eq!(Balances::slash_reserved(&1, 42).1, 0); - assert_eq!(Balances::reserved_balance(&1), 69); - assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(>::get(), 69); - }); -} - -#[test] -fn slashing_incomplete_reserved_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_ok!(Balances::reserve(&1, 42)); - assert_eq!(Balances::slash_reserved(&1, 69).1, 27); - assert_eq!(Balances::free_balance(&1), 69); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(>::get(), 69); - }); -} - -#[test] -fn transferring_reserved_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 110); - let _ = Balances::deposit_creating(&2, 1); - assert_ok!(Balances::reserve(&1, 110)); - assert_ok!(Balances::repatriate_reserved(&1, &2, 41), 0); - assert_eq!(Balances::reserved_balance(&1), 69); - assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(Balances::reserved_balance(&2), 0); - assert_eq!(Balances::free_balance(&2), 42); - }); -} - -#[test] -fn transferring_reserved_balance_to_nonexistent_should_fail() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 111); - assert_ok!(Balances::reserve(&1, 111)); - assert_noop!(Balances::repatriate_reserved(&1, &2, 42), "beneficiary account must pre-exist"); - }); -} - -#[test] -fn transferring_incomplete_reserved_balance_should_work() { - ExtBuilder::default().build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 110); - let _ = Balances::deposit_creating(&2, 1); - assert_ok!(Balances::reserve(&1, 41)); - assert_ok!(Balances::repatriate_reserved(&1, &2, 69), 28); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(Balances::free_balance(&1), 69); - assert_eq!(Balances::reserved_balance(&2), 0); - assert_eq!(Balances::free_balance(&2), 42); - }); -} - -#[test] -fn transferring_too_high_value_should_not_panic() { - ExtBuilder::default().build().execute_with(|| { - >::insert(1, u64::max_value()); - >::insert(2, 1); - - assert_err!( - Balances::transfer(Some(1).into(), 2, u64::max_value()), - "destination balance too high to receive value", - ); - - assert_eq!(Balances::free_balance(&1), u64::max_value()); - assert_eq!(Balances::free_balance(&2), 1); - }); -} - -#[test] -fn account_create_on_free_too_low_with_other() { - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - let _ = Balances::deposit_creating(&1, 100); - assert_eq!(>::get(), 100); - - // No-op. - let _ = Balances::deposit_creating(&2, 50); - assert_eq!(Balances::free_balance(&2), 0); - assert_eq!(>::get(), 100); - }) -} - - -#[test] -fn account_create_on_free_too_low() { - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - // No-op. - let _ = Balances::deposit_creating(&2, 50); - assert_eq!(Balances::free_balance(&2), 0); - assert_eq!(>::get(), 0); - }) -} - -#[test] -fn account_removal_on_free_too_low() { - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - assert_eq!(>::get(), 0); - - // Setup two accounts with free balance above the existential threshold. - let _ = Balances::deposit_creating(&1, 110); - let _ = Balances::deposit_creating(&2, 110); - - assert_eq!(Balances::free_balance(&1), 110); - assert_eq!(Balances::free_balance(&2), 110); - assert_eq!(>::get(), 220); - - // Transfer funds from account 1 of such amount that after this transfer - // the balance of account 1 will be below the existential threshold. - // This should lead to the removal of all balance of this account. - assert_ok!(Balances::transfer(Some(1).into(), 2, 20)); - - // Verify free balance removal of account 1. - assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(Balances::free_balance(&2), 130); - - // Verify that TotalIssuance tracks balance removal when free balance is too low. - assert_eq!(>::get(), 130); - }); -} - -#[test] -fn transfer_overflow_isnt_exploitable() { - ExtBuilder::default().creation_fee(50).build().execute_with(|| { - // Craft a value that will overflow if summed with `creation_fee`. - let evil_value = u64::max_value() - 49; - - assert_err!( - Balances::transfer(Some(1).into(), 5, evil_value), - "got overflow after adding a fee to value", - ); - }); -} - -#[test] -fn check_vesting_status() { - ExtBuilder::default() - .existential_deposit(256) - .monied(true) - .vesting(true) - .build() - .execute_with(|| { - assert_eq!(System::block_number(), 1); - let user1_free_balance = Balances::free_balance(&1); - let user2_free_balance = Balances::free_balance(&2); - let user12_free_balance = Balances::free_balance(&12); - assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance - assert_eq!(user2_free_balance, 256 * 20); // Account 2 has free balance - assert_eq!(user12_free_balance, 256 * 10); // Account 12 has free balance - let user1_vesting_schedule = VestingSchedule { - locked: 256 * 5, - per_block: 128, // Vesting over 10 blocks - starting_block: 0, - }; - let user2_vesting_schedule = VestingSchedule { - locked: 256 * 20, - per_block: 256, // Vesting over 20 blocks - starting_block: 10, - }; - let user12_vesting_schedule = VestingSchedule { - locked: 256 * 5, - per_block: 64, // Vesting over 20 blocks - starting_block: 10, - }; - 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(&12), Some(user12_vesting_schedule)); // Account 12 has a vesting schedule - - // Account 1 has only 128 units vested from their illiquid 256 * 5 units at block 1 - assert_eq!(Balances::vesting_balance(&1), 128 * 9); - // Account 2 has their full balance locked - assert_eq!(Balances::vesting_balance(&2), user2_free_balance); - // Account 12 has only their illiquid funds locked - assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5); - - System::set_block_number(10); - assert_eq!(System::block_number(), 10); - - // Account 1 has fully vested by block 10 - assert_eq!(Balances::vesting_balance(&1), 0); - // Account 2 has started vesting by block 10 - assert_eq!(Balances::vesting_balance(&2), user2_free_balance); - // Account 12 has started vesting by block 10 - assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5); - - 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 - assert_eq!(Balances::vesting_balance(&12), 0); // Account 2 has fully vested by block 30 - - }); -} - -#[test] -fn unvested_balance_should_not_transfer() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .vesting(true) - .build() - .execute_with(|| { - assert_eq!(System::block_number(), 1); - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 100); // Account 1 has free balance - // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Balances::vesting_balance(&1), 45); - assert_noop!( - Balances::transfer(Some(1).into(), 2, 56), - "vesting balance too high to send value", - ); // Account 1 cannot send more than vested amount - }); -} - -#[test] -fn vested_balance_should_transfer() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .vesting(true) - .build() - .execute_with(|| { - assert_eq!(System::block_number(), 1); - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 100); // Account 1 has free balance - // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Balances::vesting_balance(&1), 45); - assert_ok!(Balances::transfer(Some(1).into(), 2, 55)); - }); -} - -#[test] -fn extra_balance_should_transfer() { - ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .vesting(true) - .build() - .execute_with(|| { - assert_eq!(System::block_number(), 1); - assert_ok!(Balances::transfer(Some(3).into(), 1, 100)); - assert_ok!(Balances::transfer(Some(3).into(), 2, 100)); - - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 200); // Account 1 has 100 more free balance than normal - - let user2_free_balance = Balances::free_balance(&2); - assert_eq!(user2_free_balance, 300); // Account 2 has 100 more free balance than normal - - // Account 1 has only 5 units vested at block 1 (plus 150 unvested) - assert_eq!(Balances::vesting_balance(&1), 45); - assert_ok!(Balances::transfer(Some(1).into(), 3, 155)); // Account 1 can send extra units gained - - // Account 2 has no units vested at block 1, but gained 100 - assert_eq!(Balances::vesting_balance(&2), 200); - assert_ok!(Balances::transfer(Some(2).into(), 3, 100)); // Account 2 can send extra units gained - }); -} - -#[test] -fn liquid_funds_should_transfer_with_delayed_vesting() { - ExtBuilder::default() - .existential_deposit(256) - .monied(true) - .vesting(true) - .build() - .execute_with(|| { - assert_eq!(System::block_number(), 1); - let user12_free_balance = Balances::free_balance(&12); - - assert_eq!(user12_free_balance, 2560); // Account 12 has free balance - // Account 12 has liquid funds - assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5); - - // Account 12 has delayed vesting - let user12_vesting_schedule = VestingSchedule { - locked: 256 * 5, - per_block: 64, // Vesting over 20 blocks - starting_block: 10, - }; - assert_eq!(Balances::vesting(&12), Some(user12_vesting_schedule)); - - // Account 12 can still send liquid funds - assert_ok!(Balances::transfer(Some(12).into(), 3, 256 * 5)); - }); -} - -#[test] -fn burn_must_work() { - ExtBuilder::default().monied(true).build().execute_with(|| { - let init_total_issuance = Balances::total_issuance(); - let imbalance = Balances::burn(10); - assert_eq!(Balances::total_issuance(), init_total_issuance - 10); - drop(imbalance); - assert_eq!(Balances::total_issuance(), init_total_issuance); - }); -} diff --git a/srml/collective/Cargo.toml b/srml/collective/Cargo.toml deleted file mode 100644 index 347a289b57b89..0000000000000 --- a/srml/collective/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "srml-collective" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -hex-literal = "0.2.1" -balances = { package = "srml-balances", path = "../balances" } - -[features] -default = ["std"] -std = [ - "safe-mix/std", - "codec/std", - "primitives/std", - "rstd/std", - "serde", - "runtime-io/std", - "support/std", - "sr-primitives/std", - "system/std", -] diff --git a/srml/collective/src/lib.rs b/srml/collective/src/lib.rs deleted file mode 100644 index 37c1482f9ba15..0000000000000 --- a/srml/collective/src/lib.rs +++ /dev/null @@ -1,743 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Collective system: Members of a set of account IDs can make their collective feelings known -//! through dispatched calls from one of two specialised origins. -//! -//! The membership can be provided in one of two ways: either directly, using the Root-dispatchable -//! function `set_members`, or indirectly, through implementing the `ChangeMembers` - -#![cfg_attr(not(feature = "std"), no_std)] -#![recursion_limit="128"] - -use rstd::{prelude::*, result}; -use primitives::u32_trait::Value as U32; -use sr_primitives::RuntimeDebug; -use sr_primitives::traits::{Hash, EnsureOrigin}; -use sr_primitives::weights::SimpleDispatchInfo; -use support::{ - dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, - traits::{ChangeMembers, InitializeMembers}, decl_module, decl_event, - decl_storage, ensure, -}; -use system::{self, ensure_signed, ensure_root}; - -/// Simple index type for proposal counting. -pub type ProposalIndex = u32; - -/// A number of members. -/// -/// This also serves as a number of voting members, and since for motions, each member may -/// vote exactly once, therefore also the number of votes for any given motion. -pub type MemberCount = u32; - -pub trait Trait: system::Trait { - /// The outer origin type. - type Origin: From>; - - /// The outer call dispatch type. - type Proposal: Parameter + Dispatchable>::Origin>; - - /// The outer event type. - type Event: From> + Into<::Event>; -} - -/// Origin for the collective module. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] -pub enum RawOrigin { - /// It has been condoned by a given number of members of the collective from a given total. - Members(MemberCount, MemberCount), - /// It has been condoned by a single member of the collective. - Member(AccountId), - /// Dummy to manage the fact we have instancing. - _Phantom(rstd::marker::PhantomData), -} - -/// Origin for the collective module. -pub type Origin = RawOrigin<::AccountId, I>; - -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] -/// Info for keeping track of a motion being voted on. -pub struct Votes { - /// The proposal's unique index. - index: ProposalIndex, - /// The number of approval votes that are needed to pass the motion. - threshold: MemberCount, - /// The current set of voters that approved it. - ayes: Vec, - /// The current set of voters that rejected it. - nays: Vec, -} - -decl_storage! { - trait Store for Module, I: Instance=DefaultInstance> as Collective { - /// The hashes of the active proposals. - pub Proposals get(fn proposals): Vec; - /// Actual proposal for a given hash, if it's current. - pub ProposalOf get(fn proposal_of): map T::Hash => Option<>::Proposal>; - /// Votes on a given proposal, if it is ongoing. - pub Voting get(fn voting): map T::Hash => Option>; - /// Proposals so far. - pub ProposalCount get(fn proposal_count): u32; - /// The current members of the collective. This is stored sorted (just by value). - pub Members get(fn members): Vec; - } - add_extra_genesis { - config(phantom): rstd::marker::PhantomData; - config(members): Vec; - build(|config| Module::::initialize_members(&config.members)) - } -} - -decl_event!( - pub enum Event where - ::Hash, - ::AccountId, - { - /// A motion (given hash) has been proposed (by given account) with a threshold (given - /// `MemberCount`). - Proposed(AccountId, ProposalIndex, Hash, MemberCount), - /// A motion (given hash) has been voted on by given account, leaving - /// a tally (yes votes and no votes given respectively as `MemberCount`). - Voted(AccountId, Hash, bool, MemberCount, MemberCount), - /// A motion was approved by the required threshold. - Approved(Hash), - /// A motion was not approved by the required threshold. - Disapproved(Hash), - /// A motion was executed; `bool` is true if returned without error. - Executed(Hash, bool), - /// A single member did some action; `bool` is true if returned without error. - MemberExecuted(Hash, bool), - } -); - -// Note: this module is not benchmarked. The weights are obtained based on the similarity of the -// executed logic with other democracy function. Note that councillor operations are assigned to the -// operational class. -decl_module! { - pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { - fn deposit_event() = default; - - /// Set the collective's membership manually to `new_members`. Be nice to the chain and - /// provide it pre-sorted. - /// - /// Requires root origin. - #[weight = SimpleDispatchInfo::FixedOperational(100_000)] - fn set_members(origin, new_members: Vec) { - ensure_root(origin)?; - let mut new_members = new_members; - new_members.sort(); - >::mutate(|m| { - >::set_members_sorted(&new_members[..], m); - *m = new_members; - }); - } - - /// Dispatch a proposal from a member using the `Member` origin. - /// - /// Origin must be a member of the collective. - #[weight = SimpleDispatchInfo::FixedOperational(100_000)] - fn execute(origin, proposal: Box<>::Proposal>) { - let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), "proposer not a member"); - - let proposal_hash = T::Hashing::hash_of(&proposal); - let ok = proposal.dispatch(RawOrigin::Member(who).into()).is_ok(); - Self::deposit_event(RawEvent::MemberExecuted(proposal_hash, ok)); - } - - /// # - /// - Bounded storage reads and writes. - /// - Argument `threshold` has bearing on weight. - /// # - #[weight = SimpleDispatchInfo::FixedOperational(5_000_000)] - fn propose(origin, #[compact] threshold: MemberCount, proposal: Box<>::Proposal>) { - let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), "proposer not a member"); - - let proposal_hash = T::Hashing::hash_of(&proposal); - - ensure!(!>::exists(proposal_hash), "duplicate proposals not allowed"); - - if threshold < 2 { - let seats = Self::members().len() as MemberCount; - let ok = proposal.dispatch(RawOrigin::Members(1, seats).into()).is_ok(); - Self::deposit_event(RawEvent::Executed(proposal_hash, ok)); - } else { - let index = Self::proposal_count(); - >::mutate(|i| *i += 1); - >::mutate(|proposals| proposals.push(proposal_hash)); - >::insert(proposal_hash, *proposal); - let votes = Votes { index, threshold, ayes: vec![who.clone()], nays: vec![] }; - >::insert(proposal_hash, votes); - - Self::deposit_event(RawEvent::Proposed(who, index, proposal_hash, threshold)); - } - } - - /// # - /// - Bounded storage read and writes. - /// - Will be slightly heavier if the proposal is approved / disapproved after the vote. - /// # - #[weight = SimpleDispatchInfo::FixedOperational(200_000)] - fn vote(origin, proposal: T::Hash, #[compact] index: ProposalIndex, approve: bool) { - let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), "voter not a member"); - - let mut voting = Self::voting(&proposal).ok_or("proposal must exist")?; - ensure!(voting.index == index, "mismatched index"); - - let position_yes = voting.ayes.iter().position(|a| a == &who); - let position_no = voting.nays.iter().position(|a| a == &who); - - if approve { - if position_yes.is_none() { - voting.ayes.push(who.clone()); - } else { - return Err("duplicate vote ignored") - } - if let Some(pos) = position_no { - voting.nays.swap_remove(pos); - } - } else { - if position_no.is_none() { - voting.nays.push(who.clone()); - } else { - return Err("duplicate vote ignored") - } - if let Some(pos) = position_yes { - voting.ayes.swap_remove(pos); - } - } - - let yes_votes = voting.ayes.len() as MemberCount; - let no_votes = voting.nays.len() as MemberCount; - Self::deposit_event(RawEvent::Voted(who, proposal, approve, yes_votes, no_votes)); - - let seats = Self::members().len() as MemberCount; - let approved = yes_votes >= voting.threshold; - let disapproved = seats.saturating_sub(no_votes) < voting.threshold; - if approved || disapproved { - if approved { - Self::deposit_event(RawEvent::Approved(proposal)); - - // execute motion, assuming it exists. - if let Some(p) = >::take(&proposal) { - let origin = RawOrigin::Members(voting.threshold, seats).into(); - let ok = p.dispatch(origin).is_ok(); - Self::deposit_event(RawEvent::Executed(proposal, ok)); - } - } else { - // disapproved - Self::deposit_event(RawEvent::Disapproved(proposal)); - } - - // remove vote - >::remove(&proposal); - >::mutate(|proposals| proposals.retain(|h| h != &proposal)); - } else { - // update voting - >::insert(&proposal, voting); - } - } - } -} - -impl, I: Instance> Module { - pub fn is_member(who: &T::AccountId) -> bool { - Self::members().contains(who) - } -} - -impl, I: Instance> ChangeMembers for Module { - fn change_members_sorted(_incoming: &[T::AccountId], outgoing: &[T::AccountId], new: &[T::AccountId]) { - // remove accounts from all current voting in motions. - let mut outgoing = outgoing.to_vec(); - outgoing.sort_unstable(); - for h in Self::proposals().into_iter() { - >::mutate(h, |v| - if let Some(mut votes) = v.take() { - votes.ayes = votes.ayes.into_iter() - .filter(|i| outgoing.binary_search(i).is_err()) - .collect(); - votes.nays = votes.nays.into_iter() - .filter(|i| outgoing.binary_search(i).is_err()) - .collect(); - *v = Some(votes); - } - ); - } - >::put(new); - } -} - -impl, I: Instance> InitializeMembers for Module { - fn initialize_members(members: &[T::AccountId]) { - if !members.is_empty() { - assert!(>::get().is_empty(), "Members are already initialized!"); - >::put(members); - } - } -} - -/// Ensure that the origin `o` represents at least `n` members. Returns `Ok` or an `Err` -/// otherwise. -pub fn ensure_members(o: OuterOrigin, n: MemberCount) - -> result::Result -where - OuterOrigin: Into, OuterOrigin>> -{ - match o.into() { - Ok(RawOrigin::Members(x, _)) if x >= n => Ok(n), - _ => Err("bad origin: expected to be a threshold number of members"), - } -} - -pub struct EnsureMember(rstd::marker::PhantomData<(AccountId, I)>); -impl< - O: Into, O>> + From>, - AccountId, - I, -> EnsureOrigin for EnsureMember { - type Success = AccountId; - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Member(id) => Ok(id), - r => Err(O::from(r)), - }) - } -} - -pub struct EnsureMembers(rstd::marker::PhantomData<(N, AccountId, I)>); -impl< - O: Into, O>> + From>, - N: U32, - AccountId, - I, -> EnsureOrigin for EnsureMembers { - type Success = (MemberCount, MemberCount); - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n >= N::VALUE => Ok((n, m)), - r => Err(O::from(r)), - }) - } -} - -pub struct EnsureProportionMoreThan( - rstd::marker::PhantomData<(N, D, AccountId, I)> -); -impl< - O: Into, O>> + From>, - N: U32, - D: U32, - AccountId, - I, -> EnsureOrigin for EnsureProportionMoreThan { - type Success = (); - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n * D::VALUE > N::VALUE * m => Ok(()), - r => Err(O::from(r)), - }) - } -} - -pub struct EnsureProportionAtLeast( - rstd::marker::PhantomData<(N, D, AccountId, I)> -); -impl< - O: Into, O>> + From>, - N: U32, - D: U32, - AccountId, - I, -> EnsureOrigin for EnsureProportionAtLeast { - type Success = (); - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Members(n, m) if n * D::VALUE >= N::VALUE * m => Ok(()), - r => Err(O::from(r)), - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use support::{Hashable, assert_ok, assert_noop, parameter_types}; - use system::{EventRecord, Phase}; - use hex_literal::hex; - use primitives::H256; - use sr_primitives::{ - Perbill, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, - BuildStorage, - }; - use crate as collective; - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - impl Trait for Test { - type Origin = Origin; - type Proposal = Call; - type Event = Event; - } - impl Trait for Test { - type Origin = Origin; - type Proposal = Call; - type Event = Event; - } - - pub type Block = sr_primitives::generic::Block; - pub type UncheckedExtrinsic = sr_primitives::generic::UncheckedExtrinsic; - - support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Module, Call, Event}, - Collective: collective::::{Module, Call, Event, Origin, Config}, - DefaultCollective: collective::{Module, Call, Event, Origin, Config}, - } - ); - - fn make_ext() -> runtime_io::TestExternalities { - GenesisConfig { - collective_Instance1: Some(collective::GenesisConfig { - members: vec![1, 2, 3], - phantom: Default::default(), - }), - collective: None, - }.build_storage().unwrap().into() - } - - #[test] - fn motions_basic_environment_works() { - make_ext().execute_with(|| { - System::set_block_number(1); - assert_eq!(Collective::members(), vec![1, 2, 3]); - assert_eq!(Collective::proposals(), Vec::::new()); - }); - } - - fn make_proposal(value: u64) -> Call { - Call::System(system::Call::remark(value.encode())) - } - - #[test] - fn removal_of_old_voters_votes_works() { - make_ext().execute_with(|| { - System::set_block_number(1); - let proposal = make_proposal(42); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); - assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![] }) - ); - Collective::change_members_sorted(&[4], &[1], &[2, 3, 4]); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![] }) - ); - - let proposal = make_proposal(69); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()))); - assert_ok!(Collective::vote(Origin::signed(3), hash.clone(), 1, false)); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3] }) - ); - Collective::change_members_sorted(&[], &[3], &[2, 4]); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![] }) - ); - }); - } - - #[test] - fn removal_of_old_voters_votes_works_with_set_members() { - make_ext().execute_with(|| { - System::set_block_number(1); - let proposal = make_proposal(42); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); - assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![] }) - ); - assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 3, 4])); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![] }) - ); - - let proposal = make_proposal(69); - let hash = BlakeTwo256::hash_of(&proposal); - assert_ok!(Collective::propose(Origin::signed(2), 2, Box::new(proposal.clone()))); - assert_ok!(Collective::vote(Origin::signed(3), hash.clone(), 1, false)); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3] }) - ); - assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 4])); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![] }) - ); - }); - } - - #[test] - fn propose_works() { - make_ext().execute_with(|| { - System::set_block_number(1); - let proposal = make_proposal(42); - let hash = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); - assert_eq!(Collective::proposals(), vec![hash]); - assert_eq!(Collective::proposal_of(&hash), Some(proposal)); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 0, threshold: 3, ayes: vec![1], nays: vec![] }) - ); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Proposed( - 1, - 0, - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - 3, - )), - topics: vec![], - } - ]); - }); - } - - #[test] - fn motions_ignoring_non_collective_proposals_works() { - make_ext().execute_with(|| { - System::set_block_number(1); - let proposal = make_proposal(42); - assert_noop!( - Collective::propose(Origin::signed(42), 3, Box::new(proposal.clone())), - "proposer not a member" - ); - }); - } - - #[test] - fn motions_ignoring_non_collective_votes_works() { - make_ext().execute_with(|| { - System::set_block_number(1); - let proposal = make_proposal(42); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); - assert_noop!( - Collective::vote(Origin::signed(42), hash.clone(), 0, true), - "voter not a member", - ); - }); - } - - #[test] - fn motions_ignoring_bad_index_collective_vote_works() { - make_ext().execute_with(|| { - System::set_block_number(3); - let proposal = make_proposal(42); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); - assert_noop!( - Collective::vote(Origin::signed(2), hash.clone(), 1, true), - "mismatched index", - ); - }); - } - - #[test] - fn motions_revoting_works() { - make_ext().execute_with(|| { - System::set_block_number(1); - let proposal = make_proposal(42); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 0, threshold: 2, ayes: vec![1], nays: vec![] }) - ); - assert_noop!( - Collective::vote(Origin::signed(1), hash.clone(), 0, true), - "duplicate vote ignored", - ); - assert_ok!(Collective::vote(Origin::signed(1), hash.clone(), 0, false)); - assert_eq!( - Collective::voting(&hash), - Some(Votes { index: 0, threshold: 2, ayes: vec![], nays: vec![1] }) - ); - assert_noop!( - Collective::vote(Origin::signed(1), hash.clone(), 0, false), - "duplicate vote ignored", - ); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Proposed( - 1, - 0, - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - 2, - )), - topics: vec![], - }, - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Voted( - 1, - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - false, - 0, - 1, - )), - topics: vec![], - } - ]); - }); - } - - #[test] - fn motions_disapproval_works() { - make_ext().execute_with(|| { - System::set_block_number(1); - let proposal = make_proposal(42); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); - assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, false)); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1( - RawEvent::Proposed( - 1, - 0, - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - 3, - )), - topics: vec![], - }, - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Voted( - 2, - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - false, - 1, - 1, - )), - topics: vec![], - }, - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Disapproved( - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - )), - topics: vec![], - } - ]); - }); - } - - #[test] - fn motions_approval_works() { - make_ext().execute_with(|| { - System::set_block_number(1); - let proposal = make_proposal(42); - let hash: H256 = proposal.blake2_256().into(); - assert_ok!(Collective::propose(Origin::signed(1), 2, Box::new(proposal.clone()))); - assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Proposed( - 1, - 0, - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - 2, - )), - topics: vec![], - }, - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Voted( - 2, - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - true, - 2, - 0, - )), - topics: vec![], - }, - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Approved( - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - )), - topics: vec![], - }, - EventRecord { - phase: Phase::Finalization, - event: Event::collective_Instance1(RawEvent::Executed( - hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), - false, - )), - topics: vec![], - } - ]); - }); - } -} diff --git a/srml/contracts/Cargo.toml b/srml/contracts/Cargo.toml deleted file mode 100644 index 365566cfb547e..0000000000000 --- a/srml/contracts/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "srml-contracts" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true, features = ["derive"] } -pwasm-utils = { version = "0.11.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -parity-wasm = { version = "0.40.3", default-features = false } -wasmi-validation = { version = "0.2.0", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sandbox = { package = "sr-sandbox", path = "../../core/sr-sandbox", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -wabt = "0.9.2" -assert_matches = "1.3.0" -hex-literal = "0.2.1" -balances = { package = "srml-balances", path = "../balances" } -hex = "0.3.2" -timestamp = { package = "srml-timestamp", path = "../timestamp" } -randomness-collective-flip = { package = "srml-randomness-collective-flip", path = "../randomness-collective-flip" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "primitives/std", - "sr-primitives/std", - "runtime-io/std", - "rstd/std", - "sandbox/std", - "support/std", - "system/std", - "parity-wasm/std", - "pwasm-utils/std", - "wasmi-validation/std", -] diff --git a/srml/contracts/rpc/Cargo.toml b/srml/contracts/rpc/Cargo.toml deleted file mode 100644 index 90bf34bec1fd9..0000000000000 --- a/srml/contracts/rpc/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "srml-contracts-rpc" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../../../core/client" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -jsonrpc-core = "13.2.0" -jsonrpc-core-client = "13.2.0" -jsonrpc-derive = "13.2.0" -primitives = { package = "substrate-primitives", path = "../../../core/primitives" } -rpc-primitives = { package = "substrate-rpc-primitives", path = "../../../core/rpc/primitives" } -serde = { version = "1.0.101", features = ["derive"] } -sr-primitives = { path = "../../../core/sr-primitives" } -srml-contracts-rpc-runtime-api = { path = "./runtime-api" } diff --git a/srml/contracts/rpc/runtime-api/Cargo.toml b/srml/contracts/rpc/runtime-api/Cargo.toml deleted file mode 100644 index 2a36ed2c96cc4..0000000000000 --- a/srml/contracts/rpc/runtime-api/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "srml-contracts-rpc-runtime-api" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../../../../core/client", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../../../core/sr-std", default-features = false } -serde = { version = "1.0.101", optional = true, features = ["derive"] } -sr-primitives = { path = "../../../../core/sr-primitives", default-features = false } - -[features] -default = ["std"] -std = [ - "client/std", - "codec/std", - "rstd/std", - "serde", - "sr-primitives/std", -] diff --git a/srml/contracts/rpc/runtime-api/src/lib.rs b/srml/contracts/rpc/runtime-api/src/lib.rs deleted file mode 100644 index 7f01b8bdfa6c0..0000000000000 --- a/srml/contracts/rpc/runtime-api/src/lib.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Runtime API definition required by Contracts RPC extensions. -//! -//! This API should be imported and implemented by the runtime, -//! of a node that wants to use the custom RPC extension -//! adding Contracts access methods. - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::vec::Vec; -use codec::{Encode, Decode, Codec}; -use sr_primitives::RuntimeDebug; - -/// A result of execution of a contract. -#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] -pub enum ContractExecResult { - /// The contract returned successfully. - /// - /// There is a status code and, optionally, some data returned by the contract. - Success { - /// Status code returned by the contract. - status: u8, - /// Output data returned by the contract. - /// - /// Can be empty. - data: Vec, - }, - /// The contract execution either trapped or returned an error. - Error, -} - -client::decl_runtime_apis! { - /// The API to interact with contracts without using executive. - pub trait ContractsApi where - AccountId: Codec, - Balance: Codec, - { - /// Perform a call from a specified account to a given contract. - /// - /// See the contracts' `call` dispatchable function for more details. - fn call( - origin: AccountId, - dest: AccountId, - value: Balance, - gas_limit: u64, - input_data: Vec, - ) -> ContractExecResult; - } -} diff --git a/srml/contracts/rpc/src/lib.rs b/srml/contracts/rpc/src/lib.rs deleted file mode 100644 index ba50bd12f0300..0000000000000 --- a/srml/contracts/rpc/src/lib.rs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Node-specific RPC methods for interaction with contracts. - -use std::sync::Arc; - -use serde::{Serialize, Deserialize}; -use client::blockchain::HeaderBackend; -use codec::Codec; -use jsonrpc_core::{Error, ErrorCode, Result}; -use jsonrpc_derive::rpc; -use primitives::Bytes; -use sr_primitives::{ - generic::BlockId, - traits::{Block as BlockT, ProvideRuntimeApi}, -}; -use rpc_primitives::number; - -pub use srml_contracts_rpc_runtime_api::{ContractExecResult, ContractsApi as ContractsRuntimeApi}; -pub use self::gen_client::Client as ContractsClient; - -/// A struct that encodes RPC parameters required for a call to a smart-contract. -#[derive(Serialize, Deserialize)] -#[serde(rename_all="camelCase")] -#[serde(deny_unknown_fields)] -pub struct CallRequest { - origin: AccountId, - dest: AccountId, - value: Balance, - gas_limit: number::NumberOrHex, - input_data: Bytes, -} - -/// Contracts RPC methods. -#[rpc] -pub trait ContractsApi { - /// Executes a call to a contract. - /// - /// This call is performed locally without submitting any transactions. Thus executing this - /// won't change any state. Nonetheless, the calling state-changing contracts is still possible. - /// - /// This method is useful for calling getter-like methods on contracts. - #[rpc(name = "contracts_call")] - fn call( - &self, - call_request: CallRequest, - at: Option, - ) -> Result; -} - -/// An implementation of contract specific RPC methods. -pub struct Contracts { - client: Arc, - _marker: std::marker::PhantomData, -} - -impl Contracts { - /// Create new `Contracts` with the given reference to the client. - pub fn new(client: Arc) -> Self { - Contracts { client, _marker: Default::default() } - } -} - -const RUNTIME_ERROR: i64 = 1; - -impl ContractsApi<::Hash, AccountId, Balance> for Contracts -where - Block: BlockT, - C: Send + Sync + 'static, - C: ProvideRuntimeApi, - C: HeaderBackend, - C::Api: ContractsRuntimeApi, - AccountId: Codec, - Balance: Codec, -{ - fn call( - &self, - call_request: CallRequest, - at: Option<::Hash>, - ) -> Result { - let api = self.client.runtime_api(); - let at = BlockId::hash(at.unwrap_or_else(|| - // If the block hash is not supplied assume the best block. - self.client.info().best_hash - )); - - let CallRequest { - origin, - dest, - value, - gas_limit, - input_data - } = call_request; - let gas_limit = gas_limit.to_number().map_err(|e| Error { - code: ErrorCode::InvalidParams, - message: e, - data: None, - })?; - - let exec_result = api - .call(&at, origin, dest, value, gas_limit, input_data.to_vec()) - .map_err(|e| Error { - code: ErrorCode::ServerError(RUNTIME_ERROR), - message: "Runtime trapped while executing a contract.".into(), - data: Some(format!("{:?}", e).into()), - })?; - - Ok(exec_result) - } -} diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs deleted file mode 100644 index 8eaef951bae46..0000000000000 --- a/srml/contracts/src/lib.rs +++ /dev/null @@ -1,1043 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Contract Module -//! -//! The Contract module provides functionality for the runtime to deploy and execute WebAssembly smart-contracts. -//! -//! - [`contract::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! -//! ## Overview -//! -//! This module extends accounts based on the `Currency` trait to have smart-contract functionality. It can -//! be used with other modules that implement accounts based on `Currency`. These "smart-contract accounts" -//! have the ability to instantiate smart-contracts and make calls to other contract and non-contract accounts. -//! -//! The smart-contract code is stored once in a `code_cache`, and later retrievable via its `code_hash`. -//! This means that multiple smart-contracts can be instantiated from the same `code_cache`, without replicating -//! the code each time. -//! -//! When a smart-contract is called, its associated code is retrieved via the code hash and gets executed. -//! This call can alter the storage entries of the smart-contract account, instantiate new smart-contracts, -//! or call other smart-contracts. -//! -//! Finally, when an account is reaped, its associated code and storage of the smart-contract account -//! will also be deleted. -//! -//! ### Gas -//! -//! Senders must specify a gas limit with every call, as all instructions invoked by the smart-contract require gas. -//! Unused gas is refunded after the call, regardless of the execution outcome. -//! -//! If the gas limit is reached, then all calls and state changes (including balance transfers) are only -//! reverted at the current call's contract level. For example, if contract A calls B and B runs out of gas mid-call, -//! then all of B's calls are reverted. Assuming correct error handling by contract A, A's other calls and state -//! changes still persist. -//! -//! ### Notable Scenarios -//! -//! Contract call failures are not always cascading. When failures occur in a sub-call, they do not "bubble up", -//! and the call will only revert at the specific contract level. For example, if contract A calls contract B, and B -//! fails, A can decide how to handle that failure, either proceeding or reverting A's changes. -//! -//! ## Interface -//! -//! ### Dispatchable functions -//! -//! * `put_code` - Stores the given binary Wasm code into the chain's storage and returns its `code_hash`. -//! * `instantiate` - Deploys a new contract from the given `code_hash`, optionally transferring some balance. -//! This instantiates a new smart contract account and calls its contract deploy handler to -//! initialize the contract. -//! * `call` - Makes a call to an account, optionally transferring some balance. -//! -//! ### Signed Extensions -//! -//! The contracts module defines the following extension: -//! -//! - [`CheckBlockGasLimit`]: Ensures that the transaction does not exceeds the block gas limit. -//! -//! The signed extension needs to be added as signed extra to the transaction type to be used in the -//! runtime. -//! -//! ## Usage -//! -//! The Contract module is a work in progress. The following examples show how this Contract module -//! can be used to instantiate and call contracts. -//! -//! * [`ink`](https://github.com/paritytech/ink) is -//! an [`eDSL`](https://wiki.haskell.org/Embedded_domain_specific_language) that enables writing -//! WebAssembly based smart contracts in the Rust programming language. This is a work in progress. -//! -//! ## Related Modules -//! -//! * [Balances](../srml_balances/index.html) - -#![cfg_attr(not(feature = "std"), no_std)] - -#[macro_use] -mod gas; - -mod account_db; -mod exec; -mod wasm; -mod rent; - -#[cfg(test)] -mod tests; - -use crate::exec::ExecutionContext; -use crate::account_db::{AccountDb, DirectAccountDb}; -use crate::wasm::{WasmLoader, WasmVm}; - -pub use crate::gas::{Gas, GasMeter}; -pub use crate::exec::{ExecResult, ExecReturnValue, ExecError, StatusCode}; - -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -use primitives::crypto::UncheckedFrom; -use rstd::{prelude::*, marker::PhantomData, fmt::Debug}; -use codec::{Codec, Encode, Decode}; -use runtime_io::blake2_256; -use sr_primitives::{ - traits::{Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, SignedExtension}, - weights::DispatchInfo, - transaction_validity::{ - ValidTransaction, InvalidTransaction, TransactionValidity, TransactionValidityError, - }, - RuntimeDebug, -}; -use support::dispatch::{Result, Dispatchable}; -use support::{ - Parameter, decl_module, decl_event, decl_storage, storage::child, - parameter_types, IsSubType -}; -use support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency, Get, Time, Randomness}; -use system::{ensure_signed, RawOrigin, ensure_root}; -use primitives::storage::well_known_keys::CHILD_STORAGE_KEY_PREFIX; - -pub type CodeHash = ::Hash; -pub type TrieId = Vec; - -/// 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; -} - -/// A function that returns the fee for dispatching a `Call`. -pub trait ComputeDispatchFee { - fn compute_dispatch_fee(call: &Call) -> Balance; -} - -/// Information for managing an acocunt and its sub trie abstraction. -/// This is the required info to cache for an account -#[derive(Encode, Decode, RuntimeDebug)] -pub enum ContractInfo { - Alive(AliveContractInfo), - Tombstone(TombstoneContractInfo), -} - -impl ContractInfo { - /// If contract is alive then return some alive info - pub fn get_alive(self) -> Option> { - if let ContractInfo::Alive(alive) = self { - Some(alive) - } else { - None - } - } - /// If contract is alive then return some reference to alive info - pub fn as_alive(&self) -> Option<&AliveContractInfo> { - if let ContractInfo::Alive(ref alive) = self { - Some(alive) - } else { - None - } - } - /// If contract is alive then return some mutable reference to alive info - pub fn as_alive_mut(&mut self) -> Option<&mut AliveContractInfo> { - if let ContractInfo::Alive(ref mut alive) = self { - Some(alive) - } else { - None - } - } - - /// If contract is tombstone then return some tombstone info - pub fn get_tombstone(self) -> Option> { - if let ContractInfo::Tombstone(tombstone) = self { - Some(tombstone) - } else { - None - } - } - /// If contract is tombstone then return some reference to tombstone info - pub fn as_tombstone(&self) -> Option<&TombstoneContractInfo> { - if let ContractInfo::Tombstone(ref tombstone) = self { - Some(tombstone) - } else { - None - } - } - /// If contract is tombstone then return some mutable reference to tombstone info - pub fn as_tombstone_mut(&mut self) -> Option<&mut TombstoneContractInfo> { - if let ContractInfo::Tombstone(ref mut tombstone) = self { - Some(tombstone) - } else { - None - } - } -} - -pub type AliveContractInfo = - RawAliveContractInfo, BalanceOf, ::BlockNumber>; - -/// Information for managing an account and its sub trie abstraction. -/// This is the required info to cache for an account. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct RawAliveContractInfo { - /// Unique ID for the subtree encoded as a bytes vector. - pub trie_id: TrieId, - /// The size of stored value in octet. - pub storage_size: u32, - /// The code associated with a given account. - pub code_hash: CodeHash, - /// Pay rent at most up to this value. - pub rent_allowance: Balance, - /// Last block rent has been payed. - pub deduct_block: BlockNumber, - /// Last block child storage has been written. - pub last_write: Option, -} - -pub type TombstoneContractInfo = - RawTombstoneContractInfo<::Hash, ::Hashing>; - -#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug)] -pub struct RawTombstoneContractInfo(H, PhantomData); - -impl RawTombstoneContractInfo -where - H: Member + MaybeSerializeDeserialize+ Debug - + AsRef<[u8]> + AsMut<[u8]> + Copy + Default - + rstd::hash::Hash + Codec, - Hasher: Hash, -{ - fn new(storage_root: &[u8], code_hash: H) -> Self { - let mut buf = Vec::new(); - storage_root.using_encoded(|encoded| buf.extend_from_slice(encoded)); - buf.extend_from_slice(code_hash.as_ref()); - RawTombstoneContractInfo(Hasher::hash(&buf[..]), PhantomData) - } -} - -/// Get a trie id (trie id must be unique and collision resistant depending upon its context). -/// Note that it is different than encode because trie id should be collision resistant -/// (being a proper unique identifier). -pub trait TrieIdGenerator { - /// Get a trie id for an account, using reference to parent account trie id to ensure - /// uniqueness of trie id. - /// - /// The implementation must ensure every new trie id is unique: two consecutive calls with the - /// same parameter needs to return different trie id values. - /// - /// Also, the implementation is responsible for ensuring that `TrieId` starts with - /// `:child_storage:`. - /// TODO: We want to change this, see https://github.com/paritytech/substrate/issues/2325 - fn trie_id(account_id: &AccountId) -> TrieId; -} - -/// Get trie id from `account_id`. -pub struct TrieIdFromParentCounter(PhantomData); - -/// This generator uses inner counter for account id and applies the hash over `AccountId + -/// accountid_counter`. -impl TrieIdGenerator for TrieIdFromParentCounter -where - T::AccountId: AsRef<[u8]> -{ - fn trie_id(account_id: &T::AccountId) -> TrieId { - // Note that skipping a value due to error is not an issue here. - // We only need uniqueness, not sequence. - let new_seed = AccountCounter::mutate(|v| { - *v = v.wrapping_add(1); - *v - }); - - let mut buf = Vec::new(); - buf.extend_from_slice(account_id.as_ref()); - buf.extend_from_slice(&new_seed.to_le_bytes()[..]); - - // TODO: see https://github.com/paritytech/substrate/issues/2325 - CHILD_STORAGE_KEY_PREFIX.iter() - .chain(b"default:") - .chain(T::Hashing::hash(&buf[..]).as_ref().iter()) - .cloned() - .collect() - } -} - -pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -pub type NegativeImbalanceOf = - <::Currency as Currency<::AccountId>>::NegativeImbalance; - -parameter_types! { - /// A reasonable default value for [`Trait::SignedClaimedHandicap`]. - pub const DefaultSignedClaimHandicap: u32 = 2; - /// A reasonable default value for [`Trait::TombstoneDeposit`]. - pub const DefaultTombstoneDeposit: u32 = 16; - /// A reasonable default value for [`Trait::StorageSizeOffset`]. - pub const DefaultStorageSizeOffset: u32 = 8; - /// A reasonable default value for [`Trait::RentByteFee`]. - pub const DefaultRentByteFee: u32 = 4; - /// A reasonable default value for [`Trait::RentDepositOffset`]. - pub const DefaultRentDepositOffset: u32 = 1000; - /// A reasonable default value for [`Trait::SurchargeReward`]. - pub const DefaultSurchargeReward: u32 = 150; - /// A reasonable default value for [`Trait::TransferFee`]. - pub const DefaultTransferFee: u32 = 0; - /// A reasonable default value for [`Trait::InstantiationFee`]. - pub const DefaultInstantiationFee: u32 = 0; - /// A reasonable default value for [`Trait::TransactionBaseFee`]. - pub const DefaultTransactionBaseFee: u32 = 0; - /// A reasonable default value for [`Trait::TransactionByteFee`]. - pub const DefaultTransactionByteFee: u32 = 0; - /// A reasonable default value for [`Trait::ContractFee`]. - pub const DefaultContractFee: u32 = 21; - /// A reasonable default value for [`Trait::CallBaseFee`]. - pub const DefaultCallBaseFee: u32 = 1000; - /// A reasonable default value for [`Trait::InstantiateBaseFee`]. - pub const DefaultInstantiateBaseFee: u32 = 1000; - /// A reasonable default value for [`Trait::MaxDepth`]. - pub const DefaultMaxDepth: u32 = 32; - /// A reasonable default value for [`Trait::MaxValueSize`]. - pub const DefaultMaxValueSize: u32 = 16_384; - /// A reasonable default value for [`Trait::BlockGasLimit`]. - pub const DefaultBlockGasLimit: u32 = 10_000_000; -} - -pub trait Trait: system::Trait { - type Currency: Currency; - type Time: Time; - type Randomness: Randomness; - - /// The outer call dispatch type. - type Call: Parameter + Dispatchable::Origin> + IsSubType, Self>; - - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// A function type to get the contract address given the instantiator. - type DetermineContractAddress: ContractAddressFor, Self::AccountId>; - - /// A function type that computes the fee for dispatching the given `Call`. - /// - /// It is recommended (though not required) for this function to return a fee that would be - /// taken by the Executive module for regular dispatch. - type ComputeDispatchFee: ComputeDispatchFee<::Call, BalanceOf>; - - /// trie id generator - type TrieIdGenerator: TrieIdGenerator; - - /// Handler for the unbalanced reduction when making a gas payment. - type GasPayment: OnUnbalanced>; - - /// Handler for rent payments. - type RentPayment: OnUnbalanced>; - - /// Number of block delay an extrinsic claim surcharge has. - /// - /// When claim surcharge is called by an extrinsic the rent is checked - /// for current_block - delay - type SignedClaimHandicap: Get; - - /// The minimum amount required to generate a tombstone. - type TombstoneDeposit: Get>; - - /// Size of a contract at the time of instantiation. This is a simple way to ensure - /// that empty contracts eventually gets deleted. - type StorageSizeOffset: Get; - - /// Price of a byte of storage per one block interval. Should be greater than 0. - type RentByteFee: Get>; - - /// The amount of funds a contract should deposit in order to offset - /// the cost of one byte. - /// - /// Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day, - /// then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent. - /// But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000, - /// then it would pay 500 BU/day. - type RentDepositOffset: Get>; - - /// Reward that is received by the party whose touch has led - /// to removal of a contract. - type SurchargeReward: Get>; - - /// The fee required to make a transfer. - type TransferFee: Get>; - - /// The fee required to create an account. - type CreationFee: Get>; - - /// The fee to be paid for making a transaction; the base. - type TransactionBaseFee: Get>; - - /// The fee to be paid for making a transaction; the per-byte portion. - type TransactionByteFee: Get>; - - /// The fee required to instantiate a contract instance. - type ContractFee: Get>; - - /// The base fee charged for calling into a contract. - type CallBaseFee: Get; - - /// The base fee charged for instantiating a contract. - type InstantiateBaseFee: Get; - - /// The maximum nesting level of a call/instantiate stack. - type MaxDepth: Get; - - /// The maximum size of a storage value in bytes. - type MaxValueSize: Get; - - /// The maximum amount of gas that could be expended per block. - type BlockGasLimit: Get; -} - -/// Simple contract address determiner. -/// -/// Address calculated from the code (of the constructor), input data to the constructor, -/// and the account id that requested the account creation. -/// -/// Formula: `blake2_256(blake2_256(code) + blake2_256(data) + origin)` -pub struct SimpleAddressDeterminator(PhantomData); -impl ContractAddressFor, T::AccountId> for SimpleAddressDeterminator -where - T::AccountId: UncheckedFrom + AsRef<[u8]> -{ - 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(); - buf.extend_from_slice(code_hash.as_ref()); - buf.extend_from_slice(data_hash.as_ref()); - buf.extend_from_slice(origin.as_ref()); - - UncheckedFrom::unchecked_from(T::Hashing::hash(&buf[..])) - } -} - -/// The default dispatch fee computor computes the fee in the same way that -/// the implementation of `ChargeTransactionPayment` for the Balances module does. Note that this only takes a fixed -/// fee based on size. Unlike the balances module, weight-fee is applied. -pub struct DefaultDispatchFeeComputor(PhantomData); -impl ComputeDispatchFee<::Call, BalanceOf> for DefaultDispatchFeeComputor { - fn compute_dispatch_fee(call: &::Call) -> BalanceOf { - let encoded_len = call.using_encoded(|encoded| encoded.len() as u32); - let base_fee = T::TransactionBaseFee::get(); - let byte_fee = T::TransactionByteFee::get(); - base_fee + byte_fee * encoded_len.into() - } -} - -decl_module! { - /// Contracts module. - pub struct Module for enum Call where origin: ::Origin { - /// Number of block delay an extrinsic claim surcharge has. - /// - /// When claim surcharge is called by an extrinsic the rent is checked - /// for current_block - delay - const SignedClaimHandicap: T::BlockNumber = T::SignedClaimHandicap::get(); - - /// The minimum amount required to generate a tombstone. - const TombstoneDeposit: BalanceOf = T::TombstoneDeposit::get(); - - /// Size of a contract at the time of instantiaion. This is a simple way to ensure that - /// empty contracts eventually gets deleted. - const StorageSizeOffset: u32 = T::StorageSizeOffset::get(); - - /// Price of a byte of storage per one block interval. Should be greater than 0. - const RentByteFee: BalanceOf = T::RentByteFee::get(); - - /// The amount of funds a contract should deposit in order to offset - /// the cost of one byte. - /// - /// Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day, - /// then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent. - /// But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000, - /// then it would pay 500 BU/day. - const RentDepositOffset: BalanceOf = T::RentDepositOffset::get(); - - /// Reward that is received by the party whose touch has led - /// to removal of a contract. - const SurchargeReward: BalanceOf = T::SurchargeReward::get(); - - /// The fee required to make a transfer. - const TransferFee: BalanceOf = T::TransferFee::get(); - - /// The fee required to create an account. - const CreationFee: BalanceOf = T::CreationFee::get(); - - /// The fee to be paid for making a transaction; the base. - const TransactionBaseFee: BalanceOf = T::TransactionBaseFee::get(); - - /// The fee to be paid for making a transaction; the per-byte portion. - const TransactionByteFee: BalanceOf = T::TransactionByteFee::get(); - - /// The fee required to instantiate a contract instance. A reasonable default value - /// is 21. - const ContractFee: BalanceOf = T::ContractFee::get(); - - /// The base fee charged for calling into a contract. A reasonable default - /// value is 135. - const CallBaseFee: Gas = T::CallBaseFee::get(); - - /// The base fee charged for instantiating a contract. A reasonable default value - /// is 175. - const InstantiateBaseFee: Gas = T::InstantiateBaseFee::get(); - - /// The maximum nesting level of a call/instantiate stack. A reasonable default - /// value is 100. - const MaxDepth: u32 = T::MaxDepth::get(); - - /// The maximum size of a storage value in bytes. A reasonable default is 16 KiB. - const MaxValueSize: u32 = T::MaxValueSize::get(); - - /// The maximum amount of gas that could be expended per block. A reasonable - /// default value is 10_000_000. - const BlockGasLimit: Gas = T::BlockGasLimit::get(); - - fn deposit_event() = default; - - /// Updates the schedule for metering contracts. - /// - /// The schedule must have a greater version than the stored schedule. - pub fn update_schedule(origin, schedule: Schedule) -> Result { - ensure_root(origin)?; - if >::current_schedule().version >= schedule.version { - return Err("new schedule must have a greater version than current"); - } - - Self::deposit_event(RawEvent::ScheduleUpdated(schedule.version)); - CurrentSchedule::put(schedule); - - Ok(()) - } - - /// Stores the given binary Wasm code into the chain's storage and returns its `codehash`. - /// You can instantiate contracts only with stored code. - pub fn put_code( - origin, - #[compact] gas_limit: Gas, - code: Vec - ) -> Result { - let origin = ensure_signed(origin)?; - - let (mut gas_meter, imbalance) = gas::buy_gas::(&origin, gas_limit)?; - - let schedule = >::current_schedule(); - 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, imbalance); - - result.map(|_| ()) - } - - /// Makes a call to an account, optionally transferring some balance. - /// - /// * If the account is a smart-contract account, the associated code will be - /// executed and any value will be transferred. - /// * If the account is a regular account, any value will be transferred. - /// * If no account exists and the call value is not less than `existential_deposit`, - /// a regular account will be created and any value will be transferred. - pub fn call( - origin, - dest: ::Source, - #[compact] value: BalanceOf, - #[compact] gas_limit: Gas, - data: Vec - ) -> Result { - let origin = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; - - Self::bare_call(origin, dest, value, gas_limit, data) - .map(|_| ()) - .map_err(|e| e.reason) - } - - /// Instantiates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance. - /// - /// Instantiation is executed as follows: - /// - /// - The destination address is computed based on the sender and hash of the code. - /// - The smart-contract account is created at the computed address. - /// - The `ctor_code` is executed in the context of the newly-created account. Buffer returned - /// after the execution is saved as the `code` of the account. That code will be invoked - /// upon any call received by this account. - /// - The contract is initialized. - pub fn instantiate( - origin, - #[compact] endowment: BalanceOf, - #[compact] gas_limit: Gas, - code_hash: CodeHash, - data: Vec - ) -> Result { - let origin = ensure_signed(origin)?; - - Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { - ctx.instantiate(endowment, gas_meter, &code_hash, data) - .map(|(_address, output)| output) - }) - .map(|_| ()) - .map_err(|e| e.reason) - } - - /// Allows block producers to claim a small reward for evicting a contract. If a block producer - /// fails to do so, a regular users will be allowed to claim the reward. - /// - /// If contract is not evicted as a result of this call, no actions are taken and - /// the sender is not eligible for the reward. - fn claim_surcharge(origin, dest: T::AccountId, aux_sender: Option) { - let origin = origin.into(); - let (signed, rewarded) = match (origin, aux_sender) { - (Ok(system::RawOrigin::Signed(account)), None) => { - (true, account) - }, - (Ok(system::RawOrigin::None), Some(aux_sender)) => { - (false, aux_sender) - }, - _ => return Err( - "Invalid surcharge claim: origin must be signed or \ - inherent and auxiliary sender only provided on inherent" - ), - }; - - // Add some advantage for block producers (who send unsigned extrinsics) by - // adding a handicap: for signed extrinsics we use a slightly older block number - // for the eviction check. This can be viewed as if we pushed regular users back in past. - let handicap = if signed { - T::SignedClaimHandicap::get() - } else { - Zero::zero() - }; - - // If poking the contract has lead to eviction of the contract, give out the rewards. - if rent::try_evict::(&dest, handicap) == rent::RentOutcome::Evicted { - T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?; - } - } - - fn on_finalize() { - GasSpent::kill(); - } - } -} - -impl Module { - /// Perform a call to a specified contract. - /// - /// This function is similar to `Self::call`, but doesn't perform any lookups and better - /// suitable for calling directly from Rust. - pub fn bare_call( - origin: T::AccountId, - dest: T::AccountId, - value: BalanceOf, - gas_limit: Gas, - input_data: Vec, - ) -> ExecResult { - Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { - ctx.call(dest, value, gas_meter, input_data) - }) - } - - fn execute_wasm( - origin: T::AccountId, - gas_limit: Gas, - func: impl FnOnce(&mut ExecutionContext, &mut GasMeter) -> ExecResult - ) -> ExecResult { - // Pay for the gas upfront. - // - // NOTE: it is very important to avoid any state changes before - // paying for the gas. - let (mut gas_meter, imbalance) = - try_or_exec_error!( - gas::buy_gas::(&origin, gas_limit), - // We don't have a spare buffer here in the first place, so create a new empty one. - Vec::new() - ); - - let cfg = Config::preload(); - let vm = WasmVm::new(&cfg.schedule); - let loader = WasmLoader::new(&cfg.schedule); - let mut ctx = ExecutionContext::top_level(origin.clone(), &cfg, &vm, &loader); - - let result = func(&mut ctx, &mut gas_meter); - - if result.as_ref().map(|output| output.is_success()).unwrap_or(false) { - // Commit all changes that made it thus far into the persistent storage. - DirectAccountDb.commit(ctx.overlay.into_change_set()); - } - - // Refund cost of the unused gas. - // - // NOTE: This should go after the commit to the storage, since the storage changes - // can alter the balance of the caller. - gas::refund_unused_gas::(&origin, gas_meter, imbalance); - - // Execute deferred actions. - ctx.deferred.into_iter().for_each(|deferred| { - use self::exec::DeferredAction::*; - match deferred { - DepositEvent { - topics, - event, - } => >::deposit_event_indexed( - &*topics, - ::Event::from(event).into(), - ), - DispatchRuntimeCall { - origin: who, - call, - } => { - let result = call.dispatch(RawOrigin::Signed(who.clone()).into()); - Self::deposit_event(RawEvent::Dispatched(who, result.is_ok())); - } - RestoreTo { - donor, - dest, - code_hash, - rent_allowance, - delta, - } => { - let _result = Self::restore_to(donor, dest, code_hash, rent_allowance, delta); - } - } - }); - - result - } - - fn restore_to( - origin: T::AccountId, - dest: T::AccountId, - code_hash: CodeHash, - rent_allowance: BalanceOf, - delta: Vec - ) -> Result { - let mut origin_contract = >::get(&origin) - .and_then(|c| c.get_alive()) - .ok_or("Cannot restore from inexisting or tombstone contract")?; - - let current_block = >::block_number(); - - if origin_contract.last_write == Some(current_block) { - return Err("Origin TrieId written in the current block"); - } - - let dest_tombstone = >::get(&dest) - .and_then(|c| c.get_tombstone()) - .ok_or("Cannot restore to inexisting or alive contract")?; - - let last_write = if !delta.is_empty() { - Some(current_block) - } else { - origin_contract.last_write - }; - - let key_values_taken = delta.iter() - .filter_map(|key| { - child::get_raw(&origin_contract.trie_id, &blake2_256(key)).map(|value| { - child::kill(&origin_contract.trie_id, &blake2_256(key)); - (key, value) - }) - }) - .collect::>(); - - let tombstone = >::new( - // This operation is cheap enough because last_write (delta not included) - // is not this block as it has been checked earlier. - &runtime_io::child_storage_root(&origin_contract.trie_id)[..], - code_hash, - ); - - if tombstone != dest_tombstone { - for (key, value) in key_values_taken { - child::put_raw(&origin_contract.trie_id, &blake2_256(key), &value); - } - - return Err("Tombstones don't match"); - } - - origin_contract.storage_size -= key_values_taken.iter() - .map(|(_, value)| value.len() as u32) - .sum::(); - - >::remove(&origin); - >::insert(&dest, ContractInfo::Alive(RawAliveContractInfo { - trie_id: origin_contract.trie_id, - storage_size: origin_contract.storage_size, - code_hash, - rent_allowance, - deduct_block: current_block, - last_write, - })); - - let origin_free_balance = T::Currency::free_balance(&origin); - T::Currency::make_free_balance_be(&origin, >::zero()); - T::Currency::deposit_creating(&dest, origin_free_balance); - - Ok(()) - } -} - -decl_event! { - pub enum Event - where - Balance = BalanceOf, - ::AccountId, - ::Hash - { - /// Transfer happened `from` to `to` with given `value` as part of a `call` or `instantiate`. - Transfer(AccountId, AccountId, Balance), - - /// Contract deployed by address at the specified address. - Instantiated(AccountId, AccountId), - - /// 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), - - /// An event from contract of account. - Contract(AccountId, Vec), - } -} - -decl_storage! { - trait Store for Module as Contract { - /// Gas spent so far in this block. - GasSpent get(fn gas_spent): Gas; - /// Current cost schedule for contracts. - CurrentSchedule get(fn current_schedule) config(): Schedule = Schedule::default(); - /// A mapping from an original code hash to the original code, untouched by instrumentation. - pub PristineCode: map CodeHash => Option>; - /// A mapping between an original code hash and instrumented wasm code, ready for execution. - pub CodeStorage: map CodeHash => Option; - /// The subtrie counter. - pub AccountCounter: u64 = 0; - /// The code associated with a given account. - pub ContractInfoOf: map T::AccountId => Option>; - /// The price of one unit of gas. - GasPrice get(fn gas_price) config(): BalanceOf = 1.into(); - } -} - -impl OnFreeBalanceZero for Module { - fn on_free_balance_zero(who: &T::AccountId) { - if let Some(ContractInfo::Alive(info)) = >::take(who) { - child::kill_storage(&info.trie_id); - } - } -} - -/// In-memory cache of configuration values. -/// -/// We assume that these values can't be changed in the -/// course of transaction execution. -pub struct Config { - pub schedule: Schedule, - pub existential_deposit: BalanceOf, - pub max_depth: u32, - pub max_value_size: u32, - pub contract_account_instantiate_fee: BalanceOf, - pub account_create_fee: BalanceOf, - pub transfer_fee: BalanceOf, -} - -impl Config { - fn preload() -> Config { - Config { - schedule: >::current_schedule(), - existential_deposit: T::Currency::minimum_balance(), - max_depth: T::MaxDepth::get(), - max_value_size: T::MaxValueSize::get(), - contract_account_instantiate_fee: T::ContractFee::get(), - account_create_fee: T::CreationFee::get(), - transfer_fee: T::TransferFee::get(), - } - } -} - -/// Definition of the cost schedule and other parameterizations for wasm vm. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] -pub struct Schedule { - /// Version of the schedule. - pub version: u32, - - /// Cost of putting a byte of code into storage. - pub put_code_per_byte_cost: Gas, - - /// Gas cost of a growing memory by single page. - pub grow_mem_cost: Gas, - - /// Gas cost of a regular operation. - pub regular_op_cost: Gas, - - /// Gas cost per one byte returned. - pub return_data_per_byte_cost: Gas, - - /// Gas cost to deposit an event; the per-byte portion. - pub event_data_per_byte_cost: Gas, - - /// Gas cost to deposit an event; the cost per topic. - pub event_per_topic_cost: Gas, - - /// Gas cost to deposit an event; the base. - pub event_base_cost: Gas, - - /// Base gas cost to call into a contract. - pub call_base_cost: Gas, - - /// Base gas cost to instantiate a contract. - pub instantiate_base_cost: Gas, - - /// Gas cost per one byte read from the sandbox memory. - pub sandbox_data_read_cost: Gas, - - /// Gas cost per one byte written to the sandbox memory. - pub sandbox_data_write_cost: Gas, - - /// The maximum number of topics supported by an event. - pub max_event_topics: u32, - - /// Maximum allowed stack height. - /// - /// See https://wiki.parity.io/WebAssembly-StackHeight to find out - /// how the stack frame cost is calculated. - pub max_stack_height: u32, - - /// Maximum number of memory pages allowed for a contract. - pub max_memory_pages: u32, - - /// Maximum allowed size of a declared table. - pub max_table_size: u32, - - /// Whether the `ext_println` function is allowed to be used contracts. - /// MUST only be enabled for `dev` chains, NOT for production chains - pub enable_println: bool, - - /// The maximum length of a subject used for PRNG generation. - pub max_subject_len: u32, -} - -impl Default for Schedule { - fn default() -> Schedule { - Schedule { - version: 0, - put_code_per_byte_cost: 1, - grow_mem_cost: 1, - regular_op_cost: 1, - return_data_per_byte_cost: 1, - event_data_per_byte_cost: 1, - event_per_topic_cost: 1, - event_base_cost: 1, - call_base_cost: 135, - instantiate_base_cost: 175, - sandbox_data_read_cost: 1, - sandbox_data_write_cost: 1, - max_event_topics: 4, - max_stack_height: 64 * 1024, - max_memory_pages: 16, - max_table_size: 16 * 1024, - enable_println: false, - max_subject_len: 32, - } - } -} - -/// `SignedExtension` that checks if a transaction would exhausts the block gas limit. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckBlockGasLimit(PhantomData); - -impl Default for CheckBlockGasLimit { - fn default() -> Self { - Self(PhantomData) - } -} - -impl rstd::fmt::Debug for CheckBlockGasLimit { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "CheckBlockGasLimit") - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -impl SignedExtension for CheckBlockGasLimit { - type AccountId = T::AccountId; - type Call = ::Call; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } - - fn validate( - &self, - _: &Self::AccountId, - call: &Self::Call, - _: DispatchInfo, - _: usize, - ) -> TransactionValidity { - let call = match call.is_sub_type() { - Some(call) => call, - None => return Ok(ValidTransaction::default()), - }; - - match call { - Call::claim_surcharge(_, _) | Call::update_schedule(_) => - Ok(ValidTransaction::default()), - Call::put_code(gas_limit, _) - | Call::call(_, _, gas_limit, _) - | Call::instantiate(_, gas_limit, _, _) - => { - // Check if the specified amount of gas is available in the current block. - // This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`. - let gas_available = T::BlockGasLimit::get() - >::gas_spent(); - if *gas_limit > gas_available { - // gas limit reached, revert the transaction and retry again in the future - InvalidTransaction::ExhaustsResources.into() - } else { - Ok(ValidTransaction::default()) - } - }, - Call::__PhantomItem(_, _) => unreachable!("Variant is never constructed"), - } - } -} diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs deleted file mode 100644 index 7a13a66de26c7..0000000000000 --- a/srml/contracts/src/tests.rs +++ /dev/null @@ -1,2343 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -// TODO: #1417 Add more integration tests -// also remove the #![allow(unused)] below. - -#![allow(unused)] - -use crate::{ - BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, - Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, Schedule, - TrieIdGenerator, CheckBlockGasLimit, account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}, -}; -use assert_matches::assert_matches; -use hex_literal::*; -use codec::{Decode, Encode, KeyedVec}; -use sr_primitives::{ - Perbill, BuildStorage, transaction_validity::{InvalidTransaction, ValidTransaction}, - traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension}, - weights::{DispatchInfo, DispatchClass}, - testing::{Digest, DigestItem, Header, UintAuthorityId, H256}, -}; -use support::{ - assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, - storage::child, StorageMap, StorageValue, traits::{Currency, Get}, -}; -use std::{cell::RefCell, sync::atomic::{AtomicUsize, Ordering}}; -use primitives::storage::well_known_keys; -use system::{self, EventRecord, Phase}; - -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 support::impl_outer_event; -} -impl_outer_event! { - pub enum MetaEvent for Test { - balances, contract, - } -} -impl_outer_origin! { - pub enum Origin for Test { } -} -impl_outer_dispatch! { - pub enum Call for Test where origin: Origin { - balances::Balances, - contract::Contract, - } -} - -thread_local! { - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); - static TRANSFER_FEE: RefCell = RefCell::new(0); - static INSTANTIATION_FEE: RefCell = RefCell::new(0); - static BLOCK_GAS_LIMIT: RefCell = RefCell::new(0); -} - -pub struct ExistentialDeposit; -impl Get for ExistentialDeposit { - fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } -} - -pub struct TransferFee; -impl Get for TransferFee { - fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) } -} - -pub struct CreationFee; -impl Get for CreationFee { - fn get() -> u64 { INSTANTIATION_FEE.with(|v| *v.borrow()) } -} - -pub struct BlockGasLimit; -impl Get for BlockGasLimit { - fn get() -> u64 { BLOCK_GAS_LIMIT.with(|v| *v.borrow()) } -} - -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct Test; -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = (); - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = MetaEvent; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); -} -impl balances::Trait for Test { - type Balance = u64; - type OnFreeBalanceZero = Contract; - type OnNewAccount = (); - type Event = MetaEvent; - type DustRemoval = (); - type TransferPayment = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} -parameter_types! { - pub const MinimumPeriod: u64 = 1; -} -impl timestamp::Trait for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; -} -parameter_types! { - pub const SignedClaimHandicap: u64 = 2; - pub const TombstoneDeposit: u64 = 16; - pub const StorageSizeOffset: u32 = 8; - pub const RentByteFee: u64 = 4; - pub const RentDepositOffset: u64 = 10_000; - pub const SurchargeReward: u64 = 150; - pub const TransactionBaseFee: u64 = 2; - pub const TransactionByteFee: u64 = 6; - pub const ContractFee: u64 = 21; - pub const CallBaseFee: u64 = 135; - pub const InstantiateBaseFee: u64 = 175; - pub const MaxDepth: u32 = 100; - pub const MaxValueSize: u32 = 16_384; -} -impl Trait for Test { - type Currency = Balances; - type Time = Timestamp; - type Randomness = Randomness; - type Call = Call; - type DetermineContractAddress = DummyContractAddressFor; - type Event = MetaEvent; - type ComputeDispatchFee = DummyComputeDispatchFee; - type TrieIdGenerator = DummyTrieIdGenerator; - type GasPayment = (); - type RentPayment = (); - type SignedClaimHandicap = SignedClaimHandicap; - type TombstoneDeposit = TombstoneDeposit; - type StorageSizeOffset = StorageSizeOffset; - type RentByteFee = RentByteFee; - type RentDepositOffset = RentDepositOffset; - type SurchargeReward = SurchargeReward; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type ContractFee = ContractFee; - type CallBaseFee = CallBaseFee; - type InstantiateBaseFee = InstantiateBaseFee; - type MaxDepth = MaxDepth; - type MaxValueSize = MaxValueSize; - type BlockGasLimit = BlockGasLimit; -} - -type Balances = balances::Module; -type Timestamp = timestamp::Module; -type Contract = Module; -type System = system::Module; -type Randomness = randomness_collective_flip::Module; - -pub struct DummyContractAddressFor; -impl ContractAddressFor for DummyContractAddressFor { - fn contract_address_for(_code_hash: &H256, _data: &[u8], origin: &u64) -> u64 { - *origin + 1 - } -} - -pub struct DummyTrieIdGenerator; -impl TrieIdGenerator for DummyTrieIdGenerator { - fn trie_id(account_id: &u64) -> TrieId { - use primitives::storage::well_known_keys; - - let new_seed = super::AccountCounter::mutate(|v| { - *v = v.wrapping_add(1); - *v - }); - - // TODO: see https://github.com/paritytech/substrate/issues/2325 - let mut res = vec![]; - res.extend_from_slice(well_known_keys::CHILD_STORAGE_KEY_PREFIX); - res.extend_from_slice(b"default:"); - res.extend_from_slice(&new_seed.to_le_bytes()); - res.extend_from_slice(&account_id.to_le_bytes()); - res - } -} - -pub struct DummyComputeDispatchFee; -impl ComputeDispatchFee for DummyComputeDispatchFee { - fn compute_dispatch_fee(call: &Call) -> u64 { - 69 - } -} - -const ALICE: u64 = 1; -const BOB: u64 = 2; -const CHARLIE: u64 = 3; -const DJANGO: u64 = 4; - -pub struct ExtBuilder { - existential_deposit: u64, - gas_price: u64, - block_gas_limit: u64, - transfer_fee: u64, - instantiation_fee: u64, -} -impl Default for ExtBuilder { - fn default() -> Self { - Self { - existential_deposit: 0, - gas_price: 2, - block_gas_limit: 100_000_000, - transfer_fee: 0, - instantiation_fee: 0, - } - } -} -impl ExtBuilder { - pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { - self.existential_deposit = existential_deposit; - self - } - pub fn gas_price(mut self, gas_price: u64) -> Self { - self.gas_price = gas_price; - self - } - pub fn block_gas_limit(mut self, block_gas_limit: u64) -> Self { - self.block_gas_limit = block_gas_limit; - self - } - pub fn transfer_fee(mut self, transfer_fee: u64) -> Self { - self.transfer_fee = transfer_fee; - self - } - pub fn instantiation_fee(mut self, instantiation_fee: u64) -> Self { - self.instantiation_fee = instantiation_fee; - self - } - pub fn set_associated_consts(&self) { - EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); - TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee); - INSTANTIATION_FEE.with(|v| *v.borrow_mut() = self.instantiation_fee); - BLOCK_GAS_LIMIT.with(|v| *v.borrow_mut() = self.block_gas_limit); - } - pub fn build(self) -> runtime_io::TestExternalities { - self.set_associated_consts(); - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig:: { - balances: vec![], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - GenesisConfig:: { - current_schedule: Schedule { - enable_println: true, - ..Default::default() - }, - gas_price: self.gas_price, - }.assimilate_storage(&mut t).unwrap(); - runtime_io::TestExternalities::new(t) - } -} - -/// Generate Wasm binary and code hash from wabt source. -fn compile_module(wabt_module: &str) - -> Result<(Vec, ::Output), wabt::Error> - where T: system::Trait -{ - let wasm = wabt::wat2wasm(wabt_module)?; - let code_hash = T::Hashing::hash(&wasm); - Ok((wasm, code_hash)) -} - -// Perform a simple transfer to a non-existent account supplying way more gas than needed. -// Then we check that the all unused gas is refunded. -#[test] -fn refunds_unused_gas() { - ExtBuilder::default().gas_price(2).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 100_000_000); - - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, Vec::new())); - - // 2 * 135 - gas price multiplied by the call base fee. - assert_eq!(Balances::free_balance(&ALICE), 100_000_000 - (2 * 135)); - }); -} - -#[test] -fn account_removal_removes_storage() { - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - let trie_id1 = ::TrieIdGenerator::trie_id(&1); - let trie_id2 = ::TrieIdGenerator::trie_id(&2); - let key1 = &[1; 32]; - let key2 = &[2; 32]; - - // Set up two accounts with free balance above the existential threshold. - { - Balances::deposit_creating(&1, 110); - ContractInfoOf::::insert(1, &ContractInfo::Alive(RawAliveContractInfo { - trie_id: trie_id1.clone(), - storage_size: ::StorageSizeOffset::get(), - deduct_block: System::block_number(), - code_hash: H256::repeat_byte(1), - rent_allowance: 40, - last_write: None, - })); - - let mut overlay = OverlayAccountDb::::new(&DirectAccountDb); - overlay.set_storage(&1, key1.clone(), Some(b"1".to_vec())); - overlay.set_storage(&1, key2.clone(), Some(b"2".to_vec())); - DirectAccountDb.commit(overlay.into_change_set()); - - Balances::deposit_creating(&2, 110); - ContractInfoOf::::insert(2, &ContractInfo::Alive(RawAliveContractInfo { - trie_id: trie_id2.clone(), - storage_size: ::StorageSizeOffset::get(), - deduct_block: System::block_number(), - code_hash: H256::repeat_byte(2), - rent_allowance: 40, - last_write: None, - })); - - let mut overlay = OverlayAccountDb::::new(&DirectAccountDb); - overlay.set_storage(&2, key1.clone(), Some(b"3".to_vec())); - overlay.set_storage(&2, key2.clone(), Some(b"4".to_vec())); - DirectAccountDb.commit(overlay.into_change_set()); - } - - // Transfer funds from account 1 of such amount that after this transfer - // the balance of account 1 will be below the existential threshold. - // - // This should lead to the removal of all storage associated with this account. - assert_ok!(Balances::transfer(Origin::signed(1), 2, 20)); - - // Verify that all entries from account 1 is removed, while - // entries from account 2 is in place. - { - assert!(>::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key1).is_none()); - assert!(>::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key2).is_none()); - - assert_eq!( - >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key1), - Some(b"3".to_vec()) - ); - assert_eq!( - >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key2), - Some(b"4".to_vec()) - ); - } - }); -} - -const CODE_RETURN_FROM_START_FN: &str = r#" -(module - (import "env" "ext_return" (func $ext_return (param i32 i32))) - (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (start $start) - (func $start - (call $ext_deposit_event - (i32.const 0) ;; The topics buffer - (i32.const 0) ;; The topics buffer's length - (i32.const 8) ;; The data buffer - (i32.const 4) ;; The data buffer's length - ) - (call $ext_return - (i32.const 8) - (i32.const 4) - ) - (unreachable) - ) - - (func (export "call") - (unreachable) - ) - (func (export "deploy")) - - (data (i32.const 8) "\01\02\03\04") -) -"#; - -#[test] -fn instantiate_and_call_and_deposit_event() { - let (wasm, code_hash) = compile_module::(CODE_RETURN_FROM_START_FN).unwrap(); - - ExtBuilder::default().existential_deposit(100).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Check at the end to get hash on error easily - let creation = Contract::instantiate( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - ); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Contract(BOB, vec![1, 2, 3, 4])), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - } - ]); - - assert_ok!(creation); - assert!(ContractInfoOf::::exists(BOB)); - }); -} - -const CODE_DISPATCH_CALL: &str = r#" -(module - (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_dispatch_call - (i32.const 8) ;; Pointer to the start of encoded call buffer - (i32.const 11) ;; Length of the buffer - ) - ) - (func (export "deploy")) - - (data (i32.const 8) "\00\00\03\00\00\00\00\00\00\00\C8") -) -"#; - -#[test] -fn dispatch_call() { - // This test can fail due to the encoding changes. In case it becomes too annoying - // let's rewrite so as we use this module controlled call or we serialize it in runtime. - let encoded = Encode::encode(&Call::Balances(balances::Call::transfer(CHARLIE, 50))); - assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - - let (wasm, code_hash) = compile_module::(CODE_DISPATCH_CALL).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Let's keep this assert even though it's redundant. If you ever need to update the - // wasm source this test will fail and will show you the actual hash. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - )); - - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, // newly created account - 0, - 100_000, - vec![], - )); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - }, - - // Dispatching the call. - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount(CHARLIE, 50) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::Transfer(BOB, CHARLIE, 50, 0) - ), - topics: vec![], - }, - - // Event emited as a result of dispatch. - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Dispatched(BOB, true)), - topics: vec![], - } - ]); - }); -} - -const CODE_DISPATCH_CALL_THEN_TRAP: &str = r#" -(module - (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_dispatch_call - (i32.const 8) ;; Pointer to the start of encoded call buffer - (i32.const 11) ;; Length of the buffer - ) - (unreachable) ;; trap so that the top level transaction fails - ) - (func (export "deploy")) - - (data (i32.const 8) "\00\00\03\00\00\00\00\00\00\00\C8") -) -"#; - -#[test] -fn dispatch_call_not_dispatched_after_top_level_transaction_failure() { - // This test can fail due to the encoding changes. In case it becomes too annoying - // let's rewrite so as we use this module controlled call or we serialize it in runtime. - let encoded = Encode::encode(&Call::Balances(balances::Call::transfer(CHARLIE, 50))); - assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - - let (wasm, code_hash) = compile_module::(CODE_DISPATCH_CALL_THEN_TRAP).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Let's keep this assert even though it's redundant. If you ever need to update the - // wasm source this test will fail and will show you the actual hash. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - )); - - // Call the newly instantiated contract. The contract is expected to dispatch a call - // and then trap. - assert_err!( - Contract::call( - Origin::signed(ALICE), - BOB, // newly created account - 0, - 100_000, - vec![], - ), - "during execution" - ); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - }, - // ABSENCE of events which would be caused by dispatched Balances::transfer call - ]); - }); -} - -const CODE_SET_RENT: &str = r#" -(module - (import "env" "ext_dispatch_call" (func $ext_dispatch_call (param i32 i32))) - (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) - (import "env" "ext_set_rent_allowance" (func $ext_set_rent_allowance (param i32 i32))) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; insert a value of 4 bytes into storage - (func $call_0 - (call $ext_set_storage - (i32.const 1) - (i32.const 1) - (i32.const 0) - (i32.const 4) - ) - ) - - ;; remove the value inserted by call_1 - (func $call_1 - (call $ext_set_storage - (i32.const 1) - (i32.const 0) - (i32.const 0) - (i32.const 0) - ) - ) - - ;; transfer 50 to ALICE - (func $call_2 - (call $ext_dispatch_call - (i32.const 68) - (i32.const 11) - ) - ) - - ;; do nothing - (func $call_else) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - ;; Dispatch the call according to input size - (func (export "call") - (local $input_size i32) - (set_local $input_size - (call $ext_scratch_size) - ) - (block $IF_ELSE - (block $IF_2 - (block $IF_1 - (block $IF_0 - (br_table $IF_0 $IF_1 $IF_2 $IF_ELSE - (get_local $input_size) - ) - (unreachable) - ) - (call $call_0) - return - ) - (call $call_1) - return - ) - (call $call_2) - return - ) - (call $call_else) - ) - - ;; Set into storage a 4 bytes value - ;; Set call set_rent_allowance with input - (func (export "deploy") - (local $input_size i32) - (set_local $input_size - (call $ext_scratch_size) - ) - (call $ext_set_storage - (i32.const 0) - (i32.const 1) - (i32.const 0) - (i32.const 4) - ) - (call $ext_scratch_read - (i32.const 0) - (i32.const 0) - (get_local $input_size) - ) - (call $ext_set_rent_allowance - (i32.const 0) - (get_local $input_size) - ) - ) - - ;; Encoding of 10 in balance - (data (i32.const 0) "\28") - - ;; Encoding of call transfer 50 to CHARLIE - (data (i32.const 68) "\00\00\03\00\00\00\00\00\00\00\C8") -) -"#; - -/// Input data for each call in set_rent code -mod call { - pub fn set_storage_4_byte() -> Vec { vec![] } - pub fn remove_storage_4_byte() -> Vec { vec![0] } - pub fn transfer() -> Vec { vec![0, 0] } - pub fn null() -> Vec { vec![0, 0, 0] } -} - -/// Test correspondence of set_rent code and its hash. -/// Also test that encoded extrinsic in code correspond to the correct transfer -#[test] -fn test_set_rent_code_and_hash() { - // This test can fail due to the encoding changes. In case it becomes too annoying - // let's rewrite so as we use this module controlled call or we serialize it in runtime. - let encoded = Encode::encode(&Call::Balances(balances::Call::transfer(CHARLIE, 50))); - assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]); - - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // If you ever need to update the wasm source this test will fail - // and will show you the actual hash. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - }); -} - -#[test] -fn storage_size() { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - - // Storage size - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 30_000, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); - - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::set_storage_4_byte())); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4 + 4); - - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::remove_storage_4_byte())); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); - }); -} - -#[test] -fn deduct_blocks() { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 30_000, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000); - - // Advance 4 blocks - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Check result - let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset - * 4 // rent byte price - * 4; // blocks to rent - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent); - assert_eq!(bob_contract.deduct_block, 5); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent); - - // Advance 7 blocks more - System::initialize(&12, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Check result - let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset - * 4 // rent byte price - * 7; // blocks to rent - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); - assert_eq!(bob_contract.deduct_block, 12); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); - - // Second call on same block should have no effect on rent - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); - assert_eq!(bob_contract.deduct_block, 12); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); - }); -} - -#[test] -fn call_contract_removals() { - removals(|| { - // Call on already-removed account might fail, and this is fine. - Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()); - true - }); -} - -#[test] -fn inherent_claim_surcharge_contract_removals() { - removals(|| Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok()); -} - -#[test] -fn signed_claim_surcharge_contract_removals() { - removals(|| Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok()); -} - -#[test] -fn claim_surcharge_malus() { - // Test surcharge malus for inherent - claim_surcharge(4, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(3, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(2, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(1, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), false); - - // Test surcharge malus for signed - claim_surcharge(4, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), true); - claim_surcharge(3, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); - claim_surcharge(2, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); - claim_surcharge(1, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), false); -} - -/// Claim surcharge with the given trigger_call at the given blocks. -/// if removes is true then assert that the contract is a tombstonedead -fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 100, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Advance blocks - System::initialize(&blocks, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert!(trigger_call()); - - if removes { - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - } else { - assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some()); - } - }); -} - -/// Test for all kind of removals for the given trigger: -/// * if balance is reached and balance > subsistence threshold -/// * if allowance is exceeded -/// * if balance is reached and balance < subsistence threshold -fn removals(trigger_call: impl Fn() -> bool) { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - - // Balance reached and superior to subsistence threshold - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 100, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/; - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(&BOB), 100); - - // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(&BOB), subsistence_threshold); - - // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(&BOB), subsistence_threshold); - }); - - // Allowance exceeded - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 1_000, - 100_000, code_hash.into(), - ::Balance::from(100u32).encode() // rent allowance - )); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100); - assert_eq!(Balances::free_balance(&BOB), 1_000); - - // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - // Balance should be initial balance - initial rent_allowance - assert_eq!(Balances::free_balance(&BOB), 900); - - // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(&BOB), 900); - }); - - // Balance reached and inferior to subsistence threshold - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 50+Balances::minimum_balance(), - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(&BOB), 50 + Balances::minimum_balance()); - - // Transfer funds - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::transfer())); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); - - // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).is_none()); - assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); - - // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).is_none()); - assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); - }); -} - -#[test] -fn call_removed_contract() { - let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - - // Balance reached and superior to subsistence threshold - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 100, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Calling contract should succeed. - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Calling contract should remove contract and fail. - assert_err!( - Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" - ); - - // Subsequent contract calls should also fail. - assert_err!( - Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" - ); - }) -} - -const CODE_CHECK_DEFAULT_RENT_ALLOWANCE: &str = r#" -(module - (import "env" "ext_rent_allowance" (func $ext_rent_allowance)) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call")) - - (func (export "deploy") - ;; fill the scratch buffer with the rent allowance. - (call $ext_rent_allowance) - - ;; assert $ext_scratch_size == 8 - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - - ;; copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to >::max_value(). - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 0xFFFFFFFFFFFFFFFF) - ) - ) - ) -) -"#; - -#[test] -fn default_rent_allowance_on_instantiate() { - let (wasm, code_hash) = compile_module::(CODE_CHECK_DEFAULT_RENT_ALLOWANCE).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 30_000, - 100_000, - code_hash.into(), - vec![], - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, >::max_value()); - - // Advance blocks - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Check contract is still alive - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive(); - assert!(bob_contract.is_some()) - }); -} - -const CODE_RESTORATION: &str = r#" -(module - (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) - (import "env" "ext_restore_to" (func $ext_restore_to (param i32 i32 i32 i32 i32 i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_restore_to - ;; Pointer and length of the encoded dest buffer. - (i32.const 256) - (i32.const 8) - ;; Pointer and length of the encoded code hash buffer - (i32.const 264) - (i32.const 32) - ;; Pointer and length of the encoded rent_allowance buffer - (i32.const 296) - (i32.const 8) - ;; Pointer and number of items in the delta buffer. - ;; This buffer specifies multiple keys for removal before restoration. - (i32.const 100) - (i32.const 1) - ) - ) - (func (export "deploy") - ;; Data to restore - (call $ext_set_storage - (i32.const 0) - (i32.const 1) - (i32.const 0) - (i32.const 4) - ) - - ;; ACL - (call $ext_set_storage - (i32.const 100) - (i32.const 1) - (i32.const 0) - (i32.const 4) - ) - ) - - ;; Data to restore - (data (i32.const 0) "\28") - - ;; Buffer that has ACL storage keys. - (data (i32.const 100) "\01") - - ;; Address of bob - (data (i32.const 256) "\02\00\00\00\00\00\00\00") - - ;; Code hash of SET_RENT - (data (i32.const 264) - "\14\eb\65\3c\86\98\d6\b2\3d\8d\3c\4a\54\c6\c4\71" - "\b9\fc\19\36\df\ca\a0\a1\f2\dc\ad\9d\e5\36\0b\25" - ) - - ;; Rent allowance - (data (i32.const 296) "\32\00\00\00\00\00\00\00") -) -"#; - -#[test] -fn restorations_dirty_storage_and_different_storage() { - restoration(true, true); -} - -#[test] -fn restorations_dirty_storage() { - restoration(false, true); -} - -#[test] -fn restoration_different_storage() { - restoration(true, false); -} - -#[test] -fn restoration_success() { - restoration(false, false); -} - -fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: bool) { - let (set_rent_wasm, set_rent_code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - let (restoration_wasm, restoration_code_hash) = - compile_module::(CODE_RESTORATION).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, restoration_wasm)); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, set_rent_wasm)); - - // If you ever need to update the wasm source this test will fail - // and will show you the actual hash. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(restoration_code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(set_rent_code_hash.into())), - topics: vec![], - }, - ]); - - // Create an account with address `BOB` with code `CODE_SET_RENT`. - // The input parameter sets the rent allowance to 0. - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 30_000, - 100_000, - set_rent_code_hash.into(), - ::Balance::from(0u32).encode() - )); - - // Check if `BOB` was created successfully and that the rent allowance is - // set to 0. - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 0); - - if test_different_storage { - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, 0, 100_000, - call::set_storage_4_byte()) - ); - } - - // Advance 4 blocks, to the 5th. - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0 - // we expect that it will get removed leaving tombstone. - assert_err!( - Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" - ); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - - /// Create another account with the address `DJANGO` with `CODE_RESTORATION`. - /// - /// Note that we can't use `ALICE` for creating `DJANGO` so we create yet another - /// account `CHARLIE` and create `DJANGO` with it. - Balances::deposit_creating(&CHARLIE, 1_000_000); - assert_ok!(Contract::instantiate( - Origin::signed(CHARLIE), - 30_000, - 100_000, - restoration_code_hash.into(), - ::Balance::from(0u32).encode() - )); - - // Before performing a call to `DJANGO` save its original trie id. - let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap() - .get_alive().unwrap().trie_id; - - if !test_restore_to_with_dirty_storage { - // Advance 1 block, to the 6th. - System::initialize(&6, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - } - - // Perform a call to `DJANGO`. This should either perform restoration successfully or - // fail depending on the test parameters. - assert_ok!(Contract::call( - Origin::signed(ALICE), - DJANGO, - 0, - 100_000, - vec![], - )); - - if test_different_storage || test_restore_to_with_dirty_storage { - // Parametrization of the test imply restoration failure. Check that `DJANGO` aka - // restoration contract is still in place and also that `BOB` doesn't exist. - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - let django_contract = ContractInfoOf::::get(DJANGO).unwrap() - .get_alive().unwrap(); - assert_eq!(django_contract.storage_size, 16); - assert_eq!(django_contract.trie_id, django_trie_id); - assert_eq!(django_contract.deduct_block, System::block_number()); - } else { - // Here we expect that the restoration is succeeded. Check that the restoration - // contract `DJANGO` ceased to exist and that `BOB` returned back. - println!("{:?}", ContractInfoOf::::get(BOB)); - let bob_contract = ContractInfoOf::::get(BOB).unwrap() - .get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 50); - assert_eq!(bob_contract.storage_size, 12); - assert_eq!(bob_contract.trie_id, django_trie_id); - assert_eq!(bob_contract.deduct_block, System::block_number()); - assert!(ContractInfoOf::::get(DJANGO).is_none()); - } - }); -} - -const CODE_STORAGE_SIZE: &str = r#" -(module - (import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32))) - (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 16 16)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; assert $ext_scratch_size == 8 - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 4) - ) - ) - - ;; copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_read - (i32.const 32) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 4) ;; Count of bytes to copy. - ) - - ;; place a garbage value in storage, the size of which is specified by the call input. - (call $ext_set_storage - (i32.const 0) ;; Pointer to storage key - (i32.const 1) ;; Value is not null - (i32.const 0) ;; Pointer to value - (i32.load (i32.const 32)) ;; Size of value - ) - - (call $assert - (i32.eq - (call $ext_get_storage - (i32.const 0) ;; Pointer to storage key - ) - (i32.const 0) - ) - ) - - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.load (i32.const 32)) - ) - ) - ) - - (func (export "deploy")) - - (data (i32.const 0) "\01") ;; Storage key (32 B) -) -"#; - -#[test] -fn storage_max_value_limit() { - let (wasm, code_hash) = compile_module::(CODE_STORAGE_SIZE).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 30_000, - 100_000, - code_hash.into(), - vec![], - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, >::max_value()); - - // Call contract with allowed storage value. - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, - 0, - 100_000, - Encode::encode(&self::MaxValueSize::get()), - )); - - // Call contract with too large a storage value. - assert_err!( - Contract::call( - Origin::signed(ALICE), - BOB, - 0, - 100_000, - Encode::encode(&(self::MaxValueSize::get() + 1)), - ), - "during execution" - ); - }); -} - -const CODE_RETURN_WITH_DATA: &str = r#" -(module - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "ext_scratch_write" (func $ext_scratch_write (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; Deploy routine is the same as call. - (func (export "deploy") (result i32) - (call $call) - ) - - ;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data. - (func $call (export "call") (result i32) - (local $buf_size i32) - (local $exit_status i32) - - ;; Find out the size of the scratch buffer - (set_local $buf_size (call $ext_scratch_size)) - - ;; Copy scratch buffer into this contract memory. - (call $ext_scratch_read - (i32.const 0) ;; The pointer where to store the scratch buffer contents, - (i32.const 0) ;; Offset from the start of the scratch buffer. - (get_local $buf_size) ;; Count of bytes to copy. - ) - - ;; Copy all but the first 4 bytes of the input data as the output data. - (call $ext_scratch_write - (i32.const 4) ;; Pointer to the data to return. - (i32.sub ;; Count of bytes to copy. - (get_local $buf_size) - (i32.const 4) - ) - ) - - ;; Return the first 4 bytes of the input data as the exit status. - (i32.load (i32.const 0)) - ) -) -"#; - -const CODE_CALLER_CONTRACT: &str = r#" -(module - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "ext_balance" (func $ext_balance)) - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "ext_println" (func $ext_println (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func $current_balance (param $sp i32) (result i64) - (call $ext_balance) - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 8)) - ) - (call $ext_scratch_read - (i32.sub (get_local $sp) (i32.const 8)) - (i32.const 0) - (i32.const 8) - ) - (i64.load (i32.sub (get_local $sp) (i32.const 8))) - ) - - (func (export "deploy")) - - (func (export "call") - (local $sp i32) - (local $exit_code i32) - (local $balance i64) - - ;; Input data is the code hash of the contract to be deployed. - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 32) - ) - ) - - ;; Copy code hash from scratch buffer into this contract's memory. - (call $ext_scratch_read - (i32.const 24) ;; The pointer where to store the scratch buffer contents, - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 32) ;; Count of bytes to copy. - ) - - ;; Read current balance into local variable. - (set_local $sp (i32.const 1024)) - (set_local $balance - (call $current_balance (get_local $sp)) - ) - - ;; Fail to deploy the contract since it returns a non-zero exit status. - (set_local $exit_code - (call $ext_instantiate - (i32.const 24) ;; Pointer to the code hash. - (i32.const 32) ;; Length of the code hash. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 9) ;; Pointer to input data buffer address - (i32.const 7) ;; Length of input data buffer - ) - ) - - ;; Check non-zero exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x11)) - ) - - ;; Check that scratch buffer is empty since contract instantiation failed. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 0)) - ) - - ;; Check that balance has not changed. - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Fail to deploy the contract due to insufficient gas. - (set_local $exit_code - (call $ext_instantiate - (i32.const 24) ;; Pointer to the code hash. - (i32.const 32) ;; Length of the code hash. - (i64.const 200) ;; How much gas to devote for the execution. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - ) - ) - - ;; Check for special trap exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x0100)) - ) - - ;; Check that scratch buffer is empty since contract instantiation failed. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 0)) - ) - - ;; Check that balance has not changed. - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Deploy the contract successfully. - (set_local $exit_code - (call $ext_instantiate - (i32.const 24) ;; Pointer to the code hash. - (i32.const 32) ;; Length of the code hash. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - ) - ) - - ;; Check for success exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x00)) - ) - - ;; Check that scratch buffer contains the address of the new contract. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 8)) - ) - - ;; Copy contract address from scratch buffer into this contract's memory. - (call $ext_scratch_read - (i32.const 16) ;; The pointer where to store the scratch buffer contents, - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; Check that balance has been deducted. - (set_local $balance - (i64.sub (get_local $balance) (i64.load (i32.const 0))) - ) - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Call the new contract and expect it to return failing exit code. - (set_local $exit_code - (call $ext_call - (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 9) ;; Pointer to input data buffer address - (i32.const 7) ;; Length of input data buffer - ) - ) - - ;; Check non-zero exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x11)) - ) - - ;; Check that scratch buffer contains the expected return data. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 3)) - ) - (i32.store - (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 0) - ) - (call $ext_scratch_read - (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 0) - (i32.const 3) - ) - (call $assert - (i32.eq - (i32.load (i32.sub (get_local $sp) (i32.const 4))) - (i32.const 0x00776655) - ) - ) - - ;; Check that balance has not changed. - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Fail to call the contract due to insufficient gas. - (set_local $exit_code - (call $ext_call - (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. - (i64.const 100) ;; How much gas to devote for the execution. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - ) - ) - - ;; Check for special trap exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x0100)) - ) - - ;; Check that scratch buffer is empty since call trapped. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 0)) - ) - - ;; Check that balance has not changed. - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - - ;; Call the contract successfully. - (set_local $exit_code - (call $ext_call - (i32.const 16) ;; Pointer to "callee" address. - (i32.const 8) ;; Length of "callee" address. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 8) ;; Pointer to input data buffer address - (i32.const 8) ;; Length of input data buffer - ) - ) - - ;; Check for success exit status. - (call $assert - (i32.eq (get_local $exit_code) (i32.const 0x00)) - ) - - ;; Check that scratch buffer contains the expected return data. - (call $assert - (i32.eq (call $ext_scratch_size) (i32.const 4)) - ) - (i32.store - (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 0) - ) - (call $ext_scratch_read - (i32.sub (get_local $sp) (i32.const 4)) - (i32.const 0) - (i32.const 4) - ) - (call $assert - (i32.eq - (i32.load (i32.sub (get_local $sp) (i32.const 4))) - (i32.const 0x77665544) - ) - ) - - ;; Check that balance has been deducted. - (set_local $balance - (i64.sub (get_local $balance) (i64.load (i32.const 0))) - ) - (call $assert - (i64.eq (get_local $balance) (call $current_balance (get_local $sp))) - ) - ) - - (data (i32.const 0) "\00\80") ;; The value to transfer on instantiation and calls. - ;; Chosen to be greater than existential deposit. - (data (i32.const 8) "\00\11\22\33\44\55\66\77") ;; The input data to instantiations and calls. -) -"#; - -#[test] -fn deploy_and_call_other_contract() { - let (callee_wasm, callee_code_hash) = compile_module::(CODE_RETURN_WITH_DATA).unwrap(); - let (caller_wasm, caller_code_hash) = compile_module::(CODE_CALLER_CONTRACT).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, caller_wasm)); - - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 100_000, - 100_000, - caller_code_hash.into(), - vec![], - )); - - // Call BOB contract, which attempts to instantiate and call the callee contract and - // makes various assertions on the results from those calls. - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, - 0, - 200_000, - callee_code_hash.as_ref().to_vec(), - )); - }); -} - -const CODE_SELF_DESTRUCT: &str = r#" -(module - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "ext_address" (func $ext_address)) - (import "env" "ext_balance" (func $ext_balance)) - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - ;; If the input data is not empty, then recursively call self with empty input data. - ;; This should trap instead of self-destructing since a contract cannot be removed live in - ;; the execution stack cannot be removed. If the recursive call traps, then trap here as - ;; well. - (if (call $ext_scratch_size) - (then - (call $ext_address) - - ;; Expect address to be 8 bytes. - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - - ;; Read own address into memory. - (call $ext_scratch_read - (i32.const 16) ;; Pointer to write address to - (i32.const 0) ;; Offset into scrach buffer - (i32.const 8) ;; Length of encoded address - ) - - ;; Recursively call self with empty imput data. - (call $assert - (i32.eq - (call $ext_call - (i32.const 16) ;; Pointer to own address - (i32.const 8) ;; Length of own address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 8) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - ) - (i32.const 0) - ) - ) - ) - ) - - ;; Send entire remaining balance to the 0 address. - (call $ext_balance) - - ;; Balance should be encoded as a u64. - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - - ;; Read balance into memory. - (call $ext_scratch_read - (i32.const 8) ;; Pointer to write balance to - (i32.const 0) ;; Offset into scrach buffer - (i32.const 8) ;; Length of encoded balance - ) - - ;; Self-destruct by sending full balance to the 0 address. - (call $assert - (i32.eq - (call $ext_call - (i32.const 0) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 8) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - ) - (i32.const 0) - ) - ) - ) -) -"#; - -#[test] -fn self_destruct_by_draining_balance() { - let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Instantiate the BOB contract. - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 100_000, - 100_000, - code_hash.into(), - vec![], - )); - - // Check that the BOB contract has been instantiated. - assert_matches!( - ContractInfoOf::::get(BOB), - Some(ContractInfo::Alive(_)) - ); - - // Call BOB with no input data, forcing it to self-destruct. - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, - 0, - 100_000, - vec![], - )); - - // Check that BOB is now dead. - assert!(ContractInfoOf::::get(BOB).is_none()); - }); -} - -#[test] -fn cannot_self_destruct_while_live() { - let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Instantiate the BOB contract. - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 100_000, - 100_000, - code_hash.into(), - vec![], - )); - - // Check that the BOB contract has been instantiated. - assert_matches!( - ContractInfoOf::::get(BOB), - Some(ContractInfo::Alive(_)) - ); - - // Call BOB with input data, forcing it make a recursive call to itself to - // self-destruct, resulting in a trap. - assert_err!( - Contract::call( - Origin::signed(ALICE), - BOB, - 0, - 100_000, - vec![0], - ), - "during execution" - ); - - // Check that BOB is still alive. - assert_matches!( - ContractInfoOf::::get(BOB), - Some(ContractInfo::Alive(_)) - ); - }); -} - -const CODE_DESTROY_AND_TRANSFER: &str = r#" -(module - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32))) - (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "deploy") - ;; Input data is the code hash of the contract to be deployed. - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 32) - ) - ) - - ;; Copy code hash from scratch buffer into this contract's memory. - (call $ext_scratch_read - (i32.const 48) ;; The pointer where to store the scratch buffer contents, - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 32) ;; Count of bytes to copy. - ) - - ;; Deploy the contract with the provided code hash. - (call $assert - (i32.eq - (call $ext_instantiate - (i32.const 48) ;; Pointer to the code hash. - (i32.const 32) ;; Length of the code hash. - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer. - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - ) - (i32.const 0) - ) - ) - - ;; Read the address of the instantiated contract into memory. - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - (call $ext_scratch_read - (i32.const 80) ;; The pointer where to store the scratch buffer contents, - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; Store the return address. - (call $ext_set_storage - (i32.const 16) ;; Pointer to the key - (i32.const 1) ;; Value is not null - (i32.const 80) ;; Pointer to the value - (i32.const 8) ;; Length of the value - ) - ) - - (func (export "call") - ;; Read address of destination contract from storage. - (call $assert - (i32.eq - (call $ext_get_storage - (i32.const 16) ;; Pointer to the key - ) - (i32.const 0) - ) - ) - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - (call $ext_scratch_read - (i32.const 80) ;; The pointer where to store the contract address. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; Calling the destination contract with non-empty input data should fail. - (call $assert - (i32.eq - (call $ext_call - (i32.const 80) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 1) ;; Length of input data buffer - ) - (i32.const 0x0100) - ) - ) - - ;; Call the destination contract regularly, forcing it to self-destruct. - (call $assert - (i32.eq - (call $ext_call - (i32.const 80) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 8) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - ) - (i32.const 0) - ) - ) - - ;; Calling the destination address with non-empty input data should now work since the - ;; contract has been removed. Also transfer a balance to the address so we can ensure this - ;; does not keep the contract alive. - (call $assert - (i32.eq - (call $ext_call - (i32.const 80) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 0) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 1) ;; Length of input data buffer - ) - (i32.const 0) - ) - ) - ) - - (data (i32.const 0) "\00\00\01") ;; Endowment to send when creating contract. - (data (i32.const 8) "") ;; Value to send when calling contract. - (data (i32.const 16) "") ;; The key to store the contract address under. -) -"#; - -// This tests that one contract cannot prevent another from self-destructing by sending it -// additional funds after it has been drained. -#[test] -fn destroy_contract_and_transfer_funds() { - let (callee_wasm, callee_code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); - let (caller_wasm, caller_code_hash) = compile_module::(CODE_DESTROY_AND_TRANSFER).unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, caller_wasm)); - - // This deploys the BOB contract, which in turn deploys the CHARLIE contract during - // construction. - assert_ok!(Contract::instantiate( - Origin::signed(ALICE), - 200_000, - 100_000, - caller_code_hash.into(), - callee_code_hash.as_ref().to_vec(), - )); - - // Check that the CHARLIE contract has been instantiated. - assert_matches!( - ContractInfoOf::::get(CHARLIE), - Some(ContractInfo::Alive(_)) - ); - - // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, - 0, - 100_000, - CHARLIE.encode(), - )); - - // Check that CHARLIE has moved on to the great beyond (ie. died). - assert!(ContractInfoOf::::get(CHARLIE).is_none()); - }); -} - -const CODE_SELF_DESTRUCTING_CONSTRUCTOR: &str = r#" -(module - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "ext_balance" (func $ext_balance)) - (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "deploy") - ;; Send entire remaining balance to the 0 address. - (call $ext_balance) - - ;; Balance should be encoded as a u64. - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - - ;; Read balance into memory. - (call $ext_scratch_read - (i32.const 8) ;; Pointer to write balance to - (i32.const 0) ;; Offset into scrach buffer - (i32.const 8) ;; Length of encoded balance - ) - - ;; Self-destruct by sending full balance to the 0 address. - (call $assert - (i32.eq - (call $ext_call - (i32.const 0) ;; Pointer to destination address - (i32.const 8) ;; Length of destination address - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (i32.const 8) ;; Pointer to the buffer with value to transfer - (i32.const 8) ;; Length of the buffer with value to transfer - (i32.const 0) ;; Pointer to input data buffer address - (i32.const 0) ;; Length of input data buffer - ) - (i32.const 0) - ) - ) - ) - - (func (export "call")) -) -"#; - -#[test] -fn cannot_self_destruct_in_constructor() { - let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCTING_CONSTRUCTOR).unwrap(); - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Fail to instantiate the BOB contract since its final balance is below existential - // deposit. - assert_err!( - Contract::instantiate( - Origin::signed(ALICE), - 100_000, - 100_000, - code_hash.into(), - vec![], - ), - "insufficient remaining balance" - ); - }); -} - -#[test] -fn check_block_gas_limit_works() { - ExtBuilder::default().block_gas_limit(50).build().execute_with(|| { - let info = DispatchInfo { weight: 100, class: DispatchClass::Normal }; - let check = CheckBlockGasLimit::(Default::default()); - let call: Call = crate::Call::put_code(1000, vec![]).into(); - - assert_eq!( - check.validate(&0, &call, info, 0), InvalidTransaction::ExhaustsResources.into(), - ); - - let call: Call = crate::Call::update_schedule(Default::default()).into(); - assert_eq!(check.validate(&0, &call, info, 0), Ok(Default::default())); - }); -} diff --git a/srml/contracts/src/wasm/env_def/mod.rs b/srml/contracts/src/wasm/env_def/mod.rs deleted file mode 100644 index d51a157910d5c..0000000000000 --- a/srml/contracts/src/wasm/env_def/mod.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use super::Runtime; -use crate::exec::Ext; - -use sandbox::{self, TypedValue}; -use parity_wasm::elements::{FunctionType, ValueType}; - -#[macro_use] -pub(crate) mod macros; - -pub trait ConvertibleToWasm: Sized { - const VALUE_TYPE: ValueType; - type NativeType; - fn to_typed_value(self) -> TypedValue; - fn from_typed_value(_: TypedValue) -> Option; -} -impl ConvertibleToWasm for i32 { - type NativeType = i32; - const VALUE_TYPE: ValueType = ValueType::I32; - fn to_typed_value(self) -> TypedValue { - TypedValue::I32(self) - } - fn from_typed_value(v: TypedValue) -> Option { - v.as_i32() - } -} -impl ConvertibleToWasm for u32 { - type NativeType = u32; - const VALUE_TYPE: ValueType = ValueType::I32; - fn to_typed_value(self) -> TypedValue { - TypedValue::I32(self as i32) - } - fn from_typed_value(v: TypedValue) -> Option { - match v { - TypedValue::I32(v) => Some(v as u32), - _ => None, - } - } -} -impl ConvertibleToWasm for u64 { - type NativeType = u64; - const VALUE_TYPE: ValueType = ValueType::I64; - fn to_typed_value(self) -> TypedValue { - TypedValue::I64(self as i64) - } - fn from_typed_value(v: TypedValue) -> Option { - match v { - TypedValue::I64(v) => Some(v as u64), - _ => None, - } - } -} - -pub(crate) type HostFunc = - fn( - &mut Runtime, - &[sandbox::TypedValue] - ) -> Result; - -pub(crate) trait FunctionImplProvider { - fn impls)>(f: &mut F); -} - -/// 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/contracts/src/wasm/mod.rs b/srml/contracts/src/wasm/mod.rs deleted file mode 100644 index 4fa9412bc1769..0000000000000 --- a/srml/contracts/src/wasm/mod.rs +++ /dev/null @@ -1,1637 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! 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, ExecResult}; -use crate::gas::GasMeter; - -use rstd::prelude::*; -use 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> { - schedule: &'a Schedule, -} - -impl<'a> WasmLoader<'a> { - pub fn new(schedule: &'a Schedule) -> Self { - WasmLoader { schedule } - } -} - -impl<'a, T: Trait> crate::exec::Loader for WasmLoader<'a> { - 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> { - schedule: &'a Schedule, -} - -impl<'a> WasmVm<'a> { - pub fn new(schedule: &'a Schedule) -> Self { - WasmVm { schedule } - } -} - -impl<'a, T: Trait> crate::exec::Vm for WasmVm<'a> { - type Executable = WasmExecutable; - - fn execute>( - &self, - exec: &WasmExecutable, - mut ext: E, - input_data: Vec, - gas_meter: &mut GasMeter, - ) -> ExecResult { - 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( - &mut ext, - input_data, - &self.schedule, - memory, - gas_meter, - ); - - // Instantiate the instance from the instrumented module code and invoke the contract - // entrypoint. - let result = sandbox::Instance::new(&exec.prefab_module.code, &imports, &mut runtime) - .and_then(|mut instance| instance.invoke(exec.entrypoint_name, &[], &mut runtime)); - to_execution_result(runtime, result) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::collections::HashMap; - use primitives::H256; - use crate::exec::{Ext, StorageKey, ExecError, ExecReturnValue, STATUS_SUCCESS}; - use crate::gas::{Gas, GasMeter}; - use crate::tests::{Test, Call}; - use crate::wasm::prepare::prepare_contract; - use crate::CodeHash; - use wabt; - use hex_literal::hex; - use assert_matches::assert_matches; - - #[derive(Debug, PartialEq, Eq)] - struct DispatchEntry(Call); - - #[derive(Debug, PartialEq, Eq)] - struct RestoreEntry { - dest: u64, - code_hash: H256, - rent_allowance: u64, - delta: Vec, - } - - #[derive(Debug, PartialEq, Eq)] - struct InstantiateEntry { - 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>, - rent_allowance: u64, - instantiates: Vec, - transfers: Vec, - dispatches: Vec, - restores: Vec, - // (topics, data) - events: Vec<(Vec, Vec)>, - next_account_id: u64, - } - - impl Ext for MockExt { - type T = Test; - - fn get_storage(&self, key: &StorageKey) -> Option> { - self.storage.get(key).cloned() - } - fn set_storage(&mut self, key: StorageKey, value: Option>) - -> Result<(), &'static str> - { - *self.storage.entry(key).or_insert(Vec::new()) = value.unwrap_or(Vec::new()); - Ok(()) - } - fn instantiate( - &mut self, - code_hash: &CodeHash, - endowment: u64, - gas_meter: &mut GasMeter, - data: Vec, - ) -> Result<(u64, ExecReturnValue), ExecError> { - self.instantiates.push(InstantiateEntry { - 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((address, ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() })) - } - fn call( - &mut self, - to: &u64, - value: u64, - gas_meter: &mut GasMeter, - data: Vec, - ) -> ExecResult { - 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(ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() }) - } - fn note_dispatch_call(&mut self, call: Call) { - self.dispatches.push(DispatchEntry(call)); - } - fn note_restore_to( - &mut self, - dest: u64, - code_hash: H256, - rent_allowance: u64, - delta: Vec, - ) { - self.restores.push(RestoreEntry { - dest, - code_hash, - rent_allowance, - delta, - }); - } - 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 minimum_balance(&self) -> u64 { - 666 - } - - fn random(&self, subject: &[u8]) -> H256 { - H256::from_slice(subject) - } - - fn deposit_event(&mut self, topics: Vec, data: Vec) { - self.events.push((topics, data)) - } - - fn set_rent_allowance(&mut self, rent_allowance: u64) { - self.rent_allowance = rent_allowance; - } - - fn rent_allowance(&self) -> u64 { - self.rent_allowance - } - - fn block_number(&self) -> u64 { 121 } - - fn max_value_size(&self) -> u32 { 16_384 } - } - - impl Ext for &mut MockExt { - type T = ::T; - - fn get_storage(&self, key: &[u8; 32]) -> Option> { - (**self).get_storage(key) - } - fn set_storage(&mut self, key: [u8; 32], value: Option>) - -> Result<(), &'static str> - { - (**self).set_storage(key, value) - } - fn instantiate( - &mut self, - code: &CodeHash, - value: u64, - gas_meter: &mut GasMeter, - input_data: Vec, - ) -> Result<(u64, ExecReturnValue), ExecError> { - (**self).instantiate(code, value, gas_meter, input_data) - } - fn call( - &mut self, - to: &u64, - value: u64, - gas_meter: &mut GasMeter, - input_data: Vec, - ) -> ExecResult { - (**self).call(to, value, gas_meter, input_data) - } - fn note_dispatch_call(&mut self, call: Call) { - (**self).note_dispatch_call(call) - } - fn note_restore_to( - &mut self, - dest: u64, - code_hash: H256, - rent_allowance: u64, - delta: Vec, - ) { - (**self).note_restore_to( - dest, - code_hash, - rent_allowance, - delta, - ) - } - fn caller(&self) -> &u64 { - (**self).caller() - } - fn address(&self) -> &u64 { - (**self).address() - } - fn balance(&self) -> u64 { - (**self).balance() - } - fn value_transferred(&self) -> u64 { - (**self).value_transferred() - } - fn now(&self) -> &u64 { - (**self).now() - } - fn minimum_balance(&self) -> u64 { - (**self).minimum_balance() - } - fn random(&self, subject: &[u8]) -> H256 { - (**self).random(subject) - } - fn deposit_event(&mut self, topics: Vec, data: Vec) { - (**self).deposit_event(topics, data) - } - fn set_rent_allowance(&mut self, rent_allowance: u64) { - (**self).set_rent_allowance(rent_allowance) - } - fn rent_allowance(&self) -> u64 { - (**self).rent_allowance() - } - fn block_number(&self) -> u64 { - (**self).block_number() - } - fn max_value_size(&self) -> u32 { - (**self).max_value_size() - } - } - - fn execute( - wat: &str, - input_data: Vec, - ext: E, - gas_meter: &mut GasMeter, - ) -> ExecResult { - 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); - - vm.execute(&exec, ext, input_data, gas_meter) - } - - 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(); - let _ = execute( - CODE_TRANSFER, - vec![], - &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: 49971, - }] - ); - } - - const CODE_INSTANTIATE: &str = r#" -(module - ;; ext_instantiate( - ;; 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_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory 1 1)) - (func (export "call") - (drop - (call $ext_instantiate - (i32.const 16) ;; Pointer to `code_hash` - (i32.const 32) ;; Length of `code_hash` - (i64.const 0) ;; How much gas to devote for the execution. 0 = all. - (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 instantiated. - (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_instantiate() { - let mut mock_ext = MockExt::default(); - let _ = execute( - CODE_INSTANTIATE, - vec![], - &mut mock_ext, - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!( - &mock_ext.instantiates, - &[InstantiateEntry { - code_hash: [0x11; 32].into(), - endowment: 3, - data: vec![1, 2, 3, 4], - gas_left: 49947, - }] - ); - } - - 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(); - let _ = execute( - &CODE_TRANSFER_LIMITED_GAS, - vec![], - &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_read" (func $ext_scratch_read (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_read - (i32.const 36) ;; The pointer where to store the scratch buffer contents, - ;; 36 = 4 + 32 - (i32.const 0) ;; Offset from the start of the scratch buffer. - (get_local ;; Count of bytes to copy. - $buf_size - ) - ) - - ;; 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], [0x22; 32].to_vec()); - - let output = execute( - CODE_GET_STORAGE, - vec![], - mock_ext, - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: [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_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; 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_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 42. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 42) - ) - ) - ) - - (func (export "deploy")) -) -"#; - - #[test] - fn caller() { - let _ = execute( - CODE_CALLER, - vec![], - MockExt::default(), - &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_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; 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_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 69. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 69) - ) - ) - ) - - (func (export "deploy")) -) -"#; - - #[test] - fn address() { - let _ = execute( - CODE_ADDRESS, - vec![], - MockExt::default(), - &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_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; 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_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 228. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 228) - ) - ) - ) - (func (export "deploy")) -) -"#; - - #[test] - fn balance() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); - let _ = execute( - CODE_BALANCE, - vec![], - MockExt::default(), - &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_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; 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_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 1312. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 1312) - ) - ) - ) - (func (export "deploy")) -) -"#; - - #[test] - fn gas_price() { - let mut gas_meter = GasMeter::with_limit(50_000, 1312); - let _ = execute( - CODE_GAS_PRICE, - vec![], - MockExt::default(), - &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_read" (func $ext_scratch_read (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_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - (call $ext_return - (i32.const 8) - (i32.const 8) - ) - - (unreachable) - ) - (func (export "deploy")) -) -"#; - - #[test] - fn gas_left() { - let mut gas_meter = GasMeter::with_limit(50_000, 1312); - - let output = execute( - CODE_GAS_LEFT, - vec![], - MockExt::default(), - &mut gas_meter, - ).unwrap(); - - let gas_left = Gas::decode(&mut output.data.as_slice()).unwrap(); - assert!(gas_left < 50_000, "gas_left must be less than initial"); - assert!(gas_left > gas_meter.gas_left(), "gas_left must be greater than final"); - } - - const CODE_VALUE_TRANSFERRED: &str = r#" -(module - (import "env" "ext_value_transferred" (func $ext_value_transferred)) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "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_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 1337. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 1337) - ) - ) - ) - (func (export "deploy")) -) -"#; - - #[test] - fn value_transferred() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); - let _ = execute( - CODE_VALUE_TRANSFERRED, - vec![], - MockExt::default(), - &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(); - let _ = execute( - CODE_DISPATCH_CALL, - vec![], - &mut mock_ext, - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!( - &mock_ext.dispatches, - &[DispatchEntry( - Call::Balances(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 output = execute( - CODE_RETURN_FROM_START_FN, - vec![], - MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!(output, ExecReturnValue { status: STATUS_SUCCESS, data: vec![1, 2, 3, 4] }); - } - - const CODE_TIMESTAMP_NOW: &str = r#" -(module - (import "env" "ext_now" (func $ext_now)) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "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_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 1111. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 1111) - ) - ) - ) - (func (export "deploy")) -) -"#; - - #[test] - fn now() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); - let _ = execute( - CODE_TIMESTAMP_NOW, - vec![], - MockExt::default(), - &mut gas_meter, - ).unwrap(); - } - - const CODE_MINIMUM_BALANCE: &str = r#" -(module - (import "env" "ext_minimum_balance" (func $ext_minimum_balance)) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - (call $ext_minimum_balance) - - ;; assert $ext_scratch_size == 8 - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - - ;; copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 666. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 666) - ) - ) - ) - (func (export "deploy")) -) -"#; - - #[test] - fn minimum_balance() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); - let _ = execute( - CODE_MINIMUM_BALANCE, - vec![], - MockExt::default(), - &mut gas_meter, - ).unwrap(); - } - - const CODE_RANDOM: &str = r#" -(module - (import "env" "ext_random" (func $ext_random (param i32 i32))) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "ext_return" (func $ext_return (param i32 i32))) - (import "env" "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 - (i32.const 40) ;; Pointer in memory to the start of the subject buffer - (i32.const 32) ;; The subject buffer's length - ) - - ;; 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_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 32) ;; Count of bytes to copy. - ) - - ;; return the data from the contract - (call $ext_return - (i32.const 8) - (i32.const 32) - ) - ) - (func (export "deploy")) - - ;; [8,40) is reserved for the result of PRNG. - - ;; the subject used for the PRNG. [40,72) - (data (i32.const 40) - "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F" - "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F" - ) -) -"#; - - #[test] - fn random() { - let mut gas_meter = GasMeter::with_limit(50_000, 1); - - let output = execute( - CODE_RANDOM, - vec![], - MockExt::default(), - &mut gas_meter, - ).unwrap(); - - // The mock ext just returns the same data that was passed as the subject. - assert_eq!( - output, - ExecReturnValue { - status: STATUS_SUCCESS, - data: hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F").to_vec(), - }, - ); - } - - const CODE_DEPOSIT_EVENT: &str = r#" -(module - (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_deposit_event - (i32.const 32) ;; Pointer to the start of topics buffer - (i32.const 33) ;; The length of the topics buffer. - (i32.const 8) ;; Pointer to the start of the data 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") - - ;; Encoded Vec>, the buffer has length of 33 bytes. - (data (i32.const 32) "\04\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33\33" - "\33\33\33\33\33\33\33\33\33") -) -"#; - - #[test] - fn deposit_event() { - let mut mock_ext = MockExt::default(); - let mut gas_meter = GasMeter::with_limit(50_000, 1); - let _ = execute( - CODE_DEPOSIT_EVENT, - vec![], - &mut mock_ext, - &mut gas_meter - ).unwrap(); - - assert_eq!(mock_ext.events, vec![ - (vec![H256::repeat_byte(0x33)], - vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]) - ]); - - assert_eq!(gas_meter.gas_left(), 49934); - } - - const CODE_DEPOSIT_EVENT_MAX_TOPICS: &str = r#" -(module - (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_deposit_event - (i32.const 32) ;; Pointer to the start of topics buffer - (i32.const 161) ;; The length of the topics buffer. - (i32.const 8) ;; Pointer to the start of the data 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") - - ;; Encoded Vec>, the buffer has length of 161 bytes. - (data (i32.const 32) "\14" -"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" -"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02" -"\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03" -"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04" -"\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05") -) -"#; - - #[test] - fn deposit_event_max_topics() { - // Checks that the runtime traps if there are more than `max_topic_events` topics. - let mut gas_meter = GasMeter::with_limit(50_000, 1); - - assert_matches!( - execute( - CODE_DEPOSIT_EVENT_MAX_TOPICS, - vec![], - MockExt::default(), - &mut gas_meter - ), - Err(ExecError { reason: "during execution", buffer: _ }) - ); - } - - const CODE_DEPOSIT_EVENT_DUPLICATES: &str = r#" -(module - (import "env" "ext_deposit_event" (func $ext_deposit_event (param i32 i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func (export "call") - (call $ext_deposit_event - (i32.const 32) ;; Pointer to the start of topics buffer - (i32.const 129) ;; The length of the topics buffer. - (i32.const 8) ;; Pointer to the start of the data 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") - - ;; Encoded Vec>, the buffer has length of 129 bytes. - (data (i32.const 32) "\10" -"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" -"\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02" -"\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01" -"\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04") -) -"#; - - #[test] - fn deposit_event_duplicates() { - // Checks that the runtime traps if there are duplicates. - let mut gas_meter = GasMeter::with_limit(50_000, 1); - - assert_matches!( - execute( - CODE_DEPOSIT_EVENT_DUPLICATES, - vec![], - MockExt::default(), - &mut gas_meter - ), - Err(ExecError { reason: "during execution", buffer: _ }) - ); - } - - /// calls `ext_block_number`, loads the current block number from the scratch buffer and - /// compares it with the constant 121. - const CODE_BLOCK_NUMBER: &str = r#" -(module - (import "env" "ext_block_number" (func $ext_block_number)) - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "memory" (memory 1 1)) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "call") - ;; This stores the block height in the scratch buffer - (call $ext_block_number) - - ;; assert $ext_scratch_size == 8 - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 8) - ) - ) - - ;; copy contents of the scratch buffer into the contract's memory. - (call $ext_scratch_read - (i32.const 8) ;; Pointer in memory to the place where to copy. - (i32.const 0) ;; Offset from the start of the scratch buffer. - (i32.const 8) ;; Count of bytes to copy. - ) - - ;; assert that contents of the buffer is equal to the i64 value of 121. - (call $assert - (i64.eq - (i64.load - (i32.const 8) - ) - (i64.const 121) - ) - ) - ) - - (func (export "deploy")) -) -"#; - - #[test] - fn block_number() { - let _ = execute( - CODE_BLOCK_NUMBER, - vec![], - MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - } - - // asserts that the size of the input data is 4. - const CODE_SIMPLE_ASSERT: &str = r#" -(module - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - - (func $assert (param i32) - (block $ok - (br_if $ok - (get_local 0) - ) - (unreachable) - ) - ) - - (func (export "deploy")) - - (func (export "call") - (call $assert - (i32.eq - (call $ext_scratch_size) - (i32.const 4) - ) - ) - ) -) -"#; - - #[test] - fn output_buffer_capacity_preserved_on_success() { - let mut input_data = Vec::with_capacity(1_234); - input_data.extend_from_slice(&[1, 2, 3, 4][..]); - - let output = execute( - CODE_SIMPLE_ASSERT, - input_data, - MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!(output.data.len(), 0); - assert_eq!(output.data.capacity(), 1_234); - } - - #[test] - fn output_buffer_capacity_preserved_on_failure() { - let mut input_data = Vec::with_capacity(1_234); - input_data.extend_from_slice(&[1, 2, 3, 4, 5][..]); - - let error = execute( - CODE_SIMPLE_ASSERT, - input_data, - MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), - ).err().unwrap(); - - assert_eq!(error.buffer.capacity(), 1_234); - } - - const CODE_RETURN_WITH_DATA: &str = r#" -(module - (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) - (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) - (import "env" "ext_scratch_write" (func $ext_scratch_write (param i32 i32))) - (import "env" "memory" (memory 1 1)) - - ;; Deploy routine is the same as call. - (func (export "deploy") (result i32) - (call $call) - ) - - ;; Call reads the first 4 bytes (LE) as the exit status and returns the rest as output data. - (func $call (export "call") (result i32) - (local $buf_size i32) - (local $exit_status i32) - - ;; Find out the size of the scratch buffer - (set_local $buf_size (call $ext_scratch_size)) - - ;; Copy scratch buffer into this contract memory. - (call $ext_scratch_read - (i32.const 0) ;; The pointer where to store the scratch buffer contents, - (i32.const 0) ;; Offset from the start of the scratch buffer. - (get_local $buf_size) ;; Count of bytes to copy. - ) - - ;; Copy all but the first 4 bytes of the input data as the output data. - (call $ext_scratch_write - (i32.const 4) ;; Offset from the start of the scratch buffer. - (i32.sub ;; Count of bytes to copy. - (get_local $buf_size) - (i32.const 4) - ) - ) - - ;; Return the first 4 bytes of the input data as the exit status. - (i32.load (i32.const 0)) - ) -) -"#; - - #[test] - fn return_with_success_status() { - let output = execute( - CODE_RETURN_WITH_DATA, - hex!("00112233445566778899").to_vec(), - MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!(output, ExecReturnValue { status: 0, data: hex!("445566778899").to_vec() }); - assert!(output.is_success()); - } - - #[test] - fn return_with_failure_status() { - let output = execute( - CODE_RETURN_WITH_DATA, - hex!("112233445566778899").to_vec(), - MockExt::default(), - &mut GasMeter::with_limit(50_000, 1), - ).unwrap(); - - assert_eq!(output, ExecReturnValue { status: 17, data: hex!("5566778899").to_vec() }); - assert!(!output.is_success()); - } -} diff --git a/srml/contracts/src/wasm/runtime.rs b/srml/contracts/src/wasm/runtime.rs deleted file mode 100644 index 28117eaa7c690..0000000000000 --- a/srml/contracts/src/wasm/runtime.rs +++ /dev/null @@ -1,856 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Environment definition of the wasm smart-contract runtime. - -use crate::{Schedule, Trait, CodeHash, ComputeDispatchFee, BalanceOf}; -use crate::exec::{ - Ext, ExecResult, ExecError, ExecReturnValue, StorageKey, TopicOf, STATUS_SUCCESS, -}; -use crate::gas::{Gas, GasMeter, Token, GasMeterResult, approx_gas_for_balance}; -use sandbox; -use system; -use rstd::prelude::*; -use rstd::convert::TryInto; -use rstd::mem; -use codec::{Decode, Encode}; -use sr_primitives::traits::{Bounded, SaturatedConversion}; - -/// The value returned from ext_call and ext_instantiate contract external functions if the call or -/// instantiation traps. This value is chosen as if the execution does not trap, the return value -/// will always be an 8-bit integer, so 0x0100 is the smallest value that could not be returned. -const TRAP_RETURN_CODE: u32 = 0x0100; - -/// Enumerates all possible *special* trap conditions. -/// -/// In this runtime traps used not only for signaling about errors but also -/// to just terminate quickly in some cases. -enum SpecialTrap { - /// Signals that trap was generated in response to call `ext_return` host function. - Return(Vec), -} - -/// Can only be used for one call. -pub(crate) struct Runtime<'a, E: Ext + 'a> { - ext: &'a mut E, - scratch_buf: Vec, - schedule: &'a Schedule, - memory: sandbox::Memory, - gas_meter: &'a mut GasMeter, - special_trap: Option, -} -impl<'a, E: Ext + 'a> Runtime<'a, E> { - pub(crate) fn new( - ext: &'a mut E, - input_data: Vec, - schedule: &'a Schedule, - memory: sandbox::Memory, - gas_meter: &'a mut GasMeter, - ) -> Self { - Runtime { - ext, - // Put the input data into the scratch buffer immediately. - scratch_buf: input_data, - schedule, - memory, - gas_meter, - special_trap: None, - } - } -} - -pub(crate) fn to_execution_result( - runtime: Runtime, - sandbox_result: Result, -) -> ExecResult { - // Special case. The trap was the result of the execution `return` host function. - if let Some(SpecialTrap::Return(data)) = runtime.special_trap { - return Ok(ExecReturnValue { status: STATUS_SUCCESS, data }); - } - - // Check the exact type of the error. - match sandbox_result { - // No traps were generated. Proceed normally. - Ok(sandbox::ReturnValue::Unit) => { - let mut buffer = runtime.scratch_buf; - buffer.clear(); - Ok(ExecReturnValue { status: STATUS_SUCCESS, data: buffer }) - } - Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(exit_code))) => { - let status = (exit_code & 0xFF).try_into() - .expect("exit_code is masked into the range of a u8; qed"); - Ok(ExecReturnValue { status, data: runtime.scratch_buf }) - } - // This should never happen as the return type of exported functions should have been - // validated by the code preparation process. However, because panics are really - // undesirable in the runtime code, we treat this as a trap for now. Eventually, we might - // want to revisit this. - Ok(_) => Err(ExecError { reason: "return type error", buffer: runtime.scratch_buf }), - // `Error::Module` is returned only if instantiation or linking failed (i.e. - // wasm binary tried to import a function that is not provided by the host). - // This shouldn't happen because validation process ought to reject such binaries. - // - // Because panics are really undesirable in the runtime code, we treat this as - // a trap for now. Eventually, we might want to revisit this. - Err(sandbox::Error::Module) => - Err(ExecError { reason: "validation error", buffer: runtime.scratch_buf }), - // Any other kind of a trap should result in a failure. - Err(sandbox::Error::Execution) | Err(sandbox::Error::OutOfBounds) => - Err(ExecError { reason: "during execution", buffer: runtime.scratch_buf }), - } -} - -#[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), - /// (topic_count, data_bytes): A buffer of the given size is posted as an event indexed with the - /// given number of topics. - DepositEvent(u32, u32), -} - -impl Token for RuntimeToken { - type Metadata = Schedule; - - fn calculate_amount(&self, metadata: &Schedule) -> Gas { - use self::RuntimeToken::*; - let value = match *self { - Explicit(amount) => Some(amount.into()), - ReadMemory(byte_count) => metadata - .sandbox_data_read_cost - .checked_mul(byte_count.into()), - WriteMemory(byte_count) => metadata - .sandbox_data_write_cost - .checked_mul(byte_count.into()), - ReturnData(byte_count) => metadata - .return_data_per_byte_cost - .checked_mul(byte_count.into()), - DepositEvent(topic_count, data_byte_count) => { - let data_cost = metadata - .event_data_per_byte_cost - .checked_mul(data_byte_count.into()); - - let topics_cost = metadata - .event_per_topic_cost - .checked_mul(topic_count.into()); - - data_cost - .and_then(|data_cost| { - topics_cost.and_then(|topics_cost| { - data_cost.checked_add(topics_cost) - }) - }) - .and_then(|data_and_topics_cost| - data_and_topics_cost.checked_add(metadata.event_base_cost) - ) - }, - ComputedDispatchFee(gas) => Some(gas), - }; - - value.unwrap_or_else(|| Bounded::max_value()) - } -} - -/// Charge the gas meter with the specified token. -/// -/// Returns `Err(HostError)` if there is not enough gas. -fn charge_gas>( - gas_meter: &mut GasMeter, - metadata: &Tok::Metadata, - token: Tok, -) -> Result<(), sandbox::HostError> { - match gas_meter.charge(metadata, token) { - GasMeterResult::Proceed => Ok(()), - GasMeterResult::OutOfGas => Err(sandbox::HostError), - } -} - -/// Read designated chunk from the sandbox memory, consuming an appropriate amount of -/// gas. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - calculating the gas cost resulted in overflow. -/// - out of gas -/// - requested buffer is not within the bounds of the sandbox memory. -fn read_sandbox_memory( - ctx: &mut Runtime, - ptr: u32, - len: u32, -) -> Result, sandbox::HostError> { - charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReadMemory(len))?; - - let mut buf = vec![0u8; len as usize]; - ctx.memory.get(ptr, buf.as_mut_slice()).map_err(|_| sandbox::HostError)?; - Ok(buf) -} - -/// Read designated chunk from the sandbox memory into the scratch buffer, consuming an -/// appropriate amount of gas. Resizes the scratch buffer to the specified length on success. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - calculating the gas cost resulted in overflow. -/// - out of gas -/// - requested buffer is not within the bounds of the sandbox memory. -fn read_sandbox_memory_into_scratch( - ctx: &mut Runtime, - ptr: u32, - len: u32, -) -> Result<(), sandbox::HostError> { - charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReadMemory(len))?; - - ctx.scratch_buf.resize(len as usize, 0); - ctx.memory.get(ptr, ctx.scratch_buf.as_mut_slice()).map_err(|_| sandbox::HostError)?; - Ok(()) -} - -/// Read designated chunk from the sandbox memory into the supplied buffer, consuming -/// an appropriate amount of gas. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - calculating the gas cost resulted in overflow. -/// - out of gas -/// - requested buffer is not within the bounds of the sandbox memory. -fn read_sandbox_memory_into_buf( - ctx: &mut Runtime, - ptr: u32, - buf: &mut [u8], -) -> Result<(), sandbox::HostError> { - charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReadMemory(buf.len() as u32))?; - - ctx.memory.get(ptr, buf).map_err(Into::into) -} - -/// Read designated chunk from the sandbox memory, consuming an appropriate amount of -/// gas, and attempt to decode into the specified type. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - calculating the gas cost resulted in overflow. -/// - out of gas -/// - requested buffer is not within the bounds of the sandbox memory. -/// - the buffer contents cannot be decoded as the required type. -fn read_sandbox_memory_as( - ctx: &mut Runtime, - ptr: u32, - len: u32, -) -> Result { - let buf = read_sandbox_memory(ctx, ptr, len)?; - D::decode(&mut &buf[..]).map_err(|_| sandbox::HostError) -} - -/// Write the given buffer to the designated location in the sandbox memory, consuming -/// an appropriate amount of gas. -/// -/// Returns `Err` if one of the following conditions occurs: -/// -/// - calculating the gas cost resulted in overflow. -/// - out of gas -/// - designated area is not within the bounds of the sandbox memory. -fn write_sandbox_memory( - schedule: &Schedule, - gas_meter: &mut GasMeter, - memory: &sandbox::Memory, - ptr: u32, - buf: &[u8], -) -> Result<(), sandbox::HostError> { - charge_gas(gas_meter, schedule, RuntimeToken::WriteMemory(buf.len() as u32))?; - - memory.set(ptr, buf)?; - - Ok(()) -} - -// *********************************************************** -// * AFTER MAKING A CHANGE MAKE SURE TO UPDATE COMPLEXITY.MD * -// *********************************************************** - -// Define a function `fn init_env() -> HostFunctionSet` that returns -// a function set which can be imported by an executed contract. -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) => { - charge_gas(&mut ctx.gas_meter, ctx.schedule, RuntimeToken::Explicit(amount))?; - Ok(()) - }, - - // Change the value at the given key in the storage or remove the entry. - // The value length must not exceed the maximum defined by the Contracts module parameters. - // - // - key_ptr: pointer into the linear - // memory where the location of the requested value is placed. - // - value_non_null: if set to 0, then the entry - // at the given location will be removed. - // - value_ptr: pointer into the linear memory - // where the value to set is placed. If `value_non_null` is set to 0, then this parameter is ignored. - // - value_len: the length of the value. If `value_non_null` is set to 0, then this parameter is ignored. - ext_set_storage(ctx, key_ptr: u32, value_non_null: u32, value_ptr: u32, value_len: u32) => { - if value_non_null != 0 && ctx.ext.max_value_size() < value_len { - return Err(sandbox::HostError); - } - let mut key: StorageKey = [0; 32]; - read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; - let value = - if value_non_null != 0 { - Some(read_sandbox_memory(ctx, value_ptr, value_len)?) - } else { - None - }; - ctx.ext.set_storage(key, value).map_err(|_| sandbox::HostError)?; - - Ok(()) - }, - - // Retrieve the value at the given location from the storage and return 0. - // If there is no entry at the given location then this function will return 1 and - // clear the scratch buffer. - // - // - key_ptr: pointer into the linear memory where the key - // of the requested value is placed. - ext_get_storage(ctx, key_ptr: u32) -> u32 => { - let mut key: StorageKey = [0; 32]; - read_sandbox_memory_into_buf(ctx, key_ptr, &mut key)?; - if let Some(value) = ctx.ext.get_storage(&key) { - ctx.scratch_buf = value; - Ok(0) - } else { - ctx.scratch_buf.clear(); - Ok(1) - } - }, - - // Make a call to another contract. - // - // If the called contract runs to completion, then this returns the status code the callee - // returns on exit in the bottom 8 bits of the return value. The top 24 bits are 0s. A status - // code of 0 indicates success, and any other code indicates a failure. On failure, any state - // changes made by the called contract are reverted. The scratch buffer is filled with the - // output data returned by the called contract, even in the case of a failure status. - // - // If the contract traps during execution or otherwise fails to complete successfully, then - // this function clears the scratch buffer and returns 0x0100. As with a failure status, any - // state changes made by the called contract are reverted. - // - // - callee_ptr: a pointer to the address of the callee contract. - // Should be decodable as an `T::AccountId`. Traps otherwise. - // - callee_len: length of the address buffer. - // - gas: how much gas to devote to the execution. - // - value_ptr: a pointer to the buffer with value, how much value to send. - // Should be decodable as a `T::Balance`. Traps otherwise. - // - value_len: length of the value buffer. - // - input_data_ptr: a pointer to a buffer to be used as input data to the callee. - // - input_data_len: length of the input data buffer. - ext_call( - ctx, - callee_ptr: u32, - callee_len: u32, - gas: u64, - value_ptr: u32, - value_len: u32, - input_data_ptr: u32, - input_data_len: u32 - ) -> u32 => { - let callee: <::T as system::Trait>::AccountId = - read_sandbox_memory_as(ctx, callee_ptr, callee_len)?; - let value: BalanceOf<::T> = - read_sandbox_memory_as(ctx, value_ptr, value_len)?; - - // Read input data into the scratch buffer, then take ownership of it. - read_sandbox_memory_into_scratch(ctx, input_data_ptr, input_data_len)?; - let input_data = mem::replace(&mut ctx.scratch_buf, Vec::new()); - - let nested_gas_limit = if gas == 0 { - ctx.gas_meter.gas_left() - } else { - gas.saturated_into() - }; - let ext = &mut ctx.ext; - 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, - ) - .map_err(|err| err.buffer) - } - // there is not enough gas to allocate for the nested call. - None => Err(input_data), - } - }); - - match call_outcome { - Ok(output) => { - ctx.scratch_buf = output.data; - Ok(output.status.into()) - }, - Err(buffer) => { - ctx.scratch_buf = buffer; - ctx.scratch_buf.clear(); - Ok(TRAP_RETURN_CODE) - }, - } - }, - - // Instantiate a contract with the specified code hash. - // - // This function creates an account and executes the constructor defined in the code specified - // by the code hash. - // - // If the constructor runs to completion, then this returns the status code that the newly - // instantiated contract returns on exit in the bottom 8 bits of the return value. The top 24 - // bits are 0s. A status code of 0 indicates success, and any other code indicates a failure. - // On failure, any state changes made by the called contract are reverted and the contract is - // not instantiated. On a success status, the scratch buffer is filled with the encoded address - // of the newly instantiated contract. In the case of a failure status, the scratch buffer is - // cleared. - // - // If the contract traps during execution or otherwise fails to complete successfully, then - // this function clears the scratch buffer and returns 0x0100. As with a failure status, any - // state changes made by the called contract are reverted. - - // This function creates an account and executes initializer code. After the execution, - // the returned buffer is saved as the code of the created account. - // - // Returns 0 on the successful contract instantiation and puts the address of the instantiated - // contract into the scratch buffer. Otherwise, returns non-zero value and clears the scratch - // buffer. - // - // - code_hash_ptr: a pointer to the buffer that contains the initializer code. - // - code_hash_len: length of the initializer code buffer. - // - gas: how much gas to devote to the execution of the initializer code. - // - value_ptr: a pointer to the buffer with value, how much value to send. - // Should be decodable as a `T::Balance`. Traps otherwise. - // - value_len: length of the value buffer. - // - input_data_ptr: a pointer to a buffer to be used as input data to the initializer code. - // - input_data_len: length of the input data buffer. - ext_instantiate( - ctx, - code_hash_ptr: u32, - code_hash_len: u32, - gas: u64, - value_ptr: u32, - value_len: u32, - input_data_ptr: u32, - input_data_len: u32 - ) -> u32 => { - let code_hash: CodeHash<::T> = - read_sandbox_memory_as(ctx, code_hash_ptr, code_hash_len)?; - let value: BalanceOf<::T> = - read_sandbox_memory_as(ctx, value_ptr, value_len)?; - - // Read input data into the scratch buffer, then take ownership of it. - read_sandbox_memory_into_scratch(ctx, input_data_ptr, input_data_len)?; - let input_data = mem::replace(&mut ctx.scratch_buf, Vec::new()); - - let nested_gas_limit = if gas == 0 { - ctx.gas_meter.gas_left() - } else { - gas.saturated_into() - }; - let ext = &mut ctx.ext; - let instantiate_outcome = ctx.gas_meter.with_nested(nested_gas_limit, |nested_meter| { - match nested_meter { - Some(nested_meter) => { - ext.instantiate( - &code_hash, - value, - nested_meter, - input_data - ) - .map_err(|err| err.buffer) - } - // there is not enough gas to allocate for the nested call. - None => Err(input_data), - } - }); - match instantiate_outcome { - Ok((address, output)) => { - let is_success = output.is_success(); - ctx.scratch_buf = output.data; - ctx.scratch_buf.clear(); - if is_success { - // Write the address to the scratch buffer. - address.encode_to(&mut ctx.scratch_buf); - } - Ok(output.status.into()) - }, - Err(buffer) => { - ctx.scratch_buf = buffer; - ctx.scratch_buf.clear(); - Ok(TRAP_RETURN_CODE) - }, - } - }, - - // Save a data buffer as a result of the execution, terminate the execution and return a - // successful result to the caller. - // - // This is the only way to return a data buffer to the caller. - ext_return(ctx, data_ptr: u32, data_len: u32) => { - charge_gas(ctx.gas_meter, ctx.schedule, RuntimeToken::ReturnData(data_len))?; - - read_sandbox_memory_into_scratch(ctx, data_ptr, data_len)?; - let output_buf = mem::replace(&mut ctx.scratch_buf, Vec::new()); - - ctx.special_trap = Some(SpecialTrap::Return(output_buf)); - - // The trap mechanism is used to immediately terminate the execution. - // This trap should be handled appropriately before returning the result - // to the user of this crate. - Err(sandbox::HostError) - }, - - // Stores the address of the caller into the scratch buffer. - // - // If this is a top-level call (i.e. initiated by an extrinsic) the origin address of the - // extrinsic will be returned. Otherwise, if this call is initiated by another contract then the - // address of the contract will be returned. - ext_caller(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.caller().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // Stores the address of the current contract into the scratch buffer. - ext_address(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.address().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // Stores the 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.clear(); - ctx.gas_meter.gas_price().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // Stores the amount of gas left into the scratch buffer. - // - // The data is encoded as Gas. The current contents of the scratch buffer are overwritten. - ext_gas_left(ctx) => { - ctx.scratch_buf.clear(); - ctx.gas_meter.gas_left().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // 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.clear(); - ctx.ext.balance().encode_to(&mut ctx.scratch_buf); - 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.clear(); - ctx.ext.value_transferred().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // Stores the random number for the current block for the given subject into the scratch - // buffer. - // - // The data is encoded as T::Hash. The current contents of the scratch buffer are - // overwritten. - ext_random(ctx, subject_ptr: u32, subject_len: u32) => { - // The length of a subject can't exceed `max_subject_len`. - if subject_len > ctx.schedule.max_subject_len { - return Err(sandbox::HostError); - } - - let subject_buf = read_sandbox_memory(ctx, subject_ptr, subject_len)?; - ctx.scratch_buf.clear(); - ctx.ext.random(&subject_buf).encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // Load the latest block timestamp into the scratch buffer - ext_now(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.now().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // Stores the minimum balance (a.k.a. existential deposit) into the scratch buffer. - // - // The data is encoded as T::Balance. The current contents of the scratch buffer are - // overwritten. - ext_minimum_balance(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.minimum_balance().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, - - // Decodes the given buffer as a `T::Call` and adds it to the list - // of to-be-dispatched calls. - // - // All calls made it to the top-level context will be dispatched before - // finishing the execution of the calling extrinsic. - ext_dispatch_call(ctx, call_ptr: u32, call_len: u32) => { - let call: <::T as Trait>::Call = - read_sandbox_memory_as(ctx, call_ptr, call_len)?; - - // Charge gas for dispatching this call. - let fee = { - let balance_fee = <::T as Trait>::ComputeDispatchFee::compute_dispatch_fee(&call); - approx_gas_for_balance(ctx.gas_meter.gas_price(), balance_fee) - }; - charge_gas(&mut ctx.gas_meter, ctx.schedule, RuntimeToken::ComputedDispatchFee(fee))?; - - ctx.ext.note_dispatch_call(call); - - Ok(()) - }, - - // Record a request to restore the caller contract to the specified contract. - // - // At the finalization stage, i.e. when all changes from the extrinsic that invoked this - // contract are commited, this function will compute a tombstone hash from the caller's - // storage and the given code hash and if the hash matches the hash found in the tombstone at - // the specified address - kill the caller contract and restore the destination contract and set - // the specified `rent_allowance`. All caller's funds are transfered to the destination. - // - // This function doesn't perform restoration right away but defers it to the end of the - // transaction. If there is no tombstone in the destination address or if the hashes don't match - // then restoration is cancelled and no changes are made. - // - // `dest_ptr`, `dest_len` - the pointer and the length of a buffer that encodes `T::AccountId` - // with the address of the to be restored contract. - // `code_hash_ptr`, `code_hash_len` - the pointer and the length of a buffer that encodes - // a code hash of the to be restored contract. - // `rent_allowance_ptr`, `rent_allowance_len` - the pointer and the length of a buffer that - // encodes the rent allowance that must be set in the case of successful restoration. - // `delta_ptr` is the pointer to the start of a buffer that has `delta_count` storage keys - // laid out sequentially. - ext_restore_to( - ctx, - dest_ptr: u32, - dest_len: u32, - code_hash_ptr: u32, - code_hash_len: u32, - rent_allowance_ptr: u32, - rent_allowance_len: u32, - delta_ptr: u32, - delta_count: u32 - ) => { - let dest: <::T as system::Trait>::AccountId = - read_sandbox_memory_as(ctx, dest_ptr, dest_len)?; - let code_hash: CodeHash<::T> = - read_sandbox_memory_as(ctx, code_hash_ptr, code_hash_len)?; - let rent_allowance: BalanceOf<::T> = - read_sandbox_memory_as(ctx, rent_allowance_ptr, rent_allowance_len)?; - let delta = { - // We don't use `with_capacity` here to not eagerly allocate the user specified amount - // of memory. - let mut delta = Vec::new(); - let mut key_ptr = delta_ptr; - - for _ in 0..delta_count { - const KEY_SIZE: usize = 32; - - // Read the delta into the provided buffer and collect it into the buffer. - let mut delta_key: StorageKey = [0; KEY_SIZE]; - read_sandbox_memory_into_buf(ctx, key_ptr, &mut delta_key)?; - delta.push(delta_key); - - // Offset key_ptr to the next element. - key_ptr = key_ptr.checked_add(KEY_SIZE as u32).ok_or_else(|| sandbox::HostError)?; - } - - delta - }; - - ctx.ext.note_restore_to( - dest, - code_hash, - rent_allowance, - delta, - ); - - Ok(()) - }, - - // Returns the size of the scratch buffer. - // - // For more details on the scratch buffer see `ext_scratch_read`. - ext_scratch_size(ctx) -> u32 => { - Ok(ctx.scratch_buf.len() as u32) - }, - - // Copy data from the scratch buffer starting from `offset` with length `len` into the contract - // memory. The region at which the data should be put is specified by `dest_ptr`. - // - // In order to get size of the scratch buffer use `ext_scratch_size`. At the start of contract - // execution, the scratch buffer is filled with the input data. Whenever a contract calls - // function that uses the scratch buffer the contents of the scratch buffer are overwritten. - ext_scratch_read(ctx, dest_ptr: u32, offset: u32, len: u32) => { - let offset = offset as usize; - if offset > ctx.scratch_buf.len() { - // Offset can't be larger than scratch buffer length. - return Err(sandbox::HostError); - } - - // This can't panic since `offset <= ctx.scratch_buf.len()`. - let src = &ctx.scratch_buf[offset..]; - if src.len() != len as usize { - return Err(sandbox::HostError); - } - - // Finally, perform the write. - write_sandbox_memory( - ctx.schedule, - ctx.gas_meter, - &ctx.memory, - dest_ptr, - src, - )?; - - Ok(()) - }, - - // Copy data from contract memory starting from `src_ptr` with length `len` into the scratch - // buffer. This overwrites the entire scratch buffer and resizes to `len`. Specifying a `len` - // of zero clears the scratch buffer. - // - // This should be used before exiting a call or instantiation in order to set the return data. - ext_scratch_write(ctx, src_ptr: u32, len: u32) => { - read_sandbox_memory_into_scratch(ctx, src_ptr, len) - }, - - // Deposit a contract event with the data buffer and optional list of topics. There is a limit - // on the maximum number of topics specified by `max_event_topics`. - // - // - topics_ptr - a pointer to the buffer of topics encoded as `Vec`. The value of this - // is ignored if `topics_len` is set to 0. The topics list can't contain duplicates. - // - topics_len - the length of the topics buffer. Pass 0 if you want to pass an empty vector. - // - data_ptr - a pointer to a raw data buffer which will saved along the event. - // - data_len - the length of the data buffer. - ext_deposit_event(ctx, topics_ptr: u32, topics_len: u32, data_ptr: u32, data_len: u32) => { - let mut topics: Vec::::T>> = match topics_len { - 0 => Vec::new(), - _ => read_sandbox_memory_as(ctx, topics_ptr, topics_len)?, - }; - - // If there are more than `max_event_topics`, then trap. - if topics.len() > ctx.schedule.max_event_topics as usize { - return Err(sandbox::HostError); - } - - // Check for duplicate topics. If there are any, then trap. - if has_duplicates(&mut topics) { - return Err(sandbox::HostError); - } - - let event_data = read_sandbox_memory(ctx, data_ptr, data_len)?; - - charge_gas( - ctx.gas_meter, - ctx.schedule, - RuntimeToken::DepositEvent(topics.len() as u32, data_len) - )?; - ctx.ext.deposit_event(topics, event_data); - - Ok(()) - }, - - // Set rent allowance of the contract - // - // - value_ptr: a pointer to the buffer with value, how much to allow for rent - // Should be decodable as a `T::Balance`. Traps otherwise. - // - value_len: length of the value buffer. - ext_set_rent_allowance(ctx, value_ptr: u32, value_len: u32) => { - let value: BalanceOf<::T> = - read_sandbox_memory_as(ctx, value_ptr, value_len)?; - ctx.ext.set_rent_allowance(value); - - Ok(()) - }, - - // Stores the rent allowance into the scratch buffer. - // - // The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten. - ext_rent_allowance(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.rent_allowance().encode_to(&mut ctx.scratch_buf); - - Ok(()) - }, - - // Prints utf8 encoded string from the data buffer. - // Only available on `--dev` chains. - // This function may be removed at any time, superseded by a more general contract debugging feature. - ext_println(ctx, str_ptr: u32, str_len: u32) => { - let data = read_sandbox_memory(ctx, str_ptr, str_len)?; - if let Ok(utf8) = core::str::from_utf8(&data) { - sr_primitives::print(utf8); - } - Ok(()) - }, - - // Stores the current block number of the current contract into the scratch buffer. - ext_block_number(ctx) => { - ctx.scratch_buf.clear(); - ctx.ext.block_number().encode_to(&mut ctx.scratch_buf); - Ok(()) - }, -); - -/// Finds duplicates in a given vector. -/// -/// This function has complexity of O(n log n) and no additional memory is required, although -/// the order of items is not preserved. -fn has_duplicates>(items: &mut Vec) -> bool { - // Sort the vector - items.sort_unstable_by(|a, b| { - Ord::cmp(a.as_ref(), b.as_ref()) - }); - // And then find any two consecutive equal elements. - items.windows(2).any(|w| { - match w { - &[ref a, ref b] => a == b, - _ => false, - } - }) -} diff --git a/srml/democracy/Cargo.toml b/srml/democracy/Cargo.toml deleted file mode 100644 index 761e56ceda6cb..0000000000000 --- a/srml/democracy/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "srml-democracy" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true, features = ["derive"] } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -balances = { package = "srml-balances", path = "../balances" } - -[features] -default = ["std"] -std = [ - "serde", - "safe-mix/std", - "codec/std", - "rstd/std", - "runtime-io/std", - "support/std", - "sr-primitives/std", - "system/std", -] diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs deleted file mode 100644 index 545666e493026..0000000000000 --- a/srml/democracy/src/lib.rs +++ /dev/null @@ -1,2052 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Democratic system: Handles administration of general stakeholder voting. -#![recursion_limit="128"] -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::prelude::*; -use rstd::{result, convert::TryFrom}; -use sr_primitives::{ - RuntimeDebug, - traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash, Dispatchable}, - weights::SimpleDispatchInfo, -}; -use codec::{Ref, Encode, Decode, Input, Output, Error}; -use support::{ - decl_module, decl_storage, decl_event, ensure, - Parameter, - traits::{ - Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get, - OnFreeBalanceZero - } -}; -use support::dispatch::Result; -use system::{ensure_signed, ensure_root}; - -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. -pub type ReferendumIndex = u32; - -/// A value denoting the strength of conviction of a vote. -#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)] -pub enum Conviction { - /// 0.1x votes, unlocked. - None, - /// 1x votes, locked for an enactment period following a successful vote. - Locked1x, - /// 2x votes, locked for 2x enactment periods following a successful vote. - Locked2x, - /// 3x votes, locked for 4x... - Locked3x, - /// 4x votes, locked for 8x... - Locked4x, - /// 5x votes, locked for 16x... - Locked5x, - /// 6x votes, locked for 32x... - Locked6x, -} - -impl Default for Conviction { - fn default() -> Self { - Conviction::None - } -} - -impl From for u8 { - fn from(c: Conviction) -> u8 { - match c { - Conviction::None => 0, - Conviction::Locked1x => 1, - Conviction::Locked2x => 2, - Conviction::Locked3x => 3, - Conviction::Locked4x => 4, - Conviction::Locked5x => 5, - Conviction::Locked6x => 6, - } - } -} - -impl TryFrom for Conviction { - type Error = (); - fn try_from(i: u8) -> result::Result { - Ok(match i { - 0 => Conviction::None, - 1 => Conviction::Locked1x, - 2 => Conviction::Locked2x, - 3 => Conviction::Locked3x, - 4 => Conviction::Locked4x, - 5 => Conviction::Locked5x, - 6 => Conviction::Locked6x, - _ => return Err(()), - }) - } -} - -impl Conviction { - /// The amount of time (in number of periods) that our conviction implies a successful voter's - /// balance should be locked for. - fn lock_periods(self) -> u32 { - match self { - Conviction::None => 0, - Conviction::Locked1x => 1, - Conviction::Locked2x => 2, - Conviction::Locked3x => 4, - Conviction::Locked4x => 8, - Conviction::Locked5x => 16, - Conviction::Locked6x => 32, - } - } - - /// The votes of a voter of the given `balance` with our conviction. - fn votes< - B: From + Zero + Copy + CheckedMul + CheckedDiv + Bounded - >(self, balance: B) -> (B, B) { - match self { - Conviction::None => { - let r = balance.checked_div(&10u8.into()).unwrap_or_else(Zero::zero); - (r, r) - } - x => ( - balance.checked_mul(&u8::from(x).into()).unwrap_or_else(B::max_value), - balance, - ) - } - } -} - -impl Bounded for Conviction { - fn min_value() -> Self { - Conviction::None - } - - fn max_value() -> Self { - Conviction::Locked6x - } -} - -const MAX_RECURSION_LIMIT: u32 = 16; - -/// A number of lock periods, plus a vote, one way or the other. -#[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug)] -pub struct Vote { - pub aye: bool, - pub conviction: Conviction, -} - -impl Encode for Vote { - fn encode_to(&self, output: &mut T) { - output.push_byte(u8::from(self.conviction) | if self.aye { 0b1000_0000 } else { 0 }); - } -} - -impl codec::EncodeLike for Vote {} - -impl Decode for Vote { - fn decode(input: &mut I) -> core::result::Result { - let b = input.read_byte()?; - Ok(Vote { - aye: (b & 0b1000_0000) == 0b1000_0000, - conviction: Conviction::try_from(b & 0b0111_1111) - .map_err(|_| Error::from("Invalid conviction"))?, - }) - } -} - -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - -pub trait Trait: system::Trait + Sized { - type Proposal: Parameter + Dispatchable; - type Event: From> + Into<::Event>; - - /// Currency type for this module. - type Currency: ReservableCurrency - + LockableCurrency; - - /// The minimum period of locking and the period between a proposal being approved and enacted. - /// - /// It should generally be a little more than the unstake period to ensure that - /// voting stakers have an opportunity to remove themselves from the system in the case where - /// they are on the losing side of a vote. - type EnactmentPeriod: Get; - - /// How often (in blocks) new public referenda are launched. - type LaunchPeriod: Get; - - /// How often (in blocks) to check for new votes. - type VotingPeriod: Get; - - /// The minimum amount to be used as a deposit for a public referendum proposal. - type MinimumDeposit: Get>; - - /// Origin from which the next tabled referendum may be forced. This is a normal - /// "super-majority-required" referendum. - type ExternalOrigin: EnsureOrigin; - - /// Origin from which the next tabled referendum may be forced; this allows for the tabling of - /// a majority-carries referendum. - type ExternalMajorityOrigin: EnsureOrigin; - - /// Origin from which the next tabled referendum may be forced; this allows for the tabling of - /// a negative-turnout-bias (default-carries) referendum. - type ExternalDefaultOrigin: EnsureOrigin; - - /// Origin from which the next referendum proposed by the external majority may be immediately - /// tabled to vote asynchronously in a similar manner to the emergency origin. It remains a - /// majority-carries vote. - type FastTrackOrigin: EnsureOrigin; - - /// Minimum voting period allowed for an fast-track/emergency referendum. - type EmergencyVotingPeriod: Get; - - /// Origin from which any referendum may be cancelled in an emergency. - type CancellationOrigin: EnsureOrigin; - - /// Origin for anyone able to veto proposals. - type VetoOrigin: EnsureOrigin; - - /// Period in blocks where an external proposal may not be re-submitted after being vetoed. - type CooloffPeriod: Get; -} - -/// Info regarding an ongoing referendum. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct ReferendumInfo { - /// When voting on this referendum will end. - end: BlockNumber, - /// The proposal being voted on. - proposal: Proposal, - /// The thresholding mechanism to determine whether it passed. - threshold: VoteThreshold, - /// The delay (in blocks) to wait after a successful referendum before deploying. - delay: BlockNumber, -} - -impl ReferendumInfo { - /// Create a new instance. - pub fn new( - end: BlockNumber, - proposal: Proposal, - threshold: VoteThreshold, - delay: BlockNumber - ) -> Self { - ReferendumInfo { end, proposal, threshold, delay } - } -} - -decl_storage! { - trait Store for Module as Democracy { - /// The number of (public) proposals that have been made so far. - pub PublicPropCount get(fn public_prop_count) build(|_| 0 as PropIndex) : PropIndex; - /// The public proposals. Unsorted. - pub PublicProps get(fn public_props): Vec<(PropIndex, T::Proposal, T::AccountId)>; - /// Those who have locked a deposit. - pub DepositOf get(fn deposit_of): map PropIndex => Option<(BalanceOf, Vec)>; - - /// The next free referendum index, aka the number of referenda started so far. - pub ReferendumCount get(fn referendum_count) build(|_| 0 as ReferendumIndex): ReferendumIndex; - /// The next referendum index that should be tallied. - pub NextTally get(fn next_tally) build(|_| 0 as ReferendumIndex): ReferendumIndex; - /// Information concerning any given referendum. - pub ReferendumInfoOf get(fn referendum_info): - map ReferendumIndex => Option<(ReferendumInfo)>; - /// Queue of successful referenda to be dispatched. - pub DispatchQueue get(fn dispatch_queue): - map T::BlockNumber => Vec>; - - /// Get the voters for the current proposal. - pub VotersFor get(fn voters_for): map ReferendumIndex => Vec; - - /// Get the vote in a given referendum of a particular voter. The result is meaningful only - /// if `voters_for` includes the voter when called with the referendum (you'll get the - /// default `Vote` value otherwise). If you don't want to check `voters_for`, then you can - /// also check for simple existence with `VoteOf::exists` first. - pub VoteOf get(fn vote_of): map (ReferendumIndex, T::AccountId) => Vote; - - /// Who is able to vote for whom. Value is the fund-holding account, key is the - /// vote-transaction-sending account. - pub Proxy get(fn proxy): map T::AccountId => Option; - - /// Get the account (and lock periods) to which another account is delegating vote. - pub Delegations get(fn delegations): linked_map T::AccountId => (T::AccountId, Conviction); - - /// True if the last referendum tabled was submitted externally. False if it was a public - /// proposal. - pub LastTabledWasExternal: bool; - - /// The referendum to be tabled whenever it would be valid to table an external proposal. - /// This happens when a referendum needs to be tabled and one of two conditions are met: - /// - `LastTabledWasExternal` is `false`; or - /// - `PublicProps` is empty. - pub NextExternal: Option<(T::Proposal, VoteThreshold)>; - - /// A record of who vetoed what. Maps proposal hash to a possible existent block number - /// (until when it may not be resubmitted) and who vetoed it. - pub Blacklist get(fn blacklist): map T::Hash => Option<(T::BlockNumber, Vec)>; - - /// Record of all proposals that have been subject to emergency cancellation. - pub Cancellations: map T::Hash => bool; - } -} - -decl_event!( - pub enum Event where - Balance = BalanceOf, - ::AccountId, - ::Hash, - ::BlockNumber, - { - Proposed(PropIndex, Balance), - Tabled(PropIndex, Balance, Vec), - ExternalTabled, - Started(ReferendumIndex, VoteThreshold), - Passed(ReferendumIndex), - NotPassed(ReferendumIndex), - Cancelled(ReferendumIndex), - Executed(ReferendumIndex, bool), - Delegated(AccountId, AccountId), - Undelegated(AccountId), - Vetoed(AccountId, Hash, BlockNumber), - } -); - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// The minimum period of locking and the period between a proposal being approved and enacted. - /// - /// It should generally be a little more than the unstake period to ensure that - /// voting stakers have an opportunity to remove themselves from the system in the case where - /// they are on the losing side of a vote. - const EnactmentPeriod: T::BlockNumber = T::EnactmentPeriod::get(); - - /// How often (in blocks) new public referenda are launched. - const LaunchPeriod: T::BlockNumber = T::LaunchPeriod::get(); - - /// How often (in blocks) to check for new votes. - const VotingPeriod: T::BlockNumber = T::VotingPeriod::get(); - - /// The minimum amount to be used as a deposit for a public referendum proposal. - const MinimumDeposit: BalanceOf = T::MinimumDeposit::get(); - - /// Minimum voting period allowed for an emergency referendum. - const EmergencyVotingPeriod: T::BlockNumber = T::EmergencyVotingPeriod::get(); - - /// Period in blocks where an external proposal may not be re-submitted after being vetoed. - const CooloffPeriod: T::BlockNumber = T::CooloffPeriod::get(); - - fn deposit_event() = default; - - /// Propose a sensitive action to be taken. - /// - /// # - /// - O(1). - /// - Two DB changes, one DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] - fn propose(origin, - proposal: Box, - #[compact] value: BalanceOf - ) { - let who = ensure_signed(origin)?; - - ensure!(value >= T::MinimumDeposit::get(), "value too low"); - T::Currency::reserve(&who, value) - .map_err(|_| "proposer's balance too low")?; - - let index = Self::public_prop_count(); - PublicPropCount::put(index + 1); - >::insert(index, (value, &[&who][..])); - - let new_prop = (index, proposal, who); - >::append_or_put(&[Ref::from(&new_prop)][..]); - - Self::deposit_event(RawEvent::Proposed(index, value)); - } - - /// Propose a sensitive action to be taken. - /// - /// # - /// - O(1). - /// - One DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] - fn second(origin, #[compact] proposal: PropIndex) { - let who = ensure_signed(origin)?; - let mut deposit = Self::deposit_of(proposal) - .ok_or("can only second an existing proposal")?; - T::Currency::reserve(&who, deposit.0) - .map_err(|_| "seconder's balance too low")?; - deposit.1.push(who); - >::insert(proposal, deposit); - } - - /// 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. - /// - /// # - /// - O(1). - /// - One DB change, one DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(200_000)] - fn vote(origin, - #[compact] ref_index: ReferendumIndex, - vote: Vote - ) -> Result { - let who = ensure_signed(origin)?; - Self::do_vote(who, ref_index, vote) - } - - /// Vote in a referendum on behalf of a stash. If `vote.is_aye()`, the vote is to enact - /// the proposal; otherwise it is a vote to keep the status quo. - /// - /// # - /// - O(1). - /// - One DB change, one DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(200_000)] - fn proxy_vote(origin, - #[compact] ref_index: ReferendumIndex, - vote: Vote - ) -> Result { - let who = Self::proxy(ensure_signed(origin)?).ok_or("not a proxy")?; - Self::do_vote(who, ref_index, vote) - } - - /// Schedule an emergency cancellation of a referendum. Cannot happen twice to the same - /// referendum. - #[weight = SimpleDispatchInfo::FixedOperational(500_000)] - fn emergency_cancel(origin, ref_index: ReferendumIndex) { - T::CancellationOrigin::ensure_origin(origin)?; - - let info = Self::referendum_info(ref_index).ok_or("unknown index")?; - let h = T::Hashing::hash_of(&info.proposal); - ensure!(!>::exists(h), "cannot cancel the same proposal twice"); - - >::insert(h, true); - Self::clear_referendum(ref_index); - } - - /// Schedule a referendum to be tabled once it is legal to schedule an external - /// referendum. - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] - fn external_propose(origin, proposal: Box) { - T::ExternalOrigin::ensure_origin(origin)?; - ensure!(!>::exists(), "proposal already made"); - let proposal_hash = T::Hashing::hash_of(&proposal); - if let Some((until, _)) = >::get(proposal_hash) { - ensure!(>::block_number() >= until, "proposal still blacklisted"); - } - >::put((*proposal, VoteThreshold::SuperMajorityApprove)); - } - - /// Schedule a majority-carries referendum to be tabled next once it is legal to schedule - /// an external referendum. - /// - /// Unlike `external_propose`, blacklisting has no effect on this and it may replace a - /// pre-scheduled `external_propose` call. - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] - fn external_propose_majority(origin, proposal: Box) { - T::ExternalMajorityOrigin::ensure_origin(origin)?; - >::put((*proposal, VoteThreshold::SimpleMajority)); - } - - /// Schedule a negative-turnout-bias referendum to be tabled next once it is legal to - /// schedule an external referendum. - /// - /// Unlike `external_propose`, blacklisting has no effect on this and it may replace a - /// pre-scheduled `external_propose` call. - #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] - fn external_propose_default(origin, proposal: Box) { - T::ExternalDefaultOrigin::ensure_origin(origin)?; - >::put((*proposal, VoteThreshold::SuperMajorityAgainst)); - } - - /// Schedule the currently externally-proposed majority-carries referendum to be tabled - /// immediately. If there is no externally-proposed referendum currently, or if there is one - /// but it is not a majority-carries referendum then it fails. - /// - /// - `proposal_hash`: The hash of the current external proposal. - /// - `voting_period`: The period that is allowed for voting on this proposal. Increased to - /// `EmergencyVotingPeriod` if too low. - /// - `delay`: The number of block after voting has ended in approval and this should be - /// enacted. This doesn't have a minimum amount. - #[weight = SimpleDispatchInfo::FixedNormal(200_000)] - fn fast_track(origin, - proposal_hash: T::Hash, - voting_period: T::BlockNumber, - delay: T::BlockNumber - ) { - T::FastTrackOrigin::ensure_origin(origin)?; - let (proposal, threshold) = >::get().ok_or("no proposal made")?; - ensure!(threshold != VoteThreshold::SuperMajorityApprove, "next external proposal not simple majority"); - ensure!(proposal_hash == T::Hashing::hash_of(&proposal), "invalid hash"); - - >::kill(); - let now = >::block_number(); - // We don't consider it an error if `vote_period` is too low, like `emergency_propose`. - let period = voting_period.max(T::EmergencyVotingPeriod::get()); - Self::inject_referendum(now + period, proposal, threshold, delay).map(|_| ())?; - } - - /// Veto and blacklist the external proposal hash. - #[weight = SimpleDispatchInfo::FixedNormal(200_000)] - fn veto_external(origin, proposal_hash: T::Hash) { - let who = T::VetoOrigin::ensure_origin(origin)?; - - if let Some((proposal, _)) = >::get() { - ensure!(proposal_hash == T::Hashing::hash_of(&proposal), "unknown proposal"); - } else { - Err("no external proposal")?; - } - - let mut existing_vetoers = >::get(&proposal_hash) - .map(|pair| pair.1) - .unwrap_or_else(Vec::new); - let insert_position = existing_vetoers.binary_search(&who) - .err().ok_or("identity may not veto a proposal twice")?; - - existing_vetoers.insert(insert_position, who.clone()); - let until = >::block_number() + T::CooloffPeriod::get(); - >::insert(&proposal_hash, (until, existing_vetoers)); - - Self::deposit_event(RawEvent::Vetoed(who, proposal_hash, until)); - >::kill(); - } - - /// Remove a referendum. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn cancel_referendum(origin, #[compact] ref_index: ReferendumIndex) { - ensure_root(origin)?; - Self::clear_referendum(ref_index); - } - - /// Cancel a proposal queued for enactment. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn cancel_queued( - origin, - #[compact] when: T::BlockNumber, - #[compact] which: u32, - #[compact] what: ReferendumIndex - ) { - ensure_root(origin)?; - let which = which as usize; - let mut items = >::get(when); - if items.get(which).and_then(Option::as_ref).map_or(false, |x| x.1 == what) { - items[which] = None; - >::insert(when, items); - } else { - Err("proposal not found")? - } - } - - fn on_initialize(n: T::BlockNumber) { - if let Err(e) = Self::end_block(n) { - sr_primitives::print(e); - } - } - - /// Specify a proxy. Called by the stash. - /// - /// # - /// - One extra DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn set_proxy(origin, proxy: T::AccountId) { - let who = ensure_signed(origin)?; - ensure!(!>::exists(&proxy), "already a proxy"); - >::insert(proxy, who) - } - - /// Clear the proxy. Called by the proxy. - /// - /// # - /// - One DB clear. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn resign_proxy(origin) { - let who = ensure_signed(origin)?; - >::remove(who); - } - - /// Clear the proxy. Called by the stash. - /// - /// # - /// - One DB clear. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn remove_proxy(origin, proxy: T::AccountId) { - let who = ensure_signed(origin)?; - ensure!(&Self::proxy(&proxy).ok_or("not a proxy")? == &who, "wrong proxy"); - >::remove(proxy); - } - - /// Delegate vote. - /// - /// # - /// - One extra DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - pub fn delegate(origin, to: T::AccountId, conviction: Conviction) { - let who = ensure_signed(origin)?; - >::insert(&who, (&to, conviction)); - // Currency is locked indefinitely as long as it's delegated. - T::Currency::extend_lock( - DEMOCRACY_ID, - &who, - Bounded::max_value(), - T::BlockNumber::max_value(), - WithdrawReason::Transfer.into() - ); - Self::deposit_event(RawEvent::Delegated(who, to)); - } - - /// Undelegate vote. - /// - /// # - /// - O(1). - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn undelegate(origin) { - let who = ensure_signed(origin)?; - ensure!(>::exists(&who), "not delegated"); - let (_, conviction) = >::take(&who); - // Indefinite lock is reduced to the maximum voting lock that could be possible. - let now = >::block_number(); - let locked_until = now + T::EnactmentPeriod::get() * conviction.lock_periods().into(); - T::Currency::set_lock( - DEMOCRACY_ID, - &who, - Bounded::max_value(), - locked_until, - WithdrawReason::Transfer.into() - ); - Self::deposit_event(RawEvent::Undelegated(who)); - } - } -} - -impl Module { - // exposed immutables. - - /// 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 * (l.len() as u32).into()) - } - - /// Return true if `ref_index` is an on-going referendum. - pub fn is_active_referendum(ref_index: ReferendumIndex) -> bool { - >::exists(ref_index) - } - - /// Get all referenda currently active. - pub fn active_referenda() - -> Vec<(ReferendumIndex, ReferendumInfo)> - { - let next = Self::next_tally(); - let last = Self::referendum_count(); - (next..last).into_iter() - .filter_map(|i| Self::referendum_info(i).map(|info| (i, info))) - .collect() - } - - /// Get all referenda ready for tally at block `n`. - pub fn maturing_referenda_at( - n: T::BlockNumber - ) -> Vec<(ReferendumIndex, ReferendumInfo)> { - let next = Self::next_tally(); - let last = Self::referendum_count(); - (next..last).into_iter() - .filter_map(|i| Self::referendum_info(i).map(|info| (i, info))) - .take_while(|&(_, ref info)| info.end == n) - .collect() - } - - /// Get the voters for the current proposal. - pub fn tally(ref_index: ReferendumIndex) -> (BalanceOf, BalanceOf, BalanceOf) { - let (approve, against, capital): - (BalanceOf, BalanceOf, BalanceOf) = Self::voters_for(ref_index) - .iter() - .map(|voter| ( - T::Currency::total_balance(voter), Self::vote_of((ref_index, voter.clone())) - )) - .map(|(balance, Vote { aye, conviction })| { - let (votes, turnout) = conviction.votes(balance); - if aye { - (votes, Zero::zero(), turnout) - } else { - (Zero::zero(), votes, turnout) - } - }).fold( - (Zero::zero(), Zero::zero(), Zero::zero()), - |(a, b, c), (d, e, f)| (a + d, b + e, c + f) - ); - let (del_approve, del_against, del_capital) = Self::tally_delegation(ref_index); - (approve + del_approve, against + del_against, capital + del_capital) - } - - /// Get the delegated voters for the current proposal. - /// I think this goes into a worker once https://github.com/paritytech/substrate/issues/1458 is - /// done. - fn tally_delegation(ref_index: ReferendumIndex) -> (BalanceOf, BalanceOf, BalanceOf) { - Self::voters_for(ref_index).iter().fold( - (Zero::zero(), Zero::zero(), Zero::zero()), - |(approve_acc, against_acc, turnout_acc), voter| { - let Vote { aye, conviction } = Self::vote_of((ref_index, voter.clone())); - let (votes, turnout) = Self::delegated_votes( - ref_index, - voter.clone(), - conviction, - MAX_RECURSION_LIMIT - ); - if aye { - (approve_acc + votes, against_acc, turnout_acc + turnout) - } else { - (approve_acc, against_acc + votes, turnout_acc + turnout) - } - } - ) - } - - fn delegated_votes( - ref_index: ReferendumIndex, - to: T::AccountId, - parent_conviction: Conviction, - recursion_limit: u32, - ) -> (BalanceOf, BalanceOf) { - if recursion_limit == 0 { return (Zero::zero(), Zero::zero()); } - >::enumerate() - .filter(|(delegator, (delegate, _))| - *delegate == to && !>::exists(&(ref_index, delegator.clone())) - ).fold( - (Zero::zero(), Zero::zero()), - |(votes_acc, turnout_acc), (delegator, (_delegate, max_conviction))| { - let conviction = Conviction::min(parent_conviction, max_conviction); - let balance = T::Currency::total_balance(&delegator); - let (votes, turnout) = conviction.votes(balance); - let (del_votes, del_turnout) = Self::delegated_votes( - ref_index, - delegator, - conviction, - recursion_limit - 1 - ); - (votes_acc + votes + del_votes, turnout_acc + turnout + del_turnout) - } - ) - } - - // Exposed mutables. - - #[cfg(feature = "std")] - pub fn force_proxy(stash: T::AccountId, proxy: T::AccountId) { - >::insert(proxy, stash) - } - - /// Start a referendum. - pub fn internal_start_referendum( - proposal: T::Proposal, - threshold: VoteThreshold, - delay: T::BlockNumber - ) -> result::Result { - >::inject_referendum( - >::block_number() + T::VotingPeriod::get(), - proposal, - threshold, - delay - ) - } - - /// Remove a referendum. - pub fn internal_cancel_referendum(ref_index: ReferendumIndex) { - Self::deposit_event(RawEvent::Cancelled(ref_index)); - >::clear_referendum(ref_index); - } - - // private. - - /// Actually enact a vote, if legit. - fn do_vote(who: T::AccountId, ref_index: ReferendumIndex, vote: Vote) -> Result { - ensure!(Self::is_active_referendum(ref_index), "vote given for invalid referendum."); - if !>::exists((ref_index, &who)) { - >::append_or_insert(ref_index, &[&who][..]); - } - >::insert((ref_index, &who), vote); - Ok(()) - } - - /// Start a referendum - fn inject_referendum( - end: T::BlockNumber, - proposal: T::Proposal, - threshold: VoteThreshold, - delay: T::BlockNumber, - ) -> result::Result { - let ref_index = Self::referendum_count(); - if ref_index.checked_sub(1) - .and_then(Self::referendum_info) - .map(|i| i.end > end) - .unwrap_or(false) - { - Err("Cannot inject a referendum that ends earlier than preceeding referendum")? - } - - ReferendumCount::put(ref_index + 1); - let item = ReferendumInfo { end, proposal, threshold, delay }; - >::insert(ref_index, item); - Self::deposit_event(RawEvent::Started(ref_index, threshold)); - Ok(ref_index) - } - - /// Remove all info on a referendum. - fn clear_referendum(ref_index: ReferendumIndex) { - >::remove(ref_index); - >::remove(ref_index); - for v in Self::voters_for(ref_index) { - >::remove((ref_index, v)); - } - } - - /// Enact a proposal from a referendum. - fn enact_proposal(proposal: T::Proposal, index: ReferendumIndex) { - let ok = proposal.dispatch(system::RawOrigin::Root.into()).is_ok(); - Self::deposit_event(RawEvent::Executed(index, ok)); - } - - /// Table the next waiting proposal for a vote. - fn launch_next(now: T::BlockNumber) -> Result { - if LastTabledWasExternal::take() { - Self::launch_public(now).or_else(|_| Self::launch_external(now)) - } else { - Self::launch_external(now).or_else(|_| Self::launch_public(now)) - }.map_err(|_| "No proposals waiting") - } - - /// Table the waiting external proposal for a vote, if there is one. - fn launch_external(now: T::BlockNumber) -> Result { - if let Some((proposal, threshold)) = >::take() { - LastTabledWasExternal::put(true); - Self::deposit_event(RawEvent::ExternalTabled); - Self::inject_referendum( - now + T::VotingPeriod::get(), - proposal, - threshold, - T::EnactmentPeriod::get(), - )?; - Ok(()) - } else { - Err("No external proposal waiting") - } - } - - /// Table the waiting public proposal with the highest backing for a vote. - fn launch_public(now: T::BlockNumber) -> Result { - let mut public_props = Self::public_props(); - if let Some((winner_index, _)) = public_props.iter() - .enumerate() - .max_by_key(|x| Self::locked_for((x.1).0).unwrap_or_else(Zero::zero) - /* ^^ defensive only: All current public proposals have an amount locked*/) - { - let (prop_index, proposal, _) = public_props.swap_remove(winner_index); - >::put(public_props); - - if let Some((deposit, depositors)) = >::take(prop_index) { - // refund depositors - for d in &depositors { - T::Currency::unreserve(d, deposit); - } - Self::deposit_event(RawEvent::Tabled(prop_index, deposit, depositors)); - Self::inject_referendum( - now + T::VotingPeriod::get(), - proposal, - VoteThreshold::SuperMajorityApprove, - T::EnactmentPeriod::get(), - )?; - } - Ok(()) - } else { - Err("No public proposals waiting") - } - - } - - fn bake_referendum( - now: T::BlockNumber, - index: ReferendumIndex, - info: ReferendumInfo - ) -> Result { - let (approve, against, capital) = Self::tally(index); - let total_issuance = T::Currency::total_issuance(); - let approved = info.threshold.approved(approve, against, capital, total_issuance); - - // Logic defined in https://www.slideshare.net/gavofyork/governance-in-polkadot-poc3 - // Essentially, we extend the lock-period of the coins behind the winning votes to be the - // vote strength times the public delay period from now. - for (a, Vote { conviction, .. }) in Self::voters_for(index).into_iter() - .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.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 + T::EnactmentPeriod::get() * conviction.lock_periods().into(); - // ...extend their bondage until at least then. - T::Currency::extend_lock( - DEMOCRACY_ID, - &a, - Bounded::max_value(), - locked_until, - WithdrawReason::Transfer.into() - ); - } - - Self::clear_referendum(index); - if approved { - Self::deposit_event(RawEvent::Passed(index)); - if info.delay.is_zero() { - Self::enact_proposal(info.proposal, index); - } else { - >::append_or_insert( - now + info.delay, - &[Some((info.proposal, index))][..] - ); - } - } else { - Self::deposit_event(RawEvent::NotPassed(index)); - } - NextTally::put(index + 1); - - Ok(()) - } - - /// Current era is ending; we should finish up any proposals. - // TODO: move to initialize_block #2779 - fn end_block(now: T::BlockNumber) -> Result { - // pick out another public referendum if it's time. - if (now % T::LaunchPeriod::get()).is_zero() { - // Errors come from the queue being empty. we don't really care about that, and even if - // we did, there is nothing we can do here. - let _ = Self::launch_next(now); - } - - // tally up votes for any expiring referenda. - for (index, info) in Self::maturing_referenda_at(now).into_iter() { - Self::bake_referendum(now, index, info)?; - } - - for (proposal, index) in >::take(now).into_iter().filter_map(|x| x) { - Self::enact_proposal(proposal, index); - } - Ok(()) - } -} - -impl OnFreeBalanceZero for Module { - fn on_free_balance_zero(who: &T::AccountId) { - >::remove(who) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use support::{ - impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, - traits::Contains - }; - use primitives::H256; - use sr_primitives::{traits::{BlakeTwo256, IdentityLookup, Bounded}, testing::Header, Perbill}; - use balances::BalanceLock; - use system::EnsureSignedBy; - - const AYE: Vote = Vote{ aye: true, conviction: Conviction::None }; - const NAY: Vote = Vote{ aye: false, conviction: Conviction::None }; - const BIG_AYE: Vote = Vote{ aye: true, conviction: Conviction::Locked1x }; - const BIG_NAY: Vote = Vote{ aye: false, conviction: Conviction::Locked1x }; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - impl_outer_dispatch! { - pub enum Call for Test where origin: Origin { - balances::Balances, - democracy::Democracy, - } - } - - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, Eq, PartialEq, Debug)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - } - impl balances::Trait for Test { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - parameter_types! { - pub const LaunchPeriod: u64 = 2; - pub const VotingPeriod: u64 = 2; - pub const EmergencyVotingPeriod: u64 = 1; - pub const MinimumDeposit: u64 = 1; - pub const EnactmentPeriod: u64 = 2; - pub const CooloffPeriod: u64 = 2; - pub const One: u64 = 1; - pub const Two: u64 = 2; - pub const Three: u64 = 3; - pub const Four: u64 = 4; - pub const Five: u64 = 5; - } - pub struct OneToFive; - impl Contains for OneToFive { - fn contains(n: &u64) -> bool { - *n >= 1 && *n <= 5 - } - } - impl super::Trait for Test { - type Proposal = Call; - type Event = (); - type Currency = balances::Module; - type EnactmentPeriod = EnactmentPeriod; - type LaunchPeriod = LaunchPeriod; - type VotingPeriod = VotingPeriod; - type EmergencyVotingPeriod = EmergencyVotingPeriod; - type MinimumDeposit = MinimumDeposit; - type ExternalOrigin = EnsureSignedBy; - type ExternalMajorityOrigin = EnsureSignedBy; - type ExternalDefaultOrigin = EnsureSignedBy; - type FastTrackOrigin = EnsureSignedBy; - type CancellationOrigin = EnsureSignedBy; - type VetoOrigin = EnsureSignedBy; - type CooloffPeriod = CooloffPeriod; - } - - fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig::{ - balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - GenesisConfig::default().assimilate_storage(&mut t).unwrap(); - runtime_io::TestExternalities::new(t) - } - - type System = system::Module; - type Balances = balances::Module; - type Democracy = Module; - - #[test] - fn params_should_work() { - new_test_ext().execute_with(|| { - assert_eq!(Democracy::referendum_count(), 0); - assert_eq!(Balances::free_balance(&42), 0); - assert_eq!(Balances::total_issuance(), 210); - }); - } - - fn set_balance_proposal(value: u64) -> Call { - Call::Balances(balances::Call::set_balance(42, value, 0)) - } - - fn propose_set_balance(who: u64, value: u64, delay: u64) -> super::Result { - Democracy::propose( - Origin::signed(who), - Box::new(set_balance_proposal(value)), - delay - ) - } - - fn next_block() { - assert_eq!(Democracy::end_block(System::block_number()), Ok(())); - System::set_block_number(System::block_number() + 1); - } - - fn fast_forward_to(n: u64) { - while System::block_number() < n { - next_block(); - } - } - - #[test] - fn external_and_public_interleaving_works() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(1)), - )); - assert_ok!(propose_set_balance(6, 2, 2)); - - fast_forward_to(1); - - // both waiting: external goes first. - assert_eq!( - Democracy::referendum_info(0), - Some(ReferendumInfo { - end: 2, - proposal: set_balance_proposal(1), - threshold: VoteThreshold::SuperMajorityApprove, - delay: 2 - }) - ); - // replenish external - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(3)), - )); - - fast_forward_to(3); - - // both waiting: public goes next. - assert_eq!( - Democracy::referendum_info(1), - Some(ReferendumInfo { - end: 4, - proposal: set_balance_proposal(2), - threshold: VoteThreshold::SuperMajorityApprove, - delay: 2 - }) - ); - // don't replenish public - - fast_forward_to(5); - - // it's external "turn" again, though since public is empty that doesn't really matter - assert_eq!( - Democracy::referendum_info(2), - Some(ReferendumInfo { - end: 6, - proposal: set_balance_proposal(3), - threshold: VoteThreshold::SuperMajorityApprove, - delay: 2 - }) - ); - // replenish external - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(5)), - )); - - fast_forward_to(7); - - // external goes again because there's no public waiting. - assert_eq!( - Democracy::referendum_info(3), - Some(ReferendumInfo { - end: 8, - proposal: set_balance_proposal(5), - threshold: VoteThreshold::SuperMajorityApprove, - delay: 2 - }) - ); - // replenish both - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(7)), - )); - assert_ok!(propose_set_balance(6, 4, 2)); - - fast_forward_to(9); - - // public goes now since external went last time. - assert_eq!( - Democracy::referendum_info(4), - Some(ReferendumInfo { - end: 10, - proposal: set_balance_proposal(4), - threshold: VoteThreshold::SuperMajorityApprove, - delay: 2 - }) - ); - // replenish public again - assert_ok!(propose_set_balance(6, 6, 2)); - // cancel external - let h = BlakeTwo256::hash_of(&set_balance_proposal(7)); - assert_ok!(Democracy::veto_external(Origin::signed(3), h)); - - fast_forward_to(11); - - // public goes again now since there's no external waiting. - assert_eq!( - Democracy::referendum_info(5), - Some(ReferendumInfo { - end: 12, - proposal: set_balance_proposal(6), - threshold: VoteThreshold::SuperMajorityApprove, - delay: 2 - }) - ); - }); - } - - - #[test] - fn emergency_cancel_should_work() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - let r = Democracy::inject_referendum( - 2, - set_balance_proposal(2), - VoteThreshold::SuperMajorityApprove, - 2 - ).unwrap(); - assert!(Democracy::referendum_info(r).is_some()); - - assert_noop!(Democracy::emergency_cancel(Origin::signed(3), r), "Invalid origin"); - assert_ok!(Democracy::emergency_cancel(Origin::signed(4), r)); - assert!(Democracy::referendum_info(r).is_none()); - - // some time later... - - let r = Democracy::inject_referendum( - 2, - set_balance_proposal(2), - VoteThreshold::SuperMajorityApprove, - 2 - ).unwrap(); - assert!(Democracy::referendum_info(r).is_some()); - assert_noop!(Democracy::emergency_cancel(Origin::signed(4), r), "cannot cancel the same proposal twice"); - }); - } - - #[test] - fn veto_external_works() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(2)), - )); - assert!(>::exists()); - - let h = BlakeTwo256::hash_of(&set_balance_proposal(2)); - assert_ok!(Democracy::veto_external(Origin::signed(3), h.clone())); - // cancelled. - assert!(!>::exists()); - // fails - same proposal can't be resubmitted. - assert_noop!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(2)), - ), "proposal still blacklisted"); - - fast_forward_to(1); - // fails as we're still in cooloff period. - assert_noop!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(2)), - ), "proposal still blacklisted"); - - fast_forward_to(2); - // works; as we're out of the cooloff period. - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(2)), - )); - assert!(>::exists()); - - // 3 can't veto the same thing twice. - assert_noop!( - Democracy::veto_external(Origin::signed(3), h.clone()), - "identity may not veto a proposal twice" - ); - - // 4 vetoes. - assert_ok!(Democracy::veto_external(Origin::signed(4), h.clone())); - // cancelled again. - assert!(!>::exists()); - - fast_forward_to(3); - // same proposal fails as we're still in cooloff - assert_noop!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(2)), - ), "proposal still blacklisted"); - // different proposal works fine. - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(3)), - )); - }); - } - - #[test] - fn external_referendum_works() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_noop!(Democracy::external_propose( - Origin::signed(1), - Box::new(set_balance_proposal(2)), - ), "Invalid origin"); - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(2)), - )); - assert_noop!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(1)), - ), "proposal already made"); - fast_forward_to(1); - assert_eq!( - Democracy::referendum_info(0), - Some(ReferendumInfo { - end: 2, - proposal: set_balance_proposal(2), - threshold: VoteThreshold::SuperMajorityApprove, - delay: 2 - }) - ); - }); - } - - #[test] - fn external_majority_referendum_works() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_noop!(Democracy::external_propose_majority( - Origin::signed(1), - Box::new(set_balance_proposal(2)) - ), "Invalid origin"); - assert_ok!(Democracy::external_propose_majority( - Origin::signed(3), - Box::new(set_balance_proposal(2)) - )); - fast_forward_to(1); - assert_eq!( - Democracy::referendum_info(0), - Some(ReferendumInfo { - end: 2, - proposal: set_balance_proposal(2), - threshold: VoteThreshold::SimpleMajority, - delay: 2, - }) - ); - }); - } - - #[test] - fn external_default_referendum_works() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_noop!(Democracy::external_propose_default( - Origin::signed(3), - Box::new(set_balance_proposal(2)) - ), "Invalid origin"); - assert_ok!(Democracy::external_propose_default( - Origin::signed(1), - Box::new(set_balance_proposal(2)) - )); - fast_forward_to(1); - assert_eq!( - Democracy::referendum_info(0), - Some(ReferendumInfo { - end: 2, - proposal: set_balance_proposal(2), - threshold: VoteThreshold::SuperMajorityAgainst, - delay: 2, - }) - ); - }); - } - - #[test] - fn fast_track_referendum_works() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - let h = BlakeTwo256::hash_of(&set_balance_proposal(2)); - assert_noop!(Democracy::fast_track(Origin::signed(5), h, 3, 2), "no proposal made"); - assert_ok!(Democracy::external_propose_majority( - Origin::signed(3), - Box::new(set_balance_proposal(2)) - )); - assert_noop!(Democracy::fast_track(Origin::signed(1), h, 3, 2), "Invalid origin"); - assert_ok!(Democracy::fast_track(Origin::signed(5), h, 0, 0)); - assert_eq!( - Democracy::referendum_info(0), - Some(ReferendumInfo { - end: 1, - proposal: set_balance_proposal(2), - threshold: VoteThreshold::SimpleMajority, - delay: 0, - }) - ); - }); - } - - #[test] - fn fast_track_referendum_fails_when_no_simple_majority() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - let h = BlakeTwo256::hash_of(&set_balance_proposal(2)); - assert_ok!(Democracy::external_propose( - Origin::signed(2), - Box::new(set_balance_proposal(2)) - )); - assert_noop!( - Democracy::fast_track(Origin::signed(5), h, 3, 2), - "next external proposal not simple majority" - ); - }); - } - - #[test] - fn locked_for_should_work() { - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert_ok!(propose_set_balance(1, 2, 2)); - assert_ok!(propose_set_balance(1, 4, 4)); - assert_ok!(propose_set_balance(1, 3, 3)); - assert_eq!(Democracy::locked_for(0), Some(2)); - assert_eq!(Democracy::locked_for(1), Some(4)); - assert_eq!(Democracy::locked_for(2), Some(3)); - }); - } - - #[test] - fn single_proposal_should_work() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_ok!(propose_set_balance(1, 2, 1)); - assert!(Democracy::referendum_info(0).is_none()); - - // end of 0 => next referendum scheduled. - fast_forward_to(1); - - let r = 0; - assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); - - assert_eq!(Democracy::referendum_count(), 1); - assert_eq!( - Democracy::referendum_info(0), - Some(ReferendumInfo { - end: 2, - proposal: set_balance_proposal(2), - threshold: VoteThreshold::SuperMajorityApprove, - delay: 2 - }) - ); - assert_eq!(Democracy::voters_for(r), vec![1]); - assert_eq!(Democracy::vote_of((r, 1)), AYE); - assert_eq!(Democracy::tally(r), (1, 0, 1)); - - fast_forward_to(2); - - // referendum still running - assert!(Democracy::referendum_info(0).is_some()); - - // referendum runs during 1 and 2, ends @ end of 2. - fast_forward_to(3); - - assert!(Democracy::referendum_info(0).is_none()); - assert_eq!(Democracy::dispatch_queue(4), vec![ - Some((set_balance_proposal(2), 0)) - ]); - - // referendum passes and wait another two blocks for enactment. - fast_forward_to(5); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn cancel_queued_should_work() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_ok!(propose_set_balance(1, 2, 1)); - - // end of 0 => next referendum scheduled. - fast_forward_to(1); - - assert_ok!(Democracy::vote(Origin::signed(1), 0, AYE)); - - fast_forward_to(3); - - assert_eq!(Democracy::dispatch_queue(4), vec![ - Some((set_balance_proposal(2), 0)) - ]); - - assert_noop!(Democracy::cancel_queued(Origin::ROOT, 3, 0, 0), "proposal not found"); - assert_noop!(Democracy::cancel_queued(Origin::ROOT, 4, 1, 0), "proposal not found"); - assert_ok!(Democracy::cancel_queued(Origin::ROOT, 4, 0, 0)); - assert_eq!(Democracy::dispatch_queue(4), vec![None]); - }); - } - - #[test] - fn proxy_should_work() { - new_test_ext().execute_with(|| { - assert_eq!(Democracy::proxy(10), None); - assert_ok!(Democracy::set_proxy(Origin::signed(1), 10)); - assert_eq!(Democracy::proxy(10), Some(1)); - - // Can't set when already set. - assert_noop!(Democracy::set_proxy(Origin::signed(2), 10), "already a proxy"); - - // But this works because 11 isn't proxying. - assert_ok!(Democracy::set_proxy(Origin::signed(2), 11)); - assert_eq!(Democracy::proxy(10), Some(1)); - assert_eq!(Democracy::proxy(11), Some(2)); - - // 2 cannot fire 1's proxy: - assert_noop!(Democracy::remove_proxy(Origin::signed(2), 10), "wrong proxy"); - - // 1 fires his proxy: - assert_ok!(Democracy::remove_proxy(Origin::signed(1), 10)); - assert_eq!(Democracy::proxy(10), None); - assert_eq!(Democracy::proxy(11), Some(2)); - - // 11 resigns: - assert_ok!(Democracy::resign_proxy(Origin::signed(11))); - assert_eq!(Democracy::proxy(10), None); - assert_eq!(Democracy::proxy(11), None); - }); - } - - #[test] - fn single_proposal_should_work_with_proxy() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_ok!(propose_set_balance(1, 2, 1)); - - fast_forward_to(1); - let r = 0; - assert_ok!(Democracy::set_proxy(Origin::signed(1), 10)); - assert_ok!(Democracy::proxy_vote(Origin::signed(10), r, AYE)); - - assert_eq!(Democracy::voters_for(r), vec![1]); - assert_eq!(Democracy::vote_of((r, 1)), AYE); - assert_eq!(Democracy::tally(r), (1, 0, 1)); - - fast_forward_to(5); - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn single_proposal_should_work_with_delegation() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - - assert_ok!(propose_set_balance(1, 2, 1)); - - fast_forward_to(1); - - // Delegate vote. - assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); - - let r = 0; - 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); - // Delegated vote is counted. - assert_eq!(Democracy::tally(r), (3, 0, 3)); - - fast_forward_to(5); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn single_proposal_should_work_with_cyclic_delegation() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - - assert_ok!(propose_set_balance(1, 2, 1)); - - fast_forward_to(1); - - // Check behavior with cycle. - assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); - assert_ok!(Democracy::delegate(Origin::signed(3), 2, Conviction::max_value())); - assert_ok!(Democracy::delegate(Origin::signed(1), 3, Conviction::max_value())); - let r = 0; - assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); - assert_eq!(Democracy::voters_for(r), vec![1]); - - // Delegated vote is counted. - assert_eq!(Democracy::tally(r), (6, 0, 6)); - - fast_forward_to(5); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - /// If transactor already voted, delegated vote is overwriten. - fn single_proposal_should_work_with_vote_and_delegation() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - - assert_ok!(propose_set_balance(1, 2, 1)); - - fast_forward_to(1); - - let r = 0; - assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); - // Vote. - assert_ok!(Democracy::vote(Origin::signed(2), r, AYE)); - // Delegate vote. - assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); - assert_eq!(Democracy::voters_for(r), vec![1, 2]); - assert_eq!(Democracy::vote_of((r, 1)), AYE); - // Delegated vote is not counted. - assert_eq!(Democracy::tally(r), (3, 0, 3)); - - fast_forward_to(5); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn single_proposal_should_work_with_undelegation() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - - assert_ok!(propose_set_balance(1, 2, 1)); - - // Delegate and undelegate vote. - assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); - assert_ok!(Democracy::undelegate(Origin::signed(2))); - - fast_forward_to(1); - let r = 0; - assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); - - assert_eq!(Democracy::referendum_count(), 1); - assert_eq!(Democracy::voters_for(r), vec![1]); - assert_eq!(Democracy::vote_of((r, 1)), AYE); - - // Delegated vote is not counted. - assert_eq!(Democracy::tally(r), (1, 0, 1)); - - fast_forward_to(5); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - /// If transactor voted, delegated vote is overwriten. - fn single_proposal_should_work_with_delegation_and_vote() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - - assert_ok!(propose_set_balance(1, 2, 1)); - - fast_forward_to(1); - let r = 0; - - assert_ok!(Democracy::vote(Origin::signed(1), r, AYE)); - - // Delegate vote. - assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value())); - - // Vote. - assert_ok!(Democracy::vote(Origin::signed(2), r, AYE)); - - assert_eq!(Democracy::referendum_count(), 1); - assert_eq!(Democracy::voters_for(r), vec![1, 2]); - assert_eq!(Democracy::vote_of((r, 1)), AYE); - - // Delegated vote is not counted. - assert_eq!(Democracy::tally(r), (3, 0, 3)); - - fast_forward_to(5); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn deposit_for_proposals_should_be_taken() { - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert_ok!(propose_set_balance(1, 2, 5)); - assert_ok!(Democracy::second(Origin::signed(2), 0)); - 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); - }); - } - - #[test] - fn deposit_for_proposals_should_be_returned() { - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert_ok!(propose_set_balance(1, 2, 5)); - assert_ok!(Democracy::second(Origin::signed(2), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - assert_ok!(Democracy::second(Origin::signed(5), 0)); - fast_forward_to(3); - assert_eq!(Balances::free_balance(&1), 10); - assert_eq!(Balances::free_balance(&2), 20); - assert_eq!(Balances::free_balance(&5), 50); - }); - } - - #[test] - fn proposal_with_deposit_below_minimum_should_not_work() { - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert_noop!(propose_set_balance(1, 2, 0), "value too low"); - }); - } - - #[test] - fn poor_proposer_should_not_work() { - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert_noop!(propose_set_balance(1, 2, 11), "proposer\'s balance too low"); - }); - } - - #[test] - fn poor_seconder_should_not_work() { - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert_ok!(propose_set_balance(2, 2, 11)); - assert_noop!(Democracy::second(Origin::signed(1), 0), "seconder\'s balance too low"); - }); - } - - #[test] - fn runners_up_should_come_after() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - assert_ok!(propose_set_balance(1, 2, 2)); - assert_ok!(propose_set_balance(1, 4, 4)); - assert_ok!(propose_set_balance(1, 3, 3)); - fast_forward_to(1); - assert_ok!(Democracy::vote(Origin::signed(1), 0, AYE)); - fast_forward_to(3); - assert_ok!(Democracy::vote(Origin::signed(1), 1, AYE)); - fast_forward_to(5); - assert_ok!(Democracy::vote(Origin::signed(1), 2, AYE)); - }); - } - - #[test] - fn simple_passing_should_work() { - new_test_ext().execute_with(|| { - 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, AYE)); - - assert_eq!(Democracy::voters_for(r), vec![1]); - assert_eq!(Democracy::vote_of((r, 1)), AYE); - assert_eq!(Democracy::tally(r), (1, 0, 1)); - - next_block(); - next_block(); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn cancel_referendum_should_work() { - new_test_ext().execute_with(|| { - 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, AYE)); - assert_ok!(Democracy::cancel_referendum(Origin::ROOT, r.into())); - - next_block(); - next_block(); - - assert_eq!(Balances::free_balance(&42), 0); - }); - } - - #[test] - fn simple_failing_should_work() { - new_test_ext().execute_with(|| { - 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, NAY)); - - assert_eq!(Democracy::voters_for(r), vec![1]); - assert_eq!(Democracy::vote_of((r, 1)), NAY); - assert_eq!(Democracy::tally(r), (0, 1, 1)); - - next_block(); - next_block(); - - assert_eq!(Balances::free_balance(&42), 0); - }); - } - - #[test] - fn controversial_voting_should_work() { - new_test_ext().execute_with(|| { - 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, BIG_AYE)); - assert_ok!(Democracy::vote(Origin::signed(2), r, BIG_NAY)); - assert_ok!(Democracy::vote(Origin::signed(3), r, BIG_NAY)); - assert_ok!(Democracy::vote(Origin::signed(4), r, BIG_AYE)); - assert_ok!(Democracy::vote(Origin::signed(5), r, BIG_NAY)); - assert_ok!(Democracy::vote(Origin::signed(6), r, BIG_AYE)); - - assert_eq!(Democracy::tally(r), (110, 100, 210)); - - next_block(); - next_block(); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn delayed_enactment_should_work() { - new_test_ext().execute_with(|| { - 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, 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), (21, 0, 21)); - - next_block(); - assert_eq!(Balances::free_balance(&42), 0); - - next_block(); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn controversial_low_turnout_voting_should_work() { - new_test_ext().execute_with(|| { - 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, BIG_NAY)); - assert_ok!(Democracy::vote(Origin::signed(6), r, BIG_AYE)); - - assert_eq!(Democracy::tally(r), (60, 50, 110)); - - next_block(); - next_block(); - - assert_eq!(Balances::free_balance(&42), 0); - }); - } - - #[test] - fn passing_low_turnout_voting_should_work() { - new_test_ext().execute_with(|| { - assert_eq!(Balances::free_balance(&42), 0); - assert_eq!(Balances::total_issuance(), 210); - - 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, BIG_AYE)); - assert_ok!(Democracy::vote(Origin::signed(5), r, BIG_NAY)); - assert_ok!(Democracy::vote(Origin::signed(6), r, BIG_AYE)); - - assert_eq!(Democracy::tally(r), (100, 50, 150)); - - next_block(); - next_block(); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn lock_voting_should_work() { - new_test_ext().execute_with(|| { - System::set_block_number(0); - let r = Democracy::inject_referendum( - 1, - set_balance_proposal(2), - VoteThreshold::SuperMajorityApprove, - 0 - ).unwrap(); - assert_ok!(Democracy::vote(Origin::signed(1), r, Vote { - aye: false, - conviction: Conviction::Locked5x - })); - assert_ok!(Democracy::vote(Origin::signed(2), r, Vote { - aye: true, - conviction: Conviction::Locked4x - })); - assert_ok!(Democracy::vote(Origin::signed(3), r, Vote { - aye: true, - conviction: Conviction::Locked3x - })); - assert_ok!(Democracy::vote(Origin::signed(4), r, Vote { - aye: true, - conviction: Conviction::Locked2x - })); - assert_ok!(Democracy::vote(Origin::signed(5), r, Vote { - aye: false, - conviction: Conviction::Locked1x - })); - - assert_eq!(Democracy::tally(r), (250, 100, 150)); - - fast_forward_to(2); - - assert_eq!(Balances::locks(1), vec![]); - assert_eq!(Balances::locks(2), vec![BalanceLock { - id: DEMOCRACY_ID, - amount: u64::max_value(), - until: 17, - reasons: WithdrawReason::Transfer.into() - }]); - assert_eq!(Balances::locks(3), vec![BalanceLock { - id: DEMOCRACY_ID, - amount: u64::max_value(), - until: 9, - reasons: WithdrawReason::Transfer.into() - }]); - assert_eq!(Balances::locks(4), vec![BalanceLock { - id: DEMOCRACY_ID, - amount: u64::max_value(), - until: 5, - reasons: WithdrawReason::Transfer.into() - }]); - assert_eq!(Balances::locks(5), vec![]); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } - - #[test] - fn lock_voting_should_work_with_delegation() { - new_test_ext().execute_with(|| { - 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, Vote { - aye: false, - conviction: Conviction::Locked5x - })); - assert_ok!(Democracy::vote(Origin::signed(2), r, Vote { - aye: true, - conviction: Conviction::Locked4x - })); - assert_ok!(Democracy::vote(Origin::signed(3), r, Vote { - aye: true, - conviction: Conviction::Locked3x - })); - assert_ok!(Democracy::delegate(Origin::signed(4), 2, Conviction::Locked2x)); - assert_ok!(Democracy::vote(Origin::signed(5), r, Vote { - aye: false, - conviction: Conviction::Locked1x - })); - - assert_eq!(Democracy::tally(r), (250, 100, 150)); - - next_block(); - next_block(); - - assert_eq!(Balances::free_balance(&42), 2); - }); - } -} diff --git a/srml/elections-phragmen/Cargo.toml b/srml/elections-phragmen/Cargo.toml deleted file mode 100644 index 02898fc754f2e..0000000000000 --- a/srml/elections-phragmen/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "srml-elections-phragmen" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -phragmen = { package = "substrate-phragmen", path = "../../core/phragmen", default-features = false } -srml-support = { path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } - -[dev-dependencies] -hex-literal = "0.2.1" -balances = { package = "srml-balances", path = "../balances" } - -[features] -default = ["std"] -std = [ - "codec/std", - "primitives/std", - "serde", - "runtime_io/std", - "srml-support/std", - "sr-primitives/std", - "phragmen/std", - "system/std", - "rstd/std", -] diff --git a/srml/elections-phragmen/src/lib.rs b/srml/elections-phragmen/src/lib.rs deleted file mode 100644 index f56c5a4ec3cb5..0000000000000 --- a/srml/elections-phragmen/src/lib.rs +++ /dev/null @@ -1,1639 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Phragmen Election Module. -//! -//! An election module based on sequential phragmen. -//! -//! ### Term and Round -//! -//! The election happens in _rounds_: every `N` blocks, all previous members are retired and a new -//! set is elected (which may or may not have an intersection with the previous set). Each round -//! lasts for some number of blocks defined by `TermDuration` storage item. The words _term_ and -//! _round_ can be used interchangeably in this context. -//! -//! `TermDuration` might change during a round. This can shorten or extend the length of the round. -//! The next election round's block number is never stored but rather always checked on the fly. -//! Based on the current block number and `TermDuration`, the condition `BlockNumber % TermDuration -//! == 0` being satisfied will always trigger a new election round. -//! -//! ### Voting -//! -//! Voters can vote for any set of the candidates by providing a list of account ids. Invalid votes -//! (voting for non-candidates) are ignored during election. Yet, a voter _might_ vote for a future -//! candidate. Voters reserve a bond as they vote. Each vote defines a `value`. This amount is -//! locked from the account of the voter and indicates the weight of the vote. Voters can update -//! their votes at any time by calling `vote()` again. This keeps the bond untouched but can -//! optionally change the locked `value`. After a round, votes are kept and might still be valid for -//! further rounds. A voter is responsible for calling `remove_voter` once they are done to have -//! their bond back and remove the lock. -//! -//! Voters also report other voters as being defunct to earn their bond. A voter is defunct once all -//! of the candidates that they have voted for are neither a valid candidate anymore nor a member. -//! Upon reporting, if the target voter is actually defunct, the reporter will be rewarded by the -//! voting bond of the target. The target will lose their bond and get removed. If the target is not -//! defunct, the reporter is slashed and removed. To prevent being reported, voters should manually -//! submit a `remove_voter()` as soon as they are in the defunct state. -//! -//! ### Candidacy and Members -//! -//! Candidates also reserve a bond as they submit candidacy. A candidate cannot take their candidacy -//! back. A candidate can end up in one of the below situations: -//! - **Winner**: A winner is kept as a _member_. They must still have a bond in reserve and they -//! are automatically counted as a candidate for the next election. -//! - **Loser**: Any of the candidate who are not a winner are left as losers. A loser might be an -//! _outgoing member_, meaning that they are an active member who failed to keep their spot. In -//! this case, the outgoing member will get their bond back. Otherwise, the bond is slashed from -//! the loser candidate. -//! - **Runner-up**: Runners-up are the best candidates immediately after the winners. The number -//! of runners_up to keep is configurable. Runners-up are used, in order that they are elected, -//! as replacements when a candidate is kicked by `remove_member()`. -//! -//! Note that with the members being the default candidates for the next round and votes persisting -//! in storage, the election system is entirely stable given no further input. This means that if -//! the system has a particular set of candidates `C` and voters `V` that lead to a set of members -//! `M` being elected, as long as `V` and `C` don't remove their candidacy and votes, `M` will keep -//! being re-elected at the end of each round. -//! -//! ### Module Information -//! -//! - [`election_phragmen::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! - [`Module`](./struct.Module.html) - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::prelude::*; -use sr_primitives::{print, traits::{Zero, StaticLookup, Bounded, Convert}}; -use sr_primitives::weights::SimpleDispatchInfo; -use srml_support::{ - decl_storage, decl_event, ensure, decl_module, dispatch, - traits::{ - Currency, Get, LockableCurrency, LockIdentifier, ReservableCurrency, WithdrawReasons, - ChangeMembers, OnUnbalanced, - } -}; -use system::{self, ensure_signed, ensure_root}; - -const MODULE_ID: LockIdentifier = *b"phrelect"; - -/// The maximum votes allowed per voter. -pub const MAXIMUM_VOTE: usize = 16; - -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -type NegativeImbalanceOf = - <::Currency as Currency<::AccountId>>::NegativeImbalance; - -pub trait Trait: system::Trait { - /// The overarching event type.c - type Event: From> + Into<::Event>; - - /// The currency that people are electing with. - type Currency: - LockableCurrency + - ReservableCurrency; - - /// What to do when the members change. - type ChangeMembers: ChangeMembers; - - /// Convert a balance into a number used for election calculation. - /// This must fit into a `u64` but is allowed to be sensibly lossy. - type CurrencyToVote: Convert, u64> + Convert>; - - /// How much should be locked up in order to submit one's candidacy. - type CandidacyBond: Get>; - - /// How much should be locked up in order to be able to submit votes. - type VotingBond: Get>; - - /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner-up) - type LoserCandidate: OnUnbalanced>; - - /// Handler for the unbalanced reduction when a reporter has submitted a bad defunct report. - type BadReport: OnUnbalanced>; - - /// Handler for the unbalanced reduction when a member has been kicked. - type KickedMember: OnUnbalanced>; -} - -decl_storage! { - trait Store for Module as PhragmenElection { - // ---- parameters - /// Number of members to elect. - pub DesiredMembers get(fn desired_members) config(): u32; - /// Number of runners_up to keep. - pub DesiredRunnersUp get(fn desired_runners_up) config(): u32; - /// How long each seat is kept. This defines the next block number at which an election - /// round will happen. If set to zero, no elections are ever triggered and the module will - /// be in passive mode. In that case only a member set defined in at genesis can exist. - pub TermDuration get(fn term_duration) config(): T::BlockNumber; - - // ---- State - /// The current elected membership. Sorted based on account id. - pub Members get(fn members) config(): Vec; - /// The current runners_up. Sorted based on low to high merit (worse to best runner). - pub RunnersUp get(fn runners_up): Vec; - /// The total number of vote rounds that have happened, excluding the upcoming one. - pub ElectionRounds get(fn election_rounds): u32 = Zero::zero(); - - /// Votes of a particular voter, with the round index of the votes. - pub VotesOf get(fn votes_of): linked_map T::AccountId => Vec; - /// Locked stake of a voter. - pub StakeOf get(fn stake_of): map T::AccountId => BalanceOf; - - /// The present candidate list. Sorted based on account id. A current member can never enter - /// this vector and is always implicitly assumed to be a candidate. - pub Candidates get(fn candidates): Vec; - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - const CandidacyBond: BalanceOf = T::CandidacyBond::get(); - const VotingBond: BalanceOf = T::VotingBond::get(); - - /// Vote for a set of candidates for the upcoming round of election. - /// - /// The `votes` should: - /// - not be empty. - /// - be less than the number of candidates. - /// - /// Upon voting, `value` units of `who`'s balance is locked and a bond amount is reserved. - /// It is the responsibility of the caller to not place all of their balance into the lock - /// and keep some for further transactions. - /// - /// # - /// #### State - /// Reads: O(1) - /// Writes: O(V) given `V` votes. V is bounded by 16. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(100_000)] - fn vote(origin, votes: Vec, #[compact] value: BalanceOf) { - let who = ensure_signed(origin)?; - - let candidates_count = >::decode_len().unwrap_or(0) as usize; - let members_count = >::decode_len().unwrap_or(0) as usize; - // addition is valid: candidates and members never overlap. - let allowed_votes = candidates_count + members_count; - - ensure!(!allowed_votes.is_zero(), "cannot vote when no candidates or members exist"); - ensure!(votes.len() <= allowed_votes, "cannot vote more than candidates"); - ensure!(votes.len() <= MAXIMUM_VOTE, "cannot vote more than maximum allowed"); - - ensure!(!votes.is_empty(), "must vote for at least one candidate."); - ensure!( - value > T::Currency::minimum_balance(), - "cannot vote with stake less than minimum balance" - ); - - if !Self::is_voter(&who) { - // first time voter. Reserve bond. - T::Currency::reserve(&who, T::VotingBond::get()) - .map_err(|_| "voter can not pay voting bond")?; - } - // Amount to be locked up. - let locked_balance = value.min(T::Currency::total_balance(&who)); - - // lock - T::Currency::set_lock( - MODULE_ID, - &who, - locked_balance, - T::BlockNumber::max_value(), - WithdrawReasons::all(), - ); - >::insert(&who, locked_balance); - >::insert(&who, votes); - } - - /// Remove `origin` as a voter. This removes the lock and returns the bond. - /// - /// # - /// #### State - /// Reads: O(1) - /// Writes: O(1) - /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] - fn remove_voter(origin) { - let who = ensure_signed(origin)?; - - ensure!(Self::is_voter(&who), "must be a voter"); - - Self::do_remove_voter(&who, true); - } - - /// Report `target` for being an defunct voter. In case of a valid report, the reporter is - /// rewarded by the bond amount of `target`. Otherwise, the reporter itself is removed and - /// their bond is slashed. - /// - /// A defunct voter is defined to be: - /// - a voter whose current submitted votes are all invalid. i.e. all of them are no - /// longer a candidate nor an active member. - /// - /// # - /// #### State - /// Reads: O(NLogM) given M current candidates and N votes for `target`. - /// Writes: O(1) - /// # - #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] - fn report_defunct_voter(origin, target: ::Source) { - let reporter = ensure_signed(origin)?; - let target = T::Lookup::lookup(target)?; - - ensure!(reporter != target, "cannot report self"); - ensure!(Self::is_voter(&reporter), "reporter must be a voter"); - - // Checking if someone is a candidate and a member here is O(LogN), making the whole - // function O(MLonN) with N candidates in total and M of them being voted by `target`. - // We could easily add another mapping to be able to check if someone is a candidate in - // `O(1)` but that would make the process of removing candidates at the end of each - // round slightly harder. Note that for now we have a bound of number of votes (`N`). - let valid = Self::is_defunct_voter(&target); - if valid { - // reporter will get the voting bond of the target - T::Currency::repatriate_reserved(&target, &reporter, T::VotingBond::get())?; - // remove the target. They are defunct. - Self::do_remove_voter(&target, false); - } else { - // slash the bond of the reporter. - let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0; - T::BadReport::on_unbalanced(imbalance); - // remove the reporter. - Self::do_remove_voter(&reporter, false); - } - Self::deposit_event(RawEvent::VoterReported(target, reporter, valid)); - } - - - /// Submit oneself for candidacy. - /// - /// A candidate will either: - /// - Lose at the end of the term and forfeit their deposit. - /// - Win and become a member. Members will eventually get their stash back. - /// - Become a runner-up. Runners-ups are reserved members in case one gets forcefully - /// removed. - /// - /// # - /// #### State - /// Reads: O(LogN) Given N candidates. - /// Writes: O(1) - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn submit_candidacy(origin) { - let who = ensure_signed(origin)?; - - let is_candidate = Self::is_candidate(&who); - ensure!(is_candidate.is_err(), "duplicate candidate submission"); - // assured to be an error, error always contains the index. - let index = is_candidate.unwrap_err(); - - ensure!(!Self::is_member(&who), "member cannot re-submit candidacy"); - - T::Currency::reserve(&who, T::CandidacyBond::get()) - .map_err(|_| "candidate does not have enough funds")?; - - >::mutate(|c| c.insert(index, who)); - } - - /// Set the desired member count. Changes will be effective at the beginning of next round. - /// - /// # - /// #### State - /// Reads: O(1) - /// Writes: O(1) - /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_desired_member_count(origin, #[compact] count: u32) { - ensure_root(origin)?; - DesiredMembers::put(count); - } - - /// Remove a particular member from the set. This is effective immediately. - /// - /// If a runner-up is available, then the best runner-up will be removed and replaces the - /// outgoing member. Otherwise, a new phragmen round is started. - /// - /// Note that this does not affect the designated block number of the next election. - /// - /// # - /// #### State - /// Reads: O(do_phragmen) - /// Writes: O(do_phragmen) - /// # - #[weight = SimpleDispatchInfo::FixedOperational(2_000_000)] - fn remove_member(origin, who: ::Source) { - ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; - - let mut members = Self::members(); - if let Ok(index) = members.binary_search(&who) { - // remove, slash, emit event. - members.remove(index); - let (imbalance, _) = T::Currency::slash_reserved(&who, T::CandidacyBond::get()); - T::KickedMember::on_unbalanced(imbalance); - Self::deposit_event(RawEvent::MemberKicked(who.clone())); - - let mut runners_up = Self::runners_up(); - if let Some(replacement) = runners_up.pop() { - // replace the outgoing with the best runner up. - if let Err(index) = members.binary_search(&replacement) { - members.insert(index, replacement.clone()); - ElectionRounds::mutate(|v| *v += 1); - T::ChangeMembers::change_members_sorted(&[replacement], &[who], &members); - } - // else it would mean that the runner up was already a member. This cannot - // happen. If it does, not much that we can do about it. - - >::put(members); - >::put(runners_up); - } else { - // update `Members` storage -- `do_phragmen` adds this to the candidate list. - >::put(members); - // trigger a new phragmen. grab a cup of coffee. This might take a while. - Self::do_phragmen(); - } - } - } - - /// Set the duration of each term. This will affect the next election's block number. - /// - /// # - /// #### State - /// Reads: O(1) - /// Writes: O(1) - /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_term_duration(origin, #[compact] count: T::BlockNumber) { - ensure_root(origin)?; - >::put(count); - } - - /// What to do at the end of each block. Checks if an election needs to happen or not. - fn on_initialize(n: T::BlockNumber) { - if let Err(e) = Self::end_block(n) { - print("Guru meditation"); - print(e); - } - } - } -} - -decl_event!( - pub enum Event where ::AccountId { - /// A new term with new members. This indicates that enough candidates existed, not that - /// enough have has been elected. The inner value must be examined for this purpose. - NewTerm(Vec), - /// No (or not enough) candidates existed for this round. - EmptyTerm, - /// A member has been removed. This should always be followed by either `NewTerm` ot - /// `EmptyTerm`. - MemberKicked(AccountId), - /// A voter (first element) was reported (byt the second element) with the the report being - /// successful or not (third element). - VoterReported(AccountId, AccountId, bool), - } -); - -impl Module { - /// Check if `who` is a candidate. It returns the insert index if the element does not exists as - /// an error. - /// - /// State: O(LogN) given N candidates. - fn is_candidate(who: &T::AccountId) -> Result<(), usize> { - Self::candidates().binary_search(who).map(|_| ()) - } - - /// Check if `who` is a voter. It may or may not be a _current_ one. - /// - /// State: O(1). - fn is_voter(who: &T::AccountId) -> bool { - >::exists(who) - } - - /// Check if `who` is currently an active member. - /// - /// Limited number of members. Binary search. Constant time factor. O(1) - fn is_member(who: &T::AccountId) -> bool { - Self::members().binary_search(who).is_ok() - } - - /// Check if `who` is a defunct voter. - /// - /// Note that false is returned if `who` is not a voter at all. - /// - /// O(NLogM) with M candidates and `who` having voted for `N` of them. - fn is_defunct_voter(who: &T::AccountId) -> bool { - if Self::is_voter(who) { - Self::votes_of(who) - .iter() - .all(|v| !Self::is_member(v) && !Self::is_candidate(v).is_ok()) - } else { - false - } - } - - /// Remove a certain someone as a voter. - /// - /// This will clean always clean the storage associated with the voter, and remove the balance - /// lock. Optionally, it would also return the reserved voting bond if indicated by `unreserve`. - fn do_remove_voter(who: &T::AccountId, unreserve: bool) { - // remove storage and lock. - >::remove(who); - >::remove(who); - T::Currency::remove_lock(MODULE_ID, who); - - if unreserve { - T::Currency::unreserve(who, T::VotingBond::get()); - } - } - - /// The locked stake of a voter. - fn locked_stake_of(who: &T::AccountId) -> BalanceOf { - Self::stake_of(who) - } - - /// Check there's nothing to do this block. - /// - /// Runs phragmen election and cleans all the previous candidate state. The voter state is NOT - /// cleaned and voters must themselves submit a transaction to retract. - fn end_block(block_number: T::BlockNumber) -> dispatch::Result { - if !Self::term_duration().is_zero() { - if (block_number % Self::term_duration()).is_zero() { - Self::do_phragmen(); - } - } - Ok(()) - } - - /// Run the phragmen election with all required side processes and state updates. - /// - /// Calls the appropriate `ChangeMembers` function variant internally. - /// - /// # - /// #### State - /// Reads: O(C + V*E) where C = candidates, V voters and E votes per voter exits. - /// Writes: O(M + R) with M desired members and R runners_up. - /// # - fn do_phragmen() { - let desired_seats = Self::desired_members() as usize; - let desired_runners_up = Self::desired_runners_up() as usize; - let num_to_elect = desired_runners_up + desired_seats; - - let mut candidates = Self::candidates(); - // candidates who explicitly called `submit_candidacy`. Only these folks are at the risk of - // losing their bond. - let mut exposed_candidates = candidates.clone(); - // current members are always a candidate for the next round as well. - // this is guaranteed to not create any duplicates. - candidates.append(&mut Self::members()); - // previous runners_up are also always candidates for the next round. - candidates.append(&mut Self::runners_up()); - // and exposed to being an outgoing in case they are no longer elected. - exposed_candidates.append(&mut Self::runners_up()); - - let voters_and_votes = >::enumerate() - .map(|(v, i)| (v, i)) - .collect::)>>(); - let maybe_phragmen_result = phragmen::elect::<_, _, _, T::CurrencyToVote>( - num_to_elect, - 0, - candidates, - voters_and_votes, - Self::locked_stake_of, - false, - ); - - let mut to_release_bond: Vec = Vec::with_capacity(desired_seats); - let old_members = >::take(); - if let Some(phragmen_result) = maybe_phragmen_result { - // filter out those who had literally no votes at all. - // AUDIT/NOTE: the need to do this is because all candidates, even those who have no - // vote are still considered by phragmen and when good candidates are scarce, then these - // cheap ones might get elected. We might actually want to remove the filter and allow - // zero-voted candidates to also make it to the membership set. - let new_set_with_approval = phragmen_result.winners; - let new_set = new_set_with_approval - .into_iter() - .filter_map(|(m, a)| if a.is_zero() { None } else { Some(m) } ) - .collect::>(); - - // split new set into winners and runner ups. - let split_point = desired_seats.min(new_set.len()); - let mut new_members = (&new_set[..split_point]).to_vec(); - let runners_up = &new_set[split_point..] - .into_iter() - .cloned() - .rev() - .collect::>(); - - // sort and save the members. - new_members.sort(); - >::put(&new_members); - - // save the runners as-is - >::put(runners_up); - - // report member changes. We compute diff because we need the outgoing list. - let (incoming, outgoing) = T::ChangeMembers::compute_members_diff( - &new_members, - &old_members - ); - T::ChangeMembers::change_members_sorted( - &incoming, - &outgoing.clone(), - &new_members - ); - - // unlike exposed_candidates, these are members who were in the list and no longer - // exist. They must get their bond back. - to_release_bond = outgoing.to_vec(); - - // Burn loser bond. members list is sorted. O(NLogM) (N candidates, M members) - // runner up list is not sorted. O(K*N) given K runner ups. Overall: O(NLogM + N*K) - exposed_candidates.into_iter().for_each(|c| { - // any candidate who is not a member and not a runner up. - if new_members.binary_search(&c).is_err() && !runners_up.contains(&c) - { - let (imbalance, _) = T::Currency::slash_reserved(&c, T::CandidacyBond::get()); - T::LoserCandidate::on_unbalanced(imbalance); - } - }); - Self::deposit_event(RawEvent::NewTerm(new_members.to_vec())); - } else { - Self::deposit_event(RawEvent::EmptyTerm); - } - - // unreserve the bond of all the outgoings. - to_release_bond.iter().for_each(|m| { - T::Currency::unreserve(&m, T::CandidacyBond::get()); - }); - - // clean candidates. - >::kill(); - - ElectionRounds::mutate(|v| *v += 1); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::cell::RefCell; - use srml_support::{assert_ok, assert_noop, parameter_types, assert_eq_uvec}; - use primitives::H256; - use sr_primitives::{ - Perbill, testing::Header, BuildStorage, - traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, - }; - use crate as elections; - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - - parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - } - - impl balances::Trait for Test { - type Balance = u64; - type OnNewAccount = (); - type OnFreeBalanceZero = (); - type Event = Event; - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - - parameter_types! { - pub const CandidacyBond: u64 = 3; - } - - thread_local! { - static VOTING_BOND: RefCell = RefCell::new(2); - static MEMBERS: RefCell> = RefCell::new(vec![]); - } - - pub struct VotingBond; - impl Get for VotingBond { - fn get() -> u64 { VOTING_BOND.with(|v| *v.borrow()) } - } - - pub struct TestChangeMembers; - impl ChangeMembers for TestChangeMembers { - fn change_members_sorted(_: &[u64], _: &[u64], _: &[u64]) {} - } - - /// Simple structure that exposes how u64 currency can be represented as... u64. - pub struct CurrencyToVoteHandler; - impl Convert for CurrencyToVoteHandler { - fn convert(x: u64) -> u64 { x } - } - impl Convert for CurrencyToVoteHandler { - fn convert(x: u128) -> u64 { - x as u64 - } - } - - impl Trait for Test { - type Event = Event; - type Currency = Balances; - type CurrencyToVote = CurrencyToVoteHandler; - type ChangeMembers = TestChangeMembers; - type CandidacyBond = CandidacyBond; - type VotingBond = VotingBond; - type LoserCandidate = (); - type KickedMember = (); - type BadReport = (); - } - - pub type Block = sr_primitives::generic::Block; - pub type UncheckedExtrinsic = sr_primitives::generic::UncheckedExtrinsic; - - srml_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Module, Call, Event}, - Balances: balances::{Module, Call, Event, Config}, - Elections: elections::{Module, Call, Event, Config}, - } - ); - - pub struct ExtBuilder { - balance_factor: u64, - voter_bond: u64, - term_duration: u64, - desired_runners_up: u32, - members: Vec, - } - - impl Default for ExtBuilder { - fn default() -> Self { - Self { - balance_factor: 1, - voter_bond: 2, - desired_runners_up: 0, - term_duration: 5, - members: vec![], - } - } - } - - impl ExtBuilder { - pub fn voter_bond(mut self, fee: u64) -> Self { - self.voter_bond = fee; - self - } - pub fn desired_runners_up(mut self, count: u32) -> Self { - self.desired_runners_up = count; - self - } - pub fn term_duration(mut self, duration: u64) -> Self { - self.term_duration = duration; - self - } - pub fn members(mut self, members: Vec) -> Self { - self.members = members; - self - } - pub fn build(self) -> runtime_io::TestExternalities { - VOTING_BOND.with(|v| *v.borrow_mut() = self.voter_bond); - GenesisConfig { - balances: Some(balances::GenesisConfig::{ - balances: vec![ - (1, 10 * self.balance_factor), - (2, 20 * self.balance_factor), - (3, 30 * self.balance_factor), - (4, 40 * self.balance_factor), - (5, 50 * self.balance_factor), - (6, 60 * self.balance_factor) - ], - vesting: vec![], - }), - elections: Some(elections::GenesisConfig::{ - members: self.members, - desired_members: 2, - desired_runners_up: self.desired_runners_up, - term_duration: self.term_duration, - }), - }.build_storage().unwrap().into() - } - } - - fn all_voters() -> Vec { - >::enumerate().map(|(v, _)| v).collect::>() - } - - fn balances(who: &u64) -> (u64, u64) { - (Balances::free_balance(who), Balances::reserved_balance(who)) - } - - fn has_lock(who: &u64) -> u64 { - let lock = Balances::locks(who)[0].clone(); - assert_eq!(lock.id, MODULE_ID); - lock.amount - } - - #[test] - fn params_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::desired_members(), 2); - assert_eq!(Elections::term_duration(), 5); - assert_eq!(Elections::election_rounds(), 0); - - assert_eq!(Elections::members(), vec![]); - assert_eq!(Elections::runners_up(), vec![]); - - assert_eq!(Elections::candidates(), vec![]); - assert_eq!(>::decode_len().unwrap(), 0); - assert!(Elections::is_candidate(&1).is_err()); - - assert_eq!(all_voters(), vec![]); - assert_eq!(Elections::votes_of(&1), vec![]); - }); - } - - #[test] - fn passive_module_should_work() { - ExtBuilder::default() - .term_duration(0) - .members(vec![1, 2, 3]) - .build() - .execute_with(|| - { - System::set_block_number(1); - assert_eq!(Elections::term_duration(), 0); - assert_eq!(Elections::desired_members(), 2); - assert_eq!(Elections::election_rounds(), 0); - - assert_eq!(Elections::members(), vec![1, 2, 3]); - assert_eq!(Elections::runners_up(), vec![]); - - assert_eq!(Elections::candidates(), vec![]); - assert_eq!(all_voters(), vec![]); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![1, 2, 3]); - assert_eq!(Elections::runners_up(), vec![]); - }); - } - - #[test] - fn simple_candidate_submission_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert!(Elections::is_candidate(&1).is_err()); - assert!(Elections::is_candidate(&2).is_err()); - - assert_eq!(balances(&1), (10, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_eq!(balances(&1), (7, 3)); - - assert_eq!(Elections::candidates(), vec![1]); - - assert!(Elections::is_candidate(&1).is_ok()); - assert!(Elections::is_candidate(&2).is_err()); - - assert_eq!(balances(&2), (20, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_eq!(balances(&2), (17, 3)); - - assert_eq!(Elections::candidates(), vec![1, 2]); - - assert!(Elections::is_candidate(&1).is_ok()); - assert!(Elections::is_candidate(&2).is_ok()); - }); - } - - #[test] - fn simple_candidate_submission_with_no_votes_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - - assert!(Elections::is_candidate(&1).is_ok()); - assert!(Elections::is_candidate(&2).is_ok()); - assert_eq!(Elections::candidates(), vec![1, 2]); - - assert_eq!(Elections::members(), vec![]); - assert_eq!(Elections::runners_up(), vec![]); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert!(Elections::is_candidate(&1).is_err()); - assert!(Elections::is_candidate(&2).is_err()); - assert_eq!(Elections::candidates(), vec![]); - - assert_eq!(Elections::members(), vec![]); - assert_eq!(Elections::runners_up(), vec![]); - }); - } - - #[test] - fn dupe_candidate_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_eq!(Elections::candidates(), vec![1]); - assert_noop!( - Elections::submit_candidacy(Origin::signed(1)), - "duplicate candidate submission" - ); - }); - } - - #[test] - fn member_candidacy_submission_should_not_work() { - // critically important to make sure that outgoing candidates and losers are not mixed up. - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![5]); - assert_eq!(Elections::runners_up(), vec![]); - assert_eq!(Elections::candidates(), vec![]); - - assert_noop!( - Elections::submit_candidacy(Origin::signed(5)), - "member cannot re-submit candidacy" - ); - }); - } - - #[test] - fn poor_candidate_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_noop!( - Elections::submit_candidacy(Origin::signed(7)), - "candidate does not have enough funds" - ); - }); - } - - #[test] - fn simple_voting_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(balances(&2), (20, 0)); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - - assert_eq!(balances(&2), (18, 2)); - assert_eq!(has_lock(&2), 20); - }); - } - - #[test] - fn can_vote_with_custom_stake() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(balances(&2), (20, 0)); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 12)); - - assert_eq!(balances(&2), (18, 2)); - assert_eq!(has_lock(&2), 12); - }); - } - - #[test] - fn can_update_votes_and_stake() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(balances(&2), (20, 0)); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - - assert_eq!(balances(&2), (18, 2)); - assert_eq!(has_lock(&2), 20); - assert_eq!(Elections::stake_of(2), 20); - - // can update; different stake; different lock and reserve. - assert_ok!(Elections::vote(Origin::signed(2), vec![5, 4], 15)); - assert_eq!(balances(&2), (18, 2)); - assert_eq!(has_lock(&2), 15); - assert_eq!(Elections::stake_of(2), 15); - }); - } - - #[test] - fn cannot_vote_for_no_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - Elections::vote(Origin::signed(2), vec![], 20), - "cannot vote when no candidates or members exist" - ); - }); - } - - #[test] - fn can_vote_for_old_members_even_when_no_new_candidates() { - // let allowed_votes = candidates_count as usize + Self::members().len() - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::candidates(), vec![]); - - assert_ok!(Elections::vote(Origin::signed(3), vec![4, 5], 10)); - }); - } - - #[test] - fn cannot_vote_for_more_than_candidates() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_noop!( - Elections::vote(Origin::signed(2), vec![10, 20, 30], 20), - "cannot vote more than candidates" - ); - }); - } - - #[test] - fn cannot_vote_for_less_than_ed() { - ExtBuilder::default().voter_bond(8).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_noop!( - Elections::vote(Origin::signed(2), vec![4], 1), - "cannot vote with stake less than minimum balance" - ); - }) - } - - #[test] - fn can_vote_for_more_than_total_balance_but_moot() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 30)); - // you can lie but won't get away with it. - assert_eq!(Elections::stake_of(2), 20); - assert_eq!(has_lock(&2), 20); - }); - } - - #[test] - fn remove_voter_should_work() { - ExtBuilder::default().voter_bond(8).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![5], 30)); - - assert_eq_uvec!(all_voters(), vec![2, 3]); - assert_eq!(Elections::stake_of(2), 20); - assert_eq!(Elections::stake_of(3), 30); - assert_eq!(Elections::votes_of(2), vec![5]); - assert_eq!(Elections::votes_of(3), vec![5]); - - assert_ok!(Elections::remove_voter(Origin::signed(2))); - - assert_eq_uvec!(all_voters(), vec![3]); - assert_eq!(Elections::votes_of(2), vec![]); - assert_eq!(Elections::stake_of(2), 0); - - assert_eq!(balances(&2), (20, 0)); - assert_eq!(Balances::locks(&2).len(), 0); - }); - } - - #[test] - fn non_voter_remove_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!(Elections::remove_voter(Origin::signed(3)), "must be a voter"); - }); - } - - #[test] - fn dupe_remove_should_fail() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - - assert_ok!(Elections::remove_voter(Origin::signed(2))); - assert_eq!(all_voters(), vec![]); - - assert_noop!(Elections::remove_voter(Origin::signed(2)), "must be a voter"); - }); - } - - #[test] - fn removed_voter_should_not_be_counted() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - - assert_ok!(Elections::remove_voter(Origin::signed(4))); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![3, 5]); - }); - } - - #[test] - fn reporter_must_be_voter() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - Elections::report_defunct_voter(Origin::signed(1), 2), - "reporter must be a voter", - ); - }); - } - - #[test] - fn can_detect_defunct_voter() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); - // will be soon a defunct voter. - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::candidates(), vec![]); - - // all of them have a member that they voted for. - assert_eq!(Elections::is_defunct_voter(&5), false); - assert_eq!(Elections::is_defunct_voter(&4), false); - assert_eq!(Elections::is_defunct_voter(&2), false); - - // defunct - assert_eq!(Elections::is_defunct_voter(&3), true); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); - - // has a candidate voted for. - assert_eq!(Elections::is_defunct_voter(&1), false); - - }); - } - - #[test] - fn report_voter_should_work_and_earn_reward() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); - // will be soon a defunct voter. - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::candidates(), vec![]); - - assert_eq!(balances(&3), (28, 2)); - assert_eq!(balances(&5), (45, 5)); - - assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 3)); - assert_eq!( - System::events()[1].event, - Event::elections(RawEvent::VoterReported(3, 5, true)) - ); - - assert_eq!(balances(&3), (28, 0)); - assert_eq!(balances(&5), (47, 5)); - }); - } - - #[test] - fn report_voter_should_slash_when_bad_report() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::candidates(), vec![]); - - assert_eq!(balances(&4), (35, 5)); - assert_eq!(balances(&5), (45, 5)); - - assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 4)); - assert_eq!( - System::events()[1].event, - Event::elections(RawEvent::VoterReported(4, 5, false)) - ); - - assert_eq!(balances(&4), (35, 5)); - assert_eq!(balances(&5), (45, 3)); - }); - } - - - #[test] - fn simple_voting_rounds_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 15)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - - assert_eq_uvec!(all_voters(), vec![2, 3, 4]); - - assert_eq!(Elections::votes_of(2), vec![5]); - assert_eq!(Elections::votes_of(3), vec![3]); - assert_eq!(Elections::votes_of(4), vec![4]); - - assert_eq!(Elections::candidates(), vec![3, 4, 5]); - assert_eq!(>::decode_len().unwrap(), 3); - - assert_eq!(Elections::election_rounds(), 0); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![3, 5]); - assert_eq!(Elections::runners_up(), vec![]); - assert_eq_uvec!(all_voters(), vec![2, 3, 4]); - assert_eq!(Elections::candidates(), vec![]); - assert_eq!(>::decode_len().unwrap(), 0); - - assert_eq!(Elections::election_rounds(), 1); - }); - } - - #[test] - fn defunct_voter_will_be_counted() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - - // This guy's vote is pointless for this round. - assert_ok!(Elections::vote(Origin::signed(3), vec![4], 30)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![5]); - assert_eq!(Elections::election_rounds(), 1); - - // but now it has a valid target. - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); - - // candidate 4 is affected by an old vote. - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::election_rounds(), 2); - assert_eq_uvec!(all_voters(), vec![3, 5]); - }); - } - - #[test] - fn only_desired_seats_are_chosen() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::election_rounds(), 1); - assert_eq!(Elections::members(), vec![4, 5]); - }); - } - - #[test] - fn phragmen_should_not_self_vote() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::candidates(), vec![]); - assert_eq!(Elections::election_rounds(), 1); - assert_eq!(Elections::members(), vec![]); - }); - } - - #[test] - fn runners_up_should_be_kept() { - ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![2], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - // sorted based on account id. - assert_eq!(Elections::members(), vec![4, 5]); - // sorted based on merit (least -> most) - assert_eq!(Elections::runners_up(), vec![3, 2]); - - // runner ups are still locked. - assert_eq!(balances(&4), (35, 5)); - assert_eq!(balances(&5), (45, 5)); - assert_eq!(balances(&3), (25, 5)); - }); - } - - #[test] - fn runners_up_should_be_next_candidates() { - ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::runners_up(), vec![2, 3]); - - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 15)); - - System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![3, 4]); - assert_eq!(Elections::runners_up(), vec![5, 2]); - }); - } - - #[test] - fn runners_up_lose_bond_once_outgoing() { - ExtBuilder::default().desired_runners_up(1).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![4, 5]); - - assert_eq!(Elections::runners_up(), vec![2]); - assert_eq!(balances(&2), (15, 5)); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - - System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![4, 5]); - - assert_eq!(Elections::runners_up(), vec![3]); - assert_eq!(balances(&3), (25, 5)); - assert_eq!(balances(&2), (15, 2)); - }); - } - - #[test] - fn current_members_are_always_implicitly_next_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::election_rounds(), 1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - - assert_ok!(Elections::remove_voter(Origin::signed(4))); - - // 5 will persist as candidates despite not being in the list. - assert_eq!(Elections::candidates(), vec![2, 3]); - - System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); - - // 4 removed; 5 and 3 are the new best. - assert_eq!(Elections::members(), vec![3, 5]); - }); - } - - #[test] - fn election_state_is_uninterrupted() { - // what I mean by uninterrupted: - // given no input or stimulants the same members are re-elected. - ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - - let check_at_block = |b: u32| { - System::set_block_number(b.into()); - assert_ok!(Elections::end_block(System::block_number())); - // we keep re-electing the same folks. - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::runners_up(), vec![2, 3]); - // no new candidates but old members and runners-up are always added. - assert_eq!(Elections::candidates(), vec![]); - assert_eq!(Elections::election_rounds(), b / 5); - assert_eq_uvec!(all_voters(), vec![2, 3, 4, 5]); - }; - - // this state will always persist when no further input is given. - check_at_block(5); - check_at_block(10); - check_at_block(15); - check_at_block(20); - }); - } - - #[test] - fn remove_members_triggers_election() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![4, 5]); - assert_eq!(Elections::election_rounds(), 1); - - // a new candidate - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - - assert_ok!(Elections::remove_member(Origin::ROOT, 4)); - - assert_eq!(balances(&4), (35, 2)); // slashed - assert_eq!(Elections::election_rounds(), 2); // new election round - assert_eq!(Elections::members(), vec![3, 5]); // new members - }); - } - - #[test] - fn seats_should_be_released_when_no_vote() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - - assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - - assert_eq!(>::decode_len().unwrap(), 3); - - assert_eq!(Elections::election_rounds(), 0); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![3, 5]); - assert_eq!(Elections::election_rounds(), 1); - - assert_ok!(Elections::remove_voter(Origin::signed(2))); - assert_ok!(Elections::remove_voter(Origin::signed(3))); - assert_ok!(Elections::remove_voter(Origin::signed(4))); - assert_ok!(Elections::remove_voter(Origin::signed(5))); - - // meanwhile, no one cares to become a candidate again. - System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![]); - assert_eq!(Elections::election_rounds(), 2); - }); - } - - #[test] - fn outgoing_will_get_the_bond_back() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(balances(&5), (50, 0)); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_eq!(balances(&5), (47, 3)); - - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - assert_eq!(balances(&5), (45, 5)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![5]); - - assert_ok!(Elections::remove_voter(Origin::signed(5))); - assert_eq!(balances(&5), (47, 3)); - - System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![]); - - assert_eq!(balances(&5), (50, 0)); - }); - } - - #[test] - fn losers_will_lose_the_bond() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - - assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); - - assert_eq!(balances(&5), (47, 3)); - assert_eq!(balances(&3), (27, 3)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![5]); - - // winner - assert_eq!(balances(&5), (47, 3)); - // loser - assert_eq!(balances(&3), (27, 0)); - }); - } - - #[test] - fn incoming_outgoing_are_reported() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(5))); - - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - assert_eq!(Elections::members(), vec![4, 5]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1))); - assert_ok!(Elections::submit_candidacy(Origin::signed(2))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - - // 5 will change their vote and becomes an `outgoing` - assert_ok!(Elections::vote(Origin::signed(5), vec![4], 8)); - // 4 will stay in the set - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - // 3 will become a winner - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - // these two are losers. - assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); - assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); - - System::set_block_number(10); - assert_ok!(Elections::end_block(System::block_number())); - - // 3, 4 are new members, must still be bonded, nothing slashed. - assert_eq!(Elections::members(), vec![3, 4]); - assert_eq!(balances(&3), (25, 5)); - assert_eq!(balances(&4), (35, 5)); - - // 1 is a loser, slashed by 3. - assert_eq!(balances(&1), (5, 2)); - - // 5 is an outgoing loser, it will get their bond back. - assert_eq!(balances(&5), (48, 2)); - - assert_eq!(System::events()[0].event, Event::elections(RawEvent::NewTerm(vec![4, 5]))); - }) - } - - #[test] - fn invalid_votes_are_moot() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(4))); - assert_ok!(Elections::submit_candidacy(Origin::signed(3))); - - assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); - assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); - assert_ok!(Elections::vote(Origin::signed(5), vec![10], 50)); - - System::set_block_number(5); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq_uvec!(Elections::members(), vec![3, 4]); - assert_eq!(Elections::election_rounds(), 1); - }); - } -} diff --git a/srml/elections/Cargo.toml b/srml/elections/Cargo.toml deleted file mode 100644 index 88d147ac087aa..0000000000000 --- a/srml/elections/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "srml-elections" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -hex-literal = "0.2.1" -balances = { package = "srml-balances", path = "../balances" } - -[features] -default = ["std"] -std = [ - "safe-mix/std", - "codec/std", - "primitives/std", - "rstd/std", - "serde", - "runtime-io/std", - "support/std", - "sr-primitives/std", - "system/std", -] diff --git a/srml/elections/src/lib.rs b/srml/elections/src/lib.rs deleted file mode 100644 index 87e29f3b14498..0000000000000 --- a/srml/elections/src/lib.rs +++ /dev/null @@ -1,1154 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Election module for stake-weighted membership selection of a collective. -//! -//! The composition of a set of account IDs works according to one or more approval votes -//! weighted by stake. There is a partial carry-over facility to give greater weight to those -//! whose voting is serially unsuccessful. - -#![cfg_attr(not(feature = "std"), no_std)] -#![recursion_limit="128"] - -use rstd::prelude::*; -use sr_primitives::{ - RuntimeDebug, - print, - traits::{Zero, One, StaticLookup, Bounded, Saturating}, - weights::SimpleDispatchInfo, -}; -use support::{ - dispatch::Result, decl_storage, decl_event, ensure, decl_module, - traits::{ - Currency, ExistenceRequirement, Get, LockableCurrency, LockIdentifier, - OnUnbalanced, ReservableCurrency, WithdrawReason, WithdrawReasons, ChangeMembers - } -}; -use codec::{Encode, Decode}; -use system::{self, ensure_signed, ensure_root}; - -mod mock; -mod tests; - -// no polynomial attacks: -// -// all unbonded public operations should be constant time. -// all other public operations must be linear time in terms of prior public operations and: -// - those "valid" ones that cost nothing be limited to a constant number per single protected -// operation -// - the rest costing the same order as the computational complexity -// all protected operations must complete in at most O(public operations) -// -// we assume "beneficial" transactions will have the same access as attack transactions. -// -// any storage requirements should be bonded by the same order as the volume. - -// public operations: -// - express approvals (you pay in a "voter" bond the first time you do this; O(1); one extra DB -// entry, one DB change) -// - remove active voter (you get your "voter" bond back; O(1); one fewer DB entry, one DB change) -// - remove inactive voter (either you or the target is removed; if the target, you get their -// "voter" bond back; O(1); one fewer DB entry, one DB change) -// - submit candidacy (you pay a "candidate" bond; O(1); one extra DB entry, two DB changes) -// - present winner/runner-up (you may pay a "presentation" bond of O(voters) if the presentation -// is invalid; O(voters) compute; ) protected operations: -// - remove candidacy (remove all votes for a candidate) (one fewer DB entry, two DB changes) - -// to avoid a potentially problematic case of not-enough approvals prior to voting causing a -// back-to-back votes that have no way of ending, then there's a forced grace period between votes. -// to keep the system as stateless as possible (making it a bit easier to reason about), we just -// restrict when votes can begin to blocks that lie on boundaries (`voting_period`). - -// for an approval vote of C members: - -// top K runners-up are maintained between votes. all others are discarded. -// - candidate removed & bond returned when elected. -// - candidate removed & bond burned when discarded. - -// at the point that the vote ends (), all voters' balances are snapshotted. - -// for B blocks following, there's a counting period whereby each of the candidates that believe -// they fall in the top K+C voted can present themselves. they get the total stake -// recorded (based on the snapshot); an ordered list is maintained (the leaderboard). Noone may -// present themselves that, if elected, would result in being included twice in the collective -// (important since existing members will have their approval votes as it may be that they -// don't get removed), nor if existing presenters would mean they're not in the top K+C. - -// following B blocks, the top C candidates are elected and have their bond returned. the top C -// candidates and all other candidates beyond the top C+K are cleared. - -// vote-clearing happens lazily; for an approval to count, the most recent vote at the time of the -// voter's most recent vote must be no later than the most recent vote at the time that the -// candidate in the approval position was registered there. as candidates are removed from the -// register and others join in their place, this prevents an approval meant for an earlier candidate -// being used to elect a new candidate. - -// the candidate list increases as needed, but the contents (though not really the capacity) reduce -// after each vote as all but K entries are cleared. newly registering candidates must use cleared -// entries before they increase the capacity. - -/// The activity status of a voter. -#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, Default, RuntimeDebug)] -pub struct VoterInfo { - /// Last VoteIndex in which this voter assigned (or initialized) approvals. - last_active: VoteIndex, - /// Last VoteIndex in which one of this voter's approvals won. - /// Note that `last_win = N` indicates a last win at index `N-1`, hence `last_win = 0` means no - /// win ever. - last_win: VoteIndex, - /// The amount of stored weight as a result of not winning but changing approvals. - pot: Balance, - /// Current staked amount. A lock equal to this value always exists. - stake: Balance, -} - -/// Used to demonstrate the status of a particular index in the global voter list. -#[derive(PartialEq, Eq, RuntimeDebug)] -pub enum CellStatus { - /// Any out of bound index. Means a push a must happen to the chunk pointed by `NextVoterSet`. - /// Voting fee is applied in case a new chunk is created. - Head, - /// Already occupied by another voter. Voting fee is applied. - Occupied, - /// Empty hole which should be filled. No fee will be applied. - Hole, -} - -const MODULE_ID: LockIdentifier = *b"py/elect"; - -/// Number of voters grouped in one chunk. -pub const VOTER_SET_SIZE: usize = 64; -/// NUmber of approvals grouped in one chunk. -pub const APPROVAL_SET_SIZE: usize = 8; - -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -type NegativeImbalanceOf = - <::Currency as Currency<::AccountId>>::NegativeImbalance; - -/// Index used to access chunks. -type SetIndex = u32; -/// Index used to count voting rounds. -pub type VoteIndex = u32; -/// Underlying data type of the approvals. -type ApprovalFlag = u32; -/// Number of approval flags that can fit into [`ApprovalFlag`] type. -const APPROVAL_FLAG_LEN: usize = 32; - -pub trait Trait: system::Trait { - type Event: From> + Into<::Event>; - - /// The currency that people are electing with. - type Currency: - LockableCurrency - + ReservableCurrency; - - /// Handler for the unbalanced reduction when slashing a validator. - type BadPresentation: OnUnbalanced>; - - /// Handler for the unbalanced reduction when slashing an invalid reaping attempt. - type BadReaper: OnUnbalanced>; - - /// Handler for the unbalanced reduction when submitting a bad `voter_index`. - type BadVoterIndex: OnUnbalanced>; - - /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner up) - type LoserCandidate: OnUnbalanced>; - - /// What to do when the members change. - type ChangeMembers: ChangeMembers; - - /// How much should be locked up in order to submit one's candidacy. A reasonable - /// default value is 9. - type CandidacyBond: Get>; - - /// How much should be locked up in order to be able to submit votes. - type VotingBond: Get>; - - /// The amount of fee paid upon each vote submission, unless if they submit a - /// _hole_ index and replace it. - type VotingFee: Get>; - - /// Minimum about that can be used as the locked value for voting. - type MinimumVotingLock: Get>; - - /// The punishment, per voter, if you provide an invalid presentation. A - /// reasonable default value is 1. - type PresentSlashPerVoter: Get>; - - /// How many runners-up should have their approvals persist until the next - /// vote. A reasonable default value is 2. - type CarryCount: Get; - - /// How many vote indices need to go by after a target voter's last vote before - /// they can be reaped if their approvals are moot. A reasonable default value - /// is 1. - type InactiveGracePeriod: Get; - - /// How often (in blocks) to check for new votes. A reasonable default value - /// is 1000. - type VotingPeriod: Get; - - /// Decay factor of weight when being accumulated. It should typically be set to - /// __at least__ `membership_size -1` to keep the collective secure. - /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight - /// increment step `t`. 0 will result in no weight being added at all (normal - /// approval voting). A reasonable default value is 24. - type DecayRatio: Get; -} - -decl_storage! { - trait Store for Module as Council { - // ---- parameters - - /// How long to give each top candidate to present themselves after the vote ends. - pub PresentationDuration get(fn presentation_duration) config(): T::BlockNumber; - /// How long each position is active for. - pub TermDuration get(fn term_duration) config(): T::BlockNumber; - /// Number of accounts that should constitute the collective. - pub DesiredSeats get(fn desired_seats) config(): u32; - - // ---- permanent state (always relevant, changes only at the finalization of voting) - - /// The current membership. When there's a vote going on, this should still be used for - /// executive matters. The block number (second element in the tuple) is the block that - /// their position is active until (calculated by the sum of the block number when the - /// member was elected and their term duration). - pub Members get(fn members) config(): Vec<(T::AccountId, T::BlockNumber)>; - /// The total number of vote rounds that have happened or are in progress. - pub VoteCount get(fn vote_index): VoteIndex; - - // ---- persistent state (always relevant, changes constantly) - - // A list of votes for each voter. The votes are stored as numeric values and parsed in a - // bit-wise manner. In order to get a human-readable representation (`Vec`), use - // [`all_approvals_of`]. Furthermore, each vector of scalars is chunked with the cap of - // `APPROVAL_SET_SIZE`. - pub ApprovalsOf get(fn approvals_of): map (T::AccountId, SetIndex) => Vec; - /// The vote index and list slot that the candidate `who` was registered or `None` if they - /// are not currently registered. - pub RegisterInfoOf get(fn candidate_reg_info): map T::AccountId => Option<(VoteIndex, u32)>; - /// Basic information about a voter. - pub VoterInfoOf get(fn voter_info): map T::AccountId => Option>>; - /// The present voter list (chunked and capped at [`VOTER_SET_SIZE`]). - pub Voters get(fn voters): map SetIndex => Vec>; - /// the next free set to store a voter in. This will keep growing. - pub NextVoterSet get(fn next_nonfull_voter_set): SetIndex = 0; - /// Current number of Voters. - pub VoterCount get(fn voter_count): SetIndex = 0; - /// The present candidate list. - pub Candidates get(fn candidates): Vec; // has holes - /// Current number of active candidates - pub CandidateCount get(fn candidate_count): u32; - - // ---- temporary state (only relevant during finalization/presentation) - - /// The accounts holding the seats that will become free on the next tally. - pub NextFinalize get(fn next_finalize): Option<(T::BlockNumber, u32, Vec)>; - /// Get the leaderboard if we're in the presentation phase. The first element is the weight - /// of each entry; It may be the direct summed approval stakes, or a weighted version of it. - /// Sorted from low to high. - pub Leaderboard get(fn leaderboard): Option, T::AccountId)> >; - - /// Who is able to vote for whom. Value is the fund-holding account, key is the - /// vote-transaction-sending account. - pub Proxy get(fn proxy): map T::AccountId => Option; - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// How much should be locked up in order to submit one's candidacy. A reasonable - /// default value is 9. - const CandidacyBond: BalanceOf = T::CandidacyBond::get(); - - /// How much should be locked up in order to be able to submit votes. - const VotingBond: BalanceOf = T::VotingBond::get(); - - /// The amount of fee paid upon each vote submission, unless if they submit a - /// _hole_ index and replace it. - const VotingFee: BalanceOf = T::VotingFee::get(); - - /// The punishment, per voter, if you provide an invalid presentation. A - /// reasonable default value is 1. - const PresentSlashPerVoter: BalanceOf = T::PresentSlashPerVoter::get(); - - /// How many runners-up should have their approvals persist until the next - /// vote. A reasonable default value is 2. - const CarryCount: u32 = T::CarryCount::get(); - - /// How many vote indices need to go by after a target voter's last vote before - /// they can be reaped if their approvals are moot. A reasonable default value - /// is 1. - const InactiveGracePeriod: VoteIndex = T::InactiveGracePeriod::get(); - - /// How often (in blocks) to check for new votes. A reasonable default value - /// is 1000. - const VotingPeriod: T::BlockNumber = T::VotingPeriod::get(); - - /// Minimum about that can be used as the locked value for voting. - const MinimumVotingLock: BalanceOf = T::MinimumVotingLock::get(); - - /// Decay factor of weight when being accumulated. It should typically be set to - /// __at least__ `membership_size -1` to keep the collective secure. - /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight - /// increment step `t`. 0 will result in no weight being added at all (normal - /// approval voting). A reasonable default value is 24. - const DecayRatio: u32 = T::DecayRatio::get(); - - /// The chunk size of the voter vector. - const VOTER_SET_SIZE: u32 = VOTER_SET_SIZE as u32; - /// The chunk size of the approval vector. - const APPROVAL_SET_SIZE: u32 = APPROVAL_SET_SIZE as u32; - - fn deposit_event() = default; - - /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots - /// are registered. - /// - /// Locks `value` from the balance of `origin` indefinitely. Only [`retract_voter`] or - /// [`reap_inactive_voter`] can unlock the balance. - /// - /// `hint` argument is interpreted differently based on: - /// - if `origin` is setting approvals for the first time: The index will be checked for - /// being a valid _hole_ in the voter list. - /// - if the hint is correctly pointing to a hole, no fee is deducted from `origin`. - /// - Otherwise, the call will succeed but the index is ignored and simply a push to the - /// last chunk with free space happens. If the new push causes a new chunk to be - /// created, a fee indicated by [`VotingFee`] is deducted. - /// - if `origin` is already a voter: the index __must__ be valid and point to the correct - /// position of the `origin` in the current voters list. - /// - /// Note that any trailing `false` votes in `votes` is ignored; In approval voting, not - /// voting for a candidate and voting false, are equal. - /// - /// # - /// - O(1). - /// - Two extra DB entries, one DB change. - /// - Argument `votes` is limited in length to number of candidates. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] - fn set_approvals( - origin, - votes: Vec, - #[compact] index: VoteIndex, - hint: SetIndex, - #[compact] value: BalanceOf - ) -> Result { - let who = ensure_signed(origin)?; - Self::do_set_approvals(who, votes, index, hint, value) - } - - /// Set candidate approvals from a proxy. Approval slots stay valid as long as candidates in - /// those slots are registered. - /// - /// # - /// - Same as `set_approvals` with one additional storage read. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] - fn proxy_set_approvals(origin, - votes: Vec, - #[compact] index: VoteIndex, - hint: SetIndex, - #[compact] value: BalanceOf - ) -> Result { - let who = Self::proxy(ensure_signed(origin)?).ok_or("not a proxy")?; - Self::do_set_approvals(who, votes, index, hint, value) - } - - /// Remove a voter. For it not to be a bond-consuming no-op, all approved candidate indices - /// must now be either unregistered or registered to a candidate that registered the slot - /// after the voter gave their last approval set. - /// - /// Both indices must be provided as explained in [`voter_at`] function. - /// - /// May be called by anyone. Returns the voter deposit to `signed`. - /// - /// # - /// - O(1). - /// - Two fewer DB entries, one DB change. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] - fn reap_inactive_voter( - origin, - #[compact] reporter_index: u32, - who: ::Source, - #[compact] who_index: u32, - #[compact] assumed_vote_index: VoteIndex - ) { - let reporter = ensure_signed(origin)?; - let who = T::Lookup::lookup(who)?; - - ensure!(!Self::presentation_active(), "cannot reap during presentation period"); - ensure!(Self::voter_info(&reporter).is_some(), "reporter must be a voter"); - - let info = Self::voter_info(&who) - .ok_or("target for inactivity cleanup must be active")?; - let last_active = info.last_active; - - ensure!(assumed_vote_index == Self::vote_index(), "vote index not current"); - ensure!( - assumed_vote_index > last_active + T::InactiveGracePeriod::get(), - "cannot reap during grace period" - ); - - let reporter_index = reporter_index as usize; - let who_index = who_index as usize; - let assumed_reporter = Self::voter_at(reporter_index).ok_or("invalid reporter index")?; - let assumed_who = Self::voter_at(who_index).ok_or("invalid target index")?; - - ensure!(assumed_reporter == reporter, "bad reporter index"); - ensure!(assumed_who == who, "bad target index"); - - // will definitely kill one of reporter or who now. - - let valid = !Self::all_approvals_of(&who).iter() - .zip(Self::candidates().iter()) - .any(|(&appr, addr)| - appr && - *addr != T::AccountId::default() && - // defensive only: all items in candidates list are registered - Self::candidate_reg_info(addr).map_or(false, |x| x.0 <= last_active) - ); - - Self::remove_voter( - if valid { &who } else { &reporter }, - if valid { who_index } else { reporter_index } - ); - - T::Currency::remove_lock( - MODULE_ID, - if valid { &who } else { &reporter } - ); - - if valid { - // This only fails if `reporter` doesn't exist, which it clearly must do since its - // the origin. Still, it's no more harmful to propagate any error at this point. - T::Currency::repatriate_reserved(&who, &reporter, T::VotingBond::get())?; - Self::deposit_event(RawEvent::VoterReaped(who, reporter)); - } else { - let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0; - T::BadReaper::on_unbalanced(imbalance); - Self::deposit_event(RawEvent::BadReaperSlashed(reporter)); - } - } - - /// Remove a voter. All votes are cancelled and the voter deposit is returned. - /// - /// The index must be provided as explained in [`voter_at`] function. - /// - /// Also removes the lock on the balance of the voter. See [`do_set_approvals()`]. - /// - /// # - /// - O(1). - /// - Two fewer DB entries, one DB change. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(1_250_000)] - 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 index = index as usize; - let voter = Self::voter_at(index).ok_or("retraction index invalid")?; - ensure!(voter == who, "retraction index mismatch"); - - Self::remove_voter(&who, index); - T::Currency::unreserve(&who, T::VotingBond::get()); - T::Currency::remove_lock(MODULE_ID, &who); - } - - /// Submit oneself for candidacy. - /// - /// Account must have enough transferrable funds in it to pay the bond. - /// - /// NOTE: if `origin` has already assigned approvals via [`set_approvals`], - /// it will NOT have any usable funds to pass candidacy bond and must first retract. - /// Note that setting approvals will lock the entire balance of the voter until - /// retraction or being reported. - /// - /// # - /// - Independent of input. - /// - Three DB changes. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] - fn submit_candidacy(origin, #[compact] slot: u32) { - let who = ensure_signed(origin)?; - - ensure!(!Self::is_a_candidate(&who), "duplicate candidate submission"); - let slot = slot as usize; - let count = Self::candidate_count() as usize; - let candidates = Self::candidates(); - ensure!( - (slot == count && count == candidates.len()) || - (slot < candidates.len() && candidates[slot] == T::AccountId::default()), - "invalid candidate slot" - ); - // NOTE: This must be last as it has side-effects. - T::Currency::reserve(&who, T::CandidacyBond::get()) - .map_err(|_| "candidate has not enough funds")?; - - >::insert(&who, (Self::vote_index(), slot as u32)); - let mut candidates = candidates; - if slot == candidates.len() { - candidates.push(who); - } else { - candidates[slot] = who; - } - >::put(candidates); - CandidateCount::put(count as u32 + 1); - } - - /// Claim that `candidate` is one of the top `carry_count + desired_seats` candidates. Only - /// works iff the presentation period is active. `candidate` should have at least collected - /// some non-zero `total` votes and `origin` must have enough funds to pay for a potential - /// slash. - /// - /// # - /// - O(voters) compute. - /// - One DB change. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(10_000_000)] - fn present_winner( - origin, - candidate: ::Source, - #[compact] total: BalanceOf, - #[compact] index: VoteIndex - ) -> Result { - let who = ensure_signed(origin)?; - ensure!( - !total.is_zero(), - "stake deposited to present winner and be added to leaderboard should be non-zero", - ); - - let candidate = T::Lookup::lookup(candidate)?; - ensure!(index == Self::vote_index(), "index not current"); - let (_, _, expiring) = Self::next_finalize() - .ok_or("cannot present outside of presentation period")?; - let bad_presentation_punishment = - T::PresentSlashPerVoter::get() - * BalanceOf::::from(Self::voter_count() as u32); - 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"); - - if let Some(p) = Self::members().iter().position(|&(ref c, _)| c == &candidate) { - ensure!( - p < expiring.len(), - "candidate must not form a duplicated member if elected" - ); - } - - let voters = Self::all_voters(); - let (registered_since, candidate_index): (VoteIndex, u32) = - Self::candidate_reg_info(&candidate).ok_or("presented candidate must be current")?; - let actual_total = voters.iter() - .filter_map(|maybe_voter| maybe_voter.as_ref()) - .filter_map(|voter| match Self::voter_info(voter) { - Some(b) if b.last_active >= registered_since => { - let last_win = b.last_win; - let now = Self::vote_index(); - let stake = b.stake; - let offset = Self::get_offset(stake, now - last_win); - let weight = stake + offset + b.pot; - if Self::approvals_of_at(voter, candidate_index as usize) { - Some(weight) - } else { None } - }, - _ => None, - }) - .fold(Zero::zero(), |acc, n| acc + n); - let dupe = leaderboard.iter().find(|&&(_, ref c)| c == &candidate).is_some(); - if total == actual_total && !dupe { - // insert into leaderboard - leaderboard[0] = (total, candidate); - leaderboard.sort_by_key(|&(t, _)| t); - >::put(leaderboard); - Ok(()) - } else { - // we can rest assured it will be Ok since we checked `can_slash` earlier; still - // better safe than sorry. - let imbalance = T::Currency::slash(&who, bad_presentation_punishment).0; - T::BadPresentation::on_unbalanced(imbalance); - Err(if dupe { "duplicate presentation" } else { "incorrect total" }) - } - } - - /// Set the desired member count; if lower than the current count, then seats will not be up - /// election when they expire. If more, then a new vote will be started if one is not - /// already in progress. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_desired_seats(origin, #[compact] count: u32) { - ensure_root(origin)?; - DesiredSeats::put(count); - } - - /// Remove a particular member from the set. This is effective immediately. - /// - /// Note: A tally should happen instantly (if not already in a presentation - /// period) to fill the seat if removal means that the desired members are not met. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn remove_member(origin, who: ::Source) { - ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; - let new_set: Vec<(T::AccountId, T::BlockNumber)> = Self::members() - .into_iter() - .filter(|i| i.0 != who) - .collect(); - >::put(&new_set); - let new_set = new_set.into_iter().map(|x| x.0).collect::>(); - T::ChangeMembers::change_members(&[], &[who], new_set); - } - - /// Set the presentation duration. If there is currently a vote being presented for, will - /// invoke `finalize_vote`. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_presentation_duration(origin, #[compact] count: T::BlockNumber) { - ensure_root(origin)?; - >::put(count); - } - - /// Set the presentation duration. If there is current a vote being presented for, will - /// invoke `finalize_vote`. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_term_duration(origin, #[compact] count: T::BlockNumber) { - ensure_root(origin)?; - >::put(count); - } - - fn on_initialize(n: T::BlockNumber) { - if let Err(e) = Self::end_block(n) { - print("Guru meditation"); - print(e); - } - } - } -} - -decl_event!( - pub enum Event where ::AccountId { - /// reaped voter, reaper - VoterReaped(AccountId, AccountId), - /// slashed reaper - BadReaperSlashed(AccountId), - /// A tally (for approval votes of seat(s)) has started. - TallyStarted(u32), - /// A tally (for approval votes of seat(s)) has ended (with one or more new members). - TallyFinalized(Vec, Vec), - } -); - -impl Module { - // exposed immutables. - - /// True if we're currently in a presentation period. - pub fn presentation_active() -> bool { - >::exists() - } - - /// If `who` a candidate at the moment? - pub fn is_a_candidate(who: &T::AccountId) -> bool { - >::exists(who) - } - - /// Iff the member `who` still has a seat at blocknumber `n` returns `true`. - pub fn will_still_be_member_at(who: &T::AccountId, n: T::BlockNumber) -> bool { - Self::members().iter() - .find(|&&(ref a, _)| a == who) - .map(|&(_, expires)| expires > n) - .unwrap_or(false) - } - - /// Determine the block that a vote can happen on which is no less than `n`. - pub fn next_vote_from(n: T::BlockNumber) -> T::BlockNumber { - let voting_period = T::VotingPeriod::get(); - (n + voting_period - One::one()) / voting_period * voting_period - } - - /// The block number on which the tally for the next election will happen. `None` only if the - /// desired seats of the set is zero. - pub fn next_tally() -> Option { - let desired_seats = Self::desired_seats(); - if desired_seats == 0 { - None - } else { - let c = Self::members(); - let (next_possible, count, coming) = - if let Some((tally_end, comers, leavers)) = Self::next_finalize() { - // if there's a tally in progress, then next tally can begin immediately afterwards - (tally_end, c.len() - leavers.len() + comers as usize, comers) - } else { - (>::block_number(), c.len(), 0) - }; - if count < desired_seats as usize { - Some(next_possible) - } else { - // next tally begins once enough members expire to bring members below desired. - if desired_seats <= coming { - // the entire amount of desired seats is less than those new members - we'll - // have to wait until they expire. - Some(next_possible + Self::term_duration()) - } else { - Some(c[c.len() - (desired_seats - coming) as usize].1) - } - }.map(Self::next_vote_from) - } - } - - // Private - /// Check there's nothing to do this block - fn end_block(block_number: T::BlockNumber) -> Result { - if (block_number % T::VotingPeriod::get()).is_zero() { - if let Some(number) = Self::next_tally() { - if block_number == number { - Self::start_tally(); - } - } - } - if let Some((number, _, _)) = Self::next_finalize() { - if block_number == number { - Self::finalize_tally()? - } - } - Ok(()) - } - - /// Remove a voter at a specified index from the system. - fn remove_voter(voter: &T::AccountId, index: usize) { - let (set_index, vec_index) = Self::split_index(index, VOTER_SET_SIZE); - let mut set = Self::voters(set_index); - set[vec_index] = None; - >::insert(set_index, set); - VoterCount::mutate(|c| *c = *c - 1); - Self::remove_all_approvals_of(voter); - >::remove(voter); - } - - /// Actually do the voting. - /// - /// The voter index must be provided as explained in [`voter_at`] function. - fn do_set_approvals( - who: T::AccountId, - votes: Vec, - index: VoteIndex, - hint: SetIndex, - value: BalanceOf, - ) -> Result { - let candidates_len = ::Candidates::decode_len().unwrap_or(0_usize); - - ensure!(!Self::presentation_active(), "no approval changes during presentation period"); - ensure!(index == Self::vote_index(), "incorrect vote index"); - ensure!( - !candidates_len.is_zero(), - "amount of candidates to receive approval votes should be non-zero" - ); - // Prevent a vote from voters that provide a list of votes that exceeds the candidates - // length since otherwise an attacker may be able to submit a very long list of `votes` that - // far exceeds the amount of candidates and waste more computation than a reasonable voting - // bond would cover. - ensure!( - candidates_len >= votes.len(), - "amount of candidate votes cannot exceed amount of candidates" - ); - ensure!(value >= T::MinimumVotingLock::get(), "locked value must be more than limit"); - - // Amount to be locked up. - let mut locked_balance = value.min(T::Currency::total_balance(&who)); - let mut pot_to_set = Zero::zero(); - let hint = hint as usize; - - if let Some(info) = Self::voter_info(&who) { - // already a voter. Index must be valid. No fee. update pot. O(1) - let voter = Self::voter_at(hint).ok_or("invalid voter index")?; - ensure!(voter == who, "wrong voter index"); - - // write new accumulated offset. - let last_win = info.last_win; - let now = index; - let offset = Self::get_offset(info.stake, now - last_win); - pot_to_set = info.pot + offset; - } else { - // not yet a voter. Index _could be valid_. Fee might apply. Bond will be reserved O(1). - ensure!( - T::Currency::free_balance(&who) > T::VotingBond::get(), - "new voter must have sufficient funds to pay the bond" - ); - - let (set_index, vec_index) = Self::split_index(hint, VOTER_SET_SIZE); - match Self::cell_status(set_index, vec_index) { - CellStatus::Hole => { - // requested cell was a valid hole. - >::mutate(set_index, |set| set[vec_index] = Some(who.clone())); - }, - CellStatus::Head | CellStatus::Occupied => { - // Either occupied or out-of-range. - let next = Self::next_nonfull_voter_set(); - let set_len = >::decode_len(next).unwrap_or(0_usize); - // Caused a new set to be created. Pay for it. - // This is the last potential error. Writes will begin afterwards. - if set_len == 0 { - let imbalance = T::Currency::withdraw( - &who, - T::VotingFee::get(), - WithdrawReason::Fee, - ExistenceRequirement::KeepAlive, - )?; - T::BadVoterIndex::on_unbalanced(imbalance); - // NOTE: this is safe since the `withdraw()` will check this. - locked_balance -= T::VotingFee::get(); - } - if set_len + 1 == VOTER_SET_SIZE { - NextVoterSet::put(next + 1); - } - >::append_or_insert(next, &[Some(who.clone())][..]) - } - } - - T::Currency::reserve(&who, T::VotingBond::get())?; - VoterCount::mutate(|c| *c = *c + 1); - } - - T::Currency::set_lock( - MODULE_ID, - &who, - locked_balance, - T::BlockNumber::max_value(), - WithdrawReasons::all(), - ); - - >::insert( - &who, - VoterInfo::> { - last_active: index, - last_win: index, - stake: locked_balance, - pot: pot_to_set, - } - ); - Self::set_approvals_chunked(&who, votes); - - Ok(()) - } - - /// Close the voting, record the number of seats that are actually up for grabs. - fn start_tally() { - let members = Self::members(); - let desired_seats = Self::desired_seats() as usize; - let number = >::block_number(); - let expiring = - members.iter().take_while(|i| i.1 <= number).map(|i| i.0.clone()).collect::>(); - let retaining_seats = members.len() - expiring.len(); - if retaining_seats < desired_seats { - let empty_seats = desired_seats - retaining_seats; - >::put( - (number + Self::presentation_duration(), empty_seats as u32, expiring) - ); - - // initialize leaderboard. - let leaderboard_size = empty_seats + T::CarryCount::get() as usize; - >::put(vec![(BalanceOf::::zero(), T::AccountId::default()); leaderboard_size]); - - Self::deposit_event(RawEvent::TallyStarted(empty_seats as u32)); - } - } - - /// Finalize the vote, removing each of the `removals` and inserting `seats` of the most - /// approved candidates in their place. If the total number of members is less than the desired - /// membership a new vote is started. Clears all presented candidates, returning the bond of the - /// elected ones. - fn finalize_tally() -> Result { - let (_, coming, expiring): (T::BlockNumber, u32, Vec) = - >::take() - .ok_or("finalize can only be called after a tally is started.")?; - let leaderboard: Vec<(BalanceOf, T::AccountId)> = >::take() - .unwrap_or_default(); - let new_expiry = >::block_number() + Self::term_duration(); - - // return bond to winners. - let candidacy_bond = T::CandidacyBond::get(); - let incoming: Vec<_> = leaderboard.iter() - .rev() - .take_while(|&&(b, _)| !b.is_zero()) - .take(coming as usize) - .map(|(_, a)| a) - .cloned() - .inspect(|a| { T::Currency::unreserve(a, candidacy_bond); }) - .collect(); - - // Update last win index for anyone voted for any of the incomings. - incoming.iter().filter_map(|i| Self::candidate_reg_info(i)).for_each(|r| { - let index = r.1 as usize; - Self::all_voters() - .iter() - .filter_map(|mv| mv.as_ref()) - .filter(|v| Self::approvals_of_at(*v, index)) - .for_each(|v| >::mutate(v, |a| { - if let Some(activity) = a { activity.last_win = Self::vote_index() + 1; } - })); - }); - let members = Self::members(); - let outgoing: Vec<_> = members.iter() - .take(expiring.len()) - .map(|a| a.0.clone()).collect(); - - // set the new membership set. - let mut new_set: Vec<_> = members - .into_iter() - .skip(expiring.len()) - .chain(incoming.iter().cloned().map(|a| (a, new_expiry))) - .collect(); - new_set.sort_by_key(|&(_, expiry)| expiry); - >::put(&new_set); - - let new_set = new_set.into_iter().map(|x| x.0).collect::>(); - T::ChangeMembers::change_members(&incoming, &outgoing, new_set); - - // clear all except runners-up from candidate list. - let candidates = Self::candidates(); - let mut new_candidates = vec![T::AccountId::default(); candidates.len()]; // shrink later. - let runners_up = leaderboard.into_iter() - .rev() - .take_while(|&(b, _)| !b.is_zero()) - .skip(coming as usize) - .filter_map(|(_, a)| Self::candidate_reg_info(&a).map(|i| (a, i.1))); - let mut count = 0u32; - for (address, slot) in runners_up { - new_candidates[slot as usize] = address; - count += 1; - } - for (old, new) in candidates.iter().zip(new_candidates.iter()) { - // candidate is not a runner up. - if old != new { - // removed - kill it - >::remove(old); - - // and candidate is not a winner. - if incoming.iter().find(|e| *e == old).is_none() { - // slash the bond. - let (imbalance, _) = T::Currency::slash_reserved(&old, T::CandidacyBond::get()); - T::LoserCandidate::on_unbalanced(imbalance); - } - } - } - // discard any superfluous slots. - if let Some(last_index) = new_candidates - .iter() - .rposition(|c| *c != T::AccountId::default()) { - new_candidates.truncate(last_index + 1); - } - - Self::deposit_event(RawEvent::TallyFinalized(incoming, outgoing)); - - >::put(new_candidates); - CandidateCount::put(count); - VoteCount::put(Self::vote_index() + 1); - Ok(()) - } - - /// Get the set and vector index of a global voter index. - /// - /// Note that this function does not take holes into account. - /// See [`voter_at`]. - fn split_index(index: usize, scale: usize) -> (SetIndex, usize) { - let set_index = (index / scale) as u32; - let vec_index = index % scale; - (set_index, vec_index) - } - - /// Return a concatenated vector over all voter sets. - fn all_voters() -> Vec> { - let mut all = >::get(0); - let mut index = 1; - // NOTE: we could also use `Self::next_nonfull_voter_set()` here but that might change based - // on how we do chunking. This is more generic. - loop { - let next_set = >::get(index); - if next_set.is_empty() { - break; - } else { - index += 1; - all.extend(next_set); - } - } - all - } - - /// Shorthand for fetching a voter at a specific (global) index. - /// - /// NOTE: this function is used for checking indices. Yet, it does not take holes into account. - /// This means that any account submitting an index at any point in time should submit: - /// `VOTER_SET_SIZE * set_index + local_index`, meaning that you are ignoring all holes in the - /// first `set_index` sets. - fn voter_at(index: usize) -> Option { - let (set_index, vec_index) = Self::split_index(index, VOTER_SET_SIZE); - let set = Self::voters(set_index); - if vec_index < set.len() { - set[vec_index].clone() - } else { - None - } - } - - /// A more sophisticated version of `voter_at`. Will be kept separate as most often it is an - /// overdue compared to `voter_at`. Only used when setting approvals. - fn cell_status(set_index: SetIndex, vec_index: usize) -> CellStatus { - let set = Self::voters(set_index); - if vec_index < set.len() { - if let Some(_) = set[vec_index] { - CellStatus::Occupied - } else { - CellStatus::Hole - } - } else { - CellStatus::Head - } - } - - /// Sets the approval of a voter in a chunked manner. - fn set_approvals_chunked(who: &T::AccountId, approvals: Vec) { - let approvals_flag_vec = Self::bool_to_flag(approvals); - approvals_flag_vec - .chunks(APPROVAL_SET_SIZE) - .enumerate() - .for_each(|(index, slice)| >::insert( - (&who, index as SetIndex), slice) - ); - } - - /// shorthand for fetching a specific approval of a voter at a specific (global) index. - /// - /// Using this function to read a vote is preferred as it reads `APPROVAL_SET_SIZE` items of - /// type `ApprovalFlag` from storage at most; not all of them. - /// - /// Note that false is returned in case of no-vote or an explicit `false`. - fn approvals_of_at(who: &T::AccountId, index: usize) -> bool { - let (flag_index, bit) = Self::split_index(index, APPROVAL_FLAG_LEN); - let (set_index, vec_index) = Self::split_index(flag_index as usize, APPROVAL_SET_SIZE); - let set = Self::approvals_of((who.clone(), set_index)); - if vec_index < set.len() { - // This is because bit_at treats numbers in lsb -> msb order. - let reversed_index = set.len() - 1 - vec_index; - Self::bit_at(set[reversed_index], bit) - } else { - false - } - } - - /// Return true of the bit `n` of scalar `x` is set to `1` and false otherwise. - fn bit_at(x: ApprovalFlag, n: usize) -> bool { - if n < APPROVAL_FLAG_LEN { - x & ( 1 << n ) != 0 - } else { - false - } - } - - /// Convert a vec of boolean approval flags to a vec of integers, as denoted by - /// the type `ApprovalFlag`. see `bool_to_flag_should_work` test for examples. - pub fn bool_to_flag(x: Vec) -> Vec { - let mut result: Vec = Vec::with_capacity(x.len() / APPROVAL_FLAG_LEN); - if x.is_empty() { - return result; - } - result.push(0); - let mut index = 0; - let mut counter = 0; - loop { - let shl_index = counter % APPROVAL_FLAG_LEN; - result[index] += (if x[counter] { 1 } else { 0 }) << shl_index; - counter += 1; - if counter > x.len() - 1 { break; } - if counter % APPROVAL_FLAG_LEN == 0 { - result.push(0); - index += 1; - } - } - result - } - - /// Convert a vec of flags (u32) to boolean. - pub fn flag_to_bool(chunk: Vec) -> Vec { - let mut result = Vec::with_capacity(chunk.len()); - if chunk.is_empty() { return vec![] } - chunk.into_iter() - .map(|num| - (0..APPROVAL_FLAG_LEN).map(|bit| Self::bit_at(num, bit)).collect::>() - ) - .for_each(|c| { - let last_approve = match c.iter().rposition(|n| *n) { - Some(index) => index + 1, - None => 0 - }; - result.extend(c.into_iter().take(last_approve)); - }); - result - } - - /// Return a concatenated vector over all approvals of a voter as boolean. - /// The trailing zeros are removed. - fn all_approvals_of(who: &T::AccountId) -> Vec { - let mut all: Vec = vec![]; - let mut index = 0_u32; - loop { - let chunk = Self::approvals_of((who.clone(), index)); - if chunk.is_empty() { break; } - all.extend(Self::flag_to_bool(chunk)); - index += 1; - } - all - } - - /// Remove all approvals associated with one account. - fn remove_all_approvals_of(who: &T::AccountId) { - let mut index = 0; - loop { - let set = Self::approvals_of((who.clone(), index)); - if set.len() > 0 { - >::remove((who.clone(), index)); - index += 1; - } else { - break - } - } - } - - /// Calculates the offset value (stored pot) of a stake, based on the distance - /// to the last win_index, `t`. Regardless of the internal implementation, - /// it should always be used with the following structure: - /// - /// Given Stake of voter `V` being `x` and distance to last_win index `t`, the new weight - /// of `V` is `x + get_offset(x, t)`. - /// - /// In other words, this function returns everything extra that should be added - /// to a voter's stake value to get the correct weight. Indeed, zero is - /// returned if `t` is zero. - fn get_offset(stake: BalanceOf, t: VoteIndex) -> BalanceOf { - let decay_ratio: BalanceOf = T::DecayRatio::get().into(); - if t > 150 { return stake * decay_ratio } - let mut offset = stake; - let mut r = Zero::zero(); - let decay = decay_ratio + One::one(); - for _ in 0..t { - offset = offset.saturating_sub(offset / decay); - r += offset - } - r - } -} diff --git a/srml/elections/src/mock.rs b/srml/elections/src/mock.rs deleted file mode 100644 index 77b13d74a139f..0000000000000 --- a/srml/elections/src/mock.rs +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Mock file for election module. - -#![cfg(test)] - -use std::cell::RefCell; -use support::{ - StorageValue, StorageMap, parameter_types, assert_ok, - traits::{Get, ChangeMembers, Currency} -}; -use primitives::H256; -use sr_primitives::{ - Perbill, BuildStorage, testing::Header, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, -}; -use crate as elections; - - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} - -parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; -} -impl balances::Trait for Test { - type Balance = u64; - type OnNewAccount = (); - type OnFreeBalanceZero = (); - type Event = Event; - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} - -parameter_types! { - pub const CandidacyBond: u64 = 3; - pub const CarryCount: u32 = 2; - pub const InactiveGracePeriod: u32 = 1; - pub const VotingPeriod: u64 = 4; - pub const MinimumVotingLock: u64 = 5; -} - -thread_local! { - static VOTER_BOND: RefCell = RefCell::new(0); - static VOTING_FEE: RefCell = RefCell::new(0); - static PRESENT_SLASH_PER_VOTER: RefCell = RefCell::new(0); - static DECAY_RATIO: RefCell = RefCell::new(0); - static MEMBERS: RefCell> = RefCell::new(vec![]); -} - -pub struct VotingBond; -impl Get for VotingBond { - fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) } -} - -pub struct VotingFee; -impl Get for VotingFee { - fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) } -} - -pub struct PresentSlashPerVoter; -impl Get for PresentSlashPerVoter { - fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) } -} - -pub struct DecayRatio; -impl Get for DecayRatio { - fn get() -> u32 { DECAY_RATIO.with(|v| *v.borrow()) } -} - -pub struct TestChangeMembers; -impl ChangeMembers for TestChangeMembers { - fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { - let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); - old_plus_incoming.extend_from_slice(incoming); - old_plus_incoming.sort(); - let mut new_plus_outgoing = new.to_vec(); - new_plus_outgoing.extend_from_slice(outgoing); - new_plus_outgoing.sort(); - assert_eq!(old_plus_incoming, new_plus_outgoing); - - MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); - } -} - -impl elections::Trait for Test { - type Event = Event; - type Currency = Balances; - type BadPresentation = (); - type BadReaper = (); - type BadVoterIndex = (); - type LoserCandidate = (); - type ChangeMembers = TestChangeMembers; - type CandidacyBond = CandidacyBond; - type VotingBond = VotingBond; - type VotingFee = VotingFee; - type MinimumVotingLock = MinimumVotingLock; - type PresentSlashPerVoter = PresentSlashPerVoter; - type CarryCount = CarryCount; - type InactiveGracePeriod = InactiveGracePeriod; - type VotingPeriod = VotingPeriod; - type DecayRatio = DecayRatio; -} - -pub type Block = sr_primitives::generic::Block; -pub type UncheckedExtrinsic = sr_primitives::generic::UncheckedExtrinsic; - -support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Module, Call, Event}, - Balances: balances::{Module, Call, Event, Config, Error}, - Elections: elections::{Module, Call, Event, Config}, - } -); - -pub struct ExtBuilder { - balance_factor: u64, - decay_ratio: u32, - desired_seats: u32, - voting_fee: u64, - voter_bond: u64, - bad_presentation_punishment: u64, -} - -impl Default for ExtBuilder { - fn default() -> Self { - Self { - balance_factor: 1, - decay_ratio: 24, - desired_seats: 2, - voting_fee: 0, - voter_bond: 0, - bad_presentation_punishment: 1, - } - } -} - -impl ExtBuilder { - pub fn balance_factor(mut self, factor: u64) -> Self { - self.balance_factor = factor; - self - } - pub fn decay_ratio(mut self, ratio: u32) -> Self { - self.decay_ratio = ratio; - self - } - pub fn voting_fee(mut self, fee: u64) -> Self { - self.voting_fee = fee; - self - } - pub fn bad_presentation_punishment(mut self, fee: u64) -> Self { - self.bad_presentation_punishment = fee; - self - } - pub fn voter_bond(mut self, fee: u64) -> Self { - self.voter_bond = fee; - self - } - pub fn desired_seats(mut self, seats: u32) -> Self { - self.desired_seats = seats; - self - } - pub fn build(self) -> runtime_io::TestExternalities { - VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond); - VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee); - PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment); - DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio); - GenesisConfig { - balances: Some(balances::GenesisConfig::{ - balances: vec![ - (1, 10 * self.balance_factor), - (2, 20 * self.balance_factor), - (3, 30 * self.balance_factor), - (4, 40 * self.balance_factor), - (5, 50 * self.balance_factor), - (6, 60 * self.balance_factor) - ], - vesting: vec![], - }), - elections: Some(elections::GenesisConfig::{ - members: vec![], - desired_seats: self.desired_seats, - presentation_duration: 2, - term_duration: 5, - }), - }.build_storage().unwrap().into() - } -} - -pub(crate) fn voter_ids() -> Vec { - Elections::all_voters().iter().map(|v| v.unwrap_or(0) ).collect::>() -} - -pub(crate) fn vote(i: u64, l: usize) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!( - Elections::set_approvals( - Origin::signed(i), - (0..l).map(|_| true).collect::>(), - 0, - 0, - 20, - ) - ); -} - -pub(crate) fn vote_at(i: u64, l: usize, index: elections::VoteIndex) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!( - Elections::set_approvals( - Origin::signed(i), - (0..l).map(|_| true).collect::>(), - 0, - index, - 20, - ) - ); -} - -pub(crate) fn create_candidate(i: u64, index: u32) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!(Elections::submit_candidacy(Origin::signed(i), index)); -} - -pub(crate) fn balances(who: &u64) -> (u64, u64) { - (Balances::free_balance(who), Balances::reserved_balance(who)) -} - -pub(crate) fn locks(who: &u64) -> Vec { - Balances::locks(who).iter().map(|l| l.amount).collect::>() -} - -pub(crate) fn new_test_ext_with_candidate_holes() -> runtime_io::TestExternalities { - let mut t = ExtBuilder::default().build(); - t.execute_with(|| { - >::put(vec![0, 0, 1]); - elections::CandidateCount::put(1); - >::insert(1, (0, 2)); - }); - t -} diff --git a/srml/elections/src/tests.rs b/srml/elections/src/tests.rs deleted file mode 100644 index c9bb054ab2353..0000000000000 --- a/srml/elections/src/tests.rs +++ /dev/null @@ -1,1681 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for election module. - -#![cfg(test)] - -use crate::mock::*; -use crate::*; - -use support::{assert_ok, assert_err, assert_noop}; - -#[test] -fn params_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::next_vote_from(1), 4); - assert_eq!(Elections::next_vote_from(4), 4); - assert_eq!(Elections::next_vote_from(5), 8); - assert_eq!(Elections::vote_index(), 0); - assert_eq!(Elections::presentation_duration(), 2); - assert_eq!(Elections::term_duration(), 5); - assert_eq!(Elections::desired_seats(), 2); - - assert_eq!(Elections::members(), vec![]); - assert_eq!(Elections::next_tally(), Some(4)); - assert_eq!(Elections::presentation_active(), false); - assert_eq!(Elections::next_finalize(), None); - - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(Elections::is_a_candidate(&1), false); - assert_eq!(Elections::candidate_reg_info(1), None); - - assert_eq!(Elections::voters(0), Vec::>::new()); - assert_eq!(Elections::voter_info(1), None); - assert_eq!(Elections::all_approvals_of(&1), vec![]); - }); -} - -#[test] -fn chunking_bool_to_flag_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::bool_to_flag(vec![]), vec![]); - assert_eq!(Elections::bool_to_flag(vec![false]), vec![0]); - assert_eq!(Elections::bool_to_flag(vec![true]), vec![1]); - assert_eq!(Elections::bool_to_flag(vec![true, true, true, true]), vec![15]); - assert_eq!(Elections::bool_to_flag(vec![true, true, true, true, true]), vec![15 + 16]); - - let set_1 = vec![ - true, false, false, false, // 0x1 - false, true, true, true, // 0xE - ]; - assert_eq!( - Elections::bool_to_flag(set_1.clone()), - vec![0x00_00_00_E1_u32] - ); - assert_eq!( - Elections::flag_to_bool(vec![0x00_00_00_E1_u32]), - set_1 - ); - - let set_2 = vec![ - false, false, false, true, // 0x8 - false, true, false, true, // 0xA - ]; - assert_eq!( - Elections::bool_to_flag(set_2.clone()), - vec![0x00_00_00_A8_u32] - ); - assert_eq!( - Elections::flag_to_bool(vec![0x00_00_00_A8_u32]), - set_2 - ); - - let mut rhs = (0..100/APPROVAL_FLAG_LEN).map(|_| 0xFFFFFFFF_u32).collect::>(); - // NOTE: this might be need change based on `APPROVAL_FLAG_LEN`. - rhs.extend(vec![0x00_00_00_0F]); - assert_eq!( - Elections::bool_to_flag((0..100).map(|_| true).collect()), - rhs - ) - }) -} - -#[test] -fn chunking_voter_set_growth_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - // create 65. 64 (set0) + 1 (set1) - (1..=63).for_each(|i| vote(i, 0)); - assert_eq!(Elections::next_nonfull_voter_set(), 0); - vote(64, 0); - assert_eq!(Elections::next_nonfull_voter_set(), 1); - vote(65, 0); - - let set1 = Elections::voters(0); - let set2 = Elections::voters(1); - - assert_eq!(set1.len(), 64); - assert_eq!(set2.len(), 1); - - assert_eq!(set1[0], Some(1)); - assert_eq!(set1[10], Some(11)); - assert_eq!(set2[0], Some(65)); - }) -} - -#[test] -fn chunking_voter_set_reclaim_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - (1..=129).for_each(|i| vote(i, 0)); - assert_eq!(Elections::next_nonfull_voter_set(), 2); - - assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); - - assert_ok!(Elections::retract_voter(Origin::signed(66), 65)); - assert_ok!(Elections::retract_voter(Origin::signed(67), 66)); - - // length does not show it but holes do exist. - assert_eq!(Elections::voters(0).len(), 64); - assert_eq!(Elections::voters(1).len(), 64); - assert_eq!(Elections::voters(2).len(), 1); - - assert_eq!(Elections::voters(0)[10], None); - assert_eq!(Elections::voters(1)[1], None); - assert_eq!(Elections::voters(1)[2], None); - // Next set with capacity is 2. - assert_eq!(Elections::next_nonfull_voter_set(), 2); - - // But we can fill a hole. - vote_at(130, 0, 10); - - // Nothing added to set 2. A hole was filled. - assert_eq!(Elections::voters(0).len(), 64); - assert_eq!(Elections::voters(1).len(), 64); - assert_eq!(Elections::voters(2).len(), 1); - - // and the next two (scheduled) to the second set. - assert_eq!(Elections::next_nonfull_voter_set(), 2); - }) -} - -#[test] -fn chunking_approvals_set_growth_should_work() { - ExtBuilder::default().build().execute_with(|| { - // create candidates and voters. - (1..=250).for_each(|i| create_candidate(i, (i-1) as u32)); - (1..=250).for_each(|i| vote(i, i as usize)); - - // all approvals of should return the exact expected vector. - assert_eq!( - Elections::all_approvals_of(&180), - (0..180).map(|_| true).collect::>() - ); - assert_eq!( - Elections::all_approvals_of(&32), - (0..32).map(|_| true).collect::>() - ); - assert_eq!( - Elections::all_approvals_of(&8), - (0..8).map(|_| true).collect::>() - ); - assert_eq!( - Elections::all_approvals_of(&64), - (0..64).map(|_| true).collect::>() - ); - assert_eq!( - Elections::all_approvals_of(&65), - (0..65).map(|_| true).collect::>() - ); - assert_eq!( - Elections::all_approvals_of(&63), - (0..63).map(|_| true).collect::>() - ); - - // NOTE: assuming that APPROVAL_SET_SIZE is more or less small-ish. Might fail otherwise. - let full_sets = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; - let left_over = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; - let rem = 180 % APPROVAL_FLAG_LEN; - - // grab and check the last full set, if it exists. - if full_sets > 0 { - assert_eq!( - Elections::approvals_of((180, (full_sets-1) as SetIndex )), - Elections::bool_to_flag( - (0..APPROVAL_SET_SIZE * APPROVAL_FLAG_LEN) - .map(|_| true).collect::>() - ) - ); - } - - // grab and check the last, half-empty, set. - if left_over > 0 { - assert_eq!( - Elections::approvals_of((180, full_sets as SetIndex)), - Elections::bool_to_flag( - (0..left_over * APPROVAL_FLAG_LEN + rem) - .map(|_| true).collect::>() - ) - ); - } - }) -} - -#[test] -fn chunking_cell_status_works() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - (1..=63).for_each(|i| vote(i, 0)); - - assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); - assert_ok!(Elections::retract_voter(Origin::signed(21), 20)); - - assert_eq!(Elections::cell_status(0, 10), CellStatus::Hole); - assert_eq!(Elections::cell_status(0, 0), CellStatus::Occupied); - assert_eq!(Elections::cell_status(0, 20), CellStatus::Hole); - assert_eq!(Elections::cell_status(0, 63), CellStatus::Head); - assert_eq!(Elections::cell_status(1, 0), CellStatus::Head); - assert_eq!(Elections::cell_status(1, 10), CellStatus::Head); - }) -} - -#[test] -fn chunking_voter_index_does_not_take_holes_into_account() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - // create 65. 64 (set0) + 1 (set1) - (1..=65).for_each(|i| vote(i, 0)); - - // account 65 has global index 65. - assert_eq!(Elections::voter_at(64).unwrap(), 65); - - assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); - - // still the same. These holes are in some other set. - assert_eq!(Elections::voter_at(64).unwrap(), 65); - // proof: can submit a new approval with the old index. - assert_noop!( - Elections::set_approvals(Origin::signed(65), vec![], 0, 64 - 2, 10), - "wrong voter index" - ); - assert_ok!(Elections::set_approvals(Origin::signed(65), vec![], 0, 64, 10)); - }) -} - -#[test] -fn chunking_approval_storage_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false], 0, 0, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 0, 40)); - - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - // NOTE: these two are stored in mem differently though. - assert_eq!(Elections::all_approvals_of(&3), vec![]); - assert_eq!(Elections::all_approvals_of(&4), vec![]); - - assert_eq!(Elections::approvals_of((3, 0)), vec![0]); - assert_eq!(Elections::approvals_of((4, 0)), vec![]); - }); -} - -#[test] -fn voting_initial_set_approvals_ignores_voter_index() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - // Last argument is essentially irrelevant. You might get or miss a tip. - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 5, 40)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![], 0, 100, 50)); - - // indices are more or less ignored. all is pushed. - assert_eq!(voter_ids(), vec![3, 4, 5]); - }) -} -#[test] -fn voting_bad_approval_index_slashes_voters_and_bond_reduces_stake() { - ExtBuilder::default().voting_fee(5).voter_bond(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - (1..=63).for_each(|i| vote(i, 0)); - assert_eq!(balances(&1), (13, 2)); - assert_eq!(balances(&10), (18, 2)); - assert_eq!(balances(&60), (18, 2)); - - // still no fee - vote(64, 0); - assert_eq!(balances(&64), (18, 2)); - assert_eq!( - Elections::voter_info(&64).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 20, pot:0 } - ); - - assert_eq!(Elections::next_nonfull_voter_set(), 1); - - // now we charge the next voter. - vote(65, 0); - assert_eq!(balances(&65), (13, 2)); - assert_eq!( - Elections::voter_info(&65).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 15, pot:0 } - ); - }); -} - -#[test] -fn voting_subsequent_set_approvals_checks_voter_index() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 5, 40)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![], 0, 100, 50)); - - // invalid index - assert_noop!( - Elections::set_approvals(Origin::signed(4), vec![true], 0, 5, 40), - "invalid voter index" - ); - // wrong index - assert_noop!( - Elections::set_approvals(Origin::signed(4), vec![true], 0, 0, 40), - "wrong voter index" - ); - // correct - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1, 40)); - }) -} - -#[test] -fn voting_cannot_lock_less_than_limit() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - assert_noop!( - Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 4), - "locked value must be more than limit", - ); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 5)); - }); -} - -#[test] -fn voting_locking_more_than_total_balance_is_moot() { - ExtBuilder::default().voter_bond(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - assert_eq!(balances(&3), (30, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 35)); - - assert_eq!(balances(&3), (28, 2)); - assert_eq!( - Elections::voter_info(&3).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 30, pot:0 } - ); - }); -} - -#[test] -fn voting_locking_stake_and_reserving_bond_works() { - ExtBuilder::default().voter_bond(2).build().execute_with(|| { - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - - assert_eq!(balances(&2), (20, 0)); - assert_eq!(locks(&2), vec![]); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![], 0, 0, 15)); - assert_eq!(balances(&2), (18, 2)); - assert_eq!(locks(&2), vec![15]); - - // deposit a bit more. - let _ = Balances::make_free_balance_be(&2, 100); - - // change vote - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 70)); - assert_eq!(balances(&2), (100, 2)); - assert_eq!(locks(&2), vec![70]); - - assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); - - assert_eq!(balances(&2), (102, 0)); - assert_eq!(locks(&2), vec![]); - }); -} - -#[test] -fn voting_without_any_candidate_count_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - - assert_eq!(Elections::candidates().len(), 0); - - assert_noop!( - Elections::set_approvals(Origin::signed(4), vec![], 0, 0, 40), - "amount of candidates to receive approval votes should be non-zero" - ); - }); -} - -#[test] -fn voting_setting_an_approval_vote_count_more_than_candidate_count_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_eq!(Elections::candidates().len(), 1); - - assert_noop!( - Elections::set_approvals(Origin::signed(4),vec![true, true], 0, 0, 40), - "amount of candidate votes cannot exceed amount of candidates" - ); - }); -} - -#[test] -fn voting_resubmitting_approvals_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 0, 40)); - - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_eq!(Elections::candidates().len(), 3); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true, false, true], 0, 0, 40)); - - assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); - }); -} - -#[test] -fn voting_retracting_voter_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_eq!(Elections::candidates().len(), 1); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 1, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![true], 0, 2, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 3, 40)); - - assert_eq!(voter_ids(), vec![1, 2, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - assert_eq!(Elections::all_approvals_of(&3), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); - - assert_eq!(voter_ids(), vec![0, 2, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - assert_eq!(Elections::all_approvals_of(&3), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); - - assert_eq!(voter_ids(), vec![0, 0, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&3), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::retract_voter(Origin::signed(3), 2)); - - assert_eq!(voter_ids(), vec![0, 0, 0, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&3), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - }); -} - -#[test] -fn voting_invalid_retraction_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_eq!(voter_ids(), vec![1, 2]); - assert_noop!(Elections::retract_voter(Origin::signed(1), 1), "retraction index mismatch"); - }); -} - -#[test] -fn voting_overflow_retraction_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_noop!(Elections::retract_voter(Origin::signed(1), 1), "retraction index invalid"); - }); -} - -#[test] -fn voting_non_voter_retraction_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_noop!(Elections::retract_voter(Origin::signed(2), 0), "cannot retract non-voter"); - }); -} - -#[test] -fn retracting_inactive_voter_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_ok!(Elections::reap_inactive_voter(Origin::signed(5), - (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), - 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![0, 5]); - assert_eq!(Elections::all_approvals_of(&2).len(), 0); - assert_eq!(Balances::total_balance(&2), 20); - assert_eq!(Balances::total_balance(&5), 50); - }); -} - -#[test] -fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { - ExtBuilder::default().voter_bond(2).build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(11); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - - assert_ok!(Elections::reap_inactive_voter(Origin::signed(5), - (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), - 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![0, 5]); - assert_eq!(Elections::all_approvals_of(&2).len(), 0); - }); -} - -#[test] -fn retracting_inactive_voter_with_bad_reporter_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!(Elections::reap_inactive_voter(Origin::signed(2), - 42, - 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - ), "invalid reporter index"); - }); -} - -#[test] -fn retracting_inactive_voter_with_bad_target_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!(Elections::reap_inactive_voter(Origin::signed(2), - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2, 42, - 2 - ), "invalid target index"); - }); -} - -#[test] -fn retracting_active_voter_should_slash_reporter() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 2)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false, false, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, false, false], 0, 0, 30)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, true, false], 0, 0, 40)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20 + Elections::get_offset(20, 1), 1)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30 + Elections::get_offset(30, 1), 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::vote_index(), 2); - assert_eq!(::InactiveGracePeriod::get(), 1); - assert_eq!(::VotingPeriod::get(), 4); - assert_eq!(Elections::voter_info(4), Some(VoterInfo { last_win: 1, last_active: 0, stake: 40, pot: 0 })); - - assert_ok!(Elections::reap_inactive_voter(Origin::signed(4), - (voter_ids().iter().position(|&i| i == 4).unwrap() as u32).into(), - 2, - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![2, 3, 0, 5]); - assert_eq!(Elections::all_approvals_of(&4).len(), 0); - assert_eq!(Balances::total_balance(&4), 40); - }); -} - -#[test] -fn retracting_inactive_voter_by_nonvoter_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!(Elections::reap_inactive_voter(Origin::signed(4), - 0, - 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - ), "reporter must be a voter"); - }); -} - -#[test] -fn candidacy_simple_candidate_submission_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(Elections::candidate_reg_info(1), None); - assert_eq!(Elections::candidate_reg_info(2), None); - assert_eq!(Elections::is_a_candidate(&1), false); - assert_eq!(Elections::is_a_candidate(&2), false); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); - assert_eq!(Elections::candidate_reg_info(2), None); - assert_eq!(Elections::is_a_candidate(&1), true); - assert_eq!(Elections::is_a_candidate(&2), false); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_eq!(Elections::candidates(), vec![1, 2]); - assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); - assert_eq!(Elections::candidate_reg_info(2), Some((0, 1))); - assert_eq!(Elections::is_a_candidate(&1), true); - assert_eq!(Elections::is_a_candidate(&2), true); - }); -} - -#[test] -fn candidacy_submission_using_free_slot_should_work() { - let mut t = new_test_ext_with_candidate_holes(); - - t.execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::candidates(), vec![0, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_eq!(Elections::candidates(), vec![0, 2, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - assert_eq!(Elections::candidates(), vec![3, 2, 1]); - }); -} - -#[test] -fn candidacy_submission_using_alternative_free_slot_should_work() { - let mut t = new_test_ext_with_candidate_holes(); - - t.execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::candidates(), vec![0, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_eq!(Elections::candidates(), vec![2, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - assert_eq!(Elections::candidates(), vec![2, 3, 1]); - }); -} - -#[test] -fn candidacy_submission_not_using_free_slot_should_not_work() { - let mut t = new_test_ext_with_candidate_holes(); - - t.execute_with(|| { - System::set_block_number(1); - assert_noop!( - Elections::submit_candidacy(Origin::signed(4), 3), - "invalid candidate slot" - ); - }); -} - -#[test] -fn candidacy_bad_candidate_slot_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_noop!( - Elections::submit_candidacy(Origin::signed(1), 1), - "invalid candidate slot" - ); - }); -} - -#[test] -fn candidacy_non_free_candidate_slot_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_noop!( - Elections::submit_candidacy(Origin::signed(2), 0), - "invalid candidate slot" - ); - }); -} - -#[test] -fn candidacy_dupe_candidate_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_noop!( - Elections::submit_candidacy(Origin::signed(1), 1), - "duplicate candidate submission" - ); - }); -} - -#[test] -fn candidacy_poor_candidate_submission_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_noop!( - Elections::submit_candidacy(Origin::signed(7), 0), - "candidate has not enough funds" - ); - }); -} - -#[test] -fn election_voting_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1, 40)); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(voter_ids(), vec![1, 4]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true, true], 0, 2, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, true], 0, 3, 30)); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(Elections::all_approvals_of(&2), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); - - assert_eq!(voter_ids(), vec![1, 4, 2, 3]); - }); -} - -#[test] -fn election_proxy_voting_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - - >::insert(11, 1); - >::insert(12, 2); - >::insert(13, 3); - >::insert(14, 4); - assert_ok!( - Elections::proxy_set_approvals(Origin::signed(11), vec![true], 0, 0, 10) - ); - assert_ok!( - Elections::proxy_set_approvals(Origin::signed(14), vec![true], 0, 1, 40) - ); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(voter_ids(), vec![1, 4]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - - assert_ok!( - Elections::proxy_set_approvals(Origin::signed(12), vec![false, true], 0, 2, 20) - ); - assert_ok!( - Elections::proxy_set_approvals(Origin::signed(13), vec![false, true], 0, 3, 30) - ); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(Elections::all_approvals_of(&2), vec![false, true]); - assert_eq!(Elections::all_approvals_of(&3), vec![false, true]); - - assert_eq!(voter_ids(), vec![1, 4, 2, 3]); - }); -} - -#[test] -fn election_simple_tally_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_eq!(voter_ids(), vec![2, 5]); - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - assert_eq!(Elections::all_approvals_of(&5), vec![false, true]); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - - assert!(!Elections::is_a_candidate(&2)); - assert!(!Elections::is_a_candidate(&5)); - assert_eq!(Elections::vote_index(), 1); - assert_eq!( - Elections::voter_info(2), - Some(VoterInfo { last_win: 1, last_active: 0, stake: 20, pot: 0 }) - ); - assert_eq!( - Elections::voter_info(5), - Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 }) - ); - }); -} - -#[test] -fn election_seats_should_be_released() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - let mut current = System::block_number(); - let free_block; - loop { - current += 1; - System::set_block_number(current); - assert_ok!(Elections::end_block(System::block_number())); - if Elections::members().len() == 0 { - free_block = current; - break; - } - } - // 11 + 2 which is the next voting period. - assert_eq!(free_block, 14); - }); -} - -#[test] -fn election_presentations_with_zero_staked_deposit_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_noop!( - Elections::present_winner(Origin::signed(4), 2, 0, 0), - "stake deposited to present winner and be added to leaderboard should be non-zero" - ); - }); -} - -#[test] -fn election_double_presentations_should_be_punished() { - ExtBuilder::default().build().execute_with(|| { - assert!(Balances::can_slash(&4, 10)); - - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Err("duplicate presentation")); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - assert_eq!(Balances::total_balance(&4), 38); - }); -} - -#[test] -fn election_presenting_for_double_election_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - // NOTE: This is now mandatory to disable the lock - assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); - assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 1, 0, 20)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_noop!( - Elections::present_winner(Origin::signed(4), 2, 20, 1), - "candidate must not form a duplicated member if elected" - ); - }); -} - -#[test] -fn election_presenting_loser_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - - assert_eq!(Elections::leaderboard(), Some(vec![ - (30, 3), - (40, 4), - (50, 5), - (60, 1) - ])); - - assert_noop!(Elections::present_winner(Origin::signed(4), 2, 20, 0), "candidate not worthy of leaderboard"); - }); -} - -#[test] -fn election_presenting_loser_first_should_not_matter() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - - assert_eq!(Elections::leaderboard(), Some(vec![ - (30, 3), - (40, 4), - (50, 5), - (60, 1) - ])); - }); -} - -#[test] -fn election_present_outside_of_presentation_period_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - assert_noop!( - Elections::present_winner(Origin::signed(5), 5, 1, 0), - "cannot present outside of presentation period" - ); - }); -} - -#[test] -fn election_present_with_invalid_vote_index_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_noop!(Elections::present_winner(Origin::signed(4), 2, 20, 1), "index not current"); - }); -} - -#[test] -fn election_present_when_presenter_is_poor_should_not_work() { - let test_present = |p| { - ExtBuilder::default() - .voting_fee(5) - .voter_bond(2) - .bad_presentation_punishment(p) - .build() - .execute_with(|| { - System::set_block_number(4); - let _ = Balances::make_free_balance_be(&1, 15); - assert!(!Elections::presentation_active()); - - // -3 - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Balances::free_balance(&1), 12); - // -2 -5 - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 15)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_eq!(Balances::free_balance(&1), 5); - assert_eq!(Balances::reserved_balance(&1), 5); - if p > 5 { - assert_noop!(Elections::present_winner( - Origin::signed(1), 1, 10, 0), - "presenter must have sufficient slashable funds" - ); - } else { - assert_ok!(Elections::present_winner(Origin::signed(1), 1, 10, 0)); - } - }); - }; - test_present(4); - test_present(6); -} - -#[test] -fn election_invalid_present_tally_should_slash() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - assert_eq!(Balances::total_balance(&4), 40); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_err!(Elections::present_winner(Origin::signed(4), 2, 80, 0), "incorrect total"); - - assert_eq!(Balances::total_balance(&4), 38); - }); -} - -#[test] -fn election_runners_up_should_be_kept() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - // leaderboard length is the empty seats plus the carry count (i.e. 5 + 2), where those - // to be carried are the lowest and stored in lowest indices - assert_eq!(Elections::leaderboard(), Some(vec![ - (0, 0), - (0, 0), - (0, 0), - (60, 1) - ])); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_eq!(Elections::leaderboard(), Some(vec![ - (30, 3), - (40, 4), - (50, 5), - (60, 1) - ])); - - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(1, 11), (5, 11)]); - - assert!(!Elections::is_a_candidate(&1)); - assert!(!Elections::is_a_candidate(&5)); - assert!(!Elections::is_a_candidate(&2)); - assert!(Elections::is_a_candidate(&3)); - assert!(Elections::is_a_candidate(&4)); - assert_eq!(Elections::vote_index(), 1); - assert_eq!(Elections::voter_info(2), Some(VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0 })); - assert_eq!(Elections::voter_info(3), Some(VoterInfo { last_win: 0, last_active: 0, stake: 30, pot: 0 })); - assert_eq!(Elections::voter_info(4), Some(VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0 })); - assert_eq!(Elections::voter_info(5), Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 })); - assert_eq!(Elections::voter_info(6), Some(VoterInfo { last_win: 1, last_active: 0, stake: 60, pot: 0 })); - assert_eq!(Elections::candidate_reg_info(3), Some((0, 2))); - assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); - }); -} - -#[test] -fn election_second_tally_should_use_runners_up() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![false, false, true, false], 1, 0, 60)); - assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30 + Elections::get_offset(30, 1) + 60, 1)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40 + Elections::get_offset(40, 1), 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(1, 11), (5, 11), (3, 15)]); - - assert!(!Elections::is_a_candidate(&1)); - assert!(!Elections::is_a_candidate(&2)); - assert!(!Elections::is_a_candidate(&3)); - assert!(!Elections::is_a_candidate(&5)); - assert!(Elections::is_a_candidate(&4)); - assert_eq!(Elections::vote_index(), 2); - assert_eq!(Elections::voter_info(2), Some( VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0})); - assert_eq!(Elections::voter_info(3), Some( VoterInfo { last_win: 2, last_active: 0, stake: 30, pot: 0})); - assert_eq!(Elections::voter_info(4), Some( VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0})); - assert_eq!(Elections::voter_info(5), Some( VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0})); - assert_eq!( - Elections::voter_info(6), - Some(VoterInfo { last_win: 2, last_active: 1, stake: 60, pot: 0}) - ); - - assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); - }); -} - -#[test] -fn election_loser_candidates_bond_gets_slashed() { - ExtBuilder::default().desired_seats(1).build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - - assert_eq!(balances(&2), (17, 3)); - - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 0, 0, 50)); - assert_ok!( - Elections::set_approvals(Origin::signed(1), vec![false, true, true, true], 0, 0, 10) - ); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 10, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(3), 3, 10, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(2), 2, 10, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 50, 0), Ok(())); - - - // winner + carry - assert_eq!(Elections::leaderboard(), Some(vec![(10, 3), (10, 4), (50, 1)])); - assert_ok!(Elections::end_block(System::block_number())); - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(1, 11)]); - - // account 2 is not a runner up or in leaderboard. - assert_eq!(balances(&2), (17, 0)); - }); -} - -#[test] -fn pot_accumulating_weight_and_decaying_should_work() { - ExtBuilder::default().balance_factor(10).build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); - - assert_ok!( - Elections::set_approvals(Origin::signed(6), vec![true, false, false], 0, 0, 600) - ); - assert_ok!( - Elections::set_approvals(Origin::signed(5), vec![false, true, false], 0, 0, 500) - ); - assert_ok!( - Elections::set_approvals(Origin::signed(1), vec![false, false, true], 0, 0, 100) - ); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 1, last_active: 0, stake: 600, pot: 0}, - ); - assert_eq!( - Elections::voter_info(5).unwrap(), - VoterInfo { last_win: 1, last_active: 0, stake: 500, pot: 0}, - ); - assert_eq!( - Elections::voter_info(1).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}, - ); - - System::set_block_number(12); - // retract needed to unlock approval funds => submit candidacy again. - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!( - Elections::set_approvals(Origin::signed(6), vec![true, false, false], 1, 0, 600) - ); - assert_ok!( - Elections::set_approvals(Origin::signed(5), vec![false, true, false], 1, 1, 500) - ); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 1), 1), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 19), (5, 19)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 2, last_active: 1, stake: 600, pot:0 } - ); - assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 2, last_active: 1, stake: 500, pot:0 }); - assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot:0 }); - - System::set_block_number(20); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 2, 0, 600)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 2, 1, 500)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(22); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 2), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 2), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 2), 2), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96 + 93, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 27), (5, 27)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 3, last_active: 2, stake: 600, pot: 0} - ); - assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 3, last_active: 2, stake: 500, pot: 0}); - assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); - - - System::set_block_number(28); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 3, 0, 600)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 3, 1, 500)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(30); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 3), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 3), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 3), 3), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96 + 93 + 90, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 35), (5, 35)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 4, last_active: 3, stake: 600, pot: 0} - ); - assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 4, last_active: 3, stake: 500, pot: 0}); - assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); - }) -} - -#[test] -fn pot_winning_resets_accumulated_pot() { - ExtBuilder::default().balance_factor(10).build().execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 3)); - - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false, false], 0, 0, 600)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, true, false, false], 0, 1, 400)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true, true], 0, 2, 300)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(300, 2), (300, 3), (400, 4), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (4, 11)]); - - System::set_block_number(12); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(4), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false, false], 1, 0, 600)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, true, false, false], 1, 1, 400)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300 + Elections::get_offset(300, 1), 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300 + Elections::get_offset(300, 1), 1), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(400, 4), (588, 2), (588, 3), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 19), (3, 19)]); - - System::set_block_number(20); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(22); - // 2 will not get re-elected with 300 + 288, instead just 300. - // because one of 3's candidates (3) won in previous round - // 4 on the other hand will get extra weight since it was unlucky. - assert_eq!(Elections::present_winner(Origin::signed(3), 2, 300, 2), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400 + Elections::get_offset(400, 1), 2), Ok(())); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(4, 27), (2, 27)]); - }) -} - -#[test] -fn pot_resubmitting_approvals_stores_pot() { - ExtBuilder::default() - .voter_bond(0) - .voting_fee(0) - .balance_factor(10) - .build() - .execute_with(|| { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); - - assert_ok!( - Elections::set_approvals(Origin::signed(6), vec![true, false, false], 0, 0, 600), - ); - assert_ok!( - Elections::set_approvals(Origin::signed(5), vec![false, true, false], 0, 1, 500), - ); - assert_ok!( - Elections::set_approvals(Origin::signed(1), vec![false, false, true], 0, 2, 100), - ); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - - System::set_block_number(12); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!( - Elections::set_approvals(Origin::signed(6), vec![true, false, false], 1, 0, 600), - ); - assert_ok!( - Elections::set_approvals(Origin::signed(5), vec![false, true, false], 1, 1, 500), - ); - // give 1 some new high balance - let _ = Balances::make_free_balance_be(&1, 997); - assert_ok!( - Elections::set_approvals(Origin::signed(1), vec![false, false, true], 1, 2, 1000), - ); - assert_eq!(Elections::voter_info(1).unwrap(), - VoterInfo { - stake: 1000, // 997 + 3 which is candidacy bond. - pot: Elections::get_offset(100, 1), - last_active: 1, - last_win: 1, - } - ); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); - assert_eq!( - Elections::present_winner(Origin::signed(1), 1, 1000 + 96 /* pot */, 1), - Ok(()), - ); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (500, 5), (600, 6), (1096, 1)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(1, 19), (6, 19)]); - }) -} - -#[test] -fn pot_get_offset_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Elections::get_offset(100, 0), 0); - assert_eq!(Elections::get_offset(100, 1), 96); - assert_eq!(Elections::get_offset(100, 2), 96 + 93); - assert_eq!(Elections::get_offset(100, 3), 96 + 93 + 90); - assert_eq!(Elections::get_offset(100, 4), 96 + 93 + 90 + 87); - // limit - assert_eq!(Elections::get_offset(100, 1000), 100 * 24); - - assert_eq!(Elections::get_offset(50_000_000_000, 0), 0); - assert_eq!(Elections::get_offset(50_000_000_000, 1), 48_000_000_000); - assert_eq!(Elections::get_offset(50_000_000_000, 2), 48_000_000_000 + 46_080_000_000); - assert_eq!(Elections::get_offset(50_000_000_000, 3), 48_000_000_000 + 46_080_000_000 + 44_236_800_000); - assert_eq!( - Elections::get_offset(50_000_000_000, 4), - 48_000_000_000 + 46_080_000_000 + 44_236_800_000 + 42_467_328_000 - ); - // limit - assert_eq!(Elections::get_offset(50_000_000_000, 1000), 50_000_000_000 * 24); - }) -} - -#[test] -fn pot_get_offset_with_zero_decay() { - ExtBuilder::default().decay_ratio(0).build().execute_with(|| { - assert_eq!(Elections::get_offset(100, 0), 0); - assert_eq!(Elections::get_offset(100, 1), 0); - assert_eq!(Elections::get_offset(100, 2), 0); - assert_eq!(Elections::get_offset(100, 3), 0); - // limit - assert_eq!(Elections::get_offset(100, 1000), 0); - }) -} diff --git a/srml/example/Cargo.toml b/srml/example/Cargo.toml deleted file mode 100644 index 695e0602fb327..0000000000000 --- a/srml/example/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "srml-example" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -balances = { package = "srml-balances", path = "../balances", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "sr-primitives/std", - "support/std", - "system/std", - "balances/std", - "runtime-io/std", - "rstd/std" -] diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs deleted file mode 100644 index c9d9d93cc7334..0000000000000 --- a/srml/example/src/lib.rs +++ /dev/null @@ -1,774 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Example Module -//! -//! -//! The Example: A simple example of a runtime module demonstrating -//! concepts, APIs and structures common to most runtime modules. -//! -//! Run `cargo doc --package srml-example --open` to view this module's documentation. -//! -//! ### Documentation Guidelines: -//! -//! -//! -//! -//! -//! ### Documentation Template:
-//! -//! Copy and paste this template from srml/example/src/lib.rs into file -//! `srml//src/lib.rs` of your own custom module and complete it. -//!

-//! // Add heading with custom module name
-//!
-//! \#  Module
-//!
-//! // Add simple description
-//!
-//! // Include the following links that shows what trait needs to be implemented to use the module
-//! // and the supported dispatchables that are documented in the Call enum.
-//!
-//! - \[`::Trait`](./trait.Trait.html)
-//! - \[`Call`](./enum.Call.html)
-//! - \[`Module`](./struct.Module.html)
-//!
-//! \## Overview
-//!
-//! 
-//! // Short description of module purpose.
-//! // Links to Traits that should be implemented.
-//! // What this module is for.
-//! // What functionality the module provides.
-//! // When to use the module (use case examples).
-//! // How it is used.
-//! // Inputs it uses and the source of each input.
-//! // Outputs it produces.
-//!
-//! 
-//! 
-//!
-//! \## Terminology
-//!
-//! // Add terminology used in the custom module. Include concepts, storage items, or actions that you think
-//! // deserve to be noted to give context to the rest of the documentation or module usage. The author needs to
-//! // use some judgment about what is included. We don't want a list of every storage item nor types - the user
-//! // can go to the code for that. For example, "transfer fee" is obvious and should not be included, but
-//! // "free balance" and "reserved balance" should be noted to give context to the module.
-//! // Please do not link to outside resources. The reference docs should be the ultimate source of truth.
-//!
-//! 
-//!
-//! \## Goals
-//!
-//! // Add goals that the custom module is designed to achieve.
-//!
-//! 
-//!
-//! \### Scenarios
-//!
-//! 
-//!
-//! \#### 
-//!
-//! // Describe requirements prior to interacting with the custom module.
-//! // Describe the process of interacting with the custom module for this scenario and public API functions used.
-//!
-//! \## Interface
-//!
-//! \### Supported Origins
-//!
-//! // What origins are used and supported in this module (root, signed, none)
-//! // i.e. root when \`ensure_root\` used
-//! // i.e. none when \`ensure_none\` used
-//! // i.e. signed when \`ensure_signed\` used
-//!
-//! \`inherent\` 
-//!
-//! 
-//! 
-//!
-//! \### Types
-//!
-//! // Type aliases. Include any associated types and where the user would typically define them.
-//!
-//! \`ExampleType\` 
-//!
-//! 
-//!
-//! // Reference documentation of aspects such as `storageItems` and `dispatchable` functions should only be
-//! // included in the https://docs.rs Rustdocs for Substrate and not repeated in the README file.
-//!
-//! \### Dispatchable Functions
-//!
-//! 
-//!
-//! // A brief description of dispatchable functions and a link to the rustdoc with their actual documentation.
-//!
-//! // MUST have link to Call enum
-//! // MUST have origin information included in function doc
-//! // CAN have more info up to the user
-//!
-//! \### Public Functions
-//!
-//! 
-//!
-//! // A link to the rustdoc and any notes about usage in the module, not for specific functions.
-//! // For example, in the balances module: "Note that when using the publicly exposed functions,
-//! // you (the runtime developer) are responsible for implementing any necessary checks
-//! // (e.g. that the sender is the signer) before calling a function that will affect storage."
-//!
-//! 
-//!
-//! // It is up to the writer of the respective module (with respect to how much information to provide).
-//!
-//! \#### Public Inspection functions - Immutable (getters)
-//!
-//! // Insert a subheading for each getter function signature
-//!
-//! \##### \`example_getter_name()\`
-//!
-//! // What it returns
-//! // Why, when, and how often to call it
-//! // When it could panic or error
-//! // When safety issues to consider
-//!
-//! \#### Public Mutable functions (changing state)
-//!
-//! // Insert a subheading for each setter function signature
-//!
-//! \##### \`example_setter_name(origin, parameter_name: T::ExampleType)\`
-//!
-//! // What state it changes
-//! // Why, when, and how often to call it
-//! // When it could panic or error
-//! // When safety issues to consider
-//! // What parameter values are valid and why
-//!
-//! \### Storage Items
-//!
-//! // Explain any storage items included in this module
-//!
-//! \### Digest Items
-//!
-//! // Explain any digest items included in this module
-//!
-//! \### Inherent Data
-//!
-//! // Explain what inherent data (if any) is defined in the module and any other related types
-//!
-//! \### Events:
-//!
-//! // Insert events for this module if any
-//!
-//! \### Errors:
-//!
-//! // Explain what generates errors
-//!
-//! \## Usage
-//!
-//! // Insert 2-3 examples of usage and code snippets that show how to
-//! // use  module in a custom module.
-//!
-//! \### Prerequisites
-//!
-//! // Show how to include necessary imports for  and derive
-//! // your module configuration trait with the `INSERT_CUSTOM_MODULE_NAME` trait.
-//!
-//! \```rust
-//! use ;
-//!
-//! pub trait Trait: ::Trait { }
-//! \```
-//!
-//! \### Simple Code Snippet
-//!
-//! // Show a simple example (e.g. how to query a public getter function of )
-//!
-//! \### Example from SRML
-//!
-//! // Show a usage example in an actual runtime
-//!
-//! // See:
-//! // - Substrate TCR https://github.com/parity-samples/substrate-tcr
-//! // - Substrate Kitties https://shawntabrizi.github.io/substrate-collectables-workshop/#/
-//!
-//! \## Genesis Config
-//!
-//! 
-//!
-//! \## Dependencies
-//!
-//! // Dependencies on other SRML modules and the genesis config should be mentioned,
-//! // but not the Rust Standard Library.
-//! // Genesis configuration modifications that may be made to incorporate this module
-//! // Interaction with other modules
-//!
-//! 
-//!
-//! \## Related Modules
-//!
-//! // Interaction with other modules in the form of a bullet point list
-//!
-//! \## References
-//!
-//! 
-//!
-//! // Links to reference material, if applicable. For example, Phragmen, W3F research, etc.
-//! // that the implementation is based on.
-//! 

- -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::marker::PhantomData; -use support::{dispatch::Result, decl_module, decl_storage, decl_event}; -use system::{ensure_signed, ensure_root}; -use codec::{Encode, Decode}; -use sr_primitives::{ - traits::{SignedExtension, Bounded, SaturatedConversion}, - weights::{SimpleDispatchInfo, DispatchInfo, DispatchClass, ClassifyDispatch, WeighData, Weight}, - transaction_validity::{ - ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, - }, -}; - -// A custom weight calculator tailored for the dispatch call `set_dummy()`. This actually examines -// the arguments and makes a decision based upon them. -// -// The `WeightData` trait has access to the arguments of the dispatch that it wants to assign a -// weight to. Nonetheless, the trait itself can not make any assumptions about what that type -// generic type of the arguments, `T`, is. Based on our needs, we could replace `T` with a more -// concrete type while implementing the trait. The `decl_module!` expects whatever implements -// `WeighData` to replace `T` with a tuple of the dispatch arguments. This is exactly how we will -// craft the implementation below. -// -// The rules of `WeightForSetDummy` is as follows: -// - The final weight of each dispatch is calculated as the argument of the call multiplied by the -// parameter given to the `WeightForSetDummy`'s constructor. -// - assigns a dispatch class `operational` if the argument of the call is more than 1000. -struct WeightForSetDummy(BalanceOf); - -impl WeighData<(&BalanceOf,)> for WeightForSetDummy -{ - fn weigh_data(&self, target: (&BalanceOf,)) -> Weight { - let multiplier = self.0; - (*target.0 * multiplier).saturated_into::() - } -} - -impl ClassifyDispatch<(&BalanceOf,)> for WeightForSetDummy { - fn classify_dispatch(&self, target: (&BalanceOf,)) -> DispatchClass { - if *target.0 > >::from(1000u32) { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} - -/// A type alias for the balance type from this module's point of view. -type BalanceOf = ::Balance; - -/// Our module's configuration trait. All our types and constants go in here. If the -/// module is dependent on specific other modules, then their configuration traits -/// should be added to our implied traits list. -/// -/// `system::Trait` should always be included in our implied traits. -pub trait Trait: balances::Trait { - /// The overarching event type. - 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(fn 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(fn bar): map T::AccountId => Vec<(T::Balance, u64)>; - // - // For basic value items, you'll get a type which implements - // `support::StorageValue`. For map items, you'll get a type which - // 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(fn dummy) config(): Option; - - // A map that has enumerable entries. - Bar get(fn bar) config(): linked_map T::AccountId => T::Balance; - - // this one uses the default, we'll demonstrate the usage of 'mutate' API. - Foo get(fn foo) config(): T::Balance; - } -} - -decl_event!( - /// Events are a 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. - 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. -// -// Anyone can have these functions execute by signing and submitting -// an extrinsic. Ensure that calls into each of these execute in a time, memory and -// using storage space proportional to any costs paid for by the caller or otherwise the -// difficulty of forcing the call to happen. -// -// Generally you'll want to split these into three groups: -// - Public calls that are signed by an external account. -// - Root calls that are allowed to be made only by the governance system. -// - Unsigned calls that can be of two kinds: -// * "Inherent extrinsics" that are opinions generally held by the block -// authors that build child blocks. -// * Unsigned Transactions that are of intrinsic recognisable utility to the -// network, and are validated by the runtime. -// -// Information about where this dispatch initiated from is provided as the first argument -// "origin". As such functions must always look like: -// -// `fn foo(origin, bar: Bar, baz: Baz) -> Result;` -// -// The `Result` is required as part of the syntax (and expands to the conventional dispatch -// result of `Result<(), &'static str>`). -// -// When you come to `impl` them later in the module, you must specify the full type for `origin`: -// -// `fn foo(origin: T::Origin, bar: Bar, baz: Baz) { ... }` -// -// There are three entries in the `system::Origin` enum that correspond -// to the above bullets: `::Signed(AccountId)`, `::Root` and `::None`. You should always match -// against them as the first thing you do in your function. There are three convenience calls -// in system that do the matching for you and return a convenient result: `ensure_signed`, -// `ensure_root` and `ensure_none`. -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 { - /// Deposit one of this module's events by using the default implementation. - /// It is also possible to provide a custom implementation. - /// For non-generic events, the generic parameter just needs to be dropped, so that it - /// looks like: `fn deposit_event() = default;`. - fn deposit_event() = default; - /// 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. - // This just increases the value of `Dummy` by `increase_by`. - // - // Since this is a dispatched function there are two extremely important things to - // remember: - // - // - MUST NOT PANIC: Under no circumstances (save, perhaps, storage getting into an - // irreparably damaged state) must this function panic. - // - NO SIDE-EFFECTS ON ERROR: This function must either complete totally (and return - // `Ok(())` or it must have no side-effects on storage and return `Err('Some reason')`. - // - // The first is relatively easy to audit for - just ensure all panickers are removed from - // logic that executes in production (which you do anyway, right?!). To ensure the second - // is followed, you should do all tests for validity at the top of your function. This - // is stuff like checking the sender (`origin`) or that state is such that the operation - // makes sense. - // - // Once you've determined that it's all good, then enact the operation and change storage. - // If you can't be certain that the operation will succeed without substantial computation - // then you have a classic blockchain attack scenario. The normal way of managing this is - // to attach a bond to the operation. As the first major alteration of storage, reserve - // some value from the sender's account (`Balances` module has a `reserve` function for - // exactly this scenario). This amount should be enough to cover any costs of the - // substantial execution in case it turns out that you can't proceed with the operation. - // - // If it eventually transpires that the operation is fine and, therefore, that the - // expense of the checks should be borne by the network, then you can refund the reserved - // deposit. If, however, the operation turns out to be invalid and the computation is - // wasted, then you can burn it or repatriate elsewhere. - // - // Security bonds ensure that attackers can't game it by ensuring that anyone interacting - // with the system either progresses it or pays for the trouble of faffing around with - // no progress. - // - // If you don't respect these rules, it is likely that your chain will be attackable. - // - // Each transaction can define an optional `#[weight]` attribute to convey a set of static - // information about its dispatch. The `system` and `executive` module then use this - // information to properly execute the transaction, whilst keeping the total load of the - // chain in a moderate rate. - // - // The _right-hand-side_ value of the `#[weight]` attribute can be any type that implements - // a set of traits, namely [`WeighData`] and [`ClassifyDispatch`]. The former conveys the - // weight (a numeric representation of pure execution time and difficulty) of the - // transaction and the latter demonstrates the `DispatchClass` of the call. A higher weight - // means a larger transaction (less of which can be placed in a single block). See the - // `CheckWeight` signed extension struct in the `system` module for more information. - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] - fn accumulate_dummy(origin, increase_by: T::Balance) -> Result { - // This is a public call, so we ensure that the origin is some signed account. - let _sender = ensure_signed(origin)?; - - // Read the value of dummy from storage. - // let dummy = Self::dummy(); - // Will also work using the `::get` on the storage item type itself: - // let dummy = >::get(); - - // Calculate the new value. - // let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by); - - // Put the new value into storage. - // >::put(new_dummy); - // Will also work with a reference: - // >::put(&new_dummy); - - // Here's the new one of read and then modify the value. - >::mutate(|dummy| { - let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by); - *dummy = Some(new_dummy); - }); - - // Let's deposit an event to let the outside world know this happened. - Self::deposit_event(RawEvent::Dummy(increase_by)); - - // All good. - Ok(()) - } - - /// A privileged call; in this case it resets our dummy value to something new. - // Implementation of a privileged call. The `origin` parameter is ROOT because - // it's not (directly) from an extrinsic, but rather the system as a whole has decided - // to execute it. Different runtimes have different reasons for allow privileged - // calls to be executed - we don't need to care why. Because it's privileged, we can - // assume it's a one-off operation and substantial processing/storage/memory can be used - // without worrying about gameability or attack scenarios. - // If you not specify `Result` explicitly as return value, it will be added automatically - // for you and `Ok(())` will be returned. - #[weight = WeightForSetDummy::(>::from(100u32))] - fn set_dummy(origin, #[compact] new_value: T::Balance) { - ensure_root(origin)?; - // Put the new value into storage. - >::put(new_value); - } - - // The signature could also look like: `fn on_initialize()` - fn on_initialize(_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_finalize()` - fn on_finalize(_n: T::BlockNumber) { - // Anything that needs to be done at the end of the block. - // We just kill our dummy storage item. - >::kill(); - } - - // A runtime code run after every block and have access to extended set of APIs. - // - // For instance you can generate extrinsics for the upcoming produced block. - fn offchain_worker(_n: T::BlockNumber) { - // We don't do anything here. - // but we could dispatch extrinsic (transaction/unsigned/inherent) using - // runtime_io::submit_extrinsic - } - } -} - -// 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 -// functions that do not write to storage and operation functions that do. -// - Private functions. These are your usual private utilities unavailable to other modules. -impl Module { - // Add public immutables and private mutables. - #[allow(dead_code)] - fn accumulate_foo(origin: T::Origin, increase_by: T::Balance) -> Result { - let _sender = ensure_signed(origin)?; - - let prev = >::get(); - // Because Foo has 'default', the type of 'foo' in closure is the raw type instead of an Option<> type. - let result = >::mutate(|foo| { - *foo = *foo + increase_by; - *foo - }); - assert!(prev + increase_by == result); - - Ok(()) - } -} - -// Similar to other SRML modules, your module can also define a signed extension and perform some -// checks and [pre/post]processing [before/after] the transaction. A signed extension can be any -// decodable type that implements `SignedExtension`. See the trait definition for the full list of -// bounds. As a convention, you can follow this approach to create an extension for your module: -// - If the extension does not carry any data, then use a tuple struct with just a `marker` -// (needed for the compiler to accept `T: Trait`) will suffice. -// - Otherwise, create a tuple struct which contains the external data. Of course, for the entire -// struct to be decodable, each individual item also needs to be decodable. -// -// Note that a signed extension can also indicate that a particular data must be present in the -// _signing payload_ of a transaction by providing an implementation for the `additional_signed` -// method. This example will not cover this type of extension. See `CheckRuntime` in system module -// for an example. -// -// Using the extension, you can add some hooks to the lifecycle of each transaction. Note that by -// default, an extension is applied to all `Call` functions (i.e. all transactions). the `Call` enum -// variant is given to each function of `SignedExtension`. Hence, you can filter based on module or -// a particular call if needed. -// -// Some extra information, such as encoded length, some static dispatch info like weight and the -// sender of the transaction (if signed) are also provided. -// -// The full list of hooks that can be added to a signed extension can be found -// [here](https://crates.parity.io/sr_primitives/traits/trait.SignedExtension.html). -// -// The signed extensions are aggregated in the runtime file of a substrate chain. All extensions -// should be aggregated in a tuple and passed to the `CheckedExtrinsic` and `UncheckedExtrinsic` -// types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and -// `node-template` for an example of this. - -/// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the -/// priority and prints some log. -/// -/// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No -/// particular reason why, just to demonstrate the power of signed extensions. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct WatchDummy(PhantomData); - -impl rstd::fmt::Debug for WatchDummy { - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "WatchDummy") - } -} - -impl SignedExtension for WatchDummy { - type AccountId = T::AccountId; - // Note that this could also be assigned to the top-level call enum. It is passed into the - // balances module directly and since `Trait: balances::Trait`, you could also use `T::Call`. - // In that case, you would have had access to all call variants and could match on variants from - // other modules. - type Call = Call; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } - - fn validate( - &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: DispatchInfo, - len: usize, - ) -> TransactionValidity { - // if the transaction is too big, just drop it. - if len > 200 { - return InvalidTransaction::ExhaustsResources.into() - } - - // check for `set_dummy` - match call { - Call::set_dummy(..) => { - sr_primitives::print("set_dummy was received."); - - let mut valid_tx = ValidTransaction::default(); - valid_tx.priority = Bounded::max_value(); - Ok(valid_tx) - } - _ => Ok(Default::default()), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use support::{assert_ok, impl_outer_origin, parameter_types}; - use primitives::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. - use sr_primitives::{ - Perbill, weights::GetDispatchInfo, testing::Header, - traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup}, - }; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - // For testing the module, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of modules we want to use. - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = (); - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - } - impl balances::Trait for Test { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - impl Trait for Test { - type Event = (); - } - type Example = Module; - - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. - fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. - balances::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); - GenesisConfig::{ - dummy: 42, - // we configure the map with (key, value) pairs. - bar: vec![(1, 2), (2, 3)], - foo: 24, - }.assimilate_storage(&mut t).unwrap(); - t.into() - } - - #[test] - fn it_works_for_optional_value() { - new_test_ext().execute_with(|| { - // Check that GenesisBuilder works properly. - assert_eq!(Example::dummy(), Some(42)); - - // Check that accumulate works when we have Some value in Dummy already. - assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); - assert_eq!(Example::dummy(), Some(69)); - - // Check that finalizing the block removes Dummy from storage. - >::on_finalize(1); - assert_eq!(Example::dummy(), None); - - // Check that accumulate works when we Dummy has None in it. - >::on_initialize(2); - assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); - assert_eq!(Example::dummy(), Some(42)); - }); - } - - #[test] - fn it_works_for_default_value() { - new_test_ext().execute_with(|| { - assert_eq!(Example::foo(), 24); - assert_ok!(Example::accumulate_foo(Origin::signed(1), 1)); - assert_eq!(Example::foo(), 25); - }); - } - - #[test] - fn signed_ext_watch_dummy_works() { - new_test_ext().execute_with(|| { - let call = >::set_dummy(10); - let info = DispatchInfo::default(); - - assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, info, 150) - .unwrap() - .priority, - Bounded::max_value(), - ); - assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, info, 250), - InvalidTransaction::ExhaustsResources.into(), - ); - }) - } - - #[test] - fn weights_work() { - // must have a default weight. - let default_call = >::accumulate_dummy(10); - let info = default_call.get_dispatch_info(); - // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` - assert_eq!(info.weight, 10_000); - - // must have a custom weight of `100 * arg = 2000` - let custom_call = >::set_dummy(20); - let info = custom_call.get_dispatch_info(); - assert_eq!(info.weight, 2000); - } -} diff --git a/srml/executive/Cargo.toml b/srml/executive/Cargo.toml deleted file mode 100644 index 92191a7aac4db..0000000000000 --- a/srml/executive/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "srml-executive" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -hex-literal = "0.2.1" -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -srml-indices = { path = "../indices" } -balances = { package = "srml-balances", path = "../balances" } -transaction-payment = { package = "srml-transaction-payment", path = "../transaction-payment" } - -[features] -default = ["std"] -std = [ - "rstd/std", - "support/std", - "serde", - "codec/std", - "sr-primitives/std", - "runtime-io/std", - "system/std", -] diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs deleted file mode 100644 index 401f07d2069e9..0000000000000 --- a/srml/executive/src/lib.rs +++ /dev/null @@ -1,645 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Executive Module -//! -//! The Executive module acts as the orchestration layer for the runtime. It dispatches incoming -//! extrinsic calls to the respective modules in the runtime. -//! -//! ## Overview -//! -//! The executive module is not a typical SRML module providing functionality around a specific feature. -//! It is a cross-cutting framework component for the SRML. It works in conjunction with the -//! [SRML System module](../srml_system/index.html) to perform these cross-cutting functions. -//! -//! The Executive module provides functions to: -//! -//! - Check transaction validity. -//! - Initialize a block. -//! - Apply extrinsics. -//! - Execute a block. -//! - Finalize a block. -//! - Start an off-chain worker. -//! -//! ### Implementations -//! -//! The Executive module provides the following implementations: -//! -//! - `ExecuteBlock`: Trait that can be used to execute a block. -//! - `Executive`: Type that can be used to make the SRML available from the runtime. -//! -//! ## Usage -//! -//! The default Substrate node template declares the [`Executive`](./struct.Executive.html) type in its library. -//! -//! ### Example -//! -//! `Executive` type declaration from the node template. -//! -//! ``` -//! # use sr_primitives::generic; -//! # use srml_executive as executive; -//! # pub struct UncheckedExtrinsic {}; -//! # pub struct Header {}; -//! # type Context = system::ChainContext; -//! # pub type Block = generic::Block; -//! # pub type Balances = u64; -//! # pub type AllModules = u64; -//! # pub enum Runtime {}; -//! # use sr_primitives::transaction_validity::{TransactionValidity, UnknownTransaction}; -//! # use sr_primitives::traits::ValidateUnsigned; -//! # impl ValidateUnsigned for Runtime { -//! # type Call = (); -//! # -//! # fn validate_unsigned(_call: &Self::Call) -> TransactionValidity { -//! # UnknownTransaction::NoUnsignedValidator.into() -//! # } -//! # } -//! /// Executive: handles dispatch to the various modules. -//! pub type Executive = executive::Executive; -//! ``` - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::{prelude::*, marker::PhantomData}; -use sr_primitives::{ - generic::Digest, ApplyResult, weights::GetDispatchInfo, - traits::{ - self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, - NumberFor, Block as BlockT, OffchainWorker, ValidateUnsigned, Dispatchable - }, - transaction_validity::TransactionValidity, -}; -use codec::{Codec, Encode}; -use system::{extrinsics_root, DigestOf}; - -/// Trait that can be used to execute a block. -pub trait ExecuteBlock { - /// Actually execute all transitions for `block`. - fn execute_block(block: Block); -} - -pub type CheckedOf = >::Checked; -pub type CallOf = as Applyable>::Call; -pub type OriginOf = as Dispatchable>::Origin; - -pub struct Executive( - PhantomData<(System, Block, Context, UnsignedValidator, AllModules)> -); - -impl< - System: system::Trait, - Block: traits::Block, - Context: Default, - UnsignedValidator, - AllModules: OnInitialize + OnFinalize + OffchainWorker, -> ExecuteBlock for Executive -where - Block::Extrinsic: Checkable + Codec, - CheckedOf: Applyable + GetDispatchInfo, - CallOf: Dispatchable, - OriginOf: From>, - UnsignedValidator: ValidateUnsigned>, -{ - fn execute_block(block: Block) { - Executive::::execute_block(block); - } -} - -impl< - System: system::Trait, - Block: traits::Block, - Context: Default, - UnsignedValidator, - AllModules: OnInitialize + OnFinalize + OffchainWorker, -> Executive -where - Block::Extrinsic: Checkable + Codec, - CheckedOf: Applyable + GetDispatchInfo, - CallOf: Dispatchable, - OriginOf: From>, - UnsignedValidator: ValidateUnsigned>, -{ - /// Start the execution of a particular block. - pub fn initialize_block(header: &System::Header) { - let mut digests = >::default(); - header.digest().logs().iter().for_each(|d| if d.as_pre_runtime().is_some() { digests.push(d.clone()) }); - Self::initialize_block_impl(header.number(), header.parent_hash(), header.extrinsics_root(), &digests); - } - - fn initialize_block_impl( - block_number: &System::BlockNumber, - parent_hash: &System::Hash, - extrinsics_root: &System::Hash, - digest: &Digest, - ) { - >::initialize(block_number, parent_hash, extrinsics_root, digest); - >::on_initialize(*block_number); - } - - fn initial_checks(block: &Block) { - let header = block.header(); - - // Check that `parent_hash` is correct. - let n = header.number().clone(); - assert!( - n > System::BlockNumber::zero() - && >::block_hash(n - System::BlockNumber::one()) == *header.parent_hash(), - "Parent hash should be valid." - ); - - // Check that transaction trie root represents the transactions. - let xts_root = extrinsics_root::(&block.extrinsics()); - header.extrinsics_root().check_equal(&xts_root); - assert!(header.extrinsics_root() == &xts_root, "Transaction trie root must be valid."); - } - - /// Actually execute all transitions for `block`. - pub fn execute_block(block: Block) { - Self::initialize_block(block.header()); - - // any initial checks - Self::initial_checks(&block); - - // execute extrinsics - let (header, extrinsics) = block.deconstruct(); - Self::execute_extrinsics_with_book_keeping(extrinsics, *header.number()); - - // any final checks - Self::final_checks(&header); - } - - /// 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_finalize(block_number); - } - - /// Finalize the block - it is up the caller to ensure that all header fields are valid - /// except state-root. - pub fn finalize_block() -> System::Header { - >::note_finished_extrinsics(); - >::on_finalize(>::block_number()); - - // set up extrinsics - >::derive_extrinsics(); - >::finalize() - } - - /// Apply extrinsic outside of the block execution function. - /// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt - /// hashes. - pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyResult { - let encoded = uxt.encode(); - let encoded_len = encoded.len(); - Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded)) - } - - /// Apply an extrinsic inside the block execution function. - fn apply_extrinsic_no_note(uxt: Block::Extrinsic) { - let l = uxt.encode().len(); - match Self::apply_extrinsic_with_len(uxt, l, None) { - Ok(Ok(())) => (), - Ok(Err(e)) => sr_primitives::print(e), - Err(e) => { let err: &'static str = e.into(); panic!(err) }, - } - } - - /// Actually apply an extrinsic given its `encoded_len`; this doesn't note its hash. - fn apply_extrinsic_with_len( - uxt: Block::Extrinsic, - encoded_len: usize, - to_note: Option>, - ) -> ApplyResult { - // Verify that the signature is good. - let xt = uxt.check(&Default::default())?; - - // We don't need to make sure to `note_extrinsic` only after we know it's going to be - // executed to prevent it from leaking in storage since at this point, it will either - // execute or panic (and revert storage changes). - if let Some(encoded) = to_note { - >::note_extrinsic(encoded); - } - - // AUDIT: Under no circumstances may this function panic from here onwards. - - // Decode parameters and dispatch - let dispatch_info = xt.get_dispatch_info(); - let r = Applyable::apply(xt, dispatch_info, encoded_len)?; - - >::note_applied_extrinsic(&r, encoded_len as u32); - - Ok(r) - } - - fn final_checks(header: &System::Header) { - // remove temporaries - let new_header = >::finalize(); - - // check digest - assert_eq!( - header.digest().logs().len(), - new_header.digest().logs().len(), - "Number of digest items must match that calculated." - ); - let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter()); - for (header_item, computed_item) in items_zip { - header_item.check_equal(&computed_item); - assert!(header_item == computed_item, "Digest item must match that calculated."); - } - - // check storage root. - let storage_root = new_header.state_root(); - header.state_root().check_equal(&storage_root); - assert!(header.state_root() == storage_root, "Storage root must match that calculated."); - } - - /// Check a given signed transaction for validity. This doesn't execute any - /// side-effects; it merely checks whether the transaction would panic if it were included or not. - /// - /// Changes made to storage should be discarded. - pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity { - let encoded_len = uxt.using_encoded(|d| d.len()); - let xt = uxt.check(&Default::default())?; - - let dispatch_info = xt.get_dispatch_info(); - xt.validate::(dispatch_info, encoded_len) - } - - /// Start an offchain worker and generate extrinsics. - pub fn offchain_worker(n: System::BlockNumber) { - >::generate_extrinsics(n) - } -} - - -#[cfg(test)] -mod tests { - use super::*; - use primitives::H256; - use sr_primitives::{ - generic::Era, Perbill, DispatchError, weights::Weight, testing::{Digest, Header, Block}, - traits::{Bounded, Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}, - transaction_validity::{InvalidTransaction, UnknownTransaction}, ApplyError, - }; - use support::{ - impl_outer_event, impl_outer_origin, parameter_types, impl_outer_dispatch, - traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}, - }; - use system::Call as SystemCall; - use balances::Call as BalancesCall; - use hex_literal::hex; - - type System = system::Module; - type Balances = balances::Module; - - impl_outer_origin! { - pub enum Origin for Runtime { } - } - - impl_outer_event!{ - pub enum MetaEvent for Runtime { - balances, - } - } - impl_outer_dispatch! { - pub enum Call for Runtime where origin: Origin { - system::System, - balances::Balances, - } - } - - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, Eq, PartialEq)] - pub struct Runtime; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Runtime { - type Origin = Origin; - type Index = u64; - type Call = Call; - type BlockNumber = u64; - type Hash = primitives::H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = MetaEvent; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - } - impl balances::Trait for Runtime { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = MetaEvent; - type DustRemoval = (); - type TransferPayment = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - - parameter_types! { - pub const TransactionBaseFee: u64 = 10; - pub const TransactionByteFee: u64 = 0; - } - impl transaction_payment::Trait for Runtime { - type Currency = Balances; - type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; - type FeeMultiplierUpdate = (); - } - - impl ValidateUnsigned for Runtime { - type Call = Call; - - fn validate_unsigned(call: &Self::Call) -> TransactionValidity { - match call { - Call::Balances(BalancesCall::set_balance(_, _, _)) => Ok(Default::default()), - _ => UnknownTransaction::NoUnsignedValidator.into(), - } - } - } - - type SignedExtra = ( - system::CheckEra, - system::CheckNonce, - system::CheckWeight, - transaction_payment::ChargeTransactionPayment - ); - type TestXt = sr_primitives::testing::TestXt; - type Executive = super::Executive, system::ChainContext, Runtime, ()>; - - fn extra(nonce: u64, fee: u64) -> SignedExtra { - ( - system::CheckEra::from(Era::Immortal), - system::CheckNonce::from(nonce), - system::CheckWeight::new(), - transaction_payment::ChargeTransactionPayment::from(fee) - ) - } - - fn sign_extra(who: u64, nonce: u64, fee: u64) -> Option<(u64, SignedExtra)> { - Some((who, extra(nonce, fee))) - } - - #[test] - fn balance_transfer_dispatch_works() { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig:: { - balances: vec![(1, 211)], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(2, 69))); - let weight = xt.get_dispatch_info().weight as u64; - let mut t = runtime_io::TestExternalities::new(t); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - let r = Executive::apply_extrinsic(xt); - assert!(r.is_ok()); - assert_eq!(>::total_balance(&1), 142 - 10 - weight); - assert_eq!(>::total_balance(&2), 69); - }); - } - - fn new_test_ext(balance_factor: u64) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig:: { - balances: vec![(1, 111 * balance_factor)], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - t.into() - } - - #[test] - fn block_import_works() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: hex!("f0d1d66255c2e5b40580eb8b93ddbe732491478487f85e358e1d167d369e398e").into(), - extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), - digest: Digest { logs: vec![], }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_state_root_fails() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: [0u8; 32].into(), - extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), - digest: Digest { logs: vec![], }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_extrinsic_root_fails() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: hex!("49cd58a254ccf6abc4a023d9a22dcfc421e385527a250faec69f8ad0d8ed3e48").into(), - extrinsics_root: [0u8; 32].into(), - digest: Digest { logs: vec![], }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - fn bad_extrinsic_not_inserted() { - let mut t = new_test_ext(1); - // bad nonce check! - let xt = sr_primitives::testing::TestXt(sign_extra(1, 30, 0), Call::Balances(BalancesCall::transfer(33, 69))); - t.execute_with(|| { - Executive::initialize_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_weight_limit_enforced() { - let mut t = new_test_ext(10000); - // given: TestXt uses the encoded len as fixed Len: - let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0))); - let encoded = xt.encode(); - let encoded_len = encoded.len() as Weight; - let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get(); - let num_to_exhaust_block = limit / encoded_len; - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - assert_eq!(>::all_extrinsics_weight(), 0); - - for nonce in 0..=num_to_exhaust_block { - let xt = sr_primitives::testing::TestXt( - sign_extra(1, nonce.into(), 0), Call::Balances(BalancesCall::transfer(33, 0)), - ); - let res = Executive::apply_extrinsic(xt); - if nonce != num_to_exhaust_block { - assert!(res.is_ok()); - assert_eq!( - >::all_extrinsics_weight(), - encoded_len * (nonce + 1), - ); - assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); - } else { - assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); - } - } - }); - } - - #[test] - fn block_weight_and_size_is_stored_per_tx() { - let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0))); - let x1 = sr_primitives::testing::TestXt(sign_extra(1, 1, 0), Call::Balances(BalancesCall::transfer(33, 0))); - let x2 = sr_primitives::testing::TestXt(sign_extra(1, 2, 0), Call::Balances(BalancesCall::transfer(33, 0))); - let len = xt.clone().encode().len() as u32; - let mut t = new_test_ext(1); - t.execute_with(|| { - assert_eq!(>::all_extrinsics_weight(), 0); - assert_eq!(>::all_extrinsics_weight(), 0); - - assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); - assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); - assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); - - // default weight for `TestXt` == encoded length. - assert_eq!(>::all_extrinsics_weight(), (3 * len).into()); - assert_eq!(>::all_extrinsics_len(), 3 * len); - - let _ = >::finalize(); - - assert_eq!(>::all_extrinsics_weight(), 0); - assert_eq!(>::all_extrinsics_weight(), 0); - }); - } - - #[test] - fn validate_unsigned() { - let xt = sr_primitives::testing::TestXt(None, Call::Balances(BalancesCall::set_balance(33, 69, 69))); - let mut t = new_test_ext(1); - - t.execute_with(|| { - assert_eq!(Executive::validate_transaction(xt.clone()), Ok(Default::default())); - assert_eq!( - Executive::apply_extrinsic(xt), - Ok( - Err( - DispatchError { module: Some(1), error: 0, message: Some("RequireRootOrigin") } - ) - ) - ); - }); - } - - #[test] - fn can_pay_for_tx_fee_on_full_lock() { - let id: LockIdentifier = *b"0 "; - let execute_with_lock = |lock: WithdrawReasons| { - let mut t = new_test_ext(1); - t.execute_with(|| { - as LockableCurrency>::set_lock( - id, - &1, - 110, - Bounded::max_value(), - lock, - ); - let xt = sr_primitives::testing::TestXt( - sign_extra(1, 0, 0), - Call::System(SystemCall::remark(vec![1u8])), - ); - let weight = xt.get_dispatch_info().weight as u64; - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - if lock == WithdrawReasons::except(WithdrawReason::TransactionPayment) { - assert!(Executive::apply_extrinsic(xt).unwrap().is_ok()); - // tx fee has been deducted. - assert_eq!(>::total_balance(&1), 111 - 10 - weight); - } else { - assert_eq!( - Executive::apply_extrinsic(xt), - Err(ApplyError::Validity(InvalidTransaction::Payment.into())), - ); - assert_eq!(>::total_balance(&1), 111); - } - }); - }; - - execute_with_lock(WithdrawReasons::all()); - execute_with_lock(WithdrawReasons::except(WithdrawReason::TransactionPayment)); - } -} diff --git a/srml/finality-tracker/Cargo.toml b/srml/finality-tracker/Cargo.toml deleted file mode 100644 index 7e3439e0fecea..0000000000000 --- a/srml/finality-tracker/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "srml-finality-tracker" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", default-features = false, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -srml-system = { path = "../system", default-features = false } -impl-trait-for-tuples = "0.1.2" - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } - -[features] -default = ["std"] -std = [ - "serde/std", - "codec/std", - "rstd/std", - "support/std", - "sr-primitives/std", - "srml-system/std", - "inherents/std", -] diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs deleted file mode 100644 index 5e973cd43235d..0000000000000 --- a/srml/finality-tracker/src/lib.rs +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! SRML module that tracks the last finalized block, as perceived by block authors. - -#![cfg_attr(not(feature = "std"), no_std)] - -use inherents::{ - RuntimeString, InherentIdentifier, ProvideInherent, - InherentData, MakeFatalError, -}; -use sr_primitives::traits::{One, Zero, SaturatedConversion}; -use rstd::{prelude::*, result, cmp, vec}; -use codec::Decode; -use support::{decl_module, decl_storage}; -use support::traits::Get; -use srml_system::{ensure_none, Trait as SystemTrait}; - -#[cfg(feature = "std")] -use codec::Encode; - -/// 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 const DEFAULT_WINDOW_SIZE: u32 = 101; -pub const DEFAULT_REPORT_LATENCY: u32 = 1000; - -pub trait Trait: SystemTrait { - /// Something which can be notified when the timestamp is set. Set this to `()` - /// if not needed. - type OnFinalizationStalled: OnFinalizationStalled; - /// The number of recent samples to keep from this chain. Default is 101. - type WindowSize: Get; - /// The delay after which point things become suspicious. Default is 1000. - type ReportLatency: Get; -} - -decl_storage! { - trait Store for Module as Timestamp { - /// Recent hints. - RecentHints get(fn recent_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; - /// Ordered recent hints. - OrderedHints get(fn ordered_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; - /// The median. - Median get(fn median) build(|_| T::BlockNumber::zero()): T::BlockNumber; - - /// Final hint to apply in the block. `None` means "same as parent". - Update: Option; - - // when initialized through config this is set in the beginning. - Initialized get(fn initialized) build(|_| false): bool; - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// The number of recent samples to keep from this chain. Default is 101. - const WindowSize: T::BlockNumber = T::WindowSize::get(); - - /// The delay after which point things become suspicious. Default is 1000. - const ReportLatency: T::BlockNumber = T::ReportLatency::get(); - - /// 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_none(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_finalize() { - 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(), T::WindowSize::get()); - - 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.saturated_into::()); - - 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() as u32; - - ::RecentHints::put(recent); - ::OrderedHints::put(ordered); - ::Median::put(median); - - if T::BlockNumber::from(our_window_size) == window_size { - let now = srml_system::Module::::block_number(); - let latency = T::ReportLatency::get(); - - // 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(), median); - } - } - } -} - -/// Called when finalization stalled at a given number. -#[impl_trait_for_tuples::impl_for_tuples(30)] -pub trait OnFinalizationStalled { - /// The parameter here is how many more blocks to wait before applying - /// changes triggered by finality stalling. - fn on_stalled(further_wait: N, median: N); -} - -impl ProvideInherent for Module { - type Call = Call; - type Error = MakeFatalError<()>; - const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; - - fn create_inherent(data: &InherentData) -> Option { - if let Ok(final_num) = data.finalized_number() { - // 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)) - }) - } else { - None - } - } - - fn check_inherent(_call: &Self::Call, _data: &InherentData) -> result::Result<(), Self::Error> { - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use runtime_io::TestExternalities; - use primitives::H256; - use sr_primitives::{ - testing::Header, Perbill, - traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}, - }; - use support::{assert_ok, impl_outer_origin, parameter_types}; - use srml_system as system; - use std::cell::RefCell; - - #[derive(Clone, PartialEq, Debug)] - pub struct StallEvent { - at: u64, - further_wait: u64, - } - - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - thread_local! { - static NOTIFICATIONS: RefCell> = Default::default(); - } - - pub struct StallTracker; - impl OnFinalizationStalled for StallTracker { - fn on_stalled(further_wait: u64, _median: u64) { - let now = System::block_number(); - NOTIFICATIONS.with(|v| v.borrow_mut().push(StallEvent { at: now, further_wait })); - } - } - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - parameter_types! { - pub const WindowSize: u64 = 11; - pub const ReportLatency: u64 = 100; - } - impl Trait for Test { - type OnFinalizationStalled = StallTracker; - type WindowSize = WindowSize; - type ReportLatency = ReportLatency; - } - - type System = system::Module; - type FinalityTracker = Module; - - #[test] - fn median_works() { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { - FinalityTracker::update_hint(Some(500)); - assert_eq!(FinalityTracker::median(), 250); - assert!(NOTIFICATIONS.with(|n| n.borrow().is_empty())); - }); - } - - #[test] - fn notifies_when_stalled() { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { - let mut parent_hash = System::parent_hash(); - for i in 2..106 { - System::initialize(&i, &parent_hash, &Default::default(), &Default::default()); - FinalityTracker::on_finalize(i); - let hdr = System::finalize(); - parent_hash = hdr.hash(); - } - - assert_eq!( - NOTIFICATIONS.with(|n| n.borrow().clone()), - vec![StallEvent { at: 105, further_wait: 10 }] - ) - }); - } - - #[test] - fn recent_notifications_prevent_stalling() { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { - let mut parent_hash = System::parent_hash(); - for i in 2..106 { - System::initialize(&i, &parent_hash, &Default::default(), &Default::default()); - assert_ok!(FinalityTracker::dispatch( - Call::final_hint(i-1), - Origin::NONE, - )); - FinalityTracker::on_finalize(i); - let hdr = System::finalize(); - parent_hash = hdr.hash(); - } - - assert!(NOTIFICATIONS.with(|n| n.borrow().is_empty())); - }); - } -} diff --git a/srml/generic-asset/Cargo.toml b/srml/generic-asset/Cargo.toml deleted file mode 100644 index 49a9db4c0ecd8..0000000000000 --- a/srml/generic-asset/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "srml-generic-asset" -version = "2.0.0" -authors = ["Centrality Developers "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -runtime-io ={ package = "sr-io", path = "../../core/sr-io" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } - -[features] -default = ["std"] -std =[ - "serde/std", - "codec/std", - "rstd/std", - "sr-primitives/std", - "support/std", - "system/std", -] diff --git a/srml/generic-asset/src/lib.rs b/srml/generic-asset/src/lib.rs deleted file mode 100644 index fdbb57f56fc99..0000000000000 --- a/srml/generic-asset/src/lib.rs +++ /dev/null @@ -1,1285 +0,0 @@ -// Copyright 2019 -// by Centrality Investments Ltd. -// and Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU 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 Asset Module -//! -//! The Generic Asset module provides functionality for handling accounts and asset balances. -//! -//! ## Overview -//! -//! The Generic Asset module provides functions for: -//! -//! - Creating a new kind of asset. -//! - Setting permissions of an asset. -//! - Getting and setting free balances. -//! - Retrieving total, reserved and unreserved balances. -//! - Repatriating a reserved balance to a beneficiary account. -//! - Transferring a balance between accounts (when not reserved). -//! - Slashing an account balance. -//! - Managing total issuance. -//! - Setting and managing locks. -//! -//! ### Terminology -//! -//! - **Staking Asset:** The asset for staking, to participate as Validators in the network. -//! - **Spending Asset:** The asset for payment, such as paying transfer fees, gas fees, etc. -//! - **Permissions:** A set of rules for a kind of asset, defining the allowed operations to the asset, and which -//! accounts are allowed to possess it. -//! - **Total Issuance:** The total number of units in existence in a system. -//! - **Free Balance:** The portion of a balance that is not reserved. The free balance is the only balance that matters -//! for most operations. When this balance falls below the existential deposit, most functionality of the account is -//! removed. When both it and the reserved balance are deleted, then the account is said to be dead. -//! - **Reserved Balance:** Reserved balance still belongs to the account holder, but is suspended. Reserved balance -//! can still be slashed, but only after all the free balance has been slashed. If the reserved balance falls below the -//! existential deposit then it and any related functionality will be deleted. When both it and the free balance are -//! deleted, then the account is said to be dead. -//! - **Imbalance:** A condition when some assets were credited or debited without equal and opposite accounting -//! (i.e. a difference between total issuance and account balances). Functions that result in an imbalance will -//! return an object of the `Imbalance` trait that can be managed within your runtime logic. (If an imbalance is -//! simply dropped, it should automatically maintain any book-keeping such as total issuance.) -//! - **Lock:** A freeze on a specified amount of an account's free balance until a specified block number. Multiple -//! locks always operate over the same funds, so they "overlay" rather than "stack". -//! -//! ### Implementations -//! -//! The Generic Asset module provides `AssetCurrency`, which implements the following traits. If these traits provide -//! the functionality that you need, you can avoid coupling with the Generic Asset module. -//! -//! - `Currency`: Functions for dealing with a fungible assets system. -//! - `ReservableCurrency`: Functions for dealing with assets that can be reserved from an account. -//! - `LockableCurrency`: Functions for dealing with accounts that allow liquidity restrictions. -//! - `Imbalance`: Functions for handling imbalances between total issuance in the system and account balances. -//! Must be used when a function creates new assets (e.g. a reward) or destroys some assets (e.g. a system fee). -//! -//! The Generic Asset module provides two types of `AssetCurrency` as follows. -//! -//! - `StakingAssetCurrency`: Currency for staking. -//! - `SpendingAssetCurrency`: Currency for payments such as transfer fee, gas fee. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! - `create`: Create a new kind of asset. -//! - `transfer`: Transfer some liquid free balance to another account. -//! - `update_permission`: Updates permission for a given `asset_id` and an account. The origin of this call -//! must have update permissions. -//! - `mint`: Mint an asset, increases its total issuance. The origin of this call must have mint permissions. -//! - `burn`: Burn an asset, decreases its total issuance. The origin of this call must have burn permissions. -//! - `create_reserved`: Create a new kind of reserved asset. The origin of this call must be root. -//! -//! ### Public Functions -//! -//! - `total_balance`: Get an account's total balance of an asset kind. -//! - `free_balance`: Get an account's free balance of an asset kind. -//! - `reserved_balance`: Get an account's reserved balance of an asset kind. -//! - `create_asset`: Creates an asset. -//! - `make_transfer`: Transfer some liquid free balance from one account to another. -//! This will not emit the `Transferred` event. -//! - `make_transfer_with_event`: Transfer some liquid free balance from one account to another. -//! This will emit the `Transferred` event. -//! - `reserve`: Moves an amount from free balance to reserved balance. -//! - `unreserve`: Move up to an amount from reserved balance to free balance. This function cannot fail. -//! - `slash`: Deduct up to an amount from the combined balance of `who`, preferring to deduct from the -//! free balance. This function cannot fail. -//! - `reward`: Add up to an amount to the free balance of an account. -//! - `slash_reserved`: Deduct up to an amount from reserved balance of an account. This function cannot fail. -//! - `repatriate_reserved`: Move up to an amount from reserved balance of an account to free balance of another -//! account. -//! - `check_permission`: Check permission to perform burn, mint or update. -//! - `ensure_can_withdraw`: Check if the account is able to make a withdrawal of the given amount -//! for the given reason. -//! -//! ### Usage -//! -//! The following examples show how to use the Generic Asset module in your custom module. -//! -//! ### Examples from the PRML -//! -//! The Fees module uses the `Currency` trait to handle fee charge/refund, and its types inherit from `Currency`: -//! -//! ``` -//! use support::{ -//! traits::{Currency, ExistenceRequirement, WithdrawReason}, -//! dispatch::Result, -//! }; -//! # pub trait Trait: system::Trait { -//! # type Currency: Currency; -//! # } -//! type AssetOf = <::Currency as Currency<::AccountId>>::Balance; -//! -//! fn charge_fee(transactor: &T::AccountId, amount: AssetOf) -> Result { -//! // ... -//! T::Currency::withdraw( -//! transactor, -//! amount, -//! WithdrawReason::TransactionPayment, -//! ExistenceRequirement::KeepAlive, -//! )?; -//! // ... -//! Ok(()) -//! } -//! -//! fn refund_fee(transactor: &T::AccountId, amount: AssetOf) -> Result { -//! // ... -//! T::Currency::deposit_into_existing(transactor, amount)?; -//! // ... -//! Ok(()) -//! } -//! -//! # fn main() {} -//! ``` -//! -//! ## Genesis config -//! -//! The Generic Asset module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). - -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::{Decode, Encode, HasCompact, Input, Output, Error}; - -use sr_primitives::RuntimeDebug; -use sr_primitives::traits::{ - CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, SimpleArithmetic, Zero, Bounded -}; - -use rstd::prelude::*; -use rstd::{cmp, result, fmt::Debug}; -use support::dispatch::Result; -use support::{ - decl_event, decl_module, decl_storage, ensure, - traits::{ - Currency, ExistenceRequirement, Imbalance, LockIdentifier, LockableCurrency, ReservableCurrency, - SignedImbalance, UpdateBalanceOutcome, WithdrawReason, WithdrawReasons, - }, - Parameter, StorageMap, -}; -use system::{ensure_signed, ensure_root}; - -mod mock; -mod tests; - -pub use self::imbalances::{NegativeImbalance, PositiveImbalance}; - -pub trait Trait: system::Trait { - type Balance: Parameter - + Member - + SimpleArithmetic - + Default - + Copy - + MaybeSerializeDeserialize - + Debug; - type AssetId: Parameter + Member + SimpleArithmetic + Default + Copy; - type Event: From> + Into<::Event>; -} - -pub trait Subtrait: system::Trait { - type Balance: Parameter - + Member - + SimpleArithmetic - + Default - + Copy - + MaybeSerializeDeserialize - + Debug; - type AssetId: Parameter + Member + SimpleArithmetic + Default + Copy; -} - -impl Subtrait for T { - type Balance = T::Balance; - type AssetId = T::AssetId; -} - -/// Asset creation options. -#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] -pub struct AssetOptions { - /// Initial issuance of this asset. All deposit to the creater of the asset. - #[codec(compact)] - pub initial_issuance: Balance, - /// Which accounts are allowed to possess this asset. - pub permissions: PermissionLatest, -} - -/// Owner of an asset. -#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] -pub enum Owner { - /// No owner. - None, - /// Owned by an AccountId - Address(AccountId), -} - -impl Default for Owner { - fn default() -> Self { - Owner::None - } -} - -/// Asset permissions -#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] -pub struct PermissionsV1 { - /// Who have permission to update asset permission - pub update: Owner, - /// Who have permission to mint new asset - pub mint: Owner, - /// Who have permission to burn asset - pub burn: Owner, -} - -#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] -#[repr(u8)] -enum PermissionVersionNumber { - V1 = 0, -} - -/// Versioned asset permission -#[derive(Clone, PartialEq, Eq, RuntimeDebug)] -pub enum PermissionVersions { - V1(PermissionsV1), -} - -/// Asset permission types -pub enum PermissionType { - /// Permission to burn asset permission - Burn, - /// Permission to mint new asset - Mint, - /// Permission to update asset - Update, -} - -/// Alias to latest asset permissions -pub type PermissionLatest = PermissionsV1; - -impl Default for PermissionVersions { - fn default() -> Self { - PermissionVersions::V1(Default::default()) - } -} - -impl Encode for PermissionVersions { - fn encode_to(&self, dest: &mut T) { - match self { - PermissionVersions::V1(payload) => { - dest.push(&PermissionVersionNumber::V1); - dest.push(payload); - }, - } - } -} - -impl codec::EncodeLike for PermissionVersions {} - -impl Decode for PermissionVersions { - fn decode(input: &mut I) -> core::result::Result { - let version = PermissionVersionNumber::decode(input)?; - Ok( - match version { - PermissionVersionNumber::V1 => PermissionVersions::V1(Decode::decode(input)?) - } - ) - } -} - -impl Default for PermissionsV1 { - fn default() -> Self { - PermissionsV1 { - update: Owner::None, - mint: Owner::None, - burn: Owner::None, - } - } -} - -impl Into> for PermissionVersions { - fn into(self) -> PermissionLatest { - match self { - PermissionVersions::V1(v1) => v1, - } - } -} - -/// Converts the latest permission to other version. -impl Into> for PermissionLatest { - fn into(self) -> PermissionVersions { - PermissionVersions::V1(self) - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - /// Create a new kind of asset. - fn create(origin, options: AssetOptions) -> Result { - let origin = ensure_signed(origin)?; - let id = Self::next_asset_id(); - - let permissions: PermissionVersions = options.permissions.clone().into(); - - // The last available id serves as the overflow mark and won't be used. - let next_id = id.checked_add(&One::one()).ok_or_else(|| "No new assets id available.")?; - - >::put(next_id); - >::insert(id, &options.initial_issuance); - >::insert(&id, &origin, &options.initial_issuance); - >::insert(&id, permissions); - - Self::deposit_event(RawEvent::Created(id, origin, options)); - - Ok(()) - } - - /// Transfer some liquid free balance to another account. - pub fn transfer(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, #[compact] amount: T::Balance) { - let origin = ensure_signed(origin)?; - ensure!(!amount.is_zero(), "cannot transfer zero amount"); - Self::make_transfer_with_event(&asset_id, &origin, &to, amount)?; - } - - /// Updates permission for a given `asset_id` and an account. - /// - /// The `origin` must have `update` permission. - fn update_permission( - origin, - #[compact] asset_id: T::AssetId, - new_permission: PermissionLatest - ) -> Result { - let origin = ensure_signed(origin)?; - - let permissions: PermissionVersions = new_permission.into(); - - if Self::check_permission(&asset_id, &origin, &PermissionType::Update) { - >::insert(asset_id, &permissions); - - Self::deposit_event(RawEvent::PermissionUpdated(asset_id, permissions.into())); - - Ok(()) - } else { - Err("Origin does not have enough permission to update permissions.") - } - } - - /// Mints an asset, increases its total issuance. - /// The origin must have `mint` permissions. - fn mint(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, amount: T::Balance) -> Result { - let origin = ensure_signed(origin)?; - if Self::check_permission(&asset_id, &origin, &PermissionType::Mint) { - let original_free_balance = Self::free_balance(&asset_id, &to); - let current_total_issuance = >::get(asset_id); - let new_total_issuance = current_total_issuance.checked_add(&amount) - .ok_or_else(|| "total_issuance got overflow after minting.")?; - let value = original_free_balance.checked_add(&amount) - .ok_or_else(|| "free balance got overflow after minting.")?; - - >::insert(asset_id, new_total_issuance); - Self::set_free_balance(&asset_id, &to, value); - - Self::deposit_event(RawEvent::Minted(asset_id, to, amount)); - - Ok(()) - } else { - Err("The origin does not have permission to mint an asset.") - } - } - - /// Burns an asset, decreases its total issuance. - /// - /// The `origin` must have `burn` permissions. - fn burn(origin, #[compact] asset_id: T::AssetId, to: T::AccountId, amount: T::Balance) -> Result { - let origin = ensure_signed(origin)?; - - if Self::check_permission(&asset_id, &origin, &PermissionType::Burn) { - let original_free_balance = Self::free_balance(&asset_id, &to); - - let current_total_issuance = >::get(asset_id); - let new_total_issuance = current_total_issuance.checked_sub(&amount) - .ok_or_else(|| "total_issuance got underflow after burning")?; - let value = original_free_balance.checked_sub(&amount) - .ok_or_else(|| "free_balance got underflow after burning")?; - - >::insert(asset_id, new_total_issuance); - - Self::set_free_balance(&asset_id, &to, value); - - Self::deposit_event(RawEvent::Burned(asset_id, to, amount)); - - Ok(()) - } else { - Err("The origin does not have permission to burn an asset.") - } - } - - /// Can be used to create reserved tokens. - /// Requires Root call. - fn create_reserved(origin, asset_id: T::AssetId, options: AssetOptions) -> Result { - ensure_root(origin)?; - Self::create_asset(Some(asset_id), None, options) - } - } -} - -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct BalanceLock { - pub id: LockIdentifier, - pub amount: Balance, - pub until: BlockNumber, - pub reasons: WithdrawReasons, -} - -decl_storage! { - trait Store for Module as GenericAsset { - /// Total issuance of a given asset. - pub TotalIssuance get(fn total_issuance) build(|config: &GenesisConfig| { - let issuance = config.initial_balance * (config.endowed_accounts.len() as u32).into(); - config.assets.iter().map(|id| (id.clone(), issuance)).collect::>() - }): map T::AssetId => T::Balance; - - /// The free balance of a given asset under an account. - pub FreeBalance: double_map T::AssetId, twox_128(T::AccountId) => T::Balance; - - /// The reserved balance of a given asset under an account. - pub ReservedBalance: double_map T::AssetId, twox_128(T::AccountId) => T::Balance; - - /// Next available ID for user-created asset. - pub NextAssetId get(fn next_asset_id) config(): T::AssetId; - - /// Permission options for a given asset. - pub Permissions get(fn get_permission): map T::AssetId => PermissionVersions; - - /// Any liquidity locks on some account balances. - pub Locks get(fn locks): map T::AccountId => Vec>; - - /// The identity of the asset which is the one that is designated for the chain's staking system. - pub StakingAssetId get(fn staking_asset_id) config(): T::AssetId; - - /// The identity of the asset which is the one that is designated for paying the chain's transaction fee. - pub SpendingAssetId get(fn spending_asset_id) config(): T::AssetId; - } - add_extra_genesis { - config(assets): Vec; - config(initial_balance): T::Balance; - config(endowed_accounts): Vec; - - build(|config: &GenesisConfig| { - config.assets.iter().for_each(|asset_id| { - config.endowed_accounts.iter().for_each(|account_id| { - >::insert(asset_id, account_id, &config.initial_balance); - }); - }); - }); - } -} - -decl_event!( - pub enum Event where - ::AccountId, - ::Balance, - ::AssetId, - AssetOptions = AssetOptions<::Balance, ::AccountId> - { - /// Asset created (asset_id, creator, asset_options). - Created(AssetId, AccountId, AssetOptions), - /// Asset transfer succeeded (asset_id, from, to, amount). - Transferred(AssetId, AccountId, AccountId, Balance), - /// Asset permission updated (asset_id, new_permissions). - PermissionUpdated(AssetId, PermissionLatest), - /// New asset minted (asset_id, account, amount). - Minted(AssetId, AccountId, Balance), - /// Asset burned (asset_id, account, amount). - Burned(AssetId, AccountId, Balance), - } -); - -impl Module { - // PUBLIC IMMUTABLES - - /// Get an account's total balance of an asset kind. - pub fn total_balance(asset_id: &T::AssetId, who: &T::AccountId) -> T::Balance { - Self::free_balance(asset_id, who) + Self::reserved_balance(asset_id, who) - } - - /// Get an account's free balance of an asset kind. - pub fn free_balance(asset_id: &T::AssetId, who: &T::AccountId) -> T::Balance { - >::get(asset_id, who) - } - - /// Get an account's reserved balance of an asset kind. - pub fn reserved_balance(asset_id: &T::AssetId, who: &T::AccountId) -> T::Balance { - >::get(asset_id, who) - } - - /// Creates an asset. - /// - /// # Arguments - /// * `asset_id`: An ID of a reserved asset. - /// If not provided, a user-generated asset will be created with the next available ID. - /// * `from_account`: The initiator account of this call - /// * `asset_options`: Asset creation options. - /// - pub fn create_asset( - asset_id: Option, - from_account: Option, - options: AssetOptions, - ) -> Result { - let asset_id = if let Some(asset_id) = asset_id { - ensure!(!>::exists(&asset_id), "Asset id already taken."); - ensure!(asset_id < Self::next_asset_id(), "Asset id not available."); - asset_id - } else { - let asset_id = Self::next_asset_id(); - let next_id = asset_id - .checked_add(&One::one()) - .ok_or_else(|| "No new user asset id available.")?; - >::put(next_id); - asset_id - }; - - let account_id = from_account.unwrap_or_default(); - let permissions: PermissionVersions = options.permissions.clone().into(); - - >::insert(asset_id, &options.initial_issuance); - >::insert(&asset_id, &account_id, &options.initial_issuance); - >::insert(&asset_id, permissions); - - Self::deposit_event(RawEvent::Created(asset_id, account_id, options)); - - Ok(()) - } - - /// Transfer some liquid free balance from one account to another. - /// This will not emit the `Transferred` event. - pub fn make_transfer(asset_id: &T::AssetId, from: &T::AccountId, to: &T::AccountId, amount: T::Balance) -> Result { - let new_balance = Self::free_balance(asset_id, from) - .checked_sub(&amount) - .ok_or_else(|| "balance too low to send amount")?; - Self::ensure_can_withdraw(asset_id, from, amount, WithdrawReason::Transfer, new_balance)?; - - if from != to { - >::mutate(asset_id, from, |balance| *balance -= amount); - >::mutate(asset_id, to, |balance| *balance += amount); - } - - Ok(()) - } - - /// Transfer some liquid free balance from one account to another. - /// This will emit the `Transferred` event. - pub fn make_transfer_with_event( - asset_id: &T::AssetId, - from: &T::AccountId, - to: &T::AccountId, - amount: T::Balance, - ) -> Result { - Self::make_transfer(asset_id, from, to, amount)?; - - if from != to { - Self::deposit_event(RawEvent::Transferred(*asset_id, from.clone(), to.clone(), amount)); - } - - Ok(()) - } - - /// Move `amount` from free balance to reserved balance. - /// - /// If the free balance is lower than `amount`, then no funds will be moved and an `Err` will - /// be returned. This is different behavior than `unreserve`. - pub fn reserve(asset_id: &T::AssetId, who: &T::AccountId, amount: T::Balance) -> Result { - // Do we need to consider that this is an atomic transaction? - let original_reserve_balance = Self::reserved_balance(asset_id, who); - let original_free_balance = Self::free_balance(asset_id, who); - if original_free_balance < amount { - return Err("not enough free funds"); - } - let new_reserve_balance = original_reserve_balance + amount; - Self::set_reserved_balance(asset_id, who, new_reserve_balance); - let new_free_balance = original_free_balance - amount; - Self::set_free_balance(asset_id, who, new_free_balance); - Ok(()) - } - - /// Moves up to `amount` from reserved balance to free balance. This function cannot fail. - /// - /// As many assets up to `amount` will be moved as possible. If the reserve balance of `who` - /// is less than `amount`, then the remaining amount will be returned. - /// NOTE: This is different behavior than `reserve`. - pub fn unreserve(asset_id: &T::AssetId, who: &T::AccountId, amount: T::Balance) -> T::Balance { - let b = Self::reserved_balance(asset_id, who); - let actual = rstd::cmp::min(b, amount); - let original_free_balance = Self::free_balance(asset_id, who); - let new_free_balance = original_free_balance + actual; - Self::set_free_balance(asset_id, who, new_free_balance); - Self::set_reserved_balance(asset_id, who, b - actual); - amount - actual - } - - /// Deduct up to `amount` from the combined balance of `who`, preferring to deduct from the - /// free balance. This function cannot fail. - /// - /// As much funds up to `amount` will be deducted as possible. If this is less than `amount` - /// then `Some(remaining)` will be returned. Full completion is given by `None`. - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - fn slash(asset_id: &T::AssetId, who: &T::AccountId, amount: T::Balance) -> Option { - let free_balance = Self::free_balance(asset_id, who); - let free_slash = rstd::cmp::min(free_balance, amount); - let new_free_balance = free_balance - free_slash; - Self::set_free_balance(asset_id, who, new_free_balance); - if free_slash < amount { - Self::slash_reserved(asset_id, who, amount - free_slash) - } else { - None - } - } - - /// Deducts up to `amount` from reserved balance of `who`. This function cannot fail. - /// - /// As much funds up to `amount` will be deducted as possible. If the reserve balance of `who` - /// is less than `amount`, then a non-zero second item will be returned. - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - fn slash_reserved(asset_id: &T::AssetId, who: &T::AccountId, amount: T::Balance) -> Option { - let original_reserve_balance = Self::reserved_balance(asset_id, who); - let slash = rstd::cmp::min(original_reserve_balance, amount); - let new_reserve_balance = original_reserve_balance - slash; - Self::set_reserved_balance(asset_id, who, new_reserve_balance); - if amount == slash { - None - } else { - Some(amount - slash) - } - } - - /// Move up to `amount` from reserved balance of account `who` to free balance of account - /// `beneficiary`. - /// - /// As much funds up to `amount` will be moved as possible. If this is less than `amount`, then - /// the `remaining` would be returned, else `Zero::zero()`. - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - fn repatriate_reserved( - asset_id: &T::AssetId, - who: &T::AccountId, - beneficiary: &T::AccountId, - amount: T::Balance, - ) -> T::Balance { - let b = Self::reserved_balance(asset_id, who); - let slash = rstd::cmp::min(b, amount); - - let original_free_balance = Self::free_balance(asset_id, beneficiary); - let new_free_balance = original_free_balance + slash; - Self::set_free_balance(asset_id, beneficiary, new_free_balance); - - let new_reserve_balance = b - slash; - Self::set_reserved_balance(asset_id, who, new_reserve_balance); - amount - slash - } - - /// Check permission to perform burn, mint or update. - /// - /// # Arguments - /// * `asset_id`: A `T::AssetId` type that contains the `asset_id`, which has the permission embedded. - /// * `who`: A `T::AccountId` type that contains the `account_id` for which to check permissions. - /// * `what`: The permission to check. - /// - pub fn check_permission(asset_id: &T::AssetId, who: &T::AccountId, what: &PermissionType) -> bool { - let permission_versions: PermissionVersions = Self::get_permission(asset_id); - let permission = permission_versions.into(); - - match (what, permission) { - ( - PermissionType::Burn, - PermissionLatest { - burn: Owner::Address(account), - .. - }, - ) => account == *who, - ( - PermissionType::Mint, - PermissionLatest { - mint: Owner::Address(account), - .. - }, - ) => account == *who, - ( - PermissionType::Update, - PermissionLatest { - update: Owner::Address(account), - .. - }, - ) => account == *who, - _ => false, - } - } - - /// Return `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_can_withdraw( - asset_id: &T::AssetId, - who: &T::AccountId, - _amount: T::Balance, - reason: WithdrawReason, - new_balance: T::Balance, - ) -> Result { - if asset_id != &Self::staking_asset_id() { - return Ok(()); - } - - 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") - } - } - - // PRIVATE MUTABLES - - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - fn set_reserved_balance(asset_id: &T::AssetId, who: &T::AccountId, balance: T::Balance) { - >::insert(asset_id, who, &balance); - } - - /// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that - /// the caller will do this. - fn set_free_balance(asset_id: &T::AssetId, who: &T::AccountId, balance: T::Balance) { - >::insert(asset_id, who, &balance); - } - - 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 = >::locks(who) - .into_iter() - .filter_map(|l| { - if l.id == id { - new_lock.take() - } else if l.until > now { - Some(l) - } else { - None - } - }) - .collect::>(); - if let Some(lock) = new_lock { - locks.push(lock) - } - >::insert(who, locks); - } - - 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 = >::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); - } - - fn remove_lock(id: LockIdentifier, who: &T::AccountId) { - let now = >::block_number(); - let locks = >::locks(who) - .into_iter() - .filter_map(|l| if l.until > now && l.id != id { Some(l) } else { None }) - .collect::>(); - >::insert(who, locks); - } -} - -pub trait AssetIdProvider { - type AssetId; - fn asset_id() -> Self::AssetId; -} - -// wrapping these imbalanes in a private module is necessary to ensure absolute privacy -// of the inner member. -mod imbalances { - use super::{result, AssetIdProvider, Imbalance, Saturating, StorageMap, Subtrait, Zero}; - use rstd::mem; - - /// Opaque, move-only struct with private fields that serves as a token denoting that - /// funds have been created without any equal and opposite accounting. - #[must_use] - pub struct PositiveImbalance>( - T::Balance, - rstd::marker::PhantomData, - ); - impl PositiveImbalance - where - T: Subtrait, - U: AssetIdProvider, - { - pub fn new(amount: T::Balance) -> Self { - PositiveImbalance(amount, Default::default()) - } - } - - /// Opaque, move-only struct with private fields that serves as a token denoting that - /// funds have been destroyed without any equal and opposite accounting. - #[must_use] - pub struct NegativeImbalance>( - T::Balance, - rstd::marker::PhantomData, - ); - impl NegativeImbalance - where - T: Subtrait, - U: AssetIdProvider, - { - pub fn new(amount: T::Balance) -> Self { - NegativeImbalance(amount, Default::default()) - } - } - - impl Imbalance for PositiveImbalance - where - T: Subtrait, - U: AssetIdProvider, - { - type Opposite = NegativeImbalance; - - fn zero() -> Self { - Self::new(Zero::zero()) - } - fn drop_zero(self) -> result::Result<(), Self> { - if self.0.is_zero() { - Ok(()) - } else { - Err(self) - } - } - fn split(self, amount: T::Balance) -> (Self, Self) { - let first = self.0.min(amount); - let second = self.0 - first; - - mem::forget(self); - (Self::new(first), Self::new(second)) - } - fn merge(mut self, other: Self) -> Self { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - - self - } - fn subsume(&mut self, other: Self) { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - } - fn offset(self, other: Self::Opposite) -> result::Result { - let (a, b) = (self.0, other.0); - mem::forget((self, other)); - - if a >= b { - Ok(Self::new(a - b)) - } else { - Err(NegativeImbalance::new(b - a)) - } - } - fn peek(&self) -> T::Balance { - self.0.clone() - } - } - - impl Imbalance for NegativeImbalance - where - T: Subtrait, - U: AssetIdProvider, - { - type Opposite = PositiveImbalance; - - fn zero() -> Self { - Self::new(Zero::zero()) - } - fn drop_zero(self) -> result::Result<(), Self> { - if self.0.is_zero() { - Ok(()) - } else { - Err(self) - } - } - fn split(self, amount: T::Balance) -> (Self, Self) { - let first = self.0.min(amount); - let second = self.0 - first; - - mem::forget(self); - (Self::new(first), Self::new(second)) - } - fn merge(mut self, other: Self) -> Self { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - - self - } - fn subsume(&mut self, other: Self) { - self.0 = self.0.saturating_add(other.0); - mem::forget(other); - } - fn offset(self, other: Self::Opposite) -> result::Result { - let (a, b) = (self.0, other.0); - mem::forget((self, other)); - - if a >= b { - Ok(Self::new(a - b)) - } else { - Err(PositiveImbalance::new(b - a)) - } - } - fn peek(&self) -> T::Balance { - self.0.clone() - } - } - - impl Drop for PositiveImbalance - where - T: Subtrait, - U: AssetIdProvider, - { - /// Basic drop handler will just square up the total issuance. - fn drop(&mut self) { - >>::mutate(&U::asset_id(), |v| *v = v.saturating_add(self.0)); - } - } - - impl Drop for NegativeImbalance - where - T: Subtrait, - U: AssetIdProvider, - { - /// Basic drop handler will just square up the total issuance. - fn drop(&mut self) { - >>::mutate(&U::asset_id(), |v| *v = v.saturating_sub(self.0)); - } - } -} - -// TODO: #2052 -// Somewhat ugly hack in order to gain access to module's `increase_total_issuance_by` -// using only the Subtrait (which defines only the types that are not dependent -// on Positive/NegativeImbalance). Subtrait must be used otherwise we end up with a -// circular dependency with Trait having some types be dependent on PositiveImbalance -// and PositiveImbalance itself depending back on Trait for its Drop impl (and thus -// its type declaration). -// This works as long as `increase_total_issuance_by` doesn't use the Imbalance -// types (basically for charging fees). -// This should eventually be refactored so that the three type items that do -// depend on the Imbalance type (TransactionPayment, TransferPayment, DustRemoval) -// are placed in their own SRML module. -struct ElevatedTrait(T); -impl Clone for ElevatedTrait { - fn clone(&self) -> Self { - unimplemented!() - } -} -impl PartialEq for ElevatedTrait { - fn eq(&self, _: &Self) -> bool { - unimplemented!() - } -} -impl Eq for ElevatedTrait {} -impl system::Trait for ElevatedTrait { - type Origin = T::Origin; - type Call = T::Call; - type Index = T::Index; - type BlockNumber = T::BlockNumber; - type Hash = T::Hash; - type Hashing = T::Hashing; - type AccountId = T::AccountId; - type Lookup = T::Lookup; - type Header = T::Header; - type Event = (); - type MaximumBlockWeight = T::MaximumBlockWeight; - type MaximumBlockLength = T::MaximumBlockLength; - type AvailableBlockRatio = T::AvailableBlockRatio; - type BlockHashCount = T::BlockHashCount; - type Version = T::Version; -} -impl Trait for ElevatedTrait { - type Balance = T::Balance; - type AssetId = T::AssetId; - type Event = (); -} - -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct AssetCurrency(rstd::marker::PhantomData, rstd::marker::PhantomData); - -impl Currency for AssetCurrency -where - T: Trait, - U: AssetIdProvider, -{ - type Balance = T::Balance; - type PositiveImbalance = PositiveImbalance; - type NegativeImbalance = NegativeImbalance; - - fn total_balance(who: &T::AccountId) -> Self::Balance { - Self::free_balance(&who) + Self::reserved_balance(&who) - } - - fn free_balance(who: &T::AccountId) -> Self::Balance { - >::free_balance(&U::asset_id(), &who) - } - - /// Returns the total staking asset issuance - fn total_issuance() -> Self::Balance { - >::total_issuance(U::asset_id()) - } - - fn minimum_balance() -> Self::Balance { - Zero::zero() - } - - fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::Balance) -> Result { - >::make_transfer(&U::asset_id(), transactor, dest, value) - } - - fn ensure_can_withdraw( - who: &T::AccountId, - amount: Self::Balance, - reason: WithdrawReason, - new_balance: Self::Balance, - ) -> Result { - >::ensure_can_withdraw(&U::asset_id(), who, amount, reason, new_balance) - } - - fn withdraw( - who: &T::AccountId, - value: Self::Balance, - reason: WithdrawReason, - _: ExistenceRequirement, // no existential deposit policy for generic asset - ) -> result::Result { - let new_balance = Self::free_balance(who) - .checked_sub(&value) - .ok_or_else(|| "account has too few funds")?; - Self::ensure_can_withdraw(who, value, reason, new_balance)?; - >::set_free_balance(&U::asset_id(), who, new_balance); - Ok(NegativeImbalance::new(value)) - } - - fn deposit_into_existing( - who: &T::AccountId, - value: Self::Balance, - ) -> result::Result { - // No existential deposit rule and creation fee in GA. `deposit_into_existing` is same with `deposit_creating`. - Ok(Self::deposit_creating(who, value)) - } - - fn deposit_creating(who: &T::AccountId, value: Self::Balance) -> Self::PositiveImbalance { - let (imbalance, _) = Self::make_free_balance_be(who, Self::free_balance(who) + value); - if let SignedImbalance::Positive(p) = imbalance { - p - } else { - // Impossible, but be defensive. - Self::PositiveImbalance::zero() - } - } - - fn make_free_balance_be( - who: &T::AccountId, - balance: Self::Balance, - ) -> ( - SignedImbalance, - UpdateBalanceOutcome, - ) { - let original = >::free_balance(&U::asset_id(), who); - let imbalance = if original <= balance { - SignedImbalance::Positive(PositiveImbalance::new(balance - original)) - } else { - SignedImbalance::Negative(NegativeImbalance::new(original - balance)) - }; - >::set_free_balance(&U::asset_id(), who, balance); - (imbalance, UpdateBalanceOutcome::Updated) - } - - fn can_slash(who: &T::AccountId, value: Self::Balance) -> bool { - >::free_balance(&U::asset_id(), &who) >= value - } - - fn slash(who: &T::AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) { - let remaining = >::slash(&U::asset_id(), who, value); - if let Some(r) = remaining { - (NegativeImbalance::new(value - r), r) - } else { - (NegativeImbalance::new(value), Zero::zero()) - } - } - - fn burn(mut amount: Self::Balance) -> Self::PositiveImbalance { - >::mutate(&U::asset_id(), |issued| - issued.checked_sub(&amount).unwrap_or_else(|| { - amount = *issued; - Zero::zero() - }) - ); - PositiveImbalance::new(amount) - } - - fn issue(mut amount: Self::Balance) -> Self::NegativeImbalance { - >::mutate(&U::asset_id(), |issued| - *issued = issued.checked_add(&amount).unwrap_or_else(|| { - amount = Self::Balance::max_value() - *issued; - Self::Balance::max_value() - }) - ); - NegativeImbalance::new(amount) - } -} - -impl ReservableCurrency for AssetCurrency -where - T: Trait, - U: AssetIdProvider, -{ - fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { - Self::free_balance(who) - .checked_sub(&value) - .map_or(false, |new_balance| - >::ensure_can_withdraw( - &U::asset_id(), who, value, WithdrawReason::Reserve, new_balance - ).is_ok() - ) - } - - fn reserved_balance(who: &T::AccountId) -> Self::Balance { - >::reserved_balance(&U::asset_id(), &who) - } - - fn reserve(who: &T::AccountId, value: Self::Balance) -> result::Result<(), &'static str> { - >::reserve(&U::asset_id(), who, value) - } - - fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance { - >::unreserve(&U::asset_id(), who, value) - } - - fn slash_reserved(who: &T::AccountId, value: Self::Balance) -> (Self::NegativeImbalance, Self::Balance) { - let b = Self::reserved_balance(&who.clone()); - let slash = cmp::min(b, value); - - >::set_reserved_balance(&U::asset_id(), who, b - slash); - (NegativeImbalance::new(slash), value - slash) - } - - fn repatriate_reserved( - slashed: &T::AccountId, - beneficiary: &T::AccountId, - value: Self::Balance, - ) -> result::Result { - Ok(>::repatriate_reserved(&U::asset_id(), slashed, beneficiary, value)) - } -} - -pub struct StakingAssetIdProvider(rstd::marker::PhantomData); - -impl AssetIdProvider for StakingAssetIdProvider { - type AssetId = T::AssetId; - fn asset_id() -> Self::AssetId { - >::staking_asset_id() - } -} - -pub struct SpendingAssetIdProvider(rstd::marker::PhantomData); - -impl AssetIdProvider for SpendingAssetIdProvider { - type AssetId = T::AssetId; - fn asset_id() -> Self::AssetId { - >::spending_asset_id() - } -} - -impl LockableCurrency for AssetCurrency> -where - T: Trait, - T::Balance: MaybeSerializeDeserialize + Debug, -{ - type Moment = T::BlockNumber; - - fn set_lock( - id: LockIdentifier, - who: &T::AccountId, - amount: T::Balance, - until: T::BlockNumber, - reasons: WithdrawReasons, - ) { - >::set_lock(id, who, amount, until, reasons) - } - - fn extend_lock( - id: LockIdentifier, - who: &T::AccountId, - amount: T::Balance, - until: T::BlockNumber, - reasons: WithdrawReasons, - ) { - >::extend_lock(id, who, amount, until, reasons) - } - - fn remove_lock(id: LockIdentifier, who: &T::AccountId) { - >::remove_lock(id, who) - } -} - -pub type StakingAssetCurrency = AssetCurrency>; -pub type SpendingAssetCurrency = AssetCurrency>; diff --git a/srml/generic-asset/src/mock.rs b/srml/generic-asset/src/mock.rs deleted file mode 100644 index 57b13760fa03d..0000000000000 --- a/srml/generic-asset/src/mock.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2019 -// by Centrality Investments Ltd. -// and Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Mocks for the module. - -#![cfg(test)] - -use sr_primitives::{ - Perbill, - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, -}; -use primitives::H256; -use support::{parameter_types, impl_outer_event, impl_outer_origin}; - -use super::*; - -impl_outer_origin! { - pub enum Origin for Test {} -} - -// For testing the module, we construct most of a mock runtime. This means -// first constructing a configuration type (`Test`) which `impl`s each of the -// configuration traits of modules we want to use. -#[derive(Clone, Eq, PartialEq)] -pub struct Test; -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = TestEvent; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type BlockHashCount = BlockHashCount; - type Version = (); -} - -impl Trait for Test { - type Balance = u64; - type AssetId = u32; - type Event = TestEvent; -} - -mod generic_asset { - pub use crate::Event; -} - -impl_outer_event! { - pub enum TestEvent for Test { - generic_asset, - } -} - -pub type GenericAsset = Module; - -pub type System = system::Module; - -pub struct ExtBuilder { - asset_id: u32, - next_asset_id: u32, - accounts: Vec, - initial_balance: u64, -} - -// Returns default values for genesis config -impl Default for ExtBuilder { - fn default() -> Self { - Self { - asset_id: 0, - next_asset_id: 1000, - accounts: vec![0], - initial_balance: 0, - } - } -} - -impl ExtBuilder { - // Sets free balance to genesis config - pub fn free_balance(mut self, free_balance: (u32, u64, u64)) -> Self { - self.asset_id = free_balance.0; - self.accounts = vec![free_balance.1]; - self.initial_balance = free_balance.2; - self - } - - pub fn next_asset_id(mut self, asset_id: u32) -> Self { - self.next_asset_id = asset_id; - self - } - - // builds genesis config - pub fn build(self) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - - GenesisConfig:: { - assets: vec![self.asset_id], - endowed_accounts: self.accounts, - initial_balance: self.initial_balance, - next_asset_id: self.next_asset_id, - staking_asset_id: 16000, - spending_asset_id: 16001, - } - .assimilate_storage(&mut t).unwrap(); - - t.into() - } -} - -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. -pub fn new_test_ext() -> runtime_io::TestExternalities { - system::GenesisConfig::default() - .build_storage::() - .unwrap() - .into() -} diff --git a/srml/generic-asset/src/tests.rs b/srml/generic-asset/src/tests.rs deleted file mode 100644 index 165936d0215a6..0000000000000 --- a/srml/generic-asset/src/tests.rs +++ /dev/null @@ -1,1217 +0,0 @@ -// Copyright 2019 -// by Centrality Investments Ltd. -// and Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU 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::{new_test_ext, ExtBuilder, GenericAsset, Origin, System, Test, TestEvent}; -use support::{assert_noop, assert_ok}; - -#[test] -fn issuing_asset_units_to_issuer_should_work() { - let balance = 100; - - ExtBuilder::default().free_balance((16000, 1, 100)).build().execute_with(|| { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - - let expected_balance = balance; - - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: balance, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&16000, &1), expected_balance); - }); -} - -#[test] -fn issuing_with_next_asset_id_overflow_should_not_work() { - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - NextAssetId::::put(u32::max_value()); - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_noop!( - GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 1, - permissions: default_permission - } - ), - "No new assets id available." - ); - assert_eq!(GenericAsset::next_asset_id(), u32::max_value()); - }); -} - -#[test] -fn querying_total_supply_should_work() { - let asset_id = 1000; - - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); - assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 2, 50)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); - assert_eq!(GenericAsset::free_balance(&asset_id, &2), 50); - assert_ok!(GenericAsset::transfer(Origin::signed(2), asset_id, 3, 31)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); - assert_eq!(GenericAsset::free_balance(&asset_id, &2), 19); - assert_eq!(GenericAsset::free_balance(&asset_id, &3), 31); - assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 1, 1)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); - }); -} - -// Given -// - The next asset id as `asset_id` = 1000. -// - AssetOptions with all permissions. -// - GenesisStore has sufficient free balance. -// -// When -// - Create an asset from `origin` as 1. -// Then -// - free_balance of next asset id = 100. -// -// When -// - After transferring 40 from account 1 to account 2. -// Then -// - Origin account's `free_balance` = 60. -// - account 2's `free_balance` = 40. -#[test] -fn transferring_amount_should_work() { - let asset_id = 1000; - let free_balance = 100; - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: free_balance, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), free_balance); - assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 2, 40)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 60); - assert_eq!(GenericAsset::free_balance(&asset_id, &2), 40); - }); -} - -// Given -// - The next asset id as `asset_id` = 1000. -// - AssetOptions with all permissions. -// - GenesisStore has sufficient free balance. -// -// When -// - Create an asset from `origin` as 1. -// Then -// - free_balance of next asset id = 100. -// -// When -// - After transferring 40 from account 1 to account 2. -// Then -// - Origin account's `free_balance` = 60. -// - account 2's `free_balance` = 40. -#[test] -fn transferring_amount_should_fail_when_transferring_more_than_free_balance() { - let asset_id = 1000; - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_noop!( - GenericAsset::transfer(Origin::signed(1), asset_id, 2, 2000), - "balance too low to send amount" - ); - }); -} - -#[test] -fn transferring_less_than_one_unit_should_not_work() { - let asset_id = 1000; - - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); - assert_noop!( - GenericAsset::transfer(Origin::signed(1), asset_id, 2, 0), - "cannot transfer zero amount" - ); - }); -} - -// Given -// - Next asset id as `asset_id` = 1000. -// - Sufficient free balance. -// - initial balance = 100. -// When -// - After performing a self transfer from account 1 to 1. -// Then -// - Should not throw any errors. -// - Free balance after self transfer should equal to the free balance before self transfer. -#[test] -fn self_transfer_should_fail() { - let asset_id = 1000; - let balance = 100; - - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: balance, - permissions: default_permission - } - )); - - let initial_free_balance = GenericAsset::free_balance(&asset_id, &1); - assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 1, 10)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), initial_free_balance); - }); -} - -#[test] -fn transferring_more_units_than_total_supply_should_not_work() { - let asset_id = 1000; - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); - assert_noop!( - GenericAsset::transfer(Origin::signed(1), asset_id, 2, 101), - "balance too low to send amount" - ); - }); -} - -// Ensures it uses fake money for staking asset id. -#[test] -fn staking_asset_id_should_return_0() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(GenericAsset::staking_asset_id(), 16000); - }); -} - -// Ensures it uses fake money for spending asset id. -#[test] -fn spending_asset_id_should_return_10() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(GenericAsset::spending_asset_id(), 16001); - }); -} - -// Given -// -Â Free balance is 0 and the reserved balance is 0. -// Then -// -Â total_balance should return 0 -#[test] -fn total_balance_should_be_zero() { - new_test_ext().execute_with(|| { - assert_eq!(GenericAsset::total_balance(&0, &0), 0); - }); -} - -// Given -// -Â Free balance is 0 and the reserved balance > 0. -// When -// - After calling total_balance. -// Then -// -Â total_balance should equals to reserved balance. -#[test] -fn total_balance_should_be_equal_to_account_balance() { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::total_balance(&1000, &1), 100); - }); -} - -// Given -// - An account presents with AccountId = 1 -// -Â free_balance > 0. -// - reserved_balance = 50. -// When -// - After calling free_balance. -// Then -// -Â free_balance should return 50. -#[test] -fn free_balance_should_only_return_account_free_balance() { - ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 70); - assert_eq!(GenericAsset::free_balance(&1, &0), 50); - }); -} - -// Given -// - An account presents with AccountId = 1. -// -Â Free balance > 0 and the reserved balance > 0. -// When -// - After calling total_balance. -// Then -// -Â total_balance should equals to account balance + free balance. -#[test] -fn total_balance_should_be_equal_to_sum_of_account_balance_and_free_balance() { - ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 70); - assert_eq!(GenericAsset::total_balance(&1, &0), 120); - }); -} - -// Given -// -Â free_balance > 0. -// - reserved_balance = 70. -// When -// - After calling reserved_balance. -// Then -// - reserved_balance should return 70. -#[test] -fn reserved_balance_should_only_return_account_reserved_balance() { - ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 70); - assert_eq!(GenericAsset::reserved_balance(&1, &0), 70); - }); -} - -// Given -// - A valid account presents. -// - Initial reserved_balance = 0 -// When -// - After calls set_reserved_balance -// Then -// - Should persists the amount as reserved_balance. -// - reserved_balance = amount -#[test] -fn set_reserved_balance_should_add_balance_as_reserved() { - ExtBuilder::default().build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 50); - assert_eq!(GenericAsset::reserved_balance(&1, &0), 50); - }); -} - -// Given -// - A valid account presents. -// - Initial free_balance = 100. -// When -// - After calling set_free_balance. -// Then -// - Should persists the amount as free_balance. -// - New free_balance should replace older free_balance. -#[test] -fn set_free_balance_should_add_amount_as_free_balance() { - ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { - GenericAsset::set_free_balance(&1, &0, 50); - assert_eq!(GenericAsset::free_balance(&1, &0), 50); - }); -} - -// Given -// - free_balance is greater than the account balance. -// - free_balance = 100 -// - reserved_balance = 0 -// - reserve amount = 70 -// When -// - After calling reserve -// Then -// - Funds should be removed from the account. -// - new free_balance = original free_balance - reserved amount -// - new reserved_balance = original free balance + reserved amount -#[test] -fn reserve_should_moves_amount_from_balance_to_reserved_balance() { - ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { - assert_ok!(GenericAsset::reserve(&1, &0, 70)); - assert_eq!(GenericAsset::free_balance(&1, &0), 30); - assert_eq!(GenericAsset::reserved_balance(&1, &0), 70); - }); -} - -// Given -// - Free balance is lower than the account balance. -// - free_balance = 100 -// - reserved_balance = 0 -// - reserve amount = 120 -// When -// - After calling reverse function. -// Then -// - Funds should not be removed from the account. -// - Should throw an error. -#[test] -fn reserve_should_not_moves_amount_from_balance_to_reserved_balance() { - ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { - assert_noop!(GenericAsset::reserve(&1, &0, 120), "not enough free funds"); - assert_eq!(GenericAsset::free_balance(&1, &0), 100); - assert_eq!(GenericAsset::reserved_balance(&1, &0), 0); - }); -} - -// Given -// - unreserved_amount > reserved_balance. -// - reserved_balance = 100. -// - free_balance = 100. -// - unreserved_amount = 120. -// When -// - After calling unreserve function. -// Then -// - unreserved should return 20. -#[test] -fn unreserve_should_return_substratced_value_from_unreserved_amount_by_actual_acount_balance() { - ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 100); - assert_eq!(GenericAsset::unreserve(&1, &0, 120), 20); - }); -} - -// Given -// - unreserved_amount < reserved_balance. -// - reserved_balance = 100. -// - free_balance = 100. -// - unreserved_amount = 50. -// When -// - After calling unreserve function. -// Then -// - unreserved should return None. -#[test] -fn unreserve_should_return_none() { - ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 100); - assert_eq!(GenericAsset::unreserve(&1, &0, 50), 0); - }); -} - -// Given -// - unreserved_amount > reserved_balance. -// - reserved_balance = 100. -// - free_balance = 100. -// - unreserved_amount = 120. -// When -// - After calling unreserve function. -// Then -// - free_balance should be 200. -#[test] -fn unreserve_should_increase_free_balance_by_reserved_balance() { - ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 100); - GenericAsset::unreserve(&1, &0, 120); - assert_eq!(GenericAsset::free_balance(&1, &0), 200); - }); -} - -// Given -// - unreserved_amount > reserved_balance. -// - reserved_balance = 100. -// - free_balance = 100. -// - unreserved_amount = 120. -// When -// - After calling unreserve function. -// Then -// - reserved_balance should be 0. -#[test] -fn unreserve_should_deduct_reserved_balance_by_reserved_amount() { - ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { - GenericAsset::set_free_balance(&1, &0, 100); - GenericAsset::unreserve(&1, &0, 120); - assert_eq!(GenericAsset::reserved_balance(&1, &0), 0); - }); -} - -// Given -// - slash amount < free_balance. -// - reserved_balance = 100. -// - free_balance = 100. -// - slash amount = 70. -// When -// - After calling slash function. -// Then -// - slash should return None. -#[test] -fn slash_should_return_slash_reserved_amount() { - ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 100); - assert_eq!(GenericAsset::slash(&1, &0, 70), None); - }); -} - -// Given -// - slashed_amount > reserved_balance. -// When -// - After calling slashed_reverse function. -// Then -// - Should return slashed_reserved - reserved_balance. -#[test] -fn slash_reserved_should_deducts_up_to_amount_from_reserved_balance() { - ExtBuilder::default().build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 100); - assert_eq!(GenericAsset::slash_reserved(&1, &0, 150), Some(50)); - }); -} - -// Given -// - slashed_amount equals to reserved_amount. -// When -// - After calling slashed_reverse function. -// Then -// - Should return None. -#[test] -fn slash_reserved_should_return_none() { - ExtBuilder::default().build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 100); - assert_eq!(GenericAsset::slash_reserved(&1, &0, 100), None); - }); -} - -// Given -// - reserved_balance = 100. -// - repatriate_reserved_amount > reserved_balance. -// When -// - After calling repatriate_reserved. -// Then -// - Should not return None. -#[test] -fn repatriate_reserved_return_amount_substracted_by_slash_amount() { - ExtBuilder::default().build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 100); - assert_eq!(GenericAsset::repatriate_reserved(&1, &0, &1, 130), 30); - }); -} - -// Given -// - reserved_balance = 100. -// - repatriate_reserved_amount > reserved_balance. -// When -// - After calling repatriate_reserved. -// Then -// - Should return None. -#[test] -fn repatriate_reserved_return_none() { - ExtBuilder::default().build().execute_with(|| { - GenericAsset::set_reserved_balance(&1, &0, 100); - assert_eq!(GenericAsset::repatriate_reserved(&1, &0, &1, 90), 0); - }); -} - -// Given -// - An asset with all permissions -// When -// - After calling `create_reserved` function. -// Then -// - Should create a new reserved asset. -#[test] -fn create_reserved_should_create_a_default_account_with_the_balance_given() { - ExtBuilder::default().next_asset_id(10).build().execute_with(|| { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - let options = AssetOptions { - initial_issuance: 500, - permissions: default_permission, - }; - - let expected_total_issuance = 500; - let created_asset_id = 9; - let created_account_id = 0; - - assert_ok!(GenericAsset::create_reserved(Origin::ROOT, created_asset_id, options)); - - // Tests for side effects. - assert_eq!(>::get(created_asset_id), expected_total_issuance); - assert_eq!( - >::get(&created_asset_id, &created_account_id), - expected_total_issuance - ); - }); -} - -// Given -// - Origin is signed -// - Origin does not have minting permission -// When -// - After calling mint function -// Then -// - Should throw a permission error -#[test] -fn mint_should_throw_permission_error() { - ExtBuilder::default().build().execute_with(|| { - let origin = 1; - let asset_id = 4; - let to_account = 2; - let amount = 100; - - assert_noop!( - GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount), - "The origin does not have permission to mint an asset." - ); - }); -} - -// Given -// - Origin is signed. -// - Origin has permissions. -// When -// - After calling mint function -// Then -// - Should increase `to` free_balance. -// - Should not change `origins` free_balance. -#[test] -fn mint_should_increase_asset() { - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let origin = 1; - let asset_id = 1000; - let to_account = 2; - let amount = 500; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); - - assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount)); - assert_eq!(GenericAsset::free_balance(&asset_id, &to_account), amount); - - // Origin's free_balance should not change. - assert_eq!(GenericAsset::free_balance(&asset_id, &origin), initial_issuance); - }); -} - -// Given -// - Origin is signed. -// - Origin does not have burning permission. -// When -// - After calling burn function. -// Then -// - Should throw a permission error. -#[test] -fn burn_should_throw_permission_error() { - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let origin = 1; - let asset_id = 4; - let to_account = 2; - let amount = 10; - - assert_noop!( - GenericAsset::burn(Origin::signed(origin), asset_id, to_account, amount), - "The origin does not have permission to burn an asset." - ); - }); -} - -// Given -// - Origin is signed. -// - Origin has permissions. -// When -// - After calling burn function -// Then -// - Should decrease `to`'s free_balance. -// - Should not change `origin`'s free_balance. -#[test] -fn burn_should_burn_an_asset() { - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let origin = 1; - let asset_id = 1000; - let to_account = 2; - let amount = 1000; - let initial_issuance = 100; - let burn_amount = 400; - let expected_amount = 600; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); - assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount)); - - assert_ok!(GenericAsset::burn( - Origin::signed(origin), - asset_id, - to_account, - burn_amount - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &to_account), expected_amount); - }); -} - -// Given -// - `default_permission` with all privileges. -// - All permissions for origin. -// When -// - After executing create function and check_permission function. -// Then -// - The account origin should have burn, mint and update permissions. -#[test] -fn check_permission_should_return_correct_permission() { - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let origin = 1; - let asset_id = 1000; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - }, - )); - - assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); - assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); - assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Update)); - }); -} - -// Given -// - `default_permission` with no privileges. -// - No permissions for origin. -// When -// - After executing create function and check_permission function. -// Then -// - The account origin should not have burn, mint and update permissions. -#[test] -fn check_permission_should_return_false_for_no_permission() { - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let origin = 1; - let asset_id = 1000; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::None, - mint: Owner::None, - burn: Owner::None, - }; - - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); - - assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); - assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); - assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Update)); - }); -} - -// Given -// - `default_permission` only with update. -// When -// - After executing update_permission function. -// Then -// - The account origin should not have the burn permission. -// - The account origin should have update and mint permissions. -#[test] -fn update_permission_should_change_permission() { - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let origin = 1; - let asset_id = 1000; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::None, - burn: Owner::None, - }; - - let new_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::None, - }; - - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); - - assert_ok!(GenericAsset::update_permission( - Origin::signed(origin), - asset_id, - new_permission, - )); - assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); - assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); - }); -} - -// Given -// - `default_permission` without any permissions. -// When -// - After executing update_permission function. -// Then -// - Should throw an error stating "Origin does not have enough permission to update permissions." -#[test] -fn update_permission_should_throw_error_when_lack_of_permissions() { - ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { - let origin = 1; - let asset_id = 1000; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::None, - mint: Owner::None, - burn: Owner::None, - }; - - let new_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::None, - }; - - let expected_error_message = "Origin does not have enough permission to update permissions."; - - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - }, - )); - - assert_noop!( - GenericAsset::update_permission(Origin::signed(origin), asset_id, new_permission), - expected_error_message, - ); - }); -} - -// Given -// - `asset_id` provided. -// - `from_account` is present. -// - All permissions for origin. -// When -// - After calling create_asset. -// Then -// - Should create a reserved token with provided id. -// - NextAssetId doesn't change. -// - TotalIssuance must equal to initial issuance. -// - FreeBalance must equal to initial issuance for the given account. -// - Permissions must have burn, mint and updatePermission for the given asset_id. -#[test] -fn create_asset_works_with_given_asset_id_and_from_account() { - ExtBuilder::default().next_asset_id(10).build().execute_with(|| { - let origin = 1; - let from_account: Option<::AccountId> = Some(1); - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - let expected_permission = PermissionVersions::V1(default_permission.clone()); - let asset_id = 9; - let initial_issuance = 100; - - assert_ok!(GenericAsset::create_asset( - Some(asset_id), - from_account, - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission.clone() - } - )); - - // Test for side effects. - assert_eq!(>::get(), 10); - assert_eq!(>::get(asset_id), initial_issuance); - assert_eq!(>::get(&asset_id, &origin), initial_issuance); - assert_eq!(>::get(&asset_id), expected_permission); - }); -} - -// Given -// - `asset_id` is an id for user generated assets. -// - Whatever other params. -// Then -// - `create_asset` should not work. -#[test] -fn create_asset_with_non_reserved_asset_id_should_not_work() { - ExtBuilder::default().next_asset_id(10).build().execute_with(|| { - let origin = 1; - let from_account: Option<::AccountId> = Some(1); - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - - let asset_id = 11; - let initial_issuance = 100; - - assert_noop!( - GenericAsset::create_asset( - Some(asset_id), - from_account, - AssetOptions { - initial_issuance, - permissions: default_permission.clone() - } - ), - "Asset id not available." - ); - }); -} - -// Given -// - `asset_id` is for reserved assets, but already taken. -// - Whatever other params. -// Then -// - `create_asset` should not work. -#[test] -fn create_asset_with_a_taken_asset_id_should_not_work() { - ExtBuilder::default().next_asset_id(10).build().execute_with(|| { - let origin = 1; - let from_account: Option<::AccountId> = Some(1); - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - - let asset_id = 9; - let initial_issuance = 100; - - assert_ok!(GenericAsset::create_asset( - Some(asset_id), - from_account, - AssetOptions { - initial_issuance, - permissions: default_permission.clone() - } - )); - assert_noop!( - GenericAsset::create_asset( - Some(asset_id), - from_account, - AssetOptions { - initial_issuance, - permissions: default_permission.clone() - } - ), - "Asset id already taken." - ); - }); -} - -// Given -// - `asset_id` provided. -// - `from_account` is None. -// - All permissions for origin. -// When -// - After calling create_asset. -// Then -// - Should create a reserved token. -#[test] -fn create_asset_should_create_a_reserved_asset_when_from_account_is_none() { - ExtBuilder::default().next_asset_id(10).build().execute_with(|| { - let origin = 1; - let from_account: Option<::AccountId> = None; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - - let created_account_id = 0; - let asset_id = 9; - let initial_issuance = 100; - - assert_ok!(GenericAsset::create_asset( - Some(asset_id), - from_account, - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); - - // Test for a side effect. - assert_eq!( - >::get(&asset_id, &created_account_id), - initial_issuance - ); - }); -} - -// Given -// - `asset_id` not provided. -// - `from_account` is None. -// - All permissions for origin. -// When -// - After calling create_asset. -// Then -// - Should create a user token. -// - `NextAssetId`'s get should return a new value. -// - Should not create a `reserved_asset`. -#[test] -fn create_asset_should_create_a_user_asset() { - ExtBuilder::default().next_asset_id(10).build().execute_with(|| { - let origin = 1; - let from_account: Option<::AccountId> = None; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - - let created_account_id = 0; - let reserved_asset_id = 100000; - let initial_issuance = 100; - let created_user_asset_id = 10; - - assert_ok!(GenericAsset::create_asset( - None, - from_account, - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); - - // Test for side effects. - assert_eq!(>::get(&reserved_asset_id, &created_account_id), 0); - assert_eq!( - >::get(&created_user_asset_id, &created_account_id), - initial_issuance - ); - assert_eq!(>::get(created_user_asset_id), initial_issuance); - }); -} - -#[test] -fn update_permission_should_raise_event() { - // Arrange - let staking_asset_id = 16000; - let asset_id = 1000; - let origin = 1; - let initial_balance = 1000; - let permissions = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - - ExtBuilder::default() - .next_asset_id(asset_id) - .free_balance((staking_asset_id, origin, initial_balance)) - .build() - .execute_with(|| { - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: 0, - permissions: permissions.clone(), - } - )); - - // Act - assert_ok!(GenericAsset::update_permission( - Origin::signed(origin), - asset_id, - permissions.clone() - )); - - let expected_event = TestEvent::generic_asset( - RawEvent::PermissionUpdated(asset_id, permissions.clone()), - ); - // Assert - assert!(System::events().iter().any(|record| record.event == expected_event)); - }, - ); -} - -#[test] -fn mint_should_raise_event() { - // Arrange - let staking_asset_id = 16000; - let asset_id = 1000; - let origin = 1; - let initial_balance = 1000; - let permissions = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - let to = 2; - let amount = 100; - - ExtBuilder::default() - .next_asset_id(asset_id) - .free_balance((staking_asset_id, origin, initial_balance)) - .build() - .execute_with(|| { - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: 0, - permissions: permissions.clone(), - }, - )); - - // Act - assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to, amount)); - - let expected_event = TestEvent::generic_asset(RawEvent::Minted(asset_id, to, amount)); - - // Assert - assert!(System::events().iter().any(|record| record.event == expected_event)); - }, - ); -} - -#[test] -fn burn_should_raise_event() { - // Arrange - let staking_asset_id = 16000; - let asset_id = 1000; - let origin = 1; - let initial_balance = 1000; - let permissions = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; - let amount = 100; - - ExtBuilder::default() - .next_asset_id(asset_id) - .free_balance((staking_asset_id, origin, initial_balance)) - .build() - .execute_with(|| { - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: amount, - permissions: permissions.clone(), - }, - )); - - // Act - assert_ok!(GenericAsset::burn(Origin::signed(origin), asset_id, origin, amount)); - - let expected_event = TestEvent::generic_asset(RawEvent::Burned(asset_id, origin, amount)); - - // Assert - assert!(System::events().iter().any(|record| record.event == expected_event)); - }, - ); -} diff --git a/srml/grandpa/Cargo.toml b/srml/grandpa/Cargo.toml deleted file mode 100644 index 4b494cfeff8d1..0000000000000 --- a/srml/grandpa/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "srml-grandpa" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -substrate-finality-grandpa-primitives = { path = "../../core/finality-grandpa/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -session = { package = "srml-session", path = "../session", default-features = false } -finality-tracker = { package = "srml-finality-tracker", path = "../finality-tracker", default-features = false } - -[dev-dependencies] -runtime-io ={ package = "sr-io", path = "../../core/sr-io" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "primitives/std", - "substrate-finality-grandpa-primitives/std", - "rstd/std", - "support/std", - "sr-primitives/std", - "sr-staking-primitives/std", - "system/std", - "session/std", - "finality-tracker/std", -] diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs deleted file mode 100644 index 0fc0df382a0bd..0000000000000 --- a/srml/grandpa/src/lib.rs +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! GRANDPA Consensus module for runtime. -//! -//! This manages the GRANDPA authority set ready for the native code. -//! These authorities are only for GRANDPA finality, not for consensus overall. -//! -//! In the future, it will also handle misbehavior reports, and on-chain -//! finality notifications. -//! -//! For full integration with GRANDPA, the `GrandpaApi` should be implemented. -//! The necessary items are re-exported via the `fg_primitives` crate. - -#![cfg_attr(not(feature = "std"), no_std)] - -// re-export since this is necessary for `impl_apis` in runtime. -pub use substrate_finality_grandpa_primitives as fg_primitives; - -use rstd::prelude::*; -use codec::{self as codec, Encode, Decode, Error}; -use support::{ - decl_event, decl_storage, decl_module, dispatch::Result, -}; -use sr_primitives::{ - generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, - Perbill, -}; -use sr_staking_primitives::{ - SessionIndex, - offence::{Offence, Kind}, -}; -use fg_primitives::{GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog, SetId, RoundNumber}; -pub use fg_primitives::{AuthorityId, AuthorityWeight}; -use system::{ensure_signed, DigestOf}; - -mod mock; -mod tests; - -pub trait Trait: system::Trait { - /// The event type of this module. - type Event: From + Into<::Event>; -} - -/// 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<(AuthorityId, AuthorityWeight)>, -} - -/// A stored pending change. -#[derive(Encode)] -pub struct StoredPendingChange { - /// 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<(AuthorityId, AuthorityWeight)>, - /// If defined it means the change was forced and the given block number - /// indicates the median last finalized block when the change was signaled. - pub forced: Option, -} - -impl Decode for StoredPendingChange { - fn decode(value: &mut I) -> core::result::Result { - let old = OldStoredPendingChange::decode(value)?; - let forced = >::decode(value).unwrap_or(None); - - Ok(StoredPendingChange { - scheduled_at: old.scheduled_at, - delay: old.delay, - next_authorities: old.next_authorities, - forced, - }) - } -} - -/// Current state of the GRANDPA authority set. State transitions must happen in -/// the same order of states defined below, e.g. `Paused` implies a prior -/// `PendingPause`. -#[derive(Decode, Encode)] -#[cfg_attr(test, derive(Debug, PartialEq))] -pub enum StoredState { - /// The current authority set is live, and GRANDPA is enabled. - Live, - /// There is a pending pause event which will be enacted at the given block - /// height. - PendingPause { - /// Block at which the intention to pause was scheduled. - scheduled_at: N, - /// Number of blocks after which the change will be enacted. - delay: N - }, - /// The current GRANDPA authority set is paused. - Paused, - /// There is a pending resume event which will be enacted at the given block - /// height. - PendingResume { - /// Block at which the intention to resume was scheduled. - scheduled_at: N, - /// Number of blocks after which the change will be enacted. - delay: N, - }, -} - -decl_event!( - pub enum Event { - /// New authority set has been applied. - NewAuthorities(Vec<(AuthorityId, AuthorityWeight)>), - /// Current authority set has been paused. - Paused, - /// Current authority set has been resumed. - Resumed, - } -); - -decl_storage! { - trait Store for Module as GrandpaFinality { - /// The current authority set. - Authorities get(fn authorities): Vec<(AuthorityId, AuthorityWeight)>; - - /// State of the current authority set. - State get(fn state): StoredState = StoredState::Live; - - /// Pending change: (signaled at, scheduled change). - PendingChange: Option>; - - /// next block number where we can force a change. - NextForced get(fn next_forced): Option; - - /// `true` if we are currently stalled. - Stalled get(fn stalled): Option<(T::BlockNumber, T::BlockNumber)>; - - /// The number of changes (both in terms of keys and underlying economic responsibilities) - /// in the "set" of Grandpa validators from genesis. - CurrentSetId get(fn current_set_id) build(|_| fg_primitives::SetId::default()): SetId; - - /// A mapping from grandpa set ID to the index of the *most recent* session for which its members were responsible. - SetIdSession get(fn session_for_set): map SetId => Option; - } - add_extra_genesis { - config(authorities): Vec<(AuthorityId, AuthorityWeight)>; - build(|config| Module::::initialize_authorities(&config.authorities)) - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - /// Report some misbehavior. - fn report_misbehavior(origin, _report: Vec) { - ensure_signed(origin)?; - // FIXME: https://github.com/paritytech/substrate/issues/1112 - } - - fn on_finalize(block_number: T::BlockNumber) { - // check for scheduled pending authority set changes - if let Some(pending_change) = >::get() { - // emit signal if we're at the block that scheduled the change - if block_number == pending_change.scheduled_at { - if let Some(median) = pending_change.forced { - Self::deposit_log(ConsensusLog::ForcedChange( - median, - ScheduledChange { - delay: pending_change.delay, - next_authorities: pending_change.next_authorities.clone(), - } - )) - } else { - Self::deposit_log(ConsensusLog::ScheduledChange( - ScheduledChange{ - delay: pending_change.delay, - next_authorities: pending_change.next_authorities.clone(), - } - )); - } - } - - // enact the change if we've reached the enacting block - if block_number == pending_change.scheduled_at + pending_change.delay { - Authorities::put(&pending_change.next_authorities); - Self::deposit_event( - Event::NewAuthorities(pending_change.next_authorities) - ); - >::kill(); - } - } - - // check for scheduled pending state changes - match >::get() { - StoredState::PendingPause { scheduled_at, delay } => { - // signal change to pause - if block_number == scheduled_at { - Self::deposit_log(ConsensusLog::Pause(delay)); - } - - // enact change to paused state - if block_number == scheduled_at + delay { - >::put(StoredState::Paused); - Self::deposit_event(Event::Paused); - } - }, - StoredState::PendingResume { scheduled_at, delay } => { - // signal change to resume - if block_number == scheduled_at { - Self::deposit_log(ConsensusLog::Resume(delay)); - } - - // enact change to live state - if block_number == scheduled_at + delay { - >::put(StoredState::Live); - Self::deposit_event(Event::Resumed); - } - }, - _ => {}, - } - } - } -} - -impl Module { - /// Get the current set of authorities, along with their respective weights. - pub fn grandpa_authorities() -> Vec<(AuthorityId, AuthorityWeight)> { - Authorities::get() - } - - /// Schedule GRANDPA to pause starting in the given number of blocks. - /// Cannot be done when already paused. - pub fn schedule_pause(in_blocks: T::BlockNumber) -> Result { - if let StoredState::Live = >::get() { - let scheduled_at = >::block_number(); - >::put(StoredState::PendingPause { - delay: in_blocks, - scheduled_at, - }); - - Ok(()) - } else { - Err("Attempt to signal GRANDPA pause when the authority set isn't live \ - (either paused or already pending pause).") - } - } - - /// Schedule a resume of GRANDPA after pausing. - pub fn schedule_resume(in_blocks: T::BlockNumber) -> Result { - if let StoredState::Paused = >::get() { - let scheduled_at = >::block_number(); - >::put(StoredState::PendingResume { - delay: in_blocks, - scheduled_at, - }); - - Ok(()) - } else { - Err("Attempt to signal GRANDPA resume when the authority set isn't paused \ - (either live or already pending resume).") - } - } - - /// Schedule a change in the authorities. - /// - /// The change will be applied at the end of execution of the block - /// `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 signaled while any change is pending. Returns - /// an error if a change is already pending. - pub fn schedule_change( - next_authorities: Vec<(AuthorityId, AuthorityWeight)>, - in_blocks: T::BlockNumber, - forced: Option, - ) -> Result { - if !>::exists() { - let scheduled_at = >::block_number(); - - 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 * 2.into()); - } - - >::put(StoredPendingChange { - delay: in_blocks, - scheduled_at, - next_authorities, - forced, - }); - - Ok(()) - } else { - Err("Attempt to signal GRANDPA change with one already pending.") - } - } - - /// Deposit one of this module's logs. - fn deposit_log(log: ConsensusLog) { - let log: DigestItem = DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()); - >::deposit_log(log.into()); - } - - fn initialize_authorities(authorities: &[(AuthorityId, AuthorityWeight)]) { - if !authorities.is_empty() { - assert!(Authorities::get().is_empty(), "Authorities are already initialized!"); - Authorities::put(authorities); - } - } -} - -impl Module { - /// Attempt to extract a GRANDPA log from a generic digest. - pub fn grandpa_log(digest: &DigestOf) -> Option> { - let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); - digest.convert_first(|l| l.try_to::>(id)) - } - - /// Attempt to extract a pending set-change signal from a digest. - pub fn pending_change(digest: &DigestOf) - -> Option> - { - Self::grandpa_log(digest).and_then(|signal| signal.try_into_change()) - } - - /// Attempt to extract a forced set-change signal from a digest. - pub fn forced_change(digest: &DigestOf) - -> Option<(T::BlockNumber, ScheduledChange)> - { - Self::grandpa_log(digest).and_then(|signal| signal.try_into_forced_change()) - } - - /// Attempt to extract a pause signal from a digest. - pub fn pending_pause(digest: &DigestOf) - -> Option - { - Self::grandpa_log(digest).and_then(|signal| signal.try_into_pause()) - } - - /// Attempt to extract a resume signal from a digest. - pub fn pending_resume(digest: &DigestOf) - -> Option - { - Self::grandpa_log(digest).and_then(|signal| signal.try_into_resume()) - } -} - -impl session::OneSessionHandler for Module - where T: session::Trait -{ - type Key = AuthorityId; - - fn on_genesis_session<'a, I: 'a>(validators: I) - where I: Iterator - { - let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); - Self::initialize_authorities(&authorities); - } - - fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) - where I: Iterator - { - // Always issue a change if `session` says that the validators have changed. - // Even if their session keys are the same as before, the underyling economic - // identities have changed. - let current_set_id = if changed { - let next_authorities = validators.map(|(_, k)| (k, 1)).collect::>(); - if let Some((further_wait, median)) = >::take() { - let _ = Self::schedule_change(next_authorities, further_wait, Some(median)); - } else { - let _ = Self::schedule_change(next_authorities, Zero::zero(), None); - } - CurrentSetId::mutate(|s| { *s += 1; *s }) - } else { - // nothing's changed, neither economic conditions nor session keys. update the pointer - // of the current set. - Self::current_set_id() - }; - - // if we didn't issue a change, we update the mapping to note that the current - // set corresponds to the latest equivalent session (i.e. now). - let session_index = >::current_index(); - SetIdSession::insert(current_set_id, &session_index); - } - - fn on_disabled(i: usize) { - Self::deposit_log(ConsensusLog::OnDisabled(i as u64)) - } -} - -impl finality_tracker::OnFinalizationStalled for Module { - fn on_stalled(further_wait: T::BlockNumber, median: 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. - >::put((further_wait, median)); - } -} - -/// A round number and set id which point on the time of an offence. -#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Encode, Decode)] -struct GrandpaTimeSlot { - // The order of these matters for `derive(Ord)`. - set_id: SetId, - round: RoundNumber, -} - -// TODO [slashing]: Integrate this. -/// A grandpa equivocation offence report. -#[allow(dead_code)] -struct GrandpaEquivocationOffence { - /// Time slot at which this incident happened. - time_slot: GrandpaTimeSlot, - /// The session index in which the incident happened. - session_index: SessionIndex, - /// The size of the validator set at the time of the offence. - validator_set_count: u32, - /// The authority which produced this equivocation. - offender: FullIdentification, -} - -impl Offence for GrandpaEquivocationOffence { - const ID: Kind = *b"grandpa:equivoca"; - type TimeSlot = GrandpaTimeSlot; - - fn offenders(&self) -> Vec { - vec![self.offender.clone()] - } - - fn session_index(&self) -> SessionIndex { - self.session_index - } - - fn validator_set_count(&self) -> u32 { - self.validator_set_count - } - - fn time_slot(&self) -> Self::TimeSlot { - self.time_slot - } - - fn slash_fraction( - offenders_count: u32, - validator_set_count: u32, - ) -> Perbill { - // the formula is min((3k / n)^2, 1) - let x = Perbill::from_rational_approximation(3 * offenders_count, validator_set_count); - // _ ^ 2 - x.square() - } -} diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs deleted file mode 100644 index fcacbade20490..0000000000000 --- a/srml/grandpa/src/mock.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -#![cfg(test)] - -use sr_primitives::{Perbill, DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; -use runtime_io; -use support::{impl_outer_origin, impl_outer_event, parameter_types}; -use primitives::H256; -use codec::{Encode, Decode}; -use crate::{AuthorityId, GenesisConfig, Trait, Module, ConsensusLog}; -use substrate_finality_grandpa_primitives::GRANDPA_ENGINE_ID; - -impl_outer_origin!{ - pub enum Origin for Test {} -} - -pub fn grandpa_log(log: ConsensusLog) -> DigestItem { - DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()) -} - -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug, Decode, Encode)] -pub struct Test; - -impl Trait for Test { - type Event = TestEvent; -} -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = sr_primitives::traits::BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = TestEvent; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} - -mod grandpa { - pub use crate::Event; -} - -impl_outer_event!{ - pub enum TestEvent for Test { - grandpa, - } -} - -pub fn to_authorities(vec: Vec<(u64, u64)>) -> Vec<(AuthorityId, u64)> { - vec.into_iter() - .map(|(id, weight)| (UintAuthorityId(id).to_public_key::(), weight)) - .collect() -} - -pub fn new_test_ext(authorities: Vec<(u64, u64)>) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig { - authorities: to_authorities(authorities), - }.assimilate_storage::(&mut t).unwrap(); - t.into() -} - -pub type System = system::Module; -pub type Grandpa = Module; diff --git a/srml/grandpa/src/tests.rs b/srml/grandpa/src/tests.rs deleted file mode 100644 index 2efeb4b5bf3cf..0000000000000 --- a/srml/grandpa/src/tests.rs +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the module. - -#![cfg(test)] - -use sr_primitives::{testing::Digest, traits::{Header, OnFinalize}}; -use crate::mock::*; -use system::{EventRecord, Phase}; -use codec::{Decode, Encode}; -use fg_primitives::ScheduledChange; -use super::*; - -#[test] -fn authorities_change_logged() { - new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 0, None).unwrap(); - - System::note_finished_extrinsics(); - Grandpa::on_finalize(1); - - let header = System::finalize(); - assert_eq!(header.digest, Digest { - logs: vec![ - grandpa_log(ConsensusLog::ScheduledChange( - ScheduledChange { delay: 0, next_authorities: to_authorities(vec![(4, 1), (5, 1), (6, 1)]) } - )), - ], - }); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Finalization, - event: Event::NewAuthorities(to_authorities(vec![(4, 1), (5, 1), (6, 1)])).into(), - topics: vec![], - }, - ]); - }); -} - -#[test] -fn authorities_change_logged_after_delay() { - new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 1, None).unwrap(); - Grandpa::on_finalize(1); - let header = System::finalize(); - assert_eq!(header.digest, Digest { - logs: vec![ - grandpa_log(ConsensusLog::ScheduledChange( - ScheduledChange { delay: 1, next_authorities: to_authorities(vec![(4, 1), (5, 1), (6, 1)]) } - )), - ], - }); - - // no change at this height. - assert_eq!(System::events(), vec![]); - - System::initialize(&2, &header.hash(), &Default::default(), &Default::default()); - System::note_finished_extrinsics(); - Grandpa::on_finalize(2); - - let _header = System::finalize(); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::Finalization, - event: Event::NewAuthorities(to_authorities(vec![(4, 1), (5, 1), (6, 1)])).into(), - topics: vec![], - }, - ]); - }); -} - -#[test] -fn cannot_schedule_change_when_one_pending() { - new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 1, None).unwrap(); - assert!(>::exists()); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err()); - - Grandpa::on_finalize(1); - let header = System::finalize(); - - System::initialize(&2, &header.hash(), &Default::default(), &Default::default()); - assert!(>::exists()); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err()); - - Grandpa::on_finalize(2); - let header = System::finalize(); - - System::initialize(&3, &header.hash(), &Default::default(), &Default::default()); - assert!(!>::exists()); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_ok()); - - Grandpa::on_finalize(3); - let _header = System::finalize(); - }); -} - -#[test] -fn new_decodes_from_old() { - let old = OldStoredPendingChange { - scheduled_at: 5u32, - delay: 100u32, - next_authorities: to_authorities(vec![(1, 5), (2, 10), (3, 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() { - new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - Grandpa::schedule_change( - to_authorities(vec![(4, 1), (5, 1), (6, 1)]), - 5, - Some(0), - ).unwrap(); - - assert!(>::exists()); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, Some(0)).is_err()); - - Grandpa::on_finalize(1); - let mut header = System::finalize(); - - for i in 2..7 { - System::initialize(&i, &header.hash(), &Default::default(), &Default::default()); - assert!(>::get().unwrap().forced.is_some()); - assert_eq!(Grandpa::next_forced(), Some(11)); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err()); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, Some(0)).is_err()); - - Grandpa::on_finalize(i); - header = System::finalize(); - } - - // change has been applied at the end of block 6. - // add a normal change. - { - System::initialize(&7, &header.hash(), &Default::default(), &Default::default()); - assert!(!>::exists()); - assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(4, 1), (5, 1), (6, 1)])); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_ok()); - Grandpa::on_finalize(7); - header = System::finalize(); - } - - // run the normal change. - { - System::initialize(&8, &header.hash(), &Default::default(), &Default::default()); - assert!(>::exists()); - assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(4, 1), (5, 1), (6, 1)])); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err()); - Grandpa::on_finalize(8); - header = System::finalize(); - } - - // normal change applied. but we can't apply a new forced change for some - // time. - for i in 9..11 { - System::initialize(&i, &header.hash(), &Default::default(), &Default::default()); - assert!(!>::exists()); - assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(5, 1)])); - assert_eq!(Grandpa::next_forced(), Some(11)); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1), (6, 1)]), 5, Some(0)).is_err()); - Grandpa::on_finalize(i); - header = System::finalize(); - } - - { - System::initialize(&11, &header.hash(), &Default::default(), &Default::default()); - assert!(!>::exists()); - assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1), (6, 1), (7, 1)]), 5, Some(0)).is_ok()); - assert_eq!(Grandpa::next_forced(), Some(21)); - Grandpa::on_finalize(11); - header = System::finalize(); - } - let _ = header; - }); -} - -#[test] -fn schedule_pause_only_when_live() { - new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { - // we schedule a pause at block 1 with delay of 1 - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - Grandpa::schedule_pause(1).unwrap(); - - // we've switched to the pending pause state - assert_eq!( - Grandpa::state(), - StoredState::PendingPause { - scheduled_at: 1u64, - delay: 1, - }, - ); - - Grandpa::on_finalize(1); - let _ = System::finalize(); - - System::initialize(&2, &Default::default(), &Default::default(), &Default::default()); - - // signaling a pause now should fail - assert!(Grandpa::schedule_pause(1).is_err()); - - Grandpa::on_finalize(2); - let _ = System::finalize(); - - // after finalizing block 2 the set should have switched to paused state - assert_eq!( - Grandpa::state(), - StoredState::Paused, - ); - }); -} - -#[test] -fn schedule_resume_only_when_paused() { - new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - - // the set is currently live, resuming it is an error - assert!(Grandpa::schedule_resume(1).is_err()); - - assert_eq!( - Grandpa::state(), - StoredState::Live, - ); - - // we schedule a pause to be applied instantly - Grandpa::schedule_pause(0).unwrap(); - Grandpa::on_finalize(1); - let _ = System::finalize(); - - assert_eq!( - Grandpa::state(), - StoredState::Paused, - ); - - // we schedule the set to go back live in 2 blocks - System::initialize(&2, &Default::default(), &Default::default(), &Default::default()); - Grandpa::schedule_resume(2).unwrap(); - Grandpa::on_finalize(2); - let _ = System::finalize(); - - System::initialize(&3, &Default::default(), &Default::default(), &Default::default()); - Grandpa::on_finalize(3); - let _ = System::finalize(); - - System::initialize(&4, &Default::default(), &Default::default(), &Default::default()); - Grandpa::on_finalize(4); - let _ = System::finalize(); - - // it should be live at block 4 - assert_eq!( - Grandpa::state(), - StoredState::Live, - ); - }); -} - -#[test] -fn time_slot_have_sane_ord() { - // Ensure that `Ord` implementation is sane. - const FIXTURE: &[GrandpaTimeSlot] = &[ - GrandpaTimeSlot { - set_id: 0, - round: 0, - }, - GrandpaTimeSlot { - set_id: 0, - round: 1, - }, - GrandpaTimeSlot { - set_id: 1, - round: 0, - }, - GrandpaTimeSlot { - set_id: 1, - round: 1, - }, - GrandpaTimeSlot { - set_id: 1, - round: 2, - } - ]; - assert!(FIXTURE.windows(2).all(|f| f[0] < f[1])); -} diff --git a/srml/im-online/Cargo.toml b/srml/im-online/Cargo.toml deleted file mode 100644 index b62cc2a8f9615..0000000000000 --- a/srml/im-online/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "srml-im-online" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package="substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -serde = { version = "1.0.101", optional = true } -session = { package = "srml-session", path = "../session", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -offchain = { package = "substrate-offchain", path = "../../core/offchain" } - -[features] -default = ["std", "session/historical"] -std = [ - "app-crypto/std", - "codec/std", - "primitives/std", - "rstd/std", - "serde", - "session/std", - "runtime-io/std", - "sr-primitives/std", - "sr-staking-primitives/std", - "support/std", - "system/std", -] diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs deleted file mode 100644 index 82b866d32bc86..0000000000000 --- a/srml/im-online/src/lib.rs +++ /dev/null @@ -1,584 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # I'm online Module -//! -//! If the local node is a validator (i.e. contains an authority key), this module -//! gossips a heartbeat transaction with each new session. The heartbeat functions -//! as a simple mechanism to signal that the node is online in the current era. -//! -//! Received heartbeats are tracked for one era and reset with each new era. The -//! module exposes two public functions to query if a heartbeat has been received -//! in the current era or session. -//! -//! The heartbeat is a signed transaction, which was signed using the session key -//! and includes the recent best block number of the local validators chain as well -//! as the [NetworkState](../../core/offchain/struct.NetworkState.html). -//! It is submitted as an Unsigned Transaction via off-chain workers. -//! -//! - [`im_online::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! - [`Module`](./struct.Module.html) -//! -//! ## Interface -//! -//! ### Public Functions -//! -//! - `is_online_in_current_session` - True if the validator sent a heartbeat in the current session. -//! -//! ## Usage -//! -//! ``` -//! use support::{decl_module, dispatch::Result}; -//! use system::ensure_signed; -//! use srml_im_online::{self as im_online}; -//! -//! pub trait Trait: im_online::Trait {} -//! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! pub fn is_online(origin, authority_index: u32) -> Result { -//! let _sender = ensure_signed(origin)?; -//! let _is_online = >::is_online_in_current_session(authority_index); -//! Ok(()) -//! } -//! } -//! } -//! # fn main() { } -//! ``` -//! -//! ## Dependencies -//! -//! This module depends on the [Session module](../srml_session/index.html). - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -mod mock; -mod tests; - -use app_crypto::RuntimeAppPublic; -use codec::{Encode, Decode}; -use primitives::offchain::{OpaqueNetworkState, StorageKind}; -use rstd::prelude::*; -use session::historical::IdentificationTuple; -use sr_primitives::{ - RuntimeDebug, - traits::{Convert, Member, Printable, Saturating}, Perbill, - transaction_validity::{ - TransactionValidity, TransactionLongevity, ValidTransaction, InvalidTransaction, - }, -}; -use sr_staking_primitives::{ - SessionIndex, - offence::{ReportOffence, Offence, Kind}, -}; -use support::{ - decl_module, decl_event, decl_storage, print, ensure, Parameter, debug -}; -use system::ensure_none; -use system::offchain::SubmitUnsignedTransaction; - -pub mod sr25519 { - mod app_sr25519 { - use app_crypto::{app_crypto, key_types::IM_ONLINE, sr25519}; - app_crypto!(sr25519, IM_ONLINE); - } - - /// An i'm online keypair using sr25519 as its crypto. - #[cfg(feature = "std")] - pub type AuthorityPair = app_sr25519::Pair; - - /// An i'm online signature using sr25519 as its crypto. - pub type AuthoritySignature = app_sr25519::Signature; - - /// An i'm online identifier using sr25519 as its crypto. - pub type AuthorityId = app_sr25519::Public; -} - -pub mod ed25519 { - mod app_ed25519 { - use app_crypto::{app_crypto, key_types::IM_ONLINE, ed25519}; - app_crypto!(ed25519, IM_ONLINE); - } - - /// An i'm online keypair using ed25519 as its crypto. - #[cfg(feature = "std")] - pub type AuthorityPair = app_ed25519::Pair; - - /// An i'm online signature using ed25519 as its crypto. - pub type AuthoritySignature = app_ed25519::Signature; - - /// An i'm online identifier using ed25519 as its crypto. - pub type AuthorityId = app_ed25519::Public; -} - -/// The local storage database key under which the worker progress status -/// is tracked. -const DB_KEY: &[u8] = b"srml/im-online-worker-status"; - -/// It's important to persist the worker state, since e.g. the -/// server could be restarted while starting the gossip process, but before -/// finishing it. With every execution of the off-chain worker we check -/// if we need to recover and resume gossipping or if there is already -/// another off-chain worker in the process of gossipping. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -struct WorkerStatus { - done: bool, - gossipping_at: BlockNumber, -} - -/// Error which may occur while executing the off-chain code. -#[derive(RuntimeDebug)] -enum OffchainErr { - DecodeWorkerStatus, - FailedSigning, - NetworkState, - SubmitTransaction, -} - -impl Printable for OffchainErr { - fn print(&self) { - match self { - OffchainErr::DecodeWorkerStatus => print("Offchain error: decoding WorkerStatus failed!"), - OffchainErr::FailedSigning => print("Offchain error: signing failed!"), - OffchainErr::NetworkState => print("Offchain error: fetching network state failed!"), - OffchainErr::SubmitTransaction => print("Offchain error: submitting transaction failed!"), - } - } -} - -pub type AuthIndex = u32; - -/// Heartbeat which is sent/received. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct Heartbeat - where BlockNumber: PartialEq + Eq + Decode + Encode, -{ - block_number: BlockNumber, - network_state: OpaqueNetworkState, - session_index: SessionIndex, - authority_index: AuthIndex, -} - -pub trait Trait: system::Trait + session::historical::Trait { - /// The identifier type for an authority. - type AuthorityId: Member + Parameter + RuntimeAppPublic + Default + Ord; - - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// A dispatchable call type. - type Call: From>; - - /// A transaction submitter. - type SubmitTransaction: SubmitUnsignedTransaction::Call>; - - /// A type that gives us the ability to submit unresponsiveness offence reports. - type ReportUnresponsiveness: - ReportOffence< - Self::AccountId, - IdentificationTuple, - UnresponsivenessOffence>, - >; -} - -decl_event!( - pub enum Event where - ::AuthorityId, - { - /// A new heartbeat was received from `AuthorityId` - HeartbeatReceived(AuthorityId), - } -); - -decl_storage! { - trait Store for Module as ImOnline { - /// The block number when we should gossip. - GossipAt get(fn gossip_at): T::BlockNumber; - - /// The current set of keys that may issue a heartbeat. - Keys get(fn keys): Vec; - - /// For each session index we keep a mapping of `AuthorityId` - /// to `offchain::OpaqueNetworkState`. - ReceivedHeartbeats get(fn received_heartbeats): double_map SessionIndex, - blake2_256(AuthIndex) => Vec; - } - add_extra_genesis { - config(keys): Vec; - build(|config| Module::::initialize_keys(&config.keys)) - } -} - - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - fn heartbeat( - origin, - heartbeat: Heartbeat, - signature: ::Signature - ) { - ensure_none(origin)?; - - let current_session = >::current_index(); - ensure!(current_session == heartbeat.session_index, "Outdated heartbeat received."); - let exists = ::exists( - ¤t_session, - &heartbeat.authority_index - ); - let keys = Keys::::get(); - let public = keys.get(heartbeat.authority_index as usize); - if let (true, Some(public)) = (!exists, public) { - let signature_valid = heartbeat.using_encoded(|encoded_heartbeat| { - public.verify(&encoded_heartbeat, &signature) - }); - ensure!(signature_valid, "Invalid heartbeat signature."); - - Self::deposit_event(Event::::HeartbeatReceived(public.clone())); - - let network_state = heartbeat.network_state.encode(); - ::insert( - ¤t_session, - &heartbeat.authority_index, - &network_state - ); - } else if exists { - Err("Duplicated heartbeat.")? - } else { - Err("Non existent public key.")? - } - } - - // Runs after every block. - fn offchain_worker(now: T::BlockNumber) { - debug::RuntimeLogger::init(); - - // Only send messages if we are a potential validator. - if runtime_io::is_validator() { - Self::offchain(now); - } - } - } -} - -impl Module { - /// Returns `true` if a heartbeat has been received for the authority at `authority_index` in - /// the authorities series, during the current session. Otherwise `false`. - pub fn is_online_in_current_session(authority_index: AuthIndex) -> bool { - let current_session = >::current_index(); - ::exists(¤t_session, &authority_index) - } - - pub(crate) fn offchain(now: T::BlockNumber) { - let next_gossip = >::get(); - let check = Self::check_not_yet_gossipped(now, next_gossip); - let (curr_worker_status, not_yet_gossipped) = match check { - Ok((s, v)) => (s, v), - Err(err) => { - print(err); - return; - }, - }; - if next_gossip < now && not_yet_gossipped { - let value_set = Self::compare_and_set_worker_status(now, false, curr_worker_status); - if !value_set { - // value could not be set in local storage, since the value was - // different from `curr_worker_status`. this indicates that - // another worker was running in parallel. - return; - } - - match Self::do_gossip_at(now) { - Ok(_) => {}, - Err(err) => print(err), - } - } else { - debug::native::trace!( - target: "imonline", - "Skipping gossip at: {:?} >= {:?} || {:?}", - next_gossip, - now, - if not_yet_gossipped { "not gossipped" } else { "gossipped" } - ); - } - } - - fn do_gossip_at(block_number: T::BlockNumber) -> Result<(), OffchainErr> { - // we run only when a local authority key is configured - let authorities = Keys::::get(); - let mut local_keys = T::AuthorityId::all(); - local_keys.sort(); - - for (authority_index, key) in authorities.into_iter() - .enumerate() - .filter_map(|(index, authority)| { - local_keys.binary_search(&authority) - .ok() - .map(|location| (index as u32, &local_keys[location])) - }) - { - let network_state = runtime_io::network_state().map_err(|_| OffchainErr::NetworkState)?; - let heartbeat_data = Heartbeat { - block_number, - network_state, - session_index: >::current_index(), - authority_index, - }; - - let signature = key.sign(&heartbeat_data.encode()).ok_or(OffchainErr::FailedSigning)?; - let call = Call::heartbeat(heartbeat_data, signature); - - debug::info!( - target: "imonline", - "[index: {:?}] Reporting im-online at block: {:?}", - authority_index, - block_number - ); - T::SubmitTransaction::submit_unsigned(call) - .map_err(|_| OffchainErr::SubmitTransaction)?; - - // once finished we set the worker status without comparing - // if the existing value changed in the meantime. this is - // because at this point the heartbeat was definitely submitted. - Self::set_worker_status(block_number, true); - } - Ok(()) - } - - fn compare_and_set_worker_status( - gossipping_at: T::BlockNumber, - done: bool, - curr_worker_status: Option>, - ) -> bool { - let enc = WorkerStatus { - done, - gossipping_at, - }; - runtime_io::local_storage_compare_and_set( - StorageKind::PERSISTENT, - DB_KEY, - curr_worker_status.as_ref().map(Vec::as_slice), - &enc.encode() - ) - } - - fn set_worker_status( - gossipping_at: T::BlockNumber, - done: bool, - ) { - let enc = WorkerStatus { - done, - gossipping_at, - }; - runtime_io::local_storage_set( - StorageKind::PERSISTENT, DB_KEY, &enc.encode()); - } - - // Checks if a heartbeat gossip already occurred at this block number. - // Returns a tuple of `(current worker status, bool)`, whereby the bool - // is true if not yet gossipped. - fn check_not_yet_gossipped( - now: T::BlockNumber, - next_gossip: T::BlockNumber, - ) -> Result<(Option>, bool), OffchainErr> { - let last_gossip = runtime_io::local_storage_get(StorageKind::PERSISTENT, DB_KEY); - match last_gossip { - Some(last) => { - let worker_status: WorkerStatus = Decode::decode(&mut &last[..]) - .map_err(|_| OffchainErr::DecodeWorkerStatus)?; - - let was_aborted = !worker_status.done && worker_status.gossipping_at < now; - - // another off-chain worker is currently in the process of submitting - let already_submitting = - !worker_status.done && worker_status.gossipping_at == now; - - let not_yet_gossipped = - worker_status.done && worker_status.gossipping_at < next_gossip; - - let ret = (was_aborted && !already_submitting) || not_yet_gossipped; - Ok((Some(last), ret)) - }, - None => Ok((None, true)), - } - } - - fn initialize_keys(keys: &[T::AuthorityId]) { - if !keys.is_empty() { - assert!(Keys::::get().is_empty(), "Keys are already initialized!"); - Keys::::put(keys); - } - } -} - -impl session::OneSessionHandler for Module { - - type Key = T::AuthorityId; - - fn on_genesis_session<'a, I: 'a>(validators: I) - where I: Iterator - { - let keys = validators.map(|x| x.1).collect::>(); - Self::initialize_keys(&keys); - } - - fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, _queued_validators: I) - where I: Iterator - { - // Tell the offchain worker to start making the next session's heartbeats. - >::put(>::block_number()); - - // Remember who the authorities are for the new session. - Keys::::put(validators.map(|x| x.1).collect::>()); - } - - fn on_before_session_ending() { - let mut unresponsive = vec![]; - - let current_session = >::current_index(); - - let keys = Keys::::get(); - let current_validators = >::validators(); - - for (auth_idx, validator_id) in current_validators.into_iter().enumerate() { - let auth_idx = auth_idx as u32; - let exists = ::exists(¤t_session, &auth_idx); - if !exists { - let full_identification = T::FullIdentificationOf::convert(validator_id.clone()) - .expect( - "we got the validator_id from current_validators; - current_validators is set of currently acting validators; - the mapping between the validator id and its full identification should be valid; - thus `FullIdentificationOf::convert` can't return `None`; - qed", - ); - - unresponsive.push((validator_id, full_identification)); - } - } - - if unresponsive.is_empty() { - return; - } - - let validator_set_count = keys.len() as u32; - let offence = UnresponsivenessOffence { - session_index: current_session, - validator_set_count, - offenders: unresponsive, - }; - - T::ReportUnresponsiveness::report_offence(vec![], offence); - - // Remove all received heartbeats from the current session, they have - // already been processed and won't be needed anymore. - ::remove_prefix(&>::current_index()); - } - - fn on_disabled(_i: usize) { - // ignore - } -} - -impl support::unsigned::ValidateUnsigned for Module { - type Call = Call; - - fn validate_unsigned(call: &Self::Call) -> TransactionValidity { - if let Call::heartbeat(heartbeat, signature) = call { - if >::is_online_in_current_session(heartbeat.authority_index) { - // we already received a heartbeat for this authority - return InvalidTransaction::Stale.into(); - } - - // check if session index from heartbeat is recent - let current_session = >::current_index(); - if heartbeat.session_index != current_session { - return InvalidTransaction::Stale.into(); - } - - // verify that the incoming (unverified) pubkey is actually an authority id - let keys = Keys::::get(); - let authority_id = match keys.get(heartbeat.authority_index as usize) { - Some(id) => id, - None => return InvalidTransaction::BadProof.into(), - }; - - // check signature (this is expensive so we do it last). - let signature_valid = heartbeat.using_encoded(|encoded_heartbeat| { - authority_id.verify(&encoded_heartbeat, &signature) - }); - - if !signature_valid { - return InvalidTransaction::BadProof.into(); - } - - Ok(ValidTransaction { - priority: 0, - requires: vec![], - provides: vec![(current_session, authority_id).encode()], - longevity: TransactionLongevity::max_value(), - propagate: true, - }) - } else { - InvalidTransaction::Call.into() - } - } -} - -/// An offence that is filed if a validator didn't send a heartbeat message. -#[derive(RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Clone, PartialEq, Eq))] -pub struct UnresponsivenessOffence { - /// The current session index in which we report the unresponsive validators. - /// - /// It acts as a time measure for unresponsiveness reports and effectively will always point - /// at the end of the session. - session_index: SessionIndex, - /// The size of the validator set in current session/era. - validator_set_count: u32, - /// Authorities that were unresponsive during the current era. - offenders: Vec, -} - -impl Offence for UnresponsivenessOffence { - const ID: Kind = *b"im-online:offlin"; - type TimeSlot = SessionIndex; - - fn offenders(&self) -> Vec { - self.offenders.clone() - } - - fn session_index(&self) -> SessionIndex { - self.session_index - } - - fn validator_set_count(&self) -> u32 { - self.validator_set_count - } - - fn time_slot(&self) -> Self::TimeSlot { - self.session_index - } - - fn slash_fraction(offenders: u32, validator_set_count: u32) -> Perbill { - // the formula is min((3 * (k - 1)) / n, 1) * 0.05 - let x = Perbill::from_rational_approximation(3 * (offenders - 1), validator_set_count); - x.saturating_mul(Perbill::from_percent(5)) - } -} diff --git a/srml/im-online/src/mock.rs b/srml/im-online/src/mock.rs deleted file mode 100644 index e50e7779e9fcd..0000000000000 --- a/srml/im-online/src/mock.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -#![cfg(test)] - -use std::cell::RefCell; - -use crate::{Module, Trait}; -use sr_primitives::Perbill; -use sr_staking_primitives::{SessionIndex, offence::ReportOffence}; -use sr_primitives::testing::{Header, UintAuthorityId, TestXt}; -use sr_primitives::traits::{IdentityLookup, BlakeTwo256, ConvertInto}; -use primitives::H256; -use support::{impl_outer_origin, impl_outer_dispatch, parameter_types}; -use {runtime_io, system}; - -impl_outer_origin!{ - pub enum Origin for Runtime {} -} - -impl_outer_dispatch! { - pub enum Call for Runtime where origin: Origin { - imonline::ImOnline, - } -} - -thread_local! { - pub static VALIDATORS: RefCell>> = RefCell::new(Some(vec![1, 2, 3])); -} - -pub struct TestOnSessionEnding; -impl session::OnSessionEnding for TestOnSessionEnding { - fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) - -> Option> - { - VALIDATORS.with(|l| l.borrow_mut().take()) - } -} - -impl session::historical::OnSessionEnding for TestOnSessionEnding { - fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) - -> Option<(Vec, Vec<(u64, u64)>)> - { - VALIDATORS.with(|l| l - .borrow_mut() - .take() - .map(|validators| { - let full_identification = validators.iter().map(|v| (*v, *v)).collect(); - (validators, full_identification) - }) - ) - } -} - -/// An extrinsic type used for tests. -pub type Extrinsic = TestXt; -type SubmitTransaction = system::offchain::TransactionSubmitter<(), Call, Extrinsic>; -type IdentificationTuple = (u64, u64); -type Offence = crate::UnresponsivenessOffence; - -thread_local! { - pub static OFFENCES: RefCell, Offence)>> = RefCell::new(vec![]); -} - -/// A mock offence report handler. -pub struct OffenceHandler; -impl ReportOffence for OffenceHandler { - fn report_offence(reporters: Vec, offence: Offence) { - OFFENCES.with(|l| l.borrow_mut().push((reporters, offence))); - } -} - -pub fn new_test_ext() -> runtime_io::TestExternalities { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - t.into() -} - - -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Runtime; - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - -impl system::Trait for Runtime { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = Call; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} - -parameter_types! { - pub const Period: u64 = 1; - pub const Offset: u64 = 0; -} - -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); -} - -impl session::Trait for Runtime { - type ShouldEndSession = session::PeriodicSessions; - type OnSessionEnding = session::historical::NoteHistoricalRoot; - type SessionHandler = (ImOnline, ); - type ValidatorId = u64; - type ValidatorIdOf = ConvertInto; - type Keys = UintAuthorityId; - type Event = (); - type SelectInitialValidators = (); - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; -} - -impl session::historical::Trait for Runtime { - type FullIdentification = u64; - type FullIdentificationOf = ConvertInto; -} - -impl Trait for Runtime { - type AuthorityId = UintAuthorityId; - type Event = (); - type Call = Call; - type SubmitTransaction = SubmitTransaction; - type ReportUnresponsiveness = OffenceHandler; -} - -/// Im Online module. -pub type ImOnline = Module; -pub type System = system::Module; -pub type Session = session::Module; - -pub fn advance_session() { - let now = System::block_number(); - System::set_block_number(now + 1); - Session::rotate_session(); - assert_eq!(Session::current_index(), (now / Period::get()) as u32); -} diff --git a/srml/im-online/src/tests.rs b/srml/im-online/src/tests.rs deleted file mode 100644 index 652d751281294..0000000000000 --- a/srml/im-online/src/tests.rs +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the im-online module. - -#![cfg(test)] - -use super::*; -use crate::mock::*; -use offchain::testing::TestOffchainExt; -use primitives::offchain::{OpaquePeerId, OffchainExt}; -use support::{dispatch, assert_noop}; -use sr_primitives::testing::UintAuthorityId; - -#[test] -fn test_unresponsiveness_slash_fraction() { - // A single case of unresponsiveness is not slashed. - assert_eq!( - UnresponsivenessOffence::<()>::slash_fraction(1, 50), - Perbill::zero(), - ); - - assert_eq!( - UnresponsivenessOffence::<()>::slash_fraction(3, 50), - Perbill::from_parts(6000000), // 0.6% - ); - - // One third offline should be punished around 5%. - assert_eq!( - UnresponsivenessOffence::<()>::slash_fraction(17, 50), - Perbill::from_parts(48000000), // 4.8% - ); -} - -#[test] -fn should_report_offline_validators() { - new_test_ext().execute_with(|| { - // given - let block = 1; - System::set_block_number(block); - // buffer new validators - Session::rotate_session(); - // enact the change and buffer another one - let validators = vec![1, 2, 3, 4, 5, 6]; - VALIDATORS.with(|l| *l.borrow_mut() = Some(validators.clone())); - Session::rotate_session(); - - // when - // we end current session and start the next one - Session::rotate_session(); - - // then - let offences = OFFENCES.with(|l| l.replace(vec![])); - assert_eq!(offences, vec![ - (vec![], UnresponsivenessOffence { - session_index: 2, - validator_set_count: 3, - offenders: vec![ - (1, 1), - (2, 2), - (3, 3), - ], - }) - ]); - - // should not report when heartbeat is sent - for (idx, v) in validators.into_iter().take(4).enumerate() { - let _ = heartbeat(block, 3, idx as u32, v.into()).unwrap(); - } - Session::rotate_session(); - - // then - let offences = OFFENCES.with(|l| l.replace(vec![])); - assert_eq!(offences, vec![ - (vec![], UnresponsivenessOffence { - session_index: 3, - validator_set_count: 6, - offenders: vec![ - (5, 5), - (6, 6), - ], - }) - ]); - }); -} - -fn heartbeat( - block_number: u64, - session_index: u32, - authority_index: u32, - id: UintAuthorityId, -) -> dispatch::Result { - let heartbeat = Heartbeat { - block_number, - network_state: OpaqueNetworkState { - peer_id: OpaquePeerId(vec![1]), - external_addresses: vec![], - }, - session_index, - authority_index, - }; - let signature = id.sign(&heartbeat.encode()).unwrap(); - - ImOnline::heartbeat( - Origin::system(system::RawOrigin::None), - heartbeat, - signature - ) -} - -#[test] -fn should_mark_online_validator_when_heartbeat_is_received() { - new_test_ext().execute_with(|| { - advance_session(); - // given - VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); - assert_eq!(Session::validators(), Vec::::new()); - // enact the change and buffer another one - advance_session(); - - assert_eq!(Session::current_index(), 2); - assert_eq!(Session::validators(), vec![1, 2, 3]); - - assert!(!ImOnline::is_online_in_current_session(0)); - assert!(!ImOnline::is_online_in_current_session(1)); - assert!(!ImOnline::is_online_in_current_session(2)); - - // when - let _ = heartbeat(1, 2, 0, 1.into()).unwrap(); - - // then - assert!(ImOnline::is_online_in_current_session(0)); - assert!(!ImOnline::is_online_in_current_session(1)); - assert!(!ImOnline::is_online_in_current_session(2)); - - // and when - let _ = heartbeat(1, 2, 2, 3.into()).unwrap(); - - // then - assert!(ImOnline::is_online_in_current_session(0)); - assert!(!ImOnline::is_online_in_current_session(1)); - assert!(ImOnline::is_online_in_current_session(2)); - }); -} - -#[test] -fn late_heartbeat_should_fail() { - new_test_ext().execute_with(|| { - advance_session(); - // given - VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 4, 4, 5, 6])); - assert_eq!(Session::validators(), Vec::::new()); - // enact the change and buffer another one - advance_session(); - - assert_eq!(Session::current_index(), 2); - assert_eq!(Session::validators(), vec![1, 2, 3]); - - // when - assert_noop!(heartbeat(1, 3, 0, 1.into()), "Outdated heartbeat received."); - assert_noop!(heartbeat(1, 1, 0, 1.into()), "Outdated heartbeat received."); - }); -} - -#[test] -fn should_generate_heartbeats() { - let mut ext = new_test_ext(); - let (offchain, state) = TestOffchainExt::new(); - ext.register_extension(OffchainExt::new(offchain)); - - ext.execute_with(|| { - // given - let block = 1; - System::set_block_number(block); - // buffer new validators - Session::rotate_session(); - // enact the change and buffer another one - VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); - Session::rotate_session(); - - // when - UintAuthorityId::set_all_keys(vec![0, 1, 2]); - ImOnline::offchain(2); - - // then - let transaction = state.write().transactions.pop().unwrap(); - // All validators have `0` as their session key, so we generate 3 transactions. - assert_eq!(state.read().transactions.len(), 2); - // check stuff about the transaction. - let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); - let heartbeat = match ex.1 { - crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h, - e => panic!("Unexpected call: {:?}", e), - }; - - assert_eq!(heartbeat, Heartbeat { - block_number: 2, - network_state: runtime_io::network_state().unwrap(), - session_index: 2, - authority_index: 2, - }); - }); -} - -#[test] -fn should_cleanup_received_heartbeats_on_session_end() { - new_test_ext().execute_with(|| { - advance_session(); - - VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3])); - assert_eq!(Session::validators(), Vec::::new()); - - // enact the change and buffer another one - advance_session(); - - assert_eq!(Session::current_index(), 2); - assert_eq!(Session::validators(), vec![1, 2, 3]); - - // send an heartbeat from authority id 0 at session 2 - let _ = heartbeat(1, 2, 0, 1.into()).unwrap(); - - // the heartbeat is stored - assert!(!ImOnline::received_heartbeats(&2, &0).is_empty()); - - advance_session(); - - // after the session has ended we have already processed the heartbeat - // message, so any messages received on the previous session should have - // been pruned. - assert!(ImOnline::received_heartbeats(&2, &0).is_empty()); - }); -} diff --git a/srml/indices/Cargo.toml b/srml/indices/Cargo.toml deleted file mode 100644 index b8b560c3f9b4d..0000000000000 --- a/srml/indices/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "srml-indices" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -substrate-keyring = { path = "../../core/keyring", optional = true } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -ref_thread_local = "0.0.0" - -[features] -default = ["std"] -std = [ - "serde", - "safe-mix/std", - "substrate-keyring", - "codec/std", - "primitives/std", - "rstd/std", - "runtime-io/std", - "support/std", - "sr-primitives/std", - "system/std", -] diff --git a/srml/indices/src/lib.rs b/srml/indices/src/lib.rs deleted file mode 100644 index 31aa57276bde9..0000000000000 --- a/srml/indices/src/lib.rs +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! An 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::*, marker::PhantomData, convert::TryInto}; -use codec::{Encode, Codec}; -use support::{Parameter, decl_module, decl_event, decl_storage}; -use sr_primitives::traits::{One, SimpleArithmetic, StaticLookup, Member, LookupError}; -use system::{IsDeadAccount, OnNewAccount}; - -use self::address::Address as RawAddress; - -mod mock; - -pub mod address; -mod tests; - -/// Number of account IDs stored per enum set. -const ENUM_SET_SIZE: u32 = 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 implementation. -pub struct SimpleResolveHint(PhantomData<(AccountId, AccountIndex)>); -impl> - ResolveHint for SimpleResolveHint -{ - fn resolve_hint(who: &AccountId) -> Option { - Some(AccountIndex::from(who.using_encoded(|e| e[0] as u32 + e[1] as u32 * 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 + 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(fn next_enum_set) build(|config: &GenesisConfig| { - (config.ids.len() as u32 / ENUM_SET_SIZE).into() - }): T::AccountIndex; - - /// The enumeration sets. - pub EnumSet get(fn enum_set) build(|config: &GenesisConfig| { - (0..((config.ids.len() as u32) + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE) - .map(|i| ( - i.into(), - config.ids[ - (i * ENUM_SET_SIZE) as usize.. - config.ids.len().min(((i + 1) * ENUM_SET_SIZE) as usize) - ].to_owned(), - )) - .collect::>() - }): map T::AccountIndex => Vec; - } - add_extra_genesis { - config(ids): Vec; - } -} - -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).try_into().ok()?; - 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 maybe_usize: Result = (try_index % enum_set_size).try_into(); - if let Ok(i) = maybe_usize { - i < try_set.len() && T::IsDeadAccount::is_dead_account(&try_set[i]) - } else { - false - } - } - - /// 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 { - ENUM_SET_SIZE.into() - } -} - -impl OnNewAccount for Module { - // Implementation of the config type managing the creation of new accounts. - // See Balances module for a concrete example. - // - // # - // - Independent of the arguments. - // - Given the correct value of `Self::next_enum_set`, it always has a limited - // number of reads and writes and no complex computation. - // - // As for storage, calling this function with _non-dead-indices_ will linearly grow the length of - // of `Self::enum_set`. Appropriate economic incentives should exist to make callers of this - // function provide a `who` argument that reclaims a dead account. - // - // At the time of this writing, only the Balances module calls this function upon creation - // of new accounts. - // # - 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); - if let Ok(item_index) = (try_index % enum_set_size).try_into() { - 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 as usize { - break set; - } - set_index += One::one(); - }; - - let index = set_index * enum_set_size + T::AccountIndex::from(set.len() as u32); - - // update set. - set.push(who.clone()); - - // keep NextEnumSet up to date - if set.len() == ENUM_SET_SIZE as usize { - >::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 { - Self::lookup_address(a).ok_or(LookupError) - } - - fn unlookup(a: Self::Target) -> Self::Source { - address::Address::Id(a) - } -} diff --git a/srml/indices/src/mock.rs b/srml/indices/src/mock.rs deleted file mode 100644 index 427fd87c47e7d..0000000000000 --- a/srml/indices/src/mock.rs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -#![cfg(test)] - -use std::collections::HashSet; -use ref_thread_local::{ref_thread_local, RefThreadLocal}; -use sr_primitives::testing::Header; -use sr_primitives::Perbill; -use primitives::H256; -use support::{impl_outer_origin, parameter_types}; -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; -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl system::Trait for Runtime { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = ::sr_primitives::traits::BlakeTwo256; - type AccountId = u64; - type Lookup = Indices; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} -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(); - GenesisConfig:: { - ids: vec![1, 2, 3, 4] - }.assimilate_storage(&mut t).unwrap(); - t.into() -} - -pub type Indices = Module; diff --git a/srml/indices/src/tests.rs b/srml/indices/src/tests.rs deleted file mode 100644 index 3bcf0157130ce..0000000000000 --- a/srml/indices/src/tests.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the module. - -#![cfg(test)] - -use super::*; -use crate::mock::{Indices, new_test_ext, make_account, kill_account, TestIsDeadAccount}; - -#[test] -fn indexing_lookup_should_work() { - new_test_ext().execute_with(|| { - assert_eq!(Indices::lookup_index(0), Some(1)); - assert_eq!(Indices::lookup_index(1), Some(2)); - assert_eq!(Indices::lookup_index(2), Some(3)); - assert_eq!(Indices::lookup_index(3), Some(4)); - assert_eq!(Indices::lookup_index(4), None); - }); -} - -#[test] -fn default_indexing_on_new_accounts_should_work() { - new_test_ext().execute_with(|| { - assert_eq!(Indices::lookup_index(4), None); - make_account(5); - assert_eq!(Indices::lookup_index(4), Some(5)); - }); -} - -#[test] -fn reclaim_indexing_on_new_accounts_should_work() { - new_test_ext().execute_with(|| { - assert_eq!(Indices::lookup_index(1), Some(2)); - assert_eq!(Indices::lookup_index(4), None); - - kill_account(2); // index 1 no longer locked to id 2 - - make_account(1 + 256); // id 257 takes index 1. - assert_eq!(Indices::lookup_index(1), Some(257)); - }); -} - -#[test] -fn alive_account_should_prevent_reclaim() { - new_test_ext().execute_with(|| { - assert!(!TestIsDeadAccount::is_dead_account(&2)); - assert_eq!(Indices::lookup_index(1), Some(2)); - assert_eq!(Indices::lookup_index(4), None); - - make_account(1 + 256); // id 257 takes index 1. - assert_eq!(Indices::lookup_index(4), Some(257)); - }); -} diff --git a/srml/membership/Cargo.toml b/srml/membership/Cargo.toml deleted file mode 100644 index a8cb73055563e..0000000000000 --- a/srml/membership/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "srml-membership" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "sr-primitives/std", - "rstd/std", - "runtime-io/std", - "support/std", - "system/std", -] diff --git a/srml/membership/src/lib.rs b/srml/membership/src/lib.rs deleted file mode 100644 index 6cd2a914e6bff..0000000000000 --- a/srml/membership/src/lib.rs +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Membership Module -//! -//! Allows control of membership of a set of `AccountId`s, useful for managing membership of of a -//! collective. - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::prelude::*; -use support::{ - decl_module, decl_storage, decl_event, traits::{ChangeMembers, InitializeMembers}, -}; -use system::ensure_root; -use sr_primitives::{traits::EnsureOrigin, weights::SimpleDispatchInfo}; - -pub trait Trait: system::Trait { - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// Required origin for adding a member (though can always be Root). - type AddOrigin: EnsureOrigin; - - /// Required origin for removing a member (though can always be Root). - type RemoveOrigin: EnsureOrigin; - - /// Required origin for adding and removing a member in a single action. - type SwapOrigin: EnsureOrigin; - - /// Required origin for resetting membership. - type ResetOrigin: EnsureOrigin; - - /// The receiver of the signal for when the membership has been initialized. This happens pre- - /// genesis and will usually be the same as `MembershipChanged`. If you need to do something - /// different on initialization, then you can change this accordingly. - type MembershipInitialized: InitializeMembers; - - /// The receiver of the signal for when the membership has changed. - type MembershipChanged: ChangeMembers; -} - -decl_storage! { - trait Store for Module, I: Instance=DefaultInstance> as Membership { - /// The current membership, stored as an ordered Vec. - Members get(fn members): Vec; - } - add_extra_genesis { - config(members): Vec; - config(phantom): rstd::marker::PhantomData; - build(|config: &Self| { - let mut members = config.members.clone(); - members.sort(); - T::MembershipInitialized::initialize_members(&members); - >::put(members); - }) - } -} - -decl_event!( - pub enum Event where - ::AccountId, - >::Event, - { - /// The given member was added; see the transaction for who. - MemberAdded, - /// The given member was removed; see the transaction for who. - MemberRemoved, - /// Two members were swapped; see the transaction for who. - MembersSwapped, - /// The membership was reset; see the transaction for who the new set is. - MembersReset, - /// Phantom member, never used. - Dummy(rstd::marker::PhantomData<(AccountId, Event)>), - } -); - -decl_module! { - pub struct Module, I: Instance=DefaultInstance> - for enum Call - where origin: T::Origin - { - fn deposit_event() = default; - - /// Add a member `who` to the set. - /// - /// May only be called from `AddOrigin` or root. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn add_member(origin, who: T::AccountId) { - T::AddOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - let mut members = >::get(); - let location = members.binary_search(&who).err().ok_or("already a member")?; - members.insert(location, who.clone()); - >::put(&members); - - T::MembershipChanged::change_members_sorted(&[who], &[], &members[..]); - - Self::deposit_event(RawEvent::MemberAdded); - } - - /// Remove a member `who` from the set. - /// - /// May only be called from `RemoveOrigin` or root. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn remove_member(origin, who: T::AccountId) { - T::RemoveOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - let mut members = >::get(); - let location = members.binary_search(&who).ok().ok_or("not a member")?; - members.remove(location); - >::put(&members); - - T::MembershipChanged::change_members_sorted(&[], &[who], &members[..]); - - Self::deposit_event(RawEvent::MemberRemoved); - } - - /// Swap out one member `remove` for another `add`. - /// - /// May only be called from `SwapOrigin` or root. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn swap_member(origin, remove: T::AccountId, add: T::AccountId) { - T::SwapOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - if remove == add { return Ok(()) } - - let mut members = >::get(); - let location = members.binary_search(&remove).ok().ok_or("not a member")?; - members[location] = add.clone(); - let _location = members.binary_search(&add).err().ok_or("already a member")?; - members.sort(); - >::put(&members); - - T::MembershipChanged::change_members_sorted( - &[add], - &[remove], - &members[..], - ); - - Self::deposit_event(RawEvent::MembersSwapped); - } - - /// Change the membership to a new set, disregarding the existing membership. Be nice and - /// pass `members` pre-sorted. - /// - /// May only be called from `ResetOrigin` or root. - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn reset_members(origin, members: Vec) { - T::ResetOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - let mut members = members; - members.sort(); - >::mutate(|m| { - T::MembershipChanged::set_members_sorted(&members[..], m); - *m = members; - }); - - Self::deposit_event(RawEvent::MembersReset); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use std::cell::RefCell; - use support::{assert_ok, assert_noop, impl_outer_origin, parameter_types}; - use primitives::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. - use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; - use system::EnsureSignedBy; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - // For testing the module, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of modules we want to use. - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = (); - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - parameter_types! { - pub const One: u64 = 1; - pub const Two: u64 = 2; - pub const Three: u64 = 3; - pub const Four: u64 = 4; - pub const Five: u64 = 5; - } - - thread_local! { - static MEMBERS: RefCell> = RefCell::new(vec![]); - } - - pub struct TestChangeMembers; - impl ChangeMembers for TestChangeMembers { - fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { - let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); - old_plus_incoming.extend_from_slice(incoming); - old_plus_incoming.sort(); - let mut new_plus_outgoing = new.to_vec(); - new_plus_outgoing.extend_from_slice(outgoing); - new_plus_outgoing.sort(); - assert_eq!(old_plus_incoming, new_plus_outgoing); - - MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); - } - } - impl InitializeMembers for TestChangeMembers { - fn initialize_members(members: &[u64]) { - MEMBERS.with(|m| *m.borrow_mut() = members.to_vec()); - } - } - - impl Trait for Test { - type Event = (); - type AddOrigin = EnsureSignedBy; - type RemoveOrigin = EnsureSignedBy; - type SwapOrigin = EnsureSignedBy; - type ResetOrigin = EnsureSignedBy; - type MembershipInitialized = TestChangeMembers; - type MembershipChanged = TestChangeMembers; - } - - type Membership = Module; - - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. - fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. - GenesisConfig::{ - members: vec![10, 20, 30], - .. Default::default() - }.assimilate_storage(&mut t).unwrap(); - t.into() - } - - #[test] - fn query_membership_works() { - new_test_ext().execute_with(|| { - assert_eq!(Membership::members(), vec![10, 20, 30]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), vec![10, 20, 30]); - }); - } - - #[test] - fn add_member_works() { - new_test_ext().execute_with(|| { - assert_noop!(Membership::add_member(Origin::signed(5), 15), "bad origin"); - assert_noop!(Membership::add_member(Origin::signed(1), 10), "already a member"); - assert_ok!(Membership::add_member(Origin::signed(1), 15)); - assert_eq!(Membership::members(), vec![10, 15, 20, 30]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); - }); - } - - #[test] - fn remove_member_works() { - new_test_ext().execute_with(|| { - assert_noop!(Membership::remove_member(Origin::signed(5), 20), "bad origin"); - assert_noop!(Membership::remove_member(Origin::signed(2), 15), "not a member"); - assert_ok!(Membership::remove_member(Origin::signed(2), 20)); - assert_eq!(Membership::members(), vec![10, 30]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); - }); - } - - #[test] - fn swap_member_works() { - new_test_ext().execute_with(|| { - assert_noop!(Membership::swap_member(Origin::signed(5), 10, 25), "bad origin"); - assert_noop!(Membership::swap_member(Origin::signed(3), 15, 25), "not a member"); - assert_noop!(Membership::swap_member(Origin::signed(3), 10, 30), "already a member"); - assert_ok!(Membership::swap_member(Origin::signed(3), 20, 20)); - assert_eq!(Membership::members(), vec![10, 20, 30]); - assert_ok!(Membership::swap_member(Origin::signed(3), 10, 25)); - assert_eq!(Membership::members(), vec![20, 25, 30]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); - }); - } - - #[test] - fn reset_members_works() { - new_test_ext().execute_with(|| { - assert_noop!(Membership::reset_members(Origin::signed(1), vec![20, 40, 30]), "bad origin"); - assert_ok!(Membership::reset_members(Origin::signed(4), vec![20, 40, 30])); - assert_eq!(Membership::members(), vec![20, 30, 40]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), Membership::members()); - }); - } -} diff --git a/srml/metadata/Cargo.toml b/srml/metadata/Cargo.toml deleted file mode 100644 index e9381f68bbbf9..0000000000000 --- a/srml/metadata/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "srml-metadata" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", optional = true, features = ["derive"] } -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 = [ - "codec/std", - "rstd/std", - "primitives/std", - "serde", -] diff --git a/srml/metadata/src/lib.rs b/srml/metadata/src/lib.rs deleted file mode 100644 index d85a6837fc6e0..0000000000000 --- a/srml/metadata/src/lib.rs +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Decodable variant of the RuntimeMetadata. -//! -//! This really doesn't belong here, but is necessary for the moment. In the future -//! it should be removed entirely to an external module for shimming on to the -//! codec-encoded metadata. - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -use serde::Serialize; -#[cfg(feature = "std")] -use codec::{Decode, Input, Error}; -use codec::{Encode, Output}; -use rstd::vec::Vec; -use primitives::RuntimeDebug; - -#[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"))] -type StringBuf = &'static str; - -/// A type that decodes to a different type than it encodes. -/// The user needs to make sure that both types use the same encoding. -/// -/// For example a `&'static [ &'static str ]` can be decoded to a `Vec`. -#[derive(Clone)] -pub enum DecodeDifferent where B: 'static, O: 'static { - Encode(B), - Decoded(O), -} - -impl Encode for DecodeDifferent where B: Encode + 'static, O: Encode + 'static { - fn encode_to(&self, dest: &mut W) { - match self { - DecodeDifferent::Encode(b) => b.encode_to(dest), - DecodeDifferent::Decoded(o) => o.encode_to(dest), - } - } -} - -impl codec::EncodeLike for DecodeDifferent where B: Encode + 'static, O: Encode + 'static {} - -#[cfg(feature = "std")] -impl Decode for DecodeDifferent where B: 'static, O: Decode + 'static { - fn decode(input: &mut I) -> Result { - ::decode(input).map(|val| { - DecodeDifferent::Decoded(val) - }) - } -} - -impl PartialEq for DecodeDifferent -where - B: Encode + Eq + PartialEq + 'static, - O: Encode + Eq + PartialEq + 'static, -{ - fn eq(&self, other: &Self) -> bool { - self.encode() == other.encode() - } -} - -impl Eq for DecodeDifferent - where B: Encode + Eq + PartialEq + 'static, O: Encode + Eq + PartialEq + 'static -{} - -impl rstd::fmt::Debug for DecodeDifferent - where - B: rstd::fmt::Debug + Eq + 'static, - O: rstd::fmt::Debug + Eq + 'static, -{ - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - match self { - DecodeDifferent::Encode(b) => b.fmt(f), - DecodeDifferent::Decoded(o) => o.fmt(f), - } - } -} - -#[cfg(feature = "std")] -impl serde::Serialize for DecodeDifferent - where - B: serde::Serialize + 'static, - O: serde::Serialize + 'static, -{ - fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - match self { - DecodeDifferent::Encode(b) => b.serialize(serializer), - DecodeDifferent::Decoded(o) => o.serialize(serializer), - } - } -} - -pub type DecodeDifferentArray = DecodeDifferent<&'static [B], Vec>; - -type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; - -/// All the metadata about a function. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct FunctionMetadata { - pub name: DecodeDifferentStr, - pub arguments: DecodeDifferentArray, - pub documentation: DecodeDifferentArray<&'static str, StringBuf>, -} - -/// All the metadata about a function argument. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct FunctionArgumentMetadata { - pub name: DecodeDifferentStr, - pub ty: DecodeDifferentStr, -} - -/// Newtype wrapper for support encoding functions (actual the result of the function). -#[derive(Clone, Eq)] -pub struct FnEncode(pub fn() -> E) where E: Encode + 'static; - -impl Encode for FnEncode { - fn encode_to(&self, dest: &mut W) { - self.0().encode_to(dest); - } -} - -impl codec::EncodeLike for FnEncode {} - -impl PartialEq for FnEncode { - fn eq(&self, other: &Self) -> bool { - self.0().eq(&other.0()) - } -} - -impl rstd::fmt::Debug for FnEncode { - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - self.0().fmt(f) - } -} - -#[cfg(feature = "std")] -impl serde::Serialize for FnEncode { - fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - self.0().serialize(serializer) - } -} - -/// All the metadata about an outer event. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct OuterEventMetadata { - pub name: DecodeDifferentStr, - pub events: DecodeDifferentArray< - (&'static str, FnEncode<&'static [EventMetadata]>), - (StringBuf, Vec) - >, -} - -/// All the metadata about an event. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct EventMetadata { - pub name: DecodeDifferentStr, - pub arguments: DecodeDifferentArray<&'static str, StringBuf>, - pub documentation: DecodeDifferentArray<&'static str, StringBuf>, -} - -/// All the metadata about one storage entry. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct StorageEntryMetadata { - pub name: DecodeDifferentStr, - pub modifier: StorageEntryModifier, - pub ty: StorageEntryType, - pub default: ByteGetter, - pub documentation: DecodeDifferentArray<&'static str, StringBuf>, -} - -/// All the metadata about one module constant. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct ModuleConstantMetadata { - pub name: DecodeDifferentStr, - pub ty: DecodeDifferentStr, - pub value: ByteGetter, - pub documentation: DecodeDifferentArray<&'static str, StringBuf>, -} - -/// All the metadata about a module error. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct ErrorMetadata { - pub name: DecodeDifferentStr, - pub documentation: DecodeDifferentArray<&'static str, StringBuf>, -} - -/// All the metadata about errors in a module. -pub trait ModuleErrorMetadata { - fn metadata() -> &'static [ErrorMetadata]; -} - -impl ModuleErrorMetadata for &'static str { - fn metadata() -> &'static [ErrorMetadata] { - &[] - } -} - -/// A technical trait to store lazy initiated vec value as static dyn pointer. -pub trait DefaultByte: Send + Sync { - fn default_byte(&self) -> Vec; -} - -/// 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 codec::EncodeLike for DefaultByteGetter {} - -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) - } -} - -impl rstd::fmt::Debug for DefaultByteGetter { - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - self.0.default_byte().fmt(f) - } -} - -/// Hasher used by storage maps -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub enum StorageHasher { - Blake2_128, - Blake2_256, - Twox128, - Twox256, - Twox64Concat, -} - -/// A storage entry type. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub enum StorageEntryType { - Plain(DecodeDifferentStr), - Map { - hasher: StorageHasher, - key: DecodeDifferentStr, - value: DecodeDifferentStr, - is_linked: bool, - }, - DoubleMap { - hasher: StorageHasher, - key1: DecodeDifferentStr, - key2: DecodeDifferentStr, - value: DecodeDifferentStr, - key2_hasher: StorageHasher, - }, -} - -/// A storage entry modifier. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub enum StorageEntryModifier { - Optional, - Default, -} - -/// All metadata of the storage. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct StorageMetadata { - /// The common prefix used by all storage entries. - pub prefix: DecodeDifferent<&'static str, StringBuf>, - pub entries: DecodeDifferent<&'static [StorageEntryMetadata], Vec>, -} - -#[derive(Eq, Encode, PartialEq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -/// Metadata prefixed by a u32 for reserved usage -pub struct RuntimeMetadataPrefixed(pub u32, pub RuntimeMetadata); - -/// The metadata of a runtime. -/// The version ID encoded/decoded through -/// the enum nature of `RuntimeMetadata`. -#[derive(Eq, Encode, PartialEq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub enum RuntimeMetadata { - /// Unused; enum filler. - V0(RuntimeMetadataDeprecated), - /// Version 1 for runtime metadata. No longer used. - V1(RuntimeMetadataDeprecated), - /// Version 2 for runtime metadata. No longer used. - V2(RuntimeMetadataDeprecated), - /// Version 3 for runtime metadata. No longer used. - V3(RuntimeMetadataDeprecated), - /// Version 4 for runtime metadata. No longer used. - V4(RuntimeMetadataDeprecated), - /// Version 5 for runtime metadata. No longer used. - V5(RuntimeMetadataDeprecated), - /// Version 6 for runtime metadata. No longer used. - V6(RuntimeMetadataDeprecated), - /// Version 7 for runtime metadata. No longer used. - V7(RuntimeMetadataDeprecated), - /// Version 8 for runtime metadata. - V8(RuntimeMetadataV8), -} - -/// Enum that should fail. -#[derive(Eq, PartialEq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize))] -pub enum RuntimeMetadataDeprecated { } - -impl Encode for RuntimeMetadataDeprecated { - fn encode_to(&self, _dest: &mut W) {} -} - -impl codec::EncodeLike for RuntimeMetadataDeprecated {} - -#[cfg(feature = "std")] -impl Decode for RuntimeMetadataDeprecated { - fn decode(_input: &mut I) -> Result { - Err("Decoding is not supported".into()) - } -} - -/// The metadata of a runtime. -#[derive(Eq, Encode, PartialEq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct RuntimeMetadataV8 { - pub modules: DecodeDifferentArray, -} - -/// The latest version of the metadata. -pub type RuntimeMetadataLastVersion = RuntimeMetadataV8; - -/// All metadata about an runtime module. -#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode, Serialize))] -pub struct ModuleMetadata { - pub name: DecodeDifferentStr, - pub storage: Option, StorageMetadata>>, - pub calls: ODFnA, - pub event: ODFnA, - pub constants: DFnA, - pub errors: DFnA, -} - -type ODFnA = Option>; -type DFnA = DecodeDifferent, Vec>; - -impl Into for RuntimeMetadataPrefixed { - fn into(self) -> primitives::OpaqueMetadata { - primitives::OpaqueMetadata::new(self.encode()) - } -} - -impl Into for RuntimeMetadataLastVersion { - fn into(self) -> RuntimeMetadataPrefixed { - RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V8(self)) - } -} diff --git a/srml/nicks/Cargo.toml b/srml/nicks/Cargo.toml deleted file mode 100644 index 4b8fabe9effe5..0000000000000 --- a/srml/nicks/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "srml-nicks" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -balances = { package = "srml-balances", path = "../balances", default-features = false } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "rstd/std", - "runtime-io/std", - "sr-primitives/std", - "support/std", - "system/std", -] diff --git a/srml/nicks/src/lib.rs b/srml/nicks/src/lib.rs deleted file mode 100644 index 6b914ca5dc220..0000000000000 --- a/srml/nicks/src/lib.rs +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Nicks Module -//! -//! - [`nicks::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! -//! ## Overview -//! -//! Nicks is a trivial module for keeping track of account names on-chain. It makes no effort to -//! create a name hierarchy, be a DNS replacement or provide reverse lookups. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! * `set_name` - Set the associated name of an account; a small deposit is reserved if not already -//! taken. -//! * `clear_name` - Remove an account's associated name; the deposit is returned. -//! * `kill_name` - Forcibly remove the associated name; the deposit is lost. -//! -//! [`Call`]: ./enum.Call.html -//! [`Trait`]: ./trait.Trait.html - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::prelude::*; -use sr_primitives::{ - traits::{StaticLookup, EnsureOrigin, Zero}, weights::SimpleDispatchInfo -}; -use support::{ - decl_module, decl_event, decl_storage, ensure, traits::{ - Currency, ReservableCurrency, OnUnbalanced, Get - }, -}; -use system::{ensure_signed, ensure_root}; - -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; - -pub trait Trait: system::Trait { - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// The currency trait. - type Currency: ReservableCurrency; - - /// Reservation fee. - type ReservationFee: Get>; - - /// What to do with slashed funds. - type Slashed: OnUnbalanced>; - - /// The origin which may forcibly set or remove a name. Root can always do this. - type ForceOrigin: EnsureOrigin; - - /// The minimum length a name may be. - type MinLength: Get; - - /// The maximum length a name may be. - type MaxLength: Get; -} - -decl_storage! { - trait Store for Module as Sudo { - /// The lookup table for names. - NameOf: map T::AccountId => Option<(Vec, BalanceOf)>; - } -} - -decl_event!( - pub enum Event where AccountId = ::AccountId, Balance = BalanceOf { - /// A name was set. - NameSet(AccountId), - /// A name was forcibly set. - NameForced(AccountId), - /// A name was changed. - NameChanged(AccountId), - /// A name was cleared, and the given balance returned. - NameCleared(AccountId, Balance), - /// A name was removed and the given balance slashed. - NameKilled(AccountId, Balance), - } -); - -decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what it's working on. - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - /// Reservation fee. - const ReservationFee: BalanceOf = T::ReservationFee::get(); - - /// The minimum length a name may be. - const MinLength: u32 = T::MinLength::get() as u32; - - /// The maximum length a name may be. - const MaxLength: u32 = T::MaxLength::get() as u32; - - /// Set an account's name. The name should be a UTF-8-encoded string by convention, though - /// we don't check it. - /// - /// The name may not be more than `T::MaxLength` bytes, nor less than `T::MinLength` bytes. - /// - /// If the account doesn't already have a name, then a fee of `ReservationFee` is reserved - /// in the account. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// # - /// - O(1). - /// - At most one balance operation. - /// - One storage read/write. - /// - One event. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn set_name(origin, name: Vec) { - let sender = ensure_signed(origin)?; - - ensure!(name.len() >= T::MinLength::get(), "Name too short"); - ensure!(name.len() <= T::MaxLength::get(), "Name too long"); - - let deposit = if let Some((_, deposit)) = >::get(&sender) { - Self::deposit_event(RawEvent::NameSet(sender.clone())); - deposit - } else { - let deposit = T::ReservationFee::get(); - T::Currency::reserve(&sender, deposit.clone())?; - Self::deposit_event(RawEvent::NameChanged(sender.clone())); - deposit - }; - - >::insert(&sender, (name, deposit)); - } - - /// Clear an account's name and return the deposit. Fails if the account was not named. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// # - /// - O(1). - /// - One balance operation. - /// - One storage read/write. - /// - One event. - /// # - fn clear_name(origin) { - let sender = ensure_signed(origin)?; - - let deposit = >::take(&sender).ok_or("Not named")?.1; - - let _ = T::Currency::unreserve(&sender, deposit.clone()); - - Self::deposit_event(RawEvent::NameCleared(sender, deposit)); - } - - /// Remove an account's name and take charge of the deposit. - /// - /// Fails if `who` has not been named. The deposit is dealt with through `T::Slashed` - /// imbalance handler. - /// - /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. - /// - /// # - /// - O(1). - /// - One unbalanced handler (probably a balance transfer) - /// - One storage read/write. - /// - One event. - /// # - #[weight = SimpleDispatchInfo::FreeOperational] - fn kill_name(origin, target: ::Source) { - T::ForceOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - // Figure out who we're meant to be clearing. - let target = T::Lookup::lookup(target)?; - // Grab their deposit (and check that they have one). - let deposit = >::take(&target).ok_or("Not named")?.1; - // Slash their deposit from them. - T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit.clone()).0); - - Self::deposit_event(RawEvent::NameKilled(target, deposit)); - } - - /// Set a third-party account's name with no deposit. - /// - /// No length checking is done on the name. - /// - /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. - /// - /// # - /// - O(1). - /// - At most one balance operation. - /// - One storage read/write. - /// - One event. - /// # - #[weight = SimpleDispatchInfo::FreeOperational] - fn force_name(origin, target: ::Source, name: Vec) { - T::ForceOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - let target = T::Lookup::lookup(target)?; - let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); - >::insert(&target, (name, deposit)); - - Self::deposit_event(RawEvent::NameForced(target)); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use support::{assert_ok, assert_noop, impl_outer_origin, parameter_types}; - use primitives::H256; - use system::EnsureSignedBy; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. - use sr_primitives::{ - Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, - }; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - // For testing the module, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of modules we want to use. - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = (); - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - } - impl balances::Trait for Test { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - parameter_types! { - pub const ReservationFee: u64 = 2; - pub const MinLength: usize = 3; - pub const MaxLength: usize = 16; - pub const One: u64 = 1; - } - impl Trait for Test { - type Event = (); - type Currency = Balances; - type ReservationFee = ReservationFee; - type Slashed = (); - type ForceOrigin = EnsureSignedBy; - type MinLength = MinLength; - type MaxLength = MaxLength; - } - type Balances = balances::Module; - type Nicks = Module; - - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. - fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. - balances::GenesisConfig:: { - balances: vec![ - (1, 10), - (2, 10), - ], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - t.into() - } - - #[test] - fn kill_name_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); - assert_eq!(Balances::total_balance(&2), 10); - assert_ok!(Nicks::kill_name(Origin::signed(1), 2)); - assert_eq!(Balances::total_balance(&2), 8); - assert_eq!(>::get(2), None); - }); - } - - #[test] - fn force_name_should_work() { - new_test_ext().execute_with(|| { - assert_noop!( - Nicks::set_name(Origin::signed(2), b"Dr. David Brubeck, III".to_vec()), - "Name too long" - ); - - assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); - assert_eq!(Balances::reserved_balance(&2), 2); - assert_ok!(Nicks::force_name(Origin::signed(1), 2, b"Dr. David Brubeck, III".to_vec())); - assert_eq!(Balances::reserved_balance(&2), 2); - assert_eq!(>::get(2).unwrap(), (b"Dr. David Brubeck, III".to_vec(), 2)); - }); - } - - #[test] - fn normal_operation_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Nicks::set_name(Origin::signed(1), b"Gav".to_vec())); - assert_eq!(Balances::reserved_balance(&1), 2); - assert_eq!(Balances::free_balance(&1), 8); - assert_eq!(>::get(1).unwrap().0, b"Gav".to_vec()); - - assert_ok!(Nicks::set_name(Origin::signed(1), b"Gavin".to_vec())); - assert_eq!(Balances::reserved_balance(&1), 2); - assert_eq!(Balances::free_balance(&1), 8); - assert_eq!(>::get(1).unwrap().0, b"Gavin".to_vec()); - - assert_ok!(Nicks::clear_name(Origin::signed(1))); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(Balances::free_balance(&1), 10); - }); - } - - #[test] - fn error_catching_should_work() { - new_test_ext().execute_with(|| { - assert_noop!(Nicks::clear_name(Origin::signed(1)), "Not named"); - - assert_noop!(Nicks::set_name(Origin::signed(3), b"Dave".to_vec()), "not enough free funds"); - - assert_noop!(Nicks::set_name(Origin::signed(1), b"Ga".to_vec()), "Name too short"); - assert_noop!( - Nicks::set_name(Origin::signed(1), b"Gavin James Wood, Esquire".to_vec()), - "Name too long" - ); - assert_ok!(Nicks::set_name(Origin::signed(1), b"Dave".to_vec())); - assert_noop!(Nicks::kill_name(Origin::signed(2), 1), "bad origin"); - assert_noop!(Nicks::force_name(Origin::signed(2), 1, b"Whatever".to_vec()), "bad origin"); - }); - } -} diff --git a/srml/offences/Cargo.toml b/srml/offences/Cargo.toml deleted file mode 100644 index 90a3396d11228..0000000000000 --- a/srml/offences/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "srml-offences" -version = "1.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -balances = { package = "srml-balances", path = "../balances", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -serde = { version = "1.0.101", optional = true } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -runtime-io = { package = "sr-io", path = "../../core/sr-io" } -substrate-primitives = { path = "../../core/primitives" } - -[features] -default = ["std"] -std = [ - "balances/std", - "codec/std", - "rstd/std", - "serde", - "sr-primitives/std", - "sr-staking-primitives/std", - "support/std", - "system/std", -] diff --git a/srml/offences/src/lib.rs b/srml/offences/src/lib.rs deleted file mode 100644 index a6cf4d7956467..0000000000000 --- a/srml/offences/src/lib.rs +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Offences Module -//! -//! Tracks reported offences - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -mod mock; -mod tests; - -use rstd::{ - vec::Vec, - collections::btree_set::BTreeSet, -}; -use support::{ - decl_module, decl_event, decl_storage, Parameter, -}; -use sr_primitives::{ - Perbill, - traits::{Hash, Saturating}, -}; -use sr_staking_primitives::{ - offence::{Offence, ReportOffence, Kind, OnOffenceHandler, OffenceDetails}, -}; -use codec::{Encode, Decode}; - -/// A binary blob which represents a SCALE codec-encoded `O::TimeSlot`. -type OpaqueTimeSlot = Vec; - -/// A type alias for a report identifier. -type ReportIdOf = ::Hash; - -/// Offences trait -pub trait Trait: system::Trait { - /// The overarching event type. - type Event: From + Into<::Event>; - /// Full identification of the validator. - type IdentificationTuple: Parameter + Ord; - /// A handler called for every offence report. - type OnOffenceHandler: OnOffenceHandler; -} - -decl_storage! { - trait Store for Module as Offences { - /// The primary structure that holds all offence records keyed by report identifiers. - Reports get(fn reports): map ReportIdOf => Option>; - - /// A vector of reports of the same kind that happened at the same time slot. - ConcurrentReportsIndex: double_map Kind, blake2_256(OpaqueTimeSlot) => Vec>; - - /// Enumerates all reports of a kind along with the time they happened. - /// - /// All reports are sorted by the time of offence. - /// - /// Note that the actual type of this mapping is `Vec`, this is because values of - /// different types are not supported at the moment so we are doing the manual serialization. - ReportsByKindIndex: map Kind => Vec; // (O::TimeSlot, ReportIdOf) - } -} - -decl_event!( - pub enum Event { - /// There is an offence reported of the given `kind` happened at the `session_index` and - /// (kind-specific) time slot. This event is not deposited for duplicate slashes. - Offence(Kind, OpaqueTimeSlot), - } -); - -decl_module! { - /// Offences module, currently just responsible for taking offence reports. - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - } -} -impl> - ReportOffence for Module -where - T::IdentificationTuple: Clone, -{ - fn report_offence(reporters: Vec, offence: O) { - let offenders = offence.offenders(); - let time_slot = offence.time_slot(); - let validator_set_count = offence.validator_set_count(); - - // Go through all offenders in the offence report and find all offenders that was spotted - // in unique reports. - let TriageOutcome { - new_offenders, - concurrent_offenders, - } = match Self::triage_offence_report::(reporters, &time_slot, offenders) { - Some(triage) => triage, - // The report contained only duplicates, so there is no need to slash again. - None => return, - }; - - // Deposit the event. - Self::deposit_event(Event::Offence(O::ID, time_slot.encode())); - - let offenders_count = concurrent_offenders.len() as u32; - let previous_offenders_count = offenders_count - new_offenders.len() as u32; - - // The amount new offenders are slashed - let new_fraction = O::slash_fraction(offenders_count, validator_set_count); - - // The amount previous offenders are slashed additionally. - // - // Since they were slashed in the past, we slash by: - // x = (new - prev) / (1 - prev) - // because: - // Y = X * (1 - prev) - // Z = Y * (1 - x) - // Z = X * (1 - new) - let old_fraction = if previous_offenders_count > 0 { - let previous_fraction = O::slash_fraction( - offenders_count.saturating_sub(previous_offenders_count), - validator_set_count, - ); - let numerator = new_fraction.saturating_sub(previous_fraction); - let denominator = Perbill::one().saturating_sub(previous_fraction); - denominator.saturating_mul(numerator) - } else { - new_fraction.clone() - }; - - // calculate how much to slash - let slash_perbill = concurrent_offenders - .iter() - .map(|details| { - if previous_offenders_count > 0 && new_offenders.contains(&details.offender) { - new_fraction.clone() - } else { - old_fraction.clone() - } - }) - .collect::>(); - - T::OnOffenceHandler::on_offence(&concurrent_offenders, &slash_perbill); - } -} - -impl Module { - /// Compute the ID for the given report properties. - /// - /// The report id depends on the offence kind, time slot and the id of offender. - fn report_id>( - time_slot: &O::TimeSlot, - offender: &T::IdentificationTuple, - ) -> ReportIdOf { - (O::ID, time_slot.encode(), offender).using_encoded(T::Hashing::hash) - } - - /// Triages the offence report and returns the set of offenders that was involved in unique - /// reports along with the list of the concurrent offences. - fn triage_offence_report>( - reporters: Vec, - time_slot: &O::TimeSlot, - offenders: Vec, - ) -> Option> { - let mut storage = ReportIndexStorage::::load(time_slot); - let mut new_offenders = BTreeSet::new(); - - for offender in offenders { - let report_id = Self::report_id::(time_slot, &offender); - - if !>::exists(&report_id) { - new_offenders.insert(offender.clone()); - >::insert( - &report_id, - OffenceDetails { - offender, - reporters: reporters.clone(), - }, - ); - - storage.insert(time_slot, report_id); - } - } - - if !new_offenders.is_empty() { - // Load report details for the all reports happened at the same time. - let concurrent_offenders = storage.concurrent_reports - .iter() - .filter_map(|report_id| >::get(report_id)) - .collect::>(); - - storage.save(); - - Some(TriageOutcome { - new_offenders, - concurrent_offenders, - }) - } else { - None - } - } -} - -struct TriageOutcome { - /// Offenders that was spotted in the unique reports. - new_offenders: BTreeSet, - /// Other reports for the same report kinds. - concurrent_offenders: Vec>, -} - -/// An auxilary struct for working with storage of indexes localized for a specific offence -/// kind (specified by the `O` type parameter). -/// -/// This struct is responsible for aggregating storage writes and the underlying storage should not -/// accessed directly meanwhile. -#[must_use = "The changes are not saved without called `save`"] -struct ReportIndexStorage> { - opaque_time_slot: OpaqueTimeSlot, - concurrent_reports: Vec>, - same_kind_reports: Vec<(O::TimeSlot, ReportIdOf)>, -} - -impl> ReportIndexStorage { - /// Preload indexes from the storage for the specific `time_slot` and the kind of the offence. - fn load(time_slot: &O::TimeSlot) -> Self { - let opaque_time_slot = time_slot.encode(); - - let same_kind_reports = ::get(&O::ID); - let same_kind_reports = - Vec::<(O::TimeSlot, ReportIdOf)>::decode(&mut &same_kind_reports[..]) - .unwrap_or_default(); - - let concurrent_reports = >::get(&O::ID, &opaque_time_slot); - - Self { - opaque_time_slot, - concurrent_reports, - same_kind_reports, - } - } - - /// Insert a new report to the index. - fn insert(&mut self, time_slot: &O::TimeSlot, report_id: ReportIdOf) { - // Insert the report id into the list while maintaining the ordering by the time - // slot. - let pos = match self - .same_kind_reports - .binary_search_by_key(&time_slot, |&(ref when, _)| when) - { - Ok(pos) => pos, - Err(pos) => pos, - }; - self.same_kind_reports - .insert(pos, (time_slot.clone(), report_id)); - - // Update the list of concurrent reports. - self.concurrent_reports.push(report_id); - } - - /// Dump the indexes to the storage. - fn save(self) { - ::insert(&O::ID, self.same_kind_reports.encode()); - >::insert( - &O::ID, - &self.opaque_time_slot, - &self.concurrent_reports, - ); - } -} diff --git a/srml/offences/src/mock.rs b/srml/offences/src/mock.rs deleted file mode 100644 index f9c79390819e0..0000000000000 --- a/srml/offences/src/mock.rs +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -#![cfg(test)] - -use std::cell::RefCell; -use crate::{Module, Trait}; -use codec::Encode; -use sr_primitives::Perbill; -use sr_staking_primitives::{ - SessionIndex, - offence::{self, Kind, OffenceDetails}, -}; -use sr_primitives::testing::Header; -use sr_primitives::traits::{IdentityLookup, BlakeTwo256}; -use substrate_primitives::H256; -use support::{impl_outer_origin, impl_outer_event, parameter_types, StorageMap, StorageDoubleMap}; -use {runtime_io, system}; - -impl_outer_origin!{ - pub enum Origin for Runtime {} -} - -pub struct OnOffenceHandler; - -thread_local! { - pub static ON_OFFENCE_PERBILL: RefCell> = RefCell::new(Default::default()); -} - -impl offence::OnOffenceHandler for OnOffenceHandler { - fn on_offence( - _offenders: &[OffenceDetails], - slash_fraction: &[Perbill], - ) { - ON_OFFENCE_PERBILL.with(|f| { - *f.borrow_mut() = slash_fraction.to_vec(); - }); - } -} - -pub fn with_on_offence_fractions) -> R>(f: F) -> R { - ON_OFFENCE_PERBILL.with(|fractions| { - f(&mut *fractions.borrow_mut()) - }) -} - -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Runtime; -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl system::Trait for Runtime { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = TestEvent; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} - -impl Trait for Runtime { - type Event = TestEvent; - type IdentificationTuple = u64; - type OnOffenceHandler = OnOffenceHandler; -} - -mod offences { - pub use crate::Event; -} - -impl_outer_event! { - pub enum TestEvent for Runtime { - offences, - } -} - -pub fn new_test_ext() -> runtime_io::TestExternalities { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - t.into() -} - -/// Offences module. -pub type Offences = Module; -pub type System = system::Module; - -pub const KIND: [u8; 16] = *b"test_report_1234"; - -/// Returns all offence details for the specific `kind` happened at the specific time slot. -pub fn offence_reports(kind: Kind, time_slot: u128) -> Vec> { - >::get(&kind, &time_slot.encode()) - .into_iter() - .map(|report_id| { - >::get(&report_id) - .expect("dangling report id is found in ConcurrentReportsIndex") - }) - .collect() -} - -#[derive(Clone)] -pub struct Offence { - pub validator_set_count: u32, - pub offenders: Vec, - pub time_slot: u128, -} - -impl offence::Offence for Offence { - const ID: offence::Kind = KIND; - type TimeSlot = u128; - - fn offenders(&self) -> Vec { - self.offenders.clone() - } - - fn validator_set_count(&self) -> u32 { - self.validator_set_count - } - - fn time_slot(&self) -> u128 { - self.time_slot - } - - fn session_index(&self) -> SessionIndex { - // session index is not used by the srml-offences directly, but rather it exists only for - // filtering historical reports. - unimplemented!() - } - - fn slash_fraction( - offenders_count: u32, - validator_set_count: u32, - ) -> Perbill { - Perbill::from_percent(5 + offenders_count * 100 / validator_set_count) - } -} diff --git a/srml/offences/src/tests.rs b/srml/offences/src/tests.rs deleted file mode 100644 index 28e655d16bfdd..0000000000000 --- a/srml/offences/src/tests.rs +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the offences module. - -#![cfg(test)] - -use super::*; -use crate::mock::{ - Offences, System, Offence, TestEvent, KIND, new_test_ext, with_on_offence_fractions, - offence_reports, -}; -use system::{EventRecord, Phase}; - -#[test] -fn should_report_an_authority_and_trigger_on_offence() { - new_test_ext().execute_with(|| { - // given - let time_slot = 42; - assert_eq!(offence_reports(KIND, time_slot), vec![]); - - let offence = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![5], - }; - - // when - Offences::report_offence(vec![], offence); - - // then - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); - }); - }); -} - -#[test] -fn should_calculate_the_fraction_correctly() { - new_test_ext().execute_with(|| { - // given - let time_slot = 42; - assert_eq!(offence_reports(KIND, time_slot), vec![]); - let offence1 = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![5], - }; - let offence2 = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![4], - }; - - // when - Offences::report_offence(vec![], offence1); - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); - }); - - Offences::report_offence(vec![], offence2); - - // then - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![Perbill::from_percent(15), Perbill::from_percent(45)]); - }); - }); -} - -#[test] -fn should_not_report_the_same_authority_twice_in_the_same_slot() { - new_test_ext().execute_with(|| { - // given - let time_slot = 42; - assert_eq!(offence_reports(KIND, time_slot), vec![]); - - let offence = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![5], - }; - Offences::report_offence(vec![], offence.clone()); - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); - f.clear(); - }); - - // when - // report for the second time - Offences::report_offence(vec![], offence); - - // then - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![]); - }); - }); -} - - -#[test] -fn should_report_in_different_time_slot() { - new_test_ext().execute_with(|| { - // given - let time_slot = 42; - assert_eq!(offence_reports(KIND, time_slot), vec![]); - - let mut offence = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![5], - }; - Offences::report_offence(vec![], offence.clone()); - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); - f.clear(); - }); - - // when - // reportfor the second time - offence.time_slot += 1; - Offences::report_offence(vec![], offence); - - // then - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); - }); - }); -} - -#[test] -fn should_deposit_event() { - new_test_ext().execute_with(|| { - // given - let time_slot = 42; - assert_eq!(offence_reports(KIND, time_slot), vec![]); - - let offence = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![5], - }; - - // when - Offences::report_offence(vec![], offence); - - // then - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: TestEvent::offences(crate::Event::Offence(KIND, time_slot.encode())), - topics: vec![], - }] - ); - }); -} - -#[test] -fn doesnt_deposit_event_for_dups() { - new_test_ext().execute_with(|| { - // given - let time_slot = 42; - assert_eq!(offence_reports(KIND, time_slot), vec![]); - - let offence = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![5], - }; - Offences::report_offence(vec![], offence.clone()); - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); - f.clear(); - }); - - // when - // report for the second time - Offences::report_offence(vec![], offence); - - // then - // there is only one event. - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: TestEvent::offences(crate::Event::Offence(KIND, time_slot.encode())), - topics: vec![], - }] - ); - }); -} - -#[test] -fn should_properly_count_offences() { - // We report two different authorities for the same issue. Ultimately, the 1st authority - // should have `count` equal 2 and the count of the 2nd one should be equal to 1. - new_test_ext().execute_with(|| { - // given - let time_slot = 42; - assert_eq!(offence_reports(KIND, time_slot), vec![]); - - let offence1 = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![5], - }; - let offence2 = Offence { - validator_set_count: 5, - time_slot, - offenders: vec![4], - }; - Offences::report_offence(vec![], offence1); - with_on_offence_fractions(|f| { - assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); - f.clear(); - }); - - // when - // report for the second time - Offences::report_offence(vec![], offence2); - - // then - // the 1st authority should have count 2 and the 2nd one should be reported only once. - assert_eq!( - offence_reports(KIND, time_slot), - vec![ - OffenceDetails { offender: 5, reporters: vec![] }, - OffenceDetails { offender: 4, reporters: vec![] }, - ] - ); - }); -} diff --git a/srml/randomness-collective-flip/Cargo.toml b/srml/randomness-collective-flip/Cargo.toml deleted file mode 100644 index 5be9aad50f0b3..0000000000000 --- a/srml/randomness-collective-flip/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "srml-randomness-collective-flip" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -safe-mix = { version = "1.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -runtime-io = { package = "sr-io", path = "../../core/sr-io" } - -[features] -default = ["std"] -std = [ - "safe-mix/std", - "system/std", - "codec/std", - "support/std", - "sr-primitives/std", - "rstd/std", -] diff --git a/srml/randomness-collective-flip/src/lib.rs b/srml/randomness-collective-flip/src/lib.rs deleted file mode 100644 index 3644b8898c2ab..0000000000000 --- a/srml/randomness-collective-flip/src/lib.rs +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Randomness Module -//! -//! The Randomness Collective Flip module provides a [`random`](./struct.Module.html#method.random) -//! function that generates low-influence random values based on the block hashes from the previous -//! `81` blocks. Low-influence randomness can be useful when defending against relatively weak -//! adversaries. -//! -//! ## Public Functions -//! -//! See the [`Module`](./struct.Module.html) struct for details of publicly available functions. -//! -//! ## Usage -//! -//! ### Prerequisites -//! -//! Import the Randomness Collective Flip module and derive your module's configuration trait from -//! the system trait. -//! -//! ### Example - Get random seed for the current block -//! -//! ``` -//! use support::{decl_module, dispatch::Result, traits::Randomness}; -//! -//! pub trait Trait: system::Trait {} -//! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! pub fn random_module_example(origin) -> Result { -//! let _random_seed = >::random_seed(); -//! Ok(()) -//! } -//! } -//! } -//! # fn main() { } -//! ``` - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::{prelude::*, convert::TryInto}; -use sr_primitives::traits::Hash; -use support::{decl_module, decl_storage, traits::Randomness}; -use safe_mix::TripletMix; -use codec::Encode; -use system::Trait; - -const RANDOM_MATERIAL_LEN: u32 = 81; - -fn block_number_to_index(block_number: T::BlockNumber) -> usize { - // on_initialize is called on the first block after genesis - let index = (block_number - 1.into()) % RANDOM_MATERIAL_LEN.into(); - index.try_into().ok().expect("Something % 81 is always smaller than usize; qed") -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn on_initialize(block_number: T::BlockNumber) { - let parent_hash = >::parent_hash(); - - >::mutate(|ref mut values| if values.len() < RANDOM_MATERIAL_LEN as usize { - values.push(parent_hash) - } else { - let index = block_number_to_index::(block_number); - values[index] = parent_hash; - }); - } - } -} - -decl_storage! { - trait Store for Module as RandomnessCollectiveFlip { - /// Series of block headers from the last 81 blocks that acts as random seed material. This - /// is arranged as a ring buffer with `block_number % 81` being the index into the `Vec` of - /// the oldest hash. - RandomMaterial get(fn random_material): Vec; - } -} - -impl Randomness for Module { - /// Get a low-influence "random" value. - /// - /// Being a deterministic block chain, real randomness is difficult to come by. This gives you - /// something that approximates it. `subject` is a context identifier and allows you to get a - /// different result to other callers of this function; use it like - /// `random(&b"my context"[..])`. This is initially implemented through a low-influence - /// "triplet mix" convolution of previous block hash values. In the future it will be generated - /// from a secure verifiable random function (VRF). - /// - /// ### Security Notes - /// - /// This randomness uses a low-influence function, drawing upon the block hashes from the - /// previous 81 blocks. Its result for any given subject will be known far in advance by anyone - /// observing the chain. Any block producer has significant influence over their block hashes - /// bounded only by their computational resources. Our low-influence function reduces the actual - /// block producer's influence over the randomness, but increases the influence of small - /// colluding groups of recent block producers. - /// - /// Some BABE blocks have VRF outputs where the block producer has exactly one bit of influence, - /// either they make the block or they do not make the block and thus someone else makes the - /// next block. Yet, this randomness is not fresh in all BABE blocks. - /// - /// If that is an insufficient security guarantee then two things can be used to improve this - /// randomness: - /// - /// - Name, in advance, the block number whose random value will be used; ensure your module - /// retains a buffer of previous random values for its subject and then index into these in - /// order to obviate the ability of your user to look up the parent hash and choose when to - /// transact based upon it. - /// - Require your user to first commit to an additional value by first posting its hash. - /// Require them to reveal the value to determine the final result, hashing it with the - /// output of this random function. This reduces the ability of a cabal of block producers - /// from conspiring against individuals. - /// - /// WARNING: Hashing the result of this function will remove any low-influence properties it has - /// and mean that all bits of the resulting value are entirely manipulatable by the author of - /// the parent block, who can determine the value of `parent_hash`. - fn random(subject: &[u8]) -> T::Hash { - let block_number = >::block_number(); - let index = block_number_to_index::(block_number); - - let hash_series = >::get(); - if !hash_series.is_empty() { - // Always the case after block 1 is initialised. - hash_series.iter() - .cycle() - .skip(index) - .take(RANDOM_MATERIAL_LEN as usize) - .enumerate() - .map(|(i, h)| (i as i8, subject, h).using_encoded(T::Hashing::hash)) - .triplet_mix() - } else { - T::Hash::default() - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use primitives::H256; - use sr_primitives::{ - Perbill, traits::{BlakeTwo256, OnInitialize, Header as _, IdentityLookup}, testing::Header, - }; - use support::{impl_outer_origin, parameter_types, traits::Randomness}; - - #[derive(Clone, PartialEq, Eq)] - pub struct Test; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - - type System = system::Module; - type CollectiveFlip = Module; - - fn new_test_ext() -> runtime_io::TestExternalities { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - t.into() - } - - #[test] - fn test_block_number_to_index() { - for i in 1 .. 1000 { - assert_eq!((i - 1) as usize % 81, block_number_to_index::(i)); - } - } - - fn setup_blocks(blocks: u64) { - let mut parent_hash = System::parent_hash(); - - for i in 1 .. (blocks + 1) { - System::initialize(&i, &parent_hash, &Default::default(), &Default::default()); - CollectiveFlip::on_initialize(i); - - let header = System::finalize(); - parent_hash = header.hash(); - System::set_block_number(*header.number()); - } - } - - #[test] - fn test_random_material_parital() { - new_test_ext().execute_with(|| { - let genesis_hash = System::parent_hash(); - - setup_blocks(38); - - let random_material = CollectiveFlip::random_material(); - - assert_eq!(random_material.len(), 38); - assert_eq!(random_material[0], genesis_hash); - }); - } - - #[test] - fn test_random_material_filled() { - new_test_ext().execute_with(|| { - let genesis_hash = System::parent_hash(); - - setup_blocks(81); - - let random_material = CollectiveFlip::random_material(); - - assert_eq!(random_material.len(), 81); - assert_ne!(random_material[0], random_material[1]); - assert_eq!(random_material[0], genesis_hash); - }); - } - - #[test] - fn test_random_material_filled_twice() { - new_test_ext().execute_with(|| { - let genesis_hash = System::parent_hash(); - - setup_blocks(162); - - let random_material = CollectiveFlip::random_material(); - - assert_eq!(random_material.len(), 81); - assert_ne!(random_material[0], random_material[1]); - assert_ne!(random_material[0], genesis_hash); - }); - } - - #[test] - fn test_random() { - new_test_ext().execute_with(|| { - setup_blocks(162); - - assert_eq!(System::block_number(), 162); - assert_eq!(CollectiveFlip::random_seed(), CollectiveFlip::random_seed()); - assert_ne!(CollectiveFlip::random(b"random_1"), CollectiveFlip::random(b"random_2")); - - let random = CollectiveFlip::random_seed(); - - assert_ne!(random, H256::zero()); - assert!(!CollectiveFlip::random_material().contains(&random)); - }); - } -} diff --git a/srml/scored-pool/Cargo.toml b/srml/scored-pool/Cargo.toml deleted file mode 100644 index e65f71a10d13e..0000000000000 --- a/srml/scored-pool/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "srml-scored-pool" -version = "1.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", optional = true } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -balances = { package = "srml-balances", path = "../balances" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } - -[features] -default = ["std"] -std = [ - "codec/std", - "serde", - "runtime-io/std", - "sr-primitives/std", - "rstd/std", - "support/std", - "system/std", -] diff --git a/srml/scored-pool/src/lib.rs b/srml/scored-pool/src/lib.rs deleted file mode 100644 index 5fde1e9c450cf..0000000000000 --- a/srml/scored-pool/src/lib.rs +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Scored Pool Module -//! -//! The module maintains a scored membership pool. Each entity in the -//! pool can be attributed a `Score`. From this pool a set `Members` -//! is constructed. This set contains the `MemberCount` highest -//! scoring entities. Unscored entities are never part of `Members`. -//! -//! If an entity wants to be part of the pool a deposit is required. -//! The deposit is returned when the entity withdraws or when it -//! is removed by an entity with the appropriate authority. -//! -//! Every `Period` blocks the set of `Members` is refreshed from the -//! highest scoring members in the pool and, no matter if changes -//! occurred, `T::MembershipChanged::set_members_sorted` is invoked. -//! On first load `T::MembershipInitialized::initialize_members` is -//! invoked with the initial `Members` set. -//! -//! It is possible to withdraw candidacy/resign your membership at any -//! time. If an entity is currently a member, this results in removal -//! from the `Pool` and `Members`; the entity is immediately replaced -//! by the next highest scoring candidate in the pool, if available. -//! -//! - [`scored_pool::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! - [`Module`](./struct.Module.html) -//! -//! ## Interface -//! -//! ### Public Functions -//! -//! - `submit_candidacy` - Submit candidacy to become a member. Requires a deposit. -//! - `withdraw_candidacy` - Withdraw candidacy. Deposit is returned. -//! - `score` - Attribute a quantitative score to an entity. -//! - `kick` - Remove an entity from the pool and members. Deposit is returned. -//! - `change_member_count` - Changes the amount of candidates taken into `Members`. -//! -//! ## Usage -//! -//! ``` -//! use support::{decl_module, dispatch::Result}; -//! use system::ensure_signed; -//! use srml_scored_pool::{self as scored_pool}; -//! -//! pub trait Trait: scored_pool::Trait {} -//! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! pub fn candidate(origin) -> Result { -//! let who = ensure_signed(origin)?; -//! -//! let _ = >::submit_candidacy( -//! T::Origin::from(Some(who.clone()).into()) -//! ); -//! Ok(()) -//! } -//! } -//! } -//! -//! # fn main() { } -//! ``` -//! -//! ## Dependencies -//! -//! This module depends on the [System module](../srml_system/index.html). - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; - -use codec::FullCodec; -use rstd::{ - fmt::Debug, - prelude::*, -}; -use support::{ - decl_module, decl_storage, decl_event, ensure, - traits::{ChangeMembers, InitializeMembers, Currency, Get, ReservableCurrency}, -}; -use system::{self, ensure_root, ensure_signed}; -use sr_primitives::{ - traits::{EnsureOrigin, SimpleArithmetic, MaybeSerializeDeserialize, Zero, StaticLookup}, -}; - -type BalanceOf = <>::Currency as Currency<::AccountId>>::Balance; -type PoolT = Vec<(::AccountId, Option<>::Score>)>; - -/// The enum is supplied when refreshing the members set. -/// Depending on the enum variant the corresponding associated -/// type function will be invoked. -enum ChangeReceiver { - /// Should call `T::MembershipInitialized`. - MembershipInitialized, - /// Should call `T::MembershipChanged`. - MembershipChanged, -} - -pub trait Trait: system::Trait { - /// The currency used for deposits. - type Currency: Currency + ReservableCurrency; - - /// The score attributed to a member or candidate. - type Score: - SimpleArithmetic + Clone + Copy + Default + FullCodec + MaybeSerializeDeserialize + Debug; - - /// The overarching event type. - type Event: From> + Into<::Event>; - - // The deposit which is reserved from candidates if they want to - // start a candidacy. The deposit gets returned when the candidacy is - // withdrawn or when the candidate is kicked. - type CandidateDeposit: Get>; - - /// Every `Period` blocks the `Members` are filled with the highest scoring - /// members in the `Pool`. - type Period: Get; - - /// The receiver of the signal for when the membership has been initialized. - /// This happens pre-genesis and will usually be the same as `MembershipChanged`. - /// If you need to do something different on initialization, then you can change - /// this accordingly. - type MembershipInitialized: InitializeMembers; - - /// The receiver of the signal for when the members have changed. - type MembershipChanged: ChangeMembers; - - /// Allows a configurable origin type to set a score to a candidate in the pool. - type ScoreOrigin: EnsureOrigin; - - /// Required origin for removing a member (though can always be Root). - /// Configurable origin which enables removing an entity. If the entity - /// is part of the `Members` it is immediately replaced by the next - /// highest scoring candidate, if available. - type KickOrigin: EnsureOrigin; -} - -decl_storage! { - trait Store for Module, I: Instance=DefaultInstance> as ScoredPool { - /// The current pool of candidates, stored as an ordered Vec - /// (ordered descending by score, `None` last, highest first). - Pool get(fn pool) config(): PoolT; - - /// A Map of the candidates. The information in this Map is redundant - /// to the information in the `Pool`. But the Map enables us to easily - /// check if a candidate is already in the pool, without having to - /// iterate over the entire pool (the `Pool` is not sorted by - /// `T::AccountId`, but by `T::Score` instead). - CandidateExists get(fn candidate_exists): map T::AccountId => bool; - - /// The current membership, stored as an ordered Vec. - Members get(fn members): Vec; - - /// Size of the `Members` set. - MemberCount get(fn member_count) config(): u32; - } - add_extra_genesis { - config(members): Vec; - config(phantom): rstd::marker::PhantomData; - build(|config| { - let mut pool = config.pool.clone(); - - // reserve balance for each candidate in the pool. - // panicking here is ok, since this just happens one time, pre-genesis. - pool - .iter() - .for_each(|(who, _)| { - T::Currency::reserve(&who, T::CandidateDeposit::get()) - .expect("balance too low to create candidacy"); - >::insert(who, true); - }); - - /// Sorts the `Pool` by score in a descending order. Entities which - /// have a score of `None` are sorted to the beginning of the vec. - pool.sort_by_key(|(_, maybe_score)| - Reverse(maybe_score.unwrap_or_default()) - ); - - >::put(&pool); - >::refresh_members(pool, ChangeReceiver::MembershipInitialized); - }) - } -} - -decl_event!( - pub enum Event where - ::AccountId, - { - /// The given member was removed. See the transaction for who. - MemberRemoved, - /// An entity has issued a candidacy. See the transaction for who. - CandidateAdded, - /// An entity withdrew candidacy. See the transaction for who. - CandidateWithdrew, - /// The candidacy was forcefully removed for an entity. - /// See the transaction for who. - CandidateKicked, - /// A score was attributed to the candidate. - /// See the transaction for who. - CandidateScored, - /// Phantom member, never used. - Dummy(rstd::marker::PhantomData<(AccountId, I)>), - } -); - -decl_module! { - pub struct Module, I: Instance=DefaultInstance> - for enum Call - where origin: T::Origin - { - fn deposit_event() = default; - - /// Every `Period` blocks the `Members` set is refreshed from the - /// highest scoring members in the pool. - fn on_initialize(n: T::BlockNumber) { - if n % T::Period::get() == Zero::zero() { - let pool = >::get(); - >::refresh_members(pool, ChangeReceiver::MembershipChanged); - } - } - - /// Add `origin` to the pool of candidates. - /// - /// This results in `CandidateDeposit` being reserved from - /// the `origin` account. The deposit is returned once - /// candidacy is withdrawn by the candidate or the entity - /// is kicked by `KickOrigin`. - /// - /// The dispatch origin of this function must be signed. - /// - /// The `index` parameter of this function must be set to - /// the index of the transactor in the `Pool`. - pub fn submit_candidacy(origin) { - let who = ensure_signed(origin)?; - ensure!(!>::exists(&who), "already a member"); - - let deposit = T::CandidateDeposit::get(); - T::Currency::reserve(&who, deposit) - .map_err(|_| "balance too low to submit candidacy")?; - - // can be inserted as last element in pool, since entities with - // `None` are always sorted to the end. - if let Err(e) = >::append(&[(who.clone(), None)]) { - T::Currency::unreserve(&who, deposit); - return Err(e); - } - - >::insert(&who, true); - - Self::deposit_event(RawEvent::CandidateAdded); - } - - /// An entity withdraws candidacy and gets its deposit back. - /// - /// If the entity is part of the `Members`, then the highest member - /// of the `Pool` that is not currently in `Members` is immediately - /// placed in the set instead. - /// - /// The dispatch origin of this function must be signed. - /// - /// The `index` parameter of this function must be set to - /// the index of the transactor in the `Pool`. - pub fn withdraw_candidacy( - origin, - index: u32 - ) { - let who = ensure_signed(origin)?; - - let pool = >::get(); - Self::ensure_index(&pool, &who, index)?; - - Self::remove_member(pool, who, index)?; - Self::deposit_event(RawEvent::CandidateWithdrew); - } - - /// Kick a member `who` from the set. - /// - /// May only be called from `KickOrigin` or root. - /// - /// The `index` parameter of this function must be set to - /// the index of `dest` in the `Pool`. - pub fn kick( - origin, - dest: ::Source, - index: u32 - ) { - T::KickOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - let who = T::Lookup::lookup(dest)?; - - let pool = >::get(); - Self::ensure_index(&pool, &who, index)?; - - Self::remove_member(pool, who, index)?; - Self::deposit_event(RawEvent::CandidateKicked); - } - - /// Score a member `who` with `score`. - /// - /// May only be called from `ScoreOrigin` or root. - /// - /// The `index` parameter of this function must be set to - /// the index of the `dest` in the `Pool`. - pub fn score( - origin, - dest: ::Source, - index: u32, - score: T::Score - ) { - T::ScoreOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - let who = T::Lookup::lookup(dest)?; - - let mut pool = >::get(); - Self::ensure_index(&pool, &who, index)?; - - pool.remove(index as usize); - - // we binary search the pool (which is sorted descending by score). - // if there is already an element with `score`, we insert - // right before that. if not, the search returns a location - // where we can insert while maintaining order. - let item = (who.clone(), Some(score.clone())); - let location = pool - .binary_search_by_key( - &Reverse(score), - |(_, maybe_score)| Reverse(maybe_score.unwrap_or_default()) - ) - .unwrap_or_else(|l| l); - pool.insert(location, item); - - >::put(&pool); - Self::deposit_event(RawEvent::CandidateScored); - } - - /// Dispatchable call to change `MemberCount`. - /// - /// This will only have an effect the next time a refresh happens - /// (this happens each `Period`). - /// - /// May only be called from root. - pub fn change_member_count(origin, count: u32) { - ensure_root(origin)?; - >::put(&count); - } - } -} - -impl, I: Instance> Module { - - /// Fetches the `MemberCount` highest scoring members from - /// `Pool` and puts them into `Members`. - /// - /// The `notify` parameter is used to deduct which associated - /// type function to invoke at the end of the method. - fn refresh_members( - pool: PoolT, - notify: ChangeReceiver - ) { - let count = >::get(); - - let mut new_members: Vec = pool - .into_iter() - .filter(|(_, score)| score.is_some()) - .take(count as usize) - .map(|(account_id, _)| account_id) - .collect(); - new_members.sort(); - - let old_members = >::get(); - >::put(&new_members); - - match notify { - ChangeReceiver::MembershipInitialized => - T::MembershipInitialized::initialize_members(&new_members), - ChangeReceiver::MembershipChanged => - T::MembershipChanged::set_members_sorted( - &new_members[..], - &old_members[..], - ), - } - } - - /// Removes an entity `remove` at `index` from the `Pool`. - /// - /// If the entity is a member it is also removed from `Members` and - /// the deposit is returned. - fn remove_member( - mut pool: PoolT, - remove: T::AccountId, - index: u32 - ) -> Result<(), &'static str> { - // all callers of this function in this module also check - // the index for validity before calling this function. - // nevertheless we check again here, to assert that there was - // no mistake when invoking this sensible function. - Self::ensure_index(&pool, &remove, index)?; - - pool.remove(index as usize); - >::put(&pool); - - // remove from set, if it was in there - let members = >::get(); - if members.binary_search(&remove).is_ok() { - Self::refresh_members(pool, ChangeReceiver::MembershipChanged); - } - - >::remove(&remove); - - T::Currency::unreserve(&remove, T::CandidateDeposit::get()); - - Self::deposit_event(RawEvent::MemberRemoved); - Ok(()) - } - - /// Checks if `index` is a valid number and if the element found - /// at `index` in `Pool` is equal to `who`. - fn ensure_index( - pool: &PoolT, - who: &T::AccountId, - index: u32 - ) -> Result<(), &'static str> { - ensure!(index < pool.len() as u32, "index out of bounds"); - - let (index_who, _index_score) = &pool[index as usize]; - ensure!(index_who == who, "index does not match requested account"); - - Ok(()) - } -} - diff --git a/srml/scored-pool/src/mock.rs b/srml/scored-pool/src/mock.rs deleted file mode 100644 index 394f486a8bec3..0000000000000 --- a/srml/scored-pool/src/mock.rs +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -use super::*; - -use std::cell::RefCell; -use support::{impl_outer_origin, parameter_types}; -use primitives::H256; -// The testing primitives are very useful for avoiding having to work with signatures -// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. -use sr_primitives::{ - Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header, -}; -use system::EnsureSignedBy; - -impl_outer_origin! { - pub enum Origin for Test {} -} - -// For testing the module, we construct most of a mock runtime. This means -// first constructing a configuration type (`Test`) which `impl`s each of the -// configuration traits of modules we want to use. -#[derive(Clone, Eq, PartialEq)] -pub struct Test; -parameter_types! { - pub const CandidateDeposit: u64 = 25; - pub const Period: u64 = 4; - - pub const KickOrigin: u64 = 2; - pub const ScoreOrigin: u64 = 3; - - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; -} - -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = (); - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} - -impl balances::Trait for Test { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} - -thread_local! { - pub static MEMBERS: RefCell> = RefCell::new(vec![]); -} - -pub struct TestChangeMembers; -impl ChangeMembers for TestChangeMembers { - fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { - let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); - old_plus_incoming.extend_from_slice(incoming); - old_plus_incoming.sort(); - - let mut new_plus_outgoing = new.to_vec(); - new_plus_outgoing.extend_from_slice(outgoing); - new_plus_outgoing.sort(); - - assert_eq!(old_plus_incoming, new_plus_outgoing); - - MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); - } -} - -impl InitializeMembers for TestChangeMembers { - fn initialize_members(new_members: &[u64]) { - MEMBERS.with(|m| *m.borrow_mut() = new_members.to_vec()); - } -} - -impl Trait for Test { - type Event = (); - type KickOrigin = EnsureSignedBy; - type MembershipInitialized = TestChangeMembers; - type MembershipChanged = TestChangeMembers; - type Currency = balances::Module; - type CandidateDeposit = CandidateDeposit; - type Period = Period; - type Score = u64; - type ScoreOrigin = EnsureSignedBy; -} - -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. -pub fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. - balances::GenesisConfig:: { - balances: vec![ - (5, 500_000), - (10, 500_000), - (15, 500_000), - (20, 500_000), - (31, 500_000), - (40, 500_000), - (99, 1), - ], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - GenesisConfig::{ - pool: vec![ - (5, None), - (10, Some(1)), - (20, Some(2)), - (31, Some(2)), - (40, Some(3)), - ], - member_count: 2, - .. Default::default() - }.assimilate_storage(&mut t).unwrap(); - t.into() -} - -/// Fetch an entity from the pool, if existent. -pub fn fetch_from_pool(who: u64) -> Option<(u64, Option)> { - >::pool() - .into_iter() - .find(|item| item.0 == who) -} - -/// Find an entity in the pool. -/// Returns its position in the `Pool` vec, if existent. -pub fn find_in_pool(who: u64) -> Option { - >::pool() - .into_iter() - .position(|item| item.0 == who) -} diff --git a/srml/scored-pool/src/tests.rs b/srml/scored-pool/src/tests.rs deleted file mode 100644 index 2f47b5da6fe26..0000000000000 --- a/srml/scored-pool/src/tests.rs +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the module. - -use super::*; -use mock::*; - -use support::{assert_ok, assert_noop}; -use sr_primitives::traits::OnInitialize; - -type ScoredPool = Module; -type System = system::Module; -type Balances = balances::Module; - -const OOB_ERR: &str = "index out of bounds"; -const INDEX_ERR: &str = "index does not match requested account"; - -#[test] -fn query_membership_works() { - new_test_ext().execute_with(|| { - assert_eq!(ScoredPool::members(), vec![20, 40]); - assert_eq!(Balances::reserved_balance(&31), CandidateDeposit::get()); - assert_eq!(Balances::reserved_balance(&40), CandidateDeposit::get()); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), vec![20, 40]); - }); -} - -#[test] -fn submit_candidacy_must_not_work() { - new_test_ext().execute_with(|| { - assert_noop!( - ScoredPool::submit_candidacy(Origin::signed(99)), - "balance too low to submit candidacy" - ); - assert_noop!( - ScoredPool::submit_candidacy(Origin::signed(40)), - "already a member" - ); - }); -} - -#[test] -fn submit_candidacy_works() { - new_test_ext().execute_with(|| { - // given - let who = 15; - - // when - assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); - assert_eq!(fetch_from_pool(15), Some((who, None))); - - // then - assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); - }); -} - -#[test] -fn scoring_works() { - new_test_ext().execute_with(|| { - // given - let who = 15; - let score = 99; - assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); - - // when - let index = find_in_pool(who).expect("entity must be in pool") as u32; - assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, score)); - - // then - assert_eq!(fetch_from_pool(who), Some((who, Some(score)))); - assert_eq!(find_in_pool(who), Some(0)); // must be first element, since highest scored - }); -} - -#[test] -fn scoring_same_element_with_same_score_works() { - new_test_ext().execute_with(|| { - // given - let who = 31; - let index = find_in_pool(who).expect("entity must be in pool") as u32; - let score = 2; - - // when - assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, score)); - - // then - assert_eq!(fetch_from_pool(who), Some((who, Some(score)))); - - // must have been inserted right before the `20` element which is - // of the same score as `31`. so sort order is maintained. - assert_eq!(find_in_pool(who), Some(1)); - }); -} - -#[test] -fn kicking_works_only_for_authorized() { - new_test_ext().execute_with(|| { - let who = 40; - let index = find_in_pool(who).expect("entity must be in pool") as u32; - assert_noop!(ScoredPool::kick(Origin::signed(99), who, index), "bad origin"); - }); -} - -#[test] -fn kicking_works() { - new_test_ext().execute_with(|| { - // given - let who = 40; - assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); - assert_eq!(find_in_pool(who), Some(0)); - - // when - let index = find_in_pool(who).expect("entity must be in pool") as u32; - assert_ok!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index)); - - // then - assert_eq!(find_in_pool(who), None); - assert_eq!(ScoredPool::members(), vec![20, 31]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); - assert_eq!(Balances::reserved_balance(&who), 0); // deposit must have been returned - }); -} - -#[test] -fn unscored_entities_must_not_be_used_for_filling_members() { - new_test_ext().execute_with(|| { - // given - // we submit a candidacy, score will be `None` - assert_ok!(ScoredPool::submit_candidacy(Origin::signed(15))); - - // when - // we remove every scored member - ScoredPool::pool() - .into_iter() - .for_each(|(who, score)| { - if let Some(_) = score { - let index = find_in_pool(who).expect("entity must be in pool") as u32; - assert_ok!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index)); - } - }); - - // then - // the `None` candidates should not have been filled in - assert_eq!(ScoredPool::members(), vec![]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); - }); -} - -#[test] -fn refreshing_works() { - new_test_ext().execute_with(|| { - // given - let who = 15; - assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); - let index = find_in_pool(who).expect("entity must be in pool") as u32; - assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, 99)); - - // when - ScoredPool::refresh_members(ScoredPool::pool(), ChangeReceiver::MembershipChanged); - - // then - assert_eq!(ScoredPool::members(), vec![15, 40]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); - }); -} - -#[test] -fn refreshing_happens_every_period() { - new_test_ext().execute_with(|| { - // given - System::set_block_number(1); - assert_ok!(ScoredPool::submit_candidacy(Origin::signed(15))); - let index = find_in_pool(15).expect("entity must be in pool") as u32; - assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), 15, index, 99)); - assert_eq!(ScoredPool::members(), vec![20, 40]); - - // when - System::set_block_number(4); - ScoredPool::on_initialize(4); - - // then - assert_eq!(ScoredPool::members(), vec![15, 40]); - assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); - }); -} - -#[test] -fn withdraw_candidacy_must_only_work_for_members() { - new_test_ext().execute_with(|| { - let who = 77; - let index = 0; - assert_noop!( ScoredPool::withdraw_candidacy(Origin::signed(who), index), INDEX_ERR); - }); -} - -#[test] -fn oob_index_should_abort() { - new_test_ext().execute_with(|| { - let who = 40; - let oob_index = ScoredPool::pool().len() as u32; - assert_noop!(ScoredPool::withdraw_candidacy(Origin::signed(who), oob_index), OOB_ERR); - assert_noop!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, oob_index, 99), OOB_ERR); - assert_noop!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, oob_index), OOB_ERR); - }); -} - -#[test] -fn index_mismatches_should_abort() { - new_test_ext().execute_with(|| { - let who = 40; - let index = 3; - assert_noop!(ScoredPool::withdraw_candidacy(Origin::signed(who), index), INDEX_ERR); - assert_noop!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, 99), INDEX_ERR); - assert_noop!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index), INDEX_ERR); - }); -} - -#[test] -fn withdraw_unscored_candidacy_must_work() { - new_test_ext().execute_with(|| { - // given - let who = 5; - - // when - let index = find_in_pool(who).expect("entity must be in pool") as u32; - assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); - - // then - assert_eq!(fetch_from_pool(5), None); - }); -} - -#[test] -fn withdraw_scored_candidacy_must_work() { - new_test_ext().execute_with(|| { - // given - let who = 40; - assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); - - // when - let index = find_in_pool(who).expect("entity must be in pool") as u32; - assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); - - // then - assert_eq!(fetch_from_pool(who), None); - assert_eq!(ScoredPool::members(), vec![20, 31]); - assert_eq!(Balances::reserved_balance(&who), 0); - }); -} - -#[test] -fn candidacy_resubmitting_works() { - new_test_ext().execute_with(|| { - // given - let who = 15; - - // when - assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); - assert_eq!(ScoredPool::candidate_exists(who), true); - let index = find_in_pool(who).expect("entity must be in pool") as u32; - assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); - assert_eq!(ScoredPool::candidate_exists(who), false); - assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); - - // then - assert_eq!(ScoredPool::candidate_exists(who), true); - }); -} diff --git a/srml/session/Cargo.toml b/srml/session/Cargo.toml deleted file mode 100644 index b114755ad91c2..0000000000000 --- a/srml/session/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "srml-session" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } -substrate-trie = { path = "../../core/trie", default-features = false, optional = true } -runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } -impl-trait-for-tuples = "0.1.2" - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto" } -lazy_static = "1.4.0" - -[features] -default = ["std", "historical"] -historical = ["substrate-trie"] -std = [ - "serde", - "safe-mix/std", - "codec/std", - "rstd/std", - "support/std", - "sr-primitives/std", - "sr-staking-primitives/std", - "timestamp/std", - "substrate-trie/std", - "runtime-io/std", -] diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs deleted file mode 100644 index 76cc6d0663a49..0000000000000 --- a/srml/session/src/lib.rs +++ /dev/null @@ -1,979 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Session Module -//! -//! The Session module allows validators to manage their session keys, provides a function for changing -//! the session length, and handles session rotation. -//! -//! - [`session::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! - [`Module`](./struct.Module.html) -//! -//! ## Overview -//! -//! ### Terminology -//! -//! -//! - **Session:** A session is a period of time that has a constant set of validators. Validators can only join -//! or exit the validator set at a session change. It is measured in block numbers. The block where a session is -//! ended is determined by the `ShouldSessionEnd` trait. When the session is ending, a new validator set -//! can be chosen by `OnSessionEnding` implementations. -//! - **Session key:** A session key is actually several keys kept together that provide the various signing -//! functions required by network authorities/validators in pursuit of their duties. -//! - **Validator ID:** Every account has an associated validator ID. For some simple staking systems, this -//! may just be the same as the account ID. For staking systems using a stash/controller model, -//! the validator ID would be the stash account ID of the controller. -//! - **Session key configuration process:** A session key is set using `set_key` for use in the -//! next session. It is stored in `NextKeyFor`, a mapping between the caller's `ValidatorId` and the session -//! keys provided. `set_key` allows users to set their session key prior to being selected as validator. -//! It is a public call since it uses `ensure_signed`, which checks that the origin is a signed account. -//! As such, the account ID of the origin stored in in `NextKeyFor` may not necessarily be associated with -//! a block author or a validator. The session keys of accounts are removed once their account balance is zero. -//! - **Validator set session key configuration process:** Each session we iterate through the current -//! set of validator account IDs to check if a session key was created for it in the previous session -//! using `set_key`. If it was then we call `set_authority` from the [Consensus module](../srml_consensus/index.html) -//! and pass it a set of session keys (each associated with an account ID) as the session keys for the new -//! validator set. Lastly, if the session key of the current authority does not match any session keys stored under -//! its validator index in the `AuthorityStorageVec` mapping, then we update the mapping with its session -//! key and update the saved list of original authorities if necessary -//! (see https://github.com/paritytech/substrate/issues/1290). Note: Authorities are stored in the Consensus module. -//! They are represented by a validator account ID index from the Session module and allocated with a session -//! key for the length of the session. -//! - **Session length change process:** At the start of the next session we allocate a session index and record the -//! timestamp when the session started. If a `NextSessionLength` was recorded in the previous session, we record -//! it as the new session length. Additionally, if the new session length differs from the length of the -//! next session then we record a `LastLengthChange`. -//! - **Session rotation configuration:** Configure as either a 'normal' (rewardable session where rewards are -//! applied) or 'exceptional' (slashable) session rotation. -//! - **Session rotation process:** The session is changed at the end of the final block of the current session -//! using the `on_finalize` method. It may be called by either an origin or internally from another runtime -//! module at the end of each block. -//! -//! ### Goals -//! -//! The Session module in Substrate is designed to make the following possible: -//! -//! - Set session keys of the validator set for the next session. -//! - Set the length of a session. -//! - Configure and switch between either normal or exceptional session rotations. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! - `set_key` - Set a validator's session key for the next session. -//! - `set_length` - Set a new session length to be applied upon the next session change. -//! - `force_new_session` - Force a new session that should be considered either a normal (rewardable) -//! or exceptional rotation. -//! - `on_finalize` - Called when a block is finalized. Will rotate session if it is the last -//! block of the current session. -//! -//! ### Public Functions -//! -//! - `validator_count` - Get the current number of validators. -//! - `last_length_change` - Get the block number when the session length last changed. -//! - `apply_force_new_session` - Force a new session. Can be called by other runtime modules. -//! - `set_validators` - Set the current set of validators. Can only be called by the Staking module. -//! - `check_rotate_session` - Rotate the session and apply rewards if necessary. Called after the Staking -//! module updates the authorities to the new validator set. -//! - `rotate_session` - Change to the next session. Register the new authority set. Update session keys. -//! Enact session length change if applicable. -//! - `ideal_session_duration` - Get the time of an ideal session. -//! - `blocks_remaining` - Get the number of blocks remaining in the current session, -//! excluding the current block. -//! -//! ## Usage -//! -//! ### Example from the SRML -//! -//! The [Staking module](../srml_staking/index.html) uses the Session module to get the validator set. -//! -//! ``` -//! use srml_session as session; -//! # fn not_executed() { -//! -//! let validators = >::validators(); -//! # } -//! # fn main(){} -//! ``` -//! -//! ## Related Modules -//! -//! - [Consensus](../srml_consensus/index.html) -//! - [Staking](../srml_staking/index.html) -//! - [Timestamp](../srml_timestamp/index.html) - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::{prelude::*, marker::PhantomData, ops::{Sub, Rem}}; -use codec::Decode; -use sr_primitives::{KeyTypeId, Perbill, RuntimeAppPublic}; -use sr_primitives::weights::SimpleDispatchInfo; -use sr_primitives::traits::{Convert, Zero, Member, OpaqueKeys}; -use sr_staking_primitives::SessionIndex; -use support::{ - dispatch::Result, ConsensusEngineId, decl_module, decl_event, - decl_storage, -}; -use support::{ensure, traits::{OnFreeBalanceZero, Get, FindAuthor}, Parameter}; -use system::{self, ensure_signed}; - -#[cfg(test)] -mod mock; - -#[cfg(feature = "historical")] -pub mod historical; - -/// Decides whether the session should be ended. -pub trait ShouldEndSession { - /// Return `true` if the session should be ended. - fn should_end_session(now: BlockNumber) -> bool; -} - -/// Ends the session after a fixed period of blocks. -/// -/// The first session will have length of `Offset`, and -/// the following sessions will have length of `Period`. -/// This may prove nonsensical if `Offset` >= `Period`. -pub struct PeriodicSessions< - Period, - Offset, ->(PhantomData<(Period, Offset)>); - -impl< - BlockNumber: Rem + Sub + Zero + PartialOrd, - Period: Get, - Offset: Get, -> ShouldEndSession for PeriodicSessions { - fn should_end_session(now: BlockNumber) -> bool { - let offset = Offset::get(); - now >= offset && ((now - offset) % Period::get()).is_zero() - } -} - -/// An event handler for when the session is ending. -/// TODO [slashing] consider renaming to OnSessionStarting -pub trait OnSessionEnding { - /// Handle the fact that the session is ending, and optionally provide the new validator set. - /// - /// Even if the validator-set is the same as before, if any underlying economic - /// conditions have changed (i.e. stake-weights), the new validator set must be returned. - /// This is necessary for consensus engines making use of the session module to - /// issue a validator-set change so misbehavior can be provably associated with the new - /// economic conditions as opposed to the old. - /// - /// `ending_index` is the index of the currently ending session. - /// The returned validator set, if any, will not be applied until `will_apply_at`. - /// `will_apply_at` is guaranteed to be at least `ending_index + 1`, since session indices don't - /// repeat, but it could be some time after in case we are staging authority set changes. - fn on_session_ending( - ending_index: SessionIndex, - will_apply_at: SessionIndex - ) -> Option>; -} - -impl OnSessionEnding for () { - fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { None } -} - -/// Handler for session lifecycle events. -pub trait SessionHandler { - /// The given validator set will be used for the genesis session. - /// It is guaranteed that the given validator set will also be used - /// for the second session, therefore the first call to `on_new_session` - /// should provide the same validator set. - fn on_genesis_session(validators: &[(ValidatorId, Ks)]); - - /// Session set has changed; act appropriately. Note that this can be called - /// before initialization of your module. - /// - /// `changed` is true whenever any of the session keys or underlying economic - /// identities or weightings behind those keys has changed. - fn on_new_session( - changed: bool, - validators: &[(ValidatorId, Ks)], - queued_validators: &[(ValidatorId, Ks)], - ); - - /// A notification for end of the session. - /// - /// Note it is triggered before any `OnSessionEnding` handlers, - /// so we can still affect the validator set. - fn on_before_session_ending() {} - - /// A validator got disabled. Act accordingly until a new session begins. - fn on_disabled(validator_index: usize); -} - -/// A session handler for specific key type. -pub trait OneSessionHandler { - /// The key type expected. - type Key: Decode + Default + RuntimeAppPublic; - - fn on_genesis_session<'a, I: 'a>(validators: I) - where I: Iterator, ValidatorId: 'a; - - /// Session set has changed; act appropriately. Note that this can be called - /// before initialization of your module. - /// - /// `changed` is true when at least one of the session keys - /// or the underlying economic identities/distribution behind one the - /// session keys has changed, false otherwise. - /// - /// The `validators` are the validators of the incoming session, and `queued_validators` - /// will follow. - fn on_new_session<'a, I: 'a>( - changed: bool, - validators: I, - queued_validators: I, - ) where I: Iterator, ValidatorId: 'a; - - - /// A notification for end of the session. - /// - /// Note it is triggered before any `OnSessionEnding` handlers, - /// so we can still affect the validator set. - fn on_before_session_ending() {} - - /// A validator got disabled. Act accordingly until a new session begins. - fn on_disabled(_validator_index: usize); -} - -#[impl_trait_for_tuples::impl_for_tuples(30)] -#[tuple_types_no_default_trait_bound] -impl SessionHandler for Tuple { - for_tuples!( where #( Tuple: OneSessionHandler )* ); - - fn on_genesis_session(validators: &[(AId, Ks)]) { - for_tuples!( - #( - let our_keys: Box> = Box::new(validators.iter() - .map(|k| (&k.0, k.1.get::(::ID) - .unwrap_or_default()))); - - Tuple::on_genesis_session(our_keys); - )* - ) - } - - fn on_new_session( - changed: bool, - validators: &[(AId, Ks)], - queued_validators: &[(AId, Ks)], - ) { - for_tuples!( - #( - let our_keys: Box> = Box::new(validators.iter() - .map(|k| (&k.0, k.1.get::(::ID) - .unwrap_or_default()))); - let queued_keys: Box> = Box::new(queued_validators.iter() - .map(|k| (&k.0, k.1.get::(::ID) - .unwrap_or_default()))); - Tuple::on_new_session(changed, our_keys, queued_keys); - )* - ) - } - - fn on_before_session_ending() { - for_tuples!( #( Tuple::on_before_session_ending(); )* ) - } - - fn on_disabled(i: usize) { - for_tuples!( #( Tuple::on_disabled(i); )* ) - } -} - -/// Handler for selecting the genesis validator set. -pub trait SelectInitialValidators { - /// Returns the initial validator set. If `None` is returned - /// all accounts that have session keys set in the genesis block - /// will be validators. - fn select_initial_validators() -> Option>; -} - -/// Implementation of `SelectInitialValidators` that does nothing. -impl SelectInitialValidators for () { - fn select_initial_validators() -> Option> { - None - } -} - -pub trait Trait: system::Trait { - /// The overarching event type. - type Event: From + Into<::Event>; - - /// A stable ID for a validator. - type ValidatorId: Member + Parameter; - - /// A conversion to validator ID to account ID. - type ValidatorIdOf: Convert>; - - /// Indicator for when to end the session. - type ShouldEndSession: ShouldEndSession; - - /// Handler for when a session is about to end. - type OnSessionEnding: OnSessionEnding; - - /// Handler when a session has changed. - type SessionHandler: SessionHandler; - - /// The keys. - type Keys: OpaqueKeys + Member + Parameter + Default; - - /// The fraction of validators set that is safe to be disabled. - /// - /// After the threshold is reached `disabled` method starts to return true, - /// which in combination with `srml_staking` forces a new era. - type DisabledValidatorsThreshold: Get; - - /// Select initial validators. - type SelectInitialValidators: SelectInitialValidators; -} - -const DEDUP_KEY_PREFIX: &[u8] = b":session:keys"; - -decl_storage! { - trait Store for Module as Session { - /// The current set of validators. - Validators get(fn validators): Vec; - - /// Current index of the session. - CurrentIndex get(fn current_index): SessionIndex; - - /// True if the underlying economic identities or weighting behind the validators - /// has changed in the queued validator set. - QueuedChanged: bool; - - /// The queued keys for the next session. When the next session begins, these keys - /// will be used to determine the validator's session keys. - QueuedKeys get(fn queued_keys): Vec<(T::ValidatorId, T::Keys)>; - - /// Indices of disabled validators. - /// - /// The set is cleared when `on_session_ending` returns a new set of identities. - DisabledValidators get(fn disabled_validators): Vec; - - /// The next session keys for a validator. - /// - /// The first key is always `DEDUP_KEY_PREFIX` to have all the data in the same branch of - /// the trie. Having all data in the same branch should prevent slowing down other queries. - NextKeys: double_map hasher(twox_64_concat) Vec, blake2_256(T::ValidatorId) => Option; - - /// The owner of a key. The second key is the `KeyTypeId` + the encoded key. - /// - /// The first key is always `DEDUP_KEY_PREFIX` to have all the data in the same branch of - /// the trie. Having all data in the same branch should prevent slowing down other queries. - KeyOwner: double_map hasher(twox_64_concat) Vec, blake2_256((KeyTypeId, Vec)) => Option; - } - add_extra_genesis { - config(keys): Vec<(T::ValidatorId, T::Keys)>; - build(|config: &GenesisConfig| { - for (who, keys) in config.keys.iter().cloned() { - assert!( - >::load_keys(&who).is_none(), - "genesis config contained duplicate validator {:?}", who, - ); - - >::do_set_keys(&who, keys) - .expect("genesis config must not contain duplicates; qed"); - } - - let initial_validators = T::SelectInitialValidators::select_initial_validators() - .unwrap_or_else(|| config.keys.iter().map(|(ref v, _)| v.clone()).collect()); - - assert!(!initial_validators.is_empty(), "Empty validator set in genesis block!"); - - let queued_keys: Vec<_> = initial_validators - .iter() - .cloned() - .map(|v| ( - v.clone(), - >::load_keys(&v).unwrap_or_default(), - )) - .collect(); - - // Tell everyone about the genesis session keys - T::SessionHandler::on_genesis_session::(&queued_keys); - - >::put(initial_validators); - >::put(queued_keys); - }); - } -} - -decl_event!( - pub enum Event { - /// New session has happened. Note that the argument is the session index, not the block - /// number as the type might suggest. - NewSession(SessionIndex), - } -); - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// Used as first key for `NextKeys` and `KeyOwner` to put all the data into the same branch - /// of the trie. - const DEDUP_KEY_PREFIX: &[u8] = DEDUP_KEY_PREFIX; - - fn deposit_event() = default; - - /// Sets the session key(s) of the function caller to `key`. - /// Allows an account to set its session key prior to becoming a validator. - /// This doesn't take effect until the next session. - /// - /// The dispatch origin of this function must be signed. - /// - /// # - /// - O(log n) in number of accounts. - /// - One extra DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(150_000)] - fn set_keys(origin, keys: T::Keys, proof: Vec) -> Result { - let who = ensure_signed(origin)?; - - ensure!(keys.ownership_proof_is_valid(&proof), "invalid ownership proof"); - - let who = match T::ValidatorIdOf::convert(who) { - Some(val_id) => val_id, - None => return Err("no associated validator ID for account."), - }; - - Self::do_set_keys(&who, keys)?; - - Ok(()) - } - - /// Called when a block is initialized. Will rotate session if it is the last - /// block of the current session. - fn on_initialize(n: T::BlockNumber) { - if T::ShouldEndSession::should_end_session(n) { - Self::rotate_session(); - } - } - } -} - -impl Module { - /// Move on to next session. Register new validator set and session keys. Changes - /// to the validator set have a session of delay to take effect. This allows for - /// equivocation punishment after a fork. - pub fn rotate_session() { - let session_index = CurrentIndex::get(); - - let changed = QueuedChanged::get(); - - // Inform the session handlers that a session is going to end. - T::SessionHandler::on_before_session_ending(); - - // Get queued session keys and validators. - let session_keys = >::get(); - let validators = session_keys.iter() - .map(|(validator, _)| validator.clone()) - .collect::>(); - >::put(&validators); - - if changed { - // reset disabled validators - DisabledValidators::take(); - } - - let applied_at = session_index + 2; - - // Get next validator set. - let maybe_next_validators = T::OnSessionEnding::on_session_ending(session_index, applied_at); - let (next_validators, next_identities_changed) - = if let Some(validators) = maybe_next_validators - { - // NOTE: as per the documentation on `OnSessionEnding`, we consider - // the validator set as having changed even if the validators are the - // same as before, as underlying economic conditions may have changed. - (validators, true) - } else { - (>::get(), false) - }; - - // Increment session index. - let session_index = session_index + 1; - CurrentIndex::put(session_index); - - // Queue next session keys. - let (queued_amalgamated, next_changed) = { - // until we are certain there has been a change, iterate the prior - // validators along with the current and check for changes - let mut changed = next_identities_changed; - - let mut now_session_keys = session_keys.iter(); - let mut check_next_changed = |keys: &T::Keys| { - if changed { return } - // since a new validator set always leads to `changed` starting - // as true, we can ensure that `now_session_keys` and `next_validators` - // have the same length. this function is called once per iteration. - if let Some(&(_, ref old_keys)) = now_session_keys.next() { - if old_keys != keys { - changed = true; - return - } - } - }; - let queued_amalgamated = next_validators.into_iter() - .map(|a| { - let k = Self::load_keys(&a).unwrap_or_default(); - check_next_changed(&k); - (a, k) - }) - .collect::>(); - - (queued_amalgamated, changed) - }; - - >::put(queued_amalgamated.clone()); - QueuedChanged::put(next_changed); - - // Record that this happened. - Self::deposit_event(Event::NewSession(session_index)); - - // Tell everyone about the new session keys. - T::SessionHandler::on_new_session::( - changed, - &session_keys, - &queued_amalgamated, - ); - } - - /// Disable the validator of index `i`. - /// - /// Returns `true` if this causes a `DisabledValidatorsThreshold` of validators - /// to be already disabled. - pub fn disable_index(i: usize) -> bool { - let (fire_event, threshold_reached) = DisabledValidators::mutate(|disabled| { - let i = i as u32; - if let Err(index) = disabled.binary_search(&i) { - let count = >::decode_len().unwrap_or(0) as u32; - let threshold = T::DisabledValidatorsThreshold::get() * count; - disabled.insert(index, i); - (true, disabled.len() as u32 > threshold) - } else { - (false, false) - } - }); - - if fire_event { - T::SessionHandler::on_disabled(i); - } - - threshold_reached - } - - /// Disable the validator identified by `c`. (If using with the staking module, - /// this would be their *stash* account.) - /// - /// Returns `Ok(true)` if more than `DisabledValidatorsThreshold` validators in current - /// session is already disabled. - /// If used with the staking module it allows to force a new era in such case. - pub fn disable(c: &T::ValidatorId) -> rstd::result::Result { - Self::validators().iter().position(|i| i == c).map(Self::disable_index).ok_or(()) - } - - // perform the set_key operation, checking for duplicates. - // does not set `Changed`. - fn do_set_keys(who: &T::ValidatorId, keys: T::Keys) -> Result { - let old_keys = Self::load_keys(&who); - - for id in T::Keys::key_ids() { - let key = keys.get_raw(id); - - // ensure keys are without duplication. - ensure!( - Self::key_owner(id, key).map_or(true, |owner| &owner == who), - "registered duplicate key" - ); - - if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(id)) { - if key == old { - continue; - } - - Self::clear_key_owner(id, old); - } - - Self::put_key_owner(id, key, &who); - } - - Self::put_keys(&who, &keys); - - Ok(()) - } - - fn prune_dead_keys(who: &T::ValidatorId) { - if let Some(old_keys) = Self::take_keys(who) { - for id in T::Keys::key_ids() { - let key_data = old_keys.get_raw(id); - Self::clear_key_owner(id, key_data); - } - } - } - - fn load_keys(v: &T::ValidatorId) -> Option { - >::get(DEDUP_KEY_PREFIX, v) - } - - fn take_keys(v: &T::ValidatorId) -> Option { - >::take(DEDUP_KEY_PREFIX, v) - } - - fn put_keys(v: &T::ValidatorId, keys: &T::Keys) { - >::insert(DEDUP_KEY_PREFIX, v, keys); - } - - fn key_owner(id: KeyTypeId, key_data: &[u8]) -> Option { - >::get(DEDUP_KEY_PREFIX, (id, key_data)) - } - - fn put_key_owner(id: KeyTypeId, key_data: &[u8], v: &T::ValidatorId) { - >::insert(DEDUP_KEY_PREFIX, (id, key_data), v) - } - - fn clear_key_owner(id: KeyTypeId, key_data: &[u8]) { - >::remove(DEDUP_KEY_PREFIX, (id, key_data)); - } -} - -impl OnFreeBalanceZero for Module { - fn on_free_balance_zero(who: &T::ValidatorId) { - Self::prune_dead_keys(who); - } -} - -/// Wraps the author-scraping logic for consensus engines that can recover -/// the canonical index of an author. This then transforms it into the -/// registering account-ID of that session key index. -pub struct FindAccountFromAuthorIndex(rstd::marker::PhantomData<(T, Inner)>); - -impl> FindAuthor - for FindAccountFromAuthorIndex -{ - fn find_author<'a, I>(digests: I) -> Option - where I: 'a + IntoIterator - { - let i = Inner::find_author(digests)?; - - let validators = >::validators(); - validators.get(i as usize).map(|k| k.clone()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use support::assert_ok; - use primitives::crypto::key_types::DUMMY; - use sr_primitives::{traits::OnInitialize, testing::UintAuthorityId}; - use mock::{ - NEXT_VALIDATORS, SESSION_CHANGED, TEST_SESSION_CHANGED, authorities, force_new_session, - set_next_validators, set_session_length, session_changed, Test, Origin, System, Session, - reset_before_session_end_called, before_session_end_called, - }; - - fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig:: { - keys: NEXT_VALIDATORS.with(|l| - l.borrow().iter().cloned().map(|i| (i, UintAuthorityId(i).into())).collect() - ), - }.assimilate_storage(&mut t).unwrap(); - runtime_io::TestExternalities::new(t) - } - - fn initialize_block(block: u64) { - SESSION_CHANGED.with(|l| *l.borrow_mut() = false); - System::set_block_number(block); - Session::on_initialize(block); - } - - #[test] - fn simple_setup_should_work() { - new_test_ext().execute_with(|| { - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - assert_eq!(Session::validators(), vec![1, 2, 3]); - }); - } - - #[test] - fn put_get_keys() { - new_test_ext().execute_with(|| { - Session::put_keys(&10, &UintAuthorityId(10).into()); - assert_eq!(Session::load_keys(&10), Some(UintAuthorityId(10).into())); - }) - } - - #[test] - fn keys_cleared_on_kill() { - let mut ext = new_test_ext(); - ext.execute_with(|| { - assert_eq!(Session::validators(), vec![1, 2, 3]); - assert_eq!(Session::load_keys(&1), Some(UintAuthorityId(1).into())); - - let id = DUMMY; - assert_eq!(Session::key_owner(id, UintAuthorityId(1).get_raw(id)), Some(1)); - - Session::on_free_balance_zero(&1); - assert_eq!(Session::load_keys(&1), None); - assert_eq!(Session::key_owner(id, UintAuthorityId(1).get_raw(id)), None); - }) - } - - #[test] - fn authorities_should_track_validators() { - reset_before_session_end_called(); - - new_test_ext().execute_with(|| { - set_next_validators(vec![1, 2]); - force_new_session(); - initialize_block(1); - assert_eq!(Session::queued_keys(), vec![ - (1, UintAuthorityId(1).into()), - (2, UintAuthorityId(2).into()), - ]); - assert_eq!(Session::validators(), vec![1, 2, 3]); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - force_new_session(); - initialize_block(2); - assert_eq!(Session::queued_keys(), vec![ - (1, UintAuthorityId(1).into()), - (2, UintAuthorityId(2).into()), - ]); - assert_eq!(Session::validators(), vec![1, 2]); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - set_next_validators(vec![1, 2, 4]); - assert_ok!(Session::set_keys(Origin::signed(4), UintAuthorityId(4).into(), vec![])); - force_new_session(); - initialize_block(3); - assert_eq!(Session::queued_keys(), vec![ - (1, UintAuthorityId(1).into()), - (2, UintAuthorityId(2).into()), - (4, UintAuthorityId(4).into()), - ]); - assert_eq!(Session::validators(), vec![1, 2]); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); - assert!(before_session_end_called()); - - force_new_session(); - initialize_block(4); - assert_eq!(Session::queued_keys(), vec![ - (1, UintAuthorityId(1).into()), - (2, UintAuthorityId(2).into()), - (4, UintAuthorityId(4).into()), - ]); - assert_eq!(Session::validators(), vec![1, 2, 4]); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(4)]); - }); - } - - #[test] - fn should_work_with_early_exit() { - new_test_ext().execute_with(|| { - set_session_length(10); - - initialize_block(1); - assert_eq!(Session::current_index(), 0); - - initialize_block(2); - assert_eq!(Session::current_index(), 0); - - force_new_session(); - initialize_block(3); - assert_eq!(Session::current_index(), 1); - - initialize_block(9); - assert_eq!(Session::current_index(), 1); - - initialize_block(10); - assert_eq!(Session::current_index(), 2); - }); - } - - #[test] - fn session_change_should_work() { - new_test_ext().execute_with(|| { - // Block 1: No change - initialize_block(1); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - - // Block 2: Session rollover, but no change. - initialize_block(2); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - - // Block 3: Set new key for validator 2; no visible change. - initialize_block(3); - assert_ok!(Session::set_keys(Origin::signed(2), UintAuthorityId(5).into(), vec![])); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - - // Block 4: Session rollover; no visible change. - initialize_block(4); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - - // Block 5: No change. - initialize_block(5); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - - // Block 6: Session rollover; authority 2 changes. - initialize_block(6); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(5), UintAuthorityId(3)]); - }); - } - - #[test] - fn duplicates_are_not_allowed() { - new_test_ext().execute_with(|| { - System::set_block_number(1); - Session::on_initialize(1); - assert!(Session::set_keys(Origin::signed(4), UintAuthorityId(1).into(), vec![]).is_err()); - assert!(Session::set_keys(Origin::signed(1), UintAuthorityId(10).into(), vec![]).is_ok()); - - // is fine now that 1 has migrated off. - assert!(Session::set_keys(Origin::signed(4), UintAuthorityId(1).into(), vec![]).is_ok()); - }); - } - - #[test] - fn session_changed_flag_works() { - reset_before_session_end_called(); - - new_test_ext().execute_with(|| { - TEST_SESSION_CHANGED.with(|l| *l.borrow_mut() = true); - - force_new_session(); - initialize_block(1); - assert!(!session_changed()); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - force_new_session(); - initialize_block(2); - assert!(!session_changed()); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - Session::disable_index(0); - force_new_session(); - initialize_block(3); - assert!(!session_changed()); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - force_new_session(); - initialize_block(4); - assert!(session_changed()); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - force_new_session(); - initialize_block(5); - assert!(!session_changed()); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - assert_ok!(Session::set_keys(Origin::signed(2), UintAuthorityId(5).into(), vec![])); - force_new_session(); - initialize_block(6); - assert!(!session_changed()); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - // changing the keys of a validator leads to change. - assert_ok!(Session::set_keys(Origin::signed(69), UintAuthorityId(69).into(), vec![])); - force_new_session(); - initialize_block(7); - assert!(session_changed()); - assert!(before_session_end_called()); - reset_before_session_end_called(); - - // while changing the keys of a non-validator does not. - force_new_session(); - initialize_block(7); - assert!(!session_changed()); - assert!(before_session_end_called()); - reset_before_session_end_called(); - }); - } - - #[test] - fn periodic_session_works() { - struct Period; - struct Offset; - - impl Get for Period { - fn get() -> u64 { 10 } - } - - impl Get for Offset { - fn get() -> u64 { 3 } - } - - - type P = PeriodicSessions; - - for i in 0..3 { - assert!(!P::should_end_session(i)); - } - - assert!(P::should_end_session(3)); - - for i in (1..10).map(|i| 3 + i) { - assert!(!P::should_end_session(i)); - } - - assert!(P::should_end_session(13)); - } - - #[test] - fn session_keys_generate_output_works_as_set_keys_input() { - new_test_ext().execute_with(|| { - let new_keys = mock::MockSessionKeys::generate(None); - assert_ok!( - Session::set_keys( - Origin::signed(2), - ::Keys::decode(&mut &new_keys[..]).expect("Decode keys"), - vec![], - ) - ); - }); - } - - #[test] - fn return_true_if_more_than_third_is_disabled() { - new_test_ext().execute_with(|| { - set_next_validators(vec![1, 2, 3, 4, 5, 6, 7]); - force_new_session(); - initialize_block(1); - // apply the new validator set - force_new_session(); - initialize_block(2); - - assert_eq!(Session::disable_index(0), false); - assert_eq!(Session::disable_index(1), false); - assert_eq!(Session::disable_index(2), true); - assert_eq!(Session::disable_index(3), true); - }); - } -} diff --git a/srml/session/src/mock.rs b/srml/session/src/mock.rs deleted file mode 100644 index d680fdc96b015..0000000000000 --- a/srml/session/src/mock.rs +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Mock helpers for Session. - -use super::*; -use std::cell::RefCell; -use support::{impl_outer_origin, parameter_types}; -use primitives::{crypto::key_types::DUMMY, H256}; -use sr_primitives::{ - Perbill, impl_opaque_keys, traits::{BlakeTwo256, IdentityLookup, ConvertInto}, - testing::{Header, UintAuthorityId} -}; -use sr_staking_primitives::SessionIndex; - -impl_opaque_keys! { - pub struct MockSessionKeys { - #[id(DUMMY)] - pub dummy: UintAuthorityId, - } -} - -impl From for MockSessionKeys { - fn from(dummy: UintAuthorityId) -> Self { - Self { dummy } - } -} - -impl_outer_origin! { - pub enum Origin for Test {} -} - -thread_local! { - pub static VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); - pub static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); - pub static AUTHORITIES: RefCell> = - RefCell::new(vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - pub static FORCE_SESSION_END: RefCell = RefCell::new(false); - pub static SESSION_LENGTH: RefCell = RefCell::new(2); - pub static SESSION_CHANGED: RefCell = RefCell::new(false); - pub static TEST_SESSION_CHANGED: RefCell = RefCell::new(false); - pub static DISABLED: RefCell = RefCell::new(false); - // Stores if `on_before_session_end` was called - pub static BEFORE_SESSION_END_CALLED: RefCell = RefCell::new(false); -} - -pub struct TestShouldEndSession; -impl ShouldEndSession for TestShouldEndSession { - fn should_end_session(now: u64) -> bool { - let l = SESSION_LENGTH.with(|l| *l.borrow()); - now % l == 0 || FORCE_SESSION_END.with(|l| { let r = *l.borrow(); *l.borrow_mut() = false; r }) - } -} - -pub struct TestSessionHandler; -impl SessionHandler for TestSessionHandler { - fn on_genesis_session(_validators: &[(u64, T)]) {} - fn on_new_session( - changed: bool, - validators: &[(u64, T)], - _queued_validators: &[(u64, T)], - ) { - SESSION_CHANGED.with(|l| *l.borrow_mut() = changed); - AUTHORITIES.with(|l| - *l.borrow_mut() = validators.iter() - .map(|(_, id)| id.get::(DUMMY).unwrap_or_default()) - .collect() - ); - } - fn on_disabled(_validator_index: usize) { - DISABLED.with(|l| *l.borrow_mut() = true) - } - fn on_before_session_ending() { - BEFORE_SESSION_END_CALLED.with(|b| *b.borrow_mut() = true); - } -} - -pub struct TestOnSessionEnding; -impl OnSessionEnding for TestOnSessionEnding { - fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { - if !TEST_SESSION_CHANGED.with(|l| *l.borrow()) { - VALIDATORS.with(|v| { - let mut v = v.borrow_mut(); - *v = NEXT_VALIDATORS.with(|l| l.borrow().clone()); - Some(v.clone()) - }) - } else if DISABLED.with(|l| std::mem::replace(&mut *l.borrow_mut(), false)) { - // If there was a disabled validator, underlying conditions have changed - // so we return `Some`. - Some(VALIDATORS.with(|v| v.borrow().clone())) - } else { - None - } - } -} - -#[cfg(feature = "historical")] -impl crate::historical::OnSessionEnding for TestOnSessionEnding { - fn on_session_ending(ending_index: SessionIndex, will_apply_at: SessionIndex) - -> Option<(Vec, Vec<(u64, u64)>)> - { - let pair_with_ids = |vals: &[u64]| vals.iter().map(|&v| (v, v)).collect::>(); - >::on_session_ending(ending_index, will_apply_at) - .map(|vals| (pair_with_ids(&vals), vals)) - .map(|(ids, vals)| (vals, ids)) - } -} - -pub fn authorities() -> Vec { - AUTHORITIES.with(|l| l.borrow().to_vec()) -} - -pub fn force_new_session() { - FORCE_SESSION_END.with(|l| *l.borrow_mut() = true ) -} - -pub fn set_session_length(x: u64) { - SESSION_LENGTH.with(|l| *l.borrow_mut() = x ) -} - -pub fn session_changed() -> bool { - SESSION_CHANGED.with(|l| *l.borrow()) -} - -pub fn set_next_validators(next: Vec) { - NEXT_VALIDATORS.with(|v| *v.borrow_mut() = next); -} - -pub fn before_session_end_called() -> bool { - BEFORE_SESSION_END_CALLED.with(|b| *b.borrow()) -} - -pub fn reset_before_session_end_called() { - BEFORE_SESSION_END_CALLED.with(|b| *b.borrow_mut() = false); -} - -#[derive(Clone, Eq, PartialEq)] -pub struct Test; - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const MinimumPeriod: u64 = 5; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); -} - -impl timestamp::Trait for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; -} - -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); -} - -impl Trait for Test { - type ShouldEndSession = TestShouldEndSession; - #[cfg(feature = "historical")] - type OnSessionEnding = crate::historical::NoteHistoricalRoot; - #[cfg(not(feature = "historical"))] - type OnSessionEnding = TestOnSessionEnding; - type SessionHandler = TestSessionHandler; - type ValidatorId = u64; - type ValidatorIdOf = ConvertInto; - type Keys = MockSessionKeys; - type Event = (); - type SelectInitialValidators = (); - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; -} - -#[cfg(feature = "historical")] -impl crate::historical::Trait for Test { - type FullIdentification = u64; - type FullIdentificationOf = sr_primitives::traits::ConvertInto; -} - -pub type System = system::Module; -pub type Session = Module; diff --git a/srml/staking/Cargo.toml b/srml/staking/Cargo.toml deleted file mode 100644 index 67f3ab41d6583..0000000000000 --- a/srml/staking/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "srml-staking" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -substrate-keyring = { path = "../../core/keyring", optional = true } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -phragmen = { package = "substrate-phragmen", path = "../../core/phragmen", default-features = false } -runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -session = { package = "srml-session", path = "../session", default-features = false, features = ["historical"] } -authorship = { package = "srml-authorship", path = "../authorship", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -balances = { package = "srml-balances", path = "../balances" } -timestamp = { package = "srml-timestamp", path = "../timestamp" } -srml-staking-reward-curve = { path = "../staking/reward-curve"} - -[features] -equalize = [] -default = ["std", "equalize"] -std = [ - "serde", - "safe-mix/std", - "substrate-keyring", - "codec/std", - "rstd/std", - "phragmen/std", - "runtime-io/std", - "support/std", - "sr-primitives/std", - "sr-staking-primitives/std", - "session/std", - "system/std", - "authorship/std", -] diff --git a/srml/staking/reward-curve/Cargo.toml b/srml/staking/reward-curve/Cargo.toml deleted file mode 100644 index 4fb0ab1672ce0..0000000000000 --- a/srml/staking/reward-curve/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "srml-staking-reward-curve" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -syn = { version = "1.0", features = [ "full", "visit" ] } -quote = "1.0" -proc-macro2 = "1.0.4" -proc-macro-crate = "0.1.4" - -[dev-dependencies] -sr-primitives = { path = "../../../core/sr-primitives" } diff --git a/srml/staking/reward-curve/src/lib.rs b/srml/staking/reward-curve/src/lib.rs deleted file mode 100644 index 7e1f1e6aa945f..0000000000000 --- a/srml/staking/reward-curve/src/lib.rs +++ /dev/null @@ -1,416 +0,0 @@ -extern crate proc_macro; - -mod log; - -use log::log2; -use proc_macro::TokenStream; -use proc_macro2::{TokenStream as TokenStream2, Span}; -use proc_macro_crate::crate_name; -use quote::{quote, ToTokens}; -use std::convert::TryInto; -use syn::parse::{Parse, ParseStream}; - -/// Accepts a number of expressions to create a instance of PiecewiseLinear which represents the -/// NPoS curve (as detailed -/// [here](http://research.web3.foundation/en/latest/polkadot/Token%20Economics/#inflation-model)) -/// for those parameters. Parameters are: -/// - `min_inflation`: the minimal amount to be rewarded between validators, expressed as a fraction -/// of total issuance. Known as `I_0` in the literature. -/// Expressed in millionth, must be between 0 and 1_000_000. -/// -/// - `max_inflation`: the maximum amount to be rewarded between validators, expressed as a fraction -/// of total issuance. This is attained only when `ideal_stake` is achieved. -/// Expressed in millionth, must be between min_inflation and 1_000_000. -/// -/// - `ideal_stake`: the fraction of total issued tokens that should be actively staked behind -/// validators. Known as `x_ideal` in the literature. -/// Expressed in millionth, must be between 0_100_000 and 0_900_000. -/// -/// - `falloff`: Known as `decay_rate` in the literature. A co-efficient dictating the strength of -/// the global incentivisation to get the `ideal_stake`. A higher number results in less typical -/// inflation at the cost of greater volatility for validators. -/// Expressed in millionth, must be between 0 and 1_000_000. -/// -/// - `max_piece_count`: The maximum number of pieces in the curve. A greater number uses more -/// resources but results in higher accuracy. -/// Must be between 2 and 1_000. -/// -/// - `test_precision`: The maximum error allowed in the generated test. -/// Expressed in millionth, must be between 0 and 1_000_000. -/// -/// # Example -/// -/// ``` -/// # fn main() {} -/// use sr_primitives::curve::PiecewiseLinear; -/// -/// srml_staking_reward_curve::build! { -/// const I_NPOS: PiecewiseLinear<'static> = curve!( -/// min_inflation: 0_025_000, -/// max_inflation: 0_100_000, -/// ideal_stake: 0_500_000, -/// falloff: 0_050_000, -/// max_piece_count: 40, -/// test_precision: 0_005_000, -/// ); -/// } -/// ``` -#[proc_macro] -pub fn build(input: TokenStream) -> TokenStream { - let input = syn::parse_macro_input!(input as INposInput); - - let points = compute_points(&input); - - let declaration = generate_piecewise_linear(points); - let test_module = generate_test_module(&input); - - let imports = match crate_name("sr-primitives") { - Ok(sr_primitives) => { - let ident = syn::Ident::new(&sr_primitives, Span::call_site()); - quote!( extern crate #ident as _sr_primitives; ) - }, - Err(e) => syn::Error::new(Span::call_site(), &e).to_compile_error(), - }; - - let const_name = input.ident; - let const_type = input.typ; - - quote!( - const #const_name: #const_type = { - #imports - #declaration - }; - #test_module - ).into() -} - -const MILLION: u32 = 1_000_000; - -mod keyword { - syn::custom_keyword!(curve); - syn::custom_keyword!(min_inflation); - syn::custom_keyword!(max_inflation); - syn::custom_keyword!(ideal_stake); - syn::custom_keyword!(falloff); - syn::custom_keyword!(max_piece_count); - syn::custom_keyword!(test_precision); -} - -struct INposInput { - ident: syn::Ident, - typ: syn::Type, - min_inflation: u32, - ideal_stake: u32, - max_inflation: u32, - falloff: u32, - max_piece_count: u32, - test_precision: u32, -} - -struct Bounds { - min: u32, - min_strict: bool, - max: u32, - max_strict: bool, -} - -impl Bounds { - fn check(&self, value: u32) -> bool { - let wrong = (self.min_strict && value <= self.min) - || (!self.min_strict && value < self.min) - || (self.max_strict && value >= self.max) - || (!self.max_strict && value > self.max); - - !wrong - } -} - -impl core::fmt::Display for Bounds { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!( - f, - "{}{:07}; {:07}{}", - if self.min_strict { "]" } else { "[" }, - self.min, - self.max, - if self.max_strict { "[" } else { "]" }, - ) - } -} - -fn parse_field(input: ParseStream, bounds: Bounds) - -> syn::Result -{ - ::parse(&input)?; - ::parse(&input)?; - let value_lit = syn::LitInt::parse(&input)?; - let value: u32 = value_lit.base10_parse()?; - if !bounds.check(value) { - return Err(syn::Error::new(value_lit.span(), format!( - "Invalid {}: {}, must be in {}", Token::default().to_token_stream(), value, bounds, - ))); - } - - Ok(value) -} - -impl Parse for INposInput { - fn parse(input: ParseStream) -> syn::Result { - let args_input; - - ::parse(&input)?; - let ident = ::parse(&input)?; - ::parse(&input)?; - let typ = ::parse(&input)?; - ::parse(&input)?; - ::parse(&input)?; - ::parse(&input)?; - syn::parenthesized!(args_input in input); - ::parse(&input)?; - - if !input.is_empty() { - return Err(input.error("expected end of input stream, no token expected")); - } - - let min_inflation = parse_field::(&args_input, Bounds { - min: 0, - min_strict: true, - max: 1_000_000, - max_strict: false, - })?; - ::parse(&args_input)?; - let max_inflation = parse_field::(&args_input, Bounds { - min: min_inflation, - min_strict: true, - max: 1_000_000, - max_strict: false, - })?; - ::parse(&args_input)?; - let ideal_stake = parse_field::(&args_input, Bounds { - min: 0_100_000, - min_strict: false, - max: 0_900_000, - max_strict: false, - })?; - ::parse(&args_input)?; - let falloff = parse_field::(&args_input, Bounds { - min: 0_010_000, - min_strict: false, - max: 1_000_000, - max_strict: false, - })?; - ::parse(&args_input)?; - let max_piece_count = parse_field::(&args_input, Bounds { - min: 2, - min_strict: false, - max: 1_000, - max_strict: false, - })?; - ::parse(&args_input)?; - let test_precision = parse_field::(&args_input, Bounds { - min: 0, - min_strict: false, - max: 1_000_000, - max_strict: false, - })?; - >::parse(&args_input)?; - - if !args_input.is_empty() { - return Err(args_input.error("expected end of input stream, no token expected")); - } - - Ok(Self { - ident, - typ, - min_inflation, - ideal_stake, - max_inflation, - falloff, - max_piece_count, - test_precision, - }) - } -} - -struct INPoS { - i_0: u32, - i_ideal_times_x_ideal: u32, - i_ideal: u32, - x_ideal: u32, - d: u32, -} - -impl INPoS { - fn from_input(input: &INposInput) -> Self { - INPoS { - i_0: input.min_inflation, - i_ideal: (input.max_inflation as u64 * MILLION as u64 / input.ideal_stake as u64) - .try_into().unwrap(), - i_ideal_times_x_ideal: input.max_inflation, - x_ideal: input.ideal_stake, - d: input.falloff, - } - } - - fn compute_opposite_after_x_ideal(&self, y: u32) -> u32 { - if y == self.i_0 { - return u32::max_value(); - } - let log = log2(self.i_ideal_times_x_ideal - self.i_0, y - self.i_0); - - let term: u32 = ((self.d as u64 * log as u64) / 1_000_000).try_into().unwrap(); - - self.x_ideal + term - } -} - -fn compute_points(input: &INposInput) -> Vec<(u32, u32)> { - let inpos = INPoS::from_input(input); - - let mut points = vec![]; - points.push((0, inpos.i_0)); - points.push((inpos.x_ideal, inpos.i_ideal_times_x_ideal)); - - // For each point p: (next_p.0 - p.0) < segment_lenght && (next_p.1 - p.1) < segment_lenght. - // This ensures that the total number of segment doesn't overflow max_piece_count. - let max_length = (input.max_inflation - input.min_inflation + 1_000_000 - inpos.x_ideal) - / (input.max_piece_count - 1); - - let mut delta_y = max_length; - let mut y = input.max_inflation; - - // The algorithm divide the curve in segment with vertical len and horizontal len less - // than `max_length`. This is not very accurate in case of very consequent steep. - while delta_y != 0 { - let next_y = y - delta_y; - - if next_y <= input.min_inflation { - delta_y = delta_y.saturating_sub(1); - continue - } - - let next_x = inpos.compute_opposite_after_x_ideal(next_y); - - if (next_x - points.last().unwrap().0) > max_length { - delta_y = delta_y.saturating_sub(1); - continue - } - - if next_x >= 1_000_000 { - let prev = points.last().unwrap(); - // Compute the y corresponding to x=1_000_000 using the this point and the previous one. - - let delta_y: u32 = ( - (next_x - 1_000_000) as u64 - * (prev.1 - next_y) as u64 - / (next_x - prev.0) as u64 - ).try_into().unwrap(); - - let y = next_y + delta_y; - - points.push((1_000_000, y)); - return points; - } - points.push((next_x, next_y)); - y = next_y; - } - - points.push((1_000_000, inpos.i_0)); - - points -} - -fn generate_piecewise_linear(points: Vec<(u32, u32)>) -> TokenStream2 { - let mut points_tokens = quote!(); - - for (x, y) in points { - let error = || panic!(format!( - "Generated reward curve approximation doesn't fit into [0, 1] -> [0, 1] \ - because of point: - x = {:07} per million - y = {:07} per million", - x, y - )); - - let x_perbill = x.checked_mul(1_000).unwrap_or_else(error); - let y_perbill = y.checked_mul(1_000).unwrap_or_else(error); - - points_tokens.extend(quote!( - ( - _sr_primitives::Perbill::from_parts(#x_perbill), - _sr_primitives::Perbill::from_parts(#y_perbill), - ), - )); - } - - quote!( - _sr_primitives::curve::PiecewiseLinear::<'static> { - points: & [ #points_tokens ], - } - ) -} - -fn generate_test_module(input: &INposInput) -> TokenStream2 { - let inpos = INPoS::from_input(input); - - let ident = &input.ident; - let precision = input.test_precision; - let i_0 = inpos.i_0 as f64/ MILLION as f64; - let i_ideal_times_x_ideal = inpos.i_ideal_times_x_ideal as f64 / MILLION as f64; - let i_ideal = inpos.i_ideal as f64 / MILLION as f64; - let x_ideal = inpos.x_ideal as f64 / MILLION as f64; - let d = inpos.d as f64 / MILLION as f64; - let max_piece_count = input.max_piece_count; - - quote!( - #[cfg(test)] - mod __srml_staking_reward_curve_test_module { - fn i_npos(x: f64) -> f64 { - if x <= #x_ideal { - #i_0 + x * (#i_ideal - #i_0 / #x_ideal) - } else { - #i_0 + (#i_ideal_times_x_ideal - #i_0) * 2_f64.powf((#x_ideal - x) / #d) - } - } - - const MILLION: u32 = 1_000_000; - - #[test] - fn reward_curve_precision() { - for &base in [MILLION, u32::max_value()].into_iter() { - let number_of_check = 100_000.min(base); - for check_index in 0..=number_of_check { - let i = (check_index as u64 * base as u64 / number_of_check as u64) as u32; - let x = i as f64 / base as f64; - let float_res = (i_npos(x) * base as f64).round() as u32; - let int_res = super::#ident.calculate_for_fraction_times_denominator(i, base); - let err = ( - (float_res.max(int_res) - float_res.min(int_res)) as u64 - * MILLION as u64 - / float_res as u64 - ) as u32; - if err > #precision { - panic!(format!("\n\ - Generated reward curve approximation differ from real one:\n\t\ - for i = {} and base = {}, f(i/base) * base = {},\n\t\ - but approximation = {},\n\t\ - err = {:07} millionth,\n\t\ - try increase the number of segment: {} or the test_error: {}.\n", - i, base, float_res, int_res, err, #max_piece_count, #precision - )); - } - } - } - } - - #[test] - fn reward_curve_piece_count() { - assert!( - super::#ident.points.len() as u32 - 1 <= #max_piece_count, - "Generated reward curve approximation is invalid: \ - has more points than specified, please fill an issue." - ); - } - } - ).into() -} diff --git a/srml/staking/reward-curve/tests/test.rs b/srml/staking/reward-curve/tests/test.rs deleted file mode 100644 index 55a3b7d383e9e..0000000000000 --- a/srml/staking/reward-curve/tests/test.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test crate for srml-staking-reward-curve. Allows to test for procedural macro. -//! See tests directory. - -mod test_small_falloff { - srml_staking_reward_curve::build! { - const REWARD_CURVE: sr_primitives::curve::PiecewiseLinear<'static> = curve!( - min_inflation: 0_020_000, - max_inflation: 0_200_000, - ideal_stake: 0_600_000, - falloff: 0_010_000, - max_piece_count: 200, - test_precision: 0_005_000, - ); - } -} - -mod test_big_falloff { - srml_staking_reward_curve::build! { - const REWARD_CURVE: sr_primitives::curve::PiecewiseLinear<'static> = curve!( - min_inflation: 0_100_000, - max_inflation: 0_400_000, - ideal_stake: 0_400_000, - falloff: 1_000_000, - max_piece_count: 40, - test_precision: 0_005_000, - ); - } -} diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs deleted file mode 100644 index f6d123bd1393d..0000000000000 --- a/srml/staking/src/lib.rs +++ /dev/null @@ -1,1589 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Staking Module -//! -//! The Staking module is used to manage funds at stake by network maintainers. -//! -//! - [`staking::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! - [`Module`](./struct.Module.html) -//! -//! ## Overview -//! -//! The Staking module is the means by which a set of network maintainers (known as _authorities_ -//! in some contexts and _validators_ in others) are chosen based upon those who voluntarily place -//! funds under deposit. Under deposit, those funds are rewarded under normal operation but are -//! held at pain of _slash_ (expropriation) should the staked maintainer be found not to be -//! discharging its duties properly. -//! -//! ### Terminology -//! -//! -//! - Staking: The process of locking up funds for some time, placing them at risk of slashing -//! (loss) in order to become a rewarded maintainer of the network. -//! - Validating: The process of running a node to actively maintain the network, either by -//! producing blocks or guaranteeing finality of the chain. -//! - Nominating: The process of placing staked funds behind one or more validators in order to -//! share in any reward, and punishment, they take. -//! - Stash account: The account holding an owner's funds used for staking. -//! - Controller account: The account that controls an owner's funds for staking. -//! - Era: A (whole) number of sessions, which is the period that the validator set (and each -//! validator's active nominator set) is recalculated and where rewards are paid out. -//! - Slash: The punishment of a staker by reducing its funds. -//! -//! ### Goals -//! -//! -//! The staking system in Substrate NPoS is designed to make the following possible: -//! -//! - Stake funds that are controlled by a cold wallet. -//! - Withdraw some, or deposit more, funds without interrupting the role of an entity. -//! - Switch between roles (nominator, validator, idle) with minimal overhead. -//! -//! ### Scenarios -//! -//! #### Staking -//! -//! Almost any interaction with the Staking module requires a process of _**bonding**_ (also known -//! as being a _staker_). To become *bonded*, a fund-holding account known as the _stash account_, -//! which holds some or all of the funds that become frozen in place as part of the staking process, -//! is paired with an active **controller** account, which issues instructions on how they shall be -//! used. -//! -//! An account pair can become bonded using the [`bond`](./enum.Call.html#variant.bond) call. -//! -//! Stash accounts can change their associated controller using the -//! [`set_controller`](./enum.Call.html#variant.set_controller) call. -//! -//! There are three possible roles that any staked account pair can be in: `Validator`, `Nominator` -//! and `Idle` (defined in [`StakerStatus`](./enum.StakerStatus.html)). There are three -//! corresponding instructions to change between roles, namely: -//! [`validate`](./enum.Call.html#variant.validate), [`nominate`](./enum.Call.html#variant.nominate), -//! and [`chill`](./enum.Call.html#variant.chill). -//! -//! #### Validating -//! -//! A **validator** takes the role of either validating blocks or ensuring their finality, -//! maintaining the veracity of the network. A validator should avoid both any sort of malicious -//! misbehavior and going offline. Bonded accounts that state interest in being a validator do NOT -//! get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they -//! _might_ get elected at the _next era_ as a validator. The result of the election is determined -//! by nominators and their votes. -//! -//! An account can become a validator candidate via the -//! [`validate`](./enum.Call.html#variant.validate) call. -//! -//! #### Nomination -//! -//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on -//! a set of validators to be elected. Once interest in nomination is stated by an account, it -//! takes effect at the next election round. The funds in the nominator's stash account indicate the -//! _weight_ of its vote. Both the rewards and any punishment that a validator earns are shared -//! between the validator and its nominators. This rule incentivizes the nominators to NOT vote for -//! the misbehaving/offline validators as much as possible, simply because the nominators will also -//! lose funds if they vote poorly. -//! -//! An account can become a nominator via the [`nominate`](enum.Call.html#variant.nominate) call. -//! -//! #### Rewards and Slash -//! -//! The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace -//! valid behavior_ while _punishing any misbehavior or lack of availability_. -//! -//! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is -//! determined, a value is deducted from the balance of the validator and all the nominators who -//! voted for this validator (values are deducted from the _stash_ account of the slashed entity). -//! -//! Similar to slashing, rewards are also shared among a validator and its associated nominators. -//! Yet, the reward funds are not always transferred to the stash account and can be configured. -//! See [Reward Calculation](#reward-calculation) for more details. -//! -//! #### Chilling -//! -//! Finally, any of the roles above can choose to step back temporarily and just chill for a while. -//! This means that if they are a nominator, they will not be considered as voters anymore and if -//! they are validators, they will no longer be a candidate for the next election. -//! -//! An account can step back via the [`chill`](enum.Call.html#variant.chill) call. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! The dispatchable functions of the Staking module enable the steps needed for entities to accept -//! and change their role, alongside some helper functions to get/set the metadata of the module. -//! -//! ### Public Functions -//! -//! The Staking module contains many public storage items and (im)mutable functions. -//! -//! ## Usage -//! -//! ### Example: Rewarding a validator by id. -//! -//! ``` -//! use support::{decl_module, dispatch::Result}; -//! use system::ensure_signed; -//! use srml_staking::{self as staking}; -//! -//! pub trait Trait: staking::Trait {} -//! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! /// Reward a validator. -//! pub fn reward_myself(origin) -> Result { -//! let reported = ensure_signed(origin)?; -//! >::reward_by_ids(vec![(reported, 10)]); -//! Ok(()) -//! } -//! } -//! } -//! # fn main() { } -//! ``` -//! -//! ## Implementation Details -//! -//! ### Slot Stake -//! -//! The term [`SlotStake`](./struct.Module.html#method.slot_stake) will be used throughout this -//! section. It refers to a value calculated at the end of each era, containing the _minimum value -//! at stake among all validators._ Note that a validator's value at stake might be a combination -//! of the validator's own stake and the votes it received. See [`Exposure`](./struct.Exposure.html) -//! for more details. -//! -//! ### Reward Calculation -//! -//! Validators and nominators are rewarded at the end of each era. The total reward of an era is -//! calculated using the era duration and the staking rate (the total amount of tokens staked by -//! nominators and validators, divided by the total token supply). It aims to incentivise toward a -//! defined staking rate. The full specification can be found -//! [here](https://research.web3.foundation/en/latest/polkadot/Token%20Economics/#inflation-model). -//! -//! Total reward is split among validators and their nominators depending on the number of points -//! they received during the era. Points are added to a validator using -//! [`reward_by_ids`](./enum.Call.html#variant.reward_by_ids) or -//! [`reward_by_indices`](./enum.Call.html#variant.reward_by_indices). -//! -//! [`Module`](./struct.Module.html) implements -//! [`authorship::EventHandler`](../srml_authorship/trait.EventHandler.html) to add reward points -//! to block producer and block producer of referenced uncles. -//! -//! The validator and its nominator split their reward as following: -//! -//! The validator can declare an amount, named -//! [`validator_payment`](./struct.ValidatorPrefs.html#structfield.validator_payment), that does not -//! get shared with the nominators at each reward payout through its -//! [`ValidatorPrefs`](./struct.ValidatorPrefs.html). This value gets deducted from the total reward -//! that is paid to the validator and its nominators. The remaining portion is split among the -//! validator and all of the nominators that nominated the validator, proportional to the value -//! staked behind this validator (_i.e._ dividing the -//! [`own`](./struct.Exposure.html#structfield.own) or -//! [`others`](./struct.Exposure.html#structfield.others) by -//! [`total`](./struct.Exposure.html#structfield.total) in [`Exposure`](./struct.Exposure.html)). -//! -//! All entities who receive a reward have the option to choose their reward destination -//! through the [`Payee`](./struct.Payee.html) storage item (see -//! [`set_payee`](enum.Call.html#variant.set_payee)), to be one of the following: -//! -//! - Controller account, (obviously) not increasing the staked value. -//! - Stash account, not increasing the staked value. -//! - Stash account, also increasing the staked value. -//! -//! ### Additional Fund Management Operations -//! -//! Any funds already placed into stash can be the target of the following operations: -//! -//! The controller account can free a portion (or all) of the funds using the -//! [`unbond`](enum.Call.html#variant.unbond) call. Note that the funds are not immediately -//! accessible. Instead, a duration denoted by [`BondingDuration`](./struct.BondingDuration.html) -//! (in number of eras) must pass until the funds can actually be removed. Once the -//! `BondingDuration` is over, the [`withdraw_unbonded`](./enum.Call.html#variant.withdraw_unbonded) -//! call can be used to actually withdraw the funds. -//! -//! Note that there is a limitation to the number of fund-chunks that can be scheduled to be -//! unlocked in the future via [`unbond`](enum.Call.html#variant.unbond). In case this maximum -//! (`MAX_UNLOCKING_CHUNKS`) is reached, the bonded account _must_ first wait until a successful -//! call to `withdraw_unbonded` to remove some of the chunks. -//! -//! ### Election Algorithm -//! -//! The current election algorithm is implemented based on Phragmén. -//! The reference implementation can be found -//! [here](https://github.com/w3f/consensus/tree/master/NPoS). -//! -//! The election algorithm, aside from electing the validators with the most stake value and votes, -//! tries to divide the nominator votes among candidates in an equal manner. To further assure this, -//! an optional post-processing can be applied that iteratively normalizes the nominator staked -//! values until the total difference among votes of a particular nominator are less than a -//! threshold. -//! -//! ## GenesisConfig -//! -//! The Staking module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). -//! -//! ## Related Modules -//! -//! - [Balances](../srml_balances/index.html): Used to manage values at stake. -//! - [Session](../srml_session/index.html): Used to manage sessions. Also, a list of new validators -//! is stored in the Session module's `Validators` at the end of each era. - -#![recursion_limit="128"] -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -pub mod inflation; - -use rstd::{prelude::*, result}; -use codec::{HasCompact, Encode, Decode}; -use support::{ - decl_module, decl_event, decl_storage, ensure, - traits::{ - Currency, OnFreeBalanceZero, OnDilution, LockIdentifier, LockableCurrency, - WithdrawReasons, OnUnbalanced, Imbalance, Get, Time - } -}; -use session::{historical::OnSessionEnding, SelectInitialValidators}; -use sr_primitives::{ - Perbill, - RuntimeDebug, - curve::PiecewiseLinear, - weights::SimpleDispatchInfo, - traits::{ - Convert, Zero, One, StaticLookup, CheckedSub, Saturating, Bounded, SaturatedConversion, - } -}; -use sr_staking_primitives::{ - SessionIndex, - offence::{OnOffenceHandler, OffenceDetails, Offence, ReportOffence}, -}; -#[cfg(feature = "std")] -use sr_primitives::{Serialize, Deserialize}; -use system::{ensure_signed, ensure_root}; - -use phragmen::{elect, equalize, ExtendedBalance, Support, SupportMap, PhragmenStakedAssignment}; - -const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4; -const MAX_NOMINATIONS: usize = 16; -const MAX_UNLOCKING_CHUNKS: usize = 32; -const STAKING_ID: LockIdentifier = *b"staking "; - -/// Counter for the number of eras that have passed. -pub type EraIndex = u32; - -/// Counter for the number of "reward" points earned by a given validator. -pub type Points = u32; - -/// Reward points of an era. Used to split era total payout between validators. -#[derive(Encode, Decode, Default)] -pub struct EraPoints { - /// Total number of points. Equals the sum of reward points for each validator. - total: Points, - /// The reward points earned by a given validator. The index of this vec corresponds to the - /// index into the current validator set. - individual: Vec, -} - -impl EraPoints { - /// Add the reward to the validator at the given index. Index must be valid - /// (i.e. `index < current_elected.len()`). - fn add_points_to_index(&mut self, index: u32, points: u32) { - if let Some(new_total) = self.total.checked_add(points) { - self.total = new_total; - self.individual.resize((index as usize + 1).max(self.individual.len()), 0); - self.individual[index as usize] += points; // Addition is less than total - } - } -} - -/// Indicates the initial status of the staker. -#[derive(RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub enum StakerStatus { - /// Chilling. - Idle, - /// Declared desire in validating or already participating in it. - Validator, - /// Nominating for a group of other stakers. - Nominator(Vec), -} - -/// A destination account for payment. -#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug)] -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, RuntimeDebug)] -pub struct ValidatorPrefs { - /// Reward that validator takes up-front; only the rest is split between themselves and - /// nominators. - #[codec(compact)] - pub validator_payment: Balance, -} - -impl Default for ValidatorPrefs { - fn default() -> Self { - ValidatorPrefs { - validator_payment: Default::default(), - } - } -} - -/// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] -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: EraIndex, -} - -/// The ledger of a (bonded) stash. -#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] -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, -> 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: EraIndex) -> 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, RuntimeDebug)] -pub struct IndividualExposure { - /// The stash account of the nominator in question. - 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, RuntimeDebug)] -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>, -} - -/// A slashing event occurred, slashing a validator for a given amount of balance. -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default, RuntimeDebug)] -pub struct SlashJournalEntry { - who: AccountId, - amount: Balance, - own_slash: Balance, // the amount of `who`'s own exposure that was slashed -} - -pub type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; -type PositiveImbalanceOf = - <::Currency as Currency<::AccountId>>::PositiveImbalance; -type NegativeImbalanceOf = - <::Currency as Currency<::AccountId>>::NegativeImbalance; -type MomentOf= <::Time as Time>::Moment; - -/// Means for interacting with a specialized version of the `session` trait. -/// -/// This is needed because `Staking` sets the `ValidatorIdOf` of the `session::Trait` -pub trait SessionInterface: system::Trait { - /// Disable a given validator by stash ID. - /// - /// Returns `true` if new era should be forced at the end of this session. - /// This allows preventing a situation where there is too many validators - /// disabled and block production stalls. - fn disable_validator(validator: &AccountId) -> Result; - /// Get the validators from session. - fn validators() -> Vec; - /// Prune historical session tries up to but not including the given index. - fn prune_historical_up_to(up_to: SessionIndex); -} - -impl SessionInterface<::AccountId> for T where - T: session::Trait::AccountId>, - T: session::historical::Trait< - FullIdentification = Exposure<::AccountId, BalanceOf>, - FullIdentificationOf = ExposureOf, - >, - T::SessionHandler: session::SessionHandler<::AccountId>, - T::OnSessionEnding: session::OnSessionEnding<::AccountId>, - T::SelectInitialValidators: session::SelectInitialValidators<::AccountId>, - T::ValidatorIdOf: Convert<::AccountId, Option<::AccountId>> -{ - fn disable_validator(validator: &::AccountId) -> Result { - >::disable(validator) - } - - fn validators() -> Vec<::AccountId> { - >::validators() - } - - fn prune_historical_up_to(up_to: SessionIndex) { - >::prune_up_to(up_to); - } -} - -pub trait Trait: system::Trait { - /// The staking balance. - type Currency: LockableCurrency; - - /// Time used for computing era duration. - type Time: Time; - - /// Convert a balance into a number used for election calculation. - /// This must fit into a `u64` but is allowed to be sensibly lossy. - /// TODO: #1377 - /// The backward convert should be removed as the new Phragmen API returns ratio. - /// The post-processing needs it but will be moved to off-chain. TODO: #2908 - type CurrencyToVote: Convert, u64> + Convert>; - - /// Some tokens minted. - type OnRewardMinted: OnDilution>; - - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// Handler for the unbalanced reduction when slashing a staker. - type Slash: OnUnbalanced>; - - /// Handler for the unbalanced increment when rewarding a staker. - type Reward: OnUnbalanced>; - - /// Number of sessions per era. - type SessionsPerEra: Get; - - /// Number of eras that staked funds must remain bonded for. - type BondingDuration: Get; - - /// Interface for interacting with a session module. - type SessionInterface: self::SessionInterface; - - /// The NPoS reward curve to use. - type RewardCurve: Get<&'static PiecewiseLinear<'static>>; -} - -/// Mode of era-forcing. -#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub enum Forcing { - /// Not forcing anything - just let whatever happen. - NotForcing, - /// Force a new era, then reset to `NotForcing` as soon as it is done. - ForceNew, - /// Avoid a new era indefinitely. - ForceNone, -} - -impl Default for Forcing { - fn default() -> Self { Forcing::NotForcing } -} - -decl_storage! { - trait Store for Module as Staking { - - /// The ideal number of staking participants. - pub ValidatorCount get(fn validator_count) config(): u32; - /// Minimum number of staking participants before emergency conditions are imposed. - pub MinimumValidatorCount get(fn minimum_validator_count) config(): - u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT; - - /// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're - /// easy to initialize and the performance hit is minimal (we expect no more than four - /// invulnerables) and restricted to testnets. - pub Invulnerables get(fn invulnerables) config(): Vec; - - /// Map from all locked "stash" accounts to the controller account. - pub Bonded get(fn bonded): map T::AccountId => Option; - /// Map from all (unlocked) "controller" accounts to the info regarding the staking. - pub Ledger get(fn ledger): - map T::AccountId => Option>>; - - /// Where the reward payment should be made. Keyed by stash. - pub Payee get(fn payee): map T::AccountId => RewardDestination; - - /// The map from (wannabe) validator stash key to the preferences of that validator. - pub Validators get(fn validators): linked_map T::AccountId => ValidatorPrefs>; - - /// The map from nominator stash key to the set of stash keys of all validators to nominate. - pub Nominators get(fn nominators): linked_map T::AccountId => Vec; - - /// Nominators for a particular account that is in action right now. You can't iterate - /// through validators here, but you can find them in the Session module. - /// - /// This is keyed by the stash account. - pub Stakers get(fn stakers): map T::AccountId => Exposure>; - - /// The currently elected validator set keyed by stash account ID. - pub CurrentElected get(fn current_elected): Vec; - - /// The current era index. - pub CurrentEra get(fn current_era) config(): EraIndex; - - /// The start of the current era. - pub CurrentEraStart get(fn current_era_start): MomentOf; - - /// The session index at which the current era started. - pub CurrentEraStartSessionIndex get(fn current_era_start_session_index): SessionIndex; - - /// Rewards for the current era. Using indices of current elected set. - CurrentEraPointsEarned get(fn current_era_reward): EraPoints; - - /// The amount of balance actively at stake for each validator slot, currently. - /// - /// This is used to derive rewards and punishments. - pub SlotStake get(fn slot_stake) build(|config: &GenesisConfig| { - config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() - }): BalanceOf; - - /// True if the next session change will be a new era regardless of index. - pub ForceEra get(fn force_era) config(): Forcing; - - /// The percentage of the slash that is distributed to reporters. - /// - /// The rest of the slashed value is handled by the `Slash`. - pub SlashRewardFraction get(fn slash_reward_fraction) config(): Perbill; - - /// A mapping from still-bonded eras to the first session index of that era. - BondedEras: Vec<(EraIndex, SessionIndex)>; - - /// All slashes that have occurred in a given era. - EraSlashJournal get(fn era_slash_journal): - map EraIndex => Vec>>; - } - add_extra_genesis { - config(stakers): - Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; - build(|config: &GenesisConfig| { - for &(ref stash, ref controller, balance, ref status) in &config.stakers { - assert!( - T::Currency::free_balance(&stash) >= balance, - "Stash does not have enough balance to bond." - ); - let _ = >::bond( - T::Origin::from(Some(stash.clone()).into()), - T::Lookup::unlookup(controller.clone()), - balance, - RewardDestination::Staked, - ); - let _ = match status { - StakerStatus::Validator => { - >::validate( - T::Origin::from(Some(controller.clone()).into()), - Default::default(), - ) - }, - StakerStatus::Nominator(votes) => { - >::nominate( - T::Origin::from(Some(controller.clone()).into()), - votes.iter().map(|l| T::Lookup::unlookup(l.clone())).collect(), - ) - }, _ => Ok(()) - }; - } - }); - } -} - -decl_event!( - pub enum Event where Balance = BalanceOf, ::AccountId { - /// All validators have been rewarded by the given balance. - Reward(Balance), - /// One validator (and its nominators) has been slashed by the given amount. - Slash(AccountId, Balance), - /// An old slashing report from a prior era was discarded because it could - /// not be processed. - OldSlashingReportDiscarded(SessionIndex), - } -); - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// Number of sessions per era. - const SessionsPerEra: SessionIndex = T::SessionsPerEra::get(); - - /// Number of eras that staked funds must remain bonded for. - const BondingDuration: EraIndex = T::BondingDuration::get(); - - fn deposit_event() = default; - - fn on_finalize() { - // Set the start of the first era. - if !>::exists() { - >::put(T::Time::now()); - } - } - - /// Take the origin account as a stash and lock up `value` of its balance. `controller` will - /// be the account that controls it. - /// - /// `value` must be more than the `minimum_balance` specified by `T::Currency`. - /// - /// The dispatch origin for this call must be _Signed_ by the stash account. - /// - /// # - /// - Independent of the arguments. Moderate complexity. - /// - O(1). - /// - Three extra DB entries. - /// - /// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned unless - /// the `origin` falls below _existential deposit_ and gets removed as dust. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn bond(origin, - controller: ::Source, - #[compact] value: BalanceOf, - payee: RewardDestination - ) { - let stash = ensure_signed(origin)?; - - if >::exists(&stash) { - return Err("stash already bonded") - } - - let controller = T::Lookup::lookup(controller)?; - - if >::exists(&controller) { - return Err("controller already paired") - } - - // reject a bond which is considered to be _dust_. - if value < T::Currency::minimum_balance() { - return Err("can not bond with value less than minimum balance") - } - - // You're auto-bonded forever, here. We might improve this by only bonding when - // you actually validate/nominate and remove once you unbond __everything__. - >::insert(&stash, &controller); - >::insert(&stash, payee); - - let stash_balance = T::Currency::free_balance(&stash); - let value = value.min(stash_balance); - let item = StakingLedger { stash, total: value, active: value, unlocking: vec![] }; - Self::update_ledger(&controller, &item); - } - - /// Add some extra amount that have appeared in the stash `free_balance` into the balance up - /// for staking. - /// - /// Use this if there are additional funds in your stash account that you wish to bond. - /// Unlike [`bond`] or [`unbond`] this function does not impose any limitation on the amount - /// that can be added. - /// - /// The dispatch origin for this call must be _Signed_ by the stash, not the controller. - /// - /// # - /// - Independent of the arguments. Insignificant complexity. - /// - O(1). - /// - One DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn bond_extra(origin, #[compact] max_additional: BalanceOf) { - let stash = ensure_signed(origin)?; - - let controller = Self::bonded(&stash).ok_or("not a stash")?; - let mut ledger = Self::ledger(&controller).ok_or("not a controller")?; - - let stash_balance = T::Currency::free_balance(&stash); - - if let Some(extra) = stash_balance.checked_sub(&ledger.total) { - let extra = extra.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::minimum_balance(), then it is increased to the full amount. - /// - /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move - /// the funds out of management ready for transfer. - /// - /// No more than a limited number of unlocking chunks (see `MAX_UNLOCKING_CHUNKS`) - /// can co-exists at the same time. In that case, [`Call::withdraw_unbonded`] need - /// to be called first to remove some of the chunks (if possible). - /// - /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. - /// - /// See also [`Call::withdraw_unbonded`]. - /// - /// # - /// - Independent of the arguments. Limited but potentially exploitable complexity. - /// - Contains a limited number of reads. - /// - Each call (requires the remainder of the bonded balance to be above `minimum_balance`) - /// will cause a new entry to be inserted into a vector (`Ledger.unlocking`) kept in storage. - /// The only way to clean the aforementioned storage item is also user-controlled via `withdraw_unbonded`. - /// - One DB entry. - /// - #[weight = SimpleDispatchInfo::FixedNormal(400_000)] - fn unbond(origin, #[compact] value: BalanceOf) { - let controller = ensure_signed(origin)?; - let mut ledger = Self::ledger(&controller).ok_or("not a controller")?; - ensure!( - ledger.unlocking.len() < MAX_UNLOCKING_CHUNKS, - "can not schedule more unlock chunks" - ); - - 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. - if ledger.active < T::Currency::minimum_balance() { - value += ledger.active; - ledger.active = Zero::zero(); - } - - let era = Self::current_era() + T::BondingDuration::get(); - 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. - /// - /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. - /// - /// See also [`Call::unbond`]. - /// - /// # - /// - Could be dependent on the `origin` argument and how much `unlocking` chunks exist. - /// It implies `consolidate_unlocked` which loops over `Ledger.unlocking`, which is - /// indirectly user-controlled. See [`unbond`] for more detail. - /// - Contains a limited number of reads, yet the size of which could be large based on `ledger`. - /// - Writes are limited to the `origin` account key. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(400_000)] - 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()); - - if ledger.unlocking.is_empty() && ledger.active.is_zero() { - // This account must have called `unbond()` with some value that caused the active - // portion to fall below existential deposit + will have no more unlocking chunks - // left. We can now safely remove this. - let stash = ledger.stash; - // remove the lock. - T::Currency::remove_lock(STAKING_ID, &stash); - // remove all staking-related information. - Self::kill_stash(&stash); - } else { - // This was the consequence of a partial unbond. just update the ledger and move on. - 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. - /// - /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. - /// - /// # - /// - Independent of the arguments. Insignificant complexity. - /// - Contains a limited number of reads. - /// - Writes are limited to the `origin` account key. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(750_000)] - fn validate(origin, prefs: ValidatorPrefs>) { - let controller = ensure_signed(origin)?; - let ledger = Self::ledger(&controller).ok_or("not a controller")?; - let stash = &ledger.stash; - >::remove(stash); - >::insert(stash, prefs); - } - - /// Declare the desire to nominate `targets` for the origin controller. - /// - /// Effects will be felt at the beginning of the next era. - /// - /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. - /// - /// # - /// - The transaction's complexity is proportional to the size of `targets`, - /// which is capped at `MAX_NOMINATIONS`. - /// - Both the reads and writes follow a similar pattern. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(750_000)] - fn nominate(origin, targets: Vec<::Source>) { - let controller = ensure_signed(origin)?; - let ledger = Self::ledger(&controller).ok_or("not a controller")?; - let stash = &ledger.stash; - ensure!(!targets.is_empty(), "targets cannot be empty"); - let targets = targets.into_iter() - .take(MAX_NOMINATIONS) - .map(|t| T::Lookup::lookup(t)) - .collect::, _>>()?; - - >::remove(stash); - >::insert(stash, targets); - } - - /// Declare no desire to either validate or nominate. - /// - /// Effects will be felt at the beginning of the next era. - /// - /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. - /// - /// # - /// - Independent of the arguments. Insignificant complexity. - /// - Contains one read. - /// - Writes are limited to the `origin` account key. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn chill(origin) { - let controller = ensure_signed(origin)?; - let ledger = Self::ledger(&controller).ok_or("not a controller")?; - let stash = &ledger.stash; - >::remove(stash); - >::remove(stash); - } - - /// (Re-)set the payment target for a controller. - /// - /// Effects will be felt at the beginning of the next era. - /// - /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. - /// - /// # - /// - Independent of the arguments. Insignificant complexity. - /// - Contains a limited number of reads. - /// - Writes are limited to the `origin` account key. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn set_payee(origin, payee: RewardDestination) { - let controller = ensure_signed(origin)?; - let ledger = Self::ledger(&controller).ok_or("not a controller")?; - let stash = &ledger.stash; - >::insert(stash, payee); - } - - /// (Re-)set the controller of a stash. - /// - /// Effects will be felt at the beginning of the next era. - /// - /// The dispatch origin for this call must be _Signed_ by the stash, not the controller. - /// - /// # - /// - Independent of the arguments. Insignificant complexity. - /// - Contains a limited number of reads. - /// - Writes are limited to the `origin` account key. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(750_000)] - fn set_controller(origin, controller: ::Source) { - let stash = ensure_signed(origin)?; - let old_controller = Self::bonded(&stash).ok_or("not a stash")?; - let controller = T::Lookup::lookup(controller)?; - if >::exists(&controller) { - return Err("controller already paired") - } - if controller != old_controller { - >::insert(&stash, &controller); - if let Some(l) = >::take(&old_controller) { - >::insert(&controller, l); - } - } - } - - /// The ideal number of validators. - #[weight = SimpleDispatchInfo::FixedOperational(150_000)] - fn set_validator_count(origin, #[compact] new: u32) { - ensure_root(origin)?; - ValidatorCount::put(new); - } - - // ----- Root calls. - - /// Force there to be no new eras indefinitely. - /// - /// # - /// - No arguments. - /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn force_no_eras(origin) { - ensure_root(origin)?; - ForceEra::put(Forcing::ForceNone); - } - - /// Force there to be a new era at the end of the next session. After this, it will be - /// reset to normal (non-forced) behaviour. - /// - /// # - /// - No arguments. - /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn force_new_era(origin) { - ensure_root(origin)?; - ForceEra::put(Forcing::ForceNew); - } - - /// Set the validators who cannot be slashed (if any). - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_invulnerables(origin, validators: Vec) { - ensure_root(origin)?; - >::put(validators); - } - - /// Force a current staker to become completely unstaked, immediately. - #[weight = SimpleDispatchInfo::FreeOperational] - fn force_unstake(origin, stash: T::AccountId) { - ensure_root(origin)?; - - // remove the lock. - T::Currency::remove_lock(STAKING_ID, &stash); - // remove all staking-related information. - Self::kill_stash(&stash); - } - } -} - -impl Module { - // PUBLIC IMMUTABLES - - /// The total balance that can be slashed from a validator controller account as of - /// right now. - pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { - Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default() - } - - // MUTABLES (DANGEROUS) - - /// Update the ledger for a controller. This will also update the stash lock. The lock will - /// will lock the entire funds except paying for further transactions. - fn update_ledger( - controller: &T::AccountId, - ledger: &StakingLedger> - ) { - T::Currency::set_lock( - STAKING_ID, - &ledger.stash, - ledger.total, - T::BlockNumber::max_value(), - WithdrawReasons::all(), - ); - >::insert(controller, ledger); - } - - /// Slash a given validator by a specific amount with given (historical) exposure. - /// - /// Removes the slash from the validator's balance by preference, - /// and reduces the nominators' balance if needed. - /// - /// Returns the resulting `NegativeImbalance` to allow distributing the slashed amount and - /// pushes an entry onto the slash journal. - fn slash_validator( - stash: &T::AccountId, - slash: BalanceOf, - exposure: &Exposure>, - journal: &mut Vec>>, - ) -> NegativeImbalanceOf { - // The amount we are actually going to slash (can't be bigger than the validator's total - // exposure) - let slash = slash.min(exposure.total); - - // limit what we'll slash of the stash's own to only what's in - // the exposure. - // - // note: this is fine only because we limit reports of the current era. - // otherwise, these funds may have already been slashed due to something - // reported from a prior era. - let already_slashed_own = journal.iter() - .filter(|entry| &entry.who == stash) - .map(|entry| entry.own_slash) - .fold(>::zero(), |a, c| a.saturating_add(c)); - - let own_remaining = exposure.own.saturating_sub(already_slashed_own); - - // The amount we'll slash from the validator's stash directly. - let own_slash = own_remaining.min(slash); - let (mut imbalance, missing) = T::Currency::slash(stash, own_slash); - let own_slash = own_slash - missing; - // The amount remaining that we can't slash from the validator, - // that must be taken from the nominators. - 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() { - for i in exposure.others.iter() { - let per_u64 = Perbill::from_rational_approximation(i.value, total); - // best effort - not much that can be done on fail. - imbalance.subsume(T::Currency::slash(&i.who, per_u64 * rest_slash).0) - } - } - } - - journal.push(SlashJournalEntry { - who: stash.clone(), - own_slash: own_slash.clone(), - amount: slash, - }); - - // trigger the event - Self::deposit_event( - RawEvent::Slash(stash.clone(), slash) - ); - - imbalance - } - - /// Actually make a payment to a staker. This uses the currency's reward function - /// to pay the right payee for the given staker account. - fn make_payout(stash: &T::AccountId, amount: BalanceOf) -> Option> { - let dest = Self::payee(stash); - match dest { - RewardDestination::Controller => Self::bonded(stash) - .and_then(|controller| - T::Currency::deposit_into_existing(&controller, amount).ok() - ), - RewardDestination::Stash => - T::Currency::deposit_into_existing(stash, amount).ok(), - RewardDestination::Staked => Self::bonded(stash) - .and_then(|c| Self::ledger(&c).map(|l| (c, l))) - .and_then(|(controller, mut l)| { - l.active += amount; - l.total += amount; - let r = T::Currency::deposit_into_existing(stash, amount).ok(); - Self::update_ledger(&controller, &l); - r - }), - } - } - - /// Reward a given validator by a specific amount. Add the reward to the validator's, and its - /// nominators' balance, pro-rata based on their exposure, after having removed the validator's - /// pre-payout cut. - fn reward_validator(stash: &T::AccountId, reward: BalanceOf) -> PositiveImbalanceOf { - let off_the_table = reward.min(Self::validators(stash).validator_payment); - let reward = reward - off_the_table; - let mut imbalance = >::zero(); - let validator_cut = if reward.is_zero() { - Zero::zero() - } else { - let exposure = Self::stakers(stash); - let total = exposure.total.max(One::one()); - - for i in &exposure.others { - let per_u64 = Perbill::from_rational_approximation(i.value, total); - imbalance.maybe_subsume(Self::make_payout(&i.who, per_u64 * reward)); - } - - let per_u64 = Perbill::from_rational_approximation(exposure.own, total); - per_u64 * reward - }; - - imbalance.maybe_subsume(Self::make_payout(stash, validator_cut + off_the_table)); - - imbalance - } - - /// Session has just ended. Provide the validator set for the next session if it's an era-end, along - /// with the exposure of the prior validator set. - fn new_session(session_index: SessionIndex) - -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> - { - let era_length = session_index.checked_sub(Self::current_era_start_session_index()).unwrap_or(0); - match ForceEra::get() { - Forcing::ForceNew => ForceEra::kill(), - Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (), - _ => return None, - } - let validators = T::SessionInterface::validators(); - let prior = validators.into_iter() - .map(|v| { let e = Self::stakers(&v); (v, e) }) - .collect(); - - Self::new_era(session_index).map(move |new| (new, prior)) - } - - /// The era has changed - enact new staking set. - /// - /// 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(start_session_index: SessionIndex) -> Option> { - // Payout - let points = CurrentEraPointsEarned::take(); - let now = T::Time::now(); - let previous_era_start = >::mutate(|v| { - rstd::mem::replace(v, now) - }); - let era_duration = now - previous_era_start; - if !era_duration.is_zero() { - let validators = Self::current_elected(); - - let validator_len: BalanceOf = (validators.len() as u32).into(); - let total_rewarded_stake = Self::slot_stake() * validator_len; - - let total_payout = inflation::compute_total_payout( - &T::RewardCurve::get(), - total_rewarded_stake.clone(), - T::Currency::total_issuance(), - // Duration of era; more than u64::MAX is rewarded as u64::MAX. - era_duration.saturated_into::(), - ); - - let mut total_imbalance = >::zero(); - - for (v, p) in validators.iter().zip(points.individual.into_iter()) { - if p != 0 { - let reward = Perbill::from_rational_approximation(p, points.total) * total_payout; - total_imbalance.subsume(Self::reward_validator(v, reward)); - } - } - - let total_reward = total_imbalance.peek(); - // assert!(total_reward <= total_payout) - - Self::deposit_event(RawEvent::Reward(total_reward)); - T::Reward::on_unbalanced(total_imbalance); - T::OnRewardMinted::on_dilution(total_reward, total_rewarded_stake); - } - - // Increment current era. - let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); - - // prune journal for last era. - >::remove(current_era - 1); - - CurrentEraStartSessionIndex::mutate(|v| { - *v = start_session_index; - }); - let bonding_duration = T::BondingDuration::get(); - - if current_era > bonding_duration { - let first_kept = current_era - bonding_duration; - BondedEras::mutate(|bonded| { - bonded.push((current_era, start_session_index)); - - // prune out everything that's from before the first-kept index. - let n_to_prune = bonded.iter() - .take_while(|&&(era_idx, _)| era_idx < first_kept) - .count(); - - bonded.drain(..n_to_prune); - - if let Some(&(_, first_session)) = bonded.first() { - T::SessionInterface::prune_historical_up_to(first_session); - } - }) - } - - // Reassign all Stakers. - let (_slot_stake, maybe_new_validators) = Self::select_validators(); - - maybe_new_validators - } - - /// Select a new validator set from the assembled stakers and their role preferences. - /// - /// Returns the new `SlotStake` value and a set of newly selected _stash_ IDs. - fn select_validators() -> (BalanceOf, Option>) { - let maybe_phragmen_result = elect::<_, _, _, T::CurrencyToVote>( - Self::validator_count() as usize, - Self::minimum_validator_count().max(1) as usize, - >::enumerate().map(|(who, _)| who).collect::>(), - >::enumerate().collect(), - Self::slashable_balance_of, - true, - ); - - if let Some(phragmen_result) = maybe_phragmen_result { - let elected_stashes = phragmen_result.winners.iter() - .map(|(s, _)| s.clone()) - .collect::>(); - let assignments = phragmen_result.assignments; - - let to_votes = |b: BalanceOf| - , u64>>::convert(b) as ExtendedBalance; - let to_balance = |e: ExtendedBalance| - >>::convert(e); - - // Initialize the support of each candidate. - let mut supports = >::new(); - elected_stashes - .iter() - .map(|e| (e, to_votes(Self::slashable_balance_of(e)))) - .for_each(|(e, s)| { - let item = Support { own: s, total: s, ..Default::default() }; - supports.insert(e.clone(), item); - }); - - // build support struct. - for (n, assignment) in assignments.iter() { - for (c, per_thing) in assignment.iter() { - let nominator_stake = to_votes(Self::slashable_balance_of(n)); - // AUDIT: it is crucially important for the `Mul` implementation of all - // per-things to be sound. - let other_stake = *per_thing * nominator_stake; - if let Some(support) = supports.get_mut(c) { - // For an astronomically rich validator with more astronomically rich - // set of nominators, this might saturate. - support.total = support.total.saturating_add(other_stake); - support.others.push((n.clone(), other_stake)); - } - } - } - - if cfg!(feature = "equalize") { - let mut staked_assignments - : Vec<(T::AccountId, Vec>)> - = Vec::with_capacity(assignments.len()); - for (n, assignment) in assignments.iter() { - let mut staked_assignment - : Vec> - = Vec::with_capacity(assignment.len()); - for (c, per_thing) in assignment.iter() { - let nominator_stake = to_votes(Self::slashable_balance_of(n)); - let other_stake = *per_thing * nominator_stake; - staked_assignment.push((c.clone(), other_stake)); - } - staked_assignments.push((n.clone(), staked_assignment)); - } - - let tolerance = 0_u128; - let iterations = 2_usize; - equalize::<_, _, T::CurrencyToVote, _>( - staked_assignments, - &mut supports, - tolerance, - iterations, - Self::slashable_balance_of, - ); - } - - // Clear Stakers. - for v in Self::current_elected().iter() { - >::remove(v); - } - - // Populate Stakers and figure out the minimum stake behind a slot. - let mut slot_stake = BalanceOf::::max_value(); - for (c, s) in supports.into_iter() { - // build `struct exposure` from `support` - let exposure = Exposure { - own: to_balance(s.own), - // This might reasonably saturate and we cannot do much about it. The sum of - // someone's stake might exceed the balance type if they have the maximum amount - // of balance and receive some support. This is super unlikely to happen, yet - // we simulate it in some tests. - total: to_balance(s.total), - others: s.others - .into_iter() - .map(|(who, value)| IndividualExposure { who, value: to_balance(value) }) - .collect::>>(), - }; - if exposure.total < slot_stake { - slot_stake = exposure.total; - } - >::insert(&c, exposure.clone()); - } - - // Update slot stake. - >::put(&slot_stake); - - // Set the new validator set in sessions. - >::put(&elected_stashes); - - // In order to keep the property required by `n_session_ending` - // that we must return the new validator set even if it's the same as the old, - // as long as any underlying economic conditions have changed, we don't attempt - // to do any optimization where we compare against the prior set. - (slot_stake, Some(elected_stashes)) - } else { - // There were not enough candidates for even our minimal level of functionality. - // This is bad. - // We should probably disable all functionality except for block production - // and let the chain keep producing blocks until we can decide on a sufficiently - // substantial set. - // TODO: #2494 - (Self::slot_stake(), None) - } - } - - /// Remove all associated data of a stash account from the staking system. - /// - /// This is called : - /// - Immediately when an account's balance falls below existential deposit. - /// - after a `withdraw_unbond()` call that frees all of a stash's bonded balance. - fn kill_stash(stash: &T::AccountId) { - if let Some(controller) = >::take(stash) { - >::remove(&controller); - } - >::remove(stash); - >::remove(stash); - >::remove(stash); - } - - /// Add reward points to validators using their stash account ID. - /// - /// Validators are keyed by stash account ID and must be in the current elected set. - /// - /// For each element in the iterator the given number of points in u32 is added to the - /// validator, thus duplicates are handled. - /// - /// At the end of the era each the total payout will be distributed among validator - /// relatively to their points. - /// - /// COMPLEXITY: Complexity is `number_of_validator_to_reward x current_elected_len`. - /// If you need to reward lots of validator consider using `reward_by_indices`. - pub fn reward_by_ids(validators_points: impl IntoIterator) { - CurrentEraPointsEarned::mutate(|rewards| { - let current_elected = >::current_elected(); - for (validator, points) in validators_points.into_iter() { - if let Some(index) = current_elected.iter() - .position(|elected| *elected == validator) - { - rewards.add_points_to_index(index as u32, points); - } - } - }); - } - - /// Add reward points to validators using their validator index. - /// - /// For each element in the iterator the given number of points in u32 is added to the - /// validator, thus duplicates are handled. - pub fn reward_by_indices(validators_points: impl IntoIterator) { - // TODO: This can be optimised once #3302 is implemented. - let current_elected_len = >::current_elected().len() as u32; - - CurrentEraPointsEarned::mutate(|rewards| { - for (validator_index, points) in validators_points.into_iter() { - if validator_index < current_elected_len { - rewards.add_points_to_index(validator_index, points); - } - } - }); - } -} - -impl session::OnSessionEnding for Module { - fn on_session_ending(_ending: SessionIndex, start_session: SessionIndex) -> Option> { - Self::new_session(start_session - 1).map(|(new, _old)| new) - } -} - -impl OnSessionEnding>> for Module { - fn on_session_ending(_ending: SessionIndex, start_session: SessionIndex) - -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> - { - Self::new_session(start_session - 1) - } -} - -impl OnFreeBalanceZero for Module { - fn on_free_balance_zero(stash: &T::AccountId) { - Self::kill_stash(stash); - } -} - -/// Add reward points to block authors: -/// * 20 points to the block producer for producing a (non-uncle) block in the relay chain, -/// * 2 points to the block producer for each reference to a previously unreferenced uncle, and -/// * 1 point to the producer of each referenced uncle block. -impl authorship::EventHandler for Module { - fn note_author(author: T::AccountId) { - Self::reward_by_ids(vec![(author, 20)]); - } - fn note_uncle(author: T::AccountId, _age: T::BlockNumber) { - Self::reward_by_ids(vec![ - (>::author(), 2), - (author, 1) - ]) - } -} - -/// A `Convert` implementation that finds the stash of the given controller account, -/// if any. -pub struct StashOf(rstd::marker::PhantomData); - -impl Convert> for StashOf { - fn convert(controller: T::AccountId) -> Option { - >::ledger(&controller).map(|l| l.stash) - } -} - -/// A typed conversion from stash account ID to the current exposure of nominators -/// on that account. -pub struct ExposureOf(rstd::marker::PhantomData); - -impl Convert>>> - for ExposureOf -{ - fn convert(validator: T::AccountId) -> Option>> { - Some(>::stakers(&validator)) - } -} - -impl SelectInitialValidators for Module { - fn select_initial_validators() -> Option> { - >::select_validators().1 - } -} - -/// This is intended to be used with `FilterHistoricalOffences`. -impl OnOffenceHandler> for Module where - T: session::Trait::AccountId>, - T: session::historical::Trait< - FullIdentification = Exposure<::AccountId, BalanceOf>, - FullIdentificationOf = ExposureOf, - >, - T::SessionHandler: session::SessionHandler<::AccountId>, - T::OnSessionEnding: session::OnSessionEnding<::AccountId>, - T::SelectInitialValidators: session::SelectInitialValidators<::AccountId>, - T::ValidatorIdOf: Convert<::AccountId, Option<::AccountId>> -{ - fn on_offence( - offenders: &[OffenceDetails>], - slash_fraction: &[Perbill], - ) { - let mut remaining_imbalance = >::zero(); - let slash_reward_fraction = SlashRewardFraction::get(); - - let era_now = Self::current_era(); - let mut journal = Self::era_slash_journal(era_now); - for (details, slash_fraction) in offenders.iter().zip(slash_fraction) { - let stash = &details.offender.0; - let exposure = &details.offender.1; - - // Skip if the validator is invulnerable. - if Self::invulnerables().contains(stash) { - continue - } - - // calculate the amount to slash - let slash_exposure = exposure.total; - let amount = *slash_fraction * slash_exposure; - // in some cases `slash_fraction` can be just `0`, - // which means we are not slashing this time. - if amount.is_zero() { - continue; - } - - // make sure to disable validator till the end of this session - if T::SessionInterface::disable_validator(stash).unwrap_or(false) { - // force a new era, to select a new validator set - ForceEra::put(Forcing::ForceNew); - } - // actually slash the validator - let slashed_amount = Self::slash_validator(stash, amount, exposure, &mut journal); - - // distribute the rewards according to the slash - let slash_reward = slash_reward_fraction * slashed_amount.peek(); - if !slash_reward.is_zero() && !details.reporters.is_empty() { - let (mut reward, rest) = slashed_amount.split(slash_reward); - // split the reward between reporters equally. Division cannot fail because - // we guarded against it in the enclosing if. - let per_reporter = reward.peek() / (details.reporters.len() as u32).into(); - for reporter in &details.reporters { - let (reporter_reward, rest) = reward.split(per_reporter); - reward = rest; - T::Currency::resolve_creating(reporter, reporter_reward); - } - // The rest goes to the treasury. - remaining_imbalance.subsume(reward); - remaining_imbalance.subsume(rest); - } else { - remaining_imbalance.subsume(slashed_amount); - } - } - >::insert(era_now, journal); - - // Handle the rest of imbalances - T::Slash::on_unbalanced(remaining_imbalance); - } -} - -/// Filter historical offences out and only allow those from the current era. -pub struct FilterHistoricalOffences { - _inner: rstd::marker::PhantomData<(T, R)>, -} - -impl ReportOffence - for FilterHistoricalOffences, R> where - T: Trait, - R: ReportOffence, - O: Offence, -{ - fn report_offence(reporters: Vec, offence: O) { - // disallow any slashing from before the current era. - let offence_session = offence.session_index(); - if offence_session >= >::current_era_start_session_index() { - R::report_offence(reporters, offence) - } else { - >::deposit_event( - RawEvent::OldSlashingReportDiscarded(offence_session) - ) - } - } -} diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs deleted file mode 100644 index 41a2ad4802097..0000000000000 --- a/srml/staking/src/mock.rs +++ /dev/null @@ -1,453 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test utilities - -use std::{collections::HashSet, cell::RefCell}; -use sr_primitives::Perbill; -use sr_primitives::curve::PiecewiseLinear; -use sr_primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize, SaturatedConversion}; -use sr_primitives::testing::{Header, UintAuthorityId}; -use sr_staking_primitives::SessionIndex; -use primitives::H256; -use runtime_io; -use support::{assert_ok, impl_outer_origin, parameter_types, StorageLinkedMap}; -use support::traits::{Currency, Get, FindAuthor}; -use crate::{ - EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination, - Nominators, inflation -}; - -/// The AccountId alias in this test module. -pub type AccountId = u64; -pub type BlockNumber = u64; -pub type Balance = u64; - -/// Simple structure that exposes how u64 currency can be represented as... u64. -pub struct CurrencyToVoteHandler; -impl Convert for CurrencyToVoteHandler { - fn convert(x: u64) -> u64 { x } -} -impl Convert for CurrencyToVoteHandler { - fn convert(x: u128) -> u64 { x.saturated_into() } -} - -thread_local! { - static SESSION: RefCell<(Vec, HashSet)> = RefCell::new(Default::default()); - static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); -} - -pub struct TestSessionHandler; -impl session::SessionHandler for TestSessionHandler { - fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} - - fn on_new_session( - _changed: bool, - validators: &[(AccountId, Ks)], - _queued_validators: &[(AccountId, Ks)], - ) { - SESSION.with(|x| - *x.borrow_mut() = (validators.iter().map(|x| x.0.clone()).collect(), HashSet::new()) - ); - } - - fn on_disabled(validator_index: usize) { - SESSION.with(|d| { - let mut d = d.borrow_mut(); - let value = d.0[validator_index]; - d.1.insert(value); - }) - } -} - -pub fn is_disabled(controller: AccountId) -> bool { - let stash = Staking::ledger(&controller).unwrap().stash; - SESSION.with(|d| d.borrow().1.contains(&stash)) -} - -pub struct ExistentialDeposit; -impl Get for ExistentialDeposit { - fn get() -> u64 { - EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) - } -} - -impl_outer_origin!{ - pub enum Origin for Test {} -} - -/// Author of block is always 11 -pub struct Author11; -impl FindAuthor for Author11 { - fn find_author<'a, I>(_digests: I) -> Option - where I: 'a + IntoIterator - { - Some(11) - } -} - -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Test; -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = BlockNumber; - type Call = (); - type Hash = H256; - type Hashing = ::sr_primitives::traits::BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); -} -parameter_types! { - pub const TransferFee: Balance = 0; - pub const CreationFee: Balance = 0; -} -impl balances::Trait for Test { - type Balance = Balance; - type OnFreeBalanceZero = Staking; - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} -parameter_types! { - pub const Period: BlockNumber = 1; - pub const Offset: BlockNumber = 0; - pub const UncleGenerations: u64 = 0; - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(25); -} -impl session::Trait for Test { - type OnSessionEnding = session::historical::NoteHistoricalRoot; - type Keys = UintAuthorityId; - type ShouldEndSession = session::PeriodicSessions; - type SessionHandler = TestSessionHandler; - type Event = (); - type ValidatorId = AccountId; - type ValidatorIdOf = crate::StashOf; - type SelectInitialValidators = Staking; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; -} - -impl session::historical::Trait for Test { - type FullIdentification = crate::Exposure; - type FullIdentificationOf = crate::ExposureOf; -} -impl authorship::Trait for Test { - type FindAuthor = Author11; - type UncleGenerations = UncleGenerations; - type FilterUncle = (); - type EventHandler = Module; -} -parameter_types! { - pub const MinimumPeriod: u64 = 5; -} -impl timestamp::Trait for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; -} -srml_staking_reward_curve::build! { - const I_NPOS: PiecewiseLinear<'static> = curve!( - min_inflation: 0_025_000, - max_inflation: 0_100_000, - ideal_stake: 0_500_000, - falloff: 0_050_000, - max_piece_count: 40, - test_precision: 0_005_000, - ); -} -parameter_types! { - pub const SessionsPerEra: SessionIndex = 3; - pub const BondingDuration: EraIndex = 3; - pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS; -} -impl Trait for Test { - type Currency = balances::Module; - type Time = timestamp::Module; - type CurrencyToVote = CurrencyToVoteHandler; - type OnRewardMinted = (); - type Event = (); - type Slash = (); - type Reward = (); - type SessionsPerEra = SessionsPerEra; - type BondingDuration = BondingDuration; - type SessionInterface = Self; - type RewardCurve = RewardCurve; -} - -pub struct ExtBuilder { - existential_deposit: u64, - validator_pool: bool, - nominate: bool, - validator_count: u32, - minimum_validator_count: u32, - fair: bool, - num_validators: Option, - invulnerables: Vec, -} - -impl Default for ExtBuilder { - fn default() -> Self { - Self { - existential_deposit: 0, - validator_pool: false, - nominate: true, - validator_count: 2, - minimum_validator_count: 0, - fair: true, - num_validators: None, - invulnerables: vec![], - } - } -} - -impl ExtBuilder { - pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { - self.existential_deposit = existential_deposit; - self - } - pub fn validator_pool(mut self, validator_pool: bool) -> Self { - self.validator_pool = validator_pool; - self - } - pub fn nominate(mut self, nominate: bool) -> Self { - 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 fair(mut self, is_fair: bool) -> Self { - self.fair = is_fair; - self - } - pub fn num_validators(mut self, num_validators: u32) -> Self { - self.num_validators = Some(num_validators); - self - } - pub fn invulnerables(mut self, invulnerables: Vec) -> Self { - self.invulnerables = invulnerables; - self - } - pub fn set_associated_consts(&self) { - EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); - } - pub fn build(self) -> runtime_io::TestExternalities { - self.set_associated_consts(); - let mut storage = system::GenesisConfig::default().build_storage::().unwrap(); - let balance_factor = if self.existential_deposit > 0 { - 256 - } else { - 1 - }; - - let num_validators = self.num_validators.unwrap_or(self.validator_count); - let validators = (0..num_validators) - .map(|x| ((x + 1) * 10 + 1) as u64) - .collect::>(); - - let _ = balances::GenesisConfig::{ - balances: 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), - (30, balance_factor), - (31, balance_factor * 2000), - (40, balance_factor), - (41, balance_factor * 2000), - (100, 2000 * balance_factor), - (101, 2000 * balance_factor), - // This allow us to have a total_payout different from 0. - (999, 1_000_000_000_000), - ], - vesting: vec![], - }.assimilate_storage(&mut storage); - - let stake_21 = if self.fair { 1000 } else { 2000 }; - let stake_31 = if self.validator_pool { balance_factor * 1000 } else { 1 }; - let status_41 = if self.validator_pool { - StakerStatus::::Validator - } else { - StakerStatus::::Idle - }; - let nominated = if self.nominate { vec![11, 21] } else { vec![] }; - let _ = GenesisConfig::{ - current_era: 0, - stakers: vec![ - // (stash, controller, staked_amount, status) - (11, 10, balance_factor * 1000, StakerStatus::::Validator), - (21, 20, stake_21, StakerStatus::::Validator), - (31, 30, stake_31, StakerStatus::::Validator), - (41, 40, balance_factor * 1000, status_41), - // nominator - (101, 100, balance_factor * 500, StakerStatus::::Nominator(nominated)) - ], - validator_count: self.validator_count, - minimum_validator_count: self.minimum_validator_count, - invulnerables: self.invulnerables, - slash_reward_fraction: Perbill::from_percent(10), - ..Default::default() - }.assimilate_storage(&mut storage); - - let _ = session::GenesisConfig:: { - keys: validators.iter().map(|x| (*x, UintAuthorityId(*x))).collect(), - }.assimilate_storage(&mut storage); - - let mut ext = runtime_io::TestExternalities::from(storage); - ext.execute_with(|| { - let validators = Session::validators(); - SESSION.with(|x| - *x.borrow_mut() = (validators.clone(), HashSet::new()) - ); - }); - ext - } -} - -pub type System = system::Module; -pub type Balances = balances::Module; -pub type Session = session::Module; -pub type Timestamp = timestamp::Module; -pub type Staking = Module; - -pub fn check_exposure_all() { - Staking::current_elected().into_iter().for_each(|acc| check_exposure(acc)); -} - -pub fn check_nominator_all() { - >::enumerate().for_each(|(acc, _)| check_nominator_exposure(acc)); -} - -/// Check for each selected validator: expo.total = Sum(expo.other) + expo.own -pub fn check_exposure(stash: u64) { - assert_is_stash(stash); - let expo = Staking::stakers(&stash); - assert_eq!( - expo.total as u128, expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), - "wrong total exposure for {:?}: {:?}", stash, expo, - ); -} - -/// Check that for each nominator: slashable_balance > sum(used_balance) -/// Note: we might not consume all of a nominator's balance, but we MUST NOT over spend it. -pub fn check_nominator_exposure(stash: u64) { - assert_is_stash(stash); - let mut sum = 0; - Staking::current_elected() - .iter() - .map(|v| Staking::stakers(v)) - .for_each(|e| e.others.iter() - .filter(|i| i.who == stash) - .for_each(|i| sum += i.value)); - let nominator_stake = Staking::slashable_balance_of(&stash); - // a nominator cannot over-spend. - assert!( - nominator_stake >= sum, - "failed: Nominator({}) stake({}) >= sum divided({})", stash, nominator_stake, sum, - ); -} - -pub fn assert_is_stash(acc: u64) { - assert!(Staking::bonded(&acc).is_some(), "Not a stash."); -} - -pub fn bond_validator(acc: u64, val: u64) { - // a = controller - // a + 1 = stash - let _ = Balances::make_free_balance_be(&(acc + 1), val); - assert_ok!(Staking::bond(Origin::signed(acc + 1), acc, val, RewardDestination::Controller)); - assert_ok!(Staking::validate(Origin::signed(acc), ValidatorPrefs::default())); -} - -pub fn bond_nominator(acc: u64, val: u64, target: Vec) { - // a = controller - // a + 1 = stash - let _ = Balances::make_free_balance_be(&(acc + 1), val); - assert_ok!(Staking::bond(Origin::signed(acc + 1), acc, val, RewardDestination::Controller)); - assert_ok!(Staking::nominate(Origin::signed(acc), target)); -} - -pub fn advance_session() { - let current_index = Session::current_index(); - start_session(current_index + 1); -} - -pub fn start_session(session_index: SessionIndex) { - // Compensate for session delay - let session_index = session_index + 1; - for i in Session::current_index()..session_index { - System::set_block_number((i + 1).into()); - Timestamp::set_timestamp(System::block_number() * 1000); - Session::on_initialize(System::block_number()); - } - - assert_eq!(Session::current_index(), session_index); -} - -pub fn start_era(era_index: EraIndex) { - start_session((era_index * 3).into()); - assert_eq!(Staking::current_era(), era_index); -} - -pub fn current_total_payout_for_duration(duration: u64) -> u64 { - let res = inflation::compute_total_payout( - ::RewardCurve::get(), - >::slot_stake() * 2, - Balances::total_issuance(), - duration, - ); - - res -} - -pub fn reward_all_elected() { - let rewards = >::current_elected().iter() - .map(|v| (*v, 1)) - .collect::>(); - - >::reward_by_ids(rewards) -} - -pub fn validator_controllers() -> Vec { - Session::validators().into_iter().map(|s| Staking::bonded(&s).expect("no controller for validator")).collect() -} diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs deleted file mode 100644 index 2b821764579d4..0000000000000 --- a/srml/staking/src/tests.rs +++ /dev/null @@ -1,1878 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Tests for the module. - -use super::*; -use mock::*; -use sr_primitives::{assert_eq_error_rate, traits::OnInitialize}; -use sr_staking_primitives::offence::{OffenceDetails, OnOffenceHandler}; -use support::{assert_ok, assert_noop, assert_eq_uvec, traits::{Currency, ReservableCurrency}}; - -#[test] -fn force_unstake_works() { - // Verifies initial conditions of mock - ExtBuilder::default().build().execute_with(|| { - // Account 11 is stashed and locked, and account 10 is the controller - assert_eq!(Staking::bonded(&11), Some(10)); - // Cant transfer - assert_noop!( - Balances::transfer(Origin::signed(11), 1, 10), - "account liquidity restrictions prevent withdrawal" - ); - // Force unstake requires root. - assert_noop!(Staking::force_unstake(Origin::signed(11), 11), "RequireRootOrigin"); - // We now force them to unstake - assert_ok!(Staking::force_unstake(Origin::ROOT, 11)); - // No longer bonded. - assert_eq!(Staking::bonded(&11), None); - // Transfer works. - assert_ok!(Balances::transfer(Origin::signed(11), 1, 10)); - }); -} - -#[test] -fn basic_setup_works() { - // Verifies initial conditions of mock - ExtBuilder::default().build().execute_with(|| { - // Account 11 is stashed and locked, and account 10 is the controller - assert_eq!(Staking::bonded(&11), Some(10)); - // Account 21 is stashed and locked, and account 20 is the controller - assert_eq!(Staking::bonded(&21), Some(20)); - // Account 1 is not a stashed - assert_eq!(Staking::bonded(&1), None); - - // Account 10 controls the stash from account 11, which is 100 * balance_factor units - assert_eq!( - Staking::ledger(&10), - Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] }) - ); - // Account 20 controls the stash from account 21, which is 200 * balance_factor units - assert_eq!( - Staking::ledger(&20), - Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![] }) - ); - // Account 1 does not control any stash - assert_eq!(Staking::ledger(&1), None); - - // ValidatorPrefs are default - assert_eq!(>::enumerate().collect::>(), vec![ - (31, ValidatorPrefs::default()), - (21, ValidatorPrefs::default()), - (11, ValidatorPrefs::default()) - ]); - - assert_eq!( - Staking::ledger(100), - Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![] }) - ); - assert_eq!(Staking::nominators(101), vec![11, 21]); - - if cfg!(feature = "equalize") { - assert_eq!( - Staking::stakers(11), - Exposure { total: 1250, own: 1000, others: vec![ IndividualExposure { who: 101, value: 250 }] } - ); - assert_eq!( - Staking::stakers(21), - Exposure { total: 1250, own: 1000, others: vec![ IndividualExposure { who: 101, value: 250 }] } - ); - // initial slot_stake - assert_eq!(Staking::slot_stake(), 1250); - } else { - assert_eq!( - Staking::stakers(11), - Exposure { total: 1125, own: 1000, others: vec![ IndividualExposure { who: 101, value: 125 }] } - ); - assert_eq!( - Staking::stakers(21), - Exposure { total: 1375, own: 1000, others: vec![ IndividualExposure { who: 101, value: 375 }] } - ); - // initial slot_stake - assert_eq!(Staking::slot_stake(), 1125); - } - - - // The number of validators required. - assert_eq!(Staking::validator_count(), 2); - - // Initial Era and session - assert_eq!(Staking::current_era(), 0); - - // Account 10 has `balance_factor` free balance - assert_eq!(Balances::free_balance(&10), 1); - assert_eq!(Balances::free_balance(&10), 1); - - // New era is not being forced - assert_eq!(Staking::force_era(), Forcing::NotForcing); - - // All exposures must be correct. - check_exposure_all(); - check_nominator_all(); - }); -} - -#[test] -fn change_controller_works() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::bonded(&11), Some(10)); - - assert!(>::enumerate().map(|(c, _)| c).collect::>().contains(&11)); - // 10 can control 11 who is initially a validator. - assert_ok!(Staking::chill(Origin::signed(10))); - assert!(!>::enumerate().map(|(c, _)| c).collect::>().contains(&11)); - - assert_ok!(Staking::set_controller(Origin::signed(11), 5)); - - start_era(1); - - assert_noop!( - Staking::validate(Origin::signed(10), ValidatorPrefs::default()), - "not a controller" - ); - assert_ok!(Staking::validate(Origin::signed(5), ValidatorPrefs::default())); - }) -} - -#[test] -fn rewards_should_work() { - // should check that: - // * rewards get recorded per session - // * rewards get paid per Era - // * Check that nominators are also rewarded - ExtBuilder::default().nominate(false).build().execute_with(|| { - // Init some balances - let _ = Balances::make_free_balance_be(&2, 500); - - let delay = 1000; - let init_balance_2 = Balances::total_balance(&2); - let init_balance_10 = Balances::total_balance(&10); - let init_balance_11 = Balances::total_balance(&11); - - // Set payee to controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - - // Initial config should be correct - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 0); - - // Add a dummy nominator. - // - // Equal division indicates that the reward will be equally divided among validator and - // nominator. - >::insert(&11, Exposure { - own: 500, - total: 1000, - others: vec![IndividualExposure {who: 2, value: 500 }] - }); - - >::insert(&2, RewardDestination::Stash); - assert_eq!(Staking::payee(2), RewardDestination::Stash); - assert_eq!(Staking::payee(11), RewardDestination::Controller); - - let mut block = 3; // Block 3 => Session 1 => Era 0 - System::set_block_number(block); - Timestamp::set_timestamp(block * 5000); // on time. - Session::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 1); - >::reward_by_ids(vec![(11, 50)]); - >::reward_by_ids(vec![(11, 50)]); - // This is the second validator of the current elected set. - >::reward_by_ids(vec![(21, 50)]); - // This must be no-op as it is not an elected validator. - >::reward_by_ids(vec![(1001, 10_000)]); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout = current_total_payout_for_duration(9 * 5 * 1000); - assert!(total_payout > 10); // Test is meaningful if reward something - - // No reward yet - assert_eq!(Balances::total_balance(&2), init_balance_2); - assert_eq!(Balances::total_balance(&10), init_balance_10); - assert_eq!(Balances::total_balance(&11), init_balance_11); - - block = 6; // Block 6 => Session 2 => Era 0 - System::set_block_number(block); - Timestamp::set_timestamp(block * 5000 + delay); // a little late. - Session::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 2); - - block = 9; // Block 9 => Session 3 => Era 1 - System::set_block_number(block); - Timestamp::set_timestamp(block * 5000); // back to being on time. no delays - Session::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::current_index(), 3); - - // 11 validator has 2/3 of the total rewards and half half for it and its nominator - assert_eq_error_rate!(Balances::total_balance(&2), init_balance_2 + total_payout / 3, 1); - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + total_payout / 3, 1); - assert_eq!(Balances::total_balance(&11), init_balance_11); - }); -} - -#[test] -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. - ExtBuilder::default().nominate(false).build().execute_with(|| { - let init_balance_10 = Balances::total_balance(&10); - - // Set payee to controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - - // Compute now as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 10); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); - - start_session(0); - start_session(1); - start_session(2); - start_session(3); - - assert_eq!(Staking::current_era(), 1); - assert_eq!(Balances::total_balance(&10), init_balance_10 + total_payout_0); - - start_session(4); - - let total_payout_1 = current_total_payout_for_duration(3000); - assert!(total_payout_1 > 10); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 101)]); - - // new era is triggered here. - start_session(5); - - // pay time - assert_eq!(Balances::total_balance(&10), init_balance_10 + total_payout_0 + total_payout_1); - }); -} - -#[test] -fn staking_should_work() { - // 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. - ExtBuilder::default() - .nominate(false) - .fair(false) // to give 20 more staked value - .build() - .execute_with(|| { - Timestamp::set_timestamp(1); // Initialize time. - - // remember + compare this along with the test. - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // put some money in account that we'll use. - for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); } - - // --- Block 1: - start_session(1); - // add a new candidate for being a validator. account 3 controlled by 4. - assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); - assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); - - // No effects will be seen so far. - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // --- Block 2: - start_session(2); - - // No effects will be seen so far. Era has not been yet triggered. - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - - // --- Block 3: the validators will now be queued. - start_session(3); - assert_eq!(Staking::current_era(), 1); - - // --- Block 4: the validators will now be changed. - start_session(4); - - assert_eq_uvec!(validator_controllers(), vec![20, 4]); - // --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3 - // 4 will chill - Staking::chill(Origin::signed(4)).unwrap(); - - // --- Block 5: nothing. 4 is still there. - start_session(5); - assert_eq_uvec!(validator_controllers(), vec![20, 4]); - - // --- Block 6: 4 will not be a validator. - start_session(7); - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // Note: the stashed value of 4 is still lock - assert_eq!( - Staking::ledger(&4), - Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![] }) - ); - // e.g. it cannot spend more than 500 that it has free from the total 2000 - assert_noop!(Balances::reserve(&3, 501), "account liquidity restrictions prevent withdrawal"); - assert_ok!(Balances::reserve(&3, 409)); - }); -} - -#[test] -fn less_than_needed_candidates_works() { - ExtBuilder::default() - .minimum_validator_count(1) - .validator_count(4) - .nominate(false) - .num_validators(3) - .build() - .execute_with(|| { - assert_eq!(Staking::validator_count(), 4); - assert_eq!(Staking::minimum_validator_count(), 1); - assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); - - start_era(1); - - // Previous set is selected. NO election algorithm is even executed. - assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); - - // But the exposure is updated in a simple way. No external votes exists. - // This is purely self-vote. - assert_eq!(Staking::stakers(10).others.len(), 0); - assert_eq!(Staking::stakers(20).others.len(), 0); - assert_eq!(Staking::stakers(30).others.len(), 0); - check_exposure_all(); - check_nominator_all(); - }); -} - -#[test] -fn no_candidate_emergency_condition() { - ExtBuilder::default() - .minimum_validator_count(10) - .validator_count(15) - .num_validators(4) - .validator_pool(true) - .nominate(false) - .build() - .execute_with(|| { - // initial validators - assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); - - // set the minimum validator count. - ::MinimumValidatorCount::put(10); - ::ValidatorCount::put(15); - assert_eq!(Staking::validator_count(), 15); - - let _ = Staking::chill(Origin::signed(10)); - - // trigger era - System::set_block_number(1); - Session::on_initialize(System::block_number()); - - // Previous ones are elected. chill is invalidates. TODO: #2494 - assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); - assert_eq!(Staking::current_elected().len(), 0); - }); -} - -#[test] -fn nominating_and_rewards_should_work() { - // PHRAGMEN OUTPUT: running this test with the reference impl gives: - // - // Sequential Phragmén gives - // 10 is elected with stake 2200.0 and score 0.0003333333333333333 - // 20 is elected with stake 1800.0 and score 0.0005555555555555556 - - // 10 has load 0.0003333333333333333 and supported - // 10 with stake 1000.0 - // 20 has load 0.0005555555555555556 and supported - // 20 with stake 1000.0 - // 30 has load 0 and supported - // 30 with stake 0 - // 40 has load 0 and supported - // 40 with stake 0 - // 2 has load 0.0005555555555555556 and supported - // 10 with stake 600.0 20 with stake 400.0 30 with stake 0.0 - // 4 has load 0.0005555555555555556 and supported - // 10 with stake 600.0 20 with stake 400.0 40 with stake 0.0 - - // Sequential Phragmén with post processing gives - // 10 is elected with stake 2000.0 and score 0.0003333333333333333 - // 20 is elected with stake 2000.0 and score 0.0005555555555555556 - - // 10 has load 0.0003333333333333333 and supported - // 10 with stake 1000.0 - // 20 has load 0.0005555555555555556 and supported - // 20 with stake 1000.0 - // 30 has load 0 and supported - // 30 with stake 0 - // 40 has load 0 and supported - // 40 with stake 0 - // 2 has load 0.0005555555555555556 and supported - // 10 with stake 400.0 20 with stake 600.0 30 with stake 0 - // 4 has load 0.0005555555555555556 and supported - // 10 with stake 600.0 20 with stake 400.0 40 with stake 0.0 - ExtBuilder::default() - .nominate(false) - .validator_pool(true) - .build() - .execute_with(|| { - // initial validators -- everyone is actually even. - assert_eq_uvec!(validator_controllers(), vec![40, 30]); - - // Set payee to controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(20), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(30), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(40), RewardDestination::Controller)); - - // give the man some money - let initial_balance = 1000; - for i in [1, 2, 3, 4, 5, 10, 11, 20, 21].iter() { - let _ = Balances::make_free_balance_be(i, initial_balance); - } - - // bond two account pairs and state interest in nomination. - // 2 will nominate for 10, 20, 30 - assert_ok!(Staking::bond(Origin::signed(1), 2, 1000, RewardDestination::Controller)); - assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21, 31])); - // 4 will nominate for 10, 20, 40 - assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::Controller)); - assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41])); - - // the total reward for era 0 - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(41, 1)]); - >::reward_by_ids(vec![(31, 1)]); - >::reward_by_ids(vec![(21, 10)]); // must be no-op - >::reward_by_ids(vec![(11, 10)]); // must be no-op - - start_era(1); - - // 10 and 20 have more votes, they will be chosen by phragmen. - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // OLD validators must have already received some rewards. - assert_eq!(Balances::total_balance(&40), 1 + total_payout_0 / 2); - assert_eq!(Balances::total_balance(&30), 1 + total_payout_0 / 2); - - // ------ check the staked value of all parties. - - if cfg!(feature = "equalize") { - // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(11).own, 1000); - assert_eq_error_rate!(Staking::stakers(11).total, 1000 + 1000, 2); - // 2 and 4 supported 10, each with stake 600, according to phragmen. - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), - vec![600, 400] - ); - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - // total expo of 20, with 500 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(21).own, 1000); - assert_eq_error_rate!(Staking::stakers(21).total, 1000 + 1000, 2); - // 2 and 4 supported 20, each with stake 250, according to phragmen. - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), - vec![400, 600] - ); - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - } else { - // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(11).own, 1000); - assert_eq!(Staking::stakers(11).total, 1000 + 800); - // 2 and 4 supported 10, each with stake 600, according to phragmen. - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), - vec![400, 400] - ); - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - // total expo of 20, with 500 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(21).own, 1000); - assert_eq_error_rate!(Staking::stakers(21).total, 1000 + 1200, 2); - // 2 and 4 supported 20, each with stake 250, according to phragmen. - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), - vec![600, 600] - ); - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - } - - // They are not chosen anymore - assert_eq!(Staking::stakers(31).total, 0); - assert_eq!(Staking::stakers(41).total, 0); - - // the total reward for era 1 - let total_payout_1 = current_total_payout_for_duration(3000); - assert!(total_payout_1 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(41, 10)]); // must be no-op - >::reward_by_ids(vec![(31, 10)]); // must be no-op - >::reward_by_ids(vec![(21, 2)]); - >::reward_by_ids(vec![(11, 1)]); - - start_era(2); - - // nothing else will happen, era ends and rewards are paid again, - // it is expected that nominators will also be paid. See below - - let payout_for_10 = total_payout_1 / 3; - let payout_for_20 = 2 * total_payout_1 / 3; - if cfg!(feature = "equalize") { - // Nominator 2: has [400 / 2000 ~ 1 / 5 from 10] + [600 / 2000 ~ 3 / 10 from 20]'s reward. - assert_eq_error_rate!( - Balances::total_balance(&2), - initial_balance + payout_for_10 / 5 + payout_for_20 * 3 / 10, - 2, - ); - // Nominator 4: has [400 / 2000 ~ 1 / 5 from 20] + [600 / 2000 ~ 3 / 10 from 10]'s reward. - assert_eq_error_rate!( - Balances::total_balance(&4), - initial_balance + payout_for_20 / 5 + payout_for_10 * 3 / 10, - 2, - ); - - // Validator 10: got 1000 / 2000 external stake. - assert_eq_error_rate!( - Balances::total_balance(&10), - initial_balance + payout_for_10 / 2, - 1, - ); - // Validator 20: got 1000 / 2000 external stake. - assert_eq_error_rate!( - Balances::total_balance(&20), - initial_balance + payout_for_20 / 2, - 1, - ); - } else { - // Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 - assert_eq_error_rate!( - Balances::total_balance(&2), - initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), - 1, - ); - // Nominator 4: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 - assert_eq_error_rate!( - Balances::total_balance(&4), - initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), - 1, - ); - - // Validator 10: got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9 - assert_eq_error_rate!( - Balances::total_balance(&10), - initial_balance + 5 * payout_for_10 / 9, - 1, - ); - // Validator 20: got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = 5/11 - assert_eq_error_rate!( - Balances::total_balance(&20), - initial_balance + 5 * payout_for_20 / 11, - 1, - ); - } - - check_exposure_all(); - check_nominator_all(); - }); -} - -#[test] -fn nominators_also_get_slashed() { - // A nominator should be slashed if the validator they nominated is slashed - // Here is the breakdown of roles: - // 10 - is the controller of 11 - // 11 - is the stash. - // 2 - is the nominator of 20, 10 - ExtBuilder::default().nominate(false).build().execute_with(|| { - assert_eq!(Staking::validator_count(), 2); - - // Set payee to controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - - // give the man some money. - let initial_balance = 1000; - for i in [1, 2, 3, 10].iter() { - let _ = Balances::make_free_balance_be(i, initial_balance); - } - - // 2 will nominate for 10, 20 - let nominator_stake = 500; - assert_ok!(Staking::bond(Origin::signed(1), 2, nominator_stake, RewardDestination::default())); - assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 10])); - - let total_payout = current_total_payout_for_duration(3000); - assert!(total_payout > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); - - // new era, pay rewards, - start_era(1); - - // Nominator stash didn't collect any. - assert_eq!(Balances::total_balance(&2), initial_balance); - - // 10 goes offline - Staking::on_offence( - &[OffenceDetails { - offender: ( - 11, - Staking::stakers(&11), - ), - reporters: vec![], - }], - &[Perbill::from_percent(5)], - ); - let expo = Staking::stakers(11); - let slash_value = 50; - let total_slash = expo.total.min(slash_value); - let validator_slash = expo.own.min(total_slash); - let nominator_slash = nominator_stake.min(total_slash - validator_slash); - - // initial + first era reward + slash - assert_eq!(Balances::total_balance(&11), initial_balance - validator_slash); - assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); - check_exposure_all(); - check_nominator_all(); - // Because slashing happened. - assert!(is_disabled(10)); - }); -} - -#[test] -fn double_staking_should_fail() { - // should test (in the same order): - // * an account already bonded as stash cannot be be stashed again. - // * an account already bonded as stash cannot nominate. - // * an account already bonded as controller can nominate. - ExtBuilder::default().build().execute_with(|| { - let arbitrary_value = 5; - // 2 = controller, 1 stashed => ok - assert_ok!( - Staking::bond(Origin::signed(1), 2, arbitrary_value, - RewardDestination::default()) - ); - // 4 = not used so far, 1 stashed => not allowed. - assert_noop!( - Staking::bond(Origin::signed(1), 4, arbitrary_value, - RewardDestination::default()), "stash already bonded" - ); - // 1 = stashed => attempting to nominate should fail. - assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), "not a controller"); - // 2 = controller => nominating should work. - assert_ok!(Staking::nominate(Origin::signed(2), vec![1])); - }); -} - -#[test] -fn double_controlling_should_fail() { - // should test (in the same order): - // * an account already bonded as controller CANNOT be reused as the controller of another account. - ExtBuilder::default().build().execute_with(|| { - let arbitrary_value = 5; - // 2 = controller, 1 stashed => ok - assert_ok!(Staking::bond( - Origin::signed(1), - 2, - arbitrary_value, - RewardDestination::default(), - )); - // 2 = controller, 3 stashed (Note that 2 is reused.) => no-op - assert_noop!( - Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default()), - "controller already paired", - ); - }); -} - -#[test] -fn session_and_eras_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::current_era(), 0); - - // Block 1: No change. - start_session(0); - assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::current_era(), 0); - - // Block 2: Simple era change. - start_session(2); - assert_eq!(Session::current_index(), 3); - assert_eq!(Staking::current_era(), 1); - - // Block 3: Schedule an era length change; no visible changes. - start_session(3); - assert_eq!(Session::current_index(), 4); - assert_eq!(Staking::current_era(), 1); - - // Block 4: Era change kicks in. - start_session(5); - assert_eq!(Session::current_index(), 6); - assert_eq!(Staking::current_era(), 2); - - // Block 5: No change. - start_session(6); - assert_eq!(Session::current_index(), 7); - assert_eq!(Staking::current_era(), 2); - - // Block 6: No change. - start_session(7); - assert_eq!(Session::current_index(), 8); - assert_eq!(Staking::current_era(), 2); - - // Block 7: Era increment. - start_session(8); - assert_eq!(Session::current_index(), 9); - assert_eq!(Staking::current_era(), 3); - }); -} - -#[test] -fn forcing_new_era_works() { - ExtBuilder::default().build().execute_with(|| { - // normal flow of session. - assert_eq!(Staking::current_era(), 0); - start_session(0); - assert_eq!(Staking::current_era(), 0); - start_session(1); - assert_eq!(Staking::current_era(), 0); - start_session(2); - assert_eq!(Staking::current_era(), 1); - - // no era change. - ForceEra::put(Forcing::ForceNone); - start_session(3); - assert_eq!(Staking::current_era(), 1); - start_session(4); - assert_eq!(Staking::current_era(), 1); - start_session(5); - assert_eq!(Staking::current_era(), 1); - start_session(6); - assert_eq!(Staking::current_era(), 1); - - // back to normal. - // this immediatelly starts a new session. - ForceEra::put(Forcing::NotForcing); - start_session(7); - assert_eq!(Staking::current_era(), 2); - start_session(8); - assert_eq!(Staking::current_era(), 2); - - // forceful change - ForceEra::put(Forcing::ForceNew); - start_session(9); - assert_eq!(Staking::current_era(), 3); - }); -} - -#[test] -fn cannot_transfer_staked_balance() { - // Tests that a stash account cannot transfer funds - ExtBuilder::default().nominate(false).build().execute_with(|| { - // Confirm account 11 is stashed - assert_eq!(Staking::bonded(&11), Some(10)); - // Confirm account 11 has some free balance - assert_eq!(Balances::free_balance(&11), 1000); - // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::stakers(&11).total, 1000); - // Confirm account 11 cannot transfer as a result - assert_noop!( - Balances::transfer(Origin::signed(11), 20, 1), - "account liquidity restrictions prevent withdrawal", - ); - - // Give account 11 extra free balance - let _ = Balances::make_free_balance_be(&11, 10000); - // Confirm that account 11 can now transfer some balance - assert_ok!(Balances::transfer(Origin::signed(11), 20, 1)); - }); -} - -#[test] -fn cannot_transfer_staked_balance_2() { - // Tests that a stash account cannot transfer funds - // Same test as above but with 20, and more accurate. - // 21 has 2000 free balance but 1000 at stake - ExtBuilder::default().nominate(false).fair(true).build().execute_with(|| { - // Confirm account 21 is stashed - assert_eq!(Staking::bonded(&21), Some(20)); - // Confirm account 21 has some free balance - assert_eq!(Balances::free_balance(&21), 2000); - // Confirm account 21 (via controller 20) is totally staked - assert_eq!(Staking::stakers(&21).total, 1000); - // Confirm account 21 can transfer at most 1000 - assert_noop!( - Balances::transfer(Origin::signed(21), 20, 1001), - "account liquidity restrictions prevent withdrawal", - ); - assert_ok!(Balances::transfer(Origin::signed(21), 20, 1000)); - }); -} - -#[test] -fn cannot_reserve_staked_balance() { - // Checks that a bonded account cannot reserve balance from free balance - ExtBuilder::default().build().execute_with(|| { - // 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(&11).own, 1000); - // 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 - let _ = Balances::make_free_balance_be(&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 - ExtBuilder::default().nominate(false).build().execute_with(|| { - // Check that account 11 is a validator - assert!(Staking::current_elected().contains(&11)); - // Check the balance of the validator account - assert_eq!(Balances::free_balance(&10), 1); - // Check the balance of the stash account - assert_eq!(Balances::free_balance(&11), 1000); - // Check how much is at stake - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, - total: 1000, - active: 1000, - unlocking: vec![], - })); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); - - start_era(1); - - // Check that RewardDestination is Staked (default) - assert_eq!(Staking::payee(&11), RewardDestination::Staked); - // Check that reward went to the stash account of validator - assert_eq!(Balances::free_balance(&11), 1000 + total_payout_0); - // Check that amount at stake increased accordingly - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, - total: 1000 + total_payout_0, - active: 1000 + total_payout_0, - unlocking: vec![], - })); - - //Change RewardDestination to Stash - >::insert(&11, RewardDestination::Stash); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_1 = current_total_payout_for_duration(3000); - assert!(total_payout_1 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); - - start_era(2); - - // Check that RewardDestination is Stash - assert_eq!(Staking::payee(&11), RewardDestination::Stash); - // Check that reward went to the stash account - assert_eq!(Balances::free_balance(&11), 1000 + total_payout_0 + total_payout_1); - // Record this value - let recorded_stash_balance = 1000 + total_payout_0 + total_payout_1; - // Check that amount at stake is NOT increased - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, - total: 1000 + total_payout_0, - active: 1000 + total_payout_0, - unlocking: vec![], - })); - - // Change RewardDestination to Controller - >::insert(&11, RewardDestination::Controller); - - // Check controller balance - assert_eq!(Balances::free_balance(&10), 1); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_2 = current_total_payout_for_duration(3000); - assert!(total_payout_2 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); - - start_era(3); - - // Check that RewardDestination is Controller - assert_eq!(Staking::payee(&11), RewardDestination::Controller); - // Check that reward went to the controller account - assert_eq!(Balances::free_balance(&10), 1 + total_payout_2); - // Check that amount at stake is NOT increased - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, - total: 1000 + total_payout_0, - active: 1000 + total_payout_0, - unlocking: vec![], - })); - // Check that amount in staked account is NOT increased. - assert_eq!(Balances::free_balance(&11), recorded_stash_balance); - }); -} - -#[test] -fn validator_payment_prefs_work() { - // Test that validator preferences are correctly honored - // Note: unstake threshold is being directly tested in slashing tests. - // This test will focus on validator payment. - ExtBuilder::default().build().execute_with(|| { - // Initial config - let validator_cut = 5; - let stash_initial_balance = Balances::total_balance(&11); - - // check the balance of a validator accounts. - assert_eq!(Balances::total_balance(&10), 1); - // check the balance of a validator's stash accounts. - assert_eq!(Balances::total_balance(&11), stash_initial_balance); - // and the nominator (to-be) - let _ = Balances::make_free_balance_be(&2, 500); - - // add a dummy nominator. - >::insert(&11, 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::Stash); - >::insert(&11, ValidatorPrefs { - validator_payment: validator_cut - }); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); - - start_era(1); - - // whats left to be shared is the sum of 3 rounds minus the validator's cut. - let shared_cut = total_payout_0 - validator_cut; - // Validator's payee is Staked account, 11, reward will be paid here. - assert_eq!(Balances::total_balance(&11), stash_initial_balance + shared_cut / 2 + validator_cut); - // Controller account will not get any reward. - assert_eq!(Balances::total_balance(&10), 1); - // Rest of the reward will be shared and paid to the nominator in stake. - assert_eq!(Balances::total_balance(&2), 500 + shared_cut / 2); - - check_exposure_all(); - check_nominator_all(); - }); - -} - -#[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`. - ExtBuilder::default().build().execute_with(|| { - // Check that account 10 is a validator - assert!(>::exists(11)); - // 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 - let _ = Balances::make_free_balance_be(&11, 1000000); - - // Call the bond_extra function from controller, add only 100 - assert_ok!(Staking::bond_extra(Origin::signed(11), 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(11), 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. - ExtBuilder::default().nominate(false).build().execute_with(|| { - // Set payee to controller. avoids confusion - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - - // Give account 11 some large free balance greater than total - let _ = Balances::make_free_balance_be(&11, 1000000); - - // Initial config should be correct - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 0); - - // 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. - start_era(1); - - // Initial state of 10 - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, - total: 1000, - active: 1000, - unlocking: vec![], - })); - assert_eq!(Staking::stakers(&11), Exposure { total: 1000, own: 1000, others: vec![] }); - - // deposit the extra 100 units - Staking::bond_extra(Origin::signed(11), 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(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); - - // trigger next era. - Timestamp::set_timestamp(10); - start_era(2); - assert_eq!(Staking::current_era(), 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(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); - - // Unbond almost all of the funds in stash. - Staking::unbond(Origin::signed(10), 1000).unwrap(); - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] }) - ); - - // Attempting to free the balances now will fail. 2 eras need to pass. - Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] })); - - // trigger next era. - start_era(3); - - // nothing yet - Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); - assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] })); - - // trigger next era. - start_era(5); - - 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 too_many_unbond_calls_should_not_work() { - ExtBuilder::default().build().execute_with(|| { - // locked at era 0 until 3 - for _ in 0..MAX_UNLOCKING_CHUNKS-1 { - assert_ok!(Staking::unbond(Origin::signed(10), 1)); - } - - start_era(1); - - // locked at era 1 until 4 - assert_ok!(Staking::unbond(Origin::signed(10), 1)); - // can't do more. - assert_noop!(Staking::unbond(Origin::signed(10), 1), "can not schedule more unlock chunks"); - - start_era(3); - - assert_noop!(Staking::unbond(Origin::signed(10), 1), "can not schedule more unlock chunks"); - // free up. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(10))); - - // Can add again. - assert_ok!(Staking::unbond(Origin::signed(10), 1)); - assert_eq!(Staking::ledger(&10).unwrap().unlocking.len(), 2); - }) -} - -#[test] -fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment() { - // Test that slot_stake is determined by the least staked validator - // Test that slot_stake is the maximum punishment that can happen to a validator - ExtBuilder::default().nominate(false).fair(false).build().execute_with(|| { - // Confirm validator count is 2 - assert_eq!(Staking::validator_count(), 2); - // Confirm account 10 and 20 are validators - assert!(>::exists(&11) && >::exists(&21)); - - assert_eq!(Staking::stakers(&11).total, 1000); - assert_eq!(Staking::stakers(&21).total, 2000); - - // Give the man some money. - let _ = Balances::make_free_balance_be(&10, 1000); - let _ = Balances::make_free_balance_be(&20, 1000); - - // We confirm initialized slot_stake is this value - assert_eq!(Staking::slot_stake(), Staking::stakers(&11).total); - - // Now lets lower account 20 stake - >::insert(&21, Exposure { total: 69, own: 69, others: vec![] }); - assert_eq!(Staking::stakers(&21).total, 69); - >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![] }); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); - >::reward_by_ids(vec![(21, 1)]); - - // New era --> rewards are paid --> stakes are changed - start_era(1); - - // -- new balances + reward - assert_eq!(Staking::stakers(&11).total, 1000 + total_payout_0 / 2); - assert_eq!(Staking::stakers(&21).total, 69 + total_payout_0 / 2); - - let _11_balance = Balances::free_balance(&11); - assert_eq!(_11_balance, 1000 + total_payout_0 / 2); - - // -- slot stake should also be updated. - assert_eq!(Staking::slot_stake(), 69 + total_payout_0 / 2); - - check_exposure_all(); - check_nominator_all(); - }); -} - -#[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 - ExtBuilder::default().existential_deposit(10).build().execute_with(|| { - // Check the balance of the validator account - assert_eq!(Balances::free_balance(&10), 256); - // Check the balance of the stash account - 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 - // 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(&11)); - assert!(>::exists(&11)); - assert!(>::exists(&11)); - - // Reduce free_balance of controller to 0 - let _ = Balances::slash(&10, u64::max_value()); - - // 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(&11)); - assert!(>::exists(&11)); - assert!(>::exists(&11)); - - // Reduce free_balance of stash to 0 - let _ = Balances::slash(&11, u64::max_value()); - // Check total balance of stash - assert_eq!(Balances::total_balance(&11), 0); - - // Check storage items do not exist - assert!(!>::exists(&10)); - assert!(!>::exists(&11)); - assert!(!>::exists(&11)); - assert!(!>::exists(&11)); - 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 - ExtBuilder::default().existential_deposit(10).build().execute_with(|| { - // Make 10 a nominator - assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); - // Check that account 10 is a nominator - assert!(>::exists(11)); - // 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); - - // 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(&11)); - assert!(>::exists(&11)); - assert!(>::exists(&11)); - - // Reduce free_balance of controller to 0 - let _ = Balances::slash(&10, u64::max_value()); - // 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(&11)); - assert!(>::exists(&11)); - assert!(>::exists(&11)); - - // Reduce free_balance of stash to 0 - let _ = Balances::slash(&11, u64::max_value()); - // Check total balance of stash - assert_eq!(Balances::total_balance(&11), 0); - - // Check storage items do not exist - assert!(!>::exists(&10)); - assert!(!>::exists(&11)); - assert!(!>::exists(&11)); - assert!(!>::exists(&11)); - assert!(!>::exists(&11)); - }); -} - - -#[test] -fn switching_roles() { - // Test that it should be possible to switch between roles (nominator, validator, idle) with minimal overhead. - ExtBuilder::default().nominate(false).build().execute_with(|| { - Timestamp::set_timestamp(1); // Initialize time. - - // Reset reward destination - for i in &[10, 20] { assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); } - - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // put some money in account that we'll use. - for i in 1..7 { let _ = Balances::deposit_creating(&i, 5000); } - - // add 2 nominators - assert_ok!(Staking::bond(Origin::signed(1), 2, 2000, RewardDestination::Controller)); - assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 5])); - - assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Controller)); - assert_ok!(Staking::nominate(Origin::signed(4), vec![21, 1])); - - // add a new validator candidate - assert_ok!(Staking::bond(Origin::signed(5), 6, 1000, RewardDestination::Controller)); - assert_ok!(Staking::validate(Origin::signed(6), ValidatorPrefs::default())); - - // new block - start_session(1); - - // no change - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // new block - start_session(2); - - // no change - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // new block --> ne era --> new validators - start_session(3); - - // with current nominators 10 and 5 have the most stake - assert_eq_uvec!(validator_controllers(), vec![6, 10]); - - // 2 decides to be a validator. Consequences: - assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); - // new stakes: - // 10: 1000 self vote - // 20: 1000 self vote + 250 vote - // 6 : 1000 self vote - // 2 : 2000 self vote + 250 vote. - // Winners: 20 and 2 - - start_session(4); - assert_eq_uvec!(validator_controllers(), vec![6, 10]); - - start_session(5); - assert_eq_uvec!(validator_controllers(), vec![6, 10]); - - // ne era - start_session(6); - assert_eq_uvec!(validator_controllers(), vec![2, 20]); - - check_exposure_all(); - check_nominator_all(); - }); -} - -#[test] -fn wrong_vote_is_null() { - ExtBuilder::default().nominate(false).validator_pool(true).build().execute_with(|| { - assert_eq_uvec!(validator_controllers(), vec![40, 30]); - - // put some money in account that we'll use. - for i in 1..3 { let _ = Balances::deposit_creating(&i, 5000); } - - // add 1 nominators - assert_ok!(Staking::bond(Origin::signed(1), 2, 2000, RewardDestination::default())); - assert_ok!(Staking::nominate(Origin::signed(2), vec![ - 11, 21, // good votes - 1, 2, 15, 1000, 25 // crap votes. No effect. - ])); - - // new block - start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - }); -} - -#[test] -fn bond_with_no_staked_value() { - // Behavior when someone bonds with no staked value. - // Particularly when she votes and the candidate is elected. - ExtBuilder::default() - .validator_count(3) - .existential_deposit(5) - .nominate(false) - .minimum_validator_count(1) - .build() - .execute_with(|| { - // Can't bond with 1 - assert_noop!( - Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller), - "can not bond with value less than minimum balance", - ); - // bonded with absolute minimum value possible. - assert_ok!(Staking::bond(Origin::signed(1), 2, 5, RewardDestination::Controller)); - assert_eq!(Balances::locks(&1)[0].amount, 5); - - // unbonding even 1 will cause all to be unbonded. - assert_ok!(Staking::unbond(Origin::signed(2), 1)); - assert_eq!( - Staking::ledger(2), - Some(StakingLedger { - stash: 1, - active: 0, - total: 5, - unlocking: vec![UnlockChunk {value: 5, era: 3}] - }) - ); - - start_era(1); - start_era(2); - - // not yet removed. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); - assert!(Staking::ledger(2).is_some()); - assert_eq!(Balances::locks(&1)[0].amount, 5); - - start_era(3); - - // poof. Account 1 is removed from the staking system. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); - assert!(Staking::ledger(2).is_none()); - assert_eq!(Balances::locks(&1).len(), 0); - }); -} - -#[test] -fn bond_with_little_staked_value_bounded_by_slot_stake() { - // Behavior when someone bonds with little staked value. - // Particularly when she votes and the candidate is elected. - ExtBuilder::default() - .validator_count(3) - .nominate(false) - .minimum_validator_count(1) - .build() - .execute_with(|| { - // setup - assert_ok!(Staking::chill(Origin::signed(30))); - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - let init_balance_2 = Balances::free_balance(&2); - let init_balance_10 = Balances::free_balance(&10); - - // Stingy validator. - assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); - assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); - - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - reward_all_elected(); - start_era(1); - - // 2 is elected. - // and fucks up the slot stake. - assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::slot_stake(), 1); - - // Old ones are rewarded. - assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3); - // no rewards paid to 2. This was initial election. - assert_eq!(Balances::free_balance(&2), init_balance_2); - - let total_payout_1 = current_total_payout_for_duration(3000); - assert!(total_payout_1 > 100); // Test is meaningfull if reward something - reward_all_elected(); - start_era(2); - - assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::slot_stake(), 1); - - assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_1 / 3); - assert_eq!( - Balances::free_balance(&10), - init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3, - ); - check_exposure_all(); - check_nominator_all(); - }); -} - -#[cfg(feature = "equalize")] -#[test] -fn phragmen_linear_worse_case_equalize() { - ExtBuilder::default() - .nominate(false) - .validator_pool(true) - .fair(true) - .build() - .execute_with(|| { - bond_validator(50, 1000); - bond_validator(60, 1000); - bond_validator(70, 1000); - - bond_nominator(2, 2000, vec![11]); - bond_nominator(4, 1000, vec![11, 21]); - bond_nominator(6, 1000, vec![21, 31]); - bond_nominator(8, 1000, vec![31, 41]); - bond_nominator(110, 1000, vec![41, 51]); - bond_nominator(120, 1000, vec![51, 61]); - bond_nominator(130, 1000, vec![61, 71]); - - for i in &[10, 20, 30, 40, 50, 60, 70] { - assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); - } - - assert_eq_uvec!(validator_controllers(), vec![40, 30]); - assert_ok!(Staking::set_validator_count(Origin::ROOT, 7)); - - start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![10, 60, 40, 20, 50, 30, 70]); - - assert_eq_error_rate!(Staking::stakers(11).total, 3000, 2); - assert_eq_error_rate!(Staking::stakers(21).total, 2255, 2); - assert_eq_error_rate!(Staking::stakers(31).total, 2255, 2); - assert_eq_error_rate!(Staking::stakers(41).total, 1925, 2); - assert_eq_error_rate!(Staking::stakers(51).total, 1870, 2); - assert_eq_error_rate!(Staking::stakers(61).total, 1890, 2); - assert_eq_error_rate!(Staking::stakers(71).total, 1800, 2); - - check_exposure_all(); - check_nominator_all(); - }) -} - -#[test] -fn new_era_elects_correct_number_of_validators() { - ExtBuilder::default() - .nominate(true) - .validator_pool(true) - .fair(true) - .validator_count(1) - .build() - .execute_with(|| { - assert_eq!(Staking::validator_count(), 1); - assert_eq!(validator_controllers().len(), 1); - - System::set_block_number(1); - Session::on_initialize(System::block_number()); - - assert_eq!(validator_controllers().len(), 1); - check_exposure_all(); - check_nominator_all(); - }) -} - -#[test] -fn phragmen_should_not_overflow_validators() { - ExtBuilder::default().nominate(false).build().execute_with(|| { - let _ = Staking::chill(Origin::signed(10)); - let _ = Staking::chill(Origin::signed(20)); - - bond_validator(2, u64::max_value()); - bond_validator(4, u64::max_value()); - - bond_nominator(6, u64::max_value() / 2, vec![3, 5]); - bond_nominator(8, u64::max_value() / 2, vec![3, 5]); - - start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![4, 2]); - - // This test will fail this. Will saturate. - // check_exposure_all(); - assert_eq!(Staking::stakers(3).total, u64::max_value()); - assert_eq!(Staking::stakers(5).total, u64::max_value()); - }) -} - -#[test] -fn phragmen_should_not_overflow_nominators() { - ExtBuilder::default().nominate(false).build().execute_with(|| { - let _ = Staking::chill(Origin::signed(10)); - let _ = Staking::chill(Origin::signed(20)); - - bond_validator(2, u64::max_value() / 2); - bond_validator(4, u64::max_value() / 2); - - bond_nominator(6, u64::max_value(), vec![3, 5]); - bond_nominator(8, u64::max_value(), vec![3, 5]); - - start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![4, 2]); - - // Saturate. - assert_eq!(Staking::stakers(3).total, u64::max_value()); - assert_eq!(Staking::stakers(5).total, u64::max_value()); - }) -} - -#[test] -fn phragmen_should_not_overflow_ultimate() { - ExtBuilder::default().nominate(false).build().execute_with(|| { - bond_validator(2, u64::max_value()); - bond_validator(4, u64::max_value()); - - bond_nominator(6, u64::max_value(), vec![3, 5]); - bond_nominator(8, u64::max_value(), vec![3, 5]); - - start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![4, 2]); - - // Saturate. - assert_eq!(Staking::stakers(3).total, u64::max_value()); - assert_eq!(Staking::stakers(5).total, u64::max_value()); - }) -} - -#[test] -fn reward_validator_slashing_validator_doesnt_overflow() { - ExtBuilder::default().build().execute_with(|| { - let stake = u32::max_value() as u64 * 2; - let reward_slash = u32::max_value() as u64 * 2; - - // Assert multiplication overflows in balance arithmetic. - assert!(stake.checked_mul(reward_slash).is_none()); - - // Set staker - let _ = Balances::make_free_balance_be(&11, stake); - >::insert(&11, Exposure { total: stake, own: stake, others: vec![] }); - - // Check reward - let _ = Staking::reward_validator(&11, reward_slash); - assert_eq!(Balances::total_balance(&11), stake * 2); - - // Set staker - let _ = Balances::make_free_balance_be(&11, stake); - let _ = Balances::make_free_balance_be(&2, stake); - >::insert(&11, Exposure { total: stake, own: 1, others: vec![ - IndividualExposure { who: 2, value: stake - 1 } - ]}); - - // Check slashing - let _ = Staking::slash_validator(&11, reward_slash, &Staking::stakers(&11), &mut Vec::new()); - assert_eq!(Balances::total_balance(&11), stake - 1); - assert_eq!(Balances::total_balance(&2), 1); - }) -} - -#[test] -fn reward_from_authorship_event_handler_works() { - ExtBuilder::default().build().execute_with(|| { - use authorship::EventHandler; - - assert_eq!(>::author(), 11); - - >::note_author(11); - >::note_uncle(21, 1); - // An uncle author that is not currently elected doesn't get rewards, - // but the block producer does get reward for referencing it. - >::note_uncle(31, 1); - // Rewarding the same two times works. - >::note_uncle(11, 1); - - // Not mandatory but must be coherent with rewards - assert_eq!(>::get(), vec![21, 11]); - - // 21 is rewarded as an uncle producer - // 11 is rewarded as a block producer and uncle referencer and uncle producer - assert_eq!(CurrentEraPointsEarned::get().individual, vec![1, 20 + 2 * 3 + 1]); - assert_eq!(CurrentEraPointsEarned::get().total, 28); - }) -} - -#[test] -fn add_reward_points_fns_works() { - ExtBuilder::default().build().execute_with(|| { - let validators = >::current_elected(); - // Not mandatory but must be coherent with rewards - assert_eq!(validators, vec![21, 11]); - - >::reward_by_indices(vec![ - (0, 1), - (1, 1), - (2, 1), - (1, 1), - ]); - - >::reward_by_ids(vec![ - (21, 1), - (11, 1), - (31, 1), - (11, 1), - ]); - - assert_eq!(CurrentEraPointsEarned::get().individual, vec![2, 4]); - assert_eq!(CurrentEraPointsEarned::get().total, 6); - }) -} - -#[test] -fn unbonded_balance_is_not_slashable() { - ExtBuilder::default().build().execute_with(|| { - // total amount staked is slashable. - assert_eq!(Staking::slashable_balance_of(&11), 1000); - - assert_ok!(Staking::unbond(Origin::signed(10), 800)); - - // only the active portion. - assert_eq!(Staking::slashable_balance_of(&11), 200); - }) -} - -#[test] -fn era_is_always_same_length() { - // This ensures that the sessions is always of the same length if there is no forcing no - // session changes. - ExtBuilder::default().build().execute_with(|| { - start_era(1); - assert_eq!(Staking::current_era_start_session_index(), SessionsPerEra::get()); - - start_era(2); - assert_eq!(Staking::current_era_start_session_index(), SessionsPerEra::get() * 2); - - let session = Session::current_index(); - ForceEra::put(Forcing::ForceNew); - advance_session(); - assert_eq!(Staking::current_era(), 3); - assert_eq!(Staking::current_era_start_session_index(), session + 1); - - start_era(4); - assert_eq!(Staking::current_era_start_session_index(), session + SessionsPerEra::get() + 1); - }); -} - -#[test] -fn offence_forces_new_era() { - ExtBuilder::default().build().execute_with(|| { - Staking::on_offence( - &[OffenceDetails { - offender: ( - 11, - Staking::stakers(&11), - ), - reporters: vec![], - }], - &[Perbill::from_percent(5)], - ); - - assert_eq!(Staking::force_era(), Forcing::ForceNew); - }); -} - -#[test] -fn slashing_performed_according_exposure() { - // This test checks that slashing is performed according the exposure (or more precisely, - // historical exposure), not the current balance. - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::stakers(&11).own, 1000); - - // Handle an offence with a historical exposure. - Staking::on_offence( - &[OffenceDetails { - offender: ( - 11, - Exposure { - total: 500, - own: 500, - others: vec![], - }, - ), - reporters: vec![], - }], - &[Perbill::from_percent(50)], - ); - - // The stash account should be slashed for 250 (50% of 500). - assert_eq!(Balances::free_balance(&11), 1000 - 250); - }); -} - -#[test] -fn reporters_receive_their_slice() { - // This test verifies that the reporters of the offence receive their slice from the slashed - // amount. - ExtBuilder::default().build().execute_with(|| { - // The reporters' reward is calculated from the total exposure. - #[cfg(feature = "equalize")] - let initial_balance = 1250; - #[cfg(not(feature = "equalize"))] - let initial_balance = 1125; - - assert_eq!(Staking::stakers(&11).total, initial_balance); - - Staking::on_offence( - &[OffenceDetails { - offender: ( - 11, - Staking::stakers(&11), - ), - reporters: vec![1, 2], - }], - &[Perbill::from_percent(50)], - ); - - // initial_balance x 50% (slash fraction) x 10% (rewards slice) - let reward = initial_balance / 20 / 2; - assert_eq!(Balances::free_balance(&1), 10 + reward); - assert_eq!(Balances::free_balance(&2), 20 + reward); - }); -} - -#[test] -fn invulnerables_are_not_slashed() { - // For invulnerable validators no slashing is performed. - ExtBuilder::default().invulnerables(vec![11]).build().execute_with(|| { - #[cfg(feature = "equalize")] - let initial_balance = 1250; - #[cfg(not(feature = "equalize"))] - let initial_balance = 1375; - - assert_eq!(Balances::free_balance(&11), 1000); - assert_eq!(Balances::free_balance(&21), 2000); - assert_eq!(Staking::stakers(&21).total, initial_balance); - - Staking::on_offence( - &[ - OffenceDetails { - offender: (11, Staking::stakers(&11)), - reporters: vec![], - }, - OffenceDetails { - offender: (21, Staking::stakers(&21)), - reporters: vec![], - }, - ], - &[Perbill::from_percent(50), Perbill::from_percent(20)], - ); - - // The validator 11 hasn't been slashed, but 21 has been. - assert_eq!(Balances::free_balance(&11), 1000); - // 2000 - (0.2 * initial_balance) - assert_eq!(Balances::free_balance(&21), 2000 - (2 * initial_balance / 10)); - }); -} - -#[test] -fn dont_slash_if_fraction_is_zero() { - // Don't slash if the fraction is zero. - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Balances::free_balance(&11), 1000); - - Staking::on_offence( - &[OffenceDetails { - offender: ( - 11, - Staking::stakers(&11), - ), - reporters: vec![], - }], - &[Perbill::from_percent(0)], - ); - - // The validator hasn't been slashed. The new era is not forced. - assert_eq!(Balances::free_balance(&11), 1000); - assert_eq!(Staking::force_era(), Forcing::NotForcing); - }); -} diff --git a/srml/sudo/Cargo.toml b/srml/sudo/Cargo.toml deleted file mode 100644 index 152f32ab89363..0000000000000 --- a/srml/sudo/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "srml-sudo" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "rstd/std", - "runtime-io/std", - "sr-primitives/std", - "support/std", - "system/std", -] diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs deleted file mode 100644 index 7801384abcc2f..0000000000000 --- a/srml/sudo/src/lib.rs +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Sudo Module -//! -//! - [`sudo::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! -//! ## Overview -//! -//! The Sudo module allows for a single account (called the "sudo key") -//! to execute dispatchable functions that require a `Root` call -//! or designate a new account to replace them as the sudo key. -//! Only one account can be the sudo key at a time. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! Only the sudo key can call the dispatchable functions from the Sudo module. -//! -//! * `sudo` - Make a `Root` call to a dispatchable function. -//! * `set_key` - Assign a new account to be the sudo key. -//! -//! ## Usage -//! -//! ### Executing Privileged Functions -//! -//! The Sudo module itself is not intended to be used within other modules. -//! Instead, you can build "privileged functions" (i.e. functions that require `Root` origin) in other modules. -//! You can execute these privileged functions by calling `sudo` with the sudo key account. -//! Privileged functions cannot be directly executed via an extrinsic. -//! -//! Learn more about privileged functions and `Root` origin in the [`Origin`] type documentation. -//! -//! ### Simple Code Snippet -//! -//! This is an example of a module that exposes a privileged function: -//! -//! ``` -//! use support::{decl_module, dispatch::Result}; -//! use system::ensure_root; -//! -//! pub trait Trait: system::Trait {} -//! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! pub fn privileged_function(origin) -> Result { -//! ensure_root(origin)?; -//! -//! // do something... -//! -//! Ok(()) -//! } -//! } -//! } -//! # fn main() {} -//! ``` -//! -//! ## Genesis Config -//! -//! The Sudo module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). -//! You need to set an initial superuser account as the sudo `key`. -//! -//! ## Related Modules -//! -//! * [Consensus](../srml_consensus/index.html) -//! * [Democracy](../srml_democracy/index.html) -//! -//! [`Call`]: ./enum.Call.html -//! [`Trait`]: ./trait.Trait.html -//! [`Origin`]: https://docs.substrate.dev/docs/substrate-types - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::prelude::*; -use sr_primitives::{ - traits::{StaticLookup, Dispatchable}, weights::SimpleDispatchInfo, DispatchError, -}; -use support::{Parameter, decl_module, decl_event, decl_storage, ensure}; -use system::ensure_signed; - -pub trait Trait: system::Trait { - /// 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 it's working on. - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - /// Authenticates the sudo key and dispatches a function call with `Root` origin. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB write (event). - /// - Unknown weight of derivative `proposal` execution. - /// # - #[weight = SimpleDispatchInfo::FreeOperational] - fn sudo(origin, proposal: Box) { - // This is a public call, so we ensure that the origin is some signed account. - let sender = ensure_signed(origin)?; - ensure!(sender == Self::key(), "only the current sudo key can sudo"); - - let res = match proposal.dispatch(system::RawOrigin::Root.into()) { - Ok(_) => true, - Err(e) => { - let e: DispatchError = e.into(); - sr_primitives::print(e); - false - } - }; - - Self::deposit_event(RawEvent::Sudid(res)); - } - - /// Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo key. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB change. - /// # - 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); - } - - /// Authenticates the sudo key and dispatches a function call with `Signed` origin from - /// a given account. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB write (event). - /// - Unknown weight of derivative `proposal` execution. - /// # - #[weight = SimpleDispatchInfo::FixedOperational(0)] - fn sudo_as(origin, who: ::Source, proposal: Box) { - // This is a public call, so we ensure that the origin is some signed account. - let sender = ensure_signed(origin)?; - ensure!(sender == Self::key(), "only the current sudo key can sudo"); - - let who = T::Lookup::lookup(who)?; - - let res = match proposal.dispatch(system::RawOrigin::Signed(who).into()) { - Ok(_) => true, - Err(e) => { - let e: DispatchError = e.into(); - sr_primitives::print(e); - false - } - }; - - Self::deposit_event(RawEvent::SudoAsDone(res)); - } - } -} - -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), - /// A sudo just took place. - SudoAsDone(bool), - } -); - -decl_storage! { - trait Store for Module as Sudo { - /// The `AccountId` of the sudo key. - Key get(fn key) config(): T::AccountId; - } -} diff --git a/srml/support/Cargo.toml b/srml/support/Cargo.toml deleted file mode 100644 index 2b8c4cb9f98b8..0000000000000 --- a/srml/support/Cargo.toml +++ /dev/null @@ -1,41 +0,0 @@ -[package] -name = "srml-support" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -log = "0.4" -serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } -srml-metadata = { path = "../metadata", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -srml-support-procedural = { package = "srml-support-procedural", path = "./procedural" } -paste = "0.1.6" -once_cell = { version = "0.2.4", default-features = false, optional = true } -bitmask = { version = "0.5.0", default-features = false } -impl-trait-for-tuples = "0.1.2" - -[dev-dependencies] -pretty_assertions = "0.6.1" -srml-system = { path = "../system" } - -[features] -default = ["std"] -std = [ - "once_cell", - "bitmask/std", - "serde", - "runtime-io/std", - "codec/std", - "rstd/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 deleted file mode 100644 index 91b4ca507497e..0000000000000 --- a/srml/support/procedural/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "srml-support-procedural" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -srml-support-procedural-tools = { package = "srml-support-procedural-tools", path = "./tools" } -sr-api-macros = { path = "../../../core/sr-api-macros" } - -proc-macro2 = "0.4.27" -quote = "0.6.12" -syn = { version = "0.15.44", features = ["full"] } diff --git a/srml/support/procedural/src/lib.rs b/srml/support/procedural/src/lib.rs deleted file mode 100644 index 792f739f1c357..0000000000000 --- a/srml/support/procedural/src/lib.rs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -// tag::description[] -//! Proc macro of Support code for the runtime. -// end::description[] - -#![recursion_limit="512"] - -extern crate proc_macro; - -mod storage; - -use proc_macro::TokenStream; - -/// Declares strongly-typed wrappers around codec-compatible types in storage. -/// -/// ## Example -/// -/// ```nocompile -/// decl_storage! { -/// trait Store for Module as Example { -/// Foo get(fn foo) config(): u32=12; -/// Bar: map u32 => u32; -/// pub Zed build(|config| vec![(0, 0)]): linked_map u32 => u32; -/// } -/// } -/// ``` -/// -/// Declaration is set with the header `(pub) trait Store for Module as Example`, -/// with `Store` a (pub) trait generated associating each storage item to the `Module` and -/// `as Example` setting the prefix used for storage items of this module. `Example` must be unique: -/// another module with the same name and the same inner storage item name will conflict. -/// `Example` is called the module prefix. -/// -/// note: For instantiable modules the module prefix is prepended with instance -/// prefix. Instance prefix is "" for default instance and "Instance$n" for instance number $n. -/// Thus, instance 3 of module Example has a module prefix of `Instance3Example` -/// -/// Basic storage consists of a name and a type; supported types are: -/// -/// * Value: `Foo: type`: Implements the -/// [`StorageValue`](../srml_support/storage/trait.StorageValue.html) trait using the -/// [`StorageValue generator`](../srml_support/storage/generator/trait.StorageValue.html). -/// The generator `unhashed_key` is `$module_prefix ++ " " ++ $storage_name` -/// -/// * Map: `Foo: map hasher($hash) type => type`: Implements the -/// [`StorageMap`](../srml_support/storage/trait.StorageMap.html) trait using the -/// [`StorageMap generator`](../srml_support/storage/generator/trait.StorageMap.html). -/// -/// `$hash` representing a choice of hashing algorithms available in the -/// [`Hashable`](../srml_support/trait.Hashable.html) trait. -/// -/// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher -/// with care, see generator documentation. -/// -/// The generator is implemented with: -/// * `prefix`: `$module_prefix ++ " " ++ $storage_name` -/// * `Hasher`: $hash -/// -/// * Linked map: `Foo: linked_map hasher($hash) type => type`: Implements the -/// [`StorageLinkedMap`](../srml_support/storage/trait.StorageLinkedMap.html) trait using the -/// [`StorageLinkedMap generator`](../srml_support/storage/generator/trait.StorageLinkedMap.html). -/// -/// `$hash` representing a choice of hashing algorithms available in the -/// [`Hashable`](../srml_support/trait.Hashable.html) trait. -/// -/// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher -/// with care, see generator documentation. -/// -/// The generator is implemented with: -/// * `prefix`: `$module_prefix ++ " " ++ $storage_name` -/// * `head_key`: `"head of " ++ $module_prefix ++ " " ++ $storage_name` -/// * `Hasher`: $hash -/// -/// * Double map: `Foo: double_map hasher($hash1) u32, $hash2(u32) => u32`: Implements the -/// [`StorageDoubleMap`](../srml_support/storage/trait.StorageDoubleMap.html) trait using the -/// [`StorageDoubleMap generator`](../srml_support/storage/generator/trait.StorageDoubleMap.html). -/// -/// `$hash1` and `$hash2` representing choices of hashing algorithms available in the -/// [`Hashable`](../srml_support/trait.Hashable.html) trait. They must be choosen with care, see -/// generator documentation. -/// -/// `hasher($hash)` is optional and its default is `blake2_256`. -/// -/// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher -/// with care, see generator documentation. -/// -/// If the first key is untrusted, a cryptographic `hasher` such as `blake2_256` must be used. -/// Otherwise, other values of all storage items can be compromised. -/// -/// If the second key is untrusted, a cryptographic `hasher` such as `blake2_256` must be used. -/// Otherwise, other items in storage with the same first key can be compromised. -/// -/// The generator is implemented with: -/// * `key1_prefix`: `$module_prefix ++ " " ++ $storage_name` -/// * `Hasher1`: $hash1 -/// * `Hasher2`: $hash2 -/// -/// Supported hashers (ordered from least to best security): -/// -/// * `twox_64_concat` - TwoX with 64bit + key concatenated. -/// * `twox_128` - TwoX with 128bit. -/// * `twox_256` - TwoX with with 256bit. -/// * `blake2_128` - Blake2 with 128bit. -/// * `blake2_256` - Blake2 with 256bit. -/// -/// Basic storage can be extended as such: -/// -/// `#vis #name get(fn #getter) config(#field_name) build(#closure): #type = #default;` -/// -/// * `#vis`: Set the visibility of the structure. `pub` or nothing. -/// * `#name`: Name of the storage item, used as a prefix in storage. -/// * [optional] `get(fn #getter)`: Implements the function #getter to `Module`. -/// * [optional] `config(#field_name)`: `field_name` is optional if get is set. -/// Will include the item in `GenesisConfig`. -/// * [optional] `build(#closure)`: Closure called with storage overlays. -/// * `#type`: Storage type. -/// * [optional] `#default`: Value returned when none. -/// -/// Storage items are accessible in multiple ways: -/// -/// * The structure: `Foo` or `Foo::` depending if the value type is generic or not. -/// * The `Store` trait structure: ` as Store>::Foo` -/// * The getter on the module that calls get on the structure: `Module::::foo()` -/// -/// ## GenesisConfig -/// -/// An optional `GenesisConfig` struct for storage initialization can be defined, either -/// when at least one storage field requires default initialization -/// (both `get` and `config` or `build`), or specifically as in: -/// -/// ```nocompile -/// decl_storage! { -/// trait Store for Module as Example { -/// -/// // Your storage items -/// } -/// add_extra_genesis { -/// config(genesis_field): GenesisFieldType; -/// config(genesis_field2): GenesisFieldType; -/// ... -/// build(|_: &Self| { -/// // Modification of storage -/// }) -/// } -/// } -/// ``` -/// -/// This struct can be exposed as `ExampleConfig` by the `construct_runtime!` macro like follows: -/// -/// ```nocompile -/// construct_runtime!( -/// pub enum Runtume with ... { -/// ..., -/// Example: example::{Module, Storage, ..., Config}, -/// ..., -/// } -/// ); -/// ``` -/// -/// ### Module with Instances -/// -/// The `decl_storage!` macro supports building modules with instances with the following syntax -/// (`DefaultInstance` type is optional): -/// -/// ```nocompile -/// trait Store for Module, I: Instance=DefaultInstance> as Example {} -/// ``` -/// -/// Accessing the structure no requires the instance as generic parameter: -/// * `Foo::` if the value type is not generic -/// * `Foo::` if the value type is generic -/// -/// ## Where clause -/// -/// This macro supports a where clause which will be replicated to all generated types. -/// -/// ```nocompile -/// trait Store for Module as Example where T::AccountId: std::fmt::Display {} -/// ``` -/// -/// ## Limitations -/// -/// # Instancing and generic `GenesisConfig` -/// -/// If your module supports instancing and you see an error like `parameter `I` is never used` for -/// your `decl_storage!`, you are hitting a limitation of the current implementation. You probably -/// try to use an associated type of a non-instantiable trait. To solve this, add the following to -/// your macro call: -/// -/// ```nocompile -/// add_extra_genesis { -/// config(phantom): std::marker::PhantomData, -/// } -/// ... -/// -/// This adds a field to your `GenesisConfig` with the name `phantom` that you can initialize with -/// `Default::default()`. -/// -#[proc_macro] -pub fn decl_storage(input: TokenStream) -> TokenStream { - storage::decl_storage_impl(input) -} diff --git a/srml/support/procedural/src/storage/genesis_config/builder_def.rs b/srml/support/procedural/src/storage/genesis_config/builder_def.rs deleted file mode 100644 index fc425e4a6d532..0000000000000 --- a/srml/support/procedural/src/storage/genesis_config/builder_def.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Builder logic definition used to build genesis storage. - -use srml_support_procedural_tools::syn_ext as ext; -use proc_macro2::TokenStream; -use syn::spanned::Spanned; -use quote::{quote, quote_spanned}; -use super::super::{DeclStorageDefExt, StorageLineTypeDef}; - -/// Definition of builder blocks, each block insert some value in the storage. -/// They must be called inside externalities, and with `self` being the genesis config. -pub struct BuilderDef { - /// Contains: - /// * build block for storage with build attribute. - /// * build block for storage with config attribute and no build attribute. - /// * build block for extra genesis build expression. - pub blocks: Vec, - /// The build blocks requires generic traits. - pub is_generic: bool, -} - -impl BuilderDef { - pub fn from_def(scrate: &TokenStream, def: &DeclStorageDefExt) -> Self { - let mut blocks = Vec::new(); - let mut is_generic = false; - - for line in def.storage_lines.iter() { - let storage_struct = &line.storage_struct; - let storage_trait = &line.storage_trait; - let value_type = &line.value_type; - - // Contains the data to inset at genesis either from build or config. - let mut data = None; - - if let Some(builder) = &line.build { - is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic); - is_generic |= line.is_generic; - - data = Some(quote_spanned!(builder.span() => &(#builder)(self))); - } else if let Some(config) = &line.config { - is_generic |= line.is_generic; - - data = Some(quote!(&self.#config;)); - }; - - if let Some(data) = data { - blocks.push(match &line.storage_type { - StorageLineTypeDef::Simple(_) => { - quote!{{ - let v: &#value_type = #data; - <#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v); - }} - }, - StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => { - let key = &map.key; - quote!{{ - let data: &#scrate::rstd::vec::Vec<(#key, #value_type)> = #data; - data.iter().for_each(|(k, v)| { - <#storage_struct as #scrate::#storage_trait>::insert::< - &#key, &#value_type - >(k, v); - }); - }} - }, - StorageLineTypeDef::DoubleMap(map) => { - let key1 = &map.key1; - let key2 = &map.key2; - quote!{{ - let data: &#scrate::rstd::vec::Vec<(#key1, #key2, #value_type)> = #data; - data.iter().for_each(|(k1, k2, v)| { - <#storage_struct as #scrate::#storage_trait>::insert::< - &#key1, &#key2, &#value_type - >(k1, k2, v); - }); - }} - }, - }); - } - } - - if let Some(builder) = def.extra_genesis_build.as_ref() { - is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic); - - blocks.push(quote_spanned! { builder.span() => - let extra_genesis_builder: fn(&Self) = #builder; - extra_genesis_builder(self); - }); - } - - - Self { - blocks, - is_generic, - } - } -} diff --git a/srml/support/procedural/src/storage/genesis_config/mod.rs b/srml/support/procedural/src/storage/genesis_config/mod.rs deleted file mode 100644 index 2d4d4af3861ed..0000000000000 --- a/srml/support/procedural/src/storage/genesis_config/mod.rs +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Declaration of genesis config structure and implementation of build storage trait and -//! functions. - -use proc_macro2::{TokenStream, Span}; -use quote::quote; -use super::{DeclStorageDefExt, instance_trait::DEFAULT_INSTANTIABLE_TRAIT_NAME}; -use genesis_config_def::GenesisConfigDef; -use builder_def::BuilderDef; - -mod genesis_config_def; -mod builder_def; - -const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance"; - -fn decl_genesis_config_and_impl_default( - scrate: &TokenStream, - genesis_config: &GenesisConfigDef, -) -> TokenStream { - let config_fields = genesis_config.fields.iter().map(|field| { - let (name, typ, doc) = (&field.name, &field.typ, &field.doc); - quote!( #( #[ #doc] )* pub #name: #typ, ) - }); - - let config_field_defaults = genesis_config.fields.iter().map(|field| { - let (name, default, doc) = (&field.name, &field.default, &field.doc); - quote!( #( #[ #doc] )* #name: #default, ) - }); - - let serde_bug_bound = if !genesis_config.fields.is_empty() { - let mut b_ser = String::new(); - let mut b_dser = String::new(); - - for typ in genesis_config.fields.iter().map(|c| &c.typ) { - let typ = quote!( #typ ); - b_ser.push_str(&format!("{} : {}::serde::Serialize, ", typ, scrate)); - b_dser.push_str(&format!("{} : {}::serde::de::DeserializeOwned, ", typ, scrate)); - } - - quote! { - #[serde(bound(serialize = #b_ser))] - #[serde(bound(deserialize = #b_dser))] - } - } else { - quote!() - }; - - let genesis_struct_decl = &genesis_config.genesis_struct_decl; - let genesis_struct = &genesis_config.genesis_struct; - let genesis_impl = &genesis_config.genesis_impl; - let genesis_where_clause = &genesis_config.genesis_where_clause; - - quote!( - #[derive(#scrate::Serialize, #scrate::Deserialize)] - #[cfg(feature = "std")] - #[serde(rename_all = "camelCase")] - #[serde(deny_unknown_fields)] - #serde_bug_bound - pub struct GenesisConfig#genesis_struct_decl #genesis_where_clause { - #( #config_fields )* - } - - #[cfg(feature = "std")] - impl#genesis_impl Default for GenesisConfig#genesis_struct #genesis_where_clause { - fn default() -> Self { - GenesisConfig { - #( #config_field_defaults )* - } - } - } - ) -} - -fn impl_build_storage( - scrate: &TokenStream, - def: &DeclStorageDefExt, - genesis_config: &GenesisConfigDef, - builders: &BuilderDef, -) -> TokenStream { - let runtime_generic = &def.module_runtime_generic; - let runtime_trait = &def.module_runtime_trait; - let optional_instance = &def.optional_instance; - let optional_instance_bound = &def.optional_instance_bound; - let where_clause = &def.where_clause; - - let inherent_instance = def.optional_instance.clone().unwrap_or_else(|| { - let name = syn::Ident::new(DEFAULT_INSTANCE_NAME, Span::call_site()); - quote!( #name ) - }); - let inherent_instance_bound = def.optional_instance_bound.clone().unwrap_or_else(|| { - let bound = syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site()); - quote!( #inherent_instance: #bound ) - }); - - let build_storage_impl = quote!( - <#runtime_generic: #runtime_trait, #inherent_instance_bound> - ); - - let genesis_struct = &genesis_config.genesis_struct; - let genesis_impl = &genesis_config.genesis_impl; - let genesis_where_clause = &genesis_config.genesis_where_clause; - - let ( - fn_generic, - fn_traitinstance, - fn_where_clause - ) = if !genesis_config.is_generic && builders.is_generic { - ( - quote!( <#runtime_generic: #runtime_trait, #optional_instance_bound> ), - quote!( #runtime_generic, #optional_instance ), - Some(&def.where_clause), - ) - } else { - (quote!(), quote!(), None) - }; - - let builder_blocks = &builders.blocks; - - let build_storage_impl_trait = quote!( - #scrate::sr_primitives::BuildModuleGenesisStorage<#runtime_generic, #inherent_instance> - ); - - quote!{ - #[cfg(feature = "std")] - impl#genesis_impl GenesisConfig#genesis_struct #genesis_where_clause { - pub fn build_storage #fn_generic (&self) -> std::result::Result< - ( - #scrate::sr_primitives::StorageOverlay, - #scrate::sr_primitives::ChildrenStorageOverlay, - ), - String - > #fn_where_clause { - let mut storage = (Default::default(), Default::default()); - self.assimilate_storage::<#fn_traitinstance>(&mut storage)?; - Ok(storage) - } - - /// Assimilate the storage for this module into pre-existing overlays. - pub fn assimilate_storage #fn_generic ( - &self, - tuple_storage: &mut ( - #scrate::sr_primitives::StorageOverlay, - #scrate::sr_primitives::ChildrenStorageOverlay, - ), - ) -> std::result::Result<(), String> #fn_where_clause { - #scrate::with_storage(tuple_storage, || { - #( #builder_blocks )* - Ok(()) - }) - } - } - - #[cfg(feature = "std")] - impl#build_storage_impl #build_storage_impl_trait for GenesisConfig#genesis_struct - #where_clause - { - fn build_module_genesis_storage( - &self, - storage: &mut ( - #scrate::sr_primitives::StorageOverlay, - #scrate::sr_primitives::ChildrenStorageOverlay, - ), - ) -> std::result::Result<(), String> { - self.assimilate_storage::<#fn_traitinstance> (storage) - } - } - } -} - -pub fn genesis_config_and_build_storage( - scrate: &TokenStream, - def: &DeclStorageDefExt, -) -> TokenStream { - let builders = BuilderDef::from_def(scrate, def); - if !builders.blocks.is_empty() { - let genesis_config = &GenesisConfigDef::from_def(def); - let decl_genesis_config_and_impl_default = - decl_genesis_config_and_impl_default(scrate, genesis_config); - let impl_build_storage = impl_build_storage(scrate, def, genesis_config, &builders); - - quote!{ - #decl_genesis_config_and_impl_default - #impl_build_storage - } - } else { - quote!() - } -} diff --git a/srml/support/procedural/src/storage/instance_trait.rs b/srml/support/procedural/src/storage/instance_trait.rs deleted file mode 100644 index 1a7add89a4b80..0000000000000 --- a/srml/support/procedural/src/storage/instance_trait.rs +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Implementation of the trait instance and the instance structures implementing it. -//! (For not instantiable traits there is still the inherent instance implemented). - -use proc_macro2::{TokenStream, Span}; -use quote::quote; -use super::{DeclStorageDefExt, StorageLineTypeDef}; - -const NUMBER_OF_INSTANCE: usize = 16; -const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; -pub(crate) const DEFAULT_INSTANTIABLE_TRAIT_NAME: &str = "__GeneratedInstantiable"; - -// prefix for consts in trait Instance -pub(crate) const PREFIX_FOR: &str = "PREFIX_FOR_"; -pub(crate) const HEAD_KEY_FOR: &str = "HEAD_KEY_FOR_"; - -// Used to generate the const: -// `const $name: &'static str = $value_prefix ++ instance_prefix ++ $value_suffix` -struct InstanceConstDef { - name: syn::Ident, - value_prefix: String, - value_suffix: String, -} - -// Used to generate an instance implementation. -struct InstanceDef { - prefix: String, - instance_struct: syn::Ident, - doc: TokenStream, -} - -pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { - let mut impls = TokenStream::new(); - - let mut const_defs = vec![]; - - for line in def.storage_lines.iter() { - let storage_prefix = format!("{} {}", def.crate_name, line.name); - - let const_name = syn::Ident::new( - &format!("{}{}", PREFIX_FOR, line.name.to_string()), proc_macro2::Span::call_site() - ); - const_defs.push(InstanceConstDef { - name: const_name, - value_prefix: String::new(), - value_suffix: storage_prefix.clone(), - }); - - if let StorageLineTypeDef::LinkedMap(_) = line.storage_type { - let const_name = syn::Ident::new( - &format!("{}{}", HEAD_KEY_FOR, line.name.to_string()), proc_macro2::Span::call_site() - ); - const_defs.push(InstanceConstDef { - name: const_name, - value_prefix: "head of ".into(), - value_suffix: storage_prefix, - }); - } - } - - impls.extend(create_instance_trait(&const_defs, def)); - - // Implementation of instances. - if let Some(module_instance) = &def.module_instance { - let instance_defs = (0..NUMBER_OF_INSTANCE) - .map(|i| { - let name = format!("Instance{}", i); - InstanceDef { - instance_struct: syn::Ident::new(&name, proc_macro2::Span::call_site()), - prefix: name, - doc: quote!(#[doc=r"Module instance"]), - } - }) - .chain( - module_instance.instance_default.as_ref().map(|ident| InstanceDef { - prefix: String::new(), - instance_struct: ident.clone(), - doc: quote!(#[doc=r"Default module instance"]), - }) - ); - - for instance_def in instance_defs { - impls.extend(create_and_impl_instance_struct(scrate, &instance_def, &const_defs, def)); - } - } - - // The name of the inherently available instance. - let inherent_instance = syn::Ident::new(INHERENT_INSTANCE_NAME, Span::call_site()); - - // Implementation of inherent instance. - if let Some(default_instance) = def.module_instance.as_ref() - .and_then(|i| i.instance_default.as_ref()) - { - impls.extend(quote! { - #[doc(hidden)] - pub type #inherent_instance = #default_instance; - }); - } else { - let instance_def = InstanceDef { - prefix: String::new(), - instance_struct: inherent_instance, - doc: quote!(#[doc(hidden)]), - }; - impls.extend(create_and_impl_instance_struct(scrate, &instance_def, &const_defs, def)); - } - - impls -} - -fn create_instance_trait( - const_defs: &[InstanceConstDef], - def: &DeclStorageDefExt, -) -> TokenStream { - let instance_trait = def.module_instance.as_ref().map(|i| i.instance_trait.clone()) - .unwrap_or_else(|| syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); - - let mut const_impls = TokenStream::new(); - for const_def in const_defs { - let const_name = &const_def.name; - const_impls.extend(quote! { - const #const_name: &'static str; - }); - } - - let optional_hide = if def.module_instance.is_some() { - quote!() - } else { - quote!(#[doc(hidden)]) - }; - - quote! { - /// Tag a type as an instance of a module. - /// - /// Defines storage prefixes, they must be unique. - #optional_hide - pub trait #instance_trait: 'static { - /// The prefix used by any storage entry of an instance. - const PREFIX: &'static str; - #const_impls - } - } -} - -fn create_and_impl_instance_struct( - scrate: &TokenStream, - instance_def: &InstanceDef, - const_defs: &[InstanceConstDef], - def: &DeclStorageDefExt, -) -> TokenStream { - let mut const_impls = TokenStream::new(); - - for const_def in const_defs { - let const_value = format!( - "{}{}{}", const_def.value_prefix, instance_def.prefix, const_def.value_suffix - ); - let const_name = &const_def.name; - - const_impls.extend(quote! { - const #const_name: &'static str = #const_value; - }); - } - - let instance_trait = def.module_instance.as_ref().map(|i| i.instance_trait.clone()) - .unwrap_or_else(|| syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); - - let instance_struct = &instance_def.instance_struct; - let prefix = format!("{}{}", instance_def.prefix, def.crate_name.to_string()); - let doc = &instance_def.doc; - - quote! { - // Those trait are derived because of wrong bounds for generics - #[derive( - Clone, Eq, PartialEq, - #scrate::codec::Encode, - #scrate::codec::Decode, - #scrate::RuntimeDebug, - )] - #doc - pub struct #instance_struct; - impl #instance_trait for #instance_struct { - const PREFIX: &'static str = #prefix; - #const_impls - } - } -} diff --git a/srml/support/procedural/src/storage/metadata.rs b/srml/support/procedural/src/storage/metadata.rs deleted file mode 100644 index e280c7d8a20c6..0000000000000 --- a/srml/support/procedural/src/storage/metadata.rs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Implementation of `storage_metadata` on module structure, used by construct_runtime. - -use srml_support_procedural_tools::clean_type_string; -use proc_macro2::TokenStream; -use quote::quote; -use super::{DeclStorageDefExt, StorageLineDefExt, StorageLineTypeDef}; - -fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) -> TokenStream { - let value_type = &line.value_type; - let value_type = clean_type_string("e!( #value_type ).to_string()); - match &line.storage_type { - StorageLineTypeDef::Simple(_) => { - quote!{ - #scrate::metadata::StorageEntryType::Plain( - #scrate::metadata::DecodeDifferent::Encode(#value_type), - ) - } - }, - StorageLineTypeDef::Map(map) => { - let hasher = map.hasher.into_metadata(); - let key = &map.key; - let key = clean_type_string("e!(#key).to_string()); - quote!{ - #scrate::metadata::StorageEntryType::Map { - hasher: #scrate::metadata::#hasher, - key: #scrate::metadata::DecodeDifferent::Encode(#key), - value: #scrate::metadata::DecodeDifferent::Encode(#value_type), - is_linked: false, - } - } - }, - StorageLineTypeDef::LinkedMap(map) => { - let hasher = map.hasher.into_metadata(); - let key = &map.key; - let key = clean_type_string("e!(#key).to_string()); - quote!{ - #scrate::metadata::StorageEntryType::Map { - hasher: #scrate::metadata::#hasher, - key: #scrate::metadata::DecodeDifferent::Encode(#key), - value: #scrate::metadata::DecodeDifferent::Encode(#value_type), - is_linked: true, - } - } - }, - StorageLineTypeDef::DoubleMap(map) => { - let hasher1 = map.hasher1.into_metadata(); - let hasher2 = map.hasher2.into_metadata(); - let key1 = &map.key1; - let key1 = clean_type_string("e!(#key1).to_string()); - let key2 = &map.key2; - let key2 = clean_type_string("e!(#key2).to_string()); - quote!{ - #scrate::metadata::StorageEntryType::DoubleMap { - hasher: #scrate::metadata::#hasher1, - key1: #scrate::metadata::DecodeDifferent::Encode(#key1), - key2: #scrate::metadata::DecodeDifferent::Encode(#key2), - value: #scrate::metadata::DecodeDifferent::Encode(#value_type), - key2_hasher: #scrate::metadata::#hasher2, - } - } - }, - } -} - -fn default_byte_getter( - scrate: &TokenStream, - line: &StorageLineDefExt, - def: &DeclStorageDefExt, -) -> (TokenStream, TokenStream) { - let default = line.default_value.as_ref().map(|d| quote!( #d )) - .unwrap_or_else(|| quote!( Default::default() )); - - let str_name = line.name.to_string(); - let struct_name = syn::Ident::new(&("__GetByteStruct".to_string() + &str_name), line.name.span()); - let cache_name = syn::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), line.name.span()); - - let runtime_generic = &def.module_runtime_generic; - let runtime_trait = &def.module_runtime_trait; - let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default; - let optional_instance_bound = &def.optional_instance_bound; - let optional_instance = &def.optional_instance; - let optional_comma_instance = optional_instance.as_ref().map(|i| quote!(, #i)); - let where_clause = &def.where_clause; - - let query_type = &line.query_type; - - let struct_def = quote! { - #[doc(hidden)] - pub struct #struct_name< - #runtime_generic, #optional_instance_bound_optional_default - >(pub #scrate::rstd::marker::PhantomData<(#runtime_generic #optional_comma_instance)>); - - #[cfg(feature = "std")] - #[allow(non_upper_case_globals)] - static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::rstd::vec::Vec> = - #scrate::once_cell::sync::OnceCell::new(); - - #[cfg(feature = "std")] - impl<#runtime_generic: #runtime_trait, #optional_instance_bound> - #scrate::metadata::DefaultByte - for #struct_name<#runtime_generic, #optional_instance> - #where_clause - { - fn default_byte(&self) -> #scrate::rstd::vec::Vec { - use #scrate::codec::Encode; - #cache_name.get_or_init(|| { - let def_val: #query_type = #default; - <#query_type as Encode>::encode(&def_val) - }).clone() - } - } - - unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Send - for #struct_name<#runtime_generic, #optional_instance> #where_clause {} - - unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Sync - for #struct_name<#runtime_generic, #optional_instance> #where_clause {} - - #[cfg(not(feature = "std"))] - impl<#runtime_generic: #runtime_trait, #optional_instance_bound> - #scrate::metadata::DefaultByte - for #struct_name<#runtime_generic, #optional_instance> - #where_clause - { - fn default_byte(&self) -> #scrate::rstd::vec::Vec { - use #scrate::codec::Encode; - let def_val: #query_type = #default; - <#query_type as Encode>::encode(&def_val) - } - } - }; - let struct_instance = quote!( - #struct_name::<#runtime_generic, #optional_instance>(#scrate::rstd::marker::PhantomData) - ); - - (struct_def, struct_instance) -} - -pub fn impl_metadata(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { - let mut entries = TokenStream::new(); - let mut default_byte_getter_struct_defs = TokenStream::new(); - - for line in def.storage_lines.iter() { - let str_name = line.name.to_string(); - - let modifier = if line.is_option { - quote!(#scrate::metadata::StorageEntryModifier::Optional) - } else { - quote!(#scrate::metadata::StorageEntryModifier::Default) - }; - - let ty = storage_line_metadata_type(scrate, line); - - let ( - default_byte_getter_struct_def, - default_byte_getter_struct_instance, - ) = default_byte_getter(scrate, line, def); - - let mut docs = TokenStream::new(); - for attr in line.attrs.iter().filter_map(|v| v.parse_meta().ok()) { - if let syn::Meta::NameValue(meta) = attr { - if meta.ident == "doc" { - let lit = meta.lit; - docs.extend(quote!(#lit,)); - } - } - } - - let entry = quote! { - #scrate::metadata::StorageEntryMetadata { - name: #scrate::metadata::DecodeDifferent::Encode(#str_name), - modifier: #modifier, - ty: #ty, - default: #scrate::metadata::DecodeDifferent::Encode( - #scrate::metadata::DefaultByteGetter(&#default_byte_getter_struct_instance) - ), - documentation: #scrate::metadata::DecodeDifferent::Encode(&[ #docs ]), - }, - }; - - default_byte_getter_struct_defs.extend(default_byte_getter_struct_def); - entries.extend(entry); - } - - let prefix = if let Some(instance) = &def.module_instance { - let instance_generic = &instance.instance_generic; - quote!(#instance_generic::PREFIX) - } else { - let prefix = def.crate_name.to_string(); - quote!(#prefix) - }; - - let store_metadata = quote!( - #scrate::metadata::StorageMetadata { - prefix: #scrate::metadata::DecodeDifferent::Encode(#prefix), - entries: #scrate::metadata::DecodeDifferent::Encode(&[ #entries ][..]), - } - ); - - let module_struct = &def.module_struct; - let module_impl = &def.module_impl; - let where_clause = &def.where_clause; - - quote!( - #default_byte_getter_struct_defs - - impl#module_impl #module_struct #where_clause { - #[doc(hidden)] - pub fn storage_metadata() -> #scrate::metadata::StorageMetadata { - #store_metadata - } - } - ) -} diff --git a/srml/support/procedural/src/storage/mod.rs b/srml/support/procedural/src/storage/mod.rs deleted file mode 100644 index 9a6931d87e9c8..0000000000000 --- a/srml/support/procedural/src/storage/mod.rs +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! `decl_storage` input definition and expansion. - -mod storage_struct; -mod parse; -mod store_trait; -mod getters; -mod metadata; -mod instance_trait; -mod genesis_config; - -use quote::quote; -use srml_support_procedural_tools::{ - generate_crate_access, generate_hidden_includes, syn_ext as ext -}; - -/// All informations contained in input of decl_storage -pub struct DeclStorageDef { - /// Name of the module used to import hidden imports. - hidden_crate: Option, - /// Visibility of store trait. - visibility: syn::Visibility, - /// Name of store trait: usually `Store`. - store_trait: syn::Ident, - /// Module name used by construct_runtime: usually `Module`. - module_name: syn::Ident, - /// Usually `T`. - module_runtime_generic: syn::Ident, - /// Usually `Trait` - module_runtime_trait: syn::Path, - /// For instantiable module: usually `I: Instance=DefaultInstance`. - module_instance: Option, - /// Where claused used to constrain T and I even more. - where_clause: Option, - /// The extra build function used to build storage at genesis. - extra_genesis_build: Option, - /// The extra genesis config fields. - extra_genesis_config_lines: Vec, - /// Definition of storages. - storage_lines: Vec, - /// Name of the crate, used for storage prefixes. - crate_name: syn::Ident, -} - -impl syn::parse::Parse for DeclStorageDef { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - parse::parse(input) - } -} - -/// Extended version of `DeclStorageDef` with useful precomputed value. -pub struct DeclStorageDefExt { - /// Name of the module used to import hidden imports. - hidden_crate: Option, - /// Visibility of store trait. - visibility: syn::Visibility, - /// Name of store trait: usually `Store`. - store_trait: syn::Ident, - /// Module name used by construct_runtime: usually `Module`. - #[allow(unused)] - module_name: syn::Ident, - /// Usually `T`. - module_runtime_generic: syn::Ident, - /// Usually `Trait`. - module_runtime_trait: syn::Path, - /// For instantiable module: usually `I: Instance=DefaultInstance`. - module_instance: Option, - /// Where claused used to constrain T and I even more. - where_clause: Option, - /// The extra build function used to build storage at genesis. - extra_genesis_build: Option, - /// The extra genesis config fields. - extra_genesis_config_lines: Vec, - /// Definition of storages. - storage_lines: Vec, - /// Name of the crate, used for storage prefixes. - crate_name: syn::Ident, - /// Full struct expansion: `Module`. - module_struct: proc_macro2::TokenStream, - /// Impl block for module: ``. - module_impl: proc_macro2::TokenStream, - /// For instantiable: `I`. - optional_instance: Option, - /// For instantiable: `I: Instance`. - optional_instance_bound: Option, - /// For instantiable: `I: Instance = DefaultInstance`. - optional_instance_bound_optional_default: Option, -} - -impl From for DeclStorageDefExt { - fn from(mut def: DeclStorageDef) -> Self { - let storage_lines = def.storage_lines.drain(..).collect::>(); - let storage_lines = storage_lines.into_iter() - .map(|line| StorageLineDefExt::from_def(line, &def)) - .collect(); - - let ( - optional_instance, - optional_instance_bound, - optional_instance_bound_optional_default, - ) = if let Some(instance) = def.module_instance.as_ref() { - let instance_generic = &instance.instance_generic; - let instance_trait= &instance.instance_trait; - let optional_equal_instance_default = instance.instance_default.as_ref() - .map(|d| quote!( = #d )); - ( - Some(quote!(#instance_generic)), - Some(quote!(#instance_generic: #instance_trait)), - Some(quote!(#instance_generic: #instance_trait #optional_equal_instance_default)), - ) - } else { - (None, None, None) - }; - - let module_runtime_generic = &def.module_runtime_generic; - let module_runtime_trait = &def.module_runtime_trait; - let module_name = &def.module_name; - - let module_struct = quote!( - #module_name<#module_runtime_generic, #optional_instance> - ); - - let module_impl = quote!( - <#module_runtime_generic: #module_runtime_trait + 'static, #optional_instance_bound> - ); - - Self { - hidden_crate: def.hidden_crate, - visibility: def.visibility, - store_trait: def.store_trait, - module_name: def.module_name, - module_runtime_generic: def.module_runtime_generic, - module_runtime_trait: def.module_runtime_trait, - module_instance: def.module_instance, - where_clause: def.where_clause, - extra_genesis_build: def.extra_genesis_build, - extra_genesis_config_lines: def.extra_genesis_config_lines, - crate_name: def.crate_name, - storage_lines, - module_struct, - module_impl, - optional_instance, - optional_instance_bound, - optional_instance_bound_optional_default, - } - } -} - -/// Usually `I: Instance=DefaultInstance`. -pub struct ModuleInstanceDef { - /// Usually: `I`. - instance_generic: syn::Ident, - /// Usually: `Instance`. - instance_trait: syn::Ident, - /// Usually: `DefaultInstance`. - instance_default: Option, -} - -pub struct StorageLineDef { - attrs: Vec, - /// Visibility of the storage struct. - visibility: syn::Visibility, - name: syn::Ident, - /// The name of getter function to be implemented on Module struct. - getter: Option, - /// The name of the field to be used in genesis config if any. - config: Option, - /// The build function of the storage if any. - build: Option, - /// Default value of genesis config field and also for storage when no value available. - default_value: Option, - storage_type: StorageLineTypeDef, -} - -pub struct StorageLineDefExt { - #[allow(unused)] - attrs: Vec, - /// Visibility of the storage struct. - visibility: syn::Visibility, - name: syn::Ident, - /// The name of getter function to be implemented on Module struct. - getter: Option, - /// The name of the field to be used in genesis config if any. - config: Option, - /// The build function of the storage if any. - build: Option, - /// Default value of genesis config field and also for storage when no value available. - default_value: Option, - storage_type: StorageLineTypeDef, - doc_attrs: Vec, - /// Either the type stored in storage or wrapped in an Option. - query_type: syn::Type, - /// The type stored in storage. - value_type: syn::Type, - /// Full struct, for example: `StorageName`. - storage_struct: proc_macro2::TokenStream, - /// If storage is generic over runtime then `T`. - optional_storage_runtime_comma: Option, - /// If storage is generic over runtime then `T: Trait`. - optional_storage_runtime_bound_comma: Option, - /// The where clause to use to constrain generics if storage is generic over runtime. - optional_storage_where_clause: Option, - /// Full trait, for example: `storage::StorageMap`. - storage_trait: proc_macro2::TokenStream, - /// Full trait, for example: `storage::generator::StorageMap`. - storage_generator_trait: proc_macro2::TokenStream, - /// Weither the storage is generic. - is_generic: bool, - /// Weither the storage value is an option. - is_option: bool, -} - -impl StorageLineDefExt { - fn from_def(storage_def: StorageLineDef, def: &DeclStorageDef) -> Self { - let is_generic = match &storage_def.storage_type { - StorageLineTypeDef::Simple(value) => { - ext::type_contains_ident(&value, &def.module_runtime_generic) - }, - StorageLineTypeDef::Map(map) => { - ext::type_contains_ident(&map.key, &def.module_runtime_generic) - || ext::type_contains_ident(&map.value, &def.module_runtime_generic) - } - StorageLineTypeDef::LinkedMap(map) => { - ext::type_contains_ident(&map.key, &def.module_runtime_generic) - || ext::type_contains_ident(&map.value, &def.module_runtime_generic) - } - StorageLineTypeDef::DoubleMap(map) => { - ext::type_contains_ident(&map.key1, &def.module_runtime_generic) - || ext::type_contains_ident(&map.key2, &def.module_runtime_generic) - || ext::type_contains_ident(&map.value, &def.module_runtime_generic) - } - }; - - let query_type = match &storage_def.storage_type { - StorageLineTypeDef::Simple(value) => value.clone(), - StorageLineTypeDef::Map(map) => map.value.clone(), - StorageLineTypeDef::LinkedMap(map) => map.value.clone(), - StorageLineTypeDef::DoubleMap(map) => map.value.clone(), - }; - let is_option = ext::extract_type_option(&query_type).is_some(); - let value_type = ext::extract_type_option(&query_type).unwrap_or(query_type.clone()); - - let module_runtime_generic = &def.module_runtime_generic; - let module_runtime_trait = &def.module_runtime_trait; - let optional_storage_runtime_comma = if is_generic { - Some(quote!( #module_runtime_generic, )) - } else { - None - }; - let optional_storage_runtime_bound_comma = if is_generic { - Some(quote!( #module_runtime_generic: #module_runtime_trait, )) - } else { - None - }; - - let storage_name = &storage_def.name; - let optional_instance_generic = def.module_instance.as_ref().map(|i| { - let instance_generic = &i.instance_generic; - quote!( #instance_generic ) - }); - let storage_struct = quote!( - #storage_name<#optional_storage_runtime_comma #optional_instance_generic> - ); - - let optional_storage_where_clause = if is_generic { - def.where_clause.as_ref().map(|w| quote!( #w )) - } else { - None - }; - - let storage_trait_trunkated = match &storage_def.storage_type { - StorageLineTypeDef::Simple(_) => { - quote!( StorageValue<#value_type> ) - }, - StorageLineTypeDef::Map(map) => { - let key = &map.key; - quote!( StorageMap<#key, #value_type> ) - }, - StorageLineTypeDef::LinkedMap(map) => { - let key = &map.key; - quote!( StorageLinkedMap<#key, #value_type> ) - }, - StorageLineTypeDef::DoubleMap(map) => { - let key1 = &map.key1; - let key2 = &map.key2; - quote!( StorageDoubleMap<#key1, #key2, #value_type> ) - }, - }; - - let storage_trait = quote!( storage::#storage_trait_trunkated ); - let storage_generator_trait = quote!( storage::generator::#storage_trait_trunkated ); - - let doc_attrs = storage_def.attrs.iter() - .filter_map(|a| a.parse_meta().ok()) - .filter(|m| m.name() == "doc") - .collect(); - - Self { - attrs: storage_def.attrs, - visibility: storage_def.visibility, - name: storage_def.name, - getter: storage_def.getter, - config: storage_def.config, - build: storage_def.build, - default_value: storage_def.default_value, - storage_type: storage_def.storage_type, - doc_attrs, - query_type, - value_type, - storage_struct, - optional_storage_runtime_comma, - optional_storage_runtime_bound_comma, - optional_storage_where_clause, - storage_trait, - storage_generator_trait, - is_generic, - is_option, - } - } -} - -pub enum StorageLineTypeDef { - Map(MapDef), - LinkedMap(MapDef), - DoubleMap(DoubleMapDef), - Simple(syn::Type), -} - -pub struct MapDef { - pub hasher: HasherKind, - pub key: syn::Type, - /// This is the query value not the inner value used in storage trait implementation. - pub value: syn::Type, -} - -pub struct DoubleMapDef { - pub hasher1: HasherKind, - pub hasher2: HasherKind, - pub key1: syn::Type, - pub key2: syn::Type, - /// This is the query value not the inner value used in storage trait implementation. - pub value: syn::Type, -} - -pub struct ExtraGenesisLineDef { - attrs: Vec, - name: syn::Ident, - typ: syn::Type, - default: Option, -} - -#[derive(Debug, Clone)] -pub enum HasherKind { - Blake2_256, - Blake2_128, - Twox256, - Twox128, - Twox64Concat, -} - -impl HasherKind { - fn to_storage_hasher_struct(&self) -> proc_macro2::TokenStream { - match self { - HasherKind::Blake2_256 => quote!( Blake2_256 ), - HasherKind::Blake2_128 => quote!( Blake2_128 ), - HasherKind::Twox256 => quote!( Twox256 ), - HasherKind::Twox128 => quote!( Twox128 ), - HasherKind::Twox64Concat => quote!( Twox64Concat ), - } - } - - fn into_metadata(&self) -> proc_macro2::TokenStream { - match self { - HasherKind::Blake2_256 => quote!( StorageHasher::Blake2_256 ), - HasherKind::Blake2_128 => quote!( StorageHasher::Blake2_128 ), - HasherKind::Twox256 => quote!( StorageHasher::Twox256 ), - HasherKind::Twox128 => quote!( StorageHasher::Twox128 ), - HasherKind::Twox64Concat => quote!( StorageHasher::Twox64Concat ), - } - } -} - -/// Full implementation of decl_storage. -pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let def = syn::parse_macro_input!(input as DeclStorageDef); - let def_ext = DeclStorageDefExt::from(def); - - let hidden_crate_name = def_ext.hidden_crate.as_ref().map(|i| i.to_string()) - .unwrap_or_else(|| "decl_storage".to_string()); - - let scrate = generate_crate_access(&hidden_crate_name, "srml-support"); - let scrate_decl = generate_hidden_includes(&hidden_crate_name, "srml-support"); - - let store_trait = store_trait::decl_and_impl(&def_ext); - let getters = getters::impl_getters(&scrate, &def_ext); - let metadata = metadata::impl_metadata(&scrate, &def_ext); - let instance_trait = instance_trait::decl_and_impl(&scrate, &def_ext); - let genesis_config = genesis_config::genesis_config_and_build_storage(&scrate, &def_ext); - let storage_struct = storage_struct::decl_and_impl(&scrate, &def_ext); - - quote!( - use #scrate::{ - StorageValue as _, - StorageMap as _, - StorageLinkedMap as _, - StorageDoubleMap as _ - }; - - #scrate_decl - #store_trait - #getters - #metadata - #instance_trait - #genesis_config - #storage_struct - ).into() -} diff --git a/srml/support/procedural/src/storage/parse.rs b/srml/support/procedural/src/storage/parse.rs deleted file mode 100644 index e428fbe24f295..0000000000000 --- a/srml/support/procedural/src/storage/parse.rs +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Parsing of decl_storage input. - -use srml_support_procedural_tools::{ToTokens, Parse, syn_ext as ext}; -use syn::{Ident, Token, spanned::Spanned}; - -mod keyword { - syn::custom_keyword!(hiddencrate); - syn::custom_keyword!(add_extra_genesis); - syn::custom_keyword!(extra_genesis_skip_phantom_data_field); - syn::custom_keyword!(config); - syn::custom_keyword!(build); - syn::custom_keyword!(get); - syn::custom_keyword!(map); - syn::custom_keyword!(linked_map); - syn::custom_keyword!(double_map); - syn::custom_keyword!(blake2_256); - syn::custom_keyword!(blake2_128); - syn::custom_keyword!(twox_256); - syn::custom_keyword!(twox_128); - syn::custom_keyword!(twox_64_concat); - syn::custom_keyword!(hasher); -} - -/// Parsing usage only -#[derive(Parse, ToTokens, Debug)] -struct StorageDefinition { - pub hidden_crate: ext::Opt, - pub visibility: syn::Visibility, - pub trait_token: Token![trait], - pub ident: Ident, - pub for_token: Token![for], - pub module_ident: Ident, - pub mod_lt_token: Token![<], - pub mod_param_generic: syn::Ident, - pub mod_param_bound_token: Option, - pub mod_param_bound: syn::Path, - pub mod_instance_param_token: Option, - pub mod_instance: Option, - pub mod_instantiable_token: Option, - pub mod_instantiable: Option, - pub mod_default_instance_token: Option, - pub mod_default_instance: Option, - pub mod_gt_token: Token![>], - pub as_token: Token![as], - pub crate_ident: Ident, - pub where_clause: Option, - pub content: ext::Braces>, - pub extra_genesis: ext::Opt, -} - -#[derive(Parse, ToTokens, Debug)] -struct SpecificHiddenCrate { - pub keyword: keyword::hiddencrate, - pub ident: ext::Parens, -} - -#[derive(Parse, ToTokens, Debug)] -struct AddExtraGenesis { - pub extragenesis_keyword: keyword::add_extra_genesis, - pub content: ext::Braces, -} - -#[derive(Parse, ToTokens, Debug)] -struct AddExtraGenesisContent { - pub lines: ext::Punctuated, -} - -#[derive(Parse, ToTokens, Debug)] -enum AddExtraGenesisLineEnum { - AddExtraGenesisLine(AddExtraGenesisLine), - AddExtraGenesisBuild(DeclStorageBuild), -} - -#[derive(Parse, ToTokens, Debug)] -struct AddExtraGenesisLine { - pub attrs: ext::OuterAttributes, - pub config_keyword: keyword::config, - pub extra_field: ext::Parens, - pub coldot_token: Token![:], - pub extra_type: syn::Type, - pub default_value: ext::Opt, -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageLine { - // attrs (main use case is doc) - pub attrs: ext::OuterAttributes, - // visibility (no need to make optional - pub visibility: syn::Visibility, - // name - pub name: Ident, - pub getter: ext::Opt, - pub config: ext::Opt, - pub build: ext::Opt, - pub coldot_token: Token![:], - pub storage_type: DeclStorageType, - pub default_value: ext::Opt, -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageGetterBody { - fn_keyword: Option, - ident: Ident, -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageGetter { - pub getter_keyword: keyword::get, - pub getfn: ext::Parens, -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageConfig { - pub config_keyword: keyword::config, - pub expr: ext::Parens>, -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageBuild { - pub build_keyword: keyword::build, - pub expr: ext::Parens, -} - -#[derive(Parse, ToTokens, Debug)] -enum DeclStorageType { - Map(DeclStorageMap), - LinkedMap(DeclStorageLinkedMap), - DoubleMap(DeclStorageDoubleMap), - Simple(syn::Type), -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageMap { - pub map_keyword: keyword::map, - pub hasher: ext::Opt, - pub key: syn::Type, - pub ass_keyword: Token![=>], - pub value: syn::Type, -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageLinkedMap { - pub map_keyword: keyword::linked_map, - pub hasher: ext::Opt, - pub key: syn::Type, - pub ass_keyword: Token![=>], - pub value: syn::Type, -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageDoubleMap { - pub map_keyword: keyword::double_map, - pub hasher: ext::Opt, - pub key1: syn::Type, - pub comma_keyword: Token![,], - pub key2_hasher: Hasher, - pub key2: ext::Parens, - pub ass_keyword: Token![=>], - pub value: syn::Type, -} - -#[derive(Parse, ToTokens, Debug)] -enum Hasher { - Blake2_256(keyword::blake2_256), - Blake2_128(keyword::blake2_128), - Twox256(keyword::twox_256), - Twox128(keyword::twox_128), - Twox64Concat(keyword::twox_64_concat), -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageDefault { - pub equal_token: Token![=], - pub expr: syn::Expr, -} - -#[derive(Parse, ToTokens, Debug)] -struct SetHasher { - pub hasher_keyword: keyword::hasher, - pub inner: ext::Parens, -} - -impl From for super::HasherKind { - fn from(set_hasher: SetHasher) -> Self { - set_hasher.inner.content.into() - } -} - -impl From for super::HasherKind { - fn from(hasher: Hasher) -> Self { - match hasher { - Hasher::Blake2_256(_) => super::HasherKind::Blake2_256, - Hasher::Blake2_128(_) => super::HasherKind::Blake2_128, - Hasher::Twox256(_) => super::HasherKind::Twox256, - Hasher::Twox128(_) => super::HasherKind::Twox128, - Hasher::Twox64Concat(_) => super::HasherKind::Twox64Concat, - } - } -} - -fn get_module_instance( - instance: Option, - instantiable: Option, - default_instance: Option, -) -> syn::Result> { - let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance"; - - match (instance, instantiable, default_instance) { - (Some(instance), Some(instantiable), default_instance) => { - Ok(Some(super::ModuleInstanceDef { - instance_generic: instance, - instance_trait: instantiable, - instance_default: default_instance, - })) - }, - (None, None, None) => Ok(None), - (Some(instance), None, _) => Err( - syn::Error::new( - instance.span(), - format!( - "Expect instantiable trait bound for instance: {}. {}", - instance, - right_syntax, - ) - ) - ), - (None, Some(instantiable), _) => Err( - syn::Error::new( - instantiable.span(), - format!( - "Expect instance generic for bound instantiable: {}. {}", - instantiable, - right_syntax, - ) - ) - ), - (None, _, Some(default_instance)) => Err( - syn::Error::new( - default_instance.span(), - format!( - "Expect instance generic for default instance: {}. {}", - default_instance, - right_syntax, - ) - ) - ), - } -} - -pub fn parse(input: syn::parse::ParseStream) -> syn::Result { - use syn::parse::Parse; - - let def = StorageDefinition::parse(input)?; - - let module_instance = get_module_instance( - def.mod_instance, - def.mod_instantiable, - def.mod_default_instance, - )?; - - let mut extra_genesis_config_lines = vec![]; - let mut extra_genesis_build = None; - - for line in def.extra_genesis.inner.into_iter() - .flat_map(|o| o.content.content.lines.inner.into_iter()) - { - match line { - AddExtraGenesisLineEnum::AddExtraGenesisLine(def) => { - extra_genesis_config_lines.push(super::ExtraGenesisLineDef{ - attrs: def.attrs.inner, - name: def.extra_field.content, - typ: def.extra_type, - default: def.default_value.inner.map(|o| o.expr), - }); - } - AddExtraGenesisLineEnum::AddExtraGenesisBuild(def) => { - if extra_genesis_build.is_some() { - return Err(syn::Error::new( - def.span(), - "Only one build expression allowed for extra genesis" - )) - } - - extra_genesis_build = Some(def.expr.content); - } - } - } - - let storage_lines = parse_storage_line_defs(def.content.content.inner.into_iter())?; - - Ok(super::DeclStorageDef { - hidden_crate: def.hidden_crate.inner.map(|i| i.ident.content), - visibility: def.visibility, - module_name: def.module_ident, - store_trait: def.ident, - module_runtime_generic: def.mod_param_generic, - module_runtime_trait: def.mod_param_bound, - where_clause: def.where_clause, - crate_name: def.crate_ident, - module_instance, - extra_genesis_build, - extra_genesis_config_lines, - storage_lines, - }) -} - -/// Parse the `DeclStorageLine` into `StorageLineDef`. -fn parse_storage_line_defs( - defs: impl Iterator, -) -> syn::Result> { - let mut storage_lines = Vec::::new(); - - for line in defs { - let getter = line.getter.inner.map(|o| o.getfn.content.ident); - let config = if let Some(config) = line.config.inner { - if let Some(ident) = config.expr.content { - Some(ident) - } else if let Some(ref ident) = getter { - Some(ident.clone()) - } else { - return Err(syn::Error::new( - config.span(), - "Invalid storage definition, couldn't find config identifier: storage must \ - either have a get identifier `get(fn ident)` or a defined config identifier \ - `config(ident)`", - )) - } - } else { - None - }; - - if let Some(ref config) = config { - storage_lines.iter().filter_map(|sl| sl.config.as_ref()).try_for_each(|other_config| { - if other_config == config { - Err(syn::Error::new( - config.span(), - "`config()`/`get()` with the same name already defined.", - )) - } else { - Ok(()) - } - })?; - } - - let storage_type = match line.storage_type { - DeclStorageType::Map(map) => super::StorageLineTypeDef::Map( - super::MapDef { - hasher: map.hasher.inner.map(Into::into) - .unwrap_or(super::HasherKind::Blake2_256), - key: map.key, - value: map.value, - } - ), - DeclStorageType::LinkedMap(map) => super::StorageLineTypeDef::LinkedMap( - super::MapDef { - hasher: map.hasher.inner.map(Into::into) - .unwrap_or(super::HasherKind::Blake2_256), - key: map.key, - value: map.value, - } - ), - DeclStorageType::DoubleMap(map) => super::StorageLineTypeDef::DoubleMap( - super::DoubleMapDef { - hasher1: map.hasher.inner.map(Into::into) - .unwrap_or(super::HasherKind::Blake2_256), - hasher2: map.key2_hasher.into(), - key1: map.key1, - key2: map.key2.content, - value: map.value, - } - ), - DeclStorageType::Simple(expr) => super::StorageLineTypeDef::Simple(expr), - }; - - storage_lines.push(super::StorageLineDef { - attrs: line.attrs.inner, - visibility: line.visibility, - name: line.name, - getter, - config, - build: line.build.inner.map(|o| o.expr.content), - default_value: line.default_value.inner.map(|o| o.expr), - storage_type, - }) - } - - Ok(storage_lines) -} diff --git a/srml/support/procedural/src/storage/storage_struct.rs b/srml/support/procedural/src/storage/storage_struct.rs deleted file mode 100644 index e195fb53e8a2c..0000000000000 --- a/srml/support/procedural/src/storage/storage_struct.rs +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Implementation of storage structures and implementation of storage traits on them. - -use proc_macro2::TokenStream; -use quote::quote; -use super::{ - DeclStorageDefExt, StorageLineTypeDef, - instance_trait::{PREFIX_FOR, HEAD_KEY_FOR}, -}; - -fn from_optional_value_to_query(is_option: bool, default: &Option) -> TokenStream { - let default = default.as_ref().map(|d| quote!( #d )) - .unwrap_or_else(|| quote!( Default::default() )); - - if !is_option { - // raw type case - quote!( v.unwrap_or_else(|| #default ) ) - } else { - // Option<> type case - quote!( v.or_else(|| #default ) ) - } -} - -fn from_query_to_optional_value(is_option: bool) -> TokenStream { - if !is_option { - // raw type case - quote!( Some(v) ) - } else { - // Option<> type case - quote!( v ) - } -} - -pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { - let mut impls = TokenStream::new(); - - for line in &def.storage_lines { - - // Propagate doc attributes. - let attrs = &line.doc_attrs; - - let visibility = &line.visibility; - let optional_storage_runtime_comma = &line.optional_storage_runtime_comma; - let optional_storage_runtime_bound_comma = &line.optional_storage_runtime_bound_comma; - let optional_storage_where_clause = &line.optional_storage_where_clause; - let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default; - let optional_instance_bound = &def.optional_instance_bound; - let optional_instance = &def.optional_instance; - let name = &line.name; - - let struct_decl = quote!( - #( #[ #attrs ] )* - #visibility struct #name< - #optional_storage_runtime_bound_comma #optional_instance_bound_optional_default - >( - #scrate::rstd::marker::PhantomData< - (#optional_storage_runtime_comma #optional_instance) - > - ) #optional_storage_where_clause; - ); - - let from_query_to_optional_value = from_query_to_optional_value(line.is_option); - let from_optional_value_to_query = - from_optional_value_to_query(line.is_option, &line.default_value); - - let final_prefix = if let Some(instance) = def.module_instance.as_ref() { - let instance = &instance.instance_generic; - let const_name = syn::Ident::new( - &format!("{}{}", PREFIX_FOR, line.name.to_string()), proc_macro2::Span::call_site() - ); - quote!( #instance::#const_name.as_bytes() ) - } else { - let prefix = format!("{} {}", def.crate_name, line.name); - quote!( #prefix.as_bytes() ) - }; - - - let storage_generator_trait = &line.storage_generator_trait; - let storage_struct = &line.storage_struct; - let impl_trait = quote!( #optional_storage_runtime_bound_comma #optional_instance_bound ); - let value_type = &line.value_type; - let query_type = &line.query_type; - - let struct_impl = match &line.storage_type { - StorageLineTypeDef::Simple(_) => { - quote!( - impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct - #optional_storage_where_clause - { - type Query = #query_type; - - fn unhashed_key() -> &'static [u8] { - #final_prefix - } - - fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { - #from_optional_value_to_query - } - - fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { - #from_query_to_optional_value - } - } - ) - }, - StorageLineTypeDef::Map(map) => { - let hasher = map.hasher.to_storage_hasher_struct(); - quote!( - impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct - #optional_storage_where_clause - { - type Query = #query_type; - type Hasher = #scrate::#hasher; - - fn prefix() -> &'static [u8] { - #final_prefix - } - - fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { - #from_optional_value_to_query - } - - fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { - #from_query_to_optional_value - } - } - ) - }, - StorageLineTypeDef::LinkedMap(map) => { - let hasher = map.hasher.to_storage_hasher_struct(); - - // make sure to use different prefix for head and elements. - let head_key = if let Some(instance) = def.module_instance.as_ref() { - let instance = &instance.instance_generic; - let const_name = syn::Ident::new( - &format!("{}{}", HEAD_KEY_FOR, line.name.to_string()), proc_macro2::Span::call_site() - ); - quote!( #instance::#const_name.as_bytes() ) - } else { - let prefix = format!("head of {} {}", def.crate_name, line.name); - quote!( #prefix.as_bytes() ) - }; - - quote!( - impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct - #optional_storage_where_clause - { - type Query = #query_type; - type Hasher = #scrate::#hasher; - - fn prefix() -> &'static [u8] { - #final_prefix - } - - fn head_key() -> &'static [u8] { - #head_key - } - - fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { - #from_optional_value_to_query - } - - fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { - #from_query_to_optional_value - } - } - ) - }, - StorageLineTypeDef::DoubleMap(map) => { - let hasher1 = map.hasher1.to_storage_hasher_struct(); - let hasher2 = map.hasher2.to_storage_hasher_struct(); - quote!( - impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct - #optional_storage_where_clause - { - type Query = #query_type; - - type Hasher1 = #scrate::#hasher1; - - type Hasher2 = #scrate::#hasher2; - - fn key1_prefix() -> &'static [u8] { - #final_prefix - } - - fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { - #from_optional_value_to_query - } - - fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { - #from_query_to_optional_value - } - } - ) - } - }; - - impls.extend(quote!( - #struct_decl - #struct_impl - )) - } - - impls -} diff --git a/srml/support/procedural/tools/Cargo.toml b/srml/support/procedural/tools/Cargo.toml deleted file mode 100644 index 62c55a703f4ed..0000000000000 --- a/srml/support/procedural/tools/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "srml-support-procedural-tools" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -srml-support-procedural-tools-derive = { package = "srml-support-procedural-tools-derive", path = "./derive" } -proc-macro2 = "0.4.27" -quote = "0.6.12" -syn = { version = "0.15.44", features = ["full"] } -proc-macro-crate = "0.1.4" diff --git a/srml/support/procedural/tools/derive/Cargo.toml b/srml/support/procedural/tools/derive/Cargo.toml deleted file mode 100644 index 54bfaba838434..0000000000000 --- a/srml/support/procedural/tools/derive/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "srml-support-procedural-tools-derive" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "0.4.27" -quote = { version = "0.6.12", features = ["proc-macro"] } -syn = { version = "0.15.44", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/srml/support/procedural/tools/derive/src/lib.rs b/srml/support/procedural/tools/derive/src/lib.rs deleted file mode 100644 index 4bf1a5f44c252..0000000000000 --- a/srml/support/procedural/tools/derive/src/lib.rs +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -// tag::description[] -//! Use to derive parsing for parsing struct. -// end::description[] - -#![recursion_limit = "128"] - -extern crate proc_macro; - -use proc_macro::TokenStream; -use proc_macro2::Span; -use syn::parse_macro_input; -use quote::quote; - -pub(crate) fn fields_idents( - fields: impl Iterator, -) -> impl Iterator { - fields.enumerate().map(|(ix, field)| { - field.ident.clone().map(|i| quote!{#i}).unwrap_or_else(|| { - let f_ix: syn::Ident = syn::Ident::new(&format!("f_{}", ix), Span::call_site()); - quote!( #f_ix ) - }) - }) -} - -pub(crate) fn fields_access( - fields: impl Iterator, -) -> impl Iterator { - fields.enumerate().map(|(ix, field)| { - field.ident.clone().map(|i| quote!( #i )).unwrap_or_else(|| { - let f_ix: syn::Index = syn::Index { - index: ix as u32, - span: Span::call_site(), - }; - quote!( #f_ix ) - }) - }) -} - -/// 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 successful 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, - .. - } = input; - let field_names = { - let name = fields_idents(fields.iter().map(Clone::clone)); - quote!{ - #( - #name, - )* - } - }; - let field = fields_idents(fields.iter().map(Clone::clone)); - let tokens = quote! { - impl #generics syn::parse::Parse for #ident #generics { - fn parse(input: syn::parse::ParseStream) -> syn::parse::Result { - #( - let #field = input.parse()?; - )* - Ok(Self { - #field_names - }) - } - } - }; - tokens.into() -} - -fn derive_parse_enum(input: syn::ItemEnum) -> TokenStream { - let syn::ItemEnum { - ident, - generics, - variants, - .. - } = input; - let variants = variants.iter().map(|v| { - let variant_ident = v.ident.clone(); - let fields_build = if v.fields.iter().count() > 0 { - let fields_id = fields_idents(v.fields.iter().map(Clone::clone)); - quote!( (#(#fields_id), *) ) - } else { - quote!() - }; - - let fields_procs = fields_idents(v.fields.iter().map(Clone::clone)) - .map(|fident| { - quote!{ - let mut #fident = match fork.parse() { - Ok(r) => r, - Err(_e) => break, - }; - } - }); - let fields_procs_again = fields_idents(v.fields.iter().map(Clone::clone)) - .map(|fident| { - quote!{ - #fident = input.parse().expect("was parsed just before"); - } - }); - - // double parse to update input cursor position - // next syn crate version should be checked for a way - // to copy position/state from a fork - quote!{ - let mut fork = input.fork(); - loop { - #(#fields_procs)* - #(#fields_procs_again)* - return Ok(#ident::#variant_ident#fields_build); - } - } - }); - - let tokens = quote! { - impl #generics syn::parse::Parse for #ident #generics { - fn parse(input: syn::parse::ParseStream) -> syn::parse::Result { - #( - #variants - )* - // no early return from any variants - Err( - syn::parse::Error::new( - proc_macro2::Span::call_site(), - "derived enum no matching variants" - ) - ) - } - } - - }; - tokens.into() -} - -/// 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, - .. - } = input; - let variants = variants.iter().map(|v| { - let v_ident = v.ident.clone(); - let fields_build = if v.fields.iter().count() > 0 { - let fields_id = fields_idents(v.fields.iter().map(Clone::clone)); - quote!( (#(#fields_id), *) ) - } else { - quote!() - }; - let field = fields_idents(v.fields.iter().map(Clone::clone)); - quote! { - #ident::#v_ident#fields_build => { - #( - #field.to_tokens(tokens); - )* - }, - } - }); - let tokens = quote! { - impl #generics quote::ToTokens for #ident #generics { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - match self { - #( - #variants - )* - } - } - } - }; - - tokens.into() -} diff --git a/srml/support/procedural/tools/src/lib.rs b/srml/support/procedural/tools/src/lib.rs deleted file mode 100644 index 2b08104ca71ba..0000000000000 --- a/srml/support/procedural/tools/src/lib.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -// tag::description[] -//! Proc macro helpers for procedural macros -// end::description[] - -// 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; - -// FIXME #1569, remove the following functions, which are copied from sr-api-macros -use proc_macro2::{TokenStream, Span}; -use syn::Ident; - -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 `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::quote!( srml_support ) - } else { - let mod_name = generate_hidden_includes_mod_name(unique_id); - 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) -> TokenStream { - if ::std::env::var("CARGO_PKG_NAME").unwrap() == def_crate { - TokenStream::new() - } else { - let mod_name = generate_hidden_includes_mod_name(unique_id); - - 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 ) - } - } - - } -} - -// fn to remove white spaces around string types -// (basically whitespaces around 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/src/error.rs b/srml/support/src/error.rs deleted file mode 100644 index 9aa13713daafb..0000000000000 --- a/srml/support/src/error.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Macro for declaring a module error. - -#[doc(hidden)] -pub use sr_primitives::traits::LookupError; -pub use srml_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent}; - -/// Declare an error type for a runtime module. -/// -/// The generated error type inherently has the variants `Other` and `CannotLookup`. `Other` can -/// hold any `&'static str` error message and is present for convenience/backward compatibility. -/// The `CannotLookup` variant indicates that some lookup could not be done. For both variants the -/// error type implements `From<&'static str>` and `From` to make them usable with the -/// try operator. -/// -/// # Usage -/// -/// ``` -/// # use srml_support::decl_error; -/// decl_error! { -/// /// Errors that can occur in my module. -/// pub enum MyError { -/// /// Hey this is an error message that indicates bla. -/// MyCoolErrorMessage, -/// /// You are just not cool enough for my module! -/// YouAreNotCoolEnough, -/// } -/// } -/// ``` -/// -/// `decl_error!` supports only variants that do not hold any data. -#[macro_export] -macro_rules! decl_error { - ( - $(#[$attr:meta])* - pub enum $error:ident { - $( - $( #[doc = $doc_attr:tt] )* - $name:ident - ),* - $(,)? - } - ) => { - #[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)] - $(#[$attr])* - pub enum $error { - Other(&'static str), - CannotLookup, - $( - $( #[doc = $doc_attr] )* - $name - ),* - } - - impl $crate::dispatch::ModuleDispatchError for $error { - fn as_u8(&self) -> u8 { - $crate::decl_error! { - @GENERATE_AS_U8 - self - $error - {} - 2, - $( $name ),* - } - } - - fn as_str(&self) -> &'static str { - match self { - $error::Other(err) => err, - $error::CannotLookup => "Can not lookup", - $( - $error::$name => stringify!($name), - )* - } - } - } - - impl From<&'static str> for $error { - fn from(val: &'static str) -> $error { - $error::Other(val) - } - } - - impl From<$crate::error::LookupError> for $error { - fn from(_: $crate::error::LookupError) -> $error { - $error::CannotLookup - } - } - - impl From<$error> for &'static str { - fn from(err: $error) -> &'static str { - use $crate::dispatch::ModuleDispatchError; - err.as_str() - } - } - - impl Into<$crate::dispatch::DispatchError> for $error { - fn into(self) -> $crate::dispatch::DispatchError { - use $crate::dispatch::ModuleDispatchError; - $crate::dispatch::DispatchError::new(None, self.as_u8(), Some(self.as_str())) - } - } - - impl $crate::error::ModuleErrorMetadata for $error { - fn metadata() -> &'static [$crate::error::ErrorMetadata] { - &[ - $( - $crate::error::ErrorMetadata { - name: $crate::error::DecodeDifferent::Encode(stringify!($name)), - documentation: $crate::error::DecodeDifferent::Encode(&[ - $( $doc_attr ),* - ]), - } - ),* - ] - } - } - }; - (@GENERATE_AS_U8 - $self:ident - $error:ident - { $( $generated:tt )* } - $index:expr, - $name:ident - $( , $rest:ident )* - ) => { - $crate::decl_error! { - @GENERATE_AS_U8 - $self - $error - { - $( $generated )* - $error::$name => $index, - } - $index + 1, - $( $rest ),* - } - }; - (@GENERATE_AS_U8 - $self:ident - $error:ident - { $( $generated:tt )* } - $index:expr, - ) => { - match $self { - $error::Other(_) => 0, - $error::CannotLookup => 1, - $( $generated )* - } - } -} diff --git a/srml/support/src/event.rs b/srml/support/src/event.rs deleted file mode 100644 index 3411c93922e2b..0000000000000 --- a/srml/support/src/event.rs +++ /dev/null @@ -1,819 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -//! 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 . - -pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEncode}; - -/// Implement the `Event` for a module. -/// -/// # Simple Event Example: -/// -/// ```rust -/// srml_support::decl_event!( -/// pub enum Event { -/// Success, -/// Failure(String), -/// } -/// ); -/// -///# fn main() {} -/// ``` -/// -/// # Generic Event Example: -/// -/// ```rust -/// trait Trait { -/// type Balance; -/// type Token; -/// } -/// -/// mod event1 { -/// // Event that specifies the generic parameter explicitly (`Balance`). -/// srml_support::decl_event!( -/// pub enum Event where Balance = ::Balance { -/// Message(Balance), -/// } -/// ); -/// } -/// -/// mod event2 { -/// // Event that uses the generic parameter `Balance`. -/// // If no name for the generic parameter is specified explicitly, -/// // the name will be taken from the type name of the trait. -/// srml_support::decl_event!( -/// pub enum Event where ::Balance { -/// Message(Balance), -/// } -/// ); -/// } -/// -/// mod event3 { -/// // And we even support declaring multiple generic parameters! -/// srml_support::decl_event!( -/// pub enum Event where ::Balance, ::Token { -/// Message(Balance, Token), -/// } -/// ); -/// } -/// -///# fn main() {} -/// ``` -/// -/// The syntax for generic events requires the `where`. -/// -/// # Generic Event with Instance Example: -/// -/// ```rust -///# struct DefaultInstance; -///# trait Instance {} -///# impl Instance for DefaultInstance {} -/// trait Trait { -/// type Balance; -/// type Token; -/// } -/// -/// // For module with instances, DefaultInstance is optional -/// srml_support::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 $(, $instance:ident $(: $instantiable:ident)? $( = $event_default_instance:path)? )?> where - $( $tt:tt )* - ) => { - $crate::__decl_generic_event!( - $( #[ $attr ] )*; - $evt_generic_param; - $($instance $( = $event_default_instance)? )?; - { $( $tt )* }; - ); - }; - ( - $(#[$attr:meta])* - pub enum Event { - $( - $events:tt - )* - } - ) => { - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive( - Clone, PartialEq, Eq, - $crate::codec::Encode, - $crate::codec::Decode, - $crate::RuntimeDebug, - )] - /// Events for this module. - /// - $(#[$attr])* - pub enum Event { - $( - $events - )* - } - impl From for () { - fn from(_: Event) -> () { () } - } - impl Event { - #[allow(dead_code)] - #[doc(hidden)] - pub fn metadata() -> &'static [ $crate::event::EventMetadata ] { - $crate::__events_to_metadata!(; $( $events )* ) - } - } - } -} - -#[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; - $($instance:ident $( = $event_default_instance:path)? )?; - { $( $tt:tt )* }; - ) => { - $crate::__decl_generic_event!(@format_generic - $( #[ $attr ] )*; - $event_generic_param; - $($instance $( = $event_default_instance)? )?; - { $( $tt )* }; - {}; - ); - }; - // Finish formatting on an unnamed one - (@format_generic - $(#[$attr:meta])*; - $event_generic_param:ident; - $($instance:ident $( = $event_default_instance:path)? )?; - { <$generic:ident as $trait:path>::$trait_type:ident $(,)? { $( $events:tt )* } }; - {$( $parsed:tt)*}; - ) => { - $crate::__decl_generic_event!(@generate - $( #[ $attr ] )*; - $event_generic_param; - $($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; - $($instance:ident $( = $event_default_instance:path)? )?; - { $generic_rename:ident = $generic_type:ty $(,)? { $( $events:tt )* } }; - { $($parsed:tt)* }; - ) => { - $crate::__decl_generic_event!(@generate - $(#[$attr])*; - $event_generic_param; - $($instance $( = $event_default_instance)? )?; - { $($events)* }; - { $($parsed)*, $generic_rename = $generic_type }; - ); - }; - // Parse named - (@format_generic - $(#[$attr:meta])*; - $event_generic_param:ident; - $($instance:ident $( = $event_default_instance:path)? )?; - { $generic_rename:ident = $generic_type:ty, $($rest:tt)* }; - {$( $parsed:tt)*}; - ) => { - $crate::__decl_generic_event!(@format_generic - $( #[ $attr ] )*; - $event_generic_param; - $( $instance $( = $event_default_instance)? )?; - { $($rest)* }; - { $($parsed)*, $generic_rename = $generic_type }; - ); - }; - // Parse unnamed - (@format_generic - $(#[$attr:meta])*; - $event_generic_param:ident; - $($instance:ident $( = $event_default_instance:path)? )?; - { <$generic:ident as $trait:path>::$trait_type:ident, $($rest:tt)* }; - {$($parsed:tt)*}; - ) => { - $crate::__decl_generic_event!(@format_generic - $( #[ $attr ] )*; - $event_generic_param; - $($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); - }; - // 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)? >; - - #[derive( - Clone, PartialEq, Eq, - $crate::codec::Encode, - $crate::codec::Decode, - $crate::RuntimeDebug, - )] - /// Events for this module. - /// - $(#[$attr])* - pub enum RawEvent<$( $generic_param ),* $(, $instance)? > { - $( - $events - )* - $( - #[doc(hidden)] - #[codec(skip)] - PhantomData($crate::rstd::marker::PhantomData<$instance>), - )? - } - impl<$( $generic_param ),* $(, $instance)? > From> for () { - fn from(_: RawEvent<$( $generic_param ),* $(, $instance)?>) -> () { () } - } - impl<$( $generic_param ),* $(, $instance)?> RawEvent<$( $generic_param ),* $(, $instance)?> { - #[allow(dead_code)] - pub fn metadata() -> &'static [$crate::event::EventMetadata] { - $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), "`")); - } -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __events_to_metadata { - ( - $( $metadata:expr ),*; - $( #[doc = $doc_attr:tt] )* - $event:ident $( ( $( $param:path ),* ) )*, - $( $rest:tt )* - ) => { - $crate::__events_to_metadata!( - $( $metadata, )* - $crate::event::EventMetadata { - name: $crate::event::DecodeDifferent::Encode(stringify!($event)), - arguments: $crate::event::DecodeDifferent::Encode(&[ - $( $( stringify!($param) ),* )* - ]), - documentation: $crate::event::DecodeDifferent::Encode(&[ - $( $doc_attr ),* - ]), - }; - $( $rest )* - ) - }; - ( - $( $metadata:expr ),*; - ) => { - &[ $( $metadata ),* ] - } -} - -/// Constructs an Event type for a runtime. This is usually called automatically by the -/// construct_runtime 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_event_without_system:tt )* - } - ) => { - $crate::impl_outer_event!( - $( #[$attr] )*; - $name; - $runtime; - system; - Modules { $( $rest_event_without_system )* }; - ; - ); - }; - ( - $(#[$attr:meta])* - pub enum $name:ident for $runtime:ident where system = $system:ident { - $( $rest_event_with_system:tt )* - } - ) => { - $crate::impl_outer_event!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_event_with_system )* }; - ; - ); - }; - // Generic + Instance - ( - $(#[$attr:meta])*; - $name:ident; - $runtime:ident; - $system:ident; - Modules { - $module:ident $instance:ident, - $( $rest_event_generic_instance:tt )* - }; - $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; - ) => { - $crate::impl_outer_event!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_event_generic_instance )* }; - $( $module_name::Event $( <$generic_param> )? $( { $generic_instance } )?, )* $module::Event<$runtime>{ $instance },; - ); - }; - // Instance - ( - $(#[$attr:meta])*; - $name:ident; - $runtime:ident; - $system:ident; - Modules { - $module:ident $instance:ident, - $( $rest_event_instance:tt )* - }; - $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; - ) => { - $crate::impl_outer_event!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_event_instance )* }; - $( $module_name::Event $( <$generic_param> )* $( { $generic_instance } )?, )* $module::Event { $instance },; - ); - }; - // Generic - ( - $(#[$attr:meta])*; - $name:ident; - $runtime:ident; - $system:ident; - Modules { - $module:ident, - $( $rest_event_generic:tt )* - }; - $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; - ) => { - $crate::impl_outer_event!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_event_generic )* }; - $( $module_name::Event $( <$generic_param> )? $( { $generic_instance } )?, )* $module::Event<$runtime>,; - ); - }; - // No Generic and no Instance - ( - $(#[$attr:meta])*; - $name:ident; - $runtime:ident; - $system:ident; - Modules { - $module:ident, - $( $rest_event_no_generic_no_instance:tt )* - }; - $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; - ) => { - $crate::impl_outer_event!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_event_no_generic_no_instance )* }; - $( $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> )? $( { $generic_instance:ident } )?, )*; - ) => { - $crate::paste::item! { - #[derive( - Clone, PartialEq, Eq, - $crate::codec::Encode, - $crate::codec::Decode, - $crate::RuntimeDebug, - )] - $(#[$attr])* - #[allow(non_camel_case_types)] - pub enum $name { - system($system::Event), - $( - [< $module_name $(_ $generic_instance )? >]( - $module_name::Event < $( $generic_param )? $(, $module_name::$generic_instance )? > - ), - )* - } - impl From<$system::Event> for $name { - fn from(x: $system::Event) -> Self { - $name::system(x) - } - } - $( - impl From<$module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >> for $name { - fn from(x: $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >) -> Self { - $name::[< $module_name $(_ $generic_instance )? >](x) - } - } - impl $crate::rstd::convert::TryInto< - $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? > - > for $name { - type Error = (); - - fn try_into(self) -> $crate::rstd::result::Result< - $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >, Self::Error - > { - match self { - Self::[< $module_name $(_ $generic_instance )? >](evt) => Ok(evt), - _ => Err(()), - } - } - } - )* - } - $crate::__impl_outer_event_json_metadata!( - $runtime; - $name; - $system; - $( - $module_name::Event - < $( $generic_param )? $(, $module_name::$generic_instance )? > - $( $generic_instance )?, - )*; - ); - } -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __impl_outer_event_json_metadata { - ( - $runtime:ident; - $event_name:ident; - $system:ident; - $( $module_name:ident::Event < $( $generic_params:path ),* > $( $instance:ident )?, )*; - ) => { - impl $runtime { - #[allow(dead_code)] - pub fn outer_event_metadata() -> $crate::event::OuterEventMetadata { - $crate::event::OuterEventMetadata { - name: $crate::event::DecodeDifferent::Encode(stringify!($event_name)), - events: $crate::event::DecodeDifferent::Encode(&[ - ("system", $crate::event::FnEncode(system::Event::metadata)) - $( - , ( - stringify!($module_name), - $crate::event::FnEncode( - $module_name::Event ::< $( $generic_params ),* > ::metadata - ) - ) - )* - ]) - } - } - #[allow(dead_code)] - pub fn __module_events_system() -> &'static [$crate::event::EventMetadata] { - system::Event::metadata() - } - - $crate::paste::item! { - $( - #[allow(dead_code)] - pub fn [< __module_events_ $module_name $( _ $instance )? >] () -> - &'static [$crate::event::EventMetadata] - { - $module_name::Event ::< $( $generic_params ),* > ::metadata() - } - )* - } - } - } -} - -#[cfg(test)] -#[allow(dead_code)] -mod tests { - use super::*; - use serde::Serialize; - use codec::{Encode, Decode}; - - mod system { - pub trait Trait { - type Origin; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - decl_event!( - pub enum Event { - SystemEvent, - } - ); - } - - mod system_renamed { - pub trait Trait { - type Origin; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - decl_event!( - pub enum Event { - SystemEvent, - } - ); - } - - mod event_module { - pub trait Trait { - type Origin; - type Balance; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - decl_event!( - /// Event without renaming the generic parameter `Balance` and `Origin`. - pub enum Event where ::Balance, ::Origin - { - /// Hi, I am a comment. - TestEvent(Balance, Origin), - /// Dog - EventWithoutParams, - } - ); - } - - mod event_module2 { - pub trait Trait { - type Origin; - type Balance; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - decl_event!( - /// Event with renamed generic parameter - pub enum Event where - BalanceRenamed = ::Balance, - OriginRenamed = ::Origin - { - TestEvent(BalanceRenamed), - TestOrigin(OriginRenamed), - } - ); - } - - mod event_module3 { - decl_event!( - pub enum Event { - HiEvent, - } - ); - } - - mod event_module4 { - pub trait Trait { - type Origin; - type Balance; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - decl_event!( - /// Event finish formatting on an unnamed one with trailling comma - pub enum Event where - ::Balance, - ::Origin, - { - TestEvent(Balance, Origin), - } - ); - } - - mod event_module5 { - pub trait Trait { - type Origin; - type Balance; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - decl_event!( - /// Event finish formatting on an named one with trailing comma - pub enum Event where - BalanceRenamed = ::Balance, - OriginRenamed = ::Origin, - { - TestEvent(BalanceRenamed, OriginRenamed), - } - ); - } - - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)] - pub struct TestRuntime; - - impl_outer_event! { - pub enum TestEvent for TestRuntime { - event_module, - event_module2, - event_module3, - } - } - - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)] - pub struct TestRuntime2; - - impl_outer_event! { - pub enum TestEventSystemRenamed for TestRuntime2 where system = system_renamed { - event_module, - event_module2, - event_module3, - } - } - - impl event_module::Trait for TestRuntime { - type Origin = u32; - type Balance = u32; - type BlockNumber = u32; - } - - impl event_module2::Trait for TestRuntime { - type Origin = u32; - type Balance = u32; - type BlockNumber = u32; - } - - impl system::Trait for TestRuntime { - type Origin = u32; - type BlockNumber = u32; - } - - impl event_module::Trait for TestRuntime2 { - type Origin = u32; - type Balance = u32; - type BlockNumber = u32; - } - - impl event_module2::Trait for TestRuntime2 { - type Origin = u32; - type Balance = u32; - type BlockNumber = u32; - } - - impl system_renamed::Trait for TestRuntime2 { - type Origin = u32; - type BlockNumber = u32; - } - - const EXPECTED_METADATA: OuterEventMetadata = OuterEventMetadata { - name: DecodeDifferent::Encode("TestEvent"), - events: DecodeDifferent::Encode(&[ - ( - "system", - FnEncode(|| &[ - EventMetadata { - name: DecodeDifferent::Encode("SystemEvent"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[]), - } - ]) - ), - ( - "event_module", - FnEncode(|| &[ - EventMetadata { - name: DecodeDifferent::Encode("TestEvent"), - arguments: DecodeDifferent::Encode(&[ "Balance", "Origin" ]), - documentation: DecodeDifferent::Encode(&[ " Hi, I am a comment." ]) - }, - EventMetadata { - name: DecodeDifferent::Encode("EventWithoutParams"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[ " Dog" ]), - }, - ]) - ), - ( - "event_module2", - FnEncode(|| &[ - EventMetadata { - name: DecodeDifferent::Encode("TestEvent"), - arguments: DecodeDifferent::Encode(&[ "BalanceRenamed" ]), - documentation: DecodeDifferent::Encode(&[]) - }, - EventMetadata { - name: DecodeDifferent::Encode("TestOrigin"), - arguments: DecodeDifferent::Encode(&[ "OriginRenamed" ]), - documentation: DecodeDifferent::Encode(&[]), - }, - ]) - ), - ( - "event_module3", - FnEncode(|| &[ - EventMetadata { - name: DecodeDifferent::Encode("HiEvent"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[]) - } - ]) - ) - ]) - }; - - #[test] - fn outer_event_metadata() { - assert_eq!(EXPECTED_METADATA, TestRuntime::outer_event_metadata()); - } -} diff --git a/srml/support/src/hash.rs b/srml/support/src/hash.rs deleted file mode 100644 index cbd78f603241e..0000000000000 --- a/srml/support/src/hash.rs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Hash utilities. - -use codec::Codec; -use rstd::prelude::Vec; -use runtime_io::{blake2_128, blake2_256, twox_64, twox_128, twox_256}; - -// This trait must be kept coherent with srml-support-procedural HasherKind usage -pub trait Hashable: Sized { - fn blake2_128(&self) -> [u8; 16]; - fn blake2_256(&self) -> [u8; 32]; - fn twox_128(&self) -> [u8; 16]; - fn twox_256(&self) -> [u8; 32]; - fn twox_64_concat(&self) -> Vec; -} - -impl Hashable for T { - fn blake2_128(&self) -> [u8; 16] { - self.using_encoded(blake2_128) - } - fn blake2_256(&self) -> [u8; 32] { - self.using_encoded(blake2_256) - } - fn twox_128(&self) -> [u8; 16] { - self.using_encoded(twox_128) - } - fn twox_256(&self) -> [u8; 32] { - self.using_encoded(twox_256) - } - fn twox_64_concat(&self) -> Vec { - self.using_encoded(Twox64Concat::hash) - } -} - -/// Hasher to use to hash keys to insert to storage. -pub trait StorageHasher: 'static { - type Output: AsRef<[u8]>; - fn hash(x: &[u8]) -> Self::Output; -} - -/// Hash storage keys with `concat(twox64(key), key)` -pub struct Twox64Concat; -impl StorageHasher for Twox64Concat { - type Output = Vec; - fn hash(x: &[u8]) -> Vec { - twox_64(x) - .iter() - .chain(x.into_iter()) - .cloned() - .collect::>() - } -} - -/// Hash storage keys with blake2 128 -pub struct Blake2_128; -impl StorageHasher for Blake2_128 { - type Output = [u8; 16]; - fn hash(x: &[u8]) -> [u8; 16] { - blake2_128(x) - } -} - -/// Hash storage keys with blake2 256 -pub struct Blake2_256; -impl StorageHasher for Blake2_256 { - type Output = [u8; 32]; - fn hash(x: &[u8]) -> [u8; 32] { - blake2_256(x) - } -} - -/// Hash storage keys with twox 128 -pub struct Twox128; -impl StorageHasher for Twox128 { - type Output = [u8; 16]; - fn hash(x: &[u8]) -> [u8; 16] { - twox_128(x) - } -} - -/// Hash storage keys with twox 256 -pub struct Twox256; -impl StorageHasher for Twox256 { - type Output = [u8; 32]; - fn hash(x: &[u8]) -> [u8; 32] { - twox_256(x) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_twox_64_concat() { - let r = Twox64Concat::hash(b"foo"); - assert_eq!(r.split_at(8), (&twox_128(b"foo")[..8], &b"foo"[..])) - } -} diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs deleted file mode 100644 index 2a9f66bd526e2..0000000000000 --- a/srml/support/src/lib.rs +++ /dev/null @@ -1,601 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Support code for the runtime. - -#![cfg_attr(not(feature = "std"), no_std)] - -/// Export ourself as `srml_support` to make tests happy. -extern crate self as srml_support; - -#[macro_use] -extern crate bitmask; - -#[cfg(feature = "std")] -pub use serde; -#[doc(hidden)] -pub use rstd; -#[doc(hidden)] -pub use codec; -#[cfg(feature = "std")] -#[doc(hidden)] -pub use once_cell; -#[doc(hidden)] -pub use paste; -#[cfg(feature = "std")] -#[doc(hidden)] -pub use runtime_io::with_storage; -#[doc(hidden)] -pub use runtime_io::storage_root; -#[doc(hidden)] -pub use sr_primitives::RuntimeDebug; - -#[macro_use] -pub mod debug; -#[macro_use] -pub mod dispatch; -#[macro_use] -pub mod storage; -mod hash; -#[macro_use] -pub mod event; -#[macro_use] -mod origin; -#[macro_use] -pub mod metadata; -#[macro_use] -mod runtime; -#[macro_use] -pub mod inherent; -#[macro_use] -pub mod unsigned; -#[macro_use] -pub mod error; -pub mod traits; - -pub use self::hash::{Twox256, Twox128, Blake2_256, Blake2_128, Twox64Concat, Hashable}; -pub use self::storage::{StorageValue, StorageMap, StorageLinkedMap, StorageDoubleMap}; -pub use self::dispatch::{Parameter, Callable, IsSubType}; -pub use sr_primitives::{self, ConsensusEngineId, print, traits::Printable}; - -/// Macro for easily creating a new implementation of the `Get` trait. Use similarly to -/// how you would declare a `const`: -/// -/// ```no_compile -/// parameter_types! { -/// pub const Argument: u64 = 42; -/// } -/// trait Config { -/// type Parameter: Get; -/// } -/// struct Runtime; -/// impl Config for Runtime { -/// type Parameter = Argument; -/// } -/// ``` -#[macro_export] -macro_rules! parameter_types { - ( - $( #[ $attr:meta ] )* - $vis:vis const $name:ident: $type:ty = $value:expr; - $( $rest:tt )* - ) => ( - $( #[ $attr ] )* - $vis struct $name; - $crate::parameter_types!{IMPL $name , $type , $value} - $crate::parameter_types!{ $( $rest )* } - ); - () => (); - (IMPL $name:ident , $type:ty , $value:expr) => { - impl $name { - pub fn get() -> $type { - $value - } - } - impl> $crate::traits::Get for $name { - fn get() -> I { - I::from($value) - } - } - } -} - -#[doc(inline)] -pub use srml_support_procedural::decl_storage; - -/// Return Err of the expression: `return Err($expression);`. -/// -/// Used as `fail!(expression)`. -#[macro_export] -macro_rules! fail { - ( $y:expr ) => {{ - return Err($y); - }} -} - -/// Evaluate `$x:expr` and if not true return `Err($y:expr)`. -/// -/// Used as `ensure!(expression_to_ensure, expression_to_return_on_false)`. -#[macro_export] -macro_rules! ensure { - ( $x:expr, $y:expr $(,)? ) => {{ - if !$x { - $crate::fail!($y); - } - }} -} - -/// Evaluate an expression, assert it returns an expected `Err` value and that -/// runtime storage has not been mutated (i.e. expression is a no-operation). -/// -/// Used as `assert_noop(expression_to_assert, expected_error_expression)`. -#[macro_export] -#[cfg(feature = "std")] -macro_rules! assert_noop { - ( - $x:expr, - $y:expr $(,)? - ) => { - let h = $crate::storage_root(); - $crate::assert_err!($x, $y); - assert_eq!(h, $crate::storage_root()); - } -} - -/// Panic if an expression doesn't evaluate to an `Err`. -/// -/// Used as `assert_err!(expression_to_assert, expected_err_expression)`. - -/// Assert an expression returns an error specified. -/// -/// Used as `assert_err!(expression_to_assert, expected_error_expression)` -#[macro_export] -#[cfg(feature = "std")] -macro_rules! assert_err { - ( $x:expr , $y:expr $(,)? ) => { - assert_eq!($x, Err($y)); - } -} - -/// Panic if an expression doesn't evaluate to `Ok`. -/// -/// Used as `assert_ok!(expression_to_assert, expected_ok_expression)`, -/// or `assert_ok!(expression_to_assert)` which would assert against `Ok(())`. -#[macro_export] -#[cfg(feature = "std")] -macro_rules! assert_ok { - ( $x:expr $(,)? ) => { - assert_eq!($x, Ok(())); - }; - ( $x:expr, $y:expr $(,)? ) => { - assert_eq!($x, Ok($y)); - } -} - -/// Panic when the vectors are different, without taking the order into account. -/// -/// # Examples -/// -/// ```rust -/// #[macro_use] -/// # extern crate srml_support; -/// # use srml_support::{assert_eq_uvec}; -/// # fn main() { -/// assert_eq_uvec!(vec![1,2], vec![2,1]); -/// # } -/// ``` -/// -/// ```rust,should_panic -/// #[macro_use] -/// # extern crate srml_support; -/// # use srml_support::{assert_eq_uvec}; -/// # fn main() { -/// assert_eq_uvec!(vec![1,2,3], vec![2,1]); -/// # } -/// ``` -#[macro_export] -#[cfg(feature = "std")] -macro_rules! assert_eq_uvec { - ( $x:expr, $y:expr ) => { - $crate::__assert_eq_uvec!($x, $y); - $crate::__assert_eq_uvec!($y, $x); - } -} - -#[macro_export] -#[doc(hidden)] -#[cfg(feature = "std")] -macro_rules! __assert_eq_uvec { - ( $x:expr, $y:expr ) => { - $x.iter().for_each(|e| { - if !$y.contains(e) { panic!(format!("vectors not equal: {:?} != {:?}", $x, $y)); } - }); - } -} - -/// The void type - it cannot exist. -// Oh rust, you crack me up... -#[derive(Clone, Eq, PartialEq, RuntimeDebug)] -pub enum Void {} - -#[cfg(feature = "std")] -#[doc(hidden)] -pub use serde::{Serialize, Deserialize}; - -#[cfg(test)] -mod tests { - use super::*; - use codec::{Codec, EncodeLike}; - use srml_metadata::{ - DecodeDifferent, StorageEntryMetadata, StorageMetadata, StorageEntryType, - StorageEntryModifier, DefaultByteGetter, StorageHasher, - }; - use rstd::marker::PhantomData; - - pub trait Trait { - type BlockNumber: Codec + EncodeLike + 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(fn data) build(|_| vec![(15u32, 42u64)]): linked_map hasher(twox_64_concat) u32 => u64; - pub OptionLinkedMap: linked_map u32 => Option; - pub GenericData get(fn generic_data): linked_map hasher(twox_128) T::BlockNumber => T::BlockNumber; - pub GenericData2 get(fn generic_data2): linked_map T::BlockNumber => Option; - pub GetterNoFnKeyword get(no_fn): Option; - - pub DataDM config(test_config) build(|_| vec![(15u32, 16u32, 42u64)]): - double_map hasher(twox_64_concat) u32, blake2_256(u32) => u64; - pub GenericDataDM: double_map T::BlockNumber, twox_128(T::BlockNumber) => T::BlockNumber; - pub GenericData2DM: double_map T::BlockNumber, twox_256(T::BlockNumber) => Option; - pub AppendableDM: double_map u32, blake2_256(T::BlockNumber) => Vec; - } - } - - struct Test; - impl Trait for Test { - type BlockNumber = u32; - type Origin = u32; - } - - fn new_test_ext() -> runtime_io::TestExternalities { - GenesisConfig::default().build_storage().unwrap().into() - } - - type Map = Data; - - #[test] - fn linked_map_issue_3318() { - new_test_ext().execute_with(|| { - OptionLinkedMap::insert(1, 1); - assert_eq!(OptionLinkedMap::get(1), Some(1)); - OptionLinkedMap::insert(1, 2); - assert_eq!(OptionLinkedMap::get(1), Some(2)); - }); - } - - #[test] - fn linked_map_swap_works() { - new_test_ext().execute_with(|| { - OptionLinkedMap::insert(0, 0); - OptionLinkedMap::insert(1, 1); - OptionLinkedMap::insert(2, 2); - OptionLinkedMap::insert(3, 3); - - let collect = || OptionLinkedMap::enumerate().collect::>(); - assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); - - // Two existing - OptionLinkedMap::swap(1, 2); - assert_eq!(collect(), vec![(3, 3), (2, 1), (1, 2), (0, 0)]); - - // Back to normal - OptionLinkedMap::swap(2, 1); - assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); - - // Left existing - OptionLinkedMap::swap(2, 5); - assert_eq!(collect(), vec![(5, 2), (3, 3), (1, 1), (0, 0)]); - - // Right existing - OptionLinkedMap::swap(5, 2); - assert_eq!(collect(), vec![(2, 2), (3, 3), (1, 1), (0, 0)]); - }); - } - - #[test] - fn linked_map_basic_insert_remove_should_work() { - new_test_ext().execute_with(|| { - // initialized 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 linked_map_enumeration_and_head_should_work() { - new_test_ext().execute_with(|| { - 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![]); - }); - } - - #[test] - fn double_map_basic_insert_remove_remove_prefix_should_work() { - new_test_ext().execute_with(|| { - type DoubleMap = DataDM; - // initialized during genesis - assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64); - - // get / insert / take - let key1 = 17u32; - let key2 = 18u32; - assert_eq!(DoubleMap::get(&key1, &key2), 0u64); - DoubleMap::insert(&key1, &key2, &4u64); - assert_eq!(DoubleMap::get(&key1, &key2), 4u64); - assert_eq!(DoubleMap::take(&key1, &key2), 4u64); - assert_eq!(DoubleMap::get(&key1, &key2), 0u64); - - // mutate - DoubleMap::mutate(&key1, &key2, |val| { - *val = 15; - }); - assert_eq!(DoubleMap::get(&key1, &key2), 15u64); - - // remove - DoubleMap::remove(&key1, &key2); - assert_eq!(DoubleMap::get(&key1, &key2), 0u64); - - // remove prefix - DoubleMap::insert(&key1, &key2, &4u64); - DoubleMap::insert(&key1, &(key2 + 1), &4u64); - DoubleMap::insert(&(key1 + 1), &key2, &4u64); - DoubleMap::insert(&(key1 + 1), &(key2 + 1), &4u64); - DoubleMap::remove_prefix(&key1); - assert_eq!(DoubleMap::get(&key1, &key2), 0u64); - assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64); - assert_eq!(DoubleMap::get(&(key1 + 1), &key2), 4u64); - assert_eq!(DoubleMap::get(&(key1 + 1), &(key2 + 1)), 4u64); - - }); - } - - #[test] - fn double_map_append_should_work() { - new_test_ext().execute_with(|| { - type DoubleMap = AppendableDM; - - let key1 = 17u32; - let key2 = 18u32; - - DoubleMap::insert(&key1, &key2, &vec![1]); - DoubleMap::append(&key1, &key2, &[2, 3]).unwrap(); - assert_eq!(DoubleMap::get(&key1, &key2), &[1, 2, 3]); - }); - } - - const EXPECTED_METADATA: StorageMetadata = StorageMetadata { - prefix: DecodeDifferent::Encode("Example"), - entries: DecodeDifferent::Encode( - &[ - StorageEntryMetadata { - name: DecodeDifferent::Encode("Data"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map{ - hasher: StorageHasher::Twox64Concat, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("u64"), - is_linked: true, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructData(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("OptionLinkedMap"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("u32"), - is_linked: true, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructOptionLinkedMap(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GenericData"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map{ - hasher: StorageHasher::Twox128, - key: DecodeDifferent::Encode("T::BlockNumber"), - value: DecodeDifferent::Encode("T::BlockNumber"), - is_linked: true - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGenericData(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GenericData2"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Map{ - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("T::BlockNumber"), - value: DecodeDifferent::Encode("T::BlockNumber"), - is_linked: true - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGenericData2(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GetterNoFnKeyword"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGetterNoFnKeyword(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("DataDM"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::DoubleMap{ - hasher: StorageHasher::Twox64Concat, - key1: DecodeDifferent::Encode("u32"), - key2: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("u64"), - key2_hasher: StorageHasher::Blake2_256, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructDataDM(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GenericDataDM"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::DoubleMap{ - hasher: StorageHasher::Blake2_256, - key1: DecodeDifferent::Encode("T::BlockNumber"), - key2: DecodeDifferent::Encode("T::BlockNumber"), - value: DecodeDifferent::Encode("T::BlockNumber"), - key2_hasher: StorageHasher::Twox128, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGenericDataDM(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GenericData2DM"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::DoubleMap{ - hasher: StorageHasher::Blake2_256, - key1: DecodeDifferent::Encode("T::BlockNumber"), - key2: DecodeDifferent::Encode("T::BlockNumber"), - value: DecodeDifferent::Encode("T::BlockNumber"), - key2_hasher: StorageHasher::Twox256, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("AppendableDM"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::DoubleMap{ - hasher: StorageHasher::Blake2_256, - key1: DecodeDifferent::Encode("u32"), - key2: DecodeDifferent::Encode("T::BlockNumber"), - value: DecodeDifferent::Encode("Vec"), - key2_hasher: StorageHasher::Blake2_256, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGenericData2DM(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - ] - ), - }; - - #[test] - fn store_metadata() { - let metadata = Module::::storage_metadata(); - pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata); - } -} diff --git a/srml/support/src/metadata.rs b/srml/support/src/metadata.rs deleted file mode 100644 index a223a14f9e405..0000000000000 --- a/srml/support/src/metadata.rs +++ /dev/null @@ -1,553 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -pub use srml_metadata::{ - DecodeDifferent, FnEncode, RuntimeMetadata, ModuleMetadata, RuntimeMetadataLastVersion, - DefaultByteGetter, RuntimeMetadataPrefixed, StorageEntryMetadata, StorageMetadata, - StorageEntryType, StorageEntryModifier, DefaultByte, StorageHasher, ModuleErrorMetadata -}; - -/// Implements the metadata support for the given runtime and all its modules. -/// -/// Example: -/// ``` -///# mod module0 { -///# pub trait Trait { -///# type Origin; -///# type BlockNumber; -///# } -///# srml_support::decl_module! { -///# pub struct Module for enum Call where origin: T::Origin {} -///# } -///# -///# srml_support::decl_storage! { -///# trait Store for Module as TestStorage {} -///# } -///# } -///# use module0 as module1; -///# use module0 as module2; -///# impl module0::Trait for Runtime { -///# type Origin = u32; -///# type BlockNumber = u32; -///# } -/// -/// struct Runtime; -/// srml_support::impl_runtime_metadata! { -/// for Runtime with modules -/// module0::Module as Module0 with, -/// module1::Module as Module1 with, -/// module2::Module as Module2 with Storage, -/// }; -/// ``` -/// -/// In this example, just `MODULE3` implements the `Storage` trait. -#[macro_export] -macro_rules! impl_runtime_metadata { - ( - for $runtime:ident with modules - $( $rest:tt )* - ) => { - impl $runtime { - pub fn metadata() -> $crate::metadata::RuntimeMetadataPrefixed { - $crate::metadata::RuntimeMetadataLastVersion { - modules: $crate::__runtime_modules_to_metadata!($runtime;; $( $rest )*), - }.into() - } - } - } -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __runtime_modules_to_metadata { - ( - $runtime: ident; - $( $metadata:expr ),*; - $mod:ident::$module:ident $( < $instance:ident > )? as $name:ident $(with)+ $($kw:ident)*, - $( $rest:tt )* - ) => { - $crate::__runtime_modules_to_metadata!( - $runtime; - $( $metadata, )* $crate::metadata::ModuleMetadata { - name: $crate::metadata::DecodeDifferent::Encode(stringify!($name)), - 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)* - ), - constants: $crate::metadata::DecodeDifferent::Encode( - $crate::metadata::FnEncode( - $mod::$module::<$runtime $(, $mod::$instance )?>::module_constants_metadata - ) - ), - errors: $crate::metadata::DecodeDifferent::Encode( - $crate::metadata::FnEncode( - <$mod::$module::<$runtime $(, $mod::$instance )?> as $crate::metadata::ModuleErrorMetadata>::metadata - ) - ) - }; - $( $rest )* - ) - }; - ( - $runtime:ident; - $( $metadata:expr ),*; - ) => { - $crate::metadata::DecodeDifferent::Encode(&[ $( $metadata ),* ]) - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __runtime_modules_to_metadata_calls_call { - ( - $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_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 )?>::storage_metadata - ) - )) - }; - ( - $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, StorageEntryModifier, StorageEntryType, FunctionMetadata, StorageEntryMetadata, - ModuleMetadata, RuntimeMetadataPrefixed, DefaultByte, ModuleConstantMetadata, DefaultByteGetter, - ErrorMetadata, - }; - use codec::{Encode, Decode}; - use crate::traits::Get; - - mod system { - use super::*; - - pub trait Trait { - const ASSOCIATED_CONST: u64 = 500; - type Origin: Into, Self::Origin>> - + From>; - type AccountId: From + Encode; - type BlockNumber: From + Encode; - type SomeValue: Get; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// Hi, I am a comment. - const BlockNumber: T::BlockNumber = 100.into(); - const GetType: T::AccountId = T::SomeValue::get().into(); - const ASSOCIATED_CONST: u64 = T::ASSOCIATED_CONST.into(); - } - } - - decl_event!( - pub enum Event { - SystemEvent, - } - ); - - #[derive(Clone, PartialEq, Eq, Debug)] - pub enum RawOrigin { - Root, - Signed(AccountId), - None, - } - - impl From> for RawOrigin { - fn from(s: Option) -> RawOrigin { - match s { - Some(who) => RawOrigin::Signed(who), - None => RawOrigin::None, - } - } - } - - pub type Origin = RawOrigin<::AccountId>; - } - - mod event_module { - use crate::dispatch::DispatchResult; - - pub trait Trait { - type Origin; - type Balance; - type BlockNumber; - } - - decl_event!( - pub enum Event where ::Balance - { - /// Hi, I am a comment. - TestEvent(Balance), - } - ); - - decl_module! { - pub struct Module for enum Call where origin: T::Origin { - type Error = Error; - - fn aux_0(_origin) -> DispatchResult { unreachable!() } - } - } - - crate::decl_error! { - pub enum Error { - /// Some user input error - UserInputError, - /// Something bad happened - /// this could be due to many reasons - BadThingHappened, - } - } - } - - mod event_module2 { - pub trait Trait { - type Origin; - type Balance; - type BlockNumber; - } - - decl_event!( - pub enum Event where ::Balance - { - TestEvent(Balance), - } - ); - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - crate::decl_storage! { - trait Store for Module as TestStorage { - StorageMethod : Option; - } - add_extra_genesis { - build(|_| {}); - } - } - } - - type EventModule = event_module::Module; - type EventModule2 = event_module2::Module; - - #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] - pub struct TestRuntime; - - impl_outer_event! { - pub enum TestEvent for TestRuntime { - event_module, - event_module2, - } - } - - impl_outer_origin! { - pub enum Origin for TestRuntime {} - } - - impl_outer_dispatch! { - pub enum Call for TestRuntime where origin: Origin { - event_module::EventModule, - event_module2::EventModule2, - } - } - - impl event_module::Trait for TestRuntime { - type Origin = Origin; - type Balance = u32; - type BlockNumber = u32; - } - - impl event_module2::Trait for TestRuntime { - type Origin = Origin; - type Balance = u32; - type BlockNumber = u32; - } - - crate::parameter_types! { - pub const SystemValue: u32 = 600; - } - - impl system::Trait for TestRuntime { - type Origin = Origin; - type AccountId = u32; - type BlockNumber = u32; - type SomeValue = SystemValue; - } - - impl_runtime_metadata!( - for TestRuntime with modules - system::Module as System with Event, - event_module::Module as Module with Event Call, - event_module2::Module as Module2 with Event Storage Call, - ); - - struct ConstantBlockNumberByteGetter; - impl DefaultByte for ConstantBlockNumberByteGetter { - fn default_byte(&self) -> Vec { - 100u32.encode() - } - } - - struct ConstantGetTypeByteGetter; - impl DefaultByte for ConstantGetTypeByteGetter { - fn default_byte(&self) -> Vec { - SystemValue::get().encode() - } - } - - struct ConstantAssociatedConstByteGetter; - impl DefaultByte for ConstantAssociatedConstByteGetter { - fn default_byte(&self) -> Vec { - ::ASSOCIATED_CONST.encode() - } - } - - const EXPECTED_METADATA: RuntimeMetadataLastVersion = RuntimeMetadataLastVersion { - modules: DecodeDifferent::Encode(&[ - ModuleMetadata { - name: DecodeDifferent::Encode("System"), - storage: None, - calls: None, - event: Some(DecodeDifferent::Encode( - FnEncode(||&[ - EventMetadata { - name: DecodeDifferent::Encode("SystemEvent"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[]) - } - ]) - )), - constants: DecodeDifferent::Encode( - FnEncode(|| &[ - ModuleConstantMetadata { - name: DecodeDifferent::Encode("BlockNumber"), - ty: DecodeDifferent::Encode("T::BlockNumber"), - value: DecodeDifferent::Encode( - DefaultByteGetter(&ConstantBlockNumberByteGetter) - ), - documentation: DecodeDifferent::Encode(&[" Hi, I am a comment."]), - }, - ModuleConstantMetadata { - name: DecodeDifferent::Encode("GetType"), - ty: DecodeDifferent::Encode("T::AccountId"), - value: DecodeDifferent::Encode( - DefaultByteGetter(&ConstantGetTypeByteGetter) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - ModuleConstantMetadata { - name: DecodeDifferent::Encode("ASSOCIATED_CONST"), - ty: DecodeDifferent::Encode("u64"), - value: DecodeDifferent::Encode( - DefaultByteGetter(&ConstantAssociatedConstByteGetter) - ), - documentation: DecodeDifferent::Encode(&[]), - } - ]) - ), - errors: DecodeDifferent::Encode(FnEncode(|| &[])), - }, - ModuleMetadata { - name: DecodeDifferent::Encode("Module"), - storage: None, - calls: Some( - DecodeDifferent::Encode(FnEncode(|| &[ - FunctionMetadata { - name: DecodeDifferent::Encode("aux_0"), - arguments: DecodeDifferent::Encode(&[]), - documentation: DecodeDifferent::Encode(&[]), - } - ]))), - event: Some(DecodeDifferent::Encode( - FnEncode(||&[ - EventMetadata { - name: DecodeDifferent::Encode("TestEvent"), - arguments: DecodeDifferent::Encode(&["Balance"]), - documentation: DecodeDifferent::Encode(&[" Hi, I am a comment."]) - } - ]) - )), - constants: DecodeDifferent::Encode(FnEncode(|| &[])), - errors: DecodeDifferent::Encode(FnEncode(|| &[ - ErrorMetadata { - name: DecodeDifferent::Encode("UserInputError"), - documentation: DecodeDifferent::Encode(&[" Some user input error"]), - }, - ErrorMetadata { - name: DecodeDifferent::Encode("BadThingHappened"), - documentation: DecodeDifferent::Encode(&[ - " Something bad happened", - " this could be due to many reasons", - ]), - }, - ])), - }, - ModuleMetadata { - name: DecodeDifferent::Encode("Module2"), - storage: Some(DecodeDifferent::Encode( - FnEncode(|| StorageMetadata { - prefix: DecodeDifferent::Encode("TestStorage"), - entries: DecodeDifferent::Encode( - &[ - StorageEntryMetadata { - name: DecodeDifferent::Encode("StorageMethod"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::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(&[]) - } - ]) - )), - constants: DecodeDifferent::Encode(FnEncode(|| &[])), - errors: DecodeDifferent::Encode(FnEncode(|| &[])), - }, - ]) - }; - - #[test] - fn runtime_metadata() { - let metadata_encoded = TestRuntime::metadata().encode(); - let metadata_decoded = RuntimeMetadataPrefixed::decode(&mut &metadata_encoded[..]); - let expected_metadata: RuntimeMetadataPrefixed = EXPECTED_METADATA.into(); - - pretty_assertions::assert_eq!(expected_metadata, metadata_decoded.unwrap()); - } -} diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs deleted file mode 100644 index 52bf48baa5740..0000000000000 --- a/srml/support/src/runtime.rs +++ /dev/null @@ -1,948 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! 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 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` -/// and the modules that are used by the runtime. -/// `Block` is the block type that is used in the runtime and `NodeBlock` is the block type -/// that is used in the node. For instance they can differ in the extrinsics type. -/// -/// # Example: -/// -/// ```nocompile -/// construct_runtime!( -/// pub enum Runtime where -/// Block = Block, -/// NodeBlock = runtime::Block, -/// UncheckedExtrinsic = UncheckedExtrinsic -/// { -/// System: system, -/// Test: test::{default}, -/// 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 identifier `System` is the name of the module and the lower case identifier `system` is the -/// name of the Rust module/crate for this Substrate module. -/// -/// The module `Test: test::{default}` will expand to -/// `Test: test::{Module, Call, Storage, Event, Config}`. -/// -/// The module `Test2: test_with_long_module::{Module}` will expand to -/// `Test2: test_with_long_module::{Module}`. -/// -/// We provide support for the following types in a module: -/// -/// - `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) -/// - `Inherent $( (CALL) )*` - If the module provides/can check inherents. The optional parameter -/// is for modules that use a `Call` from a different module as -/// inherent. -/// - `ValidateUnsigned` - If the module validates unsigned extrinsics. -/// -/// # Note -/// -/// The population of the genesis storage depends on the order of modules. So, if one of your -/// modules depends on another module, the module that is depended upon needs 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 - where - Block = $block:ident, - NodeBlock = $node_block:ty, - UncheckedExtrinsic = $uncheckedextrinsic:ident - { - $( $rest:tt )* - } - ) => { - $crate::construct_runtime!( - { - $runtime; - $block; - $node_block; - $uncheckedextrinsic; - }; - {}; - $( $rest )* - ); - }; - // No modules given, expand to the default module set. - ( - { $( $preset:tt )* }; - { $( $expanded:tt )* }; - $name:ident: $module:ident, - $( $rest:tt )* - ) => { - $crate::construct_runtime!( - { $( $preset )* }; - { $( $expanded )* }; - $name: $module::{default}, - $( $rest )* - ); - }; - // `default` identifier given, expand to default + given extra modules - ( - { $( $preset:tt )* }; - { $( $expanded:tt )* }; - $name:ident: $module:ident::{ - default - $(, - $modules:ident - $( <$modules_generic:ident> )* - $( ( $( $modules_args:ident ),* ) )* - )* - }, - $( $rest:tt )* - ) => { - $crate::construct_runtime!( - { $( $preset )* }; - { - $( $expanded )* - $name: $module::{ - Module, Call, Storage, Event, Config - $(, - $modules $( <$modules_generic> )* - $( ( $( $modules_args ),* ) )* - )* - }, - }; - $( $rest )* - ); - }; - // Take all modules as given by the user. - ( - { $( $preset:tt )* }; - { $( $expanded:tt )* }; - $name:ident: $module:ident :: $( < $module_instance:ident >:: )? { - $( - $modules:ident - $( <$modules_generic:ident> )* - $( ( $( $modules_args:ident ),* ) )* - ),* - }, - $( $rest:tt )* - ) => { - $crate::construct_runtime!( - { $( $preset )* }; - { - $( $expanded )* - $name: $module:: $( < $module_instance >:: )? { - $( - $modules $( <$modules_generic> )* - $( ( $( $modules_args ),* ) )* - ),* - }, - }; - $( $rest )* - ); - }; - // The main macro expansion that actually renders the Runtime code. - ( - { - $runtime:ident; - $block:ident; - $node_block:ty; - $uncheckedextrinsic:ident; - }; - { - $( - $name:ident: $module:ident :: $( < $module_instance:ident >:: )? { - $( - $modules:ident - $( <$modules_generic:ident> )* - $( ( $( $modules_args:ident ),* ) )* - ),* - }, - )* - }; - ) => { - #[derive(Clone, Copy, PartialEq, Eq, $crate::RuntimeDebug)] - pub struct $runtime; - impl $crate::sr_primitives::traits::GetNodeBlockType for $runtime { - type NodeBlock = $node_block; - } - impl $crate::sr_primitives::traits::GetRuntimeBlockType for $runtime { - type RuntimeBlock = $block; - } - $crate::__decl_outer_event!( - $runtime; - $( - $name: $module:: $( < $module_instance >:: )? { - $( $modules $( <$modules_generic> )* ),* - } - ),* - ); - $crate::__decl_outer_origin!( - $runtime; - $( - $name: $module:: $( < $module_instance >:: )? { - $( $modules $( <$modules_generic> )* ),* - } - ),* - ); - $crate::__decl_all_modules!( - $runtime; - ; - {}; - {}; - $( - $name: $module:: $( < $module_instance >:: )? { $( $modules ),* }, - )* - ); - $crate::__decl_outer_dispatch!( - $runtime; - ; - $( - $name: $module::{ $( $modules ),* } - ),*; - ); - $crate::__decl_runtime_metadata!( - $runtime; - {}; - $( - $name: $module:: $( < $module_instance >:: )? { $( $modules )* } - )* - ); - $crate::__decl_outer_config!( - $runtime; - {}; - $( - $name: $module:: $( < $module_instance >:: )? { - $( $modules $( <$modules_generic> )* ),* - }, - )* - ); - $crate::__decl_outer_inherent!( - $runtime; - $block; - $uncheckedextrinsic; - ; - $( - $name: $module::{ $( $modules $( ( $( $modules_args )* ) )* ),* } - ),*; - ); - $crate::__impl_outer_validate_unsigned!( - $runtime; - {}; - $( - $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 { - ( - // Parameter $d is a hack for the following issue: - // https://github.com/rust-lang/rust/issues/35853 - $macro_name:ident, $macro_outer_name:ident, $macro_enum_name:ident, $d:tt - ) => { - #[macro_export] - #[doc(hidden)] - macro_rules! $macro_name { - ( - $runtime:ident; - $d( $name:ident : $module:ident:: $d( < $module_instance:ident >:: )? { - $d( $modules:ident $d( <$modules_generic:ident> ),* ),* - }),* - ) => { - $d crate::$macro_name!(@inner - $runtime; - ; - {}; - $d( - $name: $module:: $d( < $module_instance >:: )? { - $d( $modules $d( <$modules_generic> )* ),* - }, - )* - ); - }; - // Parse system module - (@inner - $runtime:ident; - ; // there can not be multiple `System`s - { $d( $parsed:tt )* }; - System: $module:ident::{ - $d( $modules:ident $d( <$modules_generic:ident> )* ),* - }, - $d( $rest:tt )* - ) => { - $d crate::$macro_name!(@inner - $runtime; - $module; - { $d( $parsed )* }; - $d( $rest )* - ); - }; - // Parse instantiable module with generic - (@inner - $runtime:ident; - $d( $system:ident )?; - { $d( $parsed:tt )* }; - $name:ident : $module:ident:: < $module_instance:ident >:: { - $macro_enum_name <$event_generic:ident> $d(, $ingore:ident $d( <$ignor:ident> )* )* - }, - $d( $rest:tt )* - ) => { - $d crate::$macro_name!(@inner - $runtime; - $d( $system )?; - { - $d( $parsed )* - $module $module_instance <$event_generic>, - }; - $d( $rest )* - ); - }; - // Parse instantiable module with no generic - (@inner - $runtime:ident; - $d( $system:ident )?; - { $d( $parsed:tt )* }; - $name:ident : $module:ident:: < $module_instance:ident >:: { - $macro_enum_name $d(, $ingore:ident $d( <$ignor:ident> )* )* - }, - $d( $rest:tt )* - ) => { - compile_error!(concat!( - "Instantiable module with not generic ", stringify!($macro_enum_name), - " cannot be constructed: module `", stringify!($name), "` must have generic ", - stringify!($macro_enum_name), "." - )); - }; - // Parse instantiable module with no generic - (@inner - $runtime:ident; - $d( $system:ident )?; - { $d( $parsed:tt )* }; - $name:ident : $module:ident:: { - $macro_enum_name $d( <$event_generic:ident> )* $d(, $ignore:ident $d( <$ignor:ident> )* )* - }, - $d( $rest:tt )* - ) => { - $d crate::$macro_name!(@inner - $runtime; - $d( $system )?; - { - $d( $parsed )* - $module $d( <$event_generic> )*, - }; - $d( $rest )* - ); - }; - // Ignore keyword - (@inner - $runtime:ident; - $d( $system:ident )?; - { $d( $parsed:tt )* }; - $name:ident : $module:ident:: $d( < $module_instance:ident >:: )? { - $ingore:ident $d( <$ignor:ident> )* $d(, $modules:ident $d( <$modules_generic:ident> )* )* - }, - $d( $rest:tt )* - ) => { - $d crate::$macro_name!(@inner - $runtime; - $d( $system )?; - { $d( $parsed )* }; - $name: $module:: $d( < $module_instance >:: )? { $d( $modules $d( <$modules_generic> )* ),* }, - $d( $rest )* - ); - }; - // Ignore module - (@inner - $runtime:ident; - $d( $system:ident )?; - { $d( $parsed:tt )* }; - $name:ident: $module:ident:: $d( < $module_instance:ident >:: )? {}, - $d( $rest:tt )* - ) => { - $d crate::$macro_name!(@inner - $runtime; - $d( $system )?; - { $d( $parsed )* }; - $d( $rest )* - ); - }; - // Expand - (@inner - $runtime:ident; - $system:ident; - { $d( $parsed_modules:ident $d( $instance:ident )? $d( <$parsed_generic:ident> )? ,)* }; - ) => { - $d crate::$macro_outer_name! { - pub enum $macro_enum_name for $runtime where system = $system { - $d( - $parsed_modules $d( $instance )? $d( <$parsed_generic> )?, - )* - } - } - } - } - } -} - -__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:tt )* }; - { $( $parsed_nested:tt )* }; - System: $module:ident::{ Module $(, $modules:ident )* }, - $( $rest:tt )* - ) => { - $crate::__decl_all_modules!( - $runtime; - $module; - { $( $parsed )* }; - { $( $parsed_nested )* }; - $( $rest )* - ); - }; - ( - $runtime:ident; - $( $system:ident )?; - { $( $parsed:tt )* }; - {}; - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $(, $modules:ident )* }, - $( $rest:tt )* - ) => { - $crate::__decl_all_modules!( - $runtime; - $( $system )?; - { - $( $parsed )* - $module::$name $(<$module_instance>)?, - }; - { $name }; - $( $rest )* - ); - }; - ( - $runtime:ident; - $( $system:ident )?; - { $( $parsed:tt )* }; - { $( $parsed_nested:tt )* }; - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $(, $modules:ident )* }, - $( $rest:tt )* - ) => { - $crate::__decl_all_modules!( - $runtime; - $( $system )?; - { - $( $parsed )* - $module::$name $(<$module_instance>)?, - }; - { ( $( $parsed_nested )*, $name, ) }; - $( $rest )* - ); - }; - ( - $runtime:ident; - $( $system:ident )?; - { $( $parsed:tt )* }; - { $( $parsed_nested:tt )* }; - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { $ignore:ident $(, $modules:ident )* }, - $( $rest:tt )* - ) => { - $crate::__decl_all_modules!( - $runtime; - $( $system )?; - { $( $parsed )* }; - { $( $parsed_nested )* }; - $name: $module::{ $( $modules ),* }, - $( $rest )* - ); - }; - ( - $runtime:ident; - $( $system:ident )?; - { $( $parsed:tt )* }; - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {}, - $( $rest:tt )* - ) => { - $crate::__decl_all_modules!( - $runtime; - $( $system )?; - { $( $parsed )* }; - { $( $parsed_nested )* }; - $( $rest )* - ); - }; - ( - $runtime:ident; - $system:ident; - { $( $parsed_module:ident :: $parsed_name:ident $(<$instance:ident>)? ,)*}; - { $( $parsed_nested:tt )* }; - ) => { - pub type System = system::Module<$runtime>; - $( - pub type $parsed_name = $parsed_module::Module<$runtime $(, $parsed_module::$instance )?>; - )* - type AllModules = ( $( $parsed_nested )* ); - } -} - -/// 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 { - ( - $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{ - Call $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - $crate::__decl_outer_dispatch!( - $runtime; - $( $parsed_modules :: $parsed_name, )* $module::$name; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; - ); - }; - ( - $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{ - $ignore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* - } - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - $crate::__decl_outer_dispatch!( - $runtime; - $( $parsed_modules :: $parsed_name ),*; - $name: $module::{ $( $modules $( <$modules_generic> )* ),* } - $( - , $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - )*; - ); - }; - ( - $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* - })*; - ) => { - $crate::__decl_outer_dispatch!( - $runtime; - $( $parsed_modules :: $parsed_name ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( <$rest_modules_generic> )* ),* - } - ),*; - ); - }; - ( - $runtime:ident; - $( $parsed_modules:ident :: $parsed_name:ident ),*; - ; - ) => { - $crate::impl_outer_dispatch!( - pub enum Call for $runtime where origin: Origin { - $( $parsed_modules::$parsed_name, )* - } - ); - }; -} - -/// 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:tt )* }; - $( { leading_module: $( $leading_module:ident )* } )? - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { - Module $( $modules:ident )* - } - $( $rest:tt )* - ) => { - $crate::__decl_runtime_metadata!( - $runtime; - { - $( $parsed )* - $module $( < $module_instance > )? as $name { - $( $( $leading_module )* )? $( $modules )* - } - }; - $( $rest )* - ); - }; - // leading isn't Module : put it in leadings - ( - $runtime:ident; - { $( $parsed:tt )* }; - $( { leading_module: $( $leading_module:ident )* } )? - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { - $other_module:ident $( $modules:ident )* - } - $( $rest:tt )* - ) => { - $crate::__decl_runtime_metadata!( - $runtime; - { $( $parsed )* }; - { leading_module: $( $( $leading_module )* )? $other_module } - $name: $module:: $( < $module_instance >:: )? { - $( $modules )* - } - $( $rest )* - ); - }; - // does not contain Module : skip - ( - $runtime:ident; - { $( $parsed:tt )* }; - $( { leading_module: $( $leading_module:ident )* } )? - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {} - $( $rest:tt )* - ) => { - $crate::__decl_runtime_metadata!( - $runtime; - { $( $parsed )* }; - $( $rest )* - ); - }; - // end of decl - ( - $runtime:ident; - { - $( - $parsed_modules:ident $( < $module_instance:ident > )? as $parsed_name:ident { - $( $withs:ident )* - } - )* - }; - ) => { - $crate::impl_runtime_metadata!( - for $runtime with modules - $( $parsed_modules::Module $( < $module_instance > )? as $parsed_name - with $( $withs )* , )* - ); - } -} - -/// 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:tt )* }; - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { - Config $( <$config_generic:ident> )? - $(, $modules:ident $( <$modules_generic:ident> )* )* - }, - $( $rest:tt )* - ) => { - $crate::__decl_outer_config!( - $runtime; - { - $( $parsed )* - $module::$name $( $module_instance )? $( <$config_generic> )?, - }; - $( $rest )* - ); - }; - ( - $runtime:ident; - { $( $parsed:tt )* }; - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { - $ingore:ident $( <$ignore_gen:ident> )* - $(, $modules:ident $( <$modules_generic:ident> )* )* - }, - $( $rest:tt )* - ) => { - $crate::__decl_outer_config!( - $runtime; - { $( $parsed )* }; - $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic> )* ),* }, - $( $rest )* - ); - }; - ( - $runtime:ident; - { $( $parsed:tt )* }; - $name:ident: $module:ident:: $( < $module_instance:ident >:: )? {}, - $( $rest:tt )* - ) => { - $crate::__decl_outer_config!( - $runtime; - { $( $parsed )* }; - $( $rest )* - ); - }; - ( - $runtime:ident; - { - $( - $parsed_modules:ident :: $parsed_name:ident $( $parsed_instance:ident )? - $( - <$parsed_generic:ident> - )* - ,)* - }; - ) => { - $crate::paste::item! { - $crate::sr_primitives::impl_outer_config!( - pub struct GenesisConfig for $runtime { - $( - [< $parsed_name Config >] => - $parsed_modules $( $parsed_instance )? $( <$parsed_generic> )*, - )* - } - ); - } - }; -} - -/// A private macro that generates check_inherents() implementation for the runtime. -#[macro_export] -#[doc(hidden)] -macro_rules! __decl_outer_inherent { - ( - $runtime:ident; - $block:ident; - $uncheckedextrinsic:ident; - $( $parsed_name:ident :: $parsed_call:ident ),*; - $name:ident: $module:ident::{ - Inherent $(, $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::$name; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( ( $( $rest_call )* ) )* ),* - } - ),*; - ); - }; - ( - $runtime:ident; - $block:ident; - $uncheckedextrinsic:ident; - $( $parsed_name:ident :: $parsed_call:ident ),*; - $name:ident: $module:ident::{ - Inherent ( $call: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::$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::{ - $ignore: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_call )* ) )* ),* - } - )*; - ); - }; - ( - $runtime:ident; - $block:ident; - $uncheckedextrinsic:ident; - $( $parsed_name:ident :: $parsed_call:ident ),*; - $name:ident: $module:ident::{} - $(, $rest_name:ident : $rest_module:ident::{ - $( $rest_modules:ident $( ( $( $rest_call:ident )* ) )* ),* - })*; - ) => { - $crate::__decl_outer_inherent!( - $runtime; - $block; - $uncheckedextrinsic; - $( $parsed_name :: $parsed_call ),*; - $( - $rest_name: $rest_module::{ - $( $rest_modules $( ( $( $rest_call )* ) )* ),* - } - ),*; - ); - }; - ( - $runtime:ident; - $block:ident; - $uncheckedextrinsic:ident; - $( $parsed_name:ident :: $parsed_call:ident ),*; - ; - ) => { - $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 >];)* - } - }; -} - -/// A private macro that calls impl_outer_validate_unsigned for Call. -#[macro_export] -#[doc(hidden)] -macro_rules! __impl_outer_validate_unsigned { - ( - $runtime:ident; - { $( $parsed:tt )* }; - $name:ident: $module:ident:: $(<$module_instance:ident>::)? { - ValidateUnsigned $( $modules:ident $( ( $( $modules_args:ident )* ) )* )* - } - $( $rest:tt )* - ) => { - $crate::__impl_outer_validate_unsigned!( - $runtime; - { $( $parsed )* $name }; - $( $rest )* - ); - }; - ( - $runtime:ident; - { $( $parsed:tt )* }; - $name:ident: $module:ident:: $(<$module_instance:ident>::)? { - $ignore:ident $( ( $( $args_ignore:ident )* ) )* - $( $modules:ident $( ( $( $modules_args:ident )* ) )* )* - } - $( $rest:tt )* - ) => { - $crate::__impl_outer_validate_unsigned!( - $runtime; - { $( $parsed )* }; - $name: $module:: $(<$module_instance>::)? { - $( $modules $( ( $( $modules_args )* ) )* )* - } - $( $rest )* - ); - }; - ( - $runtime:ident; - { $( $parsed:tt )* }; - $name:ident: $module:ident:: $(<$module_instance:ident>::)? {} - $( $rest:tt )* - ) => { - $crate::__impl_outer_validate_unsigned!( - $runtime; - { $( $parsed )* }; - $( $rest )* - ); - }; - ( - $runtime:ident; - { $( - $parsed_modules:ident - )* }; - ) => { - $crate::impl_outer_validate_unsigned!( - impl ValidateUnsigned for $runtime { - $( $parsed_modules )* - } - ); - }; -} diff --git a/srml/support/src/storage/child.rs b/srml/support/src/storage/child.rs deleted file mode 100644 index 1d6ee7a6f1a61..0000000000000 --- a/srml/support/src/storage/child.rs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Operation on runtime child storages. -//! -//! This module is a currently only a variant of unhashed with additional `storage_key`. -//! Note that `storage_key` must be unique and strong (strong in the sense of being long enough to -//! avoid collision from a resistant hash function (which unique implies)). -// NOTE: could replace unhashed by having only one kind of storage (root being null storage key (storage_key can become Option<&[u8]>). - -use crate::rstd::prelude::*; -use codec::{Codec, Encode, Decode}; - -/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. -pub fn get(storage_key: &[u8], key: &[u8]) -> Option { - runtime_io::child_storage(storage_key, key).map(|v| { - Decode::decode(&mut &v[..]).expect("storage is not null, therefore must be a valid type") - }) -} - -/// Return the value of the item in storage under `key`, or the type's default if there is no -/// explicit entry. -pub fn get_or_default(storage_key: &[u8], key: &[u8]) -> T { - get(storage_key, key).unwrap_or_else(Default::default) -} - -/// Return the value of the item in storage under `key`, or `default_value` if there is no -/// explicit entry. -pub fn get_or(storage_key: &[u8], key: &[u8], default_value: T) -> T { - get(storage_key, key).unwrap_or(default_value) -} - -/// Return the value of the item in storage under `key`, or `default_value()` if there is no -/// explicit entry. -pub fn get_or_else T>(storage_key: &[u8], key: &[u8], default_value: F) -> T { - get(storage_key, key).unwrap_or_else(default_value) -} - -/// Put `value` in storage under `key`. -pub fn put(storage_key: &[u8], key: &[u8], value: &T) { - value.using_encoded(|slice| runtime_io::set_child_storage(storage_key, key, slice)); -} - -/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. -pub fn take(storage_key: &[u8], key: &[u8]) -> Option { - let r = get(storage_key, key); - if r.is_some() { - kill(storage_key, key); - } - r -} - -/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, -/// the default for its type. -pub fn take_or_default(storage_key: &[u8], key: &[u8]) -> T { - take(storage_key, key).unwrap_or_else(Default::default) -} - -/// Return the value of the item in storage under `key`, or `default_value` if there is no -/// explicit entry. Ensure there is no explicit entry on return. -pub fn take_or(storage_key: &[u8],key: &[u8], default_value: T) -> T { - take(storage_key, key).unwrap_or(default_value) -} - -/// Return the value of the item in storage under `key`, or `default_value()` if there is no -/// explicit entry. Ensure there is no explicit entry on return. -pub fn take_or_else T>(storage_key: &[u8], key: &[u8], default_value: F) -> T { - take(storage_key, key).unwrap_or_else(default_value) -} - -/// Check to see if `key` has an explicit entry in storage. -pub fn exists(storage_key: &[u8], key: &[u8]) -> bool { - runtime_io::read_child_storage(storage_key, key, &mut [0;0][..], 0).is_some() -} - -/// Remove all `storage_key` key/values -pub fn kill_storage(storage_key: &[u8]) { - runtime_io::kill_child_storage(storage_key) -} - -/// Ensure `key` has no explicit entry in storage. -pub fn kill(storage_key: &[u8], key: &[u8]) { - runtime_io::clear_child_storage(storage_key, key); -} - -/// Get a Vec of bytes from storage. -pub fn get_raw(storage_key: &[u8], key: &[u8]) -> Option> { - runtime_io::child_storage(storage_key, key) -} - -/// Put a raw byte slice into storage. -pub fn put_raw(storage_key: &[u8], key: &[u8], value: &[u8]) { - runtime_io::set_child_storage(storage_key, key, value) -} diff --git a/srml/support/src/storage/generator/double_map.rs b/srml/support/src/storage/generator/double_map.rs deleted file mode 100644 index cac8dbd034e85..0000000000000 --- a/srml/support/src/storage/generator/double_map.rs +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use rstd::prelude::*; -use rstd::borrow::Borrow; -use codec::{Ref, FullCodec, FullEncode, Encode, EncodeLike, EncodeAppend}; -use crate::{storage::{self, unhashed}, hash::StorageHasher}; - -/// Generator for `StorageDoubleMap` used by `decl_storage`. -/// -/// # Mapping of keys to a storage path -/// -/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. -/// The first part is a hash of a concatenation of the `key1_prefix` and `Key1`. And the second part -/// is a hash of a `Key2`. -/// -/// Thus value for (key1, key2) is stored at: -/// ```nocompile -/// Hasher1(key1_prefix ++ key1) ++ Hasher2(key2) -/// ``` -/// -/// # Warning -/// -/// If the key1s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as -/// `blake2_256` must be used for Hasher1. Otherwise, other values in storage can be compromised. -/// If the key2s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as -/// `blake2_256` must be used for Hasher2. Otherwise, other items in storage with the same first -/// key can be compromised. -pub trait StorageDoubleMap { - /// The type that get/take returns. - type Query; - - /// Hasher for the first key. - type Hasher1: StorageHasher; - - /// Hasher for the second key. - type Hasher2: StorageHasher; - - /// Get the prefix for first key. - fn key1_prefix() -> &'static [u8]; - - /// Convert an optional value retrieved from storage to the type queried. - fn from_optional_value_to_query(v: Option) -> Self::Query; - - /// Convert a query to an optional value into storage. - fn from_query_to_optional_value(v: Self::Query) -> Option; - - /// Generate the first part of the key used in top storage. - fn storage_double_map_final_key1(k1: KArg1) -> ::Output - where - KArg1: EncodeLike, - { - let mut final_key1 = Self::key1_prefix().to_vec(); - k1.encode_to(&mut final_key1); - Self::Hasher1::hash(&final_key1) - } - - /// Generate the full key used in top storage. - fn storage_double_map_final_key(k1: KArg1, k2: KArg2) -> Vec - where - KArg1: EncodeLike, - KArg2: EncodeLike, - { - let mut final_key = Self::storage_double_map_final_key1(k1).as_ref().to_vec(); - final_key.extend_from_slice(k2.using_encoded(Self::Hasher2::hash).as_ref()); - final_key - } -} - -impl storage::StorageDoubleMap for G -where - K1: FullEncode, - K2: FullEncode, - V: FullCodec, - G: StorageDoubleMap, -{ - type Query = G::Query; - - fn exists(k1: KArg1, k2: KArg2) -> bool - where - KArg1: EncodeLike, - KArg2: EncodeLike, - { - unhashed::exists(&Self::storage_double_map_final_key(k1, k2)) - } - - fn get(k1: KArg1, k2: KArg2) -> Self::Query - where - KArg1: EncodeLike, - KArg2: EncodeLike, - { - G::from_optional_value_to_query(unhashed::get(&Self::storage_double_map_final_key(k1, k2))) - } - - fn take(k1: KArg1, k2: KArg2) -> Self::Query - where - KArg1: EncodeLike, - KArg2: EncodeLike, - { - let final_key = Self::storage_double_map_final_key(k1, k2); - - let value = unhashed::take(&final_key); - G::from_optional_value_to_query(value) - } - - fn insert(k1: KArg1, k2: KArg2, val: VArg) - where - KArg1: EncodeLike, - KArg2: EncodeLike, - VArg: EncodeLike, - { - unhashed::put(&Self::storage_double_map_final_key(k1, k2), &val.borrow()) - } - - fn remove(k1: KArg1, k2: KArg2) - where - KArg1: EncodeLike, - KArg2: EncodeLike, - { - unhashed::kill(&Self::storage_double_map_final_key(k1, k2)) - } - - fn remove_prefix(k1: KArg1) where KArg1: EncodeLike { - unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref()) - } - - fn mutate(k1: KArg1, k2: KArg2, f: F) -> R - where - KArg1: EncodeLike, - KArg2: EncodeLike, - F: FnOnce(&mut Self::Query) -> R, - { - let final_key = Self::storage_double_map_final_key(k1, k2); - let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref())); - - let ret = f(&mut val); - match G::from_query_to_optional_value(val) { - Some(ref val) => unhashed::put(final_key.as_ref(), val), - None => unhashed::kill(final_key.as_ref()), - } - ret - } - - fn append( - k1: KArg1, - k2: KArg2, - items: Items, - ) -> Result<(), &'static str> - where - KArg1: EncodeLike, - KArg2: EncodeLike, - Item: Encode, - EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator, - Items::IntoIter: ExactSizeIterator - { - let final_key = Self::storage_double_map_final_key(k1, k2); - - let encoded_value = unhashed::get_raw(&final_key) - .unwrap_or_else(|| { - match G::from_query_to_optional_value(G::from_optional_value_to_query(None)) { - Some(value) => value.encode(), - None => vec![], - } - }); - - let new_val = V::append_or_new( - encoded_value, - items, - ).map_err(|_| "Could not append given item")?; - unhashed::put_raw(&final_key, &new_val); - - Ok(()) - } - - fn append_or_insert( - k1: KArg1, - k2: KArg2, - items: Items, - ) - where - KArg1: EncodeLike, - KArg2: EncodeLike, - Item: Encode, - EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator + Clone + EncodeLike, - Items::IntoIter: ExactSizeIterator - { - Self::append(Ref::from(&k1), Ref::from(&k2), items.clone()) - .unwrap_or_else(|_| Self::insert(k1, k2, items)); - } -} diff --git a/srml/support/src/storage/generator/linked_map.rs b/srml/support/src/storage/generator/linked_map.rs deleted file mode 100644 index 6643a37f4f50c..0000000000000 --- a/srml/support/src/storage/generator/linked_map.rs +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use codec::{FullCodec, Encode, Decode, EncodeLike, Ref}; -use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len}; -use rstd::marker::PhantomData; - -/// Generator for `StorageLinkedMap` used by `decl_storage`. -/// -/// # Mapping of keys to a storage path -/// -/// The key for the head of the map is stored at one fixed path: -/// ```nocompile -/// Hasher(head_key) -/// ``` -/// -/// For each key, the value stored under that key is appended with a -/// [`Linkage`](struct.Linkage.html) (which hold previous and next key) at the path: -/// ```nocompile -/// Hasher(prefix ++ key) -/// ``` -/// -/// Enumeration is done by getting the head of the linked map and then iterating getting the -/// value and linkage stored at the key until the found linkage has no next key. -/// -/// # Warning -/// -/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as -/// `blake2_256` must be used. Otherwise, other values in storage can be compromised. -pub trait StorageLinkedMap { - /// The type that get/take returns. - type Query; - - /// Hasher used to insert into storage. - type Hasher: StorageHasher; - - /// Prefix used to prepend each key. - fn prefix() -> &'static [u8]; - - /// Key used to store linked map head. - fn head_key() -> &'static [u8]; - - /// Convert an optionnal value retrieved from storage to the type queried. - fn from_optional_value_to_query(v: Option) -> Self::Query; - - /// Convert a query to an optionnal value into storage. - fn from_query_to_optional_value(v: Self::Query) -> Option; - - /// Generate the full key used in top storage. - fn storage_linked_map_final_key(key: KeyArg) -> ::Output - where - KeyArg: EncodeLike, - { - let mut final_key = Self::prefix().to_vec(); - key.encode_to(&mut final_key); - Self::Hasher::hash(&final_key) - } - - /// Generate the hashed key for head - fn storage_linked_map_final_head_key() -> ::Output { - Self::Hasher::hash(Self::head_key()) - } -} - -/// Linkage data of an element (it's successor and predecessor) -#[derive(Encode, Decode)] -pub struct Linkage { - /// Previous element key in storage (None for the first element) - pub previous: Option, - /// Next element key in storage (None for the last element) - pub next: Option, -} - -impl Default for Linkage { - fn default() -> Self { - Self { - previous: None, - next: None, - } - } -} - -// Encode like a linkage. -#[derive(Encode)] -struct EncodeLikeLinkage, NKey: EncodeLike, Key: Encode> { - // Previous element key in storage (None for the first element) - previous: Option, - // Next element key in storage (None for the last element) - next: Option, - // The key of the linkage this type encode to - phantom: core::marker::PhantomData, -} - -/// A key-value pair iterator for enumerable map. -pub struct Enumerator> { - next: Option, - _phantom: PhantomData<(G, V)>, -} - -impl Iterator for Enumerator -where - K: FullCodec, - V: FullCodec, - G: StorageLinkedMap, -{ - type Item = (K, V); - - fn next(&mut self) -> Option { - let next = self.next.take()?; - let (val, linkage): (V, Linkage) = { - let next_full_key = G::storage_linked_map_final_key(&next); - unhashed::get(next_full_key.as_ref()) - .expect("previous/next only contain existing entires; - we enumerate using next; entry exists; qed") - }; - - self.next = linkage.next; - Some((next, val)) - } -} - -/// Update linkage when this element is removed. -/// -/// Takes care of updating previous and next elements points -/// as well as updates head if the element is first or last. -fn remove_linkage(linkage: Linkage) -where - K: FullCodec, - V: FullCodec, - G: StorageLinkedMap, -{ - let next_key = linkage.next.as_ref() - .map(G::storage_linked_map_final_key) - .map(|x| x.as_ref().to_vec()); - let prev_key = linkage.previous.as_ref() - .map(G::storage_linked_map_final_key) - .map(|x| x.as_ref().to_vec()); - - if let Some(prev_key) = prev_key { - // Retrieve previous element and update `next` - let mut res = read_with_linkage::<_, _, G>(prev_key.as_ref()) - .expect("Linkage is updated in case entry is removed; - it always points to existing keys; qed"); - res.1.next = linkage.next; - unhashed::put(prev_key.as_ref(), &res); - } else { - // we were first so let's update the head - write_head::<_, _, _, G>(linkage.next.as_ref()); - } - if let Some(next_key) = next_key { - // Update previous of next element - let mut res = read_with_linkage::<_, _, G>(next_key.as_ref()) - .expect("Linkage is updated in case entry is removed; - it always points to existing keys; qed"); - res.1.previous = linkage.previous; - unhashed::put(next_key.as_ref(), &res); - } -} - -/// Read the contained data and it's linkage. -fn read_with_linkage(key: &[u8]) -> Option<(V, Linkage)> -where - K: FullCodec, - V: FullCodec, - G: StorageLinkedMap, -{ - unhashed::get(key) -} - -/// Generate linkage for newly inserted element. -/// -/// Takes care of updating head and previous head's pointer. -fn new_head_linkage(key: KeyArg) -> Linkage -where - KeyArg: EncodeLike, - K: FullCodec, - V: FullCodec, - G: StorageLinkedMap, -{ - if let Some(head) = read_head::<_, _, G>() { - // update previous head predecessor - { - let head_key = G::storage_linked_map_final_key(&head); - let (data, linkage) = read_with_linkage::<_, _, G>(head_key.as_ref()) - .expect("head is set when first element is inserted - and unset when last element is removed; - if head is Some then it points to existing key; qed"); - let new_linkage = EncodeLikeLinkage::<_, _, K> { - previous: Some(Ref::from(&key)), - next: linkage.next.as_ref(), - phantom: Default::default(), - }; - unhashed::put(head_key.as_ref(), &(data, new_linkage)); - } - // update to current head - write_head::<_, _, _, G>(Some(key)); - // return linkage with pointer to previous head - let mut linkage = Linkage::default(); - linkage.next = Some(head); - linkage - } else { - // we are first - update the head and produce empty linkage - write_head::<_, _, _, G>(Some(key)); - Linkage::default() - } -} - -/// Read current head pointer. -fn read_head() -> Option -where - K: FullCodec, - V: FullCodec, - G: StorageLinkedMap, -{ - unhashed::get(G::storage_linked_map_final_head_key().as_ref()) -} - -/// Overwrite current head pointer. -/// -/// If `None` is given head is removed from storage. -fn write_head(head: Option) -where - KeyArg: EncodeLike, - K: FullCodec, - V: FullCodec, - G: StorageLinkedMap, -{ - match head.as_ref() { - Some(head) => unhashed::put(G::storage_linked_map_final_head_key().as_ref(), head), - None => unhashed::kill(G::storage_linked_map_final_head_key().as_ref()), - } -} - -impl storage::StorageLinkedMap for G -where - K: FullCodec, - V: FullCodec, - G: StorageLinkedMap, -{ - type Query = G::Query; - - type Enumerator = Enumerator; - - fn exists>(key: KeyArg) -> bool { - unhashed::exists(Self::storage_linked_map_final_key(key).as_ref()) - } - - fn get>(key: KeyArg) -> Self::Query { - let val = unhashed::get(Self::storage_linked_map_final_key(key).as_ref()); - G::from_optional_value_to_query(val) - } - - fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2) { - let final_key1 = Self::storage_linked_map_final_key(Ref::from(&key1)); - let final_key2 = Self::storage_linked_map_final_key(Ref::from(&key2)); - let full_value_1 = read_with_linkage::<_, _, G>(final_key1.as_ref()); - let full_value_2 = read_with_linkage::<_, _, G>(final_key2.as_ref()); - - match (full_value_1, full_value_2) { - // Just keep linkage in order and only swap values. - (Some((value1, linkage1)), Some((value2, linkage2))) => { - unhashed::put(final_key1.as_ref(), &(value2, linkage1)); - unhashed::put(final_key2.as_ref(), &(value1, linkage2)); - } - // Remove key and insert the new one. - (Some((value, _linkage)), None) => { - Self::remove(key1); - let linkage = new_head_linkage::<_, _, _, G>(key2); - unhashed::put(final_key2.as_ref(), &(value, linkage)); - } - // Remove key and insert the new one. - (None, Some((value, _linkage))) => { - Self::remove(key2); - let linkage = new_head_linkage::<_, _, _, G>(key1); - unhashed::put(final_key1.as_ref(), &(value, linkage)); - } - // No-op. - (None, None) => (), - } - } - - fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg) { - let final_key = Self::storage_linked_map_final_key(Ref::from(&key)); - let linkage = match read_with_linkage::<_, _, G>(final_key.as_ref()) { - // overwrite but reuse existing linkage - Some((_data, linkage)) => linkage, - // create new linkage - None => new_head_linkage::<_, _, _, G>(key), - }; - unhashed::put(final_key.as_ref(), &(val, linkage)) - } - - fn remove>(key: KeyArg) { - G::take(key); - } - - fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R { - let final_key = Self::storage_linked_map_final_key(Ref::from(&key)); - - let (mut val, _linkage) = read_with_linkage::<_, _, G>(final_key.as_ref()) - .map(|(data, linkage)| (G::from_optional_value_to_query(Some(data)), Some(linkage))) - .unwrap_or_else(|| (G::from_optional_value_to_query(None), None)); - - let ret = f(&mut val); - match G::from_query_to_optional_value(val) { - Some(ref val) => G::insert(key, val), - None => G::remove(key), - } - ret - } - - fn take>(key: KeyArg) -> Self::Query { - let final_key = Self::storage_linked_map_final_key(key); - - let full_value: Option<(V, Linkage)> = unhashed::take(final_key.as_ref()); - - let value = full_value.map(|(data, linkage)| { - remove_linkage::<_, _, G>(linkage); - data - }); - - G::from_optional_value_to_query(value) - } - - fn enumerate() -> Self::Enumerator { - Enumerator::<_, _, G> { - next: read_head::<_, _, G>(), - _phantom: Default::default(), - } - } - - fn head() -> Option { - read_head::<_, _, G>() - } - - fn decode_len>(key: KeyArg) -> Result - where V: codec::DecodeLength + Len - { - let key = Self::storage_linked_map_final_key(key); - if let Some(v) = unhashed::get_raw(key.as_ref()) { - ::len(&v).map_err(|e| e.what()) - } else { - let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) - .map(|v| v.len()) - .unwrap_or(0); - - Ok(len) - } - } -} diff --git a/srml/support/src/storage/generator/mod.rs b/srml/support/src/storage/generator/mod.rs deleted file mode 100644 index ab7616158afd8..0000000000000 --- a/srml/support/src/storage/generator/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Generators are a set of trait on which storage traits are implemented. -//! -//! (i.e. implementing the generator for StorageValue on a type will automatically derive the -//! implementation of StorageValue for this type). -//! -//! They are used by `decl_storage`. - -mod linked_map; -mod map; -mod double_map; -mod value; - -pub use linked_map::{StorageLinkedMap, Enumerator, Linkage}; -pub use map::StorageMap; -pub use double_map::StorageDoubleMap; -pub use value::StorageValue; diff --git a/srml/support/src/storage/mod.rs b/srml/support/src/storage/mod.rs deleted file mode 100644 index 648009b470e42..0000000000000 --- a/srml/support/src/storage/mod.rs +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Stuff to do with the runtime's storage. - -use rstd::prelude::*; -use codec::{FullCodec, FullEncode, Encode, EncodeAppend, EncodeLike}; -use crate::traits::Len; - -#[macro_use] -pub mod storage_items; -pub mod unhashed; -pub mod hashed; -pub mod child; -pub mod generator; - -/// A trait for working with macro-generated storage values under the substrate storage API. -pub trait StorageValue { - /// The type that get/take return. - type Query; - - /// Get the storage key. - fn hashed_key() -> [u8; 16]; - - /// Does the value (explicitly) exist in storage? - fn exists() -> bool; - - /// Load the value from the provided storage instance. - fn get() -> Self::Query; - - /// Store a value under this key into the provided storage instance. - fn put>(val: Arg); - - /// Mutate the value - fn mutate R>(f: F) -> R; - - /// Clear the storage value. - fn kill(); - - /// Take a value from storage, removing it afterwards. - fn take() -> Self::Query; - - /// Append the given item to the value in the storage. - /// - /// `T` is required to implement `codec::EncodeAppend`. - fn append(items: Items) -> Result<(), &'static str> - where - Item: Encode, - EncodeLikeItem: EncodeLike, - T: EncodeAppend, - Items: IntoIterator, - Items::IntoIter: ExactSizeIterator; - - /// Append the given items to the value in the storage. - /// - /// `T` is required to implement `Codec::EncodeAppend`. - /// - /// Upon any failure, it replaces `items` as the new value (assuming that the previous stored - /// data is simply corrupt and no longer usable). - /// - /// ### WARNING - /// - /// use with care; if your use-case is not _exactly_ as what this function is doing, - /// you should use append and sensibly handle failure within the runtime code if it happens. - fn append_or_put(items: Items) where - Item: Encode, - EncodeLikeItem: EncodeLike, - T: EncodeAppend, - Items: IntoIterator + Clone + EncodeLike, - Items::IntoIter: ExactSizeIterator; - - - /// Read the length of the value in a fast way, without decoding the entire value. - /// - /// `T` is required to implement `Codec::DecodeLength`. - fn decode_len() -> Result - where T: codec::DecodeLength + Len; -} - -/// A strongly-typed map in storage. -pub trait StorageMap { - /// The type that get/take return. - type Query; - - /// Get the storage key used to fetch a value corresponding to a specific key. - fn hashed_key_for>(key: KeyArg) -> Vec; - - /// Does the value (explicitly) exist in storage? - fn exists>(key: KeyArg) -> bool; - - /// Load the value associated with the given key from the map. - fn get>(key: KeyArg) -> Self::Query; - - /// Swap the values of two keys. - fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2); - - /// Store a value to be associated with the given key from the map. - fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg); - - /// Remove the value under a key. - fn remove>(key: KeyArg); - - /// Mutate the value under a key. - fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R; - - /// Take the value under a key. - fn take>(key: KeyArg) -> Self::Query; - - /// Append the given items to the value in the storage. - /// - /// `V` is required to implement `codec::EncodeAppend`. - fn append(key: KeyArg, items: Items) -> Result<(), &'static str> - where - KeyArg: EncodeLike, - Item: Encode, - EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator, - Items::IntoIter: ExactSizeIterator; - - /// Safely append the given items to the value in the storage. If a codec error occurs, then the - /// old (presumably corrupt) value is replaced with the given `items`. - /// - /// `V` is required to implement `codec::EncodeAppend`. - fn append_or_insert(key: KeyArg, items: Items) - where - KeyArg: EncodeLike, - Item: Encode, - EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator + Clone + EncodeLike, - Items::IntoIter: ExactSizeIterator; - - /// Read the length of the value in a fast way, without decoding the entire value. - /// - /// `T` is required to implement `Codec::DecodeLength`. - /// - /// Note that `0` is returned as the default value if no encoded value exists at the given key. - /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` - /// function for this purpose. - fn decode_len>(key: KeyArg) -> Result - where V: codec::DecodeLength + Len; -} - -/// A strongly-typed linked map in storage. -/// -/// Similar to `StorageMap` but allows to enumerate other elements and doesn't implement append. -pub trait StorageLinkedMap { - /// The type that get/take return. - type Query; - - /// The type that iterates over all `(key, value)`. - type Enumerator: Iterator; - - /// Does the value (explicitly) exist in storage? - fn exists>(key: KeyArg) -> bool; - - /// Load the value associated with the given key from the map. - fn get>(key: KeyArg) -> Self::Query; - - /// Swap the values of two keys. - fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2); - - /// Store a value to be associated with the given key from the map. - fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg); - - /// Remove the value under a key. - fn remove>(key: KeyArg); - - /// Mutate the value under a key. - fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R; - - /// Take the value under a key. - fn take>(key: KeyArg) -> Self::Query; - - /// Return current head element. - fn head() -> Option; - - /// Enumerate all elements in the map. - fn enumerate() -> Self::Enumerator; - - /// Read the length of the value in a fast way, without decoding the entire value. - /// - /// `T` is required to implement `Codec::DecodeLength`. - /// - /// Note that `0` is returned as the default value if no encoded value exists at the given key. - /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` - /// function for this purpose. - fn decode_len>(key: KeyArg) -> Result - where V: codec::DecodeLength + Len; -} - -/// An implementation of a map with a two keys. -/// -/// It provides an important ability to efficiently remove all entries -/// that have a common first key. -pub trait StorageDoubleMap { - /// The type that get/take returns. - type Query; - - fn exists(k1: KArg1, k2: KArg2) -> bool - where - KArg1: EncodeLike, - KArg2: EncodeLike; - - fn get(k1: KArg1, k2: KArg2) -> Self::Query - where - KArg1: EncodeLike, - KArg2: EncodeLike; - - fn take(k1: KArg1, k2: KArg2) -> Self::Query - where - KArg1: EncodeLike, - KArg2: EncodeLike; - - fn insert(k1: KArg1, k2: KArg2, val: VArg) - where - KArg1: EncodeLike, - KArg2: EncodeLike, - VArg: EncodeLike; - - fn remove(k1: KArg1, k2: KArg2) - where - KArg1: EncodeLike, - KArg2: EncodeLike; - - fn remove_prefix(k1: KArg1) where KArg1: ?Sized + EncodeLike; - - fn mutate(k1: KArg1, k2: KArg2, f: F) -> R - where - KArg1: EncodeLike, - KArg2: EncodeLike, - F: FnOnce(&mut Self::Query) -> R; - - fn append( - k1: KArg1, - k2: KArg2, - items: Items, - ) -> Result<(), &'static str> - where - KArg1: EncodeLike, - KArg2: EncodeLike, - Item: Encode, - EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator, - Items::IntoIter: ExactSizeIterator; - - fn append_or_insert( - k1: KArg1, - k2: KArg2, - items: Items, - ) - where - KArg1: EncodeLike, - KArg2: EncodeLike, - Item: Encode, - EncodeLikeItem: EncodeLike, - V: EncodeAppend, - Items: IntoIterator + Clone + EncodeLike, - Items::IntoIter: ExactSizeIterator; -} diff --git a/srml/support/src/storage/storage_items.rs b/srml/support/src/storage/storage_items.rs deleted file mode 100644 index 1edf9c03db61a..0000000000000 --- a/srml/support/src/storage/storage_items.rs +++ /dev/null @@ -1,905 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Strongly typed wrappers around values in storage. -//! -//! This crate exports a macro `storage_items!` and traits describing behavior of generated -//! structs. -//! -//! Two kinds of data types are currently supported: -//! - values -//! - maps -//! -//! # Examples: -//! -//! ```rust -//! #[macro_use] -//! extern crate srml_support; -//! -//! type AuthorityId = [u8; 32]; -//! type Balance = u64; -//! pub type SessionKey = [u8; 32]; -//! -//! storage_items! { -//! // public value -//! pub Value: b"putd_key" => SessionKey; -//! // private map. -//! Balances: b"private_map:" => map [AuthorityId => Balance]; -//! } -//! -//!# fn main() { } -//! ``` - -#[doc(hidden)] -pub use crate::rstd::borrow::Borrow; -#[doc(hidden)] -pub use crate::rstd::marker::PhantomData; -#[doc(hidden)] -pub use crate::rstd::boxed::Box; - -#[doc(hidden)] -pub fn id(t: T) -> T { - t -} - -#[doc(hidden)] -pub use Some; - -#[doc(hidden)] -pub fn unwrap_or_default(t: Option) -> T { - t.unwrap_or_else(|| Default::default()) -} - -#[doc(hidden)] -pub fn require(t: Option) -> T { - t.expect("Required values must be in storage") -} - -// FIXME #1466 Remove this in favor of `decl_storage` macro. -/// Declares strongly-typed wrappers around codec-compatible types in storage. -#[macro_export] -macro_rules! storage_items { - // simple values - ($name:ident : $key:expr => $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (OPTION_TYPE Option<$ty>) (id) (id) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (OPTION_TYPE Option<$ty>) (id) (id) $name: $key => $ty); - storage_items!($($t)*); - }; - ($name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (unwrap_or_default) (Some) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (unwrap_or_default) (Some) $name: $key => $ty); - storage_items!($($t)*); - }; - ($name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (require) (Some) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (require) (Some) $name: $key => $ty); - storage_items!($($t)*); - }; - - ($name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (OPTION_TYPE Option<$ty>) (id) (id) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (OPTION_TYPE Option<$ty>) (id) (id) $name: $key => $ty); - storage_items!($($t)*); - }; - ($name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (unwrap_or_default) (Some) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (unwrap_or_default) (Some) $name: $key => $ty); - storage_items!($($t)*); - }; - ($name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (require) (Some) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (require) (Some) $name: $key => $ty); - storage_items!($($t)*); - }; - - // maps - ($name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (OPTION_TYPE Option<$ty>) (id) (id) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (OPTION_TYPE Option<$ty>) (id) (id) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - ($name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (unwrap_or_default) (Some) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (unwrap_or_default) (Some) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - ($name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (require) (Some) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (require) (Some) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - - ($name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (OPTION_TYPE Option<$ty>) (id) (id) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (OPTION_TYPE Option<$ty>) (id) (id) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - ($name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (unwrap_or_default) (Some) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (unwrap_or_default) (Some) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - ($name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (require) (Some) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (require) (Some) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - - () => () -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __storage_items_internal { - // generator for values. - (($($vis:tt)*) ($get_fn:ident) ($wraptype:ident $gettype:ty) ($into_query:ident) ($into_opt_val:ident) $name:ident : $key:expr => $ty:ty) => { - $crate::__storage_items_internal!{ ($($vis)*) () ($wraptype $gettype) ($into_query) ($into_opt_val) $name : $key => $ty } - pub fn $get_fn() -> $gettype { <$name as $crate::storage::StorageValue<$ty>> :: get() } - }; - (($($vis:tt)*) () ($wraptype:ident $gettype:ty) ($into_query:ident) ($into_opt_val:ident) $name:ident : $key:expr => $ty:ty) => { - $($vis)* struct $name; - - impl $crate::storage::generator::StorageValue<$ty> for $name { - type Query = $gettype; - - fn unhashed_key() -> &'static [u8] { - $key - } - - fn from_optional_value_to_query(v: Option<$ty>) -> Self::Query { - $crate::storage::storage_items::$into_query(v) - } - - fn from_query_to_optional_value(v: Self::Query) -> Option<$ty> { - $crate::storage::storage_items::$into_opt_val(v) - } - } - }; - // generator for maps. - (($($vis:tt)*) ($get_fn:ident) ($wraptype:ident $gettype:ty) ($into_query:ident) ($into_opt_val:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => { - $crate::__storage_items_internal!{ ($($vis)*) () ($wraptype $gettype) ($into_query) ($into_opt_val) $name : $prefix => map [$kty => $ty] } - pub fn $get_fn>(key: K) -> $gettype { - <$name as $crate::storage::StorageMap<$kty, $ty>> :: get(key.borrow()) - } - }; - (($($vis:tt)*) () ($wraptype:ident $gettype:ty) ($into_query:ident) ($into_opt_val:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => { - $($vis)* struct $name; - - impl $crate::storage::generator::StorageMap<$kty, $ty> for $name { - type Query = $gettype; - type Hasher = $crate::Blake2_256; - - fn prefix() -> &'static [u8] { - $prefix - } - - fn from_optional_value_to_query(v: Option<$ty>) -> Self::Query { - $crate::storage::storage_items::$into_query(v) - } - - fn from_query_to_optional_value(v: Self::Query) -> Option<$ty> { - $crate::storage::storage_items::$into_opt_val(v) - } - } - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __handle_wrap_internal { - (RAW_TYPE { $($raw:tt)* } { $($option:tt)* }) => { - $($raw)*; - }; - (OPTION_TYPE { $($raw:tt)* } { $($option:tt)* }) => { - $($option)*; - }; -} - -// FIXME: revisit this idiom once we get `type`s in `impl`s. -/*impl Module { - type Now = super::Now; -}*/ - -#[cfg(test)] -// Do not complain about unused `dispatch` and `dispatch_aux`. -#[allow(dead_code)] -mod tests { - use crate::metadata::*; - use crate::metadata::StorageHasher; - use crate::rstd::marker::PhantomData; - use crate::codec::{Encode, Decode, EncodeLike}; - - storage_items! { - Value: b"a" => u32; - Map: b"c:" => map [u32 => [u8; 32]]; - } - - #[test] - fn value() { - runtime_io::with_storage(&mut Default::default(), || { - assert!(Value::get().is_none()); - Value::put(&100_000); - assert_eq!(Value::get(), Some(100_000)); - Value::kill(); - assert!(Value::get().is_none()); - }) - } - - #[test] - fn map() { - runtime_io::with_storage(&mut Default::default(), || { - assert!(Map::get(&5).is_none()); - Map::insert(&5, &[1; 32]); - assert_eq!(Map::get(&5), Some([1; 32])); - assert_eq!(Map::take(&5), Some([1; 32])); - assert!(Map::get(&5).is_none()); - assert!(Map::get(&999).is_none()); - }) - } - - pub trait Trait { - type Origin: Encode + Decode + EncodeLike + std::default::Default; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - crate::decl_storage! { - trait Store for Module as TestStorage { - // non-getters: pub / $default - - /// Hello, this is doc! - U32 : Option; - pub PUBU32 : Option; - U32MYDEF : Option; - pub PUBU32MYDEF : Option; - - // getters: pub / $default - // we need at least one type which uses T, otherwise GenesisConfig will complain. - GETU32 get(fn u32_getter): T::Origin; - pub PUBGETU32 get(fn pub_u32_getter) build(|config: &GenesisConfig| config.u32_getter_with_config): u32; - GETU32WITHCONFIG get(fn u32_getter_with_config) config(): u32; - pub PUBGETU32WITHCONFIG get(fn pub_u32_getter_with_config) config(): u32; - GETU32MYDEF get(fn u32_getter_mydef): Option; - pub PUBGETU32MYDEF get(fn pub_u32_getter_mydef) config(): u32 = 3; - GETU32WITHCONFIGMYDEF get(fn u32_getter_with_config_mydef) config(): u32 = 2; - pub PUBGETU32WITHCONFIGMYDEF get(fn pub_u32_getter_with_config_mydef) config(): u32 = 1; - PUBGETU32WITHCONFIGMYDEFOPT get(fn pub_u32_getter_with_config_mydef_opt) config(): Option; - - // map non-getters: pub / $default - MAPU32 : map u32 => Option; - pub PUBMAPU32 : map u32 => Option; - MAPU32MYDEF : map u32 => Option; - pub PUBMAPU32MYDEF : map u32 => Option; - - // map getters: pub / $default - GETMAPU32 get(fn map_u32_getter): map u32 => String; - pub PUBGETMAPU32 get(fn pub_map_u32_getter): map u32 => String; - - GETMAPU32MYDEF get(fn map_u32_getter_mydef): map u32 => String = "map".into(); - pub PUBGETMAPU32MYDEF get(fn pub_map_u32_getter_mydef): map u32 => String = "pubmap".into(); - - // linked map - LINKEDMAPU32 : linked_map u32 => Option; - pub PUBLINKEDMAPU32MYDEF : linked_map u32 => Option; - GETLINKEDMAPU32 get(fn linked_map_u32_getter): linked_map u32 => String; - pub PUBGETLINKEDMAPU32MYDEF get(fn pub_linked_map_u32_getter_mydef): linked_map u32 => String = "pubmap".into(); - - COMPLEXTYPE1: ::std::vec::Vec<::Origin>; - COMPLEXTYPE2: (Vec)>>, u32); - COMPLEXTYPE3: ([u32;25]); - } - add_extra_genesis { - build(|_| {}); - } - } - - struct TraitImpl {} - - impl Trait for TraitImpl { - type Origin = u32; - type BlockNumber = u32; - } - - const EXPECTED_METADATA: StorageMetadata = StorageMetadata { - prefix: DecodeDifferent::Encode("TestStorage"), - entries: DecodeDifferent::Encode( - &[ - StorageEntryMetadata { - name: DecodeDifferent::Encode("U32"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[ " Hello, this is doc!" ]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBU32"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("U32MYDEF"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBU32MYDEF"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GETU32"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("T::Origin")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETU32"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GETU32WITHCONFIG"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETU32WITHCONFIG(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETU32WITHCONFIG"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIG(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GETU32MYDEF"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETU32MYDEF"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GETU32WITHCONFIGMYDEF"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETU32WITHCONFIGMYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEF"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIGMYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEFOPT"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIGMYDEFOPT(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - - StorageEntryMetadata { - name: DecodeDifferent::Encode("MAPU32"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: false, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructMAPU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBMAPU32"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: false, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBMAPU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("MAPU32MYDEF"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: false, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructMAPU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBMAPU32MYDEF"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: false, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBMAPU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GETMAPU32"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: false, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETMAPU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETMAPU32"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: false, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETMAPU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GETMAPU32MYDEF"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: false, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETMAPU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETMAPU32MYDEF"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: false, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETMAPU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("LINKEDMAPU32"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: true, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructLINKEDMAPU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBLINKEDMAPU32MYDEF"), - modifier: StorageEntryModifier::Optional, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: true, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBLINKEDMAPU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("GETLINKEDMAPU32"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: true, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructGETLINKEDMAPU32(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("PUBGETLINKEDMAPU32MYDEF"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Map { - hasher: StorageHasher::Blake2_256, - key: DecodeDifferent::Encode("u32"), - value: DecodeDifferent::Encode("String"), - is_linked: true, - }, - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructPUBGETLINKEDMAPU32MYDEF(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("COMPLEXTYPE1"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("::std::vec::Vec<::Origin>")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructCOMPLEXTYPE1(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("COMPLEXTYPE2"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("(Vec)>>, u32)")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructCOMPLEXTYPE2(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - StorageEntryMetadata { - name: DecodeDifferent::Encode("COMPLEXTYPE3"), - modifier: StorageEntryModifier::Default, - ty: StorageEntryType::Plain(DecodeDifferent::Encode("([u32; 25])")), - default: DecodeDifferent::Encode( - DefaultByteGetter(&__GetByteStructCOMPLEXTYPE3(PhantomData::)) - ), - documentation: DecodeDifferent::Encode(&[]), - }, - ] - ), - }; - - #[test] - fn store_metadata() { - let metadata = Module::::storage_metadata(); - assert_eq!(EXPECTED_METADATA, metadata); - } - - #[test] - fn check_genesis_config() { - let config = GenesisConfig::default(); - assert_eq!(config.u32_getter_with_config, 0u32); - assert_eq!(config.pub_u32_getter_with_config, 0u32); - - assert_eq!(config.pub_u32_getter_mydef, 3u32); - assert_eq!(config.u32_getter_with_config_mydef, 2u32); - assert_eq!(config.pub_u32_getter_with_config_mydef, 1u32); - assert_eq!(config.pub_u32_getter_with_config_mydef_opt, 0u32); - } - -} - -#[cfg(test)] -#[allow(dead_code)] -mod test2 { - pub trait Trait { - type Origin; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - type PairOf = (T, T); - - crate::decl_storage! { - trait Store for Module as TestStorage { - SingleDef : u32; - PairDef : PairOf; - Single : Option; - Pair : (u32, u32); - } - add_extra_genesis { - config(_marker) : ::std::marker::PhantomData; - config(extra_field) : u32 = 32; - build(|_| {}); - } - } - - struct TraitImpl {} - - impl Trait for TraitImpl { - type Origin = u32; - 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(fn foo) config(initial_foo): u32; - } - } - - type PairOf = (T, T); - - struct TraitImpl {} - - impl Trait for TraitImpl { - type Origin = u32; - type BlockNumber = u32; - } -} - -#[cfg(test)] -#[allow(dead_code)] -mod test_append_and_len { - use runtime_io::TestExternalities; - use codec::{Encode, Decode}; - - pub trait Trait { - type Origin; - type BlockNumber; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - #[derive(PartialEq, Eq, Clone, Encode, Decode)] - struct NoDef(u32); - - crate::decl_storage! { - trait Store for Module as Test { - NoDefault: Option; - - JustVec: Vec; - JustVecWithDefault: Vec = vec![6, 9]; - OptionVec: Option>; - - MapVec: map u32 => Vec; - MapVecWithDefault: map u32 => Vec = vec![6, 9]; - OptionMapVec: map u32 => Option>; - - LinkedMapVec: linked_map u32 => Vec; - LinkedMapVecWithDefault: linked_map u32 => Vec = vec![6, 9]; - OptionLinkedMapVec: linked_map u32 => Option>; - } - } - - struct Test {} - - impl Trait for Test { - type Origin = u32; - type BlockNumber = u32; - } - - #[test] - fn default_for_option() { - TestExternalities::default().execute_with(|| { - assert_eq!(OptionVec::get(), None); - assert_eq!(JustVec::get(), vec![]); - }); - } - - #[test] - fn append_works() { - TestExternalities::default().execute_with(|| { - let _ = MapVec::append(1, [1, 2, 3].iter()); - let _ = MapVec::append(1, [4, 5].iter()); - assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); - - let _ = JustVec::append([1, 2, 3].iter()); - let _ = JustVec::append([4, 5].iter()); - assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); - }); - } - - #[test] - fn append_works_for_default() { - TestExternalities::default().execute_with(|| { - assert_eq!(JustVecWithDefault::get(), vec![6, 9]); - let _ = JustVecWithDefault::append([1].iter()); - assert_eq!(JustVecWithDefault::get(), vec![6, 9, 1]); - - assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); - let _ = MapVecWithDefault::append(0, [1].iter()); - assert_eq!(MapVecWithDefault::get(0), vec![6, 9, 1]); - - assert_eq!(OptionVec::get(), None); - let _ = OptionVec::append([1].iter()); - assert_eq!(OptionVec::get(), Some(vec![1])); - }); - } - - #[test] - fn append_or_put_works() { - TestExternalities::default().execute_with(|| { - let _ = MapVec::append_or_insert(1, &[1, 2, 3][..]); - let _ = MapVec::append_or_insert(1, &[4, 5][..]); - assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); - - let _ = JustVec::append_or_put(&[1, 2, 3][..]); - let _ = JustVec::append_or_put(&[4, 5][..]); - assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); - - let _ = OptionVec::append_or_put(&[1, 2, 3][..]); - let _ = OptionVec::append_or_put(&[4, 5][..]); - assert_eq!(OptionVec::get(), Some(vec![1, 2, 3, 4, 5])); - }); - } - - #[test] - fn len_works() { - TestExternalities::default().execute_with(|| { - JustVec::put(&vec![1, 2, 3, 4]); - OptionVec::put(&vec![1, 2, 3, 4, 5]); - MapVec::insert(1, &vec![1, 2, 3, 4, 5, 6]); - LinkedMapVec::insert(2, &vec![1, 2, 3]); - - assert_eq!(JustVec::decode_len().unwrap(), 4); - assert_eq!(OptionVec::decode_len().unwrap(), 5); - assert_eq!(MapVec::decode_len(1).unwrap(), 6); - assert_eq!(LinkedMapVec::decode_len(2).unwrap(), 3); - }); - } - - #[test] - fn len_works_for_default() { - TestExternalities::default().execute_with(|| { - // vec - assert_eq!(JustVec::get(), vec![]); - assert_eq!(JustVec::decode_len(), Ok(0)); - - assert_eq!(JustVecWithDefault::get(), vec![6, 9]); - assert_eq!(JustVecWithDefault::decode_len(), Ok(2)); - - assert_eq!(OptionVec::get(), None); - assert_eq!(OptionVec::decode_len(), Ok(0)); - - // map - assert_eq!(MapVec::get(0), vec![]); - assert_eq!(MapVec::decode_len(0), Ok(0)); - - assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); - assert_eq!(MapVecWithDefault::decode_len(0), Ok(2)); - - assert_eq!(OptionMapVec::get(0), None); - assert_eq!(OptionMapVec::decode_len(0), Ok(0)); - - // linked map - assert_eq!(LinkedMapVec::get(0), vec![]); - assert_eq!(LinkedMapVec::decode_len(0), Ok(0)); - - assert_eq!(LinkedMapVecWithDefault::get(0), vec![6, 9]); - assert_eq!(LinkedMapVecWithDefault::decode_len(0), Ok(2)); - - assert_eq!(OptionLinkedMapVec::get(0), None); - assert_eq!(OptionLinkedMapVec::decode_len(0), Ok(0)); - }); - } -} diff --git a/srml/support/src/traits.rs b/srml/support/src/traits.rs deleted file mode 100644 index c58d60ffc9cf9..0000000000000 --- a/srml/support/src/traits.rs +++ /dev/null @@ -1,742 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Traits for SRML. -//! -//! NOTE: If you're looking for `parameter_types`, it has moved in to the top-level module. - -use rstd::{prelude::*, result, marker::PhantomData, ops::Div, fmt::Debug}; -use codec::{FullCodec, Codec, Encode, Decode}; -use primitives::u32_trait::Value as U32; -use sr_primitives::{ - ConsensusEngineId, - traits::{MaybeSerializeDeserialize, SimpleArithmetic, Saturating}, -}; - -/// Anything that can have a `::len()` method. -pub trait Len { - /// Return the length of data type. - fn len(&self) -> usize; -} - -impl Len for T where ::IntoIter: ExactSizeIterator { - fn len(&self) -> usize { - self.clone().into_iter().len() - } -} - -/// A trait for querying a single fixed value from a type. -pub trait Get { - /// Return a constant value. - fn get() -> T; -} - -impl Get for () { - fn get() -> T { T::default() } -} - -/// A trait for querying whether a type can be said to statically "contain" a value. Similar -/// in nature to `Get`, except it is designed to be lazy rather than active (you can't ask it to -/// enumerate all values that it contains) and work for multiple values rather than just one. -pub trait Contains { - /// Return `true` if this "contains" the given value `t`. - fn contains(t: &T) -> bool; -} - -impl> Contains for T { - fn contains(t: &V) -> bool { - &Self::get() == t - } -} - -/// The account with the given id was killed. -#[impl_trait_for_tuples::impl_for_tuples(30)] -pub trait OnFreeBalanceZero { - /// The account was the given id was killed. - fn on_free_balance_zero(who: &AccountId); -} - -/// 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 led to killing the account. - AccountKilled, -} - -/// A trait for finding the author of a block header based on the `PreRuntime` digests contained -/// within it. -pub trait FindAuthor { - /// Find the author of a block based on the pre-runtime digests. - fn find_author<'a, I>(digests: I) -> Option - where I: 'a + IntoIterator; -} - -impl FindAuthor for () { - fn find_author<'a, I>(_: I) -> Option - where I: 'a + IntoIterator - { - None - } -} - -/// A trait for verifying the seal of a header and returning the author. -pub trait VerifySeal { - /// Verify a header and return the author, if any. - fn verify_seal(header: &Header) -> Result, &'static str>; -} - -/// Something which can compute and check proofs of -/// a historical key owner and return full identification data of that -/// key owner. -pub trait KeyOwnerProofSystem { - /// The proof of membership itself. - type Proof: Codec; - /// The full identification of a key owner and the stash account. - type IdentificationTuple: Codec; - - /// Prove membership of a key owner in the current block-state. - /// - /// This should typically only be called off-chain, since it may be - /// computationally heavy. - /// - /// Returns `Some` iff the key owner referred to by the given `key` is a - /// member of the current set. - fn prove(key: Key) -> Option; - - /// Check a proof of membership on-chain. Return `Some` iff the proof is - /// valid and recent enough to check. - fn check_proof(key: Key, proof: Self::Proof) -> Option; -} - -/// Handler for when some currency "account" decreased in balance for -/// some reason. -/// -/// The only reason at present for an increase would be for validator rewards, but -/// there may be other reasons in the future or for other chains. -/// -/// Reasons for decreases include: -/// -/// - Someone got slashed. -/// - Someone paid for a transaction to be included. -pub trait OnUnbalanced { - /// Handler for some imbalance. Infallible. - fn on_unbalanced(amount: Imbalance); -} - -impl OnUnbalanced for () { - fn on_unbalanced(amount: Imbalance) { drop(amount); } -} - -/// Simple boolean for whether an account needs to be kept in existence. -#[derive(Copy, Clone, Eq, PartialEq)] -pub enum ExistenceRequirement { - /// Operation must not result in the account going out of existence. - /// - /// Note this implies that if the account never existed in the first place, then the operation - /// may legitimately leave the account unchanged and still non-existent. - KeepAlive, - /// Operation may result in account going out of existence. - AllowDeath, -} - -/// A trait for a not-quite Linear Type that tracks an imbalance. -/// -/// Functions that alter account balances return an object of this trait to -/// express how much account balances have been altered in aggregate. If -/// dropped, the currency system will take some default steps to deal with -/// the imbalance (`balances` module simply reduces or increases its -/// total issuance). Your module should generally handle it in some way, -/// good practice is to do so in a configurable manner using an -/// `OnUnbalanced` type for each situation in which your module needs to -/// handle an imbalance. -/// -/// Imbalances can either be Positive (funds were added somewhere without -/// being subtracted elsewhere - e.g. a reward) or Negative (funds deducted -/// somewhere without an equal and opposite addition - e.g. a slash or -/// system fee payment). -/// -/// Since they are unsigned, the actual type is always Positive or Negative. -/// The trait makes no distinction except to define the `Opposite` type. -/// -/// New instances of zero value can be created (`zero`) and destroyed -/// (`drop_zero`). -/// -/// Existing instances can be `split` and merged either consuming `self` with -/// `merge` or mutating `self` with `subsume`. If the target is an `Option`, -/// then `maybe_merge` and `maybe_subsume` might work better. Instances can -/// also be `offset` with an `Opposite` that is less than or equal to in value. -/// -/// You can always retrieve the raw balance value using `peek`. -#[must_use] -pub trait Imbalance: Sized { - /// The oppositely imbalanced type. They come in pairs. - type Opposite: Imbalance; - - /// The zero imbalance. Can be destroyed with `drop_zero`. - fn zero() -> Self; - - /// Drop an instance cleanly. Only works if its `value()` is zero. - fn drop_zero(self) -> Result<(), Self>; - - /// Consume `self` and return two independent instances; the first - /// is guaranteed to be at most `amount` and the second will be the remainder. - fn split(self, amount: Balance) -> (Self, Self); - - /// Consume `self` and an `other` to return a new instance that combines - /// both. - fn merge(self, other: Self) -> Self; - - /// Consume `self` and maybe an `other` to return a new instance that combines - /// both. - fn maybe_merge(self, other: Option) -> Self { - if let Some(o) = other { - self.merge(o) - } else { - self - } - } - - /// Consume an `other` to mutate `self` into a new instance that combines - /// both. - fn subsume(&mut self, other: Self); - - /// Maybe consume an `other` to mutate `self` into a new instance that combines - /// both. - fn maybe_subsume(&mut self, other: Option) { - if let Some(o) = other { - self.subsume(o) - } - } - - /// Consume self and along with an opposite counterpart to return - /// a combined result. - /// - /// Returns `Ok` along with a new instance of `Self` if this instance has a - /// greater value than the `other`. Otherwise returns `Err` with an instance of - /// the `Opposite`. In both cases the value represents the combination of `self` - /// and `other`. - fn offset(self, other: Self::Opposite) -> Result; - - /// The raw value of self. - fn peek(&self) -> Balance; -} - -/// Either a positive or a negative imbalance. -pub enum SignedImbalance>{ - /// A positive imbalance (funds have been created but none destroyed). - Positive(P), - /// A negative imbalance (funds have been destroyed but none created). - Negative(P::Opposite), -} - -impl< - P: Imbalance, - N: Imbalance, - B: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default, -> SignedImbalance { - pub fn zero() -> Self { - SignedImbalance::Positive(P::zero()) - } - - pub fn drop_zero(self) -> Result<(), Self> { - match self { - SignedImbalance::Positive(x) => x.drop_zero().map_err(SignedImbalance::Positive), - SignedImbalance::Negative(x) => x.drop_zero().map_err(SignedImbalance::Negative), - } - } - - /// Consume `self` and an `other` to return a new instance that combines - /// both. - pub fn merge(self, other: Self) -> Self { - match (self, other) { - (SignedImbalance::Positive(one), SignedImbalance::Positive(other)) => - SignedImbalance::Positive(one.merge(other)), - (SignedImbalance::Negative(one), SignedImbalance::Negative(other)) => - SignedImbalance::Negative(one.merge(other)), - (SignedImbalance::Positive(one), SignedImbalance::Negative(other)) => - if one.peek() > other.peek() { - SignedImbalance::Positive(one.offset(other).ok().unwrap_or_else(P::zero)) - } else { - SignedImbalance::Negative(other.offset(one).ok().unwrap_or_else(N::zero)) - }, - (one, other) => other.merge(one), - } - } -} - -/// Split an unbalanced amount two ways between a common divisor. -pub struct SplitTwoWays< - Balance, - Imbalance, - Part1, - Target1, - Part2, - Target2, ->(PhantomData<(Balance, Imbalance, Part1, Target1, Part2, Target2)>); - -impl< - Balance: From + Saturating + Div, - I: Imbalance, - Part1: U32, - Target1: OnUnbalanced, - Part2: U32, - Target2: OnUnbalanced, -> OnUnbalanced for SplitTwoWays -{ - fn on_unbalanced(amount: I) { - let total: u32 = Part1::VALUE + Part2::VALUE; - let amount1 = amount.peek().saturating_mul(Part1::VALUE.into()) / total.into(); - let (imb1, imb2) = amount.split(amount1); - Target1::on_unbalanced(imb1); - Target2::on_unbalanced(imb2); - } -} - -/// Abstraction over a fungible assets system. -pub trait Currency { - /// The balance of an account. - type Balance: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default; - - /// The opaque token type for an imbalance. This is returned by unbalanced operations - /// and must be dealt with. It may be dropped but cannot be cloned. - type PositiveImbalance: Imbalance; - - /// The opaque token type for an imbalance. This is returned by unbalanced operations - /// and must be dealt with. It may be dropped but cannot be cloned. - type NegativeImbalance: Imbalance; - - // PUBLIC IMMUTABLES - - /// The combined balance of `who`. - fn total_balance(who: &AccountId) -> Self::Balance; - - /// Same 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; - - /// The total amount of issuance in the system. - fn total_issuance() -> Self::Balance; - - /// The minimum balance any single account may have. This is equivalent to the `Balances` module's - /// `ExistentialDeposit`. - fn minimum_balance() -> Self::Balance; - - /// Reduce the total issuance by `amount` and return the according imbalance. The imbalance will - /// typically be used to reduce an account by the same amount with e.g. `settle`. - /// - /// This is infallible, but doesn't guarantee that the entire `amount` is burnt, for example - /// in the case of underflow. - fn burn(amount: Self::Balance) -> Self::PositiveImbalance; - - /// Increase the total issuance by `amount` and return the according imbalance. The imbalance - /// will typically be used to increase an account by the same amount with e.g. - /// `resolve_into_existing` or `resolve_creating`. - /// - /// This is infallible, but doesn't guarantee that the entire `amount` is issued, for example - /// in the case of overflow. - fn issue(amount: Self::Balance) -> Self::NegativeImbalance; - - /// The 'free' balance of a given account. - /// - /// This is the only balance that matters in terms of most operations on tokens. It alone - /// is 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`. Further, the `OnFreeBalanceZero` callback - /// is invoked, giving a chance to external modules to clean up 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; - - /// Returns `Ok` iff the account is able to make a withdrawal of the given amount - /// for the given reason. Basically, it's just a dry-run of `withdraw`. - /// - /// `Err(...)` with the reason why not otherwise. - fn ensure_can_withdraw( - who: &AccountId, - _amount: Self::Balance, - reason: WithdrawReason, - new_balance: Self::Balance, - ) -> result::Result<(), &'static str>; - - // PUBLIC MUTABLES (DANGEROUS) - - /// Transfer some liquid free balance to another staker. - /// - /// This is a very high-level function. It will ensure all appropriate fees are paid - /// and no imbalance in the system remains. - fn transfer( - source: &AccountId, - dest: &AccountId, - value: Self::Balance, - ) -> result::Result<(), &'static str>; - - /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the - /// free balance. This function cannot fail. - /// - /// The resulting imbalance is the first item of the tuple returned. - /// - /// As much funds up to `value` will be deducted as possible. If this is less than `value`, - /// then a non-zero second item will be returned. - fn slash( - who: &AccountId, - value: Self::Balance - ) -> (Self::NegativeImbalance, Self::Balance); - - /// Mints `value` to the free balance of `who`. - /// - /// If `who` doesn't exist, nothing is done and an Err returned. - fn deposit_into_existing( - who: &AccountId, - value: Self::Balance - ) -> result::Result; - - /// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on - /// success. - fn resolve_into_existing( - who: &AccountId, - value: Self::NegativeImbalance, - ) -> result::Result<(), Self::NegativeImbalance> { - let v = value.peek(); - match Self::deposit_into_existing(who, v) { - Ok(opposite) => Ok(drop(value.offset(opposite))), - _ => Err(value), - } - } - - /// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created. - /// - /// Infallible. - fn deposit_creating( - who: &AccountId, - value: Self::Balance, - ) -> Self::PositiveImbalance; - - /// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on - /// success. - fn resolve_creating( - who: &AccountId, - value: Self::NegativeImbalance, - ) { - let v = value.peek(); - drop(value.offset(Self::deposit_creating(who, v))); - } - - /// Removes some free balance from `who` account for `reason` if possible. If `liveness` is - /// `KeepAlive`, then no less than `ExistentialDeposit` must be left remaining. - /// - /// This checks any locks, vesting, and liquidity requirements. If the removal is not possible, - /// then it returns `Err`. - /// - /// If the operation is successful, this will return `Ok` with a `NegativeImbalance` whose value - /// is `value`. - fn withdraw( - who: &AccountId, - value: Self::Balance, - reason: WithdrawReason, - liveness: ExistenceRequirement, - ) -> result::Result; - - /// Similar to withdraw, only accepts a `PositiveImbalance` and returns nothing on success. - fn settle( - who: &AccountId, - value: Self::PositiveImbalance, - reason: WithdrawReason, - liveness: ExistenceRequirement, - ) -> result::Result<(), Self::PositiveImbalance> { - let v = value.peek(); - match Self::withdraw(who, v, reason, liveness) { - Ok(opposite) => Ok(drop(value.offset(opposite))), - _ => Err(value), - } - } - - /// Ensure an account's free balance equals some value; this will create the account - /// if needed. - /// - /// Returns a signed imbalance and status to indicate if the account was successfully updated or update - /// has led to killing of the account. - fn make_free_balance_be( - who: &AccountId, - balance: Self::Balance, - ) -> ( - SignedImbalance, - UpdateBalanceOutcome, - ); -} - -/// A currency where funds can be reserved from the user. -pub trait ReservableCurrency: Currency { - /// 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; - - /// 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 the reserve balance of `who` - /// is less than `value`, then a non-zero second item will be returned. - fn slash_reserved( - who: &AccountId, - value: Self::Balance - ) -> (Self::NegativeImbalance, 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. - /// - /// 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; - - - /// 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 behavior than `unreserve`. - fn reserve(who: &AccountId, value: Self::Balance) -> result::Result<(), &'static str>; - - /// Moves up to `value` from reserved balance to free balance. This function cannot fail. - /// - /// As much funds up to `value` will be moved as possible. If the reserve balance of `who` - /// is less than `value`, then the remaining amount will be returned. - /// - /// # NOTES - /// - /// - This is different from `reserve`. - /// - If the remaining reserved balance is less than `ExistentialDeposit`, it will - /// invoke `on_reserved_too_low` and could reap the account. - fn unreserve(who: &AccountId, value: Self::Balance) -> Self::Balance; - - /// 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 deducted as possible. If this is less than `value`, - /// then `Ok(non_zero)` will be returned. - fn repatriate_reserved( - slashed: &AccountId, - beneficiary: &AccountId, - value: Self::Balance - ) -> result::Result; -} - -/// 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; - - /// Create a new balance lock on account `who`. - /// - /// If the new lock is valid (i.e. not already expired), it will push the struct to - /// the `Locks` vec in storage. Note that you can lock more funds than a user has. - /// - /// If the lock `id` already exists, this will update it. - fn set_lock( - id: LockIdentifier, - who: &AccountId, - amount: Self::Balance, - until: Self::Moment, - reasons: WithdrawReasons, - ); - - /// Changes a balance lock (selected by `id`) so that it becomes less liquid in all - /// parameters or creates a new one if it does not exist. - /// - /// Calling `extend_lock` on an existing lock `id` differs from `set_lock` in that it - /// applies the most severe constraints of the two, while `set_lock` replaces the lock - /// with the new parameters. As in, `extend_lock` will set: - /// - maximum `amount` - /// - farthest duration (`until`) - /// - bitwise mask of all `reasons` - 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, - ); -} - -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, - /// In order to pay some other (higher-level) fees. - Fee = 0b00001000, - } -} - -pub trait Time { - type Moment: SimpleArithmetic + FullCodec + Clone + Default + Copy; - - fn now() -> Self::Moment; -} - -impl WithdrawReasons { - /// Choose all variants except for `one`. - /// - /// ```rust - /// # use srml_support::traits::{WithdrawReason, WithdrawReasons}; - /// # fn main() { - /// assert_eq!( - /// WithdrawReason::Fee | WithdrawReason::Transfer | WithdrawReason::Reserve, - /// WithdrawReasons::except(WithdrawReason::TransactionPayment), - /// ); - /// # } - /// ``` - pub fn except(one: WithdrawReason) -> WithdrawReasons { - let mut mask = Self::all(); - mask.toggle(one); - mask - } -} - -/// Trait for type that can handle incremental changes to a set of account IDs. -pub trait ChangeMembers { - /// A number of members `incoming` just joined the set and replaced some `outgoing` ones. The - /// new set is given by `new`, and need not be sorted. - fn change_members(incoming: &[AccountId], outgoing: &[AccountId], mut new: Vec) { - new.sort_unstable(); - Self::change_members_sorted(incoming, outgoing, &new[..]); - } - - /// A number of members `_incoming` just joined the set and replaced some `_outgoing` ones. The - /// new set is thus given by `sorted_new` and **must be sorted**. - /// - /// NOTE: This is the only function that needs to be implemented in `ChangeMembers`. - fn change_members_sorted( - incoming: &[AccountId], - outgoing: &[AccountId], - sorted_new: &[AccountId], - ); - - /// Set the new members; they **must already be sorted**. This will compute the diff and use it to - /// call `change_members_sorted`. - fn set_members_sorted(new_members: &[AccountId], old_members: &[AccountId]) { - let (incoming, outgoing) = Self::compute_members_diff(new_members, old_members); - Self::change_members_sorted(&incoming[..], &outgoing[..], &new_members); - } - - /// Set the new members; they **must already be sorted**. This will compute the diff and use it to - /// call `change_members_sorted`. - fn compute_members_diff( - new_members: &[AccountId], - old_members: &[AccountId] - ) -> (Vec, Vec) { - let mut old_iter = old_members.iter(); - let mut new_iter = new_members.iter(); - let mut incoming = Vec::new(); - let mut outgoing = Vec::new(); - let mut old_i = old_iter.next(); - let mut new_i = new_iter.next(); - loop { - match (old_i, new_i) { - (None, None) => break, - (Some(old), Some(new)) if old == new => { - old_i = old_iter.next(); - new_i = new_iter.next(); - } - (Some(old), Some(new)) if old < new => { - outgoing.push(old.clone()); - old_i = old_iter.next(); - } - (Some(old), None) => { - outgoing.push(old.clone()); - old_i = old_iter.next(); - } - (_, Some(new)) => { - incoming.push(new.clone()); - new_i = new_iter.next(); - } - } - } - (incoming, outgoing) - } -} - -impl ChangeMembers for () { - fn change_members(_: &[T], _: &[T], _: Vec) {} - fn change_members_sorted(_: &[T], _: &[T], _: &[T]) {} - fn set_members_sorted(_: &[T], _: &[T]) {} -} - -/// Trait for type that can handle the initialization of account IDs at genesis. -pub trait InitializeMembers { - /// Initialize the members to the given `members`. - fn initialize_members(members: &[AccountId]); -} - -impl InitializeMembers for () { - fn initialize_members(_: &[T]) {} -} - -// A trait that is able to provide randomness. -pub trait Randomness { - /// Get a "random" value - /// - /// Being a deterministic blockchain, real randomness is difficult to come by. This gives you - /// something that approximates it. `subject` is a context identifier and allows you to get a - /// different result to other callers of this function; use it like - /// `random(&b"my context"[..])`. - fn random(subject: &[u8]) -> Output; - - /// Get the basic random seed. - /// - /// In general you won't want to use this, but rather `Self::random` which allows you to give a - /// subject for the random result and whose value will be independently low-influence random - /// from any other such seeds. - fn random_seed() -> Output { - Self::random(&[][..]) - } -} diff --git a/srml/support/test/Cargo.toml b/srml/support/test/Cargo.toml deleted file mode 100644 index a5e375b5c6b93..0000000000000 --- a/srml/support/test/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "srml-support-test" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", default-features = false, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -runtime-io ={ package = "sr-io", path = "../../../core/sr-io", default-features = false } -support = { package = "srml-support", version = "2", path = "../", default-features = false } -inherents = { package = "substrate-inherents", path = "../../../core/inherents", default-features = false } -sr-primitives = { package = "sr-primitives", path = "../../../core/sr-primitives", default-features = false } -primitives = { package = "substrate-primitives", path = "../../../core/primitives", default-features = false } -trybuild = "1.0.17" -pretty_assertions = "0.6.1" - -[features] -default = ["std"] -std = [ - "serde/std", - "codec/std", - "runtime-io/std", - "support/std", - "inherents/std", - "primitives/std", - "sr-primitives/std", -] diff --git a/srml/support/test/src/lib.rs b/srml/support/test/src/lib.rs deleted file mode 100644 index b65bc43cbb5a8..0000000000000 --- a/srml/support/test/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Test crate for srml_support. Allow to make use of `support::decl_storage`. -//! See tests directory. diff --git a/srml/support/test/tests/final_keys.rs b/srml/support/test/tests/final_keys.rs deleted file mode 100644 index 44a6b540a7a0e..0000000000000 --- a/srml/support/test/tests/final_keys.rs +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use runtime_io::with_storage; -use support::storage::unhashed; -use codec::Encode; -use support::{StorageDoubleMap, StorageLinkedMap, StorageMap, StorageValue}; - -mod no_instance { - use codec::{Encode, Decode, EncodeLike}; - - pub trait Trait { - type Origin; - type BlockNumber: Encode + Decode + EncodeLike + Default + Clone; - } - - support::decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - support::decl_storage!{ - trait Store for Module as FinalKeysNone { - pub Value config(value): u32; - - pub Map: map u32 => u32; - pub Map2: map hasher(twox_128) u32 => u32; - - pub LinkedMap: linked_map u32 => u32; - pub LinkedMap2: linked_map hasher(twox_128) u32 => u32; - - pub DoubleMap: double_map u32, blake2_256(u32) => u32; - pub DoubleMap2: double_map hasher(twox_128) u32, blake2_128(u32) => u32; - - pub TestGenericValue get(fn test_generic_value) config(): Option; - pub TestGenericDoubleMap get(fn foo2) config(test_generic_double_map): - double_map u32, blake2_256(T::BlockNumber) => Option; - } - } -} - -mod instance { - pub trait Trait: super::no_instance::Trait {} - - support::decl_module! { - pub struct Module, I: Instantiable = DefaultInstance> - for enum Call where origin: T::Origin {} - } - - support::decl_storage!{ - trait Store for Module, I: Instantiable = DefaultInstance> - as FinalKeysSome - { - pub Value config(value): u32; - - pub Map: map u32 => u32; - pub Map2: map hasher(twox_128) u32 => u32; - - pub LinkedMap: linked_map u32 => u32; - pub LinkedMap2: linked_map hasher(twox_128) u32 => u32; - - pub DoubleMap: double_map u32, blake2_256(u32) => u32; - pub DoubleMap2: double_map hasher(twox_128) u32, blake2_128(u32) => u32; - - pub TestGenericValue get(fn test_generic_value) config(): Option; - pub TestGenericDoubleMap get(fn foo2) config(test_generic_double_map): - double_map u32, blake2_256(T::BlockNumber) => Option; - } - add_extra_genesis { - // See `decl_storage` limitation. - config(phantom): core::marker::PhantomData; - } - } -} - -#[test] -fn final_keys_no_instance() { - with_storage(&mut Default::default(), || { - no_instance::Value::put(1); - assert_eq!(unhashed::get::(&runtime_io::twox_128(b"FinalKeysNone Value")), Some(1u32)); - - no_instance::Map::insert(1, 2); - let mut k = b"FinalKeysNone Map".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); - - no_instance::Map2::insert(1, 2); - let mut k = b"FinalKeysNone Map2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - - let head = b"head of FinalKeysNone LinkedMap".to_vec(); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), None); - - no_instance::LinkedMap::insert(1, 2); - let mut k = b"FinalKeysNone LinkedMap".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), Some(1u32)); - - no_instance::LinkedMap2::insert(1, 2); - let mut k = b"FinalKeysNone LinkedMap2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - - no_instance::DoubleMap::insert(&1, &2, &3); - let mut k = b"FinalKeysNone DoubleMap".to_vec(); - k.extend(1u32.encode()); - let mut k = runtime_io::blake2_256(&k).to_vec(); - k.extend(&runtime_io::blake2_256(&2u32.encode())); - assert_eq!(unhashed::get::(&k), Some(3u32)); - - no_instance::DoubleMap2::insert(&1, &2, &3); - let mut k = b"FinalKeysNone DoubleMap2".to_vec(); - k.extend(1u32.encode()); - let mut k = runtime_io::twox_128(&k).to_vec(); - k.extend(&runtime_io::blake2_128(&2u32.encode())); - assert_eq!(unhashed::get::(&k), Some(3u32)); - }); -} - -#[test] -fn final_keys_default_instance() { - with_storage(&mut Default::default(), || { - >::put(1); - assert_eq!(unhashed::get::(&runtime_io::twox_128(b"FinalKeysSome Value")), Some(1u32)); - - >::insert(1, 2); - let mut k = b"FinalKeysSome Map".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); - - >::insert(1, 2); - let mut k = b"FinalKeysSome Map2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - - let head = b"head of FinalKeysSome LinkedMap".to_vec(); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), None); - - >::insert(1, 2); - let mut k = b"FinalKeysSome LinkedMap".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), Some(1u32)); - -< instance::LinkedMap2>::insert(1, 2); - let mut k = b"FinalKeysSome LinkedMap2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - - >::insert(&1, &2, &3); - let mut k = b"FinalKeysSome DoubleMap".to_vec(); - k.extend(1u32.encode()); - let mut k = runtime_io::blake2_256(&k).to_vec(); - k.extend(&runtime_io::blake2_256(&2u32.encode())); - assert_eq!(unhashed::get::(&k), Some(3u32)); - - >::insert(&1, &2, &3); - let mut k = b"FinalKeysSome DoubleMap2".to_vec(); - k.extend(1u32.encode()); - let mut k = runtime_io::twox_128(&k).to_vec(); - k.extend(&runtime_io::blake2_128(&2u32.encode())); - assert_eq!(unhashed::get::(&k), Some(3u32)); - }); -} - -#[test] -fn final_keys_instance_2() { - with_storage(&mut Default::default(), || { - >::put(1); - assert_eq!( - unhashed::get::(&runtime_io::twox_128(b"Instance2FinalKeysSome Value")), - Some(1u32) - ); - - >::insert(1, 2); - let mut k = b"Instance2FinalKeysSome Map".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); - - >::insert(1, 2); - let mut k = b"Instance2FinalKeysSome Map2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - - let head = b"head of Instance2FinalKeysSome LinkedMap".to_vec(); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), None); - - >::insert(1, 2); - let mut k = b"Instance2FinalKeysSome LinkedMap".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); - assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), Some(1u32)); - - >::insert(1, 2); - let mut k = b"Instance2FinalKeysSome LinkedMap2".to_vec(); - k.extend(1u32.encode()); - assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - - >::insert(&1, &2, &3); - let mut k = b"Instance2FinalKeysSome DoubleMap".to_vec(); - k.extend(1u32.encode()); - let mut k = runtime_io::blake2_256(&k).to_vec(); - k.extend(&runtime_io::blake2_256(&2u32.encode())); - assert_eq!(unhashed::get::(&k), Some(3u32)); - - >::insert(&1, &2, &3); - let mut k = b"Instance2FinalKeysSome DoubleMap2".to_vec(); - k.extend(1u32.encode()); - let mut k = runtime_io::twox_128(&k).to_vec(); - k.extend(&runtime_io::blake2_128(&2u32.encode())); - assert_eq!(unhashed::get::(&k), Some(3u32)); - }); -} diff --git a/srml/support/test/tests/reserved_keyword/on_initialize.rs b/srml/support/test/tests/reserved_keyword/on_initialize.rs deleted file mode 100644 index f9604c9487a9e..0000000000000 --- a/srml/support/test/tests/reserved_keyword/on_initialize.rs +++ /dev/null @@ -1,32 +0,0 @@ -macro_rules! reserved { - ($($reserved:ident)*) => { - $( - mod $reserved { - pub use support::dispatch::Result; - - pub trait Trait { - type Origin; - type BlockNumber: Into; - } - - pub mod system { - use support::dispatch::Result; - - pub fn ensure_root(_: R) -> Result { - Ok(()) - } - } - - support::decl_module! { - pub struct Module for enum Call where origin: T::Origin { - fn $reserved(_origin) -> Result { unreachable!() } - } - } - } - )* - } -} - -reserved!(on_finalize on_initialize on_finalise on_initialise offchain_worker deposit_event); - -fn main() {} diff --git a/srml/support/test/tests/system.rs b/srml/support/test/tests/system.rs deleted file mode 100644 index 2996724f62598..0000000000000 --- a/srml/support/test/tests/system.rs +++ /dev/null @@ -1,64 +0,0 @@ -use support::codec::{Encode, Decode, EncodeLike}; - -pub trait Trait: 'static + Eq + Clone { - type Origin: Into, Self::Origin>> - + From>; - - type BlockNumber: Decode + Encode + EncodeLike + Clone + Default; - type Hash; - type AccountId: Encode + EncodeLike + Decode; - type Event: From; -} - -support::decl_module! { - pub struct Module for enum Call where origin: T::Origin { - } -} - -impl Module { - pub fn deposit_event(_event: impl Into) { - } -} - -support::decl_event!( - pub enum Event { - ExtrinsicSuccess, - ExtrinsicFailed, - } -); - -support::decl_error! { - pub enum Error { - /// Test error documentation - TestError, - /// Error documentation - /// with multiple lines - AnotherError - } -} - -/// Origin for the system module. -#[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] -pub enum RawOrigin { - Root, - Signed(AccountId), - None, -} - -impl From> for RawOrigin { - fn from(s: Option) -> RawOrigin { - match s { - Some(who) => RawOrigin::Signed(who), - None => RawOrigin::None, - } - } -} - -pub type Origin = RawOrigin<::AccountId>; - -#[allow(dead_code)] -pub fn ensure_root(o: OuterOrigin) -> Result<(), &'static str> - where OuterOrigin: Into, OuterOrigin>> -{ - o.into().map(|_| ()).map_err(|_| "bad origin: expected to be a root origin") -} diff --git a/srml/system/Cargo.toml b/srml/system/Cargo.toml deleted file mode 100644 index a9ce6b3f8c830..0000000000000 --- a/srml/system/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "srml-system" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true, features = ["derive"] } -safe-mix = { version = "1.0.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -sr-version = { path = "../../core/sr-version", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -impl-trait-for-tuples = "0.1.2" - -[dev-dependencies] -criterion = "0.2.11" - -[features] -default = ["std"] -std = [ - "serde", - "safe-mix/std", - "codec/std", - "primitives/std", - "rstd/std", - "runtime-io/std", - "support/std", - "sr-primitives/std", - "sr-version/std", -] - -[[bench]] -name = "bench" -harness = false diff --git a/srml/system/benches/bench.rs b/srml/system/benches/bench.rs deleted file mode 100644 index 6da02cf9c8cea..0000000000000 --- a/srml/system/benches/bench.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use criterion::{Criterion, criterion_group, criterion_main, black_box}; -use srml_system as system; -use support::{decl_module, decl_event, impl_outer_origin, impl_outer_event}; -use primitives::H256; -use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; - -mod module { - use super::*; - - pub trait Trait: system::Trait { - type Event: From + Into<::Event>; - } - - decl_module! { - pub struct Module for enum Call where origin: T::Origin { - pub fn deposit_event() = default; - } - } - - decl_event!( - pub enum Event { - Complex(Vec, u32, u16, u128), - } - ); -} - -impl_outer_origin!{ - pub enum Origin for Runtime {} -} - -impl_outer_event! { - pub enum Event for Runtime { - module, - } -} - -support::parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024; - pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); -} -#[derive(Clone, Eq, PartialEq)] -pub struct Runtime; -impl system::Trait for Runtime { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); -} - -impl module::Trait for Runtime { - type Event = Event; -} - -fn new_test_ext() -> runtime_io::TestExternalities { - system::GenesisConfig::default().build_storage::().unwrap().into() -} - -fn deposit_events(n: usize) { - let mut t = new_test_ext(); - t.execute_with(|| { - for _ in 0..n { - module::Module::::deposit_event( - module::Event::Complex(vec![1, 2, 3], 2, 3, 899) - ); - } - }); -} - -fn sr_system_benchmark(c: &mut Criterion) { - c.bench_function("deposit 100 events", |b| { - b.iter(|| deposit_events(black_box(100))) - }); -} - -criterion_group!(benches, sr_system_benchmark); -criterion_main!(benches); diff --git a/srml/system/rpc/Cargo.toml b/srml/system/rpc/Cargo.toml deleted file mode 100644 index 04856a817f681..0000000000000 --- a/srml/system/rpc/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "srml-system-rpc" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../../../core/client" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -jsonrpc-core = "13.2.0" -jsonrpc-core-client = "13.2.0" -jsonrpc-derive = "13.2.0" -log = "0.4.8" -serde = { version = "1.0.101", features = ["derive"] } -sr-primitives = { path = "../../../core/sr-primitives" } -srml-system-rpc-runtime-api = { path = "./runtime-api" } -substrate-primitives = { path = "../../../core/primitives" } -transaction_pool = { package = "substrate-transaction-pool", path = "../../../core/transaction-pool" } - -[dev-dependencies] -test-client = { package = "substrate-test-runtime-client", path = "../../../core/test-runtime/client" } -env_logger = "0.7.0" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19" } diff --git a/srml/system/rpc/runtime-api/Cargo.toml b/srml/system/rpc/runtime-api/Cargo.toml deleted file mode 100644 index fc525d8fce2ad..0000000000000 --- a/srml/system/rpc/runtime-api/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "srml-system-rpc-runtime-api" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -client = { package = "substrate-client", path = "../../../../core/client", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } - -[features] -default = ["std"] -std = [ - "client/std", - "codec/std", -] diff --git a/srml/system/rpc/runtime-api/src/lib.rs b/srml/system/rpc/runtime-api/src/lib.rs deleted file mode 100644 index 45af0241e0836..0000000000000 --- a/srml/system/rpc/runtime-api/src/lib.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Runtime API definition required by System RPC extensions. -//! -//! This API should be imported and implemented by the runtime, -//! of a node that wants to use the custom RPC extension -//! adding System access methods. - -#![cfg_attr(not(feature = "std"), no_std)] - -client::decl_runtime_apis! { - /// The API to query account nonce (aka transaction index). - pub trait AccountNonceApi where - AccountId: codec::Codec, - Index: codec::Codec, - { - /// Get current account nonce of given `AccountId`. - fn account_nonce(account: AccountId) -> Index; - } -} diff --git a/srml/system/rpc/src/lib.rs b/srml/system/rpc/src/lib.rs deleted file mode 100644 index c6c0a658fba53..0000000000000 --- a/srml/system/rpc/src/lib.rs +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! System SRML specific RPC methods. - -use std::sync::Arc; - -use codec::{self, Codec, Encode}; -use client::blockchain::HeaderBackend; -use jsonrpc_core::{Result, Error, ErrorCode}; -use jsonrpc_derive::rpc; -use sr_primitives::{ - generic::BlockId, - traits, -}; -use substrate_primitives::hexdisplay::HexDisplay; -use transaction_pool::txpool::{self, Pool}; - -pub use srml_system_rpc_runtime_api::AccountNonceApi; -pub use self::gen_client::Client as SystemClient; - -/// System RPC methods. -#[rpc] -pub trait SystemApi { - /// Returns the next valid index (aka nonce) for given account. - /// - /// This method takes into consideration all pending transactions - /// currently in the pool and if no transactions are found in the pool - /// it fallbacks to query the index from the runtime (aka. state nonce). - #[rpc(name = "system_accountNextIndex", alias("account_nextIndex"))] - fn nonce(&self, account: AccountId) -> Result; -} - -const RUNTIME_ERROR: i64 = 1; - -/// An implementation of System-specific RPC methods. -pub struct System { - client: Arc, - pool: Arc>, - _marker: std::marker::PhantomData, -} - -impl System { - /// Create new `System` given client and transaction pool. - pub fn new(client: Arc, pool: Arc>) -> Self { - System { - client, - pool, - _marker: Default::default(), - } - } -} - -impl SystemApi for System -where - C: traits::ProvideRuntimeApi, - C: HeaderBackend, - C: Send + Sync + 'static, - C::Api: AccountNonceApi, - P: txpool::ChainApi + Sync + Send + 'static, - Block: traits::Block, - AccountId: Clone + std::fmt::Display + Codec, - Index: Clone + std::fmt::Display + Codec + traits::SimpleArithmetic, -{ - fn nonce(&self, account: AccountId) -> Result { - let api = self.client.runtime_api(); - let best = self.client.info().best_hash; - let at = BlockId::hash(best); - - let nonce = api.account_nonce(&at, account.clone()).map_err(|e| Error { - code: ErrorCode::ServerError(RUNTIME_ERROR), - message: "Unable to query nonce.".into(), - data: Some(format!("{:?}", e).into()), - })?; - - log::debug!(target: "rpc", "State nonce for {}: {}", account, nonce); - // Now we need to query the transaction pool - // and find transactions originating from the same sender. - // - // Since extrinsics are opaque to us, we look for them using - // `provides` tag. And increment the nonce if we find a transaction - // that matches the current one. - let mut current_nonce = nonce.clone(); - let mut current_tag = (account.clone(), nonce.clone()).encode(); - for tx in self.pool.ready() { - log::debug!( - target: "rpc", - "Current nonce to {}, checking {} vs {:?}", - current_nonce, - HexDisplay::from(¤t_tag), - tx.provides.iter().map(|x| format!("{}", HexDisplay::from(x))).collect::>(), - ); - // since transactions in `ready()` need to be ordered by nonce - // it's fine to continue with current iterator. - if tx.provides.get(0) == Some(¤t_tag) { - current_nonce += traits::One::one(); - current_tag = (account.clone(), current_nonce.clone()).encode(); - } - } - - Ok(current_nonce) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use futures03::executor::block_on; - use test_client::{ - runtime::Transfer, - AccountKeyring, - }; - - #[test] - fn should_return_next_nonce_for_some_account() { - // given - let _ = env_logger::try_init(); - let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone()))); - - let new_transaction = |nonce: u64| { - let t = Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Bob.into(), - amount: 5, - nonce, - }; - t.into_signed_tx() - }; - // Populate the pool - let ext0 = new_transaction(0); - block_on(pool.submit_one(&BlockId::number(0), ext0)).unwrap(); - let ext1 = new_transaction(1); - block_on(pool.submit_one(&BlockId::number(0), ext1)).unwrap(); - - let accounts = System::new(client, pool); - - // when - let nonce = accounts.nonce(AccountKeyring::Alice.into()); - - // then - assert_eq!(nonce.unwrap(), 2); - } -} diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs deleted file mode 100644 index 87c38096ab934..0000000000000 --- a/srml/system/src/lib.rs +++ /dev/null @@ -1,1481 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # System Module -//! -//! The System module provides low-level access to core types and cross-cutting utilities. -//! It acts as the base layer for other SRML modules to interact with the Substrate framework components. -//! -//! - [`system::Trait`](./trait.Trait.html) -//! -//! ## Overview -//! -//! The System module defines the core data types used in a Substrate runtime. -//! It also provides several utility functions (see [`Module`](./struct.Module.html)) for other runtime modules. -//! -//! In addition, it manages the storage items for extrinsics data, indexes, event records, and digest items, -//! among other things that support the execution of the current block. -//! -//! It also handles low-level tasks like depositing logs, basic set up and take down of -//! temporary storage entries, and access to previous block hashes. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! The System module does not implement any dispatchable functions. -//! -//! ### Public Functions -//! -//! See the [`Module`](./struct.Module.html) struct for details of publicly available functions. -//! -//! ### Signed Extensions -//! -//! The system module defines the following extensions: -//! -//! - [`CheckWeight`]: Checks the weight and length of the block and ensure that it does not -//! exceed the limits. -//! - [`CheckNonce`]: Checks the nonce of the transaction. Contains a single payload of type -//! `T::Index`. -//! - [`CheckEra`]: Checks the era of the transaction. Contains a single payload of type `Era`. -//! - [`CheckGenesis`]: Checks the provided genesis hash of the transaction. Must be a part of the -//! signed payload of the transaction. -//! - [`CheckVersion`]: Checks that the runtime version is the same as the one encoded in the -//! transaction. -//! -//! Lookup the runtime aggregator file (e.g. `node/runtime`) to see the full list of signed -//! extensions included in a chain. -//! -//! ## Usage -//! -//! ### Prerequisites -//! -//! Import the System module and derive your module's configuration trait from the system trait. -//! -//! ### Example - Get extrinsic count and parent hash for the current block -//! -//! ``` -//! use support::{decl_module, dispatch::Result}; -//! use srml_system::{self as system, ensure_signed}; -//! -//! pub trait Trait: system::Trait {} -//! -//! decl_module! { -//! pub struct Module for enum Call where origin: T::Origin { -//! pub fn system_module_example(origin) -> Result { -//! let _sender = ensure_signed(origin)?; -//! let _extrinsic_count = >::extrinsic_count(); -//! let _parent_hash = >::parent_hash(); -//! Ok(()) -//! } -//! } -//! } -//! # fn main() { } -//! ``` - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -use serde::Serialize; -use rstd::prelude::*; -#[cfg(any(feature = "std", test))] -use rstd::map; -use rstd::marker::PhantomData; -use rstd::fmt::Debug; -use sr_version::RuntimeVersion; -use sr_primitives::{ - RuntimeDebug, - generic::{self, Era}, Perbill, ApplyError, ApplyOutcome, DispatchError, - weights::{Weight, DispatchInfo, DispatchClass, SimpleDispatchInfo}, - transaction_validity::{ - ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError, - InvalidTransaction, TransactionValidity, - }, - traits::{ - self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Lookup, LookupError, - SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, SaturatedConversion, - MaybeSerialize, MaybeSerializeDeserialize, StaticLookup, One, Bounded, - }, -}; - -use primitives::storage::well_known_keys; -use support::{ - decl_module, decl_event, decl_storage, decl_error, storage, Parameter, - traits::{Contains, Get}, -}; -use codec::{Encode, Decode}; - -#[cfg(any(feature = "std", test))] -use runtime_io::TestExternalities; - -#[cfg(any(feature = "std", test))] -use primitives::ChangesTrieConfiguration; - -pub mod offchain; - -/// Handler for when a new account has been created. -#[impl_trait_for_tuples::impl_for_tuples(30)] -pub trait OnNewAccount { - /// A new account `who` has been registered. - fn on_new_account(who: &AccountId); -} - -/// Determiner 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 trie root of a list of extrinsics. -pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { - extrinsics_data_root::(extrinsics.iter().map(codec::Encode::encode).collect()) -} - -/// Compute the trie root of a list of extrinsics. -pub fn extrinsics_data_root(xts: Vec>) -> H::Output { - H::ordered_trie_root(xts) -} - -pub trait Trait: 'static + Eq + Clone { - /// The aggregated `Origin` type used by dispatchable calls. - type Origin: - Into, Self::Origin>> + From>; - - /// The aggregated `Call` type. - type Call: Debug; - - /// Account index (aka nonce) type. This stores the number of previous transactions associated - /// with a sender account. - type Index: - Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + SimpleArithmetic - + Copy; - - /// The block number type used by the runtime. - type BlockNumber: - Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleArithmetic - + Default + Bounded + Copy + rstd::hash::Hash; - - /// The output of the `Hashing` function. - type Hash: - Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleBitOps - + Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]>; - - /// The hashing system (algorithm) being used in the runtime (e.g. Blake2). - type Hashing: Hash; - - /// The user account identifier type for the runtime. - type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord - + Default; - - /// Converting trait to take a source type and convert to `AccountId`. - /// - /// Used to define the type and conversion mechanism for referencing accounts in transactions. - /// It's perfectly reasonable for this to be an identity conversion (with the source type being - /// `AccountId`), but other modules (e.g. Indices module) may provide more functional/efficient - /// alternatives. - type Lookup: StaticLookup; - - /// The block header. - type Header: Parameter + traits::Header< - Number = Self::BlockNumber, - Hash = Self::Hash, - >; - - /// The aggregated event type of the runtime. - type Event: Parameter + Member + From + Debug; - - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount: Get; - - /// The maximum weight of a block. - type MaximumBlockWeight: Get; - - /// The maximum length of a block (in bytes). - type MaximumBlockLength: Get; - - /// The portion of the block that is available to normal transaction. The rest can only be used - /// by operational transactions. This can be applied to any resource limit managed by the system - /// module, including weight and length. - type AvailableBlockRatio: Get; - - /// Get the chain's current version. - type Version: Get; -} - -pub type DigestOf = generic::Digest<::Hash>; -pub type DigestItemOf = generic::DigestItem<::Hash>; - -pub type Key = Vec; -pub type KeyValue = (Vec, Vec); - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - type Error = Error; - - /// A big dispatch that will disallow any other transaction to be included. - // TODO: this must be preferable available for testing really (not possible at the moment). - #[weight = SimpleDispatchInfo::MaxOperational] - fn fill_block(origin) { - ensure_root(origin)?; - } - - /// Make some on-chain remark. - #[weight = SimpleDispatchInfo::FixedNormal(10_000)] - fn remark(origin, _remark: Vec) { - ensure_signed(origin)?; - } - - /// Set the number of pages in the WebAssembly environment's heap. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_heap_pages(origin, pages: u64) { - ensure_root(origin)?; - storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode()); - } - - /// Set the new code. - #[weight = SimpleDispatchInfo::FixedOperational(200_000)] - pub fn set_code(origin, new: Vec) { - ensure_root(origin)?; - storage::unhashed::put_raw(well_known_keys::CODE, &new); - } - - /// Set some items of storage. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_storage(origin, items: Vec) { - ensure_root(origin)?; - for i in &items { - storage::unhashed::put_raw(&i.0, &i.1); - } - } - - /// Kill some items from storage. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn kill_storage(origin, keys: Vec) { - ensure_root(origin)?; - for key in &keys { - storage::unhashed::kill(&key); - } - } - - /// Kill all storage items with a key that starts with the given prefix. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn kill_prefix(origin, prefix: Key) { - ensure_root(origin)?; - storage::unhashed::kill_prefix(&prefix); - } - } -} - -/// A phase of a block's execution. -#[derive(Encode, Decode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))] -pub enum Phase { - /// Applying an extrinsic. - ApplyExtrinsic(u32), - /// The end. - Finalization, -} - -/// Record of an event happening. -#[derive(Encode, Decode, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))] -pub struct EventRecord { - /// The phase of the block it happened in. - pub phase: Phase, - /// The event itself. - pub event: E, - /// The list of the topics this event has. - pub topics: Vec, -} - -decl_event!( - /// Event for the System module. - pub enum Event { - /// An extrinsic completed successfully. - ExtrinsicSuccess, - /// An extrinsic failed. - ExtrinsicFailed(DispatchError), - } -); - -decl_error! { - /// Error for the System module - pub enum Error { - BadSignature, - BlockFull, - RequireSignedOrigin, - RequireRootOrigin, - RequireNoOrigin, - } -} - -/// Origin for the System module. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] -pub enum RawOrigin { - /// The system itself ordained this dispatch to happen: this is the highest privilege level. - Root, - /// It is signed by some public key and we provide the `AccountId`. - Signed(AccountId), - /// It is signed by nobody, can be either: - /// * included and agreed upon by the validators anyway, - /// * or unsigned transaction validated by a module. - None, -} - -impl From> for RawOrigin { - fn from(s: Option) -> RawOrigin { - match s { - Some(who) => RawOrigin::Signed(who), - None => RawOrigin::None, - } - } -} - -/// Exposed trait-generic origin type. -pub type Origin = RawOrigin<::AccountId>; - -// 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 -} - -/// This type alias represents an index of an event. -/// -/// We use `u32` here because this index is used as index for `Events` -/// which can't contain more than `u32::max_value()` items. -type EventIndex = u32; - -decl_storage! { - trait Store for Module as System { - /// Extrinsics nonce for accounts. - pub AccountNonce get(fn account_nonce): map T::AccountId => T::Index; - /// Total extrinsics count for the current block. - ExtrinsicCount: Option; - /// Total weight for all extrinsics put together, for the current block. - AllExtrinsicsWeight: Option; - /// Total length (in bytes) for all extrinsics put together, for the current block. - AllExtrinsicsLen: Option; - /// Map of block numbers to block hashes. - pub BlockHash get(fn block_hash) build(|_| vec![(T::BlockNumber::zero(), hash69())]): map T::BlockNumber => T::Hash; - /// Extrinsics data for the current block (maps an extrinsic's index to its data). - ExtrinsicData get(fn extrinsic_data): map u32 => Vec; - /// The current block number being processed. Set by `execute_block`. - Number get(fn block_number) build(|_| 1.into()): T::BlockNumber; - /// Hash of the previous block. - ParentHash get(fn parent_hash) build(|_| hash69()): T::Hash; - /// Extrinsics root of the current block, also part of the block header. - ExtrinsicsRoot get(fn extrinsics_root): T::Hash; - /// Digest of the current block, also part of the block header. - Digest get(fn digest): DigestOf; - /// Events deposited for the current block. - Events get(fn events): Vec>; - /// The number of events in the `Events` list. - EventCount get(fn event_count): EventIndex; - - // TODO: https://github.com/paritytech/substrate/issues/2553 - // Possibly, we can improve it by using something like: - // `Option<(BlockNumber, Vec)>`, however in this case we won't be able to use - // `EventTopics::append`. - - /// Mapping between a topic (represented by T::Hash) and a vector of indexes - /// of events in the `>` list. - /// - /// The first key serves no purpose. This field is declared as double_map just - /// for convenience of using `remove_prefix`. - /// - /// All topic vectors have deterministic storage locations depending on the topic. This - /// allows light-clients to leverage the changes trie storage tracking mechanism and - /// in case of changes fetch the list of events of interest. - /// - /// The value has the type `(T::BlockNumber, EventIndex)` because if we used only just - /// the `EventIndex` then in case if the topic has the same contents on the next block - /// no notification will be triggered thus the event might be lost. - EventTopics get(fn event_topics): double_map hasher(blake2_256) (), blake2_256(T::Hash) - => Vec<(T::BlockNumber, EventIndex)>; - } - add_extra_genesis { - config(changes_trie_config): Option; - #[serde(with = "primitives::bytes")] - config(code): Vec; - - build(|config: &GenesisConfig| { - use codec::Encode; - - runtime_io::set_storage(well_known_keys::CODE, &config.code); - runtime_io::set_storage(well_known_keys::EXTRINSIC_INDEX, &0u32.encode()); - - if let Some(ref changes_trie_config) = config.changes_trie_config { - runtime_io::set_storage( - well_known_keys::CHANGES_TRIE_CONFIG, - &changes_trie_config.encode(), - ); - } - }); - } -} - -pub struct EnsureRoot(rstd::marker::PhantomData); -impl< - O: Into, O>> + From>, - AccountId, -> EnsureOrigin for EnsureRoot { - type Success = (); - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Root => Ok(()), - r => Err(O::from(r)), - }) - } -} - -pub struct EnsureSigned(rstd::marker::PhantomData); -impl< - O: Into, O>> + From>, - AccountId, -> EnsureOrigin for EnsureSigned { - type Success = AccountId; - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Signed(who) => Ok(who), - r => Err(O::from(r)), - }) - } -} - -pub struct EnsureSignedBy(rstd::marker::PhantomData<(Who, AccountId)>); -impl< - O: Into, O>> + From>, - Who: Contains, - AccountId: PartialEq + Clone, -> EnsureOrigin for EnsureSignedBy { - type Success = AccountId; - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Signed(ref who) if Who::contains(who) => Ok(who.clone()), - r => Err(O::from(r)), - }) - } -} - -pub struct EnsureNone(rstd::marker::PhantomData); -impl< - O: Into, O>> + From>, - AccountId, -> EnsureOrigin for EnsureNone { - type Success = (); - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::None => Ok(()), - r => Err(O::from(r)), - }) - } -} - -pub struct EnsureNever(rstd::marker::PhantomData); -impl EnsureOrigin for EnsureNever { - type Success = T; - fn try_origin(o: O) -> Result { - Err(o) - } -} - -/// Ensure that the origin `o` represents a signed extrinsic (i.e. transaction). -/// Returns `Ok` with the account that signed the extrinsic or an `Err` otherwise. -pub fn ensure_signed(o: OuterOrigin) -> Result - where OuterOrigin: Into, OuterOrigin>> -{ - match o.into() { - Ok(RawOrigin::Signed(t)) => Ok(t), - _ => Err(Error::RequireSignedOrigin), - } -} - -/// Ensure that the origin `o` represents the root. Returns `Ok` or an `Err` otherwise. -pub fn ensure_root(o: OuterOrigin) -> Result<(), Error> - where OuterOrigin: Into, OuterOrigin>> -{ - match o.into() { - Ok(RawOrigin::Root) => Ok(()), - _ => Err(Error::RequireRootOrigin), - } -} - -/// Ensure that the origin `o` represents an unsigned extrinsic. Returns `Ok` or an `Err` otherwise. -pub fn ensure_none(o: OuterOrigin) -> Result<(), Error> - where OuterOrigin: Into, OuterOrigin>> -{ - match o.into() { - Ok(RawOrigin::None) => Ok(()), - _ => Err(Error::RequireNoOrigin), - } -} - -impl Module { - /// Deposits an event into this block's event record. - pub fn deposit_event(event: impl Into) { - Self::deposit_event_indexed(&[], event.into()); - } - - /// Deposits an event into this block's event record adding this event - /// to the corresponding topic indexes. - /// - /// This will update storage entries that correspond to the specified topics. - /// It is expected that light-clients could subscribe to this topics. - pub fn deposit_event_indexed(topics: &[T::Hash], event: T::Event) { - let extrinsic_index = Self::extrinsic_index(); - let phase = extrinsic_index.map_or(Phase::Finalization, |c| Phase::ApplyExtrinsic(c)); - let event = EventRecord { - phase, - event, - topics: topics.iter().cloned().collect::>(), - }; - - // Index of the to be added event. - let event_idx = { - let old_event_count = EventCount::get(); - let new_event_count = match old_event_count.checked_add(1) { - // We've reached the maximum number of events at this block, just - // don't do anything and leave the event_count unaltered. - None => return, - Some(nc) => nc, - }; - EventCount::put(new_event_count); - old_event_count - }; - - // Appending can only fail if `Events` can not be decoded or - // when we try to insert more than `u32::max_value()` events. - // - // We perform early return if we've reached the maximum capacity of the event list, - // so `Events` seems to be corrupted. Also, this has happened after the start of execution - // (since the event list is cleared at the block initialization). - if >::append([event].iter()).is_err() { - // The most sensible thing to do here is to just ignore this event and wait until the - // new block. - return; - } - - let block_no = Self::block_number(); - for topic in topics { - // The same applies here. - if >::append(&(), topic, &[(block_no, event_idx)]).is_err() { - return; - } - } - } - - /// Gets the index of extrinsic that is currently executing. - pub fn extrinsic_index() -> Option { - storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX) - } - - /// Gets extrinsics count. - pub fn extrinsic_count() -> u32 { - ExtrinsicCount::get().unwrap_or_default() - } - - /// Gets a total weight of all executed extrinsics. - pub fn all_extrinsics_weight() -> Weight { - AllExtrinsicsWeight::get().unwrap_or_default() - } - - pub fn all_extrinsics_len() -> u32 { - AllExtrinsicsLen::get().unwrap_or_default() - } - - /// Start the execution of a particular block. - pub fn initialize( - number: &T::BlockNumber, - parent_hash: &T::Hash, - txs_root: &T::Hash, - digest: &DigestOf, - ) { - // populate environment - storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); - >::put(number); - >::put(digest); - >::put(parent_hash); - >::insert(*number - One::one(), parent_hash); - >::put(txs_root); - >::kill(); - EventCount::kill(); - >::remove_prefix(&()); - } - - /// Remove temporary "environment" entries in storage. - pub fn finalize() -> T::Header { - ExtrinsicCount::kill(); - AllExtrinsicsWeight::kill(); - AllExtrinsicsLen::kill(); - - let number = >::take(); - let parent_hash = >::take(); - let mut digest = >::take(); - let extrinsics_root = >::take(); - - // move block hash pruning window by one block - let block_hash_count = ::get(); - if number > block_hash_count { - let to_remove = number - block_hash_count - One::one(); - - // keep genesis hash - if to_remove != Zero::zero() { - >::remove(to_remove); - } - } - - let storage_root = T::Hashing::storage_root(); - let storage_changes_root = T::Hashing::storage_changes_root(parent_hash); - - // we can't compute changes trie root earlier && put it to the Digest - // because it will include all currently existing temporaries. - if let Some(storage_changes_root) = storage_changes_root { - let item = generic::DigestItem::ChangesTrieRoot(storage_changes_root); - digest.push(item); - } - - // The following fields - // - // - > - // - > - // - > - // - // stay to be inspected by the client and will be cleared by `Self::initialize`. - - ::new(number, extrinsics_root, storage_root, parent_hash, digest) - } - - /// Deposits a log and ensures it matches the block's log data. - pub fn deposit_log(item: DigestItemOf) { - let mut l = >::get(); - l.push(item); - >::put(l); - } - - /// Get the basic externalities for this module, useful for tests. - #[cfg(any(feature = "std", test))] - pub fn externalities() -> TestExternalities { - TestExternalities::new((map![ - >::hashed_key_for(T::BlockNumber::zero()) => [69u8; 32].encode(), - >::hashed_key().to_vec() => T::BlockNumber::one().encode(), - >::hashed_key().to_vec() => [69u8; 32].encode() - ], map![])) - } - - /// Set the block number to something in particular. Can be used as an alternative to - /// `initialize` for tests that don't need to bother with the other environment entries. - #[cfg(any(feature = "std", test))] - pub fn set_block_number(n: T::BlockNumber) { - >::put(n); - } - - /// Sets the index of extrinsic that is currently executing. - #[cfg(any(feature = "std", test))] - pub fn set_extrinsic_index(extrinsic_index: u32) { - storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &extrinsic_index) - } - - /// Set the parent hash number to something in particular. Can be used as an alternative to - /// `initialize` for tests that don't need to bother with the other environment entries. - #[cfg(any(feature = "std", test))] - pub fn set_parent_hash(n: T::Hash) { - >::put(n); - } - - /// Set the current block weight. This should only be used in some integration tests. - #[cfg(any(feature = "std", test))] - pub fn set_block_limits(weight: Weight, len: usize) { - AllExtrinsicsWeight::put(weight); - AllExtrinsicsLen::put(len as u32); - } - - /// Return the chain's current runtime version. - pub fn runtime_version() -> RuntimeVersion { T::Version::get() } - - /// Increment a particular account's nonce by 1. - pub fn inc_account_nonce(who: &T::AccountId) { - >::insert(who, Self::account_nonce(who) + T::Index::one()); - } - - /// 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) { - ExtrinsicData::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: &ApplyOutcome, _encoded_len: u32) { - Self::deposit_event( - match r { - Ok(()) => Event::ExtrinsicSuccess, - Err(err) => Event::ExtrinsicFailed(err.clone()), - } - ); - - let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32; - - storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &next_extrinsic_index); - } - - /// To be called immediately after `note_applied_extrinsic` of the last extrinsic of the block - /// has been called. - pub fn note_finished_extrinsics() { - let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX) - .unwrap_or_default(); - ExtrinsicCount::put(extrinsic_index); - } - - /// Remove all extrinsic data and save the extrinsics trie root. - pub fn derive_extrinsics() { - let extrinsics = (0..ExtrinsicCount::get().unwrap_or_default()) - .map(ExtrinsicData::take).collect(); - let xts_root = extrinsics_data_root::(extrinsics); - >::put(xts_root); - } -} - -/// resource limit check. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckWeight(PhantomData); - -impl CheckWeight { - /// Get the quota ratio of each dispatch class type. This indicates that all operational - /// dispatches can use the full capacity of any resource, while user-triggered ones can consume - /// a portion. - fn get_dispatch_limit_ratio(class: DispatchClass) -> Perbill { - match class { - DispatchClass::Operational => Perbill::one(), - // TODO: this must be some sort of a constant. - DispatchClass::Normal => T::AvailableBlockRatio::get(), - } - } - - /// Checks if the current extrinsic can fit into the block with respect to block weight limits. - /// - /// Upon successes, it returns the new block weight as a `Result`. - fn check_weight(info: DispatchInfo) -> Result { - let current_weight = Module::::all_extrinsics_weight(); - let maximum_weight = T::MaximumBlockWeight::get(); - let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_weight; - let added_weight = info.weight.min(limit); - let next_weight = current_weight.saturating_add(added_weight); - if next_weight > limit { - Err(InvalidTransaction::ExhaustsResources.into()) - } else { - Ok(next_weight) - } - } - - /// Checks if the current extrinsic can fit into the block with respect to block length limits. - /// - /// Upon successes, it returns the new block length as a `Result`. - fn check_block_length(info: DispatchInfo, len: usize) -> Result { - let current_len = Module::::all_extrinsics_len(); - let maximum_len = T::MaximumBlockLength::get(); - let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_len; - let added_len = len as u32; - let next_len = current_len.saturating_add(added_len); - if next_len > limit { - Err(InvalidTransaction::ExhaustsResources.into()) - } else { - Ok(next_len) - } - } - - /// get the priority of an extrinsic denoted by `info`. - fn get_priority(info: DispatchInfo) -> TransactionPriority { - match info.class { - DispatchClass::Normal => info.weight.into(), - DispatchClass::Operational => Bounded::max_value() - } - } - - /// Creates new `SignedExtension` to check weight of the extrinsic. - pub fn new() -> Self { - Self(PhantomData) - } -} - -impl SignedExtension for CheckWeight { - type AccountId = T::AccountId; - type Call = T::Call; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } - - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> Result<(), ApplyError> { - let next_len = Self::check_block_length(info, len)?; - AllExtrinsicsLen::put(next_len); - let next_weight = Self::check_weight(info)?; - AllExtrinsicsWeight::put(next_weight); - Ok(()) - } - - fn validate( - &self, - _who: &Self::AccountId, - _call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> TransactionValidity { - // There is no point in writing to storage here since changes are discarded. This basically - // discards any transaction which is bigger than the length or weight limit **alone**, which - // is a guarantee that it will fail in the pre-dispatch phase. - if let Err(e) = Self::check_block_length(info, len) { - return Err(e); - } - - if let Err(e) = Self::check_weight(info) { - return Err(e); - } - - Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) - } -} - -impl Debug for CheckWeight { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "CheckWeight") - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -/// Nonce check and increment to give replay protection for transactions. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckNonce(#[codec(compact)] T::Index); - -impl CheckNonce { - /// utility constructor. Used only in client/factory code. - pub fn from(nonce: T::Index) -> Self { - Self(nonce) - } -} - -impl Debug for CheckNonce { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - self.0.fmt(f) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -impl SignedExtension for CheckNonce { - type AccountId = T::AccountId; - type Call = T::Call; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } - - fn pre_dispatch( - self, - who: &Self::AccountId, - _call: &Self::Call, - _info: DispatchInfo, - _len: usize, - ) -> Result<(), ApplyError> { - let expected = >::get(who); - if self.0 != expected { - return Err( - if self.0 < expected { - InvalidTransaction::Stale - } else { - InvalidTransaction::Future - }.into() - ) - } - - >::insert(who, expected + T::Index::one()); - Ok(()) - } - - fn validate( - &self, - who: &Self::AccountId, - _call: &Self::Call, - info: DispatchInfo, - _len: usize, - ) -> TransactionValidity { - // check index - let expected = >::get(who); - if self.0 < expected { - return InvalidTransaction::Stale.into() - } - - let provides = vec![Encode::encode(&(who, self.0))]; - let requires = if expected < self.0 { - vec![Encode::encode(&(who, self.0 - One::one()))] - } else { - vec![] - }; - - Ok(ValidTransaction { - priority: info.weight as TransactionPriority, - requires, - provides, - longevity: TransactionLongevity::max_value(), - propagate: true, - }) - } -} - -/// Check for transaction mortality. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckEra((Era, rstd::marker::PhantomData)); - -impl CheckEra { - /// utility constructor. Used only in client/factory code. - pub fn from(era: Era) -> Self { - Self((era, rstd::marker::PhantomData)) - } -} - -impl Debug for CheckEra { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - self.0.fmt(f) - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -impl SignedExtension for CheckEra { - type AccountId = T::AccountId; - type Call = T::Call; - type AdditionalSigned = T::Hash; - type Pre = (); - - fn validate( - &self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: DispatchInfo, - _len: usize, - ) -> TransactionValidity { - let current_u64 = >::block_number().saturated_into::(); - let valid_till = (self.0).0.death(current_u64); - Ok(ValidTransaction { - longevity: valid_till.saturating_sub(current_u64), - ..Default::default() - }) - } - - fn additional_signed(&self) -> Result { - let current_u64 = >::block_number().saturated_into::(); - let n = (self.0).0.birth(current_u64).saturated_into::(); - if !>::exists(n) { - Err(InvalidTransaction::AncientBirthBlock.into()) - } else { - Ok(>::block_hash(n)) - } - } -} - -/// Nonce check and increment to give replay protection for transactions. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckGenesis(rstd::marker::PhantomData); - -impl Debug for CheckGenesis { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "CheckGenesis") - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -impl CheckGenesis { - /// Creates new `SignedExtension` to check genesis hash. - pub fn new() -> Self { - Self(rstd::marker::PhantomData) - } -} - -impl SignedExtension for CheckGenesis { - type AccountId = T::AccountId; - type Call = ::Call; - type AdditionalSigned = T::Hash; - type Pre = (); - - fn additional_signed(&self) -> Result { - Ok(>::block_hash(T::BlockNumber::zero())) - } -} - -/// Ensure the runtime version registered in the transaction is the same as at present. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct CheckVersion(rstd::marker::PhantomData); - -impl Debug for CheckVersion { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "CheckVersion") - } - - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -impl CheckVersion { - /// Create new `SignedExtension` to check runtime version. - pub fn new() -> Self { - Self(rstd::marker::PhantomData) - } -} - -impl SignedExtension for CheckVersion { - type AccountId = T::AccountId; - type Call = ::Call; - type AdditionalSigned = u32; - type Pre = (); - - fn additional_signed(&self) -> Result { - Ok(>::runtime_version().spec_version) - } -} - -pub struct ChainContext(rstd::marker::PhantomData); -impl Default for ChainContext { - fn default() -> Self { - ChainContext(rstd::marker::PhantomData) - } -} - -impl Lookup for ChainContext { - type Source = ::Source; - type Target = ::Target; - - fn lookup(&self, s: Self::Source) -> Result { - ::lookup(s) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use primitives::H256; - use sr_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header, DispatchError}; - use support::{impl_outer_origin, parameter_types}; - - impl_outer_origin! { - pub enum Origin for Test where system = super {} - } - - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - - parameter_types! { - pub const BlockHashCount: u64 = 10; - pub const MaximumBlockWeight: Weight = 1024; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); - pub const MaximumBlockLength: u32 = 1024; - } - - impl Trait for Test { - type Origin = Origin; - type Call = (); - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = u16; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - - impl From for u16 { - fn from(e: Event) -> u16 { - match e { - Event::ExtrinsicSuccess => 100, - Event::ExtrinsicFailed(_) => 101, - } - } - } - - type System = Module; - - const CALL: &::Call = &(); - - fn new_test_ext() -> runtime_io::TestExternalities { - GenesisConfig::default().build_storage::().unwrap().into() - } - - fn normal_weight_limit() -> Weight { - ::AvailableBlockRatio::get() * ::MaximumBlockWeight::get() - } - - fn normal_length_limit() -> u32 { - ::AvailableBlockRatio::get() * ::MaximumBlockLength::get() - } - - #[test] - fn origin_works() { - let o = Origin::from(RawOrigin::::Signed(1u64)); - let x: Result, Origin> = o.into(); - assert_eq!(x, Ok(RawOrigin::::Signed(1u64))); - } - - #[test] - fn deposit_event_should_work() { - new_test_ext().execute_with(|| { - System::initialize(&1, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - System::note_finished_extrinsics(); - System::deposit_event(1u16); - System::finalize(); - assert_eq!( - System::events(), - vec![ - EventRecord { - phase: Phase::Finalization, - event: 1u16, - topics: vec![], - } - ] - ); - - System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - System::deposit_event(42u16); - System::note_applied_extrinsic(&Ok(()), 0); - System::note_applied_extrinsic(&Err(DispatchError::new(Some(1), 2, None)), 0); - System::note_finished_extrinsics(); - System::deposit_event(3u16); - System::finalize(); - assert_eq!( - System::events(), - vec![ - EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(1), event: 101u16, topics: vec![] }, - EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } - ] - ); - }); - } - - #[test] - fn deposit_event_topics() { - new_test_ext().execute_with(|| { - const BLOCK_NUMBER: u64 = 1; - - System::initialize( - &BLOCK_NUMBER, - &[0u8; 32].into(), - &[0u8; 32].into(), - &Default::default(), - ); - System::note_finished_extrinsics(); - - let topics = vec![ - H256::repeat_byte(1), - H256::repeat_byte(2), - H256::repeat_byte(3), - ]; - - // We deposit a few events with different sets of topics. - System::deposit_event_indexed(&topics[0..3], 1u16); - System::deposit_event_indexed(&topics[0..1], 2u16); - System::deposit_event_indexed(&topics[1..2], 3u16); - - System::finalize(); - - // Check that topics are reflected in the event record. - assert_eq!( - System::events(), - vec![ - EventRecord { - phase: Phase::Finalization, - event: 1u16, - topics: topics[0..3].to_vec(), - }, - EventRecord { - phase: Phase::Finalization, - event: 2u16, - topics: topics[0..1].to_vec(), - }, - EventRecord { - phase: Phase::Finalization, - event: 3u16, - topics: topics[1..2].to_vec(), - } - ] - ); - - // Check that the topic-events mapping reflects the deposited topics. - // Note that these are indexes of the events. - assert_eq!( - System::event_topics(&(), &topics[0]), - vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 1)], - ); - assert_eq!( - System::event_topics(&(), &topics[1]), - vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 2)], - ); - assert_eq!( - System::event_topics(&(), &topics[2]), - vec![(BLOCK_NUMBER, 0)], - ); - }); - } - - #[test] - fn prunes_block_hash_mappings() { - new_test_ext().execute_with(|| { - // simulate import of 15 blocks - for n in 1..=15 { - System::initialize( - &n, - &[n as u8 - 1; 32].into(), - &[0u8; 32].into(), - &Default::default(), - ); - - System::finalize(); - } - - // first 5 block hashes are pruned - for n in 0..5 { - assert_eq!( - System::block_hash(n), - H256::zero(), - ); - } - - // the remaining 10 are kept - for n in 5..15 { - assert_eq!( - System::block_hash(n), - [n as u8; 32].into(), - ); - } - }) - } - - #[test] - fn signed_ext_check_nonce_works() { - new_test_ext().execute_with(|| { - >::insert(1, 1); - let info = DispatchInfo::default(); - let len = 0_usize; - // stale - assert!(CheckNonce::(0).validate(&1, CALL, info, len).is_err()); - assert!(CheckNonce::(0).pre_dispatch(&1, CALL, info, len).is_err()); - // correct - assert!(CheckNonce::(1).validate(&1, CALL, info, len).is_ok()); - assert!(CheckNonce::(1).pre_dispatch(&1, CALL, info, len).is_ok()); - // future - assert!(CheckNonce::(5).validate(&1, CALL, info, len).is_ok()); - assert!(CheckNonce::(5).pre_dispatch(&1, CALL, info, len).is_err()); - }) - } - - #[test] - fn signed_ext_check_weight_works_normal_tx() { - new_test_ext().execute_with(|| { - let normal_limit = normal_weight_limit(); - let small = DispatchInfo { weight: 100, ..Default::default() }; - let medium = DispatchInfo { - weight: normal_limit - 1, - ..Default::default() - }; - let big = DispatchInfo { - weight: normal_limit + 1, - ..Default::default() - }; - let len = 0_usize; - - let reset_check_weight = |i, f, s| { - AllExtrinsicsWeight::put(s); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, i, len); - if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } - }; - - reset_check_weight(small, false, 0); - reset_check_weight(medium, false, 0); - reset_check_weight(big, true, 1); - }) - } - - #[test] - fn signed_ext_check_weight_fee_works() { - new_test_ext().execute_with(|| { - let free = DispatchInfo { weight: 0, ..Default::default() }; - let len = 0_usize; - - assert_eq!(System::all_extrinsics_weight(), 0); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, free, len); - assert!(r.is_ok()); - assert_eq!(System::all_extrinsics_weight(), 0); - }) - } - - #[test] - fn signed_ext_check_weight_max_works() { - new_test_ext().execute_with(|| { - let max = DispatchInfo { weight: Weight::max_value(), ..Default::default() }; - let len = 0_usize; - let normal_limit = normal_weight_limit(); - - assert_eq!(System::all_extrinsics_weight(), 0); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, max, len); - assert!(r.is_ok()); - assert_eq!(System::all_extrinsics_weight(), normal_limit); - }) - } - - #[test] - fn signed_ext_check_weight_works_operational_tx() { - new_test_ext().execute_with(|| { - let normal = DispatchInfo { weight: 100, ..Default::default() }; - let op = DispatchInfo { weight: 100, class: DispatchClass::Operational }; - let len = 0_usize; - let normal_limit = normal_weight_limit(); - - // given almost full block - AllExtrinsicsWeight::put(normal_limit); - // will not fit. - assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, normal, len).is_err()); - // will fit. - assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, op, len).is_ok()); - - // likewise for length limit. - let len = 100_usize; - AllExtrinsicsLen::put(normal_length_limit()); - assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, normal, len).is_err()); - assert!(CheckWeight::(PhantomData).pre_dispatch(&1, CALL, op, len).is_ok()); - }) - } - - #[test] - fn signed_ext_check_weight_priority_works() { - new_test_ext().execute_with(|| { - let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal }; - let op = DispatchInfo { weight: 100, class: DispatchClass::Operational }; - let len = 0_usize; - - let priority = CheckWeight::(PhantomData) - .validate(&1, CALL, normal, len) - .unwrap() - .priority; - assert_eq!(priority, 100); - - let priority = CheckWeight::(PhantomData) - .validate(&1, CALL, op, len) - .unwrap() - .priority; - assert_eq!(priority, Bounded::max_value()); - }) - } - - #[test] - fn signed_ext_check_weight_block_size_works() { - new_test_ext().execute_with(|| { - let normal = DispatchInfo::default(); - let normal_limit = normal_weight_limit() as usize; - let reset_check_weight = |tx, s, f| { - AllExtrinsicsLen::put(0); - let r = CheckWeight::(PhantomData).pre_dispatch(&1, CALL, tx, s); - if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } - }; - - reset_check_weight(normal, normal_limit - 1, false); - reset_check_weight(normal, normal_limit, false); - reset_check_weight(normal, normal_limit + 1, true); - - // Operational ones don't have this limit. - let op = DispatchInfo { weight: 0, class: DispatchClass::Operational }; - reset_check_weight(op, normal_limit, false); - reset_check_weight(op, normal_limit + 100, false); - reset_check_weight(op, 1024, false); - reset_check_weight(op, 1025, true); - }) - } - - #[test] - fn signed_ext_check_era_should_work() { - new_test_ext().execute_with(|| { - // future - assert_eq!( - CheckEra::::from(Era::mortal(4, 2)).additional_signed().err().unwrap(), - InvalidTransaction::AncientBirthBlock.into(), - ); - - // correct - System::set_block_number(13); - >::insert(12, H256::repeat_byte(1)); - assert!(CheckEra::::from(Era::mortal(4, 12)).additional_signed().is_ok()); - }) - } - - #[test] - fn signed_ext_check_era_should_change_longevity() { - new_test_ext().execute_with(|| { - let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal }; - let len = 0_usize; - let ext = ( - CheckWeight::(PhantomData), - CheckEra::::from(Era::mortal(16, 256)), - ); - System::set_block_number(17); - >::insert(16, H256::repeat_byte(1)); - - assert_eq!(ext.validate(&1, CALL, normal, len).unwrap().longevity, 15); - }) - } -} diff --git a/srml/system/src/offchain.rs b/srml/system/src/offchain.rs deleted file mode 100644 index 11f7e234f7197..0000000000000 --- a/srml/system/src/offchain.rs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Module helpers for offchain calls. - -use codec::Encode; -use sr_primitives::app_crypto::{self, RuntimeAppPublic}; -use sr_primitives::traits::{Extrinsic as ExtrinsicT, IdentifyAccount}; - -/// A trait responsible for signing a payload using given account. -pub trait Signer { - /// Sign any encodable payload with given account and produce a signature. - /// - /// Returns `Some` if signing succeeded and `None` in case the `account` couldn't be used. - fn sign(public: Public, payload: &Payload) -> Option; -} - -/// A `Signer` implementation for any `AppPublic` type. -/// -/// This implementation additionaly supports conversion to/from multi-signature/multi-signer -/// wrappers. -/// If the wrapped crypto doesn't match `AppPublic`s crypto `None` is returned. -impl Signer for AppPublic where - AppPublic: RuntimeAppPublic - + app_crypto::AppPublic - + From<::Generic>, - ::Signature: app_crypto::AppSignature, - Signature: From< - <::Signature as app_crypto::AppSignature>::Generic - >, - Public: rstd::convert::TryInto<::Generic> -{ - fn sign(public: Public, raw_payload: &Payload) -> Option { - raw_payload.using_encoded(|payload| { - let public = public.try_into().ok()?; - AppPublic::from(public).sign(&payload) - .map( - <::Signature as app_crypto::AppSignature> - ::Generic::from - ) - .map(Signature::from) - }) - } -} - -/// Creates runtime-specific signed transaction. -pub trait CreateTransaction { - /// A `Public` key representing a particular `AccountId`. - type Public; - /// A `Signature` generated by the `Signer`. - type Signature; - - /// Attempt to create signed extrinsic data that encodes call from given account. - /// - /// Runtime implementation is free to construct the payload to sign and the signature - /// in any way it wants. - /// Returns `None` if signed extrinsic could not be created (either because signing failed - /// or because of any other runtime-specific reason). - fn create_transaction>( - call: Extrinsic::Call, - public: Self::Public, - account: T::AccountId, - nonce: T::Index, - ) -> Option<(Extrinsic::Call, Extrinsic::SignaturePayload)>; -} - -type PublicOf = < - >::CreateTransaction as CreateTransaction< - T, - >::Extrinsic, - > ->::Public; - -/// A trait to sign and submit transactions in offchain calls. -pub trait SubmitSignedTransaction -where - PublicOf: IdentifyAccount + Clone, -{ - /// Unchecked extrinsic type. - type Extrinsic: ExtrinsicT + codec::Encode; - - /// A runtime-specific type to produce signed data for the extrinsic. - type CreateTransaction: CreateTransaction; - - /// A type used to sign transactions created using `CreateTransaction`. - type Signer: Signer< - PublicOf, - >::Signature, - >; - - /// Sign given call and submit it to the transaction pool. - /// - /// Returns `Ok` if the transaction was submitted correctly - /// and `Err` if the key for given `id` was not found or the - /// transaction was rejected from the pool. - fn sign_and_submit(call: impl Into, public: PublicOf) -> Result<(), ()> { - let call = call.into(); - let id = public.clone().into_account(); - let expected = >::account_nonce(&id); - let (call, signature_data) = Self::CreateTransaction - ::create_transaction::(call, public, id, expected) - .ok_or(())?; - let xt = Self::Extrinsic::new(call, Some(signature_data)).ok_or(())?; - runtime_io::submit_transaction(xt.encode()) - } -} - -/// A trait to submit unsigned transactions in offchain calls. -pub trait SubmitUnsignedTransaction { - /// Unchecked extrinsic type. - type Extrinsic: ExtrinsicT + codec::Encode; - - /// Submit given call to the transaction pool as unsigned transaction. - /// - /// Returns `Ok` if the transaction was submitted correctly - /// and `Err` if transaction was rejected from the pool. - fn submit_unsigned(call: impl Into) -> Result<(), ()> { - let xt = Self::Extrinsic::new(call.into(), None).ok_or(())?; - runtime_io::submit_transaction(xt.encode()) - } -} - -/// A default type used to submit transactions to the pool. -pub struct TransactionSubmitter { - _signer: rstd::marker::PhantomData<(S, C, E)>, -} - -impl Default for TransactionSubmitter { - fn default() -> Self { - Self { - _signer: Default::default(), - } - } -} - -/// A blanket implementation to simplify creation of transaction signer & submitter in the runtime. -impl SubmitSignedTransaction for TransactionSubmitter where - T: crate::Trait, - C: CreateTransaction, - S: Signer<>::Public, >::Signature>, - E: ExtrinsicT + codec::Encode, - >::Public: IdentifyAccount + Clone, -{ - type Extrinsic = E; - type CreateTransaction = C; - type Signer = S; -} - -/// A blanket impl to use the same submitter for usigned transactions as well. -impl SubmitUnsignedTransaction for TransactionSubmitter where - T: crate::Trait, - E: ExtrinsicT + codec::Encode, -{ - type Extrinsic = E; -} diff --git a/srml/timestamp/Cargo.toml b/srml/timestamp/Cargo.toml deleted file mode 100644 index 939fb72566608..0000000000000 --- a/srml/timestamp/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "srml-timestamp" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -impl-trait-for-tuples = "0.1.2" - -[dev-dependencies] -runtime-io ={ package = "sr-io", path = "../../core/sr-io" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } - -[features] -default = ["std"] -std = [ - "inherents/std", - "codec/std", - "rstd/std", - "sr-primitives/std", - "support/std", - "serde", - "system/std", -] diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs deleted file mode 100644 index 2ab751088e8c7..0000000000000 --- a/srml/timestamp/src/lib.rs +++ /dev/null @@ -1,398 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Timestamp Module -//! -//! The Timestamp module provides functionality to get and set the on-chain time. -//! -//! - [`timestamp::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! - [`Module`](./struct.Module.html) -//! -//! ## Overview -//! -//! The Timestamp module allows the validators to set and validate a timestamp with 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 number based time measurement can cause issues -//! because of cumulative calculation errors and hence should be avoided. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! * `set` - Sets the current time. -//! -//! ### Public functions -//! -//! * `get` - Gets the current time for the current block. If this function is called prior to -//! setting the timestamp, it will return the timestamp of the previous block. -//! -//! ### Trait Getters -//! -//! * `MinimumPeriod` - 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 into your custom module and derive the module configuration -//! trait from the timestamp trait. -//! -//! ### Get current timestamp -//! -//! ``` -//! use support::{decl_module, dispatch::Result}; -//! # use srml_timestamp as timestamp; -//! 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(()) -//! } -//! } -//! } -//! # fn main() {} -//! ``` -//! -//! ### Example from the 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 -//! -//! * [Session](../srml_session/index.html) - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::{result, cmp}; -use codec::Encode; -#[cfg(feature = "std")] -use codec::Decode; -#[cfg(feature = "std")] -use inherents::ProvideInherentData; -use support::{Parameter, decl_storage, decl_module}; -use support::traits::{Time, Get}; -use sr_primitives::traits::{ - SimpleArithmetic, Zero, SaturatedConversion, Scale -}; -use sr_primitives::weights::SimpleDispatchInfo; -use system::ensure_none; -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, sr_primitives::RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Decode))] -pub enum InherentError { - /// The timestamp is valid in the future. - /// This is a non-fatal-error and will not stop checking the inherents. - ValidAtTimestamp(InherentType), - /// Some other error. - Other(RuntimeString), -} - -impl IsFatalError for InherentError { - fn is_fatal_error(&self) -> bool { - match self { - InherentError::ValidAtTimestamp(_) => false, - InherentError::Other(_) => true, - } - } -} - -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[..]).ok() - } 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_millis() as u64; - 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. -#[impl_trait_for_tuples::impl_for_tuples(30)] -pub trait OnTimestampSet { - fn on_timestamp_set(moment: Moment); -} - -/// The module configuration trait -pub trait Trait: system::Trait { - /// Type used for expressing timestamp. - type Moment: Parameter + Default + SimpleArithmetic - + Scale + Copy; - - /// Something which can be notified when the timestamp is set. Set this to `()` if not needed. - type OnTimestampSet: OnTimestampSet; - - /// The minimum period between blocks. Beware that this is different to the *expected* period - /// that the block production apparatus provides. Your chosen consensus system will generally - /// work with this to determine a sensible block time. e.g. For Aura, it will be double this - /// period on default settings. - type MinimumPeriod: Get; -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// The minimum period between blocks. Beware that this is different to the *expected* period - /// that the block production apparatus provides. Your chosen consensus system will generally - /// work with this to determine a sensible block time. e.g. For Aura, it will be double this - /// period on default settings. - const MinimumPeriod: T::Moment = T::MinimumPeriod::get(); - - /// Set the current time. - /// - /// 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 - /// `MinimumPeriod`. - /// - /// The dispatch origin for this call must be `Inherent`. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set(origin, #[compact] now: T::Moment) { - ensure_none(origin)?; - assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); - assert!( - Self::now().is_zero() || now >= Self::now() + T::MinimumPeriod::get(), - "Timestamp must increment by at least between sequential blocks" - ); - ::Now::put(now); - ::DidUpdate::put(true); - - >::on_timestamp_set(now); - } - - fn on_finalize() { - assert!(::DidUpdate::take(), "Timestamp must be updated once in the block"); - } - } -} - -decl_storage! { - trait Store for Module as Timestamp { - /// Current time for the current block. - pub Now get(fn now) build(|_| 0.into()): T::Moment; - - /// Did the timestamp get updated in this block? - DidUpdate: bool; - } -} - -impl Module { - /// Get the current time for the current block. - /// - /// 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() - } - - /// Set the timestamp to something in particular. Only used for tests. - #[cfg(feature = "std")] - pub fn set_timestamp(now: T::Moment) { - ::Now::put(now); - } -} - -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 Call = Call; - type Error = InherentError; - const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; - - fn create_inherent(data: &InherentData) -> Option { - let data: T::Moment = extract_inherent_data(data) - .expect("Gets and decodes timestamp inherent data") - .saturated_into(); - - let next_time = cmp::max(data, Self::now() + T::MinimumPeriod::get()); - Some(Call::set(next_time.into())) - } - - fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> { - const MAX_TIMESTAMP_DRIFT: u64 = 60; - - let t: u64 = match call { - Call::set(ref t) => t.clone().saturated_into::(), - _ => return Ok(()), - }; - - let data = extract_inherent_data(data).map_err(|e| InherentError::Other(e))?; - - let minimum = (Self::now() + T::MinimumPeriod::get()).saturated_into::(); - if t > data + MAX_TIMESTAMP_DRIFT { - Err(InherentError::Other("Timestamp too far in future to accept".into())) - } else if t < minimum { - Err(InherentError::ValidAtTimestamp(minimum)) - } else { - Ok(()) - } - } -} - -impl Time for Module { - type Moment = T::Moment; - - /// Before the first set of now with inherent the value returned is zero. - fn now() -> Self::Moment { - Self::now() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use support::{impl_outer_origin, assert_ok, parameter_types}; - use runtime_io::TestExternalities; - use primitives::H256; - use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - parameter_types! { - pub const MinimumPeriod: u64 = 5; - } - impl Trait for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; - } - type Timestamp = Module; - - #[test] - fn timestamp_works() { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { - Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); - assert_eq!(Timestamp::now(), 69); - }); - } - - #[test] - #[should_panic(expected = "Timestamp must be updated only once in the block")] - fn double_timestamp_should_fail() { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { - Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); - let _ = Timestamp::dispatch(Call::set(70), Origin::NONE); - }); - } - - #[test] - #[should_panic(expected = "Timestamp must increment by at least between sequential blocks")] - fn block_period_minimum_enforced() { - let t = system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t).execute_with(|| { - Timestamp::set_timestamp(42); - let _ = Timestamp::dispatch(Call::set(46), Origin::NONE); - }); - } -} diff --git a/srml/transaction-payment/Cargo.toml b/srml/transaction-payment/Cargo.toml deleted file mode 100644 index 7f8eddab19d98..0000000000000 --- a/srml/transaction-payment/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "srml-transaction-payment" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -runtime-io = { package = "sr-io", path = "../../core/sr-io" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -balances = { package = "srml-balances", path = "../balances" } - -[features] -default = ["std"] -std = [ - "codec/std", - "rstd/std", - "sr-primitives/std", - "support/std", - "system/std", -] diff --git a/srml/transaction-payment/src/lib.rs b/srml/transaction-payment/src/lib.rs deleted file mode 100644 index 5ad5c650af8a0..0000000000000 --- a/srml/transaction-payment/src/lib.rs +++ /dev/null @@ -1,457 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Transaction Payment Module -//! -//! This module provides the basic logic needed to pay the absolute minimum amount needed for a -//! transaction to be included. This includes: -//! - _weight fee_: A fee proportional to amount of weight a transaction consumes. -//! - _length fee_: A fee proportional to the encoded length of the transaction. -//! - _tip_: An optional tip. Tip increases the priority of the transaction, giving it a higher -//! chance to be included by the transaction queue. -//! -//! Additionally, this module allows one to configure: -//! - The mapping between one unit of weight to one unit of fee via [`WeightToFee`]. -//! - A means of updating the fee for the next block, via defining a multiplier, based on the -//! final state of the chain at the end of the previous block. This can be configured via -//! [`FeeMultiplierUpdate`] - -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::prelude::*; -use codec::{Encode, Decode}; -use support::{ - decl_storage, decl_module, - traits::{Currency, Get, OnUnbalanced, ExistenceRequirement, WithdrawReason}, -}; -use sr_primitives::{ - Fixed64, - transaction_validity::{ - TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError, - TransactionValidity, - }, - traits::{Zero, Saturating, SignedExtension, SaturatedConversion, Convert}, - weights::{Weight, DispatchInfo}, -}; - -type Multiplier = Fixed64; -type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; -type NegativeImbalanceOf = - <::Currency as Currency<::AccountId>>::NegativeImbalance; - -pub trait Trait: system::Trait { - /// The currency type in which fees will be paid. - type Currency: Currency; - - /// Handler for the unbalanced reduction when taking transaction fees. - type OnTransactionPayment: OnUnbalanced>; - - /// The fee to be paid for making a transaction; the base. - type TransactionBaseFee: Get>; - - /// The fee to be paid for making a transaction; the per-byte portion. - type TransactionByteFee: Get>; - - /// Convert a weight value into a deductible fee based on the currency type. - type WeightToFee: Convert>; - - /// Update the multiplier of the next block, based on the previous block's weight. - type FeeMultiplierUpdate: Convert; -} - -decl_storage! { - trait Store for Module as Balances { - NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::from_parts(0); - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// The fee to be paid for making a transaction; the base. - const TransactionBaseFee: BalanceOf = T::TransactionBaseFee::get(); - - /// The fee to be paid for making a transaction; the per-byte portion. - const TransactionByteFee: BalanceOf = T::TransactionByteFee::get(); - - fn on_finalize() { - NextFeeMultiplier::mutate(|fm| { - *fm = T::FeeMultiplierUpdate::convert(*fm) - }); - } - } -} - -impl Module {} - -/// Require the transactor pay for themselves and maybe include a tip to gain additional priority -/// in the queue. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct ChargeTransactionPayment(#[codec(compact)] BalanceOf); - -impl ChargeTransactionPayment { - /// utility constructor. Used only in client/factory code. - pub fn from(fee: BalanceOf) -> Self { - Self(fee) - } - - /// Compute the final fee value for a particular transaction. - /// - /// The final fee is composed of: - /// - _length-fee_: This is the amount paid merely to pay for size of the transaction. - /// - _weight-fee_: This amount is computed based on the weight of the transaction. Unlike - /// size-fee, this is not input dependent and reflects the _complexity_ of the execution - /// and the time it consumes. - /// - (optional) _tip_: if included in the transaction, it will be added on top. Only signed - /// transactions can have a tip. - fn compute_fee(len: usize, info: DispatchInfo, tip: BalanceOf) -> BalanceOf { - let len_fee = if info.pay_length_fee() { - let len = >::from(len as u32); - let base = T::TransactionBaseFee::get(); - let per_byte = T::TransactionByteFee::get(); - base.saturating_add(per_byte.saturating_mul(len)) - } else { - Zero::zero() - }; - - let weight_fee = { - // cap the weight to the maximum defined in runtime, otherwise it will be the `Bounded` - // maximum of its data type, which is not desired. - let capped_weight = info.weight.min(::MaximumBlockWeight::get()); - T::WeightToFee::convert(capped_weight) - }; - - // everything except for tip - let basic_fee = len_fee.saturating_add(weight_fee); - let fee_update = NextFeeMultiplier::get(); - let adjusted_fee = fee_update.saturated_multiply_accumulate(basic_fee); - - adjusted_fee.saturating_add(tip) - } -} - -impl rstd::fmt::Debug for ChargeTransactionPayment { - #[cfg(feature = "std")] - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "ChargeTransactionPayment<{:?}>", self.0) - } - #[cfg(not(feature = "std"))] - fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - Ok(()) - } -} - -impl SignedExtension for ChargeTransactionPayment - where BalanceOf: Send + Sync -{ - type AccountId = T::AccountId; - type Call = T::Call; - type AdditionalSigned = (); - type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } - - fn validate( - &self, - who: &Self::AccountId, - _call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> TransactionValidity { - // pay any fees. - let fee = Self::compute_fee(len, info, self.0); - let imbalance = match T::Currency::withdraw( - who, - fee, - WithdrawReason::TransactionPayment, - ExistenceRequirement::KeepAlive, - ) { - Ok(imbalance) => imbalance, - Err(_) => return InvalidTransaction::Payment.into(), - }; - T::OnTransactionPayment::on_unbalanced(imbalance); - - let mut r = ValidTransaction::default(); - // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which - // will be a bit more than setting the priority to tip. For now, this is enough. - r.priority = fee.saturated_into::(); - Ok(r) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use support::{parameter_types, impl_outer_origin}; - use primitives::H256; - use sr_primitives::{ - Perbill, - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - weights::DispatchClass, - }; - use rstd::cell::RefCell; - - const CALL: &::Call = &(); - - #[derive(Clone, PartialEq, Eq, Debug)] - pub struct Runtime; - - impl_outer_origin!{ - pub enum Origin for Runtime {} - } - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl system::Trait for Runtime { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - - parameter_types! { - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - pub const ExistentialDeposit: u64 = 0; - } - - impl balances::Trait for Runtime { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - - thread_local! { - static TRANSACTION_BASE_FEE: RefCell = RefCell::new(0); - static TRANSACTION_BYTE_FEE: RefCell = RefCell::new(1); - static WEIGHT_TO_FEE: RefCell = RefCell::new(1); - } - - pub struct TransactionBaseFee; - impl Get for TransactionBaseFee { - fn get() -> u64 { TRANSACTION_BASE_FEE.with(|v| *v.borrow()) } - } - - pub struct TransactionByteFee; - impl Get for TransactionByteFee { - fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) } - } - - pub struct WeightToFee(u64); - impl Convert for WeightToFee { - fn convert(t: Weight) -> u64 { - WEIGHT_TO_FEE.with(|v| *v.borrow() * (t as u64)) - } - } - - impl Trait for Runtime { - type Currency = balances::Module; - type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = WeightToFee; - type FeeMultiplierUpdate = (); - } - - type Balances = balances::Module; - - pub struct ExtBuilder { - balance_factor: u64, - base_fee: u64, - byte_fee: u64, - weight_to_fee: u64 - } - - impl Default for ExtBuilder { - fn default() -> Self { - Self { - balance_factor: 1, - base_fee: 0, - byte_fee: 1, - weight_to_fee: 1, - } - } - } - - impl ExtBuilder { - pub fn fees(mut self, base: u64, byte: u64, weight: u64) -> Self { - self.base_fee = base; - self.byte_fee = byte; - self.weight_to_fee = weight; - self - } - pub fn balance_factor(mut self, factor: u64) -> Self { - self.balance_factor = factor; - self - } - fn set_constants(&self) { - TRANSACTION_BASE_FEE.with(|v| *v.borrow_mut() = self.base_fee); - TRANSACTION_BYTE_FEE.with(|v| *v.borrow_mut() = self.byte_fee); - WEIGHT_TO_FEE.with(|v| *v.borrow_mut() = self.weight_to_fee); - } - pub fn build(self) -> runtime_io::TestExternalities { - self.set_constants(); - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig:: { - balances: vec![ - (1, 10 * self.balance_factor), - (2, 20 * self.balance_factor), - (3, 30 * self.balance_factor), - (4, 40 * self.balance_factor), - (5, 50 * self.balance_factor), - (6, 60 * self.balance_factor) - ], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - t.into() - } - } - - /// create a transaction info struct from weight. Handy to avoid building the whole struct. - pub fn info_from_weight(w: Weight) -> DispatchInfo { - DispatchInfo { weight: w, ..Default::default() } - } - - #[test] - fn signed_extension_transaction_payment_work() { - ExtBuilder::default() - .balance_factor(10) // 100 - .fees(5, 1, 1) // 5 fixed, 1 per byte, 1 per weight - .build() - .execute_with(|| - { - let len = 10; - assert!( - ChargeTransactionPayment::::from(0) - .pre_dispatch(&1, CALL, info_from_weight(5), len) - .is_ok() - ); - assert_eq!(Balances::free_balance(&1), 100 - 5 - 5 - 10); - - assert!( - ChargeTransactionPayment::::from(5 /* tipped */) - .pre_dispatch(&2, CALL, info_from_weight(3), len) - .is_ok() - ); - assert_eq!(Balances::free_balance(&2), 200 - 5 - 10 - 3 - 5); - }); - } - - #[test] - fn signed_extension_transaction_payment_is_bounded() { - ExtBuilder::default() - .balance_factor(1000) - .fees(0, 0, 1) - .build() - .execute_with(|| - { - use sr_primitives::weights::Weight; - - // maximum weight possible - assert!( - ChargeTransactionPayment::::from(0) - .pre_dispatch(&1, CALL, info_from_weight(Weight::max_value()), 10) - .is_ok() - ); - // fee will be proportional to what is the actual maximum weight in the runtime. - assert_eq!( - Balances::free_balance(&1), - (10000 - ::MaximumBlockWeight::get()) as u64 - ); - }); - } - - #[test] - fn signed_extension_allows_free_transactions() { - ExtBuilder::default() - .fees(100, 1, 1) - .balance_factor(0) - .build() - .execute_with(|| - { - // 1 ain't have a penny. - assert_eq!(Balances::free_balance(&1), 0); - - // like a FreeOperational - let operational_transaction = DispatchInfo { - weight: 0, - class: DispatchClass::Operational - }; - let len = 100; - assert!( - ChargeTransactionPayment::::from(0) - .validate(&1, CALL, operational_transaction , len) - .is_ok() - ); - - // like a FreeNormal - let free_transaction = DispatchInfo { - weight: 0, - class: DispatchClass::Normal - }; - assert!( - ChargeTransactionPayment::::from(0) - .validate(&1, CALL, free_transaction , len) - .is_err() - ); - }); - } - - #[test] - fn signed_ext_length_fee_is_also_updated_per_congestion() { - ExtBuilder::default() - .fees(5, 1, 1) - .balance_factor(10) - .build() - .execute_with(|| - { - // all fees should be x1.5 - NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); - let len = 10; - - assert!( - ChargeTransactionPayment::::from(10) // tipped - .pre_dispatch(&1, CALL, info_from_weight(3), len) - .is_ok() - ); - assert_eq!(Balances::free_balance(&1), 100 - 10 - (5 + 10 + 3) * 3 / 2); - }) - } -} - - diff --git a/srml/treasury/Cargo.toml b/srml/treasury/Cargo.toml deleted file mode 100644 index f19fa2c2188eb..0000000000000 --- a/srml/treasury/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "srml-treasury" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -balances = { package = "srml-balances", path = "../balances", default-features = false } - -[dev-dependencies] -runtime-io ={ package = "sr-io", path = "../../core/sr-io" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "rstd/std", - "sr-primitives/std", - "support/std", - "system/std", - "balances/std", -] diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs deleted file mode 100644 index 668dcaca322df..0000000000000 --- a/srml/treasury/src/lib.rs +++ /dev/null @@ -1,698 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Treasury Module -//! -//! The Treasury module provides a "pot" of funds that can be managed by stakeholders in the -//! system and a structure for making spending proposals from this pot. -//! -//! - [`treasury::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! -//! ## Overview -//! -//! The Treasury Module itself provides the pot to store funds, and a means for stakeholders to -//! propose, approve, and deny expendatures. The chain will need to provide a method (e.g. -//! inflation, fees) for collecting funds. -//! -//! By way of example, the Council could vote to fund the Treasury with a portion of the block -//! reward and use the funds to pay developers. -//! -//! ### Terminology -//! -//! - **Proposal:** A suggestion to allocate funds from the pot to a beneficiary. -//! - **Beneficiary:** An account who will receive the funds from a proposal iff -//! the proposal is approved. -//! - **Deposit:** Funds that a proposer must lock when making a proposal. The -//! deposit will be returned or slashed if the proposal is approved or rejected -//! respectively. -//! - **Pot:** Unspent funds accumulated by the treasury module. -//! -//! ### Implementations -//! -//! The treasury module provides an implementation for the following trait: -//! -//! - `OnDilution` - When new funds are minted to reward the deployment of other existing funds, -//! a corresponding amount of tokens are minted into the treasury so that the tokens being rewarded -//! do not represent a higher portion of total supply. For example, in the default substrate node, -//! when validators are rewarded new tokens for staking, they do not hold a higher portion of total -//! tokens. Rather, tokens are added to the treasury to keep the portion of tokens staked constant. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! - `propose_spend` - Make a spending proposal and stake the required deposit. -//! - `set_pot` - Set the spendable balance of funds. -//! - `configure` - Configure the module's proposal requirements. -//! - `reject_proposal` - Reject a proposal, slashing the deposit. -//! - `approve_proposal` - Accept the proposal, returning the deposit. -//! -//! ## GenesisConfig -//! -//! The Treasury module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -use rstd::prelude::*; -use support::{decl_module, decl_storage, decl_event, ensure, print}; -use support::traits::{ - Currency, ExistenceRequirement, Get, Imbalance, OnDilution, OnUnbalanced, - ReservableCurrency, WithdrawReason -}; -use sr_primitives::{Permill, Perbill, ModuleId}; -use sr_primitives::traits::{ - Zero, EnsureOrigin, StaticLookup, AccountIdConversion, CheckedSub, Saturating -}; -use sr_primitives::weights::SimpleDispatchInfo; -use codec::{Encode, Decode}; -use system::ensure_signed; - -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -type PositiveImbalanceOf = <::Currency as Currency<::AccountId>>::PositiveImbalance; -type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; - -const MODULE_ID: ModuleId = ModuleId(*b"py/trsry"); - -pub trait Trait: system::Trait { - /// The staking balance. - type Currency: Currency + ReservableCurrency; - - /// Origin from which approvals must come. - type ApproveOrigin: EnsureOrigin; - - /// Origin from which rejections must come. - type RejectOrigin: EnsureOrigin; - - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// Handler for the unbalanced decrease when slashing for a rejected proposal. - type ProposalRejection: OnUnbalanced>; - - /// Fraction of a proposal's value that should be bonded in order to place the proposal. - /// An accepted proposal gets these back. A rejected proposal does not. - type ProposalBond: Get; - - /// Minimum amount of funds that should be placed in a deposit for making a proposal. - type ProposalBondMinimum: Get>; - - /// Period between successive spends. - type SpendPeriod: Get; - - /// Percentage of spare funds (if any) that are burnt per spend period. - type Burn: Get; -} - -type ProposalIndex = u32; - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// Fraction of a proposal's value that should be bonded in order to place the proposal. - /// An accepted proposal gets these back. A rejected proposal does not. - const ProposalBond: Permill = T::ProposalBond::get(); - - /// Minimum amount of funds that should be placed in a deposit for making a proposal. - const ProposalBondMinimum: BalanceOf = T::ProposalBondMinimum::get(); - - /// Period between successive spends. - const SpendPeriod: T::BlockNumber = T::SpendPeriod::get(); - - /// Percentage of spare funds (if any) that are burnt per spend period. - const Burn: Permill = T::Burn::get(); - - 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. - /// - /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB change, one extra DB entry. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn propose_spend( - origin, - #[compact] value: BalanceOf, - beneficiary: ::Source - ) { - let proposer = ensure_signed(origin)?; - let beneficiary = T::Lookup::lookup(beneficiary)?; - - let bond = Self::calculate_bond(value); - T::Currency::reserve(&proposer, bond) - .map_err(|_| "Proposer's balance too low")?; - - let c = Self::proposal_count(); - ProposalCount::put(c + 1); - >::insert(c, Proposal { proposer, value, beneficiary, bond }); - - Self::deposit_event(RawEvent::Proposed(c)); - } - - /// Reject a proposed spend. The original deposit will be slashed. - /// - /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB clear. - /// # - #[weight = SimpleDispatchInfo::FixedOperational(100_000)] - fn reject_proposal(origin, #[compact] proposal_id: ProposalIndex) { - T::RejectOrigin::ensure_origin(origin)?; - let proposal = >::take(proposal_id).ok_or("No proposal at that index")?; - - let value = proposal.bond; - let imbalance = T::Currency::slash_reserved(&proposal.proposer, value).0; - T::ProposalRejection::on_unbalanced(imbalance); - } - - /// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary - /// and the original deposit will be returned. - /// - /// # - /// - O(1). - /// - Limited storage reads. - /// - One DB change. - /// # - #[weight = SimpleDispatchInfo::FixedOperational(100_000)] - fn approve_proposal(origin, #[compact] proposal_id: ProposalIndex) { - T::ApproveOrigin::ensure_origin(origin)?; - - ensure!(>::exists(proposal_id), "No proposal at that index"); - - Approvals::mutate(|v| v.push(proposal_id)); - } - - fn on_finalize(n: T::BlockNumber) { - // Check to see if we should spend some funds! - if (n % T::SpendPeriod::get()).is_zero() { - Self::spend_funds(); - } - } - } -} - -/// A spending proposal. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Encode, Decode, Clone, PartialEq, Eq, sr_primitives::RuntimeDebug)] -pub struct Proposal { - proposer: AccountId, - value: Balance, - beneficiary: AccountId, - bond: Balance, -} - -decl_storage! { - trait Store for Module as Treasury { - /// Number of proposals that have been made. - ProposalCount get(fn proposal_count): ProposalIndex; - - /// Proposals that have been made. - Proposals get(fn proposals): map ProposalIndex => Option>>; - - /// Proposal indices that have been approved but not yet awarded. - Approvals get(fn approvals): Vec; - } - add_extra_genesis { - build(|_config| { - // Create Treasury account - let _ = T::Currency::make_free_balance_be( - &>::account_id(), - T::Currency::minimum_balance(), - ); - }); - } -} - -decl_event!( - pub enum Event - where - Balance = BalanceOf, - ::AccountId - { - /// New proposal. - Proposed(ProposalIndex), - /// We have ended a spend period and will now allocate funds. - Spending(Balance), - /// Some funds have been allocated. - Awarded(ProposalIndex, Balance, AccountId), - /// Some of our funds have been burnt. - Burnt(Balance), - /// Spending has finished; this is the amount that rolls over until next spend. - Rollover(Balance), - } -); - -impl Module { - // Add public immutables and private mutables. - - /// The account ID of the treasury pot. - /// - /// This actually does computation. If you need to keep using it, then make sure you cache the - /// value and only call this once. - pub fn account_id() -> T::AccountId { - MODULE_ID.into_account() - } - - /// The needed bond for a proposal whose spend is `value`. - fn calculate_bond(value: BalanceOf) -> BalanceOf { - T::ProposalBondMinimum::get().max(T::ProposalBond::get() * value) - } - - // Spend some money! - fn spend_funds() { - let mut budget_remaining = Self::pot(); - Self::deposit_event(RawEvent::Spending(budget_remaining)); - - let mut missed_any = false; - let mut imbalance = >::zero(); - Approvals::mutate(|v| { - v.retain(|&index| { - // Should always be true, but shouldn't panic if false or we're screwed. - if let Some(p) = Self::proposals(index) { - if p.value <= budget_remaining { - budget_remaining -= p.value; - >::remove(index); - - // return their deposit. - let _ = T::Currency::unreserve(&p.proposer, p.bond); - - // provide the allocation. - imbalance.subsume(T::Currency::deposit_creating(&p.beneficiary, p.value)); - - Self::deposit_event(RawEvent::Awarded(index, p.value, p.beneficiary)); - false - } else { - missed_any = true; - true - } - } else { - false - } - }); - }); - - if !missed_any { - // burn some proportion of the remaining budget if we run a surplus. - let burn = (T::Burn::get() * budget_remaining).min(budget_remaining); - budget_remaining -= burn; - imbalance.subsume(T::Currency::burn(burn)); - Self::deposit_event(RawEvent::Burnt(burn)) - } - - // Must never be an error, but better to be safe. - // proof: budget_remaining is account free balance minus ED; - // Thus we can't spend more than account free balance minus ED; - // Thus account is kept alive; qed; - if let Err(problem) = T::Currency::settle( - &Self::account_id(), - imbalance, - WithdrawReason::Transfer, - ExistenceRequirement::KeepAlive - ) { - print("Inconsistent state - couldn't settle imbalance for funds spent by treasury"); - // Nothing else to do here. - drop(problem); - } - - Self::deposit_event(RawEvent::Rollover(budget_remaining)); - } - - /// Return the amount of money in the pot. - // The existential deposit is not part of the pot so treasury account never gets deleted. - fn pot() -> BalanceOf { - T::Currency::free_balance(&Self::account_id()) - // Must never be less than 0 but better be safe. - .saturating_sub(T::Currency::minimum_balance()) - } -} - -impl OnUnbalanced> for Module { - fn on_unbalanced(amount: NegativeImbalanceOf) { - // Must resolve into existing but better to be safe. - let _ = T::Currency::resolve_creating(&Self::account_id(), amount); - } -} - -/// Mint extra funds for the treasury to keep the ratio of portion to total_issuance equal -/// pre dilution and post-dilution. -/// -/// i.e. -/// ```nocompile -/// portion / total_issuance_before_dilution == -/// (portion + minted) / (total_issuance_before_dilution + minted_to_treasury + minted) -/// ``` -impl OnDilution> for Module { - fn on_dilution(minted: BalanceOf, portion: BalanceOf) { - if !minted.is_zero() && !portion.is_zero() { - let total_issuance = T::Currency::total_issuance(); - if let Some(funding) = total_issuance.checked_sub(&portion) { - let increase_ratio = Perbill::from_rational_approximation(minted, portion); - let funding = increase_ratio * funding; - Self::on_unbalanced(T::Currency::issue(funding)); - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use support::{assert_noop, assert_ok, impl_outer_origin, parameter_types}; - use primitives::H256; - use sr_primitives::{ - traits::{BlakeTwo256, OnFinalize, IdentityLookup}, testing::Header, assert_eq_error_rate, - }; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; - type Version = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - } - impl balances::Trait for Test { - type Balance = u64; - type OnNewAccount = (); - type OnFreeBalanceZero = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - parameter_types! { - pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: u64 = 1; - pub const SpendPeriod: u64 = 2; - pub const Burn: Permill = Permill::from_percent(50); - } - impl Trait for Test { - type Currency = balances::Module; - type ApproveOrigin = system::EnsureRoot; - type RejectOrigin = system::EnsureRoot; - type Event = (); - type ProposalRejection = (); - type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; - type SpendPeriod = SpendPeriod; - type Burn = Burn; - } - type Balances = balances::Module; - type Treasury = Module; - - fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig::{ - // Total issuance will be 200 with treasury account initialized at ED. - balances: vec![(0, 100), (1, 98), (2, 1)], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - GenesisConfig::default().assimilate_storage::(&mut t).unwrap(); - t.into() - } - - #[test] - fn genesis_config_works() { - new_test_ext().execute_with(|| { - assert_eq!(Treasury::pot(), 0); - assert_eq!(Treasury::proposal_count(), 0); - }); - } - - #[test] - fn minting_works() { - new_test_ext().execute_with(|| { - // Check that accumulate works when we have Some value in Dummy already. - Treasury::on_dilution(100, 100); - assert_eq!(Treasury::pot(), 100); - }); - } - - #[test] - fn minting_works_2() { - let tests = [(1, 10), (1, 20), (40, 130), (2, 66), (2, 67), (2, 100), (2, 101), (2, 134)]; - for &(minted, portion) in &tests { - new_test_ext().execute_with(|| { - let init_total_issuance = Balances::total_issuance(); - Treasury::on_dilution(minted, portion); - - assert_eq!( - Treasury::pot(), - (((init_total_issuance - portion) * minted) as f32 / portion as f32) - .round() as u64 - ); - - // Assert: - // portion / init_total_issuance - // == (portion + minted) / (init_total_issuance + Treasury::pot() + minted), - assert_eq_error_rate!( - portion * 1_000 / init_total_issuance, - (portion + minted) * 1_000 / (init_total_issuance + Treasury::pot() + minted), - 2, - ); - }); - } - } - - #[test] - fn spend_proposal_takes_min_deposit() { - new_test_ext().execute_with(|| { - assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); - assert_eq!(Balances::free_balance(&0), 99); - assert_eq!(Balances::reserved_balance(&0), 1); - }); - } - - #[test] - fn spend_proposal_takes_proportional_deposit() { - new_test_ext().execute_with(|| { - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); - assert_eq!(Balances::free_balance(&0), 95); - assert_eq!(Balances::reserved_balance(&0), 5); - }); - } - - #[test] - fn spend_proposal_fails_when_proposer_poor() { - new_test_ext().execute_with(|| { - assert_noop!(Treasury::propose_spend(Origin::signed(2), 100, 3), "Proposer's balance too low"); - }); - } - - #[test] - fn accepted_spend_proposal_ignored_outside_spend_period() { - new_test_ext().execute_with(|| { - Treasury::on_dilution(100, 100); - - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); - - >::on_finalize(1); - assert_eq!(Balances::free_balance(&3), 0); - assert_eq!(Treasury::pot(), 100); - }); - } - - #[test] - fn unused_pot_should_diminish() { - new_test_ext().execute_with(|| { - let init_total_issuance = Balances::total_issuance(); - Treasury::on_dilution(100, 100); - assert_eq!(Balances::total_issuance(), init_total_issuance + 100); - - >::on_finalize(2); - assert_eq!(Treasury::pot(), 50); - assert_eq!(Balances::total_issuance(), init_total_issuance + 50); - }); - } - - #[test] - fn rejected_spend_proposal_ignored_on_spend_period() { - new_test_ext().execute_with(|| { - Treasury::on_dilution(100, 100); - - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); - assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); - - >::on_finalize(2); - assert_eq!(Balances::free_balance(&3), 0); - assert_eq!(Treasury::pot(), 50); - }); - } - - #[test] - fn reject_already_rejected_spend_proposal_fails() { - new_test_ext().execute_with(|| { - Treasury::on_dilution(100, 100); - - 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() { - new_test_ext().execute_with(|| { - assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), "No proposal at that index"); - }); - } - - #[test] - fn accept_non_existant_spend_proposal_fails() { - new_test_ext().execute_with(|| { - assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), "No proposal at that index"); - }); - } - - #[test] - fn accept_already_rejected_spend_proposal_fails() { - new_test_ext().execute_with(|| { - Treasury::on_dilution(100, 100); - - 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"); - }); - } - - #[test] - fn accepted_spend_proposal_enacted_on_spend_period() { - new_test_ext().execute_with(|| { - Treasury::on_dilution(100, 100); - assert_eq!(Treasury::pot(), 100); - - assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); - - >::on_finalize(2); - assert_eq!(Balances::free_balance(&3), 100); - assert_eq!(Treasury::pot(), 0); - }); - } - - #[test] - fn pot_underflow_should_not_diminish() { - new_test_ext().execute_with(|| { - Treasury::on_dilution(100, 100); - assert_eq!(Treasury::pot(), 100); - - assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); - - >::on_finalize(2); - assert_eq!(Treasury::pot(), 100); // Pot hasn't changed - - Treasury::on_dilution(100, 100); - >::on_finalize(4); - assert_eq!(Balances::free_balance(&3), 150); // Fund has been spent - assert_eq!(Treasury::pot(), 75); // Pot has finally changed - }); - } - - // Treasury account doesn't get deleted if amount approved to spend is all its free balance. - // i.e. pot should not include existential deposit needed for account survival. - #[test] - fn treasury_account_doesnt_get_deleted() { - new_test_ext().execute_with(|| { - Treasury::on_dilution(100, 100); - assert_eq!(Treasury::pot(), 100); - let treasury_balance = Balances::free_balance(&Treasury::account_id()); - - assert_ok!(Treasury::propose_spend(Origin::signed(0), treasury_balance, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); - - >::on_finalize(2); - assert_eq!(Treasury::pot(), 100); // Pot hasn't changed - - assert_ok!(Treasury::propose_spend(Origin::signed(0), Treasury::pot(), 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); - - >::on_finalize(4); - assert_eq!(Treasury::pot(), 0); // Pot is emptied - assert_eq!(Balances::free_balance(&Treasury::account_id()), 1); // but the account is still there - }); - } - - // In case treasury account is not existing then it works fine. - // This is usefull for chain that will just update runtime. - #[test] - fn inexisting_account_works() { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig::{ - balances: vec![(0, 100), (1, 99), (2, 1)], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - // Treasury genesis config is not build thus treasury account does not exist - let mut t: runtime_io::TestExternalities = t.into(); - - t.execute_with(|| { - assert_eq!(Balances::free_balance(&Treasury::account_id()), 0); // Account does not exist - assert_eq!(Treasury::pot(), 0); // Pot is empty - - assert_ok!(Treasury::propose_spend(Origin::signed(0), 99, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); - assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); - assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); - >::on_finalize(2); - assert_eq!(Treasury::pot(), 0); // Pot hasn't changed - assert_eq!(Balances::free_balance(&3), 0); // Balance of `3` hasn't changed - - Treasury::on_dilution(100, 100); - assert_eq!(Treasury::pot(), 99); // Pot now contains funds - assert_eq!(Balances::free_balance(&Treasury::account_id()), 100); // Account does exist - - >::on_finalize(4); - - assert_eq!(Treasury::pot(), 0); // Pot has changed - assert_eq!(Balances::free_balance(&3), 99); // Balance of `3` has changed - }); - } -} diff --git a/srml/utility/Cargo.toml b/srml/utility/Cargo.toml deleted file mode 100644 index 5e92bcf88ad48..0000000000000 --- a/srml/utility/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "srml-utility" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -support = { package = "srml-support", path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } - -[dev-dependencies] -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -balances = { package = "srml-balances", path = "../balances" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "sr-primitives/std", - "support/std", - "system/std", - "runtime-io/std", - "rstd/std" -] diff --git a/srml/utility/src/lib.rs b/srml/utility/src/lib.rs deleted file mode 100644 index d69e260ff9aac..0000000000000 --- a/srml/utility/src/lib.rs +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! # Utility Module -//! A module full of useful helpers for practical chain management. - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -use rstd::prelude::*; -use support::{decl_module, decl_event, Parameter}; -use system::ensure_root; -use sr_primitives::{traits::Dispatchable, weights::SimpleDispatchInfo, DispatchError}; - -/// Configuration trait. -pub trait Trait: system::Trait { - /// The overarching event type. - type Event: From + Into<::Event>; - - /// The overarching call type. - type Call: Parameter + Dispatchable; -} - -decl_event!( - /// Events type. - pub enum Event { - BatchExecuted(Vec>), - } -); - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// Deposit one of this module's events by using the default implementation. - fn deposit_event() = default; - - /// Send a batch of dispatch calls (only root). - #[weight = SimpleDispatchInfo::FreeOperational] - fn batch(origin, calls: Vec<::Call>) { - ensure_root(origin)?; - let results = calls.into_iter() - .map(|call| call.dispatch(system::RawOrigin::Root.into())) - .map(|res| res.map_err(Into::into)) - .collect::>(); - Self::deposit_event(Event::BatchExecuted(results)); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use support::{assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch}; - use primitives::H256; - use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; - - impl_outer_origin! { - pub enum Origin for Test {} - } - - impl_outer_dispatch! { - pub enum Call for Test where origin: Origin { - balances::Balances, - utility::Utility, - } - } - - // For testing the module, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of modules we want to use. - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = Call; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - } - impl balances::Trait for Test { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - impl Trait for Test { - type Event = (); - type Call = Call; - } - type Balances = balances::Module; - type Utility = Module; - - fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig:: { - balances: vec![(1, 10), (2, 0)], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - t.into() - } - - #[test] - fn batch_works() { - new_test_ext().execute_with(|| { - assert_eq!(Balances::free_balance(1), 10); - assert_eq!(Balances::free_balance(2), 0); - assert_noop!(Utility::batch(Origin::signed(1), vec![ - Call::Balances(balances::Call::force_transfer(1, 2, 5)), - Call::Balances(balances::Call::force_transfer(1, 2, 5)) - ]), "RequireRootOrigin"); - assert_ok!(Utility::batch(Origin::ROOT, vec![ - Call::Balances(balances::Call::force_transfer(1, 2, 5)), - Call::Balances(balances::Call::force_transfer(1, 2, 5)) - ])); - assert_eq!(Balances::free_balance(1), 0); - assert_eq!(Balances::free_balance(2), 10); - }); - } -} diff --git a/subkey/Cargo.toml b/subkey/Cargo.toml deleted file mode 100644 index e1c3ef64d26d4..0000000000000 --- a/subkey/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "subkey" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -primitives = { package = "substrate-primitives", version = "*", path = "../core/primitives" } -node-runtime = { version = "*", path = "../node/runtime" } -node-primitives = { version = "*", path = "../node/primitives" } -sr-primitives = { version = "*", path = "../core/sr-primitives" } -rand = "0.7.2" -clap = { version = "2.33.0", features = ["yaml"] } -tiny-bip39 = "0.6.2" -rustc-hex = "2.0.1" -substrate-bip39 = "0.3.1" -hex = "0.3.2" -hex-literal = "0.2.1" -codec = { package = "parity-scale-codec", version = "1.0.0" } -system = { package = "srml-system", path = "../srml/system" } -balances = { package = "srml-balances", path = "../srml/balances" } -transaction-payment = { package = "srml-transaction-payment", path = "../srml/transaction-payment" } - -[features] -bench = [] diff --git a/subkey/src/cli.yml b/subkey/src/cli.yml deleted file mode 100644 index 5d8cd11b1e6f8..0000000000000 --- a/subkey/src/cli.yml +++ /dev/null @@ -1,144 +0,0 @@ -name: subkey -author: "Parity Team " -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 - - secp256k1: - short: k - long: secp256k1 - help: Use SECP256k1/ECDSA/BIP39 cryptography - takes_value: false - - password: - short: p - long: password - takes_value: true - required: false - help: The password for the key - - network: - short: n - long: network - takes_value: true - required: false - help: Specify a network. One of substrate (default), polkadot, kusama, or dothereum. -subcommands: - - generate: - about: Generate a random account - args: - - words: - short: w - long: words - help: The number of words in the phrase to generate. One of 12 (default), 15, 18, 21 and 24. - takes_value: true - - inspect: - about: Gets a public key and a SS58 address from the provided Secret URI - args: - - uri: - index: 1 - required: true - 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 - - transfer: - about: Author and sign a Node balances::Transfer transaction with a given (secret) key - args: - - from: - index: 1 - required: true - help: The signing secret key URI. - - to: - index: 2 - required: true - help: The destination account public key URI. - - amount: - index: 3 - required: true - help: The number of units to transfer. - - index: - index: 4 - required: true - help: The signing account's transaction index. - - genesis: - short: g - long: genesis - help: The genesis hash or a recognised chain identifier (dev, elm, alex). - takes_value: true - - 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 a seed that provides a vanity address - args: - - pattern: - index: 1 - help: Desired pattern - - number: - short: n - long: number - help: Number of keys to generate - takes_value: true - default_value: "1" - - sign-transaction: - about: Sign transaction from encoded Call. Returns a signed and encoded UncheckedMortalCompactExtrinsic as hex. - args: - - call: - short: c - long: call - help: The call, hex-encoded. - takes_value: true - required: true - - nonce: - short: n - long: nonce - help: The nonce. - takes_value: true - required: true - - suri: - long: suri - short: s - help: The secret key URI. - takes_value: true - required: true - - password: - short: p - long: password - takes_value: true - help: The password for the key. - required: true - - prior-block-hash: - short: h - long: prior-block-hash - help: The prior block hash, hex-encoded. - takes_value: true - required: true diff --git a/subkey/src/main.rs b/subkey/src/main.rs deleted file mode 100644 index 1b537580f57ff..0000000000000 --- a/subkey/src/main.rs +++ /dev/null @@ -1,534 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -#![cfg_attr(feature = "bench", feature(test))] -#[cfg(feature = "bench")] -extern crate test; - -use bip39::{Language, Mnemonic, MnemonicType}; -use clap::{load_yaml, App, ArgMatches}; -use codec::{Decode, Encode}; -use hex_literal::hex; -use node_primitives::{Balance, Hash, Index, AccountId, Signature}; -use node_runtime::{BalancesCall, Call, Runtime, SignedPayload, UncheckedExtrinsic, VERSION}; -use primitives::{ - crypto::{set_default_ss58_version, Ss58AddressFormat, Ss58Codec}, - ed25519, sr25519, ecdsa, Pair, Public, H256, hexdisplay::HexDisplay, -}; -use sr_primitives::{traits::{IdentifyAccount, Verify}, generic::Era}; -use std::{ - convert::{TryInto, TryFrom}, - io::{stdin, Read}, - str::FromStr, -}; - -mod vanity; - -trait Crypto: Sized { - type Pair: Pair; - type Public: Public + Ss58Codec + AsRef<[u8]> + std::hash::Hash; - fn pair_from_suri(suri: &str, password: Option<&str>) -> Self::Pair { - Self::Pair::from_string(suri, password).expect("Invalid phrase") - } - fn ss58_from_pair(pair: &Self::Pair) -> String where - ::Public: PublicT, - { - pair.public().into_runtime().into_account().to_ss58check() - } - fn public_from_pair(pair: &Self::Pair) -> Self::Public { - pair.public() - } - fn print_from_uri( - uri: &str, - password: Option<&str>, - network_override: Option, - ) where - ::Public: PublicT, - { - if let Ok((pair, seed)) = Self::Pair::from_phrase(uri, password) { - let public_key = Self::public_from_pair(&pair); - println!("Secret phrase `{}` is account:\n \ - Secret seed: {}\n \ - Public key (hex): {}\n \ - Account ID: {}\n \ - SS58 Address: {}", - uri, - format_seed::(seed), - format_public_key::(public_key.clone()), - format_account_id::(public_key), - Self::ss58_from_pair(&pair) - ); - } else if let Ok((pair, seed)) = Self::Pair::from_string_with_seed(uri, password) { - let public_key = Self::public_from_pair(&pair); - println!("Secret Key URI `{}` is account:\n \ - Secret seed: {}\n \ - Public key (hex): {}\n \ - Account ID: {}\n \ - SS58 Address: {}", - uri, - if let Some(seed) = seed { format_seed::(seed) } else { "n/a".into() }, - format_public_key::(public_key.clone()), - format_account_id::(public_key), - Self::ss58_from_pair(&pair) - ); - } else if let Ok((public_key, v)) = - ::Public::from_string_with_version(uri) - { - let v = network_override.unwrap_or(v); - println!("Public Key URI `{}` is account:\n \ - Network ID/version: {}\n \ - Public key (hex): {}\n \ - Account ID: {}\n \ - SS58 Address: {}", - uri, - String::from(v), - format_public_key::(public_key.clone()), - format_account_id::(public_key.clone()), - public_key.to_ss58check_with_version(v) - ); - } else { - println!("Invalid phrase/URI given"); - } - } -} - -struct Ed25519; - -impl Crypto for Ed25519 { - type Pair = ed25519::Pair; - type Public = ed25519::Public; - - fn pair_from_suri(suri: &str, password_override: Option<&str>) -> Self::Pair { - ed25519::Pair::from_legacy_string(suri, password_override) - } -} - -struct Sr25519; - -impl Crypto for Sr25519 { - type Pair = sr25519::Pair; - type Public = sr25519::Public; -} - -struct Ecdsa; - -impl Crypto for Ecdsa { - type Pair = ecdsa::Pair; - type Public = ecdsa::Public; -} - -type SignatureOf = <::Pair as Pair>::Signature; -type PublicOf = <::Pair as Pair>::Public; -type SeedOf = <::Pair as Pair>::Seed; -type AccountPublic = ::Signer; - -trait SignatureT: AsRef<[u8]> + AsMut<[u8]> + Default { - /// Converts the signature into a runtime account signature, if possible. If not possible, bombs out. - fn into_runtime(self) -> Signature { - panic!("This cryptography isn't supported for this runtime.") - } -} -trait PublicT: Sized + AsRef<[u8]> + Ss58Codec { - /// Converts the public key into a runtime account public key, if possible. If not possible, bombs out. - fn into_runtime(self) -> AccountPublic { - panic!("This cryptography isn't supported for this runtime.") - } -} - -impl SignatureT for sr25519::Signature { fn into_runtime(self) -> Signature { self.into() } } -impl SignatureT for ed25519::Signature { fn into_runtime(self) -> Signature { self.into() } } -impl SignatureT for ecdsa::Signature { fn into_runtime(self) -> Signature { self.into() } } -impl PublicT for sr25519::Public { fn into_runtime(self) -> AccountPublic { self.into() } } -impl PublicT for ed25519::Public { fn into_runtime(self) -> AccountPublic { self.into() } } -impl PublicT for ecdsa::Public { fn into_runtime(self) -> AccountPublic { self.into() } } - -fn main() { - let yaml = load_yaml!("cli.yml"); - let matches = App::from_yaml(yaml) - .version(env!("CARGO_PKG_VERSION")) - .get_matches(); - - if matches.is_present("ed25519") { - return execute::(matches) - } - if matches.is_present("secp256k1") { - return execute::(matches) - } - return execute::(matches) -} - -fn execute(matches: ArgMatches) -where - SignatureOf: SignatureT, - PublicOf: PublicT, -{ - let password = matches.value_of("password"); - let maybe_network: Option = matches.value_of("network").map(|network| { - network - .try_into() - .expect("Invalid network name: must be polkadot/substrate/kusama/dothereum") - }); - if let Some(network) = maybe_network { - set_default_ss58_version(network); - } - match matches.subcommand() { - ("generate", Some(matches)) => { - let mnemonic = generate_mnemonic(matches); - C::print_from_uri(mnemonic.phrase(), password, maybe_network); - } - ("inspect", Some(matches)) => { - let uri = matches - .value_of("uri") - .expect("URI parameter is required; thus it can't be None; qed"); - C::print_from_uri(uri, password, maybe_network); - } - ("sign", Some(matches)) => { - let should_decode = matches.is_present("hex"); - let message = read_message_from_stdin(should_decode); - let signature = do_sign::(matches, message, password); - println!("{}", signature); - } - ("verify", Some(matches)) => { - let should_decode = matches.is_present("hex"); - let message = read_message_from_stdin(should_decode); - let is_valid_signature = do_verify::(matches, message); - if is_valid_signature { - println!("Signature verifies correctly."); - } else { - println!("Signature invalid."); - } - } - ("vanity", Some(matches)) => { - let desired: String = matches - .value_of("pattern") - .map(str::to_string) - .unwrap_or_default(); - let result = vanity::generate_key::(&desired).expect("Key generation failed"); - let formated_seed = format_seed::(result.seed); - C::print_from_uri(&formated_seed, None, maybe_network); - } - ("transfer", Some(matches)) => { - let signer = read_pair::(matches.value_of("from"), password); - let index = read_required_parameter::(matches, "index"); - let genesis_hash = read_genesis_hash(matches); - - let to: AccountId = read_account_id(matches.value_of("to")); - let amount = read_required_parameter::(matches, "amount"); - let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); - - let extrinsic = create_extrinsic::(function, index, signer, genesis_hash); - - print_extrinsic(extrinsic); - } - ("sign-transaction", Some(matches)) => { - let signer = read_pair::(matches.value_of("suri"), password); - let index = read_required_parameter::(matches, "nonce"); - let genesis_hash = read_genesis_hash(matches); - - let call = matches.value_of("call").expect("call is required; qed"); - let function: Call = hex::decode(&call) - .ok() - .and_then(|x| Decode::decode(&mut &x[..]).ok()) - .unwrap(); - - let extrinsic = create_extrinsic::(function, index, signer, genesis_hash); - - print_extrinsic(extrinsic); - } - _ => print_usage(&matches), - } -} - -/// Creates a new randomly generated mnemonic phrase. -fn generate_mnemonic(matches: &ArgMatches) -> Mnemonic { - let words = matches - .value_of("words") - .map(|x| usize::from_str(x).expect("Invalid number given for --words")) - .map(|x| { - MnemonicType::for_word_count(x) - .expect("Invalid number of words given for phrase: must be 12/15/18/21/24") - }) - .unwrap_or(MnemonicType::Words12); - Mnemonic::new(words, Language::English) -} - -fn do_sign(matches: &ArgMatches, message: Vec, password: Option<&str>) -> String -where - SignatureOf: SignatureT, - PublicOf: PublicT, -{ - let pair = read_pair::(matches.value_of("suri"), password); - let signature = pair.sign(&message); - format_signature::(&signature) -} - -fn do_verify(matches: &ArgMatches, message: Vec) -> bool -where - SignatureOf: SignatureT, - PublicOf: PublicT, -{ - let signature = read_signature::(matches); - let pubkey = read_public_key::(matches.value_of("uri")); - <::Pair as Pair>::verify(&signature, &message, &pubkey) -} - -fn read_message_from_stdin(should_decode: bool) -> Vec { - let mut message = vec![]; - stdin() - .lock() - .read_to_end(&mut message) - .expect("Error reading from stdin"); - if should_decode { - message = hex::decode(&message).expect("Invalid hex in message"); - } - message -} - -fn read_required_parameter(matches: &ArgMatches, name: &str) -> T -where - ::Err: std::fmt::Debug, -{ - let str_value = matches - .value_of(name) - .expect("parameter is required; thus it can't be None; qed"); - str::parse::(str_value).expect("Invalid 'nonce' parameter; expecting an integer.") -} - -fn read_genesis_hash(matches: &ArgMatches) -> H256 { - let genesis_hash: Hash = match matches.value_of("genesis").unwrap_or("alex") { - "elm" => hex!["10c08714a10c7da78f40a60f6f732cf0dba97acfb5e2035445b032386157d5c3"].into(), - "alex" => hex!["dcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b"].into(), - h => hex::decode(h) - .ok() - .and_then(|x| Decode::decode(&mut &x[..]).ok()) - .expect("Invalid genesis hash or unrecognised chain identifier"), - }; - println!( - "Using a genesis hash of {}", - HexDisplay::from(&genesis_hash.as_ref()) - ); - genesis_hash -} - -fn read_signature(matches: &ArgMatches) -> SignatureOf -where - SignatureOf: SignatureT, - PublicOf: PublicT, -{ - let sig_data = matches - .value_of("sig") - .expect("signature parameter is required; thus it can't be None; qed"); - let mut signature = <::Pair as Pair>::Signature::default(); - let sig_data = hex::decode(sig_data).expect("signature is invalid hex"); - if sig_data.len() != signature.as_ref().len() { - panic!( - "signature has an invalid length. read {} bytes, expected {} bytes", - sig_data.len(), - signature.as_ref().len(), - ); - } - signature.as_mut().copy_from_slice(&sig_data); - signature -} - -fn read_public_key(matched_uri: Option<&str>) -> PublicOf where - PublicOf: PublicT, -{ - let uri = matched_uri.expect("parameter is required; thus it can't be None; qed"); - let uri = if uri.starts_with("0x") { - &uri[2..] - } else { - uri - }; - if let Ok(pubkey_vec) = hex::decode(uri) { - ::Public::from_slice(pubkey_vec.as_slice()) - } else { - ::Public::from_string(uri) - .ok() - .expect("Invalid URI; expecting either a secret URI or a public URI.") - } -} - -fn read_account_id(matched_uri: Option<&str>) -> AccountId { - let uri = matched_uri.expect("parameter is required; thus it can't be None; qed"); - let uri = if uri.starts_with("0x") { - &uri[2..] - } else { - uri - }; - if let Ok(data_vec) = hex::decode(uri) { - AccountId::try_from(data_vec.as_slice()) - .expect("Invalid hex length for account ID; should be 32 bytes") - } else { - AccountId::from_ss58check(uri).ok() - .expect("Invalid SS58-check address given for account ID.") - } -} - -fn read_pair( - matched_suri: Option<&str>, - password: Option<&str>, -) -> ::Pair -where - SignatureOf: SignatureT, - PublicOf: PublicT, -{ - let suri = matched_suri.expect("parameter is required; thus it can't be None; qed"); - C::pair_from_suri(suri, password) -} - -fn format_signature(signature: &SignatureOf) -> String { - format!("{}", hex::encode(signature)) -} - -fn format_seed(seed: SeedOf) -> String { - format!("0x{}", HexDisplay::from(&seed.as_ref())) -} - -fn format_public_key(public_key: PublicOf) -> String { - format!("0x{}", HexDisplay::from(&public_key.as_ref())) -} - -fn format_account_id(public_key: PublicOf) -> String where - PublicOf: PublicT, -{ - format!("0x{}", HexDisplay::from(&public_key.into_runtime().into_account().as_ref())) -} - -fn create_extrinsic( - function: Call, - index: Index, - signer: C::Pair, - genesis_hash: H256, -) -> UncheckedExtrinsic where - PublicOf: PublicT, - SignatureOf: SignatureT, -{ - let extra = |i: Index, f: Balance| { - ( - system::CheckVersion::::new(), - system::CheckGenesis::::new(), - system::CheckEra::::from(Era::Immortal), - system::CheckNonce::::from(i), - system::CheckWeight::::new(), - transaction_payment::ChargeTransactionPayment::::from(f), - Default::default(), - ) - }; - let raw_payload = SignedPayload::from_raw( - function, - extra(index, 0), - ( - VERSION.spec_version as u32, - genesis_hash, - genesis_hash, - (), - (), - (), - (), - ), - ); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)).into_runtime(); - let signer = signer.public().into_runtime(); - let (function, extra, _) = raw_payload.deconstruct(); - - UncheckedExtrinsic::new_signed( - function, - signer.into_account().into(), - signature, - extra, - ) -} - -fn print_extrinsic(extrinsic: UncheckedExtrinsic) { - println!("0x{}", hex::encode(&extrinsic.encode())); -} - -fn print_usage(matches: &ArgMatches) { - println!("{}", matches.usage()); -} - -#[cfg(test)] -mod tests { - use super::*; - - fn test_generate_sign_verify() - where - SignatureOf: SignatureT, - PublicOf: PublicT, - { - let yaml = load_yaml!("cli.yml"); - let app = App::from_yaml(yaml); - let password = None; - - // Generate public key and seed. - let arg_vec = vec!["subkey", "generate"]; - - let matches = app.clone().get_matches_from(arg_vec); - let matches = matches.subcommand().1.unwrap(); - let mnemonic = generate_mnemonic(matches); - - let (pair, seed) = - <::Pair as Pair>::from_phrase(mnemonic.phrase(), password) - .unwrap(); - let public_key = CryptoType::public_from_pair(&pair); - let public_key = format_public_key::(public_key); - let seed = format_seed::(seed); - - // Sign a message using previous seed. - let arg_vec = vec!["subkey", "sign", &seed[..]]; - - let matches = app.get_matches_from(arg_vec); - let matches = matches.subcommand().1.unwrap(); - let message = "Blah Blah\n".as_bytes().to_vec(); - let signature = do_sign::(matches, message.clone(), password); - - // Verify the previous signature. - let arg_vec = vec!["subkey", "verify", &signature[..], &public_key[..]]; - - let matches = App::from_yaml(yaml).get_matches_from(arg_vec); - let matches = matches.subcommand().1.unwrap(); - assert!(do_verify::(matches, message)); - } - - #[test] - fn generate_sign_verify_should_work_for_ed25519() { - test_generate_sign_verify::(); - } - - #[test] - fn generate_sign_verify_should_work_for_sr25519() { - test_generate_sign_verify::(); - } - - #[test] - fn should_work() { - let s = "0123456789012345678901234567890123456789012345678901234567890123"; - - let d1: Hash = hex::decode(s) - .ok() - .and_then(|x| Decode::decode(&mut &x[..]).ok()) - .unwrap(); - - let d2: Hash = { - let mut gh: [u8; 32] = Default::default(); - gh.copy_from_slice(hex::decode(s).unwrap().as_ref()); - Hash::from(gh) - }; - - assert_eq!(d1, d2); - } -} diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml new file mode 100644 index 0000000000000..ac4c9954192dc --- /dev/null +++ b/test-utils/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "substrate-test-utils" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" diff --git a/test-utils/chain-spec-builder/Cargo.toml b/test-utils/chain-spec-builder/Cargo.toml deleted file mode 100644 index 324d33cbf0da7..0000000000000 --- a/test-utils/chain-spec-builder/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "chain-spec-builder" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -ansi_term = "0.12.1" -keystore = { package = "substrate-keystore", path = "../../core/keystore" } -node-cli = { path = "../../node/cli" } -primitives = { package = "substrate-primitives", path = "../../core/primitives" } -rand = "0.7.2" -structopt = "0.3.3" diff --git a/test-utils/chain-spec-builder/src/main.rs b/test-utils/chain-spec-builder/src/main.rs deleted file mode 100644 index 8fdd282345bc0..0000000000000 --- a/test-utils/chain-spec-builder/src/main.rs +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use std::{fs, path::{Path, PathBuf}}; - -use ansi_term::Style; -use rand::{Rng, distributions::Alphanumeric, rngs::OsRng}; -use structopt::StructOpt; - -use keystore::{Store as Keystore}; -use node_cli::chain_spec::{self, AccountId}; -use primitives::{sr25519, crypto::{Public, Ss58Codec}, traits::BareCryptoStore}; - -/// A utility to easily create a testnet chain spec definition with a given set -/// of authorities and endowed accounts and/or generate random accounts. -#[derive(StructOpt)] -#[structopt(rename_all = "kebab-case")] -enum ChainSpecBuilder { - /// Create a new chain spec with the given authorities, endowed and sudo - /// accounts. - New { - /// Authority key seed. - #[structopt(long, short, required = true)] - authority_seeds: Vec, - /// Endowed account address (SS58 format). - #[structopt(long, short)] - endowed_accounts: Vec, - /// Sudo account address (SS58 format). - #[structopt(long, short)] - sudo_account: String, - /// The path where the chain spec should be saved. - #[structopt(long, short, default_value = "./chain_spec.json")] - chain_spec_path: PathBuf, - }, - /// Create a new chain spec with the given number of authorities and endowed - /// accounts. Random keys will be generated as required. - Generate { - /// The number of authorities. - #[structopt(long, short)] - authorities: usize, - /// The number of endowed accounts. - #[structopt(long, short, default_value = "0")] - endowed: usize, - /// The path where the chain spec should be saved. - #[structopt(long, short, default_value = "./chain_spec.json")] - chain_spec_path: PathBuf, - /// Path to use when saving generated keystores for each authority. - /// - /// At this path, a new folder will be created for each authority's - /// keystore named `auth-$i` where `i` is the authority index, i.e. - /// `auth-0`, `auth-1`, etc. - #[structopt(long, short)] - keystore_path: Option, - }, -} - -impl ChainSpecBuilder { - /// Returns the path where the chain spec should be saved. - fn chain_spec_path(&self) -> &Path { - match self { - ChainSpecBuilder::New { chain_spec_path, .. } => - chain_spec_path.as_path(), - ChainSpecBuilder::Generate { chain_spec_path, .. } => - chain_spec_path.as_path(), - } - } -} - -fn genesis_constructor( - authority_seeds: &[String], - endowed_accounts: &[AccountId], - sudo_account: &AccountId, -) -> chain_spec::GenesisConfig { - let authorities = authority_seeds - .iter() - .map(AsRef::as_ref) - .map(chain_spec::get_authority_keys_from_seed) - .collect::>(); - - let enable_println = true; - - chain_spec::testnet_genesis( - authorities, - sudo_account.clone(), - Some(endowed_accounts.to_vec()), - enable_println, - ) -} - -fn generate_chain_spec( - authority_seeds: Vec, - endowed_accounts: Vec, - sudo_account: String, -) -> Result { - let parse_account = |address: &String| { - AccountId::from_string(address) - .map_err(|err| format!("Failed to parse account address: {:?}", err)) - }; - - let endowed_accounts = endowed_accounts - .iter() - .map(parse_account) - .collect::, String>>()?; - - let sudo_account = parse_account(&sudo_account)?; - - let chain_spec = chain_spec::ChainSpec::from_genesis( - "Custom", - "custom", - move || genesis_constructor(&authority_seeds, &endowed_accounts, &sudo_account), - vec![], - None, - None, - None, - Default::default(), - ); - - chain_spec.to_json(false).map_err(|err| err.to_string()) -} - -fn generate_authority_keys_and_store( - seeds: &[String], - keystore_path: &Path, -) -> Result<(), String> { - for (n, seed) in seeds.into_iter().enumerate() { - let keystore = Keystore::open( - keystore_path.join(format!("auth-{}", n)), - None, - ).map_err(|err| err.to_string())?; - - let (_, _, grandpa, babe, im_online) = - chain_spec::get_authority_keys_from_seed(seed); - - let insert_key = |key_type, public| { - keystore.write().insert_unknown( - key_type, - &format!("//{}", seed), - public, - ).map_err(|_| format!("Failed to insert key: {}", grandpa)) - }; - - insert_key( - primitives::crypto::key_types::BABE, - babe.as_slice(), - )?; - - insert_key( - primitives::crypto::key_types::GRANDPA, - grandpa.as_slice(), - )?; - - insert_key( - primitives::crypto::key_types::IM_ONLINE, - im_online.as_slice(), - )?; - } - - Ok(()) -} - -fn print_seeds( - authority_seeds: &[String], - endowed_seeds: &[String], - sudo_seed: &str, -) { - let header = Style::new().bold().underline(); - let entry = Style::new().bold(); - - println!("{}", header.paint("Authority seeds")); - - for (n, seed) in authority_seeds.iter().enumerate() { - println!("{} //{}", - entry.paint(format!("auth-{}:", n)), - seed, - ); - } - - println!(); - - if !endowed_seeds.is_empty() { - println!("{}", header.paint("Endowed seeds")); - for (n, seed) in endowed_seeds.iter().enumerate() { - println!("{} //{}", - entry.paint(format!("endowed-{}:", n)), - seed, - ); - } - - println!(); - } - - println!("{}", header.paint("Sudo seed")); - println!("//{}", sudo_seed); -} - -fn main() -> Result<(), String> { - let builder = ChainSpecBuilder::from_args(); - let chain_spec_path = builder.chain_spec_path().to_path_buf(); - - let (authority_seeds, endowed_accounts, sudo_account) = match builder { - ChainSpecBuilder::Generate { authorities, endowed, keystore_path, .. } => { - let authorities = authorities.max(1); - let rand_str = || -> String { - OsRng.sample_iter(&Alphanumeric) - .take(32) - .collect() - }; - - let authority_seeds = (0..authorities).map(|_| rand_str()).collect::>(); - let endowed_seeds = (0..endowed).map(|_| rand_str()).collect::>(); - let sudo_seed = rand_str(); - - print_seeds( - &authority_seeds, - &endowed_seeds, - &sudo_seed, - ); - - if let Some(keystore_path) = keystore_path { - generate_authority_keys_and_store( - &authority_seeds, - &keystore_path, - )?; - } - - let endowed_accounts = endowed_seeds.iter().map(|seed| { - chain_spec::get_account_id_from_seed::(seed) - .to_ss58check() - }).collect(); - - let sudo_account = chain_spec::get_account_id_from_seed::(&sudo_seed) - .to_ss58check(); - - (authority_seeds, endowed_accounts, sudo_account) - }, - ChainSpecBuilder::New { authority_seeds, endowed_accounts, sudo_account, .. } => { - (authority_seeds, endowed_accounts, sudo_account) - }, - }; - - let json = generate_chain_spec( - authority_seeds, - endowed_accounts, - sudo_account, - )?; - - fs::write(chain_spec_path, json).map_err(|err| err.to_string()) -} diff --git a/test-utils/client/Cargo.toml b/test-utils/client/Cargo.toml new file mode 100644 index 0000000000000..05dc41b2233a1 --- /dev/null +++ b/test-utils/client/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "substrate-test-client" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sc-client-api = { version = "2.0.0", path = "../../client/api" } +sc-client = { version = "2.0.0", path = "../../client/" } +sc-client-db = { version = "2.0.0", features = ["test-helpers"], path = "../../client/db" } +sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" } +sc-executor = { version = "2.0.0", path = "../../client/executor" } +futures = "0.3.1" +hash-db = "0.15.2" +sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" } +sp-blockchain = { version = "2.0.0", path = "../../primitives/blockchain" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } diff --git a/test-utils/client/src/client_ext.rs b/test-utils/client/src/client_ext.rs new file mode 100644 index 0000000000000..67d08c5fa600f --- /dev/null +++ b/test-utils/client/src/client_ext.rs @@ -0,0 +1,254 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Client extension for tests. + +use sc_client::{self, Client}; +use sc_client_api::backend::Finalizer; +use sp_consensus::{ + BlockImportParams, BlockImport, BlockOrigin, Error as ConsensusError, + ForkChoiceStrategy, +}; +use sp_runtime::Justification; +use sp_runtime::traits::{Block as BlockT}; +use sp_runtime::generic::BlockId; +use codec::alloc::collections::hash_map::HashMap; + +/// Extension trait for a test client. +pub trait ClientExt: Sized { + /// Finalize a block. + fn finalize_block( + &self, + id: BlockId, + justification: Option, + ) -> sp_blockchain::Result<()>; + + /// Returns hash of the genesis block. + fn genesis_hash(&self) -> ::Hash; +} + +/// Extension trait for a test client around block importing. +pub trait ClientBlockImportExt: Sized { + /// Import block to the chain. No finality. + fn import(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError>; + + /// Import a block and make it our best block if possible. + fn import_as_best(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError>; + + /// Import a block and finalize it. + fn import_as_final(&mut self, origin: BlockOrigin, block: Block) + -> Result<(), ConsensusError>; + + /// Import block with justification, finalizes block. + fn import_justified( + &mut self, + origin: BlockOrigin, + block: Block, + justification: Justification + ) -> Result<(), ConsensusError>; +} + +impl ClientExt for Client + where + B: sc_client_api::backend::Backend, + E: sc_client::CallExecutor, + Self: BlockImport, + Block: BlockT, +{ + fn finalize_block( + &self, + id: BlockId, + justification: Option, + ) -> sp_blockchain::Result<()> { + Finalizer::finalize_block(self, id, justification, true) + } + + fn genesis_hash(&self) -> ::Hash { + self.block_hash(0.into()).unwrap().unwrap() + } +} + +/// This implementation is required, because of the weird api requirements around `BlockImport`. +impl ClientBlockImportExt for std::sync::Arc + where for<'r> &'r T: BlockImport +{ + fn import(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> { + let (header, extrinsics) = block.deconstruct(); + let import = BlockImportParams { + origin, + header, + justification: None, + post_digests: vec![], + body: Some(extrinsics), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + + BlockImport::import_block(self, import, HashMap::new()).map(|_| ()) + } + + fn import_as_best(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> { + let (header, extrinsics) = block.deconstruct(); + let import = BlockImportParams { + origin, + header, + justification: None, + post_digests: vec![], + body: Some(extrinsics), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::Custom(true), + allow_missing_state: false, + import_existing: false, + }; + + BlockImport::import_block(self, import, HashMap::new()).map(|_| ()) + } + + fn import_as_final(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> { + let (header, extrinsics) = block.deconstruct(); + let import = BlockImportParams { + origin, + header, + justification: None, + post_digests: vec![], + body: Some(extrinsics), + storage_changes: None, + finalized: true, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::Custom(true), + allow_missing_state: false, + import_existing: false, + }; + + BlockImport::import_block(self, import, HashMap::new()).map(|_| ()) + } + + fn import_justified( + &mut self, + origin: BlockOrigin, + block: Block, + justification: Justification, + ) -> Result<(), ConsensusError> { + let (header, extrinsics) = block.deconstruct(); + let import = BlockImportParams { + origin, + header, + justification: Some(justification), + post_digests: vec![], + body: Some(extrinsics), + storage_changes: None, + finalized: true, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + + BlockImport::import_block(self, import, HashMap::new()).map(|_| ()) + } +} + +impl ClientBlockImportExt for Client + where + Self: BlockImport, +{ + fn import(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> { + let (header, extrinsics) = block.deconstruct(); + let import = BlockImportParams { + origin, + header, + justification: None, + post_digests: vec![], + body: Some(extrinsics), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + + BlockImport::import_block(self, import, HashMap::new()).map(|_| ()) + } + + fn import_as_best(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> { + let (header, extrinsics) = block.deconstruct(); + let import = BlockImportParams { + origin, + header, + justification: None, + post_digests: vec![], + body: Some(extrinsics), + storage_changes: None, + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::Custom(true), + allow_missing_state: false, + import_existing: false, + }; + + BlockImport::import_block(self, import, HashMap::new()).map(|_| ()) + } + + fn import_as_final(&mut self, origin: BlockOrigin, block: Block) -> Result<(), ConsensusError> { + let (header, extrinsics) = block.deconstruct(); + let import = BlockImportParams { + origin, + header, + justification: None, + post_digests: vec![], + body: Some(extrinsics), + storage_changes: None, + finalized: true, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::Custom(true), + allow_missing_state: false, + import_existing: false, + }; + + BlockImport::import_block(self, import, HashMap::new()).map(|_| ()) + } + + fn import_justified( + &mut self, + origin: BlockOrigin, + block: Block, + justification: Justification, + ) -> Result<(), ConsensusError> { + let (header, extrinsics) = block.deconstruct(); + let import = BlockImportParams { + origin, + header, + justification: Some(justification), + post_digests: vec![], + body: Some(extrinsics), + storage_changes: None, + finalized: true, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + allow_missing_state: false, + import_existing: false, + }; + + BlockImport::import_block(self, import, HashMap::new()).map(|_| ()) + } +} diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs new file mode 100644 index 0000000000000..ac1cfe4d6b6a5 --- /dev/null +++ b/test-utils/client/src/lib.rs @@ -0,0 +1,238 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Client testing utilities. + +#![warn(missing_docs)] + +pub mod client_ext; + +pub use sc_client::{blockchain, self}; +pub use sc_client_api::execution_extensions::{ExecutionStrategies, ExecutionExtensions}; +pub use sc_client_db::{Backend, self}; +pub use sp_consensus; +pub use sc_executor::{NativeExecutor, WasmExecutionMethod, self}; +pub use sp_keyring::{ + AccountKeyring, + ed25519::Keyring as Ed25519Keyring, + sr25519::Keyring as Sr25519Keyring, +}; +pub use sp_core::{Blake2Hasher, traits::BareCryptoStorePtr}; +pub use sp_runtime::{Storage, StorageChild}; +pub use sp_state_machine::ExecutionStrategy; + +pub use self::client_ext::{ClientExt, ClientBlockImportExt}; + +use std::sync::Arc; +use std::collections::HashMap; +use sp_core::storage::{well_known_keys, ChildInfo}; +use sp_runtime::traits::Block as BlockT; +use sc_client::LocalCallExecutor; + +/// Test client light database backend. +pub type LightBackend = sc_client::light::backend::Backend< + sc_client_db::light::LightStorage, + Blake2Hasher, +>; + +/// A genesis storage initialisation trait. +pub trait GenesisInit: Default { + /// Construct genesis storage. + fn genesis_storage(&self) -> Storage; +} + +impl GenesisInit for () { + fn genesis_storage(&self) -> Storage { + Default::default() + } +} + +/// A builder for creating a test client instance. +pub struct TestClientBuilder { + execution_strategies: ExecutionStrategies, + genesis_init: G, + child_storage_extension: HashMap, StorageChild>, + backend: Arc, + _executor: std::marker::PhantomData, + keystore: Option, +} + +impl Default + for TestClientBuilder, G> { + fn default() -> Self { + Self::with_default_backend() + } +} + +impl TestClientBuilder, G> { + /// Create new `TestClientBuilder` with default backend. + pub fn with_default_backend() -> Self { + let backend = Arc::new(Backend::new_test(std::u32::MAX, std::u64::MAX)); + Self::with_backend(backend) + } + + /// Create new `TestClientBuilder` with default backend and pruning window size + pub fn with_pruning_window(keep_blocks: u32) -> Self { + let backend = Arc::new(Backend::new_test(keep_blocks, 0)); + Self::with_backend(backend) + } +} + +impl TestClientBuilder { + /// Create a new instance of the test client builder. + pub fn with_backend(backend: Arc) -> Self { + TestClientBuilder { + backend, + execution_strategies: ExecutionStrategies::default(), + child_storage_extension: Default::default(), + genesis_init: Default::default(), + _executor: Default::default(), + keystore: None, + } + } + + /// Set the keystore that should be used by the externalities. + pub fn set_keystore(mut self, keystore: BareCryptoStorePtr) -> Self { + self.keystore = Some(keystore); + self + } + + /// Alter the genesis storage parameters. + pub fn genesis_init_mut(&mut self) -> &mut G { + &mut self.genesis_init + } + + /// Give access to the underlying backend of these clients + pub fn backend(&self) -> Arc { + self.backend.clone() + } + + /// Extend child storage + pub fn add_child_storage( + mut self, + key: impl AsRef<[u8]>, + child_key: impl AsRef<[u8]>, + child_info: ChildInfo, + value: impl AsRef<[u8]>, + ) -> Self { + let entry = self.child_storage_extension.entry(key.as_ref().to_vec()) + .or_insert_with(|| StorageChild { + data: Default::default(), + child_info: child_info.to_owned(), + }); + entry.data.insert(child_key.as_ref().to_vec(), value.as_ref().to_vec()); + self + } + + /// Set the execution strategy that should be used by all contexts. + pub fn set_execution_strategy( + mut self, + execution_strategy: ExecutionStrategy + ) -> Self { + self.execution_strategies = ExecutionStrategies { + syncing: execution_strategy, + importing: execution_strategy, + block_construction: execution_strategy, + offchain_worker: execution_strategy, + other: execution_strategy, + }; + self + } + + /// Build the test client with the given native executor. + pub fn build_with_executor( + self, + executor: Executor, + ) -> ( + sc_client::Client< + Backend, + Executor, + Block, + RuntimeApi, + >, + sc_client::LongestChain, + ) where + Executor: sc_client::CallExecutor, + Backend: sc_client_api::backend::Backend, + Block: BlockT, + { + + let storage = { + let mut storage = self.genesis_init.genesis_storage(); + + // Add some child storage keys. + for (key, child_content) in self.child_storage_extension { + storage.children.insert( + well_known_keys::CHILD_STORAGE_KEY_PREFIX.iter().cloned().chain(key).collect(), + StorageChild { + data: child_content.data.into_iter().collect(), + child_info: child_content.child_info, + }, + ); + } + + storage + }; + + let client = sc_client::Client::new( + self.backend.clone(), + executor, + storage, + Default::default(), + Default::default(), + ExecutionExtensions::new( + self.execution_strategies, + self.keystore.clone(), + ) + ).expect("Creates new client"); + + let longest_chain = sc_client::LongestChain::new(self.backend); + + (client, longest_chain) + } +} + +impl TestClientBuilder< + sc_client::LocalCallExecutor>, + Backend, + G, +> { + /// Build the test client with the given native executor. + pub fn build_with_native_executor( + self, + executor: I, + ) -> ( + sc_client::Client< + Backend, + sc_client::LocalCallExecutor>, + Block, + RuntimeApi + >, + sc_client::LongestChain, + ) where + I: Into>>, + E: sc_executor::NativeExecutionDispatch, + Backend: sc_client_api::backend::Backend, + Block: BlockT, + { + let executor = executor.into().unwrap_or_else(|| + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + ); + let executor = LocalCallExecutor::new(self.backend.clone(), executor); + + self.build_with_executor(executor) + } +} diff --git a/test-utils/runtime/Cargo.toml b/test-utils/runtime/Cargo.toml new file mode 100644 index 0000000000000..6444c7fcf1463 --- /dev/null +++ b/test-utils/runtime/Cargo.toml @@ -0,0 +1,83 @@ +[package] +name = "substrate-test-runtime" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" + +[dependencies] +sp-application-crypto = { version = "2.0.0", default-features = false, path = "../../primitives/application-crypto" } +sp-consensus-aura = { version = "0.8", default-features = false, path = "../../primitives/consensus/aura" } +sp-consensus-babe = { version = "0.8", default-features = false, path = "../../primitives/consensus/babe" } +sp-block-builder = { version = "2.0.0", default-features = false, path = "../../primitives/block-builder" } +cfg-if = "0.1.10" +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +frame-executive = { version = "2.0.0", default-features = false, path = "../../frame/executive" } +sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +sp-keyring = { version = "2.0.0", optional = true, path = "../../primitives/keyring" } +log = { version = "0.4.8", optional = true } +memory-db = { version = "0.18.0", default-features = false } +sp-offchain = { path = "../../primitives/offchain", default-features = false} +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-runtime-interface = { path = "../../primitives/runtime-interface", default-features = false} +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +frame-support = { version = "2.0.0", default-features = false, path = "../../frame/support" } +sp-version = { version = "2.0.0", default-features = false, path = "../../primitives/version" } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sp-session = { version = "2.0.0", default-features = false, path = "../../primitives/session" } +sp-api = { version = "2.0.0", default-features = false, path = "../../primitives/api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +pallet-babe = { version = "2.0.0", default-features = false, path = "../../frame/babe" } +frame-system = { version = "2.0.0", default-features = false, path = "../../frame/system" } +frame-system-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../frame/system/rpc/runtime-api" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../frame/timestamp" } +sc-client = { version = "2.0.0", optional = true, path = "../../client" } +sp-trie = { version = "2.0.0", default-features = false, path = "../../primitives/trie" } +sp-transaction-pool = { version = "2.0.0", default-features = false, path = "../../primitives/transaction-pool" } +trie-db = { version = "0.18.1", default-features = false } + +[dev-dependencies] +sc-executor = { version = "2.0.0", path = "../../client/executor" } +substrate-test-runtime-client = { version = "2.0.0", path = "./client" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } + +[build-dependencies] +wasm-builder-runner = { version = "1.0.4", package = "substrate-wasm-builder-runner", path = "../../utils/wasm-builder-runner" } + +[features] +default = [ + "std", +] +std = [ + "sp-application-crypto/std", + "sp-consensus-aura/std", + "sp-consensus-babe/std", + "sp-block-builder/std", + "codec/std", + "frame-executive/std", + "sp-inherents/std", + "sp-keyring", + "log", + "memory-db/std", + "sp-offchain/std", + "sp-core/std", + "sp-core/std", + "sp-std/std", + "sp-runtime-interface/std", + "sp-io/std", + "frame-support/std", + "sp-version/std", + "serde", + "sp-session/std", + "sp-api/std", + "sp-runtime/std", + "pallet-babe/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "pallet-timestamp/std", + "sc-client", + "sp-trie/std", + "sp-transaction-pool/std", + "trie-db/std", +] diff --git a/test-utils/runtime/build.rs b/test-utils/runtime/build.rs new file mode 100644 index 0000000000000..a90270d85d55f --- /dev/null +++ b/test-utils/runtime/build.rs @@ -0,0 +1,35 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSource}; + +fn main() { + build_current_project_with_rustflags( + "wasm_binary.rs", + WasmBuilderSource::CratesOrPath { + path: "../../utils/wasm-builder", + version: "1.0.8", + }, + // Note that we set the stack-size to 1MB explicitly even though it is set + // to this value by default. This is because some of our tests (`restoration_of_globals`) + // depend on the stack-size. + // + // The --export=__heap_base instructs LLD to export __heap_base as a global variable, which + // is used by the external memory allocator. + "-Clink-arg=-zstack-size=1048576 \ + -Clink-arg=--export=__heap_base", + ); +} diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml new file mode 100644 index 0000000000000..8e08f6a1b5ec8 --- /dev/null +++ b/test-utils/runtime/client/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "substrate-test-runtime-client" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sc-block-builder = { version = "2.0.0", path = "../../../client/block-builder" } +substrate-test-client = { version = "2.0.0", path = "../../client" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +substrate-test-runtime = { version = "2.0.0", path = "../../runtime" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-api = { version = "2.0.0", path = "../../../primitives/api" } +sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +sc-client-api = { version = "2.0.0", path = "../../../client/api" } +sc-client = { version = "2.0.0", path = "../../../client/" } +futures = "0.3.1" diff --git a/test-utils/runtime/client/src/block_builder_ext.rs b/test-utils/runtime/client/src/block_builder_ext.rs new file mode 100644 index 0000000000000..7626ac2ffa5f4 --- /dev/null +++ b/test-utils/runtime/client/src/block_builder_ext.rs @@ -0,0 +1,60 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Block Builder extensions for tests. + +use sp_api::{ApiExt, ProvideRuntimeApi}; +use sc_client_api::backend; +use sp_runtime::traits::HasherFor; + +use sc_block_builder::BlockBuilderApi; + +/// Extension trait for test block builder. +pub trait BlockBuilderExt { + /// Add transfer extrinsic to the block. + fn push_transfer(&mut self, transfer: substrate_test_runtime::Transfer) -> Result<(), sp_blockchain::Error>; + /// Add storage change extrinsic to the block. + fn push_storage_change( + &mut self, + key: Vec, + value: Option>, + ) -> Result<(), sp_blockchain::Error>; +} + +impl<'a, A, B> BlockBuilderExt for sc_block_builder::BlockBuilder<'a, substrate_test_runtime::Block, A, B> where + A: ProvideRuntimeApi + 'a, + A::Api: BlockBuilderApi + + ApiExt< + substrate_test_runtime::Block, + StateBackend = backend::StateBackendFor + >, + B: backend::Backend, + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + backend::StateBackendFor: + sp_api::StateBackend>, +{ + fn push_transfer(&mut self, transfer: substrate_test_runtime::Transfer) -> Result<(), sp_blockchain::Error> { + self.push(transfer.into_signed_tx()) + } + + fn push_storage_change( + &mut self, + key: Vec, + value: Option>, + ) -> Result<(), sp_blockchain::Error> { + self.push(substrate_test_runtime::Extrinsic::StorageChange(key, value)) + } +} diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs new file mode 100644 index 0000000000000..4faf7f8ab4851 --- /dev/null +++ b/test-utils/runtime/client/src/lib.rs @@ -0,0 +1,374 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Client testing utilities. + +#![warn(missing_docs)] + +pub mod trait_tests; + +mod block_builder_ext; + +use std::sync::Arc; +use std::collections::HashMap; +pub use substrate_test_client::*; +pub use substrate_test_runtime as runtime; +pub use sc_client::LongestChain; + +pub use self::block_builder_ext::BlockBuilderExt; + +use sp_core::sr25519; +use sp_core::storage::{ChildInfo, Storage, StorageChild}; +use substrate_test_runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, NumberFor, HasherFor}; +use sc_client::{ + light::fetcher::{ + Fetcher, + RemoteHeaderRequest, RemoteReadRequest, RemoteReadChildRequest, + RemoteCallRequest, RemoteChangesRequest, RemoteBodyRequest, + }, +}; + + +/// A prelude to import in tests. +pub mod prelude { + // Trait extensions + pub use super::{ + BlockBuilderExt, DefaultTestClientBuilderExt, TestClientBuilderExt, ClientExt, + ClientBlockImportExt, + }; + // Client structs + pub use super::{ + TestClient, TestClientBuilder, Backend, LightBackend, + Executor, LightExecutor, LocalExecutor, NativeExecutor, WasmExecutionMethod, + }; + // Keyring + pub use super::{AccountKeyring, Sr25519Keyring}; +} + +mod local_executor { + #![allow(missing_docs)] + use substrate_test_runtime; + use crate::sc_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, + substrate_test_runtime::api::dispatch, + substrate_test_runtime::native_version + ); +} + +/// Native executor used for tests. +pub use self::local_executor::LocalExecutor; + +/// Test client database backend. +pub type Backend = substrate_test_client::Backend; + +/// Test client executor. +pub type Executor = sc_client::LocalCallExecutor< + Backend, + NativeExecutor, +>; + +/// Test client light database backend. +pub type LightBackend = substrate_test_client::LightBackend; + +/// Test client light executor. +pub type LightExecutor = sc_client::light::call_executor::GenesisCallExecutor< + LightBackend, + sc_client::LocalCallExecutor< + sc_client::light::backend::Backend< + sc_client_db::light::LightStorage, + HasherFor + >, + NativeExecutor + > +>; + +/// Parameters of test-client builder with test-runtime. +#[derive(Default)] +pub struct GenesisParameters { + support_changes_trie: bool, + heap_pages_override: Option, + extra_storage: Storage, +} + +impl GenesisParameters { + fn genesis_config(&self) -> GenesisConfig { + GenesisConfig::new( + self.support_changes_trie, + vec![ + sr25519::Public::from(Sr25519Keyring::Alice).into(), + sr25519::Public::from(Sr25519Keyring::Bob).into(), + sr25519::Public::from(Sr25519Keyring::Charlie).into(), + ], + vec![ + AccountKeyring::Alice.into(), + AccountKeyring::Bob.into(), + AccountKeyring::Charlie.into(), + ], + 1000, + self.heap_pages_override, + self.extra_storage.clone(), + ) + } +} + +impl substrate_test_client::GenesisInit for GenesisParameters { + fn genesis_storage(&self) -> Storage { + use codec::Encode; + + let mut storage = self.genesis_config().genesis_map(); + + let child_roots = storage.children.iter().map(|(sk, child_content)| { + let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + child_content.data.clone().into_iter().collect() + ); + (sk.clone(), state_root.encode()) + }); + let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + storage.top.clone().into_iter().chain(child_roots).collect() + ); + let block: runtime::Block = sc_client::genesis::construct_genesis_block(state_root); + storage.top.extend(additional_storage_with_genesis(&block)); + + storage + } +} + +/// A `TestClient` with `test-runtime` builder. +pub type TestClientBuilder = substrate_test_client::TestClientBuilder; + +/// Test client type with `LocalExecutor` and generic Backend. +pub type Client = sc_client::Client< + B, + sc_client::LocalCallExecutor>, + substrate_test_runtime::Block, + substrate_test_runtime::RuntimeApi, +>; + +/// A test client with default backend. +pub type TestClient = Client; + +/// A `TestClientBuilder` with default backend and executor. +pub trait DefaultTestClientBuilderExt: Sized { + /// Create new `TestClientBuilder` + fn new() -> Self; +} + +impl DefaultTestClientBuilderExt for TestClientBuilder { + fn new() -> Self { + Self::with_default_backend() + } +} + +/// A `test-runtime` extensions to `TestClientBuilder`. +pub trait TestClientBuilderExt: Sized { + /// Returns a mutable reference to the genesis parameters. + fn genesis_init_mut(&mut self) -> &mut GenesisParameters; + + /// Enable or disable support for changes trie in genesis. + fn set_support_changes_trie(mut self, support_changes_trie: bool) -> Self { + self.genesis_init_mut().support_changes_trie = support_changes_trie; + self + } + + /// Override the default value for Wasm heap pages. + fn set_heap_pages(mut self, heap_pages: u64) -> Self { + self.genesis_init_mut().heap_pages_override = Some(heap_pages); + self + } + + /// Add an extra value into the genesis storage. + /// + /// # Panics + /// + /// Panics if the key is empty. + fn add_extra_child_storage>, K: Into>, V: Into>>( + mut self, + storage_key: SK, + child_info: ChildInfo, + key: K, + value: V, + ) -> Self { + let storage_key = storage_key.into(); + let key = key.into(); + assert!(!storage_key.is_empty()); + assert!(!key.is_empty()); + self.genesis_init_mut().extra_storage.children + .entry(storage_key) + .or_insert_with(|| StorageChild { + data: Default::default(), + child_info: child_info.to_owned(), + }).data.insert(key, value.into()); + self + } + + /// Add an extra child value into the genesis storage. + /// + /// # Panics + /// + /// Panics if the key is empty. + fn add_extra_storage>, V: Into>>(mut self, key: K, value: V) -> Self { + let key = key.into(); + assert!(!key.is_empty()); + self.genesis_init_mut().extra_storage.top.insert(key, value.into()); + self + } + + /// Build the test client. + fn build(self) -> Client { + self.build_with_longest_chain().0 + } + + /// Build the test client and longest chain selector. + fn build_with_longest_chain(self) -> (Client, sc_client::LongestChain); + + /// Build the test client and the backend. + fn build_with_backend(self) -> (Client, Arc); +} + +impl TestClientBuilderExt for TestClientBuilder< + sc_client::LocalCallExecutor>, + B +> where + B: sc_client_api::backend::Backend, + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + >::State: + sp_api::StateBackend>, +{ + fn genesis_init_mut(&mut self) -> &mut GenesisParameters { + Self::genesis_init_mut(self) + } + + fn build_with_longest_chain(self) -> (Client, sc_client::LongestChain) { + self.build_with_native_executor(None) + } + + fn build_with_backend(self) -> (Client, Arc) { + let backend = self.backend(); + (self.build_with_native_executor(None).0, backend) + } +} + +/// Type of optional fetch callback. +type MaybeFetcherCallback = Option Result + Send + Sync>>; + +/// Type of fetcher future result. +type FetcherFutureResult = futures::future::Ready>; + +/// Implementation of light client fetcher used in tests. +#[derive(Default)] +pub struct LightFetcher { + call: MaybeFetcherCallback, Vec>, + body: MaybeFetcherCallback, Vec>, +} + +impl LightFetcher { + /// Sets remote call callback. + pub fn with_remote_call( + self, + call: MaybeFetcherCallback, Vec>, + ) -> Self { + LightFetcher { + call, + body: self.body, + } + } + + /// Sets remote body callback. + pub fn with_remote_body( + self, + body: MaybeFetcherCallback, Vec>, + ) -> Self { + LightFetcher { + call: self.call, + body, + } + } +} + +impl Fetcher for LightFetcher { + type RemoteHeaderResult = FetcherFutureResult; + type RemoteReadResult = FetcherFutureResult, Option>>>; + type RemoteCallResult = FetcherFutureResult>; + type RemoteChangesResult = FetcherFutureResult, u32)>>; + type RemoteBodyResult = FetcherFutureResult>; + + fn remote_header(&self, _: RemoteHeaderRequest) -> Self::RemoteHeaderResult { + unimplemented!() + } + + fn remote_read(&self, _: RemoteReadRequest) -> Self::RemoteReadResult { + unimplemented!() + } + + fn remote_read_child(&self, _: RemoteReadChildRequest) -> Self::RemoteReadResult { + unimplemented!() + } + + fn remote_call(&self, req: RemoteCallRequest) -> Self::RemoteCallResult { + match self.call { + Some(ref call) => futures::future::ready(call(req)), + None => unimplemented!(), + } + } + + fn remote_changes(&self, _: RemoteChangesRequest) -> Self::RemoteChangesResult { + unimplemented!() + } + + fn remote_body(&self, req: RemoteBodyRequest) -> Self::RemoteBodyResult { + match self.body { + Some(ref body) => futures::future::ready(body(req)), + None => unimplemented!(), + } + } +} + +/// Creates new client instance used for tests. +pub fn new() -> Client { + TestClientBuilder::new().build() +} + +/// Creates new light client instance used for tests. +pub fn new_light() -> ( + sc_client::Client, + Arc, +) { + + let storage = sc_client_db::light::LightStorage::new_test(); + let blockchain = Arc::new(sc_client::light::blockchain::Blockchain::new(storage)); + let backend = Arc::new(LightBackend::new(blockchain.clone())); + let executor = NativeExecutor::new(WasmExecutionMethod::Interpreted, None); + let local_call_executor = sc_client::LocalCallExecutor::new(backend.clone(), executor); + let call_executor = LightExecutor::new( + backend.clone(), + local_call_executor, + ); + + ( + TestClientBuilder::with_backend(backend.clone()) + .build_with_executor(call_executor) + .0, + backend, + ) +} + +/// Creates new light client fetcher used for tests. +pub fn new_light_fetcher() -> LightFetcher { + LightFetcher::default() +} diff --git a/test-utils/runtime/client/src/trait_tests.rs b/test-utils/runtime/client/src/trait_tests.rs new file mode 100644 index 0000000000000..05db43298fd49 --- /dev/null +++ b/test-utils/runtime/client/src/trait_tests.rs @@ -0,0 +1,467 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! tests that should hold for all implementations of certain traits. +//! to test implementations without duplication. + +#![allow(missing_docs)] + +use std::sync::Arc; + +use crate::{ + AccountKeyring, ClientBlockImportExt, BlockBuilderExt, TestClientBuilder, TestClientBuilderExt, +}; +use sc_client_api::backend; +use sc_client_api::blockchain::{Backend as BlockChainBackendT, HeaderBackend}; +use substrate_test_client::sp_consensus::BlockOrigin; +use substrate_test_runtime::{self, Transfer}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{Block as BlockT, HasherFor}; + +/// helper to test the `leaves` implementation for various backends +pub fn test_leaves_for_backend(backend: Arc) where + B: backend::Backend, + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + backend::StateBackendFor: + sp_api::StateBackend>, +{ + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + + let mut client = TestClientBuilder::with_backend(backend.clone()).build(); + let blockchain = backend.blockchain(); + + let genesis_hash = client.chain_info().genesis_hash; + + assert_eq!( + blockchain.leaves().unwrap(), + vec![genesis_hash]); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + assert_eq!( + blockchain.leaves().unwrap(), + vec![a1.hash()], + ); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + #[allow(deprecated)] + assert_eq!( + blockchain.leaves().unwrap(), + vec![a2.hash()], + ); + + // A2 -> A3 + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + assert_eq!( + blockchain.leaves().unwrap(), + vec![a3.hash()], + ); + + // A3 -> A4 + let a4 = client.new_block_at( + &BlockId::Hash(a3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + assert_eq!( + blockchain.leaves().unwrap(), + vec![a4.hash()], + ); + + // A4 -> A5 + let a5 = client.new_block_at( + &BlockId::Hash(a4.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + assert_eq!( + blockchain.leaves().unwrap(), + vec![a5.hash()], + ); + + // A1 -> B2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + assert_eq!( + blockchain.leaves().unwrap(), + vec![a5.hash(), b2.hash()], + ); + + // B2 -> B3 + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + assert_eq!( + blockchain.leaves().unwrap(), + vec![a5.hash(), b3.hash()], + ); + + // B3 -> B4 + let b4 = client.new_block_at( + &BlockId::Hash(b3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + assert_eq!( + blockchain.leaves().unwrap(), + vec![a5.hash(), b4.hash()], + ); + + // // B2 -> C3 + let mut builder = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + assert_eq!( + blockchain.leaves().unwrap(), + vec![a5.hash(), b4.hash(), c3.hash()], + ); + + // A1 -> D2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + assert_eq!( + blockchain.leaves().unwrap(), + 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, + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + >::State: + sp_api::StateBackend>, +{ + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + + let mut client = TestClientBuilder::with_backend(backend.clone()).build(); + let blockchain = backend.blockchain(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + // A3 -> A4 + let a4 = client.new_block_at( + &BlockId::Hash(a3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + + // A4 -> A5 + let a5 = client.new_block_at( + &BlockId::Hash(a4.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + + // A1 -> B2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // B2 -> B3 + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + // B3 -> B4 + let b4 = client.new_block_at( + &BlockId::Hash(b3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + + // // B2 -> C3 + let mut builder = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + + // A1 -> D2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + + let genesis_hash = client.chain_info().genesis_hash; + + let children1 = blockchain.children(a4.hash()).unwrap(); + assert_eq!(vec![a5.hash()], children1); + + let children2 = blockchain.children(a1.hash()).unwrap(); + assert_eq!(vec![a2.hash(), b2.hash(), d2.hash()], children2); + + let children3 = blockchain.children(genesis_hash).unwrap(); + assert_eq!(vec![a1.hash()], children3); + + let children4 = 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 + B: backend::LocalBackend, + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + >::State: + sp_api::StateBackend>, +{ + // block tree: + // G -> A1 -> A2 -> A3 -> A4 -> A5 + // A1 -> B2 -> B3 -> B4 + // B2 -> C3 + // A1 -> D2 + let mut client = TestClientBuilder::with_backend(backend.clone()).build(); + let blockchain = backend.blockchain(); + + // G -> A1 + let a1 = client.new_block(Default::default()).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a1.clone()).unwrap(); + + // A1 -> A2 + let a2 = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + + // A2 -> A3 + let a3 = client.new_block_at( + &BlockId::Hash(a2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a3.clone()).unwrap(); + + // A3 -> A4 + let a4 = client.new_block_at( + &BlockId::Hash(a3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a4.clone()).unwrap(); + + // A4 -> A5 + let a5 = client.new_block_at( + &BlockId::Hash(a4.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, a5.clone()).unwrap(); + + // A1 -> B2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise B2 has the same hash as A2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 41, + nonce: 0, + }).unwrap(); + let b2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // B2 -> B3 + let b3 = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b3.clone()).unwrap(); + + // B3 -> B4 + let b4 = client.new_block_at( + &BlockId::Hash(b3.hash()), + Default::default(), + false, + ).unwrap().build().unwrap().block; + client.import(BlockOrigin::Own, b4.clone()).unwrap(); + + // // B2 -> C3 + let mut builder = client.new_block_at( + &BlockId::Hash(b2.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise C3 has the same hash as B3 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 1, + }).unwrap(); + let c3 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, c3.clone()).unwrap(); + + // A1 -> D2 + let mut builder = client.new_block_at( + &BlockId::Hash(a1.hash()), + Default::default(), + false, + ).unwrap(); + // this push is required as otherwise D2 has the same hash as B2 and won't get imported + builder.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 1, + nonce: 0, + }).unwrap(); + let d2 = builder.build().unwrap().block; + client.import(BlockOrigin::Own, d2.clone()).unwrap(); + + let genesis_hash = client.chain_info().genesis_hash; + + assert_eq!(blockchain.header(BlockId::Number(0)).unwrap().unwrap().hash(), genesis_hash); + assert_eq!(blockchain.hash(0).unwrap().unwrap(), genesis_hash); + + assert_eq!(blockchain.header(BlockId::Number(1)).unwrap().unwrap().hash(), a1.hash()); + assert_eq!(blockchain.hash(1).unwrap().unwrap(), a1.hash()); + + assert_eq!(blockchain.header(BlockId::Number(2)).unwrap().unwrap().hash(), a2.hash()); + assert_eq!(blockchain.hash(2).unwrap().unwrap(), a2.hash()); + + assert_eq!(blockchain.header(BlockId::Number(3)).unwrap().unwrap().hash(), a3.hash()); + assert_eq!(blockchain.hash(3).unwrap().unwrap(), a3.hash()); + + assert_eq!(blockchain.header(BlockId::Number(4)).unwrap().unwrap().hash(), a4.hash()); + assert_eq!(blockchain.hash(4).unwrap().unwrap(), a4.hash()); + + assert_eq!(blockchain.header(BlockId::Number(5)).unwrap().unwrap().hash(), a5.hash()); + assert_eq!(blockchain.hash(5).unwrap().unwrap(), a5.hash()); +} diff --git a/test-utils/runtime/src/genesismap.rs b/test-utils/runtime/src/genesismap.rs new file mode 100644 index 0000000000000..f6fbcddf44e16 --- /dev/null +++ b/test-utils/runtime/src/genesismap.rs @@ -0,0 +1,112 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tool for creating the genesis block. + +use std::collections::BTreeMap; +use sp_io::hashing::{blake2_256, twox_128}; +use super::{AuthorityId, AccountId, WASM_BINARY, system}; +use codec::{Encode, KeyedVec, Joiner}; +use sp_core::{ChangesTrieConfiguration, map}; +use sp_core::storage::{well_known_keys, Storage}; +use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; + +/// Configuration of a general Substrate test genesis block. +pub struct GenesisConfig { + changes_trie_config: Option, + authorities: Vec, + balances: Vec<(AccountId, u64)>, + heap_pages_override: Option, + /// Additional storage key pairs that will be added to the genesis map. + extra_storage: Storage, +} + +impl GenesisConfig { + pub fn new( + support_changes_trie: bool, + authorities: Vec, + endowed_accounts: Vec, + balance: u64, + heap_pages_override: Option, + extra_storage: Storage, + ) -> Self { + GenesisConfig { + changes_trie_config: match support_changes_trie { + true => Some(super::changes_trie_config()), + false => None, + }, + authorities: authorities.clone(), + balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(), + heap_pages_override, + extra_storage, + } + } + + pub fn genesis_map(&self) -> Storage { + let wasm_runtime = WASM_BINARY.to_vec(); + let mut map: BTreeMap, Vec> = self.balances.iter() + .map(|&(ref account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) + .map(|(k, v)| (blake2_256(&k[..])[..].to_vec(), v.to_vec())) + .chain(vec![ + (well_known_keys::CODE.into(), wasm_runtime), + ( + well_known_keys::HEAP_PAGES.into(), + vec![].and(&(self.heap_pages_override.unwrap_or(16 as u64))), + ), + ].into_iter()) + .collect(); + if let Some(ref changes_trie_config) = self.changes_trie_config { + map.insert(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), changes_trie_config.encode()); + } + map.insert(twox_128(&b"sys:auth"[..])[..].to_vec(), self.authorities.encode()); + // Add the extra storage entries. + map.extend(self.extra_storage.top.clone().into_iter()); + + // Assimilate the system genesis config. + let mut storage = Storage { top: map, children: self.extra_storage.children.clone()}; + let mut config = system::GenesisConfig::default(); + config.authorities = self.authorities.clone(); + config.assimilate_storage(&mut storage).expect("Adding `system::GensisConfig` to the genesis"); + + storage + } +} + +pub fn insert_genesis_block( + storage: &mut Storage, +) -> sp_core::hash::H256 { + let child_roots = storage.children.iter().map(|(sk, child_content)| { + let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + child_content.data.clone().into_iter().collect(), + ); + (sk.clone(), state_root.encode()) + }); + // add child roots to storage + storage.top.extend(child_roots); + let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + storage.top.clone().into_iter().collect() + ); + let block: crate::Block = sc_client::genesis::construct_genesis_block(state_root); + let genesis_hash = block.header.hash(); + storage.top.extend(additional_storage_with_genesis(&block)); + genesis_hash +} + +pub fn additional_storage_with_genesis(genesis_block: &crate::Block) -> BTreeMap, Vec> { + map![ + twox_128(&b"latest"[..]).to_vec() => genesis_block.hash().as_fixed_bytes().to_vec() + ] +} diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs new file mode 100644 index 0000000000000..4dfddfda21aec --- /dev/null +++ b/test-utils/runtime/src/lib.rs @@ -0,0 +1,1054 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! The Substrate runtime. This can be compiled with #[no_std], ready for Wasm. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +pub mod genesismap; +pub mod system; + +use sp_std::{prelude::*, marker::PhantomData}; +use codec::{Encode, Decode, Input, Error}; + +use sp_core::{Blake2Hasher, OpaqueMetadata, RuntimeDebug}; +use sp_application_crypto::{ed25519, sr25519, RuntimeAppPublic}; +use trie_db::{TrieMut, Trie}; +use sp_trie::PrefixedMemoryDB; +use sp_trie::trie_types::{TrieDB, TrieDBMut}; + +use sp_api::{decl_runtime_apis, impl_runtime_apis}; +use sp_runtime::{ + ApplyExtrinsicResult, create_runtime_str, Perbill, impl_opaque_keys, + transaction_validity::{ + TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction, + }, + traits::{ + BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, + GetNodeBlockType, GetRuntimeBlockType, Verify, IdentityLookup, + }, +}; +use sp_version::RuntimeVersion; +pub use sp_core::{hash::H256}; +#[cfg(any(feature = "std", test))] +use sp_version::NativeVersion; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use sp_inherents::{CheckInherentsResult, InherentData}; +use cfg_if::cfg_if; +use sp_core::storage::ChildType; + +// Ensure Babe and Aura use the same crypto to simplify things a bit. +pub use sp_consensus_babe::AuthorityId; +pub type AuraId = sp_consensus_aura::sr25519::AuthorityId; + +// Inlucde the WASM binary +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +/// Test runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("test"), + impl_name: create_runtime_str!("parity-test"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: RUNTIME_API_VERSIONS, +}; + +fn version() -> RuntimeVersion { + VERSION +} + +/// Native version. +#[cfg(any(feature = "std", test))] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +/// Calls in transactions. +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub struct Transfer { + pub from: AccountId, + pub to: AccountId, + pub amount: u64, + pub nonce: u64, +} + +impl Transfer { + /// Convert into a signed extrinsic. + #[cfg(feature = "std")] + pub fn into_signed_tx(self) -> Extrinsic { + let signature = sp_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, RuntimeDebug)] +pub enum Extrinsic { + AuthoritiesChange(Vec), + Transfer(Transfer, AccountSignature), + IncludeData(Vec), + StorageChange(Vec, Option>), +} + +#[cfg(feature = "std")] +impl serde::Serialize for Extrinsic { + fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { + self.using_encoded(|bytes| seq.serialize_bytes(bytes)) + } +} + +impl BlindCheckable for Extrinsic { + type Checked = Self; + + fn check(self) -> Result { + match self { + Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)), + Extrinsic::Transfer(transfer, signature) => { + if sp_runtime::verify_encoded_lazy(&signature, &transfer, &transfer.from) { + Ok(Extrinsic::Transfer(transfer, signature)) + } else { + Err(InvalidTransaction::BadProof.into()) + } + }, + Extrinsic::IncludeData(_) => Err(InvalidTransaction::BadProof.into()), + Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)), + } + } +} + +impl ExtrinsicT for Extrinsic { + type Call = Extrinsic; + type SignaturePayload = (); + + fn is_signed(&self) -> Option { + if let Extrinsic::IncludeData(_) = *self { + Some(false) + } else { + Some(true) + } + } + + fn new(call: Self::Call, _signature_payload: Option) -> Option { + Some(call) + } +} + +impl Extrinsic { + pub fn transfer(&self) -> &Transfer { + match self { + Extrinsic::Transfer(ref transfer, _) => transfer, + _ => panic!("cannot convert to transfer ref"), + } + } +} + +/// The signature type used by accounts/transactions. +pub type AccountSignature = sr25519::Signature; +/// An identifier for an account on this system. +pub type AccountId = ::Signer; +/// A simple hash type for all our hashing. +pub type Hash = H256; +/// The block number type used in this runtime. +pub type BlockNumber = u64; +/// Index of a transaction. +pub type Index = u64; +/// The item of a block digest. +pub type DigestItem = sp_runtime::generic::DigestItem; +/// The digest of a block. +pub type Digest = sp_runtime::generic::Digest; +/// A test block. +pub type Block = sp_runtime::generic::Block; +/// A test block's header. +pub type Header = sp_runtime::generic::Header; + +/// Run whatever tests we have. +pub fn run_tests(mut input: &[u8]) -> Vec { + use sp_runtime::print; + + print("run_tests..."); + let block = Block::decode(&mut input).unwrap(); + print("deserialized block."); + let stxs = block.extrinsics.iter().map(Encode::encode).collect::>(); + print("reserialized transactions."); + [stxs.len() as u8].encode() +} + +/// Changes trie configuration (optionally) used in tests. +pub fn changes_trie_config() -> sp_core::ChangesTrieConfiguration { + sp_core::ChangesTrieConfiguration { + digest_interval: 4, + digest_levels: 2, + } +} + +/// A type that can not be decoded. +#[derive(PartialEq)] +pub struct DecodeFails { + _phantom: PhantomData, +} + +impl Encode for DecodeFails { + fn encode(&self) -> Vec { + Vec::new() + } +} + +impl codec::EncodeLike for DecodeFails {} + +impl DecodeFails { + /// Create a new instance. + pub fn new() -> DecodeFails { + DecodeFails { + _phantom: Default::default(), + } + } +} + +impl Decode for DecodeFails { + fn decode(_: &mut I) -> Result { + Err("DecodeFails always fails".into()) + } +} + +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; + /// trie no_std testing + fn use_trie() -> u64; + fn benchmark_indirect_call() -> u64; + fn benchmark_direct_call() -> u64; + fn returns_mutable_static() -> u64; + fn allocates_huge_stack_array(trap: bool) -> Vec; + fn vec_with_capacity(size: u32) -> Vec; + /// Returns the initialized block number. + fn get_block_number() -> u64; + /// Takes and returns the initialized block number. + fn take_block_number() -> Option; + /// Returns if no block was initialized. + #[skip_initialize_block] + fn without_initialize_block() -> bool; + /// Test that `ed25519` crypto works in the runtime. + /// + /// Returns the signature generated for the message `ed25519` and the public key. + fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic); + /// Test that `sr25519` crypto works in the runtime. + /// + /// Returns the signature generated for the message `sr25519`. + fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); + /// Run various tests against storage. + fn test_storage(); + } + } + } else { + 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; + /// trie no_std testing + fn use_trie() -> u64; + fn benchmark_indirect_call() -> u64; + fn benchmark_direct_call() -> u64; + fn returns_mutable_static() -> u64; + fn allocates_huge_stack_array(trap: bool) -> Vec; + fn vec_with_capacity(size: u32) -> Vec; + /// Returns the initialized block number. + fn get_block_number() -> u64; + /// Takes and returns the initialized block number. + fn take_block_number() -> Option; + /// Returns if no block was initialized. + #[skip_initialize_block] + fn without_initialize_block() -> bool; + /// Test that `ed25519` crypto works in the runtime. + /// + /// Returns the signature generated for the message `ed25519` and the public key. + fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic); + /// Test that `sr25519` crypto works in the runtime. + /// + /// Returns the signature generated for the message `sr25519`. + fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); + /// Run various tests against storage. + fn test_storage(); + } + } + } +} + +#[derive(Clone, Eq, PartialEq)] +pub struct Runtime; + +impl GetNodeBlockType for Runtime { + type NodeBlock = Block; +} + +impl GetRuntimeBlockType for Runtime { + type RuntimeBlock = Block; +} + +impl_outer_origin!{ + pub enum Origin for Runtime where system = frame_system {} +} + +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] +pub struct Event; + +impl From for Event { + fn from(_evt: frame_system::Event) -> Self { + unimplemented!("Not required in tests!") + } +} + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub const MinimumPeriod: u64 = 5; + pub const MaximumBlockWeight: Weight = 4 * 1024 * 1024; + pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); +} + +impl frame_system::Trait for Runtime { + type Origin = Origin; + type Call = Extrinsic; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} + +impl pallet_timestamp::Trait for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; +} + +parameter_types! { + pub const EpochDuration: u64 = 6; + pub const ExpectedBlockTime: u64 = 10_000; +} + +impl pallet_babe::Trait for Runtime { + type EpochDuration = EpochDuration; + type ExpectedBlockTime = ExpectedBlockTime; + // there is no actual runtime in this test-runtime, so testing crates + // are manually adding the digests. normally in this situation you'd use + // pallet_babe::SameAuthoritiesForever. + type EpochChangeTrigger = pallet_babe::ExternalTrigger; +} + +/// Adds one to the given input and returns the final result. +#[inline(never)] +fn benchmark_add_one(i: u64) -> u64 { + i + 1 +} + +/// The `benchmark_add_one` function as function pointer. +#[cfg(not(feature = "std"))] +static BENCHMARK_ADD_ONE: sp_runtime_interface::wasm::ExchangeableFunction u64> = + sp_runtime_interface::wasm::ExchangeableFunction::new(benchmark_add_one); + +fn code_using_trie() -> u64 { + let pairs = [ + (b"0103000000000000000464".to_vec(), b"0400000000".to_vec()), + (b"0103000000000000000469".to_vec(), b"0401000000".to_vec()), + ].to_vec(); + + let mut mdb = PrefixedMemoryDB::default(); + let mut root = sp_std::default::Default::default(); + let _ = { + let v = &pairs; + let mut t = TrieDBMut::::new(&mut mdb, &mut root); + for i in 0..v.len() { + let key: &[u8]= &v[i].0; + let val: &[u8] = &v[i].1; + if !t.insert(key, val).is_ok() { + return 101; + } + } + t + }; + + if let Ok(trie) = TrieDB::::new(&mdb, &root) { + if let Ok(iter) = trie.iter() { + let mut iter_pairs = Vec::new(); + for pair in iter { + if let Ok((key, value)) = pair { + iter_pairs.push((key, value.to_vec())); + } + } + iter_pairs.len() as u64 + } else { 102 } + } else { 103 } +} + +impl_opaque_keys! { + pub struct SessionKeys { + pub ed25519: ed25519::AppPublic, + pub sr25519: sr25519::AppPublic, + } +} + +#[cfg(not(feature = "std"))] +/// Mutable static variables should be always observed to have +/// the initialized value at the start of a runtime call. +static mut MUTABLE_STATIC: u64 = 32; + +cfg_if! { + if #[cfg(feature = "std")] { + impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + version() + } + + fn execute_block(block: Block) { + system::execute_block(block) + } + + fn initialize_block(header: &::Header) { + system::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + unimplemented!() + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { + if let Extrinsic::IncludeData(data) = utx { + return Ok(ValidTransaction { + priority: data.len() as u64, + requires: vec![], + provides: vec![data], + longevity: 1, + propagate: false, + }); + } + + system::validate_transaction(utx) + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + system::execute_transaction(extrinsic) + } + + fn finalize_block() -> ::Header { + system::finalize_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 use_trie() -> u64 { + code_using_trie() + } + + 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)) + } + + fn returns_mutable_static() -> u64 { + unimplemented!("is not expected to be invoked from non-wasm builds"); + } + + fn allocates_huge_stack_array(_trap: bool) -> Vec { + unimplemented!("is not expected to be invoked from non-wasm builds"); + } + + fn vec_with_capacity(_size: u32) -> Vec { + unimplemented!("is not expected to be invoked from non-wasm builds"); + } + + fn get_block_number() -> u64 { + system::get_block_number().expect("Block number is initialized") + } + + fn without_initialize_block() -> bool { + system::get_block_number().is_none() + } + + fn take_block_number() -> Option { + system::take_block_number() + } + + fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { + test_ed25519_crypto() + } + + fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { + test_sr25519_crypto() + } + + fn test_storage() { + test_read_storage(); + test_read_child_storage(); + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { 1000 } + fn authorities() -> Vec { + system::authorities().into_iter().map(|a| { + let authority: sr25519::Public = a.into(); + AuraId::from(authority) + }).collect() + } + } + + impl sp_consensus_babe::BabeApi for Runtime { + fn configuration() -> sp_consensus_babe::BabeConfiguration { + sp_consensus_babe::BabeConfiguration { + slot_duration: 1000, + epoch_length: EpochDuration::get(), + c: (3, 10), + genesis_authorities: system::authorities() + .into_iter().map(|x|(x, 1)).collect(), + randomness: >::randomness(), + secondary_slots: true, + } + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + let ex = Extrinsic::IncludeData(header.number.encode()); + sp_io::offchain::submit_transaction(ex.encode()).unwrap(); + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(_: Option>) -> Vec { + SessionKeys::generate(None) + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(_account: AccountId) -> Index { + 0 + } + } + } + } else { + impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + version() + } + + fn execute_block(block: Block) { + system::execute_block(block) + } + + fn initialize_block(header: &::Header) { + system::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + unimplemented!() + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { + if let Extrinsic::IncludeData(data) = utx { + return Ok(ValidTransaction{ + priority: data.len() as u64, + requires: vec![], + provides: vec![data], + longevity: 1, + propagate: false, + }); + } + + system::validate_transaction(utx) + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + system::execute_transaction(extrinsic) + } + + fn finalize_block() -> ::Header { + system::finalize_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 use_trie() -> u64 { + code_using_trie() + } + + 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)) + } + + fn returns_mutable_static() -> u64 { + unsafe { + MUTABLE_STATIC += 1; + MUTABLE_STATIC + } + } + + fn allocates_huge_stack_array(trap: bool) -> Vec { + // Allocate a stack frame that is approx. 75% of the stack (assuming it is 1MB). + // This will just decrease (stacks in wasm32-u-u grow downwards) the stack + // pointer. This won't trap on the current compilers. + let mut data = [0u8; 1024 * 768]; + + // Then make sure we actually write something to it. + // + // If: + // 1. the stack area is placed at the beginning of the linear memory space, and + // 2. the stack pointer points to out-of-bounds area, and + // 3. a write is performed around the current stack pointer. + // + // then a trap should happen. + // + for (i, v) in data.iter_mut().enumerate() { + *v = i as u8; // deliberate truncation + } + + if trap { + // There is a small chance of this to be pulled up in theory. In practice + // the probability of that is rather low. + panic!() + } + + data.to_vec() + } + + fn vec_with_capacity(size: u32) -> Vec { + Vec::with_capacity(size as usize) + } + + fn get_block_number() -> u64 { + system::get_block_number().expect("Block number is initialized") + } + + fn without_initialize_block() -> bool { + system::get_block_number().is_none() + } + + fn take_block_number() -> Option { + system::take_block_number() + } + + fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { + test_ed25519_crypto() + } + + fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { + test_sr25519_crypto() + } + + fn test_storage() { + test_read_storage(); + test_read_child_storage(); + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { 1000 } + fn authorities() -> Vec { + system::authorities().into_iter().map(|a| { + let authority: sr25519::Public = a.into(); + AuraId::from(authority) + }).collect() + } + } + + impl sp_consensus_babe::BabeApi for Runtime { + fn configuration() -> sp_consensus_babe::BabeConfiguration { + sp_consensus_babe::BabeConfiguration { + slot_duration: 1000, + epoch_length: EpochDuration::get(), + c: (3, 10), + genesis_authorities: system::authorities() + .into_iter().map(|x|(x, 1)).collect(), + randomness: >::randomness(), + secondary_slots: true, + } + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + let ex = Extrinsic::IncludeData(header.number.encode()); + sp_io::offchain::submit_transaction(ex.encode()).unwrap() + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(_: Option>) -> Vec { + SessionKeys::generate(None) + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(_account: AccountId) -> Index { + 0 + } + } + } + } +} + +fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) { + let public0 = ed25519::AppPublic::generate_pair(None); + let public1 = ed25519::AppPublic::generate_pair(None); + let public2 = ed25519::AppPublic::generate_pair(None); + + let all = ed25519::AppPublic::all(); + assert!(all.contains(&public0)); + assert!(all.contains(&public1)); + assert!(all.contains(&public2)); + + let signature = public0.sign(&"ed25519").expect("Generates a valid `ed25519` signature."); + assert!(public0.verify(&"ed25519", &signature)); + (signature, public0) +} + +fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { + let public0 = sr25519::AppPublic::generate_pair(None); + let public1 = sr25519::AppPublic::generate_pair(None); + let public2 = sr25519::AppPublic::generate_pair(None); + + let all = sr25519::AppPublic::all(); + assert!(all.contains(&public0)); + assert!(all.contains(&public1)); + assert!(all.contains(&public2)); + + let signature = public0.sign(&"sr25519").expect("Generates a valid `sr25519` signature."); + assert!(public0.verify(&"sr25519", &signature)); + (signature, public0) +} + +fn test_read_storage() { + const KEY: &[u8] = b":read_storage"; + sp_io::storage::set(KEY, b"test"); + + let mut v = [0u8; 4]; + let r = sp_io::storage::read( + KEY, + &mut v, + 0 + ); + assert_eq!(r, Some(4)); + assert_eq!(&v, b"test"); + + let mut v = [0u8; 4]; + let r = sp_io::storage::read(KEY, &mut v, 8); + assert_eq!(r, Some(4)); + assert_eq!(&v, &[0, 0, 0, 0]); +} + +fn test_read_child_storage() { + const CHILD_KEY: &[u8] = b":child_storage:default:read_child_storage"; + const UNIQUE_ID: &[u8] = b":unique_id"; + const KEY: &[u8] = b":read_child_storage"; + sp_io::storage::child_set( + CHILD_KEY, + UNIQUE_ID, + ChildType::CryptoUniqueId as u32, + KEY, + b"test", + ); + + let mut v = [0u8; 4]; + let r = sp_io::storage::child_read( + CHILD_KEY, + UNIQUE_ID, + ChildType::CryptoUniqueId as u32, + KEY, + &mut v, + 0, + ); + assert_eq!(r, Some(4)); + assert_eq!(&v, b"test"); + + let mut v = [0u8; 4]; + let r = sp_io::storage::child_read( + CHILD_KEY, + UNIQUE_ID, + ChildType::CryptoUniqueId as u32, + KEY, + &mut v, + 8, + ); + assert_eq!(r, Some(4)); + assert_eq!(&v, &[0, 0, 0, 0]); +} + +#[cfg(test)] +mod tests { + use substrate_test_runtime_client::{ + prelude::*, + sp_consensus::BlockOrigin, + DefaultTestClientBuilderExt, TestClientBuilder, + runtime::TestAPI, + }; + use sp_api::ProvideRuntimeApi; + use sp_runtime::generic::BlockId; + use sp_core::storage::well_known_keys::HEAP_PAGES; + use sp_state_machine::ExecutionStrategy; + use codec::Encode; + + #[test] + fn returns_mutable_static() { + let client = TestClientBuilder::new() + .set_execution_strategy(ExecutionStrategy::AlwaysWasm) + .build(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.chain_info().best_number); + + let ret = runtime_api.returns_mutable_static(&block_id).unwrap(); + assert_eq!(ret, 33); + + // We expect that every invocation will need to return the initial + // value plus one. If the value increases more than that then it is + // a sign that the wasm runtime preserves the memory content. + let ret = runtime_api.returns_mutable_static(&block_id).unwrap(); + assert_eq!(ret, 33); + } + + // If we didn't restore the wasm instance properly, on a trap the stack pointer would not be + // returned to its initial value and thus the stack space is going to be leaked. + // + // See https://github.com/paritytech/substrate/issues/2967 for details + #[test] + fn restoration_of_globals() { + // Allocate 32 pages (of 65536 bytes) which gives the runtime 2048KB of heap to operate on + // (plus some additional space unused from the initial pages requested by the wasm runtime + // module). + // + // The fixture performs 2 allocations of 768KB and this theoretically gives 1536KB, however, due + // to our allocator algorithm there are inefficiencies. + const REQUIRED_MEMORY_PAGES: u64 = 32; + + let client = TestClientBuilder::new() + .set_execution_strategy(ExecutionStrategy::AlwaysWasm) + .set_heap_pages(REQUIRED_MEMORY_PAGES) + .build(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.chain_info().best_number); + + // On the first invocation we allocate approx. 768KB (75%) of stack and then trap. + let ret = runtime_api.allocates_huge_stack_array(&block_id, true); + assert!(ret.is_err()); + + // On the second invocation we allocate yet another 768KB (75%) of stack + let ret = runtime_api.allocates_huge_stack_array(&block_id, false); + assert!(ret.is_ok()); + } + + #[test] + fn heap_pages_is_respected() { + // This tests that the on-chain HEAP_PAGES parameter is respected. + + // Create a client devoting only 8 pages of wasm memory. This gives us ~512k of heap memory. + let mut client = TestClientBuilder::new() + .set_execution_strategy(ExecutionStrategy::AlwaysWasm) + .set_heap_pages(8) + .build(); + let block_id = BlockId::Number(client.chain_info().best_number); + + // Try to allocate 1024k of memory on heap. This is going to fail since it is twice larger + // than the heap. + let ret = client.runtime_api().vec_with_capacity(&block_id, 1048576); + assert!(ret.is_err()); + + // Create a block that sets the `:heap_pages` to 32 pages of memory which corresponds to + // ~2048k of heap memory. + let (new_block_id, block) = { + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push_storage_change(HEAP_PAGES.to_vec(), Some(32u64.encode())).unwrap(); + let block = builder.build().unwrap().block; + let hash = block.header.hash(); + (BlockId::Hash(hash), block) + }; + + client.import(BlockOrigin::Own, block).unwrap(); + + // Allocation of 1024k while having ~2048k should succeed. + let ret = client.runtime_api().vec_with_capacity(&new_block_id, 1048576); + assert!(ret.is_ok()); + } + + #[test] + fn test_storage() { + let client = TestClientBuilder::new() + .set_execution_strategy(ExecutionStrategy::Both) + .build(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.chain_info().best_number); + + runtime_api.test_storage(&block_id).unwrap(); + } +} diff --git a/test-utils/runtime/src/system.rs b/test-utils/runtime/src/system.rs new file mode 100644 index 0000000000000..b04ebc1cf2f56 --- /dev/null +++ b/test-utils/runtime/src/system.rs @@ -0,0 +1,482 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code +//! and depositing logs. + +use sp_std::prelude::*; +use sp_io::{ + storage::root as storage_root, storage::changes_root as storage_changes_root, + hashing::blake2_256, trie, +}; +use frame_support::storage; +use frame_support::{decl_storage, decl_module}; +use sp_runtime::{ + traits::Header as _, generic, ApplyExtrinsicResult, + transaction_validity::{ + TransactionValidity, ValidTransaction, InvalidTransaction, TransactionValidityError, + }, +}; +use codec::{KeyedVec, Encode, Decode}; +use frame_system::Trait; +use crate::{ + AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId +}; +use sp_core::storage::well_known_keys; + +const NONCE_OF: &[u8] = b"nonce:"; +const BALANCE_OF: &[u8] = b"balance:"; + +decl_module! { + pub struct Module for enum Call where origin: T::Origin {} +} + +decl_storage! { + trait Store for Module as TestRuntime { + ExtrinsicData: map u32 => Vec; + // The current block number being processed. Set by `execute_block`. + Number get(fn number): Option; + ParentHash get(fn parent_hash): Hash; + NewAuthorities get(fn new_authorities): Option>; + StorageDigest get(fn storage_digest): Option; + Authorities get(fn authorities) config(): Vec; + } +} + +pub fn balance_of_key(who: AccountId) -> Vec { + who.to_keyed_vec(BALANCE_OF) +} + +pub fn balance_of(who: AccountId) -> u64 { + storage::hashed::get_or(&blake2_256, &balance_of_key(who), 0) +} + +pub fn nonce_of(who: AccountId) -> u64 { + storage::hashed::get_or(&blake2_256, &who.to_keyed_vec(NONCE_OF), 0) +} + +pub fn initialize_block(header: &Header) { + // populate environment. + ::put(&header.number); + ::put(&header.parent_hash); + ::put(header.digest()); + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); + + // try to read something that depends on current header digest + // so that it'll be included in execution proof + if let Some(generic::DigestItem::Other(v)) = header.digest().logs().iter().next() { + let _: Option = storage::unhashed::get(&v); + } +} + +pub fn authorities() -> Vec { + Authorities::get() +} + +pub fn get_block_number() -> Option { + Number::get() +} + +pub fn take_block_number() -> Option { + Number::take() +} + +#[derive(Copy, Clone)] +enum Mode { + Verify, + Overwrite, +} + +/// Actually execute all transitioning for `block`. +pub fn polish_block(block: &mut Block) { + execute_block_with_state_root_handler(block, Mode::Overwrite); +} + +pub fn execute_block(mut block: Block) { + execute_block_with_state_root_handler(&mut block, Mode::Verify); +} + +fn execute_block_with_state_root_handler(block: &mut Block, mode: Mode) { + let header = &mut block.header; + + initialize_block(header); + + // execute transactions + block.extrinsics.iter().for_each(|e| { + let _ = execute_transaction(e.clone()).unwrap_or_else(|_| panic!("Invalid transaction")); + }); + + let new_header = finalize_block(); + + if let Mode::Overwrite = mode { + header.state_root = new_header.state_root; + } else { + info_expect_equal_hash(&new_header.state_root, &header.state_root); + assert!( + new_header.state_root == header.state_root, + "Storage root must match that calculated.", + ); + } + + if let Mode::Overwrite = mode { + header.extrinsics_root = new_header.extrinsics_root; + } else { + info_expect_equal_hash(&new_header.extrinsics_root, &header.extrinsics_root); + assert!( + new_header.extrinsics_root == header.extrinsics_root, + "Transaction trie root must be valid.", + ); + } +} + +/// The block executor. +pub struct BlockExecutor; + +impl frame_executive::ExecuteBlock for BlockExecutor { + fn execute_block(block: Block) { + execute_block(block); + } +} + +/// 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 { + if check_signature(&utx).is_err() { + return InvalidTransaction::BadProof.into(); + } + + let tx = utx.transfer(); + let nonce_key = tx.from.to_keyed_vec(NONCE_OF); + let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); + if tx.nonce < expected_nonce { + return InvalidTransaction::Stale.into(); + } + if tx.nonce > expected_nonce + 64 { + return InvalidTransaction::Future.into(); + } + + let encode = |from: &AccountId, nonce: u64| (from, nonce).encode(); + let requires = if tx.nonce != expected_nonce && tx.nonce > 0 { + vec![encode(&tx.from, tx.nonce - 1)] + } else { + vec![] + }; + + let provides = vec![encode(&tx.from, tx.nonce)]; + + Ok(ValidTransaction { + priority: tx.amount, + requires, + provides, + longevity: 64, + propagate: true, + }) +} + +/// 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) -> ApplyExtrinsicResult { + let extrinsic_index: u32 = storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap(); + let result = execute_transaction_backend(&utx); + ExtrinsicData::insert(extrinsic_index, utx.encode()); + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(extrinsic_index + 1)); + result +} + +/// Finalize the block. +pub fn finalize_block() -> Header { + let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap(); + let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect(); + let extrinsics_root = trie::blake2_256_ordered_root(txs).into(); + let number = ::take().expect("Number is set by `initialize_block`"); + let parent_hash = ::take(); + let mut digest = ::take().expect("StorageDigest is set by `initialize_block`"); + + let o_new_authorities = ::take(); + // This MUST come after all changes to storage are done. Otherwise we will fail the + // “Storage root does not match that calculated” assertion. + let storage_root = Hash::decode(&mut &storage_root()[..]) + .expect("`storage_root` is a valid hash"); + let storage_changes_root = storage_changes_root(&parent_hash.encode()) + .map(|r| Hash::decode(&mut &r[..]).expect("`storage_changes_root` is a valid hash")); + + if let Some(storage_changes_root) = storage_changes_root { + digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root)); + } + + if let Some(new_authorities) = o_new_authorities { + digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode())); + digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode())); + } + + Header { + number, + extrinsics_root, + state_root: storage_root, + parent_hash, + digest: digest, + } +} + +#[inline(always)] +fn check_signature(utx: &Extrinsic) -> Result<(), TransactionValidityError> { + use sp_runtime::traits::BlindCheckable; + utx.clone().check().map_err(|_| InvalidTransaction::BadProof.into()).map(|_| ()) +} + +fn execute_transaction_backend(utx: &Extrinsic) -> ApplyExtrinsicResult { + check_signature(utx)?; + match utx { + Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), + Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), + Extrinsic::IncludeData(_) => Ok(Ok(())), + Extrinsic::StorageChange(key, value) => execute_storage_change(key, value.as_ref().map(|v| &**v)), + } +} + +fn execute_transfer_backend(tx: &Transfer) -> ApplyExtrinsicResult { + // check nonce + let nonce_key = tx.from.to_keyed_vec(NONCE_OF); + let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); + if !(tx.nonce == expected_nonce) { + return Err(InvalidTransaction::Stale.into()); + } + + // increment nonce in storage + storage::hashed::put(&blake2_256, &nonce_key, &(expected_nonce + 1)); + + // check sender balance + let from_balance_key = tx.from.to_keyed_vec(BALANCE_OF); + let from_balance: u64 = storage::hashed::get_or(&blake2_256, &from_balance_key, 0); + + // enact transfer + if !(tx.amount <= from_balance) { + return Err(InvalidTransaction::Payment.into()); + } + let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); + let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); + storage::hashed::put(&blake2_256, &from_balance_key, &(from_balance - tx.amount)); + storage::hashed::put(&blake2_256, &to_balance_key, &(to_balance + tx.amount)); + Ok(Ok(())) +} + +fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyExtrinsicResult { + NewAuthorities::put(new_authorities.to_vec()); + Ok(Ok(())) +} + +fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyExtrinsicResult { + match value { + Some(value) => storage::unhashed::put_raw(key, value), + None => storage::unhashed::kill(key), + } + Ok(Ok(())) +} + +#[cfg(feature = "std")] +fn info_expect_equal_hash(given: &Hash, expected: &Hash) { + use sp_core::hexdisplay::HexDisplay; + if given != expected { + println!( + "Hash: given={}, expected={}", + HexDisplay::from(given.as_fixed_bytes()), + HexDisplay::from(expected.as_fixed_bytes()), + ); + } +} + +#[cfg(not(feature = "std"))] +fn info_expect_equal_hash(given: &Hash, expected: &Hash) { + if given != expected { + sp_runtime::print("Hash not equal"); + sp_runtime::print(given.as_bytes()); + sp_runtime::print(expected.as_bytes()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use sp_io::TestExternalities; + use substrate_test_runtime_client::{AccountKeyring, Sr25519Keyring}; + use crate::{Header, Transfer, WASM_BINARY}; + use sp_core::{NeverNativeValue, map, traits::CodeExecutor}; + use sc_executor::{NativeExecutor, WasmExecutionMethod, native_executor_instance}; + use sp_io::hashing::twox_128; + + // Declare an instance of the native executor dispatch for the test runtime. + native_executor_instance!( + NativeDispatch, + crate::api::dispatch, + crate::native_version + ); + + fn executor() -> NativeExecutor { + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + } + + fn new_test_ext() -> TestExternalities { + let authorities = vec![ + Sr25519Keyring::Alice.to_raw_public(), + Sr25519Keyring::Bob.to_raw_public(), + Sr25519Keyring::Charlie.to_raw_public() + ]; + TestExternalities::new_with_code( + WASM_BINARY, + sp_core::storage::Storage { + top: map![ + twox_128(b"latest").to_vec() => vec![69u8; 32], + twox_128(b"sys:auth").to_vec() => authorities.encode(), + blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0] + } + ], + children: map![], + }, + ) + } + + 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: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), + }; + let mut b = Block { + header: h, + extrinsics: vec![], + }; + + new_test_ext().execute_with(|| polish_block(&mut b)); + + block_executor(b, &mut new_test_ext()); + } + + #[test] + fn block_import_works_native() { + block_import_works(|b, ext| ext.execute_with(|| execute_block(b))); + } + + #[test] + fn block_import_works_wasm() { + block_import_works(|b, ext| { + let mut ext = ext.ext(); + executor().call::<_, NeverNativeValue, fn() -> _>( + &mut ext, + "Core_execute_block", + &b.encode(), + false, + None, + ).0.unwrap(); + }) + } + + fn block_import_with_transaction_works(block_executor: F) + where F: Fn(Block, &mut TestExternalities) + { + let mut b1 = Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), + }, + extrinsics: vec![ + Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), + amount: 69, + nonce: 0, + }.into_signed_tx() + ], + }; + + let mut dummy_ext = new_test_ext(); + dummy_ext.execute_with(|| polish_block(&mut b1)); + + let mut b2 = Block { + header: Header { + parent_hash: b1.header.hash(), + number: 2, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), + }, + extrinsics: vec![ + Transfer { + from: AccountKeyring::Bob.into(), + to: AccountKeyring::Alice.into(), + amount: 27, + nonce: 0, + }.into_signed_tx(), + Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Charlie.into(), + amount: 69, + nonce: 1, + }.into_signed_tx(), + ], + }; + + dummy_ext.execute_with(|| polish_block(&mut b2)); + drop(dummy_ext); + + let mut t = new_test_ext(); + + t.execute_with(|| { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 111); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 0); + }); + + block_executor(b1, &mut t); + + t.execute_with(|| { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 42); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 69); + }); + + block_executor(b2, &mut t); + + t.execute_with(|| { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 0); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 42); + assert_eq!(balance_of(AccountKeyring::Charlie.into()), 69); + }); + } + + #[test] + fn block_import_with_transaction_works_native() { + block_import_with_transaction_works(|b, ext| ext.execute_with(|| execute_block(b))); + } + + #[test] + fn block_import_with_transaction_works_wasm() { + block_import_with_transaction_works(|b, ext| { + let mut ext = ext.ext(); + executor().call::<_, NeverNativeValue, fn() -> _>( + &mut ext, + "Core_execute_block", + &b.encode(), + false, + None, + ).0.unwrap(); + }) + } +} diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs new file mode 100644 index 0000000000000..c1a18a1fa7a3b --- /dev/null +++ b/test-utils/src/lib.rs @@ -0,0 +1,54 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utils + +/// Panic when the vectors are different, without taking the order into account. +/// +/// # Examples +/// +/// ```rust +/// #[macro_use] +/// # use substrate_test_utils::{assert_eq_uvec}; +/// # fn main() { +/// assert_eq_uvec!(vec![1,2], vec![2,1]); +/// # } +/// ``` +/// +/// ```rust,should_panic +/// #[macro_use] +/// # use substrate_test_utils::{assert_eq_uvec}; +/// # fn main() { +/// assert_eq_uvec!(vec![1,2,3], vec![2,1]); +/// # } +/// ``` +#[macro_export] +macro_rules! assert_eq_uvec { + ( $x:expr, $y:expr ) => { + $crate::__assert_eq_uvec!($x, $y); + $crate::__assert_eq_uvec!($y, $x); + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __assert_eq_uvec { + ( $x:expr, $y:expr ) => { + $x.iter().for_each(|e| { + if !$y.contains(e) { panic!(format!("vectors not equal: {:?} != {:?}", $x, $y)); } + }); + } +} diff --git a/test-utils/transaction-factory/Cargo.toml b/test-utils/transaction-factory/Cargo.toml deleted file mode 100644 index e53972eec65c5..0000000000000 --- a/test-utils/transaction-factory/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "transaction-factory" -version = "0.0.1" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -cli = { package = "substrate-cli", path = "../../core/cli" } -client = { package = "substrate-client", path = "../../core/client" } -consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } -log = "0.4.8" -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -substrate-service = { path = "../../core/service" } - -[features] -default = ["std"] -std = [ - "codec/std", - "sr-primitives/std", -] diff --git a/test-utils/transaction-factory/src/lib.rs b/test-utils/transaction-factory/src/lib.rs deleted file mode 100644 index 067c75c3fc344..0000000000000 --- a/test-utils/transaction-factory/src/lib.rs +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Simple transaction factory which distributes tokens from a master -//! account to a specified number of newly created accounts. -//! -//! The factory currently only works on an empty database! - -use std::collections::HashMap; -use std::sync::Arc; -use std::cmp::PartialOrd; -use std::fmt::Display; - -use log::info; - -use client::{Client, block_builder::api::BlockBuilder, runtime_api::ConstructRuntimeApi}; -use consensus_common::{ - BlockOrigin, BlockImportParams, InherentData, ForkChoiceStrategy, - SelectChain -}; -use consensus_common::block_import::BlockImport; -use codec::{Decode, Encode}; -use primitives::{Blake2Hasher, Hasher}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ - Block as BlockT, Header as HeaderT, ProvideRuntimeApi, SimpleArithmetic, - One, Zero, -}; -pub use crate::modes::Mode; - -pub mod modes; -mod complex_mode; -mod simple_modes; - -pub trait RuntimeAdapter { - type AccountId: Display; - type Balance: Display + SimpleArithmetic + From; - type Block: BlockT; - type Index: Copy; - type Number: Display + PartialOrd + SimpleArithmetic + Zero + One; - type Phase: Copy; - type Secret; - - fn new(mode: Mode, rounds: u64, start_number: u64) -> Self; - - fn block_no(&self) -> Self::Number; - fn block_in_round(&self) -> Self::Number; - fn mode(&self) -> &Mode; - fn num(&self) -> Self::Number; - fn rounds(&self) -> Self::Number; - fn round(&self) -> Self::Number; - fn start_number(&self) -> Self::Number; - - fn set_block_in_round(&mut self, val: Self::Number); - fn set_block_no(&mut self, val: Self::Number); - fn set_round(&mut self, val: Self::Number); - - fn transfer_extrinsic( - &self, - sender: &Self::AccountId, - key: &Self::Secret, - destination: &Self::AccountId, - amount: &Self::Balance, - version: u32, - genesis_hash: &::Hash, - prior_block_hash: &::Hash, - ) -> ::Extrinsic; - - fn inherent_extrinsics(&self) -> InherentData; - - fn minimum_balance() -> Self::Balance; - fn master_account_id() -> Self::AccountId; - fn master_account_secret() -> Self::Secret; - fn extract_index(&self, account_id: &Self::AccountId, block_hash: &::Hash) -> Self::Index; - fn extract_phase(&self, block_hash: ::Hash) -> Self::Phase; - fn gen_random_account_id(seed: &Self::Number) -> Self::AccountId; - fn gen_random_account_secret(seed: &Self::Number) -> Self::Secret; -} - -/// Manufactures transactions. The exact amount depends on -/// `mode`, `num` and `rounds`. -pub fn factory( - mut factory_state: RA, - client: &Arc>, - select_chain: &Sc, -) -> cli::error::Result<()> -where - Block: BlockT::Out>, - Exec: client::CallExecutor + Send + Sync + Clone, - Backend: client::backend::Backend + Send, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilder, - RtApi: ConstructRuntimeApi> + Send + Sync, - Sc: SelectChain, - RA: RuntimeAdapter, - <::Block as BlockT>::Hash: From, -{ - if *factory_state.mode() != Mode::MasterToNToM && factory_state.rounds() > RA::Number::one() { - let msg = "The factory can only be used with rounds set to 1 in this mode.".into(); - return Err(cli::error::Error::Input(msg)); - } - - let best_header: Result<::Header, cli::error::Error> = - select_chain.best_chain().map_err(|e| format!("{:?}", e).into()); - let mut best_hash = best_header?.hash(); - let mut best_block_id = BlockId::::hash(best_hash); - let version = client.runtime_version_at(&best_block_id)?.spec_version; - let genesis_hash = client.block_hash(Zero::zero())? - .expect("Genesis block always exists; qed").into(); - - while let Some(block) = match factory_state.mode() { - Mode::MasterToNToM => complex_mode::next::( - &mut factory_state, - &client, - version, - genesis_hash, - best_hash.into(), - best_block_id, - ), - _ => simple_modes::next::( - &mut factory_state, - &client, - version, - genesis_hash, - best_hash.into(), - best_block_id, - ), - } { - best_hash = block.header().hash(); - best_block_id = BlockId::::hash(best_hash); - import_block(&client, block); - - info!("Imported block at {}", factory_state.block_no()); - } - - Ok(()) -} - -/// Create a baked block from a transfer extrinsic and timestamp inherent. -pub fn create_block( - client: &Arc>, - transfer: ::Extrinsic, - inherent_extrinsics: Vec<::Extrinsic>, -) -> Block -where - Block: BlockT::Out>, - Exec: client::CallExecutor + Send + Sync + Clone, - Backend: client::backend::Backend + Send, - Client: ProvideRuntimeApi, - RtApi: ConstructRuntimeApi> + Send + Sync, - as ProvideRuntimeApi>::Api: BlockBuilder, - RA: RuntimeAdapter, -{ - let mut block = client.new_block(Default::default()).expect("Failed to create new block"); - block.push( - Decode::decode(&mut &transfer.encode()[..]) - .expect("Failed to decode transfer extrinsic") - ).expect("Failed to push transfer extrinsic into block"); - - for inherent in inherent_extrinsics { - block.push(inherent).expect("Failed ..."); - } - - block.bake().expect("Failed to bake block") -} - -fn import_block( - client: &Arc>, - block: Block -) -> () where - Block: BlockT::Out>, - Exec: client::CallExecutor + Send + Sync + Clone, - Backend: client::backend::Backend + Send, -{ - let import = BlockImportParams { - origin: BlockOrigin::File, - header: block.header().clone(), - post_digests: Vec::new(), - body: Some(block.extrinsics().to_vec()), - finalized: false, - justification: None, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - }; - (&**client).import_block(import, HashMap::new()).expect("Failed to import block"); -} diff --git a/utils/browser/Cargo.toml b/utils/browser/Cargo.toml new file mode 100644 index 0000000000000..b58774075b34b --- /dev/null +++ b/utils/browser/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "browser-utils" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Utilities for creating a browser light-client." +edition = "2018" + +[dependencies] +futures = "0.3" +futures01 = { package = "futures", version = "0.1.29" } +log = "0.4.8" +libp2p = { version = "0.14.0-alpha.1", default-features = false } +console_error_panic_hook = "0.1.6" +console_log = "0.1.2" +js-sys = "0.3.34" +wasm-bindgen = "0.2.57" +wasm-bindgen-futures = "0.4.7" +kvdb-web = "0.3" +service = { version = "2.0.0", package = "sc-service", path = "../../client/service", default-features = false } +network = { package = "sc-network", path = "../../client/network" } +chain-spec = { package = "sc-chain-spec", path = "../../client/chain-spec" } + +# Imported just for the `no_cc` feature +clear_on_drop = { version = "0.2.3", features = ["no_cc"] } +# Imported just for the `wasm-bindgen` feature +rand6 = { package = "rand", version = "0.6", features = ["wasm-bindgen"] } +rand = { version = "0.7", features = ["wasm-bindgen"] } diff --git a/utils/browser/src/lib.rs b/utils/browser/src/lib.rs new file mode 100644 index 0000000000000..e404c6612906c --- /dev/null +++ b/utils/browser/src/lib.rs @@ -0,0 +1,173 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use futures01::sync::mpsc as mpsc01; +use log::{debug, info}; +use std::sync::Arc; +use service::{ + AbstractService, RpcSession, Roles, Configuration, config::{DatabaseConfig, KeystoreConfig}, + ChainSpec, RuntimeGenesis +}; +use wasm_bindgen::prelude::*; +use futures::{ + TryFutureExt as _, FutureExt as _, Stream as _, Future as _, TryStreamExt as _, + channel::{oneshot, mpsc}, future::{poll_fn, ok}, compat::*, +}; +use std::task::Poll; +use std::pin::Pin; +use chain_spec::Extension; + +pub use libp2p::wasm_ext::{ExtTransport, ffi::Transport}; +pub use console_error_panic_hook::set_once as set_console_error_panic_hook; +pub use console_log::init_with_level as init_console_log; + +/// Create a service configuration from a chain spec and the websocket transport. +/// +/// This configuration contains good defaults for a browser light client. +pub async fn browser_configuration( + transport: Transport, + chain_spec: ChainSpec, +) -> Result, Box> +where + C: Default, + G: RuntimeGenesis, + E: Extension, +{ + let name = chain_spec.name().to_string(); + + let transport = ExtTransport::new(transport); + let mut config = Configuration::default_with_spec_and_base_path(chain_spec, None); + config.network.transport = network::config::TransportConfig::Normal { + wasm_external_transport: Some(transport.clone()), + allow_private_ipv4: true, + enable_mdns: false, + }; + config.telemetry_external_transport = Some(transport); + config.roles = Roles::LIGHT; + config.name = format!("{} (Browser)", name); + config.database = { + info!("Opening Indexed DB database '{}'...", name); + let db = kvdb_web::Database::open(name, 10) + .await?; + DatabaseConfig::Custom(Arc::new(db)) + }; + config.keystore = KeystoreConfig::InMemory; + + Ok(config) +} + +/// A running client. +#[wasm_bindgen] +pub struct Client { + rpc_send_tx: mpsc::UnboundedSender, +} + +struct RpcMessage { + rpc_json: String, + session: RpcSession, + send_back: oneshot::Sender> + Send>>>, +} + +/// Create a Client object that connects to a service. +pub fn start_client(service: impl AbstractService) -> Client { + let mut service = service.compat(); + // We dispatch a background task responsible for processing the service. + // + // The main action performed by the code below consists in polling the service with + // `service.poll()`. + // The rest consists in handling RPC requests. + let (rpc_send_tx, mut rpc_send_rx) = mpsc::unbounded::(); + wasm_bindgen_futures::spawn_local(poll_fn(move |cx| { + loop { + match Pin::new(&mut rpc_send_rx).poll_next(cx) { + Poll::Ready(Some(message)) => { + let fut = service.get_ref() + .rpc_query(&message.session, &message.rpc_json) + .compat() + .unwrap_or_else(|_| None) + .boxed(); + let _ = message.send_back.send(fut); + }, + Poll::Pending => break, + Poll::Ready(None) => return Poll::Ready(()), + } + } + + Pin::new(&mut service) + .poll(cx) + .map(drop) + })); + + Client { + rpc_send_tx, + } +} + +#[wasm_bindgen] +impl Client { + /// Allows starting an RPC request. Returns a `Promise` containing the result of that request. + #[wasm_bindgen(js_name = "rpcSend")] + pub fn rpc_send(&mut self, rpc: &str) -> js_sys::Promise { + let rpc_session = RpcSession::new(mpsc01::channel(1).0); + let (tx, rx) = oneshot::channel(); + let _ = self.rpc_send_tx.unbounded_send(RpcMessage { + rpc_json: rpc.to_owned(), + session: rpc_session, + send_back: tx, + }); + wasm_bindgen_futures::future_to_promise(async { + match rx.await { + Ok(fut) => { + fut.await + .map(|s| JsValue::from_str(&s)) + .ok_or_else(|| JsValue::NULL) + }, + Err(_) => Err(JsValue::NULL) + } + }) + } + + /// Subscribes to an RPC pubsub endpoint. + #[wasm_bindgen(js_name = "rpcSubscribe")] + pub fn rpc_subscribe(&mut self, rpc: &str, callback: js_sys::Function) { + let (tx, rx) = mpsc01::channel(4); + let rpc_session = RpcSession::new(tx); + let (fut_tx, fut_rx) = oneshot::channel(); + let _ = self.rpc_send_tx.unbounded_send(RpcMessage { + rpc_json: rpc.to_owned(), + session: rpc_session.clone(), + send_back: fut_tx, + }); + wasm_bindgen_futures::spawn_local(async { + if let Ok(fut) = fut_rx.await { + fut.await; + } + }); + + wasm_bindgen_futures::spawn_local(async move { + let _ = rx.compat() + .try_for_each(|s| { + let _ = callback.call1(&callback, &JsValue::from_str(&s)); + ok(()) + }) + .await; + + // We need to keep `rpc_session` alive. + debug!("RPC subscription has ended"); + drop(rpc_session); + }); + } +} diff --git a/utils/build-script-utils/Cargo.toml b/utils/build-script-utils/Cargo.toml new file mode 100644 index 0000000000000..36703ab838f06 --- /dev/null +++ b/utils/build-script-utils/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "substrate-build-script-utils" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] diff --git a/utils/build-script-utils/src/lib.rs b/utils/build-script-utils/src/lib.rs new file mode 100644 index 0000000000000..1b915bdcafacb --- /dev/null +++ b/utils/build-script-utils/src/lib.rs @@ -0,0 +1,44 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Crate with utility functions for `build.rs` scripts. + +use std::{env, path::PathBuf}; + +/// Make sure the calling `build.rs` script is rerun when `.git/HEAD` changed. +/// +/// The file is searched from the `CARGO_MANIFEST_DIR` upwards. If the file can not be found, +/// a warning is generated. +pub fn rerun_if_git_head_changed() { + let mut manifest_dir = PathBuf::from( + env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo.") + ); + let manifest_dir_copy = manifest_dir.clone(); + + while manifest_dir.parent().is_some() { + if manifest_dir.join(".git/HEAD").exists() { + println!("cargo:rerun-if-changed={}", manifest_dir.join(".git/HEAD").display()); + return + } + + manifest_dir.pop(); + } + + println!( + "cargo:warning=Could not find `.git/HEAD` searching from `{}` upwards!", + manifest_dir_copy.display(), + ); +} diff --git a/core/utils/fork-tree/Cargo.toml b/utils/fork-tree/Cargo.toml similarity index 100% rename from core/utils/fork-tree/Cargo.toml rename to utils/fork-tree/Cargo.toml diff --git a/utils/fork-tree/src/lib.rs b/utils/fork-tree/src/lib.rs new file mode 100644 index 0000000000000..1aa085c3da485 --- /dev/null +++ b/utils/fork-tree/src/lib.rs @@ -0,0 +1,1327 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Utility library for managing tree-like ordered data with logic for pruning +//! the tree while finalizing nodes. + +#![warn(missing_docs)] + +use std::cmp::Reverse; +use std::fmt; +use codec::{Decode, Encode}; + +/// Error occured when iterating with the tree. +#[derive(Clone, Debug, PartialEq)] +pub enum Error { + /// Adding duplicate node to tree. + Duplicate, + /// Finalizing descendent of tree node without finalizing ancestor(s). + UnfinalizedAncestor, + /// Imported or finalized node that is an ancestor of previously finalized node. + Revert, + /// Error throw by client when checking for node ancestry. + Client(E), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let message = match *self { + Error::Duplicate => "Hash already exists in Tree".into(), + Error::UnfinalizedAncestor => "Finalized descendent of Tree node without finalizing its ancestor(s) first".into(), + Error::Revert => "Tried to import or finalize node that is an ancestor of a previously finalized node".into(), + Error::Client(ref err) => format!("Client error: {}", err), + }; + write!(f, "{}", message) + } +} + +impl std::error::Error for Error { + fn cause(&self) -> Option<&dyn std::error::Error> { + None + } +} + +impl From for Error { + fn from(err: E) -> Error { + Error::Client(err) + } +} + +/// Result of finalizing a node (that could be a part of the tree or not). +#[derive(Debug, PartialEq)] +pub enum FinalizationResult { + /// The tree has changed, optionally return the value associated with the finalized node. + Changed(Option), + /// The tree has not changed. + Unchanged, +} + +/// 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 + Clone, + N: Ord + Clone, + V: Clone, +{ + /// Prune the tree, removing all non-canonical nodes. We find the node in the + /// tree that is the deepest ancestor of the given hash and that passes the + /// given predicate. If such a node exists, we re-root the tree to this + /// node. Otherwise the tree remains unchanged. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is a + /// descendent of the first hash (base). + pub fn prune( + &mut self, + hash: &H, + number: &N, + is_descendent_of: &F, + predicate: &P, + ) -> Result<(), Error> + where E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + let new_root = self.find_node_where( + hash, + number, + is_descendent_of, + predicate, + )?; + + if let Some(root) = new_root { + let mut root = root.clone(); + + // we found the deepest ancestor of the finalized block, so we prune + // out any children that don't include the finalized block. + let children = std::mem::replace(&mut root.children, Vec::new()); + root.children = children.into_iter().filter(|node| { + node.number == *number && node.hash == *hash || + node.number < *number && is_descendent_of(&node.hash, hash).unwrap_or(false) + }).take(1).collect(); + + self.roots = vec![root]; + } + + self.rebalance(); + + Ok(()) + } +} + +impl ForkTree where + H: PartialEq, + N: Ord, +{ + /// Create a new empty tree. + pub fn new() -> ForkTree { + ForkTree { + roots: Vec::new(), + best_finalized_number: None, + } + } + + /// Rebalance the tree, i.e. sort child nodes by max branch depth + /// (decreasing). + /// + /// Most operations in the tree are performed with depth-first search + /// starting from the leftmost node at every level, since this tree is meant + /// to be used in a blockchain context, a good heuristic is that the node + /// we'll be looking + /// for at any point will likely be in one of the deepest chains (i.e. the + /// longest ones). + pub fn rebalance(&mut self) { + self.roots.sort_by_key(|n| Reverse(n.max_depth())); + for root in &mut self.roots { + root.rebalance(); + } + } + + /// Import a new node into the tree. The given function `is_descendent_of` + /// should return `true` if the second hash (target) is a descendent of the + /// first hash (base). This method assumes that nodes in the same branch are + /// imported in order. + /// + /// Returns `true` if the imported node is a root. + 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(), + }); + + self.rebalance(); + + 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)) + } + + /// Find a node in the tree that is the deepest ancestor of the given + /// block hash and which passes the given predicate. The given function + /// `is_descendent_of` should return `true` if the second hash (target) + /// is a descendent of the first hash (base). + pub fn find_node_where( + &self, + hash: &H, + number: &N, + is_descendent_of: &F, + predicate: &P, + ) -> Result>, Error> + where E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + // search for node starting from all roots + for root in self.roots.iter() { + let node = root.find_node_where(hash, number, is_descendent_of, predicate)?; + + // found the node, early exit + if let FindOutcome::Found(node) = node { + return Ok(Some(node)); + } + } + + Ok(None) + } + + /// Finalize a root in the tree and return it, return `None` in case no root + /// with the given hash exists. All other roots are pruned, and the children + /// of the finalized node become the new roots. + pub fn finalize_root(&mut self, hash: &H) -> Option { + self.roots.iter().position(|node| node.hash == *hash) + .map(|position| self.finalize_root_at(position)) + } + + /// Finalize root at given positiion. See `finalize_root` comment for details. + fn finalize_root_at(&mut self, position: usize) -> V { + let node = self.roots.swap_remove(position); + self.roots = node.children; + self.best_finalized_number = Some(node.number); + return node.data; + } + + /// Finalize a node in the tree. This method will make sure that the node + /// being finalized is either an existing root (and return its data), or a + /// node from a competing branch (not in the tree), tree pruning is done + /// accordingly. The given function `is_descendent_of` should return `true` + /// if the second hash (target) is a descendent of the first hash (base). + pub fn finalize( + &mut self, + hash: &H, + number: N, + is_descendent_of: &F, + ) -> Result, Error> + where E: std::error::Error, + F: Fn(&H, &H) -> Result + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert); + } + } + + // check if one of the current roots is being finalized + if let Some(root) = self.finalize_root(hash) { + return Ok(FinalizationResult::Changed(Some(root))); + } + + // make sure we're not finalizing a descendent of any root + for root in self.roots.iter() { + if number > root.number && is_descendent_of(&root.hash, hash)? { + return Err(Error::UnfinalizedAncestor); + } + } + + // we finalized a block earlier than any existing root (or possibly + // another fork not part of the tree). make sure to only keep roots that + // are part of the finalized branch + let mut changed = false; + 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) + } + } + + /// Finalize a node in the tree and all its ancestors. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is + // a descendent of the first hash (base). + pub fn finalize_with_ancestors( + &mut self, + hash: &H, + number: N, + is_descendent_of: &F, + ) -> Result, Error> + where E: std::error::Error, + F: Fn(&H, &H) -> Result + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert); + } + } + + // check if one of the current roots is being finalized + if let Some(root) = self.finalize_root(hash) { + return Ok(FinalizationResult::Changed(Some(root))); + } + + // we need to: + // 1) remove all roots that are not ancestors AND not descendants of finalized block; + // 2) if node is descendant - just leave it; + // 3) if node is ancestor - 'open it' + let mut changed = false; + let mut idx = 0; + while idx != self.roots.len() { + let (is_finalized, is_descendant, is_ancestor) = { + let root = &self.roots[idx]; + let is_finalized = root.hash == *hash; + let is_descendant = !is_finalized + && root.number > number && is_descendent_of(hash, &root.hash).unwrap_or(false); + let is_ancestor = !is_finalized && !is_descendant + && root.number < number && is_descendent_of(&root.hash, hash).unwrap_or(false); + (is_finalized, is_descendant, is_ancestor) + }; + + // if we have met finalized root - open it and return + if is_finalized { + return Ok(FinalizationResult::Changed(Some(self.finalize_root_at(idx)))); + } + + // if node is descendant of finalized block - just leave it as is + if is_descendant { + idx += 1; + continue; + } + + // if node is ancestor of finalized block - remove it and continue with children + if is_ancestor { + let root = self.roots.swap_remove(idx); + self.roots.extend(root.children); + changed = true; + continue; + } + + // if node is neither ancestor, nor descendant of the finalized block - remove it + self.roots.swap_remove(idx); + changed = true; + } + + self.best_finalized_number = Some(number); + + if changed { + Ok(FinalizationResult::Changed(None)) + } else { + Ok(FinalizationResult::Unchanged) + } + } + + /// Checks if any node in the tree is finalized by either finalizing the + /// node itself or a child node that's not in the tree, guaranteeing that + /// the node being finalized isn't a descendent of any of the node's + /// children. Returns `Some(true)` if the node being finalized is a root, + /// `Some(false)` if the node being finalized is not a root, and `None` if + /// no node in the tree is finalized. The given `predicate` is checked on + /// the prospective finalized root and must pass for finalization to occur. + /// The given function `is_descendent_of` should return `true` if the second + /// hash (target) is a descendent of the first hash (base). + pub fn finalizes_any_with_descendent_if( + &self, + hash: &H, + number: N, + is_descendent_of: &F, + predicate: P, + ) -> Result, Error> + where E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert); + } + } + + // check if the given hash is equal or a descendent of any node in the + // tree, if we find a valid node that passes the predicate then we must + // ensure that we're not finalizing past any of its child nodes. + for node in self.node_iter() { + if predicate(&node.data) { + if node.hash == *hash || is_descendent_of(&node.hash, hash)? { + for node in node.children.iter() { + if node.number <= number && is_descendent_of(&node.hash, &hash)? { + return Err(Error::UnfinalizedAncestor); + } + } + + return Ok(Some(self.roots.iter().any(|root| root.hash == node.hash))); + } + } + } + + Ok(None) + } + + /// Finalize a root in the tree by either finalizing the node itself or a + /// 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 predicate(&root.data) { + if root.hash == *hash || is_descendent_of(&root.hash, hash)? { + 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::*; + + /// The outcome of a search within a node. + pub enum FindOutcome { + // this is the node we were looking for. + Found(T), + // not the node we're looking for. contains a flag indicating + // whether the node was a descendent. true implies the predicate failed. + Failure(bool), + // Abort search. + Abort, + } + + #[derive(Clone, Debug, Decode, Encode, PartialEq)] + pub struct Node { + pub hash: H, + pub number: N, + pub data: V, + pub children: Vec>, + } + + impl Node { + /// Rebalance the tree, i.e. sort child nodes by max branch depth (decreasing). + pub fn rebalance(&mut self) { + self.children.sort_by_key(|n| Reverse(n.max_depth())); + for child in &mut self.children { + child.rebalance(); + } + } + + /// Finds the max depth among all branches descendent from this node. + pub fn max_depth(&self) -> usize { + let mut max = 0; + + for node in &self.children { + max = node.max_depth().max(max) + } + + max + 1 + } + + 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))) + } + } + + /// Find a node in the tree that is the deepest ancestor of the given + /// block hash which also passes the given predicate, backtracking + /// when the predicate fails. + /// The given function `is_descendent_of` should return `true` if the second hash (target) + /// is a descendent of the first hash (base). + // FIXME: it would be useful if this returned a mutable reference but + // rustc can't deal with lifetimes properly. an option would be to try + // an iterative definition instead. + pub fn find_node_where( + &self, + hash: &H, + number: &N, + is_descendent_of: &F, + predicate: &P, + ) -> Result>, Error> + where E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + // stop searching this branch + if *number < self.number { + return Ok(FindOutcome::Failure(false)); + } + + let mut known_descendent_of = false; + + // continue depth-first search through all children + for node in self.children.iter() { + // found node, early exit + match node.find_node_where(hash, number, is_descendent_of, predicate)? { + FindOutcome::Abort => return Ok(FindOutcome::Abort), + FindOutcome::Found(x) => return Ok(FindOutcome::Found(x)), + FindOutcome::Failure(true) => { + // if the block was a descendent of this child, + // then it cannot be a descendent of any others, + // so we don't search them. + known_descendent_of = true; + break; + }, + FindOutcome::Failure(false) => {}, + } + } + + // node not found in any of the descendents, if the node we're + // searching for is a descendent of this node then we will stop the + // search here, since there aren't any more children and we found + // the correct node so we don't want to backtrack. + let is_descendent_of = known_descendent_of || is_descendent_of(&self.hash, hash)?; + if is_descendent_of { + // if the predicate passes we return the node + if predicate(&self.data) { + return Ok(FindOutcome::Found(self)); + } + } + + // otherwise, tell our ancestor that we failed, and whether + // the block was a descendent. + Ok(FindOutcome::Failure(is_descendent_of)) + } + } +} + +// Workaround for: https://github.com/rust-lang/rust/issues/34537 +use node_implementation::{Node, FindOutcome}; + +struct ForkTreeIterator<'a, H, N, V> { + stack: Vec<&'a Node>, +} + +impl<'a, H, N, V> Iterator for ForkTreeIterator<'a, H, N, V> { + type Item = &'a Node; + + fn next(&mut self) -> Option { + self.stack.pop().map(|node| { + // child nodes are stored ordered by max branch height (decreasing), + // we want to keep this ordering while iterating but since we're + // using a stack for iterator state we need to reverse it. + self.stack.extend(node.children.iter().rev()); + node + }) + } +} + +#[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 + // \ + // - L - M - N + // \ + // - O + // \ + // — J - K + // + // (where N is not a part of fork tree) + let is_descendent_of = |base: &&str, block: &&str| -> Result { + let letters = vec!["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]; + match (*base, *block) { + ("A", b) => Ok(letters.into_iter().any(|n| n == b)), + ("B", b) => Ok(b == "C" || b == "D" || b == "E"), + ("C", b) => Ok(b == "D" || b == "E"), + ("D", b) => Ok(b == "E"), + ("E", _) => Ok(false), + ("F", b) => Ok(b == "G" || b == "H" || b == "I" || b == "L" || b == "M" || b == "N" || b == "O"), + ("G", _) => Ok(false), + ("H", b) => Ok(b == "I" || b == "L" || b == "M" || b == "O"), + ("I", _) => Ok(false), + ("J", b) => Ok(b == "K"), + ("K", _) => Ok(false), + ("L", b) => Ok(b == "M" || b == "O" || b == "N"), + ("M", b) => Ok(b == "N"), + ("N", _) => Ok(false), + ("O", _) => Ok(false), + ("0", _) => Ok(true), + _ => Ok(false), + } + }; + + tree.import("A", 1, (), &is_descendent_of).unwrap(); + + tree.import("B", 2, (), &is_descendent_of).unwrap(); + tree.import("C", 3, (), &is_descendent_of).unwrap(); + tree.import("D", 4, (), &is_descendent_of).unwrap(); + tree.import("E", 5, (), &is_descendent_of).unwrap(); + + tree.import("F", 2, (), &is_descendent_of).unwrap(); + tree.import("G", 3, (), &is_descendent_of).unwrap(); + + tree.import("H", 3, (), &is_descendent_of).unwrap(); + tree.import("I", 4, (), &is_descendent_of).unwrap(); + tree.import("L", 4, (), &is_descendent_of).unwrap(); + tree.import("M", 5, (), &is_descendent_of).unwrap(); + tree.import("O", 5, (), &is_descendent_of).unwrap(); + + tree.import("J", 2, (), &is_descendent_of).unwrap(); + tree.import("K", 3, (), &is_descendent_of).unwrap(); + + (tree, is_descendent_of) + } + + #[test] + fn import_doesnt_revert() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + tree.finalize_root(&"A"); + + assert_eq!( + tree.best_finalized_number, + Some(1), + ); + + assert_eq!( + tree.import("A", 1, (), &is_descendent_of), + Err(Error::Revert), + ); + } + + #[test] + fn import_doesnt_add_duplicates() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + assert_eq!( + tree.import("A", 1, (), &is_descendent_of), + Err(Error::Duplicate), + ); + + assert_eq!( + tree.import("I", 4, (), &is_descendent_of), + Err(Error::Duplicate), + ); + + assert_eq!( + tree.import("G", 3, (), &is_descendent_of), + Err(Error::Duplicate), + ); + + assert_eq!( + tree.import("K", 3, (), &is_descendent_of), + Err(Error::Duplicate), + ); + } + + #[test] + fn finalize_root_works() { + let finalize_a = || { + let (mut tree, ..) = test_fork_tree(); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.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), ("L", 4)], + ); + + // finalizing a node from another fork that isn't part of the tree clears the tree + assert_eq!( + tree.finalize(&"Z", 5, &is_descendent_of), + Ok(FinalizationResult::Changed(None)), + ); + + assert!(tree.roots.is_empty()); + } + + #[test] + fn finalize_with_ancestor_works() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + let original_roots = tree.roots.clone(); + + // finalizing a block prior to any in the node doesn't change the tree + assert_eq!( + tree.finalize_with_ancestors(&"0", 0, &is_descendent_of), + Ok(FinalizationResult::Unchanged), + ); + + assert_eq!(tree.roots, original_roots); + + // finalizing "A" opens up three possible forks + assert_eq!( + tree.finalize_with_ancestors(&"A", 1, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), + vec![("B", 2), ("F", 2), ("J", 2)], + ); + + // finalizing H: + // 1) removes roots that are not ancestors/descendants of H (B, J) + // 2) opens root that is ancestor of H (F -> G+H) + // 3) finalizes the just opened root H (H -> I + L) + assert_eq!( + tree.finalize_with_ancestors(&"H", 3, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), + vec![("I", 4), ("L", 4)], + ); + + assert_eq!( + tree.best_finalized_number, + Some(3), + ); + + // finalizing N (which is not a part of the tree): + // 1) removes roots that are not ancestors/descendants of N (I) + // 2) opens root that is ancestor of N (L -> M+O) + // 3) removes roots that are not ancestors/descendants of N (O) + // 4) opens root that is ancestor of N (M -> {}) + assert_eq!( + tree.finalize_with_ancestors(&"N", 6, &is_descendent_of), + Ok(FinalizationResult::Changed(None)), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), + vec![], + ); + + assert_eq!( + tree.best_finalized_number, + Some(6), + ); + } + + #[test] + fn finalize_with_descendent_works() { + #[derive(Debug, PartialEq)] + 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(None), + ); + + // finalizing "D" will finalize a block from the tree, but it can't be applied yet + // since it is not a root change + assert_eq!( + tree.finalizes_any_with_descendent_if( + &"D", + 10, + &is_descendent_of, + |c| c.effective == 10, + ), + Ok(Some(false)), + ); + + // finalizing "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(Some(true)), + ); + + assert_eq!( + tree.finalize_with_descendent_if( + &"C", + 5, + &is_descendent_of, + |c| c.effective <= 5, + ), + Ok(FinalizationResult::Changed(Some(Change { effective: 5 }))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.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(Some(true)), + ); + + assert_eq!( + tree.finalize_with_descendent_if( + &"G", + 100, + &is_descendent_of, + |c| c.effective <= 100, + ), + Ok(FinalizationResult::Changed(Some(Change { effective: 10 }))), + ); + + // "E" will be pruned out + assert_eq!(tree.roots().count(), 0); + } + + #[test] + fn iter_iterates_in_preorder() { + let (tree, ..) = test_fork_tree(); + assert_eq!( + tree.iter().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), + vec![ + ("A", 1), + ("B", 2), ("C", 3), ("D", 4), ("E", 5), + ("F", 2), + ("G", 3), + ("H", 3), ("I", 4), + ("L", 4), ("M", 5), ("O", 5), + ("J", 2), ("K", 3) + ], + ); + } + + #[test] + fn minimizes_calls_to_is_descendent_of() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + let n_is_descendent_of_calls = AtomicUsize::new(0); + + let is_descendent_of = |_: &&str, _: &&str| -> Result { + n_is_descendent_of_calls.fetch_add(1, Ordering::SeqCst); + Ok(true) + }; + + { + // Deep tree where we want to call `finalizes_any_with_descendent_if`. The + // search for the node should first check the predicate (which is cheaper) and + // only then call `is_descendent_of` + let mut tree = ForkTree::new(); + let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; + + for (i, letter) in letters.iter().enumerate() { + tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(true)).unwrap(); + } + + // "L" is a descendent of "K", but the predicate will only pass for "K", + // therefore only one call to `is_descendent_of` should be made + assert_eq!( + tree.finalizes_any_with_descendent_if( + &"L", + 11, + &is_descendent_of, + |i| *i == 10, + ), + Ok(Some(false)), + ); + + assert_eq!( + n_is_descendent_of_calls.load(Ordering::SeqCst), + 1, + ); + } + + n_is_descendent_of_calls.store(0, Ordering::SeqCst); + + { + // Multiple roots in the tree where we want to call `finalize_with_descendent_if`. + // The search for the root node should first check the predicate (which is cheaper) + // and only then call `is_descendent_of` + let mut tree = ForkTree::new(); + let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; + + for (i, letter) in letters.iter().enumerate() { + tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(false)).unwrap(); + } + + // "L" is a descendent of "K", but the predicate will only pass for "K", + // therefore only one call to `is_descendent_of` should be made + assert_eq!( + tree.finalize_with_descendent_if( + &"L", + 11, + &is_descendent_of, + |i| *i == 10, + ), + Ok(FinalizationResult::Changed(Some(10))), + ); + + assert_eq!( + n_is_descendent_of_calls.load(Ordering::SeqCst), + 1, + ); + } + } + + #[test] + fn find_node_works() { + let (tree, is_descendent_of) = test_fork_tree(); + + let node = tree.find_node_where( + &"D", + &4, + &is_descendent_of, + &|_| true, + ).unwrap().unwrap(); + + assert_eq!(node.hash, "C"); + assert_eq!(node.number, 3); + } + + #[test] + fn prune_works() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + tree.prune( + &"C", + &3, + &is_descendent_of, + &|_| true, + ).unwrap(); + + assert_eq!( + tree.roots.iter().map(|node| node.hash).collect::>(), + vec!["B"], + ); + + assert_eq!( + tree.iter().map(|(hash, _, _)| *hash).collect::>(), + vec!["B", "C", "D", "E"], + ); + + tree.prune( + &"E", + &5, + &is_descendent_of, + &|_| true, + ).unwrap(); + + assert_eq!( + tree.roots.iter().map(|node| node.hash).collect::>(), + vec!["D"], + ); + + assert_eq!( + tree.iter().map(|(hash, _, _)| *hash).collect::>(), + vec!["D", "E"], + ); + } + + #[test] + fn find_node_backtracks_after_finding_highest_descending_node() { + let mut tree = ForkTree::new(); + + // + // A - B + // \ + // — C + // + let is_descendent_of = |base: &&str, block: &&str| -> Result { + match (*base, *block) { + ("A", b) => Ok(b == "B" || b == "C" || b == "D"), + ("B", b) | ("C", b) => Ok(b == "D"), + ("0", _) => Ok(true), + _ => Ok(false), + } + }; + + tree.import("A", 1, 1, &is_descendent_of).unwrap(); + tree.import("B", 2, 2, &is_descendent_of).unwrap(); + tree.import("C", 2, 4, &is_descendent_of).unwrap(); + + // when searching the tree we reach node `C`, but the + // predicate doesn't pass. we should backtrack to `B`, but not to `A`, + // since "B" fulfills the predicate. + let node = tree.find_node_where( + &"D", + &3, + &is_descendent_of, + &|data| *data < 3, + ).unwrap(); + + assert_eq!(node.unwrap().hash, "B"); + } + + #[test] + fn tree_rebalance() { + let (mut tree, _) = test_fork_tree(); + + assert_eq!( + tree.iter().map(|(h, _, _)| *h).collect::>(), + vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "L", "M", "O", "J", "K"], + ); + + // after rebalancing the tree we should iterate in preorder exploring + // the longest forks first. check the ascii art above to understand the + // expected output below. + tree.rebalance(); + + assert_eq!( + tree.iter().map(|(h, _, _)| *h).collect::>(), + ["A", "B", "C", "D", "E", "F", "H", "L", "M", "O", "I", "G", "J", "K"] + ); + } +} diff --git a/utils/frame/rpc/support/Cargo.toml b/utils/frame/rpc/support/Cargo.toml new file mode 100644 index 0000000000000..f26a69cc5fa0c --- /dev/null +++ b/utils/frame/rpc/support/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "substrate-frame-rpc-support" +version = "2.0.0" +authors = ["Parity Technologies ", "Andrew Dirksen "] +edition = "2018" + +[dependencies] +futures = { version = "0.3.0", features = ["compat"] } +jsonrpc-client-transports = "14" +jsonrpc-core = "14" +codec = { package = "parity-scale-codec", version = "1" } +serde = "1" +frame-support = { version = "2.0.0", path = "../../../../frame/support" } +sp-storage = { version = "2.0.0", path = "../../../../primitives/storage" } +sc-rpc-api = { version = "2.0.0", path = "../../../../client/rpc-api" } + +[dev-dependencies] +frame-system = { version = "2.0.0", path = "../../../../frame/system" } +tokio = "0.1" diff --git a/utils/frame/rpc/support/src/lib.rs b/utils/frame/rpc/support/src/lib.rs new file mode 100644 index 0000000000000..1e29c4e91b495 --- /dev/null +++ b/utils/frame/rpc/support/src/lib.rs @@ -0,0 +1,155 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Combines [sc_rpc_api::state::StateClient] with [frame_support::storage::generator] traits +//! to provide strongly typed chain state queries over rpc. + +#![warn(missing_docs)] + +use core::marker::PhantomData; +use futures::compat::Future01CompatExt; +use jsonrpc_client_transports::RpcError; +use codec::{DecodeAll, FullCodec, FullEncode}; +use serde::{de::DeserializeOwned, Serialize}; +use frame_support::storage::generator::{ + StorageDoubleMap, StorageLinkedMap, StorageMap, StorageValue +}; +use sp_storage::{StorageData, StorageKey}; +use sc_rpc_api::state::StateClient; + +/// A typed query on chain state usable from an RPC client. +/// +/// ```no_run +/// # use futures::compat::Compat; +/// # use futures::compat::Future01CompatExt; +/// # use futures::future::FutureExt; +/// # use jsonrpc_client_transports::RpcError; +/// # use jsonrpc_client_transports::transports::http; +/// # use codec::Encode; +/// # use frame_support::{decl_storage, decl_module}; +/// # use substrate_frame_rpc_support::StorageQuery; +/// # use frame_system::Trait; +/// # use sc_rpc_api::state::StateClient; +/// # +/// # // Hash would normally be ::Hash, but we don't have +/// # // frame_system::Trait implemented for TestRuntime. Here we just pretend. +/// # type Hash = (); +/// # +/// # fn main() -> Result<(), RpcError> { +/// # tokio::runtime::Runtime::new().unwrap().block_on(Compat::new(test().boxed())) +/// # } +/// # +/// # struct TestRuntime; +/// # +/// # decl_module! { +/// # pub struct Module for enum Call where origin: T::Origin {} +/// # } +/// # +/// pub type Loc = (i64, i64, i64); +/// pub type Block = u8; +/// +/// // Note that all fields are marked pub. +/// decl_storage! { +/// trait Store for Module as TestRuntime { +/// pub LastActionId: u64; +/// pub Voxels: map Loc => Block; +/// pub Actions: linked_map u64 => Loc; +/// pub Prefab: double_map u128, (i8, i8, i8) => Block; +/// } +/// } +/// +/// # async fn test() -> Result<(), RpcError> { +/// let conn = http::connect("http://[::1]:9933").compat().await?; +/// let cl = StateClient::::new(conn); +/// +/// let q = StorageQuery::value::(); +/// let _: Option = q.get(&cl, None).await?; +/// +/// let q = StorageQuery::map::((0, 0, 0)); +/// let _: Option = q.get(&cl, None).await?; +/// +/// let q = StorageQuery::linked_map::(12); +/// let _: Option = q.get(&cl, None).await?; +/// +/// let q = StorageQuery::double_map::(3, (0, 0, 0)); +/// let _: Option = q.get(&cl, None).await?; +/// # +/// # Ok(()) +/// # } +/// ``` +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +pub struct StorageQuery { + key: StorageKey, + _spook: PhantomData, +} + +impl StorageQuery { + /// Create a storage query for a StorageValue. + pub fn value>() -> Self { + Self { + key: StorageKey(St::storage_value_final_key().to_vec()), + _spook: PhantomData, + } + } + + /// Create a storage query for a value in a StorageMap. + pub fn map, K: FullEncode>(key: K) -> Self { + Self { + key: StorageKey(St::storage_map_final_key(key)), + _spook: PhantomData, + } + } + + /// Create a storage query for a value in a StorageLinkedMap. + pub fn linked_map, K: FullCodec>(key: K) -> Self { + Self { + key: StorageKey(St::storage_linked_map_final_key(key)), + _spook: PhantomData, + } + } + + /// Create a storage query for a value in a StorageDoubleMap. + pub fn double_map, K1: FullEncode, K2: FullEncode>( + key1: K1, + key2: K2, + ) -> Self { + Self { + key: StorageKey(St::storage_double_map_final_key(key1, key2)), + _spook: PhantomData, + } + } + + /// Send this query over RPC, await the typed result. + /// + /// Hash should be ::Hash. + /// + /// # Arguments + /// + /// state_client represents a connection to the RPC server. + /// + /// block_index indicates the block for which state will be queried. A value of None indicates + /// the latest block. + pub async fn get( + self, + state_client: &StateClient, + block_index: Option, + ) -> Result, RpcError> { + let opt: Option = state_client.storage(self.key, block_index).compat().await?; + opt.map(|encoded| V::decode_all(&encoded.0)) + .transpose() + .map_err(|decode_err| RpcError::Other(decode_err.into())) + } +} diff --git a/utils/frame/rpc/system/Cargo.toml b/utils/frame/rpc/system/Cargo.toml new file mode 100644 index 0000000000000..1a479c54e57d5 --- /dev/null +++ b/utils/frame/rpc/system/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "substrate-frame-rpc-system" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sc-client = { version = "2.0.0", path = "../../../../client/" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +futures = "0.3.1" +jsonrpc-core = "14.0.3" +jsonrpc-core-client = "14.0.3" +jsonrpc-derive = "14.0.3" +log = "0.4.8" +serde = { version = "1.0.101", features = ["derive"] } +sp-runtime = { version = "2.0.0", path = "../../../../primitives/runtime" } +sp-api = { version = "2.0.0", path = "../../../../primitives/api" } +frame-system-rpc-runtime-api = { version = "2.0.0", path = "../../../../frame/system/rpc/runtime-api" } +sp-core = { version = "2.0.0", path = "../../../../primitives/core" } +sp-blockchain = { version = "2.0.0", path = "../../../../primitives/blockchain" } +sp-transaction-pool = { version = "2.0.0", path = "../../../../primitives/transaction-pool" } + +[dev-dependencies] +substrate-test-runtime-client = { version = "2.0.0", path = "../../../../test-utils/runtime/client" } +env_logger = "0.7.0" +sc-transaction-pool = { version = "2.0.0", path = "../../../../client/transaction-pool" } diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs new file mode 100644 index 0000000000000..f909e66fd6e2e --- /dev/null +++ b/utils/frame/rpc/system/src/lib.rs @@ -0,0 +1,263 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! System SRML specific RPC methods. + +use std::sync::Arc; + +use codec::{self, Codec, Decode, Encode}; +use sc_client::{ + light::blockchain::{future_header, RemoteBlockchain}, + light::fetcher::{Fetcher, RemoteCallRequest}, +}; +use jsonrpc_core::{ + Error, ErrorCode, + futures::future::{result, Future}, +}; +use jsonrpc_derive::rpc; +use futures::future::{ready, TryFutureExt}; +use sp_blockchain::{ + HeaderBackend, + Error as ClientError +}; +use sp_runtime::{ + generic::BlockId, + traits, +}; +use sp_core::hexdisplay::HexDisplay; +use sp_transaction_pool::{TransactionPool, InPoolTransaction}; + +pub use frame_system_rpc_runtime_api::AccountNonceApi; +pub use self::gen_client::Client as SystemClient; + +/// Future that resolves to account nonce. +pub type FutureResult = Box + Send>; + +/// System RPC methods. +#[rpc] +pub trait SystemApi { + /// Returns the next valid index (aka nonce) for given account. + /// + /// This method takes into consideration all pending transactions + /// currently in the pool and if no transactions are found in the pool + /// it fallbacks to query the index from the runtime (aka. state nonce). + #[rpc(name = "system_accountNextIndex", alias("account_nextIndex"))] + fn nonce(&self, account: AccountId) -> FutureResult; +} + +const RUNTIME_ERROR: i64 = 1; + +/// An implementation of System-specific RPC methods on full client. +pub struct FullSystem { + client: Arc, + pool: Arc

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

) -> Self { + FullSystem { + client, + pool, + _marker: Default::default(), + } + } +} + +impl SystemApi for FullSystem +where + C: sp_api::ProvideRuntimeApi, + C: HeaderBackend, + C: Send + Sync + 'static, + C::Api: AccountNonceApi, + P: TransactionPool + 'static, + Block: traits::Block, + AccountId: Clone + std::fmt::Display + Codec, + Index: Clone + std::fmt::Display + Codec + Send + traits::SimpleArithmetic + 'static, +{ + fn nonce(&self, account: AccountId) -> FutureResult { + let get_nonce = || { + let api = self.client.runtime_api(); + let best = self.client.info().best_hash; + let at = BlockId::hash(best); + + let nonce = api.account_nonce(&at, account.clone()).map_err(|e| Error { + code: ErrorCode::ServerError(RUNTIME_ERROR), + message: "Unable to query nonce.".into(), + data: Some(format!("{:?}", e).into()), + })?; + + Ok(adjust_nonce(&*self.pool, account, nonce)) + }; + + Box::new(result(get_nonce())) + } +} + +/// An implementation of System-specific RPC methods on light client. +pub struct LightSystem { + client: Arc, + remote_blockchain: Arc>, + fetcher: Arc, + pool: Arc

, +} + +impl LightSystem { + /// Create new `LightSystem`. + pub fn new( + client: Arc, + remote_blockchain: Arc>, + fetcher: Arc, + pool: Arc

, + ) -> Self { + LightSystem { + client, + remote_blockchain, + fetcher, + pool, + } + } +} + +impl SystemApi for LightSystem +where + P: TransactionPool + 'static, + C: HeaderBackend, + C: Send + Sync + 'static, + F: Fetcher + 'static, + Block: traits::Block, + AccountId: Clone + std::fmt::Display + Codec + Send + 'static, + Index: Clone + std::fmt::Display + Codec + Send + traits::SimpleArithmetic + 'static, +{ + fn nonce(&self, account: AccountId) -> FutureResult { + let best_hash = self.client.info().best_hash; + let best_id = BlockId::hash(best_hash); + let future_best_header = future_header(&*self.remote_blockchain, &*self.fetcher, best_id); + let fetcher = self.fetcher.clone(); + let call_data = account.encode(); + let future_best_header = future_best_header + .and_then(move |maybe_best_header| ready( + match maybe_best_header { + Some(best_header) => Ok(best_header), + None => Err(ClientError::UnknownBlock(format!("{}", best_hash))), + } + )); + let future_nonce = future_best_header.and_then(move |best_header| + fetcher.remote_call(RemoteCallRequest { + block: best_hash, + header: best_header, + method: "AccountNonceApi_account_nonce".into(), + call_data, + retry_count: None, + }) + ).compat(); + let future_nonce = future_nonce.and_then(|nonce| Decode::decode(&mut &nonce[..]) + .map_err(|e| ClientError::CallResultDecode("Cannot decode account nonce", e))); + let future_nonce = future_nonce.map_err(|e| Error { + code: ErrorCode::ServerError(RUNTIME_ERROR), + message: "Unable to query nonce.".into(), + data: Some(format!("{:?}", e).into()), + }); + + let pool = self.pool.clone(); + let future_nonce = future_nonce.map(move |nonce| adjust_nonce(&*pool, account, nonce)); + + Box::new(future_nonce) + } +} + +/// Adjust account nonce from state, so that tx with the nonce will be +/// placed after all ready txpool transactions. +fn adjust_nonce( + pool: &P, + account: AccountId, + nonce: Index, +) -> Index where + P: TransactionPool, + AccountId: Clone + std::fmt::Display + Encode, + Index: Clone + std::fmt::Display + Encode + traits::SimpleArithmetic + 'static, +{ + log::debug!(target: "rpc", "State nonce for {}: {}", account, nonce); + // Now we need to query the transaction pool + // and find transactions originating from the same sender. + // + // Since extrinsics are opaque to us, we look for them using + // `provides` tag. And increment the nonce if we find a transaction + // that matches the current one. + let mut current_nonce = nonce.clone(); + let mut current_tag = (account.clone(), nonce.clone()).encode(); + for tx in pool.ready() { + log::debug!( + target: "rpc", + "Current nonce to {}, checking {} vs {:?}", + current_nonce, + HexDisplay::from(¤t_tag), + tx.provides().iter().map(|x| format!("{}", HexDisplay::from(x))).collect::>(), + ); + // since transactions in `ready()` need to be ordered by nonce + // it's fine to continue with current iterator. + if tx.provides().get(0) == Some(¤t_tag) { + current_nonce += traits::One::one(); + current_tag = (account.clone(), current_nonce.clone()).encode(); + } + } + + current_nonce +} + +#[cfg(test)] +mod tests { + use super::*; + + use futures::executor::block_on; + use substrate_test_runtime_client::{ + runtime::Transfer, + AccountKeyring, + }; + use sc_transaction_pool::{BasicPool, FullChainApi}; + + #[test] + fn should_return_next_nonce_for_some_account() { + // given + let _ = env_logger::try_init(); + let client = Arc::new(substrate_test_runtime_client::new()); + let pool = Arc::new(BasicPool::new(Default::default(), FullChainApi::new(client.clone()))); + + let new_transaction = |nonce: u64| { + let t = Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), + amount: 5, + nonce, + }; + t.into_signed_tx() + }; + // Populate the pool + let ext0 = new_transaction(0); + block_on(pool.submit_one(&BlockId::number(0), ext0)).unwrap(); + let ext1 = new_transaction(1); + block_on(pool.submit_one(&BlockId::number(0), ext1)).unwrap(); + + let accounts = FullSystem::new(client, pool); + + // when + let nonce = accounts.nonce(AccountKeyring::Alice.into()); + + // then + assert_eq!(nonce.wait().unwrap(), 2); + } +} diff --git a/utils/grafana-data-source/Cargo.toml b/utils/grafana-data-source/Cargo.toml new file mode 100644 index 0000000000000..76bf7d5988d9a --- /dev/null +++ b/utils/grafana-data-source/Cargo.toml @@ -0,0 +1,23 @@ +[package] +description = "Grafana data source server" +name = "grafana-data-source" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +log = "0.4.8" +hyper = { version = "0.13.1", default-features = false, features = ["stream"] } +tokio = "0.2" +futures-util = { version = "0.3.1", default-features = false, features = ["io"] } +serde_json = "1" +serde = { version = "1", features = ["derive"] } +chrono = { version = "0.4", features = ["serde"] } +lazy_static = "1.4" +parking_lot = "0.9" +futures-timer = "2.0" +derive_more = "0.99" + +[target.'cfg(not(target_os = "unknown"))'.dependencies] +async-std = { version = "1.0.1", features = ["unstable"] } diff --git a/utils/grafana-data-source/src/database.rs b/utils/grafana-data-source/src/database.rs new file mode 100644 index 0000000000000..f20917cf785d4 --- /dev/null +++ b/utils/grafana-data-source/src/database.rs @@ -0,0 +1,154 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::collections::HashMap; +use std::convert::TryFrom; +use crate::Error; + +pub struct Database { + base_timestamp: i64, + storage: HashMap> +} + +impl Database { + /// Create a new Database. + pub fn new() -> Self { + Self { + base_timestamp: now_millis(), + storage: HashMap::new() + } + } + + /// Produce an iterator for keys starting with a base string. + pub fn keys_starting_with<'a>(&'a self, base: &'a str) -> impl Iterator + 'a { + self.storage.keys() + .filter(move |key| key.starts_with(base)) + .cloned() + } + + /// Select `max_datapoints` datapoints that have been added between `from` and `to`. + pub fn datapoints_between(&self, key: &str, from: i64, to: i64, max_datapoints: usize) -> Option> { + self.storage.get(key) + .map(|vec| { + let from = find_index(vec, self.base_timestamp, from); + let to = find_index(vec, self.base_timestamp, to); + let slice = &vec[from .. to]; + + if max_datapoints == 0 { + Vec::new() + } else if max_datapoints >= slice.len() { + // Just convert the slice as-is + slice.iter() + .map(|dp| dp.make_absolute(self.base_timestamp)) + .collect() + } else { + // We have more datapoints than we need, so we need to skip some + (0 .. max_datapoints - 1) + .map(|i| &slice[i * slice.len() / (max_datapoints - 1)]) + .chain(slice.last()) + .map(|dp| dp.make_absolute(self.base_timestamp)) + .collect() + } + }) + } + + /// Push a new datapoint. Will error if the base timestamp hasn't been updated in `2^32` + /// milliseconds (49 days). + pub fn push(&mut self, key: &str, value: f32) -> Result<(), Error> { + self.storage.entry(key.into()) + .or_insert_with(Vec::new) + .push(Datapoint::new(self.base_timestamp, value)?); + + Ok(()) + } + + /// Set a new base timestamp, and remove metrics older than this new timestamp. Errors if the + /// difference between timestamps is greater than `2^32` milliseconds (49 days). + pub fn truncate(&mut self, new_base_timestamp: i64) -> Result<(), Error> { + // Ensure that the new base is older. + if self.base_timestamp >= new_base_timestamp { + return Ok(()); + } + + // If the old base timestamp was too long ago, the + let delta = u32::try_from(new_base_timestamp - self.base_timestamp) + .map_err(Error::Timestamp)?; + + for metric in self.storage.values_mut() { + // Find the index of the oldest allowed timestamp and cut out all those before it. + let index = find_index(&metric, self.base_timestamp, new_base_timestamp); + + *metric = metric.iter_mut() + .skip(index) + .map(|dp| { + dp.delta_timestamp -= delta; + *dp + }) + .collect(); + } + + self.base_timestamp = new_base_timestamp; + + Ok(()) + } +} + +#[derive(Clone, Copy)] +struct Datapoint { + delta_timestamp: u32, + value: f32 +} + +impl Datapoint { + fn new(base_timestamp: i64, value: f32) -> Result { + Ok(Self { + delta_timestamp: u32::try_from(now_millis() - base_timestamp) + .map_err(Error::Timestamp)?, + value + }) + } + + fn make_absolute(self, base_timestamp: i64) -> (f32, i64) { + (self.value, base_timestamp + self.delta_timestamp as i64) + } +} + +fn find_index(slice: &[Datapoint], base_timestamp: i64, timestamp: i64) -> usize { + slice.binary_search_by_key(×tamp, |datapoint| { + base_timestamp + datapoint.delta_timestamp as i64 + }).unwrap_or_else(|index| index) +} + +/// Get the current unix timestamp in milliseconds. +fn now_millis() -> i64 { + chrono::Utc::now().timestamp_millis() +} + +#[test] +fn test() { + let mut database = Database::new(); + + database.push("test", 1.0).unwrap(); + database.push("test", 2.5).unwrap(); + database.push("test", 2.0).unwrap(); + database.push("test 2", 1.0).unwrap(); + + let mut keys: Vec<_> = database.keys_starting_with("test").collect(); + keys.sort(); + + assert_eq!(keys, ["test", "test 2"]); + assert_eq!(database.keys_starting_with("test ").collect::>(), ["test 2"]); +} diff --git a/utils/grafana-data-source/src/lib.rs b/utils/grafana-data-source/src/lib.rs new file mode 100644 index 0000000000000..fbba064706e0a --- /dev/null +++ b/utils/grafana-data-source/src/lib.rs @@ -0,0 +1,96 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! [Grafana] data source server +//! +//! To display node statistics with [Grafana], this module exposes a `run_server` function that +//! starts up a HTTP server that conforms to the [`grafana-json-data-source`] API. The +//! `record_metrics` macro can be used to pass metrics to this server. +//! +//! [Grafana]: https://grafana.com/ +//! [`grafana-json-data-source`]: https://github.com/simPod/grafana-json-datasource + +#![warn(missing_docs)] + +use lazy_static::lazy_static; +use parking_lot::RwLock; + +mod types; +mod server; +#[cfg(not(target_os = "unknown"))] +mod networking; +mod database; + +use database::Database; +pub use server::run_server; +use std::num::TryFromIntError; + +lazy_static! { + // The `RwLock` wrapping the metrics database. + static ref DATABASE: RwLock = RwLock::new(Database::new()); +} + +/// Write metrics to `METRICS`. +#[macro_export] +macro_rules! record_metrics( + ($($key:expr => $value:expr,)*) => { + if cfg!(not(target_os = "unknown")) { + $crate::record_metrics_slice(&[ + $( ($key, $value as f32), )* + ]) + } else { + Ok(()) + } + } +); + +/// Write metrics to `METRICS` as a slice. Intended to be only used via `record_metrics!`. +pub fn record_metrics_slice(metrics: &[(&str, f32)]) -> Result<(), Error> { + let mut database = crate::DATABASE.write(); + + for &(key, value) in metrics.iter() { + database.push(key, value)?; + } + + Ok(()) +} + +/// Error type that can be returned by either `record_metrics` or `run_server`. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Hyper internal error. + Hyper(hyper::Error), + /// Serialization/deserialization error. + Serde(serde_json::Error), + /// Http request error. + Http(hyper::http::Error), + /// Timestamp error. + Timestamp(TryFromIntError), + /// i/o error. + Io(std::io::Error) +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Hyper(error) => Some(error), + Error::Serde(error) => Some(error), + Error::Http(error) => Some(error), + Error::Timestamp(error) => Some(error), + Error::Io(error) => Some(error) + } + } +} diff --git a/utils/grafana-data-source/src/networking.rs b/utils/grafana-data-source/src/networking.rs new file mode 100644 index 0000000000000..5c8c036d44597 --- /dev/null +++ b/utils/grafana-data-source/src/networking.rs @@ -0,0 +1,66 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use async_std::pin::Pin; +use std::task::{Poll, Context}; +use futures_util::{stream::Stream, io::{AsyncRead, AsyncWrite}}; + +pub struct Incoming<'a>(pub async_std::net::Incoming<'a>); + +impl hyper::server::accept::Accept for Incoming<'_> { + type Conn = TcpStream; + type Error = async_std::io::Error; + + fn poll_accept(self: Pin<&mut Self>, cx: &mut Context) -> Poll>> { + Pin::new(&mut Pin::into_inner(self).0) + .poll_next(cx) + .map(|opt| opt.map(|res| res.map(TcpStream))) + } +} + +pub struct TcpStream(pub async_std::net::TcpStream); + +impl tokio::io::AsyncRead for TcpStream { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context, + buf: &mut [u8] + ) -> Poll> { + Pin::new(&mut Pin::into_inner(self).0) + .poll_read(cx, buf) + } +} + +impl tokio::io::AsyncWrite for TcpStream { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context, + buf: &[u8] + ) -> Poll> { + Pin::new(&mut Pin::into_inner(self).0) + .poll_write(cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + Pin::new(&mut Pin::into_inner(self).0) + .poll_flush(cx) + } + + fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + Pin::new(&mut Pin::into_inner(self).0) + .poll_close(cx) + } +} diff --git a/utils/grafana-data-source/src/server.rs b/utils/grafana-data-source/src/server.rs new file mode 100644 index 0000000000000..8ef5e0378478c --- /dev/null +++ b/utils/grafana-data-source/src/server.rs @@ -0,0 +1,160 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use serde::{Serialize, de::DeserializeOwned}; +use hyper::{Body, Request, Response, header, service::{service_fn, make_service_fn}, Server}; +use chrono::{Duration, Utc}; +use futures_util::{FutureExt, TryStreamExt, future::{Future, select, Either}}; +use futures_timer::Delay; +use crate::{DATABASE, Error, types::{Target, Query, TimeseriesData, Range}}; + +async fn api_response(req: Request) -> Result, Error> { + match req.uri().path() { + "/search" => { + map_request_to_response(req, |target: Target| { + // Filter and return metrics relating to the target + DATABASE.read() + .keys_starting_with(&target.target) + .collect::>() + }).await + }, + "/query" => { + map_request_to_response(req, |query: Query| { + let metrics = DATABASE.read(); + + let Query { + range: Range { from, to }, + max_datapoints, .. + } = query; + + // Return timeseries data related to the specified metrics + query.targets.iter() + .map(|target| { + let datapoints = metrics.datapoints_between(&target.target, from, to, max_datapoints) + .unwrap_or_else(Vec::new); + + TimeseriesData { + target: target.target.clone(), datapoints + } + }) + .collect::>() + }).await + }, + _ => Ok(Response::new(Body::empty())), + } +} + +async fn map_request_to_response(req: Request, transformation: T) -> Result, Error> + where + Req: DeserializeOwned, + Res: Serialize, + T: Fn(Req) -> Res + Send + Sync + 'static +{ + let body = req.into_body() + .map_ok(|bytes| bytes.to_vec()) + .try_concat() + .await + .map_err(Error::Hyper)?; + + let req = serde_json::from_slice(body.as_ref()).map_err(Error::Serde)?; + let res = transformation(req); + let string = serde_json::to_string(&res).map_err(Error::Serde)?; + + Response::builder() + .header(header::CONTENT_TYPE, "application/json") + .body(Body::from(string)) + .map_err(Error::Http) +} + +/// Given that we're not using hyper's tokio feature, we need to define out own executor. +#[derive(Clone)] +pub struct Executor; + +#[cfg(not(target_os = "unknown"))] +impl hyper::rt::Executor for Executor + where + T: Future + Send + 'static, + T::Output: Send + 'static, +{ + fn execute(&self, future: T) { + async_std::task::spawn(future); + } +} + +/// Start the data source server. +#[cfg(not(target_os = "unknown"))] +pub async fn run_server(mut address: std::net::SocketAddr) -> Result<(), Error> { + use async_std::{net, io}; + use crate::networking::Incoming; + + let listener = loop { + let listener = net::TcpListener::bind(&address).await; + match listener { + Ok(listener) => { + log::info!("Grafana data source server started at {}", address); + break listener + }, + Err(err) => match err.kind() { + io::ErrorKind::AddrInUse | io::ErrorKind::PermissionDenied if address.port() != 0 => { + log::warn!( + "Unable to bind grafana data source server to {}. Trying random port.", + address + ); + address.set_port(0); + continue; + }, + _ => return Err(err.into()), + } + } + }; + + let service = make_service_fn(|_| { + async { + Ok::<_, Error>(service_fn(api_response)) + } + }); + + let server = Server::builder(Incoming(listener.incoming())) + .executor(Executor) + .serve(service) + .boxed(); + + let every = std::time::Duration::from_secs(24 * 3600); + let clean = clean_up(every, Duration::weeks(1)) + .boxed(); + + let result = match select(server, clean).await { + Either::Left((result, _)) => result.map_err(Into::into), + Either::Right((result, _)) => result + }; + + result +} + +#[cfg(target_os = "unknown")] +pub async fn run_server(_: std::net::SocketAddr) -> Result<(), Error> { + Ok(()) +} + +/// Periodically remove old metrics. +async fn clean_up(every: std::time::Duration, before: Duration) -> Result<(), Error> { + loop { + Delay::new(every).await; + + let oldest_allowed = (Utc::now() - before).timestamp_millis(); + DATABASE.write().truncate(oldest_allowed)?; + } +} diff --git a/utils/grafana-data-source/src/types.rs b/utils/grafana-data-source/src/types.rs new file mode 100644 index 0000000000000..960fc787e3eb2 --- /dev/null +++ b/utils/grafana-data-source/src/types.rs @@ -0,0 +1,50 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use serde::{Serialize, Deserialize}; + +#[derive(Serialize, Deserialize)] +pub struct Target { + pub target: String, +} + +#[derive(Serialize, Deserialize)] +pub struct Query { + #[serde(rename = "maxDataPoints")] + pub max_datapoints: usize, + pub targets: Vec, + pub range: Range, +} + +#[derive(Serialize, Deserialize)] +pub struct Range { + #[serde(deserialize_with = "date_to_timestamp_ms")] + pub from: i64, + #[serde(deserialize_with = "date_to_timestamp_ms")] + pub to: i64, +} + +// Deserialize a timestamp via a `DateTime` +fn date_to_timestamp_ms<'de, D: serde::Deserializer<'de>>(timestamp: D) -> Result { + Deserialize::deserialize(timestamp) + .map(|date: chrono::DateTime| date.timestamp_millis()) +} + +#[derive(Serialize, Deserialize)] +pub struct TimeseriesData { + pub target: String, + pub datapoints: Vec<(f32, i64)> +} diff --git a/utils/grafana-data-source/test/Cargo.toml b/utils/grafana-data-source/test/Cargo.toml new file mode 100644 index 0000000000000..079b49dc8608a --- /dev/null +++ b/utils/grafana-data-source/test/Cargo.toml @@ -0,0 +1,13 @@ +[package] +description = "Grafana data source server test" +name = "grafana-data-source-test" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +grafana-data-source = { version = "2.0.0", path = ".." } +futures = "0.3" +futures-timer = "2.0" +rand = "0.7" diff --git a/utils/grafana-data-source/test/src/main.rs b/utils/grafana-data-source/test/src/main.rs new file mode 100644 index 0000000000000..53deaffc3beb6 --- /dev/null +++ b/utils/grafana-data-source/test/src/main.rs @@ -0,0 +1,44 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use grafana_data_source::{run_server, record_metrics}; +use std::time::Duration; +use rand::Rng; +use futures::{future::join, executor}; + +async fn randomness() { + loop { + futures_timer::Delay::new(Duration::from_secs(1)).await; + + let random = rand::thread_rng().gen_range(0.0, 1000.0); + + let result = record_metrics!( + "random data" => random, + "random^2" => random * random, + ); + + if let Err(error) = result { + eprintln!("{}", error); + } + } +} + +fn main() { + executor::block_on(join( + run_server("127.0.0.1:9955".parse().unwrap()), + randomness() + )).0.unwrap(); +} diff --git a/core/utils/wasm-builder-runner/Cargo.toml b/utils/wasm-builder-runner/Cargo.toml similarity index 100% rename from core/utils/wasm-builder-runner/Cargo.toml rename to utils/wasm-builder-runner/Cargo.toml diff --git a/core/utils/wasm-builder-runner/README.md b/utils/wasm-builder-runner/README.md similarity index 100% rename from core/utils/wasm-builder-runner/README.md rename to utils/wasm-builder-runner/README.md diff --git a/utils/wasm-builder-runner/src/lib.rs b/utils/wasm-builder-runner/src/lib.rs new file mode 100644 index 0000000000000..40016a015972c --- /dev/null +++ b/utils/wasm-builder-runner/src/lib.rs @@ -0,0 +1,275 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # WASM builder runner +//! +//! Since cargo contains many bugs when it comes to correct dependency and feature +//! resolution, we need this little tool. See for +//! more information. +//! +//! It will create a project that will call `substrate-wasm-builder` to prevent any dependencies +//! from `substrate-wasm-builder` influencing the main project's dependencies. +//! +//! For more information see + +use std::{env, process::{Command, self}, fs, path::{PathBuf, Path}}; + +/// Environment variable that tells us to skip building the WASM binary. +const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; + +/// Environment variable that tells us to create a dummy WASM binary. +/// +/// This is useful for `cargo check` to speed-up the compilation. +/// +/// # Caution +/// +/// Enabling this option will just provide `&[]` as WASM binary. +const DUMMY_WASM_BINARY_ENV: &str = "BUILD_DUMMY_WASM_BINARY"; + +/// Environment variable that makes sure the WASM build is triggered. +const TRIGGER_WASM_BUILD_ENV: &str = "TRIGGER_WASM_BUILD"; + +/// Replace all backslashes with slashes. +fn replace_back_slashes(path: T) -> String { + path.to_string().replace("\\", "/") +} + +/// The `wasm-builder` dependency source. +pub enum WasmBuilderSource { + /// The relative path to the source code from the current manifest dir. + Path(&'static str), + /// The git repository that contains the source code. + Git { + repo: &'static str, + rev: &'static str, + }, + /// Use the given version released on crates.io. + Crates(&'static str), + /// Use the given version released on crates.io or from the given path. + CratesOrPath { + version: &'static str, + path: &'static str, + } +} + +impl WasmBuilderSource { + /// Convert to a valid cargo source declaration. + /// + /// `absolute_path` - The manifest dir. + fn to_cargo_source(&self, manifest_dir: &Path) -> String { + match self { + WasmBuilderSource::Path(path) => { + replace_back_slashes(format!("path = \"{}\"", manifest_dir.join(path).display())) + } + WasmBuilderSource::Git { repo, rev } => { + format!("git = \"{}\", rev=\"{}\"", repo, rev) + } + WasmBuilderSource::Crates(version) => { + format!("version = \"{}\"", version) + } + WasmBuilderSource::CratesOrPath { version, path } => { + replace_back_slashes( + format!( + "path = \"{}\", version = \"{}\"", + manifest_dir.join(path).display(), + version + ) + ) + } + } + } +} + +/// Build the currently built project as WASM binary and extend `RUSTFLAGS` with the given rustflags. +/// +/// For more information, see [`build_current_project`]. +pub fn build_current_project_with_rustflags( + file_name: &str, + wasm_builder_source: WasmBuilderSource, + default_rustflags: &str, +) { + if check_skip_build() { + // If we skip the build, we still want to make sure to be called when an env variable changes + generate_rerun_if_changed_instructions(); + return; + } + + let manifest_dir = PathBuf::from( + env::var("CARGO_MANIFEST_DIR").expect( + "`CARGO_MANIFEST_DIR` is always set for `build.rs` files; qed" + ) + ); + + let cargo_toml_path = manifest_dir.join("Cargo.toml"); + let out_dir = PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!")); + let file_path = out_dir.join(file_name); + let project_name = env::var("CARGO_PKG_NAME").expect("`CARGO_PKG_NAME` is set by cargo!"); + let project_folder = get_workspace_root().join(project_name); + + if check_provide_dummy_wasm_binary() { + provide_dummy_wasm_binary(&file_path); + } else { + create_project( + &project_folder, + &file_path, + &manifest_dir, + wasm_builder_source, + &cargo_toml_path, + default_rustflags, + ); + run_project(&project_folder); + } + + // As last step we need to generate our `rerun-if-changed` stuff. If a build fails, we don't + // want to spam the output! + generate_rerun_if_changed_instructions(); +} + +/// Build the currently built project as WASM binary. +/// +/// The current project is determined using the `CARGO_MANIFEST_DIR` environment variable. +/// +/// `file_name` - The name of the file being generated in the `OUT_DIR`. The file contains the +/// constant `WASM_BINARY` which contains the build wasm binary. +/// `wasm_builder_path` - Path to the wasm-builder project, relative to `CARGO_MANIFEST_DIR`. +pub fn build_current_project(file_name: &str, wasm_builder_source: WasmBuilderSource) { + build_current_project_with_rustflags(file_name, wasm_builder_source, ""); +} + +/// Returns the root path of the wasm-builder workspace. +/// +/// The wasm-builder workspace contains all wasm-builder's projects. +fn get_workspace_root() -> PathBuf { + let out_dir_env = env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!"); + let mut out_dir = PathBuf::from(&out_dir_env); + + loop { + match out_dir.parent() { + Some(parent) if out_dir.ends_with("build") => return parent.join("wbuild-runner"), + _ => if !out_dir.pop() { + break; + } + } + } + + panic!("Could not find target dir in: {}", out_dir_env) +} + +fn create_project( + project_folder: &Path, + file_path: &Path, + manifest_dir: &Path, + wasm_builder_source: WasmBuilderSource, + cargo_toml_path: &Path, + default_rustflags: &str, +) { + fs::create_dir_all(project_folder.join("src")) + .expect("WASM build runner dir create can not fail; qed"); + + fs::write( + project_folder.join("Cargo.toml"), + format!( + r#" + [package] + name = "wasm-build-runner-impl" + version = "1.0.0" + edition = "2018" + + [dependencies] + substrate-wasm-builder = {{ {wasm_builder_source} }} + + [workspace] + "#, + wasm_builder_source = wasm_builder_source.to_cargo_source(manifest_dir), + ) + ).expect("WASM build runner `Cargo.toml` writing can not fail; qed"); + + fs::write( + project_folder.join("src/main.rs"), + format!( + r#" + use substrate_wasm_builder::build_project_with_default_rustflags; + + fn main() {{ + build_project_with_default_rustflags( + "{file_path}", + "{cargo_toml_path}", + "{default_rustflags}", + ) + }} + "#, + file_path = replace_back_slashes(file_path.display()), + cargo_toml_path = replace_back_slashes(cargo_toml_path.display()), + default_rustflags = default_rustflags, + ) + ).expect("WASM build runner `main.rs` writing can not fail; qed"); +} + +fn run_project(project_folder: &Path) { + let cargo = env::var("CARGO").expect("`CARGO` env variable is always set when executing `build.rs`."); + let mut cmd = Command::new(cargo); + cmd.arg("run").arg(format!("--manifest-path={}", project_folder.join("Cargo.toml").display())); + + if env::var("DEBUG") != Ok(String::from("true")) { + cmd.arg("--release"); + } + + // Unset the `CARGO_TARGET_DIR` to prevent a cargo deadlock (cargo locks a target dir exclusive). + // The runner project is created in `CARGO_TARGET_DIR` and executing it will create a sub target + // directory inside of `CARGO_TARGET_DIR`. + cmd.env_remove("CARGO_TARGET_DIR"); + + if !cmd.status().map(|s| s.success()).unwrap_or(false) { + // Don't spam the output with backtraces when a build failed! + process::exit(1); + } +} + +/// Generate the name of the skip build environment variable for the current crate. +fn generate_crate_skip_build_env_name() -> String { + format!( + "SKIP_{}_WASM_BUILD", + env::var("CARGO_PKG_NAME").expect("Package name is set").to_uppercase().replace('-', "_"), + ) +} + +/// Checks if the build of the WASM binary should be skipped. +fn check_skip_build() -> bool { + env::var(SKIP_BUILD_ENV).is_ok() || env::var(generate_crate_skip_build_env_name()).is_ok() +} + +/// Check if we should provide a dummy WASM binary. +fn check_provide_dummy_wasm_binary() -> bool { + env::var(DUMMY_WASM_BINARY_ENV).is_ok() +} + +/// Provide the dummy WASM binary +fn provide_dummy_wasm_binary(file_path: &Path) { + fs::write( + file_path, + "pub const WASM_BINARY: &[u8] = &[]; pub const WASM_BINARY_BLOATY: &[u8] = &[];", + ).expect("Writing dummy WASM binary should not fail"); +} + +/// Generate the `rerun-if-changed` instructions for cargo to make sure that the WASM binary is +/// rebuilt when needed. +fn generate_rerun_if_changed_instructions() { + // Make sure that the `build.rs` is called again if one of the following env variables changes. + println!("cargo:rerun-if-env-changed={}", SKIP_BUILD_ENV); + println!("cargo:rerun-if-env-changed={}", DUMMY_WASM_BINARY_ENV); + println!("cargo:rerun-if-env-changed={}", TRIGGER_WASM_BUILD_ENV); + println!("cargo:rerun-if-env-changed={}", generate_crate_skip_build_env_name()); +} diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml new file mode 100644 index 0000000000000..66d94c32ab330 --- /dev/null +++ b/utils/wasm-builder/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "substrate-wasm-builder" +version = "1.0.8" +authors = ["Parity Technologies "] +description = "Utility for building WASM binaries" +edition = "2018" +readme = "README.md" +repository = "https://github.com/paritytech/substrate" +license = "GPL-3.0" + +[dependencies] +build-helper = "0.1.1" +cargo_metadata = "0.9.0" +tempfile = "3.1.0" +toml = "0.5.4" +walkdir = "2.2.9" +fs2 = "0.4.3" +wasm-gc-api = "0.1.11" +atty = "0.2.13" diff --git a/utils/wasm-builder/README.md b/utils/wasm-builder/README.md new file mode 100644 index 0000000000000..b21c588ac383c --- /dev/null +++ b/utils/wasm-builder/README.md @@ -0,0 +1,65 @@ +# WASM builder is a utility for building a project as a WASM binary + +The WASM builder is a tool that integrates the process of building the WASM binary of your project into the main +`cargo` build process. + +## Project setup + +A project that should be compiled as a WASM binary needs to: + +1. Add a `build.rs` file. +2. Add `substrate-wasm-builder` as dependency into `build-dependencies`. + +The `build.rs` file needs to contain the following code: + +```rust +use wasm_builder_runner::{build_current_project, WasmBuilderSource}; + +fn main() { + build_current_project( + // The name of the file being generated in out-dir. + "wasm_binary.rs", + // How to include wasm-builder, in this case from crates.io. + WasmBuilderSource::Crates("1.0.0"), + ); +} +``` + +As the final step, you need to add the following to your project: + +```rust +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +``` + +This will include the generated WASM binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. +The former is a compact WASM binary and the latter is not compacted. + +## Environment variables + +By using environment variables, you can configure which WASM binaries are built and how: + +- `SKIP_WASM_BUILD` - Skips building any wasm binary. This is useful when only native should be recompiled. +- `BUILD_DUMMY_WASM_BINARY` - Builds dummy wasm binaries. These dummy binaries are empty and useful + for `cargo check` runs. +- `WASM_BUILD_TYPE` - Sets the build type for building wasm binaries. Supported values are `release` or `debug`. + By default the build type is equal to the build type used by the main build. +- `TRIGGER_WASM_BUILD` - Can be set to trigger a wasm build. On subsequent calls the value of the variable + needs to change. As WASM builder instructs `cargo` to watch for file changes + this environment variable should only be required in certain circumstances. +- `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. +- `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. +- `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs + to be absolute. + +Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. +Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will +be `NODE_RUNTIME`. + +## Prerequisites: + +WASM builder requires the following prerequisities for building the WASM binary: + +- rust nightly + `wasm32-unknown-unknown` toolchain + + +License: GPL-3.0 diff --git a/utils/wasm-builder/src/lib.rs b/utils/wasm-builder/src/lib.rs new file mode 100644 index 0000000000000..80192eb3613ce --- /dev/null +++ b/utils/wasm-builder/src/lib.rs @@ -0,0 +1,245 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # WASM builder is a utility for building a project as a WASM binary +//! +//! The WASM builder is a tool that integrates the process of building the WASM binary of your project into the main +//! `cargo` build process. +//! +//! ## Project setup +//! +//! A project that should be compiled as a WASM binary needs to: +//! +//! 1. Add a `build.rs` file. +//! 2. Add `substrate-wasm-builder` as dependency into `build-dependencies`. +//! +//! The `build.rs` file needs to contain the following code: +//! +//! ```ignore +//! use wasm_builder_runner::{build_current_project, WasmBuilderSource}; +//! +//! fn main() { +//! build_current_project( +//! // The name of the file being generated in out-dir. +//! "wasm_binary.rs", +//! // How to include wasm-builder, in this case from crates.io. +//! WasmBuilderSource::Crates("1.0.0"), +//! ); +//! } +//! ``` +//! +//! As the final step, you need to add the following to your project: +//! +//! ```ignore +//! include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +//! ``` +//! +//! This will include the generated WASM binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. +//! The former is a compact WASM binary and the latter is not compacted. +//! +//! ## Environment variables +//! +//! By using environment variables, you can configure which WASM binaries are built and how: +//! +//! - `SKIP_WASM_BUILD` - Skips building any wasm binary. This is useful when only native should be recompiled. +//! - `BUILD_DUMMY_WASM_BINARY` - Builds dummy wasm binaries. These dummy binaries are empty and useful +//! for `cargo check` runs. +//! - `WASM_BUILD_TYPE` - Sets the build type for building wasm binaries. Supported values are `release` or `debug`. +//! By default the build type is equal to the build type used by the main build. +//! - `TRIGGER_WASM_BUILD` - Can be set to trigger a wasm build. On subsequent calls the value of the variable +//! needs to change. As WASM builder instructs `cargo` to watch for file changes +//! this environment variable should only be required in certain circumstances. +//! - `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. +//! - `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. +//! - `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs +//! to be absolute. +//! +//! Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. +//! Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will +//! be `NODE_RUNTIME`. +//! +//! ## Prerequisites: +//! +//! WASM builder requires the following prerequisities for building the WASM binary: +//! +//! - rust nightly + `wasm32-unknown-unknown` toolchain +//! + +use std::{env, fs, path::PathBuf, process::{Command, Stdio, self}}; + +mod prerequisites; +mod wasm_project; + +/// Environment variable that tells us to skip building the wasm binary. +const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; + +/// Environment variable to force a certain build type when building the wasm binary. +/// Expects "debug" or "release" as value. +/// +/// By default the WASM binary uses the same build type as the main cargo build. +const WASM_BUILD_TYPE_ENV: &str = "WASM_BUILD_TYPE"; + +/// Environment variable to extend the `RUSTFLAGS` variable given to the wasm build. +const WASM_BUILD_RUSTFLAGS_ENV: &str = "WASM_BUILD_RUSTFLAGS"; + +/// Environment variable to set the target directory to copy the final wasm binary. +/// +/// The directory needs to be an absolute path. +const WASM_TARGET_DIRECTORY: &str = "WASM_TARGET_DIRECTORY"; + +/// Environment variable to disable color output of the wasm build. +const WASM_BUILD_NO_COLOR: &str = "WASM_BUILD_NO_COLOR"; + +/// Build the currently built project as wasm binary. +/// +/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. +/// +/// `file_name` - The name + path of the file being generated. The file contains the +/// constant `WASM_BINARY`, which contains the built WASM binary. +/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built. +pub fn build_project(file_name: &str, cargo_manifest: &str) { + build_project_with_default_rustflags(file_name, cargo_manifest, ""); +} + +/// Build the currently built project as wasm binary. +/// +/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. +/// +/// `file_name` - The name + path of the file being generated. The file contains the +/// constant `WASM_BINARY`, which contains the built WASM binary. +/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built. +/// `default_rustflags` - Default `RUSTFLAGS` that will always be set for the build. +pub fn build_project_with_default_rustflags( + file_name: &str, + cargo_manifest: &str, + default_rustflags: &str, +) { + if check_skip_build() { + return; + } + + let cargo_manifest = PathBuf::from(cargo_manifest); + + if !cargo_manifest.exists() { + panic!("'{}' does not exist!", cargo_manifest.display()); + } + + if !cargo_manifest.ends_with("Cargo.toml") { + panic!("'{}' no valid path to a `Cargo.toml`!", cargo_manifest.display()); + } + + if let Some(err_msg) = prerequisites::check() { + eprintln!("{}", err_msg); + process::exit(1); + } + + let (wasm_binary, bloaty) = wasm_project::create_and_compile( + &cargo_manifest, + default_rustflags, + ); + + write_file_if_changed( + file_name.into(), + format!( + r#" + pub const WASM_BINARY: &[u8] = include_bytes!("{wasm_binary}"); + pub const WASM_BINARY_BLOATY: &[u8] = include_bytes!("{wasm_binary_bloaty}"); + "#, + wasm_binary = wasm_binary.wasm_binary_path(), + wasm_binary_bloaty = bloaty.wasm_binary_bloaty_path(), + ), + ); +} + +/// Checks if the build of the WASM binary should be skipped. +fn check_skip_build() -> bool { + env::var(SKIP_BUILD_ENV).is_ok() +} + +/// Write to the given `file` if the `content` is different. +fn write_file_if_changed(file: PathBuf, content: String) { + if fs::read_to_string(&file).ok().as_ref() != Some(&content) { + fs::write(&file, content).expect(&format!("Writing `{}` can not fail!", file.display())); + } +} + +/// Get a cargo command that compiles with nightly +fn get_nightly_cargo() -> CargoCommand { + let default_cargo = CargoCommand::new("cargo"); + let mut rustup_run_nightly = CargoCommand::new("rustup"); + rustup_run_nightly.args(&["run", "nightly", "cargo"]); + + if default_cargo.is_nightly() { + default_cargo + } else if rustup_run_nightly.works() { + rustup_run_nightly + } else { + default_cargo + } +} + +/// Builder for cargo commands +#[derive(Debug)] +struct CargoCommand { + program: String, + args: Vec, +} + +impl CargoCommand { + fn new(program: &str) -> Self { + CargoCommand { program: program.into(), args: Vec::new() } + } + + fn arg(&mut self, arg: &str) -> &mut Self { + self.args.push(arg.into()); + self + } + + fn args(&mut self, args: &[&str]) -> &mut Self { + args.into_iter().for_each(|a| { self.arg(a); }); + self + } + + fn command(&self) -> Command { + let mut cmd = Command::new(&self.program); + cmd.args(&self.args); + cmd + } + + fn works(&self) -> bool { + self.command() + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .map(|s| s.success()).unwrap_or(false) + } + + /// Check if the supplied cargo command is a nightly version + fn is_nightly(&self) -> bool { + // `RUSTC_BOOTSTRAP` tells a stable compiler to behave like a nightly. So, when this env + // variable is set, we can assume that whatever rust compiler we have, it is a nightly compiler. + // For "more" information, see: + // https://github.com/rust-lang/rust/blob/fa0f7d0080d8e7e9eb20aa9cbf8013f96c81287f/src/libsyntax/feature_gate/check.rs#L891 + env::var("RUSTC_BOOTSTRAP").is_ok() || + self.command() + .arg("--version") + .output() + .map_err(|_| ()) + .and_then(|o| String::from_utf8(o.stdout).map_err(|_| ())) + .unwrap_or_default() + .contains("-nightly") + } +} diff --git a/core/utils/wasm-builder/src/prerequisites.rs b/utils/wasm-builder/src/prerequisites.rs similarity index 97% rename from core/utils/wasm-builder/src/prerequisites.rs rename to utils/wasm-builder/src/prerequisites.rs index 3a7f8387dc8b8..da118a71f98da 100644 --- a/core/utils/wasm-builder/src/prerequisites.rs +++ b/utils/wasm-builder/src/prerequisites.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 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/utils/wasm-builder/src/wasm_project.rs b/utils/wasm-builder/src/wasm_project.rs similarity index 86% rename from core/utils/wasm-builder/src/wasm_project.rs rename to utils/wasm-builder/src/wasm_project.rs index 1651642ee0a7b..a028d00930a4e 100644 --- a/core/utils/wasm-builder/src/wasm_project.rs +++ b/utils/wasm-builder/src/wasm_project.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -172,17 +172,69 @@ fn get_wasm_workspace_root() -> PathBuf { panic!("Could not find target dir in: {}", build_helper::out_dir().display()) } -fn create_wasm_workspace_project(wasm_workspace: &Path, cargo_manifest: &Path) { - let members = WalkDir::new(wasm_workspace) +/// Find all workspace members. +/// +/// Each folder in `wasm_workspace` is seen as a member of the workspace. Exceptions are +/// folders starting with "." and the "target" folder. +/// +/// Every workspace member that is not valid anymore is deleted (the folder of it). A +/// member is not valid anymore when the `wasm-project` dependency points to an non-existing +/// folder or the package name is not valid. +fn find_and_clear_workspace_members(wasm_workspace: &Path) -> Vec { + let mut members = WalkDir::new(wasm_workspace) .min_depth(1) .max_depth(1) .into_iter() .filter_map(|p| p.ok()) .map(|d| d.into_path()) - .filter(|p| p.is_dir() && !p.ends_with("target")) + .filter(|p| p.is_dir()) .filter_map(|p| p.file_name().map(|f| f.to_owned()).and_then(|s| s.into_string().ok())) + .filter(|f| !f.starts_with(".") && f != "target") .collect::>(); + let mut i = 0; + while i != members.len() { + let path = wasm_workspace.join(&members[i]).join("Cargo.toml"); + + // Extract the `wasm-project` dependency. + // If the path can be extracted and is valid and the package name matches, + // the member is valid. + if let Some(mut wasm_project) = fs::read_to_string(path) + .ok() + .and_then(|s| toml::from_str::(&s).ok()) + .and_then(|mut t| t.remove("dependencies")) + .and_then(|p| p.try_into::
().ok()) + .and_then(|mut t| t.remove("wasm_project")) + .and_then(|p| p.try_into::
().ok()) + { + if let Some(path) = wasm_project.remove("path") + .and_then(|p| p.try_into::().ok()) + { + if let Some(name) = wasm_project.remove("package") + .and_then(|p| p.try_into::().ok()) + { + let path = PathBuf::from(path); + if path.exists() { + if name == get_crate_name(&path.join("Cargo.toml")) { + i += 1; + continue + } + } + } + } + } + + fs::remove_dir_all(wasm_workspace.join(&members[i])) + .expect("Removing invalid workspace member can not fail; qed"); + members.remove(i); + } + + members +} + +fn create_wasm_workspace_project(wasm_workspace: &Path, cargo_manifest: &Path) { + let members = find_and_clear_workspace_members(wasm_workspace); + let crate_metadata = MetadataCommand::new() .manifest_path(cargo_manifest) .exec() @@ -320,12 +372,16 @@ fn build_project(project: &Path, default_rustflags: &str) { env::var(crate::WASM_BUILD_RUSTFLAGS_ENV).unwrap_or_default(), ); - build_cmd.args(&["build", "--target=wasm32-unknown-unknown"]) + build_cmd.args(&["rustc", "--target=wasm32-unknown-unknown"]) .arg(format!("--manifest-path={}", manifest_path.display())) .env("RUSTFLAGS", rustflags) // We don't want to call ourselves recursively .env(crate::SKIP_BUILD_ENV, ""); + if env::var(crate::WASM_BUILD_NO_COLOR).is_err() { + build_cmd.arg("--color=always"); + } + if is_release_build() { build_cmd.arg("--release"); };